Add trusted_ca_keys to TLS1.2/TLCP

This commit is contained in:
Zhi Guan
2026-06-12 10:24:32 +08:00
parent b1f670c6c6
commit dbbee6dbe0
9 changed files with 555 additions and 8 deletions

View File

@@ -329,8 +329,11 @@ int tlcp_send_client_hello(TLS_CONNECT *conn)
// trusted_ca_keys
if (conn->ctx->trusted_ca_keys) {
error_print();
return -1;
if (tls_trusted_ca_keys_ext_to_bytes(conn->ctx->trusted_authorities,
conn->ctx->trusted_authorities_len, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// status_request (hint only)
@@ -1315,8 +1318,9 @@ int tlcp_recv_client_hello(TLS_CONNECT *conn)
// extensions
const uint8_t *server_name = NULL;
size_t server_name_len = 0;
const uint8_t *trusted_ca_keys = NULL;
size_t trusted_ca_keys_len = 0;
int trusted_ca_keys = 0;
const uint8_t *trusted_authorities = NULL;
size_t trusted_authorities_len = 0;
const uint8_t *status_request = NULL;
size_t status_request_len = 0;
const uint8_t *supported_groups = NULL;
@@ -1434,8 +1438,13 @@ int tlcp_recv_client_hello(TLS_CONNECT *conn)
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
trusted_ca_keys = ext_data;
trusted_ca_keys_len = ext_datalen;
if (tls_trusted_authorities_from_bytes(&trusted_authorities,
&trusted_authorities_len, ext_data, ext_datalen) != 1) {
error_print();
tls13_send_alert(conn, TLS_alert_decode_error);
return -1;
}
trusted_ca_keys = 1;
break;
case TLS_extension_status_request:
@@ -1500,6 +1509,19 @@ int tlcp_recv_client_hello(TLS_CONNECT *conn)
return -1;
}
if (trusted_ca_keys) {
conn->trusted_ca_keys = 1;
if (trusted_authorities_len > sizeof(conn->trusted_authorities)) {
error_print();
tls_send_alert(conn, TLS_alert_internal_error);
return -1;
}
if (trusted_authorities_len) {
memcpy(conn->trusted_authorities, trusted_authorities, trusted_authorities_len);
}
conn->trusted_authorities_len = trusted_authorities_len;
}
if (application_layer_protocol_negotiation) {
if (!conn->ctx->alpn_protocols_cnt) {
error_print();

View File

@@ -2507,6 +2507,11 @@ int tls_ctx_set_ca_certificates(TLS_CTX *ctx, const char *cacertsfile, int depth
error_print();
return -1;
}
if (tls_trusted_authorities_from_ca_names(ctx->trusted_authorities, &ctx->trusted_authorities_len,
sizeof(ctx->trusted_authorities), ctx->ca_names, ctx->ca_names_len) != 1) {
error_print();
return -1;
}
ctx->verify_depth = depth;
return 1;
@@ -2522,6 +2527,16 @@ int tls_ctx_enable_verbose(TLS_CTX *ctx, int enable)
return 1;
}
int tls_ctx_enable_trusted_ca_keys(TLS_CTX *ctx, int enable)
{
if (!ctx) {
error_print();
return -1;
}
ctx->trusted_ca_keys = enable ? 1 : 0;
return 1;
}
int tls_ctx_enable_certificate_request(TLS_CTX *ctx, int enable)
{
if (!ctx) {

View File

@@ -868,6 +868,15 @@ int tls_send_client_hello(TLS_CONNECT *conn)
}
}
// trusted_ca_keys
if (conn->ctx->trusted_ca_keys) {
if (tls_trusted_ca_keys_ext_to_bytes(conn->ctx->trusted_authorities,
conn->ctx->trusted_authorities_len, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// server_name
if (conn->server_name) {
if (tls_server_name_ext_to_bytes(conn->host_name, conn->host_name_len, &pexts, &extslen) != 1) {
@@ -1275,6 +1284,9 @@ int tls_recv_client_hello(TLS_CONNECT *conn)
size_t signature_algorithms_len = 0;
const uint8_t *signature_algorithms_cert = NULL;
size_t signature_algorithms_cert_len = 0;
int trusted_ca_keys = 0;
const uint8_t *trusted_authorities = NULL;
size_t trusted_authorities_len = 0;
const uint8_t *server_name = NULL;
size_t server_name_len = 0;
const uint8_t *renegotiation_info = NULL;
@@ -1352,7 +1364,6 @@ int tls_recv_client_hello(TLS_CONNECT *conn)
case TLS_extension_supported_groups:
case TLS_extension_signature_algorithms:
case TLS_extension_signature_algorithms_cert:
case TLS_extension_server_name:
case TLS_extension_renegotiation_info:
if (!ext_data) {
error_print();
@@ -1360,6 +1371,9 @@ int tls_recv_client_hello(TLS_CONNECT *conn)
return -1;
}
break;
case TLS_extension_trusted_ca_keys:
case TLS_extension_server_name:
break;
}
switch (ext_type) {
@@ -1399,6 +1413,20 @@ int tls_recv_client_hello(TLS_CONNECT *conn)
signature_algorithms_cert = ext_data;
signature_algorithms_cert_len = ext_datalen;
break;
case TLS_extension_trusted_ca_keys:
if (trusted_ca_keys) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
if (tls_trusted_authorities_from_bytes(&trusted_authorities,
&trusted_authorities_len, ext_data, ext_datalen) != 1) {
error_print();
tls_send_alert(conn, TLS_alert_decode_error);
return -1;
}
trusted_ca_keys = 1;
break;
case TLS_extension_server_name:
if (server_name) {
error_print();
@@ -1465,6 +1493,19 @@ int tls_recv_client_hello(TLS_CONNECT *conn)
conn->ec_point_formats = 1;
}
if (trusted_ca_keys) {
conn->trusted_ca_keys = 1;
if (trusted_authorities_len > sizeof(conn->trusted_authorities)) {
error_print();
tls_send_alert(conn, TLS_alert_internal_error);
return -1;
}
if (trusted_authorities_len) {
memcpy(conn->trusted_authorities, trusted_authorities, trusted_authorities_len);
}
conn->trusted_authorities_len = trusted_authorities_len;
}
if ((ret = tls12_select_common_cipher_suites(cipher_suites, cipher_suites_len,
conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt,
common_cipher_suites, &common_cipher_suites_cnt,
@@ -1636,6 +1677,14 @@ int tls_send_server_hello(TLS_CONNECT *conn)
}
}
// trusted_ca_keys
if (conn->trusted_ca_keys) {
if (tls_ext_to_bytes(TLS_extension_trusted_ca_keys, NULL, 0, &pexts, &extslen) != 1) {
error_print();
return -1;
}
}
// renegotiation_info
if (conn->secure_renegotiation) {
uint8_t ext_data[1] = { 0 };
@@ -1695,6 +1744,7 @@ int tls_recv_server_hello(TLS_CONNECT *conn)
const uint8_t *ec_point_formats = NULL;
size_t ec_point_formats_len = 0;
int server_name = 0;
int trusted_ca_keys = 0;
int renegotiation_info = 0;
tls_trace("recv ServerHello\n");
@@ -1787,6 +1837,15 @@ int tls_recv_server_hello(TLS_CONNECT *conn)
}
server_name = 1;
break;
case TLS_extension_trusted_ca_keys:
if (!conn->ctx->trusted_ca_keys || trusted_ca_keys || ext_datalen) {
error_print();
tls_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
trusted_ca_keys = 1;
conn->trusted_ca_keys = 1;
break;
case TLS_extension_renegotiation_info:
if ((!conn->ctx->renegotiation_info && !conn->ctx->empty_renegotiation_info_scsv)
|| renegotiation_info) {

View File

@@ -62,6 +62,311 @@ int tls_ext_from_bytes(int *type, const uint8_t **data, size_t *datalen, const u
return 1;
}
/*
3. trusted_ca_keys
struct {
TrustedAuthority trusted_authorities_list<0..2^16-1>;
} TrustedAuthorities;
struct {
IdentifierType identifier_type;
select (identifier_type) {
case pre_agreed: struct {};
case key_sha1_hash: SHA1Hash;
case x509_name: DistinguishedName;
case cert_sha1_hash: SHA1Hash;
} identifier;
} TrustedAuthority;
enum {
pre_agreed(0), key_sha1_hash(1), x509_name(2),
cert_sha1_hash(3), (255)
} IdentifierType;
opaque DistinguishedName<1..2^16-1>;
*/
const char *tls_trusted_authority_type_name(int type)
{
switch (type) {
case TLS_trusted_authority_pre_agreed: return "pre_agreed";
case TLS_trusted_authority_key_sha1_hash: return "key_sha1_hash";
case TLS_trusted_authority_x509_name: return "x509_name";
case TLS_trusted_authority_cert_sha1_hash: return "cert_sha1_hash";
default: return NULL;
}
}
int tls_trusted_authority_to_bytes(int type, const uint8_t *data, size_t datalen,
uint8_t **out, size_t *outlen)
{
if (!outlen) {
error_print();
return -1;
}
if (!tls_trusted_authority_type_name(type)) {
error_print();
return -1;
}
switch (type) {
case TLS_trusted_authority_pre_agreed:
if (data || datalen) {
error_print();
return -1;
}
tls_uint8_to_bytes((uint8_t)type, out, outlen);
break;
case TLS_trusted_authority_key_sha1_hash:
case TLS_trusted_authority_cert_sha1_hash:
if (!data || datalen != 20) {
error_print();
return -1;
}
tls_uint8_to_bytes((uint8_t)type, out, outlen);
tls_array_to_bytes(data, datalen, out, outlen);
break;
case TLS_trusted_authority_x509_name:
if (!data || datalen < 1 || datalen > UINT16_MAX) {
error_print();
return -1;
}
tls_uint8_to_bytes((uint8_t)type, out, outlen);
tls_uint16array_to_bytes(data, datalen, out, outlen);
break;
}
return 1;
}
int tls_trusted_authority_from_bytes(int *type, const uint8_t **data, size_t *datalen,
const uint8_t **in, size_t *inlen)
{
uint8_t u8;
if (!type || !data || !datalen || !in || !(*in) || !inlen) {
error_print();
return -1;
}
if (tls_uint8_from_bytes(&u8, in, inlen) != 1) {
error_print();
return -1;
}
if (!tls_trusted_authority_type_name(u8)) {
error_print();
return -1;
}
*type = u8;
switch (u8) {
case TLS_trusted_authority_pre_agreed:
*data = NULL;
*datalen = 0;
break;
case TLS_trusted_authority_key_sha1_hash:
case TLS_trusted_authority_cert_sha1_hash:
if (*inlen < 20) {
error_print();
return -1;
}
*data = *in;
*datalen = 20;
*in += 20;
*inlen -= 20;
break;
case TLS_trusted_authority_x509_name:
if (tls_uint16array_from_bytes(data, datalen, in, inlen) != 1) {
error_print();
return -1;
}
if (*datalen < 1) {
error_print();
return -1;
}
break;
}
return 1;
}
int tls_trusted_authorities_to_bytes(const uint8_t *authorities, size_t authorities_len,
uint8_t **out, size_t *outlen)
{
if (!outlen) {
error_print();
return -1;
}
if (!authorities && authorities_len) {
error_print();
return -1;
}
if (authorities_len > UINT16_MAX) {
error_print();
return -1;
}
tls_uint16array_to_bytes(authorities, authorities_len, out, outlen);
return 1;
}
int tls_trusted_authorities_from_bytes(const uint8_t **authorities, size_t *authorities_len,
const uint8_t *data, size_t datalen)
{
const uint8_t *p;
size_t len;
if (!authorities || !authorities_len) {
error_print();
return -1;
}
if (tls_uint16array_from_bytes(&p, &len, &data, &datalen) != 1
|| tls_length_is_zero(datalen) != 1) {
error_print();
return -1;
}
*authorities = p;
*authorities_len = len;
while (len) {
int type;
const uint8_t *d;
size_t dlen;
if (tls_trusted_authority_from_bytes(&type, &d, &dlen, &p, &len) != 1) {
error_print();
return -1;
}
if (type == TLS_trusted_authority_x509_name) {
const uint8_t *name;
size_t namelen;
if (asn1_sequence_from_der(&name, &namelen, &d, &dlen) != 1
|| asn1_length_is_zero(dlen) != 1) {
error_print();
return -1;
}
}
}
return 1;
}
int tls_trusted_ca_keys_ext_to_bytes(const uint8_t *authorities, size_t authorities_len,
uint8_t **out, size_t *outlen)
{
uint8_t ext_data[512];
uint8_t *p = ext_data;
size_t len = 0;
if (authorities_len > sizeof(ext_data) - tls_uint16_size()) {
error_print();
return -1;
}
if (tls_trusted_authorities_to_bytes(authorities, authorities_len, &p, &len) != 1) {
error_print();
return -1;
}
if (tls_ext_to_bytes(TLS_extension_trusted_ca_keys, ext_data, len, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int tls_trusted_authorities_from_ca_names(uint8_t *authorities, size_t *authorities_len, size_t maxlen,
const uint8_t *ca_names, size_t ca_names_len)
{
uint8_t *p = authorities;
if (!authorities || !authorities_len) {
error_print();
return -1;
}
if (!ca_names && ca_names_len) {
error_print();
return -1;
}
*authorities_len = 0;
while (ca_names_len) {
const uint8_t *name;
size_t namelen;
size_t len = 0;
if (tls_uint16array_from_bytes(&name, &namelen, &ca_names, &ca_names_len) != 1) {
error_print();
return -1;
}
if (tls_trusted_authority_to_bytes(TLS_trusted_authority_x509_name,
name, namelen, NULL, &len) != 1) {
error_print();
return -1;
}
if (*authorities_len + len > maxlen) {
error_print();
return -1;
}
if (tls_trusted_authority_to_bytes(TLS_trusted_authority_x509_name,
name, namelen, &p, authorities_len) != 1) {
error_print();
return -1;
}
}
return 1;
}
int tls_trusted_authorities_print(FILE *fp, int fmt, int ind, const uint8_t *ext_data, size_t ext_datalen)
{
const uint8_t *authorities;
size_t authorities_len;
format_print(fp, fmt, ind, "trusted_authorities\n");
ind += 4;
if (tls_trusted_authorities_from_bytes(&authorities, &authorities_len, ext_data, ext_datalen) != 1) {
error_print();
return -1;
}
while (authorities_len) {
int type;
const uint8_t *data;
size_t datalen;
if (tls_trusted_authority_from_bytes(&type, &data, &datalen, &authorities, &authorities_len) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "%s (%d)\n", tls_trusted_authority_type_name(type), type);
switch (type) {
case TLS_trusted_authority_pre_agreed:
break;
case TLS_trusted_authority_key_sha1_hash:
case TLS_trusted_authority_cert_sha1_hash:
format_bytes(fp, fmt, ind + 4, "sha1_hash", data, datalen);
break;
case TLS_trusted_authority_x509_name:
{
const uint8_t *name;
size_t namelen;
if (asn1_sequence_from_der(&name, &namelen, &data, &datalen) != 1
|| asn1_length_is_zero(datalen) != 1) {
error_print();
return -1;
}
x509_name_print(fp, fmt, ind + 4, "DistinguishedName", name, namelen);
}
break;
}
}
return 1;
}
/*
11. ec_point_formats

View File

@@ -520,6 +520,16 @@ int tls_extension_print(FILE *fp, int type, const uint8_t *data, size_t datalen,
tls_ec_point_format_name(point_form), point_form);
}
break;
case TLS_extension_trusted_ca_keys:
if (datalen == 0) {
format_bytes(fp, format, indent, "raw_data", data, datalen);
break;
}
if (tls_trusted_authorities_print(fp, format, indent, data, datalen) != 1) {
error_print();
return -1;
}
break;
case TLS_extension_signature_algorithms:
if (tls_uint16array_from_bytes(&p, &len, &data, &datalen) != 1
|| datalen