mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-06-29 01:03:38 +08:00
9299 lines
242 KiB
C
9299 lines
242 KiB
C
/*
|
||
* 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,这个数据有可能被修改
|
||
// 并且如果确定了发送EarlyData,cipher_suite就确定了,不应该再备份了
|
||
|
||
// 由于服务器可能拒绝EarlyData,并且不选择第一个PSK
|
||
// 那么可能导致最终的cipher_suite和客户端计算EarlyData不同的值
|
||
// 这就导致客户端必须重新计算ClientHello的digest
|
||
// 因此我们还是保存ClientHello,而不是立即就计算digest
|
||
|
||
memcpy(conn->plain_record, conn->record, conn->recordlen);
|
||
conn->plain_recordlen = conn->recordlen;
|
||
}
|
||
|
||
if ((ret = tls_send_record(conn)) != 1) {
|
||
if (ret != TLS_ERROR_SEND_AGAIN) {
|
||
error_print();
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
tls_clean_record(conn);
|
||
return 1;
|
||
}
|
||
|
||
/*
|
||
recv HelloRetryRequest:
|
||
* set conn->protocol
|
||
* set conn->cipher_suite, conn->cipher, conn->digest
|
||
* set conn->key_exchange_group
|
||
* set conn->dgst_ctx <= ClientHello, HelloRetryRequest, ClientHello2
|
||
|
||
recv ServerHello after HelloRetryRequest:
|
||
* check ServerHello.protocol == conn->protocol
|
||
* check ServerHello.cipher_suite == conn->cipher_suite
|
||
* check ServerHello.key_share.group == conn->key_exchange_group
|
||
* conn->dgst_ctx <= ServerHello
|
||
|
||
recv ServerHello without HelloRetryRequest:
|
||
* set conn->protocol
|
||
* set conn->cipher_suite, conn->cipher, conn->digest
|
||
* set conn->key_exchange_group
|
||
* set conn->dgst_ctx <= ClientHello
|
||
*/
|
||
|
||
int tls13_recv_hello_retry_request(TLS_CONNECT *conn)
|
||
{
|
||
int ret;
|
||
|
||
// handshake
|
||
int handshake_type;
|
||
const uint8_t *handshake_data;
|
||
size_t handshake_datalen;
|
||
|
||
// HelloRetryRequest
|
||
int legacy_version;
|
||
const uint8_t *random;
|
||
const uint8_t *legacy_session_id_echo;
|
||
size_t legacy_session_id_echo_len;
|
||
int cipher_suite;
|
||
int legacy_compress_meth;
|
||
const uint8_t *exts;
|
||
size_t extslen;
|
||
|
||
// extensions
|
||
const uint8_t *supported_versions = NULL;
|
||
size_t supported_versions_len = 0;
|
||
const uint8_t *key_share = NULL;
|
||
size_t key_share_len = 0;
|
||
const uint8_t *cookie = NULL;
|
||
size_t cookie_len = 0;
|
||
|
||
int selected_version;
|
||
int key_exchange_group;
|
||
|
||
if(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;
|
||
}
|