Files
GmSSL/src/tls13.c
2026-04-28 11:50:15 +08:00

8516 lines
219 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <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>
static const int tls13_ciphers[] = { TLS_cipher_sm4_gcm_sm3 };
static size_t tls13_ciphers_count = sizeof(tls13_ciphers)/sizeof(int);
static int tls13_client_hello_exts[] = {
TLS_extension_supported_versions,
TLS_extension_padding,
};
int tls13_random_generate(uint8_t random[32])
{
if (rand_bytes(random, 32) != 1) {
error_print();
return -1;
}
return 1;
}
int tls13_cipher_suite_get(int cipher_suite, const BLOCK_CIPHER **cipher, const DIGEST **digest)
{
switch (cipher_suite) {
case TLS_cipher_sm4_gcm_sm3:
*digest = DIGEST_sm3();
*cipher = BLOCK_CIPHER_sm4();
break;
#if defined(ENABLE_AES) && defined(ENABLE_SHA2)
case TLS_cipher_aes_128_gcm_sha256:
*digest = DIGEST_sha256();
*cipher = BLOCK_CIPHER_aes128();
break;
#endif
default:
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;
return 1;
}
int gcm_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *iv, size_t ivlen,
const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen,
uint8_t *out, size_t taglen, uint8_t *tag)
{
if (key->cipher == BLOCK_CIPHER_sm4()) {
if (sm4_gcm_encrypt(&(key->u.sm4_key), iv, ivlen, aad, aadlen, in, inlen, out, taglen, tag) != 1) {
error_print();
return -1;
}
// 避免在tls13.c中引入宏
#ifdef ENABLE_AES
} else if (key->cipher == BLOCK_CIPHER_aes128()) {
if (aes_gcm_encrypt(&(key->u.aes_key), iv, ivlen, aad, aadlen, in, inlen, out, taglen, tag) != 1) {
error_print();
return -1;
}
#endif
} else {
error_print();
return -1;
}
return 1;
}
int gcm_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *iv, size_t ivlen,
const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen,
const uint8_t *tag, size_t taglen, uint8_t *out)
{
if (key->cipher == BLOCK_CIPHER_sm4()) {
if (sm4_gcm_decrypt(&(key->u.sm4_key), iv, ivlen, aad, aadlen, in, inlen, tag, taglen, out) != 1) {
error_print();
return -1;
}
#ifdef ENABLE_AES
} else if (key->cipher == BLOCK_CIPHER_aes128()) {
if (aes_gcm_decrypt(&(key->u.aes_key), iv, ivlen, aad, aadlen, in, inlen, tag, taglen, out) != 1) {
error_print();
return -1;
}
#endif
} else {
error_print();
return -1;
}
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; // FIXME: update gcm_encrypt API
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;
if (gcm_encrypt(key, nonce, sizeof(nonce), aad, sizeof(aad), mbuf, mlen, out, 16, gmac) != 1) {
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;
if (gcm_decrypt(key, nonce, 12, aad, 5, in, mlen, gmac, GHASH_SIZE, out) != 1) {
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;
}
int tls13_record_encrypt(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)
{
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;
}
// 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(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;
if (tls13_gcm_decrypt(key, iv,
seq_num, enced_record + 5, enced_recordlen - 5,
&record_type, record + 5, recordlen) != 1) {
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;
}
/*
KeyUpate的流程
客户端发现需要KeyUpdate 可能是C->S 或者C <- S某个方向需要
如果是自己方向的需要更新或者对方需要更新那么就一定要发送KeyUpdate
如果对方不需要更新,那么不要求对方更新
客户端更新自己的密钥
服务器端在收到通知后,更新客户端的密钥
服务器端查看是否要求自己也更新密钥,如果要求
因此向客户端发送KeyUpdate
注意因为客户端的密钥刚更新过,作为响应方的服务器一定不能要求对方再更新了
客户端接受到服务器的请求,如果自己才刚刚更新过,就不再发送反馈了
这里一个主要的状态判断是,
某一方在接收到对方的KeyUpdate请求后是否响。
*/
int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *sentlen)
{
int key_update = 0;
tls_trace("send {ApplicationData}\n");
format_print(stderr, 0, 0, "data = %p, datalen = %zu\n", data, datalen);
*sentlen = 0;
if (!conn->recordlen) {
const BLOCK_CIPHER_KEY *key;
const uint8_t *iv;
uint8_t *seq_num;
size_t padding_len = 0;
size_t record_datalen;
if (!data || !datalen) {
return 0;
}
if (datalen > TLS_MAX_PLAINTEXT_SIZE) {
datalen = TLS_MAX_PLAINTEXT_SIZE;
}
if (conn->is_client) {
key = &conn->client_write_key;
iv = conn->client_write_iv;
seq_num = conn->client_seq_num;
} else {
key = &conn->server_write_key;
iv = conn->server_write_iv;
seq_num = conn->server_seq_num;
}
tls13_padding_len_rand(&padding_len);
if (tls13_gcm_encrypt(key, iv,
seq_num, TLS_record_application_data, data, datalen, padding_len,
conn->record + 5, &record_datalen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(seq_num);
tls_record_set_type(conn->record, TLS_record_application_data);
tls_record_set_protocol(conn->record, TLS_protocol_tls12);
tls_record_set_data_length(conn->record, record_datalen);
conn->recordlen = 5 + record_datalen;
conn->record_offset = 0;
conn->plain_recordlen = datalen + 5;
/*
KeyUpdate有两个原因
* 我们自己检查应该KeyUpdate了那么发送KeyUpdate并且要求对方也Update
* 对方要求KeyUpdate那么我们只是通知对方我方KeyUPdate不要求对方再次Update
*/
// check if KeyUpdate
if (GETU64(seq_num) >= conn->ctx->key_update_seq_num_limit) {
key_update = 1;
}
}
while (conn->recordlen) {
tls_ret_t n;
if ((n = tls_socket_send(conn->sock, conn->record + conn->record_offset, conn->recordlen, 0)) <= 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
return EAGAIN;
} else {
if (n == 0) {
error_puts("TCP connection closed");
}
error_print();
return -1;
}
}
conn->recordlen -= n;
conn->record_offset += n;
}
if (key_update) {
int ret;
if (conn->is_client) {
if ((ret = tls13_send_client_key_update(conn, 1)) <= 0) {
if (ret == TLS_ERROR_SEND_AGAIN) {
return ret;
}
} else {
error_print();
return -1;
}
} else {
if ((ret = tls13_send_server_key_update(conn, 1)) <= 0) {
if (ret == TLS_ERROR_SEND_AGAIN) {
return ret;
}
} else {
error_print();
return -1;
}
}
}
*sentlen = conn->plain_recordlen - 5;
return 1;
}
int tls13_do_recv(TLS_CONNECT *conn)
{
tls_ret_t n;
const BLOCK_CIPHER_KEY *key;
const uint8_t *iv;
uint8_t *seq_num;
tls_trace("recv {ApplicationData}\n");
switch (conn->state) {
case 0:
conn->record_offset = 0;
conn->recordlen = TLS_RECORD_HEADER_SIZE;
conn->state = TLS_state_recv_record_header;
case TLS_state_recv_record_header:
while (conn->recordlen) {
if ((n = tls_socket_recv(conn->sock, conn->record + conn->record_offset, conn->recordlen, 0)) <= 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
return TLS_ERROR_RECV_AGAIN;
} else {
error_print();
return -1;
}
}
conn->recordlen -= 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;
}
conn->recordlen = tls_record_length(conn->record);
conn->state = TLS_state_recv_record_data;
case TLS_state_recv_record_data:
while (conn->recordlen) {
if ((n = tls_socket_recv(conn->sock, conn->record + conn->record_offset, conn->recordlen, 0)) <= 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
return TLS_ERROR_RECV_AGAIN;
} else {
error_print();
return -1;
}
}
conn->recordlen -= n;
}
conn->state = 0;
break;
default:
error_print();
return -1;
}
conn->recordlen = tls_record_length(conn->record) + TLS_RECORD_HEADER_SIZE;
// 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;
} else {
key = &conn->client_write_key;
iv = conn->client_write_iv;
seq_num = conn->client_seq_num;
}
if (tls13_record_decrypt(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);
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;
}
break;
case TLS_handshake_key_update:
if (tls13_record_get_handshake_key_update(conn->plain_record, &update_requested) != 1) {
error_print();
return -1;
}
// 对方的密钥已经更新了,我方必须更新
// 但是我方密钥是否更新以及发送KeyUpdate通知呢要看当前密钥使用了多久
if (conn->is_client) {
uint64_t seq_num;
int ret;
tls13_update_server_application_keys(conn);
seq_num = GETU64(conn->client_seq_num);
if (seq_num > 1 && update_requested) {
if ((ret = tls13_send_client_key_update(conn, 0)) <= 0) {
if (ret == TLS_ERROR_SEND_AGAIN) {
return ret;
}
}
}
} else {
uint64_t seq_num;
int ret;
tls13_update_client_application_keys(conn);
seq_num = GETU64(conn->server_seq_num);
if (seq_num > 1 && update_requested) {
if ((ret = tls13_send_server_key_update(conn, 0)) <= 0) {
if (ret == TLS_ERROR_SEND_AGAIN) {
return ret;
} else {
error_print();
return -1;
}
}
}
}
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;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
}
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;
}
if (conn->datalen == 0) {
int ret;
if ((ret = tls13_do_recv(conn)) != 1) {
if (ret) error_print();
return ret;
}
}
*recvlen = outlen <= conn->datalen ? outlen : conn->datalen;
memcpy(out, conn->data, *recvlen);
conn->data += *recvlen;
conn->datalen -= *recvlen;
return 1;
}
// 这里需要考虑max_early_data_size的问题
int tls13_recv_early_data(TLS_CONNECT *conn)
{
tls_trace("recv EarlyData\n");
if (tls13_do_recv(conn) != 1) {
error_print();
return -1;
}
memcpy(conn->early_data_buf, conn->data, conn->datalen);
conn->early_data_len = conn->datalen;
format_string(stderr, 0, 4, "EarlyData", conn->early_data_buf, conn->early_data_len);
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; }
Derive-Secret(Secret, Label, Messages) =
HKDF-Expand-Label(Secret, Label, Hash(Messages), Hash.length)
*/
int tls13_hkdf_extract(const DIGEST *digest, const uint8_t salt[32], const uint8_t in[32], uint8_t out[32])
{
size_t dgstlen;
if (hkdf_extract(digest, salt, 32, in, 32, out, &dgstlen) != 1
|| dgstlen != 32) {
error_print();
return -1;
}
return 1;
}
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 label_len;
uint8_t hkdf_label[2 + 256 + 256];
uint8_t *p = hkdf_label;
size_t hkdf_label_len = 0;
label_len = (uint8_t)(strlen("tls13 ") + strlen(label)); //FIXME: check length < 255
tls_uint16_to_bytes((uint16_t)outlen, &p, &hkdf_label_len);
tls_uint8_to_bytes(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, 32, hkdf_label, hkdf_label_len, outlen, out);
return 1;
}
// 输入参数都需要提供长度
int tls13_derive_secret(const uint8_t secret[32], const char *label, const DIGEST_CTX *dgst_ctx, uint8_t out[32])
{
DIGEST_CTX ctx = *dgst_ctx;
uint8_t dgst[64];
size_t dgstlen;
if (digest_finish(&ctx, dgst, &dgstlen) != 1
|| tls13_hkdf_expand_label(dgst_ctx->digest, secret, label, dgst, 32, dgstlen, out) != 1) {
error_print();
return -1;
}
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, 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;
}
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;
}
if (x509_verify_init(&sign_ctx, public_key, 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;
}
/*
verify_data in Finished
finished_key =
HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)
Structure of this message:
struct {
opaque verify_data[Hash.length];
} Finished;
The verify_data value is computed as follows:
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 temp_dgst_ctx;
uint8_t dgst[64];
size_t dgstlen;
uint8_t finished_key[64];
size_t finished_key_len;
temp_dgst_ctx = *dgst_ctx;
digest_finish(&temp_dgst_ctx, dgst, &dgstlen);
finished_key_len = dgstlen;
tls13_hkdf_expand_label(dgst_ctx->digest, handshake_traffic_secret,
"finished", NULL, 0, finished_key_len, finished_key);
hmac(dgst_ctx->digest, finished_key, finished_key_len, dgst, dgstlen, verify_data, verify_data_len);
return 1;
}
/*
CertificateEntry {
select (certificate_type) {
case X509: opaque cert_data<1..2^24-1>; // DER编码的X.509证书
};
Extension extensions<0..2^16-1>; // 这个证书的扩展列表
}
*/
int tls13_cert_list_get_count(const uint8_t *d, size_t dlen, size_t *cnt)
{
int ret;
ret = asn1_types_get_count(d, dlen, ASN1_TAG_SEQUENCE, cnt);
if (ret < 0) error_print();
return ret;
}
int tls13_cert_list_get_cert_by_index(const uint8_t *d, size_t dlen, int index, const uint8_t **cert, size_t *certlen)
{
int i = 0;
if (index < 0) {
error_print();
return -1;
}
while (dlen) {
if (x509_cert_from_der(cert, certlen, &d, &dlen) != 1) {
error_print();
return -1;
}
if (i++ == index) {
return 1;
}
}
*cert = NULL;
*certlen = 0;
return 0;
}
int tls13_cert_list_get_last(const uint8_t *d, size_t dlen, const uint8_t **cert, size_t *certlen)
{
if (dlen == 0) {
return 0;
}
while (dlen) {
if (x509_cert_from_der(cert, certlen, &d, &dlen) != 1) {
error_print();
return -1;
}
}
return 1;
}
// extensions
// 这个函数需要测试一下看看是否支持ext_data == NULL ext_datalen != 0时可以只输出头部并正确的修改输出长度
int tls_ext_to_bytes(int ext_type, const uint8_t *ext_data, size_t ext_datalen,
uint8_t **out, size_t *outlen)
{
tls_uint16_to_bytes(ext_type, out, outlen);
tls_uint16array_to_bytes(ext_data, ext_datalen, out, outlen);
return 1;
}
/*
struct {
ProtocolVersion versions<2..254>;
} SupportedVersions; -- in ClientHello
*/
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;
size_t i;
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_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;
}
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;
}
/*
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;
}
*group = named_curve;
if (!tls_named_curve_name(named_curve)) {
error_print();
return -1;
}
if (*key_exchange_len != 65) {
error_print();
return -1;
}
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;
}
/*
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;
size_t ext_datalen;
size_t authorities_len;
const uint8_t *name;
size_t namelen;
const uint8_t *p;
size_t len;
p = ca_names;
len = ca_names_len;
authorities_len = 0;
while (len) {
if (x509_name_from_der(&name, &namelen, &p, &len) != 1) {
error_print();
return -1;
}
tls_uint16array_to_bytes(name, namelen, NULL, &authorities_len);
}
if (authorities_len < 3 || authorities_len > (1 << 16) - 1) {
error_print();
return -1;
}
ext_datalen = tls_uint16_size() + authorities_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)authorities_len, out, outlen);
while (ca_names_len) {
x509_name_from_der(&name, &namelen, &ca_names, &ca_names_len);
tls_uint16array_to_bytes(name, namelen, 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)
{
if (!conn) {
error_print();
return -1;
}
if (!conn->ctx->cacertslen) {
error_print();
return -1;
}
conn->certificate_authorities = 1;
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;
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 *dn;
size_t dn_len;
if (tls_uint16array_from_bytes(&dn, &dn_len, &authorities, &authorities_len) != 1) {
error_print();
return -1;
}
x509_name_print(fp, fmt, ind, "DistinguishedName", dn, dn_len);
}
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(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)
{
return 1;
}
/*
struct {
opaque certificate_request_context<0..2^8-1>;
Extension extensions<2..2^16-1>;
} CertificateRequest;
certificate_request_context 用于 Post-handshake Authentication否则应该长度为0
*/
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 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;
}
format_print(fp, fmt, ind, "%s (%d)\n", tls_extension_name(ext_type), 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_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_print(fp, fmt, ind + 4, "signed_certificate_timestamp\n");
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_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);
//error_print();
//return -1;
}
}
if (dlen) {
error_print();
return -1;
}
return 1;
}
int tls13_server_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;
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 (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_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);
return -1;
}
}
if (dlen) {
error_print();
return -1;
}
return 1;
}
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;
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) {
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_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;
}
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:
default:
format_bytes(fp, fmt, ind, "raw_data", ext_data, ext_datalen);
}
}
if (dlen) {
error_print();
return -1;
}
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:
case TLS_extension_signed_certificate_timestamp:
case TLS_extension_server_certificate_type:
case TLS_extension_client_certificate_type:
break;
default:
error_print();
return -1;
}
}
}
if (dlen) {
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;
}
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;
}
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_message_hash_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
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;
}
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;
case TLS_handshake_message_hash:
tls13_message_hash_print(fp, fmt, ind, data, datalen);
break;
default:
error_print();
return -1;
}
return 1;
}
int tls13_record_print(FILE *fp, int format, int indent, const uint8_t *record, size_t recordlen)
{
const uint8_t *data;
size_t datalen;
int protocol;
format |= TLS_cipher_sm4_gcm_sm3 << 8;
if (!fp || !record || recordlen < 5) {
error_print();
return -1;
}
protocol = tls_record_protocol(record);
format_print(fp, format, indent, "Record\n"); indent += 4;
format_print(fp, format, indent, "ContentType: %s (%d)\n", tls_record_type_name(record[0]), record[0]);
format_print(fp, format, indent, "Version: %s (%04x)\n", tls_protocol_name(protocol), protocol);
format_print(fp, format, indent, "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;
}
// 最高字节设置后强制打印记录原始数据
if (format >> 24) {
format_bytes(fp, format, indent, "Data", data, datalen);
fprintf(fp, "\n");
return 1;
}
switch (record[0]) {
case TLS_record_handshake:
tls13_handshake_print(fp, format, indent, data, datalen);
break;
case TLS_record_alert:
if (tls_alert_print(fp, data, datalen, format, indent) != 1) {
error_print();
return -1;
}
break;
case TLS_record_change_cipher_spec:
if (tls_change_cipher_spec_print(fp, data, datalen, format, indent) != 1) {
error_print();
return -1;
}
break;
case TLS_record_application_data:
if (tls_application_data_print(fp, data, datalen, format, indent) != 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;
}
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;
}
// 1. client_hello
// 2. server_hello
/*
int tls13_record_set_handshake_hello_retry_request(uint8_t *record, size_t *recordlen,
int protocol, const uint8_t random[32],
const uint8_t *session_id, size_t session_id_len, int cipher_suite,
const uint8_t *exts, size_t exts_len)
{
uint8_t type = TLS_handshake_hello_retry_request;
uint8_t *p;
size_t len;
if (!record || !recordlen || !random) {
error_print();
return -1;
}
if (session_id) {
if (session_id_len == 0
|| session_id_len < TLS_MIN_SESSION_ID_SIZE
|| session_id_len > TLS_MAX_SESSION_ID_SIZE) {
error_print();
return -1;
}
}
if (!tls_protocol_name(protocol)) {
error_print();
return -1;
}
if (!tls_cipher_suite_name(cipher_suite)) {
error_print();
return -1;
}
p = tls_handshake_data(tls_record_data(record));
len = 0;
tls_uint16_to_bytes((uint16_t)protocol, &p, &len);
tls_array_to_bytes(random, 32, &p, &len);
tls_uint8array_to_bytes(session_id, session_id_len, &p, &len);
tls_uint16_to_bytes((uint16_t)cipher_suite, &p, &len);
tls_uint8_to_bytes((uint8_t)TLS_compression_null, &p, &len);
if (exts) {
if (protocol < TLS_protocol_tls12) {
error_print();
return -1;
}
tls_uint16array_to_bytes(exts, exts_len, &p, &len);
}
if (tls_record_set_handshake(record, recordlen, type, NULL, len) != 1) {
error_print();
return -1;
}
return 1;
}
*/
/*
NewSessionTicket
struct {
uint32 ticket_lifetime;
uint32 ticket_age_add;
opaque ticket_nonce<0..255>;
opaque ticket<1..2^16-1>;
Extension extensions<0..2^16-2>;
} NewSessionTicket;
*/
// 8. encrypted_extensions
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;
}
// 11. 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(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;
}
/*
struct {
opaque certificate_request_context<0..2^8-1>;
CertificateEntry certificate_list<0..2^24-1>;
} Certificate;
if has no proper certificate chain
the client should send the Certificate with empty certificate_list content
*/
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;
}
/*
int _tls13_record_get_handshake_certificate(const uint8_t *record,
const uint8_t **request_context, size_t *request_context_len,
const uint8_t **cert_list, size_t *cert_list_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) {
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;
}
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;
}
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;
}
// 13. certificate_request
/*
struct {
opaque certificate_request_context<0..2^8-1>;
Extension extensions<2..2^16-1>;
} CertificateRequest;
extensiosns:
Extension signature_algorithms MUST be specified
*/
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;
}
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_set_handshake_certificate_request_default(uint8_t *record, size_t *recordlen)
{
int sig_algs[] = { TLS_sig_sm2sig_sm3 };
uint8_t exts[256];
uint8_t *p = exts;
size_t extslen = 0;
tls_signature_algorithms_ext_to_bytes(sig_algs, sizeof(sig_algs)/sizeof(int), &p, &extslen);
tls13_record_set_handshake_certificate_request(record, recordlen, NULL, 0, exts, extslen);
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;
}
return 1;
}
/*
handshake #15
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;
}
// 20. finished
/*
finished_key = HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)
struct {
opaque verify_data[Hash.length];
} Finished;
verify_data = HMAC(finished_key, Hash(Handshake Context, Certificate*, CertificateVerify*))
Hash = SM3, SHA256 or SHA384
*/
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;
}
// 24. key_update
int tls13_record_set_handshake_key_update(uint8_t *record, size_t *recordlen,
int request_update)
{
int type = TLS_handshake_key_update;
uint8_t data[1]; // 这个值不太好
data[0] = request_update ? 1 : 0;
if (tls_record_set_handshake(record, recordlen, type, data, sizeof(data)) != 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;
}
// 254. message_hash
int tls13_record_set_message_hash(uint8_t *record, size_t *recordlen)
{
return -1;
}
int tls13_record_get_message_hash(uint8_t *record, size_t *recordlen)
{
return -1;
}
int tls_handshake_digest_print(FILE *fp, int fmt, int ind, const char *label, const DIGEST_CTX *dgst_ctx)
{
DIGEST_CTX tmp_ctx;
uint8_t dgst[64];
size_t dgstlen;
tmp_ctx = *dgst_ctx;
digest_finish(&tmp_ctx, dgst, &dgstlen);
format_bytes(fp, fmt, ind, label, dgst, dgstlen);
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 tls_key_exchange_modes_print(FILE *fp, int fmt, int ind, const char *label, int modes)
{
format_print(fp, fmt, ind, "%s:", label);
if (modes & TLS_KE_CERT_DHE) {
fprintf(fp, " CERT_DHE");
}
if (modes & TLS_KE_PSK_DHE) {
fprintf(fp, " PSK_DHE");
}
if (modes & TLS_KE_PSK) {
fprintf(fp, " PSK");
}
fprintf(fp, "\n");
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_handshake_keys(TLS_CONNECT *conn)
{
uint8_t zeros[32] = {0};
uint8_t early_secret[32];
uint8_t handshake_secret[32];
uint8_t pre_master_secret[32] = {0};
size_t pre_master_secret_len;
uint8_t client_write_key[16] = {0};
uint8_t server_write_key[16] = {0};
DIGEST_CTX null_dgst_ctx;
printf("generate handshake secrets\n");
/*
generate handshake keys
uint8_t client_write_key[32]
uint8_t server_write_key[32]
uint8_t client_write_iv[12]
uint8_t server_write_iv[12]
*/
// 计算ECDHE
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,
pre_master_secret, &pre_master_secret_len) != 1) {
error_print();
return -1;
}
}
digest_init(&null_dgst_ctx, conn->digest);
/* [1] */ tls13_hkdf_extract(conn->digest, zeros, conn->psk, early_secret);
/* [5] */ tls13_derive_secret(early_secret, "derived", &null_dgst_ctx, handshake_secret);
/* [6] */ tls13_hkdf_extract(conn->digest, handshake_secret, pre_master_secret, handshake_secret);
/* [7] */ tls13_derive_secret(handshake_secret, "c hs traffic", &conn->dgst_ctx, conn->client_handshake_traffic_secret);
/* [8] */ tls13_derive_secret(handshake_secret, "s hs traffic", &conn->dgst_ctx, conn->server_handshake_traffic_secret);
/* [9] */ tls13_derive_secret(handshake_secret, "derived", &null_dgst_ctx, conn->master_secret);
/* [10] */ tls13_hkdf_extract(conn->digest, conn->master_secret, zeros, conn->master_secret);
//[sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length)
//[sender]_write_iv = HKDF-Expand-Label(Secret, "iv", "", iv_length)
//[sender] in {server, client}
tls13_hkdf_expand_label(conn->digest, conn->server_handshake_traffic_secret, "key", NULL, 0, 16, server_write_key);
block_cipher_set_encrypt_key(&conn->server_write_key, conn->cipher, server_write_key);
tls13_hkdf_expand_label(conn->digest, conn->server_handshake_traffic_secret, "iv", NULL, 0, 12, conn->server_write_iv);
tls_seq_num_reset(conn->server_seq_num);
format_bytes(stderr, 0, 0, "server_handshake_traffic_secret", conn->server_handshake_traffic_secret, 48);
format_bytes(stderr, 0, 0, "client_handshake_traffic_secret", conn->client_handshake_traffic_secret, 48);
if (!conn->early_data) {
format_print(stderr, 0, 0, "update client_write_key, client_write_iv\n");
tls13_hkdf_expand_label(conn->digest, conn->client_handshake_traffic_secret, "key", NULL, 0, 16, client_write_key);
block_cipher_set_encrypt_key(&conn->client_write_key, conn->cipher, client_write_key);
tls13_hkdf_expand_label(conn->digest, conn->client_handshake_traffic_secret, "iv", NULL, 0, 12, conn->client_write_iv);
tls_seq_num_reset(conn->client_seq_num);
}
format_bytes(stderr, 0, 4, "server_write_key", server_write_key, 16);
format_bytes(stderr, 0, 4, "server_write_iv", conn->server_write_iv, 12);
format_bytes(stderr, 0, 4, "client_write_key", client_write_key, 16);
format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, 12);
return 1;
}
int tls13_init(TLS_CONNECT *conn, TLS_CTX *ctx)
{
size_t i;
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->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]
*/
fprintf(stderr, "tls13_init\n");
// 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;
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;
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;
}
}
// 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
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_keys, conn->psk_keys_len,
conn->record + 5, conn->recordlen - 5,
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;
}
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_data_keys(conn) != 1) {
error_print();
return -1;
}
}
// backup client_hello
memcpy(conn->plain_record, conn->record, conn->recordlen);
conn->plain_recordlen = conn->recordlen;
}
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_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;
tls_trace("recv HelloRetryRequest*\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
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) {
tls_trace(" no HelloRetryRequest\n");
return 0;
}
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
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;
}
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 (tls13_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;
}
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;
}
if (conn->client_certs_len) {
sm2_sign_update(&conn->sign_ctx, conn->record + 5, conn->recordlen - 5);
}
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;
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);
// client_random
if (tls13_random_generate(conn->client_random) != 1) {
error_print();
return -1;
}
// 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;
}
}
// 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_keys, conn->psk_keys_len,
conn->record + 5, conn->recordlen - 5,
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;
}
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;
tls_trace("recv ServerHello\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
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 (tls13_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 <= 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
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;
}
tls_handshake_digest_print(stderr, 0, 0, "ServerHello", &conn->dgst_ctx);
} else {
if (digest_init(&conn->dgst_ctx, conn->digest) != 1
// dgst_ctx <= ClientHello
|| digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1
// dgst_ctx <= ServerHello
|| digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) {
error_print();
return -1;
}
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_keys(conn) != 1) {
error_print();
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;
size_t supported_groups_len;
int server_name = 0;
int early_data = 0;
printf("recv {EncryptedExtensions}\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
if (tls13_record_decrypt(&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;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
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;
}
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:
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) {
return TLS_CERT_VERIFY_NO_SUBJECT_ALT_NAME;
}
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, certlen)) < 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
|| !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;
int common_sig_algs_cert[4];
size_t common_sig_algs_cert_cnt;
const uint8_t *ca_names = NULL;
size_t ca_names_len = 0;
const uint8_t *filters = NULL;
size_t filters_len = 0;
tls_trace("recv {CertificateRequest*}\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
if (tls13_record_decrypt(&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) {
tls_trace(" no {CertificateRequest}\n");
return 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) {
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;
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;
size_t leaf_status_request_ocsp_response_len;
const uint8_t *leaf_signed_certificate_timestamp;
size_t leaf_signed_certificate_timestamp_len;
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;
tls_trace("recv server {Certificate}\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
// decrypt unless previous handshake is CertificateRequest
if (!conn->plain_recordlen) {
if (tls13_record_decrypt(&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;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
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();
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->server_name) {
host_name = conn->host_name;
host_name_len = conn->host_name_len;
}
if (tls_cert_chain_match_extensions(conn->peer_cert_chain, conn->peer_cert_chain_len,
conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt,
signature_algorithms_cert, signature_algorithms_cert_cnt,
ca_names, ca_names_len, // certificate_authorities
NULL, 0, // oid_filters
host_name, host_name_len,
NULL) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
// verify server cert_chain
if (x509_certs_verify(
conn->peer_cert_chain, conn->peer_cert_chain_len, X509_cert_chain_server,
conn->ctx->cacerts, conn->ctx->cacertslen,
conn->ctx->verify_depth, &verify_result) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
// status_request
if (leaf_status_request_ocsp_response) {
if (ocsp_response_verify(
leaf_status_request_ocsp_response,
leaf_status_request_ocsp_response_len,
conn->ctx->cacerts, conn->ctx->cacertslen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_certificate_revoked);
return -1;
}
}
// signed_certificate_timestamp
if (leaf_signed_certificate_timestamp) {
if (tls13_signed_certificate_timestamp_verify(
leaf_signed_certificate_timestamp,
leaf_signed_certificate_timestamp_len) != 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;
tls_trace("recv server {CertificateVerify}\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
if (tls13_record_decrypt(&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);
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;
}
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;
tls_trace("recv client {CertificateVerify}\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
if (tls13_record_decrypt(&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);
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;
}
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;
uint8_t server_write_key[16];
// 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;
}
tls_trace("recv server {Finished}\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
if (tls13_record_decrypt(&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);
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;
}
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;
}
// generate client_application_traffic_secret
/* [11] */ tls13_derive_secret(conn->master_secret, "c ap traffic", &conn->dgst_ctx, conn->client_application_traffic_secret);
// generate server_application_traffic_secret
/* [12] */ tls13_derive_secret(conn->master_secret, "s ap traffic", &conn->dgst_ctx, conn->server_application_traffic_secret);
// update server_write_key, server_write_iv, reset server_seq_num
tls13_hkdf_expand_label(conn->digest, conn->server_application_traffic_secret, "key", NULL, 0, 16, server_write_key);
block_cipher_set_encrypt_key(&conn->server_write_key, conn->cipher, server_write_key);
tls13_hkdf_expand_label(conn->digest, conn->server_application_traffic_secret, "iv", NULL, 0, 12, conn->server_write_iv);
tls_seq_num_reset(conn->server_seq_num);
format_print(stderr, 0, 0, "update server secrets\n");
format_bytes(stderr, 0, 4, "server_application_traffic_secret", conn->server_application_traffic_secret, 48);
format_bytes(stderr, 0, 4, "server_write_key", server_write_key, 16);
format_bytes(stderr, 0, 4, "server_write_iv", conn->server_write_iv, 12);
format_print(stderr, 0, 0, "\n");
tls_seq_num_reset(conn->server_seq_num);
return 1;
}
int tls13_send_client_certificate(TLS_CONNECT *conn)
{
int ret;
tls_trace("send {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;
}
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->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;
tls_trace("send {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;
}
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->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;
uint8_t client_write_key[16];
tls_trace("send client {Finished}\n");
if (!conn->recordlen) {
uint8_t verify_data[64];
size_t verify_data_len;
size_t padding_len;
tls_handshake_digest_print(stderr, 0, 0, "before ClientFinished", &conn->dgst_ctx);
tls13_compute_verify_data(conn->client_handshake_traffic_secret, &conn->dgst_ctx,
verify_data, &verify_data_len);
memset(&conn->dgst_ctx, 0, sizeof(conn->dgst_ctx));
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;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
format_bytes(stderr, 0, 0, "client_seq_num", conn->client_seq_num, 8);
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(&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;
}
//update client_write_key, client_write_iv, reset client_seq_num
tls13_hkdf_expand_label(conn->digest, conn->client_application_traffic_secret, "key", NULL, 0, 16, client_write_key);
tls13_hkdf_expand_label(conn->digest, conn->client_application_traffic_secret, "iv", NULL, 0, 12, conn->client_write_iv);
block_cipher_set_encrypt_key(&conn->client_write_key, conn->cipher, client_write_key);
tls_seq_num_reset(conn->client_seq_num);
format_print(stderr, 0, 0, "update client secrets\n");
format_bytes(stderr, 0, 4, "client_application_traffic_secret", conn->client_application_traffic_secret, 48);
format_bytes(stderr, 0, 4, "client_write_key", client_write_key, 16);
format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, 12);
format_print(stderr, 0, 0, "\n");
return 1;
}
int tls13_recv_client_hello(TLS_CONNECT *conn)
{
int ret;
uint8_t *record = conn->record;
size_t recordlen;
int client_verify = 0;
int protocol;
// 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 *legacy_comp_methods;
size_t legacy_comp_methods_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 *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);
*/
tls_trace("recv ClientHello\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
if (tls_record_protocol(record) != TLS_protocol_tls1) {
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();
}
// cipher_suites
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;
}
tls13_cipher_suite_get(conn->cipher_suite, &conn->cipher, &conn->digest);
// digest_update(client_hello) until conn->hello_retry_request
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_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_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_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:
break;
case TLS_extension_cookie:
error_print();
default:
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
}
// 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 ((psk_key_exchange_modes && !pre_shared_key)
|| (!psk_key_exchange_modes && pre_shared_key)) {
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;
}
// select server cert_chain
// * signature_algorithms
// * [signature_algorithms_cert]
// * [certificate_authorities]
// * [server_name.host_name]
//
if (common_key_exchange_modes & TLS_KE_CERT_DHE) {
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;
}
}
// 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) {
if (conn->selected_psk_identity && 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) {
if (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, ">>>> key_exchange_modes", 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;
}
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_data_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;
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;
int curve_oid;
uint8_t cookie[256];
size_t cookie_len;
tls_record_set_protocol(conn->record, TLS_protocol_tls12);
if (tls13_random_generate(conn->server_random) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_internal_error);
return -1;
}
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;
}
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;
}
int tls13_recv_client_hello_again(TLS_CONNECT *conn)
{
int ret;
uint8_t *record = conn->record;
size_t recordlen;
int client_verify = 0;
int protocol;
// 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 *_legacy_comp_methods;
size_t _legacy_comp_methods_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 *legacy_comp_methods;
size_t legacy_comp_methods_len;
const uint8_t *exts;
size_t extslen;
// Extensions
const uint8_t *key_share = NULL;
size_t key_share_len;
const uint8_t *pre_shared_key = NULL;
size_t pre_shared_key_len;
const uint8_t *cookie = NULL;
size_t cookie_len;
const uint8_t *key_exchange;
size_t key_exchange_len;
tls_trace("recv ClientHello again\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
if (tls_record_protocol(record) != TLS_protocol_tls1) {
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 not 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);
while (extslen) {
int ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
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;
}
// 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;
}
// get ext in ClientHello1 (omit early_data)
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;
}
if (_ext_type == TLS_extension_early_data) {
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;
}
}
if (ext_type != _ext_type) {
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;
}
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;
size_t _psk_identities_len;
if (!ext_data) {
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, 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, _ext_data, _ext_datalen) != 1) {
error_print();
return -1;
}
while (psk_identities_len) {
const uint8_t *id;
size_t idlen;
uint32_t age;
const uint8_t *_id;
size_t _idlen;
int match = 0;
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 != _ext_datalen
|| memcmp(ext_data, _ext_data, _ext_datalen) != 0) {
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;
tls_trace("send ServerHello\n");
if (conn->recordlen == 0) {
uint8_t exts[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->key_exchange_modes & (TLS_KE_PSK_DHE|TLS_KE_PSK)) {
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, NULL, 0,
conn->cipher_suite, exts, extslen) != 1) {
error_print();
return -1;
}
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;
}
tls_handshake_digest_print(stderr, 0, 0, "ServerHello", &conn->dgst_ctx);
if (tls13_generate_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;
tls_trace("send {Alert}\n");
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);
switch (conn->state) {
case TLS_handshake_client_hello:
case TLS_handshake_server_hello:
case TLS_handshake_hello_retry_request:
tls_socket_send(conn->sock, conn->plain_record, conn->plain_recordlen, 0);
break;
default:
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(&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_encrypted_extensions(TLS_CONNECT *conn)
{
int ret;
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;
}
}
if (tls13_record_set_handshake_encrypted_extensions(
conn->plain_record, &conn->plain_recordlen,
exts, extslen) != 1) {
error_print();
return -1;
}
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);
tls_handshake_digest_print(stderr, 0, 0, "EncryptedExtensions", &conn->dgst_ctx);
tls13_padding_len_rand(&padding_len);
format_bytes(stderr, 0, 0, "server_seq_num", conn->server_seq_num, 8);
if (tls13_record_encrypt(&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;
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->signature_algorithms_cnt) {
error_print();
return -1;
}
// subset of ClientHello.signature_algorithms
if (tls_signature_algorithms_ext_to_bytes(
conn->signature_algorithms, conn->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->signature_algorithms, conn->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;
}
}
// 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;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
format_bytes(stderr, 0, 0, "server_seq_num", conn->server_seq_num, 8);
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(&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;
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;
}
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;
}
tls_handshake_digest_print(stderr, 0, 0, "ServerCertificate", &conn->dgst_ctx);
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(&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;
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;
}
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->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;
tls_trace("send server {Finished}\n");
if (conn->recordlen == 0) {
uint8_t verify_data[64];
size_t verify_data_len;
uint8_t server_write_key[16];
// 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;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
tls_handshake_digest_print(stderr, 0, 0, "ServerFinished", &conn->dgst_ctx);
format_bytes(stderr, 0, 0, "server_seq_num", conn->server_seq_num, 8);
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(&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);
// Generate client_application_traffic_secret
/* 11 */ tls13_derive_secret(conn->master_secret, "c ap traffic", &conn->dgst_ctx, conn->client_application_traffic_secret);
// generate server_application_traffic_secret
/* 12 */ tls13_derive_secret(conn->master_secret, "s ap traffic", &conn->dgst_ctx, conn->server_application_traffic_secret);
// update server_write_key, server_write_iv, reset server_seq_num
tls13_hkdf_expand_label(conn->digest, conn->server_application_traffic_secret, "key", NULL, 0, 16, server_write_key);
block_cipher_set_encrypt_key(&conn->server_write_key, conn->cipher, server_write_key);
tls13_hkdf_expand_label(conn->digest, conn->server_application_traffic_secret, "iv", NULL, 0, 12, conn->server_write_iv);
tls_seq_num_reset(conn->server_seq_num);
format_print(stderr, 0, 0, "update server secrets\n");
format_bytes(stderr, 0, 4, "server_application_traffic_secret", conn->server_application_traffic_secret, 48);
format_bytes(stderr, 0, 4, "server_write_key", server_write_key, 16);
format_bytes(stderr, 0, 4, "server_write_iv", conn->server_write_iv, 12);
format_print(stderr, 0, 0, "\n");
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
return 1;
}
int tls13_recv_client_certificate(TLS_CONNECT *conn)
{
int ret;
size_t padding_len;
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;
const uint8_t *signed_certificate_timestamp = NULL;
size_t signed_certificate_timestamp_len;
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;
tls_trace("recv {Certificate*}\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
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;
}
format_bytes(stderr, 0, 0, "client_seq_num", conn->client_seq_num, 8);
if (tls13_record_decrypt(&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);
tls13_record_trace(stderr, conn->plain_record, conn->plain_recordlen, 0, 0);
if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) {
error_print();
return -1;
}
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) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
// 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;
}
if (tls_cert_chain_match_extensions(conn->peer_cert_chain, conn->peer_cert_chain_len,
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, // server_name not in CertificateRequest
NULL) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
// verify client cert_chain
if (x509_certs_verify(conn->peer_cert_chain, conn->peer_cert_chain_len, X509_cert_chain_client,
conn->ctx->cacerts, conn->ctx->cacertslen,
conn->ctx->verify_depth, &verify_result) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
// status_request
if (status_request_ocsp_response) {
if (ocsp_response_verify(
status_request_ocsp_response, status_request_ocsp_response_len,
conn->ctx->cacerts, conn->ctx->cacertslen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_certificate_revoked);
return -1;
}
}
// signed_certificate_timestamp
if (signed_certificate_timestamp) {
if (tls13_signed_certificate_timestamp_verify(
signed_certificate_timestamp, signed_certificate_timestamp_len) != 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;
uint8_t client_write_key[16];
tls_trace("recv client {Finished}\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
if (tls_record_protocol(conn->record) != TLS_protocol_tls12) {
error_print();
tls13_send_alert(conn, TLS_alert_protocol_version);
return -1;
}
format_bytes(stderr, 0, 0, "client_seq_num", conn->client_seq_num, 8);
if (tls13_record_decrypt(&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);
tls13_record_trace(stderr, conn->plain_record, conn->plain_recordlen, 0, 0);
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;
}
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;
}
memset(&conn->dgst_ctx, 0, sizeof(conn->dgst_ctx));
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;
}
// update client_write_key, client_write_iv, reset client_seq_num
tls13_hkdf_expand_label(conn->digest, conn->client_application_traffic_secret, "key", NULL, 0, 16, client_write_key);
block_cipher_set_encrypt_key(&conn->client_write_key, conn->cipher, client_write_key);
tls13_hkdf_expand_label(conn->digest, conn->client_application_traffic_secret, "iv", NULL, 0, 12, conn->client_write_iv);
tls_seq_num_reset(conn->client_seq_num);
format_print(stderr, 0, 0, "update client secrets\n");
format_bytes(stderr, 0, 4, "client_write_key", client_write_key, 16);
format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, 12);
format_print(stderr, 0, 0, "\n");
return 1;
}
int tls13_send_early_data(TLS_CONNECT *conn)
{
size_t sentlen;
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 ((ret = tls13_send(conn, conn->early_data_buf + conn->early_data_offset,
conn->early_data_len - conn->early_data_offset, &sentlen)) <= 0) {
if (ret == TLS_ERROR_SEND_AGAIN) {
return ret;
}
}
conn->early_data_offset += sentlen;
}
return 1;
}
int tls13_update_client_application_keys(TLS_CONNECT *conn)
{
uint8_t client_write_key[16];
tls13_hkdf_expand_label(conn->digest, conn->client_application_traffic_secret, "traffic upd", NULL, 0, 48, conn->client_application_traffic_secret);
tls13_hkdf_expand_label(conn->digest, conn->client_application_traffic_secret, "key", NULL, 0, 16, client_write_key);
block_cipher_set_encrypt_key(&conn->client_write_key, conn->cipher, client_write_key);
tls13_hkdf_expand_label(conn->digest, conn->client_application_traffic_secret, "iv", NULL, 0, 12, conn->client_write_iv);
tls_seq_num_reset(conn->client_seq_num);
format_print(stderr, 0, 0, "update client secrets\n");
format_bytes(stderr, 0, 4, "client application_traffic_secret", conn->client_application_traffic_secret, 48);
format_bytes(stderr, 0, 4, "client_write_key", client_write_key, 16);
format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, 12);
format_print(stderr, 0, 0, "\n");
return 1;
}
int tls13_update_server_application_keys(TLS_CONNECT *conn)
{
uint8_t server_write_key[16];
tls13_hkdf_expand_label(conn->digest, conn->server_application_traffic_secret, "traffic upd", NULL, 0, 48, conn->server_application_traffic_secret);
tls13_hkdf_expand_label(conn->digest, conn->server_application_traffic_secret, "key", NULL, 0, 16, server_write_key);
block_cipher_set_encrypt_key(&conn->server_write_key, conn->cipher, server_write_key);
tls13_hkdf_expand_label(conn->digest, conn->server_application_traffic_secret, "iv", NULL, 0, 12, conn->server_write_iv);
tls_seq_num_reset(conn->server_seq_num);
format_print(stderr, 0, 0, "update server secrets\n");
format_bytes(stderr, 0, 4, "server_application_traffic_secret", conn->server_application_traffic_secret, 48);
format_bytes(stderr, 0, 4, "server_write_key", server_write_key, 16);
format_bytes(stderr, 0, 4, "server_write_iv", conn->server_write_iv, 12);
format_print(stderr, 0, 0, "\n");
return 1;
}
// 参数request_update应该根据当前状态设置
int tls13_send_client_key_update(TLS_CONNECT *conn, int request_update)
{
int ret;
if (conn->recordlen == 0) {
size_t padding_len = 0;
tls_trace("send {KeyUpdate}\n");
if (tls13_record_set_handshake_key_update(conn->plain_record, &conn->plain_recordlen,
request_update) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(&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;
}
tls13_update_client_application_keys(conn);
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
return 1;
}
int tls13_send_server_key_update(TLS_CONNECT *conn, int request_update)
{
int ret;
if (conn->recordlen == 0) {
size_t padding_len = 0;
tls_trace("send {KeyUpdate}\n");
if (tls13_record_set_handshake_key_update(conn->plain_record, &conn->plain_recordlen,
request_update) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(&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;
}
tls13_update_server_application_keys(conn);
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
return 1;
}
/*
Post-Handshake-Auth
客户端在 ClientHello 中发送post_handshake_auht说明支持PHA
在握手完成并进行数据通信时,如果客户端请求一个特殊的地址 比如 GET /admin
默认未认证的客户端不能访问此地址因此服务器端如果发现客户端支持PHA那么就会给客户端发送一个CertificateRequest
客户端不需要立即响应,但是如果客户端响应
则需要发出连续的 Certificate, CertificateVerify, Finished消息
这意味着如果客户端开始发送Certificate
服务器就必须再次进入到握手的状态机中
这意味着SSL再次进入到状态机中
是否意味着每次不论上层调用是read/writeSSL都是按照状态机来处理
*/
int tls13_do_client_handshake(TLS_CONNECT *conn)
{
int ret;
int next_state;
// 客户端的状态机可能还是有问题的
switch (conn->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) {
tls_trace("send EarlyData\n");
if (tls13_send_early_data(conn) != 1) {
error_print();
return -1;
}
}
break;
}
switch (conn->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);
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->client_certificate_verify)
next_state = TLS_state_client_certificate;
else next_state = TLS_state_client_finished;
break;
case TLS_state_end_of_early_data:
ret = tls13_send_end_of_early_data(conn);
next_state = TLS_state_client_finished;
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_finished;
break;
case TLS_state_client_certificate_verify:
ret = tls13_send_client_certificate_verify(conn);
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->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 next_state;
switch (conn->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);
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_finished;
break;
case TLS_state_end_of_early_data:
ret = tls13_recv_end_of_early_data(conn);
next_state = TLS_state_client_finished;
break;
case TLS_state_client_certificate:
ret = tls13_recv_client_certificate(conn);
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_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->state = next_state;
tls_clean_record(conn);
return 1;
}
int tls13_client_handshake(TLS_CONNECT *conn)
{
int ret;
while (conn->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->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;
fd_set rfds;
fd_set wfds;
// 应该把protocol_version的初始化放在这里
conn->state = TLS_state_client_hello;
sm3_init(&conn->sm3_ctx);
while (1) {
ret = tls13_client_handshake(conn);
if (ret == 1) {
break;
} else if (ret == TLS_ERROR_SEND_AGAIN) {
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_SET(conn->sock, &rfds);
select(conn->sock + 1, &rfds, &wfds, NULL, NULL);
} else if (ret == TLS_ERROR_RECV_AGAIN) {
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_SET(conn->sock, &wfds);
select(conn->sock + 1, &rfds, &wfds, NULL, NULL);
} else {
error_print();
return -1;
}
}
fprintf(stderr, "tls13_do_connect: connected\n");
return 1;
}
int tls13_do_accept(TLS_CONNECT *conn)
{
int ret;
fd_set rfds;
fd_set wfds;
conn->state = TLS_state_client_hello;
sm3_init(&conn->sm3_ctx);
fprintf(stderr, "tls13_do_accept\n");
while (1) {
ret = tls13_server_handshake(conn);
if (ret == 1) {
break;
} else if (ret == TLS_ERROR_SEND_AGAIN) {
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_SET(conn->sock, &rfds);
select(conn->sock + 1, &rfds, &wfds, NULL, NULL);
} else if (ret == TLS_ERROR_RECV_AGAIN) {
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_SET(conn->sock, &wfds);
select(conn->sock + 1, &rfds, &wfds, NULL, NULL);
} else {
error_print();
return -1;
}
}
fprintf(stderr, "tls13_do_accept: connected\n");
return 1;
}
// 这个函数应该是属于key_share的不要放在这个函数里面
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;
}