Skip to content

Commit

Permalink
Make the RAND code available from inside the FIPS module
Browse files Browse the repository at this point in the history
Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
(Merged from #9035)
  • Loading branch information
mattcaswell committed Jun 28, 2019
1 parent 0da1d43 commit 57ca171
Show file tree
Hide file tree
Showing 13 changed files with 105 additions and 43 deletions.
7 changes: 5 additions & 2 deletions crypto/hmac/build.info
Original file line number Diff line number Diff line change
@@ -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
10 changes: 10 additions & 0 deletions crypto/hmac/hm_meth.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,23 @@ 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);

if (d == NULL)
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);
Expand Down
10 changes: 6 additions & 4 deletions crypto/rand/build.info
Original file line number Diff line number Diff line change
@@ -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
13 changes: 10 additions & 3 deletions crypto/rand/drbg_ctr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -369,24 +370,30 @@ 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:
/* This can't happen, but silence the compiler warning. */
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;

Expand Down
25 changes: 21 additions & 4 deletions crypto/rand/drbg_hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 */
Expand Down
21 changes: 18 additions & 3 deletions crypto/rand/drbg_hmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -197,23 +198,37 @@ 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;

drbg->meth = &drbg_hmac_meth;

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 */
Expand Down
6 changes: 4 additions & 2 deletions crypto/rand/drbg_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
28 changes: 16 additions & 12 deletions crypto/rand/rand_crng_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
}
Expand All @@ -64,27 +65,29 @@ 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)
{
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;
Expand Down Expand Up @@ -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;
Expand Down
16 changes: 9 additions & 7 deletions crypto/rand/rand_lcl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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];
Expand All @@ -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];
Expand All @@ -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];
Expand Down Expand Up @@ -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
2 changes: 1 addition & 1 deletion crypto/rand/rand_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion crypto/rand/rand_win.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
4 changes: 2 additions & 2 deletions test/build.info
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions test/drbgtest.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 57ca171

Please sign in to comment.