/* * Copyright 2014-2026 The GmSSL Project. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * * http://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include #include #include #include #include #include #include #include #include #include #include const int tls12_supported_groups[] = { TLS_curve_sm2p256v1, #ifdef ENABLE_SECP256R1 TLS_curve_secp256r1, #endif }; const size_t tls12_supported_groups_cnt = sizeof(tls12_supported_groups)/sizeof(tls12_supported_groups[0]); const int tls12_signature_algorithms[] = { TLS_sig_sm2sig_sm3, #if defined(ENABLE_SECP256R1) && defined(ENABLE_SHA2) TLS_sig_ecdsa_secp256r1_sha256, #endif }; const size_t tls12_signature_algorithms_cnt = sizeof(tls12_signature_algorithms)/sizeof(tls12_signature_algorithms[0]); const int tls12_cipher_suites[] = { TLS_cipher_ecdhe_sm4_cbc_sm3, TLS_cipher_ecdhe_sm4_gcm_sm3, #if defined(ENABLE_AES) && defined(ENABLE_SHA2) && defined(ENABLE_SECP256R1) TLS_cipher_ecdhe_ecdsa_with_aes_128_cbc_sha256, TLS_cipher_ecdhe_ecdsa_with_aes_128_gcm_sha256, #ifdef ENABLE_AES_CCM TLS_cipher_ecdhe_ecdsa_with_aes_128_ccm_sha256, #endif #endif }; const size_t tls12_cipher_suites_cnt = sizeof(tls12_cipher_suites)/sizeof(tls12_cipher_suites[0]); // Handshake messages int tls12_record_set_handshake_server_key_exchange(uint8_t *record, size_t *recordlen, int server_key_exchange_alg, const uint8_t *server_ecdh_params, size_t server_ecdh_params_len, int sig_alg, const uint8_t *sig, size_t siglen) { const int type = TLS_handshake_server_key_exchange; uint8_t *p = tls_handshake_data(tls_record_data(record)); size_t len = 0; if (!record || !recordlen || !sig || !siglen) { error_print(); return -1; } if (!tls_signature_scheme_name(sig_alg)) { error_print(); return -1; } if (siglen > TLS_MAX_SIGNATURE_SIZE) { error_print(); return -1; } switch (server_key_exchange_alg) { case TLS_server_key_exchange_ecdhe: if (!server_ecdh_params || !server_ecdh_params_len) { error_print(); return -1; } tls_array_to_bytes(server_ecdh_params, server_ecdh_params_len, &p, &len); break; case TLS_server_key_exchange_ecc: if (server_ecdh_params || server_ecdh_params_len) { error_print(); return -1; } break; default: error_print(); return -1; } tls_uint16_to_bytes((uint16_t)sig_alg, &p, &len); tls_uint16array_to_bytes(sig, siglen, &p, &len); tls_record_set_handshake(record, recordlen, type, NULL, len); return 1; } int tls12_record_get_handshake_server_key_exchange(const uint8_t *record, int server_key_exchange_alg, const uint8_t **server_ecdh_params, size_t *server_ecdh_params_len, int *sig_alg, const uint8_t **sig, size_t *siglen) { int type; const uint8_t *p; size_t len; uint16_t alg; if (!record || !sig_alg || !sig || !siglen) { error_print(); return -1; } if (tls_record_get_handshake(record, &type, &p, &len) != 1) { error_print(); return -1; } if (type != TLS_handshake_server_key_exchange) { error_print(); return 0; } switch (server_key_exchange_alg) { case TLS_server_key_exchange_ecdhe: if (!server_ecdh_params || !server_ecdh_params_len) { error_print(); return -1; } *server_ecdh_params = p; *server_ecdh_params_len = len; { int key_exchange_group; const uint8_t *key_exchange; size_t key_exchange_len; if (tls_server_ecdh_params_from_bytes(&key_exchange_group, &key_exchange, &key_exchange_len, &p, &len) != 1) { error_print(); return -1; } } *server_ecdh_params_len -= len; break; case TLS_server_key_exchange_ecc: if (server_ecdh_params || server_ecdh_params_len) { error_print(); return -1; } break; default: error_print(); return -1; } if (tls_uint16_from_bytes(&alg, &p, &len) != 1 || tls_uint16array_from_bytes(sig, siglen, &p, &len) != 1 || tls_length_is_zero(len) != 1) { error_print(); return -1; } if (!tls_signature_scheme_name(alg)) { error_print(); return -1; } if (!siglen) { error_print(); return -1; } *sig_alg = alg; return 1; } /* struct { ClientCertificateType certificate_types<1..2^8-1>; SignatureAndHashAlgorithm supported_signature_algorithms<2^16-1>; // TLS 1.2 only DistinguishedName certificate_authorities<0..2^16-1>; } CertificateRequest; */ int tls12_record_set_handshake_certificate_request(uint8_t *record, size_t *recordlen, const uint8_t *cert_types, size_t cert_types_len, const uint8_t *sig_algs, size_t sig_algs_len, const uint8_t *ca_names, size_t ca_names_len) { int type = TLS_handshake_certificate_request; uint8_t *p; size_t len =0; size_t datalen = 0; if (!record || !recordlen) { error_print(); return -1; } if (cert_types) { if (cert_types_len == 0 || cert_types_len > TLS_MAX_CERTIFICATE_TYPES) { error_print(); return -1; } } if (ca_names) { if (ca_names_len == 0 || ca_names_len > TLS_MAX_CA_NAMES_SIZE) { error_print(); return -1; } } tls_uint8array_to_bytes(cert_types, cert_types_len, NULL, &datalen); tls_uint16array_to_bytes(ca_names, ca_names_len, NULL, &datalen); if (datalen > TLS_MAX_HANDSHAKE_DATA_SIZE) { error_print(); return -1; } p = tls_handshake_data(tls_record_data(record)); 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, datalen); return 1; } int tls12_record_get_handshake_certificate_request(const uint8_t *record, const uint8_t **cert_types, size_t *cert_types_len, const uint8_t **sig_algs, size_t *sig_algs_len, const uint8_t **ca_names, size_t *ca_names_len) { int type; const uint8_t *cp; size_t len; size_t i; if (!record || !cert_types || !cert_types_len || !ca_names || !ca_names_len) { error_print(); return -1; } if (tls_record_get_handshake(record, &type, &cp, &len) != 1) { error_print(); return -1; } if (type != TLS_handshake_certificate_request) { error_print(); return -1; } if (tls_uint8array_from_bytes(cert_types, cert_types_len, &cp, &len) != 1 || tls_uint16array_from_bytes(ca_names, ca_names_len, &cp, &len) != 1 || tls_length_is_zero(len) != 1) { error_print(); return -1; } if (*cert_types == NULL) { error_print(); return -1; } for (i = 0; i < *cert_types_len; i++) { if (!tls_cert_type_name((*cert_types)[i])) { error_print(); return -1; } } if (*ca_names) { const uint8_t *names = *ca_names; size_t nameslen = *ca_names_len; while (nameslen) { if (tls_uint16array_from_bytes(&cp, &len, &names, &nameslen) != 1) { error_print(); return -1; } } } return 1; } int tls12_record_set_handshake_client_key_exchange(uint8_t *record, size_t *recordlen, const uint8_t *point_octets, size_t point_octets_len) { int type = TLS_handshake_client_key_exchange; uint8_t *p = tls_handshake_data(tls_record_data(record)); size_t len = 0; if (point_octets_len != 65) { error_print(); return -1; } tls_uint8array_to_bytes(point_octets, (uint8_t)point_octets_len, &p, &len); tls_record_set_handshake(record, recordlen, type, NULL, len); return 1; } int tls12_record_get_handshake_client_key_exchange(const uint8_t *record, const uint8_t **point_octets, size_t *point_octets_len) { int type; const uint8_t *p; size_t len; if (tls_record_get_handshake(record, &type, &p, &len) != 1 || type != TLS_handshake_client_key_exchange) { error_print(); return -1; } if (tls_uint8array_from_bytes(point_octets, point_octets_len, &p, &len) != 1) { error_print(); return -1; } if (*point_octets_len != 65) { error_print(); return -1; } if (len) { error_print(); return -1; } return 1; } int tls12_ctx_set_renegotiation_info(TLS_CTX *ctx, int enable) { if (!ctx || ctx->protocol != TLS_protocol_tls12) { error_print(); return -1; } ctx->renegotiation_info = enable ? 1 : 0; return 1; } int tls12_ctx_set_empty_renegotiation_info_scsv(TLS_CTX *ctx, int enable) { if (!ctx || ctx->protocol != TLS_protocol_tls12) { error_print(); return -1; } ctx->empty_renegotiation_info_scsv = enable ? 1 : 0; return 1; } static int tls12_renegotiation_info_ext_is_empty(const uint8_t *ext_data, size_t ext_datalen) { const uint8_t *renegotiated_connection; size_t renegotiated_connection_len; if (tls_uint8array_from_bytes(&renegotiated_connection, &renegotiated_connection_len, &ext_data, &ext_datalen) != 1 || tls_length_is_zero(ext_datalen) != 1) { error_print(); return -1; } return renegotiated_connection_len == 0; } static int tls12_cipher_suites_include_empty_renegotiation_info_scsv( const uint8_t *cipher_suites, size_t cipher_suites_len) { while (cipher_suites_len) { uint16_t cipher_suite; if (tls_uint16_from_bytes(&cipher_suite, &cipher_suites, &cipher_suites_len) != 1) { error_print(); return -1; } if (cipher_suite == TLS_cipher_empty_renegotiation_info_scsv) { return 1; } } return 0; } int tls_curve_match_cipher_suite(int named_curve, int cipher_suite) { switch (named_curve) { case TLS_curve_sm2p256v1: switch (cipher_suite) { case TLS_cipher_ecdhe_sm4_cbc_sm3: case TLS_cipher_ecdhe_sm4_gcm_sm3: break; default: error_print(); return -1; } break; case TLS_curve_secp256r1: switch (cipher_suite) { case TLS_cipher_ecdhe_ecdsa_with_aes_128_cbc_sha256: case TLS_cipher_ecdhe_ecdsa_with_aes_128_gcm_sha256: case TLS_cipher_ecdhe_ecdsa_with_aes_128_ccm: break; default: error_print(); return -1; } break; default: error_print(); return -1; } return 1; } int tls_signature_scheme_match_cipher_suite(int sig_alg, int cipher_suite) { switch (sig_alg) { case TLS_sig_sm2sig_sm3: switch (cipher_suite) { case TLS_cipher_ecdhe_sm4_cbc_sm3: case TLS_cipher_ecdhe_sm4_gcm_sm3: case TLS_cipher_ecc_sm4_cbc_sm3: case TLS_cipher_ecc_sm4_gcm_sm3: break; default: error_print(); return -1; } break; case TLS_sig_ecdsa_secp256r1_sha256: switch (cipher_suite) { case TLS_cipher_ecdhe_ecdsa_with_aes_128_cbc_sha256: case TLS_cipher_ecdhe_ecdsa_with_aes_128_gcm_sha256: case TLS_cipher_ecdhe_ecdsa_with_aes_128_ccm: break; default: error_print(); return -1; } break; default: error_print(); return -1; } return 1; } static int tls12_cipher_suite_match_cert_group(int cipher_suite, int cert_group) { switch (cipher_suite) { case TLS_cipher_ecdhe_sm4_cbc_sm3: case TLS_cipher_ecdhe_sm4_gcm_sm3: return cert_group == TLS_curve_sm2p256v1; case TLS_cipher_ecdhe_ecdsa_with_aes_128_cbc_sha256: case TLS_cipher_ecdhe_ecdsa_with_aes_128_gcm_sha256: case TLS_cipher_ecdhe_ecdsa_with_aes_128_ccm: return cert_group == TLS_curve_secp256r1; default: return 0; } } static int tls12_signature_scheme_match_cert_group(int sig_alg, int cert_group) { return tls_signature_scheme_group_oid(sig_alg) == tls_named_curve_oid(cert_group); } static int tls12_signature_scheme_match_cipher_suite(int sig_alg, int cipher_suite) { switch (sig_alg) { case TLS_sig_sm2sig_sm3: switch (cipher_suite) { case TLS_cipher_ecdhe_sm4_cbc_sm3: case TLS_cipher_ecdhe_sm4_gcm_sm3: return 1; } break; case TLS_sig_ecdsa_secp256r1_sha256: switch (cipher_suite) { case TLS_cipher_ecdhe_ecdsa_with_aes_128_cbc_sha256: case TLS_cipher_ecdhe_ecdsa_with_aes_128_gcm_sha256: case TLS_cipher_ecdhe_ecdsa_with_aes_128_ccm: return 1; } break; } return 0; } static int tls12_key_exchange_group_match_cipher_suite(int group, int cipher_suite) { switch (cipher_suite) { case TLS_cipher_ecdhe_sm4_cbc_sm3: case TLS_cipher_ecdhe_sm4_gcm_sm3: return group == TLS_curve_sm2p256v1; case TLS_cipher_ecdhe_ecdsa_with_aes_128_cbc_sha256: case TLS_cipher_ecdhe_ecdsa_with_aes_128_gcm_sha256: case TLS_cipher_ecdhe_ecdsa_with_aes_128_ccm: return group == TLS_curve_secp256r1; default: return 0; } } static int tls12_select_common_cipher_suites(const uint8_t *client_ciphers, size_t client_ciphers_len, const int *server_ciphers, size_t server_ciphers_cnt, int *common_ciphers, size_t *common_ciphers_cnt, size_t max_cnt) { size_t i; if (!client_ciphers || !client_ciphers_len || !server_ciphers || !server_ciphers_cnt || !common_ciphers || !common_ciphers_cnt || !max_cnt) { error_print(); return -1; } *common_ciphers_cnt = 0; for (i = 0; i < server_ciphers_cnt && *common_ciphers_cnt < max_cnt; i++) { 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[i]) { common_ciphers[(*common_ciphers_cnt)++] = server_ciphers[i]; break; } } } return *common_ciphers_cnt ? 1 : 0; } static int tls12_cert_chain_get_end_entity_group(const uint8_t *cert_chain, size_t cert_chain_len, int *group) { const uint8_t *cert; size_t certlen; X509_KEY public_key; if (!cert_chain || !cert_chain_len || !group) { error_print(); return -1; } if (x509_certs_get_cert_by_index(cert_chain, cert_chain_len, 0, &cert, &certlen) != 1 || x509_cert_get_subject_public_key(cert, certlen, &public_key) != 1) { error_print(); return -1; } if (public_key.algor != OID_ec_public_key) { error_print(); return -1; } if ((*group = tls_named_curve_from_oid(public_key.algor_param)) == 0) { error_print(); return -1; } return 1; } // 应该去掉 static int tls12_public_key_get_group(const X509_KEY *public_key, int *group) { if (!public_key || !group) { error_print(); return -1; } if (public_key->algor != OID_ec_public_key) { error_print(); return -1; } if ((*group = tls_named_curve_from_oid(public_key->algor_param)) == 0) { error_print(); return -1; } return 1; } // 应该去掉 static int tls12_select_key_exchange_group(const int *groups, size_t groups_cnt, int cipher_suite, int *selected_group) { size_t i; if (!groups || !groups_cnt || !selected_group) { error_print(); return -1; } for (i = 0; i < groups_cnt; i++) { if (tls12_key_exchange_group_match_cipher_suite(groups[i], cipher_suite)) { *selected_group = groups[i]; return 1; } } return 0; } // 这个函数的名字最好换一下 static int tls12_select_parameters(TLS_CONNECT *conn, const int *common_cipher_suites, size_t common_cipher_suites_cnt, const int *common_supported_groups, size_t common_supported_groups_cnt, const int *common_signature_algorithms, size_t common_signature_algorithms_cnt, const int *signature_algorithms_cert, size_t signature_algorithms_cert_cnt, const uint8_t *host_name, size_t host_name_len) { const uint8_t *cert_chains = conn->ctx->cert_chains; size_t cert_chains_len = conn->ctx->cert_chains_len; size_t cert_chain_idx; if (!conn || !common_cipher_suites || !common_cipher_suites_cnt || !common_supported_groups || !common_supported_groups_cnt || !common_signature_algorithms || !common_signature_algorithms_cnt) { error_print(); return -1; } if (!cert_chains || !cert_chains_len) { error_print(); return -1; } for (cert_chain_idx = 1; cert_chains_len; cert_chain_idx++) { const uint8_t *cert_chain; size_t cert_chain_len; const uint8_t *cert; size_t certlen; int cert_group; size_t i; int ret; if (tls_uint24array_from_bytes(&cert_chain, &cert_chain_len, &cert_chains, &cert_chains_len) != 1) { error_print(); return -1; } if (tls12_cert_chain_get_end_entity_group(cert_chain, cert_chain_len, &cert_group) != 1) { error_print(); return -1; } if (!tls_type_is_in_list(cert_group, common_supported_groups, common_supported_groups_cnt)) { continue; } if (x509_certs_get_cert_by_index(cert_chain, cert_chain_len, 0, &cert, &certlen) != 1) { error_print(); return -1; } if (host_name && host_name_len) { if ((ret = tls_cert_match_server_name(cert, certlen, host_name, host_name_len)) < 0) { error_print(); return -1; } else if (ret == 0) { continue; } } if (signature_algorithms_cert && signature_algorithms_cert_cnt) { if ((ret = tls_cert_chain_match_signature_algorithms_cert(cert_chain, cert_chain_len, signature_algorithms_cert, signature_algorithms_cert_cnt)) < 0) { error_print(); return -1; } else if (ret == 0) { continue; } } for (i = 0; i < common_cipher_suites_cnt; i++) { size_t j; int cipher_suite = common_cipher_suites[i]; int key_exchange_group; if (!tls12_cipher_suite_match_cert_group(cipher_suite, cert_group)) { continue; } if ((ret = tls12_select_key_exchange_group(common_supported_groups, common_supported_groups_cnt, cipher_suite, &key_exchange_group)) < 0) { error_print(); return -1; } else if (ret == 0) { continue; } for (j = 0; j < common_signature_algorithms_cnt; j++) { int sig_alg = common_signature_algorithms[j]; if (!tls12_signature_scheme_match_cert_group(sig_alg, cert_group)) { continue; } if (!tls12_signature_scheme_match_cipher_suite(sig_alg, cipher_suite)) { continue; } conn->cipher_suite = cipher_suite; conn->cert_chain = cert_chain; conn->cert_chain_len = cert_chain_len; conn->cert_chain_idx = cert_chain_idx; conn->sig_alg = sig_alg; conn->key_exchange_group = key_exchange_group; return 1; } } } warning_print(); return 0; } // TODO: Client Handshake int tls_send_client_hello(TLS_CONNECT *conn) { int ret; if (!conn->recordlen) { uint8_t exts[TLS_MAX_EXTENSIONS_SIZE]; uint8_t *pexts = exts; size_t extslen = 0; int cipher_suites[TLS_MAX_CIPHER_SUITES_COUNT + 1]; const int *client_cipher_suites = conn->ctx->cipher_suites; size_t client_cipher_suites_cnt = conn->ctx->cipher_suites_cnt; if(conn->verbose) tls_trace("send ClientHello\n"); tls_record_set_protocol(conn->record, TLS_protocol_tls1); if (tls_random_generate(conn->client_random) != 1) { error_print(); return -1; } // ec_point_formats if (tls_ec_point_formats_ext_to_bytes( ec_point_formats, ec_point_formats_cnt, &pexts, &extslen) != 1) { error_print(); return -1; } // supported_groups if (conn->ctx->supported_groups_cnt) { if (tls_supported_groups_ext_to_bytes(conn->ctx->supported_groups, conn->ctx->supported_groups_cnt, &pexts, &extslen) != 1) { error_print(); return -1; } } // signature_algorithms if (conn->ctx->signature_algorithms_cnt) { if (tls_signature_algorithms_ext_to_bytes(conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt, &pexts, &extslen) != 1) { error_print(); return -1; } } // trusted_ca_keys if (conn->ctx->trusted_ca_keys) { if (tls_trusted_ca_keys_ext_to_bytes(conn->ctx->trusted_authorities, conn->ctx->trusted_authorities_len, &pexts, &extslen) != 1) { error_print(); return -1; } } // server_name if (conn->server_name) { if (tls_server_name_ext_to_bytes(conn->host_name, conn->host_name_len, &pexts, &extslen) != 1) { error_print(); return -1; } } // renegotiation_info if (conn->ctx->renegotiation_info) { uint8_t ext_data[1] = { 0 }; if (conn->ctx->empty_renegotiation_info_scsv) { error_print(); return -1; } if (tls_ext_to_bytes(TLS_extension_renegotiation_info, ext_data, sizeof(ext_data), &pexts, &extslen) != 1) { error_print(); return -1; } } // TLS_EMPTY_RENEGOTIATION_INFO_SCSV if (conn->ctx->empty_renegotiation_info_scsv) { memcpy(cipher_suites, conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt * sizeof(conn->ctx->cipher_suites[0])); cipher_suites[conn->ctx->cipher_suites_cnt] = TLS_cipher_empty_renegotiation_info_scsv; client_cipher_suites = cipher_suites; client_cipher_suites_cnt = conn->ctx->cipher_suites_cnt + 1; } if (tls_record_set_handshake_client_hello(conn->record, &conn->recordlen, conn->protocol, conn->client_random, NULL, 0, client_cipher_suites, client_cipher_suites_cnt, exts, extslen) != 1) { error_print(); return -1; } if (conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); // backup ClientHello memcpy(conn->plain_record, conn->record, conn->recordlen); conn->plain_recordlen = conn->recordlen; if (tls_update_transcript(conn, conn->record) != 1) { error_print(); return -1; } } /* if (conn->client_certificate_verify) { sm2_sign_update(&conn->sign_ctx, conn->record + 5, conn->recordlen - 5); } */ if ((ret = tls_send_record(conn)) != 1) { if (ret != TLS_ERROR_SEND_AGAIN) { error_print(); } return ret; } tls_clean_record(conn); return 1; } int tls_recv_server_hello(TLS_CONNECT *conn) { int ret; int protocol; int cipher_suite; const uint8_t *server_random; const uint8_t *session_id; size_t session_id_len; const uint8_t *exts; size_t extslen; const uint8_t *ec_point_formats = NULL; size_t ec_point_formats_len = 0; int server_name = 0; int trusted_ca_keys = 0; int renegotiation_info = 0; if(conn->verbose) tls_trace("recv ServerHello\n"); if ((ret = tls_recv_record(conn)) != 1) { if (ret != TLS_ERROR_RECV_AGAIN) { error_print(); } return ret; } if (conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); if (tls_record_protocol(conn->record) != conn->protocol) { error_print(); tls_send_alert(conn, TLS_alert_protocol_version); return -1; } if ((ret = tls_record_get_handshake_server_hello(conn->record, &protocol, &server_random, &session_id, &session_id_len, &cipher_suite, &exts, &extslen)) < 0) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } else if (ret == 0) { error_print(); tls_send_alert(conn, TLS_alert_unexpected_message); return -1; } // version if (protocol != conn->protocol) { error_print(); tls_send_alert(conn, TLS_alert_protocol_version); return -1; } // random memcpy(conn->server_random, server_random, 32); // session_id memcpy(conn->session_id, session_id, session_id_len); conn->session_id_len = session_id_len; // cipher_suite if (tls_type_is_in_list(cipher_suite, conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt) != 1) { error_print(); tls_send_alert(conn, TLS_alert_handshake_failure); return -1; } conn->cipher_suite = cipher_suite; if (tls_cipher_suite_get(conn->cipher_suite, &conn->cipher, &conn->digest) != 1) { error_print(); tls_send_alert(conn, TLS_alert_internal_error); return -1; } if (digest_init(&conn->dgst_ctx, conn->digest) != 1) { error_print(); return -1; } while (extslen) { int ext_type; const uint8_t *ext_data; size_t ext_datalen; if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_datalen, &exts, &extslen) != 1) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } switch (ext_type) { case TLS_extension_ec_point_formats: if (ec_point_formats) { error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } ec_point_formats = ext_data; ec_point_formats_len = ext_datalen; break; case TLS_extension_server_name: if (!conn->server_name || server_name || ext_datalen) { error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } server_name = 1; break; case TLS_extension_trusted_ca_keys: if (!conn->ctx->trusted_ca_keys || trusted_ca_keys || ext_datalen) { error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } trusted_ca_keys = 1; conn->trusted_ca_keys = 1; break; case TLS_extension_renegotiation_info: if ((!conn->ctx->renegotiation_info && !conn->ctx->empty_renegotiation_info_scsv) || renegotiation_info) { error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } if ((ret = tls12_renegotiation_info_ext_is_empty(ext_data, ext_datalen)) < 0) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } else if (ret == 0) { error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } renegotiation_info = 1; conn->secure_renegotiation = 1; break; default: error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } } if ((conn->ctx->renegotiation_info || conn->ctx->empty_renegotiation_info_scsv) && !renegotiation_info) { error_print(); tls_send_alert(conn, TLS_alert_handshake_failure); return -1; } if (ec_point_formats) { if ((ret = tls_ec_point_formats_support_uncompressed(ec_point_formats, ec_point_formats_len)) < 0) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } else if (ret == 0) { error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } } if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) { error_print(); return -1; } if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ClientHello", &conn->dgst_ctx); if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) { error_print(); return -1; } if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ServerHello", &conn->dgst_ctx); if (tls_update_transcript(conn, conn->record) != 1) { error_print(); return -1; } return 1; } int tls_recv_server_certificate(TLS_CONNECT *conn) { int ret; int verify_result = 0; const uint8_t *server_cert; size_t server_cert_len; X509_KEY server_sign_key; int server_sig_alg = 0; int server_group; int cert_sig_alg = 0; const int *signature_algorithms_cert = NULL; size_t signature_algorithms_cert_cnt = 0; if(conn->verbose) tls_trace("recv server Certificate\n"); if ((ret = tls_recv_record(conn)) != 1) { if (ret != TLS_ERROR_RECV_AGAIN) { error_print(); } return ret; } if(conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); if (tls_record_protocol(conn->record) != conn->protocol) { error_print(); tls_send_alert(conn, TLS_alert_unexpected_message); return -1; } if ((ret = tls_record_get_handshake_certificate(conn->record, conn->peer_cert_chain, &conn->peer_cert_chain_len)) < 0) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } else if (ret == 0) { error_print(); tls_send_alert(conn, TLS_alert_unexpected_message); return 0; } if (!conn->peer_cert_chain_len) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) { error_print(); return -1; } if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "Certificate", &conn->dgst_ctx); if (tls_update_transcript(conn, conn->record) != 1) { error_print(); return -1; } // server_sign_key if (x509_certs_get_cert_by_index(conn->peer_cert_chain, conn->peer_cert_chain_len, 0, &server_cert, &server_cert_len) != 1) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } if (x509_cert_get_subject_public_key(server_cert, server_cert_len, &server_sign_key) != 1) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } if (tls12_public_key_get_group(&server_sign_key, &server_group) != 1) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } // check server certificate matches negotiated cipher_suite if (!tls12_cipher_suite_match_cert_group(conn->cipher_suite, server_group)) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } switch (conn->cipher_suite) { case TLS_cipher_ecdhe_sm4_cbc_sm3: case TLS_cipher_ecdhe_sm4_gcm_sm3: case TLS_cipher_ecc_sm4_cbc_sm3: case TLS_cipher_ecc_sm4_gcm_sm3: server_sig_alg = TLS_sig_sm2sig_sm3; break; case TLS_cipher_ecdhe_ecdsa_with_aes_128_cbc_sha256: case TLS_cipher_ecdhe_ecdsa_with_aes_128_gcm_sha256: #ifdef ENABLE_AES_CCM case TLS_cipher_ecdhe_ecdsa_with_aes_128_ccm: #endif server_sig_alg = TLS_sig_ecdsa_secp256r1_sha256; break; default: error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } // check server certificate matches ClientHello.supported_groups if (conn->ctx->supported_groups_cnt) { if (!tls_type_is_in_list(server_group, conn->ctx->supported_groups, conn->ctx->supported_groups_cnt)) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } } // check server certificate matches ClientHello.signature_algorithms if (conn->ctx->signature_algorithms_cnt) { if ((ret = tls_cert_match_signature_algorithms(server_cert, server_cert_len, conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt, &cert_sig_alg)) < 0) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } else if (ret == 0) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } if (!tls12_signature_scheme_match_cert_group(cert_sig_alg, server_group) || !tls12_signature_scheme_match_cipher_suite(cert_sig_alg, conn->cipher_suite)) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } server_sig_alg = cert_sig_alg; } // check certificate-chain signatures match ClientHello.signature_algorithms_cert if (conn->signature_algorithms_cert) { signature_algorithms_cert = conn->ctx->signature_algorithms; signature_algorithms_cert_cnt = conn->ctx->signature_algorithms_cnt; } else if (conn->ctx->signature_algorithms_cnt) { signature_algorithms_cert = conn->ctx->signature_algorithms; signature_algorithms_cert_cnt = conn->ctx->signature_algorithms_cnt; } if (signature_algorithms_cert && signature_algorithms_cert_cnt) { if ((ret = tls_cert_chain_match_signature_algorithms_cert( conn->peer_cert_chain, conn->peer_cert_chain_len, signature_algorithms_cert, signature_algorithms_cert_cnt)) < 0) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } else if (ret == 0) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } } // check server certificate matches ClientHello.server_name if (conn->server_name) { if ((ret = tls_cert_match_server_name(server_cert, server_cert_len, conn->host_name, conn->host_name_len)) < 0) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } else if (ret == 0) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } } conn->signature_algorithms[0] = server_sig_alg; conn->signature_algorithms_cnt = 1; if (conn->client_certs_len) { sm2_sign_update(&conn->sign_ctx, conn->record + 5, conn->recordlen - 5); } assert(conn->ctx->verify_depth > 0 && conn->ctx->verify_depth < 10); // verify server Certificate if (conn->ctx->cacertslen) { if (x509_certs_verify(conn->peer_cert_chain, conn->peer_cert_chain_len, X509_cert_chain_server, conn->ctx->cacerts, conn->ctx->cacertslen, NULL, 0, NULL, 0, conn->ctx->verify_depth, &verify_result) != 1) { error_print(); conn->verify_result = verify_result; tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } } conn->verify_result = verify_result; return 1; } int tls_recv_server_key_exchange(TLS_CONNECT *conn) { int ret; // 这部分是被签名的值,必须要拿到 const uint8_t *server_ecdh_params; size_t server_ecdh_params_len; const uint8_t *server_key_exchange; size_t server_key_exchange_len; int sig_alg; const uint8_t *sig; size_t siglen; // verify ServerKeyExchange X509_KEY server_sign_key; int server_cert_index = 0; const uint8_t *server_cert; size_t server_cert_len; X509_SIGN_CTX sign_ctx; const void *sign_args = NULL; size_t sign_argslen = 0; if(conn->verbose) tls_trace("recv ServerKeyExchange\n"); if ((ret = tls_recv_record(conn)) != 1) { if (ret != TLS_ERROR_RECV_AGAIN) { error_print(); } return ret; } if (tls_record_protocol(conn->record) != conn->protocol) { error_print(); tls_send_alert(conn, TLS_alert_unexpected_message); return -1; } if(conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); if ((ret = tls12_record_get_handshake_server_key_exchange(conn->record, TLS_server_key_exchange_ecdhe, &server_ecdh_params, &server_ecdh_params_len, &sig_alg, &sig, &siglen)) < 0) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } else if (ret == 0) { error_print(); tls_send_alert(conn, TLS_alert_unexpected_message); return 0; } if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) { error_print(); return -1; } if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ServerKeyExchange", &conn->dgst_ctx); if (tls_update_transcript(conn, conn->record) != 1) { error_print(); return -1; } if (tls_signature_scheme_match_cipher_suite(sig_alg, conn->cipher_suite) != 1) { error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } if (conn->client_certs_len) sm2_sign_update(&conn->sign_ctx, conn->record + 5, conn->recordlen - 5); if (x509_certs_get_cert_by_index(conn->peer_cert_chain, conn->peer_cert_chain_len, server_cert_index, &server_cert, &server_cert_len) != 1) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } if (x509_cert_get_subject_public_key(server_cert, server_cert_len, &server_sign_key) != 1) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } switch (sig_alg) { case TLS_sig_sm2sig_sm3: if (server_sign_key.algor != OID_ec_public_key || server_sign_key.algor_param != OID_sm2) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } break; case TLS_sig_ecdsa_secp256r1_sha256: if (server_sign_key.algor != OID_ec_public_key || server_sign_key.algor_param != OID_secp256r1) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } break; default: error_print(); return -1; } if (server_sign_key.algor == OID_ec_public_key && server_sign_key.algor_param == OID_sm2) { sign_args = SM2_DEFAULT_ID; sign_argslen = SM2_DEFAULT_ID_LENGTH; } if (x509_verify_init(&sign_ctx, &server_sign_key, sign_args, sign_argslen, sig, siglen) != 1 || x509_verify_update(&sign_ctx, conn->client_random, 32) != 1 || x509_verify_update(&sign_ctx, conn->server_random, 32) != 1 || x509_verify_update(&sign_ctx, server_ecdh_params, server_ecdh_params_len) != 1 || x509_verify_finish(&sign_ctx) != 1) { error_print(); tls_send_alert(conn, TLS_alert_decrypt_error); return -1; } if (tls_server_ecdh_params_from_bytes(&conn->key_exchange_group, &server_key_exchange, &server_key_exchange_len, &server_ecdh_params, &server_ecdh_params_len) != 1 || tls_length_is_zero(server_ecdh_params_len) != 1) { error_print(); return -1; } if (server_key_exchange_len != sizeof(conn->peer_key_exchange)) { error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } if (tls_curve_match_cipher_suite(conn->key_exchange_group, conn->cipher_suite) != 1) { error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } memcpy(conn->peer_key_exchange, server_key_exchange, server_key_exchange_len); conn->peer_key_exchange_len = server_key_exchange_len; return 1; } int tls12_recv_certificate_request(TLS_CONNECT *conn) { int ret; uint8_t *record = conn->record; const uint8_t *cp; size_t len; int handshake_type; const uint8_t *cert_types; size_t cert_types_len; const uint8_t *sig_algs; size_t sig_algs_len; const uint8_t *ca_names; size_t ca_names_len; if(conn->verbose) tls_trace("recv CertificateRequest*\n"); if ((ret = tls_recv_record(conn)) != 1) { if (ret != TLS_ERROR_RECV_AGAIN) { error_print(); } return ret; } if (tls_record_protocol(conn->record) != conn->protocol) { error_print(); tls_send_alert(conn, TLS_alert_unexpected_message); return -1; } if (tls_record_get_handshake(record, &handshake_type, &cp, &len) != 1) { error_print(); tls_send_alert(conn, TLS_alert_unexpected_message); return -1; } if (handshake_type != TLS_handshake_certificate_request) { if(conn->verbose) tls_trace(" no CertificateRequest\n"); return 0; // 表明对方没有发送预期的报文 } if(conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); if (tls12_record_get_handshake_certificate_request(conn->record, &cert_types, &cert_types_len, &sig_algs, &sig_algs_len, &ca_names, &ca_names_len) != 1) { error_print(); tls_send_alert(conn, TLS_alert_unexpected_message); return -1; } if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) { error_print(); return -1; } if (tls_update_transcript(conn, conn->record) != 1) { error_print(); return -1; } if (tls_cert_types_has_ecdsa_sign(cert_types, cert_types_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); return -1; } sm2_sign_update(&conn->sign_ctx, conn->record + 5, conn->recordlen - 5); conn->recordlen = 0; return 1; } // 这是一个非常特殊的状态,其他的所有recv状态都是要读取的 // 但是这个状态在大多数情况下,之前已经读取完了,但是我们无法判断这个信息 int tls_recv_server_hello_done(TLS_CONNECT *conn) { int ret; if(conn->verbose) tls_trace("recv ServerHelloDone\n"); if ((ret = tls_recv_record(conn)) != 1) { if (ret != TLS_ERROR_RECV_AGAIN) { error_print(); } return ret; } if (tls_record_protocol(conn->record) != conn->protocol) { error_print(); tls_send_alert(conn, TLS_alert_unexpected_message); return -1; } if(conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); if (tls_record_get_handshake_server_hello_done(conn->record) != 1) { error_print(); tls_send_alert(conn, TLS_alert_unexpected_message); return -1; } if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) { error_print(); return -1; } if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ServerHelloDone", &conn->dgst_ctx); if (tls_update_transcript(conn, conn->record) != 1) { error_print(); return -1; } if (conn->client_certs_len) sm2_sign_update(&conn->sign_ctx, conn->record + 5, conn->recordlen - 5); return 1; } int tls_send_client_certificate(TLS_CONNECT *conn) { int ret; if(conn->verbose) tls_trace("send ClientCertificate\n"); if (conn->client_certs_len == 0) { error_print(); return -1; } if (conn->recordlen == 0) { if (tls_record_set_handshake_certificate(conn->record, &conn->recordlen, conn->client_certs, conn->client_certs_len) != 1) { error_print(); tls_send_alert(conn, TLS_alert_internal_error); return -1; } if(conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) { error_print(); return -1; } if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "client Certificate", &conn->dgst_ctx); if (tls_update_transcript(conn, conn->record) != 1) { error_print(); return -1; } } if ((ret = tls_send_record(conn)) != 1) { if (ret != TLS_ERROR_SEND_AGAIN) { error_print(); } return ret; } //sm3_update(&conn->sm3_ctx, conn->record + 5, conn->recordlen - 5); sm2_sign_update(&conn->sign_ctx, conn->record + 5, conn->recordlen - 5); return 1; } int tls_send_client_key_exchange(TLS_CONNECT *conn) { int ret; if (conn->recordlen == 0) { uint8_t point_octets[65]; uint8_t *point_octets_ptr = point_octets; size_t point_octets_len = 0; int curve_oid = tls_named_curve_oid(conn->key_exchange_group); if (conn->verbose) tls_trace("send ClientKeyExchange\n"); if (x509_key_generate(&conn->key_exchanges[0], OID_ec_public_key, &curve_oid, sizeof(curve_oid)) != 1) { error_print(); return -1; } if (x509_public_key_to_bytes(&conn->key_exchanges[0], &point_octets_ptr, &point_octets_len) != 1) { error_print(); return -1; } if (point_octets_len != sizeof(point_octets)) { error_print(); return -1; } if (tls12_record_set_handshake_client_key_exchange(conn->record, &conn->recordlen, point_octets, point_octets_len) != 1) { error_print(); tls_send_alert(conn, TLS_alert_internal_error); return -1; } if (conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) { error_print(); return -1; } if (conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ClientKeyExchange", &conn->dgst_ctx); if (tls_update_transcript(conn, conn->record) != 1) { error_print(); return -1; } if (conn->client_certs_len) { sm2_sign_update(&conn->sign_ctx, conn->record + 5, conn->recordlen - 5); } if (tls_derive_pre_master_secret(conn) != 1 || tls_derive_master_secret(conn) != 1 || tls_derive_key_block(conn) != 1 || tls_init_application_keys(conn) != 1) { error_print(); return -1; } } if ((ret = tls_send_record(conn)) != 1) { if (ret != TLS_ERROR_SEND_AGAIN) { error_print(); } return ret; } return 1; } int tls_send_certificate_verify(TLS_CONNECT *conn) { int ret; uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; size_t siglen; if (conn->verbose) tls_trace("send CertificateVerify\n"); if (conn->recordlen == 0) { X509_KEY *sign_key = &conn->ctx->x509_keys[conn->cert_chain_idx - 1]; X509_SIGN_CTX sign_ctx; const uint8_t *signer_id = NULL; size_t signer_idlen = 0; if (sign_key->algor == OID_ec_public_key && sign_key->algor_param == OID_sm2) { signer_id = (uint8_t *)SM2_DEFAULT_ID; signer_idlen = SM2_DEFAULT_ID_LENGTH; } if (x509_sign_init(&sign_ctx, sign_key, signer_id, signer_idlen) != 1 || x509_sign_update(&sign_ctx, conn->transcript, conn->transcript_len) != 1 || x509_sign_finish(&sign_ctx, sig, &siglen) != 1) { gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); error_print(); return -1; } gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); if (tls_record_set_handshake_certificate_verify(conn->record, &conn->recordlen, sig, siglen) != 1) { error_print(); tls_send_alert(conn, TLS_alert_internal_error); return -1; } if (conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) { error_print(); return -1; } if (conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ClientKeyExchange", &conn->dgst_ctx); if (tls_update_transcript(conn, conn->record) != 1) { error_print(); return -1; } } if ((ret = tls_send_record(conn)) != 1) { if (ret != TLS_ERROR_SEND_AGAIN) { error_print(); } return ret; } return 1; } int tls_send_client_finished(TLS_CONNECT *conn) { int ret; if (conn->recordlen == 0) { if(conn->verbose) tls_trace("send client {Finished}\n"); uint8_t local_verify_data[12]; if (tls_compute_verify_data(conn->digest, conn->master_secret, "client finished", &conn->dgst_ctx, local_verify_data) != 1) { error_print(); tls12_send_alert(conn, TLS_alert_internal_error); return -1; } tls_record_set_protocol(conn->plain_record, conn->protocol); if (tls_record_set_handshake_finished(conn->plain_record, &conn->plain_recordlen, local_verify_data, sizeof(local_verify_data)) != 1) { error_print(); tls12_send_alert(conn, TLS_alert_internal_error); return -1; } if(conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->plain_record, conn->plain_recordlen); if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) { error_print(); return -1; } if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "Finished", &conn->dgst_ctx); if (tls_update_transcript(conn, conn->plain_record) != 1) { error_print(); return -1; } if (tls_record_encrypt(conn->cipher_suite, &conn->client_write_mac_ctx, &conn->client_write_key, conn->client_write_iv, conn->client_seq_num, conn->plain_record, conn->plain_recordlen, conn->record, &conn->recordlen) != 1) { error_print(); tls12_send_alert(conn, TLS_alert_internal_error); return -1; } tls_seq_num_incr(conn->client_seq_num); } if ((ret = tls_send_record(conn)) != 1) { if (ret != TLS_ERROR_SEND_AGAIN) { error_print(); } return ret; } return 1; } int tls_recv_server_finished(TLS_CONNECT *conn) { int ret; uint8_t finished_record[TLS_FINISHED_RECORD_BUF_SIZE]; size_t finished_record_len; const uint8_t *verify_data; size_t verify_data_len; uint8_t local_verify_data[12]; if (tls_compute_verify_data(conn->digest, conn->master_secret, "server finished", &conn->dgst_ctx, local_verify_data) != 1) { error_print(); tls12_send_alert(conn, TLS_alert_internal_error); return -1; } // Finished if ((ret = tls_recv_record(conn)) != 1) { if (ret != TLS_ERROR_RECV_AGAIN) { error_print(); } return ret; } if(conn->verbose) tls_trace("recv server Finished\n"); if (tls_record_protocol(conn->record) != conn->protocol) { error_print(); tls12_send_alert(conn, TLS_alert_unexpected_message); return -1; } if (tls_record_decrypt(conn->cipher_suite, &conn->server_write_mac_ctx, &conn->server_write_key, conn->server_write_iv, conn->server_seq_num, conn->record, conn->recordlen, conn->plain_record, &conn->plain_recordlen) != 1) { error_print(); tls12_send_alert(conn, TLS_alert_bad_record_mac); return -1; } if(conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->plain_record, conn->plain_recordlen); tls_seq_num_incr(conn->server_seq_num); if (tls_record_get_handshake_finished(conn->plain_record, &verify_data, &verify_data_len) != 1) { error_print(); tls12_send_alert(conn, TLS_alert_unexpected_message); return -1; } if (verify_data_len != sizeof(local_verify_data)) { error_print(); tls12_send_alert(conn, TLS_alert_unexpected_message); return -1; } if (memcmp(verify_data, local_verify_data, sizeof(local_verify_data)) != 0) { error_puts("server_finished.verify_data verification failure"); tls12_send_alert(conn, TLS_alert_decrypt_error); return -1; } return 1; } //TODO: Server Handshake int tls_recv_client_hello(TLS_CONNECT *conn) { int ret; int client_verify = 0; int protocol; const uint8_t *client_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 extslen; const uint8_t *ec_point_formats = NULL; size_t ec_point_formats_len = 0; const uint8_t *supported_groups = NULL; size_t supported_groups_len = 0; const uint8_t *signature_algorithms = NULL; size_t signature_algorithms_len = 0; const uint8_t *signature_algorithms_cert = NULL; size_t signature_algorithms_cert_len = 0; int trusted_ca_keys = 0; const uint8_t *trusted_authorities = NULL; size_t trusted_authorities_len = 0; const uint8_t *server_name = NULL; size_t server_name_len = 0; const uint8_t *renegotiation_info = NULL; size_t renegotiation_info_len = 0; int empty_renegotiation_info_scsv = 0; int common_cipher_suites[TLS_MAX_CIPHER_SUITES_COUNT]; size_t common_cipher_suites_cnt = 0; int common_supported_groups[32]; size_t common_supported_groups_cnt = 0; int common_signature_algorithms[32]; size_t common_signature_algorithms_cnt = 0; int common_signature_algorithms_cert[32]; size_t common_signature_algorithms_cert_cnt = 0; const int *cert_signature_algorithms = NULL; size_t cert_signature_algorithms_cnt = 0; const uint8_t *host_name = NULL; size_t host_name_len = 0; if(conn->verbose) tls_trace("recv ClientHello\n"); if ((ret = tls_recv_record(conn)) != 1) { if (ret != TLS_ERROR_RECV_AGAIN) { error_print(); } return ret; } if(conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); if (tls_record_protocol(conn->record) != TLS_protocol_tls1) { error_print(); tls_send_alert(conn, TLS_alert_protocol_version); return -1; } if ((ret = tls_record_get_handshake_client_hello(conn->record, &protocol, &client_random, &session_id, &session_id_len, &cipher_suites, &cipher_suites_len, &exts, &extslen)) < 0) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } else if (ret == 0) { error_print(); tls_send_alert(conn, TLS_alert_unexpected_message); return -1; } if (protocol != conn->protocol) { error_print(); tls_send_alert(conn, TLS_alert_protocol_version); return -1; } memcpy(conn->client_random, client_random, 32); while (extslen) { int ext_type; const uint8_t *ext_data; size_t ext_datalen; if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_datalen, &exts, &extslen) != 1) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } switch (ext_type) { case TLS_extension_ec_point_formats: case TLS_extension_supported_groups: case TLS_extension_signature_algorithms: case TLS_extension_signature_algorithms_cert: case TLS_extension_renegotiation_info: if (!ext_data) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } break; case TLS_extension_trusted_ca_keys: case TLS_extension_server_name: break; } switch (ext_type) { case TLS_extension_ec_point_formats: if (ec_point_formats) { error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } ec_point_formats = ext_data; ec_point_formats_len = ext_datalen; break; case TLS_extension_supported_groups: if (supported_groups) { error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } supported_groups = ext_data; supported_groups_len = ext_datalen; break; case TLS_extension_signature_algorithms: if (signature_algorithms) { error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } signature_algorithms = ext_data; signature_algorithms_len = ext_datalen; break; case TLS_extension_signature_algorithms_cert: if (signature_algorithms_cert) { error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } signature_algorithms_cert = ext_data; signature_algorithms_cert_len = ext_datalen; break; case TLS_extension_trusted_ca_keys: if (trusted_ca_keys) { error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } if (tls_trusted_authorities_from_bytes(&trusted_authorities, &trusted_authorities_len, ext_data, ext_datalen) != 1) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } trusted_ca_keys = 1; break; case TLS_extension_server_name: if (server_name) { error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } server_name = ext_data; server_name_len = ext_datalen; break; case TLS_extension_renegotiation_info: if (renegotiation_info) { error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } renegotiation_info = ext_data; renegotiation_info_len = ext_datalen; break; default: warning_print(); } } if ((ret = tls12_cipher_suites_include_empty_renegotiation_info_scsv( cipher_suites, cipher_suites_len)) < 0) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } else if (ret == 1) { empty_renegotiation_info_scsv = 1; } if (renegotiation_info && empty_renegotiation_info_scsv) { error_print(); tls_send_alert(conn, TLS_alert_handshake_failure); return -1; } if (renegotiation_info) { if ((ret = tls12_renegotiation_info_ext_is_empty( renegotiation_info, renegotiation_info_len)) < 0) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } else if (ret == 0) { error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } } if (conn->ctx->renegotiation_info && (renegotiation_info || empty_renegotiation_info_scsv)) { conn->secure_renegotiation = 1; } if (ec_point_formats) { if ((ret = tls_ec_point_formats_support_uncompressed(ec_point_formats, ec_point_formats_len)) < 0) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } else if (ret == 0) { error_print(); tls_send_alert(conn, TLS_alert_illegal_parameter); return -1; } conn->ec_point_formats = 1; } if (trusted_ca_keys) { conn->trusted_ca_keys = 1; if (trusted_authorities_len > sizeof(conn->trusted_authorities)) { error_print(); tls_send_alert(conn, TLS_alert_internal_error); return -1; } if (trusted_authorities_len) { memcpy(conn->trusted_authorities, trusted_authorities, trusted_authorities_len); } conn->trusted_authorities_len = trusted_authorities_len; } if ((ret = tls12_select_common_cipher_suites(cipher_suites, cipher_suites_len, conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt, common_cipher_suites, &common_cipher_suites_cnt, sizeof(common_cipher_suites)/sizeof(common_cipher_suites[0]))) < 0) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } else if (ret == 0) { error_print(); tls_send_alert(conn, TLS_alert_handshake_failure); return -1; } if (supported_groups) { if ((ret = tls_process_supported_groups(supported_groups, supported_groups_len, conn->ctx->supported_groups, conn->ctx->supported_groups_cnt, common_supported_groups, &common_supported_groups_cnt, sizeof(common_supported_groups)/sizeof(common_supported_groups[0]))) < 0) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } else if (ret == 0) { error_print(); tls_send_alert(conn, TLS_alert_handshake_failure); return -1; } } else { if (!conn->ctx->supported_groups_cnt) { error_print(); tls_send_alert(conn, TLS_alert_handshake_failure); return -1; } // TODO: unify secure memcpy common_supported_groups_cnt = sizeof(common_supported_groups)/sizeof(common_supported_groups[0]); if (conn->ctx->supported_groups_cnt < common_supported_groups_cnt) { common_supported_groups_cnt = conn->ctx->supported_groups_cnt; } memcpy(common_supported_groups, conn->ctx->supported_groups, common_supported_groups_cnt * sizeof(conn->ctx->supported_groups[0])); } if (signature_algorithms) { if ((ret = tls_process_signature_algorithms(signature_algorithms, signature_algorithms_len, conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt, common_signature_algorithms, &common_signature_algorithms_cnt, sizeof(common_signature_algorithms)/sizeof(common_signature_algorithms[0]))) < 0) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } else if (ret == 0) { error_print(); tls_send_alert(conn, TLS_alert_handshake_failure); return -1; } } else { if (!conn->ctx->signature_algorithms_cnt) { error_print(); tls_send_alert(conn, TLS_alert_handshake_failure); return -1; } // TODO: unify secure memcpy common_signature_algorithms_cnt = sizeof(common_signature_algorithms)/sizeof(common_signature_algorithms[0]); if (conn->ctx->signature_algorithms_cnt < common_signature_algorithms_cnt) common_signature_algorithms_cnt = conn->ctx->signature_algorithms_cnt; memcpy(common_signature_algorithms, conn->ctx->signature_algorithms, common_signature_algorithms_cnt * sizeof(conn->ctx->signature_algorithms[0])); } if (signature_algorithms_cert) { if ((ret = tls_process_signature_algorithms(signature_algorithms_cert, signature_algorithms_cert_len, conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt, common_signature_algorithms_cert, &common_signature_algorithms_cert_cnt, sizeof(common_signature_algorithms_cert)/sizeof(common_signature_algorithms_cert[0]))) < 0) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } else if (ret == 0) { error_print(); tls_send_alert(conn, TLS_alert_handshake_failure); return -1; } cert_signature_algorithms = common_signature_algorithms_cert; cert_signature_algorithms_cnt = common_signature_algorithms_cert_cnt; } else if (signature_algorithms) { cert_signature_algorithms = common_signature_algorithms; cert_signature_algorithms_cnt = common_signature_algorithms_cnt; } if (server_name) { if (tls_server_name_from_bytes(&host_name, &host_name_len, server_name, server_name_len) != 1) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } conn->server_name = 1; } if ((ret = tls12_select_parameters(conn, common_cipher_suites, common_cipher_suites_cnt, common_supported_groups, common_supported_groups_cnt, common_signature_algorithms, common_signature_algorithms_cnt, cert_signature_algorithms, cert_signature_algorithms_cnt, host_name, host_name_len)) < 0) { error_print(); tls_send_alert(conn, TLS_alert_decode_error); return -1; } else if (ret == 0) { error_print(); tls_send_alert(conn, TLS_alert_handshake_failure); return -1; } if (tls_cipher_suite_get(conn->cipher_suite, &conn->cipher, &conn->digest) != 1) { error_print(); tls_send_alert(conn, TLS_alert_internal_error); return -1; } if (digest_init(&conn->dgst_ctx, conn->digest) != 1) { error_print(); return -1; } if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) { error_print(); return -1; } if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ClientHello", &conn->dgst_ctx); if (tls_update_transcript(conn, conn->record) != 1) { error_print(); return -1; } tls_clean_record(conn); return 1; } int tls_send_server_hello(TLS_CONNECT *conn) { int ret; if(conn->verbose) tls_trace("send ServerHello\n"); if (conn->recordlen == 0) { uint8_t exts[512]; uint8_t *pexts = exts; size_t extslen = 0; tls_record_set_protocol(conn->record, conn->protocol); if (tls_random_generate(conn->server_random) != 1) { error_print(); return -1; } // extensions in ServerHello // ec_point_formats if (conn->ec_point_formats) { if (tls_ec_point_formats_ext_to_bytes(ec_point_formats, ec_point_formats_cnt, &pexts, &extslen) != 1) { error_print(); return -1; } } // server_name if (conn->server_name) { if (tls_ext_to_bytes(TLS_extension_server_name, NULL, 0, &pexts, &extslen) != 1) { error_print(); return -1; } } // trusted_ca_keys if (conn->trusted_ca_keys) { if (tls_ext_to_bytes(TLS_extension_trusted_ca_keys, NULL, 0, &pexts, &extslen) != 1) { error_print(); return -1; } } // renegotiation_info if (conn->secure_renegotiation) { uint8_t ext_data[1] = { 0 }; if (tls_ext_to_bytes(TLS_extension_renegotiation_info, ext_data, sizeof(ext_data), &pexts, &extslen) != 1) { error_print(); return -1; } } if (tls_record_set_handshake_server_hello(conn->record, &conn->recordlen, conn->protocol, conn->server_random, NULL, 0, conn->cipher_suite, exts, extslen) != 1) { error_print(); tls_send_alert(conn, TLS_alert_internal_error); return -1; } if(conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) { error_print(); return -1; } if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ServerHello", &conn->dgst_ctx); if (tls_update_transcript(conn, conn->record) != 1) { error_print(); return -1; } } if ((ret = tls_send_record(conn)) != 1) { if (ret != TLS_ERROR_SEND_AGAIN) { error_print(); } return ret; } if (conn->ctx->cacertslen) { tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5); } tls_clean_record(conn); return 1; } int tls_send_server_certificate(TLS_CONNECT *conn) { int ret; if (conn->verbose) tls_trace("send ServerCertificate\n"); if (conn->recordlen == 0) { if (tls_record_set_handshake_certificate(conn->record, &conn->recordlen, conn->cert_chain, conn->cert_chain_len) != 1) { error_print(); tls_send_alert(conn, TLS_alert_internal_error); return -1; } if (conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) { error_print(); return -1; } if (conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "Certificate", &conn->dgst_ctx); if (tls_update_transcript(conn, conn->record) != 1) { error_print(); return -1; } } if ((ret = tls_send_record(conn)) != 1) { if (ret != TLS_ERROR_SEND_AGAIN) { error_print(); } return ret; } return 1; } int tls_send_server_key_exchange(TLS_CONNECT *conn) { int ret; if(conn->verbose) tls_trace("send ServerKeyExchange\n"); if (conn->recordlen == 0) { int curve_oid = tls_named_curve_oid(conn->key_exchange_group); X509_KEY *sign_key = &conn->ctx->x509_keys[conn->cert_chain_idx - 1]; uint8_t server_ecdh_params[69]; uint8_t *p = server_ecdh_params; size_t server_ecdh_params_len = 0; X509_SIGN_CTX sign_ctx; const void *sign_args = NULL; size_t sign_argslen = 0; uint8_t sig[X509_SIGNATURE_MAX_SIZE]; size_t siglen; // generate server ecdh_key if (x509_key_generate(&conn->key_exchanges[0], OID_ec_public_key, &curve_oid, sizeof(curve_oid)) != 1) { error_print(); return -1; } if (tls_server_ecdh_params_to_bytes(&conn->key_exchanges[0], &p, &server_ecdh_params_len) != 1) { error_print(); return -1; } if (server_ecdh_params_len != sizeof(server_ecdh_params)) { error_print(); return -1; } // sign server_ecdh_params if (sign_key->algor == OID_ec_public_key && sign_key->algor_param == OID_sm2) { sign_args = SM2_DEFAULT_ID; sign_argslen = SM2_DEFAULT_ID_LENGTH; } if (x509_sign_init(&sign_ctx, sign_key, sign_args, sign_argslen) != 1 || x509_sign_update(&sign_ctx, conn->client_random, 32) != 1 || x509_sign_update(&sign_ctx, conn->server_random, 32) != 1 || x509_sign_update(&sign_ctx, server_ecdh_params, server_ecdh_params_len) != 1 || x509_sign_finish(&sign_ctx, sig, &siglen) != 1) { x509_sign_ctx_cleanup(&sign_ctx); error_print(); return -1; } x509_sign_ctx_cleanup(&sign_ctx); if (tls12_record_set_handshake_server_key_exchange(conn->record, &conn->recordlen, TLS_server_key_exchange_ecdhe, server_ecdh_params, server_ecdh_params_len, conn->sig_alg, sig, siglen) != 1) { error_print(); tls_send_alert(conn, TLS_alert_internal_error); return -1; } if(conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) { error_print(); return -1; } if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ServerKeyExchange", &conn->dgst_ctx); if (tls_update_transcript(conn, conn->record) != 1) { error_print(); return -1; } } if ((ret = tls_send_record(conn)) != 1) { if (ret != TLS_ERROR_SEND_AGAIN) { error_print(); } return ret; } return 1; } int tls12_send_certificate_request(TLS_CONNECT *conn) { int ret; // 如果要进行客户端证书验证,服务器要提供验证的证书,但是所有证书的 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; if (!conn->client_certificate_verify) { error_print(); return -1; } if (conn->recordlen == 0) { if(conn->verbose) tls_trace("send CertificateRequest\n"); if (tls_authorities_from_certs(ca_names, &ca_names_len, sizeof(ca_names), conn->ctx->cacerts, conn->ctx->cacertslen) != 1) { error_print(); tls_send_alert(conn, TLS_alert_internal_error); return -1; } if (tls12_record_set_handshake_certificate_request(conn->record, &conn->recordlen, cert_types, sizeof(cert_types), NULL, 0, // TODO: 这里需要至少添加TLS_cert_type_ecdsa_sign ca_names, ca_names_len) != 1) { error_print(); tls_send_alert(conn, TLS_alert_internal_error); return -1; } if(conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) { error_print(); return -1; } if (tls_update_transcript(conn, conn->record) != 1) { error_print(); return -1; } } if ((ret = tls_send_record(conn)) != 1) { if (ret != TLS_ERROR_SEND_AGAIN) { error_print(); } return ret; } return 1; } int tls_send_server_hello_done(TLS_CONNECT *conn) { int ret; if(conn->verbose) tls_trace("send ServerHelloDone\n"); if (conn->recordlen == 0) { tls_record_set_handshake_server_hello_done(conn->record, &conn->recordlen); if(conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) { error_print(); return -1; } if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ServerHelloDone", &conn->dgst_ctx); if (tls_update_transcript(conn, conn->record) != 1) { error_print(); return -1; } } if ((ret = tls_send_record(conn)) != 1) { if (ret != TLS_ERROR_SEND_AGAIN) { error_print(); } return ret; } if (conn->client_certs_len) { tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5); } return 1; } // 只有在需要验证客户端证书的时候这个函数才执行,是否内部要判断一下 int tls_recv_client_certificate(TLS_CONNECT *conn) { int ret; int verify_result = 0; if(conn->verbose) tls_trace("recv ClientCertificate\n"); if (conn->ctx->cacertslen == 0) { error_print(); return -1; } if ((ret = tls_recv_record(conn)) != 1) { if (ret != TLS_ERROR_RECV_AGAIN) { error_print(); } return ret; } if (tls_record_protocol(conn->record) != conn->protocol) { // protocol检查应该在trace之后 error_print(); tls_send_alert(conn, TLS_alert_unexpected_message); return -1; } if(conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); if (tls_record_get_handshake_certificate(conn->record, conn->client_certs, &conn->client_certs_len) != 1) { error_print(); tls_send_alert(conn, TLS_alert_unexpected_message); return -1; } if (x509_certs_verify(conn->client_certs, conn->client_certs_len, X509_cert_chain_client, conn->ctx->cacerts, conn->ctx->cacertslen, NULL, 0, NULL, 0, conn->ctx->verify_depth, &verify_result) != 1) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) { error_print(); return -1; } if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "client Certificate", &conn->dgst_ctx); if (tls_update_transcript(conn, conn->record) != 1) { error_print(); return -1; } //sm3_update(&conn->sm3_ctx, conn->record + 5, conn->recordlen - 5); tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5); return 1; } int tls_recv_client_key_exchange(TLS_CONNECT *conn) { int ret; const uint8_t *point_octets; size_t point_octets_len; if ((ret = tls_recv_record(conn)) != 1) { if (ret != TLS_ERROR_RECV_AGAIN) { error_print(); } return ret; } if (conn->verbose) tls_trace("recv ClientKeyExchange\n"); if (tls_record_protocol(conn->record) != conn->protocol) { error_print(); tls_send_alert(conn, TLS_alert_unexpected_message); return -1; } if (conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) { error_print(); return -1; } if (conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ClientKeyExchange", &conn->dgst_ctx); if (tls_update_transcript(conn, conn->record) != 1) { error_print(); return -1; } if (tls12_record_get_handshake_client_key_exchange(conn->record, &point_octets, &point_octets_len) != 1) { error_print(); tls_send_alert(conn, TLS_alert_unexpected_message); return -1; } if (point_octets_len != 65) { error_print(); return -1; } memcpy(conn->peer_key_exchange, point_octets, point_octets_len); conn->peer_key_exchange_len = point_octets_len; if (tls_derive_pre_master_secret(conn) != 1 || tls_derive_master_secret(conn) != 1 || tls_derive_key_block(conn) != 1 || tls_init_application_keys(conn) != 1) { error_print(); return -1; } if (conn->ctx->cacertslen) { tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5); } return 1; } int tls_recv_certificate_verify(TLS_CONNECT *conn) { int ret; X509_SIGN_CTX sign_ctx; X509_KEY client_sign_key; const uint8_t *signer_id = NULL; size_t signer_idlen = 0; const uint8_t *sig; size_t siglen; const uint8_t *client_cert; size_t client_cert_len; if (!conn->client_certificate_verify) { error_print(); return -1; } if (conn->verbose) tls_trace("recv CertificateVerify\n"); if ((ret = tls_recv_record(conn)) != 1) { if (ret != TLS_ERROR_RECV_AGAIN) { error_print(); } return ret; } if (tls_record_protocol(conn->record) != conn->protocol) { tls_send_alert(conn, TLS_alert_unexpected_message); error_print(); return -1; } if (conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); // get signature from certificate_verify if (tls_record_get_handshake_certificate_verify(conn->record, &sig, &siglen) != 1) { tls_send_alert(conn, TLS_alert_unexpected_message); error_print(); return -1; } // get sign_key from client certificate if (x509_certs_get_cert_by_index(conn->client_certs, conn->client_certs_len, 0, &client_cert, &client_cert_len) != 1) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } if (x509_cert_get_subject_public_key(client_cert, client_cert_len, &client_sign_key) != 1) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } if (client_sign_key.algor != OID_ec_public_key) { error_print(); tls_send_alert(conn, TLS_alert_bad_certificate); return -1; } if (client_sign_key.algor_param == OID_sm2) { signer_id = (uint8_t *)SM2_DEFAULT_ID; signer_idlen = SM2_DEFAULT_ID_LENGTH; } if (x509_verify_init(&sign_ctx, &client_sign_key, signer_id, signer_idlen, sig, siglen) != 1 || x509_verify_update(&sign_ctx, conn->transcript, conn->transcript_len) != 1 || x509_verify_finish(&sign_ctx) != 1) { error_print(); return -1; } if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) { error_print(); return -1; } if (tls_update_transcript(conn, conn->record) != 1) { error_print(); return -1; } return 1; } int tls_recv_client_finished(TLS_CONNECT *conn) { int ret; const uint8_t *verify_data; size_t verify_data_len; uint8_t local_verify_data[12]; if (tls_compute_verify_data(conn->digest, conn->master_secret, "client finished", &conn->dgst_ctx, local_verify_data) != 1) { error_print(); tls_send_alert(conn, TLS_alert_internal_error); return -1; } // recv ClientFinished if(conn->verbose) tls_trace("recv client {Finished}\n"); if ((ret = tls_recv_record(conn)) != 1) { if (ret != TLS_ERROR_RECV_AGAIN) { error_print(); } return ret; } //tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); if (tls_record_protocol(conn->record) != conn->protocol) { error_print(); tls_send_alert(conn, TLS_alert_unexpected_message); return -1; } // decrypt ClientFinished if (tls_record_decrypt(conn->cipher_suite, &conn->client_write_mac_ctx, &conn->client_write_key, conn->client_write_iv, conn->client_seq_num, conn->record, conn->recordlen, conn->plain_record, &conn->plain_recordlen) != 1) { error_print(); tls_send_alert(conn, TLS_alert_bad_record_mac); return -1; } tls_seq_num_incr(conn->client_seq_num); if(conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->plain_record, conn->plain_recordlen); if (tls_record_get_handshake_finished(conn->plain_record, &verify_data, &verify_data_len) != 1) { error_print(); tls_send_alert(conn, TLS_alert_bad_record_mac); return -1; } if (verify_data_len != sizeof(local_verify_data)) { error_print(); tls_send_alert(conn, TLS_alert_bad_record_mac); return -1; } if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) { error_print(); return -1; } if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "client Finished", &conn->dgst_ctx); if (tls_update_transcript(conn, conn->plain_record) != 1) { error_print(); return -1; } // verify ClientFinished if (memcmp(verify_data, local_verify_data, sizeof(local_verify_data)) != 0) { error_puts("client_finished.verify_data verification failure"); tls_send_alert(conn, TLS_alert_decrypt_error); return -1; } return 1; } int tls_send_server_finished(TLS_CONNECT *conn) { int ret; uint8_t *record = conn->record; size_t recordlen; uint8_t local_verify_data[12]; tls_record_set_protocol(conn->plain_record, conn->protocol); if (conn->recordlen == 0) { if(conn->verbose) tls_trace("send server Finished\n"); if (tls_compute_verify_data(conn->digest, conn->master_secret, "server finished", &conn->dgst_ctx, local_verify_data) != 1) { error_print(); tls12_send_alert(conn, TLS_alert_internal_error); return -1; } if (conn->verbose >= 5) { format_bytes(stderr, 0, 0, "server verify_data", local_verify_data, 12); } if (tls_record_set_handshake_finished(conn->plain_record, &conn->plain_recordlen, local_verify_data, sizeof(local_verify_data)) != 1) { error_print(); tls12_send_alert(conn, TLS_alert_internal_error); return -1; } if(conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->plain_record, conn->plain_recordlen); if (tls_record_encrypt(conn->cipher_suite, &conn->server_write_mac_ctx, &conn->server_write_key, conn->server_write_iv, conn->server_seq_num, conn->plain_record, conn->plain_recordlen, conn->record, &conn->recordlen) != 1) { error_print(); tls12_send_alert(conn, TLS_alert_internal_error); return -1; } tls_seq_num_incr(conn->server_seq_num); } if ((ret = tls_send_record(conn)) != 1) { if (ret != TLS_ERROR_SEND_AGAIN) { error_print(); } return ret; } return 1; } int tls_send_change_cipher_spec(TLS_CONNECT *conn) { int ret; if (conn->recordlen == 0) { if(conn->verbose) tls_trace("send [ChangeCipherSpec]\n"); if (tls_record_set_change_cipher_spec(conn->record, &conn->recordlen) !=1) { error_print(); tls_send_alert(conn, TLS_alert_internal_error); return -1; } if(conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); } if ((ret = tls_send_record(conn)) != 1) { if (ret != TLS_ERROR_SEND_AGAIN) { error_print(); } return ret; } return 1; } int tls_recv_change_cipher_spec(TLS_CONNECT *conn) { int ret; if ((ret = tls_recv_record(conn)) != 1) { if (ret != TLS_ERROR_RECV_AGAIN) { error_print(); } return ret; } if(conn->verbose) tls_trace("recv [ChangeCipherSpec]\n"); if (tls_record_protocol(conn->record) != conn->protocol) { error_print(); if (conn->is_client && conn->handshake_state == TLS_state_server_change_cipher_spec) tls12_send_alert(conn, TLS_alert_unexpected_message); else tls_send_alert(conn, TLS_alert_unexpected_message); return -1; } if (conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, conn->recordlen); if (tls_record_get_change_cipher_spec(conn->record) != 1) { error_print(); if (conn->is_client && conn->handshake_state == TLS_state_server_change_cipher_spec) tls12_send_alert(conn, TLS_alert_unexpected_message); else tls_send_alert(conn, TLS_alert_unexpected_message); return -1; } return 1; } int tls12_send(TLS_CONNECT *conn, const uint8_t *in, size_t inlen, size_t *sentlen) { const HMAC_CTX *hmac_ctx; const BLOCK_CIPHER_KEY *enc_key; const uint8_t *fixed_iv; uint8_t *seq_num; size_t recordlen; int ret; if (!conn) { error_print(); return -1; } if (!in || !inlen || !sentlen) { error_print(); return -1; } if (conn->recv_state) { *sentlen = 0; return TLS_ERROR_RECV_AGAIN; } if (conn->send_state && conn->send_state != TLS_state_send_record) { error_print(); return -1; } *sentlen = 0; if (!conn->recordlen) { if (inlen > TLS_MAX_PLAINTEXT_SIZE) { inlen = TLS_MAX_PLAINTEXT_SIZE; } if (conn->datalen) { error_puts("recv all buffered data before send"); return -1; } if (conn->is_client) { hmac_ctx = &conn->client_write_mac_ctx; enc_key = &conn->client_write_key; fixed_iv = conn->client_write_iv; seq_num = conn->client_seq_num; } else { hmac_ctx = &conn->server_write_mac_ctx; enc_key = &conn->server_write_key; fixed_iv = conn->server_write_iv; seq_num = conn->server_seq_num; } if (tls_record_set_type(conn->databuf, TLS_record_application_data) != 1 || tls_record_set_protocol(conn->databuf, conn->protocol) != 1 || tls_record_set_data(conn->databuf, in, inlen) != 1) { error_print(); return -1; } if(conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->databuf, tls_record_length(conn->databuf)); switch (conn->cipher_suite) { case TLS_cipher_ecdhe_sm4_cbc_sm3: case TLS_cipher_ecdhe_ecdsa_with_aes_128_cbc_sha256: if (tls_cbc_encrypt(hmac_ctx, enc_key, seq_num, conn->databuf, conn->databuf + 5, tls_record_data_length(conn->databuf), conn->record + 5, &recordlen) != 1) { error_print(); return -1; } break; case TLS_cipher_ecdhe_sm4_gcm_sm3: case TLS_cipher_ecdhe_ecdsa_with_aes_128_gcm_sha256: if (tls_gcm_encrypt(enc_key, fixed_iv, seq_num, conn->databuf, conn->databuf + 5, tls_record_data_length(conn->databuf), conn->record + 5, &recordlen) != 1) { error_print(); return -1; } break; #ifdef ENABLE_AES_CCM case TLS_cipher_ecdhe_ecdsa_aes_128_ccm_sha256: if (tls_ccm_encrypt(enc_key, fixed_iv, seq_num, conn->databuf, conn->databuf + 5, tls_record_data_length(conn->databuf), conn->record + 5, &recordlen) != 1) { error_print(); return -1; } break; #endif default: error_print(); return -1; } tls_seq_num_incr(seq_num); conn->record[0] = conn->databuf[0]; conn->record[1] = conn->databuf[1]; conn->record[2] = conn->databuf[2]; conn->record[3] = (uint8_t)(recordlen >> 8); conn->record[4] = (uint8_t)(recordlen); recordlen += 5; conn->recordlen = recordlen; conn->record_offset = 0; conn->sentlen = inlen; conn->send_state = TLS_state_send_record; if(conn->verbose) tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->record, recordlen); } ret = tls_send_record(conn); if (ret != 1) { if (ret != TLS_ERROR_SEND_AGAIN) { error_print(); } return ret; } *sentlen = conn->sentlen; conn->send_state = 0; tls_clean_record(conn); return 1; } static int tls12_send_alert_ex(TLS_CONNECT *conn, int level, int alert) { const HMAC_CTX *hmac; const BLOCK_CIPHER_KEY *key; const uint8_t *iv; uint8_t *seq_num; int ret; if (!conn) { error_print(); return -1; } if (conn->protocol == TLS_protocol_tls13) { error_print(); return -1; } if (!tls_alert_level_name(level) || !tls_alert_description_text(alert)) { error_print(); return -1; } if (conn->send_state && conn->send_state != TLS_state_send_record) { error_print(); return -1; } if (conn->send_state == TLS_state_send_record && tls_record_type(conn->record) != TLS_record_alert) { error_print(); return -1; } if (!conn->send_state) { tls_clean_record(conn); conn->plain_recordlen = 0; if (conn->is_client) { hmac = &conn->client_write_mac_ctx; key = &conn->client_write_key; iv = conn->client_write_iv; seq_num = conn->client_seq_num; } else { hmac = &conn->server_write_mac_ctx; key = &conn->server_write_key; iv = conn->server_write_iv; seq_num = conn->server_seq_num; } tls_record_set_protocol(conn->plain_record, conn->protocol); if (tls_record_set_alert(conn->plain_record, &conn->plain_recordlen, level, alert) != 1) { error_print(); return -1; } if (conn->verbose) { tls_record_print(stderr, 0, 0, conn->cipher_suite, conn->plain_record, conn->plain_recordlen); } if (tls_record_encrypt(conn->cipher_suite, hmac, key, iv, seq_num, conn->plain_record, conn->plain_recordlen, conn->record, &conn->recordlen) != 1) { error_print(); conn->plain_recordlen = 0; tls_clean_record(conn); return -1; } tls_seq_num_incr(seq_num); conn->record_offset = 0; conn->send_state = TLS_state_send_record; if (conn->verbose) { tls_encrypted_record_print(stderr, conn->record, conn->recordlen, 0, 0); } } ret = tls_send_record(conn); if (ret != 1) { if (ret != TLS_ERROR_SEND_AGAIN) { error_print(); } return ret; } conn->send_state = 0; conn->plain_recordlen = 0; tls_clean_record(conn); return 1; } int tls12_send_alert(TLS_CONNECT *conn, int alert) { return tls12_send_alert_ex(conn, TLS_alert_level_fatal, alert); } int tls12_send_warning(TLS_CONNECT *conn, int alert) { return tls12_send_alert_ex(conn, TLS_alert_level_warning, alert); } /* Client Server ClientHello --------> ServerHello Certificate ServerKeyExchange CertificateRequest* <-------- ServerHelloDone Certificate* ClientKeyExchange CertificateVerify* [ChangeCipherSpec] Finished --------> [ChangeCipherSpec] <-------- Finished Application Data <-------> Application Data */ int tls12_do_client_handshake(TLS_CONNECT *conn) { int ret; int next_state; switch (conn->handshake_state) { case TLS_state_client_hello: ret = tls_send_client_hello(conn); next_state = TLS_state_server_hello; break; case TLS_state_server_hello: ret = tls_recv_server_hello(conn); next_state = TLS_state_server_certificate; break; case TLS_state_server_certificate: ret = tls_recv_server_certificate(conn); next_state = TLS_state_server_key_exchange; break; case TLS_state_server_key_exchange: ret = tls_recv_server_key_exchange(conn); next_state = TLS_state_certificate_request; break; case TLS_state_certificate_request: ret = tls12_recv_certificate_request(conn); if (ret == 1) conn->client_certificate_verify = 1; next_state = TLS_state_server_hello_done; break; case TLS_state_server_hello_done: ret = tls_recv_server_hello_done(conn); if (conn->client_certificate_verify) next_state = TLS_state_client_certificate; else next_state = TLS_state_client_key_exchange; break; case TLS_state_client_certificate: ret = tls_send_client_certificate(conn); next_state = TLS_state_client_key_exchange; break; case TLS_state_client_key_exchange: ret = tls_send_client_key_exchange(conn); if (conn->client_certificate_verify) next_state = TLS_state_certificate_verify; else next_state = TLS_state_client_change_cipher_spec; break; case TLS_state_certificate_verify: ret = tls_send_certificate_verify(conn); next_state = TLS_state_client_change_cipher_spec; break; case TLS_state_client_change_cipher_spec: ret = tls_send_change_cipher_spec(conn); next_state = TLS_state_client_finished; break; case TLS_state_client_finished: ret = tls_send_client_finished(conn); next_state = TLS_state_server_change_cipher_spec; break; case TLS_state_server_change_cipher_spec: ret = tls_recv_change_cipher_spec(conn); next_state = TLS_state_server_finished; break; case TLS_state_server_finished: ret = tls_recv_server_finished(conn); next_state = TLS_state_handshake_over; break; default: error_print(); return -1; } if (ret < 0) { if (ret == TLS_ERROR_RECV_AGAIN || ret == TLS_ERROR_SEND_AGAIN) { return ret; } else { error_print(); return ret; } } conn->handshake_state = next_state; // ret == 0 means this step is bypassed if (ret == 1) { tls_clean_record(conn); } return 1; } int tls12_do_server_handshake(TLS_CONNECT *conn) { int ret; int next_state; switch (conn->handshake_state) { case TLS_state_client_hello: ret = tls_recv_client_hello(conn); next_state = TLS_state_server_hello; break; case TLS_state_server_hello: ret = tls_send_server_hello(conn); next_state = TLS_state_server_certificate; break; case TLS_state_server_certificate: ret = tls_send_server_certificate(conn); next_state = TLS_state_server_key_exchange; break; case TLS_state_server_key_exchange: ret = tls_send_server_key_exchange(conn); if (conn->client_certificate_verify) next_state = TLS_state_certificate_request; else next_state = TLS_state_server_hello_done; break; case TLS_state_certificate_request: ret = tls12_send_certificate_request(conn); next_state = TLS_state_server_hello_done; break; case TLS_state_server_hello_done: ret = tls_send_server_hello_done(conn); if (conn->client_certificate_verify) next_state = TLS_state_client_certificate; else next_state = TLS_state_client_key_exchange; break; case TLS_state_client_certificate: ret = tls_recv_client_certificate(conn); next_state = TLS_state_client_key_exchange; break; case TLS_state_client_key_exchange: ret = tls_recv_client_key_exchange(conn); if (conn->client_certificate_verify) next_state = TLS_state_certificate_verify; else next_state = TLS_state_client_change_cipher_spec; break; case TLS_state_certificate_verify: ret = tls_recv_certificate_verify(conn); next_state = TLS_state_client_change_cipher_spec; break; case TLS_state_client_change_cipher_spec: ret = tls_recv_change_cipher_spec(conn); next_state = TLS_state_client_finished; break; case TLS_state_client_finished: ret = tls_recv_client_finished(conn); next_state = TLS_state_server_change_cipher_spec; break; case TLS_state_server_change_cipher_spec: ret = tls_send_change_cipher_spec(conn); next_state = TLS_state_server_finished; break; case TLS_state_server_finished: ret = tls_send_server_finished(conn); next_state = TLS_state_handshake_over; break; default: error_print(); return -1; } if (ret != 1) { if (ret == TLS_ERROR_RECV_AGAIN || ret == TLS_ERROR_SEND_AGAIN) { return ret; } else { error_print(); return ret; } } conn->handshake_state = next_state; tls_clean_record(conn); return 1; } // 这个函数显然是不对的,因为这个函数就是一个重入的函数,重入函数不应该自己设置状态啊 int tls12_client_handshake(TLS_CONNECT *conn) { int ret; while (conn->handshake_state != TLS_state_handshake_over) { ret = tls12_do_client_handshake(conn); if (ret != 1) { if (ret != TLS_ERROR_RECV_AGAIN && ret != TLS_ERROR_SEND_AGAIN) { error_print(); } return ret; } } // TODO: cleanup conn? return 1; } int tls12_server_handshake(TLS_CONNECT *conn) { int ret; while (conn->handshake_state != TLS_state_handshake_over) { ret = tls12_do_server_handshake(conn); if (ret != 1) { if (ret != TLS_ERROR_RECV_AGAIN && ret != TLS_ERROR_SEND_AGAIN) { error_print(); } return ret; } } // TODO: cleanup conn? return 1; } int tls12_do_connect(TLS_CONNECT *conn) { int ret; if (conn->handshake_state == TLS_state_handshake_over) { return 1; } if (conn->handshake_state == TLS_state_handshake_init) { conn->handshake_state = TLS_state_client_hello; digest_init(&conn->dgst_ctx, DIGEST_sm3()); } ret = tls12_client_handshake(conn); if (ret == 1 || ret == TLS_ERROR_RECV_AGAIN || ret == TLS_ERROR_SEND_AGAIN) { return ret; } error_print(); return -1; } int tls12_do_accept(TLS_CONNECT *conn) { int ret; if (conn->handshake_state == TLS_state_handshake_over) { return 1; } if (conn->handshake_state == TLS_state_handshake_init) { conn->handshake_state = TLS_state_client_hello; digest_init(&conn->dgst_ctx, DIGEST_sm3()); } ret = tls12_server_handshake(conn); if (ret == 1 || ret == TLS_ERROR_RECV_AGAIN || ret == TLS_ERROR_SEND_AGAIN) { return ret; } error_print(); return -1; }