1
0
mirror of https://github.com/wolfSSL/wolfssl.git synced 2026-10-24 04:09:07 +03:00

3902 Commits

Author SHA1 Message Date
philljj
3803bdd531 Merge pull request #11666 from Frauschi/cryptocb_setkey_keyinstalled
Fix AES and GCM state after a crypto callback claims the key
2026-10-23 13:59:28 -05:00
Tobias Frauenschläger
edb6f7156b Honor WOLF_CRYPTO_CB_FIND in the ARM32 and PPC asm wc_AesSetKey
The ARM32 and PPC asm wc_AesSetKey only ran the crypto callback block
when aes->devId was set. With WOLF_CRYPTO_CB_FIND a find callback can
map an INVALID_DEVID object onto a device, and the AES encrypt paths
already dispatch such objects to it, but the key was never offered to
a SETKEY device or copied into devKey. The device then ran on a key it
never saw.

Skip the devId check under WOLF_CRYPTO_CB_FIND, as the generic
wc_AesSetKey already does. test_wc_CryptoCb_Aes_SetKey_Find maps
INVALID_DEVID onto a key-owning device and checks that wc_AesSetKey and
wc_AesSetKeyDirect both offer it the key.
2026-10-23 08:56:15 +02:00
Tobias Frauenschläger
198602c406 Route the ARM32 asm wc_AesSetKeyDirect through wc_AesSetKey
With WOLFSSL_ARMASM on 32-bit ARM, wc_AesSetKeyDirect() called the
static AesSetKey() directly, so neither the AES_SETKEY nor the SETKEY
device hook saw a re-key, and the plain crypto callback path kept the
old key in devKey. A device that had claimed the previous key went on
encrypting with it while every call returned 0.

Call wc_AesSetKey() instead, as the PPC asm variant already does. Like
PPC, this makes Direct reject key sizes compiled out with
WOLFSSL_AES_128, WOLFSSL_AES_192 or WOLFSSL_AES_256.
2026-10-23 08:56:15 +02:00
Tobias Frauenschläger
6c712d628e Close three gaps around a key a SETKEY device claims
wc_AesGetKeySize() reports aes->keylen for a key a crypto callback
device owns, so the MAX3266X ECB and CBC entry points, which take a
zero return from it as proof of a key, ran the TPU on the wiped
all-zero aes->key after a claim and returned success. They now check
WC_AES_KEY_IS_SET() first and return MISSING_KEY, as the generic modes
do. The check is only in effect with MAX3266X_CB, which is also the
only MAX3266X build where a device can claim a key.

The wipe before a claim left aes->tmp and aes->left, so the keystream
of the old key buffered by CTR, CFB or OFB stayed in the context. The
generic, ARM32 and PPC set-key now clear both as well.

The docs told a callback to build a software schedule by calling
wc_AesSetKey() with aes->devId set to INVALID_DEVID. Under
WOLF_CRYPTO_CB_FIND the find callback can map INVALID_DEVID back to
the same device, so that call recurses into the callback without end.
The docs now ask for a devId no device is registered under, as the
test devices in tests/api.c already use.
2026-10-23 08:56:15 +02:00
Tobias Frauenschläger
a5ee666332 Wipe the old GCM H when a device claims an AES key
When a SETKEY device claimed a new key through wc_AesSetKey(),
wc_AesCcmSetKey() or wc_AesSetKeyDirect(), the set-key wiped the old
key schedule and devKey but left gcm.H and the GHASH table M0 of an
earlier software GCM key in the context. Only wc_AesGcmSetKey() wiped
them. gcmKeySet is already cleared on that path, so the stale H could
not be used, but it is key material derived from the old key and goes
with the rest of it.

The pre-claim wipe in the generic, ARM32 and PPC set-key now clears H
and M0 too, through a WC_AES_GCM_WIPE_H() macro that wc_AesGcmSetKey()
uses as well.

