Make the RAND code available from inside the FIPS module
authorMatt Caswell <matt@openssl.org>
Thu, 23 May 2019 13:35:42 +0000 (14:35 +0100)
committerMatt Caswell <matt@openssl.org>
Fri, 28 Jun 2019 09:22:21 +0000 (10:22 +0100)
Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
(Merged from https://github.com/openssl/openssl/pull/9035)

13 files changed:
crypto/hmac/build.info
crypto/hmac/hm_meth.c
crypto/rand/build.info
crypto/rand/drbg_ctr.c
crypto/rand/drbg_hash.c
crypto/rand/drbg_hmac.c
crypto/rand/drbg_lib.c
crypto/rand/rand_crng_test.c
crypto/rand/rand_lcl.h
crypto/rand/rand_unix.c
crypto/rand/rand_win.c
test/build.info
test/drbgtest.c

index f63524d..b1c1461 100644 (file)
@@ -1,3 +1,6 @@
 LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
-        hmac.c hm_ameth.c hm_meth.c
+
+$COMMON=hmac.c hm_meth.c
+
+SOURCE[../../libcrypto]=$COMMON hm_ameth.c
+SOURCE[../../providers/fips]=$COMMON
index db9af95..19278ef 100644 (file)
@@ -152,6 +152,15 @@ static int hmac_ctrl_str(EVP_MAC_IMPL *hctx, const char *type,
 {
     if (!value)
         return 0;
+#ifndef FIPS_MODE
+    /*
+     * We don't have EVP_get_digestbyname() in FIPS_MODE. That function returns
+     * an EVP_MD without an associated provider implementation (i.e. it is
+     * using "implicit fetch"). We could replace it with an "explicit" fetch
+     * using EVP_MD_fetch(), but we'd then be required to free the returned
+     * EVP_MD somewhere. Probably the complexity isn't worth it as we are
+     * unlikely to need this ctrl in FIPS_MODE anyway.
+     */
     if (strcmp(type, "digest") == 0) {
         const EVP_MD *d = EVP_get_digestbyname(value);
 
@@ -159,6 +168,7 @@ static int hmac_ctrl_str(EVP_MAC_IMPL *hctx, const char *type,
             return 0;
         return hmac_ctrl_int(hctx, EVP_MAC_CTRL_SET_MD, d);
     }
+#endif
     if (strcmp(type, "key") == 0)
         return EVP_str2ctrl(hmac_ctrl_str_cb, hctx, EVP_MAC_CTRL_SET_KEY,
                             value);
index 70d2580..3e0a9c7 100644 (file)
@@ -1,5 +1,7 @@
 LIBS=../../libcrypto
-SOURCE[../../libcrypto]=\
-        randfile.c rand_lib.c rand_err.c rand_crng_test.c rand_egd.c \
-        rand_win.c rand_unix.c rand_vms.c drbg_lib.c drbg_ctr.c rand_vxworks.c \
-        drbg_hash.c drbg_hmac.c
+
+$COMMON=rand_lib.c rand_crng_test.c rand_win.c rand_unix.c  rand_vms.c \
+        drbg_lib.c drbg_ctr.c rand_vxworks.c drbg_hash.c drbg_hmac.c
+
+SOURCE[../../libcrypto]=$COMMON randfile.c rand_err.c rand_egd.c
+SOURCE[../../providers/fips]=$COMMON
index 4c11e65..23e504b 100644 (file)
@@ -354,6 +354,7 @@ static int drbg_ctr_uninstantiate(RAND_DRBG *drbg)
 {
     EVP_CIPHER_CTX_free(drbg->data.ctr.ctx);
     EVP_CIPHER_CTX_free(drbg->data.ctr.ctx_df);
+    EVP_CIPHER_meth_free(drbg->data.ctr.cipher);
     OPENSSL_cleanse(&drbg->data.ctr, sizeof(drbg->data.ctr));
     return 1;
 }
@@ -369,6 +370,7 @@ int drbg_ctr_init(RAND_DRBG *drbg)
 {
     RAND_DRBG_CTR *ctr = &drbg->data.ctr;
     size_t keylen;
+    EVP_CIPHER *cipher = NULL;
 
     switch (drbg->type) {
     default:
@@ -376,17 +378,22 @@ int drbg_ctr_init(RAND_DRBG *drbg)
         return 0;
     case NID_aes_128_ctr:
         keylen = 16;
-        ctr->cipher = EVP_aes_128_ecb();
+        cipher = EVP_CIPHER_fetch(drbg->libctx, "AES-128-ECB", "");
         break;
     case NID_aes_192_ctr:
         keylen = 24;
-        ctr->cipher = EVP_aes_192_ecb();
+        cipher = EVP_CIPHER_fetch(drbg->libctx, "AES-192-ECB", "");
         break;
     case NID_aes_256_ctr:
         keylen = 32;
-        ctr->cipher = EVP_aes_256_ecb();
+        cipher = EVP_CIPHER_fetch(drbg->libctx, "AES-256-ECB", "");
         break;
     }
+    if (cipher == NULL)
+        return 0;
+
+    EVP_CIPHER_meth_free(ctr->cipher);
+    ctr->cipher = cipher;
 
     drbg->meth = &drbg_ctr_meth;
 
index 0943180..2b261fa 100644 (file)
@@ -289,6 +289,7 @@ static int drbg_hash_generate(RAND_DRBG *drbg,
 
 static int drbg_hash_uninstantiate(RAND_DRBG *drbg)
 {
+    EVP_MD_meth_free(drbg->data.hash.md);
     EVP_MD_CTX_free(drbg->data.hash.ctx);
     OPENSSL_cleanse(&drbg->data.hash, sizeof(drbg->data.hash));
     return 1;
@@ -303,23 +304,39 @@ static RAND_DRBG_METHOD drbg_hash_meth = {
 
 int drbg_hash_init(RAND_DRBG *drbg)
 {
-    const EVP_MD *md;
+    EVP_MD *md;
     RAND_DRBG_HASH *hash = &drbg->data.hash;
 
+#ifndef FIPS_MODE
     /* Any approved digest is allowed */
-    md = EVP_get_digestbynid(drbg->type);
+    md = EVP_MD_meth_dup(EVP_get_digestbynid(drbg->type));
+#else
+    /* TODO(3.0): Fill this out with the complete list of allowed digests */
+    switch (drbg->type) {
+    default:
+        return 0;
+    case NID_sha256:
+        md = EVP_MD_fetch(drbg->libctx, "SHA256", "");
+        break;
+    }
+#endif
     if (md == NULL)
         return 0;
 
+
     drbg->meth = &drbg_hash_meth;
-    hash->md = md;
 
     if (hash->ctx == NULL) {
         hash->ctx = EVP_MD_CTX_new();
-        if (hash->ctx == NULL)
+        if (hash->ctx == NULL) {
+            EVP_MD_meth_free(md);
             return 0;
+        }
     }
 
+    EVP_MD_meth_free(hash->md);
+    hash->md = md;
+
     /* These are taken from SP 800-90 10.1 Table 2 */
     hash->blocklen = EVP_MD_size(md);
     /* See SP800-57 Part1 Rev4 5.6.1 Table 3 */
index cb70bcb..a6ed58b 100644 (file)
@@ -183,6 +183,7 @@ static int drbg_hmac_generate(RAND_DRBG *drbg,
 
 static int drbg_hmac_uninstantiate(RAND_DRBG *drbg)
 {
+    EVP_MD_meth_free(drbg->data.hmac.md);
     HMAC_CTX_free(drbg->data.hmac.ctx);
     OPENSSL_cleanse(&drbg->data.hmac, sizeof(drbg->data.hmac));
     return 1;
@@ -197,11 +198,22 @@ static RAND_DRBG_METHOD drbg_hmac_meth = {
 
 int drbg_hmac_init(RAND_DRBG *drbg)
 {
-    const EVP_MD *md = NULL;
+    EVP_MD *md = NULL;
     RAND_DRBG_HMAC *hmac = &drbg->data.hmac;
 
+#ifndef FIPS_MODE
     /* Any approved digest is allowed - assume we pass digest (not NID_hmac*) */
-    md = EVP_get_digestbynid(drbg->type);
+    md = EVP_MD_meth_dup(EVP_get_digestbynid(drbg->type));
+#else
+    /* TODO(3.0): Fill this out with the complete list of allowed digests */
+    switch (drbg->type) {
+    default:
+        return 0;
+    case NID_sha256:
+        md = EVP_MD_fetch(drbg->libctx, "SHA256", "");
+        break;
+    }
+#endif
     if (md == NULL)
         return 0;
 
@@ -209,11 +221,14 @@ int drbg_hmac_init(RAND_DRBG *drbg)
 
     if (hmac->ctx == NULL) {
         hmac->ctx = HMAC_CTX_new();
-        if (hmac->ctx == NULL)
+        if (hmac->ctx == NULL) {
+            EVP_MD_meth_free(md);
             return 0;
+        }
     }
 
     /* These are taken from SP 800-90 10.1 Table 2 */
+    EVP_MD_meth_free(hmac->md);
     hmac->md = md;
     hmac->blocklen = EVP_MD_size(md);
     /* See SP800-57 Part1 Rev4 5.6.1 Table 3 */
index 33bc81c..812a52f 100644 (file)
@@ -1339,7 +1339,8 @@ RAND_DRBG *OPENSSL_CTX_get0_public_drbg(OPENSSL_CTX *ctx)
 
     drbg = CRYPTO_THREAD_get_local(&dgbl->public_drbg);
     if (drbg == NULL) {
-        if (!ossl_init_thread_start(NULL, NULL, drbg_delete_thread_state))
+        ctx = openssl_ctx_get_concrete(ctx);
+        if (!ossl_init_thread_start(NULL, ctx, drbg_delete_thread_state))
             return NULL;
         drbg = drbg_setup(ctx, dgbl->master_drbg, RAND_DRBG_TYPE_PUBLIC);
         CRYPTO_THREAD_set_local(&dgbl->public_drbg, drbg);
@@ -1366,7 +1367,8 @@ RAND_DRBG *OPENSSL_CTX_get0_private_drbg(OPENSSL_CTX *ctx)
 
     drbg = CRYPTO_THREAD_get_local(&dgbl->private_drbg);
     if (drbg == NULL) {
-        if (!ossl_init_thread_start(NULL, NULL, drbg_delete_thread_state))
+        ctx = openssl_ctx_get_concrete(ctx);
+        if (!ossl_init_thread_start(NULL, ctx, drbg_delete_thread_state))
             return NULL;
         drbg = drbg_setup(ctx, dgbl->master_drbg, RAND_DRBG_TYPE_PRIVATE);
         CRYPTO_THREAD_set_local(&dgbl->private_drbg, drbg);
index 11d85f3..44e077e 100644 (file)
@@ -24,8 +24,8 @@ typedef struct crng_test_global_st {
     RAND_POOL *crngt_pool;
 } CRNG_TEST_GLOBAL;
 
-int (*crngt_get_entropy)(OPENSSL_CTX *, unsigned char *, unsigned char *,
-                         unsigned int *)
+int (*crngt_get_entropy)(OPENSSL_CTX *, RAND_POOL *, unsigned char *,
+                         unsigned char *, unsigned int *)
     = &rand_crngt_get_entropy_cb;
 
 static void rand_crng_ossl_ctx_free(void *vcrngt_glob)
@@ -49,7 +49,8 @@ static void *rand_crng_ossl_ctx_new(OPENSSL_CTX *ctx)
         OPENSSL_free(crngt_glob);
         return NULL;
     }
-    if (crngt_get_entropy(ctx, buf, crngt_glob->crngt_prev, NULL)) {
+    if (crngt_get_entropy(ctx, crngt_glob->crngt_pool, buf,
+                          crngt_glob->crngt_prev, NULL)) {
         OPENSSL_cleanse(buf, sizeof(buf));
         return crngt_glob;
     }
@@ -64,6 +65,7 @@ static const OPENSSL_CTX_METHOD rand_crng_ossl_ctx_method = {
 };
 
 int rand_crngt_get_entropy_cb(OPENSSL_CTX *ctx,
+                              RAND_POOL *pool,
                               unsigned char *buf,
                               unsigned char *md,
                               unsigned int *md_size)
@@ -71,20 +73,21 @@ int rand_crngt_get_entropy_cb(OPENSSL_CTX *ctx,
     int r;
     size_t n;
     unsigned char *p;
-    CRNG_TEST_GLOBAL *crngt_glob
-        = openssl_ctx_get_data(ctx, OPENSSL_CTX_RAND_CRNGT_INDEX,
-                               &rand_crng_ossl_ctx_method);
 
-    if (crngt_glob == NULL)
+    if (pool == NULL)
         return 0;
 
-    n = rand_pool_acquire_entropy(crngt_glob->crngt_pool);
+    n = rand_pool_acquire_entropy(pool);
     if (n >= CRNGT_BUFSIZ) {
-        p = rand_pool_detach(crngt_glob->crngt_pool);
-        r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, EVP_sha256(), NULL);
+        EVP_MD *fmd = EVP_MD_fetch(ctx, "SHA256", "");
+        if (fmd == NULL)
+            return 0;
+        p = rand_pool_detach(pool);
+        r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, fmd, NULL);
         if (r != 0)
             memcpy(buf, p, CRNGT_BUFSIZ);
-        rand_pool_reattach(crngt_glob->crngt_pool, p);
+        rand_pool_reattach(pool, p);
+        EVP_MD_meth_free(fmd);
         return r;
     }
     return 0;
@@ -112,7 +115,8 @@ size_t rand_crngt_get_entropy(RAND_DRBG *drbg,
 
     while ((q = rand_pool_bytes_needed(pool, 1)) > 0 && attempts-- > 0) {
         s = q > sizeof(buf) ? sizeof(buf) : q;
-        if (!crngt_get_entropy(drbg->libctx, buf, md, &sz)
+        if (!crngt_get_entropy(drbg->libctx, crngt_glob->crngt_pool, buf, md,
+                               &sz)
             || memcmp(crngt_glob->crngt_prev, md, sz) == 0
             || !rand_pool_add(pool, buf, s, s * 8))
             goto err;
index 97126bc..416237a 100644 (file)
@@ -17,6 +17,7 @@
 # include <openssl/ec.h>
 # include <openssl/rand_drbg.h>
 # include "internal/tsan_assist.h"
+# include "internal/rand_int.h"
 
 # include "internal/numbers.h"
 
@@ -129,7 +130,7 @@ typedef struct rand_drbg_method_st {
 #define HASH_PRNG_MAX_SEEDLEN    (888/8)
 
 typedef struct rand_drbg_hash_st {
-    const EVP_MD *md;
+    EVP_MD *md;
     EVP_MD_CTX *ctx;
     size_t blocklen;
     unsigned char V[HASH_PRNG_MAX_SEEDLEN];
@@ -139,7 +140,7 @@ typedef struct rand_drbg_hash_st {
 } RAND_DRBG_HASH;
 
 typedef struct rand_drbg_hmac_st {
-    const EVP_MD *md;
+    EVP_MD *md;
     HMAC_CTX *ctx;
     size_t blocklen;
     unsigned char K[EVP_MAX_MD_SIZE];
@@ -152,7 +153,7 @@ typedef struct rand_drbg_hmac_st {
 typedef struct rand_drbg_ctr_st {
     EVP_CIPHER_CTX *ctx;
     EVP_CIPHER_CTX *ctx_df;
-    const EVP_CIPHER *cipher;
+    EVP_CIPHER *cipher;
     size_t keylen;
     unsigned char K[32];
     unsigned char V[16];
@@ -336,10 +337,11 @@ int drbg_hmac_init(RAND_DRBG *drbg);
  * Entropy call back for the FIPS 140-2 section 4.9.2 Conditional Tests.
  * These need to be exposed for the unit tests.
  */
-int rand_crngt_get_entropy_cb(OPENSSL_CTX *ctx, unsigned char *buf,
-                              unsigned char *md, unsigned int *md_size);
-extern int (*crngt_get_entropy)(OPENSSL_CTX *ctx, unsigned char *buf,
-                                unsigned char *md,
+int rand_crngt_get_entropy_cb(OPENSSL_CTX *ctx, RAND_POOL *pool,
+                              unsigned char *buf, unsigned char *md,
+                              unsigned int *md_size);
+extern int (*crngt_get_entropy)(OPENSSL_CTX *ctx, RAND_POOL *pool,
+                                unsigned char *buf, unsigned char *md,
                                 unsigned int *md_size);
 
 #endif
index 6161909..e45e018 100644 (file)
@@ -285,7 +285,7 @@ static ssize_t syscall_random(void *buf, size_t buflen)
 
     if (getentropy != NULL)
         return getentropy(buf, buflen) == 0 ? (ssize_t)buflen : -1;
-#  else
+#  elif !defined(FIPS_MODE)
     union {
         void *p;
         int (*f)(void *buffer, size_t length);
index 17ab137..8b87419 100644 (file)
@@ -162,7 +162,7 @@ int rand_pool_add_additional_data(RAND_POOL *pool)
     return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
 }
 
-# if !OPENSSL_API_1_1_0
+# if !OPENSSL_API_1_1_0 && !defined(FIPS_MODE)
 int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam)
 {
     RAND_poll();
index 1cf604e..f5b802d 100644 (file)
@@ -371,13 +371,13 @@ IF[{- !$disabled{tests} -}]
   DEPEND[recordlentest]=../libcrypto ../libssl libtestutil.a
 
   SOURCE[drbgtest]=drbgtest.c
-  INCLUDE[drbgtest]=../include ../apps/include
+  INCLUDE[drbgtest]=../include ../apps/include ../crypto/include
   DEPEND[drbgtest]=../libcrypto.a libtestutil.a
 
   SOURCE[drbg_cavs_test]=drbg_cavs_test.c drbg_cavs_data_ctr.c \
                          drbg_cavs_data_hash.c drbg_cavs_data_hmac.c
 
-  INCLUDE[drbg_cavs_test]=../include ../apps/include . ..
+  INCLUDE[drbg_cavs_test]=../include ../apps/include . .. ../crypto/include
   DEPEND[drbg_cavs_test]=../libcrypto libtestutil.a
 
   SOURCE[x509_dup_cert_test]=x509_dup_cert_test.c
index 618403f..f75c432 100644 (file)
@@ -1264,8 +1264,8 @@ static const size_t crngt_num_cases = 6;
 
 static size_t crngt_case, crngt_idx;
 
-static int crngt_entropy_cb(OPENSSL_CTX *ctx, unsigned char *buf,
-                            unsigned char *md,
+static int crngt_entropy_cb(OPENSSL_CTX *ctx, RAND_POOL *pool,
+                            unsigned char *buf, unsigned char *md,
                             unsigned int *md_size)
 {
     size_t i, z;