Commit Graph

808 Commits (6e2b6f676c49f271b55f52dd35450d172ff8468c)

Author SHA1 Message Date
David Garske e51c06e0a6
Merge pull request #10983 from Frauschi/zephyr_fixes
Zephyr: wolfSSL module support for the wolfPSA provider and native RTOS use
2026-08-04 20:04:25 -07:00
David Garske 5f272267c0
Merge pull request #10901 from Frauschi/slhdsa_tls_handshake
Add SLH-DSA support for the TLS 1.3 and DTLS 1.3 handshake
2026-08-04 18:46:01 -07:00
David Garske 0ffedd2b69
Merge pull request #10971 from LinuxJedi/se050_applet72_ecdh
SE050: create ECDH derive target object for applet 7.2 middleware
2026-08-04 17:35:23 -07:00
David Garske d6708600a2
Merge pull request #11027 from Frauschi/fenrir_2
Fixes for OCSP stapling, cert manager, and certificate_status_request_v2 handling
2026-08-04 15:54:59 -07:00
David Garske 684e06df00
Merge pull request #10991 from padelsbach/ccache-init-seed-settings
CI: set ccache path so settings are saved on initial seed
2026-08-04 15:54:14 -07:00
Tobias Frauenschläger 039d689809
Merge pull request #10975 from aidangarske/x509-tiny-ci
Move WOLFSSL_X509_TINY test to the unit test suite and run
2026-08-04 23:28:52 +02:00
Tobias Frauenschläger ac75f181cd Add SLH-DSA support for the TLS 1.3 and DTLS 1.3 handshake
Implement SLH-DSA (SPHINCS+, FIPS 205) as an entity authentication
algorithm for the TLS 1.3 and DTLS 1.3 handshake, following
draft-reddy-tls-slhdsa. All twelve parameter sets (SHAKE and SHA2 families,
128/192/256 in the f and s variants) are wired into the handshake for
signing and verifying the CertificateVerify message; test certificates and
configs cover the 128f and 128s sets.

Handshake integration:
- Map the SLH-DSA signature schemes to and from the wire in the
  signature_algorithms extension and CertificateVerify. The mapping,
  advertisement, and OID handling are gated per parameter set so a build
  only offers, accepts, and maps the variants actually compiled in
  (including partial SHA2 builds).
- Sign and verify the CertificateVerify with an SLH-DSA entity key, and
  load SLH-DSA private keys and certificates (ssl_load.c, ssl.c,
  ssl_api_pk.c, asn.c).
- Preserve the verify return code on a failed SLH-DSA CertificateVerify
  rather than flattening every non-zero result to SIG_VERIFY_E.
  wc_SlhDsaKey_Verify already returns SIG_VERIFY_E on a real mismatch, so
  the failure semantics are unchanged while WC_PENDING_E (async crypto
  callbacks) and hard errors now propagate, matching ML-DSA and Falcon.

Protocol version gating:
- SLH-DSA is defined for TLS 1.3 only, so the schemes are no longer offered
  to a TLS 1.2 peer, and MatchSigAlgo and PickHashSigAlgo pin an SLH-DSA
  certificate both to the scheme for its exact parameter set and to
  TLS 1.3.
- Reject a Falcon, ML-DSA or SLH-DSA key in the TLS 1.2 CertificateVerify
  with SIG_TYPE_E. No signature scheme below TLS 1.3 covers a post-quantum
  key, the record is reserved for a classic signature, and the signing
  switches have no post-quantum case, so continuing would have sent the
  reserved buffer's uninitialized tail.

Streamed CertificateVerify send:
- SLH-DSA signatures are large (up to ~50 KB). When the CertificateVerify
  body exceeds a single record, generate the signature into a
  connection-level buffer and emit it one record at a time so the output
  buffer never has to hold the whole signature. This keeps peak memory near
  one signature plus a single fragment and resumes correctly across a
  non-blocking WANT_WRITE without recomputing the randomized signature.
  Gated by WOLFSSL_TLS13_STREAM_CERT_VERIFY (TLS 1.3, non-async, PQC
  signatures); DTLS and WOLFSSL_ASYNC_CRYPT keep the existing in-place
  fragmented path.
- Drop a half-sent streamed CertificateVerify in wolfSSL_clear. Left in
  place, the resume guard would fire on the next handshake and re-send the
  previous one's signature into a different transcript.
- Dual-algorithm (WOLFSSL_DUAL_ALG_CERTS, BOTH) CertificateVerify bodies are
  streamed as well. The combined two-signature body may include a
  variable-length signature, so the body buffer is sized from the
  per-signature upper bounds and the exact length is recorded after signing;
  the small trailing slack is never sent.

Buffer sizing:
- Keep MAX_X509_SIZE a fixed 9 KB for post-quantum builds. It sizes a
  static per-certificate slot embedded by value in every cached session, so
  it must not scale with a post-quantum signature; nor may it derive from
  the enabled ML-DSA level, or a level-restricted build would silently drop
  certificates that a full build keeps.
- Add MAX_CERT_WIRE_SZ for the largest certificate that may appear in a
  handshake message, sized from the enabled post-quantum signatures, and
  derive MAX_CERTIFICATE_SZ from it instead of from MAX_X509_SIZE.
