Skip to content

20260807-linuxkm-ed-pqc-glue - #11180

Open
douzzer wants to merge 43 commits into
wolfSSL:masterfrom
douzzer:20260807-linuxkm-ed-pqc-glue
Open

20260807-linuxkm-ed-pqc-glue#11180
douzzer wants to merge 43 commits into
wolfSSL:masterfrom
douzzer:20260807-linuxkm-ed-pqc-glue

Conversation

@douzzer

@douzzer douzzer commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

src/pk_ec.c: fix identicalInnerCondition in wolfSSL_ECDH_compute_key().

wolfcrypt/src/ecc.c: fix identicalInnerCondition in _ecc_import_x963_ex2().

wolfcrypt/src/md5.c: fix MSAN-detected unaligned access in Transform().

wolfcrypt/benchmark/benchmark.c: smallstack refactor of bench_chacha20_poly1305_aead().

wolfssl/openssl/hmac.h: add missing !OPENSSL_COEXIST gate around #define HMAC_MAX_MD_CBLOCK.

wolfssl/wolfcrypt/memory.h: add configuration consistency asserts around DEBUG_VECTOR_REGISTER_ACCESS*.

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().
  • refactor bare XMALLOC in aeskeywrap_test() using WC_*_VAR*(), and implement associated error handling and propagation.
  • 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.

linuxkm/lkcapi_ecdh_glue.c: implement ecdh-nist-p521 driver.

linuxkm/lkcapi_ecdsa_glue.c:

  • hoist LINUXKM_ECC192 setup into lkcapi_glue.c (used by both lkcapi_ecdh_glue.c and lkcapi_ecdsa_glue.c).
  • use LINUXKM_ECC521, not HAVE_ECC521, as the pivot for gating in P521.

linuxkm/lkcapi_ed_glue.c: implement LKCAPI glue logic for EdDSA-25519 and -448.

linuxkm/lkcapi_lms_glue.c: implement LKCAPI glue logic for LMS/HSS (RFC 8554, SP 800-208).

linuxkm/lkcapi_xmss_glue.c: implement LKCAPI glue logic for XMSS/XMSS^MT (RFC 8391, SP 800-208).

linuxkm/lkcapi_mlkem_glue.c: implement LKCAPI glue logic for FIPS 203 ML-KEM, supporting both roles (encapsulation/initiator, decapsulation/responder).

linuxkm/lkcapi_mldsa_glue.c: implement LKCAPI glue logic for FIPS 204 mldsa44, mldsa65, and mldsa87, with both sign and verify operations.

linuxkm/lkcapi_slhdsa_glue.c: implement LKCAPI glue logic for FIPS 205 SLH-DSA (all parameter sets).

linuxkm/lkcapi_glue.c:

  • add setup for LINUXKM_ECC192, adopted from lkcapi_ecdsa_glue.c, and add setup for LINUXKM_ECC521.
  • add inclusion, registration, and deregistration, for EdDSA, ML-DSA, ML-KEM, SLH-DSA, LMS, and XMSS.

configure.ac: add LKCAPI handling for EdDSA, ML-DSA, ML-KEM, SLH-DSA, LMS, and XMSS.