The CryptoCb AES set-key tests in test_aes.c took buffer sizes with
sizeof, which is the size of a pointer under WOLFSSL_SMALL_STACK. In
such builds test_wc_CryptoCb_AesSetKey and
test_wc_CryptoCb_AesGcm_EncryptDecrypt failed at their first set-key
with an 8-byte key, and the declined re-key check passed an 8-byte tag
that wc_AesGcmEncrypt() rejects before it asks the device. Both tests
now use the allocation sizes.
2026-10-23 08:56:15 +02:00
Tobias Frauenschläger
6c8b85e0b5 Keep AES modes off a key a device claimed without a schedule
When a WOLF_CRYPTO_CB_SETKEY or WOLF_CRYPTO_CB_AES_SETKEY callback
claims an AES key, wc_AesSetKey() builds no software key schedule. The
wrapper still marked the context keyInstalled because the set-key
returned 0, so a mode the device then declined passed the
WC_AES_KEY_IS_SET guard and ran in software:

- On a fresh context rounds is 0. With the C implementation the mode
  fails with KEYUSAGE_E; with ARM assembly on aarch64 it crashes
  (SIGSEGV in AES_CBC_encrypt).
- On a context that held a software key before, rounds and the
  schedule were still the old key's. The declined mode then succeeded,
  encrypting with the previous key instead of the one just set.

The set-key now drops the old schedule before offering the key to the
device: rounds goes to 0, and the schedule, including the C-fallback and
bitsliced copies, and devKey are wiped so no material from the previous
key outlives the claim. After a claim the context is marked installed
only if the callback built a schedule itself, as the in-tree test
callbacks do by re-running the software set-key. Otherwise a declined
mode returns MISSING_KEY, matching wc_AesInit_Id().
WOLF_CRYPTO_CB_ONLY_AES builds keep the key marked installed, since
there every block goes to the device's ECB callback.

The same wipe also clears the streaming GCM key and the recorded key
length. Otherwise a context that held a software GCM key and was then
re-keyed through wc_AesSetKey() or wc_AesCcmSetKey() kept gcmKeySet, and
the ARM assembly build streamed GCM on the wiped schedule; and a set-key
the device failed left the old key length behind, which
wc_AesGetKeySize() reported as a valid key.

The ARM32 and PPC assembly builds have their own wc_AesSetKey(), which
set keyInstalled on every claim and kept the old schedule. They get the
same reset. On ARM32 a declined CBC on a freshly claimed key returned 0,
with output from the empty schedule. The PPC copy only offers the key
through WOLF_CRYPTO_CB_AES_SETKEY, so it resets on that path alone.

Streaming GCM had the same problem through gcmKeySet, which
wc_AesGcmSetKey() never cleared. After a software GCM key, a key the
device then claimed left the flag set, and with ARM assembly the
streaming API encrypted under the previous key and returned 0.
wc_AesGcmSetKey() now clears gcmKeySet before setting the key and sets
it again only on success. A set-key the device fails returns before
deriving H or copying the key to devKey, so a caller that ignores the
error cannot stream on the wiped schedule. Dropping the key also clears
nonceSet, so a context already set up for a message under the old key
needs a new wc_AesGcmInit() instead of streaming on that key's counter
state.

The flag is set before H is derived, so a failure there, a refused
vector register save in an AES-NI build or a failing wc_AesEncrypt(),
returned an error with gcmKeySet still set and H from the previous key.
That block now clears the flag on failure, as the aarch64 path already
did. Neither failure can be provoked from the API tests.

wc_AesGcmSetKey() also stops skipping H and the devKey copy when devCtx
is set. A key a device owns without a schedule now leaves through the
early return, so devCtx is only still set at that point when the context
has a software schedule: the device built one, or a
WOLF_CRYPTO_CB_AES_SETKEY device declined a re-key and kept its handle
from an earlier claim. In the second case the skip left H all zero, and
the C build produced streaming GCM tags that did not depend on the
ciphertext. The ARM assembly H derivation never checked devCtx.

The wc_CryptoCb_AesSetKey() docs promised a devKey copy and GCM tables
for software fallback in TLS builds, which no build provides, while the
README and the AES CryptoCB key import page promised the opposite with
no conditions. All three now describe what a claimed key leaves behind,
and that wolfCrypt takes a non-zero aes->rounds to mean the callback
built a software schedule. wc_AesGetKeySize() reports aes->keylen for a
key with a length but no rounds, so a callback has no reason to set
aes->rounds just to make key-size queries work. The keyInstalled field
comment in aes.h now says a claimed key counts only with a schedule.

