mirror of https://github.com/wolfSSL/wolfssl.git
wolfcrypt/src/random.c, wolfssl/wolfcrypt/random.h, wolfcrypt/src/rng_bank.c, wolfssl/wolfcrypt/rng_bank.h, wolfcrypt/test/test.c: generalize SP 800-90C RBG chains from a leaf tag to strata:
* struct WC_RNG.isRbgcLeaf becomes int RBGCStratum: 0 for a root, n for a chain member seeded from a stratum-(n-1) parent, sticky for the instance's lifetime, with SEQ_OVERFLOW_E on stratum overflow; wc_RNG_DRBG_IsRBGCLeaf() becomes wc_RNG_DRBG_GetRBGCStratum(); SpawnRngRBGC() reworks to parent/child terms with a flags argument, omitting the seed health test (superfluous when a healthy DRBG generates the seed data); * the wc_InitRng*RBGC() constructors gain a flags argument (WC_RNG_INIT_FLAGS_*); new wc_RNG_DRBG_ReseedRBGC_Uncredited(); * banked next seeds carry provenance: nextSeedRBGCStratum in the DRBG aperture, WC_RNG_FLAG_RBGC_NEXT_SEED marking a chain-filled bank, wc_RNG_DRBG_NextSeedGenerate_RBGC() to fill from a parent, and wc_RNG_DRBG_GetNextSeedRBGCStratum() (race-free via the aperture protocol) to interrogate it; * carve the whole facility out under WC_RNG_HAVE_RBGC (opt-out: WC_RNG_NO_RBGC), derived from HAVE_HASHDRBG && !CUSTOM_RAND_GENERATE_BLOCK; * rng_bank: WC_RNG_BANK_FLAG_INIT_RBGC instantiates bank instances as chain children of an internal root, on FIPS v7+ boundaries with _LOCK_REQUIRED; * test.c: rng_drbg_rbgc_test() reworked for strata (including a pre-v7 compat arm via the rng_bank.h shims), spawn contracts updated for the flags argument, and stratum probes in the svc and bank tests.pull/11435/head
parent
2237e5e1c1
commit
7bca2d66f6
|
|
@ -806,6 +806,7 @@ WC_RNG_BLOCKING
|
|||
WC_RNG_NO_LOCK
|
||||
WC_RNG_NO_LOCK_FULL_MUTEX
|
||||
WC_RNG_NO_NEXT_SEED
|
||||
WC_RNG_NO_RBGC
|
||||
WC_RSA_NONBLOCK_TIME
|
||||
WC_RSA_NO_FERMAT_CHECK
|
||||
WC_RTL8735B_NO_DERIVE_CACHE
|
||||
|
|
|
|||
|
|
@ -839,6 +839,10 @@ int wc_RNG_DRBG_Reseed_Nonce(WC_RNG* rng, const byte* seed, word32 seedSz,
|
|||
return ret;
|
||||
|
||||
ret = Hash_DRBG_Reseed(rng, seed, seedSz, nonce, nonceSz, 1 /* credited */);
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
if (ret == 0)
|
||||
rng->RBGCStratum = 0;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -847,16 +851,53 @@ int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* seed, word32 seedSz) {
|
|||
return wc_RNG_DRBG_Reseed_Nonce(rng, seed, seedSz, NULL, 0);
|
||||
}
|
||||
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
|
||||
/* Returns 1 if rng was seeded from another DRBG's output (an SP 800-90C
|
||||
* chain leaf, via wc_InitRng*RBGC() or wc_RNG_DRBG_ReseedRBGC()), else 0.
|
||||
* The tag is sticky for the instance's lifetime; a leaf is never usable as
|
||||
* a chain root. */
|
||||
int wc_RNG_DRBG_IsRBGCLeaf(const WC_RNG* rng)
|
||||
int wc_RNG_DRBG_GetRBGCStratum(const WC_RNG* rng)
|
||||
{
|
||||
return (rng != NULL) && rng->isRbgcLeaf;
|
||||
if (rng)
|
||||
return rng->RBGCStratum;
|
||||
else
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
#ifdef WC_RNG_HAVE_NEXT_SEED
|
||||
int wc_RNG_DRBG_GetNextSeedRBGCStratum(const WC_RNG* rng)
|
||||
{
|
||||
if (rng == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
/* Race-free via the NextSeed aperture protocol. If called with rng locked,
|
||||
* and ->nextSeedLen == WC_DRBG_NEXT_SEED_READY, then competing producers
|
||||
* and consumers are all excluded, unambiguously marking ->nextSeedRBGCStratum
|
||||
* as strictly reliable and stable. nextSeedLen functions as the
|
||||
* synchronizer -- the producer writes ->nextSeedRBGCStratum before publishing
|
||||
* WC_DRBG_NEXT_SEED_READY to nextSeedLen with release semantics.
|
||||
*/
|
||||
|
||||
#ifndef NO_SHA256
|
||||
if ((rng->drbgType == WC_DRBG_SHA256) && (rng->drbg != NULL)) {
|
||||
if (WOLFSSL_ATOMIC_LOAD(((const DRBG_internal*)rng->drbg)->nextSeedLen) != WC_DRBG_NEXT_SEED_READY)
|
||||
return NOT_READY_E;
|
||||
else
|
||||
return ((const DRBG_internal *)rng->drbg)->nextSeedRBGCStratum;
|
||||
}
|
||||
#endif
|
||||
#ifdef WOLFSSL_DRBG_SHA512
|
||||
if ((rng->drbgType == WC_DRBG_SHA512) && (rng->drbg512 != NULL)) {
|
||||
if (WOLFSSL_ATOMIC_LOAD(((const DRBG_SHA512_internal*)rng->drbg512)->nextSeedLen) != WC_DRBG_NEXT_SEED_READY)
|
||||
return NOT_READY_E;
|
||||
else
|
||||
return ((const DRBG_SHA512_internal *)rng->drbg512)->nextSeedRBGCStratum;
|
||||
}
|
||||
#endif
|
||||
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
#endif /* WC_RNG_HAVE_NEXT_SEED */
|
||||
|
||||
#endif /* WC_RNG_HAVE_RBGC */
|
||||
|
||||
/* Read-only accessor for the DRBG reseed counter. When no DRBG is
|
||||
* instantiated (see wc_RNG_DRBG_Present()) there is no counter; *reseedCtr
|
||||
* is set to 0 -- never due for reseed -- and 0 is returned. */
|
||||
|
|
@ -2167,9 +2208,17 @@ static int _InitRng(WC_RNG* rng, const byte* nonce, word32 nonceSz,
|
|||
#endif /* WC_RNG_HAVE_LOCK */
|
||||
{
|
||||
XMEMSET(rng, 0, sizeof(*rng));
|
||||
rng->isRbgcLeaf = (seedRng != NULL);
|
||||
}
|
||||
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
if (seedRng == NULL)
|
||||
rng->RBGCStratum = 0;
|
||||
else {
|
||||
if (seedRng->RBGCStratum >= WC_MAX_SINT_OF(int))
|
||||
return SEQ_OVERFLOW_E;
|
||||
rng->RBGCStratum = seedRng->RBGCStratum + 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_HEAP_TEST
|
||||
rng->heap = (void*)WOLFSSL_HEAP_TEST;
|
||||
|
|
@ -2980,106 +3029,175 @@ int wc_RNG_lock_clear_extra(WC_RNG* rng, WC_RNG_lock_arg_t extra_bits)
|
|||
#endif /* WC_RNG_HAVE_LOCK */
|
||||
|
||||
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
|
||||
#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK)
|
||||
|
||||
/* Unified mechanics for the four wc_InitRng*RBGC() APIs: instantiate a leaf
|
||||
* DRBG subordinate to root in an SP 800-90C RBG chain, drawing its seed
|
||||
* material from root's generate function in place of the module's seed
|
||||
* source; every other aspect of instantiation -- seed byte accounting,
|
||||
* health testing, nonce handling, failure disposition -- is _InitRng()'s,
|
||||
* identically to wc_InitRngNonce_ex().
|
||||
/* Unified mechanics for the four wc_InitRng*RBGC() APIs: instantiate a child
|
||||
* DRBG subordinate to parent in an SP 800-90C RBG chain, drawing its seed
|
||||
* material from parent's generate function in place of the module's seed
|
||||
* source; every other aspect of instantiation -- seed byte accounting, nonce
|
||||
* handling, failure disposition -- is _InitRng()'s, identically to
|
||||
* wc_InitRngNonce_ex() with the omission of health testing, which is
|
||||
* superfluous when a healthy DRBG generates the seed data.
|
||||
*
|
||||
* Exactly one of new_leaf_stack (caller-provided WC_RNG, uninitialized) and
|
||||
* new_leaf_heap (callee-allocated from root's heap, to be released with
|
||||
* SP 800-90C accounting: the child's claimable security strength is capped by
|
||||
* the parent's, and the child has no formal prediction resistance. The child's
|
||||
* own reseeds default to the module's seed source (the reseed-interval
|
||||
* backstop, wc_RNG_DRBG_Reseed_Now()); wc_RNG_DRBG_ReseedRBGC() reseeds it from
|
||||
* a supplied root instead. In configurations with no DRBG (RDRAND et al.), the
|
||||
* child comes up as _InitRng() dictates for such configurations and the parent
|
||||
* is not consulted.
|
||||
*
|
||||
* Exactly one of new_child_stack (caller-provided WC_RNG, uninitialized) and
|
||||
* new_child_heap (callee-allocated from parent's heap, to be released with
|
||||
* wc_rng_free()) must be non-NULL. The caller must hold exclusive access
|
||||
* to root for the duration of the call, as for all WC_RNG operations; the
|
||||
* spawn debits root's reseed counter by one generate.
|
||||
*
|
||||
* SP 800-90C accounting: the leaf's claimable security strength is capped
|
||||
* by root's, and the leaf has no prediction resistance. The leaf's own
|
||||
* reseeds default to the module's seed source (the reseed-interval
|
||||
* backstop, wc_RNG_DRBG_Reseed_Now()); wc_RNG_DRBG_ReseedRBGC() reseeds it
|
||||
* from root instead. Chains are depth-one BY POLICY, with programmatic
|
||||
* enforcement: a leaf is tagged (WC_RNG.isRbgcLeaf, sticky for the
|
||||
* instance's lifetime even across source reseeds) and is rejected as a
|
||||
* root by every RBGC API. In configurations with no DRBG (RDRAND et al.),
|
||||
* the leaf comes up as _InitRng() dictates for such configurations and
|
||||
* root is not consulted. */
|
||||
static int SpawnRngRBGC(WC_RNG* new_leaf_stack, WC_RNG** new_leaf_heap,
|
||||
WC_RNG* root, byte* nonce, word32 nonceSz)
|
||||
* to parent for the duration of the call, as for all WC_RNG operations; the
|
||||
* spawn debits parent's reseed counter by one generate.
|
||||
*/
|
||||
static int SpawnRngRBGC(WC_RNG* new_child_stack, WC_RNG** new_child_heap,
|
||||
WC_RNG* parent, const byte* nonce, word32 nonceSz,
|
||||
word32 flags)
|
||||
{
|
||||
WC_RNG* leaf = new_leaf_stack;
|
||||
WC_RNG* child = new_child_stack;
|
||||
int ret;
|
||||
#ifdef WC_USE_DEVID
|
||||
int devId = WC_USE_DEVID;
|
||||
#else
|
||||
int devId = INVALID_DEVID;
|
||||
#endif
|
||||
|
||||
if ((root == NULL) ||
|
||||
((new_leaf_stack == NULL) == (new_leaf_heap == NULL)) ||
|
||||
(new_leaf_stack == root))
|
||||
{
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
/* Depth-one chains only, by policy: a leaf is never a root. */
|
||||
if (root->isRbgcLeaf)
|
||||
if (parent == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (new_leaf_heap != NULL) {
|
||||
leaf = (WC_RNG*)XMALLOC(sizeof(WC_RNG), root->heap, DYNAMIC_TYPE_RNG);
|
||||
if (leaf == NULL)
|
||||
if ((new_child_stack == NULL) == (new_child_heap == NULL))
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (new_child_stack == parent)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if ((nonce == NULL) && (nonceSz > 0))
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (new_child_heap != NULL) {
|
||||
*new_child_heap = (WC_RNG*)XMALLOC(sizeof(WC_RNG), parent->heap, DYNAMIC_TYPE_RNG);
|
||||
if (*new_child_heap == NULL)
|
||||
return MEMORY_E;
|
||||
child = *new_child_heap;
|
||||
}
|
||||
|
||||
ret = _InitRng(leaf, nonce, nonceSz, root->heap, devId, root,
|
||||
WC_RNG_INIT_FLAGS_NONE);
|
||||
ret = _InitRng(child, nonce, nonceSz, parent->heap,
|
||||
#if defined(WOLF_CRYPTO_CB)
|
||||
parent->devId,
|
||||
#else
|
||||
INVALID_DEVID,
|
||||
#endif
|
||||
parent, flags);
|
||||
|
||||
if (new_leaf_heap != NULL) {
|
||||
if (new_child_heap != NULL) {
|
||||
if (ret != 0) {
|
||||
XFREE(leaf, root->heap, DYNAMIC_TYPE_RNG);
|
||||
leaf = NULL;
|
||||
XFREE(child, parent->heap, DYNAMIC_TYPE_RNG);
|
||||
*new_child_heap = child = NULL;
|
||||
}
|
||||
*new_leaf_heap = leaf;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wc_InitRngRBGC(WC_RNG* leaf, WC_RNG* root)
|
||||
int wc_InitRngRBGC(WC_RNG* child, WC_RNG* parent, word32 flags)
|
||||
{
|
||||
return SpawnRngRBGC(leaf, NULL, root, NULL, 0);
|
||||
return SpawnRngRBGC(child, NULL, parent, NULL, 0, flags);
|
||||
}
|
||||
|
||||
int wc_InitRngNonceRBGC(WC_RNG* leaf, WC_RNG* root, byte* nonce,
|
||||
word32 nonceSz)
|
||||
int wc_InitRngNonceRBGC(WC_RNG* child, WC_RNG* parent, const byte* nonce,
|
||||
word32 nonceSz, word32 flags)
|
||||
{
|
||||
return SpawnRngRBGC(leaf, NULL, root, nonce, nonceSz);
|
||||
return SpawnRngRBGC(child, NULL, parent, nonce, nonceSz, flags);
|
||||
}
|
||||
|
||||
#ifndef WC_NO_CONSTRUCTORS
|
||||
int wc_InitRngRBGC_New(WC_RNG** leaf, WC_RNG* root)
|
||||
int wc_InitRngRBGC_New(WC_RNG** child, WC_RNG* parent, word32 flags)
|
||||
{
|
||||
return SpawnRngRBGC(NULL, leaf, root, NULL, 0);
|
||||
return SpawnRngRBGC(NULL, child, parent, NULL, 0, flags);
|
||||
}
|
||||
|
||||
int wc_InitRngNonceRBGC_New(WC_RNG** leaf, WC_RNG* root, byte* nonce,
|
||||
word32 nonceSz)
|
||||
int wc_InitRngNonceRBGC_New(WC_RNG** child, WC_RNG* parent, const byte* nonce,
|
||||
word32 nonceSz, word32 flags)
|
||||
{
|
||||
return SpawnRngRBGC(NULL, leaf, root, nonce, nonceSz);
|
||||
return SpawnRngRBGC(NULL, child, parent, nonce, nonceSz, flags);
|
||||
}
|
||||
#endif /* !WC_NO_CONSTRUCTORS */
|
||||
|
||||
/* PollAndReSeed() and wc_RNG_GenerateBlock() form a single-cycle recursion when
|
||||
* a seedRng is passed to PollAndReSeed() by the RBGC chain APIs.
|
||||
* wc_RNG_GenerateBlock() itself never passes a seedRng, ending the cycle
|
||||
* immediately.
|
||||
/* Immediately reseed rng from root's generate output -- the reseed counterpart
|
||||
* of the wc_InitRng*RBGC() spawn. The reseed counter is reset iff the reseed
|
||||
* succeeds and credited. The nonce, if any, rides the same reseed derivation
|
||||
* as (uncredited) additional input. The caller must hold exclusive access to
|
||||
* BOTH rng and root. On credited success, rng is (or remains) a chain RNG:
|
||||
* its current seed period is chain-backed, so RBGCStratum is set, and it is not
|
||||
* usable as a reseed root.
|
||||
*/
|
||||
/* NOLINTNEXTLINE(misc-no-recursion) */
|
||||
static int wc_RNG_DRBG_ReseedRBGC_local(WC_RNG* rng, WC_RNG* root, const byte* nonce,
|
||||
word32 nonceSz, int credited)
|
||||
{
|
||||
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
||||
byte *seed;
|
||||
#else
|
||||
byte seed[SEED_SZ];
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
if ((rng == NULL) || (root == NULL) || (rng == root) ||
|
||||
((nonce == NULL) && (nonceSz > 0)))
|
||||
{
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
ret = rng_lock_required_check(rng);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
||||
seed = rng->newSeed_buf;
|
||||
#endif
|
||||
|
||||
/* Reseed from root only, by policy. */
|
||||
if (root->RBGCStratum > 0)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (rng->status != DRBG_OK)
|
||||
return RNG_FAILURE_E;
|
||||
|
||||
if (! wc_RNG_DRBG_Present(rng)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = wc_RNG_GenerateBlock(root, seed, SEED_SZ);
|
||||
if (ret == 0) {
|
||||
if (credited) {
|
||||
ret = wc_RNG_DRBG_Reseed_Nonce(rng, seed, SEED_SZ, nonce, nonceSz);
|
||||
if (ret == 0) {
|
||||
rng->RBGCStratum = root->RBGCStratum + 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = wc_RNG_DRBG_Reseed_Nonce_Uncredited(rng, seed, SEED_SZ, nonce, nonceSz);
|
||||
}
|
||||
}
|
||||
ForceZero(seed, SEED_SZ);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wc_RNG_DRBG_ReseedRBGC(WC_RNG* rng, WC_RNG* root, const byte* nonce,
|
||||
word32 nonceSz)
|
||||
{
|
||||
return wc_RNG_DRBG_ReseedRBGC_local(rng, root, nonce, nonceSz, 1);
|
||||
}
|
||||
|
||||
int wc_RNG_DRBG_ReseedRBGC_Uncredited(WC_RNG* rng, WC_RNG* root, const byte* nonce,
|
||||
word32 nonceSz)
|
||||
{
|
||||
return wc_RNG_DRBG_ReseedRBGC_local(rng, root, nonce, nonceSz, 0);
|
||||
}
|
||||
|
||||
#endif /* WC_RNG_HAVE_RBGC */
|
||||
|
||||
#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK)
|
||||
|
||||
static int PollAndReSeed(WC_RNG* rng, const byte* additional,
|
||||
word32 additionalSz, WC_RNG* seedRng)
|
||||
word32 additionalSz)
|
||||
{
|
||||
int ret = WC_NO_ERR_TRACE(DRBG_NEED_RESEED);
|
||||
int devId = INVALID_DEVID;
|
||||
|
|
@ -3099,17 +3217,6 @@ static int PollAndReSeed(WC_RNG* rng, const byte* additional,
|
|||
ret = DRBG_SUCCESS;
|
||||
#endif
|
||||
if (ret == DRBG_SUCCESS) {
|
||||
if (seedRng != NULL) {
|
||||
/* RBGC reseed (wc_RNG_DRBG_ReseedRBGC()): draw the seed
|
||||
* material from the parent DRBG's generate function in place
|
||||
* of the module's seed source; all subsequent handling is
|
||||
* identical to the seed-source path. */
|
||||
ret = wc_RNG_GenerateBlock(seedRng, newSeed,
|
||||
SEED_SZ + SEED_BLOCK_SZ);
|
||||
if (ret != 0)
|
||||
ret = DRBG_FAILURE;
|
||||
}
|
||||
else {
|
||||
#ifdef WC_RNG_SEED_CB
|
||||
if (seedCb == NULL) {
|
||||
ret = DRBG_NO_SEED_CB;
|
||||
|
|
@ -3136,7 +3243,6 @@ static int PollAndReSeed(WC_RNG* rng, const byte* additional,
|
|||
ret = DRBG_FAILURE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (ret == DRBG_SUCCESS) {
|
||||
ret = wc_RNG_TestSeed(newSeed, SEED_SZ + SEED_BLOCK_SZ);
|
||||
|
|
@ -3150,6 +3256,11 @@ static int PollAndReSeed(WC_RNG* rng, const byte* additional,
|
|||
if (ret == DRBG_SUCCESS) {
|
||||
ret = Hash_DRBG_Reseed(rng, newSeed + SEED_BLOCK_SZ, SEED_SZ,
|
||||
additional, additionalSz, 1 /* credited */);
|
||||
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
if (ret == 0)
|
||||
rng->RBGCStratum = 0;
|
||||
#endif
|
||||
}
|
||||
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
|
||||
if (newSeed != NULL) {
|
||||
|
|
@ -3208,7 +3319,7 @@ int wc_RNG_DRBG_Reseed_Now(WC_RNG* rng, const byte* nonce, word32 nonceSz)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ret = PollAndReSeed(rng, nonce, nonceSz, NULL);
|
||||
ret = PollAndReSeed(rng, nonce, nonceSz);
|
||||
|
||||
/* Identical outcome mapping to the generate-path reseed. */
|
||||
if (ret == DRBG_SUCCESS) {
|
||||
|
|
@ -3226,62 +3337,6 @@ int wc_RNG_DRBG_Reseed_Now(WC_RNG* rng, const byte* nonce, word32 nonceSz)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Immediately reseed leaf from root's generate output -- the reseed
|
||||
* counterpart of the wc_InitRng*RBGC() spawn, with identical semantics to
|
||||
* wc_RNG_DRBG_Reseed_Now() except for the seed source: the drawn material is
|
||||
* health-tested and applied by the module's own reseed function, the reseed
|
||||
* counter is reset iff the reseed succeeds, and a nonce rides the same
|
||||
* reseed derivation as (uncredited) additional input. The caller must hold
|
||||
* exclusive access to BOTH leaf and root. On success leaf is (or remains) a
|
||||
* chain leaf: its current seed period is chain-backed, so isRbgcLeaf is set
|
||||
* and it is not usable as a root. Depth-one policy applies: root must not
|
||||
* itself be a leaf. */
|
||||
int wc_RNG_DRBG_ReseedRBGC(WC_RNG* leaf, WC_RNG* root, const byte* nonce,
|
||||
word32 nonceSz)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((leaf == NULL) || (root == NULL) || (leaf == root) ||
|
||||
((nonce == NULL) && (nonceSz > 0)))
|
||||
{
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
ret = rng_lock_required_check(leaf);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
/* Depth-one chains only, by policy: a leaf is never a root. */
|
||||
if (root->isRbgcLeaf)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
/* Mirror wc_RNG_GenerateBlock(): only an in-service DRBG may reseed. */
|
||||
if (leaf->status != DRBG_OK)
|
||||
return RNG_FAILURE_E;
|
||||
|
||||
if (! wc_RNG_DRBG_Present(leaf)) {
|
||||
/* No DRBG instantiated -- nothing to reseed (RDRAND et al.). */
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = PollAndReSeed(leaf, nonce, nonceSz, root);
|
||||
|
||||
/* Identical outcome mapping to the generate-path reseed. */
|
||||
if (ret == DRBG_SUCCESS) {
|
||||
leaf->isRbgcLeaf = 1;
|
||||
ret = 0;
|
||||
}
|
||||
else if (ret == WC_NO_ERR_TRACE(DRBG_CONT_FAILURE)) {
|
||||
ret = DRBG_CONT_FIPS_E;
|
||||
leaf->status = DRBG_CONT_FAILED;
|
||||
}
|
||||
else {
|
||||
ret = RNG_FAILURE_E;
|
||||
leaf->status = DRBG_FAILED;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef WC_RNG_HAVE_NEXT_SEED
|
||||
|
||||
/* Banked-next-seed services. _NextSeedGenerate() banks up to n more
|
||||
|
|
@ -3324,26 +3379,42 @@ int wc_RNG_DRBG_ReseedRBGC(WC_RNG* leaf, WC_RNG* root, const byte* nonce,
|
|||
|
||||
/* Locate the aperture members for rng's live DRBG. Returns nonzero when no
|
||||
* DRBG is instantiated (RDRAND et al.). */
|
||||
static int NextSeedPtrs(WC_RNG* rng, byte** seed, wolfSSL_Atomic_Int** len)
|
||||
static WC_INLINE int NextSeedPtrs(WC_RNG* rng, byte** seed, word32 *nextSeedSz, wolfSSL_Atomic_Int** len, int **nextSeedRBGCStratum)
|
||||
{
|
||||
#ifndef NO_SHA256
|
||||
if ((rng->drbgType == WC_DRBG_SHA256) && (rng->drbg != NULL)) {
|
||||
*seed = ((DRBG_internal*)rng->drbg)->nextSeed;
|
||||
*nextSeedSz = (word32)sizeof(((DRBG_internal*)rng->drbg)->nextSeed);
|
||||
*len = &((DRBG_internal*)rng->drbg)->nextSeedLen;
|
||||
if (nextSeedRBGCStratum) {
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
*nextSeedRBGCStratum = &((DRBG_internal*)rng->drbg)->nextSeedRBGCStratum;
|
||||
#else
|
||||
*nextSeedRBGCStratum = NULL;
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef WOLFSSL_DRBG_SHA512
|
||||
if ((rng->drbgType == WC_DRBG_SHA512) && (rng->drbg512 != NULL)) {
|
||||
*seed = ((DRBG_SHA512_internal*)rng->drbg512)->nextSeed;
|
||||
*nextSeedSz = (word32)sizeof(((DRBG_SHA512_internal*)rng->drbg512)->nextSeed);
|
||||
*len = &((DRBG_SHA512_internal*)rng->drbg512)->nextSeedLen;
|
||||
if (nextSeedRBGCStratum) {
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
*nextSeedRBGCStratum = &((DRBG_SHA512_internal*)rng->drbg512)->nextSeedRBGCStratum;
|
||||
#else
|
||||
*nextSeedRBGCStratum = NULL;
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return MISSING_RNG_E;
|
||||
}
|
||||
|
||||
/* Bank up to n more bytes of seed material from the module's seed source into
|
||||
/* Bank up to n more bytes of seed material from a supplied root RNG into
|
||||
* rng's next-seed bank. Callable without owning the instance (the scheduling
|
||||
* daemon's entry point); deliberately independent of rng->status so that
|
||||
* banking can proceed for any instantiated DRBG. n is clamped to the space
|
||||
|
|
@ -3352,67 +3423,138 @@ static int NextSeedPtrs(WC_RNG* rng, byte** seed, wolfSSL_Atomic_Int** len)
|
|||
* published; a failed test consumes the material (use-once) and returns the
|
||||
* test's error, leaving an empty bank for the next cycle. A gather failure
|
||||
* leaves the partial bank intact for retry. */
|
||||
int wc_RNG_DRBG_NextSeedGenerate(WC_RNG* rng, word32 n)
|
||||
static int wc_RNG_DRBG_NextSeedGenerate_local(WC_RNG* rng, WC_RNG *root, word32 n)
|
||||
{
|
||||
byte* seed;
|
||||
wolfSSL_Atomic_Int* lenp;
|
||||
int *nextSeedRBGCStratum_p = NULL;
|
||||
WC_ATOMIC_INT_ARG cur;
|
||||
word32 nextSeedSz;
|
||||
int ret;
|
||||
|
||||
if ((rng == NULL) || (n == 0))
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (NextSeedPtrs(rng, &seed, &lenp) != 0) {
|
||||
/* Note, rng need not be locked -- that's the whole point of the
|
||||
* banked-next-seed aperture protocol.
|
||||
*/
|
||||
|
||||
if (root) {
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
if (root->RBGCStratum > 0)
|
||||
return BAD_FUNC_ARG;
|
||||
ret = rng_lock_required_check(root);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
#else
|
||||
return NOT_COMPILED_IN;
|
||||
#endif
|
||||
}
|
||||
|
||||
ret = NextSeedPtrs(rng, &seed, &nextSeedSz, &lenp, &nextSeedRBGCStratum_p);
|
||||
if (ret != 0) {
|
||||
/* No DRBG instantiated -- nothing to bank (RDRAND et al.). */
|
||||
return BAD_FUNC_ARG;
|
||||
return ret;
|
||||
}
|
||||
|
||||
cur = *lenp;
|
||||
if ((cur < 0) || (cur >= (WC_ATOMIC_INT_ARG)WC_DRBG_NEXT_SEED_LEN)) {
|
||||
if (cur != (WC_ATOMIC_INT_ARG)WC_DRBG_NEXT_SEED_LEN) {
|
||||
if ((cur < 0) || (cur >= (WC_ATOMIC_INT_ARG)nextSeedSz)) {
|
||||
|
||||
if (cur != (WC_ATOMIC_INT_ARG)nextSeedSz) {
|
||||
/* Ready, consuming, or other sentinel -- nothing to do. */
|
||||
return ALREADY_E;
|
||||
return WC_NO_ERR_TRACE(ALREADY_E); /* not an error */
|
||||
}
|
||||
/* Complete but unpublished (interrupted between fill completion and
|
||||
* publication): retry the health test and publication below. */
|
||||
n = 0;
|
||||
}
|
||||
else if (n > WC_DRBG_NEXT_SEED_LEN - (word32)cur) {
|
||||
n = WC_DRBG_NEXT_SEED_LEN - (word32)cur;
|
||||
}
|
||||
|
||||
if (n > 0) {
|
||||
/* wc_GenerateSeed() must be called completely independent of rng, aside
|
||||
* from the memory aperture itself. For safety, we pass a dummy
|
||||
* OS_Seed, which will be ignored by the wc_GenerateSeed() typically
|
||||
* used in conjunction with WC_RNG_HAVE_NEXT_SEED.
|
||||
*/
|
||||
struct OS_Seed os;
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
if (root) {
|
||||
/* If primary seed bytes were carried forward, reset now to avoid
|
||||
* wc_RNG_TestSeed() at completion. */
|
||||
if ((cur > 0) && (*nextSeedRBGCStratum_p == 0)) {
|
||||
cur = 0;
|
||||
WOLFSSL_ATOMIC_STORE(*lenp, cur);
|
||||
}
|
||||
|
||||
/* Named-member init: layout-proof against OS_Seed growing or
|
||||
* reordering members under its several config axes. */
|
||||
XMEMSET(&os, 0, sizeof(os));
|
||||
if (n > nextSeedSz - (word32)cur)
|
||||
n = nextSeedSz - (word32)cur;
|
||||
|
||||
ret = wc_RNG_GenerateBlock(root, seed + cur, n);
|
||||
if (ret != 0) {
|
||||
/* Partial bank preserved -- retry on a later cycle. */
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If RBGC seed bytes were carried forward, make sure we're
|
||||
* pessimistic about the RBGC stratum. */
|
||||
if ((cur == 0) || (*nextSeedRBGCStratum_p < root->RBGCStratum + 1))
|
||||
*nextSeedRBGCStratum_p = root->RBGCStratum + 1;
|
||||
}
|
||||
else
|
||||
#endif /* WC_RNG_HAVE_RBGC */
|
||||
{
|
||||
/* wc_GenerateSeed() must be called completely independent of rng, aside
|
||||
* from the memory aperture itself. For safety, we pass a dummy
|
||||
* OS_Seed, which will be ignored by the wc_GenerateSeed() typically
|
||||
* used in conjunction with WC_RNG_HAVE_NEXT_SEED.
|
||||
*/
|
||||
struct OS_Seed os;
|
||||
|
||||
/* Named-member init: layout-proof against OS_Seed growing or
|
||||
* reordering members under its several config axes. */
|
||||
XMEMSET(&os, 0, sizeof(os));
|
||||
#ifndef USE_WINDOWS_API
|
||||
os.fd = -1;
|
||||
os.fd = -1;
|
||||
#endif
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
os.devId = INVALID_DEVID;
|
||||
os.devId = INVALID_DEVID;
|
||||
#endif
|
||||
|
||||
ret = wc_GenerateSeed(&os, seed + cur, n);
|
||||
if (ret != 0) {
|
||||
/* Partial bank preserved -- retry on a later cycle. */
|
||||
return ret;
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
/* If RBGC seed bytes were carried forward, reset now to avoid
|
||||
* intermixture and force wc_RNG_TestSeed() at completion. */
|
||||
if ((cur > 0) && (*nextSeedRBGCStratum_p > 0)) {
|
||||
cur = 0;
|
||||
WOLFSSL_ATOMIC_STORE(*lenp, cur);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (n > nextSeedSz - (word32)cur)
|
||||
n = nextSeedSz - (word32)cur;
|
||||
|
||||
ret = wc_GenerateSeed(&os, seed + cur, n);
|
||||
if (ret != 0) {
|
||||
/* Partial bank preserved -- retry on a later cycle. */
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
*nextSeedRBGCStratum_p = 0;
|
||||
#endif
|
||||
}
|
||||
cur = wolfSSL_Atomic_Int_AddFetch(lenp, (WC_ATOMIC_INT_ARG)n);
|
||||
|
||||
cur += (int)n;
|
||||
WOLFSSL_ATOMIC_STORE(*lenp, cur);
|
||||
}
|
||||
|
||||
if (cur == (WC_ATOMIC_INT_ARG)WC_DRBG_NEXT_SEED_LEN) {
|
||||
if (cur == (WC_ATOMIC_INT_ARG)nextSeedSz) {
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
/* If RBGC bytes were used for the reseed, then we can skip
|
||||
* wc_RNG_TestSeed(). */
|
||||
if (*nextSeedRBGCStratum_p > 0) {
|
||||
WOLFSSL_ATOMIC_STORE(*lenp, WC_DRBG_NEXT_SEED_READY);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
/* Bank complete: health-test now, in advance of consumption, so
|
||||
* that wc_RNG_DRBG_NextSeedNow() is pure computation. */
|
||||
ret = wc_RNG_TestSeed(seed, WC_DRBG_NEXT_SEED_LEN);
|
||||
ret = wc_RNG_TestSeed(seed, nextSeedSz);
|
||||
if (ret == 0) {
|
||||
WOLFSSL_ATOMIC_STORE(*lenp, WC_DRBG_NEXT_SEED_READY);
|
||||
return 0;
|
||||
}
|
||||
else if (ret == WC_NO_ERR_TRACE(MEMORY_E)) {
|
||||
/* wc_RNG_TestSeed() did nothing with the data -- not
|
||||
|
|
@ -3425,7 +3567,7 @@ int wc_RNG_DRBG_NextSeedGenerate(WC_RNG* rng, word32 n)
|
|||
/* Use-once: a failed test consumes the material. Release
|
||||
* store: the ForceZero() must be visible before the empty
|
||||
* aperture is. */
|
||||
ForceZero(seed, WC_DRBG_NEXT_SEED_LEN);
|
||||
ForceZero(seed, nextSeedSz);
|
||||
WOLFSSL_ATOMIC_STORE(*lenp, WC_DRBG_NEXT_SEED_EMPTY);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -3438,6 +3580,18 @@ int wc_RNG_DRBG_NextSeedGenerate(WC_RNG* rng, word32 n)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
int wc_RNG_DRBG_NextSeedGenerate_RBGC(WC_RNG* rng, WC_RNG *root, word32 n) {
|
||||
if (root == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
return wc_RNG_DRBG_NextSeedGenerate_local(rng, root, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
int wc_RNG_DRBG_NextSeedGenerate(WC_RNG* rng, word32 n) {
|
||||
return wc_RNG_DRBG_NextSeedGenerate_local(rng, NULL, n);
|
||||
}
|
||||
|
||||
/* Report the raw aperture value: a racy snapshot by design. Values in [0, bank
|
||||
* length) count banked bytes; WC_DRBG_NEXT_SEED_READY and
|
||||
* WC_DRBG_NEXT_SEED_CONSUMING indicate a ready or in-consumption bank,
|
||||
|
|
@ -3446,11 +3600,12 @@ int wc_RNG_DRBG_NextSeedCurrent(WC_RNG* rng, WC_ATOMIC_INT_ARG* n)
|
|||
{
|
||||
byte* seed;
|
||||
wolfSSL_Atomic_Int* lenp;
|
||||
word32 nextSeedSz;
|
||||
|
||||
if ((rng == NULL) || (n == NULL))
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (NextSeedPtrs(rng, &seed, &lenp) != 0) {
|
||||
if (NextSeedPtrs(rng, &seed, &nextSeedSz, &lenp, NULL) != 0) {
|
||||
*n = WC_DRBG_NEXT_SEED_EMPTY;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -3459,25 +3614,26 @@ int wc_RNG_DRBG_NextSeedCurrent(WC_RNG* rng, WC_ATOMIC_INT_ARG* n)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Consume a ready next-seed bank in an immediate credited reseed. The
|
||||
* caller must own the instance. Source-free by construction -- the
|
||||
* material was gathered from the module's seed source and health-tested at
|
||||
* bank time -- so consumption is pure computation and safe in atomic
|
||||
* context: the one credited reseed shape with that property. Distinct
|
||||
* protocol results: NOT_READY_E when no bank is ready (nothing consumed),
|
||||
* MISSING_RNG_E when the instance has no DRBG (RDRAND et al.) -- both
|
||||
* deliberately loud, so a direct caller must demonstrate it understands
|
||||
* the instance it holds. (The WC_RNG_BANK_FLAG_CONSUME_NEXT_SEED
|
||||
* checkout arm is return-agnostic by construction and needs neither.)
|
||||
* Use-once: the bank is consumed by the attempt, success or failure. Note
|
||||
* that a banked reseed can never provide SP 800-90 prediction resistance
|
||||
* (the material predates the request by construction);
|
||||
* wc_RNG_DRBG_Reseed_Now() remains the live-gather shape. */
|
||||
/* Consume a ready next-seed bank in an immediate credited reseed. The caller
|
||||
* must own the instance. Source-free by construction -- the material was
|
||||
* gathered from the module's seed source and health-tested at bank time -- so
|
||||
* consumption is pure computation and safe in atomic context: the one credited
|
||||
* primary reseed shape with that property. Distinct protocol results:
|
||||
* NOT_READY_E when no bank is ready (nothing consumed), MISSING_RNG_E when the
|
||||
* instance has no DRBG (RDRAND et al.) -- both deliberately loud, so a direct
|
||||
* caller must demonstrate it understands the instance it holds. (The
|
||||
* WC_RNG_BANK_FLAG_CONSUME_NEXT_SEED checkout arm is return-agnostic by
|
||||
* construction and needs neither.) Use-once: the bank is consumed by the
|
||||
* attempt, success or failure. Note that a banked reseed can never provide SP
|
||||
* 800-90 prediction resistance (the material predates the request by
|
||||
* construction); wc_RNG_DRBG_Reseed_Now() remains the live-gather shape. */
|
||||
int wc_RNG_DRBG_NextSeedNow_Nonce(WC_RNG* rng, const byte* nonce,
|
||||
word32 nonceSz)
|
||||
{
|
||||
byte* seed;
|
||||
wolfSSL_Atomic_Int* lenp;
|
||||
word32 nextSeedSz;
|
||||
int *nextSeedRBGCStratum_p;
|
||||
WC_ATOMIC_INT_ARG expected = WC_DRBG_NEXT_SEED_READY;
|
||||
int ret;
|
||||
|
||||
|
|
@ -3495,7 +3651,7 @@ int wc_RNG_DRBG_NextSeedNow_Nonce(WC_RNG* rng, const byte* nonce,
|
|||
if (rng->status != DRBG_OK)
|
||||
return RNG_FAILURE_E;
|
||||
|
||||
ret = NextSeedPtrs(rng, &seed, &lenp);
|
||||
ret = NextSeedPtrs(rng, &seed, &nextSeedSz, &lenp, &nextSeedRBGCStratum_p);
|
||||
if (ret != 0) {
|
||||
/* No DRBG instantiated -- nothing to reseed (RDRAND et al.). */
|
||||
return ret;
|
||||
|
|
@ -3513,6 +3669,14 @@ int wc_RNG_DRBG_NextSeedNow_Nonce(WC_RNG* rng, const byte* nonce,
|
|||
ret = Hash_DRBG_Reseed(rng, seed + SEED_BLOCK_SZ, SEED_SZ,
|
||||
nonce, nonceSz, 1 /* credited */);
|
||||
|
||||
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
if (ret == 0) {
|
||||
rng->RBGCStratum = *nextSeedRBGCStratum_p;
|
||||
*nextSeedRBGCStratum_p = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Use-once: consumed by the attempt, success or not. Release store:
|
||||
* the ForceZero() must be visible before the empty aperture is. */
|
||||
ForceZero(seed, WC_DRBG_NEXT_SEED_LEN);
|
||||
|
|
@ -3617,7 +3781,7 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
|
|||
#if defined(HAVE_GETPID) && !defined(WOLFSSL_NO_GETPID)
|
||||
if (rng->pid != getpid()) {
|
||||
rng->pid = getpid();
|
||||
ret = PollAndReSeed(rng, NULL, 0, NULL);
|
||||
ret = PollAndReSeed(rng, NULL, 0);
|
||||
if (ret != DRBG_SUCCESS) {
|
||||
rng->status = DRBG_FAILED;
|
||||
return RNG_FAILURE_E;
|
||||
|
|
@ -3630,7 +3794,7 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
|
|||
ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, sz,
|
||||
NULL, 0);
|
||||
if (ret == WC_NO_ERR_TRACE(DRBG_NEED_RESEED)) {
|
||||
ret = PollAndReSeed(rng, NULL, 0, NULL);
|
||||
ret = PollAndReSeed(rng, NULL, 0);
|
||||
if (ret == DRBG_SUCCESS)
|
||||
ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output,
|
||||
sz, NULL, 0);
|
||||
|
|
@ -3643,7 +3807,7 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz)
|
|||
ret = Hash512_DRBG_Generate((DRBG_SHA512_internal *)rng->drbg512,
|
||||
output, sz, NULL, 0);
|
||||
if (ret == WC_NO_ERR_TRACE(DRBG_NEED_RESEED)) {
|
||||
ret = PollAndReSeed(rng, NULL, 0, NULL);
|
||||
ret = PollAndReSeed(rng, NULL, 0);
|
||||
if (ret == DRBG_SUCCESS)
|
||||
ret = Hash512_DRBG_Generate(
|
||||
(DRBG_SHA512_internal *)rng->drbg512, output, sz,
|
||||
|
|
|
|||
|
|
@ -49,6 +49,10 @@ WOLFSSL_API int wc_rng_bank_init_nonce(
|
|||
int i;
|
||||
int ret;
|
||||
int need_reenable_vec = 0;
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
WC_RNG root;
|
||||
int root_inited = 0;
|
||||
#endif
|
||||
|
||||
if ((ctx == NULL) || (n_rngs <= 0))
|
||||
return BAD_FUNC_ARG;
|
||||
|
|
@ -77,8 +81,16 @@ WOLFSSL_API int wc_rng_bank_init_nonce(
|
|||
ret = MEMORY_E;
|
||||
#endif
|
||||
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
if ((ret == 0) && (flags & WC_RNG_BANK_FLAG_INIT_RBGC)) {
|
||||
ret = wc_InitRngNonce_ex(&root, nonce, nonceSz, heap, devId);
|
||||
if (ret == 0)
|
||||
root_inited = 1;
|
||||
}
|
||||
#else
|
||||
(void)nonce;
|
||||
(void)nonceSz;
|
||||
#endif
|
||||
|
||||
if (ret == 0) {
|
||||
XMEMSET(ctx->rngs, 0, sizeof(*ctx->rngs) * (size_t)n_rngs);
|
||||
|
|
@ -98,6 +110,21 @@ WOLFSSL_API int wc_rng_bank_init_nonce(
|
|||
if (flags & WC_RNG_BANK_FLAG_NO_VECTOR_OPS)
|
||||
need_reenable_vec = (DISABLE_VECTOR_REGISTERS() == 0);
|
||||
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
if (flags & WC_RNG_BANK_FLAG_INIT_RBGC) {
|
||||
ret = wc_InitRngNonceRBGC(
|
||||
WC_RNG_BANK_INST_TO_RNG(rng_inst),
|
||||
&root,
|
||||
(byte *)&rng_inst, sizeof(byte *)
|
||||
#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)
|
||||
, WC_RNG_INIT_FLAGS_LOCK_REQUIRED
|
||||
#else
|
||||
, WC_RNG_INIT_FLAGS_NONE
|
||||
#endif
|
||||
);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifdef WC_RNG_INIT_FLAGS_LOCK_REQUIRED
|
||||
ret = wc_InitRngNonce_ex2(
|
||||
|
|
@ -174,6 +201,10 @@ out:
|
|||
if (ret != 0)
|
||||
(void)wc_rng_bank_fini(ctx);
|
||||
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
if (root_inited)
|
||||
wc_FreeRng(&root);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1136,19 +1167,28 @@ WOLFSSL_API int wc_rng_bank_inst_checkin(
|
|||
#define WC_RNG_BANK_INST_OP_DAEMON ((WC_ATOMIC_INT_ARG)1)
|
||||
#define WC_RNG_BANK_INST_OP_REINIT ((WC_ATOMIC_INT_ARG)2)
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_next_seed_generate(
|
||||
static int wc_rng_bank_next_seed_generate_local(
|
||||
struct wc_rng_bank *bank,
|
||||
int inst_offset,
|
||||
word32 n)
|
||||
word32 n,
|
||||
WC_RNG *root)
|
||||
{
|
||||
int ret;
|
||||
WC_ATOMIC_INT_ARG expected = 0;
|
||||
|
||||
if ((bank == NULL) || (! (bank->flags & WC_RNG_BANK_FLAG_INITED)) ||
|
||||
(inst_offset < 0) || (inst_offset >= bank->n_rngs))
|
||||
{
|
||||
if (bank == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
if (! (bank->flags & WC_RNG_BANK_FLAG_INITED))
|
||||
return BAD_FUNC_ARG;
|
||||
if (inst_offset < 0)
|
||||
return BAD_FUNC_ARG;
|
||||
if (inst_offset >= bank->n_rngs)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
#ifndef WC_RNG_HAVE_RBGC
|
||||
if (root != NULL)
|
||||
return NOT_COMPILED_IN;
|
||||
#endif
|
||||
|
||||
if (! wolfSSL_Atomic_Int_CompareExchange(&bank->inst_op_gate, &expected,
|
||||
WC_RNG_BANK_INST_OP_DAEMON))
|
||||
|
|
@ -1158,14 +1198,42 @@ WOLFSSL_API int wc_rng_bank_next_seed_generate(
|
|||
return BUSY_E;
|
||||
}
|
||||
|
||||
ret = wc_RNG_DRBG_NextSeedGenerate(
|
||||
WC_RNG_BANK_INST_TO_RNG(&bank->rngs[inst_offset]), n);
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
if (root != NULL) {
|
||||
ret = wc_RNG_DRBG_NextSeedGenerate_RBGC(
|
||||
WC_RNG_BANK_INST_TO_RNG(&bank->rngs[inst_offset]), root, n);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ret = wc_RNG_DRBG_NextSeedGenerate(
|
||||
WC_RNG_BANK_INST_TO_RNG(&bank->rngs[inst_offset]), n);
|
||||
}
|
||||
|
||||
WOLFSSL_ATOMIC_STORE(bank->inst_op_gate, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_next_seed_generate_rbgc(
|
||||
struct wc_rng_bank *bank,
|
||||
int inst_offset,
|
||||
word32 n,
|
||||
WC_RNG *root)
|
||||
{
|
||||
if (root == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
return wc_rng_bank_next_seed_generate_local(bank, inst_offset, n, root);
|
||||
}
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_next_seed_generate(
|
||||
struct wc_rng_bank *bank,
|
||||
int inst_offset,
|
||||
word32 n)
|
||||
{
|
||||
return wc_rng_bank_next_seed_generate_local(bank, inst_offset, n, NULL);
|
||||
}
|
||||
|
||||
#endif /* WC_RNG_HAVE_NEXT_SEED */
|
||||
|
||||
/* note the rng_inst passed to wc_rng_bank_inst_reinit() must have been obtained
|
||||
|
|
@ -1382,9 +1450,7 @@ WOLFSSL_API int wc_rng_bank_recover_inst(
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK) && \
|
||||
(!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0))
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
/* Unified mechanics for wc_rng_bank_spawn() and wc_rng_bank_spawn_new():
|
||||
* check out -> wc_InitRngNonceRBGC[_New]() -> check in, following the
|
||||
* exactly-one-destination convention of random.c's SpawnRngRBGC(). All
|
||||
|
|
@ -1427,22 +1493,28 @@ static int rng_bank_spawn(
|
|||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
{
|
||||
word32 child_init_flags = WC_RNG_INIT_FLAGS_NONE;
|
||||
if (leaf_stack != NULL) {
|
||||
ret = wc_InitRngNonceRBGC(leaf_stack,
|
||||
WC_RNG_BANK_INST_TO_RNG(rng_inst),
|
||||
nonce, nonceSz);
|
||||
nonce, nonceSz,
|
||||
child_init_flags
|
||||
);
|
||||
}
|
||||
else {
|
||||
#ifndef WC_NO_CONSTRUCTORS
|
||||
ret = wc_InitRngNonceRBGC_New(leaf_heap,
|
||||
WC_RNG_BANK_INST_TO_RNG(rng_inst),
|
||||
nonce, nonceSz);
|
||||
nonce, nonceSz,
|
||||
child_init_flags);
|
||||
#else
|
||||
/* Unreachable: wc_rng_bank_spawn_new() is absent under
|
||||
* WC_NO_CONSTRUCTORS, so leaf_heap is always null here. */
|
||||
ret = BAD_FUNC_ARG;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
checkin_ret = wc_rng_bank_inst_checkin(&rng_inst);
|
||||
if ((checkin_ret != 0) && (ret == 0)) {
|
||||
|
|
@ -1491,8 +1563,7 @@ WOLFSSL_API int wc_rng_bank_spawn_new(
|
|||
preferred_inst_offset, timeout_secs, flags);
|
||||
}
|
||||
#endif /* !WC_NO_CONSTRUCTORS */
|
||||
#endif /* HAVE_HASHDRBG && !CUSTOM_RAND_GENERATE_BLOCK &&
|
||||
* (!HAVE_FIPS || FIPS_VERSION3_GE(7,0,0)) */
|
||||
#endif /* WC_RNG_HAVE_RBGC */
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_seed(struct wc_rng_bank *bank,
|
||||
const byte* seed, word32 seedSz,
|
||||
|
|
|
|||
|
|
@ -943,6 +943,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t noisesrc_test(void);
|
|||
#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK) && \
|
||||
(!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0))
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rng_drbg_svc_test(void);
|
||||
#endif
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rng_drbg_rbgc_test(void);
|
||||
#endif
|
||||
#ifdef WC_RNG_HAVE_NEXT_SEED
|
||||
|
|
@ -2617,6 +2619,8 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\
|
|||
TEST_FAIL("RNGSVC test failed!\n", ret);
|
||||
else
|
||||
TEST_PASS("RNGSVC test passed!\n");
|
||||
#endif
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
if ((ret = rng_drbg_rbgc_test()) != 0)
|
||||
TEST_FAIL("RNGRBGC test failed!\n", ret);
|
||||
else
|
||||
|
|
@ -27927,8 +27931,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void)
|
|||
#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)
|
||||
int svc_present = 0;
|
||||
#endif
|
||||
#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK) && \
|
||||
(!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0))
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
#ifndef WC_NO_CONSTRUCTORS
|
||||
WC_RNG *spawned_rng = NULL;
|
||||
#endif
|
||||
|
|
@ -27946,8 +27949,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void)
|
|||
ERROR_OUT(WC_TEST_RET_ENC_EC(MEMORY_E), out));
|
||||
XMEMSET(rng, 0, sizeof(*rng));
|
||||
#endif
|
||||
#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK) && \
|
||||
(!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0))
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
WC_ALLOC_VAR_EX(leaf_rng, WC_RNG, 1, HEAP_HINT,
|
||||
DYNAMIC_TYPE_TMP_BUFFER,
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(MEMORY_E), out));
|
||||
|
|
@ -28655,25 +28657,22 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void)
|
|||
}
|
||||
#endif /* WC_RNG_HAVE_NEXT_SEED */
|
||||
|
||||
#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK) && \
|
||||
(!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0))
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
/* RBGC spawn: argument and flag contracts */
|
||||
if (wc_rng_bank_spawn(bank, NULL, NULL, 0, 0, 0, 0) !=
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
ret = wc_rng_bank_spawn(bank, NULL, NULL, 0, 0, 0, 0);
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
#ifndef WC_NO_CONSTRUCTORS
|
||||
if (wc_rng_bank_spawn_new(bank, NULL, NULL, 0, 0, 0, 0) !=
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
ret = wc_rng_bank_spawn_new(bank, NULL, NULL, 0, 0, 0, 0);
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
#endif
|
||||
if (wc_rng_bank_spawn(bank, leaf_rng, NULL, 0, 0, 0,
|
||||
WC_RNG_BANK_FLAG_SEED_UNCREDITED) !=
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
if (wc_rng_bank_spawn(bank, leaf_rng, NULL, 0, 0, 0,
|
||||
WC_RNG_BANK_FLAG_FOR_RECOVERY) !=
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
ret = wc_rng_bank_spawn(bank, leaf_rng, NULL, 0, 0, 0, WC_RNG_BANK_FLAG_SEED_UNCREDITED);
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
ret = wc_rng_bank_spawn(bank, leaf_rng, NULL, 0, 0, 0, WC_RNG_BANK_FLAG_FOR_RECOVERY);
|
||||
if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
||||
/* nonce-bearing stack spawn: the leaf is a tagged chain leaf,
|
||||
* generates, and is torn down independently of the bank */
|
||||
|
|
@ -28682,8 +28681,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void)
|
|||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
leaf_rng_inited = 1;
|
||||
if (wc_RNG_DRBG_IsRBGCLeaf(leaf_rng) != 1)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)
|
||||
ret = wc_RNG_DRBG_GetRBGCStratum(leaf_rng);
|
||||
if (ret != 1)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_I(ret), out);
|
||||
#endif
|
||||
ret = wc_RNG_GenerateBlock(leaf_rng, outbuf1, sizeof(outbuf1));
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
|
|
@ -28697,16 +28699,59 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void)
|
|||
ret = wc_rng_bank_spawn_new(bank, &spawned_rng, NULL, 0, 1, 0, 0);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
if ((spawned_rng == NULL) || (wc_RNG_DRBG_IsRBGCLeaf(spawned_rng) != 1))
|
||||
if (spawned_rng == NULL)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)
|
||||
ret = wc_RNG_DRBG_GetRBGCStratum(spawned_rng);
|
||||
if (ret != 1)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_I(ret), out);
|
||||
#endif
|
||||
ret = wc_RNG_GenerateBlock(spawned_rng, outbuf1, sizeof(outbuf1));
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
wc_rng_free(spawned_rng);
|
||||
spawned_rng = NULL;
|
||||
#endif /* !WC_NO_CONSTRUCTORS */
|
||||
#endif /* HAVE_HASHDRBG && !CUSTOM_RAND_GENERATE_BLOCK &&
|
||||
* (!HAVE_FIPS || FIPS_VERSION3_GE(7,0,0)) */
|
||||
|
||||
/* PR spawn: a fresh credited primary reseed of the parent instance
|
||||
* immediately before the child's seed draw (the SP 800-90C Sec. 4.1.1
|
||||
* pattern). The child is stratum 1; the parent instance's counter
|
||||
* shows reseed-then-one-draw. */
|
||||
ret = wc_rng_bank_spawn(bank, leaf_rng, NULL, 0, 0, 10,
|
||||
WC_RNG_BANK_FLAG_PREDICTION_RESISTANCE |
|
||||
WC_RNG_BANK_FLAG_CAN_WAIT);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
leaf_rng_inited = 1;
|
||||
#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)
|
||||
ret = wc_RNG_DRBG_GetRBGCStratum(leaf_rng);
|
||||
if (ret != 1)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_I(ret), out);
|
||||
#endif
|
||||
ret = wc_RNG_GenerateBlock(leaf_rng, outbuf1, sizeof(outbuf1));
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
ret = wc_FreeRng(leaf_rng);
|
||||
leaf_rng_inited = 0;
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)
|
||||
if (svc_present) {
|
||||
wc_drbg_reseed_ctr_t ns_ctr;
|
||||
ret = wc_rng_bank_checkout(bank, &rng_inst, 0, 10,
|
||||
WC_RNG_BANK_FLAG_NONE);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
ret = wc_RNG_DRBG_GetReseedCtr(
|
||||
WC_RNG_BANK_INST_TO_RNG(rng_inst), &ns_ctr);
|
||||
if ((ret != 0) || (ns_ctr != 2))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
ret = wc_rng_bank_inst_checkin(&rng_inst);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
}
|
||||
#endif /* !HAVE_FIPS || FIPS_VERSION3_GE(7,0,0) */
|
||||
#endif /* WC_RNG_HAVE_RBGC */
|
||||
|
||||
/* WC_RNG_BANK_FLAG_PREDICTION_RESISTANCE checkout contracts.
|
||||
* Per-call PR demands CAN_WAIT (the fresh gather may block) and
|
||||
|
|
@ -28883,8 +28928,7 @@ out:
|
|||
ret = WC_TEST_RET_ENC_NC;
|
||||
#endif /* !WC_RNG_BANK_STATIC */
|
||||
|
||||
#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK) && \
|
||||
(!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0))
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
#ifndef WC_NO_CONSTRUCTORS
|
||||
if (spawned_rng != NULL)
|
||||
wc_rng_free(spawned_rng);
|
||||
|
|
@ -28895,8 +28939,7 @@ out:
|
|||
ret = WC_TEST_RET_ENC_EC(cleanup_ret);
|
||||
}
|
||||
WC_FREE_VAR_EX(leaf_rng, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#endif /* HAVE_HASHDRBG && !CUSTOM_RAND_GENERATE_BLOCK &&
|
||||
* (!HAVE_FIPS || FIPS_VERSION3_GE(7,0,0)) */
|
||||
#endif /* WC_RNG_HAVE_RBGC */
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -28938,8 +28981,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rng_drbg_svc_test(void)
|
|||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
if (wc_RNG_DRBG_Present(NULL) != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
if (wc_RNG_DRBG_IsRBGCLeaf(NULL) != 0)
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
if (wc_RNG_DRBG_GetRBGCStratum(NULL) != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
#endif
|
||||
if (wc_RNG_DRBG_GetReseedCtr(NULL, &c1) != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
|
||||
|
|
@ -28953,8 +28998,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rng_drbg_svc_test(void)
|
|||
if (wc_RNG_DRBG_GetReseedCtr(root, NULL) !=
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
if (wc_RNG_DRBG_IsRBGCLeaf(root) != 0)
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
if (wc_RNG_DRBG_GetRBGCStratum(root) != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
#endif
|
||||
|
||||
present = wc_RNG_DRBG_Present(root);
|
||||
|
||||
|
|
@ -29141,8 +29188,15 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
#endif /* HAVE_HASHDRBG && !CUSTOM_RAND_GENERATE_BLOCK && */
|
||||
/* (!HAVE_FIPS || FIPS_VERSION3_GE(7,0,0)) */
|
||||
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
|
||||
#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)
|
||||
|
||||
/* Coverage for the SP 800-90C RBGC (RBG chain) APIs: spawn, reseed-from-
|
||||
* root, the leaf tag and accessor, and the sticky depth-one enforcement.
|
||||
* root, the leaf tag and accessor, and the sticky stratum-one enforcement.
|
||||
* DRBG-internal observations are gated at runtime on wc_RNG_DRBG_Present(),
|
||||
* so the test also passes on RDRAND-shaped instantiations, where the RBGC
|
||||
* APIs are exercised in their degenerate arms. */
|
||||
|
|
@ -29175,15 +29229,19 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rng_drbg_rbgc_test(void)
|
|||
present = wc_RNG_DRBG_Present(&root);
|
||||
|
||||
/* spawn argument contracts */
|
||||
if (wc_InitRngRBGC(NULL, &root) != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
if (wc_InitRngRBGC(&leaf, NULL) != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
if (wc_InitRngRBGC(&root, &root) != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
api_ret = wc_InitRngRBGC(NULL, &root, WC_RNG_INIT_FLAGS_NONE);
|
||||
if (api_ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
api_ret = wc_InitRngRBGC(&leaf, NULL, WC_RNG_INIT_FLAGS_NONE);
|
||||
if (api_ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
api_ret = wc_InitRngRBGC(&root, &root, WC_RNG_INIT_FLAGS_NONE);
|
||||
if (api_ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
#ifndef WC_NO_CONSTRUCTORS
|
||||
if (wc_InitRngRBGC_New(NULL, &root) != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
api_ret = wc_InitRngRBGC_New(NULL, &root, WC_RNG_INIT_FLAGS_NONE);
|
||||
if (api_ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
#endif
|
||||
|
||||
/* spawn a leaf; the spawn debits root's counter; the leaf is tagged */
|
||||
|
|
@ -29192,7 +29250,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rng_drbg_rbgc_test(void)
|
|||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
}
|
||||
api_ret = wc_InitRngRBGC(&leaf, &root);
|
||||
api_ret = wc_InitRngRBGC(&leaf, &root, WC_RNG_INIT_FLAGS_NONE);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
leaf_inited = 1;
|
||||
|
|
@ -29200,27 +29258,25 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rng_drbg_rbgc_test(void)
|
|||
api_ret = wc_RNG_DRBG_GetReseedCtr(&root, &c2);
|
||||
if ((api_ret != 0) || (c2 <= c1))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
/* the spawn draw is one fully-served generate on the parent */
|
||||
}
|
||||
if (wc_RNG_DRBG_IsRBGCLeaf(&leaf) != 1)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
if (wc_RNG_DRBG_IsRBGCLeaf(&root) != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
api_ret = wc_RNG_DRBG_GetRBGCStratum(&leaf);
|
||||
if (api_ret != 1)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_I(api_ret), out);
|
||||
api_ret = wc_RNG_DRBG_GetRBGCStratum(&root);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_I(api_ret), out);
|
||||
api_ret = wc_RNG_GenerateBlock(&leaf, buf, sizeof(buf));
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
if (present) {
|
||||
/* chain-provenance accounting: bytes generated at stratum 1 count
|
||||
* in both the total and the RBGC ledgers */
|
||||
}
|
||||
|
||||
/* depth-one enforcement: a leaf is never a root */
|
||||
if (wc_InitRngRBGC(&extra, &leaf) != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
#ifndef WC_NO_CONSTRUCTORS
|
||||
if (wc_InitRngRBGC_New(&pleaf, &leaf) != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
if (pleaf != NULL)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
#endif
|
||||
if (wc_RNG_DRBG_ReseedRBGC(&root, &leaf, NULL, 0) !=
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
api_ret = wc_RNG_DRBG_ReseedRBGC(&root, &leaf, NULL, 0);
|
||||
if (api_ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
|
||||
/* reseed-from-root, without and with a nonce; counter resets */
|
||||
api_ret = wc_RNG_DRBG_ReseedRBGC(&leaf, &root, NULL, 0);
|
||||
|
|
@ -29233,26 +29289,33 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rng_drbg_rbgc_test(void)
|
|||
api_ret = wc_RNG_DRBG_GetReseedCtr(&leaf, &c1);
|
||||
if ((api_ret != 0) || (c1 != 1))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
/* target: two credited chain reseeds; source: two fully-served
|
||||
* seed draws */
|
||||
}
|
||||
if (wc_RNG_DRBG_ReseedRBGC(&leaf, &leaf, NULL, 0) !=
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
if (wc_RNG_DRBG_ReseedRBGC(NULL, &root, NULL, 0) !=
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
if (wc_RNG_DRBG_ReseedRBGC(&leaf, &root, NULL, 7) !=
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
api_ret = wc_RNG_DRBG_ReseedRBGC(&leaf, &leaf, NULL, 0);
|
||||
if (api_ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
api_ret = wc_RNG_DRBG_ReseedRBGC(NULL, &root, NULL, 0);
|
||||
if (api_ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
api_ret = wc_RNG_DRBG_ReseedRBGC(&leaf, &root, NULL, 7);
|
||||
if (api_ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
|
||||
/* the leaf tag is sticky across a source reseed */
|
||||
/* The RBGC stratum is reset to zero by a primary source reseed. */
|
||||
api_ret = wc_RNG_DRBG_ScheduleReseed(&leaf);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
api_ret = wc_RNG_GenerateBlock(&leaf, buf, sizeof(buf));
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
if (wc_RNG_DRBG_IsRBGCLeaf(&leaf) != 1)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
ret = wc_RNG_DRBG_GetRBGCStratum(&leaf);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_I(ret), out);
|
||||
if (present) {
|
||||
/* the primary reseed precedes the byte production, so the served
|
||||
* bytes are not chain-provenance */
|
||||
}
|
||||
|
||||
#if !defined(WC_NO_CONSTRUCTORS)
|
||||
/* chain-reseeding a source-born instance demotes it, one-way */
|
||||
|
|
@ -29260,34 +29323,42 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rng_drbg_rbgc_test(void)
|
|||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
extra_inited = 1;
|
||||
if (wc_RNG_DRBG_IsRBGCLeaf(&extra) != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
api_ret = wc_RNG_DRBG_GetRBGCStratum(&extra);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_I(api_ret), out);
|
||||
if (present) {
|
||||
api_ret = wc_RNG_DRBG_ReseedRBGC(&extra, &root, NULL, 0);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
if (wc_RNG_DRBG_IsRBGCLeaf(&extra) != 1)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
if (wc_InitRngRBGC_New(&pleaf, &extra) !=
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
api_ret = wc_RNG_DRBG_GetRBGCStratum(&extra);
|
||||
if (api_ret != 1)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_I(api_ret), out);
|
||||
/* long-chained init is allowed, only chained reseed is forbidden. */
|
||||
ret = wc_InitRngRBGC_New(&pleaf, &extra, WC_RNG_INIT_FLAGS_NONE);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
if ((pleaf == NULL) || (wc_RNG_DRBG_GetRBGCStratum(pleaf) != 2))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
wc_rng_free(pleaf);
|
||||
pleaf = NULL;
|
||||
}
|
||||
|
||||
/* heap-allocated leaves, without and with a nonce */
|
||||
api_ret = wc_InitRngRBGC_New(&pleaf, &root);
|
||||
api_ret = wc_InitRngRBGC_New(&pleaf, &root, WC_RNG_INIT_FLAGS_NONE);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
if ((pleaf == NULL) || (wc_RNG_DRBG_IsRBGCLeaf(pleaf) != 1))
|
||||
if ((pleaf == NULL) || (wc_RNG_DRBG_GetRBGCStratum(pleaf) != 1))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
api_ret = wc_RNG_GenerateBlock(pleaf, buf, sizeof(buf));
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
wc_rng_free(pleaf);
|
||||
pleaf = NULL;
|
||||
api_ret = wc_InitRngNonceRBGC_New(&pleaf, &root, matter, 16);
|
||||
api_ret = wc_InitRngNonceRBGC_New(&pleaf, &root, matter, 16,
|
||||
WC_RNG_INIT_FLAGS_NONE);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
if ((pleaf == NULL) || (wc_RNG_DRBG_IsRBGCLeaf(pleaf) != 1))
|
||||
if ((pleaf == NULL) || (wc_RNG_DRBG_GetRBGCStratum(pleaf) != 1))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
wc_rng_free(pleaf);
|
||||
pleaf = NULL;
|
||||
|
|
@ -29298,12 +29369,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rng_drbg_rbgc_test(void)
|
|||
leaf_inited = 0;
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
api_ret = wc_InitRngNonceRBGC(&leaf, &root, matter, 16);
|
||||
api_ret = wc_InitRngNonceRBGC(&leaf, &root, matter, 16,
|
||||
WC_RNG_INIT_FLAGS_NONE);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
leaf_inited = 1;
|
||||
if (wc_RNG_DRBG_IsRBGCLeaf(&leaf) != 1)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
api_ret = wc_RNG_DRBG_GetRBGCStratum(&leaf);
|
||||
if (api_ret != 1)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_I(api_ret), out);
|
||||
|
||||
out:
|
||||
|
||||
|
|
@ -29330,8 +29403,193 @@ out:
|
|||
|
||||
return ret;
|
||||
}
|
||||
#endif /* HAVE_HASHDRBG && !CUSTOM_RAND_GENERATE_BLOCK &&
|
||||
* (!HAVE_FIPS || FIPS_VERSION3_GE(7,0,0)) */
|
||||
|
||||
#else /* HAVE_FIPS && FIPS_VERSION3_LT(7,0,0) */
|
||||
|
||||
#ifndef WC_RNG_BANK_SUPPORT
|
||||
/* needed for compat setup */
|
||||
#define WC_RNG_BANK_SUPPORT
|
||||
#include <wolfssl/wolfcrypt/rng_bank.h>
|
||||
#undef WC_RNG_BANK_SUPPORT
|
||||
#endif
|
||||
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rng_drbg_rbgc_test(void)
|
||||
{
|
||||
wc_test_ret_t ret = 0;
|
||||
int api_ret;
|
||||
int present;
|
||||
int root_inited = 0;
|
||||
int leaf_inited = 0;
|
||||
int extra_inited = 0;
|
||||
WC_RNG root;
|
||||
WC_RNG leaf;
|
||||
WC_RNG extra;
|
||||
WC_RNG* pleaf = NULL;
|
||||
wc_drbg_reseed_ctr_t c1 = 0;
|
||||
wc_drbg_reseed_ctr_t c2 = 0;
|
||||
byte buf[32];
|
||||
byte matter[32];
|
||||
|
||||
WOLFSSL_ENTER("rng_drbg_rbgc_test");
|
||||
|
||||
XMEMSET(matter, 0xa5, sizeof(matter));
|
||||
|
||||
api_ret = wc_InitRng(&root);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
root_inited = 1;
|
||||
|
||||
present = wc_RNG_DRBG_Present(&root);
|
||||
|
||||
/* spawn argument contracts */
|
||||
if (wc_InitRngRBGC(NULL, &root, WC_RNG_INIT_FLAGS_NONE) !=
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
if (wc_InitRngRBGC(&leaf, NULL, WC_RNG_INIT_FLAGS_NONE) !=
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
if (wc_InitRngRBGC(&root, &root, WC_RNG_INIT_FLAGS_NONE) !=
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
#ifndef WC_NO_CONSTRUCTORS
|
||||
if (wc_InitRngRBGC_New(NULL, &root, WC_RNG_INIT_FLAGS_NONE) !=
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
#endif
|
||||
|
||||
/* spawn a leaf; the spawn debits root's counter; the leaf is tagged */
|
||||
if (present) {
|
||||
api_ret = wc_RNG_DRBG_GetReseedCtr(&root, &c1);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
}
|
||||
api_ret = wc_InitRngRBGC(&leaf, &root, WC_RNG_INIT_FLAGS_NONE);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
leaf_inited = 1;
|
||||
if (present) {
|
||||
api_ret = wc_RNG_DRBG_GetReseedCtr(&root, &c2);
|
||||
if ((api_ret != 0) || (c2 <= c1))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
}
|
||||
api_ret = wc_RNG_GenerateBlock(&leaf, buf, sizeof(buf));
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
|
||||
#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)
|
||||
if (wc_RNG_DRBG_ReseedRBGC(&root, &leaf) !=
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
#endif
|
||||
|
||||
/* reseed-from-root, without and with a nonce; counter resets */
|
||||
api_ret = wc_RNG_DRBG_ReseedRBGC(&leaf, &root);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
api_ret = wc_RNG_DRBG_ReseedRBGC(&leaf, &root);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
if (present) {
|
||||
api_ret = wc_RNG_DRBG_GetReseedCtr(&leaf, &c1);
|
||||
if ((api_ret != 0) || (c1 != 1))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
}
|
||||
if (wc_RNG_DRBG_ReseedRBGC(&leaf, &leaf) !=
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
if (wc_RNG_DRBG_ReseedRBGC(NULL, &root) !=
|
||||
WC_NO_ERR_TRACE(BAD_FUNC_ARG))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
|
||||
/* The RGBC stratum is reset to zero by a primary source reseed. */
|
||||
api_ret = wc_RNG_DRBG_ScheduleReseed(&leaf);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
api_ret = wc_RNG_GenerateBlock(&leaf, buf, sizeof(buf));
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
|
||||
#if !defined(WC_NO_CONSTRUCTORS)
|
||||
/* chain-reseeding a source-born instance demotes it, one-way */
|
||||
api_ret = wc_InitRng(&extra);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
extra_inited = 1;
|
||||
if (present) {
|
||||
api_ret = wc_RNG_DRBG_ReseedRBGC(&extra, &root);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
/* long-chained init is allowed, only chained reseed is forbidden. */
|
||||
ret = wc_InitRngRBGC_New(&pleaf, &extra, WC_RNG_INIT_FLAGS_NONE);
|
||||
if (ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out);
|
||||
if (pleaf == NULL)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
wc_rng_free(pleaf);
|
||||
pleaf = NULL;
|
||||
}
|
||||
|
||||
/* heap-allocated leaves, without and with a nonce */
|
||||
api_ret = wc_InitRngRBGC_New(&pleaf, &root, WC_RNG_INIT_FLAGS_NONE);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
if (pleaf == NULL)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
api_ret = wc_RNG_GenerateBlock(pleaf, buf, sizeof(buf));
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
wc_rng_free(pleaf);
|
||||
pleaf = NULL;
|
||||
api_ret = wc_InitRngNonceRBGC_New(&pleaf, &root, matter, 16,
|
||||
WC_RNG_INIT_FLAGS_NONE);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
if (pleaf == NULL)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
wc_rng_free(pleaf);
|
||||
pleaf = NULL;
|
||||
#endif /* !WC_NO_CONSTRUCTORS */
|
||||
|
||||
/* nonce-bearing stack spawn */
|
||||
api_ret = wc_FreeRng(&leaf);
|
||||
leaf_inited = 0;
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
api_ret = wc_InitRngNonceRBGC(&leaf, &root, matter, 16,
|
||||
WC_RNG_INIT_FLAGS_NONE);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
leaf_inited = 1;
|
||||
|
||||
out:
|
||||
|
||||
{
|
||||
int cleanup_ret;
|
||||
if (pleaf != NULL)
|
||||
wc_rng_free(pleaf);
|
||||
if (leaf_inited) {
|
||||
cleanup_ret = wc_FreeRng(&leaf);
|
||||
if ((cleanup_ret != 0) && (ret == 0))
|
||||
ret = WC_TEST_RET_ENC_EC(cleanup_ret);
|
||||
}
|
||||
if (extra_inited) {
|
||||
cleanup_ret = wc_FreeRng(&extra);
|
||||
if ((cleanup_ret != 0) && (ret == 0))
|
||||
ret = WC_TEST_RET_ENC_EC(cleanup_ret);
|
||||
}
|
||||
if (root_inited) {
|
||||
cleanup_ret = wc_FreeRng(&root);
|
||||
if ((cleanup_ret != 0) && (ret == 0))
|
||||
ret = WC_TEST_RET_ENC_EC(cleanup_ret);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* HAVE_FIPS && FIPS_VERSION3_LT(7,0,0) */
|
||||
|
||||
#endif /* WC_RNG_HAVE_RBGC */
|
||||
|
||||
#ifdef WC_RNG_HAVE_NEXT_SEED
|
||||
/* Coverage for the banked-next-seed facility: the aperture protocol
|
||||
|
|
@ -29471,6 +29729,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rng_drbg_nextseed_test(void)
|
|||
api_ret = wc_RNG_DRBG_GetReseedCtr(root, &c1);
|
||||
if ((api_ret != 0) || (c1 != 1))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, out);
|
||||
/* redemption of a primary-provenance bank: credited, counted as a
|
||||
* primary redemption */
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
#endif
|
||||
api_ret = wc_RNG_DRBG_NextSeedCurrent(root, &cur);
|
||||
if (api_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(api_ret), out);
|
||||
|
|
|
|||
|
|
@ -262,9 +262,9 @@ extern WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void);
|
|||
#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK) && \
|
||||
(!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0))
|
||||
extern WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rng_drbg_svc_test(void);
|
||||
#endif
|
||||
extern WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rng_drbg_rbgc_test(void);
|
||||
extern WOLFSSL_TEST_SUBROUTINE wc_test_ret_t rng_drbg_nextseed_test(void);
|
||||
#endif
|
||||
#endif /* WC_NO_RNG */
|
||||
extern WOLFSSL_TEST_SUBROUTINE wc_test_ret_t pwdbased_test(void);
|
||||
#if defined(USE_CERT_BUFFERS_2048) && \
|
||||
|
|
|
|||
|
|
@ -43,6 +43,16 @@
|
|||
WOLFSSL_LOCAL int wolfCrypt_FIPS_DRBG_sanity(void);
|
||||
#endif
|
||||
|
||||
#ifndef WC_RNG_NO_RBGC
|
||||
#if !defined(WC_RNG_HAVE_RBGC) && \
|
||||
defined(HAVE_HASHDRBG) && \
|
||||
!defined(CUSTOM_RAND_GENERATE_BLOCK)
|
||||
#define WC_RNG_HAVE_RBGC
|
||||
#endif
|
||||
#else
|
||||
#undef WC_RNG_HAVE_RBGC
|
||||
#endif
|
||||
|
||||
/* _FULL_MUTEX is opt-in, and depends on WC_RNG_HAVE_LOCK. */
|
||||
#ifdef WC_RNG_NO_LOCK_FULL_MUTEX
|
||||
#undef WC_RNG_HAVE_LOCK_FULL_MUTEX
|
||||
|
|
@ -356,6 +366,9 @@ struct DRBG_internal {
|
|||
#ifdef WC_RNG_HAVE_NEXT_SEED
|
||||
byte nextSeed[WC_DRBG_NEXT_SEED_LEN];
|
||||
WC_DRBG_nextSeedLen_t nextSeedLen;
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
int nextSeedRBGCStratum;
|
||||
#endif
|
||||
#endif
|
||||
void* heap;
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
|
||||
|
|
@ -381,6 +394,9 @@ struct DRBG_SHA512_internal {
|
|||
#ifdef WC_RNG_HAVE_NEXT_SEED
|
||||
byte nextSeed[WC_DRBG_NEXT_SEED_LEN];
|
||||
WC_DRBG_nextSeedLen_t nextSeedLen;
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
int nextSeedRBGCStratum;
|
||||
#endif
|
||||
#endif
|
||||
void* heap;
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB)
|
||||
|
|
@ -412,6 +428,7 @@ enum wc_RngHealthState {
|
|||
};
|
||||
|
||||
#define WC_RNG_FLAG_NONE 0
|
||||
#define WC_RNG_FLAG_RBGC_NEXT_SEED (1U << 0)
|
||||
#define WC_RNG_FLAG_FULL_MUTEX (1U << 1)
|
||||
#define WC_RNG_FLAG_BANKREF (1U << 2)
|
||||
|
||||
|
|
@ -422,11 +439,9 @@ struct WC_RNG {
|
|||
void* heap;
|
||||
byte status;
|
||||
word32 flags;
|
||||
/* Set when this instance was seeded from another DRBG's output
|
||||
* (wc_InitRng*RBGC(), wc_RNG_DRBG_ReseedRBGC()) -- an SP 800-90C chain
|
||||
* leaf. Sticky by policy: a leaf is never usable as a chain root, even
|
||||
* after a subsequent reseed from the module's seed source. */
|
||||
byte isRbgcLeaf;
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
int RBGCStratum;
|
||||
#endif
|
||||
#ifdef WC_RNG_HAVE_LOCK
|
||||
WC_RNG_lock_t lock;
|
||||
#ifdef WC_RNG_HAVE_LOCK_FULL_MUTEX
|
||||
|
|
@ -700,7 +715,12 @@ WOLFSSL_API int wc_RNG_DRBG_Present(const WC_RNG* rng);
|
|||
#endif
|
||||
#endif
|
||||
|
||||
WOLFSSL_API int wc_RNG_DRBG_IsRBGCLeaf(const WC_RNG* rng);
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
WOLFSSL_API int wc_RNG_DRBG_GetRBGCStratum(const WC_RNG* rng);
|
||||
#ifdef WC_RNG_HAVE_NEXT_SEED
|
||||
WOLFSSL_API int wc_RNG_DRBG_GetNextSeedRBGCStratum(const WC_RNG* rng);
|
||||
#endif
|
||||
#endif /* WC_RNG_HAVE_RBGC */
|
||||
WOLFSSL_API int wc_RNG_DRBG_GetReseedCtr(const WC_RNG* rng,
|
||||
wc_drbg_reseed_ctr_t* reseedCtr);
|
||||
WOLFSSL_API int wc_RNG_DRBG_ScheduleReseed(WC_RNG* rng);
|
||||
|
|
@ -813,21 +833,33 @@ WOLFSSL_API int wc_RNG_DRBG_Present(const WC_RNG* rng);
|
|||
|
||||
#endif /* HAVE_HASHDRBG */
|
||||
|
||||
#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK)
|
||||
/* SP 800-90C RBG-chain spawn: instantiate leaf as a subordinate DRBG
|
||||
* seeded from root's generate output. The _New variants allocate the
|
||||
* leaf from root's heap; release those with wc_rng_free(). */
|
||||
WOLFSSL_API int wc_InitRngRBGC(WC_RNG* leaf, WC_RNG* root);
|
||||
WOLFSSL_API int wc_InitRngNonceRBGC(WC_RNG* leaf, WC_RNG* root,
|
||||
byte* nonce, word32 nonceSz);
|
||||
#ifndef WC_NO_CONSTRUCTORS
|
||||
WOLFSSL_API int wc_InitRngRBGC_New(WC_RNG** leaf, WC_RNG* root);
|
||||
WOLFSSL_API int wc_InitRngNonceRBGC_New(WC_RNG** leaf, WC_RNG* root,
|
||||
byte* nonce, word32 nonceSz);
|
||||
#endif /* !WC_NO_CONSTRUCTORS */
|
||||
WOLFSSL_API int wc_RNG_DRBG_ReseedRBGC(WC_RNG* leaf, WC_RNG* root,
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
/* SP 800-90C RBG-chain spawn: instantiate child as a subordinate DRBG
|
||||
* seeded from parent's generate output. The _New variants allocate the
|
||||
* child from parent's heap; release them with ordinary wc_rng_free(). */
|
||||
WOLFSSL_API int wc_InitRngRBGC(WC_RNG* child, WC_RNG* parent, word32 flags);
|
||||
WOLFSSL_API int wc_InitRngNonceRBGC(WC_RNG* child, WC_RNG* parent,
|
||||
const byte* nonce, word32 nonceSz,
|
||||
word32 flags);
|
||||
#ifndef WC_NO_CONSTRUCTORS
|
||||
/* flags are per-object (WC_RNG_INIT_FLAGS_*), deliberately NOT
|
||||
* inherited from the parent: a child's lock policy is its own. */
|
||||
WOLFSSL_API int wc_InitRngRBGC_New(WC_RNG** child, WC_RNG* parent,
|
||||
word32 flags);
|
||||
WOLFSSL_API int wc_InitRngNonceRBGC_New(WC_RNG** child, WC_RNG* parent,
|
||||
const byte* nonce, word32 nonceSz,
|
||||
word32 flags);
|
||||
#endif /* !WC_NO_CONSTRUCTORS */
|
||||
/* Note, only a root RNG -- stratum 0, i.e. primary-seeded -- is permitted
|
||||
* to generate reseed bytes (wolfCrypt policy; stricter than SP 800-90C
|
||||
* 7.1.2.2, which also permits parent reseed). */
|
||||
WOLFSSL_API int wc_RNG_DRBG_ReseedRBGC(WC_RNG* rng, WC_RNG* root,
|
||||
const byte* nonce, word32 nonceSz);
|
||||
#endif /* HAVE_HASHDRBG && !CUSTOM_RAND_GENERATE_BLOCK */
|
||||
WOLFSSL_API int wc_RNG_DRBG_ReseedRBGC_Uncredited(WC_RNG* rng,
|
||||
WC_RNG* root,
|
||||
const byte* nonce,
|
||||
word32 nonceSz);
|
||||
#endif /* WC_RNG_HAVE_RBGC */
|
||||
|
||||
#ifdef WC_RNG_HAVE_NEXT_SEED
|
||||
#define WC_DRBG_NEXT_SEED_EMPTY 0
|
||||
|
|
@ -837,6 +869,11 @@ WOLFSSL_API int wc_RNG_DRBG_Present(const WC_RNG* rng);
|
|||
#define WC_DRBG_NEXT_SEED_CONSUMING ((WC_ATOMIC_INT_ARG)(-1))
|
||||
|
||||
WOLFSSL_API int wc_RNG_DRBG_NextSeedGenerate(WC_RNG* rng, word32 n);
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
WOLFSSL_API int wc_RNG_DRBG_NextSeedGenerate_RBGC(WC_RNG* rng,
|
||||
WC_RNG *root,
|
||||
word32 n);
|
||||
#endif
|
||||
WOLFSSL_API int wc_RNG_DRBG_NextSeedCurrent(WC_RNG* rng,
|
||||
WC_ATOMIC_INT_ARG* n);
|
||||
WOLFSSL_API int wc_RNG_DRBG_NextSeedNow_Nonce(WC_RNG* rng,
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@
|
|||
* a use-after-free instead of BUSY_E -- only containers whose teardown
|
||||
* provably quiesces consumers first may set it. */
|
||||
#define WC_RNG_BANK_FLAG_NO_CHECKOUT_REFCOUNTING (1U << 11)
|
||||
#define WC_RNG_BANK_FLAG_INIT_RBGC (1U << 12)
|
||||
#define WC_RNG_BANK_FLAG_PREDICTION_RESISTANCE (1U << 14)
|
||||
|
||||
/* base lock states are WC_RNG_LOCK_FREE / WC_RNG_LOCK_HELD in random.h;
|
||||
|
|
@ -290,6 +291,11 @@ WOLFSSL_API int wc_rng_bank_next_seed_generate(
|
|||
struct wc_rng_bank *bank,
|
||||
int inst_offset,
|
||||
word32 n);
|
||||
WOLFSSL_API int wc_rng_bank_next_seed_generate_rbgc(
|
||||
struct wc_rng_bank *bank,
|
||||
int inst_offset,
|
||||
word32 n,
|
||||
WC_RNG *root);
|
||||
#endif
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_inst_reinit(
|
||||
|
|
@ -313,26 +319,25 @@ WOLFSSL_API int wc_rng_bank_recover_inst(
|
|||
int timeout_secs,
|
||||
word32 flags);
|
||||
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
|
||||
#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK) && \
|
||||
(!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0))
|
||||
/* Spawn an SP 800-90C chain leaf from a bank instance: check out an
|
||||
/* Spawn an SP 800-90C chain RNG from a bank instance: check out a parent
|
||||
* instance (honoring the usual selection flags), wc_InitRngNonceRBGC() /
|
||||
* wc_InitRngNonceRBGC_New() the leaf from it, and check the instance back
|
||||
* in. The leaf's lifetime is thereafter decoupled from the bank: it is
|
||||
* lock-free for its owner and is released with wc_FreeRng() (stack form)
|
||||
* or wc_rng_free() (heap form). nonce/nonceSz may be NULL/0 for a plain
|
||||
* spawn; per the bank's distinctness convention, passing the address of
|
||||
* the leaf's owning object or request is recommended. bank == NULL uses
|
||||
* the default bank where support is compiled in.
|
||||
* WC_RNG_BANK_FLAG_CONSUME_NEXT_SEED composes (banked reseed before the
|
||||
* spawn draw); WC_RNG_BANK_FLAG_SEED_UNCREDITED and
|
||||
* WC_RNG_BANK_FLAG_FOR_RECOVERY are rejected.
|
||||
* WC_RNG_BANK_FLAG_ERROR_ON_RNG_FAILED is implied: the root is guaranteed
|
||||
* in-service, or an error is returned with no lease and no leaf. */
|
||||
* wc_InitRngNonceRBGC_New() the child from it, and check the parent instance
|
||||
* back in. The child's lifetime is thereafter decoupled from the parent and
|
||||
* its bank: it is lock-free for its owner and is released with wc_FreeRng()
|
||||
* (stack form) or wc_rng_free() (heap form). The child's RBGC stratum is one
|
||||
* plus the parent's stratum at time of instantiation. nonce/nonceSz may be
|
||||
* NULL/0 for a plain spawn; an example of a recommended nonce is Linux kernel
|
||||
* random_get_entropy() (which is typically a racy read of a high-resolution
|
||||
* timer). bank == NULL uses the default bank where support is compiled in.
|
||||
* WC_RNG_BANK_FLAG_CONSUME_NEXT_SEED composes (banked reseed before the spawn
|
||||
* draw); WC_RNG_BANK_FLAG_SEED_UNCREDITED and WC_RNG_BANK_FLAG_FOR_RECOVERY are
|
||||
* rejected. WC_RNG_BANK_FLAG_ERROR_ON_RNG_FAILED is implied: the parent is
|
||||
* guaranteed in-service, or an error is returned with no lease and no child. */
|
||||
WOLFSSL_API int wc_rng_bank_spawn(
|
||||
struct wc_rng_bank *bank,
|
||||
WC_RNG *leaf_rng,
|
||||
WC_RNG *child_rng,
|
||||
byte *nonce,
|
||||
word32 nonceSz,
|
||||
int preferred_inst_offset,
|
||||
|
|
@ -342,15 +347,15 @@ WOLFSSL_API int wc_rng_bank_spawn(
|
|||
#ifndef WC_NO_CONSTRUCTORS
|
||||
WOLFSSL_API int wc_rng_bank_spawn_new(
|
||||
struct wc_rng_bank *bank,
|
||||
WC_RNG **leaf_rng,
|
||||
WC_RNG **child_rng,
|
||||
byte *nonce,
|
||||
word32 nonceSz,
|
||||
int preferred_inst_offset,
|
||||
int timeout_secs,
|
||||
word32 flags);
|
||||
#endif /* !WC_NO_CONSTRUCTORS */
|
||||
#endif /* HAVE_HASHDRBG && !CUSTOM_RAND_GENERATE_BLOCK &&
|
||||
* (!HAVE_FIPS || FIPS_VERSION3_GE(7,0,0)) */
|
||||
|
||||
#endif /* WC_RNG_HAVE_RBGC */
|
||||
|
||||
WOLFSSL_API int wc_rng_bank_seed(struct wc_rng_bank *bank,
|
||||
const byte* seed, word32 seedSz,
|
||||
|
|
@ -689,6 +694,35 @@ static WC_INLINE WC_MAYBE_UNUSED int wc_rng_bank_inst_lock_clear_extra(struct wc
|
|||
wc_static_assert((WC_RESEED_INTERVAL) <= 0xFFFFFFFFUL);
|
||||
#endif
|
||||
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
|
||||
#define wc_InitRngRBGC(leaf, root, flags) \
|
||||
wc_InitRngNonceRBGC(leaf, root, NULL, 0, flags)
|
||||
|
||||
WC_MAYBE_UNUSED static WC_INLINE int wc_InitRngRBGC_New(WC_RNG** leaf, WC_RNG* root, word32 flags) {
|
||||
if ((leaf == NULL) || (root == NULL))
|
||||
return BAD_FUNC_ARG;
|
||||
*leaf = (WC_RNG*)XMALLOC(sizeof(WC_RNG), root->heap, DYNAMIC_TYPE_RNG);
|
||||
if (*leaf == NULL)
|
||||
return MEMORY_E;
|
||||
else
|
||||
return wc_InitRngNonceRBGC(*leaf, root, NULL, 0, flags);
|
||||
}
|
||||
|
||||
WC_MAYBE_UNUSED static WC_INLINE int wc_InitRngNonceRBGC_New(WC_RNG** leaf, WC_RNG* root,
|
||||
const byte* nonce, word32 nonceSz,
|
||||
word32 flags)
|
||||
{
|
||||
if ((leaf == NULL) || (root == NULL))
|
||||
return BAD_FUNC_ARG;
|
||||
*leaf = (WC_RNG*)XMALLOC(sizeof(WC_RNG), root->heap, DYNAMIC_TYPE_RNG);
|
||||
if (*leaf == NULL)
|
||||
return MEMORY_E;
|
||||
else
|
||||
return wc_InitRngNonceRBGC(*leaf, root, nonce, nonceSz, flags);
|
||||
}
|
||||
|
||||
#endif /* WC_RNG_HAVE_RBGC */
|
||||
|
||||
WC_MAYBE_UNUSED static WC_INLINE int wc_RNG_GetStatus(const WC_RNG* rng)
|
||||
{
|
||||
|
|
@ -811,6 +845,17 @@ static WC_INLINE WC_MAYBE_UNUSED int wc_rng_bank_inst_reseed_now(
|
|||
return wc_RNG_DRBG_Reseed_Now(WC_RNG_BANK_INST_TO_RNG(inst),
|
||||
nonce, nonceSz);
|
||||
}
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
static WC_INLINE WC_MAYBE_UNUSED int wc_rng_bank_inst_reseed_rbgc(
|
||||
struct wc_rng_bank_inst *inst, WC_RNG* root, const byte* nonce,
|
||||
word32 nonceSz)
|
||||
{
|
||||
if (inst == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
return wc_RNG_DRBG_ReseedRBGC(WC_RNG_BANK_INST_TO_RNG(inst), root,
|
||||
nonce, nonceSz);
|
||||
}
|
||||
#endif /* WC_RNG_HAVE_RBGC */
|
||||
|
||||
#else /* !WC_RNG_HAVE_LOCK */
|
||||
|
||||
|
|
@ -825,6 +870,28 @@ static WC_INLINE WC_MAYBE_UNUSED int wc_rng_bank_inst_reseed_now(
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef WC_RNG_HAVE_RBGC
|
||||
static WC_INLINE WC_MAYBE_UNUSED int wc_rng_bank_inst_reseed_rbgc(
|
||||
struct wc_rng_bank_inst *inst, WC_RNG* root, const byte* nonce,
|
||||
word32 nonceSz)
|
||||
{
|
||||
int ret;
|
||||
if (inst == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
#if defined(HAVE_FIPS) && FIPS_VERSION3_LT(7,0,0)
|
||||
/* the pre-v7 boundary's wc_RNG_DRBG_ReseedRBGC() predates the nonce
|
||||
* parameters; honest rejection, as with the boundary's Reseed_Now(). */
|
||||
if (nonceSz > 0)
|
||||
return NOT_COMPILED_IN;
|
||||
(void)nonce;
|
||||
ret = wc_RNG_DRBG_ReseedRBGC(WC_RNG_BANK_INST_TO_RNG(inst), root);
|
||||
#else
|
||||
ret = wc_RNG_DRBG_ReseedRBGC(WC_RNG_BANK_INST_TO_RNG(inst), root,
|
||||
nonce, nonceSz);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
#endif /* WC_RNG_HAVE_RBGC */
|
||||
|
||||
#endif /* !WC_RNG_HAVE_LOCK */
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue