文件
PazeSSH/include/paze/tls.h
T
JGZYES 3e8a5442fa 实现 TLS 1.3 PSK 会话恢复,构建输出移至 bin/ 并新增 standalone/psftp 命令
TLS 1.3 PSK 会话恢复: NewSessionTicket 签发/解析、ticket+binder 校验、selected_identity 回选、恢复握手免证书(pazessl -sess_in/-sess_out 端到端验证); 构建脚本输出 bin/ 并支持独立命令与 psftp; 修复 SFTP 二进制传输与 copy_id -P; 补充 tests/ 调试与 verify_tls
2026-08-13 19:30:07 +08:00

271 行
11 KiB
C

/* tls.h —— PazeSSL: TLS 1.2 / 1.3 客户端 + 服务端
*
* 目标:仅依赖 libc + 内部 crypto,跨平台 (Win/Unix),面向 Los4。
* 预算:SSL 全量 ≤ 100000 行。
*
* 支持范围:
* - TLS 1.3 (RFC 8446):
* cipher suites: AES-128-GCM-SHA256 / AES-256-GCM-SHA384 / ChaCha20-Poly1305-SHA256
* key exchange : X25519 / secp256r1 (ECDHE)
* signatures : ecdsa_secp256r1_sha256 / rsa_pss_rsae_sha256 / rsa_pkcs1_sha256
* - TLS 1.2 (RFC 5246 + RFC 8422/7919):
* cipher suites: ECDHE-RSA-AES128-GCM-SHA256 / ECDHE-ECDSA-AES128-GCM-SHA256 /
* ECDHE-RSA-CHACHA20-POLY1305 / RSA-AES128-GCM-SHA256
* groups : X25519 / secp256r1
*
* 公共 API 采用不透明指针: paze_tls_t / paze_tls_config_t。
* 读写通过回调 BIO 抽象,可绑 socket / 内存 / 自定义。
*/
#ifndef PAZE_TLS_H
#define PAZE_TLS_H
#include "paze/paze_types.h"
#include "paze/x509.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================
* 版本
* ============================================================ */
#define PAZE_TLS_VERSION_1_2 0x0303
#define PAZE_TLS_VERSION_1_3 0x0304
/* ClientHello 顶层 legacy_version */
#define PAZE_TLS_LEGACY_VERSION 0x0303
/* ============================================================
* Cipher Suite (IANA)
* ============================================================ */
/* TLS 1.3 */
#define PAZE_TLS_AES_128_GCM_SHA256 0x1301
#define PAZE_TLS_AES_256_GCM_SHA384 0x1302
#define PAZE_TLS_CHACHA20_POLY1305_SHA256 0x1303
/* TLS 1.2 */
#define PAZE_TLS_ECDHE_RSA_AES128_GCM_SHA256 0xC02F
#define PAZE_TLS_ECDHE_ECDSA_AES128_GCM_SHA256 0xC02B
#define PAZE_TLS_ECDHE_RSA_CHACHA20_POLY1305 0xCCA8
#define PAZE_TLS_RSA_AES128_GCM_SHA256 0x009C
/* 命名组 (NamedGroup, key exchange) */
#define PAZE_TLS_GROUP_SECP256R1 0x0017
#define PAZE_TLS_GROUP_X25519 0x001D
/* 签名算法 (SignatureScheme) */
#define PAZE_TLS_SIG_ECDSA_SECP256R1_SHA256 0x0403
#define PAZE_TLS_SIG_RSA_PSS_RSAE_SHA256 0x0804
#define PAZE_TLS_SIG_RSA_PSS_RSAE_SHA384 0x0805
#define PAZE_TLS_SIG_RSA_PKCS1_SHA256 0x0401
#define PAZE_TLS_SIG_RSA_PKCS1_SHA384 0x0501
/* 握手类型 (HandshakeType) */
#define PAZE_TLS_HS_CLIENT_HELLO 1
#define PAZE_TLS_HS_SERVER_HELLO 2
#define PAZE_TLS_HS_NEW_SESSION_TICKET 4
#define PAZE_TLS_HS_END_OF_EARLY_DATA 5
#define PAZE_TLS_HS_ENCRYPTED_EXTENSIONS 8
#define PAZE_TLS_HS_CERTIFICATE 11
#define PAZE_TLS_HS_SERVER_KEY_EXCHANGE 12 /* TLS 1.2 */
#define PAZE_TLS_HS_CERTIFICATE_REQUEST 13
#define PAZE_TLS_HS_SERVER_HELLO_DONE 14 /* TLS 1.2 */
#define PAZE_TLS_HS_CERTIFICATE_VERIFY 15
#define PAZE_TLS_HS_CLIENT_KEY_EXCHANGE 16 /* TLS 1.2 */
#define PAZE_TLS_HS_FINISHED 20
#define PAZE_TLS_HS_KEY_UPDATE 24
#define PAZE_TLS_HS_MESSAGE_HASH 254
/* ContentType (record) */
#define PAZE_TLS_CT_CHANGE_CIPHER_SPEC 20
#define PAZE_TLS_CT_ALERT 21
#define PAZE_TLS_CT_HANDSHAKE 22
#define PAZE_TLS_CT_APPLICATION_DATA 23
/* AlertLevel */
#define PAZE_TLS_ALERT_WARNING 1
#define PAZE_TLS_ALERT_FATAL 2
/* AlertDescription (常用) */
#define PAZE_TLS_ALERT_CLOSE_NOTIFY 0
#define PAZE_TLS_ALERT_UNEXPECTED_MESSAGE 10
#define PAZE_TLS_ALERT_BAD_RECORD_MAC 20
#define PAZE_TLS_ALERT_HANDSHAKE_FAILURE 40
#define PAZE_TLS_ALERT_BAD_CERTIFICATE 42
#define PAZE_TLS_ALERT_UNSUPPORTED_CERT 43
#define PAZE_TLS_ALERT_CERTIFICATE_REVOKED 44
#define PAZE_TLS_ALERT_CERTIFICATE_EXPIRED 45
#define PAZE_TLS_ALERT_CERTIFICATE_UNKNOWN 46
#define PAZE_TLS_ALERT_ILLEGAL_PARAMETER 47
#define PAZE_TLS_ALERT_UNKNOWN_CA 48
#define PAZE_TLS_ALERT_ACCESS_DENIED 49
#define PAZE_TLS_ALERT_DECODE_ERROR 50
#define PAZE_TLS_ALERT_DECRYPT_ERROR 51
#define PAZE_TLS_ALERT_PROTOCOL_VERSION 70
#define PAZE_TLS_ALERT_INSUFFICIENT_SECURITY 71
#define PAZE_TLS_ALERT_INTERNAL_ERROR 80
#define PAZE_TLS_ALERT_USER_CANCELED 90
#define PAZE_TLS_ALERT_MISSING_EXTENSION 109
#define PAZE_TLS_ALERT_UNSUPPORTED_EXT 110
#define PAZE_TLS_ALERT_UNRECOGNIZED_NAME 112
#define PAZE_TLS_ALERT_BAD_CERT_STATUS 113
#define PAZE_TLS_ALERT_UNKNOWN_PSK_IDENTITY 115
#define PAZE_TLS_ALERT_CERT_REQUIRED 116
#define PAZE_TLS_ALERT_NO_APPLICATION_PROTOCOL 120
/* ExtensionType */
#define PAZE_TLS_EXT_SERVER_NAME 0
#define PAZE_TLS_EXT_STATUS_REQUEST 5 /* OCSP */
#define PAZE_TLS_EXT_SUPPORTED_GROUPS 10
#define PAZE_TLS_EXT_EC_POINT_FORMATS 11
#define PAZE_TLS_EXT_SIGNATURE_ALGORITHMS 13
#define PAZE_TLS_EXT_ALPN 16
#define PAZE_TLS_EXT_KEY_SHARE 51
#define PAZE_TLS_EXT_PRE_SHARED_KEY 41
#define PAZE_TLS_EXT_EARLY_DATA 42
#define PAZE_TLS_EXT_SUPPORTED_VERSIONS 43
#define PAZE_TLS_EXT_COOKIE 44
#define PAZE_TLS_EXT_PSK_KEY_EXCHANGE_MODES 45
#define PAZE_TLS_EXT_CERTIFICATE_AUTHORITIES 47
#define PAZE_TLS_EXT_SIGNATURE_ALGORITHMS_CERT 50
#define PAZE_TLS_EXT_RENEGOTIATION_INFO 0xFF01
/* ============================================================
* BIO: I/O 抽象
* ============================================================
* 用户实现 read/write 回调,典型为 socket。
* - read: 返回读取字节数(>=0),负数=错误。
* 需要支持 0 表示"非阻塞暂无数据"时,由上层处理;阻塞 IO 应等待。
* - write: 返回写入字节数(>=0),负数=错误。
*/
typedef int (*paze_tls_io_fn)(void *ctx, uint8_t *buf, size_t len); /* read */
typedef int (*paze_tls_io_write_fn)(void *ctx, const uint8_t *buf, size_t len); /* write */
typedef struct {
void *ctx;
paze_tls_io_fn read;
paze_tls_io_write_fn write;
} paze_tls_bio_t;
/* ============================================================
* 证书验证回调
* 返回 1 接受,0 拒绝。chain/chain_len 为已解析的服务端证书链。
* verified: 内部链验证结果(PAZE_OK=通过)。
* ============================================================ */
typedef int (*paze_tls_verify_cb)(void *ctx,
const paze_x509_cert_t *chain, int chain_len,
paze_status_t verified);
/* ============================================================
* 配置
* ============================================================ */
typedef struct paze_tls_config paze_tls_config_t;
/* 角色 */
typedef enum {
PAZE_TLS_CLIENT = 0,
PAZE_TLS_SERVER = 1
} paze_tls_role_t;
/* 证书验证模式 */
typedef enum {
PAZE_TLS_VERIFY_NONE = 0, /* 不验证(仅测试) */
PAZE_TLS_VERIFY_OPTIONAL = 1,
PAZE_TLS_VERIFY_REQUIRED = 2 /* 默认:服务端必须可信 */
} paze_tls_verify_mode_t;
/* ============================================================
* 会话复用(TLS 1.3 PSK 会话恢复)
* ============================================================ */
typedef struct {
uint8_t ticket[512]; /* NewSessionTicket 的 ticket 字段 */
size_t ticket_len;
uint8_t psk[64]; /* 由 resumption_master_secret 派生的 PSK */
size_t psk_len;
uint32_t age_add; /* ticket_age_add */
int32_t recv_time; /* 收到 ticket 的 unix 时间(用于 obfuscated age) */
int hash; /* 关联 hash: 0=SHA-256, 1=SHA-384 */
int valid;
} paze_tls_session_t;
/* 客户端:设置要用于会话恢复的 PSK 会话(来自上一次 paze_tls_get_session) */
paze_status_t paze_tls_config_set_session(paze_tls_config_t *cfg,
const paze_tls_session_t *sess);
paze_tls_config_t *paze_tls_config_new(paze_tls_role_t role);
void paze_tls_config_free(paze_tls_config_t *cfg);
/* 设置 SNI 主机名(client) */
paze_status_t paze_tls_config_set_sni(paze_tls_config_t *cfg, const char *host);
/* 设置 ALPN 协议列表(以 NULL 结尾的字符串数组,n 项) */
paze_status_t paze_tls_config_set_alpn(paze_tls_config_t *cfg, const char *const *alpn, int n);
/* 服务端:加载证书链与私钥(PEM 文本) */
paze_status_t paze_tls_config_set_cert_chain(paze_tls_config_t *cfg,
const char *cert_pem,
const char *privkey_pem);
/* 客户端:信任锚(根证书 PEM 文本,可为多张) */
paze_status_t paze_tls_config_set_trust_roots(paze_tls_config_t *cfg,
const char *roots_pem);
/* 验证模式 */
paze_status_t paze_tls_config_set_verify(paze_tls_config_t *cfg,
paze_tls_verify_mode_t mode,
paze_tls_verify_cb cb, void *ctx);
/* 启用/禁用版本(默认 1.3 优先,回退 1.2) */
paze_status_t paze_tls_config_set_versions(paze_tls_config_t *cfg,
int enable_1_3, int enable_1_2);
/* ============================================================
* 连接对象
* ============================================================ */
typedef struct paze_tls paze_tls_t;
/* 握手后获取服务端下发的会话(客户端收到 NewSessionTicket 后);
* 未收到 ticket 或非 1.3 时返回 valid=0。 */
paze_status_t paze_tls_get_session(const paze_tls_t *tls, paze_tls_session_t *sess);
/* 本次握手是否通过 PSK 会话恢复(客户端/服务端均适用) */
int paze_tls_session_resumed(const paze_tls_t *tls);
/* 服务端:导出本次连接使用的 session ticket key(供多连接共享以实现恢复);
* ready 返回 0 表示尚未生成。 */
paze_status_t paze_tls_get_session_ticket_key(const paze_tls_t *tls,
uint8_t key[32], int *ready);
/* 服务端:显式设置 session ticket key(使所有连接用同一密钥) */
paze_status_t paze_tls_config_set_session_ticket_key(paze_tls_config_t *cfg,
const uint8_t key[32]);
paze_tls_t *paze_tls_new(const paze_tls_config_t *cfg);
void paze_tls_free(paze_tls_t *tls);
/* 绑定 BIO(必须在 handshake 前调用) */
paze_status_t paze_tls_set_bio(paze_tls_t *tls, paze_tls_bio_t bio);
/* 驱动握手。返回 PAZE_OK 表示握手完成;PAZE_ERR_IO 表示需更多数据(非阻塞);
其他负数表示致命错误。可重复调用直到成功。 */
paze_status_t paze_tls_handshake(paze_tls_t *tls);
/* 是否完成握手 */
int paze_tls_is_handshake_done(const paze_tls_t *tls);
/* 应用层数据读写。read 返回读取字节数(>0);0=对端关闭;负数=错误。
PAZE_ERR_IO(非阻塞无数据)时上层应等待可读后重试。 */
int paze_tls_read(paze_tls_t *tls, uint8_t *buf, size_t len);
int paze_tls_write(paze_tls_t *tls, const uint8_t *buf, size_t len);
/* 优雅关闭:发送 close_notify */
paze_status_t paze_tls_close(paze_tls_t *tls);
/* 协商结果查询 */
int paze_tls_get_version(const paze_tls_t *tls); /* 0x0303/0x0304 */
uint16_t paze_tls_get_cipher_suite(const paze_tls_t *tls);
const char *paze_tls_get_alpn(const paze_tls_t *tls); /* 协商的 ALPN 或 NULL */
const char *paze_tls_get_sni(const paze_tls_t *tls);
/* 最近错误描述 */
const char *paze_tls_last_error(const paze_tls_t *tls);
#ifdef __cplusplus
}
#endif
#endif /* PAZE_TLS_H */