The docs also now say that a callback declining a new key must first
release any key it holds for the object and set aes->devCtx to NULL.
wolfCrypt leaves devCtx alone on a decline, so a callback that kept its
handle went on running the operations it accepts, such as one-shot GCM,
under the old key while the software modes used the new one.

A WOLF_CRYPTO_CB_SETKEY claim now also stores the IV it was given in
aes->reg, as the AES_SETKEY claim and the software set-key already do,
so a device that reads the IV from aes->reg does not get the previous
key's.

test_wc_CryptoCb_Aes_SetKey_Declined claims a key, declines CBC and
expects MISSING_KEY, both on a fresh context and after a software key,
and checks the old key is gone from devKey. It needs
WOLFSSL_AES_REQUIRE_KEY_SET, since without the key-set check the
declined mode fails with KEYUSAGE_E instead.
test_wc_CryptoCb_AesGcm_SetKey covers the same software-then-claimed
sequence for streaming GCM.

test_wc_CryptoCb_AesSetKey checks the same for a key claimed through
WOLF_CRYPTO_CB_AES_SETKEY: CBC, which its device declines, returns
MISSING_KEY.

Both tests also check a set-key the device fails with WC_HW_E: CBC and
streaming GCM then return MISSING_KEY.

test_wc_CryptoCb_AesSetKey has its device release its handle and
decline a re-key to a different key, checks that one-shot GCM then fails
in the callback instead of using the old key, and compares the streaming
GCM tag with one computed in software under the new key.

test_wc_CryptoCb_Aes_SetKey_Declined also checks that a claimed key
takes the IV passed with it and reports its size, and that a failed
set-key reports none. test_wc_CryptoCb_AesGcm_SetKey re-keys a software
GCM key through wc_AesSetKey() and checks that streaming GCM refuses the
claimed key. test_wc_AesGcmStream checks that wc_AesGcmSetKey() on a
context initialized for a message leaves updates waiting for a new
wc_AesGcmInit().
2026-10-23 08:56:15 +02:00
Tobias Frauenschläger
5044ea40c5 Skip GCM H derivation for an AES key a SETKEY device claimed
With WOLF_CRYPTO_CB_SETKEY, a callback that returns 0 for WC_SETKEY_AES
owns the key: wc_AesSetKey() builds no key schedule and leaves rounds at
0. wc_AesGcmSetKey() still derived the hash subkey H from that empty
schedule. With the C implementation wc_AesEncrypt() rejects rounds 0 and
the set-key fails with KEYUSAGE_E. On aarch64 with ARM assembly,
AES_ECB_encrypt() runs with rounds 0 and crashes (SIGSEGV). The
function also copied the plaintext key into devKey, which should not stay
behind once a device owns the key.

wc_AesGcmSetKey() now returns as soon as the device has claimed the key,
before deriving H, marking the streaming API keyed or copying to devKey.
On that return it wipes the GHASH subkey a previous key may have left,
and the key unwrapped from a CAAM blob. One-shot GCM reaches the device
through its callback as before.

Streaming GCM has no callback, so it must refuse such a key. The update
calls already return MISSING_KEY while gcmKeySet is clear, but
wc_AesGcmInit() set up the IV without checking it: given a key and an
IV, it ran the counter block through the empty schedule, with the same
KEYUSAGE_E or SIGSEGV as above. It now sets up the IV only once a GCM
key is set. Without one it keeps the IV cached and returns 0, so the
first update returns MISSING_KEY and a later call that sets the key
picks the IV up. That is also what an IV passed before the key relies
on, which on master crashed on aarch64 and failed with KEYUSAGE_E in C.
An IV longer than a block cannot be cached, since it goes through GHASH,
so that case returns MISSING_KEY and leaves the context unchanged.

The same applies to a key claimed through the older
WOLF_CRYPTO_CB_AES_SETKEY hook. The C code already skipped H when the
callback set devCtx, but the ARM assembly derivation did not, so
test_wc_CryptoCb_AesSetKey crashed in AES_ECB_encrypt on aarch64 with
--enable-armasm. Both hooks signal ownership by leaving rounds at 0,
which the XTS entry points already rely on.

