Make the RAND code available from inside the FIPS module

Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
(Merged from https://github.com/openssl/openssl/pull/9035)
This commit is contained in:
Matt Caswell 2019-05-23 14:35:42 +01:00
parent 0da1d43a94
commit 57ca171a13
13 changed files with 105 additions and 43 deletions

View 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

View 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);

View 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

View 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;

View 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 */

View 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 */

View 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);

View 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;

View 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

View 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);

View 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();

View 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

View 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;