diff --git a/include/gmssl/tls.h b/include/gmssl/tls.h index 888d3fd9..dffdb28d 100644 --- a/include/gmssl/tls.h +++ b/include/gmssl/tls.h @@ -841,6 +841,8 @@ typedef struct { // 3. trusted_ca_keys int trusted_ca_keys; + uint8_t trusted_authorities[512]; + size_t trusted_authorities_len; // 5. status_request 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_trusted_ca_keys(TLS_CTX *ctx, int enable); // KeyUpdate @@ -1174,6 +1177,8 @@ typedef struct { // 3. trusted_ca_keys int trusted_ca_keys; + uint8_t trusted_authorities[512]; + size_t trusted_authorities_len; // 5. status_request int status_request; @@ -1688,12 +1693,35 @@ enum { 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) int tls_ext_to_bytes(int ext_type, const uint8_t *ext_data, size_t ext_datalen, 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); + diff --git a/src/tlcp.c b/src/tlcp.c index 95d81b96..b7426f8d 100644 --- a/src/tlcp.c +++ b/src/tlcp.c @@ -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(); diff --git a/src/tls.c b/src/tls.c index 162096dd..cd0953c1 100644 --- a/src/tls.c +++ b/src/tls.c @@ -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) { diff --git a/src/tls12.c b/src/tls12.c index ba56f99c..e090fe3d 100644 --- a/src/tls12.c +++ b/src/tls12.c @@ -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) { diff --git a/src/tls_ext.c b/src/tls_ext.c index 3ea575d2..28f6a415 100644 --- a/src/tls_ext.c +++ b/src/tls_ext.c @@ -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 diff --git a/src/tls_trace.c b/src/tls_trace.c index 90ee70bf..34ade208 100644 --- a/src/tls_trace.c +++ b/src/tls_trace.c @@ -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 diff --git a/tests/tlstest.c b/tests/tlstest.c index ef4c9816..a371744b 100644 --- a/tests/tlstest.c +++ b/tests/tlstest.c @@ -352,6 +352,90 @@ static int test_tls_status_request_ext(void) 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) { 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_application_data() != 1) goto err; */ + if (test_tls_trusted_ca_keys_ext() != 1) goto err; if (test_tls_status_request_ext() != 1) goto err; printf("%s all tests passed\n", __FILE__); return 0; diff --git a/tools/tlcp_client.c b/tools/tlcp_client.c index f587e40c..0791594b 100644 --- a/tools/tlcp_client.c +++ b/tools/tlcp_client.c @@ -25,6 +25,7 @@ static const char *usage = " [-outcerts file]" " [-get path]" " [-alpn str]" + " [-trusted_ca_keys]" " [-quiet]"; static const char *help = @@ -44,6 +45,7 @@ static const char *help = " -get path Send a GET request with given path of URI\n" " -outcerts file Save server certificates to a PEM file\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" " -status_request Send status_request (OCSP Stapling) request\n" " -quiet Without printing any status message\n" @@ -71,6 +73,7 @@ int tlcp_client_main(int argc, char *argv[]) char *keyfile = NULL; char *pass = NULL; char *server_name = NULL; + int trusted_ca_keys = 0; char *alpn_protocols[4]; size_t alpn_protocols_cnt = 0; int client_cert_optional = 0; @@ -169,6 +172,8 @@ int tlcp_client_main(int argc, char *argv[]) } else if (!strcmp(*argv, "-server_name")) { if (--argc < 1) goto bad; server_name = *(++argv); + } else if (!strcmp(*argv, "-trusted_ca_keys")) { + trusted_ca_keys = 1; } else if (!strcmp(*argv, "-alpn")) { if (alpn_protocols_cnt >= sizeof(alpn_protocols)/sizeof(alpn_protocols[0])) { fprintf(stderr, "%s: too many -alpn options\n", prog); @@ -224,6 +229,13 @@ bad: 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 (tls_ctx_set_application_layer_protocol_negotiation(&ctx, alpn_protocols, alpn_protocols_cnt) != 1) { diff --git a/tools/tls12_client.c b/tools/tls12_client.c index 94e85db8..bba29650 100644 --- a/tools/tls12_client.c +++ b/tools/tls12_client.c @@ -23,7 +23,7 @@ static const char *http_get = "Hostname: aaa\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 = "Options\n" @@ -40,6 +40,7 @@ static const char *help = " -pass str Password to decrypt private key\n" " -client_cert_optional Allow client send empty Certificate\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_scsv\n" " Send TLS_EMPTY_RENEGOTIATION_INFO_SCSV\n" @@ -67,6 +68,7 @@ int tls12_client_main(int argc, char *argv[]) char *pass = NULL; int client_cert_optional = 0; char *server_name = NULL; + int trusted_ca_keys = 0; int renegotiation_info = 0; int empty_renegotiation_info_scsv = 0; TLS_CTX ctx; @@ -160,6 +162,8 @@ int tls12_client_main(int argc, char *argv[]) } else if (!strcmp(*argv, "-server_name")) { if (--argc < 1) goto bad; server_name = *(++argv); + } else if (!strcmp(*argv, "-trusted_ca_keys")) { + trusted_ca_keys = 1; } else if (!strcmp(*argv, "-renegotiation_info")) { renegotiation_info = 1; } else if (!strcmp(*argv, "-renegotiation_info_scsv")) { @@ -202,6 +206,13 @@ bad: goto end; } + if (trusted_ca_keys) { + if (tls_ctx_enable_trusted_ca_keys(&ctx, 1) != 1) { + error_print(); + goto end; + } + } + if (cacertfile) { if (tls_ctx_set_ca_certificates(&ctx, cacertfile, verify_depth) != 1) { fprintf(stderr, "%s: failed to load CA certificate\n", prog);