Commit Graph

2567 Commits (master)

Author SHA1 Message Date
JacobBarthelmeh e2ee66c64b
Merge pull request #11480 from SparkiDev/crypto_fixes_1
Cryptography implementation fixes
2026-09-18 16:26:37 -06:00
JacobBarthelmeh 034ea67809
Merge pull request #11431 from Frauschi/zephyr_fixes_2
More Zephyr fixes
2026-09-18 14:25:27 -06:00
Tobias Frauenschläger 2b0e284934 zephyr: call Zephyr's clock API instead of remapping the POSIX names
wc_port.h guarded a sys_clock_gettime()/sys_clock_settime() remap with
"#ifndef CLOCK_REALTIME". On Zephyr 4.3 and newer the same header includes
<time.h>, and both picolibc and newlib define CLOCK_REALTIME as 1. The guard was
therefore always false, the whole block was skipped, and z_time() called
clock_gettime() - a symbol Zephyr only defines when the application enables
CONFIG_POSIX_TIMERS, which is itself gated behind CONFIG_POSIX_SYSTEM_INTERFACES.
A build without them failed:

  test.c:3657:9: error: implicit declaration of function 'clock_settime';
                 did you mean 'sys_clock_settime'?

Making the remap unconditional fixes that build but hands every consumer a
library-wide rewrite of two POSIX names. wc_port.h is reached from every
wolfCrypt header, so an application calling clock_gettime() would silently get
sys_clock_gettime(), which reports failure as a negative errno instead of -1
plus errno, and code that stores a function pointer under either name would stop
compiling depending on its include order.

Drop the macros and name the Zephyr API at the three places that need it -
z_time(), the wolfCrypt test's dummy wallclock and the threaded TLS sample -
keeping the POSIX call for Zephyr versions without SYS_CLOCK_REALTIME.
sys_clock_gettime() lives in lib/os/clock.c and is core Zephyr rather than
POSIX, so a Zephyr build no longer has to enable the POSIX layer just to satisfy
wc_port.c.
2026-09-17 10:27:06 +02:00
Sean Parkinson 1445c701dd Cryptography implementation fixes
fe_448.c: small code corner case in reductions
eccsi.c: don't modify ssk field of key on verify
wc_mlkem_poly.c: When compiled for Intel assembly but not AVX2 - no assembly code used - the initialization of the SHAKE is needed in derive secret. Always initialize as it doesn't cost much.
sp_c32.c/sp_c64.c: corner case of div - when r1 is negative is really is going meant to be 0
sp_c32.c: Fix TOOM-3 mul and sqr to handle over large inputs.
ed448.c: check non-canonical keys better
2026-09-17 17:42:23 +10:00
Daniel Pouzzner 60f220abfd linuxkm/lkcapi_sha_glue.c, wolfcrypt/src/random.c, wolfcrypt/src/rng_bank.c,
wolfcrypt/test/test.c, wolfssl/wolfcrypt/random.h: fixes for a second batch
  of static-analysis findings.

* vmgenid fallback poller: search the ACPI IDs the kernel vmgenid driver
  matches -- "VMGENCTR" and "VM_GEN_COUNTER" -- rather than the spec's
  mixed-case spellings.  ACPICA upcases _HID/_CID strings when building
  the namespace and acpi_get_devices() matches by strcmp, so the old walk
  found QEMU only by its _HID and missed CID-only devices (Hyper-V, VMware).

* wc_linuxkm_drbg_generate(): in non-vector builds, drop local_bh_disable()
  around the blockable CAN_WAIT reseed and reinit operations and retake it
  after, mirroring the vector arm's release/reacquire bracket; the
  checkout's migrate_disable() persists across the sleep, preserving CPU
  pinning preemptibly.

* entropy daemon and sysfs stats dumps: gate the next-stir format fragments
  and arguments on WC_RNG_HAVE_NEXT_SEED.

* new WC_LKM_BANK_RBGC_FLAG (WC_RNG_BANK_FLAG_RBGC when WC_RNG_HAVE_RBGC,
  else WC_RNG_BANK_FLAG_NONE): keep LKCAPI functional without RBGC support
  compiled in.

* wc_rng_bank_init_nonce(): use (size_t)(-1) rather than SIZE_MAX in the
  allocation overflow check (C90 and NO_STDINT_H builds).

* wc_rng_bank_fini(): pre-scan all instances for WC_RNG_LOCK_HELD before any
  mutation, returning BUSY_E (retryable) with refcount untouched, free hook
  unfired, and root intact.

* random.h: #error on WC_RNG_DEBUG_STATS without the RNG lock facility.

* wc_RNG_DRBG_Stir_Nonce(): reject nonce == NULL with nonzero nonceSz
  (BAD_FUNC_ARG), matching the other nonce-bearing APIs.

* random_bank_test(): hoist held_inst to function scope and check it in
  from the shared teardown path, closing a leak on failing assertions.

* wc_RNG_DRBG_NextSeedGenerate_local(): pointer declaration style cleanup.
2026-09-16 17:55:36 -05:00
Daniel Pouzzner 5ba5b5cbe1 wolfcrypt/src/random.c, wolfcrypt/src/rng_bank.c, wolfcrypt/test/test.c,
wolfssl/wolfcrypt/settings.h: fixes for a batch of static-analysis findings.

* complete the WC_CAS_WITH_RETRY post-loop dispositions in rng_bank.c and the
  lock_put()s: aborted releases percolate before the lock word (and, in
  wc_RNG_lock_put(), the mutex) is reported free, keeping ownership with the
  caller for retry; the inst_lock_*_extra() setters return the CAS result;
  wc_rng_bank_inst_invalidate_entropy() latches or condemns, mirroring
  wc_RNG_invalidate_entropy().

* wc_RNG_invalidate_entropy(): tolerate WRONG_TYPE_OBJECT_E from
  wc_RNG_DRBG_ScheduleReseed() -- a no-DRBG (direct-RDRAND) instance has
  nothing to schedule and nothing whose staleness the latch would mark;
  don't condemn it.

* wc_rng_bank_reseed_range(): fix undeclared identifier (inst -> drbg) in the
  HAVE_FIPS && FIPS_VERSION3_LT(7,0,0) && WC_RNG_HAVE_RBGC branch.

* _InitRng(): free and clear the full mutex when wc_LockMutex() fails after
  successful wc_InitMutex() (WC_RNG_INIT_FLAG_LOCK_INITIALLY).

