Commit Graph
10128 Commits
Author SHA1 Message Date
Tobias Frauenschläger 18414d7b4b Let a DTLS 1.3 reader send the work it schedules
With WOLFSSL_RW_THREADED the read path performs no scheduled work, because
transmitting from the reader would race the write thread over the output
buffer and the sending key schedule, neither of which is covered by a lock.
Post-handshake the only remaining consumers are on the write path, and
wolfSSL_dtls_retransmit() only helps while the handshake is unfinished. An
application that reads without writing therefore never acknowledges a
NewSessionTicket, KeyUpdate or connection ID message, and the peer keeps
retransmitting what it is waiting to have acknowledged. RFC 9147 relies on
those ACKs, so this is a protocol level break rather than a missed
optimisation.

Add wolfSSL_dtls13_do_scheduled_work() so such an application can send that
work from its write thread, and wolfSSL_dtls13_pending_work() so it can tell
when there is any.

Both entry points ask the same helpers rather than each testing conditions of
their own, so they cannot drift into the predicate promising work the pump
then declines or silently discards, which would leave a drain loop spinning or
mislead the caller about what happened. That covers key updates in particular:
none is sent while one of ours is unacknowledged, since DTLS must not have two
in flight and Tls13UpdateKeys() drops a locally scheduled one in that state,
and a peer request is kept rather than dropped until it can be answered. The
predicate also errs towards reporting work when it cannot tell, so a loop
surfaces the error rather than stopping silently.

Refusing an object is treated as a usage error and leaves ssl->error alone.
That field is sticky, since SendData() only clears it for WANT_WRITE, pending
async work and the DTLS MAC and decrypt cases, and wolfSSL_write() skips its
write-dup drain while it is set, so recording one would disable the very drain
a write-dup application depends on.

Write-dup pairs are out of scope on both sides. They park the read side's work
in the shared WriteDup struct, which only wolfSSL_write() reconciles, so they
already have a drain. Completing a key update we started ourselves is out of
scope too: that needs the peer's acknowledgement processed, which rotates the
sending keys and creates an epoch, and the epoch table has no locking while
the read thread mutates it as well.

The declaration is gated to match where the definitions live, so a lean build
is not promised a symbol it does not get.
2026-08-01 12:04:56 +02:00
Tobias Frauenschläger 428bfe9f58 Restore the caller's key RNG after an HPKE operation
The encap and decap paths create a temporary RNG, install it into a key that
belongs to the caller so the shared secret computation can blind, and then
free it without taking it back out. Both wc_ecc_set_rng and
wc_curve25519_set_rng only record the pointer, and nothing else ever writes
that field, so the caller's key was left pointing at freed memory. Encap does
this to the ephemeral key and decap to the receiver key, including the
curve25519 branch. Repeated HPKE calls hide it because each one installs a
fresh RNG first, but any other use of the key that consults it, such as an
ECDH or a signature under timing resistance, reads the freed object. ECH
holds exactly such a long lived key.

Save whatever RNG the key already had and put it back before freeing the
temporary one, so the key is handed back to the caller unchanged. Clearing
the field instead would silently drop an RNG the caller had installed for
blinding of their own.

Extend the HPKE round trip test to give both keys an RNG of its own and to
require them to still have it once the seal and open have finished.

Fixes F-7083.
2026-08-01 12:04:56 +02:00
Tobias Frauenschläger e2cce035eb Zeroize key material when clearing a WOLFSSL for reuse
SSL_clear recycles a WOLFSSL object for a new connection, which is the usual
pattern in connection pooling servers, and wolfSSL_shutdown calls it on
success as well. It reset the option and state fields but left every piece of
key material from the previous connection in place. The teardown path in
SSL_ResourceFree is careful here and force zeroes the keys struct and the TLS
1.3 traffic secrets, so a reused object ended up holding material that a
freed one would not.

The keys struct keeps the write keys, MAC secrets and IVs, clientSecret and
serverSecret keep the TLS 1.3 traffic secrets, the DTLS 1.3 epoch table keeps
traffic keys, IVs and sequence number keys for every epoch, and the handshake
arrays keep the master secret, the pre master secret, the PSK key and the TLS
1.3 key schedule secret. The tls-unique fields keep the Finished values of the
connection that just ended, so the next caller could bind to the wrong
session. The buffers are sized for the largest supported algorithm, so a later
handshake that negotiates something smaller only overwrites a prefix and the
tail survives.

