1/* 2 * cgVerifyParsed.cpp - basic test of TP's CertGroupVerify using parsed anchors 3 * 4 * ------- THIS TEST IS OBSOLETE; WE DON'T SUPPORT PARSED ANCHORS ---------- 5 * 6 * cook up array of n key pairs; 7 * cook up cert chain to go with them; 8 * main test loop { 9 * numCerts = total # of incoming certs; 10 * test one of four or five "expected result" cases { 11 * case root in certGroup but not found in AnchorCerts: 12 * certGroup = tpMakeRandCertGroup(certs[0..numCerts-1]; 13 * anchorCerts = tpMakeRandCertGroup[certs[0...numCerts-2]; 14 * expErr = CSSMERR_TP_INVALID_ANCHOR_CERT; 15 * expEvidenceSize = numCerts; 16 * case root in certGroup, found a copy in AnchorCerts: 17 * certGroup = tpMakeRandCertGroup(certs[0..numCerts-1]; 18 * anchorCerts = tpMakeRandCertGroup[certs[0...numCerts-1]; 19 * expErr = CSSM_OK; 20 * expEvidenceSize = numCerts; 21 * case verified by an AnchorCert: 22 * n = rand(1, numCerts-2); 23 * certGroup = tpMakeRandCertGroup(certs[0..n]); 24 * anchorCerts = tpMakeRandCertGroup[certs[0...numCerts-2]; 25 * expErr = CSSM_OK; 26 * expEvidenceSize = n+2; 27 * case no root found: 28 * n = rand(1, numCerts-3); 29 * certGroup = tpMakeRandCertGroup(certs[0..n]); 30 * anchorCerts = tpMakeRandCertGroup[certs[n+2...numCerts-2]; 31 * anchorCerts may be empty.... 32 * expErr = CSSMERR_TP_NOT_TRUSTED; 33 * expEvidenceSize = n+1; 34 * case incomplete public key (DSA only): 35 * root public keys is incomplete; 36 * certGroup = tpMakeRandCertGroup(certs[0..numCerts-1]; 37 * anchorCerts = tpMakeRandCertGroup[certs[0...numCerts-1]; 38 * expErr = CSSM_OK; 39 * expEvidenceSize = numCerts; 40 * } 41 * result = certGroupVerify(); 42 * verify expected result and getError(); 43 * delete certs from DB; 44 * } 45 */ 46 47#include <Security/cssm.h> 48#include <utilLib/common.h> 49#include <utilLib/cspwrap.h> 50#include <clAppUtils/clutils.h> 51#include <clAppUtils/tpUtils.h> 52#include <clAppUtils/timeStr.h> 53#include <utilLib/nssAppUtils.h> 54#include <utilLib/fileIo.h> 55#include <stdio.h> 56#include <stdlib.h> 57#include <time.h> 58#include <string.h> 59#include <sys/types.h> 60#include <unistd.h> 61#include <Security/oidsalg.h> 62#include "tpVerifyParsed.h" 63 64#define NUM_CERTS_DEF 10 65#define KEYGEN_ALG_DEF CSSM_ALGID_RSA 66#define SIG_ALG_DEF CSSM_ALGID_SHA1WithRSA 67#define LOOPS_DEF 10 68#define SECONDS_TO_LIVE (60 * 60 * 24) /* certs are valid for this long */ 69//#define SECONDS_TO_LIVE 5 70 71#define CERT_IN_DB 1 72#define DB_NAME "cgVerify.db" 73#define DSA_PARAM_FILE "dsaParam512.der" 74 75/* 76 * How we define the "expected result". 77 */ 78typedef enum { 79 ER_InvalidAnchor, // root in certGroup, not found in AnchorCerts 80 ER_RootInCertGroup, // root in certGroup, copy in AnchorCerts 81 ER_AnchorVerify, // end of chain verified by an anchor 82 ER_NoRoot, // no root, no anchor verify 83 ER_IncompleteKey // un-completable public key (all keys are partial), DSA 84 // ONLY 85} ExpectResult; 86 87static void usage(char **argv) 88{ 89 printf("Usage: %s [options]\n", argv[0]); 90 printf(" Options:\n"); 91 printf(" n=numCerts; default = %d\n", NUM_CERTS_DEF); 92 printf(" l=loops; default=%d; 0=forever\n", LOOPS_DEF); 93 printf(" a=alg (f=FEE/MD5, F=FEE/SHA1, e=FEE/ECDSA, s=RSA/SHA1, m=RSA/MD5,\n"); 94 printf(" d=DSA; 6=RSA/SHA256, 3=RSA/SHA384, 5=RSA/SHA512; default = RSA/SHA1\n"); 95 printf(" k=keySizeInBits\n"); 96 printf(" d(isable DB)\n"); 97 printf(" P(ause on each loop)\n"); 98 printf(" N (no partial pub keys)\n"); 99 printf(" v(erbose)\n"); 100 printf(" q(uiet)\n"); 101 printf(" h(elp)\n"); 102 exit(1); 103} 104 105static int doTest( 106 CSSM_TP_HANDLE tpHand, 107 CSSM_CL_HANDLE clHand, 108 CSSM_CSP_HANDLE cspHand, 109 CSSM_DL_DB_HANDLE dlDb, 110 CSSM_DATA_PTR certs, 111 unsigned numCerts, 112 CSSM_KEY_PTR pubKeys, // for partial key detect 113 CSSM_BOOL useDb, 114 ExpectResult expectResult, 115 CSSM_BOOL verbose, 116 CSSM_BOOL quiet) 117{ 118 unsigned cgEnd; // last cert in certGroupFrag 119 unsigned anchorStart; // first cert in anchorGroup 120 unsigned anchorEnd; // last cert in anchorGroup 121 CSSM_CERTGROUP certGroupFrag; // INPUT to CertGroupVerify 122 CSSM_CERTGROUP anchorCerts; // ditto 123 unsigned die; // random number 124 CSSM_DL_DB_LIST dbList; 125 CSSM_DL_DB_LIST_PTR dbListPtr; 126 CSSM_RETURN expErr; // expected rtn from GroupVfy() 127 int rtn = 0; 128 char *expResStr; 129 uint32 expEvidenceSize; // expected evidenceSize 130 unsigned evidenceSize; // actual evidence size 131 CSSM_TP_VERIFY_CONTEXT_RESULT vfyResult; 132 CSSM_CERTGROUP_PTR outGrp = NULL; 133 CSSM_RETURN crtn; 134 CSSM_DL_DB_HANDLE_PTR dlDbPtr; 135 unsigned numAnchors; 136 137 memset(&vfyResult, 0, sizeof(CSSM_TP_VERIFY_CONTEXT_RESULT)); 138 139 if(useDb) { 140 dlDbPtr = &dlDb; 141 dbList.NumHandles = 1; 142 dbList.DLDBHandle = &dlDb; 143 dbListPtr = &dbList; 144 } 145 else { 146 /* not yet */ 147 dlDbPtr = NULL; 148 dbListPtr = NULL; 149 } 150 151 /* the four test cases */ 152 switch(expectResult) { 153 case ER_InvalidAnchor: 154 /* root in certGroup, not found in AnchorCerts */ 155 cgEnd = numCerts - 1; // certGroupFrag is the whole pile 156 anchorStart = 0; // anchors = all except root 157 anchorEnd = numCerts - 2; 158 expErr = CSSMERR_TP_INVALID_ANCHOR_CERT; 159 expEvidenceSize = numCerts; 160 expResStr = "InvalidAnchor (root in certGroup but not in anchors)"; 161 break; 162 163 case ER_RootInCertGroup: 164 /* root in certGroup, copy in AnchorCerts */ 165 cgEnd = numCerts - 1; // certGroupFrag = the whole pile 166 anchorStart = 0; // anchors = the whole pile 167 anchorEnd = numCerts - 1; 168 expErr = CSSM_OK; 169 expEvidenceSize = numCerts; 170 expResStr = "Good (root in certGroup AND in anchors)"; 171 break; 172 173 case ER_AnchorVerify: 174 /* non-root end of chain verified by an anchor */ 175 /* break chain at random place other than end */ 176 /* die is the last cert in certGroupFrag */ 177 die = genRand(0, numCerts-2); 178 cgEnd = die; // certGroupFrag up to break point 179 anchorStart = 0; // anchors = all 180 anchorEnd = numCerts - 1; 181 if(pubKeys[die+1].KeyHeader.KeyAttr & CSSM_KEYATTR_PARTIAL) { 182 /* this will fail due to an unusable anchor */ 183 expErr = CSSMERR_TP_CERTIFICATE_CANT_OPERATE; 184 expResStr = "Root ONLY in anchors but has partial pub key"; 185 } 186 else { 187 expErr = CSSM_OK; 188 expResStr = "Good (root ONLY in anchors)"; 189 } 190 /* size = # certs in certGroupFrag, plus one anchor */ 191 expEvidenceSize = die + 2; 192 break; 193 194 case ER_NoRoot: 195 /* no root, no anchor verify */ 196 /* break chain at random place other than end */ 197 /* die is the last cert in certGroupFrag */ 198 /* skip a cert, then anchors start at die + 2 */ 199 die = genRand(0, numCerts-2); 200 cgEnd = die; // certGroupFrag up to break point 201 anchorStart = die + 2; // anchors = n+1...numCerts-2 202 // may be empty if n == numCerts-2 203 anchorEnd = numCerts - 2; 204 if((die != 0) && // partial leaf not reported as partial! 205 (pubKeys[die].KeyHeader.KeyAttr & CSSM_KEYATTR_PARTIAL)) { 206 /* this will fail due to an unusable cert (this one) */ 207 expErr = CSSMERR_TP_CERTIFICATE_CANT_OPERATE; 208 expResStr = "Not Trusted (no root, no anchor verify), partial"; 209 } 210 else { 211 expErr = CSSMERR_TP_NOT_TRUSTED; 212 expResStr = "Not Trusted (no root, no anchor verify)"; 213 } 214 expEvidenceSize = die + 1; 215 break; 216 217 case ER_IncompleteKey: 218 /* 219 * Anchor has incomplete pub key 220 * Root in certGroup, copy in AnchorCerts 221 * Avoid putting anchor in certGroupFrag because the TP will think 222 * it's NOT a root and it'll show up twice in the evidence - once 223 * from certGroupFrag (at which point the search for a root 224 * keeps going), and once from Anchors. 225 */ 226 cgEnd = numCerts - 2; // certGroupFrag = the whole pile less the anchor 227 anchorStart = 0; // anchors = the whole pile 228 anchorEnd = numCerts - 1; 229 expErr = CSSMERR_TP_CERTIFICATE_CANT_OPERATE; 230 expEvidenceSize = numCerts; 231 expResStr = "Partial public key in anchor"; 232 break; 233 } 234 235 if(verbose) { 236 printf(" ...expectResult = %s\n", expResStr); 237 } 238 239 /* cook up two cert groups */ 240 if(verbose) { 241 printf(" ...building certGroupFrag from certs[0..%d]\n", 242 cgEnd); 243 } 244 if(tpMakeRandCertGroup(clHand, 245 dbListPtr, 246 certs, // certGroupFrag always starts at 0 247 cgEnd+1, // # of certs 248 &certGroupFrag, 249 CSSM_TRUE, // firstCertIsSubject 250 verbose, 251 CSSM_FALSE, // allInDbs 252 CSSM_FALSE)) { // skipFirstDb 253 printf("Error in tpMakeRandCertGroup\n"); 254 return 1; 255 } 256 257 if(verbose) { 258 printf(" ...building anchorCerts from certs[%d..%d]\n", 259 anchorStart, anchorEnd); 260 } 261 if(anchorEnd > (numCerts - 1)) { 262 printf("anchorEnd overflow\n"); 263 exit(1); 264 } 265 if(anchorStart >= anchorEnd) { 266 /* legal in some corner cases, ==> empty enchors */ 267 numAnchors = 0; 268 } 269 else { 270 numAnchors = anchorEnd - anchorStart + 1; 271 } 272 /* anchors do not go in DB */ 273 if(tpMakeRandCertGroup(clHand, 274 NULL, 275 certs + anchorStart, 276 numAnchors, // # of certs 277 &anchorCerts, 278 CSSM_FALSE, // firstCertIsSubject 279 verbose, 280 CSSM_FALSE, // allInDbs 281 CSSM_FALSE)) { // skipFirstDb 282 printf("Error in tpMakeRandCertGroup\n"); 283 return 1; 284 } 285 286 crtn = tpCertGroupVerifyParsed( 287 tpHand, 288 clHand, 289 cspHand, 290 dbListPtr, 291 &CSSMOID_APPLE_X509_BASIC, // policy 292 NULL, // fieldOpts 293 NULL, // actionData 294 NULL, // policyOpts 295 &certGroupFrag, 296 anchorCerts.GroupList.CertList, // passed as CSSM_DATA_PTR, not CERTGROUP.... 297 anchorCerts.NumCerts, 298 CSSM_TP_STOP_ON_POLICY, 299 NULL, // cssmTimeStr 300 &vfyResult); 301 302 /* first verify format of result */ 303 if( (vfyResult.NumberOfEvidences != 3) || 304 (vfyResult.Evidence == NULL) || 305 (vfyResult.Evidence[0].EvidenceForm != CSSM_EVIDENCE_FORM_APPLE_HEADER) || 306 (vfyResult.Evidence[1].EvidenceForm != CSSM_EVIDENCE_FORM_APPLE_CERTGROUP) || 307 (vfyResult.Evidence[2].EvidenceForm != CSSM_EVIDENCE_FORM_APPLE_CERT_INFO) || 308 (vfyResult.Evidence[0].Evidence == NULL) || 309 (vfyResult.Evidence[1].Evidence == NULL) || 310 (vfyResult.Evidence[2].Evidence == NULL)) { 311 printf("***Malformed VerifyContextResult\n"); 312 rtn = testError(quiet); 313 if(rtn) { 314 return rtn; 315 } 316 } 317 if((vfyResult.Evidence != NULL) && (vfyResult.Evidence[1].Evidence != NULL)) { 318 outGrp = (CSSM_CERTGROUP_PTR)vfyResult.Evidence[1].Evidence; 319 evidenceSize = outGrp->NumCerts; 320 } 321 else { 322 /* in case no evidence returned */ 323 evidenceSize = 0; 324 } 325 if((crtn != expErr) || 326 (evidenceSize != expEvidenceSize)) { 327 printf("***Error on expectResult %s\n", expResStr); 328 printf(" err %s expErr %s\n", 329 cssmErrToStr(crtn), cssmErrToStr(expErr)); 330 printf(" evidenceSize %d expEvidenceSize %lu\n", 331 evidenceSize, expEvidenceSize); 332 rtn = testError(quiet); 333 } 334 else { 335 rtn = 0; 336 } 337 338 /* free resources */ 339 tpFreeCertGroup(&certGroupFrag, 340 CSSM_FALSE, // caller malloc'd the actual certs 341 CSSM_FALSE); // struct is on stack 342 tpFreeCertGroup(&anchorCerts, 343 CSSM_FALSE, // caller malloc'd the actual certs 344 CSSM_FALSE); // struct is on stack 345 freeVfyResult(&vfyResult); 346 if(useDb) { 347 clDeleteAllCerts(dlDb); 348 } 349 return rtn; 350} 351 352int main(int argc, char **argv) 353{ 354 int arg; 355 char *argp; 356 unsigned loop; 357 CSSM_TP_HANDLE tpHand = 0; 358 CSSM_CL_HANDLE clHand = 0; 359 CSSM_CSP_HANDLE cspHand = 0; 360 CSSM_DL_DB_HANDLE dlDbHand = {0, 0}; 361 ExpectResult expectResult; 362 char *notAfterStr; 363 char *notBeforeStr; 364 unsigned i; 365 CSSM_DATA paramData; 366 CSSM_DATA_PTR paramDataP = NULL; 367 unsigned numTests = 4; 368 369 /* all three of these are arrays with numCert elements */ 370 CSSM_KEY_PTR pubKeys = NULL; 371 CSSM_KEY_PTR privKeys = NULL; 372 CSSM_DATA_PTR certs = NULL; 373 374 /* Keys do NOT go in the cert DB */ 375 CSSM_DL_DB_HANDLE keyDb = {0, 0}; 376 CSSM_KEY savedRoot; // for ER_IncompleteKey 377 378 /* 379 * User-spec'd params 380 */ 381 unsigned loops = LOOPS_DEF; 382 CSSM_BOOL verbose = CSSM_FALSE; 383 CSSM_BOOL quiet = CSSM_FALSE; 384 unsigned numCerts = NUM_CERTS_DEF; 385 uint32 keyGenAlg = KEYGEN_ALG_DEF; 386 uint32 sigAlg = SIG_ALG_DEF; 387 #if CERT_IN_DB 388 CSSM_BOOL useDb = CSSM_TRUE; 389 #else 390 CSSM_BOOL useDb = CSSM_FALSE; 391 #endif 392 CSSM_BOOL doPause = CSSM_FALSE; 393 uint32 keySizeInBits = CSP_KEY_SIZE_DEFAULT; 394 CSSM_BOOL noPartialKeys = CSSM_FALSE; 395 char dbName[100]; /* DB_NAME_pid */ 396 397 for(arg=1; arg<argc; arg++) { 398 argp = argv[arg]; 399 switch(argp[0]) { 400 case 'l': 401 loops = atoi(&argp[2]); 402 break; 403 case 'k': 404 keySizeInBits = atoi(&argp[2]); 405 break; 406 case 'n': 407 numCerts = atoi(&argp[2]); 408 break; 409 case 'v': 410 verbose = CSSM_TRUE; 411 break; 412 case 'q': 413 quiet = CSSM_TRUE; 414 break; 415 case 'a': 416 switch(argp[2]) { 417 case 'f': 418 keyGenAlg = CSSM_ALGID_FEE; 419 sigAlg = CSSM_ALGID_FEE_MD5; 420 break; 421 case 'F': 422 keyGenAlg = CSSM_ALGID_FEE; 423 sigAlg = CSSM_ALGID_FEE_SHA1; 424 break; 425 case 'e': 426 keyGenAlg = CSSM_ALGID_FEE; 427 sigAlg = CSSM_ALGID_SHA1WithECDSA; 428 break; 429 case 's': 430 keyGenAlg = CSSM_ALGID_RSA; 431 sigAlg = CSSM_ALGID_SHA1WithRSA; 432 break; 433 case 'm': 434 keyGenAlg = CSSM_ALGID_RSA; 435 sigAlg = CSSM_ALGID_MD5WithRSA; 436 break; 437 case 'd': 438 keyGenAlg = CSSM_ALGID_DSA; 439 sigAlg = CSSM_ALGID_SHA1WithDSA; 440 break; 441 case '6': 442 keyGenAlg = CSSM_ALGID_RSA; 443 sigAlg = CSSM_ALGID_SHA256WithRSA; 444 break; 445 case '3': 446 keyGenAlg = CSSM_ALGID_RSA; 447 sigAlg = CSSM_ALGID_SHA512WithRSA; 448 break; 449 case '5': 450 keyGenAlg = CSSM_ALGID_RSA; 451 sigAlg = CSSM_ALGID_SHA512WithRSA; 452 break; 453 default: 454 usage(argv); 455 } 456 break; 457 case 'N': 458 noPartialKeys = CSSM_TRUE; 459 break; 460 case 'd': 461 useDb = CSSM_FALSE; 462 break; 463 case 'P': 464 doPause = CSSM_TRUE; 465 break; 466 case 'h': 467 default: 468 usage(argv); 469 } 470 } 471 472 sprintf(dbName, "%s_%d", DB_NAME, (int)getpid()); 473 474 if(numCerts < 2) { 475 printf("Can't run with cert chain smaller than 2\n"); 476 exit(1); 477 } 478 479 /* attach to all the modules we need */ 480 cspHand = cspStartup(); 481 if(cspHand == 0) { 482 exit(1); 483 } 484 #if CERT_IN_DB 485 if(useDb) { 486 dlDbHand.DLHandle = dlStartup(); 487 if(dlDbHand.DLHandle == 0) { 488 exit(1); 489 } 490 CSSM_RETURN crtn = tpKcOpen(dlDbHand.DLHandle, dbName, dbName, 491 CSSM_TRUE, &dlDbHand.DBHandle); 492 if(crtn) { 493 printf("Error opening keychain %s; aborting.\n", dbName); 494 exit(1); 495 } 496 } 497 #endif 498 clHand = clStartup(); 499 if(clHand == 0) { 500 goto abort; 501 } 502 tpHand = tpStartup(); 503 if(tpHand == 0) { 504 goto abort; 505 } 506 507 /* malloc empty keys and certs */ 508 pubKeys = (CSSM_KEY_PTR)CSSM_CALLOC(numCerts, sizeof(CSSM_KEY)); 509 privKeys = (CSSM_KEY_PTR)CSSM_CALLOC(numCerts, sizeof(CSSM_KEY)); 510 certs = (CSSM_DATA_PTR)CSSM_CALLOC(numCerts, sizeof(CSSM_DATA)); 511 if((pubKeys == NULL) || (privKeys == NULL) || (certs == NULL)) { 512 printf("not enough memory for %u keys pairs and certs.\n", 513 numCerts); 514 goto abort; 515 } 516 517 printf("Starting cgVerify; args: "); 518 for(i=1; i<(unsigned)argc; i++) { 519 printf("%s ", argv[i]); 520 } 521 printf("\n"); 522 523 /* generate key pairs */ 524 if(!quiet) { 525 printf("generating keys...\n"); 526 } 527 if(keyGenAlg == CSSM_ALGID_DSA) { 528 unsigned len; 529 if(!readFile(DSA_PARAM_FILE, (unsigned char **)¶mData.Data, &len)) { 530 if(!quiet) { 531 printf("...using DSA params from %s\n", DSA_PARAM_FILE); 532 } 533 paramData.Length = len; 534 paramDataP = ¶mData; 535 } 536 else { 537 printf("***warning: no param file. KeyGen is going to be slow!\n"); 538 printf("***You might consider running this from the clxutils/cgVerify " 539 "directory.\n"); 540 } 541 } 542 if(tpGenKeys(cspHand, 543 keyDb, 544 numCerts, 545 keyGenAlg, 546 keySizeInBits, 547 "cgVerify", // keyLabelBase 548 pubKeys, 549 privKeys, 550 paramDataP)) { 551 goto abort; 552 } 553 notBeforeStr = genTimeAtNowPlus(0); 554 notAfterStr = genTimeAtNowPlus(SECONDS_TO_LIVE); 555 556 /* 557 * If DSA, insert some random partial public keys which are not 558 * fatal (i.e., root can not be partial). We include the leaf in this 559 * loop - the TP is *supposed* to ignore that situation, ane we make 560 * sure it does. 561 */ 562 if((keyGenAlg == CSSM_ALGID_DSA) && !noPartialKeys) { 563 for(unsigned dex=0; dex<(numCerts-1); dex++) { 564 int die = genRand(0,1); 565 if(die) { 566 /* this one gets partialized */ 567 CSSM_KEY newKey; 568 if(verbose) { 569 printf("...making partial DSA pub key at index %u\n", dex); 570 } 571 CSSM_RETURN crtn = extractDsaPartial(cspHand, &pubKeys[dex], &newKey); 572 if(crtn) { 573 printf("***Error converting to partial key. Aborting.\n"); 574 exit(1); 575 } 576 CSSM_FREE(pubKeys[dex].KeyData.Data); 577 pubKeys[dex] = newKey; 578 } 579 } 580 } 581 if(!quiet) { 582 printf("starting %s test\n", argv[0]); 583 584 } 585 if(keyGenAlg == CSSM_ALGID_DSA) { 586 numTests = 5; 587 } 588 for(loop=1; ; loop++) { 589 if(!quiet) { 590 printf("...loop %d\n", loop); 591 } 592 593 /* cycle thru test scenarios */ 594 switch(loop % numTests) { 595 case 0: 596 expectResult = ER_InvalidAnchor; 597 break; 598 case 1: 599 expectResult = ER_RootInCertGroup; 600 break; 601 case 2: 602 expectResult = ER_AnchorVerify; 603 break; 604 case 3: 605 expectResult = ER_NoRoot; 606 break; 607 case 4: 608 /* DSA only */ 609 expectResult = ER_IncompleteKey; 610 savedRoot = pubKeys[numCerts-1]; 611 /* make anchor unusable */ 612 if(extractDsaPartial(cspHand, &savedRoot, &pubKeys[numCerts-1])) { 613 printf("...error partializing anchor key; aborting\n"); 614 exit(1); 615 } 616 break; 617 } 618 if(tpGenCerts(cspHand, 619 clHand, 620 numCerts, 621 sigAlg, 622 "cgConstruct", // nameBase 623 pubKeys, 624 privKeys, 625 certs, 626 notBeforeStr, 627 notAfterStr)) { 628 break; 629 } 630 631 if(doTest(tpHand, 632 clHand, 633 cspHand, 634 dlDbHand, 635 certs, 636 numCerts, 637 pubKeys, 638 useDb, 639 expectResult, 640 verbose, 641 quiet)) { 642 break; 643 } 644 for(i=0; i<numCerts; i++) { 645 appFreeCssmData(&certs[i], CSSM_FALSE); 646 } 647 if(expectResult == ER_IncompleteKey) { 648 CSSM_FREE(pubKeys[numCerts-1].KeyData.Data); 649 pubKeys[numCerts-1] = savedRoot; 650 } 651 652 memset(certs, 0, numCerts * sizeof(CSSM_DATA)); 653 if(loops && (loop == loops)) { 654 break; 655 } 656 if(doPause) { 657 printf("Hit CR to continue: "); 658 fpurge(stdin); 659 getchar(); 660 } 661 } 662abort: 663 if(privKeys != NULL) { 664 for(i=0; i<numCerts; i++) { 665 if(privKeys[i].KeyData.Data != NULL) { 666 cspFreeKey(cspHand, &privKeys[i]); 667 } 668 } 669 CSSM_FREE(privKeys); 670 } 671 if(pubKeys != NULL) { 672 for(i=0; i<numCerts; i++) { 673 if(pubKeys[i].KeyData.Data != NULL) { 674 cspFreeKey(cspHand, &pubKeys[i]); 675 } 676 } 677 CSSM_FREE(pubKeys); 678 } 679 if(certs != NULL) { 680 for(i=0; i<numCerts; i++) { 681 appFreeCssmData(&certs[i], CSSM_FALSE); 682 } 683 CSSM_FREE(certs); 684 } 685 if(cspHand != 0) { 686 CSSM_ModuleDetach(cspHand); 687 } 688 if(clHand != 0) { 689 CSSM_ModuleDetach(clHand); 690 } 691 if(tpHand != 0) { 692 CSSM_ModuleDetach(tpHand); 693 } 694 695 if(!quiet) { 696 printf("%s test complete\n", argv[0]); 697 } 698 return 0; 699} 700