mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-05-07 00:46:17 +08:00
Update TLS 1.3
This commit is contained in:
@@ -38,6 +38,7 @@ void tls_uint8_to_bytes(uint8_t a, uint8_t **out, size_t *outlen);
|
||||
void tls_uint16_to_bytes(uint16_t a, uint8_t **out, size_t *outlen);
|
||||
void tls_uint24_to_bytes(uint24_t a, uint8_t **out, size_t *outlen);
|
||||
void tls_uint32_to_bytes(uint32_t a, uint8_t **out, size_t *outlen);
|
||||
void tls_uint64_to_bytes(uint64_t a, uint8_t **out, size_t *outlen);
|
||||
void tls_array_to_bytes(const uint8_t *data, size_t len, uint8_t **out, size_t *outlen);
|
||||
void tls_uint8array_to_bytes(const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen);
|
||||
void tls_uint16array_to_bytes(const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen);
|
||||
@@ -46,6 +47,7 @@ int tls_uint8_from_bytes(uint8_t *a, const uint8_t **in, size_t *inlen);
|
||||
int tls_uint16_from_bytes(uint16_t *a, const uint8_t **in, size_t *inlen);
|
||||
int tls_uint24_from_bytes(uint24_t *a, const uint8_t **in, size_t *inlen);
|
||||
int tls_uint32_from_bytes(uint32_t *a, const uint8_t **in, size_t *inlen);
|
||||
int tls_uint64_from_bytes(uint64_t *a, const uint8_t **in, size_t *inlen);
|
||||
int tls_array_from_bytes(const uint8_t **data, size_t datalen, const uint8_t **in, size_t *inlen);
|
||||
int tls_uint8array_from_bytes(const uint8_t **data, size_t *datalen, const uint8_t **in, size_t *inlen);
|
||||
int tls_uint16array_from_bytes(const uint8_t **data, size_t *datalen, const uint8_t **in, size_t *inlen);
|
||||
@@ -67,7 +69,7 @@ typedef enum {
|
||||
} TLS_PROTOCOL;
|
||||
|
||||
const char *tls_protocol_name(int proto);
|
||||
|
||||
int tls_protocol_from_name(const char *name);
|
||||
|
||||
typedef enum {
|
||||
TLS_cipher_null_with_null_null = 0x0000,
|
||||
@@ -103,6 +105,7 @@ typedef enum {
|
||||
} TLS_CIPHER_SUITE;
|
||||
|
||||
const char *tls_cipher_suite_name(int cipher);
|
||||
int tls_cipher_suite_from_name(const char *name);
|
||||
int tls_cipher_suites_select(const uint8_t *client_ciphers, size_t client_ciphers_len,
|
||||
const int *server_ciphers, size_t server_ciphers_cnt, int *selected_cipher);
|
||||
int tls_cipher_suite_in_list(int cipher, const int *list, size_t list_count);
|
||||
@@ -258,7 +261,7 @@ typedef enum {
|
||||
} TLS_CURVE_TYPE;
|
||||
|
||||
const char *tls_curve_type_name(int type);
|
||||
|
||||
int tls_named_curve_from_name(const char *name);
|
||||
|
||||
typedef enum {
|
||||
TLS_curve_secp256k1 = 22,
|
||||
@@ -307,6 +310,12 @@ typedef enum {
|
||||
} TLS_SIGNATURE_SCHEME;
|
||||
|
||||
const char *tls_signature_scheme_name(int scheme);
|
||||
int tls_signature_scheme_from_name(const char *name);
|
||||
|
||||
int tls_signature_scheme_algorithm_oid(int sig_alg);
|
||||
int tls_signature_scheme_group_oid(int sig_alg);
|
||||
|
||||
|
||||
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);
|
||||
@@ -725,94 +734,135 @@ typedef struct {
|
||||
} TLS_CERTS;
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
char hostname[256];
|
||||
|
||||
uint8_t pre_shared_key[32];
|
||||
uint16_t protocol_version;
|
||||
uint16_t cipher_suite;
|
||||
uint32_t ticket_issue_time;
|
||||
uint32_t ticket_lifetime;
|
||||
|
||||
uint32_t ticket_age_add;
|
||||
uint8_t ticket[256];
|
||||
size_t ticketlen;
|
||||
|
||||
|
||||
// TODO: SNI, ALPN, client_certificate (dgst or subject), ticket_age_add, max_early_data_size
|
||||
} TLS_SESSION;
|
||||
|
||||
#define TLS13_SCT_MAX_SIZE (32 + 8 + 2 + SM2_MAX_SIGNATURE_SIZE) // = 114
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
int is_client;
|
||||
|
||||
int quiet;
|
||||
|
||||
int protocol;
|
||||
|
||||
|
||||
int is_client;
|
||||
|
||||
// 客户端和服务器端协商出公共的cipher_suite
|
||||
int cipher_suites[TLS_MAX_CIPHER_SUITES_COUNT];
|
||||
size_t cipher_suites_cnt;
|
||||
|
||||
uint8_t *cacerts;
|
||||
size_t cacertslen;
|
||||
int key_exchange_modes;
|
||||
|
||||
uint8_t *certs;
|
||||
|
||||
// 服务器端需要根据客户端提供的SNI来选择证书链
|
||||
// 客户端需要根据服务器提供的CA以及算法限定来选择证书链,因此双方都需要准备多个证书链
|
||||
|
||||
|
||||
// 在TLS 1.3中,证书链是 CertificateEntry certificate_list
|
||||
// 这意味着其中每个证书都可能有附带的扩展,
|
||||
/*
|
||||
|
||||
status_request 这个信息主要是最近的OCSP的信息,表明证书的状态
|
||||
signed_certificate_timestamp 这个信息是长期的,CT的信息,一般是不变的
|
||||
|
||||
因此客户端在提供证书的时候,实际上可以将这个信息直接附在上面
|
||||
|
||||
我们在保存的时候也应该保存完整的certificate_list,而不是单独的信息
|
||||
也许我们需要一个信息来标注里面存储的格式
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// 允许设定多个证书链,每个证书链对应一个x509_key,或者一个附加的enc_key
|
||||
|
||||
uint8_t cert_chains[8192];
|
||||
size_t cert_chains_len;
|
||||
size_t cert_chains_cnt; // 这是一个多余的值,不应该存储多余的值
|
||||
size_t cert_chain_idx;
|
||||
uint8_t *certs; // 这里应该改为cert_chain,我们将certs表示为互相独立的证书
|
||||
size_t certslen;
|
||||
|
||||
TLS_CERTS extra_certs[16];
|
||||
size_t extra_certs_cnt;
|
||||
// 每个证书链都应该有附带的status_request和sct信息
|
||||
// status_request_ocsp_response
|
||||
// sct_list 证书透明有关的信息,这是一个长期的信息
|
||||
// 这两个信息实际上都是证书链的扩展,因此这里我们需要准备相应的数据了
|
||||
// 这里还是暂时不给出好了
|
||||
|
||||
|
||||
// extensions
|
||||
int supported_versions[4];
|
||||
size_t supported_versions_cnt;
|
||||
|
||||
int supported_groups[32];
|
||||
size_t supported_groups_cnt;
|
||||
|
||||
int signature_algorithms[2];
|
||||
size_t signature_algorithms_cnt;
|
||||
|
||||
int protocols[4];
|
||||
size_t protocols_cnt;
|
||||
|
||||
// 这里面需要解决的是,TLCP和TLS中证书链和密钥数量不对等的问题,一个TLCP证书链需要2个密钥
|
||||
X509_KEY x509_keys[4];
|
||||
X509_KEY enc_keys[4];
|
||||
|
||||
size_t x509_keys_cnt;
|
||||
X509_KEY signkey;
|
||||
X509_KEY kenckey;
|
||||
|
||||
// 对于客户端来说,需要提供所有的CA证书,注意这里不是证书链,而是一个个独立的证书
|
||||
// 对于服务器来说,在certificate_request中,需要从这些证书中提取dn_names,并发送给客户端,然后再验证客户端证书
|
||||
uint8_t *cacerts;
|
||||
size_t cacertslen;
|
||||
int verify_depth;
|
||||
|
||||
// 这个应该是和服务器证书相关的
|
||||
const uint8_t *certificate_status;
|
||||
size_t certificate_status_len;
|
||||
// 这是一个系统参数,决定了客户端在ClientHello中发送多少个key_exchanges
|
||||
// CTX中这个参数应该是没有意义的,服务器应该总是1,客户端应该>=1
|
||||
// 是否可以设置为0呢?
|
||||
size_t key_exchanges_cnt;
|
||||
|
||||
const uint8_t *signed_certificate_timestamp;
|
||||
size_t signed_certificate_timestamp_len;
|
||||
|
||||
// extensions
|
||||
|
||||
// 5. status_request
|
||||
int status_request;
|
||||
const uint8_t *status_request_responder_id_list;
|
||||
size_t status_request_responder_id_list_len;
|
||||
const uint8_t *status_request_exts;
|
||||
size_t status_request_exts_len;
|
||||
const uint8_t *status_request_ocsp_response;
|
||||
size_t status_request_ocsp_response_len;
|
||||
|
||||
|
||||
// 10. supported_gruops
|
||||
int supported_groups[32];
|
||||
size_t supported_groups_cnt;
|
||||
|
||||
|
||||
// 13. signature_algorithms
|
||||
int signature_algorithms[2];
|
||||
size_t signature_algorithms_cnt;
|
||||
|
||||
// 18. signed_certificate_timestamp
|
||||
int signed_certificate_timestamp;
|
||||
const uint8_t *signed_certificate_timestamp_list;
|
||||
size_t signed_certificate_timestamp_list_len;
|
||||
|
||||
// 35. session_ticket
|
||||
// NewSessionTicket
|
||||
int new_session_ticket;
|
||||
int new_session_ticket_cnt;
|
||||
SM4_KEY *session_ticket_key;
|
||||
SM4_KEY _session_ticket_key;
|
||||
|
||||
int new_session_ticket;
|
||||
int new_session_ticket_cnt;
|
||||
|
||||
|
||||
// 设置客户端是否启用PSK模式
|
||||
int pre_shared_key_enabled;
|
||||
|
||||
|
||||
TLS_SESSION session;
|
||||
|
||||
int early_data_enabled;
|
||||
// 42. early_data
|
||||
int early_data;
|
||||
int max_early_data_size;
|
||||
|
||||
int quiet;
|
||||
// 43. supported_versions
|
||||
int supported_versions[4];
|
||||
size_t supported_versions_cnt;
|
||||
|
||||
// 44. cookie
|
||||
int cookie;
|
||||
SM4_KEY cookie_key;
|
||||
|
||||
|
||||
// 46. psk_key_exchange_modes
|
||||
|
||||
|
||||
} TLS_CTX;
|
||||
|
||||
int tls_ctx_init(TLS_CTX *ctx, int protocol, int is_client);
|
||||
int tls_ctx_set_cipher_suites(TLS_CTX *ctx, const int *cipher_suites, size_t cipher_suites_cnt);
|
||||
int tls_ctx_set_signature_algorithms(TLS_CTX *ctx, const int *sig_algs, size_t sig_algs_cnt);
|
||||
int tls_ctx_set_ca_certificates(TLS_CTX *ctx, const char *cacertsfile, int depth);
|
||||
int tls_ctx_set_certificate_and_key(TLS_CTX *ctx, const char *chainfile,
|
||||
const char *keyfile, const char *keypass);
|
||||
@@ -821,6 +871,8 @@ int tls_ctx_set_tlcp_server_certificate_and_keys(TLS_CTX *ctx, const char *chain
|
||||
const char *kenckeyfile, const char *kenckeypass);
|
||||
void tls_ctx_cleanup(TLS_CTX *ctx);
|
||||
|
||||
int tls_ctx_add_certificate_chain_and_key(TLS_CTX *ctx, const char *chainfile,
|
||||
const char *keyfile, const char *keypass);
|
||||
|
||||
|
||||
#define TLS_MAX_CERTIFICATES_SIZE 2048
|
||||
@@ -867,51 +919,68 @@ enum {
|
||||
TLS_state_handshake_over,
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
int is_client;
|
||||
|
||||
const char *hostname;
|
||||
|
||||
int protocol;
|
||||
|
||||
|
||||
|
||||
int cipher_suites[TLS_MAX_CIPHER_SUITES_COUNT];
|
||||
size_t cipher_suites_cnt;
|
||||
int cipher_suite;
|
||||
const DIGEST *digest;
|
||||
const BLOCK_CIPHER *cipher;
|
||||
int is_client; // 这个在CTX中应该是有的
|
||||
|
||||
int quiet;
|
||||
|
||||
tls_socket_t sock;
|
||||
|
||||
uint8_t enced_record[TLS_MAX_RECORD_SIZE];
|
||||
size_t enced_record_len;
|
||||
TLS_CTX *ctx;
|
||||
|
||||
// handshake state for state machine
|
||||
int state;
|
||||
|
||||
|
||||
uint8_t record[TLS_MAX_RECORD_SIZE];
|
||||
size_t record_offset; // offset of processed record
|
||||
size_t recordlen;
|
||||
|
||||
|
||||
uint8_t plain_record[TLS_MAX_RECORD_SIZE];
|
||||
size_t plain_recordlen;
|
||||
|
||||
int record_state;
|
||||
|
||||
|
||||
uint8_t databuf[TLS_MAX_RECORD_SIZE];
|
||||
uint8_t databuf[TLS_MAX_RECORD_SIZE]; // 需要替换为plain_record
|
||||
uint8_t *data;
|
||||
size_t datalen;
|
||||
|
||||
|
||||
|
||||
|
||||
int protocol;
|
||||
|
||||
int key_exchange_modes;
|
||||
|
||||
int cipher_suite;
|
||||
const DIGEST *digest;
|
||||
const BLOCK_CIPHER *cipher;
|
||||
|
||||
|
||||
uint8_t session_id[32];
|
||||
size_t session_id_len;
|
||||
uint8_t client_random[32];
|
||||
uint8_t server_random[32];
|
||||
|
||||
|
||||
// 一般来说我们只要保存对方发过来的证书,因为己方的证书都在CTX中,对吗?
|
||||
uint8_t server_certs[TLS_MAX_CERTIFICATES_SIZE]; // TODO: use ptr and malloc
|
||||
size_t server_certs_len;
|
||||
uint8_t client_certs[TLS_MAX_CERTIFICATES_SIZE];
|
||||
size_t client_certs_len;
|
||||
uint8_t ca_certs[2048];
|
||||
size_t ca_certs_len;
|
||||
|
||||
|
||||
// 己方的证书链,指向TLS_CTX中的cert_chains
|
||||
const uint8_t *cert_chain;
|
||||
size_t cert_chain_len;
|
||||
int cert_chain_idx; // 这样就指向了CTX中的密钥
|
||||
|
||||
int sig_alg;
|
||||
|
||||
|
||||
uint8_t peer_cert_chain[TLS_MAX_CERTIFICATES_SIZE];
|
||||
size_t peer_cert_chain_len;
|
||||
|
||||
|
||||
X509_KEY sign_key;
|
||||
X509_KEY kenc_key; // 应该作为服务器的SM2加密
|
||||
@@ -920,8 +989,12 @@ typedef struct {
|
||||
int verify_result;
|
||||
|
||||
|
||||
// transcript hash
|
||||
SM3_CTX sm3_ctx;
|
||||
DIGEST_CTX dgst_ctx;
|
||||
|
||||
|
||||
// secrets
|
||||
SM3_HMAC_CTX client_write_mac_ctx;
|
||||
SM3_HMAC_CTX server_write_mac_ctx;
|
||||
SM4_KEY client_write_enc_key;
|
||||
@@ -934,77 +1007,6 @@ typedef struct {
|
||||
BLOCK_CIPHER_KEY client_write_key;
|
||||
BLOCK_CIPHER_KEY server_write_key;
|
||||
|
||||
int quiet;
|
||||
|
||||
|
||||
// handshake state for state machine
|
||||
int state;
|
||||
|
||||
|
||||
|
||||
SM3_CTX sm3_ctx;
|
||||
|
||||
DIGEST_CTX dgst_ctx;
|
||||
|
||||
|
||||
SM2_SIGN_CTX sign_ctx;
|
||||
TLS_CLIENT_VERIFY_CTX client_verify_ctx;
|
||||
uint8_t client_random[32];
|
||||
uint8_t server_random[32];
|
||||
uint8_t server_exts[512]; // TODO
|
||||
size_t server_exts_len;
|
||||
|
||||
|
||||
// 在TLS中,密钥交换的密钥是不在证书中的?
|
||||
uint16_t sig_alg;
|
||||
|
||||
// TLS中客户端和服务器端可以使用不同的签名算法,但是最好是一致的
|
||||
// 这个算法是由cipher_suite和服务器证书决定的(其中是服务器AUTH算法)
|
||||
// 但是客户端的签名算法不是由cipher_suite决定
|
||||
uint16_t server_sig_alg;
|
||||
|
||||
|
||||
uint16_t ecdh_named_curve;
|
||||
|
||||
X509_KEY ecdh_keys[2];
|
||||
|
||||
|
||||
size_t ecdh_keys_cnt;
|
||||
|
||||
X509_KEY ecdh_key;
|
||||
|
||||
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;
|
||||
SECP256R1_KEY p256_ecdhe;
|
||||
uint8_t peer_sm2_ecdhe[65];
|
||||
uint8_t peer_p256_ecdhe[65];
|
||||
|
||||
|
||||
// 服务器在接收到ClientHello中,计算出双方算法的交集,并保存
|
||||
// 服务器在发送CertificateRequest的时候,需要把这个集合发送给客户端
|
||||
// 客户端在使用的时候实际上使用CTX中的集合发送
|
||||
int signature_algorithms[2];
|
||||
size_t signature_algorithms_cnt;
|
||||
|
||||
|
||||
|
||||
int verify_depth; // 这个可能没有被设置
|
||||
|
||||
const TLS_CTX *ctx;
|
||||
|
||||
uint8_t pre_master_secret[48]; // 是否可以重用master_secret作为pre_master_secret呢?
|
||||
uint8_t master_secret[48];
|
||||
uint8_t resumption_master_secret[48];
|
||||
@@ -1019,51 +1021,92 @@ typedef struct {
|
||||
uint8_t server_application_traffic_secret[32];
|
||||
|
||||
|
||||
SM2_SIGN_CTX sign_ctx;
|
||||
TLS_CLIENT_VERIFY_CTX client_verify_ctx;
|
||||
|
||||
|
||||
|
||||
// 所有这些命名为ecdh的都需要替换掉
|
||||
uint16_t ecdh_named_curve;
|
||||
X509_KEY ecdh_keys[2];
|
||||
size_t ecdh_keys_cnt;
|
||||
X509_KEY ecdh_key;
|
||||
uint8_t peer_ecdh_point[65];
|
||||
size_t peer_ecdh_point_len;
|
||||
|
||||
|
||||
// key_share
|
||||
int key_share;
|
||||
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;
|
||||
|
||||
|
||||
|
||||
// CertificateRequest.signature_algorithms =
|
||||
// common(ClientHello.signature_algorithms, ctx->signature_algorithms)
|
||||
int signature_algorithms[2];
|
||||
size_t signature_algorithms_cnt;
|
||||
|
||||
|
||||
// handshake messages
|
||||
int hello_retry_request;
|
||||
int certificate_request;
|
||||
int new_session_ticket;
|
||||
|
||||
|
||||
int pre_shared_key_enabled;
|
||||
|
||||
// extensions
|
||||
|
||||
// 客户端和服务器端都可以直接指定若干psk
|
||||
// 服务器端也可能通过解密客户端发出
|
||||
// 0. server_name
|
||||
uint8_t server_name[256];
|
||||
size_t server_name_len;
|
||||
|
||||
// 5. status_request
|
||||
int status_request;
|
||||
|
||||
// 18. signed_certificate_timestamp
|
||||
int signed_certificate_timestamp;
|
||||
|
||||
// 41. pre_shared_key
|
||||
int pre_shared_key;
|
||||
const DIGEST *psk_digests[8];
|
||||
size_t psk_digests_cnt;
|
||||
uint8_t psk_identities[512];
|
||||
size_t psk_identities_len;
|
||||
uint8_t psk_keys[32 * 8];
|
||||
size_t psk_keys_len;
|
||||
|
||||
uint8_t psk[32];
|
||||
size_t psk_len;
|
||||
|
||||
const uint8_t *psk_identity;
|
||||
size_t psk_identity_len;
|
||||
|
||||
|
||||
|
||||
// psk_key_exchange_modes
|
||||
int psk_ke;
|
||||
int psk_dhe_ke;
|
||||
|
||||
int new_session_ticket_cnt;
|
||||
|
||||
|
||||
uint8_t psk[32]; // 这应该改为一个指针
|
||||
size_t psk_len;
|
||||
int selected_psk_identity;
|
||||
|
||||
|
||||
// session_ticket
|
||||
const char *session_in;
|
||||
const char *session_out;
|
||||
|
||||
int client_certificate_verify; // TLS1.2 TLCP需要这个
|
||||
|
||||
uint8_t cookie[512];
|
||||
size_t cookielen;
|
||||
|
||||
int early_data_enabled;
|
||||
uint8_t early_data[8192];
|
||||
size_t early_data_len;
|
||||
|
||||
// 42. early_data
|
||||
int early_data;
|
||||
size_t max_early_data_size;
|
||||
uint8_t early_data_buf[8192];
|
||||
size_t early_data_len;
|
||||
|
||||
// 44. cookie
|
||||
uint8_t cookie_buf[256];
|
||||
size_t cookie_len;
|
||||
|
||||
|
||||
|
||||
const char *session_in;
|
||||
const char *session_out;
|
||||
} TLS_CONNECT;
|
||||
|
||||
|
||||
@@ -1113,7 +1156,7 @@ void tls_clean_record(TLS_CONNECT *conn);
|
||||
|
||||
int tls_print_record(FILE *fp, int fmt, int ind, const char *label, TLS_CONNECT *conn);
|
||||
|
||||
int tls_init(TLS_CONNECT *conn, const TLS_CTX *ctx);
|
||||
int tls_init(TLS_CONNECT *conn, TLS_CTX *ctx);
|
||||
int tls_set_hostname(TLS_CONNECT *conn, const char *hostname);
|
||||
int tls_set_socket(TLS_CONNECT *conn, tls_socket_t sock);
|
||||
|
||||
@@ -1260,6 +1303,7 @@ EarlyData (0-RTT)
|
||||
*/
|
||||
int tls13_set_early_data(TLS_CONNECT *conn, const uint8_t *data, size_t datalen);
|
||||
|
||||
int tls13_ctx_set_max_key_exchanges(TLS_CTX *ctx, size_t cnt);
|
||||
int tls13_ctx_set_max_early_data_size(TLS_CTX *ctx, size_t max_early_data_size);
|
||||
int tls13_set_max_early_data_size(TLS_CONNECT *conn, size_t max_early_data_size);
|
||||
|
||||
@@ -1277,7 +1321,7 @@ PSK 模式
|
||||
*/
|
||||
|
||||
// enable PSK, enable ClientHello.exts.pre_shared_key
|
||||
int tls13_set_session_infile(TLS_CONNECT *conn, const char *file);
|
||||
//int tls13_set_session_infile(TLS_CONNECT *conn, const char *file);
|
||||
|
||||
int tls13_set_session_resumption(TLS_CONNECT *conn, const char *session_file);
|
||||
|
||||
@@ -1294,7 +1338,6 @@ int tls13_set_session_resumption(TLS_CONNECT *conn, const char *session_file);
|
||||
*/
|
||||
|
||||
|
||||
#define TLS_NEW_SESSION_TICKET_MAX_COUNT 5
|
||||
|
||||
|
||||
|
||||
@@ -1316,16 +1359,23 @@ enum {
|
||||
TLS_psk_preserved_max = 255,
|
||||
};
|
||||
|
||||
|
||||
#define TLS_KE_CERT_DHE 1
|
||||
#define TLS_KE_PSK_DHE 2
|
||||
#define TLS_KE_PSK 4
|
||||
|
||||
/*
|
||||
enum {
|
||||
TLS_psk_mode_null = 0,
|
||||
TLS_psk_mode_ke = 1,
|
||||
TLS_psk_mode_dhe_ke = 2,
|
||||
TLS_psk_mode_both = 3,
|
||||
TLS_psk_key_exchange_modes_none = 0,
|
||||
TLS_psk_key_exchange_modes_psk_only = 1,
|
||||
TLS_psk_key_exchange_modes_psk_dhe = 2,
|
||||
TLS_psk_key_exchange_modes_both = 3,
|
||||
};
|
||||
*/
|
||||
|
||||
const char *tls13_psk_key_exchange_mode_name(int mode);
|
||||
int tls13_psk_key_exchange_modes_ext_to_bytes(int ke, int dhe_ke, uint8_t **out, size_t *outlen);
|
||||
int tls13_psk_key_exchange_modes_from_bytes(int *ke, int *dhe_ke, const uint8_t *ext_data, size_t ext_datalen);
|
||||
int tls13_psk_key_exchange_modes_ext_to_bytes(int modes, uint8_t **out, size_t *outlen);
|
||||
int tls13_psk_key_exchange_modes_from_bytes(int *modes, const uint8_t *ext_data, size_t ext_datalen);
|
||||
|
||||
int tls13_enable_pre_shared_key(TLS_CONNECT *conn, int enable);
|
||||
int tls13_enable_early_data(TLS_CONNECT *conn, int enable);
|
||||
@@ -1337,11 +1387,90 @@ int tls13_add_pre_shared_key_from_file(TLS_CONNECT *conn, const char *file);
|
||||
|
||||
int tls13_set_psk_key_exchange_modes(TLS_CONNECT *conn, int psk_ke, int psk_dhe_ke);
|
||||
|
||||
|
||||
int tls13_verify_psk_binder(const DIGEST *digest,
|
||||
const uint8_t *pre_shared_key, size_t pre_shared_key_len,
|
||||
const DIGEST_CTX *truncated_client_hello_dgst_ctx,
|
||||
const uint8_t *binder, size_t binderlen);
|
||||
|
||||
int tls_ctx_set_supported_groups(TLS_CTX *ctx, const int *groups, size_t groups_cnt);
|
||||
int tls13_set_psk_key_exchange_modes(TLS_CONNECT *conn, int psk_ke, int psk_dhe_ke);
|
||||
|
||||
int tls13_psk_key_exchange_modes_print(FILE *fp, int fmt, int ind, const uint8_t *ext_data, size_t ext_datalen);
|
||||
|
||||
|
||||
enum {
|
||||
TLS_name_type_host_name = 0,
|
||||
TLS_name_type_preserved_max = 255,
|
||||
};
|
||||
|
||||
|
||||
#define tls_ext_data(ext) ((ext) + 4)
|
||||
|
||||
int tls_ext_to_bytes(int ext_type, const uint8_t *ext_data, size_t ext_datalen,
|
||||
uint8_t **out, size_t *outlen);
|
||||
|
||||
int tls_server_name_ext_to_bytes(const uint8_t *host_name, size_t host_name_len, uint8_t **out, size_t *outlen);
|
||||
int tls_server_name_from_bytes(const uint8_t **host_name, size_t *host_name_len,
|
||||
const uint8_t *ext_data, size_t ext_datalen);
|
||||
int tls_server_name_print(FILE *fp, int fmt, int ind, const uint8_t *ext_data, size_t ext_datalen);
|
||||
|
||||
int tls_set_server_name(TLS_CONNECT *conn, const uint8_t *host_name, size_t host_name_len);
|
||||
|
||||
int tls_status_request_ext_to_bytes(const uint8_t *ocsp_response, size_t ocsp_response_len,
|
||||
uint8_t **out, size_t *outlen);
|
||||
|
||||
|
||||
enum {
|
||||
TLS_certificate_status_type_ocsp = 1,
|
||||
};
|
||||
|
||||
int tls_ocsp_status_request_to_bytes(
|
||||
const uint8_t *responder_id_list, size_t responder_id_list_len,
|
||||
const uint8_t *request_exts, size_t request_exts_len,
|
||||
uint8_t **out, size_t *outlen);
|
||||
int tls_ocsp_status_request_from_bytes(
|
||||
const uint8_t **responder_id_list, size_t *responder_id_list_len,
|
||||
const uint8_t **request_exts, size_t *request_exts_len,
|
||||
const uint8_t **in, size_t *inlen);
|
||||
int tls_ocsp_status_request_print(FILE *fp, int fmt, int ind,
|
||||
const char *label, const uint8_t *ext_data, size_t ext_datalen);
|
||||
|
||||
int tls_client_status_request_ext_to_bytes(int status_type,
|
||||
const uint8_t *responder_id_list, size_t responder_id_list_len,
|
||||
const uint8_t *request_exts, size_t request_exts_len,
|
||||
uint8_t **out, size_t *outlen);
|
||||
int tls_client_status_request_from_bytes(int *status_type,
|
||||
const uint8_t **responder_id_list, size_t *responder_id_list_len,
|
||||
const uint8_t **request_exts, size_t *request_exts_len,
|
||||
const uint8_t *ext_data, size_t ext_datalen);
|
||||
int tls_client_status_request_print(FILE *fp, int fmt, int ind,
|
||||
const uint8_t *ext_data, size_t ext_datalen);
|
||||
|
||||
int tls_server_status_request_ext_to_bytes(const uint8_t *ocsp_response, size_t ocsp_response_len,
|
||||
uint8_t **out, size_t *outlen);
|
||||
int tls_server_status_request_from_bytes(const uint8_t **ocsp_response, size_t *ocsp_response_len,
|
||||
const uint8_t *ext_data, size_t ext_datalen);
|
||||
int tls_server_status_request_print(FILE *fp, int fmt, int ind,
|
||||
const uint8_t *ext_data, size_t ext_datalen);
|
||||
|
||||
|
||||
int tls_signed_certificate_timestamp_entry_to_bytes(const uint8_t key_id[32],
|
||||
uint64_t timestamp, const uint8_t *signature, size_t signature_len,
|
||||
uint8_t **out, size_t *outlen);
|
||||
int tls_signed_certificate_timestamp_entry_from_bytes(const uint8_t **key_id,
|
||||
uint64_t *timestamp, const uint8_t **signature, size_t *signature_len,
|
||||
const uint8_t **in, size_t *inlen);
|
||||
int tls_signed_certificate_timestamp_ext_to_bytes(const uint8_t *sct_list, size_t sct_list_len,
|
||||
uint8_t **out, size_t *outlen);
|
||||
int tls_signed_certificate_timestamp_from_bytes(const uint8_t **sct_list, size_t *sct_list_len,
|
||||
const uint8_t **in, size_t *inlen);
|
||||
int tls_signed_certificate_timestamp_print(FILE *fp, int fmt, int ind,
|
||||
const char *label, const uint8_t *d, size_t dlen);
|
||||
|
||||
int ocsp_response_verify(const uint8_t *ocsp_response, size_t ocsp_response_len,
|
||||
const uint8_t *ca_certs, size_t ca_certs_len);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -338,6 +338,7 @@ int x509_cert_get_subject(const uint8_t *a, size_t alen, const uint8_t **subj, s
|
||||
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_cert_get_subject_alt_name_dns_name(const uint8_t *a, size_t alen, const uint8_t **dns_name, size_t *dns_name_len);
|
||||
|
||||
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);
|
||||
|
||||
@@ -142,8 +142,11 @@ typedef enum {
|
||||
|
||||
int x509_general_name_to_der(int choice, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen);
|
||||
int x509_general_name_from_der(int *choice, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen);
|
||||
int x509_general_names_get_first(const uint8_t *gns, size_t gns_len, const uint8_t **ptr, int choice, const uint8_t **d, size_t *dlen);
|
||||
int x509_general_names_get_next(const uint8_t *gns, size_t gns_len, const uint8_t **ptr, int choice, const uint8_t **d, size_t *dlen);
|
||||
int x509_general_name_print(FILE *fp, int fmt, int ind, const char *label, int choice, const uint8_t *d, size_t dlen);
|
||||
|
||||
|
||||
/*
|
||||
GeneralNames ::= SEQUENCE OF GeneralName
|
||||
*/
|
||||
|
||||
@@ -137,7 +137,8 @@ int x509_private_key_info_decrypt_from_der(X509_KEY *x509_key,
|
||||
int x509_private_key_info_encrypt_to_pem(const X509_KEY *key, const char *pass, FILE *fp);
|
||||
int x509_private_key_info_decrypt_from_pem(X509_KEY *key, const uint8_t **attrs, size_t *attrslen, const char *pass, FILE *fp);
|
||||
int x509_private_key_from_file(X509_KEY *key, int algor, const char *pass, FILE *fp);
|
||||
|
||||
int x509_private_keys_from_file(X509_KEY *keys, size_t *keys_cnt, size_t max_cnt,
|
||||
int algor, const char *pass, FILE *fp);
|
||||
|
||||
|
||||
// SM2_SIGNATURE_MAX_SIZE = 72
|
||||
|
||||
@@ -150,6 +150,7 @@ int tlcp_server_key_exchange_pke_print(FILE *fp, const uint8_t *data, size_t dat
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int _tlcp_do_connect(TLS_CONNECT *conn)
|
||||
{
|
||||
int ret = -1;
|
||||
@@ -1056,6 +1057,7 @@ end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
SM9_SM4_CBC_SM3
|
||||
|
||||
|
||||
488
src/tls.c
488
src/tls.c
@@ -18,6 +18,7 @@
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/x509.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/endian.h>
|
||||
#include <gmssl/mem.h>
|
||||
#include <gmssl/sm2.h>
|
||||
#include <gmssl/sm3.h>
|
||||
@@ -64,6 +65,14 @@ void tls_uint32_to_bytes(uint32_t a, uint8_t **out, size_t *outlen)
|
||||
(*outlen) += 4;
|
||||
}
|
||||
|
||||
void tls_uint64_to_bytes(uint64_t a, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
if (out && *out) {
|
||||
PUTU64(*out, a);
|
||||
}
|
||||
(*outlen) += 8;
|
||||
}
|
||||
|
||||
void tls_array_to_bytes(const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen)
|
||||
{
|
||||
if (out && *out) {
|
||||
@@ -156,6 +165,18 @@ int tls_uint32_from_bytes(uint32_t *a, const uint8_t **in, size_t *inlen)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_uint64_from_bytes(uint64_t *a, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
if (*inlen < 8) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*a = GETU64(*in);
|
||||
*in += 8;
|
||||
*inlen -= 8;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_array_from_bytes(const uint8_t **data, size_t datalen, const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
if (*inlen < datalen) {
|
||||
@@ -1466,11 +1487,11 @@ int tls_record_get_application_data(uint8_t *record,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_type_is_in_list(int cipher, const int *list, size_t list_count)
|
||||
int tls_type_is_in_list(int type, const int *list, size_t list_count)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < list_count; i++) {
|
||||
if (cipher == list[i]) {
|
||||
if (type == list[i]) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -2162,10 +2183,78 @@ void tls_ctx_cleanup(TLS_CTX *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
int tls_ctx_print(FILE *fp, int fmt, int ind, const char *label, const TLS_CTX *ctx)
|
||||
{
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int tls_ctx_init(TLS_CTX *ctx, int protocol, int is_client)
|
||||
{
|
||||
const int supported_versions[] = {
|
||||
TLS_protocol_tls13,
|
||||
TLS_protocol_tls12,
|
||||
TLS_protocol_tlcp,
|
||||
};
|
||||
|
||||
if (!ctx) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
|
||||
// protocol
|
||||
switch (protocol) {
|
||||
case TLS_protocol_tlcp:
|
||||
case TLS_protocol_tls12:
|
||||
case TLS_protocol_tls13:
|
||||
ctx->protocol = protocol;
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->is_client = is_client ? 1 : 0;
|
||||
|
||||
|
||||
// supported_versions
|
||||
memcpy(ctx->supported_versions, supported_versions, sizeof(supported_versions));
|
||||
ctx->supported_versions_cnt = sizeof(supported_versions)/sizeof(supported_versions[0]);
|
||||
|
||||
|
||||
// key_exchange_modes
|
||||
ctx->key_exchange_modes = TLS_KE_CERT_DHE;
|
||||
|
||||
|
||||
ctx->verify_depth = 5;
|
||||
|
||||
|
||||
// key_share
|
||||
ctx->key_exchanges_cnt = 2;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_ctx_set_supported_versions(TLS_CTX *ctx, const int *versions, size_t versions_cnt)
|
||||
{
|
||||
size_t i;
|
||||
@@ -2178,6 +2267,7 @@ int tls_ctx_set_supported_versions(TLS_CTX *ctx, const int *versions, size_t ver
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < versions_cnt; i++) {
|
||||
switch (versions[i]) {
|
||||
case TLS_protocol_tls13:
|
||||
@@ -2191,130 +2281,10 @@ int tls_ctx_set_supported_versions(TLS_CTX *ctx, const int *versions, size_t ver
|
||||
ctx->supported_versions[i] = versions[i];
|
||||
}
|
||||
ctx->supported_versions_cnt = versions_cnt;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_ctx_set_supported_groups(TLS_CTX *ctx, const int *groups, size_t groups_cnt)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!ctx || !groups || !groups_cnt) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (groups_cnt > sizeof(ctx->supported_groups)/sizeof(ctx->supported_groups[0])) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < groups_cnt; i++) {
|
||||
switch (groups[i]) {
|
||||
case TLS_curve_sm2p256v1:
|
||||
case TLS_curve_secp256r1:
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->supported_groups[i] = groups[i];
|
||||
}
|
||||
ctx->supported_groups_cnt = groups_cnt;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_ctx_set_signature_algorithms(TLS_CTX *ctx, const int *sig_algs, size_t sig_algs_cnt)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!ctx || !sig_algs || !sig_algs_cnt) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sig_algs_cnt > sizeof(ctx->signature_algorithms)/sizeof(ctx->signature_algorithms[0])) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < sig_algs_cnt; i++) {
|
||||
switch (sig_algs[i]) {
|
||||
case TLS_sig_sm2sig_sm3:
|
||||
case TLS_sig_ecdsa_secp256r1_sha256:
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->signature_algorithms[i] = sig_algs[i];
|
||||
}
|
||||
ctx->signature_algorithms_cnt = sig_algs_cnt;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int tls_ctx_init(TLS_CTX *ctx, int protocol, int is_client)
|
||||
{
|
||||
const int supported_versions[] = {
|
||||
TLS_protocol_tls13,
|
||||
TLS_protocol_tls12,
|
||||
TLS_protocol_tlcp,
|
||||
};
|
||||
size_t supported_versions_cnt = sizeof(supported_versions)/sizeof(supported_versions[0]);
|
||||
|
||||
const int supported_groups[] = {
|
||||
TLS_curve_sm2p256v1,
|
||||
TLS_curve_secp256r1,
|
||||
};
|
||||
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,
|
||||
};
|
||||
size_t signature_algorithms_cnt = sizeof(signature_algorithms)/sizeof(signature_algorithms[0]);
|
||||
|
||||
|
||||
if (!ctx) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
switch (protocol) {
|
||||
case TLS_protocol_tlcp:
|
||||
case TLS_protocol_tls12:
|
||||
case TLS_protocol_tls13:
|
||||
ctx->protocol = protocol;
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->is_client = is_client ? 1 : 0;
|
||||
|
||||
|
||||
if (tls_ctx_set_supported_versions(ctx, supported_versions, supported_versions_cnt) != 1
|
||||
|| tls_ctx_set_supported_groups(ctx, supported_groups, supported_groups_cnt) != 1
|
||||
|| tls_ctx_set_signature_algorithms(ctx, signature_algorithms, signature_algorithms_cnt) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// test HelloRetryRequest
|
||||
if (!is_client) {
|
||||
tls_ctx_set_supported_groups(ctx, supported_groups + 1, supported_groups_cnt - 1);
|
||||
}
|
||||
|
||||
|
||||
ctx->verify_depth = 5;
|
||||
|
||||
|
||||
// TODO: 需要通过函数或者其他设置来启用这个开关
|
||||
ctx->pre_shared_key_enabled = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int tls_ctx_set_cipher_suites(TLS_CTX *ctx, const int *cipher_suites, size_t cipher_suites_cnt)
|
||||
{
|
||||
size_t i;
|
||||
@@ -2323,7 +2293,7 @@ int tls_ctx_set_cipher_suites(TLS_CTX *ctx, const int *cipher_suites, size_t cip
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (cipher_suites_cnt < 1 || cipher_suites_cnt > TLS_MAX_CIPHER_SUITES_COUNT) {
|
||||
if (cipher_suites_cnt > sizeof(ctx->cipher_suites)/sizeof(ctx->cipher_suites[0])) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -2333,18 +2303,30 @@ int tls_ctx_set_cipher_suites(TLS_CTX *ctx, const int *cipher_suites, size_t cip
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < cipher_suites_cnt; i++) {
|
||||
if (!tls_cipher_suite_support_protocol(cipher_suites[i], ctx->protocol)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->cipher_suites[i] = cipher_suites[i];
|
||||
}
|
||||
ctx->cipher_suites_cnt = cipher_suites_cnt;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_ctx_set_key_exchange_modes(TLS_CTX *ctx, int modes)
|
||||
{
|
||||
if (!ctx) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (modes & ~(TLS_KE_CERT_DHE|TLS_KE_PSK_DHE|TLS_KE_PSK)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->key_exchange_modes = modes;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 这个函数不是很好,直接提供的是一个文件名
|
||||
int tls_ctx_set_ca_certificates(TLS_CTX *ctx, const char *cacertsfile, int depth)
|
||||
{
|
||||
if (!ctx || !cacertsfile) {
|
||||
@@ -2377,7 +2359,89 @@ int tls_ctx_set_ca_certificates(TLS_CTX *ctx, const char *cacertsfile, int depth
|
||||
}
|
||||
|
||||
|
||||
// 这个函数要独立出去
|
||||
// 这个函数需要设置一个默认的证书链
|
||||
// 这个函数实际上是有问题的,没有给这个证书链提供status_request和sct_list
|
||||
// cert_chain的格式到底是什么呢?
|
||||
// 是单独的证书链,还是也包含扩展呢?
|
||||
int tls_ctx_add_certificate_chain_and_key(TLS_CTX *ctx, const char *chainfile,
|
||||
const char *keyfile, const char *keypass)
|
||||
{
|
||||
uint8_t *cert_chain;
|
||||
size_t cert_chain_len;
|
||||
FILE *certfp = NULL;
|
||||
const uint8_t *cert;
|
||||
size_t certlen;
|
||||
X509_KEY public_key;
|
||||
FILE *keyfp = NULL;
|
||||
|
||||
if (!ctx || !chainfile || !keyfile || !keypass) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// no space in ctx->cert_chains[]
|
||||
if (sizeof(ctx->cert_chains) <= ctx->cert_chains_len + tls_uint24_size()) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
// no space in ctx->x509_keys[]
|
||||
if (sizeof(ctx->x509_keys)/sizeof(ctx->x509_keys[0]) <= ctx->x509_keys_cnt) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(certfp = fopen(chainfile, "r"))) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// read and save cert_chain as uint24array
|
||||
cert_chain = ctx->cert_chains + ctx->cert_chains_len;
|
||||
if (x509_certs_from_pem(cert_chain + tls_uint24_size(), &cert_chain_len,
|
||||
sizeof(ctx->cert_chains) - ctx->cert_chains_len - tls_uint24_size(),
|
||||
certfp) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
tls_uint24_to_bytes(cert_chain_len, &cert_chain, &cert_chain_len);
|
||||
ctx->cert_chains_len += cert_chain_len;
|
||||
|
||||
cert_chain_len -= tls_uint24_size();
|
||||
if (x509_certs_get_cert_by_index(cert_chain, cert_chain_len, 0, &cert, &certlen) != 1
|
||||
|| x509_cert_get_subject_public_key(cert, certlen, &public_key) != 1) {
|
||||
fclose(certfp);
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (public_key.algor == OID_ec_public_key) {
|
||||
if (!(keyfp = fopen(keyfile, "r"))) {
|
||||
fclose(certfp);
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (!(keyfp = fopen(keyfile, "rb+"))) {
|
||||
fclose(certfp);
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// read and save at most two keys as uint16array
|
||||
if (x509_private_key_from_file(&ctx->x509_keys[ctx->x509_keys_cnt], public_key.algor, keypass, keyfp) != 1) {
|
||||
fclose(certfp);
|
||||
fclose(keyfp);
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->x509_keys_cnt++;
|
||||
|
||||
fclose(certfp);
|
||||
fclose(keyfp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 保留这个函数,相当于是对证书链的初始化
|
||||
int tls_ctx_set_certificate_and_key(TLS_CTX *ctx, const char *chainfile,
|
||||
const char *keyfile, const char *keypass)
|
||||
{
|
||||
@@ -2428,10 +2492,6 @@ int tls_ctx_set_certificate_and_key(TLS_CTX *ctx, const char *chainfile,
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_public_key_equ(&ctx->signkey, &public_key) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
ctx->certs = certs;
|
||||
ctx->certslen = certslen;
|
||||
@@ -2444,7 +2504,6 @@ end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int tls_ctx_set_tlcp_server_certificate_and_keys(TLS_CTX *ctx, const char *chainfile,
|
||||
const char *signkeyfile, const char *signkeypass,
|
||||
const char *kenckeyfile, const char *kenckeypass)
|
||||
@@ -2533,71 +2592,88 @@ end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
服务器的控制开关
|
||||
int tls_ctx_set_supported_groups(TLS_CTX *ctx, const int *groups, size_t groups_cnt)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
* 是否验证客户端,这可能依赖很多条件
|
||||
服务器至少需要提供CA证书
|
||||
状态certificate_request = on
|
||||
if (!ctx || !groups || !groups_cnt) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (groups_cnt > sizeof(ctx->supported_groups)/sizeof(ctx->supported_groups[0])) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
* 是否发送NewSessionTicket
|
||||
这和是否采用PSK模式实际上是没有关系的
|
||||
本次启动服务器可能不支持PSK模式,但是仍然可以提供session_ticket
|
||||
服务器需要设置session的加密密钥
|
||||
for (i = 0; i < groups_cnt; i++) {
|
||||
switch (groups[i]) {
|
||||
case TLS_curve_sm2p256v1:
|
||||
case TLS_curve_secp256r1:
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->supported_groups[i] = groups[i];
|
||||
}
|
||||
ctx->supported_groups_cnt = groups_cnt;
|
||||
|
||||
是否要设置可以发送ticket的次数
|
||||
|
||||
以及ticket有关的信息(有效期之类)
|
||||
|
||||
自动化设置max_early_data_size
|
||||
|
||||
* 是否支持pre_shared_key (1-RTT)
|
||||
TLS 1.3有好几种PSK的模式,比如PSK之后是否进行ECDH
|
||||
服务器需要设置session的加密密钥
|
||||
|
||||
// ok
|
||||
* 是否支持early_data
|
||||
这是一个独立的开关
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
客户端的控制开关
|
||||
|
||||
* 初始设置客户端的证书(这和服务器无关)
|
||||
int tls_ctx_set_signature_algorithms(TLS_CTX *ctx, const int *sig_algs, size_t sig_algs_cnt)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
* 是否发送pre_shared_key
|
||||
if (!ctx || !sig_algs || !sig_algs_cnt) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (sig_algs_cnt > sizeof(ctx->signature_algorithms)/sizeof(ctx->signature_algorithms[0])) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
需要提供session_ticket的文件,载入信息
|
||||
并且需要开关
|
||||
for (i = 0; i < sig_algs_cnt; i++) {
|
||||
switch (sig_algs[i]) {
|
||||
case TLS_sig_sm2sig_sm3:
|
||||
case TLS_sig_ecdsa_secp256r1_sha256:
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ctx->signature_algorithms[i] = sig_algs[i];
|
||||
}
|
||||
ctx->signature_algorithms_cnt = sig_algs_cnt;
|
||||
|
||||
* 是否发送early_data
|
||||
return 1;
|
||||
}
|
||||
|
||||
是否已经准备了session
|
||||
是否已经准备了early_data数据(这个无所谓,只要指定了这个状态,有没有数据都发送一个early_data报文)
|
||||
如果有max_early_data_size,要判断一下大小
|
||||
int tls13_ctx_set_client_hello_key_exchanges_cnt(TLS_CTX *ctx, size_t cnt)
|
||||
{
|
||||
if (!ctx) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (cnt > sizeof(((TLS_CONNECT *)NULL)->key_exchanges)/sizeof(((TLS_CONNECT *)NULL)->key_exchanges[0])) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
我们可以延迟到开始发送early_data的时候再检查
|
||||
ctx->key_exchanges_cnt = cnt;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
服务器是否支持PSK,客户端是否发送PSK实际上是两个独立的功能。
|
||||
|
||||
如果我们打开服务器支持PSK的开关,但是没有设置session_ticket的密钥,那么就会出问题
|
||||
我们还是延迟检查比较好
|
||||
|
||||
因为PSK对于服务器来说是一个隐含的,不是主动的,服务器是被动的
|
||||
如果服务器准备好了session_ticket_key,那么就意味着允许
|
||||
|
||||
|
||||
对于客户端来说,如果要在ClientHello中提供pre_shared_key,那么就必须要提供session_infile
|
||||
或者说,set_session_in 就说明我们一定是要发送pre_shared_key的,并且就来自于session_in
|
||||
但是如果设置了session_out ,那么意味着我们会保存信息,但是不一定会发送psk,这两个是独立的
|
||||
|
||||
因此对于客户端来说,pre_shared_key的状态是否有必要的
|
||||
|
||||
|
||||
*/
|
||||
|
||||
int tls_init(TLS_CONNECT *conn, const TLS_CTX *ctx)
|
||||
int tls_init(TLS_CONNECT *conn, TLS_CTX *ctx)
|
||||
{
|
||||
size_t i;
|
||||
memset(conn, 0, sizeof(*conn));
|
||||
@@ -2607,10 +2683,12 @@ int tls_init(TLS_CONNECT *conn, const TLS_CTX *ctx)
|
||||
|
||||
conn->protocol = ctx->protocol;
|
||||
|
||||
/*
|
||||
for (i = 0; i < ctx->cipher_suites_cnt; i++) {
|
||||
conn->cipher_suites[i] = ctx->cipher_suites[i];
|
||||
}
|
||||
conn->cipher_suites_cnt = ctx->cipher_suites_cnt;
|
||||
*/
|
||||
|
||||
|
||||
if (ctx->certslen > TLS_MAX_CERTIFICATES_SIZE) {
|
||||
@@ -2625,12 +2703,15 @@ int tls_init(TLS_CONNECT *conn, const TLS_CTX *ctx)
|
||||
conn->server_certs_len = ctx->certslen;
|
||||
}
|
||||
|
||||
/*
|
||||
if (ctx->cacertslen > TLS_MAX_CERTIFICATES_SIZE) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memcpy(conn->ca_certs, ctx->cacerts, ctx->cacertslen);
|
||||
conn->ca_certs_len = ctx->cacertslen;
|
||||
*/
|
||||
|
||||
|
||||
conn->sign_key = ctx->signkey;
|
||||
conn->kenc_key = ctx->kenckey;
|
||||
@@ -2638,23 +2719,22 @@ int tls_init(TLS_CONNECT *conn, const TLS_CTX *ctx)
|
||||
conn->quiet = ctx->quiet;
|
||||
|
||||
|
||||
conn->verify_depth = ctx->verify_depth;
|
||||
|
||||
conn->ctx = ctx;
|
||||
|
||||
conn->key_exchanges_cnt = 2;
|
||||
conn->key_exchanges_cnt = ctx->key_exchanges_cnt;
|
||||
|
||||
|
||||
conn->new_session_ticket = ctx->new_session_ticket;
|
||||
|
||||
conn->pre_shared_key_enabled = ctx->pre_shared_key_enabled;
|
||||
|
||||
// 仅仅用于测试0-RTT
|
||||
/*
|
||||
conn->early_data_enabled = 1;
|
||||
tls13_set_early_data(conn, (uint8_t *)"Early data", strlen("Early data"));
|
||||
*/
|
||||
conn->key_exchange_modes = ctx->key_exchange_modes;
|
||||
|
||||
tls13_set_max_early_data_size(conn, ctx->max_early_data_size);
|
||||
|
||||
|
||||
// early_data
|
||||
conn->early_data = ctx->early_data;
|
||||
conn->max_early_data_size = ctx->max_early_data_size;
|
||||
|
||||
|
||||
return 1;
|
||||
@@ -2665,6 +2745,7 @@ void tls_cleanup(TLS_CONNECT *conn)
|
||||
gmssl_secure_clear(conn, sizeof(TLS_CONNECT));
|
||||
}
|
||||
|
||||
/*
|
||||
int tls_set_hostname(TLS_CONNECT *conn, const char *hostname)
|
||||
{
|
||||
if (strlen(hostname) > 255) {
|
||||
@@ -2674,6 +2755,7 @@ int tls_set_hostname(TLS_CONNECT *conn, const char *hostname)
|
||||
conn->hostname = hostname;
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
|
||||
int tls_set_socket(TLS_CONNECT *conn, tls_socket_t sock)
|
||||
{
|
||||
@@ -2724,8 +2806,6 @@ int tls_get_verify_result(TLS_CONNECT *conn, int *result)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int tls_uint16array_from_file(uint8_t *arr, size_t *arrlen, size_t maxlen, FILE *fp)
|
||||
{
|
||||
uint16_t datalen;
|
||||
@@ -2764,5 +2844,23 @@ int tls_uint16array_from_file(uint8_t *arr, size_t *arrlen, size_t maxlen, FILE
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int tls_set_server_name(TLS_CONNECT *conn, const uint8_t *host_name, size_t host_name_len)
|
||||
{
|
||||
if (!conn || !host_name || !host_name_len) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (!conn->is_client) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (host_name_len >= sizeof(conn->server_name)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memcpy(conn->server_name, host_name, host_name_len);
|
||||
conn->server_name[host_name_len] = 0;
|
||||
conn->server_name_len = host_name_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
583
src/tls12.c
583
src/tls12.c
@@ -194,6 +194,122 @@ int tls_named_curve_from_oid(int oid)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
session_ticket_key
|
||||
|
||||
* server_only
|
||||
* server encrypt and send NewSessionTicket
|
||||
* server decrypt ClientHello.pre_shared_key
|
||||
*/
|
||||
int tls13_ctx_set_session_ticket_key(TLS_CTX *ctx, const uint8_t *key, size_t keylen)
|
||||
{
|
||||
if (!ctx || !key || !keylen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (ctx->is_client) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (keylen != SM4_KEY_SIZE) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sm4_set_encrypt_key(&ctx->_session_ticket_key, key);
|
||||
ctx->session_ticket_key = &ctx->_session_ticket_key;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define TLS_MAX_NEW_SESSION_TICKETS 5
|
||||
|
||||
int tls13_ctx_set_new_session_ticket(TLS_CTX *ctx, size_t new_session_ticket_cnt)
|
||||
{
|
||||
if (!ctx) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (new_session_ticket_cnt > TLS_MAX_NEW_SESSION_TICKETS) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->new_session_ticket = (int)new_session_ticket_cnt;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls13_set_new_session_ticket(TLS_CONNECT *conn, size_t new_session_ticket_cnt)
|
||||
{
|
||||
if (!conn) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (new_session_ticket_cnt > TLS_MAX_NEW_SESSION_TICKETS) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
conn->new_session_ticket = new_session_ticket_cnt;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 这两个函数还有用吗?
|
||||
/*
|
||||
int tls13_set_session_infile(TLS_CONNECT *conn, const char *file)
|
||||
{
|
||||
if (!conn || !file) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (!conn->is_client) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
conn->session_in = file;
|
||||
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
|
||||
int tls13_set_session_outfile(TLS_CONNECT *conn, const char *file)
|
||||
{
|
||||
if (!conn || !file) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (!conn->is_client) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
conn->session_out = file;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -402,7 +518,7 @@ int tls_send_client_hello(TLS_CONNECT *conn)
|
||||
}
|
||||
if (tls_record_set_handshake_client_hello(conn->record, &conn->recordlen,
|
||||
conn->protocol, conn->client_random, NULL, 0,
|
||||
conn->cipher_suites, conn->cipher_suites_cnt,
|
||||
conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt,
|
||||
client_exts, client_exts_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
@@ -449,7 +565,7 @@ int tlcp_send_client_hello(TLS_CONNECT *conn)
|
||||
|
||||
if (tls_record_set_handshake_client_hello(conn->record, &conn->recordlen,
|
||||
conn->protocol, conn->client_random, NULL, 0,
|
||||
conn->cipher_suites, conn->cipher_suites_cnt,
|
||||
conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt,
|
||||
NULL, 0) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
@@ -507,7 +623,7 @@ int tlcp_recv_client_hello(TLS_CONNECT *conn)
|
||||
|
||||
|
||||
// 服务器端如果设置了CA
|
||||
if (conn->ca_certs_len)
|
||||
if (conn->ctx->cacertslen)
|
||||
client_verify = 1;
|
||||
|
||||
// 这个判断应该改为一个函数
|
||||
@@ -550,7 +666,7 @@ int tlcp_recv_client_hello(TLS_CONNECT *conn)
|
||||
memcpy(conn->client_random, client_random, 32);
|
||||
|
||||
if (tls_cipher_suites_select(client_ciphers, client_ciphers_len,
|
||||
conn->cipher_suites, conn->cipher_suites_cnt,
|
||||
conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt,
|
||||
&conn->cipher_suite) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_insufficient_security);
|
||||
@@ -559,7 +675,7 @@ int tlcp_recv_client_hello(TLS_CONNECT *conn)
|
||||
|
||||
switch (conn->cipher_suite) {
|
||||
case TLS_cipher_ecc_sm4_cbc_sm3:
|
||||
conn->sig_alg = TLS_sig_sm2sig_sm3;
|
||||
conn->signature_algorithms[0] = TLS_sig_sm2sig_sm3;
|
||||
conn->ecdh_named_curve = 0;
|
||||
break;
|
||||
case TLS_cipher_ecdhe_sm4_cbc_sm3:
|
||||
@@ -621,7 +737,7 @@ int tls_recv_client_hello(TLS_CONNECT *conn)
|
||||
|
||||
|
||||
// 服务器端如果设置了CA
|
||||
if (conn->ca_certs_len)
|
||||
if (conn->ctx->cacertslen)
|
||||
client_verify = 1;
|
||||
|
||||
// 这个判断应该改为一个函数
|
||||
@@ -667,7 +783,7 @@ int tls_recv_client_hello(TLS_CONNECT *conn)
|
||||
|
||||
// 服务器选择的cipher_suites需要和服务器准备的证书和公钥匹配
|
||||
if (tls_cipher_suites_select(client_ciphers, client_ciphers_len,
|
||||
conn->cipher_suites, conn->cipher_suites_cnt,
|
||||
conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt,
|
||||
&conn->cipher_suite) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_insufficient_security);
|
||||
@@ -677,11 +793,11 @@ int tls_recv_client_hello(TLS_CONNECT *conn)
|
||||
switch (conn->cipher_suite) {
|
||||
case TLS_cipher_ecdhe_sm4_cbc_sm3:
|
||||
case TLS_cipher_ecdhe_sm4_gcm_sm3:
|
||||
conn->sig_alg = TLS_sig_sm2sig_sm3;
|
||||
conn->signature_algorithms[0] = TLS_sig_sm2sig_sm3;
|
||||
conn->ecdh_named_curve = TLS_curve_sm2p256v1;
|
||||
break;
|
||||
case TLS_cipher_ecdhe_ecdsa_with_aes_128_cbc_sha256:
|
||||
conn->sig_alg = TLS_sig_ecdsa_secp256r1_sha256;
|
||||
conn->signature_algorithms[0] = TLS_sig_ecdsa_secp256r1_sha256;
|
||||
conn->ecdh_named_curve = TLS_curve_secp256r1;
|
||||
break;
|
||||
default:
|
||||
@@ -691,8 +807,9 @@ int tls_recv_client_hello(TLS_CONNECT *conn)
|
||||
|
||||
if (client_exts) {
|
||||
// 这些函数需要能够访问conn的内部变量
|
||||
tls_process_client_hello_exts(client_exts, client_exts_len,
|
||||
conn->server_exts, &conn->server_exts_len, sizeof(conn->server_exts));
|
||||
// 修改处理扩展的逻辑
|
||||
//tls_process_client_hello_exts(client_exts, client_exts_len,
|
||||
// conn->server_exts, &conn->server_exts_len, sizeof(conn->server_exts));
|
||||
}
|
||||
|
||||
sm3_update(&conn->sm3_ctx, conn->record + 5, conn->recordlen - 5);
|
||||
@@ -720,10 +837,13 @@ int tls_send_server_hello(TLS_CONNECT *conn)
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
// 修改处理扩展的逻辑,把ClientHello的每个扩展处理结果分别放在conn的各个变量中
|
||||
/*
|
||||
if (conn->server_exts_len) {
|
||||
server_exts = conn->server_exts;
|
||||
server_exts_len = conn->server_exts_len;
|
||||
}
|
||||
*/
|
||||
if (tls_record_set_handshake_server_hello(conn->record, &conn->recordlen,
|
||||
conn->protocol, conn->server_random, NULL, 0,
|
||||
conn->cipher_suite,
|
||||
@@ -743,7 +863,7 @@ int tls_send_server_hello(TLS_CONNECT *conn)
|
||||
}
|
||||
|
||||
sm3_update(&conn->sm3_ctx, conn->record + 5, conn->recordlen - 5);
|
||||
if (conn->ca_certs_len) {
|
||||
if (conn->ctx->cacertslen) {
|
||||
tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5);
|
||||
}
|
||||
|
||||
@@ -933,7 +1053,7 @@ int tls_recv_server_certificate(TLS_CONNECT *conn)
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
conn->server_sig_alg = TLS_sig_sm2sig_sm3;
|
||||
conn->signature_algorithms[0] = TLS_sig_sm2sig_sm3;
|
||||
break;
|
||||
|
||||
case TLS_cipher_ecdhe_ecdsa_with_aes_128_cbc_sha256:
|
||||
@@ -941,7 +1061,7 @@ int tls_recv_server_certificate(TLS_CONNECT *conn)
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
conn->server_sig_alg = TLS_sig_ecdsa_secp256r1_sha256;
|
||||
conn->signature_algorithms[0] = TLS_sig_ecdsa_secp256r1_sha256;
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
@@ -953,26 +1073,26 @@ int tls_recv_server_certificate(TLS_CONNECT *conn)
|
||||
sm2_sign_update(&conn->sign_ctx, conn->record + 5, conn->recordlen - 5);
|
||||
}
|
||||
|
||||
assert(conn->verify_depth > 0 && conn->verify_depth < 10);
|
||||
assert(conn->ctx->verify_depth > 0 && conn->ctx->verify_depth < 10);
|
||||
|
||||
// verify ServerCertificate
|
||||
|
||||
switch (conn->protocol) {
|
||||
case TLS_protocol_tls12:
|
||||
if (x509_certs_verify(conn->server_certs, conn->server_certs_len, X509_cert_chain_server,
|
||||
conn->ca_certs, conn->ca_certs_len, conn->verify_depth, &verify_result) != 1) {
|
||||
conn->ctx->cacerts, conn->ctx->cacertslen, conn->ctx->verify_depth, &verify_result) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_bad_certificate);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case TLS_protocol_tlcp:
|
||||
if (!conn->ca_certs_len) {
|
||||
if (!conn->ctx->cacertslen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_certs_verify_tlcp(conn->server_certs, conn->server_certs_len, X509_cert_chain_server,
|
||||
conn->ca_certs, conn->ca_certs_len, conn->verify_depth, &verify_result) != 1) {
|
||||
conn->ctx->cacerts, conn->ctx->cacertslen, conn->ctx->verify_depth, &verify_result) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_bad_certificate);
|
||||
return -1;
|
||||
@@ -1100,7 +1220,7 @@ int tls_send_server_key_exchange(TLS_CONNECT *conn)
|
||||
|
||||
if (tls_record_set_handshake_server_key_exchange(conn->record, &conn->recordlen,
|
||||
server_ecdh_params, sizeof(server_ecdh_params),
|
||||
conn->sig_alg, sig, siglen) != 1) {
|
||||
conn->signature_algorithms[0], sig, siglen) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
@@ -1424,7 +1544,7 @@ int tls_send_certificate_request(TLS_CONNECT *conn)
|
||||
if (conn->recordlen == 0) {
|
||||
tls_trace("send CertificateRequest\n");
|
||||
if (tls_authorities_from_certs(ca_names, &ca_names_len, sizeof(ca_names),
|
||||
conn->ca_certs, conn->ca_certs_len) != 1) {
|
||||
conn->ctx->cacerts, conn->ctx->cacertslen) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_internal_error);
|
||||
return -1;
|
||||
@@ -1624,7 +1744,7 @@ int tls_recv_client_certificate(TLS_CONNECT *conn)
|
||||
|
||||
tls_trace("recv ClientCertificate\n");
|
||||
|
||||
if (conn->ca_certs_len == 0) {
|
||||
if (conn->ctx->cacertslen == 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -1647,7 +1767,7 @@ int tls_recv_client_certificate(TLS_CONNECT *conn)
|
||||
return -1;
|
||||
}
|
||||
if (x509_certs_verify(conn->client_certs, conn->client_certs_len, X509_cert_chain_client,
|
||||
conn->ca_certs, conn->ca_certs_len, verify_depth, &verify_result) != 1) {
|
||||
conn->ctx->cacerts, conn->ctx->cacertslen, verify_depth, &verify_result) != 1) {
|
||||
error_print();
|
||||
tls_send_alert(conn, TLS_alert_bad_certificate);
|
||||
return -1;
|
||||
@@ -1867,7 +1987,7 @@ int tls_recv_client_key_exchange(TLS_CONNECT *conn)
|
||||
conn->peer_ecdh_point_len = point_octets_len;
|
||||
|
||||
sm3_update(&conn->sm3_ctx, conn->record + 5, conn->recordlen - 5);
|
||||
if (conn->ca_certs_len)
|
||||
if (conn->ctx->cacertslen)
|
||||
tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5);
|
||||
|
||||
return 1;
|
||||
@@ -2756,3 +2876,420 @@ int tls12_do_accept(TLS_CONNECT *conn)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
status_request(5)
|
||||
|
||||
这个扩展在客户端和服务器端中是不同的
|
||||
|
||||
ClientHello.status_request
|
||||
|
||||
|
||||
struct {
|
||||
CertificateStatusType status_type = ocsp(1);
|
||||
opaque request<0..2^16-1>;
|
||||
} CertificateStatusRequest;
|
||||
|
||||
其中request中是:
|
||||
|
||||
struct {
|
||||
ResponderID responder_id_list<0..2^16-1>;
|
||||
Extensions request_extensions;
|
||||
} OCSPStatusRequest;
|
||||
|
||||
------------------------------------------------------
|
||||
|
||||
server Certificate
|
||||
|
||||
struct {
|
||||
CertificateStatusType status_type;
|
||||
opaque response<1..2^24-1>;
|
||||
} CertificateStatus;
|
||||
|
||||
response中的数据是就是一个原始的OCSP的response,我们将其视为二进制数据
|
||||
|
||||
|
||||
在TLS 1.2中,如果服务器同意status_request,会在ServerHello中返回一个空的status_request
|
||||
并且会返回一个独立的CertificateStatus握手消息
|
||||
*/
|
||||
|
||||
int tls_ocsp_status_request_to_bytes(
|
||||
const uint8_t *responder_id_list, size_t responder_id_list_len,
|
||||
const uint8_t *request_exts, size_t request_exts_len,
|
||||
uint8_t **out, size_t *outlen)
|
||||
{
|
||||
uint8_t **pp = out;
|
||||
size_t request_len = 0;
|
||||
size_t len;
|
||||
|
||||
if (!outlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
tls_uint16_to_bytes(0, out, &len);
|
||||
tls_uint16array_to_bytes(responder_id_list, responder_id_list_len, out, &request_len);
|
||||
tls_uint16array_to_bytes(request_exts, request_exts_len, out, &request_len);
|
||||
tls_uint16array_to_bytes(NULL, request_len, pp, outlen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_ocsp_status_request_from_bytes(
|
||||
const uint8_t **responder_id_list, size_t *responder_id_list_len,
|
||||
const uint8_t **request_exts, size_t *request_exts_len,
|
||||
const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
const uint8_t *request;
|
||||
size_t request_len;
|
||||
|
||||
if (!responder_id_list || !responder_id_list_len || !request_exts || !request_exts_len
|
||||
|| !in || !(*in) || !inlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (tls_uint16array_from_bytes(&request, &request_len, in, inlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (!request) {
|
||||
*responder_id_list = NULL;
|
||||
*responder_id_list_len = 0;
|
||||
*request_exts = NULL;
|
||||
*request_exts_len = 0;
|
||||
return 1;
|
||||
}
|
||||
if (tls_uint16array_from_bytes(responder_id_list, responder_id_list_len, &request, &request_len) != 1
|
||||
|| tls_uint16array_from_bytes(request_exts, request_exts_len, &request, &request_len) != 1
|
||||
|| tls_length_is_zero(request_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_ocsp_status_request_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *ext_data, size_t ext_datalen)
|
||||
{
|
||||
const uint8_t *request;
|
||||
size_t request_len;
|
||||
const uint8_t *responder_id_list;
|
||||
size_t responder_id_list_len;
|
||||
const uint8_t *request_exts;
|
||||
size_t request_exts_len;
|
||||
|
||||
format_print(fp, fmt, ind, "%s\n", label);
|
||||
ind += 4;
|
||||
|
||||
if (tls_uint16array_from_bytes(&request, &request_len, &ext_data, &ext_datalen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (!request) {
|
||||
format_print(fp, fmt, ind, "(null)\n");
|
||||
if (ext_datalen) {
|
||||
format_print(fp, fmt, ind, "error: left %zu bytes\n", ext_datalen);
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (tls_uint16array_from_bytes(&responder_id_list, &responder_id_list_len, &request, &request_len) != 1
|
||||
|| tls_uint16array_from_bytes(&request_exts, &request_exts_len, &request, &request_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
while (responder_id_list_len) {
|
||||
const uint8_t *responder_id;
|
||||
size_t responder_id_len;
|
||||
|
||||
if (tls_uint16array_from_bytes(&responder_id, &responder_id_len,
|
||||
&responder_id_list, &responder_id_list_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_bytes(fp, fmt, ind + 4, "ResponderID", responder_id, responder_id_len);
|
||||
}
|
||||
while (request_exts_len) {
|
||||
int ext_type;
|
||||
const uint8_t *ext_data;
|
||||
size_t ext_datalen;
|
||||
|
||||
if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_datalen, &request_exts, &request_exts_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
// print
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
struct {
|
||||
CertificateStatusType status_type = ocsp(1);
|
||||
opaque request<0..2^16-1>;
|
||||
} CertificateStatusRequest;
|
||||
*/
|
||||
int tls_client_status_request_ext_to_bytes(int status_type,
|
||||
const uint8_t *responder_id_list, size_t responder_id_list_len,
|
||||
const uint8_t *request_exts, size_t request_exts_len,
|
||||
uint8_t **out, size_t *outlen)
|
||||
{
|
||||
int ext_type = TLS_extension_status_request;
|
||||
size_t ext_datalen = 0;
|
||||
uint8_t **pp = out;
|
||||
size_t len;
|
||||
|
||||
if (!outlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
tls_ext_to_bytes(ext_type, NULL, 0, out, &len);
|
||||
tls_uint8_to_bytes(status_type, out, &ext_datalen);
|
||||
tls_ocsp_status_request_to_bytes(responder_id_list, responder_id_list_len,
|
||||
request_exts, request_exts_len, out, &ext_datalen);
|
||||
tls_ext_to_bytes(ext_type, NULL, ext_datalen, pp, outlen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_client_status_request_from_bytes(int *status_type,
|
||||
const uint8_t **responder_id_list, size_t *responder_id_list_len,
|
||||
const uint8_t **request_exts, size_t *request_exts_len,
|
||||
const uint8_t *ext_data, size_t ext_datalen)
|
||||
{
|
||||
uint8_t status;
|
||||
|
||||
if (!status_type || !responder_id_list || !responder_id_list_len
|
||||
|| !request_exts || !request_exts_len || !ext_data || !ext_datalen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (tls_uint8_from_bytes(&status, &ext_data, &ext_datalen) != 1
|
||||
|| tls_ocsp_status_request_from_bytes(responder_id_list, responder_id_list_len,
|
||||
request_exts, request_exts_len, &ext_data, &ext_datalen) != 1
|
||||
|| tls_length_is_zero(ext_datalen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*status_type = status;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_client_status_request_print(FILE *fp, int fmt, int ind, const uint8_t *ext_data, size_t ext_datalen)
|
||||
{
|
||||
uint8_t status_type;
|
||||
const uint8_t *request;
|
||||
size_t request_len;
|
||||
|
||||
if (tls_uint8_from_bytes(&status_type, &ext_data, &ext_datalen) != 1
|
||||
|| tls_uint16array_from_bytes(&request, &request_len, &ext_data, &ext_datalen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_print(fp, fmt, ind, "status_type: %s (%d)\n", status_type == TLS_certificate_status_type_ocsp ? "ocsp" : NULL, status_type);
|
||||
|
||||
|
||||
request -= tls_uint16_size();
|
||||
request_len += tls_uint16_size();
|
||||
tls_ocsp_status_request_print(fp, fmt, ind, "request", request, request_len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
int ocsp_response_verify(const uint8_t *ocsp_response, size_t ocsp_response_len,
|
||||
const uint8_t *ca_certs, size_t ca_certs_len)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_server_status_request_ext_to_bytes(const uint8_t *ocsp_response, size_t ocsp_response_len,
|
||||
uint8_t **out, size_t *outlen)
|
||||
{
|
||||
int ext_type = TLS_extension_status_request;
|
||||
size_t ext_datalen = 0;
|
||||
uint8_t **pp = out;
|
||||
size_t len;
|
||||
|
||||
if (!ocsp_response || !ocsp_response_len || !outlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
tls_ext_to_bytes(ext_type, NULL, 0, out, &len);
|
||||
tls_uint24array_to_bytes(ocsp_response, ocsp_response_len, out, &ext_datalen);
|
||||
tls_ext_to_bytes(ext_type, NULL, ext_datalen, pp, outlen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_server_status_request_from_bytes(const uint8_t **ocsp_response, size_t *ocsp_response_len,
|
||||
const uint8_t *ext_data, size_t ext_datalen)
|
||||
{
|
||||
if (!ocsp_response || !ocsp_response_len || !ext_data || !ext_datalen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (tls_uint24array_from_bytes(ocsp_response, ocsp_response_len, &ext_data, &ext_datalen) != 1
|
||||
|| tls_length_is_zero(ext_datalen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_server_status_request_print(FILE *fp, int fmt, int ind, const uint8_t *ext_data, size_t ext_datalen)
|
||||
{
|
||||
const uint8_t *ocsp_response;
|
||||
size_t ocsp_response_len;
|
||||
|
||||
if (tls_uint24array_from_bytes(&ocsp_response, &ocsp_response_len, &ext_data, &ext_datalen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_bytes(fp, fmt, ind, "ocsp_response", ocsp_response, ocsp_response_len);
|
||||
if (ext_datalen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
signed_certificate_timestamp
|
||||
|
||||
|
||||
struct {
|
||||
opaque sct_list<1..2^16-1>;
|
||||
} SignedCertificateTimestampList;
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
signed_certificate_timestamp (CT)
|
||||
|
||||
这是一个tls13的扩展
|
||||
|
||||
这个扩展只在ServerCertificate, ClientCertificate握手消息的扩展中
|
||||
|
||||
这个扩展主要是提供一个格外的信息:
|
||||
证书透明度(CT)日志服务器签发的“证书存在证明”的扩展。
|
||||
|
||||
struct {
|
||||
opaque key_id[32]; // 日志服务器ID
|
||||
uint64 timestamp; // 证书提交时间戳
|
||||
opaque signature<0..2^16-1>; // 日志服务器签名
|
||||
} SignedCertificateTimestamp;
|
||||
|
||||
struct {
|
||||
SignedCertificateTimestamp sct_list<0..2^16-1>;
|
||||
} SignedCertificateTimestampList;
|
||||
*/
|
||||
|
||||
|
||||
|
||||
int tls_signed_certificate_timestamp_entry_to_bytes(const uint8_t key_id[32],
|
||||
uint64_t timestamp, const uint8_t *signature, size_t signature_len,
|
||||
uint8_t **out, size_t *outlen)
|
||||
{
|
||||
|
||||
if (!key_id || !signature || !signature_len || !outlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
tls_array_to_bytes(key_id, 32, out, outlen);
|
||||
tls_uint64_to_bytes(timestamp, out, outlen);
|
||||
tls_uint16array_to_bytes(signature, signature_len, out, outlen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_signed_certificate_timestamp_entry_from_bytes(const uint8_t **key_id,
|
||||
uint64_t *timestamp, const uint8_t **signature, size_t *signature_len,
|
||||
const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
if (!key_id || !timestamp || !signature || !signature_len || !in || !(*in) || !inlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (tls_array_from_bytes(key_id, 32, in, inlen) != 1
|
||||
|| tls_uint64_from_bytes(timestamp, in, inlen) != 1
|
||||
|| tls_uint16array_from_bytes(signature, signature_len, in, inlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_signed_certificate_timestamp_ext_to_bytes(const uint8_t *sct_list, size_t sct_list_len,
|
||||
uint8_t **out, size_t *outlen)
|
||||
{
|
||||
if (!sct_list || !sct_list_len || !outlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
tls_uint16array_to_bytes(sct_list, sct_list_len, out, outlen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_signed_certificate_timestamp_from_bytes(const uint8_t **sct_list, size_t *sct_list_len,
|
||||
const uint8_t **in, size_t *inlen)
|
||||
{
|
||||
if (!sct_list || !sct_list_len || !in || !(*in) || !inlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (tls_uint16array_from_bytes(sct_list, sct_list_len, in, inlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_signed_certificate_timestamp_print(FILE *fp, int fmt, int ind,
|
||||
const char *label, const uint8_t *d, size_t dlen)
|
||||
{
|
||||
const uint8_t *sct_list;
|
||||
size_t sct_list_len;
|
||||
|
||||
if (tls_uint16array_from_bytes(&sct_list, &sct_list_len, &d, &dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_print(fp, fmt, ind, "sct_list\n");
|
||||
ind += 4;
|
||||
|
||||
if (!sct_list_len) {
|
||||
format_print(fp, fmt, ind, "(null)\n");
|
||||
}
|
||||
while (sct_list_len) {
|
||||
const uint8_t *key_id;
|
||||
uint64_t timestamp;
|
||||
const uint8_t *signature;
|
||||
size_t signature_len;
|
||||
int entry_ind = ind + 4;
|
||||
|
||||
format_print(fp, fmt, ind, "SignedCertificateTimestamp\n");
|
||||
|
||||
if (tls_array_from_bytes(&key_id, 32, &sct_list, &sct_list_len) != 1
|
||||
|| tls_uint64_from_bytes(×tamp, &sct_list, &sct_list_len) != 1
|
||||
|| tls_uint16array_from_bytes(&signature, &signature_len, &sct_list, &sct_list_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_bytes(fp, fmt, entry_ind, "key_id", key_id, 32);
|
||||
format_print(fp, fmt, entry_ind, "timestamp: %"PRIu64"\n", timestamp);
|
||||
format_bytes(fp, fmt, entry_ind, "signature", signature, signature_len);
|
||||
if (dlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
4322
src/tls13.c
4322
src/tls13.c
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <gmssl/ec.h>
|
||||
#include <gmssl/tls.h>
|
||||
#include <gmssl/x509.h>
|
||||
#include <gmssl/error.h>
|
||||
@@ -44,6 +45,18 @@ const char *tls_protocol_name(int protocol)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int tls_protocol_from_name(const char *name)
|
||||
{
|
||||
if (!strcmp(name, "TLS1.3")) {
|
||||
return TLS_protocol_tls13;
|
||||
} else if (!strcmp(name, "TLS1.2")) {
|
||||
return TLS_protocol_tls12;
|
||||
} else if (!strcmp(name, "TLCP")) {
|
||||
return TLS_protocol_tlcp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *tls_cipher_suite_name(int cipher)
|
||||
{
|
||||
switch (cipher) {
|
||||
@@ -73,6 +86,23 @@ const char *tls_cipher_suite_name(int cipher)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int tls_cipher_suite_from_name(const char *name)
|
||||
{
|
||||
if (!strcmp(name, "TLS_SM4_GCM_SM3")) {
|
||||
return TLS_cipher_sm4_gcm_sm3;
|
||||
} else if (!strcmp(name, "TLS_AES_128_GCM_SHA256")) {
|
||||
return TLS_cipher_aes_128_gcm_sha256;
|
||||
} else if (!strcmp(name, "TLS_ECDHE_SM4_CBC_SM3")) {
|
||||
return TLS_cipher_ecdhe_sm4_cbc_sm3;
|
||||
} else if (!strcmp(name, "TLS_ECC_SM4_CBC_SM3")) {
|
||||
return TLS_cipher_ecc_sm4_cbc_sm3;
|
||||
} else if (!strcmp(name, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256")) {
|
||||
return TLS_cipher_ecdhe_ecdsa_with_aes_128_cbc_sha256;
|
||||
}
|
||||
error_print();
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *tls_compression_method_name(int meth)
|
||||
{
|
||||
switch (meth) {
|
||||
@@ -238,6 +268,7 @@ const char *tls_alert_description_text(int description)
|
||||
case TLS_alert_bad_ibcparam: return "bad_ibcparam";
|
||||
case TLS_alert_unsupported_ibcparam: return "unsupported_ibcparam";
|
||||
case TLS_alert_identity_need: return "identity_need";
|
||||
case TLS_alert_missing_extension: return "missing_extension";
|
||||
}
|
||||
error_print_msg("unknown alert description %d", description);
|
||||
return NULL;
|
||||
@@ -291,6 +322,20 @@ const char *tls_named_curve_name(int curve)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int tls_named_curve_from_name(const char *name)
|
||||
{
|
||||
int oid;
|
||||
if ((oid = ec_named_curve_from_name(name)) == OID_undef) {
|
||||
return 0;
|
||||
}
|
||||
switch (oid) {
|
||||
case OID_sm2:
|
||||
case OID_secp256r1:
|
||||
return tls_named_curve_from_oid(oid);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *tls_signature_scheme_name(int scheme)
|
||||
{
|
||||
switch (scheme) {
|
||||
@@ -321,6 +366,35 @@ const char *tls_signature_scheme_name(int scheme)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int tls_signature_scheme_from_name(const char *name)
|
||||
{
|
||||
if (!strcmp(name, "ecdsa_secp256r1_sha256")) {
|
||||
return TLS_sig_ecdsa_secp256r1_sha256;
|
||||
} else if (!strcmp(name, "sm2sig_sm3")) {
|
||||
return TLS_sig_sm2sig_sm3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tls_signature_scheme_algorithm_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_group_oid(int sig_alg)
|
||||
{
|
||||
switch (sig_alg) {
|
||||
case TLS_sig_sm2sig_sm3: return OID_sm2;
|
||||
case TLS_sig_ecdsa_secp256r1_sha256: return OID_secp256r1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 这个函数去掉
|
||||
int tls_signature_scheme_oid(int sig_alg)
|
||||
{
|
||||
switch (sig_alg) {
|
||||
@@ -330,6 +404,7 @@ int tls_signature_scheme_oid(int sig_alg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 这个函数也应该修改,必须同时提供算法/group
|
||||
int tls_signature_scheme_from_oid(int sig_alg_oid)
|
||||
{
|
||||
switch (sig_alg_oid) {
|
||||
|
||||
@@ -1594,6 +1594,47 @@ int x509_cert_get_exts(const uint8_t *a, size_t alen, const uint8_t **d, size_t
|
||||
return 1;
|
||||
}
|
||||
|
||||
// compre host_name of server_name (SNI) extension with SubjectAltName.dnsName
|
||||
int x509_cert_get_subject_alt_name_dns_name(const uint8_t *a, size_t alen, const uint8_t **dns_name, size_t *dns_name_len)
|
||||
{
|
||||
const uint8_t *exts;
|
||||
size_t extslen;
|
||||
const uint8_t *general_names;
|
||||
size_t general_names_len;
|
||||
int choice = X509_gn_dns_name;
|
||||
int critical;
|
||||
int ret;
|
||||
|
||||
if (!a || !alen || !dns_name || !dns_name_len) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*dns_name = NULL;
|
||||
*dns_name_len = 0;
|
||||
|
||||
if ((ret = x509_cert_get_exts(a, alen, &exts, &extslen)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
} else if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
if ((ret = x509_exts_get_ext_by_oid(exts, extslen, OID_ce_subject_alt_name,
|
||||
&critical, &general_names, &general_names_len)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
} else if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
if ((ret = x509_general_names_get_first(general_names, general_names_len,
|
||||
NULL, choice, dns_name, dns_name_len)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
} else if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_cert_get_signature_algor(const uint8_t *a, size_t alen, int *oid)
|
||||
{
|
||||
int inner_alg;
|
||||
|
||||
@@ -1297,6 +1297,7 @@ int x509_private_key_info_encrypt_to_pem(const X509_KEY *key, const char *pass,
|
||||
|
||||
int x509_private_key_info_decrypt_from_pem(X509_KEY *key, const uint8_t **attrs, size_t *attrslen, const char *pass, FILE *fp)
|
||||
{
|
||||
int ret;
|
||||
uint8_t buf[512];
|
||||
const uint8_t *cp = buf;
|
||||
size_t len;
|
||||
@@ -1305,9 +1306,11 @@ int x509_private_key_info_decrypt_from_pem(X509_KEY *key, const uint8_t **attrs,
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (pem_read(fp, "ENCRYPTED PRIVATE KEY", buf, &len, sizeof(buf)) != 1) {
|
||||
if ((ret = pem_read(fp, "ENCRYPTED PRIVATE KEY", buf, &len, sizeof(buf))) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
} else if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (x509_private_key_info_decrypt_from_der(key, attrs, attrslen, pass, &cp, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
@@ -1325,15 +1328,18 @@ int x509_private_key_from_file(X509_KEY *key, int algor, const char *pass, FILE
|
||||
}
|
||||
|
||||
if (algor == OID_ec_public_key) {
|
||||
int ret;
|
||||
const uint8_t *attrs;
|
||||
size_t attrslen;
|
||||
if (!pass) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_private_key_info_decrypt_from_pem(key, &attrs, &attrslen, pass, fp) != 1) {
|
||||
if ((ret = x509_private_key_info_decrypt_from_pem(key, &attrs, &attrslen, pass, fp)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
} else if (ret == 0) {
|
||||
return 0; // TODO: support return 0 for other algors
|
||||
}
|
||||
} else if (algor == OID_lms_hashsig) {
|
||||
uint8_t buf[LMS_PRIVATE_KEY_SIZE];
|
||||
@@ -1420,6 +1426,32 @@ int x509_private_key_from_file(X509_KEY *key, int algor, const char *pass, FILE
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_private_keys_from_file(X509_KEY *keys, size_t *keys_cnt, size_t max_cnt,
|
||||
int algor, const char *pass, FILE *fp)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!keys || !keys_cnt || !pass || !fp) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < max_cnt; i++) {
|
||||
int ret;
|
||||
if ((ret = x509_private_key_from_file(&keys[i], algor, pass, fp)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
} else if (ret == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*keys_cnt = i;
|
||||
|
||||
if (i == 0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_key_get_sign_algor(const X509_KEY *key, int *algor)
|
||||
{
|
||||
if (!key || !algor) {
|
||||
|
||||
@@ -20,6 +20,33 @@
|
||||
#include <gmssl/sm4.h>
|
||||
|
||||
|
||||
|
||||
static int test_tls_ext(void)
|
||||
{
|
||||
uint8_t ext_data[30];
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
|
||||
if (tls_ext_to_bytes(TLS_extension_max_fragment_length, NULL, sizeof(ext_data), &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (len != 4 + sizeof(ext_data)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (p != buf + 4 + sizeof(ext_data)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int test_tls13_gcm(void)
|
||||
{
|
||||
|
||||
@@ -499,11 +526,104 @@ static int test_tls13_ticket(void)
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static int test_tls13_psk_key_exchange_modes(void)
|
||||
{
|
||||
int modes[] = {
|
||||
TLS_psk_key_exchange_modes_psk_dhe,
|
||||
TLS_psk_key_exchange_modes_psk_only,
|
||||
TLS_psk_key_exchange_modes_both,
|
||||
};
|
||||
|
||||
uint8_t buf[128];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(modes)/sizeof(modes[0]); i++) {
|
||||
if (tls13_psk_key_exchange_modes_ext_to_bytes(modes[i], &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(modes)/sizeof(modes[0]); i++) {
|
||||
int type;
|
||||
const uint8_t *d;
|
||||
size_t dlen;
|
||||
int mode;
|
||||
|
||||
if (tls_ext_from_bytes(&type, &d, &dlen, &cp, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (type != TLS_extension_psk_key_exchange_modes) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
format_print(stderr, 0, 4, "psk_key_exchange_modes\n");
|
||||
tls13_psk_key_exchange_modes_print(stderr, 0, 8, d, dlen);
|
||||
|
||||
if (tls13_psk_key_exchange_modes_from_bytes(&mode, d, dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (mode != modes[i]) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
if (len) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int test_tls_server_name_ext(void)
|
||||
{
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
int ext_type;
|
||||
const uint8_t *ext_data;
|
||||
size_t ext_datalen;
|
||||
const uint8_t *hostname;
|
||||
size_t hostname_len;
|
||||
|
||||
|
||||
if (tls_server_name_ext_to_bytes((uint8_t *)"www.pku.edu.cn", sizeof("www.pku.edu.cn"), &p, &len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_datalen, &cp, &len) != 1
|
||||
|| tls_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (tls_server_name_from_bytes(&hostname, &hostname_len, ext_data, ext_datalen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
tls_server_name_print(stderr, 0, 0, ext_data, ext_datalen);
|
||||
|
||||
|
||||
// 这里应该补充一个包含多个host_name的例子
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -541,15 +661,19 @@ static int test_tls13_ticket(void)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (test_tls_ext() != 1) goto err;
|
||||
if (test_tls13_gcm() != 1) goto err;
|
||||
if (test_tls13_supported_versions_ext() != 1) goto err;
|
||||
if (test_tls13_key_share_ext() != 1) goto err;
|
||||
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;
|
||||
// if (test_tls13_ticket() != 1) goto err;
|
||||
// if (test_tls13_psk_key_exchange_modes() != 1) goto err;
|
||||
|
||||
|
||||
if (test_tls_server_name_ext() != 1) goto err;
|
||||
|
||||
printf("%s all tests passed\n", __FILE__);
|
||||
return 0;
|
||||
err:
|
||||
|
||||
@@ -63,6 +63,22 @@ static int test_tls_encode(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_tls_null_to_bytes(void)
|
||||
{
|
||||
uint8_t buf[10];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
|
||||
tls_uint16array_to_bytes(buf, sizeof(buf), NULL, &len);
|
||||
|
||||
// this will segment fault
|
||||
//p = NULL;
|
||||
//tls_uint16array_to_bytes(buf, sizeof(buf), &p, &len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_tls_cbc(void)
|
||||
{
|
||||
uint8_t key[32] = {0};
|
||||
@@ -320,8 +336,26 @@ static int test_tls_application_data(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_tls_status_request_ext(void)
|
||||
{
|
||||
uint8_t ocsp_response[5];
|
||||
uint8_t buf[256];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *cp = buf;
|
||||
size_t len = 0;
|
||||
|
||||
memset(ocsp_response, 0xff, sizeof(ocsp_response));
|
||||
|
||||
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (test_tls_null_to_bytes() != 1) goto err;
|
||||
/*
|
||||
if (test_tls_encode() != 1) goto err;
|
||||
if (test_tls_cbc() != 1) goto err;
|
||||
if (test_tls_random() != 1) goto err;
|
||||
@@ -334,6 +368,8 @@ int main(void)
|
||||
if (test_tls_alert() != 1) goto err;
|
||||
if (test_tls_change_cipher_spec() != 1) goto err;
|
||||
if (test_tls_application_data() != 1) goto err;
|
||||
*/
|
||||
if (test_tls_status_request_ext() != 1) goto err;
|
||||
printf("%s all tests passed\n", __FILE__);
|
||||
return 0;
|
||||
err:
|
||||
|
||||
@@ -352,6 +352,49 @@ static int test_x509_private_key_info_encrypt_to_pem(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_x509_private_key_info_decrypt_from_pem(void)
|
||||
{
|
||||
const char *file = "test_x509_private_key_info_decrypt_from_pem.pem";
|
||||
const char *pass = "P@ssw0rd";
|
||||
FILE *fp;
|
||||
int i;
|
||||
|
||||
if (!(fp = fopen(file, "w"))) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < sizeof(tests)/sizeof(tests[0]) && tests[i].algor == OID_ec_public_key; i++) {
|
||||
if (x509_private_key_info_encrypt_to_pem(&x509_keys[i], pass, fp) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
if (!(fp = fopen(file, "r"))) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
while (1) {
|
||||
int ret;
|
||||
X509_KEY key;
|
||||
const uint8_t *attrs;
|
||||
size_t attrslen;
|
||||
|
||||
if ((ret = x509_private_key_info_decrypt_from_pem(&key, &attrs, &attrslen, pass, fp)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
} else if (ret == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_x509_sign(void)
|
||||
{
|
||||
size_t i;
|
||||
@@ -559,7 +602,6 @@ static int test_x509_kem(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (test_x509_key_generate() != 1) goto err;
|
||||
@@ -569,6 +611,7 @@ int main(void)
|
||||
if (test_x509_private_key_info_to_der() != 1) goto err;
|
||||
if (test_x509_private_key_info_encrypt_to_der() != 1) goto err;
|
||||
if (test_x509_private_key_info_encrypt_to_pem() != 1) goto err;
|
||||
if (test_x509_private_key_info_decrypt_from_pem() != 1) goto err;
|
||||
if (test_x509_sign() != 1) goto err;
|
||||
if (test_x509_sign_sm9() != 1) goto err;
|
||||
if (test_x509_key_exchange() != 1) goto err;
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
#include <gmssl/error.h>
|
||||
|
||||
|
||||
static int client_ciphers[] = { TLS_cipher_sm4_gcm_sm3 };
|
||||
|
||||
static const char *http_get =
|
||||
"GET / HTTP/1.1\r\n"
|
||||
"Hostname: aaa\r\n"
|
||||
@@ -29,18 +27,34 @@ static const char *options = "-host str [-port num] [-cacert file] [-cert file -
|
||||
static const char *help =
|
||||
"Options\n"
|
||||
"\n"
|
||||
" -host str Server's hostname\n"
|
||||
" -port num Server's port number, default 443\n"
|
||||
" -cacert file Root CA certificate\n"
|
||||
" -cert file Client's certificate chain in PEM format\n"
|
||||
" -key file Client's encrypted private key in PEM format\n"
|
||||
" -pass str Password to decrypt private key\n"
|
||||
" -sess_in Load server's session ticket file\n"
|
||||
" -sess_out Save server's session ticket file\n"
|
||||
" -psk_identity str Identity of pre_shared_key\n"
|
||||
" -psk hex Pre-shared key in HEX format\n"
|
||||
" -early_data file Send early data\n"
|
||||
" -host str Server's hostname\n"
|
||||
" -port num Server's port number, default 443\n"
|
||||
" -cipher_suite str Supported cipher suites, may appear multiple times, higher priority first\n"
|
||||
" -supported_group str Supported elliptic curves, may appear multiple times, higher priority first\n"
|
||||
" -sig_alg str Supported signature algorithms\n"
|
||||
" -max_key_exchanges num Number of key exchanges in key_share extension\n"
|
||||
" -cacert file Root CA certificate\n"
|
||||
" -cert file Client's certificate chain in PEM format\n"
|
||||
" -key file Client's encrypted private key in PEM format\n"
|
||||
" -pass str Password to decrypt private key\n"
|
||||
" -psk_ke Support PSK-only key exchange\n"
|
||||
" -psk_dhe_ke Support PSK with (EC)DHE key exchange\n"
|
||||
" -psk_identity str Identity of pre_shared_key\n"
|
||||
" -psk hex Pre-shared key in HEX format\n"
|
||||
" -sess_in Load server's session ticket file\n"
|
||||
" -sess_out Save server's session ticket file\n"
|
||||
" -early_data file Send early data, -psk_ke and/or -psk_dhe_ke should be set\n"
|
||||
"\n"
|
||||
"CipherSuites\n"
|
||||
" TLS_SM4_GCM_SM3 TLS 1.3\n"
|
||||
" TLS_AES_128_GCM_SHA256 TLS 1.3\n"
|
||||
" TLS_ECC_SM4_CBC_SM3 TLCP\n"
|
||||
" TLS_ECDHE_SM4_CBC_SM3 TLCP TLS 1.2\n"
|
||||
" TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 TLS 1.2\n"
|
||||
"\n"
|
||||
" -supported_group\n"
|
||||
" sm2p256v1\n"
|
||||
" prime256v1\n"
|
||||
"Examples\n"
|
||||
"\n"
|
||||
" gmssl sm2keygen -pass 1234 -out rootcakey.pem\n"
|
||||
@@ -96,6 +110,29 @@ int tls13_client_main(int argc, char *argv[])
|
||||
FILE *early_data_fp = NULL;
|
||||
int max_early_data_size = 0;
|
||||
|
||||
char *cipher_suite;
|
||||
int cipher;
|
||||
int cipher_suites[4];
|
||||
size_t cipher_suites_cnt = 0;
|
||||
|
||||
char *supported_group_name;
|
||||
int supported_group;
|
||||
int supported_groups[4];
|
||||
size_t supported_groups_cnt = 0;
|
||||
|
||||
char *max_key_exchanges = NULL;
|
||||
int max_key_exchanges_cnt;
|
||||
|
||||
char *sig_alg_name;
|
||||
int sig_alg;
|
||||
int sig_algs[4];
|
||||
size_t sig_algs_cnt = 0;
|
||||
|
||||
|
||||
int psk_ke = 0;
|
||||
int psk_dhe_ke = 0;
|
||||
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
if (argc < 1) {
|
||||
@@ -137,12 +174,67 @@ int tls13_client_main(int argc, char *argv[])
|
||||
} else if (!strcmp(*argv, "-psk")) {
|
||||
if (--argc < 1) goto bad;
|
||||
psk = *(++argv);
|
||||
} else if (!strcmp(*argv, "-psk_ke")) {
|
||||
psk_ke = 1;
|
||||
} else if (!strcmp(*argv, "-psk_dhe_ke")) {
|
||||
psk_dhe_ke = 1;
|
||||
} else if (!strcmp(*argv, "-early_data")) {
|
||||
if (--argc < 1) goto bad;
|
||||
early_data_file = *(++argv);
|
||||
} else if (!strcmp(*argv, "-max_early_data_size")) {
|
||||
if (--argc < 1) goto bad;
|
||||
max_early_data_size = atoi(*(++argv));
|
||||
} else if (!strcmp(*argv, "-cipher_suite")) {
|
||||
if (--argc < 1) goto bad;
|
||||
cipher_suite = *(++argv);
|
||||
if ((cipher = tls_cipher_suite_from_name(cipher_suite)) == 0) {
|
||||
error_print();
|
||||
fprintf(stderr, "%s: cipher suite '%s' not supported\n", prog, cipher_suite);
|
||||
return -1;
|
||||
}
|
||||
if (cipher_suites_cnt >= sizeof(cipher_suites)/sizeof(cipher_suites[0])) {
|
||||
error_print();
|
||||
fprintf(stderr, "%s: too much cipher suites\n", prog);
|
||||
return -1;
|
||||
}
|
||||
cipher_suites[cipher_suites_cnt] = cipher;
|
||||
cipher_suites_cnt++;
|
||||
} else if (!strcmp(*argv, "-supported_group")) {
|
||||
if (--argc < 1) goto bad;
|
||||
supported_group_name = *(++argv);
|
||||
if ((supported_group = tls_named_curve_from_name(supported_group_name)) == 0) {
|
||||
error_print();
|
||||
fprintf(stderr, "%s: supported_group '%s' not supported\n", prog, supported_group_name);
|
||||
return -1;
|
||||
}
|
||||
if (supported_groups_cnt >= sizeof(supported_groups)/sizeof(supported_groups[0])) {
|
||||
error_print();
|
||||
fprintf(stderr, "%s: too much supported_group\n", prog);
|
||||
return -1;
|
||||
}
|
||||
supported_groups[supported_groups_cnt++] = supported_group;
|
||||
} else if (!strcmp(*argv, "-sig_alg")) {
|
||||
if (--argc < 1) goto bad;
|
||||
sig_alg_name = *(++argv);
|
||||
if ((sig_alg = tls_signature_scheme_from_name(sig_alg_name)) == 0) {
|
||||
error_print();
|
||||
fprintf(stderr, "%s: sig_alg '%s' not supported\n", prog, sig_alg_name);
|
||||
return -1;
|
||||
}
|
||||
if (sig_algs_cnt >= sizeof(sig_algs)/sizeof(sig_algs[0])) {
|
||||
error_print();
|
||||
fprintf(stderr, "%s: too much sig_algs\n", prog);
|
||||
return -1;
|
||||
}
|
||||
sig_algs[sig_algs_cnt++] = sig_alg;
|
||||
} else if (!strcmp(*argv, "-max_key_exchanges")) {
|
||||
if (--argc < 1) goto bad;
|
||||
max_key_exchanges = *(++argv);
|
||||
max_key_exchanges_cnt = atoi(max_key_exchanges);
|
||||
if (max_key_exchanges_cnt < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "%s: invalid option '%s'\n", prog, *argv);
|
||||
return 1;
|
||||
@@ -168,8 +260,6 @@ bad:
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
||||
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
memset(&conn, 0, sizeof(conn));
|
||||
|
||||
@@ -186,11 +276,41 @@ bad:
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (tls_ctx_init(&ctx, TLS_protocol_tls13, TLS_client_mode) != 1
|
||||
|| tls_ctx_set_cipher_suites(&ctx, client_ciphers, sizeof(client_ciphers)/sizeof(client_ciphers[0])) != 1) {
|
||||
if (tls_ctx_init(&ctx, TLS_protocol_tls13, TLS_client_mode) != 1) {
|
||||
fprintf(stderr, "%s: context init error\n", prog);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!cipher_suites_cnt) {
|
||||
error_print();
|
||||
fprintf(stderr, "%s: option '-cipher_suite' required\n", prog);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (tls_ctx_set_cipher_suites(&ctx, cipher_suites, cipher_suites_cnt) != 1) {
|
||||
fprintf(stderr, "%s: context init error\n", prog);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (supported_groups_cnt > 0) {
|
||||
if (tls_ctx_set_supported_groups(&ctx, supported_groups, supported_groups_cnt) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (max_key_exchanges) {
|
||||
tls13_ctx_set_max_key_exchanges(&ctx, max_key_exchanges_cnt);
|
||||
}
|
||||
|
||||
|
||||
if (sig_algs_cnt > 0) {
|
||||
if (tls_ctx_set_signature_algorithms(&ctx, sig_algs, sig_algs_cnt) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (cacertfile) {
|
||||
if (tls_ctx_set_ca_certificates(&ctx, cacertfile, TLS_DEFAULT_VERIFY_DEPTH) != 1) {
|
||||
fprintf(stderr, "%s: context init error\n", prog);
|
||||
@@ -215,16 +335,31 @@ bad:
|
||||
return -1;
|
||||
}
|
||||
tls13_enable_pre_shared_key(&conn, 1);
|
||||
tls13_set_psk_key_exchange_modes(&conn, 1, 1);
|
||||
}
|
||||
|
||||
if (sess_out) {
|
||||
if (tls13_set_session_outfile(&conn, sess_out) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (psk_ke || psk_dhe_ke) {
|
||||
if (!sess_in && !psk) {
|
||||
fprintf(stderr, "%s: -sess_in or -psk is required\n", prog);
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
tls13_set_psk_key_exchange_modes(&conn, psk_ke, psk_dhe_ke);
|
||||
|
||||
fprintf(stderr, "conn->psk_key_exchange_modes: %d\n", conn.key_exchange_modes);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (psk) {
|
||||
if (!psk_identity) {
|
||||
fprintf(stderr, "%s: -psk_identity is required for every -psk\n", prog);
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
@@ -236,14 +371,14 @@ bad:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// support multiple pairs
|
||||
if (tls13_add_pre_shared_key(&conn, DIGEST_sm3(), (uint8_t *)psk_identity, strlen(psk_identity), psk_buf, psk_len, 0) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
tls13_enable_pre_shared_key(&conn, 1);
|
||||
tls13_set_psk_key_exchange_modes(&conn, 1, 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -251,6 +386,12 @@ bad:
|
||||
uint8_t early_data[8192];
|
||||
size_t early_data_len;
|
||||
|
||||
if (!psk_ke && !psk_dhe_ke) {
|
||||
error_print();
|
||||
fprintf(stderr, "%s: -early_data need -psk_ke and/or -psk_dhe_ke set\n", prog);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(early_data_fp = fopen(early_data_file, "rb"))) {
|
||||
error_print();
|
||||
return -1;
|
||||
|
||||
@@ -25,17 +25,37 @@ static const char *help =
|
||||
"Options\n"
|
||||
"\n"
|
||||
" -port num Listening port number, default 443\n"
|
||||
" -cipher_suite str Client's cipher suites, may appear multiple times, higher priority first\n"
|
||||
" -supported_group str Supported elliptic curves, may appear multiple times, higher priority first\n"
|
||||
" -sig_alg str Supported signature algorithms\n"
|
||||
" -cert file Server's certificate chain in PEM format\n"
|
||||
" -key file Server's encrypted private key in PEM format\n"
|
||||
" -pass str Password to decrypt private key\n"
|
||||
" -cacert file CA certificate for client certificate verification\n"
|
||||
" -new_session_ticket num Send NewSessionTicket <num> times\n"
|
||||
" -ticket_key hex Session ticket encrypt/decrypt key in HEX format\n"
|
||||
" -psk_ke Support PSK-only key exchange\n"
|
||||
" -psk_dhe_ke Support PSK with (EC)DHE key exchange\n"
|
||||
" -psk_identity str Identity of pre_shared_key\n"
|
||||
" -psk hex Pre-shared key in HEX format\n"
|
||||
" -early_data Accept EarlyData, support 0-RTT\n"
|
||||
" -max_early_data_size num Set extension max_early_data_size\n"
|
||||
"\n"
|
||||
" -cipher_suite options\n"
|
||||
" TLS_SM4_GCM_SM3 TLS 1.3\n"
|
||||
" TLS_AES_128_GCM_SHA256 TLS 1.3\n"
|
||||
" TLS_ECC_SM4_CBC_SM3 TLCP\n"
|
||||
" TLS_ECDHE_SM4_CBC_SM3 TLCP TLS 1.2\n"
|
||||
" TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 TLS 1.2\n"
|
||||
"\n"
|
||||
" -supported_group options\n"
|
||||
" sm2p256v1\n"
|
||||
" prime256v1\n"
|
||||
"\n"
|
||||
" -sig_alg options\n"
|
||||
" sm2sig_sm3\n"
|
||||
" ecdsa_secp256r1_sha256\n"
|
||||
"\n"
|
||||
"Examples\n"
|
||||
"\n"
|
||||
" gmssl sm2keygen -pass 1234 -out rootcakey.pem\n"
|
||||
@@ -83,6 +103,9 @@ int tls13_server_main(int argc , char **argv)
|
||||
char *ticket_key = NULL;
|
||||
uint8_t ticket_key_buf[16];
|
||||
|
||||
int psk_ke = 0;
|
||||
int psk_dhe_ke = 0;
|
||||
|
||||
// TODO: clean
|
||||
char *psk_identity = NULL;
|
||||
char *psk = NULL;
|
||||
@@ -92,6 +115,21 @@ int tls13_server_main(int argc , char **argv)
|
||||
int early_data = 0;
|
||||
int max_early_data_size = 0;
|
||||
|
||||
char *cipher_suite_name;
|
||||
int cipher_suite;
|
||||
int cipher_suites[4];
|
||||
size_t cipher_suites_cnt = 0;
|
||||
|
||||
char *supported_group_name;
|
||||
int supported_group;
|
||||
int supported_groups[4];
|
||||
size_t supported_groups_cnt = 0;
|
||||
|
||||
char *sig_alg_name;
|
||||
int sig_alg;
|
||||
int sig_algs[4];
|
||||
size_t sig_algs_cnt = 0;
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
@@ -126,6 +164,10 @@ int tls13_server_main(int argc , char **argv)
|
||||
} else if (!strcmp(*argv, "-ticket_key")) {
|
||||
if (--argc < 1) goto bad;
|
||||
ticket_key = *(++argv);
|
||||
} else if (!strcmp(*argv, "-psk_ke")) {
|
||||
psk_ke = 1;
|
||||
} else if (!strcmp(*argv, "-psk_dhe_ke")) {
|
||||
psk_dhe_ke = 1;
|
||||
} else if (!strcmp(*argv, "-psk_identity")) {
|
||||
if (--argc < 1) goto bad;
|
||||
psk_identity = *(++argv);
|
||||
@@ -137,6 +179,49 @@ int tls13_server_main(int argc , char **argv)
|
||||
} else if (!strcmp(*argv, "-max_early_data_size")) {
|
||||
if (--argc < 1) goto bad;
|
||||
max_early_data_size = atoi(*(++argv));
|
||||
} else if (!strcmp(*argv, "-cipher_suite")) {
|
||||
if (--argc < 1) goto bad;
|
||||
cipher_suite_name = *(++argv);
|
||||
if ((cipher_suite = tls_cipher_suite_from_name(cipher_suite_name)) == 0) {
|
||||
error_print();
|
||||
fprintf(stderr, "%s: cipher suite '%s' not supported\n", prog, cipher_suite_name);
|
||||
return -1;
|
||||
}
|
||||
if (cipher_suites_cnt >= sizeof(cipher_suites)/sizeof(cipher_suites[0])) {
|
||||
error_print();
|
||||
fprintf(stderr, "%s: too much cipher suites\n", prog);
|
||||
return -1;
|
||||
}
|
||||
cipher_suites[cipher_suites_cnt] = cipher_suite;
|
||||
cipher_suites_cnt++;
|
||||
} else if (!strcmp(*argv, "-supported_group")) {
|
||||
if (--argc < 1) goto bad;
|
||||
supported_group_name = *(++argv);
|
||||
if ((supported_group = tls_named_curve_from_name(supported_group_name)) == 0) {
|
||||
error_print();
|
||||
fprintf(stderr, "%s: supported_group '%s' not supported\n", prog, supported_group_name);
|
||||
return -1;
|
||||
}
|
||||
if (supported_groups_cnt >= sizeof(supported_groups)/sizeof(supported_groups[0])) {
|
||||
error_print();
|
||||
fprintf(stderr, "%s: too much supported_group\n", prog);
|
||||
return -1;
|
||||
}
|
||||
supported_groups[supported_groups_cnt++] = supported_group;
|
||||
} else if (!strcmp(*argv, "-sig_alg")) {
|
||||
if (--argc < 1) goto bad;
|
||||
sig_alg_name = *(++argv);
|
||||
if ((sig_alg = tls_signature_scheme_from_name(sig_alg_name)) == 0) {
|
||||
error_print();
|
||||
fprintf(stderr, "%s: sig_alg '%s' not supported\n", prog, sig_alg_name);
|
||||
return -1;
|
||||
}
|
||||
if (sig_algs_cnt >= sizeof(sig_algs)/sizeof(sig_algs[0])) {
|
||||
error_print();
|
||||
fprintf(stderr, "%s: too much sig_algs\n", prog);
|
||||
return -1;
|
||||
}
|
||||
sig_algs[sig_algs_cnt++] = sig_alg;
|
||||
} else {
|
||||
fprintf(stderr, "%s: invalid option '%s'\n", prog, *argv);
|
||||
return 1;
|
||||
@@ -147,19 +232,15 @@ bad:
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
// 服务器的证书
|
||||
if (!certfile) {
|
||||
fprintf(stderr, "%s: '-cert' option required\n", prog);
|
||||
return 1;
|
||||
}
|
||||
if (!keyfile) {
|
||||
fprintf(stderr, "%s: '-key' option required\n", prog);
|
||||
return 1;
|
||||
}
|
||||
if (!pass) {
|
||||
fprintf(stderr, "%s: '-pass' option required\n", prog);
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
|
||||
if (tls_socket_lib_init() != 1) {
|
||||
@@ -170,12 +251,51 @@ bad:
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
memset(&conn, 0, sizeof(conn));
|
||||
|
||||
if (tls_ctx_init(&ctx, TLS_protocol_tls13, TLS_server_mode) != 1
|
||||
|| tls_ctx_set_cipher_suites(&ctx, server_ciphers, sizeof(server_ciphers)/sizeof(int)) != 1
|
||||
|| tls_ctx_set_certificate_and_key(&ctx, certfile, keyfile, pass) != 1) {
|
||||
if (tls_ctx_init(&ctx, TLS_protocol_tls13, TLS_server_mode) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 应该判断有cert的时候才载入
|
||||
|
||||
if (certfile) {
|
||||
if (!keyfile) {
|
||||
fprintf(stderr, "%s: '-key' option required\n", prog);
|
||||
return 1;
|
||||
}
|
||||
if (!pass) {
|
||||
fprintf(stderr, "%s: '-pass' option required\n", prog);
|
||||
return 1;
|
||||
}
|
||||
if (tls_ctx_add_certificate_chain_and_key(&ctx, certfile, keyfile, pass) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cipher_suites_cnt) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (tls_ctx_set_cipher_suites(&ctx, cipher_suites, cipher_suites_cnt) != 1) {
|
||||
fprintf(stderr, "%s: context init error\n", prog);
|
||||
goto end;
|
||||
}
|
||||
if (supported_groups_cnt > 0) {
|
||||
if (tls_ctx_set_supported_groups(&ctx, supported_groups, supported_groups_cnt) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (sig_algs_cnt > 0) {
|
||||
if (tls_ctx_set_signature_algorithms(&ctx, sig_algs, sig_algs_cnt) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (cacertfile) {
|
||||
if (tls_ctx_set_ca_certificates(&ctx, cacertfile, TLS_DEFAULT_VERIFY_DEPTH) != 1) {
|
||||
error_print();
|
||||
@@ -248,6 +368,11 @@ restart:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (psk_ke || psk_dhe_ke) {
|
||||
// 对于服务器来说只是允许进行这些模式
|
||||
tls13_set_psk_key_exchange_modes(&conn, psk_ke, psk_dhe_ke);
|
||||
}
|
||||
|
||||
|
||||
if (psk) {
|
||||
if (!psk_identity) {
|
||||
|
||||
Reference in New Issue
Block a user