linuxkm/x86_vector_register_glue.c, wolfcrypt/src/wc_port.c, linuxkm/linuxkm_wc_port.h:

  • allow vector registers in softirq contexts on the idle process.
  • rename {allocate,free}wolfcrypt_linuxkm_fpu_states() to wc_linuxkm{allocate,free}_svr_states().
  • rename wc_linuxkm_fpu_() to wc_linuxkm_svr_().
  • rename struct wc_thread_fpu_count_ent to wc_thread_svr_count_ent.
  • add wc_thread_svr_count_ent.reserved_at and WC_SVR_SLOT_AGE_MS(), and set .reserved_at on each outermost save, and leverage them for more informative log output.
  • rename WC_FPU_COUNT_MASK and WC_FPU_INHIBITED_FLAG to WC_SVR_COUNT_MASK and WC_SVR_INHIBITED_FLAG.
  • in wc_linuxkm_free_svr_states(), inhibit deallocation entirely if any slots are still occupied (a small one-time leak is much better than a near-certain crash).
  • add WC_SVR_FREE_SLOT_PID, WC_SVR_IDLE_PID, and WC_SVR_PID_SLOT_ID(), allowing representation of the idle process (one per CPU, all PID 0 in current kernels) in the .pid member.
  • in wc_linuxkm_svr_state_assoc*(), wc_can_save_vector_registers_x86(), and wc_save_vector_registers_x86(), accommodate WC_SVR_IDLE_PID, allowing calls from softirq contexts on the idle process.
  • add wc_svr_disallowed_count_reset(), wc_svr_disallowed_count_current(), and wc_svr_disallowed_count_increment(), for auditing of refused vector saves.
  • add WC_SVR_BH_HELD_FLAG, use it to track and restore local_bh_disable(), inhibit local_bh_disable() when irqs_disabled(), and use softirq_count(), not preempt_count(), to confirm that local_bh_disable() was called successfully and appropriately.

linuxkm/linuxkm_wc_port.h:

  • reduce WC_LINUXKM_MAX_NS_WITHOUT_YIELD from 1 second to 25 ms for better kernel citizenship.
  • add WC_DEBUG_FORCE_KERNEL_SETTINGS for inhibiting #errors on unsupported configurations.
  • add __extension__ annotation to macros that need it.
  • add wc_svr_disallowed_count_reset() and wc_svr_disallowed_count_current().
  • fix CAN_SAVE_VECTOR_REGISTERS() to honor DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_{ON,OFF}.
  • add WC_RELAX_LONG_LOOP() to DEBUG_VECTOR_REGISTER_ACCESS_ALWAYS_OFF variant of SAVE_VECTOR_REGISTERS2().
  • allow for fully user-supplied SAVE_VECTOR_REGISTERS() and friends.

linuxkm/module_hooks.c:

  • add WOLFSSL_DEBUG_TRACE_ERROR_CODES coverage for all system error codes used by module_hooks.c and its includes.
  • implement double-run wolfCrypt_IntegrityTest_fips() and wc_RunAllCast_fips() in WC_C_DYNAMIC_FALLBACK configurations, once with acceleration on (leveraging fallback instrumentation to fail the module if any fallbacks occur), and once with it forced off using DISABLE_VECTOR_REGISTERS().

linuxkm/lkcapi_aes_glue.c: implement WC_LINUXKM{GCM,XTS}SVR_BATCH, batching several chunks within a single SAVE_VECTOR_REGISTERS2() bracket (entails adding WALK_ATOMIC to calls that affect walk dynamics during the locked batches).

tested with

wolfssl-multi-test.sh ... pr-check

and numerous kernel-oriented scenarios.

@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown

MemBrowse Memory Report

gcc-arm-cortex-m0plus

  • FLASH: .text +280 B (+0.4%, 67,135 B / 262,144 B, total: 26% used)

gcc-arm-cortex-m3

  • FLASH: .text +236 B (+0.2%, 125,887 B / 262,144 B, total: 48% used)

gcc-arm-cortex-m4

  • FLASH: .rodata.CSWTCH.1 +4 B, .rodata.str1.1 +46 B, .text +256 B (+0.1%, 204,577 B / 262,144 B, total: 78% used)

gcc-arm-cortex-m4-baremetal

  • FLASH: .text +256 B (+0.4%, 69,603 B / 262,144 B, total: 27% used)

gcc-arm-cortex-m4-crypto-only

  • FLASH: .rodata.CSWTCH.1 +4 B, .rodata.str1.1 +46 B, .text +768 B (+0.5%, 178,780 B / 262,144 B, total: 68% used)

gcc-arm-cortex-m4-dtls13

  • FLASH: .text +256 B (+0.1%, 185,852 B / 1,048,576 B, total: 18% used)

gcc-arm-cortex-m4-min-ecc

  • FLASH: .text +192 B (+0.3%, 64,453 B / 262,144 B, total: 25% used)

gcc-arm-cortex-m4-openssl-compat

  • FLASH: .rodata +48 B, .text +896 B (+0.1%, 780,356 B / 1,048,576 B, total: 74% used)

