1
0
mirror of https://github.com/wolfSSL/wolfssl.git synced 2026-10-24 04:09:07 +03:00

2776 Commits

Author SHA1 Message Date
philljj
06d4408d87 Merge pull request #11799 from padelsbach/swdev-falcon
Tests: add Falcon to swdev for crypto cb testing
2026-10-22 22:30:20 -05:00
Chris Conlon
278e98f952 Merge pull request #11798 from aidangarske/remove/whitewood-netrandom
Remove Whitewood netRandom support
2026-10-22 16:01:19 -06:00
philljj
17302ea446 Merge pull request #11831 from rlm2002/fipsV5customSHAKEPQ
Add V523_NONFIPS_SHAKE dev opt-in for FIPS v5 SHAKE128/256
2026-10-22 16:54:19 -05:00
Ruby Martin
9f27dba749 Add V523_NONFIPS_SHAKE dev opt-in for FIPS v5 SHAKE128/256
FIPS builds at v5.2 or older force WOLFSSL_NO_SHAKE128/256 on in
settings.h, which blocks ML-DSA and ML-KEM's internal SHAKE hashing
under --enable-fips=v5. Adds a CFLAGS opt-in, V523_NONFIPS_SHAKE,
that restores SHAKE128/256 for exactly the cert4718 (5.2.1) build.

- configure.ac, src/include.am, wolfssl/wolfcrypt/include.am: build
  and install the paired shake.c/shake.h from the internal fips repo
  overlay only when the opt-in and FIPS version match, validating
  both files exist first
- hash.c, asn.c, wc_mldsa.c/.h, benchmark.c, test.c, test_sha3.c:
  include shake.h ahead of their first sha3.h/asn.h include, since
  asn.h can reach sha3.h unguarded via ed448.h/wc_lms.h/wc_xmss.h
  first
- wc_mlkem.h: the one exception - its override must come after its
  sha3.h include, since sha3.h processes first there with SHAKE off,
  and shake.h's own fallback typedef and prototypes are what actually
  declare wc_Shake
- every override site uses the same
  defined(WOLFSSL_SHA3) && defined(V523_NONFIPS_SHAKE) guard
- registers V523_NONFIPS_SHAKE in .wolfssl_known_macro_extras, which
  check-source-text otherwise flags as unrecognized
