Add a gettable for provider ciphers to return the EVP_CIPH_RAND_KEY flag
authorShane Lontis <shane.lontis@oracle.com>
Thu, 3 Jun 2021 09:09:38 +0000 (19:09 +1000)
committerPauli <pauli@openssl.org>
Tue, 8 Jun 2021 05:16:06 +0000 (15:16 +1000)
Fixes #15531

DES and TDES set this flag which could possibly be used by applications.
The gettable cipher param OSSL_CIPHER_PARAM_HAS_RAND_KEY has been added.

Note that EVP_CIPHER_CTX_rand_key() uses this flag.

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

crypto/evp/evp_lib.c
doc/man3/EVP_EncryptInit.pod
include/openssl/core_names.h
providers/implementations/ciphers/cipher_des.c
providers/implementations/ciphers/cipher_tdes.h
providers/implementations/ciphers/cipher_tdes_wrap.c
providers/implementations/ciphers/ciphercommon.c
providers/implementations/include/prov/ciphercommon.h
test/evp_libctx_test.c

index bb91b22678852e860da5ddf387ca1d5938b72be5..0b08c9adfd1d321390f7f0cd58b0a91a6eff7a9a 100644 (file)
@@ -340,12 +340,12 @@ int EVP_CIPHER_get_type(const EVP_CIPHER *cipher)
 
 int evp_cipher_cache_constants(EVP_CIPHER *cipher)
 {
-    int ok, aead = 0, custom_iv = 0, cts = 0, multiblock = 0;
+    int ok, aead = 0, custom_iv = 0, cts = 0, multiblock = 0, randkey = 0;
     size_t ivlen = 0;
     size_t blksz = 0;
     size_t keylen = 0;
     unsigned int mode = 0;
-    OSSL_PARAM params[9];
+    OSSL_PARAM params[10];
 
     params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_BLOCK_SIZE, &blksz);
     params[1] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_IVLEN, &ivlen);
@@ -357,7 +357,9 @@ int evp_cipher_cache_constants(EVP_CIPHER *cipher)
     params[6] = OSSL_PARAM_construct_int(OSSL_CIPHER_PARAM_CTS, &cts);
     params[7] = OSSL_PARAM_construct_int(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK,
                                          &multiblock);
