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
The verify-only SLH-DSA benchmark only had a SHAKE-128s vector, because
that is the only verify-only signature in wolfcrypt/test/test.c. Builds
with only the SHA2 parameter sets showed no SLH-DSA row at all.
Add a SHA2-128s vector: a deterministic, empty-context signature of
"Hello World!" by the existing bench_slhdsa_sha2_128s_key.der. It was
generated with OpenSSL 4.0.3; wolfSSL verifies it, rejects it once a
message bit is flipped, and its own deterministic signature from the
same key is byte-identical. gen-slhdsa-mldsa-certs.sh gains the step
that produces it, and a rerun reproduces the committed files. The pq-all
verify-only benchmark config enables sha2 and requires this row too.
bench_slhdsa_verify() now takes the parameter set and vector. The row
uses the full benchmark's name, SLH-DSA-SHA2-S, and takes its strength
from the public key size, as the full benchmark does. Verify-only
builds accept -slhdsa-sha2-128s when SHA2-128s is built.
Tested on the host with --enable-slhdsa=yes,sha2,verify-only on its
own, with --enable-smallstack and with --disable-rng, with sha2 only,
with SHAKE only and 192f only (no SHA2 row, no warnings), and with the
full sha2 build.
The benchmark measured LMS, XMSS and SLH-DSA verify only after
generating a key and signing with it, so a build with
WOLFSSL_LMS_VERIFY_ONLY, WOLFSSL_XMSS_VERIFY_ONLY or
WOLFSSL_SLHDSA_VERIFY_ONLY compiled the algorithm out of the benchmark
entirely. Targets that only check signatures, such as a boot loader
verifying an image, got no numbers at all.
Verify-only builds now time verify against a fixed vector: LMS
L1_H10_W8, XMSS-SHA2_10_256 and SLH-DSA-SHAKE-128s. The vectors are the
verify-only KATs already in wolfcrypt/test/test.c, stored as binary
files under certs/lms, certs/xmss and certs/slhdsa and emitted into
certs_test.h by gencertbuf.pl. The rows use the same names as the full
benchmark, and a parameter set without a vector, or one that is not
compiled in, is skipped. If loading the key fails, the failing call is
printed and no row is shown.
In a verify-only build, -lms_hss, -xmss_xmssmt(_sha256),
-slhdsa-shake128s and -slhdsa are accepted only when their vector
applies, and the other XMSS and SLH-DSA parameter options are rejected,
so no option silently runs nothing.
Verify needs no RNG, so the asymmetric result printing is built
whenever one of these vectors applies, also with WC_NO_RNG. A
verify-only build with no vector no longer counts as an asymmetric
algorithm. This also fixes an LMS verify-only build with no other
asymmetric algorithm, which failed -Werror on master with an unused
bench_stats_asym_finish(). The SRTP-KDF, scrypt and Argon2 benchmarks
also call it, so it is now built for them too: on master each of them
failed to compile with no asymmetric algorithm, which an LMS
verify-only build used to hide.
The benchmark exits 0 even when verify fails, so a new pq-all CI config
builds all three verify-only with no other asymmetric algorithm and
-Werror=unused-function, runs the benchmark, and fails on any reported
benchmark error, such as a key that does not import, or on a missing
verify row.
Tested on the host with --enable-{lms,xmss,slhdsa}=yes,verify-only on
its own, with --enable-smallstack, with --disable-rng, and with
--enable-all-crypto; with edge configurations where no vector applies
(SLH-DSA 192f only, LMS max height 5, XMSS min hash size 512), both
with --disable-rng and with RNG but no other asymmetric algorithm; with
SRTP-KDF, scrypt or Argon2 as the only such user, with and without an
RNG and with LMS verify-only; and
with --enable-all and the full LMS/XMSS/SLH-DSA build, whose benchmark
output is unchanged. The new CI config passes under
parallel-make-check.py and fails with a corrupted signature byte, a
truncated public key, a missing row and an unused static function.
Three changes aimed at builds where a Falcon-1024-sized structure or an 8KB
stack frame is not affordable.
Levels are now selectable. --enable-falcon=level1 or =level5
(WOLFSSL_NO_FALCON_LEVEL5 / WOLFSSL_NO_FALCON_LEVEL1) builds only the levels
named; naming neither builds both, as before. Every FALCON_MAX_* bound
follows the highest level built rather than always Falcon-1024, so a level-1
only build takes falcon_key from 4120 to 2200 bytes and the verify stack
frame from 4304 to 2224. wc_falcon_set_level() rejects a level that was not
built.
--enable-falcon=dynamic-keys (WOLFSSL_FALCON_DYNAMIC_KEYS), the counterpart of
WOLFSSL_MLDSA_DYNAMIC_KEYS, moves the encoded public and private key to heap
buffers sized for the key's own level, leaving falcon_key at 32 bytes.
wc_falcon_set_level() allocates them, so it can now return MEMORY_E; they are
released, the private one zeroized, by wc_falcon_free() and on a level change.
The allocated length of the private buffer is kept in the key: deriving it
from key->level would zeroize a Falcon-1024 length over a Falcon-512
allocation if a caller had put an out-of-range level in the structure, which
the MC/DC coverage test does deliberately.
The verify working set drops from four n-element buffers to two, which is all
that is ever live at once. The public key is dead once the pointwise product
is formed, so the hashed point is built there instead and reuses it; the
signature polynomial is dead once its squared norm is accumulated, which now
happens before it is lifted in place into that product. wc_falcon_verify_msg
goes from an 8368-byte frame to 4304 at Falcon-1024, and to 2224 in a level-1
only build. Results are unchanged and WOLFSSL_SMALL_STACK still moves the
buffer to the heap.
wc_falcon_set_level() can therefore fail where it could not before, so its
callers check the result, and a failed reallocation leaves the key reading
as empty rather than with a level and no buffers.
The API tests, testwolfcrypt, the benchmark and the signature-group test
follow the levels the build has rather than both. CI runs the full unit
suite on every level-restricted and struct-changing leg, since
--group falcon reaches neither the signature group nor the TLS and ASN
callers of wc_falcon_set_level().
wolfcrypt/src/random.c: allow WC_HAVE_RNG_BANKREF with HAVE_FIPS if WOLFSSL_FIPS_DEV.
wolfssl/wolfcrypt/random.h:
* remove WC_RNG_BANK_SUPPORT from the exclusion list for WC_RNG_LOCK_ATFORK
* pivot WC_HAVE_RNG_BANKREF on WC_RNG_WANT_BANKREF_SUPPORT, with FIPS exclusion.
wolfcrypt/src/rng_bank.c: update wc_InitRng_BankRef_local() and wc_BankRef_Release() to use WC_RNG_FLAG_BANKREF, not WC_DRBG_BANKREF.
wolfssl/wolfcrypt/rng_bank.h: remove backward-compat clause defining WC_HAVE_RNG_BANKREF.
linuxkm/lkcapi_rsa_glue.c: refactor km_rsa_ctx_init_rng() to check ctx->rng.flags, not ctx->rng.status, for bankref status.
configure.ac: in ENABLED_RNG_BANK setup, split out WC_RNG_WANT_BANKREF_SUPPORT as a separate flag, and don't define it if FIPS.
wolfcrypt/benchmark/fips_cast_bench.c: omit bench_pct_slhdsa() if defined(WOLFSSL_SLHDSA_VERIFY_ONLY).
wolfcrypt/test/test.c: in myCryptoDevCb(), add HAVE_INTEL_RDRAND to list of macros enabling use of wc_RNG_GenerateBlock() for WC_ALGO_TYPE_RNG.
linuxkm/Makefile: use bash-4.3-compatible syntax in $(()) expression.
.wolfssl_known_macro_extras: remove unneeded entries.
bench_gmac_internal() passed a literal 0 as useDeviceID to
bench_stats_sym_finish(), so with BENCH_DEVID defined both the software and the
hardware run printed "SW", and bench_stats_add() merged them into one entry
because it keys on that value too. On an accelerator where GMAC goes from
146 KiB/s to 8.7 MiB/s the mislabelling is easy to spot, but the table said the
two were the same measurement.
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.
wc_LmsKey_ExportPubRaw only required key->params to be set. Parameters
are populated by wc_LmsKey_SetParameters, well before wc_LmsKey_MakeKey
or an import produces a public key, so a caller that had merely selected
a parameter set received a buffer full of zeros and a success return.
Require the same OK, VERIFYONLY or NOSIGS state that
wc_LmsKey_ExportPub_ex already enforces, and cover the parameter-only
case in the LMS decision coverage test.
Fixes F-8150.
Move MlKemKey/wc_MlDsaKey and the seed/shared-secret buffers to the heap
using WC_DECLARE_VAR()/WC_ALLOC_VAR_EX()/WC_FREE_VAR_EX() with inline
goto-out failure handling, single exit per function. Frames were 5328
and 8096 bytes against -Werror=frame-larger-than=2048.
Mirror curve25519: keygen, shared secret, make pub and generic
callbacks, wc_curve448_init_ex/new/delete, new wc_curve448_generic
API with scalar clamp checks, WOLF_CRYPTO_CB_ONLY_CURVE448 mode,
TLS devId plumbing, tests (test.c, api unit tests, swdev),
benchmark devId, CI entries.
The config probe now uses the target include path, and ARM assembly builds in
both modes. Documents the ECIES hardware path, drops a dead protocol branch,
declines a zero length message, and builds the ECC request helpers only where
they are called. Benchmark rows no longer claim hardware they cannot reach.