test_wc_CryptoCb_AesGcm_SetKey registers a device that claims the key and
performs GCM itself, checks the result against software, and checks that
streaming GCM refuses the key in both wc_AesGcmInit() and the update.

test_wc_CryptoCb_AesSetKey also checks that streaming GCM refuses an
AES_SETKEY claim, and test_wc_AesGcmStream that an IV set before the key
is used once the key arrives, through wc_AesGcmInit() with the key or
the first wc_AesGcmInit() after wc_AesGcmSetKey(), and that a long one
is refused.
2026-10-23 08:56:15 +02:00
Emma Stensland
bda00f528c Tests: Pin validity dates in test_dual_alg_ecdsa_mldsa 2026-10-21 12:40:58 -06:00
Tobias Frauenschlaeger
296ef4be79 Hold the EC point formats in one allocation
The point formats extension stored its formats as a linked list with one heap
node per one byte value, which is the shape the supported groups extension had
before. A node costs sixteen bytes to hold one.

Replace the list with a block holding a count, a capacity and a flat array,
matching what the supported groups extension does now. The block starts with
room for four formats, which is more than are defined, and doubles if a caller
adds more.
2026-10-21 11:31:28 +02:00
Tobias Frauenschlaeger
caafb688c3 Keep the max fragment length code in the extension
TLSX_UseMaxFragment() asked the allocator for a single byte to hold the length
code the peer is told about, and freed it when the extension went away. The
TLSX object already carries a value field for extensions whose data is a
scalar, which is how the PSK key exchange modes and early data extensions
store theirs, so use that and hold no data at all.
2026-10-21 11:31:28 +02:00
Tobias Frauenschlaeger
9b6f9cc50c Store the ALPN protocol name with its object
TLSX_ALPN_New() allocated the object and then the protocol name it points at.
A client offering several protocols paid two allocations for each. Put the
name in a flexible array at the end of the object instead, so TLSX_ALPN_Free()
has one buffer to release.

The name can no longer be NULL, so TicketAlpnHash() and the ALPN tests drop
their NULL checks on it.
2026-10-21 11:31:28 +02:00
philljj
c177f861d0 Merge pull request #11576 from douzzer/20260925-WC_RNG_RBGC_STRATUM_IMMUTABLE
20260925-WC_RNG_RBGC_STRATUM_IMMUTABLE
2026-10-20 10:15:26 -05:00
Tobias Frauenschläger
b8891fa1a4 Rework the static-memory heap hint fix
Heap hints are inherited from the CTX, and switching a static-memory SSL
to a CTX with a different heap is outside that model. Instead of freeing
through a stack-local hint that carries the creating pool,
wolfSSL_set_SSL_CTX() now refuses a CTX whose heap differs from the
current one. ssl->ctx->heap is then always the heap the SSL was created
from, so wolfSSL_free(), FreeSSL() and FreeSSL_StaticMemory() go back to
freeing through it.

Releasing the SSL heap hint last in wolfSSL_ResourceFree() stays, as the
DTLS 1.3, QUIC and peerSigSpec cleanups still free through ssl->heap.

FreeSSL_StaticMemory() now clears ssl_hint->stats before freeing the
stats block. When wolfSSL_new() fails before SetSSL_CTX(), ssl->ctx is
NULL and the stats block and the hint are freed through ssl->heap
itself, so wolfSSL_Free() wrote the connection statistics into the
freed stats block on both frees.

