From 4e297b7441a070f9dd557445665365b4377e9498 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Thu, 23 May 2019 16:51:55 +0100 Subject: [PATCH 1/1] Make the rand_crng code OPENSSL_CTX aware This is in preparation for moving this code inside the FIPS module. Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/9039) --- crypto/rand/rand_crng_test.c | 105 ++++++++++++++++++++--------------- crypto/rand/rand_lcl.h | 16 ++---- include/internal/cryptlib.h | 3 +- test/drbgtest.c | 15 +++-- 4 files changed, 74 insertions(+), 65 deletions(-) diff --git a/crypto/rand/rand_crng_test.c b/crypto/rand/rand_crng_test.c index 1b4f1674b3..11d85f395d 100644 --- a/crypto/rand/rand_crng_test.c +++ b/crypto/rand/rand_crng_test.c @@ -16,64 +16,78 @@ #include #include "internal/rand_int.h" #include "internal/thread_once.h" +#include "internal/cryptlib.h" #include "rand_lcl.h" -static RAND_POOL *crngt_pool; -static unsigned char crngt_prev[EVP_MAX_MD_SIZE]; +typedef struct crng_test_global_st { + unsigned char crngt_prev[EVP_MAX_MD_SIZE]; + RAND_POOL *crngt_pool; +} CRNG_TEST_GLOBAL; -int (*crngt_get_entropy)(unsigned char *, unsigned char *, unsigned int *) +int (*crngt_get_entropy)(OPENSSL_CTX *, unsigned char *, unsigned char *, + unsigned int *) = &rand_crngt_get_entropy_cb; -int rand_crngt_get_entropy_cb(unsigned char *buf, unsigned char *md, - unsigned int *md_size) +static void rand_crng_ossl_ctx_free(void *vcrngt_glob) { - int r; - size_t n; - unsigned char *p; + CRNG_TEST_GLOBAL *crngt_glob = vcrngt_glob; - n = rand_pool_acquire_entropy(crngt_pool); - if (n >= CRNGT_BUFSIZ) { - p = rand_pool_detach(crngt_pool); - r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, EVP_sha256(), NULL); - if (r != 0) - memcpy(buf, p, CRNGT_BUFSIZ); - rand_pool_reattach(crngt_pool, p); - return r; - } - return 0; -} - -void rand_crngt_cleanup(void) -{ - rand_pool_free(crngt_pool); - crngt_pool = NULL; + rand_pool_free(crngt_glob->crngt_pool); + OPENSSL_free(crngt_glob); } -int rand_crngt_init(void) +static void *rand_crng_ossl_ctx_new(OPENSSL_CTX *ctx) { unsigned char buf[CRNGT_BUFSIZ]; + CRNG_TEST_GLOBAL *crngt_glob = OPENSSL_zalloc(sizeof(*crngt_glob)); - if ((crngt_pool = rand_pool_new(0, CRNGT_BUFSIZ, CRNGT_BUFSIZ)) == NULL) - return 0; - if (crngt_get_entropy(buf, crngt_prev, NULL)) { + if (crngt_glob == NULL) + return NULL; + + if ((crngt_glob->crngt_pool + = rand_pool_new(0, CRNGT_BUFSIZ, CRNGT_BUFSIZ)) == NULL) { + OPENSSL_free(crngt_glob); + return NULL; + } + if (crngt_get_entropy(ctx, buf, crngt_glob->crngt_prev, NULL)) { OPENSSL_cleanse(buf, sizeof(buf)); - return 1; + return crngt_glob; } - rand_crngt_cleanup(); - return 0; + rand_pool_free(crngt_glob->crngt_pool); + OPENSSL_free(crngt_glob); + return NULL; } -static CRYPTO_ONCE rand_crngt_init_flag = CRYPTO_ONCE_STATIC_INIT; -DEFINE_RUN_ONCE_STATIC(do_rand_crngt_init) -{ - return OPENSSL_init_crypto(0, NULL) - && rand_crngt_init() - && OPENSSL_atexit(&rand_crngt_cleanup); -} +static const OPENSSL_CTX_METHOD rand_crng_ossl_ctx_method = { + rand_crng_ossl_ctx_new, + rand_crng_ossl_ctx_free, +}; -int rand_crngt_single_init(void) +int rand_crngt_get_entropy_cb(OPENSSL_CTX *ctx, + unsigned char *buf, + unsigned char *md, + unsigned int *md_size) { - return RUN_ONCE(&rand_crngt_init_flag, do_rand_crngt_init); + 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) + return 0; + + n = rand_pool_acquire_entropy(crngt_glob->crngt_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); + if (r != 0) + memcpy(buf, p, CRNGT_BUFSIZ); + rand_pool_reattach(crngt_glob->crngt_pool, p); + return r; + } + return 0; } size_t rand_crngt_get_entropy(RAND_DRBG *drbg, @@ -86,8 +100,11 @@ size_t rand_crngt_get_entropy(RAND_DRBG *drbg, RAND_POOL *pool; size_t q, r = 0, s, t = 0; int attempts = 3; + CRNG_TEST_GLOBAL *crngt_glob + = openssl_ctx_get_data(drbg->libctx, OPENSSL_CTX_RAND_CRNGT_INDEX, + &rand_crng_ossl_ctx_method); - if (!RUN_ONCE(&rand_crngt_init_flag, do_rand_crngt_init)) + if (crngt_glob == NULL) return 0; if ((pool = rand_pool_new(entropy, min_len, max_len)) == NULL) @@ -95,11 +112,11 @@ 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(buf, md, &sz) - || memcmp(crngt_prev, md, sz) == 0 + if (!crngt_get_entropy(drbg->libctx, buf, md, &sz) + || memcmp(crngt_glob->crngt_prev, md, sz) == 0 || !rand_pool_add(pool, buf, s, s * 8)) goto err; - memcpy(crngt_prev, md, sz); + memcpy(crngt_glob->crngt_prev, md, sz); t += s; attempts++; } diff --git a/crypto/rand/rand_lcl.h b/crypto/rand/rand_lcl.h index 4e1c9c02d3..97126bcb5e 100644 --- a/crypto/rand/rand_lcl.h +++ b/crypto/rand/rand_lcl.h @@ -336,18 +336,10 @@ 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(unsigned char *buf, unsigned char *md, - unsigned int *md_size); -extern int (*crngt_get_entropy)(unsigned char *buf, unsigned char *md, +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, unsigned int *md_size); -int rand_crngt_init(void); -void rand_crngt_cleanup(void); - -/* - * Expose the run once initialisation function for the unit tests because. - * they need to restart from scratch to validate the first block is skipped - * properly. - */ -int rand_crngt_single_init(void); #endif diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h index 9ec1a3777a..585263a173 100644 --- a/include/internal/cryptlib.h +++ b/include/internal/cryptlib.h @@ -147,7 +147,8 @@ typedef struct ossl_ex_data_global_st { # define OPENSSL_CTX_PROPERTY_STRING_INDEX 3 # define OPENSSL_CTX_NAMEMAP_INDEX 4 # define OPENSSL_CTX_DRBG_INDEX 5 -# define OPENSSL_CTX_MAX_INDEXES 6 +# define OPENSSL_CTX_RAND_CRNGT_INDEX 6 +# define OPENSSL_CTX_MAX_INDEXES 7 typedef struct openssl_ctx_method { void *(*new_func)(OPENSSL_CTX *ctx); diff --git a/test/drbgtest.c b/test/drbgtest.c index 9e0aba83ab..618403fd3a 100644 --- a/test/drbgtest.c +++ b/test/drbgtest.c @@ -1264,7 +1264,8 @@ static const size_t crngt_num_cases = 6; static size_t crngt_case, crngt_idx; -static int crngt_entropy_cb(unsigned char *buf, unsigned char *md, +static int crngt_entropy_cb(OPENSSL_CTX *ctx, unsigned char *buf, + unsigned char *md, unsigned int *md_size) { size_t i, z; @@ -1288,19 +1289,16 @@ static int test_crngt(int n) size_t ent; int res = 0; int expect; + OPENSSL_CTX *ctx = OPENSSL_CTX_new(); - if (!TEST_true(rand_crngt_single_init())) - return 0; - rand_crngt_cleanup(); - - if (!TEST_ptr(drbg = RAND_DRBG_new(dt->nid, dt->flags, NULL))) + if (!TEST_ptr(ctx)) return 0; + if (!TEST_ptr(drbg = RAND_DRBG_new_ex(ctx, dt->nid, dt->flags, NULL))) + goto err; ent = (drbg->min_entropylen + CRNGT_BUFSIZ - 1) / CRNGT_BUFSIZ; crngt_case = n % crngt_num_cases; crngt_idx = 0; crngt_get_entropy = &crngt_entropy_cb; - if (!TEST_true(rand_crngt_init())) - goto err; #ifndef FIPS_MODE if (!TEST_true(RAND_DRBG_set_callbacks(drbg, &rand_crngt_get_entropy, &rand_crngt_cleanup_entropy, @@ -1333,6 +1331,7 @@ err: uninstantiate(drbg); RAND_DRBG_free(drbg); crngt_get_entropy = &rand_crngt_get_entropy_cb; + OPENSSL_CTX_free(ctx); return res; } -- 2.39.5