* settings.h: WC_RESEED_INTERVAL (1UL << 48UL) -> (W64LIT(1) << 48) --
  unsigned long is 32 bits on LLP64 targets (64-bit MinGW), making the
  shift undefined.

* test.c: silence unused i in random_bank_test() when the reseed-interval
  check is configured out.
2026-09-16 16:32:14 -05:00
Daniel Pouzzner 8cddf2177e wolfcrypt/test/test.h: fix bugprone-macro-parentheses in revised WC_TEST_RET_ENC_I(). 2026-09-16 02:06:29 -05:00
Daniel Pouzzner 8d95ec5da0 wolfcrypt/test/test.c: in rng_drbg_svc_test(), fix gating on wc_ecc_set_rng(). 2026-09-16 01:15:05 -05:00
Daniel Pouzzner 622299a7ba wolfcrypt/src/random.c, wolfcrypt/src/rng_bank.c, wolfcrypt/test/test.c: fix RNG-extras support for HAVE_INTEL_RDRAND. 2026-09-16 01:09:11 -05:00
Daniel Pouzzner 5bda097a91 wolfcrypt/test/test.h: tweak WC_TEST_RET_ENC_I() to put a ceiling on i. 2026-09-16 01:07:38 -05:00
Daniel Pouzzner d0c48dd8f5 wolfcrypt/test/test.c: old-FIPS compat def for WC_RNG_INIT_FLAG_NONE. 2026-09-15 19:20:02 -05:00
Daniel Pouzzner 9913e49c3b wolfcrypt/src/random.c, wolfssl/wolfcrypt/random.h, wolfcrypt/src/rng_bank.c, linuxkm/lkcapi_sha_glue.c, wolfcrypt/test/test.c: 's/WC_RNG_INIT_FLAGS_/WC_RNG_INIT_FLAG_/g'. 2026-09-15 19:20:02 -05:00
Daniel Pouzzner fd14f12c06 wolfcrypt/src/rng_bank.c, wolfssl/wolfcrypt/rng_bank.h, wolfcrypt/test/test.c: fixes for old-FIPS compatibility. 2026-09-15 19:20:02 -05:00
Daniel Pouzzner b25bd17474 wolfcrypt/test/test.c: when TEST_SLEEP is not otherwise defined, define it to WC_RELAX_LONG_LOOP(). 2026-09-15 19:20:02 -05:00
Daniel Pouzzner 64ea3bc6ca wolfcrypt/src/rng_bank.[ch]:
* in struct wc_rng_bank, rename daemon_root to root_rng, and change its gate from WC_RNG_BANK_HAVE_DAEMON_SUPPORT to WC_RNG_HAVE_RBGC || WC_RNG_HAVE_NEXT_SEED || WC_RNG_HAVE_POOL.

* add devId slot to struct wc_rng_bank.

* rename WC_RNG_BANK_FLAG_INIT_RBGC to WC_RNG_BANK_FLAG_RBGC, and support it in wc_rng_bank_reseed_range().

* remove root argument from wc_rng_bank_next_seed_generate_rbgc() (bank->root_rng is now implicit).

* remove wc_rng_bank_daemon_root_set() and wc_rng_bank_daemon_root_get(), and add wc_rng_bank_root_rng_init() and wc_rng_bank_root_rng_get().

* revert wc_rng_bank_inst_lock_get() et al from macros back to inlines, to assure type enforcement, and remove dangerous cast from WC_RNG_BANK_INST_TO_RNG().

* in wc_rng_bank_init_nonce(), use the persistent ctx->root_rng, removing the ephemeral-on-stack "WC_RNG root".

* in wc_rng_bank_fini(), clean up ctx->root_rng.

* in wc_rng_bank_reseed_range(), implement support for WC_RNG_BANK_FLAG_RBGC.

* in wc_rng_bank_invalidate_entropy(), add invalidation of bank->root_rng.

linuxkm/lkcapi_sha_glue.c:

* in wc_linuxkm_rng_state_invalidate(), remove now-obsolete special-case "daemon_root" code, and pass WC_RNG_BANK_FLAG_RBGC to the inline (non-daemon) wc_rng_bank_reseed_range().

* in wc_linuxkm_entropy_daemon(), rename local_root to root_rng, assign it at entry from wc_rng_bank_root_rng_get(bank), and remove the in-daemon cleanup of local_root; move the periodic explicit reseed of the root_rng to precede the pooling pass.
2026-09-15 19:20:01 -05:00
Daniel Pouzzner 306eaea22f test: free the leaf RNG from the shared teardown path
leaf was declared inside the inner block that initializes it, so the
ERROR_OUT() calls between its wc_InitRngNonceRBGC() and its wc_FreeRng()
jumped to a teardown that could neither see it nor free it.  Any failed
assertion in that window leaked the DRBG allocation and whatever else the
instance held.

Hoist the declaration to function scope under the same guard, track
initialization, and free it from out: alongside root.

Reported by Fenrir.
2026-09-15 19:20:01 -05:00
Daniel Pouzzner e604292132 test: pin the stir's effect on the reseed counter
The assertion rejected only a decreased reseed counter, which no
implementation would produce, so it could not distinguish a stir from a
credited reseed or from a stir that never ran.

A stir is one SP 800-90A Rev.1 10.1.1.4 generate with the stir material as
additional input, so step 7 advances the counter by exactly one.  Require
that: a reset to 1 would mean the stir had masqueraded as a credited reseed,
and no change at all would mean it never executed.

Reported by Fenrir, whose suggested assertion -- that the counter be
unchanged -- does not hold: it fails against the current implementation,
because incrementing is what the generate is required to do.
2026-09-15 19:20:01 -05:00
Daniel Pouzzner 8d84c4e0fb test: validate the NextSeedGenerate() result before overwriting it
The banking loop assigned wc_RNG_DRBG_NextSeedGenerate()'s return value to
api_ret and then immediately overwrote it with wc_RNG_DRBG_NextSeedCurrent()'s,
so every check below -- the error classification, the ALREADY_E break, and the
guard on the monotonic-progress assertion -- was reading the query's result,
not the generation's.  A hard failure from the generate could not fail the
test.

Keep the two results in separate variables and classify the generate's own
return value.

Reported by Fenrir.
2026-09-15 19:20:00 -05:00
Daniel Pouzzner 945c33a857 random/rng_bank/linuxkm: add nonce and personalization-string plumbing
Two related gaps in what callers could supply.

