-
Notifications
You must be signed in to change notification settings - Fork 34
wp_drbg: gate wc_RNG_DRBG_Reseed on FIPS version #408
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -179,7 +179,15 @@ install_wolfssl() { | |
| # Determine configure option from tag | ||
| local fips_configure_arg="" | ||
| case "$fips_tag" in | ||
| v5.2.4|linuxv5.2.4) | ||
| # Distinct module (SP math, PATCH 4) — not the v5/cert4718 base | ||
| fips_configure_arg="v5.2.4" | ||
| ;; | ||
| v5.2.3|linuxv5.2.3) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 [Medium] Untested v5.2.3 FIPS tag mapping added without validation The PR adds a new case mapping Fix: Confirm |
||
| fips_configure_arg="v5.2.3" | ||
| ;; | ||
| v5.2.*|v5.3.*|v5.4.*|v5.5.*|linuxv5.*) | ||
| # v5.2.1/cert4718 and other v5.x map to the base v5 module | ||
| fips_configure_arg="v5" | ||
| ;; | ||
| v6.*|linuxv6.*) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,7 @@ | |
| #include <openssl/evp.h> | ||
| #include <openssl/hmac.h> | ||
|
|
||
| #include <wolfprovider/settings.h> | ||
| #include <wolfprovider/alg_funcs.h> | ||
| #include <wolfprovider/internal.h> | ||
|
|
||
|
|
@@ -61,6 +62,10 @@ typedef struct wp_DrbgCtx { | |
| OSSL_FUNC_rand_get_seed_fn* parentGetSeed; | ||
| /** Parent's clear_seed function. */ | ||
| OSSL_FUNC_rand_clear_seed_fn* parentClearSeed; | ||
| #ifndef WP_HAVE_DRBG_RESEED | ||
|
aidangarske marked this conversation as resolved.
|
||
| /** Set when a failed reseed re-instantiation left ctx->rng de-instantiated. */ | ||
| int rngError; | ||
| #endif | ||
| } wp_DrbgCtx; | ||
|
|
||
|
|
||
|
|
@@ -143,6 +148,8 @@ static void wp_drbg_free(wp_DrbgCtx* ctx) | |
| } | ||
| } | ||
|
|
||
| static int wp_drbg_uninstantiate(wp_DrbgCtx* ctx); | ||
|
|
||
| /** | ||
| * Instantiate a new DRBG. | ||
| * | ||
|
|
@@ -171,6 +178,11 @@ static int wp_drbg_instantiate(wp_DrbgCtx* ctx, unsigned int strength, | |
| ok = 0; | ||
| } | ||
|
|
||
| /* Free any existing DRBG before re-allocating to avoid a leak. */ | ||
| if (ok && ctx->rng != NULL) { | ||
| wp_drbg_uninstantiate(ctx); | ||
| } | ||
|
|
||
| if (ok && ctx->parentGetSeed != NULL) { | ||
| /* Get entropy from parent DRBG (no file I/O needed) */ | ||
| WOLFPROV_MSG_DEBUG(WP_LOG_COMP_RNG, | ||
|
|
@@ -189,22 +201,29 @@ static int wp_drbg_instantiate(wp_DrbgCtx* ctx, unsigned int strength, | |
| } | ||
|
|
||
| if (ok) { | ||
| /* Initialize wolfCrypt RNG with parent-provided seed */ | ||
| ctx->rng = OPENSSL_zalloc(sizeof(*ctx->rng)); | ||
| /* Use wc_rng_new (>= 5.0) so alloc and free use the same allocator, | ||
| * matching the root path and wc_rng_free() in teardown. */ | ||
| #if LIBWOLFSSL_VERSION_HEX >= 0x05000000 | ||
| ctx->rng = wc_rng_new(seed, (word32)seedLen, NULL); | ||
| if (ctx->rng == NULL) { | ||
|
aidangarske marked this conversation as resolved.
|
||
| ok = 0; | ||
| } | ||
| } | ||
|
|
||
| if (ok) { | ||
| int rc = wc_InitRngNonce(ctx->rng, seed, (word32)seedLen); | ||
| if (rc != 0) { | ||
| WOLFPROV_MSG_DEBUG_RETCODE(WP_LOG_COMP_RNG, | ||
| "wc_InitRngNonce", rc); | ||
| OPENSSL_free(ctx->rng); | ||
| ctx->rng = NULL; | ||
| #else | ||
| ctx->rng = OPENSSL_zalloc(sizeof(*ctx->rng)); | ||
| if (ctx->rng == NULL) { | ||
| ok = 0; | ||
| } | ||
| if (ok) { | ||
| int rc = wc_InitRngNonce(ctx->rng, seed, (word32)seedLen); | ||
| if (rc != 0) { | ||
| WOLFPROV_MSG_DEBUG_RETCODE(WP_LOG_COMP_RNG, | ||
| "wc_InitRngNonce", rc); | ||
| OPENSSL_clear_free(ctx->rng, sizeof(*ctx->rng)); | ||
| ctx->rng = NULL; | ||
| ok = 0; | ||
| } | ||
| } | ||
| #endif | ||
| } | ||
|
|
||
| /* Clear the seed from parent */ | ||
|
|
@@ -242,6 +261,13 @@ static int wp_drbg_instantiate(wp_DrbgCtx* ctx, unsigned int strength, | |
| #endif | ||
| } | ||
|
|
||
| #ifndef WP_HAVE_DRBG_RESEED | ||
| if (ok) { | ||
| /* Clear any prior reseed error state. */ | ||
| ctx->rngError = 0; | ||
| } | ||
| #endif | ||
|
|
||
| WOLFPROV_LEAVE(WP_LOG_COMP_RNG, __FILE__ ":" WOLFPROV_STRINGIZE(__LINE__), ok); | ||
| return ok; | ||
| } | ||
|
|
@@ -262,6 +288,9 @@ static int wp_drbg_uninstantiate(wp_DrbgCtx* ctx) | |
| OPENSSL_clear_free(ctx->rng, sizeof(*ctx->rng)); | ||
| #endif | ||
| ctx->rng = NULL; | ||
| #ifndef WP_HAVE_DRBG_RESEED | ||
| ctx->rngError = 0; | ||
| #endif | ||
| WOLFPROV_LEAVE(WP_LOG_COMP_RNG, __FILE__ ":" WOLFPROV_STRINGIZE(__LINE__), 1); | ||
| return 1; | ||
| } | ||
|
|
@@ -292,6 +321,16 @@ static int wp_drbg_generate(wp_DrbgCtx* ctx, unsigned char* out, | |
| if (strength > WP_DRBG_STRENGTH) { | ||
| ok = 0; | ||
| } | ||
| if (ok && ctx->rng == NULL) { | ||
| WOLFPROV_MSG_DEBUG(WP_LOG_COMP_RNG, "DRBG not instantiated"); | ||
| ok = 0; | ||
| } | ||
| #ifndef WP_HAVE_DRBG_RESEED | ||
| if (ok && ctx->rngError) { | ||
| WOLFPROV_MSG_DEBUG(WP_LOG_COMP_RNG, "DRBG in error state"); | ||
| ok = 0; | ||
| } | ||
| #endif | ||
| #if 0 | ||
| if (ok && (addInLen > 0)) { | ||
| rc = wc_RNG_DRBG_Reseed(ctx->rng, addIn, addInLen); | ||
|
|
@@ -322,6 +361,10 @@ static int wp_drbg_generate(wp_DrbgCtx* ctx, unsigned char* out, | |
| /** | ||
| * Reseed DRBG. | ||
| * | ||
| * When WP_HAVE_DRBG_RESEED is undefined (FIPS modules without an exported | ||
| * wc_RNG_DRBG_Reseed), this re-instantiates rather than reseeding: @p entropy / | ||
| * @p addIn are used as the nonce, not as DRBG entropy_input. | ||
| * | ||
| * @param [in, out] ctx DRBG context object. | ||
| * @param [in] predResist Prediction resistance required. | ||
| * @param [in] entropy Entropy data to reseed with. | ||
|
|
@@ -338,52 +381,130 @@ static int wp_drbg_reseed(wp_DrbgCtx* ctx, int predResist, | |
| { | ||
| int ok = 1; | ||
| int rc; | ||
| unsigned char *seed = NULL; | ||
| size_t seedLen = 0; | ||
|
|
||
| WOLFPROV_ENTER(WP_LOG_COMP_RNG, "wp_drbg_reseed"); | ||
|
|
||
| /* If no entropy provided, get fresh entropy from the OS source. */ | ||
| if (entropy == NULL || entropyLen == 0) { | ||
| seedLen = 48; | ||
| seed = OPENSSL_malloc(seedLen); | ||
| if (seed == NULL) { | ||
| ok = 0; | ||
| } | ||
| if (ok) { | ||
| OS_Seed osSeed; | ||
| rc = wc_GenerateSeed(&osSeed, seed, (word32)seedLen); | ||
| if (rc != 0) { | ||
| /* Reseed requires an instantiated DRBG. */ | ||
| if (ctx->rng == NULL) { | ||
| ok = 0; | ||
| } | ||
|
|
||
| /* wolfCrypt RNG APIs take word32 lengths; reject oversized inputs. */ | ||
| if (ok && entropy != NULL && entropyLen > 0xFFFFFFFFU) { | ||
| ok = 0; | ||
| } | ||
| if (ok && addIn != NULL && addInLen > 0xFFFFFFFFU) { | ||
| ok = 0; | ||
| } | ||
|
|
||
| #ifdef WP_HAVE_DRBG_RESEED | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟠 [Medium] Bare scope block introduced in wp_drbg_reseed native path The Fix: Remove the bare scope block to comply with the no-bare-scope-block convention; the
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔵 [Low] Bare scope block introduced in wp_drbg_reseed native reseed path · Logic The new native ( Fix: Declare |
||
| { | ||
| unsigned char* seed = NULL; | ||
| size_t seedLen = 0; | ||
|
|
||
| /* An in-place reseed needs explicit entropy. If the caller supplied | ||
| * none, draw fresh entropy from the cached /dev/urandom fd (SEED-SRC), | ||
| * which stays open across a seccomp sandbox, rather than | ||
| * wc_GenerateSeed() which opens /dev/urandom directly and would be | ||
| * blocked under the sandbox. */ | ||
| if (ok && (entropy == NULL || entropyLen == 0)) { | ||
| seedLen = 48; | ||
| seed = OPENSSL_malloc(seedLen); | ||
| if (seed == NULL) { | ||
| ok = 0; | ||
| } | ||
| else { | ||
| if (ok) { | ||
| #if defined(WP_HAVE_SEED_SRC) && defined(WP_HAVE_RANDOM) | ||
| if (wp_urandom_read(seed, seedLen) != (int)seedLen) { | ||
| ok = 0; | ||
| } | ||
| #else | ||
| OS_Seed osSeed; | ||
| if (wc_GenerateSeed(&osSeed, seed, (word32)seedLen) != 0) { | ||
| ok = 0; | ||
| } | ||
| #endif | ||
| } | ||
| if (ok) { | ||
| entropy = seed; | ||
| entropyLen = seedLen; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (ok && entropy != NULL && entropyLen > 0) { | ||
| rc = wc_RNG_DRBG_Reseed(ctx->rng, entropy, (word32)entropyLen); | ||
| if (rc != 0) { | ||
| WOLFPROV_MSG_DEBUG_RETCODE(WP_LOG_COMP_RNG, | ||
| "wc_RNG_DRBG_Reseed", rc); | ||
| ok = 0; | ||
| /* In-place SP 800-90A reseed via wolfCrypt's public DRBG API. */ | ||
| if (ok && entropy != NULL && entropyLen > 0) { | ||
| rc = wc_RNG_DRBG_Reseed(ctx->rng, entropy, (word32)entropyLen); | ||
| if (rc != 0) { | ||
| WOLFPROV_MSG_DEBUG_RETCODE(WP_LOG_COMP_RNG, | ||
| "wc_RNG_DRBG_Reseed", rc); | ||
| ok = 0; | ||
| } | ||
| } | ||
| } | ||
| if (ok && (addInLen > 0) && (addIn != NULL)) { | ||
| rc = wc_RNG_DRBG_Reseed(ctx->rng, addIn, (word32)addInLen); | ||
| if (rc != 0) { | ||
| WOLFPROV_MSG_DEBUG_RETCODE(WP_LOG_COMP_RNG, | ||
| "wc_RNG_DRBG_Reseed", rc); | ||
| ok = 0; | ||
| if (ok && (addInLen > 0) && (addIn != NULL)) { | ||
| rc = wc_RNG_DRBG_Reseed(ctx->rng, addIn, (word32)addInLen); | ||
| if (rc != 0) { | ||
| WOLFPROV_MSG_DEBUG_RETCODE(WP_LOG_COMP_RNG, | ||
| "wc_RNG_DRBG_Reseed", rc); | ||
| ok = 0; | ||
| } | ||
| } | ||
|
|
||
| if (seed != NULL) { | ||
| OPENSSL_clear_free(seed, seedLen); | ||
| } | ||
| } | ||
| #else | ||
|
aidangarske marked this conversation as resolved.
|
||
| /* FIPS modules without an exported wc_RNG_DRBG_Reseed (e.g. cert4718): | ||
| * re-instantiate in place via wc_FreeRng() + wc_InitRngNonce() on the same | ||
| * WC_RNG struct. wc_InitRngNonce self-seeds fresh entropy_input; with | ||
| * SEED-SRC that entropy comes from the cached /dev/urandom fd via the seed | ||
| * callback (so it stays sandbox-safe), otherwise from wc_GenerateSeed(). | ||
| * Caller entropy/addIn are folded in only as the nonce (which may be empty). | ||
| * A failed re-init leaves the DRBG de-instantiated and sets rngError. */ | ||
| if (ok) { | ||
| unsigned char* nonce = NULL; | ||
| word32 nonceLen = 0; | ||
| word32 eLen = (entropy != NULL) ? (word32)entropyLen : 0; | ||
| word32 aLen = (addIn != NULL) ? (word32)addInLen : 0; | ||
|
|
||
| /* Securely clear and free locally allocated seed buffer. */ | ||
| if (seed != NULL) { | ||
| OPENSSL_clear_free(seed, seedLen); | ||
| /* Build nonce = entropy || addIn (either may be absent). */ | ||
| if (aLen > (0xFFFFFFFFU - eLen)) { | ||
| ok = 0; | ||
| } | ||
| if (ok && (eLen + aLen) > 0) { | ||
| nonceLen = eLen + aLen; | ||
| nonce = OPENSSL_malloc(nonceLen); | ||
| if (nonce == NULL) { | ||
| ok = 0; | ||
| } | ||
| else { | ||
| if (eLen > 0) { | ||
| XMEMCPY(nonce, entropy, eLen); | ||
| } | ||
| if (aLen > 0) { | ||
| XMEMCPY(nonce + eLen, addIn, aLen); | ||
| } | ||
| } | ||
| } | ||
| if (ok) { | ||
| wc_FreeRng(ctx->rng); | ||
|
aidangarske marked this conversation as resolved.
|
||
| rc = wc_InitRngNonce(ctx->rng, nonce, nonceLen); | ||
| if (rc != 0) { | ||
| WOLFPROV_MSG_DEBUG_RETCODE(WP_LOG_COMP_RNG, | ||
| "wc_InitRngNonce", rc); | ||
| ctx->rngError = 1; | ||
| ok = 0; | ||
| } | ||
| else { | ||
| /* Recovered: clear any prior reseed error. */ | ||
| ctx->rngError = 0; | ||
| } | ||
| } | ||
| if (nonce != NULL) { | ||
| OPENSSL_clear_free(nonce, nonceLen); | ||
| } | ||
| } | ||
| #endif /* WP_HAVE_DRBG_RESEED */ | ||
|
|
||
| (void)predResist; | ||
|
|
||
|
|
@@ -512,15 +633,25 @@ static int wp_drbg_get_ctx_params(wp_DrbgCtx* ctx, OSSL_PARAM params[]) | |
|
|
||
| WOLFPROV_ENTER(WP_LOG_COMP_RNG, "wp_drbg_get_ctx_params"); | ||
|
|
||
| (void)ctx; | ||
|
|
||
| p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST); | ||
| if ((p != NULL) && (!OSSL_PARAM_set_size_t(p, WP_DRBG_MAX_REQUESTS))) { | ||
| ok = 0; | ||
| } | ||
| if (ok) { | ||
| int state = EVP_RAND_STATE_READY; | ||
|
|
||
| if (ctx->rng == NULL) { | ||
| state = EVP_RAND_STATE_UNINITIALISED; | ||
| } | ||
| #ifndef WP_HAVE_DRBG_RESEED | ||
| /* Failed reseed re-instantiation left the DRBG de-instantiated. */ | ||
| else if (ctx->rngError) { | ||
| state = EVP_RAND_STATE_ERROR; | ||
| } | ||
| #endif | ||
|
|
||
| p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE); | ||
| if ((p != NULL) && (!OSSL_PARAM_set_int(p, EVP_RAND_STATE_READY))) { | ||
| if ((p != NULL) && (!OSSL_PARAM_set_int(p, state))) { | ||
| ok = 0; | ||
| } | ||
| } | ||
|
|
@@ -622,6 +753,12 @@ static size_t wp_drbg_get_seed(wp_DrbgCtx* ctx, unsigned char** pSeed, | |
| "DRBG not instantiated"); | ||
| goto end; | ||
| } | ||
| #ifndef WP_HAVE_DRBG_RESEED | ||
| if (ctx->rngError) { | ||
| WOLFPROV_MSG_DEBUG(WP_LOG_COMP_RNG, "DRBG in error state"); | ||
| goto end; | ||
| } | ||
| #endif | ||
|
|
||
| buffer = OPENSSL_secure_malloc(minLen); | ||
| if (buffer == NULL) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔵 [Low] Non-ASCII em-dash in shell comment
The added comment uses a Unicode em-dash (
—) in an otherwise ASCII source tree. For consistency with the rest of the C/shell sources and to avoid encoding surprises in tooling/diffs, prefer a plain ASCII hyphen.Fix: Replace the em-dash with an ASCII hyphen.