Force zero all of it. A freshly created object has these zeroed already, with
two exceptions that are put back after the wipe: the multicast peer identifier
sentinel, and the unprotected DTLS 1.3 epoch 0 together with the epoch
pointers aimed at it, which only InitSSL sets up and without which the next
handshake has no valid epoch.

Wipe the handshake arrays in place rather than releasing them. They have to
stay allocated because wolfSSL_set_secret, the exporter and the accessors that
run after a connection all read from them on an object that is being recycled
rather than freed, and because the key agreement routines take preMasterSz as
the size of the buffer they may write, so that is restored to what a freshly
allocated Arrays carries. An application that asked to keep the arrays still
gets back everything the API can hand it, so the master secret and the
exporter secret only go when it did not ask, while the pre master secret, the
PSK key and the key schedule secret always do because nothing reads those
back.

wolfSSL_set_secret and wolfSSL_make_eap_keys both reached into the arrays
without checking that they are there, which the ordinary handshake teardown
can already leave them not to be, so both now report a bad argument instead.

Add a regression test that runs a handshake, clears the object with the arrays
kept, and requires the write keys, both traffic secrets and the pre master
secret to be gone while the master secret, the exporter secret and the client
random survive. It then takes that request back, clears again, and requires
the master and exporter secrets to be gone with the arrays themselves still
present.

Fixes F-7258.
2026-08-01 11:54:40 +02:00
Tobias Frauenschläger cb73424c31 Zeroize the saved HMAC pads on cleanup
WOLFSSL_HMAC_CTX keeps a copy of the inner and outer pads outside the
embedded wolfCrypt HMAC object so that a later init with a NULL key can
restore the key. Those pads are the key combined with the fixed padding, so
for any key no longer than the hash block size the key falls out of a single
exclusive or. Cleanup only called wc_HmacFree on the embedded object, which
zeroes what it is given but cannot reach the enclosing context, so the saved
pads survived. HMAC_CTX_free then returned that heap block to the allocator
with the key material still in it, where it stayed until some later
allocation happened to overwrite it.

Wipe both saved pads in wolfSSL_HMAC_cleanup, which HMAC_CTX_cleanup,
HMAC_CTX_reset and HMAC_CTX_free all reach. Do the same on the set key
failure path in the init function, since the context is reported as unkeyed
there while the previous key's pads would otherwise remain.

The session ticket key callback had the same leak for the same reason. It
holds a WOLFSSL_HMAC_CTX on the stack, hands it to the application to be
keyed with the long lived ticket HMAC key, and then only freed the embedded
object, leaving the pads on the stack after every ticket encrypt and every
ticket decrypt including the error paths. Have it clean up through
wolfSSL_HMAC_CTX_cleanup so it picks up the wipe.

Add a regression test that keys a context, checks the pads were populated,
runs cleanup and requires both arrays to be zero.

Fixes F-7256 and F-7257.
2026-08-01 11:54:40 +02:00
Tobias Frauenschläger 96fb284398 Honour chklen when matching an IP in X509_check_host
wolfSSL_X509_check_host takes an explicit length and its own validation
accepts a buffer with no NUL terminator, since only an embedded NUL is
rejected and a trailing one is merely stripped when present. The iPAddress
check then called CheckIPAddr, which drops the length and measures the
buffer with XSTRLEN, reading past the end of a caller supplied buffer that
is length delimited rather than terminated. This ran on every call, not
only when checking an IP address, and is compiled in whenever
WOLFSSL_IP_ALT_NAME is defined, which OPENSSL_ALL and WOLFSSL_QT enable.

Call CheckHostName directly with the caller's length and the IP flag set.
That is what CheckIPAddr does internally, minus the length being recomputed.
Behaviour is unchanged for NUL terminated input, because the normalization
above already leaves chklen equal to the string length in that case. It
also fixes a matching bug, since a length delimited IP address sitting in a
longer buffer no longer fails to match an iPAddress entry.

Add a regression test covering an interior slice of a longer buffer and a
buffer sized exactly to the name with no terminator.

