xref: /openbsd/lib/libcrypto/ocsp/ocsp_vfy.c (revision 5a38ef86)
1 /* $OpenBSD: ocsp_vfy.c,v 1.19 2021/11/24 19:33:24 tb Exp $ */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project 2000.
4  */
5 /* ====================================================================
6  * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58 
59 #include <openssl/ocsp.h>
60 #include <openssl/err.h>
61 #include <string.h>
62 
63 #include "x509_lcl.h"
64 
65 static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs,
66     STACK_OF(X509) *certs, X509_STORE *st, unsigned long flags);
67 static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id);
68 static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain,
69     unsigned long flags);
70 static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret);
71 static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid,
72     STACK_OF(OCSP_SINGLERESP) *sresp);
73 static int ocsp_check_delegated(X509 *x, int flags);
74 static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req,
75     X509_NAME *nm, STACK_OF(X509) *certs, X509_STORE *st,
76     unsigned long flags);
77 
78 /* Verify a basic response message */
79 int
80 OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, X509_STORE *st,
81     unsigned long flags)
82 {
83 	X509 *signer, *x;
84 	STACK_OF(X509) *chain = NULL;
85 	STACK_OF(X509) *untrusted = NULL;
86 	X509_STORE_CTX ctx;
87 	int i, ret = 0;
88 
89 	ret = ocsp_find_signer(&signer, bs, certs, st, flags);
90 	if (!ret) {
91 		OCSPerror(OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
92 		goto end;
93 	}
94 	if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
95 		flags |= OCSP_NOVERIFY;
96 	if (!(flags & OCSP_NOSIGS)) {
97 		EVP_PKEY *skey;
98 
99 		skey = X509_get0_pubkey(signer);
100 		if (skey) {
101 			ret = OCSP_BASICRESP_verify(bs, skey, 0);
102 		}
103 		if (!skey || ret <= 0) {
104 			OCSPerror(OCSP_R_SIGNATURE_FAILURE);
105 			goto end;
106 		}
107 	}
108 	if (!(flags & OCSP_NOVERIFY)) {
109 		int init_res;
110 
111 		if (flags & OCSP_NOCHAIN) {
112 			untrusted = NULL;
113 		} else if (bs->certs && certs) {
114 			untrusted = sk_X509_dup(bs->certs);
115 			for (i = 0; i < sk_X509_num(certs); i++) {
116 				if (!sk_X509_push(untrusted,
117 					sk_X509_value(certs, i))) {
118 					OCSPerror(ERR_R_MALLOC_FAILURE);
119 					goto end;
120 				}
121 			}
122 		} else if (certs != NULL) {
123 			untrusted = certs;
124 		} else {
125 			untrusted = bs->certs;
126 		}
127 		init_res = X509_STORE_CTX_init(&ctx, st, signer, untrusted);
128 		if (!init_res) {
129 			ret = -1;
130 			OCSPerror(ERR_R_X509_LIB);
131 			goto end;
132 		}
133 
134 		if (X509_STORE_CTX_set_purpose(&ctx,
135 		    X509_PURPOSE_OCSP_HELPER) == 0) {
136 			X509_STORE_CTX_cleanup(&ctx);
137 			ret = -1;
138 			goto end;
139 		}
140 		ret = X509_verify_cert(&ctx);
141 		chain = X509_STORE_CTX_get1_chain(&ctx);
142 		X509_STORE_CTX_cleanup(&ctx);
143 		if (ret <= 0) {
144 			i = X509_STORE_CTX_get_error(&ctx);
145 			OCSPerror(OCSP_R_CERTIFICATE_VERIFY_ERROR);
146 			ERR_asprintf_error_data("Verify error:%s",
147 			    X509_verify_cert_error_string(i));
148 			goto end;
149 		}
150 		if (flags & OCSP_NOCHECKS) {
151 			ret = 1;
152 			goto end;
153 		}
154 		/* At this point we have a valid certificate chain
155 		 * need to verify it against the OCSP issuer criteria.
156 		 */
157 		ret = ocsp_check_issuer(bs, chain, flags);
158 
159 		/* If fatal error or valid match then finish */
160 		if (ret != 0)
161 			goto end;
162 
163 		/* Easy case: explicitly trusted. Get root CA and
164 		 * check for explicit trust
165 		 */
166 		if (flags & OCSP_NOEXPLICIT)
167 			goto end;
168 
169 		x = sk_X509_value(chain, sk_X509_num(chain) - 1);
170 		if (X509_check_trust(x, NID_OCSP_sign, 0) !=
171 			X509_TRUST_TRUSTED) {
172 			OCSPerror(OCSP_R_ROOT_CA_NOT_TRUSTED);
173 			goto end;
174 		}
175 		ret = 1;
176 	}
177 
178 end:
179 	if (chain)
180 		sk_X509_pop_free(chain, X509_free);
181 	if (bs->certs && certs)
182 		sk_X509_free(untrusted);
183 	return ret;
184 }
185 
186 int
187 OCSP_resp_get0_signer(OCSP_BASICRESP *bs, X509 **signer,
188     STACK_OF(X509) *extra_certs)
189 {
190 	return ocsp_find_signer(signer, bs, extra_certs, NULL, 0) > 0;
191 }
192 
193 static int
194 ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
195     X509_STORE *st, unsigned long flags)
196 {
197 	X509 *signer;
198 	OCSP_RESPID *rid = bs->tbsResponseData->responderId;
199 
200 	if ((signer = ocsp_find_signer_sk(certs, rid))) {
201 		*psigner = signer;
202 		return 2;
203 	}
204 	if (!(flags & OCSP_NOINTERN) &&
205 	    (signer = ocsp_find_signer_sk(bs->certs, rid))) {
206 		*psigner = signer;
207 		return 1;
208 	}
209 	/* Maybe lookup from store if by subject name */
210 
211 	*psigner = NULL;
212 	return 0;
213 }
214 
215 static X509 *
216 ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
217 {
218 	int i;
219 	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
220 	X509 *x;
221 
222 	/* Easy if lookup by name */
223 	if (id->type == V_OCSP_RESPID_NAME)
224 		return X509_find_by_subject(certs, id->value.byName);
225 
226 	/* Lookup by key hash */
227 
228 	/* If key hash isn't SHA1 length then forget it */
229 	if (id->value.byKey->length != SHA_DIGEST_LENGTH)
230 		return NULL;
231 	keyhash = id->value.byKey->data;
232 	/* Calculate hash of each key and compare */
233 	for (i = 0; i < sk_X509_num(certs); i++) {
234 		x = sk_X509_value(certs, i);
235 		X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
236 		if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
237 			return x;
238 	}
239 	return NULL;
240 }
241 
242 static int
243 ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain,
244     unsigned long flags)
245 {
246 	STACK_OF(OCSP_SINGLERESP) *sresp;
247 	X509 *signer, *sca;
248 	OCSP_CERTID *caid = NULL;
249 	int i;
250 
251 	sresp = bs->tbsResponseData->responses;
252 
253 	if (sk_X509_num(chain) <= 0) {
254 		OCSPerror(OCSP_R_NO_CERTIFICATES_IN_CHAIN);
255 		return -1;
256 	}
257 
258 	/* See if the issuer IDs match. */
259 	i = ocsp_check_ids(sresp, &caid);
260 
261 	/* If ID mismatch or other error then return */
262 	if (i <= 0)
263 		return i;
264 
265 	signer = sk_X509_value(chain, 0);
266 	/* Check to see if OCSP responder CA matches request CA */
267 	if (sk_X509_num(chain) > 1) {
268 		sca = sk_X509_value(chain, 1);
269 		i = ocsp_match_issuerid(sca, caid, sresp);
270 		if (i < 0)
271 			return i;
272 		if (i) {
273 			/* We have a match, if extensions OK then success */
274 			if (ocsp_check_delegated(signer, flags))
275 				return 1;
276 			return 0;
277 		}
278 	}
279 
280 	/* Otherwise check if OCSP request signed directly by request CA */
281 	return ocsp_match_issuerid(signer, caid, sresp);
282 }
283 
284 /* Check the issuer certificate IDs for equality. If there is a mismatch with the same
285  * algorithm then there's no point trying to match any certificates against the issuer.
286  * If the issuer IDs all match then we just need to check equality against one of them.
287  */
288 static int
289 ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret)
290 {
291 	OCSP_CERTID *tmpid, *cid;
292 	int i, idcount;
293 
294 	idcount = sk_OCSP_SINGLERESP_num(sresp);
295 	if (idcount <= 0) {
296 		OCSPerror(OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA);
297 		return -1;
298 	}
299 
300 	cid = sk_OCSP_SINGLERESP_value(sresp, 0)->certId;
301 
302 	*ret = NULL;
303 
304 	for (i = 1; i < idcount; i++) {
305 		tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId;
306 		/* Check to see if IDs match */
307 		if (OCSP_id_issuer_cmp(cid, tmpid)) {
308 			return 0;
309 		}
310 	}
311 
312 	/* All IDs match: only need to check one ID */
313 	*ret = cid;
314 	return 1;
315 }
316 
317 static int
318 ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid,
319     STACK_OF(OCSP_SINGLERESP) *sresp)
320 {
321 	/* If only one ID to match then do it */
322 	if (cid) {
323 		const EVP_MD *dgst;
324 		X509_NAME *iname;
325 		int mdlen;
326 		unsigned char md[EVP_MAX_MD_SIZE];
327 
328 		if (!(dgst =
329 		    EVP_get_digestbyobj(cid->hashAlgorithm->algorithm))) {
330 			OCSPerror(OCSP_R_UNKNOWN_MESSAGE_DIGEST);
331 			return -1;
332 		}
333 
334 		mdlen = EVP_MD_size(dgst);
335 		if (mdlen < 0)
336 			return -1;
337 		if (cid->issuerNameHash->length != mdlen ||
338 		    cid->issuerKeyHash->length != mdlen)
339 			return 0;
340 		iname = X509_get_subject_name(cert);
341 		if (!X509_NAME_digest(iname, dgst, md, NULL))
342 			return -1;
343 		if (memcmp(md, cid->issuerNameHash->data, mdlen))
344 			return 0;
345 		X509_pubkey_digest(cert, dgst, md, NULL);
346 		if (memcmp(md, cid->issuerKeyHash->data, mdlen))
347 			return 0;
348 
349 		return 1;
350 	} else {
351 		/* We have to match the whole lot */
352 		int i, ret;
353 		OCSP_CERTID *tmpid;
354 
355 		for (i = 0; i < sk_OCSP_SINGLERESP_num(sresp); i++) {
356 			tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId;
357 			ret = ocsp_match_issuerid(cert, tmpid, NULL);
358 			if (ret <= 0)
359 				return ret;
360 		}
361 		return 1;
362 	}
363 }
364 
365 static int
366 ocsp_check_delegated(X509 *x, int flags)
367 {
368 	X509_check_purpose(x, -1, 0);
369 	if ((x->ex_flags & EXFLAG_XKUSAGE) && (x->ex_xkusage & XKU_OCSP_SIGN))
370 		return 1;
371 	OCSPerror(OCSP_R_MISSING_OCSPSIGNING_USAGE);
372 	return 0;
373 }
374 
375 /* Verify an OCSP request. This is fortunately much easier than OCSP
376  * response verify. Just find the signers certificate and verify it
377  * against a given trust value.
378  */
379 int
380 OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store,
381     unsigned long flags)
382 {
383 	X509 *signer;
384 	X509_NAME *nm;
385 	GENERAL_NAME *gen;
386 	int ret;
387 	X509_STORE_CTX ctx;
388 
389 	if (!req->optionalSignature) {
390 		OCSPerror(OCSP_R_REQUEST_NOT_SIGNED);
391 		return 0;
392 	}
393 	gen = req->tbsRequest->requestorName;
394 	if (!gen || gen->type != GEN_DIRNAME) {
395 		OCSPerror(OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE);
396 		return 0;
397 	}
398 	nm = gen->d.directoryName;
399 	ret = ocsp_req_find_signer(&signer, req, nm, certs, store, flags);
400 	if (ret <= 0) {
401 		OCSPerror(OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
402 		return 0;
403 	}
404 	if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
405 		flags |= OCSP_NOVERIFY;
406 	if (!(flags & OCSP_NOSIGS)) {
407 		EVP_PKEY *skey;
408 
409 		skey = X509_get_pubkey(signer);
410 		ret = OCSP_REQUEST_verify(req, skey);
411 		EVP_PKEY_free(skey);
412 		if (ret <= 0) {
413 			OCSPerror(OCSP_R_SIGNATURE_FAILURE);
414 			return 0;
415 		}
416 	}
417 	if (!(flags & OCSP_NOVERIFY)) {
418 		int init_res;
419 
420 		if (flags & OCSP_NOCHAIN)
421 			init_res = X509_STORE_CTX_init(&ctx, store, signer,
422 			    NULL);
423 		else
424 			init_res = X509_STORE_CTX_init(&ctx, store, signer,
425 			    req->optionalSignature->certs);
426 		if (!init_res) {
427 			OCSPerror(ERR_R_X509_LIB);
428 			return 0;
429 		}
430 
431 		if (X509_STORE_CTX_set_purpose(&ctx,
432 		      X509_PURPOSE_OCSP_HELPER) == 0 ||
433 		    X509_STORE_CTX_set_trust(&ctx,
434 		      X509_TRUST_OCSP_REQUEST) == 0) {
435 			X509_STORE_CTX_cleanup(&ctx);
436 			return 0;
437 		}
438 		ret = X509_verify_cert(&ctx);
439 		X509_STORE_CTX_cleanup(&ctx);
440 		if (ret <= 0) {
441 			ret = X509_STORE_CTX_get_error(&ctx);
442 			OCSPerror(OCSP_R_CERTIFICATE_VERIFY_ERROR);
443 			ERR_asprintf_error_data("Verify error:%s",
444 			    X509_verify_cert_error_string(ret));
445 			return 0;
446 		}
447 	}
448 	return 1;
449 }
450 
451 static int
452 ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, X509_NAME *nm,
453     STACK_OF(X509) *certs, X509_STORE *st, unsigned long flags)
454 {
455 	X509 *signer;
456 
457 	if (!(flags & OCSP_NOINTERN)) {
458 		signer = X509_find_by_subject(req->optionalSignature->certs, nm);
459 		if (signer) {
460 			*psigner = signer;
461 			return 1;
462 		}
463 	}
464 
465 	signer = X509_find_by_subject(certs, nm);
466 	if (signer) {
467 		*psigner = signer;
468 		return 2;
469 	}
470 	return 0;
471 }
472