summaryrefslogtreecommitdiff
path: root/src/regress/lib/libcrypto/x509/verify.c
diff options
context:
space:
mode:
authorbeck <>2020-09-13 15:06:17 +0000
committerbeck <>2020-09-13 15:06:17 +0000
commita328631fddec2556ad8af08ce4de240790c537c9 (patch)
tree4e2deda0db62092481ad6901c374736e60f249a2 /src/regress/lib/libcrypto/x509/verify.c
parent4f04d3f588f91c98b4b1cdfcffe028a036c96283 (diff)
downloadopenbsd-a328631fddec2556ad8af08ce4de240790c537c9.tar.gz
openbsd-a328631fddec2556ad8af08ce4de240790c537c9.tar.bz2
openbsd-a328631fddec2556ad8af08ce4de240790c537c9.zip
Add new x509 certificate chain validator in x509_verify.c
The new validator finds multiple validated chains to handle the modern PKI cases which may frequently have multiple paths via different intermediates to different roots. It is loosely based on golang's x509 validator This includes integration so that the new validator can be used via X509_verify_cert() as well as a new api x509_verify() which will return multiple chains (similar to go). The new validator is not enabled by default with this commit, this will be changed in a follow on commit. The new public API is not yet exposed, and will be finalized and exposed with a man page and a library minor bump later. ok tb@ inoguchi@ jsing@
Diffstat (limited to 'src/regress/lib/libcrypto/x509/verify.c')
-rw-r--r--src/regress/lib/libcrypto/x509/verify.c99
1 files changed, 90 insertions, 9 deletions
diff --git a/src/regress/lib/libcrypto/x509/verify.c b/src/regress/lib/libcrypto/x509/verify.c
index 08ca0b24ff..1a11c2ffe5 100644
--- a/src/regress/lib/libcrypto/x509/verify.c
+++ b/src/regress/lib/libcrypto/x509/verify.c
@@ -1,6 +1,7 @@
1/* $OpenBSD: verify.c,v 1.1 2020/07/14 18:33:00 jsing Exp $ */ 1/* $OpenBSD: verify.c,v 1.2 2020/09/13 15:06:17 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 * 5 *
5 * Permission to use, copy, modify, and distribute this software for any 6 * 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 * purpose with or without fee is hereby granted, provided that the above
@@ -23,6 +24,11 @@
23#include <openssl/pem.h> 24#include <openssl/pem.h>
24#include <openssl/x509.h> 25#include <openssl/x509.h>
25#include <openssl/x509v3.h> 26#include <openssl/x509v3.h>
27#include <openssl/x509_verify.h>
28
29#define MODE_MODERN_VFY 0
30#define MODE_LEGACY_VFY 1
31#define MODE_VERIFY 2
26 32
27static int verbose = 1; 33static int verbose = 1;
28 34
@@ -94,10 +100,12 @@ verify_cert_cb(int ok, X509_STORE_CTX *xsc)
94} 100}
95 101
96static void 102static void
97verify_cert(const char *roots_file, const char *bundle_file, int *chains) 103verify_cert(const char *roots_file, const char *bundle_file, int *chains,
104 int mode)
98{ 105{
99 STACK_OF(X509) *roots = NULL, *bundle = NULL; 106 STACK_OF(X509) *roots = NULL, *bundle = NULL;
100 X509_STORE_CTX *xsc = NULL; 107 X509_STORE_CTX *xsc = NULL;
108 unsigned long flags;
101 X509 *leaf = NULL; 109 X509 *leaf = NULL;
102 int verify_err; 110 int verify_err;
103 111
@@ -117,6 +125,16 @@ verify_cert(const char *roots_file, const char *bundle_file, int *chains)
117 ERR_print_errors_fp(stderr); 125 ERR_print_errors_fp(stderr);
118 errx(1, "failed to init store context"); 126 errx(1, "failed to init store context");
119 } 127 }
128 if (mode == MODE_LEGACY_VFY) {
129 flags = X509_VERIFY_PARAM_get_flags(xsc->param);
130 flags |= X509_V_FLAG_LEGACY_VERIFY;
131 X509_VERIFY_PARAM_set_flags(xsc->param, flags);
132 } else {
133 flags = X509_VERIFY_PARAM_get_flags(xsc->param);
134 flags &= ~X509_V_FLAG_LEGACY_VERIFY;
135 X509_VERIFY_PARAM_set_flags(xsc->param, flags);
136 }
137
120 if (verbose) 138 if (verbose)
121 X509_STORE_CTX_set_verify_cb(xsc, verify_cert_cb); 139 X509_STORE_CTX_set_verify_cb(xsc, verify_cert_cb);
122 X509_STORE_CTX_set0_trusted_stack(xsc, roots); 140 X509_STORE_CTX_set0_trusted_stack(xsc, roots);
@@ -143,6 +161,60 @@ struct verify_cert_test {
143 int failing; 161 int failing;
144}; 162};
145 163
164static void
165verify_cert_new(const char *roots_file, const char *bundle_file, int *chains)
166{
167 STACK_OF(X509) *roots = NULL, *bundle = NULL;
168 X509_STORE_CTX *xsc = NULL;
169 X509 *leaf = NULL;
170 struct x509_verify_ctx *ctx;
171
172 *chains = 0;
173
174 if (!certs_from_file(roots_file, &roots))
175 errx(1, "failed to load roots from '%s'", roots_file);
176 if (!certs_from_file(bundle_file, &bundle))
177 errx(1, "failed to load bundle from '%s'", bundle_file);
178 if (sk_X509_num(bundle) < 1)
179 errx(1, "not enough certs in bundle");
180 leaf = sk_X509_shift(bundle);
181
182 if ((xsc = X509_STORE_CTX_new()) == NULL)
183 errx(1, "X509_STORE_CTX");
184 if (!X509_STORE_CTX_init(xsc, NULL, leaf, bundle)) {
185 ERR_print_errors_fp(stderr);
186 errx(1, "failed to init store context");
187 }
188 if (verbose)
189 X509_STORE_CTX_set_verify_cb(xsc, verify_cert_cb);
190
191 if ((ctx = x509_verify_ctx_new(roots)) == NULL)
192 errx(1, "failed to create ctx");
193 if (!x509_verify_ctx_set_intermediates(ctx, bundle))
194 errx(1, "failed to set intermediates");
195
196 if ((*chains = x509_verify(ctx, leaf, NULL)) == 0) {
197 fprintf(stderr, "failed to verify at %lu: %s\n",
198 x509_verify_ctx_error_depth(ctx),
199 x509_verify_ctx_error_string(ctx));
200 } else {
201 for (int c = 0; verbose && c < *chains; c++) {
202 fprintf(stderr, "Chain %d\n--------\n", c);
203 STACK_OF(X509) * chain = x509_verify_ctx_chain(ctx, c);
204 for (int i = 0; i < sk_X509_num(chain); i++) {
205 X509 *cert = sk_X509_value(chain, i);
206 X509_NAME_print_ex_fp(stderr,
207 X509_get_subject_name(cert), 0,
208 XN_FLAG_ONELINE);
209 fprintf(stderr, "\n");
210 }
211 }
212 }
213 sk_X509_pop_free(roots, X509_free);
214 sk_X509_pop_free(bundle, X509_free);
215 X509_free(leaf);
216}
217
146struct verify_cert_test verify_cert_tests[] = { 218struct verify_cert_test verify_cert_tests[] = {
147 { 219 {
148 .id = "1a", 220 .id = "1a",
@@ -306,7 +378,7 @@ struct verify_cert_test verify_cert_tests[] = {
306 (sizeof(verify_cert_tests) / sizeof(*verify_cert_tests)) 378 (sizeof(verify_cert_tests) / sizeof(*verify_cert_tests))
307 379
308static int 380static int
309verify_cert_test(const char *certs_path) 381verify_cert_test(const char *certs_path, int mode)
310{ 382{
311 char *roots_file, *bundle_file; 383 char *roots_file, *bundle_file;
312 struct verify_cert_test *vct; 384 struct verify_cert_test *vct;
@@ -325,16 +397,20 @@ verify_cert_test(const char *certs_path)
325 errx(1, "asprintf"); 397 errx(1, "asprintf");
326 398
327 fprintf(stderr, "== Test %zu (%s)\n", i, vct->id); 399 fprintf(stderr, "== Test %zu (%s)\n", i, vct->id);
328 verify_cert(roots_file, bundle_file, &chains); 400 if (mode == MODE_VERIFY)
329 if ((chains == 0 && vct->want_chains == 0) || 401 verify_cert_new(roots_file, bundle_file, &chains);
402 else
403 verify_cert(roots_file, bundle_file, &chains, mode);
404 if ((mode == 2 && chains == vct->want_chains) ||
405 (chains == 0 && vct->want_chains == 0) ||
330 (chains == 1 && vct->want_chains > 0)) { 406 (chains == 1 && vct->want_chains > 0)) {
331 fprintf(stderr, "INFO: Succeeded with %d chains%s\n", 407 fprintf(stderr, "INFO: Succeeded with %d chains%s\n",
332 chains, vct->failing ? " (known failure)" : ""); 408 chains, vct->failing ? " (legacy failure)" : "");
333 if (vct->failing) 409 if (mode == MODE_LEGACY_VFY && vct->failing)
334 failed |= 1; 410 failed |= 1;
335 } else { 411 } else {
336 fprintf(stderr, "FAIL: Failed with %d chains%s\n", 412 fprintf(stderr, "FAIL: Failed with %d chains%s\n",
337 chains, vct->failing ? " (known failure)" : ""); 413 chains, vct->failing ? " (legacy failure)" : "");
338 if (!vct->failing) 414 if (!vct->failing)
339 failed |= 1; 415 failed |= 1;
340 } 416 }
@@ -357,7 +433,12 @@ main(int argc, char **argv)
357 exit(1); 433 exit(1);
358 } 434 }
359 435
360 failed |= verify_cert_test(argv[1]); 436 fprintf(stderr, "\n\nTesting legacy x509_vfy\n");
437 failed |= verify_cert_test(argv[1], MODE_LEGACY_VFY);
438 fprintf(stderr, "\n\nTesting modern x509_vfy\n");
439 failed |= verify_cert_test(argv[1], MODE_MODERN_VFY);
440 fprintf(stderr, "\n\nTesting x509_verify\n");
441 failed |= verify_cert_test(argv[1], MODE_VERIFY);
361 442
362 return (failed); 443 return (failed);
363} 444}