From: Michael Baentsch Date: Thu, 7 Jan 2021 08:09:32 +0000 (+0100) Subject: Adding TLS group name retrieval X-Git-Tag: openssl-3.0.0-alpha11~158 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=becbacd705170952725571ae4404846b0ecee86a;p=thirdparty%2Fopenssl.git Adding TLS group name retrieval Function SSL_group_to_name() added, together with documentation and tests. This now permits displaying names of internal and external provider-implemented groups. Partial fix of #13767 Reviewed-by: Tomas Mraz Reviewed-by: Nicola Tuveri Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/13785) --- diff --git a/apps/lib/s_cb.c b/apps/lib/s_cb.c index c7994417aa9..67e0fbd5bd8 100644 --- a/apps/lib/s_cb.c +++ b/apps/lib/s_cb.c @@ -345,7 +345,6 @@ int ssl_print_point_formats(BIO *out, SSL *s) int ssl_print_groups(BIO *out, SSL *s, int noshared) { int i, ngroups, *groups, nid; - const char *gname; ngroups = SSL_get1_groups(s, NULL); if (ngroups <= 0) @@ -353,39 +352,25 @@ int ssl_print_groups(BIO *out, SSL *s, int noshared) groups = app_malloc(ngroups * sizeof(int), "groups to print"); SSL_get1_groups(s, groups); - BIO_puts(out, "Supported Elliptic Groups: "); + BIO_puts(out, "Supported groups: "); for (i = 0; i < ngroups; i++) { if (i) BIO_puts(out, ":"); nid = groups[i]; - /* If unrecognised print out hex version */ - if (nid & TLSEXT_nid_unknown) { - BIO_printf(out, "0x%04X", nid & 0xFFFF); - } else { - /* TODO(TLS1.3): Get group name here */ - /* Use NIST name for curve if it exists */ - gname = EC_curve_nid2nist(nid); - if (gname == NULL) - gname = OBJ_nid2sn(nid); - BIO_printf(out, "%s", gname); - } + BIO_printf(out, "%s", SSL_group_to_name(s, nid)); } OPENSSL_free(groups); if (noshared) { BIO_puts(out, "\n"); return 1; } - BIO_puts(out, "\nShared Elliptic groups: "); + BIO_puts(out, "\nShared groups: "); ngroups = SSL_get_shared_group(s, -1); for (i = 0; i < ngroups; i++) { if (i) BIO_puts(out, ":"); nid = SSL_get_shared_group(s, i); - /* TODO(TLS1.3): Convert for DH groups */ - gname = EC_curve_nid2nist(nid); - if (gname == NULL) - gname = OBJ_nid2sn(nid); - BIO_printf(out, "%s", gname); + BIO_printf(out, "%s", SSL_group_to_name(s, nid)); } if (ngroups == 0) BIO_puts(out, "NONE"); diff --git a/doc/man3/SSL_group_to_name.pod b/doc/man3/SSL_group_to_name.pod new file mode 100644 index 00000000000..9c0e75c1886 --- /dev/null +++ b/doc/man3/SSL_group_to_name.pod @@ -0,0 +1,43 @@ +=pod + +=head1 NAME + +SSL_group_to_name - get name of group + +=head1 SYNOPSIS + + #include + + const char *SSL_group_to_name(const SSL *ssl, int id); + +=head1 DESCRIPTION + +SSL_group_to_name() is used to retrieve the TLS group name +associated with a given TLS group ID, as registered via built-in +or external providers and as returned by a call to SSL_get1_groups() +or SSL_get_shared_group(). + +=head1 RETURN VALUES + +If non-NULL, SSL_group_to_name() returns the TLS group name +corresponding to the given I as a NULL-terminated string. +If SSL_group_to_name() returns NULL, an error occurred; possibly no +corresponding tlsname was registered during provider initialisation. + +Note that the return value is valid only during the lifetime of the +SSL object I. + +=head1 SEE ALSO + +L + +=head1 COPYRIGHT + +Copyright 2021 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/include/openssl/ssl.h.in b/include/openssl/ssl.h.in index 37b4c82f025..4e5d50bd6db 100644 --- a/include/openssl/ssl.h.in +++ b/include/openssl/ssl.h.in @@ -1501,6 +1501,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) # define SSL_get_max_proto_version(s) \ SSL_ctrl(s, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL) +const char *SSL_group_to_name(SSL *s, int id); + /* Backwards compatibility, original 1.1.0 names */ # define SSL_CTRL_GET_SERVER_TMP_KEY \ SSL_CTRL_GET_PEER_TMP_KEY diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 298efdc1cbb..0739bc9082d 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -4986,3 +4986,21 @@ int ssl_encapsulate(SSL *s, EVP_PKEY *pubkey, EVP_PKEY_CTX_free(pctx); return rv; } + +const char *SSL_group_to_name(SSL *s, int nid) { + int group_id = 0; + const TLS_GROUP_INFO *cinf = NULL; + + /* first convert to real group id for internal and external IDs */ + if (nid & TLSEXT_nid_unknown) + group_id = nid & 0xFFFF; + else + group_id = tls1_nid2group_id(nid); + + /* then look up */ + cinf = tls1_group_id_lookup(s->ctx, group_id); + + if (cinf != NULL) + return cinf->tlsname; + return NULL; +} diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h index c2a4087c3b6..22ab3874227 100644 --- a/ssl/ssl_local.h +++ b/ssl/ssl_local.h @@ -2650,6 +2650,7 @@ SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n); __owur const TLS_GROUP_INFO *tls1_group_id_lookup(SSL_CTX *ctx, uint16_t curve_id); __owur int tls1_group_id2nid(uint16_t group_id, int include_unknown); +__owur uint16_t tls1_nid2group_id(int nid); __owur int tls1_check_group_id(SSL *s, uint16_t group_id, int check_own_curves); __owur uint16_t tls1_shared_group(SSL *s, int nmatch); __owur int tls1_set_groups(uint16_t **pext, size_t *pextlen, diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index bc366c8a7cf..60c17dd809c 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -460,7 +460,7 @@ int tls1_group_id2nid(uint16_t group_id, int include_unknown) return TLSEXT_nid_unknown | (int)group_id; } -static uint16_t tls1_nid2group_id(int nid) +uint16_t tls1_nid2group_id(int nid) { size_t i; diff --git a/test/sslapitest.c b/test/sslapitest.c index 915387a87c6..984c6a8764b 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -4318,6 +4318,7 @@ static int test_key_exchange(int idx) int *kexch_groups = &kexch_alg; int kexch_groups_size = 1; int max_version = TLS1_3_VERSION; + char *kexch_name0 = NULL; switch (idx) { # ifndef OPENSSL_NO_EC @@ -4329,47 +4330,60 @@ static int test_key_exchange(int idx) case 0: kexch_groups = ecdhe_kexch_groups; kexch_groups_size = OSSL_NELEM(ecdhe_kexch_groups); + kexch_name0 = "secp256r1"; break; case 1: kexch_alg = NID_X9_62_prime256v1; + kexch_name0 = "secp256r1"; break; case 2: kexch_alg = NID_secp384r1; + kexch_name0 = "secp384r1"; break; case 3: kexch_alg = NID_secp521r1; + kexch_name0 = "secp521r1"; break; case 4: kexch_alg = NID_X25519; + kexch_name0 = "x25519"; break; case 5: kexch_alg = NID_X448; + kexch_name0 = "x448"; break; # endif # ifndef OPENSSL_NO_DH # ifndef OPENSSL_NO_TLS1_2 case 13: max_version = TLS1_2_VERSION; + kexch_name0 = "ffdhe2048"; # endif /* Fall through */ case 6: kexch_groups = ffdhe_kexch_groups; kexch_groups_size = OSSL_NELEM(ffdhe_kexch_groups); + kexch_name0 = "ffdhe2048"; break; case 7: kexch_alg = NID_ffdhe2048; + kexch_name0 = "ffdhe2048"; break; case 8: kexch_alg = NID_ffdhe3072; + kexch_name0 = "ffdhe3072"; break; case 9: kexch_alg = NID_ffdhe4096; + kexch_name0 = "ffdhe4096"; break; case 10: kexch_alg = NID_ffdhe6144; + kexch_name0 = "ffdhe6144"; break; case 11: kexch_alg = NID_ffdhe8192; + kexch_name0 = "ffdhe8192"; break; # endif default: @@ -4425,6 +4439,11 @@ static int test_key_exchange(int idx) if (!TEST_int_eq(SSL_get_shared_group(serverssl, 0), idx == 13 ? 0 : kexch_groups[0])) goto end; + + if (!TEST_str_eq(SSL_group_to_name(serverssl, kexch_groups[0]), + kexch_name0)) + goto end; + if (max_version == TLS1_3_VERSION) { if (!TEST_int_eq(SSL_get_negotiated_group(serverssl), kexch_groups[0])) goto end; @@ -8000,6 +8019,10 @@ static int test_pluggable_group(int idx) if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) goto end; + if (!TEST_str_eq(group_name, + SSL_group_to_name(serverssl, SSL_get_shared_group(serverssl, 0)))) + goto end; + testresult = 1; end: diff --git a/util/libssl.num b/util/libssl.num index 37b0d377358..cd620677635 100644 --- a/util/libssl.num +++ b/util/libssl.num @@ -519,3 +519,4 @@ SSL_get1_peer_certificate ? 3_0_0 EXIST::FUNCTION: SSL_load_client_CA_file_ex ? 3_0_0 EXIST::FUNCTION: SSL_set0_tmp_dh_pkey ? 3_0_0 EXIST::FUNCTION: SSL_CTX_set0_tmp_dh_pkey ? 3_0_0 EXIST::FUNCTION: +SSL_group_to_name ? 3_0_0 EXIST::FUNCTION: