Files
GmSSL/src/tls13.c
2026-06-20 11:40:27 +08:00

9299 lines
242 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>
const int tls13_supported_groups[] = {
TLS_curve_sm2p256v1,
#ifdef ENABLE_SECP256R1
TLS_curve_secp256r1,
#endif
};
const size_t tls13_supported_groups_cnt =
sizeof(tls13_supported_groups)/sizeof(tls13_supported_groups[0]);
const int tls13_signature_algorithms[] = {
TLS_sig_sm2sig_sm3,
#if defined(ENABLE_SECP256R1) && defined(ENABLE_SHA2)
TLS_sig_ecdsa_secp256r1_sha256,
#endif
};
const size_t tls13_signature_algorithms_cnt =
sizeof(tls13_signature_algorithms)/sizeof(tls13_signature_algorithms[0]);
const int tls13_cipher_suites[] = {
TLS_cipher_sm4_gcm_sm3,
#ifdef ENABLE_SM4_CCM
TLS_cipher_sm4_ccm_sm3,
#endif
#if defined(ENABLE_AES) && defined(ENABLE_SHA2)
TLS_cipher_aes_128_gcm_sha256,
#ifdef ENABLE_AES_CCM
TLS_cipher_aes_128_ccm_sha256,
#endif
#endif
};
const size_t tls13_cipher_suites_cnt =
sizeof(tls13_cipher_suites)/sizeof(tls13_cipher_suites[0]);
int tls13_random_generate(uint8_t random[32])
{
if (rand_bytes(random, 32) != 1) {
error_print();
return -1;
}
return 1;
}
int tls13_padding_len_rand(size_t *padding_len)
{
uint8_t val;
rand_bytes(&val, 1);
*padding_len = val % 128;
*padding_len = 0;
return 1;
}
/*
struct {
opaque content[TLSPlaintext.length];
ContentType type;
uint8 zeros[length_of_padding];
} TLSInnerPlaintext;
struct {
ContentType opaque_type = application_data; // 23
ProtocolVersion legacy_record_version = 0x0303; // TLS v1.2
uint16 length;
opaque encrypted_record[TLSCiphertext.length];
} TLSCiphertext;
*/
int tls13_gcm_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
const uint8_t seq_num[8], int record_type,
const uint8_t *in, size_t inlen, size_t padding_len, // TLSInnerPlaintext.content
uint8_t *out, size_t *outlen) // TLSCiphertext.encrypted_record
{
uint8_t nonce[12];
uint8_t aad[5];
uint8_t *gmac;
uint8_t *mbuf = NULL;
size_t mlen, clen;
if (!(mbuf = malloc(inlen + 256))) {
error_print();
return -1;
}
// nonce = (zeros|seq_num) xor (iv)
nonce[0] = nonce[1] = nonce[2] = nonce[3] = 0;
memcpy(nonce + 4, seq_num, 8);
gmssl_memxor(nonce, nonce, iv, 12);
// TLSInnerPlaintext
memcpy(mbuf, in, inlen);
mbuf[inlen] = record_type;
memset(mbuf + inlen + 1, 0, padding_len);
mlen = inlen + 1 + padding_len;
clen = mlen + GHASH_SIZE;
// aad = TLSCiphertext header
aad[0] = TLS_record_application_data;
aad[1] = 0x03; //TLS_protocol_tls12_major;
aad[2] = 0x03; //TLS_protocol_tls12_minor;
aad[3] = (uint8_t)(clen >> 8);
aad[4] = (uint8_t)(clen);
gmac = out + mlen;
switch (key->cipher->oid) {
case OID_sm4:
if (sm4_gcm_encrypt(&(key->u.sm4_key), nonce, sizeof(nonce), aad, sizeof(aad),
mbuf, mlen, out, 16, gmac) != 1) {
error_print();
free(mbuf);
return -1;
}
break;
#ifdef ENABLE_AES
case OID_aes128:
if (aes_gcm_encrypt(&(key->u.aes_key), nonce, sizeof(nonce), aad, sizeof(aad),
mbuf, mlen, out, 16, gmac) != 1) {
error_print();
free(mbuf);
return -1;
}
break;
#endif
default:
error_print();
free(mbuf);
return -1;
}
*outlen = clen;
free(mbuf);
return 1;
}
int tls13_gcm_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
const uint8_t seq_num[8], const uint8_t *in, size_t inlen,
int *record_type, uint8_t *out, size_t *outlen)
{
uint8_t nonce[12];
uint8_t aad[5];
size_t mlen;
const uint8_t *gmac;
// nonce = (zeros|seq_num) xor (iv)
nonce[0] = nonce[1] = nonce[2] = nonce[3] = 0;
memcpy(nonce + 4, seq_num, 8);
gmssl_memxor(nonce, nonce, iv, 12);
// aad = TLSCiphertext header
aad[0] = TLS_record_application_data;
aad[1] = 0x03; //TLS_protocol_tls12_major;
aad[2] = 0x03; //TLS_protocol_tls12_minor;
aad[3] = (uint8_t)(inlen >> 8);
aad[4] = (uint8_t)(inlen);
if (inlen < GHASH_SIZE) {
error_print();
return -1;
}
mlen = inlen - GHASH_SIZE;
gmac = in + mlen;
switch (key->cipher->oid) {
case OID_sm4:
if (sm4_gcm_decrypt(&(key->u.sm4_key), nonce, sizeof(nonce), aad, sizeof(aad),
in, mlen, gmac, GHASH_SIZE, out) != 1) {
error_print();
return -1;
}
break;
case OID_aes128:
#ifdef ENABLE_AES
if (aes_gcm_decrypt(&(key->u.aes_key), nonce, sizeof(nonce), aad, sizeof(aad),
in, mlen, gmac, GHASH_SIZE, out) != 1) {
error_print();
return -1;
}
break;
#endif
default:
error_print();
return -1;
}
// remove padding, get record_type
*record_type = 0;
while (mlen--) {
if (out[mlen] != 0) {
*record_type = out[mlen];
break;
}
}
*outlen = mlen;
if (!tls_record_type_name(*record_type)) {
error_print();
return -1;
}
return 1;
}
static int tls13_ccm_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
const uint8_t seq_num[8], int record_type,
const uint8_t *in, size_t inlen, size_t padding_len,
uint8_t *out, size_t *outlen)
{
uint8_t nonce[12];
uint8_t aad[5];
uint8_t *tag;
uint8_t *mbuf = NULL;
size_t mlen, clen;
if (!(mbuf = malloc(inlen + 256))) {
error_print();
return -1;
}
nonce[0] = nonce[1] = nonce[2] = nonce[3] = 0;
memcpy(nonce + 4, seq_num, 8);
gmssl_memxor(nonce, nonce, iv, 12);
memcpy(mbuf, in, inlen);
mbuf[inlen] = record_type;
memset(mbuf + inlen + 1, 0, padding_len);
mlen = inlen + 1 + padding_len;
clen = mlen + GHASH_SIZE;
aad[0] = TLS_record_application_data;
aad[1] = 0x03;
aad[2] = 0x03;
aad[3] = (uint8_t)(clen >> 8);
aad[4] = (uint8_t)(clen);
tag = out + mlen;
switch (key->cipher->oid) {
#ifdef ENABLE_SM4_CCM
case OID_sm4:
if (sm4_ccm_encrypt(&(key->u.sm4_key), nonce, sizeof(nonce), aad, sizeof(aad),
mbuf, mlen, out, GHASH_SIZE, tag) != 1) {
error_print();
free(mbuf);
return -1;
}
break;
#endif
#ifdef ENABLE_AES_CCM
case OID_aes128:
if (aes_ccm_encrypt(&(key->u.aes_key), nonce, sizeof(nonce), aad, sizeof(aad),
mbuf, mlen, out, GHASH_SIZE, tag) != 1) {
error_print();
free(mbuf);
return -1;
}
break;
#endif
default:
error_print();
free(mbuf);
return -1;
}
*outlen = clen;
free(mbuf);
return 1;
}
static int tls13_ccm_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
const uint8_t seq_num[8], const uint8_t *in, size_t inlen,
int *record_type, uint8_t *out, size_t *outlen)
{
uint8_t nonce[12];
uint8_t aad[5];
size_t mlen;
const uint8_t *tag;
nonce[0] = nonce[1] = nonce[2] = nonce[3] = 0;
memcpy(nonce + 4, seq_num, 8);
gmssl_memxor(nonce, nonce, iv, 12);
aad[0] = TLS_record_application_data;
aad[1] = 0x03;
aad[2] = 0x03;
aad[3] = (uint8_t)(inlen >> 8);
aad[4] = (uint8_t)(inlen);
if (inlen < GHASH_SIZE) {
error_print();
return -1;
}
mlen = inlen - GHASH_SIZE;
tag = in + mlen;
switch (key->cipher->oid) {
#ifdef ENABLE_SM4_CCM
case OID_sm4:
if (sm4_ccm_decrypt(&(key->u.sm4_key), nonce, sizeof(nonce), aad, sizeof(aad),
in, mlen, tag, GHASH_SIZE, out) != 1) {
error_print();
return -1;
}
break;
#endif
#ifdef ENABLE_AES_CCM
case OID_aes128:
if (aes_ccm_decrypt(&(key->u.aes_key), nonce, sizeof(nonce), aad, sizeof(aad),
in, mlen, tag, GHASH_SIZE, out) != 1) {
error_print();
return -1;
}
break;
#endif
default:
error_print();
return -1;
}
*record_type = 0;
while (mlen--) {
if (out[mlen] != 0) {
*record_type = out[mlen];
break;
}
}
*outlen = mlen;
if (!tls_record_type_name(*record_type)) {
error_print();
return -1;
}
return 1;
}
int tls13_record_encrypt(int cipher_suite, const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
const uint8_t seq_num[8], const uint8_t *record, size_t recordlen, size_t padding_len,
uint8_t *enced_record, size_t *enced_recordlen)
{
switch (cipher_suite) {
case TLS_cipher_sm4_gcm_sm3:
case TLS_cipher_aes_128_gcm_sha256:
if (tls13_gcm_encrypt(key, iv,
seq_num, record[0], record + 5, recordlen - 5, padding_len,
enced_record + 5, enced_recordlen) != 1) {
error_print();
return -1;
}
break;
case TLS_cipher_sm4_ccm_sm3:
#ifdef ENABLE_AES_CCM
case TLS_cipher_aes_128_ccm_sha256:
#endif
if (tls13_ccm_encrypt(key, iv,
seq_num, record[0], record + 5, recordlen - 5, padding_len,
enced_record + 5, enced_recordlen) != 1) {
error_print();
return -1;
}
break;
default:
error_print();
return -1;
}
// in tls1.3, type of encrypted records must be application_data
enced_record[0] = TLS_record_application_data;
enced_record[1] = 0x03; //TLS_protocol_tls12_major;
enced_record[2] = 0x03; //TLS_protocol_tls12_minor;
enced_record[3] = (uint8_t)((*enced_recordlen) >> 8);
enced_record[4] = (uint8_t)(*enced_recordlen);
(*enced_recordlen) += 5;
return 1;
}
int tls13_record_decrypt(int cipher_suite, const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
const uint8_t seq_num[8], const uint8_t *enced_record, size_t enced_recordlen,
uint8_t *record, size_t *recordlen)
{
int record_type;
switch (cipher_suite) {
case TLS_cipher_sm4_gcm_sm3:
case TLS_cipher_aes_128_gcm_sha256:
if (tls13_gcm_decrypt(key, iv,
seq_num, enced_record + 5, enced_recordlen - 5,
&record_type, record + 5, recordlen) != 1) {
error_print();
return -1;
}
break;
case TLS_cipher_sm4_ccm_sm3:
#ifdef ENABLE_AES_CCM
case TLS_cipher_aes_128_ccm_sha256:
#endif
if (tls13_ccm_decrypt(key, iv,
seq_num, enced_record + 5, enced_recordlen - 5,
&record_type, record + 5, recordlen) != 1) {
error_print();
return -1;
}
break;
default:
error_print();
return -1;
}
record[0] = record_type;
record[1] = 0x03; //TLS_protocol_tls12_major;
record[2] = 0x03; //TLS_protocol_tls12_minor;
record[3] = (uint8_t)((*recordlen) >> 8);
record[4] = (uint8_t)(*recordlen);
(*recordlen) += 5;
return 1;
}
int tls13_hkdf_extract(const DIGEST *digest, const uint8_t salt[32], const uint8_t in[32], uint8_t out[32])
{
size_t saltlen;
size_t inlen;
size_t outlen;
if (!digest || !salt || !in || !out) {
error_print();
return -1;
}
saltlen = digest->digest_size;
inlen = digest->digest_size;
if (hkdf_extract(digest, salt, saltlen, in, inlen, out, &outlen) != 1) {
error_print();
return -1;
}
// outlen == digest->digest_size
return 1;
}
/*
HKDF-Expand-Label(Secret, Label, Context, Length) =
HKDF-Expand(Secret, HkdfLabel, Length);
HkdfLabel = struct {
uint16 length = Length;
opaque label<7..255> = "tls13 " + Label;
opaque context<0..255> = Context; }
*/
int tls13_hkdf_expand_label(const DIGEST *digest, const uint8_t secret[32],
const char *label, const uint8_t *context, size_t context_len,
size_t outlen, uint8_t *out)
{
uint8_t hkdf_label[2 + 256 + 256];
uint8_t *p = hkdf_label;
size_t hkdf_label_len = 0;
size_t secret_len;
size_t label_len;
if (!digest || !secret || !label || !outlen || !out) {
error_print();
return -1;
}
if (strlen(label) > 255 - strlen("tls13 ")) {
error_print();
return -1;
}
if (outlen > 65535) {
error_print();
return -1;
}
secret_len = digest->digest_size;
label_len = strlen("tls13 ") + strlen(label);
tls_uint16_to_bytes((uint16_t)outlen, &p, &hkdf_label_len);
tls_uint8_to_bytes((uint8_t)label_len, &p, &hkdf_label_len);
tls_array_to_bytes((uint8_t *)"tls13 ", strlen("tls13 "), &p, &hkdf_label_len);
tls_array_to_bytes((uint8_t *)label, strlen(label), &p, &hkdf_label_len);
tls_uint8array_to_bytes(context, context_len, &p, &hkdf_label_len);
hkdf_expand(digest, secret, secret_len, hkdf_label, hkdf_label_len, outlen, out);
return 1;
}
/*
Derive-Secret(Secret, Label, Messages) =
HKDF-Expand-Label(Secret, Label, Hash(Messages), Hash.length)
*/
int tls13_derive_secret(const uint8_t secret[32], const char *label, const DIGEST_CTX *dgst_ctx, uint8_t out[32])
{
DIGEST_CTX ctx;
size_t outlen = 32;
uint8_t context[32];
size_t context_len;
if (!secret || !label || !dgst_ctx || !out) {
error_print();
return -1;
}
ctx = *dgst_ctx;
if (digest_finish(&ctx, context, &context_len) != 1) {
error_print();
return -1;
}
if (tls13_hkdf_expand_label(dgst_ctx->digest, secret, label, context, context_len, outlen, out) != 1) {
error_print();
return -1;
}
return 1;
}
/*
0
|
v
[1] PSK -> HKDF-Extract = Early Secret
|
[2] +-----> Derive-Secret(., "ext binder" | "res binder", "")
| = binder_key
|
[3] +-----> Derive-Secret(., "c e traffic", ClientHello)
| = client_early_traffic_secret
|
[4] +-----> Derive-Secret(., "e exp master", ClientHello)
| = early_exporter_master_secret
v
[5] Derive-Secret(., "derived", "")
|
v
[6] (EC)DHE -> HKDF-Extract = Handshake Secret
|
[7] +-----> Derive-Secret(., "c hs traffic",
| ClientHello...ServerHello)
| = client_handshake_traffic_secret
|
[8] +-----> Derive-Secret(., "s hs traffic",
| ClientHello...ServerHello)
| = server_handshake_traffic_secret
v
[9] Derive-Secret(., "derived", "")
|
v
[10] 0 -> HKDF-Extract = Master Secret
|
[11] +-----> Derive-Secret(., "c ap traffic",
| ClientHello...server Finished)
| = client_application_traffic_secret_0
|
[12] +-----> Derive-Secret(., "s ap traffic",
| ClientHello...server Finished)
| = server_application_traffic_secret_0
|
[13] +-----> Derive-Secret(., "exp master",
| ClientHello...server Finished)
| = exporter_master_secret
|
[14] +-----> Derive-Secret(., "res master",
ClientHello...client Finished)
= resumption_master_secret
*/
int tls13_generate_early_keys(TLS_CONNECT *conn)
{
const uint8_t zeros[32] = {0};
const uint8_t *psk_keys;
size_t psk_keys_len;
const uint8_t *first_psk_key;
size_t first_psk_key_len;
uint8_t client_write_key[16];
size_t client_write_key_len;
if (!conn) {
error_print();
return -1;
}
if (tls_cipher_suite_get(conn->psk_cipher_suites[0], &conn->cipher, &conn->digest) != 1) {
error_print();
return -1;
}
conn->cipher_suite = conn->psk_cipher_suites[0];
client_write_key_len = conn->cipher->key_size;
if (digest_init(&conn->dgst_ctx, conn->digest) != 1
|| digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) {
error_print();
return -1;
}
// early_data always encrypted with the first psk
psk_keys = conn->psk_keys;
psk_keys_len = conn->psk_keys_len;
if (tls_uint8array_from_bytes(&first_psk_key, &first_psk_key_len, &psk_keys, &psk_keys_len) != 1) {
error_print();
return -1;
}
if (first_psk_key_len != conn->digest->digest_size) {
error_print();
return -1;
}
// first_psk_key => client_early_traffic_secret
if (tls13_hkdf_extract(conn->digest, zeros, first_psk_key, conn->early_secret) != 1
|| tls13_derive_secret(conn->early_secret, "c e traffic", &conn->dgst_ctx, conn->client_early_traffic_secret) != 1
|| tls13_hkdf_expand_label(conn->digest, conn->client_early_traffic_secret, "key", NULL, 0, client_write_key_len, client_write_key) != 1
|| tls13_hkdf_expand_label(conn->digest, conn->client_early_traffic_secret, "iv", NULL, 0, TLS13_IV_SIZE, conn->client_write_iv) != 1
|| block_cipher_set_encrypt_key(&conn->client_write_key, conn->cipher, client_write_key) != 1) {
error_print();
return -1;
}
tls_seq_num_reset(conn->client_seq_num);
if (conn->verbose == TLS_verbose_print_key) {
format_print(stderr, 0, 0, "generate_early_keys\n");
format_bytes(stderr, 0, 4, "early_secret", conn->early_secret, conn->digest->digest_size);
format_bytes(stderr, 0, 4, "client_early_traffic_secret", conn->client_early_traffic_secret, conn->digest->digest_size);
format_bytes(stderr, 0, 4, "client_write_key", client_write_key, client_write_key_len);
format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, TLS13_IV_SIZE);
}
gmssl_secure_clear(client_write_key, sizeof(client_write_key));
return 1;
}
int tls13_generate_handshake_secrets(TLS_CONNECT *conn)
{
const uint8_t zeros[32] = {0};
uint8_t ecdhe_shared_secret[32] = {0};
size_t ecdhe_shared_secret_len = sizeof(ecdhe_shared_secret);
uint8_t derived_secret[32];
DIGEST_CTX null_dgst_ctx;
if (!conn || !conn->digest) {
error_print();
return -1;
}
// (EC)DHE
if (conn->key_exchange_modes != TLS_KE_PSK) {
if (conn->key_exchange_idx >= conn->key_exchanges_cnt) {
error_print();
return -1;
}
if (x509_key_exchange(&conn->key_exchanges[conn->key_exchange_idx],
conn->peer_key_exchange, conn->peer_key_exchange_len,
ecdhe_shared_secret, &ecdhe_shared_secret_len) != 1) {
error_print();
return -1;
}
}
if (digest_init(&null_dgst_ctx, conn->digest) != 1) {
error_print();
return -1;
}
if (tls13_hkdf_extract(conn->digest, zeros, conn->psk, conn->early_secret) != 1
|| tls13_derive_secret(conn->early_secret, "derived", &null_dgst_ctx, derived_secret) != 1
|| tls13_hkdf_extract(conn->digest, derived_secret, ecdhe_shared_secret, conn->handshake_secret) != 1
|| tls13_derive_secret(conn->handshake_secret, "c hs traffic", &conn->dgst_ctx, conn->client_handshake_traffic_secret) != 1
|| tls13_derive_secret(conn->handshake_secret, "s hs traffic", &conn->dgst_ctx, conn->server_handshake_traffic_secret) != 1) {
error_print();
return -1;
}
if (conn->verbose == TLS_verbose_print_key) {
format_print(stderr, 0, 0, "generate_handshake_secrets\n");
format_bytes(stderr, 0, 4, "early_secret", conn->early_secret, conn->digest->digest_size);
format_bytes(stderr, 0, 4, "derived_secret", derived_secret, conn->digest->digest_size);
format_bytes(stderr, 0, 4, "ecdhe_shared_secret", ecdhe_shared_secret, ecdhe_shared_secret_len);
format_bytes(stderr, 0, 4, "handshake_secret", conn->handshake_secret, conn->digest->digest_size);
format_bytes(stderr, 0, 4, "client_handshake_traffic_secret", conn->client_handshake_traffic_secret, conn->digest->digest_size);
format_bytes(stderr, 0, 4, "server_handshake_traffic_secret", conn->server_handshake_traffic_secret, conn->digest->digest_size);
}
gmssl_secure_clear(ecdhe_shared_secret, sizeof(ecdhe_shared_secret));
gmssl_secure_clear(derived_secret, sizeof(derived_secret));
return 1;
}
int tls13_generate_master_secret(TLS_CONNECT *conn)
{
const uint8_t zeros[32] = {0};
DIGEST_CTX null_dgst_ctx;
if (!conn || !conn->digest) {
error_print();
return -1;
}
if (digest_init(&null_dgst_ctx, conn->digest) != 1) {
error_print();
return -1;
}
if (tls13_derive_secret(conn->handshake_secret, "derived", &null_dgst_ctx, conn->master_secret) != 1
|| tls13_hkdf_extract(conn->digest, conn->master_secret, zeros, conn->master_secret) != 1) {
error_print();
return -1;
}
if (conn->verbose == TLS_verbose_print_key) {
format_print(stderr, 0, 0, "generate_master_secret\n");
format_bytes(stderr, 0, 4, "master_secret", conn->master_secret, conn->digest->digest_size);
}
return 1;
}
int tls13_generate_client_handshake_keys(TLS_CONNECT *conn)
{
uint8_t client_write_key[16];
size_t client_write_key_len;
if (!conn || !conn->cipher) {
error_print();
return -1;
}
client_write_key_len = conn->cipher->key_size;
if (tls13_hkdf_expand_label(conn->digest, conn->client_handshake_traffic_secret, "key", NULL, 0, client_write_key_len, client_write_key) != 1
|| tls13_hkdf_expand_label(conn->digest, conn->client_handshake_traffic_secret, "iv", NULL, 0, TLS13_IV_SIZE, conn->client_write_iv) != 1
|| block_cipher_set_encrypt_key(&conn->client_write_key, conn->cipher, client_write_key) != 1) {
error_print();
return -1;
}
tls_seq_num_reset(conn->client_seq_num);
if (conn->verbose == TLS_verbose_print_key) {
format_print(stderr, 0, 0, "generate_client_handshake_keys\n");
format_bytes(stderr, 0, 4, "client_write_key", client_write_key, client_write_key_len);
format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, TLS13_IV_SIZE);
format_print(stderr, 0, 4, "client_seq_num: %"PRIu64"\n", GETU64(conn->client_seq_num));
}
gmssl_secure_clear(client_write_key, sizeof(client_write_key));
return 1;
}
int tls13_generate_server_handshake_keys(TLS_CONNECT *conn)
{
uint8_t server_write_key[16];
size_t server_write_key_len;
if (!conn || !conn->cipher) {
error_print();
return -1;
}
server_write_key_len = conn->cipher->key_size;
if (tls13_hkdf_expand_label(conn->digest, conn->server_handshake_traffic_secret, "key", NULL, 0, server_write_key_len, server_write_key) != 1
|| tls13_hkdf_expand_label(conn->digest, conn->server_handshake_traffic_secret, "iv", NULL, 0, TLS13_IV_SIZE, conn->server_write_iv) != 1
|| block_cipher_set_encrypt_key(&conn->server_write_key, conn->cipher, server_write_key) != 1) {
error_print();
return -1;
}
tls_seq_num_reset(conn->server_seq_num);
if (conn->verbose == TLS_verbose_print_key) {
format_print(stderr, 0, 0, "generate_server_handshake_keys\n");
format_bytes(stderr, 0, 4, "server_write_key", server_write_key, server_write_key_len);
format_bytes(stderr, 0, 4, "server_write_iv", conn->server_write_iv, TLS13_IV_SIZE);
format_print(stderr, 0, 4, "server_seq_num: %"PRIu64"\n", GETU64(conn->server_seq_num));
}
gmssl_secure_clear(server_write_key, sizeof(server_write_key));
return 1;
}
int tls13_generate_application_secrets(TLS_CONNECT *conn)
{
if (!conn || !conn->digest) {
error_print();
return -1;
}
if (tls13_derive_secret(conn->master_secret, "c ap traffic", &conn->dgst_ctx, conn->client_application_traffic_secret) != 1
|| tls13_derive_secret(conn->master_secret, "s ap traffic", &conn->dgst_ctx, conn->server_application_traffic_secret) != 1) {
error_print();
return -1;
}
if (conn->verbose == TLS_verbose_print_key) {
format_print(stderr, 0, 0, "generate_application_secrets\n");
format_bytes(stderr, 0, 4, "client_application_traffic_secret", conn->client_application_traffic_secret, conn->dgst_ctx.digest->digest_size);
format_bytes(stderr, 0, 4, "server_application_traffic_secret", conn->server_application_traffic_secret, conn->dgst_ctx.digest->digest_size);
}
return 1;
}
int tls13_update_client_application_secret(TLS_CONNECT *conn)
{
if (!conn || !conn->digest) {
error_print();
return -1;
}
if (tls13_hkdf_expand_label(conn->digest, conn->client_application_traffic_secret, "traffic upd", NULL, 0,
conn->digest->digest_size, conn->client_application_traffic_secret) != 1) {
error_print();
return -1;
}
if (conn->verbose == TLS_verbose_print_key) {
format_print(stderr, 0, 0, "update_client_application_secret\n");
format_bytes(stderr, 0, 4, "client_application_traffic_secret",
conn->client_application_traffic_secret, conn->digest->digest_size);
}
return 1;
}
int tls13_update_server_application_secret(TLS_CONNECT *conn)
{
if (!conn || !conn->digest) {
error_print();
return -1;
}
if (tls13_hkdf_expand_label(conn->digest, conn->server_application_traffic_secret, "traffic upd", NULL, 0,
conn->digest->digest_size, conn->server_application_traffic_secret) != 1) {
error_print();
return -1;
}
if (conn->verbose == TLS_verbose_print_key) {
format_print(stderr, 0, 0, "update_server_application_secret\n");
format_bytes(stderr, 0, 4, "server_application_traffic_secret",
conn->server_application_traffic_secret, conn->digest->digest_size);
}
return 1;
}
int tls13_generate_client_application_keys(TLS_CONNECT *conn)
{
uint8_t client_write_key[16];
size_t client_write_key_len;
if (!conn || !conn->digest) {
error_print();
return -1;
}
client_write_key_len = conn->cipher->key_size;
if (tls13_hkdf_expand_label(conn->digest, conn->client_application_traffic_secret, "key", NULL, 0, client_write_key_len, client_write_key) != 1
|| tls13_hkdf_expand_label(conn->digest, conn->client_application_traffic_secret, "iv", NULL, 0, TLS13_IV_SIZE, conn->client_write_iv) != 1
|| block_cipher_set_encrypt_key(&conn->client_write_key, conn->cipher, client_write_key) != 1) {
error_print();
return -1;
}
tls_seq_num_reset(conn->client_seq_num);
if (conn->verbose == TLS_verbose_print_key) {
format_print(stderr, 0, 0, "update_client_application_keys\n");
format_bytes(stderr, 0, 4, "client_write_key", client_write_key, client_write_key_len);
format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, TLS13_IV_SIZE);
format_print(stderr, 0, 4, "client_seq_num: %"PRIu64"\n", GETU64(conn->client_seq_num));
}
gmssl_secure_clear(client_write_key, sizeof(client_write_key));
return 1;
}
int tls13_generate_server_application_keys(TLS_CONNECT *conn)
{
uint8_t server_write_key[16];
size_t server_write_key_len;
if (!conn || !conn->digest) {
error_print();
return -1;
}
server_write_key_len = conn->cipher->key_size;
if (tls13_hkdf_expand_label(conn->digest, conn->server_application_traffic_secret, "key", NULL, 0, server_write_key_len, server_write_key) != 1
|| tls13_hkdf_expand_label(conn->digest, conn->server_application_traffic_secret, "iv", NULL, 0, TLS13_IV_SIZE, conn->server_write_iv) != 1
|| block_cipher_set_encrypt_key(&conn->server_write_key, conn->cipher, server_write_key) != 1) {
error_print();
return -1;
}
tls_seq_num_reset(conn->server_seq_num);
if (conn->verbose == TLS_verbose_print_key) {
format_print(stderr, 0, 0, "update_server_application_keys\n");
format_bytes(stderr, 0, 4, "server_write_key", server_write_key, server_write_key_len);
format_bytes(stderr, 0, 4, "server_write_iv", conn->server_write_iv, TLS13_IV_SIZE);
format_print(stderr, 0, 4, "server_seq_num: %"PRIu64"\n", GETU64(conn->server_seq_num));
}
gmssl_secure_clear(server_write_key, sizeof(server_write_key));
return 1;
}
static const uint8_t TLS13_client_context_str_and_zero[] = "TLS 1.3, client CertificateVerify";
static const uint8_t TLS13_server_context_str_and_zero[] = "TLS 1.3, server CertificateVerify";
static size_t TLS13_client_context_str_and_zero_size = sizeof(TLS13_client_context_str_and_zero);
static size_t TLS13_server_context_str_and_zero_size = sizeof(TLS13_server_context_str_and_zero);
int tls13_sign_certificate_verify(int tls_mode, int sig_alg,
X509_KEY *sign_key, const DIGEST_CTX *tbs_dgst_ctx,
uint8_t *sig, size_t *siglen)
{
uint8_t prefix[64];
const uint8_t *context_str_and_zero;
size_t context_str_and_zero_len;
DIGEST_CTX dgst_ctx;
uint8_t dgst[64];
size_t dgstlen;
X509_SIGN_CTX sign_ctx;
const char *signer_id = NULL;
size_t signer_id_len = 0;
if (!sign_key || !tbs_dgst_ctx || !sig || !siglen) {
error_print();
return -1;
}
memset(prefix, 0x20, 64);
switch (tls_mode) {
case TLS_client_mode:
context_str_and_zero = TLS13_client_context_str_and_zero;
context_str_and_zero_len = TLS13_client_context_str_and_zero_size;
break;
case TLS_server_mode:
context_str_and_zero = TLS13_server_context_str_and_zero;
context_str_and_zero_len = TLS13_server_context_str_and_zero_size;
break;
default:
error_print();
return -1;
}
switch (sig_alg) {
case TLS_sig_sm2sig_sm3:
if (sign_key->algor != OID_ec_public_key
&& sign_key->algor_param != OID_sm2) {
error_print();
return -1;
}
if (tbs_dgst_ctx->digest->oid != OID_sm3) {
error_print();
return -1;
}
signer_id = TLS13_SM2_ID;
signer_id_len = TLS13_SM2_ID_LENGTH;
break;
case TLS_sig_ecdsa_secp256r1_sha256:
if (sign_key->algor != OID_ec_public_key
&& sign_key->algor_param != OID_secp256r1) {
error_print();
return -1;
}
if (tbs_dgst_ctx->digest->oid != OID_sha256) {
error_print();
return -1;
}
break;
default:
error_print();
return -1;
}
dgst_ctx = *tbs_dgst_ctx;
if (digest_finish(&dgst_ctx, dgst, &dgstlen) != 1) {
error_print();
return -1;
}
if (x509_sign_init(&sign_ctx, sign_key, signer_id, signer_id_len) != 1
|| x509_sign_update(&sign_ctx, prefix, 64) != 1
|| x509_sign_update(&sign_ctx, context_str_and_zero, context_str_and_zero_len) != 1
|| x509_sign_update(&sign_ctx, dgst, dgstlen) != 1
|| x509_sign_finish(&sign_ctx, sig, siglen) != 1) {
gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx));
error_print();
return -1;
}
/*
format_print(stderr, 0, 0, "sign_certificate_verify\n");
format_bytes(stderr, 0, 4, "transcript_hash", dgst, dgstlen);
format_bytes(stderr, 0, 4, "signature", sig, *siglen);
*/
gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx));
return 1;
}
int tls13_verify_certificate_verify(int tls_mode, int sig_alg,
const X509_KEY *public_key, const DIGEST_CTX *tbs_dgst_ctx,
const uint8_t *sig, size_t siglen)
{
int ret;
uint8_t prefix[64];
const uint8_t *context_str_and_zero;
size_t context_str_and_zero_len;
DIGEST_CTX dgst_ctx;
uint8_t dgst[64];
size_t dgstlen;
X509_SIGN_CTX sign_ctx;
const char *signer_id = NULL;
size_t signer_id_len = 0;
if (!public_key || !tbs_dgst_ctx || !sig || !siglen) {
error_print();
return -1;
}
memset(prefix, 0x20, 64);
switch (tls_mode) {
case TLS_client_mode:
context_str_and_zero = TLS13_client_context_str_and_zero;
context_str_and_zero_len = TLS13_client_context_str_and_zero_size;
break;
case TLS_server_mode:
context_str_and_zero = TLS13_server_context_str_and_zero;
context_str_and_zero_len = TLS13_server_context_str_and_zero_size;
break;
default:
error_print();
return -1;
}
switch (sig_alg) {
case TLS_sig_sm2sig_sm3:
if (public_key->algor != OID_ec_public_key
&& public_key->algor_param != OID_sm2) {
error_print();
return -1;
}
if (tbs_dgst_ctx->digest->oid != OID_sm3) {
error_print();
return -1;
}
signer_id = TLS13_SM2_ID;
signer_id_len = TLS13_SM2_ID_LENGTH;
break;
case TLS_sig_ecdsa_secp256r1_sha256:
if (public_key->algor != OID_ec_public_key
&& public_key->algor_param != OID_secp256r1) {
error_print();
return -1;
}
if (tbs_dgst_ctx->digest->oid != OID_sha256) {
error_print();
return -1;
}
break;
default:
error_print();
return -1;
}
dgst_ctx = *tbs_dgst_ctx;
if (digest_finish(&dgst_ctx, dgst, &dgstlen) != 1) {
error_print();
return -1;
}
/*
format_print(stderr, 0, 0, "verify_certificate_verify\n");
format_bytes(stderr, 0, 4, "transcript_hash", dgst, dgstlen);
format_bytes(stderr, 0, 4, "signature", sig, siglen);
*/
if (x509_verify_init(&sign_ctx, public_key, signer_id, signer_id_len, sig, siglen) != 1
|| x509_verify_update(&sign_ctx, prefix, 64) != 1
|| x509_verify_update(&sign_ctx, context_str_and_zero, context_str_and_zero_len) != 1
|| x509_verify_update(&sign_ctx, dgst, dgstlen) != 1) {
error_print();
return -1;
}
if ((ret = x509_verify_finish(&sign_ctx)) < 0) {
error_print();
return -1;
}
if (ret != 1) {
error_print();
}
return ret;
}
/*
Finished.verify_data
finished_key =
HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)
verify_data =
HMAC(finished_key, Transcript-Hash(Handshake Context, Certificate*, CertificateVerify*))
*/
int tls13_compute_verify_data(const uint8_t *handshake_traffic_secret,
const DIGEST_CTX *dgst_ctx, uint8_t *verify_data, size_t *verify_data_len)
{
DIGEST_CTX tmp_dgst_ctx;
uint8_t dgst[64];
size_t dgstlen;
uint8_t finished_key[64];
size_t finished_key_len;
if (!handshake_traffic_secret || !dgst_ctx || !verify_data || !verify_data_len) {
error_print();
return -1;
}
finished_key_len = dgst_ctx->digest->digest_size;
if (tls13_hkdf_expand_label(dgst_ctx->digest, handshake_traffic_secret,
"finished", NULL, 0, finished_key_len, finished_key) != 1) {
error_print();
return -1;
}
tmp_dgst_ctx = *dgst_ctx;
if (digest_finish(&tmp_dgst_ctx, dgst, &dgstlen) != 1) {
gmssl_secure_clear(finished_key, sizeof(finished_key));
error_print();
return -1;
}
if (hmac(dgst_ctx->digest, finished_key, finished_key_len, dgst, dgstlen,
verify_data, verify_data_len) != 1) {
gmssl_secure_clear(finished_key, sizeof(finished_key));
error_print();
return -1;
}
/*
format_print(stderr, 0, 0, "compute_verify_data\n");
format_bytes(stderr, 0, 4, "finished_key", finished_key, finished_key_len);
format_bytes(stderr, 0, 4, "transcript_hash", dgst, dgstlen);
format_bytes(stderr, 0, 4, "verify_data", verify_data, *verify_data_len);
*/
gmssl_secure_clear(finished_key, sizeof(finished_key));
return 1;
}
int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *sentlen)
{
int ret = 1;
if (!data || !datalen) {
error_print();
return 0;
}
*sentlen = 0;
if (!conn->recordlen) {
const BLOCK_CIPHER_KEY *key;
const uint8_t *iv;
uint8_t *seq_num;
size_t padding_len = 0;
int request_update = 0;
if (conn->is_client) {
key = &conn->client_write_key;
iv = conn->client_write_iv;
seq_num = conn->client_seq_num;
//format_bytes(stderr, 0, 4, "client_write_iv", iv, 12);
//format_bytes(stderr, 0, 4, "client_seq_num", seq_num, 8);
//format_print(stderr, 0, 0, "\n");
} else {
key = &conn->server_write_key;
iv = conn->server_write_iv;
seq_num = conn->server_seq_num;
//format_bytes(stderr, 0, 4, "server_write_iv", iv, 12);
//format_bytes(stderr, 0, 4, "server_seq_num", seq_num, 8);
//format_print(stderr, 0, 0, "\n");
}
// check if KeyUpdate
if (conn->ctx->key_update
&& GETU64(seq_num) >= conn->ctx->key_update_seq_num_limit) {
if (!conn->key_update) {
conn->key_update = 1;
request_update = 1;
}
}
if (conn->key_update) {
if (conn->is_client) {
ret = tls13_send_client_key_update(conn, request_update);
} else {
ret = tls13_send_server_key_update(conn, request_update);
}
if (ret == 1) {
ret = TLS_ERROR_SEND_AGAIN;
}
return ret;
}
if (datalen > TLS_MAX_PLAINTEXT_SIZE) {
datalen = TLS_MAX_PLAINTEXT_SIZE;
}
if(conn->verbose) {
format_bytes(stderr, 0, 0, "send", data, datalen);
}
tls13_padding_len_rand(&padding_len);
if (tls_record_set_application_data(conn->plain_record, &conn->plain_recordlen,
data, datalen) != 1) {
error_print();
return -1;
}
if (tls13_record_encrypt(conn->cipher_suite, key, iv,
seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(seq_num);
ret = 1;
conn->record_offset = 0;
conn->send_state = TLS_state_send_record;
// 需要记录密文对应的明文是什么,当完整的报文发送之后,这些信息要返回给调用方
//conn->plain_recordlen = datalen + 5;
conn->sentlen = datalen;
if(conn->verbose) tls_trace("send {ApplicationData}\n");
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
}
while (conn->recordlen) {
tls_ret_t n;
n = tls_socket_send(conn->sock, conn->record + conn->record_offset, conn->recordlen, 0);
if (n < 0) {
int err = tls_socket_get_error();
tls_socket_err_t type = tls_socket_get_error_type(err, 0);
if (type == TLS_SOCKET_ERR_WANT_WRITE) {
return TLS_ERROR_SEND_AGAIN;
} else if (type == TLS_SOCKET_ERR_INTERRUPTED) {
continue;
}
error_print();
return TLS_ERROR_SYSCALL;
} else if (n == 0) {
return TLS_ERROR_TCP_CLOSED;
}
conn->recordlen -= n;
conn->record_offset += n;
}
//*sentlen = conn->plain_recordlen - 5;
*sentlen = conn->sentlen;
conn->record_offset = 0;
conn->send_state = 0;
return ret;
}
int tls13_do_recv(TLS_CONNECT *conn)
{
tls_ret_t n;
const BLOCK_CIPHER_KEY *key;
const uint8_t *iv;
uint8_t *seq_num;
switch (conn->recv_state) {
case 0:
conn->record_offset = 0;
conn->recordlen = TLS_RECORD_HEADER_SIZE;
conn->recv_state = TLS_state_recv_record_header;
case TLS_state_recv_record_header:
while (conn->recordlen) {
n = tls_socket_recv(conn->sock, conn->record + conn->record_offset, conn->recordlen, 0);
if (n < 0) {
int err = tls_socket_get_error();
tls_socket_err_t type = tls_socket_get_error_type(err, 1);
if (type == TLS_SOCKET_ERR_WANT_READ) {
return TLS_ERROR_RECV_AGAIN;
} else if (type == TLS_SOCKET_ERR_INTERRUPTED) {
continue;
}
error_print();
return TLS_ERROR_SYSCALL;
} else if (n == 0) {
return TLS_ERROR_TCP_CLOSED;
}
conn->recordlen -= n;
conn->record_offset += n;
}
if (tls_record_type(conn->record) != TLS_record_application_data) {
error_print();
return -1;
}
if (tls_record_protocol(conn->record) != TLS_protocol_tls12) {
error_print();
return -1;
}
if (tls_record_data_length(conn->record) > TLS_MAX_RECORD_SIZE - TLS_RECORD_HEADER_SIZE) {
error_print();
return -1;
}
conn->recordlen = tls_record_data_length(conn->record);
conn->recv_state = TLS_state_recv_record_data;
// pass through
case TLS_state_recv_record_data:
while (conn->recordlen) {
n = tls_socket_recv(conn->sock, conn->record + conn->record_offset, conn->recordlen, 0);
if (n < 0) {
int err = tls_socket_get_error();
tls_socket_err_t type = tls_socket_get_error_type(err, 1);
if (type == TLS_SOCKET_ERR_WANT_READ) {
return TLS_ERROR_RECV_AGAIN;
} else if (type == TLS_SOCKET_ERR_INTERRUPTED) {
continue;
}
error_print();
return TLS_ERROR_SYSCALL;
} else if (n == 0) {
return TLS_ERROR_TCP_CLOSED;
}
conn->recordlen -= n;
conn->record_offset += n;
}
conn->recv_state = 0;
break;
default:
fprintf(stderr, "conn->recv_state = %d\n", conn->recv_state);
error_print();
return -1;
}
conn->recordlen = tls_record_length(conn->record);
if(conn->verbose) tls_trace("recv {Record}\n");
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
if (conn->is_client) {
key = &conn->server_write_key;
iv = conn->server_write_iv;
seq_num = conn->server_seq_num;
//format_bytes(stderr, 0, 4, "server_write_iv", iv, 12);
//format_bytes(stderr, 0, 4, "server_seq_num", seq_num, 8);
//format_print(stderr, 0, 0, "\n");
} else {
key = &conn->client_write_key;
iv = conn->client_write_iv;
seq_num = conn->client_seq_num;
//format_bytes(stderr, 0, 4, "client_write_iv", iv, 12);
//format_bytes(stderr, 0, 4, "client_seq_num", seq_num, 8);
//format_print(stderr, 0, 0, "\n");
}
if (tls13_record_decrypt(conn->cipher_suite, key, iv, seq_num, conn->record, conn->recordlen,
conn->plain_record, &conn->plain_recordlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(seq_num);
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
switch (tls_record_type(conn->plain_record)) {
case TLS_record_application_data:
conn->data = conn->plain_record + 5;
conn->datalen = conn->plain_recordlen - 5;
break;
case TLS_record_handshake:
{
int handshake_type;
const uint8_t *handshake_data;
size_t handshake_datalen;
int update_requested;
if (tls_record_get_handshake(conn->plain_record, &handshake_type, &handshake_data, &handshake_datalen) != 1) {
error_print();
return -1;
}
switch (handshake_type) {
// NewSessionTicket 也不应该是被单独接收的只能在解密并解析了handshake之后才可以
case TLS_handshake_new_session_ticket:
if (tls13_process_new_session_ticket(conn) != 1) {
error_print();
return -1;
}
conn->data = NULL;
conn->datalen = 0;
break;
case TLS_handshake_key_update:
if (tls13_record_get_handshake_key_update(conn->plain_record, &update_requested) != 1) {
error_print();
return -1;
}
// 如果对方要求KeyUpdate并且也满足我方KeyUpdate的最低条件
// 那么我们就设置key_update标志位
// 下次发送的时候就启动KeyUpdate
if (conn->is_client) {
uint64_t seq_num;
tls13_update_server_application_secret(conn);
tls13_generate_server_application_keys(conn);
seq_num = GETU64(conn->client_seq_num);
if (seq_num > 2 && update_requested && conn->ctx->key_update) {
conn->key_update = 1;
}
} else {
uint64_t seq_num;
tls13_update_client_application_secret(conn);
tls13_generate_client_application_keys(conn);
seq_num = GETU64(conn->server_seq_num);
if (seq_num > 2 && update_requested && conn->ctx->key_update) {
if(conn->verbose) {
fprintf(stderr, "server prepare key_update\n");
}
conn->key_update = 1;
}
}
conn->data = NULL;
conn->datalen = 0;
break;
default:
error_print();
return -1;
}
}
break;
case TLS_record_alert:
{
int alert_level;
int alert_description;
if (tls_record_get_alert(conn->plain_record, &alert_level, &alert_description) != 1) {
error_print();
return -1;
}
if (alert_description == TLS_alert_close_notify) {
if(conn->verbose) tls_trace("recv {Alert.close_notify}\n");
conn->close_notify_received = 1;
conn->data = NULL;
conn->datalen = 0;
conn->record_offset = 0;
conn->recordlen = 0;
conn->plain_recordlen = 0;
return 0;
}
}
return -1;
default:
error_print();
return -1;
}
return 1;
}
int tls13_recv(TLS_CONNECT *conn, uint8_t *out, size_t outlen, size_t *recvlen)
{
if (!conn || !out || !outlen || !recvlen) {
error_print();
return -1;
}
*recvlen = 0;
if (conn->datalen == 0) {
int ret;
for (;;) {
if ((ret = tls13_do_recv(conn)) != 1) {
if (ret != 0 && ret != TLS_ERROR_RECV_AGAIN && ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
if (conn->datalen) {
break;
}
conn->record_offset = 0;
conn->recordlen = 0;
conn->plain_recordlen = 0;
}
}
*recvlen = outlen <= conn->datalen ? outlen : conn->datalen;
memcpy(out, conn->data, *recvlen);
conn->data += *recvlen;
conn->datalen -= *recvlen;
// 这里接受完成之后应该recordlen = 0
conn->recordlen = 0;
return 1;
}
// 这里需要考虑max_early_data_size的问题
int tls13_recv_early_data(TLS_CONNECT *conn)
{
int ret;
if(conn->verbose) tls_trace("recv EarlyData\n");
if ((ret = tls13_do_recv(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN && ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
if (conn->datalen > sizeof(conn->early_data_buf)) {
error_print();
return -1;
}
memcpy(conn->early_data_buf, conn->data, conn->datalen);
conn->early_data_len = conn->datalen;
if(conn->verbose) {
format_string(stderr, 0, 4, "EarlyData", conn->early_data_buf, conn->early_data_len);
}
// 清空记录,防止后续的握手处理过程出现问题
// 需要考虑统一的record状态更新
// 还需要考虑 tls13_recv 如何消费掉 early_data
conn->record_offset = 0;
conn->recordlen = 0;
conn->plain_recordlen = 0;
return 1;
}
int tls13_ctx_set_max_key_exchanges(TLS_CTX *ctx, size_t cnt)
{
size_t key_exchanges_capacity
= sizeof(((TLS_CONNECT *)0)->key_exchanges)/sizeof(((TLS_CONNECT *)0)->key_exchanges[0]);
if (!ctx) {
error_print();
return -1;
}
if (cnt > key_exchanges_capacity) {
cnt = key_exchanges_capacity;
}
ctx->key_exchanges_cnt = cnt;
return 1;
}
int tls13_enable_post_handshake_auth(TLS_CONNECT *conn)
{
if (!conn) {
error_print();
return -1;
}
conn->post_handshake_auth = 1;
return 1;
}
// Extensions
/*
43. supported_versions
struct {
ProtocolVersion versions<2..254>;
} SupportedVersions; -- in ClientHello, ClientHello2
*/
int tls13_client_supported_versions_ext_to_bytes(const int *versions, size_t versions_cnt,
uint8_t **out, size_t *outlen)
{
uint16_t ext_type = TLS_extension_supported_versions;
size_t ext_datalen;
size_t versions_len;
size_t i;
if (!versions || !versions_cnt || !outlen) {
error_print();
return -1;
}
if (versions_cnt > 254/2) {
error_print();
return -1;
}
for (i = 0; i < versions_cnt; i++) {
if (!tls_protocol_name(versions[i])) {
error_print();
return -1;
}
}
versions_len = tls_uint16_size() * versions_cnt;
ext_datalen = tls_uint8_size() + versions_len;
tls_uint16_to_bytes(ext_type, out, outlen);
tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen);
tls_uint8_to_bytes((uint8_t)versions_len, out, outlen);
for (i = 0; i < versions_cnt; i++) {
tls_uint16_to_bytes((uint16_t)versions[i], out, outlen);
}
return 1;
}
int tls13_process_client_supported_versions(const uint8_t *ext_data, size_t ext_datalen,
const int *server_versions, size_t server_versions_cnt,
int *common_versions, size_t *common_versions_cnt, size_t max_cnt)
{
const uint8_t *versions;
size_t versions_len;
const uint8_t *cp;
size_t len;
uint16_t version;
size_t i, j = 0;
if (tls_uint8array_from_bytes(&versions, &versions_len, &ext_data, &ext_datalen) != 1
|| tls_length_is_zero(ext_datalen) != 1) {
error_print();
return -1;
}
if (versions_len < 2 || versions_len > 254) {
error_print();
return -1;
}
cp = versions;
len = versions_len;
while (len) {
if (tls_uint16_from_bytes(&version, &cp, &len) != 1) {
error_print();
return -1;
}
if (!tls_protocol_name(version)) {
error_print();
return -1;
}
if (version == server_versions[0] && j < max_cnt) {
common_versions[j++] = version;
}
}
for (i = 1; i < server_versions_cnt && j < max_cnt; i++) {
cp = versions;
len = versions_len;
while (len) {
tls_uint16_from_bytes(&version, &cp, &len);
if (version == server_versions[i]) {
common_versions[j++] = version;
break;
}
}
}
*common_versions_cnt = j;
if (*common_versions_cnt == 0) {
error_print();
return 0;
}
return 1;
}
int tls13_client_supported_versions_print(FILE *fp, int fmt, int ind,
const uint8_t *ext_data, size_t ext_datalen)
{
const uint8_t *versions;
size_t versions_len;
format_print(fp, fmt, ind, "versions\n");
ind += 4;
if (tls_uint8array_from_bytes(&versions, &versions_len, &ext_data, &ext_datalen) != 1) {
error_print();
return -1;
}
if (versions_len < 2 || versions_len > 254) {
error_print();
return -1;
}
while (versions_len) {
uint16_t version;
if (tls_uint16_from_bytes(&version, &versions, &versions_len) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "%s (%04x)\n", tls_protocol_name(version), version);
}
if (ext_datalen) {
error_print();
return -1;
}
return 1;
}
/*
struct {
ProtocolVersion selected_version;
} SupportedVersions; -- in ServerHello and HelloRetryRequest
*/
int tls13_server_supported_versions_ext_to_bytes(int selected_version, uint8_t **out, size_t *outlen)
{
uint16_t ext_type = TLS_extension_supported_versions;
size_t ext_datalen;
if (!outlen) {
error_print();
return -1;
}
if (!tls_protocol_name(selected_version)) {
error_print();
return -1;
}
ext_datalen = tls_uint16_size();
tls_uint16_to_bytes(ext_type, out, outlen);
tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen);
tls_uint16_to_bytes(selected_version, out, outlen);
return 1;
}
int tls13_server_supported_versions_from_bytes(int *selected_version, const uint8_t *ext_data, size_t ext_datalen)
{
uint16_t version;
if (tls_uint16_from_bytes(&version, &ext_data, &ext_datalen) != 1
|| tls_length_is_zero(ext_datalen) != 1) {
error_print();
return -1;
}
if (!tls_protocol_name(version)) {
error_print();
return -1;
}
*selected_version = version;
return 1;
}
int tls13_process_server_supported_versions(const int *client_versions, size_t client_versions_cnt,
const uint8_t *server_ext_data, size_t server_ext_datalen,
int *selected_version)
{
uint16_t version;
size_t i;
if (tls_uint16_from_bytes(&version, &server_ext_data, &server_ext_datalen) != 1
|| tls_length_is_zero(server_ext_datalen) != 1) {
error_print();
return -1;
}
for (i = 0; i < client_versions_cnt; i++) {
if (version == client_versions[i]) {
*selected_version = version;
return 1;
}
}
error_print();
return -1;
}
int tls13_server_supported_versions_print(FILE *fp, int fmt, int ind,
const uint8_t *ext_data, size_t ext_datalen)
{
uint16_t version;
if (tls_uint16_from_bytes(&version, &ext_data, &ext_datalen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "selected_version: %s (%04x)\n", tls_protocol_name(version), version);
if (ext_datalen) {
error_print();
return -1;
}
return 1;
}
/*
47. certificate_authorities
opaque DistinguishedName<1..2^16-1>;
struct {
DistinguishedName authorities<3..2^16-1>;
} CertificateAuthoritiesExtension;
*/
int tls13_certificate_authorities_ext_to_bytes(const uint8_t *ca_names, size_t ca_names_len,
uint8_t **out, size_t *outlen)
{
int ext_type = TLS_extension_certificate_authorities;
if (!ca_names || !ca_names_len || !outlen) {
error_print();
return -1;
}
tls_uint16_to_bytes(ext_type, out, outlen);
tls_uint16_to_bytes((uint16_t)(tls_uint16_size() + ca_names_len), out, outlen);
tls_uint16array_to_bytes(ca_names, ca_names_len, out, outlen);
return 1;
}
int tls13_certificate_authorities_from_bytes(const uint8_t **ca_names, size_t *ca_names_len,
const uint8_t *ext_data, size_t ext_datalen)
{
if (tls_uint16array_from_bytes(ca_names, ca_names_len, &ext_data, &ext_datalen) != 1
|| tls_length_is_zero(ext_datalen) != 1) {
error_print();
return -1;
}
if (*ca_names == NULL) {
error_print();
return -1;
}
return 1;
}
int tls13_enable_certificate_authorities(TLS_CONNECT *conn, int enable)
{
if (!conn) {
error_print();
return -1;
}
if (!conn->ctx->cacertslen) {
error_print();
return -1;
}
conn->certificate_authorities = enable ? 1 : 0;
return 1;
}
int tls13_certificate_authorities_print(FILE *fp, int fmt, int ind,
const uint8_t *ext_data, size_t ext_datalen)
{
const uint8_t *authorities;
size_t authorities_len;
format_print(fp, fmt, ind, "authorities\n");
ind += 4;
if (tls_uint16array_from_bytes(&authorities, &authorities_len, &ext_data, &ext_datalen) != 1
|| tls_length_is_zero(ext_datalen) != 1) {
error_print();
return -1;
}
while (authorities_len) {
const uint8_t *name;
size_t namelen;
const uint8_t *d;
size_t dlen;
if (tls_uint16array_from_bytes(&name, &namelen, &authorities, &authorities_len) != 1) {
error_print();
return -1;
}
if (asn1_sequence_from_der(&d, &dlen, &name, &namelen) != 1
|| asn1_length_is_zero(namelen) != 1) {
error_print();
return -1;
}
x509_name_print(fp, fmt, ind, "DistinguishedName", d, dlen);
}
return 1;
}
/*
48. oid_filters
struct {
OIDFilter filters<0..2^16-1>;
} OIDFilterExtension;
struct {
opaque certificate_extension_oid<1..2^8-1>;
opaque certificate_extension_values<0..2^16-1>;
} OIDFilter;
*/
int tls13_oid_filters_ext_to_bytes(const uint8_t *filters, size_t filters_len, uint8_t **out, size_t *outlen)
{
uint16_t ext_type = TLS_extension_oid_filters;
size_t ext_datalen;
if (!outlen) {
error_print();
return -1;
}
ext_datalen = tls_uint16_size() + filters_len;
tls_uint16_to_bytes(ext_type, out, outlen);
tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen);
tls_uint16array_to_bytes(filters, filters_len, out, outlen);
return 1;
}
int tls13_oid_filters_from_bytes(const uint8_t **filters, size_t *filters_len,
const uint8_t *ext_data, size_t ext_datalen)
{
if (tls_uint16array_from_bytes(filters, filters_len, &ext_data, &ext_datalen) != 1
|| tls_length_is_zero(ext_datalen) != 1) {
error_print();
return -1;
}
return 1;
}
int tls13_oid_filters_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
format_bytes(fp, fmt, ind, "data", d, dlen);
return 1;
}
/*
51. key_share
struct {
NamedGroup group;
opaque key_exchange<1..2^16-1>;
} KeyShareEntry;
*/
int tls13_key_share_entry_to_bytes(const X509_KEY *key, uint8_t **out, size_t *outlen)
{
uint16_t group;
uint8_t key_exchange[65];
if (!key || !outlen) {
error_print();
return -1;
}
if (key->algor != OID_ec_public_key) {
error_print();
return -1;
}
if (!(group = tls_named_curve_from_oid(key->algor_param))) {
error_print();
return -1;
}
if (out && *out) {
uint8_t *p = key_exchange;
size_t len = 0;
if (x509_public_key_to_bytes(key, &p, &len) != 1) {
error_print();
return -1;
}
if (len != 65) {
error_print();
return -1;
}
}
tls_uint16_to_bytes(group, out, outlen);
tls_uint16array_to_bytes(key_exchange, 65, out, outlen);
return 1;
}
int tls13_key_share_entry_from_bytes(int *group, const uint8_t **key_exchange, size_t *key_exchange_len,
const uint8_t **in, size_t *inlen)
{
uint16_t named_curve;
if (tls_uint16_from_bytes(&named_curve, in, inlen) != 1
|| tls_uint16array_from_bytes(key_exchange, key_exchange_len, in, inlen) != 1) {
error_print();
return -1;
}
switch (named_curve) {
case TLS_curve_secp256r1:
case TLS_curve_sm2p256v1:
if (*key_exchange_len != 65) {
error_print();
return -1;
}
break;
}
*group = named_curve;
return 1;
}
/*
struct {
KeyShareEntry client_shares<0..2^16-1>;
} KeyShareClientHello;
*/
int tls13_key_share_client_hello_ext_to_bytes(const X509_KEY *keys, size_t keys_cnt, uint8_t **out, size_t *outlen)
{
uint16_t ext_type = TLS_extension_key_share;
size_t ext_datalen = 0;
size_t client_shares_len = 0;
size_t i;
for (i = 0; i < keys_cnt; i++) {
if (tls13_key_share_entry_to_bytes(&keys[i], NULL, &client_shares_len) != 1) {
error_print();
return -1;
}
}
ext_datalen = 2 + client_shares_len;
tls_uint16_to_bytes(ext_type, out, outlen);
tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen);
tls_uint16_to_bytes((uint16_t)client_shares_len, out, outlen);
for (i = 0; i < keys_cnt; i++) {
tls13_key_share_entry_to_bytes(&keys[i], out, outlen);
}
return 1;
}
// allow supported_groups, supported_groups_cnt == NULL, 0
int tls13_process_key_share_client_hello(const uint8_t *ext_data, size_t ext_datalen,
const int *supported_groups, size_t supported_groups_cnt,
int *group, const uint8_t **key_exchange, size_t *key_exchange_len)
{
int ret = 0;
const uint8_t *client_shares;
size_t client_shares_len;
size_t i;
if (tls_uint16array_from_bytes(&client_shares, &client_shares_len, &ext_data, &ext_datalen) != 1
|| tls_length_is_zero(ext_datalen) != 1) {
error_print();
return -1;
}
for (i = 0; i < supported_groups_cnt; i++) {
const uint8_t *cp = client_shares;
size_t len = client_shares_len;
int named_curve;
const uint8_t *point;
size_t pointlen;
while (len) {
if (tls13_key_share_entry_from_bytes(&named_curve, &point, &pointlen, &cp, &len) != 1) {
error_print();
return -1;
}
if (named_curve == supported_groups[i]) {
*group = named_curve;
*key_exchange = point;
*key_exchange_len = pointlen;
return 1;
}
}
}
return 0;
}
int tls13_process_key_share_client_hello_again(const uint8_t *ext_data, size_t ext_datalen,
int key_exchange_group, const uint8_t **key_exchange, size_t *key_exchange_len)
{
int ret = 0;
const uint8_t *client_shares;
size_t client_shares_len;
int group;
if (tls_uint16array_from_bytes(&client_shares, &client_shares_len, &ext_data, &ext_datalen) != 1
|| tls_length_is_zero(ext_datalen) != 1) {
error_print();
return -1;
}
if (tls13_key_share_entry_from_bytes(&group, key_exchange, key_exchange_len, &client_shares, &client_shares_len) != 1
|| tls_length_is_zero(client_shares_len) != 1) {
error_print();
return -1;
}
if (group != key_exchange_group) {
error_print();
return -1;
}
return 1;
}
int tls13_key_share_client_hello_print(FILE *fp, int fmt, int ind,
const uint8_t *data, size_t datalen)
{
const uint8_t *client_shares;
size_t client_shares_len;
format_print(fp, fmt, ind, "client_shares\n");
ind += 4;
if (tls_uint16array_from_bytes(&client_shares, &client_shares_len, &data, &datalen) != 1) {
error_print();
return -1;
}
if (!client_shares_len) {
format_print(fp, fmt, ind, "(null)\n");
}
while (client_shares_len) {
uint16_t group;
const uint8_t *key_exchange;
size_t key_exchange_len;
format_print(fp, fmt, ind, "KeyShareEntry\n");
if (tls_uint16_from_bytes(&group, &client_shares, &client_shares_len) != 1
|| tls_uint16array_from_bytes(&key_exchange, &key_exchange_len, &client_shares, &client_shares_len) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind + 4, "group: %s (%04x)\n", tls_named_curve_name(group), group);
format_bytes(fp, fmt, ind + 4, "key_exchange", key_exchange, key_exchange_len);
}
if (datalen) {
error_print();
return -1;
}
return 1;
}
/*
struct {
KeyShareEntry server_share;
} KeyShareServerHello;
*/
int tls13_key_share_server_hello_ext_to_bytes(const X509_KEY *key, uint8_t **out, size_t *outlen)
{
uint16_t ext_type = TLS_extension_key_share;
size_t ext_datalen = 0;
if (tls13_key_share_entry_to_bytes(key, NULL, &ext_datalen) != 1) {
error_print();
return -1;
}
tls_uint16_to_bytes(ext_type, out, outlen);
tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen);
tls13_key_share_entry_to_bytes(key, out, outlen);
return 1;
}
int tls13_key_share_server_hello_from_bytes(int *group, const uint8_t **key_exchange, size_t *key_exchange_len,
const uint8_t *ext_data, size_t ext_datalen)
{
if (tls13_key_share_entry_from_bytes(group, key_exchange, key_exchange_len,
&ext_data, &ext_datalen) != 1
|| tls_length_is_zero(ext_datalen) != 1) {
error_print();
return -1;
}
return 1;
}
int tls13_key_share_server_hello_print(FILE *fp, int fmt, int ind,
const uint8_t *data, size_t datalen)
{
uint16_t group;
const uint8_t *key_exchange;
size_t key_exchange_len;
format_print(fp, fmt, ind, "server_share\n");
ind += 4;
if (tls_uint16_from_bytes(&group, &data, &datalen) != 1
|| tls_uint16array_from_bytes(&key_exchange, &key_exchange_len, &data, &datalen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "group: %s (%04x)\n", tls_named_curve_name(group), group);
format_bytes(fp, fmt, ind, "key_exchange", key_exchange, key_exchange_len);
if (datalen) {
error_print();
return -1;
}
return 1;
}
/*
struct {
NamedGroup selected_group;
} KeyShareHelloRetryRequest;
*/
int tls13_key_share_hello_retry_request_ext_to_bytes(int selected_group, uint8_t **out, size_t *outlen)
{
uint16_t ext_type = TLS_extension_key_share;
uint8_t ext_data[2];
uint8_t *p = ext_data;
size_t len = 0;
tls_uint16_to_bytes((uint16_t)selected_group, &p, &len);
tls_ext_to_bytes(ext_type, ext_data, sizeof(ext_data), out, outlen);
return 1;
}
int tls13_key_share_hello_retry_request_from_bytes(int *selected_group, const uint8_t *ext_data, size_t ext_datalen)
{
uint16_t group;
if (tls_uint16_from_bytes(&group, &ext_data, &ext_datalen) != 1
|| tls_length_is_zero(ext_datalen) != 1) {
error_print();
return -1;
}
if (!tls_named_curve_name(group)) {
error_print();
return -1;
}
*selected_group = group;
return 1;
}
int tls13_key_share_hello_retry_request_print(FILE *fp, int fmt, int ind,
const uint8_t *ext_data, size_t ext_datalen)
{
uint16_t selected_group;
if (tls_uint16_from_bytes(&selected_group, &ext_data, &ext_datalen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "selected_group: %s (%04x)\n",
tls_named_curve_name(selected_group), selected_group);
if (ext_datalen) {
error_print();
return -1;
}
return 1;
}
// Handshakes
// ClientHello
// ServerHello
// HelloRetryRequest
// EncryptedExtensions
// Certificate
// CertificateRequest
// CertificateVerify
// Finished
// KeyUpdate
/*
ClientHello
struct {
ProtocolVersion legacy_version = 0x0303;
Random random;
opaque legacy_session_id<0..32>;
CipherSuite cipher_suites<2..2^16-2>;
opaque legacy_compression_methods<1..2^8-1>;
Extension extensions<8..2^16-1>;
} ClientHello;
uint16 ProtocolVersion;
opaque Random[32];
uint8 CipherSuite[2];
*/
int tls13_ctx_set_client_hello_key_exchanges_cnt(TLS_CTX *ctx, size_t cnt)
{
if (!ctx) {
error_print();
return -1;
}
if (cnt > sizeof(((TLS_CONNECT *)NULL)->key_exchanges)/sizeof(((TLS_CONNECT *)NULL)->key_exchanges[0])) {
error_print();
return -1;
}
ctx->key_exchanges_cnt = cnt;
return 1;
}
int tls13_client_hello_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
uint16_t protocol;
const uint8_t *random;
const uint8_t *session_id;
const uint8_t *cipher_suites;
const uint8_t *comp_meths;
const uint8_t *exts;
size_t session_id_len, cipher_suites_len, comp_meths_len, extslen;
size_t i;
format_print(fp, fmt, ind, "ClientHello\n");
ind += 4;
if (tls_uint16_from_bytes(&protocol, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "legacy_version: %s (%04x)\n",
tls_protocol_name(protocol), protocol);
if (tls_array_from_bytes(&random, 32, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "random", random ,32);
if (tls_uint8array_from_bytes(&session_id, &session_id_len, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "legacy_session_id", session_id, session_id_len);
format_print(fp, fmt, ind, "cipher_suites\n");
if (tls_uint16array_from_bytes(&cipher_suites, &cipher_suites_len, &d, &dlen) != 1) {
error_print();
return -1;
}
while (cipher_suites_len) {
uint16_t cipher;
if (tls_uint16_from_bytes(&cipher, &cipher_suites, &cipher_suites_len) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind+4, "%s (%04x)\n", tls_cipher_suite_name(cipher), cipher);
}
format_print(fp, fmt, ind, "legacy_compression_methods\n");
if (tls_uint8array_from_bytes(&comp_meths, &comp_meths_len, &d, &dlen) != 1) {
error_print();
return -1;
}
for (i = 0; i < comp_meths_len; i++) {
format_print(fp, fmt, ind + 4, "%s (%d)\n",
tls_compression_method_name(comp_meths[i]), comp_meths[i]);
}
format_print(fp, fmt, ind, "extensions\n");
ind += 4;
if (tls_uint16array_from_bytes(&exts, &extslen, &d, &dlen) != 1) {
error_print();
return -1;
}
while (extslen) {
uint16_t ext_type;
const char *ext_name;
const uint8_t *ext_data;
size_t ext_datalen;
// tls_ext_from_bytes can not parse unknown ext
if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
return -1;
}
ext_name = tls_extension_name(ext_type);
if (!ext_name) {
ext_name = "(unknown)";
}
format_print(fp, fmt, ind, "%s (%d)\n", ext_name, ext_type);
switch (ext_type) {
case TLS_extension_supported_versions:
tls13_client_supported_versions_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_signature_algorithms:
tls_signature_algorithms_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_signature_algorithms_cert:
tls_signature_algorithms_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_certificate_authorities:
tls13_certificate_authorities_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_server_name:
tls_server_name_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_status_request:
tls_client_status_request_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_signed_certificate_timestamp:
format_bytes(fp, fmt, ind + 4, "data", ext_data, ext_datalen); // should be empty
break;
case TLS_extension_supported_groups:
tls_supported_groups_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_key_share:
tls13_key_share_client_hello_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_psk_key_exchange_modes:
tls13_psk_key_exchange_modes_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_pre_shared_key:
tls13_client_pre_shared_key_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_early_data:
tls13_early_data_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_cookie:
tls13_cookie_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_post_handshake_auth:
format_bytes(fp, fmt, ind + 4, "data", ext_data, ext_datalen); // should be empty
break;
case TLS_extension_ec_point_formats:
tls_ec_point_formats_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_max_fragment_length:
case TLS_extension_use_srtp:
case TLS_extension_heartbeat:
case TLS_extension_application_layer_protocol_negotiation:
case TLS_extension_server_certificate_type:
case TLS_extension_client_certificate_type:
case TLS_extension_padding:
case TLS_extension_record_size_limit:
format_bytes(fp, fmt, ind + 4, "data", ext_data, ext_datalen);
break;
default:
format_bytes(fp, fmt, ind + 4, "data", ext_data, ext_datalen);
}
}
if (dlen) {
error_print();
return -1;
}
return 1;
}
// ServerHello.random if HelloRetryReqeust
static const unsigned char TLS13_HELLO_RETRY_REQUEST_RANDOM[32] = {
0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,
0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C
};
/*
ServerHello
struct {
ProtocolVersion legacy_version = 0x0303;
Random random;
opaque legacy_session_id_echo<0..32>;
CipherSuite cipher_suite;
uint8 legacy_compression_method = 0;
Extension extensions<6..2^16-1>;
} ServerHello;
*/
int tls13_server_hello_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
int hello_retry_request = 0;
uint16_t protocol;
const uint8_t *random;
const uint8_t *session_id;
uint16_t cipher_suite;
uint8_t comp_meth;
const uint8_t *exts;
size_t session_id_len, extslen;
format_print(fp, fmt, ind, "ServerHello\n");
ind += 4;
if (tls_uint16_from_bytes(&protocol, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "legacy_version: %s (%04x)\n",
tls_protocol_name(protocol), protocol);
if (tls_array_from_bytes(&random, 32, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "random", random, 32);
// if ServerHello is HelloRetryRequest
if (memcmp(random, TLS13_HELLO_RETRY_REQUEST_RANDOM, 32) == 0) {
hello_retry_request = 1;
}
if (tls_uint8array_from_bytes(&session_id, &session_id_len, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "legacy_session_id", session_id, session_id_len);
if (tls_uint16_from_bytes(&cipher_suite, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "cipher_suite: %s (%04x)\n",
tls_cipher_suite_name(cipher_suite), cipher_suite);
if (tls_uint8_from_bytes(&comp_meth, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "legacy_compression_method: %s (%d)\n",
tls_compression_method_name(comp_meth), comp_meth);
format_print(fp, fmt, ind, "extensions\n");
ind += 4;
if (tls_uint16array_from_bytes(&exts, &extslen, &d, &dlen) != 1) {
error_print();
return -1;
}
while (extslen) {
uint16_t ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "%s (%d)\n", tls_extension_name(ext_type), ext_type);
switch (ext_type) {
case TLS_extension_supported_versions:
tls13_server_supported_versions_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_key_share:
if (hello_retry_request)
tls13_key_share_hello_retry_request_print(fp, fmt, ind + 4, ext_data, ext_datalen);
else tls13_key_share_server_hello_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_pre_shared_key:
tls13_server_pre_shared_key_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_cookie:
tls13_cookie_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
default:
format_bytes(fp, fmt, ind + 4, "raw_data", ext_data, ext_datalen);
error_print();
return -1;
}
}
if (dlen) {
error_print();
return -1;
}
return 1;
}
/*
HelloRetryReqeust
For reasons of backward compatibility with middleboxes (see
Appendix D.4), the HelloRetryRequest message uses the same structure
as the ServerHello, but with Random set to the special value of the
SHA-256 of "HelloRetryRequest":
CF 21 AD 74 E5 9A 61 11 BE 1D 8C 02 1E 65 B8 91
C2 A2 11 16 7A BB 8C 5E 07 9E 09 E2 C8 A8 33 9C
TLS 1.3 has a downgrade protection mechanism embedded in the server's
random value. TLS 1.3 servers which negotiate TLS 1.2 or below in
response to a ClientHello MUST set the last 8 bytes of their Random
value specially in their ServerHello.
If negotiating TLS 1.2, TLS 1.3 servers MUST set the last 8 bytes of
their Random value to the bytes:
44 4F 57 4E 47 52 44 01
If negotiating TLS 1.1 or below, TLS 1.3 servers MUST, and TLS 1.2
servers SHOULD, set the last 8 bytes of their ServerHello.Random
value to the bytes:
44 4F 57 4E 47 52 44 00
*/
int tls13_record_set_handshake_hello_retry_request(uint8_t *record, size_t *recordlen,
int legacy_version, const uint8_t random[32],
const uint8_t *legacy_session_id_echo, size_t legacy_session_id_echo_len,
int cipher_suite, int legacy_compress_meth,
const uint8_t *exts, size_t extslen)
{
//int type = TLS_handshake_hello_retry_request;
int type = TLS_handshake_server_hello;
uint8_t *p;
size_t len;
if (!tls_protocol_name(legacy_version)) {
error_print();
return -1;
}
if (legacy_session_id_echo_len > 32) {
error_print();
return -1;
}
if (!tls_cipher_suite_name(cipher_suite)) {
error_print();
return -1;
}
if (legacy_compress_meth > 255) {
error_print();
return -1;
}
p = tls_handshake_data(tls_record_data(record));
len = 0;
tls_uint16_to_bytes((uint16_t)legacy_version, &p, &len);
tls_array_to_bytes(random, 32, &p, &len);
tls_uint8array_to_bytes(legacy_session_id_echo, legacy_session_id_echo_len, &p, &len);
tls_uint16_to_bytes((uint16_t)cipher_suite, &p, &len);
tls_uint8_to_bytes((uint8_t)legacy_compress_meth, &p, &len);
tls_uint16array_to_bytes(exts, extslen, &p, &len);
if (tls_record_set_handshake(record, recordlen, type, NULL, len) != 1) {
error_print();
return -1;
}
return 1;
}
int tls13_record_get_handshake_hello_retry_request(uint8_t *record,
int *legacy_version, const uint8_t **random,
const uint8_t **legacy_session_id_echo, size_t *legacy_session_id_echo_len,
int *cipher_suite, int *legacy_compress_meth,
const uint8_t **exts, size_t *extslen)
{
int type;
const uint8_t *cp;
size_t len;
uint16_t version;
uint16_t cipher;
uint8_t comp_meth;
if (tls_record_get_handshake(record, &type, &cp, &len) != 1) {
error_print();
return -1;
}
if (type != TLS_handshake_hello_retry_request
&& type != TLS_handshake_server_hello) {
error_print();
return -1;
}
if (tls_uint16_from_bytes(&version, &cp, &len) != 1
|| tls_array_from_bytes(random, 32, &cp, &len) != 1
|| tls_uint8array_from_bytes(legacy_session_id_echo, legacy_session_id_echo_len, &cp, &len) != 1
|| tls_uint16_from_bytes(&cipher, &cp, &len) != 1
|| tls_uint8_from_bytes(&comp_meth, &cp, &len) != 1
|| tls_uint16array_from_bytes(exts, extslen, &cp, &len) != 1
|| tls_length_is_zero(len) != 1) {
error_print();
return -1;
}
// if legacy_version != tls12, send protocol_version alert
if (!tls_protocol_name(version)) {
error_print();
return -1;
}
if (version != TLS_protocol_tls12) {
error_print();
}
*legacy_version = version;
if (*legacy_session_id_echo_len > 32) {
error_print();
return -1;
}
if (!tls_cipher_suite_name(cipher)) {
error_print();
return -1;
}
*cipher_suite = cipher;
// if legacy_compress_meth != 0, send illegal_parameter alert
if (comp_meth != 0) {
error_print();
}
*legacy_compress_meth = comp_meth;
if (*extslen < 6) {
error_print();
return -1;
}
return 1;
}
int tls13_hello_retry_request_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
uint16_t protocol;
const uint8_t *random;
const uint8_t *session_id;
uint16_t cipher_suite;
uint8_t comp_meth;
const uint8_t *exts;
size_t session_id_len, extslen;
format_print(fp, fmt, ind, "HelloRetryRequest\n");
ind += 4;
if (tls_uint16_from_bytes(&protocol, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "legacy_version: %s (%04x)\n",
tls_protocol_name(protocol), protocol);
if (tls_array_from_bytes(&random, 32, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "random", random, 32);
if (tls_uint8array_from_bytes(&session_id, &session_id_len, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "legacy_session_id", session_id, session_id_len);
if (tls_uint16_from_bytes(&cipher_suite, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "cipher_suite: %s (%04x)\n",
tls_cipher_suite_name(cipher_suite), cipher_suite);
if (tls_uint8_from_bytes(&comp_meth, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "legacy_compression_method: %s (%d)\n",
tls_compression_method_name(comp_meth), comp_meth);
format_print(fp, fmt, ind, "extensions\n");
ind += 4;
if (tls_uint16array_from_bytes(&exts, &extslen, &d, &dlen) != 1) {
error_print();
return -1;
}
while (extslen) {
uint16_t ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "%s (%d)\n", tls_extension_name(ext_type), ext_type);
switch (ext_type) {
case TLS_extension_supported_versions:
tls13_server_supported_versions_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_key_share:
tls13_key_share_hello_retry_request_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_pre_shared_key:
tls13_client_pre_shared_key_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_cookie:
tls13_cookie_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
default:
format_bytes(fp, fmt, ind + 4, "raw_data", ext_data, ext_datalen);
return -1;
}
}
if (dlen) {
error_print();
return -1;
}
return 1;
}
/*
EncrypytedExtensions
struct {
Extension extensions<0..2^16-1>;
} EncryptedExtensions;
*/
int tls13_record_set_handshake_encrypted_extensions(uint8_t *record, size_t *recordlen,
const uint8_t *exts, size_t extslen)
{
int type = TLS_handshake_encrypted_extensions;
uint8_t *p = record + 5 + 4;
size_t len = 0;
tls_uint16array_to_bytes(exts, extslen, &p, &len);
tls_record_set_handshake(record, recordlen, type, NULL, len);
return 1;
}
int tls13_record_get_handshake_encrypted_extensions(const uint8_t *record,
const uint8_t **exts, size_t *extslen)
{
int type;
const uint8_t *cp;
size_t len;
if (tls_record_get_handshake(record, &type, &cp, &len) != 1) {
error_print();
return -1;
}
if (type != TLS_handshake_encrypted_extensions) {
error_print();
return 0;
}
if (tls_uint16array_from_bytes(exts, extslen, &cp, &len) != 1
|| tls_length_is_zero(len) != 1) {
error_print();
return -1;
}
return 1;
}
int tls13_encrypted_extensions_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
const uint8_t *exts;
size_t extslen;
format_print(fp, fmt, ind, "EncryptedExtensions\n");
ind += 4;
format_print(fp, fmt, ind, "extensions\n");
ind += 4;
if (tls_uint16array_from_bytes(&exts, &extslen, &d, &dlen) != 1) {
error_print();
return -1;
}
if (!extslen) {
format_print(fp, fmt, ind, "(null)\n");
}
while (extslen) {
uint16_t ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "%s (%d)\n", tls_extension_name(ext_type), ext_type);
switch (ext_type) {
case TLS_extension_supported_groups:
tls_supported_groups_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_early_data:
tls13_early_data_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_client_certificate_type:
case TLS_extension_server_certificate_type:
case TLS_extension_server_name:
case TLS_extension_max_fragment_length:
case TLS_extension_use_srtp:
case TLS_extension_heartbeat:
case TLS_extension_application_layer_protocol_negotiation:
case TLS_extension_record_size_limit:
format_bytes(fp, fmt, ind + 4, "data", ext_data, ext_datalen);
break;
default:
format_bytes(fp, fmt, ind + 4, "data", ext_data, ext_datalen);
error_print();
}
}
if (dlen) {
error_print();
return -1;
}
return 1;
}
/*
Certificate
Certificate {
opaque certificate_request_context<0..2^8-1>;
CertificateEntry certificate_list<0..2^24-1>;
}
CertificateEntry {
opaque cert_data<1..2^24-1>;
Extension extensions<0..2^16-1>;
}
*/
int tls13_certificate_entry_to_bytes(const uint8_t *cert, size_t certlen,
const uint8_t *status_request_ocsp_response, size_t status_request_ocsp_response_len,
const uint8_t *signed_certificate_timestamp, size_t signed_certificate_timestamp_len,
uint8_t **out, size_t *outlen)
{
size_t extslen = 0;
if (status_request_ocsp_response && status_request_ocsp_response_len) {
tls_server_status_request_ext_to_bytes(status_request_ocsp_response, status_request_ocsp_response_len, NULL, &extslen);
}
if (signed_certificate_timestamp && signed_certificate_timestamp_len) {
tls_signed_certificate_timestamp_ext_to_bytes(signed_certificate_timestamp, signed_certificate_timestamp_len, NULL, &extslen);
}
tls_uint24array_to_bytes(cert, certlen, out, outlen);
tls_uint16_to_bytes((uint16_t)extslen, out, outlen);
if (status_request_ocsp_response && status_request_ocsp_response_len) {
tls_server_status_request_ext_to_bytes(status_request_ocsp_response, status_request_ocsp_response_len, out, outlen);
}
if (signed_certificate_timestamp && signed_certificate_timestamp_len) {
tls_signed_certificate_timestamp_ext_to_bytes(signed_certificate_timestamp, signed_certificate_timestamp_len, out, outlen);
}
return 1;
}
int tls13_certificate_entry_from_bytes(const uint8_t **cert, size_t *certlen,
const uint8_t **status_request_ocsp_response, size_t *status_request_ocsp_response_len,
const uint8_t **signed_certificate_timestamp, size_t *signed_certificate_timestamp_len,
const uint8_t **in, size_t *inlen)
{
const uint8_t *exts;
size_t extslen;
if (!cert || !certlen
|| !status_request_ocsp_response || !status_request_ocsp_response_len
|| !signed_certificate_timestamp || !signed_certificate_timestamp_len
|| !in || !(*in) || !inlen) {
error_print();
return -1;
}
if (tls_uint24array_from_bytes(cert, certlen, in, inlen) != 1
|| tls_uint16array_from_bytes(&exts, &extslen, in, inlen) != 1) {
error_print();
return -1;
}
while (extslen) {
int ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
return -1;
}
switch (ext_type) {
case TLS_extension_status_request:
*status_request_ocsp_response = ext_data;
*status_request_ocsp_response_len = ext_datalen;
break;
case TLS_extension_signed_certificate_timestamp:
*signed_certificate_timestamp = ext_data;
*signed_certificate_timestamp_len = ext_datalen;
break;
default:
error_print();
return -1;
}
}
return 1;
}
int tls13_certificate_list_to_bytes(const uint8_t *certs, size_t certslen,
uint8_t **out, size_t *outlen)
{
uint8_t *p = NULL;
size_t cert_list_len = 0;
if (out && *out) {
p = (*out) + tls_uint24_size();
}
while (certslen) {
const uint8_t *cert;
size_t certlen;
const uint8_t *entry_exts = NULL;
size_t entry_exts_len = 0;
if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1) {
error_print();
return -1;
}
tls_uint24array_to_bytes(cert, certlen, &p, &cert_list_len);
tls_uint16array_to_bytes(entry_exts, entry_exts_len, &p, &cert_list_len);
}
tls_uint24array_to_bytes(NULL, cert_list_len, out, outlen);
return 1;
}
int tls13_process_certificate_list(const uint8_t *cert_list, size_t cert_list_len,
uint8_t *certs, size_t *certs_len)
{
*certs_len = 0;
while (cert_list_len) {
const uint8_t *cert_data;
size_t cert_data_len;
const uint8_t *exts;
size_t exts_len;
const uint8_t *cert;
size_t cert_len;
if (tls_uint24array_from_bytes(&cert_data, &cert_data_len, &cert_list, &cert_list_len) != 1
|| tls_uint16array_from_bytes(&exts, &exts_len, &cert_list, &cert_list_len) != 1) {
error_print();
return -1;
}
if (x509_cert_from_der(&cert, &cert_len, &cert_data, &cert_data_len) != 1
|| asn1_length_is_zero(cert_data_len) != 1
|| x509_cert_to_der(cert, cert_len, &certs, certs_len) != 1) {
error_print();
return -1;
}
while (exts_len) {
int ext_type;
const uint8_t *ext_data;
size_t ext_data_len;
if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_data_len, &exts, &exts_len) != 1) {
error_print();
return -1;
}
switch (ext_type) {
case TLS_extension_status_request:
case TLS_extension_signed_certificate_timestamp:
error_print();
return -1;
default:
error_print();
return -1;
}
}
}
return 1;
}
int tls13_record_set_handshake_certificate(uint8_t *record, size_t *recordlen,
const uint8_t *request_context, size_t request_context_len,
const uint8_t *certs, size_t certslen,
const uint8_t *entity_status_request_ocsp_response, size_t entity_status_request_ocsp_response_len,
const uint8_t *entity_signed_certificate_timestamp, size_t entity_signed_certificate_timestamp_len)
{
int type = TLS_handshake_certificate;
uint8_t *data;
size_t datalen = 0;
uint8_t *cert_list;
size_t cert_list_len = 0;
const uint8_t *cert;
size_t certlen;
size_t len;
if (!record || !recordlen) {
error_print();
return -1;
}
data = tls_handshake_data(tls_record_data(record));
// certificate_request_context<0..2^8-1>
tls_uint8array_to_bytes(request_context, request_context_len, &data, &datalen);
// certificate_list<0..2^24-1>
cert_list = data;
tls_uint24_to_bytes(0, &data, &len);
// client might send null certificate_list
if (certs && certslen) {
// first (entity) cert entry
if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1) {
error_print();
return -1;
}
if (tls13_certificate_entry_to_bytes(cert, certlen,
entity_status_request_ocsp_response, entity_status_request_ocsp_response_len,
entity_signed_certificate_timestamp, entity_signed_certificate_timestamp_len,
&data, &cert_list_len) != 1) {
error_print();
return -1;
}
// ca certs entries
while (certslen) {
if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1) {
error_print();
return -1;
}
if (tls13_certificate_entry_to_bytes(cert, certlen, NULL, 0, NULL, 0, &data, &cert_list_len) != 1) {
error_print();
return -1;
}
}
}
tls_uint24array_to_bytes(NULL, cert_list_len, &cert_list, &datalen);
if (tls_record_set_handshake(record, recordlen, type, NULL, datalen) != 1) {
error_print();
return -1;
}
return 1;
}
// even if status_request, signed_certificate_timestamp not requested
// server/client can still return certificate with these two extensions
int tls13_record_get_handshake_certificate(const uint8_t *record,
const uint8_t **request_context, size_t *request_context_len,
uint8_t *cert_chain, size_t *cert_chain_len, size_t cert_chain_maxlen,
const uint8_t **entity_status_request_ocsp_response, size_t *entity_status_request_ocsp_response_len,
const uint8_t **entity_signed_certificate_timestamp, size_t *entity_signed_certificate_timestamp_len)
{
int type;
const uint8_t *p;
size_t len;
const uint8_t *cert_list;
size_t cert_list_len;
const uint8_t *cert;
size_t certlen;
if (tls_record_get_handshake(record, &type, &p, &len) != 1) {
error_print();
return -1;
}
if (type != TLS_handshake_certificate) {
error_print();
return -1;
}
if (tls_uint8array_from_bytes(request_context, request_context_len, &p, &len) != 1
|| tls_uint24array_from_bytes(&cert_list, &cert_list_len, &p, &len) != 1
|| tls_length_is_zero(len) != 1) {
error_print();
return -1;
}
if (cert_list_len > cert_chain_maxlen) {
error_print();
return -1;
}
// client Certificate.certificate_list might be empty/null
if (!cert_list) {
*cert_chain_len = 0;
*entity_status_request_ocsp_response = NULL;
*entity_status_request_ocsp_response_len = 0;
*entity_signed_certificate_timestamp = NULL;
*entity_signed_certificate_timestamp_len = 0;
return 1;
}
if (tls13_certificate_entry_from_bytes(&cert, &certlen,
entity_status_request_ocsp_response, entity_status_request_ocsp_response_len,
entity_signed_certificate_timestamp, entity_signed_certificate_timestamp_len,
&cert_list, &cert_list_len) != 1) {
error_print();
return -1;
}
*cert_chain_len = 0;
x509_cert_to_der(cert, certlen, &cert_chain, cert_chain_len);
while (cert_list_len) {
const uint8_t *status_request_ocsp_response;
size_t status_request_ocsp_response_len;
const uint8_t *signed_certificate_timestamp;
size_t signed_certificate_timestamp_len;
if (tls13_certificate_entry_from_bytes(&cert, &certlen,
&status_request_ocsp_response, &status_request_ocsp_response_len,
&signed_certificate_timestamp, &signed_certificate_timestamp_len,
&cert_list, &cert_list_len) != 1) {
error_print();
return -1;
}
// 这里的解析可能是有问题的
x509_cert_to_der(cert, certlen, &cert_chain, cert_chain_len);
}
return 1;
}
int tls13_certificate_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
const uint8_t *req_context;
size_t req_context_len;
const uint8_t *cert_list;
size_t cert_list_len;
format_print(fp, fmt, ind, "Certificate\n");
ind += 4;
if (tls_uint8array_from_bytes(&req_context, &req_context_len, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "certificate_request_context", req_context, req_context_len);
format_print(fp, fmt, ind, "certificate_list\n");
ind += 4;
if (tls_uint24array_from_bytes(&cert_list, &cert_list_len, &d, &dlen) != 1) {
error_print();
return -1;
}
while (cert_list_len) {
const uint8_t *cert_data;
size_t cert_data_len;
const uint8_t *exts;
size_t extslen;
format_print(fp, fmt, ind, "CertificateEntry\n");
if (tls_uint24array_from_bytes(&cert_data, &cert_data_len, &cert_list, &cert_list_len) != 1
|| tls_uint16array_from_bytes(&exts, &extslen, &cert_list, &cert_list_len) != 1) {
error_print();
return -1;
}
if (!cert_data_len) {
error_print();
return -1;
}
x509_cert_print(fp, fmt, ind + 4, "Certificate", cert_data, cert_data_len);
x509_cert_to_pem(cert_data, cert_data_len, fp);
if (extslen)
format_print(fp, fmt, ind + 4, "extensions\n");
else format_print(fp, fmt, ind + 4, "extensions: (null)\n");
while (extslen) {
uint16_t ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "%s (%d)\n", tls_extension_name(ext_type), ext_type);
ind += 4;
switch (ext_type) {
case TLS_extension_status_request:
tls_server_status_request_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_signed_certificate_timestamp:
tls_signed_certificate_timestamp_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_server_certificate_type:
case TLS_extension_client_certificate_type:
format_bytes(fp, fmt, ind, "data", ext_data, ext_datalen);
break;
default:
format_bytes(fp, fmt, ind, "data", ext_data, ext_datalen);
error_print();
//return -1;
}
}
}
if (dlen) {
error_print();
return -1;
}
return 1;
}
/*
CertificateRequest
struct {
opaque certificate_request_context<0..2^8-1>;
Extension extensions<2..2^16-1>;
} CertificateRequest;
*/
int tls13_record_set_handshake_certificate_request(uint8_t *record, size_t *recordlen,
const uint8_t *request_context, size_t request_context_len,
const uint8_t *exts, size_t extslen)
{
int type = TLS_handshake_certificate_request;
uint8_t *data;
size_t datalen = 0;
if (!record || !recordlen) {
error_print();
return -1;
}
if (!exts || !extslen) {
// signature_algorithms extension must exist
error_print();
return -1;
}
data = tls_handshake_data(tls_record_data(record));
tls_uint8array_to_bytes(request_context, request_context_len, &data, &datalen);
tls_uint16array_to_bytes(exts, extslen, &data, &datalen);
tls_record_set_handshake(record, recordlen, type, NULL, datalen);
return 1;
}
int tls13_record_get_handshake_certificate_request(const uint8_t *record,
const uint8_t **requst_context, size_t *request_context_len,
const uint8_t **exts, size_t *exts_len)
{
int type;
const uint8_t *p;
size_t len;
if (tls_record_get_handshake(record, &type, &p, &len) != 1) {
error_print();
return -1;
}
if (type != TLS_handshake_certificate_request) {
error_print();
return -1;
}
if (tls_uint8array_from_bytes(requst_context, request_context_len, &p, &len) != 1
|| tls_uint16array_from_bytes(exts, exts_len, &p, &len) != 1
|| tls_length_is_zero(len) != 1) {
error_print();
return -1;
}
if (!exts) {
// signature_algorithms extension must exist
error_print();
return -1;
}
return 1;
}
int tls13_certificate_request_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
const uint8_t *req_context;
size_t req_context_len;
const uint8_t *exts;
size_t extslen;
format_print(fp, fmt, ind, "CertificateRequest\n");
ind += 4;
if (tls_uint8array_from_bytes(&req_context, &req_context_len, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "certificate_request_context", req_context, req_context_len);
format_print(fp, fmt, ind, "extensions\n");
ind += 4;
if (tls_uint16array_from_bytes(&exts, &extslen, &d, &dlen) != 1) {
error_print();
return -1;
}
while (extslen) {
uint16_t ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
return -1;
}
switch (ext_type) {
case TLS_extension_signature_algorithms:
tls_signature_algorithms_print(fp, fmt, ind, ext_data, ext_datalen);
break;
case TLS_extension_certificate_authorities:
tls13_certificate_authorities_print(fp, fmt, ind, ext_data, ext_datalen);
break;
case TLS_extension_status_request:
//tls13_status_request_print(fp, fmt, ind, ext_data, ext_datalen);
break;
case TLS_extension_signature_algorithms_cert:
tls_signature_algorithms_print(fp, fmt, ind, ext_data, ext_datalen);
break;
case TLS_extension_client_certificate_type:
//tls13_client_certificate_type_print(fp, fmt, ind, ext_data, ext_datalen);
break;
default:
error_print();
return -1;
}
}
if (dlen) {
error_print();
return -1;
}
return 1;
}
/*
CertificateVerify
struct {
SignatureScheme algorithm;
opaque signature<0..2^16-1>;
} CertificateVerify;
*/
int tls13_record_set_handshake_certificate_verify(uint8_t *record, size_t *recordlen,
int sig_alg, const uint8_t *sig, size_t siglen)
{
int type = TLS_handshake_certificate_verify;
uint8_t *p = record + 5 + 4; // 这里都应该改为tls_record_handshake_data
size_t len = 0;
if (!tls_signature_scheme_name(sig_alg)) {
error_print();
return -1;
}
tls_uint16_to_bytes((uint16_t)sig_alg, &p, &len);
tls_uint16array_to_bytes(sig, siglen, &p, &len);
if (tls_record_set_handshake_header(record, recordlen, type, len) != 1) {
error_print();
return -1;
}
return 1;
}
int tls13_record_get_handshake_certificate_verify(const uint8_t *record,
int *sig_alg, const uint8_t **sig, size_t *siglen)
{
int type;
const uint8_t *cp;
size_t len ;
uint16_t alg;
if (tls_record_get_handshake(record, &type, &cp, &len) != 1) {
error_print();
return -1;
}
if (type != TLS_handshake_certificate_verify) {
return 0;
}
if (tls_uint16_from_bytes(&alg, &cp, &len) != 1
|| tls_uint16array_from_bytes(sig, siglen, &cp, &len) != 1) {
error_print();
return -1;
}
if (!tls_signature_scheme_name(alg)) {
error_print();
return -1;
}
*sig_alg = alg;
return 1;
}
int tls13_certificate_verify_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
uint16_t sig_alg;
const uint8_t *sig;
size_t siglen;
format_print(fp, fmt, ind, "CertificateVerify\n");
ind += 4;
if (tls_uint16_from_bytes(&sig_alg, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "algorithm: %s (%04x)\n", tls_signature_scheme_name(sig_alg), sig_alg);
if (tls_uint16array_from_bytes(&sig, &siglen, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "signature", sig, siglen);
if (tls_length_is_zero(dlen) != 1) {
error_print();
return -1;
}
return 1;
}
/*
Finished
struct {
opaque verify_data[Hash.length];
} Finished;
*/
int tls13_record_set_handshake_finished(uint8_t *record, size_t *recordlen,
const uint8_t *verify_data, size_t verify_data_len)
{
int type = TLS_handshake_finished;
if (!verify_data || !verify_data_len) {
error_print();
return -1;
}
if (verify_data_len != 32) {
error_print();
return -1;
}
if (tls_record_set_handshake(record, recordlen, type, verify_data, verify_data_len) != 1) {
error_print();
return -1;
}
return 1;
}
int tls13_record_get_handshake_finished(const uint8_t *record,
const uint8_t **verify_data, size_t *verify_data_len)
{
int type;
if (tls_record_get_handshake(record, &type, verify_data, verify_data_len) != 1) {
error_print();
return -1;
}
if (type != TLS_handshake_finished) {
return 0;
}
if (*verify_data_len == 0) {
error_print();
return -1;
}
return 1;
}
int tls13_finished_print(FILE *fp, int fmt, int ind, const uint8_t *data, size_t datalen)
{
format_print(fp, fmt, ind, "Finished\n");
ind += 4;
format_bytes(fp, fmt, ind, "verify_data", data, datalen);
return 1;
}
/*
KeyUpdate
struct {
KeyUpdateRequest request_update;
} KeyUpdate;
enum {
update_not_requested(0), update_requested(1), (255)
} KeyUpdateRequest;
*/
int tls13_record_set_handshake_key_update(uint8_t *record, size_t *recordlen,
int req_update)
{
int type = TLS_handshake_key_update;
uint8_t request_update;
request_update = req_update ? 1 : 0;
if (tls_record_set_handshake(record, recordlen, type, &request_update, sizeof(request_update)) != 1) {
error_print();
return -1;
}
return 1;
}
int tls13_record_get_handshake_key_update(uint8_t *record, int *request_update)
{
int type;
const uint8_t *cp;
size_t len;
if (tls_record_get_handshake(record, &type, &cp, &len) != 1) {
error_print();
return -1;
}
if (type != TLS_handshake_key_update) {
return 0;
}
if (len != 1) {
error_print();
return -1;
}
switch (cp[0]) {
case 0:
*request_update = 0;
break;
case 1:
*request_update = 1;
break;
default:
error_print();
return -1;
}
return 1;
}
int tls13_key_update_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
uint8_t update_requested;
if (tls_uint8_from_bytes(&update_requested, &d, &dlen) != 1
|| tls_length_is_zero(dlen) != 1) {
error_print();
return -1;
}
switch (update_requested) {
case 0:
case 1:
break;
default:
error_print();
return -1;
}
format_print(fp, fmt, ind, "request_update: %d\n", update_requested);
return 1;
}
int tls13_ctx_enable_key_update(TLS_CTX *ctx, int enable)
{
if (!ctx) {
error_print();
return -1;
}
ctx->key_update = enable ? 1 : 0;
ctx->key_update_seq_num_limit = TLS13_DEFAULT_KEY_UPDATE_SEQ_NUM_LIMIT;
return 1;
}
int tls13_ctx_set_key_update_seq_num_limit(TLS_CTX *ctx, size_t max_seq_num)
{
if (!ctx || !max_seq_num) {
error_print();
return -1;
}
if (!ctx->key_update) {
error_print();
return -1;
}
ctx->key_update_seq_num_limit = max_seq_num;
return 1;
}
// ChangeCipherSpec
int tls13_ctx_set_change_cipher_spec_compat(TLS_CTX *ctx, int enable)
{
if (!ctx) {
error_print();
return -1;
}
ctx->change_cipher_spec_compat = enable ? 1 : 0;
ctx->change_cipher_spec = ctx->change_cipher_spec_compat;
return 1;
}
int tls13_ctx_set_accept_change_cipher_spec(TLS_CTX *ctx, int enable)
{
if (!ctx) {
error_print();
return -1;
}
ctx->accept_change_cipher_spec = enable ? 1 : 0;
return 1;
}
int tls13_ctx_enable_change_cipher_spec(TLS_CTX *ctx, int enable)
{
return tls13_ctx_set_change_cipher_spec_compat(ctx, enable);
}
static int tls13_ctx_change_cipher_spec_compat(const TLS_CTX *ctx)
{
if (!ctx) {
return 0;
}
return ctx->change_cipher_spec_compat || ctx->change_cipher_spec;
}
static int tls13_ctx_accept_change_cipher_spec(const TLS_CTX *ctx)
{
if (!ctx) {
return 0;
}
return ctx->accept_change_cipher_spec;
}
static int tls13_recv_change_cipher_spec_if_present(TLS_CONNECT *conn)
{
int ret;
if(conn->verbose) tls_trace("recv [ChangeCipherSpec*]\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
if(conn->verbose) tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
if (tls_record_type(conn->record) != TLS_record_change_cipher_spec) {
return 0;
}
if (tls_record_get_change_cipher_spec(conn->record) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
}
return 1;
}
int tls13_handshake_print(FILE *fp, int fmt, int ind, const uint8_t *handshake, size_t handshake_len)
{
const uint8_t *p = handshake;
size_t len = handshake_len;
uint8_t type;
const uint8_t *data;
size_t datalen;
if (tls_uint8_from_bytes(&type, &handshake, &handshake_len) != 1
|| tls_uint24array_from_bytes(&data, &datalen, &handshake, &handshake_len) != 1
|| tls_length_is_zero(handshake_len) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "Handshake\n");
ind += 4;
format_print(fp, fmt, ind, "Type: %s (%d)\n", tls_handshake_type_name(type), type);
format_print(fp, fmt, ind, "Length: %zu\n", datalen);
switch (type) {
case TLS_handshake_client_hello:
tls13_client_hello_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_server_hello:
tls13_server_hello_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_hello_retry_request:
tls13_hello_retry_request_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_new_session_ticket:
tls13_new_session_ticket_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_end_of_early_data:
tls13_end_of_early_data_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_encrypted_extensions:
tls13_encrypted_extensions_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_certificate:
tls13_certificate_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_certificate_request:
tls13_certificate_request_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_certificate_verify:
tls13_certificate_verify_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_finished:
tls13_finished_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_key_update:
tls13_key_update_print(fp, fmt, ind, data, datalen);
break;
default:
error_print();
return -1;
}
return 1;
}
int tls13_record_print(FILE *fp, int fmt, int ind, const uint8_t *record, size_t recordlen)
{
const uint8_t *data;
size_t datalen;
int protocol;
fmt |= TLS_cipher_sm4_gcm_sm3 << 8;
if (!fp || !record || recordlen < 5) {
error_print();
return -1;
}
protocol = tls_record_protocol(record);
format_print(fp, fmt, ind, "Record\n"); ind += 4;
format_print(fp, fmt, ind, "ContentType: %s (%d)\n", tls_record_type_name(record[0]), record[0]);
format_print(fp, fmt, ind, "Version: %s (%04x)\n", tls_protocol_name(protocol), protocol);
format_print(fp, fmt, ind, "Length: %d\n", tls_record_data_length(record));
data = tls_record_data(record);
datalen = tls_record_data_length(record);
if (recordlen < tls_record_length(record)) {
error_print();
return -1;
}
//format_bytes(fp, fmt, ind, "RecordRawData", data, datalen);
switch (record[0]) {
case TLS_record_handshake:
tls13_handshake_print(fp, fmt, ind, data, datalen);
break;
case TLS_record_alert:
if (tls_alert_print(fp, data, datalen, fmt, ind) != 1) {
error_print();
return -1;
}
break;
case TLS_record_change_cipher_spec:
if (tls_change_cipher_spec_print(fp, data, datalen, fmt, ind) != 1) {
error_print();
return -1;
}
break;
case TLS_record_application_data:
if (tls_application_data_print(fp, data, datalen, fmt, ind) != 1) {
error_print();
return -1;
}
break;
default:
error_print();
return -1;
}
recordlen -= tls_record_length(record);
if (recordlen) {
format_print(fp, 0, 0, "DataLeftInRecord: %zu\n", recordlen);
}
//fprintf(fp, "\n");
return 1;
}
/*
Client Server
Key ^ ClientHello
Exch | + key_share*
| + signature_algorithms*
| + psk_key_exchange_modes*
v + pre_shared_key* -------->
ServerHello ^ Key
+ key_share* | Exch
+ pre_shared_key* v
| ecdhe => handshake_secret |
| handshake_secret => master_secret |
| handshake_secret, client_hello, server_hello |
| => client_handshake_traffic_secret |
| => server_handshake_traffic_secret |
{EncryptedExtensions} ^ Server
{CertificateRequest*} v Params
{Certificate} ^
{CertificateVerify} | Auth
{Finished} v
+ master_secret, ClientHello .. server Finished
=> server_application_traffic_secret_0
<-------- [Application Data*]
^ {Certificate*}
Auth | {CertificateVerify*}
v {Finished} -------->
+ master_secret, ClientHello .. server Finished
=> client_application_traffic_secret_0
[Application Data] <-------> [Application Data]
*/
int tls13_init(TLS_CONNECT *conn, TLS_CTX *ctx)
{
if (!ctx->supported_versions_cnt) {
error_print();
return -1;
}
if (!ctx->cipher_suites_cnt) {
error_print();
return -1;
}
memset(conn, 0, sizeof(*conn));
conn->ctx = ctx;
conn->is_client = ctx->is_client;
conn->verbose = ctx->verbose;
conn->protocol = ctx->protocol;
conn->new_session_ticket = ctx->new_session_ticket;
/*
extensions depends on key_exchange_modes
switch (key_exchange_mode)
case CERT_DHE:
* supported_groups ctx->supported_groups_cnt != 0
* signature_algorithms ctx->signature_algorithms_cnt != 0
* key_share generated in ClientHello, so always ok
* [signature_algorithms_cert]
* [certificate_authorities]
case PSK_DHE:
* supported_groups
* psk_key_exchange_modes ctx->psk_key_exchange_modes has psk_dhe_ke
* pre_shared_key call tls13_add_pre_shared_key, tls13_add_pre_shared_key_from_session_file after tls13_init
* key_share
* [early_data]
* [signature_algorithms]
* [signature_algorithms_cert]
case PSK:
* psk_key_exchange_modes ctx->psk_key_exchange_modes has psk_ke
* pre_shared_key
* [early_data]
* [supported_groups]
* [signature_algorithms]
* [signature_algorithms_cert]
*/
// key_exchange_modes
conn->key_exchange_modes = ctx->psk_key_exchange_modes;
if (ctx->supported_groups_cnt && ctx->signature_algorithms_cnt) {
conn->key_exchange_modes |= TLS_KE_CERT_DHE;
}
if (!ctx->supported_groups_cnt) {
conn->key_exchange_modes &= ~(TLS_KE_CERT_DHE|TLS_KE_PSK_DHE);
}
if (!conn->key_exchange_modes) {
error_print();
return -1;
}
// TLS_KE_PSK_DHE|TLS_KE_PSK depends on pre_shared_key
// but pre_shared_key is set by tls13_add_pre_shared_key, tls13_add_pre_shared_key_from_session_file
// after tls13_init
// key_share
if (conn->key_exchange_modes & (TLS_KE_CERT_DHE|TLS_KE_PSK_DHE)) {
conn->key_share = 1;
}
conn->signed_certificate_timestamp = ctx->signed_certificate_timestamp;
// early_data
conn->early_data = ctx->early_data;
conn->max_early_data_size = ctx->max_early_data_size;
// CertificateRequest
if (!ctx->is_client) {
conn->certificate_request = ctx->certificate_request;
}
return 1;
}
int tls13_send_client_hello(TLS_CONNECT *conn)
{
int ret;
if (!conn->recordlen) {
const uint8_t *legacy_session_id = NULL;
size_t legacy_session_id_len = 0;
uint8_t exts[TLS_MAX_EXTENSIONS_SIZE];
uint8_t *pexts = exts;
size_t extslen = 0;
if(conn->verbose) tls_trace("send ClientHello\n");
// record_version
tls_record_set_protocol(conn->record, TLS_protocol_tls1);
// client_random
if (tls13_random_generate(conn->client_random) != 1) {
error_print();
return -1;
}
// legacy_session_id
conn->session_id_len = 0;
// exts in CH (RFC 8446 page 37), only oid_filter not in CH
// * supported_versions
// * signature_algorithms
// * signature_algorithms_cert
// * certificate_authorities
// * server_name
// * status_request
// * signed_certificate_timestamp
// * supported_groups
// * key_share
// * psk_key_exchange_modes
// * pre_shared_key
// * early_data (only in ClientHello1)
// * cookie (only in ClientHello2)
// * post_handshake_auth: client support post handshake auth
// * max_fragment_length
// * use_srtp
// * heartbeat
// * application_layer_protocol_negotiation
// * server_certificate_type: if client accept raw/x509
// * client_certificate_type: if client sned raw/x509
// * padding
// supported_versions
if (tls13_client_supported_versions_ext_to_bytes(conn->ctx->supported_versions,
conn->ctx->supported_versions_cnt, &pexts, &extslen) != 1) {
error_print();
return -1;
}
// supported_groups
if (conn->ctx->supported_groups_cnt) {
if (tls_supported_groups_ext_to_bytes(conn->ctx->supported_groups,
conn->ctx->supported_groups_cnt, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// signature_algorithms
if (conn->ctx->signature_algorithms_cnt) {
if (tls_signature_algorithms_ext_to_bytes(conn->ctx->signature_algorithms,
conn->ctx->signature_algorithms_cnt, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// signature_algorithms_cert
if (conn->signature_algorithms_cert) {
if (tls13_signature_algorithms_cert_ext_to_bytes(conn->ctx->signature_algorithms,
conn->ctx->signature_algorithms_cnt, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// certificate_authorities
if (conn->certificate_authorities) {
if (tls13_certificate_authorities_ext_to_bytes(
conn->ctx->ca_names, conn->ctx->ca_names_len, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// key_share
if (conn->key_share) {
size_t i;
// empty ClientHello.key_share is allowed
for (i = 0; i < conn->ctx->key_exchanges_cnt && i < conn->ctx->supported_groups_cnt; i++) {
int curve_oid = tls_named_curve_oid(conn->ctx->supported_groups[i]);
if (x509_key_generate(&conn->key_exchanges[i],
OID_ec_public_key, &curve_oid, sizeof(curve_oid)) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_internal_error);
return -1;
}
}
conn->key_exchanges_cnt = i;
if (tls13_key_share_client_hello_ext_to_bytes(conn->key_exchanges,
conn->key_exchanges_cnt, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// server_name
if (conn->server_name) {
if (tls_server_name_ext_to_bytes(
conn->host_name, conn->host_name_len, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// application_layer_protocol_negotiation
if (conn->ctx->alpn_protocols_cnt) {
if (tls_application_layer_protocol_negotiation_ext_to_bytes(
conn->ctx->alpn_protocols, conn->ctx->alpn_protocols_cnt,
&pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// psk_key_exchange_modes
if (conn->key_exchange_modes & (TLS_KE_PSK_DHE|TLS_KE_PSK)) {
if (tls13_psk_key_exchange_modes_ext_to_bytes(
conn->key_exchange_modes, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// status_request (hint only)
if (conn->status_request) {
if (tls_client_status_request_ext_to_bytes(TLS_certificate_status_type_ocsp,
conn->status_request_responder_id_list, conn->status_request_responder_id_list_len,
conn->status_request_exts, conn->status_request_exts_len,
&pexts, &extslen) != 1) {
error_print();
return -1;
}
conn->status_request = 0; // to track CertificateRequest.status_request
}
// signed_certificate_timestamp (hint only)
if (conn->signed_certificate_timestamp) {
if (tls_ext_to_bytes(TLS_extension_signed_certificate_timestamp, NULL, 0,
&pexts, &extslen) != 1) {
error_print();
return -1;
}
conn->signed_certificate_timestamp = 0; // to track CertificateRequest.signed_certificate_timestamp
}
// early_data
// 客户端启用early_data是非常特殊的需要在ClientHello就确定cipher_suite
// 并且固定采用第一个pre_shared_key
if (conn->early_data) {
if (tls_ext_to_bytes(TLS_extension_early_data, NULL, 0,
&pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// post_handshake_auth
if (conn->post_handshake_auth) {
if (tls_ext_to_bytes(TLS_extension_post_handshake_auth, NULL, 0,
&pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// pre_shared_key (must be the last extension)
if (conn->pre_shared_key) {
uint8_t *ptruncated_exts = pexts;
size_t truncated_extslen = extslen;
uint8_t binders[256];
uint8_t *pbinders = binders;
size_t binderslen = 0;
if (!conn->psk_identities_len
|| !conn->psk_keys_len
|| !conn->psk_cipher_suites_cnt ) {
error_print();
return -1;
}
// output pre_shared_key ext with empty binders
if (tls13_psk_binders_generate_empty(
conn->psk_cipher_suites, conn->psk_cipher_suites_cnt,
binders, &binderslen) != 1) {
error_print();
return -1;
}
if (tls13_client_pre_shared_key_ext_to_bytes(
conn->psk_identities, conn->psk_identities_len,
binders, binderslen, &ptruncated_exts, &truncated_extslen) != 1) {
error_print();
return -1;
}
// truncate(ClientHello)
if (tls_record_set_handshake_client_hello(conn->record, &conn->recordlen,
TLS_protocol_tls12, conn->client_random,
legacy_session_id, legacy_session_id_len,
conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt,
exts, truncated_extslen) != 1) {
error_print();
return -1;
}
//tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
// generate binders and output final pre_shared_key ext
if (tls13_psk_binders_generate(
conn->psk_cipher_suites, conn->psk_cipher_suites_cnt,
conn->psk_identity_types,
conn->psk_keys, conn->psk_keys_len,
conn->record + 5, conn->recordlen - 5 - 2 - binderslen,
binders, &binderslen) != 1) {
error_print();
return -1;
}
if (tls13_client_pre_shared_key_ext_to_bytes(
conn->psk_identities, conn->psk_identities_len,
binders, binderslen, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
if (tls_record_set_handshake_client_hello(conn->record, &conn->recordlen,
TLS_protocol_tls12, conn->client_random,
legacy_session_id, legacy_session_id_len,
conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt,
exts, extslen) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
// early_data encryption keys depends on the full client_hello
if (conn->early_data) {
if (tls13_generate_early_keys(conn) != 1) {
error_print();
return -1;
}
}
// backup client_hello
// 如果后面发送EarlyData这个数据有可能被修改
// 并且如果确定了发送EarlyDatacipher_suite就确定了不应该再备份了
// 由于服务器可能拒绝EarlyData并且不选择第一个PSK
// 那么可能导致最终的cipher_suite和客户端计算EarlyData不同的值
// 这就导致客户端必须重新计算ClientHello的digest
// 因此我们还是保存ClientHello而不是立即就计算digest
memcpy(conn->plain_record, conn->record, conn->recordlen);
conn->plain_recordlen = conn->recordlen;
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
tls_clean_record(conn);
return 1;
}
/*
recv HelloRetryRequest:
* set conn->protocol
* set conn->cipher_suite, conn->cipher, conn->digest
* set conn->key_exchange_group
* set conn->dgst_ctx <= ClientHello, HelloRetryRequest, ClientHello2
recv ServerHello after HelloRetryRequest:
* check ServerHello.protocol == conn->protocol
* check ServerHello.cipher_suite == conn->cipher_suite
* check ServerHello.key_share.group == conn->key_exchange_group
* conn->dgst_ctx <= ServerHello
recv ServerHello without HelloRetryRequest:
* set conn->protocol
* set conn->cipher_suite, conn->cipher, conn->digest
* set conn->key_exchange_group
* set conn->dgst_ctx <= ClientHello
*/
int tls13_recv_hello_retry_request(TLS_CONNECT *conn)
{
int ret;
// handshake
int handshake_type;
const uint8_t *handshake_data;
size_t handshake_datalen;
// HelloRetryRequest
int legacy_version;
const uint8_t *random;
const uint8_t *legacy_session_id_echo;
size_t legacy_session_id_echo_len;
int cipher_suite;
int legacy_compress_meth;
const uint8_t *exts;
size_t extslen;
// extensions
const uint8_t *supported_versions = NULL;
size_t supported_versions_len = 0;
const uint8_t *key_share = NULL;
size_t key_share_len = 0;
const uint8_t *cookie = NULL;
size_t cookie_len = 0;
int selected_version;
int key_exchange_group;
if(conn->verbose) tls_trace("recv HelloRetryRequest*\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
if(conn->verbose) {
fprintf(stderr, "tls_recv_record return %d\n", ret);
}
error_print();
}
return ret;
}
if (tls_record_protocol(conn->record) != TLS_protocol_tls12) {
error_print();
tls13_send_alert(conn, TLS_alert_protocol_version);
return -1;
}
// the record might be Alert?
if ((ret = tls_record_get_handshake(conn->record,
&handshake_type, &handshake_data, &handshake_datalen)) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
return -1;
}
if (handshake_type != TLS_handshake_hello_retry_request
&& handshake_type != TLS_handshake_server_hello) {
if(conn->verbose) tls_trace(" no HelloRetryRequest\n");
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;
}
if (memcmp(random, TLS13_HELLO_RETRY_REQUEST_RANDOM, 32) != 0) {
if(conn->verbose) tls_trace(" no HelloRetryRequest\n");
return 0;
}
conn->hello_retry_request = 1;
// HelloRetryRequest disable early_data
conn->early_data = 0;
// legacy_version
if (legacy_version != TLS_protocol_tls12) {
error_print();
tls13_send_alert(conn, TLS_alert_protocol_version);
return -1;
}
// random
memcpy(conn->server_random, random, 32);
// legacy_session_id_echo
if (legacy_session_id_echo_len != conn->session_id_len
|| memcmp(legacy_session_id_echo, conn->session_id, conn->session_id_len) != 0) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
// cipher_suite
if (tls_type_is_in_list(cipher_suite, conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (tls_cipher_suite_get(cipher_suite, &conn->cipher, &conn->digest) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_internal_error);
return -1;
}
conn->cipher_suite = cipher_suite;
// legacy_compression_method
if (legacy_compress_meth != 0) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
while (extslen) {
int ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
}
// exts in HRR
// * supported_versions
// * key_share
// * cookie
switch (ext_type) {
case TLS_extension_supported_versions:
case TLS_extension_key_share:
case TLS_extension_cookie:
if (!ext_data) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
break;
}
switch (ext_type) {
case TLS_extension_supported_versions:
if (supported_versions) {
error_print();
return -1;
}
supported_versions = ext_data;
supported_versions_len = ext_datalen;
break;
case TLS_extension_key_share:
if (!conn->key_share) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (key_share) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
key_share = ext_data;
key_share_len = ext_datalen;
break;
case TLS_extension_cookie:
if (cookie) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
cookie = ext_data;
cookie_len = ext_datalen;
conn->cookie = 1;
break;
default:
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
}
// supported_versions
if (!supported_versions) {
error_print();
tls13_send_alert(conn, TLS_alert_missing_extension);
return -1;
}
if (tls13_server_supported_versions_from_bytes(&selected_version,
supported_versions, supported_versions_len) != 1) {
tls13_send_alert(conn, TLS_alert_decode_error);
error_print();
return -1;
}
if (tls_type_is_in_list(selected_version,
conn->ctx->supported_versions, conn->ctx->supported_versions_cnt) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (selected_version != TLS_protocol_tls13) {
error_print();
tls13_send_alert(conn, TLS_alert_internal_error);
return -1;
}
conn->protocol = selected_version;
// key_share
if (!key_share) {
error_print();
tls13_send_alert(conn, TLS_alert_missing_extension);
return -1;
}
if (tls13_key_share_hello_retry_request_from_bytes(&key_exchange_group,
key_share, key_share_len) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
}
if (tls_type_is_in_list(key_exchange_group,
conn->ctx->supported_groups, conn->ctx->supported_groups_cnt) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
// HelloRetryRequest must choose a group not in ClientHello.key_share
while (conn->key_exchanges_cnt--) {
if (key_exchange_group == tls_named_curve_from_oid(
conn->key_exchanges[conn->key_exchanges_cnt].algor_param)) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
}
}
conn->key_exchange_group = key_exchange_group;
// cookie
if (cookie) {
const uint8_t *cookie_data;
size_t cookie_datalen;
if (tls13_cookie_from_bytes(&cookie_data, &cookie_datalen,
cookie, cookie_len) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
}
if (cookie_len > sizeof(conn->cookie_buf)) {
error_print();
return -1;
}
memcpy(conn->cookie_buf, cookie_data, cookie_datalen);
conn->cookie_len = cookie_datalen;
}
// ClientHello1
uint8_t message_hash[4 + 32];
size_t dgstlen;
message_hash[0] = TLS_handshake_message_hash;
message_hash[1] = 0;
message_hash[2] = 0;
message_hash[3] = 32;
// 我猜如果用了HRR那么客户端实际上并没有保存ClientHello的数据而是用ClientHello的哈希值来计算后续的
if (digest_init(&conn->dgst_ctx, conn->digest) != 1
|| digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1
|| digest_finish(&conn->dgst_ctx, message_hash + 4, &dgstlen) != 1) {
error_print();
return -1;
}
// ClientHello, HelloRetryRequest
if (digest_init(&conn->dgst_ctx, conn->digest) != 1
|| digest_update(&conn->dgst_ctx, message_hash, sizeof(message_hash)) != 1
|| digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) {
error_print();
return -1;
}
return 1;
}
int tls13_client_hello_again_psk_update(TLS_CONNECT *conn)
{
const uint8_t *psk_identities;
const uint8_t *psk_keys;
uint8_t tmp_identities_buf[sizeof(conn->psk_identities)];
uint8_t *tmp_identities = tmp_identities_buf;
size_t tmp_identities_len = 0;
uint8_t tmp_keys_buf[sizeof(conn->psk_keys)];
uint8_t *tmp_keys = tmp_keys_buf;
size_t tmp_keys_len = 0;
size_t tmp_cipher_suites_cnt = 0;
size_t i;
if (!conn) {
error_print();
return -1;
}
psk_identities = conn->psk_identities;
psk_keys = conn->psk_keys;
for (i = 0; i < conn->psk_cipher_suites_cnt; i++) {
const uint8_t *identity;
size_t identity_len;
uint32_t obfuscated_ticket_age;
const uint8_t *key;
size_t key_len;
if (tls13_psk_identity_from_bytes(&identity, &identity_len, &obfuscated_ticket_age, &psk_identities, &conn->psk_identities_len) != 1
|| tls_uint8array_from_bytes(&key, &key_len, &psk_keys, &conn->psk_keys_len) != 1) {
gmssl_secure_clear(tmp_keys_buf, sizeof(tmp_keys_buf));
error_print();
return -1;
}
if (conn->psk_cipher_suites[i] == conn->cipher_suite) {
tls13_psk_identity_to_bytes(identity, identity_len, obfuscated_ticket_age, &tmp_identities, &tmp_identities_len);
tls_uint16array_to_bytes(key, key_len, &tmp_keys, &tmp_keys_len);
tmp_cipher_suites_cnt++;
}
}
if (conn->psk_identities_len || conn->psk_keys_len) {
gmssl_secure_clear(tmp_keys_buf, sizeof(tmp_keys_buf));
error_print();
return -1;
}
memcpy(conn->psk_identities, tmp_identities_buf, tmp_identities_len);
conn->psk_identities_len = tmp_identities_len;
memcpy(conn->psk_keys, tmp_keys_buf, tmp_keys_len);
conn->psk_keys_len = tmp_keys_len;
for (i = 0; i < tmp_cipher_suites_cnt; i++) {
conn->psk_cipher_suites[i] = conn->cipher_suite;
}
conn->psk_cipher_suites_cnt = tmp_cipher_suites_cnt;
gmssl_secure_clear(tmp_keys_buf, sizeof(tmp_keys_buf));
return 1;
}
int tls13_send_client_hello_again(TLS_CONNECT *conn)
{
int ret;
if(conn->verbose) tls_trace("send ClientHello again\n");
if (!conn->recordlen) {
const uint8_t *legacy_session_id = NULL;
size_t legacy_session_id_len = 0;
uint8_t exts[TLS_MAX_EXTENSIONS_SIZE];
uint8_t *pexts = exts;
size_t extslen = 0;
int supported_versions = TLS_protocol_tls13;
int curve_oid;
// record_version
tls_record_set_protocol(conn->record, TLS_protocol_tls1);
// Extensions
// keep ClientHello extensions except
// * key_share - generate a new key_exchange based on conn->key_exchange_group
// * pre_shared_key - remove PSKs not compatible with conn->cipher_suite
// * early_data - disable early_data
// * cookie - echo cookie if exist
// supported_versions
if (tls13_client_supported_versions_ext_to_bytes(conn->ctx->supported_versions,
conn->ctx->supported_versions_cnt, &pexts, &extslen) != 1) {
error_print();
return -1;
}
// supported_groups
if (conn->ctx->supported_groups_cnt) {
if (tls_supported_groups_ext_to_bytes(conn->ctx->supported_groups,
conn->ctx->supported_groups_cnt, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// signature_algorithms
if (conn->ctx->signature_algorithms_cnt) {
if (tls_signature_algorithms_ext_to_bytes(conn->ctx->signature_algorithms,
conn->ctx->signature_algorithms_cnt, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// signature_algorithms_cert
if (conn->signature_algorithms_cert) {
if (tls13_signature_algorithms_cert_ext_to_bytes(conn->ctx->signature_algorithms,
conn->ctx->signature_algorithms_cnt, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// server_name
if (conn->server_name) {
if (tls_server_name_ext_to_bytes(conn->host_name, conn->host_name_len, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// application_layer_protocol_negotiation
if (conn->ctx->alpn_protocols_cnt) {
if (tls_application_layer_protocol_negotiation_ext_to_bytes(
conn->ctx->alpn_protocols, conn->ctx->alpn_protocols_cnt,
&pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// key_share (re-generated)
if ((curve_oid = tls_named_curve_oid(conn->key_exchange_group)) == OID_undef) {
error_print();
return -1;
}
if (x509_key_generate(&conn->key_exchanges[0],
OID_ec_public_key, &curve_oid, sizeof(curve_oid)) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_internal_error);
return -1;
}
conn->key_exchange_idx = 0;
conn->key_exchanges_cnt = 1;
if (tls13_key_share_client_hello_ext_to_bytes(conn->key_exchanges,
conn->key_exchanges_cnt, &pexts, &extslen) != 1) {
error_print();
return -1;
}
// psk_key_exchange_modes
if (conn->key_exchange_modes & (TLS_KE_PSK_DHE|TLS_KE_PSK)) {
if (tls13_psk_key_exchange_modes_ext_to_bytes(conn->key_exchange_modes, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// update key_exchange_modes (disable PSK-only)
conn->key_exchange_modes &= ~TLS_KE_PSK;
// status_request
if (conn->status_request) {
if (tls_client_status_request_ext_to_bytes(TLS_certificate_status_type_ocsp,
conn->status_request_responder_id_list, conn->status_request_responder_id_list_len,
conn->status_request_exts, conn->status_request_exts_len,
&pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// signed_certificate_timestamp
if (conn->ctx->signed_certificate_timestamp) {
if (tls_ext_to_bytes(TLS_extension_signed_certificate_timestamp, NULL, 0, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// post_handshake_auth
if (conn->post_handshake_auth) {
if (tls_ext_to_bytes(TLS_extension_post_handshake_auth, NULL, 0,
&pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// early_data must not in ClientHello2
// cookie
if (conn->cookie) {
if (tls13_cookie_ext_to_bytes(conn->cookie_buf, conn->cookie_len, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// pre_shared_key
if (conn->pre_shared_key) {
if (!conn->psk_identities_len
|| !conn->psk_keys_len
|| !conn->psk_cipher_suites_cnt ) {
error_print();
return -1;
}
if (tls13_client_hello_again_psk_update(conn) != 1) {
error_print();
return -1;
}
if (!conn->psk_cipher_suites_cnt) {
conn->pre_shared_key = 0;
}
}
if (conn->pre_shared_key) {
uint8_t *ptruncated_exts = pexts;
size_t truncated_extslen = extslen;
uint8_t binders[256];
uint8_t *pbinders = binders;
size_t binderslen = 0;
// output pre_shared_key ext with empty binders
if (tls13_psk_binders_generate_empty(
conn->psk_cipher_suites, conn->psk_cipher_suites_cnt,
binders, &binderslen) != 1) {
error_print();
return -1;
}
if (tls13_client_pre_shared_key_ext_to_bytes(
conn->psk_identities, conn->psk_identities_len,
binders, binderslen, &ptruncated_exts, &truncated_extslen) != 1) {
error_print();
return -1;
}
// truncate(ClientHello)
if (tls_record_set_handshake_client_hello(conn->record, &conn->recordlen,
TLS_protocol_tls12, conn->client_random,
legacy_session_id, legacy_session_id_len,
conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt,
exts, truncated_extslen) != 1) {
error_print();
return -1;
}
//tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
// generate binders and output final pre_shared_key ext
if (tls13_psk_binders_generate(
conn->psk_cipher_suites, conn->psk_cipher_suites_cnt,
conn->psk_identity_types,
conn->psk_keys, conn->psk_keys_len,
conn->record + 5, conn->recordlen - 5 - 2 - binderslen,
binders, &binderslen) != 1) {
error_print();
return -1;
}
if (tls13_client_pre_shared_key_ext_to_bytes(
conn->psk_identities, conn->psk_identities_len,
binders, binderslen, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
if (tls_record_set_handshake_client_hello(conn->record, &conn->recordlen,
TLS_protocol_tls12, conn->client_random,
legacy_session_id, legacy_session_id_len,
conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt,
exts, extslen) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
// ClientHello2
if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) {
error_print();
return -1;
}
if (conn->client_certificate_verify) {
sm2_sign_update(&conn->sign_ctx, conn->record + 5, conn->recordlen - 5);
}
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
tls_clean_record(conn);
return 1;
}
/*
recv HelloRetryRequest:
* set conn->protocol
* set conn->cipher_suite, conn->cipher, conn->digest
* set conn->key_exchange_group
* set conn->dgst_ctx <= ClientHello, HelloRetryRequest, ClientHello2
recv ServerHello after HelloRetryRequest:
* check ServerHello.protocol == conn->protocol
* check ServerHello.cipher_suite == conn->cipher_suite
* check ServerHello.key_share.group == conn->key_exchange_group
* conn->dgst_ctx <= ServerHello
recv ServerHello without HelloRetryRequest:
* set conn->protocol
* set conn->cipher_suite, conn->cipher, conn->digest
* set conn->key_exchange_group
* set conn->dgst_ctx <= ClientHello
*/
int tls13_recv_server_hello(TLS_CONNECT *conn)
{
int ret;
// server_hello
int legacy_version;
const uint8_t *random;
const uint8_t *legacy_session_id_echo;
size_t legacy_session_id_echo_len;
int cipher_suite;
const uint8_t *exts;
size_t extslen;
const uint8_t *supported_versions = NULL;
size_t supported_versions_len;
const uint8_t *key_share = NULL;
size_t key_share_len;
const uint8_t *pre_shared_key = NULL;
size_t pre_shared_key_len;
int selected_version;
int server_key_exchange_mode = 0;
if(conn->verbose) 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 (tls_cipher_suite_get(cipher_suite, &conn->cipher, &conn->digest) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_internal_error);
return -1;
}
}
while (extslen) {
int ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
}
// exts in SH
// * supported_versions
// * key_share
// * pre_shared_key (not in HRR)
//
//
// ServerHello.key_share if only ClientHello.key_share
// ServerHello.pre_shared_key if only ClientHello.pre_shared_key
// if HelloRetryRequest, key_share must exist
switch (ext_type) {
case TLS_extension_supported_versions:
case TLS_extension_key_share:
case TLS_extension_pre_shared_key:
if (!ext_data) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
break;
}
switch (ext_type) {
case TLS_extension_supported_versions:
if (supported_versions) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
supported_versions = ext_data;
supported_versions_len = ext_datalen;
break;
case TLS_extension_key_share:
// ServerHello.key_share if only ClientHello.key_share
if (!conn->key_share) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (key_share) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
key_share = ext_data;
key_share_len = ext_datalen;
break;
case TLS_extension_pre_shared_key:
// ServerHello.pre_shared_key if only ClientHello.pre_shared_key
if (!conn->pre_shared_key) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (pre_shared_key) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
pre_shared_key = ext_data;
pre_shared_key_len = ext_datalen;
break;
default:
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
}
if (!supported_versions) {
error_print();
tls13_send_alert(conn, TLS_alert_missing_extension);
return -1;
}
// if HelloRetryRequest, key_share must exist
if (conn->hello_retry_request) {
if (!key_share) {
error_print();
tls13_send_alert(conn, TLS_alert_missing_extension);
return -1;
}
}
// key_exchange_mode
// implicitly sent through ServerHello exts
//
// * key_share + pre_shared_key PSK_DHE
// * key_share CERT_DHE
// * pre_shared_key PSK
// * (none) error
//
if (pre_shared_key) {
if (key_share)
server_key_exchange_mode = TLS_KE_PSK_DHE;
else server_key_exchange_mode = TLS_KE_PSK;
} else {
if (key_share) {
server_key_exchange_mode = TLS_KE_CERT_DHE;
} else {
error_print();
tls13_send_alert(conn, TLS_alert_missing_extension);
return -1;
}
}
// set key_exchange_mode
conn->key_exchange_modes &= server_key_exchange_mode;
if (!conn->key_exchange_modes) {
error_print();
tls13_send_alert(conn, TLS_alert_handshake_failure);
return -1;
}
// supported_versions
if (tls13_server_supported_versions_from_bytes(
&selected_version, supported_versions, supported_versions_len) != 1) {
tls13_send_alert(conn, TLS_alert_decode_error);
error_print();
return -1;
}
if (conn->hello_retry_request) {
if (selected_version != conn->protocol) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
} else {
if (tls_type_is_in_list(selected_version,
conn->ctx->supported_versions, conn->ctx->supported_versions_cnt) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (selected_version != TLS_protocol_tls13) {
error_print();
tls13_send_alert(conn, TLS_alert_internal_error);
return -1;
}
conn->protocol = selected_version;
}
// key_share
if (key_share) {
int key_exchange_group;
const uint8_t *key_exchange;
size_t key_exchange_len;
if (!conn->key_exchanges_cnt) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (tls13_key_share_server_hello_from_bytes(&key_exchange_group,
&key_exchange, &key_exchange_len, key_share, key_share_len) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
}
// compatible with/without HRR
while (conn->key_exchange_idx < conn->key_exchanges_cnt) {
if (conn->key_exchanges[conn->key_exchange_idx].algor_param ==
tls_named_curve_oid(key_exchange_group)) {
break;
}
conn->key_exchange_idx++;
}
if (conn->key_exchange_idx >= conn->key_exchanges_cnt) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (key_exchange_len != 65) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
conn->key_exchange_group = key_exchange_group;
memcpy(conn->peer_key_exchange, key_exchange, key_exchange_len);
conn->peer_key_exchange_len = 65;
}
// pre_shared_key
if (pre_shared_key) {
const uint8_t *psk_keys = conn->psk_keys;
size_t psk_keys_len = conn->psk_keys_len;
int selected_identity;
const uint8_t *key = NULL;
size_t keylen = 0;
size_t i;
if (tls13_server_pre_shared_key_from_bytes(&selected_identity,
pre_shared_key, pre_shared_key_len) != 1) {
error_print();
return -1;
}
for (i = 0; i <= (size_t)selected_identity; i++) {
if (tls_uint8array_from_bytes(&key, &keylen, &psk_keys, &psk_keys_len) != 1) {
error_print();
return -1;
}
}
if (!key) {
error_print();
return -1;
}
// TODO: change psk from buf to reference
if (keylen > sizeof(conn->psk)) {
error_print();
return -1;
}
memcpy(conn->psk, key, keylen);
conn->psk_len = keylen;
}
if (conn->hello_retry_request) {
// dgst_ctx <= ServerHello
if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_internal_error);
return -1;
}
if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ServerHello", &conn->dgst_ctx);
} else {
if (digest_init(&conn->dgst_ctx, conn->digest) != 1) {
error_print();
return -1;
}
// update(ClientHello)
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ClientHello", &conn->dgst_ctx);
// update(ServerHello)
if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) {
error_print();
return -1;
}
if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ServerHello", &conn->dgst_ctx);
}
if (conn->client_certs_len) {
sm2_sign_update(&conn->sign_ctx, conn->record + 5, conn->recordlen - 5);
}
if (tls13_generate_handshake_secrets(conn) != 1) {
error_print();
return -1;
}
tls13_generate_master_secret(conn);
if (tls13_generate_server_handshake_keys(conn) != 1) {
error_print();
return -1;
}
if (!conn->early_data) {
if (tls13_generate_client_handshake_keys(conn) != 1) {
error_print();
return -1;
}
}
return 1;
}
int tls13_send_change_cipher_spec(TLS_CONNECT *conn)
{
int ret;
if (!conn->recordlen) {
if(conn->verbose) tls_trace("send [ChangeCipherSpec]\n");
if (tls_record_set_change_cipher_spec(conn->record, &conn->recordlen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_internal_error);
return -1;
}
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
return 1;
}
int tls13_recv_change_cipher_spec(TLS_CONNECT *conn)
{
int ret;
if(conn->verbose) tls_trace("recv [ChangeCipherSpec]\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 ((ret = tls_record_get_change_cipher_spec(conn->record)) < 0) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls13_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
return 1;
}
int tls13_recv_encrypted_extensions(TLS_CONNECT *conn)
{
int ret;
const uint8_t *exts;
size_t extslen;
const uint8_t *supported_groups = NULL;
int server_name = 0;
int early_data = 0;
int alpn = 0;
if(conn->verbose) {
printf("recv {EncryptedExtensions}\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 (tls13_record_decrypt(conn->cipher_suite, &conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->record, conn->recordlen,
conn->plain_record, &conn->plain_recordlen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "EncryptedExtension", &conn->dgst_ctx);
if ((ret = tls13_record_get_handshake_encrypted_extensions(conn->plain_record,
&exts, &extslen)) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls13_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
while (extslen) {
int ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
}
// Exts in EE (see RFC 8446 page 37)
// * supported_groups
// * server_name
// * early_data
// * application_layer_protocol_negotiation
// * use_srtp
// * client_certificate_type
// * server_certificate_type
// * max_fragment_length
// * heartbeat
// * record_size_limit (RFC 8449)
switch (ext_type) {
case TLS_extension_supported_groups:
if (!ext_data) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
break;
case TLS_extension_server_name:
case TLS_extension_early_data:
if (ext_data) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
break;
case TLS_extension_application_layer_protocol_negotiation:
if (!ext_data) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
break;
}
switch (ext_type) {
case TLS_extension_supported_groups:
if (!conn->ctx->supported_groups_cnt) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (supported_groups) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
break;
case TLS_extension_server_name:
if (!conn->server_name) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (server_name) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
server_name = 1;
break;
case TLS_extension_early_data:
if (!conn->early_data) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (early_data) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
early_data = 1;
break;
case TLS_extension_application_layer_protocol_negotiation:
if (!conn->ctx->alpn_protocols_cnt) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (alpn) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if ((ret = tls_application_layer_protocol_negotiation_selected_from_bytes(
&conn->alpn_selected, ext_data, ext_datalen,
conn->ctx->alpn_protocols, conn->ctx->alpn_protocols_cnt)) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
alpn = 1;
break;
case TLS_extension_use_srtp:
case TLS_extension_client_certificate_type:
case TLS_extension_server_certificate_type:
case TLS_extension_max_fragment_length:
case TLS_extension_heartbeat:
case TLS_extension_record_size_limit:
break;
default:
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
}
// server_name
// if or not server support SNI, do nothing
// early_data
conn->early_data = early_data; // server allow EarlyData messages
return 1;
}
int tls_cert_match_signature_algorithms(const uint8_t *cert, size_t certlen,
const int *signature_algorithms, size_t signature_algorithms_cnt,
int *first_matched_sig_alg)
{
X509_KEY subject_public_key;
int group_oid;
size_t i;
if (!cert || !certlen || !signature_algorithms || !signature_algorithms_cnt) {
error_print();
return -1;
}
if (x509_cert_get_subject_public_key(cert, certlen, &subject_public_key) != 1) {
error_print();
return -1;
}
if (subject_public_key.algor != OID_ec_public_key) {
error_print();
return -1;
}
group_oid = subject_public_key.algor_param;
for (i = 0; i < signature_algorithms_cnt; i++) {
if (group_oid == tls_signature_scheme_group_oid(signature_algorithms[i])) {
*first_matched_sig_alg = signature_algorithms[i];
return 1;
}
}
*first_matched_sig_alg = 0;
return 0;
}
int tls_cert_chain_match_signature_algorithms_cert(
const uint8_t *cert_chain, size_t cert_chain_len,
const int *signature_algorithms_cert, size_t signature_algorithms_cert_cnt)
{
const uint8_t *cert;
size_t certlen;
const uint8_t *next_cert;
size_t next_certlen;
X509_KEY subject_public_key;
int alg_oid;
int group_oid;
int sig_alg;
if (!cert_chain || !cert_chain_len
|| !signature_algorithms_cert && signature_algorithms_cert_cnt) {
error_print();
return -1;
}
if (x509_cert_from_der(&cert, &certlen, &cert_chain, &cert_chain_len) != 1) {
error_print();
return -1;
}
while (cert_chain_len) {
if (x509_cert_get_signature_algor(cert, certlen, &alg_oid) != 1) {
error_print();
return -1;
}
if (x509_cert_from_der(&next_cert, &next_certlen, &cert_chain, &cert_chain_len) != 1
|| x509_cert_get_subject_public_key(next_cert, next_certlen, &subject_public_key) != 1) {
error_print();
return -1;
}
if (subject_public_key.algor != OID_ec_public_key) {
error_print();
return -1;
}
group_oid = subject_public_key.algor_param;
if (!(sig_alg = tls_signature_scheme_from_algorithm_and_group_oid(alg_oid, group_oid))) {
error_print();
return -1;
}
if (!tls_type_is_in_list(sig_alg, signature_algorithms_cert, signature_algorithms_cert_cnt)) {
return 0;
}
cert = next_cert;
certlen = next_certlen;
}
// can not do full check on the last cert, the public key is in root CA cert
if (x509_cert_get_signature_algor(cert, certlen, &alg_oid) != 1) {
error_print();
return -1;
}
// 这里需要CA证书才能验证最后一个证书的签名算法是否满足要求
return 1;
}
int tls_cert_match_server_name(const uint8_t *cert, size_t certlen, const uint8_t *host_name, size_t host_name_len)
{
int ret;
const uint8_t *subject_dns_name;
size_t subject_dns_name_len;
if (!cert || !certlen || !host_name || !host_name_len) {
error_print();
return -1;
}
if ((ret = x509_cert_get_subject_alt_name_dns_name(cert, certlen,
&subject_dns_name, &subject_dns_name_len)) < 0) {
error_print();
return -1;
} else if (ret == 0) {
// certificate without SubjectAltName extension will fail the check
// this is the default policy of major browsers and it is simple
// else we need to check all the cert chains to make sure none of them match the SNI
// then we can choose the default cert chain
return 0;
}
if (subject_dns_name_len != host_name_len
|| memcmp(subject_dns_name, host_name, host_name_len) != 0) {
return 0;
}
return 1;
}
int tls_cert_chain_match_extensions(
const uint8_t *cert_chain, size_t cert_chain_len,
const int *signature_algorithms, size_t signature_algorithms_cnt,
const int *signature_algorithms_cert, size_t signature_algorithms_cert_cnt, // optional
const uint8_t *ca_names, size_t ca_names_len, // optional
const uint8_t *oid_filters, size_t oid_filters_len, // optional
const uint8_t *host_name, size_t host_name_len, // optional
int *prefered_sig_alg)
{
int ret;
const uint8_t *cert;
size_t certlen;
int sig_alg;
if (!cert_chain || !cert_chain_len
|| !signature_algorithms || !signature_algorithms_cnt) {
error_print();
return -1;
}
if (prefered_sig_alg) {
*prefered_sig_alg = 0;
}
if (x509_certs_get_cert_by_index(cert_chain, cert_chain_len, 0,
&cert, &certlen) != 1) {
error_print();
return -1;
}
// signature_algorithms
if ((ret = tls_cert_match_signature_algorithms(cert, certlen,
signature_algorithms, signature_algorithms_cnt, &sig_alg)) < 0) {
error_print();
return -1;
} else if (ret == 0) {
return 0;
}
// server_name
if (host_name && host_name_len) {
if ((ret = tls_cert_match_server_name(cert, certlen,
host_name, host_name_len)) < 0) {
error_print();
return -1;
} else if (ret == 0) {
return 0;
}
}
// signature_algorithms_cert
if (signature_algorithms_cert && signature_algorithms_cert_cnt) {
if ((ret = tls_cert_chain_match_signature_algorithms_cert(cert_chain, cert_chain_len,
signature_algorithms_cert, signature_algorithms_cert_cnt)) < 0) {
error_print();
return -1;
} else if (ret == 0) {
return 0;
}
}
// certificate_authorities
if (ca_names && ca_names_len) {
if ((ret = tls_authorities_issued_certificate(
ca_names, ca_names_len, cert_chain, cert_chain_len)) < 0) {
error_print();
return -1;
} else if (ret == 0) {
return 0;
}
}
// oid_filters
if (oid_filters && oid_filters_len) {
}
if (prefered_sig_alg) {
*prefered_sig_alg = sig_alg;
}
return 1;
}
int tls13_cert_chains_select(const uint8_t *cert_chains, size_t cert_chains_len,
const int *signature_algorithms, size_t signature_algorithms_cnt,
const int *signature_algorithms_cert, size_t signature_algorithms_cert_cnt, // optional
const uint8_t *ca_names, size_t ca_names_len, // certificate_authorities optional
const uint8_t *oid_filters, size_t oid_filters_len, // optional, only in CertificateRequest
const uint8_t *host_name, size_t host_name_len, // optional, only in ClientHello
const uint8_t **certs, size_t *certs_len, size_t *certs_idx, int *prefered_sig_alg) // optional
{
size_t i;
if (!cert_chains || !cert_chains_len) {
error_print();
return -1;
}
if (!signature_algorithms || !signature_algorithms_cnt) {
error_print();
return -1;
}
for (i = 1; cert_chains_len; i++) {
const uint8_t *cert_chain;
size_t cert_chain_len;
int sig_alg;
int ret;
if (tls_uint24array_from_bytes(&cert_chain, &cert_chain_len,
&cert_chains, &cert_chains_len) != 1) {
error_print();
return -1;
}
if ((ret = tls_cert_chain_match_extensions(cert_chain, cert_chain_len,
signature_algorithms, signature_algorithms_cnt,
signature_algorithms_cert, signature_algorithms_cert_cnt,
ca_names, ca_names_len,
oid_filters, oid_filters_len,
host_name, host_name_len,
&sig_alg)) < 0) {
error_print();
return -1;
} else if (ret == 0) {
continue;
}
if (certs) *certs = cert_chain;
if (certs_len) *certs_len = cert_chain_len;
if (certs_idx) *certs_idx = i;
if (prefered_sig_alg) *prefered_sig_alg = sig_alg;
return 1;
}
if (certs) *certs = NULL;
if (certs_len) *certs_len = 0;
if (certs_idx) *certs_idx = 0;
if (prefered_sig_alg) *prefered_sig_alg = 0;
warning_print();
return 0;
}
int tls13_recv_certificate_request(TLS_CONNECT *conn)
{
int ret;
int handshake_type;
const uint8_t *handshake_data;
size_t handshake_datalen;
int client_cert;
// certificate_request
const uint8_t *request_context;
size_t request_context_len;
const uint8_t *exts;
size_t extslen;
// extensions
const uint8_t *signature_algorithms = NULL;
size_t signature_algorithms_len;
const uint8_t *signature_algorithms_cert = NULL;
size_t signature_algorithms_cert_len;
const uint8_t *certificate_authorities = NULL;
size_t certificate_authorities_len;
const uint8_t *oid_filters = NULL;
size_t oid_filters_len;
int status_request = 0;
int signed_certificate_timestamp = 0;
int common_sig_algs[4];
size_t common_sig_algs_cnt;
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;
if(conn->verbose) tls_trace("recv {CertificateRequest*}\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
if (tls13_record_decrypt(conn->cipher_suite, &conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->record, conn->recordlen,
conn->plain_record, &conn->plain_recordlen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
if (tls_record_get_handshake(conn->plain_record,
&handshake_type, &handshake_data, &handshake_datalen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
}
if (handshake_type != TLS_handshake_certificate_request) {
if(conn->verbose) tls_trace(" no {CertificateRequest}\n");
return 0;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
if ((ret = tls13_record_get_handshake_certificate_request(conn->plain_record,
&request_context, &request_context_len, &exts, &extslen)) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
}
if (request_context) {
// request_context must be null in full/initial handshake
// and must not be null in post authentication handshakes
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
while (extslen) {
int ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
}
// exts in CR (from RFC 8446 page 37)
// * signature_algorithms - the only ext must exist
// * signature_algorithms_cert
// * certificate_authorities
// * oid_filters (only in CR)
// * status_request
// * signed_certificate_timestamp
switch (ext_type) {
case TLS_extension_signature_algorithms:
case TLS_extension_signature_algorithms_cert:
case TLS_extension_certificate_authorities:
case TLS_extension_oid_filters:
if (!ext_data) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
break;
case TLS_extension_status_request:
case TLS_extension_signed_certificate_timestamp:
if (ext_data) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
break;
}
switch (ext_type) {
case TLS_extension_signature_algorithms:
if (signature_algorithms) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
signature_algorithms = ext_data;
signature_algorithms_len = ext_datalen;
break;
case TLS_extension_signature_algorithms_cert:
if (signature_algorithms_cert) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
signature_algorithms_cert = ext_data;
signature_algorithms_cert_len = ext_datalen;
break;
case TLS_extension_certificate_authorities:
if (certificate_authorities) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
certificate_authorities = ext_data;
certificate_authorities_len = ext_datalen;
break;
case TLS_extension_oid_filters:
if (oid_filters) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
oid_filters = ext_data;
oid_filters_len = ext_datalen;
break;
case TLS_extension_status_request:
if (status_request) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
status_request = 1;
break;
case TLS_extension_signed_certificate_timestamp:
if (signed_certificate_timestamp) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
signed_certificate_timestamp = 1;
break;
default:
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
}
if (!signature_algorithms) {
error_print();
tls13_send_alert(conn, TLS_alert_missing_extension);
return -1;
}
// even if no client cert, check extensions
if (conn->ctx->cert_chains_len) {
client_cert = 1;
}
// signature_algorithms
if ((ret = tls_process_signature_algorithms(
signature_algorithms, signature_algorithms_len,
conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt,
common_sig_algs, &common_sig_algs_cnt,
sizeof(common_sig_algs)/sizeof(common_sig_algs[0]))) < 0) {
error_print();
return -1;
} else if (ret == 0) {
client_cert = 0;
}
// signature_algorithms_cert
if (signature_algorithms_cert) {
if ((ret = tls_process_signature_algorithms(
signature_algorithms_cert, signature_algorithms_cert_len,
conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt,
common_sig_algs_cert, &common_sig_algs_cert_cnt,
sizeof(common_sig_algs_cert)/sizeof(common_sig_algs_cert[0]))) < 0) {
error_print();
return -1;
} else if (ret == 0) {
client_cert = 0;
}
}
// certificate_authorities
if (certificate_authorities) {
if (tls13_certificate_authorities_from_bytes(
&ca_names, &ca_names_len,
certificate_authorities, certificate_authorities_len) != 1) {
error_print();
return -1;
}
}
// oid_filters
if (oid_filters) {
if (tls13_oid_filters_from_bytes(
&filters, &filters_len, oid_filters, oid_filters_len) != 1) {
error_print();
return -1;
}
}
// status_request
if (status_request) {
conn->status_request = 1;
}
// signed_certificate_timestamp
if (signed_certificate_timestamp) {
conn->signed_certificate_timestamp = 1;
}
// select cert_chain
// * signature_algorithms
// * [signature_algorithms_cert]
// * [certificate_authorities]
// * [oid_filter]
//
if (client_cert) {
// client provides no certificate
if (!conn->ctx->cert_chains_len) {
warning_print();
conn->cert_chain = NULL;
conn->cert_chain_len = 0;
conn->cert_chain_idx = 0;
ret = 0;
} else if ((ret = tls13_cert_chains_select(
conn->ctx->cert_chains, conn->ctx->cert_chains_len,
common_sig_algs, common_sig_algs_cnt,
common_sig_algs_cert, common_sig_algs_cert_cnt,
ca_names, ca_names_len,
filters, filters_len,
NULL, 0,
&conn->cert_chain, &conn->cert_chain_len, &conn->cert_chain_idx, &conn->sig_alg)) < 0) {
error_print();
return -1;
}
// when ret == 0, conn->cert_chain == NULL
}
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
conn->certificate_request = 1;
conn->record_offset = 0;
conn->recordlen = 0;
conn->plain_recordlen = 0;
return ret;
}
int tls13_recv_server_certificate(TLS_CONNECT *conn)
{
int ret;
const uint8_t *request_context;
size_t request_context_len;
const uint8_t *leaf_status_request_ocsp_response = NULL;
size_t leaf_status_request_ocsp_response_len = 0;
const uint8_t *leaf_signed_certificate_timestamp;
size_t leaf_signed_certificate_timestamp_len;
const uint8_t *cert;
size_t certlen;
const int *signature_algorithms_cert = NULL;
size_t signature_algorithms_cert_cnt = 0;
const uint8_t *ca_names = NULL;
size_t ca_names_len = 0;
const uint8_t *host_name = NULL;
size_t host_name_len = 0;
int verify_result = X509_verify_ok;
if(conn->verbose) tls_trace("recv server {Certificate}\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
// decrypt unless previous handshake is CertificateRequest
if (!conn->plain_recordlen) {
if (tls13_record_decrypt(conn->cipher_suite, &conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->record, conn->recordlen,
conn->plain_record, &conn->plain_recordlen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
}
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ServerCertificate", &conn->dgst_ctx);
if ((ret = tls13_record_get_handshake_certificate(conn->plain_record,
&request_context, &request_context_len,
conn->peer_cert_chain, &conn->peer_cert_chain_len, sizeof(conn->peer_cert_chain),
&leaf_status_request_ocsp_response, &leaf_status_request_ocsp_response_len,
&leaf_signed_certificate_timestamp, &leaf_signed_certificate_timestamp_len)) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls13_send_alert(conn, TLS_alert_unexpected_message);
return 0;
}
if (request_context) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (!conn->peer_cert_chain_len) {
error_print();
conn->verify_result = X509_verify_err_certificate;
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
// check server cert_chain match ClientHello.extensions
if (conn->signature_algorithms_cert) {
signature_algorithms_cert = conn->ctx->signature_algorithms;
signature_algorithms_cert_cnt = conn->ctx->signature_algorithms_cnt;
}
if (conn->certificate_authorities) {
ca_names = conn->ctx->ca_names;
ca_names_len = conn->ctx->ca_names_len;
}
if (conn->host_name_len) {
host_name = conn->host_name;
host_name_len = conn->host_name_len;
}
// verify server cert_chain
ret = tls_cert_chain_verify(
conn->protocol, X509_cert_chain_server, conn->cipher_suite,
1,
conn->peer_cert_chain, conn->peer_cert_chain_len,
conn->ctx->cacerts, conn->ctx->cacertslen,
NULL, 0,
leaf_status_request_ocsp_response, leaf_status_request_ocsp_response_len,
conn->ctx->verify_depth,
NULL, 0,
conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt,
signature_algorithms_cert, signature_algorithms_cert_cnt,
ca_names, ca_names_len,
NULL, 0,
host_name, host_name_len,
&verify_result, NULL);
if (ret < 0) {
error_print();
conn->verify_result = verify_result;
tls13_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
if (ret == 0) {
error_print();
conn->verify_result = verify_result;
if (verify_result == X509_verify_err_crl
|| verify_result == X509_verify_err_ocsp) {
tls13_send_alert(conn, TLS_alert_certificate_revoked);
} else {
tls13_send_alert(conn, TLS_alert_bad_certificate);
}
return -1;
}
conn->verify_result = verify_result;
// signed_certificate_timestamp
if (leaf_signed_certificate_timestamp) {
if (x509_certs_get_cert_by_index(conn->peer_cert_chain,
conn->peer_cert_chain_len, 0, &cert, &certlen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
if (tls13_signed_certificate_timestamp_verify(
leaf_signed_certificate_timestamp,
leaf_signed_certificate_timestamp_len,
SCT_log_entry_type_x509_entry, NULL, cert, certlen,
conn->ctx->ct_logs, conn->ctx->ct_logs_cnt,
conn->ctx->ct_at_least) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
}
return 1;
}
int tls13_recv_server_certificate_verify(TLS_CONNECT *conn)
{
int ret;
int sig_alg;
const uint8_t *sig;
size_t siglen;
const uint8_t *cert;
size_t certlen;
X509_KEY public_key;
if(conn->verbose) 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->cipher_suite, &conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->record, conn->recordlen,
conn->plain_record, &conn->plain_recordlen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
if ((ret = tls13_record_get_handshake_certificate_verify(conn->plain_record,
&sig_alg, &sig, &siglen)) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls13_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
if (tls_type_is_in_list(sig_alg, conn->ctx->signature_algorithms,
conn->ctx->signature_algorithms_cnt) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (!sig) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (x509_certs_get_cert_by_index(conn->peer_cert_chain, conn->peer_cert_chain_len, 0, &cert, &certlen) != 1
|| x509_cert_get_subject_public_key(cert, certlen, &public_key) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
// verify signature
if (tls13_verify_certificate_verify(TLS_server_mode, sig_alg, &public_key,
&conn->dgst_ctx, sig, siglen) != 1) {
error_print();
return -1;
}
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
conn->recordlen = 0;
conn->plain_recordlen = 0;
return 1;
}
int tls13_recv_client_certificate_verify(TLS_CONNECT *conn)
{
int ret;
int sig_alg;
const uint8_t *sig;
size_t siglen;
const uint8_t *cert;
size_t certlen;
X509_KEY public_key;
if(conn->verbose) 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->cipher_suite, &conn->client_write_key, conn->client_write_iv,
conn->client_seq_num, conn->record, conn->recordlen,
conn->plain_record, &conn->plain_recordlen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
tls_seq_num_incr(conn->client_seq_num);
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
if ((ret = tls13_record_get_handshake_certificate_verify(conn->plain_record,
&sig_alg, &sig, &siglen)) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls13_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
if (tls_type_is_in_list(sig_alg, conn->ctx->signature_algorithms,
conn->ctx->signature_algorithms_cnt) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (!sig) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (x509_certs_get_cert_by_index(conn->peer_cert_chain, conn->peer_cert_chain_len, 0, &cert, &certlen) != 1
|| x509_cert_get_subject_public_key(cert, certlen, &public_key) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
// verify signature
if (tls13_verify_certificate_verify(TLS_client_mode, sig_alg, &public_key,
&conn->dgst_ctx, sig, siglen) != 1) {
error_print();
return -1;
}
// must update after tls13_verify_certificate_verify
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "CertificateVerify", &conn->dgst_ctx);
return 1;
}
int tls13_recv_server_finished(TLS_CONNECT *conn)
{
int ret;
const uint8_t *server_verify_data;
size_t server_verify_data_len;
uint8_t verify_data[64];
size_t verify_data_len;
// compute verify_data before digest_update
if (tls13_compute_verify_data(conn->server_handshake_traffic_secret,
&conn->dgst_ctx, verify_data, &verify_data_len) != 1) {
error_print();
return -1;
}
if(conn->verbose) tls_trace("recv server {Finished}\n");
if (!conn->plain_recordlen) {
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
if (tls13_record_decrypt(conn->cipher_suite, &conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->record, conn->recordlen,
conn->plain_record, &conn->plain_recordlen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ServerFinished", &conn->dgst_ctx);
if ((ret = tls13_record_get_handshake_finished(conn->plain_record,
&server_verify_data, &server_verify_data_len)) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls13_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
if (server_verify_data_len != verify_data_len
|| memcmp(server_verify_data, verify_data, verify_data_len) != 0) {
error_print();
tls13_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
tls13_generate_application_secrets(conn);
tls13_generate_server_application_keys(conn);
return 1;
}
int tls13_send_client_certificate(TLS_CONNECT *conn)
{
int ret;
if(conn->verbose) tls_trace("send client {Certificate*}\n");
if (conn->recordlen == 0) {
const uint8_t *request_context = NULL;
size_t request_context_len = 0;
const uint8_t *entity_status_request_ocsp_response = NULL;
size_t entity_status_request_ocsp_response_len = 0;
const uint8_t *entity_signed_certificate_timestamp = NULL;
size_t entity_signed_certificate_timestamp_len = 0;
size_t padding_len;
// status_request
if (conn->status_request) {
entity_status_request_ocsp_response = conn->status_request_ocsp_response;
entity_status_request_ocsp_response_len = conn->status_request_ocsp_response_len;
}
// signed_certificate_timestamp
if (conn->signed_certificate_timestamp) {
entity_signed_certificate_timestamp = conn->signed_certificate_timestamp_list;
entity_signed_certificate_timestamp_len = conn->signed_certificate_timestamp_list_len;
}
if (tls13_record_set_handshake_certificate(conn->plain_record, &conn->plain_recordlen,
request_context, request_context_len,
conn->cert_chain, conn->cert_chain_len,
entity_status_request_ocsp_response, entity_status_request_ocsp_response_len,
entity_signed_certificate_timestamp, entity_signed_certificate_timestamp_len) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_internal_error);
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "client Certficate", &conn->dgst_ctx);
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(conn->cipher_suite, &conn->client_write_key, conn->client_write_iv,
conn->client_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->client_seq_num);
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
return 1;
}
int tls13_send_client_certificate_verify(TLS_CONNECT *conn)
{
int ret;
if(conn->verbose) tls_trace("send client {CertificateVerify*}\n");
if (!conn->recordlen) {
X509_KEY *sign_key = &conn->ctx->x509_keys[conn->cert_chain_idx - 1];
uint8_t sig[256];
size_t siglen;
size_t padding_len;
if (tls13_sign_certificate_verify(TLS_client_mode, conn->sig_alg,
sign_key, &conn->dgst_ctx, sig, &siglen) != 1) {
error_print();
return -1;
}
if (tls13_record_set_handshake_certificate_verify(
conn->plain_record, &conn->plain_recordlen,
conn->sig_alg, sig, siglen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_internal_error);
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "after client CertificateVerify", &conn->dgst_ctx);
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(conn->cipher_suite, &conn->client_write_key, conn->client_write_iv,
conn->client_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_internal_error);
return -1;
}
tls_seq_num_incr(conn->client_seq_num);
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
return 1;
}
int tls13_send_client_finished(TLS_CONNECT *conn)
{
int ret;
if(conn->verbose) tls_trace("send client {Finished}\n");
if (!conn->recordlen) {
uint8_t verify_data[64];
size_t verify_data_len;
size_t padding_len;
tls13_compute_verify_data(conn->client_handshake_traffic_secret, &conn->dgst_ctx,
verify_data, &verify_data_len);
if (tls_record_set_handshake_finished(conn->plain_record, &conn->plain_recordlen,
verify_data, verify_data_len) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_internal_error);
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
//format_print(stderr, 0, 0, "client_seq_num: "PRIu64"\n", GETU64(conn->client_seq_num));
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(conn->cipher_suite, &conn->client_write_key, conn->client_write_iv,
conn->client_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_internal_error);
return -1;
}
tls_seq_num_incr(conn->client_seq_num);
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
tls13_generate_client_application_keys(conn);
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
return 1;
}
static int tls13_cipher_suites_match_signature_scheme(
const int *cipher_suites, size_t cipher_suites_cnt, int sig_alg,
int *selected, size_t *selected_cnt, size_t max_cnt)
{
int digest_oid;
size_t i;
switch (tls_signature_scheme_algorithm_oid(sig_alg)) {
case OID_sm2sign_with_sm3:
digest_oid = OID_sm3;
break;
case OID_ecdsa_with_sha256:
digest_oid = OID_sha256;
break;
default:
error_print();
return -1;
}
*selected_cnt = 0;
for (i = 0; i < cipher_suites_cnt && i < max_cnt; i++) {
const BLOCK_CIPHER *cipher;
const DIGEST *digest;
if (tls_cipher_suite_get(cipher_suites[i], &cipher, &digest) != 1) {
error_print();
return -1;
}
if (digest->oid == digest_oid) {
selected[(*selected_cnt)++] = cipher_suites[i];
}
}
if (*selected_cnt == 0) {
return 0;
}
return 1;
}
int tls13_recv_client_hello(TLS_CONNECT *conn)
{
int ret;
uint8_t *record = conn->record;
int client_verify = 0;
// client_hello
int legacy_version;
const uint8_t *random;
const uint8_t *legacy_session_id;
size_t legacy_session_id_len;
const uint8_t *cipher_suites;
size_t cipher_suites_len;
const uint8_t *exts;
size_t extslen;
// extensions
const uint8_t *supported_versions = NULL;
size_t supported_versions_len;
const uint8_t *supported_groups = NULL;
size_t supported_groups_len;
const uint8_t *signature_algorithms = NULL;
size_t signature_algorithms_len;
const uint8_t *signature_algorithms_cert = NULL;
size_t signature_algorithms_cert_len;
const uint8_t *certificate_authorities = NULL;
size_t certificate_authorities_len;
const uint8_t *key_share = NULL;
size_t key_share_len;
const uint8_t *server_name = NULL;
size_t server_name_len;
const uint8_t *alpn = NULL;
size_t alpn_len;
const uint8_t *psk_key_exchange_modes = NULL;
size_t psk_key_exchange_modes_len;
const uint8_t *pre_shared_key = NULL;
size_t pre_shared_key_len;
const uint8_t *status_request = NULL;
size_t status_request_len;
int signed_certificate_timestamp = 0;
int early_data = 0;
int common_versions[4];
size_t common_versions_cnt = 0;
int common_groups[4];
size_t common_groups_cnt = 0;
int common_sig_algs[4];
size_t common_sig_algs_cnt = 0;
int common_sig_algs_cert[4];
size_t common_sig_algs_cert_cnt = 0;
const uint8_t *host_name = NULL;
size_t host_name_len;
int common_key_exchange_modes = 0;
const uint8_t *ca_names = NULL;
size_t ca_names_len = 0;
// 这个判断应该改为一个函数
/*
if (client_verify)
tls_client_verify_init(&conn->client_verify_ctx);
*/
if(conn->verbose) 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
&& tls_record_protocol(record) != TLS_protocol_tls12) {
error_print();
tls13_send_alert(conn, TLS_alert_protocol_version);
return -1;
}
if ((ret = tls_record_get_handshake_client_hello(conn->record,
&legacy_version, &random, &legacy_session_id, &legacy_session_id_len,
&cipher_suites, &cipher_suites_len, &exts, &extslen)) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls13_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
// legacy_version
if (legacy_version != TLS_protocol_tls12) {
error_print();
tls13_send_alert(conn, TLS_alert_protocol_version);
return -1;
}
// random
memcpy(conn->client_random, random, 32);
// legacy_session_id
if (legacy_session_id_len) {
// tls13 server ignore legacy_session_id
warning_print();
if (legacy_session_id_len > sizeof(conn->session_id)) {
error_print();
return -1;
}
memcpy(conn->session_id, legacy_session_id, legacy_session_id_len);
conn->session_id_len = legacy_session_id_len;
}
// cipher_suites
// after select server cert_chain, cipher_suite might be changed
if ((ret = tls_cipher_suites_select(cipher_suites, cipher_suites_len,
conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt,
&conn->cipher_suite)) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls13_send_alert(conn, TLS_alert_handshake_failure);
return -1;
}
while (extslen) {
int ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
}
// exts in CH (RFC 8446 page 37), only oid_filter not in CH
// * supported_versions
// * signature_algorithms
// * signature_algorithms_cert
// * certificate_authorities
// * server_name
// * status_request
// * signed_certificate_timestamp
// * supported_groups
// * key_share
// * psk_key_exchange_modes
// * pre_shared_key
// * early_data (only in ClientHello1)
// * max_fragment_length
// * use_srtp
// * heartbeat
// * application_layer_protocol_negotiation
// * server_certificate_type: if client accept raw/x509
// * client_certificate_type: if client sned raw/x509
// * padding
// * post_handshake_auth: client support post handshake auth
// * cookie (only in ClientHello2)
switch (ext_type) {
case TLS_extension_supported_versions:
case TLS_extension_supported_groups:
case TLS_extension_signature_algorithms:
case TLS_extension_signature_algorithms_cert:
case TLS_extension_certificate_authorities:
case TLS_extension_key_share:
case TLS_extension_server_name:
case TLS_extension_application_layer_protocol_negotiation:
case TLS_extension_psk_key_exchange_modes:
case TLS_extension_pre_shared_key:
case TLS_extension_status_request:
if (!ext_data) {
error_print();
return -1;
}
break;
case TLS_extension_signed_certificate_timestamp:
case TLS_extension_early_data:
if (ext_data) {
error_print();
return -1;
}
break;
}
switch (ext_type) {
case TLS_extension_supported_versions:
if (supported_versions) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
supported_versions = ext_data;
supported_versions_len = ext_datalen;
break;
case TLS_extension_supported_groups:
if (supported_groups) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
supported_groups = ext_data;
supported_groups_len = ext_datalen;
break;
case TLS_extension_signature_algorithms:
if (signature_algorithms) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
signature_algorithms = ext_data;
signature_algorithms_len = ext_datalen;
break;
case TLS_extension_signature_algorithms_cert:
if (signature_algorithms_cert) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
signature_algorithms_cert = ext_data;
signature_algorithms_cert_len = ext_datalen;
break;
case TLS_extension_certificate_authorities:
if (certificate_authorities) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
certificate_authorities = ext_data;
certificate_authorities_len = ext_datalen;
break;
case TLS_extension_key_share:
if (key_share) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
key_share = ext_data;
key_share_len = ext_datalen;
break;
case TLS_extension_server_name:
if (server_name) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
server_name = ext_data;
server_name_len = ext_datalen;
break;
case TLS_extension_application_layer_protocol_negotiation:
if (alpn) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
alpn = ext_data;
alpn_len = ext_datalen;
break;
case TLS_extension_psk_key_exchange_modes:
if (psk_key_exchange_modes) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
psk_key_exchange_modes = ext_data;
psk_key_exchange_modes_len = ext_datalen;
break;
case TLS_extension_pre_shared_key:
if (pre_shared_key) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
pre_shared_key = ext_data;
pre_shared_key_len = ext_datalen;
break;
case TLS_extension_status_request:
if (status_request) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
status_request = ext_data;
status_request_len = ext_datalen;
break;
case TLS_extension_signed_certificate_timestamp:
if (signed_certificate_timestamp) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
signed_certificate_timestamp = 1;
break;
case TLS_extension_early_data:
if (early_data) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
early_data = 1;
break;
case TLS_extension_cookie:
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
/*
case TLS_extension_max_fragment_length:
case TLS_extension_use_srtp:
case TLS_extension_heartbeat:
case TLS_extension_application_layer_protocol_negotiation:
case TLS_extension_server_certificate_type:
case TLS_extension_client_certificate_type:
case TLS_extension_padding:
case TLS_extension_post_handshake_auth:
default:
format_print(stderr, 0, 4, "%s: %d: unsupported extension: %s (%04x)\n",
__FILE__, __LINE__, tls_extension_name(ext_type), ext_type);
*/
}
}
// from RFC 8446 section 9.2
// * supported_versions required for CH, SH, HRR
// * if no pre_shared_key, signature_algorithms + supported_groups must exist
// * supported_groups + key_share must exist together
// * empty key_share is permitted
//
if (!supported_versions) {
error_print();
tls13_send_alert(conn, TLS_alert_missing_extension);
return -1;
}
if (!pre_shared_key) {
if (!(signature_algorithms && supported_groups)) {
error_print();
tls13_send_alert(conn, TLS_alert_missing_extension);
return -1;
}
}
if ((supported_groups && !key_share)
|| (!supported_groups && key_share)) {
error_print();
tls13_send_alert(conn, TLS_alert_missing_extension);
return -1;
}
if (pre_shared_key && !psk_key_exchange_modes) {
error_print();
tls13_send_alert(conn, TLS_alert_missing_extension);
return -1;
}
// supported_versions
if ((ret = tls13_process_client_supported_versions(
supported_versions, supported_versions_len,
conn->ctx->supported_versions, conn->ctx->supported_versions_cnt,
common_versions, &common_versions_cnt,
sizeof(common_versions)/sizeof(common_versions[0]))) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls13_send_alert(conn, TLS_alert_protocol_version);
return -1;
}
if (common_versions[0] != TLS_protocol_tls13) {
error_print();
tls13_send_alert(conn, TLS_alert_protocol_version);
return -1;
}
conn->protocol = common_versions[0];
// psk_key_exchange_modes
if (psk_key_exchange_modes) {
if (tls13_psk_key_exchange_modes_from_bytes(&common_key_exchange_modes,
psk_key_exchange_modes, psk_key_exchange_modes_len) != 1) {
error_print();
return -1;
}
}
// client key_exchange_modes
if (supported_groups && signature_algorithms) {
common_key_exchange_modes |= TLS_KE_CERT_DHE;
}
// common key_exchange_modes
common_key_exchange_modes &= conn->key_exchange_modes;
if (!common_key_exchange_modes) {
error_print();
tls13_send_alert(conn, TLS_alert_handshake_failure);
return -1;
}
// signature_algorithms
if (signature_algorithms) {
if ((ret = tls_process_signature_algorithms(
signature_algorithms, signature_algorithms_len,
conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt,
common_sig_algs, &common_sig_algs_cnt,
sizeof(common_sig_algs)/sizeof(common_sig_algs[0]))) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
common_key_exchange_modes &= ~TLS_KE_CERT_DHE;
}
}
// signature_algorithms_cert
if (signature_algorithms_cert) {
if ((ret = tls_process_signature_algorithms(
signature_algorithms_cert, signature_algorithms_cert_len,
conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt,
common_sig_algs_cert, &common_sig_algs_cert_cnt,
sizeof(common_sig_algs_cert)/sizeof(common_sig_algs_cert[0]))) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
common_key_exchange_modes &= ~TLS_KE_CERT_DHE;
}
}
// certificate_authorities
if (certificate_authorities) {
if (tls13_certificate_authorities_from_bytes(&ca_names, &ca_names_len,
certificate_authorities, certificate_authorities_len) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
}
// server_name
if (server_name) {
if (tls_server_name_from_bytes(&host_name, &host_name_len,
server_name, server_name_len) != 1) {
error_print();
return -1;
}
conn->server_name = 1;
}
// application_layer_protocol_negotiation
if (alpn) {
if (!conn->ctx->alpn_protocols_cnt) {
error_print();
tls13_send_alert(conn, TLS_alert_no_application_protocol);
return -1;
}
if ((ret = tls_application_layer_protocol_negotiation_select(
alpn, alpn_len,
conn->ctx->alpn_protocols, conn->ctx->alpn_protocols_cnt,
&conn->alpn_selected)) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls13_send_alert(conn, TLS_alert_no_application_protocol);
return -1;
}
}
// select server cert_chain
// * signature_algorithms
// * [signature_algorithms_cert]
// * [certificate_authorities]
// * [server_name.host_name]
//
if (common_key_exchange_modes & TLS_KE_CERT_DHE) {
int common_cipher_suites[4];
size_t common_cipher_suites_cnt;
if (!conn->ctx->cert_chains_len) {
error_print();
return -1;
}
if ((ret = tls13_cert_chains_select(
conn->ctx->cert_chains, conn->ctx->cert_chains_len,
common_sig_algs, common_sig_algs_cnt,
common_sig_algs_cert, common_sig_algs_cert_cnt,
ca_names, ca_names_len,
NULL, 0, // oid_filters
host_name, host_name_len,
&conn->cert_chain, &conn->cert_chain_len, &conn->cert_chain_idx, &conn->sig_alg)) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
common_key_exchange_modes &= ~TLS_KE_CERT_DHE;
}
// cipher_suites match conn->sig_alg
if (tls13_cipher_suites_match_signature_scheme(
conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt, conn->sig_alg,
common_cipher_suites, &common_cipher_suites_cnt,
sizeof(common_cipher_suites)/sizeof(common_cipher_suites[0])) != 1) {
error_print();
return -1;
}
// update conn->cipher_suite
if ((ret = tls_cipher_suites_select(cipher_suites, cipher_suites_len,
common_cipher_suites, common_cipher_suites_cnt,
&conn->cipher_suite)) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls13_send_alert(conn, TLS_alert_handshake_failure);
return -1;
}
}
// format_print(stderr, 0, 0, "conn->cipher_suite: %s\n", tls_cipher_suite_name(conn->cipher_suite));
if (tls_cipher_suite_get(conn->cipher_suite, &conn->cipher, &conn->digest) != 1) {
error_print();
return -1;
}
// digest_update(client_hello) until conn->hello_retry_request
// status_request
if (status_request) {
int status_type;
const uint8_t *responder_id_list;
size_t responder_id_list_len;
const uint8_t *request_exts;
size_t request_exts_len;
if (tls_client_status_request_from_bytes(&status_type,
&responder_id_list, &responder_id_list_len,
&request_exts, &request_exts_len,
status_request, status_request_len) != 1) {
error_print();
return -1;
}
if (status_type != TLS_certificate_status_type_ocsp) {
error_print();
return -1;
}
if (conn->cert_chain) {
const uint8_t *cp = conn->ctx->status_request_ocsp_responses;
size_t len = conn->ctx->status_request_ocsp_responses_len;
size_t i;
// get ocsp_response
for (i = 0; i < conn->cert_chain_idx; i++) {
if (tls_uint24array_from_bytes(
&conn->status_request_ocsp_response,
&conn->status_request_ocsp_response_len,
&cp, &len) != 1) {
error_print();
return -1;
}
}
// check if ocsp_response match the status_request
if (conn->status_request_ocsp_response) {
if ((ret = tls_ocsp_response_match_status_request(
conn->status_request_ocsp_response,
conn->status_request_ocsp_response_len,
responder_id_list, responder_id_list_len,
request_exts, request_exts_len)) < 0) {
error_print();
return -1;
} else if (ret == 0) {
conn->status_request_ocsp_response = NULL;
conn->status_request_ocsp_response_len = 0;
}
}
}
// send CertificateRequest.status_request
conn->status_request = 1;
}
// signed_certificate_timestamp
if (signed_certificate_timestamp) {
if (conn->cert_chain) {
const uint8_t *sct_lists = conn->ctx->signed_certificate_timestamp_lists;
size_t sct_lists_len = conn->ctx->signed_certificate_timestamp_lists_len;
size_t i;
for (i = 0; i < conn->cert_chain_idx; i++) {
if (tls_uint16array_from_bytes(
&conn->signed_certificate_timestamp_list,
&conn->signed_certificate_timestamp_list_len,
&sct_lists, &sct_lists_len) != 1) {
error_print();
return -1;
}
}
}
// send CertificateRequest.signed_certificate_timestamp
conn->signed_certificate_timestamp = 1;
}
// supported_groups
if (supported_groups) {
if ((ret = tls_process_supported_groups(
supported_groups, supported_groups_len,
conn->ctx->supported_groups, conn->ctx->supported_groups_cnt,
common_groups, &common_groups_cnt,
sizeof(common_groups)/sizeof(common_groups[0]))) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
common_key_exchange_modes &= ~(TLS_KE_CERT_DHE|TLS_KE_PSK_DHE);
}
}
// key_share
if (key_share) {
int group = 0;
const uint8_t *key_exchange = NULL;
size_t key_exchange_len = 0;
if (common_groups_cnt) {
if ((ret = tls13_process_key_share_client_hello(
key_share, key_share_len, common_groups, common_groups_cnt,
&group, &key_exchange, &key_exchange_len)) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
// send HelloRetryRequest if modes == CERT_DHE|PSK_DHE
conn->key_exchange_group = common_groups[0];
} else {
conn->key_exchange_group = group;
memcpy(conn->peer_key_exchange, key_exchange, key_exchange_len);
conn->peer_key_exchange_len = key_exchange_len;
}
}
}
// pre_shared_key
if (pre_shared_key) {
if (common_key_exchange_modes & (TLS_KE_PSK_DHE|TLS_KE_PSK)) {
if (conn->psk_identities_len) {
if ((ret = tls13_process_client_pre_shared_key_external(conn,
pre_shared_key, pre_shared_key_len)) < 0) {
error_print();
return -1;
} else if (ret == 0) {
common_key_exchange_modes &= ~(TLS_KE_PSK_DHE|TLS_KE_PSK);
}
} else if (conn->ctx->session_ticket_key) {
if ((ret = tls13_process_client_pre_shared_key_from_ticket(conn,
pre_shared_key, pre_shared_key_len)) < 0) {
error_print();
return -1;
} else if (ret == 0) {
common_key_exchange_modes &= ~(TLS_KE_PSK_DHE|TLS_KE_PSK);
}
} else {
// caller should set session_ticket_key or psk_keys
error_print();
return -1;
}
//format_print(stderr, 0, 0, "selected_psk_identity: %d\n", conn->selected_psk_identity - 1);
//format_bytes(stderr, 0, 0, "selected_psk", conn->psk, conn->psk_len);
}
}
/*
decide the final key exchange mode and hello_retry_request
PSK_DHE
* selected_psk_identity
* key_exchange_group
* [key_exchanges_cnt]
PSK
* selected_psk_identity
CERT_DHE
* cert_chain
* key_exchange_group
* [key_exchanges_cnt]
*/
if ((common_key_exchange_modes & TLS_KE_PSK_DHE) && conn->selected_psk_identity) {
if (conn->key_exchange_group) {
conn->key_exchange_modes = TLS_KE_PSK_DHE;
if (!conn->peer_key_exchange_len) {
conn->hello_retry_request = 1;
}
}
} else if ((common_key_exchange_modes & TLS_KE_PSK) && conn->selected_psk_identity) {
conn->key_exchange_modes = TLS_KE_PSK;
} else if (common_key_exchange_modes & TLS_KE_CERT_DHE) {
if (conn->cert_chain && conn->key_exchange_group) {
conn->key_exchange_modes = TLS_KE_CERT_DHE;
}
if (!conn->peer_key_exchange_len) {
conn->hello_retry_request = 1;
}
} else {
error_print();
tls13_send_alert(conn, TLS_alert_handshake_failure);
return -1;
}
//tls_key_exchange_modes_print(stderr, 0, 0, "server key_exchange_mode", conn->key_exchange_modes);
// hello_retry_request
if (conn->hello_retry_request) {
uint8_t message_hash[4 + 32];
size_t dgstlen;
// cache ClientHello1, need by recv_client_hello_again
memcpy(conn->plain_record, conn->record, conn->recordlen);
conn->plain_recordlen = conn->recordlen;
// message_hash handshake
message_hash[0] = TLS_handshake_message_hash;
message_hash[1] = 0;
message_hash[2] = 0;
message_hash[3] = 32;
if (digest_init(&conn->dgst_ctx, conn->digest) != 1
|| digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1
|| digest_finish(&conn->dgst_ctx, message_hash + 4, &dgstlen) != 1) {
error_print();
return -1;
}
if (digest_init(&conn->dgst_ctx, conn->digest) != 1
|| digest_update(&conn->dgst_ctx, message_hash, sizeof(message_hash)) != 1) {
error_print();
return -1;
}
} else {
if (digest_init(&conn->dgst_ctx, conn->digest) != 1
|| digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) {
error_print();
return -1;
}
if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ClientHello", &conn->dgst_ctx);
}
// early_data
conn->early_data =
(conn->early_data) &&
(conn->key_exchange_modes & (TLS_KE_PSK_DHE | TLS_KE_PSK)) &&
(early_data) &&
(conn->hello_retry_request == 0);
// generate early_data keys
if (conn->early_data) {
if (tls13_generate_early_keys(conn) != 1) {
error_print();
return -1;
}
}
if (client_verify)
tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5);
tls_clean_record(conn);
return 1;
}
int tls13_send_hello_retry_request(TLS_CONNECT *conn)
{
int ret;
if(conn->verbose) tls_trace("send HelloRetryRequest\n");
if (conn->recordlen == 0) {
const uint8_t *legacy_session_id_echo = NULL;
size_t legacy_session_id_echo_len = 0;
int legacy_compress_meth = 0;
uint8_t exts[256];
uint8_t *pexts = exts;
size_t extslen = 0;
uint8_t cookie[256];
size_t cookie_len;
tls_record_set_protocol(conn->record, TLS_protocol_tls12);
memcpy(conn->server_random, TLS13_HELLO_RETRY_REQUEST_RANDOM, 32);
if (conn->session_id_len) {
legacy_session_id_echo = conn->session_id;
legacy_session_id_echo_len = conn->session_id_len;
}
// exts in HRR
// * supported_versions
// * key_share
// * [cookie]
// supported_versions
if (tls13_server_supported_versions_ext_to_bytes(
TLS_protocol_tls13, &pexts, &extslen) != 1) {
error_print();
return -1;
}
// key_share
if (tls13_key_share_hello_retry_request_ext_to_bytes(
conn->key_exchange_group, &pexts, &extslen) != 1) {
error_print();
return -1;
}
// cookie
if (conn->cookie) {
// TODO: cookie = {ClientHello}
if (tls13_cookie_generate(&conn->ctx->cookie_key, NULL, 0,
cookie, &cookie_len) != 1) {
error_print();
return -1;
}
if (tls13_cookie_ext_to_bytes(
cookie, sizeof(cookie), &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
if (tls13_record_set_handshake_hello_retry_request(
conn->record, &conn->recordlen,
TLS_protocol_tls12, conn->server_random,
legacy_session_id_echo, legacy_session_id_echo_len,
conn->cipher_suite, legacy_compress_meth, exts, extslen) != 1) {
error_print();
return -1;
}
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;
int client_verify = 0;
// ClientHello1
int _legacy_version;
const uint8_t *_random;
const uint8_t *_legacy_session_id;
size_t _legacy_session_id_len;
const uint8_t *_cipher_suites;
size_t _cipher_suites_len;
const uint8_t *_exts;
size_t _extslen;
// ClientHello2
int legacy_version;
const uint8_t *random;
const uint8_t *legacy_session_id;
size_t legacy_session_id_len;
const uint8_t *cipher_suites;
size_t cipher_suites_len;
const uint8_t *exts;
size_t extslen;
// Extensions
const uint8_t *key_share = NULL;
size_t key_share_len;
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;
if(conn->verbose) 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
&& tls_record_protocol(record) != TLS_protocol_tls12) {
error_print();
tls13_send_alert(conn, TLS_alert_protocol_version);
return -1;
}
if ((ret = tls_record_get_handshake_client_hello(conn->record,
&legacy_version, &random, &legacy_session_id, &legacy_session_id_len,
&cipher_suites, &cipher_suites_len, &exts, &extslen)) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls13_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
if (legacy_version != TLS_protocol_tls12) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
// ClientHello1
if (tls_record_get_handshake_client_hello(conn->plain_record,
&_legacy_version, &_random, &_legacy_session_id, &_legacy_session_id_len,
&_cipher_suites, &_cipher_suites_len, &_exts, &_extslen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
}
if (legacy_version != _legacy_version
|| legacy_session_id_len != _legacy_session_id_len
|| memcmp(legacy_session_id, _legacy_session_id, _legacy_session_id_len) != 0
|| cipher_suites_len != _cipher_suites_len
|| memcmp(cipher_suites, _cipher_suites, _cipher_suites_len) != 0) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
// client random, should send the same random
if (memcmp(random, conn->client_random, 32) != 0) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
// update client_server
memcpy(conn->client_random, random, 32);
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;
if(conn->verbose) tls_trace("send ServerHello\n");
if (conn->recordlen == 0) {
uint8_t exts[256];// 256=> 需要的长度
uint8_t *pexts = exts;
size_t extslen = 0;
tls_record_set_protocol(conn->record, TLS_protocol_tls12);
// server_random
if (tls13_random_generate(conn->server_random) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_internal_error);
return -1;
}
// exts in SH
// * supported_versions
// * key_share
// * pre_shared_key
// supported_versions
if (tls13_server_supported_versions_ext_to_bytes(
conn->protocol, &pexts, &extslen) != 1) {
error_print();
return -1;
}
// key_share
if (conn->key_exchange_modes & (TLS_KE_CERT_DHE|TLS_KE_PSK_DHE)) {
int curve_oid;
if (!conn->key_exchange_group) {
error_print();
return -1;
}
if ((curve_oid = tls_named_curve_oid(conn->key_exchange_group)) == OID_undef) {
error_print();
return -1;
}
if (x509_key_generate(&conn->key_exchanges[0],
OID_ec_public_key, &curve_oid, sizeof(curve_oid)) != 1) {
error_print();
return -1;
}
conn->key_exchange_idx = 0;
conn->key_exchanges_cnt = 1;
if (tls13_key_share_server_hello_ext_to_bytes(
&conn->key_exchanges[0], &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// pre_shared_key
if (conn->selected_psk_identity) {
if (tls13_server_pre_shared_key_ext_to_bytes(
conn->selected_psk_identity, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
if (tls_record_set_handshake_server_hello(conn->record, &conn->recordlen,
TLS_protocol_tls12, conn->server_random,
conn->session_id, conn->session_id_len,
conn->cipher_suite, exts, extslen) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) {
error_print();
return -1;
}
if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ServerHello", &conn->dgst_ctx);
if (tls13_generate_handshake_secrets(conn) != 1) {
error_print();
return -1;
}
tls13_generate_master_secret(conn);
if (tls13_generate_server_handshake_keys(conn) != 1) {
error_print();
return -1;
}
if (!conn->early_data) {
if (tls13_generate_client_handshake_keys(conn) != 1) {
error_print();
return -1;
}
}
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
if (conn->ctx->cacertslen) {
tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5);
}
tls_clean_record(conn);
return 1;
}
int tls13_send_alert(TLS_CONNECT *conn, int alert)
{
int ret;
size_t padding_len;
if(conn->verbose) tls_trace("send {Alert}\n");
if (conn->recordlen == 0) {
tls_record_set_protocol(conn->plain_record, TLS_protocol_tls12);
tls_record_set_alert(conn->plain_record, &conn->plain_recordlen, TLS_alert_level_fatal, alert);
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
switch (conn->handshake_state) {
case TLS_state_client_hello:
case TLS_state_server_hello:
case TLS_state_hello_retry_request:
memcpy(conn->record, conn->plain_record, conn->plain_recordlen);
conn->recordlen = conn->plain_recordlen;
break;
default:
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(conn->cipher_suite, &conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
}
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
tls_clean_record(conn);
return 1;
}
int tls13_send_encrypted_extensions(TLS_CONNECT *conn)
{
int ret;
if(conn->verbose) tls_trace("send {EncryptedExtensions}\n");
if (conn->recordlen == 0) {
uint8_t exts[256];
uint8_t *pexts = exts;
size_t extslen = 0;
size_t padding_len;
tls_record_set_protocol(conn->plain_record, TLS_protocol_tls12);
// Exts in EE (see RFC 8446 page 37)
// * supported_groups
// * server_name
// * early_data
// * application_layer_protocol_negotiation
// * use_srtp
// * client_certificate_type
// * server_certificate_type
// * max_fragment_length
// * heartbeat
// * record_size_limit (RFC 8449)
// supported_groups
if (conn->key_exchange_modes & (TLS_KE_CERT_DHE|TLS_KE_PSK_DHE)) {
if (tls_supported_groups_ext_to_bytes(conn->ctx->supported_groups,
conn->ctx->supported_groups_cnt, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// server_name
if (conn->server_name) {
if (tls_ext_to_bytes(TLS_extension_server_name, NULL, 0, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// early_data
// ClientHello.early_data
// PSK_DHE or PSK
// no HelloRetryRequest
if (conn->early_data) {
if (tls_ext_to_bytes(TLS_extension_early_data, NULL, 0, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// application_layer_protocol_negotiation
if (conn->alpn_selected) {
if (tls_application_layer_protocol_negotiation_selected_ext_to_bytes(
conn->alpn_selected, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
if (tls13_record_set_handshake_encrypted_extensions(
conn->plain_record, &conn->plain_recordlen,
exts, extslen) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5);
if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "EncryptedExtensions", &conn->dgst_ctx);
tls13_padding_len_rand(&padding_len);
//format_print(stderr, 0, 0, "server_seq_num: "PRIu64"\n", GETU64(conn->server_seq_num));
if (tls13_record_encrypt(conn->cipher_suite, &conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
if (conn->ctx->cacertslen) {
tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5);
}
tls_clean_record(conn);
return 1;
}
int tls13_send_certificate_request(TLS_CONNECT *conn)
{
int ret;
if(conn->verbose) tls_trace("send {CertificateRequest*}\n");
if (conn->recordlen == 0) {
const uint8_t *request_context = NULL;
size_t request_context_len = 0;
uint8_t exts[256];
uint8_t *pexts = exts;
size_t extslen = 0;
size_t padding_len;
// exts in CR (from RFC 8446 page 37)
// * signature_algorithms
// * signature_algorithms_cert
// * certificate_authorities
// * oid_filters
// * status_request
// * signed_certificate_timestamp
// signature_algorithms
if (!conn->ctx->signature_algorithms_cnt) {
error_print();
return -1;
}
// subset of ClientHello.signature_algorithms
if (tls_signature_algorithms_ext_to_bytes(
conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt,
&pexts, &extslen) != 1) {
error_print();
return -1;
}
// signature_algorithms_cert, only when ClientHello.signature_algorithms_cert
if (conn->signature_algorithms_cert) {
if (tls13_signature_algorithms_cert_ext_to_bytes(
conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// certificate_authorities 不应该默认发送吗?
conn->certificate_authorities = 1;
// certificate_authorities
if (conn->certificate_authorities) {
if (tls13_certificate_authorities_ext_to_bytes(
conn->ctx->ca_names, conn->ctx->ca_names_len, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// oid_filters
if (conn->oid_filters) {
if (tls13_oid_filters_ext_to_bytes(
conn->ctx->oid_filters, conn->ctx->oid_filters_len, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// status_request
if (conn->status_request) {
if (tls_ext_to_bytes(TLS_extension_status_request, NULL, 0, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// signed_certificate_timestamp
if (conn->signed_certificate_timestamp) {
if (tls_ext_to_bytes(TLS_extension_signed_certificate_timestamp, NULL, 0, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
if (tls13_record_set_handshake_certificate_request(
conn->plain_record, &conn->plain_recordlen,
request_context, request_context_len, exts, extslen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_internal_error);
return -1;
}
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "after CertificateRequest", &conn->dgst_ctx);
//format_print(stderr, 0, 0, "server_seq_num: "PRIu64"\n", GETU64(conn->server_seq_num));
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(conn->cipher_suite, &conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_internal_error);
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
return 1;
}
int tls13_send_server_certificate(TLS_CONNECT *conn)
{
int ret;
if(conn->verbose) tls_trace("send server {Certificate}\n");
if (conn->recordlen == 0) {
const uint8_t *request_context = NULL;
size_t request_context_len = 0;
const uint8_t *entity_status_request_ocsp_response = NULL;
size_t entity_status_request_ocsp_response_len = 0;
const uint8_t *entity_signed_certificate_timestamp = NULL;
size_t entity_signed_certificate_timestamp_len = 0;
size_t padding_len;
// status_request
if (conn->status_request) {
entity_status_request_ocsp_response = conn->status_request_ocsp_response;
entity_status_request_ocsp_response_len = conn->status_request_ocsp_response_len;
}
// if ClientHello.status_request, CertificateRequest.status_request = 1
// signed_certificate_timestamp
if (conn->signed_certificate_timestamp) {
entity_signed_certificate_timestamp = conn->signed_certificate_timestamp_list;
entity_signed_certificate_timestamp_len = conn->signed_certificate_timestamp_list_len;
}
// if ClientHello.signed_certificate_timestamp, CertificateRequest.signed_certificate_timestamp = 1
if (tls13_record_set_handshake_certificate(conn->plain_record, &conn->plain_recordlen,
request_context, request_context_len,
conn->cert_chain, conn->cert_chain_len,
entity_status_request_ocsp_response, entity_status_request_ocsp_response_len,
entity_signed_certificate_timestamp, entity_signed_certificate_timestamp_len) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_internal_error);
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ServerCertificate", &conn->dgst_ctx);
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(conn->cipher_suite, &conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
return 1;
}
int tls13_send_server_certificate_verify(TLS_CONNECT *conn)
{
int ret;
if(conn->verbose) tls_trace("send server {CertificateVerify}\n");
if (conn->recordlen == 0) {
X509_KEY *sign_key = &conn->ctx->x509_keys[conn->cert_chain_idx - 1];
uint8_t sig[SM2_MAX_SIGNATURE_SIZE];
size_t siglen;
size_t padding_len;
if (tls13_sign_certificate_verify(TLS_server_mode, conn->sig_alg,
sign_key, &conn->dgst_ctx, sig, &siglen) != 1) {
error_print();
return -1;
}
if (tls13_record_set_handshake_certificate_verify(
conn->plain_record, &conn->plain_recordlen,
conn->sig_alg, sig, siglen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_internal_error);
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(conn->cipher_suite, &conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
return 1;
}
int tls13_send_server_finished(TLS_CONNECT *conn)
{
int ret;
size_t padding_len;
if(conn->verbose) tls_trace("send server {Finished}\n");
if (conn->recordlen == 0) {
uint8_t verify_data[64];
size_t verify_data_len;
// compute server verify_data before digest_update()
tls13_compute_verify_data(conn->server_handshake_traffic_secret,
&conn->dgst_ctx, verify_data, &verify_data_len);
if (tls13_record_set_handshake_finished(conn->plain_record, &conn->plain_recordlen,
verify_data, verify_data_len) != 1) {
error_print();
return -1;
}
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "ServerFinished", &conn->dgst_ctx);
//format_print(stderr, 0, 0, "server_seq_num: "PRIu64"\n", GETU64(conn->server_seq_num));
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(conn->cipher_suite, &conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
tls13_generate_application_secrets(conn);
tls13_generate_server_application_keys(conn);
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
conn->record_offset = 0;
conn->recordlen = 0;
return 1;
}
int tls13_recv_client_certificate(TLS_CONNECT *conn)
{
int ret;
const uint8_t *request_context;
size_t request_context_len;
const uint8_t *status_request_ocsp_response = NULL;
size_t status_request_ocsp_response_len = 0;
const uint8_t *signed_certificate_timestamp = NULL;
size_t signed_certificate_timestamp_len;
const uint8_t *cert;
size_t certlen;
const int *signature_algorithms_cert = NULL;
size_t signature_algorithms_cert_cnt = 0;
const uint8_t *ca_names = NULL;
size_t ca_names_len = 0;
const uint8_t *oid_filters = NULL;
size_t oid_filters_len = 0;
int verify_result = X509_verify_ok;
if(conn->verbose) tls_trace("recv client {Certificate*}\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_print(stderr, 0, 0, "client_seq_num: "PRIu64"\n", GETU64(conn->client_seq_num));
if (tls13_record_decrypt(conn->cipher_suite, &conn->client_write_key, conn->client_write_iv,
conn->client_seq_num, conn->record, conn->recordlen,
conn->plain_record, &conn->plain_recordlen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
tls_seq_num_incr(conn->client_seq_num);
if(conn->verbose) tls13_record_trace(stderr, conn->plain_record, conn->plain_recordlen, 0, 0);
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "after client Certificate", &conn->dgst_ctx);
if ((ret = tls13_record_get_handshake_certificate(conn->plain_record,
&request_context, &request_context_len,
conn->peer_cert_chain, &conn->peer_cert_chain_len, sizeof(conn->peer_cert_chain),
&status_request_ocsp_response, &status_request_ocsp_response_len,
&signed_certificate_timestamp, &signed_certificate_timestamp_len)) < 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls13_send_alert(conn, TLS_alert_unexpected_message);
return 0;
}
if (request_context) {
error_print();
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (!conn->peer_cert_chain_len) {
if (!conn->ctx->client_certificate_optional) {
error_print();
tls13_send_alert(conn, TLS_alert_certificate_required);
return -1;
}
return 0;
}
// client cert_chain match CertificateRequest extensions
if (conn->signature_algorithms_cert) {
signature_algorithms_cert = conn->ctx->signature_algorithms;
signature_algorithms_cert_cnt = conn->ctx->signature_algorithms_cnt;
}
if (conn->certificate_authorities) {
ca_names = conn->ctx->ca_names;
ca_names_len = conn->ctx->ca_names_len;
}
if (conn->oid_filters) {
oid_filters = conn->ctx->oid_filters;
oid_filters_len = conn->ctx->oid_filters_len;
}
// verify client cert_chain
ret = tls_cert_chain_verify(
conn->protocol, X509_cert_chain_client, conn->cipher_suite,
1,
conn->peer_cert_chain, conn->peer_cert_chain_len,
conn->ctx->cacerts, conn->ctx->cacertslen,
NULL, 0,
status_request_ocsp_response, status_request_ocsp_response_len,
conn->ctx->verify_depth,
NULL, 0,
conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt,
signature_algorithms_cert, signature_algorithms_cert_cnt,
ca_names, ca_names_len,
oid_filters, oid_filters_len,
NULL, 0,
&verify_result, NULL);
if (ret < 0) {
error_print();
conn->verify_result = verify_result;
tls13_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
if (ret == 0) {
error_print();
conn->verify_result = verify_result;
if (verify_result == X509_verify_err_crl
|| verify_result == X509_verify_err_ocsp) {
tls13_send_alert(conn, TLS_alert_certificate_revoked);
} else {
tls13_send_alert(conn, TLS_alert_bad_certificate);
}
return -1;
}
conn->verify_result = verify_result;
// signed_certificate_timestamp
if (signed_certificate_timestamp) {
if (x509_certs_get_cert_by_index(conn->peer_cert_chain,
conn->peer_cert_chain_len, 0, &cert, &certlen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
if (tls13_signed_certificate_timestamp_verify(
signed_certificate_timestamp, signed_certificate_timestamp_len,
SCT_log_entry_type_x509_entry, NULL, cert, certlen,
conn->ctx->ct_logs, conn->ctx->ct_logs_cnt,
conn->ctx->ct_at_least) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
}
return 1;
}
int tls13_recv_client_finished(TLS_CONNECT *conn)
{
int ret;
// Finished
uint8_t local_verify_data[64];
size_t local_verify_data_len;
const uint8_t *verify_data;
size_t verify_data_len;
if(conn->verbose) tls_trace("recv client {Finished}\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
if (tls_record_protocol(conn->record) != TLS_protocol_tls12) {
error_print();
tls13_send_alert(conn, TLS_alert_protocol_version);
return -1;
}
//format_print(stderr, 0, 0, "client_seq_num: "PRIu64"\n", GETU64(conn->client_seq_num));
if (tls13_record_decrypt(conn->cipher_suite, &conn->client_write_key, conn->client_write_iv,
conn->client_seq_num, conn->record, conn->recordlen,
conn->plain_record, &conn->plain_recordlen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
tls_seq_num_incr(conn->client_seq_num);
if(conn->verbose) tls13_record_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;
}
if(conn->verbose) tls_handshake_digest_print(stderr, 0, 0, "before ClientFinished", &conn->dgst_ctx);
if (tls13_compute_verify_data(conn->client_handshake_traffic_secret,
&conn->dgst_ctx, local_verify_data, &local_verify_data_len) != 1) {
error_print();
return -1;
}
// 当客户端发送了Certificate的时候这个验证是不对的
// 服务器多发送了CertificateRequest
// 客户端多发送了 Certificate, CertificateVerify
if (local_verify_data_len != verify_data_len
|| memcmp(local_verify_data, verify_data, verify_data_len) != 0) {
error_print();
tls13_send_alert(conn, TLS_alert_decrypt_error);
return -1;
}
tls13_generate_client_application_keys(conn);
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
return 1;
}
int tls13_send_early_data(TLS_CONNECT *conn)
{
if(conn->verbose) tls_trace("send EarlyData\n");
if (!conn->early_data) {
error_print();
return -1;
}
if (!conn->early_data_len) {
error_print();
return -1;
}
while (conn->early_data_offset < conn->early_data_len) {
int ret;
if (conn->recordlen == 0) {
uint8_t plain_record[TLS_MAX_RECORD_SIZE];
size_t plain_recordlen;
size_t datalen;
size_t padding_len;
datalen = conn->early_data_len - conn->early_data_offset;
if (datalen > TLS_MAX_PLAINTEXT_SIZE) {
datalen = TLS_MAX_PLAINTEXT_SIZE;
}
tls13_padding_len_rand(&padding_len);
if (tls_record_set_application_data(plain_record, &plain_recordlen,
conn->early_data_buf + conn->early_data_offset, datalen) != 1) {
error_print();
return -1;
}
if (tls13_record_encrypt(conn->cipher_suite, &conn->client_write_key, conn->client_write_iv,
conn->client_seq_num, plain_record, plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->client_seq_num);
conn->record_offset = 0;
conn->sentlen = datalen;
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret == TLS_ERROR_SEND_AGAIN) {
return ret;
}
error_print();
return -1;
}
conn->early_data_offset += conn->sentlen;
conn->record_offset = 0;
conn->recordlen = 0;
}
conn->record_offset = 0;
conn->recordlen = 0;
return 1;
}
int tls13_send_client_key_update(TLS_CONNECT *conn, int request_update)
{
int ret;
if (conn->recordlen == 0) {
size_t padding_len = 0;
if(conn->verbose) tls_trace("send client {KeyUpdate}\n");
if (tls13_record_set_handshake_key_update(conn->plain_record, &conn->plain_recordlen,
request_update) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(conn->cipher_suite, &conn->client_write_key, conn->client_write_iv,
conn->client_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
return -1;
}
// 这个很重要啊但是record_encrypt没有设置这个值这是很奇怪的
// xxxxxxxx
conn->record_offset = 0;
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
tls13_update_client_application_secret(conn);
tls13_generate_client_application_keys(conn);
conn->key_update = 0;
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN && ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
}
if (ret == 1) {
// 首先我们在发送数据的时候应该根据offset是否已经达到末尾来判断数据是否完全发送
// 其次在记录已经完全发送之后应该自动的清空recordlen, offset这个数据
conn->record_offset = 0;
conn->recordlen = 0;
}
return ret;
}
int tls13_send_server_key_update(TLS_CONNECT *conn, int request_update)
{
int ret;
if (conn->recordlen == 0) {
size_t padding_len = 0;
if(conn->verbose) tls_trace("send server {KeyUpdate}\n");
if (tls13_record_set_handshake_key_update(conn->plain_record, &conn->plain_recordlen,
request_update) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(conn->cipher_suite, &conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
conn->record_offset = 0;
tls13_update_server_application_secret(conn);
tls13_generate_server_application_keys(conn);
conn->key_update = 0;
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN && ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
}
if (ret == 1) {
// 首先我们在发送数据的时候应该根据offset是否已经达到末尾来判断数据是否完全发送
// 其次在记录已经完全发送之后应该自动的清空recordlen, offset这个数据
conn->record_offset = 0;
conn->recordlen = 0;
}
return ret;
}
int tls13_do_client_handshake(TLS_CONNECT *conn)
{
int ret;
int next_state;
switch (conn->handshake_state) {
case TLS_state_hello_retry_request:
case TLS_state_client_hello_again:
case TLS_state_server_hello:
case TLS_state_encrypted_extensions:
if (conn->early_data && conn->early_data_offset < conn->early_data_len) {
if(conn->verbose) tls_trace("send EarlyData\n");
if (tls13_send_early_data(conn) != 1) {
error_print();
return -1;
}
}
break;
}
switch (conn->handshake_state) {
case TLS_state_client_hello:
ret = tls13_send_client_hello(conn);
next_state = TLS_state_hello_retry_request;
break;
case TLS_state_hello_retry_request: // optional
ret = tls13_recv_hello_retry_request(conn);
if (conn->hello_retry_request)
next_state = TLS_state_client_hello_again;
else next_state = TLS_state_server_hello;
break;
case TLS_state_client_hello_again:
ret = tls13_send_client_hello_again(conn);
next_state = TLS_state_server_hello;
break;
case TLS_state_server_hello:
ret = tls13_recv_server_hello(conn);
if (tls13_ctx_accept_change_cipher_spec(conn->ctx))
next_state = TLS_state_server_change_cipher_spec;
else next_state = TLS_state_encrypted_extensions;
break;
case TLS_state_server_change_cipher_spec:
ret = tls13_recv_change_cipher_spec_if_present(conn);
next_state = TLS_state_encrypted_extensions;
break;
case TLS_state_encrypted_extensions:
ret = tls13_recv_encrypted_extensions(conn);
next_state = TLS_state_certificate_request;
break;
case TLS_state_certificate_request: // optional
ret = tls13_recv_certificate_request(conn);
if (conn->key_exchange_modes == TLS_KE_CERT_DHE)
next_state = TLS_state_server_certificate;
else next_state = TLS_state_server_finished;
break;
case TLS_state_server_certificate:
ret = tls13_recv_server_certificate(conn);
next_state = TLS_state_certificate_verify;
break;
case TLS_state_certificate_verify:
ret = tls13_recv_server_certificate_verify(conn);
next_state = TLS_state_server_finished;
break;
case TLS_state_server_finished:
ret = tls13_recv_server_finished(conn);
if (conn->early_data)
next_state = TLS_state_end_of_early_data;
else if (conn->certificate_request)
next_state = TLS_state_client_certificate;
else next_state = TLS_state_client_change_cipher_spec;
break;
case TLS_state_end_of_early_data:
ret = tls13_send_end_of_early_data(conn);
next_state = TLS_state_client_change_cipher_spec;
break;
case TLS_state_client_certificate:
// if client has no (proper) certificate
// client will send {Certificate} with empty certificate_list
// but will not send {CertificateVerify}
ret = tls13_send_client_certificate(conn);
if (conn->cert_chain)
next_state = TLS_state_client_certificate_verify;
else next_state = TLS_state_client_change_cipher_spec;
break;
case TLS_state_client_certificate_verify:
ret = tls13_send_client_certificate_verify(conn);
next_state = TLS_state_client_change_cipher_spec;
break;
case TLS_state_client_change_cipher_spec:
if (tls13_ctx_change_cipher_spec_compat(conn->ctx))
ret = tls13_send_change_cipher_spec(conn);
else ret = 1;
next_state = TLS_state_client_finished;
break;
case TLS_state_client_finished:
ret = tls13_send_client_finished(conn);
next_state = TLS_state_handshake_over;
break;
default:
error_print();
return -1;
}
if (ret < 0) {
if (ret == TLS_ERROR_RECV_AGAIN || ret == TLS_ERROR_SEND_AGAIN) {
return ret;
} else {
error_print();
return ret;
}
}
conn->handshake_state = next_state;
// ret == 0 means this step is bypassed
if (ret == 1) {
tls_clean_record(conn);
}
return 1;
}
int tls13_do_server_handshake(TLS_CONNECT *conn)
{
int ret;
int state = conn->handshake_state;
int next_state;
switch (conn->handshake_state) {
case TLS_state_client_hello:
ret = tls13_recv_client_hello(conn);
if (conn->early_data)
next_state = TLS_state_early_data;
else if (conn->hello_retry_request)
next_state = TLS_state_hello_retry_request;
else next_state = TLS_state_server_hello;
break;
case TLS_state_early_data:
ret = tls13_recv_early_data(conn);
next_state = TLS_state_server_hello;
break;
case TLS_state_hello_retry_request:
ret = tls13_send_hello_retry_request(conn);
next_state = TLS_state_client_hello_again;
break;
case TLS_state_client_hello_again:
ret = tls13_recv_client_hello_again(conn);
next_state = TLS_state_server_hello;
break;
case TLS_state_server_hello:
ret = tls13_send_server_hello(conn);
if (tls13_ctx_change_cipher_spec_compat(conn->ctx))
next_state = TLS_state_server_change_cipher_spec;
else next_state = TLS_state_encrypted_extensions;
break;
case TLS_state_server_change_cipher_spec:
ret = tls13_send_change_cipher_spec(conn);
next_state = TLS_state_encrypted_extensions;
break;
case TLS_state_encrypted_extensions:
ret = tls13_send_encrypted_extensions(conn);
if (conn->certificate_request)
next_state = TLS_state_certificate_request;
else if (conn->key_exchange_modes == TLS_KE_CERT_DHE)
next_state = TLS_state_server_certificate;
else next_state = TLS_state_server_finished;
break;
case TLS_state_certificate_request:
ret = tls13_send_certificate_request(conn);
if (conn->key_exchange_modes == TLS_KE_CERT_DHE)
next_state = TLS_state_server_certificate;
else next_state = TLS_state_server_finished;
break;
case TLS_state_server_certificate:
ret = tls13_send_server_certificate(conn);
next_state = TLS_state_certificate_verify;
break;
case TLS_state_certificate_verify:
ret = tls13_send_server_certificate_verify(conn);
next_state = TLS_state_server_finished;
break;
case TLS_state_server_finished:
ret = tls13_send_server_finished(conn);
if (conn->early_data)
next_state = TLS_state_end_of_early_data;
else if (conn->certificate_request)
next_state = TLS_state_client_certificate;
else next_state = TLS_state_client_change_cipher_spec;
break;
case TLS_state_end_of_early_data:
ret = tls13_recv_end_of_early_data(conn);
next_state = TLS_state_client_change_cipher_spec;
break;
case TLS_state_client_certificate:
ret = tls13_recv_client_certificate(conn);
if (ret == 0) // 客户端提供了一个空的Certificate消息
next_state = TLS_state_client_change_cipher_spec;
else next_state = TLS_state_client_certificate_verify;
break;
case TLS_state_client_certificate_verify:
ret = tls13_recv_client_certificate_verify(conn);
next_state = TLS_state_client_change_cipher_spec;
break;
case TLS_state_client_change_cipher_spec:
if (tls13_ctx_accept_change_cipher_spec(conn->ctx))
ret = tls13_recv_change_cipher_spec_if_present(conn);
else ret = 1;
next_state = TLS_state_client_finished;
break;
case TLS_state_client_finished:
ret = tls13_recv_client_finished(conn);
if (conn->new_session_ticket)
next_state = TLS_state_new_session_ticket;
else next_state = TLS_state_handshake_over;
break;
case TLS_state_new_session_ticket:
if (conn->new_session_ticket) {
ret = tls13_send_new_session_ticket(conn);
next_state = TLS_state_new_session_ticket;
} else {
ret = 1;
next_state = TLS_state_handshake_over;
}
break;
default:
error_print();
return -1;
}
if (ret < 0) {
if (ret == TLS_ERROR_RECV_AGAIN || ret == TLS_ERROR_SEND_AGAIN) {
return ret;
} else {
error_print();
return ret;
}
}
conn->handshake_state = next_state;
if (!(state == TLS_state_client_change_cipher_spec && ret == 0)) {
tls_clean_record(conn);
}
return 1;
}
int tls13_client_handshake(TLS_CONNECT *conn)
{
int ret;
while (conn->handshake_state != TLS_state_handshake_over) {
ret = tls13_do_client_handshake(conn);
if (ret != 1) {
if (ret != TLS_ERROR_RECV_AGAIN && ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
}
// TODO: cleanup conn?
return 1;
}
int tls13_server_handshake(TLS_CONNECT *conn)
{
int ret;
while (conn->handshake_state != TLS_state_handshake_over) {
ret = tls13_do_server_handshake(conn);
if (ret != 1) {
if (ret != TLS_ERROR_RECV_AGAIN && ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
}
// TODO: cleanup conn?
return 1;
}
int tls13_do_connect(TLS_CONNECT *conn)
{
int ret;
if (!conn || !conn->is_client) {
error_print();
return -1;
}
if (conn->handshake_state == TLS_state_handshake_over) {
return 1;
}
if (conn->handshake_state == TLS_state_handshake_init) {
conn->handshake_state = TLS_state_client_hello;
}
ret = tls13_client_handshake(conn);
if (ret == 1) {
conn->handshake_state = TLS_state_handshake_over;
return 1;
}
if (ret == TLS_ERROR_RECV_AGAIN || ret == TLS_ERROR_SEND_AGAIN) {
return ret;
}
error_print();
return -1;
}
int tls13_do_accept(TLS_CONNECT *conn)
{
int ret;
if (!conn || conn->is_client) {
error_print();
return -1;
}
if (conn->handshake_state == TLS_state_handshake_over) {
return 1;
}
if (conn->handshake_state == TLS_state_handshake_init) {
conn->handshake_state = TLS_state_client_hello;
}
ret = tls13_server_handshake(conn);
if (ret == 1) {
conn->handshake_state = TLS_state_handshake_over;
return 1;
}
if (ret == TLS_ERROR_RECV_AGAIN || ret == TLS_ERROR_SEND_AGAIN) {
return ret;
}
error_print();
return -1;
}