X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/Security/libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp diff --git a/Security/libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp b/Security/libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp new file mode 100644 index 00000000..a516d362 --- /dev/null +++ b/Security/libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp @@ -0,0 +1,778 @@ +/* + * Copyright (c) 2001-2003,2011-2012,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. + */ + +/* + File: cuCdsaUtils.cpp + + Description: common CDSA access utilities + + Author: dmitch +*/ + +#include "cuCdsaUtils.h" +#include +#include +#include +#include /* for cssmPerror() */ +#include +#include +#include + +static CSSM_VERSION vers = {2, 0}; +static const CSSM_GUID testGuid = { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }}; + +/* + * Standard app-level memory functions required by CDSA. + */ +void * cuAppMalloc (CSSM_SIZE size, void *allocRef) { + return( malloc(size) ); +} + +void cuAppFree (void *mem_ptr, void *allocRef) { + free(mem_ptr); + return; +} + +void * cuAppRealloc (void *ptr, CSSM_SIZE size, void *allocRef) { + return( realloc( ptr, size ) ); +} + +void * cuAppCalloc (uint32 num, CSSM_SIZE size, void *allocRef) { + return( calloc( num, size ) ); +} + +static CSSM_API_MEMORY_FUNCS memFuncs = { + cuAppMalloc, + cuAppFree, + cuAppRealloc, + cuAppCalloc, + NULL + }; + +CSSM_BOOL cuCompareCssmData(const CSSM_DATA *d1, + const CSSM_DATA *d2) +{ + if(d1->Length != d2->Length) { + return CSSM_FALSE; + } + if(memcmp(d1->Data, d2->Data, d1->Length)) { + return CSSM_FALSE; + } + return CSSM_TRUE; +} + +/* + * Init CSSM; returns CSSM_FALSE on error. Reusable. + */ +static CSSM_BOOL cssmInitd = CSSM_FALSE; + +CSSM_BOOL cuCssmStartup() +{ + CSSM_RETURN crtn; + CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE; + + if(cssmInitd) { + return CSSM_TRUE; + } + crtn = CSSM_Init (&vers, + CSSM_PRIVILEGE_SCOPE_NONE, + &testGuid, + CSSM_KEY_HIERARCHY_NONE, + &pvcPolicy, + NULL /* reserved */); + if(crtn != CSSM_OK) + { + cuPrintError("CSSM_Init", crtn); + return CSSM_FALSE; + } + else { + cssmInitd = CSSM_TRUE; + return CSSM_TRUE; + } +} + +/* + * Attach to CSP. Returns zero on error. + */ +CSSM_CSP_HANDLE cuCspStartup( + CSSM_BOOL bareCsp) // true ==> CSP, false ==> CSP/DL +{ + CSSM_CSP_HANDLE cspHand; + CSSM_RETURN crtn; + const CSSM_GUID *guid; + + /* common CSSM init */ + if(cuCssmStartup() == CSSM_FALSE) { + return 0; + } + if(bareCsp) { + guid = &gGuidAppleCSP; + } + else { + guid = &gGuidAppleCSPDL; + } + crtn = CSSM_ModuleLoad(guid, + CSSM_KEY_HIERARCHY_NONE, + NULL, // eventHandler + NULL); // AppNotifyCallbackCtx + if(crtn) { + cuPrintError("CSSM_ModuleLoad()", crtn); + return 0; + } + crtn = CSSM_ModuleAttach (guid, + &vers, + &memFuncs, // memFuncs + 0, // SubserviceID + CSSM_SERVICE_CSP, + 0, // AttachFlags + CSSM_KEY_HIERARCHY_NONE, + NULL, // FunctionTable + 0, // NumFuncTable + NULL, // reserved + &cspHand); + if(crtn) { + cuPrintError("CSSM_ModuleAttach()", crtn); + return 0; + } + return cspHand; +} + +/* Attach to DL side of CSPDL */ +CSSM_DL_HANDLE cuDlStartup() +{ + CSSM_DL_HANDLE dlHand = 0; + CSSM_RETURN crtn; + + if(cuCssmStartup() == CSSM_FALSE) { + return 0; + } + crtn = CSSM_ModuleLoad(&gGuidAppleCSPDL, + CSSM_KEY_HIERARCHY_NONE, + NULL, // eventHandler + NULL); // AppNotifyCallbackCtx + if(crtn) { + cuPrintError("CSSM_ModuleLoad(Apple CSPDL)", crtn); + return 0; + } + crtn = CSSM_ModuleAttach (&gGuidAppleCSPDL, + &vers, + &memFuncs, // memFuncs + 0, // SubserviceID + CSSM_SERVICE_DL, + 0, // AttachFlags + CSSM_KEY_HIERARCHY_NONE, + NULL, // FunctionTable + 0, // NumFuncTable + NULL, // reserved + &dlHand); + if(crtn) { + cuPrintError("CSSM_ModuleAttach(Apple CSPDL)", crtn); + return 0; + } + return dlHand; +} + +CSSM_CL_HANDLE cuClStartup() +{ + CSSM_CL_HANDLE clHand; + CSSM_RETURN crtn; + + if(cuCssmStartup() == CSSM_FALSE) { + return 0; + } + crtn = CSSM_ModuleLoad(&gGuidAppleX509CL, + CSSM_KEY_HIERARCHY_NONE, + NULL, // eventHandler + NULL); // AppNotifyCallbackCtx + if(crtn) { + cuPrintError("CSSM_ModuleLoad(AppleCL)", crtn); + return 0; + } + crtn = CSSM_ModuleAttach (&gGuidAppleX509CL, + &vers, + &memFuncs, // memFuncs + 0, // SubserviceID + CSSM_SERVICE_CL, // SubserviceFlags - Where is this used? + 0, // AttachFlags + CSSM_KEY_HIERARCHY_NONE, + NULL, // FunctionTable + 0, // NumFuncTable + NULL, // reserved + &clHand); + if(crtn) { + cuPrintError("CSSM_ModuleAttach(AppleCL)", crtn); + return 0; + } + else { + return clHand; + } +} + +CSSM_TP_HANDLE cuTpStartup() +{ + CSSM_TP_HANDLE tpHand; + CSSM_RETURN crtn; + + if(cuCssmStartup() == CSSM_FALSE) { + return 0; + } + crtn = CSSM_ModuleLoad(&gGuidAppleX509TP, + CSSM_KEY_HIERARCHY_NONE, + NULL, // eventHandler + NULL); // AppNotifyCallbackCtx + if(crtn) { + cuPrintError("CSSM_ModuleLoad(AppleTP)", crtn); + return 0; + } + crtn = CSSM_ModuleAttach (&gGuidAppleX509TP, + &vers, + &memFuncs, // memFuncs + 0, // SubserviceID + CSSM_SERVICE_TP, // SubserviceFlags + 0, // AttachFlags + CSSM_KEY_HIERARCHY_NONE, + NULL, // FunctionTable + 0, // NumFuncTable + NULL, // reserved + &tpHand); + if(crtn) { + cuPrintError("CSSM_ModuleAttach(AppleTP)", crtn); + return 0; + } + else { + return tpHand; + } +} + +/* detach and unload */ +CSSM_RETURN cuCspDetachUnload( + CSSM_CSP_HANDLE cspHand, + CSSM_BOOL bareCsp) // true ==> CSP, false ==> CSP/DL +{ + CSSM_RETURN crtn = CSSM_ModuleDetach(cspHand); + if(crtn) { + return crtn; + } + const CSSM_GUID *guid; + if(bareCsp) { + guid = &gGuidAppleCSP; + } + else { + guid = &gGuidAppleCSPDL; + } + return CSSM_ModuleUnload(guid, NULL, NULL); +} + +CSSM_RETURN cuClDetachUnload( + CSSM_CL_HANDLE clHand) +{ + CSSM_RETURN crtn = CSSM_ModuleDetach(clHand); + if(crtn) { + return crtn; + } + return CSSM_ModuleUnload(&gGuidAppleX509CL, NULL, NULL); + +} + +CSSM_RETURN cuDlDetachUnload( + CSSM_DL_HANDLE dlHand) +{ + CSSM_RETURN crtn = CSSM_ModuleDetach(dlHand); + if(crtn) { + return crtn; + } + return CSSM_ModuleUnload(&gGuidAppleCSPDL, NULL, NULL); + +} +CSSM_RETURN cuTpDetachUnload( + CSSM_TP_HANDLE tpHand) +{ + CSSM_RETURN crtn = CSSM_ModuleDetach(tpHand); + if(crtn) { + return crtn; + } + return CSSM_ModuleUnload(&gGuidAppleX509TP, NULL, NULL); + +} + +/* + * open a DB, ensure it's empty. + */ +CSSM_DB_HANDLE cuDbStartup( + CSSM_DL_HANDLE dlHand, // from dlStartup() + const char *dbName) +{ + CSSM_DB_HANDLE dbHand = 0; + CSSM_RETURN crtn; + CSSM_DBINFO dbInfo; + + /* first delete possible existing DB, ignore error */ + crtn = CSSM_DL_DbDelete(dlHand, dbName, NULL, NULL); + switch(crtn) { + /* only allowed error is "no such file" */ + case CSSM_OK: + case CSSMERR_DL_DATASTORE_DOESNOT_EXIST: + break; + default: + cuPrintError("CSSM_DL_DbDelete", crtn); + return 0; + } + + memset(&dbInfo, 0, sizeof(CSSM_DBINFO)); + + /* now create it */ + crtn = CSSM_DL_DbCreate(dlHand, + dbName, + NULL, // DbLocation + &dbInfo, + // &Security::KeychainCore::Schema::DBInfo, + CSSM_DB_ACCESS_PRIVILEGED, + NULL, // CredAndAclEntry + NULL, // OpenParameters + &dbHand); + if(crtn) { + cuPrintError("CSSM_DL_DbCreate", crtn); + } + return dbHand; +} + +/* + * Attach to existing DB or create an empty new one. + */ +CSSM_DB_HANDLE cuDbStartupByName(CSSM_DL_HANDLE dlHand, + char *dbName, + CSSM_BOOL doCreate, + CSSM_BOOL quiet) +{ + CSSM_RETURN crtn; + CSSM_DB_HANDLE dbHand; + + /* try open existing DB in either case */ + + crtn = CSSM_DL_DbOpen(dlHand, + dbName, + NULL, // DbLocation + CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE, + NULL, // CSSM_ACCESS_CREDENTIALS *AccessCred + NULL, // void *OpenParameters + &dbHand); + if(crtn == CSSM_OK) { + return dbHand; + } + if(!doCreate) { + if(!quiet) { + printf("***no such data base (%s)\n", dbName); + cuPrintError("CSSM_DL_DbOpen", crtn); + } + return 0; + } + /* have to create one */ + return cuDbStartup(dlHand, dbName); +} + +/* + * Given a context specified via a CSSM_CC_HANDLE, add a new + * CSSM_CONTEXT_ATTRIBUTE to the context as specified by AttributeType, + * AttributeLength, and an untyped pointer. + */ +static +CSSM_RETURN cuAddContextAttribute(CSSM_CC_HANDLE CCHandle, + uint32 AttributeType, + uint32 AttributeLength, + const void *AttributePtr) +{ + CSSM_CONTEXT_ATTRIBUTE newAttr; + CSSM_RETURN crtn; + + newAttr.AttributeType = AttributeType; + newAttr.AttributeLength = AttributeLength; + newAttr.Attribute.Data = (CSSM_DATA_PTR)AttributePtr; + crtn = CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr); + if(crtn) { + cuPrintError("CSSM_UpdateContextAttributes", crtn); + } + return crtn; +} + + +/* + * Derive symmetric key. + * Note in the X CSP, we never return an IV. + */ +CSSM_RETURN cuCspDeriveKey(CSSM_CSP_HANDLE cspHand, + uint32 keyAlg, // CSSM_ALGID_RC5, etc. + const char *keyLabel, + unsigned keyLabelLen, + uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + uint32 keySizeInBits, + CSSM_DATA_PTR password, // in PKCS-5 lingo + CSSM_DATA_PTR salt, // ditto + uint32 iterationCnt, // ditto + CSSM_KEY_PTR key) +{ + CSSM_RETURN crtn; + CSSM_CC_HANDLE ccHand; + uint32 keyAttr; + CSSM_DATA dummyLabel; + CSSM_PKCS5_PBKDF2_PARAMS pbeParams; + CSSM_DATA pbeData; + CSSM_ACCESS_CREDENTIALS creds; + + memset(key, 0, sizeof(CSSM_KEY)); + memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); + crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand, + CSSM_ALGID_PKCS5_PBKDF2, + keyAlg, + keySizeInBits, + &creds, + NULL, // BaseKey + iterationCnt, + salt, + NULL, // seed + &ccHand); + if(crtn) { + cuPrintError("CSSM_CSP_CreateDeriveKeyContext", crtn); + return crtn; + } + keyAttr = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_REF | + CSSM_KEYATTR_SENSITIVE; + dummyLabel.Length = keyLabelLen; + dummyLabel.Data = (uint8 *)keyLabel; + + /* passing in password is pretty strange....*/ + pbeParams.Passphrase = *password; + pbeParams.PseudoRandomFunction = CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1; + pbeData.Data = (uint8 *)&pbeParams; + pbeData.Length = sizeof(pbeParams); + crtn = CSSM_DeriveKey(ccHand, + &pbeData, + keyUsage, + keyAttr, + &dummyLabel, + NULL, // cred and acl + key); + if(crtn) { + cuPrintError("CSSM_DeriveKey", crtn); + return crtn; + } + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + cuPrintError("CSSM_DeleteContext", crtn); + } + return crtn; +} + +/* + * Generate key pair of arbitrary algorithm. + */ + +/* CSP DL currently does not perform DSA generate params; let CSP do it implicitly */ +#define DO_DSA_GEN_PARAMS 0 + +CSSM_RETURN cuCspGenKeyPair(CSSM_CSP_HANDLE cspHand, + CSSM_DL_DB_HANDLE *dlDbHand, // optional + uint32 algorithm, + const char *keyLabel, + unsigned keyLabelLen, + uint32 keySize, // in bits + CSSM_KEY_PTR pubKey, // mallocd by caller + CSSM_KEYUSE pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc. + CSSM_KEYATTR_FLAGS pubAttrs, // CSSM_KEYATTR_EXTRACTABLE, etc. + CSSM_KEY_PTR privKey, // mallocd by caller + CSSM_KEYUSE privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc. + CSSM_KEYATTR_FLAGS privAttrs) // CSSM_KEYATTR_EXTRACTABLE, etc. +{ + CSSM_RETURN crtn; + CSSM_RETURN ocrtn; + CSSM_CC_HANDLE ccHand; + CSSM_DATA keyLabelData; + + keyLabelData.Data = (uint8 *)keyLabel, + keyLabelData.Length = keyLabelLen; + memset(pubKey, 0, sizeof(CSSM_KEY)); + memset(privKey, 0, sizeof(CSSM_KEY)); + + crtn = CSSM_CSP_CreateKeyGenContext(cspHand, + algorithm, + keySize, + NULL, // Seed + NULL, // Salt + NULL, // StartDate + NULL, // EndDate + NULL, // Params + &ccHand); + if(crtn) { + cuPrintError("CSSM_CSP_CreateKeyGenContext", crtn); + return crtn; + } + + /* post-context-create algorithm-specific stuff */ + switch(algorithm) { + #if DO_DSA_GEN_PARAMS + case CSSM_ALGID_DSA: + /* + * extra step - generate params - this just adds some + * info to the context + */ + { + CSSM_DATA dummy = {0, NULL}; + crtn = CSSM_GenerateAlgorithmParams(ccHand, + keySize, &dummy); + if(crtn) { + cuPrintError("CSSM_GenerateAlgorithmParams", crtn); + CSSM_DeleteContext(ccHand); + return crtn; + } + cuAppFree(dummy.Data, NULL); + } + break; + #endif /* DO_DSA_GEN_PARAMS */ + default: + break; + } + + /* optionally specify DL/DB storage location */ + if(dlDbHand) { + crtn = cuAddContextAttribute(ccHand, + CSSM_ATTRIBUTE_DL_DB_HANDLE, + sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE), + dlDbHand); + if(crtn) { + CSSM_DeleteContext(ccHand); + return crtn; + } + } + ocrtn = CSSM_GenerateKeyPair(ccHand, + pubKeyUsage, + pubAttrs, + &keyLabelData, + pubKey, + privKeyUsage, + privAttrs, + &keyLabelData, // same labels + NULL, // CredAndAclEntry + privKey); + if(ocrtn) { + cuPrintError("CSSM_GenerateKeyPair", ocrtn); + } + crtn = CSSM_DeleteContext(ccHand); + if(crtn) { + cuPrintError("CSSM_DeleteContext", crtn); + if(ocrtn == CSSM_OK) { + /* error on CSSM_GenerateKeyPair takes precedence */ + ocrtn = crtn; + } + } + return ocrtn; +} + + +/* + * Add a certificate to an open Keychain. + */ +CSSM_RETURN cuAddCertToKC( + SecKeychainRef keychain, + const CSSM_DATA *cert, + CSSM_CERT_TYPE certType, + CSSM_CERT_ENCODING certEncoding, + const char *printName, // C string + const CSSM_DATA *keyLabel) // ?? +{ + SecCertificateRef certificate; + + OSStatus rslt = SecCertificateCreateFromData(cert, certType, certEncoding, &certificate); + if (!rslt) + { + rslt = SecCertificateAddToKeychain(certificate, keychain); + CFRelease(certificate); + } + + return rslt; +} + +/* + * Convert a CSSM_DATA_PTR, referring to a DER-encoded int, to an + * unsigned. + */ +unsigned cuDER_ToInt(const CSSM_DATA *DER_Data) +{ + uint32 rtn = 0; + unsigned i = 0; + + while(i < DER_Data->Length) { + rtn |= DER_Data->Data[i]; + if(++i == DER_Data->Length) { + break; + } + rtn <<= 8; + } + return rtn; +} + +/* + * Log CSSM error. + */ +void cuPrintError(const char *op, CSSM_RETURN err) +{ + cssmPerror(op, err); +} + +/* + * Verify a CRL against system anchors and intermediate certs. + */ +CSSM_RETURN cuCrlVerify( + CSSM_TP_HANDLE tpHand, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + const CSSM_DATA *crlData, + CSSM_DL_DB_HANDLE_PTR certKeychain, // intermediate certs + const CSSM_DATA *anchors, // optional - if NULL, use Trust Settings + uint32 anchorCount) +{ + /* main job is building a CSSM_TP_VERIFY_CONTEXT and its components */ + CSSM_TP_VERIFY_CONTEXT vfyCtx; + CSSM_TP_CALLERAUTH_CONTEXT authCtx; + + memset(&vfyCtx, 0, sizeof(CSSM_TP_VERIFY_CONTEXT)); + memset(&authCtx, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT)); + + /* CSSM_TP_CALLERAUTH_CONTEXT components */ + /* + typedef struct cssm_tp_callerauth_context { + CSSM_TP_POLICYINFO Policy; + CSSM_TIMESTRING VerifyTime; + CSSM_TP_STOP_ON VerificationAbortOn; + CSSM_TP_VERIFICATION_RESULTS_CALLBACK CallbackWithVerifiedCert; + uint32 NumberOfAnchorCerts; + CSSM_DATA_PTR AnchorCerts; + CSSM_DL_DB_LIST_PTR DBList; + CSSM_ACCESS_CREDENTIALS_PTR CallerCredentials; + } CSSM_TP_CALLERAUTH_CONTEXT, *CSSM_TP_CALLERAUTH_CONTEXT_PTR; + */ + CSSM_FIELD policyId; + CSSM_APPLE_TP_CRL_OPTIONS crlOpts; + policyId.FieldOid = CSSMOID_APPLE_TP_REVOCATION_CRL; + policyId.FieldValue.Data = (uint8 *)&crlOpts; + policyId.FieldValue.Length = sizeof(crlOpts); + crlOpts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; + /* perhaps this should be user-specifiable */ + crlOpts.CrlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET; + crlOpts.crlStore = NULL; + + authCtx.Policy.NumberOfPolicyIds = 1; + authCtx.Policy.PolicyIds = &policyId; + authCtx.Policy.PolicyControl = NULL; + + authCtx.VerifyTime = NULL; + authCtx.VerificationAbortOn = CSSM_TP_STOP_ON_POLICY; + authCtx.CallbackWithVerifiedCert = NULL; + + /* anchors */ + authCtx.NumberOfAnchorCerts = anchorCount; + authCtx.AnchorCerts = const_cast(anchors); + + /* DBList of intermediate certs, plus possible System.keychain and + * system roots */ + CSSM_DL_DB_HANDLE handles[3]; + unsigned numDbs = 0; + CSSM_DL_HANDLE dlHand = 0; + if(certKeychain != NULL) { + handles[0] = *certKeychain; + numDbs++; + } + if(anchors == NULL) { + /* Trust Settings requires two more DBs */ + if(numDbs == 0) { + /* new DL handle */ + dlHand = cuDlStartup(); + handles[numDbs].DLHandle = dlHand; + handles[numDbs + 1].DLHandle = dlHand; + } + else { + /* use the same one passed in for certKeychain */ + handles[numDbs].DLHandle = handles[0].DLHandle; + handles[numDbs + 1].DLHandle = handles[0].DLHandle; + } + handles[numDbs].DBHandle = cuDbStartupByName(handles[numDbs].DLHandle, + (char*) ADMIN_CERT_STORE_PATH, CSSM_FALSE, CSSM_TRUE); + numDbs++; + + handles[numDbs].DBHandle = cuDbStartupByName(handles[numDbs].DLHandle, + (char*) SYSTEM_ROOT_STORE_PATH, CSSM_FALSE, CSSM_TRUE); + numDbs++; + } + CSSM_DL_DB_LIST dlDbList; + dlDbList.DLDBHandle = handles; + dlDbList.NumHandles = numDbs; + + authCtx.DBList = &dlDbList; + authCtx.CallerCredentials = NULL; + + /* CSSM_TP_VERIFY_CONTEXT */ + vfyCtx.ActionData.Data = NULL; + vfyCtx.ActionData.Length = 0; + vfyCtx.Action = CSSM_TP_ACTION_DEFAULT; + vfyCtx.Cred = &authCtx; + + /* CSSM_APPLE_TP_ACTION_DATA */ + CSSM_APPLE_TP_ACTION_DATA tpAction; + if(anchors == NULL) { + /* enable Trust Settings */ + tpAction.Version = CSSM_APPLE_TP_ACTION_VERSION; + tpAction.ActionFlags = CSSM_TP_ACTION_TRUST_SETTINGS; + vfyCtx.ActionData.Data = (uint8 *)&tpAction; + vfyCtx.ActionData.Length = sizeof(tpAction); + } + + /* cook up CSSM_ENCODED_CRL */ + CSSM_ENCODED_CRL encCrl; + encCrl.CrlType = CSSM_CRL_TYPE_X_509v2; + encCrl.CrlEncoding = CSSM_CRL_ENCODING_DER; + encCrl.CrlBlob = *crlData; + + /* CDSA API requires a SignerCertGroup; for us, all the certs are in + * certKeyChain... */ + CSSM_CERTGROUP certGroup; + certGroup.CertType = CSSM_CERT_X_509v1; + certGroup.CertEncoding = CSSM_CERT_ENCODING_DER; + certGroup.NumCerts = 0; + certGroup.GroupList.CertList = NULL; + certGroup.CertGroupType = CSSM_CERTGROUP_DATA; + + CSSM_RETURN crtn = CSSM_TP_CrlVerify(tpHand, + clHand, + cspHand, + &encCrl, + &certGroup, + &vfyCtx, + NULL); // RevokerVerifyResult + if(crtn) { + cuPrintError("CSSM_TP_CrlVerify", crtn); + } + if(anchors == NULL) { + /* close the DBs and maybe the DL we opened */ + unsigned dexToClose = (certKeychain == NULL) ? 0 : 1; + CSSM_DL_DbClose(handles[dexToClose++]); + CSSM_DL_DbClose(handles[dexToClose]); + if(dlHand != 0) { + cuDlDetachUnload(dlHand); + } + } + return crtn; +} +