test_wolfSSL_set_SSL_CTX_static_heap checks that a switch to a second
pool or to a CTX without a heap, and from one to a pool, is refused and
leaves the SSL on its original CTX, while a switch between two CTXs on
the same heap still succeeds.
2026-10-15 17:24:03 +02:00
Tobias Frauenschläger
3b172fe050 Address review comments
Fail wolfssl_print_number when XSNPRINTF returns a negative length
instead of copying it as a size. Note why the file name is bounded
under WOLF_C89 and how the error-print buffer is sized. Print
large_crlnum.pem in test_wolfSSL_X509_CRL_print; its 49-digit CRL
number overflowed the old 49-byte buffer.
2026-10-15 17:24:03 +02:00
philljj
3a45cc02e6 Merge pull request #11682 from padelsbach/byteray-med-x509
Compat layer: escape control characters in X509 print output
2026-10-15 09:42:49 -05:00
Tobias Frauenschläger
f46cdde15b Merge pull request #11400 from julek-wolfssl/ca-store-loading-fixes
Thread the caller's verify setting into trusted-peer loads and parse multi-valued RDNs
2026-10-15 11:03:36 +02:00
Daniel Pouzzner
55fa3a18b1 tests/api.c: add missing NO_TLS gates around test_wolfSSL_X509_CRL_get_REVOKED_after_update(). 2026-10-14 16:13:43 -05:00
philljj
fde1138bda Merge pull request #11367 from julek-wolfssl/chain-verify-cb
Add WOLFSSL_CHAIN_VERIFY_CB to replace peer chain verification
2026-10-14 10:16:45 -05:00
philljj
6090053cbb Merge pull request #11334 from yosuke-wolfssl/fix/f_12625
asn, certman: add selfIssued and verify selfSigned against own key
2026-10-13 12:44:33 -05:00
Tobias Frauenschläger
0dbc94b555 Merge pull request #11609 from julek-wolfssl/ctx-get-ciphers-compat
Add SSL_CTX_get_ciphers() compat API
2026-10-13 15:56:24 +02:00
Juliusz Sosinowicz
be38ea3f73 Address review: self-contained WOLFSSL_CIPHER entries
- WOLFSSL_CIPHER no longer points to an SSL. It holds the suite and the
  version reported for it. Entries are filled in once and never written
  after, so threads may share the CTX stack.
- SSL_CIPHER_get_version(), SSL_CIPHER_description() and
  SSL_CIPHER_get_bits() work for list entries, including copies kept
  after the SSL is freed.
- SSL_get_current_cipher() fills in the cipher from the SSL on each call.
- SSL_CIPHER_description() and SSL_CIPHER_get_bits() describe every
  cipher the same way, wherever it came from. The Kx/Au/Enc/Mac strings
  and the bits match OpenSSL. TLS 1.3 suites go by their IANA name.
- Fix cipher_names versions with NO_CIPHER_SUITE_ALIASES outside
  OPENSSL_ALL and QT builds.
- Do not queue an error for the renegotiation SCSV found by
  SSL_CIPHER_find().
- Report a strength of 0 bits for suites without a cipher, including
  integrity-only TLS 1.3 suites.
- Describe ECDHE suites in builds without HAVE_ECC.
- Fix test_wolfSSL_certs passing a stack as an ASN1_STRING.

Behavior change: OPENSSL_ALL and QT list entries were described by
parsing the suite name, e.g. "Mac=SHA256" for AES-GCM and
"Kx=RSA Au=RSA" for TLS 1.3. The current cipher was described from the
session with wolfSSL's own strings, e.g. "Kx=ECDHE", "Au=None" for PSK
and, outside QT builds, the IANA name of a TLS 1.2 suite. Both now
print what OpenSSL prints, e.g. "ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2
Kx=ECDH Au=RSA Enc=AESGCM(128) Mac=AEAD". 3DES reports 112 bits,
alg_bits 168, instead of 168 or 192. After SSL_set_session(), until the
server's hello, and after SSL_clear(), the current cipher describes the
suite it names instead of unknown with 0 bits.
2026-10-13 11:30:54 +00:00
Tobias Frauenschläger
532294dcf4 Let sniffer builds use ephemeral test ports
With WOLFSSL_SNIFFER defined, testsuite's simple test and echoserver
and the unit test servers in api.c skipped port 0 and listened on the
fixed 11111. The exception dates from when the testsuite traffic was
sniffed live; the sniffer tests now replay pcap captures and
scripts/sniffer-gen.sh drives the example client and server itself, so
nothing relies on it.