The SP 800-90A personalization string was reachable only as the hardcoded
NULL that _InitRng() passed to Hash_DRBG_Init().  Hash_df() already had
the input; nothing could fill it.  Thread it through the instantiate
family -- wc_InitRngNonce_ex2(), wc_InitRngNonceRBGC{,_New}(),
SpawnRngRBGC(), wc_rng_bank_init_nonce() and wc_rng_bank_spawn{,_new}().

Personalization is an instantiate-time input in SP 800-90A, so the reseed
and stir APIs deliberately do not gain it; material of that kind belongs
in their existing additional-input argument.

Separately, the bank-level seed and reseed APIs had no way to pass a nonce
to the per-instance reseed underneath them, so wc_rng_bank_seed{,_range}()
and wc_rng_bank_reseed{,_range}() gain one.  The index arguments keep
their positions and the material sits immediately before timeout_secs.

linuxkm uses it to carry a post-event timestamp into the recovery reseeds
issued after a state invalidation, and zeroizes it on every path, matching
the existing uncredited-nonce sites in that file.
2026-09-15 19:20:00 -05:00
Daniel Pouzzner 30ee4c100d random: partition the RBGC stratum space for user-supplied seed
RBGCStratum was reset to 0 by any successful reseed, including one
carrying a caller-supplied seed.  Stratum 0 means "primary" -- an RNG
seeded from the entropy source -- and it is what
wc_RNG_DRBG_NextSeedGenerate_local() requires of a NextSeed root.  So a
single wc_RNG_DRBG_Reseed() call promoted an instance to a provenance it
had not earned.

Reserve a disjoint region of the stratum space for chains rooted in
user-supplied entropy.  A user-seeded reseed now sets
WC_RNG_RBGC_USER_SEED_STRATUM rather than 0, and children descend from
there, so unknown provenance is carried rather than erased.  Source-
gathered reseeds still promote to 0.

Guards in _InitRng(), wc_RNG_DRBG_ReseedRBGC_local() and
wc_RNG_DRBG_NextSeedGenerate_local() keep a natural chain from growing
into the reserved region, and a static assert keeps the two regions from
overlapping if the constant is overridden.

Consequence worth stating: while an instance carries a user-seed stratum
it cannot serve as a NextSeed root.  That is state, not a brand -- a
credited primary reseed promotes it back to 0, and an RBGC reseed places
it one below its root.  random_bank_test() covers both directions: a
spawned child at USER_SEED_STRATUM + 1, and a prediction-resistance spawn
whose parent is re-promoted to 0 by a fresh credited primary reseed
immediately before the child's draw.
2026-09-15 19:20:00 -05:00
Daniel Pouzzner 4f905ecbbb test: enable the RBGC tests on the pre-v7 FIPS boundary
The RBGC test entry points were gated on WC_RNG_HAVE_RBGC alone, and the
pre-v7 copy of rng_drbg_rbgc_test() pulled rng_bank.h in with
WC_RNG_BANK_SUPPORT defined locally and then undefined again, so that the
RNG-level compat shims were visible only inside that one translation
region.

Gate the tests on the boundary version or on WC_RNG_BANK_SUPPORT actually
being configured, and drop the local define/undef dance in favour of the
real setting.  The shims are needed by more than that one test.
2026-09-15 19:20:00 -05:00
Daniel Pouzzner 4dafa01992 test: correct FIPS gating of hkdf_cryptocb_async_test()
FIPS builds force crypto callbacks off, so a test that asserts a callback
took effect is structurally incompatible with any FIPS build, not just
pre-v7 ones.  The guard admitted FIPS v7 and later, where the test cannot
pass.

Narrow both the definition guard and the call site to !defined(HAVE_FIPS).
2026-09-15 19:20:00 -05:00
Daniel Pouzzner 0d9e3c15ed RNG extras: rename "uncredited [re]seed" in all its spellings to "stir",
appropriately spelled, for clarity and consistency.  Stirring is implemented
  by Hash_DRBG_StirGenerate() an an SP 800-90A Rev. 1 10.1.1.4 generate, with
  the stir material as additional_input and no output requested.
2026-09-15 19:19:59 -05:00
Daniel Pouzzner a3f9a12903 wolfcrypt/src/random.c, wolfcrypt/test/test.c:
* implement Hash_DRBG_StirGenerate(), refactor
  wc_RNG_DRBG_Reseed_Nonce_Uncredited() and wc_RNG_DRBG_Reseed_Uncredited() atop
  it, and revert addition of "credited" arg to Hash256_DRBG_Reseed(),
  Hash512_DRBG_Reseed(), and Hash_DRBG_Reseed();

* in _InitRng(), error early on invalid flags, and implement proper catch-all
  error path cleanup;

* in wc_RNG_GenerateBlock(), when rng->pid != getpid(), alongside
  PollAndReSeeD(), empty the pool and cached seeds, if any;

* also check for WC_RNG_LOCK_ENTROPY_INVALIDATED immediately before calling
  Hash*_DRBG_Generate() and if found, recover inline with must-succeed
  PollAndReSeed().
2026-09-15 19:19:59 -05:00
Daniel Pouzzner 2e4bf5f3f0 RNG-extras fixes from CI results:
configure.ac: add --enable-rng-extras aka -DWC_RNG_EXTRAS, default off unless KERNEL_MODE_DEFAULTS, and add it to enable-all-crypto and FIPS v7 setup.

wolfssl/wolfcrypt/random.h: refactor setup for RNG extras to default off unless defined(WC_RNG_EXTRAS) or the specific WC_RNG_WANT_foo is defined.

wolfcrypt/src/random.c: add missing WC_RNG_HAVE_LOCK gate around NextSeedPurge().

.wolfssl_known_macro_extras: add WC_RNG_WANT_*

wolfcrypt/test/test.c: add !HAVE_SELFTEST gate around rng_drbg_svc_test().

