crl.c:
- wolfSSL_X509_CRL_dup: add NULL check on input before dereferencing crl->cm
- DupX509_CRL: distinguish empty source CRL list from allocation failure so
duplicating a CRL with no entries no longer returns MEMORY_E
- wolfSSL_X509_STORE_add_crl: free newly-allocated CRL when wc_LockRwLock_Rd
fails to avoid leaking it
- InitCRL: propagate wolfSSL_RefInit failure in OPENSSL_ALL +
WOLFSSL_REFCNT_ERROR_RETURN builds, freeing crlLock (and cond when
HAVE_CRL_MONITOR is enabled) on the error path
keys.c:
- GetCipherSpec: remove duplicate usingPSK_cipher assignment in
BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 case
- GetCipherSpec: return UNSUPPORTED_SUITE for unknown cipher suite bytes in
the TLS13_BYTE, ECDHE_PSK_BYTE, and SM_BYTE switch blocks, matching the
behavior of the ECC_BYTE, CHACHA_BYTE, and normal suite switches
- SetKeys: fix misleading indentation on the AESCCM and SM4-CCM dec->aes
NULL-check return statements
ssl_certman.c / internal.h:
- AddTrustedPeer: remove dead code that checked peerCert->permittedNames
and peerCert->excludedNames immediately after XMEMSET zeroed the struct
- AddTrustedPeer: use cm->heap (matching allocation) instead of NULL when
freeing cert on the ParseCert failure path
- Extract the body of wolfSSL_CertManagerFree into a new static helper
DoCertManagerFree that unconditionally disposes of the certificate
manager, bypassing the reference count check. wolfSSL_CertManagerFree
now delegates to it after the RefDec check.
- Add caLockInit, tpLockInit, and refInit bitfield members to
WOLFSSL_CERT_MANAGER that track which sub-resources were successfully
initialized. DoCertManagerFree consults these flags so that it only
destroys mutexes and the reference count that were actually set up,
which makes partial-construction cleanup safe without relying on
platform-specific behavior of free-on-zeroed-storage.
- wolfSSL_CertManagerNew_ex: set the init flags as each sub-resource is
initialized, and on failure call DoCertManagerFree directly to free
exactly the resources that succeeded. Set cm->heap immediately after
XMEMSET so the forceful free path can use it.
Add PKCS#11 integration for ML-KEM with key generation,
encapsulation and decapsulation support through the crypto
callback path.
Includes ML-KEM PKCS#11 constants/types, key store handling,
token object lifecycle management, and ML-KEM key init helpers
for private-key ID/label workflows.
Align implementation details with current upstream conventions
and review feedback:
- internal wolfCrypt ML-KEM path only for PKCS#11
- inline ML-KEM key-type/flag checks in PKCS#11 code
- proper key template formatting and enum placement
- ensure TLS ML-KEM object storage behavior is compatible with
PKCS#11 ephemeral-key decapsulation flow
* simplify wolfSSL_BIO_set_conn_hostname, fixing OOB read
* restructure wolfSSL_BIO_ctrl_pending, fixing inverted check and
* ctrlCB checking
* return WOLFSSL_FAILURE in wolfSSL_BIO_up_ref when refInc fails,
updated test to reflect this
* check arguments for NULL in wolfSSL_BIO_ADDR_size
* replace non-portable type long usigned int with size_t
* wolfSSL_BIO_MEMORY_write: return WOLFSSL_BIO_ERROR on failure instead
of WOLFSSL_FAILURE, return 0 when len is 0
* wolfSSL_BIO_get_fp: fix type mismatch comparing XFILE* pointer against
XBADFILE
* wolfSSL_BIO_ctrl: add NULL check on bio before switch
* wolfSSL_BIO_pop: clear bio prev and next pointers after unlinking
* wolfSSL_BIO_gets: place null terminator after actual bytes read from
BIO_BIO nread
* implement legacy compatibility in settings.h and configure.ac (adds --enable-blake2b while retaining --enable-blake2);
* fix incorrect Blake2 gates in wolfcrypt/src/hash.c wc_HashGetDigestSize() and wc_HashGetBlockSize();
* in wolfcrypt/test/test.c hash_test(), backfill missing Blake2 test coverage and separate blake2b from blake2s in typesHashBad[];
* in tests/api/test_hash.c, separate blake2b from blake2s in notCompiledHash[], sizeSupportedHash[], and sizeNotCompiledHash[].
Reinitialize pointer fields in WOLFSSL_SESSION after raw XMEMCPY or
XFREAD in wolfSSL_memrestore_session_cache and
wolfSSL_restore_session_cache. After restore, ticket is reset to
staticTicket, ticketLenAlloc to 0, and peer to NULL.
Validate that the received key share data length (keLen) is at least
as large as the expected ciphertext size (ctSz) before passing it to
wc_KyberKey_Decapsulate. A malicious TLS 1.3 server could send a
short ML-KEM key share.
wc_ecc_import_x963_ex2 only checked whether an imported public point
lies on the intended curve when both USE_ECC_B_PARAM was compiled in
and the caller passed untrusted=1. In a default ./configure build,
USE_ECC_B_PARAM is not defined, so the check was compiled out entirely.
Additionally, the legacy wrapper wc_ecc_import_x963_ex unconditionally
passed untrusted=0, meaning ECIES (wc_ecc_decrypt), PKCS#7 KARI, and
the EVP ECDH layer never triggered the check even when the macro was
present. In the OpenSSL compatibility layer, wolfSSL_ECPoint_d2i
guarded its on-curve check behind !wolfSSL_BN_is_one(point->Z), but
wc_ecc_import_point_der_ex always sets Z=1 for uncompressed points,
making the check dead code.
An attacker who can supply an EC public key (e.g. via an ECIES
ciphertext, PKCS#7 enveloped-data, EVP_PKEY_derive, or
EC_POINT_oct2point + ECDH_compute_key) can choose a point on a twist
of the target curve with a smooth-order subgroup. Each ECDH query
leaks the victim's static private scalar modulo a small prime; CRT
reconstruction across enough queries recovers the full key
(Biehl-Meyer-Müller invalid-curve attack). Static-key ECIES and PKCS#7
KARI are directly affected; TLS is affected in default builds because
the USE_ECC_B_PARAM gate defeated the untrusted=1 flag that the
handshake does pass.
Four changes close the attack:
1. Remove the USE_ECC_B_PARAM gate completely in the code base so that
wc_ecc_point_is_on_curve() is compiled in all builds, not only
those with HAVE_COMP_KEY or OPENSSL_EXTRA (only set for legacy FIPS
builds in settings.h).
2. wc_ecc_import_x963_ex: pass untrusted=1 to wc_ecc_import_x963_ex2
so that ECIES, PKCS#7 KARI, and EVP callers that go through the
four-argument wrapper always validate the imported point.
3. wc_ecc_import_x963_ex2: use the lightweight sp_ecc_is_point_NNN
helpers (curve-equation check only) instead of sp_ecc_check_key_NNN
(which additionally performs a full point*order scalar multiply).
For prime-order curves (P-256, P-384, P-521, SM2) the on-curve
equation check y^2 = x^3 + ax + b is sufficient to defeat
invalid-curve attacks — every non-identity point on a prime-order
curve has the full group order, so the expensive order-multiply
check is unnecessary. This avoids the ~50% ECDH performance
regression caused by the redundant scalar multiplication.
4. wolfSSL_ECPoint_d2i (pk_ec.c): add unconditional on-curve
validation via wolfSSL_EC_POINT_is_on_curve after import. The
existing check was gated on !wolfSSL_BN_is_one(point->Z) and
therefore dead code for all uncompressed-point imports. This closes
the OpenSSL compat layer attack path (EC_POINT_oct2point followed
by ECDH_compute_key).
Non-SP curves fall back to wc_ecc_point_is_on_curve which performs the
same equation check using mp_int arithmetic.
Reported by: Nicholas Carlini (Anthropic) & Thai Duong (Calif.io)
* add WC_FIPS_186_4, WC_FIPS_186_4_PLUS, WC_FIPS_186_5, and WC_FIPS_186_5_PLUS feature macros.
* add support for WC_HASH_CUSTOM_MIN_DIGEST_SIZE, WC_HASH_CUSTOM_MAX_DIGEST_SIZE, and
WC_HASH_CUSTOM_MAX_BLOCK_SIZE, for use with custom digest algorithms.
* add SigOidMatchesKeyOid() helper function and WC_MIN_DIGEST_SIZE macro.
* add additional size and OID agreement checks for sig gen and verify ops.
* update ecc_test_vector() with FIPS 186-5 vectors.
Co-authored-by: Tobias Frauenschläger <tobias@wolfssl.com>
In TLSX_EchChangeSNI, the ctx->extensions branch set extensions
unconditionally even when TLSX_Find returned NULL. This caused
TLSX_UseSNI to attach the attacker-controlled publicName to the shared
WOLFSSL_CTX when no inner SNI was configured. TLSX_EchRestoreSNI then
failed to clean it up because its removal was gated on serverNameX !=
NULL. The inner ClientHello was sized before the pollution but written
after it, causing TLSX_SNI_Write to memcpy 255 bytes past the
allocation boundary.
Fix by mirroring the guarded pattern of the ssl->extensions branch:
only set extensions when TLSX_Find returns non-NULL, and only perform
the SNI swap when extensions is non-NULL. Also move TLSX_Remove in
TLSX_EchRestoreSNI outside the serverNameX guard so any injected
publicName SNI is always cleaned up.
Also return BAD_FUNC_ARG when ECH is used without an inner SNI,
preventing ECH ClientHello construction in an invalid configuration.
Reported by: Nicholas Carlini (Anthropic) & Thai Duong (Calif.io)
When an untrusted issuer has CA:FALSE and no verify_cb is registered,
the !isCa branch now fails closed (ret=WOLFSSL_FAILURE, goto exit)
instead of falling through and skipping X509StoreVerifyCert for the
leaf. SetupStoreCtxError_ex is also hardened to never overwrite a
previously recorded error with success, preventing a later valid chain
link from clobbering ctx->error back to X509_V_OK. Tests added for
both the no-callback rejection and the error-preservation cases.
Reported by: Nicholas Carlini (Anthropic) & Thai Duong (Calif.io)