1*0Sstevel@tonic-gate /* ocsp_vfy.c */
2*0Sstevel@tonic-gate /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3*0Sstevel@tonic-gate * project 2000.
4*0Sstevel@tonic-gate */
5*0Sstevel@tonic-gate /* ====================================================================
6*0Sstevel@tonic-gate * Copyright (c) 2000-2004 The OpenSSL Project. All rights reserved.
7*0Sstevel@tonic-gate *
8*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
9*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions
10*0Sstevel@tonic-gate * are met:
11*0Sstevel@tonic-gate *
12*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright
13*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
14*0Sstevel@tonic-gate *
15*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
16*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in
17*0Sstevel@tonic-gate * the documentation and/or other materials provided with the
18*0Sstevel@tonic-gate * distribution.
19*0Sstevel@tonic-gate *
20*0Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this
21*0Sstevel@tonic-gate * software must display the following acknowledgment:
22*0Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project
23*0Sstevel@tonic-gate * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24*0Sstevel@tonic-gate *
25*0Sstevel@tonic-gate * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26*0Sstevel@tonic-gate * endorse or promote products derived from this software without
27*0Sstevel@tonic-gate * prior written permission. For written permission, please contact
28*0Sstevel@tonic-gate * licensing@OpenSSL.org.
29*0Sstevel@tonic-gate *
30*0Sstevel@tonic-gate * 5. Products derived from this software may not be called "OpenSSL"
31*0Sstevel@tonic-gate * nor may "OpenSSL" appear in their names without prior written
32*0Sstevel@tonic-gate * permission of the OpenSSL Project.
33*0Sstevel@tonic-gate *
34*0Sstevel@tonic-gate * 6. Redistributions of any form whatsoever must retain the following
35*0Sstevel@tonic-gate * acknowledgment:
36*0Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project
37*0Sstevel@tonic-gate * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38*0Sstevel@tonic-gate *
39*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40*0Sstevel@tonic-gate * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41*0Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42*0Sstevel@tonic-gate * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43*0Sstevel@tonic-gate * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44*0Sstevel@tonic-gate * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45*0Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46*0Sstevel@tonic-gate * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47*0Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48*0Sstevel@tonic-gate * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49*0Sstevel@tonic-gate * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50*0Sstevel@tonic-gate * OF THE POSSIBILITY OF SUCH DAMAGE.
51*0Sstevel@tonic-gate * ====================================================================
52*0Sstevel@tonic-gate *
53*0Sstevel@tonic-gate * This product includes cryptographic software written by Eric Young
54*0Sstevel@tonic-gate * (eay@cryptsoft.com). This product includes software written by Tim
55*0Sstevel@tonic-gate * Hudson (tjh@cryptsoft.com).
56*0Sstevel@tonic-gate *
57*0Sstevel@tonic-gate */
58*0Sstevel@tonic-gate
59*0Sstevel@tonic-gate #include <openssl/ocsp.h>
60*0Sstevel@tonic-gate #include <openssl/err.h>
61*0Sstevel@tonic-gate #include <string.h>
62*0Sstevel@tonic-gate
63*0Sstevel@tonic-gate static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
64*0Sstevel@tonic-gate X509_STORE *st, unsigned long flags);
65*0Sstevel@tonic-gate static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id);
66*0Sstevel@tonic-gate static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, unsigned long flags);
67*0Sstevel@tonic-gate static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret);
68*0Sstevel@tonic-gate static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, STACK_OF(OCSP_SINGLERESP) *sresp);
69*0Sstevel@tonic-gate static int ocsp_check_delegated(X509 *x, int flags);
70*0Sstevel@tonic-gate static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, X509_NAME *nm, STACK_OF(X509) *certs,
71*0Sstevel@tonic-gate X509_STORE *st, unsigned long flags);
72*0Sstevel@tonic-gate
73*0Sstevel@tonic-gate /* Verify a basic response message */
74*0Sstevel@tonic-gate
OCSP_basic_verify(OCSP_BASICRESP * bs,STACK_OF (X509)* certs,X509_STORE * st,unsigned long flags)75*0Sstevel@tonic-gate int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
76*0Sstevel@tonic-gate X509_STORE *st, unsigned long flags)
77*0Sstevel@tonic-gate {
78*0Sstevel@tonic-gate X509 *signer, *x;
79*0Sstevel@tonic-gate STACK_OF(X509) *chain = NULL;
80*0Sstevel@tonic-gate X509_STORE_CTX ctx;
81*0Sstevel@tonic-gate int i, ret = 0;
82*0Sstevel@tonic-gate ret = ocsp_find_signer(&signer, bs, certs, st, flags);
83*0Sstevel@tonic-gate if (!ret)
84*0Sstevel@tonic-gate {
85*0Sstevel@tonic-gate OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
86*0Sstevel@tonic-gate goto end;
87*0Sstevel@tonic-gate }
88*0Sstevel@tonic-gate if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
89*0Sstevel@tonic-gate flags |= OCSP_NOVERIFY;
90*0Sstevel@tonic-gate if (!(flags & OCSP_NOSIGS))
91*0Sstevel@tonic-gate {
92*0Sstevel@tonic-gate EVP_PKEY *skey;
93*0Sstevel@tonic-gate skey = X509_get_pubkey(signer);
94*0Sstevel@tonic-gate ret = OCSP_BASICRESP_verify(bs, skey, 0);
95*0Sstevel@tonic-gate EVP_PKEY_free(skey);
96*0Sstevel@tonic-gate if(ret <= 0)
97*0Sstevel@tonic-gate {
98*0Sstevel@tonic-gate OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNATURE_FAILURE);
99*0Sstevel@tonic-gate goto end;
100*0Sstevel@tonic-gate }
101*0Sstevel@tonic-gate }
102*0Sstevel@tonic-gate if (!(flags & OCSP_NOVERIFY))
103*0Sstevel@tonic-gate {
104*0Sstevel@tonic-gate int init_res;
105*0Sstevel@tonic-gate if(flags & OCSP_NOCHAIN)
106*0Sstevel@tonic-gate init_res = X509_STORE_CTX_init(&ctx, st, signer, NULL);
107*0Sstevel@tonic-gate else
108*0Sstevel@tonic-gate init_res = X509_STORE_CTX_init(&ctx, st, signer, bs->certs);
109*0Sstevel@tonic-gate if(!init_res)
110*0Sstevel@tonic-gate {
111*0Sstevel@tonic-gate OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,ERR_R_X509_LIB);
112*0Sstevel@tonic-gate goto end;
113*0Sstevel@tonic-gate }
114*0Sstevel@tonic-gate
115*0Sstevel@tonic-gate X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER);
116*0Sstevel@tonic-gate ret = X509_verify_cert(&ctx);
117*0Sstevel@tonic-gate chain = X509_STORE_CTX_get1_chain(&ctx);
118*0Sstevel@tonic-gate X509_STORE_CTX_cleanup(&ctx);
119*0Sstevel@tonic-gate if (ret <= 0)
120*0Sstevel@tonic-gate {
121*0Sstevel@tonic-gate i = X509_STORE_CTX_get_error(&ctx);
122*0Sstevel@tonic-gate OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,OCSP_R_CERTIFICATE_VERIFY_ERROR);
123*0Sstevel@tonic-gate ERR_add_error_data(2, "Verify error:",
124*0Sstevel@tonic-gate X509_verify_cert_error_string(i));
125*0Sstevel@tonic-gate goto end;
126*0Sstevel@tonic-gate }
127*0Sstevel@tonic-gate if(flags & OCSP_NOCHECKS)
128*0Sstevel@tonic-gate {
129*0Sstevel@tonic-gate ret = 1;
130*0Sstevel@tonic-gate goto end;
131*0Sstevel@tonic-gate }
132*0Sstevel@tonic-gate /* At this point we have a valid certificate chain
133*0Sstevel@tonic-gate * need to verify it against the OCSP issuer criteria.
134*0Sstevel@tonic-gate */
135*0Sstevel@tonic-gate ret = ocsp_check_issuer(bs, chain, flags);
136*0Sstevel@tonic-gate
137*0Sstevel@tonic-gate /* If fatal error or valid match then finish */
138*0Sstevel@tonic-gate if (ret != 0) goto end;
139*0Sstevel@tonic-gate
140*0Sstevel@tonic-gate /* Easy case: explicitly trusted. Get root CA and
141*0Sstevel@tonic-gate * check for explicit trust
142*0Sstevel@tonic-gate */
143*0Sstevel@tonic-gate if(flags & OCSP_NOEXPLICIT) goto end;
144*0Sstevel@tonic-gate
145*0Sstevel@tonic-gate x = sk_X509_value(chain, sk_X509_num(chain) - 1);
146*0Sstevel@tonic-gate if(X509_check_trust(x, NID_OCSP_sign, 0) != X509_TRUST_TRUSTED)
147*0Sstevel@tonic-gate {
148*0Sstevel@tonic-gate OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,OCSP_R_ROOT_CA_NOT_TRUSTED);
149*0Sstevel@tonic-gate goto end;
150*0Sstevel@tonic-gate }
151*0Sstevel@tonic-gate ret = 1;
152*0Sstevel@tonic-gate }
153*0Sstevel@tonic-gate
154*0Sstevel@tonic-gate
155*0Sstevel@tonic-gate
156*0Sstevel@tonic-gate end:
157*0Sstevel@tonic-gate if(chain) sk_X509_pop_free(chain, X509_free);
158*0Sstevel@tonic-gate return ret;
159*0Sstevel@tonic-gate }
160*0Sstevel@tonic-gate
161*0Sstevel@tonic-gate
ocsp_find_signer(X509 ** psigner,OCSP_BASICRESP * bs,STACK_OF (X509)* certs,X509_STORE * st,unsigned long flags)162*0Sstevel@tonic-gate static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
163*0Sstevel@tonic-gate X509_STORE *st, unsigned long flags)
164*0Sstevel@tonic-gate {
165*0Sstevel@tonic-gate X509 *signer;
166*0Sstevel@tonic-gate OCSP_RESPID *rid = bs->tbsResponseData->responderId;
167*0Sstevel@tonic-gate if ((signer = ocsp_find_signer_sk(certs, rid)))
168*0Sstevel@tonic-gate {
169*0Sstevel@tonic-gate *psigner = signer;
170*0Sstevel@tonic-gate return 2;
171*0Sstevel@tonic-gate }
172*0Sstevel@tonic-gate if(!(flags & OCSP_NOINTERN) &&
173*0Sstevel@tonic-gate (signer = ocsp_find_signer_sk(bs->certs, rid)))
174*0Sstevel@tonic-gate {
175*0Sstevel@tonic-gate *psigner = signer;
176*0Sstevel@tonic-gate return 1;
177*0Sstevel@tonic-gate }
178*0Sstevel@tonic-gate /* Maybe lookup from store if by subject name */
179*0Sstevel@tonic-gate
180*0Sstevel@tonic-gate *psigner = NULL;
181*0Sstevel@tonic-gate return 0;
182*0Sstevel@tonic-gate }
183*0Sstevel@tonic-gate
184*0Sstevel@tonic-gate
ocsp_find_signer_sk(STACK_OF (X509)* certs,OCSP_RESPID * id)185*0Sstevel@tonic-gate static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
186*0Sstevel@tonic-gate {
187*0Sstevel@tonic-gate int i;
188*0Sstevel@tonic-gate unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
189*0Sstevel@tonic-gate X509 *x;
190*0Sstevel@tonic-gate
191*0Sstevel@tonic-gate /* Easy if lookup by name */
192*0Sstevel@tonic-gate if (id->type == V_OCSP_RESPID_NAME)
193*0Sstevel@tonic-gate return X509_find_by_subject(certs, id->value.byName);
194*0Sstevel@tonic-gate
195*0Sstevel@tonic-gate /* Lookup by key hash */
196*0Sstevel@tonic-gate
197*0Sstevel@tonic-gate /* If key hash isn't SHA1 length then forget it */
198*0Sstevel@tonic-gate if (id->value.byKey->length != SHA_DIGEST_LENGTH) return NULL;
199*0Sstevel@tonic-gate keyhash = id->value.byKey->data;
200*0Sstevel@tonic-gate /* Calculate hash of each key and compare */
201*0Sstevel@tonic-gate for (i = 0; i < sk_X509_num(certs); i++)
202*0Sstevel@tonic-gate {
203*0Sstevel@tonic-gate x = sk_X509_value(certs, i);
204*0Sstevel@tonic-gate X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL);
205*0Sstevel@tonic-gate if(!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH))
206*0Sstevel@tonic-gate return x;
207*0Sstevel@tonic-gate }
208*0Sstevel@tonic-gate return NULL;
209*0Sstevel@tonic-gate }
210*0Sstevel@tonic-gate
211*0Sstevel@tonic-gate
ocsp_check_issuer(OCSP_BASICRESP * bs,STACK_OF (X509)* chain,unsigned long flags)212*0Sstevel@tonic-gate static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, unsigned long flags)
213*0Sstevel@tonic-gate {
214*0Sstevel@tonic-gate STACK_OF(OCSP_SINGLERESP) *sresp;
215*0Sstevel@tonic-gate X509 *signer, *sca;
216*0Sstevel@tonic-gate OCSP_CERTID *caid = NULL;
217*0Sstevel@tonic-gate int i;
218*0Sstevel@tonic-gate sresp = bs->tbsResponseData->responses;
219*0Sstevel@tonic-gate
220*0Sstevel@tonic-gate if (sk_X509_num(chain) <= 0)
221*0Sstevel@tonic-gate {
222*0Sstevel@tonic-gate OCSPerr(OCSP_F_OCSP_CHECK_ISSUER, OCSP_R_NO_CERTIFICATES_IN_CHAIN);
223*0Sstevel@tonic-gate return -1;
224*0Sstevel@tonic-gate }
225*0Sstevel@tonic-gate
226*0Sstevel@tonic-gate /* See if the issuer IDs match. */
227*0Sstevel@tonic-gate i = ocsp_check_ids(sresp, &caid);
228*0Sstevel@tonic-gate
229*0Sstevel@tonic-gate /* If ID mismatch or other error then return */
230*0Sstevel@tonic-gate if (i <= 0) return i;
231*0Sstevel@tonic-gate
232*0Sstevel@tonic-gate signer = sk_X509_value(chain, 0);
233*0Sstevel@tonic-gate /* Check to see if OCSP responder CA matches request CA */
234*0Sstevel@tonic-gate if (sk_X509_num(chain) > 1)
235*0Sstevel@tonic-gate {
236*0Sstevel@tonic-gate sca = sk_X509_value(chain, 1);
237*0Sstevel@tonic-gate i = ocsp_match_issuerid(sca, caid, sresp);
238*0Sstevel@tonic-gate if (i < 0) return i;
239*0Sstevel@tonic-gate if (i)
240*0Sstevel@tonic-gate {
241*0Sstevel@tonic-gate /* We have a match, if extensions OK then success */
242*0Sstevel@tonic-gate if (ocsp_check_delegated(signer, flags)) return 1;
243*0Sstevel@tonic-gate return 0;
244*0Sstevel@tonic-gate }
245*0Sstevel@tonic-gate }
246*0Sstevel@tonic-gate
247*0Sstevel@tonic-gate /* Otherwise check if OCSP request signed directly by request CA */
248*0Sstevel@tonic-gate return ocsp_match_issuerid(signer, caid, sresp);
249*0Sstevel@tonic-gate }
250*0Sstevel@tonic-gate
251*0Sstevel@tonic-gate
252*0Sstevel@tonic-gate /* Check the issuer certificate IDs for equality. If there is a mismatch with the same
253*0Sstevel@tonic-gate * algorithm then there's no point trying to match any certificates against the issuer.
254*0Sstevel@tonic-gate * If the issuer IDs all match then we just need to check equality against one of them.
255*0Sstevel@tonic-gate */
256*0Sstevel@tonic-gate
ocsp_check_ids(STACK_OF (OCSP_SINGLERESP)* sresp,OCSP_CERTID ** ret)257*0Sstevel@tonic-gate static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret)
258*0Sstevel@tonic-gate {
259*0Sstevel@tonic-gate OCSP_CERTID *tmpid, *cid;
260*0Sstevel@tonic-gate int i, idcount;
261*0Sstevel@tonic-gate
262*0Sstevel@tonic-gate idcount = sk_OCSP_SINGLERESP_num(sresp);
263*0Sstevel@tonic-gate if (idcount <= 0)
264*0Sstevel@tonic-gate {
265*0Sstevel@tonic-gate OCSPerr(OCSP_F_OCSP_CHECK_IDS, OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA);
266*0Sstevel@tonic-gate return -1;
267*0Sstevel@tonic-gate }
268*0Sstevel@tonic-gate
269*0Sstevel@tonic-gate cid = sk_OCSP_SINGLERESP_value(sresp, 0)->certId;
270*0Sstevel@tonic-gate
271*0Sstevel@tonic-gate *ret = NULL;
272*0Sstevel@tonic-gate
273*0Sstevel@tonic-gate for (i = 1; i < idcount; i++)
274*0Sstevel@tonic-gate {
275*0Sstevel@tonic-gate tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId;
276*0Sstevel@tonic-gate /* Check to see if IDs match */
277*0Sstevel@tonic-gate if (OCSP_id_issuer_cmp(cid, tmpid))
278*0Sstevel@tonic-gate {
279*0Sstevel@tonic-gate /* If algoritm mismatch let caller deal with it */
280*0Sstevel@tonic-gate if (OBJ_cmp(tmpid->hashAlgorithm->algorithm,
281*0Sstevel@tonic-gate cid->hashAlgorithm->algorithm))
282*0Sstevel@tonic-gate return 2;
283*0Sstevel@tonic-gate /* Else mismatch */
284*0Sstevel@tonic-gate return 0;
285*0Sstevel@tonic-gate }
286*0Sstevel@tonic-gate }
287*0Sstevel@tonic-gate
288*0Sstevel@tonic-gate /* All IDs match: only need to check one ID */
289*0Sstevel@tonic-gate *ret = cid;
290*0Sstevel@tonic-gate return 1;
291*0Sstevel@tonic-gate }
292*0Sstevel@tonic-gate
293*0Sstevel@tonic-gate
ocsp_match_issuerid(X509 * cert,OCSP_CERTID * cid,STACK_OF (OCSP_SINGLERESP)* sresp)294*0Sstevel@tonic-gate static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid,
295*0Sstevel@tonic-gate STACK_OF(OCSP_SINGLERESP) *sresp)
296*0Sstevel@tonic-gate {
297*0Sstevel@tonic-gate /* If only one ID to match then do it */
298*0Sstevel@tonic-gate if(cid)
299*0Sstevel@tonic-gate {
300*0Sstevel@tonic-gate const EVP_MD *dgst;
301*0Sstevel@tonic-gate X509_NAME *iname;
302*0Sstevel@tonic-gate int mdlen;
303*0Sstevel@tonic-gate unsigned char md[EVP_MAX_MD_SIZE];
304*0Sstevel@tonic-gate if (!(dgst = EVP_get_digestbyobj(cid->hashAlgorithm->algorithm)))
305*0Sstevel@tonic-gate {
306*0Sstevel@tonic-gate OCSPerr(OCSP_F_OCSP_MATCH_ISSUERID, OCSP_R_UNKNOWN_MESSAGE_DIGEST);
307*0Sstevel@tonic-gate return -1;
308*0Sstevel@tonic-gate }
309*0Sstevel@tonic-gate
310*0Sstevel@tonic-gate mdlen = EVP_MD_size(dgst);
311*0Sstevel@tonic-gate if ((cid->issuerNameHash->length != mdlen) ||
312*0Sstevel@tonic-gate (cid->issuerKeyHash->length != mdlen))
313*0Sstevel@tonic-gate return 0;
314*0Sstevel@tonic-gate iname = X509_get_subject_name(cert);
315*0Sstevel@tonic-gate if (!X509_NAME_digest(iname, dgst, md, NULL))
316*0Sstevel@tonic-gate return -1;
317*0Sstevel@tonic-gate if (memcmp(md, cid->issuerNameHash->data, mdlen))
318*0Sstevel@tonic-gate return 0;
319*0Sstevel@tonic-gate X509_pubkey_digest(cert, EVP_sha1(), md, NULL);
320*0Sstevel@tonic-gate if (memcmp(md, cid->issuerKeyHash->data, mdlen))
321*0Sstevel@tonic-gate return 0;
322*0Sstevel@tonic-gate
323*0Sstevel@tonic-gate return 1;
324*0Sstevel@tonic-gate
325*0Sstevel@tonic-gate }
326*0Sstevel@tonic-gate else
327*0Sstevel@tonic-gate {
328*0Sstevel@tonic-gate /* We have to match the whole lot */
329*0Sstevel@tonic-gate int i, ret;
330*0Sstevel@tonic-gate OCSP_CERTID *tmpid;
331*0Sstevel@tonic-gate for (i = 0; i < sk_OCSP_SINGLERESP_num(sresp); i++)
332*0Sstevel@tonic-gate {
333*0Sstevel@tonic-gate tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId;
334*0Sstevel@tonic-gate ret = ocsp_match_issuerid(cert, tmpid, NULL);
335*0Sstevel@tonic-gate if (ret <= 0) return ret;
336*0Sstevel@tonic-gate }
337*0Sstevel@tonic-gate return 1;
338*0Sstevel@tonic-gate }
339*0Sstevel@tonic-gate
340*0Sstevel@tonic-gate }
341*0Sstevel@tonic-gate
ocsp_check_delegated(X509 * x,int flags)342*0Sstevel@tonic-gate static int ocsp_check_delegated(X509 *x, int flags)
343*0Sstevel@tonic-gate {
344*0Sstevel@tonic-gate X509_check_purpose(x, -1, 0);
345*0Sstevel@tonic-gate if ((x->ex_flags & EXFLAG_XKUSAGE) &&
346*0Sstevel@tonic-gate (x->ex_xkusage & XKU_OCSP_SIGN))
347*0Sstevel@tonic-gate return 1;
348*0Sstevel@tonic-gate OCSPerr(OCSP_F_OCSP_CHECK_DELEGATED, OCSP_R_MISSING_OCSPSIGNING_USAGE);
349*0Sstevel@tonic-gate return 0;
350*0Sstevel@tonic-gate }
351*0Sstevel@tonic-gate
352*0Sstevel@tonic-gate /* Verify an OCSP request. This is fortunately much easier than OCSP
353*0Sstevel@tonic-gate * response verify. Just find the signers certificate and verify it
354*0Sstevel@tonic-gate * against a given trust value.
355*0Sstevel@tonic-gate */
356*0Sstevel@tonic-gate
OCSP_request_verify(OCSP_REQUEST * req,STACK_OF (X509)* certs,X509_STORE * store,unsigned long flags)357*0Sstevel@tonic-gate int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store, unsigned long flags)
358*0Sstevel@tonic-gate {
359*0Sstevel@tonic-gate X509 *signer;
360*0Sstevel@tonic-gate X509_NAME *nm;
361*0Sstevel@tonic-gate GENERAL_NAME *gen;
362*0Sstevel@tonic-gate int ret;
363*0Sstevel@tonic-gate X509_STORE_CTX ctx;
364*0Sstevel@tonic-gate if (!req->optionalSignature)
365*0Sstevel@tonic-gate {
366*0Sstevel@tonic-gate OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_REQUEST_NOT_SIGNED);
367*0Sstevel@tonic-gate return 0;
368*0Sstevel@tonic-gate }
369*0Sstevel@tonic-gate gen = req->tbsRequest->requestorName;
370*0Sstevel@tonic-gate if (gen->type != GEN_DIRNAME)
371*0Sstevel@tonic-gate {
372*0Sstevel@tonic-gate OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE);
373*0Sstevel@tonic-gate return 0;
374*0Sstevel@tonic-gate }
375*0Sstevel@tonic-gate nm = gen->d.directoryName;
376*0Sstevel@tonic-gate ret = ocsp_req_find_signer(&signer, req, nm, certs, store, flags);
377*0Sstevel@tonic-gate if (ret <= 0)
378*0Sstevel@tonic-gate {
379*0Sstevel@tonic-gate OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
380*0Sstevel@tonic-gate return 0;
381*0Sstevel@tonic-gate }
382*0Sstevel@tonic-gate if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
383*0Sstevel@tonic-gate flags |= OCSP_NOVERIFY;
384*0Sstevel@tonic-gate if (!(flags & OCSP_NOSIGS))
385*0Sstevel@tonic-gate {
386*0Sstevel@tonic-gate EVP_PKEY *skey;
387*0Sstevel@tonic-gate skey = X509_get_pubkey(signer);
388*0Sstevel@tonic-gate ret = OCSP_REQUEST_verify(req, skey);
389*0Sstevel@tonic-gate EVP_PKEY_free(skey);
390*0Sstevel@tonic-gate if(ret <= 0)
391*0Sstevel@tonic-gate {
392*0Sstevel@tonic-gate OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_SIGNATURE_FAILURE);
393*0Sstevel@tonic-gate return 0;
394*0Sstevel@tonic-gate }
395*0Sstevel@tonic-gate }
396*0Sstevel@tonic-gate if (!(flags & OCSP_NOVERIFY))
397*0Sstevel@tonic-gate {
398*0Sstevel@tonic-gate int init_res;
399*0Sstevel@tonic-gate if(flags & OCSP_NOCHAIN)
400*0Sstevel@tonic-gate init_res = X509_STORE_CTX_init(&ctx, store, signer, NULL);
401*0Sstevel@tonic-gate else
402*0Sstevel@tonic-gate init_res = X509_STORE_CTX_init(&ctx, store, signer,
403*0Sstevel@tonic-gate req->optionalSignature->certs);
404*0Sstevel@tonic-gate if(!init_res)
405*0Sstevel@tonic-gate {
406*0Sstevel@tonic-gate OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY,ERR_R_X509_LIB);
407*0Sstevel@tonic-gate return 0;
408*0Sstevel@tonic-gate }
409*0Sstevel@tonic-gate
410*0Sstevel@tonic-gate X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER);
411*0Sstevel@tonic-gate X509_STORE_CTX_set_trust(&ctx, X509_TRUST_OCSP_REQUEST);
412*0Sstevel@tonic-gate ret = X509_verify_cert(&ctx);
413*0Sstevel@tonic-gate X509_STORE_CTX_cleanup(&ctx);
414*0Sstevel@tonic-gate if (ret <= 0)
415*0Sstevel@tonic-gate {
416*0Sstevel@tonic-gate ret = X509_STORE_CTX_get_error(&ctx);
417*0Sstevel@tonic-gate OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY,OCSP_R_CERTIFICATE_VERIFY_ERROR);
418*0Sstevel@tonic-gate ERR_add_error_data(2, "Verify error:",
419*0Sstevel@tonic-gate X509_verify_cert_error_string(ret));
420*0Sstevel@tonic-gate return 0;
421*0Sstevel@tonic-gate }
422*0Sstevel@tonic-gate }
423*0Sstevel@tonic-gate return 1;
424*0Sstevel@tonic-gate }
425*0Sstevel@tonic-gate
ocsp_req_find_signer(X509 ** psigner,OCSP_REQUEST * req,X509_NAME * nm,STACK_OF (X509)* certs,X509_STORE * st,unsigned long flags)426*0Sstevel@tonic-gate static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, X509_NAME *nm, STACK_OF(X509) *certs,
427*0Sstevel@tonic-gate X509_STORE *st, unsigned long flags)
428*0Sstevel@tonic-gate {
429*0Sstevel@tonic-gate X509 *signer;
430*0Sstevel@tonic-gate if(!(flags & OCSP_NOINTERN))
431*0Sstevel@tonic-gate {
432*0Sstevel@tonic-gate signer = X509_find_by_subject(req->optionalSignature->certs, nm);
433*0Sstevel@tonic-gate *psigner = signer;
434*0Sstevel@tonic-gate return 1;
435*0Sstevel@tonic-gate }
436*0Sstevel@tonic-gate
437*0Sstevel@tonic-gate signer = X509_find_by_subject(certs, nm);
438*0Sstevel@tonic-gate if (signer)
439*0Sstevel@tonic-gate {
440*0Sstevel@tonic-gate *psigner = signer;
441*0Sstevel@tonic-gate return 2;
442*0Sstevel@tonic-gate }
443*0Sstevel@tonic-gate return 0;
444*0Sstevel@tonic-gate }
445