summaryrefslogtreecommitdiff
path: root/src/regress
diff options
context:
space:
mode:
Diffstat (limited to 'src/regress')
-rw-r--r--src/regress/lib/libc/Makefile4
-rw-r--r--src/regress/lib/libc/hash/hash_test.c6
-rw-r--r--src/regress/lib/libc/illumos/Makefile7
-rw-r--r--src/regress/lib/libc/illumos/Makefile.inc9
-rw-r--r--src/regress/lib/libc/illumos/oclo/Makefile18
-rw-r--r--src/regress/lib/libc/time/time_conversion/timetest.c158
-rw-r--r--src/regress/lib/libcrypto/bn/bn_mul_div.c15
-rw-r--r--src/regress/lib/libcrypto/ec/Makefile3
-rw-r--r--src/regress/lib/libcrypto/ec/ec_arithmetic.c210
-rw-r--r--src/regress/lib/libcrypto/mlkem/Makefile4
-rw-r--r--src/regress/lib/libcrypto/mlkem/mlkem_iteration_tests.c180
-rw-r--r--src/regress/lib/libcrypto/mlkem/mlkem_tests.c299
-rw-r--r--src/regress/lib/libcrypto/mlkem/mlkem_tests_util.c161
-rw-r--r--src/regress/lib/libcrypto/mlkem/mlkem_tests_util.h63
-rw-r--r--src/regress/lib/libcrypto/mlkem/mlkem_unittest.c302
15 files changed, 744 insertions, 695 deletions
diff --git a/src/regress/lib/libc/Makefile b/src/regress/lib/libc/Makefile
index 59d043c62f..7a8db225ef 100644
--- a/src/regress/lib/libc/Makefile
+++ b/src/regress/lib/libc/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.61 2025/05/25 00:19:00 yasuoka Exp $ 1# $OpenBSD: Makefile,v 1.62 2025/08/04 06:10:40 tb Exp $
2 2
3SUBDIR+= _setjmp 3SUBDIR+= _setjmp
4SUBDIR+= alloca arc4random-fork atexit 4SUBDIR+= alloca arc4random-fork atexit
@@ -11,7 +11,7 @@ SUBDIR+= ffs fmemopen fnmatch fpclassify fread
11SUBDIR+= gcvt getaddrinfo getcap getopt getopt_long glob 11SUBDIR+= gcvt getaddrinfo getcap getopt getopt_long glob
12SUBDIR+= hash 12SUBDIR+= hash
13SUBDIR+= hsearch 13SUBDIR+= hsearch
14SUBDIR+= ieeefp ifnameindex 14SUBDIR+= ieeefp ifnameindex illumos
15SUBDIR+= ldexp locale longjmp 15SUBDIR+= ldexp locale longjmp
16SUBDIR+= malloc mkstemp modf 16SUBDIR+= malloc mkstemp modf
17SUBDIR+= netdb 17SUBDIR+= netdb
diff --git a/src/regress/lib/libc/hash/hash_test.c b/src/regress/lib/libc/hash/hash_test.c
index f9dc641186..c04a0458fe 100644
--- a/src/regress/lib/libc/hash/hash_test.c
+++ b/src/regress/lib/libc/hash/hash_test.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: hash_test.c,v 1.2 2025/04/14 18:33:56 tb Exp $ */ 1/* $OpenBSD: hash_test.c,v 1.3 2025/08/02 06:05:13 tb Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2025 Theo Buehler <tb@openbsd.org> 4 * Copyright (c) 2025 Theo Buehler <tb@openbsd.org>
@@ -757,7 +757,7 @@ struct hash_ctx {
757 void *ctx; 757 void *ctx;
758 void (*init)(void *); 758 void (*init)(void *);
759 void (*update)(void *, const uint8_t *, size_t); 759 void (*update)(void *, const uint8_t *, size_t);
760 void (*final)(void *, void *final); 760 void (*final)(void *, void *);
761}; 761};
762 762
763static const struct hash_tests { 763static const struct hash_tests {
@@ -814,7 +814,7 @@ hash_test_case(struct hash_ctx *ctx, const struct hash_test_case *tc,
814 size_t in_len = tc->in != NULL ? strlen(tc->in) : 0; 814 size_t in_len = tc->in != NULL ? strlen(tc->in) : 0;
815 815
816 ctx->init(ctx->ctx); 816 ctx->init(ctx->ctx);
817 ctx->update(ctx->ctx, (uint8_t *)tc->in, in_len); 817 ctx->update(ctx->ctx, (const uint8_t *)tc->in, in_len);
818 ctx->final(ctx->digest, ctx->ctx); 818 ctx->final(ctx->digest, ctx->ctx);
819 819
820 if (memcmp(tc->out, ctx->digest, ctx->digest_len) != 0) { 820 if (memcmp(tc->out, ctx->digest, ctx->digest_len) != 0) {
diff --git a/src/regress/lib/libc/illumos/Makefile b/src/regress/lib/libc/illumos/Makefile
new file mode 100644
index 0000000000..cf2d22eb44
--- /dev/null
+++ b/src/regress/lib/libc/illumos/Makefile
@@ -0,0 +1,7 @@
1# $OpenBSD: Makefile,v 1.1.1.1 2025/08/02 06:16:34 tb Exp $
2
3SUBDIR += oclo
4
5install:
6
7.include <bsd.subdir.mk>
diff --git a/src/regress/lib/libc/illumos/Makefile.inc b/src/regress/lib/libc/illumos/Makefile.inc
new file mode 100644
index 0000000000..4296b6e690
--- /dev/null
+++ b/src/regress/lib/libc/illumos/Makefile.inc
@@ -0,0 +1,9 @@
1# $OpenBSD: Makefile.inc,v 1.1.1.1 2025/08/02 06:16:34 tb Exp $
2
3ILLUMOS_OS_TESTDIR = /usr/local/share/illumos-os-tests
4
5.if !exists(${ILLUMOS_OS_TESTDIR})
6regress:
7 @echo package illumos-os-tests is required for this regress
8 @echo SKIPPED
9.endif
diff --git a/src/regress/lib/libc/illumos/oclo/Makefile b/src/regress/lib/libc/illumos/oclo/Makefile
new file mode 100644
index 0000000000..284e49dc73
--- /dev/null
+++ b/src/regress/lib/libc/illumos/oclo/Makefile
@@ -0,0 +1,18 @@
1# $OpenBSD: Makefile,v 1.2 2025/08/09 18:17:42 anton Exp $
2
3.if exists(/usr/local/share/illumos-os-tests)
4
5PROGS = oclo
6PROGS += oclo_errors
7PROGS += ocloexec_verify
8
9LDADD_ocloexec_verify = -lkvm
10
11WARNINGS = yes
12
13regress: ${PROGS}
14
15.PATH: /usr/local/share/illumos-os-tests/tests/oclo
16.endif
17
18.include <bsd.regress.mk>
diff --git a/src/regress/lib/libc/time/time_conversion/timetest.c b/src/regress/lib/libc/time/time_conversion/timetest.c
index 0706704ee1..1405f1c6a5 100644
--- a/src/regress/lib/libc/time/time_conversion/timetest.c
+++ b/src/regress/lib/libc/time/time_conversion/timetest.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: timetest.c,v 1.4 2023/04/13 11:32:06 mbuhl Exp $ */ 1/* $OpenBSD: timetest.c,v 1.5 2025/08/17 08:43:03 phessler Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2022 Bob Beck <beck@openbsd.org> 4 * Copyright (c) 2022 Bob Beck <beck@openbsd.org>
@@ -79,12 +79,12 @@ struct timetest timetests[] = {
79 .tm_yday=171, 79 .tm_yday=171,
80 .tm_isdst=0, 80 .tm_isdst=0,
81 .tm_gmtoff=0, 81 .tm_gmtoff=0,
82 .tm_zone="GMT" 82 .tm_zone="UTC"
83 }, 83 },
84 }, 84 },
85 { 85 {
86 .descr="moon", 86 .descr="moon",
87 .timezone="right/UTC", 87 .timezone="right/GMT",
88 .time=-16751025, 88 .time=-16751025,
89 .local_tm= { 89 .local_tm= {
90 .tm_year=69, 90 .tm_year=69,
@@ -97,7 +97,7 @@ struct timetest timetests[] = {
97 .tm_yday=171, 97 .tm_yday=171,
98 .tm_isdst=0, 98 .tm_isdst=0,
99 .tm_gmtoff=0, 99 .tm_gmtoff=0,
100 .tm_zone="UTC" 100 .tm_zone="GMT"
101 }, 101 },
102 .gmt_tm= { 102 .gmt_tm= {
103 .tm_year=69, 103 .tm_year=69,
@@ -110,7 +110,7 @@ struct timetest timetests[] = {
110 .tm_yday=171, 110 .tm_yday=171,
111 .tm_isdst=0, 111 .tm_isdst=0,
112 .tm_gmtoff=0, 112 .tm_gmtoff=0,
113 .tm_zone="GMT" 113 .tm_zone="UTC"
114 }, 114 },
115 }, 115 },
116 { 116 {
@@ -141,7 +141,7 @@ struct timetest timetests[] = {
141 .tm_yday=171, 141 .tm_yday=171,
142 .tm_isdst=0, 142 .tm_isdst=0,
143 .tm_gmtoff=0, 143 .tm_gmtoff=0,
144 .tm_zone="GMT" 144 .tm_zone="UTC"
145 }, 145 },
146 }, 146 },
147 { 147 {
@@ -172,12 +172,12 @@ struct timetest timetests[] = {
172 .tm_yday=0, 172 .tm_yday=0,
173 .tm_isdst=0, 173 .tm_isdst=0,
174 .tm_gmtoff=0, 174 .tm_gmtoff=0,
175 .tm_zone="GMT" 175 .tm_zone="UTC"
176 }, 176 },
177 }, 177 },
178 { 178 {
179 .descr="epoch", 179 .descr="epoch",
180 .timezone="right/UTC", 180 .timezone="right/GMT",
181 .time=0, 181 .time=0,
182 .local_tm= { 182 .local_tm= {
183 .tm_year=70, 183 .tm_year=70,
@@ -190,7 +190,7 @@ struct timetest timetests[] = {
190 .tm_yday=0, 190 .tm_yday=0,
191 .tm_isdst=0, 191 .tm_isdst=0,
192 .tm_gmtoff=0, 192 .tm_gmtoff=0,
193 .tm_zone="UTC" 193 .tm_zone="GMT"
194 }, 194 },
195 .gmt_tm= { 195 .gmt_tm= {
196 .tm_year=70, 196 .tm_year=70,
@@ -203,7 +203,7 @@ struct timetest timetests[] = {
203 .tm_yday=0, 203 .tm_yday=0,
204 .tm_isdst=0, 204 .tm_isdst=0,
205 .tm_gmtoff=0, 205 .tm_gmtoff=0,
206 .tm_zone="GMT" 206 .tm_zone="UTC"
207 }, 207 },
208 }, 208 },
209 { 209 {
@@ -234,7 +234,7 @@ struct timetest timetests[] = {
234 .tm_yday=0, 234 .tm_yday=0,
235 .tm_isdst=0, 235 .tm_isdst=0,
236 .tm_gmtoff=0, 236 .tm_gmtoff=0,
237 .tm_zone="GMT" 237 .tm_zone="UTC"
238 }, 238 },
239 }, 239 },
240 { 240 {
@@ -265,12 +265,12 @@ struct timetest timetests[] = {
265 .tm_yday=364, 265 .tm_yday=364,
266 .tm_isdst=0, 266 .tm_isdst=0,
267 .tm_gmtoff=0, 267 .tm_gmtoff=0,
268 .tm_zone="GMT" 268 .tm_zone="UTC"
269 }, 269 },
270 }, 270 },
271 { 271 {
272 .descr="epoch - 1", 272 .descr="epoch - 1",
273 .timezone="right/UTC", 273 .timezone="right/GMT",
274 .time=-1, 274 .time=-1,
275 .local_tm= { 275 .local_tm= {
276 .tm_year=69, 276 .tm_year=69,
@@ -283,7 +283,7 @@ struct timetest timetests[] = {
283 .tm_yday=364, 283 .tm_yday=364,
284 .tm_isdst=0, 284 .tm_isdst=0,
285 .tm_gmtoff=0, 285 .tm_gmtoff=0,
286 .tm_zone="UTC" 286 .tm_zone="GMT"
287 }, 287 },
288 .gmt_tm= { 288 .gmt_tm= {
289 .tm_year=69, 289 .tm_year=69,
@@ -296,7 +296,7 @@ struct timetest timetests[] = {
296 .tm_yday=364, 296 .tm_yday=364,
297 .tm_isdst=0, 297 .tm_isdst=0,
298 .tm_gmtoff=0, 298 .tm_gmtoff=0,
299 .tm_zone="GMT" 299 .tm_zone="UTC"
300 }, 300 },
301 }, 301 },
302 { 302 {
@@ -327,7 +327,7 @@ struct timetest timetests[] = {
327 .tm_yday=364, 327 .tm_yday=364,
328 .tm_isdst=0, 328 .tm_isdst=0,
329 .tm_gmtoff=0, 329 .tm_gmtoff=0,
330 .tm_zone="GMT" 330 .tm_zone="UTC"
331 }, 331 },
332 }, 332 },
333 { 333 {
@@ -358,12 +358,12 @@ struct timetest timetests[] = {
358 .tm_yday=346, 358 .tm_yday=346,
359 .tm_isdst=0, 359 .tm_isdst=0,
360 .tm_gmtoff=0, 360 .tm_gmtoff=0,
361 .tm_zone="GMT" 361 .tm_zone="UTC"
362 }, 362 },
363 }, 363 },
364 { 364 {
365 .descr="legacy min", 365 .descr="legacy min",
366 .timezone="right/UTC", 366 .timezone="right/GMT",
367 .time=-2147483648, 367 .time=-2147483648,
368 .local_tm= { 368 .local_tm= {
369 .tm_year=1, 369 .tm_year=1,
@@ -376,7 +376,7 @@ struct timetest timetests[] = {
376 .tm_yday=346, 376 .tm_yday=346,
377 .tm_isdst=0, 377 .tm_isdst=0,
378 .tm_gmtoff=0, 378 .tm_gmtoff=0,
379 .tm_zone="UTC" 379 .tm_zone="GMT"
380 }, 380 },
381 .gmt_tm= { 381 .gmt_tm= {
382 .tm_year=1, 382 .tm_year=1,
@@ -389,7 +389,7 @@ struct timetest timetests[] = {
389 .tm_yday=346, 389 .tm_yday=346,
390 .tm_isdst=0, 390 .tm_isdst=0,
391 .tm_gmtoff=0, 391 .tm_gmtoff=0,
392 .tm_zone="GMT" 392 .tm_zone="UTC"
393 }, 393 },
394 }, 394 },
395 { 395 {
@@ -420,12 +420,12 @@ struct timetest timetests[] = {
420 .tm_yday=346, 420 .tm_yday=346,
421 .tm_isdst=0, 421 .tm_isdst=0,
422 .tm_gmtoff=0, 422 .tm_gmtoff=0,
423 .tm_zone="GMT" 423 .tm_zone="UTC"
424 }, 424 },
425 }, 425 },
426 { 426 {
427 .descr="legacy min - 1", 427 .descr="legacy min - 1",
428 .timezone="right/UTC", 428 .timezone="right/GMT",
429 .time=-2147483649, 429 .time=-2147483649,
430 .local_tm= { 430 .local_tm= {
431 .tm_year=1, 431 .tm_year=1,
@@ -438,7 +438,7 @@ struct timetest timetests[] = {
438 .tm_yday=346, 438 .tm_yday=346,
439 .tm_isdst=0, 439 .tm_isdst=0,
440 .tm_gmtoff=0, 440 .tm_gmtoff=0,
441 .tm_zone="UTC" 441 .tm_zone="GMT"
442 }, 442 },
443 .gmt_tm= { 443 .gmt_tm= {
444 .tm_year=1, 444 .tm_year=1,
@@ -451,7 +451,7 @@ struct timetest timetests[] = {
451 .tm_yday=346, 451 .tm_yday=346,
452 .tm_isdst=0, 452 .tm_isdst=0,
453 .tm_gmtoff=0, 453 .tm_gmtoff=0,
454 .tm_zone="GMT" 454 .tm_zone="UTC"
455 }, 455 },
456 }, 456 },
457 { 457 {
@@ -482,12 +482,12 @@ struct timetest timetests[] = {
482 .tm_yday=18, 482 .tm_yday=18,
483 .tm_isdst=0, 483 .tm_isdst=0,
484 .tm_gmtoff=0, 484 .tm_gmtoff=0,
485 .tm_zone="GMT" 485 .tm_zone="UTC"
486 }, 486 },
487 }, 487 },
488 { 488 {
489 .descr="legacy max", 489 .descr="legacy max",
490 .timezone="right/UTC", 490 .timezone="right/GMT",
491 .time=2147483647, 491 .time=2147483647,
492 .local_tm= { 492 .local_tm= {
493 .tm_year=138, 493 .tm_year=138,
@@ -500,7 +500,7 @@ struct timetest timetests[] = {
500 .tm_yday=18, 500 .tm_yday=18,
501 .tm_isdst=0, 501 .tm_isdst=0,
502 .tm_gmtoff=0, 502 .tm_gmtoff=0,
503 .tm_zone="UTC" 503 .tm_zone="GMT"
504 }, 504 },
505 .gmt_tm= { 505 .gmt_tm= {
506 .tm_year=138, 506 .tm_year=138,
@@ -513,7 +513,7 @@ struct timetest timetests[] = {
513 .tm_yday=18, 513 .tm_yday=18,
514 .tm_isdst=0, 514 .tm_isdst=0,
515 .tm_gmtoff=0, 515 .tm_gmtoff=0,
516 .tm_zone="GMT" 516 .tm_zone="UTC"
517 }, 517 },
518 }, 518 },
519 { 519 {
@@ -544,12 +544,12 @@ struct timetest timetests[] = {
544 .tm_yday=18, 544 .tm_yday=18,
545 .tm_isdst=0, 545 .tm_isdst=0,
546 .tm_gmtoff=0, 546 .tm_gmtoff=0,
547 .tm_zone="GMT" 547 .tm_zone="UTC"
548 }, 548 },
549 }, 549 },
550 { 550 {
551 .descr="legacy max + 1", 551 .descr="legacy max + 1",
552 .timezone="right/UTC", 552 .timezone="right/GMT",
553 .time=2147483648, 553 .time=2147483648,
554 .local_tm= { 554 .local_tm= {
555 .tm_year=138, 555 .tm_year=138,
@@ -562,7 +562,7 @@ struct timetest timetests[] = {
562 .tm_yday=18, 562 .tm_yday=18,
563 .tm_isdst=0, 563 .tm_isdst=0,
564 .tm_gmtoff=0, 564 .tm_gmtoff=0,
565 .tm_zone="UTC" 565 .tm_zone="GMT"
566 }, 566 },
567 .gmt_tm= { 567 .gmt_tm= {
568 .tm_year=138, 568 .tm_year=138,
@@ -575,7 +575,7 @@ struct timetest timetests[] = {
575 .tm_yday=18, 575 .tm_yday=18,
576 .tm_isdst=0, 576 .tm_isdst=0,
577 .tm_gmtoff=0, 577 .tm_gmtoff=0,
578 .tm_zone="GMT" 578 .tm_zone="UTC"
579 }, 579 },
580 }, 580 },
581 { 581 {
@@ -611,7 +611,7 @@ struct timetest timetests[] = {
611 }, 611 },
612 { 612 {
613 .descr="min", 613 .descr="min",
614 .timezone="right/UTC", 614 .timezone="right/GMT",
615 .time=INT64_MIN, 615 .time=INT64_MIN,
616 .local_tm= { 616 .local_tm= {
617 .tm_year=0, 617 .tm_year=0,
@@ -704,7 +704,7 @@ struct timetest timetests[] = {
704 }, 704 },
705 { 705 {
706 .descr="max", 706 .descr="max",
707 .timezone="right/UTC", 707 .timezone="right/GMT",
708 .time=9223372036854775807, 708 .time=9223372036854775807,
709 .local_tm= { 709 .local_tm= {
710 .tm_year=0, 710 .tm_year=0,
@@ -792,7 +792,7 @@ struct timetest timetests[] = {
792 .tm_yday=30, 792 .tm_yday=30,
793 .tm_isdst=0, 793 .tm_isdst=0,
794 .tm_gmtoff=0, 794 .tm_gmtoff=0,
795 .tm_zone="GMT" 795 .tm_zone="UTC"
796 }, 796 },
797 }, 797 },
798 { 798 {
@@ -823,12 +823,12 @@ struct timetest timetests[] = {
823 .tm_yday=30, 823 .tm_yday=30,
824 .tm_isdst=0, 824 .tm_isdst=0,
825 .tm_gmtoff=0, 825 .tm_gmtoff=0,
826 .tm_zone="GMT" 826 .tm_zone="UTC"
827 }, 827 },
828 }, 828 },
829 { 829 {
830 .descr="maxint struct tm", 830 .descr="maxint struct tm",
831 .timezone="right/UTC", 831 .timezone="right/GMT",
832 .time=67767976204675199, 832 .time=67767976204675199,
833 .local_tm= { 833 .local_tm= {
834 .tm_year=2147481747, 834 .tm_year=2147481747,
@@ -841,7 +841,7 @@ struct timetest timetests[] = {
841 .tm_yday=30, 841 .tm_yday=30,
842 .tm_isdst=0, 842 .tm_isdst=0,
843 .tm_gmtoff=0, 843 .tm_gmtoff=0,
844 .tm_zone="UTC" 844 .tm_zone="GMT"
845 }, 845 },
846 .gmt_tm= { 846 .gmt_tm= {
847 .tm_year=2147481747, 847 .tm_year=2147481747,
@@ -854,12 +854,12 @@ struct timetest timetests[] = {
854 .tm_yday=30, 854 .tm_yday=30,
855 .tm_isdst=0, 855 .tm_isdst=0,
856 .tm_gmtoff=0, 856 .tm_gmtoff=0,
857 .tm_zone="GMT" 857 .tm_zone="UTC"
858 }, 858 },
859 }, 859 },
860 { 860 {
861 .descr="minint struct tm", 861 .descr="minint struct tm",
862 .timezone="right/UTC", 862 .timezone="right/GMT",
863 .time=-67768038398073601, 863 .time=-67768038398073601,
864 .local_tm= { 864 .local_tm= {
865 .tm_year=-2147483578, 865 .tm_year=-2147483578,
@@ -872,7 +872,7 @@ struct timetest timetests[] = {
872 .tm_yday=30, 872 .tm_yday=30,
873 .tm_isdst=0, 873 .tm_isdst=0,
874 .tm_gmtoff=0, 874 .tm_gmtoff=0,
875 .tm_zone="UTC" 875 .tm_zone="GMT"
876 }, 876 },
877 .gmt_tm= { 877 .gmt_tm= {
878 .tm_year=-2147483578, 878 .tm_year=-2147483578,
@@ -885,7 +885,7 @@ struct timetest timetests[] = {
885 .tm_yday=30, 885 .tm_yday=30,
886 .tm_isdst=0, 886 .tm_isdst=0,
887 .tm_gmtoff=0, 887 .tm_gmtoff=0,
888 .tm_zone="GMT" 888 .tm_zone="UTC"
889 }, 889 },
890 }, 890 },
891 { 891 {
@@ -916,12 +916,12 @@ struct timetest timetests[] = {
916 .tm_yday=0, 916 .tm_yday=0,
917 .tm_isdst=0, 917 .tm_isdst=0,
918 .tm_gmtoff=0, 918 .tm_gmtoff=0,
919 .tm_zone="GMT" 919 .tm_zone="UTC"
920 }, 920 },
921 }, 921 },
922 { 922 {
923 .descr="0000", 923 .descr="0000",
924 .timezone="right/UTC", 924 .timezone="right/GMT",
925 .time=-62167219200, 925 .time=-62167219200,
926 .local_tm= { 926 .local_tm= {
927 .tm_year=-1900, 927 .tm_year=-1900,
@@ -934,7 +934,7 @@ struct timetest timetests[] = {
934 .tm_yday=0, 934 .tm_yday=0,
935 .tm_isdst=0, 935 .tm_isdst=0,
936 .tm_gmtoff=0, 936 .tm_gmtoff=0,
937 .tm_zone="UTC" 937 .tm_zone="GMT"
938 }, 938 },
939 .gmt_tm= { 939 .gmt_tm= {
940 .tm_year=-1900, 940 .tm_year=-1900,
@@ -947,7 +947,7 @@ struct timetest timetests[] = {
947 .tm_yday=0, 947 .tm_yday=0,
948 .tm_isdst=0, 948 .tm_isdst=0,
949 .tm_gmtoff=0, 949 .tm_gmtoff=0,
950 .tm_zone="GMT" 950 .tm_zone="UTC"
951 }, 951 },
952 }, 952 },
953 { 953 {
@@ -978,7 +978,7 @@ struct timetest timetests[] = {
978 .tm_yday=0, 978 .tm_yday=0,
979 .tm_isdst=0, 979 .tm_isdst=0,
980 .tm_gmtoff=0, 980 .tm_gmtoff=0,
981 .tm_zone="GMT" 981 .tm_zone="UTC"
982 }, 982 },
983 }, 983 },
984 { 984 {
@@ -1009,12 +1009,12 @@ struct timetest timetests[] = {
1009 .tm_yday=364, 1009 .tm_yday=364,
1010 .tm_isdst=0, 1010 .tm_isdst=0,
1011 .tm_gmtoff=0, 1011 .tm_gmtoff=0,
1012 .tm_zone="GMT" 1012 .tm_zone="UTC"
1013 }, 1013 },
1014 }, 1014 },
1015 { 1015 {
1016 .descr="9999", 1016 .descr="9999",
1017 .timezone="right/UTC", 1017 .timezone="right/GMT",
1018 .time=253402300799, 1018 .time=253402300799,
1019 .local_tm= { 1019 .local_tm= {
1020 .tm_year=8099, 1020 .tm_year=8099,
@@ -1027,7 +1027,7 @@ struct timetest timetests[] = {
1027 .tm_yday=364, 1027 .tm_yday=364,
1028 .tm_isdst=0, 1028 .tm_isdst=0,
1029 .tm_gmtoff=0, 1029 .tm_gmtoff=0,
1030 .tm_zone="UTC" 1030 .tm_zone="GMT"
1031 }, 1031 },
1032 .gmt_tm= { 1032 .gmt_tm= {
1033 .tm_year=8099, 1033 .tm_year=8099,
@@ -1040,7 +1040,7 @@ struct timetest timetests[] = {
1040 .tm_yday=364, 1040 .tm_yday=364,
1041 .tm_isdst=0, 1041 .tm_isdst=0,
1042 .tm_gmtoff=0, 1042 .tm_gmtoff=0,
1043 .tm_zone="GMT" 1043 .tm_zone="UTC"
1044 }, 1044 },
1045 }, 1045 },
1046 { 1046 {
@@ -1071,7 +1071,7 @@ struct timetest timetests[] = {
1071 .tm_yday=364, 1071 .tm_yday=364,
1072 .tm_isdst=0, 1072 .tm_isdst=0,
1073 .tm_gmtoff=0, 1073 .tm_gmtoff=0,
1074 .tm_zone="GMT" 1074 .tm_zone="UTC"
1075 }, 1075 },
1076 }, 1076 },
1077 { 1077 {
@@ -1102,7 +1102,7 @@ struct timetest timetests[] = {
1102 .tm_yday=0, 1102 .tm_yday=0,
1103 .tm_isdst=0, 1103 .tm_isdst=0,
1104 .tm_gmtoff=0, 1104 .tm_gmtoff=0,
1105 .tm_zone="GMT" 1105 .tm_zone="UTC"
1106 }, 1106 },
1107 }, 1107 },
1108 { 1108 {
@@ -1133,7 +1133,7 @@ struct timetest timetests[] = {
1133 .tm_yday=0, 1133 .tm_yday=0,
1134 .tm_isdst=0, 1134 .tm_isdst=0,
1135 .tm_gmtoff=0, 1135 .tm_gmtoff=0,
1136 .tm_zone="GMT" 1136 .tm_zone="UTC"
1137 }, 1137 },
1138 }, 1138 },
1139 { 1139 {
@@ -1164,12 +1164,12 @@ struct timetest timetests[] = {
1164 .tm_yday=0, 1164 .tm_yday=0,
1165 .tm_isdst=0, 1165 .tm_isdst=0,
1166 .tm_gmtoff=0, 1166 .tm_gmtoff=0,
1167 .tm_zone="GMT" 1167 .tm_zone="UTC"
1168 }, 1168 },
1169 }, 1169 },
1170 { 1170 {
1171 .descr="leap second - 1", 1171 .descr="leap second - 1",
1172 .timezone="right/UTC", 1172 .timezone="right/GMT",
1173 .time=1483228825, 1173 .time=1483228825,
1174 .local_tm= { 1174 .local_tm= {
1175 .tm_year=116, 1175 .tm_year=116,
@@ -1182,7 +1182,7 @@ struct timetest timetests[] = {
1182 .tm_yday=365, 1182 .tm_yday=365,
1183 .tm_isdst=0, 1183 .tm_isdst=0,
1184 .tm_gmtoff=0, 1184 .tm_gmtoff=0,
1185 .tm_zone="UTC" 1185 .tm_zone="GMT"
1186 }, 1186 },
1187 .gmt_tm= { 1187 .gmt_tm= {
1188 .tm_year=117, 1188 .tm_year=117,
@@ -1195,12 +1195,12 @@ struct timetest timetests[] = {
1195 .tm_yday=0, 1195 .tm_yday=0,
1196 .tm_isdst=0, 1196 .tm_isdst=0,
1197 .tm_gmtoff=0, 1197 .tm_gmtoff=0,
1198 .tm_zone="GMT" 1198 .tm_zone="UTC"
1199 }, 1199 },
1200 }, 1200 },
1201 { 1201 {
1202 .descr="leap second", 1202 .descr="leap second",
1203 .timezone="right/UTC", 1203 .timezone="right/GMT",
1204 .time=1483228826, 1204 .time=1483228826,
1205 .local_tm= { 1205 .local_tm= {
1206 .tm_year=116, 1206 .tm_year=116,
@@ -1213,7 +1213,7 @@ struct timetest timetests[] = {
1213 .tm_yday=365, 1213 .tm_yday=365,
1214 .tm_isdst=0, 1214 .tm_isdst=0,
1215 .tm_gmtoff=0, 1215 .tm_gmtoff=0,
1216 .tm_zone="UTC" 1216 .tm_zone="GMT"
1217 }, 1217 },
1218 .gmt_tm= { 1218 .gmt_tm= {
1219 .tm_year=117, 1219 .tm_year=117,
@@ -1226,12 +1226,12 @@ struct timetest timetests[] = {
1226 .tm_yday=0, 1226 .tm_yday=0,
1227 .tm_isdst=0, 1227 .tm_isdst=0,
1228 .tm_gmtoff=0, 1228 .tm_gmtoff=0,
1229 .tm_zone="GMT" 1229 .tm_zone="UTC"
1230 }, 1230 },
1231 }, 1231 },
1232 { 1232 {
1233 .descr="leap second + 1", 1233 .descr="leap second + 1",
1234 .timezone="right/UTC", 1234 .timezone="right/GMT",
1235 .time=1483228827, 1235 .time=1483228827,
1236 .local_tm= { 1236 .local_tm= {
1237 .tm_year=117, 1237 .tm_year=117,
@@ -1244,7 +1244,7 @@ struct timetest timetests[] = {
1244 .tm_yday=0, 1244 .tm_yday=0,
1245 .tm_isdst=0, 1245 .tm_isdst=0,
1246 .tm_gmtoff=0, 1246 .tm_gmtoff=0,
1247 .tm_zone="UTC" 1247 .tm_zone="GMT"
1248 }, 1248 },
1249 .gmt_tm= { 1249 .gmt_tm= {
1250 .tm_year=117, 1250 .tm_year=117,
@@ -1257,7 +1257,7 @@ struct timetest timetests[] = {
1257 .tm_yday=0, 1257 .tm_yday=0,
1258 .tm_isdst=0, 1258 .tm_isdst=0,
1259 .tm_gmtoff=0, 1259 .tm_gmtoff=0,
1260 .tm_zone="GMT" 1260 .tm_zone="UTC"
1261 }, 1261 },
1262 }, 1262 },
1263 { 1263 {
@@ -1288,7 +1288,7 @@ struct timetest timetests[] = {
1288 .tm_yday=0, 1288 .tm_yday=0,
1289 .tm_isdst=0, 1289 .tm_isdst=0,
1290 .tm_gmtoff=0, 1290 .tm_gmtoff=0,
1291 .tm_zone="GMT" 1291 .tm_zone="UTC"
1292 }, 1292 },
1293 }, 1293 },
1294 { 1294 {
@@ -1319,7 +1319,7 @@ struct timetest timetests[] = {
1319 .tm_yday=0, 1319 .tm_yday=0,
1320 .tm_isdst=0, 1320 .tm_isdst=0,
1321 .tm_gmtoff=0, 1321 .tm_gmtoff=0,
1322 .tm_zone="GMT" 1322 .tm_zone="UTC"
1323 }, 1323 },
1324 }, 1324 },
1325 { 1325 {
@@ -1350,7 +1350,7 @@ struct timetest timetests[] = {
1350 .tm_yday=0, 1350 .tm_yday=0,
1351 .tm_isdst=0, 1351 .tm_isdst=0,
1352 .tm_gmtoff=0, 1352 .tm_gmtoff=0,
1353 .tm_zone="GMT" 1353 .tm_zone="UTC"
1354 }, 1354 },
1355 }, 1355 },
1356 { 1356 {
@@ -1381,7 +1381,7 @@ struct timetest timetests[] = {
1381 .tm_yday=72, 1381 .tm_yday=72,
1382 .tm_isdst=0, 1382 .tm_isdst=0,
1383 .tm_gmtoff=0, 1383 .tm_gmtoff=0,
1384 .tm_zone="GMT" 1384 .tm_zone="UTC"
1385 }, 1385 },
1386 }, 1386 },
1387 { 1387 {
@@ -1412,7 +1412,7 @@ struct timetest timetests[] = {
1412 .tm_yday=72, 1412 .tm_yday=72,
1413 .tm_isdst=0, 1413 .tm_isdst=0,
1414 .tm_gmtoff=0, 1414 .tm_gmtoff=0,
1415 .tm_zone="GMT" 1415 .tm_zone="UTC"
1416 }, 1416 },
1417 }, 1417 },
1418 { 1418 {
@@ -1443,7 +1443,7 @@ struct timetest timetests[] = {
1443 .tm_yday=72, 1443 .tm_yday=72,
1444 .tm_isdst=0, 1444 .tm_isdst=0,
1445 .tm_gmtoff=0, 1445 .tm_gmtoff=0,
1446 .tm_zone="GMT" 1446 .tm_zone="UTC"
1447 }, 1447 },
1448 }, 1448 },
1449 { 1449 {
@@ -1474,7 +1474,7 @@ struct timetest timetests[] = {
1474 .tm_yday=72, 1474 .tm_yday=72,
1475 .tm_isdst=0, 1475 .tm_isdst=0,
1476 .tm_gmtoff=0, 1476 .tm_gmtoff=0,
1477 .tm_zone="GMT" 1477 .tm_zone="UTC"
1478 }, 1478 },
1479 }, 1479 },
1480 { 1480 {
@@ -1505,7 +1505,7 @@ struct timetest timetests[] = {
1505 .tm_yday=72, 1505 .tm_yday=72,
1506 .tm_isdst=0, 1506 .tm_isdst=0,
1507 .tm_gmtoff=0, 1507 .tm_gmtoff=0,
1508 .tm_zone="GMT" 1508 .tm_zone="UTC"
1509 }, 1509 },
1510 }, 1510 },
1511 { 1511 {
@@ -1536,7 +1536,7 @@ struct timetest timetests[] = {
1536 .tm_yday=72, 1536 .tm_yday=72,
1537 .tm_isdst=0, 1537 .tm_isdst=0,
1538 .tm_gmtoff=0, 1538 .tm_gmtoff=0,
1539 .tm_zone="GMT" 1539 .tm_zone="UTC"
1540 }, 1540 },
1541 }, 1541 },
1542 { 1542 {
@@ -1567,7 +1567,7 @@ struct timetest timetests[] = {
1567 .tm_yday=310, 1567 .tm_yday=310,
1568 .tm_isdst=0, 1568 .tm_isdst=0,
1569 .tm_gmtoff=0, 1569 .tm_gmtoff=0,
1570 .tm_zone="GMT" 1570 .tm_zone="UTC"
1571 }, 1571 },
1572 }, 1572 },
1573 { 1573 {
@@ -1598,7 +1598,7 @@ struct timetest timetests[] = {
1598 .tm_yday=310, 1598 .tm_yday=310,
1599 .tm_isdst=0, 1599 .tm_isdst=0,
1600 .tm_gmtoff=0, 1600 .tm_gmtoff=0,
1601 .tm_zone="GMT" 1601 .tm_zone="UTC"
1602 }, 1602 },
1603 }, 1603 },
1604 { 1604 {
@@ -1629,7 +1629,7 @@ struct timetest timetests[] = {
1629 .tm_yday=310, 1629 .tm_yday=310,
1630 .tm_isdst=0, 1630 .tm_isdst=0,
1631 .tm_gmtoff=0, 1631 .tm_gmtoff=0,
1632 .tm_zone="GMT" 1632 .tm_zone="UTC"
1633 }, 1633 },
1634 }, 1634 },
1635 { 1635 {
@@ -1660,7 +1660,7 @@ struct timetest timetests[] = {
1660 .tm_yday=310, 1660 .tm_yday=310,
1661 .tm_isdst=0, 1661 .tm_isdst=0,
1662 .tm_gmtoff=0, 1662 .tm_gmtoff=0,
1663 .tm_zone="GMT" 1663 .tm_zone="UTC"
1664 }, 1664 },
1665 }, 1665 },
1666 { 1666 {
@@ -1691,7 +1691,7 @@ struct timetest timetests[] = {
1691 .tm_yday=310, 1691 .tm_yday=310,
1692 .tm_isdst=0, 1692 .tm_isdst=0,
1693 .tm_gmtoff=0, 1693 .tm_gmtoff=0,
1694 .tm_zone="GMT" 1694 .tm_zone="UTC"
1695 }, 1695 },
1696 }, 1696 },
1697 { 1697 {
@@ -1722,7 +1722,7 @@ struct timetest timetests[] = {
1722 .tm_yday=310, 1722 .tm_yday=310,
1723 .tm_isdst=0, 1723 .tm_isdst=0,
1724 .tm_gmtoff=0, 1724 .tm_gmtoff=0,
1725 .tm_zone="GMT" 1725 .tm_zone="UTC"
1726 }, 1726 },
1727 }, 1727 },
1728 { 1728 {
diff --git a/src/regress/lib/libcrypto/bn/bn_mul_div.c b/src/regress/lib/libcrypto/bn/bn_mul_div.c
index 625d5e318e..dbad01004e 100644
--- a/src/regress/lib/libcrypto/bn/bn_mul_div.c
+++ b/src/regress/lib/libcrypto/bn/bn_mul_div.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_mul_div.c,v 1.7 2023/06/21 07:18:10 jsing Exp $ */ 1/* $OpenBSD: bn_mul_div.c,v 1.8 2025/08/12 10:29:35 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2023 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -233,6 +233,13 @@ struct benchmark benchmarks[] = {
233 .b_bits = 256, 233 .b_bits = 256,
234 }, 234 },
235 { 235 {
236 .desc = "BN_mul (384 bit x 384 bit)",
237 .setup = benchmark_bn_mul_setup,
238 .run_once = benchmark_bn_mul_run_once,
239 .a_bits = 384,
240 .b_bits = 384,
241 },
242 {
236 .desc = "BN_mul (512 bit x 512 bit)", 243 .desc = "BN_mul (512 bit x 512 bit)",
237 .setup = benchmark_bn_mul_setup, 244 .setup = benchmark_bn_mul_setup,
238 .run_once = benchmark_bn_mul_run_once, 245 .run_once = benchmark_bn_mul_run_once,
@@ -294,6 +301,12 @@ struct benchmark benchmarks[] = {
294 .a_bits = 256, 301 .a_bits = 256,
295 }, 302 },
296 { 303 {
304 .desc = "BN_sqr (384 bit)",
305 .setup = benchmark_bn_sqr_setup,
306 .run_once = benchmark_bn_sqr_run_once,
307 .a_bits = 384,
308 },
309 {
297 .desc = "BN_sqr (512 bit)", 310 .desc = "BN_sqr (512 bit)",
298 .setup = benchmark_bn_sqr_setup, 311 .setup = benchmark_bn_sqr_setup,
299 .run_once = benchmark_bn_sqr_run_once, 312 .run_once = benchmark_bn_sqr_run_once,
diff --git a/src/regress/lib/libcrypto/ec/Makefile b/src/regress/lib/libcrypto/ec/Makefile
index 3595a88608..1d976c77d0 100644
--- a/src/regress/lib/libcrypto/ec/Makefile
+++ b/src/regress/lib/libcrypto/ec/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.12 2025/07/23 07:43:14 tb Exp $ 1# $OpenBSD: Makefile,v 1.13 2025/08/03 08:29:39 jsing Exp $
2 2
3.ifdef EOPENSSL35 3.ifdef EOPENSSL35
4LDADD += -Wl,-rpath,/usr/local/lib/eopenssl35 -L/usr/local/lib/eopenssl35 4LDADD += -Wl,-rpath,/usr/local/lib/eopenssl35 -L/usr/local/lib/eopenssl35
@@ -7,6 +7,7 @@ CFLAGS += -DOPENSSL_SUPPRESS_DEPRECATED
7.endif 7.endif
8 8
9PROGS += ectest 9PROGS += ectest
10PROGS += ec_arithmetic
10PROGS += ec_asn1_test 11PROGS += ec_asn1_test
11PROGS += ec_point_conversion 12PROGS += ec_point_conversion
12 13
diff --git a/src/regress/lib/libcrypto/ec/ec_arithmetic.c b/src/regress/lib/libcrypto/ec/ec_arithmetic.c
new file mode 100644
index 0000000000..c6f7cd4f8c
--- /dev/null
+++ b/src/regress/lib/libcrypto/ec/ec_arithmetic.c
@@ -0,0 +1,210 @@
1/* $OpenBSD: ec_arithmetic.c,v 1.1 2025/08/03 08:29:39 jsing Exp $ */
2/*
3 * Copyright (c) 2022,2025 Joel Sing <jsing@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <sys/time.h>
19
20#include <err.h>
21#include <signal.h>
22#include <stdio.h>
23#include <string.h>
24#include <time.h>
25#include <unistd.h>
26
27#include <openssl/bn.h>
28#include <openssl/ec.h>
29#include <openssl/objects.h>
30
31static void
32benchmark_ec_point_add(const EC_GROUP *group, EC_POINT *result,
33 const BIGNUM *scalar, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
34{
35 if (!EC_POINT_add(group, result, a, b, ctx))
36 errx(1, "EC_POINT_add");
37}
38
39static void
40benchmark_ec_point_dbl(const EC_GROUP *group, EC_POINT *result,
41 const BIGNUM *scalar, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
42{
43 if (!EC_POINT_dbl(group, result, a, ctx))
44 errx(1, "EC_POINT_dbl");
45}
46
47static void
48benchmark_ec_point_mul_generator(const EC_GROUP *group, EC_POINT *result,
49 const BIGNUM *scalar, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
50{
51 if (!EC_POINT_mul(group, result, scalar, NULL, NULL, ctx))
52 errx(1, "EC_POINT_mul");
53}
54
55struct benchmark {
56 int curve;
57 const char *desc;
58 void (*func)(const EC_GROUP *, EC_POINT *, const BIGNUM *,
59 const EC_POINT *, const EC_POINT *, BN_CTX *);
60};
61
62static const struct benchmark benchmarks[] = {
63 {
64 .curve = NID_X9_62_prime256v1,
65 .desc = "EC_POINT_add() p256",
66 .func = benchmark_ec_point_add,
67 },
68 {
69 .curve = NID_secp384r1,
70 .desc = "EC_POINT_add() p384",
71 .func = benchmark_ec_point_add,
72 },
73 {
74 .curve = NID_secp521r1,
75 .desc = "EC_POINT_add() p521",
76 .func = benchmark_ec_point_add,
77 },
78 {
79 .curve = NID_X9_62_prime256v1,
80 .desc = "EC_POINT_dbl() p256",
81 .func = benchmark_ec_point_dbl,
82 },
83 {
84 .curve = NID_secp384r1,
85 .desc = "EC_POINT_dbl() p384",
86 .func = benchmark_ec_point_dbl,
87 },
88 {
89 .curve = NID_secp521r1,
90 .desc = "EC_POINT_dbl() p521",
91 .func = benchmark_ec_point_dbl,
92 },
93 {
94 .curve = NID_X9_62_prime256v1,
95 .desc = "EC_POINT_mul() generator p256",
96 .func = benchmark_ec_point_mul_generator,
97 },
98 {
99 .curve = NID_secp384r1,
100 .desc = "EC_POINT_mul() generator p384",
101 .func = benchmark_ec_point_mul_generator,
102 },
103 {
104 .curve = NID_secp521r1,
105 .desc = "EC_POINT_mul() generator p521",
106 .func = benchmark_ec_point_mul_generator,
107 },
108};
109
110#define N_BENCHMARKS (sizeof(benchmarks) / sizeof(benchmarks[0]))
111
112static volatile sig_atomic_t benchmark_stop;
113
114static void
115benchmark_sig_alarm(int sig)
116{
117 benchmark_stop = 1;
118}
119
120static void
121benchmark_run(const struct benchmark *bm, int seconds)
122{
123 struct timespec start, end, duration;
124 EC_GROUP *group = NULL;
125 EC_POINT *a = NULL, *b = NULL, *result = NULL;
126 BIGNUM *order = NULL, *scalar = NULL;
127 BN_CTX *ctx = NULL;
128 int i;
129
130 signal(SIGALRM, benchmark_sig_alarm);
131
132 if ((ctx = BN_CTX_new()) == NULL)
133 errx(1, "BN_CTX_new");
134
135 if ((group = EC_GROUP_new_by_curve_name(bm->curve)) == NULL)
136 errx(1, "EC_GROUP_new_by_curve_name");
137 if ((order = BN_new()) == NULL)
138 errx(1, "BN_new");
139 if (!EC_GROUP_get_order(group, order, ctx))
140 errx(1, "EC_GROUP_get_order");
141
142 if ((scalar = BN_new()) == NULL)
143 errx(1, "BN_new");
144 if (!BN_rand_range(scalar, order))
145 errx(1, "BN_rand_range");
146 if (!BN_set_bit(scalar, EC_GROUP_order_bits(group) - 1))
147 errx(1, "BN_set_bit");
148
149 if ((result = EC_POINT_new(group)) == NULL)
150 errx(1, "EC_POINT_new");
151 if ((a = EC_POINT_new(group)) == NULL)
152 errx(1, "EC_POINT_new");
153 if ((b = EC_POINT_new(group)) == NULL)
154 errx(1, "EC_POINT_new");
155
156 if (!EC_POINT_mul(group, a, scalar, NULL, NULL, ctx))
157 errx(1, "EC_POINT_mul");
158 if (!EC_POINT_mul(group, b, scalar, NULL, NULL, ctx))
159 errx(1, "EC_POINT_mul");
160
161 benchmark_stop = 0;
162 i = 0;
163 alarm(seconds);
164
165 clock_gettime(CLOCK_MONOTONIC, &start);
166
167 fprintf(stderr, "Benchmarking %s for %ds: ", bm->desc, seconds);
168 while (!benchmark_stop) {
169 bm->func(group, result, scalar, a, b, ctx);
170 i++;
171 }
172 clock_gettime(CLOCK_MONOTONIC, &end);
173 timespecsub(&end, &start, &duration);
174 fprintf(stderr, "%d iterations in %f seconds\n", i,
175 duration.tv_sec + duration.tv_nsec / 1000000000.0);
176
177 EC_GROUP_free(group);
178 EC_POINT_free(result);
179 EC_POINT_free(a);
180 EC_POINT_free(b);
181 BN_free(order);
182 BN_free(scalar);
183 BN_CTX_free(ctx);
184}
185
186static void
187benchmark_ec_mul_single(void)
188{
189 const struct benchmark *bm;
190 size_t i;
191
192 for (i = 0; i < N_BENCHMARKS; i++) {
193 bm = &benchmarks[i];
194 benchmark_run(bm, 5);
195 }
196}
197
198int
199main(int argc, char **argv)
200{
201 int benchmark = 0, failed = 0;
202
203 if (argc == 2 && strcmp(argv[1], "--benchmark") == 0)
204 benchmark = 1;
205
206 if (benchmark && !failed)
207 benchmark_ec_mul_single();
208
209 return failed;
210}
diff --git a/src/regress/lib/libcrypto/mlkem/Makefile b/src/regress/lib/libcrypto/mlkem/Makefile
index a08623c90a..3acaf78e63 100644
--- a/src/regress/lib/libcrypto/mlkem/Makefile
+++ b/src/regress/lib/libcrypto/mlkem/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.9 2024/12/29 20:14:15 tb Exp $ 1# $OpenBSD: Makefile,v 1.10 2025/08/15 14:46:37 tb Exp $
2 2
3REGRESS_SLOW_TARGETS += run-regress-mlkem_iteration_tests 3REGRESS_SLOW_TARGETS += run-regress-mlkem_iteration_tests
4 4
@@ -22,7 +22,7 @@ run-regress-mlkem_tests: mlkem_tests
22 ./mlkem_tests $f ${.CURDIR}/$f.txt 22 ./mlkem_tests $f ${.CURDIR}/$f.txt
23.endfor 23.endfor
24 24
25SRCS_mlkem_tests = mlkem_tests.c mlkem_tests_util.c parse_test_file.c 25SRCS_mlkem_tests = mlkem_tests.c parse_test_file.c
26SRCS_mlkem_iteration_tests = mlkem_iteration_tests.c mlkem_tests_util.c 26SRCS_mlkem_iteration_tests = mlkem_iteration_tests.c mlkem_tests_util.c
27SRCS_mlkem_unittest = mlkem_unittest.c mlkem_tests_util.c 27SRCS_mlkem_unittest = mlkem_unittest.c mlkem_tests_util.c
28 28
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_iteration_tests.c b/src/regress/lib/libcrypto/mlkem/mlkem_iteration_tests.c
index b93243023c..053f8e1222 100644
--- a/src/regress/lib/libcrypto/mlkem/mlkem_iteration_tests.c
+++ b/src/regress/lib/libcrypto/mlkem/mlkem_iteration_tests.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mlkem_iteration_tests.c,v 1.5 2025/05/20 00:33:41 beck Exp $ */ 1/* $OpenBSD: mlkem_iteration_tests.c,v 1.8 2025/08/17 19:26:35 tb 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>
@@ -22,7 +22,7 @@
22#include <stdio.h> 22#include <stdio.h>
23#include <stdlib.h> 23#include <stdlib.h>
24 24
25#include "mlkem.h" 25#include <openssl/mlkem.h>
26 26
27#include "mlkem_internal.h" 27#include "mlkem_internal.h"
28#include "mlkem_tests_util.h" 28#include "mlkem_tests_util.h"
@@ -63,46 +63,49 @@ const uint8_t kExpectedAdam1024[32] = {
63 0x04, 0xab, 0xdb, 0x94, 0x8b, 0x90, 0x8b, 0x75, 0xba, 0xd5 63 0x04, 0xab, 0xdb, 0x94, 0x8b, 0x90, 0x8b, 0x75, 0xba, 0xd5
64}; 64};
65 65
66struct iteration_ctx {
67 uint8_t *encoded_public_key;
68 size_t encoded_public_key_len;
69 uint8_t *ciphertext;
70 size_t ciphertext_len;
71 uint8_t *invalid_ciphertext;
72 size_t invalid_ciphertext_len;
73 void *priv;
74 void *pub;
75
76 mlkem_marshal_private_key_fn marshal_private_key;
77 mlkem_encap_external_entropy_fn encap_external_entropy;
78 mlkem_generate_key_external_entropy_fn generate_key_external_entropy;
79 mlkem_public_from_private_fn public_from_private;
80 mlkem_decap_fn decap;
81
82 const uint8_t *start;
83 size_t start_len;
84
85 const uint8_t *expected;
86 size_t expected_len;
87};
88
89static int 66static int
90MlkemIterativeTest(struct iteration_ctx *ctx) 67MlkemIterativeTest(int rank)
91{ 68{
92 uint8_t shared_secret[MLKEM_SHARED_SECRET_BYTES]; 69 const uint8_t *start, *expected;
70 size_t start_len;
93 uint8_t encap_entropy[MLKEM_ENCAP_ENTROPY]; 71 uint8_t encap_entropy[MLKEM_ENCAP_ENTROPY];
94 uint8_t seed[MLKEM_SEED_BYTES] = {0}; 72 uint8_t seed[MLKEM_SEED_LENGTH] = {0};
73 uint8_t *shared_secret = NULL;
95 sha3_ctx drng, results; 74 sha3_ctx drng, results;
96 uint8_t out[32]; 75 uint8_t out[32];
97 int i; 76 int i;
98 77
78 start = kExpectedSeedStart;
79 start_len = sizeof(kExpectedSeedStart);
80 switch(rank){
81 case RANK768:
82 expected = kExpectedAdam768;
83 break;
84 case RANK1024:
85 expected = kExpectedAdam1024;
86 break;
87 default:
88 errx(1, "invalid rank %d", rank);
89 }
90
99 shake128_init(&drng); 91 shake128_init(&drng);
100 shake128_init(&results); 92 shake128_init(&results);
101 93
102 shake_xof(&drng); 94 shake_xof(&drng);
103 for (i = 0; i < 10000; i++) { 95 for (i = 0; i < 10000; i++) {
104 uint8_t *encoded_private_key = NULL; 96 uint8_t *encoded_public_key = NULL, *ciphertext = NULL,
105 size_t encoded_private_key_len; 97 *encoded_private_key = NULL, *invalid_ciphertext = NULL;
98 size_t encoded_public_key_len, ciphertext_len,
99 encoded_private_key_len, invalid_ciphertext_len;
100 MLKEM_private_key *priv;
101 MLKEM_public_key *pub;
102 size_t s_len = 0;
103
104 /* allocate keys for this iteration */
105 if ((priv = MLKEM_private_key_new(rank)) == NULL)
106 errx(1, "malloc");
107 if ((pub = MLKEM_public_key_new(rank)) == NULL)
108 errx(1, "malloc");
106 109
107 /* 110 /*
108 * This should draw both d and z from DRNG concatenating in 111 * This should draw both d and z from DRNG concatenating in
@@ -110,120 +113,91 @@ MlkemIterativeTest(struct iteration_ctx *ctx)
110 */ 113 */
111 shake_out(&drng, seed, sizeof(seed)); 114 shake_out(&drng, seed, sizeof(seed));
112 if (i == 0) { 115 if (i == 0) {
113 if (compare_data(seed, ctx->start, ctx->start_len, 116 if (compare_data(seed, start, start_len,
114 "seed start") != 0) 117 "seed start") != 0)
115 errx(1, "compare_data"); 118 errx(1, "compare_data");
116 } 119 }
117 120
118 /* generate ek as encoded_public_key */ 121 /* generate ek as encoded_public_key */
119 if (!ctx->generate_key_external_entropy(ctx->encoded_public_key, 122 if (!MLKEM_generate_key_external_entropy(priv,
120 ctx->priv, seed)) { 123 &encoded_public_key, &encoded_public_key_len,
124 seed))
121 errx(1, "generate_key_external_entropy"); 125 errx(1, "generate_key_external_entropy");
122 } 126
123 ctx->public_from_private(ctx->pub, ctx->priv); 127 if (!MLKEM_public_from_private(priv, pub))
128 errx(1, "public_from_private");
124 129
125 /* hash in ek */ 130 /* hash in ek */
126 shake_update(&results, ctx->encoded_public_key, 131 shake_update(&results, encoded_public_key,
127 ctx->encoded_public_key_len); 132 encoded_public_key_len);
128 133
129 /* marshal priv to dk as encoded_private_key */ 134 /* marshal priv to dk as encoded_private_key */
130 if (!ctx->marshal_private_key(ctx->priv, &encoded_private_key, 135 if (!MLKEM_marshal_private_key(priv, &encoded_private_key,
131 &encoded_private_key_len)) 136 &encoded_private_key_len))
132 errx(1, "encode private key"); 137 errx(1, "marshal private key");
133 138
134 /* hash in dk */ 139 /* hash in dk */
135 shake_update(&results, encoded_private_key, 140 shake_update(&results, encoded_private_key,
136 encoded_private_key_len); 141 encoded_private_key_len);
137 142
138 free(encoded_private_key); 143 freezero(encoded_private_key, encoded_private_key_len);
139 144
140 /* draw m as encap entropy from DRNG */ 145 /* draw m as encap entropy from DRNG */
141 shake_out(&drng, encap_entropy, sizeof(encap_entropy)); 146 shake_out(&drng, encap_entropy, sizeof(encap_entropy));
142 147
143 /* generate ct as ciphertext, k as shared_secret */ 148 /* generate ct as ciphertext, k as shared_secret */
144 ctx->encap_external_entropy(ctx->ciphertext, shared_secret, 149 if (!MLKEM_encap_external_entropy(pub, encap_entropy,
145 ctx->pub, encap_entropy); 150 &ciphertext, &ciphertext_len, &shared_secret, &s_len))
151 errx(1, "encap_external_entropy");
146 152
147 /* hash in ct */ 153 /* hash in ct */
148 shake_update(&results, ctx->ciphertext, ctx->ciphertext_len); 154 shake_update(&results, ciphertext, ciphertext_len);
149 /* hash in k */ 155 /* hash in k */
150 shake_update(&results, shared_secret, sizeof(shared_secret)); 156 shake_update(&results, shared_secret, s_len);
157
158 freezero(shared_secret, s_len);
159 shared_secret = NULL;
160
161 invalid_ciphertext_len = ciphertext_len;
162 if ((invalid_ciphertext = calloc(1, invalid_ciphertext_len))
163 == NULL)
164 errx(1, "malloc");
151 165
152 /* draw ct as invalid_ciphertxt from DRNG */ 166 /* draw ct as invalid_ciphertxt from DRNG */
153 shake_out(&drng, ctx->invalid_ciphertext, 167 shake_out(&drng, invalid_ciphertext, invalid_ciphertext_len);
154 ctx->invalid_ciphertext_len);
155 168
156 /* generate k as shared secret from invalid ciphertext */ 169 /* generate k as shared secret from invalid ciphertext */
157 if (!ctx->decap(shared_secret, ctx->invalid_ciphertext, 170 if (!MLKEM_decap(priv, invalid_ciphertext,
158 ctx->invalid_ciphertext_len, ctx->priv)) 171 invalid_ciphertext_len, &shared_secret, &s_len))
159 errx(1, "decap failed"); 172 errx(1, "decap failed, iteration %d", i);
160 173
161 /* hash in k */ 174 /* hash in k */
162 shake_update(&results, shared_secret, sizeof(shared_secret)); 175 shake_update(&results, shared_secret, s_len);
176
177 freezero(shared_secret, s_len);
178 shared_secret = NULL;
179 freezero(invalid_ciphertext, invalid_ciphertext_len);
180 invalid_ciphertext = NULL;
181
182 /* free keys and intermediate products for this iteration */
183 MLKEM_private_key_free(priv);
184 MLKEM_public_key_free(pub);
185 freezero(encoded_public_key, encoded_public_key_len);
186 freezero(ciphertext, ciphertext_len);
163 } 187 }
164 shake_xof(&results); 188 shake_xof(&results);
165 shake_out(&results, out, sizeof(out)); 189 shake_out(&results, out, sizeof(out));
166 190
167 return compare_data(ctx->expected, out, sizeof(out), "final result hash"); 191 return compare_data(expected, out, sizeof(out), "final result hash");
168} 192}
169 193
170int 194int
171main(void) 195main(void)
172{ 196{
173 uint8_t encoded_public_key768[MLKEM768_PUBLIC_KEY_BYTES];
174 uint8_t ciphertext768[MLKEM768_CIPHERTEXT_BYTES];
175 uint8_t invalid_ciphertext768[MLKEM768_CIPHERTEXT_BYTES];
176 struct MLKEM768_private_key priv768;
177 struct MLKEM768_public_key pub768;
178 struct iteration_ctx iteration768 = {
179 .encoded_public_key = encoded_public_key768,
180 .encoded_public_key_len = sizeof(encoded_public_key768),
181 .ciphertext = ciphertext768,
182 .ciphertext_len = sizeof(ciphertext768),
183 .invalid_ciphertext = invalid_ciphertext768,
184 .invalid_ciphertext_len = sizeof(invalid_ciphertext768),
185 .priv = &priv768,
186 .pub = &pub768,
187 .encap_external_entropy = mlkem768_encap_external_entropy,
188 .marshal_private_key = mlkem768_marshal_private_key,
189 .generate_key_external_entropy =
190 mlkem768_generate_key_external_entropy,
191 .public_from_private = mlkem768_public_from_private,
192 .decap = mlkem768_decap,
193 .start = kExpectedSeedStart,
194 .start_len = sizeof(kExpectedSeedStart),
195 .expected = kExpectedAdam768,
196 .expected_len = sizeof(kExpectedAdam768),
197 };
198 uint8_t encoded_public_key1024[MLKEM1024_PUBLIC_KEY_BYTES];
199 uint8_t ciphertext1024[MLKEM1024_CIPHERTEXT_BYTES];
200 uint8_t invalid_ciphertext1024[MLKEM1024_CIPHERTEXT_BYTES];
201 struct MLKEM1024_private_key priv1024;
202 struct MLKEM1024_public_key pub1024;
203 struct iteration_ctx iteration1024 = {
204 .encoded_public_key = encoded_public_key1024,
205 .encoded_public_key_len = sizeof(encoded_public_key1024),
206 .ciphertext = ciphertext1024,
207 .ciphertext_len = sizeof(ciphertext1024),
208 .invalid_ciphertext = invalid_ciphertext1024,
209 .invalid_ciphertext_len = sizeof(invalid_ciphertext1024),
210 .priv = &priv1024,
211 .pub = &pub1024,
212 .encap_external_entropy = mlkem1024_encap_external_entropy,
213 .marshal_private_key = mlkem1024_marshal_private_key,
214 .generate_key_external_entropy =
215 mlkem1024_generate_key_external_entropy,
216 .public_from_private = mlkem1024_public_from_private,
217 .decap = mlkem1024_decap,
218 .start = kExpectedSeedStart,
219 .start_len = sizeof(kExpectedSeedStart),
220 .expected = kExpectedAdam1024,
221 .expected_len = sizeof(kExpectedAdam1024),
222 };
223 int failed = 0; 197 int failed = 0;
224 198
225 failed |= MlkemIterativeTest(&iteration768); 199 failed |= MlkemIterativeTest(RANK768);
226 failed |= MlkemIterativeTest(&iteration1024); 200 failed |= MlkemIterativeTest(RANK1024);
227 201
228 return failed; 202 return failed;
229} 203}
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_tests.c b/src/regress/lib/libcrypto/mlkem/mlkem_tests.c
index 8e04dc6ad2..361467afd0 100644
--- a/src/regress/lib/libcrypto/mlkem/mlkem_tests.c
+++ b/src/regress/lib/libcrypto/mlkem/mlkem_tests.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mlkem_tests.c,v 1.6 2025/05/20 00:33:41 beck Exp $ */ 1/* $OpenBSD: mlkem_tests.c,v 1.10 2025/08/15 21:47:39 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2024 Google Inc. 3 * Copyright (c) 2024 Google Inc.
4 * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> 4 * Copyright (c) 2024 Theo Buehler <tb@openbsd.org>
@@ -23,12 +23,11 @@
23#include <stdlib.h> 23#include <stdlib.h>
24#include <string.h> 24#include <string.h>
25 25
26#include "bytestring.h" 26#include <openssl/mlkem.h>
27#include "mlkem.h"
28 27
28#include "bytestring.h"
29#include "mlkem_internal.h" 29#include "mlkem_internal.h"
30 30
31#include "mlkem_tests_util.h"
32#include "parse_test_file.h" 31#include "parse_test_file.h"
33 32
34enum test_type { 33enum test_type {
@@ -39,11 +38,7 @@ enum test_type {
39struct decap_ctx { 38struct decap_ctx {
40 struct parse *parse_ctx; 39 struct parse *parse_ctx;
41 40
42 void *private_key; 41 int rank;
43 size_t private_key_len;
44
45 mlkem_parse_private_key_fn parse_private_key;
46 mlkem_decap_fn decap;
47}; 42};
48 43
49enum decap_states { 44enum decap_states {
@@ -102,8 +97,10 @@ static int
102MlkemDecapFileTest(struct decap_ctx *decap) 97MlkemDecapFileTest(struct decap_ctx *decap)
103{ 98{
104 struct parse *p = decap->parse_ctx; 99 struct parse *p = decap->parse_ctx;
105 uint8_t shared_secret_buf[MLKEM_SHARED_SECRET_BYTES]; 100 MLKEM_private_key *priv_key = NULL;
106 CBS ciphertext, shared_secret, private_key; 101 CBS ciphertext, shared_secret, private_key;
102 uint8_t *shared_secret_buf = NULL;
103 size_t shared_secret_buf_len = 0;
107 int should_fail; 104 int should_fail;
108 int failed = 1; 105 int failed = 1;
109 106
@@ -112,21 +109,31 @@ MlkemDecapFileTest(struct decap_ctx *decap)
112 parse_get_cbs(p, DECAP_PRIVATE_KEY, &private_key); 109 parse_get_cbs(p, DECAP_PRIVATE_KEY, &private_key);
113 parse_get_int(p, DECAP_RESULT, &should_fail); 110 parse_get_int(p, DECAP_RESULT, &should_fail);
114 111
115 if (!decap->parse_private_key(decap->private_key, 112 if ((priv_key = MLKEM_private_key_new(decap->rank)) == NULL)
113 parse_errx(p, "MLKEM_private_key_new");
114
115 if (!MLKEM_parse_private_key(priv_key,
116 CBS_data(&private_key), CBS_len(&private_key))) { 116 CBS_data(&private_key), CBS_len(&private_key))) {
117 if ((failed = !should_fail)) 117 if ((failed = !should_fail))
118 parse_info(p, "parse private key"); 118 parse_info(p, "parse private key");
119 goto err; 119 goto err;
120 } 120 }
121 if (!decap->decap(shared_secret_buf, 121 if (!MLKEM_decap(priv_key, CBS_data(&ciphertext), CBS_len(&ciphertext),
122 CBS_data(&ciphertext), CBS_len(&ciphertext), decap->private_key)) { 122 &shared_secret_buf, &shared_secret_buf_len)) {
123 if ((failed = !should_fail)) 123 if ((failed = !should_fail))
124 parse_info(p, "decap"); 124 parse_info(p, "decap");
125 goto err; 125 goto err;
126 } 126 }
127 127
128 if (shared_secret_buf_len != MLKEM_SHARED_SECRET_LENGTH) {
129 if ((failed = !should_fail))
130 parse_info(p, "shared secret length %zu != %d",
131 shared_secret_buf_len, MLKEM_SHARED_SECRET_LENGTH);
132 goto err;
133 }
134
128 failed = !parse_data_equal(p, "shared_secret", &shared_secret, 135 failed = !parse_data_equal(p, "shared_secret", &shared_secret,
129 shared_secret_buf, sizeof(shared_secret_buf)); 136 shared_secret_buf, shared_secret_buf_len);
130 137
131 if (should_fail != failed) { 138 if (should_fail != failed) {
132 parse_info(p, "FAIL: should_fail %d, failed %d", 139 parse_info(p, "FAIL: should_fail %d, failed %d",
@@ -135,6 +142,9 @@ MlkemDecapFileTest(struct decap_ctx *decap)
135 } 142 }
136 143
137 err: 144 err:
145 MLKEM_private_key_free(priv_key);
146 freezero(shared_secret_buf, shared_secret_buf_len);
147
138 return failed; 148 return failed;
139} 149}
140 150
@@ -193,36 +203,49 @@ static int
193MlkemNistDecapFileTest(struct decap_ctx *decap) 203MlkemNistDecapFileTest(struct decap_ctx *decap)
194{ 204{
195 struct parse *p = decap->parse_ctx; 205 struct parse *p = decap->parse_ctx;
196 uint8_t shared_secret[MLKEM_SHARED_SECRET_BYTES]; 206 MLKEM_private_key *priv_key = NULL;
197 CBS dk, c, k; 207 CBS dk, c, k;
208 uint8_t *shared_secret = NULL;
209 size_t shared_secret_len = 0;
198 int failed = 1; 210 int failed = 1;
199 211
200 parse_instruction_get_cbs(p, NIST_DECAP_DK, &dk); 212 parse_instruction_get_cbs(p, NIST_DECAP_DK, &dk);
201 parse_get_cbs(p, NIST_DECAP_C, &c); 213 parse_get_cbs(p, NIST_DECAP_C, &c);
202 parse_get_cbs(p, NIST_DECAP_K, &k); 214 parse_get_cbs(p, NIST_DECAP_K, &k);
203 215
216 if ((priv_key = MLKEM_private_key_new(decap->rank)) == NULL)
217 parse_errx(p, "MLKEM_private_key_new");
218
204 if (!parse_length_equal(p, "private key", 219 if (!parse_length_equal(p, "private key",
205 decap->private_key_len, CBS_len(&dk))) 220 MLKEM_private_key_encoded_length(priv_key), CBS_len(&dk)))
206 goto err; 221 goto err;
207 if (!parse_length_equal(p, "shared secret", 222 if (!parse_length_equal(p, "shared secret",
208 MLKEM_SHARED_SECRET_BYTES, CBS_len(&k))) 223 MLKEM_SHARED_SECRET_LENGTH, CBS_len(&k)))
209 goto err; 224 goto err;
210 225
211 if (!decap->parse_private_key(decap->private_key, CBS_data(&dk), 226 if (!MLKEM_parse_private_key(priv_key, CBS_data(&dk), CBS_len(&dk))) {
212 CBS_len(&dk))) {
213 parse_info(p, "parse private key"); 227 parse_info(p, "parse private key");
214 goto err; 228 goto err;
215 } 229 }
216 if (!decap->decap(shared_secret, CBS_data(&c), CBS_len(&c), 230 if (!MLKEM_decap(priv_key, CBS_data(&c), CBS_len(&c),
217 decap->private_key)) { 231 &shared_secret, &shared_secret_len)) {
218 parse_info(p, "decap"); 232 parse_info(p, "decap");
219 goto err; 233 goto err;
220 } 234 }
221 235
236 if (shared_secret_len != MLKEM_SHARED_SECRET_LENGTH) {
237 parse_info(p, "shared secret length %zu != %d",
238 shared_secret_len, MLKEM_SHARED_SECRET_LENGTH);
239 goto err;
240 }
241
222 failed = !parse_data_equal(p, "shared secret", &k, 242 failed = !parse_data_equal(p, "shared secret", &k,
223 shared_secret, MLKEM_SHARED_SECRET_BYTES); 243 shared_secret, shared_secret_len);
224 244
225 err: 245 err:
246 MLKEM_private_key_free(priv_key);
247 freezero(shared_secret, shared_secret_len);
248
226 return failed; 249 return failed;
227} 250}
228 251
@@ -246,46 +269,24 @@ static const struct test_parse nist_decap_parse = {
246}; 269};
247 270
248static int 271static int
249mlkem_decap_tests(const char *fn, size_t size, enum test_type test_type) 272mlkem_decap_tests(const char *fn, int rank, enum test_type test_type)
250{ 273{
251 struct MLKEM768_private_key private_key768; 274 struct decap_ctx decap = {
252 struct decap_ctx decap768 = { 275 .rank = rank,
253 .private_key = &private_key768,
254 .private_key_len = MLKEM768_PRIVATE_KEY_BYTES,
255
256 .parse_private_key = mlkem768_parse_private_key,
257 .decap = mlkem768_decap,
258 }; 276 };
259 struct MLKEM1024_private_key private_key1024;
260 struct decap_ctx decap1024 = {
261 .private_key = &private_key1024,
262 .private_key_len = MLKEM1024_PRIVATE_KEY_BYTES,
263 277
264 .parse_private_key = mlkem1024_parse_private_key, 278 if (test_type == TEST_TYPE_NORMAL)
265 .decap = mlkem1024_decap, 279 return parse_test_file(fn, &decap_parse, &decap);
266 }; 280 if (test_type == TEST_TYPE_NIST)
267 281 return parse_test_file(fn, &nist_decap_parse, &decap);
268 if (size == 768 && test_type == TEST_TYPE_NORMAL)
269 return parse_test_file(fn, &decap_parse, &decap768);
270 if (size == 768 && test_type == TEST_TYPE_NIST)
271 return parse_test_file(fn, &nist_decap_parse, &decap768);
272 if (size == 1024 && test_type == TEST_TYPE_NORMAL)
273 return parse_test_file(fn, &decap_parse, &decap1024);
274 if (size == 1024 && test_type == TEST_TYPE_NIST)
275 return parse_test_file(fn, &nist_decap_parse, &decap1024);
276 282
277 errx(1, "unknown decap test: size %zu, type %d", size, test_type); 283 errx(1, "unknown decap test: rank %d, type %d", rank, test_type);
278} 284}
279 285
280struct encap_ctx { 286struct encap_ctx {
281 struct parse *parse_ctx; 287 struct parse *parse_ctx;
282 288
283 void *public_key; 289 int rank;
284 uint8_t *ciphertext;
285 size_t ciphertext_len;
286
287 mlkem_parse_public_key_fn parse_public_key;
288 mlkem_encap_external_entropy_fn encap_external_entropy;
289}; 290};
290 291
291enum encap_states { 292enum encap_states {
@@ -351,8 +352,12 @@ static int
351MlkemEncapFileTest(struct encap_ctx *encap) 352MlkemEncapFileTest(struct encap_ctx *encap)
352{ 353{
353 struct parse *p = encap->parse_ctx; 354 struct parse *p = encap->parse_ctx;
354 uint8_t shared_secret_buf[MLKEM_SHARED_SECRET_BYTES]; 355 MLKEM_public_key *pub_key = NULL;
355 CBS entropy, public_key, ciphertext, shared_secret; 356 CBS entropy, public_key, ciphertext, shared_secret;
357 uint8_t *ciphertext_buf = NULL;
358 size_t ciphertext_buf_len = 0;
359 uint8_t *shared_secret_buf = NULL;
360 size_t shared_secret_buf_len = 0;
356 int should_fail; 361 int should_fail;
357 int failed = 1; 362 int failed = 1;
358 363
@@ -362,19 +367,34 @@ MlkemEncapFileTest(struct encap_ctx *encap)
362 parse_get_cbs(p, ENCAP_SHARED_SECRET, &shared_secret); 367 parse_get_cbs(p, ENCAP_SHARED_SECRET, &shared_secret);
363 parse_get_int(p, ENCAP_RESULT, &should_fail); 368 parse_get_int(p, ENCAP_RESULT, &should_fail);
364 369
365 if (!encap->parse_public_key(encap->public_key, CBS_data(&public_key), 370 if ((pub_key = MLKEM_public_key_new(encap->rank)) == NULL)
366 CBS_len(&public_key))) { 371 parse_errx(p, "MLKEM_public_key_new");
372
373 if (!MLKEM_parse_public_key(pub_key,
374 CBS_data(&public_key), CBS_len(&public_key))) {
367 if ((failed = !should_fail)) 375 if ((failed = !should_fail))
368 parse_info(p, "parse public key"); 376 parse_info(p, "parse public key");
369 goto err; 377 goto err;
370 } 378 }
371 encap->encap_external_entropy(encap->ciphertext, shared_secret_buf, 379 if (!MLKEM_encap_external_entropy(pub_key, CBS_data(&entropy),
372 encap->public_key, CBS_data(&entropy)); 380 &ciphertext_buf, &ciphertext_buf_len,
381 &shared_secret_buf, &shared_secret_buf_len)) {
382 if ((failed = !should_fail))
383 parse_info(p, "encap_external_entropy");
384 goto err;
385 }
386
387 if (shared_secret_buf_len != MLKEM_SHARED_SECRET_LENGTH) {
388 if ((failed = !should_fail))
389 parse_info(p, "shared secret length %zu != %d",
390 shared_secret_buf_len, MLKEM_SHARED_SECRET_LENGTH);
391 goto err;
392 }
373 393
374 failed = !parse_data_equal(p, "shared_secret", &shared_secret, 394 failed = !parse_data_equal(p, "shared_secret", &shared_secret,
375 shared_secret_buf, sizeof(shared_secret_buf)); 395 shared_secret_buf, shared_secret_buf_len);
376 failed |= !parse_data_equal(p, "ciphertext", &ciphertext, 396 failed |= !parse_data_equal(p, "ciphertext", &ciphertext,
377 encap->ciphertext, encap->ciphertext_len); 397 ciphertext_buf, ciphertext_buf_len);
378 398
379 if (should_fail != failed) { 399 if (should_fail != failed) {
380 parse_info(p, "FAIL: should_fail %d, failed %d", 400 parse_info(p, "FAIL: should_fail %d, failed %d",
@@ -383,6 +403,10 @@ MlkemEncapFileTest(struct encap_ctx *encap)
383 } 403 }
384 404
385 err: 405 err:
406 MLKEM_public_key_free(pub_key);
407 freezero(ciphertext_buf, ciphertext_buf_len);
408 freezero(shared_secret_buf, shared_secret_buf_len);
409
386 return failed; 410 return failed;
387} 411}
388 412
@@ -403,48 +427,19 @@ static const struct test_parse encap_parse = {
403}; 427};
404 428
405static int 429static int
406mlkem_encap_tests(const char *fn, size_t size) 430mlkem_encap_tests(const char *fn, int rank)
407{ 431{
408 struct MLKEM768_public_key public_key768; 432 struct encap_ctx encap = {
409 uint8_t ciphertext768[MLKEM768_CIPHERTEXT_BYTES]; 433 .rank = rank,
410 struct encap_ctx encap768 = {
411 .public_key = &public_key768,
412 .ciphertext = ciphertext768,
413 .ciphertext_len = sizeof(ciphertext768),
414
415 .parse_public_key = mlkem768_parse_public_key,
416 .encap_external_entropy = mlkem768_encap_external_entropy,
417 };
418 struct MLKEM1024_public_key public_key1024;
419 uint8_t ciphertext1024[MLKEM1024_CIPHERTEXT_BYTES];
420 struct encap_ctx encap1024 = {
421 .public_key = &public_key1024,
422 .ciphertext = ciphertext1024,
423 .ciphertext_len = sizeof(ciphertext1024),
424
425 .parse_public_key = mlkem1024_parse_public_key,
426 .encap_external_entropy = mlkem1024_encap_external_entropy,
427 }; 434 };
428 435
429 if (size == 768) 436 return parse_test_file(fn, &encap_parse, &encap);
430 return parse_test_file(fn, &encap_parse, &encap768);
431 if (size == 1024)
432 return parse_test_file(fn, &encap_parse, &encap1024);
433
434 errx(1, "unknown encap test: size %zu", size);
435} 437}
436 438
437struct keygen_ctx { 439struct keygen_ctx {
438 struct parse *parse_ctx; 440 struct parse *parse_ctx;
439 441
440 void *private_key; 442 int rank;
441 void *encoded_public_key;
442 size_t encoded_public_key_len;
443 size_t private_key_len;
444 size_t public_key_len;
445
446 mlkem_generate_key_external_entropy_fn generate_key_external_entropy;
447 mlkem_marshal_private_key_fn marshal_private_key;
448}; 443};
449 444
450enum keygen_states { 445enum keygen_states {
@@ -495,27 +490,38 @@ static int
495MlkemKeygenFileTest(struct keygen_ctx *keygen) 490MlkemKeygenFileTest(struct keygen_ctx *keygen)
496{ 491{
497 struct parse *p = keygen->parse_ctx; 492 struct parse *p = keygen->parse_ctx;
493 MLKEM_private_key *priv_key = NULL;
498 CBS seed, public_key, private_key; 494 CBS seed, public_key, private_key;
499 uint8_t *encoded_private_key = NULL; 495 uint8_t *encoded_private_key = NULL;
500 size_t encoded_private_key_len = 0; 496 size_t encoded_private_key_len = 0;
497 uint8_t *encoded_public_key = NULL;
498 size_t encoded_public_key_len = 0;
501 int failed = 1; 499 int failed = 1;
502 500
503 parse_get_cbs(p, KEYGEN_SEED, &seed); 501 parse_get_cbs(p, KEYGEN_SEED, &seed);
504 parse_get_cbs(p, KEYGEN_PUBLIC_KEY, &public_key); 502 parse_get_cbs(p, KEYGEN_PUBLIC_KEY, &public_key);
505 parse_get_cbs(p, KEYGEN_PRIVATE_KEY, &private_key); 503 parse_get_cbs(p, KEYGEN_PRIVATE_KEY, &private_key);
506 504
507 if (!parse_length_equal(p, "seed", MLKEM_SEED_BYTES, CBS_len(&seed))) 505 if (!parse_length_equal(p, "seed", MLKEM_SEED_LENGTH, CBS_len(&seed)))
508 goto err; 506 goto err;
507
508 if ((priv_key = MLKEM_private_key_new(keygen->rank)) == NULL)
509 parse_errx(p, "MLKEM_public_key_free");
510
511 if (!MLKEM_generate_key_external_entropy(priv_key,
512 &encoded_public_key, &encoded_public_key_len, CBS_data(&seed))) {
513 parse_info(p, "generate_key_external_entropy");
514 goto err;
515 }
516
509 if (!parse_length_equal(p, "public key", 517 if (!parse_length_equal(p, "public key",
510 keygen->public_key_len, CBS_len(&public_key))) 518 encoded_public_key_len, CBS_len(&public_key)))
511 goto err; 519 goto err;
512 if (!parse_length_equal(p, "private key", 520 if (!parse_length_equal(p, "private key",
513 keygen->private_key_len, CBS_len(&private_key))) 521 MLKEM_private_key_encoded_length(priv_key), CBS_len(&private_key)))
514 goto err; 522 goto err;
515 523
516 keygen->generate_key_external_entropy(keygen->encoded_public_key, 524 if (!MLKEM_marshal_private_key(priv_key,
517 keygen->private_key, CBS_data(&seed));
518 if (!keygen->marshal_private_key(keygen->private_key,
519 &encoded_private_key, &encoded_private_key_len)) { 525 &encoded_private_key, &encoded_private_key_len)) {
520 parse_info(p, "encode private key"); 526 parse_info(p, "encode private key");
521 goto err; 527 goto err;
@@ -524,10 +530,12 @@ MlkemKeygenFileTest(struct keygen_ctx *keygen)
524 failed = !parse_data_equal(p, "private key", &private_key, 530 failed = !parse_data_equal(p, "private key", &private_key,
525 encoded_private_key, encoded_private_key_len); 531 encoded_private_key, encoded_private_key_len);
526 failed |= !parse_data_equal(p, "public key", &public_key, 532 failed |= !parse_data_equal(p, "public key", &public_key,
527 keygen->encoded_public_key, keygen->encoded_public_key_len); 533 encoded_public_key, encoded_public_key_len);
528 534
529 err: 535 err:
536 MLKEM_private_key_free(priv_key);
530 freezero(encoded_private_key, encoded_private_key_len); 537 freezero(encoded_private_key, encoded_private_key_len);
538 freezero(encoded_public_key, encoded_public_key_len);
531 539
532 return failed; 540 return failed;
533} 541}
@@ -587,12 +595,15 @@ static int
587MlkemNistKeygenFileTest(struct keygen_ctx *keygen) 595MlkemNistKeygenFileTest(struct keygen_ctx *keygen)
588{ 596{
589 struct parse *p = keygen->parse_ctx; 597 struct parse *p = keygen->parse_ctx;
598 MLKEM_private_key *priv_key = NULL;
590 CBB seed_cbb; 599 CBB seed_cbb;
591 CBS z, d, ek, dk; 600 CBS z, d, ek, dk;
592 uint8_t seed[MLKEM_SEED_BYTES]; 601 uint8_t seed[MLKEM_SEED_LENGTH];
593 size_t seed_len; 602 size_t seed_len;
594 uint8_t *encoded_private_key = NULL; 603 uint8_t *encoded_private_key = NULL;
595 size_t encoded_private_key_len = 0; 604 size_t encoded_private_key_len = 0;
605 uint8_t *encoded_public_key = NULL;
606 size_t encoded_public_key_len = 0;
596 int failed = 1; 607 int failed = 1;
597 608
598 parse_get_cbs(p, NIST_KEYGEN_Z, &z); 609 parse_get_cbs(p, NIST_KEYGEN_Z, &z);
@@ -609,24 +620,33 @@ MlkemNistKeygenFileTest(struct keygen_ctx *keygen)
609 if (!CBB_finish(&seed_cbb, NULL, &seed_len)) 620 if (!CBB_finish(&seed_cbb, NULL, &seed_len))
610 parse_errx(p, "CBB_finish"); 621 parse_errx(p, "CBB_finish");
611 622
612 if (!parse_length_equal(p, "bogus z or d", MLKEM_SEED_BYTES, seed_len)) 623 if (!parse_length_equal(p, "bogus z or d", MLKEM_SEED_LENGTH, seed_len))
613 goto err; 624 goto err;
614 625
615 keygen->generate_key_external_entropy(keygen->encoded_public_key, 626 if ((priv_key = MLKEM_private_key_new(keygen->rank)) == NULL)
616 keygen->private_key, seed); 627 parse_errx(p, "MLKEM_private_key_new");
617 if (!keygen->marshal_private_key(keygen->private_key, 628
629 if (!MLKEM_generate_key_external_entropy(priv_key,
630 &encoded_public_key, &encoded_public_key_len, seed)) {
631 parse_info(p, "MLKEM_generate_key_external_entropy");
632 goto err;
633 }
634
635 if (!MLKEM_marshal_private_key(priv_key,
618 &encoded_private_key, &encoded_private_key_len)) { 636 &encoded_private_key, &encoded_private_key_len)) {
619 parse_info(p, "encode private key"); 637 parse_info(p, "encode private key");
620 goto err; 638 goto err;
621 } 639 }
622 640
623 failed = !parse_data_equal(p, "public key", &ek, 641 failed = !parse_data_equal(p, "public key", &ek,
624 keygen->encoded_public_key, keygen->encoded_public_key_len); 642 encoded_public_key, encoded_public_key_len);
625 failed |= !parse_data_equal(p, "private key", &dk, 643 failed |= !parse_data_equal(p, "private key", &dk,
626 encoded_private_key, encoded_private_key_len); 644 encoded_private_key, encoded_private_key_len);
627 645
628 err: 646 err:
647 MLKEM_private_key_free(priv_key);
629 freezero(encoded_private_key, encoded_private_key_len); 648 freezero(encoded_private_key, encoded_private_key_len);
649 freezero(encoded_public_key, encoded_public_key_len);
630 650
631 return failed; 651 return failed;
632} 652}
@@ -648,74 +668,45 @@ static const struct test_parse nist_keygen_parse = {
648}; 668};
649 669
650static int 670static int
651mlkem_keygen_tests(const char *fn, size_t size, enum test_type test_type) 671mlkem_keygen_tests(const char *fn, int rank, enum test_type test_type)
652{ 672{
653 struct MLKEM768_private_key private_key768; 673 struct keygen_ctx keygen = {
654 uint8_t encoded_public_key768[MLKEM768_PUBLIC_KEY_BYTES]; 674 .rank = rank,
655 struct keygen_ctx keygen768 = {
656 .private_key = &private_key768,
657 .encoded_public_key = encoded_public_key768,
658 .encoded_public_key_len = sizeof(encoded_public_key768),
659 .private_key_len = MLKEM768_PRIVATE_KEY_BYTES,
660 .public_key_len = MLKEM768_PUBLIC_KEY_BYTES,
661
662 .generate_key_external_entropy =
663 mlkem768_generate_key_external_entropy,
664 .marshal_private_key =
665 mlkem768_marshal_private_key,
666 };
667 struct MLKEM1024_private_key private_key1024;
668 uint8_t encoded_public_key1024[MLKEM1024_PUBLIC_KEY_BYTES];
669 struct keygen_ctx keygen1024 = {
670 .private_key = &private_key1024,
671 .encoded_public_key = encoded_public_key1024,
672 .encoded_public_key_len = sizeof(encoded_public_key1024),
673 .private_key_len = MLKEM1024_PRIVATE_KEY_BYTES,
674 .public_key_len = MLKEM1024_PUBLIC_KEY_BYTES,
675
676 .generate_key_external_entropy =
677 mlkem1024_generate_key_external_entropy,
678 .marshal_private_key =
679 mlkem1024_marshal_private_key,
680 }; 675 };
681 676
682 if (size == 768 && test_type == TEST_TYPE_NORMAL) 677 if (test_type == TEST_TYPE_NORMAL)
683 return parse_test_file(fn, &keygen_parse, &keygen768); 678 return parse_test_file(fn, &keygen_parse, &keygen);
684 if (size == 768 && test_type == TEST_TYPE_NIST) 679 if (test_type == TEST_TYPE_NIST)
685 return parse_test_file(fn, &nist_keygen_parse, &keygen768); 680 return parse_test_file(fn, &nist_keygen_parse, &keygen);
686 if (size == 1024 && test_type == TEST_TYPE_NORMAL)
687 return parse_test_file(fn, &keygen_parse, &keygen1024);
688 if (size == 1024 && test_type == TEST_TYPE_NIST)
689 return parse_test_file(fn, &nist_keygen_parse, &keygen1024);
690 681
691 errx(1, "unknown keygen test: size %zu, type %d", size, test_type); 682 errx(1, "unknown keygen test: rank %d, type %d", rank, test_type);
692} 683}
693 684
694static int 685static int
695run_mlkem_test(const char *test, const char *fn) 686run_mlkem_test(const char *test, const char *fn)
696{ 687{
697 if (strcmp(test, "mlkem768_decap_tests") == 0) 688 if (strcmp(test, "mlkem768_decap_tests") == 0)
698 return mlkem_decap_tests(fn, 768, TEST_TYPE_NORMAL); 689 return mlkem_decap_tests(fn, RANK768, TEST_TYPE_NORMAL);
699 if (strcmp(test, "mlkem768_nist_decap_tests") == 0) 690 if (strcmp(test, "mlkem768_nist_decap_tests") == 0)
700 return mlkem_decap_tests(fn, 768, TEST_TYPE_NIST); 691 return mlkem_decap_tests(fn, RANK768, TEST_TYPE_NIST);
701 if (strcmp(test, "mlkem1024_decap_tests") == 0) 692 if (strcmp(test, "mlkem1024_decap_tests") == 0)
702 return mlkem_decap_tests(fn, 1024, TEST_TYPE_NORMAL); 693 return mlkem_decap_tests(fn, RANK1024, TEST_TYPE_NORMAL);
703 if (strcmp(test, "mlkem1024_nist_decap_tests") == 0) 694 if (strcmp(test, "mlkem1024_nist_decap_tests") == 0)
704 return mlkem_decap_tests(fn, 1024, TEST_TYPE_NIST); 695 return mlkem_decap_tests(fn, RANK1024, TEST_TYPE_NIST);
705 696
706 if (strcmp(test, "mlkem768_encap_tests") == 0) 697 if (strcmp(test, "mlkem768_encap_tests") == 0)
707 return mlkem_encap_tests(fn, 768); 698 return mlkem_encap_tests(fn, RANK768);
708 if (strcmp(test, "mlkem1024_encap_tests") == 0) 699 if (strcmp(test, "mlkem1024_encap_tests") == 0)
709 return mlkem_encap_tests(fn, 1024); 700 return mlkem_encap_tests(fn, RANK1024);
710 701
711 if (strcmp(test, "mlkem768_keygen_tests") == 0) 702 if (strcmp(test, "mlkem768_keygen_tests") == 0)
712 return mlkem_keygen_tests(fn, 768, TEST_TYPE_NORMAL); 703 return mlkem_keygen_tests(fn, RANK768, TEST_TYPE_NORMAL);
713 if (strcmp(test, "mlkem768_nist_keygen_tests") == 0) 704 if (strcmp(test, "mlkem768_nist_keygen_tests") == 0)
714 return mlkem_keygen_tests(fn, 768, TEST_TYPE_NIST); 705 return mlkem_keygen_tests(fn, RANK768, TEST_TYPE_NIST);
715 if (strcmp(test, "mlkem1024_keygen_tests") == 0) 706 if (strcmp(test, "mlkem1024_keygen_tests") == 0)
716 return mlkem_keygen_tests(fn, 1024, TEST_TYPE_NORMAL); 707 return mlkem_keygen_tests(fn, RANK1024, TEST_TYPE_NORMAL);
717 if (strcmp(test, "mlkem1024_nist_keygen_tests") == 0) 708 if (strcmp(test, "mlkem1024_nist_keygen_tests") == 0)
718 return mlkem_keygen_tests(fn, 1024, TEST_TYPE_NIST); 709 return mlkem_keygen_tests(fn, RANK1024, TEST_TYPE_NIST);
719 710
720 errx(1, "unknown test %s (test file %s)", test, fn); 711 errx(1, "unknown test %s (test file %s)", test, fn);
721} 712}
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.c b/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.c
index 68bd5d4871..d2e0fbd7c7 100644
--- a/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.c
+++ b/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mlkem_tests_util.c,v 1.8 2025/05/20 00:33:41 beck Exp $ */ 1/* $OpenBSD: mlkem_tests_util.c,v 1.10 2025/08/15 14:47:54 tb 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>
@@ -22,11 +22,6 @@
22#include <stdio.h> 22#include <stdio.h>
23#include <string.h> 23#include <string.h>
24 24
25#include "bytestring.h"
26#include "mlkem.h"
27
28#include "mlkem_internal.h"
29
30#include "mlkem_tests_util.h" 25#include "mlkem_tests_util.h"
31 26
32static void 27static void
@@ -59,157 +54,3 @@ compare_data(const uint8_t *want, const uint8_t *got, size_t len, const char *ms
59 54
60 return 1; 55 return 1;
61} 56}
62
63int
64mlkem768_marshal_private_key(const void *private_key, uint8_t **out_buf,
65 size_t *out_len)
66{
67 return MLKEM768_marshal_private_key(private_key, out_buf, out_len);
68}
69
70int
71mlkem768_marshal_public_key(const void *public_key, uint8_t **out_buf,
72 size_t *out_len)
73{
74 return MLKEM768_marshal_public_key(out_buf, out_len, public_key);
75}
76
77int
78mlkem1024_marshal_private_key(const void *private_key, uint8_t **out_buf,
79 size_t *out_len)
80{
81 return MLKEM1024_marshal_private_key(private_key, out_buf, out_len);
82}
83
84int
85mlkem1024_marshal_public_key(const void *public_key, uint8_t **out_buf,
86 size_t *out_len)
87{
88 return MLKEM1024_marshal_public_key(out_buf, out_len, public_key);
89}
90
91int
92mlkem768_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
93 const uint8_t *ciphertext, size_t ciphertext_len, const void *private_key)
94{
95 return MLKEM768_decap(out_shared_secret, ciphertext, ciphertext_len,
96 private_key);
97}
98
99void
100mlkem768_encap(uint8_t *out_ciphertext,
101 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
102 const void *public_key)
103{
104 MLKEM768_encap(out_ciphertext, out_shared_secret, public_key);
105}
106
107void
108mlkem768_encap_external_entropy(uint8_t *out_ciphertext,
109 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
110 const void *public_key, const uint8_t entropy[MLKEM_ENCAP_ENTROPY])
111{
112 MLKEM768_encap_external_entropy(out_ciphertext, out_shared_secret,
113 public_key, entropy);
114}
115
116int
117mlkem768_generate_key(uint8_t *out_encoded_public_key,
118 uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key)
119{
120 return MLKEM768_generate_key(out_encoded_public_key, optional_out_seed,
121 out_private_key);
122}
123
124int
125mlkem768_generate_key_external_entropy(uint8_t *out_encoded_public_key,
126 void *out_private_key, const uint8_t entropy[MLKEM_SEED_BYTES])
127{
128 return MLKEM768_generate_key_external_entropy(out_encoded_public_key,
129 out_private_key, entropy);
130}
131
132int
133mlkem768_parse_private_key(void *out_private_key, const uint8_t *private_key,
134 size_t private_key_len)
135{
136 return MLKEM768_parse_private_key(out_private_key, private_key,
137 private_key_len);
138}
139
140int
141mlkem768_parse_public_key(void *out_public_key, const uint8_t *public_key,
142 size_t public_key_len)
143{
144 return MLKEM768_parse_public_key(out_public_key, public_key,
145 public_key_len);
146}
147
148void
149mlkem768_public_from_private(void *out_public_key, const void *private_key)
150{
151 MLKEM768_public_from_private(out_public_key, private_key);
152}
153
154int
155mlkem1024_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
156 const uint8_t *ciphertext, size_t ciphertext_len, const void *private_key)
157{
158 return MLKEM1024_decap(out_shared_secret, ciphertext, ciphertext_len,
159 private_key);
160}
161
162void
163mlkem1024_encap(uint8_t *out_ciphertext,
164 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
165 const void *public_key)
166{
167 MLKEM1024_encap(out_ciphertext, out_shared_secret, public_key);
168}
169
170void
171mlkem1024_encap_external_entropy(uint8_t *out_ciphertext,
172 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
173 const void *public_key, const uint8_t entropy[MLKEM_ENCAP_ENTROPY])
174{
175 MLKEM1024_encap_external_entropy(out_ciphertext, out_shared_secret,
176 public_key, entropy);
177}
178
179int
180mlkem1024_generate_key(uint8_t *out_encoded_public_key,
181 uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key)
182{
183 return MLKEM1024_generate_key(out_encoded_public_key, optional_out_seed,
184 out_private_key);
185}
186
187int
188mlkem1024_generate_key_external_entropy(uint8_t *out_encoded_public_key,
189 void *out_private_key, const uint8_t entropy[MLKEM_SEED_BYTES])
190{
191 return MLKEM1024_generate_key_external_entropy(out_encoded_public_key,
192 out_private_key, entropy);
193}
194
195int
196mlkem1024_parse_private_key(void *out_private_key, const uint8_t *private_key,
197 size_t private_key_len)
198{
199 return MLKEM1024_parse_private_key(out_private_key, private_key,
200 private_key_len);
201}
202
203void
204mlkem1024_public_from_private(void *out_public_key, const void *private_key)
205{
206 MLKEM1024_public_from_private(out_public_key, private_key);
207}
208
209int
210mlkem1024_parse_public_key(void *out_public_key, const uint8_t *public_key,
211 size_t public_key_len)
212{
213 return MLKEM1024_parse_public_key(out_public_key, public_key,
214 public_key_len);
215}
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.h b/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.h
index 1235309f60..514a309112 100644
--- a/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.h
+++ b/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: mlkem_tests_util.h,v 1.7 2025/05/20 00:33:41 beck Exp $ */ 1/* $OpenBSD: mlkem_tests_util.h,v 1.9 2025/08/15 14:47:54 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2024 Bob Beck <beck@obtuse.com> 3 * Copyright (c) 2024 Bob Beck <beck@obtuse.com>
4 * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> 4 * Copyright (c) 2024 Theo Buehler <tb@openbsd.org>
@@ -22,68 +22,7 @@
22#include <stddef.h> 22#include <stddef.h>
23#include <stdint.h> 23#include <stdint.h>
24 24
25#include "bytestring.h"
26
27#include "mlkem.h"
28#include "mlkem_internal.h"
29
30int compare_data(const uint8_t *want, const uint8_t *got, size_t len, 25int compare_data(const uint8_t *want, const uint8_t *got, size_t len,
31 const char *msg); 26 const char *msg);
32 27
33int mlkem768_marshal_private_key(const void *priv, uint8_t **out_buf,
34 size_t *out_len);
35int mlkem768_marshal_public_key(const void *pub, uint8_t **out_buf,
36 size_t *out_len);
37int mlkem1024_marshal_private_key(const void *priv, uint8_t **out_buf,
38 size_t *out_len);
39int mlkem1024_marshal_public_key(const void *pub, uint8_t **out_buf,
40 size_t *out_len);
41
42int mlkem768_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
43 const uint8_t *ciphertext, size_t ciphertext_len, const void *priv);
44void mlkem768_encap(uint8_t *out_ciphertext,
45 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], const void *pub);
46void mlkem768_encap_external_entropy(uint8_t *out_ciphertext,
47 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], const void *pub,
48 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]);
49int mlkem768_generate_key(uint8_t *out_encoded_public_key,
50 uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key);
51int mlkem768_generate_key_external_entropy(uint8_t *out_encoded_public_key,
52 void *out_private_key, const uint8_t entropy[MLKEM_SEED_BYTES]);
53int mlkem768_parse_private_key(void *priv, const uint8_t *in, size_t in_len);
54int mlkem768_parse_public_key(void *pub, const uint8_t *in, size_t in_len);
55void mlkem768_public_from_private(void *out_public_key, const void *private_key);
56
57int mlkem1024_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
58 const uint8_t *ciphertext, size_t ciphertext_len, const void *priv);
59void mlkem1024_encap(uint8_t *out_ciphertext,
60 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], const void *pub);
61void mlkem1024_encap_external_entropy(uint8_t *out_ciphertext,
62 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], const void *pub,
63 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]);
64int mlkem1024_generate_key(uint8_t *out_encoded_public_key,
65 uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key);
66int mlkem1024_generate_key_external_entropy(uint8_t *out_encoded_public_key,
67 void *out_private_key, const uint8_t entropy[MLKEM_SEED_BYTES]);
68int mlkem1024_parse_private_key(void *priv, const uint8_t *in, size_t in_len);
69int mlkem1024_parse_public_key(void *pub, const uint8_t *in, size_t in_len);
70void mlkem1024_public_from_private(void *out_public_key, const void *private_key);
71
72typedef int (*mlkem_marshal_private_key_fn)(const void *, uint8_t **, size_t *);
73typedef int (*mlkem_marshal_public_key_fn)(const void *, uint8_t **, size_t *);
74typedef int (*mlkem_decap_fn)(uint8_t [MLKEM_SHARED_SECRET_BYTES],
75 const uint8_t *, size_t, const void *);
76typedef void (*mlkem_encap_fn)(uint8_t *, uint8_t [MLKEM_SHARED_SECRET_BYTES],
77 const void *);
78typedef void (*mlkem_encap_external_entropy_fn)(uint8_t *,
79 uint8_t [MLKEM_SHARED_SECRET_BYTES], const void *,
80 const uint8_t [MLKEM_ENCAP_ENTROPY]);
81typedef int (*mlkem_generate_key_fn)(uint8_t *, uint8_t *, void *);
82typedef int (*mlkem_generate_key_external_entropy_fn)(uint8_t *, void *,
83 const uint8_t [MLKEM_SEED_BYTES]);
84typedef int (*mlkem_parse_private_key_fn)(void *, const uint8_t *, size_t);
85typedef int (*mlkem_parse_public_key_fn)(void *, const uint8_t *, size_t);
86typedef void (*mlkem_public_from_private_fn)(void *out_public_key,
87 const void *private_key);
88
89#endif /* MLKEM_TEST_UTIL_H */ 28#endif /* MLKEM_TEST_UTIL_H */
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_unittest.c b/src/regress/lib/libcrypto/mlkem/mlkem_unittest.c
index adb1c47d8e..f802324189 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.15 2025/08/17 19:26:35 tb 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>
@@ -22,100 +22,166 @@
22#include <stdlib.h> 22#include <stdlib.h>
23#include <string.h> 23#include <string.h>
24 24
25#include "bytestring.h" 25#include <openssl/mlkem.h>
26#include "mlkem.h"
27 26
27#include "mlkem_internal.h"
28#include "mlkem_tests_util.h" 28#include "mlkem_tests_util.h"
29 29
30struct 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
49static int 30static int
50MlKemUnitTest(struct unittest_ctx *ctx) 31MlKemUnitTest(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
187static int
188mlkem768_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
216static int
217mlkem1024_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
245int 298int
246main(void) 299main(void)
247{ 300{
248 int failed = 0; 301 int failed = 0;
249 302
250 /* 303 failed |= MlKemUnitTest(RANK768);
251 * XXX - this is split into two helper functions since having a few 304 failed |= 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
257 failed |= mlkem768_unittest();
258 failed |= mlkem1024_unittest();
259 305
260 return failed; 306 return failed;
261} 307}