- Add MAX_CERT_MSG_DEPTH for the chain depth assumed when sizing the
  certificate message. MAX_CHAIN_DEPTH bounds how deep a chain may be
  verified, while this sizes a buffer an unauthenticated peer can make us
  allocate, so it is trimmed to 5 when a post-quantum certificate has
  inflated the per-certificate size. Classic builds are unchanged.
- Size the CertificateVerify buffers from the actual signature length
  instead of the worst-case WC_MAX_CERT_VERIFY_SZ, which balloons with
  SLH-DSA. WC_MAX_CERT_VERIFY_SZ is retained for API compatibility and its
  growth is documented in README.md.
- Order Scv13Args widest member first so it carries no interior padding and
  still fits ssl->async->args under WOLFSSL_ASYNC_CRYPT together with
  WOLFSSL_DUAL_ALG_CERTS.

Dual-algorithm certificates:
- Reserve the two signature length prefixes in the in-place
  CertificateVerify sizing that the streamed path already accounted for.
- Build the PreTBS for an alternative signature check from the certificate
  size minus both signatures, and retry once at a size the canonical
  re-encode cannot exceed when that estimate turns out short. The estimate
  keeps the allocation small on constrained targets, and wc_GeneratePreTBS
  reports an encoder failure as WOLFSSL_FAILURE, which is zero, so a
  non-positive result is now an error instead of silently skipping
  ConfirmSignature and reading as a verified signature.

Device held private keys:
- Support an SLH-DSA private key that lives in a device and is referenced
  by id or label. The parameter set cannot be recovered from a device side
  identifier, so it is carried from the key type down to
  wc_SlhDsaKey_Init_id and wc_SlhDsaKey_Init_label, and the key is released
  with wc_SlhDsaKey_Free once the certificate and key pair is checked.

Robustness:
- Check the SlhDsaParamToType, wc_SlhDsaKey_PublicSizeFromParam and
  wc_SlhDsaParamToOid results in the certificate and key load paths.
- Zeroize an SLH-DSA key before wc_SlhDsaKey_Init, which can return
  NOT_COMPILED_IN before it clears the object, in both the certificate load
  path and AllocKey.
- Take the alternative key's parameter set from the certificate's sapkiOID
  rather than keyOID, which describes the native key.
- Re-initialise across hash families in wc_SlhDsaKey_PublicKeyDecode as
  wc_SlhDsaKey_PrivateKeyDecode already does. The hash objects share a union
  selected by family, so importing across families writes the new family's
  state over the old one's and orphans it.
- Copy pkCurveOID in SetSSL_CTX when only SLH-DSA is enabled, matching the
  struct member guard. Without it the field stayed zero and the signature
  scheme matching above was dead in exactly that build.
- Derive the per parameter set WOLFSSL_SLHDSA_PARAM_NO_* macros from the
  group level exclusions, and select WC_SLHDSA_DEFAULT_PARAM with those
  same macros, so the parameter table and the TLS mappings cannot disagree.
- Add SLH-DSA to the lean build WOLFSSL_MAX_SIGALGO carve-out, since twelve
  more entries no longer fit the small list.
- Prefix the new SLHDSA_ALL_NO_* macros in the installed header with WC_.

Tests and certificates:
- Add SLH-DSA entity (client and server) certificates for the SHAKE and
  SHA2 128f and 128s parameter sets, and update the generation script.
- Add TLS 1.3 and DTLS 1.3 entity-cert CertificateVerify test configs
  covering the fragmented (128f) and single-record (128s) send paths for
  both hash families, wired into suites.c. These sign with the entity key,
  so they are excluded from verify-only builds.
- Interrupt the streamed CertificateVerify with one WANT_WRITE and with
  several on the same record, and assert the handshake still completes and
  re-emits identical bytes, which the blocking .conf handshakes never
  exercise. The record to interrupt is counted first, because the server's
  record batching differs between builds. Where the flight is flushed as a
  single write the send is retried below SendTls13CertificateVerify, so
  these do not by themselves cover the fragOffset resume path.
- Drive the streamed path with an ML-DSA leaf under a negotiated
  max_fragment_length, covering it for a non SLH-DSA algorithm.
- Reject a TLS 1.2 handshake that presents an SLH-DSA client certificate.
- Map every compiled-in scheme from its wire code point to the key OID, and
  extend the exhaustive SaToNid coverage with the twelve new algorithms.
- Accept an SLH-DSA private key referenced by id and by label.

Build configuration:
- configure.ac: --enable-slhdsa now keeps the certificate/ASN code enabled
  (as --enable-mldsa does), so an SLH-DSA-only build with RSA, ECC and DH
  disabled configures instead of erroring that ASN is off.
- Guard the WOLFSSL, WOLFSSL_CTX and WOLFSSL_X509 pkCurveOID members for
  WOLFSSL_HAVE_SLHDSA, so an SLH-DSA-only build declares the field the
  handshake and CopyDecodedToX509 already reference under an SLH-DSA guard.
- Mark checkKeySz used in the SLH-DSA branch of ProcessBufferCertPublicKey;
  SLH-DSA is the only certificate signature algorithm with no minimum-size
  check, so an SLH-DSA-only build otherwise tripped -Wunused-parameter.
- Propagate haveSlhDsaSig in wolfSSL_set_SSL_CTX, which copied the Falcon
  and ML-DSA flags but not the SLH-DSA one.