gcc-arm-cortex-m4-pkcs7

  • FLASH: .rodata.CSWTCH.1 +4 B, .rodata.str1.1 +46 B, .text +256 B (+0.1%, 217,376 B / 262,144 B, total: 83% used)

gcc-arm-cortex-m4-pq

  • FLASH: .rodata +48 B, .text +320 B (+0.1%, 300,620 B / 1,048,576 B, total: 29% used)

gcc-arm-cortex-m4-rsa-only

  • FLASH: .rodata +48 B, .text +768 B (+0.2%, 331,488 B / 1,048,576 B, total: 32% used)

gcc-arm-cortex-m4-sp-math

  • FLASH: .text +192 B (+0.3%, 64,453 B / 262,144 B, total: 25% used)

gcc-arm-cortex-m4-tls12

  • FLASH: .text +192 B (+0.2%, 126,643 B / 262,144 B, total: 48% used)

gcc-arm-cortex-m4-tls13

  • FLASH: .rodata.CSWTCH.1 +4 B, .rodata.str1.1 +46 B, .text +320 B (+0.2%, 241,363 B / 262,144 B, total: 92% used)

gcc-arm-cortex-m7

  • FLASH: .rodata.CSWTCH.1 +4 B, .rodata.str1.1 +46 B, .text +256 B (+0.1%, 204,577 B / 262,144 B, total: 78% used)

gcc-arm-cortex-m7-pq

  • FLASH: .rodata +48 B, .text +320 B (+0.1%, 301,516 B / 1,048,576 B, total: 29% used)

gcc-arm-cortex-m7-tls13

  • FLASH: .rodata.CSWTCH.1 +4 B, .rodata.str1.1 +46 B, .text +256 B (+0.1%, 241,363 B / 262,144 B, total: 92% used)

linuxkm-pie

  • Data: __patchable_function_entries +632 B (+2.4%, 27,464 B)

linuxkm-standard

  • Data: __patchable_function_entries +616 B (+1.2%, 50,248 B)

stm32-sim-stm32h753

  • FLASH: .text -524 B (-0.3%, 187,684 B / 2,097,152 B, total: 9% used)

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #11180

Scan targets checked: linuxkm-bugs, linuxkm-src, wolfcrypt-bugs, wolfcrypt-port-bugs, wolfcrypt-rs-bugs, wolfcrypt-src, wolfssl-bugs, wolfssl-src
Findings: 19
18 finding(s) posted as inline comments (see file-level comments below)

Low (1)

wc_rng_bank_seed() accepts instance-selection flags that break its per-index seeding loop

File: wolfcrypt/src/rng_bank.c:934
Function: wc_rng_bank_seed
Category: Cryptographic correctness

The loop passes index n to wc_rng_bank_checkout() but forwards caller flags verbatim. With WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST or WC_RNG_BANK_FLAG_CAN_FAIL_OVER_INST the checkout overrides n, so the same instance is reseeded repeatedly while others never receive the supplied entropy, and the function still returns 0. wc_rng_bank_reseed() rejects both flags at line 985.

Recommendation: Reject WC_RNG_BANK_FLAG_PREFER_AFFINITY_INST and WC_RNG_BANK_FLAG_CAN_FAIL_OVER_INST on entry, as wc_rng_bank_reseed() does.

Referenced code: wolfcrypt/src/rng_bank.c:934-936 (3 lines)


This review was generated automatically by Fenrir. Findings are non-blocking.

Comment thread linuxkm/lkcapi_slhdsa_glue.c Outdated
Comment thread linuxkm/lkcapi_xmss_glue.c Outdated
Comment thread linuxkm/lkcapi_slhdsa_glue.c
Comment thread linuxkm/module_hooks.c Outdated
Comment thread linuxkm/lkcapi_mlkem_glue.c
Comment thread wolfcrypt/test/test.c Outdated
Comment thread wolfcrypt/test/test.c Outdated
Comment thread wolfcrypt/test/test.c
Comment thread wolfcrypt/test/test.c Outdated
Comment thread wolfcrypt/test/test.c
@douzzer
douzzer requested a review from SparkiDev August 15, 2026 00:02
Comment thread linuxkm/lkcapi_slhdsa_glue.c Outdated
Comment thread linuxkm/lkcapi_xmss_glue.c Outdated
Comment thread linuxkm/lkcapi_mlkem_glue.c
Comment thread wolfcrypt/src/rng_bank.c Outdated
Comment thread linuxkm/lkcapi_mldsa_glue.c

