X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SecurityTests/clxutils/clAppUtils/certVerify.cpp?ds=inline diff --git a/SecurityTests/clxutils/clAppUtils/certVerify.cpp b/SecurityTests/clxutils/clAppUtils/certVerify.cpp new file mode 100644 index 00000000..40954256 --- /dev/null +++ b/SecurityTests/clxutils/clAppUtils/certVerify.cpp @@ -0,0 +1,692 @@ +/* + * certVerify.cpp - execute cert/CRL verify; display results + */ + +#include "certVerify.h" +#include "tpUtils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int vfyCertErrors( + const CSSM_TP_VERIFY_CONTEXT_RESULT *vfyResult, + unsigned numCertErrors, + const char **certErrors, // e.g., "2:CSSMERR_TP_CERT_EXPIRED" + CSSM_BOOL quiet) +{ + if(numCertErrors == 0) { + return 0; + } + if(vfyResult->NumberOfEvidences != 3) { + printf("***vfyCertErrors: NumberOfEvidences is %u, expect 3\n", + (unsigned)vfyResult->NumberOfEvidences); + return 1; + } + + /* numCerts from evidence[1] */ + const CSSM_EVIDENCE *ev = &vfyResult->Evidence[1]; + const CSSM_CERTGROUP *grp = (const CSSM_CERTGROUP *)ev->Evidence; + unsigned numCerts = grp->NumCerts; + /* array of Apple-specific info from evidence[2] */ + ev = &vfyResult->Evidence[2]; + const CSSM_TP_APPLE_EVIDENCE_INFO *info = + (const CSSM_TP_APPLE_EVIDENCE_INFO *)ev->Evidence; + int ourRtn = 0; + + for(unsigned dex=0; dex (numCerts-1)) { + printf("***certerror specified for cert %u, but only %u certs" + " available\n", certNum, numCerts); + return 1; + } + str++; // pts to actual desired error string now + + /* + * There may be multiple per-cert statuses in the evidence; search all + * looking for a match + */ + const CSSM_TP_APPLE_EVIDENCE_INFO *thisInfo = &info[certNum]; + char *found = NULL; + for(unsigned i=0; iNumStatusCodes; i++) { + CSSM_RETURN actRtn = thisInfo->StatusCodes[i]; + const char *actRtnStr = cssmErrToStr(actRtn); + found = strstr(actRtnStr, str); + if(found) { + break; + } + } + if(found) { + if(!quiet) { + printf("...%s per-cert status received as expected\n", str); + } + } + else { + printf("***Per cert status %s not found\n", str); + ourRtn = 1; + /* might as well keep going */ + } + } + return ourRtn; +} + +static int vfyCertStatus( + const CSSM_TP_VERIFY_CONTEXT_RESULT *vfyResult, + unsigned numCertStatus, + const char **certStatus, // e.g., "1:0x18", leading 0x optional + CSSM_BOOL quiet) +{ + if(numCertStatus == 0) { + return 0; + } + if(vfyResult->NumberOfEvidences != 3) { + printf("***vfyCertStatus: NumberOfEvidences is %u, expect 3\n", + (unsigned)vfyResult->NumberOfEvidences); + return 1; + } + + /* numCerts from evidence[1] */ + const CSSM_EVIDENCE *ev = &vfyResult->Evidence[1]; + const CSSM_CERTGROUP *grp = (const CSSM_CERTGROUP *)ev->Evidence; + unsigned numCerts = grp->NumCerts; + /* array of Apple-specific info from evidence[2] */ + ev = &vfyResult->Evidence[2]; + const CSSM_TP_APPLE_EVIDENCE_INFO *info = + (const CSSM_TP_APPLE_EVIDENCE_INFO *)ev->Evidence; + int ourRtn = 0; + + for(unsigned dex=0; dex (numCerts-1)) { + printf("***certerror specified for cert %u, but only %u certs" + " available\n", certNum, numCerts); + return 1; + } + str++; // pts to actual desired status string now + unsigned certStat = hexToBin(str); + const CSSM_TP_APPLE_EVIDENCE_INFO *thisInfo = &info[certNum]; + if(certStat == thisInfo->StatusBits) { + if(!quiet) { + printf("...0x%x per-cert status received as expected\n", certStat); + } + } + else { + printf("***Expected per cert status 0x%x, got 0x%x\n", + (unsigned)certStat, (unsigned)thisInfo->StatusBits); + ourRtn = 1; + } + } + return ourRtn; +} + +/* + * Ensure that the policy being evaluated is accessible via + * SecPolicySearch*(). Not really part of the test, but a handy place + * to catch this common error before checking in TP changes. + */ +static int verifySecPolicy( + const CSSM_OID *oid) +{ + SecPolicySearchRef srchRef = NULL; + OSStatus ortn; + + ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3, oid, NULL, &srchRef); + if(ortn) { + cssmPerror("SecPolicySearchCreate", ortn); + return -1; + } + SecPolicyRef policyRef = NULL; + ortn = SecPolicySearchCopyNext(srchRef, &policyRef); + if(ortn) { + cssmPerror("SecPolicySearchCopyNext", ortn); + printf("***The TP policy used in this test is not accessible via SecPolicySearchCopyNext().\n"); + printf(" You probably forgot to add the policy to the theOidList table in PolicyCursor.cpp\n"); + printf(" in the libsecurity_keychain project.\n"); + } + CFRelease(srchRef); + if(policyRef) { + CFRelease(policyRef); + } + return ortn; +} + +int certVerify(CertVerifyArgs *vfyArgs) +{ + if(vfyArgs->version != CERT_VFY_ARGS_VERS) { + printf("***CertVerifyArgs.Version mismatch. Clean and rebuild.\n"); + return -1; + } + + /* main job is building a CSSM_TP_VERIFY_CONTEXT and its components */ + CSSM_TP_VERIFY_CONTEXT vfyCtx; + CSSM_TP_CALLERAUTH_CONTEXT authCtx; + CSSM_TP_VERIFY_CONTEXT_RESULT vfyResult; + CSSM_APPLE_TP_SSL_OPTIONS sslOpts; + CSSM_APPLE_TP_SMIME_OPTIONS smimeOpts; + + 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; + */ + /* up to 3 policies */ + CSSM_FIELD policyIds[3]; + CSSM_FIELD *policyPtr = &policyIds[0]; + uint32 numPolicies = 0; + memset(policyIds, 0, 3 * sizeof(CSSM_FIELD)); + + switch(vfyArgs->vfyPolicy) { + case CVP_SSL: + case CVP_IPSec: + if(vfyArgs->vfyPolicy == CVP_SSL) { + policyPtr->FieldOid = CSSMOID_APPLE_TP_SSL; + } + else { + policyPtr->FieldOid = CSSMOID_APPLE_TP_IP_SEC; + } + /* otherwise these policies are identical */ + /* sslOpts is optional */ + if((vfyArgs->sslHost != NULL) || vfyArgs->sslClient) { + memset(&sslOpts, 0, sizeof(sslOpts)); + sslOpts.Version = CSSM_APPLE_TP_SSL_OPTS_VERSION; + sslOpts.ServerName = vfyArgs->sslHost; + if(vfyArgs->sslHost != NULL) { + sslOpts.ServerNameLen = strlen(vfyArgs->sslHost) + 1; + } + if(vfyArgs->sslClient) { + sslOpts.Flags |= CSSM_APPLE_TP_SSL_CLIENT; + } + policyPtr->FieldValue.Data = (uint8 *)&sslOpts; + policyPtr->FieldValue.Length = sizeof(sslOpts); + } + break; + case CVP_SMIME: + case CVP_iChat: + if(vfyArgs->vfyPolicy == CVP_SMIME) { + policyPtr->FieldOid = CSSMOID_APPLE_TP_SMIME; + } + else { + policyPtr->FieldOid = CSSMOID_APPLE_TP_ICHAT; + } + /* otherwise these policies are identical */ + /* smimeOpts is optional */ + if(vfyArgs->senderEmail != NULL) { + smimeOpts.Version = CSSM_APPLE_TP_SMIME_OPTS_VERSION; + smimeOpts.IntendedUsage = vfyArgs->intendedKeyUse; + smimeOpts.SenderEmail = vfyArgs->senderEmail; + smimeOpts.SenderEmailLen = strlen(vfyArgs->senderEmail) + 1; + policyPtr->FieldValue.Data = (uint8 *)&smimeOpts; + policyPtr->FieldValue.Length = sizeof(smimeOpts); + } + break; + case CVP_Basic: + policyPtr->FieldOid = CSSMOID_APPLE_X509_BASIC; + break; + case CVP_SWUpdateSign: + /* no options */ + policyPtr->FieldOid = CSSMOID_APPLE_TP_SW_UPDATE_SIGNING; + break; + case CVP_ResourceSigning: + /* no options */ + policyPtr->FieldOid = CSSMOID_APPLE_TP_RESOURCE_SIGN; + break; + case CVP_PKINIT_Server: + /* no options */ + policyPtr->FieldOid = CSSMOID_APPLE_TP_PKINIT_SERVER; + break; + case CVP_PKINIT_Client: + /* no options */ + policyPtr->FieldOid = CSSMOID_APPLE_TP_PKINIT_CLIENT; + break; + case CVP_AppleCodeSigning: + /* no options */ + policyPtr->FieldOid = CSSMOID_APPLE_TP_CODE_SIGNING; + break; + case CVP_PackageSigning: + /* no options */ + policyPtr->FieldOid = CSSMOID_APPLE_TP_PACKAGE_SIGNING; + break; + default: + printf("***certVerify: bogus vfyPolicy\n"); + return 1; + } + if(verifySecPolicy(&policyPtr->FieldOid)) { + return -1; + } + policyPtr++; + numPolicies++; + + CSSM_APPLE_TP_CRL_OPTIONS crlOpts; + if((vfyArgs->revokePolicy == CRP_CRL) || (vfyArgs->revokePolicy == CRP_CRL_OCSP)) { + memset(&crlOpts, 0, sizeof(crlOpts)); + policyPtr->FieldOid = CSSMOID_APPLE_TP_REVOCATION_CRL; + + crlOpts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; + crlOpts.CrlFlags = 0; + crlOpts.crlStore = NULL; + policyPtr->FieldValue.Data = (uint8 *)&crlOpts; + policyPtr->FieldValue.Length = sizeof(crlOpts); + if(vfyArgs->requireCrlForAll) { + crlOpts.CrlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_PER_CERT; + } + if(vfyArgs->crlNetFetchEnable) { + crlOpts.CrlFlags |= CSSM_TP_ACTION_FETCH_CRL_FROM_NET; + } + if(vfyArgs->requireCrlIfPresent) { + crlOpts.CrlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT; + } + crlOpts.crlStore = vfyArgs->crlDlDb; + policyPtr++; + numPolicies++; + } + + CSSM_APPLE_TP_OCSP_OPTIONS ocspOpts; + CSSM_DATA respUriData; + CSSM_DATA respCertData = {vfyArgs->responderCertLen, + (uint8 *)vfyArgs->responderCert}; + if((vfyArgs->revokePolicy == CRP_OCSP) || (vfyArgs->revokePolicy == CRP_CRL_OCSP)) { + memset(&ocspOpts, 0, sizeof(ocspOpts)); + policyPtr->FieldOid = CSSMOID_APPLE_TP_REVOCATION_OCSP; + + crlOpts.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION; + policyPtr->FieldValue.Data = (uint8 *)&ocspOpts; + policyPtr->FieldValue.Length = sizeof(ocspOpts); + if(vfyArgs->requireOcspForAll) { + ocspOpts.Flags |= CSSM_TP_ACTION_OCSP_REQUIRE_PER_CERT; + } + if(vfyArgs->requireOcspIfPresent) { + ocspOpts.Flags |= CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT; + } + if(vfyArgs->disableCache) { + ocspOpts.Flags |= (CSSM_TP_ACTION_OCSP_CACHE_READ_DISABLE | + CSSM_TP_ACTION_OCSP_CACHE_WRITE_DISABLE); + } + if(vfyArgs->disableOcspNet) { + ocspOpts.Flags |= CSSM_TP_ACTION_OCSP_DISABLE_NET; + } + if(vfyArgs->generateOcspNonce) { + ocspOpts.Flags |= CSSM_TP_OCSP_GEN_NONCE; + } + if(vfyArgs->requireOcspRespNonce) { + ocspOpts.Flags |= CSSM_TP_OCSP_REQUIRE_RESP_NONCE; + } + if(vfyArgs->responderURI != NULL) { + respUriData.Data = (uint8 *)vfyArgs->responderURI; + respUriData.Length = strlen(vfyArgs->responderURI); + ocspOpts.LocalResponder = &respUriData; + } + if(vfyArgs->responderCert != NULL) { + ocspOpts.LocalResponderCert = &respCertData; + } + /* other OCSP options here */ + policyPtr++; + numPolicies++; + } + + authCtx.Policy.NumberOfPolicyIds = numPolicies; + + authCtx.Policy.PolicyIds = policyIds; + authCtx.Policy.PolicyControl = NULL; + + authCtx.VerifyTime = vfyArgs->vfyTime; // may be NULL + authCtx.VerificationAbortOn = CSSM_TP_STOP_ON_POLICY; + authCtx.CallbackWithVerifiedCert = NULL; + + /* + * DLDBs - the caller's optional set, plus two more we open + * if trust settings are enabled and we're told to use system + * anchors. (System anchors are normally passed in via + * authCtx.AnchorCerts; they're passed in as DLDBs when + * using TrustSettings.) + */ + uint32 totalNumDbs = 0; + uint32 numCallerDbs = 0; + CSSM_BOOL weOpenedDbs = CSSM_FALSE; + if(vfyArgs->dlDbList != NULL) { + totalNumDbs = numCallerDbs = vfyArgs->dlDbList->NumHandles; + } + if(vfyArgs->useTrustSettings && vfyArgs->useSystemAnchors) { + /* we'll cook up two more DBs and possible append them */ + totalNumDbs += 2; + weOpenedDbs = CSSM_TRUE; + } + CSSM_DL_DB_HANDLE dlDbHandles[totalNumDbs]; + CSSM_DL_DB_LIST dlDbList; + CSSM_DL_HANDLE dlHand = 0; + for(unsigned dex=0; dexdlDbList->DLDBHandle[dex]; + } + if(weOpenedDbs) { + /* get a DL handle, somehow */ + if(numCallerDbs == 0) { + /* new DL handle */ + dlHand = cuDlStartup(); + dlDbHandles[0].DLHandle = dlHand; + dlDbHandles[1].DLHandle = dlHand; + } + else { + /* use the same one caller passed in */ + dlDbHandles[numCallerDbs].DLHandle = dlDbHandles[0].DLHandle; + dlDbHandles[numCallerDbs + 1].DLHandle = dlDbHandles[0].DLHandle; + } + /* now open two DBs */ + dlDbHandles[numCallerDbs].DBHandle = + cuDbStartupByName(dlDbHandles[numCallerDbs].DLHandle, + (char *)ADMIN_CERT_STORE_PATH, CSSM_FALSE, CSSM_TRUE); + dlDbHandles[numCallerDbs + 1].DBHandle = + cuDbStartupByName(dlDbHandles[numCallerDbs].DLHandle, + (char *)SYSTEM_ROOT_STORE_PATH, CSSM_FALSE, CSSM_TRUE); + } + dlDbList.DLDBHandle = dlDbHandles; + dlDbList.NumHandles = totalNumDbs; + authCtx.DBList = &dlDbList; + + CFArrayRef cfAnchors = NULL; + CSSM_DATA *cssmAnchors = NULL; + unsigned numAnchors = 0; + + if(vfyArgs->useSystemAnchors) { + if(!vfyArgs->useTrustSettings) { + /* standard system anchors - ingore error, I'm sure the + * current test will eventually fail */ + getSystemAnchors(&cfAnchors, &cssmAnchors, &numAnchors); + authCtx.NumberOfAnchorCerts = numAnchors; + authCtx.AnchorCerts = cssmAnchors; + } + } + else { + /* anchors are our caller's roots */ + if(vfyArgs->roots) { + authCtx.NumberOfAnchorCerts = vfyArgs->roots->numBlobs(); + authCtx.AnchorCerts = vfyArgs->roots->blobList(); + } + } + authCtx.CallerCredentials = NULL; + + if(vfyArgs->crls) { + /* cook up CRL group */ + CSSM_CRLGROUP_PTR cssmCrls = &vfyCtx.Crls; + cssmCrls->CrlType = CSSM_CRL_TYPE_X_509v1; + cssmCrls->CrlEncoding = CSSM_CRL_ENCODING_DER; + cssmCrls->NumberOfCrls = vfyArgs->crls->numBlobs(); + cssmCrls->GroupCrlList.CrlList = vfyArgs->crls->blobList(); + cssmCrls->CrlGroupType = CSSM_CRLGROUP_DATA; + } + + /* CSSM_APPLE_TP_ACTION_DATA */ + CSSM_APPLE_TP_ACTION_DATA tpAction; + tpAction.Version = CSSM_APPLE_TP_ACTION_VERSION; + tpAction.ActionFlags = 0; + if(vfyArgs->leafCertIsCA) { + tpAction.ActionFlags |= CSSM_TP_ACTION_LEAF_IS_CA; + } + if(vfyArgs->certNetFetchEnable) { + tpAction.ActionFlags |= CSSM_TP_ACTION_FETCH_CERT_FROM_NET; + } + if(vfyArgs->allowExpiredRoot) { + tpAction.ActionFlags |= CSSM_TP_ACTION_ALLOW_EXPIRED_ROOT; + } + if(!vfyArgs->allowUnverified) { + tpAction.ActionFlags |= CSSM_TP_ACTION_REQUIRE_REV_PER_CERT; + } + if(vfyArgs->useTrustSettings) { + tpAction.ActionFlags |= CSSM_TP_ACTION_TRUST_SETTINGS; + } + if(vfyArgs->implicitAnchors) { + tpAction.ActionFlags |= CSSM_TP_ACTION_IMPLICIT_ANCHORS; + } + + /* CSSM_TP_VERIFY_CONTEXT */ + vfyCtx.ActionData.Data = (uint8 *)&tpAction; + vfyCtx.ActionData.Length = sizeof(tpAction); + + vfyCtx.Action = CSSM_TP_ACTION_DEFAULT; + vfyCtx.Cred = &authCtx; + + /* cook up cert group */ + CSSM_CERTGROUP cssmCerts; + cssmCerts.CertType = CSSM_CERT_X_509v3; + cssmCerts.CertEncoding = CSSM_CERT_ENCODING_DER; + cssmCerts.NumCerts = vfyArgs->certs->numBlobs(); + cssmCerts.GroupList.CertList = vfyArgs->certs->blobList(); + cssmCerts.CertGroupType = CSSM_CERTGROUP_DATA; + + int ourRtn = 0; + CSSM_RETURN crtn = CSSM_TP_CertGroupVerify(vfyArgs->tpHand, + vfyArgs->clHand, + vfyArgs->cspHand, + &cssmCerts, + &vfyCtx, + &vfyResult); + if(vfyArgs->expectedErrStr != NULL) { + const char *actRtn; + if(crtn == CSSM_OK) { + /* cssmErrorString munges this to "[ok]" */ + actRtn = "CSSM_OK"; + } + else { + actRtn = cssmErrToStr(crtn); + } + char *found = strstr(actRtn, vfyArgs->expectedErrStr); + if(found) { + if(!vfyArgs->quiet) { + printf("...%s received as expected\n", vfyArgs->expectedErrStr); + } + } + else { + printf("***CSSM_TP_CertGroupVerify error\n"); + printf(" expected rtn : %s\n", vfyArgs->expectedErrStr); + printf(" actual rtn : %s\n", actRtn); + ourRtn = 1; + } + } + else { + if(crtn) { + if(!vfyArgs->quiet) { + printError("CSSM_TP_CertGroupVerify", crtn); + } + ourRtn = 1; + } + else if(!vfyArgs->quiet) { + printf("...verify successful\n"); + } + } + if(vfyArgs->certErrors) { + if(vfyCertErrors(&vfyResult, vfyArgs->numCertErrors, vfyArgs->certErrors, + vfyArgs->quiet)) { + ourRtn = 1; + } + } + if(vfyArgs->certStatus) { + if(vfyCertStatus(&vfyResult, vfyArgs->numCertStatus, vfyArgs->certStatus, + vfyArgs->quiet)) { + ourRtn = 1; + } + } + if(vfyArgs->verbose) { + dumpVfyResult(&vfyResult); + } + freeVfyResult(&vfyResult); + if(weOpenedDbs) { + /* close the DBs and maybe the DL we opened */ + CSSM_DL_DbClose(dlDbHandles[numCallerDbs]); + CSSM_DL_DbClose(dlDbHandles[numCallerDbs + 1]); + if(dlHand != 0) { + cuDlDetachUnload(dlHand); + } + } + if(cfAnchors) { + CFRelease(cfAnchors); + } + if(cssmAnchors) { + free(cssmAnchors); + } + return ourRtn; +} + +unsigned hexDigit(char digit) +{ + if((digit >= '0') && (digit <= '9')) { + return digit - '0'; + } + if((digit >= 'a') && (digit <= 'f')) { + return 10 + digit - 'a'; + } + if((digit >= 'A') && (digit <= 'F')) { + return 10 + digit - 'A'; + } + printf("***BAD HEX DIGIT (%c)\n", digit); + return 0; +} + +/* convert ASCII string in hex to unsigned */ +unsigned hexToBin(const char *hex) +{ + unsigned rtn = 0; + const char *cp = hex; + if((cp[0] == '0') && (cp[1] == 'x')) { + cp += 2; + } + if(strlen(cp) > 8) { + printf("***BAD HEX STRING (%s)\n", cp); + return 0; + } + while(*cp) { + rtn <<= 4; + rtn += hexDigit(*cp); + cp++; + } + return rtn; +} + +/* + * A slightly simplified version of certVerify: + * -- no CRLs (includes allowUnverified = CSSM_FALSE) + * -- revokePOlicy = None + * -- no DlDbs + * -- no net fetch + * -- time = now. + */ +int certVerifySimple( + CSSM_TP_HANDLE tpHand, + CSSM_CL_HANDLE clHand, + CSSM_CSP_HANDLE cspHand, + BlobList &certs, + BlobList &roots, + CSSM_BOOL useSystemAnchors, + CSSM_BOOL leafCertIsCA, + CSSM_BOOL allowExpiredRoot, + CertVerifyPolicy vfyPolicy, + const char *sslHost, // optional, SSL policy + CSSM_BOOL sslClient, // normally server side + const char *senderEmail, // optional, SMIME + CE_KeyUsage intendedKeyUse, // optional, SMIME only + const char *expectedErrStr,// e.g., + // "CSSMERR_APPLETP_CRL_NOT_TRUSTED" + + /* + * expected per-cert errors + * format is certNum:errorString + * e.g., "1:CSSMERR_APPLETP_CRL_NOT_TRUSTED" + */ + unsigned numCertErrors, + const char **certErrors, // per-cert status + + /* + * Expected per-cert status (CSSM_TP_APPLE_EVIDENCE_INFO.StatusBits) + * format is certNum:status_in_hex + * e.g., "1:0x18", leading 0x optional + */ + unsigned numCertStatus, + const char **certStatus, + CSSM_BOOL useTrustSettings, + CSSM_BOOL quiet, + CSSM_BOOL verbose) +{ + CertVerifyArgs vfyArgs; + memset(&vfyArgs, 0, sizeof(vfyArgs)); + vfyArgs.version = CERT_VFY_ARGS_VERS; + vfyArgs.tpHand = tpHand; + vfyArgs.clHand = clHand; + vfyArgs.cspHand = cspHand; + vfyArgs.certs = &certs; + vfyArgs.roots = &roots; + vfyArgs.useSystemAnchors = useSystemAnchors; + vfyArgs.useTrustSettings = useTrustSettings; + vfyArgs.leafCertIsCA = leafCertIsCA; + vfyArgs.allowExpiredRoot = allowExpiredRoot; + vfyArgs.vfyPolicy = vfyPolicy; + vfyArgs.sslHost = sslHost; + vfyArgs.sslClient = sslClient; + vfyArgs.senderEmail = senderEmail; + vfyArgs.intendedKeyUse = intendedKeyUse; + vfyArgs.allowUnverified = CSSM_TRUE; + vfyArgs.expectedErrStr = expectedErrStr; + vfyArgs.numCertErrors = numCertErrors; + vfyArgs.certErrors = certErrors; + vfyArgs.numCertStatus = numCertStatus; + vfyArgs.certStatus = certStatus; + vfyArgs.quiet = quiet; + vfyArgs.verbose = verbose; + return certVerify(&vfyArgs); +} +