Commit Graph
31340 Commits
Author SHA1 Message Date
David Garske 558f1d9d64 Add WISeKey/SealSQ VaultIC secure element port 2026-08-04 18:49:31 -07:00
David Garske b802e461d8 Merge pull request #10955 from padelsbach/curve25519-cryptocb-only-full
Extend curve25519 crypto cb and cb-only for footprint savings
2026-08-04 18:46:35 -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 36c35c9a49 Merge pull request #11007 from kareem-wolfssl/zd22219
Fix a couple of issues in DTLS ClientHello parsing.
2026-08-04 17:21:39 -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
Paul Adelsbach e40f8d8f22 PR feedback: add missing strings and precompiler checks 2026-08-04 14:36:11 -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
David Garske e100f72548 Merge pull request #10938 from yosuke-wolfssl/fix/f_6767
Avoid writing into caller ikm buffer in wc_Tls13_HKDF_Extract
2026-08-04 10:43:24 -07:00
David Garske 5d5199b01e Merge pull request #10937 from embhorn/zd22160
Fix PKCS7 SignerIdentifier SKID to implicit [0] tagging
2026-08-04 10:33:15 -07:00
David Garske 3656306dd4 Merge pull request #10930 from julek-wolfssl/fenrir-wolfcrypt-tls-fixes
wolfCrypt and TLS 1.3 correctness fixes (F-1376, F-2653, F-1972, F-4593)
2026-08-04 10:31:44 -07:00
David Garske 7e5610debf Merge pull request #10911 from rizlik/der_import_trusted
wolfssl: expose trusted argument in ed25519/ed448 der export
2026-08-04 10:29:42 -07:00
David Garske 0fb71c572f Merge pull request #10949 from SparkiDev/aes_asm_gcm_tables_fixup
AES asm: Add GCM 8-bit tabl, fixes
2026-08-04 09:48:30 -07:00
David Garske d1a683d862 Merge pull request #11047 from danielinux/mcdc-part5-fixes
Bugfixes from MCDC part 5 campaign
2026-08-04 09:45:50 -07:00
Andrew Hutchings 5d20302d93 SE050: scope curve25519 keySize to the pre-7.2 arm
The applet >= 7.2 arm of se050_curve25519_shared_secret uses
CURVE25519_KEYSIZE directly, leaving keySize unused there and failing
-Werror maintainer builds with unused-variable.
2026-08-04 15:39:38 +01: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
Daniele Lacamera 40f191717c wc_port: bound the dst scan in wc_strlcat and return the attempted length
wc_strlcat measured dst with XSTRLEN(), which keeps reading until it finds
a NUL regardless of dstSize. When dst holds no NUL within dstSize -- the
case strlcat(3) explicitly bounds to prevent security problems in
incorrect code -- that read runs off the end of the buffer. Under
AddressSanitizer an unterminated 16-byte dst with dstSize 8 is a
stack-buffer-overflow READ of size 17.

Scan for the end of dst without passing dstSize. If no NUL is found the
length of dst is taken to be dstSize, nothing is appended and dst is left
un-terminated because there is no room for the NUL, matching strlcat(3).

The return value is now the total length attempted in every case: the
initial length of dst plus the length of src. The dstSize == 0 case
returns the length of src rather than 0, since nothing can be appended and
that is still the length the call tried to create.

Verified against the OpenBSD implementation over a matrix of dst values,
src values and destination sizes, including dst buffers containing no NUL
at all: 196 cases, identical return values and identical destination
buffers throughout.
2026-08-04 07:23:09 +02:00
Daniele Lacamera 24a207826d wc_port: return the source length from wc_strlcpy
wc_strlcpy returned the number of bytes it copied, so a truncating call
reported dstSize - 1 and a caller could not tell a truncated copy from an
exact fit. strlcpy(3) instead returns the length of src -- the length the
copy would have needed -- which is what makes the documented truncation
check (ret >= dstSize) work.

The doxygen comment in doc/dox_comments/header_files/types.h already
specifies "Length of source string", so this brings the implementation in
line with its own documentation rather than changing the contract.

Walking the remainder of src also gives wc_strlcat the length it attempted
in its truncating path, matching strlcat(3). No in-tree caller uses either
return value.

Verified against the OpenBSD implementation over a matrix of source
strings and destination sizes (including dstSize 0): identical return
values and identical destination buffers in all cases.
2026-08-04 07:16:43 +02:00
Paul Adelsbach d1548c89c9 Curve25519 crypto cb full 2026-08-03 16:30:31 -07:00
David Garske 5b22fa901e Merge pull request #10954 from aidangarske/pkcs11-ecc-pubkey-label
Set label and ID on PKCS11 EC public key
2026-08-03 11:36:43 -07:00
David Garske 47cdd2c3aa Merge pull request #11026 from kojo1/sig_min_hash_test
Honor WC_SIG_MIN_HASH_TYPE override in signature decision test
2026-08-03 11:17:12 -07:00
John Safranek 396a160954 Merge pull request #10984 from embhorn/zd22162
Enforce RFC 5746 renegotiation_info in TLS 1.2 client by default
2026-08-03 10:11:25 -07:00
JacobBarthelmeh b93f965a11 Merge pull request #11024 from yosuke-wolfssl/feat/JPdoc
[JA] Add missing Japanese dox_comments for 7 API groups
2026-08-03 10:57:53 -06:00
Daniel Pouzzner b04e07f8a4 Merge pull request #11036 from Frauschi/fix-os-check-run-length
OS check CI fix
2026-08-03 11:35:47 -05:00
David Garske 80631786fc Merge pull request #10958 from Frauschi/fenrir
wolfCrypt security hardening, portability fixes, and negative test coverage
2026-08-03 09:13:36 -07:00
David Garske 74ef67f5b0 Merge pull request #11018 from Frauschi/fenrir_3
Security and correctness fixes, plus a DTLS 1.3 scheduled work API
2026-08-03 09:13:21 -07:00
David Garske bd74881516 Merge pull request #10794 from JacobBarthelmeh/changelog
update description of ML-KEM AVX2 issue
2026-08-03 09:06:41 -07:00
Andrew Hutchings e30200c236 Drop WOLFSSL_MEM_FAIL_COUNT from known macro extras
tests/unit-mcdc/test_memory_whitebox.c defines the macro directly, so
the macro check now knows it without the extras entry and flags the
entry as unneeded.
2026-08-03 16:34:23 +01: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 d75c09296c SE050: derive ECDH shared secret via direct APDU on applet 7.2
The applet refuses to export a symmetric key object regardless of the
policy attached at its creation: on SE051 applet 7.2.0 hardware,
ReadObject on an HMACKey object whose attributes confirm an attached
POLICY_OBJ_ALLOW_READ still fails with SW 0x6986, so a derived secret
stored in an SE05x object can never be read back and the previous
attach-a-read-policy approach cannot work (ZD 22212).