@philljj philljj left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir found some issues. Please review them and fix as needed

@philljj philljj assigned douzzer and unassigned philljj Aug 16, 2026
@douzzer
douzzer force-pushed the 20260807-linuxkm-ed-pqc-glue branch 3 times, most recently from ac8dc59 to 4b25e17 Compare August 18, 2026 18:58
Comment thread linuxkm/lkcapi_slhdsa_glue.c
Comment thread linuxkm/module_hooks.c Outdated
Comment thread linuxkm/lkcapi_ed_glue.c
Comment thread linuxkm/lkcapi_slhdsa_glue.c Outdated
Comment thread wolfcrypt/test/test.c Outdated
Comment thread wolfcrypt/src/rng_bank.c Outdated
Comment thread wolfcrypt/test/test.c Outdated
Comment thread wolfcrypt/test/test.c
Comment thread wolfcrypt/test/test.c Outdated
Comment thread wolfcrypt/test/test.c Outdated
Comment thread wolfcrypt/test/test.c
Comment thread wolfcrypt/test/test.c Outdated
douzzer added 20 commits August 24, 2026 17:25
…treat

any occupied slot as an error blocking deallocation, not just slots with
nonzero fpu_state -- a slot with fpu_state still zero is a claim in flight
(pid published, state not yet stored), and freeing under it is a
use-after-free for the claimant.  Reachable via the init-failure unwind
after the random_bytes handlers are installed.  (identified in 20260820
review batch)
(km_ed25519_verify() sig and akcipher editions, km_ed448_verify() ditto),
ForceZero() the transient key copy at the exit label, as the sign paths
already do -- the shallow copy includes k[], which holds live private key
bytes whenever the tfm also holds a signing key -- and correct the two
comments that claimed the copy holds only public material.  (identified in
20260820 review batch)
ctx->pub_set on the seed-expansion branch, which is the only branch that
writes ctx->pub -- a failed raw private key import must not clobber a
public key previously installed by km_mldsa_set_pub().  (identified in
20260820 review batch)
* publish the required destination size through req->dst_len before
  returning -EOVERFLOW at all four short-buffer sites
  (km_mlkem_generate_ek(), km_mlkem_generate_ct(), km_mlkem_ss_decap(),
  km_mlkem_ss_claim()), matching the convention established in
  lkcapi_ecdh_glue.c and the akcipher glues, so KPP callers can size and
  retry;
* in km_mlkem_set_secret(), store locally-set kernel errnos positive
  ("negatized at exit") and negate at the failure tail, normalizing
  wolfCrypt codes to -EINVAL -- sign as the namespace discriminator,
  since range tests cannot discriminate (wolfCrypt and errno ranges
  overlap, e.g. MEMORY_E == -ECANCELED == -125);
* add the diagnostic string to the WC_LINUXKM_MLKEM_PENDING_MAX
  wc_static_assert_if_const().