wolfssl/wolfcrypt/types.h: if WOLFSSL_NO_MALLOC and !WOLFSSL_STATIC_MEMORY, make sure WC_NO_CONSTRUCTORS is defined.
2026-09-15 19:19:59 -05:00
Daniel Pouzzner ba5f45ffb3 linuxkm/lkcapi_sha_glue.c, wolfcrypt/src/rng_bank.c, wolfcrypt/test/test.c: in linuxkm_put_drbg((), properly ignore NEEDS_RECOVERY_E from wc_rng_bank_inst_checkin(); in wc_rng_bank_recover_inst(), properly handle WC_RNG_LOCK_ENTROPY_INVALIDATED; in rng_entropy_invalidate_test(), test recovery after invalidation. 2026-09-15 19:19:59 -05:00
Daniel Pouzzner 4f1cc1e017 wolfcrypt/src/random.c, wolfcrypt/test/test.c: in wc_RNG_DRBG_ReseedRBGC_local() and wc_RNG_DRBG_NextSeedGenerate_local(), tolerate reseed by an RBGC root provided its stratum is less than the child's stratum (no stratum downgrade allowed), unless defined(WC_RNG_NO_RBGC_RESEED). Uncredited reseeds by wc_RNG_DRBG_ReseedRBGC_local() are now permitted unconditionally.
wolfssl/wolfcrypt/random.h: move wc_drbg_reseed_ctr_t definition up, and use it in DRBG*_internal.
2026-09-15 19:19:59 -05:00
Daniel Pouzzner 3fa61e2151 wolfcrypt/src/random.c, wolfcrypt/src/rng_bank.c, wolfssl/wolfcrypt/random.h, wolfssl/wolfcrypt/rng_bank.h, wolfcrypt/test/test.c: fixes for !HAVE_HASHDRBG. 2026-09-15 19:19:58 -05:00
Daniel Pouzzner a975de00b5 wolfcrypt/src/random.c: in wc_RNG_DRBG_NextSeedGenerate_local(), add missing const to nonce arg;
wolfcrypt/test/test.c: gate out argon2_test() if WOLFSSL_NO_MALLOC, and in rng_entropy_invalidate_test(), add missing !WC_NO_CONSTRUCTORS gates.
2026-09-15 19:19:58 -05:00
Daniel Pouzzner a8911b10d9 wolfcrypt/test/test.c: add FIPS gate for rng_entropy_invalidate_test(); wolfcrypt/src/rng_bank.c: in rng_bank_spawn(), add missing feature-sensing gate for WC_RNG_INIT_FLAGS_RECOVER_AND_PROMOTE_FROM_NEXT_SEED. 2026-09-15 19:19:58 -05:00
Daniel Pouzzner 553822dfbe wolfcrypt/src/random.c, wolfssl/wolfcrypt/random.h, wolfcrypt/src/rng_bank.c, wolfssl/wolfcrypt/rng_bank.h, wolfssl/wolfcrypt/settings.h, wolfcrypt/test/test.c: add opt-in RNG debug statistics:
* WC_RNG_DEBUG_STATS: global atomic counters across the RNG facilities
  -- seeds and reseeds by provenance (source, RBGC, banked next seed,
  uncredited stir), generates, pool collects/extracts, bank
  checkouts/recoveries -- with wc_rng_debug_stats_snap() /_restore()
  /_sum() for snapshot-delta accounting in tests and daemons;
  wc_rng_debug_counter_t is word64, word32 where 64-bit is unavailable;

* settings.h: default the knob on for verbose-debug kernel builds
  (WC_VERBOSE_RNG && WOLFSSL_KERNEL_VERBOSE_DEBUG), opt-out
  WC_RNG_NO_DEBUG_STATS;

* test.c: snapshot-delta assertions verifying the counters advance with
  the operations that claim them.
2026-09-15 19:19:58 -05:00
Daniel Pouzzner bd15bfd1e2 wolfcrypt/src/rng_bank.c, wolfssl/wolfcrypt/rng_bank.h, wolfcrypt/test/test.c: add bank daemon registration and the default bank:
* daemon protocol: wc_rng_bank_daemon_reserve() /_register()
  /_unregister() /_release(), a magic-word claim
  (WC_RNG_BANK_DAEMON_MAGIC_FREE when unclaimed) admitting exactly one
  scheduling daemon per bank, and wc_rng_bank_daemon_root_{set,get}()
  binding the daemon's RBGC root; gated
  WC_RNG_BANK_HAVE_DAEMON_SUPPORT;

* WC_RNG_BANK_FLAG_DEFAULT_BANK marks the process-default bank;
  wc_rng_bank_fini() for symmetric teardown; per-instance flags word
  (WC_RNG_BANK_INST_FLAG_*, with _ALREADY_WARNED de-duplicating
  degradation warnings);

* test.c random_bank_test(): daemon claim/release contracts, double
  claim rejection, root binding, and teardown coverage.
2026-09-15 19:19:57 -05:00
Daniel Pouzzner 7ba78036d6 wolfcrypt/src/random.c, wolfssl/wolfcrypt/random.h, wolfcrypt/test/test.c: add the uncredited-nextseed stir facility:
* a second, fixed-size aperture beside the banked next seed:
  wc_RNG_DRBG_NextUncreditedSeedStore() banks caller-supplied material
  (up to WC_DRBG_NEXT_UNCREDITED_SEED_LEN bytes) and
  wc_RNG_DRBG_NextUncreditedSeedNow() stirs it into the DRBG as an
  uncredited, source-free, atomic-context-safe reseed -- harvested
  entropy improves the instance without claiming credit or resetting
  the reseed counter; the hand-off reuses the nextSeedLen aperture
  protocol (WC_DRBG_nextSeedLen_t);

* test.c: uncredited-aperture coverage in rng_drbg_nextseed_test():
  store/stir protocol, non-resetting counter, coexistence with the
  credited bank, and the argument contracts.
2026-09-15 19:19:57 -05:00
Daniel Pouzzner 6341d921cf wolfcrypt/src/random.c, wolfssl/wolfcrypt/random.h, wolfcrypt/src/rng_bank.c, wolfssl/wolfcrypt/rng_bank.h, wolfcrypt/test/test.c: add entropy invalidation and recovery admission:
* wc_RNG_invalidate_entropy() / wc_rng_bank_invalidate_entropy(): mark
  an instance's (or a whole bank's) seed material untrusted -- for VM
  fork/resume and similar duplication events -- by latching
  WC_RNG_LOCK_ENTROPY_INVALIDATED in the lock word; an invalidated
  instance refuses service until recovery-reseeded, and
  wc_rng_bank_inst_lock_get_conditional() lets checkout skip
  invalidated instances rather than block on them;

* recovery admission: WC_RNG_BANK_FLAG_MAYBE_FOR_RECOVERY tolerates a
  not-actually-invalidated instance,
  WC_RNG_FLAG_RECOVER_AND_PROMOTE_FROM_NEXT_SEED (and the bank spawn
  analog _SPAWN_RECOVER_AND_PROMOTE) admits a banked next seed as the
  recovery source; wc_rng_bank_{seed,reseed}_range() (re)seed instance
  subsets;