Se05x_API_ECDHGenerateSharedSecret, which returns the shared secret
directly in the APDU response, is accepted by the same applet. It is
also what sss_se05x_derive_key_dh itself uses whenever the derived key
object lives in a host keystore, so use it for the applet >= 7.2 ECDH
offload instead of deriving into an SE05x object: pass the private key
id and the peer public point, taken from the wolfSSL key when the peer
is a software key or read back from the resident public key object
otherwise. Montgomery points and secrets are byte swapped around the
call, matching the middleware's own handling.

The pre-7.2 flow is restructured but behaviorally unchanged (Binary
derive target created by the middleware during the derive, read back
afterwards), and drops fewer APDUs per derive on 7.2 since no target
object is created, read or deleted.

Verified on SE051 applet 7.2.0 hardware: ECC P-256 and X25519 shared
secrets derive successfully in both directions, where the previous
approach failed with SW 0x6986. The pre-7.2 path remains as validated
on SE050C applet 3.1.1 hardware.
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 f165744b51 Add SSS_HAVE_SE05X_VER_GTE_07_02 to known macro extras
The SE050 port now keys the ECDH derive target type and read policy
off the middleware's SSS_HAVE_SE05X_VER_GTE_07_02 feature macro.
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 50bb36d3bc SE050: keep Binary ECDH derive target on pre-7.2 middleware
Real SE050 hardware (applet 3.1.1, JCOP4) refuses ReadObject on a
symmetric key object created without a read policy just like applet 7.2
does, and pre-7.2 middleware has no way to grant that policy:
sss_policy_common_u can_Read maps to POLICY_OBJ_ALLOW_READ only for
SSS_HAVE_SE05X_VER_GTE_07_02 builds and the symmetric key policy union
has no read flag at all. Switching the derive target to an HMACKey
object unconditionally therefore broke ECDH offload on applet 3.x parts
with SW 0x6986 at the shared secret export.

Restrict the HMACKey target and its attached read policy to
SSS_HAVE_SE05X_VER_GTE_07_02 builds and restore the original Binary
object flow otherwise: no pre-created target, erase before derive, and
the middleware creates the object when storing the derived secret.
Binary objects are readable without an attached policy.

Verified on SE050C (applet 3.1.1) hardware: the ECC and CURVE25519
wolfCrypt tests fail with SW 0x6986 without this change and pass with
it, matching master behavior on the same part. The applet 7.2 path is
unchanged.
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 473101ac95 SE050: attach read policy to ECDH derive target object (ZD 22212)
Applet 7.2 denies ReadObject on a symmetric key object that was created
with no policy attached, so the shared secret written into the derive
target by Se05x_API_ECDHGenerateSharedSecret_InObject could not be
exported: sss_key_store_get_key failed with SW 0x6986 (command not
allowed) on SE05x applet >= 7.2 hardware.

Create the derive target with an attached common policy granting read,
write and delete. An attached policy replaces the applet default
entirely, so write (the ECDH engine storing the result) and delete (the
cleanup path) must be granted explicitly alongside read. Guarded by
SSS_HAVE_SE05X_VER_GTE_07_02 so builds against older middleware keep
creating the object with no policy attached.
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
Andrew Hutchings e7ed0283a1 SE050: only flag curve25519 derive key after it is created
Align se050_curve25519_shared_secret with the ECC path: set
deriveKeyCreated only after sss_key_store_set_key succeeds, so the
cleanup path cannot erase or free a derive key object whose handle
was never allocated.
2026-08-03 16:34:06 +01:00
Andrew Hutchings 596a9a574c SE050: create ECDH derive target object for applet 7.2 middleware
Middleware built for SE05x applet >= 07_02 (required for SE052) derives
the ECDH shared secret with Se05x_API_ECDHGenerateSharedSecret_InObject,
which requires TLV[TAG_7] to reference an existing HMACKey object sized
exactly to the shared secret; otherwise the applet returns SW 0x6985
(conditions not satisfied). The port never created this object, so ECDH
offload failed with WC_HW_E on such builds.

Create the derive target as an HMACKey object of the exact secret size
before the derive, for both ECC and Curve25519 shared secrets. Read the
result back as AES type since sss_se05x_key_store_get_key has no HMAC
read case.
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
Daniel Pouzzner c3aebb970d Merge pull request #11037 from Frauschi/fix
Fix for check-source-text false-positive
2026-08-03 09:57:37 -05:00