blockability into can_wait before the DRBG checkout, and gate the
opportunistic reseed and the RNG_FAILURE_E reinit recovery on it --
wc_linuxkm_can_block() is false whenever the affinity lock is held (the
lock callback is SAVE_VECTOR_REGISTERS_MAYBE_INHIBIT()), so the previous
live-sampled guards were unsatisfiable in every reachable state and both
features were dead.  For each of the two blocking operations, bracket it
to restore preemptibility while keeping the instance checked out:
migrate_disable() (CONFIG_SMP && >= 5.11.0 -- on earlier kernels
migrate_disable() is absent or maps to preempt_disable(), so migration
during the operation is simply tolerated there), then
RESTORE_VECTOR_REGISTERS_MAYBE_INHIBITED() keyed on the lock's
_AFFINITY_LOCKED/_VEC_OPS_INH bits, then the blocking operation
preemptibly (wc_rng_bank_inst_reinit()'s WC_RELAX_LONG_LOOP now sees
can_block() true and actually yields), then re-establish the vector state
flavor-matched (SAVE_VECTOR_REGISTERS2() for the affinity hold,
DISABLE_VECTOR_REGISTERS() for the inhibit hold), then migrate_enable().
If re-establishment fails, clear the corresponding lock bits so checkin
doesn't double-restore; the cleared bits also make a failed bracket a
valid entry state for the subsequent one.  Plain (non-atomic) accesses to
drbg->lock are sound across the span: WC_RNG_BANK_INST_LOCK_HELD is
invariantly held, and it is the only bit considered by contending
threads.  (root defect identified in 20260820 review batch; see PR
discussion for why the review's proposed fix -- pre-captured blockability
alone, without releasing the holds -- would have converted the dead code
into sleep-in-atomic / bh-off stalls)
…r message on failed wc_rng_bank_default_checkout(), and rework the error message when wc_linuxkm_drbg_generate() fails.
… USE_INTEL_SPEEDUP, don't expect wc_svr_disallowed_count_current() to increase for wolfCrypt_IntegrityTest_fips() (no AES in it).
…al review of FIPS_OPTEST/LKCAPI coexistence and affinity lock error handling.

in FIPS_optest_trig_handler(), implement assiduous (atomic-based) mutual exclusion with LKCAPI registration.

in wc_rng_bank_checkout(), propagate INTERRUPTED_E from bank->affinity_lock_cb rather than swallowing it -- caller-requested interruption must abort checkout, consistent with the WC_CHECK_FOR_INTR_SIGNALS() handling in the same loop; other affinity lock errors continue to be tolerated (affinity is advisory).
…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.
…-register

selection (ed, mldsa, mlkem, slhdsa, lms, xmss) names an algorithm whose
wolfCrypt implementation is not enabled, matching the existing ecdsa/rsa/
AES-mode guards  (identified in 20260821 review batch)
…448.c,falcon.c}

and wolfcrypt/test/test.c: accept the empty message, passed as (NULL, 0), in all
sign and verify entry points -- RFCs 8032, 8554, and 8391, and FIPS 204, 205,
and (pending) 206, all permit empty messages (in fact RFC 8032's first test
vector is for the empty message).  Guards now reject a NULL message only with a
nonzero length (wc_XmssKey_Verify()/wc_XmssKey_Sign() additionally had an
off-by-one, rejecting mLen == 0 outright, unlike their LMS siblings); after
validation, a NULL message is canonicalized to a readable stand-in so downstream
consumers -- hash updates and crypto callbacks -- never see a NULL pointer.

wc_ed448_verify_msg_ex() additionally gains previously absent validation of sig
and res, which were dereferenced unchecked.

Add empty-message sign/verify roundtrips to lms_test() (spending one of the 2**5
signatures; the exhaustion loop drops to 31 iterations), xmss_test(),
mldsa_param_test(), slhdsa_test_param() (fast 128f set only -- the code path is
parameter-independent and "s"-set signing is costly), and falcon_test().  Add
(NULL, 0) sign/verify probes to ed25519_test() and ed448_test(), pinned
byte-identical to the existing (msg, 0) known answers (EdDSA is deterministic).

tests/api/test_lms_xmss.c: fix test_wc_XmssDecisionCoverage() to probe mLen < 0,
not mLen <= 0, consistent with preexisting probes in
test_wc_LmsDecisionCoverage().
…capi_lms_glue.c,lkcapi_xmss_glue.c}:

accept the empty message at all sig-edition and akcipher-edition entry guards,
and pass it through to wolfCrypt.  A NULL message pointer is now tolerated when
its length is zero, including a NULL src sg in the akcipher sign paths
(scatterwalk_map_and_copy() is a no-op at nbytes == 0).  The akcipher
message-copy machinery already supported zero-length messages by design; only
the entry guards intercepted.  Add empty-message sign/verify roundtrips to
driver self-tests (SLH-DSA: 128f sets only, ahead of the signature regeneration
the downstream checks rely on).

