From 031873fe03610aa191031b5a36089bc29c67db29 Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Mon, 23 Sep 2019 11:30:05 +0200 Subject: [PATCH] 'openssl list' and 'openssl provider': adapt display of multiple names Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/9979) --- apps/include/names.h | 17 ++++++ apps/lib/build.info | 2 +- apps/lib/names.c | 48 +++++++++++++++ apps/list.c | 65 ++++++++++++++------ apps/provider.c | 125 ++++++++++++++++++++++++++++++-------- doc/man1/openssl-list.pod | 57 +++++++++-------- 6 files changed, 247 insertions(+), 67 deletions(-) create mode 100644 apps/include/names.h create mode 100644 apps/lib/names.c diff --git a/apps/include/names.h b/apps/include/names.h new file mode 100644 index 0000000000..f4d6f6a9a3 --- /dev/null +++ b/apps/include/names.h @@ -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 + +/* 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); diff --git a/apps/lib/build.info b/apps/lib/build.info index f92d4dafc6..0c24d76d3c 100644 --- a/apps/lib/build.info +++ b/apps/lib/build.info @@ -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 index 0000000000..09ee16fd37 --- /dev/null +++ b/apps/lib/names.c @@ -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 +#include +#include +#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, " }"); +} diff --git a/apps/list.c b/apps/list.c index 1a43e43c56..2e8867df20 100644 --- a/apps/list.c +++ b/apps/list.c @@ -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); diff --git a/apps/provider.c b/apps/provider.c index ab91e68f43..325a7424cd 100644 --- a/apps/provider.c +++ b/apps/provider.c @@ -12,6 +12,7 @@ #include "apps.h" #include "app_params.h" #include "progs.h" +#include "names.h" #include #include #include @@ -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: diff --git a/doc/man1/openssl-list.pod b/doc/man1/openssl-list.pod index 9e691c60ce..5388b478a5 100644 --- a/doc/man1/openssl-list.pod +++ b/doc/man1/openssl-list.pod @@ -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 or L commands. -=item B<-digest-algorithms> - -Display a list of message digest algorithms. -If a line is of the form C bar> then C is an alias for the -official algorithm name, C. -If a line is of the form C, then C is provided by the provider -C. - -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 or L 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 bar> then C is an alias for the -official algorithm name, B. -If a line is of the form C, then C is provided by the provider -C. +Display a list of cipher, digest, kdf and mac algorithms. +See L 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. =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< bar>> to show +that C is an alias for the main name, C + +=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 is the name of the provider. + +=back + =head1 COPYRIGHT Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. -- 2.25.1