wolfcrypt/src/random.c: backport changes to random.[ch] from #9595 "20251229-linuxkm-rng-wolfentropy" (450b0b46c6, 299ca1cfef, 0621615b15) and #9616 "20251230-persistent-drbg" (3c15be6610, c1d2828daf, 0059f1647e, 1e0351a69b).
This commit is contained in:
@@ -68,6 +68,9 @@ This library contains implementation for the random number generator.
|
||||
|
||||
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
#ifdef WC_RNG_BANK_SUPPORT
|
||||
#include <wolfssl/wolfcrypt/rng_bank.h>
|
||||
#endif
|
||||
#include <wolfssl/wolfcrypt/cpuid.h>
|
||||
|
||||
#ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */
|
||||
@@ -369,6 +372,12 @@ static int Hash_df(DRBG_internal* drbg, byte* out, word32 outSz, byte type,
|
||||
XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST);
|
||||
#endif
|
||||
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
if (ret != 0)
|
||||
WOLFSSL_DEBUG_PRINTF("ERROR: %s failed with err = %d", __FUNCTION__,
|
||||
ret);
|
||||
#endif
|
||||
|
||||
return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
|
||||
}
|
||||
|
||||
@@ -406,6 +415,13 @@ static int Hash_DRBG_Reseed(DRBG_internal* drbg, const byte* seed, word32 seedSz
|
||||
#ifndef WOLFSSL_SMALL_STACK_CACHE
|
||||
WC_FREE_VAR_EX(newV, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif
|
||||
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
if (ret != 0)
|
||||
WOLFSSL_DEBUG_PRINTF("ERROR: Hash_DRBG_Reseed failed with err %d.",
|
||||
ret);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -525,6 +541,19 @@ static int Hash_gen(DRBG_internal* drbg, byte* out, word32 outSz, const byte* V)
|
||||
WC_FREE_VAR_EX(data, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif
|
||||
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
if ((ret != DRBG_SUCCESS) && (ret != DRBG_FAILURE)) {
|
||||
/* Note, if we're just going to return DRBG_FAILURE to the caller, then
|
||||
* there's no point printing it out here because (1) the lower-level
|
||||
* code that was remapped to DRBG_FAILURE already got printed before the
|
||||
* remapping, so a DRBG_FAILURE message would just be spamming the log,
|
||||
* and (2) the caller will actually see the DRBG_FAILURE code, and is
|
||||
* free to (and probably will) log it itself.
|
||||
*/
|
||||
WOLFSSL_DEBUG_PRINTF("ERROR: Hash_gen failed with err %d.", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
|
||||
}
|
||||
|
||||
@@ -635,6 +664,14 @@ static int Hash_DRBG_Generate(DRBG_internal* drbg, byte* out, word32 outSz)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
if ((ret != DRBG_SUCCESS) && (ret != DRBG_FAILURE)) {
|
||||
/* see note above regarding log spam reduction */
|
||||
WOLFSSL_DEBUG_PRINTF("ERROR: Hash_DRBG_Generate failed with err %d.",
|
||||
ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE;
|
||||
}
|
||||
|
||||
@@ -721,7 +758,6 @@ int wc_RNG_TestSeed(const byte* seed, word32 seedSz)
|
||||
if (ConstantCompare(seed + seedIdx,
|
||||
seed + seedIdx + scratchSz,
|
||||
(int)scratchSz) == 0) {
|
||||
|
||||
ret = DRBG_CONT_FAILURE;
|
||||
}
|
||||
seedIdx += SEED_BLOCK_SZ;
|
||||
@@ -922,6 +958,11 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
|
||||
else {
|
||||
ret = seedCb(&rng->seed, seed, seedSz);
|
||||
if (ret != 0) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"ERROR: seedCb in _InitRng() failed with err = %d",
|
||||
ret);
|
||||
#endif
|
||||
ret = DRBG_FAILURE;
|
||||
}
|
||||
}
|
||||
@@ -931,6 +972,10 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
|
||||
if (ret != 0) {
|
||||
#if defined(DEBUG_WOLFSSL)
|
||||
WOLFSSL_MSG_EX("Seed generation failed... %d", ret);
|
||||
#elif defined(WC_VERBOSE_RNG)
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"ERROR: wc_GenerateSeed() in _InitRng() failed with err %d",
|
||||
ret);
|
||||
#endif
|
||||
ret = DRBG_FAILURE;
|
||||
rng->status = DRBG_FAILED;
|
||||
@@ -942,7 +987,14 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
|
||||
if (ret != 0) {
|
||||
WOLFSSL_MSG_EX("wc_RNG_TestSeed failed... %d", ret);
|
||||
}
|
||||
#elif defined(WC_VERBOSE_RNG)
|
||||
if (ret != DRBG_SUCCESS) {
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"ERROR: wc_RNG_TestSeed() in _InitRng() returned err %d.",
|
||||
ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret == DRBG_SUCCESS)
|
||||
ret = Hash_DRBG_Instantiate((DRBG_internal *)rng->drbg,
|
||||
seed + SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ,
|
||||
@@ -1112,19 +1164,35 @@ static int PollAndReSeed(WC_RNG* rng)
|
||||
else {
|
||||
ret = seedCb(&rng->seed, newSeed, SEED_SZ + SEED_BLOCK_SZ);
|
||||
if (ret != 0) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF("ERROR: seedCb() in PollAndReSeed() "
|
||||
"failed with err %d", ret);
|
||||
#endif
|
||||
ret = DRBG_FAILURE;
|
||||
}
|
||||
}
|
||||
#else
|
||||
ret = wc_GenerateSeed(&rng->seed, newSeed,
|
||||
SEED_SZ + SEED_BLOCK_SZ);
|
||||
#endif
|
||||
if (ret != 0)
|
||||
if (ret != 0) {
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"ERROR: wc_GenerateSeed() in PollAndReSeed() failed with "
|
||||
"err %d", ret);
|
||||
#endif
|
||||
ret = DRBG_FAILURE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (ret == DRBG_SUCCESS)
|
||||
if (ret == DRBG_SUCCESS) {
|
||||
ret = wc_RNG_TestSeed(newSeed, SEED_SZ + SEED_BLOCK_SZ);
|
||||
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
if (ret != DRBG_SUCCESS)
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"ERROR: wc_RNG_TestSeed() in PollAndReSeed() returned "
|
||||
"err %d.", ret);
|
||||
#endif
|
||||
}
|
||||
if (ret == DRBG_SUCCESS)
|
||||
ret = Hash_DRBG_Reseed((DRBG_internal *)rng->drbg,
|
||||
newSeed + SEED_BLOCK_SZ, SEED_SZ);
|
||||
@@ -1146,8 +1214,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;
|
||||
|
||||
@@ -1194,6 +1266,11 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
|
||||
#ifdef CUSTOM_RAND_GENERATE_BLOCK
|
||||
XMEMSET(output, 0, sz);
|
||||
ret = (int)CUSTOM_RAND_GENERATE_BLOCK(output, sz);
|
||||
#ifdef WC_VERBOSE_RNG
|
||||
if (ret != 0)
|
||||
WOLFSSL_DEBUG_PRINTF(
|
||||
"ERROR: CUSTOM_RAND_GENERATE_BLOCK failed with err %d.", ret);
|
||||
#endif
|
||||
#else
|
||||
|
||||
#ifdef HAVE_HASHDRBG
|
||||
@@ -1243,6 +1320,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)
|
||||
{
|
||||
@@ -1257,6 +1370,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
|
||||
@@ -2994,32 +3112,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 <linux/random.h>
|
||||
#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 <linux/random.h>
|
||||
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
|
||||
{
|
||||
(void)os;
|
||||
@@ -3027,11 +3123,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
|
||||
@@ -3039,23 +3133,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 <sys/random.h>
|
||||
int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user