2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
20 * tpCertGroup.cpp - Cert group functions (construct, verify)
22 * Created 10/5/2000 by Doug Mitchell.
25 #include "AppleTPSession.h"
26 #include "certGroupUtils.h"
27 #include "TPCertInfo.h"
28 #include "tpPolicies.h"
29 #include "tpdebugging.h"
30 #include "rootCerts.h"
31 #include <Security/oidsalg.h>
32 #include <Security/cssmapple.h>
34 /*-----------------------------------------------------------------------------
38 * This function returns a pointer to a mallocd CSSM_CERTGROUP which
39 * refers to a mallocd list of raw ordered X.509 certs which verify back as
40 * far as the TP is able to go. The first cert of the returned list is the
41 * subject cert. The TP will attempt to search thru the DBs passed in
42 * DBList in order to complete the chain. The chain is completed when a
43 * self-signed (root) cert is found in the chain. The root cert may be
44 * present in the input CertGroupFrag, or it may have been obtained from
45 * one of the DBs passed in DBList. It is not an error if no root cert is
48 * The error conditions are:
49 * -- The first cert of CertGroupFrag is an invalid cert. NULL is returned,
50 * err = CSSM_TP_INVALID_CERTIFICATE.
51 * -- The root cert (if found) fails to verify. Valid certgroup is returned,
52 * err = CSSMERR_TP_VERIFICATION_FAILURE.
53 * -- Any cert in the (possibly partially) constructed chain has expired or
54 * isn't valid yet, err = CSSMERR_TP_CERT_EXPIRED or
55 * CSSMERR_TP_CERT_NOT_VALID_YET. A CertGroup is returned.
56 * -- CSSMERR_TP_CERT_EXPIRED and CSSMERR_TP_CERT_NOT_VALID_YET. If one of these
57 * conditions obtains for the first (leaf) cert, the function throws this
58 * error immediately and the outgoing cert group is empty. For subsequent certs,
59 * the temporal validity of a cert is only tested AFTER a cert successfully
60 * meets the cert chaining criteria (subject/issuer match and signature
61 * verify). A cert in a chain with this error is not added to the outgoing
63 * -- the usual errors like bad handle or memory failure.
66 * Two handles - to an open CL and CSP. The CSP must be capable of
67 * dealing with the signature algorithms used by the certs. The CL must be
70 * CertGroupFrag, an unordered array of raw X.509 certs in the form of a
71 * CSSM_CERTGROUP_PTR. The first cert of this list is the subject cert
72 * which is eventually to be verified. The other certs can be in any order
73 * and may not even have any relevance to the cert chain being constructed.
74 * They may also be invalid certs.
76 * DBList, a list of DB/DL handles which may contain certs necessary to
77 * complete the desired cert chain. (Not currently implemented.)
79 *---------------------------------------------------------------------------*/
82 void AppleTPSession::CertGroupConstruct(CSSM_CL_HANDLE clHand
,
83 CSSM_CSP_HANDLE cspHand
,
84 const CSSM_DL_DB_LIST
&DBList
,
85 const void *ConstructParams
,
86 const CSSM_CERTGROUP
&CertGroupFrag
,
87 CSSM_CERTGROUP_PTR
&CertGroup
)
89 TPCertGroup
*tpCertGroup
;
90 CertGroupConstructPriv(clHand
,
95 CSSM_FALSE
, // allowExpired
98 CertGroup
= tpCertGroup
->buildCssmCertGroup();
104 * Private version of CertGroupConstruct, used by CertGroupConstruct and
105 * CertGroupVerify. Returns a TP-style TPCertGroup for further processing.
106 * This only throws CSSM-style exceptions in the following cases:
108 * -- input parameter errors
109 * -- the first (leaf) cert is bad (doesn't parse, expired, not valid yet).
111 * All other cert-related errors simply result in the bad cert being ignored.
112 * Other exceptions are gross system errors like malloc failure.
114 void AppleTPSession::CertGroupConstructPriv(CSSM_CL_HANDLE clHand
,
115 CSSM_CSP_HANDLE cspHand
,
116 const CSSM_DL_DB_LIST
&DBList
,
117 const void *ConstructParams
,
118 const CSSM_CERTGROUP
&CertGroupFrag
,
119 CSSM_BOOL allowExpired
,
120 const char *cssmTimeStr
, // May be NULL
121 TPCertGroup
*&CertGroup
)
123 TPCertGroup
*inCertGroup
; // unordered input certs
124 TPCertGroup
*outCertGroup
; // ordered, verified output certs
127 * subjectCert refers to the cert we're currently trying to verify. It's either
128 * an element in inCertGroup (if we're verifying a cert from the incoming
129 * CertGroupFrag) or dbSubject (if we're verifying a cert which came from a DB).
131 * Similarly, issuerCert, when non-NULL, points to a cert which has just
132 * been located as a verifiable issuer of subjectCert. It points to either
133 * an element in inCertGroup or to dbIssuer.
135 TPCertInfo
*subjectCert
; // the one we're working on
136 TPCertInfo
*issuerCert
= NULL
; // verified as next one in chain
137 TPCertInfo
*certInfo
; // working cert
138 unsigned certDex
; // index into certInfo
140 CSSM_RETURN outErr
= CSSM_OK
;
142 /* verify input args */
143 if(cspHand
== CSSM_INVALID_HANDLE
) {
144 CssmError::throwMe(CSSMERR_TP_INVALID_CSP_HANDLE
);
146 if(clHand
== CSSM_INVALID_HANDLE
) {
147 CssmError::throwMe(CSSMERR_TP_INVALID_CL_HANDLE
);
149 if( (CertGroupFrag
.NumCerts
== 0) || // list is empty
150 (CertGroupFrag
.CertGroupType
!= CSSM_CERTGROUP_DATA
) ||
151 (CertGroupFrag
.GroupList
.CertList
[0].Data
== NULL
) || // first cert empty
152 (CertGroupFrag
.GroupList
.CertList
[0].Length
== 0)) { // first cert empty
153 CssmError::throwMe(CSSMERR_CL_INVALID_CERTGROUP_POINTER
);
155 switch(CertGroupFrag
.CertType
) {
156 case CSSM_CERT_X_509v1
:
157 case CSSM_CERT_X_509v2
:
158 case CSSM_CERT_X_509v3
:
161 CssmError::throwMe(CSSMERR_TP_UNKNOWN_FORMAT
);
163 switch(CertGroupFrag
.CertEncoding
) {
164 case CSSM_CERT_ENCODING_BER
:
165 case CSSM_CERT_ENCODING_DER
:
168 CssmError::throwMe(CSSMERR_TP_UNKNOWN_FORMAT
);
172 * Set up incoming and outgoing TPCertGrorups.
174 inCertGroup
= new TPCertGroup(*this, CertGroupFrag
.NumCerts
- 1);
175 outCertGroup
= new TPCertGroup(*this, CertGroupFrag
.NumCerts
);
178 * Parse first (leaf) cert. Note that this cert is special: if it's bad we abort
179 * immediately; otherwise it goes directly into outCertGroup.
182 certInfo
= new TPCertInfo(
183 &CertGroupFrag
.GroupList
.CertList
[0],
188 catch(const CssmError
&cerr
) {
189 outErr
= CSSMERR_TP_INVALID_CERTIFICATE
;
193 /* everything else is way fatal */
197 /* Add to outCertGroup even if it's not current */
198 outCertGroup
->appendCert(certInfo
);
200 #if TP_CERT_CURRENT_CHECK_INLINE
201 /* verify this first one is current */
202 outErr
= certInfo
->isCurrent(allowExpired
);
208 /* this'll be the first subject cert in the main loop */
209 subjectCert
= certInfo
;
212 * Add remaining input certs to inCertGroup. Note that this lets us
213 * skip bad incoming certs right away.
215 for(certDex
=1; certDex
<CertGroupFrag
.NumCerts
; certDex
++) {
217 certInfo
= new TPCertInfo(&CertGroupFrag
.GroupList
.CertList
[certDex
],
222 /* just ignore this cert */
225 certInfo
->index(certDex
);
226 inCertGroup
->appendCert(certInfo
);
231 * On entry, we have two TPCertGroups. InCertGroup contains n-1 certs, where n
232 * is the size of the CertGroupFrag passed to us by the caller. The certs in
233 * inCertGroup are unordered but are known to be parseable, CL-cacheable certs.
234 * OutGroupCert contains one cert, the incoming leaf cert.
236 * The job in this loop is to build an ordered, verified cert chain in
237 * outCertGroup out of certs from inCertGroup and/or DBList. As good certs
238 * are found in inCertGroup, they're removed from that TPCertGroup. On exit
239 * we delete inCertGroup, which deletes all the remaining TPCertInfo's in it.
240 * The constructed outCertGroup is returned to the caller.
243 * -- find a root cert in the chain
245 * -- or no more certs to add to chain.
248 /* top of loop: subjectCert is the cert we're trying to verify. */
250 /* is this a root cert? */
251 if(subjectCert
->isSelfSigned()) {
253 * Verify this alleged root cert. We're at the end of the chain no
254 * matter what happens here.
255 * Note we already validated before/after when this was tested
256 * as issuer (or, if it's the leaf cert, before we entered this loop).
258 outErr
= tp_VerifyCert(clHand
,
262 CSSM_FALSE
, // checkIssuerCurrent
263 CSSM_TRUE
); // allowExpired, don't care
267 /* Search unused incoming certs to find an issuer */
268 for(certDex
=0; certDex
<inCertGroup
->numCerts(); certDex
++) {
269 certInfo
= inCertGroup
->certAtIndex(certDex
);
271 /* potential issuer - names match? */
272 if(tpIsSameName(subjectCert
->issuerName(), certInfo
->subjectName())) {
273 /* yep, do a sig verify with "not before/after" check */
274 crtn
= tp_VerifyCert(clHand
,
282 /* YES! We'll add it to outCertGroup below...*/
283 issuerCert
= certInfo
;
284 inCertGroup
->removeCertAtIndex(certDex
);
286 case CSSMERR_TP_CERT_NOT_VALID_YET
:
287 case CSSMERR_TP_CERT_EXPIRED
:
288 /* special case - abort immediateley (note the cert
289 * sig verify succeeded.) */
290 /*** for now we include this in the evidence ***/
291 outCertGroup
->appendCert(subjectCert
);
295 /* just skip this one and keep looking */
299 } /* searching inCertGroup for issuer */
304 if(issuerCert
== NULL
) {
305 /* Issuer not in incoming cert group. Search DBList. */
306 CSSM_BOOL subjectExpired
= CSSM_FALSE
;
307 issuerCert
= tpFindIssuer(*this,
311 subjectCert
->issuerName(),
316 /* special case - abort immediately */
317 outErr
= subjectExpired
;
320 } /* Issuer not in incoming cert group */
321 #endif /* TP_DL_ENABLE */
323 if(issuerCert
== NULL
) {
324 /* end of search, broken chain */
329 * One way or the other, we've found a cert which verifies subjectCert.
330 * Add the issuer to outCertGroup and make it the new subjectCert for
333 outCertGroup
->appendCert(issuerCert
);
334 subjectCert
= issuerCert
;
340 CertGroup
= outCertGroup
;
342 CssmError::throwMe(outErr
);
345 /*-----------------------------------------------------------------------------
349 * -- Construct a cert chain using TP_CertGroupConstruct.
350 * -- Attempt to verify that cert chain against one of the known
351 * good certs passed in AnchorCerts.
352 * -- Optionally enforces additional policies (TBD) when verifying the cert chain.
353 * -- Optionally returns the entire cert chain constructed in
354 * TP_CertGroupConstruct and here, all the way to an anchor cert or as
355 * far as we were able to go, in *Evidence.
358 * Two handles - to an open CL and CSP. The CSP must be capable of
359 * dealing with the signature algorithms used by the certs. The CL must be
362 * RawCerts, an unordered array of raw certs in the form of a
363 * CSSM_CERTGROUP_PTR. The first cert of this list is the subject cert
364 * which is eventually to be verified. The other certs can be in any order
365 * and may not even have any relevance to the cert chain being constructed.
366 * They may also be invalid certs.
368 * DBList, a list of DB/DL handles which may contain certs necessary to
369 * complete the desired cert chain. (Currently not implemented.)
371 * AnchorCerts, a list of known trusted certs.
372 * NumberOfAnchorCerts, size of AnchorCerts array.
374 * PolicyIdentifiers, Optional policy OID. NULL indicates default
375 * X.509 trust policy.
377 * Supported Policies:
378 * CSSMOID_APPLE_ISIGN
379 * CSSMOID_APPLE_X509_BASIC
381 * For both of these, the associated FieldValue must be {0, NULL},
383 * NumberOfPolicyIdentifiers, size of PolicyIdentifiers array, must be
386 * All other arguments must be zero/NULL.
389 * CSSM_OK : cert chain verified all the way back to an AnchorCert.
390 * CSSMERR_TP_INVALID_ANCHOR_CERT : In this case, the cert chain
391 * was validated back to a self-signed (root) cert found in either
392 * CertToBeVerified or in one of the DBs in DBList, but that root cert
393 * was *NOT* found in the AnchorCert list.
394 * CSSMERR_TP_NOT_TRUSTED: no root cert was found and no AnchorCert
395 * verified the end of the constructed cert chain.
396 * CSSMERR_TP_VERIFICATION_FAILURE: a root cert was found which does
398 * CSSMERR_TP_VERIFY_ACTION_FAILED: indicates a failure of the requested
400 * CSSMERR_TP_INVALID_CERTIFICATE: indicates a bad leaf cert.
401 * CSSMERR_TP_INVALID_REQUEST_INPUTS : no incoming VerifyContext.
402 * CSSMERR_TP_CERT_EXPIRED and CSSMERR_TP_CERT_NOT_VALID_YET: see comments
403 * for CertGroupConstruct.
404 *---------------------------------------------------------------------------*/
406 void AppleTPSession::CertGroupVerify(CSSM_CL_HANDLE clHand
,
407 CSSM_CSP_HANDLE cspHand
,
408 const CSSM_CERTGROUP
&CertGroupToBeVerified
,
409 const CSSM_TP_VERIFY_CONTEXT
*VerifyContext
,
410 CSSM_TP_VERIFY_CONTEXT_RESULT_PTR VerifyContextResult
)
413 TPCertInfo
*lastCert
;
414 CSSM_BOOL verifiedToRoot
= CSSM_FALSE
;
416 CSSM_RETURN constructReturn
= CSSM_OK
;
417 CSSM_RETURN policyReturn
= CSSM_OK
;
419 const CSSM_TP_CALLERAUTH_CONTEXT
*cred
;
420 CSSM_OID_PTR oid
= NULL
;
421 TPCertGroup
*tpCertGroup
= NULL
; // created by
422 // CertGroupConstructPriv
423 TPCertInfo
*certInfo
= NULL
;
424 CSSM_BOOL allowExpired
= CSSM_FALSE
;
425 CSSM_BOOL allowExpiredRoot
= CSSM_FALSE
;
426 /* declare volatile as compiler workaround to avoid caching in CR4 */
427 const CSSM_APPLE_TP_ACTION_DATA
* volatile actionData
= NULL
;
428 const CSSM_APPLE_TP_SSL_OPTIONS
*sslOpts
= NULL
;
429 const CSSM_DATA
*fieldVal
;
430 CSSM_TIMESTRING cssmTimeStr
;
432 /* verify input args, skipping the ones checked by CertGroupConstruct */
433 if((VerifyContext
== NULL
) || (VerifyContext
->Cred
== NULL
)) {
434 /* the spec says that this is optional but we require it */
435 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS
);
437 cred
= VerifyContext
->Cred
;
439 /* Check out requested policies */
440 switch(cred
->Policy
.NumberOfPolicyIds
) {
446 if(cred
->Policy
.PolicyIds
== NULL
) {
447 CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
);
449 fieldVal
= &cred
->Policy
.PolicyIds
->FieldValue
;
450 oid
= &cred
->Policy
.PolicyIds
->FieldOid
;
451 if(tpCompareOids(oid
, &CSSMOID_APPLE_ISIGN
)) {
454 if(fieldVal
->Data
!= NULL
) {
455 CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
);
458 else if(tpCompareOids(oid
, &CSSMOID_APPLE_X509_BASIC
)) {
459 policy
= kTPx509Basic
;
461 if(fieldVal
->Data
!= NULL
) {
462 CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
);
465 else if(tpCompareOids(oid
, &CSSMOID_APPLE_TP_SSL
)) {
467 /* SSL-specific options */
468 sslOpts
= (CSSM_APPLE_TP_SSL_OPTIONS
*)fieldVal
->Data
;
469 if(sslOpts
!= NULL
) {
470 switch(sslOpts
->Version
) {
471 case CSSM_APPLE_TP_SSL_OPTS_VERSION
:
472 if(fieldVal
->Length
!=
473 sizeof(CSSM_APPLE_TP_SSL_OPTIONS
)) {
475 CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
);
478 /* handle backwards compatibility here if necessary */
480 CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
);
486 CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
);
490 /* only zero or one allowed */
491 CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
);
494 /* Optional ActionData affecting all policies */
495 actionData
= (CSSM_APPLE_TP_ACTION_DATA
* volatile)VerifyContext
->ActionData
.Data
;
496 if(actionData
!= NULL
) {
497 switch(actionData
->Version
) {
498 case CSSM_APPLE_TP_ACTION_VERSION
:
499 if(VerifyContext
->ActionData
.Length
!=
500 sizeof(CSSM_APPLE_TP_ACTION_DATA
)) {
501 CssmError::throwMe(CSSMERR_TP_INVALID_ACTION_DATA
);
504 /* handle backwards versions here if we ever go byond version 0 */
506 CssmError::throwMe(CSSMERR_TP_INVALID_ACTION_DATA
);
508 if(actionData
->ActionFlags
& CSSM_TP_ACTION_ALLOW_EXPIRED
) {
509 allowExpired
= CSSM_TRUE
;
511 if(actionData
->ActionFlags
& CSSM_TP_ACTION_ALLOW_EXPIRED_ROOT
) {
512 allowExpiredRoot
= CSSM_TRUE
;
516 /* optional, may be NULL */
517 cssmTimeStr
= cred
->VerifyTime
;
519 /* now the args we can't deal with */
520 if(cred
->CallerCredentials
!= NULL
) {
521 CssmError::throwMe(CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER
);
523 /* FIXME - ANY OTHERS? */
525 /* get verified (possibly partial) outCertGroup - error is fatal */
526 /* BUT: we still return partial evidence if asked to...from now on. */
528 CertGroupConstructPriv(
531 *cred
->DBList
, // not optional to Construct!
533 CertGroupToBeVerified
,
538 catch(const CssmError
&cerr
) {
539 constructReturn
= cerr
.cssmError();
540 /* abort if no certs found */
541 if((tpCertGroup
== NULL
) || (tpCertGroup
->numCerts() == 0)) {
542 CssmError::throwMe(constructReturn
);
544 /* else press on, collecting as much info as we can */
546 /* others are way fatal */
547 CASSERT(tpCertGroup
!= NULL
);
548 CASSERT(tpCertGroup
->numCerts() >= 1);
550 /* subsequent errors and returns to out: */
553 * Case 1: last cert in outCertGroup is a root cert. See if
554 * the root cert is in AnchorCerts.
555 * Note that TP_CertGroupConstruct did the actual root
558 lastCert
= tpCertGroup
->lastCert();
559 if(lastCert
->isSelfSigned()) {
560 verifiedToRoot
= CSSM_TRUE
;
562 /* see if that root cert is identical to one of the anchor certs */
563 for(i
=0; i
<cred
->NumberOfAnchorCerts
; i
++) {
564 if(tp_CompareCerts(lastCert
->certData(), &cred
->AnchorCerts
[i
])) {
565 /* one fully successful return */
570 /* verified to a root cert which is not an anchor */
571 constructReturn
= CSSMERR_TP_INVALID_ANCHOR_CERT
;
575 /* try to validate lastCert with anchor certs */
576 for(i
=0; i
<cred
->NumberOfAnchorCerts
; i
++) {
578 certInfo
= new TPCertInfo(&cred
->AnchorCerts
[i
],
583 /* bad anchor cert - ignore it */
586 if(!tpIsSameName(lastCert
->issuerName(), certInfo
->subjectName())) {
587 /* not this anchor */
591 crtn
= tp_VerifyCert(clHand
,
595 CSSM_TRUE
, // check not/before of anchor
599 /* The other normal fully successful return. */
600 if(certInfo
->isSelfSigned()) {
601 verifiedToRoot
= CSSM_TRUE
;
605 * One more thing: add this anchor cert to the Evidence chain
608 tpCertGroup
->appendCert(certInfo
);
609 certInfo
->isAnchor(true);
613 /* shoot - must be memory error */
614 verifiedToRoot
= CSSM_FALSE
;
616 constructReturn
= CSSMERR_TP_MEMORY_ERROR
;
620 #if TP_CERT_CURRENT_CHECK_INLINE
621 case CSSMERR_TP_CERT_NOT_VALID_YET
:
622 case CSSMERR_TP_CERT_EXPIRED
:
623 /* special case - abort immediateley */
625 constructReturn
= crtn
;
627 #endif /* TP_CERT_CURRENT_CHECK_INLINE */
630 /* continue to next anchor */
634 } /* for each anchor */
636 /* partial chain, no root, not verifiable by anchor */
637 constructReturn
= CSSMERR_TP_NOT_TRUSTED
;
639 /* common exit - error or success */
642 * Do further policy verification if appropriate.
644 * SSL: CSSMERR_TP_NOT_TRUSTED and CSSMERR_TP_INVALID_ANCHOR_CERT
645 * are both special cases which can result in full success.
647 #if TP_ROOT_CERT_ENABLE
648 if((policy
== kTP_SSL
) &&
649 (constructReturn
== CSSMERR_TP_NOT_TRUSTED
) &&
650 (actionData
!= NULL
) &&
651 (actionData
->ActionFlags
& 0x80000000)) {// The secret "enable root cert check" flag
652 /* see if last cert can be verified by an embedded SSL root */
653 certInfo
= tpCertGroup
->lastCert();
654 CSSM_BOOL brtn
= tp_verifyWithSslRoots(clHand
,
658 /* SSL success with no incoming root */
659 /* note unknown incoming root (INVALID_ANCHOR_CERT) is handled
660 * below, after tp_policyVerify */
661 constructReturn
= CSSM_OK
;
664 #endif /* TP_ROOT_CERT_ENABLE */
665 if(tpCertGroup
->numCerts() != 0) {
666 /* policy check if we saw even one cert */
667 policyReturn
= tp_policyVerify(policy
,
675 cred
->Policy
.PolicyControl
); // not currently used
676 #if TP_ROOT_CERT_ENABLE
677 if((policyReturn
== CSSM_OK
) &&
678 (constructReturn
== CSSMERR_TP_INVALID_ANCHOR_CERT
) &&
679 (policy
== kTP_SSL
) &&
680 (actionData
!= NULL
) &&
681 (actionData
->ActionFlags
& 0x80000000)) {
682 /* The secret "enable root cert check" flag... */
683 /* SSL - found a good anchor, move to full success */
684 constructReturn
= CSSM_OK
;
689 /* return evidence - i.e., current chain - if asked to */
690 if(VerifyContextResult
!= NULL
) {
692 * VerifyContextResult->Evidence[0] : CSSM_TP_APPLE_EVIDENCE_HEADER
693 * VerifyContextResult->Evidence[1] : CSSM_CERTGROUP
694 * VerifyContextResult->Evidence[2] : CSSM_TP_APPLE_EVIDENCE_INFO
696 VerifyContextResult
->NumberOfEvidences
= 3;
697 VerifyContextResult
->Evidence
=
698 (CSSM_EVIDENCE_PTR
)calloc(3, sizeof(CSSM_EVIDENCE
));
700 CSSM_TP_APPLE_EVIDENCE_HEADER
*hdr
=
701 (CSSM_TP_APPLE_EVIDENCE_HEADER
*)malloc(sizeof(CSSM_TP_APPLE_EVIDENCE_HEADER
));
702 hdr
->Version
= CSSM_TP_APPLE_EVIDENCE_VERSION
;
703 CSSM_EVIDENCE_PTR ev
= &VerifyContextResult
->Evidence
[0];
704 ev
->EvidenceForm
= CSSM_EVIDENCE_FORM_APPLE_HEADER
;
707 ev
= &VerifyContextResult
->Evidence
[1];
708 ev
->EvidenceForm
= CSSM_EVIDENCE_FORM_APPLE_CERTGROUP
;
709 ev
->Evidence
= tpCertGroup
->buildCssmCertGroup();
711 ev
= &VerifyContextResult
->Evidence
[2];
712 ev
->EvidenceForm
= CSSM_EVIDENCE_FORM_APPLE_CERT_INFO
;
713 ev
->Evidence
= tpCertGroup
->buildCssmEvidenceInfo();
716 CSSM_RETURN outErr
= tpCertGroup
->getReturnCode(constructReturn
,
717 allowExpired
, allowExpiredRoot
, policyReturn
);
719 /* delete (internal use only) TPCertGroup */
722 CssmError::throwMe(outErr
);