* free hooks: wc_RNG_register_free_hook() /
  wc_rng_bank_register_free_hook() -- teardown notification for
  external registries (e.g. a kernel-module RNG object registry that
  must invalidate on VM resume), gated WC_RNG_HAVE_FREE_HOOK;

* test.c: new rng_drbg_invalidate_test() (RNGINVAL) covering
  invalidation latching, refused service, conditional checkout,
  recovery admission (including next-seed-sourced), free-hook firing,
  and the argument contracts; lock-word read probes in the svc test.
2026-09-15 19:19:57 -05:00
Daniel Pouzzner e5e1484540 wolfcrypt/src/random.c, wolfssl/wolfcrypt/random.h, wolfcrypt/test/test.c: add the per-instance random pool:
* a caller-sized buffer of pre-generated output attached to a WC_RNG
  (wc_RNG_Pool_Alloc()), filled incrementally by wc_RNG_Pool_Collect()
  -- or wc_RNG_Pool_Collect2(), drawing from a second instance -- and
  drained atomic-context-safely by wc_RNG_Pool_Extract();
  wc_RNG_Pool_Current() reports the fill; the collect/extract hand-off
  is arbitrated by an aperture word (WC_RNG_pool_state_t, atomic with a
  plain-word arm for WOLFSSL_NO_ATOMICS), on the same protocol shape as
  the banked next seed;

* gated by WC_RNG_HAVE_POOL (opt-out: WC_RNG_NO_POOL);

* test.c: new rng_drbg_pool_test() (RNGPOOL), covering the collect /
  extract protocol, the two-instance collect, exhaustion, and the
  argument contracts.
2026-09-15 19:19:57 -05:00
Daniel Pouzzner 7bca2d66f6 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.
2026-09-15 19:19:57 -05:00
Daniel Pouzzner 2237e5e1c1 wolfcrypt/src/rng_bank.c, wolfssl/wolfcrypt/rng_bank.h, wolfcrypt/test/test.c: migrate bank instance locking onto the WC_RNG lock machine, and add prediction-resistance checkout:
* wc_rng_bank_inst_lock_{get,put,read}() are reimplemented over
  wc_RNG_lock_*(): the per-instance lock word is now the instance
  WC_RNG's own lock, with the bank-specific bits (affinity-locked,
  vec-ops-inherit) carried above WC_RNG_LOCK_EXTRA_SHIFT; instances are
  instantiated WC_RNG_INIT_FLAGS_LOCK_REQUIRED on FIPS v7+ boundaries;
  stale check-ins now surface OBJECT_NOT_LOCKED_E; optional
  WC_RNG_BANK_LOCK_DEBUG instrumentation;

* WC_RNG_BANK_FLAG_PREDICTION_RESISTANCE, per-call or bank-wide: every
  sleepable lease is freshly credited-reseeded before the caller's first
  draw; demands _CAN_WAIT and contradicts uncredited and recovery
  seeding (BAD_FUNC_ARG); atomic callers under a bank-wide posture are
  refused; recovery is exempt, and remains the sole restoration path for
  a failed instance; PR supersedes _CONSUME_NEXT_SEED, leaving the
  banked seed intact for a later consumer;

* new wc_rng_bank_init_nonce(), wc_rng_bank_first_failover_inst_set(),
  wc_rng_bank_get_inst_id(); WC_RNG_BANK_FLAG_NO_CHECKOUT_REFCOUNTING;
  bank flag literals become unsigned (1U << n);

* test.c random_bank_test(): argument/alignment contracts for the
  check-in entry points, PR contract and posture coverage, and probe
  modernization -- capture retvals and report them with
  WC_TEST_RET_ENC_EC()/_ENC_I() instead of bare _ENC_NC.
2026-09-15 19:19:57 -05:00
Daniel Pouzzner 6a04d7f857 wolfcrypt/src/random.c and wolfssl/wolfcrypt/random.h: unify DRBG reseed plumbing and make entropy crediting explicit:
* funnel all reseeds through a dual-DRBG-aware rng-level Hash_DRBG_Reseed()
  (the SHA-256-internal routine becomes Hash256_DRBG_Reseed()), with an
  explicit credited flag: credited reseeds reset the reseed counter,
  uncredited ones mix in material without resetting it;

* add wc_RNG_DRBG_Reseed_Nonce() and wc_RNG_DRBG_Reseed_Nonce_Uncredited(),
  accepting a nonce as additional input; wc_RNG_DRBG_Reseed() and
  wc_RNG_DRBG_Reseed_Uncredited() become thin wrappers around them;

* wc_RNG_DRBG_ScheduleReseed() and the commanded-reseed paths now return
  WRONG_TYPE_OBJECT_E, not success, for instances with no DRBG (RDRAND et
  al.) -- a commanded reseed that cannot happen is not a success;

* hoist wc_RNG_GetStatus() and wc_RNG_DRBG_Present() above the HASHDRBG
  region with hardened gates, and promote them to public API
  (WOLFSSL_API prototypes in random.h);

* random.h: regate the service prototypes per-facility (accessors ungated,
  RBGC spawn under HAVE_HASHDRBG && !CUSTOM_RAND_GENERATE_BLOCK, banked-
  next-seed under WC_RNG_HAVE_NEXT_SEED), migrating the explanatory
  comments into random.c beside the implementations.
2026-09-15 19:19:57 -05:00
Daniel Pouzzner 8054f3e5d5 wolfcrypt/src/rng_bank.c, wolfssl/wolfcrypt/rng_bank.h, wolfcrypt/test/test.c:
* integrate the banked-next-seed facility, and add WC_RNG_BANK_FLAG_QUIET.

* add recovery-patrol and leased-spawn support: WC_RNG_BANK_FLAG_FOR_RECOVERY, WC_RNG_BANK_FLAG_ERROR_ON_RNG_FAILED, wc_rng_bank_recover_inst(), wc_rng_bank_spawn(), and wc_rng_bank_spawn_new().

