diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib/libcrypto/ocsp/ocsp_vfy.c | 475 |
1 files changed, 0 insertions, 475 deletions
diff --git a/src/lib/libcrypto/ocsp/ocsp_vfy.c b/src/lib/libcrypto/ocsp/ocsp_vfy.c deleted file mode 100644 index 27d2283ea7..0000000000 --- a/src/lib/libcrypto/ocsp/ocsp_vfy.c +++ /dev/null | |||
@@ -1,475 +0,0 @@ | |||
1 | /* $OpenBSD: ocsp_vfy.c,v 1.24 2024/07/12 18:15:10 beck 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 "ocsp_local.h" | ||
64 | #include "x509_local.h" | ||
65 | |||
66 | static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, | ||
67 | STACK_OF(X509) *certs, X509_STORE *st, unsigned long flags); | ||
68 | static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id); | ||
69 | static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, | ||
70 | unsigned long flags); | ||
71 | static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret); | ||
72 | static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, | ||
73 | STACK_OF(OCSP_SINGLERESP) *sresp); | ||
74 | static int ocsp_check_delegated(X509 *x, int flags); | ||
75 | static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, | ||
76 | X509_NAME *nm, STACK_OF(X509) *certs, X509_STORE *st, | ||
77 | unsigned long flags); | ||
78 | |||
79 | /* Verify a basic response message */ | ||
80 | int | ||
81 | OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, X509_STORE *st, | ||
82 | unsigned long flags) | ||
83 | { | ||
84 | X509 *signer, *x; | ||
85 | STACK_OF(X509) *chain = NULL; | ||
86 | STACK_OF(X509) *untrusted = NULL; | ||
87 | X509_STORE_CTX ctx; | ||
88 | int i, ret = 0; | ||
89 | |||
90 | ret = ocsp_find_signer(&signer, bs, certs, st, flags); | ||
91 | if (!ret) { | ||
92 | OCSPerror(OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND); | ||
93 | goto end; | ||
94 | } | ||
95 | if ((ret == 2) && (flags & OCSP_TRUSTOTHER)) | ||
96 | flags |= OCSP_NOVERIFY; | ||
97 | if (!(flags & OCSP_NOSIGS)) { | ||
98 | EVP_PKEY *skey; | ||
99 | |||
100 | skey = X509_get0_pubkey(signer); | ||
101 | if (skey) { | ||
102 | ret = OCSP_BASICRESP_verify(bs, skey, 0); | ||
103 | } | ||
104 | if (!skey || ret <= 0) { | ||
105 | OCSPerror(OCSP_R_SIGNATURE_FAILURE); | ||
106 | goto end; | ||
107 | } | ||
108 | } | ||
109 | if (!(flags & OCSP_NOVERIFY)) { | ||
110 | int init_res; | ||
111 | |||
112 | if (flags & OCSP_NOCHAIN) { | ||
113 | untrusted = NULL; | ||
114 | } else if (bs->certs && certs) { | ||
115 | untrusted = sk_X509_dup(bs->certs); | ||
116 | for (i = 0; i < sk_X509_num(certs); i++) { | ||
117 | if (!sk_X509_push(untrusted, | ||
118 | sk_X509_value(certs, i))) { | ||
119 | OCSPerror(ERR_R_MALLOC_FAILURE); | ||
120 | goto end; | ||
121 | } | ||
122 | } | ||
123 | } else if (certs != NULL) { | ||
124 | untrusted = certs; | ||
125 | } else { | ||
126 | untrusted = bs->certs; | ||
127 | } | ||
128 | init_res = X509_STORE_CTX_init(&ctx, st, signer, untrusted); | ||
129 | if (!init_res) { | ||
130 | ret = -1; | ||
131 | OCSPerror(ERR_R_X509_LIB); | ||
132 | goto end; | ||
133 | } | ||
134 | |||
135 | if (X509_STORE_CTX_set_purpose(&ctx, | ||
136 | X509_PURPOSE_OCSP_HELPER) == 0) { | ||
137 | X509_STORE_CTX_cleanup(&ctx); | ||
138 | ret = -1; | ||
139 | goto end; | ||
140 | } | ||
141 | ret = X509_verify_cert(&ctx); | ||
142 | chain = X509_STORE_CTX_get1_chain(&ctx); | ||
143 | X509_STORE_CTX_cleanup(&ctx); | ||
144 | if (ret <= 0) { | ||
145 | i = X509_STORE_CTX_get_error(&ctx); | ||
146 | OCSPerror(OCSP_R_CERTIFICATE_VERIFY_ERROR); | ||
147 | ERR_asprintf_error_data("Verify error:%s", | ||
148 | X509_verify_cert_error_string(i)); | ||
149 | goto end; | ||
150 | } | ||
151 | if (flags & OCSP_NOCHECKS) { | ||
152 | ret = 1; | ||
153 | goto end; | ||
154 | } | ||
155 | /* At this point we have a valid certificate chain | ||
156 | * need to verify it against the OCSP issuer criteria. | ||
157 | */ | ||
158 | ret = ocsp_check_issuer(bs, chain, flags); | ||
159 | |||
160 | /* If fatal error or valid match then finish */ | ||
161 | if (ret != 0) | ||
162 | goto end; | ||
163 | |||
164 | /* Easy case: explicitly trusted. Get root CA and | ||
165 | * check for explicit trust | ||
166 | */ | ||
167 | if (flags & OCSP_NOEXPLICIT) | ||
168 | goto end; | ||
169 | |||
170 | x = sk_X509_value(chain, sk_X509_num(chain) - 1); | ||
171 | if (X509_check_trust(x, X509_TRUST_OCSP_SIGN, 0) != | ||
172 | X509_TRUST_TRUSTED) { | ||
173 | OCSPerror(OCSP_R_ROOT_CA_NOT_TRUSTED); | ||
174 | goto end; | ||
175 | } | ||
176 | ret = 1; | ||
177 | } | ||
178 | |||
179 | end: | ||
180 | if (chain) | ||
181 | sk_X509_pop_free(chain, X509_free); | ||
182 | if (bs->certs && certs) | ||
183 | sk_X509_free(untrusted); | ||
184 | return ret; | ||
185 | } | ||
186 | LCRYPTO_ALIAS(OCSP_basic_verify); | ||
187 | |||
188 | int | ||
189 | OCSP_resp_get0_signer(OCSP_BASICRESP *bs, X509 **signer, | ||
190 | STACK_OF(X509) *extra_certs) | ||
191 | { | ||
192 | return ocsp_find_signer(signer, bs, extra_certs, NULL, 0) > 0; | ||
193 | } | ||
194 | LCRYPTO_ALIAS(OCSP_resp_get0_signer); | ||
195 | |||
196 | static int | ||
197 | ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs, | ||
198 | X509_STORE *st, unsigned long flags) | ||
199 | { | ||
200 | X509 *signer; | ||
201 | OCSP_RESPID *rid = bs->tbsResponseData->responderId; | ||
202 | |||
203 | if ((signer = ocsp_find_signer_sk(certs, rid))) { | ||
204 | *psigner = signer; | ||
205 | return 2; | ||
206 | } | ||
207 | if (!(flags & OCSP_NOINTERN) && | ||
208 | (signer = ocsp_find_signer_sk(bs->certs, rid))) { | ||
209 | *psigner = signer; | ||
210 | return 1; | ||
211 | } | ||
212 | /* Maybe lookup from store if by subject name */ | ||
213 | |||
214 | *psigner = NULL; | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static X509 * | ||
219 | ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id) | ||
220 | { | ||
221 | int i; | ||
222 | unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash; | ||
223 | X509 *x; | ||
224 | |||
225 | /* Easy if lookup by name */ | ||
226 | if (id->type == V_OCSP_RESPID_NAME) | ||
227 | return X509_find_by_subject(certs, id->value.byName); | ||
228 | |||
229 | /* Lookup by key hash */ | ||
230 | |||
231 | /* If key hash isn't SHA1 length then forget it */ | ||
232 | if (id->value.byKey->length != SHA_DIGEST_LENGTH) | ||
233 | return NULL; | ||
234 | keyhash = id->value.byKey->data; | ||
235 | /* Calculate hash of each key and compare */ | ||
236 | for (i = 0; i < sk_X509_num(certs); i++) { | ||
237 | x = sk_X509_value(certs, i); | ||
238 | X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL); | ||
239 | if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH)) | ||
240 | return x; | ||
241 | } | ||
242 | return NULL; | ||
243 | } | ||
244 | |||
245 | static int | ||
246 | ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, | ||
247 | unsigned long flags) | ||
248 | { | ||
249 | STACK_OF(OCSP_SINGLERESP) *sresp; | ||
250 | X509 *signer, *sca; | ||
251 | OCSP_CERTID *caid = NULL; | ||
252 | int i; | ||
253 | |||
254 | sresp = bs->tbsResponseData->responses; | ||
255 | |||
256 | if (sk_X509_num(chain) <= 0) { | ||
257 | OCSPerror(OCSP_R_NO_CERTIFICATES_IN_CHAIN); | ||
258 | return -1; | ||
259 | } | ||
260 | |||
261 | /* See if the issuer IDs match. */ | ||
262 | i = ocsp_check_ids(sresp, &caid); | ||
263 | |||
264 | /* If ID mismatch or other error then return */ | ||
265 | if (i <= 0) | ||
266 | return i; | ||
267 | |||
268 | signer = sk_X509_value(chain, 0); | ||
269 | /* Check to see if OCSP responder CA matches request CA */ | ||
270 | if (sk_X509_num(chain) > 1) { | ||
271 | sca = sk_X509_value(chain, 1); | ||
272 | i = ocsp_match_issuerid(sca, caid, sresp); | ||
273 | if (i < 0) | ||
274 | return i; | ||
275 | if (i) { | ||
276 | /* We have a match, if extensions OK then success */ | ||
277 | if (ocsp_check_delegated(signer, flags)) | ||
278 | return 1; | ||
279 | return 0; | ||
280 | } | ||
281 | } | ||
282 | |||
283 | /* Otherwise check if OCSP request signed directly by request CA */ | ||
284 | return ocsp_match_issuerid(signer, caid, sresp); | ||
285 | } | ||
286 | |||
287 | /* Check the issuer certificate IDs for equality. If there is a mismatch with the same | ||
288 | * algorithm then there's no point trying to match any certificates against the issuer. | ||
289 | * If the issuer IDs all match then we just need to check equality against one of them. | ||
290 | */ | ||
291 | static int | ||
292 | ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret) | ||
293 | { | ||
294 | OCSP_CERTID *tmpid, *cid; | ||
295 | int i, idcount; | ||
296 | |||
297 | idcount = sk_OCSP_SINGLERESP_num(sresp); | ||
298 | if (idcount <= 0) { | ||
299 | OCSPerror(OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA); | ||
300 | return -1; | ||
301 | } | ||
302 | |||
303 | cid = sk_OCSP_SINGLERESP_value(sresp, 0)->certId; | ||
304 | |||
305 | *ret = NULL; | ||
306 | |||
307 | for (i = 1; i < idcount; i++) { | ||
308 | tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId; | ||
309 | /* Check to see if IDs match */ | ||
310 | if (OCSP_id_issuer_cmp(cid, tmpid)) { | ||
311 | return 0; | ||
312 | } | ||
313 | } | ||
314 | |||
315 | /* All IDs match: only need to check one ID */ | ||
316 | *ret = cid; | ||
317 | return 1; | ||
318 | } | ||
319 | |||
320 | static int | ||
321 | ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, | ||
322 | STACK_OF(OCSP_SINGLERESP) *sresp) | ||
323 | { | ||
324 | /* If only one ID to match then do it */ | ||
325 | if (cid) { | ||
326 | const EVP_MD *dgst; | ||
327 | X509_NAME *iname; | ||
328 | int mdlen; | ||
329 | unsigned char md[EVP_MAX_MD_SIZE]; | ||
330 | |||
331 | if (!(dgst = | ||
332 | EVP_get_digestbyobj(cid->hashAlgorithm->algorithm))) { | ||
333 | OCSPerror(OCSP_R_UNKNOWN_MESSAGE_DIGEST); | ||
334 | return -1; | ||
335 | } | ||
336 | |||
337 | mdlen = EVP_MD_size(dgst); | ||
338 | if (mdlen < 0) | ||
339 | return -1; | ||
340 | if (cid->issuerNameHash->length != mdlen || | ||
341 | cid->issuerKeyHash->length != mdlen) | ||
342 | return 0; | ||
343 | iname = X509_get_subject_name(cert); | ||
344 | if (!X509_NAME_digest(iname, dgst, md, NULL)) | ||
345 | return -1; | ||
346 | if (memcmp(md, cid->issuerNameHash->data, mdlen)) | ||
347 | return 0; | ||
348 | X509_pubkey_digest(cert, dgst, md, NULL); | ||
349 | if (memcmp(md, cid->issuerKeyHash->data, mdlen)) | ||
350 | return 0; | ||
351 | |||
352 | return 1; | ||
353 | } else { | ||
354 | /* We have to match the whole lot */ | ||
355 | int i, ret; | ||
356 | OCSP_CERTID *tmpid; | ||
357 | |||
358 | for (i = 0; i < sk_OCSP_SINGLERESP_num(sresp); i++) { | ||
359 | tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId; | ||
360 | ret = ocsp_match_issuerid(cert, tmpid, NULL); | ||
361 | if (ret <= 0) | ||
362 | return ret; | ||
363 | } | ||
364 | return 1; | ||
365 | } | ||
366 | } | ||
367 | |||
368 | static int | ||
369 | ocsp_check_delegated(X509 *x, int flags) | ||
370 | { | ||
371 | X509_check_purpose(x, -1, 0); | ||
372 | if ((x->ex_flags & EXFLAG_XKUSAGE) && (x->ex_xkusage & XKU_OCSP_SIGN)) | ||
373 | return 1; | ||
374 | OCSPerror(OCSP_R_MISSING_OCSPSIGNING_USAGE); | ||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | /* Verify an OCSP request. This is fortunately much easier than OCSP | ||
379 | * response verify. Just find the signers certificate and verify it | ||
380 | * against a given trust value. | ||
381 | */ | ||
382 | int | ||
383 | OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store, | ||
384 | unsigned long flags) | ||
385 | { | ||
386 | X509 *signer; | ||
387 | X509_NAME *nm; | ||
388 | GENERAL_NAME *gen; | ||
389 | int ret; | ||
390 | X509_STORE_CTX ctx; | ||
391 | |||
392 | if (!req->optionalSignature) { | ||
393 | OCSPerror(OCSP_R_REQUEST_NOT_SIGNED); | ||
394 | return 0; | ||
395 | } | ||
396 | gen = req->tbsRequest->requestorName; | ||
397 | if (!gen || gen->type != GEN_DIRNAME) { | ||
398 | OCSPerror(OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE); | ||
399 | return 0; | ||
400 | } | ||
401 | nm = gen->d.directoryName; | ||
402 | ret = ocsp_req_find_signer(&signer, req, nm, certs, store, flags); | ||
403 | if (ret <= 0) { | ||
404 | OCSPerror(OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND); | ||
405 | return 0; | ||
406 | } | ||
407 | if ((ret == 2) && (flags & OCSP_TRUSTOTHER)) | ||
408 | flags |= OCSP_NOVERIFY; | ||
409 | if (!(flags & OCSP_NOSIGS)) { | ||
410 | EVP_PKEY *skey; | ||
411 | |||
412 | if ((skey = X509_get0_pubkey(signer)) == NULL) | ||
413 | return 0; | ||
414 | ret = OCSP_REQUEST_verify(req, skey); | ||
415 | if (ret <= 0) { | ||
416 | OCSPerror(OCSP_R_SIGNATURE_FAILURE); | ||
417 | return 0; | ||
418 | } | ||
419 | } | ||
420 | if (!(flags & OCSP_NOVERIFY)) { | ||
421 | int init_res; | ||
422 | |||
423 | if (flags & OCSP_NOCHAIN) | ||
424 | init_res = X509_STORE_CTX_init(&ctx, store, signer, | ||
425 | NULL); | ||
426 | else | ||
427 | init_res = X509_STORE_CTX_init(&ctx, store, signer, | ||
428 | req->optionalSignature->certs); | ||
429 | if (!init_res) { | ||
430 | OCSPerror(ERR_R_X509_LIB); | ||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | if (X509_STORE_CTX_set_purpose(&ctx, | ||
435 | X509_PURPOSE_OCSP_HELPER) == 0 || | ||
436 | X509_STORE_CTX_set_trust(&ctx, | ||
437 | X509_TRUST_OCSP_REQUEST) == 0) { | ||
438 | X509_STORE_CTX_cleanup(&ctx); | ||
439 | return 0; | ||
440 | } | ||
441 | ret = X509_verify_cert(&ctx); | ||
442 | X509_STORE_CTX_cleanup(&ctx); | ||
443 | if (ret <= 0) { | ||
444 | ret = X509_STORE_CTX_get_error(&ctx); | ||
445 | OCSPerror(OCSP_R_CERTIFICATE_VERIFY_ERROR); | ||
446 | ERR_asprintf_error_data("Verify error:%s", | ||
447 | X509_verify_cert_error_string(ret)); | ||
448 | return 0; | ||
449 | } | ||
450 | } | ||
451 | return 1; | ||
452 | } | ||
453 | LCRYPTO_ALIAS(OCSP_request_verify); | ||
454 | |||
455 | static int | ||
456 | ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, X509_NAME *nm, | ||
457 | STACK_OF(X509) *certs, X509_STORE *st, unsigned long flags) | ||
458 | { | ||
459 | X509 *signer; | ||
460 | |||
461 | if (!(flags & OCSP_NOINTERN)) { | ||
462 | signer = X509_find_by_subject(req->optionalSignature->certs, nm); | ||
463 | if (signer) { | ||
464 | *psigner = signer; | ||
465 | return 1; | ||
466 | } | ||
467 | } | ||
468 | |||
469 | signer = X509_find_by_subject(certs, nm); | ||
470 | if (signer) { | ||
471 | *psigner = signer; | ||
472 | return 2; | ||
473 | } | ||
474 | return 0; | ||
475 | } | ||