X-Git-Url: https://git.openssl.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=crypto%2Frand%2Frand_crng_test.c;h=11d85f395d7e796798367a8c33583fb914c63629;hb=4e297b7441a070f9dd557445665365b4377e9498;hp=87f4ee1f483aebdc4e3fc8466c68f025e52e60df;hpb=b8621bdde70690361a36dca52688a3d946c3fe0f;p=openssl.git diff --git a/crypto/rand/rand_crng_test.c b/crypto/rand/rand_crng_test.c index 87f4ee1f48..11d85f395d 100644 --- a/crypto/rand/rand_crng_test.c +++ b/crypto/rand/rand_crng_test.c @@ -13,60 +13,81 @@ */ #include +#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; +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 *) = &rand_crngt_get_entropy_cb; +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) +static void rand_crng_ossl_ctx_free(void *vcrngt_glob) { - size_t n; - unsigned char *p; + CRNG_TEST_GLOBAL *crngt_glob = vcrngt_glob; - while ((n = rand_pool_acquire_entropy(crngt_pool)) != 0) - if (n >= CRNGT_BUFSIZ) { - p = rand_pool_detach(crngt_pool); - memcpy(buf, p, CRNGT_BUFSIZ); - rand_pool_reattach(crngt_pool, p); - return 1; - } - return 0; - -} -void rand_crngt_cleanup(void) -{ - rand_pool_free(crngt_pool); - OPENSSL_secure_free(crngt_prev); - crngt_pool = NULL; - crngt_prev = 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) { - if ((crngt_pool = rand_pool_new(0, CRNGT_BUFSIZ, CRNGT_BUFSIZ)) == NULL) - return 0; - if ((crngt_prev = OPENSSL_secure_malloc(CRNGT_BUFSIZ)) != NULL - && crngt_get_entropy(crngt_prev)) - return 1; - rand_crngt_cleanup(); - return 0; -} + unsigned char buf[CRNGT_BUFSIZ]; + CRNG_TEST_GLOBAL *crngt_glob = OPENSSL_zalloc(sizeof(*crngt_glob)); -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); + 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 crngt_glob; + } + rand_pool_free(crngt_glob->crngt_pool); + OPENSSL_free(crngt_glob); + return NULL; } -int rand_crngt_single_init(void) +static const OPENSSL_CTX_METHOD rand_crng_ossl_ctx_method = { + rand_crng_ossl_ctx_new, + rand_crng_ossl_ctx_free, +}; + +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, @@ -74,12 +95,16 @@ size_t rand_crngt_get_entropy(RAND_DRBG *drbg, int entropy, size_t min_len, size_t max_len, int prediction_resistance) { - unsigned char buf[CRNGT_BUFSIZ]; + unsigned char buf[CRNGT_BUFSIZ], md[EVP_MAX_MD_SIZE]; + unsigned int sz; 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) @@ -87,17 +112,18 @@ 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) - || memcmp(crngt_prev, buf, CRNGT_BUFSIZ) == 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, buf, CRNGT_BUFSIZ); + memcpy(crngt_glob->crngt_prev, md, sz); t += s; attempts++; } r = t; *pout = rand_pool_detach(pool); err: + OPENSSL_cleanse(buf, sizeof(buf)); rand_pool_free(pool); return r; }