Skip to content

Commit af4c5ab

Browse files
hanno-beckermkannwischer
authored andcommitted
Wycheproof: Check K value and reject unrecognized vector fields
Previous versions of the `semi_expanded_keys` Wycheproof test type did not include a `K` output. Accordingly, the Wycheproof client would only check if the test driver produced `K` upon a successful run, but not compare it to anything from the Wycheproof test data. A recent commit 782238d4 added the expected `K` to the `semi_expanded_keys` test schema. This commit modifies the Wycheproof client for this test to check the calculated `K` against this expected `K`. The above commit also added `ek`, but this is merely the PK embedded in the SK, and not returned from mlkem-native's API. We therefore ignore the value. To avoid a similar extension of the test schema go unnoticed in the future, we explicitly list the keys of each schema that we know about and handle, and error when new field are added. Signed-off-by: Hanno Becker <beckphan@amazon.co.uk>
1 parent 0a09499 commit af4c5ab

1 file changed

Lines changed: 35 additions & 1 deletion

File tree

test/wycheproof/wycheproof_client.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,25 @@
4545
"ML-KEM-1024": 1024,
4646
}
4747

48+
# Fields each test-case handler knows how to interpret. If Wycheproof adds a
49+
# new field to a schema, an unrecognized key here means it may carry
50+
# information we are silently failing to check; fail loudly instead.
51+
KNOWN_FIELDS = {
52+
"keygen_seed": {"tcId", "comment", "result", "seed", "ek", "dk"},
53+
"encaps": {"tcId", "comment", "flags", "result", "ek", "m", "c", "K"},
54+
"semi_expanded_decaps": {
55+
"tcId",
56+
"comment",
57+
"flags",
58+
"result",
59+
"dk",
60+
"c",
61+
"ek",
62+
"K",
63+
},
64+
"combined": {"tcId", "comment", "flags", "result", "seed", "ek", "c", "K"},
65+
}
66+
4867

4968
def err(msg, **kwargs):
5069
print(msg, file=sys.stderr, **kwargs)
@@ -79,6 +98,14 @@ def download_wycheproof_files(data_dir):
7998
return True
8099

81100

101+
def check_known_fields(kind, tc):
102+
unknown = set(tc.keys()) - KNOWN_FIELDS[kind]
103+
assert not unknown, (
104+
f"Unrecognized field(s) {sorted(unknown)} in {kind} tcId={tc['tcId']}; "
105+
"Wycheproof schema may have grown a new field this client doesn't check"
106+
)
107+
108+
82109
def get_binary(level):
83110
basedir = f"./test/build/mlkem{level}/bin"
84111
return f"{basedir}/wycheproof_mlkem{level}"
@@ -108,6 +135,7 @@ def run_keygen_seed_test(data_file):
108135
level = PARAMETER_SET_TO_LEVEL[tg["parameterSet"]]
109136
binary = get_binary(level)
110137
for tc in tg["tests"]:
138+
check_known_fields("keygen_seed", tc)
111139
info(f" tcId={tc['tcId']} ... ", end="")
112140
out = run_binary([binary, "keygen_seed", f"seed={tc['seed']}"])
113141
if tc["result"] == "valid":
@@ -137,6 +165,7 @@ def run_encaps_test(data_file):
137165
level = PARAMETER_SET_TO_LEVEL[tg["parameterSet"]]
138166
binary = get_binary(level)
139167
for tc in tg["tests"]:
168+
check_known_fields("encaps", tc)
140169
info(f" tcId={tc['tcId']} ... ", end="")
141170
out = run_binary([binary, "encaps", f"ek={tc['ek']}", f"m={tc['m']}"])
142171
if tc["result"] == "invalid":
@@ -171,6 +200,7 @@ def run_semi_expanded_decaps_test(data_file):
171200
level = PARAMETER_SET_TO_LEVEL[tg["parameterSet"]]
172201
binary = get_binary(level)
173202
for tc in tg["tests"]:
203+
check_known_fields("semi_expanded_decaps", tc)
174204
info(f" tcId={tc['tcId']} ... ", end="")
175205
out = run_binary([binary, "decaps", f"dk={tc['dk']}", f"c={tc['c']}"])
176206
if tc["result"] == "invalid":
@@ -179,7 +209,10 @@ def run_semi_expanded_decaps_test(data_file):
179209
f"binary success on invalid tcId={tc['tcId']}"
180210
)
181211
elif tc["result"] == "valid":
182-
assert "K" in out, f"missing K in output tcId={tc['tcId']}"
212+
assert "K" in tc, f"missing K in test vector tcId={tc['tcId']}"
213+
assert out["K"].upper() == tc["K"].upper(), (
214+
f"K mismatch tcId={tc['tcId']}"
215+
)
183216
else:
184217
assert False, (
185218
f"Unsupported test result '{tc['result']}' for tcId={tc['tcId']}"
@@ -200,6 +233,7 @@ def run_combined_test(data_file):
200233
level = PARAMETER_SET_TO_LEVEL[tg["parameterSet"]]
201234
binary = get_binary(level)
202235
for tc in tg["tests"]:
236+
check_known_fields("combined", tc)
203237
info(f" tcId={tc['tcId']} ... ", end="")
204238
# Generate keypair from seed
205239
keygen_out = run_binary([binary, "keygen_seed", f"seed={tc['seed']}"])

0 commit comments

Comments
 (0)