Fixes F-7248.
2026-08-01 11:54:40 +02:00
Tobias Frauenschläger 2788d9dac1 Use the stored entry length when printing a directoryName
X509PrintDirType derived the length of the alt name payload with XSTRLEN.
A directoryName entry holds raw DER, which routinely contains zero bytes,
and under WC_ASN_NO_HEAP the buffer is not NUL terminated at all, so the
computed length was wrong in general and reading it was already out of
bounds in the no-heap case. The length then fed an unsigned loop bound of
src_len - 5, so any entry that XSTRLEN measured as shorter than five bytes
wrapped the bound to nearly UINT32_MAX and the tag scan read far past the
end of the entry. A certificate with a short or empty directoryName alt
name reaches this from the ordinary certificate printing path.

Take the length from entry->len, which the parser already fills in, and
return early when the entry is too short to hold an OID, a tag and a
length. The scan is unchanged for entries of five bytes or more, and the
ASN parsing helpers now receive the true buffer length as their bound.

Add a regression test that prints a certificate carrying a directoryName
with an embedded zero byte before the common name, and one carrying a
directoryName too short for the tag scan.

Fixes F-7223.
2026-08-01 11:54:40 +02:00
Tobias Frauenschläger 6e4a2429e6 Take the write lock when setting the pending DTLS peer
wolfSSL_dtls_set_pending_peer acquired the DTLS peer lock for reading and
then mutated the shared state under it. It frees and clears pendingPeer,
calls SockAddrSet which frees and reallocates the address buffer, and
writes processingPendingRecord. A read lock allows several holders at once,
so two threads in this function can both free pendingPeer.sa, and a reader
in wolfSSL_dtls_get_peer or the wolfio send path can observe a dangling
pointer.

Acquire the lock for writing instead, matching wolfSSL_dtls_set_peer, which
already does so for the same class of mutation. Only affects builds that
define WOLFSSL_RW_THREADED, since the locking is compiled out otherwise.

Fixes F-7222.
2026-08-01 11:54:40 +02:00
Tobias Frauenschläger 22985984d1 Clamp CBC pad length before deriving the MAC input length
TimingPadVerify passes (pLen - macSz - padLen - 1) to ssl->hmac and relies
on the callee recovering the record length by modular addition. TLS_hmac now
does that addition with overflow checking and returns BUFFER_E before hashing
anything, so a record whose padding length byte exceeds pLen - macSz - 1 is
rejected without a MAC being computed at all, while a smaller padding byte
gets the full constant time HMAC. The padding length byte is taken straight
from the decrypted record, so this hands an attacker a Lucky13 style timing
oracle worth an entire HMAC.

Clamp the padding length in constant time before it is used, so the length
handed to ssl->hmac never wraps and every value of the padding length byte
results in the same amount of hashing. The rejection decision is unchanged,
since MaskPadding already flags an out of range padding length. The overflow
check in TLS_hmac stays as a backstop for genuinely bogus sizes.

Add a regression test that drives TimingPadVerify over every padding length
byte with a recording MAC callback and asserts the callback is always invoked
with a length that does not wrap.

Fixes F-7240.
2026-08-01 11:54:40 +02:00
David GarskeandGitHub 51f694193e Merge pull request #10972 from philljj/misc_fixes
ssl: fix miscellaneous issues found in review.
2026-07-31 14:02:17 -07:00
Tobias FrauenschlägerandGitHub b844cdcce0 Merge pull request #10421 from kojo1/pha
TLS 1.3 PHA with OCSP Stapling
2026-07-31 09:07:29 +02:00
David GarskeandGitHub 4f92fe3e85 Merge pull request #10988 from SparkiDev/mem_zero_fixes_1
MemZero: Add more checks of buffers.
2026-07-30 15:42:10 -07:00
David GarskeandGitHub 643d209dba Merge pull request #10961 from anhu/crl_unknown_ext
New API for CRL unknown extension callback
2026-07-30 09:00:23 -07:00
Sean Parkinson 1106d593fb MemZero: Add more checks of buffers.
Added wc_MemZero_Add calls and wc_MemZero_Check calls wheter ForceZero is used.
Fixed a couple of places that had the wrong size.
2026-07-30 10:50:52 +10:00
Sean ParkinsonandGitHub 9c5436b853 Merge pull request #10968 from Frauschi/fenrir_tls
Fenrir fixes
2026-07-28 11:31:19 +10:00
Sean ParkinsonandGitHub 19c1d07beb Merge pull request #10944 from Frauschi/tls-read-ahead
Add TLS receive read-ahead support
2026-07-28 11:16:21 +10:00
Sean ParkinsonandGitHub 9521f89295 Merge pull request #10989 from philljj/sess_free_cb
tls13: set sess_free_cb to null after calling.
2026-07-28 09:29:55 +10:00
Sean ParkinsonandGitHub 495296a739 Merge pull request #10625 from julek-wolfssl/client-custom-ext
Add SSL_CTX_add_client_custom_ext (OpenSSL-compat client custom extensions)
2026-07-28 09:22:47 +10:00
Tobias Frauenschläger f60002d137 Add TLS receive read-ahead support
Add WOLFSSL_TLS_READ_AHEAD (--enable-readahead), toggled at runtime via
wolfSSL_set_read_ahead(). When enabled, the record-header read pulls a
full record in one recv() so the body arrives without a second syscall.

