'openssl list' and 'openssl provider': adapt display of multiple names

Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/9979)
This commit is contained in:
Richard Levitte 2019-09-23 11:30:05 +02:00
parent 506cb0f632
commit 031873fe03
6 changed files with 247 additions and 67 deletions

17
apps/include/names.h Normal file
View File

@ -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);

View 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

48
apps/lib/names.c Normal file
View File

@ -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, " }");
}

View 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);
BIO_printf(bio_out, " %s", EVP_MAC_name(m));
EVP_MAC_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_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);

View 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:

View 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.