2026-10-22 11:18:53 -06:00
Paul Adelsbach
c161875a37 PR feedback: reorder cert gen, reuse rng, compiler gates, update comment 2026-10-22 08:45:37 -07:00
Paul Adelsbach
cba6e48b55 PR feedback: address test issue with NO_CERTS 2026-10-22 08:45:37 -07:00
Paul Adelsbach
7b03ae8c97 ML-KEM add tests for encapsulate and decapsulate for crypto cb testing 2026-10-22 08:45:37 -07:00
Paul Adelsbach
548bbf2536 Update cert loading in ML-KEM tests 2026-10-22 08:45:37 -07:00
philljj
ad48539fde Merge pull request #11688 from dgarske/mpfs_athena
Add Microchip PolarFire SoC Athena F5200 (TeraFire) crypto callback port
2026-10-22 10:27:36 -05:00
kaleb-himes
1069f95bc0 Test the SHA-512 DRBG with personalization and additional input 2026-10-21 22:21:07 -07:00
kaleb-himes
4e9a5576b1 Use an in-range enum value in the SLH-DSA init-failure test 2026-10-21 22:21:07 -07:00
kaleb-himes
d6e949af1c Test that ECDSA verify rejects a negative r as well as a negative s 2026-10-21 22:21:07 -07:00
kaleb-himes
0d24665ca1 Free the ML-KEM test key before each re-init and at the end of each pass 2026-10-21 22:21:07 -07:00
kaleb-himes
cd10c54dac Accept the FIPS seed indicator in the ML-KEM decode-public-key test 2026-10-21 22:21:07 -07:00
kaleb-himes
6f594eeed1 Drop the ML-KEM private key when a different public key is decoded 2026-10-21 22:21:07 -07:00
kaleb-himes
81f276fd62 Zero the SLH-DSA key before the parameter lookup in wc_SlhDsaKey_Init 2026-10-21 22:21:07 -07:00
kaleb-himes
123c1bb884 Reject negative r or s in ECDSA verify per FIPS 186-5 sec 6.4.2 2026-10-21 22:21:07 -07:00
kaleb-himes
0447ea34f8 Reset ret after expected failures in RSA-PSS wrong-params test 2026-10-21 22:21:07 -07:00
kaleb-himes
88e912033d Test RSA PSS, OAEP and PKCS#1 v1.5 with SHA-512/224 and SHA-512/256 2026-10-21 22:21:07 -07:00
philljj
f5c98d7d7f Merge pull request #11832 from douzzer/20261020-drbgStateMutex-refactor-out
20261020-drbgStateMutex-refactor-out
2026-10-22 00:14:12 -05:00
Paul Adelsbach
94b375ec9d Tests: add Falcon to swdev for crypto cb testing 2026-10-21 17:13:12 -07:00
philljj
37650140d9 Merge pull request #11694 from aidankeefe2022/quickassit_fixes
Fixes: Fenrir #12347 and #12348:
2026-10-21 17:09:34 -05:00
Aidan Garske
274193c166 Remove Whitewood netRandom support 2026-10-21 09:52:05 -07:00
David Garske
41d6398556 Add Microchip PolarFire SoC Athena F5200 crypto callback port 2026-10-21 09:37:55 -07:00
Daniel Pouzzner
3dc0d75336 wolfcrypt/test/test.c: add rng_drbg_flavor_flags_test() (positive and negative tests for WC_RNG_INIT_FLAG_DRBG_SHA{256,512}). 2026-10-21 10:59:22 -05:00
philljj
b0afe82085 Merge pull request #11238 from padelsbach/crypto-cb-frodo
Add crypto callback for Frodo-kem
2026-10-21 10:31:26 -05:00
Aidan Keefe
aa3f7cb6e3 remove depriacted build option 2026-10-20 16:40:06 -07:00
philljj
36cc0bf518 Merge pull request #11815 from kaleb-himes/PQ-FS-2026-Part3-ppc-aes-setkeydirect-keylen
Pq fs 2026 part3 ppc aes setkeydirect keylen
2026-10-20 10:33:09 -05:00
philljj
c177f861d0 Merge pull request #11576 from douzzer/20260925-WC_RNG_RBGC_STRATUM_IMMUTABLE
20260925-WC_RNG_RBGC_STRATUM_IMMUTABLE
2026-10-20 10:15:26 -05:00
Daniel Pouzzner
23285d3ff7 wolfcrypt/src/random.c, wolfcrypt/test/test.c, doc/dox_comments/header_files/random.h: fix FIPS eligibility criteria for rng_src in wc_RNG_Pool_Collect2(). 2026-10-19 23:20:36 -05:00
kaleb-himes
100b95ffbb Run the zero-length AES key test on PPC asm builds too 2026-10-19 21:15:12 -06:00
philljj
af7c4e356a Merge pull request #11273 from jackctj117/11288
Fix: bound explicit EC-domain field lengths to prevent buffer overflow
2026-10-18 23:22:55 -05:00
Paul Adelsbach
21d747d46c Ensure encap/decap tests go through the find callback 2026-10-16 17:02:26 -07:00
Paul Adelsbach
333a14ef4c PR feedback: tests: loosen build guards, ensure key is freed, fix build with CERT_REQ 2026-10-16 16:22:26 -07:00
Paul Adelsbach
4729b8994c PR feedback: add Frodo coverage in swdev, allow separate make/encapsulate/decapsulate testing individually 2026-10-16 16:03:31 -07:00
Paul Adelsbach
c0272af012 PR feedback: update precompiler checks, add test case 2026-10-16 16:03:31 -07:00
Paul Adelsbach
57b999a588 Add crypto callback for Frodo-kem 2026-10-16 16:03:31 -07:00
Juliusz Sosinowicz
7638751fdb Address review: check EVP_CIPHER_CTX_mode against CBC mode in test 2026-10-16 11:04:33 -07:00
Juliusz Sosinowicz
480d7d5990 Return int from EVP_CIPHER_mode and EVP_CIPHER_CTX_mode
Match OpenSSL 3. Fixes -Wconversion warnings in OpenVPN, which stores
the result in an int.
2026-10-16 11:04:33 -07:00
jackctj117
14314b626c asn: test explicit EC-domain field-length bounds (issue 11288) 2026-10-15 16:22:58 -06:00
philljj
eb113cac67 Merge pull request #11547 from padelsbach/cbonly-lmsxmss
Add CB_ONLY mode for LMS+XMSS, add swdev
2026-10-15 17:01:48 -05:00
David Garske
fa565101ab mldsa: add WOLFSSL_MLDSA_ALLOW_WEAK_PREHASH for SHA-256-only TPM firmware 2026-10-15 08:26:38 -07:00
Daniel Pouzzner
ee07709802 wolfcrypt/test/test.c: in rng_lifecycle_test(), (void)child_inited after last zeroing to hush old clang-tidy. 2026-10-15 00:17:10 -05:00
Daniel Pouzzner
2a133a160c wolfcrypt/src/rng_bank.c: a bank's root cannot be a full-mutex instance.
wc_rng_bank_root_rng_init() now refuses WC_RNG_INIT_FLAG_USE_FULL_MUTEX
with BAD_FUNC_ARG.  The bank operates its root through lock-word
operations alone -- the daemon's claims, reinit-in-place
(wc_rng_bank_reinit_rng()), the invalidation walk -- none of which take
the outer mutex, so a full-mutex root was bypassed by every one of them,
and its reinit's teardown (wc_FreeRng_PreLocked() under a lock-word-only
lease) released and destroyed a mutex the bank never took, under any
getter holding it.  wc_rng_bank_reinit_rng() gets a matching tripwire
(WRONG_TYPE_OBJECT_E on a WC_RNG_FLAG_FULL_MUTEX instance, before any
mutation), unreachable through the bank's own constructors.

