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