-    params[8] = OSSL_PARAM_construct_end();
+    params[8] = OSSL_PARAM_construct_int(OSSL_CIPHER_PARAM_HAS_RAND_KEY,
+                                         &randkey);
+    params[9] = OSSL_PARAM_construct_end();
     ok = evp_do_ciph_getparams(cipher, params) > 0;
     if (ok) {
         cipher->block_size = blksz;
@@ -374,6 +376,8 @@ int evp_cipher_cache_constants(EVP_CIPHER *cipher)
             cipher->flags |= EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK;
         if (cipher->ccipher != NULL)
             cipher->flags |= EVP_CIPH_FLAG_CUSTOM_CIPHER;
+        if (randkey)
+            cipher->flags |= EVP_CIPH_RAND_KEY;
         if (OSSL_PARAM_locate_const(EVP_CIPHER_gettable_ctx_params(cipher),
                                     OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS))
             cipher->flags |= EVP_CIPH_FLAG_CUSTOM_ASN1;
index 965e0d92489e2e52117c11eb95b5f4de87713489..4b90cdd7802844f9a8ab9bfb2e5496b2e588b2d7 100644 (file)
@@ -679,6 +679,12 @@ TLS ciphers.
 Use (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK) to retrieve the
 cached value.
 
+=item "has-randkey" (B<OSSL_CIPHER_PARAM_HAS_RANDKEY>) <integer>
+
+Gets 1 if the cipher algorithm I<cipher> supports the gettable EVP_CIPHER_CTX
+parameter B<OSSL_CIPHER_PARAM_RANDOM_KEY>. Only DES and 3DES set this to 1,
+all other OpenSSL ciphers return 0.
+
 =back
 
 =head2 Gettable and Settable EVP_CIPHER_CTX parameters
@@ -1115,6 +1121,10 @@ See L</Gettable EVP_CIPHER parameters> "cts".
 
 See L</Gettable EVP_CIPHER parameters> "tls-multi".
 
+=item EVP_CIPH_RAND_KEY
+
+See L</Gettable EVP_CIPHER parameters> "has-randkey".
+
 =back
 
 EVP_CIPHER_flags() uses the following flags for legacy purposes only:
@@ -1131,8 +1141,6 @@ EVP_CIPHER_flags() uses the following flags for legacy purposes only:
 
 =item EVP_CIPH_CUSTOM_KEY_LENGTH
 
-=item EVP_CIPH_RAND_KEY
-
 =item EVP_CIPH_CUSTOM_COPY
 
 =item EVP_CIPH_FLAG_DEFAULT_ASN1
index 097dbc1c04a86f1704248b88a52f7acc81a22775..f99497e22942009fd1e72cae5838a150b1eda1a1 100644 (file)
@@ -75,6 +75,7 @@ extern "C" {
 #define OSSL_CIPHER_PARAM_CUSTOM_IV            "custom-iv"    /* int, 0 or 1 */
 #define OSSL_CIPHER_PARAM_CTS                  "cts"          /* int, 0 or 1 */
 #define OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK      "tls-multi"    /* int, 0 or 1 */
+#define OSSL_CIPHER_PARAM_HAS_RAND_KEY         "has-randkey"  /* int, 0 or 1 */
 #define OSSL_CIPHER_PARAM_KEYLEN               "keylen"       /* size_t */
 #define OSSL_CIPHER_PARAM_IVLEN                "ivlen"        /* size_t */
 #define OSSL_CIPHER_PARAM_IV                   "iv"           /* octet_string OR octet_ptr */
index d03d65b668d3800726d9ace13443d31eaa124d64..c6d13466f79d8a27dd417f4d14c185263921ee5a 100644 (file)
@@ -20,7 +20,7 @@
 #include "prov/implementations.h"
 #include "prov/providercommon.h"
 
-#define DES_FLAGS 0
+#define DES_FLAGS PROV_CIPHER_FLAG_RAND_KEY
 
 static OSSL_FUNC_cipher_freectx_fn des_freectx;
 static OSSL_FUNC_cipher_encrypt_init_fn des_einit;
index d3d885bd180304384216b9892e208ceda19acf50..93f9d1744dc912762007179c802e263a133f2178 100644 (file)
@@ -13,7 +13,7 @@
 
 #define DES_BLOCK_SIZE 8
 #define TDES_IVLEN 8
-#define TDES_FLAGS 0
+#define TDES_FLAGS PROV_CIPHER_FLAG_RAND_KEY
 
 typedef struct prov_tdes_ctx_st {
     PROV_CIPHER_CTX base;      /* Must be first */
index f6a859539e8f9fd0eb647f00d77333bd9cf5924c..1b4539a64ce32de0b98a9f0e75581886c7938d1d 100644 (file)
@@ -22,7 +22,7 @@
 #include "prov/implementations.h"
 #include "prov/providercommon.h"
 
-#define TDES_WRAP_FLAGS PROV_CIPHER_FLAG_CUSTOM_IV
+#define TDES_WRAP_FLAGS PROV_CIPHER_FLAG_CUSTOM_IV | PROV_CIPHER_FLAG_RAND_KEY
 
 static OSSL_FUNC_cipher_update_fn tdes_wrap_update;
 static OSSL_FUNC_cipher_cipher_fn tdes_wrap_cipher;
index b5a0d43b7880e2f981d3335ab715f7e6cdb58477..fa383165d83c5b67b812ec73d347c6b47b464e0b 100644 (file)
@@ -30,6 +30,7 @@ static const OSSL_PARAM cipher_known_gettable_params[] = {
     OSSL_PARAM_int(OSSL_CIPHER_PARAM_CUSTOM_IV, NULL),
     OSSL_PARAM_int(OSSL_CIPHER_PARAM_CTS, NULL),
     OSSL_PARAM_int(OSSL_CIPHER_PARAM_TLS1_MULTIBLOCK, NULL),
+    OSSL_PARAM_int(OSSL_CIPHER_PARAM_HAS_RAND_KEY, NULL),
     OSSL_PARAM_END
 };
 const OSSL_PARAM *ossl_cipher_generic_gettable_params(ossl_unused void *provctx)
@@ -72,6 +73,12 @@ int ossl_cipher_generic_get_params(OSSL_PARAM params[], unsigned int md,
         ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
         return 0;
     }
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_HAS_RAND_KEY);
+    if (p != NULL
+        && !OSSL_PARAM_set_int(p, (flags & PROV_CIPHER_FLAG_RAND_KEY) != 0)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
     p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
     if (p != NULL && !OSSL_PARAM_set_size_t(p, kbits / 8)) {
         ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
index 7ccc9c7047d04cb48dd70047e9cabe17cfca16ef..91c4c914beb9c65b6cf68e921d49507869f2bda6 100644 (file)
@@ -36,9 +36,10 @@ typedef int (PROV_CIPHER_HW_FN)(PROV_CIPHER_CTX *dat, unsigned char *out,
 #define PROV_CIPHER_FLAG_CUSTOM_IV        0x0002
 #define PROV_CIPHER_FLAG_CTS              0x0004
 #define PROV_CIPHER_FLAG_TLS1_MULTIBLOCK  0x0008
+#define PROV_CIPHER_FLAG_RAND_KEY         0x0010
 /* Internal flags that are only used within the provider */
-#define PROV_CIPHER_FLAG_VARIABLE_LENGTH  0x0010
-#define PROV_CIPHER_FLAG_INVERSE_CIPHER   0x0020
+#define PROV_CIPHER_FLAG_VARIABLE_LENGTH  0x0100
+#define PROV_CIPHER_FLAG_INVERSE_CIPHER   0x0200
 
 struct prov_cipher_ctx_st {
     block128_f block;
index b9794b6b7d38320f02c26394a37badea53e7b314..bfbbafdbab9ca698df726db0043581b329772b6a 100644 (file)
@@ -557,6 +557,33 @@ static int kem_rsa_gen_recover(void)
     return ret;
 }
 
+#ifndef OPENSSL_NO_DES
+/*
+ * This test makes sure that EVP_CIPHER_CTX_rand_key() works correctly
+ * For fips mode this code would produce an error if the flag is not set.
+ */
+static int test_cipher_tdes_randkey(void)
+{
+    int ret;
+    EVP_CIPHER_CTX *ctx = NULL;
+    EVP_CIPHER *tdes_cipher = NULL, *aes_cipher = NULL;
+    unsigned char key[24] = { 0 };
+
+    ret = TEST_ptr(aes_cipher = EVP_CIPHER_fetch(libctx, "AES-256-CBC", NULL))
+          && TEST_int_eq(EVP_CIPHER_get_flags(aes_cipher) & EVP_CIPH_RAND_KEY, 0)
+          && TEST_ptr(tdes_cipher = EVP_CIPHER_fetch(libctx, "DES-EDE3-CBC", NULL))
+          && TEST_int_ne(EVP_CIPHER_get_flags(tdes_cipher) & EVP_CIPH_RAND_KEY, 0)
+          && TEST_ptr(ctx = EVP_CIPHER_CTX_new())
+          && TEST_true(EVP_CipherInit_ex(ctx, tdes_cipher, NULL, NULL, NULL, 1))
+          && TEST_true(EVP_CIPHER_CTX_rand_key(ctx, key));
+
+    EVP_CIPHER_CTX_free(ctx);
+    EVP_CIPHER_free(tdes_cipher);
+    EVP_CIPHER_free(aes_cipher);
+    return ret;
+}
+#endif /* OPENSSL_NO_DES */
+
 static int kem_rsa_params(void)
 {
     int ret = 0;
@@ -716,6 +743,9 @@ int setup_tests(void)
     ADD_TEST(kem_rsa_params);
 #ifndef OPENSSL_NO_DH
     ADD_TEST(kem_invalid_keytype);
+#endif
+#ifndef OPENSSL_NO_DES
+    ADD_TEST(test_cipher_tdes_randkey);
 #endif
     return 1;
 }