doc/dox_comments/header_files/rng_bank.h: wc_rng_bank_root_rng_init()
documents the refusal (and the existing ALREADY_E).

wolfcrypt/test/test.c: rng_lifecycle_test() tries the flag on a vacated
root (refused, root still vacant), then instantiates and reinstantiates
the root without it.  WC_RNG_HAVE_LOCK_FULL_MUTEX builds only; no CI
scenario sets WC_RNG_WANT_LOCK_FULL_MUTEX, so verified locally with
--enable-rng-extras --enable-rng-bank CFLAGS=-DWC_RNG_WANT_LOCK_FULL_MUTEX.
2026-10-14 19:32:59 -05:00
Daniel Pouzzner
fc89bcdfe9 wolfcrypt/src/rng_bank.c: prediction-resistant checkouts in lock-less multithreaded banks, and no waiting on verdicts in wc_rng_bank_reseed_range().
* wc_rng_bank_checkout(): without the lock facility the prediction-
  resistance reseed is wc_RNG_DRBG_Reseed_Now(), as before this branch.
  wc_RNG_DRBG_Reseed_Now_Primary() refuses a multithreaded lock-less
  build with NOT_COMPILED_IN because a bare instance there has no
  exclusion to make reseed-then-draw atomic, so every prediction-
  resistant checkout in such a bank (--enable-rng-bank without
  --enable-rng-extras) had come to fail.  The bank's lease is that
  exclusion, and without the lock facility an instance retains no chain
  parent for a reseed to defer to, so the plain reseed is the primary
  reseed and the _Primary() flag override has nothing to override.

* wc_rng_bank_reseed_range(): the _CAN_WAIT retry loop now stops on a
  non-transient code, as wc_rng_bank_inst_reinit()'s does.  A verdict --
  WRONG_TYPE_OBJECT_E for a chain reseed of a stratum-0 member under
  WC_RNG_RBGC_STRATUM_IMMUTABLE, RNG_FAILURE_E for a condemned instance
  -- does not change with waiting; the loop retried it until timeout,
  reporting WC_TIMEOUT_E in its place, or forever with no timeout, the
  member's lease held throughout.  The walk now records it and moves on
  to the remaining instances.

wolfcrypt/test/test.c: the prediction-resistance checkout tests in
random_bank_test() are no longer gated to lock or single-threaded
builds; rng_lifecycle_test() gains the chain-reseed-of-a-plain-bank
walk under immutable strata (prompt WRONG_TYPE_OBJECT_E, members
untouched, a primary walk then succeeds).
2026-10-14 19:12:20 -05:00
Daniel Pouzzner
181575db73 wolfcrypt/src/rng_bank.c: in wc_rng_bank_inst_reinit(), a member of a lock-less RBG-chain bank no longer waits on an out-of-service root.
The reinit holds the inst-op gate for the duration, and the root's
recovery (wc_rng_bank_root_rng_reinit()) needs that same gate, so a
WC_RNG_BANK_FLAG_CAN_WAIT caller waited for an event its own hold
foreclosed -- until timeout, or forever with none (and the daemon's root
recovery behind it, forever too).  The root's verdict is now returned at
once in that arm, gate released, member out of service and retryable.
With the lock facility the root's recovery rides the root's lock, not
the gate, and the wait stands.

wolfcrypt/test/test.c: rng_lifecycle_test() gains the scenario: a
lock-less RBG-chain member reinit against a torn-down root returns
NOT_READY_E well inside its timeout, and succeeds -- the member a chain
child again -- once the root is recovered.  Fails against the previous
rng_bank.c by timing out.
2026-10-14 18:19:09 -05:00
Daniel Pouzzner
267d56d920 RNG review round 2: bank teardown against retained root references, lock-less bank root reinit, user seed on RDRAND hosts, and two linuxkm legacy-kernel fixes.
wolfcrypt/src/rng_bank.c:

