wolfSSL_dtls_export()/wolfSSL_dtls_import() only ever carried a DTLS 1.2
session. A DTLS 1.3 connection additionally keeps a table of epochs, each
with its own traffic secret, record and record number keys, sequence numbers
and replay window, and none of that was serialized.
Export version 7 adds two trailing sections to the blob, the DTLS 1.3 record
layer state and the Connection ID, both length prefixed so a reader that does
not know a section can step over it and a version 6 blob still imports.
- dtls13: serialize the send epoch, the peer epoch and, when there is one,
the previous peer epoch: epoch numbers, sequence numbers, replay window,
traffic secrets and key material. Import re-derives the record keys through
Tls13DeriveRecordKeys(), the same expansion the handshake runs
- dtls: carry a tx Connection ID of any length. The peer picks it and RFC 9146
bounds it only by its one byte length field, so DTLS_CID_MAX_SIZE may not
refuse it. The rx id keeps that bound: it is the one we hand the peer and it
has to fit the record layer buffers. Clear the target's CID when the blob
carries none
Refusals, so a blob never describes a connection that cannot be restored:
- refuse to export a half sent fragmented handshake message, or while a write
dup still has work parked
- refuse a state only import into a DTLS 1.3 session, and keep stamping the
state only blob with export version 6
- require the imported epochs to be the ones the blob names, reset the epoch
table on import and commit a slot only once every field of it has been read
Bounds checking on the import path:
- keep every exported section inside the buffer the caller sized, and step
over the import sections by their declared length
- check the imported epoch key lengths against the negotiated suite and the
traffic secret length against the hash
- size the exported key state from the build's own cipher sizes
- scrub the session export scratch buffer before freeing it
- use IsAtLeastTLSv1_3() for the imported version check
CI: build the session export job with Connection ID support.
The second half of DeriveTls13Keys() - the "key"/"iv" labels, the provision
computation and the four Tls13DeriveKey() calls, plus Dtls13DeriveSnKeys() -
is the expansion of a pair of traffic secrets into the record keys. It is
reachable only through a full secret derivation, so a caller that already
holds the secrets cannot use it.
- add Tls13DeriveRecordKeys(), which expands the traffic secrets in
ssl->clientSecret/serverSecret into ssl->keys and derives the DTLS 1.3
record number key; it owns the key_dig buffer and its zeroization
- DeriveTls13Keys() keeps the secret derivation, the store gate and the
DTLS 1.3 epoch bookkeeping, and no longer allocates key_dig when store is 0
No functional change.
wolfSSL/simulators#17 (P-256 + 28-byte-digest verify case in
wolfcrypt-test) merged to main as c827ac7. Pin the workflow to that
merge commit so the STSAFE job exercises the regression test against
the digest normalization fixed on this branch.
The A100/A110 stsafe_verify wrote *pResult before validating any of
its arguments, unlike the A120 variant which rejects NULL inputs.
Move the argument validation (pointers plus hashSz) ahead of the
*pResult write and the buffer allocation, so a NULL argument returns
BAD_FUNC_ARG instead of dereferencing, and the early return happens
before the SMALL_STACK buffers are allocated.
Addresses the PR review note on *pResult before validation.
hashSz is a caller-supplied word32 (the public wc_ecc_verify_hash API
passes its length straight through to the crypto-cb). Converting it to
int before clamping lets values above INT_MAX wrap negative, and the
normalized-copy pointer arithmetic then writes out of bounds of the
field-size digest buffer. Clamp in the word32 domain first; the int
conversion then only happens for values bounded by key_sz.
Both variants (A120, A100/A110) carry the same fix. Both call sites
already reject key_sz <= 0, so no key_sz check is added here.
Addresses the PR review note on the copy_sz cast.
The pinned wolfSSL/simulators ref gains the P-256 + 28-byte-digest
verify case in wolfcrypt-test, which exercises the digest
normalization fixed in the previous commit. The simulators branch
carrying 9f9900295 (PR wolfSSL/simulators#17) must be pushed/merged before this ref is reachable.
stsafe_verify copied key_sz bytes from the caller's digest buffer and
told the SE the digest was key_sz bytes long. For a digest shorter than
the field size (P-256 with a 28-byte SHA-224 hash, P-384 with SHA-256)
that reads past the end of the buffer and submits a wrong digest, so a
valid signature fails to verify.
The A120 expects a field-size prehash on the wire, so the digest is
normalized host-side before submission: truncate if longer, left-pad if
shorter - the same convention the sign path already applies. The SE
still receives key_sz bytes, so the wire contract is unchanged; only
the buffer contents for short digests are corrected.
Both variants (A120 STSELib, A100/A110 legacy SDK) and both call sites
(crypto-cb, TLS verify-peer callback) now use the real digest length.
Verification:
- Built: host x86_64, --enable-stsafe=a120, STSELib v1.1.7 + Rust
A120 simulator.
- Tested: wolfCrypt STSAFE-A120 sim test (wolfSSL/simulators
wolfcrypt-test): new P-256 + 28-byte-digest verify case fails on the
pre-fix build (valid signature rejected) and passes post-fix; rng,
on-device keygen, sign and 32-byte verify round-trip unchanged.
- A100/A110 variant not runnable here (closed SDK, no silicon); change
mirrors the A120 logic on the existing buffer and keeps Length=key_sz.
Added a bunch of content about how to use ASN templates.
Added a section with a list of things to do when adding a new template.
Added mappiong of ASN.1 notation to template lines.
Added ASN.1 type specific information.
Added a checklist at the end to head off the common issues.
Added references to ASN_TEMPLATE.md.
Added other informatrion.
wc_curve448_make_key and wc_curve448_export_public_ex derived the public
point through the keyless wc_curve448_make_pub, which dispatches to the
first registered device; route them through a devId-carrying helper.
Mirror curve25519: keygen, shared secret, make pub and generic
callbacks, wc_curve448_init_ex/new/delete, new wc_curve448_generic
API with scalar clamp checks, WOLF_CRYPTO_CB_ONLY_CURVE448 mode,
TLS devId plumbing, tests (test.c, api unit tests, swdev),
benchmark devId, CI entries.