Follow up to PR #10450 with some minor fixes:
* FIPS 205 numbering: slh_sign is §10.2.1 Alg 22; slh_verify is Alg 24;
hash_slh_verify is Alg 25 (impl comments and doxygen).
* Widen wc_SlhDsaKey_SignHashWithRandom's addRnd to const byte* to
match wc_SlhDsaKey_SignWithRandom.
* Make the SLHDSA_PHMSG_MAX_LEN invariant explicit with a named
SLHDSA_LARGEST_APPROVED_PHM_LEN constant and a wc_static_assert.
* SHAKE128/SHAKE256 round-trip and length-rejection coverage for both
SignHash and VerifyHash.
* Doxygen: briefs for the five DER encode/decode APIs; accurate
decoder failure-rollback wording; tighter return-code lists for
Verify and VerifyMsg.
* ChangeLog: silent-failure caveat for raw messages whose length
happens to equal the digest size of the chosen hashType.
The memLock mutex and #include <pthread.h> in mem_track.h were
declared under #ifdef DO_MEM_LIST (Linux/macOS/Zephyr only), but
referenced under the broader guard
!defined(SINGLE_THREADED) && \
(defined(DO_MEM_LIST) || defined(DO_MEM_STATS))
Since DO_MEM_STATS is defined whenever WOLFSSL_TRACK_MEMORY +
USE_WOLFSSL_MEMORY are set without WOLFSSL_STATIC_MEMORY, any
non-Linux/Mac/Zephyr multi-threaded build failed to compile with
implicit pthread_mutex_lock declarations and undeclared memLock.
Replace the raw pthread mutex with wolfSSL's portable mutex API
(wc_InitMutex / wc_LockMutex / wc_UnLockMutex / wc_FreeMutex) so
locking works on every platform wolfSSL already ports to.
InitMemoryTracker now calls wc_InitMutex before
wolfSSL_SetAllocators installs TrackMalloc, guarded by a
memLockInit flag for idempotency. CleanupMemoryTracker calls
wc_FreeMutex after restoring the default allocators so no
in-flight allocation races a freed mutex. The four mutex guards
in TrackMalloc/TrackFree and the two in InitMemoryTracker/
ShowMemoryTracker are unified on the same condition as the
memLock declaration itself.
ZD #21763
wc_SlhDsaKey_{Sign,Verify}Hash* previously accepted the raw message and
performed the pre-hash internally. They now require the caller to hash the
message first and pass the resulting digest -- the functions no longer call
wc_*Hash() themselves and feed the supplied digest directly into the M'
construction. Parameters are renamed from msg/msgSz to hash/hashSz to reflect
this, and hashSz is validated against wc_HashGetDigestSize(hashType) per
FIPS 205 Section 10.2.2 (32 for SHAKE128, 64 for SHAKE256), returning
BAD_LENGTH_E on mismatch.
This matches ML-DSA's wc_dilithium_{sign,verify}_ctx_hash, NIST ACVP
signatureInterface=external / preHash=preHash vectors, and other libraries
(OpenSSL HASH-ML-DSA, leancrypto, mldsa-native). It also enables distributed
signers and HSM-style flows where the digest is computed separately from the
signing operation.
Migration: callers must now hash the message before invoking these APIs;
passing the raw message will either fail length validation or produce
signatures over the wrong input. The M'-supplied wc_SlhDsaKey_SignMsg* /
VerifyMsg family (FIPS 205 internal interface, Algorithms 19/20) is
unchanged but gains stricter input validation and doxygen coverage.
Remove WC_LMS_PARM_NONE as it serves no purpose.
Change sig_len from a 16-bit value to a 32-bit value in the parameters.
Added wc_LmsKey_SetParameters_ex() and wc_LmsKey_GetParameters_ex() to
handle hash algorithm.
Change mass ForceZeros to smaller amounts with XMEMSET and setting to
NULL or default valus.
Allow signing of empty message.
Other minor fixes.
Fix API tests to work when WOLFSSL_LMS_MAX_HEIGHT/WOLFSSL_LMS_MAX_LEVELS
are/is defined.
Copilot fixes:
- atmel.c: ATCA_ENABLE_DEPRECATED I2C path now uses ATECC_I2C_ADDR
instead of slave_address=1 (matches the non-deprecated path).
- atmel.c: capture and propagate atmel_createHandles() return value;
abort init via WC_HW_E if handle creation fails.
- atmel.h: include calib_aes_gcm.h with the same <calib/...> form used
for calib_command.h so a single -I (.../include or
.../include/cryptoauthlib) resolves both.
- configure.ac: drop the duplicated AM_CONDITIONAL([BUILD_CRYPTOAUTHLIB])
(kept only in the consolidated section near the end).
- settings.h: remove leftover commented-out '#ifdef WOLFSSL_ATECC508A'.
- benchmark.c: drop the broken TA100 wc_RsaSSL_Verify branch (it passed
message/enc as if they were sig/out).
- test.c: stop calling atmel_ecc_free() with the slot-TYPE enum
constants; wc_ecc_free(userA/userB) already releases the allocated
slots.
- ecc.c (microchip_curve_id_for_key): switch on key->dp->id, not size,
so SECP256K1 / BRAINPOOLP256R1 are not silently mapped to SECP256R1.
Helper is now defined for ATECC508A/608A as well, fixing the
TA100-only gating that broke ATECC builds.
- ecc.c (_ecc_make_key_ex): keep ATECC508A/608A's curve check at
SECP256R1-only (hardware does not support the wider curve set);
TA100 retains the multi-curve list.
Fenrir fixes:
- ecc.c (wc_ecc_init_ex): under TA100 + ALT_ECC_SIZE the pubkey x/y/z
pointers must be aimed at key->pubkey.xyz[] (with alt_fp_init) before
mp_init_multi - otherwise mp_init_multi dereferenced NULL.
- atmel.c (atmel_get_rev_info): check atcab_wakeup return and bail out
via atmel_ecc_translate_err before calling atcab_info.
- atmel.c (atmel_ecc_create_pms, TA100+ECDH_ENC): pass
MAP_TO_HANDLE(slotId) (the ephemeral private-key handle) into
talib_ecdh_compat instead of MAP_TO_HANDLE(slotIdEnc).
- atmel.c (wc_Microchip_rsa_create_key): on any failure after the first
talib_create_element succeeds, delete the previously created
handle(s) and clear rKeyH/uKeyH so device elements are not leaked.
- aes.c (wc_AesGcmEncrypt / wc_AesGcmDecrypt TA100 fast paths): replace
'(authInSz + sz) <= MAX' with bounds on each operand individually so
word32 wraparound cannot bypass the 996-byte hardware limit.
- rsa.c (RsaPrivateDecryptEx): drop the TA100 RSA_PUBLIC_DECRYPT
short-circuit. wc_Microchip_rsa_verify expects (digest, digestLen,
sig, sigLen, ...) and the verified flag must be honored; the proper
TA100 fast-path already lives in wc_RsaPSS_CheckPadding_ex2.
Wire the stateful hash-based signature schemes HSS/LMS (RFC 8554) and
XMSS / XMSS^MT (RFC 8391) into the X.509 cert-verification path per
RFC 9802.
asn:
- Register id-alg-hss-lms-hashsig (1.2.840.113549.1.9.16.3.17),
id-alg-xmss-hashsig (1.3.6.1.5.5.7.6.34) and id-alg-xmssmt-hashsig
(1.3.6.1.5.5.7.6.35) in oid_sum.h, asn.c and asn1_oid_sum.pl.
- Plumb the new keyOIDs through GetCertKey, SigOidMatchesKeyOid,
HashForSignature, FreeSignatureCtx and ConfirmSignature so leaf
and CA certificates parse, load and verify end-to-end.
- Rename IsSigAlgoECC -> IsSigAlgoNoParams; the function has tested
"AlgorithmIdentifier omits NULL parameters" since PQC algos were
added, and HSS/LMS + XMSS only made the original name more
misleading.
wc_lms / wc_xmss:
- Add wc_XmssKey_ImportPubRaw_ex which derives parameters from the
4-byte OID prefix at the start of the raw public key, taking an
is_xmssmt hint to disambiguate the overlapping XMSS / XMSS^MT OID
spaces.
- Extend wc_LmsKey_ImportPubRaw with the same auto-derive from
u32str(L) || lmsType || lmOtsType when key->params is NULL; this
also fixes a latent NULL-deref when the legacy precondition was
violated.
- Reject WC_*_STATE_OK in both ImportPubRaw paths so re-importing
on a private-key-loaded handle can't desync priv/pub.
- Tighten wc_XmssKey_Verify's length check to strict equality,
matching wc_LmsKey_Verify and the documented contract of using
wc_XmssKey_GetSigLen for the buffer size.
tests / fixtures:
- Bouncy Castle 1.81 fixtures in certs/lms and certs/xmss covering
every supported parameter set, plus CA->leaf chains per family
and one BC-native LMS fixture as a cross-impl interop gate.
- New api tests verify each fixture end-to-end, tamper TBS and
signature bytes, exercise the wolfCrypt-level negative paths
(NOT_COMPILED_IN, BUFFER_E, BAD_FUNC_ARG, BAD_STATE_E, OID/family
mismatch, partial-write invariants, lenient VERIFYONLY re-import,
strict sigLen check) and confirm the outer signatureAlgorithm
OID is rejected when it disagrees with the SPKI in both
XMSS<->XMSS^MT directions.
wolfcrypt/src/asn.c, wolfssl/wolfcrypt/asn.h, src/ssl.c, wolfssl/ssl.h: move wolfssl_local_IsValidFQDN() from ASN.1 layer (where it has no users and is gated out in lean PSK builds) to TLS layer (where its users are);
scripts/crl-revoked.test: use `cp --symbolic-link` opportunistically but fall back to `cp -p`.
Only have the public key in the ML-DSA key object when verify-only.
Be able to leave out SHA-3 APIs when only needing SHAKE.
Fix ML-DSA testing to only have data for compiled in parameters.
More checks for public or private key not set.
wc_MlKemKey_Free clears key->flags
wc_MlKemKey_DecodePrivateKey now checks the public key is valid.
wc_MlKemKey_EncodePrivateKey doesn't need calculate hash of public key
as encoding the public key will do this.
EncodePrivateKey/EncodePublicKey now return BAD_STATE_E when flags not
set.
mlkem_kdf, mlkem_check_public, mlkem_xof_absorb pointer parameters are
now const.
Now all mlkem_redistribute_*_rand_avx2 functions are WOLFSSL_LOCAL.
Changed Kyber uses to MlKem.
- x509_str: require CA:TRUE unconditionally in wolfSSL_X509_verify_cert;
verify leaf signature even when verify_cb overrides INVALID_CA
- x509_str: align WOLFSSL_X509_V_ERR_INVALID_CA with OpenSSL value (79)
so OPENSSL_COEXIST builds compile; bump WC_OSSL_V509_V_ERR_MAX to 80
and extend error_test() missing-value table for the new gaps
- asn: reject embedded NUL in dNSName / rfc822Name / URI SAN entries
- internal: re-verify restored ticket peer cert against trust store with
CRL/OCSP checks; clear stale state from session cache on verification
failure
- ticket: bind SNI and ALPN into session ticket via compile-time selected
hash (TICKET_BINDING_HASH_TYPE); reject resumption on mismatch in both
TLS 1.3 and TLS 1.2 paths
- ticket: defer SNI/ALPN binding check until after extensions are parsed
by consolidating into VerifyTicketBinding(), called once after
ALPN_Select in DoTls13ClientHello and DoClientHello; the early
per-call sites ran before extensions were parsed and rejected valid
resumptions in nginx, haproxy, grpc, and CPython integration tests
- ssl_sess: free previous session in wolfSSL_d2i_SSL_SESSION before
overwrite
- examples/client: increase SESSION_TICKET_LEN fallback from 256 to 2048
to support larger tickets
- tests: update SAN NUL fixtures and add parse-time rejection coverage;
add test_tls13_ticket_peer_cert_reverify for CA-removal scenario; skip
it under WOLFSSL_NO_DEF_TICKET_ENC_CB