diff options
-rw-r--r-- | src/regress/lib/libcrypto/x509/Makefile | 8 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/x509/make-dir-roots.pl | 69 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/x509/verify.c | 44 |
3 files changed, 106 insertions, 15 deletions
diff --git a/src/regress/lib/libcrypto/x509/Makefile b/src/regress/lib/libcrypto/x509/Makefile index 37da3fb933..6b4256bfad 100644 --- a/src/regress/lib/libcrypto/x509/Makefile +++ b/src/regress/lib/libcrypto/x509/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | # $OpenBSD: Makefile,v 1.4 2020/09/11 18:34:29 beck Exp $ | 1 | # $OpenBSD: Makefile,v 1.5 2021/08/28 15:13:50 beck Exp $ |
2 | 2 | ||
3 | PROGS = constraints verify x509attribute x509name | 3 | PROGS = constraints verify x509attribute x509name |
4 | LDADD= -Wl,-Bstatic -lcrypto -Wl,-Bdynamic | 4 | LDADD= -Wl,-Bstatic -lcrypto -Wl,-Bdynamic |
@@ -11,7 +11,13 @@ SUBDIR += bettertls | |||
11 | REGRESS_TARGETS=regress-constraints regress-verify regress-x509attribute regress-x509name | 11 | REGRESS_TARGETS=regress-constraints regress-verify regress-x509attribute regress-x509name |
12 | CLEANFILES+= x509name.result | 12 | CLEANFILES+= x509name.result |
13 | 13 | ||
14 | .if make(clean) || make(cleandir) | ||
15 | .BEGIN: | ||
16 | rm -rf ${.OBJDIR}/[0-9]* | ||
17 | .endif | ||
18 | |||
14 | regress-verify: verify | 19 | regress-verify: verify |
20 | perl ${.CURDIR}/make-dir-roots.pl ${.CURDIR}/../certs . | ||
15 | ./verify ${.CURDIR}/../certs | 21 | ./verify ${.CURDIR}/../certs |
16 | 22 | ||
17 | regress-constraints: constraints | 23 | regress-constraints: constraints |
diff --git a/src/regress/lib/libcrypto/x509/make-dir-roots.pl b/src/regress/lib/libcrypto/x509/make-dir-roots.pl new file mode 100644 index 0000000000..54d05e0519 --- /dev/null +++ b/src/regress/lib/libcrypto/x509/make-dir-roots.pl | |||
@@ -0,0 +1,69 @@ | |||
1 | #!/usr/bin/perl | ||
2 | |||
3 | # | ||
4 | # Copyright (c) 2021 Joel Sing <jsing@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 | sub root_pem_to_dir() { | ||
20 | $certs = 0; | ||
21 | $in_cert = 0; | ||
22 | |||
23 | ($roots_file, $certs_dir) = @_; | ||
24 | |||
25 | open ROOTS, "<$roots_file" or | ||
26 | die "failed to open roots file '$roots_file'"; | ||
27 | while (<ROOTS>) { | ||
28 | if ($_ eq "-----BEGIN CERTIFICATE-----\n") { | ||
29 | $in_cert = 1; | ||
30 | $cert_path = "$certs_dir/ca-$certs.pem"; | ||
31 | open CERT, ">$cert_path" or | ||
32 | die "failed to open '$cert_path'"; | ||
33 | $certs++; | ||
34 | } | ||
35 | if ($in_cert) { | ||
36 | print CERT $_; | ||
37 | } | ||
38 | if ($_ eq "-----END CERTIFICATE-----\n") { | ||
39 | $in_cert = 0; | ||
40 | } | ||
41 | } | ||
42 | close ROOTS; | ||
43 | |||
44 | my @args = ("openssl", "certhash", $certs_dir); | ||
45 | system(@args) == 0 or die "certhash failed"; | ||
46 | } | ||
47 | |||
48 | if (scalar @ARGV != 2) { | ||
49 | print("$0 <certs-path> <output-dir>\n"); | ||
50 | exit(1); | ||
51 | } | ||
52 | $certs_path = shift @ARGV; | ||
53 | $output_dir = shift @ARGV; | ||
54 | |||
55 | opendir CERTS, $certs_path or | ||
56 | die "failed to open certs directory '$certs_path'"; | ||
57 | while (readdir CERTS) { | ||
58 | next if ($_ !~ '^[0-9]+[a-z]?$'); | ||
59 | |||
60 | $roots_file = join("/", $certs_path, $_, "roots.pem"); | ||
61 | $roots_dir = join("/", $output_dir, $_, "roots"); | ||
62 | |||
63 | mkdir "$output_dir"; | ||
64 | mkdir "$output_dir/$_"; | ||
65 | mkdir "$output_dir/$_/roots"; | ||
66 | |||
67 | &root_pem_to_dir($roots_file, $roots_dir); | ||
68 | } | ||
69 | closedir CERTS; | ||
diff --git a/src/regress/lib/libcrypto/x509/verify.c b/src/regress/lib/libcrypto/x509/verify.c index 259854ef12..74ba603a22 100644 --- a/src/regress/lib/libcrypto/x509/verify.c +++ b/src/regress/lib/libcrypto/x509/verify.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* $OpenBSD: verify.c,v 1.6 2021/08/27 16:15:42 beck Exp $ */ | 1 | /* $OpenBSD: verify.c,v 1.7 2021/08/28 15:13:50 beck Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2020 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2020 Joel Sing <jsing@openbsd.org> |
4 | * Copyright (c) 2020 Bob Beck <beck@openbsd.org> | 4 | * Copyright (c) 2020-2021 Bob Beck <beck@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 |
@@ -26,9 +26,10 @@ | |||
26 | #include <openssl/x509v3.h> | 26 | #include <openssl/x509v3.h> |
27 | #include <openssl/x509_verify.h> | 27 | #include <openssl/x509_verify.h> |
28 | 28 | ||
29 | #define MODE_MODERN_VFY 0 | 29 | #define MODE_MODERN_VFY 0 |
30 | #define MODE_LEGACY_VFY 1 | 30 | #define MODE_MODERN_VFY_DIR 1 |
31 | #define MODE_VERIFY 2 | 31 | #define MODE_LEGACY_VFY 2 |
32 | #define MODE_VERIFY 3 | ||
32 | 33 | ||
33 | static int verbose = 1; | 34 | static int verbose = 1; |
34 | 35 | ||
@@ -100,18 +101,20 @@ verify_cert_cb(int ok, X509_STORE_CTX *xsc) | |||
100 | } | 101 | } |
101 | 102 | ||
102 | static void | 103 | static void |
103 | verify_cert(const char *roots_file, const char *bundle_file, int *chains, | 104 | verify_cert(const char *roots_dir, const char *roots_file, |
104 | int mode) | 105 | const char *bundle_file, int *chains, int mode) |
105 | { | 106 | { |
106 | STACK_OF(X509) *roots = NULL, *bundle = NULL; | 107 | STACK_OF(X509) *roots = NULL, *bundle = NULL; |
107 | X509_STORE_CTX *xsc = NULL; | 108 | X509_STORE_CTX *xsc = NULL; |
109 | X509_STORE *store = NULL; | ||
110 | int verify_err, use_dir; | ||
108 | unsigned long flags; | 111 | unsigned long flags; |
109 | X509 *leaf = NULL; | 112 | X509 *leaf = NULL; |
110 | int verify_err; | ||
111 | 113 | ||
112 | *chains = 0; | 114 | *chains = 0; |
115 | use_dir = (mode == MODE_MODERN_VFY_DIR); | ||
113 | 116 | ||
114 | if (!certs_from_file(roots_file, &roots)) | 117 | if (!use_dir && !certs_from_file(roots_file, &roots)) |
115 | errx(1, "failed to load roots from '%s'", roots_file); | 118 | errx(1, "failed to load roots from '%s'", roots_file); |
116 | if (!certs_from_file(bundle_file, &bundle)) | 119 | if (!certs_from_file(bundle_file, &bundle)) |
117 | errx(1, "failed to load bundle from '%s'", bundle_file); | 120 | errx(1, "failed to load bundle from '%s'", bundle_file); |
@@ -121,10 +124,16 @@ verify_cert(const char *roots_file, const char *bundle_file, int *chains, | |||
121 | 124 | ||
122 | if ((xsc = X509_STORE_CTX_new()) == NULL) | 125 | if ((xsc = X509_STORE_CTX_new()) == NULL) |
123 | errx(1, "X509_STORE_CTX"); | 126 | errx(1, "X509_STORE_CTX"); |
124 | if (!X509_STORE_CTX_init(xsc, NULL, leaf, bundle)) { | 127 | if (use_dir && (store = X509_STORE_new()) == NULL) |
128 | errx(1, "X509_STORE"); | ||
129 | if (!X509_STORE_CTX_init(xsc, store, leaf, bundle)) { | ||
125 | ERR_print_errors_fp(stderr); | 130 | ERR_print_errors_fp(stderr); |
126 | errx(1, "failed to init store context"); | 131 | errx(1, "failed to init store context"); |
127 | } | 132 | } |
133 | if (use_dir) { | ||
134 | if (!X509_STORE_load_locations(store, NULL, roots_dir)) | ||
135 | errx(1, "failed to set by_dir directory of %s", roots_dir); | ||
136 | } | ||
128 | if (mode == MODE_LEGACY_VFY) { | 137 | if (mode == MODE_LEGACY_VFY) { |
129 | flags = X509_VERIFY_PARAM_get_flags(xsc->param); | 138 | flags = X509_VERIFY_PARAM_get_flags(xsc->param); |
130 | flags |= X509_V_FLAG_LEGACY_VERIFY; | 139 | flags |= X509_V_FLAG_LEGACY_VERIFY; |
@@ -137,7 +146,8 @@ verify_cert(const char *roots_file, const char *bundle_file, int *chains, | |||
137 | 146 | ||
138 | if (verbose) | 147 | if (verbose) |
139 | X509_STORE_CTX_set_verify_cb(xsc, verify_cert_cb); | 148 | X509_STORE_CTX_set_verify_cb(xsc, verify_cert_cb); |
140 | X509_STORE_CTX_set0_trusted_stack(xsc, roots); | 149 | if (!use_dir) |
150 | X509_STORE_CTX_set0_trusted_stack(xsc, roots); | ||
141 | if (X509_verify_cert(xsc) == 1) { | 151 | if (X509_verify_cert(xsc) == 1) { |
142 | *chains = 1; /* XXX */ | 152 | *chains = 1; /* XXX */ |
143 | goto done; | 153 | goto done; |
@@ -154,6 +164,7 @@ verify_cert(const char *roots_file, const char *bundle_file, int *chains, | |||
154 | done: | 164 | done: |
155 | sk_X509_pop_free(roots, X509_free); | 165 | sk_X509_pop_free(roots, X509_free); |
156 | sk_X509_pop_free(bundle, X509_free); | 166 | sk_X509_pop_free(bundle, X509_free); |
167 | X509_STORE_free(store); | ||
157 | X509_STORE_CTX_free(xsc); | 168 | X509_STORE_CTX_free(xsc); |
158 | X509_free(leaf); | 169 | X509_free(leaf); |
159 | } | 170 | } |
@@ -394,7 +405,7 @@ struct verify_cert_test verify_cert_tests[] = { | |||
394 | static int | 405 | static int |
395 | verify_cert_test(const char *certs_path, int mode) | 406 | verify_cert_test(const char *certs_path, int mode) |
396 | { | 407 | { |
397 | char *roots_file, *bundle_file; | 408 | char *roots_file, *bundle_file, *roots_dir; |
398 | struct verify_cert_test *vct; | 409 | struct verify_cert_test *vct; |
399 | int failed = 0; | 410 | int failed = 0; |
400 | int chains; | 411 | int chains; |
@@ -409,13 +420,15 @@ verify_cert_test(const char *certs_path, int mode) | |||
409 | if (asprintf(&bundle_file, "%s/%s/bundle.pem", certs_path, | 420 | if (asprintf(&bundle_file, "%s/%s/bundle.pem", certs_path, |
410 | vct->id) == -1) | 421 | vct->id) == -1) |
411 | errx(1, "asprintf"); | 422 | errx(1, "asprintf"); |
423 | if (asprintf(&roots_dir, "./%s/roots", vct->id) == -1) | ||
424 | errx(1, "asprintf"); | ||
412 | 425 | ||
413 | fprintf(stderr, "== Test %zu (%s)\n", i, vct->id); | 426 | fprintf(stderr, "== Test %zu (%s)\n", i, vct->id); |
414 | if (mode == MODE_VERIFY) | 427 | if (mode == MODE_VERIFY) |
415 | verify_cert_new(roots_file, bundle_file, &chains); | 428 | verify_cert_new(roots_file, bundle_file, &chains); |
416 | else | 429 | else |
417 | verify_cert(roots_file, bundle_file, &chains, mode); | 430 | verify_cert(roots_dir, roots_file, bundle_file, &chains, mode); |
418 | if ((mode == 2 && chains == vct->want_chains) || | 431 | if ((mode == MODE_VERIFY && chains == vct->want_chains) || |
419 | (chains == 0 && vct->want_chains == 0) || | 432 | (chains == 0 && vct->want_chains == 0) || |
420 | (chains == 1 && vct->want_chains > 0)) { | 433 | (chains == 1 && vct->want_chains > 0)) { |
421 | fprintf(stderr, "INFO: Succeeded with %d chains%s\n", | 434 | fprintf(stderr, "INFO: Succeeded with %d chains%s\n", |
@@ -432,6 +445,7 @@ verify_cert_test(const char *certs_path, int mode) | |||
432 | 445 | ||
433 | free(roots_file); | 446 | free(roots_file); |
434 | free(bundle_file); | 447 | free(bundle_file); |
448 | free(roots_dir); | ||
435 | } | 449 | } |
436 | 450 | ||
437 | return failed; | 451 | return failed; |
@@ -451,6 +465,8 @@ main(int argc, char **argv) | |||
451 | failed |= verify_cert_test(argv[1], MODE_LEGACY_VFY); | 465 | failed |= verify_cert_test(argv[1], MODE_LEGACY_VFY); |
452 | fprintf(stderr, "\n\nTesting modern x509_vfy\n"); | 466 | fprintf(stderr, "\n\nTesting modern x509_vfy\n"); |
453 | failed |= verify_cert_test(argv[1], MODE_MODERN_VFY); | 467 | failed |= verify_cert_test(argv[1], MODE_MODERN_VFY); |
468 | fprintf(stderr, "\n\nTesting modern x509_vfy by_dir\n"); | ||
469 | failed |= verify_cert_test(argv[1], MODE_MODERN_VFY_DIR); | ||
454 | fprintf(stderr, "\n\nTesting x509_verify\n"); | 470 | fprintf(stderr, "\n\nTesting x509_verify\n"); |
455 | failed |= verify_cert_test(argv[1], MODE_VERIFY); | 471 | failed |= verify_cert_test(argv[1], MODE_VERIFY); |
456 | 472 | ||