diff options
author | beck <> | 2025-08-14 15:48:48 +0000 |
---|---|---|
committer | beck <> | 2025-08-14 15:48:48 +0000 |
commit | 6452fa9fc6f33dac80ee572764b9fe29a469f8ce (patch) | |
tree | 0956ae670e4f193442bcf99d2b1fb70a43a6b5b5 /src/regress/lib/libcrypto/mlkem/mlkem_unittest.c | |
parent | 9bef27f78e41e8026f1d588e4e36e385061f3deb (diff) | |
download | openbsd-6452fa9fc6f33dac80ee572764b9fe29a469f8ce.tar.gz openbsd-6452fa9fc6f33dac80ee572764b9fe29a469f8ce.tar.bz2 openbsd-6452fa9fc6f33dac80ee572764b9fe29a469f8ce.zip |
Add a reasonable ML-KEM API for public use.
Adapt the tests to use this API.
This does not yet make the symbols public in Symbols.list
which will happen shortly with a bump.
This includes some partial rototilling of the non-public
interfaces which will be shortly continued when the internal
code is deduplicated to not have multiple copies for ML-KEM
768 and ML-KEM 1024 (which is just an artifact of unravelling
the boring C++ code).
ok jsing@, tb@
Diffstat (limited to 'src/regress/lib/libcrypto/mlkem/mlkem_unittest.c')
-rw-r--r-- | src/regress/lib/libcrypto/mlkem/mlkem_unittest.c | 302 |
1 files changed, 174 insertions, 128 deletions
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_unittest.c b/src/regress/lib/libcrypto/mlkem/mlkem_unittest.c index adb1c47d8e..417d40555f 100644 --- a/src/regress/lib/libcrypto/mlkem/mlkem_unittest.c +++ b/src/regress/lib/libcrypto/mlkem/mlkem_unittest.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mlkem_unittest.c,v 1.11 2025/05/21 03:46:20 tb Exp $ */ | 1 | /* $OpenBSD: mlkem_unittest.c,v 1.12 2025/08/14 15:48:48 beck Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2024 Google Inc. | 3 | * Copyright (c) 2024 Google Inc. |
4 | * Copyright (c) 2024 Bob Beck <beck@obtuse.com> | 4 | * Copyright (c) 2024 Bob Beck <beck@obtuse.com> |
@@ -27,95 +27,161 @@ | |||
27 | 27 | ||
28 | #include "mlkem_tests_util.h" | 28 | #include "mlkem_tests_util.h" |
29 | 29 | ||
30 | struct unittest_ctx { | ||
31 | void *priv; | ||
32 | void *pub; | ||
33 | void *priv2; | ||
34 | void *pub2; | ||
35 | uint8_t *encoded_public_key; | ||
36 | size_t encoded_public_key_len; | ||
37 | uint8_t *ciphertext; | ||
38 | size_t ciphertext_len; | ||
39 | mlkem_decap_fn decap; | ||
40 | mlkem_encap_fn encap; | ||
41 | mlkem_generate_key_fn generate_key; | ||
42 | mlkem_parse_private_key_fn parse_private_key; | ||
43 | mlkem_parse_public_key_fn parse_public_key; | ||
44 | mlkem_marshal_private_key_fn marshal_private_key; | ||
45 | mlkem_marshal_public_key_fn marshal_public_key; | ||
46 | mlkem_public_from_private_fn public_from_private; | ||
47 | }; | ||
48 | |||
49 | static int | 30 | static int |
50 | MlKemUnitTest(struct unittest_ctx *ctx) | 31 | MlKemUnitTest(int rank) |
51 | { | 32 | { |
52 | uint8_t shared_secret1[MLKEM_SHARED_SECRET_BYTES]; | 33 | MLKEM_private_key *priv = NULL, *priv2 = NULL, *priv3 = NULL; |
53 | uint8_t shared_secret2[MLKEM_SHARED_SECRET_BYTES]; | 34 | MLKEM_public_key *pub = NULL, *pub2 = NULL, *pub3 = NULL; |
35 | uint8_t *encoded_public_key = NULL, *ciphertext = NULL, | ||
36 | *shared_secret2 = NULL, *shared_secret1 = NULL, | ||
37 | *encoded_private_key = NULL, *tmp_buf = NULL, *seed_buf = NULL; | ||
38 | size_t encoded_public_key_len, ciphertext_len, | ||
39 | encoded_private_key_len, tmp_buf_len; | ||
54 | uint8_t first_two_bytes[2]; | 40 | uint8_t first_two_bytes[2]; |
55 | uint8_t *encoded_private_key = NULL, *tmp_buf = NULL; | 41 | size_t s_len = 0; |
56 | size_t encoded_private_key_len, tmp_buf_len; | ||
57 | int failed = 0; | 42 | int failed = 0; |
58 | 43 | ||
59 | if (!ctx->generate_key(ctx->encoded_public_key, NULL, ctx->priv)) { | 44 | if ((pub = MLKEM_public_key_new(rank)) == NULL) { |
45 | warnx("public_key_new"); | ||
46 | failed |= 1; | ||
47 | } | ||
48 | |||
49 | if ((pub2 = MLKEM_public_key_new(rank)) == NULL) { | ||
50 | warnx("public_key_new"); | ||
51 | failed |= 1; | ||
52 | } | ||
53 | |||
54 | if ((priv = MLKEM_private_key_new(rank)) == NULL) { | ||
55 | warnx("private_key_new"); | ||
56 | failed |= 1; | ||
57 | } | ||
58 | |||
59 | if ((priv2 = MLKEM_private_key_new(rank)) == NULL) { | ||
60 | warnx("private_key_new"); | ||
61 | failed |= 1; | ||
62 | } | ||
63 | |||
64 | if (!MLKEM_generate_key(priv, &encoded_public_key, | ||
65 | &encoded_public_key_len, &seed_buf, &s_len)) { | ||
60 | warnx("generate_key failed"); | 66 | warnx("generate_key failed"); |
61 | failed |= 1; | 67 | failed |= 1; |
62 | } | 68 | } |
63 | 69 | ||
64 | memcpy(first_two_bytes, ctx->encoded_public_key, sizeof(first_two_bytes)); | 70 | if (s_len != MLKEM_SEED_LENGTH) { |
65 | memset(ctx->encoded_public_key, 0xff, sizeof(first_two_bytes)); | 71 | warnx("seed length %zu != %d", s_len, MLKEM_SEED_LENGTH); |
72 | failed |= 1; | ||
73 | } | ||
74 | |||
75 | if ((priv3 = MLKEM_private_key_new(rank)) == NULL) { | ||
76 | warnx("private_key_new"); | ||
77 | failed |= 1; | ||
78 | } | ||
79 | |||
80 | if ((pub3 = MLKEM_public_key_new(rank)) == NULL) { | ||
81 | warnx("public_key_new"); | ||
82 | failed |= 1; | ||
83 | } | ||
84 | |||
85 | if (!MLKEM_private_key_from_seed(priv3, seed_buf, s_len)) { | ||
86 | warnx("private_key_from_seed failed"); | ||
87 | failed |= 1; | ||
88 | } | ||
89 | |||
90 | free(seed_buf); | ||
91 | seed_buf = NULL; | ||
92 | |||
93 | if (!MLKEM_public_from_private(priv3, pub3)) { | ||
94 | warnx("public_from_private"); | ||
95 | failed |= 1; | ||
96 | } | ||
97 | |||
98 | memcpy(first_two_bytes, encoded_public_key, sizeof(first_two_bytes)); | ||
99 | memset(encoded_public_key, 0xff, sizeof(first_two_bytes)); | ||
66 | 100 | ||
67 | /* Parsing should fail because the first coefficient is >= kPrime. */ | 101 | /* Parsing should fail because the first coefficient is >= kPrime. */ |
68 | if (ctx->parse_public_key(ctx->pub, ctx->encoded_public_key, | 102 | if (MLKEM_parse_public_key(pub, encoded_public_key, |
69 | ctx->encoded_public_key_len)) { | 103 | encoded_public_key_len)) { |
70 | warnx("parse_public_key should have failed"); | 104 | warnx("parse_public_key should have failed"); |
71 | failed |= 1; | 105 | failed |= 1; |
72 | } | 106 | } |
73 | 107 | ||
74 | memcpy(ctx->encoded_public_key, first_two_bytes, sizeof(first_two_bytes)); | 108 | memcpy(encoded_public_key, first_two_bytes, sizeof(first_two_bytes)); |
75 | if (!ctx->parse_public_key(ctx->pub, ctx->encoded_public_key, | 109 | |
76 | ctx->encoded_public_key_len)) { | 110 | MLKEM_public_key_free(pub); |
77 | warnx("MLKEM768_parse_public_key"); | 111 | if ((pub = MLKEM_public_key_new(rank)) == NULL) { |
112 | warnx("public_key_new"); | ||
113 | failed |= 1; | ||
114 | } | ||
115 | if (!MLKEM_parse_public_key(pub, encoded_public_key, | ||
116 | encoded_public_key_len)) { | ||
117 | warnx("MLKEM_parse_public_key"); | ||
118 | failed |= 1; | ||
119 | } | ||
120 | |||
121 | if (!MLKEM_marshal_public_key(pub, &tmp_buf, &tmp_buf_len)) { | ||
122 | warnx("marshal_public_key"); | ||
123 | failed |= 1; | ||
124 | } | ||
125 | if (encoded_public_key_len != tmp_buf_len) { | ||
126 | warnx("encoded public key lengths differ %d != %d", | ||
127 | (int) encoded_public_key_len, (int) tmp_buf_len); | ||
128 | failed |= 1; | ||
129 | } | ||
130 | |||
131 | if (compare_data(encoded_public_key, tmp_buf, tmp_buf_len, | ||
132 | "encoded public keys") != 0) { | ||
133 | warnx("compare_data"); | ||
78 | failed |= 1; | 134 | failed |= 1; |
79 | } | 135 | } |
136 | free(tmp_buf); | ||
137 | tmp_buf = NULL; | ||
138 | tmp_buf_len = 0; | ||
80 | 139 | ||
81 | if (!ctx->marshal_public_key(ctx->pub, &tmp_buf, &tmp_buf_len)) { | 140 | if (!MLKEM_marshal_public_key(pub3, &tmp_buf, &tmp_buf_len)) { |
82 | warnx("marshal_public_key"); | 141 | warnx("marshal_public_key"); |
83 | failed |= 1; | 142 | failed |= 1; |
84 | } | 143 | } |
85 | if (ctx->encoded_public_key_len != tmp_buf_len) { | 144 | if (encoded_public_key_len != tmp_buf_len) { |
86 | warnx("encoded public key lengths differ"); | 145 | warnx("encoded public key lengths differ %d != %d", |
146 | (int) encoded_public_key_len, (int) tmp_buf_len); | ||
87 | failed |= 1; | 147 | failed |= 1; |
88 | } | 148 | } |
89 | 149 | ||
90 | if (compare_data(ctx->encoded_public_key, tmp_buf, tmp_buf_len, | 150 | if (compare_data(encoded_public_key, tmp_buf, tmp_buf_len, |
91 | "encoded public keys") != 0) { | 151 | "encoded public keys") != 0) { |
92 | warnx("compare_data"); | 152 | warnx("compare_data"); |
93 | failed |= 1; | 153 | failed |= 1; |
94 | } | 154 | } |
95 | free(tmp_buf); | 155 | free(tmp_buf); |
96 | tmp_buf = NULL; | 156 | tmp_buf = NULL; |
157 | tmp_buf_len = 0; | ||
97 | 158 | ||
98 | ctx->public_from_private(ctx->pub2, ctx->priv); | 159 | if (!MLKEM_public_from_private(priv, pub2)) { |
99 | if (!ctx->marshal_public_key(ctx->pub2, &tmp_buf, &tmp_buf_len)) { | 160 | warnx("public_from_private"); |
161 | failed |= 1; | ||
162 | } | ||
163 | if (!MLKEM_marshal_public_key(pub2, &tmp_buf, &tmp_buf_len)) { | ||
100 | warnx("marshal_public_key"); | 164 | warnx("marshal_public_key"); |
101 | failed |= 1; | 165 | failed |= 1; |
102 | } | 166 | } |
103 | if (ctx->encoded_public_key_len != tmp_buf_len) { | 167 | if (encoded_public_key_len != tmp_buf_len) { |
104 | warnx("encoded public key lengths differ"); | 168 | warnx("encoded public key lengths differ %d %d", |
169 | (int) encoded_public_key_len, (int) tmp_buf_len); | ||
105 | failed |= 1; | 170 | failed |= 1; |
106 | } | 171 | } |
107 | 172 | ||
108 | if (compare_data(ctx->encoded_public_key, tmp_buf, tmp_buf_len, | 173 | if (compare_data(encoded_public_key, tmp_buf, tmp_buf_len, |
109 | "encoded public keys") != 0) { | 174 | "encoded public keys") != 0) { |
110 | warnx("compare_data"); | 175 | warnx("compare_data"); |
111 | failed |= 1; | 176 | failed |= 1; |
112 | } | 177 | } |
113 | free(tmp_buf); | 178 | free(tmp_buf); |
114 | tmp_buf = NULL; | 179 | tmp_buf = NULL; |
180 | tmp_buf_len = 0; | ||
115 | 181 | ||
116 | if (!ctx->marshal_private_key(ctx->priv, &encoded_private_key, | 182 | if (!MLKEM_marshal_private_key(priv, &encoded_private_key, |
117 | &encoded_private_key_len)) { | 183 | &encoded_private_key_len)) { |
118 | warnx("mlkem768_encode_private_key"); | 184 | warnx("marshal_private_key"); |
119 | failed |= 1; | 185 | failed |= 1; |
120 | } | 186 | } |
121 | 187 | ||
@@ -123,27 +189,34 @@ MlKemUnitTest(struct unittest_ctx *ctx) | |||
123 | memset(encoded_private_key, 0xff, sizeof(first_two_bytes)); | 189 | memset(encoded_private_key, 0xff, sizeof(first_two_bytes)); |
124 | 190 | ||
125 | /* Parsing should fail because the first coefficient is >= kPrime. */ | 191 | /* Parsing should fail because the first coefficient is >= kPrime. */ |
126 | if (ctx->parse_private_key(ctx->priv2, encoded_private_key, | 192 | if (MLKEM_parse_private_key(priv2, encoded_private_key, |
127 | encoded_private_key_len)) { | 193 | encoded_private_key_len)) { |
128 | warnx("MLKEM768_parse_private_key should have failed"); | 194 | warnx("parse_private_key should have failed"); |
129 | failed |= 1; | 195 | failed |= 1; |
130 | } | 196 | } |
131 | 197 | ||
132 | memcpy(encoded_private_key, first_two_bytes, sizeof(first_two_bytes)); | 198 | memcpy(encoded_private_key, first_two_bytes, sizeof(first_two_bytes)); |
133 | 199 | ||
134 | if (!ctx->parse_private_key(ctx->priv2, encoded_private_key, | 200 | MLKEM_private_key_free(priv2); |
201 | priv2 = NULL; | ||
202 | |||
203 | if ((priv2 = MLKEM_private_key_new(rank)) == NULL) { | ||
204 | warnx("private_key_new"); | ||
205 | failed |= 1; | ||
206 | } | ||
207 | if (!MLKEM_parse_private_key(priv2, encoded_private_key, | ||
135 | encoded_private_key_len)) { | 208 | encoded_private_key_len)) { |
136 | warnx("MLKEM768_parse_private_key"); | 209 | warnx("parse_private_key"); |
137 | failed |= 1; | 210 | failed |= 1; |
138 | } | 211 | } |
139 | 212 | ||
140 | if (!ctx->marshal_private_key(ctx->priv2, &tmp_buf, &tmp_buf_len)) { | 213 | if (!MLKEM_marshal_private_key(priv2, &tmp_buf, &tmp_buf_len)) { |
141 | warnx("encode_private_key"); | 214 | warnx("marshal_private_key"); |
142 | failed |= 1; | 215 | failed |= 1; |
143 | } | 216 | } |
144 | 217 | ||
145 | if (encoded_private_key_len != tmp_buf_len) { | 218 | if (encoded_private_key_len != tmp_buf_len) { |
146 | warnx("encode private key lengths differ"); | 219 | warnx("encoded private key lengths differ"); |
147 | failed |= 1; | 220 | failed |= 1; |
148 | } | 221 | } |
149 | 222 | ||
@@ -156,106 +229,79 @@ MlKemUnitTest(struct unittest_ctx *ctx) | |||
156 | free(tmp_buf); | 229 | free(tmp_buf); |
157 | tmp_buf = NULL; | 230 | tmp_buf = NULL; |
158 | 231 | ||
159 | ctx->encap(ctx->ciphertext, shared_secret1, ctx->pub); | 232 | if (!MLKEM_encap(pub, &ciphertext, &ciphertext_len, &shared_secret1, |
160 | if (!ctx->decap(shared_secret2, ctx->ciphertext, ctx->ciphertext_len, | 233 | &s_len)) { |
161 | ctx->priv)) { | 234 | warnx("encap failed using pub"); |
235 | failed |= 1; | ||
236 | } | ||
237 | |||
238 | if (s_len != MLKEM_SHARED_SECRET_LENGTH) { | ||
239 | warnx("seed length %zu != %d", s_len, | ||
240 | MLKEM_SHARED_SECRET_LENGTH); | ||
241 | failed |= 1; | ||
242 | } | ||
243 | |||
244 | if (!MLKEM_decap(priv, ciphertext, ciphertext_len, | ||
245 | &shared_secret2, &s_len)) { | ||
162 | warnx("decap() failed using priv"); | 246 | warnx("decap() failed using priv"); |
163 | failed |= 1; | 247 | failed |= 1; |
164 | } | 248 | } |
165 | if (compare_data(shared_secret1, shared_secret2, MLKEM_SHARED_SECRET_BYTES, | 249 | |
250 | if (s_len != MLKEM_SHARED_SECRET_LENGTH) { | ||
251 | warnx("seed length %zu != %d", s_len, | ||
252 | MLKEM_SHARED_SECRET_LENGTH); | ||
253 | failed |= 1; | ||
254 | } | ||
255 | |||
256 | if (compare_data(shared_secret1, shared_secret2, s_len, | ||
166 | "shared secrets with priv") != 0) { | 257 | "shared secrets with priv") != 0) { |
167 | warnx("compare_data"); | 258 | warnx("compare_data"); |
168 | failed |= 1; | 259 | failed |= 1; |
169 | } | 260 | } |
170 | 261 | ||
171 | if (!ctx->decap(shared_secret2, ctx->ciphertext, ctx->ciphertext_len, | 262 | free(shared_secret2); |
172 | ctx->priv2)) { | 263 | shared_secret2 = NULL; |
264 | |||
265 | if (!MLKEM_decap(priv2, ciphertext, ciphertext_len, | ||
266 | &shared_secret2, &s_len)){ | ||
173 | warnx("decap() failed using priv2"); | 267 | warnx("decap() failed using priv2"); |
174 | failed |= 1; | 268 | failed |= 1; |
175 | } | 269 | } |
176 | if (compare_data(shared_secret1, shared_secret2, MLKEM_SHARED_SECRET_BYTES, | 270 | |
271 | if (s_len != MLKEM_SHARED_SECRET_LENGTH) { | ||
272 | warnx("seed length %zu != %d", s_len, | ||
273 | MLKEM_SHARED_SECRET_LENGTH); | ||
274 | failed |= 1; | ||
275 | } | ||
276 | |||
277 | if (compare_data(shared_secret1, shared_secret2, s_len, | ||
177 | "shared secrets with priv2") != 0) { | 278 | "shared secrets with priv2") != 0) { |
178 | warnx("compare_data"); | 279 | warnx("compare_data"); |
179 | failed |= 1; | 280 | failed |= 1; |
180 | } | 281 | } |
181 | 282 | ||
283 | MLKEM_public_key_free(pub); | ||
284 | MLKEM_public_key_free(pub2); | ||
285 | MLKEM_public_key_free(pub3); | ||
286 | MLKEM_private_key_free(priv); | ||
287 | MLKEM_private_key_free(priv2); | ||
288 | MLKEM_private_key_free(priv3); | ||
289 | free(encoded_public_key); | ||
290 | free(ciphertext); | ||
182 | free(encoded_private_key); | 291 | free(encoded_private_key); |
292 | free(shared_secret1); | ||
293 | free(shared_secret2); | ||
183 | 294 | ||
184 | return failed; | 295 | return failed; |
185 | } | 296 | } |
186 | 297 | ||
187 | static int | ||
188 | mlkem768_unittest(void) | ||
189 | { | ||
190 | struct MLKEM768_private_key mlkem768_priv, mlkem768_priv2; | ||
191 | struct MLKEM768_public_key mlkem768_pub, mlkem768_pub2; | ||
192 | uint8_t mlkem768_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES]; | ||
193 | uint8_t mlkem768_ciphertext[MLKEM768_CIPHERTEXT_BYTES]; | ||
194 | struct unittest_ctx mlkem768_test = { | ||
195 | .priv = &mlkem768_priv, | ||
196 | .pub = &mlkem768_pub, | ||
197 | .priv2 = &mlkem768_priv2, | ||
198 | .pub2 = &mlkem768_pub2, | ||
199 | .encoded_public_key = mlkem768_encoded_public_key, | ||
200 | .encoded_public_key_len = sizeof(mlkem768_encoded_public_key), | ||
201 | .ciphertext = mlkem768_ciphertext, | ||
202 | .ciphertext_len = sizeof(mlkem768_ciphertext), | ||
203 | .decap = mlkem768_decap, | ||
204 | .encap = mlkem768_encap, | ||
205 | .generate_key = mlkem768_generate_key, | ||
206 | .parse_private_key = mlkem768_parse_private_key, | ||
207 | .parse_public_key = mlkem768_parse_public_key, | ||
208 | .marshal_private_key = mlkem768_marshal_private_key, | ||
209 | .marshal_public_key = mlkem768_marshal_public_key, | ||
210 | .public_from_private = mlkem768_public_from_private, | ||
211 | }; | ||
212 | |||
213 | return MlKemUnitTest(&mlkem768_test); | ||
214 | } | ||
215 | |||
216 | static int | ||
217 | mlkem1024_unittest(void) | ||
218 | { | ||
219 | struct MLKEM1024_private_key mlkem1024_priv, mlkem1024_priv2; | ||
220 | struct MLKEM1024_public_key mlkem1024_pub, mlkem1024_pub2; | ||
221 | uint8_t mlkem1024_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES]; | ||
222 | uint8_t mlkem1024_ciphertext[MLKEM1024_CIPHERTEXT_BYTES]; | ||
223 | struct unittest_ctx mlkem1024_test = { | ||
224 | .priv = &mlkem1024_priv, | ||
225 | .pub = &mlkem1024_pub, | ||
226 | .priv2 = &mlkem1024_priv2, | ||
227 | .pub2 = &mlkem1024_pub2, | ||
228 | .encoded_public_key = mlkem1024_encoded_public_key, | ||
229 | .encoded_public_key_len = sizeof(mlkem1024_encoded_public_key), | ||
230 | .ciphertext = mlkem1024_ciphertext, | ||
231 | .ciphertext_len = sizeof(mlkem1024_ciphertext), | ||
232 | .decap = mlkem1024_decap, | ||
233 | .encap = mlkem1024_encap, | ||
234 | .generate_key = mlkem1024_generate_key, | ||
235 | .parse_private_key = mlkem1024_parse_private_key, | ||
236 | .parse_public_key = mlkem1024_parse_public_key, | ||
237 | .marshal_private_key = mlkem1024_marshal_private_key, | ||
238 | .marshal_public_key = mlkem1024_marshal_public_key, | ||
239 | .public_from_private = mlkem1024_public_from_private, | ||
240 | }; | ||
241 | |||
242 | return MlKemUnitTest(&mlkem1024_test); | ||
243 | } | ||
244 | |||
245 | int | 298 | int |
246 | main(void) | 299 | main(void) |
247 | { | 300 | { |
248 | int failed = 0; | 301 | int ret = 0; |
249 | 302 | ||
250 | /* | 303 | ret |= MlKemUnitTest(RANK768); |
251 | * XXX - this is split into two helper functions since having a few | 304 | ret |= MlKemUnitTest(RANK1024); |
252 | * ML-KEM key blobs on the stack makes Emscripten's stack explode, | ||
253 | * leading to inscrutable silent failures unless ASAN is enabled. | ||
254 | * Go figure. | ||
255 | */ | ||
256 | 305 | ||
257 | failed |= mlkem768_unittest(); | 306 | return ret; |
258 | failed |= mlkem1024_unittest(); | ||
259 | |||
260 | return failed; | ||
261 | } | 307 | } |