/*
 *  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 <gmssl/rand.h>
#include <gmssl/x509.h>
#include <gmssl/error.h>
#include <gmssl/sm2.h>
#include <gmssl/sm3.h>
#include <gmssl/sm4.h>
#include <gmssl/pem.h>
#include <gmssl/tls.h>
#include <gmssl/digest.h>
#include <gmssl/hmac.h>
#include <gmssl/hkdf.h>
#include <gmssl/mem.h>
#include <gmssl/endian.h>


const int tls13_supported_groups[] = {
	TLS_curve_sm2p256v1,
#ifdef ENABLE_SECP256R1
	TLS_curve_secp256r1,
#endif
};
const size_t tls13_supported_groups_cnt =
	sizeof(tls13_supported_groups)/sizeof(tls13_supported_groups[0]);

const int tls13_signature_algorithms[] = {
	TLS_sig_sm2sig_sm3,
#if defined(ENABLE_SECP256R1) && defined(ENABLE_SHA2)
	TLS_sig_ecdsa_secp256r1_sha256,
#endif
};
const size_t tls13_signature_algorithms_cnt =
	sizeof(tls13_signature_algorithms)/sizeof(tls13_signature_algorithms[0]);

const int tls13_cipher_suites[] = {
	TLS_cipher_sm4_gcm_sm3,
#ifdef ENABLE_SM4_CCM
	TLS_cipher_sm4_ccm_sm3,
#endif
#if defined(ENABLE_AES) && defined(ENABLE_SHA2)
	TLS_cipher_aes_128_gcm_sha256,
#ifdef ENABLE_AES_CCM
	TLS_cipher_aes_128_ccm_sha256,
#endif
#endif
};
const size_t tls13_cipher_suites_cnt =
	sizeof(tls13_cipher_suites)/sizeof(tls13_cipher_suites[0]);


int tls13_random_generate(uint8_t random[32])
{
	if (rand_bytes(random, 32) != 1) {
		error_print();
		return -1;
	}
	return 1;
}



int tls13_padding_len_rand(size_t *padding_len)
{
	uint8_t val;
	rand_bytes(&val, 1);
	*padding_len = val % 128;


	*padding_len = 0;
	return 1;
}





/*
struct {
	opaque content[TLSPlaintext.length];
	ContentType type;
	uint8 zeros[length_of_padding];
} TLSInnerPlaintext;

struct {
	ContentType opaque_type = application_data; // 23
	ProtocolVersion legacy_record_version = 0x0303; // TLS v1.2
	uint16 length;
	opaque encrypted_record[TLSCiphertext.length];
} TLSCiphertext;
*/
int tls13_gcm_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
	const uint8_t seq_num[8], int record_type,
	const uint8_t *in, size_t inlen, size_t padding_len, // TLSInnerPlaintext.content
	uint8_t *out, size_t *outlen) // TLSCiphertext.encrypted_record
{
	uint8_t nonce[12];
	uint8_t aad[5];
	uint8_t *gmac;
	uint8_t *mbuf = NULL;
	size_t mlen, clen;

	if (!(mbuf = malloc(inlen + 256))) {
		error_print();
		return -1;
	}

	// nonce = (zeros|seq_num) xor (iv)
	nonce[0] = nonce[1] = nonce[2] = nonce[3] = 0;
	memcpy(nonce + 4, seq_num, 8);
	gmssl_memxor(nonce, nonce, iv, 12);

	// TLSInnerPlaintext
	memcpy(mbuf, in, inlen);
	mbuf[inlen] = record_type;
	memset(mbuf + inlen + 1, 0, padding_len);
	mlen = inlen + 1 + padding_len;
	clen = mlen + GHASH_SIZE;

	// aad = TLSCiphertext header
	aad[0] = TLS_record_application_data;
	aad[1] = 0x03; //TLS_protocol_tls12_major;
	aad[2] = 0x03; //TLS_protocol_tls12_minor;
	aad[3] = (uint8_t)(clen >> 8);
	aad[4] = (uint8_t)(clen);

	gmac = out + mlen;

	switch (key->cipher->oid) {
	case OID_sm4:
		if (sm4_gcm_encrypt(&(key->u.sm4_key), nonce, sizeof(nonce), aad, sizeof(aad),
			mbuf, mlen, out, 16, gmac) != 1) {
			error_print();
			free(mbuf);
			return -1;
		}
		break;
#ifdef ENABLE_AES
	case OID_aes128:
		if (aes_gcm_encrypt(&(key->u.aes_key), nonce, sizeof(nonce), aad, sizeof(aad),
			mbuf, mlen, out, 16, gmac) != 1) {
			error_print();
			free(mbuf);
			return -1;
		}
		break;
#endif
	default:
		error_print();
		free(mbuf);
		return -1;
	}
	*outlen = clen;
	free(mbuf);

	return 1;
}

int tls13_gcm_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
	const uint8_t seq_num[8], const uint8_t *in, size_t inlen,
	int *record_type, uint8_t *out, size_t *outlen)
{
	uint8_t nonce[12];
	uint8_t aad[5];
	size_t mlen;
	const uint8_t *gmac;

	// nonce = (zeros|seq_num) xor (iv)
	nonce[0] = nonce[1] = nonce[2] = nonce[3] = 0;
	memcpy(nonce + 4, seq_num, 8);
	gmssl_memxor(nonce, nonce, iv, 12);

	// aad = TLSCiphertext header
	aad[0] = TLS_record_application_data;
	aad[1] = 0x03; //TLS_protocol_tls12_major;
	aad[2] = 0x03; //TLS_protocol_tls12_minor;
	aad[3] = (uint8_t)(inlen >> 8);
	aad[4] = (uint8_t)(inlen);

	if (inlen < GHASH_SIZE) {
		error_print();
		return -1;
	}
	mlen = inlen - GHASH_SIZE;
	gmac = in + mlen;

	switch (key->cipher->oid) {
	case OID_sm4:
		if (sm4_gcm_decrypt(&(key->u.sm4_key), nonce, sizeof(nonce), aad, sizeof(aad),
			in, mlen, gmac, GHASH_SIZE, out) != 1) {
			error_print();
			return -1;
		}
		break;
	case OID_aes128:
#ifdef ENABLE_AES
		if (aes_gcm_decrypt(&(key->u.aes_key), nonce, sizeof(nonce), aad, sizeof(aad),
			in, mlen, gmac, GHASH_SIZE, out) != 1) {
			error_print();
			return -1;
		}
		break;
#endif
	default:
		error_print();
		return -1;
	}
	// remove padding, get record_type
	*record_type = 0;
	while (mlen--) {
		if (out[mlen] != 0) {
			*record_type = out[mlen];
			break;
		}
	}
	*outlen = mlen;
	if (!tls_record_type_name(*record_type)) {
		error_print();
		return -1;
	}
	return 1;
}

static int tls13_ccm_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
	const uint8_t seq_num[8], int record_type,
	const uint8_t *in, size_t inlen, size_t padding_len,
	uint8_t *out, size_t *outlen)
{
	uint8_t nonce[12];
	uint8_t aad[5];
	uint8_t *tag;
	uint8_t *mbuf = NULL;
	size_t mlen, clen;

	if (!(mbuf = malloc(inlen + 256))) {
		error_print();
		return -1;
	}

	nonce[0] = nonce[1] = nonce[2] = nonce[3] = 0;
	memcpy(nonce + 4, seq_num, 8);
	gmssl_memxor(nonce, nonce, iv, 12);

	memcpy(mbuf, in, inlen);
	mbuf[inlen] = record_type;
	memset(mbuf + inlen + 1, 0, padding_len);
	mlen = inlen + 1 + padding_len;
	clen = mlen + GHASH_SIZE;

	aad[0] = TLS_record_application_data;
	aad[1] = 0x03;
	aad[2] = 0x03;
	aad[3] = (uint8_t)(clen >> 8);
	aad[4] = (uint8_t)(clen);

	tag = out + mlen;

	switch (key->cipher->oid) {
#ifdef ENABLE_SM4_CCM
	case OID_sm4:
		if (sm4_ccm_encrypt(&(key->u.sm4_key), nonce, sizeof(nonce), aad, sizeof(aad),
			mbuf, mlen, out, GHASH_SIZE, tag) != 1) {
			error_print();
			free(mbuf);
			return -1;
		}
		break;
#endif
#ifdef ENABLE_AES_CCM
	case OID_aes128:
		if (aes_ccm_encrypt(&(key->u.aes_key), nonce, sizeof(nonce), aad, sizeof(aad),
			mbuf, mlen, out, GHASH_SIZE, tag) != 1) {
			error_print();
			free(mbuf);
			return -1;
		}
		break;
#endif
	default:
		error_print();
		free(mbuf);
		return -1;
	}
	*outlen = clen;
	free(mbuf);
	return 1;
}

static int tls13_ccm_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
	const uint8_t seq_num[8], const uint8_t *in, size_t inlen,
	int *record_type, uint8_t *out, size_t *outlen)
{
	uint8_t nonce[12];
	uint8_t aad[5];
	size_t mlen;
	const uint8_t *tag;

	nonce[0] = nonce[1] = nonce[2] = nonce[3] = 0;
	memcpy(nonce + 4, seq_num, 8);
	gmssl_memxor(nonce, nonce, iv, 12);

	aad[0] = TLS_record_application_data;
	aad[1] = 0x03;
	aad[2] = 0x03;
	aad[3] = (uint8_t)(inlen >> 8);
	aad[4] = (uint8_t)(inlen);

	if (inlen < GHASH_SIZE) {
		error_print();
		return -1;
	}
	mlen = inlen - GHASH_SIZE;
	tag = in + mlen;

	switch (key->cipher->oid) {
#ifdef ENABLE_SM4_CCM
	case OID_sm4:
		if (sm4_ccm_decrypt(&(key->u.sm4_key), nonce, sizeof(nonce), aad, sizeof(aad),
			in, mlen, tag, GHASH_SIZE, out) != 1) {
			error_print();
			return -1;
		}
		break;
#endif
#ifdef ENABLE_AES_CCM
	case OID_aes128:
		if (aes_ccm_decrypt(&(key->u.aes_key), nonce, sizeof(nonce), aad, sizeof(aad),
			in, mlen, tag, GHASH_SIZE, out) != 1) {
			error_print();
			return -1;
		}
		break;
#endif
	default:
		error_print();
		return -1;
	}

	*record_type = 0;
	while (mlen--) {
		if (out[mlen] != 0) {
			*record_type = out[mlen];
			break;
		}
	}
	*outlen = mlen;
	if (!tls_record_type_name(*record_type)) {
		error_print();
		return -1;
	}
	return 1;
}


int tls13_record_encrypt(int cipher_suite, const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
	const uint8_t seq_num[8], const uint8_t *record, size_t recordlen, size_t padding_len,
	uint8_t *enced_record, size_t *enced_recordlen)
{
	switch (cipher_suite) {
	case TLS_cipher_sm4_gcm_sm3:
	case TLS_cipher_aes_128_gcm_sha256:
		if (tls13_gcm_encrypt(key, iv,
			seq_num, record[0], record + 5, recordlen - 5, padding_len,
			enced_record + 5, enced_recordlen) != 1) {
			error_print();
			return -1;
		}
		break;
	case TLS_cipher_sm4_ccm_sm3:
#ifdef ENABLE_AES_CCM
	case TLS_cipher_aes_128_ccm_sha256:
#endif
		if (tls13_ccm_encrypt(key, iv,
			seq_num, record[0], record + 5, recordlen - 5, padding_len,
			enced_record + 5, enced_recordlen) != 1) {
			error_print();
			return -1;
		}
		break;
	default:
		error_print();
		return -1;
	}

	// in tls1.3, type of encrypted records must be application_data
	enced_record[0] = TLS_record_application_data;
	enced_record[1] = 0x03; //TLS_protocol_tls12_major;
	enced_record[2] = 0x03; //TLS_protocol_tls12_minor;
	enced_record[3] = (uint8_t)((*enced_recordlen) >> 8);
	enced_record[4] = (uint8_t)(*enced_recordlen);

	(*enced_recordlen) += 5;
	return 1;
}

int tls13_record_decrypt(int cipher_suite, const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
	const uint8_t seq_num[8], const uint8_t *enced_record, size_t enced_recordlen,
	uint8_t *record, size_t *recordlen)
{
	int record_type;

	switch (cipher_suite) {
	case TLS_cipher_sm4_gcm_sm3:
	case TLS_cipher_aes_128_gcm_sha256:
		if (tls13_gcm_decrypt(key, iv,
			seq_num, enced_record + 5, enced_recordlen - 5,
			&record_type, record + 5, recordlen) != 1) {
			error_print();
			return -1;
		}
		break;
	case TLS_cipher_sm4_ccm_sm3:
#ifdef ENABLE_AES_CCM
	case TLS_cipher_aes_128_ccm_sha256:
#endif
		if (tls13_ccm_decrypt(key, iv,
			seq_num, enced_record + 5, enced_recordlen - 5,
			&record_type, record + 5, recordlen) != 1) {
			error_print();
			return -1;
		}
		break;
	default:
		error_print();
		return -1;
	}
	record[0] = record_type;
	record[1] = 0x03; //TLS_protocol_tls12_major;
	record[2] = 0x03; //TLS_protocol_tls12_minor;
	record[3] = (uint8_t)((*recordlen) >> 8);
	record[4] = (uint8_t)(*recordlen);

	(*recordlen) += 5;
	return 1;
}

int tls13_hkdf_extract(const DIGEST *digest, const uint8_t salt[32], const uint8_t in[32], uint8_t out[32])
{
	size_t saltlen;
	size_t inlen;
	size_t outlen;

	if (!digest || !salt || !in || !out) {
		error_print();
		return -1;
	}
	saltlen = digest->digest_size;
	inlen = digest->digest_size;

	if (hkdf_extract(digest, salt, saltlen, in, inlen, out, &outlen) != 1) {
		error_print();
		return -1;
	}
	// outlen == digest->digest_size

	return 1;
}

/*
HKDF-Expand-Label(Secret, Label, Context, Length) =
	HKDF-Expand(Secret, HkdfLabel, Length);

	HkdfLabel = struct {
		uint16 length = Length;
		opaque label<7..255> = "tls13 " + Label;
		opaque context<0..255> = Context; }
*/
int tls13_hkdf_expand_label(const DIGEST *digest, const uint8_t secret[32],
	const char *label, const uint8_t *context, size_t context_len,
	size_t outlen, uint8_t *out)
{
	uint8_t hkdf_label[2 + 256 + 256];
	uint8_t *p = hkdf_label;
	size_t hkdf_label_len = 0;
	size_t secret_len;
	size_t label_len;

	if (!digest || !secret || !label || !outlen || !out) {
		error_print();
		return -1;
	}
	if (strlen(label) > 255 - strlen("tls13 ")) {
		error_print();
		return -1;
	}
	if (outlen > 65535) {
		error_print();
		return -1;
	}
	secret_len = digest->digest_size;
	label_len = strlen("tls13 ") + strlen(label);

	tls_uint16_to_bytes((uint16_t)outlen, &p, &hkdf_label_len);
	tls_uint8_to_bytes((uint8_t)label_len, &p, &hkdf_label_len);
	tls_array_to_bytes((uint8_t *)"tls13 ", strlen("tls13 "), &p, &hkdf_label_len);
	tls_array_to_bytes((uint8_t *)label, strlen(label), &p, &hkdf_label_len);
	tls_uint8array_to_bytes(context, context_len, &p, &hkdf_label_len);

	hkdf_expand(digest, secret, secret_len, hkdf_label, hkdf_label_len, outlen, out);

	return 1;
}

/*
Derive-Secret(Secret, Label, Messages) =
	HKDF-Expand-Label(Secret, Label, Hash(Messages), Hash.length)
*/
int tls13_derive_secret(const uint8_t secret[32], const char *label, const DIGEST_CTX *dgst_ctx, uint8_t out[32])
{
	DIGEST_CTX ctx;
	size_t outlen = 32;
	uint8_t context[32];
	size_t context_len;

	if (!secret || !label || !dgst_ctx || !out) {
		error_print();
		return -1;
	}

 	ctx = *dgst_ctx;
	if (digest_finish(&ctx, context, &context_len) != 1) {
		error_print();
		return -1;
	}
	if (tls13_hkdf_expand_label(dgst_ctx->digest, secret, label, context, context_len, outlen, out) != 1) {
		error_print();
		return -1;
	}
	return 1;
}





/*

             0
             |
             v
[1]  PSK ->  HKDF-Extract = Early Secret
             |
[2]          +-----> Derive-Secret(., "ext binder" | "res binder", "")
             |                     = binder_key
             |
[3]          +-----> Derive-Secret(., "c e traffic", ClientHello)
             |                     = client_early_traffic_secret
             |
[4]          +-----> Derive-Secret(., "e exp master", ClientHello)
             |                     = early_exporter_master_secret
             v
[5]    Derive-Secret(., "derived", "")
             |
             v
[6]  (EC)DHE -> HKDF-Extract = Handshake Secret
             |
[7]          +-----> Derive-Secret(., "c hs traffic",
             |                     ClientHello...ServerHello)
             |                     = client_handshake_traffic_secret
             |
[8]          +-----> Derive-Secret(., "s hs traffic",
             |                     ClientHello...ServerHello)
             |                     = server_handshake_traffic_secret
             v
[9]    Derive-Secret(., "derived", "")
             |
             v
[10]   0 -> HKDF-Extract = Master Secret
             |
[11]         +-----> Derive-Secret(., "c ap traffic",
             |                     ClientHello...server Finished)
             |                     = client_application_traffic_secret_0
             |
[12]         +-----> Derive-Secret(., "s ap traffic",
             |                     ClientHello...server Finished)
             |                     = server_application_traffic_secret_0
             |
[13]         +-----> Derive-Secret(., "exp master",
             |                     ClientHello...server Finished)
             |                     = exporter_master_secret
             |
[14]         +-----> Derive-Secret(., "res master",
                                   ClientHello...client Finished)
                                   = resumption_master_secret

*/


int tls13_generate_early_keys(TLS_CONNECT *conn)
{
	const uint8_t zeros[32] = {0};
	const uint8_t *psk_keys;
	size_t psk_keys_len;
	const uint8_t *first_psk_key;
	size_t first_psk_key_len;
	uint8_t client_write_key[16];
	size_t client_write_key_len;

	if (!conn) {
		error_print();
		return -1;
	}

	if (tls_cipher_suite_get(conn->psk_cipher_suites[0], &conn->cipher, &conn->digest) != 1) {
		error_print();
		return -1;
	}
	conn->cipher_suite = conn->psk_cipher_suites[0];
	client_write_key_len = conn->cipher->key_size;

	if (digest_init(&conn->dgst_ctx, conn->digest) != 1
		|| digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) {
		error_print();
		return -1;
	}

	// early_data always encrypted with the first psk
	psk_keys = conn->psk_keys;
	psk_keys_len = conn->psk_keys_len;
	if (tls_uint8array_from_bytes(&first_psk_key, &first_psk_key_len, &psk_keys, &psk_keys_len) != 1) {
		error_print();
		return -1;
	}
	if (first_psk_key_len != conn->digest->digest_size) {
		error_print();
		return -1;
	}

	// first_psk_key => client_early_traffic_secret
	if (tls13_hkdf_extract(conn->digest, zeros, first_psk_key, conn->early_secret) != 1
		|| tls13_derive_secret(conn->early_secret, "c e traffic", &conn->dgst_ctx, conn->client_early_traffic_secret) != 1
		|| tls13_hkdf_expand_label(conn->digest, conn->client_early_traffic_secret, "key", NULL, 0, client_write_key_len, client_write_key) != 1
		|| tls13_hkdf_expand_label(conn->digest, conn->client_early_traffic_secret, "iv", NULL, 0, TLS13_IV_SIZE, conn->client_write_iv) != 1
		|| block_cipher_set_encrypt_key(&conn->client_write_key, conn->cipher, client_write_key) != 1) {
		error_print();
		return -1;
	}
	tls_seq_num_reset(conn->client_seq_num);

	if (conn->verbose == TLS_verbose_print_key) {
		format_print(stderr, 0, 0, "generate_early_keys\n");
		format_bytes(stderr, 0, 4, "early_secret", conn->early_secret, conn->digest->digest_size);
		format_bytes(stderr, 0, 4, "client_early_traffic_secret", conn->client_early_traffic_secret, conn->digest->digest_size);
		format_bytes(stderr, 0, 4, "client_write_key", client_write_key, client_write_key_len);
		format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, TLS13_IV_SIZE);
	}

	gmssl_secure_clear(client_write_key, sizeof(client_write_key));
	return 1;
}

int tls13_generate_handshake_secrets(TLS_CONNECT *conn)
{
	const uint8_t zeros[32] = {0};
	uint8_t ecdhe_shared_secret[32] = {0};
	size_t ecdhe_shared_secret_len = sizeof(ecdhe_shared_secret);
	uint8_t derived_secret[32];
	DIGEST_CTX null_dgst_ctx;

	if (!conn || !conn->digest) {
		error_print();
		return -1;
	}

	// (EC)DHE
	if (conn->key_exchange_modes != TLS_KE_PSK) {
		if (conn->key_exchange_idx >= conn->key_exchanges_cnt) {
			error_print();
			return -1;
		}
		if (x509_key_exchange(&conn->key_exchanges[conn->key_exchange_idx],
			conn->peer_key_exchange, conn->peer_key_exchange_len,
			ecdhe_shared_secret, &ecdhe_shared_secret_len) != 1) {
			error_print();
			return -1;
		}
	}

	if (digest_init(&null_dgst_ctx, conn->digest) != 1) {
		error_print();
		return -1;
	}

	if (tls13_hkdf_extract(conn->digest, zeros, conn->psk, conn->early_secret) != 1
		|| tls13_derive_secret(conn->early_secret, "derived", &null_dgst_ctx, derived_secret) != 1
		|| tls13_hkdf_extract(conn->digest, derived_secret, ecdhe_shared_secret, conn->handshake_secret) != 1
		|| tls13_derive_secret(conn->handshake_secret, "c hs traffic", &conn->dgst_ctx, conn->client_handshake_traffic_secret) != 1
		|| tls13_derive_secret(conn->handshake_secret, "s hs traffic", &conn->dgst_ctx, conn->server_handshake_traffic_secret) != 1) {
		error_print();
		return -1;
	}

	if (conn->verbose == TLS_verbose_print_key) {
		format_print(stderr, 0, 0, "generate_handshake_secrets\n");
		format_bytes(stderr, 0, 4, "early_secret", conn->early_secret, conn->digest->digest_size);
		format_bytes(stderr, 0, 4, "derived_secret", derived_secret, conn->digest->digest_size);
		format_bytes(stderr, 0, 4, "ecdhe_shared_secret", ecdhe_shared_secret, ecdhe_shared_secret_len);
		format_bytes(stderr, 0, 4, "handshake_secret", conn->handshake_secret, conn->digest->digest_size);
		format_bytes(stderr, 0, 4, "client_handshake_traffic_secret", conn->client_handshake_traffic_secret, conn->digest->digest_size);
		format_bytes(stderr, 0, 4, "server_handshake_traffic_secret", conn->server_handshake_traffic_secret, conn->digest->digest_size);
	}

	gmssl_secure_clear(ecdhe_shared_secret, sizeof(ecdhe_shared_secret));
	gmssl_secure_clear(derived_secret, sizeof(derived_secret));
	return 1;
}

int tls13_generate_master_secret(TLS_CONNECT *conn)
{
	const uint8_t zeros[32] = {0};
	DIGEST_CTX null_dgst_ctx;

	if (!conn || !conn->digest) {
		error_print();
		return -1;
	}

	if (digest_init(&null_dgst_ctx, conn->digest) != 1) {
		error_print();
		return -1;
	}

	if (tls13_derive_secret(conn->handshake_secret, "derived", &null_dgst_ctx, conn->master_secret) != 1
		|| tls13_hkdf_extract(conn->digest, conn->master_secret, zeros, conn->master_secret) != 1) {
		error_print();
		return -1;
	}
	if (conn->verbose == TLS_verbose_print_key) {
		format_print(stderr, 0, 0, "generate_master_secret\n");
		format_bytes(stderr, 0, 4, "master_secret", conn->master_secret, conn->digest->digest_size);
	}
	return 1;
}

int tls13_generate_client_handshake_keys(TLS_CONNECT *conn)
{
	uint8_t client_write_key[16];
	size_t client_write_key_len;

	if (!conn || !conn->cipher) {
		error_print();
		return -1;
	}

	client_write_key_len = conn->cipher->key_size;

	if (tls13_hkdf_expand_label(conn->digest, conn->client_handshake_traffic_secret, "key", NULL, 0, client_write_key_len, client_write_key) != 1
		|| tls13_hkdf_expand_label(conn->digest, conn->client_handshake_traffic_secret, "iv", NULL, 0, TLS13_IV_SIZE, conn->client_write_iv) != 1
		|| block_cipher_set_encrypt_key(&conn->client_write_key, conn->cipher, client_write_key) != 1) {
		error_print();
		return -1;
	}
	tls_seq_num_reset(conn->client_seq_num);

	if (conn->verbose == TLS_verbose_print_key) {
		format_print(stderr, 0, 0, "generate_client_handshake_keys\n");
		format_bytes(stderr, 0, 4, "client_write_key", client_write_key, client_write_key_len);
		format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, TLS13_IV_SIZE);
		format_print(stderr, 0, 4, "client_seq_num: %"PRIu64"\n", GETU64(conn->client_seq_num));
	}

	gmssl_secure_clear(client_write_key, sizeof(client_write_key));
	return 1;
}

int tls13_generate_server_handshake_keys(TLS_CONNECT *conn)
{
	uint8_t server_write_key[16];
	size_t server_write_key_len;

	if (!conn || !conn->cipher) {
		error_print();
		return -1;
	}

	server_write_key_len = conn->cipher->key_size;

	if (tls13_hkdf_expand_label(conn->digest, conn->server_handshake_traffic_secret, "key", NULL, 0, server_write_key_len, server_write_key) != 1
		|| tls13_hkdf_expand_label(conn->digest, conn->server_handshake_traffic_secret, "iv", NULL, 0, TLS13_IV_SIZE, conn->server_write_iv) != 1
		|| block_cipher_set_encrypt_key(&conn->server_write_key, conn->cipher, server_write_key) != 1) {
		error_print();
		return -1;
	}
	tls_seq_num_reset(conn->server_seq_num);

	if (conn->verbose == TLS_verbose_print_key) {
		format_print(stderr, 0, 0, "generate_server_handshake_keys\n");
		format_bytes(stderr, 0, 4, "server_write_key", server_write_key, server_write_key_len);
		format_bytes(stderr, 0, 4, "server_write_iv", conn->server_write_iv, TLS13_IV_SIZE);
		format_print(stderr, 0, 4, "server_seq_num: %"PRIu64"\n", GETU64(conn->server_seq_num));
	}

	gmssl_secure_clear(server_write_key, sizeof(server_write_key));
	return 1;
}

int tls13_generate_application_secrets(TLS_CONNECT *conn)
{
	if (!conn || !conn->digest) {
		error_print();
		return -1;
	}
	if (tls13_derive_secret(conn->master_secret, "c ap traffic", &conn->dgst_ctx, conn->client_application_traffic_secret) != 1
		|| tls13_derive_secret(conn->master_secret, "s ap traffic", &conn->dgst_ctx, conn->server_application_traffic_secret) != 1) {
		error_print();
		return -1;
	}
	if (conn->verbose == TLS_verbose_print_key) {
		format_print(stderr, 0, 0, "generate_application_secrets\n");
		format_bytes(stderr, 0, 4, "client_application_traffic_secret", conn->client_application_traffic_secret, conn->dgst_ctx.digest->digest_size);
		format_bytes(stderr, 0, 4, "server_application_traffic_secret", conn->server_application_traffic_secret, conn->dgst_ctx.digest->digest_size);
	}
	return 1;
}

int tls13_update_client_application_secret(TLS_CONNECT *conn)
{
	if (!conn || !conn->digest) {
		error_print();
		return -1;
	}
	if (tls13_hkdf_expand_label(conn->digest, conn->client_application_traffic_secret, "traffic upd", NULL, 0,
		conn->digest->digest_size, conn->client_application_traffic_secret) != 1) {
		error_print();
		return -1;
	}
	if (conn->verbose == TLS_verbose_print_key) {
		format_print(stderr, 0, 0, "update_client_application_secret\n");
		format_bytes(stderr, 0, 4, "client_application_traffic_secret",
			conn->client_application_traffic_secret, conn->digest->digest_size);
	}
	return 1;
}

int tls13_update_server_application_secret(TLS_CONNECT *conn)
{
	if (!conn || !conn->digest) {
		error_print();
		return -1;
	}
	if (tls13_hkdf_expand_label(conn->digest, conn->server_application_traffic_secret, "traffic upd", NULL, 0,
		conn->digest->digest_size, conn->server_application_traffic_secret) != 1) {
		error_print();
		return -1;
	}
	if (conn->verbose == TLS_verbose_print_key) {
		format_print(stderr, 0, 0, "update_server_application_secret\n");
		format_bytes(stderr, 0, 4, "server_application_traffic_secret",
			conn->server_application_traffic_secret, conn->digest->digest_size);
	}
	return 1;
}

int tls13_generate_client_application_keys(TLS_CONNECT *conn)
{
	uint8_t client_write_key[16];
	size_t client_write_key_len;

	if (!conn || !conn->digest) {
		error_print();
		return -1;
	}

	client_write_key_len = conn->cipher->key_size;

	if (tls13_hkdf_expand_label(conn->digest, conn->client_application_traffic_secret, "key", NULL, 0, client_write_key_len, client_write_key) != 1
		|| tls13_hkdf_expand_label(conn->digest, conn->client_application_traffic_secret, "iv", NULL, 0, TLS13_IV_SIZE, conn->client_write_iv) != 1
		|| block_cipher_set_encrypt_key(&conn->client_write_key, conn->cipher, client_write_key) != 1) {
		error_print();
		return -1;
	}
	tls_seq_num_reset(conn->client_seq_num);

	if (conn->verbose == TLS_verbose_print_key) {
		format_print(stderr, 0, 0, "update_client_application_keys\n");
		format_bytes(stderr, 0, 4, "client_write_key", client_write_key, client_write_key_len);
		format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, TLS13_IV_SIZE);
		format_print(stderr, 0, 4, "client_seq_num: %"PRIu64"\n", GETU64(conn->client_seq_num));
	}

	gmssl_secure_clear(client_write_key, sizeof(client_write_key));
	return 1;
}

int tls13_generate_server_application_keys(TLS_CONNECT *conn)
{
	uint8_t server_write_key[16];
	size_t server_write_key_len;

	if (!conn || !conn->digest) {
		error_print();
		return -1;
	}

	server_write_key_len = conn->cipher->key_size;

	if (tls13_hkdf_expand_label(conn->digest, conn->server_application_traffic_secret, "key", NULL, 0, server_write_key_len, server_write_key) != 1
		|| tls13_hkdf_expand_label(conn->digest, conn->server_application_traffic_secret, "iv", NULL, 0, TLS13_IV_SIZE, conn->server_write_iv) != 1
		|| block_cipher_set_encrypt_key(&conn->server_write_key, conn->cipher, server_write_key) != 1) {
		error_print();
		return -1;
	}
	tls_seq_num_reset(conn->server_seq_num);

	if (conn->verbose == TLS_verbose_print_key) {
		format_print(stderr, 0, 0, "update_server_application_keys\n");
		format_bytes(stderr, 0, 4, "server_write_key", server_write_key, server_write_key_len);
		format_bytes(stderr, 0, 4, "server_write_iv", conn->server_write_iv, TLS13_IV_SIZE);
		format_print(stderr, 0, 4, "server_seq_num: %"PRIu64"\n", GETU64(conn->server_seq_num));
	}

	gmssl_secure_clear(server_write_key, sizeof(server_write_key));
	return 1;
}

