xref: /openbsd-src/lib/libcrypto/ocsp/ocsp_vfy.c (revision 75e21034e2ed7cc3514816a96606fcbfe50e069f)
1*75e21034Sbeck /* $OpenBSD: ocsp_vfy.c,v 1.24 2024/07/12 18:15:10 beck Exp $ */
2e6841c1dSdjm /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3da347917Sbeck  * project 2000.
4da347917Sbeck  */
5da347917Sbeck /* ====================================================================
6720b416eSmarkus  * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
7da347917Sbeck  *
8da347917Sbeck  * Redistribution and use in source and binary forms, with or without
9da347917Sbeck  * modification, are permitted provided that the following conditions
10da347917Sbeck  * are met:
11da347917Sbeck  *
12da347917Sbeck  * 1. Redistributions of source code must retain the above copyright
13da347917Sbeck  *    notice, this list of conditions and the following disclaimer.
14da347917Sbeck  *
15da347917Sbeck  * 2. Redistributions in binary form must reproduce the above copyright
16da347917Sbeck  *    notice, this list of conditions and the following disclaimer in
17da347917Sbeck  *    the documentation and/or other materials provided with the
18da347917Sbeck  *    distribution.
19da347917Sbeck  *
20da347917Sbeck  * 3. All advertising materials mentioning features or use of this
21da347917Sbeck  *    software must display the following acknowledgment:
22da347917Sbeck  *    "This product includes software developed by the OpenSSL Project
23da347917Sbeck  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24da347917Sbeck  *
25da347917Sbeck  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26da347917Sbeck  *    endorse or promote products derived from this software without
27da347917Sbeck  *    prior written permission. For written permission, please contact
28da347917Sbeck  *    licensing@OpenSSL.org.
29da347917Sbeck  *
30da347917Sbeck  * 5. Products derived from this software may not be called "OpenSSL"
31da347917Sbeck  *    nor may "OpenSSL" appear in their names without prior written
32da347917Sbeck  *    permission of the OpenSSL Project.
33da347917Sbeck  *
34da347917Sbeck  * 6. Redistributions of any form whatsoever must retain the following
35da347917Sbeck  *    acknowledgment:
36da347917Sbeck  *    "This product includes software developed by the OpenSSL Project
37da347917Sbeck  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38da347917Sbeck  *
39da347917Sbeck  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40da347917Sbeck  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41da347917Sbeck  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42da347917Sbeck  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43da347917Sbeck  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44da347917Sbeck  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45da347917Sbeck  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46da347917Sbeck  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47da347917Sbeck  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48da347917Sbeck  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49da347917Sbeck  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50da347917Sbeck  * OF THE POSSIBILITY OF SUCH DAMAGE.
51da347917Sbeck  * ====================================================================
52da347917Sbeck  *
53da347917Sbeck  * This product includes cryptographic software written by Eric Young
54da347917Sbeck  * (eay@cryptsoft.com).  This product includes software written by Tim
55da347917Sbeck  * Hudson (tjh@cryptsoft.com).
56da347917Sbeck  *
57da347917Sbeck  */
58da347917Sbeck 
59da347917Sbeck #include <openssl/ocsp.h>
60da347917Sbeck #include <openssl/err.h>
61da347917Sbeck #include <string.h>
62da347917Sbeck 
639f44a700Stb #include "ocsp_local.h"
64c9675a23Stb #include "x509_local.h"
65838f0b6dStb 
662d2941d0Smiod static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs,
672d2941d0Smiod     STACK_OF(X509) *certs, X509_STORE *st, unsigned long flags);
68da347917Sbeck static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id);
692d2941d0Smiod static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain,
702d2941d0Smiod     unsigned long flags);
71da347917Sbeck static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret);
722d2941d0Smiod static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid,
732d2941d0Smiod     STACK_OF(OCSP_SINGLERESP) *sresp);
74da347917Sbeck static int ocsp_check_delegated(X509 *x, int flags);
752d2941d0Smiod static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req,
762d2941d0Smiod     X509_NAME *nm, STACK_OF(X509) *certs, X509_STORE *st,
772d2941d0Smiod     unsigned long flags);
78da347917Sbeck 
79da347917Sbeck /* Verify a basic response message */
802d2941d0Smiod int
OCSP_basic_verify(OCSP_BASICRESP * bs,STACK_OF (X509)* certs,X509_STORE * st,unsigned long flags)812d2941d0Smiod OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, X509_STORE *st,
822d2941d0Smiod     unsigned long flags)
83da347917Sbeck {
84da347917Sbeck 	X509 *signer, *x;
85da347917Sbeck 	STACK_OF(X509) *chain = NULL;
86ac6b1dd5Sbeck 	STACK_OF(X509) *untrusted = NULL;
87da347917Sbeck 	X509_STORE_CTX ctx;
88da347917Sbeck 	int i, ret = 0;
892d2941d0Smiod 
90da347917Sbeck 	ret = ocsp_find_signer(&signer, bs, certs, st, flags);
912d2941d0Smiod 	if (!ret) {
925067ae9fSbeck 		OCSPerror(OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
93da347917Sbeck 		goto end;
94da347917Sbeck 	}
95da347917Sbeck 	if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
96da347917Sbeck 		flags |= OCSP_NOVERIFY;
972d2941d0Smiod 	if (!(flags & OCSP_NOSIGS)) {
98da347917Sbeck 		EVP_PKEY *skey;
992d2941d0Smiod 
1001b78ce04Stb 		skey = X509_get0_pubkey(signer);
1012d2941d0Smiod 		if (skey) {
102da347917Sbeck 			ret = OCSP_BASICRESP_verify(bs, skey, 0);
103c5957159Smarkus 		}
1042d2941d0Smiod 		if (!skey || ret <= 0) {
1055067ae9fSbeck 			OCSPerror(OCSP_R_SIGNATURE_FAILURE);
106da347917Sbeck 			goto end;
107da347917Sbeck 		}
108da347917Sbeck 	}
1092d2941d0Smiod 	if (!(flags & OCSP_NOVERIFY)) {
110da347917Sbeck 		int init_res;
1112d2941d0Smiod 
112ac6b1dd5Sbeck 		if (flags & OCSP_NOCHAIN) {
113ac6b1dd5Sbeck 			untrusted = NULL;
114ac6b1dd5Sbeck 		} else if (bs->certs && certs) {
115ac6b1dd5Sbeck 			untrusted = sk_X509_dup(bs->certs);
116ac6b1dd5Sbeck 			for (i = 0; i < sk_X509_num(certs); i++) {
117ac6b1dd5Sbeck 				if (!sk_X509_push(untrusted,
118ac6b1dd5Sbeck 					sk_X509_value(certs, i))) {
1195067ae9fSbeck 					OCSPerror(ERR_R_MALLOC_FAILURE);
120ac6b1dd5Sbeck 					goto end;
121ac6b1dd5Sbeck 				}
122ac6b1dd5Sbeck 			}
1232b1ad87fStb 		} else if (certs != NULL) {
1242b1ad87fStb 			untrusted = certs;
1252b1ad87fStb 		} else {
126ac6b1dd5Sbeck 			untrusted = bs->certs;
1272b1ad87fStb 		}
128ac6b1dd5Sbeck 		init_res = X509_STORE_CTX_init(&ctx, st, signer, untrusted);
1292d2941d0Smiod 		if (!init_res) {
13097222eddSmiod 			ret = -1;
1315067ae9fSbeck 			OCSPerror(ERR_R_X509_LIB);
132da347917Sbeck 			goto end;
133da347917Sbeck 		}
134da347917Sbeck 
135c602b0f2Smiod 		if (X509_STORE_CTX_set_purpose(&ctx,
136c602b0f2Smiod 		    X509_PURPOSE_OCSP_HELPER) == 0) {
137c602b0f2Smiod 			X509_STORE_CTX_cleanup(&ctx);
138c602b0f2Smiod 			ret = -1;
139c602b0f2Smiod 			goto end;
140c602b0f2Smiod 		}
141da347917Sbeck 		ret = X509_verify_cert(&ctx);
142da347917Sbeck 		chain = X509_STORE_CTX_get1_chain(&ctx);
143da347917Sbeck 		X509_STORE_CTX_cleanup(&ctx);
1442d2941d0Smiod 		if (ret <= 0) {
145da347917Sbeck 			i = X509_STORE_CTX_get_error(&ctx);
1465067ae9fSbeck 			OCSPerror(OCSP_R_CERTIFICATE_VERIFY_ERROR);
1470f637b92Sbeck 			ERR_asprintf_error_data("Verify error:%s",
148da347917Sbeck 			    X509_verify_cert_error_string(i));
149da347917Sbeck 			goto end;
150da347917Sbeck 		}
1512d2941d0Smiod 		if (flags & OCSP_NOCHECKS) {
152da347917Sbeck 			ret = 1;
153da347917Sbeck 			goto end;
154da347917Sbeck 		}
155da347917Sbeck 		/* At this point we have a valid certificate chain
156da347917Sbeck 		 * need to verify it against the OCSP issuer criteria.
157da347917Sbeck 		 */
158da347917Sbeck 		ret = ocsp_check_issuer(bs, chain, flags);
159da347917Sbeck 
160da347917Sbeck 		/* If fatal error or valid match then finish */
1612d2941d0Smiod 		if (ret != 0)
1622d2941d0Smiod 			goto end;
163da347917Sbeck 
164da347917Sbeck 		/* Easy case: explicitly trusted. Get root CA and
165da347917Sbeck 		 * check for explicit trust
166da347917Sbeck 		 */
1672d2941d0Smiod 		if (flags & OCSP_NOEXPLICIT)
1682d2941d0Smiod 			goto end;
169da347917Sbeck 
170da347917Sbeck 		x = sk_X509_value(chain, sk_X509_num(chain) - 1);
171*75e21034Sbeck 		if (X509_check_trust(x, X509_TRUST_OCSP_SIGN, 0) !=
1722d2941d0Smiod 		    X509_TRUST_TRUSTED) {
1735067ae9fSbeck 			OCSPerror(OCSP_R_ROOT_CA_NOT_TRUSTED);
174da347917Sbeck 			goto end;
175da347917Sbeck 		}
176da347917Sbeck 		ret = 1;
177da347917Sbeck 	}
178da347917Sbeck 
179da347917Sbeck end:
1802d2941d0Smiod 	if (chain)
1812d2941d0Smiod 		sk_X509_pop_free(chain, X509_free);
182ac6b1dd5Sbeck 	if (bs->certs && certs)
183ac6b1dd5Sbeck 		sk_X509_free(untrusted);
184da347917Sbeck 	return ret;
185da347917Sbeck }
186a1e92f6bSbeck LCRYPTO_ALIAS(OCSP_basic_verify);
187da347917Sbeck 
188d779a45bStb int
OCSP_resp_get0_signer(OCSP_BASICRESP * bs,X509 ** signer,STACK_OF (X509)* extra_certs)189d779a45bStb OCSP_resp_get0_signer(OCSP_BASICRESP *bs, X509 **signer,
190d779a45bStb     STACK_OF(X509) *extra_certs)
191d779a45bStb {
192d779a45bStb 	return ocsp_find_signer(signer, bs, extra_certs, NULL, 0) > 0;
193d779a45bStb }
194a1e92f6bSbeck LCRYPTO_ALIAS(OCSP_resp_get0_signer);
195d779a45bStb 
1962d2941d0Smiod static int
ocsp_find_signer(X509 ** psigner,OCSP_BASICRESP * bs,STACK_OF (X509)* certs,X509_STORE * st,unsigned long flags)1972d2941d0Smiod ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
198da347917Sbeck     X509_STORE *st, unsigned long flags)
199da347917Sbeck {
200da347917Sbeck 	X509 *signer;
201da347917Sbeck 	OCSP_RESPID *rid = bs->tbsResponseData->responderId;
2022d2941d0Smiod 
2032d2941d0Smiod 	if ((signer = ocsp_find_signer_sk(certs, rid))) {
204da347917Sbeck 		*psigner = signer;
205da347917Sbeck 		return 2;
206da347917Sbeck 	}
207da347917Sbeck 	if (!(flags & OCSP_NOINTERN) &&
2082d2941d0Smiod 	    (signer = ocsp_find_signer_sk(bs->certs, rid))) {
209da347917Sbeck 		*psigner = signer;
210da347917Sbeck 		return 1;
211da347917Sbeck 	}
212da347917Sbeck 	/* Maybe lookup from store if by subject name */
213da347917Sbeck 
214da347917Sbeck 	*psigner = NULL;
215da347917Sbeck 	return 0;
216da347917Sbeck }
217da347917Sbeck 
2182d2941d0Smiod static X509 *
ocsp_find_signer_sk(STACK_OF (X509)* certs,OCSP_RESPID * id)2192d2941d0Smiod ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
220da347917Sbeck {
221da347917Sbeck 	int i;
222da347917Sbeck 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
223da347917Sbeck 	X509 *x;
224da347917Sbeck 
225da347917Sbeck 	/* Easy if lookup by name */
226da347917Sbeck 	if (id->type == V_OCSP_RESPID_NAME)
227da347917Sbeck 		return X509_find_by_subject(certs, id->value.byName);
228da347917Sbeck 
229da347917Sbeck 	/* Lookup by key hash */
230da347917Sbeck 
231da347917Sbeck 	/* If key hash isn't SHA1 length then forget it */
2322d2941d0Smiod 	if (id->value.byKey->length != SHA_DIGEST_LENGTH)
2332d2941d0Smiod 		return NULL;
234da347917Sbeck 	keyhash = id->value.byKey->data;
235da347917Sbeck 	/* Calculate hash of each key and compare */
2362d2941d0Smiod 	for (i = 0; i < sk_X509_num(certs); i++) {
237da347917Sbeck 		x = sk_X509_value(certs, i);
238da347917Sbeck 		X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
239da347917Sbeck 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
240da347917Sbeck 			return x;
241da347917Sbeck 	}
242da347917Sbeck 	return NULL;
243da347917Sbeck }
244da347917Sbeck 
2452d2941d0Smiod static int
ocsp_check_issuer(OCSP_BASICRESP * bs,STACK_OF (X509)* chain,unsigned long flags)2462d2941d0Smiod ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain,
2472d2941d0Smiod     unsigned long flags)
248da347917Sbeck {
249da347917Sbeck 	STACK_OF(OCSP_SINGLERESP) *sresp;
250da347917Sbeck 	X509 *signer, *sca;
251da347917Sbeck 	OCSP_CERTID *caid = NULL;
252da347917Sbeck 	int i;
2532d2941d0Smiod 
254da347917Sbeck 	sresp = bs->tbsResponseData->responses;
255da347917Sbeck 
2562d2941d0Smiod 	if (sk_X509_num(chain) <= 0) {
2575067ae9fSbeck 		OCSPerror(OCSP_R_NO_CERTIFICATES_IN_CHAIN);
258da347917Sbeck 		return -1;
259da347917Sbeck 	}
260da347917Sbeck 
261da347917Sbeck 	/* See if the issuer IDs match. */
262da347917Sbeck 	i = ocsp_check_ids(sresp, &caid);
263da347917Sbeck 
264da347917Sbeck 	/* If ID mismatch or other error then return */
2652d2941d0Smiod 	if (i <= 0)
2662d2941d0Smiod 		return i;
267da347917Sbeck 
268da347917Sbeck 	signer = sk_X509_value(chain, 0);
269da347917Sbeck 	/* Check to see if OCSP responder CA matches request CA */
2702d2941d0Smiod 	if (sk_X509_num(chain) > 1) {
271da347917Sbeck 		sca = sk_X509_value(chain, 1);
272da347917Sbeck 		i = ocsp_match_issuerid(sca, caid, sresp);
2732d2941d0Smiod 		if (i < 0)
2742d2941d0Smiod 			return i;
2752d2941d0Smiod 		if (i) {
276da347917Sbeck 			/* We have a match, if extensions OK then success */
2772d2941d0Smiod 			if (ocsp_check_delegated(signer, flags))
2782d2941d0Smiod 				return 1;
279da347917Sbeck 			return 0;
280da347917Sbeck 		}
281da347917Sbeck 	}
282da347917Sbeck 
283da347917Sbeck 	/* Otherwise check if OCSP request signed directly by request CA */
284da347917Sbeck 	return ocsp_match_issuerid(signer, caid, sresp);
285da347917Sbeck }
286da347917Sbeck 
287da347917Sbeck /* Check the issuer certificate IDs for equality. If there is a mismatch with the same
288da347917Sbeck  * algorithm then there's no point trying to match any certificates against the issuer.
289da347917Sbeck  * If the issuer IDs all match then we just need to check equality against one of them.
290da347917Sbeck  */
2912d2941d0Smiod static int
ocsp_check_ids(STACK_OF (OCSP_SINGLERESP)* sresp,OCSP_CERTID ** ret)2922d2941d0Smiod ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret)
293da347917Sbeck {
294da347917Sbeck 	OCSP_CERTID *tmpid, *cid;
295da347917Sbeck 	int i, idcount;
296da347917Sbeck 
297da347917Sbeck 	idcount = sk_OCSP_SINGLERESP_num(sresp);
2982d2941d0Smiod 	if (idcount <= 0) {
2995067ae9fSbeck 		OCSPerror(OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA);
300da347917Sbeck 		return -1;
301da347917Sbeck 	}
302da347917Sbeck 
303da347917Sbeck 	cid = sk_OCSP_SINGLERESP_value(sresp, 0)->certId;
304da347917Sbeck 
305da347917Sbeck 	*ret = NULL;
306da347917Sbeck 
3072d2941d0Smiod 	for (i = 1; i < idcount; i++) {
308720b416eSmarkus 		tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId;
309da347917Sbeck 		/* Check to see if IDs match */
3102d2941d0Smiod 		if (OCSP_id_issuer_cmp(cid, tmpid)) {
311da347917Sbeck 			return 0;
312da347917Sbeck 		}
313da347917Sbeck 	}
314da347917Sbeck 
315da347917Sbeck 	/* All IDs match: only need to check one ID */
316da347917Sbeck 	*ret = cid;
317da347917Sbeck 	return 1;
318da347917Sbeck }
319da347917Sbeck 
3202d2941d0Smiod static int
ocsp_match_issuerid(X509 * cert,OCSP_CERTID * cid,STACK_OF (OCSP_SINGLERESP)* sresp)3212d2941d0Smiod ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid,
322da347917Sbeck     STACK_OF(OCSP_SINGLERESP) *sresp)
323da347917Sbeck {
324da347917Sbeck 	/* If only one ID to match then do it */
3252d2941d0Smiod 	if (cid) {
326da347917Sbeck 		const EVP_MD *dgst;
327da347917Sbeck 		X509_NAME *iname;
328da347917Sbeck 		int mdlen;
329da347917Sbeck 		unsigned char md[EVP_MAX_MD_SIZE];
3302d2941d0Smiod 
3312d2941d0Smiod 		if (!(dgst =
3322d2941d0Smiod 		    EVP_get_digestbyobj(cid->hashAlgorithm->algorithm))) {
3335067ae9fSbeck 			OCSPerror(OCSP_R_UNKNOWN_MESSAGE_DIGEST);
334da347917Sbeck 			return -1;
335da347917Sbeck 		}
336da347917Sbeck 
337da347917Sbeck 		mdlen = EVP_MD_size(dgst);
3380a5d6edeSdjm 		if (mdlen < 0)
3390a5d6edeSdjm 			return -1;
3402d2941d0Smiod 		if (cid->issuerNameHash->length != mdlen ||
3412d2941d0Smiod 		    cid->issuerKeyHash->length != mdlen)
342da347917Sbeck 			return 0;
343da347917Sbeck 		iname = X509_get_subject_name(cert);
344da347917Sbeck 		if (!X509_NAME_digest(iname, dgst, md, NULL))
345da347917Sbeck 			return -1;
346da347917Sbeck 		if (memcmp(md, cid->issuerNameHash->data, mdlen))
347da347917Sbeck 			return 0;
3480a5d6edeSdjm 		X509_pubkey_digest(cert, dgst, md, NULL);
349da347917Sbeck 		if (memcmp(md, cid->issuerKeyHash->data, mdlen))
350da347917Sbeck 			return 0;
351da347917Sbeck 
352da347917Sbeck 		return 1;
3532d2941d0Smiod 	} else {
354da347917Sbeck 		/* We have to match the whole lot */
355da347917Sbeck 		int i, ret;
356da347917Sbeck 		OCSP_CERTID *tmpid;
3572d2941d0Smiod 
3582d2941d0Smiod 		for (i = 0; i < sk_OCSP_SINGLERESP_num(sresp); i++) {
359720b416eSmarkus 			tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId;
360da347917Sbeck 			ret = ocsp_match_issuerid(cert, tmpid, NULL);
3612d2941d0Smiod 			if (ret <= 0)
3622d2941d0Smiod 				return ret;
363da347917Sbeck 		}
364da347917Sbeck 		return 1;
365da347917Sbeck 	}
366da347917Sbeck }
367da347917Sbeck 
3682d2941d0Smiod static int
ocsp_check_delegated(X509 * x,int flags)3692d2941d0Smiod ocsp_check_delegated(X509 *x, int flags)
370da347917Sbeck {
371da347917Sbeck 	X509_check_purpose(x, -1, 0);
3722d2941d0Smiod 	if ((x->ex_flags & EXFLAG_XKUSAGE) && (x->ex_xkusage & XKU_OCSP_SIGN))
373da347917Sbeck 		return 1;
3745067ae9fSbeck 	OCSPerror(OCSP_R_MISSING_OCSPSIGNING_USAGE);
375da347917Sbeck 	return 0;
376da347917Sbeck }
377da347917Sbeck 
378da347917Sbeck /* Verify an OCSP request. This is fortunately much easier than OCSP
379da347917Sbeck  * response verify. Just find the signers certificate and verify it
380da347917Sbeck  * against a given trust value.
381da347917Sbeck  */
3822d2941d0Smiod int
OCSP_request_verify(OCSP_REQUEST * req,STACK_OF (X509)* certs,X509_STORE * store,unsigned long flags)3832d2941d0Smiod OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store,
3842d2941d0Smiod     unsigned long flags)
385da347917Sbeck {
386da347917Sbeck 	X509 *signer;
387da347917Sbeck 	X509_NAME *nm;
388da347917Sbeck 	GENERAL_NAME *gen;
389da347917Sbeck 	int ret;
390da347917Sbeck 	X509_STORE_CTX ctx;
3912d2941d0Smiod 
3922d2941d0Smiod 	if (!req->optionalSignature) {
3935067ae9fSbeck 		OCSPerror(OCSP_R_REQUEST_NOT_SIGNED);
394da347917Sbeck 		return 0;
395da347917Sbeck 	}
396da347917Sbeck 	gen = req->tbsRequest->requestorName;
3972d2941d0Smiod 	if (!gen || gen->type != GEN_DIRNAME) {
3985067ae9fSbeck 		OCSPerror(OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE);
399da347917Sbeck 		return 0;
400da347917Sbeck 	}
401da347917Sbeck 	nm = gen->d.directoryName;
402da347917Sbeck 	ret = ocsp_req_find_signer(&signer, req, nm, certs, store, flags);
4032d2941d0Smiod 	if (ret <= 0) {
4045067ae9fSbeck 		OCSPerror(OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
405da347917Sbeck 		return 0;
406da347917Sbeck 	}
407da347917Sbeck 	if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
408da347917Sbeck 		flags |= OCSP_NOVERIFY;
4092d2941d0Smiod 	if (!(flags & OCSP_NOSIGS)) {
410da347917Sbeck 		EVP_PKEY *skey;
4112d2941d0Smiod 
41299804f43Sinoguchi 		if ((skey = X509_get0_pubkey(signer)) == NULL)
41399804f43Sinoguchi 			return 0;
414da347917Sbeck 		ret = OCSP_REQUEST_verify(req, skey);
4152d2941d0Smiod 		if (ret <= 0) {
4165067ae9fSbeck 			OCSPerror(OCSP_R_SIGNATURE_FAILURE);
417da347917Sbeck 			return 0;
418da347917Sbeck 		}
419da347917Sbeck 	}
4202d2941d0Smiod 	if (!(flags & OCSP_NOVERIFY)) {
421da347917Sbeck 		int init_res;
4222d2941d0Smiod 
423da347917Sbeck 		if (flags & OCSP_NOCHAIN)
4242d2941d0Smiod 			init_res = X509_STORE_CTX_init(&ctx, store, signer,
4252d2941d0Smiod 			    NULL);
426da347917Sbeck 		else
427da347917Sbeck 			init_res = X509_STORE_CTX_init(&ctx, store, signer,
428da347917Sbeck 			    req->optionalSignature->certs);
4292d2941d0Smiod 		if (!init_res) {
4305067ae9fSbeck 			OCSPerror(ERR_R_X509_LIB);
431da347917Sbeck 			return 0;
432da347917Sbeck 		}
433da347917Sbeck 
434c602b0f2Smiod 		if (X509_STORE_CTX_set_purpose(&ctx,
435c602b0f2Smiod 		      X509_PURPOSE_OCSP_HELPER) == 0 ||
436c602b0f2Smiod 		    X509_STORE_CTX_set_trust(&ctx,
437c602b0f2Smiod 		      X509_TRUST_OCSP_REQUEST) == 0) {
438c602b0f2Smiod 			X509_STORE_CTX_cleanup(&ctx);
439c602b0f2Smiod 			return 0;
440c602b0f2Smiod 		}
441da347917Sbeck 		ret = X509_verify_cert(&ctx);
442da347917Sbeck 		X509_STORE_CTX_cleanup(&ctx);
4432d2941d0Smiod 		if (ret <= 0) {
444da347917Sbeck 			ret = X509_STORE_CTX_get_error(&ctx);
4455067ae9fSbeck 			OCSPerror(OCSP_R_CERTIFICATE_VERIFY_ERROR);
4460f637b92Sbeck 			ERR_asprintf_error_data("Verify error:%s",
447da347917Sbeck 			    X509_verify_cert_error_string(ret));
448da347917Sbeck 			return 0;
449da347917Sbeck 		}
450da347917Sbeck 	}
451da347917Sbeck 	return 1;
452da347917Sbeck }
453a1e92f6bSbeck LCRYPTO_ALIAS(OCSP_request_verify);
454da347917Sbeck 
4552d2941d0Smiod static int
ocsp_req_find_signer(X509 ** psigner,OCSP_REQUEST * req,X509_NAME * nm,STACK_OF (X509)* certs,X509_STORE * st,unsigned long flags)4562d2941d0Smiod ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, X509_NAME *nm,
4572d2941d0Smiod     STACK_OF(X509) *certs, X509_STORE *st, unsigned long flags)
458da347917Sbeck {
459da347917Sbeck 	X509 *signer;
4602d2941d0Smiod 
4612d2941d0Smiod 	if (!(flags & OCSP_NOINTERN)) {
462ac6b1dd5Sbeck 		signer = X509_find_by_subject(req->optionalSignature->certs, nm);
463ac6b1dd5Sbeck 		if (signer) {
464da347917Sbeck 			*psigner = signer;
465da347917Sbeck 			return 1;
466da347917Sbeck 		}
467ac6b1dd5Sbeck 	}
468da347917Sbeck 
469da347917Sbeck 	signer = X509_find_by_subject(certs, nm);
4702d2941d0Smiod 	if (signer) {
471da347917Sbeck 		*psigner = signer;
472da347917Sbeck 		return 2;
473da347917Sbeck 	}
474da347917Sbeck 	return 0;
475da347917Sbeck }
476