linuxkm/lkcapi_mldsa_glue.c: per kernel setkey semantics (cf.
rsa_set_pub_key(), which frees the entire old key before parsing the new
one), a successful set_pub_key now invalidates any resident private key,
and a successful raw-form set_priv_key invalidates any resident public
key (raw import carries no public key, and wolfCrypt exposes no
pub-from-priv derivation; the seed form installs a matched pair).  Failed
setkeys still change nothing.  Add a rekey sequence to the driver
self-test: sign must fail with -EINVAL after set_pub_key until
set_priv_key is called again.  (identified in 20260821 review batch)
… se050_ed25519_verify_msg() to tolerate null message pointer with zero message length;

add missing arg validation to se050_ed25519_sign_msg().
….c: in the

public-key setters, destroy the resident key state before validating and
importing the new key (per kernel setkey semantics -- cf.  rsa_set_pub_key() and
the new km_lms_set_pub()) -- previously a rejected key left the previously
installed key active, so verification silently continued against a key the
caller was told was not installed.  This also moves km_mldsa_set_pub()'s
invalidation of the resident private key inside a LINUXKM_MLDSA_SIGN gate,
fixing the verify-only build, and subsumes the success-path invalidation.  Add a
rejected-set_pub_key probe to the ML-DSA driver self-test: after a rejected key,
verify must fail keyless rather than succeed against the stale key.  (identified
in 20260824 review batch)
accessor and reseed scheduling services

Give outside-the-boundary consumers defined service interfaces for previously
missing semantics, avoiding any need for reaching into WC_RNG/DRBG internals
for.

* wc_RNG_GetStatus(): read-only health-status accessor.

* wc_RNG_DRBG_Present(): discriminates the HAVE_INTEL_RDRAND
  no-DRBG instantiation shape.

* wc_RNG_DRBG_GetReseedCtr(): read-only reseed counter accessor; no
  DRBG reports 0 (never due), so callers need no special-casing.
  Adds sentinel-guarded wc_drbg_reseed_ctr_t (word64, word32 when
  !WORD64_AVAILABLE) tracking struct DRBG_internal.

* wc_RNG_DRBG_ScheduleReseed(): drive reseedCtr to
  WC_RESEED_INTERVAL, forcing reseed on the next generate.
  Deliberately set-to-threshold only -- a general setter would be a
  mandatory-reseed-bypass primitive.  Compile-time assert that
  WC_RESEED_INTERVAL fits a 32-bit counter when !WORD64_AVAILABLE.

* wc_RNG_DRBG_Reseed_Uncredited(): wc_RNG_DRBG_Reseed() semantics
  with reseedCtr preserved (save/restore in-boundary) -- the
  SP 800-90A additional-input concept via the reseed derivation, for
  mixing caller material without entropy credit.

* wc_RNG_DRBG_Reseed_Now() (!CUSTOM_RAND_GENERATE_BLOCK): immediate
  reseed from the module's own seed source, identical
  gather/health-test/apply/counter/status semantics to the
  WC_RESEED_INTERVAL backstop reseed; optional nonce rides the same
  10.1.1.3 transition as uncredited additional input, via new
  (additional, additionalSz) pass-through in PollAndReSeed().
state exclusively through the new random.c services; relocate the
legacy direct-access mechanism to a pre-v7-FIPS-only compat block.

wc_rng_bank_checkout() reseed-due divert and out-of-service gates,
wc_rng_bank_seed(), and wc_rng_bank_reseed() now use wc_RNG_GetStatus()
/ wc_RNG_DRBG_Present() / wc_RNG_DRBG_GetReseedCtr(); the reseed walk
uses wc_RNG_DRBG_Reseed_Now() when waiting is allowed (no more
scratch-generate counter forcing) and wc_RNG_DRBG_ScheduleReseed() for
the non-waiting arm and to preserve the pending-reseed contract after a
failed forced reseed.

