MAX_ENCODED_SIG_SZ grows to ~50KB once SLH-DSA is enabled, yet it was
used to size PKCS#1/signature scratch and output buffers across the
library, wasting stack and heap even for classic RSA/ECC operations.
- Add MAX_ENCODED_CLASSIC_SIG_SZ for RSA/DSA/ECC DigestInfo buffers that
can never hold a PQC signature.
- Size the certificate/CSR signing output buffer from the signing key at
runtime instead of the worst-case macro.
- Add overridable WOLFSSL_MAX_SIG_SZ for the WOLFSSL_NO_MALLOC buffer.
- Reject a signature type that does not match the signing key.
Extend wc_MakeCert_ex/wc_SignCert_ex/wc_MakeCertReq_ex to issue HSS/LMS and
XMSS/XMSS^MT certificates and PKCS#10 requests, building on the existing
RFC 9802 verification support. New LMS_TYPE/XMSS_TYPE/XMSSMT_TYPE selectors,
wc_{Lms,Xmss}Key_PublicKeyToDer SPKI encoders, runtime signature-buffer
sizing, and sigType/key consistency checks. Generation is ASN.1-template
only, matching where the verification path lives.
Tests generate self-signed roots, CSRs and a CA->ECC-leaf chain in-process
and verify them, replacing the patched Bouncy Castle fixtures (only the stock
RFC 9802-aligned LMS interop anchor is kept).
RFC 9147 Section 8's 2^48-1 epoch ceiling is a sender-only rule; the same
paragraph says receiving implementations MUST NOT enforce it. The KeyUpdate
receive path was rejecting a peer epoch that crossed 2^48-1, violating that.
Guard only the genuine wrap-to-zero (Section 4.2.1) and let the receiving
epoch advance past 2^48-1. The sender-side gates are unchanged.
Add count < 0 validation to wolfSSL_CTX_set_groups and wolfSSL_set_groups
(src/tls.c) to prevent negative count from bypassing the upper-bound check
and corrupting numGroups via byte truncation.
Widen count == 0 to count <= 0 and add NULL groups check in
wolfSSL_CTX_set1_groups and wolfSSL_set1_groups (src/ssl.c).
Add NULL buf and NULL cipher checks in wolfSSL_get_shared_ciphers to
prevent NULL pointer dereference.
The cipher property helpers (SSL_CIPHER_get_kx_nid / get_auth_nid /
get_cipher_nid / get_digest_nid / is_aead) parse the cipher name looked
up via cipher->offset in GetCipherSegment(). That offset is only
populated when the cipher is obtained through wolfSSL_get_ciphers_compat()
(SSL_get_ciphers()). When the cipher comes from SSL_get_current_cipher(),
offset is left at 0, so these helpers parsed cipher_names[0] (a TLS 1.3
suite) instead of the negotiated cipher - e.g. returning NID_kx_any for a
plain PSK suite while SSL_CIPHER_get_name() (which uses the suite bytes)
reported the correct name.
Resolve the cipher_names entry from the always-populated suite bytes in
GetCipherSegment(), falling back to cipher->offset when no match is found.
Also add the missing plain "PSK" -> NID_kx_psk entry to the kx lookup
table so PSK suites report NID_kx_psk instead of NID_undef.
Add a regression test that drives the SSL_get_current_cipher() path for
TLS_PSK_WITH_AES_128_GCM_SHA256 and checks all five property helpers.
The TLS 1.2 server derived the single advertised ClientCertificateType
and the signature_algorithms list in its CertificateRequest from the
negotiated cipher suite's own signature algorithm. On an ECDHE-ECDSA
suite only ecdsa_sign was offered (and only ECDSA sig algs), so RSA
clients could not authenticate even though the server could happily
verify an RSA certificate. The same was true in reverse for an RSA
server: the CertificateRequest only advertised rsa_sign.
Refactor SendCertificateRequest to advertise certificate_types and
signature_algorithms covering both sig families when both are compiled
in. Three static helpers in internal.c keep the logic in one place
without mutating ssl->suites:
GetServerCertReqCertTypes - certificate_types to emit
GetServerCertReqHashSigAlgo - signature_algorithms to emit
InServerCertReqHashSigAlgo - membership check used for verification
The advertised lists are written to stack buffers in the caller. To
keep DoCertificateVerify in agreement with what we actually sent, the
SupportedHashSigAlgo call site there is replaced with
InServerCertReqHashSigAlgo, which rebuilds the same list locally and
looks up the client's chosen algo.
Replace the magic certTypes buffer size with a new
MAX_CERT_REQ_CERT_TYPE_CNT constant declared next to
ClientCertificateType.
Add two end-to-end mutual-auth tests covering both directions:
test_tls12_ecdhe_ecdsa_rsa_client_cert - ECDSA server, RSA client
test_tls12_ecdhe_rsa_ecdsa_client_cert - RSA server, ECDSA client
Update test_certreq_sighash_algos to permit RSA / RSA-PSS sig algs in
the ECDHE-ECDSA CertificateRequest; the previous assertion locked in
the ECDSA-only behaviour that this change corrects.
TLS 1.3 is unaffected: RFC 8446 removed certificate_types from
CertificateRequest, and TLS 1.3 cipher suites do not bind a signature
algorithm, so the server's hashSigAlgo already covers both sig
families when either has been compiled in.
Change to ignore plaintext alerts when
WOLFSSL_TLS13_IGNORE_PT_ALERT_ON_ENC is defined only until first
encrypted message from peer is seen.
Negative testing added.
Leak fixes: free existing ssl->buffers.key before overwriting in SetSSL_CTX() (internal.c) and wolfSSL_set_SSL_CTX() (ssl.c)
UAF fix: wc_CheckRsaKey() — mp_memzero_check(tmp) moved before the free (rsa.c)
Build guards: #ifndef NO_ED25519/ED448_VERIFY around forged-sig test data (test_ed25519/ed448.c); guard equal()/cmov() for verify-only builds (ge_operations.c); guard unused pointers under WOLFSSL_MLDSA_SIGN_SMALL_MEM_PRECALC (wc_mldsa.c)
Test cleanups (test.c): fix UB from out-of-range enum in hash_test(), always free AES dec object, fix der buffer declaration under small-stack builds
Removed WOLFSSL_PSK_ID_PROTECTION from use as it is now on by default.
Always check whether the server has a certificate (not a CA chain).
If there is a certificate then continue, otherwise, report a binder
error.
Added test to ensure binder error returned and alert sent when no
NO_CERT. test_tls13_bad_psk_binder already tested no certificate.
Allowed memio test harness to be built when NO_CERT is defined.
- src/x509.c: Guard wolfSSL_X509_get_der against derCert->length > INT_MAX, and reject derSz <= 0 in wolfSSL_i2d_X509.
- tests/api/test_ossl_x509_io.{c,h}: Add API coverage for the X509 DER length guards.
1. Side-aware ML-KEM in TLS (tls.c, tls13.c, ssl.c, internal.h):
TLSX_IsGroupSupported/TLSX_UseSupportedCurve take a `side` arg; new
TLSX_IsMlKemGroupSupported + client/server support macros. A build only
capable of one ML-KEM op no longer advertises groups it can't use for
its role.
2. NO_ASN_TIME support (ssl_asn1.c, ssl.h, settings.h): data-only
ASN1_TIME APIs now compile without system time; OCSP responder
auto-disabled under NO_ASN_TIME.
3. SP ECC (sp_*.c, sp_x86_64_asm.asm): curve `b` constants and
sp_ecc_is_point_* always compiled (point-check available in more
configs); asm movsxd -> movsx.
4. configure.ac: BUILD_MEMUSE fixed to trigger on != "xno".
5. Test fixes: HRR-aware TLS 1.3 memio tests (new
test_memio_msg_is_hello_retry_request); tightened build guards
(Ed25519/Ed448 key-import, AES decrypt, XMSS heights, SP sizes,
static-PSK).
The constant-time path of _DH_compute_key (DH_compute_key_padded) had
the XMEMMOVE source/dest swapped and used (padded_keySz - keySz) as the
length instead of keySz, overwriting the secret with junk when keySz <
padded_keySz. Move key[0..keySz-1] to the high end, matching the idiom
used in tls.c/sniffer.c.
FreeCiphersSide freed cipher->cam with XFREE only, leaving the expanded
key schedule and IV in freed heap memory. Call wc_CamelliaFree (which
ForceZeros the context) before XFREE, matching the ARIA cleanup above.
Dtls13NewEpochSlot never updated oldestNumber after picking a candidate,
so every eligible epoch compared "older" than the sentinel and the last
eligible slot was returned instead of the lowest epoch number. Update
oldestNumber alongside oldest so the true minimum is evicted.
wolfSSL_CTX_set_groups/wolfSSL_set_groups only rejected counts above
WOLFSSL_MAX_GROUP_COUNT; a negative count skipped the copy loop and was
cast to byte (e.g. 255) into numGroups, which InitSSL later trusts for a
fixed-size copy. Reject count <= 0 in both, and in the set1_groups
OpenSSL-compat wrappers.