You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is the "passes the official test vectors" item from #3.
Pull ML-KEM-keyGen-FIPS203 and ML-KEM-encapDecap-FIPS203 from usnistgov/ACVP-Server (gen-val/json-files), pinned to a commit
Cover keyGen, encapsulation, decapsulation, and the encapsulation-key and decapsulation-key check groups
Don't commit the vector files. Add a fetch script that downloads them at test time and checks each one against a SHA-256 in tests/vectors/manifest.json; cache them in CI and gitignore the folder
Check the current ACVP spec draft for schema changes before writing the parser (the FIPS203-tr1 revision adds seed-form decapsulation keys)
Done when: every test case in the pinned files passes in CI.
Status after #30: most of this is already in. The two pinned internalProjection files are fetched through scripts/fetch_vectors.py and tests/vectors/manifest.json (ACVP-Server commit 975de31e), and src/mlkem/acvp_tests.rs runs them against the real code: KeyGen_internal (75 cases, whole ek and dk), Encaps_internal (75), Decaps_internal (30, including the modified-ciphertext cases that expect J(z || c)), and the encapsulationKeyCheck and decapsulationKeyCheck groups (30 each, accepting and rejecting).
Still open here: check the current ACVP spec for schema changes before trusting the parser (the FIPS203-tr1 seed-form decapsulation keys), decide whether the expectedResults files should be pinned too or whether internalProjection is enough, and confirm the "every test case in the pinned files passes in CI" wording by counting cases per group against the files. It may turn out that this issue only needs that review plus a note, and can close.
Handoff for whoever picks this up (the Rust and Python ACVP tests are merged; see the status comment above).
What I found at the pinned commit 975de31e that the review should start from:
gen-val/json-files has a second directory, ML-KEM-encapDecap-FIPS203-tr1 (revision "FIPS203-tr1"), next to the one we pin. Its decapsulation groups carry d and z in every case and there are two groups per parameter set where the original has one. That is where the seed-form decapsulation keys from the checklist live. Nothing in the repo reads that directory yet. Work out from the ACVP spec (not from guessing at the JSON) what the two groups mean, whether the dk field is the expanded key or something else, and whether it is a real change for FIPS 203 final or only a draft revision.
Each directory has expectedResults.json, internalProjection.json, prompt.json, registration.json and validation.json. We pin only internalProjection.json. Decide with evidence whether prompt plus expectedResults would add coverage (the internalProjection file is the one that carries the secret inputs, so I expect not) and write the decision down.
The counts to confirm against the files per set: keyGen 25, encapsulation 25, decapsulation 10, and 10 each for the two key-check groups. The status comment says 75/75/30/30/30 in total.
Things that will bite:
External vectors are never committed. A new pin or a new file means a manifest.json change with SHA-256 values, and that is a change someone has to be able to review: say what you changed and why in the PR. Never loosen or skip a test to make a case pass; if a tr1 case fails, find out whether our code or the reading of the file is wrong and show the evidence.
Rust tests live in src/mlkem/acvp_tests.rs and use the internal functions behind cfg(any(test, feature = "acvp")). The Python ACVP tests are python/tests/test_mlkem_acvp.py and use the public API only. Keep that split.
The result may be "review plus a note, close the issue". That is a fine outcome if the evidence is in the PR or an issue comment.
PLAN-2.0.md section 9 lists the primary sources. Treat blogs and summaries as leads only.
Closing this: every case in the pinned ACVP files now runs in CI, in Rust and in Python.
Counts, checked by parsing the files at ACVP-Server commit 975de31e. keyGen 75, encapsulation 75, decapsulation 30, encapsulationKeyCheck 30, decapsulationKeyCheck 30 for ML-KEM-encapDecap-FIPS203 and ML-KEM-keyGen-FIPS203, so the wording in the issue holds for those. The FIPS203-tr1 directory had 195 more cases (75 encapsulation, 30 + 30 decapsulation with expanded and seed keys, 30 + 30 key checks) that we did not run, and none of them overlap the original files. #33 pins its internalProjection.json and runs all 195; they passed without any change to the code.
What tr1 is: the ACVP ML-KEM draft (October 2026) calls it a new test revision against the same standard, FIPS 203, so it applies to the final standard. The seed groups give d, z and c and the module derives the key from d || z; the expanded groups give the usual dk. The dk in both is the normal FIPS 203 decapsulation key.
I did not pin prompt.json or expectedResults.json. For all three directories every field in them is equal to the same field in internalProjection.json, over 435 cases, so they add nothing.
Not checked: whether a later ACVP-Server commit changes these files. The pin stays at 975de31e.
CCTV, Wycheproof and the differential test continue in #12.
Activity
Zikithezikit commentedon Oct 30, 2026
Status after #30: most of this is already in. The two pinned internalProjection files are fetched through scripts/fetch_vectors.py and tests/vectors/manifest.json (ACVP-Server commit 975de31e), and src/mlkem/acvp_tests.rs runs them against the real code: KeyGen_internal (75 cases, whole ek and dk), Encaps_internal (75), Decaps_internal (30, including the modified-ciphertext cases that expect J(z || c)), and the encapsulationKeyCheck and decapsulationKeyCheck groups (30 each, accepting and rejecting).
Still open here: check the current ACVP spec for schema changes before trusting the parser (the FIPS203-tr1 seed-form decapsulation keys), decide whether the expectedResults files should be pinned too or whether internalProjection is enough, and confirm the "every test case in the pinned files passes in CI" wording by counting cases per group against the files. It may turn out that this issue only needs that review plus a note, and can close.
Zikithezikit commentedon Oct 30, 2026
Handoff for whoever picks this up (the Rust and Python ACVP tests are merged; see the status comment above).
What I found at the pinned commit 975de31e that the review should start from:
dandzin every case and there are two groups per parameter set where the original has one. That is where the seed-form decapsulation keys from the checklist live. Nothing in the repo reads that directory yet. Work out from the ACVP spec (not from guessing at the JSON) what the two groups mean, whether thedkfield is the expanded key or something else, and whether it is a real change for FIPS 203 final or only a draft revision.Things that will bite:
Zikithezikit commentedon Oct 30, 2026
Closing this: every case in the pinned ACVP files now runs in CI, in Rust and in Python.
Counts, checked by parsing the files at ACVP-Server commit 975de31e. keyGen 75, encapsulation 75, decapsulation 30, encapsulationKeyCheck 30, decapsulationKeyCheck 30 for ML-KEM-encapDecap-FIPS203 and ML-KEM-keyGen-FIPS203, so the wording in the issue holds for those. The FIPS203-tr1 directory had 195 more cases (75 encapsulation, 30 + 30 decapsulation with expanded and seed keys, 30 + 30 key checks) that we did not run, and none of them overlap the original files. #33 pins its internalProjection.json and runs all 195; they passed without any change to the code.
What tr1 is: the ACVP ML-KEM draft (October 2026) calls it a new test revision against the same standard, FIPS 203, so it applies to the final standard. The seed groups give d, z and c and the module derives the key from d || z; the expanded groups give the usual dk. The dk in both is the normal FIPS 203 decapsulation key.
I did not pin prompt.json or expectedResults.json. For all three directories every field in them is equal to the same field in internalProjection.json, over 435 cases, so they add nothing.
Not checked: whether a later ACVP-Server commit changes these files. The pin stays at 975de31e.
CCTV, Wycheproof and the differential test continue in #12.