--- /dev/null
+#!/usr/bin/perl
+
+#
+# Copyright (c) 2021 Joel Sing <jsing@openbsd.org>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+sub root_pem_to_dir() {
+ $certs = 0;
+ $in_cert = 0;
+
+ ($roots_file, $certs_dir) = @_;
+
+ open ROOTS, "<$roots_file" or
+ die "failed to open roots file '$roots_file'";
+ while (<ROOTS>) {
+ if ($_ eq "-----BEGIN CERTIFICATE-----\n") {
+ $in_cert = 1;
+ $cert_path = "$certs_dir/ca-$certs.pem";
+ open CERT, ">$cert_path" or
+ die "failed to open '$cert_path'";
+ $certs++;
+ }
+ if ($in_cert) {
+ print CERT $_;
+ }
+ if ($_ eq "-----END CERTIFICATE-----\n") {
+ $in_cert = 0;
+ }
+ }
+ close ROOTS;
+
+ my @args = ("openssl", "certhash", $certs_dir);
+ system(@args) == 0 or die "certhash failed";
+}
+
+if (scalar @ARGV != 2) {
+ print("$0 <certs-path> <output-dir>\n");
+ exit(1);
+}
+$certs_path = shift @ARGV;
+$output_dir = shift @ARGV;
+
+opendir CERTS, $certs_path or
+ die "failed to open certs directory '$certs_path'";
+while (readdir CERTS) {
+ next if ($_ !~ '^[0-9]+[a-z]?$');
+
+ $roots_file = join("/", $certs_path, $_, "roots.pem");
+ $roots_dir = join("/", $output_dir, $_, "roots");
+
+ mkdir "$output_dir";
+ mkdir "$output_dir/$_";
+ mkdir "$output_dir/$_/roots";
+
+ &root_pem_to_dir($roots_file, $roots_dir);
+}
+closedir CERTS;
-/* $OpenBSD: verify.c,v 1.6 2021/08/27 16:15:42 beck Exp $ */
+/* $OpenBSD: verify.c,v 1.7 2021/08/28 15:13:50 beck Exp $ */
/*
* Copyright (c) 2020 Joel Sing <jsing@openbsd.org>
- * Copyright (c) 2020 Bob Beck <beck@openbsd.org>
+ * Copyright (c) 2020-2021 Bob Beck <beck@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
#include <openssl/x509v3.h>
#include <openssl/x509_verify.h>
-#define MODE_MODERN_VFY 0
-#define MODE_LEGACY_VFY 1
-#define MODE_VERIFY 2
+#define MODE_MODERN_VFY 0
+#define MODE_MODERN_VFY_DIR 1
+#define MODE_LEGACY_VFY 2
+#define MODE_VERIFY 3
static int verbose = 1;
}
static void
-verify_cert(const char *roots_file, const char *bundle_file, int *chains,
- int mode)
+verify_cert(const char *roots_dir, const char *roots_file,
+ const char *bundle_file, int *chains, int mode)
{
STACK_OF(X509) *roots = NULL, *bundle = NULL;
X509_STORE_CTX *xsc = NULL;
+ X509_STORE *store = NULL;
+ int verify_err, use_dir;
unsigned long flags;
X509 *leaf = NULL;
- int verify_err;
*chains = 0;
+ use_dir = (mode == MODE_MODERN_VFY_DIR);
- if (!certs_from_file(roots_file, &roots))
+ if (!use_dir && !certs_from_file(roots_file, &roots))
errx(1, "failed to load roots from '%s'", roots_file);
if (!certs_from_file(bundle_file, &bundle))
errx(1, "failed to load bundle from '%s'", bundle_file);
if ((xsc = X509_STORE_CTX_new()) == NULL)
errx(1, "X509_STORE_CTX");
- if (!X509_STORE_CTX_init(xsc, NULL, leaf, bundle)) {
+ if (use_dir && (store = X509_STORE_new()) == NULL)
+ errx(1, "X509_STORE");
+ if (!X509_STORE_CTX_init(xsc, store, leaf, bundle)) {
ERR_print_errors_fp(stderr);
errx(1, "failed to init store context");
}
+ if (use_dir) {
+ if (!X509_STORE_load_locations(store, NULL, roots_dir))
+ errx(1, "failed to set by_dir directory of %s", roots_dir);
+ }
if (mode == MODE_LEGACY_VFY) {
flags = X509_VERIFY_PARAM_get_flags(xsc->param);
flags |= X509_V_FLAG_LEGACY_VERIFY;
if (verbose)
X509_STORE_CTX_set_verify_cb(xsc, verify_cert_cb);
- X509_STORE_CTX_set0_trusted_stack(xsc, roots);
+ if (!use_dir)
+ X509_STORE_CTX_set0_trusted_stack(xsc, roots);
if (X509_verify_cert(xsc) == 1) {
*chains = 1; /* XXX */
goto done;
done:
sk_X509_pop_free(roots, X509_free);
sk_X509_pop_free(bundle, X509_free);
+ X509_STORE_free(store);
X509_STORE_CTX_free(xsc);
X509_free(leaf);
}
static int
verify_cert_test(const char *certs_path, int mode)
{
- char *roots_file, *bundle_file;
+ char *roots_file, *bundle_file, *roots_dir;
struct verify_cert_test *vct;
int failed = 0;
int chains;
if (asprintf(&bundle_file, "%s/%s/bundle.pem", certs_path,
vct->id) == -1)
errx(1, "asprintf");
+ if (asprintf(&roots_dir, "./%s/roots", vct->id) == -1)
+ errx(1, "asprintf");
fprintf(stderr, "== Test %zu (%s)\n", i, vct->id);
if (mode == MODE_VERIFY)
verify_cert_new(roots_file, bundle_file, &chains);
else
- verify_cert(roots_file, bundle_file, &chains, mode);
- if ((mode == 2 && chains == vct->want_chains) ||
+ verify_cert(roots_dir, roots_file, bundle_file, &chains, mode);
+ if ((mode == MODE_VERIFY && chains == vct->want_chains) ||
(chains == 0 && vct->want_chains == 0) ||
(chains == 1 && vct->want_chains > 0)) {
fprintf(stderr, "INFO: Succeeded with %d chains%s\n",
free(roots_file);
free(bundle_file);
+ free(roots_dir);
}
return failed;
failed |= verify_cert_test(argv[1], MODE_LEGACY_VFY);
fprintf(stderr, "\n\nTesting modern x509_vfy\n");
failed |= verify_cert_test(argv[1], MODE_MODERN_VFY);
+ fprintf(stderr, "\n\nTesting modern x509_vfy by_dir\n");
+ failed |= verify_cert_test(argv[1], MODE_MODERN_VFY_DIR);
fprintf(stderr, "\n\nTesting x509_verify\n");
failed |= verify_cert_test(argv[1], MODE_VERIFY);