wc_rng_bank_inst_reinit() failure now marks the instance out of
service via wc_FreeRng() (deterministic WC_DRBG_NOT_INIT) instead of
writing rng->status directly; _InitRng() has platform failure arms
(async devctx, Versal TRNG) that return nonzero with status
WC_DRBG_OK, so the explicit marking must stay, but it can be
service-mediated.  No consumer distinguishes WC_DRBG_FAILED from
other non-OK statuses.

New WC_RNG_BANK_FLAG_SEED_UNCREDITED (1<<6): wc_rng_bank_seed()
mixes via wc_RNG_DRBG_Reseed_Uncredited() per instance (and masks
the flag from its checkout calls); wc_rng_bank_reseed() rejects it
(bank reseeds are always from the module's own source, always
credited).

rng_bank.h gains a HAVE_FIPS && FIPS_VERSION3_LT(7,0,0) compat block:
the historic three-combination reseedCtr/DRBG-null macros relocated
verbatim, plus same-named static WC_INLINE fallbacks for the six
services, so call sites are uniform across boundary versions and
direct state access is confined to one labeled block that exists only
where frozen boundaries cannot supply services.  Legacy Reseed_Now is
schedule + 4-byte generate (counter lands 2 on success; nonce is a
separate follow-on uncredited transition; still-at-threshold-guarded
counter restore on failure).
kernel-supplied seed material as uncredited, per mainline
crypto/drbg.c

Delete the local copy of the reseedCtr/DRBG-null macros (now in
rng_bank.h's pre-v7 compat block); zero direct DRBG state access
remains on the v7 path.

wc_linuxkm_drbg_generate(): generate-op src now mixes via
wc_RNG_DRBG_Reseed_Uncredited() (crypto/drbg.c passes the same input
as SP 800-90A additional input, never crediting it); the
opportunistic early reseed observes wc_RNG_DRBG_GetReseedCtr() and
calls wc_RNG_DRBG_Reseed_Now() inside the existing SVR
release/reestablish bracket -- counter save/poke/restore and the
scratch generate are gone, since Reseed_Now resets the counter iff
the reseed succeeds.

wc_linuxkm_drbg_seed(): pass WC_RNG_BANK_FLAG_SEED_UNCREDITED, so
crypto_rng_reset() with caller data no longer resets reseed
schedules.  wc_mix_pool_bytes(): wc_RNG_DRBG_Present() +
wc_RNG_DRBG_Reseed_Uncredited(), dropping the counter save/restore.
log panic-adjacent, when the FIPS RNG cannot serve
(WOLFSSL_LINUXKM_GET_RANDOM_NO_FALLTHROUGH)

HAVE_FIPS now implies WOLFSSL_LINUXKM_GET_RANDOM_NO_FALLTHROUGH (no
opt-out).  Under it, wc_get_random_bytes_user() and
wc_extract_crng_user() return -EIO -- final, no fallthrough to native
randomness -- on checkout or generate failure, with
pr_emerg_ratelimited records.  In a FIPS setting an RNG failure in a
must-succeed RNG call is a system-unusable condition; emerg-over-
panic() is deliberate, so the operator can restart in a controlled
fashion (glibc getrandom()/arc4random consumers go fatal on -EIO,
which is the intended blast radius).

wc__get_random_bytes() remains must-succeed in every flavor -- the
kernel patch's dispatch point serves the request from the native
DRBG on any nonzero return, honoring the get_random_bytes()
unconditional-success contract -- but the event is now recorded
loudly (emerg under the knob, err otherwise, never silent).
Checkout-failure logging on the user paths is un-gated from
WC_VERBOSE_RNG; in-loop generate failures become ratelimited (the
paths are unprivileged-hammerable).

wc_linuxkm_drbg_generate()'s tail conversion becomes -EIO (RNG-
failure class) instead of -EINVAL, keeping the slen>0 arm's
argument-class -EINVAL distinct; no wolfCrypt-domain code reaches
the kernel interface.  wc_extract_crng_user()'s tail is reworked to
convert live generate failures (previously the raw wolfCrypt-mapped
code leaked out, and only an unreachable ret==0 arm was handled),
excluding -EFAULT so first-block copy_to_user() faults keep their
honest code; partial-copy-then-failure returns final -EIO in both
flavors, required because the -ECANCELED fallthrough contract
promises an untouched iterator.
wolfssl/wolfcrypt/{rsa,ecc,curve25519}.h: add wc_RsaClearRNG(),
wc_ecc_clear_rng(), wc_curve25519_clear_rng().

