Update specs to PSA 1.4 + Low/Info fenrir fixes#19
Conversation
…_verify Test that psa_aead_finish on a decrypt context and psa_aead_verify on an encrypt context both return PSA_ERROR_BAD_STATE, covering the direction enforcement checks that had zero test coverage.
…h, and non-hash-alg paths The ConstantCompare mismatch-detection branch was reachable only by calling psa_hash_compare before psa_crypto_init (PSA_ERROR_BAD_STATE) or with a NULL reference hash (PSA_ERROR_INVALID_ARGUMENT). The success path and the critical INVALID_SIGNATURE path were entirely untested, so a mutation of the ConstantCompare check or the hash_length guard would survive undetected.
…rypt Both xchacha20 helpers checked alg != PSA_ALG_CHACHA20_POLY1305 (passing IETF ChaCha20), but then invoked wc_XChaCha20Poly1305_Encrypt/Decrypt and required a 24-byte XChaCha20 nonce. Invert the check to reject PSA_ALG_CHACHA20_POLY1305 so the standard IETF algorithm identifier cannot route to the XChaCha20 primitive.
Mirror the decrypt branch's wc_ForceZero pattern: introduce a cbc_pkcs7_encrypt_done label so the stack buffer holding the last partial plaintext block plus PKCS7 padding is always scrubbed before the function returns, on all three exit paths (NOT_SUPPORTED, wolfCrypt error, and success).
…modifying output on BUFFER_TOO_SMALL The ciphertext size check (ciphertext_size < out_len + tag_length) ran after psa_aead_finish had already written plaintext_length bytes of ciphertext into the caller's buffer, violating the PSA Crypto API requirement that BUFFER_TOO_SMALL must not modify output buffers. Add an early check using wolfpsa_aead_tag_length before calling psa_aead_finish, using overflow-safe subtraction. The post-finish check is kept as a defence-in-depth assertion.
…_cipher_encrypt iv_len is deterministic from wolfpsa_cipher_iv_length before any side-effectful call, so the output_size < iv_len check was needlessly ordered after psa_cipher_generate_iv, which consumed entropy and mutated operation state even when the caller's buffer was too small. Move the check ahead of the generate call so BUFFER_TOO_SMALL is returned without drawing from the RNG.
…c and wire it in psa_asymmetric_export_public_key_ecc was dead code missing wc_ecc_make_pub_ex in the key-pair branch, which would cause wc_ecc_export_x963 to fail on a private-only key. Add the missing call (matching the verify path at psa_ecc.c:247 and the inline block it replaces in psa_key_storage.c), add a forward declaration, and replace the duplicated inline block with a call to the function. Add test_ecc_export_public_key to cover psa_export_public_key on a SECP R1 key pair.
…aead_setup Wildcard AEAD algorithms (PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG set) are policy-only constructs per the PSA Crypto spec and must not be accepted as the algorithm for an AEAD operation. Without this check, the flag bits were silently ignored and min_len was used as the concrete tag length.
…y_ex call Integer division truncates for P-521 (521/8=65), but the correct byte length is 66 (PSA_BITS_TO_BYTES(521)=66). The rest of the function already uses PSA_BITS_TO_BYTES consistently; align the wc_ecc_make_key_ex keysize hint to match.
…rks for Ed448PH PSA_ALG_SHAKE256_512 was missing from psa_hash_engine.c, causing psa_hash_compute() to return PSA_ERROR_NOT_SUPPORTED whenever psa_sign_message() or psa_verify_message() was called with PSA_ALG_ED448PH. Add PSA_ALG_SHAKE256_512 cases (guarded by WOLFSSL_SHAKE256) to all seven switch statements in psa_hash_engine.c: check_alg_supported, get_size, cleanup, setup, update, finish, and clone. Add test_ed448_sign_message to cover the full psa_sign_message/psa_verify_message roundtrip for Ed448PH.
…lers The three WOLFSSL_LOCAL check helpers were never called; psa_aead.c performs the equivalent validation inline. Removing them eliminates dead flash and prevents undetected mutations.
src/psa_tls_prf.c and wolfpsa/psa_tls_prf.h defined five WOLFSSL_LOCAL TLS 1.3 PRF helpers (psa_tls_prf_check_alg_supported, psa_tls13_prf, psa_tls13_hkdf_extract, psa_tls13_hkdf_expand, psa_tls13_hkdf_expand_label) that had no callers anywhere in the codebase. The header was only included by the implementation file itself. Same pattern as F-3429.
…ranch The check `out_len < ctx->tag_length` was dead code: psa_chacha20_poly1305_encrypt always sets *ciphertext_length = plaintext_length + tag_size on success, so out_len equals input_length + tag_length and the condition reduces to input_length < 0, impossible for size_t. The correct bound to protect the subsequent XMEMCPY(tag, tmp + input_length, tag_length) is out_len < input_length + tag_length.
…MAC-KDF Enable the wolfCrypt backends needed for PSA 1.4: WOLFSSL_HAVE_MLKEM, verify-only LMS/XMSS, Ascon (experimental opt-in), XChaCha, AES key wrap and CMAC KDF. Add ascon.c to the wolfCrypt source list. Quarantine the legacy ML-KEM and LMS/XMSS modules behind #if 0: they target headers and APIs that no longer exist on wolfSSL master (mlkem.h, lms.h/xmss.h, psa_ml_kem_parameter_t) and are rewritten in the PSA 1.4 work. Replace the stale WOLFSSL_HAVE_KYBER guard in psa_pq.c and add psa_pqc_internal.h with the internal PQC backend contracts.
Fill the previously empty PQC macros in crypto-pqc.h with the exact spec-defined implementations (ML-DSA/ML-KEM/SLH-DSA classifiers, key types, HashML-DSA encodings) and drop the nonstandard psa_ml_dsa_parameter_t / PSA_ML_DSA_PARAMETER_* convention. crypto_values.h: add 1.3/1.4 algorithm and policy values (EDDSA_CTX, KW/KWP, XOF algs, ECIES_SEC1, Ascon AEAD/hash, XChaCha20, SP800-108 KDFs, WPA3-SAE, WRAP/UNWRAP usage flags) and adopt the 1.4 example definitions of the sign-classification macros. crypto_sizes.h: ML-DSA/ML-KEM arms for sign/export sizes, KEM ciphertext sizes, key-wrap output sizes and the hash-suspend format constants; raise the max-size constants that ML-DSA now dominates. crypto.h/crypto_struct.h: declare psa_encapsulate/psa_decapsulate, the four *_with_context signature functions, key wrapping, the XOF operation API, hash suspend/resume, psa_attach_key and psa_check_key_usage; remove the legacy psa_ml_dsa_*/psa_lms_verify/ psa_xmss_verify declarations and add psa_xof_operation_t. Quarantine the legacy ML-DSA backend and its psa_api_test coverage pending the seed-based rewrite.
Rewrite the ML-DSA backend around the spec key format: key pairs are the 32-byte FIPS 204 seed xi with bits 128/192/256, public keys are raw pk bytes. Sign/verify dispatch covers hedged and deterministic pure ML-DSA (wc_MlDsaKey_SignCtx / SignCtxWithSeed with a zero rnd) and HashML-DSA over pre-computed digests (SignCtxHash/VerifyCtxHash), with signing contexts up to 255 bytes. Rewrite the ML-KEM backend against wc_mlkem.h: key pairs are the 64-byte d||z seed (FIPS 203) expanded via wc_MlKemKey_MakeKeyWithRandom on each use; encapsulation accepts raw public keys or seeds and decapsulation enforces exact ciphertext length, relying on ML-KEM implicit rejection. Breaking change: the legacy psa_ml_dsa_* public API and its level-as-bits (2/3/5) convention are gone.
psa_kem.c: psa_encapsulate/psa_decapsulate returning the ML-KEM shared secret as a new key created from caller attributes; ciphertext is staged locally so no partial result escapes on failure. psa_xof.c: incremental SHAKE128/256 XOF operations. wolfCrypt's Shake Absorb finalizes padding per call, so update() accumulates input and absorbs once at first output(); output is served at byte granularity over block-wise squeezes. Ascon XOFs report NOT_SUPPORTED. psa_key_wrap.c: psa_wrap_key/psa_unwrap_key with AES-KW (RFC 3394), mapping the integrity-check failure to PSA_ERROR_INVALID_SIGNATURE; KWP reports NOT_SUPPORTED (no wolfCrypt backend). psa_lms_xmss.c: verify-only LMS/HSS and XMSS/XMSS^MT backends importing raw public keys (XMSS retries the XMSS^MT OID table on lookup miss). psa_api_stub.c: NOT_SUPPORTED stubs for the interruptible operations, psa_attach_key and hash suspend/resume; trivial max-ops accessors; and psa_generate_key_custom / psa_key_derivation_output_key_custom delegating wrappers that accept only default parameters.
psa_key_storage.c: ML-DSA/ML-KEM key lifecycle (generate seeds via the PQC backends, import validation for seed and raw public formats, bit inference from public-key lengths, public-key derivation from seeds in psa_export_public_key), LMS/HSS/XMSS public-key import, XChaCha20 keys, WRAP/UNWRAP usage flags and the new psa_check_key_usage. psa_asymmetric_api.c: refactor sign/verify into context-aware workers and add the four *_with_context entry points (context <= 255 bytes, non-empty context only for EDDSA_CTX/Ed25519ph/Ed448ph/Ed448 pure and the ML-DSA family). ML-DSA dispatches before the pre-hash step so raw messages are signed directly; HashML-DSA pre-hashes via PSA_ALG_GET_HASH; pure ML-DSA is rejected in the hash entry points. LMS/HSS/XMSS/XMSS^MT verify through psa_verify_message. Policy gains the HashML-DSA ANY_HASH wildcard and the 1.4 rule that ECDSA and deterministic ECDSA are equivalent for verification. psa_ed25519_ed448.c: thread the signing context through to wolfCrypt (Ed25519ctx via wc_ed25519_sign_msg_ex, Ed448 context parameters). psa_pq.c: ML-DSA sizes are now 128/192/256; LMS/HSS/XMSS/XMSS^MT are public-key-only with bits = hash output length; SLH-DSA reports NOT_SUPPORTED. wolfpsa.map: export the new 1.4 entry points, drop psa_ml_dsa_*.
Hash engine: Ascon-Hash256 (one-shot and multipart, POD clone). AEAD: one-shot XChaCha20-Poly1305 (24-byte nonce) and Ascon-AEAD128 (16-byte key/nonce/tag); multipart setup reports NOT_SUPPORTED for both. Key derivation: SP800-108r1 counter-mode KDF in HMAC and AES-CMAC variants per the PSA 1.4 construction (4-byte counter, label, zero separator, context, output length in bits; the CMAC variant mixes in K(0)), with L snapshotted from the operation capacity at first output. Headers: PSA_HASH_LENGTH arm for Ascon-Hash256, AEAD nonce lengths for XChaCha20/Ascon (nonce max now 24), default-length-tag cases for the new AEAD algorithms and PSA_KEY_DERIVATION_INPUT_CONTEXT.
Add nine feature-area coverage tests (ML-DSA, ML-KEM and the KEM API, SHAKE XOF, AES-KW key wrapping, signature contexts, LMS/XMSS verify-only with wolfSSL KAT vectors, Ascon and XChaCha20-Poly1305 KATs, SP800-108 counter KDFs, and 1.4 miscellany: stubs, custom wrappers, psa_check_key_usage, ECDSA verify-equivalence, size macros), wire them into the test Makefile and the CI workflow, and document the 1.4 upgrade in the CHANGELOG. Fix flagged by the Ascon test: map ASCON_AUTH_E to PSA_ERROR_INVALID_SIGNATURE in the Ascon-AEAD128 decrypt path.
Running the build-config matrix against the 1.4 changes exposed -Werror failures when the new backends are compiled out: unused locals in psa_wrap_key/psa_unwrap_key without HAVE_AES_KEYWRAP, an unused key_bits in psa_decapsulate without WOLFSSL_HAVE_MLKEM, and an unused bits parameter in psa_pq_check_key_size_valid when every PQC backend is off. Fix all three. Sync build-variant.sh's baseline with the new wolfCrypt knobs (ML-KEM, verify-only LMS/XMSS, Ascon + experimental opt-in, AES-KW + AES direct, XChaCha, CMAC-KDF) and add matrix lanes that disable each new feature. Companion removals for existing lanes: chacha20-poly1305 also drops XChaCha, cmac drops the CMAC KDF, sha3-ed448 drops ML-KEM (it needs SHA-3/SHAKE), and AES key wrap explicitly carries WOLFSSL_AES_DIRECT, which wolfSSL requires for HAVE_AES_KEYWRAP. All 35 lanes build clean locally.
psa_xchacha20_poly1305_encrypt/decrypt sat behind HAVE_XCHACHA with no callers since their introduction and only started compiling when the PSA 1.4 work enabled XChaCha. The live XChaCha20-Poly1305 path is the one-shot implementation in psa_aead.c; drop the dead pair and their declarations.
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #19
Scan targets checked: none
Failed targets: wolfpsa-bugs, wolfpsa-src
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #19
Scan targets checked: none
Failed targets: wolfpsa-bugs, wolfpsa-src
dgarske
left a comment
There was a problem hiding this comment.
Skoll Code Review
Scan type: reviewOverall recommendation: COMMENT
Findings: 9 total — 8 posted, 1 skipped
8 finding(s) posted as inline comments (see file-level comments below)
Posted findings
- [Low] psa_check_key_usage declares variables after a statement (C89 violation) —
src/psa_key_storage.c:2188-2196 - [Low] Mid-block declaration in psa_xof_output and non-conforming brace style —
src/psa_xof.c:421 - [Low] Test leaks XOF operation after failed psa_xof_set_context (misleading comment) —
test/psa_server/psa_xof_test.c:test_set_context_shake - [Low] SP800-108 input-step validation claims single-set but does not enforce it —
src/psa_key_derivation.c:381-392 - [Low] psa_kem.c uses memcpy instead of XMEMCPY —
src/psa_kem.c:195 - [Low] Dead empty if-block in psa_encapsulate —
src/psa_kem.c:123-125 - [Low] LMS/XMSS verify: redundant ret==-1 branch and lossy error mapping —
src/psa_lms_xmss.c:175-180 - [Low] psa_export_public_key runs ECC export on PQC key types before PQC branch overwrites status —
src/psa_key_storage.c:1841-1957
Skipped findings
- [Medium]
Large 1568-byte ciphertext staging buffer on the stack in psa_encapsulate
Review generated by Skoll
dgarske
left a comment
There was a problem hiding this comment.
Skoll Code Review
Scan type: reviewOverall recommendation: COMMENT
Findings: 4 total — 3 posted, 1 skipped
3 finding(s) posted as inline comments (see file-level comments below)
Posted findings
- [Medium] SHAKE256_512 reuses WOLFSSL_SHA3-gated union member but is gated on WOLFSSL_SHAKE256 —
src/psa_hash_engine.c:106-114, 208-212, 271, 334, 450, 568, 685, 883 - [Low] Unreachable XChaCha/Ascon branches in wolfpsa_aead_check_key —
src/psa_aead.c:149-168 - [Low] SP800-108 L field derived from capacity; default capacity yields non-interoperable output —
src/psa_key_derivation.c:1611-1618
Skipped findings
- [Low]
Large stack buffer in psa_encapsulate; unused when ML-KEM disabled
Review generated by Skoll
…docs - aead: remove unreachable XChaCha20-Poly1305/Ascon-AEAD128 branches from wolfpsa_aead_check_key; both algorithms are one-shot only and rejected by wolfpsa_aead_setup before the key check, and the one-shot paths validate keys inline. Left a note so they are not re-added. - kdf: document that SP800-108 counter-mode binds [L]_4 to the operation capacity per PSA 1.4 §10.8, so callers must set_capacity() to the exact total output before the first read to interoperate with implementations that derive L from the requested length.
Added support for PSA 1.4 including PQC algorithms.
aab839e chacha: remove dormant XChaCha20-Poly1305 helpers
c93281b build-matrix: survive feature-off builds and cover the new 1.4 features
956b9d4 tests/ci: PSA 1.4 coverage suite, CHANGELOG
aa470dd crypto: Ascon, XChaCha20-Poly1305 and SP800-108 counter KDFs
73f0f54 psa: wire PQC and 1.4 signature features into key storage and dispatch
8ef3aed psa: KEM front-end, XOF, AES-KW, LMS/XMSS verify, 1.4 stubs
6390a47 pqc: seed-based ML-DSA and ML-KEM backends per PSA 1.4 PQC extension
1ab901e headers: complete PSA 1.4 + PQC extension macro/declaration surface
8ac5c34 build: enable ML-KEM, LMS/XMSS verify-only, Ascon, XChaCha, AES-KW, CMAC-KDF
3ef39c4 F-3654: fix dead out_len guard in wolfpsa_aead_encrypt_final ChaCha branch
bbc9206 F-3655: remove dead psa_tls_prf helpers with no callers
e89506b F-3656: remove dead psa_chacha20_poly1305_check_* helpers with no callers
889910a F-3862: add SHAKE256_512 to hash engine so psa_sign/verify_message works for Ed448PH
6c7f12b F-4090: use PSA_BITS_TO_BYTES instead of key_bits/8 in wc_ecc_make_key_ex call
930f0b3 F-4096: reject PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG in wolfpsa_aead_setup
0f67845 F-4560: add wc_ecc_make_pub_ex to psa_asymmetric_export_public_key_ecc and wire it in
38d943f F-4561: check output buffer size before psa_cipher_generate_iv in psa_cipher_encrypt
f8c4f11 F-3653: check ciphertext buffer size before psa_aead_finish to avoid modifying output on BUFFER_TOO_SMALL
19b51ca F-3658: zeroize padded plaintext block in CBC-PKCS7 encrypt path
046f3d0 F-3660: fix algorithm confusion in psa_xchacha20_poly1305_encrypt/decrypt
6c8db18 F-3859: add test_hash_compare covering success, mismatch, wrong-length, and non-hash-alg paths
4e35d84 F-3860: add direction-mismatch tests for psa_aead_finish and psa_aead_verify