+++ /dev/null
-/*
- * cgVerify.cpp - basic test of TP's CertGroupVerify
- *
- * cook up array of n key pairs;
- * cook up cert chain to go with them;
- * main test loop {
- * numCerts = total # of incoming certs;
- * test one of four or five "expected result" cases {
- * case root in certGroup but not found in AnchorCerts:
- * certGroup = tpMakeRandCertGroup(certs[0..numCerts-1];
- * anchorCerts = tpMakeRandCertGroup[certs[0...numCerts-2];
- * expErr = CSSMERR_TP_INVALID_ANCHOR_CERT;
- * expEvidenceSize = numCerts;
- * case root in certGroup, found a copy in AnchorCerts:
- * certGroup = tpMakeRandCertGroup(certs[0..numCerts-1];
- * anchorCerts = tpMakeRandCertGroup[certs[0...numCerts-1];
- * expErr = CSSM_OK;
- * expEvidenceSize = numCerts;
- * case verified by an AnchorCert:
- * n = rand(1, numCerts-2);
- * certGroup = tpMakeRandCertGroup(certs[0..n]);
- * anchorCerts = tpMakeRandCertGroup[certs[0...numCerts-2];
- * expErr = CSSM_OK;
- * expEvidenceSize = n+2;
- * case no root found:
- * n = rand(1, numCerts-3);
- * certGroup = tpMakeRandCertGroup(certs[0..n]);
- * anchorCerts = tpMakeRandCertGroup[certs[n+2...numCerts-2];
- * anchorCerts may be empty....
- * expErr = CSSMERR_TP_NOT_TRUSTED;
- * expEvidenceSize = n+1;
- * case incomplete public key (DSA only):
- * root public keys is incomplete;
- * certGroup = tpMakeRandCertGroup(certs[0..numCerts-1];
- * anchorCerts = tpMakeRandCertGroup[certs[0...numCerts-1];
- * expErr = CSSM_OK;
- * expEvidenceSize = numCerts;
- * }
- * result = certGroupVerify();
- * verify expected result and getError();
- * delete certs from DB;
- * }
- */
-
-#include <Security/cssm.h>
-#include <utilLib/common.h>
-#include <utilLib/cspwrap.h>
-#include <clAppUtils/clutils.h>
-#include <clAppUtils/tpUtils.h>
-#include <clAppUtils/timeStr.h>
-#include <utilLib/nssAppUtils.h>
-#include <security_cdsa_utils/cuFileIo.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <Security/oidsalg.h>
-
-#define NUM_CERTS_DEF 10
-#define KEYGEN_ALG_DEF CSSM_ALGID_RSA
-#define SIG_ALG_DEF CSSM_ALGID_SHA1WithRSA
-#define LOOPS_DEF 10
-#define SECONDS_TO_LIVE (60 * 60 * 24) /* certs are valid for this long */
-//#define SECONDS_TO_LIVE 5
-
-#define CERT_IN_DB 1
-#define DB_NAME "cgVerify.db"
-#define DSA_PARAM_FILE "dsaParam512.der"
-
-/*
- * How we define the "expected result".
- */
-typedef enum {
- ER_InvalidAnchor, // root in certGroup, not found in AnchorCerts
- ER_RootInCertGroup, // root in certGroup, copy in AnchorCerts
- ER_AnchorVerify, // end of chain verified by an anchor
- ER_NoRoot, // no root, no anchor verify
- ER_IncompleteKey // un-completable public key (all keys are partial), DSA
- // ONLY
-} ExpectResult;
-
-static void usage(char **argv)
-{
- printf("Usage: %s [options]\n", argv[0]);
- printf(" Options:\n");
- printf(" n=numCerts; default = %d\n", NUM_CERTS_DEF);
- printf(" l=loops; default=%d; 0=forever\n", LOOPS_DEF);
- printf(" a=alg (f=FEE/MD5, F=FEE/SHA1, e=FEE/ECDSA, s=RSA/SHA1, m=RSA/MD5,\n");
- printf(" d=DSA, 4=RSA/SHA224, 6=RSA/SHA256, 3=RSA/SHA384, 5=RSA/SHA512,\n");
- printf(" E=ANSI/ECDSA, 7=ECDSA/SHA256; default = RSA/SHA1\n");
- printf(" k=keySizeInBits\n");
- printf(" d(isable DB)\n");
- printf(" P(ause on each loop)\n");
- printf(" N (no partial pub keys)\n");
- printf(" v(erbose)\n");
- printf(" q(uiet)\n");
- printf(" h(elp)\n");
- exit(1);
-}
-
-static int doTest(
- CSSM_TP_HANDLE tpHand,
- CSSM_CL_HANDLE clHand,
- CSSM_CSP_HANDLE cspHand,
- CSSM_DL_DB_HANDLE dlDb,
- CSSM_DATA_PTR certs,
- unsigned numCerts,
- CSSM_KEY_PTR pubKeys, // for partial key detect
- CSSM_BOOL useDb,
- ExpectResult expectResult,
- CSSM_BOOL verbose,
- CSSM_BOOL quiet)
-{
- unsigned cgEnd; // last cert in certGroupFrag
- unsigned anchorStart; // first cert in anchorGroup
- unsigned anchorEnd; // last cert in anchorGroup
- CSSM_CERTGROUP certGroupFrag; // INPUT to CertGroupVerify
- CSSM_CERTGROUP anchorCerts; // ditto
- unsigned die; // random number
- CSSM_DL_DB_LIST dbList;
- CSSM_DL_DB_LIST_PTR dbListPtr;
- CSSM_RETURN expErr; // expected rtn from GroupVfy()
- int rtn = 0;
- const char *expResStr;
- uint32 expEvidenceSize; // expected evidenceSize
- unsigned evidenceSize; // actual evidence size
- CSSM_TP_VERIFY_CONTEXT_RESULT vfyResult;
- CSSM_CERTGROUP_PTR outGrp = NULL;
- CSSM_RETURN crtn;
- CSSM_DL_DB_HANDLE_PTR dlDbPtr;
- unsigned numAnchors;
-
- memset(&vfyResult, 0, sizeof(CSSM_TP_VERIFY_CONTEXT_RESULT));
-
- if(useDb) {
- dlDbPtr = &dlDb;
- dbList.NumHandles = 1;
- dbList.DLDBHandle = &dlDb;
- dbListPtr = &dbList;
- }
- else {
- /* not yet */
- dlDbPtr = NULL;
- dbListPtr = NULL;
- }
-
- /* the four test cases */
- switch(expectResult) {
- case ER_InvalidAnchor:
- /* root in certGroup, not found in AnchorCerts */
- cgEnd = numCerts - 1; // certGroupFrag is the whole pile
- anchorStart = 0; // anchors = all except root
- anchorEnd = numCerts - 2;
- expErr = CSSMERR_TP_INVALID_ANCHOR_CERT;
- expEvidenceSize = numCerts;
- expResStr = "InvalidAnchor (root in certGroup but not in anchors)";
- break;
-
- case ER_RootInCertGroup:
- /* root in certGroup, copy in AnchorCerts */
- cgEnd = numCerts - 1; // certGroupFrag = the whole pile
- anchorStart = 0; // anchors = the whole pile
- anchorEnd = numCerts - 1;
- expErr = CSSM_OK;
- expEvidenceSize = numCerts;
- expResStr = "Good (root in certGroup AND in anchors)";
- break;
-
- case ER_AnchorVerify:
- /* non-root end of chain verified by an anchor */
- /* break chain at random place other than end */
- /* die is the last cert in certGroupFrag */
- die = genRand(0, numCerts-2);
- cgEnd = die; // certGroupFrag up to break point
- anchorStart = 0; // anchors = all
- anchorEnd = numCerts - 1;
- if(pubKeys[die+1].KeyHeader.KeyAttr & CSSM_KEYATTR_PARTIAL) {
- /* this will fail due to an unusable anchor */
- expErr = CSSMERR_TP_CERTIFICATE_CANT_OPERATE;
- expResStr = "Root ONLY in anchors but has partial pub key";
- }
- else {
- expErr = CSSM_OK;
- expResStr = "Good (root ONLY in anchors)";
- }
- /* size = # certs in certGroupFrag, plus one anchor */
- expEvidenceSize = die + 2;
- break;
-
- case ER_NoRoot:
- /* no root, no anchor verify */
- /* break chain at random place other than end */
- /* die is the last cert in certGroupFrag */
- /* skip a cert, then anchors start at die + 2 */
- die = genRand(0, numCerts-2);
- cgEnd = die; // certGroupFrag up to break point
- anchorStart = die + 2; // anchors = n+1...numCerts-2
- // may be empty if n == numCerts-2
- anchorEnd = numCerts - 2;
- if((die != 0) && // partial leaf not reported as partial!
- (pubKeys[die].KeyHeader.KeyAttr & CSSM_KEYATTR_PARTIAL)) {
- /* this will fail due to an unusable cert (this one) */
- expErr = CSSMERR_TP_CERTIFICATE_CANT_OPERATE;
- expResStr = "Not Trusted (no root, no anchor verify), partial";
- }
- else {
- expErr = CSSMERR_TP_NOT_TRUSTED;
- expResStr = "Not Trusted (no root, no anchor verify)";
- }
- expEvidenceSize = die + 1;
- break;
-
- case ER_IncompleteKey:
- /*
- * Anchor has incomplete pub key
- * Root in certGroup, copy in AnchorCerts
- * Avoid putting anchor in certGroupFrag because the TP will think
- * it's NOT a root and it'll show up twice in the evidence - once
- * from certGroupFrag (at which point the search for a root
- * keeps going), and once from Anchors.
- */
- cgEnd = numCerts - 2; // certGroupFrag = the whole pile less the anchor
- anchorStart = 0; // anchors = the whole pile
- anchorEnd = numCerts - 1;
- expErr = CSSMERR_TP_CERTIFICATE_CANT_OPERATE;
- expEvidenceSize = numCerts;
- expResStr = "Partial public key in anchor";
- break;
- }
-
- if(verbose) {
- printf(" ...expectResult = %s\n", expResStr);
- }
-
- /* cook up two cert groups */
- if(verbose) {
- printf(" ...building certGroupFrag from certs[0..%d]\n",
- cgEnd);
- }
- if(tpMakeRandCertGroup(clHand,
- dbListPtr,
- certs, // certGroupFrag always starts at 0
- cgEnd+1, // # of certs
- &certGroupFrag,
- CSSM_TRUE, // firstCertIsSubject
- verbose,
- CSSM_FALSE, // allInDbs
- CSSM_FALSE)) { // skipFirstDb
- printf("Error in tpMakeRandCertGroup\n");
- return 1;
- }
-
- if(verbose) {
- printf(" ...building anchorCerts from certs[%d..%d]\n",
- anchorStart, anchorEnd);
- }
- if(anchorEnd > (numCerts - 1)) {
- printf("anchorEnd overflow\n");
- exit(1);
- }
- if(anchorStart >= anchorEnd) {
- /* legal in some corner cases, ==> empty enchors */
- numAnchors = 0;
- }
- else {
- numAnchors = anchorEnd - anchorStart + 1;
- }
- /* anchors do not go in DB */
- if(tpMakeRandCertGroup(clHand,
- NULL,
- certs + anchorStart,
- numAnchors, // # of certs
- &anchorCerts,
- CSSM_FALSE, // firstCertIsSubject
- verbose,
- CSSM_FALSE, // allInDbs
- CSSM_FALSE)) { // skipFirstDb
- printf("Error in tpMakeRandCertGroup\n");
- return 1;
- }
-
- crtn = tpCertGroupVerify(
- tpHand,
- clHand,
- cspHand,
- dbListPtr,
- &CSSMOID_APPLE_X509_BASIC, // policy
- NULL, // fieldOpts
- NULL, // actionData
- NULL, // policyOpts
- &certGroupFrag,
- anchorCerts.GroupList.CertList, // passed as CSSM_DATA_PTR, not CERTGROUP....
- anchorCerts.NumCerts,
- CSSM_TP_STOP_ON_POLICY,
- NULL, // cssmTimeStr
- &vfyResult);
-
- /* first verify format of result */
- if( (vfyResult.NumberOfEvidences != 3) ||
- (vfyResult.Evidence == NULL) ||
- (vfyResult.Evidence[0].EvidenceForm != CSSM_EVIDENCE_FORM_APPLE_HEADER) ||
- (vfyResult.Evidence[1].EvidenceForm != CSSM_EVIDENCE_FORM_APPLE_CERTGROUP) ||
- (vfyResult.Evidence[2].EvidenceForm != CSSM_EVIDENCE_FORM_APPLE_CERT_INFO) ||
- (vfyResult.Evidence[0].Evidence == NULL) ||
- (vfyResult.Evidence[1].Evidence == NULL) ||
- (vfyResult.Evidence[2].Evidence == NULL)) {
- printf("***Malformed VerifyContextResult\n");
- rtn = testError(quiet);
- if(rtn) {
- return rtn;
- }
- }
- if((vfyResult.Evidence != NULL) && (vfyResult.Evidence[1].Evidence != NULL)) {
- outGrp = (CSSM_CERTGROUP_PTR)vfyResult.Evidence[1].Evidence;
- evidenceSize = outGrp->NumCerts;
- }
- else {
- /* in case no evidence returned */
- evidenceSize = 0;
- }
-
- /* %%% since non-root anchors are permitted as of <rdar://5685316>,
- * the test assumptions have become invalid: these tests generate
- * an anchors list which always includes the full chain, so by
- * definition, the evidence chain will never be longer than 2,
- * since the leaf's issuer is always an anchor.
- * %%% need to revisit and rewrite these tests. -kcm
- */
- if ((evidenceSize > 1) && (evidenceSize < expEvidenceSize) &&
- (crtn == CSSM_OK || crtn == CSSMERR_TP_CERTIFICATE_CANT_OPERATE)) {
- /* ignore, for now */
- expErr = crtn;
- expEvidenceSize = evidenceSize;
- }
-
- if((crtn != expErr) ||
- (evidenceSize != expEvidenceSize)) {
- printf("***Error on expectResult %s\n", expResStr);
- printf(" err %s expErr %s\n",
- cssmErrToStr(crtn), cssmErrToStr(expErr));
- printf(" evidenceSize %d expEvidenceSize %u\n",
- evidenceSize, (unsigned)expEvidenceSize);
- rtn = testError(quiet);
- }
- else {
- rtn = 0;
- }
-
- /* free resources */
- tpFreeCertGroup(&certGroupFrag,
- CSSM_FALSE, // caller malloc'd the actual certs
- CSSM_FALSE); // struct is on stack
- tpFreeCertGroup(&anchorCerts,
- CSSM_FALSE, // caller malloc'd the actual certs
- CSSM_FALSE); // struct is on stack
- freeVfyResult(&vfyResult);
- if(useDb) {
- clDeleteAllCerts(dlDb);
- }
- return rtn;
-}
-
-int main(int argc, char **argv)
-{
- int arg;
- char *argp;
- unsigned loop;
- CSSM_TP_HANDLE tpHand = 0;
- CSSM_CL_HANDLE clHand = 0;
- CSSM_CSP_HANDLE cspHand = 0;
- CSSM_DL_DB_HANDLE dlDbHand = {0, 0};
- ExpectResult expectResult;
- char *notAfterStr;
- char *notBeforeStr;
- unsigned i;
- CSSM_DATA paramData;
- CSSM_DATA_PTR paramDataP = NULL;
- unsigned numTests = 4;
- unsigned len;
-
- /* all three of these are arrays with numCert elements */
- CSSM_KEY_PTR pubKeys = NULL;
- CSSM_KEY_PTR privKeys = NULL;
- CSSM_DATA_PTR certs = NULL;
-
- /* Keys do NOT go in the cert DB */
- CSSM_DL_DB_HANDLE keyDb = {0, 0};
- CSSM_KEY savedRoot; // for ER_IncompleteKey
-
- /*
- * User-spec'd params
- */
- unsigned loops = LOOPS_DEF;
- CSSM_BOOL verbose = CSSM_FALSE;
- CSSM_BOOL quiet = CSSM_FALSE;
- unsigned numCerts = NUM_CERTS_DEF;
- uint32 keyGenAlg = KEYGEN_ALG_DEF;
- uint32 sigAlg = SIG_ALG_DEF;
- #if CERT_IN_DB
- CSSM_BOOL useDb = CSSM_TRUE;
- #else
- CSSM_BOOL useDb = CSSM_FALSE;
- #endif
- CSSM_BOOL doPause = CSSM_FALSE;
- uint32 keySizeInBits = CSP_KEY_SIZE_DEFAULT;
- CSSM_BOOL noPartialKeys = CSSM_FALSE;
- char dbName[100]; /* DB_NAME_pid */
-
- for(arg=1; arg<argc; arg++) {
- argp = argv[arg];
- switch(argp[0]) {
- case 'l':
- loops = atoi(&argp[2]);
- break;
- case 'k':
- keySizeInBits = atoi(&argp[2]);
- break;
- case 'n':
- numCerts = atoi(&argp[2]);
- break;
- case 'v':
- verbose = CSSM_TRUE;
- break;
- case 'q':
- quiet = CSSM_TRUE;
- break;
- case 'a':
- switch(argp[2]) {
- case 'f':
- keyGenAlg = CSSM_ALGID_FEE;
- sigAlg = CSSM_ALGID_FEE_MD5;
- break;
- case 'F':
- keyGenAlg = CSSM_ALGID_FEE;
- sigAlg = CSSM_ALGID_FEE_SHA1;
- break;
- case 'e':
- keyGenAlg = CSSM_ALGID_FEE;
- sigAlg = CSSM_ALGID_SHA1WithECDSA;
- break;
- case 's':
- keyGenAlg = CSSM_ALGID_RSA;
- sigAlg = CSSM_ALGID_SHA1WithRSA;
- break;
- case 'm':
- keyGenAlg = CSSM_ALGID_RSA;
- sigAlg = CSSM_ALGID_MD5WithRSA;
- break;
- case 'd':
- keyGenAlg = CSSM_ALGID_DSA;
- sigAlg = CSSM_ALGID_SHA1WithDSA;
- break;
- case '4':
- keyGenAlg = CSSM_ALGID_RSA;
- sigAlg = CSSM_ALGID_SHA224WithRSA;
- break;
- case '6':
- keyGenAlg = CSSM_ALGID_RSA;
- sigAlg = CSSM_ALGID_SHA256WithRSA;
- break;
- case '3':
- keyGenAlg = CSSM_ALGID_RSA;
- sigAlg = CSSM_ALGID_SHA512WithRSA;
- break;
- case '5':
- keyGenAlg = CSSM_ALGID_RSA;
- sigAlg = CSSM_ALGID_SHA512WithRSA;
- break;
- case 'E':
- keyGenAlg = CSSM_ALGID_ECDSA;
- sigAlg = CSSM_ALGID_SHA1WithECDSA;
- break;
- case '7':
- keyGenAlg = CSSM_ALGID_ECDSA;
- sigAlg = CSSM_ALGID_SHA512WithECDSA;
- break;
- default:
- usage(argv);
- }
- break;
- case 'N':
- noPartialKeys = CSSM_TRUE;
- break;
- case 'd':
- useDb = CSSM_FALSE;
- break;
- case 'P':
- doPause = CSSM_TRUE;
- break;
- case 'h':
- default:
- usage(argv);
- }
- }
-
- sprintf(dbName, "%s_%d", DB_NAME, (int)getpid());
-
- if(numCerts < 2) {
- printf("Can't run with cert chain smaller than 2\n");
- exit(1);
- }
-
- /* attach to all the modules we need */
- cspHand = cspStartup();
- if(cspHand == 0) {
- exit(1);
- }
- #if CERT_IN_DB
- if(useDb) {
- dlDbHand.DLHandle = dlStartup();
- if(dlDbHand.DLHandle == 0) {
- exit(1);
- }
- CSSM_RETURN crtn = tpKcOpen(dlDbHand.DLHandle, dbName, dbName,
- CSSM_TRUE, &dlDbHand.DBHandle);
- if(crtn) {
- printf("Error opening keychain %s; aborting.\n", dbName);
- exit(1);
- }
- }
- #endif
- clHand = clStartup();
- if(clHand == 0) {
- goto abort;
- }
- tpHand = tpStartup();
- if(tpHand == 0) {
- goto abort;
- }
-
- /* malloc empty keys and certs */
- pubKeys = (CSSM_KEY_PTR)CSSM_CALLOC(numCerts, sizeof(CSSM_KEY));
- privKeys = (CSSM_KEY_PTR)CSSM_CALLOC(numCerts, sizeof(CSSM_KEY));
- certs = (CSSM_DATA_PTR)CSSM_CALLOC(numCerts, sizeof(CSSM_DATA));
- if((pubKeys == NULL) || (privKeys == NULL) || (certs == NULL)) {
- printf("not enough memory for %u keys pairs and certs.\n",
- numCerts);
- goto abort;
- }
-
- printf("Starting cgVerify; args: ");
- for(i=1; i<(unsigned)argc; i++) {
- printf("%s ", argv[i]);
- }
- printf("\n");
-
- /* generate key pairs */
- if(!quiet) {
- printf("generating keys...\n");
- }
- if(keyGenAlg == CSSM_ALGID_DSA) {
- if(!readFile(DSA_PARAM_FILE, (unsigned char **)¶mData.Data, &len)) {
- if(!quiet) {
- printf("...using DSA params from %s\n", DSA_PARAM_FILE);
- }
- paramData.Length = len;
- paramDataP = ¶mData;
- }
- else {
- printf("***warning: no param file. KeyGen is going to be slow!\n");
- printf("***You might consider running this from the clxutils/cgVerify "
- "directory.\n");
- }
- }
- if(tpGenKeys(cspHand,
- keyDb,
- numCerts,
- keyGenAlg,
- keySizeInBits,
- "cgVerify", // keyLabelBase
- pubKeys,
- privKeys,
- paramDataP)) {
- goto abort;
- }
- notBeforeStr = genTimeAtNowPlus(0);
- notAfterStr = genTimeAtNowPlus(SECONDS_TO_LIVE);
-
- /*
- * If DSA, insert some random partial public keys which are not
- * fatal (i.e., root can not be partial). We include the leaf in this
- * loop - the TP is *supposed* to ignore that situation, ane we make
- * sure it does.
- */
- if((keyGenAlg == CSSM_ALGID_DSA) && !noPartialKeys) {
- for(unsigned dex=0; dex<(numCerts-1); dex++) {
- int die = genRand(0,1);
- if(die) {
- /* this one gets partialized */
- CSSM_KEY newKey;
- if(verbose) {
- printf("...making partial DSA pub key at index %u\n", dex);
- }
- CSSM_RETURN crtn = extractDsaPartial(cspHand, &pubKeys[dex], &newKey);
- if(crtn) {
- printf("***Error converting to partial key. Aborting.\n");
- exit(1);
- }
- CSSM_FREE(pubKeys[dex].KeyData.Data);
- pubKeys[dex] = newKey;
- }
- }
- }
- if(!quiet) {
- printf("starting %s test\n", argv[0]);
-
- }
- if(keyGenAlg == CSSM_ALGID_DSA) {
- numTests = 5;
- }
- for(loop=1; ; loop++) {
- if(!quiet) {
- printf("...loop %d\n", loop);
- }
-
- /* cycle thru test scenarios */
- switch(loop % numTests) {
- case 0:
- expectResult = ER_InvalidAnchor;
- break;
- case 1:
- expectResult = ER_RootInCertGroup;
- break;
- case 2:
- expectResult = ER_AnchorVerify;
- break;
- case 3:
- expectResult = ER_NoRoot;
- break;
- case 4:
- /* DSA only */
- expectResult = ER_IncompleteKey;
- savedRoot = pubKeys[numCerts-1];
- /* make anchor unusable */
- if(extractDsaPartial(cspHand, &savedRoot, &pubKeys[numCerts-1])) {
- printf("...error partializing anchor key; aborting\n");
- exit(1);
- }
- break;
- }
- if(tpGenCerts(cspHand,
- clHand,
- numCerts,
- sigAlg,
- "cgConstruct", // nameBase
- pubKeys,
- privKeys,
- certs,
- notBeforeStr,
- notAfterStr)) {
- break;
- }
-
- if(doTest(tpHand,
- clHand,
- cspHand,
- dlDbHand,
- certs,
- numCerts,
- pubKeys,
- useDb,
- expectResult,
- verbose,
- quiet)) {
- break;
- }
- for(i=0; i<numCerts; i++) {
- appFreeCssmData(&certs[i], CSSM_FALSE);
- }
- if(expectResult == ER_IncompleteKey) {
- CSSM_FREE(pubKeys[numCerts-1].KeyData.Data);
- pubKeys[numCerts-1] = savedRoot;
- }
-
- memset(certs, 0, numCerts * sizeof(CSSM_DATA));
- if(loops && (loop == loops)) {
- break;
- }
- if(doPause) {
- printf("Hit CR to continue: ");
- fpurge(stdin);
- getchar();
- }
- }
-abort:
- if(privKeys != NULL) {
- for(i=0; i<numCerts; i++) {
- if(privKeys[i].KeyData.Data != NULL) {
- cspFreeKey(cspHand, &privKeys[i]);
- }
- }
- CSSM_FREE(privKeys);
- }
- if(pubKeys != NULL) {
- for(i=0; i<numCerts; i++) {
- if(pubKeys[i].KeyData.Data != NULL) {
- cspFreeKey(cspHand, &pubKeys[i]);
- }
- }
- CSSM_FREE(pubKeys);
- }
- if(certs != NULL) {
- for(i=0; i<numCerts; i++) {
- appFreeCssmData(&certs[i], CSSM_FALSE);
- }
- CSSM_FREE(certs);
- }
- if(cspHand != 0) {
- CSSM_ModuleDetach(cspHand);
- }
- if(clHand != 0) {
- CSSM_ModuleDetach(clHand);
- }
- if(tpHand != 0) {
- CSSM_ModuleDetach(tpHand);
- }
-
- if(!quiet) {
- printf("%s test complete\n", argv[0]);
- }
- return 0;
-}