With non-blocking X25519 and an async device, the shared secret pends
and its result comes back through wolfSSL_AsyncPop() in
DoTls13ServerHello() and DoTls13ClientHello(), so an all-zero result
skipped the conversion in TLSX_KeyShare_ProcessX25519_ex() and no
alert was sent. Apply the same conversion at those two pops when the
completed operation belongs to an X25519 key.
Run the low-order key share cases again with an async device when
WOLFSSL_ASYNC_CRYPT is defined.
wc_MlDsaKey_InitId() and wc_MlDsaKey_InitLabel() called
wc_MlDsaKey_SetParams(key, WC_ML_DSA_87) even when their argument
check had failed and the key was never initialized, and ignored its
return value. With ML-DSA-87 compiled in (the default), an argument
error wrote into the caller's uninitialized object, and with the
WC_MLDSA_CACHE_* options or WOLFSSL_MLDSA_DYNAMIC_KEYS it zeroized and
freed whatever pointers that memory held. In builds without
ML-DSA-87 the call failed, so InitId and InitLabel returned 0 with no
parameter set.
Call SetParams only when the key was initialized, return its result,
and use the highest level compiled in, as wc_falcon_init_id() and
wc_falcon_init_label() do with FALCON_MAX_LEVEL.
When the X25519 part of a key share gives an all-zero shared secret,
wc_curve25519_shared_secret_ex() returns ECC_OUT_OF_RANGE_E, and
TLSX_KeyShare_ProcessX25519_ex() passed it on unchanged.
TranslateErrorToAlert() has no case for that code, so a TLS 1.3
handshake was aborted without an alert. Map it to ECC_PEERKEY_ERROR,
as a failed public key check already is, so that an illegal_parameter
alert is sent, as RFC 10024 Section 4.3 requires for the hybrid
groups.
Extend test_tls13_mlkem_bad_key_share with an order-8 X25519 point in
the X25519MLKEM768 ClientHello and ServerHello and in a plain X25519
ServerHello.
Go back to the one-byte sigSz probe for SignWithRandom() with a
(NULL, 0) message in test_wc_SlhdsaDecisionCoverage(), so the test
stays argument-check only. The signing path for (NULL, 0) is covered
in test.c.
Update the Japanese doxygen for SignDeterministic, SignWithRandom,
Sign and Verify to match the English header.
- Source comments: msg may be NULL if msgSz is 0 for the sign and
verify functions, and Sign(), Verify() and slhdsakey_sign_external()
reject a NULL msg only when msgSz is greater than 0.
- Doxygen: note on the msg parameter, and SignDeterministic() returns
BAD_LENGTH_E for a too-small signature buffer.
- test.c: SignDeterministic() with (NULL, 0) must match the signature
for a non-NULL message of length 0.
- test_slhdsa.c: SignWithRandom() with (NULL, 0) and a full-size
signature buffer signs successfully.
wc_SlhDsaKey_SignWithRandom() rejected msg == NULL for any length, so it
and wc_SlhDsaKey_SignDeterministic() returned BAD_FUNC_ARG for an empty
message passed as (NULL, 0), unlike wc_SlhDsaKey_Sign() and Verify().
Use the same check as Sign() and, like Sign(), replace a NULL message
with a one-byte static stand-in before the crypto callback dispatch.
Update the doxygen and source comments, and add tests for the (NULL, 0)
case.
tests/swdev/Makefile localized every swdev symbol except the two entry
points with objcopy --keep-global-symbol, which macOS does not ship. On
Darwin, do the same with a second ld64 relocatable link and
-exported_symbol. The export check strips the Mach-O leading underscore
before comparing. The exported names now live in one SWDEV_EXPORTS list
that feeds both localization commands and the check.
The localization step is picked from configure's host_os rather than
uname, so cross-builds use the target's toolchain.
Add a macOS CI config that builds swdev with WOLF_CRYPTO_CB_ONLY_ED25519,
so make check depends on the ld64-localized swdev object.
The AES implementation chain at the top of aes.c picks one block cipher
backend, and the hardware ports ahead of WOLFSSL_ARMASM in it (STM32,
LTC, ...) store a raw key in aes->key. ECB, the software CTR mode, GCM
(subkey setup and the bulk encrypt/decrypt) and XTS tested
WOLFSSL_ARMASM directly, so with such a port and WOLFSSL_ARMASM both set
they ran the Arm assembly on the raw key and returned wrong output. On
STM32 this hit ECB and CTR (STM32 selects NEED_AES_CTR_SOFT), and GCM
wherever it falls back to software: WOLFSSL_STM32_BARE with a
non-12-byte IV, or parts without STM32_CRYPTO_AES_GCM. e31e158225 had
excluded STM32_CRYPTO for the GCM subkey only.
Define WC_AES_USE_ARMASM in the WOLFSSL_ARMASM branch of the chain and
test it in those places instead of WOLFSSL_ARMASM. The ports keep their
own block functions there, so ECB goes through wc_AesEncrypt() and
wc_AesDecrypt(), CTR through the port's block transform, GCM through
AES_GCM_encrypt_C() and AES_GCM_decrypt_C() (with IncrementGcmCounter()
now built for them on AArch64) and XTS through its software
implementation. The GHASH-only selectors keep WOLFSSL_ARMASM since they
only use H, and the AArch64 streaming GCM branches also require
use_aes_hw_crypto, which only the Arm assembly SetKey sets. This
replaces the STM32_CRYPTO exclusion from e31e158225. Builds that select
the Arm assembly backend are unchanged.
Tested on an STM32U585 (wolfDemo) with STM32 AES and HASH plus Thumb-2
assembly: the wolfCrypt test passes, including AES, AES-CTR, AES-GCM,
AES-CCM and CMAC. With STM32 AES, aes.o no longer references
AES_ECB_encrypt(), AES_ECB_decrypt() or AES_CTR_encrypt(). An AArch64
--enable-all --enable-armasm build passes the wolfCrypt test and unit
tests, and the same build with WC_AES_USE_ARMASM left undefined (as with
a port ahead of the Arm backend) now compiles and passes all AES tests,
including XTS and the streaming modes. Thumb-2 and AArch32
crypto-extension objects are unchanged.
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.