X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Frand%2Fdrbg_lib.c;h=4e1e2ea5e06441ff9f13eafec35376b2cea380a8;hp=ec4aa69db50a3a57690770fbc4596e08f7b182f2;hb=d69226a3fc8e8448572d175e8d96ff7e817b1ebd;hpb=a83dc59afa2e0207180d7218efed19b20d48de95 diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c index ec4aa69db5..4e1e2ea5e0 100644 --- a/crypto/rand/drbg_lib.c +++ b/crypto/rand/drbg_lib.c @@ -1,7 +1,7 @@ /* * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html @@ -67,7 +67,7 @@ static CRYPTO_THREAD_LOCAL private_drbg; /* NIST SP 800-90A DRBG recommends the use of a personalization string. */ -static const char ossl_pers_string[] = "OpenSSL NIST SP 800-90A DRBG"; +static const char ossl_pers_string[] = DRBG_DEFAULT_PERS_STRING; static CRYPTO_ONCE rand_drbg_init = CRYPTO_ONCE_STATIC_INIT; @@ -158,8 +158,10 @@ int RAND_DRBG_set(RAND_DRBG *drbg, int type, unsigned int flags) } /* If set is called multiple times - clear the old one */ - if (type != drbg->type && drbg->type != 0 && drbg->meth != NULL) { + if (drbg->type != 0 && (type != drbg->type || flags != drbg->flags)) { drbg->meth->uninstantiate(drbg); + rand_pool_free(drbg->adin_pool); + drbg->adin_pool = NULL; } drbg->state = DRBG_UNINITIALISED; @@ -168,6 +170,7 @@ int RAND_DRBG_set(RAND_DRBG *drbg, int type, unsigned int flags) if (type == 0) { /* Uninitialized; that's okay. */ + drbg->meth = NULL; return 1; } else if (is_ctr(type)) { ret = drbg_ctr_init(drbg); @@ -177,12 +180,17 @@ int RAND_DRBG_set(RAND_DRBG *drbg, int type, unsigned int flags) else ret = drbg_hash_init(drbg); } else { + drbg->type = 0; + drbg->flags = 0; + drbg->meth = NULL; RANDerr(RAND_F_RAND_DRBG_SET, RAND_R_UNSUPPORTED_DRBG_TYPE); return 0; } - if (ret == 0) + if (ret == 0) { + drbg->state = DRBG_ERROR; RANDerr(RAND_F_RAND_DRBG_SET, RAND_R_ERROR_INITIALISING_DRBG); + } return ret; } @@ -233,8 +241,8 @@ static RAND_DRBG *rand_drbg_new(int secure, unsigned int flags, RAND_DRBG *parent) { - RAND_DRBG *drbg = secure ? - OPENSSL_secure_zalloc(sizeof(*drbg)) : OPENSSL_zalloc(sizeof(*drbg)); + RAND_DRBG *drbg = secure ? OPENSSL_secure_zalloc(sizeof(*drbg)) + : OPENSSL_zalloc(sizeof(*drbg)); if (drbg == NULL) { RANDerr(RAND_F_RAND_DRBG_NEW, ERR_R_MALLOC_FAILURE); @@ -246,8 +254,13 @@ static RAND_DRBG *rand_drbg_new(int secure, drbg->parent = parent; if (parent == NULL) { +#ifdef FIPS_MODE + drbg->get_entropy = rand_crngt_get_entropy; + drbg->cleanup_entropy = rand_crngt_cleanup_entropy; +#else drbg->get_entropy = rand_drbg_get_entropy; drbg->cleanup_entropy = rand_drbg_cleanup_entropy; +#endif #ifndef RAND_DRBG_GET_RANDOM_NONCE drbg->get_nonce = rand_drbg_get_nonce; drbg->cleanup_nonce = rand_drbg_cleanup_nonce; @@ -287,10 +300,7 @@ static RAND_DRBG *rand_drbg_new(int secure, return drbg; err: - if (drbg->secure) - OPENSSL_secure_free(drbg); - else - OPENSSL_free(drbg); + RAND_DRBG_free(drbg); return NULL; } @@ -315,6 +325,7 @@ void RAND_DRBG_free(RAND_DRBG *drbg) if (drbg->meth != NULL) drbg->meth->uninstantiate(drbg); + rand_pool_free(drbg->adin_pool); CRYPTO_THREAD_lock_free(drbg->lock); CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DRBG, drbg, &drbg->ex_data); @@ -415,15 +426,6 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg, drbg->cleanup_entropy(drbg, entropy, entropylen); if (nonce != NULL && drbg->cleanup_nonce != NULL) drbg->cleanup_nonce(drbg, nonce, noncelen); - if (drbg->pool != NULL) { - if (drbg->state == DRBG_READY) { - RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, - RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED); - drbg->state = DRBG_ERROR; - } - rand_pool_free(drbg->pool); - drbg->pool = NULL; - } if (drbg->state == DRBG_READY) return 1; return 0; @@ -440,6 +442,7 @@ int RAND_DRBG_uninstantiate(RAND_DRBG *drbg) { int index = -1, type, flags; if (drbg->meth == NULL) { + drbg->state = DRBG_ERROR; RANDerr(RAND_F_RAND_DRBG_UNINSTANTIATE, RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED); return 0; @@ -559,11 +562,11 @@ int rand_drbg_restart(RAND_DRBG *drbg, const unsigned char *adin = NULL; size_t adinlen = 0; - if (drbg->pool != NULL) { + if (drbg->seed_pool != NULL) { RANDerr(RAND_F_RAND_DRBG_RESTART, ERR_R_INTERNAL_ERROR); drbg->state = DRBG_ERROR; - rand_pool_free(drbg->pool); - drbg->pool = NULL; + rand_pool_free(drbg->seed_pool); + drbg->seed_pool = NULL; return 0; } @@ -583,8 +586,8 @@ int rand_drbg_restart(RAND_DRBG *drbg, } /* will be picked up by the rand_drbg_get_entropy() callback */ - drbg->pool = rand_pool_attach(buffer, len, entropy); - if (drbg->pool == NULL) + drbg->seed_pool = rand_pool_attach(buffer, len, entropy); + if (drbg->seed_pool == NULL) return 0; } else { if (drbg->max_adinlen < len) { @@ -630,14 +633,8 @@ int rand_drbg_restart(RAND_DRBG *drbg, } } - /* check whether a given entropy pool was cleared properly during reseed */ - if (drbg->pool != NULL) { - drbg->state = DRBG_ERROR; - RANDerr(RAND_F_RAND_DRBG_RESTART, ERR_R_INTERNAL_ERROR); - rand_pool_free(drbg->pool); - drbg->pool = NULL; - return 0; - } + rand_pool_free(drbg->seed_pool); + drbg->seed_pool = NULL; return drbg->state == DRBG_READY; } @@ -737,9 +734,18 @@ int RAND_DRBG_bytes(RAND_DRBG *drbg, unsigned char *out, size_t outlen) unsigned char *additional = NULL; size_t additional_len; size_t chunk; - size_t ret; + size_t ret = 0; + + if (drbg->adin_pool == NULL) { + if (drbg->type == 0) + goto err; + drbg->adin_pool = rand_pool_new(0, 0, drbg->max_adinlen); + if (drbg->adin_pool == NULL) + goto err; + } - additional_len = rand_drbg_get_additional_data(&additional, drbg->max_adinlen); + additional_len = rand_drbg_get_additional_data(drbg->adin_pool, + &additional); for ( ; outlen > 0; outlen -= chunk, out += chunk) { chunk = outlen; @@ -751,9 +757,9 @@ int RAND_DRBG_bytes(RAND_DRBG *drbg, unsigned char *out, size_t outlen) } ret = 1; -err: - if (additional_len != 0) - OPENSSL_secure_clear_free(additional, additional_len); + err: + if (additional != NULL) + rand_drbg_cleanup_additional_data(drbg->adin_pool, additional); return ret; } @@ -1044,12 +1050,8 @@ static int drbg_bytes(unsigned char *out, int count) * Calculates the minimum length of a full entropy buffer * which is necessary to seed (i.e. instantiate) the DRBG * successfully. - * - * NOTE: There is a copy of this function in drbgtest.c. - * If you change anything here, you need to update - * the copy accordingly. */ -static size_t rand_drbg_seedlen(RAND_DRBG *drbg) +size_t rand_drbg_seedlen(RAND_DRBG *drbg) { /* * If no os entropy source is available then RAND_seed(buffer, bufsize) @@ -1086,7 +1088,7 @@ static int drbg_add(const void *buf, int num, double randomness) int ret = 0; RAND_DRBG *drbg = RAND_DRBG_get0_master(); size_t buflen; - size_t seedlen = rand_drbg_seedlen(drbg); + size_t seedlen; if (drbg == NULL) return 0; @@ -1094,6 +1096,9 @@ static int drbg_add(const void *buf, int num, double randomness) if (num < 0 || randomness < 0.0) return 0; + rand_drbg_lock(drbg); + seedlen = rand_drbg_seedlen(drbg); + buflen = (size_t)num; if (buflen < seedlen || randomness < (double) seedlen) { @@ -1103,10 +1108,13 @@ static int drbg_add(const void *buf, int num, double randomness) * inevitably. So we use a trick to mix the buffer contents into * the DRBG state without forcing a reseeding: we generate a * dummy random byte, using the buffer content as additional data. + * Note: This won't work with RAND_DRBG_FLAG_CTR_NO_DF. */ unsigned char dummy[1]; - return RAND_DRBG_generate(drbg, dummy, sizeof(dummy), 0, buf, buflen); + ret = RAND_DRBG_generate(drbg, dummy, sizeof(dummy), 0, buf, buflen); + rand_drbg_unlock(drbg); + return ret; #else /* * If an os entropy source is avaible then we declare the buffer content @@ -1130,7 +1138,6 @@ static int drbg_add(const void *buf, int num, double randomness) randomness = (double)seedlen; } - rand_drbg_lock(drbg); ret = rand_drbg_restart(drbg, buf, buflen, (size_t)(8 * randomness)); rand_drbg_unlock(drbg);