From f754b1222db81e20387e122f3a0467b0aee78621 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Sun, 5 Jun 2022 22:35:08 +0800 Subject: [PATCH] Update TLCP --- CMakeLists.txt | 23 +- demos/sm234demo.sh | 16 - include/gmssl/tls.h | 656 +++++++++++++------------- include/gmssl/x509.h | 9 + src/tlcp.c | 1043 +++++++++++++++++++++++++----------------- src/tls.c | 911 ++++++++++++++++++++++-------------- src/tls_trace.c | 71 ++- src/x509_cer.c | 167 ++++++- tools/certverify.c | 91 ++-- tools/gmssl.c | 2 + tools/tlcp_client.c | 44 +- tools/tlcp_server.c | 17 +- 12 files changed, 1860 insertions(+), 1190 deletions(-) delete mode 100755 demos/sm234demo.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index d58c7910..1c14ca90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,8 +63,8 @@ add_library( src/sm9_lib.c src/tlcp.c src/tls.c - src/tls12.c - src/tls13.c +# src/tls12.c +# src/tls13.c src/tls_trace.c src/version.c src/x509_alg.c @@ -122,11 +122,6 @@ add_executable( tools/certgen.c tools/certparse.c tools/certverify.c - tools/cmsdecrypt.c - tools/cmsencrypt.c - tools/cmsparse.c - tools/cmssign.c - tools/cmsverify.c tools/crlparse.c tools/crlverify.c tools/cmssign.c @@ -140,10 +135,10 @@ add_executable( tools/reqsign.c tools/tlcp_client.c tools/tlcp_server.c - tools/tls12_client.c - tools/tls12_server.c - tools/tls13_client.c - tools/tls13_server.c +# tools/tls12_client.c +# tools/tls12_server.c +# tools/tls13_client.c +# tools/tls13_server.c tools/sdfutil.c tools/skfutil.c ) @@ -260,8 +255,8 @@ target_link_libraries (x509_crltest LINK_PUBLIC gmssl) add_executable(zuctest tests/zuctest.c) target_link_libraries (zuctest LINK_PUBLIC gmssl) -add_executable(tlstest tests/tlstest.c) -target_link_libraries (tlstest LINK_PUBLIC gmssl) +#add_executable(tlstest tests/tlstest.c) +#target_link_libraries (tlstest LINK_PUBLIC gmssl) enable_testing() @@ -294,7 +289,7 @@ add_test(NAME sm2 COMMAND sm2test) add_test(NAME sm3 COMMAND sm3test) add_test(NAME sm4 COMMAND sm4test) add_test(NAME sm9 COMMAND sm9test) -add_test(NAME tls COMMAND tlstest) +#add_test(NAME tls COMMAND tlstest) add_test(NAME x509 COMMAND x509test) add_test(NAME x509_oid COMMAND x509_oidtest) add_test(NAME x509_alg COMMAND x509_algtest) diff --git a/demos/sm234demo.sh b/demos/sm234demo.sh deleted file mode 100755 index 786d6160..00000000 --- a/demos/sm234demo.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - - -ENC_KEY=`gmssl rand -outlen 16 -hex` -MAC_KEY=`gmssl rand -outlen 32 -hex` -IV=`gmssl rand -outlen 16 -hex` - -gmssl sm2keygen -pass 1234 -out sm2.pem -pubout sm2pub.pem - -echo "$ENC_KEY$MAC_KEY" | xxd -p -r | gmssl sm2encrypt -pubkey sm2pub.pem | xxd -p > out.bin -echo $IV >> out.bin -echo "plaintext" | gmssl sm4 -cbc -encrypt -key $ENC_KEY -iv $IV | xxd -p >> out.bin - - -# gmssl sm2decrypt -key sm2.pem -pass 1234 -in sm2.der - diff --git a/include/gmssl/tls.h b/include/gmssl/tls.h index ba96714f..a7f73394 100644 --- a/include/gmssl/tls.h +++ b/include/gmssl/tls.h @@ -65,6 +65,10 @@ extern "C" { typedef uint32_t uint24_t; +#define tls_uint8_size() 1 +#define tls_uint16_size() 2 +#define tls_uint24_size() 3 + 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); @@ -81,14 +85,6 @@ int tls_array_from_bytes(const uint8_t **data, size_t datalen, const uint8_t **i 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); int tls_uint24array_from_bytes(const uint8_t **data, size_t *datalen, const uint8_t **in, size_t *inlen); -int tls_array_copy_from_bytes(uint8_t *data, size_t datalen, const uint8_t **in, size_t *inlen); -int tls_uint8array_copy_from_bytes(uint8_t *data, size_t *datalen, size_t maxlen, const uint8_t **in, size_t *inlen); -int tls_uint16array_copy_from_bytes(uint8_t *data, size_t *datalen, size_t maxlen, const uint8_t **in, size_t *inlen); -int tls_uint24array_copy_from_bytes(uint8_t *data, size_t *datalen, size_t maxlen, const uint8_t **in, size_t *inlen); - - -#define TLCP_VERSION_MAJOR 1 -#define TLCP_VERSION_MINOR 1 typedef enum { @@ -105,6 +101,10 @@ typedef enum { TLS_version_dtls12 = 0xfefd, // {254, 253} } TLS_VERSION; +const char *tls_version_text(int version); + + +// 兼容GmSSL 2.5.4 typedef enum { TLS_cipher_null_with_null_null = 0x0000, TLS_cipher_sm4_gcm_sm3 = 0x00c6, @@ -125,6 +125,7 @@ typedef enum { GMSSL_cipher_ecdhe_sm2_with_sm4_gcm_sm3 = 0xe107, GMSSL_cipher_ecdhe_sm2_with_sm4_ccm_sm3 = 0xe108, GMSSL_cipher_ecdhe_sm2_with_zuc_sm3 = 0xe10d, + TLS_cipher_empty_renegotiation_info_scsv = 0x00ff, // TLS 1.3 ciphers (rfc 8446 p.133) @@ -136,16 +137,32 @@ typedef enum { } TLS_CIPHER_SUITE; +const char *tls_cipher_suite_name(int cipher); +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); + + typedef enum { - TLS_record_invalid = 0, // TLS 1.3 - TLS_record_change_cipher_spec = 20, - TLS_record_alert = 21, - TLS_record_handshake = 22, - TLS_record_application_data = 23, - TLS_record_heartbeat = 24, - TLS_record_tls12_cid = 25, + TLS_compression_null = 0, + TLS_compression_default = 1, +} TLS_COMPRESSION_METHOD; + +const char *tls_compression_method_name(int meth); + + +typedef enum { + TLS_record_invalid = 0, // TLS 1.3 + TLS_record_change_cipher_spec = 20, // 0x14 + TLS_record_alert = 21, // 0x15 + TLS_record_handshake = 22, // 0x16 + TLS_record_application_data = 23, // 0x17 + TLS_record_heartbeat = 24, // 0x18 + TLS_record_tls12_cid = 25, // 0x19 } TLS_RECORD_TYPE; +const char *tls_record_type_name(int type); + typedef enum { TLS_handshake_hello_request = 0, TLS_handshake_client_hello = 1, @@ -171,11 +188,11 @@ typedef enum { TLS_handshake_message_hash = 254, } TLS_HANDSHAKE_TYPE; -typedef enum { - TLS_compression_null = 0, - TLS_compression_default = 1, -} TLS_COMPRESSION_METHOD; +const char *tls_handshake_type_name(int type); + + +// 这里面应该有一个和OID类型的转换 typedef enum { TLS_cert_type_rsa_sign = 1, TLS_cert_type_dss_sign = 2, @@ -192,6 +209,9 @@ typedef enum { TLS_cert_type_ibc_params = 80, } TLS_CERTIFICATE_TYPE; +const char *tls_cert_type_name(int type); +int tls_cert_type_from_oid(int oid); + typedef enum { TLS_extension_server_name = 0, // tls 1.3 mandatory-to-implement TLS_extension_max_fragment_length = 1, @@ -252,60 +272,69 @@ typedef enum { TLS_extension_renegotiation_info = 65281, } TLS_EXTENSION_TYPE; + typedef enum { - TLS_point_uncompressed = 0, - TLS_point_ansix962_compressed_prime = 1, - TLS_point_ansix962_compressed_char2 = 2, + TLS_point_uncompressed = 0, + TLS_point_ansix962_compressed_prime = 1, + TLS_point_ansix962_compressed_char2 = 2, } TLS_EC_POINT_FORMAT; +const char *tls_ec_point_format_name(int format); + typedef enum { - TLS_curve_type_explicit_prime = 1, - TLS_curve_type_explicit_char2 = 2, - TLS_curve_type_named_curve = 3, + TLS_curve_type_explicit_prime = 1, + TLS_curve_type_explicit_char2 = 2, + TLS_curve_type_named_curve = 3, } TLS_CURVE_TYPE; -typedef enum { - TLS_curve_secp256k1 = 22, - TLS_curve_secp256r1 = 23, - TLS_curve_secp384r1 = 24, - TLS_curve_secp521r1 = 25, - TLS_curve_brainpoolp256r1 = 26, - TLS_curve_brainpoolp384r1 = 27, - TLS_curve_brainpoolp512r1 = 28, - TLS_curve_x25519 = 29, - TLS_curve_x448 = 99, //30, - TLS_curve_brainpoolp256r1tls13 = 31, - TLS_curve_brainpoolp384r1tls13 = 32, - TLS_curve_brainpoolp512r1tls13 = 33, - TLS_curve_sm2p256v1 = 30,//41, // in gmssl v2, is 30 -} TLS_NAMED_CURVE; +const char *tls_curve_type_name(int type); typedef enum { - TLS_sig_rsa_pkcs1_sha1 = 0x0201, - TLS_sig_ecdsa_sha1 = 0x0203, - TLS_sig_rsa_pkcs1_sha256 = 0x0401, - TLS_sig_ecdsa_secp256r1_sha256 = 0x0403, - TLS_sig_rsa_pkcs1_sha256_legacy = 0x0420, - TLS_sig_rsa_pkcs1_sha384 = 0x0501, - TLS_sig_ecdsa_secp384r1_sha384 = 0x0503, - TLS_sig_rsa_pkcs1_sha384_legacy = 0x0520, - TLS_sig_rsa_pkcs1_sha512 = 0x0601, - TLS_sig_ecdsa_secp521r1_sha512 = 0x0603, - TLS_sig_rsa_pkcs1_sha512_legacy = 0x0620, - TLS_sig_sm2sig_sm3 = 0x0707,//0x0708, // is 0707 in gmsslv2 - TLS_sig_rsa_pss_rsae_sha256 = 0x0804, - TLS_sig_rsa_pss_rsae_sha384 = 0x0805, - TLS_sig_rsa_pss_rsae_sha512 = 0x0806, - TLS_sig_ed25519 = 0x0807, - TLS_sig_ed448 = 0x0808, - TLS_sig_rsa_pss_pss_sha256 = 0x0809, - TLS_sig_rsa_pss_pss_sha384 = 0x080A, - TLS_sig_rsa_pss_pss_sha512 = 0x080B, + TLS_curve_secp256k1 = 22, + TLS_curve_secp256r1 = 23, + TLS_curve_secp384r1 = 24, + TLS_curve_secp521r1 = 25, + TLS_curve_brainpoolp256r1 = 26, + TLS_curve_brainpoolp384r1 = 27, + TLS_curve_brainpoolp512r1 = 28, + TLS_curve_x25519 = 29, + TLS_curve_x448 = 99, //30, + TLS_curve_brainpoolp256r1tls13 = 31, + TLS_curve_brainpoolp384r1tls13 = 32, + TLS_curve_brainpoolp512r1tls13 = 33, + TLS_curve_sm2p256v1 = 30,//41, // in gmssl v2, is 30 +} TLS_NAMED_CURVE; + +const char *tls_named_curve_name(int curve); + +typedef enum { + TLS_sig_rsa_pkcs1_sha1 = 0x0201, + TLS_sig_ecdsa_sha1 = 0x0203, + TLS_sig_rsa_pkcs1_sha256 = 0x0401, + TLS_sig_ecdsa_secp256r1_sha256 = 0x0403, + TLS_sig_rsa_pkcs1_sha256_legacy = 0x0420, + TLS_sig_rsa_pkcs1_sha384 = 0x0501, + TLS_sig_ecdsa_secp384r1_sha384 = 0x0503, + TLS_sig_rsa_pkcs1_sha384_legacy = 0x0520, + TLS_sig_rsa_pkcs1_sha512 = 0x0601, + TLS_sig_ecdsa_secp521r1_sha512 = 0x0603, + TLS_sig_rsa_pkcs1_sha512_legacy = 0x0620, + TLS_sig_sm2sig_sm3 = 0x0707,//0x0708, // is 0707 in gmsslv2 + TLS_sig_rsa_pss_rsae_sha256 = 0x0804, + TLS_sig_rsa_pss_rsae_sha384 = 0x0805, + TLS_sig_rsa_pss_rsae_sha512 = 0x0806, + TLS_sig_ed25519 = 0x0807, + TLS_sig_ed448 = 0x0808, + TLS_sig_rsa_pss_pss_sha256 = 0x0809, + TLS_sig_rsa_pss_pss_sha384 = 0x080A, + TLS_sig_rsa_pss_pss_sha512 = 0x080B, TLS_sig_ecdsa_brainpoolP256r1tls13_sha256 = 0x081A, TLS_sig_ecdsa_brainpoolP384r1tls13_sha384 = 0x081B, TLS_sig_ecdsa_brainpoolP512r1tls13_sha512 = 0x081C, } TLS_SIGNATURE_SCHEME; +const char *tls_signature_scheme_name(int scheme); + typedef enum { TLS_change_cipher_spec = 1, } TLS_CHANGE_CIPHER_SPEC_TYPE; @@ -316,91 +345,75 @@ typedef enum { } TLS_ALERT_LEVEL; typedef enum { - TLS_alert_close_notify = 0, - TLS_alert_unexpected_message = 10, - TLS_alert_bad_record_mac = 20, - TLS_alert_decryption_failed = 21, - TLS_alert_record_overflow = 22, - TLS_alert_decompression_failure = 30, - TLS_alert_handshake_failure = 40, - TLS_alert_no_certificate = 41, - TLS_alert_bad_certificate = 42, - TLS_alert_unsupported_certificate = 43, - TLS_alert_certificate_revoked = 44, - TLS_alert_certificate_expired = 45, - TLS_alert_certificate_unknown = 46, - TLS_alert_illegal_parameter = 47, - TLS_alert_unknown_ca = 48, - TLS_alert_access_denied = 49, - TLS_alert_decode_error = 50, - TLS_alert_decrypt_error = 51, - TLS_alert_export_restriction = 60, - TLS_alert_protocol_version = 70, - TLS_alert_insufficient_security = 71, - TLS_alert_internal_error = 80, - TLS_alert_user_canceled = 90, - TLS_alert_no_renegotiation = 100, - TLS_alert_unsupported_site2site = 200, - TLS_alert_no_area = 201, - TLS_alert_unsupported_areatype = 202, - TLS_alert_bad_ibcparam = 203, - TLS_alert_unsupported_ibcparam = 204, - TLS_alert_identity_need = 205, + TLS_alert_close_notify = 0, // Fatal + TLS_alert_unexpected_message = 10, // Fatal 和正确实现的对方交互时不应出现此错误 + TLS_alert_bad_record_mac = 20, // Fatal 密文Mac验证错误、CBC密文长度错误、CBC密文填充错误 + TLS_alert_decryption_failed = 21, // 作废 + TLS_alert_record_overflow = 22, // Fatal TLSCiphertext.length > 2^14 + 2048, TLSCompressed.length > 2^14 + 1024 + TLS_alert_decompression_failure = 30, // 本实现不支持压缩 + TLS_alert_handshake_failure = 40, // Fatal, 安全参数协商失败,TLCP服务器没有找到合适的套件 + TLS_alert_no_certificate = 41, // 作废 + TLS_alert_bad_certificate = 42, // Any 我们使用Fatal + TLS_alert_unsupported_certificate = 43, // Any 我们使用Fatal + TLS_alert_certificate_revoked = 44, // Any 我们使用Fatal + TLS_alert_certificate_expired = 45, // Any 我们使用Fatal + TLS_alert_certificate_unknown = 46, // Any 我们使用Fatal, 大概没有CA证书 + TLS_alert_illegal_parameter = 47, // Fatal, 似乎TLCP不会遇到此情况 + TLS_alert_unknown_ca = 48, // Fatal + TLS_alert_access_denied = 49, // Fatal,??? + TLS_alert_decode_error = 50, // Fatal, 正确实现不会出现此问题,可能由网络故障导致 + TLS_alert_decrypt_error = 51, // Fatal, 验签失败、Finished验证失败 + TLS_alert_export_restriction = 60, // 作废 + TLS_alert_protocol_version = 70, // Fatal + TLS_alert_insufficient_security = 71, // Fatal,如果客户端Ciphers均强度不足,则服务器返回此错误 + TLS_alert_internal_error = 80, // Fatal + TLS_alert_user_canceled = 90, // Warning, 一般后面要跟一个close_notify,似乎没有必要 + TLS_alert_no_renegotiation = 100, // Warning,客户端收到HelloRequest, 服务器在握手后收到ClientHello + TLS_alert_unsupported_extension = 110, // Fatal, 服务器ServerHello返回不在ClientHello范围内的扩展 + TLS_alert_unsupported_site2site = 200, + TLS_alert_no_area = 201, + TLS_alert_unsupported_areatype = 202, + TLS_alert_bad_ibcparam = 203, + TLS_alert_unsupported_ibcparam = 204, + TLS_alert_identity_need = 205, } TLS_ALERT_DESCRIPTION; +/* +TLCP ServerCertificate + 如果不是SM2的证书,那么返回 unsupported_certificate + 如果证书链有问题,比如不是双证书(比如少一个加密证书),bad_certificate + 如果证书本身验证错误 bad_certificate + 如果证书链没有对应的ROOTCA证书,那么返回certificate_unknown + 如果证书过期 + 如果证书作废:必须要结合CRL等 + 如果证书扩展没有通过验证,返回bad_certificate,Warning/Fatal +*/ - - -#define TLS_RECORD_MAX_PLAINDATA_SIZE 16384 // 2^14 -#define TLS_RECORD_MAX_DATA_SIZE 18432 // 2^24 + 2048 -#define TLS_RECORD_MAX_SIZE 18437 // 5 + (2^24 + 2048) - -#define TLS_MAX_RECORD_SIZE 18437 // 5 + (2^24 + 2048) - -#define TLS_MAX_SIGNATURE_SIZE SM2_MAX_SIGNATURE_SIZE - -#define TLS_MAX_EXTENSIONS_SIZE 512 -#define TLS_MAX_CERT_SIZE 1024 -#define TLS_MAX_CERTIFICATES_SIZE 2048 -#define TLS_MAX_SERVER_CERTS_SIZE 2048 - -#define TLS_MAX_HANDSHAKES_SIZE 4096 - - - - - - - - - +// Ciphers int tls_seq_num_incr(uint8_t seq_num[8]); - int tls_prf(const uint8_t *secret, size_t secretlen, const char *label, const uint8_t *seed, size_t seedlen, const uint8_t *more, size_t morelen, size_t outlen, uint8_t *out); +int tls13_hkdf_extract(const DIGEST *digest, const uint8_t salt[32], const uint8_t in[32], uint8_t out[32]); +int tls13_hkdf_expand_label(const DIGEST *digest, const uint8_t secret[32], + const char *label, const uint8_t *context, size_t context_len, + size_t outlen, uint8_t *out); +int tls13_derive_secret(const uint8_t secret[32], const char *label, const DIGEST_CTX *dgst_ctx, uint8_t out[32]); + +#define TLS_MAX_PADDING_SIZE (1 + 255) +#define TLS_MAC_SIZE 32 // 目前只支持SM3、SHA256 + int tls_cbc_encrypt(const SM3_HMAC_CTX *hmac_ctx, const SM4_KEY *enc_key, const uint8_t seq_num[8], const uint8_t header[5], const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); - int tls_cbc_decrypt(const SM3_HMAC_CTX *hmac_ctx, const SM4_KEY *dec_key, const uint8_t seq_num[8], const uint8_t header[5], const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); - -const char *tls_record_type_name(int type); -int tls_record_version(const uint8_t *record); -int tls_record_length(const uint8_t *record); - -const char *tls_version_text(int version); - -int tls_record_set_version(uint8_t *record, int version); - - int tls_record_encrypt(const SM3_HMAC_CTX *hmac_ctx, const SM4_KEY *cbc_key, const uint8_t seq_num[8], const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); @@ -408,153 +421,119 @@ int tls_record_decrypt(const SM3_HMAC_CTX *hmac_ctx, const SM4_KEY *cbc_key, const uint8_t seq_num[8], const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen); - -int tls_record_send(const uint8_t *record, size_t recordlen, int sock); -int tls_record_recv(uint8_t *record, size_t *recordlen, int sock); - - int tls_random_generate(uint8_t random[32]); int tls_random_print(FILE *fp, const uint8_t random[32], int format, int indent); + int tls_pre_master_secret_generate(uint8_t pre_master_secret[48], int version); int tls_pre_master_secret_print(FILE *fp, const uint8_t pre_master_secret[48], int format, int indent); +int tls_secrets_print(FILE *fp, + const uint8_t *pre_master_secret, size_t pre_master_secret_len, + const uint8_t client_random[32], const uint8_t server_random[32], + const uint8_t master_secret[48], + const uint8_t *key_block, size_t key_block_len, + int format, int indent); -int tls_cipher_suite_in_list(int cipher, const int *list, size_t list_count); -const char *tlcp_cipher_suite_name(int cipher); -const char *tls_cipher_suite_name(int cipher); -const char *tls_compression_method_name(int meth); +// Record + +typedef struct { + uint8_t type; + uint8_t version[2]; + uint8_t length[2]; +} TLS_RECORD_HEADER; + +#define TLS_RECORD_HEADER_SIZE 5 +#define TLS_MAX_PLAINTEXT_SIZE (1 << 14) // 2^14 = 16384 +#define TLS_MAX_COMPRESSED_SIZE ((1 << 14) + 1024) // 17408 +#define TLS_MAX_CIPHERTEXT_SIZE ((1 << 14) + 2048) // 18432 +#define TLS_MAX_RECORD_SIZE (TLS_RECORD_HEADER_SIZE + TLS_MAX_CIPHERTEXT_SIZE) // 18437 + +int tls_record_type(const uint8_t *record); +int tls_record_version(const uint8_t *record); +int tls_record_length(const uint8_t *record); +#define tls_record_data(record) ((record)+4) + +int tls_record_set_type(uint8_t *record, int type); +int tls_record_set_version(uint8_t *record, int version); + +// format +// 0-7 比特表示通用输出格式 +// 8-16 比特表示密码套件 format |= (cipher_suite << 8) +// 因为握手消息ServerKeyExchange, ClientKeyExchange的解析依赖当前密码套件 +int tls_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int format, int indent); +int tlcp_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int format, int indent); + +int tls_record_send(const uint8_t *record, size_t recordlen, int sock); +int tls_record_recv(uint8_t *record, size_t *recordlen, int sock); +int tls12_record_recv(uint8_t *record, size_t *recordlen, int sock); + +// Handshake +typedef struct { + uint8_t type; + uint8_t length[3]; +} TLS_HANDSHAKE_HEADER; + +#define TLS_HANDSHAKE_HEADER_SIZE 4 +#define TLS_MAX_HANDSHAKE_DATA_SIZE (TLS_MAX_PLAINTEXT_SIZE - TLS_HANDSHAKE_HEADER_SIZE) + +#define tls_handshake_data(p) ((p)+5) int tls_record_set_handshake(uint8_t *record, size_t *recordlen, int type, const uint8_t *data, size_t datalen); int tls_record_get_handshake(const uint8_t *record, int *type, const uint8_t **data, size_t *datalen); +int tls_handshake_print(FILE *fp, const uint8_t *handshake, size_t handshakelen, int format, int indent); +/* +HelloRequest +TLCP 服务器均不支持 HelloRequest 握手消息 +TLS 服务器 + 在握手阶段收到 HelloRequest 消息则中止握手 + 在建立连接之后收到,忽略或者同时返回一个no_renegotiation warning alert +*/ +int tls_hello_request_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent); + +// ClientHello, ServerHello +#define TLS_MIN_SESSION_ID_SIZE 0 +#define TLS_MAX_SESSION_ID_SIZE 32 int tls_record_set_handshake_client_hello(uint8_t *record, size_t *recordlen, int client_version, const uint8_t random[32], const uint8_t *session_id, size_t session_id_len, const int *cipher_suites, size_t cipher_suites_count, const uint8_t *exts, size_t exts_len); - int tls_record_get_handshake_client_hello(const uint8_t *record, - int *client_version, uint8_t random[32], - uint8_t *session_id, size_t *session_id_len, - int *cipher_suites, size_t *cipher_suites_count, - uint8_t *exts, size_t *exts_len); - + int *client_version, const uint8_t **random, + const uint8_t **session_id, size_t *session_id_len, + const uint8_t **cipher_suites, size_t *cipher_suites_len, + const uint8_t **exts, size_t *exts_len); int tls_client_hello_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent); int tls_record_set_handshake_server_hello(uint8_t *record, size_t *recordlen, int server_version, const uint8_t random[32], - const uint8_t *session_id, size_t session_id_len, int cipher_suite, - const uint8_t *exts, size_t exts_len); - + const uint8_t *session_id, size_t session_id_len, + int cipher_suite, const uint8_t *exts, size_t exts_len); int tls_record_get_handshake_server_hello(const uint8_t *record, - int *version, uint8_t random[32], uint8_t *session_id, size_t *session_id_len, - int *cipher_suite, uint8_t *exts, size_t *exts_len); - + int *version, const uint8_t **random, const uint8_t **session_id, size_t *session_id_len, + int *cipher_suite, const uint8_t **exts, size_t *exts_len); int tls_server_hello_print(FILE *fp, const uint8_t *server_hello, size_t len, int format, int indent); +// Extensions +int tls_ext_signature_algors_to_bytes(const int *algors, size_t algors_count, + uint8_t **out, size_t *outlen); + + +// Certificate int tls_record_set_handshake_certificate(uint8_t *record, size_t *recordlen, const uint8_t *certs, size_t certslen); -int tls_record_set_handshake_certificate_from_pem(uint8_t *record, size_t *recordlen, FILE *fp); +// 这个函数比较特殊,是直接解析了证书链,而不是返回指针 +// 应该提供一个独立的解析函数来解析TLS的证书链 int tls_record_get_handshake_certificate(const uint8_t *record, uint8_t *certs, size_t *certslen); -int tls_certificate_get_subject_names(const uint8_t *certs, size_t certslen, uint8_t *names, size_t *nameslen); -int tls_certificate_get_public_keys(const uint8_t *certs, size_t certslen, SM2_KEY *sign_key, SM2_KEY *enc_key); -int tls_certificate_print(FILE *fp, const uint8_t *certs, size_t certslen, int format, int indent); - -int tls_certificate_chain_verify(const uint8_t *certs, size_t certslen, FILE *ca_certs_fp, int depth); - -int tls_certificate_get_first(const uint8_t *data, size_t datalen, const uint8_t **cert, size_t *certlen); -int tls_certificate_get_second(const uint8_t *data, size_t datalen, const uint8_t **cert, size_t *certlen); - - -// 应该把所有TLCP协议的内容放到一起 -int tlcp_record_set_handshake_server_key_exchange_pke(uint8_t *record, size_t *recordlen, - const uint8_t *sig, size_t siglen); -int tlcp_record_get_handshake_server_key_exchange_pke(const uint8_t *record, - uint8_t *sig, size_t *siglen); -int tlcp_server_key_exchange_pke_print(FILE *fp, const uint8_t *sig, size_t siglen, int format, int indent); - - - +// ServerKeyExchange int tls_server_key_exchange_print(FILE *fp, const uint8_t *ske, size_t skelen, int format, int indent); -const char *tls_cert_type_name(int type); - -#define TLS_MAX_CERTIFICATE_TYPES 16 -#define TLS_MAX_CA_NAMES_SIZE 256 - - -int tls_record_set_handshake_certificate_request(uint8_t *record, size_t *recordlen, - const int *cert_types, size_t cert_types_count, - const uint8_t *ca_names, size_t ca_names_len); - -int tls_record_get_handshake_certificate_request(const uint8_t *record, - int *cert_types, size_t *cert_types_count, - uint8_t *ca_names, size_t *ca_names_len); - - - -int tls_certificate_request_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent); -int tls_record_set_handshake_server_hello_done(uint8_t *record, size_t *recordlen); -int tls_record_get_handshake_server_hello_done(const uint8_t *record); -int tls_server_hello_done_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent); - -int tls_record_set_handshake_client_key_exchange_pke(uint8_t *record, size_t *recordlen, - const uint8_t *enced_pms, size_t enced_pms_len); -int tls_record_get_handshake_client_key_exchange_pke(const uint8_t *record, - uint8_t *enced_pms, size_t *enced_pms_len); -int tls_client_key_exchange_pke_print(FILE *fp, const uint8_t *cke, size_t ckelen, int format, int indent); -int tls_client_key_exchange_print(FILE *fp, const uint8_t *cke, size_t ckelen, int format, int indent); -int tls_record_set_handshake_certificate_verify(uint8_t *record, size_t *recordlen, - const uint8_t *sig, size_t siglen); -int tls_record_get_handshake_certificate_verify(const uint8_t *record, - uint8_t *sig, size_t *siglen); -int tls_certificate_verify_print(FILE *fp, const uint8_t *p, size_t len, int format, int indent); - -int tls_record_set_handshake_finished(uint8_t *record, size_t *recordlen, - const uint8_t verify_data[12]); -int tls_record_get_handshake_finished(const uint8_t *record, uint8_t verify_data[12]); -int tls_finished_print(FILE *fp, const uint8_t *a, size_t len, int format, int indent); -const char *tls_handshake_type_name(int type); -int tls_handshake_print(FILE *fp, const uint8_t *handshake, size_t handshakelen, int format, int indent); - - -const char *tls_alert_level_name(int level); -const char *tls_alert_description_text(int description); -int tls_alert_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent); - - -int tls_record_set_alert(uint8_t *record, size_t *recordlen, - int alert_level, - int alert_description); -int tls_record_get_alert(const uint8_t *record, - int *alert_level, - int *alert_description); - -const char *tls_change_cipher_spec_text(int change_cipher_spec); -int tls_record_set_change_cipher_spec(uint8_t *record, size_t *recordlen); -int tls_record_get_change_cipher_spec(const uint8_t *record); -int tls_change_cipher_spec_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent); - -int tls_record_set_application_data(uint8_t *record, size_t *recordlen, - const uint8_t *data, size_t datalen); -int tls_record_get_application_data(uint8_t *record, - const uint8_t **data, size_t *datalen); -int tls_application_data_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent); - - -int tls_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int format, int indent); - - - -const char *tls_ec_point_format_name(int format); -const char *tls_curve_type_name(int type); -const char *tls_named_curve_name(int curve); -const char *tls_signature_scheme_name(int scheme); int tls_sign_server_ecdh_params(const SM2_KEY *server_sign_key, const uint8_t client_random[32], const uint8_t server_random[32], int curve, const SM2_POINT *point, uint8_t *sig, size_t *siglen); @@ -567,19 +546,124 @@ int tls_record_get_handshake_server_key_exchange_ecdhe(const uint8_t *record, int *curve, SM2_POINT *point, uint8_t *sig, size_t *siglen); int tls_server_key_exchange_ecdhe_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent); + +int tlcp_record_set_handshake_server_key_exchange_pke(uint8_t *record, size_t *recordlen, + const uint8_t *sig, size_t siglen); +int tlcp_record_get_handshake_server_key_exchange_pke(const uint8_t *record, + const uint8_t **sig, size_t *siglen); +int tlcp_server_key_exchange_pke_print(FILE *fp, const uint8_t *sig, size_t siglen, int format, int indent); + + + +// CertificateRequest +#define TLS_MAX_CERTIFICATE_TYPES 16 +#define TLS_MAX_CA_NAMES_SIZE 512 + +int tls_authorities_from_certs(uint8_t *ca_names, size_t *ca_names_len, size_t maxlen, const uint8_t *certs, size_t certslen); +int tls_authorities_issued_certificate(const uint8_t *ca_names, size_t ca_namelen, const uint8_t *certs, size_t certslen); +int tls_cert_types_accepted(const uint8_t *types, size_t types_len, const uint8_t *client_certs, size_t client_certs_len); + +int tls_record_set_handshake_certificate_request(uint8_t *record, size_t *recordlen, + const uint8_t *cert_types, size_t cert_types_len, + const uint8_t *ca_names, size_t ca_names_len); +int tls_record_get_handshake_certificate_request(const uint8_t *record, + const uint8_t **cert_types, size_t *cert_types_len, + const uint8_t **ca_names, size_t *ca_names_len); +int tls_certificate_request_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent); + + +// ServerHelloDone +int tls_record_set_handshake_server_hello_done(uint8_t *record, size_t *recordlen); +int tls_record_get_handshake_server_hello_done(const uint8_t *record); +int tls_server_hello_done_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent); + +// ClientKeyExchange +int tls_record_set_handshake_client_key_exchange_pke(uint8_t *record, size_t *recordlen, + const uint8_t *enced_pms, size_t enced_pms_len); +int tls_record_get_handshake_client_key_exchange_pke(const uint8_t *record, + const uint8_t **enced_pms, size_t *enced_pms_len); +int tls_client_key_exchange_pke_print(FILE *fp, const uint8_t *cke, size_t ckelen, int format, int indent); +int tls_client_key_exchange_print(FILE *fp, const uint8_t *cke, size_t ckelen, int format, int indent); + int tls_record_set_handshake_client_key_exchange_ecdhe(uint8_t *record, size_t *recordlen, const SM2_POINT *point); int tls_record_get_handshake_client_key_exchange_ecdhe(const uint8_t *record, SM2_POINT *point); int tls_client_key_exchange_ecdhe_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent); +// CertificateVerify +int tls_record_set_handshake_certificate_verify(uint8_t *record, size_t *recordlen, + const uint8_t *sig, size_t siglen); +int tls_record_get_handshake_certificate_verify(const uint8_t *record, + const uint8_t **sig, size_t *siglen); +int tls_certificate_verify_print(FILE *fp, const uint8_t *p, size_t len, int format, int indent); -int tls12_record_recv(uint8_t *record, size_t *recordlen, int sock); +typedef enum { + TLS_client_verify_client_hello = 0, + TLS_client_verify_server_hello = 1, + TLS_client_verify_server_certificate = 2, + TLS_client_verify_server_key_exchange = 3, + TLS_client_verify_cert_request = 4, + TLS_client_verify_server_hello_done = 5, + TLS_client_verify_client_certificate = 6, + TLS_client_verify_client_key_exchange = 7, +} TLS_CLIENT_VERIFY_INDEX; + +typedef struct { + TLS_CLIENT_VERIFY_INDEX index; + uint8_t *handshake[8]; // Record data only, no record header + size_t handshake_len[8]; +} TLS_CLIENT_VERIFY_CTX; + +int tls_client_verify_init(TLS_CLIENT_VERIFY_CTX *ctx); +int tls_client_verify_update(TLS_CLIENT_VERIFY_CTX *ctx, const uint8_t *handshake, size_t handshake_len); +int tls_client_verify_finish(TLS_CLIENT_VERIFY_CTX *ctx, const uint8_t *sig, size_t siglen, const SM2_KEY *public_key); +void tls_client_verify_cleanup(TLS_CLIENT_VERIFY_CTX *ctx); + +// Finished +#define TLS_VERIFY_DATA_SIZE 12 // TLS 1.3或者其他版本支持更长的verify_data +#define TLS_FINISHED_RECORD_SIZE (TLS_RECORD_HEADER_SIZE + TLS_HANDSHAKE_HEADER_SIZE + TLS_VERIFY_DATA_SIZE) // 21 +#define TLS_FINISHED_RECORD_BUF_SIZE (TLS_FINISHED_RECORD_SIZE + TLS_MAC_SIZE + TLS_MAX_PADDING_SIZE) // 309 + +int tls_record_set_handshake_finished(uint8_t *record, size_t *recordlen, + const uint8_t *verify_data, size_t verify_data_len); +int tls_record_get_handshake_finished(const uint8_t *record, + const uint8_t **verify_data, size_t *verify_data_len); +int tls_finished_print(FILE *fp, const uint8_t *a, size_t len, int format, int indent); +// Alert +typedef struct { + uint8_t level; + uint8_t description; +} TLS_ALERT; + +#define TLS_ALERT_RECORD_SIZE (TLS_RECORD_HEADER_SIZE + 2) + +const char *tls_alert_level_name(int level); +const char *tls_alert_description_text(int description); +int tls_alert_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent); + +int tls_record_set_alert(uint8_t *record, size_t *recordlen, int alert_level, int alert_description); +int tls_record_get_alert(const uint8_t *record, int *alert_level, int *alert_description); +// ChangeCipherSpec +typedef struct { + uint8_t type; +} TLS_CHANGE_CIPHER_SPEC; +const char *tls_change_cipher_spec_text(int change_cipher_spec); +int tls_change_cipher_spec_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent); +int tls_record_set_change_cipher_spec(uint8_t *record, size_t *recordlen); +int tls_record_get_change_cipher_spec(const uint8_t *record); + +// ApplicationData +int tls_record_set_application_data(uint8_t *record, size_t *recordlen, + const uint8_t *data, size_t datalen); +int tls_record_get_application_data(uint8_t *record, + const uint8_t **data, size_t *datalen); +int tls_application_data_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent); @@ -607,22 +691,7 @@ int tls_ctx_set_shutdown_mode(TLS_CTX *ctx, int mode); - - - - -typedef struct { - int version; - int cipher_suite; - uint8_t session_id[32]; - size_t session_id_len; - uint8_t peer_certs[1600]; - size_t peer_certs_len; - uint8_t master_secret[48]; - int client_cert_verify_result; - time_t start_time; - int timeout_secs; -} TLS_SESSION; +#define TLS_MAX_CERTIFICATES_SIZE 2048 typedef struct { int sock; @@ -632,12 +701,17 @@ typedef struct { int cipher_suite; uint8_t session_id[32]; size_t session_id_len; - uint8_t server_certs[TLS_MAX_CERTIFICATES_SIZE]; // + uint8_t server_certs[TLS_MAX_CERTIFICATES_SIZE]; // 动态的可能会好一点 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; + int client_cert_verify_result; + uint8_t master_secret[48]; + uint8_t key_block[96]; SM3_HMAC_CTX client_write_mac_ctx; SM3_HMAC_CTX server_write_mac_ctx; @@ -646,17 +720,12 @@ typedef struct { uint8_t client_seq_num[8]; uint8_t server_seq_num[8]; - uint8_t key_block[96]; // 这个似乎不应该放在这里 + // 这个有点问题,我们暂时还是不支持 BLOCK_CIPHER_KEY client_write_key; // used in tls13.c BLOCK_CIPHER_KEY server_write_key; // used in tls13.c - uint8_t client_write_iv[12]; // 同样 - uint8_t server_write_iv[12]; + uint8_t client_write_iv[12]; // tls13 + uint8_t server_write_iv[12]; // tls13 - uint8_t record[TLS_MAX_RECORD_SIZE]; - uint8_t handshakes[TLS_MAX_HANDSHAKES_SIZE]; - size_t handshakes_len; - - int do_trace; } TLS_CONNECT; @@ -664,12 +733,10 @@ int tls_init(TLS_CONNECT *conn, const TLS_CTX *ctx); int tls_set_fd(TLS_CONNECT *conn, int sock); int tls_get_verify_result(TLS_CONNECT *conn, int *result); +int tls_send_alert (TLS_CONNECT *conn, int alert); +int tls_send_warning(TLS_CONNECT *conn, int alert); - - - -// 客户端证书应该是预置的 int tlcp_connect(TLS_CONNECT *conn, const char *hostname, int port, FILE *ca_certs_fp, FILE *client_certs_fp, const SM2_KEY *client_sign_key); @@ -677,60 +744,37 @@ int tlcp_accept(TLS_CONNECT *conn, int port, FILE *server_certs_fp, const SM2_KEY *server_sign_key, const SM2_KEY *server_enc_key, FILE *client_cacerts_fp, uint8_t *client_cert_verify_buf, size_t client_cert_verify_buflen); - -int tls_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen); -int tls_recv(TLS_CONNECT *conn, uint8_t *data, size_t *datalen); // 发送、接收的数据量以单独的接口提供 - - - - int tls12_connect(TLS_CONNECT *conn, const char *hostname, int port, FILE *ca_certs_fp, FILE *client_certs_fp, const SM2_KEY *client_sign_key); - int tls12_accept(TLS_CONNECT *conn, int port, FILE *certs_fp, const SM2_KEY *server_sign_key, FILE *client_cacerts_fp, uint8_t *handshakes_buf, size_t handshakes_buflen); - - - - int tls13_connect(TLS_CONNECT *conn, const char *hostname, int port, FILE *ca_certs_fp, FILE *client_certs_fp, const SM2_KEY *client_sign_key); - - int tls13_accept(TLS_CONNECT *conn, int port, FILE *certs_fp, const SM2_KEY *server_sign_key, FILE *client_cacerts_fp); - -int tls_secrets_print(FILE *fp, - const uint8_t *pre_master_secret, size_t pre_master_secret_len, - const uint8_t client_random[32], const uint8_t server_random[32], - const uint8_t master_secret[48], - const uint8_t *key_block, size_t key_block_len, - int format, int indent); - - -int tls_ext_signature_algors_to_bytes(const int *algors, size_t algors_count, - uint8_t **out, size_t *outlen); +int tls_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen); +int tls_recv(TLS_CONNECT *conn, uint8_t *data, size_t *datalen); int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t padding_len); int tls13_recv(TLS_CONNECT *conn, uint8_t *data, size_t *datalen); - -int tls13_hkdf_extract(const DIGEST *digest, const uint8_t salt[32], const uint8_t in[32], uint8_t out[32]); -int tls13_hkdf_expand_label(const DIGEST *digest, const uint8_t secret[32], - const char *label, const uint8_t *context, size_t context_len, - size_t outlen, uint8_t *out); -int tls13_derive_secret(const uint8_t secret[32], const char *label, const DIGEST_CTX *dgst_ctx, uint8_t out[32]); - - - int tls_shutdown(TLS_CONNECT *conn); -#define tls_trace printf + +#if 1 +#define tls_trace(s) fprintf(stderr,(s)) +#define tls_record_trace(fp,rec,reclen,fmt,ind) tls_record_print(fp,rec,reclen,fmt,ind) +#define tlcp_record_trace(fp,rec,reclen,fmt,ind) tlcp_record_print(fp,rec,reclen,fmt,ind) +#else +#define tls_trace(s) +#define tls_record_trace(fp,rec,reclen,fmt,ind) +#define tlcp_record_trace(fp,rec,reclen,fmt,ind) +#endif #ifdef __cplusplus diff --git a/include/gmssl/x509.h b/include/gmssl/x509.h index dcb92891..1b95bc32 100644 --- a/include/gmssl/x509.h +++ b/include/gmssl/x509.h @@ -199,6 +199,9 @@ int x509_name_set(uint8_t *d, size_t *dlen, size_t maxlen, int x509_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); int x509_name_get_value_by_type(const uint8_t *d, size_t dlen, int oid, int *tag, const uint8_t **val, size_t *vlen); int x509_name_get_common_name(const uint8_t *d, size_t dlen, int *tag, const uint8_t **val, size_t *vlen); +int x509_name_equ(const uint8_t *a, size_t alen, const uint8_t *b, size_t blen); + +int x509_names_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); /* SubjectPublicKeyInfo ::= SEQUENCE { @@ -360,6 +363,7 @@ int x509_certs_from_pem(uint8_t *d, size_t *dlen, size_t maxlen, FILE *fp); int x509_certs_get_count(const uint8_t *d, size_t dlen, size_t *cnt); int x509_certs_get_cert_by_index(const uint8_t *d, size_t dlen, int index, const uint8_t **cert, size_t *certlen); int x509_certs_get_cert_by_subject(const uint8_t *d, size_t dlen, const uint8_t *subject, size_t subject_len, const uint8_t **cert, size_t *certlen); +int x509_certs_get_last(const uint8_t *d, size_t dlen, const uint8_t **cert, size_t *certlen); int x509_certs_get_cert_by_issuer_and_serial_number( const uint8_t *certs, size_t certs_len, @@ -367,6 +371,11 @@ int x509_certs_get_cert_by_issuer_and_serial_number( const uint8_t *serial, size_t serial_len, const uint8_t **cert, size_t *cert_len); +int x509_certs_verify(const uint8_t *certs, size_t certslen, + const uint8_t *rootcerts, size_t rootcertslen, int depth, int *verify_result); +int x509_certs_verify_tlcp(const uint8_t *certs, size_t certslen, + const uint8_t *rootcerts, size_t rootcertslen, int depth, int *verify_result); +int x509_certs_get_subjects(const uint8_t *certs, size_t certslen, uint8_t *names, size_t *nameslen); int x509_certs_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); diff --git a/src/tlcp.c b/src/tlcp.c index a32c58b9..239f2273 100644 --- a/src/tlcp.c +++ b/src/tlcp.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,6 +48,7 @@ #include +#include #include #include #include @@ -59,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -69,31 +71,43 @@ static const int tlcp_ciphers[] = { TLCP_cipher_ecc_sm4_cbc_sm3 }; static const size_t tlcp_ciphers_count = sizeof(tlcp_ciphers)/sizeof(tlcp_ciphers[0]); +int tlcp_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int format, int indent) +{ + // 目前只支持TLCP的ECC公钥加密套件,因此不论用哪个套件解析都是一样的 + // 如果未来支持ECDHE套件,可以将函数改为宏,直接传入 (conn->cipher_suite << 8) + format |= tlcp_ciphers[0] << 8; + return tls_record_print(fp, record, recordlen, format, indent); +} int tlcp_record_set_handshake_server_key_exchange_pke(uint8_t *record, size_t *recordlen, const uint8_t *sig, size_t siglen) { int type = TLS_handshake_server_key_exchange; - uint8_t *p = record + 5 + 4; - size_t hslen = 0; + uint8_t *p; + size_t len = 0; - if (!record || !recordlen - || !sig || !siglen || siglen > 2048) { + if (!record || !recordlen || !sig || !siglen) { error_print(); return -1; } - if (record[1] != TLCP_VERSION_MAJOR || record[2] != TLCP_VERSION_MINOR) { + if (siglen > SM2_MAX_SIGNATURE_SIZE) { error_print(); return -1; } - tls_uint16_to_bytes(siglen, &p, &hslen); - tls_array_to_bytes(sig, siglen, &p, &hslen); - tls_record_set_handshake(record, recordlen, type, NULL, hslen); + if (tls_record_version(record) != TLS_version_tlcp) { + error_print(); + return -1; + } + p = tls_handshake_data(tls_record_data(record)); + // 注意TLCP的ServerKeyExchange中的签名值需要封装在uint16array中 + // 但是CertificateVerify中直接装载签名值DER + tls_uint16array_to_bytes(sig, siglen, &p, &len); + tls_record_set_handshake(record, recordlen, type, NULL, len); return 1; } int tlcp_record_get_handshake_server_key_exchange_pke(const uint8_t *record, - uint8_t *sig, size_t *siglen) + const uint8_t **sig, size_t *siglen) { int type; const uint8_t *p; @@ -103,7 +117,6 @@ int tlcp_record_get_handshake_server_key_exchange_pke(const uint8_t *record, error_print(); return -1; } - if (tls_record_get_handshake(record, &type, &p, &len) != 1) { error_print(); return -1; @@ -112,296 +125,340 @@ int tlcp_record_get_handshake_server_key_exchange_pke(const uint8_t *record, error_print(); return -1; } - if (record[1] != TLCP_VERSION_MAJOR || record[2] != TLCP_VERSION_MINOR) { + if (tls_record_version(record) != TLS_version_tlcp) { error_print(); return -1; } - if (tls_uint16array_copy_from_bytes(sig, siglen, *siglen, &p, &len) != 1 - || len > 0) { + if (tls_uint16array_from_bytes(sig, siglen, &p, &len) != 1) { + error_print(); + return -1; + } + if (len) { error_print(); return -1; } return 1; } -int tlcp_certificate_chain_verify(const uint8_t *data, size_t datalen, FILE *ca_certs_fp, int depth) +int tlcp_server_key_exchange_pke_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent) { - const uint8_t *certs; - size_t certslen; + const uint8_t *sig; + size_t siglen; - const uint8_t *sign_cert; - size_t sign_cert_len; - const uint8_t *enc_cert; - size_t enc_cert_len; - const uint8_t *ca_cert; - size_t ca_cert_len; - const uint8_t *sign_issuer; - size_t sign_issuer_len; - const uint8_t *enc_issuer; - size_t enc_issuer_len; - - if (tls_uint24array_from_bytes(&certs, &certslen, &data, &datalen) != 1 - || datalen > 0) { + format_print(fp, format, indent, "ServerKeyExchange\n"); + indent += 4; + if (tls_uint16array_from_bytes(&sig, &siglen, &data, &datalen) != 1) { error_print(); return -1; } - if (tls_uint24array_from_bytes(&sign_cert, &sign_cert_len, &certs, &certslen) != 1) { + format_bytes(fp, format, indent, "signature", sig, siglen); + if (datalen) { error_print(); return -1; } - if (tls_uint24array_from_bytes(&enc_cert, &enc_cert_len, &certs, &certslen) != 1) { - error_print(); - return -1; - } - if (x509_cert_get_issuer(sign_cert, sign_cert_len, &sign_issuer, &sign_issuer_len) != 1 - || x509_cert_get_issuer(enc_cert, enc_cert_len, &enc_issuer, &enc_issuer_len) != 1 - || asn1_check(sign_issuer_len == enc_issuer_len) != 1 - || asn1_check(memcmp(sign_issuer, enc_issuer, enc_issuer_len) == 0) != 1) { - error_print(); - return -1; - } - - if (certslen) { - const uint8_t *chain = certs; - size_t chainlen = certslen; - if (tls_uint24array_from_bytes(&ca_cert, &ca_cert_len, &certs, &certslen) != 1) { - error_print(); - return -1; - } - if (x509_cert_verify_by_ca_cert(sign_cert, sign_cert_len, ca_cert, ca_cert_len, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1 - || x509_cert_verify_by_ca_cert(enc_cert, enc_cert_len, ca_cert, ca_cert_len, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { - error_print(); - return -1; - } - if (tls_certificate_chain_verify(chain, chainlen, ca_certs_fp, depth - 1) != 1) { - error_print(); - return -1; - } - } else { - - /* - if (x509_cert_from_pem_by_subject(&ca_cert, ca_certs_fp, &sign_cert.tbs_certificate.issuer) != 1 - || x509_certificate_verify_by_certificate(&sign_cert, &ca_cert) != 1) { - error_print(); - return -1; - } - if (x509_certificate_from_pem_by_name(&ca_cert, ca_certs_fp, &enc_cert.tbs_certificate.issuer) != 1 - || x509_certificate_verify_by_certificate(&enc_cert, &ca_cert) != 1) { - error_print(); - return -1; - } - */ - } return 1; } int tlcp_connect(TLS_CONNECT *conn, const char *hostname, int port, FILE *ca_certs_fp, FILE *client_certs_fp, const SM2_KEY *client_sign_key) { - uint8_t record[1600]; - size_t recordlen; - uint8_t finished[256]; - size_t finishedlen; - int type; - const uint8_t *data; - size_t datalen; + int ret = -1; + uint8_t record[TLS_MAX_RECORD_SIZE]; + uint8_t finished_record[TLS_FINISHED_RECORD_BUF_SIZE]; + size_t recordlen, finished_record_len; uint8_t client_random[32]; uint8_t server_random[32]; - const uint8_t *server_enc_cert; - size_t server_enc_cert_len; - SM2_KEY server_enc_key; + int version; + int cipher_suite; + const uint8_t *random; + const uint8_t *session_id; + size_t session_id_len; + const uint8_t *exts; + size_t exts_len; + SM2_KEY server_sign_key; - SM2_SIGN_CTX verify_ctx; // for server_key_exchange signature verification - SM2_SIGN_CTX sign_ctx; // for certificate_verify signature generation - uint8_t sig[TLS_MAX_SIGNATURE_SIZE]; - size_t siglen = sizeof(sig); + SM2_KEY server_enc_key; + SM2_SIGN_CTX verify_ctx; + SM2_SIGN_CTX sign_ctx; + const uint8_t *sig; + size_t siglen; uint8_t pre_master_secret[48]; - uint8_t enced_pre_master_secret[256]; + uint8_t enced_pre_master_secret[SM2_MAX_CIPHERTEXT_SIZE]; size_t enced_pre_master_secret_len; SM3_CTX sm3_ctx; SM3_CTX tmp_sm3_ctx; uint8_t sm3_hash[32]; - uint8_t verify_data[12]; + const uint8_t *verify_data; + size_t verify_data_len; uint8_t local_verify_data[12]; + int handshake_type; + const uint8_t *server_enc_cert; + size_t server_enc_cert_len; + uint8_t server_enc_cert_lenbuf[3]; + const uint8_t *cp; + uint8_t *p; + size_t len; + + int depth = 5; + int alert = 0; + int verify_result; + struct sockaddr_in server; + + + memset(conn, 0, sizeof(*conn)); + conn->is_client = 1; + + // 设置CA证书(和客户端证书) + if (ca_certs_fp) { + if (x509_certs_from_pem(conn->ca_certs, &conn->ca_certs_len, 2048, ca_certs_fp) != 1) { + error_print(); + goto end; + } + } + if (client_sign_key) { + if (!client_certs_fp) { + error_print(); + goto end; + } + if (x509_certs_from_pem(conn->client_certs, &conn->client_certs_len, 2048, client_certs_fp) != 1) { + error_print(); + goto end; + } + } + + // 初始化记录缓冲 + tls_record_set_version(record, TLS_version_tlcp); + tls_record_set_version(finished_record, TLS_version_tlcp); + + // 准备Finished Context(和ClientVerify) + sm3_init(&sm3_ctx); + if (client_sign_key) + sm2_sign_init(&sign_ctx, client_sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH); + + // 设置Socket server.sin_addr.s_addr = inet_addr(hostname); server.sin_family = AF_INET; server.sin_port = htons(port); if ((conn->sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { error_print(); - return -1; + goto end; } if (connect(conn->sock, (struct sockaddr *)&server , sizeof(server)) < 0) { error_print(); - return -1; + goto end; } - conn->is_client = 1; - sm3_init(&sm3_ctx); - if (client_sign_key) - sm2_sign_init(&sign_ctx, client_sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH); - tls_record_set_version(record, TLS_version_tlcp); - tls_record_set_version(finished, TLS_version_tlcp); - - tls_trace("send ClientHello\n"); + // send ClientHello tls_random_generate(client_random); if (tls_record_set_handshake_client_hello(record, &recordlen, TLS_version_tlcp, client_random, NULL, 0, tlcp_ciphers, tlcp_ciphers_count, NULL, 0) != 1) { error_print(); - return -1; + goto end; } - tls_record_print(stderr, record, recordlen, 0, 0); + tls_trace("send ClientHello\n"); + tlcp_record_trace(stderr, record, recordlen, 0, 0); if (tls_record_send(record, recordlen, conn->sock) != 1) { error_print(); - return -1; + goto end; } sm3_update(&sm3_ctx, record + 5, recordlen - 5); if (client_sign_key) sm2_sign_update(&sign_ctx, record + 5, recordlen - 5); + // recv ServerHello tls_trace("recv ServerHello\n"); - if (tls_record_recv(record, &recordlen, conn->sock) != 1 - || tls_record_version(record) != TLS_version_tlcp) { + if (tls_record_recv(record, &recordlen, conn->sock) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_version(record) != TLS_version_tlcp) { + error_print(); + tls_send_alert(conn, TLS_alert_protocol_version); + goto end; } - tls_record_print(stderr, record, recordlen, 0, 0); if (tls_record_get_handshake_server_hello(record, - &conn->version, server_random, conn->session_id, &conn->session_id_len, - &conn->cipher_suite, NULL, 0) != 1) { + &version, &random, &session_id, &session_id_len, &cipher_suite, + &exts, &exts_len) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } - if (conn->version != TLS_version_tlcp) { + if (version != TLS_version_tlcp) { + tls_send_alert(conn, TLS_alert_protocol_version); error_print(); - return -1; + goto end; } - if (tls_cipher_suite_in_list(conn->cipher_suite, tlcp_ciphers, tlcp_ciphers_count) != 1) { + if (tls_cipher_suite_in_list(cipher_suite, tlcp_ciphers, tlcp_ciphers_count) != 1) { + tls_send_alert(conn, TLS_alert_handshake_failure); error_print(); - return -1; + goto end; } + if (exts) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + memcpy(server_random, random, 32); + memcpy(conn->session_id, session_id, session_id_len); + conn->cipher_suite = cipher_suite; sm3_update(&sm3_ctx, record + 5, recordlen - 5); if (client_sign_key) sm2_sign_update(&sign_ctx, record + 5, recordlen - 5); + // recv ServerCertificate tls_trace("recv ServerCertificate\n"); if (tls_record_recv(record, &recordlen, conn->sock) != 1 || tls_record_version(record) != TLS_version_tlcp) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } - tls_record_print(stderr, record, recordlen, 0, 0); + tlcp_record_trace(stderr, record, recordlen, 0, 0); if (tls_record_get_handshake_certificate(record, conn->server_certs, &conn->server_certs_len) != 1) { error_print(); - return -1; - } - if (tlcp_certificate_chain_verify(conn->server_certs, conn->server_certs_len, ca_certs_fp, 5) != 1) { - error_print(); - return -1; - } - if (tls_certificate_get_public_keys(conn->server_certs, conn->server_certs_len, - &server_sign_key, &server_enc_key) != 1) { - error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } sm3_update(&sm3_ctx, record + 5, recordlen - 5); if (client_sign_key) sm2_sign_update(&sign_ctx, record + 5, recordlen - 5); + // verify ServerCertificate + if (x509_certs_verify_tlcp(conn->server_certs, conn->server_certs_len, + conn->ca_certs, conn->ca_certs_len, depth, &verify_result) != 1) { + error_print(); + tls_send_alert(conn, alert); + goto end; + } + + // recv ServerKeyExchange tls_trace("recv ServerKeyExchange\n"); if (tls_record_recv(record, &recordlen, conn->sock) != 1 || tls_record_version(record) != TLS_version_tlcp) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } - tls_record_print(stderr, record, recordlen, conn->cipher_suite << 8, 0); - if (tlcp_record_get_handshake_server_key_exchange_pke(record, sig, &siglen) != 1) { + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tlcp_record_get_handshake_server_key_exchange_pke(record, &sig, &siglen) != 1) { + tls_send_alert(conn, TLS_alert_unexpected_message); error_print(); - return -1; + goto end; } sm3_update(&sm3_ctx, record + 5, recordlen - 5); if (client_sign_key) sm2_sign_update(&sign_ctx, record + 5, recordlen - 5); - tls_trace("process ServerKeyExchange\n"); - if (tls_certificate_get_second(conn->server_certs, conn->server_certs_len, - &server_enc_cert, &server_enc_cert_len) != 1) { + // verify ServerKeyExchange + if (x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 0, &cp, &len) != 1 + || x509_cert_get_subject_public_key(cp, len, &server_sign_key) != 1 + || x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 1, &server_enc_cert, &server_enc_cert_len) != 1 + || x509_cert_get_subject_public_key(server_enc_cert, server_enc_cert_len, &server_enc_key) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_bad_certificate); + goto end; } + p = server_enc_cert_lenbuf; len = 0; + tls_uint24_to_bytes(server_enc_cert_len, &p, &len); if (sm2_verify_init(&verify_ctx, &server_sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1 || sm2_verify_update(&verify_ctx, client_random, 32) != 1 || sm2_verify_update(&verify_ctx, server_random, 32) != 1 + || sm2_verify_update(&verify_ctx, server_enc_cert_lenbuf, 3) != 1 || sm2_verify_update(&verify_ctx, server_enc_cert, server_enc_cert_len) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_internal_error); + goto end; } - if ( sm2_verify_finish(&verify_ctx, sig, siglen) != 1) { - error_puts("ServerKeyExchange signature verification failure"); - return -1; + if (sm2_verify_finish(&verify_ctx, sig, siglen) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_decrypt_error); + goto end; } + // recv CertificateRequest or ServerHelloDone if (tls_record_recv(record, &recordlen, conn->sock) != 1 || tls_record_version(record) != TLS_version_tlcp - || tls_record_get_handshake(record, &type, &data, &datalen) != 1) { + || tls_record_get_handshake(record, &handshake_type, &cp, &len) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } - if (type == TLS_handshake_certificate_request) { - tls_trace("recv CertificateRequest\n"); - int cert_types[TLS_MAX_CERTIFICATE_TYPES]; - size_t cert_types_count;; - uint8_t ca_names[TLS_MAX_CA_NAMES_SIZE]; + if (handshake_type == TLS_handshake_certificate_request) { + const uint8_t *cert_types; + size_t cert_types_len; + const uint8_t *ca_names; size_t ca_names_len; - if (tls_record_get_handshake_certificate_request(record, - cert_types, &cert_types_count, - ca_names, &ca_names_len) != 1) { - error_print(); - return -1; - } - tls_record_print(stderr, record, recordlen, 0, 0); - sm3_update(&sm3_ctx, record + 5, recordlen - 5); - if (client_sign_key) - sm2_sign_update(&sign_ctx, record + 5, recordlen - 5); + // recv CertificateRequest + tls_trace("recv CertificateRequest\n"); + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_get_handshake_certificate_request(record, + &cert_types, &cert_types_len, &ca_names, &ca_names_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if(!client_sign_key) { + error_print(); + tls_send_alert(conn, TLS_alert_internal_error); + goto end; + } + if (tls_cert_types_accepted(cert_types, cert_types_len, conn->client_certs, conn->client_certs_len) != 1 + || tls_authorities_issued_certificate(ca_names, ca_names_len, conn->client_certs, conn->client_certs_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_unsupported_certificate); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + sm2_sign_update(&sign_ctx, record + 5, recordlen - 5); + + // recv ServerHelloDone if (tls_record_recv(record, &recordlen, conn->sock) != 1 || tls_record_version(record) != TLS_version_tlcp) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } } else { - memset(&sign_ctx, 0, sizeof(SM2_SIGN_CTX)); client_sign_key = NULL; } tls_trace("recv ServerHelloDone\n"); - tls_record_print(stderr, record, recordlen, 0, 0); + tlcp_record_trace(stderr, record, recordlen, 0, 0); if (tls_record_get_handshake_server_hello_done(record) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } sm3_update(&sm3_ctx, record + 5, recordlen - 5); - if (client_sign_key) { + if (client_sign_key) sm2_sign_update(&sign_ctx, record + 5, recordlen - 5); + // send ClientCertificate + if (client_sign_key) { tls_trace("send ClientCertificate\n"); - if (tls_record_set_handshake_certificate_from_pem(record, &recordlen, client_certs_fp) != 1) { + if (tls_record_set_handshake_certificate(record, &recordlen, conn->client_certs, conn->client_certs_len) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_internal_error); + goto end; } - tls_record_print(stderr, record, recordlen, 0, 0); + tlcp_record_trace(stderr, record, recordlen, 0, 0); if (tls_record_send(record, recordlen, conn->sock) != 1) { error_print(); - return -1; + goto end; } sm3_update(&sm3_ctx, record + 5, recordlen - 5); sm2_sign_update(&sign_ctx, record + 5, recordlen - 5); } + // generate MASTER_SECRET tls_trace("generate secrets\n"); if (tls_pre_master_secret_generate(pre_master_secret, TLS_version_tlcp) != 1 || tls_prf(pre_master_secret, 48, "master secret", @@ -411,12 +468,14 @@ int tlcp_connect(TLS_CONNECT *conn, const char *hostname, int port, server_random, 32, client_random, 32, 96, conn->key_block) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_internal_error); + goto end; } sm3_hmac_init(&conn->client_write_mac_ctx, conn->key_block, 32); sm3_hmac_init(&conn->server_write_mac_ctx, conn->key_block + 32, 32); sm4_set_encrypt_key(&conn->client_write_enc_key, conn->key_block + 64); sm4_set_decrypt_key(&conn->server_write_enc_key, conn->key_block + 80); + /* format_bytes(stderr, 0, 4, "PRE_MASTER_SECRET", pre_master_secret, 48); format_bytes(stderr, 0, 4, "MASTER_SECRET", conn->master_secret, 48); format_bytes(stderr, 0, 4, "CLIENT_WRITE_MAC_KEY", conn->key_block, 32); @@ -424,435 +483,532 @@ int tlcp_connect(TLS_CONNECT *conn, const char *hostname, int port, format_bytes(stderr, 0, 4, "CLIENT_WRITE_ENC_KEY", conn->key_block + 64, 16); format_bytes(stderr, 0, 4, "SERVER_WRITE_ENC_KEY", conn->key_block + 80, 16); format_print(stderr, 0, 0, "\n"); + */ + // send ClientKeyExchange tls_trace("send ClientKeyExchange\n"); if (sm2_encrypt(&server_enc_key, pre_master_secret, 48, - enced_pre_master_secret, &enced_pre_master_secret_len) != 1) { + enced_pre_master_secret, &enced_pre_master_secret_len) != 1 + || tls_record_set_handshake_client_key_exchange_pke(record, &recordlen, + enced_pre_master_secret, enced_pre_master_secret_len) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_internal_error); + goto end; } - if (tls_record_set_handshake_client_key_exchange_pke(record, &recordlen, - enced_pre_master_secret, enced_pre_master_secret_len) != 1) { - error_print(); - return -1; - } - tls_record_print(stderr, record, recordlen, conn->cipher_suite << 8, 0); + tlcp_record_trace(stderr, record, recordlen, 0, 0); if (tls_record_send(record, recordlen, conn->sock) != 1) { error_print(); - return -1; + goto end; } sm3_update(&sm3_ctx, record + 5, recordlen - 5); if (client_sign_key) sm2_sign_update(&sign_ctx, record + 5, recordlen - 5); + // send CertificateVerify if (client_sign_key) { tls_trace("send CertificateVerify\n"); - sm2_sign_finish(&sign_ctx, sig, &siglen); - if (tls_record_set_handshake_certificate_verify(record, &recordlen, sig, siglen) != 1) { + uint8_t sigbuf[SM2_MAX_SIGNATURE_SIZE]; + if (sm2_sign_finish(&sign_ctx, sigbuf, &siglen) != 1 + || tls_record_set_handshake_certificate_verify(record, &recordlen, sigbuf, siglen) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_internal_error); + goto end; } - tls_record_print(stderr, record, recordlen, 0, 0); + tlcp_record_trace(stderr, record, recordlen, 0, 0); if (tls_record_send(record, recordlen, conn->sock) != 1) { error_print(); - return -1; + goto end; } sm3_update(&sm3_ctx, record + 5, recordlen - 5); } + // send [ChangeCipherSpec] tls_trace("send [ChangeCipherSpec]\n"); if (tls_record_set_change_cipher_spec(record, &recordlen) !=1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_internal_error); + goto end; } + tlcp_record_trace(stderr, record, recordlen, 0, 0); if (tls_record_send(record, recordlen, conn->sock) != 1) { error_print(); - return -1; + goto end; } - tls_record_print(stderr, record, recordlen, 0, 0); + // send Client Finished tls_trace("send Finished\n"); memcpy(&tmp_sm3_ctx, &sm3_ctx, sizeof(sm3_ctx)); sm3_finish(&tmp_sm3_ctx, sm3_hash); - if (tls_prf(conn->master_secret, 48, "client finished", - sm3_hash, 32, NULL, 0, - sizeof(verify_data), verify_data) != 1) { + sm3_hash, 32, NULL, 0, sizeof(local_verify_data), local_verify_data) != 1 + || tls_record_set_handshake_finished(finished_record, &finished_record_len, + local_verify_data, sizeof(local_verify_data)) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_internal_error); + goto end; } - if (tls_record_set_handshake_finished(finished, &finishedlen, verify_data) != 1) { - error_print(); - return -1; - } - tls_record_print(stderr, finished, finishedlen, 0, 0); - sm3_update(&sm3_ctx, finished + 5, finishedlen - 5); + tlcp_record_trace(stderr, finished_record, finished_record_len, 0, 0); + sm3_update(&sm3_ctx, finished_record + 5, finished_record_len - 5); + // encrypt Client Finished + tls_trace("encrypt Finished\n"); if (tls_record_encrypt(&conn->client_write_mac_ctx, &conn->client_write_enc_key, - conn->client_seq_num, finished, finishedlen, record, &recordlen) != 1) { + conn->client_seq_num, finished_record, finished_record_len, record, &recordlen) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_internal_error); + goto end; } + tlcp_record_trace(stderr, record, recordlen, (1<<24), 0); // 强制打印密文原数据 tls_seq_num_incr(conn->client_seq_num); if (tls_record_send(record, recordlen, conn->sock) != 1) { error_print(); - return -1; + goto end; } + // [ChangeCipherSpec] tls_trace("recv [ChangeCipherSpec]\n"); if (tls_record_recv(record, &recordlen, conn->sock) != 1 || tls_record_version(record) != TLS_version_tlcp) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } + tlcp_record_trace(stderr, record, recordlen, 0, 0); if (tls_record_get_change_cipher_spec(record) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } - tls_record_print(stderr, record, recordlen, 0, 0); + // Finished tls_trace("recv Finished\n"); if (tls_record_recv(record, &recordlen, conn->sock) != 1 || tls_record_version(record) != TLS_version_tlcp) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } + if (recordlen > sizeof(finished_record)) { + error_print(); // 解密可能导致 finished_record 溢出 + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, (1<<24), 0); // 强制打印密文原数据 + tls_trace("decrypt Finished\n"); if (tls_record_decrypt(&conn->server_write_mac_ctx, &conn->server_write_enc_key, - conn->server_seq_num, record, recordlen, finished, &finishedlen) != 1) { + conn->server_seq_num, record, recordlen, finished_record, &finished_record_len) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; } - tls_record_print(stderr, finished, finishedlen, 0, 0); + tlcp_record_trace(stderr, finished_record, finished_record_len, 0, 0); tls_seq_num_incr(conn->server_seq_num); - if (tls_record_get_handshake_finished(finished, verify_data) != 1) { + if (tls_record_get_handshake_finished(finished_record, &verify_data, &verify_data_len) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + if (verify_data_len != sizeof(local_verify_data)) { + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } sm3_finish(&sm3_ctx, sm3_hash); if (tls_prf(conn->master_secret, 48, "server finished", - sm3_hash, 32, NULL, 0, - sizeof(local_verify_data), local_verify_data) != 1) { + sm3_hash, 32, NULL, 0, sizeof(local_verify_data), local_verify_data) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_internal_error); + goto end; } - if (memcmp(local_verify_data, verify_data, 12) != 0) { - error_puts("server_finished.verify_data verification failure"); - return -1; + if (memcmp(verify_data, local_verify_data, sizeof(local_verify_data)) != 0) { + error_print(); + tls_send_alert(conn, TLS_alert_decrypt_error); + goto end; } + tls_trace("Connection established!\n"); - tls_trace("++++ Connection established\n"); + + conn->version = TLS_version_tlcp; + conn->cipher_suite = cipher_suite; + + ret = 1; + +end: + gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); + gmssl_secure_clear(pre_master_secret, sizeof(pre_master_secret)); return 1; } + int tlcp_accept(TLS_CONNECT *conn, int port, FILE *certs_fp, const SM2_KEY *server_sign_key, const SM2_KEY *server_enc_key, FILE *client_cacerts_fp, uint8_t *handshakes_buf, size_t handshakes_buflen) { - uint8_t *handshakes = handshakes_buf; - size_t handshakeslen = 0; - uint8_t record[TLS_MAX_RECORD_SIZE]; - size_t recordlen; - uint8_t finished[256]; - size_t finishedlen = sizeof(finished); - - uint8_t client_random[32]; - uint8_t server_random[32]; - uint8_t session_id[32]; - size_t session_id_len; - int client_ciphers[12] = {0}; - size_t client_ciphers_count = sizeof(client_ciphers)/sizeof(client_ciphers[0]); - const uint8_t *server_enc_cert; - size_t server_enc_certlen; - SM2_KEY client_sign_key; - SM2_SIGN_CTX sign_ctx; - uint8_t sig[TLS_MAX_SIGNATURE_SIZE]; - size_t siglen = sizeof(sig); - uint8_t enced_pms[256]; - size_t enced_pms_len = sizeof(enced_pms); - uint8_t pre_master_secret[48]; - size_t pre_master_secret_len = 48; - SM3_CTX sm3_ctx; - SM3_CTX tmp_sm3_ctx; - uint8_t sm3_hash[32]; - uint8_t verify_data[12]; - uint8_t local_verify_data[12]; - size_t i; + int ret = -1; int sock; struct sockaddr_in server_addr; struct sockaddr_in client_addr; socklen_t client_addrlen; - if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - error_print(); - return -1; - } - server_addr.sin_family = AF_INET; - server_addr.sin_addr.s_addr = INADDR_ANY; - server_addr.sin_port = htons(port); + int client_verify = 0; + + uint8_t record[TLS_MAX_RECORD_SIZE]; + uint8_t finished_record[TLS_FINISHED_RECORD_BUF_SIZE]; // 解密可能导致前面的record被覆盖 + size_t recordlen, finished_record_len; + const int server_ciphers[] = { TLCP_cipher_ecc_sm4_cbc_sm3 }; // 未来应该支持GCM/CBC两个套件 + + // ClientHello, ServerHello + uint8_t client_random[32]; + uint8_t server_random[32]; + int version; + const uint8_t *random; + const uint8_t *session_id; // TLCP服务器忽略客户端SessionID,也不主动设置SessionID + size_t session_id_len; + const uint8_t *client_ciphers; + size_t client_ciphers_len; + const uint8_t *exts; + size_t exts_len; + + // ServerKeyExchange + const uint8_t *server_enc_cert; + size_t server_enc_cert_len; + uint8_t server_enc_cert_lenbuf[3]; + SM2_SIGN_CTX sign_ctx; + uint8_t sigbuf[SM2_MAX_SIGNATURE_SIZE]; + size_t siglen; + + // ClientCertificate, CertificateVerify + TLS_CLIENT_VERIFY_CTX client_verify_ctx; + SM2_KEY client_sign_key; + const uint8_t *sig; + const int verify_depth = 5; + int verify_result; + + // ClientKeyExchange + const uint8_t *enced_pms; + size_t enced_pms_len; + uint8_t pre_master_secret[SM2_MAX_PLAINTEXT_SIZE]; // sm2_decrypt 保证输出不会溢出 + size_t pre_master_secret_len; + + // Finished + SM3_CTX sm3_ctx; + SM3_CTX tmp_sm3_ctx; + uint8_t sm3_hash[32]; + uint8_t local_verify_data[12]; + const uint8_t *verify_data; + size_t verify_data_len; + + uint8_t *p; + const uint8_t *cp; + size_t len; - if (bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { - error_print(); - return -1; - } - error_puts("start listen ...\n"); - listen(sock, 5); memset(conn, 0, sizeof(*conn)); + // 设置服务器证书(客户端验证CA证书) + if (!certs_fp || !server_sign_key || !server_enc_key) { + error_print(); + goto end; + } + if (x509_certs_from_pem(conn->server_certs, &conn->server_certs_len, 2048, certs_fp) != 1) { + error_print(); + goto end; + } + if (client_cacerts_fp) { + if (x509_certs_from_pem(conn->ca_certs, &conn->ca_certs_len, 2048, client_cacerts_fp) != 1) { + error_print(); + goto end; + } + client_verify = 1; + } + + // Socket + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + error_print(); + goto end; + } + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(port); + if (bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + error_print(); + perror("tlcp_accept: bind: "); + goto end; + } + puts("start listen ...\n"); + listen(sock, 5); + client_addrlen = sizeof(client_addr); if ((conn->sock = accept(sock, (struct sockaddr *)&client_addr, &client_addrlen)) < 0) { error_print(); - return -1; + goto end; } - - error_puts("connected\n"); - + puts("socket connected\n"); + // 初始化Finished和客户端验证环境 sm3_init(&sm3_ctx); + if (client_verify) + tls_client_verify_init(&client_verify_ctx); + + // recv ClientHello tls_trace("recv ClientHello\n"); - if (tls_record_recv(record, &recordlen, conn->sock) != 1 - || tls_record_version(record) != TLS_version_tlcp) { + if (tls_record_recv(record, &recordlen, conn->sock) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; + } + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_version(record) != TLS_version_tlcp) { + error_print(); + tls_send_alert(conn, TLS_alert_protocol_version); + goto end; } - tls_record_print(stderr, record, recordlen, 0, 0); if (tls_record_get_handshake_client_hello(record, - &conn->version, client_random, session_id, &session_id_len, - client_ciphers, &client_ciphers_count, NULL, 0) != 1) { + &version, &random, &session_id, &session_id_len, + &client_ciphers, &client_ciphers_len, + &exts, &exts_len) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } - if (conn->version != TLS_version_tlcp) { + if (version != TLS_version_tlcp) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_protocol_version); + goto end; } - for (i = 0; i < tlcp_ciphers_count; i++) { - if (tls_cipher_suite_in_list(tlcp_ciphers[i], client_ciphers, client_ciphers_count) == 1) { - conn->cipher_suite = tlcp_ciphers[i]; - break; - } + memcpy(client_random, random, 32); + if (tls_cipher_suites_select(client_ciphers, client_ciphers_len, + server_ciphers, sizeof(server_ciphers)/sizeof(server_ciphers[0]), + &conn->cipher_suite) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_insufficient_security); + goto end; } - if (conn->cipher_suite == 0) { - error_puts("no common cipher_suite"); - return -1; + if (exts) { + // 忽略客户端扩展错误可以兼容错误的TLCP客户端实现 + error_print(); + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } sm3_update(&sm3_ctx, record + 5, recordlen - 5); - if (handshakes) { - memcpy(handshakes, record + 5, recordlen - 5); - handshakes += recordlen - 5; - handshakeslen += recordlen - 5; - } + if (client_verify) + tls_client_verify_update(&client_verify_ctx, record + 5, recordlen - 5); + + // send ServerHello tls_trace("send ServerHello\n"); tls_random_generate(server_random); if (tls_record_set_handshake_server_hello(record, &recordlen, TLS_version_tlcp, server_random, NULL, 0, conn->cipher_suite, NULL, 0) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_internal_error); + goto end; } - tls_record_print(stderr, record, recordlen, 0, 0); + tlcp_record_trace(stderr, record, recordlen, 0, 0); if (tls_record_send(record, recordlen, conn->sock) != 1) { error_print(); - return -1; + goto end; } sm3_update(&sm3_ctx, record + 5, recordlen - 5); - if (handshakes) { - memcpy(handshakes, record + 5, recordlen - 5); - handshakes += recordlen - 5; - handshakeslen += recordlen - 5; - } + if (client_verify) + tls_client_verify_update(&client_verify_ctx, record + 5, recordlen - 5); + // send ServerCertificate tls_trace("send ServerCertificate\n"); - if (tls_record_set_handshake_certificate_from_pem(record, &recordlen, certs_fp) != 1) { + if (tls_record_set_handshake_certificate(record, &recordlen, + conn->server_certs, conn->server_certs_len) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_internal_error); + goto end; } - tls_record_print(stderr, record, recordlen, 0, 0); + tlcp_record_trace(stderr, record, recordlen, 0, 0); if (tls_record_send(record, recordlen, conn->sock) != 1) { error_print(); - return -1; - } - if (tls_record_get_handshake_certificate(record, conn->server_certs, &conn->server_certs_len) != 1 - || tls_certificate_get_second(conn->server_certs, conn->server_certs_len, - &server_enc_cert, &server_enc_certlen) != 1) { - error_print(); - return -1; + goto end; } sm3_update(&sm3_ctx, record + 5, recordlen - 5); - if (handshakes) { - memcpy(handshakes, record + 5, recordlen - 5); - handshakes += recordlen - 5; - handshakeslen += recordlen - 5; - } + if (client_verify) + tls_client_verify_update(&client_verify_ctx, record + 5, recordlen - 5); + // send ServerKeyExchange tls_trace("send ServerKeyExchange\n"); - + if (x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 1, + &server_enc_cert, &server_enc_cert_len) != 1) { + error_print(); + goto end; + } + p = server_enc_cert_lenbuf; len = 0; + tls_uint24_to_bytes(server_enc_cert_len, &p, &len); if (sm2_sign_init(&sign_ctx, server_sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1 || sm2_sign_update(&sign_ctx, client_random, 32) != 1 || sm2_sign_update(&sign_ctx, server_random, 32) != 1 - || sm2_sign_update(&sign_ctx, server_enc_cert, server_enc_certlen) != 1 - || sm2_sign_finish(&sign_ctx, sig, &siglen) != 1) { + || sm2_sign_update(&sign_ctx, server_enc_cert_lenbuf, 3) != 1 + || sm2_sign_update(&sign_ctx, server_enc_cert, server_enc_cert_len) != 1 + || sm2_sign_finish(&sign_ctx, sigbuf, &siglen) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_internal_error); + goto end; } - - if (tlcp_record_set_handshake_server_key_exchange_pke(record, &recordlen, sig, siglen) != 1) { + if (tlcp_record_set_handshake_server_key_exchange_pke(record, &recordlen, sigbuf, siglen) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_internal_error); + goto end; } - tls_record_print(stderr, record, recordlen, conn->cipher_suite << 8, 0); + tlcp_record_trace(stderr, record, recordlen, 0, 0); if (tls_record_send(record, recordlen, conn->sock) != 1) { error_print(); - return -1; + goto end; } sm3_update(&sm3_ctx, record + 5, recordlen - 5); - if (handshakes) { - memcpy(handshakes, record + 5, recordlen - 5); - handshakes += recordlen - 5; - handshakeslen += recordlen - 5; - } + if (client_verify) + tls_client_verify_update(&client_verify_ctx, record + 5, recordlen - 5); - if (client_cacerts_fp) { - tls_trace("send CertificateRequest\n"); - const int cert_types[] = { TLS_cert_type_ecdsa_sign, }; - uint8_t ca_names[TLS_MAX_CA_NAMES_SIZE] = {0}; - size_t cert_types_count = sizeof(cert_types)/sizeof(cert_types[0]); + // send CertificateRequest + if (client_verify) { + const uint8_t cert_types[] = { TLS_cert_type_ecdsa_sign }; + uint8_t ca_names[TLS_MAX_CA_NAMES_SIZE] = {0}; // TODO: 根据客户端验证CA证书列计算缓冲大小,或直接输出到record缓冲 size_t ca_names_len = 0; - //TODO : read CAnames - - - + 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) { + error_print(); + goto end; + } if (tls_record_set_handshake_certificate_request(record, &recordlen, - cert_types, cert_types_count, + cert_types, sizeof(cert_types), ca_names, ca_names_len) != 1) { error_print(); - return -1; + goto end; } - tls_record_print(stderr, record, recordlen, 0, 0); - + tlcp_record_trace(stderr, record, recordlen, 0, 0); if (tls_record_send(record, recordlen, conn->sock) != 1) { error_print(); - return -1; + goto end; } sm3_update(&sm3_ctx, record + 5, recordlen - 5); - if (handshakes) { - memcpy(handshakes, record + 5, recordlen - 5); - handshakes += recordlen - 5; - handshakeslen += recordlen - 5; - } + tls_client_verify_update(&client_verify_ctx, record + 5, recordlen - 5); } + // send ServerHelloDone tls_trace("send ServerHelloDone\n"); - if (tls_record_set_handshake_server_hello_done(record, &recordlen) != 1) { - error_print(); - return -1; - } - tls_record_print(stderr, record, recordlen, 0, 0); + tls_record_set_handshake_server_hello_done(record, &recordlen); + tlcp_record_trace(stderr, record, recordlen, 0, 0); if (tls_record_send(record, recordlen, conn->sock) != 1) { error_print(); - return -1; + goto end; } sm3_update(&sm3_ctx, record + 5, recordlen - 5); - if (handshakes) { - memcpy(handshakes, record + 5, recordlen - 5); - handshakes += recordlen - 5; - handshakeslen += recordlen - 5; - } + if (client_verify) + tls_client_verify_update(&client_verify_ctx, record + 5, recordlen - 5); + // recv ClientCertificate if (client_cacerts_fp) { tls_trace("recv ClientCertificate\n"); if (tls_record_recv(record, &recordlen, conn->sock) != 1 || tls_record_version(record) != TLS_version_tlcp) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } - tls_record_print(stderr, record, recordlen, 0, 0); - if (tls_record_get_handshake_certificate(record, - conn->client_certs, &conn->client_certs_len) != 1) { + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_get_handshake_certificate(record, conn->client_certs, &conn->client_certs_len) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } - // FIXME: verify client's certificate with ca certs - if (tls_certificate_get_public_keys(conn->client_certs, conn->client_certs_len, - &client_sign_key, NULL) != 1) { + if (x509_certs_verify(conn->client_certs, conn->client_certs_len, + conn->ca_certs, conn->ca_certs_len, verify_depth, &verify_result) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_bad_certificate); + goto end; } sm3_update(&sm3_ctx, record + 5, recordlen - 5); - memcpy(handshakes, record + 5, recordlen - 5); - handshakes += recordlen - 5; - handshakeslen += recordlen - 5; + tls_client_verify_update(&client_verify_ctx, record + 5, recordlen - 5); } + // ClientKeyExchange tls_trace("recv ClientKeyExchange\n"); if (tls_record_recv(record, &recordlen, conn->sock) != 1 || tls_record_version(record) != TLS_version_tlcp) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } - tls_record_print(stderr, record, recordlen, conn->cipher_suite << 8, 0); - if (tls_record_get_handshake_client_key_exchange_pke(record, enced_pms, &enced_pms_len) != 1) { + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_get_handshake_client_key_exchange_pke(record, &enced_pms, &enced_pms_len) != 1) { error_print(); - return -1; - } - sm3_update(&sm3_ctx, record + 5, recordlen - 5); - if (handshakes) { - memcpy(handshakes, record + 5, recordlen - 5); - handshakes += recordlen - 5; - handshakeslen += recordlen - 5; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } if (sm2_decrypt(server_enc_key, enced_pms, enced_pms_len, pre_master_secret, &pre_master_secret_len) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_decrypt_error); + goto end; } + if (pre_master_secret_len != 48) { + error_print(); + tls_send_alert(conn, TLS_alert_decrypt_error); + goto end; + } + sm3_update(&sm3_ctx, record + 5, recordlen - 5); + if (client_verify) + tls_client_verify_update(&client_verify_ctx, record + 5, recordlen - 5); - if (client_cacerts_fp) { + // recv CertificateVerify + if (client_verify) { tls_trace("recv CertificateVerify\n"); if (tls_record_recv(record, &recordlen, conn->sock) != 1 || tls_record_version(record) != TLS_version_tlcp) { + tls_send_alert(conn, TLS_alert_unexpected_message); error_print(); - return -1; + goto end; } - tls_record_print(stderr, record, recordlen, 0, 0); - if (tls_record_get_handshake_certificate_verify(record, sig, &siglen) != 1) { + tlcp_record_trace(stderr, record, recordlen, 0, 0); + if (tls_record_get_handshake_certificate_verify(record, &sig, &siglen) != 1) { + tls_send_alert(conn, TLS_alert_unexpected_message); error_print(); - return -1; + goto end; + } + if (x509_certs_get_cert_by_index(conn->client_certs, conn->client_certs_len, 0, &cp, &len) != 1 + || x509_cert_get_subject_public_key(cp, len, &client_sign_key) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_certificate); + goto end; + } + if (tls_client_verify_finish(&client_verify_ctx, sig, siglen, &client_sign_key) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_decrypt_error); + goto end; } sm3_update(&sm3_ctx, record + 5, recordlen - 5); - sm2_verify_init(&sign_ctx, &client_sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH); - sm2_verify_update(&sign_ctx, handshakes_buf, handshakeslen); - if (sm2_verify_finish(&sign_ctx, sig, siglen) != 1) { - error_print(); - return -1; - } } + // generate secrets tls_trace("generate secrets\n"); if (tls_prf(pre_master_secret, 48, "master secret", - client_random, 32, server_random, 32, - 48, conn->master_secret) != 1) { + client_random, 32, server_random, 32, + 48, conn->master_secret) != 1 + || tls_prf(conn->master_secret, 48, "key expansion", + server_random, 32, client_random, 32, + 96, conn->key_block) != 1) { error_print(); - return -1; - } - if (tls_prf(conn->master_secret, 48, "key expansion", - server_random, 32, client_random, 32, - 96, conn->key_block) != 1) { - error_print(); - return -1; + tls_send_alert(conn, TLS_alert_internal_error); + goto end; } sm3_hmac_init(&conn->client_write_mac_ctx, conn->key_block, 32); sm3_hmac_init(&conn->server_write_mac_ctx, conn->key_block + 32, 32); sm4_set_decrypt_key(&conn->client_write_enc_key, conn->key_block + 64); sm4_set_encrypt_key(&conn->server_write_enc_key, conn->key_block + 80); + /* format_bytes(stderr, 0, 4, "PRE_MASTER_SECRET", pre_master_secret, 48); format_bytes(stderr, 0, 4, "MASTER_SECRET", conn->master_secret, 48); format_bytes(stderr, 0, 4, "CLIENT_WRITE_MAC_KEY", conn->key_block, 32); @@ -860,85 +1016,122 @@ int tlcp_accept(TLS_CONNECT *conn, int port, format_bytes(stderr, 0, 4, "CLIENT_WRITE_ENC_KEY", conn->key_block + 64, 16); format_bytes(stderr, 0, 4, "SERVER_WRITE_ENC_KEY", conn->key_block + 80, 16); format_print(stderr, 0, 0, "\n"); + */ - + // recv [ChangeCipherSpec] tls_trace("recv [ChangeCipherSpec]\n"); if (tls_record_recv(record, &recordlen, conn->sock) != 1 || tls_record_version(record) != TLS_version_tlcp) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } - tls_record_print(stderr, record, recordlen, 0, 0); + tlcp_record_trace(stderr, record, recordlen, 0, 0); if (tls_record_get_change_cipher_spec(record) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } - tls_trace("recv ClientFinished\n"); + // recv ClientFinished + tls_trace("recv Finished\n"); if (tls_record_recv(record, &recordlen, conn->sock) != 1 || tls_record_version(record) != TLS_version_tlcp) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } - if (tls_record_decrypt(&conn->client_write_mac_ctx, &conn->client_write_enc_key, - conn->client_seq_num, record, recordlen, finished, &finishedlen) != 1) { + if (recordlen > sizeof(finished_record)) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_unexpected_message); + goto end; } - tls_seq_num_incr(conn->client_seq_num); - if (tls_record_get_handshake_finished(finished, verify_data) != 1) { - error_print(); - return -1; - } - tls_record_print(stderr, finished, finishedlen, 0, 0); - memcpy(&tmp_sm3_ctx, &sm3_ctx, sizeof(SM3_CTX)); - sm3_update(&sm3_ctx, finished + 5, finishedlen - 5); + tlcp_record_trace(stderr, record, recordlen, (1<<24), 0); // 强制打印密文原数据 + // decrypt ClientFinished + tls_trace("decrypt Finished\n"); + if (tls_record_decrypt(&conn->client_write_mac_ctx, &conn->client_write_enc_key, + conn->client_seq_num, record, recordlen, finished_record, &finished_record_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + tlcp_record_trace(stderr, finished_record, finished_record_len, 0, 0); + tls_seq_num_incr(conn->client_seq_num); + if (tls_record_get_handshake_finished(finished_record, &verify_data, &verify_data_len) != 1) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + if (verify_data_len != sizeof(local_verify_data)) { + error_print(); + tls_send_alert(conn, TLS_alert_bad_record_mac); + goto end; + } + + // verify ClientFinished + memcpy(&tmp_sm3_ctx, &sm3_ctx, sizeof(SM3_CTX)); + sm3_update(&sm3_ctx, finished_record + 5, finished_record_len - 5); sm3_finish(&tmp_sm3_ctx, sm3_hash); if (tls_prf(conn->master_secret, 48, "client finished", sm3_hash, 32, NULL, 0, - 12, local_verify_data) != 1) { + sizeof(local_verify_data), local_verify_data) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_internal_error); + goto end; } - if (memcmp(local_verify_data, verify_data, 12) != 0) { + if (memcmp(verify_data, local_verify_data, sizeof(local_verify_data)) != 0) { error_puts("client_finished.verify_data verification failure"); - return -1; + tls_send_alert(conn, TLS_alert_decrypt_error); + goto end; } + // send [ChangeCipherSpec] tls_trace("send [ChangeCipherSpec]\n"); if (tls_record_set_change_cipher_spec(record, &recordlen) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_internal_error); + goto end; } - tls_record_print(stderr, record, recordlen, 0, 0); + tlcp_record_trace(stderr, record, recordlen, 0, 0); if (tls_record_send(record, recordlen, conn->sock) != 1) { error_print(); - return -1; + goto end; } - tls_trace("send ServerFinished\n"); + // send ServerFinished + tls_trace("send Finished\n"); sm3_finish(&sm3_ctx, sm3_hash); if (tls_prf(conn->master_secret, 48, "server finished", sm3_hash, 32, NULL, 0, - 12, verify_data) != 1) { + sizeof(local_verify_data), local_verify_data) != 1 + || tls_record_set_handshake_finished(finished_record, &finished_record_len, + local_verify_data, sizeof(local_verify_data)) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_internal_error); + goto end; } - if (tls_record_set_handshake_finished(finished, &finishedlen, verify_data) != 1) { - error_print(); - return -1; - } - tls_record_print(stderr, finished, finishedlen, 0, 0); + tlcp_record_trace(stderr, finished_record, finished_record_len, 0, 0); if (tls_record_encrypt(&conn->server_write_mac_ctx, &conn->server_write_enc_key, - conn->server_seq_num, finished, finishedlen, record, &recordlen) != 1) { + conn->server_seq_num, finished_record, finished_record_len, record, &recordlen) != 1) { error_print(); - return -1; + tls_send_alert(conn, TLS_alert_internal_error); + goto end; } + tls_trace("encrypt Finished\n"); + tlcp_record_trace(stderr, record, recordlen, (1<<24), 0); // 强制打印密文原数据 tls_seq_num_incr(conn->server_seq_num); if (tls_record_send(record, recordlen, conn->sock) != 1) { error_print(); - return -1; + goto end; } + conn->version = TLS_version_tlcp; + tls_trace("Connection Established!\n\n"); - return 1; + ret = 1; + +end: + gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); + gmssl_secure_clear(pre_master_secret, sizeof(pre_master_secret)); + if (client_verify) tls_client_verify_cleanup(&client_verify_ctx); + return ret; } diff --git a/src/tls.c b/src/tls.c index 67243ee2..647a2ee9 100644 --- a/src/tls.c +++ b/src/tls.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -107,7 +108,9 @@ void tls_uint32_to_bytes(uint32_t a, uint8_t **out, size_t *outlen) void tls_array_to_bytes(const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen) { if (*out) { - memcpy(*out, data, datalen); + if (data) { + memcpy(*out, data, datalen); + } *out += datalen; } *outlen += datalen; @@ -199,18 +202,6 @@ int tls_array_from_bytes(const uint8_t **data, size_t datalen, const uint8_t **i return 1; } -int tls_array_copy_from_bytes(uint8_t *data, size_t datalen, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *p; - if (tls_array_from_bytes(&p, datalen, in, inlen) != 1) { - error_print(); - return -1; - } - memcpy(data, p, datalen); - return 1; -} - int tls_uint8array_from_bytes(const uint8_t **data, size_t *datalen, const uint8_t **in, size_t *inlen) { uint8_t len; @@ -219,25 +210,13 @@ int tls_uint8array_from_bytes(const uint8_t **data, size_t *datalen, const uint8 error_print(); return -1; } + if (!len) { + *data = NULL; + } *datalen = len; return 1; } -int tls_uint8array_copy_from_bytes(uint8_t *data, size_t *datalen, size_t maxlen, const uint8_t **in, size_t *inlen) -{ - const uint8_t *p; - if (tls_uint8array_from_bytes(&p, datalen, in, inlen) != 1) { - error_print(); - return -1; - } - if (*datalen > maxlen) { - error_print(); - return -1; - } - memcpy(data, p, *datalen); - return 1; -} - int tls_uint16array_from_bytes(const uint8_t **data, size_t *datalen, const uint8_t **in, size_t *inlen) { uint16_t len; @@ -246,25 +225,13 @@ int tls_uint16array_from_bytes(const uint8_t **data, size_t *datalen, const uint error_print(); return -1; } + if (!len) { + *data = NULL; + } *datalen = len; return 1; } -int tls_uint16array_copy_from_bytes(uint8_t *data, size_t *datalen, size_t maxlen, const uint8_t **in, size_t *inlen) -{ - const uint8_t *p; - if (tls_uint16array_from_bytes(&p, datalen, in, inlen) != 1) { - error_print(); - return -1; - } - if (*datalen > maxlen) { - error_print(); - return -1; - } - memcpy(data, p, *datalen); - return 1; -} - int tls_uint24array_from_bytes(const uint8_t **data, size_t *datalen, const uint8_t **in, size_t *inlen) { uint24_t len; @@ -273,28 +240,41 @@ int tls_uint24array_from_bytes(const uint8_t **data, size_t *datalen, const uint error_print(); return -1; } + if (!len) { + *data = NULL; + } *datalen = len; return 1; } -int tls_uint24array_copy_from_bytes(uint8_t *data, size_t *datalen, size_t maxlen, const uint8_t **in, size_t *inlen) +// 获取记录基本信息,不做正确性检查,考虑实现为宏 +int tls_record_type(const uint8_t *record) { - const uint8_t *p; - if (tls_uint24array_from_bytes(&p, datalen, in, inlen) != 1) { - error_print(); - return -1; - } - if (*datalen > maxlen) { - error_print(); - return -1; - } - memcpy(data, p, *datalen); - return 1; + return record[0]; } +int tls_record_length(const uint8_t *record) +{ + int ret; + ret = ((uint16_t)record[3] << 8) | record[4]; + return ret; +} +int tls_record_version(const uint8_t *record) +{ + int version = ((int)record[1] << 8) | record[2]; + return version; +} - +int tls_record_set_type(uint8_t *record, int type) +{ + if (!tls_record_type_name(type)) { + error_print(); + return -1; + } + record[0] = type; + return 1; +} int tls_record_set_version(uint8_t *record, int version) { @@ -307,21 +287,6 @@ int tls_record_set_version(uint8_t *record, int version) return 1; } -int tls_record_version(const uint8_t *record) -{ - int version = ((int)record[1] << 8) | record[2]; - return version; -} - -// -int tls_record_length(const uint8_t *record) -{ - int ret; - ret = ((uint16_t)record[3] << 8) | record[4]; - return ret; -} - - int tls_cbc_encrypt(const SM3_HMAC_CTX *inited_hmac_ctx, const SM4_KEY *enc_key, const uint8_t seq_num[8], const uint8_t header[5], const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) @@ -430,14 +395,13 @@ int tls_cbc_decrypt(const SM3_HMAC_CTX *inited_hmac_ctx, const SM4_KEY *dec_key, sm3_hmac_update(&hmac_ctx, header, 5); sm3_hmac_update(&hmac_ctx, out, *outlen); sm3_hmac_finish(&hmac_ctx, hmac); - if (memcmp(mac, hmac, sizeof(hmac)) != 0) { //FIXME: const time memcmp! - error_puts("tls ciphertext mac check failure"); + if (gmssl_secure_memcmp(mac, hmac, sizeof(hmac)) != 0) { + error_puts("tls ciphertext mac check failure\n"); return -1; } return 1; } -// 这个函数应该是处理的,这个函数是不应该用的,通常我们在加密的时候,header ,明文数据是分离的,但是输出的record是一个 int tls_record_encrypt(const SM3_HMAC_CTX *hmac_ctx, const SM4_KEY *cbc_key, const uint8_t seq_num[8], const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen) @@ -479,15 +443,16 @@ int tls_record_decrypt(const SM3_HMAC_CTX *hmac_ctx, const SM4_KEY *cbc_key, return 1; } -// handshake types - int tls_random_generate(uint8_t random[32]) { uint32_t gmt_unix_time = (uint32_t)time(NULL); uint8_t *p = random; size_t len = 0; tls_uint32_to_bytes(gmt_unix_time, &p, &len); - rand_bytes(random + 4, 28); + if (rand_bytes(random + 4, 28) != 1) { + error_print(); + return -1; + } return 1; } @@ -563,7 +528,28 @@ int tls_pre_master_secret_generate(uint8_t pre_master_secret[48], int version) return 1; } - +// 用于设置CertificateRequest +int tls_cert_type_from_oid(int oid) +{ + switch (oid) { + case OID_sm2sign_with_sm3: + case OID_ecdsa_with_sha1: + case OID_ecdsa_with_sha224: + case OID_ecdsa_with_sha256: + case OID_ecdsa_with_sha512: + return TLS_cert_type_ecdsa_sign; + case OID_rsasign_with_sm3: + case OID_rsasign_with_md5: + case OID_rsasign_with_sha1: + case OID_rsasign_with_sha224: + case OID_rsasign_with_sha256: + case OID_rsasign_with_sha384: + case OID_rsasign_with_sha512: + return TLS_cert_type_rsa_sign; + } + // TLS_cert_type_xxx 中没有为0的值 + return 0; +} int tls_sign_server_ecdh_params(const SM2_KEY *server_sign_key, const uint8_t client_random[32], const uint8_t server_random[32], @@ -602,7 +588,7 @@ int tls_verify_server_ecdh_params(const SM2_KEY *server_sign_key, if (!server_sign_key || !client_random || !server_random || curve != TLS_curve_sm2p256v1 || !point || !sig || !siglen - || siglen > TLS_MAX_SIGNATURE_SIZE) { + || siglen > SM2_MAX_SIGNATURE_SIZE) { error_print(); return -1; } @@ -621,11 +607,6 @@ int tls_verify_server_ecdh_params(const SM2_KEY *server_sign_key, return ret; } - - - -// handshakes - int tls_record_set_handshake(uint8_t *record, size_t *recordlen, int type, const uint8_t *data, size_t datalen) { @@ -635,6 +616,7 @@ int tls_record_set_handshake(uint8_t *record, size_t *recordlen, error_print(); return -1; } + // 这个长度限制应该修改为宏 if (datalen > (1 << 14) - 4) { error_puts("gmssl does not support handshake longer than record"); return -1; @@ -654,6 +636,7 @@ int tls_record_set_handshake(uint8_t *record, size_t *recordlen, return 1; } +// 这个函数应该再仔细检查一下 int tls_record_get_handshake(const uint8_t *record, int *type, const uint8_t **data, size_t *datalen) { @@ -670,7 +653,7 @@ int tls_record_get_handshake(const uint8_t *record, } // 我们应该假定这个record是正确的,不再检查长度之类 record_datalen = (size_t)record[3] << 8 | record[4]; - if (record_datalen > TLS_RECORD_MAX_PLAINDATA_SIZE + if (record_datalen > TLS_MAX_PLAINTEXT_SIZE || record_datalen < 4) { error_print(); return -1; @@ -683,6 +666,10 @@ int tls_record_get_handshake(const uint8_t *record, *type = record[5]; *datalen = ((size_t)record[6] << 16) | ((size_t)record[7] << 8) | record[8]; // FIXME:检查长度 *data = record + 5 + 4; + + if (*datalen == 0) { + *data = NULL; + } return 1; } @@ -710,6 +697,7 @@ int tls_record_set_handshake_client_hello(uint8_t *record, size_t *recordlen, return -1; } + tls_uint16_to_bytes((uint16_t)version, &p, &len); tls_array_to_bytes(random, 32, &p, &len); tls_uint8array_to_bytes(session_id, session_id_len, &p, &len); @@ -734,22 +722,27 @@ int tls_record_set_handshake_client_hello(uint8_t *record, size_t *recordlen, return 1; } +// 这样的函数是否会出现内部错误或者消息解析错误呢? int tls_record_get_handshake_client_hello(const uint8_t *record, - int *version, uint8_t random[32], uint8_t *session_id, size_t *session_id_len, - int *cipher_suites, size_t *cipher_suites_count, - uint8_t *exts, size_t *exts_len) + int *version, const uint8_t **random, + const uint8_t **session_id, size_t *session_id_len, + const uint8_t **cipher_suites, size_t *cipher_suites_len, + const uint8_t **exts, size_t *exts_len) { int type; const uint8_t *p; size_t len; - const uint8_t *ciphers; - size_t ciphers_len; + uint16_t ver; const uint8_t *comp_meths; size_t comp_meths_len; if (!record || !random || !session_id || !session_id_len - || !cipher_suites || !cipher_suites_count || (exts && !exts_len) - || record[0] != TLS_record_handshake) { + || !cipher_suites || !cipher_suites_len + || record[0] != TLS_record_handshake) { // record_type应该有一个独立的错误 + error_print(); + return -1; + } + if (tls_record_type(record) != TLS_record_handshake) { error_print(); return -1; } @@ -758,50 +751,49 @@ int tls_record_get_handshake_client_hello(const uint8_t *record, error_print(); return -1; } - *version = 0; - if (tls_uint16_from_bytes((uint16_t *)version, &p, &len) != 1 - || tls_array_copy_from_bytes(random, 32, &p, &len) != 1 - || tls_uint8array_copy_from_bytes(session_id, session_id_len, 32, &p, &len) != 1 - || tls_uint16array_from_bytes(&ciphers, &ciphers_len, &p, &len) != 1 + if (tls_uint16_from_bytes(&ver, &p, &len) != 1 + || tls_array_from_bytes(random, 32, &p, &len) != 1 + || tls_uint8array_from_bytes(session_id, session_id_len, &p, &len) != 1 + || tls_uint16array_from_bytes(cipher_suites, cipher_suites_len, &p, &len) != 1 || tls_uint8array_from_bytes(&comp_meths, &comp_meths_len, &p, &len) != 1) { error_print(); return -1; } - if (ciphers_len % 2) { + if (!tls_version_text(ver)) { error_print(); return -1; } - *cipher_suites_count = 0; - while (ciphers_len) { - uint16_t cipher_suite; - tls_uint16_from_bytes(&cipher_suite, &ciphers, &ciphers_len); - if (!tls_cipher_suite_name(cipher_suite)) { - error_print(); - return -1; - } - *cipher_suites++ = cipher_suite; - (*cipher_suites_count)++; + *version = ver; + if (*session_id_len > TLS_MAX_SESSION_ID_SIZE) { + error_print(); + return -1; } - if (len > 0) { - /* - // OpenSSL 即使在TLCP时仍然会发出扩展 - if (*version < TLS_version_tls12) { + // 是否允许未定义密码套件,留给调用方解析判断 + if (!cipher_suites) { + error_print(); + return -1; + } + if (*cipher_suites_len % 2) { + error_print(); + return -1; + } + if (len) { + if (tls_uint16array_from_bytes(exts, exts_len, &p, &len) != 1) { error_print(); return -1; } - */ - if (exts) { - if (tls_uint16array_copy_from_bytes(exts, exts_len, TLS_MAX_EXTENSIONS_SIZE, &p, &len) != 1 - || len > 0) { - error_print(); - return -1; - } - } + } else { + *exts = NULL; + *exts_len = 0; + } + if (len) { + error_print(); + return -1; } return 1; } - +// 如果有错误,都是内部错误 int tls_record_set_handshake_server_hello(uint8_t *record, size_t *recordlen, int version, const uint8_t random[32], const uint8_t *session_id, size_t session_id_len, int cipher_suite, @@ -830,7 +822,6 @@ int tls_record_set_handshake_server_hello(uint8_t *record, size_t *recordlen, return -1; } - if (record[0] != TLS_record_handshake) { error_print(); return -1; @@ -843,15 +834,12 @@ int tls_record_set_handshake_server_hello(uint8_t *record, size_t *recordlen, error_print(); return -1; } + /* if (version < tls_record_version(record)) { - - - printf("version = %d\n", version); - printf("version = %d\n", tls_record_version(record)); - error_print(); return -1; } + */ tls_uint16_to_bytes((uint16_t)version, &p, &len); tls_array_to_bytes(random, 32, &p, &len); tls_uint8array_to_bytes(session_id, session_id_len, &p, &len); @@ -872,16 +860,18 @@ int tls_record_set_handshake_server_hello(uint8_t *record, size_t *recordlen, } int tls_record_get_handshake_server_hello(const uint8_t *record, - int *version, uint8_t random[32], uint8_t *session_id, size_t *session_id_len, - int *cipher_suite, uint8_t *exts, size_t *exts_len) + int *version, const uint8_t **random, const uint8_t **session_id, size_t *session_id_len, + int *cipher_suite, const uint8_t **exts, size_t *exts_len) { int type; const uint8_t *p; size_t len; + uint16_t ver; // 如果直接读取uint16到*version中,则*version的高16位没有初始化 + uint16_t cipher; // 同上 uint8_t comp_meth; if (!record || !version || !random || !session_id || !session_id_len - || !cipher_suite || (exts && !exts_len)) { + || !cipher_suite) { error_print(); return -1; } @@ -897,80 +887,91 @@ int tls_record_get_handshake_server_hello(const uint8_t *record, error_print(); return -1; } - *version = 0; - *cipher_suite = 0; - if (tls_uint16_from_bytes((uint16_t *)version, &p, &len) != 1 - || tls_array_copy_from_bytes(random, 32, &p, &len) != 1 - || tls_uint8array_copy_from_bytes(session_id, session_id_len, 32, &p, &len) != 1 - || tls_uint16_from_bytes((uint16_t *)cipher_suite, &p, &len) != 1 + if (tls_uint16_from_bytes(&ver, &p, &len) != 1 + || tls_array_from_bytes(random, 32, &p, &len) != 1 + || tls_uint8array_from_bytes(session_id, session_id_len, &p, &len) != 1 + || tls_uint16_from_bytes(&cipher, &p, &len) != 1 || tls_uint8_from_bytes(&comp_meth, &p, &len) != 1) { error_print(); return -1; } - if (!tls_version_text(*version)) { + if (!tls_version_text(ver)) { error_print(); return -1; } - if (*version < tls_record_version(record)) { + if (ver < tls_record_version(record)) { error_print(); return -1; } - if (!tls_cipher_suite_name(*cipher_suite)) { + *version = ver; + if (*session_id_len > TLS_MAX_SESSION_ID_SIZE) { + error_print(); + return -1; + } + if (!tls_cipher_suite_name(cipher)) { error_print_msg("unknown server cipher_suite 0x%04x", *cipher_suite); return -1; } + *cipher_suite = cipher; if (comp_meth != TLS_compression_null) { error_print(); return -1; } - if (len > 0) { - if (tls_record_version(record) < TLS_version_tls12) { - error_puts("warning: should not have extentions"); - return -1; - } - // FIXME: 用 tls_extensions_from_bytes() 解析 - if (tls_uint16array_copy_from_bytes(exts, exts_len, TLS_MAX_EXTENSIONS_SIZE, &p, &len) != 1 - || len > 0) { + if (len) { + if (tls_uint16array_from_bytes(exts, exts_len, &p, &len) != 1) { error_print(); return -1; } + } else { + *exts = NULL; + *exts_len = 0; + } + if (len) { + error_print(); + return -1; } return 1; } - - - - int tls_record_set_handshake_certificate(uint8_t *record, size_t *recordlen, - const uint8_t *data, size_t datalen) + const uint8_t *certs, size_t certslen) { int type = TLS_handshake_certificate; - const uint8_t *cp = data; - size_t len = datalen; - const uint8_t *certs; - size_t certslen; + const size_t maxlen = TLS_MAX_HANDSHAKE_DATA_SIZE - tls_uint24_size(); + uint8_t *data, *p; + size_t datalen = 0; + size_t len = 0; - if (!record || !recordlen - || !data || datalen <= 3 || datalen > 65535) { + if (!record || !recordlen || !certs || !certslen) { error_print(); return -1; } - if (tls_uint24array_from_bytes(&certs, &certslen, &cp, &len) != 1 - || len > 0) { - error_print(); - return -1; + data = tls_handshake_data(tls_record_data(record)); + p = data + tls_uint24_size(); + + // set (uint24 certlen, cert)* + while (certslen) { + const uint8_t *cert; + size_t certlen; + + if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1) { + error_print(); + return -1; + } + // 如何防止溢出 + if (3 + certlen > maxlen) { + error_print(); + return -1; + } + tls_uint24array_to_bytes(cert, certlen, &p, &datalen); } - // FIXME: check certificate - if (!certslen) { - error_print(); - return -1; - } - tls_record_set_handshake(record, recordlen, type, data, datalen); + tls_uint24_to_bytes(datalen, &data, &datalen); + tls_record_set_handshake(record, recordlen, type, NULL, datalen); return 1; } +/* int tls_record_set_handshake_certificate_from_pem(uint8_t *record, size_t *recordlen, FILE *fp) { int type = TLS_handshake_certificate; @@ -996,13 +997,20 @@ int tls_record_set_handshake_certificate_from_pem(uint8_t *record, size_t *recor tls_record_set_handshake(record, recordlen, type, NULL, datalen); return 1; } +*/ -int tls_record_get_handshake_certificate(const uint8_t *record, uint8_t *data, size_t *datalen) +// 如果certs长度超过限制怎么办? +// 在调用这个函数之前,应该保证准备的缓冲区为 +int tls_record_get_handshake_certificate(const uint8_t *record, uint8_t *certs, size_t *certslen) { int type; - const uint8_t *cp; + const uint8_t *data; + size_t datalen; + uint8_t *out = certs; + const uint8_t *p; + size_t len; - if (tls_record_get_handshake(record, &type, &cp, datalen) != 1) { + if (tls_record_get_handshake(record, &type, &data, &datalen) != 1) { error_print(); return -1; } @@ -1010,147 +1018,34 @@ int tls_record_get_handshake_certificate(const uint8_t *record, uint8_t *data, s error_print(); return -1; } - memcpy(data, cp, *datalen); - return 1; -} + if (tls_uint24array_from_bytes(&p, &len, &data, &datalen) != 1) { + error_print(); + return -1; + } -int tls_certificate_get_subject_names(const uint8_t *certs, size_t certslen, uint8_t *names, size_t *nameslen) -{ - *nameslen = 0; - const uint8_t *cert; - size_t certlen; + *certslen = 0; + while (len) { + const uint8_t *d; + size_t dlen; + const uint8_t *cert; + size_t certlen; - while (certslen > 0) { - const uint8_t *subject; - size_t subject_len; - - if (tls_uint24array_from_bytes(&cert, &certlen, &certs, &certslen) != 1) { + if (tls_uint24array_from_bytes(&d, &dlen, &p, &len) != 1) { error_print(); return -1; } - if (x509_cert_get_subject(cert, certlen, &subject, &subject_len) != 1) { + if (x509_cert_from_der(&cert, &certlen, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1 + || x509_cert_to_der(cert, certlen, &out, certslen) != 1) { error_print(); return -1; } - if (asn1_sequence_to_der(subject, subject_len, &names, nameslen) != 1) { - error_print(); - return -1; - } - } - return 1; -} - -int tls_certificate_get_first(const uint8_t *data, size_t datalen, const uint8_t **cert, size_t *certlen) -{ - const uint8_t *certs; - size_t certslen; - if (tls_uint24array_from_bytes(&certs, &certslen, &data, &datalen) != 1 - || datalen > 0 - || tls_uint24array_from_bytes(cert, certlen, &certs, &certslen) != 1) { - error_print(); - return -1; - } - *cert -= 3; - *certlen += 3; - return 1; -} - -int tls_certificate_get_second(const uint8_t *data, size_t datalen, const uint8_t **cert, size_t *certlen) -{ - const uint8_t *certs; - size_t certslen; - if (tls_uint24array_from_bytes(&certs, &certslen, &data, &datalen) != 1 - || datalen > 0 - || tls_uint24array_from_bytes(cert, certlen, &certs, &certslen) != 1 - || tls_uint24array_from_bytes(cert, certlen, &certs, &certslen) != 1) { - error_print(); - return -1; - } - *cert -= 3; - *certlen += 3; - return 1; -} - -int tls_certificate_get_public_keys(const uint8_t *data, size_t datalen, - SM2_KEY *sign_key, SM2_KEY *enc_key) -{ - const uint8_t *cert; - const uint8_t *der; - size_t certlen, derlen; - - if (!data || !datalen || !sign_key) { - error_print(); - return -1; - } - if (tls_certificate_get_first(data, datalen, &cert, &certlen) != 1 - || tls_uint24array_from_bytes(&der, &derlen, &cert, &certlen) != 1 - || certlen > 0) { - error_print(); - return -1; - } - if (x509_cert_get_subject_public_key(der, derlen, sign_key) != 1) { - error_print(); - return -1; - } - - if (enc_key) { - if (tls_certificate_get_second(data, datalen, &cert, &certlen) != 1 - || tls_uint24array_from_bytes(&der, &derlen, &cert, &certlen) != 1 - || certlen > 0) { - error_print(); - return -1; - } - if (x509_cert_get_subject_public_key(der, derlen, enc_key) != 1) { - error_print(); - return -1; - } - } - return 1; -} - - - -int tls_certificate_chain_verify(const uint8_t *certs, size_t certslen, FILE *ca_certs_fp, int depth) -{ - const uint8_t *cert; - size_t certlen; - const uint8_t *cacert; - size_t cacertlen; - const uint8_t *issuer; - size_t issuer_len; - uint8_t rootcert[4096]; - size_t rootcertlen; - - if (tls_uint24array_from_bytes(&cert, &certlen, &certs, &certslen) != 1) { - error_print(); - return -1; - } - while (certslen > 0) { - if (tls_uint24array_from_bytes(&cacert, &cacertlen, &certs, &certslen) != 1) { - error_print(); - return -1; - } - if (x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { - error_print(); - return -1; - } - cert = cacert; - certlen = cacertlen; - } - if (x509_cert_get_issuer(cert, certlen, &issuer, &issuer_len) != 1) { - error_print(); - return -1; - } - if (x509_cert_from_pem_by_subject(rootcert, &rootcertlen, sizeof(rootcert), issuer, issuer_len, ca_certs_fp) != 1 - || x509_cert_verify_by_ca_cert(cert, certlen, rootcert, rootcertlen, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { - error_print(); - return -1; } return 1; } int tls_record_set_handshake_certificate_request(uint8_t *record, size_t *recordlen, - const int *cert_types, size_t cert_types_count, + const uint8_t *cert_types, size_t cert_types_len, const uint8_t *ca_names, size_t ca_names_len) { int type = TLS_handshake_certificate_request; @@ -1158,24 +1053,21 @@ int tls_record_set_handshake_certificate_request(uint8_t *record, size_t *record size_t len = 0; if (!record || !recordlen - || !cert_types || !cert_types_count || cert_types_count > TLS_MAX_CERTIFICATE_TYPES + || !cert_types || !cert_types_len || cert_types_len > TLS_MAX_CERTIFICATE_TYPES || (!ca_names && ca_names_len) || ca_names_len > TLS_MAX_CA_NAMES_SIZE) { error_print(); return -1; } - tls_uint8_to_bytes((uint8_t)cert_types_count, &p, &len); - while (cert_types_count--) { - tls_uint8_to_bytes((uint8_t)(*cert_types), &p, &len); - cert_types++; - } + // 对cert_types_len和ca_names_len的长度检查保证输出不会超过记录长度 + tls_uint8array_to_bytes(cert_types, cert_types_len, &p, &len); tls_uint16array_to_bytes(ca_names, ca_names_len, &p, &len); tls_record_set_handshake(record, recordlen, type, NULL, len); return 1; } int tls_record_get_handshake_certificate_request(const uint8_t *record, - int *cert_types, size_t *cert_types_count, - uint8_t *ca_names, size_t *ca_names_len) + const uint8_t **cert_types, size_t *cert_types_len, + const uint8_t **ca_names, size_t *ca_names_len) { int type; const uint8_t *cp; @@ -1184,25 +1076,18 @@ int tls_record_get_handshake_certificate_request(const uint8_t *record, size_t count; if (!record - || !cert_types || !cert_types_count || !ca_names || !ca_names_len + || !cert_types || !cert_types_len || !ca_names || !ca_names_len || record[0] != TLS_record_handshake) { error_print(); return -1; } if (tls_record_get_handshake(record, &type, &cp, &len) != 1 - || tls_uint8array_from_bytes(&types, &count, &cp, &len) != 1 - || tls_uint16array_copy_from_bytes(ca_names, ca_names_len, TLS_MAX_CA_NAMES_SIZE, &cp, &len) != 1 + || tls_uint8array_from_bytes(cert_types, cert_types_len, &cp, &len) != 1 + || tls_uint16array_from_bytes(ca_names, ca_names_len, &cp, &len) != 1 || len > 0) { error_print(); return -1; } - if (count > TLS_MAX_CERTIFICATE_TYPES) { - error_print(); - return -1; - } - while (count--) { - *cert_types++ = *types++; - } return 1; } @@ -1253,7 +1138,7 @@ int tls_record_set_handshake_client_key_exchange_pke(uint8_t *record, size_t *re } int tls_record_get_handshake_client_key_exchange_pke(const uint8_t *record, - uint8_t *enced_pms, size_t *enced_pms_len) + const uint8_t **enced_pms, size_t *enced_pms_len) { int type; const uint8_t *p; @@ -1269,7 +1154,7 @@ int tls_record_get_handshake_client_key_exchange_pke(const uint8_t *record, error_print(); return -1; } - if (tls_uint16array_copy_from_bytes(enced_pms, enced_pms_len, *enced_pms_len, &p, &len) != 1 + if (tls_uint16array_from_bytes(enced_pms, enced_pms_len, &p, &len) != 1 || len > 0) { error_print(); return -1; @@ -1286,57 +1171,59 @@ int tls_record_set_handshake_certificate_verify(uint8_t *record, size_t *recordl } int tls_record_get_handshake_certificate_verify(const uint8_t *record, - uint8_t *sig, size_t *siglen) + const uint8_t **sig, size_t *siglen) { int type; - const uint8_t *p; - size_t len ; - if (tls_record_get_handshake(record, &type, &p, &len) != 1 + if (tls_record_get_handshake(record, &type, sig, siglen) != 1 || type != TLS_handshake_certificate_verify) { error_print(); return -1; } - memcpy(sig, p, len); - *siglen = len; + if (*sig == NULL) { + error_print(); + return -1; + } return 1; } //FIXME: TLS 1.3 中的verify_data长度和hashLen一样,并且长度是不单独编码的, // 因此这个函数应该改一下了 int tls_record_set_handshake_finished(uint8_t *record, size_t *recordlen, - const uint8_t verify_data[12]) + const uint8_t *verify_data, size_t verify_data_len) { int type = TLS_handshake_finished; if (!record || !recordlen || !verify_data) { error_print(); return -1; } - tls_record_set_handshake(record, recordlen, type, verify_data, 12); + tls_record_set_handshake(record, recordlen, type, verify_data, verify_data_len); return 1; } -int tls_record_get_handshake_finished(const uint8_t *record, uint8_t verify_data[12]) +int tls_record_get_handshake_finished(const uint8_t *record, const uint8_t **verify_data, size_t *verify_data_len) { int type; - const uint8_t *p; - size_t len; - if (tls_record_get_handshake(record, &type, &p, &len) != 1) { + if (tls_record_get_handshake(record, &type, verify_data, verify_data_len) != 1) { error_print(); return -1; } - if (len != 12) { + if (type != TLS_handshake_finished) { + error_print(); + return -1; + } + if (*verify_data == NULL) { error_print(); return -1; } - memcpy(verify_data, p, 12); return 1; } // alert protocol +// 这个函数没有必要设置长度,因此Alert长度是固定的! int tls_record_set_alert(uint8_t *record, size_t *recordlen, int alert_level, int alert_description) @@ -1459,6 +1346,9 @@ int tls_cipher_suite_in_list(int cipher, const int *list, size_t list_count) return 0; } +// 两类错误,一种是输入的记录格式有问题,一种是网络问题 +// 显然输入格式是编译期的错误,不应该发生 +// 网络错误如果发生,那么也没有必要再发错误消息了 int tls_record_send(const uint8_t *record, size_t recordlen, int sock) { ssize_t r; @@ -1484,31 +1374,26 @@ int tls_record_recv(uint8_t *record, size_t *recordlen, int sock) size_t len; retry: + // TODO:支持非租塞socket或针对可能的网络延迟重新recv if ((r = recv(sock, record, 5, 0)) < 0) { error_print(); return -1; - } else if (r != 5) { - sleep(1); - goto retry; - - format_bytes(stderr, 0, 0, "record", record, r); - - // FIXME: 如果对方已经中断连接,那么我们要判断这个错误吗? - error_print(); - perror(""); // 否则打印ioctl错误 - return -1; } - - if (!tls_record_type_name(record[0])) { - error_print_msg("invalid record type: %d\n", record[0]); + if (!tls_record_type_name(tls_record_type(record))) { + error_print_msg("Invalid record type: %d\n", record[0]); return -1; } if (!tls_version_text(tls_record_version(record))) { - error_print_msg("invalid record version: %d.%d\n", record[1], record[2]); + error_print_msg("Invalid record version: %d.%d\n", record[1], record[2]); return -1; } len = (size_t)record[3] << 8 | record[4]; *recordlen = 5 + len; + if (*recordlen > TLS_MAX_RECORD_SIZE) { + // 这里只检查是否超过最大长度,握手协议的长度检查由上层协议完成 + error_print(); + return -1; + } if (len) { if ((r = recv(sock, record + 5, len, 0)) < 0) { error_print(); @@ -1518,9 +1403,32 @@ retry: return -1; } } - - if (record[0] == TLS_record_alert) { - tls_record_print(stderr, record, *recordlen, 0, 0); + if (tls_record_type(record) == TLS_record_alert) { + int level; + int alert; + if (tls_record_get_alert(record, &level, &alert) != 1) { + error_print(); + return -1; + } + tls_record_trace(stderr, record, *recordlen, 0, 0); + if (level == TLS_alert_level_warning) { + // 忽略Warning,读取下一个记录 + error_puts("Warning record received!\n"); + goto retry; + } + if (alert == TLS_alert_close_notify) { + // close_notify是唯一需要提供反馈的Fatal Alert,其他直接中止连接 + uint8_t alert_record[TLS_ALERT_RECORD_SIZE]; + size_t alert_record_len; + tls_record_set_type(alert_record, TLS_record_alert); + tls_record_set_version(alert_record, tls_record_version(record)); + tls_record_set_alert(alert_record, &alert_record_len, TLS_alert_level_fatal, TLS_alert_close_notify); + tls_record_print(stderr, alert_record, alert_record_len, 0, 0); + tls_record_send(alert_record, alert_record_len, sock); + } + // 返回错误0通知调用方不再做任何处理(无需再发送Alert) + error_puts("Alert record received!\n"); + return 0; } return 1; } @@ -1550,6 +1458,56 @@ int tls_compression_methods_has_null_compression(const uint8_t *meths, size_t me return -1; } +int tls_send_alert(TLS_CONNECT *conn, int alert) +{ + uint8_t record[5 + 2]; + size_t recordlen; + + tls_record_set_version(record, conn->version); + tls_record_set_alert(record, &recordlen, TLS_alert_level_fatal, alert); + tls_record_send(record, sizeof(record), conn->sock); + tls_record_trace(stderr, record, sizeof(record), 0, 0); + return 1; +} + +int tls_alert_level(int alert) +{ + switch (alert) { + case TLS_alert_bad_certificate: + case TLS_alert_unsupported_certificate: + case TLS_alert_certificate_revoked: + case TLS_alert_certificate_expired: + case TLS_alert_certificate_unknown: + return 0; + case TLS_alert_user_canceled: + case TLS_alert_no_renegotiation: + return TLS_alert_level_warning; + default: + return TLS_alert_level_fatal; + } + return -1; +} + + +int tls_send_warning(TLS_CONNECT *conn, int alert) +{ + uint8_t record[5 + 2]; + size_t recordlen; + + if (tls_alert_level(alert) == TLS_alert_level_fatal) { + error_print(); + return -1; + } + tls_record_set_version(record, conn->version); + tls_record_set_alert(record, &recordlen, TLS_alert_level_warning, alert); + tls_record_send(record, sizeof(record), conn->sock); + tls_record_trace(stderr, record, sizeof(record), 0, 0); + return 1; +} + + + + // FIXME: 设定支持的最大输入长度 // FIXME: 没回返回实际的发送长度 int tls_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen) @@ -1583,7 +1541,7 @@ int tls_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen) error_print(); return -1; } - (void)tls_record_print(stderr, crec, clen, 0, 0); + tls_record_trace(stderr, crec, clen, 0, 0); return 1; } @@ -1608,14 +1566,44 @@ int tls_recv(TLS_CONNECT *conn, uint8_t *data, size_t *datalen) } tls_trace("recv ApplicationData\n"); - if (tls_record_recv(crec, &clen, conn->sock) != 1 - // FIXME: 检查版本号 - || tls_record_decrypt(hmac_ctx, dec_key, seq_num, crec, clen, mrec, &mlen) != 1 + if (tls_record_recv(crec, &clen, conn->sock) != 1) { + error_print(); + return -1; + } + + if (crec[0] == TLS_record_alert) { + int level; + int alert; + + if (tls_record_get_alert(crec, &level, &alert) != 1) { + error_print(); + return -1; + } + if (alert == TLS_alert_close_notify) { + if (tls_record_send(crec, clen, conn->sock) != 1) { + error_print(); + return -1; + } + + } else { + error_print(); + return -1; + } + + if (level == TLS_alert_level_fatal) { + tls_trace("close Connection\n"); + return 0; + } + } + + + // FIXME: 检查版本号 + if (tls_record_decrypt(hmac_ctx, dec_key, seq_num, crec, clen, mrec, &mlen) != 1 || tls_seq_num_incr(seq_num) != 1) { error_print(); return -1; } - (void)tls_record_print(stderr, mrec, mlen, 0, 0); + tls_record_trace(stderr, mrec, mlen, 0, 0); memcpy(data, mrec + 5, mlen - 5); *datalen = mlen - 5; return 1; @@ -1624,7 +1612,31 @@ int tls_recv(TLS_CONNECT *conn, uint8_t *data, size_t *datalen) //FIXME: any difference in TLS 1.2 and TLS 1.3? int tls_shutdown(TLS_CONNECT *conn) { - return -1; + uint8_t alert[128]; + size_t len; + + tls_record_set_version(alert, conn->version); + tls_record_set_alert(alert, &len, TLS_alert_level_fatal, TLS_alert_close_notify); + + if (tls_record_send(alert, len, conn->sock) != 1) { + error_print(); + return -1; + } + + tls_trace("send Alert.close_notify\n"); + tls_record_trace(stderr, alert, len, 0, 0); + + + memset(alert, 0, sizeof(alert)); + // 这里接收实际上只是检查一下对方是否合规,不管怎么说我们都要结束了 + if (tls_record_recv(alert, &len, conn->sock) != 1) { + error_print(); + return -1; + } + tls_trace("recv Alert.close_notify\n"); + tls_record_trace(stderr, alert, len, 0, 0); + + return 1; } // 参考 man verify 的错误返回值 @@ -1633,3 +1645,190 @@ int tls_get_verify_result(TLS_CONNECT *conn, int *result) *result = 0; return 1; } + +// 这里的输出是record,因此是有一个长度限制的 + +int tls_authorities_from_certs(uint8_t *names, size_t *nameslen, size_t maxlen, const uint8_t *certs, size_t certslen) +{ + uint8_t *out = names; + const uint8_t *cert; + size_t certlen; + const uint8_t *name; + size_t namelen; + + *nameslen = 0; + while (certslen) { + size_t alen = 0; + if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1 + || x509_cert_get_subject(cert, certlen, &name, &namelen) != 1 + || asn1_sequence_to_der(name, namelen, NULL, &alen) != 1) { + error_print(); + return -1; + } + if (tls_uint16_size() + alen > maxlen) { + + fprintf(stderr, "alen = %zu\n", alen); + fprintf(stderr, "maxlen = %zu\n", maxlen); + + error_print(); + return -1; + } + // 这里要兼容names == NULL的情况 + tls_uint16_to_bytes(alen, &out, nameslen); + if (asn1_sequence_to_der(name, namelen, &out, nameslen) != 1) { + error_print(); + return -1; + } + maxlen -= alen; + } + return 1; +} + +int tls_authorities_issued_certificate(const uint8_t *ca_names, size_t ca_names_len, const uint8_t *certs, size_t certslen) +{ + const uint8_t *cert; + size_t certlen; + const uint8_t *issuer; + size_t issuer_len; + + if (x509_certs_get_last(certs, certslen, &cert, &certlen) != 1 + || x509_cert_get_issuer(cert, certlen, &issuer, &issuer_len) != 1) { + error_print(); + return -1; + } + while (ca_names_len) { + const uint8_t *p; + size_t len; + const uint8_t *name; + size_t namelen; + + if (tls_uint16array_from_bytes(&p, &len, &ca_names, &ca_names_len) != 1) { + error_print(); + return -1; + } + if (asn1_sequence_from_der(&name, &namelen, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + if (x509_name_equ(name, namelen, issuer, issuer_len) == 1) { + return 1; + } + } + error_print(); + return 0; +} + +int tls_cert_types_accepted(const uint8_t *types, size_t types_len, const uint8_t *client_certs, size_t client_certs_len) +{ + const uint8_t *cert; + size_t certlen; + int sig_alg; + size_t i; + + if (x509_certs_get_cert_by_index(client_certs, client_certs_len, 0, &cert, &certlen) != 1) { + error_print(); + return -1; + } + if ((sig_alg = tls_cert_type_from_oid(OID_sm2sign_with_sm3)) < 0) { + error_print(); + return -1; + } + for (i = 0; i < types_len; i++) { + if (sig_alg == types[i]) { + return 1; + } + } + return 0; +} + + +int tls_client_verify_init(TLS_CLIENT_VERIFY_CTX *ctx) +{ + memset(ctx, 0, sizeof(TLS_CLIENT_VERIFY_CTX)); + return 1; +} + +int tls_client_verify_update(TLS_CLIENT_VERIFY_CTX *ctx, const uint8_t *handshake, size_t handshake_len) +{ + uint8_t *buf; + if (ctx->index < 0 || ctx->index > 7) { + error_print(); + return -1; + } + if (!(buf = malloc(handshake_len))) { + error_print(); + return -1; + } + memcpy(buf, handshake, handshake_len); + ctx->handshake[ctx->index] = buf; + ctx->handshake_len[ctx->index] = handshake_len; + ctx->index++; + return 1; +} + +int tls_client_verify_finish(TLS_CLIENT_VERIFY_CTX *ctx, const uint8_t *sig, size_t siglen, const SM2_KEY *public_key) +{ + int ret; + SM2_SIGN_CTX sm2_ctx; + int i; + + if (ctx->index != 8) { + error_print(); + return -1; + } + if (sm2_verify_init(&sm2_ctx, public_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { + error_print(); + return -1; + } + for (i = 0; i < 8; i++) { + if (sm2_verify_update(&sm2_ctx, ctx->handshake[i], ctx->handshake_len[i]) != 1) { + error_print(); + return -1; + } + } + if ((ret = sm2_verify_finish(&sm2_ctx, sig, siglen)) < 0) { + error_print(); + return -1; + } + return ret; +} + +void tls_client_verify_cleanup(TLS_CLIENT_VERIFY_CTX *ctx) +{ + int i; + for (i = 0; i< ctx->index; i++) { + if (ctx->handshake[i]) { + free(ctx->handshake[i]); + ctx->handshake[i] = NULL; + ctx->handshake_len[i] = 0; + } + } +} + + +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) +{ + while (server_ciphers_cnt--) { + const uint8_t *p = client_ciphers; + size_t len = client_ciphers_len; + while (len) { + uint16_t cipher; + if (tls_uint16_from_bytes(&cipher, &p, &len) != 1) { + error_print(); + return -1; + } + if (cipher == *server_ciphers) { + *selected_cipher = *server_ciphers; + return 1; + } + } + server_ciphers++; + } + return 0; +} + + + diff --git a/src/tls_trace.c b/src/tls_trace.c index 699bfc56..f69188fb 100644 --- a/src/tls_trace.c +++ b/src/tls_trace.c @@ -222,7 +222,7 @@ const char *tls_alert_level_name(int level) case TLS_alert_level_warning: return "warning"; case TLS_alert_level_fatal: return "fatal"; } - error_print_msg("unknown alert level %d", level); + error_print_msg("unknown alert level %d\n", level); return NULL; } @@ -253,6 +253,7 @@ const char *tls_alert_description_text(int description) case TLS_alert_internal_error: return "internal_error"; case TLS_alert_user_canceled: return "user_canceled"; case TLS_alert_no_renegotiation: return "no_renegotiation"; + case TLS_alert_unsupported_extension: return "unsupported_extension"; case TLS_alert_unsupported_site2site: return "unsupported_site2site"; case TLS_alert_no_area: return "no_area"; case TLS_alert_unsupported_areatype: return "unsupported_areatype"; @@ -468,6 +469,17 @@ int tls_extensions_print(FILE *fp, const uint8_t *exts, size_t extslen, int form return 1; } +int tls_hello_request_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent) +{ + format_print(fp, format, indent, "HelloRequest\n"); + indent += 4; + if (data || datalen > 0) { + error_print(); + return -1; + } + return 1; +} + int tls_client_hello_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent) { int ret = -1; @@ -580,22 +592,6 @@ int tls_certificate_print(FILE *fp, const uint8_t *data, size_t datalen, int for return 1; } -int tlcp_server_key_exchange_pke_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent) -{ - const uint8_t *sig = data; - size_t siglen = datalen; - /* - if (tls_uint16array_from_bytes(&sig, &siglen, &data, &datalen) != 1 - || datalen > 0) { - error_print(); - } - */ - format_print(fp, format, indent, "ServerKeyExchange\n"); - indent += 4; - format_bytes(fp, format, indent, "signature", sig, siglen); - return 1; -} - int tls_server_key_exchange_ecdhe_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent) { @@ -675,6 +671,32 @@ int tls_server_key_exchange_print(FILE *fp, const uint8_t *data, size_t datalen, return 1; } +int tls_certificate_subjects_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *a; + size_t alen; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + const uint8_t *name; + size_t namelen; + + if (tls_uint16array_from_bytes(&a, &alen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (asn1_sequence_from_der(&name, &namelen, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + x509_name_print(fp, fmt, ind, "DistinguishedName", name, namelen); + } + return 1; +} + int tls_certificate_request_print(FILE *fp, const uint8_t *data, size_t datalen, int format, int indent) { const uint8_t *cert_types; @@ -688,7 +710,8 @@ int tls_certificate_request_print(FILE *fp, const uint8_t *data, size_t datalen, format_print(fp, format, indent + 4, "%s\n", tls_cert_type_name(*cert_types++)); } if (tls_uint16array_from_bytes(&ca_names, &ca_names_len, &data, &datalen) != 1) goto bad; - format_bytes(fp, format, indent, "CAnames", ca_names, ca_names_len); + tls_certificate_subjects_print(fp, format, indent, "CAnames", ca_names, ca_names_len); + return 1; bad: error_print(); @@ -806,6 +829,9 @@ int tls_handshake_print(FILE *fp, const uint8_t *handshake, size_t handshakelen, return -1; } switch (type) { + case TLS_handshake_hello_request: + if (tls_hello_request_print(fp, data, datalen, format, indent) != 1) + { error_print(); return -1; } break; case TLS_handshake_client_hello: if (tls_client_hello_print(fp, data, datalen, format, indent) != 1) { error_print(); return -1; } break; @@ -871,6 +897,8 @@ int tls_application_data_print(FILE *fp, const uint8_t *data, size_t datalen, in return 1; } +// 当消息为ClientKeyExchange,ServerKeyExchange,需要密码套件中的密钥交换算法信息 +// 当消息为加密的Finished,记录类型为Handshake,但是记录负载数据中没有Handshake头 int tls_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int format, int indent) { const uint8_t *data; @@ -890,6 +918,13 @@ int tls_record_print(FILE *fp, const uint8_t *record, size_t recordlen, int for data = record + 5; datalen = recordlen - 5; + // 最高字节设置后强制打印记录原始数据 + if (format >> 24) { + format_bytes(fp, format, indent, "Data", data, datalen); + fprintf(fp, "\n"); + return 1; + } + switch (record[0]) { case TLS_record_handshake: if (tls_handshake_print(fp, data, datalen, format, indent) != 1) { diff --git a/src/x509_cer.c b/src/x509_cer.c index 96292fbb..e27f0d0c 100644 --- a/src/x509_cer.c +++ b/src/x509_cer.c @@ -547,6 +547,24 @@ int x509_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t return 1; } +int x509_names_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_name_print(fp, fmt, ind, "Name", p, len); + } + return 1; +} + int x509_name_get_value_by_type(const uint8_t *d, size_t dlen, int oid, int *tag, const uint8_t **val, size_t *vlen) { const uint8_t *rdn_d; @@ -587,6 +605,15 @@ int x509_name_get_common_name(const uint8_t *d, size_t dlen, int *tag, const uin return -1; } +int x509_name_equ(const uint8_t *a, size_t alen, const uint8_t *b, size_t blen) +{ + if (alen != blen || memcmp(a, b, blen) != 0) { + return 0; + } + return 1; +} + + int x509_public_key_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { const uint8_t *p = d; @@ -1407,6 +1434,21 @@ int x509_certs_get_cert_by_index(const uint8_t *d, size_t dlen, int index, const return 1; } +int x509_certs_get_last(const uint8_t *d, size_t dlen, const uint8_t **cert, size_t *certlen) +{ + if (!dlen) { + error_print(); + return -1; + } + while (dlen) { + if (x509_cert_from_der(cert, certlen, &d, &dlen) != 1) { + error_print(); + return -1; + } + } + return 1; +} + int x509_certs_get_cert_by_subject(const uint8_t *d, size_t dlen, const uint8_t *subject, size_t subject_len, const uint8_t **cert, size_t *certlen) { @@ -1420,7 +1462,11 @@ int x509_certs_get_cert_by_subject(const uint8_t *d, size_t dlen, error_print(); return -1; } - if (subj_len == subject_len && memcmp(subj, subject, subj_len) == 0) { + if (x509_cert_get_subject(a, alen, &subj, &subj_len) != 1) { + error_print(); + return -1; + } + if (x509_name_equ(subj, subj_len, subject, subject_len) == 1) { *cert = a; *certlen = alen; return 1; @@ -1458,6 +1504,125 @@ int x509_certs_get_cert_by_issuer_and_serial_number( return 0; } + +int x509_certs_verify(const uint8_t *certs, size_t certslen, + const uint8_t *rootcerts, size_t rootcertslen, int depth, int *verify_result) +{ + const uint8_t *cert; + size_t certlen; + const uint8_t *cacert; + size_t cacertlen; + const uint8_t *name; + size_t namelen; + + *verify_result = -1; + + if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1) { + error_print(); + return -1; + } + while (certslen) { + if (x509_cert_from_der(&cacert, &cacertlen, &certs, &certslen) != 1) { + error_print(); + return -1; + } + // 这里应该检查证书是否有效啊, 这个函数应该返回进一步的错误信息 + if (x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, + SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { + error_print(); + return -1; + } + cert = cacert; + certlen = cacertlen; + } + if (x509_cert_get_issuer(cert, certlen, &name, &namelen) != 1) { + error_print(); + return -1; + } + if (x509_certs_get_cert_by_subject(rootcerts, rootcertslen, name, namelen, + &cacert, &cacertlen) != 1) { + error_print(); + return -1; + } + if (x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, + SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { + error_print(); + return -1; + } + + return 1; +} + +int x509_certs_verify_tlcp(const uint8_t *certs, size_t certslen, + const uint8_t *rootcerts, size_t rootcertslen, int depth, int *verify_result) +{ + const uint8_t *signcert; + size_t signcertlen; + int signcert_verified = 0; + const uint8_t *cert; + size_t certlen; + const uint8_t *cacert; + size_t cacertlen; + const uint8_t *name; + size_t namelen; + + *verify_result = -1; + + if (x509_cert_from_der(&signcert, &signcertlen, &certs, &certslen) != 1) { + error_print(); + return -1; + } + if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1) { + error_print(); + return -1; + } + // 要检查这两个证书的类型是否分别为签名和加密证书 + // FIXME: 检查depth + while (certslen) { + if (x509_cert_from_der(&cacert, &cacertlen, &certs, &certslen) != 1) { + error_print(); + return -1; + } + if (!signcert_verified) { + if (x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, + SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { + error_print(); + return -1; + } + signcert_verified = 1; + } + if (x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, + SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { + error_print(); + return -1; + } + cert = cacert; + certlen = cacertlen; + } + if (x509_cert_get_issuer(cert, certlen, &name, &namelen) != 1) { + error_print(); + return -1; + } + if (x509_certs_get_cert_by_subject(rootcerts, rootcertslen, name, namelen, &cacert, &cacertlen) != 1) { + error_print(); + return -1; + } + if (!signcert_verified) { + if (x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, + SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { + error_print(); + return -1; + } + } + if (x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, + SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { + error_print(); + return -1; + } + return 1; +} + + int x509_certs_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { const uint8_t *p; diff --git a/tools/certverify.c b/tools/certverify.c index ea008b2f..e7dc7037 100644 --- a/tools/certverify.c +++ b/tools/certverify.c @@ -53,30 +53,7 @@ #include -// 这里面我们想支持证书链的验证 -// 首先输入的应该是一个证书链 -// 需要兼容TLCP的双证书证书链 -// 验证完之后,最后一个证书需要由一个ROOTCA证书来验证 - -/* - -首先从证书链中读取第一个证书,如果没有读取到证书就失败了 - -从证书链中尝试读取一个证书,如果没有读取到,这个就结束了 -如果读取到,存放在CA证书中 -验证证书 -将CA证书copy到被验证证书缓冲中 - -从证书链中读取一个证书,如果没有读取到,就技术了 -如果读取到,存在在CA证书中 -验证证书 -将CA证书copy到被验证证书缓冲中 - -*/ - - - -static const char *options = "[-in pem] -cacert pem\n"; +static const char *options = "-in pem [-double_certs] -cacert pem\n"; int certverify_main(int argc, char **argv) { @@ -88,11 +65,16 @@ int certverify_main(int argc, char **argv) FILE *cacertfp = NULL; uint8_t cert[1024]; size_t certlen; - const uint8_t *subject; - size_t subject_len; uint8_t cacert[1024]; size_t cacertlen; - char *signer_id = SM2_DEFAULT_ID; + const uint8_t *subject; + size_t subject_len; + const uint8_t *subj; + size_t subj_len; + + int double_certs = 0; + uint8_t enc_cert[1024]; + size_t enc_cert_len; int rv; argc--; @@ -115,6 +97,8 @@ int certverify_main(int argc, char **argv) fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno)); goto end; } + } else if (!strcmp(*argv, "-double_certs")) { + double_certs = 1; } else if (!strcmp(*argv, "-cacert")) { if (--argc < 1) goto bad; cacertfile = *(++argv); @@ -122,9 +106,6 @@ int certverify_main(int argc, char **argv) fprintf(stderr, "%s: open '%s' failure : %s\n", prog, cacertfile, strerror(errno)); goto end; } - } else if (!strcmp(*argv, "-id")) { - if (--argc < 1) goto bad; - signer_id = *(++argv); } else { fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); goto end; @@ -137,20 +118,38 @@ bad: argv++; } + + if (!infile) { + fprintf(stderr, "%s: '-in' option required\n", prog); + goto end; + } if (!cacertfile) { fprintf(stderr, "%s: '-cacert' option required\n", prog); goto end; } - if (x509_cert_from_pem(cert, &certlen, sizeof(cert), infp) != 1) { + if (x509_cert_from_pem(cert, &certlen, sizeof(cert), infp) != 1 + || x509_cert_get_subject(cert, certlen, &subject, &subject_len) != 1) { fprintf(stderr, "%s: read certificate failure\n", prog); goto end; } - if (x509_cert_get_subject(cert, certlen, &subject, &subject_len) != 1) { - goto end; - } x509_name_print(stdout, 0, 0, "Certificate", subject, subject_len); + if (double_certs) { + + if (x509_cert_from_pem(enc_cert, &enc_cert_len, sizeof(enc_cert), infp) != 1 + || x509_cert_get_subject(enc_cert, enc_cert_len, &subj, &subj_len) != 1) { + fprintf(stderr, "%s: read encryption certficate failure\n", prog); + goto end; + } + + if (subj_len != subject_len + || memcmp(subject, subj, subj_len) != 0) { + fprintf(stderr, "%s: double certificates not compatible\n", prog); + goto end; + } + } + for (;;) { if ((rv = x509_cert_from_pem(cacert, &cacertlen, sizeof(cacert), infp)) != 1) { if (rv < 0) goto end; @@ -159,7 +158,6 @@ bad: if (x509_cert_get_subject(cacert, cacertlen, &subject, &subject_len) != 1) { goto end; } - x509_name_print(stdout, 0, 0, "Signed by", subject, subject_len); if ((rv = x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID))) < 0) { fprintf(stderr, "%s: inner error\n", prog); @@ -167,6 +165,18 @@ bad: } printf("Verification %s\n", rv ? "success" : "failure"); + if (double_certs) { + x509_name_print(stdout, 0, 0, "Certificate", subj, subj_len); + + if ((rv = x509_cert_verify_by_ca_cert(enc_cert, enc_cert_len, cacert, cacertlen, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID))) < 0) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + printf("Verification %s\n", rv ? "success" : "failure"); + double_certs = 0; + } + x509_name_print(stdout, 0, 0, "Signed by", subject, subject_len); + memcpy(cert, cacert, cacertlen); certlen = cacertlen; } @@ -180,12 +190,21 @@ final: fprintf(stderr, "%s: load CA certificate failure\n", prog); goto end; } - x509_name_print(stdout, 0, 0, "Signed by", subject, subject_len); if ((rv = x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID))) < 0) { fprintf(stderr, "%s: inner error\n", prog); goto end; } printf("Verification %s\n", rv ? "success" : "failure"); + x509_name_print(stdout, 0, 0, "Signed by", subject, subject_len); + + if (double_certs) { + if ((rv = x509_cert_verify_by_ca_cert(enc_cert, enc_cert_len, cacert, cacertlen, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID))) < 0) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + printf("Verification %s\n", rv ? "success" : "failure"); + } + ret = 0; end: if (infile && infp) fclose(infp); diff --git a/tools/gmssl.c b/tools/gmssl.c index d000acf8..7df3afce 100644 --- a/tools/gmssl.c +++ b/tools/gmssl.c @@ -222,6 +222,7 @@ int main(int argc, char **argv) return tlcp_client_main(argc, argv); } else if (!strcmp(*argv, "tlcp_server")) { return tlcp_server_main(argc, argv); +/* } else if (!strcmp(*argv, "tls12_client")) { return tls12_client_main(argc, argv); } else if (!strcmp(*argv, "tls12_server")) { @@ -230,6 +231,7 @@ int main(int argc, char **argv) return tls13_client_main(argc, argv); } else if (!strcmp(*argv, "tls13_server")) { return tls13_server_main(argc, argv); +*/ } else if (!strcmp(*argv, "sdfutil")) { return sdfutil_main(argc, argv); } else if (!strcmp(*argv, "skfutil")) { diff --git a/tools/tlcp_client.c b/tools/tlcp_client.c index a116461c..b89edd9c 100644 --- a/tools/tlcp_client.c +++ b/tools/tlcp_client.c @@ -74,6 +74,9 @@ int tlcp_client_main(int argc, char *argv[]) char buf[100] = {0}; size_t len = sizeof(buf); + char send_buf[1024] = {0}; + size_t send_len; + char *file; FILE *cacertfp = NULL; @@ -159,25 +162,40 @@ bad: return -1; } - - // 这个client 发收了一个消息就结束了 - if (tls_send(&conn, (uint8_t *)"12345\n", 6) != 1) { - error_print(); - return -1; - } - for (;;) { - memset(buf, 0, sizeof(buf)); - len = sizeof(buf); - if (tls_recv(&conn, (uint8_t *)buf, &len) != 1) { + + memset(send_buf, 0, sizeof(send_buf)); + + if (!fgets(send_buf, sizeof(send_buf), stdin)) { + if (feof(stdin)) { + tls_shutdown(&conn); + goto end; + } else { + continue; + } + } + + if (tls_send(&conn, (uint8_t *)send_buf, strlen(send_buf)) != 1) { error_print(); return -1; } - if (len > 0) { - printf("%s\n", buf); - break; + + for (;;) { + memset(buf, 0, sizeof(buf)); + len = sizeof(buf); + if (tls_recv(&conn, (uint8_t *)buf, &len) != 1) { + error_print(); + return -1; + } + if (len > 0) { + printf("%s\n", buf); + break; + } } + } + +end: return 0; } diff --git a/tools/tlcp_server.c b/tools/tlcp_server.c index 5990534e..e6c352e7 100644 --- a/tools/tlcp_server.c +++ b/tools/tlcp_server.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -174,6 +175,7 @@ bad: printf("start ...........\n"); +restart: memset(&conn, 0, sizeof(conn)); if (tlcp_accept(&conn, port, certfp, &signkey, &enckey, cacertfp, verify_buf, 4096) != 1) { @@ -183,17 +185,22 @@ bad: for (;;) { + int rv; + do { len = sizeof(buf); - if (tls_recv(&conn, (uint8_t *)buf, &len) != 1) { - fprintf(stderr, "%s: recv failure\n", prog); - goto end; + if ((rv = tls_recv(&conn, (uint8_t *)buf, &len)) != 1) { + if (rv < 0) fprintf(stderr, "%s: recv failure\n", prog); + else fprintf(stderr, "%s: Disconnected by remote\n", prog); + + close(conn.sock); + goto restart; } } while (!len); - if (tls_send(&conn, (uint8_t *)buf, len) != 1) { - fprintf(stderr, "%s: send failure\n", prog); + fprintf(stderr, "%s: send failure, close connection\n", prog); + close(conn.sock); goto end; } }