TLS 1.3 PSK 会话恢复: NewSessionTicket 签发/解析、ticket+binder 校验、selected_identity 回选、恢复握手免证书(pazessl -sess_in/-sess_out 端到端验证); 构建脚本输出 bin/ 并支持独立命令与 psftp; 修复 SFTP 二进制传输与 copy_id -P; 补充 tests/ 调试与 verify_tls
271 行
11 KiB
C
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 */
|