]> git.saurik.com Git - apple/security.git/blob - AppleX509TP/tpCertGroup.cpp
Security-179.tar.gz
[apple/security.git] / AppleX509TP / tpCertGroup.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 /*
20 * tpCertGroup.cpp - Cert group functions (construct, verify)
21 *
22 * Created 10/5/2000 by Doug Mitchell.
23 */
24
25 #include "AppleTPSession.h"
26 #include "certGroupUtils.h"
27 #include "TPCertInfo.h"
28 #include "TPCrlInfo.h"
29 #include "tpPolicies.h"
30 #include "tpdebugging.h"
31 #include "rootCerts.h"
32 #include "tpCrlVerify.h"
33 #include <Security/oidsalg.h>
34 #include <Security/cssmapple.h>
35
36 /*-----------------------------------------------------------------------------
37 * CertGroupConstruct
38 *
39 * Description:
40 * This function returns a pointer to a mallocd CSSM_CERTGROUP which
41 * refers to a mallocd list of raw ordered X.509 certs which verify back as
42 * far as the TP is able to go. The first cert of the returned list is the
43 * subject cert. The TP will attempt to search thru the DBs passed in
44 * DBList in order to complete the chain. The chain is completed when a
45 * self-signed (root) cert is found in the chain. The root cert may be
46 * present in the input CertGroupFrag, or it may have been obtained from
47 * one of the DBs passed in DBList. It is not an error if no root cert is
48 * found.
49 *
50 * The error conditions are:
51 * -- The first cert of CertGroupFrag is an invalid cert. NULL is returned,
52 * err = CSSM_TP_INVALID_CERTIFICATE.
53 * -- The root cert (if found) fails to verify. Valid certgroup is returned,
54 * err = CSSMERR_TP_VERIFICATION_FAILURE.
55 * -- Any cert in the (possibly partially) constructed chain has expired or
56 * isn't valid yet, err = CSSMERR_TP_CERT_EXPIRED or
57 * CSSMERR_TP_CERT_NOT_VALID_YET. A CertGroup is returned.
58 * -- CSSMERR_TP_CERT_EXPIRED and CSSMERR_TP_CERT_NOT_VALID_YET. If one of these
59 * conditions obtains for the first (leaf) cert, the function throws this
60 * error immediately and the outgoing cert group is empty. For subsequent certs,
61 * the temporal validity of a cert is only tested AFTER a cert successfully
62 * meets the cert chaining criteria (subject/issuer match and signature
63 * verify). A cert in a chain with this error is not added to the outgoing
64 * cert group.
65 * -- the usual errors like bad handle or memory failure.
66 *
67 * Parameters:
68 * Two handles - to an open CL and CSP. The CSP must be capable of
69 * dealing with the signature algorithms used by the certs. The CL must be
70 * an X.509-savvy CL.
71 *
72 * CertGroupFrag, an unordered array of raw X.509 certs in the form of a
73 * CSSM_CERTGROUP_PTR. The first cert of this list is the subject cert
74 * which is eventually to be verified. The other certs can be in any order
75 * and may not even have any relevance to the cert chain being constructed.
76 * They may also be invalid certs.
77 *
78 * DBList, a list of DB/DL handles which may contain certs necessary to
79 * complete the desired cert chain. (Not currently implemented.)
80 *
81 *---------------------------------------------------------------------------*/
82
83 /* public version */
84 void AppleTPSession::CertGroupConstruct(CSSM_CL_HANDLE clHand,
85 CSSM_CSP_HANDLE cspHand,
86 const CSSM_DL_DB_LIST &DBList,
87 const void *ConstructParams,
88 const CSSM_CERTGROUP &CertGroupFrag,
89 CSSM_CERTGROUP_PTR &CertGroup)
90 {
91 TPCertGroup outCertGroup(*this, TGO_Caller);
92 TPCertGroup inCertGroup(CertGroupFrag,
93 clHand,
94 cspHand,
95 *this,
96 NULL, // cssmTimeStr
97 true, // firstCertMustBeValid
98 TGO_Group);
99
100 /* set up for disposal of TPCertInfos created by CertGroupConstructPriv */
101 TPCertGroup certsToBeFreed(*this, TGO_Group);
102
103 CSSM_RETURN constructReturn = CSSM_OK;
104 CSSM_BOOL verifiedToRoot; // not used
105 CSSM_BOOL verifiedToAnchor; // not used
106
107 try {
108 CertGroupConstructPriv(clHand,
109 cspHand,
110 inCertGroup,
111 &DBList,
112 NULL, // cssmTimeStr
113 /* no anchors */
114 0, NULL,
115 0, // actionFlags
116 certsToBeFreed,
117 verifiedToRoot,
118 verifiedToAnchor,
119 outCertGroup);
120 }
121 catch(const CssmError &cerr) {
122 constructReturn = cerr.cssmError();
123 /* abort if no certs found */
124 if(outCertGroup.numCerts() == 0) {
125 CssmError::throwMe(constructReturn);
126 }
127 }
128 CertGroup = outCertGroup.buildCssmCertGroup();
129 if(constructReturn) {
130 CssmError::throwMe(constructReturn);
131 }
132 }
133
134
135 /*
136 * Private version of CertGroupConstruct, used by CertGroupConstruct and
137 * CertGroupVerify. Populates a TP-style TPCertGroup for further processing.
138 * This only throws CSSM-style exceptions in the following cases:
139 *
140 * -- input parameter errors
141 * -- the first (leaf) cert is bad (doesn't parse, expired, not valid yet).
142 * -- root found but it doesn't self-verify
143 *
144 * All other cert-related errors simply result in the bad cert being ignored.
145 * Other exceptions are gross system errors like malloc failure.
146 */
147 void AppleTPSession::CertGroupConstructPriv(CSSM_CL_HANDLE clHand,
148 CSSM_CSP_HANDLE cspHand,
149 TPCertGroup &inCertGroup,
150 const CSSM_DL_DB_LIST *DBList, // optional here
151 const char *cssmTimeStr, // optional
152
153 /* trusted anchors, optional */
154 /* FIXME - maybe this should be a TPCertGroup */
155 uint32 numAnchorCerts,
156 const CSSM_DATA *anchorCerts,
157
158 /* currently, only CSSM_TP_ACTION_FETCH_CERT_FROM_NET is
159 * interesting */
160 CSSM_APPLE_TP_ACTION_FLAGS actionFlags,
161 /*
162 * Certs to be freed by caller (i.e., TPCertInfo which we allocate
163 * as a result of using a cert from anchorCerts of dbList) are added
164 * to this group.
165 */
166 TPCertGroup &certsToBeFreed,
167
168 /* returned */
169 CSSM_BOOL &verifiedToRoot, // end of chain self-verifies
170 CSSM_BOOL &verifiedToAnchor, // end of chain in anchors
171 TPCertGroup &outCertGroup) // RETURNED
172 {
173 TPCertInfo *subjectCert; // the one we're working on
174 CSSM_RETURN outErr = CSSM_OK;
175
176 /* this'll be the first subject cert in the main loop */
177 subjectCert = inCertGroup.certAtIndex(0);
178
179 /* Append leaf cert to outCertGroup */
180 outCertGroup.appendCert(subjectCert);
181 subjectCert->isLeaf(true);
182 outCertGroup.setAllUnused();
183
184 outErr = outCertGroup.buildCertGroup(
185 *subjectCert,
186 &inCertGroup,
187 DBList,
188 clHand,
189 cspHand,
190 cssmTimeStr,
191 numAnchorCerts,
192 anchorCerts,
193 certsToBeFreed,
194 NULL, // gatheredCerts - none here
195 CSSM_TRUE, // subjectIsInGroup - enables root check on
196 // subject cert
197 actionFlags,
198 verifiedToRoot,
199 verifiedToAnchor);
200 if(outErr) {
201 CssmError::throwMe(outErr);
202 }
203 }
204 /*-----------------------------------------------------------------------------
205 * CertGroupVerify
206 *
207 * Description:
208 * -- Construct a cert chain using TP_CertGroupConstruct.
209 * -- Attempt to verify that cert chain against one of the known
210 * good certs passed in AnchorCerts.
211 * -- Optionally enforces additional policies (TBD) when verifying the cert chain.
212 * -- Optionally returns the entire cert chain constructed in
213 * TP_CertGroupConstruct and here, all the way to an anchor cert or as
214 * far as we were able to go, in *Evidence.
215 *
216 * Parameters:
217 * Two handles - to an open CL and CSP. The CSP must be capable of
218 * dealing with the signature algorithms used by the certs. The CL must be
219 * an X.509-savvy CL.
220 *
221 * RawCerts, an unordered array of raw certs in the form of a
222 * CSSM_CERTGROUP_PTR. The first cert of this list is the subject cert
223 * which is eventually to be verified. The other certs can be in any order
224 * and may not even have any relevance to the cert chain being constructed.
225 * They may also be invalid certs.
226 *
227 * DBList, a list of DB/DL handles which may contain certs necessary to
228 * complete the desired cert chain. (Currently not implemented.)
229 *
230 * AnchorCerts, a list of known trusted certs.
231 * NumberOfAnchorCerts, size of AnchorCerts array.
232 *
233 * PolicyIdentifiers, Optional policy OID. NULL indicates default
234 * X.509 trust policy.
235 *
236 * Supported Policies:
237 * CSSMOID_APPLE_ISIGN
238 * CSSMOID_APPLE_X509_BASIC
239 *
240 * For both of these, the associated FieldValue must be {0, NULL},
241 *
242 * NumberOfPolicyIdentifiers, size of PolicyIdentifiers array, must be
243 * zero or one.
244 *
245 * All other arguments must be zero/NULL.
246 *
247 * Returns:
248 * CSSM_OK : cert chain verified all the way back to an AnchorCert.
249 * CSSMERR_TP_INVALID_ANCHOR_CERT : In this case, the cert chain
250 * was validated back to a self-signed (root) cert found in either
251 * CertToBeVerified or in one of the DBs in DBList, but that root cert
252 * was *NOT* found in the AnchorCert list.
253 * CSSMERR_TP_NOT_TRUSTED: no root cert was found and no AnchorCert
254 * verified the end of the constructed cert chain.
255 * CSSMERR_TP_VERIFICATION_FAILURE: a root cert was found which does
256 * not self-verify.
257 * CSSMERR_TP_VERIFY_ACTION_FAILED: indicates a failure of the requested
258 * policy action.
259 * CSSMERR_TP_INVALID_CERTIFICATE: indicates a bad leaf cert.
260 * CSSMERR_TP_INVALID_REQUEST_INPUTS : no incoming VerifyContext.
261 * CSSMERR_TP_CERT_EXPIRED and CSSMERR_TP_CERT_NOT_VALID_YET: see comments
262 * for CertGroupConstruct.
263 * CSSMERR_TP_CERTIFICATE_CANT_OPERATE : issuer cert was found with a partial
264 * public key, rendering full verification impossible.
265 * CSSMERR_TP_INVALID_CERT_AUTHORITY : issuer cert was found with a partial
266 * public key and which failed to perform subsequent signature
267 * verification.
268 *---------------------------------------------------------------------------*/
269
270 void AppleTPSession::CertGroupVerify(CSSM_CL_HANDLE clHand,
271 CSSM_CSP_HANDLE cspHand,
272 const CSSM_CERTGROUP &CertGroupToBeVerified,
273 const CSSM_TP_VERIFY_CONTEXT *VerifyContext,
274 CSSM_TP_VERIFY_CONTEXT_RESULT_PTR VerifyContextResult)
275 {
276 CSSM_BOOL verifiedToRoot = CSSM_FALSE;
277 CSSM_BOOL verifiedToAnchor = CSSM_FALSE;
278 CSSM_RETURN constructReturn = CSSM_OK;
279 CSSM_RETURN policyReturn = CSSM_OK;
280 const CSSM_TP_CALLERAUTH_CONTEXT *cred;
281 CSSM_BOOL allowExpired = CSSM_FALSE;
282 CSSM_BOOL allowExpiredRoot = CSSM_FALSE;
283 /* declare volatile as compiler workaround to avoid caching in CR4 */
284 const CSSM_APPLE_TP_ACTION_DATA * volatile actionData = NULL;
285 CSSM_TIMESTRING cssmTimeStr;
286 CSSM_APPLE_TP_ACTION_FLAGS actionFlags = 0;
287 CSSM_TP_STOP_ON tpStopOn = 0;
288
289 /* keep track of whether we did policy checking; if not, we do defaults */
290 bool didCertPolicy = false;
291 bool didRevokePolicy = false;
292
293 if(VerifyContextResult) {
294 memset(VerifyContextResult, 0, sizeof(*VerifyContextResult));
295 }
296
297 /* verify input args, skipping the ones checked by CertGroupConstruct */
298 if((VerifyContext == NULL) || (VerifyContext->Cred == NULL)) {
299 /* the spec says that this is optional but we require it */
300 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS);
301 }
302 cred = VerifyContext->Cred;
303
304 /* Optional ActionData affecting all policies */
305 actionData = (CSSM_APPLE_TP_ACTION_DATA * volatile)VerifyContext->ActionData.Data;
306 if(actionData != NULL) {
307 switch(actionData->Version) {
308 case CSSM_APPLE_TP_ACTION_VERSION:
309 if(VerifyContext->ActionData.Length !=
310 sizeof(CSSM_APPLE_TP_ACTION_DATA)) {
311 CssmError::throwMe(CSSMERR_TP_INVALID_ACTION_DATA);
312 }
313 break;
314 /* handle backwards versions here if we ever go beyond version 0 */
315 default:
316 CssmError::throwMe(CSSMERR_TP_INVALID_ACTION_DATA);
317 }
318 actionFlags = actionData->ActionFlags;
319 if(actionFlags & CSSM_TP_ACTION_ALLOW_EXPIRED) {
320 allowExpired = CSSM_TRUE;
321 }
322 if(actionData->ActionFlags & CSSM_TP_ACTION_ALLOW_EXPIRED_ROOT) {
323 allowExpiredRoot = CSSM_TRUE;
324 }
325 }
326
327 /* optional, may be NULL */
328 cssmTimeStr = cred->VerifyTime;
329
330 tpStopOn = cred->VerificationAbortOn;
331 switch(tpStopOn) {
332 /* the only two we support */
333 case CSSM_TP_STOP_ON_NONE:
334 case CSSM_TP_STOP_ON_FIRST_FAIL:
335 break;
336 /* default maps to stop on first fail */
337 case CSSM_TP_STOP_ON_POLICY:
338 tpStopOn = CSSM_TP_STOP_ON_FIRST_FAIL;
339 break;
340 default:
341 CssmError::throwMe(CSSMERR_TP_INVALID_STOP_ON_POLICY);
342 }
343
344 /* now the args we can't deal with */
345 if(cred->CallerCredentials != NULL) {
346 CssmError::throwMe(CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER);
347 }
348 /* ...any others? */
349
350 /* get verified (possibly partial) outCertGroup - error is fatal */
351 /* BUT: we still return partial evidence if asked to...from now on. */
352 TPCertGroup outCertGroup(*this,
353 TGO_Caller); // certs are owned by inCertGroup
354 TPCertGroup inCertGroup(CertGroupToBeVerified, clHand, cspHand, *this,
355 cssmTimeStr, // optional 'this' time
356 true, // firstCertMustBeValid
357 TGO_Group);
358
359 /* set up for disposal of TPCertInfos created by CertGroupConstructPriv */
360 TPCertGroup certsToBeFreed(*this, TGO_Group);
361
362 try {
363 CertGroupConstructPriv(
364 clHand,
365 cspHand,
366 inCertGroup,
367 cred->DBList,
368 cssmTimeStr,
369 cred->NumberOfAnchorCerts,
370 cred->AnchorCerts,
371 actionFlags,
372 certsToBeFreed,
373 verifiedToRoot,
374 verifiedToAnchor,
375 outCertGroup);
376 }
377 catch(const CssmError &cerr) {
378 constructReturn = cerr.cssmError();
379 /* abort if no certs found */
380 if(outCertGroup.numCerts() == 0) {
381 CssmError::throwMe(constructReturn);
382 }
383 /* else press on, collecting as much info as we can */
384 }
385 /* others are way fatal */
386 assert(outCertGroup.numCerts() >= 1);
387
388 /* Infer interim status from return values */
389 if((constructReturn != CSSMERR_TP_CERTIFICATE_CANT_OPERATE) &&
390 (constructReturn != CSSMERR_TP_INVALID_CERT_AUTHORITY)) {
391 /* these returns do not get overridden */
392 if(verifiedToAnchor) {
393 /* full success; anchor doesn't have to be root */
394 constructReturn = CSSM_OK;
395 }
396 else if(verifiedToRoot) {
397 /* verified to root which is not an anchor */
398 constructReturn = CSSMERR_TP_INVALID_ANCHOR_CERT;
399 }
400 else {
401 /* partial chain, no root, not verifiable by anchor */
402 constructReturn = CSSMERR_TP_NOT_TRUSTED;
403 }
404 }
405
406 /*
407 * CSSMERR_TP_NOT_TRUSTED and CSSMERR_TP_INVALID_ANCHOR_CERT
408 * are both special cases which can result in full success
409 * when CSSM_TP_USE_INTERNAL_ROOT_CERTS is enabled.
410 */
411 #if TP_ROOT_CERT_ENABLE
412 if(actionFlags & CSSM_TP_USE_INTERNAL_ROOT_CERTS) {
413 // The secret "enable root cert check" flag
414
415 TPCertInfo *lastCert = outCertGroup.lastCert();
416 if(constructReturn == CSSMERR_TP_NOT_TRUSTED) {
417 /*
418 * See if last (non-root) cert can be verified by
419 * an embedded root */
420 assert(lastCert != NULL);
421 CSSM_BOOL brtn = tp_verifyWithKnownRoots(clHand,
422 cspHand,
423 lastCert);
424 if(brtn) {
425 /* success with no incoming root, actually common (successful) case */
426 constructReturn = CSSM_OK;
427 }
428 }
429 else if(constructReturn == CSSMERR_TP_INVALID_ANCHOR_CERT) {
430 /* is the end cert the same as one of our trusted roots? */
431 assert(lastCert != NULL);
432 bool brtn = tp_isKnownRootCert(lastCert, clHand);
433 if(brtn) {
434 constructReturn = CSSM_OK;
435 }
436 }
437 }
438 #endif /* TP_ROOT_CERT_ENABLE */
439
440 /*
441 * Parameters passed to tp_policyVerify() and which vary per policy
442 * in the loop below
443 */
444 TPPolicy tpPolicy;
445 const CSSM_APPLE_TP_SSL_OPTIONS *sslOpts;
446 CSSM_RETURN thisPolicyRtn = CSSM_OK; // returned from tp_policyVerify()
447
448 /* common CRL verify parameters */
449 TPCrlGroup *crlGroup = NULL;
450 try {
451 crlGroup = new TPCrlGroup(&VerifyContext->Crls,
452 clHand, cspHand,
453 *this, // alloc
454 cssmTimeStr,
455 TGO_Group);
456 }
457 catch(const CssmError &cerr) {
458 CSSM_RETURN cr = cerr.cssmError();
459 /* I don't see a straightforward way to report this error,
460 * other than adding it to the leaf cert's status... */
461 outCertGroup.certAtIndex(0)->addStatusCode(cr);
462 tpDebug("CertGroupVerify: error constructing CrlGroup; continuing\n");
463 }
464 /* others are way fatal */
465
466 TPCrlVerifyContext crlVfyContext(*this,
467 clHand,
468 cspHand,
469 cssmTimeStr,
470 cred->NumberOfAnchorCerts,
471 cred->AnchorCerts,
472 &inCertGroup,
473 crlGroup,
474 /*
475 * This may consist of certs gathered from the net (which is the purpose
476 * of this argument) and from DLDBs (a side-effect optimization).
477 */
478 &certsToBeFreed,
479 cred->DBList,
480 kCrlNone, // policy, varies per policy
481 actionFlags,
482 0); // crlOptFlags, varies per policy
483
484 /* true if we're to execute tp_policyVerify at end of loop */
485 bool doPolicyVerify;
486
487 /* grind thru each policy */
488 for(uint32 polDex=0; polDex<cred->Policy.NumberOfPolicyIds; polDex++) {
489 if(cred->Policy.PolicyIds == NULL) {
490 policyReturn = CSSMERR_TP_INVALID_POLICY_IDENTIFIERS;
491 break;
492 }
493 CSSM_FIELD_PTR policyId = &cred->Policy.PolicyIds[polDex];
494 const CSSM_DATA *fieldVal = &policyId->FieldValue;
495 const CSSM_OID *oid = &policyId->FieldOid;
496 thisPolicyRtn = CSSM_OK;
497 doPolicyVerify = false;
498 sslOpts = NULL;
499
500 /* first the basic cert policies */
501 if(tpCompareOids(oid, &CSSMOID_APPLE_TP_SSL)) {
502 tpPolicy = kTP_SSL;
503 doPolicyVerify = true;
504 /* and do the tp_policyVerify() call below */
505 }
506
507 else if(tpCompareOids(oid, &CSSMOID_APPLE_X509_BASIC)) {
508 /* no options */
509 if(fieldVal->Data != NULL) {
510 policyReturn = CSSMERR_TP_INVALID_POLICY_IDENTIFIERS;
511 break;
512 }
513 tpPolicy = kTPx509Basic;
514 doPolicyVerify = true;
515 }
516
517 else if(tpCompareOids(oid, &CSSMOID_APPLE_TP_SMIME)) {
518 tpPolicy = kTP_SMIME;
519 doPolicyVerify = true;
520 }
521
522 else if(tpCompareOids(oid, &CSSMOID_APPLE_TP_EAP)) {
523 /* treated here exactly the same as SSL */
524 tpPolicy = kTP_SSL;
525 doPolicyVerify = true;
526 }
527
528 else if(tpCompareOids(oid, &CSSMOID_APPLE_ISIGN)) {
529 /* no options */
530 if(fieldVal->Data != NULL) {
531 policyReturn = CSSMERR_TP_INVALID_POLICY_IDENTIFIERS;
532 break;
533 }
534 tpPolicy = kTPiSign;
535 doPolicyVerify = true;
536 }
537
538 /* now revocation policies */
539 else if(tpCompareOids(oid, &CSSMOID_APPLE_TP_REVOCATION_CRL)) {
540 /* CRL-specific options */
541 const CSSM_APPLE_TP_CRL_OPTIONS *crlOpts;
542 crlOpts = (CSSM_APPLE_TP_CRL_OPTIONS *)fieldVal->Data;
543 thisPolicyRtn = CSSM_OK;
544 if(crlOpts != NULL) {
545 switch(crlOpts->Version) {
546 case CSSM_APPLE_TP_CRL_OPTS_VERSION:
547 if(fieldVal->Length !=
548 sizeof(CSSM_APPLE_TP_CRL_OPTIONS)) {
549 thisPolicyRtn =
550 CSSMERR_TP_INVALID_POLICY_IDENTIFIERS;
551 break;
552 }
553 break;
554 /* handle backwards compatibility here if necessary */
555 default:
556 thisPolicyRtn = CSSMERR_TP_INVALID_POLICY_IDENTIFIERS;
557 break;
558 }
559 if(thisPolicyRtn != CSSM_OK) {
560 policyReturn = thisPolicyRtn;
561 break;
562 }
563 }
564 crlVfyContext.policy = kCrlBasic;
565 crlVfyContext.crlOpts = crlOpts;
566
567 thisPolicyRtn = tpVerifyCertGroupWithCrls(outCertGroup,
568 crlVfyContext);
569 didRevokePolicy = true;
570 }
571 /* etc. - add more policies here */
572 else {
573 /* unknown TP policy OID */
574 policyReturn = CSSMERR_TP_INVALID_POLICY_IDENTIFIERS;
575 break;
576 }
577
578 /* common tp_policyVerify call */
579 if(doPolicyVerify) {
580 thisPolicyRtn = tp_policyVerify(tpPolicy,
581 *this,
582 clHand,
583 cspHand,
584 &outCertGroup,
585 verifiedToRoot,
586 actionFlags,
587 fieldVal,
588 cred->Policy.PolicyControl); // not currently used
589 didCertPolicy = true;
590 }
591
592 if(thisPolicyRtn) {
593 /* Policy error. First remember the error if it's the first policy
594 * error we'veƊseen. */
595 if(policyReturn == CSSM_OK) {
596 policyReturn = thisPolicyRtn;
597 }
598 /* Keep going? */
599 if(tpStopOn == CSSM_TP_STOP_ON_FIRST_FAIL) {
600 /* Nope; we're done with policy evaluation */
601 break;
602 }
603 }
604 } /* for each policy */
605
606 /*
607 * Upon completion of the above loop, perform default policy ops if
608 * appropriate.
609 */
610 if((policyReturn == CSSM_OK) || (tpStopOn == CSSM_TP_STOP_ON_NONE)) {
611 if(!didCertPolicy) {
612 policyReturn = tp_policyVerify(kTPDefault,
613 *this,
614 clHand,
615 cspHand,
616 &outCertGroup,
617 verifiedToRoot,
618 actionFlags,
619 NULL, // policyFieldData
620 cred->Policy.PolicyControl); // not currently used
621 }
622 if( !didRevokePolicy && // no revoke policy yet
623 ( (policyReturn == CSSM_OK || // default cert policy OK
624 (tpStopOn == CSSM_TP_STOP_ON_NONE)) // keep going anyway
625 )
626 ) {
627
628 crlVfyContext.policy = TP_CRL_POLICY_DEFAULT;
629 crlVfyContext.crlOpts = NULL;
630 CSSM_RETURN thisPolicyRtn = tpVerifyCertGroupWithCrls(outCertGroup,
631 crlVfyContext);
632 if((thisPolicyRtn != CSSM_OK) && (policyReturn == CSSM_OK)) {
633 policyReturn = thisPolicyRtn;
634 }
635
636 }
637 } /* default policy opts */
638
639 delete crlGroup;
640
641 /* return evidence - i.e., constructed chain - if asked to */
642 if(VerifyContextResult != NULL) {
643 /*
644 * VerifyContextResult->Evidence[0] : CSSM_TP_APPLE_EVIDENCE_HEADER
645 * VerifyContextResult->Evidence[1] : CSSM_CERTGROUP
646 * VerifyContextResult->Evidence[2] : CSSM_TP_APPLE_EVIDENCE_INFO
647 */
648 VerifyContextResult->NumberOfEvidences = 3;
649 VerifyContextResult->Evidence =
650 (CSSM_EVIDENCE_PTR)calloc(3, sizeof(CSSM_EVIDENCE));
651
652 CSSM_TP_APPLE_EVIDENCE_HEADER *hdr =
653 (CSSM_TP_APPLE_EVIDENCE_HEADER *)malloc(
654 sizeof(CSSM_TP_APPLE_EVIDENCE_HEADER));
655 hdr->Version = CSSM_TP_APPLE_EVIDENCE_VERSION;
656 CSSM_EVIDENCE_PTR ev = &VerifyContextResult->Evidence[0];
657 ev->EvidenceForm = CSSM_EVIDENCE_FORM_APPLE_HEADER;
658 ev->Evidence = hdr;
659
660 ev = &VerifyContextResult->Evidence[1];
661 ev->EvidenceForm = CSSM_EVIDENCE_FORM_APPLE_CERTGROUP;
662 ev->Evidence = outCertGroup.buildCssmCertGroup();
663
664 ev = &VerifyContextResult->Evidence[2];
665 ev->EvidenceForm = CSSM_EVIDENCE_FORM_APPLE_CERT_INFO;
666 ev->Evidence = outCertGroup.buildCssmEvidenceInfo();
667
668 }
669 CSSM_RETURN outErr = outCertGroup.getReturnCode(constructReturn,
670 allowExpired, allowExpiredRoot, policyReturn);
671
672 if(outErr) {
673 CssmError::throwMe(outErr);
674 }
675 }
676
677