The receive window is configurable with
wolfSSL_CTX/SSL_set_default_read_buffer_len() (OpenSSL-compatible):
0 keeps the one-record default, a larger value coalesces several records
per recv(), a smaller value caps the per-connection buffer footprint.
Records exceeding the window are still received correctly, the buffer
grows on demand and is reallocated back down to the window afterwards so
the retained footprint stays bounded.

Includes docs, API tests, and a benchmark toggle.
2026-07-24 08:17:41 +02:00
Sean ParkinsonandGitHub f5ace71dd3 Merge pull request #10982 from julek-wolfssl/dtls-clear-tx-cursor-on-free
DTLS: clear dtls_tx_msg cursor when its record is freed
2026-07-24 13:24:52 +10:00
jordan 74803cea6e tls13: set sess_free_cb to null after calling. 2026-07-23 22:11:02 -05:00
jordan df73fa1b60 ssl_api_cert: remove dead sk null check. 2026-07-23 21:50:13 -05:00
Sean ParkinsonandGitHub 674a77b5a1 Merge pull request #10953 from embhorn/zd22167
Bound CKS extension allocation in TLSX_CKS_Parse
2026-07-24 10:40:29 +10:00
Sean ParkinsonandGitHub 15afad7f8f Merge pull request #10902 from rlm2002/coverity
2020714 Coverity fixes
2026-07-24 10:38:13 +10:00
Sean ParkinsonandGitHub 8731e21bcf Merge pull request #10899 from julek-wolfssl/julek-dev/zero-copy-record-encrypt
Zero-copy encrypt of AEAD application data
2026-07-24 10:22:30 +10:00
Sean ParkinsonandGitHub f7571db708 Merge pull request #10896 from julek-wolfssl/julek-dev/openvpn-set0-crls
X509_STORE_CTX_set0_crls: implement for OpenVPN
2026-07-24 10:18:40 +10:00
Sean ParkinsonandGitHub 3254e75598 Merge pull request #10811 from kareem-wolfssl/gh10746
Correct alert type for missing supported_versions in HRR and avoid sending duplicate protocol_version alerts.
2026-07-24 09:45:14 +10:00
Sean ParkinsonandGitHub 98edc78599 Merge pull request #10769 from rizlik/dtls13_max_handshake_sz
dtls13: add check over handshake message length
2026-07-24 09:35:37 +10:00
JacobBarthelmehandGitHub b3424c4df6 Merge pull request #10966 from ejohnstown/upd-ocsp
Reject CR/LF and obs-fold in OCSP requests
2026-07-23 15:07:44 -06:00
Anthony Hu 8b0e0b9683 New API for CRL unknown extension callback
Adds public entry points mirroring the existing X.509 unknown extension callback so callers can register a handler for unrecognized CRL extensions instead of failing with ASN_CRIT_EXT_E.
2026-07-23 15:30:16 -04:00
Juliusz Sosinowicz 9d2b32e9f8 DTLS: clear dtls_tx_msg cursor when its record is freed 2026-07-23 16:07:37 +02:00
Sean ParkinsonandGitHub e6c3bb4403 Merge pull request #10827 from danielinux/falcon-native
Falcon: native implementation replacing liboqs, with crypto callbacks and ARM acceleration. Deprecate liboqs support.
2026-07-23 21:17:10 +10:00
John Safranek 6b78c5952b Reject CR/LF and obs-fold in OCSP requests
The OpenSSL compatibility APIs copied caller-supplied strings into the
outbound OCSP request verbatim, so an embedded newline split it into
attacker-chosen header lines, and a header name starting with SP or HTAB
folded into the preceding header's value. OpenSSL rejects these; the
library's own fetch path already rejects CR/LF via wolfIO_DecodeUrl().

