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