Companions to the three existing RNG setters (the complete set in
wolfcrypt), so a caller can detach a key's RNG association through a
dedicated API; the setters are unchanged, in particular
wc_RsaSetRNG() retains BAD_FUNC_ARG on a NULL rng.  Each companion
is declared beside its setter under the same gate and mirrors its
shape (wc_ecc_clear_rng() keeps the success-no-op stub arm when
!ECC_TIMING_RESISTANT).  A cleared key fails RNG-requiring
operations safely: MISSING_RNG_E on RSA blinding and ECC
timing-resistant paths, BAD_FUNC_ARG from the RNG service on
curve25519 blinding; the RSA pairwise consistency test falls back to
a locally instantiated RNG.  For each key type the member written is
the sole storage site -- no subordinate object holds a copy -- so
clearing the top level detaches everything.

Enables checkout / set / operate / clear / checkin usage of
wc_rng_bank instances against per-object RNG consumers.  FIPS
wrapper plumbing for the three new symbols to follow with the DRBG
service wrappers.

wolfcrypt/src/ecc.c: in wc_ecc_encrypt_ex() and wc_ecc_decrypt(),
restore privKey->rng after lending ctx->rng for the operation

Both functions implanted ctx->rng into privKey->rng when the ctx had
an RNG and the key did not (ECC_TIMING_RESISTANT needs it in the
shared-secret point multiply), and never removed it -- the caller's
key left the call holding a borrowed pointer into the ecEncCtx's
RNG, dangling once the ctx or its RNG is freed, and silently
re-attaching an RNG behind the back of any caller practicing
set/operate/clear hygiene.  Track the lend (lentRng) and restore
privKey->rng = NULL at every post-implant exit, including both
WOLFSSL_SMALL_STACK allocation-failure arms and both tails.  Callers
that pre-set the key's RNG are unaffected.
@douzzer
douzzer force-pushed the 20260807-linuxkm-ed-pqc-glue branch from c2b5324 to 109ee77 Compare August 24, 2026 22:25
reinit brackets, release and re-establish the scheduling locks
per-level -- an affinity-locked checkout with
WC_RNG_BANK_FLAG_NO_VECTOR_OPS (from the caller's flags or bank-wide
bank->flags) holds BOTH the affinity save and the vector-ops inhibit,
and the single flavor-sniffing release only popped the innermost level,
while the re-establishment failure arm cleared both lock bits including
the never-released affinity hold, leaving checkin unable to unwind it
(leaked bh-off).  Release now mirrors wc_rng_bank_inst_checkin()
(innermost first), re-establishment mirrors wc_rng_bank_checkout()
(acquisition order), and each level's failure clears only its own bit.
(identified in 20260824 review batch)
empty-message wc_SlhDsaKey_Sign() probe with
PRIVATE_KEY_UNLOCK()/PRIVATE_KEY_LOCK(), as its neighbors do.
(identified in 20260824 review batch)
Comment thread linuxkm/lkcapi_sha_glue.c
Comment thread wolfcrypt/test/test.c
@douzzer

douzzer commented Aug 25, 2026

Copy link
Copy Markdown
Contributor Author

retest this please
(numerous unexplained aborts, no failures)

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #11180

Scan targets checked: linuxkm-bugs, linuxkm-src, wolfcrypt-bugs, wolfcrypt-port-bugs, wolfcrypt-rs-bugs, wolfcrypt-src, wolfssl-bugs, wolfssl-src

Fenrir result: Approved ✅

No new issues found in the changed files.

Advisory only — this automated result does not count as a GitHub approval.

@wolfSSL-Fenrir-bot
wolfSSL-Fenrir-bot dismissed stale reviews from themself August 25, 2026 04:57

Fenrir's latest completed scan found no issues; clearing the prior automated change request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants