From 4ba9a4265bd445428bf5bc94b6adf469de90297e Mon Sep 17 00:00:00 2001
From: "Dr. Stephen Henson" <steve@openssl.org>
Date: Sun, 22 Mar 2015 17:34:56 +0000
Subject: [PATCH] Make OCSP response verification more flexible.

If a set of certificates is supplied to OCSP_basic_verify use those in
addition to any present in the OCSP response as untrusted CAs when
verifying a certificate chain.

PR#3668

Reviewed-by: Matt Caswell <matt@openssl.org>
(cherry picked from commit 4ca5efc2874e094d6382b30416824eda6dde52fe)
---
 crypto/ocsp/ocsp_vfy.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/crypto/ocsp/ocsp_vfy.c b/crypto/ocsp/ocsp_vfy.c
index 6c0ccb565d..d4a257c33b 100644
--- a/crypto/ocsp/ocsp_vfy.c
+++ b/crypto/ocsp/ocsp_vfy.c
@@ -83,6 +83,7 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
 {
     X509 *signer, *x;
     STACK_OF(X509) *chain = NULL;
+    STACK_OF(X509) *untrusted = NULL;
     X509_STORE_CTX ctx;
     int i, ret = 0;
     ret = ocsp_find_signer(&signer, bs, certs, st, flags);
@@ -107,10 +108,20 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
     }
     if (!(flags & OCSP_NOVERIFY)) {
         int init_res;
-        if (flags & OCSP_NOCHAIN)
-            init_res = X509_STORE_CTX_init(&ctx, st, signer, NULL);
-        else
-            init_res = X509_STORE_CTX_init(&ctx, st, signer, bs->certs);
+        if (flags & OCSP_NOCHAIN) {
+            untrusted = NULL;
+        } else if (bs->certs && certs) {
+            untrusted = sk_X509_dup(bs->certs);
+            for (i = 0; i < sk_X509_num(certs); i++) {
+                if (!sk_X509_push(untrusted, sk_X509_value(certs, i))) {
+                    OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_MALLOC_FAILURE);
+                    goto end;
+                }
+            }
+        } else {
+            untrusted = bs->certs;
+        }
+        init_res = X509_STORE_CTX_init(&ctx, st, signer, untrusted);
         if (!init_res) {
             ret = -1;
             OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_X509_LIB);
@@ -161,6 +172,8 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
  end:
     if (chain)
         sk_X509_pop_free(chain, X509_free);
+    if (bs->certs && certs)
+        sk_X509_free(untrusted);
     return ret;
 }
 
-- 
2.40.0