struct wc_rng_bank gains inst_op_gate, a bank-global wolfSSL_Atomic_Int serializing whole-instance operations against the daemon's lockless banking: wc_rng_bank_next_seed_generate() (the daemon entry point) claims it around wc_RNG_DRBG_NextSeedGenerate(), and wc_rng_bank_inst_reinit() claims it around its free/reinstantiate cycle -- non-blocking on both sides (BUSY_E = skip this turn / this attempt).  lease-holders never consult the gate; instance-lock exclusion already covers every lease-holder interaction, so the hot path is untouched.  the entry point's return taxonomy is daemon policy: ALREADY_E = sleep until consumed; MISSING_RNG_E = retire the instance from the banking rotation; others transient.

WC_RNG_BANK_FLAG_CONSUME_NEXT_SEED: wc_rng_bank_checkout() consumes a ready banked next seed on the locked instance BEFORE the usability evaluation, with the return value deliberately ignored -- every outcome is fully represented in instance state and handled uniformly by the incumbent divert/error/handout machinery: a consumed bank cures a reseed-due instance in place (no divert, no warning); a hard reseed failure marks the instance out of service and flows through the standard paths.

WC_RNG_BANK_FLAG_QUIET (bank-level only, set at wc_rng_bank_init(); no per-call meaning): suppresses the facility's WC_VERBOSE_RNG expected-condition warnings -- reseed-due handout, reinit retry/timeout reports, all-instances-busy, seed-walker out-of-service reports -- so deliberate exercising doesn't spam the log; never suppresses refcount/consistency diagnostics.  random_bank_test() sets it at both bank constructions and gains coverage for the daemon entry point's contracts and the consume-at-checkout flow (fill to ALREADY_E, consume lands the reseed counter at 1, empty-bank consume is transparent).

_FOR_RECOVERY declares a recovery-intent checkout of an explicit instance: out-of-service status is expected, the consume-next-seed arm is suppressed, and selection-altering flags are rejected.  wc_rng_bank_recover_inst() packages checkout -> reinit-iff-out-of-service -> checkin; healthy instances are success no-ops, so patrols can act on lockless status observations.

_ERROR_ON_RNG_FAILED guarantees checkout returns either a lease on an in-service instance or an error with no lease, closing the two paths that could lease a dead one (targeted checkout; failover after the anti-livelock lap disarm).  under _CAN_WAIT a dead instance is retried within the timeout budget -- the window in which a recovery patrol restores it -- and a lap or wait that found only out-of-service instances reports the distinguished BAD_STATE_E.

wc_rng_bank_spawn()/_spawn_new() check out an instance (implying _ERROR_ON_RNG_FAILED), wc_InitRngNonceRBGC[_New]() an SP 800-90C chain leaf from it, and check it back in via wc_rng_bank_inst_checkin(); the leaf's lifetime is thereafter decoupled from the bank and lock-free for its owner.  _CONSUME_NEXT_SEED composes for a banked reseed of the root before the spawn draw.  the heap form and its supporting arms are gated !WC_NO_CONSTRUCTORS, mirroring wc_InitRngNonceRBGC_New()'s declaration; the stack form remains available under WC_NO_CONSTRUCTORS.  random_bank_test() gains coverage for the one-arg checkin roundtrip, the flag contracts and rejected combinations, recovery-patrol no-op semantics, and both spawn forms.
2026-09-15 19:19:56 -05:00
Daniel Pouzzner 65084f56da wolfcrypt/src/random.c, wolfssl/wolfcrypt/random.h, wolfcrypt/test/test.c, wolfcrypt/test/test.h: add seed banking facility:
wolfcrypt/src/random.c and wolfssl/wolfcrypt/random.h: add the banked-next-seed facility: wc_RNG_DRBG_NextSeedGenerate(), wc_RNG_DRBG_NextSeedCurrent(), wc_RNG_DRBG_NextSeedNow(), and wc_RNG_DRBG_NextSeedNow_Nonce(), with unit test coverage in new rng_drbg_nextseed_test() ("RNGNXTS").

seed material is banked incrementally, in-boundary, from the module's seed source, and consumed in an immediate credited reseed that touches no seed source -- pure computation, safe in atomic context (the one credited reseed shape with that property).  banked reseeds provide no SP 800-90 prediction resistance (the material predates the request by construction); wc_RNG_DRBG_Reseed_Now() remains the live-gather shape.

DRBG_internal and DRBG_SHA512_internal gain nextSeed[] (identical byte accounting to every other source-fed (re)seed) and nextSeedLen, a wolfSSL_Atomic_Int hand-off aperture: non-negative values count banked bytes (filling); negative values are sentinels (WC_DRBG_NEXT_SEED_READY, _CONSUMING).  the single-writer daemon fills with AddFetch and publishes _READY with a CAS after health-testing the completed bank (wc_RNG_TestSeed()); a consumer claims with a CAS _READY -> _CONSUMING, reseeds, zeroizes, and release-stores _EMPTY.  use-once throughout: delivered, failed, and health-test-rejected material is all zeroized before the aperture reopens.

distinct protocol results, deliberately loud: ALREADY_E (bank ready or consuming), NOT_READY_E (nothing consumable), RETRY_E (health test could not run -- non-dispositive MEMORY_E; leave the bank complete and re-call), MISSING_RNG_E (no DRBG instantiated, e.g. RDRAND bypass -- a direct caller must know what instance it holds).  gathering calls wc_GenerateSeed() with a local zero-initialized throwaway OS_Seed, fully independent of rng->seed, so the daemon cannot race an owner's own source reseed; any working seed source suffices (wolfEntropy, RDSEED, et al.).  gate: WC_RNG_HAVE_NEXT_SEED = HAVE_HASHDRBG && !CUSTOM_RAND_GENERATE_BLOCK && WOLFSSL_ATOMIC_OPS, opt-out WC_RNG_NO_NEXT_SEED (registered in .wolfssl_known_macro_extras).

RNGNXTS covers the aperture protocol as observed through _NextSeedCurrent() (empty, partial-preserved-across-consume-attempt, monotone fill, ready sentinel, ALREADY_E idempotence, consume -> reseed counter 1 -> empty, refill and _Nonce consume) and the argument contracts, runtime-gated on wc_RNG_DRBG_Present().

