]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_apple_x509_tp/lib/tpCertGroup.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / Security / libsecurity_apple_x509_tp / lib / tpCertGroup.cpp
diff --git a/Security/libsecurity_apple_x509_tp/lib/tpCertGroup.cpp b/Security/libsecurity_apple_x509_tp/lib/tpCertGroup.cpp
deleted file mode 100644 (file)
index 67f9a47..0000000
+++ /dev/null
@@ -1,1038 +0,0 @@
-/*
- * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved.
- *
- * The contents of this file constitute Original Code as defined in and are
- * subject to the Apple Public Source License Version 1.2 (the 'License').
- * You may not use this file except in compliance with the License. Please obtain
- * a copy of the License at http://www.apple.com/publicsource and read it before
- * using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
- * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
- * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
- * specific language governing rights and limitations under the License.
- */
-
-
-/*
- * tpCertGroup.cpp - Cert group functions (construct, verify)
- */
-
-#include "AppleTPSession.h"
-#include "certGroupUtils.h"
-#include "TPCertInfo.h"
-#include "TPCrlInfo.h"
-#include "tpCertAllowList.h"
-#include "tpPolicies.h"
-#include "tpdebugging.h"
-#include "tpCrlVerify.h"
-#include <Security/oidsalg.h>
-#include <Security/cssmapple.h>
-
-/*
- * This is a temporary hack to allow verification of PKINIT server certs
- * which are self-signed and not in the system anchors list. If the self-
- * signed cert is in a magic keychain (whose location is not published),
- * we'll allow it as if it were indeed a full-fledged anchor cert.
- */
-#define TP_PKINIT_SERVER_HACK  1
-#if            TP_PKINIT_SERVER_HACK
-
-#include <Security/SecKeychain.h>
-#include <Security/SecKeychainSearch.h>
-#include <Security/SecCertificate.h>
-#include <Security/oidscert.h>
-#include <sys/types.h>
-#include <pwd.h>
-
-#define CFRELEASE(cf)  if(cf) { CFRelease(cf); }
-
-/*
- * Returns true if we are to allow/trust the specified
- * cert as a PKINIT-only anchor.
- */
-static bool tpCheckPkinitServerCert(
-       TPCertGroup &certGroup)
-{
-       /*
-        * Basic requirement: exactly one cert, self-signed.
-        * The numCerts == 1 requirement might change...
-        */
-       unsigned numCerts = certGroup.numCerts();
-       if(numCerts != 1) {
-               tpDebug("tpCheckPkinitServerCert: too many certs");
-               return false;
-       }
-       /* end of chain... */
-       TPCertInfo *theCert = certGroup.certAtIndex(numCerts - 1);
-       if(!theCert->isSelfSigned()) {
-               tpDebug("tpCheckPkinitServerCert: 1 cert, not self-signed");
-               return false;
-       }
-       const CSSM_DATA *subjectName = theCert->subjectName();
-
-       /*
-        * Open the magic keychain.
-        * We're going up and over the Sec layer here, not generally
-        * kosher, but this is a hack.
-        */
-       OSStatus ortn;
-       SecKeychainRef kcRef = NULL;
-       string fullPathName;
-       const char *homeDir = getenv("HOME");
-       if (homeDir == NULL)
-       {
-               // If $HOME is unset get the current user's home directory
-               // from the passwd file.
-               uid_t uid = geteuid();
-               if (!uid) uid = getuid();
-               struct passwd *pw = getpwuid(uid);
-               if (!pw) {
-                       return false;
-               }
-               homeDir = pw->pw_dir;
-       }
-       fullPathName = homeDir;
-       fullPathName += "/Library/Application Support/PKINIT/TrustedServers.keychain";
-       ortn = SecKeychainOpen(fullPathName.c_str(), &kcRef);
-       if(ortn) {
-               tpDebug("tpCheckPkinitServerCert: keychain not found (1)");
-               return false;
-       }
-       /* subsequent errors to errOut: */
-
-       bool ourRtn = false;
-       SecKeychainStatus kcStatus;
-       CSSM_DATA_PTR subjSerial = NULL;
-       CSSM_RETURN crtn;
-       SecKeychainSearchRef            srchRef = NULL;
-       SecKeychainAttributeList        attrList;
-       SecKeychainAttribute            attrs[2];
-       SecKeychainItemRef                      foundItem = NULL;
-
-       ortn = SecKeychainGetStatus(kcRef, &kcStatus);
-       if(ortn) {
-               tpDebug("tpCheckPkinitServerCert: keychain not found (2)");
-               goto errOut;
-       }
-
-       /*
-        * We already have this cert's normalized name; get its
-        * serial number.
-        */
-       crtn = theCert->fetchField(&CSSMOID_X509V1SerialNumber, &subjSerial);
-       if(crtn) {
-               /* should never happen */
-               tpDebug("tpCheckPkinitServerCert: error fetching serial number");
-               goto errOut;
-       }
-
-       attrs[0].tag    = kSecSubjectItemAttr;
-       attrs[0].length = (UInt32)subjectName->Length;
-       attrs[0].data   = subjectName->Data;
-       attrs[1].tag    = kSecSerialNumberItemAttr;
-       attrs[1].length = (UInt32)subjSerial->Length;
-       attrs[1].data   = subjSerial->Data;
-       attrList.count  = 2;
-       attrList.attr   = attrs;
-
-       ortn = SecKeychainSearchCreateFromAttributes(kcRef,
-               kSecCertificateItemClass,
-               &attrList,
-               &srchRef);
-       if(ortn) {
-               tpDebug("tpCheckPkinitServerCert: search failure");
-               goto errOut;
-       }
-       for(;;) {
-               ortn = SecKeychainSearchCopyNext(srchRef, &foundItem);
-               if(ortn) {
-                       tpDebug("tpCheckPkinitServerCert: end search");
-                       break;
-               }
-
-               /* found a matching cert; do byte-for-byte compare */
-               CSSM_DATA certData;
-               ortn = SecCertificateGetData((SecCertificateRef)foundItem, &certData);
-               if(ortn) {
-                       tpDebug("tpCheckPkinitServerCert: SecCertificateGetData failure");
-                       continue;
-               }
-               if(tpCompareCssmData(&certData, theCert->itemData())){
-                       tpDebug("tpCheckPkinitServerCert: FOUND CERT");
-                       ourRtn = true;
-                       break;
-               }
-               tpDebug("tpCheckPkinitServerCert: skipping matching cert");
-               CFRelease(foundItem);
-               foundItem = NULL;
-       }
-errOut:
-       CFRELEASE(kcRef);
-       CFRELEASE(srchRef);
-       CFRELEASE(foundItem);
-       if(subjSerial != NULL) {
-               theCert->freeField(&CSSMOID_X509V1SerialNumber, subjSerial);
-       }
-       return ourRtn;
-}
-#endif /* TP_PKINIT_SERVER_HACK */
-
-/*-----------------------------------------------------------------------------
- * CertGroupConstruct
- *
- * Description:
- *   This function returns a pointer to a mallocd CSSM_CERTGROUP which
- *   refers to a mallocd list of raw ordered X.509 certs which verify back as
- *   far as the TP is able to go. The first cert of the returned list is the
- *   subject cert. The TP will attempt to search thru the DBs passed in
- *   DBList in order to complete the chain. The chain is completed when a
- *   self-signed (root) cert is found in the chain. The root cert may be
- *   present in the input CertGroupFrag, or it may have been obtained from
- *   one of the DBs passed in DBList. It is not an error if no root cert is
- *   found.
- *
- *   The error conditions are:
- *   -- The first cert of CertGroupFrag is an invalid cert. NULL is returned,
- *             err = CSSM_TP_INVALID_CERTIFICATE.
- *   -- The root cert (if found) fails to verify. Valid certgroup is returned,
- *      err = CSSMERR_TP_VERIFICATION_FAILURE.
- *   -- Any cert in the (possibly partially) constructed chain has expired or
- *      isn't valid yet, err = CSSMERR_TP_CERT_EXPIRED or
- *      CSSMERR_TP_CERT_NOT_VALID_YET. A CertGroup is returned.
- *   -- CSSMERR_TP_CERT_EXPIRED and CSSMERR_TP_CERT_NOT_VALID_YET. If one of these
- *             conditions obtains for the first (leaf) cert, the function throws this
- *             error immediately and the outgoing cert group is empty. For subsequent certs,
- *             the temporal validity of a cert is only tested AFTER a cert successfully
- *             meets the cert chaining criteria (subject/issuer match and signature
- *             verify). A cert in a chain with this error is not added to the outgoing
- *             cert group.
- *   -- the usual errors like bad handle or memory failure.
- *
- * Parameters:
- *   Two handles - to an open CL and CSP. The CSP must be capable of
- *   dealing with the signature algorithms used by the certs. The CL must be
- *   an X.509-savvy CL.
- *
- *   CertGroupFrag, an unordered array of raw X.509 certs in the form of a
- *   CSSM_CERTGROUP_PTR. The first cert of this list is the subject cert
- *   which is eventually to be verified. The other certs can be in any order
- *   and may not even have any relevance to the cert chain being constructed.
- *   They may also be invalid certs.
- *
- *   DBList, a list of DB/DL handles which may contain certs necessary to
- *   complete the desired cert chain. (Not currently implemented.)
- *
- *---------------------------------------------------------------------------*/
-
-/* public version */
-void AppleTPSession::CertGroupConstruct(CSSM_CL_HANDLE clHand,
-               CSSM_CSP_HANDLE cspHand,
-               const CSSM_DL_DB_LIST &DBList,
-               const void *ConstructParams,
-               const CSSM_CERTGROUP &CertGroupFrag,
-               CSSM_CERTGROUP_PTR &CertGroup)
-{
-       TPCertGroup outCertGroup(*this, TGO_Caller);
-       TPCertGroup inCertGroup(CertGroupFrag,
-               clHand,
-               cspHand,
-               *this,
-               NULL,           // cssmTimeStr
-               true,           // firstCertMustBeValid
-               TGO_Group);
-
-       /* set up for disposal of TPCertInfos created by CertGroupConstructPriv */
-       TPCertGroup                     gatheredCerts(*this, TGO_Group);
-
-       CSSM_RETURN constructReturn = CSSM_OK;
-       CSSM_APPLE_TP_ACTION_FLAGS      actionFlags = 0;
-       CSSM_BOOL verifiedToRoot;               // not used
-       CSSM_BOOL verifiedToAnchor;             // not used
-       CSSM_BOOL verifiedViaTrustSetting;      // not used
-
-       try {
-               CertGroupConstructPriv(clHand,
-                       cspHand,
-                       inCertGroup,
-                       &DBList,
-                       NULL,                           // cssmTimeStr
-                       /* no anchors */
-                       0, NULL,
-                       actionFlags,
-                       /* no user trust */
-                       NULL, NULL, 0, 0,
-                       gatheredCerts,
-                       verifiedToRoot,
-                       verifiedToAnchor,
-                       verifiedViaTrustSetting,
-                       outCertGroup);
-       }
-       catch(const CssmError &cerr) {
-               constructReturn = cerr.error;
-               /* abort if no certs found */
-               if(outCertGroup.numCerts() == 0) {
-                       CssmError::throwMe(constructReturn);
-               }
-       }
-       CertGroup = outCertGroup.buildCssmCertGroup();
-       /* caller of this function never gets evidence... */
-       outCertGroup.freeDbRecords();
-
-       if(constructReturn) {
-               CssmError::throwMe(constructReturn);
-       }
-}
-
-
-/*
- * Private version of CertGroupConstruct, used by CertGroupConstruct and
- * CertGroupVerify. Populates a TP-style TPCertGroup for further processing.
- * This only throws CSSM-style exceptions in the following cases:
- *
- *  -- input parameter errors
- *  -- the first (leaf) cert is bad (doesn't parse, expired, not valid yet).
- *  -- root found but it doesn't self-verify
- *
- *  All other cert-related errors simply result in the bad cert being ignored.
- *  Other exceptions are gross system errors like malloc failure.
- */
-void AppleTPSession::CertGroupConstructPriv(CSSM_CL_HANDLE clHand,
-               CSSM_CSP_HANDLE                 cspHand,
-               TPCertGroup                     &inCertGroup,
-               const CSSM_DL_DB_LIST   *DBList,                        // optional here
-               const char                              *cssmTimeStr,           // optional
-
-               /* trusted anchors, optional */
-               /* FIXME - maybe this should be a TPCertGroup */
-               uint32                                  numAnchorCerts,
-               const CSSM_DATA                 *anchorCerts,
-
-               /* CSSM_TP_ACTION_FETCH_CERT_FROM_NET, CSSM_TP_ACTION_TRUST_SETTINGS */
-               CSSM_APPLE_TP_ACTION_FLAGS      actionFlags,
-
-               /* optional user trust parameters */
-               const CSSM_OID                  *policyOid,
-               const char                              *policyStr,
-               uint32                                  policyStrLen,
-               SecTrustSettingsKeyUsage        keyUse,
-
-               /*
-                * Certs to be freed by caller (i.e., TPCertInfo which we allocate
-                * as a result of using a cert from anchorCerts or dbList) are added
-                * to this group.
-                */
-               TPCertGroup                             &certsToBeFreed,
-
-               /* returned */
-               CSSM_BOOL                               &verifiedToRoot,                // end of chain self-verifies
-               CSSM_BOOL                               &verifiedToAnchor,              // end of chain in anchors
-               CSSM_BOOL                               &verifiedViaTrustSetting,       // chain ends per User Trust setting
-               TPCertGroup                     &outCertGroup)                  // RETURNED
-{
-       TPCertInfo                      *subjectCert;                           // the one we're working on
-       CSSM_RETURN                     outErr = CSSM_OK;
-
-       /* this'll be the first subject cert in the main loop */
-       subjectCert = inCertGroup.certAtIndex(0);
-
-       /* Append leaf cert to outCertGroup */
-       outCertGroup.appendCert(subjectCert);
-       subjectCert->isLeaf(true);
-       subjectCert->isFromInputCerts(true);
-       outCertGroup.setAllUnused();
-       subjectCert->used(true);
-
-       outErr = outCertGroup.buildCertGroup(
-               *subjectCert,
-               &inCertGroup,
-               DBList,
-               clHand,
-               cspHand,
-               cssmTimeStr,
-               numAnchorCerts,
-               anchorCerts,
-               certsToBeFreed,
-               &certsToBeFreed,        // gatheredCerts to accumulate net/DB fetches
-               CSSM_TRUE,                      // subjectIsInGroup - enables root check on
-                                                       //    subject cert
-               actionFlags,
-               policyOid,
-               policyStr,
-               policyStrLen,
-               keyUse,
-
-               verifiedToRoot,
-               verifiedToAnchor,
-               verifiedViaTrustSetting);
-       if(outErr) {
-               CssmError::throwMe(outErr);
-       }
-}
-
-/*
- * Map a policy OID to one of the standard (non-revocation) policies.
- * Returns true if it's a standard policy.
- */
-static bool checkPolicyOid(
-       const CSSM_OID  &oid,
-       TPPolicy                &tpPolicy)              /* RETURNED */
-{
-       if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_SSL)) {
-               tpPolicy = kTP_SSL;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_X509_BASIC)) {
-               tpPolicy = kTPx509Basic;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_SMIME)) {
-               tpPolicy = kTP_SMIME;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_EAP)) {
-               tpPolicy = kTP_EAP;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_SW_UPDATE_SIGNING)) {
-               /* note: this was CSSMOID_APPLE_TP_CODE_SIGN until 8/15/06 */
-               tpPolicy = kTP_SWUpdateSign;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_RESOURCE_SIGN)) {
-               tpPolicy = kTP_ResourceSign;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_IP_SEC)) {
-               tpPolicy = kTP_IPSec;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_ICHAT)) {
-               tpPolicy = kTP_iChat;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_ISIGN)) {
-               tpPolicy = kTPiSign;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_PKINIT_CLIENT)) {
-               tpPolicy = kTP_PKINIT_Client;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_PKINIT_SERVER)) {
-               tpPolicy = kTP_PKINIT_Server;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_CODE_SIGNING)) {
-               tpPolicy = kTP_CodeSigning;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_PACKAGE_SIGNING)) {
-               tpPolicy = kTP_PackageSigning;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT)) {
-               tpPolicy = kTP_MacAppStoreRec;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_APPLEID_SHARING)) {
-               tpPolicy = kTP_AppleIDSharing;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_TIMESTAMPING)) {
-               tpPolicy = kTP_TimeStamping;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_PASSBOOK_SIGNING)) {
-               tpPolicy = kTP_PassbookSigning;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_MOBILE_STORE)) {
-               tpPolicy = kTP_MobileStore;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_TEST_MOBILE_STORE)) {
-               tpPolicy = kTP_TestMobileStore;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_ESCROW_SERVICE)) {
-               tpPolicy = kTP_EscrowService;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_PROFILE_SIGNING)) {
-               tpPolicy = kTP_ProfileSigning;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_QA_PROFILE_SIGNING)) {
-               tpPolicy = kTP_QAProfileSigning;
-               return true;
-       }
-       else if(tpCompareOids(&oid, &CSSMOID_APPLE_TP_PCS_ESCROW_SERVICE)) {
-               tpPolicy = kTP_PCSEscrowService;
-               return true;
-       }
-       return false;
-}
-
-/*-----------------------------------------------------------------------------
- * CertGroupVerify
- *
- * Description:
- *   -- Construct a cert chain using TP_CertGroupConstruct.
- *   -- Attempt to verify that cert chain against one of the known
- *      good certs passed in AnchorCerts.
- *   -- Optionally enforces additional policies (TBD) when verifying the cert chain.
- *   -- Optionally returns the entire cert chain constructed in
- *      TP_CertGroupConstruct and here, all the way to an anchor cert or as
- *      far as we were able to go, in *Evidence.
- *
- * Parameters:
- *   Two handles - to an open CL and CSP. The CSP must be capable of
- *   dealing with the signature algorithms used by the certs. The CL must be
- *   an X.509-savvy CL.
- *
- *   RawCerts, an unordered array of raw certs in the form of a
- *   CSSM_CERTGROUP_PTR. The first cert of this list is the subject cert
- *   which is eventually to be verified. The other certs can be in any order
- *   and may not even have any relevance to the cert chain being constructed.
- *   They may also be invalid certs.
- *
- *   DBList, a list of DB/DL handles which may contain certs necessary to
- *   complete the desired cert chain. (Currently not implemented.)
- *
- *   AnchorCerts, a list of known trusted certs.
- *   NumberOfAnchorCerts, size of AnchorCerts array.
- *
- *   PolicyIdentifiers, Optional policy OID. NULL indicates default
- *             X.509 trust policy.
- *
- *      Supported Policies:
- *                     CSSMOID_APPLE_ISIGN
- *                     CSSMOID_APPLE_X509_BASIC
- *
- *                     For both of these, the associated FieldValue must be {0, NULL},
- *
- *   NumberOfPolicyIdentifiers, size of PolicyIdentifiers array, must be
- *      zero or one.
- *
- *   All other arguments must be zero/NULL.
- *
- *   Returns:
- *      CSSM_OK : cert chain verified all the way back to an AnchorCert.
- *      CSSMERR_TP_INVALID_ANCHOR_CERT : In this case, the cert chain
- *             was validated back to a self-signed (root) cert found in either
- *             CertToBeVerified or in one of the DBs in DBList, but that root cert
- *             was *NOT* found in the AnchorCert list.
- *             CSSMERR_TP_NOT_TRUSTED: no root cert was found and no AnchorCert
- *             verified the end of the constructed cert chain.
- *             CSSMERR_TP_VERIFICATION_FAILURE: a root cert was found which does
- *             not self-verify.
- *     CSSMERR_TP_VERIFY_ACTION_FAILED: indicates a failure of the requested
- *                     policy action.
- *     CSSMERR_TP_INVALID_CERTIFICATE: indicates a bad leaf cert.
- *             CSSMERR_TP_INVALID_REQUEST_INPUTS : no incoming VerifyContext.
- *             CSSMERR_TP_CERT_EXPIRED and CSSMERR_TP_CERT_NOT_VALID_YET: see comments
- *                     for CertGroupConstruct.
- *             CSSMERR_TP_CERTIFICATE_CANT_OPERATE : issuer cert was found with a partial
- *                     public key, rendering full verification impossible.
- *     CSSMERR_TP_INVALID_CERT_AUTHORITY : issuer cert was found with a partial
- *                     public key and which failed to perform subsequent signature
- *                     verification.
- *---------------------------------------------------------------------------*/
-
-void AppleTPSession::CertGroupVerify(CSSM_CL_HANDLE clHand,
-               CSSM_CSP_HANDLE cspHand,
-               const CSSM_CERTGROUP &CertGroupToBeVerified,
-               const CSSM_TP_VERIFY_CONTEXT *VerifyContext,
-               CSSM_TP_VERIFY_CONTEXT_RESULT_PTR VerifyContextResult)
-{
-       CSSM_BOOL                               verifiedToRoot = CSSM_FALSE;
-       CSSM_BOOL                               verifiedToAnchor = CSSM_FALSE;
-       CSSM_BOOL                               verifiedViaTrustSetting = CSSM_FALSE;
-       CSSM_RETURN                             constructReturn = CSSM_OK;
-       CSSM_RETURN                             policyReturn = CSSM_OK;
-       const CSSM_TP_CALLERAUTH_CONTEXT *cred;
-       /* declare volatile as compiler workaround to avoid caching in CR4 */
-       const CSSM_APPLE_TP_ACTION_DATA * volatile actionData = NULL;
-       CSSM_TIMESTRING                 cssmTimeStr;
-       CSSM_APPLE_TP_ACTION_FLAGS      actionFlags = 0;
-       CSSM_TP_STOP_ON                 tpStopOn = 0;
-
-       /* keep track of whether we did policy checking; if not, we do defaults */
-       bool                                    didCertPolicy = false;
-       bool                                    didRevokePolicy = false;
-
-       /* user trust parameters */
-       CSSM_OID                                utNullPolicy = {0, NULL};
-       const CSSM_OID                  *utPolicyOid = NULL;
-       const char                              *utPolicyStr = NULL;
-       uint32                                  utPolicyStrLen = 0;
-       SecTrustSettingsKeyUsage        utKeyUse = 0;
-       bool                                    utTrustSettingEnabled = false;
-
-       if(VerifyContextResult) {
-               memset(VerifyContextResult, 0, sizeof(*VerifyContextResult));
-       }
-
-       /* verify input args, skipping the ones checked by CertGroupConstruct */
-       if((VerifyContext == NULL) || (VerifyContext->Cred == NULL)) {
-               /* the spec says that this is optional but we require it */
-                       CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS);
-       }
-       cred = VerifyContext->Cred;
-
-       /* Optional ActionData affecting all policies */
-       actionData = (CSSM_APPLE_TP_ACTION_DATA * volatile)VerifyContext->ActionData.Data;
-       if(actionData != NULL) {
-               switch(actionData->Version) {
-                       case CSSM_APPLE_TP_ACTION_VERSION:
-                               if(VerifyContext->ActionData.Length !=
-                                               sizeof(CSSM_APPLE_TP_ACTION_DATA)) {
-                                       CssmError::throwMe(CSSMERR_TP_INVALID_ACTION_DATA);
-                               }
-                               break;
-                       /* handle backwards versions here if we ever go beyond version 0 */
-                       default:
-                               CssmError::throwMe(CSSMERR_TP_INVALID_ACTION_DATA);
-               }
-               actionFlags = actionData->ActionFlags;
-               if(actionFlags & CSSM_TP_ACTION_TRUST_SETTINGS) {
-                       utTrustSettingEnabled = true;
-               }
-       }
-
-       /* optional, may be NULL */
-       cssmTimeStr = cred->VerifyTime;
-
-       tpStopOn = cred->VerificationAbortOn;
-       switch(tpStopOn) {
-               /* the only two we support */
-               case CSSM_TP_STOP_ON_NONE:
-               case CSSM_TP_STOP_ON_FIRST_FAIL:
-                       break;
-               /* default maps to stop on first fail */
-               case CSSM_TP_STOP_ON_POLICY:
-                       tpStopOn = CSSM_TP_STOP_ON_FIRST_FAIL;
-                       break;
-               default:
-                       CssmError::throwMe(CSSMERR_TP_INVALID_STOP_ON_POLICY);
-       }
-
-       /* now the args we can't deal with */
-       if(cred->CallerCredentials != NULL) {
-                       CssmError::throwMe(CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER);
-       }
-       /* ...any others? */
-
-       /* set up for optional user trust evaluation */
-       if(utTrustSettingEnabled) {
-               const CSSM_TP_POLICYINFO *pinfo = &cred->Policy;
-               TPPolicy utPolicy = kTPx509Basic;
-
-               /* default policy OID in case caller hasn't specified one */
-               utPolicyOid = &utNullPolicy;
-               if(pinfo->NumberOfPolicyIds == 0) {
-                       tpTrustSettingsDbg("CertGroupVerify: User trust enabled but no policies (1)");
-                       /* keep going, I guess - no policy-specific info - use kTPx509Basic */
-               }
-               else {
-                       CSSM_FIELD_PTR utPolicyField = &pinfo->PolicyIds[0];
-                       utPolicyOid = &utPolicyField->FieldOid;
-                       bool foundPolicy = checkPolicyOid(*utPolicyOid, utPolicy);
-                       if(!foundPolicy) {
-                               tpTrustSettingsDbg("CertGroupVerify: User trust enabled but no policies");
-                               /* keep going, I guess - no policy-specific info - use kTPx509Basic */
-                       }
-                       else {
-                               /* get policy-specific info */
-                               tp_policyTrustSettingParams(utPolicy, &utPolicyField->FieldValue,
-                                       &utPolicyStr, &utPolicyStrLen, &utKeyUse);
-                       }
-               }
-       }
-
-       /* get verified (possibly partial) outCertGroup - error is fatal */
-       /* BUT: we still return partial evidence if asked to...from now on. */
-       TPCertGroup outCertGroup(*this,
-               TGO_Caller);            // certs are owned by inCertGroup
-       TPCertGroup inCertGroup(CertGroupToBeVerified, clHand, cspHand, *this,
-               cssmTimeStr,            // optional 'this' time
-               true,                           // firstCertMustBeValid
-               TGO_Group);
-
-       /* set up for disposal of TPCertInfos created by CertGroupConstructPriv */
-       TPCertGroup     gatheredCerts(*this, TGO_Group);
-
-       try {
-               CertGroupConstructPriv(
-                       clHand,
-                       cspHand,
-                       inCertGroup,
-                       cred->DBList,
-                       cssmTimeStr,
-                       cred->NumberOfAnchorCerts,
-                       cred->AnchorCerts,
-                       actionFlags,
-                       utPolicyOid,
-                       utPolicyStr,
-                       utPolicyStrLen,
-                       utKeyUse,
-                       gatheredCerts,
-                       verifiedToRoot,
-                       verifiedToAnchor,
-                       verifiedViaTrustSetting,
-                       outCertGroup);
-       }
-       catch(const CssmError &cerr) {
-               constructReturn = cerr.error;
-               /* abort if no certs found */
-               if(outCertGroup.numCerts() == 0) {
-                       CssmError::throwMe(constructReturn);
-               }
-               /* else press on, collecting as much info as we can */
-       }
-       /* others are way fatal */
-       assert(outCertGroup.numCerts() >= 1);
-
-       /* Infer interim status from return values */
-       switch(constructReturn) {
-               /* these values do not get overridden */
-               case CSSMERR_TP_CERTIFICATE_CANT_OPERATE:
-               case CSSMERR_TP_INVALID_CERT_AUTHORITY:
-               case CSSMERR_APPLETP_TRUST_SETTING_DENY:
-               case errSecInvalidTrustSettings:
-                       break;
-               default:
-                       /* infer status from these values... */
-                       if(verifiedToAnchor || verifiedViaTrustSetting) {
-                               /* full success; anchor doesn't have to be root */
-                               constructReturn = CSSM_OK;
-                       }
-                       else if(verifiedToRoot) {
-                               if(actionFlags & CSSM_TP_ACTION_IMPLICIT_ANCHORS) {
-                                       constructReturn = CSSM_OK;
-                               }
-                               else {
-                                       /* verified to root which is not an anchor */
-                                       constructReturn = CSSMERR_TP_INVALID_ANCHOR_CERT;
-                               }
-                       }
-                       else {
-                               /* partial chain, no root, not verifiable by anchor */
-                               constructReturn = CSSMERR_TP_NOT_TRUSTED;
-                       }
-
-                       /*
-                        * Those errors can be allowed, cert-chain-wide, per individual
-                        * certs' allowedErrors
-                        */
-                       if((constructReturn != CSSM_OK) &&
-                           outCertGroup.isAllowedError(constructReturn)) {
-                               constructReturn = CSSM_OK;
-                       }
-            
-                       /*
-                        * Allow non-trusted root if whitelist check permits
-                        */
-                       if (constructReturn == CSSMERR_TP_NOT_TRUSTED) {
-                               constructReturn = tpCheckCertificateAllowList(outCertGroup);
-                       }
-                       break;
-       }
-
-       /*
-        * Parameters passed to tp_policyVerify() and which vary per policy
-        * in the loop below
-        */
-       TPPolicy tpPolicy;
-       const CSSM_APPLE_TP_SSL_OPTIONS *sslOpts;
-       CSSM_RETURN thisPolicyRtn = CSSM_OK;    // returned from tp_policyVerify()
-
-       /* common CRL verify parameters */
-       TPCrlGroup *crlGroup = NULL;
-       try {
-               crlGroup = new TPCrlGroup(&VerifyContext->Crls,
-                       clHand, cspHand,
-                       *this,                          // alloc
-                       NULL,                           // cssmTimeStr - we want CRLs that are valid 'now'
-                       TGO_Group);
-       }
-       catch(const CssmError &cerr) {
-               CSSM_RETURN cr = cerr.error;
-               /* I don't see a straightforward way to report this error,
-                * other than adding it to the leaf cert's status... */
-               outCertGroup.certAtIndex(0)->addStatusCode(cr);
-               tpDebug("CertGroupVerify: error constructing CrlGroup; continuing\n");
-       }
-       /* others are way fatal */
-
-       TPVerifyContext revokeVfyContext(*this,
-               clHand,
-               cspHand,
-               cssmTimeStr,
-               cred->NumberOfAnchorCerts,
-               cred->AnchorCerts,
-               &inCertGroup,
-               crlGroup,
-               /*
-                * This may consist of certs gathered from the net (which is the purpose
-                * of this argument) and from DLDBs (a side-effect optimization).
-                */
-               gatheredCerts,
-               cred->DBList,
-               kRevokeNone,            // policy
-               actionFlags,
-               NULL,                           // CRL options
-               NULL,                           // OCSP options
-               utPolicyOid,
-               utPolicyStr,
-               utPolicyStrLen,
-               utKeyUse);
-
-       /* true if we're to execute tp_policyVerify at end of loop */
-       bool doPolicyVerify;
-       /* true if we're to execute a revocation policy at end of loop */
-       bool doRevocationPolicy;
-
-       /* grind thru each policy */
-       for(uint32 polDex=0; polDex<cred->Policy.NumberOfPolicyIds; polDex++) {
-               if(cred->Policy.PolicyIds == NULL) {
-                       policyReturn = CSSMERR_TP_INVALID_POLICY_IDENTIFIERS;
-                       break;
-               }
-               CSSM_FIELD_PTR policyId = &cred->Policy.PolicyIds[polDex];
-               const CSSM_DATA *fieldVal = &policyId->FieldValue;
-               const CSSM_OID  *oid = &policyId->FieldOid;
-               thisPolicyRtn = CSSM_OK;
-               doPolicyVerify = false;
-               doRevocationPolicy = false;
-               sslOpts = NULL;
-
-               /* first the basic cert policies */
-               doPolicyVerify = checkPolicyOid(*oid, tpPolicy);
-               if(doPolicyVerify) {
-                       /* some basic checks... */
-                       bool policyAbort = false;
-                       switch(tpPolicy) {
-                               case kTPx509Basic:
-                               case kTPiSign:
-                               case kTP_PKINIT_Client:
-                               case kTP_PKINIT_Server:
-                                       if(fieldVal->Data != NULL) {
-                                               policyReturn = CSSMERR_TP_INVALID_POLICY_IDENTIFIERS;
-                                               policyAbort = true;
-                                               break;
-                                       }
-                                       break;
-                               default:
-                                       break;
-                       }
-                       if(policyAbort) {
-                               break;
-                       }
-                       #if             TP_PKINIT_SERVER_HACK
-                       if(tpPolicy == kTP_PKINIT_Server) {
-                               /* possible override of "root not in anchors" */
-                               if(constructReturn == CSSMERR_TP_INVALID_ANCHOR_CERT) {
-                                       if(tpCheckPkinitServerCert(outCertGroup)) {
-                                               constructReturn = CSSM_OK;
-                                       }
-                               }
-                       }
-                       #endif  /* TP_PKINIT_SERVER_HACK */
-               }
-
-               /*
-                * Now revocation policies. Note some fields in revokeVfyContext can
-                * accumulate across multiple policy calls, e.g., signerCerts.
-                */
-               else if(tpCompareOids(oid, &CSSMOID_APPLE_TP_REVOCATION_CRL)) {
-                       /* CRL-specific options */
-                       const CSSM_APPLE_TP_CRL_OPTIONS *crlOpts;
-                       crlOpts = (CSSM_APPLE_TP_CRL_OPTIONS *)fieldVal->Data;
-                       thisPolicyRtn = CSSM_OK;
-                       if(crlOpts != NULL) {
-                               switch(crlOpts->Version) {
-                                       case CSSM_APPLE_TP_CRL_OPTS_VERSION:
-                                               if(fieldVal->Length !=
-                                                               sizeof(CSSM_APPLE_TP_CRL_OPTIONS)) {
-                                                       thisPolicyRtn =
-                                                               CSSMERR_TP_INVALID_POLICY_IDENTIFIERS;
-                                                       break;
-                                               }
-                                               break;
-                                       /* handle backwards compatibility here if necessary */
-                                       default:
-                                               thisPolicyRtn = CSSMERR_TP_INVALID_POLICY_IDENTIFIERS;
-                                               break;
-                               }
-                               if(thisPolicyRtn != CSSM_OK) {
-                                       policyReturn = thisPolicyRtn;
-                                       break;
-                               }
-                       }
-                       revokeVfyContext.policy = kRevokeCrlBasic;
-                       revokeVfyContext.crlOpts = crlOpts;
-                       doRevocationPolicy = true;
-               }
-               else if(tpCompareOids(oid, &CSSMOID_APPLE_TP_REVOCATION_OCSP)) {
-                       /* OCSP-specific options */
-                       const CSSM_APPLE_TP_OCSP_OPTIONS *ocspOpts;
-                       ocspOpts = (CSSM_APPLE_TP_OCSP_OPTIONS *)fieldVal->Data;
-                       thisPolicyRtn = CSSM_OK;
-                       if(ocspOpts != NULL) {
-                               switch(ocspOpts->Version) {
-                                       case CSSM_APPLE_TP_OCSP_OPTS_VERSION:
-                                               if(fieldVal->Length !=
-                                                               sizeof(CSSM_APPLE_TP_OCSP_OPTIONS)) {
-                                                       thisPolicyRtn =
-                                                               CSSMERR_TP_INVALID_POLICY_IDENTIFIERS;
-                                                       break;
-                                               }
-                                               break;
-                                       /* handle backwards compatibility here if necessary */
-                                       default:
-                                               thisPolicyRtn = CSSMERR_TP_INVALID_POLICY_IDENTIFIERS;
-                                               break;
-                               }
-                               if(thisPolicyRtn != CSSM_OK) {
-                                       policyReturn = thisPolicyRtn;
-                                       break;
-                               }
-                       }
-                       revokeVfyContext.policy = kRevokeOcsp;
-                       revokeVfyContext.ocspOpts = ocspOpts;
-                       doRevocationPolicy = true;
-               }
-               /* etc. - add more policies here */
-               else {
-                       /* unknown TP policy OID */
-                       policyReturn = CSSMERR_TP_INVALID_POLICY_IDENTIFIERS;
-                       break;
-               }
-
-               /* common cert policy call */
-               if(doPolicyVerify) {
-                       assert(!doRevocationPolicy);    // one at a time
-                       thisPolicyRtn = tp_policyVerify(tpPolicy,
-                               *this,
-                               clHand,
-                               cspHand,
-                               &outCertGroup,
-                               verifiedToRoot,
-                               verifiedViaTrustSetting,
-                               actionFlags,
-                               fieldVal,
-                               cred->Policy.PolicyControl);    // not currently used
-                       didCertPolicy = true;
-               }
-               /* common revocation policy call */
-               if(doRevocationPolicy) {
-                       assert(!doPolicyVerify);        // one at a time
-                       thisPolicyRtn = tpRevocationPolicyVerify(revokeVfyContext, outCertGroup);
-                       didRevokePolicy = true;
-               }
-               /* See if possible error is allowed, cert-chain-wide. */
-               if((thisPolicyRtn != CSSM_OK) &&
-                   outCertGroup.isAllowedError(thisPolicyRtn)) {
-                       thisPolicyRtn = CSSM_OK;
-               }
-               if(thisPolicyRtn) {
-                       /* Now remember the error if it's the first policy
-                        * error we've seen. */
-                       if(policyReturn == CSSM_OK) {
-                               policyReturn = thisPolicyRtn;
-                       }
-                       /* Keep going? */
-                       if(tpStopOn == CSSM_TP_STOP_ON_FIRST_FAIL) {
-                               /* Nope; we're done with policy evaluation */
-                               break;
-                       }
-               }
-       }       /* for each policy */
-
-       /*
-        * Upon completion of the above loop, perform default policy ops if
-        * appropriate.
-        */
-       if((policyReturn == CSSM_OK) || (tpStopOn == CSSM_TP_STOP_ON_NONE)) {
-               if(!didCertPolicy) {
-                       policyReturn = tp_policyVerify(kTPDefault,
-                               *this,
-                               clHand,
-                               cspHand,
-                               &outCertGroup,
-                               verifiedToRoot,
-                               verifiedViaTrustSetting,
-                               actionFlags,
-                               NULL,                                                   // policyFieldData
-                               cred->Policy.PolicyControl);    // not currently used
-                       /* See if error is allowed, cert-chain-wide. */
-                       if((policyReturn != CSSM_OK) &&
-                               outCertGroup.isAllowedError(policyReturn)) {
-                               policyReturn = CSSM_OK;
-                       }
-               }
-               if( !didRevokePolicy &&                                                 // no revoke policy yet
-                       ( (policyReturn == CSSM_OK ||                           // default cert policy OK
-                     (tpStopOn == CSSM_TP_STOP_ON_NONE))               // keep going anyway
-                       )
-                 ) {
-                       revokeVfyContext.policy = TP_CRL_POLICY_DEFAULT;
-                       CSSM_RETURN thisPolicyRtn = tpRevocationPolicyVerify(revokeVfyContext,
-                               outCertGroup);
-                       if((thisPolicyRtn != CSSM_OK) &&
-                               outCertGroup.isAllowedError(thisPolicyRtn)) {
-                               thisPolicyRtn = CSSM_OK;
-                       }
-                       if((thisPolicyRtn != CSSM_OK) && (policyReturn == CSSM_OK)) {
-                               policyReturn = thisPolicyRtn;
-                       }
-
-               }
-       }       /* default policy opts */
-
-       delete crlGroup;
-
-       /* return evidence - i.e., constructed chain - if asked to */
-       if(VerifyContextResult != NULL) {
-               /*
-                * VerifyContextResult->Evidence[0] : CSSM_TP_APPLE_EVIDENCE_HEADER
-                * VerifyContextResult->Evidence[1] : CSSM_CERTGROUP
-                * VerifyContextResult->Evidence[2] : CSSM_TP_APPLE_EVIDENCE_INFO
-                */
-               VerifyContextResult->NumberOfEvidences = 3;
-               VerifyContextResult->Evidence =
-                       (CSSM_EVIDENCE_PTR)calloc(3, sizeof(CSSM_EVIDENCE));
-
-               CSSM_TP_APPLE_EVIDENCE_HEADER *hdr =
-                       (CSSM_TP_APPLE_EVIDENCE_HEADER *)malloc(
-                               sizeof(CSSM_TP_APPLE_EVIDENCE_HEADER));
-               hdr->Version = CSSM_TP_APPLE_EVIDENCE_VERSION;
-               CSSM_EVIDENCE_PTR ev = &VerifyContextResult->Evidence[0];
-               ev->EvidenceForm = CSSM_EVIDENCE_FORM_APPLE_HEADER;
-               ev->Evidence = hdr;
-
-               ev = &VerifyContextResult->Evidence[1];
-               ev->EvidenceForm = CSSM_EVIDENCE_FORM_APPLE_CERTGROUP;
-               ev->Evidence = outCertGroup.buildCssmCertGroup();
-
-               ev = &VerifyContextResult->Evidence[2];
-               ev->EvidenceForm = CSSM_EVIDENCE_FORM_APPLE_CERT_INFO;
-               ev->Evidence = outCertGroup.buildCssmEvidenceInfo();
-       }
-       else {
-               /* caller responsible for freeing these if they are for evidence.... */
-               outCertGroup.freeDbRecords();
-       }
-       CSSM_RETURN outErr = outCertGroup.getReturnCode(constructReturn, policyReturn,
-               actionFlags);
-
-       if(outErr) {
-               CssmError::throwMe(outErr);
-       }
-}
-
-