2 * Copyright (c) 2000-2001,2011-2014 Apple 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)
23 #include "AppleTPSession.h"
24 #include "certGroupUtils.h"
25 #include "TPCertInfo.h"
26 #include "TPCrlInfo.h"
27 #include "tpPolicies.h"
28 #include "tpdebugging.h"
29 #include "tpCrlVerify.h"
30 #include <Security/oidsalg.h>
31 #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
outCertGroup(*this, TGO_Caller
);
90 TPCertGroup
inCertGroup(CertGroupFrag
,
95 true, // firstCertMustBeValid
98 /* set up for disposal of TPCertInfos created by CertGroupConstructPriv */
99 TPCertGroup
gatheredCerts(*this, TGO_Group
);
101 CSSM_RETURN constructReturn
= CSSM_OK
;
102 CSSM_APPLE_TP_ACTION_FLAGS actionFlags
= 0;
103 CSSM_BOOL verifiedToRoot
; // not used
104 CSSM_BOOL verifiedToAnchor
; // not used
105 CSSM_BOOL verifiedViaTrustSetting
; // not used
108 CertGroupConstructPriv(clHand
,
121 verifiedViaTrustSetting
,
124 catch(const CssmError
&cerr
) {
125 constructReturn
= cerr
.error
;
126 /* abort if no certs found */
127 if(outCertGroup
.numCerts() == 0) {
128 CssmError::throwMe(constructReturn
);
131 CertGroup
= outCertGroup
.buildCssmCertGroup();
132 /* caller of this function never gets evidence... */
133 outCertGroup
.freeDbRecords();
135 if(constructReturn
) {
136 CssmError::throwMe(constructReturn
);
142 * Private version of CertGroupConstruct, used by CertGroupConstruct and
143 * CertGroupVerify. Populates a TP-style TPCertGroup for further processing.
144 * This only throws CSSM-style exceptions in the following cases:
146 * -- input parameter errors
147 * -- the first (leaf) cert is bad (doesn't parse, expired, not valid yet).
148 * -- root found but it doesn't self-verify
150 * All other cert-related errors simply result in the bad cert being ignored.
151 * Other exceptions are gross system errors like malloc failure.
153 void AppleTPSession::CertGroupConstructPriv(CSSM_CL_HANDLE clHand
,
154 CSSM_CSP_HANDLE cspHand
,
155 TPCertGroup
&inCertGroup
,
156 const CSSM_DL_DB_LIST
*DBList
, // optional here
157 const char *cssmTimeStr
, // optional
159 /* trusted anchors, optional */
160 /* FIXME - maybe this should be a TPCertGroup */
161 uint32 numAnchorCerts
,
162 const CSSM_DATA
*anchorCerts
,
164 /* CSSM_TP_ACTION_FETCH_CERT_FROM_NET, CSSM_TP_ACTION_TRUST_SETTINGS */
165 CSSM_APPLE_TP_ACTION_FLAGS actionFlags
,
167 /* optional user trust parameters */
168 const CSSM_OID
*policyOid
,
169 const char *policyStr
,
171 SecTrustSettingsKeyUsage keyUse
,
174 * Certs to be freed by caller (i.e., TPCertInfo which we allocate
175 * as a result of using a cert from anchorCerts or dbList) are added
178 TPCertGroup
&certsToBeFreed
,
181 CSSM_BOOL
&verifiedToRoot
, // end of chain self-verifies
182 CSSM_BOOL
&verifiedToAnchor
, // end of chain in anchors
183 CSSM_BOOL
&verifiedViaTrustSetting
, // chain ends per User Trust setting
184 TPCertGroup
&outCertGroup
) // RETURNED
186 TPCertInfo
*subjectCert
; // the one we're working on
187 CSSM_RETURN outErr
= CSSM_OK
;
189 /* this'll be the first subject cert in the main loop */
190 subjectCert
= inCertGroup
.certAtIndex(0);
192 /* Append leaf cert to outCertGroup */
193 outCertGroup
.appendCert(subjectCert
);
194 subjectCert
->isLeaf(true);
195 subjectCert
->isFromInputCerts(true);
196 outCertGroup
.setAllUnused();
197 subjectCert
->used(true);
199 outErr
= outCertGroup
.buildCertGroup(
209 &certsToBeFreed
, // gatheredCerts to accumulate net/DB fetches
210 CSSM_TRUE
, // subjectIsInGroup - enables root check on
220 verifiedViaTrustSetting
);
222 CssmError::throwMe(outErr
);
227 * Map a policy OID to one of the standard (non-revocation) policies.
228 * Returns true if it's a standard policy.
230 static bool checkPolicyOid(
232 TPPolicy
&tpPolicy
) /* RETURNED */
234 if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_SSL
)) {
238 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_X509_BASIC
)) {
239 tpPolicy
= kTPx509Basic
;
242 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_SMIME
)) {
243 tpPolicy
= kTP_SMIME
;
246 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_EAP
)) {
250 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_SW_UPDATE_SIGNING
)) {
251 /* note: this was CSSMOID_APPLE_TP_CODE_SIGN until 8/15/06 */
252 tpPolicy
= kTP_SWUpdateSign
;
255 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_RESOURCE_SIGN
)) {
256 tpPolicy
= kTP_ResourceSign
;
259 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_IP_SEC
)) {
260 tpPolicy
= kTP_IPSec
;
263 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_ICHAT
)) {
264 tpPolicy
= kTP_iChat
;
267 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_ISIGN
)) {
271 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_PKINIT_CLIENT
)) {
272 tpPolicy
= kTP_PKINIT_Client
;
275 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_PKINIT_SERVER
)) {
276 tpPolicy
= kTP_PKINIT_Server
;
279 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_CODE_SIGNING
)) {
280 tpPolicy
= kTP_CodeSigning
;
283 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_PACKAGE_SIGNING
)) {
284 tpPolicy
= kTP_PackageSigning
;
287 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT
)) {
288 tpPolicy
= kTP_MacAppStoreRec
;
291 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_APPLEID_SHARING
)) {
292 tpPolicy
= kTP_AppleIDSharing
;
295 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_TIMESTAMPING
)) {
296 tpPolicy
= kTP_TimeStamping
;
299 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_PASSBOOK_SIGNING
)) {
300 tpPolicy
= kTP_PassbookSigning
;
303 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_MOBILE_STORE
)) {
304 tpPolicy
= kTP_MobileStore
;
307 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_TEST_MOBILE_STORE
)) {
308 tpPolicy
= kTP_TestMobileStore
;
311 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_ESCROW_SERVICE
)) {
312 tpPolicy
= kTP_EscrowService
;
315 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_PROFILE_SIGNING
)) {
316 tpPolicy
= kTP_ProfileSigning
;
319 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_QA_PROFILE_SIGNING
)) {
320 tpPolicy
= kTP_QAProfileSigning
;
323 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_PCS_ESCROW_SERVICE
)) {
324 tpPolicy
= kTP_PCSEscrowService
;
327 else if(tpCompareOids(&oid
, &CSSMOID_APPLE_TP_PROVISIONING_PROFILE_SIGNING
)) {
328 tpPolicy
= kTP_ProvisioningProfileSigning
;
334 /*-----------------------------------------------------------------------------
338 * -- Construct a cert chain using TP_CertGroupConstruct.
339 * -- Attempt to verify that cert chain against one of the known
340 * good certs passed in AnchorCerts.
341 * -- Optionally enforces additional policies (TBD) when verifying the cert chain.
342 * -- Optionally returns the entire cert chain constructed in
343 * TP_CertGroupConstruct and here, all the way to an anchor cert or as
344 * far as we were able to go, in *Evidence.
347 * Two handles - to an open CL and CSP. The CSP must be capable of
348 * dealing with the signature algorithms used by the certs. The CL must be
351 * RawCerts, an unordered array of raw certs in the form of a
352 * CSSM_CERTGROUP_PTR. The first cert of this list is the subject cert
353 * which is eventually to be verified. The other certs can be in any order
354 * and may not even have any relevance to the cert chain being constructed.
355 * They may also be invalid certs.
357 * DBList, a list of DB/DL handles which may contain certs necessary to
358 * complete the desired cert chain. (Currently not implemented.)
360 * AnchorCerts, a list of known trusted certs.
361 * NumberOfAnchorCerts, size of AnchorCerts array.
363 * PolicyIdentifiers, Optional policy OID. NULL indicates default
364 * X.509 trust policy.
366 * Supported Policies:
367 * CSSMOID_APPLE_ISIGN
368 * CSSMOID_APPLE_X509_BASIC
370 * For both of these, the associated FieldValue must be {0, NULL},
372 * NumberOfPolicyIdentifiers, size of PolicyIdentifiers array, must be
375 * All other arguments must be zero/NULL.
378 * CSSM_OK : cert chain verified all the way back to an AnchorCert.
379 * CSSMERR_TP_INVALID_ANCHOR_CERT : In this case, the cert chain
380 * was validated back to a self-signed (root) cert found in either
381 * CertToBeVerified or in one of the DBs in DBList, but that root cert
382 * was *NOT* found in the AnchorCert list.
383 * CSSMERR_TP_NOT_TRUSTED: no root cert was found and no AnchorCert
384 * verified the end of the constructed cert chain.
385 * CSSMERR_TP_VERIFICATION_FAILURE: a root cert was found which does
387 * CSSMERR_TP_VERIFY_ACTION_FAILED: indicates a failure of the requested
389 * CSSMERR_TP_INVALID_CERTIFICATE: indicates a bad leaf cert.
390 * CSSMERR_TP_INVALID_REQUEST_INPUTS : no incoming VerifyContext.
391 * CSSMERR_TP_CERT_EXPIRED and CSSMERR_TP_CERT_NOT_VALID_YET: see comments
392 * for CertGroupConstruct.
393 * CSSMERR_TP_CERTIFICATE_CANT_OPERATE : issuer cert was found with a partial
394 * public key, rendering full verification impossible.
395 * CSSMERR_TP_INVALID_CERT_AUTHORITY : issuer cert was found with a partial
396 * public key and which failed to perform subsequent signature
398 *---------------------------------------------------------------------------*/
400 void AppleTPSession::CertGroupVerify(CSSM_CL_HANDLE clHand
,
401 CSSM_CSP_HANDLE cspHand
,
402 const CSSM_CERTGROUP
&CertGroupToBeVerified
,
403 const CSSM_TP_VERIFY_CONTEXT
*VerifyContext
,
404 CSSM_TP_VERIFY_CONTEXT_RESULT_PTR VerifyContextResult
)
406 CSSM_BOOL verifiedToRoot
= CSSM_FALSE
;
407 CSSM_BOOL verifiedToAnchor
= CSSM_FALSE
;
408 CSSM_BOOL verifiedViaTrustSetting
= CSSM_FALSE
;
409 CSSM_RETURN constructReturn
= CSSM_OK
;
410 CSSM_RETURN policyReturn
= CSSM_OK
;
411 const CSSM_TP_CALLERAUTH_CONTEXT
*cred
;
412 /* declare volatile as compiler workaround to avoid caching in CR4 */
413 const CSSM_APPLE_TP_ACTION_DATA
* volatile actionData
= NULL
;
414 CSSM_TIMESTRING cssmTimeStr
;
415 CSSM_APPLE_TP_ACTION_FLAGS actionFlags
= 0;
416 CSSM_TP_STOP_ON tpStopOn
= 0;
418 /* keep track of whether we did policy checking; if not, we do defaults */
419 bool didCertPolicy
= false;
420 bool didRevokePolicy
= false;
422 /* user trust parameters */
423 CSSM_OID utNullPolicy
= {0, NULL
};
424 const CSSM_OID
*utPolicyOid
= NULL
;
425 const char *utPolicyStr
= NULL
;
426 uint32 utPolicyStrLen
= 0;
427 SecTrustSettingsKeyUsage utKeyUse
= 0;
428 bool utTrustSettingEnabled
= false;
430 if(VerifyContextResult
) {
431 memset(VerifyContextResult
, 0, sizeof(*VerifyContextResult
));
434 /* verify input args, skipping the ones checked by CertGroupConstruct */
435 if((VerifyContext
== NULL
) || (VerifyContext
->Cred
== NULL
)) {
436 /* the spec says that this is optional but we require it */
437 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS
);
439 cred
= VerifyContext
->Cred
;
441 /* Optional ActionData affecting all policies */
442 actionData
= (CSSM_APPLE_TP_ACTION_DATA
* volatile)VerifyContext
->ActionData
.Data
;
443 if(actionData
!= NULL
) {
444 switch(actionData
->Version
) {
445 case CSSM_APPLE_TP_ACTION_VERSION
:
446 if(VerifyContext
->ActionData
.Length
!=
447 sizeof(CSSM_APPLE_TP_ACTION_DATA
)) {
448 CssmError::throwMe(CSSMERR_TP_INVALID_ACTION_DATA
);
451 /* handle backwards versions here if we ever go beyond version 0 */
453 CssmError::throwMe(CSSMERR_TP_INVALID_ACTION_DATA
);
455 actionFlags
= actionData
->ActionFlags
;
456 if(actionFlags
& CSSM_TP_ACTION_TRUST_SETTINGS
) {
457 utTrustSettingEnabled
= true;
461 /* optional, may be NULL */
462 cssmTimeStr
= cred
->VerifyTime
;
464 tpStopOn
= cred
->VerificationAbortOn
;
466 /* the only two we support */
467 case CSSM_TP_STOP_ON_NONE
:
468 case CSSM_TP_STOP_ON_FIRST_FAIL
:
470 /* default maps to stop on first fail */
471 case CSSM_TP_STOP_ON_POLICY
:
472 tpStopOn
= CSSM_TP_STOP_ON_FIRST_FAIL
;
475 CssmError::throwMe(CSSMERR_TP_INVALID_STOP_ON_POLICY
);
478 /* now the args we can't deal with */
479 if(cred
->CallerCredentials
!= NULL
) {
480 CssmError::throwMe(CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER
);
484 /* set up for optional user trust evaluation */
485 if(utTrustSettingEnabled
) {
486 const CSSM_TP_POLICYINFO
*pinfo
= &cred
->Policy
;
487 TPPolicy utPolicy
= kTPx509Basic
;
489 /* default policy OID in case caller hasn't specified one */
490 utPolicyOid
= &utNullPolicy
;
491 if(pinfo
->NumberOfPolicyIds
== 0) {
492 tpTrustSettingsDbg("CertGroupVerify: User trust enabled but no policies (1)");
493 /* keep going, I guess - no policy-specific info - use kTPx509Basic */
496 CSSM_FIELD_PTR utPolicyField
= &pinfo
->PolicyIds
[0];
497 utPolicyOid
= &utPolicyField
->FieldOid
;
498 bool foundPolicy
= checkPolicyOid(*utPolicyOid
, utPolicy
);
500 tpTrustSettingsDbg("CertGroupVerify: User trust enabled but no policies");
501 /* keep going, I guess - no policy-specific info - use kTPx509Basic */
504 /* get policy-specific info */
505 tp_policyTrustSettingParams(utPolicy
, &utPolicyField
->FieldValue
,
506 &utPolicyStr
, &utPolicyStrLen
, &utKeyUse
);
511 /* get verified (possibly partial) outCertGroup - error is fatal */
512 /* BUT: we still return partial evidence if asked to...from now on. */
513 TPCertGroup
outCertGroup(*this,
514 TGO_Caller
); // certs are owned by inCertGroup
515 TPCertGroup
inCertGroup(CertGroupToBeVerified
, clHand
, cspHand
, *this,
516 cssmTimeStr
, // optional 'this' time
517 true, // firstCertMustBeValid
520 /* set up for disposal of TPCertInfos created by CertGroupConstructPriv */
521 TPCertGroup
gatheredCerts(*this, TGO_Group
);
524 CertGroupConstructPriv(
530 cred
->NumberOfAnchorCerts
,
540 verifiedViaTrustSetting
,
543 catch(const CssmError
&cerr
) {
544 constructReturn
= cerr
.error
;
545 /* abort if no certs found */
546 if(outCertGroup
.numCerts() == 0) {
547 CssmError::throwMe(constructReturn
);
549 /* else press on, collecting as much info as we can */
551 /* others are way fatal */
552 assert(outCertGroup
.numCerts() >= 1);
554 /* Infer interim status from return values */
555 switch(constructReturn
) {
556 /* these values do not get overridden */
557 case CSSMERR_TP_CERTIFICATE_CANT_OPERATE
:
558 case CSSMERR_TP_INVALID_CERT_AUTHORITY
:
559 case CSSMERR_APPLETP_TRUST_SETTING_DENY
:
560 case errSecInvalidTrustSettings
:
563 /* infer status from these values... */
564 if(verifiedToAnchor
|| verifiedViaTrustSetting
) {
565 /* full success; anchor doesn't have to be root */
566 constructReturn
= CSSM_OK
;
568 else if(verifiedToRoot
) {
569 if(actionFlags
& CSSM_TP_ACTION_IMPLICIT_ANCHORS
) {
570 constructReturn
= CSSM_OK
;
573 /* verified to root which is not an anchor */
574 constructReturn
= CSSMERR_TP_INVALID_ANCHOR_CERT
;
578 /* partial chain, no root, not verifiable by anchor */
579 constructReturn
= CSSMERR_TP_NOT_TRUSTED
;
583 * Those errors can be allowed, cert-chain-wide, per individual
584 * certs' allowedErrors
586 if((constructReturn
!= CSSM_OK
) &&
587 outCertGroup
.isAllowedError(constructReturn
)) {
588 constructReturn
= CSSM_OK
;
595 * Parameters passed to tp_policyVerify() and which vary per policy
599 const CSSM_APPLE_TP_SSL_OPTIONS
*sslOpts
;
600 CSSM_RETURN thisPolicyRtn
= CSSM_OK
; // returned from tp_policyVerify()
602 /* common CRL verify parameters */
603 TPCrlGroup
*crlGroup
= NULL
;
605 crlGroup
= new TPCrlGroup(&VerifyContext
->Crls
,
608 NULL
, // cssmTimeStr - we want CRLs that are valid 'now'
611 catch(const CssmError
&cerr
) {
612 CSSM_RETURN cr
= cerr
.error
;
613 /* I don't see a straightforward way to report this error,
614 * other than adding it to the leaf cert's status... */
615 outCertGroup
.certAtIndex(0)->addStatusCode(cr
);
616 tpDebug("CertGroupVerify: error constructing CrlGroup; continuing\n");
618 /* others are way fatal */
620 TPVerifyContext
revokeVfyContext(*this,
624 cred
->NumberOfAnchorCerts
,
629 * This may consist of certs gathered from the net (which is the purpose
630 * of this argument) and from DLDBs (a side-effect optimization).
634 kRevokeNone
, // policy
637 NULL
, // OCSP options
643 /* true if we're to execute tp_policyVerify at end of loop */
645 /* true if we're to execute a revocation policy at end of loop */
646 bool doRevocationPolicy
;
648 /* grind thru each policy */
649 for(uint32 polDex
=0; polDex
<cred
->Policy
.NumberOfPolicyIds
; polDex
++) {
650 if(cred
->Policy
.PolicyIds
== NULL
) {
651 policyReturn
= CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
;
654 CSSM_FIELD_PTR policyId
= &cred
->Policy
.PolicyIds
[polDex
];
655 const CSSM_DATA
*fieldVal
= &policyId
->FieldValue
;
656 const CSSM_OID
*oid
= &policyId
->FieldOid
;
657 thisPolicyRtn
= CSSM_OK
;
658 doPolicyVerify
= false;
659 doRevocationPolicy
= false;
662 /* first the basic cert policies */
663 doPolicyVerify
= checkPolicyOid(*oid
, tpPolicy
);
665 /* some basic checks... */
666 bool policyAbort
= false;
670 case kTP_PKINIT_Client
:
671 case kTP_PKINIT_Server
:
672 if(fieldVal
->Data
!= NULL
) {
673 policyReturn
= CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
;
687 * Now revocation policies. Note some fields in revokeVfyContext can
688 * accumulate across multiple policy calls, e.g., signerCerts.
690 else if(tpCompareOids(oid
, &CSSMOID_APPLE_TP_REVOCATION_CRL
)) {
691 /* CRL-specific options */
692 const CSSM_APPLE_TP_CRL_OPTIONS
*crlOpts
;
693 crlOpts
= (CSSM_APPLE_TP_CRL_OPTIONS
*)fieldVal
->Data
;
694 thisPolicyRtn
= CSSM_OK
;
695 if(crlOpts
!= NULL
) {
696 switch(crlOpts
->Version
) {
697 case CSSM_APPLE_TP_CRL_OPTS_VERSION
:
698 if(fieldVal
->Length
!=
699 sizeof(CSSM_APPLE_TP_CRL_OPTIONS
)) {
701 CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
;
705 /* handle backwards compatibility here if necessary */
707 thisPolicyRtn
= CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
;
710 if(thisPolicyRtn
!= CSSM_OK
) {
711 policyReturn
= thisPolicyRtn
;
715 revokeVfyContext
.policy
= kRevokeCrlBasic
;
716 revokeVfyContext
.crlOpts
= crlOpts
;
717 doRevocationPolicy
= true;
719 else if(tpCompareOids(oid
, &CSSMOID_APPLE_TP_REVOCATION_OCSP
)) {
720 /* OCSP-specific options */
721 const CSSM_APPLE_TP_OCSP_OPTIONS
*ocspOpts
;
722 ocspOpts
= (CSSM_APPLE_TP_OCSP_OPTIONS
*)fieldVal
->Data
;
723 thisPolicyRtn
= CSSM_OK
;
724 if(ocspOpts
!= NULL
) {
725 switch(ocspOpts
->Version
) {
726 case CSSM_APPLE_TP_OCSP_OPTS_VERSION
:
727 if(fieldVal
->Length
!=
728 sizeof(CSSM_APPLE_TP_OCSP_OPTIONS
)) {
730 CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
;
734 /* handle backwards compatibility here if necessary */
736 thisPolicyRtn
= CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
;
739 if(thisPolicyRtn
!= CSSM_OK
) {
740 policyReturn
= thisPolicyRtn
;
744 revokeVfyContext
.policy
= kRevokeOcsp
;
745 revokeVfyContext
.ocspOpts
= ocspOpts
;
746 doRevocationPolicy
= true;
748 /* etc. - add more policies here */
750 /* unknown TP policy OID */
751 policyReturn
= CSSMERR_TP_INVALID_POLICY_IDENTIFIERS
;
755 /* common cert policy call */
757 assert(!doRevocationPolicy
); // one at a time
758 thisPolicyRtn
= tp_policyVerify(tpPolicy
,
764 verifiedViaTrustSetting
,
767 cred
->Policy
.PolicyControl
); // not currently used
768 didCertPolicy
= true;
770 /* common revocation policy call */
771 if(doRevocationPolicy
) {
772 assert(!doPolicyVerify
); // one at a time
773 thisPolicyRtn
= tpRevocationPolicyVerify(revokeVfyContext
, outCertGroup
);
774 didRevokePolicy
= true;
776 /* See if possible error is allowed, cert-chain-wide. */
777 if((thisPolicyRtn
!= CSSM_OK
) &&
778 outCertGroup
.isAllowedError(thisPolicyRtn
)) {
779 thisPolicyRtn
= CSSM_OK
;
782 /* Now remember the error if it's the first policy
783 * error we've seen. */
784 if(policyReturn
== CSSM_OK
) {
785 policyReturn
= thisPolicyRtn
;
788 if(tpStopOn
== CSSM_TP_STOP_ON_FIRST_FAIL
) {
789 /* Nope; we're done with policy evaluation */
793 } /* for each policy */
796 * Upon completion of the above loop, perform default policy ops if
799 if((policyReturn
== CSSM_OK
) || (tpStopOn
== CSSM_TP_STOP_ON_NONE
)) {
801 policyReturn
= tp_policyVerify(kTPDefault
,
807 verifiedViaTrustSetting
,
809 NULL
, // policyFieldData
810 cred
->Policy
.PolicyControl
); // not currently used
811 /* See if error is allowed, cert-chain-wide. */
812 if((policyReturn
!= CSSM_OK
) &&
813 outCertGroup
.isAllowedError(policyReturn
)) {
814 policyReturn
= CSSM_OK
;
817 if( !didRevokePolicy
&& // no revoke policy yet
818 ( (policyReturn
== CSSM_OK
|| // default cert policy OK
819 (tpStopOn
== CSSM_TP_STOP_ON_NONE
)) // keep going anyway
822 revokeVfyContext
.policy
= TP_CRL_POLICY_DEFAULT
;
823 CSSM_RETURN thisPolicyRtn
= tpRevocationPolicyVerify(revokeVfyContext
,
825 if((thisPolicyRtn
!= CSSM_OK
) &&
826 outCertGroup
.isAllowedError(thisPolicyRtn
)) {
827 thisPolicyRtn
= CSSM_OK
;
829 if((thisPolicyRtn
!= CSSM_OK
) && (policyReturn
== CSSM_OK
)) {
830 policyReturn
= thisPolicyRtn
;
834 } /* default policy opts */
838 /* return evidence - i.e., constructed chain - if asked to */
839 if(VerifyContextResult
!= NULL
) {
841 * VerifyContextResult->Evidence[0] : CSSM_TP_APPLE_EVIDENCE_HEADER
842 * VerifyContextResult->Evidence[1] : CSSM_CERTGROUP
843 * VerifyContextResult->Evidence[2] : CSSM_TP_APPLE_EVIDENCE_INFO
845 VerifyContextResult
->NumberOfEvidences
= 3;
846 VerifyContextResult
->Evidence
=
847 (CSSM_EVIDENCE_PTR
)calloc(3, sizeof(CSSM_EVIDENCE
));
849 CSSM_TP_APPLE_EVIDENCE_HEADER
*hdr
=
850 (CSSM_TP_APPLE_EVIDENCE_HEADER
*)malloc(
851 sizeof(CSSM_TP_APPLE_EVIDENCE_HEADER
));
852 hdr
->Version
= CSSM_TP_APPLE_EVIDENCE_VERSION
;
853 CSSM_EVIDENCE_PTR ev
= &VerifyContextResult
->Evidence
[0];
854 ev
->EvidenceForm
= CSSM_EVIDENCE_FORM_APPLE_HEADER
;
857 ev
= &VerifyContextResult
->Evidence
[1];
858 ev
->EvidenceForm
= CSSM_EVIDENCE_FORM_APPLE_CERTGROUP
;
859 ev
->Evidence
= outCertGroup
.buildCssmCertGroup();
861 ev
= &VerifyContextResult
->Evidence
[2];
862 ev
->EvidenceForm
= CSSM_EVIDENCE_FORM_APPLE_CERT_INFO
;
863 ev
->Evidence
= outCertGroup
.buildCssmEvidenceInfo();
866 /* caller responsible for freeing these if they are for evidence.... */
867 outCertGroup
.freeDbRecords();
869 CSSM_RETURN outErr
= outCertGroup
.getReturnCode(constructReturn
, policyReturn
,
873 CssmError::throwMe(outErr
);