Add |X509_STORE_set0_additional_untrusted|.

X509_STORE_set0_additional_untrusted allows one to set a stack of
additional untrusted certificates that can be used during chain
building. These will be merged with the untrusted certificates set on
the |X509_STORE_CTX|.

Change-Id: I3f011fb0854e16a883a798356af0a24cbc5a9d68
Reviewed-on: https://boringssl-review.googlesource.com/12980
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc
index 0c25754..f6a8b64 100644
--- a/crypto/x509/x509_test.cc
+++ b/crypto/x509/x509_test.cc
@@ -450,7 +450,8 @@
 static int Verify(X509 *leaf, const std::vector<X509 *> &roots,
                    const std::vector<X509 *> &intermediates,
                    const std::vector<X509_CRL *> &crls,
-                   unsigned long flags = 0) {
+                   unsigned long flags,
+                   bool use_additional_untrusted) {
   bssl::UniquePtr<STACK_OF(X509)> roots_stack(CertsToStack(roots));
   bssl::UniquePtr<STACK_OF(X509)> intermediates_stack(
       CertsToStack(intermediates));
@@ -469,8 +470,14 @@
     return X509_V_ERR_UNSPECIFIED;
   }
 
-  if (!X509_STORE_CTX_init(ctx.get(), store.get(), leaf,
-                           intermediates_stack.get())) {
+  if (use_additional_untrusted) {
+    X509_STORE_set0_additional_untrusted(store.get(),
+                                         intermediates_stack.get());
+  }
+
+  if (!X509_STORE_CTX_init(
+          ctx.get(), store.get(), leaf,
+          use_additional_untrusted ? nullptr : intermediates_stack.get())) {
     return X509_V_ERR_UNSPECIFIED;
   }
 
@@ -496,6 +503,24 @@
   return X509_V_OK;
 }
 
+static int Verify(X509 *leaf, const std::vector<X509 *> &roots,
+                   const std::vector<X509 *> &intermediates,
+                   const std::vector<X509_CRL *> &crls,
+                   unsigned long flags = 0) {
+  const int r1 = Verify(leaf, roots, intermediates, crls, flags, false);
+  const int r2 = Verify(leaf, roots, intermediates, crls, flags, true);
+
+  if (r1 != r2) {
+    fprintf(stderr,
+            "Verify with, and without, use_additional_untrusted gave different "
+            "results: %d vs %d.\n",
+            r1, r2);
+    return false;
+  }
+
+  return r1;
+}
+
 static bool TestVerify() {
   bssl::UniquePtr<X509> cross_signing_root(CertFromPEM(kCrossSigningRootPEM));
   bssl::UniquePtr<X509> root(CertFromPEM(kRootCAPEM));