On Tue, 15 Sep 2026 15:51:57 +0000
Kai Ji <[email protected]> wrote:
> Add a Wycheproof JSON vector validation example for cryptodev PMDs.
>
> Support these algorithms when advertised by the selected PMD:
> - AEAD: AES-GCM, AES-CCM, SM4-GCM, ChaCha20-Poly1305
> - MAC: AES-CMAC, AES-GMAC, HMAC SHA-1/SHA-2/SHA-3/SM3
> - Asymmetric: DSA (P1363 verify), ECDSA (P1363 verify),
> ECDH (ecpoint shared-secret compute)
>
> Validate valid vectors against generated ciphertexts, tags, plaintexts,
> digests, shared secrets, or signature verification, and require the
> expected rejection for invalid vectors. Digest inputs for DSA and ECDSA
> use the symmetric auth path, selecting a separate symmetric-capable
> device when the target device is asymmetric-only.
>
> Skip parameter combinations outside PMD capability ranges and identify
> recognized vector families without a compatible DPDK transform. A
> --debug option lists every failed or skipped vector.
>
> Add Meson and standalone build integration, with usage documentation.
>
> Signed-off-by: Kai Ji <[email protected]>
> ---
Fable found lots of issues that need addressing.
Review: [PATCH] examples: add Wycheproof validation app
Built with meson -Dwerror=true, gcc 13.3, crypto/openssl. Ran the app
against Wycheproof v1 vectors (GCM, CCM, GMAC, HMAC, CMAC, DSA) with
crypto_openssl after fixing the build error below; those pass.
Errors
------
1. Build fails with -Dwerror (test-meson-builds.sh default):
main.c:954,957: 'status' may be used uninitialized
main.c:1194: 'status' may be used uninitialized
process_gmac (decl line 929) and process_dsa_p1363 (line 1194)
leave status uninitialized on the -ENOTSUP and non-valid/invalid
paths. validate_aead_vector (decl line 740) has a real read: a
non-zero ret from run_aead jumps to failed: and line 795 prints
status. Initialize to RTE_CRYPTO_OP_STATUS_ERROR in all four
places, as process_ecdh_ecpoint and process_ecdsa_p1363 already do.
2. CCM AAD buffer is too small, heap overflow on QAT (line 526):
aad = rte_zmalloc(NULL, vector->aad_len + 18, 0);
rte_crypto_sym.h (aad_length) requires the 18-byte prefix plus
padding so the allocation is a multiple of 16, and says PMDs may
write the padding. QAT does: qat_crypto_pmd_gens.h ~1194-1206
memsets &aad_data[18 + aad_len] for 16 - (aad_len + 2) % 16 bytes.
Every CCM vector with (aad_len + 2) % 16 != 0 (Wycheproof aad
lengths 0, 1, 2, 7, 8, 15, 16, 17, ...) writes past the buffer.
app/test uses RTE_ALIGN_CEIL(aad_len + 18, 16); do the same.
The guard on the next line is also wrong:
if (aad == NULL && vector->aad_len != 0)
The allocation is never zero-size, so a NULL here means the PMD
writes B0 and the flags byte through a NULL aad.data. Use
if (aad == NULL).
Warnings
--------
3. EC operands passed at JSON width (lines 1548-1551, 1327, 1354):
xform.ec.q.x.length = group->wx_len;
xform.ec.pkey.length = priv_len;
Wycheproof encodes wx, wy and private as signed-style big integers:
in ecdsa_secp256r1_sha256_p1363_test.json most groups have a
33-byte wx or wy (leading 0x00), some 29 bytes; secp521r1 groups
range 62-66; ecdh private lengths are 1, 29, 32, 33. QAT, which the
README names for ECDSA/ECDH, packs with SET_PKE_LN/SET_PKE_9A_IN as
buf + alignsize - length with no length check
(drivers/crypto/qat/asym/qat_asym.c:81-96); a 33-byte value writes
its 0x00 one byte before the slot, into the neighbouring operand.
Result is wrong verifications, not skips. Normalize to bytesize:
strip leading zeros (value_equals_padded already does this), reject
anything still longer than bytesize, left-pad into a fixed buffer.
DSA p/q/g/y have the same encoding (a 2048-bit p is 257 bytes);
only crypto_openssl implements DSA today so it is tolerated there.
4. IV copied into the op with no bound (lines 533, 538, 711):
memcpy(rte_crypto_op_ctod_offset(op, uint8_t *, IV_OFFSET),
vector->iv, vector->iv_len);
The only guard is the PMD's advertised iv_size range. mvsam
advertises AES-GMAC iv_size max 65532 (rte_mrvl_pmd_ops.c:371);
aes_gcm_test.json and aes_ccm_test.json carry 257 and 268-byte
IVs. The room after IV_OFFSET is 152 bytes, and only because
priv_size at line 210 is IV_OFFSET + 64: priv_size is already
relative to the end of the sym op (rte_crypto_op_pool_create adds
sizeof(op) + sizeof(sym_op)), so IV_OFFSET is counted twice.
Define an IV maximum, use it as priv_size, and skip vectors whose
iv_len (+1 for CCM) exceeds it.
5. mbuf pool sizing (line 181):
sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM +
env.mbuf_data_room
data_room_size already excludes the mbuf struct; this wastes 128
bytes per mbuf. The parameter is uint16_t and --mbuf-dataroom is
only checked for != 0, so large values truncate silently and
values below RTE_PKTMBUF_HEADROOM wrap the check at line 754
(env.mbuf_data_room - RTE_PKTMBUF_HEADROOM). Drop the sizeof and
range-check the option.
6. PMD failures on valid vectors counted as skips (lines 1473-1476):
} else {
stats->skipped_capability++;
debug_vector("SKIP", name, &vector, "PMD could not compute");
A valid ECDH vector where the op returns an error exits 0.
run_ecdh_ecpoint and run_ecdsa_verify also turn asym session
create failure into -ENOTSUP (lines 1341, 1556) while
run_dsa_verify returns -ENOMEM and fails the vector. Capability
skips should come only from the capability query; anything the
PMD rejects after that is a failure for a validation tool.
7. Documentation and MAINTAINERS. Examples are documented in
doc/guides/sample_app_ug/<name>.rst and listed in index.rst (see
fips_validation); README.md is not the convention (only
examples/bpf/README exists). Add the rst and a MAINTAINERS entry
with F: examples/wycheproof_validation/ and the rst, as
fips_validation has.
8. Makefile has no trailing newline (checkpatch warns).
Info
----
9. process_file is a 20-arm strcmp chain re-testing algorithm and
schema in every arm. A static table {algorithm, schema, kind,
algo id} and a loop replaces it.
10. decode_hex uses rte_malloc for every field. Only the AAD (the
GCM/ChaCha path hands vector->aad to the PMD directly) and the
digest buffers need IOVA memory; keys, messages, signatures and
DSA/EC parameters are copied by the library or PMD. If the AAD is
always copied into a 16-byte-padded rte_malloc buffer (fix 2
does this for CCM), decode_hex can use plain malloc.
11. Every dequeue loop (549, 637, 717, 1064, 1143, 1363, 1574) spins
forever if the PMD never returns the op. A bounded wait that
fails the vector is better for a tool meant to run on hardware.
12. Symbols used without a direct include: bool (<stdbool.h>),
PRIu64 (<inttypes.h>), strtoul/EXIT_* (<stdlib.h>), PATH_MAX
(<limits.h>). All come in transitively today.
13. Placement: this is a conformance tool with an exit-code contract,
not a sample showing API use. app/ next to dpdk-test-crypto-perf
is the more natural home.
14. Pre-existing, not introduced by this patch: QAT SET_PKE_LN and
SET_PKE_9A_IN (qat_asym.c:81-96) never check length <= alignsize,
so an oversize rte_crypto_uint writes before its slot. Worth a
separate fix in the PMD.
Review-Result: ERROR