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 /* declare volatile as compiler workaround to avoid caching in CR4 */
426 const CSSM_APPLE_TP_ACTION_DATA
* volatile actionData
= NULL
;
427 const CSSM_APPLE_TP_SSL_OPTIONS
*sslOpts
= NULL
;
428 const CSSM_DATA
*fieldVal
;
429 CSSM_TIMESTRING cssmTimeStr
;
431 /* verify input args, skipping the ones checked by CertGroupConstruct */
432 if((VerifyContext
== NULL
) || (VerifyContext
->Cred
== NULL
)) {
433 /* the spec says that this is optional but we require it */
434 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS
);
436 cred
= VerifyContext
->Cred
;
438 /* Check out requested policies */
439 switch(cred
->Policy
.NumberOfPolicyIds
) {
445 if(cred
->Policy
.PolicyIds
== NULL
) {
446 CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
);
448 fieldVal
= &cred
->Policy
.PolicyIds
->FieldValue
;
449 oid
= &cred
->Policy
.PolicyIds
->FieldOid
;
450 if(tpCompareOids(oid
, &CSSMOID_APPLE_ISIGN
)) {
453 if(fieldVal
->Data
!= NULL
) {
454 CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
);
457 else if(tpCompareOids(oid
, &CSSMOID_APPLE_X509_BASIC
)) {
458 policy
= kTPx509Basic
;
460 if(fieldVal
->Data
!= NULL
) {
461 CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
);
464 else if(tpCompareOids(oid
, &CSSMOID_APPLE_TP_SSL
)) {
466 /* SSL-specific options */
467 sslOpts
= (CSSM_APPLE_TP_SSL_OPTIONS
*)fieldVal
->Data
;
468 if(sslOpts
!= NULL
) {
469 switch(sslOpts
->Version
) {
470 case CSSM_APPLE_TP_SSL_OPTS_VERSION
:
471 if(fieldVal
->Length
!=
472 sizeof(CSSM_APPLE_TP_SSL_OPTIONS
)) {
474 CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
);
477 /* handle backwards compatibility here if necessary */
479 CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
);
485 CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
);
489 /* only zero or one allowed */
490 CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
);
493 /* Optional ActionData affecting all policies */
494 actionData
= (CSSM_APPLE_TP_ACTION_DATA
* volatile)VerifyContext
->ActionData
.Data
;
495 if(actionData
!= NULL
) {
496 switch(actionData
->Version
) {
497 case CSSM_APPLE_TP_ACTION_VERSION
:
498 if(VerifyContext
->ActionData
.Length
!=
499 sizeof(CSSM_APPLE_TP_ACTION_DATA
)) {
500 CssmError::throwMe(CSSMERR_TP_INVALID_ACTION_DATA
);
503 /* handle backwards versions here if we ever go byond version 0 */
505 CssmError::throwMe(CSSMERR_TP_INVALID_ACTION_DATA
);
507 if(actionData
->ActionFlags
& CSSM_TP_ACTION_ALLOW_EXPIRED
) {
508 allowExpired
= CSSM_TRUE
;
512 /* optional, may be NULL */
513 cssmTimeStr
= cred
->VerifyTime
;
515 /* now the args we can't deal with */
516 if(cred
->CallerCredentials
!= NULL
) {
517 CssmError::throwMe(CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER
);
519 /* FIXME - ANY OTHERS? */
521 /* get verified (possibly partial) outCertGroup - error is fatal */
522 /* BUT: we still return partial evidence if asked to...from now on. */
524 CertGroupConstructPriv(
527 *cred
->DBList
, // not optional to Construct!
529 CertGroupToBeVerified
,
534 catch(const CssmError
&cerr
) {
535 constructReturn
= cerr
.cssmError();
536 /* abort if no certs found */
537 if((tpCertGroup
== NULL
) || (tpCertGroup
->numCerts() == 0)) {
538 CssmError::throwMe(constructReturn
);
540 /* else press on, collecting as much info as we can */
542 /* others are way fatal */
543 CASSERT(tpCertGroup
!= NULL
);
544 CASSERT(tpCertGroup
->numCerts() >= 1);
546 /* subsequent errors and returns to out: */
549 * Case 1: last cert in outCertGroup is a root cert. See if
550 * the root cert is in AnchorCerts.
551 * Note that TP_CertGroupConstruct did the actual root
554 lastCert
= tpCertGroup
->lastCert();
555 if(lastCert
->isSelfSigned()) {
556 verifiedToRoot
= CSSM_TRUE
;
558 /* see if that root cert is identical to one of the anchor certs */
559 for(i
=0; i
<cred
->NumberOfAnchorCerts
; i
++) {
560 if(tp_CompareCerts(lastCert
->certData(), &cred
->AnchorCerts
[i
])) {
561 /* one fully successful return */
566 /* verified to a root cert which is not an anchor */
567 constructReturn
= CSSMERR_TP_INVALID_ANCHOR_CERT
;
571 /* try to validate lastCert with anchor certs */
572 for(i
=0; i
<cred
->NumberOfAnchorCerts
; i
++) {
574 certInfo
= new TPCertInfo(&cred
->AnchorCerts
[i
],
579 /* bad anchor cert - ignore it */
582 if(!tpIsSameName(lastCert
->issuerName(), certInfo
->subjectName())) {
583 /* not this anchor */
587 crtn
= tp_VerifyCert(clHand
,
591 CSSM_TRUE
, // check not/before of anchor
595 /* The other normal fully successful return. */
596 if(certInfo
->isSelfSigned()) {
597 verifiedToRoot
= CSSM_TRUE
;
601 * One more thing: add this anchor cert to the Evidence chain
604 tpCertGroup
->appendCert(certInfo
);
605 certInfo
->isAnchor(true);
609 /* shoot - must be memory error */
610 verifiedToRoot
= CSSM_FALSE
;
612 constructReturn
= CSSMERR_TP_MEMORY_ERROR
;
616 #if TP_CERT_CURRENT_CHECK_INLINE
617 case CSSMERR_TP_CERT_NOT_VALID_YET
:
618 case CSSMERR_TP_CERT_EXPIRED
:
619 /* special case - abort immediateley */
621 constructReturn
= crtn
;
623 #endif /* TP_CERT_CURRENT_CHECK_INLINE */
626 /* continue to next anchor */
630 } /* for each anchor */
632 /* partial chain, no root, not verifiable by anchor */
633 constructReturn
= CSSMERR_TP_NOT_TRUSTED
;
635 /* common exit - error or success */
638 * Do further policy verification if appropriate.
640 * SSL: CSSMERR_TP_NOT_TRUSTED and CSSMERR_TP_INVALID_ANCHOR_CERT
641 * are both special cases which can result in full success.
643 #if TP_ROOT_CERT_ENABLE
644 if((policy
== kTP_SSL
) &&
645 (constructReturn
== CSSMERR_TP_NOT_TRUSTED
) &&
646 (actionData
!= NULL
) &&
647 (actionData
->ActionFlags
& 0x80000000)) {// The secret "enable root cert check" flag
648 /* see if last cert can be verified by an embedded SSL root */
649 certInfo
= tpCertGroup
->lastCert();
650 CSSM_BOOL brtn
= tp_verifyWithSslRoots(clHand
,
654 /* SSL success with no incoming root */
655 /* note unknown incoming root (INVALID_ANCHOR_CERT) is handled
656 * below, after tp_policyVerify */
657 constructReturn
= CSSM_OK
;
660 #endif /* TP_ROOT_CERT_ENABLE */
661 if(tpCertGroup
->numCerts() != 0) {
662 /* policy check if we saw even one cert */
663 policyReturn
= tp_policyVerify(policy
,
671 cred
->Policy
.PolicyControl
); // not currently used
672 #if TP_ROOT_CERT_ENABLE
673 if((policyReturn
== CSSM_OK
) &&
674 (constructReturn
== CSSMERR_TP_INVALID_ANCHOR_CERT
) &&
675 (policy
== kTP_SSL
) &&
676 (actionData
!= NULL
) &&
677 (actionData
->ActionFlags
& 0x80000000)) {
678 /* The secret "enable root cert check" flag... */
679 /* SSL - found a good anchor, move to full success */
680 constructReturn
= CSSM_OK
;
685 /* return evidence - i.e., current chain - if asked to */
686 if(VerifyContextResult
!= NULL
) {
688 * VerifyContextResult->Evidence[0] : CSSM_TP_APPLE_EVIDENCE_HEADER
689 * VerifyContextResult->Evidence[1] : CSSM_CERTGROUP
690 * VerifyContextResult->Evidence[2] : CSSM_TP_APPLE_EVIDENCE_INFO
692 VerifyContextResult
->NumberOfEvidences
= 3;
693 VerifyContextResult
->Evidence
=
694 (CSSM_EVIDENCE_PTR
)calloc(3, sizeof(CSSM_EVIDENCE
));
696 CSSM_TP_APPLE_EVIDENCE_HEADER
*hdr
=
697 (CSSM_TP_APPLE_EVIDENCE_HEADER
*)malloc(sizeof(CSSM_TP_APPLE_EVIDENCE_HEADER
));
698 hdr
->Version
= CSSM_TP_APPLE_EVIDENCE_VERSION
;
699 CSSM_EVIDENCE_PTR ev
= &VerifyContextResult
->Evidence
[0];
700 ev
->EvidenceForm
= CSSM_EVIDENCE_FORM_APPLE_HEADER
;
703 ev
= &VerifyContextResult
->Evidence
[1];
704 ev
->EvidenceForm
= CSSM_EVIDENCE_FORM_APPLE_CERTGROUP
;
705 ev
->Evidence
= tpCertGroup
->buildCssmCertGroup();
707 ev
= &VerifyContextResult
->Evidence
[2];
708 ev
->EvidenceForm
= CSSM_EVIDENCE_FORM_APPLE_CERT_INFO
;
709 ev
->Evidence
= tpCertGroup
->buildCssmEvidenceInfo();
712 CSSM_RETURN outErr
= tpCertGroup
->getReturnCode(constructReturn
,
713 allowExpired
, policyReturn
);
715 /* delete (internal use only) TPCertGroup */
718 CssmError::throwMe(outErr
);