wolfcrypt/test/test.c: in random_bank_test(), gate the wc_rng_new_bankref() probes (and the rng2 local and its cleanup) on !WC_NO_CONSTRUCTORS, matching the API's declaration; the wc_InitRng_BankRef() probes are constructor-free and keep the bare WC_HAVE_RNG_BANKREF gate.  (fixes an implicit function declaration under WC_NO_CONSTRUCTORS + WC_RNG_BANK_SUPPORT, a configuration with no prior harness coverage.  predates the NextSeed work.)
2026-09-15 19:19:56 -05:00
Daniel Pouzzner 87af605c2f wolfcrypt/src/random.c, wolfssl/wolfcrypt/random.h, wolfcrypt/test/test.c, wolfcrypt/test/test.h: add SP 800-90C RBG chain (RBGC) APIs: wc_InitRngRBGC(), wc_InitRngNonceRBGC(), wc_InitRngRBGC_New(), wc_InitRngNonceRBGC_New(), wc_RNG_DRBG_ReseedRBGC(), and read accessor wc_RNG_DRBG_IsRBGCLeaf().
implement by adding a seedRng arg to _InitRng() and PollAndReSeed(): when non-null, seed material is drawn from the parent DRBG's generate function in place of the module's seed source, inheriting all other instantiate/reseed mechanics verbatim (seed byte accounting, wc_RNG_TestSeed(), instantiate/reseed dispatch, failure disposition, RDRAND bypass, SMALL_STACK arms).  unified spawn mechanics in static SpawnRngRBGC() with exactly-one-destination arg checking; the four spawn APIs and wc_RNG_DRBG_ReseedRBGC() are minimal stubs.

add WC_RNG.isRbgcLeaf: sticky tag set by spawn and by successful wc_RNG_DRBG_ReseedRBGC() (chain-reseeding a source-born instance demotes it, one-way); every RBGC API rejects a tagged root, enforcing depth-one chains programmatically.  the tag survives source reseeds by policy.

annotate the deliberate PollAndReSeed() <-> wc_RNG_GenerateBlock() recursion for clang-tidy misc-no-recursion on each cycle member: the cycle is bounded at one trip lexically -- wc_RNG_GenerateBlock()'s backstop reseed always passes a null seedRng -- independent of chain topology and the depth-one policy.

