apps: limit get_cipher() to not return AEAD or XTS ciphers
authorPauli <pauli@openssl.org>
Tue, 15 Jun 2021 04:06:17 +0000 (14:06 +1000)
committerPauli <pauli@openssl.org>
Wed, 16 Jun 2021 08:32:30 +0000 (18:32 +1000)
Add a get_cipher_any() function to access these in addition to more normal ciphers

Fixes #7720

Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15747)

apps/include/opt.h
apps/lib/opt.c

index 96e78e4b79bad7b503df976f7e2a4ed33389bb8f..4a292213fd9042d21926c3fd422d9814ff1b2b5e 100644 (file)
@@ -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);
index c6a506480aa4e0d7387d879616fb782fd562433e..c88c99b5e6425fb2b4ebef413c87540caeab1c8d 100644 (file)
@@ -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;
 }