* wc_rng_bank_fini(): a root pinned by an external (caller-spawned)
  child, or held, is now refused before commitment, with the bank fully
  intact -- STILL_REFERENCED_E / BUSY_E, as for a member.  Previously a
  root free failure was only tallied, the bank's refcount and flags were
  destroyed, and the retry of wc_rng_bank_free() deallocated the bank
  under the child's RBGC_parent.  The pre-commit check counts member
  pins (released by the member frees) and refuses on any pin beyond
  them, regardless of the root's status: a root torn down by a failed
  reinit is NOT_INIT with its lock word live and its pins outstanding,
  and was previously skipped.  The post-commit root free now restores
  the refcount and returns on BUSY_E / STILL_REFERENCED_E, as the member
  loop does, so a child that arrives after the pre-commit check still
  leaves a retryable bank.

* wc_rng_bank_reinit_rng(): WC_RNG_INIT_FLAG_PRESERVE_LOCK is added
  only when WC_RNG_HAVE_LOCK, as wc_rng_bank_inst_reinit() already does.
  _InitRng() refuses the flag with NOT_COMPILED_IN otherwise, so in a
  bank built without the lock facility wc_rng_bank_root_rng_reinit()
  tore the root down and could not reinstantiate it; the inst-op gate is
  the exclusion in that arm.

wolfcrypt/src/random.c:

* _InitRng(): on an RDRAND-capable CPU with HAVE_INTEL_RDRAND, the DRBG
  bypass now refuses caller-supplied seed material with
  WRONG_TYPE_OBJECT_E, the instance left uninstantiated.  Previously
  wc_InitRngNonce_UserSeed() and wc_RNG_global_fallback_init_user_seed()
  returned success with the seed silently dropped and the instance
  relabeled stratum 0, generating from RDRAND -- a primary-class
  instance under a user-seeded name.  Instantiating the DRBG anyway is
  not an option: wc_RNG_GenerateBlock() reads RDRAND whenever the CPU
  has it, DRBG or not.  wc_InitRngFixedSeed()'s post-hoc backstop
  (which stays, for CUSTOM_RAND_GENERATE_BLOCK) returns the same code.

doc/dox_comments/header_files/random.h: wc_InitRngNonce_UserSeed()
documents the refusal; the previous text described a bypass
"HAVE_INTEL_RDRAND without HAVE_HASHDRBG", which cannot reach the
function (WC_RNG_HAVE_RBGC requires HAVE_HASHDRBG), while the reachable
case went undocumented.

wolfcrypt/test/test.c: rng_lifecycle_test() gains the bank-teardown
scenario (external child of the root; refused fini leaves the bank
generating; held root; torn-down pinned root; convergence once the child
is released) and a lock-less bank root reinit.  The latter fails against
the previous rng_bank.c.

linuxkm/module_hooks.c: in the pre-3.17 NMI-context time accessors, read
jiffies after the calibration latch rather than at entry: a calibration
published by another CPU between the two can carry a later tick, and
the unsigned difference wrapped.

linuxkm/linuxkm_wc_port.h: in_task() shim for kernels before 4.10, where
it first appears (include/linux/preempt.h); wc_linuxkm_can_long_loop()
used it unconditionally.
2026-10-14 17:48:07 -05:00
Arpan Sharma
d3c1d7a1fd SLH-DSA: update msg docs and empty-message tests per review
- Source comments: msg may be NULL if msgSz is 0 for the sign and
  verify functions, and Sign(), Verify() and slhdsakey_sign_external()
  reject a NULL msg only when msgSz is greater than 0.
- Doxygen: note on the msg parameter, and SignDeterministic() returns
  BAD_LENGTH_E for a too-small signature buffer.
- test.c: SignDeterministic() with (NULL, 0) must match the signature
  for a non-NULL message of length 0.
- test_slhdsa.c: SignWithRandom() with (NULL, 0) and a full-size
  signature buffer signs successfully.
2026-10-14 15:27:59 -07:00
Arpan Sharma
e0806fd809 SLH-DSA: accept (NULL, 0) message in SignWithRandom/SignDeterministic
wc_SlhDsaKey_SignWithRandom() rejected msg == NULL for any length, so it
and wc_SlhDsaKey_SignDeterministic() returned BAD_FUNC_ARG for an empty
message passed as (NULL, 0), unlike wc_SlhDsaKey_Sign() and Verify().
Use the same check as Sign() and, like Sign(), replace a NULL message
with a one-byte static stand-in before the crypto callback dispatch.
Update the doxygen and source comments, and add tests for the (NULL, 0)
case.
2026-10-14 15:27:59 -07:00
Daniel Pouzzner
8a65208daa RNG SP-800-90* compliance mechanism completion (the balance of the
WC_RNG_RBGC_STRATUM_IMMUTABLE campaign):