static const uint8_t TLS13_client_context_str_and_zero[] = "TLS 1.3, client CertificateVerify";
static const uint8_t TLS13_server_context_str_and_zero[] = "TLS 1.3, server CertificateVerify";
static size_t TLS13_client_context_str_and_zero_size = sizeof(TLS13_client_context_str_and_zero);
static size_t TLS13_server_context_str_and_zero_size = sizeof(TLS13_server_context_str_and_zero);

int tls13_sign_certificate_verify(int tls_mode, int sig_alg,
	X509_KEY *sign_key, const DIGEST_CTX *tbs_dgst_ctx,
	uint8_t *sig, size_t *siglen)
{
	uint8_t prefix[64];
	const uint8_t *context_str_and_zero;
	size_t context_str_and_zero_len;
	DIGEST_CTX dgst_ctx;
	uint8_t dgst[64];
	size_t dgstlen;
	X509_SIGN_CTX sign_ctx;
	const char *signer_id = NULL;
	size_t signer_id_len = 0;

	if (!sign_key || !tbs_dgst_ctx || !sig || !siglen) {
		error_print();
		return -1;
	}

	memset(prefix, 0x20, 64);

	switch (tls_mode) {
	case TLS_client_mode:
		context_str_and_zero = TLS13_client_context_str_and_zero;
		context_str_and_zero_len = TLS13_client_context_str_and_zero_size;
		break;
	case TLS_server_mode:
		context_str_and_zero = TLS13_server_context_str_and_zero;
		context_str_and_zero_len = TLS13_server_context_str_and_zero_size;
		break;
	default:
		error_print();
		return -1;
	}

	switch (sig_alg) {
	case TLS_sig_sm2sig_sm3:
		if (sign_key->algor != OID_ec_public_key
			&& sign_key->algor_param != OID_sm2) {
			error_print();
			return -1;
		}
		if (tbs_dgst_ctx->digest->oid != OID_sm3) {
			error_print();
			return -1;
		}
		signer_id = TLS13_SM2_ID;
		signer_id_len = TLS13_SM2_ID_LENGTH;
		break;

	case TLS_sig_ecdsa_secp256r1_sha256:
		if (sign_key->algor != OID_ec_public_key
			&& sign_key->algor_param != OID_secp256r1) {
			error_print();
			return -1;
		}
		if (tbs_dgst_ctx->digest->oid != OID_sha256) {
			error_print();
			return -1;
		}
		break;

	default:
		error_print();
		return -1;
	}

	dgst_ctx = *tbs_dgst_ctx;
	if (digest_finish(&dgst_ctx, dgst, &dgstlen) != 1) {
		error_print();
		return -1;
	}

	if (x509_sign_init(&sign_ctx, sign_key, tls_signature_scheme_algorithm_oid(sig_alg),
		signer_id, signer_id_len) !=  1
		|| x509_sign_update(&sign_ctx, prefix, 64) != 1
		|| x509_sign_update(&sign_ctx, context_str_and_zero, context_str_and_zero_len) != 1
		|| x509_sign_update(&sign_ctx, dgst, dgstlen) != 1
		|| x509_sign_finish(&sign_ctx, sig, siglen) != 1) {
		gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx));
		error_print();
		return -1;
	}

	/*
	format_print(stderr, 0, 0, "sign_certificate_verify\n");
	format_bytes(stderr, 0, 4, "transcript_hash", dgst, dgstlen);
	format_bytes(stderr, 0, 4, "signature", sig, *siglen);
	*/

	gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx));
	return 1;
}

int tls13_verify_certificate_verify(int tls_mode, int sig_alg,
	const X509_KEY *public_key, const DIGEST_CTX *tbs_dgst_ctx,
	const uint8_t *sig, size_t siglen)
{
	int ret;
	uint8_t prefix[64];
	const uint8_t *context_str_and_zero;
	size_t context_str_and_zero_len;
	DIGEST_CTX dgst_ctx;
	uint8_t dgst[64];
	size_t dgstlen;
	X509_SIGN_CTX sign_ctx;
	const char *signer_id = NULL;
	size_t signer_id_len = 0;

	if (!public_key || !tbs_dgst_ctx || !sig || !siglen) {
		error_print();
		return -1;
	}

	memset(prefix, 0x20, 64);

	switch (tls_mode) {
	case TLS_client_mode:
		context_str_and_zero = TLS13_client_context_str_and_zero;
		context_str_and_zero_len = TLS13_client_context_str_and_zero_size;
		break;
	case TLS_server_mode:
		context_str_and_zero = TLS13_server_context_str_and_zero;
		context_str_and_zero_len = TLS13_server_context_str_and_zero_size;
		break;
	default:
		error_print();
		return -1;
	}

	switch (sig_alg) {
	case TLS_sig_sm2sig_sm3:
		if (public_key->algor != OID_ec_public_key
			&& public_key->algor_param != OID_sm2) {
			error_print();
			return -1;
		}
		if (tbs_dgst_ctx->digest->oid != OID_sm3) {
			error_print();
			return -1;
		}
		signer_id = TLS13_SM2_ID;
		signer_id_len = TLS13_SM2_ID_LENGTH;
		break;

	case TLS_sig_ecdsa_secp256r1_sha256:
		if (public_key->algor != OID_ec_public_key
			&& public_key->algor_param != OID_secp256r1) {
			error_print();
			return -1;
		}
		if (tbs_dgst_ctx->digest->oid != OID_sha256) {
			error_print();
			return -1;
		}
		break;

	default:
		error_print();
		return -1;
	}

	dgst_ctx = *tbs_dgst_ctx;
	if (digest_finish(&dgst_ctx, dgst, &dgstlen) != 1) {
		error_print();
		return -1;
	}

	/*
	format_print(stderr, 0, 0, "verify_certificate_verify\n");
	format_bytes(stderr, 0, 4, "transcript_hash", dgst, dgstlen);
	format_bytes(stderr, 0, 4, "signature", sig, siglen);
	*/

	if (x509_verify_init(&sign_ctx, public_key, tls_signature_scheme_algorithm_oid(sig_alg),
		signer_id, signer_id_len, sig, siglen) != 1
		|| x509_verify_update(&sign_ctx, prefix, 64) != 1
		|| x509_verify_update(&sign_ctx, context_str_and_zero, context_str_and_zero_len) != 1
		|| x509_verify_update(&sign_ctx, dgst, dgstlen) != 1) {
		error_print();
		return -1;
	}
	if ((ret = x509_verify_finish(&sign_ctx)) < 0) {
		error_print();
		return -1;
	}
	if (ret != 1) {
		error_print();
	}
	return ret;
}

/*
Finished.verify_data

finished_key =
	HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)

verify_data =
	HMAC(finished_key, Transcript-Hash(Handshake Context, Certificate*, CertificateVerify*))

*/
int tls13_compute_verify_data(const uint8_t *handshake_traffic_secret,
	const DIGEST_CTX *dgst_ctx, uint8_t *verify_data, size_t *verify_data_len)
{
	DIGEST_CTX tmp_dgst_ctx;
	uint8_t dgst[64];
	size_t dgstlen;
	uint8_t finished_key[64];
	size_t finished_key_len;

	if (!handshake_traffic_secret || !dgst_ctx || !verify_data || !verify_data_len) {
		error_print();
		return -1;
	}

	finished_key_len = dgst_ctx->digest->digest_size;
	if (tls13_hkdf_expand_label(dgst_ctx->digest, handshake_traffic_secret,
		"finished", NULL, 0, finished_key_len, finished_key) != 1) {
		error_print();
		return -1;
	}

	tmp_dgst_ctx = *dgst_ctx;
	if (digest_finish(&tmp_dgst_ctx, dgst, &dgstlen) != 1) {
		gmssl_secure_clear(finished_key, sizeof(finished_key));
		error_print();
		return -1;
	}

	if (hmac(dgst_ctx->digest, finished_key, finished_key_len, dgst, dgstlen,
		verify_data, verify_data_len) != 1) {
		gmssl_secure_clear(finished_key, sizeof(finished_key));
		error_print();
		return -1;
	}

	/*
	format_print(stderr, 0, 0, "compute_verify_data\n");
	format_bytes(stderr, 0, 4, "finished_key", finished_key, finished_key_len);
	format_bytes(stderr, 0, 4, "transcript_hash", dgst, dgstlen);
	format_bytes(stderr, 0, 4, "verify_data", verify_data, *verify_data_len);
	*/

	gmssl_secure_clear(finished_key, sizeof(finished_key));
	return 1;
}



int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *sentlen)
{
	int ret = 1;

	if (!data || !datalen) {
		error_print();
		return 0;
	}

	*sentlen = 0;

	if (!conn->recordlen) {
		const BLOCK_CIPHER_KEY *key;
		const uint8_t *iv;
		uint8_t *seq_num;
		size_t padding_len = 0;

		int request_update = 0;

		if (conn->is_client) {
			key = &conn->client_write_key;
			iv = conn->client_write_iv;
			seq_num = conn->client_seq_num;
			//format_bytes(stderr, 0, 4, "client_write_iv", iv, 12);
			//format_bytes(stderr, 0, 4, "client_seq_num", seq_num, 8);
			//format_print(stderr, 0, 0, "\n");

		} else {
			key = &conn->server_write_key;
			iv = conn->server_write_iv;
			seq_num = conn->server_seq_num;
			//format_bytes(stderr, 0, 4, "server_write_iv", iv, 12);
			//format_bytes(stderr, 0, 4, "server_seq_num", seq_num, 8);
			//format_print(stderr, 0, 0, "\n");
		}

		// check if KeyUpdate
		if (conn->ctx->key_update
			&& GETU64(seq_num) >= conn->ctx->key_update_seq_num_limit) {
			if (!conn->key_update) {
				conn->key_update = 1;
				request_update = 1;
			}
		}
		if (conn->key_update) {
			if (conn->is_client) {
				ret = tls13_send_client_key_update(conn, request_update);
			} else {
				ret = tls13_send_server_key_update(conn, request_update);
			}

			if (ret == 1) {
				ret = TLS_ERROR_SEND_AGAIN;
			}
			return ret;
		}


		if (datalen > TLS_MAX_PLAINTEXT_SIZE) {
			datalen = TLS_MAX_PLAINTEXT_SIZE;
		}

		if(conn->verbose) {
			format_bytes(stderr, 0, 0, "send", data, datalen);
		}


		tls13_padding_len_rand(&padding_len);
		if (tls_record_set_application_data(conn->plain_record, &conn->plain_recordlen,
			data, datalen) != 1) {
			error_print();
			return -1;
		}
		if (tls13_record_encrypt(conn->cipher_suite, key, iv,
			seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
			conn->record, &conn->recordlen) != 1) {
			error_print();
			return -1;
		}
		tls_seq_num_incr(seq_num);

		ret = 1;

		conn->record_offset = 0;
		conn->send_state = TLS_state_send_record;

		// 需要记录密文对应的明文是什么，当完整的报文发送之后，这些信息要返回给调用方
		//conn->plain_recordlen = datalen + 5;
		conn->sentlen = datalen;


		if(conn->verbose) tls_trace("send {ApplicationData}\n");
		if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);

	}

	while (conn->recordlen) {
		tls_ret_t n;

		n = tls_socket_send(conn->sock, conn->record + conn->record_offset, conn->recordlen, 0);
		if (n < 0) {
			int err = tls_socket_get_error();
			tls_socket_err_t type = tls_socket_get_error_type(err, 0);
			if (type == TLS_SOCKET_ERR_WANT_WRITE) {
				return TLS_ERROR_SEND_AGAIN;
			} else if (type == TLS_SOCKET_ERR_INTERRUPTED) {
				continue;
			}
			error_print();
			return TLS_ERROR_SYSCALL;
		} else if (n == 0) {
			return TLS_ERROR_TCP_CLOSED;
		}
		conn->recordlen -= n;
		conn->record_offset += n;
	}


	//*sentlen = conn->plain_recordlen - 5;
	*sentlen = conn->sentlen;
	conn->record_offset = 0;
	conn->send_state = 0;

	return ret;
}

int tls13_do_recv(TLS_CONNECT *conn)
{
	tls_ret_t n;
	const BLOCK_CIPHER_KEY *key;
	const uint8_t *iv;
	uint8_t *seq_num;


	switch (conn->recv_state) {
	case 0:
		conn->record_offset = 0;
		conn->recordlen = TLS_RECORD_HEADER_SIZE;
		conn->recv_state = TLS_state_recv_record_header;

	case TLS_state_recv_record_header:
		while (conn->recordlen) {

			n = tls_socket_recv(conn->sock, conn->record + conn->record_offset, conn->recordlen, 0);
			if (n < 0) {
				int err = tls_socket_get_error();
				tls_socket_err_t type = tls_socket_get_error_type(err, 1);
				if (type == TLS_SOCKET_ERR_WANT_READ) {
					return TLS_ERROR_RECV_AGAIN;
				} else if (type == TLS_SOCKET_ERR_INTERRUPTED) {
					continue;
				}
				error_print();
				return TLS_ERROR_SYSCALL;
			} else if (n == 0) {
				return TLS_ERROR_TCP_CLOSED;
			}
			conn->recordlen -= n;
			conn->record_offset += n;
		}
		if (tls_record_type(conn->record) != TLS_record_application_data) {
			error_print();
			return -1;
		}
		if (tls_record_protocol(conn->record) != TLS_protocol_tls12) {
			error_print();
			return -1;
		}
		if (tls_record_data_length(conn->record) > TLS_MAX_RECORD_SIZE - TLS_RECORD_HEADER_SIZE) {
			error_print();
			return -1;
		}
		conn->recordlen = tls_record_data_length(conn->record);
		conn->recv_state = TLS_state_recv_record_data;
		// pass through

	case TLS_state_recv_record_data:
		while (conn->recordlen) {
			n = tls_socket_recv(conn->sock, conn->record + conn->record_offset, conn->recordlen, 0);
			if (n < 0) {
				int err = tls_socket_get_error();
				tls_socket_err_t type = tls_socket_get_error_type(err, 1);
				if (type == TLS_SOCKET_ERR_WANT_READ) {
					return TLS_ERROR_RECV_AGAIN;
				} else if (type == TLS_SOCKET_ERR_INTERRUPTED) {
					continue;
				}
				error_print();
				return TLS_ERROR_SYSCALL;
			} else if (n == 0) {
				return TLS_ERROR_TCP_CLOSED;
			}
			conn->recordlen -= n;
			conn->record_offset += n;
		}
		conn->recv_state = 0;
		break;

	default:
		fprintf(stderr, "conn->recv_state = %d\n", conn->recv_state);
		error_print();
		return -1;
	}

	conn->recordlen = tls_record_length(conn->record);

	if(conn->verbose) tls_trace("recv {Record}\n");
	if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);


	if (conn->is_client) {
		key = &conn->server_write_key;
		iv = conn->server_write_iv;
		seq_num = conn->server_seq_num;

		//format_bytes(stderr, 0, 4, "server_write_iv", iv, 12);
		//format_bytes(stderr, 0, 4, "server_seq_num", seq_num, 8);
		//format_print(stderr, 0, 0, "\n");


	} else {
		key = &conn->client_write_key;
		iv = conn->client_write_iv;
		seq_num = conn->client_seq_num;
		//format_bytes(stderr, 0, 4, "client_write_iv", iv, 12);
		//format_bytes(stderr, 0, 4, "client_seq_num", seq_num, 8);
		//format_print(stderr, 0, 0, "\n");
	}

	if (tls13_record_decrypt(conn->cipher_suite, key, iv, seq_num, conn->record, conn->recordlen,
		conn->plain_record, &conn->plain_recordlen) != 1) {
		error_print();
		return -1;
	}
	tls_seq_num_incr(seq_num);

	if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);


	switch (tls_record_type(conn->plain_record)) {
	case TLS_record_application_data:
		conn->data = conn->plain_record + 5;
		conn->datalen = conn->plain_recordlen - 5;
		break;

	case TLS_record_handshake:
		{
		int handshake_type;
		const uint8_t *handshake_data;
		size_t handshake_datalen;
		int update_requested;

		if (tls_record_get_handshake(conn->plain_record, &handshake_type, &handshake_data, &handshake_datalen) != 1) {
			error_print();
			return -1;
		}
		switch (handshake_type) {

		// NewSessionTicket 也不应该是被单独接收的，只能在解密并解析了handshake之后才可以
		case TLS_handshake_new_session_ticket:
			if (tls13_process_new_session_ticket(conn) != 1) {
				error_print();
				return -1;
			}
			conn->data = NULL;
			conn->datalen = 0;
			break;


		case TLS_handshake_key_update:
			if (tls13_record_get_handshake_key_update(conn->plain_record, &update_requested) != 1) {
				error_print();
				return -1;
			}

			// 如果对方要求KeyUpdate，并且也满足我方KeyUpdate的最低条件
			// 那么我们就设置key_update标志位
			// 下次发送的时候就启动KeyUpdate


			if (conn->is_client) {
				uint64_t seq_num;

				tls13_update_server_application_secret(conn);
				tls13_generate_server_application_keys(conn);


				seq_num = GETU64(conn->client_seq_num);

				if (seq_num > 2 && update_requested && conn->ctx->key_update) {
					conn->key_update = 1;
				}


			} else {
				uint64_t seq_num;

				tls13_update_client_application_secret(conn);
				tls13_generate_client_application_keys(conn);

				seq_num = GETU64(conn->server_seq_num);

				if (seq_num > 2 && update_requested && conn->ctx->key_update) {
					if(conn->verbose) {
						fprintf(stderr, "server prepare key_update\n");
					}
					conn->key_update = 1;
				}
			}

			conn->data = NULL;
			conn->datalen = 0;
			break;
		default:
			error_print();
			return -1;
		}
		}
		break;

	case TLS_record_alert:
		{
		int alert_level;
		int alert_description;

		if (tls_record_get_alert(conn->plain_record, &alert_level, &alert_description) != 1) {
			error_print();
			return -1;
		}
		if (alert_description == TLS_alert_close_notify) {
			conn->close_notify_received = 1;
			conn->data = NULL;
			conn->datalen = 0;
			conn->record_offset = 0;
			conn->recordlen = 0;
			conn->plain_recordlen = 0;
			return 0;
		}
		}
		return -1;

	default:
		error_print();
		return -1;
	}

	return 1;
}

int tls13_recv(TLS_CONNECT *conn, uint8_t *out, size_t outlen, size_t *recvlen)
{
	if (!conn || !out || !outlen || !recvlen) {
		error_print();
		return -1;
	}

	*recvlen = 0;

	if (conn->datalen == 0) {
		int ret;
		for (;;) {
			if ((ret = tls13_do_recv(conn)) != 1) {
				if (ret != 0 && ret != TLS_ERROR_RECV_AGAIN && ret != TLS_ERROR_SEND_AGAIN) {
					error_print();
				}
				return ret;
			}
			if (conn->datalen) {
				break;
			}
			conn->record_offset = 0;
			conn->recordlen = 0;
			conn->plain_recordlen = 0;
		}
	}
	*recvlen = outlen <= conn->datalen ? outlen : conn->datalen;
	memcpy(out, conn->data, *recvlen);
	conn->data += *recvlen;
	conn->datalen -= *recvlen;

	// 这里接受完成之后，应该recordlen = 0

	conn->recordlen = 0;


	return 1;
}


// 这里需要考虑max_early_data_size的问题
int tls13_recv_early_data(TLS_CONNECT *conn)
{
	int ret;

	if(conn->verbose) tls_trace("recv EarlyData\n");

	if ((ret = tls13_do_recv(conn)) != 1) {
		if (ret != TLS_ERROR_RECV_AGAIN && ret != TLS_ERROR_SEND_AGAIN) {
			error_print();
		}
		return ret;
	}

	if (conn->datalen > sizeof(conn->early_data_buf)) {
		error_print();
		return -1;
	}
	memcpy(conn->early_data_buf, conn->data, conn->datalen);
	conn->early_data_len = conn->datalen;

	if(conn->verbose) {
		format_string(stderr, 0, 4, "EarlyData", conn->early_data_buf, conn->early_data_len);
	}


	// 清空记录，防止后续的握手处理过程出现问题			
	// 需要考虑统一的record状态更新
	// 还需要考虑 tls13_recv 如何消费掉 early_data

	conn->record_offset = 0;
	conn->recordlen = 0;
	conn->plain_recordlen = 0;

	return 1;
}





int tls13_ctx_set_max_key_exchanges(TLS_CTX *ctx, size_t cnt)
{
	size_t key_exchanges_capacity
		= sizeof(((TLS_CONNECT *)0)->key_exchanges)/sizeof(((TLS_CONNECT *)0)->key_exchanges[0]);

	if (!ctx) {
		error_print();
		return -1;
	}
	if (cnt > key_exchanges_capacity) {
		cnt = key_exchanges_capacity;
	}
	ctx->key_exchanges_cnt = cnt;
	return 1;
}

int tls13_enable_post_handshake_auth(TLS_CONNECT *conn)
{
	if (!conn) {
		error_print();
		return -1;
	}
	conn->post_handshake_auth = 1;
	return 1;
}










// Extensions

/*
43. supported_versions

struct {
	ProtocolVersion versions<2..254>;
} SupportedVersions; -- in ClientHello, ClientHello2
*/
int tls13_client_supported_versions_ext_to_bytes(const int *versions, size_t versions_cnt,
	uint8_t **out, size_t *outlen)
{
	uint16_t ext_type = TLS_extension_supported_versions;
	size_t ext_datalen;
	size_t versions_len;
	size_t i;

	if (!versions || !versions_cnt || !outlen) {
		error_print();
		return -1;
	}
	if (versions_cnt > 254/2) {
		error_print();
		return -1;
	}
	for (i = 0; i < versions_cnt; i++) {
		if (!tls_protocol_name(versions[i])) {
			error_print();
			return -1;
		}
	}
 	versions_len = tls_uint16_size() * versions_cnt;
	ext_datalen = tls_uint8_size() + versions_len;
	tls_uint16_to_bytes(ext_type, out, outlen);
	tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen);
	tls_uint8_to_bytes((uint8_t)versions_len, out, outlen);
	for (i = 0; i < versions_cnt; i++) {
		tls_uint16_to_bytes((uint16_t)versions[i], out, outlen);
	}
	return 1;
}

int tls13_process_client_supported_versions(const uint8_t *ext_data, size_t ext_datalen,
	const int *server_versions, size_t server_versions_cnt,
	int *common_versions, size_t *common_versions_cnt, size_t max_cnt)
{
	const uint8_t *versions;
	size_t versions_len;
	const uint8_t *cp;
	size_t len;
	uint16_t version;
	size_t i, j = 0;

	if (tls_uint8array_from_bytes(&versions, &versions_len, &ext_data, &ext_datalen) != 1
		|| tls_length_is_zero(ext_datalen) != 1) {
		error_print();
		return -1;
	}
	if (versions_len < 2 || versions_len > 254) {
		error_print();
		return -1;
	}

	cp = versions;
	len = versions_len;
	while (len) {
		if (tls_uint16_from_bytes(&version, &cp, &len) != 1) {
			error_print();
			return -1;
		}
		if (!tls_protocol_name(version)) {
			error_print();
			return -1;
		}
		if (version == server_versions[0] && j < max_cnt) {
			common_versions[j++] = version;
		}
	}
	for (i = 1; i < server_versions_cnt && j < max_cnt; i++) {
		cp = versions;
		len = versions_len;
		while (len) {
			tls_uint16_from_bytes(&version, &cp, &len);
			if (version == server_versions[i]) {
				common_versions[j++] = version;
				break;
			}
		}
	}
	*common_versions_cnt = j;
	if (*common_versions_cnt == 0) {
		error_print();
		return 0;
	}
	return 1;
}

int tls13_client_supported_versions_print(FILE *fp, int fmt, int ind,
	const uint8_t *ext_data, size_t ext_datalen)
{
	const uint8_t *versions;
	size_t versions_len;

	format_print(fp, fmt, ind, "versions\n");
	ind += 4;

	if (tls_uint8array_from_bytes(&versions, &versions_len, &ext_data, &ext_datalen) != 1) {
		error_print();
		return -1;
	}
	if (versions_len < 2 || versions_len > 254) {
		error_print();
		return -1;
	}
	while (versions_len) {
		uint16_t version;
		if (tls_uint16_from_bytes(&version, &versions, &versions_len) != 1) {
			error_print();
			return -1;
		}
		format_print(fp, fmt, ind, "%s (%04x)\n", tls_protocol_name(version), version);
	}
	if (ext_datalen) {
		error_print();
		return -1;
	}
	return 1;
}

/*
struct {
	ProtocolVersion selected_version;
} SupportedVersions; -- in ServerHello and HelloRetryRequest
*/
int tls13_server_supported_versions_ext_to_bytes(int selected_version, uint8_t **out, size_t *outlen)
{
	uint16_t ext_type = TLS_extension_supported_versions;
	size_t ext_datalen;

	if (!outlen) {
		error_print();
		return -1;
	}
	if (!tls_protocol_name(selected_version)) {
		error_print();
		return -1;
	}
	ext_datalen = tls_uint16_size();
	tls_uint16_to_bytes(ext_type, out, outlen);
	tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen);
	tls_uint16_to_bytes(selected_version, out, outlen);
	return 1;
}

int tls13_server_supported_versions_from_bytes(int *selected_version, const uint8_t *ext_data, size_t ext_datalen)
{
	uint16_t version;
	if (tls_uint16_from_bytes(&version, &ext_data, &ext_datalen) != 1
		|| tls_length_is_zero(ext_datalen) != 1) {
		error_print();
		return -1;
	}
	if (!tls_protocol_name(version)) {
		error_print();
		return -1;
	}
	*selected_version = version;
	return 1;
}

int tls13_process_server_supported_versions(const int *client_versions, size_t client_versions_cnt,
	const uint8_t *server_ext_data, size_t server_ext_datalen,
	int *selected_version)
{
	uint16_t version;
	size_t i;

	if (tls_uint16_from_bytes(&version, &server_ext_data, &server_ext_datalen) != 1
		|| tls_length_is_zero(server_ext_datalen) != 1) {
		error_print();
		return -1;
	}
	for (i = 0; i < client_versions_cnt; i++) {
		if (version == client_versions[i]) {
			*selected_version = version;
			return 1;
		}
	}
	error_print();
	return -1;
}

int tls13_server_supported_versions_print(FILE *fp, int fmt, int ind,
	const uint8_t *ext_data, size_t ext_datalen)
{
	uint16_t version;

	if (tls_uint16_from_bytes(&version, &ext_data, &ext_datalen) != 1) {
		error_print();
		return -1;
	}
	format_print(fp, fmt, ind, "selected_version: %s (%04x)\n", tls_protocol_name(version), version);
	if (ext_datalen) {
		error_print();
		return -1;
	}
	return 1;
}

/*
47. certificate_authorities

opaque DistinguishedName<1..2^16-1>;

struct {
	DistinguishedName authorities<3..2^16-1>;
} CertificateAuthoritiesExtension;
*/

int tls13_certificate_authorities_ext_to_bytes(const uint8_t *ca_names, size_t ca_names_len,
	uint8_t **out, size_t *outlen)
{
	int ext_type = TLS_extension_certificate_authorities;

	if (!ca_names || !ca_names_len || !outlen) {
		error_print();
		return -1;
	}

	tls_uint16_to_bytes(ext_type, out, outlen);
	tls_uint16_to_bytes((uint16_t)(tls_uint16_size() + ca_names_len), out, outlen);
	tls_uint16array_to_bytes(ca_names, ca_names_len, out, outlen);

	return 1;
}

int tls13_certificate_authorities_from_bytes(const uint8_t **ca_names, size_t *ca_names_len,
	const uint8_t *ext_data, size_t ext_datalen)
{
	if (tls_uint16array_from_bytes(ca_names, ca_names_len, &ext_data, &ext_datalen) != 1
		|| tls_length_is_zero(ext_datalen) != 1) {
		error_print();
		return -1;
	}
	if (*ca_names == NULL) {
		error_print();
		return -1;
	}
	return 1;
}

int tls13_enable_certificate_authorities(TLS_CONNECT *conn, int enable)
{
	if (!conn) {
		error_print();
		return -1;
	}
	if (!conn->ctx->cacertslen) {
		error_print();
		return -1;
	}
	conn->certificate_authorities = enable ? 1 : 0;
	return 1;
}

int tls13_certificate_authorities_print(FILE *fp, int fmt, int ind,
	const uint8_t *ext_data, size_t ext_datalen)
{
	const uint8_t *authorities;
	size_t authorities_len;

	format_print(fp, fmt, ind, "authorities\n");
	ind += 4;

	if (tls_uint16array_from_bytes(&authorities, &authorities_len, &ext_data, &ext_datalen) != 1
		|| tls_length_is_zero(ext_datalen) != 1) {
		error_print();
		return -1;
	}
	while (authorities_len) {
		const uint8_t *name;
		size_t namelen;
		const uint8_t *d;
		size_t dlen;

		if (tls_uint16array_from_bytes(&name, &namelen, &authorities, &authorities_len) != 1) {
			error_print();
			return -1;
		}
		if (asn1_sequence_from_der(&d, &dlen, &name, &namelen) != 1
			|| asn1_length_is_zero(namelen) != 1) {
			error_print();
			return -1;
		}
		x509_name_print(fp, fmt, ind, "DistinguishedName", d, dlen);
	}
	return 1;
}

/*
48. oid_filters

struct {
	OIDFilter filters<0..2^16-1>;
} OIDFilterExtension;

struct {
	opaque certificate_extension_oid<1..2^8-1>;
	opaque certificate_extension_values<0..2^16-1>;
} OIDFilter;
*/

int tls13_oid_filters_ext_to_bytes(const uint8_t *filters, size_t filters_len, uint8_t **out, size_t *outlen)
{
	uint16_t ext_type = TLS_extension_oid_filters;
	size_t ext_datalen;

	if (!outlen) {
		error_print();
		return -1;
	}

	ext_datalen = tls_uint16_size() + filters_len;
	tls_uint16_to_bytes(ext_type, out, outlen);
	tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen);
	tls_uint16array_to_bytes(filters, filters_len, out, outlen);

	return 1;
}

int tls13_oid_filters_from_bytes(const uint8_t **filters, size_t *filters_len,
	const uint8_t *ext_data, size_t ext_datalen)
{
	if (tls_uint16array_from_bytes(filters, filters_len, &ext_data, &ext_datalen) != 1
		|| tls_length_is_zero(ext_datalen) != 1) {
		error_print();
		return -1;
	}
	return 1;
}

int tls13_oid_filters_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
	format_bytes(fp, fmt, ind, "data", d, dlen);
	return 1;
}

/*
51. key_share

struct {
	NamedGroup group;
	opaque key_exchange<1..2^16-1>;
} KeyShareEntry;
*/
int tls13_key_share_entry_to_bytes(const X509_KEY *key, uint8_t **out, size_t *outlen)
{
	uint16_t group;
	uint8_t key_exchange[65];

	if (!key || !outlen) {
		error_print();
		return -1;
	}
	if (key->algor != OID_ec_public_key) {
		error_print();
		return -1;
	}
	if (!(group = tls_named_curve_from_oid(key->algor_param))) {
		error_print();
		return -1;
	}
	if (out && *out) {
		uint8_t *p = key_exchange;
		size_t len = 0;
		if (x509_public_key_to_bytes(key, &p, &len) != 1) {
			error_print();
			return -1;
		}
		if (len != 65) {
			error_print();
			return -1;
		}
	}
	tls_uint16_to_bytes(group, out, outlen);
	tls_uint16array_to_bytes(key_exchange, 65, out, outlen);
	return 1;
}

int tls13_key_share_entry_from_bytes(int *group, const uint8_t **key_exchange, size_t *key_exchange_len,
	const uint8_t **in, size_t *inlen)
{
	uint16_t named_curve;

	if (tls_uint16_from_bytes(&named_curve, in, inlen) != 1
		|| tls_uint16array_from_bytes(key_exchange, key_exchange_len, in, inlen) != 1) {
		error_print();
		return -1;
	}

	switch (named_curve) {
	case TLS_curve_secp256r1:
	case TLS_curve_sm2p256v1:
		if (*key_exchange_len != 65) {
			error_print();
			return -1;
		}
		break;
	}

	*group = named_curve;
	return 1;
}

/*
struct {
	KeyShareEntry client_shares<0..2^16-1>;
} KeyShareClientHello;
*/
int tls13_key_share_client_hello_ext_to_bytes(const X509_KEY *keys, size_t keys_cnt, uint8_t **out, size_t *outlen)
{
	uint16_t ext_type = TLS_extension_key_share;
	size_t ext_datalen = 0;
	size_t client_shares_len = 0;
	size_t i;

	for (i = 0; i < keys_cnt; i++) {
		if (tls13_key_share_entry_to_bytes(&keys[i], NULL, &client_shares_len) != 1) {
			error_print();
			return -1;
		}
	}
	ext_datalen = 2 + client_shares_len;

	tls_uint16_to_bytes(ext_type, out, outlen);
	tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen);
	tls_uint16_to_bytes((uint16_t)client_shares_len, out, outlen);
	for (i = 0; i < keys_cnt; i++) {
		tls13_key_share_entry_to_bytes(&keys[i], out, outlen);
	}
	return 1;
}

// allow supported_groups, supported_groups_cnt == NULL, 0
int tls13_process_key_share_client_hello(const uint8_t *ext_data, size_t ext_datalen,
	const int *supported_groups, size_t supported_groups_cnt,
	int *group, const uint8_t **key_exchange, size_t *key_exchange_len)
{
	int ret = 0;
	const uint8_t *client_shares;
	size_t client_shares_len;
	size_t i;

	if (tls_uint16array_from_bytes(&client_shares, &client_shares_len, &ext_data, &ext_datalen) != 1
		|| tls_length_is_zero(ext_datalen) != 1) {
		error_print();
		return -1;
	}

	for (i = 0; i < supported_groups_cnt; i++) {
		const uint8_t *cp = client_shares;
		size_t len = client_shares_len;
		int named_curve;
		const uint8_t *point;
		size_t pointlen;

		while (len) {
			if (tls13_key_share_entry_from_bytes(&named_curve, &point, &pointlen, &cp, &len) != 1) {
				error_print();
				return -1;
			}
			if (named_curve == supported_groups[i]) {
				*group = named_curve;
				*key_exchange = point;
				*key_exchange_len = pointlen;
				return 1;
			}
		}
	}
	return 0;
}

int tls13_process_key_share_client_hello_again(const uint8_t *ext_data, size_t ext_datalen,
	int key_exchange_group, const uint8_t **key_exchange, size_t *key_exchange_len)
{
	int ret = 0;
	const uint8_t *client_shares;
	size_t client_shares_len;
	int group;

	if (tls_uint16array_from_bytes(&client_shares, &client_shares_len, &ext_data, &ext_datalen) != 1
		|| tls_length_is_zero(ext_datalen) != 1) {
		error_print();
		return -1;
	}
	if (tls13_key_share_entry_from_bytes(&group, key_exchange, key_exchange_len, &client_shares, &client_shares_len) != 1
		|| tls_length_is_zero(client_shares_len) != 1) {
		error_print();
		return -1;
	}
	if (group != key_exchange_group) {
		error_print();
		return -1;
	}
	return 1;
}

int tls13_key_share_client_hello_print(FILE *fp, int fmt, int ind,
	const uint8_t *data, size_t datalen)
{
	const uint8_t *client_shares;
	size_t client_shares_len;

	format_print(fp, fmt, ind, "client_shares\n");
	ind += 4;
	if (tls_uint16array_from_bytes(&client_shares, &client_shares_len, &data, &datalen) != 1) {
		error_print();
		return -1;
	}
	if (!client_shares_len) {
		format_print(fp, fmt, ind, "(null)\n");
	}
	while (client_shares_len) {
		uint16_t group;
		const uint8_t *key_exchange;
		size_t key_exchange_len;

		format_print(fp, fmt, ind, "KeyShareEntry\n");
		if (tls_uint16_from_bytes(&group, &client_shares, &client_shares_len) != 1
			|| tls_uint16array_from_bytes(&key_exchange, &key_exchange_len, &client_shares, &client_shares_len) != 1) {
			error_print();
			return -1;
		}
		format_print(fp, fmt, ind + 4, "group: %s (%04x)\n", tls_named_curve_name(group), group);
		format_bytes(fp, fmt, ind + 4, "key_exchange", key_exchange, key_exchange_len);
	}
	if (datalen) {
		error_print();
		return -1;
	}
	return 1;
}

/*
struct {
	KeyShareEntry server_share;
} KeyShareServerHello;
*/
int tls13_key_share_server_hello_ext_to_bytes(const X509_KEY *key, uint8_t **out, size_t *outlen)
{
	uint16_t ext_type = TLS_extension_key_share;
	size_t ext_datalen = 0;

	if (tls13_key_share_entry_to_bytes(key, NULL, &ext_datalen) != 1) {
		error_print();
		return -1;
	}
	tls_uint16_to_bytes(ext_type, out, outlen);
	tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen);
	tls13_key_share_entry_to_bytes(key, out, outlen);
	return 1;
}

int tls13_key_share_server_hello_from_bytes(int *group, const uint8_t **key_exchange, size_t *key_exchange_len,
	const uint8_t *ext_data, size_t ext_datalen)
{
	if (tls13_key_share_entry_from_bytes(group, key_exchange, key_exchange_len,
			&ext_data, &ext_datalen) != 1
		|| tls_length_is_zero(ext_datalen) != 1) {
		error_print();
		return -1;
	}
	return 1;
}

int tls13_key_share_server_hello_print(FILE *fp, int fmt, int ind,
	const uint8_t *data, size_t datalen)
{
	uint16_t group;
	const uint8_t *key_exchange;
	size_t key_exchange_len;

	format_print(fp, fmt, ind, "server_share\n");
	ind += 4;
	if (tls_uint16_from_bytes(&group, &data, &datalen) != 1
		|| tls_uint16array_from_bytes(&key_exchange, &key_exchange_len, &data, &datalen) != 1) {
		error_print();
		return -1;
	}
	format_print(fp, fmt, ind, "group: %s (%04x)\n", tls_named_curve_name(group), group);
	format_bytes(fp, fmt, ind, "key_exchange", key_exchange, key_exchange_len);
	if (datalen) {
		error_print();
		return -1;
	}
	return 1;
}

/*
struct {
	NamedGroup selected_group;
} KeyShareHelloRetryRequest;
*/
int tls13_key_share_hello_retry_request_ext_to_bytes(int selected_group, uint8_t **out, size_t *outlen)
{
	uint16_t ext_type = TLS_extension_key_share;

	uint8_t ext_data[2];
	uint8_t *p = ext_data;
	size_t len = 0;

	tls_uint16_to_bytes((uint16_t)selected_group, &p, &len);
	tls_ext_to_bytes(ext_type, ext_data, sizeof(ext_data), out, outlen);

	return 1;
}

int tls13_key_share_hello_retry_request_from_bytes(int *selected_group, const uint8_t *ext_data, size_t ext_datalen)
{
	uint16_t group;

	if (tls_uint16_from_bytes(&group, &ext_data, &ext_datalen) != 1
		|| tls_length_is_zero(ext_datalen) != 1) {
		error_print();
		return -1;
	}
	if (!tls_named_curve_name(group)) {
		error_print();
		return -1;
	}
	*selected_group = group;
	return 1;
}

int tls13_key_share_hello_retry_request_print(FILE *fp, int fmt, int ind,
	const uint8_t *ext_data, size_t ext_datalen)
{
	uint16_t selected_group;

	if (tls_uint16_from_bytes(&selected_group, &ext_data, &ext_datalen) != 1) {
		error_print();
		return -1;
	}
	format_print(fp, fmt, ind, "selected_group: %s (%04x)\n",
		tls_named_curve_name(selected_group), selected_group);
	if (ext_datalen) {
		error_print();
		return -1;
	}
	return 1;
}


// Handshakes
//	ClientHello
//	ServerHello
//	HelloRetryRequest
//	EncryptedExtensions
//	Certificate
//	CertificateRequest
//	CertificateVerify
//	Finished
//	KeyUpdate


/*
ClientHello

struct {
	ProtocolVersion legacy_version = 0x0303;
	Random random;
	opaque legacy_session_id<0..32>;
	CipherSuite cipher_suites<2..2^16-2>;
	opaque legacy_compression_methods<1..2^8-1>;
	Extension extensions<8..2^16-1>;
} ClientHello;

uint16 ProtocolVersion;
opaque Random[32];
uint8 CipherSuite[2];
*/

int tls13_ctx_set_client_hello_key_exchanges_cnt(TLS_CTX *ctx, size_t cnt)
{
	if (!ctx) {
		error_print();
		return -1;
	}
	if (cnt > sizeof(((TLS_CONNECT *)NULL)->key_exchanges)/sizeof(((TLS_CONNECT *)NULL)->key_exchanges[0])) {
		error_print();
		return -1;
	}

	ctx->key_exchanges_cnt = cnt;
	return 1;
}