gate RBGC APIs on !WC_NO_CONSTRUCTORS (the _New variants allocate from the root's heap and release with wc_rng_free()).  also neutralize the seed-acquisition failure message attribution in _InitRng() (no longer necessarily wc_GenerateSeed()).

add rng_drbg_svc_test() ("RNGSVC") and rng_drbg_rbgc_test() ("RNGRBGC").

RNGSVC covers the DRBG accessor/reseed services and per-key RNG clear APIs: accessor null contracts, generate advances the reseed counter, wc_RNG_DRBG_Reseed_Uncredited() preserves it, credited wc_RNG_DRBG_Reseed() resets it, wc_RNG_DRBG_ScheduleReseed() lands it exactly at WC_RESEED_INTERVAL and the next generate performs a source reseed, wc_RNG_DRBG_Reseed_Now() with and without nonce, and wc_RsaClearRNG()/wc_ecc_clear_rng()/wc_curve25519_clear_rng() including the preserved wc_RsaSetRNG(key, NULL) rejection.

RNGRBGC covers the RBGC APIs: spawn arg contracts, root reseed-counter debit, leaf tagging and wc_RNG_DRBG_IsRBGCLeaf(), depth-one rejections (spawn-from-leaf in stack and _New forms, ReseedRBGC-with-leaf-as-root), wc_RNG_DRBG_ReseedRBGC() with and without nonce, tag stickiness across a forced source reseed, one-way demotion, and the _New/wc_rng_free() lifecycle.

DRBG-internal observations are gated at runtime on wc_RNG_DRBG_Present() so both tests pass on RDRAND-shaped instantiations, exercising the degenerate arms.  key and WC_RNG objects use the WC_*_VAR() macros to respect kernel frame limits.
2026-09-15 19:19:56 -05:00
Daniel Pouzzner cd7a7d8a82 wolfcrypt/test/test.c: in random_bank_test(), hold a second instance checked out across the stale check-in probes. With the bank refcount at 1, rng_inst_matches_bank() rejected the probes with BAD_STATE_E before the WC_RNG_BANK_INST_LOCK_HELD guard in wc_rng_bank_checkin() -- the guard under test -- was reached, leaving it uncovered. With refcount >= 2 the HELD guard is the rejecting path. 2026-09-15 19:19:56 -05:00
Daniel Pouzzner 1691abd053 wolfcrypt/test/test.c: remove redundant gate in random_bank_test(). 2026-09-15 19:19:56 -05:00
Daniel Pouzzner 0fb8d25dfd wolfcrypt/test/test.c: in random_bank_test(), add negative coverage for
wc_rng_bank checkin and seed edge cases from the 20260820 review batch:
duplicate (stale-copy) checkin through both wc_rng_bank_checkin() and
wc_rng_bank_inst_checkin(), asserting BAD_STATE_E without bank mutation;
seedSz == 0 no-op success for an explicit inited bank and for the default
form while a default is set; and seedSz == 0 with no default bank set,
asserting NO_DEFAULT_FOUND_E.
2026-09-15 19:19:55 -05:00
Daniel Pouzzner 8ee7683269 wolfcrypt/src/error.c, wolfssl/wolfcrypt/error-crypt.h:
* add NO_DEFAULT_FOUND_E "No default object registered for request type".
* add missing #include <wolfssl/wolfcrypt/logging.h> in WOLFSSL_DEBUG_TRACE_ERROR_CODES path.
* add __func__ to __GNUC__ WC_ERR_TRACE().

wolfcrypt/src/rng_bank.c, wolfssl/wolfcrypt/rng_bank.h, wolfcrypt/test/test.c:
* add wc_rng_bank_inst.bank for parent access from the children.
* add wc_rng_bank_inst_checkin().
* improve thread safety, error checking, and default bank support in wc_rng_bank_checkout(), wc_local_rng_bank_checkout_for_bankref(), wc_rng_bank_inst_reinit(), wc_rng_bank_seed(), wc_rng_bank_reseed(), and wc_InitRng_BankRef_local().
* orthogonalize common code in wc_InitRng_BankRef() and wc_rng_new_bankref() into wc_InitRng_BankRef_local().

wolfcrypt/test/test.c:
* fix typo in PRINT_HEAP_CHECKPOINT().
* add wc_rng_bank_inst_checkin() tests to random_bank_test(), update expected failure codes, and remove obsolete test clauses.
* add missing !HAVE_FIPS gates in cryptocb_test().

wolfcrypt/src/random.c:
* in WC_RNG_BANK_SUPPORT variant of wc_RNG_GenerateBlock(), use the new wc_rng_bank_inst_checkin(), not wc_rng_bank_checkin().
* tweaks to WOLFSSL_DEBUG_TRACE_ERROR_CODES code wrappers to mollify clang-tidy and -Wconversion.
* fix a spelling error in _InitRng().

linuxkm/lkcapi_sha_glue.c:
* in wc_linuxkm_drbg_generate(), opportunistically reseed once half way to WC_RESEED_INTERVAL and wc_linuxkm_can_block().  Also properly inhibit the recovery call to wc_rng_bank_inst_reinit() if ! wc_linuxkm_can_block().
* refactor wc_mix_pool_bytes() to use wc_RNG_DRBG_Reseed(), and only on the CPU-local RNG.

wolfcrypt/src/asn.c, wolfcrypt/src/curve25519.c, wolfcrypt/src/evp.c, wolfcrypt/src/pkcs7.c, wolfcrypt/src/pkcs12.c, wolfcrypt/src/srp.c: at each existing wc_InitRng(), attempt wc_InitRng_BankRef() if WC_RNG_BANK_DEFAULT_SUPPORT && WC_HAVE_RNG_BANKREF.
2026-09-15 19:19:55 -05:00
JacobBarthelmeh fad92fa095
Merge pull request #11399 from night1rider/ecies-dev-id-change
Ecies dev id change
2026-09-15 14:31:49 -06:00
night1rider 2ed567c29c ECIES: take the device id from the context instead of the ECC key
A context starts in software and only wc_ecc_ctx_set_dev_id() sends the ECIES callback and the KDF, AES and HMAC steps to a device; tests, benchmark, docs and the os-check matrix are updated to match.
2026-09-15 10:18:02 -06:00
JacobBarthelmeh ecc2f75626
Merge pull request #11432 from Frauschi/rsa-ca-pubkey-static-memory
Fixes for static memory builds with WOLFSSL_NO_MALLOC
2026-09-15 10:09:31 -06:00
JacobBarthelmeh 4a9d559022
Merge pull request #11404 from SparkiDev/asn_templ_depth_fix
ASN template depth fix
2026-09-15 09:31:59 -06:00
Tobias Frauenschläger 00b8e2e5a9 Size the wolfCrypt test pool for no-malloc OPENSSL_EXTRA builds
With WOLFSSL_NO_MALLOC there is no system heap to fall back on, so an
allocation the compatibility layer makes with a NULL heap has to come out
of the static pool the test loads. The test only nominated that pool as
the global heap hint when OPENSSL_EXTRA was off, so in the combination of
the two those allocations had no source at all and openssl_test() failed.

Set the hint in that combination too, and give it a pool sized for the
compatibility layer on top of the algorithm tests. gTestMemory was sized
for the wolfCrypt tests alone and those allocations exhausted it - first in
wolfSSL_CRYPTO_malloc(), then, as the pool was enlarged, further along in
wolfSSL_X509_load_certificate_file(). Every other configuration keeps the
size it had.

The new arm goes ahead of the FrodoKEM and ML-DSA arms rather than after
them, because those fire first for exactly the builds that need the most.
With --enable-mldsa the 576 KB arm won and the RSA test died with -125, and
1 MB only moved the failure to openssl_pkey1_test(), where an exhausted pool
surfaces as a NULL from wolfSSL_X509_get_pubkey() and no error code at all.
FrodoKEM fails the same way on its own 1 MB arm. Both pass at 2 MB, so the
arm asks for 2 MB when either is enabled and 1 MB otherwise.

Claim the hint only when it is unset, and drop it only while it is still
ours. Nothing in tree installs one before wolfcrypt_test() runs, but under
OPENSSL_EXTRA the hint is never handed back, so a program embedding
wolfcrypt_test() as a smoke test would otherwise lose its own pool for the
rest of the process. This is the first-wins rule the examples already use.

The matching teardown stays restricted to !OPENSSL_EXTRA on purpose.
gTestMemory has static storage duration, so the hint cannot dangle, and
testsuite runs the echo server after wolfcrypt_test() returns: the echo
server has no pool of its own, and this is the one that outlives it.

testsuite/testsuite.test now passes with --enable-staticmemory
-DWOLFSSL_NO_MALLOC. scripts/unit.test still fails there, at seven API
tests this change does not address.

BENCH_EMBEDDED gets a #error rather than the enlarged pool. That combination
is self-contradictory - openssl_pkey0_test() is not gated on BENCH_EMBEDDED, so
it still asks for about 1 MB, which is not something to hand a target that has
declared itself embedded. Refusing at build time with the override named beats
either silently reserving a megabyte or failing at run time in RSA_new(), which
is what a 14 KB pool does today. WOLFSSL_STATIC_MEMORY_TEST_SZ remains the
override and is checked first, so such a target can still pick its own size.

The arm is also restricted to !WOLFCRYPT_ONLY. The compatibility layer tests
are gated on !WOLFCRYPT_ONLY themselves, so a crypt-only build never runs
openssl_pkey0_test() and has no reason to reserve a megabyte for it - and
with BENCH_EMBEDDED it met the #error above over a test it does not compile.
Crypt-only keeps the size it had.

Pin the behaviour the asn.c fix restores while it is here: cert_no_malloc_test()
only asserted the in-place layout under WC_ASN_NO_HEAP, so nothing covered the
copy-out side. Add the mirror assertion - pubKeyStored set, publicKey outside
the source DER. It fails on the pre-fix guard and passes after it, and unlike
fill_signer_twice_test() it is not gated on NO_FILESYSTEM, which a real
static-memory target turns off. Carry ParseCert()'s whole predicate rather
than WC_ASN_NO_HEAP alone: the copy-out is also skipped under
NO_WOLFSSL_CM_VERIFY without WOLFSSL_DYN_CERT, and the assertion must not
claim otherwise there.

The same goes for NO_RSA and NO_SHA. Both openssl_pkey0_test() and
openssl_pkey1_test() compile their bodies away without either one, and
openssl_test() alone then fits the sizes the old ladder gives it:
--disable-rsa with BENCH_EMBEDDED passes the whole suite on the 14000-byte
arm, and without BENCH_EMBEDDED it passes on the 160000-byte arm rather
than reserving a megabyte. Excluding the arm reaches both of those;
narrowing only the #error would have left the plain build at 1 MB and
handed the embedded one the same megabyte the #error exists to refuse.
2026-09-15 16:15:14 +02:00