* RNG state-invalidation delivery by entropy epoch

* Fork safety for the WC_RNG lock word

* RBGC lineage persistence with a global fallback source

* A uniform "transient vs. verdict" error taxonomy

* Lifecycle hardening that makes WC_RNG safe to reinstantiate under lease-free
  observers.

Protocol-level changes (random.[ch]):

* Entropy epoch (WC_RNG_HAVE_ENTROPY_EPOCH, on by default with atomics in
  multithreaded builds; WC_RNG_WANT_/WC_RNG_NO_ENTROPY_EPOCH override): a
  global event counter, wc_RNG_global_invalidate_entropy(), replaces the
  per-instance walk as the primary delivery mechanism for state-invalidation
  events (VM fork/resume, hibernation).  Each WC_RNG carries a stamp; every
  seeding operation captures the epoch (and PID) before acquiring material
  and stamps at completion, so an event that lands mid-operation leaves a
  stale stamp.  rng_entropy_event_propagate() converts {stale stamp,
  unlatched} to {latched, swept} lazily, at the instance's next aperture:
  "detection is also delivery," and every aperture consulted after a nonzero
  wc_RNG_entropy_needs_recovery() is post-purge.  wc_RNG_lock_put() reports
  an unpropagated increment as NEEDS_RECOVERY_E, so a holder whose last
  operation straddled the event learns of it at release.  The latch is
  cleared by a recovery only when the recovering caller's capture is still
  current.

* wc_RNG_entropy_needs_recovery() is the single authoritative verdict on a
  standing recovery obligation (latch, stale epoch, PID change, exhausted
  reseed budget), and the generate path, the stir path, the pool reader and
  the banked-seed consumer all key on it.  rng_pid_change_check() is retired
  into it: a fork() is an epoch event.  The reseed counter is thereby
  returned to its SP 800-90A meaning (budget only); invalidation never
  spends runway and is never enforced by counter saturation in lock builds.

* Fork safety for the lock word: WC_RNG_LOCK_ORPHANED (error-crypt.h:
  OBJECT_ORPHANED_E, -1036; HWPUF_* codes shift down by one).  A _HELD word
  stamped with another process's PID was held across a fork() by a holder
  absent in this process; the first post-fork contender marks it _ORPHANED
  (RngLockOrphanCheck(), from every lock getter), applies the invalidation
  once as CAS winner, and reports OBJECT_ORPHANED_E.  The verdict licenses
  nothing to the contender: the owner adopts the lease by
  wc_FreeRng_PreLocked() then wc_InitRng_ex2() with the new
  WC_RNG_INIT_FLAG_PRESERVE_LOCK (which clears _ORPHANED with the latch); a
  live holder's release or completed recovery also clears it.

* RBGC lineage persistence (WC_RNG_HAVE_LOCK && WC_RNG_HAVE_RBGC): a chain
  child retains RBGC_parent and pins it by RBGC_refcount (both live for as
  long as the lock word, preserved across _PRESERVE_LOCK reinits).
  wc_FreeRng() on a pinned parent wipes sensitive state and returns the new
  STILL_REFERENCED_E (error-crypt.h) -- the shell must outlive its
  children; wc_rng_free() leaks rather than freeing referenced memory.
  WC_RNG_FLAG_NO_RBGC_PARENT opts an instance out of being retained
  (wc_rng_new*() and *_New() constructors set it, since the void
  wc_rng_free() cannot report).  HAVE_FIPS forces lock-required parents and
  WC_RNG_RBGC_STRATUM_IMMUTABLE, and random.h refuses HAVE_FIPS with RBGC
  but without the lock facility.