* wolfSSL_OCSP_REQ_CTX_http(): reject CR/LF in op and path.
* wolfSSL_OCSP_REQ_CTX_add1_header(): reject CR/LF in name and value.
* wolfSSL_OCSP_REQ_CTX_add1_header(): reject a name starting with SP or
  HTAB, which RFC 7230 Section 3.2.4 treats as an obs-fold continuation
  of the previous header rather than a new header.
* wolfSSL_OCSP_parse_url(): reject CR/LF anywhere in the URL, the likely
  source of a tainted path via a certificate's AIA extension.
2026-07-22 20:47:06 -07:00
Takashi Kojo 60817b08c6 Fix repeated TLS 1.3 PHA over write_dup 2026-07-23 07:46:13 +09:00
Takashi Kojo df3cf63985 fix PHA client OCSP staple and write_dup for repeated PHA 2026-07-23 07:42:20 +09:00
Takashi Kojo 6d0dca2950 Post handsake authentication with client end OCSP 2026-07-23 07:42:20 +09:00
David GarskeandGitHub 983e1090d7 Merge pull request #10922 from aidangarske/fenrir-asn-strict
Enforce RFC 5280 extension MUSTs under WOLFSSL_NO_ASN_STRICT and validate DTLS 1.3 legacy_session_id echo
2026-07-22 14:12:33 -07:00
jordan b00943ce76 ssl: fix miscellaneous issues found in review. 2026-07-22 12:22:21 -05:00
Juliusz Sosinowicz 1a32f1b9af X509_STORE_CTX: chain owns references to its certs
Fixes a heap-use-after-free found by ASAN in the sanitize-asan CI
config. wolfSSL_X509_verify_cert filled ctx->chain with borrowed
pointers while CleanupStoreCtxCallback frees the chain members it
expects from X509_STORE_CTX_get_chain. Calling X509_verify_cert from a
cert verify callback, like OpenVPN does, freed the certs twice. Take a
reference for each cert pushed onto the chain and free the members
whenever the chain is freed, like OpenSSL.

Also address review comments:
- Pass a cert verify callback failure on to the following verify
  callbacks as preverify_ok = 0.
- Only define X509_STORE_CTX_set0_crls with HAVE_CRL.
2026-07-22 13:31:03 +02:00
Juliusz Sosinowicz ccc8068b05 X509_STORE_CTX_set0_crls: implement for OpenVPN
OpenVPN master keeps CRLs in its own stack and passes them to each
verification with X509_STORE_CTX_set0_crls from its cert verify
callback. CRLs are no longer loaded into the store.

- Add wolfSSL_X509_STORE_CTX_set0_crls. The ctx borrows the stack.
- Check the ctx CRLs in X509StoreVerifyCert. They can revoke a cert the
  CertManager accepted and can satisfy the CRL requirement when the
  CertManager has no CRL loaded. The check runs after the date override
  handling so that a revocation is not masked by an overridden date
  error. A stale CRL in the stack does not fail the check when another
  CRL vouches for the cert.
- Add CheckCertCRLFromCm to check a cert against a caller-owned CRL
  using the cm of the store for CRL signature verification. The CRL
  object is not modified and the cached verification result of the
  entries is not used because it is only valid for the owning cm.
- Pass the good result of the cert verify callback to the following
  verify callbacks in DoVerifyCallback. In OpenSSL the cert verify
  callback replaces chain verification so the verify callbacks only see
  its result. OpenVPN needs this to run its per-cert verification.
- Re-add OpenVPN master to CI testing.
2026-07-22 13:31:03 +02:00
Tobias Frauenschläger 64271d24ec Send unexpected_message alert on EndOfEarlyData in DTLS 1.3
RFC 9147 section 5.6.1 states that EndOfEarlyData is not used in DTLS 1.3
and that a receiver must terminate the connection with an
unexpected_message alert. Dtls13CheckEpoch grouped end_of_early_data into
the default case that returns SANITY_MSG_E without sending any alert, and
the DTLS 1.3 handshake dispatch in DoProcessReplyEx did not send a fatal
alert on error the way the DTLS 1.2 path does, so the connection was
dropped silently. Add an explicit end_of_early_data case that sends the
unexpected_message alert, and mirror the DTLS 1.2 SendFatalAlertOnly
handling in the DTLS 1.3 dispatch so other handshake errors are also
reported rather than dropped silently.

