test_wc_AesModesArgMcdc asserted that wc_AesCtrEncrypt() with corrupted
aes.rounds returns KEYUSAGE_E, but used sz = 32 (an exact block multiple).
When in != out, the full blocks are consumed by a batch path that does not
surface the per-block rounds error - the AES-NI batch, or the HAVE_AES_ECB
fast path which ignores wc_AesEcbEncrypt()'s return - leaving no trailing
partial block, so the function returns 0 and the assertion fails. This was
latent (the whole test binary failed to link before the visibility fix) and
reproduces in --disable-aesni --enable-aesecb builds.
Use a non-block-multiple size (WC_AES_BLOCK_SIZE + 4) so the
"(ret == 0) && sz" leftover-handling call runs and fails on the corrupted
rounds via wc_AesEncrypt() in every backend. Reported by Copilot review on
PR #10845.
Verified: test_wc_AesModesArgMcdc now passes under --disable-aesni
--enable-aesecb (previously failed) and under --enable-aesni --enable-aesecb.
Several MC/DC coverage tests called WOLFSSL_LOCAL (hidden-visibility)
library functions directly from the in-tree unit.test:
- wc_AesCcmCheckTagSize() (test_aes.c)
- wc_CryptoCb_Init/Cleanup/GetDevIdAtIndex() (api.c)
These only link when the library is built with test-static visibility, so
normal (shared) builds failed at link with "undefined reference", breaking
essentially every CI build job. Gate the affected assertions on
WOLFSSL_TEST_STATIC_BUILD (in addition to the existing feature guards) so
they compile out where the symbols are hidden, matching the existing
wolfSSL convention for internal-symbol tests.
Verified: ./configure --enable-all (no WOLFSSL_TEST_STATIC_BUILD) now
builds tests/unit.test cleanly and the full suite passes.
Add tests/unit-mcdc/, a standalone white-box program that compiles
wolfcrypt/src/aes.c directly to reach static/WOLFSSL_LOCAL helpers
(GHASH/GHASH_UPDATE ptr guards, _AesNew_common cross-arg checks) that
are structurally unreachable through the public API, closing 19 of the
AES MC/DC residuals. Extend tests/api/test_aes.{c,h} with the
decision/feature coverage cases these build on.
These are for the external ISO 26262 per-module MC/DC campaign; they do
not change library behaviour and are not part of the wolfSSL build.
- Break out of the chain-build loop after the partial-chain fallback accepts
a caller-trusted terminus, so it is pushed to ctx->chain once instead of
twice; X509StoreCheckPathLen's anchor-skip is now defensive, not load-bearing.
- Drop the now-dead cert == anchor guard and refresh the comment.
- Rework the pathLen regression tests: reuse the existing certs/test-pathlen
chains (chainF rejects, chainB verifies) instead of inlined report certs.
tests/api/api.h: always use FIPS 186-4 settings if defined(HAVE_SELFTEST).
wolfssl/wolfcrypt/settings.h: if defined(HAVE_SELFTEST), #define WC_FIPS_186_4.
* remove FIPS 186-5 sign-mode restrictions from WC_HASH_CUSTOM_MIN_DIGEST_SIZE.
* set up WC_MIN_DIGEST_SIZE_FOR_SIGN and WC_MIN_DIGEST_SIZE_FOR_VERIFY, derived from WC_HASH_CUSTOM_MIN_DIGEST_SIZE, but enforcing FIPS 186-5 sign-mode restrictions only for WC_MIN_DIGEST_SIZE_FOR_SIGN.
* replace all uses of WC_MIN_DIGEST_SIZE with WC_MIN_DIGEST_SIZE_FOR_SIGN or WC_MIN_DIGEST_SIZE_FOR_VERIFY as appropriate.
wolfcrypt/test/test.c: in cryptocb_test(), don't expect callback execution in FIPS builds.
wolfssl/wolfcrypt/settings.h: in WOLFSSL_LINUXKM section, if defined(NO_SHA) while registering ECDSA handlers, force WC_MIN_DIGEST_SIZE_FOR_VERIFY to 20 for SHA-1 verify support.
Add a new option to require that an external Pre-Shared Key is negotiated
for a handshake to succeed, configured via the new APIs
wolfSSL_CTX_require_psk()/wolfSSL_require_psk(). When set, a handshake
that completes without negotiating an external PSK is aborted with
PSK_MISSING_ERROR instead of falling back to a certificate handshake, so
the PSK acts as an additional security factor.
This is a TLS 1.3 / DTLS 1.3 feature. In (D)TLS 1.2 the use of a PSK is
determined by the negotiated cipher suite, so a mandatory PSK is instead
configured there by restricting the cipher suite list to PSK suites; the
new APIs therefore reject non-TLS-1.3 contexts with BAD_FUNC_ARG.
To keep the requirement fail-closed, the APIs also disable version
downgrade on the object so a downgrade-capable context (e.g. one created
from a v23 method) cannot silently fall back to (D)TLS 1.2 and complete
without a PSK; a peer that does not support (D)TLS 1.3 fails to connect.
The requirement applies to external PSKs only (not session tickets):
session-ticket resumption is exempt. To preserve forward secrecy a
mandatory external PSK must also use an (EC)DHE key exchange; a pure
psk_ke handshake is rejected with PSK_KEY_ERROR. When used with
WOLFSSL_CERT_WITH_EXTERN_PSK, it also ensures that peers are properly
authenticated with both the PSK and via certificates.
The new APIs live alongside the existing wolfSSL_[CTX_]no_dhe_psk()/
only_dhe_psk() PSK options and do not depend on certificate support, so
the feature is usable in NO_CERTS (PSK-only) builds.
Added unit tests for the new APIs and enforcement.
QUIC performs key updates at the packet-protection layer via the Key
Phase bit, so RFC 9001 section 6 requires a QUIC endpoint to reject any
received TLS KeyUpdate handshake message as a fatal unexpected_message
connection error and to never send one. The TLS 1.3 receive path
processed the message normally, rotating traffic secrets and possibly
emitting a prohibited KeyUpdate response, and the send path allowed a
QUIC connection to originate a KeyUpdate.
Guard the key_update case in SanityCheckTls13MsgReceived so a QUIC
connection aborts with a fatal unexpected_message alert, and guard
Tls13UpdateKeys so a QUIC connection cannot send a KeyUpdate. Add a
QUIC unit test that feeds a post-handshake KeyUpdate and confirms the
connection is refused.
When the caller passes the object's own data pointer as the source,
wolfSSL_ASN1_STRING_set freed the existing buffer before copying from
it, reading freed memory in the dynamic case and copying cleared bytes
in the fixed-buffer case. Duplicate the source into a temporary buffer
when it aliases the object before disposing of the old buffer, then
free the temporary once the copy completes.
An oversized length argument was passed straight to GetASNHeader as the
buffer bound. A caller supplying a length larger than the real buffer let
the OBJECT_ID header claim more content than was present, driving the OID
validation read past the end of the allocation. Since an ASN1_OBJECT is an
OID, clamp the parse window to the maximum OID encoding so the header
decode cannot read beyond a sane bound.
wolfSSL_EVP_EncodeUpdate did not validate the input length. A large
inl caused the block loop and the residual copy to read far past the
caller's input buffer, and a negative inl was silently treated as
success. Reject negative lengths and lengths whose base64 output would
overflow a positive int before processing any data.