- CI: add a SHA2-only SLH-DSA build (--enable-slhdsa=sha2) so the
  SHAKE-disabled combined-maxima guards are exercised, and an async crypto
  build with dual-algorithm certificates, which is the only configuration
  that compiles the in-place fragmented CertificateVerify send.
2026-08-04 22:23:03 +02:00
Aidan Garske 82cf3d8947 Add x509 tiny certificate test coverage 2026-08-04 12:21:25 -07:00
Paul Adelsbach 1c9ebe1af6 PR feedback: use instead of duplicating path 2026-08-04 12:06:11 -07:00
Tobias Frauenschläger 044f08c0ea Zephyr: wolfSSL module support for the wolfPSA provider and native RTOS use
Extend the wolfSSL Zephyr module for the wolfPSA-provider and secure-sockets
efforts:

  - Native RTOS threading: wolfCrypt's Zephyr port uses k_mutex/k_thread/
    k_condvar directly (no CONFIG_POSIX_THREADS), with k_condvar gated on the
    kernel version, covered by a native-threading ztest wired into CI.
  - Config interface: a user-supplied CONFIG_WOLFSSL_SETTINGS_FILE is
    authoritative and the module never layers Kconfig #defines over it. The
    module-default block is shaped by build-profile knobs (WOLFSSL_CRYPTO_ONLY,
    WOLFSSL_SINGLE_THREADED, which now defaults from !MULTITHREADING) plus new
    classic-crypto/TLS/PQC feature knobs (RSA/ECC/ChaCha-Poly/Curve25519/SNI/
    session-cache/session-ticket and ML-KEM/ML-DSA/LMS/XMSS/Falcon, each with
    its memory-reduction "small" options). A consumer such as wolfPSA validates
    its own requirements rather than the module injecting them.
  - DRBG seeding: wc_GenerateSeed() on Zephyr draws seed material from the
    hardware entropy driver when present (chunked to the entropy API's uint16_t
    length, DT_HAS_CHOSEN-guarded) and falls back to sys_rand_get() otherwise;
    HAVE_HASHDRBG stays guarded by WC_NO_HASHDRBG.
  - z_time(): read the native_sim simulator RTC for a real wall clock on the
    native targets regardless of libc.

Verified on native_sim/native/64 and nucleo_h743zi.
2026-08-04 20:53:36 +02:00
Andrew Hutchings 6176a5a77d SE050: skip peer key upload on applet 7.2 ECDH path (peer review)
The direct ECDH APDU carries the peer public point in the command, so
uploading the peer key to the SE050 on the applet >= 7.2 path wasted
APDU round trips, consumed a persistent object slot per distinct peer
in the default build, and added a failure path the derive does not
need. Confine the upload, the keyId bookkeeping and the keyCreated
cleanup to the pre-7.2 arm; on 7.2 builds a reference object is only
taken when the peer public key is already SE050-resident.

Also from review: validate the ECC direct-APDU response length against
the curve size, mirroring the Curve25519 arm; scope the derive-key
state (deriveKey, ctx_derive_key, deriveKeyCreated and their init and
cleanup) into the pre-7.2 arm instead of voiding it; and reword the CI
workflow comment to describe SE050_SIM_STRICT_ECDH as a regression
guard, noting the pre-7.2 arm is hardware-verified (SE050C applet
3.1.1) until an 03_XX matrix leg exists.

Verified: wolfCrypt suite passes against the strict simulator on the
07_02 build; the pre-7.2 arm compiles clean against an 03_XX SDK.
2026-08-04 11:42:20 +01:00
Sean Parkinson 03e9107df4 AES asm: Add GCM 8-bit table, fixes
Added assembly to do 8-bit-table GCM_gmult_len.
Wired it into aes.c and wired small to use C code.
Fixed guards around assembly.
2026-08-04 17:48:14 +10:00
Andrew Hutchings 160c616a97 SE050 CI: update pinned simulator to PR 12 head
The pinned simulator gained review cleanups; move SIMULATORS_REF to the
final wolfSSL/simulators PR #12 head. Becomes fetchable from the
upstream clone once that PR is merged.
2026-08-03 16:34:07 +01:00
Andrew Hutchings dc364d0eaa SE050 CI: pin simulator with direct ECDH variant support
Bump SIMULATORS_REF to the simulator commit that accepts the Tag7-less
direct ECDH form the port now uses on applet >= 7.2 and that refuses
HMACKey ReadObject unconditionally, both matching SE051 applet 7.2.0
hardware. The pinned commit is wolfSSL/simulators PR #12 and becomes
fetchable from the upstream clone once that PR is merged.
2026-08-03 16:34:07 +01:00
Andrew Hutchings a2bde67b70 SE050 CI: update pinned simulator to PR 11 head
The pinned simulator gained an sdk-test fix and review changes; move
SIMULATORS_REF to the final wolfSSL/simulators PR #11 head. Becomes
fetchable from the upstream clone once that PR is merged.
2026-08-03 16:34:07 +01:00
Andrew Hutchings 2ae4ec7300 SE050 CI: pin simulator that always enforces symmetric read policy
Bump SIMULATORS_REF to the simulator commit that refuses ReadObject on
an HMACKey object without POLICY_OBJ_ALLOW_READ in all modes, matching
real hardware on every applet generation as verified on SE050C applet
3.1.1 silicon. With this pin a plain (non-strict) CI run reproduces the
SW 0x6986 readback failure that previously only appeared on hardware,
covering the pre-7.2 Binary derive target fix in the previous commit.

