Adding TLS group name retrieval
authorMichael Baentsch <info@baentsch.ch>
Thu, 7 Jan 2021 08:09:32 +0000 (09:09 +0100)
committerMatt Caswell <matt@openssl.org>
Fri, 8 Jan 2021 17:04:46 +0000 (17:04 +0000)
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 <tmraz@fedoraproject.org>
Reviewed-by: Nicola Tuveri <nic.tuv@gmail.com>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/13785)

apps/lib/s_cb.c
doc/man3/SSL_group_to_name.pod [new file with mode: 0644]
include/openssl/ssl.h.in
ssl/s3_lib.c
ssl/ssl_local.h
ssl/t1_lib.c
test/sslapitest.c
util/libssl.num

index c7994417aa90752b84abdf1163a1ab64f5bcc792..67e0fbd5bd88f77793e976ea2f31b2069028d8d3 100644 (file)
@@ -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 (file)
index 0000000..9c0e75c
--- /dev/null
@@ -0,0 +1,43 @@
+=pod
+
+=head1 NAME
+
+SSL_group_to_name - get name of group
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+ 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<id> 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<ssl>.
+
+=head1 SEE ALSO
+
+L<ssl(7)>
+
+=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<https://www.openssl.org/source/license.html>.
+
+=cut
index 37b4c82f02534a7fe2bfb104d46191baa6484b7a..4e5d50bd6dbe97dd01cc588034ac1c0bb8b9e709 100644 (file)
@@ -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
index 298efdc1cbbcb8a54ba9e42eec54ba2cfd172986..0739bc9082d7d316d4802e29b730a791293086d3 100644 (file)
@@ -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;
+}
index c2a4087c3b6c85e796a8bd72bf2cd4b814d441ff..22ab387422796271a91b298ed689e69d65a609e7 100644 (file)
@@ -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,
index bc366c8a7cf1b7f2c22165df37bd64678d89dcb3..60c17dd809c0fef7964cdb5ed5fce2ae6c17aff0 100644 (file)
@@ -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;
 
index 915387a87c699d963711155ff9d13551a34dee5e..984c6a8764b30ab441fc007a5d49b63c4bd12784 100644 (file)
@@ -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:
index 37b0d377358c2005754593d415ce88698557101b..cd620677635f6338259087be7063000809cb73bf 100644 (file)
@@ -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: