文件
PazeSSH/src/ssl/tls_internal.h
T

509 行
22 KiB
C

/* tls_internal.h —— PazeSSL 内部结构(不对外暴露)
*
* 分层:
* tls_conn.c : paze_tls_t 生命周期、配置拷贝、应用读写入口
* tls_bio.c : BIO I/O + record 缓冲读写
* tls_record.c : record layer 编码/解码 + AEAD 加解密
* tls_transcript.c : 握手消息累积 + transcript hash
* tls_keys.c : TLS 1.3 key schedule (Derive-Secret/Expand-Label) + 1.2 PRF
* tls_extensions.c : 扩展解析/构造
* tls_handshake13.c : TLS 1.3 状态机
* tls_handshake12.c : TLS 1.2 状态机
* tls_client.c / tls_server.c : 角色入口
*/
#ifndef PAZE_TLS_INTERNAL_H
#define PAZE_TLS_INTERNAL_H
#include "paze/tls.h"
#include "paze/x509.h"
#include "paze/hash.h"
#include "paze/aes.h"
#include "paze/hmac.h"
#include "paze/hkdf.h"
#include "paze/aead.h"
#include "paze/curve25519.h"
#include "paze/ed25519.h"
#include "paze/ecdsa.h"
#include "paze/rsa.h"
#include "paze/mem.h"
#include "paze/random.h"
#include "paze/log.h"
#include "paze/error.h"
#include <string.h>
#include <stdlib.h>
/* ============================================================
* 常量
* ============================================================ */
#define PAZE_TLS_MAX_RECORD 16384 /* record payload 上限 */
#define PAZE_TLS_MAX_HANDSHAKE 65536 /* 单条握手消息上限 */
#define PAZE_TLS_MAX_CERTS 8 /* 证书链最大证书数 */
#define PAZE_TLS_MAX_EXT 65535
#define PAZE_TLS_KEY_LOG_MAX 64 /* key log 前缀 */
#define PAZE_TLS_MAX_ALPN 8
#define PAZE_TLS_SNI_MAX 255
/* HelloRetryRequest 魔数 random (RFC 8446 §4.1.3) */
#define PAZE_TLS_HRR_RANDOM_BYTES \
0xCF,0x21,0xAD,0x74,0xE5,0x9A,0x61,0x11,0xBE,0x1D,0x8C,0x02,0x1E,0x65,0xB8,0x91, \
0xC2,0xA2,0x11,0x16,0x7A,0xBB,0x8C,0x5E,0x07,0x9E,0x09,0xE2,0xC8,0xA8,0x33,0x9C
static const uint8_t paze_tls_hrr_random[32] = { PAZE_TLS_HRR_RANDOM_BYTES };
/* AEAD 种类 */
typedef enum {
PAZE_AEAD_NONE = 0,
PAZE_AEAD_AES_128_GCM,
PAZE_AEAD_AES_256_GCM,
PAZE_AEAD_CHACHA20_POLY1305
} paze_tls_aead_kind_t;
/* ============================================================
* Traffic key: 单向 AEAD 密钥/IV/序列号
* ============================================================ */
typedef struct {
paze_tls_aead_kind_t kind;
uint8_t key[32]; /* AES-256 用满 32;AES-128 用 16;Chacha 用 32 */
size_t key_len;
uint8_t iv[12]; /* nonce base */
uint64_t seq; /* 序列号,溢出须 rekey(1.3)/报错 */
paze_aes_ctx_t aes; /* AES key schedule(AES-GCM 时初始化) */
} paze_tls_traffic_key_t;
/* ============================================================
* Key exchange 状态
* ============================================================ */
typedef enum {
PAZE_KEX_NONE = 0,
PAZE_KEX_X25519,
PAZE_KEX_P256,
PAZE_KEX_P384
} paze_tls_kex_kind_t;
typedef struct {
paze_tls_kex_kind_t kind;
/* X25519 */
uint8_t x25519_priv[32];
uint8_t x25519_pub[32];
/* P-256 */
uint8_t p256_priv[32];
uint8_t p256_pub[65]; /* 0x04||X||Y */
/* P-384 */
uint8_t p384_priv[48];
uint8_t p384_pub[97]; /* 0x04||X||Y */
} paze_tls_kex_t;
/* ============================================================
* Transcript hash
* ============================================================ */
typedef struct {
const paze_hash_alg_t *alg; /* SHA-256 / SHA-384 */
uint8_t ctx[PAZE_HASH_MAX_CTX]; /* 当前哈希上下文 */
uint8_t snapshot[PAZE_HASH_MAX_CTX]; /* ClientHello1 快照(HRR 回退用) */
int has_snapshot;
} paze_tls_transcript_t;
/* ============================================================
* 配置(具体化)
* ============================================================ */
struct paze_tls_config {
paze_tls_role_t role;
char sni[PAZE_TLS_SNI_MAX + 1];
char *alpn[PAZE_TLS_MAX_ALPN];
int alpn_count;
/* 服务端证书链 */
uint8_t *cert_der; /* 整个 chain 的 DER(已拼装为 Certificate 消息片段) */
size_t cert_der_len;
/* 服务端私钥 */
paze_x509_signer_t privkey;
/* 客户端信任锚 */
paze_x509_cert_t *anchors;
int anchor_count;
uint8_t *anchors_owned; /* PEM 解析的 DER 缓冲集(malloc,free 时释放) */
paze_tls_verify_mode_t verify_mode;
paze_tls_verify_cb verify_cb;
void *verify_ctx;
int enable_1_3;
int enable_1_2;
/* 客户端:要用于会话恢复的 PSK 会话(值拷贝) */
paze_tls_session_t session;
/* 服务端:session ticket 加密密钥(首次使用生成)。
* 多个连接共享同一 cfg(通过 paze_tls_config_set_session_ticket_key)
* 即可实现跨连接会话恢复。 */
uint8_t ticket_key[32];
int ticket_key_ready;
/* 0-RTT: 客户端启用(服务端默认接受,1=接受) */
int enable_early;
/* 客户端 key_share 限制:0=默认(X25519 优先);
* PAZE_TLS_GROUP_X25519 / PAZE_TLS_GROUP_SECP256R1 / PAZE_TLS_GROUP_SECP384R1
* = 仅发该组 share(用于测试/限组) */
uint16_t kex_group;
};
/* ============================================================
* 握手状态机
* ============================================================ */
typedef enum {
PAZE_HS_INIT = 0,
/* client 1.3 */
PAZE_HS_CL_WAIT_SH,
PAZE_HS_CL_WAIT_EE,
PAZE_HS_CL_WAIT_CERT_CR_CV, /* Certificate/CertificateRequest/CertificateVerify */
PAZE_HS_CL_WAIT_FINISHED,
PAZE_HS_CL_DONE,
/* client 1.2 */
PAZE_HS_CL12_WAIT_SHD, /* 已发 CH,等 ServerHello */
PAZE_HS_CL12_WAIT_CERT_SKE_SHD, /* 等 Certificate/SKE/ServerHelloDone */
PAZE_HS_CL12_SEND_CKE, /* 发 CKE + CCS + Finished */
PAZE_HS_CL12_WAIT_CCS_FIN, /* 等 CCS + Finished */
/* server 1.3 */
PAZE_HS_SV_WAIT_CH,
PAZE_HS_SV_SEND_SH,
PAZE_HS_SV_SEND_EE_CERT_CV_FIN,
PAZE_HS_SV_WAIT_FINISHED,
PAZE_HS_SV_DONE,
/* server 1.2 */
PAZE_HS_SV12_SEND_SH_CERT_SKE_SHD,
PAZE_HS_SV12_WAIT_CKE,
PAZE_HS_SV12_WAIT_CCS_FIN,
PAZE_HS_SV12_SEND_CCS_FIN,
/* 通用 */
PAZE_HS_ERROR
} paze_tls_hs_state_t;
/* 当前协商参数 */
typedef struct {
int version; /* 0x0303 或 0x0304 */
uint16_t cipher; /* 选中的 cipher suite */
uint16_t group; /* 选中的 kex group */
uint16_t sig_alg; /* 选中的签名算法(server 签名用) */
const paze_hash_alg_t *hash; /* transcript/PRF hash(SHA-256/SHA-384) */
paze_tls_aead_kind_t aead; /* AEAD 种类 */
size_t hash_len;
size_t key_len; /* AEAD 密钥长度 */
char alpn[256];
} paze_tls_negotiated_t;
/* ============================================================
* 连接对象
* ============================================================ */
struct paze_tls {
const paze_tls_config_t *cfg; /* 不拥有;指向用户传入(或内部拷贝) */
paze_tls_config_t *cfg_owned; /* 内部拷贝(若有) */
paze_tls_role_t role;
paze_tls_bio_t bio;
/* record 读写缓冲 */
uint8_t in_buf[PAZE_TLS_MAX_RECORD + 2048];
size_t in_len; /* 已读入未处理 */
size_t in_off; /* 当前 record 起始偏移 */
uint8_t out_buf[PAZE_TLS_MAX_RECORD + 2048];
size_t out_len; /* 待发送 */
/* 当前 traffic keys:
* 1.3: read_key/write_key 在不同阶段切换(handshake/application)
* 1.2: 用 read/write 分别表示 */
paze_tls_traffic_key_t *read_key;
paze_tls_traffic_key_t *write_key;
paze_tls_traffic_key_t handshake_read;
paze_tls_traffic_key_t handshake_write;
paze_tls_traffic_key_t app_read;
paze_tls_traffic_key_t app_write;
int enc_read; /* 接收侧已加密(已收到 peer Finished/ChangeCipherSpec) */
int enc_write; /* 发送侧已加密 */
/* 1.3 key schedule 中间值 */
uint8_t early_secret[64];
uint8_t handshake_secret[64];
uint8_t master_secret[64];
uint8_t client_finished_key[64];
uint8_t server_finished_key[64];
uint8_t binder_key[64];
uint8_t binder_finished_key[64]; /* binder 用 finished_key(RFC 8446 §4.2.11.2) */
uint8_t resumption_master_secret[64];
int resumption_master_valid;
/* PSK 状态 */
int psk_mode; /* 本次握手为 PSK 恢复(无 ECDHE) */
int psk_hash; /* PSK 关联 hash: 0=SHA-256, 1=SHA-384 */
uint8_t psk[64]; size_t psk_len; /* 本次使用的 PSK */
int offered_psk; /* 客户端 CH 中是否发送了 pre_shared_key */
/* 客户端收到的 NewSessionTicket */
uint8_t recv_ticket[512]; size_t recv_ticket_len;
uint8_t ticket_nonce[32]; size_t ticket_nonce_len;
uint32_t ticket_lifetime;
uint32_t ticket_age_add;
int32_t ticket_recv_time;
int have_ticket;
/* transcript */
paze_tls_transcript_t transcript;
/* kex */
paze_tls_kex_t kex;
/* 协商 */
paze_tls_negotiated_t neg;
/* 状态机 */
paze_tls_hs_state_t hs_state;
int handshake_done;
/* 服务端:peer(客户端)的 ClientHello 原始(用于 HelloRetryRequest / TLS 1.2 回退) */
uint8_t *ch1; size_t ch1_len;
int hello_retry;
/* HRR(HelloRetryRequest,RFC 8446 §4.1.3/§4.1.4) */
uint8_t *hrr_raw; size_t hrr_raw_len; /* 服务端发送的 / 客户端收到的 HRR 原始 */
uint8_t *ch2; size_t ch2_len; /* 客户端 HRR 后发送的 ClientHello2 原始 */
int had_hrr; /* 本次握手是否发生 HRR */
uint16_t hrr_group; /* HRR 选择的组 */
int sent_hrr; /* 服务端已发送 HRR(等待 CH2) */
/* 0-RTT 状态(RFC 8446 §4.2.10/§4.5) */
int early_offer; /* 客户端 CH 携带 early_data 扩展 */
int early_sent; /* 客户端已发送 0-RTT 数据 */
int early_accepted; /* 服务端 EE 含 early_data(客户端视角) */
int early_accept; /* 服务端接受 0-RTT(服务端视角) */
int proto13; /* 已进入 1.3 握手(record 层分支用,neg.version 未定前) */
paze_tls_traffic_key_t early_read;
paze_tls_traffic_key_t early_write;
int early_read_valid;
int early_write_valid;
uint8_t early_buf[2048]; /* 服务端收到的 0-RTT 数据(握手完成后交应用) */
size_t early_len;
size_t early_off;
/* 客户端:TLS 1.2 回退时保存的 ServerHello 原始消息 */
uint8_t *sh1; size_t sh1_len;
/* TLS 1.2 握手随机数 */
uint8_t client_random[32];
uint8_t server_random[32];
/* TLS 1.2 master secret */
uint8_t ms12[48];
int ms12_valid;
/* TLS 1.2 pre-master secret(阶段间缓存) */
uint8_t pms12[64];
size_t pms12_len;
/* TLS 1.2 ECDHE:对端(ServerKeyExchange)公钥 */
uint8_t ske_pub[65];
size_t ske_pub_len;
/* 对端证书链(已解析) */
paze_x509_cert_t peer_chain[PAZE_TLS_MAX_CERTS];
int peer_chain_len;
/* 应用数据缓冲(record 解密后的明文,未交给用户) */
uint8_t app_buf[PAZE_TLS_MAX_RECORD];
size_t app_len;
size_t app_off;
/* close_notify */
int close_sent;
int close_recv;
/* 错误 */
char errbuf[128];
};
/* ============================================================
* 内部 API(各模块共享)
* ============================================================ */
/* ---- tls_bio.c ---- */
/* 从 BIO 阻塞读取 n 字节到 buf;返回 PAZE_OK/PAZE_ERR_IO(含 EOF) */
paze_status_t paze_tls_bio_read(paze_tls_t *tls, uint8_t *buf, size_t n);
/* 把 n 字节全部写入 BIO */
paze_status_t paze_tls_bio_write_all(paze_tls_t *tls, const uint8_t *buf, size_t n);
/* ---- tls_record.c ---- */
/* 读取并(若已加密)解密下一条 record。
* out 指向明文(可能指向 tls->in_buf 内部或 app_buf),outlen 给长度。
* content_type 返回 record 的 ContentType(解密后真实类型)。
* 阻塞直至读到一条完整 record 或错误。 */
paze_status_t paze_tls_record_read(paze_tls_t *tls,
const uint8_t **out, size_t *outlen,
uint8_t *content_type);
/* 构造并发送一条 record。fragment 为明文。若 enc=1 则用 write_key 加密。 */
paze_status_t paze_tls_record_send(paze_tls_t *tls, uint8_t content_type,
const uint8_t *fragment, size_t len);
/* 发送明文(未加密)record 的快捷 */
paze_status_t paze_tls_record_send_plain(paze_tls_t *tls, uint8_t content_type,
const uint8_t *frag, size_t len);
/* ---- tls_transcript.c ---- */
void paze_tls_tr_init(paze_tls_transcript_t *t, const paze_hash_alg_t *alg);
void paze_tls_tr_update(paze_tls_transcript_t *t, const uint8_t *data, size_t n);
void paze_tls_tr_snapshot(paze_tls_transcript_t *t);
paze_status_t paze_tls_tr_reset_to_synthetic(paze_tls_transcript_t *t);
paze_status_t paze_tls_tr_finish(paze_tls_transcript_t *t, uint8_t *out);
paze_status_t paze_tls_tr_current(paze_tls_transcript_t *t, uint8_t *out);
/* ---- tls_keys.c ---- */
/* HKDF-Expand-Label (RFC 8446 §7.1) */
paze_status_t paze_tls_hkdf_expand_label(const paze_hash_alg_t *alg,
const uint8_t *secret, size_t slen,
const char *label,
const uint8_t *context, size_t clen,
uint8_t *out, size_t outlen);
/* Derive-Secret(secret, label, transcript) */
paze_status_t paze_tls_derive_secret(const paze_hash_alg_t *alg,
const uint8_t *secret, size_t slen,
const char *label,
paze_tls_transcript_t *tr,
uint8_t *out);
/* 1.3 key schedule: 由 ECDHE 共享密钥 + transcript 推导 handshake/app traffic keys */
paze_status_t paze_tls13_derive_handshake_keys(paze_tls_t *tls,
const uint8_t *shared, size_t shared_len);
paze_status_t paze_tls13_derive_app_keys(paze_tls_t *tls);
/* 0-RTT early traffic key:
* client: 由 early_secret + hash(CH) 派生 "c e traffic" → early_write
* server: 同上 → early_read
* is_client 决定写入哪个方向;aead 为 0-RTT 使用的 AEAD(客户端 = CH 首选套件的
* AEAD;服务端 = 客户端 CH 第一个套件的 AEAD,见 RFC 8446 §4.2.10)。 */
paze_status_t paze_tls13_derive_early_key(paze_tls_t *tls, int is_client,
paze_tls_aead_kind_t aead);
/* 由 traffic secret 派生 traffic key 对象 */
paze_status_t paze_tls13_make_traffic_key(paze_tls_traffic_key_t *tk,
const paze_hash_alg_t *alg,
const uint8_t *secret, size_t slen,
paze_tls_aead_kind_t aead);
/* Finished 验证 */
paze_status_t paze_tls13_compute_finished(const paze_tls_t *tls,
const uint8_t *finished_key, size_t fklen,
const uint8_t *base_key, size_t bklen,
uint8_t *out_verify_data);
/* PSK / 会话恢复 (RFC 8446 §7.1/§7.2/§4.2.11) */
/* early_secret = HKDF-Extract(0, PSK); 并派生 binder_key */
paze_status_t paze_tls13_psk_early_secret(paze_tls_t *tls,
const uint8_t *psk, size_t psk_len,
int hash_id);
/* binder = HMAC(binder_key, transcript_hash) (transcript_hash 由调用方算好) */
paze_status_t paze_tls13_compute_binder(paze_tls_t *tls,
const uint8_t *tr_hash, size_t tr_hash_len,
uint8_t *binder_out);
/* resumption_master_secret = Derive-Secret(master_secret, "res master", tr) */
paze_status_t paze_tls13_derive_resumption_master(paze_tls_t *tls);
/* PSK = HKDF-Expand-Label(resumption_master_secret, "resumption", nonce, Hash.length) */
paze_status_t paze_tls13_derive_resumption_psk(paze_tls_t *tls,
const uint8_t *nonce, size_t nonce_len,
uint8_t *psk_out, size_t *psk_out_len);
/* TLS 1.2 PRF (HMAC-based) */
paze_status_t paze_tls12_prf(const paze_hash_alg_t *alg,
const uint8_t *secret, size_t slen,
const char *label,
const uint8_t *seed, size_t seed_len,
uint8_t *out, size_t outlen);
/* ---- tls_extensions.c ---- */
/* 写扩展到 buf,返回写入长度。各 builder 接收已构造好的数据。 */
size_t paze_tls_ext_write_supported_versions(uint8_t *buf, int is_client, int v13, int v12);
size_t paze_tls_ext_write_supported_groups(uint8_t *buf);
size_t paze_tls_ext_write_signature_algorithms(uint8_t *buf);
size_t paze_tls_ext_write_key_share_client(uint8_t *buf, const paze_tls_kex_t *kex,
uint16_t only_group);
size_t paze_tls_ext_write_sni(uint8_t *buf, const char *host);
size_t paze_tls_ext_write_alpn(uint8_t *buf, char *const *alpn, int n);
size_t paze_tls_ext_write_renegotiation_info(uint8_t *buf);
size_t paze_tls_ext_write_early_data(uint8_t *buf);
int paze_tls_ext_parse_early_data(const uint8_t *data, size_t len);
/* 服务端:构造 key_share 扩展(单 group) */
size_t paze_tls_ext_write_key_share_server(uint8_t *buf, uint16_t group,
const uint8_t *pub, size_t publen);
/* HelloRetryRequest 的 key_share:仅 selected_group(2 字节,无 share key) */
size_t paze_tls_ext_write_hrr_key_share(uint8_t *buf, uint16_t group);
uint16_t paze_tls_ext_parse_hrr_key_share(const uint8_t *data, size_t len);
/* psk_key_exchange_modes(客户端): psk_ke + psk_dhe_ke */
size_t paze_tls_ext_write_psk_key_exchange_modes(uint8_t *buf);
/* pre_shared_key(客户端): identities(1) + binder(1)。返回写入字节数。 */
size_t paze_tls_ext_write_pre_shared_key(uint8_t *buf,
const uint8_t *identity, size_t id_len,
uint32_t obfuscated_age,
const uint8_t *binder, size_t binder_len);
/* ServerHello 中的 pre_shared_key: selected_identity(2 字节) */
size_t paze_tls_ext_write_psk_selected(uint8_t *buf, uint16_t selected);
/* ---- extensions 解析 ---- */
int paze_tls_ext_parse_supported_versions(const uint8_t *data, size_t len, int *picked);
uint16_t paze_tls_ext_parse_supported_groups(const uint8_t *data, size_t len);
uint16_t paze_tls_ext_parse_key_share_server(const uint8_t *data, size_t len,
const uint8_t **pub, size_t *publen);
int paze_tls_ext_find_client_key_share(const uint8_t *data, size_t len,
uint16_t want_group,
const uint8_t **pub, size_t *publen);
int paze_tls_ext_parse_sni(const uint8_t *data, size_t len,
char out[PAZE_TLS_SNI_MAX + 1]);
int paze_tls_ext_parse_alpn(const uint8_t *data, size_t len,
char out[PAZE_TLS_MAX_ALPN][256]);
/* 解析 pre_shared_key(服务端收 CH 用):取第一个 identity 与 binder */
int paze_tls_ext_parse_pre_shared_key(const uint8_t *data, size_t len,
const uint8_t **id, size_t *idlen,
uint32_t *obfuscated_age,
const uint8_t **binder, size_t *binderlen);
/* 解析 ServerHello pre_shared_key:selected_identity */
int paze_tls_ext_parse_psk_selected(const uint8_t *data, size_t len,
uint16_t *selected);
/* 解析 psk_key_exchange_modes:返回是否包含 psk_ke(0) */
int paze_tls_ext_parse_psk_ke_modes(const uint8_t *data, size_t len);
int paze_tls_extensions_foreach(const uint8_t *exts, size_t exts_len,
int (*cb)(uint16_t type, const uint8_t *body,
size_t blen, void *ctx),
void *ctx);
/* ---- 握手消息构造/解析辅助 ---- */
/* 向 msg 写入 4 字节握手头(type + 3 字节长度),返回头指针 */
uint8_t *paze_tls_hs_put_header(uint8_t *msg, uint8_t type, size_t body_len);
/* kex 生成 + ECDHE 共享计算 */
/* group_hint: 0=默认(双组,X25519 优先);
* PAZE_TLS_GROUP_X25519 / PAZE_TLS_GROUP_SECP256R1 = 仅生成该组密钥对 */
paze_status_t paze_tls_kex_generate(paze_tls_kex_t *kex, uint16_t group_hint);
paze_status_t paze_tls_kex_ecdh(paze_tls_kex_t *mine, uint16_t server_group,
const uint8_t *peer_pub, size_t peer_pub_len,
uint8_t *shared_out, size_t *shared_len);
/* 解析对端证书 DER 为 peer_chain 条目:拷贝一份 DER 到自有缓冲,使
* issuer_dn/subject_dn/tbs_der/signature 指针在后续记录处理中保持有效
* (记录层 app_buf 会被后续记录复用)。cert->owned_der 由 paze_x509_free 释放。 */
paze_status_t paze_tls_store_peer_cert(paze_x509_cert_t *cert,
const uint8_t *der, size_t len);
/* 1.3 握手 (由 tls_client/tls_server 调用) */
paze_status_t paze_tls13_client_handshake(paze_tls_t *tls);
paze_status_t paze_tls13_server_handshake(paze_tls_t *tls);
/* 客户端:构造并发送 ClientHello(含 PSK binder 与 0-RTT 密钥派生)。
* 由握手入口与 paze_tls_early_write 共用,可重复安全调用(幂等)。 */
paze_status_t paze_tls13_client_send_ch(paze_tls_t *tls);
/* 构造兼容 CH(TLS 1.3 + 1.2 套件/扩展)。TLS 1.2 独立模式复用。 */
paze_status_t paze_tls13_build_ch(paze_tls_t *tls, uint8_t *out, size_t *outlen);
/* TLS 1.2 握手 */
paze_status_t paze_tls12_client_handshake(paze_tls_t *tls);
paze_status_t paze_tls12_server_handshake(paze_tls_t *tls);
/* ============================================================
* 便利
* ============================================================ */
void paze_tls_set_err(paze_tls_t *tls, const char *fmt, ...);
/* 由 cipher suite 推导 aead/hash/keylen */
void paze_tls_cipher_params(uint16_t cipher,
paze_tls_aead_kind_t *aead,
const paze_hash_alg_t **hash,
size_t *key_len, size_t *hash_len);
#endif /* PAZE_TLS_INTERNAL_H */