tcp_listen() sets SO_REUSEPORT, so a second process of the same user
can listen on 11111 at the same time and the kernel hands it some of our
client's connections. testsuite.test never runs under bwrap, and on a
shared CI node this shows up as "wolfSSL_connect error -308" right after
"listening on port 11111". Reproduced with a decoy SO_REUSEPORT listener
on 11111: testsuite fails 5 of 5 runs before and passes 5 of 5 after.
2026-10-13 12:39:12 +02:00
Juliusz Sosinowicz
b4d1b1077b Guard clear-chain-certs test helper like its only caller
The helper is defined without the NO_WOLFSSL_CLIENT condition its caller
has, so a build with the client compiled out fails on the unused
function. Give the definition the same guard.
2026-10-13 05:25:00 +00:00
Juliusz Sosinowicz
797e34a271 Add WOLFSSL_CHAIN_VERIFY_CB to replace peer chain verification
Adds an opt-in callback that takes over the peer certificate trust
decision. wolfSSL builds no chain, verifies no signature and checks no
date, revocation status, key usage or host name; the verify callback is
not called either. The callback gets only the DER certificates from the
Certificate message as WOLFSSL_BUFFER_INFO entries, certs[0] first. It
is consulted even under WOLFSSL_VERIFY_NONE, and its rejection fails the
handshake either way.

wolfSSL still decodes every certificate with ParseCert(NO_VERIFY) before
the callback runs, so malformed DER fails the handshake and the callback
is never handed it. Content wolfSSL does not understand - an unknown
critical extension, an unsupported key or signature algorithm, a
signature algorithm mismatch - is not a decoding failure and is left for
the callback to judge. The check runs once, not again on re-entry after
a deferred verdict.

The callback may return CHAIN_VERIFY_WANT_E to suspend the handshake and
be asked again with the same certificates when the application re-enters
wolfSSL_connect(), wolfSSL_accept(), wolfSSL_read() or wolfSSL_write().
A certificate received after the handshake (TLS 1.3 post-handshake
authentication) arrives inside wolfSSL_read() and is resumed by reading
again: ReceiveData() re-enters on any handshake-suspend error, and the
ticket-sent accept state leaves a suspended message alone. Rejection
fails with CHAIN_VERIFY_CB_E and one bad_certificate alert, and sets
peerVerifyRet so wolfSSL_get_verify_result() does not report X509_V_OK.

Still applied: an empty Certificate message keeps the existing
mutual-auth policy (the callback is not called for it), and the minimum
peer key sizes still gate the peer's own key, which the handshake uses
directly.

DTLS, raw public keys and OCSP stapling are not supported with the
callback. wolfSSL_CTX_SetChainVerifyCb() and wolfSSL_SetChainVerifyCb()
refuse with CHAIN_VERIFY_UNSUPPORTED_E when the context or object is
already configured for one of them, and a connection that uses one of
them anyway fails with the same error and an internal_error alert before
the callback is called. The DTLS paths are otherwise untouched.

The callback and its user context can be set on the context or on the
SSL object, the object's taking precedence. The feature is part of
--enable-all, has a CMake option and Doxygen entries.

The suspend machinery is shared with WOLFSSL_NONBLOCK_OCSP and
WOLFSSL_ASYNC_CRYPT. The open-coded pairs of comparisons against
WC_PENDING_E and OCSP_WANT_READ are replaced by IsHsSuspendErr(), and the
matching build guards by WOLFSSL_HAVE_HS_SUSPEND. That also closes three
holes which affected WOLFSSL_NONBLOCK_OCSP builds:

 - DoHandShakeMsg() freed ssl->pendingMsg on a non-WC_PENDING_E suspend
   while ProcPeerCertArgs still pointed into it.
 - wolfSSL_connect()/wolfSSL_accept() and their TLS 1.3 counterparts
   called FreeAsyncCtx() when buffered output flushed, discarding the
   saved certificate state.
 - ProcessPeerCerts() XFREE'd args in WOLFSSL_SMALL_STACK builds without
   WOLFSSL_ASYNC_CRYPT, where args points inside ssl->async.
2026-10-13 05:24:59 +00:00
Yosuke Shimizu
abfddc8061 asn, certman: add selfIssued and verify selfSigned against own key
- DecodedCert gains selfIssued for the issuer/subject name compare,
  and the name-compare readers use it.
- ParseCertRelative() sets selfSigned for every self-issued
  certificate whose own key verifies its signature: it reuses the
  key that passed the issuer check, or calls the new
  ConfirmSelfSignature(), which verifies in its own context with no
  device.
- CheckChainCAExtKeyUsage() exempts a CA with selfSigned set, in
  place of its own issuer key compare.
