X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SecurityTests/clxutils/secTime/secTime.cpp diff --git a/SecurityTests/clxutils/secTime/secTime.cpp b/SecurityTests/clxutils/secTime/secTime.cpp new file mode 100644 index 00000000..c34efc0e --- /dev/null +++ b/SecurityTests/clxutils/secTime/secTime.cpp @@ -0,0 +1,739 @@ +/* + * secTime.cpp - measure performance of Sec* ops + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Hard coded test params + */ + +/* + * The keychain we open and search for certs. + * MUST exist in ~/Library/Keychains. + * YOU can create it with + * % certtool c k=secTimeKc c p=secTimeKc Z + */ +#define ST_KC_NAME "secTimeKc" + +/* + * Certs to verify with SecTrust. We have a variety because the timing on + * this test is highly dependent on the position of the verifying anchor + * within the system anchors list. (This does not apply to Trust Settings). + */ +typedef struct { + const char *certFileName; + const char *hostName; +} CertToVerify; + +static const CertToVerify certsToVerify[] = +{ + { + /* issuer: Secure Server Certification Authority */ + "amazon_v3.100.cer", + "www.amazon.com" + }, + { + /* issuer: Equifax Secure Certificate Authority */ + "firstamlink.cer", + "www.firstamlink.com" + }, +}; + +#define NUM_ST_CERTS (sizeof(certsToVerify) / sizeof(certsToVerify[0])) + +/* explicit anchor for certsToVerify[0] */ +#define ST_ANCHOR_NAME "SecureServer.509.cer" /* verifies ST_CERT_HOST */ + +/* + * Cert chain for cgv3*() + */ +#define THAWTE_LEAF "dmitchThawte.cer" +#define THAWTE_CA "ThawteCA.cer" +#define THAWTE_ROOT "ThawteRoot.cer" + +static void usage(char **argv) +{ + printf("Usage: %s [option ...]\n", argv[0]); + printf("Options:\n"); + printf(" t=testspec; default=all\n"); + printf(" test specs: o keychainOpen\n"); + printf(" s keychainSearch\n"); + printf(" e secTrustEvaluate\n"); + printf(" k SecKeychainCopySearchList\n"); + printf(" v TP CertGroupVerify, system anchor\n"); + printf(" V TP CertGroupVerify, explicit anchor\n"); + printf(" 3 TP CertGroupVerify, 3 certs w/anchor\n"); + printf(" l=loops (only valid if testspec is given)\n"); + exit(1); +} + +static void printSecErr( + const char *op, + OSStatus ortn) +{ + printf("%s returned %ld\n", op, (unsigned long)ortn); +} + +/* + * Struct passed around to test-specific functions. + */ +typedef struct { + const char *testName; + void *testPriv; +} TestParams; + +/* + * Each subtest has three functions - init, run, cleanup, called out + * from main(). + * + * Init's job is one-time setup - open files, setup buffers, etc. + * PErsistent state can be saved in TestParams->testPriv. + */ +typedef OSStatus (*testInitFcn)(TestParams *testParams); + +/* + * Run's job is to perform 1 iteration with as + * little overhead as possible. Return the time spect actually + * doing the deed in *timeSpent. + */ +typedef OSStatus (*testRunFcn)(TestParams *testParams, + unsigned loopNum, + CFAbsoluteTime *timeSpent); + +/* + * CLeanu up any resources allocd in init. + */ +typedef OSStatus (*testCleanupFcn)(TestParams *testParams); + +/* + * Static declaration of a test + */ +typedef struct { + const char *testName; + unsigned loops; + testInitFcn init; + testRunFcn run; + testCleanupFcn cleanup; + char testSpec; // for t=xxx cmd line opt +} TestDefs; + +#pragma mark ---- Individual tests ---- + +#ifdef use_these_as_a_template + +static OSStatus xxxInit( + TestParams *testParams) +{ + return noErr; +} + +static OSStatus xxRun( + TestParams *testParams, + unsigned loopNum, + CFAbsoluteTime *timeSpent) +{ + CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); + /* do the op here */ + *timeSpent = CFAbsoluteTimeGetCurrent() - startTime; + return noErr; +} + +static OSStatus xxxCleanup( + TestParams *testParams) +{ + return noErr; +} +#endif /* template */ + +#pragma mark -- keychain open -- + +static OSStatus kcOpenInit( + TestParams *testParams) +{ + return noErr; +} + +static OSStatus kcOpenRun( + TestParams *testParams, + unsigned loopNum, + CFAbsoluteTime *timeSpent) +{ + SecKeychainRef kcRef; + SecKeychainStatus status; + + CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); + OSStatus ortn = SecKeychainOpen(ST_KC_NAME, &kcRef); + if(ortn) { + printSecErr("SecKeychainOpen", ortn); + return ortn; + } + ortn = SecKeychainGetStatus(kcRef, &status); + if(ortn) { + printSecErr("SecKeychainGetStatus", ortn); + CFRelease(kcRef); + if(errSecNoSuchKeychain == ortn) { + printf("The keychain %s does not exist. Please create it" + " and populate it like so:\n", ST_KC_NAME); + printf(" certtool c k=%s c p=%s Z\n", + ST_KC_NAME, ST_KC_NAME); + } + return ortn; + } + CFAbsoluteTime endTime = CFAbsoluteTimeGetCurrent(); + *timeSpent = endTime - startTime; + CFRelease(kcRef); + return noErr; +} + +static OSStatus kcOpenCleanup( + TestParams *testParams) +{ + return noErr; +} + +#pragma mark -- keychain lookup -- + +/* + * Private *testPriv is a kcRef. + */ +static OSStatus kcSearchInit( + TestParams *testParams) +{ + SecKeychainRef kcRef; + OSStatus ortn = SecKeychainOpen(ST_KC_NAME, &kcRef); + if(ortn) { + printSecErr("SecKeychainOpen", ortn); + return ortn; + } + testParams->testPriv = (void *)kcRef; + return noErr; +} + +static OSStatus kcSearchRun( + TestParams *testParams, + unsigned loopNum, + CFAbsoluteTime *timeSpent) +{ + SecKeychainRef kcRef = (SecKeychainRef)testParams->testPriv; + SecKeychainSearchRef srchRef = NULL; + SecKeychainItemRef certRef = NULL; + CFAbsoluteTime endTime; + CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); + + /* search for any cert */ + OSStatus ortn = SecKeychainSearchCreateFromAttributes(kcRef, + kSecCertificateItemClass, + NULL, // no attrs + &srchRef); + if(ortn) { + printSecErr("SecKeychainSearchCreateFromAttributes", ortn); + return ortn; + } + ortn = SecKeychainSearchCopyNext(srchRef, &certRef); + if(ortn) { + printSecErr("SecKeychainSearchCopyNext", ortn); + goto done; + } + endTime = CFAbsoluteTimeGetCurrent(); + *timeSpent = endTime - startTime; +done: + if(srchRef) { + CFRelease(srchRef); + } + if(certRef) { + CFRelease(certRef); + } + return ortn; +} + + +static OSStatus kcSearchCleanup( + TestParams *testParams) +{ + SecKeychainRef kcRef = (SecKeychainRef)testParams->testPriv; + CFRelease(kcRef); + return noErr; +} + +#pragma mark -- SecTrustEvaluate -- + +/* + * Priv data is an array of SecCertificateRef containing certs to evaluate. + * Each run evaluates one of them. + */ +static OSStatus secTrustInit( + TestParams *testParams) +{ + unsigned char *certData; + unsigned certLen; + CSSM_DATA cdata; + + SecCertificateRef *certRefs; + + certRefs = (SecCertificateRef *)malloc( + sizeof(SecCertificateRef) * NUM_ST_CERTS); + + for(unsigned dex=0; dextestPriv = certRefs; + return noErr; +} + +static OSStatus secTrustRun( + TestParams *testParams, + unsigned loopNum, + CFAbsoluteTime *timeSpent) +{ + unsigned whichDex = loopNum % NUM_ST_CERTS; + SecCertificateRef *certRefs = (SecCertificateRef *)testParams->testPriv; + SecCertificateRef certRef = certRefs[whichDex]; + + /* + * We measure the whole enchilada, that's what SecureTransport + * has to do + */ + CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); + + CFMutableArrayRef certs; + certs = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks); + CFArrayInsertValueAtIndex(certs, 0, certRef); + + SecPolicyRef policy = NULL; + SecPolicySearchRef policySearch = NULL; + + OSStatus ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3, + &CSSMOID_APPLE_TP_SSL, + NULL, // policy opts + &policySearch); + if(ortn) { + printSecErr("SecPolicySearchCreate", ortn); + return ortn; + } + + ortn = SecPolicySearchCopyNext(policySearch, &policy); + if(ortn) { + printSecErr("SecPolicySearchCopyNext", ortn); + return ortn; + } + CFRelease(policySearch); + + SecTrustRef secTrust; + ortn = SecTrustCreateWithCertificates(certs, policy, &secTrust); + if(ortn) { + printSecErr("SecTrustCreateWithCertificates", ortn); + return ortn; + } + /* no action data for now */ + + SecTrustResultType secTrustResult; + ortn = SecTrustEvaluate(secTrust, &secTrustResult); + if(ortn) { + printSecErr("SecTrustEvaluate", ortn); + return ortn; + } + + CFRelease(certs); + CFRelease(secTrust); + CFRelease(policy); + + CFAbsoluteTime endTime = CFAbsoluteTimeGetCurrent(); + *timeSpent = endTime - startTime; + + return noErr; +} + +static OSStatus secTrustCleanup( + TestParams *testParams) +{ + SecCertificateRef *certRefs = (SecCertificateRef*)testParams->testPriv; + for(unsigned dex=0; dextpHand = tpStartup(); + cgvParams->clHand = clStartup(); + cgvParams->cspHand = cspStartup(); + for(unsigned dex=0; dexcerts[dex] = new BlobList(); + cgvParams->certs[dex]->addFile(certsToVerify[dex].certFileName); + } + cgvParams->anchors = NULL; + testParams->testPriv = cgvParams; + return noErr; +} + +static OSStatus cgvRun( + TestParams *testParams, + unsigned loopNum, + CFAbsoluteTime *timeSpent) +{ + CgvParams *cgvParams = (CgvParams *)testParams->testPriv; + BlobList nullList; + unsigned whichDex = loopNum % NUM_ST_CERTS; + BlobList *certBlob = cgvParams->certs[whichDex]; + + CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); + int rtn = certVerifySimple( + cgvParams->tpHand, + cgvParams->clHand, + cgvParams->cspHand, + *certBlob, // contains one cert, the subject + nullList, // roots + CSSM_TRUE, // useSystemAnchors + CSSM_FALSE, // leafCertIsCa + CSSM_FALSE, // allow expired root + CVP_SSL, + certsToVerify[whichDex].hostName, + CSSM_FALSE, // sslClient + NULL, // senderEmail + 0, // key use + NULL, // expected error str + 0, // numCertErrors + NULL, + 0, // numCertStatus + NULL, + CSSM_FALSE, // trustSettings + CSSM_TRUE, // quiet + CSSM_FALSE); // verbose + *timeSpent = CFAbsoluteTimeGetCurrent() - startTime; + if(rtn) { + printf("***certVerify error\n"); + return (OSStatus)rtn; + } + return noErr; +} + +static OSStatus cgvCleanup( + TestParams *testParams) +{ + CgvParams *cgvParams = (CgvParams *)testParams->testPriv; + CSSM_ModuleDetach(cgvParams->cspHand); + CSSM_ModuleDetach(cgvParams->tpHand); + CSSM_ModuleDetach(cgvParams->clHand); + for(unsigned dex=0; dexcerts[dex]; + } + if(cgvParams->anchors) { + delete(cgvParams->anchors); + } + free(cgvParams); + return noErr; +} + +#pragma mark -- CSSM_TP_CertGroupVerify, explicit anchors -- + +static OSStatus cgvAnchorInit( + TestParams *testParams) +{ + CgvParams *cgvParams = (CgvParams *)malloc(sizeof(CgvParams)); + memset(cgvParams, 0, sizeof(CgvParams)); + cgvParams->tpHand = tpStartup(); + cgvParams->clHand = clStartup(); + cgvParams->cspHand = cspStartup(); + cgvParams->certs[0] = new BlobList(); + cgvParams->certs[0]->addFile(certsToVerify[0].certFileName); + cgvParams->anchors = new BlobList(); + cgvParams->anchors->addFile(ST_ANCHOR_NAME); + testParams->testPriv = cgvParams; + return noErr; +} + +static OSStatus cgvAnchorRun( + TestParams *testParams, + unsigned loopNum, + CFAbsoluteTime *timeSpent) +{ + CgvParams *cgvParams = (CgvParams *)testParams->testPriv; + BlobList nullList; + + CertVerifyArgs vfyArgs; + memset(&vfyArgs, 0, sizeof(vfyArgs)); + vfyArgs.version = CERT_VFY_ARGS_VERS; + + vfyArgs.tpHand = cgvParams->tpHand; + vfyArgs.clHand = cgvParams->clHand; + vfyArgs.cspHand = cgvParams->cspHand; + vfyArgs.certs = cgvParams->certs[0]; + vfyArgs.roots = cgvParams->anchors; + vfyArgs.allowUnverified = CSSM_TRUE; + vfyArgs.vfyPolicy = CVP_SSL; + vfyArgs.revokePolicy = CRP_None; + vfyArgs.sslHost = certsToVerify[0].hostName; + vfyArgs.revokePolicy = CRP_None; + vfyArgs.quiet = CSSM_TRUE; + + CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); + int rtn = certVerify(&vfyArgs); + *timeSpent = CFAbsoluteTimeGetCurrent() - startTime; + if(rtn) { + printf("***certVerify error\n"); + return (OSStatus)rtn; + } + return noErr; +} + +/* cleanup - use cgvCleanup() */ + +#pragma mark -- CSSM_TP_CertGroupVerify, 3 certs with anchor -- + +static OSStatus cgv3Init( + TestParams *testParams) +{ + CgvParams *cgvParams = (CgvParams *)malloc(sizeof(CgvParams)); + memset(cgvParams, 0, sizeof(CgvParams)); + cgvParams->tpHand = tpStartup(); + cgvParams->clHand = clStartup(); + cgvParams->cspHand = cspStartup(); + cgvParams->certs[0] = new BlobList(); + cgvParams->certs[0]->addFile(THAWTE_LEAF); + cgvParams->certs[0]->addFile(THAWTE_CA); + cgvParams->certs[0]->addFile(THAWTE_ROOT); + cgvParams->anchors = new BlobList(); + cgvParams->anchors->addFile(THAWTE_ROOT); + testParams->testPriv = cgvParams; + return noErr; +} + +static OSStatus cgv3Run( + TestParams *testParams, + unsigned loopNum, + CFAbsoluteTime *timeSpent) +{ + CgvParams *cgvParams = (CgvParams *)testParams->testPriv; + BlobList nullList; + + CertVerifyArgs vfyArgs; + memset(&vfyArgs, 0, sizeof(vfyArgs)); + vfyArgs.version = CERT_VFY_ARGS_VERS; + + vfyArgs.tpHand = cgvParams->tpHand; + vfyArgs.clHand = cgvParams->clHand; + vfyArgs.cspHand = cgvParams->cspHand; + vfyArgs.certs = cgvParams->certs[0]; /* that's three certs */ + vfyArgs.roots = cgvParams->anchors; + vfyArgs.allowUnverified = CSSM_TRUE; + vfyArgs.vfyPolicy = CVP_Basic; + vfyArgs.revokePolicy = CRP_None; + vfyArgs.sslHost = certsToVerify[0].hostName; + vfyArgs.revokePolicy = CRP_None; + vfyArgs.quiet = CSSM_TRUE; + + CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); + int rtn = certVerify(&vfyArgs); + *timeSpent = CFAbsoluteTimeGetCurrent() - startTime; + if(rtn) { + printf("***certVerify error\n"); + return (OSStatus)rtn; + } + return noErr; +} + +static OSStatus cgv3Cleanup( + TestParams *testParams) +{ + CgvParams *cgvParams = (CgvParams *)testParams->testPriv; + CSSM_ModuleDetach(cgvParams->cspHand); + CSSM_ModuleDetach(cgvParams->tpHand); + CSSM_ModuleDetach(cgvParams->clHand); + delete cgvParams->certs[0]; + delete(cgvParams->anchors); + free(cgvParams); + return noErr; +} + +#pragma mark ---- Static array of all tests ---- + +static TestDefs testDefs[] = +{ + { "Keychain open", + 100, + kcOpenInit, + kcOpenRun, + kcOpenCleanup, + 'o', + }, + { "Keychain cert search", + 100, + kcSearchInit, + kcSearchRun, + kcSearchCleanup, + 's', + }, + { "SecTrustEvaluate", + 100, + secTrustInit, + secTrustRun, + secTrustCleanup, + 'e', + }, + { "TP CertGroupVerify, system anchors", + 100, + cgvInit, + cgvRun, + cgvCleanup, + 'v', + }, + { "TP CertGroupVerify, explicit anchor", + 100, + cgvAnchorInit, + cgvAnchorRun, + cgvCleanup, + 'V', + }, + { "TP CertGroupVerify, 3 certs with anchor", + 100, + cgv3Init, + cgv3Run, + cgv3Cleanup, + '3', + }, + { "SecKeychainCopySearchList", + 100, + kcCSLInit, + kcCSLRun, + kcCSLCleanup, + 'k', + }, +}; + +#define NUM_TESTS (sizeof(testDefs) / sizeof(testDefs[0])) + +int main(int argc, char **argv) +{ + TestParams testParams; + TestDefs *testDef; + OSStatus ortn; + int arg; + char *argp; + unsigned cmdLoops = 0; // can be specified in cmd line + // if not, use TestDefs.loops + char testSpec = '\0'; // allows specification of one test + // otherwise run all + + for(arg=1; argtestSpec != testSpec)) { + continue; + } + printf("%s:\n", testDef->testName); + ortn = testDef->init(&testParams); + if(ortn) { + exit(1); + } + if(cmdLoops) { + /* user specified */ + loopCount = cmdLoops; + } + else { + /* default */ + loopCount = testDef->loops; + } + CFAbsoluteTime totalTime = 0; + CFAbsoluteTime thisTime; + for(unsigned loop=0; looprun(&testParams, loop, &thisTime); + if(ortn) { + exit(1); + } + totalTime += thisTime; + } + testDef->cleanup(&testParams); + printf(" %3.2f ms per op\n", (totalTime / loopCount) * 1000.0); + } + return 0; +}