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

@@ -841,6 +841,8 @@ typedef struct {
// 3. trusted_ca_keys // 3. trusted_ca_keys
int trusted_ca_keys; int trusted_ca_keys;
uint8_t trusted_authorities[512];
size_t trusted_authorities_len;
// 5. status_request // 5. status_request
int status_request; // if send in ClientHello, CertificateRequest int status_request; // if send in ClientHello, CertificateRequest
@@ -946,6 +948,7 @@ int tls_ctx_add_certificate_list_and_key(TLS_CTX *ctx, const char *chainfile,
int tls_ctx_enable_verbose(TLS_CTX *ctx, int enable); int tls_ctx_enable_verbose(TLS_CTX *ctx, int enable);
int tls_ctx_enable_trusted_ca_keys(TLS_CTX *ctx, int enable);
// KeyUpdate // KeyUpdate
@@ -1174,6 +1177,8 @@ typedef struct {
// 3. trusted_ca_keys // 3. trusted_ca_keys
int trusted_ca_keys; int trusted_ca_keys;
uint8_t trusted_authorities[512];
size_t trusted_authorities_len;
// 5. status_request // 5. status_request
int status_request; int status_request;
@@ -1688,12 +1693,35 @@ enum {
TLS_name_type_preserved_max = 255, TLS_name_type_preserved_max = 255,
}; };
enum {
TLS_trusted_authority_pre_agreed = 0,
TLS_trusted_authority_key_sha1_hash = 1,
TLS_trusted_authority_x509_name = 2,
TLS_trusted_authority_cert_sha1_hash = 3,
TLS_trusted_authority_reserved_max = 255,
};
#define tls_ext_data(ext) ((ext) + 4) #define tls_ext_data(ext) ((ext) + 4)
int tls_ext_to_bytes(int ext_type, const uint8_t *ext_data, size_t ext_datalen, int tls_ext_to_bytes(int ext_type, const uint8_t *ext_data, size_t ext_datalen,
uint8_t **out, size_t *outlen); uint8_t **out, size_t *outlen);
const char *tls_trusted_authority_type_name(int type);
int tls_trusted_authority_to_bytes(int type, const uint8_t *data, size_t datalen,
uint8_t **out, size_t *outlen);
int tls_trusted_authority_from_bytes(int *type, const uint8_t **data, size_t *datalen,
const uint8_t **in, size_t *inlen);
int tls_trusted_authorities_to_bytes(const uint8_t *authorities, size_t authorities_len,
uint8_t **out, size_t *outlen);
int tls_trusted_authorities_from_bytes(const uint8_t **authorities, size_t *authorities_len,
const uint8_t *data, size_t datalen);
int tls_trusted_ca_keys_ext_to_bytes(const uint8_t *authorities, size_t authorities_len,
uint8_t **out, size_t *outlen);
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);
int tls_trusted_authorities_print(FILE *fp, int fmt, int ind, const uint8_t *ext_data, size_t ext_datalen);

View File

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

View File

@@ -2507,6 +2507,11 @@ int tls_ctx_set_ca_certificates(TLS_CTX *ctx, const char *cacertsfile, int depth
error_print(); error_print();
return -1; 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; ctx->verify_depth = depth;
return 1; return 1;
@@ -2522,6 +2527,16 @@ int tls_ctx_enable_verbose(TLS_CTX *ctx, int enable)
return 1; 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) int tls_ctx_enable_certificate_request(TLS_CTX *ctx, int enable)
{ {
if (!ctx) { 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 // server_name
if (conn->server_name) { if (conn->server_name) {
if (tls_server_name_ext_to_bytes(conn->host_name, conn->host_name_len, &pexts, &extslen) != 1) { 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; size_t signature_algorithms_len = 0;
const uint8_t *signature_algorithms_cert = NULL; const uint8_t *signature_algorithms_cert = NULL;
size_t signature_algorithms_cert_len = 0; 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; const uint8_t *server_name = NULL;
size_t server_name_len = 0; size_t server_name_len = 0;
const uint8_t *renegotiation_info = NULL; 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_supported_groups:
case TLS_extension_signature_algorithms: case TLS_extension_signature_algorithms:
case TLS_extension_signature_algorithms_cert: case TLS_extension_signature_algorithms_cert:
case TLS_extension_server_name:
case TLS_extension_renegotiation_info: case TLS_extension_renegotiation_info:
if (!ext_data) { if (!ext_data) {
error_print(); error_print();
@@ -1360,6 +1371,9 @@ int tls_recv_client_hello(TLS_CONNECT *conn)
return -1; return -1;
} }
break; break;
case TLS_extension_trusted_ca_keys:
case TLS_extension_server_name:
break;
} }
switch (ext_type) { switch (ext_type) {
@@ -1399,6 +1413,20 @@ int tls_recv_client_hello(TLS_CONNECT *conn)
signature_algorithms_cert = ext_data; signature_algorithms_cert = ext_data;
signature_algorithms_cert_len = ext_datalen; signature_algorithms_cert_len = ext_datalen;
break; 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: case TLS_extension_server_name:
if (server_name) { if (server_name) {
error_print(); error_print();
@@ -1465,6 +1493,19 @@ int tls_recv_client_hello(TLS_CONNECT *conn)
conn->ec_point_formats = 1; 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, if ((ret = tls12_select_common_cipher_suites(cipher_suites, cipher_suites_len,
conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt, conn->ctx->cipher_suites, conn->ctx->cipher_suites_cnt,
common_cipher_suites, &common_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 // renegotiation_info
if (conn->secure_renegotiation) { if (conn->secure_renegotiation) {
uint8_t ext_data[1] = { 0 }; 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; const uint8_t *ec_point_formats = NULL;
size_t ec_point_formats_len = 0; size_t ec_point_formats_len = 0;
int server_name = 0; int server_name = 0;
int trusted_ca_keys = 0;
int renegotiation_info = 0; int renegotiation_info = 0;
tls_trace("recv ServerHello\n"); tls_trace("recv ServerHello\n");
@@ -1787,6 +1837,15 @@ int tls_recv_server_hello(TLS_CONNECT *conn)
} }
server_name = 1; server_name = 1;
break; 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: case TLS_extension_renegotiation_info:
if ((!conn->ctx->renegotiation_info && !conn->ctx->empty_renegotiation_info_scsv) if ((!conn->ctx->renegotiation_info && !conn->ctx->empty_renegotiation_info_scsv)
|| renegotiation_info) { || 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; 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 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); tls_ec_point_format_name(point_form), point_form);
} }
break; 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: case TLS_extension_signature_algorithms:
if (tls_uint16array_from_bytes(&p, &len, &data, &datalen) != 1 if (tls_uint16array_from_bytes(&p, &len, &data, &datalen) != 1
|| datalen || datalen

View File

@@ -352,6 +352,90 @@ static int test_tls_status_request_ext(void)
return 1; return 1;
} }
static int test_tls_trusted_ca_keys_ext(void)
{
uint8_t name[256];
size_t namelen = 0;
uint8_t der_name[256];
uint8_t *p = der_name;
size_t der_name_len = 0;
uint8_t hash[20];
uint8_t authorities[512];
uint8_t *pa = authorities;
size_t authorities_len = 0;
uint8_t ext[512];
const uint8_t *ext_data;
size_t ext_datalen;
int ext_type;
const uint8_t *list;
size_t list_len;
const uint8_t *cp;
size_t len;
memset(hash, 0x5a, sizeof(hash));
if (x509_name_set(name, &namelen, sizeof(name),
"CN", "Beijing", "Haidian", "PKU", "CS", "CA") != 1
|| asn1_sequence_to_der(name, namelen, &p, &der_name_len) != 1) {
error_print();
return -1;
}
if (tls_trusted_authority_to_bytes(TLS_trusted_authority_pre_agreed,
NULL, 0, &pa, &authorities_len) != 1
|| tls_trusted_authority_to_bytes(TLS_trusted_authority_key_sha1_hash,
hash, sizeof(hash), &pa, &authorities_len) != 1
|| tls_trusted_authority_to_bytes(TLS_trusted_authority_x509_name,
der_name, der_name_len, &pa, &authorities_len) != 1
|| tls_trusted_authority_to_bytes(TLS_trusted_authority_cert_sha1_hash,
hash, sizeof(hash), &pa, &authorities_len) != 1) {
error_print();
return -1;
}
p = ext;
len = 0;
if (tls_trusted_ca_keys_ext_to_bytes(authorities, authorities_len, &p, &len) != 1) {
error_print();
return -1;
}
cp = ext;
if (tls_ext_from_bytes(&ext_type, &ext_data, &ext_datalen, &cp, &len) != 1
|| ext_type != TLS_extension_trusted_ca_keys
|| len != 0
|| tls_trusted_authorities_from_bytes(&list, &list_len, ext_data, ext_datalen) != 1
|| list_len != authorities_len) {
error_print();
return -1;
}
{
int type;
const uint8_t *data;
size_t datalen;
if (tls_trusted_authority_from_bytes(&type, &data, &datalen, &list, &list_len) != 1
|| type != TLS_trusted_authority_pre_agreed
|| data != NULL || datalen != 0
|| tls_trusted_authority_from_bytes(&type, &data, &datalen, &list, &list_len) != 1
|| type != TLS_trusted_authority_key_sha1_hash
|| datalen != sizeof(hash) || memcmp(data, hash, sizeof(hash)) != 0
|| tls_trusted_authority_from_bytes(&type, &data, &datalen, &list, &list_len) != 1
|| type != TLS_trusted_authority_x509_name
|| datalen != der_name_len || memcmp(data, der_name, der_name_len) != 0
|| tls_trusted_authority_from_bytes(&type, &data, &datalen, &list, &list_len) != 1
|| type != TLS_trusted_authority_cert_sha1_hash
|| datalen != sizeof(hash) || memcmp(data, hash, sizeof(hash)) != 0
|| list_len != 0) {
error_print();
return -1;
}
}
tls_trusted_authorities_print(stdout, 0, 0, ext_data, ext_datalen);
printf("%s() ok\n", __FUNCTION__);
return 1;
}
int main(void) int main(void)
{ {
if (test_tls_null_to_bytes() != 1) goto err; if (test_tls_null_to_bytes() != 1) goto err;
@@ -369,6 +453,7 @@ int main(void)
if (test_tls_change_cipher_spec() != 1) goto err; if (test_tls_change_cipher_spec() != 1) goto err;
if (test_tls_application_data() != 1) goto err; if (test_tls_application_data() != 1) goto err;
*/ */
if (test_tls_trusted_ca_keys_ext() != 1) goto err;
if (test_tls_status_request_ext() != 1) goto err; if (test_tls_status_request_ext() != 1) goto err;
printf("%s all tests passed\n", __FILE__); printf("%s all tests passed\n", __FILE__);
return 0; return 0;

View File

@@ -25,6 +25,7 @@ static const char *usage =
" [-outcerts file]" " [-outcerts file]"
" [-get path]" " [-get path]"
" [-alpn str]" " [-alpn str]"
" [-trusted_ca_keys]"
" [-quiet]"; " [-quiet]";
static const char *help = static const char *help =
@@ -44,6 +45,7 @@ static const char *help =
" -get path Send a GET request with given path of URI\n" " -get path Send a GET request with given path of URI\n"
" -outcerts file Save server certificates to a PEM file\n" " -outcerts file Save server certificates to a PEM file\n"
" -server_name str Send server_name (SNI) request\n" " -server_name str Send server_name (SNI) request\n"
" -trusted_ca_keys Send trusted_ca_keys request\n"
" -alpn str Application protocol name, may appear multiple times, higher priority first\n" " -alpn str Application protocol name, may appear multiple times, higher priority first\n"
" -status_request Send status_request (OCSP Stapling) request\n" " -status_request Send status_request (OCSP Stapling) request\n"
" -quiet Without printing any status message\n" " -quiet Without printing any status message\n"
@@ -71,6 +73,7 @@ int tlcp_client_main(int argc, char *argv[])
char *keyfile = NULL; char *keyfile = NULL;
char *pass = NULL; char *pass = NULL;
char *server_name = NULL; char *server_name = NULL;
int trusted_ca_keys = 0;
char *alpn_protocols[4]; char *alpn_protocols[4];
size_t alpn_protocols_cnt = 0; size_t alpn_protocols_cnt = 0;
int client_cert_optional = 0; int client_cert_optional = 0;
@@ -169,6 +172,8 @@ int tlcp_client_main(int argc, char *argv[])
} else if (!strcmp(*argv, "-server_name")) { } else if (!strcmp(*argv, "-server_name")) {
if (--argc < 1) goto bad; if (--argc < 1) goto bad;
server_name = *(++argv); server_name = *(++argv);
} else if (!strcmp(*argv, "-trusted_ca_keys")) {
trusted_ca_keys = 1;
} else if (!strcmp(*argv, "-alpn")) { } else if (!strcmp(*argv, "-alpn")) {
if (alpn_protocols_cnt >= sizeof(alpn_protocols)/sizeof(alpn_protocols[0])) { if (alpn_protocols_cnt >= sizeof(alpn_protocols)/sizeof(alpn_protocols[0])) {
fprintf(stderr, "%s: too many -alpn options\n", prog); fprintf(stderr, "%s: too many -alpn options\n", prog);
@@ -224,6 +229,13 @@ bad:
goto end; goto end;
} }
if (trusted_ca_keys) {
if (tls_ctx_enable_trusted_ca_keys(&ctx, 1) != 1) {
error_print();
goto end;
}
}
if (alpn_protocols_cnt) { if (alpn_protocols_cnt) {
if (tls_ctx_set_application_layer_protocol_negotiation(&ctx, if (tls_ctx_set_application_layer_protocol_negotiation(&ctx,
alpn_protocols, alpn_protocols_cnt) != 1) { alpn_protocols, alpn_protocols_cnt) != 1) {

View File

@@ -23,7 +23,7 @@ static const char *http_get =
"Hostname: aaa\r\n" "Hostname: aaa\r\n"
"\r\n\r\n"; "\r\n\r\n";
static const char *options = "-host str [-port num] [-cacert file] [-cert file -key file -pass str]"; static const char *options = "-host str [-port num] [-cacert file] [-cert file -key file -pass str] [-trusted_ca_keys]";
static const char *help = static const char *help =
"Options\n" "Options\n"
@@ -40,6 +40,7 @@ static const char *help =
" -pass str Password to decrypt private key\n" " -pass str Password to decrypt private key\n"
" -client_cert_optional Allow client send empty Certificate\n" " -client_cert_optional Allow client send empty Certificate\n"
" -server_name str Send server_name (SNI) request\n" " -server_name str Send server_name (SNI) request\n"
" -trusted_ca_keys Send trusted_ca_keys request\n"
" -renegotiation_info Send renegotiation_info extension\n" " -renegotiation_info Send renegotiation_info extension\n"
" -renegotiation_info_scsv\n" " -renegotiation_info_scsv\n"
" Send TLS_EMPTY_RENEGOTIATION_INFO_SCSV\n" " Send TLS_EMPTY_RENEGOTIATION_INFO_SCSV\n"
@@ -67,6 +68,7 @@ int tls12_client_main(int argc, char *argv[])
char *pass = NULL; char *pass = NULL;
int client_cert_optional = 0; int client_cert_optional = 0;
char *server_name = NULL; char *server_name = NULL;
int trusted_ca_keys = 0;
int renegotiation_info = 0; int renegotiation_info = 0;
int empty_renegotiation_info_scsv = 0; int empty_renegotiation_info_scsv = 0;
TLS_CTX ctx; TLS_CTX ctx;
@@ -160,6 +162,8 @@ int tls12_client_main(int argc, char *argv[])
} else if (!strcmp(*argv, "-server_name")) { } else if (!strcmp(*argv, "-server_name")) {
if (--argc < 1) goto bad; if (--argc < 1) goto bad;
server_name = *(++argv); server_name = *(++argv);
} else if (!strcmp(*argv, "-trusted_ca_keys")) {
trusted_ca_keys = 1;
} else if (!strcmp(*argv, "-renegotiation_info")) { } else if (!strcmp(*argv, "-renegotiation_info")) {
renegotiation_info = 1; renegotiation_info = 1;
} else if (!strcmp(*argv, "-renegotiation_info_scsv")) { } else if (!strcmp(*argv, "-renegotiation_info_scsv")) {
@@ -202,6 +206,13 @@ bad:
goto end; goto end;
} }
if (trusted_ca_keys) {
if (tls_ctx_enable_trusted_ca_keys(&ctx, 1) != 1) {
error_print();
goto end;
}
}
if (cacertfile) { if (cacertfile) {
if (tls_ctx_set_ca_certificates(&ctx, cacertfile, verify_depth) != 1) { if (tls_ctx_set_ca_certificates(&ctx, cacertfile, verify_depth) != 1) {
fprintf(stderr, "%s: failed to load CA certificate\n", prog); fprintf(stderr, "%s: failed to load CA certificate\n", prog);