From fa8ff9e4e8e0937eb04bf16d0159c3aedbd33547 Mon Sep 17 00:00:00 2001 From: Pauli Date: Tue, 15 Jun 2021 14:06:17 +1000 Subject: [PATCH] apps: limit get_cipher() to not return AEAD or XTS ciphers Add a get_cipher_any() function to access these in addition to more normal ciphers Fixes #7720 Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/15747) --- apps/include/opt.h | 1 + apps/lib/opt.c | 43 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/apps/include/opt.h b/apps/include/opt.h index 96e78e4b79..4a292213fd 100644 --- a/apps/include/opt.h +++ b/apps/include/opt.h @@ -366,6 +366,7 @@ char *opt_flag(void); char *opt_arg(void); char *opt_unknown(void); int opt_cipher(const char *name, EVP_CIPHER **cipherp); +int opt_cipher_any(const char *name, EVP_CIPHER **cipherp); int opt_cipher_silent(const char *name, EVP_CIPHER **cipherp); int opt_md(const char *name, EVP_MD **mdp); int opt_md_silent(const char *name, EVP_MD **mdp); diff --git a/apps/lib/opt.c b/apps/lib/opt.c index c6a506480a..c88c99b5e6 100644 --- a/apps/lib/opt.c +++ b/apps/lib/opt.c @@ -368,27 +368,58 @@ void print_format_error(int format, unsigned long flags) (void)opt_format_error(format2str(format), flags); } -/* Parse a cipher name, put it in *EVP_CIPHER; return 0 on failure, else 1. */ +/* + * Parse a cipher name, put it in *cipherp after freeing what was there, if + * cipherp is not NULL. Return 0 on failure, else 1. + */ int opt_cipher_silent(const char *name, EVP_CIPHER **cipherp) { - EVP_CIPHER_free(*cipherp); + EVP_CIPHER *c; ERR_set_mark(); - if ((*cipherp = EVP_CIPHER_fetch(NULL, name, NULL)) != NULL - || (*cipherp = (EVP_CIPHER *)EVP_get_cipherbyname(name)) != NULL) { + if ((c = EVP_CIPHER_fetch(NULL, name, NULL)) != NULL + || (c = (EVP_CIPHER *)EVP_get_cipherbyname(name)) != NULL) { ERR_pop_to_mark(); + if (cipherp != NULL) { + EVP_CIPHER_free(*cipherp); + *cipherp = c; + } else { + EVP_CIPHER_free(c); + } return 1; } ERR_clear_last_mark(); return 0; } -int opt_cipher(const char *name, EVP_CIPHER **cipherp) +int opt_cipher_any(const char *name, EVP_CIPHER **cipherp) { int ret; if ((ret = opt_cipher_silent(name, cipherp)) == 0) - opt_printf_stderr("%s: Unknown cipher: %s\n", prog, name); + opt_printf_stderr("%s: Unknown cipher: %s\n", prog, name); + return ret; +} + +int opt_cipher(const char *name, EVP_CIPHER **cipherp) +{ + int mode, ret = 0; + unsigned long int flags; + EVP_CIPHER *c = NULL; + + if (opt_cipher_any(name, &c)) { + mode = EVP_CIPHER_get_mode(c); + flags = EVP_CIPHER_get_flags(c); + if (mode == EVP_CIPH_XTS_MODE) { + opt_printf_stderr("%s XTS ciphers not supported\n", prog); + } else if ((flags & EVP_CIPH_FLAG_AEAD_CIPHER) != 0) { + opt_printf_stderr("%s: AEAD ciphers not supported\n", prog); + } else { + ret = 1; + if (cipherp != NULL) + *cipherp = c; + } + } return ret; } -- 2.34.1