'openssl list' and 'openssl provider': adapt display of multiple names
authorRichard Levitte <levitte@openssl.org>
Mon, 23 Sep 2019 09:30:05 +0000 (11:30 +0200)
committerRichard Levitte <levitte@openssl.org>
Thu, 17 Oct 2019 07:16:45 +0000 (09:16 +0200)
Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/9979)

apps/include/names.h [new file with mode: 0644]
apps/lib/build.info
apps/lib/names.c [new file with mode: 0644]
apps/list.c
apps/provider.c
doc/man1/openssl-list.pod

diff --git a/apps/include/names.h b/apps/include/names.h
new file mode 100644 (file)
index 0000000..f4d6f6a
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 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
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/safestack.h>
+
+/* Standard comparing function for names */
+int name_cmp(const char * const *a, const char * const *b);
+/* collect_names is meant to be used with EVP_{type}_doall_names */
+void collect_names(const char *name, void *vdata);
+/* Sorts and prints a stack of names to |out| */
+void print_names(BIO *out, STACK_OF(OPENSSL_CSTRING) *names);
index f92d4da..0c24d76 100644 (file)
@@ -9,7 +9,7 @@ ENDIF
 
 # Source for libapps
 $LIBAPPSSRC=apps.c apps_ui.c opt.c fmt.c s_cb.c s_socket.c app_rand.c \
-        bf_prefix.c columns.c app_params.c
+        bf_prefix.c columns.c app_params.c names.c
 
 IF[{- !$disabled{apps} -}]
   LIBS{noinst}=../libapps.a
diff --git a/apps/lib/names.c b/apps/lib/names.c
new file mode 100644 (file)
index 0000000..09ee16f
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2019 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
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <openssl/bio.h>
+#include <openssl/safestack.h>
+#include "names.h"
+
+#ifdef _WIN32
+# define strcasecmp _stricmp
+#endif
+
+int name_cmp(const char * const *a, const char * const *b)
+{
+    return strcasecmp(*a, *b);
+}
+
+void collect_names(const char *name, void *vdata)
+{
+    STACK_OF(OPENSSL_CSTRING) *names = vdata;
+
+    sk_OPENSSL_CSTRING_push(names, name);
+}
+
+void print_names(BIO *out, STACK_OF(OPENSSL_CSTRING) *names)
+{
+    int i = sk_OPENSSL_CSTRING_num(names);
+    int j;
+
+    sk_OPENSSL_CSTRING_sort(names);
+    if (i > 1)
+        BIO_printf(out, "{ ");
+    for (j = 0; j < i; j++) {
+        const char *name = sk_OPENSSL_CSTRING_value(names, j);
+
+        if (j > 0)
+            BIO_printf(out, ", ");
+        BIO_printf(out, "%s", name);
+    }
+    if (i > 1)
+        BIO_printf(out, " }");
+}
index 1a43e43..2e8867d 100644 (file)
@@ -17,6 +17,7 @@
 #include "app_params.h"
 #include "progs.h"
 #include "opt.h"
+#include "names.h"
 
 static int verbose = 0;
 
