/*
 *  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/x509_ext.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,
#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;
*/
static int tls12_supported_signature_algorithms_to_bytes(const int *sig_algs, size_t sig_algs_cnt,
	uint8_t **out, size_t *outlen)
{
	size_t i;

	if (!sig_algs || !sig_algs_cnt || !outlen) {
		error_print();
		return -1;
	}
	if (sig_algs_cnt > ((1 << 16) - 2)/2) {
		error_print();
		return -1;
	}
	tls_uint16_to_bytes((uint16_t)(sig_algs_cnt * tls_uint16_size()), out, outlen);
	for (i = 0; i < sig_algs_cnt; i++) {
		if (!tls_signature_scheme_name(sig_algs[i])) {
			error_print();
			return -1;
		}
		tls_uint16_to_bytes((uint16_t)sig_algs[i], out, outlen);
	}
	return 1;
}

static int tls12_supported_signature_algorithms_from_bytes(const uint8_t **sig_algs, size_t *sig_algs_len,
	const uint8_t **in, size_t *inlen)
{
	const uint8_t *d;
	size_t dlen;
	const uint8_t *p;
	size_t len;
	const uint8_t *cp;
	size_t cplen;

	if (!sig_algs || !sig_algs_len || !in || !inlen) {
		error_print();
		return -1;
	}

	d = *in;
	dlen = *inlen;
	if (tls_uint16array_from_bytes(&p, &len, in, inlen) != 1) {
		error_print();
		return -1;
	}
	if (len < tls_uint16_size() || len % tls_uint16_size()) {
		error_print();
		return -1;
	}

	cp = p;
	cplen = len;
	while (cplen) {
		uint16_t sig_alg;

		if (tls_uint16_from_bytes(&sig_alg, &cp, &cplen) != 1) {
			error_print();
			return -1;
		}
		if (!tls_signature_scheme_name(sig_alg)) {
			warning_print();
		}
	}

	*sig_algs = d;
	*sig_algs_len = dlen - *inlen;
	return 1;
}

int tls12_record_set_handshake_certificate_request(uint8_t *record, size_t *recordlen,
	const uint8_t *cert_types, size_t cert_types_len,
	const int *sig_algs, size_t sig_algs_cnt,
	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 (!sig_algs || !sig_algs_cnt) {
		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);
	if (tls12_supported_signature_algorithms_to_bytes(sig_algs, sig_algs_cnt, NULL, &datalen) != 1) {
		error_print();
		return -1;
	}
	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);
	if (tls12_supported_signature_algorithms_to_bytes(sig_algs, sig_algs_cnt, &p, &len) != 1) {
		error_print();
		return -1;
	}
	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
		|| !sig_algs || !sig_algs_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
		|| tls12_supported_signature_algorithms_from_bytes(sig_algs, sig_algs_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;
}

static int tls12_record_set_handshake_certificate_verify(uint8_t *record, size_t *recordlen,
	int sig_alg, const uint8_t *sig, size_t siglen)
{
	int type = TLS_handshake_certificate_verify;
	uint8_t *p;
	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;
	}
	p = tls_handshake_data(tls_record_data(record));
	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;
}

static int tls12_record_get_handshake_certificate_verify(const uint8_t *record,
	int *sig_alg, const uint8_t **sig, size_t *siglen)
{
	int type;
	const uint8_t *cp;
	size_t len;
	uint16_t alg;

	if (!record || !sig_alg || !sig || !siglen) {
		error_print();
		return -1;
	}
	if (tls_record_get_handshake(record, &type, &cp, &len) != 1) {
		error_print();
		return -1;
	}
	if (type != TLS_handshake_certificate_verify) {
		error_print();
		return -1;
	}
	if (tls_uint16_from_bytes(&alg, &cp, &len) != 1
		|| tls_uint16array_from_bytes(sig, siglen, &cp, &len) != 1
		|| tls_length_is_zero(len) != 1) {
		error_print();
		return -1;
	}
	if (!tls_signature_scheme_name(alg)) {
		error_print();
		return -1;
	}
	*sig_alg = alg;
	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_tlcp_signature_scheme(int cipher_suite, int *sig_alg)
{
	if (!sig_alg) {
		error_print();
		return -1;
	}
	switch (cipher_suite) {
	case TLS_cipher_ecc_sm4_cbc_sm3:
	case TLS_cipher_ecc_sm4_gcm_sm3:
	case TLS_cipher_ecdhe_sm4_cbc_sm3:
	case TLS_cipher_ecdhe_sm4_gcm_sm3:
		*sig_alg = TLS_sig_sm2sig_sm3;
		return 1;
	default:
		error_print();
		return -1;
	}
}

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 + 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 (conn->protocol == TLS_protocol_tlcp
		&& tls12_select_tlcp_signature_scheme(conn->cipher_suite, &conn->sig_alg) != 1) {
		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;
	}


	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 = X509_verify_ok;
	int server_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;
	}

	// 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 (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 (tls_cert_chain_verify(conn->protocol, X509_cert_chain_server, conn->cipher_suite,
		conn->ctx->cacertslen ? 1 : 0,
		conn->peer_cert_chain, conn->peer_cert_chain_len,
		conn->ctx->cacerts, conn->ctx->cacertslen,
		NULL, 0,
		NULL, 0,
		conn->ctx->verify_depth,
		conn->ctx->supported_groups, conn->ctx->supported_groups_cnt,
		conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt,
		signature_algorithms_cert, signature_algorithms_cert_cnt,
		NULL, 0,
		NULL, 0,
		conn->host_name, conn->host_name_len,
		&verify_result, &server_sig_alg) != 1) {
		error_print();
		conn->verify_result = verify_result;
		tls_send_alert(conn, TLS_alert_bad_certificate);
		return -1;
	}
	conn->verify_result = verify_result;
	conn->signature_algorithms[0] = server_sig_alg;
	conn->signature_algorithms_cnt = 1;

	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, tls_signature_scheme_algorithm_oid(sig_alg),
		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 int *local_sig_algs;
	size_t local_sig_algs_cnt;
	int common_sig_algs[32];
	size_t common_sig_algs_cnt = 0;
	const uint8_t *ca_names;
	size_t ca_names_len;
	const uint8_t *client_cert;
	size_t client_cert_len;
	int client_sig_alg;

	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;
	}

	local_sig_algs = conn->ctx->signature_algorithms;
	local_sig_algs_cnt = conn->ctx->signature_algorithms_cnt;
	if (!local_sig_algs_cnt) {
		local_sig_algs = tls12_signature_algorithms;
		local_sig_algs_cnt = tls12_signature_algorithms_cnt;
	}
	if ((ret = tls_process_signature_algorithms(sig_algs, sig_algs_len,
		local_sig_algs, local_sig_algs_cnt,
		common_sig_algs, &common_sig_algs_cnt,
		sizeof(common_sig_algs)/sizeof(common_sig_algs[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_unsupported_certificate);
		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;
	}
	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 ((ret = tls_cert_match_signature_algorithms(client_cert, client_cert_len,
		common_sig_algs, common_sig_algs_cnt, &client_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_unsupported_certificate);
		return -1;
	}
	if ((ret = tls_cert_chain_match_signature_algorithms_cert(conn->client_certs, conn->client_certs_len,
		common_sig_algs, common_sig_algs_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_unsupported_certificate);
		return -1;
	}

	conn->sig_alg = client_sig_alg;

	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;
}

static int tlcp_cert_is_encryption_cert(const uint8_t *cert, size_t certlen)
{
	int ret;
	int critical;
	const uint8_t *exts;
	size_t extslen;
	const uint8_t *val;
	size_t vlen;
	int bits;

	if (!cert || !certlen) {
		error_print();
		return -1;
	}
	if ((ret = x509_cert_get_exts(cert, certlen, &exts, &extslen)) != 1) {
		if (ret) error_print();
		return ret;
	}
	if ((ret = x509_exts_get_ext_by_oid(exts, extslen, OID_ce_key_usage,
		&critical, &val, &vlen)) != 1) {
		if (ret) error_print();
		return ret;
	}
	if (x509_key_usage_from_der(&bits, &val, &vlen) != 1
		|| asn1_length_is_zero(vlen) != 1) {
		error_print();
		return -1;
	}
	return (bits & X509_KU_KEY_ENCIPHERMENT) ? 1 : 0;
}

static int tlcp_client_certs_without_encryption_cert(const uint8_t *certs, size_t certslen,
	uint8_t *out, size_t *outlen, size_t maxlen)
{
	const uint8_t *p = certs;
	size_t len = certslen;
	size_t cert_idx = 0;

	if (!certs || !certslen || !out || !outlen) {
		error_print();
		return -1;
	}

	*outlen = 0;
	while (len) {
		const uint8_t *cert_der = p;
		const uint8_t *cert;
		size_t certlen;
		size_t derlen;
		int skip = 0;

		if (x509_cert_from_der(&cert, &certlen, &p, &len) != 1) {
			error_print();
			return -1;
		}
		derlen = (size_t)(p - cert_der);
		if (cert_idx == 1) {
			int ret = tlcp_cert_is_encryption_cert(cert, certlen);
			if (ret < 0) {
				error_print();
				return -1;
			}
			skip = ret;
		}
		if (!skip) {
			if (*outlen > maxlen || derlen > maxlen - *outlen) {
				error_print();
				return -1;
			}
			memcpy(out + *outlen, cert_der, derlen);
			*outlen += derlen;
		}
		cert_idx++;
	}
	return 1;
}

int tls_send_client_certificate(TLS_CONNECT *conn)
{
	int ret;
	const uint8_t *client_certs;
	size_t client_certs_len;
	uint8_t client_certs_without_enc[TLS_MAX_CERTIFICATES_SIZE];
	size_t client_certs_without_enc_len;

	if(conn->verbose) tls_trace("send client Certificate\n");

	if (conn->client_certs_len == 0) {
		error_print();
		return -1;
	}

	if (conn->recordlen == 0) {
		client_certs = conn->client_certs;
		client_certs_len = conn->client_certs_len;
		if (conn->protocol == TLS_protocol_tlcp
			&& (conn->cipher_suite == TLS_cipher_ecc_sm4_cbc_sm3
				|| conn->cipher_suite == TLS_cipher_ecc_sm4_gcm_sm3)) {
			if (tlcp_client_certs_without_encryption_cert(conn->client_certs, conn->client_certs_len,
				client_certs_without_enc, &client_certs_without_enc_len,
				sizeof(client_certs_without_enc)) != 1) {
				error_print();
				tls_send_alert(conn, TLS_alert_internal_error);
				return -1;
			}
			client_certs = client_certs_without_enc;
			client_certs_len = client_certs_without_enc_len;
		}
		if (tls_record_set_handshake_certificate(conn->record, &conn->recordlen,
			client_certs, 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;
		int sign_algor = OID_undef;
		const uint8_t *signer_id = NULL;
		size_t signer_idlen = 0;

		sign_algor = tls_signature_scheme_algorithm_oid(conn->sig_alg);
		if (sign_algor == OID_undef) {
			error_print();
			return -1;
		}
		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, sign_algor, 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 (conn->protocol == TLS_protocol_tls12) {
			ret = tls12_record_set_handshake_certificate_verify(conn->record, &conn->recordlen,
				conn->sig_alg, sig, siglen);
		} else {
			ret = tls_record_set_handshake_certificate_verify(conn->record, &conn->recordlen, sig, siglen);
		}
		if (ret != 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;
	}

	if (conn->verbose)
		tls_trace("recv server {Finished}\n");

	// Finished
	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();
		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];
	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;
		}
	}
	// RFC 5746 signaling is supported for the initial handshake only.
	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 (conn->protocol == TLS_protocol_tlcp
		&& tls12_select_tlcp_signature_scheme(conn->cipher_suite, &conn->sig_alg) != 1) {
		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 server Certificate\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;
		int sign_algor = tls_signature_scheme_algorithm_oid(conn->sig_alg);
		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 (sign_algor == OID_undef) {
			error_print();
			return -1;
		}
		if (x509_sign_init(&sign_ctx, sign_key, sign_algor, 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) {
			gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx));
			error_print();
			return -1;
		}
		gmssl_secure_clear(&sign_ctx, sizeof(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 };
	const int *sig_algs = conn->ctx->signature_algorithms;
	size_t sig_algs_cnt = conn->ctx->signature_algorithms_cnt;
	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 (!sig_algs_cnt) {
		sig_algs = tls12_signature_algorithms;
		sig_algs_cnt = tls12_signature_algorithms_cnt;
	}

	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),
			sig_algs, sig_algs_cnt,
			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 client Certificate\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 (tls_cert_chain_verify(conn->protocol, X509_cert_chain_client, conn->cipher_suite,
		1,
		conn->client_certs, conn->client_certs_len,
		conn->ctx->cacerts, conn->ctx->cacertslen,
		NULL, 0,
		NULL, 0,
		conn->ctx->verify_depth,
		NULL, 0,
		conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt,
		NULL, 0,
		NULL, 0,
		NULL, 0,
		NULL, 0,
		&verify_result, NULL) != 1) {
		error_print();
		conn->verify_result = verify_result;
		tls_send_alert(conn, TLS_alert_bad_certificate);
		return -1;
	}
	conn->verify_result = verify_result;

	if (conn->protocol == TLS_protocol_tlcp
		&& (conn->cipher_suite == TLS_cipher_ecdhe_sm4_cbc_sm3
			|| conn->cipher_suite == TLS_cipher_ecdhe_sm4_gcm_sm3)) {
		const uint8_t *enc_cert;
		size_t enc_cert_len;

		if (x509_certs_get_cert_by_index(conn->client_certs, conn->client_certs_len,
			1, &enc_cert, &enc_cert_len) != 1) {
			error_print();
			tls_send_alert(conn, TLS_alert_bad_certificate);
			return -1;
		}
		ret = tlcp_cert_is_encryption_cert(enc_cert, enc_cert_len);
		if (ret < 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_unsupported_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;
	int sig_alg = 0;
	const int *local_sig_algs;
	size_t local_sig_algs_cnt;

	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);

	local_sig_algs = conn->ctx->signature_algorithms;
	local_sig_algs_cnt = conn->ctx->signature_algorithms_cnt;
	if (!local_sig_algs_cnt) {
		local_sig_algs = tls12_signature_algorithms;
		local_sig_algs_cnt = tls12_signature_algorithms_cnt;
	}

	// get signature from certificate_verify
	if (conn->protocol == TLS_protocol_tls12) {
		if (tls12_record_get_handshake_certificate_verify(conn->record, &sig_alg, &sig, &siglen) != 1) {
			tls_send_alert(conn, TLS_alert_unexpected_message);
			error_print();
			return -1;
		}
		if (tls_type_is_in_list(sig_alg, local_sig_algs, local_sig_algs_cnt) != 1) {
			tls_send_alert(conn, TLS_alert_unsupported_certificate);
			error_print();
			return -1;
		}
	} else 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;
	}
	sig_alg = tls_signature_scheme_algorithm_oid(conn->protocol == TLS_protocol_tls12 ? sig_alg : conn->sig_alg);
	if (sig_alg == OID_undef) {
		error_print();
		return -1;
	}
	if (x509_verify_init(&sign_ctx, &client_sign_key, sig_alg, 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;
	}

	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;
	}

	// 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) {
			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_trace("send {ApplicationData}\n");
		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_with_aes_128_ccm:
			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;
	}

	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_trace("send {Alert}\n");
		}
		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;
	}

	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;
}