- IsSelfSignedCert() in tls13.c is renamed IsSelfIssuedCert().
- ProcessPeerCerts() reports X509_V_ERR_INVALID_CA when a chain CA
  is refused with NOT_CA_ERROR.
- Comments that called the name compare self-signed now say
  self-issued.
- Tests cover a key rollover CA without keyCertSign in a TLS chain
  and as a trusted anchor in X509_verify_cert(), and the selfSigned
  and selfIssued flags from wc_ParseCert().

Issue: F-12625
2026-10-13 08:44:40 +09:00
Paul Adelsbach
5e71024efd PR feedback: address BIO write issue for prefix and value 2026-10-12 16:26:57 -07:00
Paul Adelsbach
944d175297 PR feedback: print full string for GEN_EMAIL and GEN_DNS 2026-10-12 16:26:56 -07:00
Paul Adelsbach
48a0411bcb Escape control characters in X509_REQ_print attribute values 2026-10-12 16:26:56 -07:00
Paul Adelsbach
63662ec213 Add X509_REQ_print test for control characters in subject 2026-10-12 16:26:56 -07:00
Paul Adelsbach
330b913e98 Add X509_CRL_print test for control characters in issuer 2026-10-12 16:26:56 -07:00
Paul Adelsbach
b1a13054ea Escape control characters in X509_print subject and issuer 2026-10-12 16:26:56 -07:00
Paul Adelsbach
ca5806224d Escape control characters in X509_print directoryName alt names 2026-10-12 16:26:56 -07:00
Paul Adelsbach
9600d4d895 Escape control characters in X509_print alt names 2026-10-12 16:26:56 -07:00
Paul Adelsbach
3eb95db74b Escape control characters in XN_FLAG_ONELINE name output 2026-10-12 15:48:07 -07:00
philljj
8efd2736d1 Merge pull request #11345 from Frauschi/tls_mem_4
Size the pre-master secret buffer by the key exchanges, and fix a DHE-PSK overflow
2026-10-09 18:17:59 -05:00
sebastian-carpenter
a060c5e540 mldsa x509 print: address PR comments 2026-10-08 12:15:59 -06:00
sebastian-carpenter
cf8674cff8 x509 printing generalization and MLDSA support 2026-10-08 12:10:45 -06:00
Tobias Frauenschlaeger
044bbfc0fa Size the pre-master secret buffer by the key exchanges
The pre-master secret buffer was sized with ENCRYPT_LEN. That constant also has
to cover an RSA signature, so it follows the largest RSA key the build supports
and a build with RSA 4096 certificates reserved 512 bytes for a secret that
ECDHE fills 32 to 98 bytes of.

MAX_PREMASTER_SZ takes the largest secret any key exchange in the build can
produce: the RSA pre-master, the DH parameters the peer may send, an ECDHE
secret plus the 32 byte ML-KEM half of a hybrid key share, and the length
prefixes and key that the PSK suites append, with the master secret length as
a floor.

A build with DH is unchanged, since the peer chooses the parameter size there.
A build without it, which is the usual TLS 1.3 configuration, holds 98 rather
than 512 bytes per handshake. A build with both DH and PSK gains two bytes:
a DHE-PSK exchange writes a two byte length, the DH secret, another two byte
length and the key, which is two more than ENCRYPT_LEN reserved for the
largest DH parameters and the longest PSK.

