Add a pass using the modern vfy with by_dir roots, code by me, script to
authorbeck <beck@openbsd.org>
Sat, 28 Aug 2021 15:13:50 +0000 (15:13 +0000)
committerbeck <beck@openbsd.org>
Sat, 28 Aug 2021 15:13:50 +0000 (15:13 +0000)
generate certdirs by jsing, and make chicken sacrifies by tb.

ok tb@ jsing@

regress/lib/libcrypto/x509/Makefile
regress/lib/libcrypto/x509/make-dir-roots.pl [new file with mode: 0644]
regress/lib/libcrypto/x509/verify.c

index 37da3fb..6b4256b 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: Makefile,v 1.4 2020/09/11 18:34:29 beck Exp $
+#      $OpenBSD: Makefile,v 1.5 2021/08/28 15:13:50 beck Exp $
 
 PROGS =        constraints verify x509attribute x509name
 LDADD= -Wl,-Bstatic -lcrypto -Wl,-Bdynamic
@@ -11,7 +11,13 @@ SUBDIR += bettertls
 REGRESS_TARGETS=regress-constraints regress-verify regress-x509attribute regress-x509name
 CLEANFILES+=   x509name.result
 
+.if make(clean) || make(cleandir)
+.BEGIN:
+        rm -rf ${.OBJDIR}/[0-9]*
+.endif
+
 regress-verify: verify
+       perl ${.CURDIR}/make-dir-roots.pl ${.CURDIR}/../certs .
        ./verify ${.CURDIR}/../certs
 
 regress-constraints: constraints
diff --git a/regress/lib/libcrypto/x509/make-dir-roots.pl b/regress/lib/libcrypto/x509/make-dir-roots.pl
new file mode 100644 (file)
index 0000000..54d05e0
--- /dev/null
@@ -0,0 +1,69 @@
+#!/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;
index 259854e..74ba603 100644 (file)
@@ -1,7 +1,7 @@
-/* $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;
 
@@ -100,18 +101,20 @@ verify_cert_cb(int ok, X509_STORE_CTX *xsc)
 }
 
 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);
@@ -121,10 +124,16 @@ verify_cert(const char *roots_file, const char *bundle_file, int *chains,
 
        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;
@@ -137,7 +146,8 @@ verify_cert(const char *roots_file, const char *bundle_file, int *chains,
 
        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;
@@ -154,6 +164,7 @@ verify_cert(const char *roots_file, const char *bundle_file, int *chains,
  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);
 }
@@ -394,7 +405,7 @@ struct verify_cert_test verify_cert_tests[] = {
 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;
@@ -409,13 +420,15 @@ verify_cert_test(const char *certs_path, int mode)
                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",
@@ -432,6 +445,7 @@ verify_cert_test(const char *certs_path, int mode)
 
                free(roots_file);
                free(bundle_file);
+               free(roots_dir);
        }
 
        return failed;
@@ -451,6 +465,8 @@ main(int argc, char **argv)
        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);