summaryrefslogtreecommitdiff
path: root/src/regress/lib/libc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/regress/lib/libc/Makefile11
-rw-r--r--src/regress/lib/libc/arc4random-fork/arc4random-fork.c2
-rw-r--r--src/regress/lib/libc/explicit_bzero/explicit_bzero.c4
-rw-r--r--src/regress/lib/libc/hash/Makefile5
-rw-r--r--src/regress/lib/libc/hash/hash_test.c935
-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/Makefile16
-rw-r--r--src/regress/lib/libc/malloc/malloc_errs/malloc_errs.c15
-rw-r--r--src/regress/lib/libc/malloc/malloc_ulimit1/malloc_ulimit1.c4
-rw-r--r--src/regress/lib/libc/stdio/Makefile29
-rw-r--r--src/regress/lib/libc/stdio/test___fpending.c58
-rw-r--r--src/regress/lib/libc/stdio/test___freadahead.c71
-rw-r--r--src/regress/lib/libc/stdio/test___freading.c125
-rw-r--r--src/regress/lib/libc/stdio/test___freadptr.c78
-rw-r--r--src/regress/lib/libc/stdio/test___fseterr.c60
-rw-r--r--src/regress/lib/libc/stdio/test___fwriting.c83
-rw-r--r--src/regress/lib/libc/stdio/test_fflush.c345
-rw-r--r--src/regress/lib/libc/stdio/test_ungetwc.c90
-rw-r--r--src/regress/lib/libcrypto/aes/aes_test.c303
-rw-r--r--src/regress/lib/libcrypto/asn1/asn1time.c26
-rw-r--r--src/regress/lib/libcrypto/bio/bio_dump.c4
-rw-r--r--src/regress/lib/libcrypto/c2sp/Makefile13
-rw-r--r--src/regress/lib/libcrypto/certs/Makefile19
-rw-r--r--src/regress/lib/libcrypto/ec/Makefile9
-rw-r--r--src/regress/lib/libcrypto/ec/ec_arithmetic.c210
-rw-r--r--src/regress/lib/libcrypto/ec/ec_asn1_test.c321
-rw-r--r--src/regress/lib/libcrypto/ec/ectest.c9
-rw-r--r--src/regress/lib/libcrypto/evp/evp_pkey_cleanup.c4
-rw-r--r--src/regress/lib/libcrypto/evp/evp_test.c82
-rw-r--r--src/regress/lib/libcrypto/gcm128/gcm128test.c32
-rwxr-xr-xsrc/regress/lib/libcrypto/man/check_complete.pl11
-rw-r--r--src/regress/lib/libcrypto/md/Makefile18
-rw-r--r--src/regress/lib/libcrypto/md/md_test.c210
-rw-r--r--src/regress/lib/libcrypto/mlkem/mlkem_iteration_tests.c16
-rw-r--r--src/regress/lib/libcrypto/mlkem/mlkem_tests.c26
-rw-r--r--src/regress/lib/libcrypto/mlkem/mlkem_tests_util.c118
-rw-r--r--src/regress/lib/libcrypto/mlkem/mlkem_tests_util.h38
-rw-r--r--src/regress/lib/libcrypto/mlkem/mlkem_unittest.c70
-rw-r--r--src/regress/lib/libcrypto/mlkem/parse_test_file.c13
-rw-r--r--src/regress/lib/libcrypto/sha/Makefile8
-rw-r--r--src/regress/lib/libcrypto/sha/sha_test.c286
-rw-r--r--src/regress/lib/libcrypto/test/test.c226
-rw-r--r--src/regress/lib/libcrypto/test/test.h137
-rw-r--r--src/regress/lib/libcrypto/test/test_util.c51
-rw-r--r--src/regress/lib/libcrypto/wycheproof/Makefile10
-rw-r--r--src/regress/lib/libcrypto/x509/Makefile11
-rw-r--r--src/regress/lib/libcrypto/x509/bettertls/Makefile8
-rw-r--r--src/regress/lib/libcrypto/x509/x509_name_test.c420
-rw-r--r--src/regress/lib/libcrypto/x509/x509name.c62
-rw-r--r--src/regress/lib/libcrypto/x509/x509name.expected3
51 files changed, 4002 insertions, 719 deletions
diff --git a/src/regress/lib/libc/Makefile b/src/regress/lib/libc/Makefile
index 3cd970e49d..7a8db225ef 100644
--- a/src/regress/lib/libc/Makefile
+++ b/src/regress/lib/libc/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.59 2024/07/14 09:48:48 jca 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
@@ -9,8 +9,9 @@ SUBDIR+= elf_aux_info
9SUBDIR+= env explicit_bzero 9SUBDIR+= env explicit_bzero
10SUBDIR+= ffs fmemopen fnmatch fpclassify fread 10SUBDIR+= ffs fmemopen fnmatch fpclassify fread
11SUBDIR+= gcvt getaddrinfo getcap getopt getopt_long glob 11SUBDIR+= gcvt getaddrinfo getcap getopt getopt_long glob
12SUBDIR+= hash
12SUBDIR+= hsearch 13SUBDIR+= hsearch
13SUBDIR+= ieeefp ifnameindex 14SUBDIR+= ieeefp ifnameindex illumos
14SUBDIR+= ldexp locale longjmp 15SUBDIR+= ldexp locale longjmp
15SUBDIR+= malloc mkstemp modf 16SUBDIR+= malloc mkstemp modf
16SUBDIR+= netdb 17SUBDIR+= netdb
@@ -18,9 +19,9 @@ SUBDIR+= open_memstream orientation
18SUBDIR+= popen printf 19SUBDIR+= popen printf
19SUBDIR+= qsort 20SUBDIR+= qsort
20SUBDIR+= regex 21SUBDIR+= regex
21SUBDIR+= setjmp setjmp-signal sigsetjmp sigthr sleep sprintf stdio_threading 22SUBDIR+= setjmp setjmp-signal sigsetjmp sigthr sleep sprintf stdio
22SUBDIR+= stpncpy strchr strerror strlcat strlcpy strnlen strtod strtol strtonum 23SUBDIR+= stdio_threading stpncpy strchr strerror strlcat strlcpy strnlen
23SUBDIR+= sys 24SUBDIR+= strtod strtol strtonum sys
24SUBDIR+= telldir time timingsafe 25SUBDIR+= telldir time timingsafe
25SUBDIR+= uuid 26SUBDIR+= uuid
26SUBDIR+= vis 27SUBDIR+= vis
diff --git a/src/regress/lib/libc/arc4random-fork/arc4random-fork.c b/src/regress/lib/libc/arc4random-fork/arc4random-fork.c
index 4bc9c634f1..9b334945af 100644
--- a/src/regress/lib/libc/arc4random-fork/arc4random-fork.c
+++ b/src/regress/lib/libc/arc4random-fork/arc4random-fork.c
@@ -111,7 +111,7 @@ main(int argc, char *argv[])
111 } 111 }
112 112
113 if (flagprefork) 113 if (flagprefork)
114 arc4random(); 114 (void)arc4random();
115 115
116 bufparent = mmap(NULL, sizeof(Buf), PROT_READ|PROT_WRITE, 116 bufparent = mmap(NULL, sizeof(Buf), PROT_READ|PROT_WRITE,
117 MAP_ANON|MAP_PRIVATE, -1, 0); 117 MAP_ANON|MAP_PRIVATE, -1, 0);
diff --git a/src/regress/lib/libc/explicit_bzero/explicit_bzero.c b/src/regress/lib/libc/explicit_bzero/explicit_bzero.c
index 496bafb208..30c86290e8 100644
--- a/src/regress/lib/libc/explicit_bzero/explicit_bzero.c
+++ b/src/regress/lib/libc/explicit_bzero/explicit_bzero.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: explicit_bzero.c,v 1.9 2022/02/10 08:39:32 tb Exp $ */ 1/* $OpenBSD: explicit_bzero.c,v 1.10 2025/05/31 15:31:40 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Google Inc. 3 * Copyright (c) 2014 Google Inc.
4 * 4 *
@@ -28,9 +28,11 @@
28 28
29#if defined(__has_feature) 29#if defined(__has_feature)
30#if __has_feature(address_sanitizer) 30#if __has_feature(address_sanitizer)
31#ifndef __SANITIZE_ADDRESS__
31#define __SANITIZE_ADDRESS__ 32#define __SANITIZE_ADDRESS__
32#endif 33#endif
33#endif 34#endif
35#endif
34#ifdef __SANITIZE_ADDRESS__ 36#ifdef __SANITIZE_ADDRESS__
35#define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) 37#define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
36#else 38#else
diff --git a/src/regress/lib/libc/hash/Makefile b/src/regress/lib/libc/hash/Makefile
new file mode 100644
index 0000000000..9bd69bf8df
--- /dev/null
+++ b/src/regress/lib/libc/hash/Makefile
@@ -0,0 +1,5 @@
1# $OpenBSD: Makefile,v 1.2 2025/04/14 18:33:56 tb Exp $
2
3PROG = hash_test
4
5.include <bsd.regress.mk>
diff --git a/src/regress/lib/libc/hash/hash_test.c b/src/regress/lib/libc/hash/hash_test.c
new file mode 100644
index 0000000000..c04a0458fe
--- /dev/null
+++ b/src/regress/lib/libc/hash/hash_test.c
@@ -0,0 +1,935 @@
1/* $OpenBSD: hash_test.c,v 1.3 2025/08/02 06:05:13 tb Exp $ */
2
3/*
4 * Copyright (c) 2025 Theo Buehler <tb@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20
21#include <md5.h>
22#include <rmd160.h>
23#include <sha1.h>
24#include <sha2.h>
25#include <stdio.h>
26#include <string.h>
27
28#define MAX_DIGEST_LENGTH SHA512_DIGEST_LENGTH
29
30struct hash_test_case {
31 const char *in;
32 const uint8_t out[MAX_DIGEST_LENGTH];
33};
34
35enum {
36 hash_md5,
37 hash_rmd160,
38 hash_sha1,
39 hash_sha224,
40 hash_sha256,
41 hash_sha384,
42 hash_sha512,
43 hash_sha512_256,
44 NUM_HASHES,
45};
46
47/* RFC 1321, Appendix A.5 */
48static const struct hash_test_case md5_tests[] = {
49 {
50 .out = {
51 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
52 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e,
53 },
54 },
55 {
56 .in = "",
57 .out = {
58 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
59 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e,
60 },
61 },
62 {
63 .in = "a",
64 .out = {
65 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
66 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61,
67 },
68 },
69 {
70 .in = "abc",
71 .out = {
72 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
73 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72,
74 },
75 },
76 {
77 .in = "message digest",
78 .out = {
79 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d,
80 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0,
81 },
82 },
83 {
84 .in = "abcdefghijklmnopqrstuvwxyz",
85 .out = {
86 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00,
87 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b,
88 },
89 },
90 {
91 .in = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
92 "abcdefghijklmnopqrstuvwxyz0123456789",
93 .out = {
94 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5,
95 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f,
96 },
97 },
98 {
99 .in = "1234567890123456789012345678901234567890"
100 "1234567890123456789012345678901234567890",
101 .out = {
102 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
103 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a,
104 },
105 },
106};
107
108#define N_MD5_TESTS (sizeof(md5_tests) / sizeof(md5_tests[0]))
109
110static void
111md5_init(void *ctx)
112{
113 MD5Init(ctx);
114}
115
116static void
117md5_update(void *ctx, const uint8_t *data, size_t len)
118{
119 MD5Update(ctx, data, len);
120}
121
122static void
123md5_final(void *digest, void *ctx)
124{
125 MD5Final(digest, ctx);
126}
127
128/* https://homes.esat.kuleuven.be/~bosselae/ripemd160.html */
129static const struct hash_test_case rmd160_tests[] = {
130 {
131 .out = {
132 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54,
133 0x61, 0x28, 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48,
134 0xb2, 0x25, 0x8d, 0x31,
135 },
136 },
137 {
138 .in = "",
139 .out = {
140 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54,
141 0x61, 0x28, 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48,
142 0xb2, 0x25, 0x8d, 0x31,
143 },
144 },
145 {
146 .in = "a",
147 .out = {
148 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9,
149 0xda, 0xae, 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83,
150 0x5a, 0x46, 0x7f, 0xfe,
151 },
152 },
153 {
154 .in = "abc",
155 .out = {
156 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a,
157 0x9b, 0x04, 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87,
158 0xf1, 0x5a, 0x0b, 0xfc,
159 },
160 },
161 {
162 .in = "message digest",
163 .out = {
164 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5,
165 0x72, 0xb8, 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa,
166 0x21, 0x59, 0x5f, 0x36,
167 },
168 },
169 {
170 .in = "abcdefghijklmnopqrstuvwxyz",
171 .out = {
172 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b,
173 0x56, 0xbb, 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65,
174 0xb3, 0x70, 0x8d, 0xbc,
175 },
176 },
177 {
178 .in = "abcdbcdecdefdefgefghfghighijhijkijkljkl"
179 "mklmnlmnomnopnopq",
180 .out = {
181 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88,
182 0xe4, 0x05, 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a,
183 0xda, 0x62, 0xeb, 0x2b,
184 },
185 },
186 {
187 .in = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
188 "0123456789",
189 .out = {
190 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02,
191 0x86, 0xed, 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79,
192 0xb2, 0x1f, 0x51, 0x89,
193 },
194 },
195 {
196 .in = "1234567890123456789012345678901234567890"
197 "1234567890123456789012345678901234567890",
198 .out = {
199 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39,
200 0xf4, 0xdb, 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf,
201 0x63, 0x32, 0x6b, 0xfb,
202 },
203 },
204};
205
206#define N_RMD160_TESTS (sizeof(rmd160_tests) / sizeof(rmd160_tests[0]))
207
208static void
209rmd160_init(void *ctx)
210{
211 RMD160Init(ctx);
212}
213
214static void
215rmd160_update(void *ctx, const uint8_t *data, size_t len)
216{
217 RMD160Update(ctx, data, len);
218}
219
220static void
221rmd160_final(void *digest, void *ctx)
222{
223 RMD160Final(digest, ctx);
224}
225
226/* RFC 3174 - Appendix A (plus two zero-length tests) */
227static const struct hash_test_case sha1_tests[] = {
228 {
229 .out = {
230 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d,
231 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90,
232 0xaf, 0xd8, 0x07, 0x09,
233 },
234 },
235 {
236 .in = "",
237 .out = {
238 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d,
239 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90,
240 0xaf, 0xd8, 0x07, 0x09,
241 },
242 },
243 {
244 .in = "abc",
245 .out = {
246 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,
247 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
248 0x9c, 0xd0, 0xd8, 0x9d,
249 },
250 },
251 {
252 .in = "abcdbcdecdefdefgefghfghighijhi"
253 "jkijkljklmklmnlmnomnopnopq",
254 .out = {
255 0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, 0x6e,
256 0xba, 0xae, 0x4a, 0xa1, 0xf9, 0x51, 0x29, 0xe5,
257 0xe5, 0x46, 0x70, 0xf1,
258 },
259 },
260 {
261 .in = "0123456701234567012345670123456701234567012345670123456701234567"
262 "0123456701234567012345670123456701234567012345670123456701234567"
263 "0123456701234567012345670123456701234567012345670123456701234567"
264 "0123456701234567012345670123456701234567012345670123456701234567"
265 "0123456701234567012345670123456701234567012345670123456701234567"
266 "0123456701234567012345670123456701234567012345670123456701234567"
267 "0123456701234567012345670123456701234567012345670123456701234567"
268 "0123456701234567012345670123456701234567012345670123456701234567"
269 "0123456701234567012345670123456701234567012345670123456701234567"
270 "0123456701234567012345670123456701234567012345670123456701234567",
271 .out = {
272 0xde, 0xa3, 0x56, 0xa2, 0xcd, 0xdd, 0x90, 0xc7,
273 0xa7, 0xec, 0xed, 0xc5, 0xeb, 0xb5, 0x63, 0x93,
274 0x4f, 0x46, 0x04, 0x52,
275 },
276 },
277};
278
279#define N_SHA1_TESTS (sizeof(sha1_tests) / sizeof(sha1_tests[0]))
280
281static void
282sha1_init(void *ctx)
283{
284 SHA1Init(ctx);
285}
286
287static void
288sha1_update(void *ctx, const uint8_t *data, size_t len)
289{
290 SHA1Update(ctx, data, len);
291}
292
293static void
294sha1_final(void *digest, void *ctx)
295{
296 SHA1Final(digest, ctx);
297}
298
299static const struct hash_test_case sha224_tests[] = {
300 {
301 .out = {
302 0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9,
303 0x47, 0x61, 0x02, 0xbb, 0x28, 0x82, 0x34, 0xc4,
304 0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a,
305 0xc5, 0xb3, 0xe4, 0x2f,
306 },
307 },
308 {
309 .in = "",
310 .out = {
311 0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9,
312 0x47, 0x61, 0x02, 0xbb, 0x28, 0x82, 0x34, 0xc4,
313 0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a,
314 0xc5, 0xb3, 0xe4, 0x2f,
315 },
316 },
317 {
318 .in = "abc",
319 .out = {
320 0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8, 0x22,
321 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2, 0x55, 0xb3,
322 0x2a, 0xad, 0xbc, 0xe4, 0xbd, 0xa0, 0xb3, 0xf7,
323 0xe3, 0x6c, 0x9d, 0xa7,
324 },
325 },
326 {
327 .in = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
328 .out = {
329 0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76, 0xcc,
330 0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89, 0x01, 0x50,
331 0xb0, 0xc6, 0x45, 0x5c, 0xb4, 0xf5, 0x8b, 0x19,
332 0x52, 0x52, 0x25, 0x25,
333 },
334 },
335 {
336 .in = "0123456701234567012345670123456701234567012345670123456701234567"
337 "0123456701234567012345670123456701234567012345670123456701234567"
338 "0123456701234567012345670123456701234567012345670123456701234567"
339 "0123456701234567012345670123456701234567012345670123456701234567"
340 "0123456701234567012345670123456701234567012345670123456701234567"
341 "0123456701234567012345670123456701234567012345670123456701234567"
342 "0123456701234567012345670123456701234567012345670123456701234567"
343 "0123456701234567012345670123456701234567012345670123456701234567"
344 "0123456701234567012345670123456701234567012345670123456701234567"
345 "0123456701234567012345670123456701234567012345670123456701234567",
346 .out = {
347 0x56, 0x7f, 0x69, 0xf1, 0x68, 0xcd, 0x78, 0x44,
348 0xe6, 0x52, 0x59, 0xce, 0x65, 0x8f, 0xe7, 0xaa,
349 0xdf, 0xa2, 0x52, 0x16, 0xe6, 0x8e, 0xca, 0x0e,
350 0xb7, 0xab, 0x82, 0x62,
351 },
352 },
353 {
354 .in = "\x07",
355 .out = {
356 0x00, 0xec, 0xd5, 0xf1, 0x38, 0x42, 0x2b, 0x8a,
357 0xd7, 0x4c, 0x97, 0x99, 0xfd, 0x82, 0x6c, 0x53,
358 0x1b, 0xad, 0x2f, 0xca, 0xbc, 0x74, 0x50, 0xbe,
359 0xe2, 0xaa, 0x8c, 0x2a,
360 },
361 },
362};
363
364#define N_SHA224_TESTS (sizeof(sha224_tests) / sizeof(sha224_tests[0]))
365
366static void
367sha224_init(void *ctx)
368{
369 SHA224Init(ctx);
370}
371
372static void
373sha224_update(void *ctx, const uint8_t *data, size_t len)
374{
375 SHA224Update(ctx, data, len);
376}
377
378static void
379sha224_final(void *digest, void *ctx)
380{
381 SHA224Final(digest, ctx);
382}
383
384static const struct hash_test_case sha256_tests[] = {
385 {
386 .out = {
387 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
388 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
389 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
390 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
391 },
392 },
393 {
394 .in = "",
395 .out = {
396 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
397 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
398 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
399 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
400 },
401 },
402 {
403 .in = "abc",
404 .out = {
405 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
406 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
407 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
408 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD,
409 },
410 },
411 {
412 .in = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
413 .out = {
414 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
415 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
416 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
417 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1,
418 },
419 },
420 {
421 .in = "0123456701234567012345670123456701234567012345670123456701234567"
422 "0123456701234567012345670123456701234567012345670123456701234567"
423 "0123456701234567012345670123456701234567012345670123456701234567"
424 "0123456701234567012345670123456701234567012345670123456701234567"
425 "0123456701234567012345670123456701234567012345670123456701234567"
426 "0123456701234567012345670123456701234567012345670123456701234567"
427 "0123456701234567012345670123456701234567012345670123456701234567"
428 "0123456701234567012345670123456701234567012345670123456701234567"
429 "0123456701234567012345670123456701234567012345670123456701234567"
430 "0123456701234567012345670123456701234567012345670123456701234567",
431 .out = {
432 0x59, 0x48, 0x47, 0x32, 0x84, 0x51, 0xBD, 0xFA,
433 0x85, 0x05, 0x62, 0x25, 0x46, 0x2C, 0xC1, 0xD8,
434 0x67, 0xD8, 0x77, 0xFB, 0x38, 0x8D, 0xF0, 0xCE,
435 0x35, 0xF2, 0x5A, 0xB5, 0x56, 0x2B, 0xFB, 0xB5,
436 },
437 },
438 {
439 .in = "\x19",
440 .out = {
441 0x68, 0xaa, 0x2e, 0x2e, 0xe5, 0xdf, 0xf9, 0x6e,
442 0x33, 0x55, 0xe6, 0xc7, 0xee, 0x37, 0x3e, 0x3d,
443 0x6a, 0x4e, 0x17, 0xf7, 0x5f, 0x95, 0x18, 0xd8,
444 0x43, 0x70, 0x9c, 0x0c, 0x9b, 0xc3, 0xe3, 0xd4,
445 },
446 },
447};
448
449#define N_SHA256_TESTS (sizeof(sha256_tests) / sizeof(sha256_tests[0]))
450
451static void
452sha256_init(void *ctx)
453{
454 SHA256Init(ctx);
455}
456
457static void
458sha256_update(void *ctx, const uint8_t *data, size_t len)
459{
460 SHA256Update(ctx, data, len);
461}
462
463static void
464sha256_final(void *digest, void *ctx)
465{
466 SHA256Final(digest, ctx);
467}
468
469static const struct hash_test_case sha384_tests[] = {
470 {
471 .out = {
472 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38,
473 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a,
474 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43,
475 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda,
476 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb,
477 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b,
478 },
479 },
480 {
481 .in = "",
482 .out = {
483 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38,
484 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a,
485 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43,
486 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda,
487 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb,
488 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b,
489 },
490 },
491 {
492 .in = "abc",
493 .out = {
494 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
495 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
496 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
497 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED,
498 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23,
499 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7,
500 },
501 },
502 {
503 .in = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
504 "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
505 .out = {
506 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8,
507 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47,
508 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2,
509 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12,
510 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9,
511 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39,
512 },
513 },
514 {
515 .in = "0123456701234567012345670123456701234567012345670123456701234567"
516 "0123456701234567012345670123456701234567012345670123456701234567"
517 "0123456701234567012345670123456701234567012345670123456701234567"
518 "0123456701234567012345670123456701234567012345670123456701234567"
519 "0123456701234567012345670123456701234567012345670123456701234567"
520 "0123456701234567012345670123456701234567012345670123456701234567"
521 "0123456701234567012345670123456701234567012345670123456701234567"
522 "0123456701234567012345670123456701234567012345670123456701234567"
523 "0123456701234567012345670123456701234567012345670123456701234567"
524 "0123456701234567012345670123456701234567012345670123456701234567",
525 .out = {
526 0x2f, 0xc6, 0x4a, 0x4f, 0x50, 0x0d, 0xdb, 0x68,
527 0x28, 0xf6, 0xa3, 0x43, 0x0b, 0x8d, 0xd7, 0x2a,
528 0x36, 0x8e, 0xb7, 0xf3, 0xa8, 0x32, 0x2a, 0x70,
529 0xbc, 0x84, 0x27, 0x5b, 0x9c, 0x0b, 0x3a, 0xb0,
530 0x0d, 0x27, 0xa5, 0xcc, 0x3c, 0x2d, 0x22, 0x4a,
531 0xa6, 0xb6, 0x1a, 0x0d, 0x79, 0xfb, 0x45, 0x96,
532 },
533 },
534 {
535 .in = "\xb9",
536 .out = {
537 0xbc, 0x80, 0x89, 0xa1, 0x90, 0x07, 0xc0, 0xb1,
538 0x41, 0x95, 0xf4, 0xec, 0xc7, 0x40, 0x94, 0xfe,
539 0xc6, 0x4f, 0x01, 0xf9, 0x09, 0x29, 0x28, 0x2c,
540 0x2f, 0xb3, 0x92, 0x88, 0x15, 0x78, 0x20, 0x8a,
541 0xd4, 0x66, 0x82, 0x8b, 0x1c, 0x6c, 0x28, 0x3d,
542 0x27, 0x22, 0xcf, 0x0a, 0xd1, 0xab, 0x69, 0x38,
543 },
544 },
545};
546
547#define N_SHA384_TESTS (sizeof(sha384_tests) / sizeof(sha384_tests[0]))
548
549static void
550sha384_init(void *ctx)
551{
552 SHA384Init(ctx);
553}
554
555static void
556sha384_update(void *ctx, const uint8_t *data, size_t len)
557{
558 SHA384Update(ctx, data, len);
559}
560
561static void
562sha384_final(void *digest, void *ctx)
563{
564 SHA384Final(digest, ctx);
565}
566
567static const struct hash_test_case sha512_tests[] = {
568 {
569 .out = {
570 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
571 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
572 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
573 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
574 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
575 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
576 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
577 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e,
578 },
579 },
580 {
581 .in = "",
582 .out = {
583 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
584 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
585 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
586 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
587 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
588 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
589 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
590 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e,
591 },
592 },
593 {
594 .in = "abc",
595 .out = {
596 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
597 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
598 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
599 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
600 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
601 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
602 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
603 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f,
604 },
605 },
606 {
607 .in = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
608 "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
609 .out = {
610 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
611 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
612 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
613 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
614 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
615 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
616 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
617 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09,
618 },
619 },
620 {
621 .in = "0123456701234567012345670123456701234567012345670123456701234567"
622 "0123456701234567012345670123456701234567012345670123456701234567"
623 "0123456701234567012345670123456701234567012345670123456701234567"
624 "0123456701234567012345670123456701234567012345670123456701234567"
625 "0123456701234567012345670123456701234567012345670123456701234567"
626 "0123456701234567012345670123456701234567012345670123456701234567"
627 "0123456701234567012345670123456701234567012345670123456701234567"
628 "0123456701234567012345670123456701234567012345670123456701234567"
629 "0123456701234567012345670123456701234567012345670123456701234567"
630 "0123456701234567012345670123456701234567012345670123456701234567",
631 .out = {
632 0x89, 0xd0, 0x5b, 0xa6, 0x32, 0xc6, 0x99, 0xc3,
633 0x12, 0x31, 0xde, 0xd4, 0xff, 0xc1, 0x27, 0xd5,
634 0xa8, 0x94, 0xda, 0xd4, 0x12, 0xc0, 0xe0, 0x24,
635 0xdb, 0x87, 0x2d, 0x1a, 0xbd, 0x2b, 0xa8, 0x14,
636 0x1a, 0x0f, 0x85, 0x07, 0x2a, 0x9b, 0xe1, 0xe2,
637 0xaa, 0x04, 0xcf, 0x33, 0xc7, 0x65, 0xcb, 0x51,
638 0x08, 0x13, 0xa3, 0x9c, 0xd5, 0xa8, 0x4c, 0x4a,
639 0xca, 0xa6, 0x4d, 0x3f, 0x3f, 0xb7, 0xba, 0xe9,
640 },
641 },
642 {
643 .in = "\xd0",
644 .out = {
645 0x99, 0x92, 0x20, 0x29, 0x38, 0xe8, 0x82, 0xe7,
646 0x3e, 0x20, 0xf6, 0xb6, 0x9e, 0x68, 0xa0, 0xa7,
647 0x14, 0x90, 0x90, 0x42, 0x3d, 0x93, 0xc8, 0x1b,
648 0xab, 0x3f, 0x21, 0x67, 0x8d, 0x4a, 0xce, 0xee,
649 0xe5, 0x0e, 0x4e, 0x8c, 0xaf, 0xad, 0xa4, 0xc8,
650 0x5a, 0x54, 0xea, 0x83, 0x06, 0x82, 0x6c, 0x4a,
651 0xd6, 0xe7, 0x4c, 0xec, 0xe9, 0x63, 0x1b, 0xfa,
652 0x8a, 0x54, 0x9b, 0x4a, 0xb3, 0xfb, 0xba, 0x15,
653 },
654 },
655};
656
657#define N_SHA512_TESTS (sizeof(sha512_tests) / sizeof(sha512_tests[0]))
658
659static void
660sha512_init(void *ctx)
661{
662 SHA512Init(ctx);
663}
664
665static void
666sha512_update(void *ctx, const uint8_t *data, size_t len)
667{
668 SHA512Update(ctx, data, len);
669}
670
671static void
672sha512_final(void *digest, void *ctx)
673{
674 SHA512Final(digest, ctx);
675}
676
677static const struct hash_test_case sha512_256_tests[] = {
678 {
679 .out = {
680 0xc6, 0x72, 0xb8, 0xd1, 0xef, 0x56, 0xed, 0x28,
681 0xab, 0x87, 0xc3, 0x62, 0x2c, 0x51, 0x14, 0x06,
682 0x9b, 0xdd, 0x3a, 0xd7, 0xb8, 0xf9, 0x73, 0x74,
683 0x98, 0xd0, 0xc0, 0x1e, 0xce, 0xf0, 0x96, 0x7a,
684 },
685 },
686 {
687 .in = "",
688 .out = {
689 0xc6, 0x72, 0xb8, 0xd1, 0xef, 0x56, 0xed, 0x28,
690 0xab, 0x87, 0xc3, 0x62, 0x2c, 0x51, 0x14, 0x06,
691 0x9b, 0xdd, 0x3a, 0xd7, 0xb8, 0xf9, 0x73, 0x74,
692 0x98, 0xd0, 0xc0, 0x1e, 0xce, 0xf0, 0x96, 0x7a,
693 },
694 },
695 {
696 .in = "abc",
697 .out = {
698 0x53, 0x04, 0x8e, 0x26, 0x81, 0x94, 0x1e, 0xf9,
699 0x9b, 0x2e, 0x29, 0xb7, 0x6b, 0x4c, 0x7d, 0xab,
700 0xe4, 0xc2, 0xd0, 0xc6, 0x34, 0xfc, 0x6d, 0x46,
701 0xe0, 0xe2, 0xf1, 0x31, 0x07, 0xe7, 0xaf, 0x23,
702 },
703 },
704 {
705 .in = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
706 "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
707 .out = {
708 0x39, 0x28, 0xe1, 0x84, 0xfb, 0x86, 0x90, 0xf8,
709 0x40, 0xda, 0x39, 0x88, 0x12, 0x1d, 0x31, 0xbe,
710 0x65, 0xcb, 0x9d, 0x3e, 0xf8, 0x3e, 0xe6, 0x14,
711 0x6f, 0xea, 0xc8, 0x61, 0xe1, 0x9b, 0x56, 0x3a,
712 },
713 },
714 {
715 .in = "0123456701234567012345670123456701234567012345670123456701234567"
716 "0123456701234567012345670123456701234567012345670123456701234567"
717 "0123456701234567012345670123456701234567012345670123456701234567"
718 "0123456701234567012345670123456701234567012345670123456701234567"
719 "0123456701234567012345670123456701234567012345670123456701234567"
720 "0123456701234567012345670123456701234567012345670123456701234567"
721 "0123456701234567012345670123456701234567012345670123456701234567"
722 "0123456701234567012345670123456701234567012345670123456701234567"
723 "0123456701234567012345670123456701234567012345670123456701234567"
724 "0123456701234567012345670123456701234567012345670123456701234567",
725 .out = {
726 0xcf, 0x78, 0xe4, 0xba, 0x93, 0x5b, 0x4d, 0x9e,
727 0xb9, 0x10, 0x52, 0xae, 0xdd, 0xf8, 0xe2, 0xd6,
728 0x06, 0xc5, 0x90, 0xf7, 0x08, 0x57, 0x36, 0x93,
729 0xea, 0x94, 0xbe, 0x82, 0x6a, 0x66, 0x6e, 0xe4,
730 },
731 },
732};
733
734#define N_SHA512_256_TESTS (sizeof(sha512_256_tests) / sizeof(sha512_256_tests[0]))
735
736static void
737sha512_256_init(void *ctx)
738{
739 SHA512_256Init(ctx);
740}
741
742static void
743sha512_256_update(void *ctx, const uint8_t *data, size_t len)
744{
745 SHA512_256Update(ctx, data, len);
746}
747
748static void
749sha512_256_final(void *digest, void *ctx)
750{
751 SHA512_256Final(digest, ctx);
752}
753
754struct hash_ctx {
755 uint8_t *digest;
756 size_t digest_len;
757 void *ctx;
758 void (*init)(void *);
759 void (*update)(void *, const uint8_t *, size_t);
760 void (*final)(void *, void *);
761};
762
763static const struct hash_tests {
764 const char *name;
765 size_t num_tests;
766 const struct hash_test_case *tests;
767} hash_tests[] = {
768 [hash_md5] = {
769 .name = "RFC 1321 MD5",
770 .num_tests = N_MD5_TESTS,
771 .tests = md5_tests,
772 },
773 [hash_rmd160] = {
774 .name = "Bosselaers RMD160",
775 .num_tests = N_RMD160_TESTS,
776 .tests = rmd160_tests,
777 },
778 [hash_sha1] = {
779 .name = "RFC 3174 SHA1",
780 .num_tests = N_SHA1_TESTS,
781 .tests = sha1_tests,
782 },
783 [hash_sha224] = {
784 .name = "RFC 6234 SHA224",
785 .num_tests = N_SHA224_TESTS,
786 .tests = sha224_tests,
787 },
788 [hash_sha256] = {
789 .name = "RFC 6234 SHA256",
790 .num_tests = N_SHA256_TESTS,
791 .tests = sha256_tests,
792 },
793 [hash_sha384] = {
794 .name = "RFC 6234 SHA384",
795 .num_tests = N_SHA384_TESTS,
796 .tests = sha384_tests,
797 },
798 [hash_sha512] = {
799 .name = "RFC 6234 SHA512",
800 .num_tests = N_SHA512_TESTS,
801 .tests = sha512_tests,
802 },
803 [hash_sha512_256] = {
804 .name = "RFC 6234 SHA512_256 (generated)",
805 .num_tests = N_SHA512_256_TESTS,
806 .tests = sha512_256_tests,
807 },
808};
809
810static int
811hash_test_case(struct hash_ctx *ctx, const struct hash_test_case *tc,
812 const char *name, size_t testno)
813{
814 size_t in_len = tc->in != NULL ? strlen(tc->in) : 0;
815
816 ctx->init(ctx->ctx);
817 ctx->update(ctx->ctx, (const uint8_t *)tc->in, in_len);
818 ctx->final(ctx->digest, ctx->ctx);
819
820 if (memcmp(tc->out, ctx->digest, ctx->digest_len) != 0) {
821 fprintf(stderr, "FAIL: %s test %zu\n", name, testno);
822 return 1;
823 }
824
825 return 0;
826}
827
828static int
829hash_test(struct hash_ctx *ctx, const struct hash_tests *tests)
830{
831 size_t i;
832 int failed = 0;
833
834 for (i = 0; i < tests->num_tests; i++) {
835 const struct hash_test_case *tc = &tests->tests[i];
836
837 failed |= hash_test_case(ctx, tc, tests->name, i);
838 }
839
840 return failed;
841}
842
843int
844main(void)
845{
846 uint8_t md5_digest[MD5_DIGEST_LENGTH];
847 uint8_t rmd160_digest[RMD160_DIGEST_LENGTH];
848 uint8_t sha1_digest[SHA1_DIGEST_LENGTH];
849 uint8_t sha224_digest[SHA224_DIGEST_LENGTH];
850 uint8_t sha256_digest[SHA256_DIGEST_LENGTH];
851 uint8_t sha384_digest[SHA384_DIGEST_LENGTH];
852 uint8_t sha512_digest[SHA512_DIGEST_LENGTH];
853 uint8_t sha512_256_digest[SHA512_256_DIGEST_LENGTH];
854 MD5_CTX md5_ctx;
855 RMD160_CTX rmd160_ctx;
856 SHA1_CTX sha1_ctx;
857 SHA2_CTX sha224_ctx;
858 SHA2_CTX sha256_ctx;
859 SHA2_CTX sha384_ctx;
860 SHA2_CTX sha512_ctx;
861 SHA2_CTX sha512_256_ctx;
862 struct hash_ctx ctx[] = {
863 [hash_md5] = {
864 .digest = md5_digest,
865 .digest_len = sizeof(md5_digest),
866 .ctx = &md5_ctx,
867 .init = md5_init,
868 .update = md5_update,
869 .final = md5_final,
870 },
871 [hash_rmd160] = {
872 .digest = rmd160_digest,
873 .digest_len = sizeof(rmd160_digest),
874 .ctx = &rmd160_ctx,
875 .init = rmd160_init,
876 .update = rmd160_update,
877 .final = rmd160_final,
878 },
879 [hash_sha1] = {
880 .digest = sha1_digest,
881 .digest_len = sizeof(sha1_digest),
882 .ctx = &sha1_ctx,
883 .init = sha1_init,
884 .update = sha1_update,
885 .final = sha1_final,
886 },
887 [hash_sha224] = {
888 .digest = sha224_digest,
889 .digest_len = sizeof(sha224_digest),
890 .ctx = &sha224_ctx,
891 .init = sha224_init,
892 .update = sha224_update,
893 .final = sha224_final,
894 },
895 [hash_sha256] = {
896 .digest = sha256_digest,
897 .digest_len = sizeof(sha256_digest),
898 .ctx = &sha256_ctx,
899 .init = sha256_init,
900 .update = sha256_update,
901 .final = sha256_final,
902 },
903 [hash_sha384] = {
904 .digest = sha384_digest,
905 .digest_len = sizeof(sha384_digest),
906 .ctx = &sha384_ctx,
907 .init = sha384_init,
908 .update = sha384_update,
909 .final = sha384_final,
910 },
911 [hash_sha512] = {
912 .digest = sha512_digest,
913 .digest_len = sizeof(sha512_digest),
914 .ctx = &sha512_ctx,
915 .init = sha512_init,
916 .update = sha512_update,
917 .final = sha512_final,
918 },
919 [hash_sha512_256] = {
920 .digest = sha512_256_digest,
921 .digest_len = sizeof(sha512_256_digest),
922 .ctx = &sha512_256_ctx,
923 .init = sha512_256_init,
924 .update = sha512_256_update,
925 .final = sha512_256_final,
926 },
927 };
928 int i;
929 int failed = 0;
930
931 for (i = 0; i < NUM_HASHES; i++)
932 failed |= hash_test(&ctx[i], &hash_tests[i]);
933
934 return failed;
935}
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..c2c24202c3
--- /dev/null
+++ b/src/regress/lib/libc/illumos/oclo/Makefile
@@ -0,0 +1,16 @@
1# $OpenBSD: Makefile,v 1.1.1.1 2025/08/02 06:16:34 tb 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
13.PATH: /usr/local/share/illumos-os-tests/tests/oclo
14.endif
15
16.include <bsd.regress.mk>
diff --git a/src/regress/lib/libc/malloc/malloc_errs/malloc_errs.c b/src/regress/lib/libc/malloc/malloc_errs/malloc_errs.c
index 486c247f0d..57d799f49d 100644
--- a/src/regress/lib/libc/malloc/malloc_errs/malloc_errs.c
+++ b/src/regress/lib/libc/malloc/malloc_errs/malloc_errs.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: malloc_errs.c,v 1.5 2024/04/14 17:47:41 otto Exp $ */ 1/* $OpenBSD: malloc_errs.c,v 1.6 2025/05/24 06:40:29 otto Exp $ */
2/* 2/*
3 * Copyright (c) 2023 Otto Moerbeek <otto@drijf.net> 3 * Copyright (c) 2023 Otto Moerbeek <otto@drijf.net>
4 * 4 *
@@ -286,11 +286,10 @@ int main(int argc, char *argv[])
286 int i, status; 286 int i, status;
287 pid_t pid; 287 pid_t pid;
288 char num[10]; 288 char num[10];
289 char options[10]; 289 char options[40];
290 extern char* malloc_options; 290 char const *env[2];
291 291
292 if (argc == 3) { 292 if (argc == 2) {
293 malloc_options = argv[2];
294 /* prevent coredumps */ 293 /* prevent coredumps */
295 setrlimit(RLIMIT_CORE, &lim); 294 setrlimit(RLIMIT_CORE, &lim);
296 i = atoi(argv[1]); 295 i = atoi(argv[1]);
@@ -303,9 +302,11 @@ int main(int argc, char *argv[])
303 pid = fork(); 302 pid = fork();
304 switch (pid) { 303 switch (pid) {
305 case 0: 304 case 0:
306 snprintf(options, sizeof(options), "us%s", tests[i].flags); 305 snprintf(options, sizeof(options), "MALLOC_OPTIONS=us%s", tests[i].flags);
307 snprintf(num, sizeof(num), "%d", i); 306 snprintf(num, sizeof(num), "%d", i);
308 execl(argv[0], argv[0], num, options, NULL); 307 env[0] = options;
308 env[1] = NULL;
309 execle(argv[0], argv[0], num, NULL, env);
309 err(1, "exec"); 310 err(1, "exec");
310 break; 311 break;
311 case -1: 312 case -1:
diff --git a/src/regress/lib/libc/malloc/malloc_ulimit1/malloc_ulimit1.c b/src/regress/lib/libc/malloc/malloc_ulimit1/malloc_ulimit1.c
index 799d2b9117..7e53c32dbc 100644
--- a/src/regress/lib/libc/malloc/malloc_ulimit1/malloc_ulimit1.c
+++ b/src/regress/lib/libc/malloc/malloc_ulimit1/malloc_ulimit1.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: malloc_ulimit1.c,v 1.5 2019/06/12 11:31:36 bluhm Exp $ */ 1/* $OpenBSD: malloc_ulimit1.c,v 1.6 2025/05/24 06:47:27 otto Exp $ */
2 2
3/* Public Domain, 2006, Otto Moerbeek <otto@drijf.net> */ 3/* Public Domain, 2006, Otto Moerbeek <otto@drijf.net> */
4 4
@@ -23,7 +23,7 @@
23#define FACTOR 1024 23#define FACTOR 1024
24 24
25/* This test takes forever with junking turned on. */ 25/* This test takes forever with junking turned on. */
26char *malloc_options = "jj"; 26const char * const malloc_options = "jj";
27 27
28int 28int
29main() 29main()
diff --git a/src/regress/lib/libc/stdio/Makefile b/src/regress/lib/libc/stdio/Makefile
new file mode 100644
index 0000000000..f1e980f688
--- /dev/null
+++ b/src/regress/lib/libc/stdio/Makefile
@@ -0,0 +1,29 @@
1# $OpenBSD: Makefile,v 1.4 2025/06/03 14:35:27 yasuoka Exp $
2
3PROGS= test_fflush
4CLEANFILES= test_fflush.tmp
5
6PROGS+= test_ungetwc
7CLEANFILES+= test_ungetwc.tmp
8
9PROGS+= test___freading
10CLEANFILES+= test___freading.tmp
11
12PROGS+= test___fwriting
13CLEANFILES+= test___fwriting.tmp
14
15PROGS+= test___fpending
16CLEANFILES+= test___fpending.tmp
17
18PROGS+= test___freadahead
19CLEANFILES+= test___freadahead.tmp
20
21PROGS+= test___freadptr
22CLEANFILES+= test___freadptr.tmp
23
24PROGS+= test___fseterr
25CLEANFILES+= test___fseterr.tmp
26
27WARNINGS= yes
28
29.include <bsd.regress.mk>
diff --git a/src/regress/lib/libc/stdio/test___fpending.c b/src/regress/lib/libc/stdio/test___fpending.c
new file mode 100644
index 0000000000..96ace2e481
--- /dev/null
+++ b/src/regress/lib/libc/stdio/test___fpending.c
@@ -0,0 +1,58 @@
1/* $OpenBSD: test___fpending.c,v 1.1 2025/05/25 00:20:54 yasuoka Exp $ */
2
3/*
4 * Copyright (c) 2025 YASUOKA Masahiko <yasuoka@yasuoka.net>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <assert.h>
20#include <stdio.h>
21#include <stdio_ext.h>
22#include <stdlib.h>
23
24/* we use assert() */
25#undef NDEBUG
26
27#define TMPFILENAME "test___fpending.tmp"
28
29void test___fpending0(void);
30
31void
32test___fpending0(void)
33{
34 FILE *fp;
35 int r;
36 size_t s;
37
38 fp = fopen(TMPFILENAME, "w");
39 assert(fp != NULL);
40 r = fputs("Hello world", fp);
41 assert(r >= 0);
42 s = __fpending(fp);
43 assert(s > 0); /* assume buffered */
44 r = fflush(fp);
45 assert(r == 0);
46 s = __fpending(fp);
47 assert(s == 0); /* buffer must be 0 */
48 r = fclose(fp);
49 assert(r == 0);
50}
51
52int
53main(int argc, char *argv[])
54{
55 test___fpending0();
56
57 exit(0);
58}
diff --git a/src/regress/lib/libc/stdio/test___freadahead.c b/src/regress/lib/libc/stdio/test___freadahead.c
new file mode 100644
index 0000000000..66d5e3492a
--- /dev/null
+++ b/src/regress/lib/libc/stdio/test___freadahead.c
@@ -0,0 +1,71 @@
1/* $OpenBSD: test___freadahead.c,v 1.2 2025/06/03 14:35:27 yasuoka Exp $ */
2
3/*
4 * Copyright (c) 2025 YASUOKA Masahiko <yasuoka@yasuoka.net>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <assert.h>
20#include <errno.h>
21#include <stdio.h>
22#include <stdio_ext.h>
23#include <stdlib.h>
24
25/* we use assert() */
26#undef NDEBUG
27
28#define TMPFILENAME "test___freadahead.tmp"
29
30void test___freadahead0(void);
31
32void
33test___freadahead0(void)
34{
35 FILE *fp;
36 int r;
37 size_t s;
38
39 fp = fopen(TMPFILENAME, "w");
40 assert(fp != NULL);
41 r = fputs("Hello world", fp);
42 assert(r >= 0);
43 r = fclose(fp);
44
45 fp = fopen(TMPFILENAME, "r");
46 s = __freadahead(fp);
47 assert(s == 0);
48 assert(fgetc(fp) == 'H');
49 s = __freadahead(fp);
50 assert(s == 10);
51 r = fflush(fp);
52#if 0
53 /* fflush() to reading file is not supported (yet) */
54 assert(errno == EBADF);
55#else
56 assert(r == 0);
57 s = __freadahead(fp);
58 assert(s == 0);
59#endif
60
61 r = fclose(fp);
62 assert(r == 0);
63}
64
65int
66main(int argc, char *argv[])
67{
68 test___freadahead0();
69
70 exit(0);
71}
diff --git a/src/regress/lib/libc/stdio/test___freading.c b/src/regress/lib/libc/stdio/test___freading.c
new file mode 100644
index 0000000000..f74eb78d35
--- /dev/null
+++ b/src/regress/lib/libc/stdio/test___freading.c
@@ -0,0 +1,125 @@
1/* $OpenBSD: test___freading.c,v 1.2 2025/06/12 07:39:26 yasuoka Exp $ */
2
3/*
4 * Copyright (c) 2025 YASUOKA Masahiko <yasuoka@yasuoka.net>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <assert.h>
20#include <stdio.h>
21#include <stdio_ext.h>
22#include <stdlib.h>
23#include <string.h>
24#include <unistd.h>
25
26/* we use assert() */
27#undef NDEBUG
28
29#define TMPFILENAME "test___freading.tmp"
30
31void setup(void);
32
33void test___freading0(void);
34void test___freading1(void);
35void test___freading2(void);
36
37void
38setup(void)
39{
40 FILE *fp;
41
42 /* common setup */
43 unlink(TMPFILENAME);
44 fp = fopen(TMPFILENAME, "w+");
45 assert(fp != NULL);
46 fputs("Hello world\n", fp);
47 fclose(fp);
48}
49
50void
51test___freading0(void)
52{
53 FILE *fp;
54 int r;
55 char buf[80];
56
57 fp = popen("echo Hello world", "r");
58 assert(fp != NULL);
59 assert(__freading(fp) != 0);
60 assert(fgets(buf, sizeof(buf), fp) != NULL);
61 assert(strcmp(buf, "Hello world\n") == 0);
62 r = pclose(fp);
63 assert(r == 0);
64}
65
66void
67test___freading1(void)
68{
69 FILE *fp;
70 int r;
71
72 /* when the last operaiton is read, __freading() returns true */
73 fp = fopen(TMPFILENAME, "w+");
74 assert(fp != NULL);
75 assert(__freading(fp) == 0);
76 r = fputs("Hello world\n", fp);
77 assert(r >= 0);
78 assert(__freading(fp) == 0);
79 rewind(fp);
80 assert(fgetc(fp) == 'H');
81 assert(__freading(fp) != 0);
82 /* write */
83 fseek(fp, 0, SEEK_END);
84 r = fputs("\n", fp);
85 assert(__freading(fp) == 0);
86 /* ungetc */
87 rewind(fp);
88 assert(ungetc('X', fp) != 0);
89 assert(__freading(fp) != 0); /* reading */
90
91 r = fclose(fp);
92 assert(r == 0);
93}
94
95void
96test___freading2(void)
97{
98 int r;
99 FILE *fp;
100
101 /*
102 * until v1.10 of fpurge.c mistakenly enables the writing buffer
103 * without _SRD flag set.
104 */
105 fp = fopen(TMPFILENAME, "r+");
106 assert(fp != NULL);
107 assert(fgetc(fp) == 'H');
108 fpurge(fp);
109 fseek(fp, 0, SEEK_CUR);
110 assert(fputc('X', fp) == 'X');
111 assert(__freading(fp) == 0);
112
113 r = fclose(fp);
114 assert(r == 0);
115}
116
117int
118main(int argc, char *argv[])
119{
120 test___freading0();
121 test___freading1();
122 test___freading2();
123
124 exit(0);
125}
diff --git a/src/regress/lib/libc/stdio/test___freadptr.c b/src/regress/lib/libc/stdio/test___freadptr.c
new file mode 100644
index 0000000000..cce362f2ae
--- /dev/null
+++ b/src/regress/lib/libc/stdio/test___freadptr.c
@@ -0,0 +1,78 @@
1/* $OpenBSD: test___freadptr.c,v 1.1 2025/05/25 00:20:54 yasuoka Exp $ */
2
3/*
4 * Copyright (c) 2025 YASUOKA Masahiko <yasuoka@yasuoka.net>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/types.h>
20#include <assert.h>
21#include <stdio.h>
22#include <stdio_ext.h>
23#include <stdlib.h>
24#include <string.h>
25
26/* we use assert() */
27#undef NDEBUG
28
29#define TMPFILENAME "test___freadptr.tmp"
30
31void test___freadptr0(void);
32
33/* test __freadptr() and __freadptrinc() */
34void
35test___freadptr0(void)
36{
37 FILE *fp;
38 int r;
39 ssize_t s;
40 const char *p;
41
42 fp = fopen(TMPFILENAME, "w");
43 assert(fp != NULL);
44 r = fputs("Hello world", fp);
45 assert(r >= 0);
46 r = fclose(fp);
47
48 fp = fopen(TMPFILENAME, "r");
49 assert(fgetc(fp) == 'H');
50 p = __freadptr(fp, &s);
51 assert(p != NULL);
52 assert(s > 4); /* this test assume this (not by the spec) */
53 assert(*p == 'e');
54 assert(strncmp(p, "ello world", s) == 0);
55
56 __freadptrinc(fp, 4);
57 assert(fgetc(fp) == ' ');
58
59 ungetc('A', fp);
60 ungetc('A', fp);
61 ungetc('A', fp);
62 p = __freadptr(fp, &s);
63 assert(s > 0);
64 assert(*p == 'A');
65 /* ptr will contains only the pushback buffer */
66 assert(strncmp(p, "AAAworld", s) == 0);
67
68 r = fclose(fp);
69 assert(r == 0);
70}
71
72int
73main(int argc, char *argv[])
74{
75 test___freadptr0();
76
77 exit(0);
78}
diff --git a/src/regress/lib/libc/stdio/test___fseterr.c b/src/regress/lib/libc/stdio/test___fseterr.c
new file mode 100644
index 0000000000..70fb491c6c
--- /dev/null
+++ b/src/regress/lib/libc/stdio/test___fseterr.c
@@ -0,0 +1,60 @@
1/* $OpenBSD: test___fseterr.c,v 1.1 2025/05/25 00:20:54 yasuoka Exp $ */
2
3/*
4 * Copyright (c) 2025 YASUOKA Masahiko <yasuoka@yasuoka.net>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <assert.h>
20#include <stdio.h>
21#include <stdio_ext.h>
22#include <stdlib.h>
23
24/* we use assert() */
25#undef NDEBUG
26
27#define TMPFILENAME "test___fseterr.tmp"
28
29void test___fseterr0(void);
30
31void
32test___fseterr0(void)
33{
34 FILE *fp;
35 int r;
36
37 fp = fopen(TMPFILENAME, "w+");
38 assert(fp != NULL);
39
40 assert(!ferror(fp));
41
42 r = fprintf(fp, "hello world\n");
43 assert(r > 0);
44
45 __fseterr(fp);
46 assert(ferror(fp));
47
48 r = fprintf(fp, "hello world\n");
49 assert(r == -1);
50
51 fclose(fp);
52}
53
54int
55main(int argc, char *argv[])
56{
57 test___fseterr0();
58
59 exit(0);
60}
diff --git a/src/regress/lib/libc/stdio/test___fwriting.c b/src/regress/lib/libc/stdio/test___fwriting.c
new file mode 100644
index 0000000000..eb4671d3cf
--- /dev/null
+++ b/src/regress/lib/libc/stdio/test___fwriting.c
@@ -0,0 +1,83 @@
1/* $OpenBSD: test___fwriting.c,v 1.1 2025/05/25 00:20:54 yasuoka Exp $ */
2
3/*
4 * Copyright (c) 2025 YASUOKA Masahiko <yasuoka@yasuoka.net>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <assert.h>
20#include <stdio.h>
21#include <stdio_ext.h>
22#include <stdlib.h>
23
24/* we use assert() */
25#undef NDEBUG
26
27#define TMPFILENAME "test___fwriting.tmp"
28
29void test___fwriting0(void);
30void test___fwriting1(void);
31
32void
33test___fwriting0(void)
34{
35 FILE *fp;
36 int r;
37
38 fp = fopen(TMPFILENAME, "w"); /* write only */
39 assert(fp != NULL);
40 assert(__fwriting(fp) != 0); /* writing is true immediately */
41 r = fputs("Hello world\n", fp);
42 assert(r >= 0);
43 r = fclose(fp);
44 assert(r == 0);
45
46 fp = fopen(TMPFILENAME, "a"); /* append only */
47 assert(fp != NULL);
48 assert(__fwriting(fp) != 0); /* writing immediately */
49 r = fclose(fp);
50 assert(r == 0);
51}
52
53void
54test___fwriting1(void)
55{
56 FILE *fp;
57 int r;
58
59 fp = fopen(TMPFILENAME, "w+"); /* read / write */
60 assert(fp != NULL);
61 r = fputs("Hello world\n", fp);
62 assert(r >= 0);
63 assert(__fwriting(fp) != 0);
64 rewind(fp);
65 assert(fgetc(fp) == 'H'); /* read */
66 assert(__fwriting(fp) == 0); /* writing becomes false */
67 fputc('e', fp);
68 assert(__fwriting(fp) != 0); /* writing becomes true */
69 ungetc('e', fp);
70 assert(__fwriting(fp) == 0); /* ungetc -> writing becomes false */
71
72 r = fclose(fp);
73 assert(r == 0);
74}
75
76int
77main(int argc, char *argv[])
78{
79 test___fwriting0();
80 test___fwriting1();
81
82 exit(0);
83}
diff --git a/src/regress/lib/libc/stdio/test_fflush.c b/src/regress/lib/libc/stdio/test_fflush.c
new file mode 100644
index 0000000000..a0586b7d14
--- /dev/null
+++ b/src/regress/lib/libc/stdio/test_fflush.c
@@ -0,0 +1,345 @@
1/* $OpenBSD: test_fflush.c,v 1.3 2025/06/08 08:53:53 yasuoka Exp $ */
2
3/*
4 * Copyright (c) 2025 YASUOKA Masahiko <yasuoka@yasuoka.net>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <assert.h>
20#include <locale.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <unistd.h>
25#include <wchar.h>
26
27/* we use assert() */
28#undef NDEBUG
29
30#define TMPFILENAME "test_fflush.tmp"
31
32void setup(void);
33
34void test_fflush_read0(void);
35void test_fflush_read1(void);
36void test_fflush_read2(void);
37void test_fflush_read3(void);
38void test_fflush_read4(void);
39void setupw(void);
40void test_fflush_read5(void);
41void test_fflush_read6(void);
42
43void
44setup(void)
45{
46 FILE *fp;
47
48 /* common setup */
49 unlink(TMPFILENAME);
50 fp = fopen(TMPFILENAME, "w+");
51 assert(fp != NULL);
52 fputs("Hello world\n", fp);
53 fclose(fp);
54}
55
56/* fflush work with reading file and seekable */
57void
58test_fflush_read0(void)
59{
60 int r;
61 char buf[80];
62 FILE *fp;
63
64 setup();
65
66 /* In POSIX 2008, fflush() must work with the file object for reading */
67 fp = fopen(TMPFILENAME, "r");
68 assert(fp != NULL);
69 assert(fgetc(fp) == 'H');
70 r = fflush(fp);
71 assert(r == 0);
72
73 /* the position is moved to 1 */
74 assert(ftell(fp) == 1);
75
76 /* can read rest of that */
77 fgets(buf, sizeof(buf), fp);
78 assert(strcmp(buf, "ello world\n") == 0);
79 r = fclose(fp);
80 assert(r == 0);
81}
82
83/* fflush work with reading file and seekable + unget */
84void
85test_fflush_read1(void)
86{
87 int r;
88 char buf[80];
89 FILE *fp;
90
91 setup();
92
93 fp = fopen(TMPFILENAME, "r");
94 assert(fp != NULL);
95 assert(fgetc(fp) == 'H');
96 assert(fgetc(fp) == 'e');
97 assert(fgetc(fp) == 'l');
98 assert(fgetc(fp) == 'l');
99 assert(fgetc(fp) == 'o');
100
101 /* push the 'AAAA' back */
102 ungetc('A', fp);
103 ungetc('A', fp);
104 ungetc('A', fp);
105 ungetc('A', fp);
106
107 /* can read rest of that */
108 fgets(buf, sizeof(buf), fp);
109 assert(strcmp(buf, "AAAA world\n") == 0);
110 r = fclose(fp);
111 assert(r == 0);
112
113 /* do the same thing + fflush */
114
115 fp = fopen(TMPFILENAME, "r");
116 assert(fp != NULL);
117 assert(fgetc(fp) == 'H');
118 assert(fgetc(fp) == 'e');
119 assert(fgetc(fp) == 'l');
120 assert(fgetc(fp) == 'l');
121 assert(fgetc(fp) == 'o');
122
123 /* push 'AAAA' back */
124 ungetc('A', fp);
125 ungetc('A', fp);
126 ungetc('A', fp);
127 ungetc('A', fp);
128
129 /* then fflush */
130 r = fflush(fp);
131 assert(r == 0);
132
133 /* fllush() clears the all pushed back chars */
134
135 /* can read rest of that */
136 fgets(buf, sizeof(buf), fp);
137 assert(strcmp(buf, " world\n") == 0);
138 r = fclose(fp);
139 assert(r == 0);
140}
141
142/* fflush() to reading and non-seekable stream */
143void
144test_fflush_read2(void)
145{
146 int r;
147 FILE *fp;
148 char buf[80];
149
150 /* In POSIX-2008, fflush() must work with the file object for reading */
151 fp = popen("echo Hello world", "r");
152 assert(fp != NULL);
153 assert(fgetc(fp) == 'H');
154 r = fflush(fp);
155 assert(r == 0);
156
157 /*
158 * FILE object for read and NOT seekable. In that case, fflush does
159 * nothing, but must keep the buffer.
160 */
161
162 /* can read rest of that */
163 fgets(buf, sizeof(buf), fp);
164 assert(strcmp(buf, "ello world\n") == 0);
165 r = pclose(fp);
166 assert(r == 0);
167}
168
169/* fflush() to the file which doesn't have any buffer */
170void
171test_fflush_read3(void)
172{
173 int r;
174 FILE *fp;
175
176 setup();
177
178 /* In POSIX-2008, fflush() must work with the file object for reading */
179 fp = fopen(TMPFILENAME, "r");
180 assert(fp != NULL);
181 r = fflush(fp);
182 assert(r == 0);
183 r = fclose(fp);
184 assert(r == 0);
185}
186
187/* freopen() should call fflush() internal */
188void
189test_fflush_read4(void)
190{
191 int r;
192 FILE *fp;
193 off_t pos;
194 char buf[80];
195
196 setup();
197
198 /* In POSIX-2008, fflush() must work with the file object for reading */
199 fp = fopen(TMPFILENAME, "r");
200 assert(fp != NULL);
201
202 assert(fgetc(fp) == 'H'); /* read 1 */
203
204 pos = lseek(fileno(fp), 0, SEEK_CUR);
205 assert(pos >= 1);
206 assert(pos > 1); /* this test assume the buffer is used */
207
208 /* freopen() should call fflush() internal */
209 fp = freopen(TMPFILENAME, "r", fp);
210 assert(fp != NULL);
211
212 /* can read rest of that on fp */
213 fgets(buf, sizeof(buf), fp);
214 assert(strcmp(buf, "Hello world\n") == 0);
215
216 r = fclose(fp);
217 assert(r == 0);
218}
219
220void
221setupw(void)
222{
223 FILE *fp;
224
225 /* common setup */
226 unlink(TMPFILENAME);
227 fp = fopen(TMPFILENAME, "w+");
228 assert(fp != NULL);
229 /* Konnitiwa Sekai(in Kanji) */
230 fputws(L"\u3053\u3093\u306b\u3061\u308f \u4e16\u754c\n", fp);
231 fclose(fp);
232}
233
234/* fflush work with reading file and seekable + ungetwc */
235void
236test_fflush_read5(void)
237{
238 int r;
239 wchar_t buf[80];
240 FILE *fp;
241
242 setupw();
243
244 fp = fopen(TMPFILENAME, "r");
245
246 assert(fp != NULL);
247 assert(fgetwc(fp) == L'\u3053'); /* Ko */
248 assert(fgetwc(fp) == L'\u3093'); /* N */
249 assert(fgetwc(fp) == L'\u306b'); /* Ni */
250 assert(fgetwc(fp) == L'\u3061'); /* Ti */
251 assert(fgetwc(fp) == L'\u308f'); /* Wa */
252
253 /* push 263A(smile) back */
254 assert(ungetwc(L'\u263a', fp));
255
256 /* we support 1 push back wchar_t */
257 assert(fgetwc(fp) == L'\u263a');
258
259 /* can read reset of that */
260 fgetws(buf, sizeof(buf), fp);
261 assert(wcscmp(buf, L" \u4e16\u754c\n") == 0);
262
263 r = fclose(fp);
264 assert(r == 0);
265
266 /* do the same thing + fflush */
267 fp = fopen(TMPFILENAME, "r");
268
269 assert(fp != NULL);
270 assert(fgetwc(fp) == L'\u3053'); /* Ko */
271 assert(fgetwc(fp) == L'\u3093'); /* N */
272 assert(fgetwc(fp) == L'\u306b'); /* Ni */
273 assert(fgetwc(fp) == L'\u3061'); /* Ti */
274 assert(fgetwc(fp) == L'\u308f'); /* Wa */
275
276 /* push 263A(smile) back */
277 assert(ungetwc(L'\u263a', fp));
278
279 /* we support 1 push back wchar_t */
280 assert(fgetwc(fp) == L'\u263a');
281
282 /* then fflush */
283 r = fflush(fp);
284 assert(r == 0);
285
286 /* fllush() clears the all pushed back chars */
287
288 /* can read rest of that */
289 fgetws(buf, sizeof(buf), fp);
290 assert(wcscmp(buf, L" \u4e16\u754c\n") == 0);
291 r = fclose(fp);
292 assert(r == 0);
293}
294
295void
296test_fflush_read6(void)
297{
298 int r, c;
299 FILE *fp;
300
301 setup();
302 fp = fopen(TMPFILENAME, "r");
303 assert(fp != NULL);
304
305 /*
306 * https://pubs.opengroup.org/onlinepubs/9699919799/functions/fflush.html
307 * .. any characters pushed back onto the stream by ungetc() or ungetwc()
308 * that have not subsequently been read from the stream shall be discarded
309 * (without further changing the file offset).
310 */
311
312 assert(fgetc(fp) == 'H');
313 c = getc(fp);
314 ungetc(c, fp); /* push back the character has been read */
315 r = fflush(fp);
316 assert(r == 0);
317 assert(getc(fp) == c);
318
319 fseek(fp, 0, SEEK_SET);
320 assert(fgetc(fp) == 'H');
321 c = getc(fp);
322 ungetc('X', fp); /* push back the character has not been read */
323 r = fflush(fp);
324 assert(r == 0);
325 assert(getc(fp) == 'l');
326
327 r = fclose(fp);
328 assert(r == 0);
329}
330
331int
332main(int argc, char *argv[])
333{
334 setlocale(LC_ALL, "C.UTF-8");
335
336 test_fflush_read0();
337 test_fflush_read1();
338 test_fflush_read2();
339 test_fflush_read3();
340 test_fflush_read4();
341 test_fflush_read5();
342 test_fflush_read6();
343
344 exit(0);
345}
diff --git a/src/regress/lib/libc/stdio/test_ungetwc.c b/src/regress/lib/libc/stdio/test_ungetwc.c
new file mode 100644
index 0000000000..bb4e853020
--- /dev/null
+++ b/src/regress/lib/libc/stdio/test_ungetwc.c
@@ -0,0 +1,90 @@
1/* $OpenBSD: test_ungetwc.c,v 1.1 2025/05/25 05:32:45 yasuoka Exp $ */
2
3/*
4 * Copyright (c) 2025 YASUOKA Masahiko <yasuoka@yasuoka.net>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <assert.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <unistd.h>
24#include <locale.h>
25#include <wchar.h>
26
27/* we use assert() */
28#undef NDEBUG
29
30#define TMPFILENAME "test_ungetwc.tmp"
31
32void setupw(void);
33void test_fflush_ungetwc0(void);
34
35void
36setupw(void)
37{
38 FILE *fp;
39
40 /* common setup */
41 unlink(TMPFILENAME);
42 fp = fopen(TMPFILENAME, "w+");
43 assert(fp != NULL);
44 /* Konnitiwa Sekai(in Kanji) */
45 fputws(L"\u3053\u3093\u306b\u3061\u308f \u4e16\u754c\n", fp);
46 fclose(fp);
47}
48
49/* fflush work with reading file and seekable + ungetwc */
50void
51test_fflush_ungetwc0(void)
52{
53 int r;
54 wchar_t buf[80];
55 FILE *fp;
56
57 setupw();
58
59 fp = fopen(TMPFILENAME, "r");
60
61 assert(fp != NULL);
62 assert(fgetwc(fp) == L'\u3053'); /* Ko */
63 assert(fgetwc(fp) == L'\u3093'); /* N */
64 assert(fgetwc(fp) == L'\u306b'); /* Ni */
65 assert(fgetwc(fp) == L'\u3061'); /* Ti */
66 assert(fgetwc(fp) == L'\u308f'); /* Wa */
67
68 /* push 263A(smile) back */
69 assert(ungetwc(L'\u263a', fp));
70
71 /* we support 1 push back wchar_t */
72 assert(fgetwc(fp) == L'\u263a');
73
74 /* can read reset of that */
75 fgetws(buf, sizeof(buf), fp);
76 assert(wcscmp(buf, L" \u4e16\u754c\n") == 0);
77
78 r = fclose(fp);
79 assert(r == 0);
80}
81
82int
83main(int argc, char *argv[])
84{
85 setlocale(LC_ALL, "C.UTF-8");
86
87 test_fflush_ungetwc0();
88
89 exit(0);
90}
diff --git a/src/regress/lib/libcrypto/aes/aes_test.c b/src/regress/lib/libcrypto/aes/aes_test.c
index 37bee05ca7..8d5947a031 100644
--- a/src/regress/lib/libcrypto/aes/aes_test.c
+++ b/src/regress/lib/libcrypto/aes/aes_test.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: aes_test.c,v 1.3 2023/09/28 08:21:43 tb Exp $ */ 1/* $OpenBSD: aes_test.c,v 1.5 2025/07/05 14:32:47 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2022 Joshua Sing <joshua@hypera.dev> 3 * Copyright (c) 2022 Joshua Sing <joshua@hypera.dev>
4 * 4 *
@@ -524,6 +524,161 @@ static const struct aes_test aes_tests[] = {
524 }, 524 },
525 .out_len = 64, 525 .out_len = 64,
526 }, 526 },
527
528 /* XTS128 - Test vectors from NIST SP 800-38A */
529 {
530 /* XTSGenAES128 1 */
531 .mode = NID_aes_128_xts,
532 .key = {
533 0xa1, 0xb9, 0x0c, 0xba, 0x3f, 0x06, 0xac, 0x35,
534 0x3b, 0x2c, 0x34, 0x38, 0x76, 0x08, 0x17, 0x62,
535 0x09, 0x09, 0x23, 0x02, 0x6e, 0x91, 0x77, 0x18,
536 0x15, 0xf2, 0x9d, 0xab, 0x01, 0x93, 0x2f, 0x2f,
537 },
538 .iv = {
539 0x4f, 0xae, 0xf7, 0x11, 0x7c, 0xda, 0x59, 0xc6,
540 0x6e, 0x4b, 0x92, 0x01, 0x3e, 0x76, 0x8a, 0xd5,
541 },
542 .iv_len = 16,
543 .in = {
544 0xeb, 0xab, 0xce, 0x95, 0xb1, 0x4d, 0x3c, 0x8d,
545 0x6f, 0xb3, 0x50, 0x39, 0x07, 0x90, 0x31, 0x1c,
546 },
547 .in_len = 16,
548 .out = {
549 0x77, 0x8a, 0xe8, 0xb4, 0x3c, 0xb9, 0x8d, 0x5a,
550 0x82, 0x50, 0x81, 0xd5, 0xbe, 0x47, 0x1c, 0x63,
551 },
552 .out_len = 16,
553 },
554 {
555 /* XTSGenAES128 385 */
556 .mode = NID_aes_128_xts,
557 .key = {
558 0xb8, 0xdb, 0x0b, 0x9e, 0x63, 0xf5, 0xf0, 0xe6,
559 0x60, 0x97, 0x98, 0xa6, 0xcb, 0x42, 0xbb, 0x5b,
560 0x5d, 0x71, 0x39, 0xbb, 0x95, 0x57, 0x99, 0xf5,
561 0x2a, 0x7c, 0x58, 0x1f, 0x84, 0x63, 0x31, 0x76,
562 },
563 .iv = {
564 0x8d, 0x46, 0xf9, 0x67, 0x01, 0x16, 0x7a, 0x1d,
565 0x77, 0xcd, 0x1e, 0x44, 0xda, 0x92, 0xf3, 0xa8,
566 },
567 .iv_len = 16,
568 .in = {
569 0xb4, 0x64, 0x4d, 0xc1, 0xb3, 0x8d, 0xd5, 0x98,
570 0xca, 0x84, 0x0a, 0x82, 0xd4, 0xd9, 0xc0, 0x65,
571 0x67, 0x23, 0xb1, 0x58, 0x01, 0xaa, 0x18, 0xe6,
572 0x6e,
573 },
574 .in_len = 25,
575 .out = {
576 0x09, 0x28, 0x8c, 0xf5, 0x1f, 0x1e, 0xb4, 0xad,
577 0xb8, 0x54, 0x23, 0xd0, 0xe0, 0xd6, 0xe9, 0x58,
578 0x18, 0x87, 0x06, 0xaf, 0x26, 0x0e, 0x24, 0x67,
579 0x4e,
580 },
581 .out_len = 25,
582 },
583 {
584 /* XTSGenAES128 404 */
585 .mode = NID_aes_128_xts,
586 .key = {
587 0xbe, 0x5c, 0xf1, 0xf9, 0x9d, 0x51, 0x59, 0xf2,
588 0x11, 0xdb, 0xc4, 0xc1, 0x47, 0xf7, 0x9c, 0x55,
589 0x6b, 0x2d, 0xa5, 0xc6, 0x91, 0xde, 0xed, 0x74,
590 0x0d, 0x01, 0x57, 0xea, 0xb8, 0xc9, 0xc8, 0x9a,
591 },
592 .iv = {
593 0x89, 0x24, 0x86, 0x24, 0xb6, 0x96, 0xcf, 0x9c,
594 0xb1, 0xb5, 0x77, 0x9c, 0xdc, 0xbc, 0xfe, 0x1c,
595 },
596 .iv_len = 16,
597 .in = {
598 0x3b, 0x80, 0xf8, 0x22, 0xc4, 0xee, 0xe1, 0x31,
599 0x3f, 0x79, 0xca, 0x3d, 0xb1, 0x34, 0xd9, 0xca,
600 0x8b, 0x09, 0xa3, 0x53, 0x4d, 0x4e, 0x18, 0xe6,
601 0x43, 0x9e, 0x1c, 0xdb, 0x86, 0x18, 0x2a, 0x4f,
602 },
603 .in_len = 32,
604 .out = {
605 0x4b, 0x6a, 0xf4, 0x3a, 0x88, 0xb6, 0x33, 0xeb,
606 0xd1, 0xe1, 0x27, 0xc1, 0xec, 0x90, 0xcc, 0x47,
607 0xa2, 0xf1, 0x6e, 0x3b, 0xc7, 0x9f, 0x88, 0x45,
608 0xe3, 0xbd, 0x00, 0x25, 0xda, 0x87, 0x26, 0x45,
609 },
610 .out_len = 32,
611 },
612 {
613 /* XTSGenAES256 1 */
614 .mode = NID_aes_256_xts,
615 .key = {
616 0x1e, 0xa6, 0x61, 0xc5, 0x8d, 0x94, 0x3a, 0x0e,
617 0x48, 0x01, 0xe4, 0x2f, 0x4b, 0x09, 0x47, 0x14,
618 0x9e, 0x7f, 0x9f, 0x8e, 0x3e, 0x68, 0xd0, 0xc7,
619 0x50, 0x52, 0x10, 0xbd, 0x31, 0x1a, 0x0e, 0x7c,
620 0xd6, 0xe1, 0x3f, 0xfd, 0xf2, 0x41, 0x8d, 0x8d,
621 0x19, 0x11, 0xc0, 0x04, 0xcd, 0xa5, 0x8d, 0xa3,
622 0xd6, 0x19, 0xb7, 0xe2, 0xb9, 0x14, 0x1e, 0x58,
623 0x31, 0x8e, 0xea, 0x39, 0x2c, 0xf4, 0x1b, 0x08,
624 },
625 .iv = {
626 0xad, 0xf8, 0xd9, 0x26, 0x27, 0x46, 0x4a, 0xd2,
627 0xf0, 0x42, 0x8e, 0x84, 0xa9, 0xf8, 0x75, 0x64,
628 },
629 .iv_len = 16,
630 .in = {
631 0x2e, 0xed, 0xea, 0x52, 0xcd, 0x82, 0x15, 0xe1,
632 0xac, 0xc6, 0x47, 0xe8, 0x10, 0xbb, 0xc3, 0x64,
633 0x2e, 0x87, 0x28, 0x7f, 0x8d, 0x2e, 0x57, 0xe3,
634 0x6c, 0x0a, 0x24, 0xfb, 0xc1, 0x2a, 0x20, 0x2e,
635 },
636 .in_len = 32,
637 .out = {
638 0xcb, 0xaa, 0xd0, 0xe2, 0xf6, 0xce, 0xa3, 0xf5,
639 0x0b, 0x37, 0xf9, 0x34, 0xd4, 0x6a, 0x9b, 0x13,
640 0x0b, 0x9d, 0x54, 0xf0, 0x7e, 0x34, 0xf3, 0x6a,
641 0xf7, 0x93, 0xe8, 0x6f, 0x73, 0xc6, 0xd7, 0xdb,
642 },
643 .out_len = 32,
644 },
645 {
646 /* XTSGenAES256 172 */
647 .mode = NID_aes_256_xts,
648 .key= {
649 0x5c, 0x7f, 0x7a, 0x36, 0x08, 0x01, 0x78, 0x43,
650 0x00, 0x83, 0xff, 0x54, 0x92, 0xef, 0x77, 0x26,
651 0x0f, 0x68, 0x0a, 0x15, 0xa7, 0x66, 0x24, 0xb8,
652 0x9e, 0x85, 0x4c, 0x94, 0xf0, 0x48, 0x8a, 0x9e,
653 0x7d, 0xaa, 0x4f, 0x33, 0x01, 0x1f, 0x91, 0xdf,
654 0x5e, 0x33, 0x80, 0x53, 0xf4, 0x6c, 0xee, 0x65,
655 0x0f, 0xb0, 0xee, 0x69, 0xf8, 0xc2, 0x15, 0x75,
656 0x5a, 0x4a, 0x63, 0xcd, 0x42, 0x28, 0xc2, 0x19,
657 },
658 .iv = {
659 0xa4, 0x01, 0xd7, 0x3c, 0x88, 0x75, 0xe7, 0x59,
660 0xaa, 0x3e, 0xef, 0x53, 0xe0, 0xfb, 0x62, 0x63,
661 },
662 .iv_len = 16,
663 .in = {
664 0xb1, 0xe6, 0x29, 0xa6, 0x2a, 0x03, 0xca, 0x96,
665 0x9b, 0x16, 0x91, 0x52, 0x02, 0xbc, 0xaa, 0x09,
666 0xe7, 0x8a, 0xe1, 0x85, 0x1b, 0xc8, 0x85, 0x81,
667 0x16, 0x49, 0x68, 0xa5, 0x65, 0x6c, 0x82, 0xc0,
668 0xe5, 0xc4, 0x03, 0xba, 0x54, 0xb9, 0xb5, 0xed,
669 0x9b, 0xab, 0xe8, 0xb0, 0x75, 0x1d, 0x1b, 0x34,
670 },
671 .in_len = 48,
672 .out = {
673 0xf5, 0xbc, 0xa6, 0x0f, 0xb9, 0x35, 0x2b, 0x1d,
674 0xe0, 0x4d, 0x71, 0x29, 0x40, 0x56, 0x26, 0xb3,
675 0xa4, 0x74, 0xa2, 0x64, 0xfb, 0xac, 0x2d, 0x6b,
676 0xe1, 0x19, 0xe1, 0xd5, 0x7a, 0xa9, 0x98, 0xd0,
677 0xe0, 0xe4, 0xd9, 0xf9, 0xc9, 0x76, 0x21, 0x0d,
678 0x93, 0xc4, 0x65, 0xa3, 0xe3, 0x60, 0xcd, 0x92,
679 },
680 .out_len = 48,
681 },
527}; 682};
528 683
529#define N_AES_TESTS (sizeof(aes_tests) / sizeof(aes_tests[0])) 684#define N_AES_TESTS (sizeof(aes_tests) / sizeof(aes_tests[0]))
@@ -542,7 +697,10 @@ aes_ecb_test(size_t test_number, const char *label, int key_bits,
542 697
543 /* Encryption */ 698 /* Encryption */
544 memset(out, 0, sizeof(out)); 699 memset(out, 0, sizeof(out));
545 AES_set_encrypt_key(at->key, key_bits, &key); 700 if (AES_set_encrypt_key(at->key, key_bits, &key) != 0) {
701 fprintf(stderr, "FAIL (%s:%zu): AES_set_encrypt_key failed\n", label, test_number);
702 return 0;
703 }
546 AES_ecb_encrypt(at->in, out, &key, 1); 704 AES_ecb_encrypt(at->in, out, &key, 1);
547 705
548 if (memcmp(at->out, out, at->out_len) != 0) { 706 if (memcmp(at->out, out, at->out_len) != 0) {
@@ -553,7 +711,10 @@ aes_ecb_test(size_t test_number, const char *label, int key_bits,
553 711
554 /* Decryption */ 712 /* Decryption */
555 memset(out, 0, sizeof(out)); 713 memset(out, 0, sizeof(out));
556 AES_set_decrypt_key(at->key, key_bits, &key); 714 if (AES_set_decrypt_key(at->key, key_bits, &key) != 0) {
715 fprintf(stderr, "FAIL (%s:%zu): AES_set_decrypt_key failed\n", label, test_number);
716 return 0;
717 }
557 AES_ecb_encrypt(at->out, out, &key, 0); 718 AES_ecb_encrypt(at->out, out, &key, 0);
558 719
559 if (memcmp(at->in, out, at->in_len) != 0) { 720 if (memcmp(at->in, out, at->in_len) != 0) {
@@ -582,7 +743,10 @@ aes_cbc_test(size_t test_number, const char *label, int key_bits,
582 /* Encryption */ 743 /* Encryption */
583 memset(out, 0, sizeof(out)); 744 memset(out, 0, sizeof(out));
584 memcpy(iv, at->iv, at->iv_len); 745 memcpy(iv, at->iv, at->iv_len);
585 AES_set_encrypt_key(at->key, key_bits, &key); 746 if (AES_set_encrypt_key(at->key, key_bits, &key) != 0) {
747 fprintf(stderr, "FAIL (%s:%zu): AES_set_encrypt_key failed\n", label, test_number);
748 return 0;
749 }
586 AES_cbc_encrypt(at->in, out, at->in_len, &key, iv, 1); 750 AES_cbc_encrypt(at->in, out, at->in_len, &key, iv, 1);
587 751
588 if (memcmp(at->out, out, at->out_len) != 0) { 752 if (memcmp(at->out, out, at->out_len) != 0) {
@@ -594,7 +758,10 @@ aes_cbc_test(size_t test_number, const char *label, int key_bits,
594 /* Decryption */ 758 /* Decryption */
595 memset(out, 0, sizeof(out)); 759 memset(out, 0, sizeof(out));
596 memcpy(iv, at->iv, at->iv_len); 760 memcpy(iv, at->iv, at->iv_len);
597 AES_set_decrypt_key(at->key, key_bits, &key); 761 if (AES_set_decrypt_key(at->key, key_bits, &key) != 0) {
762 fprintf(stderr, "FAIL (%s:%zu): AES_set_decrypt_key failed\n", label, test_number);
763 return 0;
764 }
598 AES_cbc_encrypt(at->out, out, at->out_len, &key, iv, 0); 765 AES_cbc_encrypt(at->out, out, at->out_len, &key, iv, 0);
599 766
600 if (memcmp(at->in, out, at->in_len) != 0) { 767 if (memcmp(at->in, out, at->in_len) != 0) {
@@ -607,6 +774,96 @@ aes_cbc_test(size_t test_number, const char *label, int key_bits,
607} 774}
608 775
609static int 776static int
777aes_cfb128_test(size_t test_number, const char *label, int key_bits,
778 const struct aes_test *at)
779{
780 AES_KEY key;
781 uint8_t out[64];
782 uint8_t iv[16];
783 int num = 0;
784
785 /* CFB mode has no padding */
786
787 /* Encryption */
788 memset(out, 0, sizeof(out));
789 memcpy(iv, at->iv, at->iv_len);
790 if (AES_set_encrypt_key(at->key, key_bits, &key) != 0) {
791 fprintf(stderr, "FAIL (%s:%zu): AES_set_encrypt_key failed\n", label, test_number);
792 return 0;
793 }
794 AES_cfb128_encrypt(at->in, out, at->in_len, &key, iv, &num, AES_ENCRYPT);
795
796 if (memcmp(at->out, out, at->out_len) != 0) {
797 fprintf(stderr, "FAIL (%s:%zu): encryption mismatch\n",
798 label, test_number);
799 return 0;
800 }
801
802 /* Decryption */
803 memset(out, 0, sizeof(out));
804 memcpy(iv, at->iv, at->iv_len);
805 num = 0;
806 if (AES_set_encrypt_key(at->key, key_bits, &key) != 0) {
807 fprintf(stderr, "FAIL (%s:%zu): AES_set_encrypt_key failed\n", label, test_number);
808 return 0;
809 }
810 AES_cfb128_encrypt(at->out, out, at->out_len, &key, iv, &num, AES_DECRYPT);
811
812 if (memcmp(at->in, out, at->in_len) != 0) {
813 fprintf(stderr, "FAIL (%s:%zu): decryption mismatch\n",
814 label, test_number);
815 return 0;
816 }
817
818 return 1;
819}
820
821static int
822aes_ofb128_test(size_t test_number, const char *label, int key_bits,
823 const struct aes_test *at)
824{
825 AES_KEY key;
826 uint8_t out[64];
827 uint8_t iv[16];
828 int num = 0;
829
830 /* OFB mode has no padding */
831
832 /* Encryption */
833 memset(out, 0, sizeof(out));
834 memcpy(iv, at->iv, at->iv_len);
835 if (AES_set_encrypt_key(at->key, key_bits, &key) != 0) {
836 fprintf(stderr, "FAIL (%s:%zu): AES_set_encrypt_key failed\n", label, test_number);
837 return 0;
838 }
839 AES_ofb128_encrypt(at->in, out, at->in_len, &key, iv, &num);
840
841 if (memcmp(at->out, out, at->out_len) != 0) {
842 fprintf(stderr, "FAIL (%s:%zu): encryption mismatch\n",
843 label, test_number);
844 return 0;
845 }
846
847 /* Decryption */
848 memset(out, 0, sizeof(out));
849 memcpy(iv, at->iv, at->iv_len);
850 num = 0;
851 if (AES_set_encrypt_key(at->key, key_bits, &key) != 0) {
852 fprintf(stderr, "FAIL (%s:%zu): AES_set_encrypt_key failed\n", label, test_number);
853 return 0;
854 }
855 AES_ofb128_encrypt(at->out, out, at->out_len, &key, iv, &num);
856
857 if (memcmp(at->in, out, at->in_len) != 0) {
858 fprintf(stderr, "FAIL (%s:%zu): decryption mismatch\n",
859 label, test_number);
860 return 0;
861 }
862
863 return 1;
864}
865
866static int
610aes_evp_test(size_t test_number, const struct aes_test *at, const char *label, 867aes_evp_test(size_t test_number, const struct aes_test *at, const char *label,
611 int key_bits, const EVP_CIPHER *cipher) 868 int key_bits, const EVP_CIPHER *cipher)
612{ 869{
@@ -649,6 +906,10 @@ aes_evp_test(size_t test_number, const struct aes_test *at, const char *label,
649 if (in_len > at->in_len - i) 906 if (in_len > at->in_len - i)
650 in_len = at->in_len - i; 907 in_len = at->in_len - i;
651 908
909 /* XTS needs to be single shot. */
910 if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_XTS_MODE)
911 in_len = at->in_len;
912
652 if (!EVP_EncryptUpdate(ctx, out + total_len, &out_len, 913 if (!EVP_EncryptUpdate(ctx, out + total_len, &out_len,
653 at->in + i, in_len)) { 914 at->in + i, in_len)) {
654 fprintf(stderr, 915 fprintf(stderr,
@@ -715,6 +976,10 @@ aes_evp_test(size_t test_number, const struct aes_test *at, const char *label,
715 if (in_len > at->out_len - i) 976 if (in_len > at->out_len - i)
716 in_len = at->out_len - i; 977 in_len = at->out_len - i;
717 978
979 /* XTS needs to be single shot. */
980 if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_XTS_MODE)
981 in_len = at->in_len;
982
718 if (!EVP_DecryptUpdate(ctx, out + total_len, &out_len, 983 if (!EVP_DecryptUpdate(ctx, out + total_len, &out_len,
719 at->out + i, in_len)) { 984 at->out + i, in_len)) {
720 fprintf(stderr, 985 fprintf(stderr,
@@ -881,6 +1146,16 @@ aes_cipher_from_nid(int nid, const char **out_label,
881 *out_cipher = EVP_aes_256_ccm(); 1146 *out_cipher = EVP_aes_256_ccm();
882 break; 1147 break;
883 1148
1149 /* XTS */
1150 case NID_aes_128_xts:
1151 *out_label = SN_aes_128_xts;
1152 *out_cipher = EVP_aes_128_xts();
1153 break;
1154 case NID_aes_256_xts:
1155 *out_label = SN_aes_256_xts;
1156 *out_cipher = EVP_aes_256_xts();
1157 break;
1158
884 /* Unknown */ 1159 /* Unknown */
885 default: 1160 default:
886 return 0; 1161 return 0;
@@ -902,8 +1177,10 @@ aes_test(void)
902 for (i = 0; i < N_AES_TESTS; i++) { 1177 for (i = 0; i < N_AES_TESTS; i++) {
903 at = &aes_tests[i]; 1178 at = &aes_tests[i];
904 key_bits = aes_key_bits_from_nid(at->mode); 1179 key_bits = aes_key_bits_from_nid(at->mode);
905 if (!aes_cipher_from_nid(at->mode, &label, &cipher)) 1180 if (!aes_cipher_from_nid(at->mode, &label, &cipher)) {
1181 fprintf(stderr, "unknown cipher\n");
906 goto failed; 1182 goto failed;
1183 }
907 1184
908 switch (at->mode) { 1185 switch (at->mode) {
909 /* ECB */ 1186 /* ECB */
@@ -926,14 +1203,16 @@ aes_test(void)
926 case NID_aes_128_cfb128: 1203 case NID_aes_128_cfb128:
927 case NID_aes_192_cfb128: 1204 case NID_aes_192_cfb128:
928 case NID_aes_256_cfb128: 1205 case NID_aes_256_cfb128:
929 /* XXX - CFB128 non-EVP tests */ 1206 if (!aes_cfb128_test(i, label, key_bits, at))
1207 goto failed;
930 break; 1208 break;
931 1209
932 /* OFB128 */ 1210 /* OFB128 */
933 case NID_aes_128_ofb128: 1211 case NID_aes_128_ofb128:
934 case NID_aes_192_ofb128: 1212 case NID_aes_192_ofb128:
935 case NID_aes_256_ofb128: 1213 case NID_aes_256_ofb128:
936 /* XXX - OFB128 non-EVP tests */ 1214 if (!aes_ofb128_test(i, label, key_bits, at))
1215 goto failed;
937 break; 1216 break;
938 1217
939 /* GCM */ 1218 /* GCM */
@@ -947,7 +1226,13 @@ aes_test(void)
947 case NID_aes_128_ccm: 1226 case NID_aes_128_ccm:
948 case NID_aes_192_ccm: 1227 case NID_aes_192_ccm:
949 case NID_aes_256_ccm: 1228 case NID_aes_256_ccm:
950 /* XXX - CCM non-EVP tests */ 1229 /* CCM is EVP-only */
1230 break;
1231
1232 /* XTS */
1233 case NID_aes_128_xts:
1234 case NID_aes_256_xts:
1235 /* XTS is EVP-only */
951 break; 1236 break;
952 1237
953 /* Unknown */ 1238 /* Unknown */
diff --git a/src/regress/lib/libcrypto/asn1/asn1time.c b/src/regress/lib/libcrypto/asn1/asn1time.c
index 7223ad9c9b..e0e5139808 100644
--- a/src/regress/lib/libcrypto/asn1/asn1time.c
+++ b/src/regress/lib/libcrypto/asn1/asn1time.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: asn1time.c,v 1.30 2024/07/21 13:25:11 tb Exp $ */ 1/* $OpenBSD: asn1time.c,v 1.31 2025/05/22 04:54:14 joshua Exp $ */
2/* 2/*
3 * Copyright (c) 2015 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2015 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2024 Google Inc. 4 * Copyright (c) 2024 Google Inc.
@@ -33,6 +33,7 @@ struct asn1_time_test {
33 const char *data; 33 const char *data;
34 const unsigned char der[32]; 34 const unsigned char der[32];
35 time_t time; 35 time_t time;
36 int generalized_time;
36}; 37};
37 38
38static const struct asn1_time_test asn1_invtime_tests[] = { 39static const struct asn1_time_test asn1_invtime_tests[] = {
@@ -73,20 +74,19 @@ static const struct asn1_time_test asn1_invtime_tests[] = {
73 { 74 {
74 .str = "aaaaaaaaaaaaaaZ", 75 .str = "aaaaaaaaaaaaaaZ",
75 }, 76 },
76 /* utc time with omitted seconds, should fail */
77 { 77 {
78 /* UTC time with omitted seconds, should fail */
78 .str = "1609082343Z", 79 .str = "1609082343Z",
79 }, 80 },
80};
81
82static const struct asn1_time_test asn1_invgentime_tests[] = {
83 /* Generalized time with omitted seconds, should fail */
84 { 81 {
82 /* Generalized time with omitted seconds, should fail */
85 .str = "201612081934Z", 83 .str = "201612081934Z",
84 .generalized_time = 1,
86 }, 85 },
87 /* Valid UTC time, should fail as a generalized time */
88 { 86 {
87 /* Valid UTC time, should fail as a generalized time */
89 .str = "160908234300Z", 88 .str = "160908234300Z",
89 .generalized_time = 1,
90 }, 90 },
91}; 91};
92 92
@@ -235,7 +235,7 @@ asn1_compare_str(int test_no, const struct asn1_string_st *asn1str,
235} 235}
236 236
237static int 237static int
238asn1_invtime_test(int test_no, const struct asn1_time_test *att, int gen) 238asn1_invtime_test(int test_no, const struct asn1_time_test *att)
239{ 239{
240 ASN1_GENERALIZEDTIME *gt = NULL; 240 ASN1_GENERALIZEDTIME *gt = NULL;
241 ASN1_UTCTIME *ut = NULL; 241 ASN1_UTCTIME *ut = NULL;
@@ -255,7 +255,7 @@ asn1_invtime_test(int test_no, const struct asn1_time_test *att, int gen)
255 goto done; 255 goto done;
256 } 256 }
257 257
258 if (gen) { 258 if (att->generalized_time) {
259 failure = 0; 259 failure = 0;
260 goto done; 260 goto done;
261 } 261 }
@@ -842,13 +842,7 @@ main(int argc, char **argv)
842 fprintf(stderr, "Invalid time tests...\n"); 842 fprintf(stderr, "Invalid time tests...\n");
843 for (i = 0; i < N_INVTIME_TESTS; i++) { 843 for (i = 0; i < N_INVTIME_TESTS; i++) {
844 att = &asn1_invtime_tests[i]; 844 att = &asn1_invtime_tests[i];
845 failed |= asn1_invtime_test(i, att, 0); 845 failed |= asn1_invtime_test(i, att);
846 }
847
848 fprintf(stderr, "Invalid generalized time tests...\n");
849 for (i = 0; i < N_INVGENTIME_TESTS; i++) {
850 att = &asn1_invgentime_tests[i];
851 failed |= asn1_invtime_test(i, att, 1);
852 } 846 }
853 847
854 fprintf(stderr, "GENERALIZEDTIME tests...\n"); 848 fprintf(stderr, "GENERALIZEDTIME tests...\n");
diff --git a/src/regress/lib/libcrypto/bio/bio_dump.c b/src/regress/lib/libcrypto/bio/bio_dump.c
index 22db80fa3d..fd2bb285fb 100644
--- a/src/regress/lib/libcrypto/bio/bio_dump.c
+++ b/src/regress/lib/libcrypto/bio/bio_dump.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bio_dump.c,v 1.4 2024/02/09 12:48:32 tb Exp $ */ 1/* $OpenBSD: bio_dump.c,v 1.5 2025/05/18 06:41:51 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> 3 * Copyright (c) 2024 Theo Buehler <tb@openbsd.org>
4 * 4 *
@@ -809,7 +809,7 @@ bio_dump_test(const struct bio_dump_testcase *tc)
809 tc->indent, ret, got_len, strlen(tc->output)); 809 tc->indent, ret, got_len, strlen(tc->output));
810 goto err; 810 goto err;
811 } 811 }
812 if (strncmp(tc->output, got, got_len) != 0) { 812 if (got_len > 0 && strncmp(tc->output, got, got_len) != 0) {
813 fprintf(stderr, "%d: mismatch\n", tc->indent); 813 fprintf(stderr, "%d: mismatch\n", tc->indent);
814 goto err; 814 goto err;
815 } 815 }
diff --git a/src/regress/lib/libcrypto/c2sp/Makefile b/src/regress/lib/libcrypto/c2sp/Makefile
index 9b2c944ba4..73ee0b8c22 100644
--- a/src/regress/lib/libcrypto/c2sp/Makefile
+++ b/src/regress/lib/libcrypto/c2sp/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.4 2024/10/28 16:27:14 tb Exp $ 1# $OpenBSD: Makefile,v 1.7 2025/07/23 07:35:21 tb Exp $
2 2
3C2SP_TESTVECTORS = /usr/local/share/c2sp-testvectors/ 3C2SP_TESTVECTORS = /usr/local/share/c2sp-testvectors/
4 4
@@ -13,12 +13,12 @@ PROGS += cctv
13SRCS_cctv = 13SRCS_cctv =
14 14
15cctv: cctv.go 15cctv: cctv.go
16 go build -o $@ ${.CURDIR}/cctv.go 16 env GOCACHE=${.OBJDIR}/go-build go build -o $@ ${.CURDIR}/cctv.go
17 17
18OSSL_LIB = /usr/local/lib/eopenssl 18OSSL_LIB = /usr/local/lib/eopenssl
19OSSL_INC = /usr/local/include/eopenssl 19OSSL_INC = /usr/local/include/eopenssl
20 20
21. for V in 11 32 33 34 21. for V in 35
22. if exists(/usr/local/bin/eopenssl$V) 22. if exists(/usr/local/bin/eopenssl$V)
23PROGS += cctv-openssl$V 23PROGS += cctv-openssl$V
24SRCS_cctv-openssl$V = 24SRCS_cctv-openssl$V =
@@ -29,10 +29,17 @@ CGO_LDFLAGS_$V += -L${OSSL_LIB}$V
29 29
30cctv-openssl$V: cctv.go 30cctv-openssl$V: cctv.go
31 env CGO_CFLAGS="${CGO_CFLAGS_$V}" CGO_LDFLAGS="${CGO_LDFLAGS_$V}" \ 31 env CGO_CFLAGS="${CGO_CFLAGS_$V}" CGO_LDFLAGS="${CGO_LDFLAGS_$V}" \
32 GOCACHE=${.OBJDIR}/go-build \
32 go build -o $@ ${.CURDIR}/cctv.go 33 go build -o $@ ${.CURDIR}/cctv.go
33. endif 34. endif
34. endfor 35. endfor
35 36
37REGRESS_CLEANUP = clean-go-cache
38
39clean-go-cache:
40 env GOCACHE=${.OBJDIR}/go-build go clean -cache
41 rm -rf ${.OBJDIR}/go-build
42
36.endif 43.endif
37 44
38.include <bsd.regress.mk> 45.include <bsd.regress.mk>
diff --git a/src/regress/lib/libcrypto/certs/Makefile b/src/regress/lib/libcrypto/certs/Makefile
index 621c60907f..f7ba9fcad8 100644
--- a/src/regress/lib/libcrypto/certs/Makefile
+++ b/src/regress/lib/libcrypto/certs/Makefile
@@ -1,21 +1,24 @@
1# $OpenBSD: Makefile,v 1.1 2020/07/14 18:27:28 jsing Exp $ 1# $OpenBSD: Makefile,v 1.2 2025/07/09 05:04:35 tb Exp $
2 2
3.if ! (make(clean) || make(cleandir) || make(obj)) 3.if !exists(/usr/local/bin/go)
4GO_VERSION != sh -c "(go version) 2>/dev/null || true"
5.endif
6
7.if empty(GO_VERSION)
8regress: 4regress:
9 @echo package go is required for this regress 5 @echo package go is required for this regress
10 @echo SKIPPED 6 @echo SKIPPED
11.endif 7.else
12 8
13REGRESS_TARGETS=regress-go-verify 9REGRESS_TARGETS=regress-go-verify
10REGRESS_CLEANUP=clean-go-cache
14 11
15certs: 12certs:
16 cd ${.CURDIR} && sh ./make-certs.sh 13 cd ${.CURDIR} && sh ./make-certs.sh
17 14
18regress-go-verify: 15regress-go-verify:
19 cd ${.CURDIR} && go test -test.v . 16 cd ${.CURDIR} && env GOCACHE=${.OBJDIR}/go-build go test -test.v .
17
18clean-go-cache:
19 env GOCACHE=${.OBJDIR}/go-build go clean -cache
20 rm -rf ${.OBJDIR}/go-build
21
22.endif
20 23
21.include <bsd.regress.mk> 24.include <bsd.regress.mk>
diff --git a/src/regress/lib/libcrypto/ec/Makefile b/src/regress/lib/libcrypto/ec/Makefile
index b21eacb4bc..1d976c77d0 100644
--- a/src/regress/lib/libcrypto/ec/Makefile
+++ b/src/regress/lib/libcrypto/ec/Makefile
@@ -1,12 +1,13 @@
1# $OpenBSD: Makefile,v 1.11 2025/03/08 20:09:35 tb Exp $ 1# $OpenBSD: Makefile,v 1.13 2025/08/03 08:29:39 jsing Exp $
2 2
3.ifdef EOPENSSL33 3.ifdef EOPENSSL35
4LDADD += -Wl,-rpath,/usr/local/lib/eopenssl33 -L/usr/local/lib/eopenssl33 4LDADD += -Wl,-rpath,/usr/local/lib/eopenssl35 -L/usr/local/lib/eopenssl35
5CFLAGS += -I/usr/local/include/eopenssl33/ 5CFLAGS += -I/usr/local/include/eopenssl35/
6CFLAGS += -DOPENSSL_SUPPRESS_DEPRECATED 6CFLAGS += -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/ec/ec_asn1_test.c b/src/regress/lib/libcrypto/ec/ec_asn1_test.c
index 03358e69ca..50e6304baf 100644
--- a/src/regress/lib/libcrypto/ec/ec_asn1_test.c
+++ b/src/regress/lib/libcrypto/ec/ec_asn1_test.c
@@ -1,7 +1,7 @@
1/* $OpenBSD: ec_asn1_test.c,v 1.32 2025/03/08 20:09:35 tb Exp $ */ 1/* $OpenBSD: ec_asn1_test.c,v 1.36 2025/07/23 07:42:33 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2017, 2021 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2017, 2021 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> 4 * Copyright (c) 2024, 2025 Theo Buehler <tb@openbsd.org>
5 * 5 *
6 * Permission to use, copy, modify, and distribute this software for any 6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above 7 * purpose with or without fee is hereby granted, provided that the above
@@ -17,12 +17,17 @@
17 */ 17 */
18 18
19#include <err.h> 19#include <err.h>
20#include <stdio.h>
21#include <stdint.h>
22#include <stdlib.h>
20#include <string.h> 23#include <string.h>
21 24
22#include <openssl/bio.h> 25#include <openssl/bio.h>
26#include <openssl/bn.h>
23#include <openssl/ec.h> 27#include <openssl/ec.h>
24#include <openssl/err.h> 28#include <openssl/err.h>
25#include <openssl/objects.h> 29#include <openssl/objects.h>
30#include <openssl/sha.h>
26 31
27#include "ec_local.h" 32#include "ec_local.h"
28 33
@@ -1281,126 +1286,6 @@ static const struct ec_private_key {
1281 }, 1286 },
1282 }, 1287 },
1283 { 1288 {
1284 .name = "prime239v1",
1285 .der_len = 115,
1286 .der = {
1287 0x30, 0x71, 0x02, 0x01, 0x01, 0x04, 0x1e, 0x6e,
1288 0x26, 0x5e, 0xde, 0x5b, 0x67, 0xd6, 0x38, 0x52,
1289 0xe7, 0x1e, 0x8d, 0x44, 0xb1, 0xfb, 0xf8, 0xaf,
1290 0xf9, 0x94, 0x2c, 0xe2, 0x0d, 0xa8, 0x5f, 0x03,
1291 0x67, 0x53, 0x7b, 0x8b, 0x2e, 0xa0, 0x0a, 0x06,
1292 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01,
1293 0x04, 0xa1, 0x40, 0x03, 0x3e, 0x00, 0x04, 0x33,
1294 0xc6, 0xe5, 0x8a, 0xc1, 0x8b, 0x7c, 0x96, 0x19,
1295 0xc9, 0xe1, 0x54, 0x7f, 0x81, 0x9e, 0x59, 0x62,
1296 0xec, 0xc0, 0x1e, 0xe5, 0x53, 0xd5, 0xae, 0x6b,
1297 0xd3, 0xe0, 0x09, 0x07, 0xc5, 0x27, 0x81, 0xa6,
1298 0x8d, 0x39, 0x8e, 0xfe, 0x01, 0xc2, 0x1d, 0xda,
1299 0xde, 0x7b, 0xdc, 0x76, 0x27, 0x17, 0xf9, 0x6f,
1300 0xe3, 0x04, 0xef, 0x5d, 0x65, 0x75, 0x98, 0x7f,
1301 0x2d, 0xd0, 0x68,
1302 },
1303 .hex = "0433C6E58AC18B7C"
1304 "9619C9E1547F819E"
1305 "5962ECC01EE553D5"
1306 "AE6BD3E00907C527"
1307 "81A68D398EFE01C2"
1308 "1DDADE7BDC762717"
1309 "F96FE304EF5D6575"
1310 "987F2DD068",
1311 .oct_len = 61,
1312 .oct = {
1313 0x04, 0x33, 0xc6, 0xe5, 0x8a, 0xc1, 0x8b, 0x7c,
1314 0x96, 0x19, 0xc9, 0xe1, 0x54, 0x7f, 0x81, 0x9e,
1315 0x59, 0x62, 0xec, 0xc0, 0x1e, 0xe5, 0x53, 0xd5,
1316 0xae, 0x6b, 0xd3, 0xe0, 0x09, 0x07, 0xc5, 0x27,
1317 0x81, 0xa6, 0x8d, 0x39, 0x8e, 0xfe, 0x01, 0xc2,
1318 0x1d, 0xda, 0xde, 0x7b, 0xdc, 0x76, 0x27, 0x17,
1319 0xf9, 0x6f, 0xe3, 0x04, 0xef, 0x5d, 0x65, 0x75,
1320 0x98, 0x7f, 0x2d, 0xd0, 0x68,
1321 },
1322 },
1323 {
1324 .name = "prime239v2",
1325 .der_len = 115,
1326 .der = {
1327 0x30, 0x71, 0x02, 0x01, 0x01, 0x04, 0x1e, 0x30,
1328 0x2f, 0x01, 0x10, 0xe9, 0x09, 0x15, 0xdd, 0xe3,
1329 0xdd, 0xae, 0xcb, 0x9d, 0x3a, 0x58, 0x92, 0x02,
1330 0x1e, 0x6e, 0x02, 0x57, 0xa8, 0x36, 0x0b, 0x20,
1331 0x0b, 0x7e, 0xf4, 0xad, 0x0b, 0xa0, 0x0a, 0x06,
1332 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01,
1333 0x05, 0xa1, 0x40, 0x03, 0x3e, 0x00, 0x04, 0x3c,
1334 0x10, 0x27, 0x7b, 0xac, 0xdf, 0x86, 0xc9, 0x4f,
1335 0xf8, 0x39, 0x87, 0x02, 0x39, 0xaf, 0x41, 0xbc,
1336 0x4b, 0x67, 0xd8, 0x5e, 0x04, 0x96, 0x84, 0xb5,
1337 0x60, 0x50, 0x48, 0x6a, 0x20, 0x1d, 0x2b, 0x7e,
1338 0x9f, 0xaf, 0xf8, 0x8e, 0x7e, 0xa4, 0xcd, 0x00,
1339 0xad, 0xb1, 0xad, 0x22, 0x69, 0x32, 0x10, 0x6c,
1340 0xe0, 0xcc, 0xdd, 0x45, 0xd8, 0xa6, 0x29, 0x2f,
1341 0xad, 0x6b, 0xf9,
1342 },
1343 .hex = "043C10277BACDF86"
1344 "C94FF839870239AF"
1345 "41BC4B67D85E0496"
1346 "84B56050486A201D"
1347 "2B7E9FAFF88E7EA4"
1348 "CD00ADB1AD226932"
1349 "106CE0CCDD45D8A6"
1350 "292FAD6BF9",
1351 .oct_len = 61,
1352 .oct = {
1353 0x04, 0x3c, 0x10, 0x27, 0x7b, 0xac, 0xdf, 0x86,
1354 0xc9, 0x4f, 0xf8, 0x39, 0x87, 0x02, 0x39, 0xaf,
1355 0x41, 0xbc, 0x4b, 0x67, 0xd8, 0x5e, 0x04, 0x96,
1356 0x84, 0xb5, 0x60, 0x50, 0x48, 0x6a, 0x20, 0x1d,
1357 0x2b, 0x7e, 0x9f, 0xaf, 0xf8, 0x8e, 0x7e, 0xa4,
1358 0xcd, 0x00, 0xad, 0xb1, 0xad, 0x22, 0x69, 0x32,
1359 0x10, 0x6c, 0xe0, 0xcc, 0xdd, 0x45, 0xd8, 0xa6,
1360 0x29, 0x2f, 0xad, 0x6b, 0xf9,
1361 },
1362 },
1363 {
1364 .name = "prime239v3",
1365 .der_len = 115,
1366 .der = {
1367 0x30, 0x71, 0x02, 0x01, 0x01, 0x04, 0x1e, 0x26,
1368 0x3f, 0x23, 0x4c, 0xe7, 0xbd, 0xa8, 0xe4, 0xfe,
1369 0x7c, 0xf6, 0x18, 0x6a, 0xb2, 0xa6, 0x39, 0x15,
1370 0x6d, 0x72, 0xe8, 0x9e, 0x3f, 0x0f, 0x10, 0x1e,
1371 0xe5, 0xdf, 0xac, 0xe8, 0x2f, 0xa0, 0x0a, 0x06,
1372 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01,
1373 0x06, 0xa1, 0x40, 0x03, 0x3e, 0x00, 0x04, 0x37,
1374 0xba, 0x07, 0x7f, 0xd9, 0x46, 0x5a, 0x33, 0x03,
1375 0x31, 0x77, 0x38, 0xef, 0xee, 0xcc, 0x3d, 0xe1,
1376 0xaa, 0x57, 0xe3, 0x8d, 0xb7, 0xcd, 0xe3, 0x01,
1377 0xf4, 0xd6, 0x75, 0x49, 0x72, 0x61, 0x4c, 0xbf,
1378 0xc0, 0x1f, 0x8b, 0x5f, 0x98, 0x9b, 0xa7, 0xe5,
1379 0x6a, 0xb7, 0xfe, 0x63, 0xdb, 0xb0, 0x40, 0xcb,
1380 0x26, 0x81, 0x2a, 0x91, 0x14, 0x0f, 0xc7, 0x31,
1381 0x13, 0x78, 0x16,
1382 },
1383 .hex = "0437BA077FD9465A"
1384 "3303317738EFEECC"
1385 "3DE1AA57E38DB7CD"
1386 "E301F4D675497261"
1387 "4CBFC01F8B5F989B"
1388 "A7E56AB7FE63DBB0"
1389 "40CB26812A91140F"
1390 "C731137816",
1391 .oct_len = 61,
1392 .oct = {
1393 0x04, 0x37, 0xba, 0x07, 0x7f, 0xd9, 0x46, 0x5a,
1394 0x33, 0x03, 0x31, 0x77, 0x38, 0xef, 0xee, 0xcc,
1395 0x3d, 0xe1, 0xaa, 0x57, 0xe3, 0x8d, 0xb7, 0xcd,
1396 0xe3, 0x01, 0xf4, 0xd6, 0x75, 0x49, 0x72, 0x61,
1397 0x4c, 0xbf, 0xc0, 0x1f, 0x8b, 0x5f, 0x98, 0x9b,
1398 0xa7, 0xe5, 0x6a, 0xb7, 0xfe, 0x63, 0xdb, 0xb0,
1399 0x40, 0xcb, 0x26, 0x81, 0x2a, 0x91, 0x14, 0x0f,
1400 0xc7, 0x31, 0x13, 0x78, 0x16,
1401 },
1402 },
1403 {
1404 .name = "prime256v1", 1289 .name = "prime256v1",
1405 .der_len = 121, 1290 .der_len = 121,
1406 .der = { 1291 .der = {
@@ -2468,6 +2353,197 @@ ec_group_check_private_keys(void)
2468 return failed; 2353 return failed;
2469} 2354}
2470 2355
2356static void
2357ec_group_sha1_bignum(BIGNUM *out, const BIGNUM *in)
2358{
2359 char md[SHA_DIGEST_LENGTH];
2360 unsigned char *bin;
2361 size_t bin_len;
2362
2363 if (BN_num_bytes(in) <= 0)
2364 errx(1, "%s: invalid bignum", __func__);
2365
2366 bin_len = BN_num_bytes(in);
2367 if ((bin = calloc(1, bin_len)) == NULL)
2368 err(1, "calloc");
2369 if (BN_bn2bin(in, bin) <= 0)
2370 errx(1, "BN_bn2bin");
2371
2372 SHA1(bin, bin_len, md);
2373 free(bin);
2374
2375 if (BN_bin2bn(md, sizeof(md), out) == NULL)
2376 errx(1, "BN_bin2bn");
2377}
2378
2379static int
2380ec_group_check_seed(const EC_builtin_curve *curve, BN_CTX *ctx)
2381{
2382 EC_GROUP *group = NULL;
2383 BIGNUM *p, *a, *b, *pow2, *r, *seed_bn, *w;
2384 const unsigned char *seed;
2385 size_t seed_len;
2386 int i, g, h, s, t;
2387 int failed = 1;
2388
2389 if ((group = EC_GROUP_new_by_curve_name(curve->nid)) == NULL)
2390 errx(1, "EC_GROUP_new_by_curve_name");
2391
2392 BN_CTX_start(ctx);
2393
2394 if ((p = BN_CTX_get(ctx)) == NULL)
2395 errx(1, "p = BN_CTX_get()");
2396 if ((a = BN_CTX_get(ctx)) == NULL)
2397 errx(1, "a = BN_CTX_get()");
2398 if ((b = BN_CTX_get(ctx)) == NULL)
2399 errx(1, "b = BN_CTX_get()");
2400 if ((r = BN_CTX_get(ctx)) == NULL)
2401 errx(1, "r = BN_CTX_get()");
2402 if ((pow2 = BN_CTX_get(ctx)) == NULL)
2403 errx(1, "pow2 = BN_CTX_get()");
2404 if ((seed_bn = BN_CTX_get(ctx)) == NULL)
2405 errx(1, "seed_bn = BN_CTX_get()");
2406 if ((w = BN_CTX_get(ctx)) == NULL)
2407 errx(1, "w = BN_CTX_get()");
2408
2409 /*
2410 * If the curve has a seed, verify that its parameters a and b have
2411 * been selected using that seed, loosely following X9.62, F.3.4.b.
2412 * Otherwise there's nothing to do.
2413 */
2414 if ((seed = EC_GROUP_get0_seed(group)) == NULL)
2415 goto done;
2416 seed_len = EC_GROUP_get_seed_len(group);
2417
2418 /*
2419 * This isn't a requirement but happens to be the case for NIST
2420 * curves - the only built-in curves that have a seed.
2421 */
2422 if (seed_len != SHA_DIGEST_LENGTH) {
2423 fprintf(stderr, "%s FAIL: unexpected seed length. "
2424 "want %d, got %zu\n", __func__, SHA_DIGEST_LENGTH, seed_len);
2425 goto err;
2426 }
2427
2428 /* Seed length in bits, per F.3.3.b. */
2429 g = 8 * seed_len;
2430
2431 /*
2432 * Prepare to build the verifiably random element r of GFp by
2433 * concatenating the SHA-1 of modifications of the seed as a number.
2434 */
2435 if (BN_bin2bn(seed, seed_len, seed_bn) == NULL)
2436 errx(1, "BN_bin2bn");
2437
2438 if (!EC_GROUP_get_curve(group, p, a, b, ctx))
2439 errx(1, "EC_GROUP_get_curve");
2440
2441 t = BN_num_bits(p); /* bit length needed. */
2442 s = (t - 1) / 160; /* number of SHA-1 fitting in bit length. */
2443 h = t - 160 * s; /* remaining number of bits in r. */
2444
2445 /*
2446 * Steps 1 - 3: compute hash of the seed and take h - 1 rightmost bits.
2447 */
2448
2449 ec_group_sha1_bignum(r, seed_bn);
2450 BN_zero(pow2);
2451 if (!BN_set_bit(pow2, h - 1))
2452 errx(1, "BN_set_bit");
2453 if (!BN_mod(r, r, pow2, ctx))
2454 errx(1, "BN_nnmod");
2455
2456 /*
2457 * Steps 4 - 6: for i from 1 to s do Wi = SHA-1(SEED + i mod 2^g),
2458 * With W0 = r as already computed, let r = W0 || W1 || ... || Ws.
2459 */
2460
2461 BN_zero(pow2);
2462 if (!BN_set_bit(pow2, g))
2463 errx(1, "BN_set_bit");
2464
2465 for (i = 0; i < s; i++) {
2466 /*
2467 * This is a bit silly since the seed isn't going to have all
2468 * its bits set, so BN_add_word(seed_bn, 1) would do, but for
2469 * the sake of correctness...
2470 */
2471 if (!BN_mod_add(seed_bn, seed_bn, BN_value_one(), pow2, ctx))
2472 errx(1, "BN_mod_add");
2473
2474 ec_group_sha1_bignum(w, seed_bn);
2475
2476 if (!BN_lshift(r, r, 8 * SHA_DIGEST_LENGTH))
2477 errx(1, "BN_lshift");
2478 if (!BN_add(r, r, w))
2479 errx(1, "BN_add");
2480 }
2481
2482 /*
2483 * Step 7: check that r * b^2 == a^3 (mod p)
2484 */
2485
2486 /* Compute r = r * b^2 (mod p). */
2487 if (!BN_mod_sqr(b, b, p, ctx))
2488 errx(1, "BN_mod_sqr");
2489 if (!BN_mod_mul(r, r, b, p, ctx))
2490 errx(1, "BN_mod_mul");
2491
2492 /* Compute a = a^3 (mod p). */
2493 if (!BN_mod_sqr(b, a, p, ctx))
2494 errx(1, "BN_mod_sqr");
2495 if (!BN_mod_mul(a, a, b, p, ctx))
2496 errx(1, "BN_mod_mul");
2497
2498 /*
2499 * XXX - this assumes that a, b, p >= 0, so the results are in [0, p).
2500 * This is currently enforced in the EC code.
2501 */
2502 if (BN_cmp(r, a) != 0) {
2503 fprintf(stderr, "FAIL: %s verification failed for %s\nr * b^2:\t",
2504 __func__, curve->comment);
2505 BN_print_fp(stderr, r);
2506 fprintf(stderr, "\na^3:\t\t");
2507 BN_print_fp(stderr, a);
2508 fprintf(stderr, "\n");
2509 goto err;
2510 }
2511
2512 done:
2513 failed = 0;
2514
2515 err:
2516 BN_CTX_end(ctx);
2517 EC_GROUP_free(group);
2518
2519 return failed;
2520}
2521
2522static int
2523ec_group_check_seeds(void)
2524{
2525 BN_CTX *ctx = NULL;
2526 EC_builtin_curve *all_curves = NULL;
2527 size_t curve_id, ncurves;
2528 int failed = 0;
2529
2530 if ((ctx = BN_CTX_new()) == NULL)
2531 errx(1, "BN_CTX_new");
2532
2533 ncurves = EC_get_builtin_curves(NULL, 0);
2534 if ((all_curves = calloc(ncurves, sizeof(*all_curves))) == NULL)
2535 err(1, "calloc builtin curves");
2536 EC_get_builtin_curves(all_curves, ncurves);
2537
2538 for (curve_id = 0; curve_id < ncurves; curve_id++)
2539 failed |= ec_group_check_seed(&all_curves[curve_id], ctx);
2540
2541 free(all_curves);
2542 BN_CTX_free(ctx);
2543
2544 return failed;
2545}
2546
2471int 2547int
2472main(int argc, char **argv) 2548main(int argc, char **argv)
2473{ 2549{
@@ -2479,6 +2555,7 @@ main(int argc, char **argv)
2479 failed |= ec_group_roundtrip_builtin_curves(); 2555 failed |= ec_group_roundtrip_builtin_curves();
2480 failed |= ec_group_non_builtin_curves(); 2556 failed |= ec_group_non_builtin_curves();
2481 failed |= ec_group_check_private_keys(); 2557 failed |= ec_group_check_private_keys();
2558 failed |= ec_group_check_seeds();
2482 2559
2483 return failed; 2560 return failed;
2484} 2561}
diff --git a/src/regress/lib/libcrypto/ec/ectest.c b/src/regress/lib/libcrypto/ec/ectest.c
index fc44f9c886..3e81954174 100644
--- a/src/regress/lib/libcrypto/ec/ectest.c
+++ b/src/regress/lib/libcrypto/ec/ectest.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ectest.c,v 1.35 2025/01/24 11:49:13 tb Exp $ */ 1/* $OpenBSD: ectest.c,v 1.36 2025/07/23 07:40:07 tb Exp $ */
2/* 2/*
3 * Originally written by Bodo Moeller for the OpenSSL project. 3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */ 4 */
@@ -71,14 +71,11 @@
71 71
72#include <stdio.h> 72#include <stdio.h>
73#include <stdlib.h> 73#include <stdlib.h>
74#include <string.h>
75#include <time.h>
76 74
75#include <openssl/bn.h>
76#include <openssl/crypto.h>
77#include <openssl/ec.h> 77#include <openssl/ec.h>
78#include <openssl/err.h> 78#include <openssl/err.h>
79#include <openssl/obj_mac.h>
80#include <openssl/objects.h>
81#include <openssl/bn.h>
82#include <openssl/opensslconf.h> 79#include <openssl/opensslconf.h>
83 80
84#define ABORT do { \ 81#define ABORT do { \
diff --git a/src/regress/lib/libcrypto/evp/evp_pkey_cleanup.c b/src/regress/lib/libcrypto/evp/evp_pkey_cleanup.c
index d4825f68e8..1d2fa60be7 100644
--- a/src/regress/lib/libcrypto/evp/evp_pkey_cleanup.c
+++ b/src/regress/lib/libcrypto/evp/evp_pkey_cleanup.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: evp_pkey_cleanup.c,v 1.5 2024/02/29 20:02:00 tb Exp $ */ 1/* $OpenBSD: evp_pkey_cleanup.c,v 1.6 2025/05/21 03:53:20 kenjiro Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2022 Theo Buehler <tb@openbsd.org> 4 * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
@@ -38,6 +38,8 @@ int pkey_ids[] = {
38 EVP_PKEY_RSA, 38 EVP_PKEY_RSA,
39 EVP_PKEY_RSA_PSS, 39 EVP_PKEY_RSA_PSS,
40 EVP_PKEY_X25519, 40 EVP_PKEY_X25519,
41 EVP_PKEY_HKDF,
42 EVP_PKEY_TLS1_PRF,
41}; 43};
42 44
43static const size_t N_PKEY_IDS = sizeof(pkey_ids) / sizeof(pkey_ids[0]); 45static const size_t N_PKEY_IDS = sizeof(pkey_ids) / sizeof(pkey_ids[0]);
diff --git a/src/regress/lib/libcrypto/evp/evp_test.c b/src/regress/lib/libcrypto/evp/evp_test.c
index a699832c45..0bd8b4d092 100644
--- a/src/regress/lib/libcrypto/evp/evp_test.c
+++ b/src/regress/lib/libcrypto/evp/evp_test.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: evp_test.c,v 1.20 2024/07/09 17:24:12 tb Exp $ */ 1/* $OpenBSD: evp_test.c,v 1.21 2025/05/22 00:13:47 kenjiro Exp $ */
2/* 2/*
3 * Copyright (c) 2017, 2022 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2017, 2022 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2023, 2024 Theo Buehler <tb@openbsd.org> 4 * Copyright (c) 2023, 2024 Theo Buehler <tb@openbsd.org>
@@ -802,6 +802,85 @@ kdf_compare_bytes(const char *label, const unsigned char *d1, int len1,
802} 802}
803 803
804static int 804static int
805evp_kdf_hkdf_basic(void)
806{
807 EVP_PKEY_CTX *pctx;
808 unsigned char out[42];
809 size_t outlen = sizeof(out);
810 int failed = 1;
811
812 /* Test vector from RFC 5869, Appendix A.1. */
813 const unsigned char ikm[] = {
814 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
815 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
816 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
817 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
818 0x0b, 0x0b,
819 };
820 const unsigned char salt[] = {
821 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
822 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
823 0x0c,
824 };
825 const unsigned char info[] = {
826 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
827 0xf6, 0xf7, 0xf8, 0xf9,
828 };
829 const unsigned char expected[42] = {
830 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a,
831 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a,
832 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c,
833 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf,
834 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18,
835 0x58, 0x65,
836 };
837
838 if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL)) == NULL) {
839 fprintf(stderr, "FAIL: EVP_PKEY_CTX_new_id\n");
840 goto err;
841 }
842
843 if (EVP_PKEY_derive_init(pctx) <= 0) {
844 fprintf(stderr, "FAIL: EVP_PKEY_derive_init\n");
845 goto err;
846 }
847
848 if (EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256()) <= 0) {
849 fprintf(stderr, "FAIL: EVP_PKEY_CTX_set_hkdf_md\n");
850 goto err;
851 }
852
853 if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, sizeof(salt)) <= 0) {
854 fprintf(stderr, "FAIL: EVP_PKEY_CTX_set1_hkdf_salt\n");
855 goto err;
856 }
857
858 if (EVP_PKEY_CTX_set1_hkdf_key(pctx, ikm, sizeof(ikm)) <= 0) {
859 fprintf(stderr, "FAIL: EVP_PKEY_CTX_set1_hkdf_key\n");
860 goto err;
861 }
862
863 if (EVP_PKEY_CTX_add1_hkdf_info(pctx, info, sizeof(info)) <= 0) {
864 fprintf(stderr, "FAIL: EVP_PKEY_CTX_add1_hkdf_info\n");
865 goto err;
866 }
867
868 if (EVP_PKEY_derive(pctx, out, &outlen) <= 0) {
869 fprintf(stderr, "FAIL: EVP_PKEY_derive\n");
870 goto err;
871 }
872
873 if (!kdf_compare_bytes("HKDF test", out, outlen, expected, sizeof(expected)))
874 goto err;
875
876 failed = 0;
877
878 err:
879 EVP_PKEY_CTX_free(pctx);
880 return failed;
881}
882
883static int
805evp_kdf_tls1_prf_basic(void) 884evp_kdf_tls1_prf_basic(void)
806{ 885{
807 EVP_PKEY_CTX *pctx; 886 EVP_PKEY_CTX *pctx;
@@ -1038,6 +1117,7 @@ main(int argc, char **argv)
1038 failed |= obj_name_do_all_test(); 1117 failed |= obj_name_do_all_test();
1039 failed |= evp_get_cipherbyname_test(); 1118 failed |= evp_get_cipherbyname_test();
1040 failed |= evp_get_digestbyname_test(); 1119 failed |= evp_get_digestbyname_test();
1120 failed |= evp_kdf_hkdf_basic();
1041 failed |= evp_kdf_tls1_prf_basic(); 1121 failed |= evp_kdf_tls1_prf_basic();
1042 failed |= evp_kdf_tls1_prf(); 1122 failed |= evp_kdf_tls1_prf();
1043 1123
diff --git a/src/regress/lib/libcrypto/gcm128/gcm128test.c b/src/regress/lib/libcrypto/gcm128/gcm128test.c
index def7653c7b..78631979fe 100644
--- a/src/regress/lib/libcrypto/gcm128/gcm128test.c
+++ b/src/regress/lib/libcrypto/gcm128/gcm128test.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: gcm128test.c,v 1.7 2022/09/05 21:06:31 tb Exp $ */ 1/* $OpenBSD: gcm128test.c,v 1.8 2025/05/16 14:03:49 jsing Exp $ */
2/* ==================================================================== 2/* ====================================================================
3 * Copyright (c) 2010 The OpenSSL Project. All rights reserved. 3 * Copyright (c) 2010 The OpenSSL Project. All rights reserved.
4 * 4 *
@@ -57,11 +57,6 @@
57#include <openssl/aes.h> 57#include <openssl/aes.h>
58#include <openssl/modes.h> 58#include <openssl/modes.h>
59 59
60/* XXX - something like this should be in the public headers. */
61struct gcm128_context {
62 uint64_t opaque[64];
63};
64
65struct gcm128_test { 60struct gcm128_test {
66 const uint8_t K[128]; 61 const uint8_t K[128];
67 size_t K_len; 62 size_t K_len;
@@ -856,7 +851,7 @@ struct gcm128_test gcm128_tests[] = {
856static int 851static int
857do_gcm128_test(int test_no, struct gcm128_test *tv) 852do_gcm128_test(int test_no, struct gcm128_test *tv)
858{ 853{
859 GCM128_CONTEXT ctx; 854 GCM128_CONTEXT *ctx;
860 AES_KEY key; 855 AES_KEY key;
861 uint8_t *out = NULL; 856 uint8_t *out = NULL;
862 size_t out_len; 857 size_t out_len;
@@ -873,13 +868,16 @@ do_gcm128_test(int test_no, struct gcm128_test *tv)
873 868
874 if (out_len != 0) 869 if (out_len != 0)
875 memset(out, 0, out_len); 870 memset(out, 0, out_len);
876 CRYPTO_gcm128_init(&ctx, &key, (block128_f)AES_encrypt); 871
877 CRYPTO_gcm128_setiv(&ctx, tv->IV, tv->IV_len); 872 if ((ctx = CRYPTO_gcm128_new(&key, (block128_f)AES_encrypt)) == NULL)
873 err(1, "CRYPTO_gcm128_new");
874
875 CRYPTO_gcm128_setiv(ctx, tv->IV, tv->IV_len);
878 if (tv->A_len > 0) 876 if (tv->A_len > 0)
879 CRYPTO_gcm128_aad(&ctx, tv->A, tv->A_len); 877 CRYPTO_gcm128_aad(ctx, tv->A, tv->A_len);
880 if (tv->P_len > 0) 878 if (tv->P_len > 0)
881 CRYPTO_gcm128_encrypt(&ctx, tv->P, out, out_len); 879 CRYPTO_gcm128_encrypt(ctx, tv->P, out, out_len);
882 if (CRYPTO_gcm128_finish(&ctx, tv->T, 16)) { 880 if (CRYPTO_gcm128_finish(ctx, tv->T, 16)) {
883 fprintf(stderr, "TEST %d: CRYPTO_gcm128_finish failed\n", 881 fprintf(stderr, "TEST %d: CRYPTO_gcm128_finish failed\n",
884 test_no); 882 test_no);
885 goto fail; 883 goto fail;
@@ -891,12 +889,12 @@ do_gcm128_test(int test_no, struct gcm128_test *tv)
891 889
892 if (out_len != 0) 890 if (out_len != 0)
893 memset(out, 0, out_len); 891 memset(out, 0, out_len);
894 CRYPTO_gcm128_setiv(&ctx, tv->IV, tv->IV_len); 892 CRYPTO_gcm128_setiv(ctx, tv->IV, tv->IV_len);
895 if (tv->A_len > 0) 893 if (tv->A_len > 0)
896 CRYPTO_gcm128_aad(&ctx, tv->A, tv->A_len); 894 CRYPTO_gcm128_aad(ctx, tv->A, tv->A_len);
897 if (tv->C_len > 0) 895 if (tv->C_len > 0)
898 CRYPTO_gcm128_decrypt(&ctx, tv->C, out, out_len); 896 CRYPTO_gcm128_decrypt(ctx, tv->C, out, out_len);
899 if (CRYPTO_gcm128_finish(&ctx, tv->T, 16)) { 897 if (CRYPTO_gcm128_finish(ctx, tv->T, 16)) {
900 fprintf(stderr, "TEST %d: CRYPTO_gcm128_finish failed\n", 898 fprintf(stderr, "TEST %d: CRYPTO_gcm128_finish failed\n",
901 test_no); 899 test_no);
902 goto fail; 900 goto fail;
@@ -909,6 +907,8 @@ do_gcm128_test(int test_no, struct gcm128_test *tv)
909 ret = 0; 907 ret = 0;
910 908
911fail: 909fail:
910 CRYPTO_gcm128_release(ctx);
911
912 free(out); 912 free(out);
913 return (ret); 913 return (ret);
914} 914}
diff --git a/src/regress/lib/libcrypto/man/check_complete.pl b/src/regress/lib/libcrypto/man/check_complete.pl
index 5f2d12ec73..3cbf02f16a 100755
--- a/src/regress/lib/libcrypto/man/check_complete.pl
+++ b/src/regress/lib/libcrypto/man/check_complete.pl
@@ -1,6 +1,6 @@
1#!/usr/bin/perl 1#!/usr/bin/perl
2# 2#
3# Copyright (c) 2021 Ingo Schwarze <schwarze@openbsd.org> 3# Copyright (c) 2021,2022,2023,2024,2025 Ingo Schwarze <schwarze@openbsd.org>
4# 4#
5# Permission to use, copy, modify, and distribute this software for any 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 6# purpose with or without fee is hereby granted, provided that the above
@@ -30,6 +30,9 @@ my %internal = (
30 BN_MASK2 BN_MASK2h BN_MASK2h1 BN_MASK2l 30 BN_MASK2 BN_MASK2h BN_MASK2h1 BN_MASK2l
31 BN_TBIT BN_ULLONG 31 BN_TBIT BN_ULLONG
32 )], 32 )],
33 conf => [qw(
34 conf_st conf_method_st
35 )],
33 evp => [qw( 36 evp => [qw(
34 ASN1_PKEY_CTRL_CMS_ENVELOPE ASN1_PKEY_CTRL_CMS_RI_TYPE 37 ASN1_PKEY_CTRL_CMS_ENVELOPE ASN1_PKEY_CTRL_CMS_RI_TYPE
35 ASN1_PKEY_CTRL_CMS_SIGN 38 ASN1_PKEY_CTRL_CMS_SIGN
@@ -116,7 +119,7 @@ my %postponed = (
116 119
117my $MANW = 'man -M /usr/share/man -w'; 120my $MANW = 'man -M /usr/share/man -w';
118my $srcdir = '/usr/src/lib/libcrypto/man'; 121my $srcdir = '/usr/src/lib/libcrypto/man';
119my $hfile = '/usr/include/openssl'; 122my $hfile = '/usr/include';
120 123
121my $in_cplusplus = 0; 124my $in_cplusplus = 0;
122my $in_comment = 0; 125my $in_comment = 0;
@@ -133,6 +136,7 @@ if (defined $ARGV[0] && $ARGV[0] eq '-v') {
133 shift @ARGV; 136 shift @ARGV;
134} 137}
135$#ARGV == 0 or die "usage: $0 [-v] headername"; 138$#ARGV == 0 or die "usage: $0 [-v] headername";
139$hfile .= "/openssl" unless $ARGV[0] eq 'tls';
136$hfile .= "/$ARGV[0].h"; 140$hfile .= "/$ARGV[0].h";
137open my $in_fh, '<', $hfile or die "$hfile: $!"; 141open my $in_fh, '<', $hfile or die "$hfile: $!";
138 142
@@ -236,6 +240,7 @@ try_again:
236 # Uninteresting lines. 240 # Uninteresting lines.
237 241
238 if (/^\s*$/ || 242 if (/^\s*$/ ||
243 /^DECLARE_LHASH_OF\(\w+\);$/ ||
239 /^DECLARE_STACK_OF\(\w+\)$/ || 244 /^DECLARE_STACK_OF\(\w+\)$/ ||
240 /^DECLARE_PKCS12_STACK_OF\(\w+\)$/ || 245 /^DECLARE_PKCS12_STACK_OF\(\w+\)$/ ||
241 /^TYPEDEF_D2I2D_OF\(\w+\);$/ || 246 /^TYPEDEF_D2I2D_OF\(\w+\);$/ ||
@@ -288,7 +293,7 @@ try_again:
288 print "D- $line\n" if $verbose; 293 print "D- $line\n" if $verbose;
289 next; 294 next;
290 } 295 }
291 if ($id =~ /^(?:ASN1|BIO|BN|EVP|X509(?:V3)?)_[FR]_\w+$/) { 296 if ($id =~ /^(?:ASN1|BIO|BN|CONF|EVP|X509(?:V3)?)_[FR]_\w+$/) {
292 print "D- $line\n" if $verbose; 297 print "D- $line\n" if $verbose;
293 next; 298 next;
294 } 299 }
diff --git a/src/regress/lib/libcrypto/md/Makefile b/src/regress/lib/libcrypto/md/Makefile
index 94bec95e05..1df57283b2 100644
--- a/src/regress/lib/libcrypto/md/Makefile
+++ b/src/regress/lib/libcrypto/md/Makefile
@@ -1,9 +1,15 @@
1# $OpenBSD: Makefile,v 1.1.1.1 2022/09/02 13:34:48 tb Exp $ 1# $OpenBSD: Makefile,v 1.2 2025/05/22 03:24:47 joshua Exp $
2 2
3PROG= md_test 3PROG = md_test
4LDADD= -lcrypto 4LDADD = -lcrypto
5DPADD= ${LIBCRYPTO} 5DPADD = ${LIBCRYPTO}
6WARNINGS= Yes 6WARNINGS = Yes
7CFLAGS+= -DLIBRESSL_INTERNAL -Werror 7CFLAGS += -DLIBRESSL_INTERNAL -Werror
8CFLAGS += -I${.CURDIR}/../test
9SRCS += md_test.c
10SRCS += test.c
11SRCS += test_util.c
12
13.PATH: ${.CURDIR}/../test
8 14
9.include <bsd.regress.mk> 15.include <bsd.regress.mk>
diff --git a/src/regress/lib/libcrypto/md/md_test.c b/src/regress/lib/libcrypto/md/md_test.c
index 590bb50ee3..752f2e4958 100644
--- a/src/regress/lib/libcrypto/md/md_test.c
+++ b/src/regress/lib/libcrypto/md/md_test.c
@@ -1,6 +1,6 @@
1/* $OpenBSD: md_test.c,v 1.3 2025/01/19 10:17:39 tb Exp $ */ 1/* $OpenBSD: md_test.c,v 1.4 2025/05/22 03:24:47 joshua Exp $ */
2/* 2/*
3 * Copyright (c) 2022 Joshua Sing <joshua@hypera.dev> 3 * Copyright (c) 2022, 2025 Joshua Sing <joshua@joshuasing.dev>
4 * 4 *
5 * Permission to use, copy, modify, and distribute this software for any 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 6 * purpose with or without fee is hereby granted, provided that the above
@@ -22,6 +22,8 @@
22#include <stdint.h> 22#include <stdint.h>
23#include <string.h> 23#include <string.h>
24 24
25#include "test.h"
26
25struct md_test { 27struct md_test {
26 const int algorithm; 28 const int algorithm;
27 const uint8_t in[128]; 29 const uint8_t in[128];
@@ -30,7 +32,7 @@ struct md_test {
30}; 32};
31 33
32static const struct md_test md_tests[] = { 34static const struct md_test md_tests[] = {
33 /* MD4 (RFC 1320 test vectors) */ 35 /* MD4 (RFC 1320 test vectors) */
34 { 36 {
35 .algorithm = NID_md4, 37 .algorithm = NID_md4,
36 .in = "", 38 .in = "",
@@ -99,7 +101,7 @@ static const struct md_test md_tests[] = {
99 } 101 }
100 }, 102 },
101 103
102 /* MD5 (RFC 1321 test vectors) */ 104 /* MD5 (RFC 1321 test vectors) */
103 { 105 {
104 .algorithm = NID_md5, 106 .algorithm = NID_md5,
105 .in = "", 107 .in = "",
@@ -175,25 +177,21 @@ typedef unsigned char *(*md_hash_func)(const unsigned char *, size_t,
175 unsigned char *); 177 unsigned char *);
176 178
177static int 179static int
178md_hash_from_algorithm(int algorithm, const char **out_label, 180md_hash_from_algorithm(int algorithm, md_hash_func *out_func,
179 md_hash_func *out_func, const EVP_MD **out_md, size_t *out_len) 181 const EVP_MD **out_md, size_t *out_len)
180{ 182{
181 switch (algorithm) { 183 switch (algorithm) {
182 case NID_md4: 184 case NID_md4:
183 *out_label = SN_md4;
184 *out_func = MD4; 185 *out_func = MD4;
185 *out_md = EVP_md4(); 186 *out_md = EVP_md4();
186 *out_len = MD4_DIGEST_LENGTH; 187 *out_len = MD4_DIGEST_LENGTH;
187 break; 188 break;
188 case NID_md5: 189 case NID_md5:
189 *out_label = SN_md5;
190 *out_func = MD5; 190 *out_func = MD5;
191 *out_md = EVP_md5(); 191 *out_md = EVP_md5();
192 *out_len = MD5_DIGEST_LENGTH; 192 *out_len = MD5_DIGEST_LENGTH;
193 break; 193 break;
194 default: 194 default:
195 fprintf(stderr, "FAIL: unknown algorithm (%d)\n",
196 algorithm);
197 return 0; 195 return 0;
198 } 196 }
199 197
@@ -201,108 +199,100 @@ md_hash_from_algorithm(int algorithm, const char **out_label,
201} 199}
202 200
203static void 201static void
204hexdump(const unsigned char *buf, size_t len) 202test_md_tv(struct test *t, const void *arg)
205{
206 size_t i;
207
208 for (i = 1; i <= len; i++)
209 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
210
211 fprintf(stderr, "\n");
212}
213
214static int
215md_test(void)
216{ 203{
217 unsigned char *(*md_func)(const unsigned char *, size_t, unsigned char *); 204 const struct md_test *st = arg;
218 const struct md_test *st; 205 md_hash_func md_func;
219 EVP_MD_CTX *hash = NULL;
220 const EVP_MD *md; 206 const EVP_MD *md;
207 EVP_MD_CTX *hash = NULL;
221 uint8_t out[EVP_MAX_MD_SIZE]; 208 uint8_t out[EVP_MAX_MD_SIZE];
222 size_t in_len, out_len; 209 size_t in_len, out_len;
223 size_t i;
224 const char *label;
225 int failed = 1;
226 210
227 if ((hash = EVP_MD_CTX_new()) == NULL) { 211 if (!md_hash_from_algorithm(st->algorithm, &md_func, &md, &out_len)) {
228 fprintf(stderr, "FAIL: EVP_MD_CTX_new() failed\n"); 212 test_errorf(t, "md_hash_from_algorithm: unknown algorithm: %d",
229 goto failed; 213 st->algorithm);
214 goto fail;
230 } 215 }
231 216
232 for (i = 0; i < N_MD_TESTS; i++) { 217 if ((hash = EVP_MD_CTX_new()) == NULL) {
233 st = &md_tests[i]; 218 test_errorf(t, "EVP_MD_CTX_new()");
234 if (!md_hash_from_algorithm(st->algorithm, &label, &md_func, 219 goto fail;
235 &md, &out_len)) 220 }
236 goto failed;
237
238 /* Digest */
239 memset(out, 0, sizeof(out));
240 md_func(st->in, st->in_len, out);
241 if (memcmp(st->out, out, out_len) != 0) {
242 fprintf(stderr, "FAIL (%s): mismatch\n", label);
243 goto failed;
244 }
245 221
246 /* EVP single-shot digest */ 222 /* Digest */
247 memset(out, 0, sizeof(out)); 223 memset(out, 0, sizeof(out));
248 if (!EVP_Digest(st->in, st->in_len, out, NULL, md, NULL)) { 224 md_func(st->in, st->in_len, out);
249 fprintf(stderr, "FAIL (%s): EVP_Digest failed\n", 225 if (memcmp(st->out, out, out_len) != 0) {
250 label); 226 test_errorf(t, "MD: digest output mismatch");
251 goto failed; 227 test_hexdiff(t, out, out_len, st->out);
252 } 228 }
253 229
254 if (memcmp(st->out, out, out_len) != 0) { 230 /* EVP single-shot digest */
255 fprintf(stderr, "FAIL (%s): EVP single-shot mismatch\n", 231 memset(out, 0, sizeof(out));
256 label); 232 if (!EVP_Digest(st->in, st->in_len, out, NULL, md, NULL)) {
257 goto failed; 233 test_errorf(t, "EVP_Digest()");
258 } 234 goto fail;
235 }
236 if (memcmp(st->out, out, out_len) != 0) {
237 test_errorf(t, "EVP_Digest: digest output mismatch");
238 test_hexdiff(t, out, out_len, st->out);
239 }
259 240
260 /* EVP digest */ 241 /* EVP digest */
261 memset(out, 0, sizeof(out)); 242 memset(out, 0, sizeof(out));
262 if (!EVP_DigestInit_ex(hash, md, NULL)) { 243 if (!EVP_DigestInit_ex(hash, md, NULL)) {
263 fprintf(stderr, "FAIL (%s): EVP_DigestInit_ex failed\n", 244 test_errorf(t, "EVP_DigestInit_ex()");
264 label); 245 goto fail;
265 goto failed; 246 }
266 }
267 247
268 in_len = st->in_len / 2; 248 in_len = st->in_len / 2;
269 if (!EVP_DigestUpdate(hash, st->in, in_len)) { 249 if (!EVP_DigestUpdate(hash, st->in, in_len)) {
270 fprintf(stderr, 250 test_errorf(t, "EVP_DigestUpdate: first half failed");
271 "FAIL (%s): EVP_DigestUpdate first half failed\n", 251 goto fail;
272 label); 252 }
273 goto failed;
274 }
275 253
276 if (!EVP_DigestUpdate(hash, st->in + in_len, 254 if (!EVP_DigestUpdate(hash, st->in + in_len,
277 st->in_len - in_len)) { 255 st->in_len - in_len)) {
278 fprintf(stderr, 256 test_errorf(t, "EVP_DigestUpdate: second half failed");
279 "FAIL (%s): EVP_DigestUpdate second half failed\n", 257 goto fail;
280 label); 258 }
281 goto failed;
282 }
283 259
284 if (!EVP_DigestFinal_ex(hash, out, NULL)) { 260 if (!EVP_DigestFinal_ex(hash, out, NULL)) {
285 fprintf(stderr, 261 test_errorf(t, "EVP_DigestFinal_ex()");
286 "FAIL (%s): EVP_DigestFinal_ex failed\n", 262 goto fail;
287 label); 263 }
288 goto failed;
289 }
290 264
291 if (memcmp(st->out, out, out_len) != 0) { 265 if (memcmp(st->out, out, out_len) != 0) {
292 fprintf(stderr, "FAIL (%s): EVP mismatch\n", label); 266 test_errorf(t, "EVP: digest output mismatch");
293 goto failed; 267 test_hexdiff(t, out, out_len, st->out);
294 }
295 } 268 }
296 269
297 failed = 0;
298 270
299 failed: 271 fail:
300 EVP_MD_CTX_free(hash); 272 EVP_MD_CTX_free(hash);
301 return failed;
302} 273}
303 274
304static int 275static void
305md5_large_test(void) 276test_md(struct test *t, const void *arg)
277{
278 const struct md_test *st;
279 size_t i;
280 char *name;
281
282 for (i = 0; i < N_MD_TESTS; i++) {
283 st = &md_tests[i];
284 if (asprintf(&name, "%s: '%s'", OBJ_nid2sn(st->algorithm), st->in) == -1) {
285 test_errorf(t, "create test name");
286 return;
287 }
288
289 test_run(t, name, test_md_tv, st);
290 free(name);
291 }
292}
293
294static void
295test_md5_large(struct test *t, const void *arg)
306{ 296{
307 MD5_CTX ctx; 297 MD5_CTX ctx;
308 uint8_t in[1024]; 298 uint8_t in[1024];
@@ -310,12 +300,10 @@ md5_large_test(void)
310 unsigned int out_len; 300 unsigned int out_len;
311 size_t in_len; 301 size_t in_len;
312 size_t i; 302 size_t i;
313 const char *label;
314 uint8_t want[] = { 303 uint8_t want[] = {
315 0xd8, 0xbc, 0xae, 0x13, 0xb5, 0x5a, 0xb0, 0xfc, 304 0xd8, 0xbc, 0xae, 0x13, 0xb5, 0x5a, 0xb0, 0xfc,
316 0x7f, 0x8a, 0xe1, 0x78, 0x27, 0x8d, 0x44, 0x1b, 305 0x7f, 0x8a, 0xe1, 0x78, 0x27, 0x8d, 0x44, 0x1b,
317 }; 306 };
318 int failed = 1;
319 307
320 memset(in, 'A', sizeof(in)); 308 memset(in, 'A', sizeof(in));
321 in_len = sizeof(in); 309 in_len = sizeof(in);
@@ -323,44 +311,34 @@ md5_large_test(void)
323 memset(out, 0, sizeof(out)); 311 memset(out, 0, sizeof(out));
324 out_len = 16; 312 out_len = 16;
325 313
326 label = "md5";
327
328 MD5_Init(&ctx); 314 MD5_Init(&ctx);
329 315
330 for (i = 0; i < (1<<29) + 1; i += in_len) { 316 for (i = 0; i < (1<<29) + 1; i += in_len) {
331 if (!MD5_Update(&ctx, in, in_len)) { 317 if (!MD5_Update(&ctx, in, in_len)) {
332 fprintf(stderr, "FAIL (%s): MD5_Update failed\n", label); 318 test_errorf(t, "MD5_Update()");
333 goto failed; 319 return;
334 } 320 }
335 } 321 }
336 if (!MD5_Final(out, &ctx)) { 322 if (!MD5_Final(out, &ctx)) {
337 fprintf(stderr, "FAIL (%s): MD5_Final failed\n", label); 323 test_errorf(t, "MD5_Final()");
338 goto failed; 324 return;
339 } 325 }
340 326
341 if (memcmp(out, want, out_len) != 0) { 327 if (memcmp(out, want, out_len) != 0) {
342 fprintf(stderr, "FAIL (%s): MD5 mismatch\n", label); 328 test_errorf(t, "MD5 digest output mismatch");
343 hexdump(out, out_len); 329 test_hexdump(t, out, out_len);
344 goto failed;
345 } 330 }
346 if (ctx.Nh != 0x1 || ctx.Nl != 0x2000) { 331 if (ctx.Nh != 0x1 || ctx.Nl != 0x2000)
347 fprintf(stderr, "FAIL (%s): MD5 incorrect bit length\n", label); 332 test_errorf(t, "MD5 incorrect bit length");
348 goto failed;
349 }
350
351 failed = 0;
352
353 failed:
354 return failed;
355} 333}
356 334
357int 335int
358main(int argc, char **argv) 336main(int argc, char **argv)
359{ 337{
360 int failed = 0; 338 struct test *t = test_init();
361 339
362 failed |= md_test(); 340 test_run(t, "md", test_md, NULL);
363 failed |= md5_large_test(); 341 test_run(t, "md5 large", test_md5_large, NULL);
364 342
365 return failed; 343 return test_result(t);
366} 344}
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_iteration_tests.c b/src/regress/lib/libcrypto/mlkem/mlkem_iteration_tests.c
index 5a61248090..b93243023c 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.2 2024/12/26 07:26:45 tb Exp $ */ 1/* $OpenBSD: mlkem_iteration_tests.c,v 1.5 2025/05/20 00:33:41 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2024 Google Inc. 3 * Copyright (c) 2024 Google Inc.
4 * Copyright (c) 2024 Bob Beck <beck@obtuse.com> 4 * Copyright (c) 2024 Bob Beck <beck@obtuse.com>
@@ -73,7 +73,7 @@ struct iteration_ctx {
73 void *priv; 73 void *priv;
74 void *pub; 74 void *pub;
75 75
76 mlkem_encode_private_key_fn encode_private_key; 76 mlkem_marshal_private_key_fn marshal_private_key;
77 mlkem_encap_external_entropy_fn encap_external_entropy; 77 mlkem_encap_external_entropy_fn encap_external_entropy;
78 mlkem_generate_key_external_entropy_fn generate_key_external_entropy; 78 mlkem_generate_key_external_entropy_fn generate_key_external_entropy;
79 mlkem_public_from_private_fn public_from_private; 79 mlkem_public_from_private_fn public_from_private;
@@ -116,8 +116,10 @@ MlkemIterativeTest(struct iteration_ctx *ctx)
116 } 116 }
117 117
118 /* generate ek as encoded_public_key */ 118 /* generate ek as encoded_public_key */
119 ctx->generate_key_external_entropy(ctx->encoded_public_key, 119 if (!ctx->generate_key_external_entropy(ctx->encoded_public_key,
120 ctx->priv, seed); 120 ctx->priv, seed)) {
121 errx(1, "generate_key_external_entropy");
122 }
121 ctx->public_from_private(ctx->pub, ctx->priv); 123 ctx->public_from_private(ctx->pub, ctx->priv);
122 124
123 /* hash in ek */ 125 /* hash in ek */
@@ -125,7 +127,7 @@ MlkemIterativeTest(struct iteration_ctx *ctx)
125 ctx->encoded_public_key_len); 127 ctx->encoded_public_key_len);
126 128
127 /* marshal priv to dk as encoded_private_key */ 129 /* marshal priv to dk as encoded_private_key */
128 if (!ctx->encode_private_key(ctx->priv, &encoded_private_key, 130 if (!ctx->marshal_private_key(ctx->priv, &encoded_private_key,
129 &encoded_private_key_len)) 131 &encoded_private_key_len))
130 errx(1, "encode private key"); 132 errx(1, "encode private key");
131 133
@@ -183,7 +185,7 @@ main(void)
183 .priv = &priv768, 185 .priv = &priv768,
184 .pub = &pub768, 186 .pub = &pub768,
185 .encap_external_entropy = mlkem768_encap_external_entropy, 187 .encap_external_entropy = mlkem768_encap_external_entropy,
186 .encode_private_key = mlkem768_encode_private_key, 188 .marshal_private_key = mlkem768_marshal_private_key,
187 .generate_key_external_entropy = 189 .generate_key_external_entropy =
188 mlkem768_generate_key_external_entropy, 190 mlkem768_generate_key_external_entropy,
189 .public_from_private = mlkem768_public_from_private, 191 .public_from_private = mlkem768_public_from_private,
@@ -208,7 +210,7 @@ main(void)
208 .priv = &priv1024, 210 .priv = &priv1024,
209 .pub = &pub1024, 211 .pub = &pub1024,
210 .encap_external_entropy = mlkem1024_encap_external_entropy, 212 .encap_external_entropy = mlkem1024_encap_external_entropy,
211 .encode_private_key = mlkem1024_encode_private_key, 213 .marshal_private_key = mlkem1024_marshal_private_key,
212 .generate_key_external_entropy = 214 .generate_key_external_entropy =
213 mlkem1024_generate_key_external_entropy, 215 mlkem1024_generate_key_external_entropy,
214 .public_from_private = mlkem1024_public_from_private, 216 .public_from_private = mlkem1024_public_from_private,
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_tests.c b/src/regress/lib/libcrypto/mlkem/mlkem_tests.c
index 2801a58890..8e04dc6ad2 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.2 2024/12/26 00:10:19 tb Exp $ */ 1/* $OpenBSD: mlkem_tests.c,v 1.6 2025/05/20 00:33:41 beck 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>
@@ -112,7 +112,8 @@ MlkemDecapFileTest(struct decap_ctx *decap)
112 parse_get_cbs(p, DECAP_PRIVATE_KEY, &private_key); 112 parse_get_cbs(p, DECAP_PRIVATE_KEY, &private_key);
113 parse_get_int(p, DECAP_RESULT, &should_fail); 113 parse_get_int(p, DECAP_RESULT, &should_fail);
114 114
115 if (!decap->parse_private_key(decap->private_key, &private_key)) { 115 if (!decap->parse_private_key(decap->private_key,
116 CBS_data(&private_key), CBS_len(&private_key))) {
116 if ((failed = !should_fail)) 117 if ((failed = !should_fail))
117 parse_info(p, "parse private key"); 118 parse_info(p, "parse private key");
118 goto err; 119 goto err;
@@ -207,7 +208,8 @@ MlkemNistDecapFileTest(struct decap_ctx *decap)
207 MLKEM_SHARED_SECRET_BYTES, CBS_len(&k))) 208 MLKEM_SHARED_SECRET_BYTES, CBS_len(&k)))
208 goto err; 209 goto err;
209 210
210 if (!decap->parse_private_key(decap->private_key, &dk)) { 211 if (!decap->parse_private_key(decap->private_key, CBS_data(&dk),
212 CBS_len(&dk))) {
211 parse_info(p, "parse private key"); 213 parse_info(p, "parse private key");
212 goto err; 214 goto err;
213 } 215 }
@@ -360,7 +362,8 @@ MlkemEncapFileTest(struct encap_ctx *encap)
360 parse_get_cbs(p, ENCAP_SHARED_SECRET, &shared_secret); 362 parse_get_cbs(p, ENCAP_SHARED_SECRET, &shared_secret);
361 parse_get_int(p, ENCAP_RESULT, &should_fail); 363 parse_get_int(p, ENCAP_RESULT, &should_fail);
362 364
363 if (!encap->parse_public_key(encap->public_key, &public_key)) { 365 if (!encap->parse_public_key(encap->public_key, CBS_data(&public_key),
366 CBS_len(&public_key))) {
364 if ((failed = !should_fail)) 367 if ((failed = !should_fail))
365 parse_info(p, "parse public key"); 368 parse_info(p, "parse public key");
366 goto err; 369 goto err;
@@ -441,7 +444,7 @@ struct keygen_ctx {
441 size_t public_key_len; 444 size_t public_key_len;
442 445
443 mlkem_generate_key_external_entropy_fn generate_key_external_entropy; 446 mlkem_generate_key_external_entropy_fn generate_key_external_entropy;
444 mlkem_encode_private_key_fn encode_private_key; 447 mlkem_marshal_private_key_fn marshal_private_key;
445}; 448};
446 449
447enum keygen_states { 450enum keygen_states {
@@ -512,7 +515,7 @@ MlkemKeygenFileTest(struct keygen_ctx *keygen)
512 515
513 keygen->generate_key_external_entropy(keygen->encoded_public_key, 516 keygen->generate_key_external_entropy(keygen->encoded_public_key,
514 keygen->private_key, CBS_data(&seed)); 517 keygen->private_key, CBS_data(&seed));
515 if (!keygen->encode_private_key(keygen->private_key, 518 if (!keygen->marshal_private_key(keygen->private_key,
516 &encoded_private_key, &encoded_private_key_len)) { 519 &encoded_private_key, &encoded_private_key_len)) {
517 parse_info(p, "encode private key"); 520 parse_info(p, "encode private key");
518 goto err; 521 goto err;
@@ -611,7 +614,7 @@ MlkemNistKeygenFileTest(struct keygen_ctx *keygen)
611 614
612 keygen->generate_key_external_entropy(keygen->encoded_public_key, 615 keygen->generate_key_external_entropy(keygen->encoded_public_key,
613 keygen->private_key, seed); 616 keygen->private_key, seed);
614 if (!keygen->encode_private_key(keygen->private_key, 617 if (!keygen->marshal_private_key(keygen->private_key,
615 &encoded_private_key, &encoded_private_key_len)) { 618 &encoded_private_key, &encoded_private_key_len)) {
616 parse_info(p, "encode private key"); 619 parse_info(p, "encode private key");
617 goto err; 620 goto err;
@@ -655,10 +658,11 @@ mlkem_keygen_tests(const char *fn, size_t size, enum test_type test_type)
655 .encoded_public_key_len = sizeof(encoded_public_key768), 658 .encoded_public_key_len = sizeof(encoded_public_key768),
656 .private_key_len = MLKEM768_PRIVATE_KEY_BYTES, 659 .private_key_len = MLKEM768_PRIVATE_KEY_BYTES,
657 .public_key_len = MLKEM768_PUBLIC_KEY_BYTES, 660 .public_key_len = MLKEM768_PUBLIC_KEY_BYTES,
661
658 .generate_key_external_entropy = 662 .generate_key_external_entropy =
659 mlkem768_generate_key_external_entropy, 663 mlkem768_generate_key_external_entropy,
660 .encode_private_key = 664 .marshal_private_key =
661 mlkem768_encode_private_key, 665 mlkem768_marshal_private_key,
662 }; 666 };
663 struct MLKEM1024_private_key private_key1024; 667 struct MLKEM1024_private_key private_key1024;
664 uint8_t encoded_public_key1024[MLKEM1024_PUBLIC_KEY_BYTES]; 668 uint8_t encoded_public_key1024[MLKEM1024_PUBLIC_KEY_BYTES];
@@ -671,8 +675,8 @@ mlkem_keygen_tests(const char *fn, size_t size, enum test_type test_type)
671 675
672 .generate_key_external_entropy = 676 .generate_key_external_entropy =
673 mlkem1024_generate_key_external_entropy, 677 mlkem1024_generate_key_external_entropy,
674 .encode_private_key = 678 .marshal_private_key =
675 mlkem1024_encode_private_key, 679 mlkem1024_marshal_private_key,
676 }; 680 };
677 681
678 if (size == 768 && test_type == TEST_TYPE_NORMAL) 682 if (size == 768 && test_type == TEST_TYPE_NORMAL)
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.c b/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.c
index 1bb2ed3a8b..68bd5d4871 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.5 2024/12/26 00:04:24 tb Exp $ */ 1/* $OpenBSD: mlkem_tests_util.c,v 1.8 2025/05/20 00:33:41 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2024 Google Inc. 3 * Copyright (c) 2024 Google Inc.
4 * Copyright (c) 2024 Bob Beck <beck@obtuse.com> 4 * Copyright (c) 2024 Bob Beck <beck@obtuse.com>
@@ -61,91 +61,31 @@ compare_data(const uint8_t *want, const uint8_t *got, size_t len, const char *ms
61} 61}
62 62
63int 63int
64mlkem768_encode_private_key(const void *private_key, uint8_t **out_buf, 64mlkem768_marshal_private_key(const void *private_key, uint8_t **out_buf,
65 size_t *out_len) 65 size_t *out_len)
66{ 66{
67 CBB cbb; 67 return MLKEM768_marshal_private_key(private_key, out_buf, out_len);
68 int ret = 0;
69
70 if (!CBB_init(&cbb, MLKEM768_PUBLIC_KEY_BYTES))
71 goto err;
72 if (!MLKEM768_marshal_private_key(&cbb, private_key))
73 goto err;
74 if (!CBB_finish(&cbb, out_buf, out_len))
75 goto err;
76
77 ret = 1;
78
79 err:
80 CBB_cleanup(&cbb);
81
82 return ret;
83} 68}
84 69
85int 70int
86mlkem768_encode_public_key(const void *public_key, uint8_t **out_buf, 71mlkem768_marshal_public_key(const void *public_key, uint8_t **out_buf,
87 size_t *out_len) 72 size_t *out_len)
88{ 73{
89 CBB cbb; 74 return MLKEM768_marshal_public_key(out_buf, out_len, public_key);
90 int ret = 0;
91
92 if (!CBB_init(&cbb, MLKEM768_PUBLIC_KEY_BYTES))
93 goto err;
94 if (!MLKEM768_marshal_public_key(&cbb, public_key))
95 goto err;
96 if (!CBB_finish(&cbb, out_buf, out_len))
97 goto err;
98
99 ret = 1;
100
101 err:
102 CBB_cleanup(&cbb);
103
104 return ret;
105} 75}
106 76
107int 77int
108mlkem1024_encode_private_key(const void *private_key, uint8_t **out_buf, 78mlkem1024_marshal_private_key(const void *private_key, uint8_t **out_buf,
109 size_t *out_len) 79 size_t *out_len)
110{ 80{
111 CBB cbb; 81 return MLKEM1024_marshal_private_key(private_key, out_buf, out_len);
112 int ret = 0;
113
114 if (!CBB_init(&cbb, MLKEM1024_PUBLIC_KEY_BYTES))
115 goto err;
116 if (!MLKEM1024_marshal_private_key(&cbb, private_key))
117 goto err;
118 if (!CBB_finish(&cbb, out_buf, out_len))
119 goto err;
120
121 ret = 1;
122
123 err:
124 CBB_cleanup(&cbb);
125
126 return ret;
127} 82}
128 83
129int 84int
130mlkem1024_encode_public_key(const void *public_key, uint8_t **out_buf, 85mlkem1024_marshal_public_key(const void *public_key, uint8_t **out_buf,
131 size_t *out_len) 86 size_t *out_len)
132{ 87{
133 CBB cbb; 88 return MLKEM1024_marshal_public_key(out_buf, out_len, public_key);
134 int ret = 0;
135
136 if (!CBB_init(&cbb, MLKEM1024_PUBLIC_KEY_BYTES))
137 goto err;
138 if (!MLKEM1024_marshal_public_key(&cbb, public_key))
139 goto err;
140 if (!CBB_finish(&cbb, out_buf, out_len))
141 goto err;
142
143 ret = 1;
144
145 err:
146 CBB_cleanup(&cbb);
147
148 return ret;
149} 89}
150 90
151int 91int
@@ -173,32 +113,36 @@ mlkem768_encap_external_entropy(uint8_t *out_ciphertext,
173 public_key, entropy); 113 public_key, entropy);
174} 114}
175 115
176void 116int
177mlkem768_generate_key(uint8_t *out_encoded_public_key, 117mlkem768_generate_key(uint8_t *out_encoded_public_key,
178 uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key) 118 uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key)
179{ 119{
180 MLKEM768_generate_key(out_encoded_public_key, optional_out_seed, 120 return MLKEM768_generate_key(out_encoded_public_key, optional_out_seed,
181 out_private_key); 121 out_private_key);
182} 122}
183 123
184void 124int
185mlkem768_generate_key_external_entropy(uint8_t *out_encoded_public_key, 125mlkem768_generate_key_external_entropy(uint8_t *out_encoded_public_key,
186 void *out_private_key, const uint8_t entropy[MLKEM_SEED_BYTES]) 126 void *out_private_key, const uint8_t entropy[MLKEM_SEED_BYTES])
187{ 127{
188 MLKEM768_generate_key_external_entropy(out_encoded_public_key, 128 return MLKEM768_generate_key_external_entropy(out_encoded_public_key,
189 out_private_key, entropy); 129 out_private_key, entropy);
190} 130}
191 131
192int 132int
193mlkem768_parse_private_key(void *out_private_key, CBS *private_key_cbs) 133mlkem768_parse_private_key(void *out_private_key, const uint8_t *private_key,
134 size_t private_key_len)
194{ 135{
195 return MLKEM768_parse_private_key(out_private_key, private_key_cbs); 136 return MLKEM768_parse_private_key(out_private_key, private_key,
137 private_key_len);
196} 138}
197 139
198int 140int
199mlkem768_parse_public_key(void *out_public_key, CBS *public_key_cbs) 141mlkem768_parse_public_key(void *out_public_key, const uint8_t *public_key,
142 size_t public_key_len)
200{ 143{
201 return MLKEM768_parse_public_key(out_public_key, public_key_cbs); 144 return MLKEM768_parse_public_key(out_public_key, public_key,
145 public_key_len);
202} 146}
203 147
204void 148void
@@ -232,26 +176,28 @@ mlkem1024_encap_external_entropy(uint8_t *out_ciphertext,
232 public_key, entropy); 176 public_key, entropy);
233} 177}
234 178
235void 179int
236mlkem1024_generate_key(uint8_t *out_encoded_public_key, 180mlkem1024_generate_key(uint8_t *out_encoded_public_key,
237 uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key) 181 uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key)
238{ 182{
239 MLKEM1024_generate_key(out_encoded_public_key, optional_out_seed, 183 return MLKEM1024_generate_key(out_encoded_public_key, optional_out_seed,
240 out_private_key); 184 out_private_key);
241} 185}
242 186
243void 187int
244mlkem1024_generate_key_external_entropy(uint8_t *out_encoded_public_key, 188mlkem1024_generate_key_external_entropy(uint8_t *out_encoded_public_key,
245 void *out_private_key, const uint8_t entropy[MLKEM_SEED_BYTES]) 189 void *out_private_key, const uint8_t entropy[MLKEM_SEED_BYTES])
246{ 190{
247 MLKEM1024_generate_key_external_entropy(out_encoded_public_key, 191 return MLKEM1024_generate_key_external_entropy(out_encoded_public_key,
248 out_private_key, entropy); 192 out_private_key, entropy);
249} 193}
250 194
251int 195int
252mlkem1024_parse_private_key(void *out_private_key, CBS *private_key_cbs) 196mlkem1024_parse_private_key(void *out_private_key, const uint8_t *private_key,
197 size_t private_key_len)
253{ 198{
254 return MLKEM1024_parse_private_key(out_private_key, private_key_cbs); 199 return MLKEM1024_parse_private_key(out_private_key, private_key,
200 private_key_len);
255} 201}
256 202
257void 203void
@@ -261,7 +207,9 @@ mlkem1024_public_from_private(void *out_public_key, const void *private_key)
261} 207}
262 208
263int 209int
264mlkem1024_parse_public_key(void *out_public_key, CBS *public_key_cbs) 210mlkem1024_parse_public_key(void *out_public_key, const uint8_t *public_key,
211 size_t public_key_len)
265{ 212{
266 return MLKEM1024_parse_public_key(out_public_key, public_key_cbs); 213 return MLKEM1024_parse_public_key(out_public_key, public_key,
214 public_key_len);
267} 215}
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.h b/src/regress/lib/libcrypto/mlkem/mlkem_tests_util.h
index 7fbe6f76a9..1235309f60 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.4 2024/12/26 00:04:24 tb Exp $ */ 1/* $OpenBSD: mlkem_tests_util.h,v 1.7 2025/05/20 00:33:41 beck 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>
@@ -30,13 +30,13 @@
30int compare_data(const uint8_t *want, const uint8_t *got, size_t len, 30int compare_data(const uint8_t *want, const uint8_t *got, size_t len,
31 const char *msg); 31 const char *msg);
32 32
33int mlkem768_encode_private_key(const void *priv, uint8_t **out_buf, 33int mlkem768_marshal_private_key(const void *priv, uint8_t **out_buf,
34 size_t *out_len); 34 size_t *out_len);
35int mlkem768_encode_public_key(const void *pub, uint8_t **out_buf, 35int mlkem768_marshal_public_key(const void *pub, uint8_t **out_buf,
36 size_t *out_len); 36 size_t *out_len);
37int mlkem1024_encode_private_key(const void *priv, uint8_t **out_buf, 37int mlkem1024_marshal_private_key(const void *priv, uint8_t **out_buf,
38 size_t *out_len); 38 size_t *out_len);
39int mlkem1024_encode_public_key(const void *pub, uint8_t **out_buf, 39int mlkem1024_marshal_public_key(const void *pub, uint8_t **out_buf,
40 size_t *out_len); 40 size_t *out_len);
41 41
42int mlkem768_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 42int mlkem768_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
@@ -46,12 +46,12 @@ void mlkem768_encap(uint8_t *out_ciphertext,
46void mlkem768_encap_external_entropy(uint8_t *out_ciphertext, 46void mlkem768_encap_external_entropy(uint8_t *out_ciphertext,
47 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], const void *pub, 47 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], const void *pub,
48 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]); 48 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]);
49void mlkem768_generate_key(uint8_t *out_encoded_public_key, 49int mlkem768_generate_key(uint8_t *out_encoded_public_key,
50 uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key); 50 uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key);
51void mlkem768_generate_key_external_entropy(uint8_t *out_encoded_public_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]); 52 void *out_private_key, const uint8_t entropy[MLKEM_SEED_BYTES]);
53int mlkem768_parse_private_key(void *priv, CBS *private_key_cbs); 53int mlkem768_parse_private_key(void *priv, const uint8_t *in, size_t in_len);
54int mlkem768_parse_public_key(void *pub, CBS *in); 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); 55void mlkem768_public_from_private(void *out_public_key, const void *private_key);
56 56
57int mlkem1024_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 57int mlkem1024_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
@@ -61,16 +61,16 @@ void mlkem1024_encap(uint8_t *out_ciphertext,
61void mlkem1024_encap_external_entropy(uint8_t *out_ciphertext, 61void mlkem1024_encap_external_entropy(uint8_t *out_ciphertext,
62 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], const void *pub, 62 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], const void *pub,
63 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]); 63 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]);
64void mlkem1024_generate_key(uint8_t *out_encoded_public_key, 64int mlkem1024_generate_key(uint8_t *out_encoded_public_key,
65 uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key); 65 uint8_t optional_out_seed[MLKEM_SEED_BYTES], void *out_private_key);
66void mlkem1024_generate_key_external_entropy(uint8_t *out_encoded_public_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]); 67 void *out_private_key, const uint8_t entropy[MLKEM_SEED_BYTES]);
68int mlkem1024_parse_private_key(void *priv, CBS *private_key_cbs); 68int mlkem1024_parse_private_key(void *priv, const uint8_t *in, size_t in_len);
69int mlkem1024_parse_public_key(void *pub, CBS *in); 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); 70void mlkem1024_public_from_private(void *out_public_key, const void *private_key);
71 71
72typedef int (*mlkem_encode_private_key_fn)(const void *, uint8_t **, size_t *); 72typedef int (*mlkem_marshal_private_key_fn)(const void *, uint8_t **, size_t *);
73typedef int (*mlkem_encode_public_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], 74typedef int (*mlkem_decap_fn)(uint8_t [MLKEM_SHARED_SECRET_BYTES],
75 const uint8_t *, size_t, const void *); 75 const uint8_t *, size_t, const void *);
76typedef void (*mlkem_encap_fn)(uint8_t *, uint8_t [MLKEM_SHARED_SECRET_BYTES], 76typedef void (*mlkem_encap_fn)(uint8_t *, uint8_t [MLKEM_SHARED_SECRET_BYTES],
@@ -78,11 +78,11 @@ typedef void (*mlkem_encap_fn)(uint8_t *, uint8_t [MLKEM_SHARED_SECRET_BYTES],
78typedef void (*mlkem_encap_external_entropy_fn)(uint8_t *, 78typedef void (*mlkem_encap_external_entropy_fn)(uint8_t *,
79 uint8_t [MLKEM_SHARED_SECRET_BYTES], const void *, 79 uint8_t [MLKEM_SHARED_SECRET_BYTES], const void *,
80 const uint8_t [MLKEM_ENCAP_ENTROPY]); 80 const uint8_t [MLKEM_ENCAP_ENTROPY]);
81typedef void (*mlkem_generate_key_fn)(uint8_t *, uint8_t *, void *); 81typedef int (*mlkem_generate_key_fn)(uint8_t *, uint8_t *, void *);
82typedef void (*mlkem_generate_key_external_entropy_fn)(uint8_t *, void *, 82typedef int (*mlkem_generate_key_external_entropy_fn)(uint8_t *, void *,
83 const uint8_t [MLKEM_SEED_BYTES]); 83 const uint8_t [MLKEM_SEED_BYTES]);
84typedef int (*mlkem_parse_private_key_fn)(void *, CBS *); 84typedef int (*mlkem_parse_private_key_fn)(void *, const uint8_t *, size_t);
85typedef int (*mlkem_parse_public_key_fn)(void *, CBS *); 85typedef int (*mlkem_parse_public_key_fn)(void *, const uint8_t *, size_t);
86typedef void (*mlkem_public_from_private_fn)(void *out_public_key, 86typedef void (*mlkem_public_from_private_fn)(void *out_public_key,
87 const void *private_key); 87 const void *private_key);
88 88
diff --git a/src/regress/lib/libcrypto/mlkem/mlkem_unittest.c b/src/regress/lib/libcrypto/mlkem/mlkem_unittest.c
index 23b3d8b261..adb1c47d8e 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.6 2024/12/26 12:35:25 tb Exp $ */ 1/* $OpenBSD: mlkem_unittest.c,v 1.11 2025/05/21 03:46:20 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>
@@ -41,8 +41,8 @@ struct unittest_ctx {
41 mlkem_generate_key_fn generate_key; 41 mlkem_generate_key_fn generate_key;
42 mlkem_parse_private_key_fn parse_private_key; 42 mlkem_parse_private_key_fn parse_private_key;
43 mlkem_parse_public_key_fn parse_public_key; 43 mlkem_parse_public_key_fn parse_public_key;
44 mlkem_encode_private_key_fn encode_private_key; 44 mlkem_marshal_private_key_fn marshal_private_key;
45 mlkem_encode_public_key_fn encode_public_key; 45 mlkem_marshal_public_key_fn marshal_public_key;
46 mlkem_public_from_private_fn public_from_private; 46 mlkem_public_from_private_fn public_from_private;
47}; 47};
48 48
@@ -54,36 +54,32 @@ MlKemUnitTest(struct unittest_ctx *ctx)
54 uint8_t first_two_bytes[2]; 54 uint8_t first_two_bytes[2];
55 uint8_t *encoded_private_key = NULL, *tmp_buf = NULL; 55 uint8_t *encoded_private_key = NULL, *tmp_buf = NULL;
56 size_t encoded_private_key_len, tmp_buf_len; 56 size_t encoded_private_key_len, tmp_buf_len;
57 CBS cbs;
58 int failed = 0; 57 int failed = 0;
59 58
60 ctx->generate_key(ctx->encoded_public_key, NULL, ctx->priv); 59 if (!ctx->generate_key(ctx->encoded_public_key, NULL, ctx->priv)) {
60 warnx("generate_key failed");
61 failed |= 1;
62 }
61 63
62 memcpy(first_two_bytes, ctx->encoded_public_key, sizeof(first_two_bytes)); 64 memcpy(first_two_bytes, ctx->encoded_public_key, sizeof(first_two_bytes));
63 memset(ctx->encoded_public_key, 0xff, sizeof(first_two_bytes)); 65 memset(ctx->encoded_public_key, 0xff, sizeof(first_two_bytes));
64 66
65 CBS_init(&cbs, ctx->encoded_public_key, ctx->encoded_public_key_len);
66
67 /* Parsing should fail because the first coefficient is >= kPrime. */ 67 /* Parsing should fail because the first coefficient is >= kPrime. */
68 if (ctx->parse_public_key(ctx->pub, &cbs)) { 68 if (ctx->parse_public_key(ctx->pub, ctx->encoded_public_key,
69 ctx->encoded_public_key_len)) {
69 warnx("parse_public_key should have failed"); 70 warnx("parse_public_key should have failed");
70 failed |= 1; 71 failed |= 1;
71 } 72 }
72 73
73 memcpy(ctx->encoded_public_key, first_two_bytes, sizeof(first_two_bytes)); 74 memcpy(ctx->encoded_public_key, first_two_bytes, sizeof(first_two_bytes));
74 CBS_init(&cbs, ctx->encoded_public_key, ctx->encoded_public_key_len); 75 if (!ctx->parse_public_key(ctx->pub, ctx->encoded_public_key,
75 if (!ctx->parse_public_key(ctx->pub, &cbs)) { 76 ctx->encoded_public_key_len)) {
76 warnx("MLKEM768_parse_public_key"); 77 warnx("MLKEM768_parse_public_key");
77 failed |= 1; 78 failed |= 1;
78 } 79 }
79 80
80 if (CBS_len(&cbs) != 0u) { 81 if (!ctx->marshal_public_key(ctx->pub, &tmp_buf, &tmp_buf_len)) {
81 warnx("CBS_len must be 0"); 82 warnx("marshal_public_key");
82 failed |= 1;
83 }
84
85 if (!ctx->encode_public_key(ctx->pub, &tmp_buf, &tmp_buf_len)) {
86 warnx("encode_public_key");
87 failed |= 1; 83 failed |= 1;
88 } 84 }
89 if (ctx->encoded_public_key_len != tmp_buf_len) { 85 if (ctx->encoded_public_key_len != tmp_buf_len) {
@@ -100,8 +96,8 @@ MlKemUnitTest(struct unittest_ctx *ctx)
100 tmp_buf = NULL; 96 tmp_buf = NULL;
101 97
102 ctx->public_from_private(ctx->pub2, ctx->priv); 98 ctx->public_from_private(ctx->pub2, ctx->priv);
103 if (!ctx->encode_public_key(ctx->pub2, &tmp_buf, &tmp_buf_len)) { 99 if (!ctx->marshal_public_key(ctx->pub2, &tmp_buf, &tmp_buf_len)) {
104 warnx("encode_public_key"); 100 warnx("marshal_public_key");
105 failed |= 1; 101 failed |= 1;
106 } 102 }
107 if (ctx->encoded_public_key_len != tmp_buf_len) { 103 if (ctx->encoded_public_key_len != tmp_buf_len) {
@@ -117,7 +113,7 @@ MlKemUnitTest(struct unittest_ctx *ctx)
117 free(tmp_buf); 113 free(tmp_buf);
118 tmp_buf = NULL; 114 tmp_buf = NULL;
119 115
120 if (!ctx->encode_private_key(ctx->priv, &encoded_private_key, 116 if (!ctx->marshal_private_key(ctx->priv, &encoded_private_key,
121 &encoded_private_key_len)) { 117 &encoded_private_key_len)) {
122 warnx("mlkem768_encode_private_key"); 118 warnx("mlkem768_encode_private_key");
123 failed |= 1; 119 failed |= 1;
@@ -125,23 +121,23 @@ MlKemUnitTest(struct unittest_ctx *ctx)
125 121
126 memcpy(first_two_bytes, encoded_private_key, sizeof(first_two_bytes)); 122 memcpy(first_two_bytes, encoded_private_key, sizeof(first_two_bytes));
127 memset(encoded_private_key, 0xff, sizeof(first_two_bytes)); 123 memset(encoded_private_key, 0xff, sizeof(first_two_bytes));
128 CBS_init(&cbs, encoded_private_key, encoded_private_key_len);
129 124
130 /* Parsing should fail because the first coefficient is >= kPrime. */ 125 /* Parsing should fail because the first coefficient is >= kPrime. */
131 if (ctx->parse_private_key(ctx->priv2, &cbs)) { 126 if (ctx->parse_private_key(ctx->priv2, encoded_private_key,
127 encoded_private_key_len)) {
132 warnx("MLKEM768_parse_private_key should have failed"); 128 warnx("MLKEM768_parse_private_key should have failed");
133 failed |= 1; 129 failed |= 1;
134 } 130 }
135 131
136 memcpy(encoded_private_key, first_two_bytes, sizeof(first_two_bytes)); 132 memcpy(encoded_private_key, first_two_bytes, sizeof(first_two_bytes));
137 CBS_init(&cbs, encoded_private_key, encoded_private_key_len);
138 133
139 if (!ctx->parse_private_key(ctx->priv2, &cbs)) { 134 if (!ctx->parse_private_key(ctx->priv2, encoded_private_key,
135 encoded_private_key_len)) {
140 warnx("MLKEM768_parse_private_key"); 136 warnx("MLKEM768_parse_private_key");
141 failed |= 1; 137 failed |= 1;
142 } 138 }
143 139
144 if (!ctx->encode_private_key(ctx->priv2, &tmp_buf, &tmp_buf_len)) { 140 if (!ctx->marshal_private_key(ctx->priv2, &tmp_buf, &tmp_buf_len)) {
145 warnx("encode_private_key"); 141 warnx("encode_private_key");
146 failed |= 1; 142 failed |= 1;
147 } 143 }
@@ -161,16 +157,22 @@ MlKemUnitTest(struct unittest_ctx *ctx)
161 tmp_buf = NULL; 157 tmp_buf = NULL;
162 158
163 ctx->encap(ctx->ciphertext, shared_secret1, ctx->pub); 159 ctx->encap(ctx->ciphertext, shared_secret1, ctx->pub);
164 ctx->decap(shared_secret2, ctx->ciphertext, ctx->ciphertext_len, 160 if (!ctx->decap(shared_secret2, ctx->ciphertext, ctx->ciphertext_len,
165 ctx->priv); 161 ctx->priv)) {
162 warnx("decap() failed using priv");
163 failed |= 1;
164 }
166 if (compare_data(shared_secret1, shared_secret2, MLKEM_SHARED_SECRET_BYTES, 165 if (compare_data(shared_secret1, shared_secret2, MLKEM_SHARED_SECRET_BYTES,
167 "shared secrets with priv") != 0) { 166 "shared secrets with priv") != 0) {
168 warnx("compare_data"); 167 warnx("compare_data");
169 failed |= 1; 168 failed |= 1;
170 } 169 }
171 170
172 ctx->decap(shared_secret2, ctx->ciphertext, ctx->ciphertext_len, 171 if (!ctx->decap(shared_secret2, ctx->ciphertext, ctx->ciphertext_len,
173 ctx->priv2); 172 ctx->priv2)) {
173 warnx("decap() failed using priv2");
174 failed |= 1;
175 }
174 if (compare_data(shared_secret1, shared_secret2, MLKEM_SHARED_SECRET_BYTES, 176 if (compare_data(shared_secret1, shared_secret2, MLKEM_SHARED_SECRET_BYTES,
175 "shared secrets with priv2") != 0) { 177 "shared secrets with priv2") != 0) {
176 warnx("compare_data"); 178 warnx("compare_data");
@@ -203,8 +205,8 @@ mlkem768_unittest(void)
203 .generate_key = mlkem768_generate_key, 205 .generate_key = mlkem768_generate_key,
204 .parse_private_key = mlkem768_parse_private_key, 206 .parse_private_key = mlkem768_parse_private_key,
205 .parse_public_key = mlkem768_parse_public_key, 207 .parse_public_key = mlkem768_parse_public_key,
206 .encode_private_key = mlkem768_encode_private_key, 208 .marshal_private_key = mlkem768_marshal_private_key,
207 .encode_public_key = mlkem768_encode_public_key, 209 .marshal_public_key = mlkem768_marshal_public_key,
208 .public_from_private = mlkem768_public_from_private, 210 .public_from_private = mlkem768_public_from_private,
209 }; 211 };
210 212
@@ -232,8 +234,8 @@ mlkem1024_unittest(void)
232 .generate_key = mlkem1024_generate_key, 234 .generate_key = mlkem1024_generate_key,
233 .parse_private_key = mlkem1024_parse_private_key, 235 .parse_private_key = mlkem1024_parse_private_key,
234 .parse_public_key = mlkem1024_parse_public_key, 236 .parse_public_key = mlkem1024_parse_public_key,
235 .encode_private_key = mlkem1024_encode_private_key, 237 .marshal_private_key = mlkem1024_marshal_private_key,
236 .encode_public_key = mlkem1024_encode_public_key, 238 .marshal_public_key = mlkem1024_marshal_public_key,
237 .public_from_private = mlkem1024_public_from_private, 239 .public_from_private = mlkem1024_public_from_private,
238 }; 240 };
239 241
@@ -248,7 +250,7 @@ main(void)
248 /* 250 /*
249 * XXX - this is split into two helper functions since having a few 251 * XXX - this is split into two helper functions since having a few
250 * ML-KEM key blobs on the stack makes Emscripten's stack explode, 252 * ML-KEM key blobs on the stack makes Emscripten's stack explode,
251 * leading to inscrutable silent failures unles ASAN is enabled. 253 * leading to inscrutable silent failures unless ASAN is enabled.
252 * Go figure. 254 * Go figure.
253 */ 255 */
254 256
diff --git a/src/regress/lib/libcrypto/mlkem/parse_test_file.c b/src/regress/lib/libcrypto/mlkem/parse_test_file.c
index 19f03439e2..9f3e5f3a1a 100644
--- a/src/regress/lib/libcrypto/mlkem/parse_test_file.c
+++ b/src/regress/lib/libcrypto/mlkem/parse_test_file.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: parse_test_file.c,v 1.3 2024/12/27 11:17:48 tb Exp $ */ 1/* $OpenBSD: parse_test_file.c,v 1.6 2025/06/03 10:29:37 tb Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> 4 * Copyright (c) 2024 Theo Buehler <tb@openbsd.org>
@@ -47,6 +47,8 @@ static void
47line_data_clear(struct line_data *ld) 47line_data_clear(struct line_data *ld)
48{ 48{
49 freezero(ld->data, ld->data_len); 49 freezero(ld->data, ld->data_len);
50 /* The dereference isn't enough for silly old gcc 14. */
51 assert(ld != NULL);
50 explicit_bzero(ld, sizeof(*ld)); 52 explicit_bzero(ld, sizeof(*ld));
51} 53}
52 54
@@ -644,7 +646,8 @@ parse_reinit(struct parse *p)
644 p->state.running_test_case = 0; 646 p->state.running_test_case = 0;
645 parse_line_data_clear(p); 647 parse_line_data_clear(p);
646 tctx->finish(p->ctx); 648 tctx->finish(p->ctx);
647 tctx->init(p->ctx, p); 649 if (!tctx->init(p->ctx, p))
650 parse_errx(p, "init failed");
648} 651}
649 652
650static int 653static int
@@ -706,7 +709,8 @@ parse_init(struct parse *p, const char *fn, const struct test_parse *tctx,
706 parse_state_init(&p->state, tctx->num_states, tctx->num_instructions); 709 parse_state_init(&p->state, tctx->num_states, tctx->num_instructions);
707 p->tctx = tctx; 710 p->tctx = tctx;
708 p->ctx = ctx; 711 p->ctx = ctx;
709 tctx->init(ctx, p); 712 if (!tctx->init(p->ctx, p))
713 parse_errx(p, "init failed");
710} 714}
711 715
712static int 716static int
@@ -732,7 +736,10 @@ parse_next_line(struct parse *p)
732static void 736static void
733parse_finish(struct parse *p) 737parse_finish(struct parse *p)
734{ 738{
739 const struct test_parse *tctx = p->tctx;
740
735 parse_state_finish(&p->state); 741 parse_state_finish(&p->state);
742 tctx->finish(p->ctx);
736 743
737 free(p->buf); 744 free(p->buf);
738 745
diff --git a/src/regress/lib/libcrypto/sha/Makefile b/src/regress/lib/libcrypto/sha/Makefile
index 6ec223116d..c6ab0398ba 100644
--- a/src/regress/lib/libcrypto/sha/Makefile
+++ b/src/regress/lib/libcrypto/sha/Makefile
@@ -1,9 +1,15 @@
1# $OpenBSD: Makefile,v 1.5 2022/09/01 14:02:41 tb Exp $ 1# $OpenBSD: Makefile,v 1.6 2025/05/22 03:35:40 joshua Exp $
2 2
3PROG = sha_test 3PROG = sha_test
4LDADD = -lcrypto 4LDADD = -lcrypto
5DPADD = ${LIBCRYPTO} 5DPADD = ${LIBCRYPTO}
6WARNINGS = Yes 6WARNINGS = Yes
7CFLAGS += -DLIBRESSL_INTERNAL -Werror 7CFLAGS += -DLIBRESSL_INTERNAL -Werror
8CFLAGS += -I${.CURDIR}/../test
9SRCS += sha_test.c
10SRCS += test.c
11SRCS += test_util.c
12
13.PATH: ${.CURDIR}/../test
8 14
9.include <bsd.regress.mk> 15.include <bsd.regress.mk>
diff --git a/src/regress/lib/libcrypto/sha/sha_test.c b/src/regress/lib/libcrypto/sha/sha_test.c
index 82a0c4cceb..904924c890 100644
--- a/src/regress/lib/libcrypto/sha/sha_test.c
+++ b/src/regress/lib/libcrypto/sha/sha_test.c
@@ -1,6 +1,6 @@
1/* $OpenBSD: sha_test.c,v 1.6 2023/07/19 15:11:42 joshua Exp $ */ 1/* $OpenBSD: sha_test.c,v 1.7 2025/05/22 03:35:40 joshua Exp $ */
2/* 2/*
3 * Copyright (c) 2022, 2023 Joshua Sing <joshua@hypera.dev> 3 * Copyright (c) 2022, 2023, 2025 Joshua Sing <joshua@joshuasing.dev>
4 * 4 *
5 * Permission to use, copy, modify, and distribute this software for any 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 6 * purpose with or without fee is hereby granted, provided that the above
@@ -21,6 +21,8 @@
21#include <stdint.h> 21#include <stdint.h>
22#include <string.h> 22#include <string.h>
23 23
24#include "test.h"
25
24struct sha_test { 26struct sha_test {
25 const int algorithm; 27 const int algorithm;
26 const uint8_t in[128]; 28 const uint8_t in[128];
@@ -677,260 +679,240 @@ typedef unsigned char *(*sha_hash_func)(const unsigned char *, size_t,
677 unsigned char *); 679 unsigned char *);
678 680
679static int 681static int
680sha_hash_from_algorithm(int algorithm, const char **out_label, 682sha_hash_from_algorithm(int algorithm, sha_hash_func *out_func,
681 sha_hash_func *out_func, const EVP_MD **out_md, size_t *out_len) 683 const EVP_MD **out_md)
682{ 684{
683 const char *label;
684 sha_hash_func sha_func; 685 sha_hash_func sha_func;
685 const EVP_MD *md; 686 const EVP_MD *md;
686 size_t len;
687 687
688 switch (algorithm) { 688 switch (algorithm) {
689 case NID_sha1: 689 case NID_sha1:
690 label = SN_sha1;
691 sha_func = SHA1; 690 sha_func = SHA1;
692 md = EVP_sha1(); 691 md = EVP_sha1();
693 len = SHA_DIGEST_LENGTH;
694 break; 692 break;
695 case NID_sha224: 693 case NID_sha224:
696 label = SN_sha224;
697 sha_func = SHA224; 694 sha_func = SHA224;
698 md = EVP_sha224(); 695 md = EVP_sha224();
699 len = SHA224_DIGEST_LENGTH;
700 break; 696 break;
701 case NID_sha256: 697 case NID_sha256:
702 label = SN_sha256;
703 sha_func = SHA256; 698 sha_func = SHA256;
704 md = EVP_sha256(); 699 md = EVP_sha256();
705 len = SHA256_DIGEST_LENGTH;
706 break; 700 break;
707 case NID_sha384: 701 case NID_sha384:
708 label = SN_sha384;
709 sha_func = SHA384; 702 sha_func = SHA384;
710 md = EVP_sha384(); 703 md = EVP_sha384();
711 len = SHA384_DIGEST_LENGTH;
712 break; 704 break;
713 case NID_sha512: 705 case NID_sha512:
714 label = SN_sha512;
715 sha_func = SHA512; 706 sha_func = SHA512;
716 md = EVP_sha512(); 707 md = EVP_sha512();
717 len = SHA512_DIGEST_LENGTH;
718 break; 708 break;
719 case NID_sha3_224: 709 case NID_sha3_224:
720 label = SN_sha3_224;
721 sha_func = NULL; 710 sha_func = NULL;
722 md = EVP_sha3_224(); 711 md = EVP_sha3_224();
723 len = 224 / 8;
724 break; 712 break;
725 case NID_sha3_256: 713 case NID_sha3_256:
726 label = SN_sha3_256;
727 sha_func = NULL; 714 sha_func = NULL;
728 md = EVP_sha3_256(); 715 md = EVP_sha3_256();
729 len = 256 / 8;
730 break; 716 break;
731 case NID_sha3_384: 717 case NID_sha3_384:
732 label = SN_sha3_384;
733 sha_func = NULL; 718 sha_func = NULL;
734 md = EVP_sha3_384(); 719 md = EVP_sha3_384();
735 len = 384 / 8;
736 break; 720 break;
737 case NID_sha3_512: 721 case NID_sha3_512:
738 label = SN_sha3_512;
739 sha_func = NULL; 722 sha_func = NULL;
740 md = EVP_sha3_512(); 723 md = EVP_sha3_512();
741 len = 512 / 8;
742 break; 724 break;
743 default: 725 default:
744 fprintf(stderr, "FAIL: unknown algorithm (%d)\n",
745 algorithm);
746 return 0; 726 return 0;
747 } 727 }
748 728
749 if (out_label != NULL)
750 *out_label = label;
751 if (out_func != NULL) 729 if (out_func != NULL)
752 *out_func = sha_func; 730 *out_func = sha_func;
753 if (out_md != NULL) 731 if (out_md != NULL)
754 *out_md = md; 732 *out_md = md;
755 if (out_len != NULL)
756 *out_len = len;
757 733
758 return 1; 734 return 1;
759} 735}
760 736
761static int 737static void
762sha_test(void) 738test_sha_tv(struct test *t, const void *arg)
763{ 739{
740 const struct sha_test *st = arg;
764 sha_hash_func sha_func; 741 sha_hash_func sha_func;
765 const struct sha_test *st;
766 EVP_MD_CTX *hash = NULL; 742 EVP_MD_CTX *hash = NULL;
767 const EVP_MD *md; 743 const EVP_MD *md;
768 uint8_t out[EVP_MAX_MD_SIZE]; 744 uint8_t out[EVP_MAX_MD_SIZE];
769 size_t in_len, out_len; 745 size_t in_len, out_len;
770 size_t i;
771 const char *label;
772 int failed = 1;
773 746
774 if ((hash = EVP_MD_CTX_new()) == NULL) { 747 if ((hash = EVP_MD_CTX_new()) == NULL) {
775 fprintf(stderr, "FAIL: EVP_MD_CTX_new() failed\n"); 748 test_errorf(t, "EVP_MD_CTX_new()");
776 goto failed; 749 goto fail;
777 } 750 }
778 751
779 for (i = 0; i < N_SHA_TESTS; i++) { 752 if (!sha_hash_from_algorithm(st->algorithm, &sha_func, &md))
780 st = &sha_tests[i]; 753 goto fail;
781 if (!sha_hash_from_algorithm(st->algorithm, &label, &sha_func,
782 &md, &out_len))
783 goto failed;
784
785 /* Digest */
786 if (sha_func != NULL) {
787 memset(out, 0, sizeof(out));
788 sha_func(st->in, st->in_len, out);
789 if (memcmp(st->out, out, out_len) != 0) {
790 fprintf(stderr, "FAIL (%s:%zu): mismatch\n",
791 label, i);
792 goto failed;
793 }
794 }
795 754
796 /* EVP single-shot digest */ 755 out_len = EVP_MD_size(md);
797 memset(out, 0, sizeof(out));
798 if (!EVP_Digest(st->in, st->in_len, out, NULL, md, NULL)) {
799 fprintf(stderr, "FAIL (%s:%zu): EVP_Digest failed\n",
800 label, i);
801 goto failed;
802 }
803 756
757 /* Digest */
758 if (sha_func != NULL) {
759 memset(out, 0, sizeof(out));
760 sha_func(st->in, st->in_len, out);
804 if (memcmp(st->out, out, out_len) != 0) { 761 if (memcmp(st->out, out, out_len) != 0) {
805 fprintf(stderr, 762 test_errorf(t, "SHA: digest output mismatch");
806 "FAIL (%s:%zu): EVP single-shot mismatch\n", 763 test_hexdiff(t, out, out_len, st->out);
807 label, i);
808 goto failed;
809 } 764 }
765 }
810 766
811 /* EVP digest */ 767 /* EVP single-shot digest */
812 memset(out, 0, sizeof(out)); 768 memset(out, 0, sizeof(out));
813 if (!EVP_DigestInit_ex(hash, md, NULL)) { 769 if (!EVP_Digest(st->in, st->in_len, out, NULL, md, NULL)) {
814 fprintf(stderr, 770 test_errorf(t, "EVP_Digest()");
815 "FAIL (%s:%zu): EVP_DigestInit_ex failed\n", 771 goto fail;
816 label, i); 772 }
817 goto failed;
818 }
819 773
820 in_len = st->in_len / 2; 774 if (memcmp(st->out, out, out_len) != 0) {
821 if (!EVP_DigestUpdate(hash, st->in, in_len)) { 775 test_errorf(t, "EVP single-shot: output diget mismatch");
822 fprintf(stderr, 776 test_hexdiff(t, out, out_len, st->out);
823 "FAIL (%s:%zu): EVP_DigestUpdate first half " 777 }
824 "failed\n", label, i);
825 goto failed;
826 }
827 778
828 if (!EVP_DigestUpdate(hash, st->in + in_len, 779 /* EVP digest */
829 st->in_len - in_len)) { 780 memset(out, 0, sizeof(out));
830 fprintf(stderr, 781 if (!EVP_DigestInit_ex(hash, md, NULL)) {
831 "FAIL (%s:%zu): EVP_DigestUpdate second half " 782 test_errorf(t, "EVP_DigestInit_ex() ");
832 "failed\n", label, i); 783 goto fail;
833 goto failed; 784 }
834 }
835 785
836 if (!EVP_DigestFinal_ex(hash, out, NULL)) { 786 in_len = st->in_len / 2;
837 fprintf(stderr, 787 if (!EVP_DigestUpdate(hash, st->in, in_len)) {
838 "FAIL (%s:%zu): EVP_DigestFinal_ex failed\n", 788 test_errorf(t, "EVP_DigestUpdate() first half");
839 label, i); 789 goto fail;
840 goto failed; 790 }
841 }
842 791
843 if (memcmp(st->out, out, out_len) != 0) { 792 if (!EVP_DigestUpdate(hash, st->in + in_len,
844 fprintf(stderr, "FAIL (%s:%zu): EVP mismatch\n", 793 st->in_len - in_len)) {
845 label, i); 794 test_errorf(t, "EVP_DigestUpdate() second half");
846 goto failed; 795 goto fail;
847 }
848 } 796 }
849 797
850 failed = 0; 798 if (!EVP_DigestFinal_ex(hash, out, NULL)) {
799 test_errorf(t, "EVP_DigestFinal_ex()");
800 goto fail;
801 }
851 802
852 failed: 803 if (memcmp(st->out, out, out_len) != 0) {
804 test_errorf(t, "EVP: digest output mismatch");
805 test_hexdiff(t, out, out_len, st->out);
806 }
807
808
809 fail:
853 EVP_MD_CTX_free(hash); 810 EVP_MD_CTX_free(hash);
854 return failed;
855} 811}
856 812
857static int 813static void
858sha_repetition_test(void) 814test_sha(struct test *t, const void *arg)
859{ 815{
860 const struct sha_repetition_test *st; 816 const struct sha_test *st;
817 size_t i;
818 char *name;
819
820 for (i = 0; i < N_SHA_TESTS; i++) {
821 st = &sha_tests[i];
822 if (asprintf(&name, "%s: '%s'", OBJ_nid2sn(st->algorithm), st->in) == -1) {
823 test_errorf(t, "create test name failed");
824 return;
825 }
826
827 test_run(t, name, test_sha_tv, st);
828 free(name);
829 }
830}
831
832static void
833test_sha_repetition_tv(struct test *t, const void *arg)
834{
835 const struct sha_repetition_test *st = arg;
861 EVP_MD_CTX *hash = NULL; 836 EVP_MD_CTX *hash = NULL;
862 const EVP_MD *md; 837 const EVP_MD *md;
863 uint8_t buf[1024]; 838 uint8_t buf[1024];
864 uint8_t out[EVP_MAX_MD_SIZE]; 839 uint8_t out[EVP_MAX_MD_SIZE];
865 size_t out_len, part_len; 840 size_t out_len, part_len;
866 size_t i, j; 841 size_t i;
867 const char *label;
868 int failed = 1;
869 842
870 if ((hash = EVP_MD_CTX_new()) == NULL) { 843 if ((hash = EVP_MD_CTX_new()) == NULL) {
871 fprintf(stderr, "FAIL: EVP_MD_CTX_new() failed\n"); 844 test_errorf(t, "EVP_MD_CTX_new()");
872 goto failed; 845 goto fail;
873 } 846 }
874 847
875 for (i = 0; i < N_SHA_REPETITION_TESTS; i++) { 848 if (!sha_hash_from_algorithm(st->algorithm, NULL, &md))
876 st = &sha_repetition_tests[i]; 849 goto fail;
877 if (!sha_hash_from_algorithm(st->algorithm, &label, NULL, &md,
878 &out_len))
879 goto failed;
880
881 /* EVP digest */
882 if (!EVP_DigestInit_ex(hash, md, NULL)) {
883 fprintf(stderr,
884 "FAIL (%s:%zu): EVP_DigestInit_ex failed\n",
885 label, i);
886 goto failed;
887 }
888 850
889 memset(buf, st->in, sizeof(buf)); 851 out_len = EVP_MD_size(md);
890 852
891 for (j = 0; j < st->in_repetitions;) { 853 /* EVP digest */
892 part_len = arc4random_uniform(sizeof(buf)); 854 if (!EVP_DigestInit_ex(hash, md, NULL)) {
893 if (part_len > st->in_repetitions - j) 855 test_errorf(t, "EVP_DigestInit_ex()");
894 part_len = st->in_repetitions - j; 856 goto fail;
857 }
895 858
896 if (!EVP_DigestUpdate(hash, buf, part_len)) { 859 memset(buf, st->in, sizeof(buf));
897 fprintf(stderr,
898 "FAIL (%s:%zu): EVP_DigestUpdate failed\n",
899 label, i);
900 goto failed;
901 }
902 860
903 j += part_len; 861 for (i = 0; i < st->in_repetitions;) {
904 } 862 part_len = arc4random_uniform(sizeof(buf));
863 if (part_len > st->in_repetitions - i)
864 part_len = st->in_repetitions - i;
905 865
906 if (!EVP_DigestFinal_ex(hash, out, NULL)) { 866 if (!EVP_DigestUpdate(hash, buf, part_len)) {
907 fprintf(stderr, 867 test_errorf(t, "EVP_DigestUpdate()");
908 "FAIL (%s:%zu): EVP_DigestFinal_ex failed\n", 868 goto fail;
909 label, i);
910 goto failed;
911 } 869 }
912 870
913 if (memcmp(st->out, out, out_len) != 0) { 871 i += part_len;
914 fprintf(stderr, "FAIL (%s:%zu): EVP mismatch\n", 872 }
915 label, i); 873
916 goto failed; 874 if (!EVP_DigestFinal_ex(hash, out, NULL)) {
917 } 875 test_errorf(t, "EVP_DigestFinal_ex()");
876 goto fail;
918 } 877 }
919 878
920 failed = 0; 879 if (memcmp(st->out, out, out_len) != 0) {
880 test_errorf(t, "EVP: digest output mismatch");
881 test_hexdiff(t, out, out_len, st->out);
882 goto fail;
883 }
921 884
922 failed: 885 fail:
923 EVP_MD_CTX_free(hash); 886 EVP_MD_CTX_free(hash);
924 return failed; 887}
888
889static void
890test_sha_repetition(struct test *t, const void *arg)
891{
892 const struct sha_repetition_test *st;
893 size_t i;
894 char *name;
895
896 for (i = 0; i < N_SHA_REPETITION_TESTS; i++) {
897 st = &sha_repetition_tests[i];
898 if (asprintf(&name, "%s: '%hhu' x %zu", OBJ_nid2sn(st->algorithm),
899 st->in, st->in_repetitions) == -1) {
900 test_errorf(t, "create test name failed");
901 return;
902 }
903
904 test_run(t, name, test_sha_repetition_tv, st);
905 free(name);
906 }
925} 907}
926 908
927int 909int
928main(int argc, char **argv) 910main(int argc, char **argv)
929{ 911{
930 int failed = 0; 912 struct test *t = test_init();
931 913
932 failed |= sha_test(); 914 test_run(t, "sha", test_sha, NULL);
933 failed |= sha_repetition_test(); 915 test_run(t, "sha repetition", test_sha_repetition, NULL);
934 916
935 return failed; 917 return test_result(t);
936} 918}
diff --git a/src/regress/lib/libcrypto/test/test.c b/src/regress/lib/libcrypto/test/test.c
new file mode 100644
index 0000000000..1188ec34ef
--- /dev/null
+++ b/src/regress/lib/libcrypto/test/test.c
@@ -0,0 +1,226 @@
1/* $OpenBSD: test.c,v 1.4 2025/05/31 11:36:48 tb Exp $ */
2/*
3 * Copyright (c) 2025 Joshua Sing <joshua@joshuasing.dev>
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 <err.h>
19#include <stdarg.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <unistd.h>
24
25#include "test.h"
26
27struct test {
28 struct test *parent;
29 char *name;
30 FILE *out;
31 int skipped;
32 int failed;
33};
34
35static struct test *
36test_new(struct test *pt, const char *name)
37{
38 struct test *t;
39
40 if ((t = calloc(1, sizeof(*t))) == NULL)
41 err(1, "calloc");
42
43 if (name != NULL) {
44 if ((t->name = strdup(name)) == NULL)
45 err(1, "strdup");
46 }
47
48 if (pt != NULL)
49 t->out = pt->out;
50 t->parent = pt;
51
52 return t;
53}
54
55struct test *
56test_init(void)
57{
58 struct test *t;
59 char *tmp_file;
60 int out_fd;
61 char *v;
62
63 t = test_new(NULL, NULL);
64 t->out = stderr;
65
66 if (((v = getenv("TEST_VERBOSE")) != NULL) && strcmp(v, "0") != 0)
67 return t;
68
69 /* Create a temporary file for logging in non-verbose mode */
70 if ((tmp_file = strdup("/tmp/libressl-test.XXXXXXXX")) == NULL)
71 err(1, "strdup");
72 if ((out_fd = mkstemp(tmp_file)) == -1)
73 err(1, "mkstemp");
74
75 unlink(tmp_file);
76 free(tmp_file);
77 if ((t->out = fdopen(out_fd, "w+")) == NULL)
78 err(1, "fdopen");
79
80 return t;
81}
82
83static void
84test_cleanup(struct test *t)
85{
86 free(t->name);
87 free(t);
88}
89
90int
91test_result(struct test *t)
92{
93 int failed = t->failed;
94
95 if (t->parent == NULL && t->out != stderr)
96 fclose(t->out);
97
98 test_cleanup(t);
99
100 return failed;
101}
102
103void
104test_fail(struct test *t)
105{
106 t->failed = 1;
107
108 /* Also fail parent. */
109 if (t->parent != NULL)
110 test_fail(t->parent);
111}
112
113static void
114test_vprintf(struct test *t, const char *fmt, va_list ap)
115{
116 if (vfprintf(t->out, fmt, ap) == -1)
117 err(1, "vfprintf");
118}
119
120void
121test_printf(struct test *t, const char *fmt, ...)
122{
123 va_list ap;
124
125 va_start(ap, fmt);
126 test_vprintf(t, fmt, ap);
127 va_end(ap);
128}
129
130static void
131test_vlogf_internal(struct test *t, const char *label, const char *func,
132 const char *file, int line, const char *fmt, va_list ap)
133{
134 char *msg = NULL;
135 char *l = ": ";
136 const char *filename;
137
138 if (label == NULL) {
139 label = "";
140 l = "";
141 }
142
143 if (vasprintf(&msg, fmt, ap) == -1)
144 err(1, "vasprintf");
145
146 if ((filename = strrchr(file, '/')) != NULL)
147 filename++;
148 else
149 filename = file;
150
151 test_printf(t, "%s [%s:%d]%s%s: %s\n",
152 func, filename, line, l, label, msg);
153
154 free(msg);
155}
156
157void
158test_logf_internal(struct test *t, const char *label, const char *func,
159 const char *file, int line, const char *fmt, ...)
160{
161 va_list ap;
162
163 va_start(ap, fmt);
164 test_vlogf_internal(t, label, func, file, line, fmt, ap);
165 va_end(ap);
166}
167
168void
169test_skip(struct test *t, const char *reason)
170{
171 t->skipped = 1;
172 test_printf(t, "%s\n", reason);
173}
174
175void
176test_skipf(struct test *t, const char *fmt, ...)
177{
178 va_list ap;
179
180 t->skipped = 1;
181
182 va_start(ap, fmt);
183 test_vprintf(t, fmt, ap);
184 if (fputc('\n', t->out) == EOF)
185 err(1, "fputc");
186 va_end(ap);
187}
188
189void
190test_run(struct test *pt, const char *name, test_run_func *fn, const void *arg)
191{
192 struct test *t = test_new(pt, name);
193 char *status = "PASS";
194 char buf[1024];
195 size_t buflen;
196 int ferr;
197
198 /* Run test */
199 test_printf(t, "=== RUN %s\n", t->name);
200 fn(t, arg);
201
202 if (t->skipped)
203 status = "SKIP";
204 if (t->failed)
205 status = "FAIL";
206
207 test_printf(t, "--- %s: %s\n\n", status, t->name);
208
209 /* Print result of test */
210 if (t->failed && t->out != stderr) {
211 /* Copy logs to stderr */
212 rewind(t->out);
213 while ((buflen = fread(buf, 1, sizeof(buf), t->out)) > 0)
214 fwrite(buf, 1, buflen, stderr);
215 if ((ferr = ferror(t->out)) != 0)
216 errx(1, "ferror: %d", ferr);
217 }
218
219 if (t->out != NULL && t->out != stderr) {
220 /* Reset output file */
221 rewind(t->out);
222 ftruncate(fileno(t->out), 0);
223 }
224
225 test_cleanup(t);
226}
diff --git a/src/regress/lib/libcrypto/test/test.h b/src/regress/lib/libcrypto/test/test.h
new file mode 100644
index 0000000000..1c8391d4ec
--- /dev/null
+++ b/src/regress/lib/libcrypto/test/test.h
@@ -0,0 +1,137 @@
1/* $OpenBSD: test.h,v 1.4 2025/05/31 11:37:18 tb Exp $ */
2/*
3 * Copyright (c) 2025 Joshua Sing <joshua@joshuasing.dev>
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#ifndef HEADER_TEST_H
19#define HEADER_TEST_H
20
21#include <stddef.h>
22#include <stdint.h>
23
24struct test;
25
26/*
27 * test_init creates a new root test struct.
28 *
29 * Additional tests may be run under the root test struct by calling test_run.
30 *
31 * If the TEST_VERBOSE environment variable is set and not equal to "0", then
32 * verbose mode will be enabled and all test logs will be written to stderr.
33 */
34struct test *test_init(void);
35
36/*
37 * test_result cleans up after all tests have completed and returns an
38 * appropriate exit code indicating the result of the tests.
39 */
40int test_result(struct test *_t);
41
42/*
43 * test_run_func is an individual test function. It is passed the test struct
44 * and an arbitrary argument which may be passed when test_run is called.
45 */
46typedef void (test_run_func)(struct test *_t, const void *_arg);
47
48/*
49 * test_fail marks the test and its parents as failed.
50 */
51void test_fail(struct test *_t);
52
53/*
54 * test_printf prints a test log message. When in verbose mode, the log message
55 * will be written to stderr, otherwise it will be buffered and only written to
56 * stderr if the test fails.
57 *
58 * This printf will write directly, without any additional formatting.
59 */
60void test_printf(struct test *_t, const char *_fmt, ...)
61 __attribute__((__format__ (printf, 2, 3)))
62 __attribute__((__nonnull__ (2)));
63
64/*
65 * test_logf_internal prints a test log message. When in verbose mode, the
66 * log message will be written to stderr, otherwise it will be buffered and
67 * only written to stderr if the test fails.
68 *
69 * label is an optional label indicating the severity of the log.
70 * func, file and line are used to show where the log comes from and are
71 * automatically set in the test log macros.
72 *
73 * This function should never be called directly.
74 */
75void test_logf_internal(struct test *_t, const char *_label, const char *_func,
76 const char *_file, int _line, const char *_fmt, ...)
77 __attribute__((__format__ (printf, 6, 7)))
78 __attribute__((__nonnull__ (6)));
79
80/*
81 * test_logf prints an informational log message. When in verbose mode, the log
82 * will be written to stderr, otherwise it will be buffered and only written to
83 * stderr if the test fails.
84 */
85#define test_logf(t, fmt, ...) \
86 do { \
87 test_logf_internal(t, NULL, __func__, __FILE__, __LINE__, fmt, ##__VA_ARGS__); \
88 } while (0)
89
90/*
91 * test_errorf prints an error message. It will also cause the test to fail.
92 * If the test cannot proceed, it is recommended to return or goto a cleanup
93 * label.
94 *
95 * Tests should not fail-fast if continuing will provide more detailed
96 * information about what is broken.
97 */
98#define test_errorf(t, fmt, ...) \
99 do { \
100 test_logf_internal(t, "ERROR", __func__, __FILE__, __LINE__, fmt, ##__VA_ARGS__); \
101 test_fail(t); \
102 } while (0)
103
104/*
105 * test_skip marks the test as skipped. Once called, the test should return.
106 */
107void test_skip(struct test *_t, const char *_reason);
108
109/*
110 * test_skipf marks the test as skipped with a formatted reason. Once called,
111 * the test should return.
112 */
113void test_skipf(struct test *_t, const char *_fmt, ...)
114 __attribute__((__format__ (printf, 2, 3)))
115 __attribute__((__nonnull__ (2)));
116
117/*
118 * test_run runs a test function. It will create a new test struct with the
119 * given test as the parent. An argument may be provided to pass data to the
120 * test function, otherwise NULL should be passed.
121 *
122 * Each test should have a unique and informational name.
123 */
124void test_run(struct test *_t, const char *_name, test_run_func *_fn, const void *_arg);
125
126/*
127 * test_hexdump prints the given data as hexadecimal.
128 */
129void test_hexdump(struct test *_t, const unsigned char *_buf, size_t _len);
130
131/*
132 * test_hexdiff prints the given data as hexadecimal. If a second comparison
133 * buffer is not NULL, any differing bytes will be marked with an astrix.
134 */
135void test_hexdiff(struct test *_t, const uint8_t *_buf, size_t _len, const uint8_t *_compare);
136
137#endif /* HEADER_TEST_H */
diff --git a/src/regress/lib/libcrypto/test/test_util.c b/src/regress/lib/libcrypto/test/test_util.c
new file mode 100644
index 0000000000..6ecb574788
--- /dev/null
+++ b/src/regress/lib/libcrypto/test/test_util.c
@@ -0,0 +1,51 @@
1/* $OpenBSD: test_util.c,v 1.1 2025/05/21 08:57:13 joshua Exp $ */
2/*
3 * Copyright (c) 2017 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2024 Theo Buehler <tb@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <stdio.h>
20#include <stdint.h>
21
22#include "test.h"
23
24void
25test_hexdump(struct test *t, const unsigned char *buf, size_t len)
26{
27 size_t i;
28
29 for (i = 1; i <= len; i++)
30 test_printf(t, " 0x%02x,%s", buf[i - 1], i % 8 ? "" : "\n");
31
32 if ((len % 8) != 0)
33 test_printf(t, "\n");
34}
35
36void
37test_hexdiff(struct test *t, const uint8_t *buf, size_t len, const uint8_t *compare)
38{
39 const char *mark = "", *newline;
40 size_t i;
41
42 for (i = 1; i <= len; i++) {
43 if (compare != NULL)
44 mark = (buf[i - 1] != compare[i - 1]) ? "*" : " ";
45 newline = i % 8 ? "" : "\n";
46 test_printf(t, " %s0x%02x,%s", mark, buf[i - 1], newline);
47 }
48
49 if ((len % 8) != 0)
50 test_printf(t, "\n");
51}
diff --git a/src/regress/lib/libcrypto/wycheproof/Makefile b/src/regress/lib/libcrypto/wycheproof/Makefile
index f2f7910b5b..a68a270580 100644
--- a/src/regress/lib/libcrypto/wycheproof/Makefile
+++ b/src/regress/lib/libcrypto/wycheproof/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.9 2023/07/08 19:41:07 tb Exp $ 1# $OpenBSD: Makefile,v 1.10 2025/07/09 05:04:35 tb Exp $
2 2
3WYCHEPROOF_TESTVECTORS = /usr/local/share/wycheproof/testvectors/ 3WYCHEPROOF_TESTVECTORS = /usr/local/share/wycheproof/testvectors/
4 4
@@ -18,11 +18,17 @@ REGRESS_TARGETS += regress-wycheproof
18CLEANFILES += wycheproof 18CLEANFILES += wycheproof
19 19
20wycheproof: wycheproof.go 20wycheproof: wycheproof.go
21 go build -o wycheproof ${.CURDIR}/wycheproof.go 21 env GOCACHE=${.OBJDIR}/go-build go build -o wycheproof ${.CURDIR}/wycheproof.go
22 22
23regress-wycheproof: wycheproof 23regress-wycheproof: wycheproof
24 ./wycheproof 24 ./wycheproof
25 25
26REGRESS_CLEANUP = clean-go-cache
27
28clean-go-cache:
29 env GOCACHE=${.OBJDIR}/go-build go clean -cache
30 rm -rf ${.OBJDIR}/go-build
31
26. endif 32. endif
27 33
28PROGS += wycheproof-primes 34PROGS += wycheproof-primes
diff --git a/src/regress/lib/libcrypto/x509/Makefile b/src/regress/lib/libcrypto/x509/Makefile
index 80879f6e3c..94e9e476a0 100644
--- a/src/regress/lib/libcrypto/x509/Makefile
+++ b/src/regress/lib/libcrypto/x509/Makefile
@@ -1,7 +1,8 @@
1# $OpenBSD: Makefile,v 1.23 2024/06/16 17:57:08 tb Exp $ 1# $OpenBSD: Makefile,v 1.25 2025/05/05 06:33:34 tb Exp $
2 2
3PROGS = constraints verify x509attribute x509name x509req_ext callback 3PROGS = constraints verify x509attribute x509req_ext callback
4PROGS += expirecallback callbackfailures x509_asn1 x509_extensions_test 4PROGS += expirecallback callbackfailures x509_asn1 x509_extensions_test
5PROGS += x509_name_test
5LDADD = -lcrypto 6LDADD = -lcrypto
6DPADD = ${LIBCRYPTO} 7DPADD = ${LIBCRYPTO}
7 8
@@ -15,7 +16,7 @@ CFLAGS += -I${.CURDIR}/../../../../lib/libcrypto/bytestring
15 16
16SUBDIR += bettertls policy rfc3779 17SUBDIR += bettertls policy rfc3779
17 18
18CLEANFILES += x509name.result callback.out 19CLEANFILES += callback.out
19 20
20.if make(clean) || make(cleandir) 21.if make(clean) || make(cleandir)
21. if ${.OBJDIR} != ${.CURDIR} 22. if ${.OBJDIR} != ${.CURDIR}
@@ -28,10 +29,6 @@ run-regress-verify: verify
28 perl ${.CURDIR}/make-dir-roots.pl ${.CURDIR}/../certs . 29 perl ${.CURDIR}/make-dir-roots.pl ${.CURDIR}/../certs .
29 ./verify ${.CURDIR}/../certs 30 ./verify ${.CURDIR}/../certs
30 31
31run-regress-x509name: x509name
32 ./x509name > x509name.result
33 diff -u ${.CURDIR}/x509name.expected x509name.result
34
35run-regress-callback: callback 32run-regress-callback: callback
36 ./callback ${.CURDIR}/../certs 33 ./callback ${.CURDIR}/../certs
37 perl ${.CURDIR}/callback.pl callback.out 34 perl ${.CURDIR}/callback.pl callback.out
diff --git a/src/regress/lib/libcrypto/x509/bettertls/Makefile b/src/regress/lib/libcrypto/x509/bettertls/Makefile
index 2724140635..2a06239fc5 100644
--- a/src/regress/lib/libcrypto/x509/bettertls/Makefile
+++ b/src/regress/lib/libcrypto/x509/bettertls/Makefile
@@ -1,10 +1,10 @@
1# $OpenBSD: Makefile,v 1.6 2024/12/27 08:02:27 tb Exp $ 1# $OpenBSD: Makefile,v 1.7 2025/07/23 07:46:12 tb Exp $
2 2
3PROGS = verify 3PROGS = verify
4 4
5.ifdef EOPENSSL33 5.ifdef EOPENSSL35
6LDADD += -Wl,-rpath,/usr/local/lib/eopenssl33 -L/usr/local/lib/eopenssl33 6LDADD += -Wl,-rpath,/usr/local/lib/eopenssl35 -L/usr/local/lib/eopenssl35
7CFLAGS += -I/usr/local/include/eopenssl33/ 7CFLAGS += -I/usr/local/include/eopenssl35/
8.endif 8.endif
9 9
10LDADD += -lcrypto 10LDADD += -lcrypto
diff --git a/src/regress/lib/libcrypto/x509/x509_name_test.c b/src/regress/lib/libcrypto/x509/x509_name_test.c
new file mode 100644
index 0000000000..24e62cc766
--- /dev/null
+++ b/src/regress/lib/libcrypto/x509/x509_name_test.c
@@ -0,0 +1,420 @@
1/* $OpenBSD: x509_name_test.c,v 1.3 2025/05/05 06:33:34 tb Exp $ */
2
3/*
4 * Copyright (c) 2025 Theo Buehler <tb@openbsd.org>
5 * Copyright (c) 2025 Kenjiro Nakayama <nakayamakenjiro@gmail.com>
6 * Copyright (c) 2018 Ingo Schwarze <schwarze@openbsd.org>
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */
20
21#include <err.h>
22#include <stdio.h>
23#include <string.h>
24
25#include <openssl/x509.h>
26
27static const struct x509_name_legacy {
28 const char *compat;
29 const char *oneline;
30 const uint8_t der[255];
31 size_t der_len;
32} x509_name_legacy_test[] = {
33 {
34 .compat =
35 "C=HU, "
36 "L=Budapest, "
37 "O=Microsec Ltd., "
38 "CN=Microsec e-Szigno Root CA 2009, "
39 "emailAddress=info@e-szigno.hu",
40 .oneline =
41 "/C=HU"
42 "/L=Budapest"
43 "/O=Microsec Ltd."
44 "/CN=Microsec e-Szigno Root CA 2009"
45 "/emailAddress=info@e-szigno.hu",
46 .der = {
47 0x30, 0x81, 0x82, 0x31, 0x0b, 0x30, 0x09, 0x06,
48 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x48, 0x55,
49 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04,
50 0x07, 0x0c, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70,
51 0x65, 0x73, 0x74, 0x31, 0x16, 0x30, 0x14, 0x06,
52 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0d, 0x4d, 0x69,
53 0x63, 0x72, 0x6f, 0x73, 0x65, 0x63, 0x20, 0x4c,
54 0x74, 0x64, 0x2e, 0x31, 0x27, 0x30, 0x25, 0x06,
55 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1e, 0x4d, 0x69,
56 0x63, 0x72, 0x6f, 0x73, 0x65, 0x63, 0x20, 0x65,
57 0x2d, 0x53, 0x7a, 0x69, 0x67, 0x6e, 0x6f, 0x20,
58 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20,
59 0x32, 0x30, 0x30, 0x39, 0x31, 0x1f, 0x30, 0x1d,
60 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
61 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6e, 0x66,
62 0x6f, 0x40, 0x65, 0x2d, 0x73, 0x7a, 0x69, 0x67,
63 0x6e, 0x6f, 0x2e, 0x68, 0x75,
64 },
65 .der_len = 133,
66 },
67
68 {
69 .compat =
70 "serialNumber=G63287510, "
71 "C=ES, "
72 "O=ANF Autoridad de Certificacion, "
73 "OU=ANF CA Raiz, "
74 "CN=ANF Secure Server Root CA",
75 .oneline =
76 "/serialNumber=G63287510"
77 "/C=ES"
78 "/O=ANF Autoridad de Certificacion"
79 "/OU=ANF CA Raiz"
80 "/CN=ANF Secure Server Root CA",
81 .der = {
82 0x30, 0x81, 0x84, 0x31, 0x12, 0x30, 0x10, 0x06,
83 0x03, 0x55, 0x04, 0x05, 0x13, 0x09, 0x47, 0x36,
84 0x33, 0x32, 0x38, 0x37, 0x35, 0x31, 0x30, 0x31,
85 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
86 0x13, 0x02, 0x45, 0x53, 0x31, 0x27, 0x30, 0x25,
87 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1e, 0x41,
88 0x4e, 0x46, 0x20, 0x41, 0x75, 0x74, 0x6f, 0x72,
89 0x69, 0x64, 0x61, 0x64, 0x20, 0x64, 0x65, 0x20,
90 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
91 0x61, 0x63, 0x69, 0x6f, 0x6e, 0x31, 0x14, 0x30,
92 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b,
93 0x41, 0x4e, 0x46, 0x20, 0x43, 0x41, 0x20, 0x52,
94 0x61, 0x69, 0x7a, 0x31, 0x22, 0x30, 0x20, 0x06,
95 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x41, 0x4e,
96 0x46, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65,
97 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20,
98 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41,
99 },
100 .der_len = 135,
101 },
102
103 {
104 .compat =
105 "C=GB, "
106 "ST=Greater Manchester, "
107 "L=Salford, "
108 "O=COMODO CA Limited, "
109 "CN=COMODO Certification Authority",
110 .oneline =
111 "/C=GB"
112 "/ST=Greater Manchester"
113 "/L=Salford"
114 "/O=COMODO CA Limited"
115 "/CN=COMODO Certification Authority",
116 .der = {
117 0x30, 0x81, 0x81, 0x31, 0x0b, 0x30, 0x09, 0x06,
118 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42,
119 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04,
120 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74,
121 0x65, 0x72, 0x20, 0x4d, 0x61, 0x6e, 0x63, 0x68,
122 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30,
123 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07,
124 0x53, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x64, 0x31,
125 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a,
126 0x13, 0x11, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f,
127 0x20, 0x43, 0x41, 0x20, 0x4c, 0x69, 0x6d, 0x69,
128 0x74, 0x65, 0x64, 0x31, 0x27, 0x30, 0x25, 0x06,
129 0x03, 0x55, 0x04, 0x03, 0x13, 0x1e, 0x43, 0x4f,
130 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x43, 0x65, 0x72,
131 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
132 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f,
133 0x72, 0x69, 0x74, 0x79,
134 },
135 .der_len = 132,
136 },
137
138 {
139 .compat =
140 "C=HU, "
141 "L=Budapest, "
142 "O=Microsec Ltd., "
143 "2.5.4.97=VATHU-23584497, "
144 "CN=e-Szigno Root CA 2017",
145 .oneline =
146 "/C=HU"
147 "/L=Budapest"
148 "/O=Microsec Ltd."
149 "/2.5.4.97=VATHU-23584497"
150 "/CN=e-Szigno Root CA 2017",
151 .der = {
152 0x30, 0x71, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
153 0x55, 0x04, 0x06, 0x13, 0x02, 0x48, 0x55, 0x31,
154 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07,
155 0x0c, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65,
156 0x73, 0x74, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03,
157 0x55, 0x04, 0x0a, 0x0c, 0x0d, 0x4d, 0x69, 0x63,
158 0x72, 0x6f, 0x73, 0x65, 0x63, 0x20, 0x4c, 0x74,
159 0x64, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03,
160 0x55, 0x04, 0x61, 0x0c, 0x0e, 0x56, 0x41, 0x54,
161 0x48, 0x55, 0x2d, 0x32, 0x33, 0x35, 0x38, 0x34,
162 0x34, 0x39, 0x37, 0x31, 0x1e, 0x30, 0x1c, 0x06,
163 0x03, 0x55, 0x04, 0x03, 0x0c, 0x15, 0x65, 0x2d,
164 0x53, 0x7a, 0x69, 0x67, 0x6e, 0x6f, 0x20, 0x52,
165 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32,
166 0x30, 0x31, 0x37,
167 },
168 .der_len = 115,
169 },
170
171 {
172
173 .compat =
174 "C=ES, "
175 "O=FNMT-RCM, "
176 "OU=Ceres, "
177 "2.5.4.97=VATES-Q2826004J, "
178 "CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS",
179 .oneline =
180 "/C=ES"
181 "/O=FNMT-RCM"
182 "/OU=Ceres"
183 "/2.5.4.97=VATES-Q2826004J"
184 "/CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS",
185 .der = {
186 0x30, 0x78, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
187 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53, 0x31,
188 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a,
189 0x0c, 0x08, 0x46, 0x4e, 0x4d, 0x54, 0x2d, 0x52,
190 0x43, 0x4d, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x03,
191 0x55, 0x04, 0x0b, 0x0c, 0x05, 0x43, 0x65, 0x72,
192 0x65, 0x73, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03,
193 0x55, 0x04, 0x61, 0x0c, 0x0f, 0x56, 0x41, 0x54,
194 0x45, 0x53, 0x2d, 0x51, 0x32, 0x38, 0x32, 0x36,
195 0x30, 0x30, 0x34, 0x4a, 0x31, 0x2c, 0x30, 0x2a,
196 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x23, 0x41,
197 0x43, 0x20, 0x52, 0x41, 0x49, 0x5a, 0x20, 0x46,
198 0x4e, 0x4d, 0x54, 0x2d, 0x52, 0x43, 0x4d, 0x20,
199 0x53, 0x45, 0x52, 0x56, 0x49, 0x44, 0x4f, 0x52,
200 0x45, 0x53, 0x20, 0x53, 0x45, 0x47, 0x55, 0x52,
201 0x4f, 0x53
202 },
203 .der_len = 122,
204 },
205};
206
207#define N_X509_NAME_COMPAT \
208 (sizeof(x509_name_legacy_test) / sizeof(x509_name_legacy_test[0]))
209
210static int
211x509_name_compat_testcase(const struct x509_name_legacy *test)
212{
213 const uint8_t *p;
214 X509_NAME *name = NULL;
215 unsigned char *der = NULL;
216 int der_len = 0;
217 BIO *bio = NULL;
218 char *got;
219 int got_len;
220 char *buf = NULL;
221 int failed = 1;
222
223 p = test->der;
224 if ((name = d2i_X509_NAME(NULL, &p, test->der_len)) == NULL)
225 errx(1, "d2i_X509_NAME");
226
227 if ((der_len = i2d_X509_NAME(name, &der)) <= 0) {
228 fprintf(stderr, "FAIL: %s: i2d_X509_NAME", __func__);
229 der_len = 0;
230 goto err;
231 }
232
233 if (test->der_len != (size_t)der_len) {
234 fprintf(stderr, "FAIL: %s: der len: want %zu, got %d\n",
235 __func__, test->der_len, der_len);
236 goto err;
237 }
238
239 if (memcmp(test->der, der, test->der_len) != 0) {
240 fprintf(stderr, "FAIL: %s: DER mismatch\n", __func__);
241 goto err;
242 }
243
244 if ((bio = BIO_new(BIO_s_mem())) == NULL)
245 errx(1, "BIO_new");
246
247 if (!X509_NAME_print_ex(bio, name, 0, XN_FLAG_COMPAT)) {
248 fprintf(stderr, "FAIL: %s: X509_NAME_print_ex", __func__);
249 goto err;
250 }
251
252 if ((got_len = BIO_get_mem_data(bio, &got)) < 0)
253 errx(1, "BIO_get_mem_data");
254
255 if (strcmp(test->compat, got) != 0) {
256 fprintf(stderr, "FAIL: %s compat:\nwant: \"%s\",\ngot: \"%s\"\n",
257 __func__, test->compat, got);
258 goto err;
259 }
260
261 if ((buf = X509_NAME_oneline(name, NULL, 0)) == NULL)
262 errx(1, "X509_NAME_oneline");
263
264 if (strcmp(test->oneline, buf) != 0) {
265 fprintf(stderr, "FAIL: %s oneline:\nwant: \"%s\",\ngot: \"%s\"\n",
266 __func__, test->compat, got);
267 goto err;
268 }
269
270 failed = 0;
271
272 err:
273 BIO_free(bio);
274 free(buf);
275 X509_NAME_free(name);
276 freezero(der, der_len);
277
278 return failed;
279}
280
281static int
282x509_name_compat_test(void)
283{
284 size_t i;
285 int failed = 0;
286
287 for (i = 0; i < N_X509_NAME_COMPAT; i++)
288 failed |= x509_name_compat_testcase(&x509_name_legacy_test[i]);
289
290 return failed;
291}
292
293static const struct x509_name_entry_test {
294 const char *field;
295 const char *value;
296 int loc;
297 int set;
298 const char *expected_str;
299 const int expected_set[4];
300 const int expected_count;
301} entry_tests[] = {
302 {
303 .field = "ST",
304 .value = "BaWue",
305 .loc = -1,
306 .set = 0,
307 .expected_str = "ST=BaWue",
308 .expected_set = { 0 },
309 .expected_count = 1,
310 },
311 {
312 .field = "O",
313 .value = "KIT",
314 .loc = -1,
315 .set = 0,
316 .expected_str = "ST=BaWue, O=KIT",
317 .expected_set = { 0, 1 },
318 .expected_count = 2,
319 },
320 {
321 .field = "L",
322 .value = "Karlsruhe",
323 .loc = 1,
324 .set = 0,
325 .expected_str = "ST=BaWue, L=Karlsruhe, O=KIT",
326 .expected_set = { 0, 1, 2 },
327 .expected_count = 3,
328 },
329 {
330 .field = "C",
331 .value = "DE",
332 .loc = 0,
333 .set = 1,
334 .expected_str = "C=DE + ST=BaWue, L=Karlsruhe, O=KIT",
335 .expected_set = { 0, 0, 1, 2 },
336 .expected_count = 4,
337 },
338};
339
340#define N_ENTRY_TESTS (sizeof(entry_tests) / sizeof(entry_tests[0]))
341
342static int
343verify_x509_name_output(X509_NAME *name, const struct x509_name_entry_test *tc)
344{
345 BIO *bio;
346 char *got;
347 long got_len;
348 int loc, ret;
349 int failed = 1;
350
351 if ((bio = BIO_new(BIO_s_mem())) == NULL)
352 goto fail;
353
354 if ((ret = X509_NAME_print_ex(bio, name, 0, XN_FLAG_SEP_CPLUS_SPC)) == -1)
355 goto fail;
356
357 if ((got_len = BIO_get_mem_data(bio, &got)) < 0)
358 goto fail;
359
360 if (ret != got_len || strlen(tc->expected_str) != (size_t)ret)
361 goto fail;
362
363 if (strncmp(tc->expected_str, got, got_len) != 0)
364 goto fail;
365
366 if (X509_NAME_entry_count(name) != tc->expected_count)
367 goto fail;
368
369 for (loc = 0; loc < X509_NAME_entry_count(name); loc++) {
370 X509_NAME_ENTRY *e = X509_NAME_get_entry(name, loc);
371 if (e == NULL || X509_NAME_ENTRY_set(e) != tc->expected_set[loc])
372 goto fail;
373 }
374
375 failed = 0;
376
377 fail:
378 BIO_free(bio);
379
380 return failed;
381}
382
383static int
384x509_name_add_entry_test(void)
385{
386 X509_NAME *name;
387 int failed = 1;
388
389 if ((name = X509_NAME_new()) == NULL)
390 goto done;
391
392 for (size_t i = 0; i < N_ENTRY_TESTS; i++) {
393 const struct x509_name_entry_test *t = &entry_tests[i];
394
395 if (!X509_NAME_add_entry_by_txt(name, t->field, MBSTRING_ASC,
396 (const unsigned char *)t->value, -1, t->loc, t->set))
397 goto done;
398
399 if (verify_x509_name_output(name, t))
400 goto done;
401 }
402
403 failed = 0;
404
405 done:
406 X509_NAME_free(name);
407
408 return failed;
409}
410
411int
412main(void)
413{
414 int failed = 0;
415
416 failed |= x509_name_compat_test();
417 failed |= x509_name_add_entry_test();
418
419 return failed;
420}
diff --git a/src/regress/lib/libcrypto/x509/x509name.c b/src/regress/lib/libcrypto/x509/x509name.c
deleted file mode 100644
index 9deeeb2986..0000000000
--- a/src/regress/lib/libcrypto/x509/x509name.c
+++ /dev/null
@@ -1,62 +0,0 @@
1/* $OpenBSD: x509name.c,v 1.3 2021/10/31 08:27:15 tb Exp $ */
2/*
3 * Copyright (c) 2018 Ingo Schwarze <schwarze@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 <err.h>
19#include <stdio.h>
20
21#include <openssl/x509.h>
22
23static void debug_print(X509_NAME *);
24
25static void
26debug_print(X509_NAME *name)
27{
28 int loc;
29
30 for (loc = 0; loc < X509_NAME_entry_count(name); loc++)
31 printf("%d:",
32 X509_NAME_ENTRY_set(X509_NAME_get_entry(name, loc)));
33 putchar(' ');
34 X509_NAME_print_ex_fp(stdout, name, 0, XN_FLAG_SEP_CPLUS_SPC);
35 putchar('\n');
36}
37
38int
39main(void)
40{
41 X509_NAME *name;
42
43 if ((name = X509_NAME_new()) == NULL)
44 err(1, NULL);
45 X509_NAME_add_entry_by_txt(name, "ST", MBSTRING_ASC,
46 "BaWue", -1, -1, 0);
47 X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC,
48 "KIT", -1, -1, 0);
49 debug_print(name);
50
51 X509_NAME_add_entry_by_txt(name, "L", MBSTRING_ASC,
52 "Karlsruhe", -1, 1, 0);
53 debug_print(name);
54
55 X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC,
56 "DE", -1, 0, 1);
57 debug_print(name);
58
59 X509_NAME_free(name);
60
61 return 0;
62}
diff --git a/src/regress/lib/libcrypto/x509/x509name.expected b/src/regress/lib/libcrypto/x509/x509name.expected
deleted file mode 100644
index 6cee7cc435..0000000000
--- a/src/regress/lib/libcrypto/x509/x509name.expected
+++ /dev/null
@@ -1,3 +0,0 @@
10:1: ST=BaWue, O=KIT
20:1:2: ST=BaWue, L=Karlsruhe, O=KIT
30:0:1:2: C=DE + ST=BaWue, L=Karlsruhe, O=KIT