From a5cd8842ffb374a8744f764a19c6ab0c755316a5 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Thu, 8 Jan 2026 13:45:39 -0600 Subject: [PATCH] backport changes to random.[ch] from #9616 (3c15be6610, c1d2828daf, 0059f1647e, 1e0351a69b) --- wolfcrypt/src/random.c | 101 ++++++++++++++++++++++++------------- wolfssl/wolfcrypt/random.h | 63 ++++++++++++++++------- 2 files changed, 110 insertions(+), 54 deletions(-) diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 20a777c79..e445978e5 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -68,6 +68,9 @@ This library contains implementation for the random number generator. #include +#ifdef WC_RNG_BANK_SUPPORT + #include +#endif #include #ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */ @@ -1197,8 +1200,12 @@ static int PollAndReSeed(WC_RNG* rng) #endif /* place a generated block in output */ +#ifdef WC_RNG_BANK_SUPPORT +static int wc_local_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) +#else WOLFSSL_ABI int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) +#endif { int ret; @@ -1298,6 +1305,42 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) return ret; } +#ifdef WC_RNG_BANK_SUPPORT +WOLFSSL_ABI +int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) +{ + if (rng == NULL) + return BAD_FUNC_ARG; + + if (rng->status == WC_DRBG_BANKREF) { + int ret; + struct wc_rng_bank_inst *bank_inst = NULL; + + ret = wc_local_rng_bank_checkout_for_bankref(rng->bankref, &bank_inst); + if (ret != 0) + return ret; + if (bank_inst == NULL) + return BAD_STATE_E; + ret = wc_local_RNG_GenerateBlock(WC_RNG_BANK_INST_TO_RNG(bank_inst), + output, sz); + { + int checkin_ret = wc_rng_bank_checkin(rng->bankref, &bank_inst); + if (checkin_ret != 0) { +#ifdef WC_VERBOSE_RNG + WOLFSSL_DEBUG_PRINTF( + "ERROR: wc_RNG_GenerateBlock() wc_rng_bank_checkin() " + "failed with err %d.", checkin_ret); +#endif + if (ret == 0) + ret = checkin_ret; + } + } + return ret; + } + else + return wc_local_RNG_GenerateBlock(rng, output, sz); +} +#endif int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) { @@ -1312,6 +1355,11 @@ int wc_FreeRng(WC_RNG* rng) if (rng == NULL) return BAD_FUNC_ARG; +#ifdef WC_RNG_BANK_SUPPORT + if (rng->status == WC_DRBG_BANKREF) + return wc_BankRef_Release(rng); +#endif /* WC_RNG_BANK_SUPPORT */ + #if defined(WOLFSSL_ASYNC_CRYPT) wolfAsync_DevCtxFree(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG); #endif @@ -3049,32 +3097,10 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) #elif defined(WOLFSSL_LINUXKM) - /* When registering the kernel default DRBG with a native/intrinsic entropy - * source, fallback to get_random_bytes() isn't allowed because we replace - * it with our DRBG. - */ + #ifndef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT + #include + #endif - #if defined(HAVE_ENTROPY_MEMUSE) && \ - defined(LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT) - - int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) - { - (void)os; - return wc_Entropy_Get(MAX_ENTROPY_BITS, output, sz); - } - - #elif (defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED)) && \ - defined(LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT) - - int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) - { - (void)os; - return wc_GenerateSeed_IntelRD(NULL, output, sz); - } - - #else /* !((HAVE_ENTROPY_MEMUSE || HAVE_*_RDSEED) && LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT) */ - - #include int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { (void)os; @@ -3082,11 +3108,9 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) #ifdef HAVE_ENTROPY_MEMUSE ret = wc_Entropy_Get(MAX_ENTROPY_BITS, output, sz); - if (ret == 0) { + if (ret == 0) return 0; - } #ifdef ENTROPY_MEMUSE_FORCE_FAILURE - /* Don't fallback to /dev/urandom. */ return ret; #endif #endif @@ -3094,23 +3118,30 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_AMD_RDSEED) if (IS_INTEL_RDSEED(intel_flags)) { ret = wc_GenerateSeed_IntelRD(NULL, output, sz); - #ifndef FORCE_FAILURE_RDSEED if (ret == 0) - #endif - { - return ret; - } + return 0; + #ifdef FORCE_FAILURE_RDSEED + return ret; + #endif } #endif /* HAVE_INTEL_RDSEED || HAVE_AMD_RDSEED */ + #ifdef LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT + #if !defined(HAVE_ENTROPY_MEMUSE) && \ + !defined(HAVE_INTEL_RDSEED) && \ + !defined(HAVE_AMD_RDSEED) + #error LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT requires an intrinsic entropy source. + #else + return ret; + #endif + #else (void)ret; get_random_bytes(output, sz); return 0; + #endif } - #endif /* !(HAVE_*_RDSEED && LINUXKM_LKCAPI_REGISTER_HASH_DRBG_DEFAULT) */ - #elif defined(WOLFSSL_BSDKM) #include int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) diff --git a/wolfssl/wolfcrypt/random.h b/wolfssl/wolfcrypt/random.h index 29ad26d3e..834db3ee8 100644 --- a/wolfssl/wolfcrypt/random.h +++ b/wolfssl/wolfcrypt/random.h @@ -243,12 +243,6 @@ struct OS_Seed { #define RNG_HEALTH_TEST_CHECK_SIZE (WC_SHA256_DIGEST_SIZE * 4) -/* RNG health states */ -#define WC_DRBG_NOT_INIT 0 -#define WC_DRBG_OK 1 -#define WC_DRBG_FAILED 2 -#define WC_DRBG_CONT_FAILED 3 - struct DRBG_internal { #ifdef WORD64_AVAILABLE word64 reseedCtr; @@ -267,26 +261,57 @@ struct DRBG_internal { byte digest_scratch[WC_SHA256_DIGEST_SIZE]; #endif }; +#endif /* HAVE_HASHDRBG */ + +/* RNG health states */ +#define WC_DRBG_NOT_INIT 0 +#define WC_DRBG_OK 1 +#define WC_DRBG_FAILED 2 +#define WC_DRBG_CONT_FAILED 3 +#ifdef WC_RNG_BANK_SUPPORT + #define WC_DRBG_BANKREF 4 /* Marks the WC_RNG as a ref to a wc_rng_bank, + * with no usable DRBG of its own. + */ #endif /* RNG context */ struct WC_RNG { struct OS_Seed seed; void* heap; -#ifdef HAVE_HASHDRBG - /* Hash-based Deterministic Random Bit Generator */ - struct DRBG* drbg; -#if defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_STATIC_MEMORY) - struct DRBG_internal drbg_data; -#endif -#ifdef WOLFSSL_SMALL_STACK_CACHE - /* Scratch buffer slots -- everything is preallocated by _InitRng(). */ - struct DRBG_internal *drbg_scratch; - byte *health_check_scratch; - byte *newSeed_buf; -#endif byte status; -#endif /* HAVE_HASHDRBG */ + +#ifdef HAVE_ANONYMOUS_INLINE_AGGREGATES + union { +#endif + + #ifdef WC_RNG_BANK_SUPPORT + struct wc_rng_bank *bankref; + #endif + + #ifdef HAVE_HASHDRBG + #ifdef HAVE_ANONYMOUS_INLINE_AGGREGATES + struct { + #endif + /* Hash-based Deterministic Random Bit Generator */ + struct DRBG* drbg; + #if defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_STATIC_MEMORY) + struct DRBG_internal drbg_data; + #endif + #ifdef WOLFSSL_SMALL_STACK_CACHE + /* Scratch buffers -- all preallocated by _InitRng(). */ + struct DRBG_internal *drbg_scratch; + byte *health_check_scratch; + byte *newSeed_buf; + #endif + #ifdef HAVE_ANONYMOUS_INLINE_AGGREGATES + }; + #endif + #endif /* HAVE_HASHDRBG */ + +#ifdef HAVE_ANONYMOUS_INLINE_AGGREGATES + }; +#endif + #if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID) pid_t pid; #endif