X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=fips%2Frand%2Ffips_drbg_lib.c;h=7a0a1070e2b21dd740125a1e3256a1ee4bed2ff6;hp=31c5a7a8b003c7d6ad3eb9654a7c1b331e416944;hb=42bd0a6b3c73c71b69967503c0ee0a3598b52655;hpb=fbbabb646c707b7c18a67a2724efe1a12bae15a7 diff --git a/fips/rand/fips_drbg_lib.c b/fips/rand/fips_drbg_lib.c index 31c5a7a8b0..7a0a1070e2 100644 --- a/fips/rand/fips_drbg_lib.c +++ b/fips/rand/fips_drbg_lib.c @@ -112,16 +112,17 @@ DRBG_CTX *FIPS_drbg_new(int type, unsigned int flags) void FIPS_drbg_free(DRBG_CTX *dctx) { - dctx->uninstantiate(dctx); - OPENSSL_cleanse(dctx, sizeof(DRBG_CTX)); + if (dctx->uninstantiate) + dctx->uninstantiate(dctx); + OPENSSL_cleanse(&dctx->d, sizeof(dctx->d)); OPENSSL_free(dctx); } int FIPS_drbg_instantiate(DRBG_CTX *dctx, - int strength, const unsigned char *pers, size_t perslen) { - size_t entlen, noncelen; + size_t entlen = 0, noncelen = 0; + unsigned char *nonce = NULL, *entropy = NULL; #if 0 /* Put here so error script picks them up */ @@ -151,15 +152,9 @@ int FIPS_drbg_instantiate(DRBG_CTX *dctx, goto end; } - if (strength > dctx->strength) - { - r = FIPS_R_INSUFFICIENT_SECURITY_STRENGTH; - goto end; - } - dctx->status = DRBG_STATUS_ERROR; - entlen = dctx->get_entropy(dctx, dctx->entropy, dctx->strength, + entlen = dctx->get_entropy(dctx, &entropy, dctx->strength, dctx->min_entropy, dctx->max_entropy); if (entlen < dctx->min_entropy || entlen > dctx->max_entropy) @@ -170,8 +165,7 @@ int FIPS_drbg_instantiate(DRBG_CTX *dctx, if (dctx->max_nonce > 0) { - - noncelen = dctx->get_nonce(dctx, dctx->nonce, + noncelen = dctx->get_nonce(dctx, &nonce, dctx->strength / 2, dctx->min_nonce, dctx->max_nonce); @@ -182,12 +176,10 @@ int FIPS_drbg_instantiate(DRBG_CTX *dctx, } } - else - noncelen = 0; if (!dctx->instantiate(dctx, - dctx->entropy, entlen, - dctx->nonce, noncelen, + entropy, entlen, + nonce, noncelen, pers, perslen)) { r = FIPS_R_ERROR_INSTANTIATING_DRBG; @@ -197,18 +189,19 @@ int FIPS_drbg_instantiate(DRBG_CTX *dctx, dctx->status = DRBG_STATUS_READY; dctx->reseed_counter = 1; - /* Initial test value for reseed interval */ - dctx->reseed_interval = 1<<24; end: - OPENSSL_cleanse(dctx->entropy, sizeof(dctx->entropy)); - OPENSSL_cleanse(dctx->nonce, sizeof(dctx->nonce)); + if (entropy && dctx->cleanup_entropy) + dctx->cleanup_entropy(dctx, entropy, entlen); + + if (nonce && dctx->cleanup_nonce) + dctx->cleanup_nonce(dctx, nonce, noncelen); if (dctx->status == DRBG_STATUS_READY) return 1; - if (r && !(dctx->flags & DRBG_FLAG_TEST)) + if (r && !(dctx->flags & DRBG_FLAG_NOERR)) FIPSerr(FIPS_F_FIPS_DRBG_INSTANTIATE, r); return 0; @@ -218,6 +211,7 @@ int FIPS_drbg_instantiate(DRBG_CTX *dctx, int FIPS_drbg_reseed(DRBG_CTX *dctx, const unsigned char *adin, size_t adinlen) { + unsigned char *entropy = NULL; size_t entlen; int r = 0; @@ -245,7 +239,7 @@ int FIPS_drbg_reseed(DRBG_CTX *dctx, dctx->status = DRBG_STATUS_ERROR; - entlen = dctx->get_entropy(dctx, dctx->entropy, dctx->strength, + entlen = dctx->get_entropy(dctx, &entropy, dctx->strength, dctx->min_entropy, dctx->max_entropy); if (entlen < dctx->min_entropy || entlen > dctx->max_entropy) @@ -254,18 +248,20 @@ int FIPS_drbg_reseed(DRBG_CTX *dctx, goto end; } - if (!dctx->reseed(dctx, dctx->entropy, entlen, adin, adinlen)) + if (!dctx->reseed(dctx, entropy, entlen, adin, adinlen)) goto end; dctx->status = DRBG_STATUS_READY; dctx->reseed_counter = 1; end: - OPENSSL_cleanse(dctx->entropy, sizeof(dctx->entropy)); + + if (entropy && dctx->cleanup_entropy) + dctx->cleanup_entropy(dctx, entropy, entlen); if (dctx->status == DRBG_STATUS_READY) return 1; - if (r && !(dctx->flags & DRBG_FLAG_TEST)) + if (r && !(dctx->flags & DRBG_FLAG_NOERR)) FIPSerr(FIPS_F_FIPS_DRBG_RESEED, r); return 0; @@ -277,6 +273,17 @@ int FIPS_drbg_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen, const unsigned char *adin, size_t adinlen) { int r = 0; + + if (dctx->status != DRBG_STATUS_READY + && dctx->status != DRBG_STATUS_RESEED) + { + if (dctx->status == DRBG_STATUS_ERROR) + r = FIPS_R_IN_ERROR_STATE; + else if(dctx->status == DRBG_STATUS_UNINITIALISED) + r = FIPS_R_NOT_INSTANTIATED; + goto end; + } + if (outlen > dctx->max_request) { r = FIPS_R_REQUEST_TOO_LARGE_FOR_DRBG; @@ -299,21 +306,14 @@ int FIPS_drbg_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen, adin = NULL; adinlen = 0; } - if (dctx->status != DRBG_STATUS_READY) - { - if (dctx->status == DRBG_STATUS_ERROR) - r = FIPS_R_IN_ERROR_STATE; - else if(dctx->status == DRBG_STATUS_UNINITIALISED) - r = FIPS_R_NOT_INSTANTIATED; - goto end; - } + if (!dctx->generate(dctx, out, outlen, adin, adinlen)) { r = FIPS_R_GENERATE_ERROR; dctx->status = DRBG_STATUS_ERROR; goto end; } - if (dctx->reseed_counter > dctx->reseed_interval) + if (dctx->reseed_counter >= dctx->reseed_interval) dctx->status = DRBG_STATUS_RESEED; else dctx->reseed_counter++; @@ -321,7 +321,7 @@ int FIPS_drbg_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen, end: if (r) { - if (!(dctx->flags & DRBG_FLAG_TEST)) + if (!(dctx->flags & DRBG_FLAG_NOERR)) FIPSerr(FIPS_F_FIPS_DRBG_GENERATE, r); return 0; } @@ -331,26 +331,50 @@ int FIPS_drbg_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen, int FIPS_drbg_uninstantiate(DRBG_CTX *dctx) { - int save_type, save_flags, rv; - save_type = dctx->type; - save_flags = dctx->flags; - rv = dctx->uninstantiate(dctx); - OPENSSL_cleanse(dctx, sizeof(DRBG_CTX)); + int rv; + if (!dctx->uninstantiate) + rv = 1; + else + rv = dctx->uninstantiate(dctx); + /* Although we'd like to cleanse here we can't because we have to + * test the uninstantiate really zeroes the data. + */ + memset(&dctx->d, 0, sizeof(dctx->d)); + dctx->status = DRBG_STATUS_UNINITIALISED; /* If method has problems uninstantiating, return error */ return rv; } -int FIPS_drbg_set_test_mode(DRBG_CTX *dctx, - size_t (*get_entropy)(DRBG_CTX *ctx, unsigned char *out, +int FIPS_drbg_set_callbacks(DRBG_CTX *dctx, + size_t (*get_entropy)(DRBG_CTX *ctx, unsigned char **pout, + int entropy, size_t min_len, size_t max_len), + void (*cleanup_entropy)(DRBG_CTX *ctx, unsigned char *out, size_t olen), + size_t (*get_nonce)(DRBG_CTX *ctx, unsigned char **pout, int entropy, size_t min_len, size_t max_len), - size_t (*get_nonce)(DRBG_CTX *ctx, unsigned char *out, - int entropy, size_t min_len, size_t max_len)) + void (*cleanup_nonce)(DRBG_CTX *ctx, unsigned char *out, size_t olen)) { if (dctx->status != DRBG_STATUS_UNINITIALISED) return 0; - dctx->flags |= DRBG_FLAG_TEST; dctx->get_entropy = get_entropy; + dctx->cleanup_entropy = cleanup_entropy; dctx->get_nonce = get_nonce; + dctx->cleanup_nonce = cleanup_nonce; + return 1; + } + +int FIPS_drbg_set_rand_callbacks(DRBG_CTX *dctx, + size_t (*get_adin)(DRBG_CTX *ctx, unsigned char **pout), + void (*cleanup_adin)(DRBG_CTX *ctx, unsigned char *out, size_t olen), + int (*rand_seed_cb)(DRBG_CTX *ctx, const void *buf, int num), + int (*rand_add_cb)(DRBG_CTX *ctx, + const void *buf, int num, double entropy)) + { + if (dctx->status != DRBG_STATUS_UNINITIALISED) + return 0; + dctx->get_adin = get_adin; + dctx->cleanup_adin = cleanup_adin; + dctx->rand_seed_cb = rand_seed_cb; + dctx->rand_add_cb = rand_add_cb; return 1; } @@ -373,3 +397,37 @@ int FIPS_drbg_get_strength(DRBG_CTX *dctx) { return dctx->strength; } + +static int drbg_stick = 0; + +void FIPS_drbg_stick(void) + { + drbg_stick = 1; + } + +/* Continuous DRBG utility function */ +int fips_drbg_cprng_test(DRBG_CTX *dctx, const unsigned char *out) + { + /* No CPRNG in test mode */ + if (dctx->flags & DRBG_FLAG_TEST) + return 1; + /* Check block is valid: should never happen */ + if (dctx->lb_valid == 0) + { + FIPSerr(FIPS_F_DRBG_CPRNG_TEST, FIPS_R_INTERNAL_ERROR); + fips_set_selftest_fail(); + return 0; + } + if (drbg_stick) + memcpy(dctx->lb, out, dctx->blocklength); + /* Check against last block: fail if match */ + if (!memcmp(dctx->lb, out, dctx->blocklength)) + { + FIPSerr(FIPS_F_DRBG_CPRNG_TEST, FIPS_R_DRBG_STUCK); + fips_set_selftest_fail(); + return 0; + } + /* Save last block for next comparison */ + memcpy(dctx->lb, out, dctx->blocklength); + return 1; + }