From: Matt Caswell Date: Thu, 23 May 2019 13:35:42 +0000 (+0100) Subject: Make the RAND code available from inside the FIPS module X-Git-Tag: openssl-3.0.0-alpha1~1851 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=57ca171a131e6d55b4c4f6decefedeaa509db702;p=thirdparty%2Fopenssl.git Make the RAND code available from inside the FIPS module Reviewed-by: Matthias St. Pierre (Merged from https://github.com/openssl/openssl/pull/9035) --- diff --git a/crypto/hmac/build.info b/crypto/hmac/build.info index f63524d3be..b1c146182c 100644 --- a/crypto/hmac/build.info +++ b/crypto/hmac/build.info @@ -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 diff --git a/crypto/hmac/hm_meth.c b/crypto/hmac/hm_meth.c index db9af95cb7..19278ef67d 100644 --- a/crypto/hmac/hm_meth.c +++ b/crypto/hmac/hm_meth.c @@ -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); diff --git a/crypto/rand/build.info b/crypto/rand/build.info index 70d258032b..3e0a9c7432 100644 --- a/crypto/rand/build.info +++ b/crypto/rand/build.info @@ -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 diff --git a/crypto/rand/drbg_ctr.c b/crypto/rand/drbg_ctr.c index 4c11e65733..23e504bfac 100644 --- a/crypto/rand/drbg_ctr.c +++ b/crypto/rand/drbg_ctr.c @@ -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; diff --git a/crypto/rand/drbg_hash.c b/crypto/rand/drbg_hash.c index 0943180201..2b261fac26 100644 --- a/crypto/rand/drbg_hash.c +++ b/crypto/rand/drbg_hash.c @@ -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 */ diff --git a/crypto/rand/drbg_hmac.c b/crypto/rand/drbg_hmac.c index cb70bcb8b3..a6ed58bf6c 100644 --- a/crypto/rand/drbg_hmac.c +++ b/crypto/rand/drbg_hmac.c @@ -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 */ diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c index 33bc81c07f..812a52fa5a 100644 --- a/crypto/rand/drbg_lib.c +++ b/crypto/rand/drbg_lib.c @@ -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); diff --git a/crypto/rand/rand_crng_test.c b/crypto/rand/rand_crng_test.c index 11d85f395d..44e077e0ac 100644 --- a/crypto/rand/rand_crng_test.c +++ b/crypto/rand/rand_crng_test.c @@ -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; diff --git a/crypto/rand/rand_lcl.h b/crypto/rand/rand_lcl.h index 97126bcb5e..416237ace7 100644 --- a/crypto/rand/rand_lcl.h +++ b/crypto/rand/rand_lcl.h @@ -17,6 +17,7 @@ # include # include # 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 diff --git a/crypto/rand/rand_unix.c b/crypto/rand/rand_unix.c index 61619091a4..e45e018e4a 100644 --- a/crypto/rand/rand_unix.c +++ b/crypto/rand/rand_unix.c @@ -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); diff --git a/crypto/rand/rand_win.c b/crypto/rand/rand_win.c index 17ab137118..8b87419698 100644 --- a/crypto/rand/rand_win.c +++ b/crypto/rand/rand_win.c @@ -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(); diff --git a/test/build.info b/test/build.info index 1cf604e37e..f5b802da4d 100644 --- a/test/build.info +++ b/test/build.info @@ -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 diff --git a/test/drbgtest.c b/test/drbgtest.c index 618403fd3a..f75c432724 100644 --- a/test/drbgtest.c +++ b/test/drbgtest.c @@ -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;