Use readUnaligned32/64 to ensure no unaligned read faults.
Updated implementations of read/write unaligned 32/64 to not worry about alignment on CPUs that are known to not care.
Regenerate the SP backends so the ECDH secret generators check the caller's
buffer against the number of bytes actually written. Adds a P-384/P-521
buffer-size regression test.
Only exempt the missing-certificate check during the initial handshake; once a
post-handshake CertificateRequest is outstanding the server again requires the
client certificate (and its CertificateVerify). Adds a post-handshake auth
test.
Ensure a peer's certificate form (X.509 vs raw public key) matches the
negotiated certificate type, defaulting to X.509 when none was negotiated,
on both the client and server. Adds RPK regression tests covering both
directions.
Require the keyCertSign key usage on non-root intermediate CAs added during
path building when a KeyUsage extension is present, per RFC 5280. Adds a
regression test.
Addresses PR review feedback. The kernel-tracking linuxkm bundle treated a
failed --download-only as a warning and still published, so a transient
mirror error could ship a partial bundle. Because the daily job skips
rebuilds while the kernel label matches, such a partial bundle would
persist until the kernel next changes (~monthly), forcing consumers to fall
back to apt the whole time.
The linuxkm set is small and entirely required, so resolve it as one
closure and let a failure fail the job; we push only on success, so the
last good bundle stays in place. The static -full/-minimal bundles keep
their per-package skip-and-warn - they serve many independent consumer
subsets and rebuild weekly, so maximizing coverage is the right trade-off
there.
The handshake-message defragmentation buffer (pendingMsg/pendingMsgSz/
pendingMsgOffset/pendingMsgType) lived inside ssl->arrays, which
FreeHandshakeResources() releases once the handshake completes. For a
TLS 1.3 client the arrays are released whenever they are not being
retained for later use, e.g. when the library is built without
HAVE_SESSION_TICKET.
DoTls13HandShakeMsg() then took an "arrays == NULL" early path that
handed the record straight to DoTls13HandShakeMsgType() without any
reassembly. A post-handshake handshake message split across several
records -- such as a NewSessionTicket once a small max_fragment_length
has been negotiated -- was therefore rejected with INCOMPLETE_DATA (-310)
and the peer was reset. Fragmentation during the handshake was
unaffected because the arrays still existed at that point.
Move the defragmentation buffer fields out of Arrays and into the WOLFSSL
object so they survive FreeArrays(), and drop the now-unnecessary
arrays == NULL special case in DoTls13HandShakeMsg() so that
post-handshake messages are reassembled exactly like handshake messages.
The buffer is freed in wolfSSL_ResourceFree(). DoHandShakeMsg() (TLS 1.2)
is updated to use the relocated fields as well.
Add a regression test, test_tls13_fragmented_session_ticket, that
releases the client's handshake arrays after the handshake and injects a
NewSessionTicket fragmented across two records, confirming it is
reassembled and consumed instead of failing with INCOMPLETE_DATA.
Extends the ghcr offline-install path to every install-apt-deps consumer
that was still on plain apt, and publishes the bundles they need.
New bundles built by ci-deps-image:
- ubuntu-24.04-embedded: the membrowse ARM cross-toolchain (~0.5 GB), kept
out of -full so it does not bloat the interop workflows' pull.
- ubuntu-24.04-linuxkm: linux-headers-$(uname -r) + the kernel-module build
toolchain. linux-headers tracks the runner's running kernel, so a daily
job rebuilds it only when uname -r changed (recorded as an image label);
a mismatch during a runner-image rollout just falls back to apt.
Consumers now passing ghcr-debs-tag:
- sssd -> ubuntu-24.04-full (its deps added to that list)
- hostap-vm -> ubuntu-22.04-full (its deps added to that list)
- membrowse targets -> ubuntu-24.04-embedded; the two linuxkm targets ->
ubuntu-24.04-linuxkm (new per-target matrix.ghcr_tag)
- linuxkm.yml -> ubuntu-24.04-linuxkm (pinned to ubuntu-24.04 so the
bundle's headers match the runner kernel)
Each consumer still falls back to apt when its bundle is unavailable, so
nothing breaks until ci-deps-image first publishes the new tags.
A ::warning::/::error:: emitted with no file= property is pinned by GitHub
to the .github directory, whose blob URL is a directory listing - so the
stale-"minutes" annotations rendered with a dead source link and a line
number that points at nothing.
Derive the workflow file path from GITHUB_WORKFLOW_REF (owner/repo/path@ref)
and pass it as file= so the annotations link to the real workflow that
embeds the config list. Falls back to the previous fileless form off-CI or
when the ref is unavailable.
Zeroization:
- Add missing ForceZero on the PRF outputs and WOTS+ chain state that hold
secret key material.
- Route the WOTS sign leaf through a temp so secret chain values never touch
the public signature buffer.
- Add SLHDSA_SHAKE_X4_STATE_W so buffer and wipe sizes stay in sync.
Leak / alloc-failure fixes:
- Fix chain_idx_x4 returning on SAVE_VECTOR_REGISTERS2 failure without freeing
state/fixed (memory leak, and the secret was left unzeroized); break to the
cleanup path instead.
- Guard all function-scope wipes with WC_VAR_OK to avoid a NULL deref when an
allocation fails under WOLFSSL_SMALL_STACK.
The ci-cache-offload work added a ghcr .deb bundle path to
install-apt-deps, making the actions/cache apt-archive layer redundant.
Remove it so no apt-deps-* cache entries are produced. Apt packages now
install either offline from the ghcr bundle (when ghcr-debs-tag is set)
or via plain apt-get with the existing retry/backoff.
- Strip the Compute/Restore/Pre-seed/Collect/Save cache steps and the
cache-hit fast path; drop the now-unused 'cache' input.
- Update callers that passed 'cache': membrowse-onboard, membrowse-report
(and the apt_cache matrix key in membrowse-targets.json), and sssd.
The ghcr offline path and the ccache actions/cache usage are untouched.
Align the argument parsing and handling of input group names to align it
with OpenSSL behavior:
* Do a case-insensitive comparison of the input names with our names
* Add aliases for "MLKEMxxx" groups without underscores in addition to
our names with underscores (keep our for backward compatibility)
* Extend unit tests for both
Rebasing onto master (which migrated JS actions to Node.js 24 runtimes)
left a few action refs that this branch added in new steps still on the
old major versions. Bring them in line with master:
- ccache-setup read-only restore: actions/cache/restore@v4 -> @v5
- smoke-test / os-check ccache save: actions/cache/save@v4 -> @v5
- ci-deps-image checkout: actions/checkout@v4 -> @v5
- os-check.yml linux shard: add a schedule-gated CCACHE_RECACHE=1 step so
the weekday seed reseeds from clean compiles rather than only accumulating
deltas. This shard manages ccache directly (its own restore/save) and so
was not covered by the ccache-setup composite's reseed.
- install-apt-deps: hardcode the ghcr bundle owner to wolfssl. The bundle is
only published under ghcr.io/wolfssl by ci-deps-image, so fork PRs now read
the public upstream image instead of a nonexistent ghcr.io/<fork>/wolfssl-ci-debs.
- ccache-setup: document that the read-only restore key reuses the save
key shape for symmetry and is never an exact hit by design.
Skoll F3 (a packages-subset-of-bundle CI guard) is deferred to a follow-up;
F4 (release-branch ccache saves) is left as the intended seed-on-schedule /
everything-else-reads model.
Tighten three pieces of documentation to match the implementation; no
behaviour change:
- install-apt-deps (ghcr-debs-tag description): the apt mirror is avoided
only on the successful offline path. The offline install is a single
--no-download install of the whole package set, so any miss (bundle
absent/private/incomplete) falls back to the apt path.
- ci-deps-image header: each bundle is every requested package plus the
dependencies not already present on the matching runner image - tied to
that runner, not a portable/self-contained .deb closure.
- ci-deps-image schedule note: a package missing from the bundle fails the
whole offline install (it is not per-package), falling back to the full
apt path.
- ccache-setup: gate the scheduled-reseed step with
`if: github.event_name == 'schedule'` again. The github context IS
available in a composite action's step-level if: (install-apt-deps
already relies on it), so the earlier $GITHUB_EVENT_NAME workaround and
its comment were based on a wrong premise. The real load failure was the
${{ }} expression in the read-only input description, fixed separately.
- smoke-test.yml: include github.event_name in the concurrency group. The
workflow pushes to master/main and now also runs on a weekday schedule;
both share github.ref on the default branch, so under
cancel-in-progress a seed run and a master push could cancel each other.
The read-only input description embedded `${{ github.event_name ==
'pull_request' }}` as example text. GitHub validates ${{ }} expressions in
an action's input definitions at manifest-load time, where the github
context is not available, so the action failed to load ("Unrecognized
named-value: 'github'", action.yml line 27) and every ccache-setup
consumer died at "Set up ccache" (build library, make check, Compiler
test, Multi-arch test, ...). Describe the expression in prose instead of
embedding it as a live ${{ }} template; the github.* references that
remain are in step with:/run: blocks, where the context is available.
The scheduled-reseed step gated CCACHE_RECACHE with
`if: github.event_name == 'schedule'`, but the github context is not
available in a composite action's step-level if:. The action manifest
therefore failed to load ("Unrecognized named-value: 'github'"), and
every workflow using ccache-setup broke at the "Set up ccache" step
(build library, make check, Compiler test, Multi-arch test, ...).
Gate on the built-in $GITHUB_EVENT_NAME env var in the shell instead,
which keeps the schedule-only reseed behaviour with no caller changes.
The scheduled (cron) refresh restored the prior ccache and recompiled
only the translation units that changed, so unchanged objects were never
rebuilt and the shared cache could drift indefinitely. Set
CCACHE_RECACHE=1 on schedule events - gated inside the ccache-setup
action, so none of the calling workflows change - to force fresh
compiles that re-store every result. PR and push runs are unaffected and
keep their warm hits; only the scheduled jobs pay the full recompile.
- install-apt-deps: the ghcr offline-install path now honors the
no-install-recommends input; it was always installing recommends,
diverging from the regular apt path.
- install-apt-deps: correct the ghcr-debs-tag example to a real tag
(ubuntu-24.04-minimal) - ci-deps-image publishes -minimal/-full
variants, not a bare <ver> tag.
- os-check: fix the schedule header comment - macOS runs --build-only on
the weekday cron to seed its ccache (like the linux shards); only
Windows is skipped on schedule.
The 10 GB, LRU-evicted, PR-scoped Actions cache was being thrashed - the
docker simulator buildx layers (~6 GiB), plus per-PR ccache and apt-archive
writes whose keys never hit - which kept evicting the shared ccache, while
the apt mirror timed out often enough to break PR CI. Move the heavy caches
to ghcr (free, separate pool) and make PR runs read-only against the Actions
cache.
apt dependencies from prebuilt ghcr .deb bundles
- ci-deps-image.yml resolves each package list under .github/ci-deps/ into
its .deb closure and publishes ghcr.io/<owner>/wolfssl-ci-debs:<tag> in
two tiers: <ver>-minimal (make-check family) and <ver>-full (interop
superset), for ubuntu-22.04 and 24.04.
- install-apt-deps gains a ghcr-debs-tag input: pull the bundle and install
offline (--no-download) so the apt mirror is never on the PR critical
path. Any failure (bundle missing/not public/incomplete) falls through to
the existing apt path, so it is always safe to set.
sim-test buildx layers to a shared ghcr registry cache
- the 7 docker simulator workflows switch from cache-to: type=gha to
ghcr.io/wolfssl/wolfssl-sim-cache:<scope>. cache-from reads on every run
(anonymous); cache-to writes only on the weekend cron and manual
workflow_dispatch. Per-distinct-image tags and de-duplicated writers keep
parallel matrix jobs from racing on one ref.
ccache: PRs read, the schedule writes
- ccache-setup gains read-only: PR runs restore the shared master-scoped
cache but never upload; schedule/push runs refresh it. Wired across
os-check (linux + macOS), pq-all, smoke-test and the 12 small make-check
workflows.
- parallel-make-check.py gains --build-only (compile every config, skip the
test phase) so weekday-morning seed crons warm the cache PR runs consume.
artifact retention capped at 7 days on the failure-log/result uploads that
previously defaulted to 90.
ONE-TIME SETUP: after their first publish, make the ghcr packages
wolfssl-ci-debs and wolfssl-sim-cache PUBLIC so anonymous pulls work from PR
(including fork) runs; until then everything falls back cleanly.
GitHub Actions now emits "Node.js 20 actions are deprecated" warnings:
actions are forced to Node.js 24 by default starting 2026-06-16, and
Node.js 20 is removed from the runners on 2026-09-16. Update every
JavaScript action referenced by the workflows and the local composite
actions to the lowest release that runs on Node.js 24:
actions/checkout v4 -> v5
actions/checkout (SHA pin) v4.1.7 -> v5
actions/upload-artifact v4 -> v6 (v5 still Node.js 20)
actions/download-artifact v4 -> v7 (v5/v6 still Node.js 20)
actions/cache[/restore|/save] v4 -> v5
actions/setup-python v5 -> v6
actions/github-script v7 -> v8
docker/setup-buildx-action v3 -> v4
docker/build-push-action v5 -> v7 (v6 still Node.js 20)
docker/login-action v3 -> v4
microsoft/setup-msbuild v2 -> v3
open-watcom/setup-watcom v0 -> v1
Actions already running on Node.js 24 (jwlawson/actions-setup-cmake,
shogo82148/actions-setup-perl, msys2/setup-msys2, dorny/paths-filter)
are left unchanged. These bumps are runtime-only; no workflow uses an
input or output removed by the new majors, and v4-format artifacts
remain compatible across the upload v6 / download v7 backends.
fix F-3291: Copy-paste error in linuxkm_test_aesgcm error message uses WOLFKM_AESCBC_DRIVER
fix F-1431: AES-GCM RFC4106 SetKey Uses memcpy Instead of XMEMCPY for Nonce Copy
(note, for F-1431, changed all relevant memset() and memcpy() calls in linuxkm/ to XMEMSET() and XMEMCPY() respectively.)
Addresses review feedback:
- The "minutes" header comment described the check backwards (the
estimate drifting from the measured time). Reword it to match the
code, which warns when the measured time lands more than +/-50% away
from the estimate.
- Centralize the GitHub workflow-command escaping in gh_escape() and
apply it to the ::group:: title in dump() and the ::error:: summary in
main(), not just warn(), so a config name or step carrying %, CR or LF
cannot corrupt those commands either.
A config name comes from JSON and is only checked for emptiness and a
'/', so it can carry %, CR or LF. Passed straight into the ::warning::
workflow command those would truncate the annotation or be parsed as a
second command, so escape them in the GitHub branch of warn() per
GitHub's documented command-data encoding (% first). Local output is
unchanged.