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