The pinned commit is wolfSSL/simulators PR #11 and becomes fetchable
from the upstream clone once that PR is merged.
2026-08-03 16:34:07 +01:00
Andrew Hutchings 4c055f5272 SE050 CI: pin simulator with applet 7.2 read-policy enforcement
Bump SIMULATORS_REF to the simulator commit that, in strict mode,
refuses ReadObject on an HMACKey object unless the policy attached at
creation grants POLICY_OBJ_ALLOW_READ. This reproduces the SW 0x6986
derive-target readback failure seen on SE05x applet >= 7.2 hardware
(ZD 22212) and verifies the attached-policy fix in the previous commit.

The pinned commit is wolfSSL/simulators PR #10 and becomes fetchable
from the upstream clone once that PR is merged.
2026-08-03 16:34:07 +01:00
Andrew Hutchings 356aa6338b SE050 CI: correct pinned simulator commit id
The previous pin abbreviated to the right commit but the full hash was
invalid, so the simulator checkout step could never resolve it. Pin the
full commit id of the merged simulator change.
2026-08-03 16:34:06 +01:00
Andrew Hutchings 6213bbaf58 SE050 CI: pin strict simulator for applet 7.2 ECDH contract
Bump SIMULATORS_REF to the simulator commit that supports HMACKey
WriteSymmKey and the applet 7.2 ECDH InObject contract, and run the
test container with SE050_SIM_STRICT_ECDH=1 so the simulator refuses
an ECDH derive whose Tag7 target object was not pre-created. This is
the failure mode seen on SE05x applet >= 7.2 hardware and reproduces
it in CI against the unfixed port.

The pinned simulator commit also consumes the WOLFSSL_EXTRA_CFLAGS
build ARG, so the only-key-id matrix leg now really builds with
-DWOLFSSL_SE050_ONLY_KEY_ID (previously the ARG was not consumed and
the leg silently built the default configuration), and it fixes the
simulator to derive the EC public key on private-only key pair import
so wc_ecc_use_key_id can read the public part back.

Raise the job timeout for cold image rebuilds until the weekend cron
refreshes the registry cache for the new ref.
2026-08-03 16:34:06 +01:00
Tobias Frauenschläger 91769d99f6 CI: raise the os-check linux timeout and allow seeding on demand
The ccache that keeps this workflow fast is written only by the weekday
seed job, which runs on a schedule against the default branch. Nothing
had seeded it since 2026-07-24, because the workflow itself was failing
to load for that whole stretch, and the Actions cache evicts entries
untouched for seven days. The first run after the fix therefore reported
"Cache not found for input keys" on all four shards.

That cold run measured ~102 thread-minutes per shard, or 24-27 minutes
of wall including checkout, deps and autogen, against a 30 minute
timeout. Three minutes of headroom on the slowest shard is not enough,
and a shard killed by the timeout presents as a test failure rather than
as a cold cache. Raise it to 40. The comment above it claimed ~68
thread-minutes and ~20 minutes of wall, which the measurement above
contradicts, so replace it with the measured figures. macOS and Windows
are left alone: they came in at 11.6 minutes against 45 and 2.0 against
6.

Add workflow_dispatch so the seed can be run on demand rather than
waiting up to a day for the next cron, which matters exactly in the
situation above, where every PR run stays cold until something refills
the cache.

Adding the trigger alone would not have been enough. The seed behaviour
hangs off `github.event_name == 'schedule'` in five places (CCACHE_RECACHE,
--build-only on linux and macOS, the cache save, and skipping the Windows
job), so a manual run would have gone through the full test path and
saved nothing. All five now treat a dispatch as a seed as well.

The condition is written against `github.event.inputs.seed` rather than
`inputs.seed`, because the `inputs` context is only documented as
available on workflow_dispatch and workflow_call, whereas `github.event`
always exists. That yields strings, so it is compared explicitly rather
than for truthiness, where the string 'false' would read as true. It
tests `!= 'false'` and not `== 'true'` so that a dispatch which sends no
input at all still seeds: a declared default is not reliably reflected
into `github.event.inputs`, and keying on the positive would have made
`gh workflow run` quietly skip the seeding it was invoked to do.

Comments are brought in line with all of this, including one that was
already wrong before the trigger existed: the macOS ccache step is
read-only purely on pull_request, so every non-PR run writes that cache,
where the note claimed only the seed did. The two platforms seed
differently in a second way as well - linux sets CCACHE_RECACHE and so
rebuilds from scratch, macOS never does and only accumulates deltas.
Neither behaviour is changed here, but both are now written down at the
top of the file rather than left to be rediscovered from a surprising
cache.
2026-08-03 17:05:29 +02:00
Tobias Frauenschläger 641c39dbf3 CI: catch workflows that GitHub silently fails to load
A workflow file GitHub cannot load does not fail loudly. Its runs end
within 0s with zero jobs, no logs, no annotations and no check runs, and
the workflow re-registers under its bare path instead of its `name:`
field. Among the few hundred checks on a PR that reads as unrelated
flake, so the coverage just disappears: os-check.yml was in this state on
master for ten days in July 2026 before anyone noticed, and no open PR
reported a problem the whole time.

