mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-05-06 16:36:16 +08:00
Update TLS 1.3 handshake
Working on HelloRetryRequest, NewSessionTicket
This commit is contained in:
@@ -306,6 +306,8 @@ typedef enum {
|
||||
} TLS_SIGNATURE_SCHEME;
|
||||
|
||||
const char *tls_signature_scheme_name(int scheme);
|
||||
int tls_signature_scheme_oid(int sig_alg);
|
||||
int tls_signature_scheme_from_oid(int sig_alg_oid);
|
||||
int tls_signature_scheme_match_cipher_suite(int sig_alg, int cipher_suite);
|
||||
|
||||
|
||||
@@ -350,6 +352,7 @@ typedef enum {
|
||||
TLS_alert_no_renegotiation = 100,
|
||||
TLS_alert_missing_extension = 109, // 查以下RFC
|
||||
TLS_alert_unsupported_extension = 110,
|
||||
TLS_alert_certificate_unobtainable = 111,
|
||||
TLS_alert_unsupported_site2site = 200,
|
||||
TLS_alert_no_area = 201,
|
||||
TLS_alert_unsupported_areatype = 202,
|
||||
@@ -385,6 +388,7 @@ int tls_record_decrypt(const SM3_HMAC_CTX *hmac_ctx, const SM4_KEY *cbc_key,
|
||||
uint8_t *out, size_t *outlen);
|
||||
|
||||
int tls_seq_num_incr(uint8_t seq_num[8]);
|
||||
void tls_seq_num_reset(uint8_t seq_num[8]);
|
||||
int tls_random_generate(uint8_t random[32]);
|
||||
int tls_random_print(FILE *fp, const uint8_t random[32], int format, int indent);
|
||||
int tls_pre_master_secret_generate(uint8_t pre_master_secret[48], int protocol);
|
||||
@@ -710,6 +714,16 @@ enum {
|
||||
|
||||
#define TLS_MAX_CIPHER_SUITES_COUNT 64
|
||||
|
||||
|
||||
typedef struct {
|
||||
int sig_alg;
|
||||
uint8_t *name;
|
||||
size_t namelen;
|
||||
uint8_t *certs;
|
||||
size_t certslen;
|
||||
} TLS_CERTS;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int protocol;
|
||||
|
||||
@@ -721,9 +735,13 @@ typedef struct {
|
||||
|
||||
uint8_t *cacerts;
|
||||
size_t cacertslen;
|
||||
|
||||
uint8_t *certs;
|
||||
size_t certslen;
|
||||
|
||||
TLS_CERTS extra_certs[16];
|
||||
size_t extra_certs_cnt;
|
||||
|
||||
|
||||
// extensions
|
||||
int supported_versions[4];
|
||||
@@ -751,6 +769,12 @@ typedef struct {
|
||||
const uint8_t *signed_certificate_timestamp;
|
||||
size_t signed_certificate_timestamp_len;
|
||||
|
||||
|
||||
// 用于加密和解密session ticket
|
||||
SM4_KEY server_session_ticket_key;
|
||||
|
||||
int new_session_ticket;
|
||||
|
||||
int quiet;
|
||||
} TLS_CTX;
|
||||
|
||||
@@ -802,6 +826,7 @@ enum {
|
||||
TLS_state_client_finished,
|
||||
TLS_state_server_change_cipher_spec,
|
||||
TLS_state_server_finished,
|
||||
TLS_state_new_session_ticket,
|
||||
TLS_state_handshake_over,
|
||||
};
|
||||
|
||||
@@ -810,23 +835,7 @@ typedef struct {
|
||||
|
||||
int protocol;
|
||||
|
||||
/*
|
||||
服务器端在初始化之后,会创建一个server_ciphers列表
|
||||
在接收到client_ciphers之后,和自己的server_ciphers对比,选择出conn->cipher
|
||||
也可能没有找到一致的cipher,那么就失败了
|
||||
实际上服务器端的ciphers可以完全来自CTX,并不需要缓存
|
||||
|
||||
客户端在初始化之后,创建client_ciphers,发送给服务器
|
||||
在接收到服务器的cipher后,要判断这个cipher是否在自己的client_ciphers之中
|
||||
但是客户端是需要缓存ciphers的,这样才能够判断返回的cipher是否在自己的ciphers之中
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
下面的问题是在CONN中要维护哪些信息?
|
||||
*/
|
||||
|
||||
int cipher_suites[TLS_MAX_CIPHER_SUITES_COUNT];
|
||||
size_t cipher_suites_cnt;
|
||||
@@ -916,20 +925,27 @@ typedef struct {
|
||||
uint16_t server_sig_alg;
|
||||
|
||||
|
||||
|
||||
uint16_t ecdh_named_curve;
|
||||
|
||||
|
||||
X509_KEY ecdh_keys[2];
|
||||
|
||||
|
||||
size_t ecdh_keys_cnt;
|
||||
|
||||
X509_KEY ecdh_key;
|
||||
|
||||
int peer_group;
|
||||
uint8_t peer_ecdh_point[65];
|
||||
size_t peer_ecdh_point_len;
|
||||
|
||||
|
||||
X509_KEY key_exchanges[2];
|
||||
size_t key_exchanges_cnt;
|
||||
size_t key_exchange_idx;
|
||||
|
||||
int key_exchange_group;
|
||||
uint8_t peer_key_exchange[65];
|
||||
size_t peer_key_exchange_len;
|
||||
|
||||
|
||||
// tls13 需要提前生成每一种曲线的密钥
|
||||
SM2_KEY sm2_ecdhe;
|
||||
@@ -937,7 +953,14 @@ typedef struct {
|
||||
uint8_t peer_sm2_ecdhe[65];
|
||||
uint8_t peer_p256_ecdhe[65];
|
||||
|
||||
int client_certificate_verify; // 是否验证客户端证书
|
||||
|
||||
// 服务器在接收到ClientHello中,计算出双方算法的交集,并保存
|
||||
// 服务器在发送CertificateRequest的时候,需要把这个集合发送给客户端
|
||||
// 客户端在使用的时候实际上使用CTX中的集合发送
|
||||
int signature_algorithms[2];
|
||||
size_t signature_algorithms_cnt;
|
||||
|
||||
|
||||
|
||||
int verify_depth; // 这个可能没有被设置
|
||||
|
||||
@@ -955,9 +978,19 @@ typedef struct {
|
||||
uint8_t server_application_traffic_secret[32];
|
||||
|
||||
|
||||
int hello_retry_request;
|
||||
|
||||
int key_exchange_group;
|
||||
int hello_retry_request;
|
||||
int certificate_request;
|
||||
int early_data;
|
||||
int new_session_ticket;
|
||||
|
||||
int client_certificate_verify; // TLS1.2 TLCP需要这个
|
||||
|
||||
uint8_t cookie[512];
|
||||
size_t cookielen;
|
||||
|
||||
|
||||
|
||||
} TLS_CONNECT;
|
||||
|
||||
|
||||
@@ -1131,6 +1164,21 @@ int tls13_key_share_server_hello_print(FILE *fp, int fmt, int ind,
|
||||
int tls13_signature_algorithms_cert_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen);
|
||||
|
||||
|
||||
|
||||
// NewSessionTicket
|
||||
int tls13_ticket_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
|
||||
int tls13_encrypt_ticket(const SM4_KEY *key, const uint8_t resumption_master_secret[48],
|
||||
int protocol_version, int cipher_suite, uint32_t ticket_issue_time, uint32_t ticket_lifetime,
|
||||
uint8_t *out, size_t *outlen);
|
||||
int tls13_decrypt_ticket(const SM4_KEY *key, const uint8_t *in, size_t inlen,
|
||||
uint8_t resumption_master_secret[48], int *protocol_version, int *cipher_suite,
|
||||
uint32_t *ticket_issue_time, uint32_t *ticket_lifetime);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -337,6 +337,7 @@ int x509_cert_get_issuer(const uint8_t *a, size_t alen, const uint8_t **name, si
|
||||
int x509_cert_get_subject(const uint8_t *a, size_t alen, const uint8_t **subj, size_t *subj_len);
|
||||
int x509_cert_get_subject_public_key(const uint8_t *a, size_t alen, X509_KEY *public_key);
|
||||
int x509_cert_get_exts(const uint8_t *a, size_t alen, const uint8_t **d, size_t *dlen);
|
||||
int x509_cert_get_signature_algor(const uint8_t *a, size_t alen, int *oid);
|
||||
|
||||
int x509_certs_to_pem(const uint8_t *d, size_t dlen, FILE *fp);
|
||||
int x509_certs_from_pem(uint8_t *d, size_t *dlen, size_t maxlen, FILE *fp);
|
||||
|
||||
23
src/tls.c
23
src/tls.c
@@ -1670,6 +1670,11 @@ int tls_seq_num_incr(uint8_t seq_num[8])
|
||||
return 1;
|
||||
}
|
||||
|
||||
void tls_seq_num_reset(uint8_t seq_num[8])
|
||||
{
|
||||
memset(seq_num, 0, 8);
|
||||
}
|
||||
|
||||
int tls_compression_methods_has_null_compression(const uint8_t *meths, size_t methslen)
|
||||
{
|
||||
if (!meths || !methslen) {
|
||||
@@ -2247,8 +2252,6 @@ int tls_ctx_set_signature_algorithms(TLS_CTX *ctx, const int *sig_algs, size_t s
|
||||
|
||||
int tls_ctx_init(TLS_CTX *ctx, int protocol, int is_client)
|
||||
{
|
||||
|
||||
|
||||
const int supported_versions[] = {
|
||||
TLS_protocol_tls13,
|
||||
TLS_protocol_tls12,
|
||||
@@ -2257,11 +2260,13 @@ int tls_ctx_init(TLS_CTX *ctx, int protocol, int is_client)
|
||||
size_t supported_versions_cnt = sizeof(supported_versions)/sizeof(supported_versions[0]);
|
||||
|
||||
const int supported_groups[] = {
|
||||
TLS_curve_sm2p256v1,
|
||||
TLS_curve_secp256r1,
|
||||
TLS_curve_sm2p256v1,
|
||||
};
|
||||
size_t supported_groups_cnt = sizeof(supported_groups)/sizeof(supported_groups[0]);
|
||||
|
||||
|
||||
|
||||
const int signature_algorithms[] = {
|
||||
TLS_sig_sm2sig_sm3,
|
||||
TLS_sig_ecdsa_secp256r1_sha256,
|
||||
@@ -2295,9 +2300,16 @@ int tls_ctx_init(TLS_CTX *ctx, int protocol, int is_client)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// test HelloRetryRequest
|
||||
if (!is_client) {
|
||||
tls_ctx_set_supported_groups(ctx, supported_groups + 1, supported_groups_cnt - 1);
|
||||
}
|
||||
|
||||
|
||||
ctx->verify_depth = 5;
|
||||
|
||||
ctx->new_session_ticket = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2567,6 +2579,11 @@ int tls_init(TLS_CONNECT *conn, const TLS_CTX *ctx)
|
||||
|
||||
conn->ctx = ctx;
|
||||
|
||||
|
||||
conn->key_exchanges_cnt = 1;
|
||||
|
||||
conn->new_session_ticket = ctx->new_session_ticket;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
2978
src/tls13.c
2978
src/tls13.c
File diff suppressed because it is too large
Load Diff
@@ -321,6 +321,24 @@ const char *tls_signature_scheme_name(int scheme)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int tls_signature_scheme_oid(int sig_alg)
|
||||
{
|
||||
switch (sig_alg) {
|
||||
case TLS_sig_sm2sig_sm3: return OID_sm2sign_with_sm3;
|
||||
case TLS_sig_ecdsa_secp256r1_sha256: return OID_ecdsa_with_sha256;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tls_signature_scheme_from_oid(int sig_alg_oid)
|
||||
{
|
||||
switch (sig_alg_oid) {
|
||||
case OID_sm2sign_with_sm3: return TLS_sig_sm2sig_sm3;
|
||||
case OID_ecdsa_with_sha256: return TLS_sig_ecdsa_secp256r1_sha256;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tls_random_print(FILE *fp, const uint8_t random[32], int format, int indent)
|
||||
{
|
||||
time_t gmt_unix_time = 0;
|
||||
@@ -382,7 +400,7 @@ int tls_extension_print(FILE *fp, int type, const uint8_t *data, size_t datalen,
|
||||
while (len) {
|
||||
uint16_t proto;
|
||||
tls_uint16_from_bytes(&proto, &p, &len);
|
||||
format_print(fp, format, indent, "%s (0x%04x)\n",
|
||||
format_print(fp, format, indent, "%s (%04x)\n",
|
||||
tls_protocol_name(proto), proto);
|
||||
}
|
||||
break;
|
||||
@@ -423,7 +441,7 @@ int tls_extension_print(FILE *fp, int type, const uint8_t *data, size_t datalen,
|
||||
while (len) {
|
||||
uint16_t sig_alg;
|
||||
tls_uint16_from_bytes(&sig_alg, &p, &len);
|
||||
format_print(fp, format, indent, "%s (0x%04x)\n",
|
||||
format_print(fp, format, indent, "%s (%04x)\n",
|
||||
tls_signature_scheme_name(sig_alg), sig_alg);
|
||||
}
|
||||
break;
|
||||
@@ -500,8 +518,8 @@ int tls_client_hello_print(FILE *fp, const uint8_t *data, size_t datalen, int fo
|
||||
|
||||
format_print(fp, format, indent, "ClientHello\n"); indent += 4;
|
||||
if (tls_uint16_from_bytes(&protocol, &data, &datalen) != 1) goto end;
|
||||
format_print(fp, format, indent, "Version: %s (%d.%d)\n",
|
||||
tls_protocol_name(protocol), protocol >> 8, protocol & 0xff);
|
||||
format_print(fp, format, indent, "Version: %s (%04x)\n",
|
||||
tls_protocol_name(protocol), protocol);
|
||||
if (tls_array_from_bytes(&random, 32, &data, &datalen) != 1) goto end;
|
||||
tls_random_print(fp, random, format, indent);
|
||||
if (tls_uint8array_from_bytes(&session_id, &session_id_len, &data, &datalen) != 1) goto end;
|
||||
@@ -511,7 +529,7 @@ int tls_client_hello_print(FILE *fp, const uint8_t *data, size_t datalen, int fo
|
||||
while (cipher_suites_len >= 2) {
|
||||
uint16_t cipher;
|
||||
if (tls_uint16_from_bytes(&cipher, &cipher_suites, &cipher_suites_len) != 1) goto end;
|
||||
format_print(fp, format, indent + 4, "%s (0x%04x)\n",
|
||||
format_print(fp, format, indent + 4, "%s (%04x)\n",
|
||||
tls_cipher_suite_name(cipher), cipher);
|
||||
}
|
||||
if (cipher_suites_len) {
|
||||
@@ -586,14 +604,14 @@ int tls_server_hello_print(FILE *fp, const uint8_t *data, size_t datalen, int fo
|
||||
|
||||
format_print(fp, format, indent, "ServerHello\n"); indent += 4;
|
||||
if (tls_uint16_from_bytes(&protocol, &data, &datalen) != 1) goto bad;
|
||||
format_print(fp, format, indent, "Version: %s (%d.%d)\n",
|
||||
tls_protocol_name(protocol), protocol >> 8, protocol & 0xff);
|
||||
format_print(fp, format, indent, "Version: %s (%04x)\n",
|
||||
tls_protocol_name(protocol), protocol);
|
||||
if (tls_array_from_bytes(&random, 32, &data, &datalen) != 1) goto bad;
|
||||
tls_random_print(fp, random, format, indent);
|
||||
if (tls_uint8array_from_bytes(&session_id, &session_id_len, &data, &datalen) != 1) goto bad;
|
||||
format_bytes(fp, format, indent, "SessionID", session_id, session_id_len);
|
||||
if (tls_uint16_from_bytes(&cipher_suite, &data, &datalen) != 1) goto bad;
|
||||
format_print(fp, format, indent, "CipherSuite: %s (0x%04x)\n",
|
||||
format_print(fp, format, indent, "CipherSuite: %s (%04x)\n",
|
||||
tls_cipher_suite_name(cipher_suite), cipher_suite);
|
||||
if (tls_uint8_from_bytes(&comp_meth, &data, &datalen) != 1) goto bad;
|
||||
format_print(fp, format, indent, "CompressionMethod: %s (%d)\n",
|
||||
@@ -673,7 +691,7 @@ int tls_server_key_exchange_ecdhe_print(FILE *fp, const uint8_t *data, size_t da
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_print(fp, format, indent, "SignatureScheme: %s (0x%04x)\n",
|
||||
format_print(fp, format, indent, "SignatureScheme: %s (%04x)\n",
|
||||
tls_signature_scheme_name(sig_alg), sig_alg);
|
||||
if (tls_uint16array_from_bytes(&sig, &siglen, &data, &datalen) != 1) {
|
||||
error_print();
|
||||
@@ -990,7 +1008,7 @@ int tls_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int for
|
||||
protocol = tls_record_protocol(record);
|
||||
format_print(fp, format, indent, "Record\n"); indent += 4;
|
||||
format_print(fp, format, indent, "ContentType: %s (%d)\n", tls_record_type_name(record[0]), record[0]);
|
||||
format_print(fp, format, indent, "Version: %s (%d.%d)\n", tls_protocol_name(protocol), protocol >> 8, protocol & 0xff);
|
||||
format_print(fp, format, indent, "Version: %s (%04x)\n", tls_protocol_name(protocol), protocol);
|
||||
format_print(fp, format, indent, "Length: %d\n", tls_record_data_length(record));
|
||||
|
||||
data = tls_record_data(record);
|
||||
@@ -1075,7 +1093,7 @@ int tls_encrypted_record_print(FILE *fp, const uint8_t *record, size_t recordle
|
||||
protocol = tls_record_protocol(record);
|
||||
format_print(fp, format, indent, "EncryptedRecord\n"); indent += 4;
|
||||
format_print(fp, format, indent, "ContentType: %s (%d)\n", tls_record_type_name(record[0]), record[0]);
|
||||
format_print(fp, format, indent, "Version: %s (%d.%d)\n", tls_protocol_name(protocol), protocol >> 8, protocol & 0xff);
|
||||
format_print(fp, format, indent, "Version: %s (%04x)\n", tls_protocol_name(protocol), protocol);
|
||||
format_print(fp, format, indent, "Length: %d\n", tls_record_data_length(record));
|
||||
format_bytes(fp, format, indent, "EncryptedData", tls_record_data(record), tls_record_data_length(record));
|
||||
|
||||
|
||||
@@ -1594,6 +1594,36 @@ int x509_cert_get_exts(const uint8_t *a, size_t alen, const uint8_t **d, size_t
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_cert_get_signature_algor(const uint8_t *a, size_t alen, int *oid)
|
||||
{
|
||||
int inner_alg;
|
||||
int outer_alg;
|
||||
|
||||
if (x509_cert_get_details(a, alen,
|
||||
NULL, // version
|
||||
NULL, NULL, // serial
|
||||
&inner_alg, // signature_algor
|
||||
NULL, NULL, // issuer
|
||||
NULL, NULL, // validity
|
||||
NULL, NULL, // subject
|
||||
NULL, // subject_public_key
|
||||
NULL, NULL, // issuer_unique_id
|
||||
NULL, NULL, // subject_unique_id
|
||||
NULL, NULL, // extensions
|
||||
&outer_alg, // signature_algor
|
||||
NULL, NULL // signature
|
||||
) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (inner_alg != outer_alg) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*oid = inner_alg;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_certs_to_pem(const uint8_t *d, size_t dlen, FILE *fp)
|
||||
{
|
||||
const uint8_t *a;
|
||||
|
||||
@@ -436,9 +436,68 @@ static int test_tls13_signature_algorithms_cert_ext(void)
|
||||
}
|
||||
|
||||
|
||||
int tls13_ticket_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
|
||||
int tls13_encrypt_ticket(const SM4_KEY *key, const uint8_t resumption_master_secret[48],
|
||||
int protocol_version, int cipher_suite, uint32_t ticket_issue_time, uint32_t ticket_lifetime,
|
||||
uint8_t *out, size_t *outlen);
|
||||
int tls13_decrypt_ticket(const SM4_KEY *key, const uint8_t *in, size_t inlen,
|
||||
uint8_t resumption_master_secret[48], int *protocol_version, int *cipher_suite,
|
||||
uint32_t *ticket_issue_time, uint32_t *ticket_lifetime);
|
||||
|
||||
|
||||
|
||||
static int test_tls13_ticket(void)
|
||||
{
|
||||
SM4_KEY server_session_ticket_key;
|
||||
uint8_t raw_key[16] = {0};
|
||||
|
||||
uint8_t resumption_master_secret[48] = { 1, 2, 3, };
|
||||
int protocol_version = TLS_protocol_tls13;
|
||||
int cipher_suite = TLS_cipher_sm4_gcm_sm3;
|
||||
uint32_t ticket_issue_time = time(NULL);
|
||||
uint32_t ticket_lifetime = 60 * 60 * 24;
|
||||
|
||||
uint8_t ticket[12 + 60 + 16];
|
||||
size_t ticketlen;
|
||||
|
||||
uint8_t _resumption_master_secret[48];
|
||||
int _protocol_version;
|
||||
int _cipher_suite;
|
||||
uint32_t _ticket_issue_time;
|
||||
uint32_t _ticket_lifetime;
|
||||
|
||||
sm4_set_encrypt_key(&server_session_ticket_key, raw_key);
|
||||
|
||||
if (tls13_encrypt_ticket(&server_session_ticket_key,
|
||||
resumption_master_secret, protocol_version, cipher_suite,
|
||||
ticket_issue_time, ticket_lifetime,
|
||||
ticket, &ticketlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tls13_decrypt_ticket(&server_session_ticket_key,
|
||||
ticket, ticketlen,
|
||||
_resumption_master_secret, &_protocol_version, &_cipher_suite,
|
||||
&_ticket_issue_time, &_ticket_lifetime) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(_resumption_master_secret, resumption_master_secret, 48) != 0
|
||||
|| _protocol_version != protocol_version
|
||||
|| _cipher_suite != cipher_suite
|
||||
|| _ticket_issue_time != ticket_issue_time
|
||||
|| _ticket_lifetime != ticket_lifetime) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -488,6 +547,8 @@ int main(void)
|
||||
if (test_tls_supported_groups_ext() != 1) goto err;
|
||||
if (test_tls_signature_algorithms_ext() != 1) goto err;
|
||||
if (test_tls13_signature_algorithms_cert_ext() != 1) goto err;
|
||||
if (test_tls13_ticket() != 1) goto err;
|
||||
|
||||
|
||||
printf("%s all tests passed\n", __FILE__);
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user