summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjsing <>2020-07-14 18:33:00 +0000
committerjsing <>2020-07-14 18:33:00 +0000
commitc8b770aa292e8970abfef18c490e9f6c4bec5db0 (patch)
treefcc2755b2d8f7611945ecff79b9a342062170277 /src
parent5833b446d446315876f10a00d069f4981c6cf97c (diff)
downloadopenbsd-c8b770aa292e8970abfef18c490e9f6c4bec5db0.tar.gz
openbsd-c8b770aa292e8970abfef18c490e9f6c4bec5db0.tar.bz2
openbsd-c8b770aa292e8970abfef18c490e9f6c4bec5db0.zip
Add regress for X509_verify() using the new bundles.
A number of these tests are known to fail due to bugs/incorrect verification implementation.
Diffstat (limited to 'src')
-rw-r--r--src/regress/lib/libcrypto/x509/Makefile9
-rw-r--r--src/regress/lib/libcrypto/x509/verify.c363
2 files changed, 369 insertions, 3 deletions
diff --git a/src/regress/lib/libcrypto/x509/Makefile b/src/regress/lib/libcrypto/x509/Makefile
index 19edf9398b..885a3211ec 100644
--- a/src/regress/lib/libcrypto/x509/Makefile
+++ b/src/regress/lib/libcrypto/x509/Makefile
@@ -1,14 +1,17 @@
1# $OpenBSD: Makefile,v 1.2 2020/06/04 21:21:03 schwarze Exp $ 1# $OpenBSD: Makefile,v 1.3 2020/07/14 18:33:00 jsing Exp $
2 2
3PROGS = x509attribute x509name 3PROGS = verify x509attribute x509name
4LDADD= -lcrypto 4LDADD= -lcrypto
5DPADD= ${LIBCRYPTO} 5DPADD= ${LIBCRYPTO}
6WARNINGS= Yes 6WARNINGS= Yes
7CFLAGS+= -Wall -Werror 7CFLAGS+= -Wall -Werror
8 8
9REGRESS_TARGETS=regress-x509attribute regress-x509name 9REGRESS_TARGETS=regress-verify regress-x509attribute regress-x509name
10CLEANFILES+= x509name.result 10CLEANFILES+= x509name.result
11 11
12regress-verify: verify
13 ./verify ${.CURDIR}/../certs
14
12regress-x509attribute: x509attribute 15regress-x509attribute: x509attribute
13 ./x509attribute 16 ./x509attribute
14 17
diff --git a/src/regress/lib/libcrypto/x509/verify.c b/src/regress/lib/libcrypto/x509/verify.c
new file mode 100644
index 0000000000..08ca0b24ff
--- /dev/null
+++ b/src/regress/lib/libcrypto/x509/verify.c
@@ -0,0 +1,363 @@
1/* $OpenBSD: verify.c,v 1.1 2020/07/14 18:33:00 jsing Exp $ */
2/*
3 * Copyright (c) 2020 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 <err.h>
19#include <string.h>
20
21#include <openssl/bio.h>
22#include <openssl/err.h>
23#include <openssl/pem.h>
24#include <openssl/x509.h>
25#include <openssl/x509v3.h>
26
27static int verbose = 1;
28
29static int
30passwd_cb(char *buf, int size, int rwflag, void *u)
31{
32 memset(buf, 0, size);
33 return (0);
34}
35
36static int
37certs_from_file(const char *filename, STACK_OF(X509) **certs)
38{
39 STACK_OF(X509_INFO) *xis = NULL;
40 STACK_OF(X509) *xs = NULL;
41 BIO *bio = NULL;
42 X509 *x;
43 int i;
44
45 if ((xs = sk_X509_new_null()) == NULL)
46 errx(1, "failed to create X509 stack");
47 if ((bio = BIO_new_file(filename, "r")) == NULL) {
48 ERR_print_errors_fp(stderr);
49 errx(1, "failed to create bio");
50 }
51 if ((xis = PEM_X509_INFO_read_bio(bio, NULL, passwd_cb, NULL)) == NULL)
52 errx(1, "failed to read PEM");
53
54 for (i = 0; i < sk_X509_INFO_num(xis); i++) {
55 if ((x = sk_X509_INFO_value(xis, i)->x509) == NULL)
56 continue;
57 if (!sk_X509_push(xs, x))
58 errx(1, "failed to push X509");
59 X509_up_ref(x);
60 }
61
62 *certs = xs;
63 xs = NULL;
64
65 sk_X509_INFO_pop_free(xis, X509_INFO_free);
66 sk_X509_pop_free(xs, X509_free);
67 BIO_free(bio);
68
69 return 1;
70}
71
72static int
73verify_cert_cb(int ok, X509_STORE_CTX *xsc)
74{
75 X509 *current_cert;
76 int verify_err;
77
78 current_cert = X509_STORE_CTX_get_current_cert(xsc);
79 if (current_cert != NULL) {
80 X509_NAME_print_ex_fp(stderr,
81 X509_get_subject_name(current_cert), 0,
82 XN_FLAG_ONELINE);
83 fprintf(stderr, "\n");
84 }
85
86 verify_err = X509_STORE_CTX_get_error(xsc);
87 if (verify_err != X509_V_OK) {
88 fprintf(stderr, "verify error at depth %d: %s\n",
89 X509_STORE_CTX_get_error_depth(xsc),
90 X509_verify_cert_error_string(verify_err));
91 }
92
93 return ok;
94}
95
96static void
97verify_cert(const char *roots_file, const char *bundle_file, int *chains)
98{
99 STACK_OF(X509) *roots = NULL, *bundle = NULL;
100 X509_STORE_CTX *xsc = NULL;
101 X509 *leaf = NULL;
102 int verify_err;
103
104 *chains = 0;
105
106 if (!certs_from_file(roots_file, &roots))
107 errx(1, "failed to load roots from '%s'", roots_file);
108 if (!certs_from_file(bundle_file, &bundle))
109 errx(1, "failed to load bundle from '%s'", bundle_file);
110 if (sk_X509_num(bundle) < 1)
111 errx(1, "not enough certs in bundle");
112 leaf = sk_X509_shift(bundle);
113
114 if ((xsc = X509_STORE_CTX_new()) == NULL)
115 errx(1, "X509_STORE_CTX");
116 if (!X509_STORE_CTX_init(xsc, NULL, leaf, bundle)) {
117 ERR_print_errors_fp(stderr);
118 errx(1, "failed to init store context");
119 }
120 if (verbose)
121 X509_STORE_CTX_set_verify_cb(xsc, verify_cert_cb);
122 X509_STORE_CTX_set0_trusted_stack(xsc, roots);
123 if (X509_verify_cert(xsc) == 1) {
124 *chains = 1; /* XXX */
125 goto done;
126 }
127
128 verify_err = X509_STORE_CTX_get_error(xsc);
129 fprintf(stderr, "failed to verify at %d: %s\n",
130 X509_STORE_CTX_get_error_depth(xsc),
131 X509_verify_cert_error_string(verify_err));
132
133 done:
134 sk_X509_pop_free(roots, X509_free);
135 sk_X509_pop_free(bundle, X509_free);
136 X509_STORE_CTX_free(xsc);
137 X509_free(leaf);
138}
139
140struct verify_cert_test {
141 const char *id;
142 int want_chains;
143 int failing;
144};
145
146struct verify_cert_test verify_cert_tests[] = {
147 {
148 .id = "1a",
149 .want_chains = 1,
150 },
151 {
152 .id = "2a",
153 .want_chains = 1,
154 },
155 {
156 .id = "2b",
157 .want_chains = 0,
158 },
159 {
160 .id = "3a",
161 .want_chains = 1,
162 },
163 {
164 .id = "3b",
165 .want_chains = 0,
166 },
167 {
168 .id = "3c",
169 .want_chains = 0,
170 },
171 {
172 .id = "3d",
173 .want_chains = 0,
174 },
175 {
176 .id = "3e",
177 .want_chains = 1,
178 },
179 {
180 .id = "4a",
181 .want_chains = 2,
182 },
183 {
184 .id = "4b",
185 .want_chains = 1,
186 },
187 {
188 .id = "4c",
189 .want_chains = 1,
190 .failing = 1,
191 },
192 {
193 .id = "4d",
194 .want_chains = 1,
195 },
196 {
197 .id = "4e",
198 .want_chains = 1,
199 },
200 {
201 .id = "4f",
202 .want_chains = 2,
203 },
204 {
205 .id = "4g",
206 .want_chains = 1,
207 .failing = 1,
208 },
209 {
210 .id = "4h",
211 .want_chains = 1,
212 },
213 {
214 .id = "5a",
215 .want_chains = 2,
216 },
217 {
218 .id = "5b",
219 .want_chains = 1,
220 .failing = 1,
221 },
222 {
223 .id = "5c",
224 .want_chains = 1,
225 },
226 {
227 .id = "5d",
228 .want_chains = 1,
229 },
230 {
231 .id = "5e",
232 .want_chains = 1,
233 .failing = 1,
234 },
235 {
236 .id = "5f",
237 .want_chains = 1,
238 },
239 {
240 .id = "5g",
241 .want_chains = 2,
242 },
243 {
244 .id = "5h",
245 .want_chains = 1,
246 },
247 {
248 .id = "5i",
249 .want_chains = 1,
250 .failing = 1,
251 },
252 {
253 .id = "6a",
254 .want_chains = 1,
255 },
256 {
257 .id = "6b",
258 .want_chains = 1,
259 .failing = 1,
260 },
261 {
262 .id = "7a",
263 .want_chains = 1,
264 .failing = 1,
265 },
266 {
267 .id = "7b",
268 .want_chains = 1,
269 },
270 {
271 .id = "8a",
272 .want_chains = 0,
273 },
274 {
275 .id = "9a",
276 .want_chains = 0,
277 },
278 {
279 .id = "10a",
280 .want_chains = 1,
281 },
282 {
283 .id = "10b",
284 .want_chains = 1,
285 },
286 {
287 .id = "11a",
288 .want_chains = 1,
289 .failing = 1,
290 },
291 {
292 .id = "11b",
293 .want_chains = 1,
294 },
295 {
296 .id = "12a",
297 .want_chains = 1,
298 },
299 {
300 .id = "13a",
301 .want_chains = 1,
302 },
303};
304
305#define N_VERIFY_CERT_TESTS \
306 (sizeof(verify_cert_tests) / sizeof(*verify_cert_tests))
307
308static int
309verify_cert_test(const char *certs_path)
310{
311 char *roots_file, *bundle_file;
312 struct verify_cert_test *vct;
313 int failed = 0;
314 int chains;
315 size_t i;
316
317 for (i = 0; i < N_VERIFY_CERT_TESTS; i++) {
318 vct = &verify_cert_tests[i];
319
320 if (asprintf(&roots_file, "%s/%s/roots.pem", certs_path,
321 vct->id) == -1)
322 errx(1, "asprintf");
323 if (asprintf(&bundle_file, "%s/%s/bundle.pem", certs_path,
324 vct->id) == -1)
325 errx(1, "asprintf");
326
327 fprintf(stderr, "== Test %zu (%s)\n", i, vct->id);
328 verify_cert(roots_file, bundle_file, &chains);
329 if ((chains == 0 && vct->want_chains == 0) ||
330 (chains == 1 && vct->want_chains > 0)) {
331 fprintf(stderr, "INFO: Succeeded with %d chains%s\n",
332 chains, vct->failing ? " (known failure)" : "");
333 if (vct->failing)
334 failed |= 1;
335 } else {
336 fprintf(stderr, "FAIL: Failed with %d chains%s\n",
337 chains, vct->failing ? " (known failure)" : "");
338 if (!vct->failing)
339 failed |= 1;
340 }
341 fprintf(stderr, "\n");
342
343 free(roots_file);
344 free(bundle_file);
345 }
346
347 return failed;
348}
349
350int
351main(int argc, char **argv)
352{
353 int failed = 0;
354
355 if (argc != 2) {
356 fprintf(stderr, "usage: %s <certs_path>\n", argv[0]);
357 exit(1);
358 }
359
360 failed |= verify_cert_test(argv[1]);
361
362 return (failed);
363}