Add two guards.

Pre-merge, check-workflows.py measures every `run:` step against
GitHub's 21000 character cap and fails the build past it, with a warning
from 18000 so a growing step is noticed while there is still runway.
Sizes come from the parsed YAML, which is what the Actions service
evaluates, so block-scalar indentation needs no guessing. It runs from
check-source-text.yml over every workflow and composite action rather
than only PR-changed files: the cap applies per file, the whole sweep
takes well under a second, and a file can be pushed over the line by a
change elsewhere in the PR. Note that this cap is enforced by the
service and not by the workflow schema, so neither a YAML validator nor
actionlint reports it.

Post-merge, workflow-health.yml runs check-workflow-health.py daily and
looks for the symptom rather than any particular cause, so a workflow
that stops loading for a reason nobody anticipated is still caught. Two
signals: an active workflow whose registered name equals its path, and a
completed run that failed with zero jobs (prefiltered on
created_at == updated_at, so only a handful need a jobs lookup). Against
the live repository the first signal flags os-check.yml and nothing else
across 107 workflows, and reports clean on wolfTPM and wolfMQTT. It
exits 1 on a finding and 2 when the check could not be carried out at
all, because a missing token and a broken workflow call for different
responses.

Findings go into a single reused issue rather than another red check
that would blend into the noise: the body is rewritten on each run, a
comment is posted only when the set of affected workflows changes, and
the issue closes itself once everything loads again.

Finding that issue reliably turned out to be the fiddly part, and the
approach here is the one that survived testing against a live
repository. The issue is identified by both a dedicated label and its
title, and looked up through the REST issues endpoint. Both halves of
that identity matter: the label alone is a normal repository label that
anyone can apply, and an adopted issue has its body overwritten and is
then closed, so matching on the label alone would destroy a mislabelled
issue. Searching by title instead is unusable, because search ignores
--state and returns closed issues, which had the monitor re-closing an
already closed issue on every clean run. `gh issue list` reads a GraphQL
replica that can lag. The REST endpoint lags too, by about 2.4s for a
newly created issue, so the lookup re-checks a few times before
concluding nothing is open - without that, consecutive runs each open a
duplicate, and a clean run right after an outage fails to close the
issue it just opened.

