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