@@ -38,7 +39,7 @@ DEFINE_STACK_OF(EVP_CIPHER)
 static int cipher_cmp(const EVP_CIPHER * const *a,
                       const EVP_CIPHER * const *b)
 {
-    int ret = strcasecmp(EVP_CIPHER_name(*a), EVP_CIPHER_name(*b));
+    int ret = EVP_CIPHER_number(*a) - EVP_CIPHER_number(*b);
 
     if (ret == 0)
         ret = strcmp(OSSL_PROVIDER_name(EVP_CIPHER_provider(*a)),
@@ -64,14 +65,22 @@ static void list_ciphers(void)
     EVP_CIPHER_do_all_sorted(legacy_cipher_fn, bio_out);
 
     BIO_printf(bio_out, "Provided:\n");
-    EVP_CIPHER_do_all_ex(NULL, collect_ciphers, ciphers);
+    EVP_CIPHER_do_all_provided(NULL, collect_ciphers, ciphers);
     sk_EVP_CIPHER_sort(ciphers);
     for (i = 0; i < sk_EVP_CIPHER_num(ciphers); i++) {
         const EVP_CIPHER *c = sk_EVP_CIPHER_value(ciphers, i);
+        STACK_OF(OPENSSL_CSTRING) *names =
+            sk_OPENSSL_CSTRING_new(name_cmp);
 
-        BIO_printf(bio_out, "  %s", EVP_CIPHER_name(c));
+        EVP_CIPHER_names_do_all(c, collect_names, names);
+
+        BIO_printf(bio_out, "  ");
+        print_names(bio_out, names);
         BIO_printf(bio_out, " @ %s\n",
                    OSSL_PROVIDER_name(EVP_CIPHER_provider(c)));
+
+        sk_OPENSSL_CSTRING_free(names);
+
         if (verbose) {
             print_param_types("retrievable algorithm parameters",
                               EVP_CIPHER_gettable_params(c), 4);
@@ -101,7 +110,7 @@ static void list_md_fn(const EVP_MD *m,
 DEFINE_STACK_OF(EVP_MD)
 static int md_cmp(const EVP_MD * const *a, const EVP_MD * const *b)
 {
-    int ret = strcasecmp(EVP_MD_name(*a), EVP_MD_name(*b));
+    int ret = EVP_MD_number(*a) - EVP_MD_number(*b);
 
     if (ret == 0)
         ret = strcmp(OSSL_PROVIDER_name(EVP_MD_provider(*a)),
@@ -127,14 +136,22 @@ static void list_digests(void)
     EVP_MD_do_all_sorted(list_md_fn, bio_out);
 
     BIO_printf(bio_out, "Provided:\n");
-    EVP_MD_do_all_ex(NULL, collect_digests, digests);
+    EVP_MD_do_all_provided(NULL, collect_digests, digests);
     sk_EVP_MD_sort(digests);
     for (i = 0; i < sk_EVP_MD_num(digests); i++) {
         const EVP_MD *m = sk_EVP_MD_value(digests, i);
+        STACK_OF(OPENSSL_CSTRING) *names =
+            sk_OPENSSL_CSTRING_new(name_cmp);
 
-        BIO_printf(bio_out, "  %s", EVP_MD_name(m));
+        EVP_MD_names_do_all(m, collect_names, names);
+
+        BIO_printf(bio_out, "  ");
+        print_names(bio_out, names);
         BIO_printf(bio_out, " @ %s\n",
                    OSSL_PROVIDER_name(EVP_MD_provider(m)));
+
+        sk_OPENSSL_CSTRING_free(names);
+
         if (verbose) {
             print_param_types("retrievable algorithm parameters",
                               EVP_MD_gettable_params(m), 4);
@@ -150,7 +167,7 @@ static void list_digests(void)
 DEFINE_STACK_OF(EVP_MAC)
 static int mac_cmp(const EVP_MAC * const *a, const EVP_MAC * const *b)
 {
-    int ret = strcasecmp(EVP_MAC_name(*a), EVP_MAC_name(*b));
+    int ret = EVP_MAC_number(*a) - EVP_MAC_number(*b);
 
     if (ret == 0)
         ret = strcmp(OSSL_PROVIDER_name(EVP_MAC_provider(*a)),
@@ -173,15 +190,22 @@ static void list_macs(void)
     int i;
 
     BIO_printf(bio_out, "Provided MACs:\n");
-    EVP_MAC_do_all_ex(NULL, collect_macs, macs);
+    EVP_MAC_do_all_provided(NULL, collect_macs, macs);
     sk_EVP_MAC_sort(macs);
     for (i = 0; i < sk_EVP_MAC_num(macs); i++) {
         const EVP_MAC *m = sk_EVP_MAC_value(macs, i);
+        STACK_OF(OPENSSL_CSTRING) *names =
+            sk_OPENSSL_CSTRING_new(name_cmp);
+
+        EVP_MAC_names_do_all(m, collect_names, names);
 
-        BIO_printf(bio_out, "  %s", EVP_MAC_name(m));
+        BIO_printf(bio_out, "  ");
+        print_names(bio_out, names);
         BIO_printf(bio_out, " @ %s\n",
                    OSSL_PROVIDER_name(EVP_MAC_provider(m)));
 
+        sk_OPENSSL_CSTRING_free(names);
+
         if (verbose) {
             print_param_types("retrievable algorithm parameters",
                               EVP_MAC_gettable_params(m), 4);
@@ -200,7 +224,7 @@ static void list_macs(void)
 DEFINE_STACK_OF(EVP_KDF)
 static int kdf_cmp(const EVP_KDF * const *a, const EVP_KDF * const *b)
 {
-    int ret = strcasecmp(EVP_KDF_name(*a), EVP_KDF_name(*b));
+    int ret = EVP_KDF_number(*a) - EVP_KDF_number(*b);
 
     if (ret == 0)
         ret = strcmp(OSSL_PROVIDER_name(EVP_KDF_provider(*a)),
@@ -223,22 +247,29 @@ static void list_kdfs(void)
     int i;
 
     BIO_printf(bio_out, "Provided KDFs and PDFs:\n");
-    EVP_KDF_do_all_ex(NULL, collect_kdfs, kdfs);
+    EVP_KDF_do_all_provided(NULL, collect_kdfs, kdfs);
     sk_EVP_KDF_sort(kdfs);
     for (i = 0; i < sk_EVP_KDF_num(kdfs); i++) {
-        const EVP_KDF *m = sk_EVP_KDF_value(kdfs, i);
+        const EVP_KDF *k = sk_EVP_KDF_value(kdfs, i);
+        STACK_OF(OPENSSL_CSTRING) *names =
+            sk_OPENSSL_CSTRING_new(name_cmp);
 
-        BIO_printf(bio_out, "  %s", EVP_KDF_name(m));
+        EVP_KDF_names_do_all(k, collect_names, names);
+
+        BIO_printf(bio_out, "  ");
+        print_names(bio_out, names);
         BIO_printf(bio_out, " @ %s\n",
-                   OSSL_PROVIDER_name(EVP_KDF_provider(m)));
+                   OSSL_PROVIDER_name(EVP_KDF_provider(k)));
+
+        sk_OPENSSL_CSTRING_free(names);
 
         if (verbose) {
             print_param_types("retrievable algorithm parameters",
-                              EVP_KDF_gettable_params(m), 4);
+                              EVP_KDF_gettable_params(k), 4);
             print_param_types("retrievable operation parameters",
-                              EVP_KDF_gettable_ctx_params(m), 4);
+                              EVP_KDF_gettable_ctx_params(k), 4);
             print_param_types("settable operation parameters",
-                              EVP_KDF_settable_ctx_params(m), 4);
+                              EVP_KDF_settable_ctx_params(k), 4);
         }
     }
     sk_EVP_KDF_pop_free(kdfs, EVP_KDF_free);
index ab91e68..325a742 100644 (file)
@@ -12,6 +12,7 @@
 #include "apps.h"
 #include "app_params.h"
 #include "progs.h"
+#include "names.h"
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/safestack.h>
@@ -40,7 +41,7 @@ typedef struct info_st INFO;
 typedef struct meta_st META;
 
 struct info_st {
-    const char *name;
+    void (*collect_names_fn)(void *method, STACK_OF(OPENSSL_CSTRING) *names);
     void *method;
     const OSSL_PARAM *gettable_params;
     const OSSL_PARAM *gettable_ctx_params;
@@ -58,11 +59,58 @@ struct meta_st {
     void (*fn)(META *meta, INFO *info);
 };
 
+static void collect_cipher_names(void *method,
+                                 STACK_OF(OPENSSL_CSTRING) *names)
+{
+    EVP_CIPHER_names_do_all(method, collect_names, names);
+}
+
+static void collect_digest_names(void *method,
+                                 STACK_OF(OPENSSL_CSTRING) *names)
+{
+    EVP_MD_names_do_all(method, collect_names, names);
+}
+
+static void collect_mac_names(void *method,
+                              STACK_OF(OPENSSL_CSTRING) *names)
+{
+    EVP_MAC_names_do_all(method, collect_names, names);
+}
+
+static void collect_keymgmt_names(void *method,
+                                  STACK_OF(OPENSSL_CSTRING) *names)
+{
+    EVP_KEYMGMT_names_do_all(method, collect_names, names);
+}
+
+static void collect_keyexch_names(void *method,
+                                  STACK_OF(OPENSSL_CSTRING) *names)
+{
+    EVP_KEYEXCH_names_do_all(method, collect_names, names);
+}
+
+static void collect_signature_names(void *method,
+                                  STACK_OF(OPENSSL_CSTRING) *names)
+{
+    EVP_SIGNATURE_names_do_all(method, collect_names, names);
+}
+
+static void print_method_names(BIO *out, INFO *info)
+{
+    STACK_OF(OPENSSL_CSTRING) *names = sk_OPENSSL_CSTRING_new(name_cmp);
+
+    info->collect_names_fn(info->method, names);
+    print_names(out, names);
+    sk_OPENSSL_CSTRING_free(names);
+}
+
 static void print_caps(META *meta, INFO *info)
 {
     switch (meta->verbose) {
     case 1:
-        BIO_printf(bio_out, meta->first ? "%s" : " %s", info->name);
+        if (!meta->first)
+            BIO_printf(bio_out, "; ");
+        print_method_names(bio_out, info);
         break;
     case 2:
         if (meta->first) {
@@ -70,12 +118,14 @@ static void print_caps(META *meta, INFO *info)
                 BIO_printf(bio_out, "\n");
             BIO_printf(bio_out, "%*s%ss:", meta->indent, "", meta->label);
         }
-        BIO_printf(bio_out, " %s", info->name);
+        BIO_printf(bio_out, " ");
+        print_method_names(bio_out, info);
         break;
     case 3:
     default:
-        BIO_printf(bio_out, "%*s%s %s\n", meta->indent, "", meta->label,
-                   info->name);
+        BIO_printf(bio_out, "%*s%s ", meta->indent, "", meta->label);
+        print_method_names(bio_out, info);
+        BIO_printf(bio_out, "\n");
         print_param_types("retrievable algorithm parameters",
                           info->gettable_params, meta->subindent);
         print_param_types("retrievable operation parameters",
@@ -87,7 +137,9 @@ static void print_caps(META *meta, INFO *info)
     meta->first = 0;
 }
 
-static void do_method(void *method, const char *name,
+static void do_method(void *method,
+                      void (*collect_names_fn)(void *method,
+                                               STACK_OF(OPENSSL_CSTRING) *names),
                       const OSSL_PARAM *gettable_params,
                       const OSSL_PARAM *gettable_ctx_params,
                       const OSSL_PARAM *settable_ctx_params,
@@ -95,7 +147,7 @@ static void do_method(void *method, const char *name,
 {
     INFO info;
 
-    info.name = name;
+    info.collect_names_fn = collect_names_fn;
     info.method = method;
     info.gettable_params = gettable_params;
     info.gettable_ctx_params = gettable_ctx_params;
@@ -106,7 +158,7 @@ static void do_method(void *method, const char *name,
 
 static void do_cipher(EVP_CIPHER *cipher, void *meta)
 {
-    do_method(cipher, EVP_CIPHER_name(cipher),
+    do_method(cipher, collect_cipher_names,
               EVP_CIPHER_gettable_params(cipher),
               EVP_CIPHER_gettable_ctx_params(cipher),
               EVP_CIPHER_settable_ctx_params(cipher),
@@ -115,7 +167,7 @@ static void do_cipher(EVP_CIPHER *cipher, void *meta)
 
 static void do_digest(EVP_MD *digest, void *meta)
 {
-    do_method(digest, EVP_MD_name(digest),
+    do_method(digest, collect_digest_names,
               EVP_MD_gettable_params(digest),
               EVP_MD_gettable_ctx_params(digest),
               EVP_MD_settable_ctx_params(digest),
@@ -124,35 +176,60 @@ static void do_digest(EVP_MD *digest, void *meta)
 
 static void do_mac(EVP_MAC *mac, void *meta)
 {
-    do_method(mac, EVP_MAC_name(mac),
+    do_method(mac, collect_mac_names,
               EVP_MAC_gettable_params(mac),
               EVP_MAC_gettable_ctx_params(mac),
               EVP_MAC_settable_ctx_params(mac),
               meta);
 }
 
+static void do_keymgmt(EVP_KEYMGMT *keymgmt, void *meta)
+{
+    do_method(keymgmt, collect_keymgmt_names,
 /*
  * TODO(3.0) Enable when KEYMGMT and KEYEXCH have gettables and settables
  */
 #if 0
-static void do_keymgmt(EVP_KEYMGMT *keymgmt, void *meta)
-{
-    do_method(keymgmt, EVP_KEYMGMT_name(keymgmt),
               EVP_KEYMGMT_gettable_params(keymgmt),
               EVP_KEYMGMT_gettable_ctx_params(keymgmt),
               EVP_KEYMGMT_settable_ctx_params(keymgmt),
+#else
+              NULL, NULL, NULL,
+#endif
               meta);
 }
 
 static void do_keyexch(EVP_KEYEXCH *keyexch, void *meta)
 {
-    do_method(keyexch, EVP_KEYEXCH_name(keyexch),
+    do_method(keyexch, collect_keyexch_names,
+/*
+ * TODO(3.0) Enable when KEYMGMT and KEYEXCH have gettables and settables
+ */
+#if 0
               EVP_KEYEXCH_gettable_params(keyexch),
               EVP_KEYEXCH_gettable_ctx_params(keyexch),
               EVP_KEYEXCH_settable_ctx_params(keyexch),
+#else
+              NULL, NULL, NULL,
+#endif
               meta);
 }
+
+static void do_signature(EVP_SIGNATURE *signature, void *meta)
+{
+    do_method(signature, collect_signature_names,
+/*
+ * TODO(3.0) Enable when KEYMGMT and SIGNATURE have gettables and settables
+ */
+#if 0
+              EVP_SIGNATURE_gettable_params(signature),
+              EVP_SIGNATURE_gettable_ctx_params(signature),
+              EVP_SIGNATURE_settable_ctx_params(signature),
+#else
+              NULL, NULL, NULL,
 #endif
+              meta);
+}
 
 int provider_main(int argc, char **argv)
 {
@@ -231,33 +308,33 @@ int provider_main(int argc, char **argv)
                     data.first = 1;
                     data.label = "Cipher";
                 }
-                EVP_CIPHER_do_all_ex(NULL, do_cipher, &data);
+                EVP_CIPHER_do_all_provided(NULL, do_cipher, &data);
                 if (verbose > 1) {
                     data.first = 1;
                     data.label = "Digest";
                 }
-                EVP_MD_do_all_ex(NULL, do_digest, &data);
+                EVP_MD_do_all_provided(NULL, do_digest, &data);
                 if (verbose > 1) {
                     data.first = 1;
                     data.label = "MAC";
                 }
-                EVP_MAC_do_all_ex(NULL, do_mac, &data);
+                EVP_MAC_do_all_provided(NULL, do_mac, &data);
 
-/*
- * TODO(3.0) Enable when KEYMGMT and KEYEXCH have do_all_ex functions
- */
-#if 0
                 if (verbose > 1) {
                     data.first = 1;
                     data.label = "Key manager";
                 }
-                EVP_KEYMGMT_do_all_ex(NULL, do_keymgmt, &data);
+                EVP_KEYMGMT_do_all_provided(NULL, do_keymgmt, &data);
                 if (verbose > 1) {
                     data.first = 1;
                     data.label = "Key exchange";
                 }
-                EVP_KEYEXCH_do_all_ex(NULL, do_keyexch, &data);
-#endif
+                EVP_KEYEXCH_do_all_provided(NULL, do_keyexch, &data);
+                if (verbose > 1) {
+                    data.first = 1;
+                    data.label = "Signature";
+                }
+                EVP_SIGNATURE_do_all_provided(NULL, do_signature, &data);
 
                 switch (verbose) {
                 default:
index 9e691c6..5388b47 100644 (file)
@@ -54,37 +54,17 @@ Display a list of standard commands.
 Display a list of message digest commands, which are typically used
 as input to the L<openssl-dgst(1)> or L<openssl-speed(1)> commands.
 
-=item B<-digest-algorithms>
-
-Display a list of message digest algorithms.
-If a line is of the form C<foo =E<gt> bar> then C<foo> is an alias for the
-official algorithm name, C<bar>.
-If a line is of the form C<foo @ bar>, then C<foo> is provided by the provider
-C<bar>.
-
-In verbose mode, the algorithms provided by a provider will get additional
-information on what parameters each implementation supports.
-
-=item B<-kdf-algorithms>
-
-Display a list of key derivation function algorithms.
-
-=item B<-mac-algorithms>
-
-Display a list of message authentication code algorithms.
-
 =item B<-cipher-commands>
 
 Display a list of cipher commands, which are typically used as input
 to the L<openssl-dgst(1)> or L<openssl-speed(1)> commands.
 
-=item B<-cipher-algorithms>
+=item B<-digest-algorithms>, B<-kdf-algorithms>, B<-mac-algorithms>,
+B<-cipher-algorithms>
 
-Display a list of cipher algorithms.
-If a line is of the form C<foo =E<gt> bar> then C<foo> is an alias for the
-official algorithm name, B<bar>.
-If a line is of the form C<foo @ bar>, then C<foo> is provided by the provider
-C<bar>.
+Display a list of cipher, digest, kdf and mac algorithms.
+See L</Display of algorithm names> for a description of how names are
+displayed.
 
 In verbose mode, the algorithms provided by a provider will get additional
 information on what parameters each implementation supports.
@@ -114,6 +94,33 @@ format described in L<config(5)/ASN1 Object Configuration Module>.
 
 =back
 
+=head2 Display of algorithm names
+
+Algorithm names may be displayed in one of two manners:
+
+=over 4
+
+=item Legacy implementations
+
+Legacy implementations will simply display the main name of the
+algorithm on a line of its own, or in the form C<<foo > bar>> to show
+that C<foo> is an alias for the main name, C<bar>
+
+=item Provided implementations
+
+Implementations from a provider are displayed like this if the
+implementation is labeled with a single name:
+
+ foo @ bar
+
+or like this if it's labeled with multiple names:
+
+ { foo1, foo2 } @bar
+
+In both cases, C<bar> is the name of the provider.
+
+=back
+
 =head1 COPYRIGHT
 
 Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.