Files
GmSSL/src/tls13.c
Zhi Guan 0d1acec6df Update TLS 1.3 handshake
Working on HelloRetryRequest, NewSessionTicket
2026-03-21 18:41:46 +08:00

6487 lines
167 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmssl/rand.h>
#include <gmssl/x509.h>
#include <gmssl/error.h>
#include <gmssl/sm2.h>
#include <gmssl/sm3.h>
#include <gmssl/sm4.h>
#include <gmssl/pem.h>
#include <gmssl/tls.h>
#include <gmssl/digest.h>
#include <gmssl/hmac.h>
#include <gmssl/hkdf.h>
#include <gmssl/mem.h>
static const int tls13_ciphers[] = { TLS_cipher_sm4_gcm_sm3 };
static size_t tls13_ciphers_count = sizeof(tls13_ciphers)/sizeof(int);
static int tls13_client_hello_exts[] = {
TLS_extension_supported_versions,
TLS_extension_padding,
};
#define TLS_state_hello_retry_request 111111
#define TLS_state_client_hello_again 12222
int tls13_cipher_suite_get(int cipher_suite, const BLOCK_CIPHER **cipher, const DIGEST **digest)
{
switch (cipher_suite) {
case TLS_cipher_sm4_gcm_sm3:
*digest = DIGEST_sm3();
*cipher = BLOCK_CIPHER_sm4();
break;
#if defined(ENABLE_AES) && defined(ENABLE_SHA2)
case TLS_cipher_aes_128_gcm_sha256:
*digest = DIGEST_sha256();
*cipher = BLOCK_CIPHER_aes128();
break;
#endif
default:
error_print();
return -1;
}
return 1;
}
int tls13_padding_len_rand(size_t *padding_len)
{
uint8_t val;
rand_bytes(&val, 1);
*padding_len = val % 128;
return 1;
}
int gcm_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *iv, size_t ivlen,
const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen,
uint8_t *out, size_t taglen, uint8_t *tag)
{
if (key->cipher == BLOCK_CIPHER_sm4()) {
if (sm4_gcm_encrypt(&(key->u.sm4_key), iv, ivlen, aad, aadlen, in, inlen, out, taglen, tag) != 1) {
error_print();
return -1;
}
// 避免在tls13.c中引入宏
#ifdef ENABLE_AES
} else if (key->cipher == BLOCK_CIPHER_aes128()) {
if (aes_gcm_encrypt(&(key->u.aes_key), iv, ivlen, aad, aadlen, in, inlen, out, taglen, tag) != 1) {
error_print();
return -1;
}
#endif
} else {
error_print();
return -1;
}
return 1;
}
int gcm_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *iv, size_t ivlen,
const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen,
const uint8_t *tag, size_t taglen, uint8_t *out)
{
if (key->cipher == BLOCK_CIPHER_sm4()) {
if (sm4_gcm_decrypt(&(key->u.sm4_key), iv, ivlen, aad, aadlen, in, inlen, tag, taglen, out) != 1) {
error_print();
return -1;
}
#ifdef ENABLE_AES
} else if (key->cipher == BLOCK_CIPHER_aes128()) {
if (aes_gcm_decrypt(&(key->u.aes_key), iv, ivlen, aad, aadlen, in, inlen, tag, taglen, out) != 1) {
error_print();
return -1;
}
#endif
} else {
error_print();
return -1;
}
return 1;
}
/*
struct {
opaque content[TLSPlaintext.length];
ContentType type;
uint8 zeros[length_of_padding];
} TLSInnerPlaintext;
struct {
ContentType opaque_type = application_data; // 23
ProtocolVersion legacy_record_version = 0x0303; // TLS v1.2
uint16 length;
opaque encrypted_record[TLSCiphertext.length];
} TLSCiphertext;
*/
int tls13_gcm_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
const uint8_t seq_num[8], int record_type,
const uint8_t *in, size_t inlen, size_t padding_len, // TLSInnerPlaintext.content
uint8_t *out, size_t *outlen) // TLSCiphertext.encrypted_record
{
uint8_t nonce[12];
uint8_t aad[5];
uint8_t *gmac;
uint8_t *mbuf = NULL; // FIXME: update gcm_encrypt API
size_t mlen, clen;
if (!(mbuf = malloc(inlen + 256))) {
error_print();
return -1;
}
// nonce = (zeros|seq_num) xor (iv)
nonce[0] = nonce[1] = nonce[2] = nonce[3] = 0;
memcpy(nonce + 4, seq_num, 8);
gmssl_memxor(nonce, nonce, iv, 12);
// TLSInnerPlaintext
memcpy(mbuf, in, inlen);
mbuf[inlen] = record_type;
memset(mbuf + inlen + 1, 0, padding_len);
mlen = inlen + 1 + padding_len;
clen = mlen + GHASH_SIZE;
// aad = TLSCiphertext header
aad[0] = TLS_record_application_data;
aad[1] = 0x03; //TLS_protocol_tls12_major;
aad[2] = 0x03; //TLS_protocol_tls12_minor;
aad[3] = (uint8_t)(clen >> 8);
aad[4] = (uint8_t)(clen);
gmac = out + mlen;
if (gcm_encrypt(key, nonce, sizeof(nonce), aad, sizeof(aad), mbuf, mlen, out, 16, gmac) != 1) {
error_print();
free(mbuf);
return -1;
}
*outlen = clen;
free(mbuf);
return 1;
}
int tls13_gcm_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
const uint8_t seq_num[8], const uint8_t *in, size_t inlen,
int *record_type, uint8_t *out, size_t *outlen)
{
uint8_t nonce[12];
uint8_t aad[5];
size_t mlen;
const uint8_t *gmac;
// nonce = (zeros|seq_num) xor (iv)
nonce[0] = nonce[1] = nonce[2] = nonce[3] = 0;
memcpy(nonce + 4, seq_num, 8);
gmssl_memxor(nonce, nonce, iv, 12);
// aad = TLSCiphertext header
aad[0] = TLS_record_application_data;
aad[1] = 0x03; //TLS_protocol_tls12_major;
aad[2] = 0x03; //TLS_protocol_tls12_minor;
aad[3] = (uint8_t)(inlen >> 8);
aad[4] = (uint8_t)(inlen);
if (inlen < GHASH_SIZE) {
error_print();
return -1;
}
mlen = inlen - GHASH_SIZE;
gmac = in + mlen;
if (gcm_decrypt(key, nonce, 12, aad, 5, in, mlen, gmac, GHASH_SIZE, out) != 1) {
error_print();
return -1;
}
// remove padding, get record_type
*record_type = 0;
while (mlen--) {
if (out[mlen] != 0) {
*record_type = out[mlen];
break;
}
}
*outlen = mlen;
if (!tls_record_type_name(*record_type)) {
error_print();
return -1;
}
return 1;
}
int tls13_record_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
const uint8_t seq_num[8], const uint8_t *record, size_t recordlen, size_t padding_len,
uint8_t *enced_record, size_t *enced_recordlen)
{
if (tls13_gcm_encrypt(key, iv,
seq_num, record[0], record + 5, recordlen - 5, padding_len,
enced_record + 5, enced_recordlen) != 1) {
error_print();
return -1;
}
// in tls1.3, type of encrypted records must be application_data
enced_record[0] = TLS_record_application_data;
enced_record[1] = 0x03; //TLS_protocol_tls12_major;
enced_record[2] = 0x03; //TLS_protocol_tls12_minor;
enced_record[3] = (uint8_t)((*enced_recordlen) >> 8);
enced_record[4] = (uint8_t)(*enced_recordlen);
(*enced_recordlen) += 5;
return 1;
}
int tls13_record_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
const uint8_t seq_num[8], const uint8_t *enced_record, size_t enced_recordlen,
uint8_t *record, size_t *recordlen)
{
int record_type;
if (tls13_gcm_decrypt(key, iv,
seq_num, enced_record + 5, enced_recordlen - 5,
&record_type, record + 5, recordlen) != 1) {
error_print();
return -1;
}
record[0] = record_type;
record[1] = 0x03; //TLS_protocol_tls12_major;
record[2] = 0x03; //TLS_protocol_tls12_minor;
record[3] = (uint8_t)((*recordlen) >> 8);
record[4] = (uint8_t)(*recordlen);
(*recordlen) += 5;
return 1;
}
int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t *sentlen)
{
const BLOCK_CIPHER_KEY *key;
const uint8_t *iv;
uint8_t *seq_num;
uint8_t *record = conn->record;
size_t recordlen;
size_t padding_len = 0; //FIXME: add random padding to conn
tls_trace("send {ApplicationData}\n");
if (conn->is_client) {
key = &conn->client_write_key;
iv = conn->client_write_iv;
seq_num = conn->client_seq_num;
} else {
key = &conn->server_write_key;
iv = conn->server_write_iv;
seq_num = conn->server_seq_num;
}
format_bytes(stderr, 0, 0, "send seq_num", seq_num, 8);
if (tls13_gcm_encrypt(key, iv,
seq_num, TLS_record_application_data, data, datalen, padding_len,
record + 5, &recordlen) != 1) {
error_print();
return -1;
}
record[0] = TLS_record_application_data;
record[1] = TLS_protocol_tls12 >> 8;
record[2] = TLS_protocol_tls12 & 0xff;
record[3] = (uint8_t)(recordlen >> 8);
record[4] = (uint8_t)(recordlen);
recordlen += 5;
tls_record_send(record, recordlen, conn->sock);
//tls_record_trace(stderr, record, tls_record_length(record), 0, 0);
tls_seq_num_incr(seq_num);
*sentlen = datalen;
return 1;
}
int tls13_do_recv(TLS_CONNECT *conn)
{
int ret;
const BLOCK_CIPHER_KEY *key;
const uint8_t *iv;
uint8_t *seq_num;
uint8_t *record = conn->record;
size_t recordlen;
int record_type;
if (conn->is_client) {
key = &conn->server_write_key;
iv = conn->server_write_iv;
seq_num = conn->server_seq_num;
} else {
key = &conn->client_write_key;
iv = conn->client_write_iv;
seq_num = conn->client_seq_num;
}
tls_trace("recv ApplicationData\n");
if ((ret = tls_record_recv(record, &recordlen, conn->sock)) != 1) {
if (ret < 0) error_print();
return ret;
}
tls_record_trace(stderr, record, recordlen, 0, 0);
// TODO: do we need to check record_type? record[0] != TLS_record_application_data
format_bytes(stderr, 0, 0, "recv seq_num", seq_num, 8);
if (tls13_gcm_decrypt(key, iv,
seq_num, record + 5, recordlen - 5,
&record_type, conn->databuf, &conn->datalen) != 1) {
error_print();
return -1;
}
conn->data = conn->databuf;
tls_seq_num_incr(seq_num);
tls_record_set_data(record, conn->data, conn->datalen);
//tls_trace("decrypt ApplicationData\n");
//tls_record_trace(stderr, record, tls_record_length(record), 0, 0);
if (record_type != TLS_record_application_data) {
error_print();
return -1;
}
return 1;
}
int tls13_recv(TLS_CONNECT *conn, uint8_t *out, size_t outlen, size_t *recvlen)
{
if (!conn || !out || !outlen || !recvlen) {
error_print();
return -1;
}
if (conn->datalen == 0) {
int ret;
if ((ret = tls13_do_recv(conn)) != 1) {
if (ret) error_print();
return ret;
}
}
*recvlen = outlen <= conn->datalen ? outlen : conn->datalen;
memcpy(out, conn->data, *recvlen);
conn->data += *recvlen;
conn->datalen -= *recvlen;
return 1;
}
/*
HKDF-Expand-Label(Secret, Label, Context, Length) =
HKDF-Expand(Secret, HkdfLabel, Length);
HkdfLabel = struct {
uint16 length = Length;
opaque label<7..255> = "tls13 " + Label;
opaque context<0..255> = Context; }
Derive-Secret(Secret, Label, Messages) =
HKDF-Expand-Label(Secret, Label, Hash(Messages), Hash.length)
*/
int tls13_hkdf_extract(const DIGEST *digest, const uint8_t salt[32], const uint8_t in[32], uint8_t out[32])
{
size_t dgstlen;
if (hkdf_extract(digest, salt, 32, in, 32, out, &dgstlen) != 1
|| dgstlen != 32) {
error_print();
return -1;
}
return 1;
}
int tls13_hkdf_expand_label(const DIGEST *digest, const uint8_t secret[32],
const char *label, const uint8_t *context, size_t context_len,
size_t outlen, uint8_t *out)
{
uint8_t label_len;
uint8_t hkdf_label[2 + 256 + 256];
uint8_t *p = hkdf_label;
size_t hkdf_label_len = 0;
label_len = (uint8_t)(strlen("tls13 ") + strlen(label)); //FIXME: check length < 255
tls_uint16_to_bytes((uint16_t)outlen, &p, &hkdf_label_len);
tls_uint8_to_bytes(label_len, &p, &hkdf_label_len);
tls_array_to_bytes((uint8_t *)"tls13 ", strlen("tls13 "), &p, &hkdf_label_len);
tls_array_to_bytes((uint8_t *)label, strlen(label), &p, &hkdf_label_len);
tls_uint8array_to_bytes(context, context_len, &p, &hkdf_label_len);
hkdf_expand(digest, secret, 32, hkdf_label, hkdf_label_len, outlen, out);
return 1;
}
int tls13_derive_secret(const uint8_t secret[32], const char *label, const DIGEST_CTX *dgst_ctx, uint8_t out[32])
{
DIGEST_CTX ctx = *dgst_ctx;
uint8_t dgst[64];
size_t dgstlen;
if (digest_finish(&ctx, dgst, &dgstlen) != 1
|| tls13_hkdf_expand_label(dgst_ctx->digest, secret, label, dgst, 32, dgstlen, out) != 1) {
error_print();
return -1;
}
return 1;
}
static const uint8_t TLS13_client_context_str_and_zero[] = "TLS 1.3, client CertificateVerify";
static const uint8_t TLS13_server_context_str_and_zero[] = "TLS 1.3, server CertificateVerify";
static size_t TLS13_client_context_str_and_zero_size = sizeof(TLS13_client_context_str_and_zero);
static size_t TLS13_server_context_str_and_zero_size = sizeof(TLS13_server_context_str_and_zero);
// 这个函数需要改为支持X509_KEY的版本
int tls13_sign_certificate_verify(int tls_mode,
const SM2_KEY *key, const char *signer_id, size_t signer_id_len,
const DIGEST_CTX *tbs_dgst_ctx,
uint8_t *sig, size_t *siglen)
{
SM2_SIGN_CTX sign_ctx;
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;
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;
}
dgst_ctx = *tbs_dgst_ctx;
digest_finish(&dgst_ctx, dgst, &dgstlen);
sm2_sign_init(&sign_ctx, key, signer_id, signer_id_len);
sm2_sign_update(&sign_ctx, prefix, 64);
sm2_sign_update(&sign_ctx, context_str_and_zero, context_str_and_zero_len);
sm2_sign_update(&sign_ctx, dgst, dgstlen);
sm2_sign_finish(&sign_ctx, sig, siglen);
gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx));
return 1;
}
//同上
int tls13_verify_certificate_verify(int tls_mode,
const X509_KEY *public_key, const char *signer_id, size_t signer_id_len,
const DIGEST_CTX *tbs_dgst_ctx, const uint8_t *sig, size_t siglen)
{
int ret;
SM2_VERIFY_CTX verify_ctx;
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;
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;
}
dgst_ctx = *tbs_dgst_ctx;
digest_finish(&dgst_ctx, dgst, &dgstlen);
// FIXME: use x509_verify_init/update/finish
if (public_key->algor != OID_ec_public_key
|| public_key->algor_param != OID_sm2) {
error_print();
return -1;
}
sm2_verify_init(&verify_ctx, &public_key->u.sm2_key, signer_id, signer_id_len);
sm2_verify_update(&verify_ctx, prefix, 64);
sm2_verify_update(&verify_ctx, context_str_and_zero, context_str_and_zero_len);
sm2_verify_update(&verify_ctx, dgst, dgstlen);
if ((ret = sm2_verify_finish(&verify_ctx, sig, siglen)) < 0) {
error_print();
return -1;
}
if (ret != 1) {
error_print();
}
return ret;
}
/*
verify_data in Finished
finished_key =
HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)
Structure of this message:
struct {
opaque verify_data[Hash.length];
} Finished;
The verify_data value is computed as follows:
verify_data =
HMAC(finished_key,
Transcript-Hash(Handshake Context,
Certificate*, CertificateVerify*))
*/
int tls13_compute_verify_data(const uint8_t *handshake_traffic_secret,
const DIGEST_CTX *dgst_ctx, uint8_t *verify_data, size_t *verify_data_len)
{
DIGEST_CTX temp_dgst_ctx;
uint8_t dgst[64];
size_t dgstlen;
uint8_t finished_key[64];
size_t finished_key_len;
temp_dgst_ctx = *dgst_ctx;
digest_finish(&temp_dgst_ctx, dgst, &dgstlen);
finished_key_len = dgstlen;
tls13_hkdf_expand_label(dgst_ctx->digest, handshake_traffic_secret,
"finished", NULL, 0, finished_key_len, finished_key);
hmac(dgst_ctx->digest, finished_key, finished_key_len, dgst, dgstlen, verify_data, verify_data_len);
return 1;
}
// extensions
int tls_ext_to_bytes(int ext_type, const uint8_t *ext_data, size_t ext_datalen,
uint8_t **out, size_t *outlen)
{
tls_uint16_to_bytes(ext_type, out, outlen);
tls_uint16array_to_bytes(ext_data, ext_datalen, out, outlen);
return 1;
}
/*
struct {
ProtocolVersion versions<2..254>;
} SupportedVersions; -- in ClientHello
*/
int tls13_client_supported_versions_ext_to_bytes(const int *versions, size_t versions_cnt,
uint8_t **out, size_t *outlen)
{
uint16_t ext_type = TLS_extension_supported_versions;
size_t ext_datalen;
size_t versions_len;
size_t i;
if (!versions || !versions_cnt || !outlen) {
error_print();
return -1;
}
if (versions_cnt > 254/2) {
error_print();
return -1;
}
for (i = 0; i < versions_cnt; i++) {
if (!tls_protocol_name(versions[i])) {
error_print();
return -1;
}
}
versions_len = tls_uint16_size() * versions_cnt;
ext_datalen = tls_uint8_size() + versions_len;
tls_uint16_to_bytes(ext_type, out, outlen);
tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen);
tls_uint8_to_bytes((uint8_t)versions_len, out, outlen);
for (i = 0; i < versions_cnt; i++) {
tls_uint16_to_bytes((uint16_t)versions[i], out, outlen);
}
return 1;
}
int tls13_process_client_supported_versions(const uint8_t *ext_data, size_t ext_datalen,
const int *server_versions, size_t server_versions_cnt,
int *common_versions, size_t *common_versions_cnt, size_t max_cnt)
{
const uint8_t *versions;
size_t versions_len;
const uint8_t *cp;
size_t len;
uint16_t version;
size_t i, j = 0;
if (tls_uint8array_from_bytes(&versions, &versions_len, &ext_data, &ext_datalen) != 1
|| tls_length_is_zero(ext_datalen) != 1) {
error_print();
return -1;
}
if (versions_len < 2 || versions_len > 254) {
error_print();
return -1;
}
cp = versions;
len = versions_len;
while (len) {
if (tls_uint16_from_bytes(&version, &cp, &len) != 1) {
error_print();
return -1;
}
if (!tls_protocol_name(version)) {
error_print();
return -1;
}
if (version == server_versions[0] && j < max_cnt) {
common_versions[j++] = version;
}
}
for (i = 1; i < server_versions_cnt && j < max_cnt; i++) {
cp = versions;
len = versions_len;
while (len) {
tls_uint16_from_bytes(&version, &cp, &len);
if (version == server_versions[i]) {
common_versions[j++] = version;
break;
}
}
}
*common_versions_cnt = j;
if (*common_versions_cnt == 0) {
error_print();
return 0;
}
return 1;
}
int tls13_client_supported_versions_print(FILE *fp, int fmt, int ind,
const uint8_t *ext_data, size_t ext_datalen)
{
const uint8_t *versions;
size_t versions_len;
format_print(fp, fmt, ind, "versions\n");
ind += 4;
if (tls_uint8array_from_bytes(&versions, &versions_len, &ext_data, &ext_datalen) != 1) {
error_print();
return -1;
}
if (versions_len < 2 || versions_len > 254) {
error_print();
return -1;
}
while (versions_len) {
uint16_t version;
if (tls_uint16_from_bytes(&version, &versions, &versions_len) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "%s (%04x)\n", tls_protocol_name(version), version);
}
if (ext_datalen) {
error_print();
return -1;
}
return 1;
}
/*
struct {
ProtocolVersion selected_version;
} SupportedVersions; // in ServerHello and HelloRetryRequest
*/
int tls13_server_supported_versions_ext_to_bytes(int selected_version, uint8_t **out, size_t *outlen)
{
uint16_t ext_type = TLS_extension_supported_versions;
size_t ext_datalen;
size_t i;
if (!outlen) {
error_print();
return -1;
}
if (!tls_protocol_name(selected_version)) {
error_print();
return -1;
}
ext_datalen = tls_uint16_size();
tls_uint16_to_bytes(ext_type, out, outlen);
tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen);
tls_uint16_to_bytes(selected_version, out, outlen);
return 1;
}
// 这个函数可能用不上
int tls13_server_supported_versions_from_bytes(int *selected_version, const uint8_t *ext_data, size_t ext_datalen)
{
uint16_t version;
if (tls_uint16_from_bytes(&version, &ext_data, &ext_datalen) != 1
|| tls_length_is_zero(ext_datalen) != 1) {
error_print();
return -1;
}
if (!tls_protocol_name(version)) {
error_print();
return -1;
}
*selected_version = version;
return 1;
}
int tls13_server_supported_versions_print(FILE *fp, int fmt, int ind,
const uint8_t *ext_data, size_t ext_datalen)
{
uint16_t version;
if (tls_uint16_from_bytes(&version, &ext_data, &ext_datalen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "selected_version: %s (%04x)\n", tls_protocol_name(version), version);
if (ext_datalen) {
error_print();
return -1;
}
return 1;
}
int tls13_process_server_supported_versions(const int *client_versions, size_t client_versions_cnt,
const uint8_t *server_ext_data, size_t server_ext_datalen,
int *selected_version)
{
uint16_t version;
size_t i;
if (tls_uint16_from_bytes(&version, &server_ext_data, &server_ext_datalen) != 1
|| tls_length_is_zero(server_ext_datalen) != 1) {
error_print();
return -1;
}
for (i = 0; i < client_versions_cnt; i++) {
if (version == client_versions[i]) {
*selected_version = version;
return 1;
}
}
error_print();
return -1;
}
/*
Extension Cookie
struct {
opaque cookie<1..2^16-1>;
} Cookie;
*/
int tls13_cookie_ext_to_bytes(const uint8_t *cookie, size_t cookielen, uint8_t **out, size_t *outlen)
{
uint16_t ext_type = TLS_extension_cookie;
size_t ext_datalen;
if (!cookie || !cookielen || cookielen > 65535) {
error_print();
return -1;
}
ext_datalen = 2 + cookielen;
if (ext_datalen > 65535) {
error_print();
return -1;
}
tls_uint16_to_bytes(ext_type, out, outlen);
tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen);
tls_uint16array_to_bytes(cookie, cookielen, out, outlen);
return 1;
}
int tls13_cookie_from_bytes(const uint8_t **cookie, size_t *cookielen, const uint8_t *ext_data, size_t ext_datalen)
{
if (tls_uint16array_from_bytes(cookie, cookielen, &ext_data, &ext_datalen) != 1
|| tls_length_is_zero(ext_datalen) != 1) {
error_print();
return -1;
}
if (!(*cookie) || !(*cookielen)) {
error_print();
return -1;
}
return 1;
}
int tls13_cookie_print(FILE *fp, int fmt, int ind, const uint8_t *ext_data, size_t ext_datalen)
{
const uint8_t *cookie;
size_t cookielen;
if (tls_uint16array_from_bytes(&cookie, &cookielen, &ext_data, &ext_datalen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "cookie", cookie, cookielen);
if (ext_datalen) {
error_print();
return -1;
}
return 1;
}
/*
struct {
NamedGroup group;
opaque key_exchange<1..2^16-1>;
} KeyShareEntry;
*/
int tls13_key_share_entry_to_bytes(const X509_KEY *key, uint8_t **out, size_t *outlen)
{
uint16_t group;
uint8_t key_exchange[65];
if (!key || !outlen) {
error_print();
return -1;
}
if (key->algor != OID_ec_public_key) {
error_print();
return -1;
}
if (!(group = tls_named_curve_from_oid(key->algor_param))) {
error_print();
return -1;
}
if (out && *out) {
uint8_t *p = key_exchange;
size_t len = 0;
if (x509_public_key_to_bytes(key, &p, &len) != 1) {
error_print();
return -1;
}
if (len != 65) {
error_print();
return -1;
}
}
tls_uint16_to_bytes(group, out, outlen);
tls_uint16array_to_bytes(key_exchange, 65, out, outlen);
return 1;
}
int tls13_key_share_entry_from_bytes(int *group, const uint8_t **key_exchange, size_t *key_exchange_len,
const uint8_t **in, size_t *inlen)
{
uint16_t named_curve;
if (tls_uint16_from_bytes(&named_curve, in, inlen) != 1
|| tls_uint16array_from_bytes(key_exchange, key_exchange_len, in, inlen) != 1) {
error_print();
return -1;
}
*group = named_curve;
if (!tls_named_curve_name(named_curve)) {
error_print();
return -1;
}
if (*key_exchange_len != 65) {
error_print();
return -1;
}
return 1;
}
/*
struct {
KeyShareEntry client_shares<0..2^16-1>;
} KeyShareClientHello;
*/
int tls13_key_share_client_hello_ext_to_bytes(const X509_KEY *keys, size_t keys_cnt, uint8_t **out, size_t *outlen)
{
uint16_t ext_type = TLS_extension_key_share;
size_t ext_datalen = 0;
size_t client_shares_len = 0;
size_t i;
for (i = 0; i < keys_cnt; i++) {
if (tls13_key_share_entry_to_bytes(&keys[i], NULL, &client_shares_len) != 1) {
error_print();
return -1;
}
}
ext_datalen = 2 + client_shares_len;
tls_uint16_to_bytes(ext_type, out, outlen);
tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen);
tls_uint16_to_bytes((uint16_t)client_shares_len, out, outlen);
for (i = 0; i < keys_cnt; i++) {
tls13_key_share_entry_to_bytes(&keys[i], out, outlen);
}
return 1;
}
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;
}
while (client_shares_len) {
uint16_t group;
const uint8_t *key_exchange;
size_t key_exchange_len;
format_print(fp, fmt, ind, "KeyShareEntry\n");
if (tls_uint16_from_bytes(&group, &client_shares, &client_shares_len) != 1
|| tls_uint16array_from_bytes(&key_exchange, &key_exchange_len, &client_shares, &client_shares_len) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind + 4, "group: %s (%04x)\n", tls_named_curve_name(group), group);
format_bytes(fp, fmt, ind + 4, "key_exchange", key_exchange, key_exchange_len);
}
if (datalen) {
error_print();
return -1;
}
return 1;
}
/*
struct {
KeyShareEntry server_share;
} KeyShareServerHello;
*/
int tls13_key_share_server_hello_ext_to_bytes(const X509_KEY *key, uint8_t **out, size_t *outlen)
{
uint16_t ext_type = TLS_extension_key_share;
size_t ext_datalen = 0;
if (tls13_key_share_entry_to_bytes(key, NULL, &ext_datalen) != 1) {
error_print();
return -1;
}
tls_uint16_to_bytes(ext_type, out, outlen);
tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen);
tls13_key_share_entry_to_bytes(key, out, outlen);
return 1;
}
int tls13_key_share_server_hello_from_bytes(int *group, const uint8_t **key_exchange, size_t *key_exchange_len,
const uint8_t *ext_data, size_t ext_datalen)
{
if (tls13_key_share_entry_from_bytes(group, key_exchange, key_exchange_len,
&ext_data, &ext_datalen) != 1
|| tls_length_is_zero(ext_datalen) != 1) {
error_print();
return -1;
}
return 1;
}
int tls13_key_share_server_hello_print(FILE *fp, int fmt, int ind,
const uint8_t *data, size_t datalen)
{
uint16_t group;
const uint8_t *key_exchange;
size_t key_exchange_len;
format_print(fp, fmt, ind, "server_share\n");
ind += 4;
if (tls_uint16_from_bytes(&group, &data, &datalen) != 1
|| tls_uint16array_from_bytes(&key_exchange, &key_exchange_len, &data, &datalen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "group: %s (%04x)\n", tls_named_curve_name(group), group);
format_bytes(fp, fmt, ind, "key_exchange", key_exchange, key_exchange_len);
if (datalen) {
error_print();
return -1;
}
return 1;
}
/*
struct {
NamedGroup selected_group;
} KeyShareHelloRetryRequest;
*/
int tls13_key_share_hello_retry_request_ext_to_bytes(int selected_group, uint8_t **out, size_t *outlen)
{
uint16_t ext_type = TLS_extension_key_share;
uint8_t ext_data[2];
uint8_t *p = ext_data;
size_t len = 0;
tls_uint16_to_bytes((uint16_t)selected_group, &p, &len);
tls_ext_to_bytes(ext_type, ext_data, sizeof(ext_data), out, outlen);
return 1;
}
int tls13_key_share_hello_retry_request_from_bytes(int *selected_group, const uint8_t *ext_data, size_t ext_datalen)
{
uint16_t group;
if (tls_uint16_from_bytes(&group, &ext_data, &ext_datalen) != 1
|| tls_length_is_zero(ext_datalen) != 1) {
error_print();
return -1;
}
if (!tls_named_curve_name(group)) {
error_print();
return -1;
}
*selected_group = group;
return 1;
}
int tls13_key_share_hello_retry_request_print(FILE *fp, int fmt, int ind,
const uint8_t *ext_data, size_t ext_datalen)
{
uint16_t selected_group;
if (tls_uint16_from_bytes(&selected_group, &ext_data, &ext_datalen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "selected_group: %s (%04x)\n",
tls_named_curve_name(selected_group), selected_group);
if (ext_datalen) {
error_print();
return -1;
}
return 1;
}
/*
certificate_authorities
opaque DistinguishedName<1..2^16-1>;
struct {
DistinguishedName authorities<3..2^16-1>;
} CertificateAuthoritiesExtension;
*/
int tls13_certificate_authorities_ext_to_bytes(const uint8_t *ca_names, size_t ca_names_len,
uint8_t **out, size_t *outlen)
{
int ext_type = TLS_extension_certificate_authorities;
size_t ext_datalen;
size_t authorities_len;
const uint8_t *name;
size_t namelen;
const uint8_t *p;
size_t len;
p = ca_names;
len = ca_names_len;
authorities_len = 0;
while (len) {
if (x509_name_from_der(&name, &namelen, &p, &len) != 1) {
error_print();
return -1;
}
tls_uint16array_to_bytes(name, namelen, NULL, &authorities_len);
}
if (authorities_len < 3 || authorities_len > (1 << 16) - 1) {
error_print();
return -1;
}
ext_datalen = tls_uint16_size() + authorities_len;
tls_uint16_to_bytes(ext_type, out, outlen);
tls_uint16_to_bytes((uint16_t)ext_datalen, out, outlen);
tls_uint16_to_bytes((uint16_t)authorities_len, out, outlen);
while (ca_names_len) {
x509_name_from_der(&name, &namelen, &ca_names, &ca_names_len);
tls_uint16array_to_bytes(name, namelen, out, outlen);
}
return 1;
}
int tls13_certificate_authorities_print(FILE *fp, int fmt, int ind,
const uint8_t *ext_data, size_t ext_datalen)
{
const uint8_t *authorities;
size_t authorities_len;
if (tls_uint16array_from_bytes(&authorities, &authorities_len, &ext_data, &ext_datalen) != 1
|| tls_length_is_zero(ext_datalen) != 1) {
error_print();
return -1;
}
while (authorities_len) {
const uint8_t *dn;
size_t dn_len;
if (tls_uint16array_from_bytes(&dn, &dn_len, &authorities, &authorities_len) != 1) {
error_print();
return -1;
}
x509_name_print(fp, fmt, ind, "DistinguishedName", dn, dn_len);
}
return 1;
}
/*
struct {} Empty;
struct {
select (Handshake.msg_type) {
case new_session_ticket: uint32 max_early_data_size;
case client_hello: Empty;
case encrypted_extensions: Empty;
};
} EarlyDataIndication;
*/
int tls13_early_data_ext_to_bytes(size_t max_early_data_size, uint8_t **out, size_t *outlen)
{
uint8_t ext_data[4];
uint8_t *p = ext_data;
size_t ext_datalen = 0;
tls_uint32_to_bytes(max_early_data_size, &p, &ext_datalen);
if (tls_ext_to_bytes(TLS_extension_early_data, ext_data, ext_datalen, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int tls13_early_data_from_bytes(size_t *max_early_data_size, const uint8_t *ext_data, size_t ext_datalen)
{
uint32_t max_size;
if (tls_uint32_from_bytes(&max_size, &ext_data, &ext_datalen) != 1
|| tls_length_is_zero(ext_datalen) != 1) {
error_print();
return -1;
}
*max_early_data_size = max_size;
return 1;
}
int tls13_early_data_print(FILE *fp, int fmt, int ind, const uint8_t *ext_data, size_t ext_datalen)
{
uint32_t max_early_data_size;
if (!ext_data || !ext_datalen) {
format_print(fp, fmt, ind, "(empty)\n");
} else {
if (tls_uint32_from_bytes(&max_early_data_size, &ext_data, &ext_datalen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "max_early_data_size: %"PRIu32"\n", max_early_data_size);
if (ext_datalen) {
error_print();
return -1;
}
}
return 1;
}
/*
Extension: pre_shared_key
struct {
opaque identity<1..2^16-1>;
uint32 obfuscated_ticket_age;
} PskIdentity;
每个psk_identity包含一个identity字符串可能是一个哈希值或者随机值
还有一个uint32_t 的时间
在每个pre_shared_key 扩展中首先包含一组PskIdentity
然后包含一组binder每个binder是一个
opaque PskBinderEntry<32..255>;
struct {
PskIdentity identities<7..2^16-1>;
PskBinderEntry binders<33..2^16-1>;
} OfferedPsks;
struct {
select (Handshake.msg_type) {
case client_hello: OfferedPsks;
case server_hello: uint16 selected_identity;
};
} PreSharedKeyExtension;
客户端在pre_shared_key扩展中提供一组预设的密钥让服务器从中选择
这个密钥可能来自于系统外部预设的
或者来自于之前的NewSessionTicket
每个密钥除了密钥的ID之外还包含一个密钥的MAC客户端通过这个MAC证明自己拥有密钥ID对应的密钥
这个mac命名为binder
binder = HMAC(binder_key, transcript_hash)
因为这个binder是在ClientHello也就是第一个消息中发送的
因此在计算ClientHello的哈希的时候显然存在一个死锁
因此我们需要先准备好ClientHello其中binder字段添全0长度由HMAC算法决定
然后调用binder_key生成binder
binder_key = HKDF-Expand-Label(early_secret, "res binder", "", Hash.length)
这里的early_secret是什么
客户端在完成Full Handshake之后可以缓冲
我们可以缓冲在CTX中按域名 / SNI / ALPN”等维度索引
)
*/
int tls13_server_pre_shared_key_ext_to_bytes(int selected_identity, uint8_t **out, size_t *outlen)
{
if (selected_identity > 65535) {
error_print();
return -1;
}
tls_uint16_to_bytes((uint16_t)selected_identity, out, outlen);
return 1;
}
int tls13_server_pre_shared_key_from_bytes(int *selected_identity, const uint8_t *ext_data, size_t ext_datalen)
{
uint16_t identity;
if (tls_uint16_from_bytes(&identity, &ext_data, &ext_datalen) != 1
|| tls_length_is_zero(ext_datalen) != 1) {
error_print();
return -1;
}
*selected_identity = identity;
return 1;
}
int tls13_server_pre_shared_key_print(FILE *fp, int fmt, int ind, const uint8_t *ext_data, size_t ext_datalen)
{
uint16_t identity;
if (tls_uint16_from_bytes(&identity, &ext_data, &ext_datalen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "seleceted_identity: %d\n", identity);
if (ext_datalen) {
error_print();
return -1;
}
return 1;
}
/*
struct {
opaque certificate_request_context<0..2^8-1>;
Extension extensions<2..2^16-1>;
} CertificateRequest;
certificate_request_context 用于 Post-handshake Authentication否则应该长度为0
*/
int tls13_client_hello_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
uint16_t protocol;
const uint8_t *random;
const uint8_t *session_id;
const uint8_t *cipher_suites;
const uint8_t *comp_meths;
const uint8_t *exts;
size_t session_id_len, cipher_suites_len, comp_meths_len, extslen;
size_t i;
format_print(fp, fmt, ind, "ClientHello\n");
ind += 4;
if (tls_uint16_from_bytes(&protocol, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "legacy_version: %s (%04x)\n",
tls_protocol_name(protocol), protocol);
if (tls_array_from_bytes(&random, 32, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "random", random ,32);
if (tls_uint8array_from_bytes(&session_id, &session_id_len, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "legacy_session_id", session_id, session_id_len);
format_print(fp, fmt, ind, "cipher_suites\n");
if (tls_uint16array_from_bytes(&cipher_suites, &cipher_suites_len, &d, &dlen) != 1) {
error_print();
return -1;
}
while (cipher_suites_len) {
uint16_t cipher;
if (tls_uint16_from_bytes(&cipher, &cipher_suites, &cipher_suites_len) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind+4, "%s (%04x)\n", tls_cipher_suite_name(cipher), cipher);
}
format_print(fp, fmt, ind, "legacy_compression_methods\n");
if (tls_uint8array_from_bytes(&comp_meths, &comp_meths_len, &d, &dlen) != 1) {
error_print();
return -1;
}
for (i = 0; i < comp_meths_len; i++) {
format_print(fp, fmt, ind + 4, "%s (%d)\n",
tls_compression_method_name(comp_meths[i]), comp_meths[i]);
}
format_print(fp, fmt, ind, "extensions\n");
ind += 4;
if (tls_uint16array_from_bytes(&exts, &extslen, &d, &dlen) != 1) {
error_print();
return -1;
}
while (extslen) {
uint16_t ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
// tls_ext_from_bytes can not parse unknown ext
if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "%s (%d)\n", tls_extension_name(ext_type), ext_type);
switch (ext_type) {
case TLS_extension_supported_versions:
tls13_client_supported_versions_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_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_signature_algorithms:
tls_signature_algorithms_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_early_data:
tls13_early_data_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_psk_key_exchange_modes:
case TLS_extension_pre_shared_key:
case TLS_extension_server_name:
case TLS_extension_application_layer_protocol_negotiation:
case TLS_extension_padding:
case TLS_extension_record_size_limit:
default:
error_print();
return -1;
}
}
if (dlen) {
error_print();
return -1;
}
return 1;
}
int tls13_server_hello_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
uint16_t protocol;
const uint8_t *random;
const uint8_t *session_id;
uint16_t cipher_suite;
uint8_t comp_meth;
const uint8_t *exts;
size_t session_id_len, extslen;
format_print(fp, fmt, ind, "ServerHello\n");
ind += 4;
if (tls_uint16_from_bytes(&protocol, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "legacy_version: %s (%04x)\n",
tls_protocol_name(protocol), protocol);
if (tls_array_from_bytes(&random, 32, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "random", random, 32);
if (tls_uint8array_from_bytes(&session_id, &session_id_len, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "legacy_session_id", session_id, session_id_len);
if (tls_uint16_from_bytes(&cipher_suite, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "cipher_suite: %s (%04x)\n",
tls_cipher_suite_name(cipher_suite), cipher_suite);
if (tls_uint8_from_bytes(&comp_meth, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "legacy_compression_method: %s (%d)\n",
tls_compression_method_name(comp_meth), comp_meth);
format_print(fp, fmt, ind, "extensions\n");
ind += 4;
if (tls_uint16array_from_bytes(&exts, &extslen, &d, &dlen) != 1) {
error_print();
return -1;
}
while (extslen) {
uint16_t ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "%s (%d)\n", tls_extension_name(ext_type), ext_type);
switch (ext_type) {
case TLS_extension_supported_versions:
tls13_server_supported_versions_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_key_share:
tls13_key_share_server_hello_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_pre_shared_key:
//tls13_pre_shared_key_print(fp, fmt, ind, ext_data, ext_datalen);
break;
case TLS_extension_cookie:
tls13_cookie_print(fp, fmt, ind, ext_data, ext_datalen);
break;
default:
format_bytes(fp, fmt, ind, "raw_data", ext_data, ext_datalen);
return -1;
}
}
if (dlen) {
error_print();
return -1;
}
return 1;
}
/*
struct {
ProtocolVersion server_version; // 服务器选择的版本
CipherSuite cipher_suite; // 服务器选择的密码套件
Extension extensions<2..2^16-1>; // 扩展列表
} HelloRetryRequest;
*/
int tls13_set_handshake_hello_retry_request(uint8_t *record, size_t *recordlen,
int legacy_version, const uint8_t random[32],
const uint8_t *legacy_session_id_echo, size_t legacy_session_id_echo_len,
int cipher_suite, int legacy_compress_meth,
const uint8_t *exts, size_t extslen)
{
int type = TLS_handshake_hello_retry_request;
uint8_t *p;
size_t len;
if (!tls_protocol_name(legacy_version)) {
error_print();
return -1;
}
if (legacy_session_id_echo_len > 32) {
error_print();
return -1;
}
if (!tls_cipher_suite_name(cipher_suite)) {
error_print();
return -1;
}
if (legacy_compress_meth > 255) {
error_print();
return -1;
}
p = tls_handshake_data(tls_record_data(record));
len = 0;
tls_uint16_to_bytes((uint16_t)legacy_version, &p, &len);
tls_array_to_bytes(random, 32, &p, &len);
tls_uint8array_to_bytes(legacy_session_id_echo, legacy_session_id_echo_len, &p, &len);
tls_uint16_to_bytes((uint16_t)cipher_suite, &p, &len);
tls_uint8_to_bytes((uint8_t)legacy_compress_meth, &p, &len);
tls_uint16array_to_bytes(exts, extslen, &p, &len);
if (tls_record_set_handshake(record, recordlen, type, NULL, len) != 1) {
error_print();
return -1;
}
return 1;
}
int tls13_record_get_handshake_hello_retry_request(uint8_t *record,
int *legacy_version, const uint8_t **random,
const uint8_t **legacy_session_id_echo, size_t *legacy_session_id_echo_len,
int *cipher_suite, int *legacy_compress_meth,
const uint8_t **exts, size_t *extslen)
{
int type;
const uint8_t *cp;
size_t len;
uint16_t version;
uint16_t cipher;
uint8_t comp_meth;
if (tls_record_get_handshake(record, &type, &cp, &len) != 1) {
error_print();
return -1;
}
if (type != TLS_handshake_hello_retry_request) {
error_print();
return -1;
}
if (tls_uint16_from_bytes(&version, &cp, &len) != 1
|| tls_array_from_bytes(random, 32, &cp, &len) != 1
|| tls_uint8array_from_bytes(legacy_session_id_echo, legacy_session_id_echo_len, &cp, &len) != 1
|| tls_uint16_from_bytes(&cipher, &cp, &len) != 1
|| tls_uint8_from_bytes(&comp_meth, &cp, &len) != 1
|| tls_uint16array_from_bytes(exts, extslen, &cp, &len) != 1
|| tls_length_is_zero(len) != 1) {
error_print();
return -1;
}
// if legacy_version != tls12, send protocol_version alert
if (!tls_protocol_name(version)) {
error_print();
return -1;
}
if (version != TLS_protocol_tls12) {
error_print();
}
*legacy_version = version;
if (*legacy_session_id_echo_len > 32) {
error_print();
return -1;
}
if (!tls_cipher_suite_name(cipher)) {
error_print();
return -1;
}
*cipher_suite = cipher;
// if legacy_compress_meth != 0, send illegal_parameter alert
if (comp_meth != 0) {
error_print();
}
*legacy_compress_meth = comp_meth;
if (*extslen < 6) {
error_print();
return -1;
}
return 1;
}
int tls13_hello_retry_request_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
uint16_t protocol;
const uint8_t *random;
const uint8_t *session_id;
uint16_t cipher_suite;
uint8_t comp_meth;
const uint8_t *exts;
size_t session_id_len, extslen;
format_print(fp, fmt, ind, "HelloRetryRequest\n");
ind += 4;
if (tls_uint16_from_bytes(&protocol, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "legacy_version: %s (%04x)\n",
tls_protocol_name(protocol), protocol);
if (tls_array_from_bytes(&random, 32, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "random", random, 32);
if (tls_uint8array_from_bytes(&session_id, &session_id_len, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "legacy_session_id", session_id, session_id_len);
if (tls_uint16_from_bytes(&cipher_suite, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "cipher_suite: %s (%04x)\n",
tls_cipher_suite_name(cipher_suite), cipher_suite);
if (tls_uint8_from_bytes(&comp_meth, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "legacy_compression_method: %s (%d)\n",
tls_compression_method_name(comp_meth), comp_meth);
format_print(fp, fmt, ind, "extensions\n");
ind += 4;
if (tls_uint16array_from_bytes(&exts, &extslen, &d, &dlen) != 1) {
error_print();
return -1;
}
while (extslen) {
uint16_t ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "%s (%d)\n", tls_extension_name(ext_type), ext_type);
switch (ext_type) {
case TLS_extension_supported_versions:
tls13_server_supported_versions_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_key_share:
tls13_key_share_hello_retry_request_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_pre_shared_key:
//tls13_pre_shared_key_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_cookie:
tls13_cookie_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
default:
format_bytes(fp, fmt, ind + 4, "raw_data", ext_data, ext_datalen);
return -1;
}
}
if (dlen) {
error_print();
return -1;
}
return 1;
}
/*
struct {
select (Handshake.msg_type) {
case new_session_ticket: uint32 max_early_data_size;
case client_hello: empty;
case encrypted_extensions: empty;
};
} EarlyDataIndication;
*/
int tls13_new_session_ticket_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
uint32_t ticket_lifetime;
uint32_t ticket_age_add;
const uint8_t *ticket_nonce;
size_t ticket_nonce_len;
const uint8_t *ticket;
size_t ticket_len;
const uint8_t *exts;
size_t extslen;
// early_data extension
uint32_t max_early_data_size;
format_print(fp, fmt, ind, "NewSessionTicket\n");
ind += 4;
if (tls_uint32_from_bytes(&ticket_lifetime, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "ticket_lifetime: %"PRIu32" seconds\n", ticket_lifetime);
if (tls_uint32_from_bytes(&ticket_age_add, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "ticket_age_add: %"PRIu32"\n", ticket_age_add);
if (tls_uint8array_from_bytes(&ticket_nonce, &ticket_nonce_len, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "ticket_nonce", ticket_nonce, ticket_nonce_len);
if (tls_uint16array_from_bytes(&ticket, &ticket_len, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "ticket", ticket, ticket_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_early_data:
tls13_early_data_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
default:
format_print(fp, fmt, ind, "%s (%d)\n", tls_extension_name(ext_type), ext_type);
format_bytes(fp, fmt, ind + 4, "raw_data", ext_data, ext_datalen);
error_print();
}
}
if (dlen) {
error_print();
return -1;
}
return 1;
}
int tls13_end_of_early_data_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
format_print(fp, fmt, ind, "EndOfEarlyData\n");
if (dlen) {
error_print();
return -1;
}
return 1;
}
int tls13_encrypted_extensions_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
const uint8_t *exts;
size_t extslen;
format_print(fp, fmt, ind, "EncryptedExtensions\n");
ind += 4;
format_print(fp, fmt, ind, "extensions\n");
ind += 4;
if (tls_uint16array_from_bytes(&exts, &extslen, &d, &dlen) != 1) {
error_print();
return -1;
}
if (!extslen) {
format_print(fp, fmt, ind, "(null)\n");
}
while (extslen) {
uint16_t ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "%s (%d)\n", tls_extension_name(ext_type), ext_type);
switch (ext_type) {
case TLS_extension_supported_groups:
tls_supported_groups_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_early_data:
tls13_early_data_print(fp, fmt, ind + 4, ext_data, ext_datalen);
break;
case TLS_extension_client_certificate_type:
case TLS_extension_server_certificate_type:
case TLS_extension_server_name:
case TLS_extension_max_fragment_length:
case TLS_extension_use_srtp:
case TLS_extension_heartbeat:
case TLS_extension_application_layer_protocol_negotiation:
case TLS_extension_record_size_limit:
default:
format_bytes(fp, fmt, ind, "raw_data", ext_data, ext_datalen);
}
}
if (dlen) {
error_print();
return -1;
}
return 1;
}
int tls13_certificate_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
const uint8_t *req_context;
size_t req_context_len;
const uint8_t *cert_list;
size_t cert_list_len;
format_print(fp, fmt, ind, "Certificate\n");
ind += 4;
if (tls_uint8array_from_bytes(&req_context, &req_context_len, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "certificate_request_context", req_context, req_context_len);
format_print(fp, fmt, ind, "certificate_list\n");
ind += 4;
if (tls_uint24array_from_bytes(&cert_list, &cert_list_len, &d, &dlen) != 1) {
error_print();
return -1;
}
while (cert_list_len) {
const uint8_t *cert_data;
size_t cert_data_len;
const uint8_t *exts;
size_t extslen;
format_print(fp, fmt, ind, "CertificateEntry\n");
if (tls_uint24array_from_bytes(&cert_data, &cert_data_len, &cert_list, &cert_list_len) != 1
|| tls_uint16array_from_bytes(&exts, &extslen, &cert_list, &cert_list_len) != 1) {
error_print();
return -1;
}
if (!cert_data_len) {
error_print();
return -1;
}
x509_cert_print(fp, fmt, ind + 4, "Certificate", cert_data, cert_data_len);
x509_cert_to_pem(cert_data, cert_data_len, fp);
if (extslen)
format_print(fp, fmt, ind + 4, "extensions\n");
else format_print(fp, fmt, ind + 4, "extensions: (null)\n");
while (extslen) {
uint16_t ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "%s (%d)\n", tls_extension_name(ext_type), ext_type);
ind += 4;
switch (ext_type) {
case TLS_extension_status_request:
case TLS_extension_signed_certificate_timestamp:
case TLS_extension_server_certificate_type:
case TLS_extension_client_certificate_type:
break;
default:
error_print();
return -1;
}
}
}
if (dlen) {
error_print();
return -1;
}
return 1;
}
int tls13_certificate_request_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
const uint8_t *req_context;
size_t req_context_len;
const uint8_t *exts;
size_t extslen;
format_print(fp, fmt, ind, "CertificateRequest\n");
ind += 4;
if (tls_uint8array_from_bytes(&req_context, &req_context_len, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "certificate_request_context", req_context, req_context_len);
format_print(fp, fmt, ind, "extensions\n");
ind += 4;
if (tls_uint16array_from_bytes(&exts, &extslen, &d, &dlen) != 1) {
error_print();
return -1;
}
while (extslen) {
uint16_t ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_uint16_from_bytes(&ext_type, &exts, &extslen) != 1
|| tls_uint16array_from_bytes(&ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
return -1;
}
switch (ext_type) {
case TLS_extension_signature_algorithms:
tls_signature_algorithms_print(fp, fmt, ind, ext_data, ext_datalen);
break;
case TLS_extension_certificate_authorities:
tls13_certificate_authorities_print(fp, fmt, ind, ext_data, ext_datalen);
break;
case TLS_extension_status_request:
//tls13_status_request_print(fp, fmt, ind, ext_data, ext_datalen);
break;
case TLS_extension_signature_algorithms_cert:
tls13_signature_algorithms_cert_print(fp, fmt, ind, ext_data, ext_datalen);
break;
case TLS_extension_client_certificate_type:
//tls13_client_certificate_type_print(fp, fmt, ind, ext_data, ext_datalen);
break;
default:
error_print();
return -1;
}
}
if (dlen) {
error_print();
return -1;
}
return 1;
}
int tls13_certificate_verify_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
uint16_t sig_alg;
const uint8_t *sig;
size_t siglen;
format_print(fp, fmt, ind, "CertificateVerify\n");
ind += 4;
if (tls_uint16_from_bytes(&sig_alg, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "algorithm: %s (%04x)\n", tls_signature_scheme_name(sig_alg), sig_alg);
if (tls_uint16array_from_bytes(&sig, &siglen, &d, &dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "signature", sig, siglen);
if (tls_length_is_zero(dlen) != 1) {
error_print();
return -1;
}
return 1;
}
int tls13_key_update_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
uint8_t update_requested;
if (tls_uint8_from_bytes(&update_requested, &d, &dlen) != 1
|| tls_length_is_zero(dlen) != 1) {
error_print();
return -1;
}
switch (update_requested) {
case 0:
case 1:
break;
default:
error_print();
return -1;
}
format_print(fp, fmt, ind, "request_update: %d\n", update_requested);
return 1;
}
int tls13_message_hash_print(FILE *fp, int fmt, int ind, const uint8_t *d, size_t dlen)
{
return 1;
}
int tls13_finished_print(FILE *fp, int fmt, int ind, const uint8_t *data, size_t datalen)
{
format_print(fp, fmt, ind, "Finished\n");
ind += 4;
format_bytes(fp, fmt, ind, "verify_data", data, datalen);
return 1;
}
int tls13_handshake_print(FILE *fp, int fmt, int ind, const uint8_t *handshake, size_t handshake_len)
{
const uint8_t *p = handshake;
size_t len = handshake_len;
uint8_t type;
const uint8_t *data;
size_t datalen;
if (tls_uint8_from_bytes(&type, &handshake, &handshake_len) != 1
|| tls_uint24array_from_bytes(&data, &datalen, &handshake, &handshake_len) != 1
|| tls_length_is_zero(handshake_len) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "Handshake\n");
ind += 4;
format_print(fp, fmt, ind, "Type: %s (%d)\n", tls_handshake_type_name(type), type);
format_print(fp, fmt, ind, "Length: %zu\n", datalen);
switch (type) {
case TLS_handshake_client_hello:
tls13_client_hello_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_server_hello:
tls13_server_hello_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_hello_retry_request:
tls13_hello_retry_request_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_new_session_ticket:
tls13_new_session_ticket_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_end_of_early_data:
tls13_end_of_early_data_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_encrypted_extensions:
tls13_encrypted_extensions_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_certificate:
tls13_certificate_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_certificate_request:
tls13_certificate_request_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_certificate_verify:
tls13_certificate_verify_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_finished:
tls13_finished_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_key_update:
tls13_key_update_print(fp, fmt, ind, data, datalen);
break;
case TLS_handshake_message_hash:
tls13_message_hash_print(fp, fmt, ind, data, datalen);
break;
default:
error_print();
return -1;
}
return 1;
}
int tls13_record_print(FILE *fp, int format, int indent, const uint8_t *record, size_t recordlen)
{
const uint8_t *data;
size_t datalen;
int protocol;
format |= TLS_cipher_sm4_gcm_sm3 << 8;
if (!fp || !record || recordlen < 5) {
error_print();
return -1;
}
protocol = tls_record_protocol(record);
format_print(fp, format, indent, "Record\n"); indent += 4;
format_print(fp, format, indent, "ContentType: %s (%d)\n", tls_record_type_name(record[0]), record[0]);
format_print(fp, format, indent, "Version: %s (%04x)\n", tls_protocol_name(protocol), protocol);
format_print(fp, format, indent, "Length: %d\n", tls_record_data_length(record));
data = tls_record_data(record);
datalen = tls_record_data_length(record);
if (recordlen < tls_record_length(record)) {
error_print();
return -1;
}
// 最高字节设置后强制打印记录原始数据
if (format >> 24) {
format_bytes(fp, format, indent, "Data", data, datalen);
fprintf(fp, "\n");
return 1;
}
switch (record[0]) {
case TLS_record_handshake:
tls13_handshake_print(fp, format, indent, data, datalen);
break;
case TLS_record_alert:
if (tls_alert_print(fp, data, datalen, format, indent) != 1) {
error_print();
return -1;
}
break;
case TLS_record_change_cipher_spec:
if (tls_change_cipher_spec_print(fp, data, datalen, format, indent) != 1) {
error_print();
return -1;
}
break;
case TLS_record_application_data:
if (tls_application_data_print(fp, data, datalen, format, indent) != 1) {
error_print();
return -1;
}
break;
default:
error_print();
return -1;
}
recordlen -= tls_record_length(record);
if (recordlen) {
format_print(fp, 0, 0, "DataLeftInRecord: %zu\n", recordlen);
}
fprintf(fp, "\n");
return 1;
}
int tls13_certificate_list_to_bytes(const uint8_t *certs, size_t certslen,
uint8_t **out, size_t *outlen)
{
uint8_t *p = NULL;
size_t cert_list_len = 0;
if (out && *out) {
p = (*out) + tls_uint24_size();
}
while (certslen) {
const uint8_t *cert;
size_t certlen;
const uint8_t *entry_exts = NULL;
size_t entry_exts_len = 0;
if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1) {
error_print();
return -1;
}
tls_uint24array_to_bytes(cert, certlen, &p, &cert_list_len);
tls_uint16array_to_bytes(entry_exts, entry_exts_len, &p, &cert_list_len);
}
tls_uint24array_to_bytes(NULL, cert_list_len, out, outlen);
return 1;
}
int tls13_process_certificate_list(const uint8_t *cert_list, size_t cert_list_len,
uint8_t *certs, size_t *certs_len)
{
*certs_len = 0;
while (cert_list_len) {
const uint8_t *cert_data;
size_t cert_data_len;
const uint8_t *exts;
size_t exts_len;
const uint8_t *cert;
size_t cert_len;
if (tls_uint24array_from_bytes(&cert_data, &cert_data_len, &cert_list, &cert_list_len) != 1
|| tls_uint16array_from_bytes(&exts, &exts_len, &cert_list, &cert_list_len) != 1) {
error_print();
return -1;
}
if (x509_cert_from_der(&cert, &cert_len, &cert_data, &cert_data_len) != 1
|| asn1_length_is_zero(cert_data_len) != 1
|| x509_cert_to_der(cert, cert_len, &certs, certs_len) != 1) {
error_print();
return -1;
}
while (exts_len) {
int ext_type;
const uint8_t *ext_data;
size_t ext_data_len;
if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_data_len, &exts, &exts_len) != 1) {
error_print();
return -1;
}
switch (ext_type) {
case TLS_extension_status_request:
case TLS_extension_signed_certificate_timestamp:
error_print();
return -1;
default:
error_print();
return -1;
}
}
}
return 1;
}
// 1. client_hello
// 2. server_hello
int tls13_record_set_handshake_hello_retry_request(uint8_t *record, size_t *recordlen,
int protocol, const uint8_t random[32],
const uint8_t *session_id, size_t session_id_len, int cipher_suite,
const uint8_t *exts, size_t exts_len)
{
uint8_t type = TLS_handshake_hello_retry_request;
uint8_t *p;
size_t len;
if (!record || !recordlen || !random) {
error_print();
return -1;
}
if (session_id) {
if (session_id_len == 0
|| session_id_len < TLS_MIN_SESSION_ID_SIZE
|| session_id_len > TLS_MAX_SESSION_ID_SIZE) {
error_print();
return -1;
}
}
if (!tls_protocol_name(protocol)) {
error_print();
return -1;
}
if (!tls_cipher_suite_name(cipher_suite)) {
error_print();
return -1;
}
p = tls_handshake_data(tls_record_data(record));
len = 0;
tls_uint16_to_bytes((uint16_t)protocol, &p, &len);
tls_array_to_bytes(random, 32, &p, &len);
tls_uint8array_to_bytes(session_id, session_id_len, &p, &len);
tls_uint16_to_bytes((uint16_t)cipher_suite, &p, &len);
tls_uint8_to_bytes((uint8_t)TLS_compression_null, &p, &len);
if (exts) {
if (protocol < TLS_protocol_tls12) {
error_print();
return -1;
}
tls_uint16array_to_bytes(exts, exts_len, &p, &len);
}
if (tls_record_set_handshake(record, recordlen, type, NULL, len) != 1) {
error_print();
return -1;
}
return 1;
}
/*
NewSessionTicket
struct {
uint32 ticket_lifetime;
uint32 ticket_age_add;
opaque ticket_nonce<0..255>;
opaque ticket<1..2^16-1>;
Extension extensions<0..2^16-2>;
} NewSessionTicket;
*/
typedef struct {
uint8_t resumption_master_secret[48];
uint16_t protocol_version;
uint16_t cipher_suite;
uint32_t ticket_issue_time;
uint32_t ticket_lifetime;
// TODO: SNI, ALPN, client_certificate (dgst or subject), ticket_age_add, max_early_data_size
} TLS_TICKET;
int tls13_ticket_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
{
const uint8_t *resumption_master_secret;
uint16_t protocol_version;
uint16_t cipher_suite;
uint32_t ticket_issue_time;
uint32_t ticket_lifetime;
format_print(fp, fmt, ind, "%s\n", label);
ind += 4;
if (tls_array_from_bytes(&resumption_master_secret, 48, &d, &dlen) != 1
|| tls_uint16_from_bytes(&protocol_version, &d, &dlen) != 1
|| tls_uint16_from_bytes(&cipher_suite, &d, &dlen) != 1
|| tls_uint32_from_bytes(&ticket_issue_time, &d, &dlen) != 1
|| tls_uint32_from_bytes(&ticket_lifetime, &d, &dlen) != 1
|| tls_length_is_zero(dlen) != 1) {
error_print();
return -1;
}
format_bytes(fp, fmt, ind, "resumption_master_secret", resumption_master_secret, 48);
format_print(fp, fmt, ind, "protocol_version: %s (%04x)\n", tls_protocol_name(protocol_version), protocol_version);
format_print(fp, fmt, ind, "cipher_suite: %s (%04x)\n", tls_cipher_suite_name(cipher_suite), cipher_suite);
format_print(fp, fmt, ind, "ticket_issue_time: %"PRIu32"\n", ticket_issue_time);
format_print(fp, fmt, ind, "ticket_lifetime: %"PRIu32"\n", ticket_lifetime);
return 1;
}
int tls13_encrypt_ticket(const SM4_KEY *key, const uint8_t resumption_master_secret[48],
int protocol_version, int cipher_suite, uint32_t ticket_issue_time, uint32_t ticket_lifetime,
uint8_t *out, size_t *outlen)
{
uint8_t ticket[60];
uint8_t *p = ticket;
size_t ticketlen = 0;
uint8_t *iv = out;
size_t ivlen = 12;
const uint8_t *aad = NULL;
size_t aadlen = 0;
uint8_t *tag;
size_t taglen = 16;
out += ivlen;
tag = out + sizeof(ticket);
tls_array_to_bytes(resumption_master_secret, 48, &p, &ticketlen);
tls_uint16_to_bytes(protocol_version, &p, &ticketlen);
tls_uint16_to_bytes(cipher_suite, &p, &ticketlen);
tls_uint32_to_bytes(ticket_issue_time, &p, &ticketlen);
tls_uint32_to_bytes(ticket_lifetime, &p, &ticketlen);
if (ticketlen != sizeof(ticket)) {
error_print();
return -1;
}
if (rand_bytes(iv, ivlen) != 1) {
error_print();
return -1;
}
if (sm4_gcm_encrypt(key, iv, ivlen, aad, aadlen, ticket, ticketlen, out, taglen, tag) != 1) {
error_print();
return -1;
}
*outlen = ivlen + sizeof(ticket) + taglen;
return 1;
}
int tls13_decrypt_ticket(const SM4_KEY *key, const uint8_t *in, size_t inlen,
uint8_t resumption_master_secret[48], int *protocol_version, int *cipher_suite,
uint32_t *ticket_issue_time, uint32_t *ticket_lifetime)
{
const uint8_t *iv;
size_t ivlen = 12;
const uint8_t *aad = NULL;
size_t aadlen = 0;
const uint8_t *tag;
size_t taglen = 16;
uint8_t ticket[60];
const uint8_t *cp = ticket;
const uint8_t *master_secret;
uint16_t version;
uint16_t cipher;
if (inlen != ivlen + sizeof(ticket) + taglen) {
error_print();
return -1;
}
iv = in;
in += ivlen;
inlen -= ivlen;
tag = in + sizeof(ticket);
inlen -= taglen;
if (sm4_gcm_decrypt(key, iv, ivlen, aad, aadlen, in, sizeof(ticket), tag, taglen, ticket) != 1) {
error_print();
return -1;
}
if (tls_array_from_bytes(&master_secret, 48, &cp, &inlen) != 1
|| tls_uint16_from_bytes(&version, &cp, &inlen) != 1
|| tls_uint16_from_bytes(&cipher, &cp, &inlen) != 1
|| tls_uint32_from_bytes(ticket_issue_time, &cp, &inlen) != 1
|| tls_uint32_from_bytes(ticket_lifetime, &cp, &inlen) != 1
|| tls_length_is_zero(inlen) != 1) {
error_print();
return -1;
}
memcpy(resumption_master_secret, master_secret, 48);
*protocol_version = version;
*cipher_suite = cipher;
return 1;
}
int tls13_record_set_handshake_new_session_ticket(uint8_t *record, size_t *recordlen,
uint32_t ticket_lifetime, uint32_t ticket_age_add,
const uint8_t *ticket_nonce, size_t ticket_nonce_len,
const uint8_t *ticket, size_t ticketlen,
const uint8_t *exts, size_t extslen)
{
int type = TLS_handshake_new_session_ticket;
uint8_t *p = record + 5 + 4;
size_t len = 0;
if (ticket_nonce_len > 255
|| ticketlen > 65535
|| extslen > 65534) {
error_print();
return -1;
}
tls_uint32_to_bytes(ticket_lifetime, &p, &len);
tls_uint32_to_bytes(ticket_age_add, &p, &len);
tls_uint8array_to_bytes(ticket_nonce, ticket_nonce_len, &p, &len);
tls_uint16array_to_bytes(ticket, ticketlen, &p, &len);
tls_uint16array_to_bytes(exts, extslen, &p, &len);
tls_record_set_handshake(record, recordlen, type, NULL, len);
return 1;
}
int tls13_record_get_handshake_new_session_ticket(uint8_t *record,
uint32_t *ticket_lifetime, uint32_t *ticket_age_add,
const uint8_t **ticket_nonce, size_t *ticket_nonce_len,
const uint8_t **ticket, size_t *ticketlen,
const uint8_t **exts, size_t *extslen)
{
int type;
const uint8_t *cp;
size_t len;
// new_session_ticket是optional的吗
if (tls_record_get_handshake(record, &type, &cp, &len) != 1) {
error_print();
return -1;
}
if (type != TLS_handshake_new_session_ticket) {
error_print();
return -1;
}
if (tls_uint32_from_bytes(ticket_lifetime, &cp, &len) != 1
|| tls_uint32_from_bytes(ticket_age_add, &cp, &len) != 1
|| tls_uint8array_from_bytes(ticket_nonce, ticket_nonce_len, &cp, &len) != 1
|| tls_uint16array_from_bytes(ticket, ticketlen, &cp, &len) != 1
|| tls_uint16array_from_bytes(exts, extslen, &cp, &len) != 1
|| tls_length_is_zero(len) != 1) {
error_print();
return -1;
}
if (*ticket_lifetime > 60 * 60 * 24 * 7) {
error_print();
return -1;
}
if (!ticketlen) {
error_print();
return -1;
}
if (*extslen > 65534) {
error_print();
return -1;
}
return 1;
}
// 5. end_of_early_data
int tls13_record_set_handshake_end_of_early_data(uint8_t *record, size_t *recordlen)
{
int type = TLS_handshake_end_of_early_data;
tls_record_set_handshake(record, recordlen, type, NULL, 0);
return 1;
}
int tls13_record_get_handshake_end_of_early_data(uint8_t *record, size_t *recordlen)
{
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_end_of_early_data) {
error_print();
return -1;
}
if (len) {
error_print();
return -1;
}
return 1;
}
// 8. encrypted_extensions
int tls13_record_set_handshake_encrypted_extensions(uint8_t *record, size_t *recordlen,
const uint8_t *exts, size_t extslen)
{
int type = TLS_handshake_encrypted_extensions;
uint8_t *p = record + 5 + 4;
size_t len = 0;
tls_uint16array_to_bytes(exts, extslen, &p, &len);
tls_record_set_handshake(record, recordlen, type, NULL, len);
return 1;
}
int tls13_record_get_handshake_encrypted_extensions(const uint8_t *record,
const uint8_t **exts, size_t *extslen)
{
int type;
const uint8_t *cp;
size_t len;
if (tls_record_get_handshake(record, &type, &cp, &len) != 1) {
error_print();
return -1;
}
if (type != TLS_handshake_encrypted_extensions) {
error_print();
return 0;
}
if (tls_uint16array_from_bytes(exts, extslen, &cp, &len) != 1
|| tls_length_is_zero(len) != 1) {
error_print();
return -1;
}
return 1;
}
// 11. certificate
// 这里有一个问题就是TLS 1.3的Certificate是由CertificateEntry构成的
// 每一个Entry都有可选的扩展都有哪些可选的扩展呢
/*
客户端在ClientHello扩展中对服务器的证书提出要求
status_request 证书的OCSP响应
这个扩展在ClientHello和ServerCertificate中的格式是不一样的
暂时先不要支持了
服务器可以忽略这个请求
这个信息是需要经常更新的
服务器可以每天根据OCSP的配置去OCSP服务器获取并且在初始化的时候提供给ctx
signed_certificate_timestamp 证书透明,证明证书已被提交到公共日志系统
可能出现在客户端或者服务器端
这个扩展本身可以嵌入在证书中也可以从TLS扩展提供
实际上没必要现在就实现
certificate_authorities 接收的CA
应该出现在CertificateRequest和ClientHello中
我们需要支持从一组证书中获取这个信息
这个已经支持了
oid_filters
仅仅出现在CertificateRequest中
这些扩展处理起来是比较复杂的
这里的主要问题是,每个证书都带有一组。
每个CertificateEntry都包含一个extensionsextensions的结构是uint16array
因此我们可以提供一个exts_list
Certificate {
opaque certificate_request_context<0..2^8-1>;
CertificateEntry certificate_list<0..2^24-1>; // 证书链,第一个是终端证书
}
CertificateEntry {
select (certificate_type) {
case X509: opaque cert_data<1..2^24-1>; // DER编码的X.509证书
};
Extension extensions<0..2^16-1>; // 这个证书的扩展列表
}
*/
// 这个函数还应该提供扩展
int tls13_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 *exts_list, size_t exts_list_len)
{
int type = TLS_handshake_certificate;
uint8_t *data;
size_t datalen;
if (!record || !recordlen || !certs || !certslen) {
error_print();
return -1;
}
// 这个就比较复杂了,需要先计算所有的长度
// 然后最后再输出
datalen = 0;
tls_uint8array_to_bytes(request_context, request_context_len, NULL, &datalen);
tls13_certificate_list_to_bytes(certs, certslen, NULL, &datalen);
if (datalen > TLS_MAX_HANDSHAKE_DATA_SIZE) {
error_print();
return -1;
}
data = tls_handshake_data(tls_record_data(record));
datalen = 0;
tls_uint8array_to_bytes(request_context, request_context_len, &data, &datalen);
tls13_certificate_list_to_bytes(certs, certslen, &data, &datalen);
tls_record_set_handshake(record, recordlen, type, NULL, datalen);
return 1;
}
int tls13_record_get_handshake_certificate(const uint8_t *record,
const uint8_t **cert_request_context, size_t *cert_request_context_len,
const uint8_t **cert_list, size_t *cert_list_len)
{
int type;
const uint8_t *p;
size_t len;
if (tls_record_get_handshake(record, &type, &p, &len) != 1) {
error_print();
return -1;
}
if (type != TLS_handshake_certificate) {
error_print();
return -1;
}
if (tls_uint8array_from_bytes(cert_request_context, cert_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 == NULL) {
error_print();
return -1;
}
return 1;
}
// 13. certificate_request
/*
struct {
opaque certificate_request_context<0..2^8-1>;
Extension extensions<2..2^16-1>;
} CertificateRequest;
extensiosns:
Extension signature_algorithms MUST be specified
*/
int tls13_record_set_handshake_certificate_request(uint8_t *record, size_t *recordlen,
const uint8_t *request_context, size_t request_context_len,
const uint8_t *exts, size_t extslen)
{
int type = TLS_handshake_certificate_request;
uint8_t *data;
size_t datalen = 0;
if (!record || !recordlen) {
error_print();
return -1;
}
data = tls_handshake_data(tls_record_data(record));
tls_uint8array_to_bytes(request_context, request_context_len, &data, &datalen);
tls_uint16array_to_bytes(exts, extslen, &data, &datalen);
tls_record_set_handshake(record, recordlen, type, NULL, datalen);
return 1;
}
int tls13_record_set_handshake_certificate_request_default(uint8_t *record, size_t *recordlen)
{
int sig_algs[] = { TLS_sig_sm2sig_sm3 };
uint8_t exts[256];
uint8_t *p = exts;
size_t extslen = 0;
tls_signature_algorithms_ext_to_bytes(sig_algs, sizeof(sig_algs)/sizeof(int), &p, &extslen);
tls13_record_set_handshake_certificate_request(record, recordlen, NULL, 0, exts, extslen);
return 1;
}
int tls13_record_get_handshake_certificate_request(const uint8_t *record,
const uint8_t **requst_context, size_t *request_context_len,
const uint8_t **exts, size_t *exts_len)
{
int type;
const uint8_t *p;
size_t len;
if (tls_record_get_handshake(record, &type, &p, &len) != 1) {
error_print();
return -1;
}
if (type != TLS_handshake_certificate_request) {
error_print();
return -1;
}
if (tls_uint8array_from_bytes(requst_context, request_context_len, &p, &len) != 1
|| tls_uint16array_from_bytes(exts, exts_len, &p, &len) != 1
|| tls_length_is_zero(len) != 1) {
error_print();
return -1;
}
return 1;
}
/*
handshake #15
struct {
SignatureScheme algorithm;
opaque signature<0..2^16-1>;
} CertificateVerify;
*/
int tls13_record_set_handshake_certificate_verify(uint8_t *record, size_t *recordlen,
int sig_alg, const uint8_t *sig, size_t siglen)
{
int type = TLS_handshake_certificate_verify;
uint8_t *p = record + 5 + 4; // 这里都应该改为tls_record_handshake_data
size_t len = 0;
if (!tls_signature_scheme_name(sig_alg)) {
error_print();
return -1;
}
tls_uint16_to_bytes((uint16_t)sig_alg, &p, &len);
tls_uint16array_to_bytes(sig, siglen, &p, &len);
if (tls_record_set_handshake_header(record, recordlen, type, len) != 1) {
error_print();
return -1;
}
return 1;
}
int tls13_record_get_handshake_certificate_verify(const uint8_t *record,
int *sig_alg, const uint8_t **sig, size_t *siglen)
{
int type;
const uint8_t *cp;
size_t len ;
uint16_t alg;
if (tls_record_get_handshake(record, &type, &cp, &len) != 1) {
error_print();
return -1;
}
if (type != TLS_handshake_certificate_verify) {
return 0;
}
if (tls_uint16_from_bytes(&alg, &cp, &len) != 1
|| tls_uint16array_from_bytes(sig, siglen, &cp, &len) != 1) {
error_print();
return -1;
}
if (!tls_signature_scheme_name(alg)) {
error_print();
return -1;
}
*sig_alg = alg;
return 1;
}
// 20. finished
/*
finished_key = HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)
struct {
opaque verify_data[Hash.length];
} Finished;
verify_data = HMAC(finished_key, Hash(Handshake Context, Certificate*, CertificateVerify*))
Hash = SM3, SHA256 or SHA384
*/
int tls13_record_set_handshake_finished(uint8_t *record, size_t *recordlen,
const uint8_t *verify_data, size_t verify_data_len)
{
int type = TLS_handshake_finished;
if (!verify_data || !verify_data_len) {
error_print();
return -1;
}
if (verify_data_len != 32) {
error_print();
return -1;
}
if (tls_record_set_handshake(record, recordlen, type, verify_data, verify_data_len) != 1) {
error_print();
return -1;
}
return 1;
}
int tls13_record_get_handshake_finished(const uint8_t *record,
const uint8_t **verify_data, size_t *verify_data_len)
{
int type;
if (tls_record_get_handshake(record, &type, verify_data, verify_data_len) != 1) {
error_print();
return -1;
}
if (type != TLS_handshake_finished) {
return 0;
}
if (*verify_data_len == 0) {
error_print();
return -1;
}
return 1;
}
// 24. key_update
int tls13_record_set_handshake_key_update(uint8_t *record, size_t *recordlen,
int request_update)
{
int type = TLS_handshake_key_update;
uint8_t data[1]; // 这个值不太好
data[0] = request_update ? 1 : 0;
if (tls_record_set_handshake(record, recordlen, type, data, sizeof(data)) != 1) {
error_print();
return -1;
}
return 1;
}
int tls13_record_get_handshake_key_update(uint8_t *record, size_t *recordlen,
int *request_update)
{
int type;
const uint8_t *cp;
size_t len;
if (tls_record_get_handshake(record, &type, &cp, &len) != 1) {
error_print();
return -1;
}
if (type != TLS_handshake_key_update) {
return 0;
}
if (len != 1) {
error_print();
return -1;
}
switch (cp[0]) {
case 0:
*request_update = 0;
break;
case 1:
*request_update = 1;
break;
default:
error_print();
return -1;
}
return 1;
}
// 254. message_hash
int tls13_record_set_message_hash(uint8_t *record, size_t *recordlen)
{
return -1;
}
int tls13_record_get_message_hash(uint8_t *record, size_t *recordlen)
{
return -1;
}
/*
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_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 *p = exts;
size_t extslen = 0;
size_t i;
tls_trace("send ClientHello\n");
// record_version
tls_record_set_protocol(conn->record, TLS_protocol_tls1);
if (rand_bytes(conn->client_random, 32) != 1) {
error_print();
return -1;
}
// legacy_session_id
conn->session_id_len = 0;
// key_share
if (!conn->key_exchanges_cnt || conn->key_exchanges_cnt >
sizeof(conn->key_exchanges)/sizeof(conn->key_exchanges[0])) {
error_print();
return -1;
}
for (i = 0; i < conn->ctx->supported_groups_cnt && i < conn->key_exchanges_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();
tls_send_alert(conn, TLS_alert_internal_error);
return -1;
}
}
// extensions
if (tls13_client_supported_versions_ext_to_bytes(conn->ctx->supported_versions,
conn->ctx->supported_versions_cnt, &p, &extslen) != 1
|| tls_supported_groups_ext_to_bytes(conn->ctx->supported_groups,
conn->ctx->supported_groups_cnt, &p, &extslen) != 1
|| tls13_key_share_client_hello_ext_to_bytes(conn->key_exchanges,
conn->key_exchanges_cnt, &p, &extslen) != 1
|| tls_signature_algorithms_ext_to_bytes(conn->ctx->signature_algorithms,
conn->ctx->signature_algorithms_cnt, &p, &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);
}
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;
}
// backup ClientHello record for handshake message digest
memcpy(conn->plain_record, conn->record, conn->recordlen);
conn->plain_recordlen = conn->recordlen;
tls_clean_record(conn);
return 1;
}
int tls13_recv_hello_retry_request(TLS_CONNECT *conn)
{
int ret;
// handshake
int handshake_type;
const uint8_t *handshake_data;
size_t handshake_datalen;
// 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;
int legacy_compress_meth;
const uint8_t *exts;
size_t extslen;
// extensions
int selected_version = -1;
int key_share_group = -1;
const uint8_t *cookie = NULL;
size_t cookielen = 0;
tls_trace("recv HelloRetryRequest*\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
if (tls_record_protocol(conn->record) != TLS_protocol_tls12) {
error_print();
tls_send_alert(conn, TLS_alert_protocol_version);
return -1;
}
// is ServerHello ?
if (tls_record_get_handshake(conn->record,
&handshake_type, &handshake_data, &handshake_datalen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
}
if (handshake_type == TLS_handshake_server_hello) {
tls_trace(" no HelloRetryRequest\n");
return 0;
}
// HelloRetryRequest
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)) < 0) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
conn->hello_retry_request = 1;
// legacy_version
if (legacy_version != TLS_protocol_tls12) {
error_print();
tls_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();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
// cipher_suite
if (tls_type_is_in_list(cipher_suite, conn->cipher_suites, conn->cipher_suites_cnt) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
conn->cipher_suite = cipher_suite;
if (tls13_cipher_suite_get(cipher_suite, &conn->cipher, &conn->digest) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_internal_error);
return -1;
}
// legacy_compression_method
if (legacy_compress_meth != 0) {
error_print();
tls_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();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
}
switch (ext_type) {
case TLS_extension_supported_versions:
// 这里都没有判断扩展是否重复
if (tls13_server_supported_versions_from_bytes(&selected_version,
ext_data, ext_datalen) != 1) {
tls_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();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (selected_version != TLS_protocol_tls13) {
error_print();
tls_send_alert(conn, TLS_alert_internal_error);
return -1;
}
break;
case TLS_extension_key_share:
if (tls13_key_share_hello_retry_request_from_bytes(&key_share_group,
ext_data, ext_datalen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
}
if (tls_type_is_in_list(key_share_group, conn->ctx->supported_groups, conn->ctx->supported_groups_cnt) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
conn->key_exchange_group = key_share_group;
break;
case TLS_extension_cookie:
if (tls13_cookie_from_bytes(&cookie, &cookielen, ext_data, ext_datalen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
}
memcpy(conn->cookie, cookie, cookielen);
conn->cookielen = cookielen;
break;
// extensions MUST NOT be included
case TLS_extension_supported_groups:
case TLS_extension_signature_algorithms:
case TLS_extension_server_name:
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
break;
// extensions can be ignored
case TLS_extension_pre_shared_key:
default:
warning_print();
}
}
if (selected_version < 0) {
error_print();
tls_send_alert(conn, TLS_alert_missing_extension);
return -1;
}
if (key_share_group < 0) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
// 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;
digest_init(&conn->dgst_ctx, conn->digest);
digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5);
digest_finish(&conn->dgst_ctx, message_hash + 4, &dgstlen);
// ClientHello, HelloRetryRequest
digest_init(&conn->dgst_ctx, conn->digest);
digest_update(&conn->dgst_ctx, message_hash, sizeof(message_hash));
digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5);
if (conn->client_certs_len) {
sm2_sign_update(&conn->sign_ctx, conn->record + 5, conn->recordlen - 5);
}
return 1;
}
int tls13_send_client_hello_again(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 *p = 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);
// re-generate client_random
if (rand_bytes(conn->client_random, 32) != 1) {
error_print();
return -1;
}
// re-generate key_share
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();
tls_send_alert(conn, TLS_alert_internal_error);
return -1;
}
conn->key_exchange_idx = 0;
conn->key_exchanges_cnt = 1;
// extensions
if (tls13_client_supported_versions_ext_to_bytes(conn->ctx->supported_versions,
conn->ctx->supported_versions_cnt, &p, &extslen) != 1
|| tls_supported_groups_ext_to_bytes(
conn->ctx->supported_groups, conn->ctx->supported_groups_cnt, &p, &extslen) != 1
|| tls13_key_share_client_hello_ext_to_bytes(
conn->key_exchanges, conn->key_exchanges_cnt, &p, &extslen) != 1
|| tls_signature_algorithms_ext_to_bytes(
conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt, &p, &extslen) != 1) {
error_print();
return -1;
}
if (conn->cookielen) {
if (tls13_cookie_ext_to_bytes(conn->cookie, conn->cookielen, &p, &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;
}
tls_trace("send ClientHello again\n");
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
// ClientHello2
digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5);
}
if (conn->client_certificate_verify) {
sm2_sign_update(&conn->sign_ctx, conn->record + 5, conn->recordlen - 5);
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
tls_clean_record(conn);
return 1;
}
int 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;
// supported_versions
int selected_version = 0;
// supported_groups
int group = 0;
const uint8_t *key_exchange = NULL;
size_t key_exchange_len = 0;
tls_trace("recv ServerHello\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
if (tls_record_protocol(conn->record) != TLS_protocol_tls12) {
error_print();
tls_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();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
// legacy_version
if (legacy_version != TLS_protocol_tls12) {
error_print();
tls_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();
tls_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();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
conn->cipher_suite = cipher_suite;
if (tls13_cipher_suite_get(cipher_suite, &conn->cipher, &conn->digest) != 1) {
error_print();
tls_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();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
}
switch (ext_type) {
case TLS_extension_supported_versions:
if (selected_version) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (tls13_server_supported_versions_from_bytes(
&selected_version, ext_data, ext_datalen) != 1) {
tls_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();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (selected_version != TLS_protocol_tls13) {
error_print();
tls_send_alert(conn, TLS_alert_internal_error);
return -1;
}
conn->protocol = selected_version;
break;
case TLS_extension_key_share:
if (group) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (tls13_key_share_server_hello_from_bytes(
&group, &key_exchange, &key_exchange_len, ext_data, ext_datalen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
}
while (conn->key_exchange_idx < conn->key_exchanges_cnt) {
if (conn->key_exchanges[conn->key_exchange_idx].algor_param ==
tls_named_curve_oid(group)) {
break;
}
conn->key_exchange_idx++;
}
if (conn->key_exchange_idx >= conn->key_exchanges_cnt) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (key_exchange_len != 65) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
conn->key_exchange_group = group;
memcpy(conn->peer_key_exchange, key_exchange, key_exchange_len);
conn->peer_key_exchange_len = 65;
break;
// extensions MUST NOT exist
case TLS_extension_supported_groups:
case TLS_extension_signature_algorithms:
case TLS_extension_server_name:
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
break;
// extensions can be ignored
case TLS_extension_pre_shared_key:
default:
warning_print();
}
}
// ClientHello must contain supported_versions and key_share
if (!selected_version || !group) {
error_print();
tls_send_alert(conn, TLS_alert_missing_extension);
return -1;
}
if (!conn->hello_retry_request) {
if (digest_init(&conn->dgst_ctx, conn->digest) != 1
|| digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
}
if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_internal_error);
return -1;
}
// 这里怎么没有更新服务器的seq_num
if (conn->client_certs_len) {
sm2_sign_update(&conn->sign_ctx, conn->record + 5, conn->recordlen - 5);
}
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_keys(TLS_CONNECT *conn)
{
uint8_t zeros[32] = {0};
uint8_t psk[32] = {0};
uint8_t early_secret[32];
uint8_t handshake_secret[32];
uint8_t pre_master_secret[32];
size_t pre_master_secret_len;
uint8_t client_write_key[16];
uint8_t server_write_key[16];
DIGEST_CTX null_dgst_ctx;
printf("generate handshake secrets\n");
/*
generate handshake keys
uint8_t client_write_key[32]
uint8_t server_write_key[32]
uint8_t client_write_iv[12]
uint8_t server_write_iv[12]
*/
if (x509_key_exchange(&conn->key_exchanges[conn->key_exchange_idx],
conn->peer_key_exchange, conn->peer_key_exchange_len,
pre_master_secret, &pre_master_secret_len) != 1) {
error_print();
return -1;
}
digest_init(&null_dgst_ctx, conn->digest);
{
DIGEST_CTX tmp_dgst_ctx = conn->dgst_ctx;
uint8_t dgst[32] = {0};
size_t dgstlen;
digest_finish(&tmp_dgst_ctx, dgst, &dgstlen);
format_bytes(stderr, 0, 0, "dgst_ctx", dgst, dgstlen);
}
/* [1] */ tls13_hkdf_extract(conn->digest, zeros, psk, early_secret);
/* [5] */ tls13_derive_secret(early_secret, "derived", &null_dgst_ctx, handshake_secret);
/* [6] */ tls13_hkdf_extract(conn->digest, handshake_secret, pre_master_secret, handshake_secret);
/* [7] */ tls13_derive_secret(handshake_secret, "c hs traffic", &conn->dgst_ctx, conn->client_handshake_traffic_secret);
/* [8] */ tls13_derive_secret(handshake_secret, "s hs traffic", &conn->dgst_ctx, conn->server_handshake_traffic_secret);
/* [9] */ tls13_derive_secret(handshake_secret, "derived", &null_dgst_ctx, conn->master_secret);
/* [10] */ tls13_hkdf_extract(conn->digest, conn->master_secret, zeros, conn->master_secret);
//[sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length)
//[sender]_write_iv = HKDF-Expand-Label(Secret, "iv", "", iv_length)
//[sender] in {server, client}
tls13_hkdf_expand_label(conn->digest, conn->server_handshake_traffic_secret, "key", NULL, 0, 16, server_write_key);
block_cipher_set_encrypt_key(&conn->server_write_key, conn->cipher, server_write_key);
tls13_hkdf_expand_label(conn->digest, conn->server_handshake_traffic_secret, "iv", NULL, 0, 12, conn->server_write_iv);
tls_seq_num_reset(conn->server_seq_num);
tls13_hkdf_expand_label(conn->digest, conn->client_handshake_traffic_secret, "key", NULL, 0, 16, client_write_key);
block_cipher_set_encrypt_key(&conn->client_write_key, conn->cipher, client_write_key);
tls13_hkdf_expand_label(conn->digest, conn->client_handshake_traffic_secret, "iv", NULL, 0, 12, conn->client_write_iv);
tls_seq_num_reset(conn->client_seq_num);
format_bytes(stderr, 0, 4, "client_write_key", client_write_key, 16);
format_bytes(stderr, 0, 4, "server_write_key", server_write_key, 16);
format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, 12);
format_bytes(stderr, 0, 4, "server_write_iv", conn->server_write_iv, 12);
format_print(stderr, 0, 0, "\n");
return 1;
}
int tls13_recv_encrypted_extensions(TLS_CONNECT *conn)
{
int ret;
const uint8_t *exts;
size_t extslen;
int supported_groups[1];
size_t supported_groups_cnt = 0;
printf("recv {EncryptedExtensions}\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
if (tls13_record_decrypt(&conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->record, conn->recordlen,
conn->plain_record, &conn->plain_recordlen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
if ((ret = tls13_record_get_handshake_encrypted_extensions(conn->plain_record,
&exts, &extslen)) < 0) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
while (extslen) {
int ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
}
switch (ext_type) {
case TLS_extension_supported_groups:
if (supported_groups_cnt) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
// check ServerHello.exts.key_share.group in supported_groups
if (tls_process_supported_groups(ext_data, ext_datalen,
&conn->key_exchange_group, 1,
supported_groups, &supported_groups_cnt, 1) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
break;
case TLS_extension_early_data:
if (ext_datalen) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
conn->early_data = 1;
break;
// extensions must not be included
case TLS_extension_supported_versions:
case TLS_extension_key_share:
case TLS_extension_psk_key_exchange_modes:
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
case TLS_extension_server_name:
case TLS_extension_application_layer_protocol_negotiation:
case TLS_extension_record_size_limit:
case TLS_extension_client_certificate_type:
case TLS_extension_server_certificate_type:
case TLS_extension_use_srtp:
case TLS_extension_padding:
case TLS_extension_signed_certificate_timestamp:
case TLS_extension_status_request:
default:
// ignore
warning_print();
}
}
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
return 1;
}
int tls13_recv_certificate_request(TLS_CONNECT *conn)
{
int ret;
int handshake_type;
const uint8_t *handshake_data;
size_t handshake_datalen;
// 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;
const uint8_t *certs;
size_t certslen;
const uint8_t *cert;
size_t certlen;
X509_KEY client_sign_key;
int sig_alg_oid;
int sig_algs[4];
size_t sig_algs_cnt = 0;
int common_sig_alg;
size_t common_sig_alg_cnt;
tls_trace("recv {CertificateRequest*}\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
if (tls13_record_decrypt(&conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->record, conn->recordlen,
conn->plain_record, &conn->plain_recordlen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
if (tls_record_get_handshake(conn->plain_record,
&handshake_type, &handshake_data, &handshake_datalen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
}
if (handshake_type == TLS_handshake_certificate) {
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)) < 0) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return 0;
}
conn->certificate_request = 1;
// request_context must be null in full/initial handshake
// and must not be null in post authentication handshakes
if (request_context) {
error_print();
tls_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();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
}
switch (ext_type) {
case TLS_extension_signature_algorithms:
if (signature_algorithms) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
signature_algorithms = ext_data;
signature_algorithms_len = ext_datalen;
break;
case TLS_extension_signature_algorithms_cert:
if (signature_algorithms_cert) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
signature_algorithms_cert = ext_data;
signature_algorithms_cert_len = ext_datalen;
break;
case TLS_extension_certificate_authorities:
if (certificate_authorities) {
error_print();
tls_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();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
oid_filters = ext_data;
oid_filters_len = ext_datalen;
break;
default:
error_print();
return -1;
}
}
if (!conn->client_certs_len) {
error_print();
tls_send_alert(conn, TLS_alert_certificate_unobtainable);
return -1;
}
certs = conn->client_certs;
certslen = conn->client_certs_len;
// TODO: select client's certificate based on the extensions
// currently the client's certificate has been set.
// we need to check if the certificate match the extensions
// signature_algorithms
if (!signature_algorithms) {
error_print();
tls_send_alert(conn, TLS_alert_missing_extension);
return -1;
}
if (x509_certs_get_cert_by_index(certs, certslen, 0, &cert, &certlen) != 1
|| x509_cert_get_subject_public_key(cert, certlen, &client_sign_key) != 1) {
error_print();
return -1;
}
if (x509_key_get_sign_algor(&client_sign_key, &sig_alg_oid) != 1) {
error_print();
return -1;
}
switch (sig_alg_oid) {
case OID_sm2sign_with_sm3:
sig_algs[0] = TLS_sig_sm2sig_sm3;
sig_algs_cnt = 1;
break;
case OID_ecdsa_with_sha256:
sig_algs[0] = TLS_sig_ecdsa_secp256r1_sha256;
//sig_algs[1] = TLS_sig_ecdsa_secp256r1_sha384;
sig_algs_cnt = 1;
break;
default:
error_print();
return -1;
}
if (tls_process_signature_algorithms(signature_algorithms, signature_algorithms_len,
sig_algs, sig_algs_cnt, &common_sig_alg, &common_sig_alg_cnt, 1) != 1) {
error_print();
return -1;
}
// signature_algorithms_cert, certificate_authorities, oid_filters
while (certslen) {
if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1) {
error_print();
return -1;
}
if (signature_algorithms_cert) {
int sig_alg_cert_oid;
int sig_alg_cert;
if (x509_cert_get_signature_algor(cert, certlen, &sig_alg_cert_oid) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_internal_error);
return -1;
}
sig_alg_cert = tls_signature_scheme_from_oid(sig_alg_cert_oid);
if (tls_process_signature_algorithms(
signature_algorithms_cert, signature_algorithms_cert_len,
&sig_alg_cert, 1, &common_sig_alg, &common_sig_alg_cnt, 1) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_certificate_unobtainable);
return -1;
}
}
if (certificate_authorities) {
if (tls_authorities_issued_certificate(certificate_authorities,
certificate_authorities_len, cert, certlen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_certificate_unobtainable);
return -1;
}
}
if (oid_filters) {
// TODO
}
}
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
return 1;
}
int tls13_recv_server_certificate(TLS_CONNECT *conn)
{
int ret;
const uint8_t *request_context;
size_t request_context_len;
const uint8_t *cert_list;
size_t cert_list_len;
const uint8_t *cert;
size_t certlen;
X509_KEY server_sign_key;
tls_trace("recv {Certificate}\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
// decrypt unless previous handshake is CertificateRequest
if (!conn->plain_recordlen) {
if (tls13_record_decrypt(&conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->record, conn->recordlen,
conn->plain_record, &conn->plain_recordlen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
if ((ret = tls13_record_get_handshake_certificate(conn->plain_record,
&request_context, &request_context_len,
&cert_list, &cert_list_len)) < 0) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return 0;
}
// TLS 1.3中证书列表是由CertificateListEntry构成的
// 其中包含一个证书和若干的扩展
/*
CertificateListEntry中没有必选的扩展
可选的扩展包括status_request, signed_certificate_timestamp
不能存在的扩展certificate_authoritiesserver_name
*/
if (tls13_process_certificate_list(cert_list, cert_list_len,
conn->server_certs, &conn->server_certs_len) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
if (x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 0, &cert, &certlen) != 1
|| x509_cert_get_subject_public_key(cert, certlen, &server_sign_key) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
// 要判断服务器的证书的公钥类型和客户端匹配了
if (server_sign_key.algor != OID_ec_public_key
|| server_sign_key.algor_param != OID_sm2) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5);
tls_seq_num_incr(conn->server_seq_num);
// verify ServerCertificate
int verify_result = 0; // TODO: maybe remove this arg from x509_certs_verify()
if (x509_certs_verify(conn->server_certs, conn->server_certs_len, X509_cert_chain_server,
conn->ca_certs, conn->ca_certs_len, X509_MAX_VERIFY_DEPTH, &verify_result) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
return 1;
}
int tls13_recv_certificate_verify(TLS_CONNECT *conn)
{
int ret;
int sig_alg;
const uint8_t *sig;
size_t siglen;
X509_KEY server_key;
const uint8_t *cert;
size_t certlen;
tls_trace("recv {CertificateVerify}\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
if (tls13_record_decrypt(&conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->record, conn->recordlen,
conn->plain_record, &conn->plain_recordlen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
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();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
// sig_alg in ClientHello.signature_algorithms
if (tls_type_is_in_list(sig_alg, conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
// sig_alg match server's certificate
if (x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 0, &cert, &certlen) != 1
|| x509_cert_get_subject_public_key(cert, certlen, &server_key) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
switch (server_key.algor_param) {
case OID_sm2:
if (sig_alg != TLS_sig_sm2sig_sm3) {
error_print();
return -1;
}
break;
case OID_secp256r1:
if (sig_alg != TLS_sig_ecdsa_secp256r1_sha256) {
error_print();
return -1;
}
break;
default:
error_print();
return -1;
}
// verify signature
if (tls13_verify_certificate_verify(TLS_server_mode,
&server_key, TLS13_SM2_ID, TLS13_SM2_ID_LENGTH,
&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;
}
tls_seq_num_incr(conn->server_seq_num);
return 1;
}
int tls13_recv_server_finished(TLS_CONNECT *conn)
{
int ret;
const uint8_t *server_verify_data;
size_t server_verify_data_len;
uint8_t verify_data[64];
size_t verify_data_len;
uint8_t server_write_key[16];
// compute verify_data before digest_update
if (tls13_compute_verify_data(conn->server_handshake_traffic_secret,
&conn->dgst_ctx, verify_data, &verify_data_len) != 1) {
error_print();
return -1;
}
tls_trace("recv {Finished}\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
if (tls13_record_decrypt(&conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->record, conn->recordlen,
conn->plain_record, &conn->plain_recordlen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
if ((ret = tls13_record_get_handshake_finished(conn->plain_record,
&server_verify_data, &server_verify_data_len)) < 0) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
if (server_verify_data_len != verify_data_len
|| memcmp(server_verify_data, verify_data, verify_data_len) != 0) {
error_print();
tls_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
// generate client_application_traffic_secret
/* [11] */ tls13_derive_secret(conn->master_secret, "c ap traffic", &conn->dgst_ctx, conn->client_application_traffic_secret);
// generate server_application_traffic_secret
/* [12] */ tls13_derive_secret(conn->master_secret, "s ap traffic", &conn->dgst_ctx, conn->server_application_traffic_secret);
// update server_write_key, server_write_iv, reset server_seq_num
tls13_hkdf_expand_label(conn->digest, conn->server_application_traffic_secret, "key", NULL, 0, 16, server_write_key);
block_cipher_set_encrypt_key(&conn->server_write_key, conn->cipher, server_write_key);
tls13_hkdf_expand_label(conn->digest, conn->server_application_traffic_secret, "iv", NULL, 0, 12, conn->server_write_iv);
tls_seq_num_reset(conn->server_seq_num);
format_print(stderr, 0, 0, "update server secrets\n");
format_bytes(stderr, 0, 4, "server_write_key", server_write_key, 16);
format_bytes(stderr, 0, 4, "server_write_iv", conn->server_write_iv, 12);
format_print(stderr, 0, 0, "\n");
tls_seq_num_reset(conn->server_seq_num);
return 1;
}
int tls13_send_client_certificate(TLS_CONNECT *conn)
{
int ret;
int client_sign_algor;
uint8_t sig[TLS_MAX_SIGNATURE_SIZE];
size_t siglen;
size_t padding_len;
tls_trace("send {Certificate*}\n");
const uint8_t *request_context = NULL;
size_t request_context_len = 0;
const uint8_t *exts;
size_t extslen = 0;
if (tls13_record_set_handshake_certificate(conn->plain_record, &conn->plain_recordlen,
request_context, request_context_len,
conn->client_certs, conn->client_certs_len,
exts, extslen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_internal_error);
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
tls13_padding_len_rand(&padding_len);
format_bytes(stderr, 0, 0, "client_seq_num", conn->client_seq_num, 8);
if (tls13_record_encrypt(&conn->client_write_key, conn->client_write_iv,
conn->client_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
return -1;
}
if (tls_record_send(conn->record, conn->recordlen, conn->sock) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_internal_error);
return -1;
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5);
tls_seq_num_incr(conn->client_seq_num);
return 1;
}
int tls13_send_certificate_verify(TLS_CONNECT *conn)
{
int ret;
int sig_alg;
uint8_t sig[256];
size_t siglen;
size_t padding_len;
tls_trace("send {CertificateVerify*}\n");
switch (conn->sign_key.algor_param) {
case OID_sm2:
sig_alg = TLS_sig_sm2sig_sm3;
break;
case OID_secp256r1:
sig_alg = TLS_sig_ecdsa_secp256r1_sha256;
break;
default:
error_print();
return -1;
}
tls13_sign_certificate_verify(TLS_client_mode,
&conn->sign_key.u.sm2_key, TLS13_SM2_ID, TLS13_SM2_ID_LENGTH,
&conn->dgst_ctx, sig, &siglen);
if (tls13_record_set_handshake_certificate_verify(
conn->plain_record, &conn->plain_recordlen,
sig_alg, sig, siglen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_internal_error);
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);
format_bytes(stderr, 0, 0, "client_seq_num", conn->client_seq_num, 8);
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(&conn->client_write_key, conn->client_write_iv,
conn->client_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_internal_error);
return -1;
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
tls_seq_num_incr(conn->client_seq_num);
return 1;
}
int tls13_send_client_finished(TLS_CONNECT *conn)
{
int ret;
uint8_t verify_data[64];
size_t verify_data_len;
size_t padding_len;
uint8_t client_write_key[16];
tls_trace("send {Finished}\n");
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();
tls_send_alert(conn, TLS_alert_internal_error);
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);
format_bytes(stderr, 0, 0, "client_seq_num", conn->client_seq_num, 8);
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(&conn->client_write_key, conn->client_write_iv,
conn->client_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_internal_error);
return -1;
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
tls_seq_num_incr(conn->client_seq_num);
//update client_write_key, client_write_iv, reset client_seq_num
tls13_hkdf_expand_label(conn->digest, conn->client_application_traffic_secret, "key", NULL, 0, 16, client_write_key);
tls13_hkdf_expand_label(conn->digest, conn->client_application_traffic_secret, "iv", NULL, 0, 12, conn->client_write_iv);
block_cipher_set_encrypt_key(&conn->client_write_key, conn->cipher, client_write_key);
tls_seq_num_reset(conn->client_seq_num);
format_print(stderr, 0, 0, "update client secrets\n");
format_bytes(stderr, 0, 4, "client_write_key", client_write_key, 16);
format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, 12);
format_print(stderr, 0, 0, "\n");
return 1;
}
int tls13_recv_client_hello(TLS_CONNECT *conn)
{
int ret;
uint8_t *record = conn->record;
size_t recordlen;
int client_verify = 0;
int protocol;
// client_hello
int legacy_version;
const uint8_t *random;
const uint8_t *legacy_session_id;
size_t legacy_session_id_len;
const uint8_t *cipher_suites;
size_t cipher_suites_len;
const uint8_t *legacy_comp_methods;
size_t legacy_comp_methods_len;
const uint8_t *exts;
size_t extslen;
// supported_versions ext
int supported_versions[4];
size_t supported_versions_cnt = 0;
// supported_groups ext
int supported_groups[4];
size_t supported_groups_cnt = 0;
// key_share ext
const uint8_t *key_share = NULL;
size_t key_share_len = 0;
int group = 0;
const uint8_t *key_exchange = NULL;
size_t key_exchange_len = 0;
// 这个判断应该改为一个函数
/*
if (client_verify)
tls_client_verify_init(&conn->client_verify_ctx);
*/
tls_trace("recv ClientHello\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
if (tls_record_protocol(record) != TLS_protocol_tls1) {
error_print();
tls_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();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
// legacy_version
if (legacy_version != TLS_protocol_tls12) {
error_print();
tls_send_alert(conn, TLS_alert_protocol_version);
return -1;
}
// random
memcpy(conn->client_random, random, 32);
// legacy_session_id
if (legacy_session_id_len) {
// tls13 server ignore legacy_session_id
warning_print();
}
// cipher_suites
if ((ret = tls_cipher_suites_select(cipher_suites, cipher_suites_len,
conn->cipher_suites, conn->cipher_suites_cnt,
&conn->cipher_suite)) < 0) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls_send_alert(conn, TLS_alert_handshake_failure);
return -1;
}
format_print(stderr, 0, 0, "cipher_suite: %s\n", tls_cipher_suite_name(conn->cipher_suite));
tls13_cipher_suite_get(conn->cipher_suite, &conn->cipher, &conn->digest);
while (extslen) {
int ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
}
if (!ext_datalen) {
// following extensions should not be empty
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
}
switch (ext_type) {
case TLS_extension_supported_versions:
if (supported_versions_cnt) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if ((ret = tls13_process_client_supported_versions(ext_data, ext_datalen,
conn->ctx->supported_versions, conn->ctx->supported_versions_cnt,
supported_versions, &supported_versions_cnt,
sizeof(supported_versions)/sizeof(supported_versions[0]))) < 0) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls_send_alert(conn, TLS_alert_protocol_version);
return -1;
}
// TODO: supported TLS1.2 and TLCP
if (supported_versions[0] != TLS_protocol_tls13) {
error_print();
tls_send_alert(conn, TLS_alert_protocol_version);
return -1;
}
conn->protocol = supported_versions[0];
break;
case TLS_extension_supported_groups:
if (supported_groups_cnt) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if ((ret = tls_process_supported_groups(ext_data, ext_datalen,
conn->ctx->supported_groups, conn->ctx->supported_groups_cnt,
supported_groups, &supported_groups_cnt,
sizeof(supported_groups)/sizeof(supported_groups[0]))) < 0) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls_send_alert(conn, TLS_alert_handshake_failure);
return -1;
}
break;
case TLS_extension_key_share:
if (key_share) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
key_share = ext_data;
key_share_len = ext_datalen;
break;
case TLS_extension_signature_algorithms:
if (conn->signature_algorithms_cnt) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if ((ret = tls_process_signature_algorithms(ext_data, ext_datalen,
conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt,
conn->signature_algorithms, &conn->signature_algorithms_cnt,
sizeof(conn->signature_algorithms)/sizeof(conn->signature_algorithms[0]))) < 0) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls_send_alert(conn, TLS_alert_handshake_failure);
return -1;
}
break;
default:
warning_print();
}
}
// supported_versions
if (!supported_versions_cnt) {
error_print();
tls_send_alert(conn, TLS_alert_missing_extension);
return -1;
}
// supported_groups
if (!supported_groups_cnt) {
error_print();
tls_send_alert(conn, TLS_alert_missing_extension);
return -1;
}
// key_share
if (!key_share) {
error_print();
tls_send_alert(conn, TLS_alert_missing_extension);
return -1;
}
if ((ret = tls13_process_key_share_client_hello(key_share, key_share_len,
supported_groups, supported_groups_cnt,
&group, &key_exchange, &key_exchange_len)) < 0) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
// backup ClientHello1
memcpy(conn->plain_record, conn->record, conn->recordlen);
conn->plain_recordlen = conn->recordlen;
conn->key_exchange_group = supported_groups[0];
conn->hello_retry_request = 1;
} else {
if (key_exchange_len != 65) {
error_print();
return -1;
}
conn->key_exchange_group = group;
memcpy(conn->peer_key_exchange, key_exchange, key_exchange_len);
conn->peer_key_exchange_len = key_exchange_len;
}
// signature_algorithms
if (!conn->signature_algorithms_cnt) {
error_print();
tls_send_alert(conn, TLS_alert_missing_extension);
return -1;
}
// 如果服务器支持多个证书链那么应该根据签名算法以及SNI去选择证书链
// 但是目前我们只有一个服务器证书链,因此应该判断服务器的签名算法是否和这个签名算法匹配
// 最好在设置CTX证书的时候把证书的DN和签名算法先提取出来
// 实际上证书中的公钥类型没有办法完全确定签名算法比如ecdsa-p256-sha256 和 ecdsa-p256-sha384公钥类型一样但是签名不同
if (conn->hello_retry_request) {
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;
digest_init(&conn->dgst_ctx, conn->digest);
digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5);
digest_finish(&conn->dgst_ctx, message_hash + 4, &dgstlen);
digest_init(&conn->dgst_ctx, conn->digest);
digest_update(&conn->dgst_ctx, message_hash, sizeof(message_hash));
} else {
digest_init(&conn->dgst_ctx, conn->digest);
digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5);
}
if (client_verify)
tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5);
tls_clean_record(conn);
return 1;
}
/*
如果客户端提供的supported_groups满足服务器的条件也就是有common_gruops
但是客户端发送的key_share里面并没有
这时候服务器要发送HRR消息了
因此recv_client_hello要决定下一个状态变化的状态也就是说我们要有一个conn的状态来记录这个
在初始化的时候客户端提供的supported_groups : secp256r1, sm2
但是key_share中只提供secp256r1
服务器的supported_groups 中只有sm2
*/
int tls13_send_hello_retry_request(TLS_CONNECT *conn)
{
int ret;
tls_trace("send HelloRetryRequest\n");
if (conn->recordlen == 0) {
uint8_t exts[256];
uint8_t *p = exts;
size_t extslen = 0;
int curve_oid;
uint8_t cookie[] = "Cookie from server";
tls_record_set_protocol(conn->record, TLS_protocol_tls12);
if (rand_bytes(conn->server_random, 32) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_internal_error);
return -1;
}
if (tls13_server_supported_versions_ext_to_bytes(TLS_protocol_tls13, &p, &extslen) != 1
|| tls13_key_share_hello_retry_request_ext_to_bytes(conn->key_exchange_group, &p, &extslen) != 1) {
error_print();
return -1;
}
// cookie for testing
if (tls13_cookie_ext_to_bytes(cookie, sizeof(cookie), &p, &extslen) != 1) {
error_print();
return -1;
}
if (tls13_record_set_handshake_hello_retry_request(conn->record, &conn->recordlen,
TLS_protocol_tls12, conn->server_random, NULL, 0,
conn->cipher_suite, exts, extslen) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5);
if (conn->ca_certs_len) {
tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5);
}
tls_clean_record(conn);
return 1;
return 1;
}
int tls13_recv_client_hello_again(TLS_CONNECT *conn)
{
int ret;
uint8_t *record = conn->record;
size_t recordlen;
int client_verify = 0;
int protocol;
// ClientHello2
int legacy_version;
const uint8_t *random;
const uint8_t *legacy_session_id;
size_t legacy_session_id_len;
const uint8_t *cipher_suites;
size_t cipher_suites_len;
const uint8_t *legacy_comp_methods;
size_t legacy_comp_methods_len;
const uint8_t *exts;
size_t extslen;
const uint8_t *supported_versions = NULL;
size_t supported_versions_len = 0;
const uint8_t *supported_groups = NULL;
size_t supported_groups_len = 0;
const uint8_t *key_share = NULL;
size_t key_share_len = 0;
const uint8_t *key_exchange = NULL;
size_t key_exchange_len = 0;
const uint8_t *signature_algorithms = NULL;
size_t signature_algorithms_len;
// ClientHello1
int _legacy_version;
const uint8_t *_random;
const uint8_t *_legacy_session_id;
size_t _legacy_session_id_len;
const uint8_t *_cipher_suites;
size_t _cipher_suites_len;
const uint8_t *_legacy_comp_methods;
size_t _legacy_comp_methods_len;
const uint8_t *_exts;
size_t _extslen;
const uint8_t *_supported_versions = NULL;
size_t _supported_versions_len = 0;
const uint8_t *_supported_groups = NULL;
size_t _supported_groups_len = 0;
const uint8_t *_signature_algorithms = NULL;
size_t _signature_algorithms_len = 0;
tls_trace("recv ClientHello again\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
if (tls_record_protocol(record) != TLS_protocol_tls1) {
error_print();
tls_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();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
// 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();
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
//|| legacy_comp_methods_len != _legacy_comp_methods_len
//|| memcmp(legacy_comp_methods, _legacy_comp_methods, _legacy_comp_methods_len) != 0
) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
// update random
if (memcmp(random, _random, 32) == 0) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
memcpy(conn->client_random, random, 32);
// ClientHello1 extensions
while (_extslen) {
int _ext_type;
const uint8_t *_ext_data;
size_t _ext_datalen;
if (tls_ext_from_bytes(&_ext_type, &_ext_data, &_ext_datalen, &_exts, &_extslen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
}
switch (_ext_type) {
case TLS_extension_supported_versions:
_supported_versions = _ext_data;
_supported_versions_len = _ext_datalen;
break;
case TLS_extension_supported_groups:
_supported_groups = _ext_data;
_supported_groups_len = _ext_datalen;
break;
case TLS_extension_signature_algorithms:
_signature_algorithms = _ext_data;
_signature_algorithms_len = _ext_datalen;
break;
}
}
// process ClientHello2 extensions
while (extslen) {
int ext_type;
const uint8_t *ext_data;
size_t ext_datalen;
if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_datalen, &exts, &extslen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
}
if (!ext_datalen) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
}
switch (ext_type) {
case TLS_extension_supported_versions:
if (supported_versions) {
error_print();
return -1;
}
if (ext_datalen != _supported_versions_len
|| memcmp(ext_data, _supported_versions, _supported_versions_len) != 0) {
error_print();
return -1;
}
supported_versions = ext_data;
supported_versions_len = ext_datalen;
break;
case TLS_extension_supported_groups:
if (supported_groups
|| ext_datalen != _supported_groups_len
|| memcmp(ext_data, _supported_groups, _supported_groups_len) != 0) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
supported_groups = ext_data;
supported_groups_len = ext_datalen;
break;
case TLS_extension_signature_algorithms:
if (signature_algorithms
|| ext_datalen != _signature_algorithms_len
|| memcmp(ext_data, _signature_algorithms, _signature_algorithms_len) != 0) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
signature_algorithms = ext_data;
signature_algorithms_len = ext_datalen;
break;
case TLS_extension_key_share:
if (key_share) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
key_share = ext_data;
key_share_len = ext_datalen;
break;
// ClientHello2 should not have early_data
case TLS_extension_early_data:
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
}
if (!supported_versions || !supported_groups || !key_share || !signature_algorithms) {
error_print();
tls_send_alert(conn, TLS_alert_missing_extension);
return -1;
}
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();
tls_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;
digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5);
if (client_verify)
tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5);
tls_clean_record(conn);
return 1;
}
int tls13_send_server_hello(TLS_CONNECT *conn)
{
int ret;
tls_trace("send ServerHello\n");
if (conn->recordlen == 0) {
uint8_t exts[256];
uint8_t *p = exts;
size_t extslen = 0;
int curve_oid;
tls_record_set_protocol(conn->record, TLS_protocol_tls12);
if (rand_bytes(conn->server_random, 32) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_internal_error);
return -1;
}
// key_share
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;
}
if (tls13_server_supported_versions_ext_to_bytes(conn->protocol, &p, &extslen) != 1
|| tls13_key_share_server_hello_ext_to_bytes(&conn->key_exchanges[0], &p, &extslen) != 1) {
error_print();
return -1;
}
if (tls_record_set_handshake_server_hello(conn->record, &conn->recordlen,
TLS_protocol_tls12, conn->server_random, NULL, 0,
conn->cipher_suite, exts, extslen) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5);
if (conn->ca_certs_len) {
tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5);
}
tls_clean_record(conn);
return 1;
}
int tls13_send_encrypted_extensions(TLS_CONNECT *conn)
{
int ret;
tls_trace("send {EncryptedExtensions}\n");
if (conn->recordlen == 0) {
uint8_t exts[256];
uint8_t *p = exts;
size_t extslen = 0;
size_t padding_len;
tls_record_set_protocol(conn->plain_record, TLS_protocol_tls12);
// supported_groups
if (tls_supported_groups_ext_to_bytes(conn->ctx->supported_groups,
conn->ctx->supported_groups_cnt, &p, &extslen) != 1) {
error_print();
return -1;
}
// empty early_data
// 需要根据系统的配置决定是否支持0-RTT
if (tls_ext_to_bytes(TLS_extension_early_data, NULL, 0, &p, &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);
tls13_padding_len_rand(&padding_len);
format_bytes(stderr, 0, 0, "server_seq_num", conn->server_seq_num, 8);
if (tls13_record_encrypt(&conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
return -1;
}
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
tls_seq_num_incr(conn->server_seq_num);
if (conn->ca_certs_len) {
tls_client_verify_update(&conn->client_verify_ctx, conn->record + 5, conn->recordlen - 5);
}
tls_clean_record(conn);
return 1;
}
int tls13_send_certificate_request(TLS_CONNECT *conn)
{
int ret;
tls_trace("send {CertificateRequest*}\n");
const uint8_t *request_context = NULL;
size_t request_context_len = 0;
if (conn->recordlen == 0) {
uint8_t ca_names[256];
size_t ca_names_len;
uint8_t exts[256];
uint8_t *p = exts;
size_t extslen = 0;
size_t padding_len;
if (tls_authorities_from_certs(ca_names, &ca_names_len, sizeof(ca_names),
conn->ctx->cacerts, conn->ctx->cacertslen) != 1) {
error_print();
return -1;
}
if (tls_signature_algorithms_ext_to_bytes(
conn->signature_algorithms, conn->signature_algorithms_cnt, &p, &extslen) != 1
|| tls13_signature_algorithms_cert_ext_to_bytes(
conn->signature_algorithms, conn->signature_algorithms_cnt, &p, &extslen) != 1
|| tls13_certificate_authorities_ext_to_bytes(
ca_names, ca_names_len, &p, &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();
tls_send_alert(conn, TLS_alert_internal_error);
return -1;
}
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
format_bytes(stderr, 0, 0, "server_seq_num", conn->server_seq_num, 8);
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(&conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
tls_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;
}
/*
struct {
CertificateStatusType status_type;
select (status_type) {
case ocsp:
OCSPResponse response;
};
} CertificateStatus;
OCSPResponse ::= SEQUENCE {
responseStatus OCSPResponseStatus,
responseBytes [0] EXPLICIT ResponseBytes OPTIONAL
}
OCSPResponseStatus ::= ENUMERATED {
successful (0), -- 响应有效
malformedRequest (1), -- 请求格式错误
internalError (2), -- 服务器内部错误
tryLater (3), -- 稍后重试
-- 状态码 4 未使用
sigRequired (5), -- 必须签名
unauthorized (6) -- 未授权
}
ResponseBytes ::= SEQUENCE {
responseType OBJECT IDENTIFIER,
response OCTET STRING
}
-- 当 responseType 为 id-pkix-ocsp-basic 时response 包含 BasicOCSPResponse
BasicOCSPResponse ::= SEQUENCE {
tbsResponseData ResponseData,
signatureAlgorithm AlgorithmIdentifier,
signature BIT STRING,
certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
}
*/
int tls13_send_server_certificate(TLS_CONNECT *conn)
{
int ret;
tls_trace("send {Certificate}\n");
if (conn->recordlen == 0) {
const uint8_t *request_context = NULL;
size_t request_context_len = 0;
uint8_t exts_list[256];
size_t exts_list_len = 0;
uint8_t exts[128];
uint8_t *p = exts;
size_t extslen = 0;
size_t padding_len;
// CertificateEntry.extensions
if (conn->ctx->certificate_status_len) {
if (tls_ext_to_bytes(TLS_extension_status_request,
conn->ctx->certificate_status, conn->ctx->certificate_status_len,
&p, &extslen) != 1) {
error_print();
return -1;
}
}
if (conn->ctx->signed_certificate_timestamp_len) {
if (tls_ext_to_bytes(TLS_extension_signed_certificate_timestamp,
conn->ctx->signed_certificate_timestamp, conn->ctx->signed_certificate_timestamp_len,
&p, &extslen) != 1) {
error_print();
return -1;
}
}
p = exts_list;
tls_uint16array_to_bytes(exts, extslen, &p, &exts_list_len);
if (tls13_record_set_handshake_certificate(conn->plain_record, &conn->plain_recordlen,
request_context, request_context_len,
conn->server_certs, conn->server_certs_len,
exts_list, exts_list_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);
format_bytes(stderr, 0, 0, "server_seq_num", conn->server_seq_num, 8);
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(&conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
return 1;
}
int tls13_send_server_certificate_verify(TLS_CONNECT *conn)
{
int ret;
tls_trace("send {CertificateVerify}\n");
if (conn->recordlen == 0) {
uint8_t sig[SM2_MAX_SIGNATURE_SIZE];
size_t siglen;
size_t padding_len;
tls13_sign_certificate_verify(TLS_server_mode,
&conn->sign_key.u.sm2_key, TLS13_SM2_ID, TLS13_SM2_ID_LENGTH,
&conn->dgst_ctx, sig, &siglen);
// 服务器的签名算法实际上是由签名密钥决定的,目前签名密钥(曲线)决定了签名算法
// 一个签名算法目前不支持可选的哈希函数,因此这个就决定了
// 这段代码要挪到server_hello后者之后
switch (conn->sign_key.algor_param) {
case OID_sm2:
conn->sig_alg = TLS_sig_sm2sig_sm3;
break;
case OID_secp256r1:
conn->sig_alg = TLS_sig_ecdsa_secp256r1_sha256;
break;
default:
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();
tls_send_alert(conn, TLS_alert_internal_error);
return -1;
}
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
format_bytes(stderr, 0, 0, "server_seq_num", conn->server_seq_num, 8);
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(&conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
return 1;
}
int tls13_send_server_finished(TLS_CONNECT *conn)
{
int ret;
size_t padding_len;
tls_trace("send {Finished}\n");
if (conn->recordlen == 0) {
uint8_t verify_data[64];
size_t verify_data_len;
uint8_t server_write_key[16];
// compute server verify_data before digest_update()
tls13_compute_verify_data(conn->server_handshake_traffic_secret,
&conn->dgst_ctx, verify_data, &verify_data_len);
if (tls13_record_set_handshake_finished(conn->plain_record, &conn->plain_recordlen,
verify_data, verify_data_len) != 1) {
error_print();
return -1;
}
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
format_bytes(stderr, 0, 0, "server_seq_num", conn->server_seq_num, 8);
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(&conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
// Generate client_application_traffic_secret
/* 11 */ tls13_derive_secret(conn->master_secret, "c ap traffic", &conn->dgst_ctx, conn->client_application_traffic_secret);
// generate server_application_traffic_secret
/* 12 */ tls13_derive_secret(conn->master_secret, "s ap traffic", &conn->dgst_ctx, conn->server_application_traffic_secret);
// update server_write_key, server_write_iv, reset server_seq_num
tls13_hkdf_expand_label(conn->digest, conn->server_application_traffic_secret, "key", NULL, 0, 16, server_write_key);
block_cipher_set_encrypt_key(&conn->server_write_key, conn->cipher, server_write_key);
tls13_hkdf_expand_label(conn->digest, conn->server_application_traffic_secret, "iv", NULL, 0, 12, conn->server_write_iv);
tls_seq_num_reset(conn->server_seq_num);
format_print(stderr, 0, 0, "update server secrets\n");
format_bytes(stderr, 0, 4, "server_write_key", server_write_key, 16);
format_bytes(stderr, 0, 4, "server_write_iv", conn->server_write_iv, 12);
format_print(stderr, 0, 0, "\n");
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
return 1;
}
int tls13_recv_client_certificate(TLS_CONNECT *conn)
{
int ret;
size_t padding_len;
tls_trace("recv {Certificate*}\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen);
if (tls_record_protocol(conn->record) != TLS_protocol_tls12) {
error_print();
tls_send_alert(conn, TLS_alert_protocol_version);
return -1;
}
format_bytes(stderr, 0, 0, "client_seq_num", conn->client_seq_num, 8);
if (tls13_record_decrypt(&conn->client_write_key, conn->client_write_iv,
conn->client_seq_num, conn->record, conn->recordlen,
conn->plain_record, &conn->plain_recordlen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
tls13_record_trace(stderr, conn->plain_record, conn->plain_recordlen, 0, 0);
const uint8_t *request_context;
size_t request_context_len;
const uint8_t *cert_list;
size_t cert_list_len;
if ((ret = tls13_record_get_handshake_certificate(conn->plain_record,
&request_context, &request_context_len,
&cert_list, &cert_list_len)) < 0) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return 0;
}
// 这里要处理什么?
if (tls13_process_certificate_list(cert_list, cert_list_len,
conn->server_certs, &conn->server_certs_len) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
/*
if (x509_certs_get_cert_by_index(conn->server_certs, conn->server_certs_len, 0, &cert, &certlen) != 1
|| x509_cert_get_subject_public_key(cert, certlen, &server_sign_key) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
if (x509_cert_get_subject_public_key(cert, certlen, &client_sign_key) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_bad_certificate);
goto end;
}
if (client_sign_key.algor != OID_ec_public_key
|| client_sign_key.algor_param != OID_sm2) {
error_print();
tls_send_alert(conn, TLS_alert_bad_certificate);
goto end;
}
digest_update(&dgst_ctx, record + 5, recordlen - 5);
tls_seq_num_incr(conn->client_seq_num);
// verify client Certificate
int verify_result;
if (x509_certs_verify(conn->client_certs, conn->client_certs_len, X509_cert_chain_client,
conn->ca_certs, conn->ca_certs_len, X509_MAX_VERIFY_DEPTH, &verify_result) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_bad_certificate);
goto end;
}
*/
return 1;
}
/*
struct {
SignatureScheme algorithm;
opaque signature<0..2^16-1>;
} CertificateVerify;
*/
int tls13_recv_client_certificate_verify(TLS_CONNECT *conn)
{
int ret;
// CertificateVerify
int sig_alg;
const uint8_t *sig;
size_t siglen;
tls_trace("recv Client {CertificateVerify*}\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();
tls_send_alert(conn, TLS_alert_protocol_version);
return -1;
}
format_bytes(stderr, 0, 0, "client_seq_num", conn->client_seq_num, 8);
if (tls13_record_decrypt(&conn->client_write_key, conn->client_write_iv,
conn->client_seq_num, conn->record, conn->recordlen,
conn->plain_record, &conn->plain_recordlen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
tls13_record_trace(stderr, conn->plain_record, conn->plain_recordlen, 0, 0);
if ((ret = tls13_record_get_handshake_certificate_verify(conn->plain_record,
&sig_alg, &sig, &siglen)) < 0) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
/*
if (sig_alg != conn->client_sig_alg) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
*/
X509_KEY client_sign_key;
if (tls13_verify_certificate_verify(TLS_client_mode,
&client_sign_key, TLS13_SM2_ID, TLS13_SM2_ID_LENGTH,
&conn->dgst_ctx,sig, siglen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5);
tls_seq_num_incr(conn->client_seq_num);
return 1;
}
int tls13_recv_client_finished(TLS_CONNECT *conn)
{
int ret;
// Finished
uint8_t local_verify_data[64];
size_t local_verify_data_len;
const uint8_t *verify_data;
size_t verify_data_len;
uint8_t client_write_key[16];
tls_trace("recv {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();
tls_send_alert(conn, TLS_alert_protocol_version);
return -1;
}
format_bytes(stderr, 0, 0, "client_seq_num", conn->client_seq_num, 8);
if (tls13_record_decrypt(&conn->client_write_key, conn->client_write_iv,
conn->client_seq_num, conn->record, conn->recordlen,
conn->plain_record, &conn->plain_recordlen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
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();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
} else if (ret == 0) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
if (tls13_compute_verify_data(conn->client_handshake_traffic_secret,
&conn->dgst_ctx, local_verify_data, &local_verify_data_len) != 1) {
error_print();
return -1;
}
if (local_verify_data_len != verify_data_len
|| memcmp(local_verify_data, verify_data, verify_data_len) != 0) {
error_print();
tls_send_alert(conn, TLS_alert_decrypt_error);
return -1;
}
// 这个应该放在哪个位置?
if (digest_update(&conn->dgst_ctx, conn->plain_record + 5, conn->plain_recordlen - 5) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->client_seq_num);
// update client_write_key, client_write_iv, reset client_seq_num
tls13_hkdf_expand_label(conn->digest, conn->client_application_traffic_secret, "key", NULL, 0, 16, client_write_key);
block_cipher_set_encrypt_key(&conn->client_write_key, conn->cipher, client_write_key);
tls13_hkdf_expand_label(conn->digest, conn->client_application_traffic_secret, "iv", NULL, 0, 12, conn->client_write_iv);
tls_seq_num_reset(conn->client_seq_num);
format_print(stderr, 0, 0, "update client secrets\n");
format_bytes(stderr, 0, 4, "client_write_key", client_write_key, 16);
format_bytes(stderr, 0, 4, "client_write_iv", conn->client_write_iv, 12);
format_print(stderr, 0, 0, "\n");
return 1;
}
// 这个的总长度是48 + 2 + 8 == 58
typedef struct {
uint8_t master_secret[48];
uint16_t cipher_suite;
uint64_t timestamp;
} TLS_SESSION_TICKET;
int tls13_send_new_session_ticket(TLS_CONNECT *conn)
{
int ret;
size_t padding_len;
tls_trace("send {NewSessionTicket*}\n");
if (conn->recordlen == 0) {
// new_session_ticket
uint32_t ticket_lifetime = 60 * 60 * 24 * 2; // = 2 days
uint32_t ticket_age_add;
uint8_t ticket_nonce[8];
uint8_t ticket[12 + 60 + 16];
size_t ticketlen;
uint8_t exts[16];
size_t extslen = 0;
uint8_t *p = exts;
// early_data
uint32_t max_early_data_size = 256 * 1024; // 256 KB
uint32_t ticket_issue_time = time(NULL);
if (rand_bytes((uint8_t *)&ticket_age_add, sizeof(ticket_age_add)) != 1) {
error_print();
return -1;
}
if (rand_bytes(ticket_nonce, sizeof(ticket_nonce)) != 1) {
error_print();
return -1;
}
if (tls13_encrypt_ticket(&conn->ctx->server_session_ticket_key,
conn->master_secret, conn->protocol, conn->cipher_suite,
ticket_issue_time, ticket_lifetime, ticket, &ticketlen) != 1) {
error_print();
return -1;
}
if (ticketlen != sizeof(ticket)) {
error_print();
return -1;
}
if (tls13_early_data_ext_to_bytes(max_early_data_size, &p, &extslen) != 1) {
error_print();
return -1;
}
if (tls13_record_set_handshake_new_session_ticket(
conn->plain_record, &conn->plain_recordlen,
ticket_lifetime, ticket_age_add,
ticket_nonce, sizeof(ticket_nonce),
ticket, ticketlen,
exts, extslen) != 1) {
error_print();
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
tls13_padding_len_rand(&padding_len);
if (tls13_record_encrypt(&conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->plain_record, conn->plain_recordlen, padding_len,
conn->record, &conn->recordlen) != 1) {
error_print();
return -1;
}
tls_seq_num_incr(conn->server_seq_num);
conn->new_session_ticket--;
}
if ((ret = tls_send_record(conn)) != 1) {
if (ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
return 1;
}
int tls13_save_session_ticket(TLS_CONNECT *conn, const uint8_t *new_session_ticket, size_t new_session_ticket_len)
{
tls13_ticket_print(stderr, 0, 0, "save SessionTicket", new_session_ticket, new_session_ticket_len);
return 1;
}
int tls13_recv_new_session_ticket(TLS_CONNECT *conn)
{
int ret;
int handshake_type;
const uint8_t *handshake_data;
size_t handshake_datalen;
uint32_t ticket_lifetime;
uint32_t ticket_age_add;
const uint8_t *ticket_nonce;
const uint8_t *ticket;
const uint8_t *exts;
size_t ticket_nonce_len, ticketlen, extslen;
size_t max_early_data_size;
const uint8_t *cp;
size_t len;
tls_trace("recv {NewSessionTicket*}\n");
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
error_print();
}
return ret;
}
if (tls13_record_decrypt(&conn->server_write_key, conn->server_write_iv,
conn->server_seq_num, conn->record, conn->recordlen,
conn->plain_record, &conn->plain_recordlen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_bad_record_mac);
return -1;
}
tls13_record_print(stderr, 0, 0, conn->plain_record, conn->plain_recordlen);
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();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
}
if (handshake_type != TLS_handshake_new_session_ticket) {
error_print();
tls_send_alert(conn, TLS_alert_unexpected_message);
return -1;
}
// only cheching encoding
if ((ret = tls13_record_get_handshake_new_session_ticket(conn->plain_record,
&ticket_lifetime, &ticket_age_add, &ticket_nonce, &ticket_nonce_len,
&ticket, &ticketlen, &exts, &extslen)) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
}
if (!ticket_lifetime || ticket_lifetime > 60 * 60 * 24 * 7) {
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_early_data:
if (tls13_early_data_from_bytes(&max_early_data_size, ext_data, ext_datalen) != 1) {
error_print();
return -1;
}
break;
default:
error_print();
return -1;
}
}
// save ticket
if (tls13_save_session_ticket(conn, handshake_data, handshake_datalen) != 1) {
error_print();
return -1;
}
return 1;
}
/*
send_client_hello
*recv_hello_retry_request
if (recv_hello_retry_request)
send_client_hello2
recv_server_hello
recv_encrypted_extensions
*recv_certificate_request
recv_server_certificate
recv_certificate_verify
recv_server_finished
if (recv_certificate_request)
send_client_certificate
send_certificate_verify
send_client_finished
*/
int tls13_do_client_handshake(TLS_CONNECT *conn)
{
int ret;
int next_state;
switch (conn->state) {
case TLS_state_client_hello:
ret = tls13_send_client_hello(conn);
next_state = TLS_state_hello_retry_request;
break;
case TLS_state_hello_retry_request: // optional
ret = tls13_recv_hello_retry_request(conn);
if (conn->hello_retry_request)
next_state = TLS_state_client_hello_again;
else next_state = TLS_state_server_hello;
break;
case TLS_state_client_hello_again:
ret = tls13_send_client_hello_again(conn);
next_state = TLS_state_server_hello;
break;
case TLS_state_server_hello:
ret = tls13_recv_server_hello(conn);
next_state = TLS_state_generate_keys;
break;
case TLS_state_generate_keys:
ret = tls13_generate_keys(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);
next_state = TLS_state_server_certificate;
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_certificate_verify(conn);
next_state = TLS_state_server_finished;
break;
case TLS_state_server_finished:
ret = tls13_recv_server_finished(conn);
if (conn->client_certificate_verify)
next_state = TLS_state_client_certificate;
else next_state = TLS_state_client_finished;
break;
case TLS_state_client_certificate:
ret = tls13_send_client_certificate(conn);
next_state = TLS_state_client_certificate_verify;
break;
case TLS_state_client_certificate_verify:
ret = tls13_send_certificate_verify(conn);
next_state = TLS_state_client_finished;
break;
case TLS_state_client_finished:
ret = tls13_send_client_finished(conn);
next_state = TLS_state_handshake_over;
next_state = TLS_state_new_session_ticket;
break;
case TLS_state_new_session_ticket:
ret = tls13_recv_new_session_ticket(conn);
next_state = TLS_state_handshake_over;
break;
default:
error_print();
return -1;
}
if (ret < 0) {
if (ret == TLS_ERROR_RECV_AGAIN || ret == TLS_ERROR_SEND_AGAIN) {
return ret;
} else {
error_print();
return ret;
}
}
conn->state = next_state;
// ret == 0 means this step is bypassed
if (ret == 1) {
tls_clean_record(conn);
}
return 1;
}
int tls13_do_server_handshake(TLS_CONNECT *conn)
{
int ret;
int next_state;
switch (conn->state) {
case TLS_state_client_hello:
ret = tls13_recv_client_hello(conn);
if (conn->hello_retry_request)
next_state = TLS_state_hello_retry_request;
else next_state = TLS_state_server_hello;
break;
case TLS_state_hello_retry_request:
ret = tls13_send_hello_retry_request(conn);
next_state = TLS_state_client_hello_again;
break;
case TLS_state_client_hello_again:
ret = tls13_recv_client_hello_again(conn);
next_state = TLS_state_server_hello;
break;
case TLS_state_server_hello:
ret = tls13_send_server_hello(conn);
next_state = TLS_state_generate_keys;
break;
case TLS_state_generate_keys:
ret = tls13_generate_keys(conn);
next_state = TLS_state_encrypted_extensions;
case TLS_state_encrypted_extensions:
ret = tls13_send_encrypted_extensions(conn);
if (conn->certificate_request)
next_state = TLS_state_certificate_request;
else next_state = TLS_state_server_certificate;
break;
case TLS_state_certificate_request:
ret = tls13_send_certificate_request(conn);
next_state = TLS_state_server_certificate;
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->certificate_request)
next_state = TLS_state_client_certificate;
else next_state = TLS_state_client_finished;
break;
case TLS_state_client_certificate:
ret = tls13_recv_client_certificate(conn);
next_state = TLS_state_client_certificate_verify;
break;
case TLS_state_client_certificate_verify:
ret = tls13_recv_certificate_verify(conn);
next_state = TLS_state_client_finished;
break;
case TLS_state_client_finished:
ret = tls13_recv_client_finished(conn);
if (conn->new_session_ticket)
next_state = TLS_state_new_session_ticket;
else next_state = TLS_state_handshake_over;
break;
case TLS_state_new_session_ticket:
ret = tls13_send_new_session_ticket(conn);
next_state = TLS_state_handshake_over;
break;
default:
error_print();
return -1;
}
if (ret < 0) {
if (ret == TLS_ERROR_RECV_AGAIN || ret == TLS_ERROR_SEND_AGAIN) {
return ret;
} else {
error_print();
return ret;
}
}
conn->state = next_state;
tls_clean_record(conn);
return 1;
}
int tls13_client_handshake(TLS_CONNECT *conn)
{
int ret;
while (conn->state != TLS_state_handshake_over) {
ret = tls13_do_client_handshake(conn);
if (ret != 1) {
if (ret != TLS_ERROR_RECV_AGAIN && ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
}
// TODO: cleanup conn?
return 1;
}
int tls13_server_handshake(TLS_CONNECT *conn)
{
int ret;
while (conn->state != TLS_state_handshake_over) {
ret = tls13_do_server_handshake(conn);
if (ret != 1) {
if (ret != TLS_ERROR_RECV_AGAIN && ret != TLS_ERROR_SEND_AGAIN) {
error_print();
}
return ret;
}
}
// TODO: cleanup conn?
return 1;
}
int tls13_do_connect(TLS_CONNECT *conn)
{
int ret;
fd_set rfds;
fd_set wfds;
// 应该把protocol_version的初始化放在这里
conn->state = TLS_state_client_hello;
sm3_init(&conn->sm3_ctx);
while (1) {
ret = tls13_client_handshake(conn);
if (ret == 1) {
break;
} else if (ret == TLS_ERROR_SEND_AGAIN) {
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_SET(conn->sock, &rfds);
select(conn->sock + 1, &rfds, &wfds, NULL, NULL);
} else if (ret == TLS_ERROR_RECV_AGAIN) {
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_SET(conn->sock, &wfds);
select(conn->sock + 1, &rfds, &wfds, NULL, NULL);
} else {
error_print();
return -1;
}
}
fprintf(stderr, "tls13_do_connect: connected\n");
return 1;
}
int tls13_do_accept(TLS_CONNECT *conn)
{
int ret;
fd_set rfds;
fd_set wfds;
conn->state = TLS_state_client_hello;
sm3_init(&conn->sm3_ctx);
fprintf(stderr, "tls13_do_accept\n");
while (1) {
ret = tls13_server_handshake(conn);
if (ret == 1) {
break;
} else if (ret == TLS_ERROR_SEND_AGAIN) {
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_SET(conn->sock, &rfds);
select(conn->sock + 1, &rfds, &wfds, NULL, NULL);
} else if (ret == TLS_ERROR_RECV_AGAIN) {
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_SET(conn->sock, &wfds);
select(conn->sock + 1, &rfds, &wfds, NULL, NULL);
} else {
error_print();
return -1;
}
}
fprintf(stderr, "tls13_do_accept: connected\n");
return 1;
}