Match OpenSSL signatures for X509_NAME_entry_count,
X509_NAME_ENTRY_get_object, X509_NAME_ENTRY_get_data and
ASN1_STRING_to_UTF8. Fixes -Wdiscarded-qualifiers warnings in OpenVPN.
wolfIP releases up to v1.1.0 have three Makefile rules that each run
tools/certs/mkcerts.sh, one per generated cert source. Under make -j
they run concurrently and clobber each other's files, leaving
server_cert.c without server_der, so build/test-wolfssl intermittently
fails to link. On the latest-release leg the job then asks for a
breaks-wolfip= token although wolfSSL broke nothing.
Run mkcerts.sh once before make so the cert sources already exist.
This stays harmless once wolfIP serializes the rule itself, and keeps
the released tags, which will never get that fix, building reliably.
The script is only run when present so a later wolfIP layout change
cannot fail the job here.
- WOLFSSL_ED448 now depends on !WOLFCRYPT_FIPS_V2 && !WOLFCRYPT_FIPS_V5.
Those modules drop SHAKE-256 in settings.h, so a CURVE448 selection
that defaulted Ed448 on stopped at "ED448 requires SHAKE256".
- On Zephyr 4.4 and later, default WOLFSSL_IP4, WOLFSSL_IP6 and
WOLFSSL_SOCKADDR_IN6 to NET_AF_INET, NET_AF_INET6 and
struct net_sockaddr_in6. The unprefixed names exist only under
CONFIG_NET_NAMESPACE_COMPAT_MODE, which NET_TEST without POSIX_API
turns off, so MatchIPv6() failed to compile in IP_ALT_NAME builds with
the built-in socket I/O, and the IPv4/IPv6 parsing in x509.c and ssl.c
would fail the same way with OPENSSL_EXTRA.
wc_MlKemKey_Init_Id names a key held by a crypto callback device. It sets
no key flags, because the private key never enters software. But
wc_MlKemKey_Decapsulate returned BAD_STATE_E for a key without
MLKEM_FLAG_PRIV_SET before calling the device, so a key named by id
could never decapsulate, on any device.
Check MLKEM_FLAG_PRIV_SET after the device call instead, next to the
MLKEM_FLAG_PUB_SET check that already guards the software path. A
device can then decapsulate with a key it holds. When it declines, or
there is no device, a key without a private key still gets BAD_STATE_E
before software reads any key material. wc_MlKemKey_SignCtx for ML-DSA
already dispatches in this order for the same reason.
test_wc_mlkem_decapsulate_id_key decapsulates with a key from
wc_MlKemKey_Init_Id through a callback device. It checks that the
device is called, and that BAD_STATE_E comes back when the device
declines.
- WOLFSSL_IP_ALT_NAME no longer requires NETWORKING with USER_IO or
CRYPTO_ONLY: the only socket use is the TLS layer's MatchIPv6(), which
is compiled out under WOLFSSL_USER_IO. prj-x25519-ed448.conf now
enables it with user I/O and no network stack.
- WOLFSSL_CERT_EXT no longer depends on WOLFSSL_CERT_GEN, matching
--enable-certext, since the macro also enables extension decoding.
- Add a wolfssl_tls_sock build with tls_cert.conf, so the TLS-only
options (post-handshake auth, IP SAN matching, kept peer cert) are
linked into a real handshake rather than dropped by the wolfCrypt test
app.
- Document the app-directory overlay fallback in zephyr-test.sh usage.
The wolfssl_test_cert, _x25519_ed448 and _ed25519_x448 twister scenarios
were not run by any workflow: zephyr.yml names its scenarios explicitly
and zephyr-4.x.yml builds from builds.txt instead of running twister.
Add all three to builds.txt, so each builds and runs on native_sim for
every Zephyr version in the 4.x matrix. The curve-split scenarios move
from extra_configs into prj-x25519-ed448.conf and prj-ed25519-x448.conf
so twister and the CI list read the same files, and zephyr-test.sh now
takes an overlay that is not in its own directory from the app
directory instead.
A Kconfig-configured wolfSSL could not enable CSR or key generation or
PKCS#7, so a consumer needing them, such as a certificate enrollment
client, had to supply a full settings file. Add options for
WOLFSSL_CERT_REQ, WOLFSSL_KEY_GEN, WOLFSSL_ALT_NAMES,
WOLFSSL_IP_ALT_NAME, WOLFSSL_CERT_NAME_ALL, WOLFSSL_PUBLIC_ASN and
HAVE_PKCS7, the last with the AES key wrap and X9.63 KDF that
--enable-pkcs7 adds, and for TLS 1.3 post-handshake authentication. All
default off. IP_ALT_NAME depends on NETWORKING, since its address
matching needs the socket address types.
Split WOLFSSL_CURVE25519 into X25519 and a new WOLFSSL_ED25519, which
defaults on with it so existing configurations keep Ed25519, and add
the same pair for Curve448 and Ed448.
PKCS#7 depends on RSA, ECC or ML-DSA, as settings.h requires a signing
algorithm.
A new wolfssl_test scenario turns every option on. Two more build each
X and Ed curve without its counterpart, one of them with WOLFSSL_USER_IO
and no network stack.
Three new options, each writing one define:
WOLFSSL_USER_IO leave the socket callbacks out, for an
application that installs its own transport and
therefore needs no network stack
WOLFSSL_CERT_GEN certificate generation
WOLFSSL_CERT_EXT the v3 extension setters
WC_LINUXKM_SVR_FORCE_DYNAMIC_AUDITING overrides and an svr_dynamic_auditing
runtime gate, conditional (when available) on IS_INTEL_AVX1(cpuflags), to avoid
false positive "inhibited-save instrumentation was not exercised" error at
startup.
Also add !defined(WC_SVR_USE_NATIVE_REG_BUFS) as a predicate for implicit
WC_LINUXKM_SVR_DYNAMIC_AUDITING -- no fallbacks to C occur with
WC_SVR_USE_NATIVE_REG_BUFS even if WC_C_DYNAMIC_FALLBACK is configured.
f608a41c56 bounds the explicit-parameter prime to MAX_ECC_BYTES in all
builds but A, B and the order only where WOLFSSL_ECC_CURVE_STATIC holds
them in fixed MAX_ECC_STRING buffers. Apply that bound in the dynamic
build too, so an explicit-parameter key decodes the same way however the
curve set is stored and the per-field regression tests exercise the
check in the default configuration. Field elements never exceed the
prime size, so the only key this refuses that the dynamic build took
before is one whose order is a byte wider than a prime already at
MAX_ECC_BYTES, which the static build refuses as well.
Replace the inline hash scrape with a call to fips-hash.sh so the
digest detection and length check apply here too. A rejected hash now
stops the run instead of running make check against a bad verifyCore,
and make clean only runs when verifyCore actually changed.
wc_LmsKey_SigsLeft() checked only for a NULL key and then passed
key->params to wc_hss_sigsleft(), which dereferences it. A key that
was only initialized has no parameters, so the call crashed. A
verify-only key (after wc_LmsKey_ImportPubRaw()) reported 1 although
wc_LmsKey_Sign() refuses it. Return 0 for both, as wc_LmsKey_Sign()
rejects such keys before it calls the device. The check is on the
verify-only state and not on WC_LMS_STATE_OK, because
wc_LmsKey_MakeKey() and wc_LmsKey_Reload() call wc_LmsKey_SigsLeft()
while the key is still in WC_LMS_STATE_PARMSET.
The doxygen for wc_LmsKey_SigsLeft() and wc_XmssKey_SigsLeft() said
they return the number of signatures left or a negative error code;
both return 1 or 0. Fix that in English and Japanese, and in the LMS
and XMSS group descriptions.
With non-blocking X25519 and an async device, the shared secret pends
and its result comes back through wolfSSL_AsyncPop() in
DoTls13ServerHello() and DoTls13ClientHello(), so an all-zero result
skipped the conversion in TLSX_KeyShare_ProcessX25519_ex() and no
alert was sent. Apply the same conversion at those two pops when the
completed operation belongs to an X25519 key.
Run the low-order key share cases again with an async device when
WOLFSSL_ASYNC_CRYPT is defined.
wc_MlDsaKey_InitId() and wc_MlDsaKey_InitLabel() called
wc_MlDsaKey_SetParams(key, WC_ML_DSA_87) even when their argument
check had failed and the key was never initialized, and ignored its
return value. With ML-DSA-87 compiled in (the default), an argument
error wrote into the caller's uninitialized object, and with the
WC_MLDSA_CACHE_* options or WOLFSSL_MLDSA_DYNAMIC_KEYS it zeroized and
freed whatever pointers that memory held. In builds without
ML-DSA-87 the call failed, so InitId and InitLabel returned 0 with no
parameter set.
Call SetParams only when the key was initialized, return its result,
and use the highest level compiled in, as wc_falcon_init_id() and
wc_falcon_init_label() do with FALCON_MAX_LEVEL.
When the X25519 part of a key share gives an all-zero shared secret,
wc_curve25519_shared_secret_ex() returns ECC_OUT_OF_RANGE_E, and
TLSX_KeyShare_ProcessX25519_ex() passed it on unchanged.
TranslateErrorToAlert() has no case for that code, so a TLS 1.3
handshake was aborted without an alert. Map it to ECC_PEERKEY_ERROR,
as a failed public key check already is, so that an illegal_parameter
alert is sent, as RFC 10024 Section 4.3 requires for the hybrid
groups.
Extend test_tls13_mlkem_bad_key_share with an order-8 X25519 point in
the X25519MLKEM768 ClientHello and ServerHello and in a plain X25519
ServerHello.
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.
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.
Size the CRL number string at 3 decimal digits per octet. The
CRL_MAX_NUM_SZ * 5 / 2 bound rounded down and was one byte short for
CRL_MAX_NUM_SZ of 1, 3 and 5.
Under WOLF_C89, XSNPRINTF is sprintf and ignores the size argument.
WOLFSSL_ERROR_LINE formatted the source file name into an 80-byte
buffer and wolfSSL_ERR_print_errors formatted the reason and file into
a 160-byte one, so long __FILE__ paths, as CMake builds produce,
overflowed the stack. GetTimeString wrote its 24-character string
regardless of the length wolfSSL_ASN1_TIME_to_string was given.
Bound the file name and reason with a precision, and format the time
into a local buffer and copy it only when it fits the caller's length.
DecodePolicyOID and GenerateDNSEntryRIDString wrote each OID arc
directly into the output with XSNPRINTF and rejected the result only
after the fact. Under WOLF_C89, XSNPRINTF is sprintf, so a certificate
with a long certificatePolicies OID or registeredID alt name wrote past
the output buffer while the certificate was parsed, before any
application call. DecodePolicyOID also serves wolfSSL_OBJ_obj2txt, where
it overflowed the caller's buffer.
Format each arc into a small local buffer and copy it only when it fits.
Behaviour with a bounded snprintf is unchanged.
wolfssl_print_number wrote each "xx:" group straight into the 50-byte
line buffer and checked the returned length to decide when to wrap.
Under WOLF_C89, XSNPRINTF is sprintf, so the group that did not fit was
written past the end of the line before the check, overflowing the
stack on every RSA, DH or DSA key print with more than 15 bytes.
Format each group into a small buffer and copy it only when it fits.
X509CRLPrintExtensions converted the CRL number to decimal in a 49-byte
stack buffer. A 20-octet CRL number, the maximum the parser accepts by
default, can need 49 digits, so the terminating NUL was written one
byte past the buffer when printing such a CRL with
wolfSSL_X509_CRL_print. Builds that raise CRL_MAX_NUM_SZ accept longer
numbers and overflowed it further, and the decimal string was then
formatted into an 80-byte line, which under WOLF_C89 is an unbounded
sprintf.
Size the buffer from CRL_MAX_NUM_SZ and write the number to the BIO
directly.
Fixes F-9101.
Several X509 print helpers formatted certificate-controlled data into
fixed stack buffers through XSNPRINTF and relied on checking the
returned length afterwards. Under WOLF_C89, XSNPRINTF is sprintf, so
the write overflowed before the check ran:
wolfSSL_X509V3_EXT_print wrote a key identifier as hex into a 129-byte
buffer, X509PrintSerial_ex wrote serials of up to 32 bytes into an
80-byte line, and X509PrintExtensions wrote the dotted OID of an
unrecognised extension into an 80-byte line.
Bound the key identifier with a precision, format each serial byte into
a small buffer and flush the line when full, and write extension OIDs
to the BIO directly. In builds with a bounded snprintf, long serials no
longer fail the print.
DhSetKey() only tests the server's DH prime when dhDoKeyTest is set and
dhKeyTested is clear. On the client both flags latched after the first
handshake: a successful test set dhKeyTested, and an FFDHE match in
GetDhPublicKey() cleared dhDoKeyTest. Neither wolfSSL_clear() nor
ReinitSSL() re-armed them, so a second handshake on a reused object, or a
renegotiation, installed the new server's p and g as trusted and accepted
a composite prime.
GetDhPublicKey() now clears dhKeyTested whenever it installs parameters
from the wire, and marks an FFDHE match as tested instead of clearing
dhDoKeyTest. dhDoKeyTest is left as the policy set by
wolfSSL_SetEnableDhKeyTest().
SendServerKeyExchange() allocates serverDH_Priv only when the buffer is
NULL, sized for the current prime, and DhGenKeyPair() then overwrites its
length with the size of the generated key. With secure renegotiation
enabled, FreeHandshakeResources() keeps the buffer, and wolfSSL_clear()
does not free it either. A renegotiation, or a reused server object, that
switches to a larger prime then hands GeneratePrivateDh() a buffer sized
for the previous key and the handshake fails with WC_KEY_SIZE_E.
Both DHE branches now zeroize and free a retained buffer that is shorter
than the new prime needs, so it is allocated again at the right size. The
public key buffer already had a renegotiation-only realloc for the same
reason.