The buffer becomes the first member of Arrays, so async Intel QAT builds
allocate Arrays as DYNAMIC_TYPE_SECRET. A QAT key agreement reallocs its
output buffer into NUMA memory, and IntelQaRealloc() now finds the Arrays
header there: a non-NUMA one makes it free the whole struct, a NUMA one lets
it write in place, as it did for the standalone DYNAMIC_TYPE_SECRET buffer.
A static assert keeps the buffer at offset 0.
2026-10-07 09:49:06 +02:00
Sean Parkinson
dc49262d5e Merge pull request #11498 from julek-wolfssl/openresty-1.31.1.1
Add OpenResty 1.31.1.1 support and CI
2026-10-07 10:52:05 +10:00
Sean Parkinson
41fb718965 Merge pull request #11427 from gasbytes/crl-revoked-list-compat-api-fix
Invalidate cached STACK_OF(X509_REVOKED) when the CRL list head changes
2026-10-07 10:40:03 +10:00
Sean Parkinson
bbe7989fd3 Merge pull request #11375 from julek-wolfssl/feature/extending_comp_layer
Fix X509 extension handling (X509V3_ADD_*, extKeyUsage, EC point form) and cipher suite test
2026-10-07 10:32:54 +10:00
Sean Parkinson
fe9786e1ba Merge pull request #11353 from Frauschi/tls_mem_1
Cut the signature algorithms extensions down to what they actually need
2026-10-07 09:49:51 +10:00
Paul Adelsbach
02d796129d Add CB_ONLY mode for ML-DSA 2026-10-05 15:28:26 -07:00
philljj
3136f17a93 Merge pull request #11212 from padelsbach/cbonly-mlkem
Add CB_ONLY mode for ML-KEM
2026-10-05 16:17:33 -05:00
Juliusz Sosinowicz
854b1d3ff3 Address review: only set a conversion form oct2key can name
buf[0] & ~0x01 turns a hybrid leading byte into 0x06 and the point at
infinity's 0x00 into 0x00, neither of which
wolfSSL_EC_KEY_set_conv_form() accepts. Leave the key's form alone for
those instead of calling it with a value it rejects.

test_san_first_dns() also reported the original ASN.1 length after
truncating the copy, which could exceed the buffer it returns.
2026-10-05 05:20:16 +00:00
Juliusz Sosinowicz
10c53bbf7e X509_add1_ext_i2d: validate an extKeyUsage stack before replacing
wolfSSL_X509V3_EXT_i2d() copies the object stack without inspecting it, so a
REPLACE dropped the certificate's extKeyUsage and only then discovered that the
new stack could not be stored. Split the per-entry check out of
wolfssl_x509_add_ext_key_usage_sk() and run it before the removal.
2026-10-05 05:20:16 +00:00
Juliusz Sosinowicz
c229c140b7 X509_add1_ext_i2d: refuse an extension encoded under another NID
wolfSSL_X509V3_EXT_i2d() builds the authorityKeyIdentifier object from the
caller's issuer name when no key ID is given, and wolfSSL_X509_add_ext()
dispatches on that object rather than on the NID that was asked for. A REPLACE
therefore removed the certificate's authority key identifier and then failed,
or wrote into a different extension's storage. Check the encoded NID before
anything is removed.
2026-10-05 05:20:16 +00:00
Juliusz Sosinowicz
bb5765121a X509_add1_ext_i2d: report NIDs with no presence tracking
wolfssl_x509_ext_is_set() answered "absent" for every NID it does not know, so
DELETE and REPLACE_EXISTING failed with a reason indistinguishable from a real
absence, and DEFAULT and KEEP_EXISTING could not detect a duplicate. It now
reports "unknown" separately and only X509V3_ADD_APPEND, which is defined as
not checking, is attempted for such a NID.

X509V3_ADD_SILENT only gated WOLFSSL_MSG() calls that are compiled out without
DEBUG_WOLFSSL, and this API pushes nothing to an error queue. Drop the three
dead conditionals and document the flag as accepted but inert.
2026-10-05 05:20:16 +00:00
Juliusz Sosinowicz
76031d9797 Consume extKeyUsage object stacks in X509_add_ext
wolfSSL_X509V3_EXT_i2d() encodes extKeyUsage as a stack of ASN1_OBJECTs, which
wolfSSL_X509_add_ext() could not use at all. Map each KeyPurposeId OID to its
EXTKEYUSE_* bit and store the list as DER, the layout a parsed certificate
carries, so X509_get_ext_d2i() and X509_get_extended_key_usage() both read it
back. OIDs wolfSSL has no bit for stay in the list, matching the certificate
parser. Entries that are not a single OBJECT IDENTIFIER are rejected before
anything is stored.
2026-10-05 05:20:16 +00:00
Juliusz Sosinowicz
8994bcf45d Record the point conversion form in EC_KEY_oct2key
OpenSSL saves the encoding form on the key so that a later i2o_ECPublicKey()
re-emits it. Without this a compressed point silently round-tripped back as
uncompressed.
2026-10-05 05:20:16 +00:00