Fixes F-6987.
2026-07-22 13:07:55 +02:00
Tobias Frauenschläger 8b12255d56 Document ALPN continue-on-mismatch RFC 7301 non-compliance
WOLFSSL_ALPN_CONTINUE_ON_MISMATCH makes a server continue the handshake
without an agreed protocol when no ALPN protocol matches, like OpenSSL,
instead of sending the fatal no_application_protocol alert that RFC 7301
section 3.2 requires. This is an explicit, caller-selected opt-in:
wolfSSL_UseALPN rejects a call that sets neither mismatch option, and the
library never enables it implicitly. Document the RFC non-compliance at
the option enum, the wolfSSL_UseALPN options parameter, and the mismatch
handling in ALPN_find_match so the trade-off is clear at every point a
user or maintainer encounters it. No behavior change.

Fixes F-7003.
2026-07-22 13:07:55 +02:00
Tobias Frauenschläger a347bb6a53 Zeroize secure renegotiation key copy before freeing it
The SecureRenegotiation extension embeds a Keys tmp_keys copy of the
session cipher and MAC keys, which are the keys used for the renegotiated
epoch. SCR_FREE_ALL freed that struct with a bare XFREE, leaving a full
set of session keys intact in freed heap memory. Wipe the struct with
ForceZero before freeing it, matching the ForceZero of ssl->keys on
connection teardown.

Fixes F-7008.
2026-07-22 13:07:55 +02:00
Tobias Frauenschläger 03cb14a30e Stop offering SHA-1 signature schemes for TLS 1.2 by default
InitSuitesHashSigAlgo added the ecdsa_sha1 and rsa_pkcs1_sha1 signature
schemes to the signature_algorithms list based only on the build flags,
ignoring the negotiated protocol version. Because that list is also the
set a peer's signatures are validated against, any build with old TLS
compiled in advertised and accepted SHA-1 handshake and certificate
signatures for TLS 1.2, which RFC 9155 deprecates. Gate the SHA-1 schemes
on the negotiated version so they are offered only for TLS 1.0 and 1.1
handshakes, unless WOLFSSL_ALLOW_TLS_SHA1 is defined to opt back in. The
same gate excludes them for TLS 1.3, as required by RFC 8446.

Fixes F-6991.
2026-07-22 13:07:55 +02:00
Tobias Frauenschläger 299c80a8a4 Lock sniffer session tables when thread-local storage is disabled
The sniffer elided all session, server, and keylog secret list locking
whenever HAVE_C___ATOMIC was defined, assuming those tables are
thread-local and need no mutex. Thread-locality is actually governed by
THREAD_LS_T, which is only a real qualifier when HAVE_THREAD_LS is set
and NO_THREAD_LS is not. A build with HAVE_C___ATOMIC and NO_THREAD_LS
left the tables as process-shared globals with no synchronization, so
concurrent packet processing raced on the list pointers and could free a
session another thread was still using. Gate the lock elision on both the
atomic fast path and real thread-local storage, and take the mutexes
whenever the tables are process-shared. The stats counter path is
unchanged because it uses a genuine atomic add.

Fixes F-6983.
2026-07-22 13:07:55 +02:00
Tobias Frauenschläger ce21bd67d1 Return failure when ECDSA signature encoding fails in verify
In the WOLF_CRYPTO_CB_ONLY_ECC path of wolfSSL_ECDSA_do_verify, a
non-positive length from i2d_ECDSA_SIG (an encoding failure) skipped
the verify block and left ret at its initial value of 1, reporting a
valid signature although no verification was performed. Map the
encoding failure to WOLFSSL_FATAL_ERROR so it is not treated as a
successful verification.

Fixes F-6981.
2026-07-22 13:07:55 +02:00
Tobias Frauenschläger 4cd57a206a Document ALLOW_INVALID_CERTSIGN and IGNORE_KEY_EXTENSIONS as intentional opt-in knobs
These compile-time flags are off by default and RFC-non-conformant when
enabled. Document their scope and intent at the asn.c macro list and each
enforcement site (ParseCertRelative, VerifyCRL_Signature, AddCA,
ProcessPeerCerts) so their opt-in nature is clear. No behavior change.

