summaryrefslogtreecommitdiff
path: root/src/regress/lib/libcrypto/mlkem/mlkem_tests.c
diff options
context:
space:
mode:
authortb <>2024-12-26 00:04:24 +0000
committertb <>2024-12-26 00:04:24 +0000
commit31d1b04da9af806cdb66a2b49ed6490e67479eef (patch)
treef187d226245651988501e2fb8891081ff9eea9f2 /src/regress/lib/libcrypto/mlkem/mlkem_tests.c
parentfe8b80dbfd7a71d866da84cfdab5d2ce23feac28 (diff)
downloadopenbsd-31d1b04da9af806cdb66a2b49ed6490e67479eef.tar.gz
openbsd-31d1b04da9af806cdb66a2b49ed6490e67479eef.tar.bz2
openbsd-31d1b04da9af806cdb66a2b49ed6490e67479eef.zip
Overhaul ML-KEM regress once more
Implement a file parser that drives a state machine to extract the test data from the .txt files and manages the parsed data. Comments and empty lines are ignored. The code currently assumes that instruction lines are at the start of the file (which isn't generally true) and only supports two line types for now. This is good enough for all the ML-KEM tests but should be easy enough to extend. Once all data for a test case is parsed in the expected order, a test handler is called which can retrieve the test data via a simple API and throw warnings and errors with information on the test case line number, etc. Merge the tests into three programs: one parsing the .txt files and running the corresponding test cases, a unit test and the iteration tests. Deduplicate the actual test code and let the caller pass in an object containing the API functions, private keys and arrays that need to be different between the 768 version and the 1024 version. This way we don't have two sets of half a dozen .c files differing only in 3 or 4 occurrences of 768 and 1024. All this will also make it a lot easier to hook these tests into portable.
Diffstat (limited to 'src/regress/lib/libcrypto/mlkem/mlkem_tests.c')
-rw-r--r--src/regress/lib/libcrypto/mlkem/mlkem_tests.c728
1 files changed, 728 insertions, 0 deletions
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_tests.c b/src/regress/lib/libcrypto/mlkem/mlkem_tests.c
new file mode 100644
index 0000000000..716f38d144
--- /dev/null
+++ b/src/regress/lib/libcrypto/mlkem/mlkem_tests.c
@@ -0,0 +1,728 @@
1/* $OpenBSD: mlkem_tests.c,v 1.1 2024/12/26 00:04:24 tb Exp $ */
2/*
3 * Copyright (c) 2024 Google Inc.
4 * Copyright (c) 2024 Theo Buehler <tb@openbsd.org>
5 * Copyright (c) 2024 Bob Beck <beck@obtuse.com>
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
14 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
16 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <err.h>
21#include <stdint.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26#include "bytestring.h"
27#include "mlkem.h"
28
29#include "mlkem_internal.h"
30
31#include "mlkem_tests_util.h"
32#include "parse_test_file.h"
33
34enum test_type {
35 TEST_TYPE_NORMAL,
36 TEST_TYPE_NIST,
37};
38
39struct decap_ctx {
40 struct parse *parse_ctx;
41
42 void *private_key;
43 size_t private_key_len;
44
45 mlkem_parse_private_key_fn parse_private_key;
46 mlkem_decap_fn decap;
47};
48
49enum decap_states {
50 DECAP_PRIVATE_KEY,
51 DECAP_CIPHERTEXT,
52 DECAP_RESULT,
53 DECAP_SHARED_SECRET,
54 N_DECAP_STATES,
55};
56
57static const struct line_spec decap_state_machine[] = {
58 [DECAP_PRIVATE_KEY] = {
59 .state = DECAP_PRIVATE_KEY,
60 .type = LINE_HEX,
61 .name = "private key",
62 .label = "private_key",
63 },
64 [DECAP_CIPHERTEXT] = {
65 .state = DECAP_CIPHERTEXT,
66 .type = LINE_HEX,
67 .name = "cipher text",
68 .label = "ciphertext",
69 },
70 [DECAP_RESULT] = {
71 .state = DECAP_RESULT,
72 .type = LINE_STRING_MATCH,
73 .name = "result",
74 .label = "result",
75 .match = "fail",
76 },
77 [DECAP_SHARED_SECRET] = {
78 .state = DECAP_SHARED_SECRET,
79 .type = LINE_HEX,
80 .name = "shared secret",
81 .label = "shared_secret",
82 },
83};
84
85static int
86decap_init(void *ctx, void *parse_ctx)
87{
88 struct decap_ctx *decap = ctx;
89
90 decap->parse_ctx = parse_ctx;
91
92 return 1;
93}
94
95static void
96decap_finish(void *ctx)
97{
98 (void)ctx;
99}
100
101static int
102MlkemDecapFileTest(struct decap_ctx *decap)
103{
104 struct parse *p = decap->parse_ctx;
105 uint8_t shared_secret_buf[MLKEM_SHARED_SECRET_BYTES];
106 CBS ciphertext, shared_secret, private_key;
107 int should_fail;
108 int failed = 1;
109
110 parse_get_cbs(p, DECAP_CIPHERTEXT, &ciphertext);
111 parse_get_cbs(p, DECAP_SHARED_SECRET, &shared_secret);
112 parse_get_cbs(p, DECAP_PRIVATE_KEY, &private_key);
113 parse_get_int(p, DECAP_RESULT, &should_fail);
114
115 if (!decap->parse_private_key(decap->private_key, &private_key)) {
116 if ((failed = !should_fail))
117 parse_info(p, "parse private key");
118 goto err;
119 }
120 if (!decap->decap(shared_secret_buf,
121 CBS_data(&ciphertext), CBS_len(&ciphertext), decap->private_key)) {
122 if ((failed = !should_fail))
123 parse_info(p, decap");
124 goto err;
125 }
126
127 failed = !parse_data_equal(p, "shared_secret", &shared_secret,
128 shared_secret_buf, sizeof(shared_secret_buf));
129
130 if (should_fail != failed) {
131 parse_info(p, "FAIL: should_fail %d, failed %d",
132 should_fail, failed);
133 failed = 1;
134 }
135
136 err:
137 return failed;
138}
139
140static int
141decap_run_test_case(void *ctx)
142{
143 return MlkemDecapFileTest(ctx);
144}
145
146static const struct test_parse decap_parse = {
147 .states = decap_state_machine,
148 .num_states = N_DECAP_STATES,
149
150 .init = decap_init,
151 .finish = decap_finish,
152
153 .run_test_case = decap_run_test_case,
154};
155
156enum nist_decap_instructions {
157 NIST_DECAP_DK,
158 N_NIST_DECAP_INSTRUCTIONS,
159};
160
161static const struct line_spec nist_decap_instruction_state_machine[] = {
162 [NIST_DECAP_DK] = {
163 .state = NIST_DECAP_DK,
164 .type = LINE_HEX,
165 .name = "private key (instruction [dk])",
166 .label = "dk",
167 },
168};
169
170enum nist_decap_states {
171 NIST_DECAP_C,
172 NIST_DECAP_K,
173 N_NIST_DECAP_STATES,
174};
175
176static const struct line_spec nist_decap_state_machine[] = {
177 [NIST_DECAP_C] = {
178 .state = NIST_DECAP_C,
179 .type = LINE_HEX,
180 .name = "ciphertext (c)",
181 .label = "c",
182 },
183 [NIST_DECAP_K] = {
184 .state = NIST_DECAP_K,
185 .type = LINE_HEX,
186 .name = "shared secret (k)",
187 .label = "k",
188 },
189};
190
191static int
192MlkemNistDecapFileTest(struct decap_ctx *decap)
193{
194 struct parse *p = decap->parse_ctx;
195 uint8_t shared_secret[MLKEM_SHARED_SECRET_BYTES];
196 CBS dk, c, k;
197 int failed = 1;
198
199 parse_instruction_get_cbs(p, NIST_DECAP_DK, &dk);
200 parse_get_cbs(p, NIST_DECAP_C, &c);
201 parse_get_cbs(p, NIST_DECAP_K, &k);
202
203 if (!parse_length_equal(p, "private key",
204 decap->private_key_len, CBS_len(&dk)))
205 goto err;
206 if (!parse_length_equal(p, "shared secret",
207 MLKEM_SHARED_SECRET_BYTES, CBS_len(&k)))
208 goto err;
209
210 if (!decap->parse_private_key(decap->private_key, &dk)) {
211 parse_info(p, "parse private key");
212 goto err;
213 }
214 if (!decap->decap(shared_secret, CBS_data(&c), CBS_len(&c),
215 decap->private_key)) {
216 parse_info(p, "decap");
217 goto err;
218 }
219
220 failed = !parse_data_equal(p, "shared secret", &k,
221 shared_secret, MLKEM_SHARED_SECRET_BYTES);
222
223 err:
224 return failed;
225}
226
227static int
228nist_decap_run_test_case(void *ctx)
229{
230 return MlkemNistDecapFileTest(ctx);
231}
232
233static const struct test_parse nist_decap_parse = {
234 .instructions = nist_decap_instruction_state_machine,
235 .num_instructions = N_NIST_DECAP_INSTRUCTIONS,
236
237 .states = nist_decap_state_machine,
238 .num_states = N_NIST_DECAP_STATES,
239
240 .init = decap_init,
241 .finish = decap_finish,
242
243 .run_test_case = nist_decap_run_test_case,
244};
245
246static int
247mlkem_decap_tests(const char *fn, size_t size, enum test_type test_type)
248{
249 struct MLKEM768_private_key private_key768;
250 struct decap_ctx decap768 = {
251 .private_key = &private_key768,
252 .private_key_len = MLKEM768_PRIVATE_KEY_BYTES,
253
254 .parse_private_key = mlkem768_parse_private_key,
255 .decap = mlkem768_decap,
256 };
257 struct MLKEM1024_private_key private_key1024;
258 struct decap_ctx decap1024 = {
259 .private_key = &private_key1024,
260 .private_key_len = MLKEM1024_PRIVATE_KEY_BYTES,
261
262 .parse_private_key = mlkem1024_parse_private_key,
263 .decap = mlkem1024_decap,
264 };
265
266 if (size == 768 && test_type == TEST_TYPE_NORMAL)
267 return parse_test_file(fn, &decap_parse, &decap768);
268 if (size == 768 && test_type == TEST_TYPE_NIST)
269 return parse_test_file(fn, &nist_decap_parse, &decap768);
270 if (size == 1024 && test_type == TEST_TYPE_NORMAL)
271 return parse_test_file(fn, &decap_parse, &decap1024);
272 if (size == 1024 && test_type == TEST_TYPE_NIST)
273 return parse_test_file(fn, &nist_decap_parse, &decap1024);
274
275 errx(1, "unknown decap test: size %zu, type %d", size, test_type);
276}
277
278struct encap_ctx {
279 struct parse *parse_ctx;
280
281 void *public_key;
282 uint8_t *ciphertext;
283 size_t ciphertext_len;
284
285 mlkem_parse_public_key_fn parse_public_key;
286 mlkem_encap_external_entropy_fn encap_external_entropy;
287};
288
289enum encap_states {
290 ENCAP_ENTROPY,
291 ENCAP_PUBLIC_KEY,
292 ENCAP_RESULT,
293 ENCAP_CIPHERTEXT,
294 ENCAP_SHARED_SECRET,
295 N_ENCAP_STATES,
296};
297
298static const struct line_spec encap_state_machine[] = {
299 [ENCAP_ENTROPY] = {
300 .state = ENCAP_ENTROPY,
301 .type = LINE_HEX,
302 .name = "entropy",
303 .label = "entropy",
304 },
305 [ENCAP_PUBLIC_KEY] = {
306 .state = ENCAP_PUBLIC_KEY,
307 .type = LINE_HEX,
308 .name = "public key",
309 .label = "public_key",
310 },
311 [ENCAP_RESULT] = {
312 .state = ENCAP_RESULT,
313 .type = LINE_STRING_MATCH,
314 .name = "result",
315 .label = "result",
316 .match = "fail",
317 },
318 [ENCAP_CIPHERTEXT] = {
319 .state = ENCAP_CIPHERTEXT,
320 .type = LINE_HEX,
321 .name = "ciphertext",
322 .label = "ciphertext",
323 },
324 [ENCAP_SHARED_SECRET] = {
325 .state = ENCAP_SHARED_SECRET,
326 .type = LINE_HEX,
327 .name = "shared secret",
328 .label = "shared_secret",
329 },
330};
331
332static int
333encap_init(void *ctx, void *parse_ctx)
334{
335 struct encap_ctx *encap = ctx;
336
337 encap->parse_ctx = parse_ctx;
338
339 return 1;
340}
341
342static void
343encap_finish(void *ctx)
344{
345 (void)ctx;
346}
347
348static int
349MlkemEncapFileTest(struct encap_ctx *encap)
350{
351 struct parse *p = encap->parse_ctx;
352 uint8_t shared_secret_buf[MLKEM_SHARED_SECRET_BYTES];
353 CBS entropy, public_key, ciphertext, shared_secret;
354 int should_fail;
355 int failed = 1;
356
357 parse_get_cbs(p, ENCAP_ENTROPY, &entropy);
358 parse_get_cbs(p, ENCAP_PUBLIC_KEY, &public_key);
359 parse_get_cbs(p, ENCAP_CIPHERTEXT, &ciphertext);
360 parse_get_cbs(p, ENCAP_SHARED_SECRET, &shared_secret);
361 parse_get_int(p, ENCAP_RESULT, &should_fail);
362
363 if (!encap->parse_public_key(encap->public_key, &public_key)) {
364 if ((failed = !should_fail))
365 parse_info(p, "parse public key");
366 goto err;
367 }
368 encap->encap_external_entropy(encap->ciphertext, shared_secret_buf,
369 encap->public_key, CBS_data(&entropy));
370
371 failed = !parse_data_equal(p, "shared_secret", &shared_secret,
372 shared_secret_buf, sizeof(shared_secret_buf));
373 failed |= !parse_data_equal(p, "ciphertext", &ciphertext,
374 encap->ciphertext, encap->ciphertext_len);
375
376 if (should_fail != failed) {
377 parse_info(p, "FAIL: should_fail %d, failed %d",
378 should_fail, failed);
379 failed = 1;
380 }
381
382 err:
383 return failed;
384}
385
386static int
387encap_run_test_case(void *ctx)
388{
389 return MlkemEncapFileTest(ctx);
390}
391
392static const struct test_parse encap_parse = {
393 .states = encap_state_machine,
394 .num_states = N_ENCAP_STATES,
395
396 .init = encap_init,
397 .finish = encap_finish,
398
399 .run_test_case = encap_run_test_case,
400};
401
402static int
403mlkem_encap_tests(const char *fn, size_t size)
404{
405 struct MLKEM768_public_key public_key768;
406 uint8_t ciphertext768[MLKEM768_CIPHERTEXT_BYTES];
407 struct encap_ctx encap768 = {
408 .public_key = &public_key768,
409 .ciphertext = ciphertext768,
410 .ciphertext_len = sizeof(ciphertext768),
411
412 .parse_public_key = mlkem768_parse_public_key,
413 .encap_external_entropy = mlkem768_encap_external_entropy,
414 };
415 struct MLKEM1024_public_key public_key1024;
416 uint8_t ciphertext1024[MLKEM1024_CIPHERTEXT_BYTES];
417 struct encap_ctx encap1024 = {
418 .public_key = &public_key1024,
419 .ciphertext = ciphertext1024,
420 .ciphertext_len = sizeof(ciphertext1024),
421
422 .parse_public_key = mlkem1024_parse_public_key,
423 .encap_external_entropy = mlkem1024_encap_external_entropy,
424 };
425
426 if (size == 768)
427 return parse_test_file(fn, &encap_parse, &encap768);
428 if (size == 1024)
429 return parse_test_file(fn, &encap_parse, &encap1024);
430
431 errx(1, "unknown encap test: size %zu", size);
432}
433
434struct keygen_ctx {
435 struct parse *parse_ctx;
436
437 void *private_key;
438 void *encoded_public_key;
439 size_t encoded_public_key_len;
440 size_t private_key_len;
441 size_t public_key_len;
442
443 mlkem_generate_key_external_entropy_fn generate_key_external_entropy;
444 mlkem_encode_private_key_fn encode_private_key;
445};
446
447enum keygen_states {
448 KEYGEN_SEED,
449 KEYGEN_PUBLIC_KEY,
450 KEYGEN_PRIVATE_KEY,
451 N_KEYGEN_STATES,
452};
453
454static const struct line_spec keygen_state_machine[] = {
455 [KEYGEN_SEED] = {
456 .state = KEYGEN_SEED,
457 .type = LINE_HEX,
458 .name = "seed",
459 .label = "seed",
460 },
461 [KEYGEN_PUBLIC_KEY] = {
462 .state = KEYGEN_PUBLIC_KEY,
463 .type = LINE_HEX,
464 .name = "public key",
465 .label = "public_key",
466 },
467 [KEYGEN_PRIVATE_KEY] = {
468 .state = KEYGEN_PRIVATE_KEY,
469 .type = LINE_HEX,
470 .name = "private key",
471 .label = "private_key",
472 },
473};
474
475static int
476keygen_init(void *ctx, void *parse_ctx)
477{
478 struct keygen_ctx *keygen = ctx;
479
480 keygen->parse_ctx = parse_ctx;
481
482 return 1;
483}
484
485static void
486keygen_finish(void *ctx)
487{
488 (void)ctx;
489}
490
491static int
492MlkemKeygenFileTest(struct keygen_ctx *keygen)
493{
494 struct parse *p = keygen->parse_ctx;
495 CBS seed, public_key, private_key;
496 uint8_t *encoded_private_key = NULL;
497 size_t encoded_private_key_len = 0;
498 int failed = 1;
499
500 parse_get_cbs(p, KEYGEN_SEED, &seed);
501 parse_get_cbs(p, KEYGEN_PUBLIC_KEY, &public_key);
502 parse_get_cbs(p, KEYGEN_PRIVATE_KEY, &private_key);
503
504 if (!parse_length_equal(p, "seed", MLKEM_SEED_BYTES, CBS_len(&seed)))
505 goto err;
506 if (!parse_length_equal(p, "public key",
507 keygen->public_key_len, CBS_len(&public_key)))
508 goto err;
509 if (!parse_length_equal(p, "private key",
510 keygen->private_key_len, CBS_len(&private_key)))
511 goto err;
512
513 keygen->generate_key_external_entropy(keygen->encoded_public_key,
514 keygen->private_key, CBS_data(&seed));
515 if (!keygen->encode_private_key(keygen->private_key,
516 &encoded_private_key, &encoded_private_key_len)) {
517 parse_info(p, "encode private key");
518 goto err;
519 }
520
521 failed = !parse_data_equal(p, "private key", &private_key,
522 encoded_private_key, encoded_private_key_len);
523 failed |= !parse_data_equal(p, "public key", &public_key,
524 keygen->encoded_public_key, keygen->encoded_public_key_len);
525
526 err:
527 freezero(encoded_private_key, encoded_private_key_len);
528
529 return failed;
530}
531
532static int
533keygen_run_test_case(void *ctx)
534{
535 return MlkemKeygenFileTest(ctx);
536}
537
538static const struct test_parse keygen_parse = {
539 .states = keygen_state_machine,
540 .num_states = N_KEYGEN_STATES,
541
542 .init = keygen_init,
543 .finish = keygen_finish,
544
545 .run_test_case = keygen_run_test_case,
546};
547
548enum nist_keygen_states {
549 NIST_KEYGEN_Z,
550 NIST_KEYGEN_D,
551 NIST_KEYGEN_EK,
552 NIST_KEYGEN_DK,
553 N_NIST_KEYGEN_STATES,
554};
555
556static const struct line_spec nist_keygen_state_machine[] = {
557 [NIST_KEYGEN_Z] = {
558 .state = NIST_KEYGEN_Z,
559 .type = LINE_HEX,
560 .name = "seed (z)",
561 .label = "z",
562 },
563 [NIST_KEYGEN_D] = {
564 .state = NIST_KEYGEN_D,
565 .type = LINE_HEX,
566 .name = "seed (d)",
567 .label = "d",
568 },
569 [NIST_KEYGEN_EK] = {
570 .state = NIST_KEYGEN_EK,
571 .type = LINE_HEX,
572 .name = "public key (ek)",
573 .label = "ek",
574 },
575 [NIST_KEYGEN_DK] = {
576 .state = NIST_KEYGEN_DK,
577 .type = LINE_HEX,
578 .name = "private key (dk)",
579 .label = "dk",
580 },
581};
582
583static int
584MlkemNistKeygenFileTest(struct keygen_ctx *keygen)
585{
586 struct parse *p = keygen->parse_ctx;
587 CBB seed_cbb;
588 CBS z, d, ek, dk;
589 uint8_t seed[MLKEM_SEED_BYTES];
590 size_t seed_len;
591 uint8_t *encoded_private_key = NULL;
592 size_t encoded_private_key_len = 0;
593 int failed = 1;
594
595 parse_get_cbs(p, NIST_KEYGEN_Z, &z);
596 parse_get_cbs(p, NIST_KEYGEN_D, &d);
597 parse_get_cbs(p, NIST_KEYGEN_EK, &ek);
598 parse_get_cbs(p, NIST_KEYGEN_DK, &dk);
599
600 if (!CBB_init_fixed(&seed_cbb, seed, sizeof(seed)))
601 parse_errx(p, "CBB_init_fixed");
602 if (!CBB_add_bytes(&seed_cbb, CBS_data(&d), CBS_len(&d)))
603 parse_errx(p, "CBB_add_bytes");
604 if (!CBB_add_bytes(&seed_cbb, CBS_data(&z), CBS_len(&z)))
605 parse_errx(p, "CBB_add_bytes");
606 if (!CBB_finish(&seed_cbb, NULL, &seed_len))
607 parse_errx(p, "CBB_finish");
608
609 if (!parse_length_equal(p, "bogus z or d", MLKEM_SEED_BYTES, seed_len))
610 goto err;
611
612 keygen->generate_key_external_entropy(keygen->encoded_public_key,
613 keygen->private_key, seed);
614 if (!keygen->encode_private_key(keygen->private_key,
615 &encoded_private_key, &encoded_private_key_len)) {
616 parse_info(p, "encode private key");
617 goto err;
618 }
619
620 failed = !parse_data_equal(p, "public key", &ek,
621 keygen->encoded_public_key, keygen->encoded_public_key_len);
622 failed |= !parse_data_equal(p, "private key", &dk,
623 encoded_private_key, encoded_private_key_len);
624
625 err:
626 freezero(encoded_private_key, encoded_private_key_len);
627
628 return failed;
629}
630
631static int
632nist_keygen_run_test_case(void *ctx)
633{
634 return MlkemNistKeygenFileTest(ctx);
635}
636
637static const struct test_parse nist_keygen_parse = {
638 .states = nist_keygen_state_machine,
639 .num_states = N_NIST_KEYGEN_STATES,
640
641 .init = keygen_init,
642 .finish = keygen_finish,
643
644 .run_test_case = nist_keygen_run_test_case,
645};
646
647static int
648mlkem_keygen_tests(const char *fn, size_t size, enum test_type test_type)
649{
650 struct MLKEM768_private_key private_key768;
651 uint8_t encoded_public_key768[MLKEM768_PUBLIC_KEY_BYTES];
652 struct keygen_ctx keygen768 = {
653 .private_key = &private_key768,
654 .encoded_public_key = encoded_public_key768,
655 .encoded_public_key_len = sizeof(encoded_public_key768),
656 .private_key_len = MLKEM768_PRIVATE_KEY_BYTES,
657 .public_key_len = MLKEM768_PUBLIC_KEY_BYTES,
658 .generate_key_external_entropy =
659 mlkem768_generate_key_external_entropy,
660 .encode_private_key =
661 mlkem768_encode_private_key,
662 };
663 struct MLKEM1024_private_key private_key1024;
664 uint8_t encoded_public_key1024[MLKEM1024_PUBLIC_KEY_BYTES];
665 struct keygen_ctx keygen1024 = {
666 .private_key = &private_key1024,
667 .encoded_public_key = encoded_public_key1024,
668 .encoded_public_key_len = sizeof(encoded_public_key1024),
669 .private_key_len = MLKEM1024_PRIVATE_KEY_BYTES,
670 .public_key_len = MLKEM1024_PUBLIC_KEY_BYTES,
671
672 .generate_key_external_entropy =
673 mlkem1024_generate_key_external_entropy,
674 .encode_private_key =
675 mlkem1024_encode_private_key,
676 };
677
678 if (size == 768 && test_type == TEST_TYPE_NORMAL)
679 return parse_test_file(fn, &keygen_parse, &keygen768);
680 if (size == 768 && test_type == TEST_TYPE_NIST)
681 return parse_test_file(fn, &nist_keygen_parse, &keygen768);
682 if (size == 1024 && test_type == TEST_TYPE_NORMAL)
683 return parse_test_file(fn, &keygen_parse, &keygen1024);
684 if (size == 1024 && test_type == TEST_TYPE_NIST)
685 return parse_test_file(fn, &nist_keygen_parse, &keygen1024);
686
687 errx(1, "unknown keygen test: size %zu, type %d", size, test_type);
688}
689
690static int
691run_mlkem_test(const char *test, const char *fn)
692{
693 if (strcmp(test, "mlkem768_decap_tests") == 0)
694 return mlkem_decap_tests(fn, 768, TEST_TYPE_NORMAL);
695 if (strcmp(test, "mlkem768_nist_decap_tests") == 0)
696 return mlkem_decap_tests(fn, 768, TEST_TYPE_NIST);
697 if (strcmp(test, "mlkem1024_decap_tests") == 0)
698 return mlkem_decap_tests(fn, 1024, TEST_TYPE_NORMAL);
699 if (strcmp(test, "mlkem1024_nist_decap_tests") == 0)
700 return mlkem_decap_tests(fn, 1024, TEST_TYPE_NIST);
701
702 if (strcmp(test, "mlkem768_encap_tests") == 0)
703 return mlkem_encap_tests(fn, 768);
704 if (strcmp(test, "mlkem1024_encap_tests") == 0)
705 return mlkem_encap_tests(fn, 1024);
706
707 if (strcmp(test, "mlkem768_keygen_tests") == 0)
708 return mlkem_keygen_tests(fn, 768, TEST_TYPE_NORMAL);
709 if (strcmp(test, "mlkem768_nist_keygen_tests") == 0)
710 return mlkem_keygen_tests(fn, 768, TEST_TYPE_NIST);
711 if (strcmp(test, "mlkem1024_keygen_tests") == 0)
712 return mlkem_keygen_tests(fn, 1024, TEST_TYPE_NORMAL);
713 if (strcmp(test, "mlkem1024_nist_keygen_tests") == 0)
714 return mlkem_keygen_tests(fn, 1024, TEST_TYPE_NIST);
715
716 errx(1, "unknown test %s (test file %s)", test, fn);
717}
718
719int
720main(int argc, const char *argv[])
721{
722 if (argc != 3) {
723 fprintf(stderr, "usage: mlkem_test test testfile.txt\n");
724 exit(1);
725 }
726
727 return run_mlkem_test(argv[1], argv[2]);
728}