int tls13_client_hello_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
	uint16_t protocol;
	const uint8_t *random;
	const uint8_t *session_id;
	const uint8_t *cipher_suites;
	const uint8_t *comp_meths;
	const uint8_t *exts;
	size_t session_id_len, cipher_suites_len, comp_meths_len, extslen;
	size_t i;

	format_print(fp, fmt, ind, "ClientHello\n");
	ind += 4;

	if (tls_uint16_from_bytes(&protocol, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	format_print(fp, fmt, ind, "legacy_version: %s (%04x)\n",
		tls_protocol_name(protocol), protocol);

	if (tls_array_from_bytes(&random, 32, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	format_bytes(fp, fmt, ind, "random", random ,32);

	if (tls_uint8array_from_bytes(&session_id, &session_id_len, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	format_bytes(fp, fmt, ind, "legacy_session_id", session_id, session_id_len);

	format_print(fp, fmt, ind, "cipher_suites\n");
	if (tls_uint16array_from_bytes(&cipher_suites, &cipher_suites_len, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	while (cipher_suites_len) {
		uint16_t cipher;
		if (tls_uint16_from_bytes(&cipher, &cipher_suites, &cipher_suites_len) != 1) {
			error_print();
			return -1;
		}
		format_print(fp, fmt, ind+4, "%s (%04x)\n", tls_cipher_suite_name(cipher), cipher);
	}

	format_print(fp, fmt, ind, "legacy_compression_methods\n");
	if (tls_uint8array_from_bytes(&comp_meths, &comp_meths_len, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	for (i = 0; i < comp_meths_len; i++) {
		format_print(fp, fmt, ind + 4, "%s (%d)\n",
			tls_compression_method_name(comp_meths[i]), comp_meths[i]);
	}

	format_print(fp, fmt, ind, "extensions\n");
	ind += 4;
	if (tls_uint16array_from_bytes(&exts, &extslen, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	while (extslen) {
		uint16_t ext_type;
		const char *ext_name;
		const uint8_t *ext_data;
		size_t ext_datalen;

		// tls_ext_from_bytes can not parse unknown ext
		if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
			|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
			error_print();
			return -1;
		}
		ext_name = tls_extension_name(ext_type);
		if (!ext_name) {
			ext_name = "(unknown)";
		}
		format_print(fp, fmt, ind, "%s (%d)\n", ext_name, ext_type);

		switch (ext_type) {
		case TLS_extension_supported_versions:
			tls13_client_supported_versions_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_signature_algorithms:
			tls_signature_algorithms_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_signature_algorithms_cert:
			tls_signature_algorithms_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_certificate_authorities:
			tls13_certificate_authorities_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_server_name:
			tls_server_name_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_status_request:
			tls_client_status_request_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_signed_certificate_timestamp:
			format_bytes(fp, fmt, ind + 4, "data", ext_data, ext_datalen); // should be empty
			break;
		case TLS_extension_supported_groups:
			tls_supported_groups_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_key_share:
			tls13_key_share_client_hello_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_psk_key_exchange_modes:
			tls13_psk_key_exchange_modes_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_pre_shared_key:
			tls13_client_pre_shared_key_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_early_data:
			tls13_early_data_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_cookie:
			tls13_cookie_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_post_handshake_auth:
			format_bytes(fp, fmt, ind + 4, "data", ext_data, ext_datalen); // should be empty
			break;
		case TLS_extension_ec_point_formats:
			tls_ec_point_formats_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_max_fragment_length:
		case TLS_extension_use_srtp:
		case TLS_extension_heartbeat:
		case TLS_extension_application_layer_protocol_negotiation:
		case TLS_extension_server_certificate_type:
		case TLS_extension_client_certificate_type:
		case TLS_extension_padding:
		case TLS_extension_record_size_limit:
			format_bytes(fp, fmt, ind + 4, "data", ext_data, ext_datalen);
			break;
		default:
			format_bytes(fp, fmt, ind + 4, "data", ext_data, ext_datalen);
		}
	}
	if (dlen) {
		error_print();
		return -1;
	}
	return 1;
}

// ServerHello.random if HelloRetryReqeust
static const unsigned char TLS13_HELLO_RETRY_REQUEST_RANDOM[32] = {
	0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
	0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
	0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,
	0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C
};

/*
ServerHello

struct {
	ProtocolVersion legacy_version = 0x0303;
	Random random;
	opaque legacy_session_id_echo<0..32>;
	CipherSuite cipher_suite;
	uint8 legacy_compression_method = 0;
	Extension extensions<6..2^16-1>;
} ServerHello;
*/
int tls13_server_hello_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
	int hello_retry_request = 0;
	uint16_t protocol;
	const uint8_t *random;
	const uint8_t *session_id;
	uint16_t cipher_suite;
	uint8_t comp_meth;
	const uint8_t *exts;
	size_t session_id_len, extslen;

	format_print(fp, fmt, ind, "ServerHello\n");
	ind += 4;

	if (tls_uint16_from_bytes(&protocol, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	format_print(fp, fmt, ind, "legacy_version: %s (%04x)\n",
		tls_protocol_name(protocol), protocol);

	if (tls_array_from_bytes(&random, 32, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	format_bytes(fp, fmt, ind, "random", random, 32);

	// if ServerHello is HelloRetryRequest
	if (memcmp(random, TLS13_HELLO_RETRY_REQUEST_RANDOM, 32) == 0) {
		hello_retry_request = 1;
	}

	if (tls_uint8array_from_bytes(&session_id, &session_id_len, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	format_bytes(fp, fmt, ind, "legacy_session_id", session_id, session_id_len);

	if (tls_uint16_from_bytes(&cipher_suite, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	format_print(fp, fmt, ind, "cipher_suite: %s (%04x)\n",
		tls_cipher_suite_name(cipher_suite), cipher_suite);

	if (tls_uint8_from_bytes(&comp_meth, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	format_print(fp, fmt, ind, "legacy_compression_method: %s (%d)\n",
		tls_compression_method_name(comp_meth), comp_meth);

	format_print(fp, fmt, ind, "extensions\n");
	ind += 4;
	if (tls_uint16array_from_bytes(&exts, &extslen, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	while (extslen) {
		uint16_t ext_type;
		const uint8_t *ext_data;
		size_t ext_datalen;

		if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
			|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
			error_print();
			return -1;
		}
		format_print(fp, fmt, ind, "%s (%d)\n", tls_extension_name(ext_type), ext_type);
		switch (ext_type) {
		case TLS_extension_supported_versions:
			tls13_server_supported_versions_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_key_share:
			if (hello_retry_request)
				tls13_key_share_hello_retry_request_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			else	tls13_key_share_server_hello_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_pre_shared_key:
			tls13_server_pre_shared_key_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_cookie:
			tls13_cookie_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		default:
			format_bytes(fp, fmt, ind + 4, "raw_data", ext_data, ext_datalen);
			error_print();
			return -1;
		}
	}
	if (dlen) {
		error_print();
		return -1;
	}
	return 1;
}

/*
HelloRetryReqeust

	For reasons of backward compatibility with middleboxes (see
	Appendix D.4), the HelloRetryRequest message uses the same structure
	as the ServerHello, but with Random set to the special value of the
	SHA-256 of "HelloRetryRequest":

	CF 21 AD 74 E5 9A 61 11 BE 1D 8C 02 1E 65 B8 91
	C2 A2 11 16 7A BB 8C 5E 07 9E 09 E2 C8 A8 33 9C

	TLS 1.3 has a downgrade protection mechanism embedded in the server's
	random value.  TLS 1.3 servers which negotiate TLS 1.2 or below in
	response to a ClientHello MUST set the last 8 bytes of their Random
	value specially in their ServerHello.

	If negotiating TLS 1.2, TLS 1.3 servers MUST set the last 8 bytes of
	their Random value to the bytes:

	44 4F 57 4E 47 52 44 01

	If negotiating TLS 1.1 or below, TLS 1.3 servers MUST, and TLS 1.2
	servers SHOULD, set the last 8 bytes of their ServerHello.Random
	value to the bytes:

	44 4F 57 4E 47 52 44 00
*/

int tls13_record_set_handshake_hello_retry_request(uint8_t *record, size_t *recordlen,
	int legacy_version, const uint8_t random[32],
	const uint8_t *legacy_session_id_echo, size_t legacy_session_id_echo_len,
	int cipher_suite, int legacy_compress_meth,
	const uint8_t *exts, size_t extslen)
{
	//int type = TLS_handshake_hello_retry_request;
	int type = TLS_handshake_server_hello;
	uint8_t *p;
	size_t len;

	if (!tls_protocol_name(legacy_version)) {
		error_print();
		return -1;
	}
	if (legacy_session_id_echo_len > 32) {
		error_print();
		return -1;
	}
	if (!tls_cipher_suite_name(cipher_suite)) {
		error_print();
		return -1;
	}
	if (legacy_compress_meth > 255) {
		error_print();
		return -1;
	}

	p = tls_handshake_data(tls_record_data(record));
	len = 0;

	tls_uint16_to_bytes((uint16_t)legacy_version, &p, &len);
	tls_array_to_bytes(random, 32, &p, &len);
	tls_uint8array_to_bytes(legacy_session_id_echo, legacy_session_id_echo_len, &p, &len);
	tls_uint16_to_bytes((uint16_t)cipher_suite, &p, &len);
	tls_uint8_to_bytes((uint8_t)legacy_compress_meth, &p, &len);
	tls_uint16array_to_bytes(exts, extslen, &p, &len);

	if (tls_record_set_handshake(record, recordlen, type, NULL, len) != 1) {
		error_print();
		return -1;
	}
	return 1;
}

int tls13_record_get_handshake_hello_retry_request(uint8_t *record,
	int *legacy_version, const uint8_t **random,
	const uint8_t **legacy_session_id_echo, size_t *legacy_session_id_echo_len,
	int *cipher_suite, int *legacy_compress_meth,
	const uint8_t **exts, size_t *extslen)
{
	int type;
	const uint8_t *cp;
	size_t len;
	uint16_t version;
	uint16_t cipher;
	uint8_t comp_meth;

	if (tls_record_get_handshake(record, &type, &cp, &len) != 1) {
		error_print();
		return -1;
	}
	if (type != TLS_handshake_hello_retry_request
		&& type != TLS_handshake_server_hello) {
		error_print();
		return -1;
	}
	if (tls_uint16_from_bytes(&version, &cp, &len) != 1
		|| tls_array_from_bytes(random, 32, &cp, &len) != 1
		|| tls_uint8array_from_bytes(legacy_session_id_echo, legacy_session_id_echo_len, &cp, &len) != 1
		|| tls_uint16_from_bytes(&cipher, &cp, &len) != 1
		|| tls_uint8_from_bytes(&comp_meth, &cp, &len) != 1
		|| tls_uint16array_from_bytes(exts, extslen, &cp, &len) != 1
		|| tls_length_is_zero(len) != 1) {
		error_print();
		return -1;
	}

	// if legacy_version != tls12, send protocol_version alert
	if (!tls_protocol_name(version)) {
		error_print();
		return -1;
	}
	if (version != TLS_protocol_tls12) {
		error_print();
	}
	*legacy_version = version;

	if (*legacy_session_id_echo_len > 32) {
		error_print();
		return -1;
	}

	if (!tls_cipher_suite_name(cipher)) {
		error_print();
		return -1;
	}
	*cipher_suite = cipher;

	// if legacy_compress_meth != 0, send illegal_parameter alert
	if (comp_meth != 0) {
		error_print();
	}
	*legacy_compress_meth = comp_meth;

	if (*extslen < 6) {
		error_print();
		return -1;
	}
	return 1;
}

int tls13_hello_retry_request_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
	uint16_t protocol;
	const uint8_t *random;
	const uint8_t *session_id;
	uint16_t cipher_suite;
	uint8_t comp_meth;
	const uint8_t *exts;
	size_t session_id_len, extslen;

	format_print(fp, fmt, ind, "HelloRetryRequest\n");
	ind += 4;

	if (tls_uint16_from_bytes(&protocol, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	format_print(fp, fmt, ind, "legacy_version: %s (%04x)\n",
		tls_protocol_name(protocol), protocol);

	if (tls_array_from_bytes(&random, 32, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	format_bytes(fp, fmt, ind, "random", random, 32);

	if (tls_uint8array_from_bytes(&session_id, &session_id_len, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	format_bytes(fp, fmt, ind, "legacy_session_id", session_id, session_id_len);

	if (tls_uint16_from_bytes(&cipher_suite, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	format_print(fp, fmt, ind, "cipher_suite: %s (%04x)\n",
		tls_cipher_suite_name(cipher_suite), cipher_suite);

	if (tls_uint8_from_bytes(&comp_meth, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	format_print(fp, fmt, ind, "legacy_compression_method: %s (%d)\n",
		tls_compression_method_name(comp_meth), comp_meth);

	format_print(fp, fmt, ind, "extensions\n");
	ind += 4;
	if (tls_uint16array_from_bytes(&exts, &extslen, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	while (extslen) {
		uint16_t ext_type;
		const uint8_t *ext_data;
		size_t ext_datalen;

		if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
			|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
			error_print();
			return -1;
		}
		format_print(fp, fmt, ind, "%s (%d)\n", tls_extension_name(ext_type), ext_type);
		switch (ext_type) {
		case TLS_extension_supported_versions:
			tls13_server_supported_versions_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_key_share:
			tls13_key_share_hello_retry_request_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_pre_shared_key:
			tls13_client_pre_shared_key_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_cookie:
			tls13_cookie_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		default:
			format_bytes(fp, fmt, ind + 4, "raw_data", ext_data, ext_datalen);
			return -1;
		}
	}
	if (dlen) {
		error_print();
		return -1;
	}

	return 1;
}

/*
EncrypytedExtensions

struct {
	Extension extensions<0..2^16-1>;
} EncryptedExtensions;
*/

int tls13_record_set_handshake_encrypted_extensions(uint8_t *record, size_t *recordlen,
	const uint8_t *exts, size_t extslen)
{
	int type = TLS_handshake_encrypted_extensions;
	uint8_t *p = record + 5 + 4;
	size_t len = 0;

	tls_uint16array_to_bytes(exts, extslen, &p, &len);
	tls_record_set_handshake(record, recordlen, type, NULL, len);
	return 1;
}

int tls13_record_get_handshake_encrypted_extensions(const uint8_t *record,
	const uint8_t **exts, size_t *extslen)
{
	int type;
	const uint8_t *cp;
	size_t len;

	if (tls_record_get_handshake(record, &type, &cp, &len) != 1) {
		error_print();
		return -1;
	}
	if (type != TLS_handshake_encrypted_extensions) {
		error_print();
		return 0;
	}
	if (tls_uint16array_from_bytes(exts, extslen, &cp, &len) != 1
		|| tls_length_is_zero(len) != 1) {
		error_print();
		return -1;
	}
	return 1;
}

int tls13_encrypted_extensions_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
	const uint8_t *exts;
	size_t extslen;

	format_print(fp, fmt, ind, "EncryptedExtensions\n");
	ind += 4;
	format_print(fp, fmt, ind, "extensions\n");
	ind += 4;

	if (tls_uint16array_from_bytes(&exts, &extslen, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	if (!extslen) {
		format_print(fp, fmt, ind, "(null)\n");
	}
	while (extslen) {
		uint16_t ext_type;
		const uint8_t *ext_data;
		size_t ext_datalen;

		if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
			|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
			error_print();
			return -1;
		}
		format_print(fp, fmt, ind, "%s (%d)\n", tls_extension_name(ext_type), ext_type);

		switch (ext_type) {
		case TLS_extension_supported_groups:
			tls_supported_groups_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_early_data:
			tls13_early_data_print(fp, fmt, ind + 4, ext_data, ext_datalen);
			break;
		case TLS_extension_client_certificate_type:
		case TLS_extension_server_certificate_type:
		case TLS_extension_server_name:
		case TLS_extension_max_fragment_length:
		case TLS_extension_use_srtp:
		case TLS_extension_heartbeat:
		case TLS_extension_application_layer_protocol_negotiation:
		case TLS_extension_record_size_limit:
			format_bytes(fp, fmt, ind + 4, "data", ext_data, ext_datalen);
			break;
		default:
			format_bytes(fp, fmt, ind + 4, "data", ext_data, ext_datalen);
			error_print();
		}
	}
	if (dlen) {
		error_print();
		return -1;
	}
	return 1;
}

/*
Certificate

Certificate {
	opaque certificate_request_context<0..2^8-1>;
	CertificateEntry certificate_list<0..2^24-1>;
}

CertificateEntry {
	opaque cert_data<1..2^24-1>;
	Extension extensions<0..2^16-1>;
}
*/
int tls13_certificate_entry_to_bytes(const uint8_t *cert, size_t certlen,
	const uint8_t *status_request_ocsp_response, size_t status_request_ocsp_response_len,
	const uint8_t *signed_certificate_timestamp, size_t signed_certificate_timestamp_len,
	uint8_t **out, size_t *outlen)
{
	size_t extslen = 0;

	if (status_request_ocsp_response && status_request_ocsp_response_len) {
		tls_server_status_request_ext_to_bytes(status_request_ocsp_response, status_request_ocsp_response_len, NULL, &extslen);
	}
	if (signed_certificate_timestamp && signed_certificate_timestamp_len) {
		tls_signed_certificate_timestamp_ext_to_bytes(signed_certificate_timestamp, signed_certificate_timestamp_len, NULL, &extslen);
	}

	tls_uint24array_to_bytes(cert, certlen, out, outlen);
	tls_uint16_to_bytes((uint16_t)extslen, out, outlen);
	if (status_request_ocsp_response && status_request_ocsp_response_len) {
		tls_server_status_request_ext_to_bytes(status_request_ocsp_response, status_request_ocsp_response_len, out, outlen);
	}
	if (signed_certificate_timestamp && signed_certificate_timestamp_len) {
		tls_signed_certificate_timestamp_ext_to_bytes(signed_certificate_timestamp, signed_certificate_timestamp_len, out, outlen);
	}
	return 1;
}

int tls13_certificate_entry_from_bytes(const uint8_t **cert, size_t *certlen,
	const uint8_t **status_request_ocsp_response, size_t *status_request_ocsp_response_len,
	const uint8_t **signed_certificate_timestamp, size_t *signed_certificate_timestamp_len,
	const uint8_t **in, size_t *inlen)
{
	const uint8_t *exts;
	size_t extslen;

	if (!cert || !certlen
		|| !status_request_ocsp_response || !status_request_ocsp_response_len
		|| !signed_certificate_timestamp || !signed_certificate_timestamp_len
		|| !in || !(*in) || !inlen) {
		error_print();
		return -1;
	}
	if (tls_uint24array_from_bytes(cert, certlen, in, inlen) != 1
		|| tls_uint16array_from_bytes(&exts, &extslen, in, inlen) != 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();
			return -1;
		}

		switch (ext_type) {
		case TLS_extension_status_request:
			*status_request_ocsp_response = ext_data;
			*status_request_ocsp_response_len = ext_datalen;
			break;
		case TLS_extension_signed_certificate_timestamp:
			*signed_certificate_timestamp = ext_data;
			*signed_certificate_timestamp_len = ext_datalen;
			break;
		default:
			error_print();
			return -1;
		}
	}
	return 1;
}

int tls13_certificate_list_to_bytes(const uint8_t *certs, size_t certslen,
	uint8_t **out, size_t *outlen)
{
	uint8_t *p = NULL;
	size_t cert_list_len = 0;

	if (out && *out) {
		p = (*out) + tls_uint24_size();
	}
	while (certslen) {
		const uint8_t *cert;
		size_t certlen;
		const uint8_t *entry_exts = NULL;
		size_t entry_exts_len = 0;

		if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1) {
			error_print();
			return -1;
		}
		tls_uint24array_to_bytes(cert, certlen, &p, &cert_list_len);
		tls_uint16array_to_bytes(entry_exts, entry_exts_len, &p, &cert_list_len);

	}
	tls_uint24array_to_bytes(NULL, cert_list_len, out, outlen);
	return 1;
}

int tls13_process_certificate_list(const uint8_t *cert_list, size_t cert_list_len,
	uint8_t *certs, size_t *certs_len)
{
	*certs_len = 0;

	while (cert_list_len) {
		const uint8_t *cert_data;
		size_t cert_data_len;
		const uint8_t *exts;
		size_t exts_len;
		const uint8_t *cert;
		size_t cert_len;

		if (tls_uint24array_from_bytes(&cert_data, &cert_data_len, &cert_list, &cert_list_len) != 1
			|| tls_uint16array_from_bytes(&exts, &exts_len, &cert_list, &cert_list_len) != 1) {
			error_print();
			return -1;
		}
		if (x509_cert_from_der(&cert, &cert_len, &cert_data, &cert_data_len) != 1
			|| asn1_length_is_zero(cert_data_len) != 1
			|| x509_cert_to_der(cert, cert_len, &certs, certs_len) != 1) {
			error_print();
			return -1;
		}

		while (exts_len) {
			int ext_type;
			const uint8_t *ext_data;
			size_t ext_data_len;

			if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_data_len, &exts, &exts_len) != 1) {
				error_print();
				return -1;
			}
			switch (ext_type) {
			case TLS_extension_status_request:
			case TLS_extension_signed_certificate_timestamp:
				error_print();
				return -1;
			default:
				error_print();
				return -1;
			}
		}
	}
	return 1;
}

int tls13_record_set_handshake_certificate(uint8_t *record, size_t *recordlen,
	const uint8_t *request_context, size_t request_context_len,
	const uint8_t *certs, size_t certslen,
	const uint8_t *entity_status_request_ocsp_response, size_t entity_status_request_ocsp_response_len,
	const uint8_t *entity_signed_certificate_timestamp, size_t entity_signed_certificate_timestamp_len)
{
	int type = TLS_handshake_certificate;
	uint8_t *data;
	size_t datalen = 0;
	uint8_t *cert_list;
	size_t cert_list_len = 0;
	const uint8_t *cert;
	size_t certlen;
	size_t len;

	if (!record || !recordlen) {
		error_print();
		return -1;
	}

	data = tls_handshake_data(tls_record_data(record));

	// certificate_request_context<0..2^8-1>
	tls_uint8array_to_bytes(request_context, request_context_len, &data, &datalen);

	// certificate_list<0..2^24-1>
	cert_list = data;
	tls_uint24_to_bytes(0, &data, &len);

	// client might send null certificate_list
	if (certs && certslen) {
		// first (entity) cert entry
		if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1) {
			error_print();
			return -1;
		}
		if (tls13_certificate_entry_to_bytes(cert, certlen,
			entity_status_request_ocsp_response, entity_status_request_ocsp_response_len,
			entity_signed_certificate_timestamp, entity_signed_certificate_timestamp_len,
			&data, &cert_list_len) != 1) {
			error_print();
			return -1;
		}
		// ca certs entries
		while (certslen) {
			if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1) {
				error_print();
				return -1;
			}
			if (tls13_certificate_entry_to_bytes(cert, certlen, NULL, 0, NULL, 0, &data, &cert_list_len) != 1) {
				error_print();
				return -1;
			}
		}
	}
	tls_uint24array_to_bytes(NULL, cert_list_len, &cert_list, &datalen);
	if (tls_record_set_handshake(record, recordlen, type, NULL, datalen) != 1) {
		error_print();
		return -1;
	}
	return 1;
}

// even if status_request, signed_certificate_timestamp not requested
// server/client can still return certificate with these two extensions
int tls13_record_get_handshake_certificate(const uint8_t *record,
	const uint8_t **request_context, size_t *request_context_len,
	uint8_t *cert_chain, size_t *cert_chain_len, size_t cert_chain_maxlen,
	const uint8_t **entity_status_request_ocsp_response, size_t *entity_status_request_ocsp_response_len,
	const uint8_t **entity_signed_certificate_timestamp, size_t *entity_signed_certificate_timestamp_len)
{
	int type;
	const uint8_t *p;
	size_t len;
	const uint8_t *cert_list;
	size_t cert_list_len;
	const uint8_t *cert;
	size_t certlen;


	if (tls_record_get_handshake(record, &type, &p, &len) != 1) {
		error_print();
		return -1;
	}
	if (type != TLS_handshake_certificate) {
		error_print();
		return -1;
	}
	if (tls_uint8array_from_bytes(request_context, request_context_len, &p, &len) != 1
		|| tls_uint24array_from_bytes(&cert_list, &cert_list_len, &p, &len) != 1
		|| tls_length_is_zero(len) != 1) {
		error_print();
		return -1;
	}
	if (cert_list_len > cert_chain_maxlen) {
		error_print();
		return -1;
	}

	// client Certificate.certificate_list might be empty/null
	if (!cert_list) {
		*cert_chain_len = 0;
		*entity_status_request_ocsp_response = NULL;
		*entity_status_request_ocsp_response_len = 0;
		*entity_signed_certificate_timestamp = NULL;
		*entity_signed_certificate_timestamp_len = 0;
		return 1;
	}

	if (tls13_certificate_entry_from_bytes(&cert, &certlen,
		entity_status_request_ocsp_response, entity_status_request_ocsp_response_len,
		entity_signed_certificate_timestamp, entity_signed_certificate_timestamp_len,
		&cert_list, &cert_list_len) != 1) {
		error_print();
		return -1;
	}

	*cert_chain_len = 0;

	x509_cert_to_der(cert, certlen, &cert_chain, cert_chain_len);

	while (cert_list_len) {
		const uint8_t *status_request_ocsp_response;
		size_t status_request_ocsp_response_len;
		const uint8_t *signed_certificate_timestamp;
		size_t signed_certificate_timestamp_len;

		if (tls13_certificate_entry_from_bytes(&cert, &certlen,
			&status_request_ocsp_response, &status_request_ocsp_response_len,
			&signed_certificate_timestamp, &signed_certificate_timestamp_len,
			&cert_list, &cert_list_len) != 1) {
			error_print();
			return -1;
		}
			// 这里的解析可能是有问题的				

		x509_cert_to_der(cert, certlen, &cert_chain, cert_chain_len);
	}

	return 1;
}

int tls13_certificate_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
	const uint8_t *req_context;
	size_t req_context_len;
	const uint8_t *cert_list;
	size_t cert_list_len;

	format_print(fp, fmt, ind, "Certificate\n");
	ind += 4;

	if (tls_uint8array_from_bytes(&req_context, &req_context_len, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	format_bytes(fp, fmt, ind, "certificate_request_context", req_context, req_context_len);

	format_print(fp, fmt, ind, "certificate_list\n");
	ind += 4;
	if (tls_uint24array_from_bytes(&cert_list, &cert_list_len, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	while (cert_list_len) {
		const uint8_t *cert_data;
		size_t cert_data_len;
		const uint8_t *exts;
		size_t extslen;

		format_print(fp, fmt, ind, "CertificateEntry\n");
		if (tls_uint24array_from_bytes(&cert_data, &cert_data_len, &cert_list, &cert_list_len) != 1
			|| tls_uint16array_from_bytes(&exts, &extslen, &cert_list, &cert_list_len) != 1) {
			error_print();
			return -1;
		}
		if (!cert_data_len) {
			error_print();
			return -1;
		}
		x509_cert_print(fp, fmt, ind + 4, "Certificate", cert_data, cert_data_len);
		x509_cert_to_pem(cert_data, cert_data_len, fp);

		if (extslen)
			format_print(fp, fmt, ind + 4, "extensions\n");
		else	format_print(fp, fmt, ind + 4, "extensions: (null)\n");

		while (extslen) {
			uint16_t ext_type;
			const uint8_t *ext_data;
			size_t ext_datalen;

			if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
				|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
				error_print();
				return -1;
			}
			format_print(fp, fmt, ind, "%s (%d)\n", tls_extension_name(ext_type), ext_type);
			ind += 4;

			switch (ext_type) {
			case TLS_extension_status_request:
				tls_server_status_request_print(fp, fmt, ind + 4, ext_data, ext_datalen);
				break;
			case TLS_extension_signed_certificate_timestamp:
				tls_signed_certificate_timestamp_print(fp, fmt, ind + 4, ext_data, ext_datalen);
				break;
			case TLS_extension_server_certificate_type:
			case TLS_extension_client_certificate_type:
				format_bytes(fp, fmt, ind, "data", ext_data, ext_datalen);
				break;
			default:
				format_bytes(fp, fmt, ind, "data", ext_data, ext_datalen);
				error_print();
				//return -1;
			}
		}
	}
	if (dlen) {
		error_print();
		return -1;
	}
	return 1;
}

/*
CertificateRequest

struct {
	opaque certificate_request_context<0..2^8-1>;
	Extension extensions<2..2^16-1>;
} CertificateRequest;
*/
int tls13_record_set_handshake_certificate_request(uint8_t *record, size_t *recordlen,
	const uint8_t *request_context, size_t request_context_len,
	const uint8_t *exts, size_t extslen)
{
	int type = TLS_handshake_certificate_request;
	uint8_t *data;
	size_t datalen = 0;

	if (!record || !recordlen) {
		error_print();
		return -1;
	}
	if (!exts || !extslen) {
		// signature_algorithms extension must exist
		error_print();
		return -1;
	}

	data = tls_handshake_data(tls_record_data(record));
	tls_uint8array_to_bytes(request_context, request_context_len, &data, &datalen);
	tls_uint16array_to_bytes(exts, extslen, &data, &datalen);
	tls_record_set_handshake(record, recordlen, type, NULL, datalen);
	return 1;
}

int tls13_record_get_handshake_certificate_request(const uint8_t *record,
	const uint8_t **requst_context, size_t *request_context_len,
	const uint8_t **exts, size_t *exts_len)
{
	int type;
	const uint8_t *p;
	size_t len;

	if (tls_record_get_handshake(record, &type, &p, &len) != 1) {
		error_print();
		return -1;
	}
	if (type != TLS_handshake_certificate_request) {
		error_print();
		return -1;
	}
	if (tls_uint8array_from_bytes(requst_context, request_context_len, &p, &len) != 1
		|| tls_uint16array_from_bytes(exts, exts_len, &p, &len) != 1
		|| tls_length_is_zero(len) != 1) {
		error_print();
		return -1;
	}
	if (!exts) {
		// signature_algorithms extension must exist
		error_print();
		return -1;
	}
	return 1;
}

int tls13_certificate_request_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
	const uint8_t *req_context;
	size_t req_context_len;
	const uint8_t *exts;
	size_t extslen;

	format_print(fp, fmt, ind, "CertificateRequest\n");
	ind += 4;

	if (tls_uint8array_from_bytes(&req_context, &req_context_len, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	format_bytes(fp, fmt, ind, "certificate_request_context", req_context, req_context_len);

	format_print(fp, fmt, ind, "extensions\n");
	ind += 4;
	if (tls_uint16array_from_bytes(&exts, &extslen, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	while (extslen) {
		uint16_t ext_type;
		const uint8_t *ext_data;
		size_t ext_datalen;

		if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
			|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
			error_print();
			return -1;
		}
		switch (ext_type) {
		case TLS_extension_signature_algorithms:
			tls_signature_algorithms_print(fp, fmt, ind, ext_data, ext_datalen);
			break;
		case TLS_extension_certificate_authorities:
			tls13_certificate_authorities_print(fp, fmt, ind, ext_data, ext_datalen);
			break;
		case TLS_extension_status_request:
			//tls13_status_request_print(fp, fmt, ind, ext_data, ext_datalen);				
			break;
		case TLS_extension_signature_algorithms_cert:
			tls_signature_algorithms_print(fp, fmt, ind, ext_data, ext_datalen);
			break;
		case TLS_extension_client_certificate_type:
			//tls13_client_certificate_type_print(fp, fmt, ind, ext_data, ext_datalen);			
			break;
		default:
			error_print();
			return -1;
		}
	}
	if (dlen) {
		error_print();
		return -1;
	}
	return 1;
}

/*
CertificateVerify

struct {
	SignatureScheme algorithm;
	opaque signature<0..2^16-1>;
} CertificateVerify;
*/

int tls13_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 = record + 5 + 4; // 这里都应该改为tls_record_handshake_data			
	size_t len = 0;

	if (!tls_signature_scheme_name(sig_alg)) {
		error_print();
		return -1;
	}
	tls_uint16_to_bytes((uint16_t)sig_alg, &p, &len);
	tls_uint16array_to_bytes(sig, siglen, &p, &len);
	if (tls_record_set_handshake_header(record, recordlen, type, len) != 1) {
		error_print();
		return -1;
	}
	return 1;
}

int tls13_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 (tls_record_get_handshake(record, &type, &cp, &len) != 1) {
		error_print();
		return -1;
	}
	if (type != TLS_handshake_certificate_verify) {
		return 0;
	}
	if (tls_uint16_from_bytes(&alg, &cp, &len) != 1
		|| tls_uint16array_from_bytes(sig, siglen, &cp, &len) != 1) {
		error_print();
		return -1;
	}
	if (!tls_signature_scheme_name(alg)) {
		error_print();
		return -1;
	}
	*sig_alg = alg;
	return 1;
}

int tls13_certificate_verify_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
	uint16_t sig_alg;
	const uint8_t *sig;
	size_t siglen;

	format_print(fp, fmt, ind, "CertificateVerify\n");
	ind += 4;

	if (tls_uint16_from_bytes(&sig_alg, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	format_print(fp, fmt, ind, "algorithm: %s (%04x)\n", tls_signature_scheme_name(sig_alg), sig_alg);
	if (tls_uint16array_from_bytes(&sig, &siglen, &d, &dlen) != 1) {
		error_print();
		return -1;
	}
	format_bytes(fp, fmt, ind, "signature", sig, siglen);
	if (tls_length_is_zero(dlen) != 1) {
		error_print();
		return -1;
	}
	return 1;
}

/*
Finished

struct {
	opaque verify_data[Hash.length];
} Finished;
*/

int tls13_record_set_handshake_finished(uint8_t *record, size_t *recordlen,
	const uint8_t *verify_data, size_t verify_data_len)
{
	int type = TLS_handshake_finished;

	if (!verify_data || !verify_data_len) {
		error_print();
		return -1;
	}
	if (verify_data_len != 32) {
		error_print();
		return -1;
	}
	if (tls_record_set_handshake(record, recordlen, type, verify_data, verify_data_len) != 1) {
		error_print();
		return -1;
	}
	return 1;
}

int tls13_record_get_handshake_finished(const uint8_t *record,
	const uint8_t **verify_data, size_t *verify_data_len)
{
	int type;

	if (tls_record_get_handshake(record, &type, verify_data, verify_data_len) != 1) {
		error_print();
		return -1;
	}
	if (type != TLS_handshake_finished) {
		return 0;
	}
	if (*verify_data_len == 0) {
		error_print();
		return -1;
	}
	return 1;
}

int tls13_finished_print(FILE *fp, int fmt, int ind, const uint8_t *data, size_t datalen)
{
	format_print(fp, fmt, ind, "Finished\n");
	ind += 4;
	format_bytes(fp, fmt, ind, "verify_data", data, datalen);
	return 1;
}

/*
KeyUpdate

struct {
	KeyUpdateRequest request_update;
} KeyUpdate;

enum {
	update_not_requested(0), update_requested(1), (255)
} KeyUpdateRequest;
*/

int tls13_record_set_handshake_key_update(uint8_t *record, size_t *recordlen,
	int req_update)
{
	int type = TLS_handshake_key_update;
	uint8_t request_update;

	request_update = req_update ? 1 : 0;
	if (tls_record_set_handshake(record, recordlen, type, &request_update, sizeof(request_update)) != 1) {
		error_print();
		return -1;
	}
	return 1;
}

int tls13_record_get_handshake_key_update(uint8_t *record, int *request_update)
{
	int type;
	const uint8_t *cp;
	size_t len;

	if (tls_record_get_handshake(record, &type, &cp, &len) != 1) {
		error_print();
		return -1;
	}
	if (type != TLS_handshake_key_update) {
		return 0;
	}

	if (len != 1) {
		error_print();
		return -1;
	}
	switch (cp[0]) {
	case 0:
		*request_update = 0;
		break;
	case 1:
		*request_update = 1;
		break;
	default:
		error_print();
		return -1;
	}
	return 1;
}

int tls13_key_update_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
	uint8_t update_requested;

	if (tls_uint8_from_bytes(&update_requested, &d, &dlen) != 1
		|| tls_length_is_zero(dlen) != 1) {
		error_print();
		return -1;
	}
	switch (update_requested) {
	case 0:
	case 1:
		break;
	default:
		error_print();
		return -1;
	}
	format_print(fp, fmt, ind, "request_update: %d\n", update_requested);
	return 1;
}

int tls13_ctx_enable_key_update(TLS_CTX *ctx, int enable)
{
	if (!ctx) {
		error_print();
		return -1;
	}
	ctx->key_update = enable ? 1 : 0;
	ctx->key_update_seq_num_limit = TLS13_DEFAULT_KEY_UPDATE_SEQ_NUM_LIMIT;
	return 1;
}

int tls13_ctx_set_key_update_seq_num_limit(TLS_CTX *ctx, size_t max_seq_num)
{
	if (!ctx || !max_seq_num) {
		error_print();
		return -1;
	}
	if (!ctx->key_update) {
		error_print();
		return -1;
	}
	ctx->key_update_seq_num_limit = max_seq_num;
	return 1;
}

// ChangeCipherSpec

int tls13_ctx_set_change_cipher_spec_compat(TLS_CTX *ctx, int enable)
{
	if (!ctx) {
		error_print();
		return -1;
	}
	ctx->change_cipher_spec_compat = enable ? 1 : 0;
	ctx->change_cipher_spec = ctx->change_cipher_spec_compat;
	return 1;
}

int tls13_ctx_set_accept_change_cipher_spec(TLS_CTX *ctx, int enable)
{
	if (!ctx) {
		error_print();
		return -1;
	}
	ctx->accept_change_cipher_spec = enable ? 1 : 0;
	return 1;
}

int tls13_ctx_enable_change_cipher_spec(TLS_CTX *ctx, int enable)
{
	return tls13_ctx_set_change_cipher_spec_compat(ctx, enable);
}

static int tls13_ctx_change_cipher_spec_compat(const TLS_CTX *ctx)
{
	if (!ctx) {
		return 0;
	}
	return ctx->change_cipher_spec_compat || ctx->change_cipher_spec;
}

static int tls13_ctx_accept_change_cipher_spec(const TLS_CTX *ctx)
{
	if (!ctx) {
		return 0;
	}
	return ctx->accept_change_cipher_spec;
}

static int tls13_recv_change_cipher_spec_if_present(TLS_CONNECT *conn)
{
	int ret;

	if ((ret = tls_recv_record(conn)) != 1) {
		if (ret != TLS_ERROR_RECV_AGAIN) {
			error_print();
		}
		return ret;
	}

	if (tls_record_type(conn->record) != TLS_record_change_cipher_spec) {
		if(conn->verbose) tls_trace("recv [ChangeCipherSpec*]\n    no [ChangeCipherSpec]\n\n");
		return 0;
	}
	if(conn->verbose) tls_trace("recv [ChangeCipherSpec*]\n");
	if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);

	if (tls_record_get_change_cipher_spec(conn->record) != 1) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	}

	return 1;
}



int tls13_handshake_print(FILE *fp, int fmt, int ind, const uint8_t *handshake, size_t handshake_len)
{
	const uint8_t *p = handshake;
	size_t len = handshake_len;
	uint8_t type;
	const uint8_t *data;
	size_t datalen;

	if (tls_uint8_from_bytes(&type, &handshake, &handshake_len) != 1
		|| tls_uint24array_from_bytes(&data, &datalen, &handshake, &handshake_len) != 1
		|| tls_length_is_zero(handshake_len) != 1) {
		error_print();
		return -1;
	}
	format_print(fp, fmt, ind, "Handshake\n");
	ind += 4;
	format_print(fp, fmt, ind, "Type: %s (%d)\n", tls_handshake_type_name(type), type);
	format_print(fp, fmt, ind, "Length: %zu\n", datalen);

	switch (type) {
	case TLS_handshake_client_hello:
		tls13_client_hello_print(fp, fmt, ind, data, datalen);
		break;
	case TLS_handshake_server_hello:
		tls13_server_hello_print(fp, fmt, ind, data, datalen);
		break;
	case TLS_handshake_hello_retry_request:
		tls13_hello_retry_request_print(fp, fmt, ind, data, datalen);
		break;
	case TLS_handshake_new_session_ticket:
		tls13_new_session_ticket_print(fp, fmt, ind, data, datalen);
		break;
	case TLS_handshake_end_of_early_data:
		tls13_end_of_early_data_print(fp, fmt, ind, data, datalen);
		break;
	case TLS_handshake_encrypted_extensions:
		tls13_encrypted_extensions_print(fp, fmt, ind, data, datalen);
		break;
	case TLS_handshake_certificate:
		tls13_certificate_print(fp, fmt, ind, data, datalen);
		break;
	case TLS_handshake_certificate_request:
		tls13_certificate_request_print(fp, fmt, ind, data, datalen);
		break;
	case TLS_handshake_certificate_verify:
		tls13_certificate_verify_print(fp, fmt, ind, data, datalen);
		break;
	case TLS_handshake_finished:
		tls13_finished_print(fp, fmt, ind, data, datalen);
		break;
	case TLS_handshake_key_update:
		tls13_key_update_print(fp, fmt, ind, data, datalen);
		break;
	default:
		error_print();
		return -1;
	}
	return 1;
}

int tls13_record_print(FILE *fp, int fmt, int ind, const uint8_t *record, size_t recordlen)
{
	const uint8_t *data;
	size_t datalen;
	int protocol;

	fmt |= TLS_cipher_sm4_gcm_sm3 << 8;

	if (!fp || !record || recordlen < 5) {
		error_print();
		return -1;
	}
	protocol = tls_record_protocol(record);
	format_print(fp, fmt, ind, "Record\n"); ind += 4;
	format_print(fp, fmt, ind, "ContentType: %s (%d)\n", tls_record_type_name(record[0]), record[0]);
	format_print(fp, fmt, ind, "Version: %s (%04x)\n", tls_protocol_name(protocol), protocol);
	format_print(fp, fmt, ind, "Length: %d\n", tls_record_data_length(record));

	data = tls_record_data(record);
	datalen = tls_record_data_length(record);

	if (recordlen < tls_record_length(record)) {
		error_print();
		return -1;
	}

	//format_bytes(fp, fmt, ind, "RecordRawData", data, datalen);

	switch (record[0]) {
	case TLS_record_handshake:
		tls13_handshake_print(fp, fmt, ind, data, datalen);
		break;

	case TLS_record_alert:
		if (tls_alert_print(fp, data, datalen, fmt, ind) != 1) {
			error_print();
			return -1;
		}
		break;
	case TLS_record_change_cipher_spec:
		if (tls_change_cipher_spec_print(fp, data, datalen, fmt, ind) != 1) {
			error_print();
			return -1;
		}
		break;
	case TLS_record_application_data:
		if (tls_application_data_print(fp, data, datalen, fmt, ind) != 1) {
			error_print();
			return -1;
		}
		break;
	default:
		error_print();
		return -1;
	}

	recordlen -= tls_record_length(record);
	if (recordlen) {
		format_print(fp, 0, 0, "DataLeftInRecord: %zu\n", recordlen);
	}

	fprintf(fp, "\n");
	return 1;
}




/*
       Client                                           Server

Key  ^ ClientHello
Exch | + key_share*
     | + signature_algorithms*
     | + psk_key_exchange_modes*
     v + pre_shared_key*       -------->
                                                  ServerHello  ^ Key
                                                 + key_share*  | Exch
                                            + pre_shared_key*  v


	| ecdhe => handshake_secret			|
	| handshake_secret => master_secret		|
	| handshake_secret, client_hello, server_hello	|
	|	=> client_handshake_traffic_secret	|
	| => server_handshake_traffic_secret		|


                                        {EncryptedExtensions}  ^  Server
                                        {CertificateRequest*}  v  Params
                                                {Certificate}  ^
                                          {CertificateVerify}  | Auth
                                                   {Finished}  v

	+ master_secret, ClientHello .. server Finished
		=> server_application_traffic_secret_0

                               <--------  [Application Data*]

     ^ {Certificate*}
Auth | {CertificateVerify*}
     v {Finished}              -------->


	+ master_secret, ClientHello .. server Finished
		=> client_application_traffic_secret_0

       [Application Data]      <------->  [Application Data]




*/



int tls13_init(TLS_CONNECT *conn, TLS_CTX *ctx)
{
	if (!ctx->supported_versions_cnt) {
		error_print();
		return -1;
	}

	if (!ctx->cipher_suites_cnt) {
		error_print();
		return -1;
	}


	memset(conn, 0, sizeof(*conn));

	conn->ctx = ctx;

	conn->is_client = ctx->is_client;
	conn->verbose = ctx->verbose;

	conn->protocol = ctx->protocol;


	conn->new_session_ticket = ctx->new_session_ticket;


	/*
	extensions depends on key_exchange_modes


	switch (key_exchange_mode)
	case CERT_DHE:
		* supported_groups		ctx->supported_groups_cnt != 0
		* signature_algorithms		ctx->signature_algorithms_cnt != 0
		* key_share			generated in ClientHello, so always ok
		* [signature_algorithms_cert]
		* [certificate_authorities]

	case PSK_DHE:
		* supported_groups
		* psk_key_exchange_modes	ctx->psk_key_exchange_modes has psk_dhe_ke
		* pre_shared_key		call tls13_add_pre_shared_key, tls13_add_pre_shared_key_from_session_file after tls13_init
		* key_share
		* [early_data]
		* [signature_algorithms]
		* [signature_algorithms_cert]

	case PSK:
		* psk_key_exchange_modes	ctx->psk_key_exchange_modes has psk_ke
		* pre_shared_key
		* [early_data]
		* [supported_groups]
		* [signature_algorithms]
		* [signature_algorithms_cert]
	*/

	// key_exchange_modes
	conn->key_exchange_modes = ctx->psk_key_exchange_modes;
	if (ctx->supported_groups_cnt && ctx->signature_algorithms_cnt) {
		conn->key_exchange_modes |= TLS_KE_CERT_DHE;
	}
	if (!ctx->supported_groups_cnt) {
		conn->key_exchange_modes &= ~(TLS_KE_CERT_DHE|TLS_KE_PSK_DHE);
	}


	if (!conn->key_exchange_modes) {
		error_print();
		return -1;
	}

	// TLS_KE_PSK_DHE|TLS_KE_PSK depends on pre_shared_key
	// but pre_shared_key is set by tls13_add_pre_shared_key, tls13_add_pre_shared_key_from_session_file
	// after tls13_init

	// key_share
	if (conn->key_exchange_modes & (TLS_KE_CERT_DHE|TLS_KE_PSK_DHE)) {
		conn->key_share = 1;
	}

	conn->signed_certificate_timestamp = ctx->signed_certificate_timestamp;

	// early_data
	conn->early_data = ctx->early_data;
	conn->max_early_data_size = ctx->max_early_data_size;


	// CertificateRequest
	if (!ctx->is_client) {
		conn->certificate_request = ctx->certificate_request;
	}


	return 1;
}

int tls13_send_client_hello(TLS_CONNECT *conn)
{
	int ret;

	if (!conn->recordlen) {
		const uint8_t *legacy_session_id = NULL;
		size_t legacy_session_id_len = 0;
		uint8_t exts[TLS_MAX_EXTENSIONS_SIZE];
		uint8_t *pexts = exts;
		size_t extslen = 0;

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

		// record_version
		tls_record_set_protocol(conn->record, TLS_protocol_tls1);

		// client_random
		if (tls13_random_generate(conn->client_random) != 1) {
			error_print();
			return -1;
		}

		// legacy_session_id
		conn->session_id_len = 0;


		// exts in CH (RFC 8446 page 37), only oid_filter not in CH
		//  * supported_versions
		//  * signature_algorithms
		//  * signature_algorithms_cert
		//  * certificate_authorities
		//  * server_name
		//  * status_request
		//  * signed_certificate_timestamp
		//  * supported_groups
		//  * key_share
		//  * psk_key_exchange_modes
		//  * pre_shared_key
		//  * early_data (only in ClientHello1)
		//  * cookie (only in ClientHello2)
		//  * post_handshake_auth: client support post handshake auth
		//  * max_fragment_length
		//  * use_srtp
		//  * heartbeat
		//  * application_layer_protocol_negotiation
		//  * server_certificate_type: if client accept raw/x509
		//  * client_certificate_type: if client sned raw/x509
		//  * padding


		// supported_versions
		if (tls13_client_supported_versions_ext_to_bytes(conn->ctx->supported_versions,
			conn->ctx->supported_versions_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;
			}
		}

		// signature_algorithms_cert
		if (conn->signature_algorithms_cert) {
			if (tls13_signature_algorithms_cert_ext_to_bytes(conn->ctx->signature_algorithms,
				conn->ctx->signature_algorithms_cnt, &pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		// certificate_authorities
		if (conn->certificate_authorities) {
			if (tls13_certificate_authorities_ext_to_bytes(
				conn->ctx->ca_names, conn->ctx->ca_names_len, &pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		// key_share
		if (conn->key_share) {
			size_t i;

			// empty ClientHello.key_share is allowed
			for (i = 0; i < conn->ctx->key_exchanges_cnt && i < conn->ctx->supported_groups_cnt; i++) {
				int curve_oid = tls_named_curve_oid(conn->ctx->supported_groups[i]);
				if (x509_key_generate(&conn->key_exchanges[i],
					OID_ec_public_key, &curve_oid, sizeof(curve_oid)) != 1) {
					error_print();
					tls13_send_alert(conn, TLS_alert_internal_error);
					return -1;
				}
			}
			conn->key_exchanges_cnt = i;
			if (tls13_key_share_client_hello_ext_to_bytes(conn->key_exchanges,
				conn->key_exchanges_cnt, &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;
			}
		}

		// application_layer_protocol_negotiation
		if (conn->ctx->alpn_protocols_cnt) {
			if (tls_application_layer_protocol_negotiation_ext_to_bytes(
				conn->ctx->alpn_protocols, conn->ctx->alpn_protocols_cnt,
				&pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		// psk_key_exchange_modes
		if (conn->key_exchange_modes & (TLS_KE_PSK_DHE|TLS_KE_PSK)) {
			if (tls13_psk_key_exchange_modes_ext_to_bytes(
				conn->key_exchange_modes, &pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		// status_request (hint only)
		if (conn->status_request) {
			if (tls_client_status_request_ext_to_bytes(TLS_certificate_status_type_ocsp,
				conn->status_request_responder_id_list, conn->status_request_responder_id_list_len,
				conn->status_request_exts, conn->status_request_exts_len,
				&pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
			conn->status_request = 0; // to track CertificateRequest.status_request
		}

		// signed_certificate_timestamp (hint only)
		if (conn->signed_certificate_timestamp) {
			if (tls_ext_to_bytes(TLS_extension_signed_certificate_timestamp, NULL, 0,
				&pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
			conn->signed_certificate_timestamp = 0; // to track CertificateRequest.signed_certificate_timestamp
		}

		// early_data
		// 客户端启用early_data是非常特殊的，需要在ClientHello就确定cipher_suite
		// 并且固定采用第一个pre_shared_key			
		if (conn->early_data) {
			if (tls_ext_to_bytes(TLS_extension_early_data, NULL, 0,
				&pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		// post_handshake_auth
		if (conn->post_handshake_auth) {
			if (tls_ext_to_bytes(TLS_extension_post_handshake_auth, NULL, 0,
				&pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		// pre_shared_key (must be the last extension)
		if (conn->pre_shared_key) {
			uint8_t *ptruncated_exts = pexts;
			size_t truncated_extslen = extslen;
			uint8_t binders[256];
			uint8_t *pbinders = binders;
			size_t binderslen = 0;

			if (!conn->psk_identities_len
				|| !conn->psk_keys_len
				|| !conn->psk_cipher_suites_cnt ) {
				error_print();
				return -1;
			}

			// output pre_shared_key ext with empty binders
			if (tls13_psk_binders_generate_empty(
				conn->psk_cipher_suites, conn->psk_cipher_suites_cnt,
				binders, &binderslen) != 1) {
				error_print();
				return -1;
			}
			if (tls13_client_pre_shared_key_ext_to_bytes(
				conn->psk_identities, conn->psk_identities_len,
				binders, binderslen, &ptruncated_exts, &truncated_extslen) != 1) {
				error_print();
				return -1;
			}

			// truncate(ClientHello)
			if (tls_record_set_handshake_client_hello(conn->record, &conn->recordlen,
				TLS_protocol_tls12, conn->client_random,
				legacy_session_id, legacy_session_id_len,
				conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt,
				exts, truncated_extslen) != 1) {
				error_print();
				return -1;
			}
			//tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);

			// generate binders and output final pre_shared_key ext
			if (tls13_psk_binders_generate(
				conn->psk_cipher_suites, conn->psk_cipher_suites_cnt,
				conn->psk_identity_types,
				conn->psk_keys, conn->psk_keys_len,
				conn->record + 5, conn->recordlen - 5 - 2 - binderslen,
				binders, &binderslen) != 1) {
				error_print();
				return -1;
			}
			if (tls13_client_pre_shared_key_ext_to_bytes(
				conn->psk_identities, conn->psk_identities_len,
				binders, binderslen, &pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		if (tls_record_set_handshake_client_hello(conn->record, &conn->recordlen,
			TLS_protocol_tls12, conn->client_random,
			legacy_session_id, legacy_session_id_len,
			conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt,
			exts, extslen) != 1) {
			error_print();
			return -1;
		}
		if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);

		// early_data encryption keys depends on the full client_hello
		if (conn->early_data) {
			if (tls13_generate_early_keys(conn) != 1) {
				error_print();
				return -1;
			}
		}

		// backup client_hello
		// 如果后面发送EarlyData，这个数据有可能被修改
		// 并且如果确定了发送EarlyData，cipher_suite就确定了，不应该再备份了

		// 由于服务器可能拒绝EarlyData，并且不选择第一个PSK
		// 那么可能导致最终的cipher_suite和客户端计算EarlyData不同的值
		// 这就导致客户端必须重新计算ClientHello的digest
		// 因此我们还是保存ClientHello，而不是立即就计算digest

		memcpy(conn->plain_record, conn->record, conn->recordlen);
		conn->plain_recordlen = conn->recordlen;
	}

	if ((ret = tls_send_record(conn)) != 1) {
		if (ret != TLS_ERROR_SEND_AGAIN) {
			error_print();
		}
		return ret;
	}

	tls_clean_record(conn);
	return 1;
}

/*
recv HelloRetryRequest:
	* set conn->protocol
	* set conn->cipher_suite, conn->cipher, conn->digest
	* set conn->key_exchange_group
	* set conn->dgst_ctx <= ClientHello, HelloRetryRequest, ClientHello2

recv ServerHello after HelloRetryRequest:
	* check ServerHello.protocol == conn->protocol
	* check ServerHello.cipher_suite == conn->cipher_suite
	* check ServerHello.key_share.group == conn->key_exchange_group
	* conn->dgst_ctx <= ServerHello

recv ServerHello without HelloRetryRequest:
	* set conn->protocol
	* set conn->cipher_suite, conn->cipher, conn->digest
	* set conn->key_exchange_group
	* set conn->dgst_ctx <= ClientHello
*/

int tls13_recv_hello_retry_request(TLS_CONNECT *conn)
{
	int ret;

	// handshake
	int handshake_type;
	const uint8_t *handshake_data;
	size_t handshake_datalen;

	// HelloRetryRequest
	int legacy_version;
	const uint8_t *random;
	const uint8_t *legacy_session_id_echo;
	size_t legacy_session_id_echo_len;
	int cipher_suite;
	int legacy_compress_meth;
	const uint8_t *exts;
	size_t extslen;

	// extensions
	const uint8_t *supported_versions = NULL;
	size_t supported_versions_len = 0;
	const uint8_t *key_share = NULL;
	size_t key_share_len = 0;
	const uint8_t *cookie = NULL;
	size_t cookie_len = 0;

	int selected_version;
	int key_exchange_group;

	if ((ret = tls_recv_record(conn)) != 1) {
		if (ret != TLS_ERROR_RECV_AGAIN) {

			if(conn->verbose) {
				fprintf(stderr, "tls_recv_record return %d\n", ret);
			}

			error_print();
		}
		return ret;
	}
	if(conn->verbose) tls_trace("recv HelloRetryRequest*\n");

	if (tls_record_protocol(conn->record) != TLS_protocol_tls12) {
		error_print();
		tls13_send_alert(conn, TLS_alert_protocol_version);
		return -1;
	}

	// the record might be Alert?
	if ((ret = tls_record_get_handshake(conn->record,
		&handshake_type, &handshake_data, &handshake_datalen)) < 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	} else if (ret == 0) {
		error_print();
		return -1;
	}
	if (handshake_type != TLS_handshake_hello_retry_request
		&& handshake_type != TLS_handshake_server_hello) {
		if(conn->verbose) tls_trace("    no HelloRetryRequest\n\n");
		return 0;
	}

	if ((ret = tls13_record_get_handshake_hello_retry_request(conn->record,
		&legacy_version, &random,
		&legacy_session_id_echo, &legacy_session_id_echo_len,
		&cipher_suite, &legacy_compress_meth, &exts, &extslen)) != 1) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	}
	if (memcmp(random, TLS13_HELLO_RETRY_REQUEST_RANDOM, 32) != 0) {
		if(conn->verbose) tls_trace("    no HelloRetryRequest\n\n");
		return 0;
	}
	if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
	conn->hello_retry_request = 1;


	// HelloRetryRequest disable early_data
	conn->early_data = 0;


	// legacy_version
	if (legacy_version != TLS_protocol_tls12) {
		error_print();
		tls13_send_alert(conn, TLS_alert_protocol_version);
		return -1;
	}

	// random
	memcpy(conn->server_random, random, 32);

	// legacy_session_id_echo
	if (legacy_session_id_echo_len != conn->session_id_len
		|| memcmp(legacy_session_id_echo, conn->session_id, conn->session_id_len) != 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_illegal_parameter);
		return -1;
	}

	// cipher_suite
	if (tls_type_is_in_list(cipher_suite, conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt) != 1) {
		error_print();
		tls13_send_alert(conn, TLS_alert_illegal_parameter);
		return -1;
	}
	if (tls_cipher_suite_get(cipher_suite, &conn->cipher, &conn->digest) != 1) {
		error_print();
		tls13_send_alert(conn, TLS_alert_internal_error);
		return -1;
	}
	conn->cipher_suite = cipher_suite;

	// legacy_compression_method
	if (legacy_compress_meth != 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_illegal_parameter);
		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();
			tls13_send_alert(conn, TLS_alert_decode_error);
			return -1;
		}

		// exts in HRR
		//  * supported_versions
		//  * key_share
		//  * cookie

		switch (ext_type) {
		case TLS_extension_supported_versions:
		case TLS_extension_key_share:
		case TLS_extension_cookie:
			if (!ext_data) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			break;
		}

		switch (ext_type) {
		case TLS_extension_supported_versions:
			if (supported_versions) {
				error_print();
				return -1;
			}
			supported_versions = ext_data;
			supported_versions_len = ext_datalen;
			break;

		case TLS_extension_key_share:
			if (!conn->key_share) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			if (key_share) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			key_share = ext_data;
			key_share_len = ext_datalen;
			break;

		case TLS_extension_cookie:
			if (cookie) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			cookie = ext_data;
			cookie_len = ext_datalen;
			conn->cookie = 1;
			break;

		default:
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;
		}
	}

	// supported_versions
	if (!supported_versions) {
		error_print();
		tls13_send_alert(conn, TLS_alert_missing_extension);
		return -1;
	}
	if (tls13_server_supported_versions_from_bytes(&selected_version,
		supported_versions, supported_versions_len) != 1) {
		tls13_send_alert(conn, TLS_alert_decode_error);
		error_print();
		return -1;
	}
	if (tls_type_is_in_list(selected_version,
		conn->ctx->supported_versions, conn->ctx->supported_versions_cnt) != 1) {
		error_print();
		tls13_send_alert(conn, TLS_alert_illegal_parameter);
		return -1;
	}
	if (selected_version != TLS_protocol_tls13) {
		error_print();
		tls13_send_alert(conn, TLS_alert_internal_error);
		return -1;
	}
	conn->protocol = selected_version;

	// key_share
	if (!key_share) {
		error_print();
		tls13_send_alert(conn, TLS_alert_missing_extension);
		return -1;
	}
	if (tls13_key_share_hello_retry_request_from_bytes(&key_exchange_group,
		key_share, key_share_len) != 1) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	}
	if (tls_type_is_in_list(key_exchange_group,
		conn->ctx->supported_groups, conn->ctx->supported_groups_cnt) != 1) {
		error_print();
		tls13_send_alert(conn, TLS_alert_illegal_parameter);
		return -1;
	}
	// HelloRetryRequest must choose a group not in ClientHello.key_share
	while (conn->key_exchanges_cnt--) {
		if (key_exchange_group == tls_named_curve_from_oid(
			conn->key_exchanges[conn->key_exchanges_cnt].algor_param)) {
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
		}
	}
	conn->key_exchange_group = key_exchange_group;

	// cookie
	if (cookie) {
		const uint8_t *cookie_data;
		size_t cookie_datalen;

		if (tls13_cookie_from_bytes(&cookie_data, &cookie_datalen,
			cookie, cookie_len) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_decode_error);
			return -1;
		}
		if (cookie_len > sizeof(conn->cookie_buf)) {
			error_print();
			return -1;
		}
		memcpy(conn->cookie_buf, cookie_data, cookie_datalen);
		conn->cookie_len = cookie_datalen;
	}

	// ClientHello1
	uint8_t message_hash[4 + 32];
	size_t dgstlen;
	message_hash[0] = TLS_handshake_message_hash;
	message_hash[1] = 0;
	message_hash[2] = 0;
	message_hash[3] = 32;

	// 我猜如果用了HRR，那么客户端实际上并没有保存ClientHello的数据，而是用ClientHello的哈希值来计算后续的

	if (digest_init(&conn->dgst_ctx, conn->digest) != 1
		|| digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1
		|| digest_finish(&conn->dgst_ctx, message_hash + 4, &dgstlen) != 1) {
		error_print();
		return -1;
	}

	// ClientHello, HelloRetryRequest
	if (digest_init(&conn->dgst_ctx, conn->digest) != 1
		|| digest_update(&conn->dgst_ctx, message_hash, sizeof(message_hash)) != 1
		|| digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) {
		error_print();
		return -1;
	}

	return 1;
}

int tls13_client_hello_again_psk_update(TLS_CONNECT *conn)
{
	const uint8_t *psk_identities;
	const uint8_t *psk_keys;
	uint8_t tmp_identities_buf[sizeof(conn->psk_identities)];
	uint8_t *tmp_identities = tmp_identities_buf;
	size_t tmp_identities_len = 0;
	uint8_t tmp_keys_buf[sizeof(conn->psk_keys)];
	uint8_t *tmp_keys = tmp_keys_buf;
	size_t tmp_keys_len = 0;
	size_t tmp_cipher_suites_cnt = 0;
	size_t i;

	if (!conn) {
		error_print();
		return -1;
	}
	psk_identities = conn->psk_identities;
	psk_keys = conn->psk_keys;

	for (i = 0; i < conn->psk_cipher_suites_cnt; i++) {
		const uint8_t *identity;
		size_t identity_len;
		uint32_t obfuscated_ticket_age;
		const uint8_t *key;
		size_t key_len;

		if (tls13_psk_identity_from_bytes(&identity, &identity_len, &obfuscated_ticket_age, &psk_identities, &conn->psk_identities_len) != 1
			|| tls_uint8array_from_bytes(&key, &key_len, &psk_keys, &conn->psk_keys_len) != 1) {
			gmssl_secure_clear(tmp_keys_buf, sizeof(tmp_keys_buf));
			error_print();
			return -1;
		}
		if (conn->psk_cipher_suites[i] == conn->cipher_suite) {
			tls13_psk_identity_to_bytes(identity, identity_len, obfuscated_ticket_age, &tmp_identities, &tmp_identities_len);
			tls_uint16array_to_bytes(key, key_len, &tmp_keys, &tmp_keys_len);
			tmp_cipher_suites_cnt++;
		}
	}
	if (conn->psk_identities_len || conn->psk_keys_len) {
		gmssl_secure_clear(tmp_keys_buf, sizeof(tmp_keys_buf));
		error_print();
		return -1;
	}

	memcpy(conn->psk_identities, tmp_identities_buf, tmp_identities_len);
	conn->psk_identities_len = tmp_identities_len;
	memcpy(conn->psk_keys, tmp_keys_buf, tmp_keys_len);
	conn->psk_keys_len = tmp_keys_len;
	for (i = 0; i < tmp_cipher_suites_cnt; i++) {
		conn->psk_cipher_suites[i] = conn->cipher_suite;
	}
	conn->psk_cipher_suites_cnt = tmp_cipher_suites_cnt;

	gmssl_secure_clear(tmp_keys_buf, sizeof(tmp_keys_buf));
	return 1;
}

int tls13_send_client_hello_again(TLS_CONNECT *conn)
{
	int ret;
	if(conn->verbose) tls_trace("send ClientHello again\n");

	if (!conn->recordlen) {
		const uint8_t *legacy_session_id = NULL;
		size_t legacy_session_id_len = 0;
		uint8_t exts[TLS_MAX_EXTENSIONS_SIZE];
		uint8_t *pexts = exts;
		size_t extslen = 0;
		int supported_versions = TLS_protocol_tls13;
		int curve_oid;

		// record_version
		tls_record_set_protocol(conn->record, TLS_protocol_tls1);

		// Extensions

		// keep ClientHello extensions except
		//	* key_share - generate a new key_exchange based on conn->key_exchange_group
		//	* pre_shared_key - remove PSKs not compatible with conn->cipher_suite
		//	* early_data - disable early_data
		//	* cookie - echo cookie if exist

		// supported_versions
		if (tls13_client_supported_versions_ext_to_bytes(conn->ctx->supported_versions,
			conn->ctx->supported_versions_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;
			}
		}

		// signature_algorithms_cert
		if (conn->signature_algorithms_cert) {
			if (tls13_signature_algorithms_cert_ext_to_bytes(conn->ctx->signature_algorithms,
				conn->ctx->signature_algorithms_cnt, &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;
			}
		}

		// application_layer_protocol_negotiation
		if (conn->ctx->alpn_protocols_cnt) {
			if (tls_application_layer_protocol_negotiation_ext_to_bytes(
				conn->ctx->alpn_protocols, conn->ctx->alpn_protocols_cnt,
				&pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		// key_share (re-generated)
		if ((curve_oid = tls_named_curve_oid(conn->key_exchange_group)) == OID_undef) {
			error_print();
			return -1;
		}
		if (x509_key_generate(&conn->key_exchanges[0],
			OID_ec_public_key, &curve_oid, sizeof(curve_oid)) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_internal_error);
			return -1;
		}
		conn->key_exchange_idx = 0;
		conn->key_exchanges_cnt = 1;
		if (tls13_key_share_client_hello_ext_to_bytes(conn->key_exchanges,
			conn->key_exchanges_cnt, &pexts, &extslen) != 1) {
			error_print();
			return -1;
		}

		// psk_key_exchange_modes
		if (conn->key_exchange_modes & (TLS_KE_PSK_DHE|TLS_KE_PSK)) {
			if (tls13_psk_key_exchange_modes_ext_to_bytes(conn->key_exchange_modes, &pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}
		// update key_exchange_modes (disable PSK-only)
		conn->key_exchange_modes &= ~TLS_KE_PSK;

		// status_request
		if (conn->status_request) {
			if (tls_client_status_request_ext_to_bytes(TLS_certificate_status_type_ocsp,
				conn->status_request_responder_id_list, conn->status_request_responder_id_list_len,
				conn->status_request_exts, conn->status_request_exts_len,
				&pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		// signed_certificate_timestamp
		if (conn->ctx->signed_certificate_timestamp) {
			if (tls_ext_to_bytes(TLS_extension_signed_certificate_timestamp, NULL, 0, &pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		// post_handshake_auth
		if (conn->post_handshake_auth) {
			if (tls_ext_to_bytes(TLS_extension_post_handshake_auth, NULL, 0,
				&pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		// early_data must not in ClientHello2

		// cookie
		if (conn->cookie) {
			if (tls13_cookie_ext_to_bytes(conn->cookie_buf, conn->cookie_len, &pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		// pre_shared_key
		if (conn->pre_shared_key) {
			if (!conn->psk_identities_len
				|| !conn->psk_keys_len
				|| !conn->psk_cipher_suites_cnt ) {
				error_print();
				return -1;
			}
			if (tls13_client_hello_again_psk_update(conn) != 1) {
				error_print();
				return -1;
			}
			if (!conn->psk_cipher_suites_cnt) {
				conn->pre_shared_key = 0;
			}
		}
		if (conn->pre_shared_key) {
			uint8_t *ptruncated_exts = pexts;
			size_t truncated_extslen = extslen;
			uint8_t binders[256];
			uint8_t *pbinders = binders;
			size_t binderslen = 0;

			// output pre_shared_key ext with empty binders
			if (tls13_psk_binders_generate_empty(
				conn->psk_cipher_suites, conn->psk_cipher_suites_cnt,
				binders, &binderslen) != 1) {
				error_print();
				return -1;
			}
			if (tls13_client_pre_shared_key_ext_to_bytes(
				conn->psk_identities, conn->psk_identities_len,
				binders, binderslen, &ptruncated_exts, &truncated_extslen) != 1) {
				error_print();
				return -1;
			}

			// truncate(ClientHello)
			if (tls_record_set_handshake_client_hello(conn->record, &conn->recordlen,
				TLS_protocol_tls12, conn->client_random,
				legacy_session_id, legacy_session_id_len,
				conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt,
				exts, truncated_extslen) != 1) {
				error_print();
				return -1;
			}
			//tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);

			// generate binders and output final pre_shared_key ext
			if (tls13_psk_binders_generate(
				conn->psk_cipher_suites, conn->psk_cipher_suites_cnt,
				conn->psk_identity_types,
				conn->psk_keys, conn->psk_keys_len,
				conn->record + 5, conn->recordlen - 5 - 2 - binderslen,
				binders, &binderslen) != 1) {
				error_print();
				return -1;
			}
			if (tls13_client_pre_shared_key_ext_to_bytes(
				conn->psk_identities, conn->psk_identities_len,
				binders, binderslen, &pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		if (tls_record_set_handshake_client_hello(conn->record, &conn->recordlen,
			TLS_protocol_tls12, conn->client_random,
			legacy_session_id, legacy_session_id_len,
			conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt,
			exts, extslen) != 1) {
			error_print();
			return -1;
		}
		if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);

		// ClientHello2
		if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 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;
}


/*
recv HelloRetryRequest:
	* set conn->protocol
	* set conn->cipher_suite, conn->cipher, conn->digest
	* set conn->key_exchange_group
	* set conn->dgst_ctx <= ClientHello, HelloRetryRequest, ClientHello2

recv ServerHello after HelloRetryRequest:
	* check ServerHello.protocol == conn->protocol
	* check ServerHello.cipher_suite == conn->cipher_suite
	* check ServerHello.key_share.group == conn->key_exchange_group
	* conn->dgst_ctx <= ServerHello

recv ServerHello without HelloRetryRequest:
	* set conn->protocol
	* set conn->cipher_suite, conn->cipher, conn->digest
	* set conn->key_exchange_group
	* set conn->dgst_ctx <= ClientHello
*/
int tls13_recv_server_hello(TLS_CONNECT *conn)
{
	int ret;

	// server_hello
	int legacy_version;
	const uint8_t *random;
	const uint8_t *legacy_session_id_echo;
	size_t legacy_session_id_echo_len;
	int cipher_suite;
	const uint8_t *exts;
	size_t extslen;

	const uint8_t *supported_versions = NULL;
	size_t supported_versions_len;
	const uint8_t *key_share = NULL;
	size_t key_share_len;
	const uint8_t *pre_shared_key = NULL;
	size_t pre_shared_key_len;

	int selected_version;
	int server_key_exchange_mode = 0;

	if ((ret = tls_recv_record(conn)) != 1) {
		if (ret != TLS_ERROR_RECV_AGAIN) {
			error_print();
		}
		return ret;
	}
	if(conn->verbose) tls_trace("recv ServerHello\n");
	if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);

	if (tls_record_protocol(conn->record) != TLS_protocol_tls12) {
		error_print();
		tls13_send_alert(conn, TLS_alert_protocol_version);
		return -1;
	}
	if ((ret = tls_record_get_handshake_server_hello(conn->record,
		&legacy_version, &random,
		&legacy_session_id_echo, &legacy_session_id_echo_len,
		&cipher_suite, &exts, &extslen)) < 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	} else if (ret == 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_unexpected_message);
		return -1;
	}

	// legacy_version
	if (legacy_version != TLS_protocol_tls12) {
		error_print();
		tls13_send_alert(conn, TLS_alert_protocol_version);
		return -1;
	}

	// random
	if (conn->hello_retry_request) {
		if (memcmp(random, conn->server_random, 32) == 0) {
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;
		}
	}
	memcpy(conn->server_random, random, 32);

	// legacy_session_id_echo
	if (legacy_session_id_echo_len != conn->session_id_len
		|| memcmp(legacy_session_id_echo, conn->session_id, conn->session_id_len) != 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_illegal_parameter);
		return -1;
	}

	// cipher_suite
	if (conn->hello_retry_request) {
		if (cipher_suite != conn->cipher_suite) {
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;
		}
	} else {
		if (tls_type_is_in_list(cipher_suite,
			conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;
		}
		conn->cipher_suite = cipher_suite;
		if (tls_cipher_suite_get(cipher_suite, &conn->cipher, &conn->digest) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_internal_error);
			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();
			tls13_send_alert(conn, TLS_alert_decode_error);
			return -1;
		}

		// exts in SH
		//  * supported_versions
		//  * key_share
		//  * pre_shared_key (not in HRR)
		//
		//
		//	ServerHello.key_share if only ClientHello.key_share
		//	ServerHello.pre_shared_key if only ClientHello.pre_shared_key
		//	if HelloRetryRequest, key_share must exist

		switch (ext_type) {
		case TLS_extension_supported_versions:
		case TLS_extension_key_share:
		case TLS_extension_pre_shared_key:
			if (!ext_data) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			break;
		}

		switch (ext_type) {
		case TLS_extension_supported_versions:
			if (supported_versions) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			supported_versions = ext_data;
			supported_versions_len = ext_datalen;
			break;

		case TLS_extension_key_share:
			// ServerHello.key_share if only ClientHello.key_share
			if (!conn->key_share) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			if (key_share) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			key_share = ext_data;
			key_share_len = ext_datalen;
			break;

		case TLS_extension_pre_shared_key:
			// ServerHello.pre_shared_key if only ClientHello.pre_shared_key
			if (!conn->pre_shared_key) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			if (pre_shared_key) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			pre_shared_key = ext_data;
			pre_shared_key_len = ext_datalen;
			break;

		default:
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;
		}
	}

	if (!supported_versions) {
		error_print();
		tls13_send_alert(conn, TLS_alert_missing_extension);
		return -1;
	}

	// if HelloRetryRequest, key_share must exist
	if (conn->hello_retry_request) {
		if (!key_share) {
			error_print();
			tls13_send_alert(conn, TLS_alert_missing_extension);
			return -1;
		}
	}

	// key_exchange_mode
	//  implicitly sent through ServerHello exts
	//
	//  * key_share + pre_shared_key	PSK_DHE
	//  * key_share				CERT_DHE
	//  * pre_shared_key			PSK
	//  * (none)				error
	//
	if (pre_shared_key) {
		if (key_share)
			server_key_exchange_mode = TLS_KE_PSK_DHE;
		else	server_key_exchange_mode = TLS_KE_PSK;
	} else {
		if (key_share) {
			server_key_exchange_mode = TLS_KE_CERT_DHE;
		} else {
			error_print();
			tls13_send_alert(conn, TLS_alert_missing_extension);
			return -1;
		}
	}


	// set key_exchange_mode
	conn->key_exchange_modes &= server_key_exchange_mode;

	if (!conn->key_exchange_modes) {
		error_print();
		tls13_send_alert(conn, TLS_alert_handshake_failure);
		return -1;
	}


	// supported_versions
	if (tls13_server_supported_versions_from_bytes(
		&selected_version, supported_versions, supported_versions_len) != 1) {
		tls13_send_alert(conn, TLS_alert_decode_error);
		error_print();
		return -1;
	}
	if (conn->hello_retry_request) {
		if (selected_version != conn->protocol) {
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;
		}
	} else {
		if (tls_type_is_in_list(selected_version,
			conn->ctx->supported_versions, conn->ctx->supported_versions_cnt) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;
		}
		if (selected_version != TLS_protocol_tls13) {
			error_print();
			tls13_send_alert(conn, TLS_alert_internal_error);
			return -1;
		}
		conn->protocol = selected_version;
	}


	// key_share
	if (key_share) {
		int key_exchange_group;
		const uint8_t *key_exchange;
		size_t key_exchange_len;

		if (!conn->key_exchanges_cnt) {
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;
		}
		if (tls13_key_share_server_hello_from_bytes(&key_exchange_group,
			&key_exchange, &key_exchange_len, key_share, key_share_len) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_decode_error);
			return -1;
		}
		// compatible with/without HRR
		while (conn->key_exchange_idx < conn->key_exchanges_cnt) {
			if (conn->key_exchanges[conn->key_exchange_idx].algor_param ==
				tls_named_curve_oid(key_exchange_group)) {
				break;
			}
			conn->key_exchange_idx++;
		}
		if (conn->key_exchange_idx >= conn->key_exchanges_cnt) {
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;
		}
		if (key_exchange_len != 65) {
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;
		}
		conn->key_exchange_group = key_exchange_group;
		memcpy(conn->peer_key_exchange, key_exchange, key_exchange_len);
		conn->peer_key_exchange_len = 65;
	}

	// pre_shared_key
	if (pre_shared_key) {
		const uint8_t *psk_keys = conn->psk_keys;
		size_t psk_keys_len = conn->psk_keys_len;
		int selected_identity;
		const uint8_t *key = NULL;
		size_t keylen = 0;
		size_t i;

		if (tls13_server_pre_shared_key_from_bytes(&selected_identity,
			pre_shared_key, pre_shared_key_len) != 1) {
			error_print();
			return -1;
		}
		for (i = 0; i <= (size_t)selected_identity; i++) {
			if (tls_uint8array_from_bytes(&key, &keylen, &psk_keys, &psk_keys_len) != 1) {
				error_print();
				return -1;
			}
		}
		if (!key) {
			error_print();
			return -1;
		}

		// TODO: change psk from buf to reference
		if (keylen > sizeof(conn->psk)) {
			error_print();
			return -1;
		}
		memcpy(conn->psk, key, keylen);
		conn->psk_len = keylen;
	}


	if (conn->hello_retry_request) {
		// dgst_ctx <= ServerHello
		if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_internal_error);
			return -1;
		}
		if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ServerHello", &conn->dgst_ctx);
	} else {
		if (digest_init(&conn->dgst_ctx, conn->digest) != 1) {
			error_print();
			return -1;
		}

		// update(ClientHello)
		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);

		// update(ServerHello)
		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 (conn->client_certs_len) {
		sm2_sign_update(&conn->sign_ctx, conn->record + 5, conn->recordlen - 5);
	}

	if (tls13_generate_handshake_secrets(conn) != 1) {
		error_print();
		return -1;
	}

	tls13_generate_master_secret(conn);

	if (tls13_generate_server_handshake_keys(conn) != 1) {
		error_print();
		return -1;
	}
	if (!conn->early_data) {
		if (tls13_generate_client_handshake_keys(conn) != 1) {
			error_print();
			return -1;
		}
	}

	return 1;
}

int tls13_send_change_cipher_spec(TLS_CONNECT *conn)
{
	int ret;

	if (!conn->recordlen) {

		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) tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
	}

	if ((ret = tls_send_record(conn)) != 1) {
		if (ret != TLS_ERROR_SEND_AGAIN) {
			error_print();
		}
		return ret;
	}

	return 1;
}

int tls13_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(conn->verbose) tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);

	if ((ret = tls_record_get_change_cipher_spec(conn->record)) < 0) {
		error_print();
		tls_send_alert(conn, TLS_alert_decode_error);
		return -1;
	} else if (ret == 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_unexpected_message);
		return -1;
	}

	return 1;
}

int tls13_recv_encrypted_extensions(TLS_CONNECT *conn)
{
	int ret;
	const uint8_t *exts;
	size_t extslen;

	const uint8_t *supported_groups = NULL;

	int server_name = 0;
	int early_data = 0;
	int alpn = 0;

	if ((ret = tls_recv_record(conn)) != 1) {
		if (ret != TLS_ERROR_RECV_AGAIN) {
			error_print();
		}
		return ret;
	}
	if(conn->verbose) tls_trace("recv {EncryptedExtensions}\n");
	if (tls13_record_decrypt(conn->cipher_suite, &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();
		tls13_send_alert(conn, TLS_alert_bad_record_mac);
		return -1;
	}
	tls_seq_num_incr(conn->server_seq_num);


	if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
		error_print();
		return -1;
	}
	if(conn->verbose) tls13_record_trace(stderr, conn->plain_record, conn->plain_recordlen, 0, 0);

	if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "EncryptedExtension", &conn->dgst_ctx);


	if ((ret = tls13_record_get_handshake_encrypted_extensions(conn->plain_record,
		&exts, &extslen)) < 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	} else if (ret == 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_unexpected_message);
		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();
			tls13_send_alert(conn, TLS_alert_decode_error);
			return -1;
		}

		// Exts in EE (see RFC 8446 page 37)
		//  * supported_groups
		//  * server_name
		//  * early_data
		//  * application_layer_protocol_negotiation
		//  * use_srtp
		//  * client_certificate_type
		//  * server_certificate_type
		//  * max_fragment_length
		//  * heartbeat
		//  * record_size_limit (RFC 8449)


		switch (ext_type) {
		case TLS_extension_supported_groups:
			if (!ext_data) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			break;
		case TLS_extension_server_name:
		case TLS_extension_early_data:
			if (ext_data) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			break;
		case TLS_extension_application_layer_protocol_negotiation:
			if (!ext_data) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			break;
		}

		switch (ext_type) {
		case TLS_extension_supported_groups:
			if (!conn->ctx->supported_groups_cnt) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			if (supported_groups) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			break;

		case TLS_extension_server_name:
			if (!conn->server_name) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			if (server_name) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			server_name = 1;
			break;

		case TLS_extension_early_data:
			if (!conn->early_data) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			if (early_data) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			early_data = 1;
			break;

		case TLS_extension_application_layer_protocol_negotiation:
			if (!conn->ctx->alpn_protocols_cnt) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			if (alpn) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			if ((ret = tls_application_layer_protocol_negotiation_selected_from_bytes(
				&conn->alpn_selected, ext_data, ext_datalen,
				conn->ctx->alpn_protocols, conn->ctx->alpn_protocols_cnt)) < 0) {
				error_print();
				tls13_send_alert(conn, TLS_alert_decode_error);
				return -1;
			} else if (ret == 0) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			alpn = 1;
			break;

		case TLS_extension_use_srtp:
		case TLS_extension_client_certificate_type:
		case TLS_extension_server_certificate_type:
		case TLS_extension_max_fragment_length:
		case TLS_extension_heartbeat:
		case TLS_extension_record_size_limit:
			break;

		default:
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;
		}
	}

	// server_name
	// if or not server support SNI, do nothing

	// early_data
	conn->early_data = early_data; // server allow EarlyData messages


	return 1;
}

int tls_cert_match_signature_algorithms(const uint8_t *cert, size_t certlen,
	const int *signature_algorithms, size_t signature_algorithms_cnt,
	int *first_matched_sig_alg)
{
	X509_KEY subject_public_key;
	int group_oid;
	size_t i;

	if (!cert || !certlen || !signature_algorithms || !signature_algorithms_cnt) {
		error_print();
		return -1;
	}

	if (x509_cert_get_subject_public_key(cert, certlen, &subject_public_key) != 1) {
		error_print();
		return -1;
	}
	if (subject_public_key.algor != OID_ec_public_key) {
		error_print();
		return -1;
	}
	group_oid = subject_public_key.algor_param;

	for (i = 0; i < signature_algorithms_cnt; i++) {
		if (group_oid == tls_signature_scheme_group_oid(signature_algorithms[i])) {
			*first_matched_sig_alg = signature_algorithms[i];
			return 1;
		}
	}

	*first_matched_sig_alg = 0;
	return 0;
}

int tls_cert_chain_match_signature_algorithms_cert(
	const uint8_t *cert_chain, size_t cert_chain_len,
	const int *signature_algorithms_cert, size_t signature_algorithms_cert_cnt)
{
	const uint8_t *cert;
	size_t certlen;
	const uint8_t *next_cert;
	size_t next_certlen;
	X509_KEY subject_public_key;
	int alg_oid;
	int group_oid;
	int sig_alg;

	if (!cert_chain || !cert_chain_len
		|| !signature_algorithms_cert && signature_algorithms_cert_cnt) {
		error_print();
		return -1;
	}

	if (x509_cert_from_der(&cert, &certlen, &cert_chain, &cert_chain_len) != 1) {
		error_print();
		return -1;
	}

	while (cert_chain_len) {
		if (x509_cert_get_signature_algor(cert, certlen, &alg_oid) != 1) {
			error_print();
			return -1;
		}
		if (x509_cert_from_der(&next_cert, &next_certlen, &cert_chain, &cert_chain_len) != 1
			|| x509_cert_get_subject_public_key(next_cert, next_certlen, &subject_public_key) != 1) {
			error_print();
			return -1;
		}
		if (subject_public_key.algor != OID_ec_public_key) {
			error_print();
			return -1;
		}
		group_oid = subject_public_key.algor_param;
		if (!(sig_alg = tls_signature_scheme_from_algorithm_and_group_oid(alg_oid, group_oid))) {
			error_print();
			return -1;
		}
		if (!tls_type_is_in_list(sig_alg, signature_algorithms_cert, signature_algorithms_cert_cnt)) {
			return 0;
		}

		cert = next_cert;
		certlen = next_certlen;
	}

	// can not do full check on the last cert, the public key is in root CA cert
	if (x509_cert_get_signature_algor(cert, certlen, &alg_oid) != 1) {
		error_print();
		return -1;
	}
	// 这里需要CA证书才能验证最后一个证书的签名算法是否满足要求

	return 1;
}

int tls_cert_match_server_name(const uint8_t *cert, size_t certlen, const uint8_t *host_name, size_t host_name_len)
{
	int ret;
	const uint8_t *subject_dns_name;
	size_t subject_dns_name_len;

	if (!cert || !certlen || !host_name || !host_name_len) {
		error_print();
		return -1;
	}
	if ((ret = x509_cert_get_subject_alt_name_dns_name(cert, certlen,
		&subject_dns_name, &subject_dns_name_len)) < 0) {
		error_print();
		return -1;
	} else if (ret == 0) {
		// certificate without SubjectAltName extension will fail the check
		// this is the default policy of major browsers and it is simple
		// else we need to check all the cert chains to make sure none of them match the SNI
		// then we can choose the default cert chain
		return 0;
	}
	if (subject_dns_name_len != host_name_len
		|| memcmp(subject_dns_name, host_name, host_name_len) != 0) {
		return 0;
	}
	return 1;
}

int tls_cert_chain_match_extensions(
	const uint8_t *cert_chain, size_t cert_chain_len,
	const int *signature_algorithms, size_t signature_algorithms_cnt,
	const int *signature_algorithms_cert, size_t signature_algorithms_cert_cnt, // optional
	const uint8_t *ca_names, size_t ca_names_len, // optional
	const uint8_t *oid_filters, size_t oid_filters_len, // optional
	const uint8_t *host_name, size_t host_name_len, // optional
	int *prefered_sig_alg)
{
	int ret;
	const uint8_t *cert;
	size_t certlen;
	int sig_alg;

	if (!cert_chain || !cert_chain_len
		|| !signature_algorithms || !signature_algorithms_cnt) {
		error_print();
		return -1;
	}

	if (prefered_sig_alg) {
		*prefered_sig_alg = 0;
	}

	if (x509_certs_get_cert_by_index(cert_chain, cert_chain_len, 0,
		&cert, &certlen) != 1) {
		error_print();
		return -1;
	}

	// signature_algorithms
	if ((ret = tls_cert_match_signature_algorithms(cert, certlen,
		signature_algorithms, signature_algorithms_cnt, &sig_alg)) < 0) {
		error_print();
		return -1;
	} else if (ret == 0) {
		return 0;
	}


	// server_name
	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) {
			return 0;
		}

	}

	// signature_algorithms_cert
	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) {
			return 0;
		}
	}

	// certificate_authorities
	if (ca_names && ca_names_len) {
		if ((ret = tls_authorities_issued_certificate(
			ca_names, ca_names_len, cert_chain, cert_chain_len)) < 0) {
			error_print();
			return -1;
		} else if (ret == 0) {
			return 0;
		}
	}

	// oid_filters
	if (oid_filters && oid_filters_len) {
	}

	if (prefered_sig_alg) {
		*prefered_sig_alg = sig_alg;
	}
	return 1;
}

int tls13_cert_chains_select(const uint8_t *cert_chains, size_t cert_chains_len,
	const int *signature_algorithms, size_t signature_algorithms_cnt,
	const int *signature_algorithms_cert, size_t signature_algorithms_cert_cnt, // optional
	const uint8_t *ca_names, size_t ca_names_len, // certificate_authorities optional
	const uint8_t *oid_filters, size_t oid_filters_len, // optional, only in CertificateRequest
	const uint8_t *host_name, size_t host_name_len, // optional, only in ClientHello
	const uint8_t **certs, size_t *certs_len, size_t *certs_idx, int *prefered_sig_alg) // optional
{
	size_t i;

	if (!cert_chains || !cert_chains_len) {
		error_print();
		return -1;
	}
	if (!signature_algorithms || !signature_algorithms_cnt) {
		error_print();
		return -1;
	}

	for (i = 1; cert_chains_len; i++) {
		const uint8_t *cert_chain;
		size_t cert_chain_len;
		int sig_alg;
		int ret;

		if (tls_uint24array_from_bytes(&cert_chain, &cert_chain_len,
			&cert_chains, &cert_chains_len) != 1) {
			error_print();
			return -1;
		}

		if ((ret = tls_cert_chain_match_extensions(cert_chain, cert_chain_len,
			signature_algorithms, signature_algorithms_cnt,
			signature_algorithms_cert, signature_algorithms_cert_cnt,
			ca_names, ca_names_len,
			oid_filters, oid_filters_len,
			host_name, host_name_len,
			&sig_alg)) < 0) {
			error_print();
			return -1;
		} else if (ret == 0) {
			continue;
		}

		if (certs) *certs = cert_chain;
		if (certs_len) *certs_len = cert_chain_len;
		if (certs_idx) *certs_idx = i;
		if (prefered_sig_alg) *prefered_sig_alg = sig_alg;
		return 1;
	}

	if (certs) *certs = NULL;
	if (certs_len) *certs_len = 0;
	if (certs_idx) *certs_idx = 0;
	if (prefered_sig_alg) *prefered_sig_alg = 0;
	warning_print();
	return 0;
}


int tls13_recv_certificate_request(TLS_CONNECT *conn)
{
	int ret;
	int handshake_type;
	const uint8_t *handshake_data;
	size_t handshake_datalen;
	int client_cert;

	// certificate_request
	const uint8_t *request_context;
	size_t request_context_len;
	const uint8_t *exts;
	size_t extslen;

	// extensions
	const uint8_t *signature_algorithms = NULL;
	size_t signature_algorithms_len;
	const uint8_t *signature_algorithms_cert = NULL;
	size_t signature_algorithms_cert_len;
	const uint8_t *certificate_authorities = NULL;
	size_t certificate_authorities_len;
	const uint8_t *oid_filters = NULL;
	size_t oid_filters_len;
	int status_request = 0;
	int signed_certificate_timestamp = 0;

	int common_sig_algs[4];
	size_t common_sig_algs_cnt = 0;
	int common_sig_algs_cert[4];
	size_t common_sig_algs_cert_cnt = 0;
	const uint8_t *ca_names = NULL;
	size_t ca_names_len = 0;
	const uint8_t *filters = NULL;
	size_t filters_len = 0;

	if ((ret = tls_recv_record(conn)) != 1) {
		if (ret != TLS_ERROR_RECV_AGAIN) {
			error_print();
		}
		return ret;
	}
	if(conn->verbose) tls_trace("recv {CertificateRequest*}\n");

	if (tls13_record_decrypt(conn->cipher_suite, &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();
		tls13_send_alert(conn, TLS_alert_bad_record_mac);
		return -1;
	}
	tls_seq_num_incr(conn->server_seq_num);

	if (tls_record_get_handshake(conn->plain_record,
		&handshake_type, &handshake_data, &handshake_datalen) != 1) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	}
	if (handshake_type != TLS_handshake_certificate_request) {
		if(conn->verbose) tls_trace("    no {CertificateRequest}\n\n");
		return 0;
	}
	if(conn->verbose) tls13_record_trace(stderr, conn->plain_record, conn->plain_recordlen, 0, 0);


	if ((ret = tls13_record_get_handshake_certificate_request(conn->plain_record,
		&request_context, &request_context_len, &exts, &extslen)) != 1) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	}

	if (request_context) {
		// request_context must be null in full/initial handshake
		// and must not be null in post authentication handshakes
		error_print();
		tls13_send_alert(conn, TLS_alert_illegal_parameter);
		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();
			tls13_send_alert(conn, TLS_alert_decode_error);
			return -1;
		}

		// exts in CR (from RFC 8446 page 37)
		//  * signature_algorithms - the only ext must exist
		//  * signature_algorithms_cert
		//  * certificate_authorities
		//  * oid_filters (only in CR)
		//  * status_request
		//  * signed_certificate_timestamp

		switch (ext_type) {
		case TLS_extension_signature_algorithms:
		case TLS_extension_signature_algorithms_cert:
		case TLS_extension_certificate_authorities:
		case TLS_extension_oid_filters:
			if (!ext_data) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			break;
		case TLS_extension_status_request:
		case TLS_extension_signed_certificate_timestamp:
			if (ext_data) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			break;
		}

		switch (ext_type) {
		case TLS_extension_signature_algorithms:
			if (signature_algorithms) {
				error_print();
				tls13_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();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			signature_algorithms_cert = ext_data;
			signature_algorithms_cert_len = ext_datalen;
			break;

		case TLS_extension_certificate_authorities:
			if (certificate_authorities) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			certificate_authorities = ext_data;
			certificate_authorities_len = ext_datalen;
			break;

		case TLS_extension_oid_filters:
			if (oid_filters) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			oid_filters = ext_data;
			oid_filters_len = ext_datalen;
			break;

		case TLS_extension_status_request:
			if (status_request) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			status_request = 1;
			break;

		case TLS_extension_signed_certificate_timestamp:
			if (signed_certificate_timestamp) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			signed_certificate_timestamp = 1;
			break;

		default:
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;
		}
	}

	if (!signature_algorithms) {
		error_print();
		tls13_send_alert(conn, TLS_alert_missing_extension);
		return -1;
	}

	// even if no client cert, check extensions
	if (conn->ctx->cert_chains_len) {
		client_cert = 1;
	}

	// signature_algorithms
	if ((ret = tls_process_signature_algorithms(
		signature_algorithms, signature_algorithms_len,
		conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt,
		common_sig_algs, &common_sig_algs_cnt,
		sizeof(common_sig_algs)/sizeof(common_sig_algs[0]))) < 0) {
		error_print();
		return -1;
	} else if (ret == 0) {
		client_cert = 0;
	}

	// signature_algorithms_cert
	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_sig_algs_cert, &common_sig_algs_cert_cnt,
			sizeof(common_sig_algs_cert)/sizeof(common_sig_algs_cert[0]))) < 0) {
			error_print();
			return -1;
		} else if (ret == 0) {
			client_cert = 0;
		}
	}

	// certificate_authorities
	if (certificate_authorities) {
		if (tls13_certificate_authorities_from_bytes(
			&ca_names, &ca_names_len,
			certificate_authorities, certificate_authorities_len) != 1) {
			error_print();
			return -1;
		}
	}

	// oid_filters
	if (oid_filters) {
		if (tls13_oid_filters_from_bytes(
			&filters, &filters_len, oid_filters, oid_filters_len) != 1) {
			error_print();
			return -1;
		}
	}

	// status_request
	if (status_request) {
		conn->status_request = 1;
	}

	// signed_certificate_timestamp
	if (signed_certificate_timestamp) {
		conn->signed_certificate_timestamp = 1;
	}

	// select cert_chain
	//	* signature_algorithms
	//	* [signature_algorithms_cert]
	//	* [certificate_authorities]
	//	* [oid_filter]
	//
	if (client_cert) {
		// client provides no certificate
		if (!conn->ctx->cert_chains_len) {
			warning_print();
			conn->cert_chain = NULL;
			conn->cert_chain_len = 0;
			conn->cert_chain_idx = 0;
			ret = 0;
		} else  if ((ret = tls13_cert_chains_select(
			conn->ctx->cert_chains, conn->ctx->cert_chains_len,
			common_sig_algs, common_sig_algs_cnt,
			common_sig_algs_cert, common_sig_algs_cert_cnt,
			ca_names, ca_names_len,
			filters, filters_len,
			NULL, 0,
			&conn->cert_chain, &conn->cert_chain_len, &conn->cert_chain_idx, &conn->sig_alg)) < 0) {
			error_print();
			return -1;
		}
		// when ret == 0, conn->cert_chain == NULL
	}

	if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
		error_print();
		return -1;
	}

	conn->certificate_request = 1;


	conn->record_offset = 0;
	conn->recordlen = 0;
	conn->plain_recordlen = 0;


	return ret;
}

int tls13_recv_server_certificate(TLS_CONNECT *conn)
{
	int ret;
	const uint8_t *request_context;
	size_t request_context_len;
	const uint8_t *leaf_status_request_ocsp_response = NULL;
	size_t leaf_status_request_ocsp_response_len = 0;
	const uint8_t *leaf_signed_certificate_timestamp;
	size_t leaf_signed_certificate_timestamp_len;
	const uint8_t *cert;
	size_t certlen;

	const int *signature_algorithms_cert = NULL;
	size_t signature_algorithms_cert_cnt = 0;
	const uint8_t *ca_names = NULL;
	size_t ca_names_len = 0;
	const uint8_t *host_name = NULL;
	size_t host_name_len = 0;

	int verify_result = X509_verify_ok;

	if ((ret = tls_recv_record(conn)) != 1) {
		if (ret != TLS_ERROR_RECV_AGAIN) {
			error_print();
		}
		return ret;
	}
	if(conn->verbose) tls_trace("recv server {Certificate}\n");

	// decrypt unless previous handshake is CertificateRequest
	if (!conn->plain_recordlen) {
		if (tls13_record_decrypt(conn->cipher_suite, &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();
			tls13_send_alert(conn, TLS_alert_bad_record_mac);
			return -1;
		}
		tls_seq_num_incr(conn->server_seq_num);

	}

	if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
		error_print();
		return -1;
	}
	if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
	if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ServerCertificate", &conn->dgst_ctx);

	if ((ret = tls13_record_get_handshake_certificate(conn->plain_record,
		&request_context, &request_context_len,
		conn->peer_cert_chain, &conn->peer_cert_chain_len, sizeof(conn->peer_cert_chain),
		&leaf_status_request_ocsp_response, &leaf_status_request_ocsp_response_len,
		&leaf_signed_certificate_timestamp, &leaf_signed_certificate_timestamp_len)) < 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	} else if (ret == 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_unexpected_message);
		return 0;
	}

	if (request_context) {
		error_print();
		tls13_send_alert(conn, TLS_alert_illegal_parameter);
		return -1;
	}
	if (!conn->peer_cert_chain_len) {
		error_print();
		conn->verify_result = X509_verify_err_certificate;
		tls13_send_alert(conn, TLS_alert_illegal_parameter);
		return -1;
	}

	// check server cert_chain match ClientHello.extensions
	if (conn->signature_algorithms_cert) {
		signature_algorithms_cert = conn->ctx->signature_algorithms;
		signature_algorithms_cert_cnt = conn->ctx->signature_algorithms_cnt;
	}
	if (conn->certificate_authorities) {
		ca_names = conn->ctx->ca_names;
		ca_names_len = conn->ctx->ca_names_len;
	}
	if (conn->host_name_len) {
		host_name = conn->host_name;
		host_name_len = conn->host_name_len;
	}

	// verify server cert_chain
	ret = tls_cert_chain_verify(
		conn->protocol, X509_cert_chain_server, conn->cipher_suite,
		1,
		conn->peer_cert_chain, conn->peer_cert_chain_len,
		conn->ctx->cacerts, conn->ctx->cacertslen,
		NULL, 0,
		leaf_status_request_ocsp_response, leaf_status_request_ocsp_response_len,
		conn->ctx->verify_depth,
		NULL, 0,
		conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt,
		signature_algorithms_cert, signature_algorithms_cert_cnt,
		ca_names, ca_names_len,
		NULL, 0,
		host_name, host_name_len,
		&verify_result, NULL);
	if (ret < 0) {
		error_print();
		conn->verify_result = verify_result;
		tls13_send_alert(conn, TLS_alert_bad_certificate);
		return -1;
	}
	if (ret == 0) {
		error_print();
		conn->verify_result = verify_result;
		if (verify_result == X509_verify_err_crl
			|| verify_result == X509_verify_err_ocsp) {
			tls13_send_alert(conn, TLS_alert_certificate_revoked);
		} else {
			tls13_send_alert(conn, TLS_alert_bad_certificate);
		}
		return -1;
	}
	conn->verify_result = verify_result;
	// signed_certificate_timestamp
	if (leaf_signed_certificate_timestamp) {
		if (x509_certs_get_cert_by_index(conn->peer_cert_chain,
			conn->peer_cert_chain_len, 0, &cert, &certlen) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_bad_certificate);
			return -1;
		}
		if (tls13_signed_certificate_timestamp_verify(
			leaf_signed_certificate_timestamp,
			leaf_signed_certificate_timestamp_len,
			SCT_log_entry_type_x509_entry, NULL, cert, certlen,
			conn->ctx->ct_logs, conn->ctx->ct_logs_cnt,
			conn->ctx->ct_at_least) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_bad_certificate);
			return -1;
		}
	}

	return 1;
}

int tls13_recv_server_certificate_verify(TLS_CONNECT *conn)
{
	int ret;
	int sig_alg;
	const uint8_t *sig;
	size_t siglen;
	const uint8_t *cert;
	size_t certlen;
	X509_KEY public_key;

	if ((ret = tls_recv_record(conn)) != 1) {
		if (ret != TLS_ERROR_RECV_AGAIN) {
			error_print();
		}
		return ret;
	}
	if(conn->verbose) tls_trace("recv server {CertificateVerify}\n");

	if (tls13_record_decrypt(conn->cipher_suite, &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();
		tls13_send_alert(conn, TLS_alert_bad_record_mac);
		return -1;
	}
	tls_seq_num_incr(conn->server_seq_num);
	if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);

	if ((ret = tls13_record_get_handshake_certificate_verify(conn->plain_record,
		&sig_alg, &sig, &siglen)) < 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	} else if (ret == 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_unexpected_message);
		return -1;
	}
	if (tls_type_is_in_list(sig_alg, conn->ctx->signature_algorithms,
		conn->ctx->signature_algorithms_cnt) != 1) {
		error_print();
		tls13_send_alert(conn, TLS_alert_illegal_parameter);
		return -1;
	}
	if (!sig) {
		error_print();
		tls13_send_alert(conn, TLS_alert_illegal_parameter);
		return -1;
	}

	if (x509_certs_get_cert_by_index(conn->peer_cert_chain, conn->peer_cert_chain_len, 0, &cert, &certlen) != 1
		|| x509_cert_get_subject_public_key(cert, certlen, &public_key) != 1) {
		error_print();
		tls13_send_alert(conn, TLS_alert_unexpected_message);
		return -1;
	}

	// verify signature
	if (tls13_verify_certificate_verify(TLS_server_mode, sig_alg, &public_key,
		&conn->dgst_ctx, sig, siglen) != 1) {
		error_print();
		return -1;
	}

	if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
		error_print();
		return -1;
	}

	conn->recordlen = 0;
	conn->plain_recordlen = 0;

	return 1;
}

int tls13_recv_client_certificate_verify(TLS_CONNECT *conn)
{
	int ret;
	int sig_alg;
	const uint8_t *sig;
	size_t siglen;
	const uint8_t *cert;
	size_t certlen;
	X509_KEY public_key;

	if ((ret = tls_recv_record(conn)) != 1) {
		if (ret != TLS_ERROR_RECV_AGAIN) {
			error_print();
		}
		return ret;
	}
	if(conn->verbose) tls_trace("recv client {CertificateVerify}\n");

	if (tls13_record_decrypt(conn->cipher_suite, &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();
		tls13_send_alert(conn, TLS_alert_bad_record_mac);
		return -1;
	}
	tls_seq_num_incr(conn->client_seq_num);
	if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);




	if ((ret = tls13_record_get_handshake_certificate_verify(conn->plain_record,
		&sig_alg, &sig, &siglen)) < 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	} else if (ret == 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_unexpected_message);
		return -1;
	}
	if (tls_type_is_in_list(sig_alg, conn->ctx->signature_algorithms,
		conn->ctx->signature_algorithms_cnt) != 1) {
		error_print();
		tls13_send_alert(conn, TLS_alert_illegal_parameter);
		return -1;
	}
	if (!sig) {
		error_print();
		tls13_send_alert(conn, TLS_alert_illegal_parameter);
		return -1;
	}


	if (x509_certs_get_cert_by_index(conn->peer_cert_chain, conn->peer_cert_chain_len, 0, &cert, &certlen) != 1
		|| x509_cert_get_subject_public_key(cert, certlen, &public_key) != 1) {
		error_print();
		tls13_send_alert(conn, TLS_alert_unexpected_message);
		return -1;
	}

	// verify signature
	if (tls13_verify_certificate_verify(TLS_client_mode, sig_alg, &public_key,
		&conn->dgst_ctx, sig, siglen) != 1) {
		error_print();
		return -1;
	}

	// must update after tls13_verify_certificate_verify
	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, "CertificateVerify", &conn->dgst_ctx);

	return 1;
}

int tls13_recv_server_finished(TLS_CONNECT *conn)
{
	int ret;
	const uint8_t *server_verify_data;
	size_t server_verify_data_len;
	uint8_t verify_data[64];
	size_t verify_data_len;

	// compute verify_data before digest_update
	if (tls13_compute_verify_data(conn->server_handshake_traffic_secret,
		&conn->dgst_ctx, verify_data, &verify_data_len) != 1) {
		error_print();
		return -1;
	}

	if (!conn->plain_recordlen) {

		if ((ret = tls_recv_record(conn)) != 1) {
			if (ret != TLS_ERROR_RECV_AGAIN) {
				error_print();
			}
			return ret;
		}

		if (tls13_record_decrypt(conn->cipher_suite, &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();
			tls13_send_alert(conn, TLS_alert_bad_record_mac);
			return -1;
		}
		tls_seq_num_incr(conn->server_seq_num);
	}
	if(conn->verbose) tls_trace("recv server {Finished}\n");
	if(conn->verbose) tls13_record_print(stderr, 0, 0, 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, "ServerFinished", &conn->dgst_ctx);


	if ((ret = tls13_record_get_handshake_finished(conn->plain_record,
		&server_verify_data, &server_verify_data_len)) < 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	} else if (ret == 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_unexpected_message);
		return -1;
	}

	if (server_verify_data_len != verify_data_len
		|| memcmp(server_verify_data, verify_data, verify_data_len) != 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_bad_record_mac);
		return -1;
	}


	tls13_generate_application_secrets(conn);
	tls13_generate_server_application_keys(conn);


	return 1;
}

int tls13_send_client_certificate(TLS_CONNECT *conn)
{
	int ret;

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

	if (conn->recordlen == 0) {
		const uint8_t *request_context = NULL;
		size_t request_context_len = 0;
		const uint8_t *entity_status_request_ocsp_response = NULL;
		size_t entity_status_request_ocsp_response_len = 0;
		const uint8_t *entity_signed_certificate_timestamp = NULL;
		size_t entity_signed_certificate_timestamp_len = 0;
		size_t padding_len;

		// status_request
		if (conn->status_request) {
			entity_status_request_ocsp_response = conn->status_request_ocsp_response;
			entity_status_request_ocsp_response_len = conn->status_request_ocsp_response_len;
		}

		// signed_certificate_timestamp
		if (conn->signed_certificate_timestamp) {
			entity_signed_certificate_timestamp = conn->signed_certificate_timestamp_list;
			entity_signed_certificate_timestamp_len = conn->signed_certificate_timestamp_list_len;
		}

		if (tls13_record_set_handshake_certificate(conn->plain_record, &conn->plain_recordlen,
			request_context, request_context_len,
			conn->cert_chain, conn->cert_chain_len,
			entity_status_request_ocsp_response, entity_status_request_ocsp_response_len,
			entity_signed_certificate_timestamp, entity_signed_certificate_timestamp_len) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_internal_error);
			return -1;
		}
		if(conn->verbose) tls13_record_print(stderr, 0, 0, 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, "client Certficate", &conn->dgst_ctx);


		tls13_padding_len_rand(&padding_len);
		if (tls13_record_encrypt(conn->cipher_suite, &conn->client_write_key, conn->client_write_iv,
			conn->client_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
			conn->record, &conn->recordlen) != 1) {
			error_print();
			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 tls13_send_client_certificate_verify(TLS_CONNECT *conn)
{
	int ret;

	if(conn->verbose) tls_trace("send client {CertificateVerify*}\n");

	if (!conn->recordlen) {
		X509_KEY *sign_key = &conn->ctx->x509_keys[conn->cert_chain_idx - 1];
		uint8_t sig[256];
		size_t siglen;
		size_t padding_len;

		if (tls13_sign_certificate_verify(TLS_client_mode, conn->sig_alg,
			sign_key, &conn->dgst_ctx, sig, &siglen) != 1) {
			error_print();
			return -1;
		}

		if (tls13_record_set_handshake_certificate_verify(
			conn->plain_record, &conn->plain_recordlen,
			conn->sig_alg, sig, siglen) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_internal_error);
			return -1;
		}
		if(conn->verbose) tls13_record_print(stderr, 0, 0, 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, "after client CertificateVerify", &conn->dgst_ctx);

		tls13_padding_len_rand(&padding_len);
		if (tls13_record_encrypt(conn->cipher_suite, &conn->client_write_key, conn->client_write_iv,
			conn->client_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
			conn->record, &conn->recordlen) != 1) {
			error_print();
			tls13_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 tls13_send_client_finished(TLS_CONNECT *conn)
{
	int ret;

	if(conn->verbose) tls_trace("send client {Finished}\n");

	if (!conn->recordlen) {
		uint8_t verify_data[64];
		size_t verify_data_len;
		size_t padding_len;

		tls13_compute_verify_data(conn->client_handshake_traffic_secret, &conn->dgst_ctx,
			verify_data, &verify_data_len);

		if (tls_record_set_handshake_finished(conn->plain_record, &conn->plain_recordlen,
			verify_data, verify_data_len) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_internal_error);
			return -1;
		}
		if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);

		//format_print(stderr, 0, 0, "client_seq_num: "PRIu64"\n", GETU64(conn->client_seq_num));

		tls13_padding_len_rand(&padding_len);
		if (tls13_record_encrypt(conn->cipher_suite, &conn->client_write_key, conn->client_write_iv,
			conn->client_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
			conn->record, &conn->recordlen) != 1) {
			error_print();
			tls13_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;
	}


	tls13_generate_client_application_keys(conn);
	if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
		error_print();
		return -1;
	}

	return 1;
}

static int tls13_cipher_suites_match_signature_scheme(
	const int *cipher_suites, size_t cipher_suites_cnt, int sig_alg,
	int *selected, size_t *selected_cnt, size_t max_cnt)
{
	int digest_oid;
	size_t i;

	switch (tls_signature_scheme_algorithm_oid(sig_alg)) {
	case OID_sm2sign_with_sm3:
		digest_oid = OID_sm3;
		break;
	case OID_ecdsa_with_sha256:
		digest_oid = OID_sha256;
		break;
	default:
		error_print();
		return -1;
	}

	*selected_cnt = 0;

	for (i = 0; i < cipher_suites_cnt && i < max_cnt; i++) {
		const BLOCK_CIPHER *cipher;
		const DIGEST *digest;

		if (tls_cipher_suite_get(cipher_suites[i], &cipher, &digest) != 1) {
			error_print();
			return -1;
		}
		if (digest->oid == digest_oid) {
			selected[(*selected_cnt)++] = cipher_suites[i];
		}
	}

	if (*selected_cnt == 0) {
		return 0;
	}
	return 1;
}


int tls13_recv_client_hello(TLS_CONNECT *conn)
{
	int ret;
	uint8_t *record = conn->record;

	int client_verify = 0;

	// client_hello
	int legacy_version;
	const uint8_t *random;
	const uint8_t *legacy_session_id;
	size_t legacy_session_id_len;
	const uint8_t *cipher_suites;
	size_t cipher_suites_len;
	const uint8_t *exts;
	size_t extslen;

	// extensions
	const uint8_t *supported_versions = NULL;
	size_t supported_versions_len;
	const uint8_t *supported_groups = NULL;
	size_t supported_groups_len;
	const uint8_t *signature_algorithms = NULL;
	size_t signature_algorithms_len;
	const uint8_t *signature_algorithms_cert = NULL;
	size_t signature_algorithms_cert_len;
	const uint8_t *certificate_authorities = NULL;
	size_t certificate_authorities_len;
	const uint8_t *key_share = NULL;
	size_t key_share_len;
	const uint8_t *server_name = NULL;
	size_t server_name_len;
	const uint8_t *alpn = NULL;
	size_t alpn_len;
	const uint8_t *psk_key_exchange_modes = NULL;
	size_t psk_key_exchange_modes_len;
	const uint8_t *pre_shared_key = NULL;
	size_t pre_shared_key_len;
	const uint8_t *status_request = NULL;
	size_t status_request_len;
	int signed_certificate_timestamp = 0;
	int early_data = 0;

	int common_versions[4];
	size_t common_versions_cnt = 0;
	int common_groups[4];
	size_t common_groups_cnt = 0;
	int common_sig_algs[4];
	size_t common_sig_algs_cnt = 0;
	int common_sig_algs_cert[4];
	size_t common_sig_algs_cert_cnt = 0;

	const uint8_t *host_name = NULL;
	size_t host_name_len;

	int common_key_exchange_modes = 0;

	const uint8_t *ca_names = NULL;
	size_t ca_names_len = 0;


	// 这个判断应该改为一个函数
	/*
	if (client_verify)
		tls_client_verify_init(&conn->client_verify_ctx);
	*/

	if ((ret = tls_recv_record(conn)) != 1) {
		if (ret != TLS_ERROR_RECV_AGAIN) {
			error_print();
		}
		return ret;
	}
	if(conn->verbose) tls_trace("recv ClientHello\n");
	if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);

	if (tls_record_protocol(record) != TLS_protocol_tls1
		&& tls_record_protocol(record) != TLS_protocol_tls12) {
		error_print();
		tls13_send_alert(conn, TLS_alert_protocol_version);
		return -1;
	}
	if ((ret = tls_record_get_handshake_client_hello(conn->record,
		&legacy_version, &random, &legacy_session_id, &legacy_session_id_len,
		&cipher_suites, &cipher_suites_len, &exts, &extslen)) < 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	} else if (ret == 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_unexpected_message);
		return -1;
	}

	// legacy_version
	if (legacy_version != TLS_protocol_tls12) {
		error_print();
		tls13_send_alert(conn, TLS_alert_protocol_version);
		return -1;
	}

	// random
	memcpy(conn->client_random, random, 32);

	// legacy_session_id
	if (legacy_session_id_len) {
		// tls13 server ignore legacy_session_id
		warning_print();

		if (legacy_session_id_len > sizeof(conn->session_id)) {
			error_print();
			return -1;
		}
		memcpy(conn->session_id, legacy_session_id, legacy_session_id_len);
		conn->session_id_len = legacy_session_id_len;
	}

	// cipher_suites
	// after select server cert_chain, cipher_suite might be changed
	if ((ret = tls_cipher_suites_select(cipher_suites, cipher_suites_len,
		conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt,
		&conn->cipher_suite)) < 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	} else if (ret == 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_handshake_failure);
		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();
			tls13_send_alert(conn, TLS_alert_decode_error);
			return -1;
		}

		// exts in CH (RFC 8446 page 37), only oid_filter not in CH
		//  * supported_versions
		//  * signature_algorithms
		//  * signature_algorithms_cert
		//  * certificate_authorities
		//  * server_name
		//  * status_request
		//  * signed_certificate_timestamp
		//  * supported_groups
		//  * key_share
		//  * psk_key_exchange_modes
		//  * pre_shared_key
		//  * early_data (only in ClientHello1)
		//  * max_fragment_length
		//  * use_srtp
		//  * heartbeat
		//  * application_layer_protocol_negotiation
		//  * server_certificate_type: if client accept raw/x509
		//  * client_certificate_type: if client sned raw/x509
		//  * padding
		//  * post_handshake_auth: client support post handshake auth
		//  * cookie (only in ClientHello2)


		switch (ext_type) {
		case TLS_extension_supported_versions:
		case TLS_extension_supported_groups:
		case TLS_extension_signature_algorithms:
		case TLS_extension_signature_algorithms_cert:
		case TLS_extension_certificate_authorities:
		case TLS_extension_key_share:
		case TLS_extension_server_name:
		case TLS_extension_application_layer_protocol_negotiation:
		case TLS_extension_psk_key_exchange_modes:
		case TLS_extension_pre_shared_key:
		case TLS_extension_status_request:
			if (!ext_data) {
				error_print();
				return -1;
			}
			break;
		case TLS_extension_signed_certificate_timestamp:
		case TLS_extension_early_data:
			if (ext_data) {
				error_print();
				return -1;
			}
			break;
		}

		switch (ext_type) {
		case TLS_extension_supported_versions:
			if (supported_versions) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			supported_versions = ext_data;
			supported_versions_len = ext_datalen;
			break;

		case TLS_extension_supported_groups:
			if (supported_groups) {
				error_print();
				tls13_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();
				tls13_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();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			signature_algorithms_cert = ext_data;
			signature_algorithms_cert_len = ext_datalen;
			break;

		case TLS_extension_certificate_authorities:
			if (certificate_authorities) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			certificate_authorities = ext_data;
			certificate_authorities_len = ext_datalen;
			break;

		case TLS_extension_key_share:
			if (key_share) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			key_share = ext_data;
			key_share_len = ext_datalen;
			break;

		case TLS_extension_server_name:
			if (server_name) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			server_name = ext_data;
			server_name_len = ext_datalen;
			break;

		case TLS_extension_application_layer_protocol_negotiation:
			if (alpn) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			alpn = ext_data;
			alpn_len = ext_datalen;
			break;

		case TLS_extension_psk_key_exchange_modes:
			if (psk_key_exchange_modes) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			psk_key_exchange_modes = ext_data;
			psk_key_exchange_modes_len = ext_datalen;
			break;

		case TLS_extension_pre_shared_key:
			if (pre_shared_key) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			pre_shared_key = ext_data;
			pre_shared_key_len = ext_datalen;
			break;

		case TLS_extension_status_request:
			if (status_request) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			status_request = ext_data;
			status_request_len = ext_datalen;
			break;

		case TLS_extension_signed_certificate_timestamp:
			if (signed_certificate_timestamp) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			signed_certificate_timestamp = 1;
			break;

		case TLS_extension_early_data:
			if (early_data) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			early_data = 1;
			break;

		case TLS_extension_cookie:
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;

		/*
		case TLS_extension_max_fragment_length:
		case TLS_extension_use_srtp:
		case TLS_extension_heartbeat:
		case TLS_extension_application_layer_protocol_negotiation:
		case TLS_extension_server_certificate_type:
		case TLS_extension_client_certificate_type:
		case TLS_extension_padding:
		case TLS_extension_post_handshake_auth:
		default:
			format_print(stderr, 0, 4, "%s: %d: unsupported extension: %s (%04x)\n",
				__FILE__, __LINE__, tls_extension_name(ext_type), ext_type);
		*/
		}
	}

	// from RFC 8446 section 9.2
	//   * supported_versions required for CH, SH, HRR
	//   * if no pre_shared_key, signature_algorithms + supported_groups must exist
	//   * supported_groups + key_share must exist together
	//   * empty key_share is permitted
	//
	if (!supported_versions) {
		error_print();
		tls13_send_alert(conn, TLS_alert_missing_extension);
		return -1;
	}
	if (!pre_shared_key) {
		if (!(signature_algorithms && supported_groups)) {
			error_print();
			tls13_send_alert(conn, TLS_alert_missing_extension);
			return -1;
		}
	}
	if ((supported_groups && !key_share)
		|| (!supported_groups && key_share)) {
		error_print();
		tls13_send_alert(conn, TLS_alert_missing_extension);
		return -1;
	}
	if (pre_shared_key && !psk_key_exchange_modes) {
		error_print();
		tls13_send_alert(conn, TLS_alert_missing_extension);
		return -1;
	}

	// supported_versions
	if ((ret = tls13_process_client_supported_versions(
		supported_versions, supported_versions_len,
		conn->ctx->supported_versions, conn->ctx->supported_versions_cnt,
		common_versions, &common_versions_cnt,
		sizeof(common_versions)/sizeof(common_versions[0]))) < 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	} else if (ret == 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_protocol_version);
		return -1;
	}
	if (common_versions[0] != TLS_protocol_tls13) {
		error_print();
		tls13_send_alert(conn, TLS_alert_protocol_version);
		return -1;
	}
	conn->protocol = common_versions[0];


	// psk_key_exchange_modes
	if (psk_key_exchange_modes) {
		if (tls13_psk_key_exchange_modes_from_bytes(&common_key_exchange_modes,
			psk_key_exchange_modes, psk_key_exchange_modes_len) != 1) {
			error_print();
			return -1;
		}
	}
	// client key_exchange_modes
	if (supported_groups && signature_algorithms) {
		common_key_exchange_modes |= TLS_KE_CERT_DHE;
	}

	// common key_exchange_modes
	common_key_exchange_modes &= conn->key_exchange_modes;
	if (!common_key_exchange_modes) {
		error_print();
		tls13_send_alert(conn, TLS_alert_handshake_failure);
		return -1;
	}

	// signature_algorithms
	if (signature_algorithms) {
		if ((ret = tls_process_signature_algorithms(
			signature_algorithms, signature_algorithms_len,
			conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt,
			common_sig_algs, &common_sig_algs_cnt,
			sizeof(common_sig_algs)/sizeof(common_sig_algs[0]))) < 0) {
			error_print();
			tls13_send_alert(conn, TLS_alert_decode_error);
			return -1;
		} else if (ret == 0) {
			common_key_exchange_modes &= ~TLS_KE_CERT_DHE;
		}
	}

	// signature_algorithms_cert
	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_sig_algs_cert, &common_sig_algs_cert_cnt,
			sizeof(common_sig_algs_cert)/sizeof(common_sig_algs_cert[0]))) < 0) {
			error_print();
			tls13_send_alert(conn, TLS_alert_decode_error);
			return -1;
		} else if (ret == 0) {
			common_key_exchange_modes &= ~TLS_KE_CERT_DHE;
		}
	}

	// certificate_authorities
	if (certificate_authorities) {
		if (tls13_certificate_authorities_from_bytes(&ca_names, &ca_names_len,
			certificate_authorities, certificate_authorities_len) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;
		}
	}

	// server_name
	if (server_name) {
		if (tls_server_name_from_bytes(&host_name, &host_name_len,
			server_name, server_name_len) != 1) {
			error_print();
			return -1;
		}
		conn->server_name = 1;
	}

	// application_layer_protocol_negotiation
	if (alpn) {
		if (!conn->ctx->alpn_protocols_cnt) {
			error_print();
			tls13_send_alert(conn, TLS_alert_no_application_protocol);
			return -1;
		}
		if ((ret = tls_application_layer_protocol_negotiation_select(
			alpn, alpn_len,
			conn->ctx->alpn_protocols, conn->ctx->alpn_protocols_cnt,
			&conn->alpn_selected)) < 0) {
			error_print();
			tls13_send_alert(conn, TLS_alert_decode_error);
			return -1;
		} else if (ret == 0) {
			error_print();
			tls13_send_alert(conn, TLS_alert_no_application_protocol);
			return -1;
		}
	}

	// select server cert_chain
	//	* signature_algorithms
	//	* [signature_algorithms_cert]
	//	* [certificate_authorities]
	//	* [server_name.host_name]
	//
	if (common_key_exchange_modes & TLS_KE_CERT_DHE) {
		int common_cipher_suites[TLS_MAX_CIPHER_SUITES];
		size_t common_cipher_suites_cnt;

		if (!conn->ctx->cert_chains_len) {
			error_print();
			return -1;
		}

		if ((ret = tls13_cert_chains_select(
			conn->ctx->cert_chains, conn->ctx->cert_chains_len,
			common_sig_algs, common_sig_algs_cnt,
			common_sig_algs_cert, common_sig_algs_cert_cnt,
			ca_names, ca_names_len,
			NULL, 0, // oid_filters
			host_name, host_name_len,
			&conn->cert_chain, &conn->cert_chain_len, &conn->cert_chain_idx, &conn->sig_alg)) < 0) {
			error_print();
			tls13_send_alert(conn, TLS_alert_decode_error);
			return -1;
		} else if (ret == 0) {
			error_print();
			common_key_exchange_modes &= ~TLS_KE_CERT_DHE;
		}

		// cipher_suites match conn->sig_alg
		if (tls13_cipher_suites_match_signature_scheme(
			conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt, conn->sig_alg,
			common_cipher_suites, &common_cipher_suites_cnt,
			sizeof(common_cipher_suites)/sizeof(common_cipher_suites[0])) != 1) {
			error_print();
			return -1;
		}

		// update conn->cipher_suite
		if ((ret = tls_cipher_suites_select(cipher_suites, cipher_suites_len,
			common_cipher_suites, common_cipher_suites_cnt,
			&conn->cipher_suite)) < 0) {
			error_print();
			tls13_send_alert(conn, TLS_alert_decode_error);
			return -1;
		} else if (ret == 0) {
			error_print();
			tls13_send_alert(conn, TLS_alert_handshake_failure);
			return -1;
		}

	}

	// format_print(stderr, 0, 0, "conn->cipher_suite: %s\n", tls_cipher_suite_name(conn->cipher_suite));

	if (tls_cipher_suite_get(conn->cipher_suite, &conn->cipher, &conn->digest) != 1) {
		error_print();
		return -1;
	}
	// digest_update(client_hello) until conn->hello_retry_request

	// status_request
	if (status_request) {
		int status_type;
		const uint8_t *responder_id_list;
		size_t responder_id_list_len;
		const uint8_t *request_exts;
		size_t request_exts_len;

		if (tls_client_status_request_from_bytes(&status_type,
			&responder_id_list, &responder_id_list_len,
			&request_exts, &request_exts_len,
			status_request, status_request_len) != 1) {
			error_print();
			return -1;
		}
		if (status_type != TLS_certificate_status_type_ocsp) {
			error_print();
			return -1;
		}
		if (conn->cert_chain) {
			const uint8_t *cp = conn->ctx->status_request_ocsp_responses;
			size_t len = conn->ctx->status_request_ocsp_responses_len;
			size_t i;

			// get ocsp_response
			for (i = 0; i < conn->cert_chain_idx; i++) {
				if (tls_uint24array_from_bytes(
					&conn->status_request_ocsp_response,
					&conn->status_request_ocsp_response_len,
					&cp, &len) != 1) {
					error_print();
					return -1;
				}
			}
			// check if ocsp_response match the status_request
			if (conn->status_request_ocsp_response) {
				if ((ret = tls_ocsp_response_match_status_request(
					conn->status_request_ocsp_response,
					conn->status_request_ocsp_response_len,
					responder_id_list, responder_id_list_len,
					request_exts, request_exts_len)) < 0) {
					error_print();
					return -1;
				} else if (ret == 0) {
					conn->status_request_ocsp_response = NULL;
					conn->status_request_ocsp_response_len = 0;
				}
			}
		}
		// send CertificateRequest.status_request
		conn->status_request = 1;
	}

	// signed_certificate_timestamp
	if (signed_certificate_timestamp) {
		if (conn->cert_chain) {
			const uint8_t *sct_lists = conn->ctx->signed_certificate_timestamp_lists;
			size_t sct_lists_len = conn->ctx->signed_certificate_timestamp_lists_len;
			size_t i;

			for (i = 0; i < conn->cert_chain_idx; i++) {
				if (tls_uint16array_from_bytes(
					&conn->signed_certificate_timestamp_list,
					&conn->signed_certificate_timestamp_list_len,
					&sct_lists, &sct_lists_len) != 1) {
					error_print();
					return -1;
				}
			}
		}
		// send CertificateRequest.signed_certificate_timestamp
		conn->signed_certificate_timestamp = 1;
	}

	// supported_groups
	if (supported_groups) {
		if ((ret = tls_process_supported_groups(
			supported_groups, supported_groups_len,
			conn->ctx->supported_groups, conn->ctx->supported_groups_cnt,
			common_groups, &common_groups_cnt,
			sizeof(common_groups)/sizeof(common_groups[0]))) < 0) {
			error_print();
			tls13_send_alert(conn, TLS_alert_decode_error);
			return -1;
		} else if (ret == 0) {
			common_key_exchange_modes &= ~(TLS_KE_CERT_DHE|TLS_KE_PSK_DHE);
		}
	}

	// key_share
	if (key_share) {
		int group = 0;
		const uint8_t *key_exchange = NULL;
		size_t key_exchange_len = 0;

		if (common_groups_cnt) {
			if ((ret = tls13_process_key_share_client_hello(
				key_share, key_share_len, common_groups, common_groups_cnt,
				&group, &key_exchange, &key_exchange_len)) < 0) {
				error_print();
				tls13_send_alert(conn, TLS_alert_decode_error);
				return -1;
			} else if (ret == 0) {
				// send HelloRetryRequest if modes == CERT_DHE|PSK_DHE
				conn->key_exchange_group = common_groups[0];
			} else {
				conn->key_exchange_group = group;
				memcpy(conn->peer_key_exchange, key_exchange, key_exchange_len);
				conn->peer_key_exchange_len = key_exchange_len;
			}
		}
	}

	// pre_shared_key
	if (pre_shared_key) {
		if (common_key_exchange_modes & (TLS_KE_PSK_DHE|TLS_KE_PSK)) {
			if (conn->psk_identities_len) {
				if ((ret = tls13_process_client_pre_shared_key_external(conn,
					pre_shared_key, pre_shared_key_len)) < 0) {
					error_print();
					return -1;
				} else if (ret == 0) {
					common_key_exchange_modes &= ~(TLS_KE_PSK_DHE|TLS_KE_PSK);
				}
			} else if (conn->ctx->session_ticket_key) {
				if ((ret = tls13_process_client_pre_shared_key_from_ticket(conn,
					pre_shared_key, pre_shared_key_len)) < 0) {
					error_print();
					return -1;
				} else if (ret == 0) {
					common_key_exchange_modes &= ~(TLS_KE_PSK_DHE|TLS_KE_PSK);
				}
			} else {
				// caller should set session_ticket_key or psk_keys
				error_print();
				return -1;
			}

			//format_print(stderr, 0, 0, "selected_psk_identity: %d\n", conn->selected_psk_identity - 1);
			//format_bytes(stderr, 0, 0, "selected_psk", conn->psk, conn->psk_len);
		}
	}

	/*
	decide the final key exchange mode and  hello_retry_request

	PSK_DHE
		* selected_psk_identity
		* key_exchange_group
		* [key_exchanges_cnt]

	PSK
		* selected_psk_identity

	CERT_DHE
		* cert_chain
		* key_exchange_group
		* [key_exchanges_cnt]
	*/
	if ((common_key_exchange_modes & TLS_KE_PSK_DHE) && conn->selected_psk_identity) {
		if (conn->key_exchange_group) {
			conn->key_exchange_modes = TLS_KE_PSK_DHE;
			if (!conn->peer_key_exchange_len) {
				conn->hello_retry_request = 1;
			}
		}
	} else if ((common_key_exchange_modes & TLS_KE_PSK) && conn->selected_psk_identity) {
		conn->key_exchange_modes = TLS_KE_PSK;
	} else if (common_key_exchange_modes & TLS_KE_CERT_DHE) {
		if (conn->cert_chain && conn->key_exchange_group) {
			conn->key_exchange_modes = TLS_KE_CERT_DHE;
		}
		if (!conn->peer_key_exchange_len) {
			conn->hello_retry_request = 1;
		}
	} else {
		error_print();
		tls13_send_alert(conn, TLS_alert_handshake_failure);
		return -1;
	}

	//tls_key_exchange_modes_print(stderr, 0, 0, "server key_exchange_mode", conn->key_exchange_modes);

	// hello_retry_request
	if (conn->hello_retry_request) {
		uint8_t message_hash[4 + 32];
		size_t dgstlen;

		// cache ClientHello1, need by recv_client_hello_again
		memcpy(conn->plain_record, conn->record, conn->recordlen);
		conn->plain_recordlen = conn->recordlen;


		// message_hash handshake
		message_hash[0] = TLS_handshake_message_hash;
		message_hash[1] = 0;
		message_hash[2] = 0;
		message_hash[3] = 32;

		if (digest_init(&conn->dgst_ctx, conn->digest) != 1
			|| digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1
			|| digest_finish(&conn->dgst_ctx, message_hash + 4, &dgstlen) != 1) {
			error_print();
			return -1;
		}
		if (digest_init(&conn->dgst_ctx, conn->digest) != 1
			|| digest_update(&conn->dgst_ctx, message_hash, sizeof(message_hash)) != 1) {
			error_print();
			return -1;
		}
	} else {
		if (digest_init(&conn->dgst_ctx, conn->digest) != 1
			|| 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);
	}

	// early_data
	conn->early_data =
		(conn->early_data) &&
		(conn->key_exchange_modes & (TLS_KE_PSK_DHE | TLS_KE_PSK)) &&
		(early_data) &&
		(conn->hello_retry_request == 0);

	// generate early_data keys
	if (conn->early_data) {
		if (tls13_generate_early_keys(conn) != 1) {
			error_print();
			return -1;
		}
	}

	if (client_verify)
		tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5);

	tls_clean_record(conn);

	return 1;
}

int tls13_send_hello_retry_request(TLS_CONNECT *conn)
{
	int ret;

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

	if (conn->recordlen == 0) {
		const uint8_t *legacy_session_id_echo = NULL;
		size_t legacy_session_id_echo_len = 0;
		int legacy_compress_meth = 0;
		uint8_t exts[256];
		uint8_t *pexts = exts;
		size_t extslen = 0;
		uint8_t cookie[256];
		size_t cookie_len;

		tls_record_set_protocol(conn->record, TLS_protocol_tls12);

		memcpy(conn->server_random, TLS13_HELLO_RETRY_REQUEST_RANDOM, 32);

		if (conn->session_id_len) {
			legacy_session_id_echo = conn->session_id;
			legacy_session_id_echo_len = conn->session_id_len;
		}

		// exts in HRR
		//  * supported_versions
		//  * key_share
		//  * [cookie]

		// supported_versions
		if (tls13_server_supported_versions_ext_to_bytes(
			TLS_protocol_tls13, &pexts, &extslen) != 1) {
			error_print();
			return -1;
		}

		// key_share
		if (tls13_key_share_hello_retry_request_ext_to_bytes(
			conn->key_exchange_group, &pexts, &extslen) != 1) {
			error_print();
			return -1;
		}

		// cookie
		if (conn->cookie) {
			// TODO: cookie = {ClientHello}
			if (tls13_cookie_generate(&conn->ctx->cookie_key, NULL, 0,
				cookie, &cookie_len) != 1) {
				error_print();
				return -1;
			}
			if (tls13_cookie_ext_to_bytes(
				cookie, sizeof(cookie), &pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		if (tls13_record_set_handshake_hello_retry_request(
			conn->record, &conn->recordlen,
			TLS_protocol_tls12, conn->server_random,
			legacy_session_id_echo, legacy_session_id_echo_len,
			conn->cipher_suite, legacy_compress_meth, exts, extslen) != 1) {
			error_print();
			return -1;
		}
		if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
	}

	if ((ret = tls_send_record(conn)) != 1) {
		if (ret != TLS_ERROR_SEND_AGAIN) {
			error_print();
		}
		return ret;
	}

	if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) {
		error_print();
		return -1;
	}

	if (conn->ctx->cacertslen) {
		tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5);
	}

	tls_clean_record(conn);

	return 1;
}

/*
 * 处理 HelloRetryRequest 之后客户端重新发送的 ClientHello。
 *
 * 旧实现按扩展在 ClientHello1 和 ClientHello2 中出现的顺序逐项比较。
 * 但合法客户端在 HRR 后可能调整扩展顺序，例如重新发送的 key_share
 * 可能移动到和第一次 ClientHello 不同的位置；顺序比较会把这种合法
 * ClientHello2 误判为非法并中止握手。
 *
 * 这里改为按扩展类型在 ClientHello1 中查找对应项，再分别校验 HRR
 * 允许变化的扩展：key_share 必须替换为服务端要求的组，pre_shared_key
 * 可以是第一次 identities 的子集，early_data 必须被删除，cookie 只在
 * 服务端要求时允许新增；其他扩展仍要求内容保持不变，同时拒绝重复扩展
 * 和不允许的扩展丢失。
 */
int tls13_recv_client_hello_again(TLS_CONNECT *conn)
{
	int ret;
	uint8_t *record = conn->record;

	int client_verify = 0;

	// ClientHello1
	int _legacy_version;
	const uint8_t *_random;
	const uint8_t *_legacy_session_id;
	size_t _legacy_session_id_len;
	const uint8_t *_cipher_suites;
	size_t _cipher_suites_len;
	const uint8_t *_exts;
	size_t _extslen;

	// ClientHello2
	int legacy_version;
	const uint8_t *random;
	const uint8_t *legacy_session_id;
	size_t legacy_session_id_len;
	const uint8_t *cipher_suites;
	size_t cipher_suites_len;
	const uint8_t *exts;
	size_t extslen;

	// Extensions
	const uint8_t *key_share = NULL;
	size_t key_share_len = 0;
	const uint8_t *pre_shared_key = NULL;
	size_t pre_shared_key_len = 0;
	const uint8_t *cookie = NULL;
	size_t cookie_len = 0;
	const uint8_t *client_hello1_exts;
	size_t client_hello1_exts_len;
	const uint8_t *client_hello2_exts;
	size_t client_hello2_exts_len;

	const uint8_t *key_exchange;
	size_t key_exchange_len;


	if ((ret = tls_recv_record(conn)) != 1) {
		if (ret != TLS_ERROR_RECV_AGAIN) {
			error_print();
		}
		return ret;
	}
	if(conn->verbose) tls_trace("recv ClientHello again\n");
	if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);

	if (tls_record_protocol(record) != TLS_protocol_tls1
		&& tls_record_protocol(record) != TLS_protocol_tls12) {
		error_print();
		tls13_send_alert(conn, TLS_alert_protocol_version);
		return -1;
	}
	if ((ret = tls_record_get_handshake_client_hello(conn->record,
		&legacy_version, &random, &legacy_session_id, &legacy_session_id_len,
		&cipher_suites, &cipher_suites_len, &exts, &extslen)) < 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	} else if (ret == 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_unexpected_message);
		return -1;
	}
	if (legacy_version != TLS_protocol_tls12) {
		error_print();
		tls13_send_alert(conn, TLS_alert_illegal_parameter);
		return -1;
	}

	// ClientHello1
	if (tls_record_get_handshake_client_hello(conn->plain_record,
		&_legacy_version, &_random, &_legacy_session_id, &_legacy_session_id_len,
		&_cipher_suites, &_cipher_suites_len, &_exts, &_extslen) != 1) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	}
	if (legacy_version != _legacy_version
		|| legacy_session_id_len != _legacy_session_id_len
		|| memcmp(legacy_session_id, _legacy_session_id, _legacy_session_id_len) != 0
		|| cipher_suites_len != _cipher_suites_len
		|| memcmp(cipher_suites, _cipher_suites, _cipher_suites_len) != 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_illegal_parameter);
		return -1;
	}
	// client random, should send the same random
	if (memcmp(random, conn->client_random, 32) != 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_illegal_parameter);
		return -1;
	}

	// update client_server
	memcpy(conn->client_random, random, 32);
	client_hello1_exts = _exts;
	client_hello1_exts_len = _extslen;
	client_hello2_exts = exts;
	client_hello2_exts_len = extslen;

	while (extslen) {
		int ext_type;
		const uint8_t *ext_data;
		size_t ext_datalen;
		const uint8_t *matching_ext_data = NULL;
		size_t matching_ext_datalen = 0;
		int matching_ext_found = 0;
		const uint8_t *search_exts = client_hello1_exts;
		size_t search_exts_len = client_hello1_exts_len;

		if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_datalen, &exts, &extslen) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_decode_error);
			return -1;
		}

		{
		const uint8_t *dup_exts = exts;
		size_t dup_exts_len = extslen;

		while (dup_exts_len) {
			int dup_ext_type;
			const uint8_t *dup_ext_data;
			size_t dup_ext_datalen;

			if (tls_ext_from_bytes(&dup_ext_type, &dup_ext_data, &dup_ext_datalen,
				&dup_exts, &dup_exts_len) != 1) {
				error_print();
				tls13_send_alert(conn, TLS_alert_decode_error);
				return -1;
			}
			if (dup_ext_type == ext_type) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
		}
		}

		// ClientHello2 extensions
		//	* key_share - must exist, only one key_exchange based on conn->key_exchange_group
		//	* pre_shared_key - might be subset of ClientHello1.pre_shared_key
		//	* early_data - must not exist
		//	* cookie - should exsit if conn->cookie == 1

		// early_data must not in ClientHello2
		if (ext_type == TLS_extension_early_data) {
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;
		}

		// cookie not in ClientHello1
		if (ext_type == TLS_extension_cookie) {
			if (!conn->cookie) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			if (!ext_data) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			cookie = ext_data;
			cookie_len = ext_datalen;
			continue;
		}

		// Find the corresponding ClientHello1 extension by type. The order
		// can change after HRR; early_data is intentionally omitted.
		while (search_exts_len) {
			int _ext_type;
			const uint8_t *_ext_data;
			size_t _ext_datalen;

			if (tls_ext_from_bytes(&_ext_type, &_ext_data, &_ext_datalen, &search_exts, &search_exts_len) != 1) {
				error_print();
				tls13_send_alert(conn, TLS_alert_decode_error);
				return -1;
			}

			if (_ext_type == TLS_extension_early_data) {
				continue;
			}
			if (ext_type == _ext_type) {
				matching_ext_data = _ext_data;
				matching_ext_datalen = _ext_datalen;
				matching_ext_found = 1;
				break;
			}
		}
		if (!matching_ext_found) {
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;
		}

		// check ext_data
		switch (ext_type) {
		case TLS_extension_key_share:
			if (!ext_data) {
				error_print();
				tls13_send_alert(conn, TLS_alert_decode_error);
				return -1;
			}
			if (key_share) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			key_share = ext_data;
			key_share_len = ext_datalen;
			break;

		case TLS_extension_pre_shared_key:
			{
			const uint8_t *psk_identities;
			size_t psk_identities_len;
			const uint8_t *binders;
			size_t binders_len;
			const uint8_t *_psk_identities;
			const uint8_t *_psk_identities_start;
			size_t _psk_identities_len;
			size_t _psk_identities_start_len;

			if (!ext_data) {
				error_print();
				tls13_send_alert(conn, TLS_alert_decode_error);
				return -1;
			}
			if (pre_shared_key) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
			if (tls13_client_pre_shared_key_from_bytes(&psk_identities, &psk_identities_len,
				&binders, &binders_len, ext_data, ext_datalen) != 1) {
				error_print();
				tls13_send_alert(conn, TLS_alert_decode_error);
				return -1;
			}
			if (tls13_client_pre_shared_key_from_bytes(&_psk_identities, &_psk_identities_len,
				&binders, &binders_len, matching_ext_data, matching_ext_datalen) != 1) {
				error_print();
				return -1;
			}
			_psk_identities_start = _psk_identities;
			_psk_identities_start_len = _psk_identities_len;
			while (psk_identities_len) {
				const uint8_t *id;
				size_t idlen;
				uint32_t age;
				const uint8_t *_id;
				size_t _idlen;
				int match = 0;
				_psk_identities = _psk_identities_start;
				_psk_identities_len = _psk_identities_start_len;

				if (tls13_psk_identity_from_bytes(&id, &idlen, &age, &psk_identities, &psk_identities_len) != 1) {
					error_print();
					tls13_send_alert(conn, TLS_alert_decode_error);
					return -1;
				}
				while (_psk_identities_len) {
					if (tls13_psk_identity_from_bytes(&_id, &_idlen, &age, &_psk_identities, &_psk_identities_len) != 1) {
						error_print();
						return -1;
					}
					if (idlen == _idlen && memcmp(id, _id, _idlen) == 0) {
						match = 1;
						break;
					}
				}
				if (!match) {
					error_print();
					tls13_send_alert(conn, TLS_alert_illegal_parameter);
					return -1;
				}
			}
			pre_shared_key = ext_data;
			pre_shared_key_len = ext_datalen;
			}
			break;

		default:
			if (ext_datalen != matching_ext_datalen
				|| (ext_datalen && memcmp(ext_data, matching_ext_data, matching_ext_datalen) != 0)) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
		}
	}

	// ClientHello2 must not drop any ClientHello1 extension except early_data.
	while (client_hello1_exts_len) {
		int _ext_type;
		const uint8_t *_ext_data;
		size_t _ext_datalen;
		const uint8_t *search_exts = client_hello2_exts;
		size_t search_exts_len = client_hello2_exts_len;
		int found = 0;

		if (tls_ext_from_bytes(&_ext_type, &_ext_data, &_ext_datalen,
			&client_hello1_exts, &client_hello1_exts_len) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_decode_error);
			return -1;
		}
		if (_ext_type == TLS_extension_early_data) {
			continue;
		}
		if (_ext_type == TLS_extension_key_share && key_share) {
			continue;
		}
		if (_ext_type == TLS_extension_pre_shared_key && pre_shared_key) {
			continue;
		}
		while (!found && search_exts_len) {
			int ext_type;
			const uint8_t *ext_data;
			size_t ext_datalen;

			if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_datalen, &search_exts, &search_exts_len) != 1) {
				error_print();
				tls13_send_alert(conn, TLS_alert_decode_error);
				return -1;
			}
			if (ext_type == _ext_type
				&& ext_datalen == _ext_datalen
				&& (!ext_datalen || memcmp(ext_data, _ext_data, _ext_datalen) == 0)) {
				found = 1;
			}
		}
		if (!found) {
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;
		}
	}

	// client must echo ClientHello1.cookie
	if (conn->cookie && !cookie) {
		error_print();
		tls13_send_alert(conn, TLS_alert_missing_extension);
		return -1;
	}

	// cookie
	if (cookie) {
		const uint8_t *cookie_data;
		size_t cookie_datalen;

		if (!conn->cookie) {
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;
		}
		if (tls13_cookie_from_bytes(&cookie_data, &cookie_datalen, cookie, cookie_len) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_decode_error);
			return -1;
		}
		if (tls13_cookie_verify(&conn->ctx->cookie_key, NULL, 0, cookie_data, cookie_datalen) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_illegal_parameter);
			return -1;
		}
	}

	// key_share
	if (tls13_process_key_share_client_hello_again(key_share, key_share_len,
		conn->key_exchange_group, &key_exchange, &key_exchange_len) != 1) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	}
	if (key_exchange_len != 65) {
		error_print();
		return -1;
	}
	memcpy(conn->peer_key_exchange, key_exchange, key_exchange_len);
	conn->peer_key_exchange_len = key_exchange_len;

	// pre_shared_key
	if (pre_shared_key) {
		if (conn->key_exchange_modes & (TLS_KE_PSK_DHE|TLS_KE_PSK)) {
			size_t selected_psk_identity = conn->selected_psk_identity;
			conn->selected_psk_identity = 0;

			if (conn->psk_identities_len) {
				if (tls13_process_client_pre_shared_key_external(conn,
					pre_shared_key, pre_shared_key_len) != 1) {
					tls13_send_alert(conn, TLS_alert_illegal_parameter);
					error_print();
					return -1;
				}
			} else if (conn->ctx->session_ticket_key) {
				if (tls13_process_client_pre_shared_key_from_ticket(conn,
					pre_shared_key, pre_shared_key_len) != 1) {
					error_print();
					tls13_send_alert(conn, TLS_alert_illegal_parameter);
					return -1;
				}
			}
			if (conn->selected_psk_identity != selected_psk_identity) {
				error_print();
				tls13_send_alert(conn, TLS_alert_illegal_parameter);
				return -1;
			}
		}
	}

	if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) {
		error_print();
		return -1;
	}

	if (client_verify)
		tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5);

	tls_clean_record(conn);
	return 1;
}

int tls13_send_server_hello(TLS_CONNECT *conn)
{
	int ret;

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

	if (conn->recordlen == 0) {
		uint8_t exts[256];// 256=> 需要的长度			
		uint8_t *pexts = exts;
		size_t extslen = 0;

		tls_record_set_protocol(conn->record, TLS_protocol_tls12);

		// server_random
		if (tls13_random_generate(conn->server_random) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_internal_error);
			return -1;
		}

		// exts in SH
		//  * supported_versions
		//  * key_share
		//  * pre_shared_key

		// supported_versions
		if (tls13_server_supported_versions_ext_to_bytes(
			conn->protocol, &pexts, &extslen) != 1) {
			error_print();
			return -1;
		}

		// key_share
		if (conn->key_exchange_modes & (TLS_KE_CERT_DHE|TLS_KE_PSK_DHE)) {
			int curve_oid;

			if (!conn->key_exchange_group) {
				error_print();
				return -1;
			}
			if ((curve_oid = tls_named_curve_oid(conn->key_exchange_group)) == OID_undef) {
				error_print();
				return -1;
			}
			if (x509_key_generate(&conn->key_exchanges[0],
				OID_ec_public_key, &curve_oid, sizeof(curve_oid)) != 1) {
				error_print();
				return -1;
			}
			conn->key_exchange_idx = 0;
			conn->key_exchanges_cnt = 1;
			if (tls13_key_share_server_hello_ext_to_bytes(
				&conn->key_exchanges[0], &pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		// pre_shared_key
		if (conn->selected_psk_identity) {
			if (tls13_server_pre_shared_key_ext_to_bytes(
				conn->selected_psk_identity, &pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		if (tls_record_set_handshake_server_hello(conn->record, &conn->recordlen,
			TLS_protocol_tls12, conn->server_random,
			conn->session_id, conn->session_id_len,
			conn->cipher_suite, exts, extslen) != 1) {
			error_print();
			return -1;
		}
		if(conn->verbose) tls13_record_print(stderr, 0, 0, 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 (tls13_generate_handshake_secrets(conn) != 1) {
			error_print();
			return -1;
		}
		tls13_generate_master_secret(conn);

		if (tls13_generate_server_handshake_keys(conn) != 1) {
			error_print();
			return -1;
		}
		if (!conn->early_data) {
			if (tls13_generate_client_handshake_keys(conn) != 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 tls13_send_alert(TLS_CONNECT *conn, int alert)
{
	int ret;
	size_t padding_len;

	if(conn->verbose) tls_trace("send {Alert}\n");

	if (conn->recordlen == 0) {
		tls_record_set_protocol(conn->plain_record, TLS_protocol_tls12);
		tls_record_set_alert(conn->plain_record, &conn->plain_recordlen, TLS_alert_level_fatal, alert);

		if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);


		switch (conn->handshake_state) {
		case TLS_state_client_hello:
		case TLS_state_server_hello:
		case TLS_state_hello_retry_request:
			memcpy(conn->record, conn->plain_record, conn->plain_recordlen);
			conn->recordlen = conn->plain_recordlen;
			break;
		default:
			tls13_padding_len_rand(&padding_len);
			if (tls13_record_encrypt(conn->cipher_suite, &conn->server_write_key, conn->server_write_iv,
				conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
				conn->record, &conn->recordlen) != 1) {
				error_print();
				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;
	}

	tls_clean_record(conn);
	return 1;
}

int tls13_send_encrypted_extensions(TLS_CONNECT *conn)
{
	int ret;
	if(conn->verbose) tls_trace("send {EncryptedExtensions}\n");

	if (conn->recordlen == 0) {
		uint8_t exts[256];
		uint8_t *pexts = exts;
		size_t extslen = 0;
		size_t padding_len;

		tls_record_set_protocol(conn->plain_record, TLS_protocol_tls12);

		// Exts in EE (see RFC 8446 page 37)
		//  * supported_groups
		//  * server_name
		//  * early_data
		//  * application_layer_protocol_negotiation
		//  * use_srtp
		//  * client_certificate_type
		//  * server_certificate_type
		//  * max_fragment_length
		//  * heartbeat
		//  * record_size_limit (RFC 8449)

		// supported_groups
		if (conn->key_exchange_modes & (TLS_KE_CERT_DHE|TLS_KE_PSK_DHE)) {
			if (tls_supported_groups_ext_to_bytes(conn->ctx->supported_groups,
				conn->ctx->supported_groups_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;
			}
		}

		// early_data
		//	ClientHello.early_data
		//	PSK_DHE or PSK
		//	no HelloRetryRequest
		if (conn->early_data) {
			if (tls_ext_to_bytes(TLS_extension_early_data, NULL, 0, &pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		// application_layer_protocol_negotiation
		if (conn->alpn_selected) {
			if (tls_application_layer_protocol_negotiation_selected_ext_to_bytes(
				conn->alpn_selected, &pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		if (tls13_record_set_handshake_encrypted_extensions(
			conn->plain_record, &conn->plain_recordlen,
			exts, extslen) != 1) {
			error_print();
			return -1;
		}
		if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
		digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5);


		if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "EncryptedExtensions", &conn->dgst_ctx);


		tls13_padding_len_rand(&padding_len);

		//format_print(stderr, 0, 0, "server_seq_num: "PRIu64"\n", GETU64(conn->server_seq_num));

		if (tls13_record_encrypt(conn->cipher_suite, &conn->server_write_key, conn->server_write_iv,
			conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
			conn->record, &conn->recordlen) != 1) {
			error_print();
			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;
	}


	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 tls13_send_certificate_request(TLS_CONNECT *conn)
{
	int ret;
	if(conn->verbose) tls_trace("send {CertificateRequest*}\n");

	if (conn->recordlen == 0) {
		const uint8_t *request_context = NULL;
		size_t request_context_len = 0;
		uint8_t exts[256];
		uint8_t *pexts = exts;
		size_t extslen = 0;
		size_t padding_len;

		// exts in CR (from RFC 8446 page 37)
		//  * signature_algorithms
		//  * signature_algorithms_cert
		//  * certificate_authorities
		//  * oid_filters
		//  * status_request
		//  * signed_certificate_timestamp

		// signature_algorithms
		if (!conn->ctx->signature_algorithms_cnt) {
			error_print();
			return -1;
		}
		// subset of ClientHello.signature_algorithms
		if (tls_signature_algorithms_ext_to_bytes(
			conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt,
			&pexts, &extslen) != 1) {
			error_print();
			return -1;
		}

		// signature_algorithms_cert, only when ClientHello.signature_algorithms_cert
		if (conn->signature_algorithms_cert) {
			if (tls13_signature_algorithms_cert_ext_to_bytes(
				conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt, &pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		// certificate_authorities 不应该默认发送吗？
		conn->certificate_authorities = 1;

		// certificate_authorities
		if (conn->certificate_authorities) {
			if (tls13_certificate_authorities_ext_to_bytes(
				conn->ctx->ca_names, conn->ctx->ca_names_len, &pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		// oid_filters
		if (conn->oid_filters) {
			if (tls13_oid_filters_ext_to_bytes(
				conn->ctx->oid_filters, conn->ctx->oid_filters_len, &pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		// status_request
		if (conn->status_request) {
			if (tls_ext_to_bytes(TLS_extension_status_request, NULL, 0, &pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		// signed_certificate_timestamp
		if (conn->signed_certificate_timestamp) {
			if (tls_ext_to_bytes(TLS_extension_signed_certificate_timestamp, NULL, 0, &pexts, &extslen) != 1) {
				error_print();
				return -1;
			}
		}

		if (tls13_record_set_handshake_certificate_request(
			conn->plain_record, &conn->plain_recordlen,
			request_context, request_context_len, exts, extslen) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_internal_error);
			return -1;
		}
		if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
			error_print();
			return -1;
		}
		if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);

		if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "after CertificateRequest", &conn->dgst_ctx);


		//format_print(stderr, 0, 0, "server_seq_num: "PRIu64"\n", GETU64(conn->server_seq_num));
		tls13_padding_len_rand(&padding_len);
		if (tls13_record_encrypt(conn->cipher_suite, &conn->server_write_key, conn->server_write_iv,
			conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
			conn->record, &conn->recordlen) != 1) {
			error_print();
			tls13_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 tls13_send_server_certificate(TLS_CONNECT *conn)
{
	int ret;

	if(conn->verbose) tls_trace("send server {Certificate}\n");

	if (conn->recordlen == 0) {
		const uint8_t *request_context = NULL;
		size_t request_context_len = 0;
		const uint8_t *entity_status_request_ocsp_response = NULL;
		size_t entity_status_request_ocsp_response_len = 0;
		const uint8_t *entity_signed_certificate_timestamp = NULL;
		size_t entity_signed_certificate_timestamp_len = 0;
		size_t padding_len;

		// status_request
		if (conn->status_request) {
			entity_status_request_ocsp_response = conn->status_request_ocsp_response;
			entity_status_request_ocsp_response_len = conn->status_request_ocsp_response_len;
		}
		// if ClientHello.status_request, CertificateRequest.status_request = 1

		// signed_certificate_timestamp
		if (conn->signed_certificate_timestamp) {
			entity_signed_certificate_timestamp = conn->signed_certificate_timestamp_list;
			entity_signed_certificate_timestamp_len = conn->signed_certificate_timestamp_list_len;
		}
		// if ClientHello.signed_certificate_timestamp, CertificateRequest.signed_certificate_timestamp = 1

		if (tls13_record_set_handshake_certificate(conn->plain_record, &conn->plain_recordlen,
			request_context, request_context_len,
			conn->cert_chain, conn->cert_chain_len,
			entity_status_request_ocsp_response, entity_status_request_ocsp_response_len,
			entity_signed_certificate_timestamp, entity_signed_certificate_timestamp_len) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_internal_error);
			return -1;
		}
		if(conn->verbose) tls13_record_print(stderr, 0, 0, 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, "ServerCertificate", &conn->dgst_ctx);

		tls13_padding_len_rand(&padding_len);
		if (tls13_record_encrypt(conn->cipher_suite, &conn->server_write_key, conn->server_write_iv,
			conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
			conn->record, &conn->recordlen) != 1) {
			error_print();
			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 tls13_send_server_certificate_verify(TLS_CONNECT *conn)
{
	int ret;

	if(conn->verbose) tls_trace("send server {CertificateVerify}\n");

	if (conn->recordlen == 0) {
		X509_KEY *sign_key = &conn->ctx->x509_keys[conn->cert_chain_idx - 1];
		uint8_t sig[SM2_MAX_SIGNATURE_SIZE];
		size_t siglen;
		size_t padding_len;

		if (tls13_sign_certificate_verify(TLS_server_mode, conn->sig_alg,
			sign_key, &conn->dgst_ctx, sig, &siglen) != 1) {
			error_print();
			return -1;
		}

		if (tls13_record_set_handshake_certificate_verify(
			conn->plain_record, &conn->plain_recordlen,
			conn->sig_alg, sig, siglen) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_internal_error);
			return -1;
		}
		if(conn->verbose) tls13_record_print(stderr, 0, 0, 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;
		}

		tls13_padding_len_rand(&padding_len);
		if (tls13_record_encrypt(conn->cipher_suite, &conn->server_write_key, conn->server_write_iv,
			conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
			conn->record, &conn->recordlen) != 1) {
			error_print();
			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 tls13_send_server_finished(TLS_CONNECT *conn)
{
	int ret;
	size_t padding_len;

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

	if (conn->recordlen == 0) {
		uint8_t verify_data[64];
		size_t verify_data_len;

		// compute server verify_data before digest_update()
		tls13_compute_verify_data(conn->server_handshake_traffic_secret,
			&conn->dgst_ctx, verify_data, &verify_data_len);

		if (tls13_record_set_handshake_finished(conn->plain_record, &conn->plain_recordlen,
			verify_data, verify_data_len) != 1) {
			error_print();
			return -1;
		}
		if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
			error_print();
			return -1;
		}
		if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);

		if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ServerFinished", &conn->dgst_ctx);


		//format_print(stderr, 0, 0, "server_seq_num: "PRIu64"\n", GETU64(conn->server_seq_num));
		tls13_padding_len_rand(&padding_len);
		if (tls13_record_encrypt(conn->cipher_suite, &conn->server_write_key, conn->server_write_iv,
			conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
			conn->record, &conn->recordlen) != 1) {
			error_print();
			return -1;
		}
		tls_seq_num_incr(conn->server_seq_num);

		tls13_generate_application_secrets(conn);

		tls13_generate_server_application_keys(conn);
	}

	if ((ret = tls_send_record(conn)) != 1) {
		if (ret != TLS_ERROR_SEND_AGAIN) {
			error_print();
		}
		return ret;
	}

	conn->record_offset = 0;
	conn->recordlen = 0;

	return 1;
}

int tls13_recv_client_certificate(TLS_CONNECT *conn)
{
	int ret;
	const uint8_t *request_context;
	size_t request_context_len;
	const uint8_t *status_request_ocsp_response = NULL;
	size_t status_request_ocsp_response_len = 0;
	const uint8_t *signed_certificate_timestamp = NULL;
	size_t signed_certificate_timestamp_len;
	const uint8_t *cert;
	size_t certlen;

	const int *signature_algorithms_cert = NULL;
	size_t signature_algorithms_cert_cnt = 0;
	const uint8_t *ca_names = NULL;
	size_t ca_names_len = 0;
	const uint8_t *oid_filters = NULL;
	size_t oid_filters_len = 0;

	int verify_result = X509_verify_ok;

	if ((ret = tls_recv_record(conn)) != 1) {
		if (ret != TLS_ERROR_RECV_AGAIN) {
			error_print();
		}
		return ret;
	}
	if(conn->verbose) tls_trace("recv client {Certificate*}\n");

	if (tls_record_protocol(conn->record) != TLS_protocol_tls12) {
		error_print();
		tls13_send_alert(conn, TLS_alert_protocol_version);
		return -1;
	}

	//format_print(stderr, 0, 0, "client_seq_num: "PRIu64"\n", GETU64(conn->client_seq_num));

	if (tls13_record_decrypt(conn->cipher_suite, &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();
		tls13_send_alert(conn, TLS_alert_bad_record_mac);
		return -1;
	}
	tls_seq_num_incr(conn->client_seq_num);

	if(conn->verbose) tls13_record_print(stderr, 0, 0, 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, "after client Certificate", &conn->dgst_ctx);


	if ((ret = tls13_record_get_handshake_certificate(conn->plain_record,
		&request_context, &request_context_len,
		conn->peer_cert_chain, &conn->peer_cert_chain_len, sizeof(conn->peer_cert_chain),
		&status_request_ocsp_response, &status_request_ocsp_response_len,
		&signed_certificate_timestamp, &signed_certificate_timestamp_len)) < 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	} else if (ret == 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_unexpected_message);
		return 0;
	}
	if (request_context) {
		error_print();
		tls13_send_alert(conn, TLS_alert_illegal_parameter);
		return -1;
	}

	if (!conn->peer_cert_chain_len) {
		if (!conn->ctx->client_certificate_optional) {
			error_print();
			tls13_send_alert(conn, TLS_alert_certificate_required);
			return -1;
		}
		return 0;
	}

	// client cert_chain match CertificateRequest extensions
	if (conn->signature_algorithms_cert) {
		signature_algorithms_cert = conn->ctx->signature_algorithms;
		signature_algorithms_cert_cnt = conn->ctx->signature_algorithms_cnt;
	}
	if (conn->certificate_authorities) {
		ca_names = conn->ctx->ca_names;
		ca_names_len = conn->ctx->ca_names_len;
	}
	if (conn->oid_filters) {
		oid_filters = conn->ctx->oid_filters;
		oid_filters_len = conn->ctx->oid_filters_len;
	}
	// verify client cert_chain
	ret = tls_cert_chain_verify(
		conn->protocol, X509_cert_chain_client, conn->cipher_suite,
		1,
		conn->peer_cert_chain, conn->peer_cert_chain_len,
		conn->ctx->cacerts, conn->ctx->cacertslen,
		NULL, 0,
		status_request_ocsp_response, status_request_ocsp_response_len,
		conn->ctx->verify_depth,
		NULL, 0,
		conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt,
		signature_algorithms_cert, signature_algorithms_cert_cnt,
		ca_names, ca_names_len,
		oid_filters, oid_filters_len,
		NULL, 0,
		&verify_result, NULL);
	if (ret < 0) {
		error_print();
		conn->verify_result = verify_result;
		tls13_send_alert(conn, TLS_alert_bad_certificate);
		return -1;
	}
	if (ret == 0) {
		error_print();
		conn->verify_result = verify_result;
		if (verify_result == X509_verify_err_crl
			|| verify_result == X509_verify_err_ocsp) {
			tls13_send_alert(conn, TLS_alert_certificate_revoked);
		} else {
			tls13_send_alert(conn, TLS_alert_bad_certificate);
		}
		return -1;
	}
	conn->verify_result = verify_result;
	// signed_certificate_timestamp
	if (signed_certificate_timestamp) {
		if (x509_certs_get_cert_by_index(conn->peer_cert_chain,
			conn->peer_cert_chain_len, 0, &cert, &certlen) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_bad_certificate);
			return -1;
		}
		if (tls13_signed_certificate_timestamp_verify(
			signed_certificate_timestamp, signed_certificate_timestamp_len,
			SCT_log_entry_type_x509_entry, NULL, cert, certlen,
			conn->ctx->ct_logs, conn->ctx->ct_logs_cnt,
			conn->ctx->ct_at_least) != 1) {
			error_print();
			tls13_send_alert(conn, TLS_alert_bad_certificate);
			return -1;
		}
	}

	return 1;
}

int tls13_recv_client_finished(TLS_CONNECT *conn)
{
	int ret;

	// Finished
	uint8_t local_verify_data[64];
	size_t local_verify_data_len;
	const uint8_t *verify_data;
	size_t verify_data_len;

	if ((ret = tls_recv_record(conn)) != 1) {
		if (ret != TLS_ERROR_RECV_AGAIN) {
			error_print();
		}
		return ret;
	}
	if(conn->verbose) tls_trace("recv client {Finished}\n");

	if (tls_record_protocol(conn->record) != TLS_protocol_tls12) {
		error_print();
		tls13_send_alert(conn, TLS_alert_protocol_version);
		return -1;
	}

	//format_print(stderr, 0, 0, "client_seq_num: "PRIu64"\n", GETU64(conn->client_seq_num));

	if (tls13_record_decrypt(conn->cipher_suite, &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();
		tls13_send_alert(conn, TLS_alert_bad_record_mac);
		return -1;
	}
	tls_seq_num_incr(conn->client_seq_num);

	if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);


	if ((ret = tls13_record_get_handshake_finished(conn->plain_record,
		&verify_data, &verify_data_len)) < 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decode_error);
		return -1;
	} else if (ret == 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_unexpected_message);
		return -1;
	}

	if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "before ClientFinished", &conn->dgst_ctx);

	if (tls13_compute_verify_data(conn->client_handshake_traffic_secret,
		&conn->dgst_ctx, local_verify_data, &local_verify_data_len) != 1) {
		error_print();
		return -1;
	}

	// 当客户端发送了Certificate的时候，这个验证是不对的
	// 服务器多发送了CertificateRequest
	// 客户端多发送了 Certificate, CertificateVerify

	if (local_verify_data_len != verify_data_len
		|| memcmp(local_verify_data, verify_data, verify_data_len) != 0) {
		error_print();
		tls13_send_alert(conn, TLS_alert_decrypt_error);
		return -1;
	}

	tls13_generate_client_application_keys(conn);
	if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
		error_print();
		return -1;
	}

	return 1;
}

int tls13_send_early_data(TLS_CONNECT *conn)
{
	if(conn->verbose) tls_trace("send EarlyData\n");

	if (!conn->early_data) {
		error_print();
		return -1;
	}
	if (!conn->early_data_len) {
		error_print();
		return -1;
	}

	while (conn->early_data_offset < conn->early_data_len) {
		int ret;
		if (conn->recordlen == 0) {
			uint8_t plain_record[TLS_MAX_RECORD_SIZE];
			size_t plain_recordlen;
			size_t datalen;
			size_t padding_len;

			datalen = conn->early_data_len - conn->early_data_offset;
			if (datalen > TLS_MAX_PLAINTEXT_SIZE) {
				datalen = TLS_MAX_PLAINTEXT_SIZE;
			}

			tls13_padding_len_rand(&padding_len);
			if (tls_record_set_application_data(plain_record, &plain_recordlen,
				conn->early_data_buf + conn->early_data_offset, datalen) != 1) {
				error_print();
				return -1;
			}
			if (tls13_record_encrypt(conn->cipher_suite, &conn->client_write_key, conn->client_write_iv,
				conn->client_seq_num, plain_record, plain_recordlen, padding_len,
				conn->record, &conn->recordlen) != 1) {
				error_print();
				return -1;
			}
			tls_seq_num_incr(conn->client_seq_num);

			conn->record_offset = 0;
			conn->sentlen = datalen;

			if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
		}

		if ((ret = tls_send_record(conn)) != 1) {
			if (ret == TLS_ERROR_SEND_AGAIN) {
				return ret;
			}
			error_print();
			return -1;
		}

		conn->early_data_offset += conn->sentlen;
		conn->record_offset = 0;
		conn->recordlen = 0;
	}

	conn->record_offset = 0;
	conn->recordlen = 0;

	return 1;
}

int tls13_send_client_key_update(TLS_CONNECT *conn, int request_update)
{
	int ret;

	if (conn->recordlen == 0) {
		size_t padding_len = 0;

		if(conn->verbose) tls_trace("send client {KeyUpdate}\n");

		if (tls13_record_set_handshake_key_update(conn->plain_record, &conn->plain_recordlen,
			request_update) != 1) {
			error_print();
			return -1;
		}
		if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);

		tls13_padding_len_rand(&padding_len);

		if (tls13_record_encrypt(conn->cipher_suite, &conn->client_write_key, conn->client_write_iv,
			conn->client_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
			conn->record, &conn->recordlen) != 1) {
			error_print();
			return -1;
		}

		// 这个很重要啊，但是record_encrypt没有设置这个值，这是很奇怪的				
		// xxxxxxxx
		conn->record_offset = 0;

		tls13_update_client_application_secret(conn);
		tls13_generate_client_application_keys(conn);

		conn->key_update = 0;

	}

	if ((ret = tls_send_record(conn)) != 1) {
		if (ret != TLS_ERROR_SEND_AGAIN && ret != TLS_ERROR_RECV_AGAIN) {
			error_print();
		}
	}

	if (ret == 1) {

		// 首先我们在发送数据的时候，应该根据offset是否已经达到末尾来判断数据是否完全发送
		// 其次在记录已经完全发送之后，应该自动的清空recordlen, offset这个数据

		conn->record_offset = 0;
		conn->recordlen = 0;
	}

	return ret;
}

int tls13_send_server_key_update(TLS_CONNECT *conn, int request_update)
{
	int ret;

	if (conn->recordlen == 0) {
		size_t padding_len = 0;

		if(conn->verbose) tls_trace("send server {KeyUpdate}\n");

		if (tls13_record_set_handshake_key_update(conn->plain_record, &conn->plain_recordlen,
			request_update) != 1) {
			error_print();
			return -1;
		}
		if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);

		tls13_padding_len_rand(&padding_len);
		if (tls13_record_encrypt(conn->cipher_suite, &conn->server_write_key, conn->server_write_iv,
			conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
			conn->record, &conn->recordlen) != 1) {
			error_print();
			return -1;
		}

		conn->record_offset = 0;

		tls13_update_server_application_secret(conn);
		tls13_generate_server_application_keys(conn);

		conn->key_update = 0;

	}


	if ((ret = tls_send_record(conn)) != 1) {
		if (ret != TLS_ERROR_SEND_AGAIN && ret != TLS_ERROR_RECV_AGAIN) {
			error_print();
		}
	}

	if (ret == 1) {

		// 首先我们在发送数据的时候，应该根据offset是否已经达到末尾来判断数据是否完全发送
		// 其次在记录已经完全发送之后，应该自动的清空recordlen, offset这个数据

		conn->record_offset = 0;
		conn->recordlen = 0;
	}

	return ret;


}

int tls13_do_client_handshake(TLS_CONNECT *conn)
{
	int ret;
	int next_state;

	switch (conn->handshake_state) {
	case TLS_state_hello_retry_request:
	case TLS_state_client_hello_again:
	case TLS_state_server_hello:
	case TLS_state_encrypted_extensions:
		if (conn->early_data && conn->early_data_offset < conn->early_data_len) {
			if(conn->verbose) tls_trace("send EarlyData\n");
			if (tls13_send_early_data(conn) != 1) {
				error_print();
				return -1;
			}
		}
		break;
	}

	switch (conn->handshake_state) {
	case TLS_state_client_hello:
		ret = tls13_send_client_hello(conn);
		next_state = TLS_state_hello_retry_request;
		break;

	case TLS_state_hello_retry_request: // optional
		ret = tls13_recv_hello_retry_request(conn);
		if (conn->hello_retry_request)
			next_state = TLS_state_client_hello_again;
		else	next_state = TLS_state_server_hello;
		break;

	case TLS_state_client_hello_again:
		ret = tls13_send_client_hello_again(conn);
		next_state = TLS_state_server_hello;
		break;

	case TLS_state_server_hello:
		ret = tls13_recv_server_hello(conn);
		if (tls13_ctx_accept_change_cipher_spec(conn->ctx))
			next_state = TLS_state_server_change_cipher_spec;
		else	next_state = TLS_state_encrypted_extensions;
		break;

	case TLS_state_server_change_cipher_spec:
		ret = tls13_recv_change_cipher_spec_if_present(conn);
		next_state = TLS_state_encrypted_extensions;
		break;

	case TLS_state_encrypted_extensions:
		ret = tls13_recv_encrypted_extensions(conn);
		next_state = TLS_state_certificate_request;
		break;

	case TLS_state_certificate_request: // optional
		ret = tls13_recv_certificate_request(conn);
		if (conn->key_exchange_modes == TLS_KE_CERT_DHE)
			next_state = TLS_state_server_certificate;
		else	next_state = TLS_state_server_finished;
		break;

	case TLS_state_server_certificate:
		ret = tls13_recv_server_certificate(conn);
		next_state = TLS_state_certificate_verify;
		break;

	case TLS_state_certificate_verify:
		ret = tls13_recv_server_certificate_verify(conn);
		next_state = TLS_state_server_finished;
		break;

	case TLS_state_server_finished:
		ret = tls13_recv_server_finished(conn);
		if (conn->early_data)
			next_state = TLS_state_end_of_early_data;
		else if (conn->certificate_request)
			next_state = TLS_state_client_certificate;
		else	next_state = TLS_state_client_change_cipher_spec;
		break;

	case TLS_state_end_of_early_data:
		ret = tls13_send_end_of_early_data(conn);
		next_state = TLS_state_client_change_cipher_spec;
		break;

	case TLS_state_client_certificate:
		// if client has no (proper) certificate
		// client will send {Certificate} with empty certificate_list
		// but will not send {CertificateVerify}
		ret = tls13_send_client_certificate(conn);
		if (conn->cert_chain)
			next_state = TLS_state_client_certificate_verify;
		else	next_state = TLS_state_client_change_cipher_spec;
		break;

	case TLS_state_client_certificate_verify:
		ret = tls13_send_client_certificate_verify(conn);
		next_state = TLS_state_client_change_cipher_spec;
		break;

	case TLS_state_client_change_cipher_spec:
		if (tls13_ctx_change_cipher_spec_compat(conn->ctx))
			ret = tls13_send_change_cipher_spec(conn);
		else	ret = 1;
		next_state = TLS_state_client_finished;
		break;

	case TLS_state_client_finished:
		ret = tls13_send_client_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 tls13_do_server_handshake(TLS_CONNECT *conn)
{
	int ret;
	int state = conn->handshake_state;
	int next_state;

	switch (conn->handshake_state) {
	case TLS_state_client_hello:
		ret = tls13_recv_client_hello(conn);
		if (conn->early_data)
			next_state = TLS_state_early_data;
		else if (conn->hello_retry_request)
			next_state = TLS_state_hello_retry_request;
		else	next_state = TLS_state_server_hello;
		break;

	case TLS_state_early_data:
		ret = tls13_recv_early_data(conn);
		next_state = TLS_state_server_hello;
		break;

	case TLS_state_hello_retry_request:
		ret = tls13_send_hello_retry_request(conn);
		next_state = TLS_state_client_hello_again;
		break;

	case TLS_state_client_hello_again:
		ret = tls13_recv_client_hello_again(conn);
		next_state = TLS_state_server_hello;
		break;

	case TLS_state_server_hello:
		ret = tls13_send_server_hello(conn);
		if (tls13_ctx_change_cipher_spec_compat(conn->ctx))
			next_state = TLS_state_server_change_cipher_spec;
		else	next_state = TLS_state_encrypted_extensions;
		break;

	case TLS_state_server_change_cipher_spec:
		ret = tls13_send_change_cipher_spec(conn);
		next_state = TLS_state_encrypted_extensions;
		break;

	case TLS_state_encrypted_extensions:
		ret = tls13_send_encrypted_extensions(conn);
		if (conn->certificate_request)
			next_state = TLS_state_certificate_request;
		else if (conn->key_exchange_modes == TLS_KE_CERT_DHE)
			next_state = TLS_state_server_certificate;
		else	next_state = TLS_state_server_finished;
		break;

	case TLS_state_certificate_request:
		ret = tls13_send_certificate_request(conn);
		if (conn->key_exchange_modes == TLS_KE_CERT_DHE)
			next_state = TLS_state_server_certificate;
		else	next_state = TLS_state_server_finished;
		break;

	case TLS_state_server_certificate:
		ret = tls13_send_server_certificate(conn);
		next_state = TLS_state_certificate_verify;
		break;
	case TLS_state_certificate_verify:
		ret = tls13_send_server_certificate_verify(conn);
		next_state = TLS_state_server_finished;
		break;

	case TLS_state_server_finished:
		ret = tls13_send_server_finished(conn);
		if (conn->early_data)
			next_state = TLS_state_end_of_early_data;
		else if (conn->certificate_request)
			next_state = TLS_state_client_certificate;
		else	next_state = TLS_state_client_change_cipher_spec;
		break;

	case TLS_state_end_of_early_data:
		ret = tls13_recv_end_of_early_data(conn);
		next_state = TLS_state_client_change_cipher_spec;
		break;

	case TLS_state_client_certificate:
		ret = tls13_recv_client_certificate(conn);
		if (ret == 0) // 客户端提供了一个空的Certificate消息
			next_state = TLS_state_client_change_cipher_spec;
		else	next_state = TLS_state_client_certificate_verify;
		break;

	case TLS_state_client_certificate_verify:
		ret = tls13_recv_client_certificate_verify(conn);
		next_state = TLS_state_client_change_cipher_spec;
		break;

	case TLS_state_client_change_cipher_spec:
		if (tls13_ctx_accept_change_cipher_spec(conn->ctx))
			ret = tls13_recv_change_cipher_spec_if_present(conn);
		else	ret = 1;
		next_state = TLS_state_client_finished;
		break;

	case TLS_state_client_finished:
		ret = tls13_recv_client_finished(conn);
		if (conn->new_session_ticket)
			next_state = TLS_state_new_session_ticket;
		else	next_state = TLS_state_handshake_over;
		break;

	case TLS_state_new_session_ticket:
		if (conn->new_session_ticket) {
			ret = tls13_send_new_session_ticket(conn);
			next_state = TLS_state_new_session_ticket;
		} else {
			ret = 1;
			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;

	if (!(state == TLS_state_client_change_cipher_spec && ret == 0)) {
		tls_clean_record(conn);
	}

	return 1;
}

int tls13_client_handshake(TLS_CONNECT *conn)
{
	int ret;

	while (conn->handshake_state != TLS_state_handshake_over) {

		ret = tls13_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 tls13_server_handshake(TLS_CONNECT *conn)
{
	int ret;

	while (conn->handshake_state != TLS_state_handshake_over) {

		ret = tls13_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 tls13_do_connect(TLS_CONNECT *conn)
{
	int ret;

	if (!conn || !conn->is_client) {
		error_print();
		return -1;
	}

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

	ret = tls13_client_handshake(conn);
	if (ret == 1) {
		conn->handshake_state = TLS_state_handshake_over;
		return 1;
	}
	if (ret == TLS_ERROR_RECV_AGAIN || ret == TLS_ERROR_SEND_AGAIN) {
		return ret;
	}

	error_print();
	return -1;
}

int tls13_do_accept(TLS_CONNECT *conn)
{
	int ret;

	if (!conn || conn->is_client) {
		error_print();
		return -1;
	}

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

	ret = tls13_server_handshake(conn);
	if (ret == 1) {
		conn->handshake_state = TLS_state_handshake_over;
		return 1;
	}
	if (ret == TLS_ERROR_RECV_AGAIN || ret == TLS_ERROR_SEND_AGAIN) {
		return ret;
	}

	error_print();
	return -1;
}