Fixes F-6984 and F-6985.
2026-07-22 13:07:55 +02:00
Daniele Lacamera 502ebf4a5d Falcon: fold the AVX2/NEON FFT backends into the single falcon.c
Move the AVX2 (__m256d+FMA) and AArch64 NEON FFT intrinsics, plus the three
internal seam headers (wc_falcon_{fpr,fft,poly}.h), into falcon.c so the native
implementation is one translation unit -- matching how sha256.c and chacha.c
carry their SIMD backends inline (only hand-written .S stays a separate file).
The blocks are gated by WOLFSSL_FALCON_FFT_AVX2 / _NEON and need no per-file
CFLAGS: AVX2 self-annotates every function with target("avx2,fma") and NEON is
AArch64-baseline. Per-backend FPC_* macros are undef'd before redefinition, as
sha512.c does for SHA_METHOD. Only the generated fpr x86-64 asm remains a file.
2026-07-22 09:52:27 +02:00
Daniele Lacamera b3274a58b1 Falcon: consolidate the native C into a single falcon.c
Merge the nine wc_falcon_*.c cores into wolfcrypt/src/falcon.c, matching the
one-file-per-algorithm convention (ed25519.c, wc_mldsa.c). Sign and keygen are
gated internally on WOLFSSL_FALCON_VERIFY_ONLY and the internal helpers become
static. The fpr/fft/poly primitives stay external (shared with the separate
AVX2/NEON FFT backends) so their three headers are retained; the other five
internal headers are removed.
2026-07-22 09:52:27 +02:00
Daniele Lacamera 84b6a59243 Falcon: AArch64 NEON (float64x2_t) vectorized FFT for signing/keygen
Add wc_falcon_fft_neon.c, the 2-wide-double counterpart of the AVX2 FFT
backend: it processes two doubles per 128-bit vector with fused multiply-add
for the complex butterflies (falcon_FFT / falcon_iFFT), over the inline-double
fpr backend. Enabled with --enable-falcon-neon (AArch64; implies
--enable-falcon-double). Advanced SIMD is part of the ARMv8-A baseline, so no
special -march is needed; the scalar FFT/iFFT in wc_falcon_fft.c are excluded
under WOLFSSL_FALCON_FFT_NEON, and only the tail level (ht/t == 1) falls back to
scalar. Like the AVX2 backend, it does not promise bit-identical (no-FMA)
results; that is safe for the signing FFT (the sampler's determinism and
verification are unaffected).

Tested under qemu-system-aarch64 -machine virt (cortex-a53) via the new
IDE/qemu-falcon-neon bare-metal harness: a full keygen -> sign -> verify
round-trip at levels 1 and 5 accepts genuine signatures and rejects tampered
ones (NEON_FFT_PASS), with vector fmla v.2d confirmed in the FFT.
2026-07-22 09:52:26 +02:00
Daniele Lacamera 509b29bc9c Remove liboqs dependency
Falcon was the last algorithm backed by liboqs; now that wolfCrypt has a
native Falcon implementation, liboqs is no longer needed. Remove the
integration entirely so liboqs does not appear as a build or SBOM dependency:

  - configure: drop --with-liboqs (and the -loqs link), the BUILD_LIBOQS
    conditional and the summary line.
  - CMake: drop WOLFSSL_OQS, the duplicate liboqs-backed WOLFSSL_FALCON
    option, the OQS cross-validation / find_package(OQS) block, the
    FindOQS.cmake module, BUILD_OQS_HELPER, and HAVE_LIBOQS from options.h.in.
  - Remove the wolfcrypt/src/port/liboqs port layer (liboqs.c/.h) and its
    wolfSSL_liboqsInit/Close calls in wc_port.c.
  - settings.h: drop HAVE_LIBOQS from the asym key import/export aggregates
    (HAVE_FALCON already covers them) and from the experimental gate; add
    HAVE_FALCON to the experimental gate so the unstandardized Falcon requires
    WOLFSSL_EXPERIMENTAL_SETTINGS in every build system.
  - Drop liboqs.c from the VS/Zephyr/INTIME project files, remove the liboqs
    install from Docker, and update INSTALL/tls.c text (Falcon is native now).

No functional change to non-Falcon builds; the library links no liboqs.
2026-07-22 09:52:26 +02:00