* Global fallback RBGC source (WC_RNG_HAVE_GLOBAL_FALLBACK_RNG):
  wc_RNG_global_fallback_init[_user_seed]() / _get() / _free(), a static
  lock-required WC_RNG, freed by wolfCrypt_Cleanup().  PollAndReSeed() and
  wc_RNG_DRBG_NextSeedGenerate() climb a ladder for a chain-backed
  instance: the retained parent, then the global fallback (under FIPS only
  when it qualifies as "a sibling of the parent, an ancestor, or the initial
  randomness source" per SP 800-90C), then -- unless the instance is
  WC_RNG_FLAG_NO_PRIMARY_SEED -- the primary source.  A ladder rung whose
  release reports NEEDS_RECOVERY_E voids the reseed (DRBG_NEED_RESEED) or
  purges the bank just filled.  SP 800-90C qualification of a supplied root
  against the retained parent is enforced in wc_RNG_DRBG_ReseedRBGC() and
  wc_RNG_DRBG_NextSeedGenerate_RBGC() under FIPS.

* Runtime policy flags: wc_RNG_SetFlags() / wc_RNG_ClearFlags() /
  wc_RNG_GetFlags(), limited to WC_RNG_FLAGS_SETTABLE / _CLEARABLE
  (FAIL_FAST, ONLY_PRIMARY_SEED, NO_PRIMARY_SEED) and to exclusive
  ownership.  WC_RNG_FLAG_FAIL_FAST (WC_RNG_INIT_FLAG_FAIL_FAST at birth):
  a generate that would otherwise reseed in-line reports instead --
  NOT_READY_E for the budget, NEEDS_RECOVERY_E for a latched or stale
  instance (RngFailFastVerdict()) -- leaving the DRBG uncondemned;
  wc_RNG_Pool_Collect2() sets it transiently on its source so the ring claim
  is held for one bounded generate.  WC_RNG_FLAG_NO_PRIMARY_SEED /
  WC_RNG_INIT_FLAG_NO_PRIMARY_SEED forbids the primary source after
  instantiation (chain members that must stay chain-fed; MISSING_RNG_E on an
  instance with no chain parent); WC_RNG_FLAG_ONLY_PRIMARY_SEED is the
  converse, set transiently by the new wc_RNG_DRBG_Reseed_Now_Primary() for
  prediction-resistant constructions on chain-backed instances.
  WC_RNG_{INIT_,}FLAG_RECOVER_AND_PROMOTE_FROM_NEXT_SEED is renamed
  _UPGRADE_FROM_NEXT_SEED (rng_bank.h: WC_RNG_BANK_FLAG_AUTO_UPGRADE_FROM_
  NEXT_SEED).  WC_RNG_INIT_FLAG_* retain their shipped values, with the
  new flags appended; WC_RNG_FLAG_* are renumbered alongside.

* Transient-vs-verdict taxonomy: WC_RNG_ERR_IS_TRANSIENT() (random.h, with
  a mirror in rng_bank.h for boundaries that predate it) names the codes
  that mean "not now" -- BUSY_E, NOT_READY_E, NEEDS_RECOVERY_E, RAN_BLOCK_E,
  ENTROPY_RT_E, ENTROPY_APT_E.  wc_InitRng*() passes them through from the
  seed source verbatim (ReseedSourceFailure(), shared by instantiate and
  reseed) rather than folding them into RNG_FAILURE_E; rng_bank.c keys its
  retry loops on the same set.  BUSY_E and MEMORY_E -- a resource that
  requires waiting, in a context that can't -- never condemn, even with no
  reseed runway (RngGenerateFailure(), now also the single outcome mapping
  for wc_RNG_DRBG_Reseed_Now()).  wc_RNG_Status() precomputes the code for
  a status (NOT_READY_E / RNG_FAILURE_E / DRBG_CONT_FIPS_E) and replaces
  the ad hoc status checks throughout.  wc_GenerateSeed() with
  HAVE_ENTROPY_MEMUSE returns BUSY_E from a context that cannot run the
  wolfEntropy source rather than silently substituting a backup source.

* WC_RNG_INIT_FLAG_TEST_USER_SEED: caller-supplied seed material is
  health-tested and laid out exactly as module-gathered material (leading
  SEED_BLOCK_SZ bytes are the test block, excluded from DRBG input in FIPS
  and non-FULL_SEED builds); wc_InitRngFixedSeed() uses it, restoring its
  master behavior.  Without the flag the user seed is copied at the
  instantiate offset, so no supplied byte is discarded and no health test
  runs.  The strength floors live at the public entry points
  (UserSeedSzFloor(): WC_DRBG_SEED_SZ, plus a block under the flag where the
  block is excluded; zero refused); _InitRng() keeps only the one-block
  backstop.  wc_InitRngNonce_UserSeed() refuses without WC_RNG_HAVE_RBGC
  (provenance marking lives there) and validates its shape arguments.

Lifecycle hardening (random.[ch]):

* WC_RNG members shared by both DRBG cores -- drbgType, reseedCtr, the
  banked-next-seed aperture (nextSeed, nextSeedLen, nextSeedRBGCStratum) --
  move from DRBG_internal / DRBG_SHA512_internal into WC_RNG, for safe
  lock-free access by lease-free observers; the per-core structs keep the
  SMALL_STACK_CACHE newSeed_buf.  WC_DRBG_SEED_BUF_SIZE names the gathered
  seed length; the generic DRBG functions take the reseed counter by
  pointer.  NextSeedPtrs() and the per-core duplication it served are gone.

* _InitRng() zeroization (RngInitWipe()) skips the atomic words that can
  have lease-free concurrent observers (lock, RBGC_refcount, poolHead/Tail,
  nextStirLen, nextSeedLen), which are instead atomically (re)initialized;
  the apertures are painted _TORNDOWN at entry and reopened as the last act
  before publication, and rng->status becomes DRBG_OK only at the very end.
  WC_RNG_INIT_FLAG_PRESERVE_LOCK leaves the lock word and refcount exactly
  as found (refusing _LOCK_INITIALLY and _USE_FULL_MUTEX, and insisting the
  _REQUIRED bits agree), and discharges an inherited latch by CAS at entry
  rather than erasing it.  WC_RNG_STATIC_INITIALIZER is provided.

* Pool lifecycle: poolHead carries a 2-bit state above the epoch (UNALLOC,
  LIVE, CLAIMED, TORNDOWN).  wc_RNG_Pool_Alloc() allocates unclaimed and
  publishes by CAS; a writer claims by one CAS at entry and releases by CAS
  at every exit; wc_FreeRng() takes LIVE -> TORNDOWN by one CAS before any
  irreversible step and returns BUSY_E (nothing mutated) when a claim is
  held, never spinning; TORNDOWN refuses re-equipment until the next
  _InitRng().  Likewise the credited seed aperture gains
  WC_DRBG_NEXT_SEED_TORNDOWN, every ownership transition is a CAS, and a
  purge repaints a live claim _PURGED for its holder to unwind rather than
  reopening it from under the holder.  wc_FreeRng() frees the DRBG after
  nulling the pointer at every site, and uninstantiates only the core
  matching drbgType.

* wc_FreeRng() in lock builds takes the lease itself (unconditionally, so a
  standing latch or condemnation does not block teardown) and refuses a
  held instance with BUSY_E; wc_FreeRng_PreLocked() is the form for a
  caller already holding the lease, which it retains.  The WC_RNG_LOCK_
  REQUIRED-but-unheld case is OBJECT_NOT_LOCKED_E.  wc_RNG_lock_get_
  unconditional() / _put_unconditional() are the internal trivial forms.

* wc_RNG_DRBG_GetReseedCtr() becomes WOLFSSL_LOCAL (the counter is
  potentially sensitive internal state); wc_RNG_DRBG_NextSeedGenerate_
  Primary() is added; wc_RNG_DRBG_NextSeedCurrent(), wc_RNG_Pool_Current()
  and wc_RNG_lock_read() take const.  An instance with no DRBG (RDRAND et
  al.) never opens its seed aperture, and producers and consumers alike
  refuse it with WRONG_TYPE_OBJECT_E (was MISSING_RNG_E, which nothing on
  that path returned).  A stir refuses with the needs-recovery verdict
  (NEEDS_RECOVERY_E) when the instance is quarantined, due, or stale, and
  NOT_READY_E only when the interval trips within the call.

* WC_VERBOSE_RNG logging follows the taxonomy: transient codes are never
  logged as errors.

rng_bank.c / rng_bank.h:

* struct wc_rng_bank_inst now places its WC_RNG at offset 0, so
  WC_RNG_BANK_INST_TO_RNG() is a cast; wc_rng_bank_reinit_rng() (LOCAL)
  retires and reinstantiates any bank-owned rng, protected by WC_RNG.lock
  under _PRESERVE_LOCK where available (a held root yields BUSY_E) and by
  the inst-op gate otherwise; wc_rng_bank_inst_reinit() and
  wc_rng_bank_root_rng_reinit() are built on it.  A member is reborn only
  as a chain child of its root -- a root that cannot serve right now is a
  reason to retry, never to substitute a primary reseed.

* wc_rng_bank_reseed_range(): the RBGC arm takes the root's lease for the
  chain draw; the walk carries on past a per-instance failure (marking the
  instance due) and returns the first such failure, with a code that
  aborted the walk (WC_TIMEOUT_E, INTERRUPTED_E, a checkout failure)
  outranking it; wc_rng_bank_next_seed_generate_local() purges the member
  when the root's release reports an event under its hold, as
  wc_RNG_DRBG_NextSeedGenerate()'s chain arm does.

* wc_rng_bank_fini(): a member refusing to free (BUSY_E /
  STILL_REFERENCED_E) restores the bank refcount so the caller can and must
  retry; the root is freed after the members, so member pins are released
  before the root's refcount is judged.  The invalidation walk's root arm is
  unconditional (a root mid-reinit is NOT_INIT with its lock word live).
  Init retry loops key on WC_RNG_ERR_IS_TRANSIENT().

* rng_bank.h: WC_RNG_LOCK_ORPHANED / WC_RNG_LOCK_EXTRA_SHIFT 5 mirrored in
  the no-lock compat arm; for the WCv5.2.4 boundary, which carries the
  backported RNG services, WC_RNG_HAVE_STIR / WC_RNG_HAVE_RESEED_NOW
  capability markers and a wc_InitRngNonceRBGC() perso-argument shim, so
  consumers outside the boundary (src/ssl.c, src/ssl_crypto.c) gate on the
  markers rather than on FIPS version arithmetic.

linuxkm/lkcapi_sha_glue.c:

* wc_linuxkm_rng_state_invalidate(): with the entropy epoch, bumps the
  epoch and materializes only the bank root's latch synchronously
  (rng_invalidation_pre_check() keys on it), leaving members to lazy
  delivery so a consumer is admitted to a still-unlatched member and
  recovers it under its own lease rather than waiting out a quarantine;
  without the epoch, the synchronous walk as before.  The daemon-less bank
  path treats a transient member code from wc_rng_bank_reseed_range() as a
  deferred recovery, not a failure.

* Entropy daemon: a transient failure of the last-ditch root reinit is
  retried next pass rather than ending the daemon (which had made root
  recovery and next-seed feeding end for good on ordinary contention);
  the vmgenid poller's immediate root reseed takes the root's lease (it was
  OBJECT_NOT_LOCKED_E and void-cast); the kernel-log rule throughout --
  transient codes are one pass away and not errors, the SP 800-90B health
  verdicts are warnings (WC_LKM_RNG_ERR_IS_HEALTH()), anything else is an
  error -- at the recovery, banking, bonus-reseed and reinit arms; the
  banking pass's no-DRBG case is WRONG_TYPE_OBJECT_E; busy instances are
  counted in the recovery sweep's tally.

* wc_linuxkm_drbg_generate(): the kernel-facing language is two-valued --
  -EIO for a verdict (non-transient, or ENTROPY_RT_E / ENTROPY_APT_E),
  -EBUSY for every "not now" code; only BUSY_E outside the invalidation
  window (every instance held at once: an undersized bank) is logged as an
  error.  The pooling pass (re)equips any instance it finds poolless each
  turn, so no up-front allocation and no special case after a
  reinstantiation.  Bank sizing rationale documented.

* The _get_random_bytes() callback contract is best-effort, not
  unconditional success: a refusal from atomic context immediately after a
  global invalidation falls through silently to the native generator.
  linuxkm/WOLFSSL_LINUXKM_HAVE_GET_RANDOM_CALLBACKS-7v3.patch: drop the
  WARN_ONCE on callback failure, and drop the routing of the batched
  get_random_{u8,u16,u32,u64}() through the callback (not FIPS-controlled
  consumers; get_random_bytes_user() and getrandom() remain fully covered).

Tests:

* wolfcrypt/test/test.c: flags_test() (WCFLAGS) replaces rng_flag_abi_test():
  pairwise-disjointness of every bit-flag namespace in the wolfcrypt headers
  at compile time and of the hand-numbered registries at run time, against
  the symbols rather than literal values; rng_epoch_test() (RNGEPOCH: epoch
  propagation on every aperture, mid-gather increments, busy and
  out-of-memory seed sources never condemn); rng_lifecycle_test() (RNGLIFE:
  RBGC parent pinning and STILL_REFERENCED_E, the destruction latch,
  wc_FreeRng_PreLocked() and the _PRESERVE_* reinit, the bank-walk mirror
  arm); rng_lock_fork_test() (RNGLKFRK: the orphaned-lease verdict and
  adoption across a real fork()); rng_init_flags_test() (contradictory and
  not-compiled-in init flags refused) and rng_seed_verdict_test() (transient
  codes from the seed source survive wc_InitRng*() verbatim; FIPS v7+ only,
  the pinned legacy random.c folds them); rng_seed_test() reactivated (dead
  since the seed-size defaults moved into random.h) and steered to SHA-256
  in SHA-512-preferring builds; WC_RNG_INIT_FLAG_TEST_USER_SEED arms in the
  wc_InitRngNonce_UserSeed() strict-contract block; leak fixes and
  goto-teardown in the RBGC-lifetime and pool tests; per-subtest in-kernel
  stack high-water marks (WC_LINUXKM_STACK_DEBUG_PER_TEST); WC_RNG moved to
  the heap in pkcs7authenveloped_run_vectors().

* tests/api/test_random.c, tests/unit-mcdc/test_random_*whitebox.c: follow
  the reseed counter to WC_RNG; forced seed failures use a nonsense code so
  the WC_VERBOSE_RNG line stays quiet; condemnation-on-reseed-failure arms
  saturate the counter explicitly, since invalidation no longer does.

* doc/dox_comments: every new API and flag; the instantiation-input and
  user-seed contracts; reseed/reseed_range return semantics; the next-seed
  return taxonomy.
2026-10-14 16:13:43 -05:00