Verified against the commit that caused the outage: check-workflows.py
fails on acff4d62a (21813 characters) and passes on its parent
f5ace71dd, which it flags at 20662 - already inside the warning band,
338 characters short of breaking. The full issue lifecycle (open,
repeat with no comment, comment on change, close, stay closed, reopen a
fresh issue for a new outage) was exercised end to end against a live
repository.
2026-08-03 17:05:29 +02:00
Tobias Frauenschläger a6bd8c00e4 CI: move parallel-make-check config lists into .github/configs
GitHub caps a single `run:` step at 21000 characters. os-check.yml
embedded its 109-entry Linux config list as a heredoc inside that step,
and commit c00e7260b ("Add AES-GCM DEM, CryptoCb support, and devId
threading to ECIES") pushed it from 20662 to 21813 characters. Since
that merge on 2026-07-24 GitHub has refused to load the file at all:
every run of the workflow ends in failure within 0s with zero jobs, on
master and on every PR branch.

The failure is easy to miss. The run registers under the literal path
`.github/workflows/os-check.yml` rather than its `name:` field, its
check suite carries no check runs so there are no logs or annotations,
and because GitHub cannot read the file it cannot apply the `on:`
filters either - hence the master push runs for a workflow whose push
trigger is restricted to release/**. Meanwhile `gh pr checks` still
reports hundreds of green checks from the other workflows.

Move the config lists to checked-in JSON under .github/configs/;
parallel-make-check.py already accepts the JSON path as its positional
argument. Splitting the step in two would not have been enough: the
heredoc alone was 21387 characters once de-indented.

  os-check-linux.json   109 configs
  os-check-macos.json     7 configs
  pq-all.json            31 configs
  multi-arch.json        23 configs
  smoke-test.json        10 configs

The os-check lists are the fix; the other three are preventive - pq-all
and multi-arch were the next largest run steps at 14076 and 11011
characters. The largest remaining run step is now 6285 characters.

Each list was compared object-for-object against the version it
replaces, so this is a pure relocation with no coverage change.
2026-08-03 17:05:29 +02:00
David Garske 56e92ea0dc
Merge pull request #10947 from night1rider/benchmark-msvc-arm64
benchmark: build the AArch64 cycle counter under MSVC/ARM64
2026-07-31 14:23:26 -07:00
Tobias Frauenschläger 1d15e1f27f Make OCSP stapling request ownership explicit
The OcspRequest carried a "void* ssl" back-pointer that the stapling
paths wrote just before handing the request to the OCSP layer. For the
request cached on the WOLFSSL_CTX that field is shared by every
connection using it, so concurrent handshakes raced on it. Drop the
field and pass the connection to CheckOcspRequest() and
CheckOcspResponse() as an argument instead, which is the only thing it
was ever read for.

Ownership of the cached request was equally implicit. Publication moves
out of CreateOcspRequest() into CreateOcspResponse(), and callers now
learn whether the CTX took ownership from a "ctxOwnsRequest" flag rather
than by comparing pointers against ssl->ctx->certOcspRequest, which was
read without the lock that guards it. The flag and the request are
handed back together on success and both left untouched on failure, so a
caller never decides ownership against a request it is not holding.

The cache is a field of the WOLFSSL_CTX, so serialize it with a lock
scoped to the CTX. SSL_CM(ssl) can resolve to a per-SSL cert manager
when WOLFSSL_LOCAL_X509_STORE is defined, which left two connections on
one CTX taking different locks for a check-then-set on the same pointer.
GetCtxOcspLock() keys off ssl->ctx->cm for both the reader and the
publisher, and a failure to take it is logged instead of silently
disabling the cache.

CheckOcspRequest() also loses its heap argument. It was only ever the
hint for the response buffer it hands back, which the caller frees
against the connection, so take it from the connection rather than from
a parameter every caller had to keep in step with its own free.

Smaller fixes in the same paths: zero the caller's response buffer
before the argument check can return, since SendCertificateStatus()
frees it without checking the return code; fold the ocsp_stapling NULL
check into the single early skip so the later uses need no guard;
gate the SetupOcspResp() free on success like the other two callers;
split the three differently owned requests in the
WOLFSSL_CSR2_OCSP_MULTI case into separate variables; and let that
case's allocation failures fall through to its shared cleanup instead of
returning, which leaked an already built leaf response.

Add test_ocsp_ctx_request_cache, which runs three handshakes over one
CTX pair and checks that the later ones reuse the cached request rather
than building another. The responder callback answers with a canned good
response, so stapling runs all the way through and the ownership
decision each connection makes is actually acted on: a connection that
freed the shared request shows up as a use after free on the next pass
and a double free at CTX teardown. The cached request is marked before
the last pass and the encoded request the callback sees is compared,
since a request rebuilt from the same certificate would otherwise be
identical byte for byte. The test is gated on !WOLFSSL_COPY_CERT:
OPENSSL_ALL implies it, and it gives every WOLFSSL its own certificate
copy, which takes the cache out of play. A new ocsp.yml job covers the
plain stapling build, an --enable-all build with the copy turned back
off, and an ASan build.

Also gate test_tls13_pha_status_request on KEEP_PEER_CERT. It checks the
received client certificate with wolfSSL_get_peer_certificate(), which is
only built when that macro is defined, so a post-handshake auth build with
stapling but without the OpenSSL compatibility layer failed to link
tests/unit.test.

Fixes F-7230 and F-7231.
2026-07-31 22:02:42 +02:00
Sean Parkinson c78f35725b
Merge pull request #10343 from MarkAtwood/feat/sbom-bomsh
feat: SBOM generation and OmniBOR build provenance (CRA compliance)
2026-07-27 21:28:22 +10:00
night1rider 59c79512e3 benchmark: build and run the wolfCrypt benchmark in Windows ARM64 CI 2026-07-24 16:42:44 -06:00
JacobBarthelmeh acff4d62a1
Merge pull request #10883 from night1rider/Extend-ECIES
Add AES-GCM DEM, CryptoCb support, and devId threading to ECIES
2026-07-24 14:02:32 -06:00
Paul Adelsbach a192af8ff9 CI: set ccache path so settings are saved on initial seed 2026-07-24 11:56:31 -07:00
night1rider c00e7260be Add AES-GCM DEM, CryptoCb support, and devId threading to ECIES
Add AES-GCM (128/256) as an ECIES DEM next to the AES-CBC/CTR+HMAC modes. Only the encryption key comes from the KDF; the mac salt is bound as GCM AAD and the 16-byte tag replaces the HMAC. The GCM DEM honors all three IV build modes, and default fixed-nonce GCM is gated behind the new WOLFSSL_ECIES_STATIC_GCM_NONCE opt-in. Adds ECIES CryptoCb encrypt/decrypt, the WOLF_CRYPTO_CB ctx getters, devId/heap threading into the DEM primitives, and test/benchmark/CI coverage.
2026-07-24 10:19:40 -06:00
Mark Atwood be9963f392 sbom: drop liboqs dependency support (removed from wolfSSL)
wolfSSL removed liboqs: Falcon is now provided natively by wolfCrypt, and
--with-liboqs is a deprecated no-op (configure.ac). A build therefore no
longer links liboqs, so recording it as an SBOM dependency is dead code and
the SBOM integration CI (which asserted a liboqs dep package) failed.

Remove the liboqs dependency throughout:
- scripts/gen-sbom: drop DEP_META['liboqs'] and the --dep-liboqs flag.
- Makefile.am / configure.ac: drop --dep-liboqs "$(ENABLED_LIBOQS)" and the
  now-unused AC_SUBST([ENABLED_LIBOQS]).
- .github/workflows/sbom.yml: drop the liboqs install / --with-liboqs steps
  and the liboqs dep assertion; keep the native-Falcon build so the
  HAVE_FALCON build-property capture is still exercised.
- scripts/test_gen_sbom.py: drop the liboqs-specific tests, guard against
  the key reappearing, and use openssl as the example dep elsewhere.
- doc/SBOM.md: drop the --dep-liboqs / liboqs dependency references.
2026-07-23 22:32:50 -07:00
Sameeh Jubran d08282ff9a sbom: use docdir, portable version parse, and widen CI filter
Use Automake's $(docdir) for sbomdir so a --docdir override is honoured,
match tab/space in the wolfSSL version parse ([[:space:]]), document the
GNU-make requirement and the intentional install/uninstall-sbom
asymmetry, and widen the SBOM workflow pull_request filter to '**' so PRs
onto release/** base branches also run.

Signed-off-by: Sameeh Jubran <sameeh@wolfssl.com>
2026-07-23 21:51:26 -07:00
Sameeh Jubran 5ab0ad9fab sbom: address advisory/SBOM review findings
- gen-advisory: honour explicit per-version status when defaultStatus is
  "affected", so unaffected/fixed releases are no longer marked vulnerable
- gen-advisory: fail loudly when a CVE record has no non-empty English
  description (CSAF/CycloneDX note text is required, minLength 1)
- gen-advisory: note that --cve-id fetches from the CVE Services API
- bomsh_verify: scope the object-store shape check to sha1, matching the
  sha1 gitoid hashing (drop the unreachable sha256-length branch)
- Makefile.am: fail `make bomsh` early when python3/pyspdxtools are absent;
  quote $(ENABLED_LIBZ)/$(ENABLED_LIBOQS); consolidate clean-local so the
  omnibor/ and advisories/out/ build dirs are removed on clean
- tests: cover the defaultStatus fix, the _bucket_for unknown-state
  hard-fail, and a csaf_validate.mjs runner self-test wired into CI

Signed-off-by: Sameeh Jubran <sameeh@wolfssl.com>
2026-07-23 21:51:26 -07:00
Sameeh Jubran 4ec80d309a feat: SBOM generation and OmniBOR build provenance (CRA compliance)
Add tooling to produce Software Bills of Materials and build provenance
for wolfSSL, supporting EU Cyber Resilience Act (CRA) obligations.

SBOM generation:
- New `make sbom` target producing SPDX 2.3 output with NTIA minimum
  elements, urn:uuid document namespaces, and SPDX LicenseRef compliance.
- Reproducible library discovery across autotools and CMake builds, with
  liboqs recorded as a linked artefact.
- Standalone `scripts/gen-sbom` for embedded / RTOS / custom-builder
  flows that do not use the main build system, plus --srcs-file,
  --no-artifact-hash, and hash-source options.

Build provenance (OmniBOR / bomsh):
- End-to-end bomsh tracing of the built binaries with ArtifactID
  insertion, snapshotting the traced library before libtool relink and
  hashing the bomsh-traced binary.
- `scripts/bomsh_verify.py` to validate provenance against the traced
  gitoid.

Security advisories:
- `scripts/gen-advisory` generating CSAF 2.0 and CycloneDX VEX, with a
  `make` target, VEX overlay schema/example, and CWE name data.

Docs, tests, and CI:
- doc/SBOM.md and doc/CRA.md, plus README/INSTALL updates.
- Unit and regression tests for gen-sbom and gen-advisory.
- New sbom.yml and advisory.yml workflows: SPDX validation via
  pyspdxtools, CSAF validation, bomsh provenance verification, SBOM
  artifact archiving, macOS coverage, and actions pinned to SHAs.

Signed-off-by: Sameeh Jubran <sameeh@wolfssl.com>
2026-07-23 21:51:26 -07:00
Sean Parkinson e23054ca9e
Merge pull request #10931 from julek-wolfssl/socat-ci-hang-fix
socat CI: prevent rare shard hang in inverted OPENSSL tests
2026-07-24 10:45:20 +10:00
Sean Parkinson 00c9405c24
Merge pull request #10969 from Frauschi/ci_flakyness_fixes
CI: reduce flakiness in the libssh2, trackmemory, and socat jobs
2026-07-24 10:41:54 +10:00
Sean Parkinson 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 Parkinson 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
Brett Nicholas e6d86b4bbb
Merge pull request #10832 from padelsbach/curve25519-cryptocb-only
Add crypto callback only mode for curve25519
2026-07-22 17:35:55 -06:00
David Garske 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
Tobias Frauenschläger adb0da74a9 Tolerate timing-flaky non-TLS socat tests via expect_fail
A few socat core tests intermittently fail the interop job with diff or
timeout mismatches. They exercise socat's own system()/socket/exec-pty
plumbing, not the wolfSSL backend, and race under the deliberate CPU
oversubscription of the parallel shard scheduling. With parallel-make-check
running fail-fast, one such flake in any shard aborts the whole job.

Add the observed offenders to the per-version socat test.sh --expect-fail
list: 23 (DUALSYSTEMFDSFLUSH) on 1.8.0.3, and 205 (TCP4ENDCLOSE) and 227
(EXECPTYKILL) on 1.8.0.0. test.sh keys its exit status only on unexpected
failures, so a listed test that later passes is reported as "OK unexpected"
and does not fail the job. Numbers come from each version's own test output,
so they match that version's numbering.
2026-07-22 16:51:31 +02:00
Tobias Frauenschläger c5518f2c18 Correct stale make-check timing weights in trackmemory CI
parallel-make-check.py schedules configs longest-first by their "minutes"
weight, but five of the seven trackmemory configs were weighted well below
their real runtime, which the run summary flags every time ("ran X min but
minutes says Y (>50% off)"). The underweighted configs include the two
wolfEntropy jitter configs, whose runtime already varies severalfold with
runner contention. Scheduling them last, on stale short weights, is what
lets a contended run drift into the 40-minute timeout.

Update the five flagged weights to the durations reported by the run
summary and re-sort the list descending so the slowest, most variable
configs start in the first scheduling wave and get the full time budget.
Config coverage is unchanged.
2026-07-22 15:26:36 +02:00
Tobias Frauenschläger ae1ea4079b Retry flaky libssh2 Docker tests with make recheck
The libssh2 integration tests start a fresh OpenSSH-server container per
test with "docker run -d -p 22" and then immediately open the SSH
connection. Docker maps the port as soon as the container starts, so the
TCP connect succeeds before sshd inside the container is ready to send its
banner, and the handshake fails with "Failed getting banner" (-43). This
shows up as an intermittent failure of a single test, most often
test_read, on unrelated pull requests.

Fall back to "make recheck" when "make check" fails. The automake parallel
test harness re-runs only the tests that did not pass, so a transient
container-readiness race no longer fails the job while a genuine failure
still does.
2026-07-22 15:07:46 +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
Juliusz Sosinowicz b0c0ceed3d socat.yml: assert retry=2 pattern before patching test.sh
Fail the shard loudly if socat's test.sh no longer contains the
fork,retry=2 pattern, instead of letting sed silently no-op and
reintroduce the hang while the run still looks green.
2026-07-22 13:30:12 +02:00
Juliusz Sosinowicz 2ed0369ecc socat.yml: tighten comment 2026-07-22 13:30:12 +02:00
Juliusz Sosinowicz 95b9dd653a socat.yml: prevent rare shard hang in inverted OPENSSL tests
The inverted testserversec OPENSSL tests (OPENSSLCERTCLIENT, the
commonname test and the fips test) run a foreground one-shot SSL
listener with no port-wait; their background connector exits after 2s
(retry=2, 1s apart). On a loaded runner the listener can bind after the
connector is already gone and then blocks in accept() forever, stalling
the shard until the job-level 15-minute timeout kills the run with no
diagnosable output. Seen once on a run whose re-run passed; reproduced
deterministically by delaying the listener past the retry budget.

- Widen the connector budget to retry=30. Retries only happen while the
  listener is not yet up and testserversec kills the connector as soon
  as the client returns, so passing runs are unaffected.
- Bound each shard with timeout(1) at 10 minutes (normal shard time is
  ~2 min) so any future hang fails fast and the shard output names the
  test that was running.
2026-07-22 13:30:12 +02:00
Daniele Lacamera 1a867244ed Falcon: CI-test every selectable backend, not just the default
The Falcon workflow only built --enable-falcon (default integer fpr). Add a
falcon_backends matrix that builds and runs testwolfcrypt for asm, double, avx2,
small-mem and avx2+small-mem on ubuntu-latest, and neon on the free ubuntu-24.04-arm
runner -- the SIMD/asm backends are the highest-risk code and now execute in CI.
verify-only is a build/link-only leg (its self-test needs signing). An AVX2 leg
guards on /proc/cpuinfo since backend dispatch is compile-time.
2026-07-22 09:52:27 +02:00
Daniele Lacamera 9e21ed4799 Falcon: fix liboqs interop workflow wiping the liboqs install
The falcon_interop job restored/untarred liboqs into the workspace and only
then ran actions/checkout, whose "git clean -ffdx" deleted the untracked
oqs-install/ directory. The interop harness build then failed with
"oqs/oqs.h: No such file or directory".

Move the wolfSSL checkout ahead of the cache-restore / artifact-download /
untar steps so the liboqs install lands after the clean and survives.

The harness itself is fine: built locally against liboqs it passes all eight
interop cells (liboqs<->native, both directions, levels 1 and 5).
2026-07-22 09:52:26 +02:00
Daniele Lacamera f2d79b554e Falcon: fix codespell and source-text CI checks
- codespell.yml: add "fpr"/"FPR" to ignore_words_list. "fpr" is the Falcon
  reference's canonical name for the floating-point primitive seam and
  appears hundreds of times across the sources; it is not a typo.
- wc_falcon.c: rename local "clen" -> "compLen" (codespell flagged clen)
  and replace a non-ASCII em-dash in a comment with "--" (check-source-text
  8-bit byte violation).
- wc_falcon_bigint.c: fix typos "morever" -> "moreover", "Mutiply" ->
  "Multiply".
- wc_falcon_codec.c: reword "are statics in" -> "are static functions in"
  (codespell flagged "statics").
2026-07-22 09:52:26 +02:00
Daniele Lacamera effc05a171 Falcon: remove FN-DSA / FIPS 206 references from code comments and text
Scrub the temporary "FN-DSA" name and the "FIPS 206" designation from all
in-tree comments, build text, and message strings, leaving the algorithm
named only as "Falcon". The eventual standardized name is not announced.

The differential known-answer test message ("wolfSSL FN-DSA differential
KAT") is a signed input, so the Falcon-512/1024 public keys and signatures
in wolfcrypt/test/test.c (and the mirrored Falcon-512 vector in
IDE/m33mu-falcon-verify/kat.h) were regenerated with liboqs over the new
message "wolfSSL Falcon differential KAT", preserving the differential
property (liboqs-produced signatures verified by the native verifier).

Verified: testwolfcrypt Falcon test passes; the m33mu verify-only harness
passes (BKPT 0x7f) with the regenerated vector.
2026-07-22 09:52:26 +02:00