Files
GmSSL/src/tls12.c
Zhi Guan f4abd90fba Fix bugs
2026-06-19 17:18:59 +08:00

3483 lines
88 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 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 <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <gmssl/x509.h>
#include <gmssl/error.h>
#include <gmssl/sm2.h>
#include <gmssl/sm3.h>
#include <gmssl/sm4.h>
#include <gmssl/pem.h>
#include <gmssl/mem.h>
#include <gmssl/tls.h>
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;
}