1/* 2 * cgConstruct.c - basic test of TP's CertGroupConstruct 3 * 4 * cook up array of n key pairs; 5 * cook up cert chain to go with them; 6 * main test loop { 7 * pick a random spot to break the cert chain - half the time use the 8 * whole chain, half the time break it; 9 * cook up CertGroup frag big enough for the unbroken part of the chain; 10 * put cert[0] in certGroup[0]; 11 * for each cert from cert[1] to break point { 12 * roll the dice and put the cert in either a random place 13 * in certGroup or in DB; 14 * } 15 * resultGroup = certGroupConstruct(); 16 * vfy result Grp is identical to unbroken part of chain; 17 * delete certs from DB; 18 * } 19 */ 20 21#include <Security/cssm.h> 22#include <utilLib/common.h> 23#include <utilLib/cspwrap.h> 24#include <clAppUtils/clutils.h> 25#include <clAppUtils/tpUtils.h> 26#include <clAppUtils/timeStr.h> 27#include <stdio.h> 28#include <stdlib.h> 29#include <time.h> 30#include <string.h> 31 32#define NUM_CERTS_DEF 10 33#define NUM_DBS_DEF 3 34#define KEYGEN_ALG_DEF CSSM_ALGID_RSA 35#define SIG_ALG_DEF CSSM_ALGID_SHA1WithRSA 36#define LOOPS_DEF 10 37#define DB_NAME_BASE "cgConstruct" /* default */ 38#define SECONDS_TO_LIVE (60 * 60 * 24) /* certs are valid for this long */ 39 40/* Read-only access not supported */ 41#define PUBLIC_READ_ENABLE 0 42 43static void usage(char **argv) 44{ 45 printf("Usage: %s [options]\n", argv[0]); 46 printf(" Options:\n"); 47 printf(" n=numCerts; default = %d\n", NUM_CERTS_DEF); 48 printf(" l=loops; default=%d; 0=forever\n", LOOPS_DEF); 49 printf(" a=alg (f=FEE/MD5, f=FEE/SHA1, e=FEE/ECDSA, r=RSA, E=ANSI ECDSA; default = RSA\n"); 50 printf(" K=keySizeInBits\n"); 51 #if TP_DB_ENABLE 52 printf(" d=numDBs, default = %d\n", NUM_DBS_DEF); 53 printf(" A(ll certs to DBs)\n"); 54 printf(" k (skip first DB when storing)\n"); 55 #if PUBLIC_READ_ENABLE 56 printf(" p(ublic access open on read)\n"); 57 #endif 58 #endif 59 printf(" f=fileNameBase (default = %s)\n", DB_NAME_BASE); 60 printf(" P(ause on each loop)\n"); 61 printf(" v(erbose)\n"); 62 printf(" q(uiet)\n"); 63 printf(" h(elp)\n"); 64 exit(1); 65} 66 67#if TP_DB_ENABLE 68static int doOpenDbs( 69 CSSM_DL_HANDLE dlHand, 70 const char *dbNameBase, 71 CSSM_DL_DB_HANDLE_PTR dlDbPtr, 72 unsigned numDbs, 73 CSSM_BOOL publicReadOnly, // ignored if !PUBLIC_READ_ENABLE 74 CSSM_BOOL quiet) 75{ 76 unsigned i; 77 char dbName[20]; 78 CSSM_BOOL doCreate = (publicReadOnly ? CSSM_FALSE : CSSM_TRUE); 79 80 for(i=0; i<numDbs; i++) { 81 dlDbPtr[i].DLHandle = dlHand; 82 sprintf(dbName, "%s%d", dbNameBase, i); 83 CSSM_RETURN crtn = tpKcOpen(dlHand, dbName, 84 dbName, // file name as pwd 85 doCreate, 86 &dlDbPtr[i].DBHandle); 87 if(crtn) { 88 printf("Can't create %d DBs\n", numDbs); 89 return testError(quiet); 90 } 91 } 92 return 0; 93} 94#endif 95 96static int doTest( 97 CSSM_TP_HANDLE tpHand, 98 CSSM_CL_HANDLE clHand, 99 CSSM_CSP_HANDLE cspHand, 100 CSSM_DL_HANDLE dlHand, 101 CSSM_DL_DB_LIST_PTR dbList, 102 CSSM_DATA_PTR certs, 103 unsigned numCerts, 104 CSSM_BOOL verbose, 105 CSSM_BOOL allInDbs, 106 CSSM_BOOL skipFirstDb, 107 CSSM_BOOL publicRead, // close/open with public access 108 const char *fileBaseName, 109 CSSM_BOOL quiet) 110{ 111 unsigned certsToUse; // # of certs we actually use 112 CSSM_CERTGROUP certGroupFrag; // INPUT to CertGroupConstruct 113 CSSM_CERTGROUP_PTR resultGroup; // OUTPUT from " 114 unsigned certDex; 115 int rtn = 0; 116 CSSM_RETURN crtn; 117 118 #if TP_DB_ENABLE 119 if(publicRead && (dbList != NULL)) { 120 /* DBs are closed on entry, open r/w */ 121 if(doOpenDbs(dlHand, 122 fileBaseName, 123 dbList->DLDBHandle, 124 dbList->NumHandles, 125 CSSM_FALSE, 126 quiet)) { // publicReadOnly: this is create/write 127 return 1; 128 } 129 } 130 /* else DBs are already open and stay that way */ 131 #endif 132 133 /* 134 * Pick a random spot to break the cert chain - half the time use the 135 * whole chain, half the time break it. 136 */ 137 certsToUse = genRand(1, numCerts * 2); 138 if(certsToUse > numCerts) { 139 /* use the whole chain */ 140 certsToUse = numCerts; 141 } 142 if(verbose) { 143 printf(" ...numCerts %d certsToUse %d\n", numCerts, certsToUse); 144 } 145 146 if(tpMakeRandCertGroup(clHand, 147 #if TP_DB_ENABLE 148 dbList, 149 #else 150 NULL, 151 #endif 152 certs, 153 certsToUse, 154 &certGroupFrag, 155 CSSM_TRUE, // firstCertIsSubject 156 verbose, 157 allInDbs, 158 skipFirstDb)) { 159 printf("Error in tpMakeRandCertGroup\n"); 160 return testError(quiet); 161 } 162 163 if(certGroupFrag.NumCerts > certsToUse) { 164 printf("Error NOMAD sterlize\n"); 165 exit(1); 166 } 167 168 #if TP_DB_ENABLE 169 if(publicRead) { 170 /* close existing DBs and open again read-only */ 171 172 unsigned i; 173 CSSM_RETURN crtn; 174 175 if(verbose) { 176 printf(" ...closing DBs\n"); 177 } 178 for(i=0; i<dbList->NumHandles; i++) { 179 crtn = CSSM_DL_DbClose(dbList->DLDBHandle[i]); 180 if(crtn) { 181 printError("CSSM_DL_DbClose", crtn); 182 if(testError(quiet)) { 183 return 1; 184 } 185 } 186 } 187 if(verbose) { 188 printf(" ...opening DBs read-only\n"); 189 } 190 if(doOpenDbs(dlHand, 191 fileBaseName, 192 dbList->DLDBHandle, 193 dbList->NumHandles, 194 CSSM_TRUE, // publicReadOnly: this is read only 195 quiet)) { 196 return 1; 197 } 198 } 199 #endif 200 201 /* 202 * Okay, some of the certs we were given are in the DB, some are in 203 * random places in certGroupFrag, some are nowhere (if certsToUse is 204 * less than numCerts). Have the TP construct us an ordered verified 205 * group. 206 */ 207 crtn = CSSM_TP_CertGroupConstruct( 208 tpHand, 209 clHand, 210 cspHand, 211 dbList, 212 NULL, // ConstructParams 213 &certGroupFrag, 214 &resultGroup); 215 if(crtn) { 216 printError("CSSM_TP_CertGroupConstruct", crtn); 217 return testError(quiet); 218 } 219 220 /* vfy resultGroup is identical to unbroken part of chain */ 221 if(verbose) { 222 printf(" ...CSSM_TP_CertGroupConstruct returned %u certs\n", 223 (unsigned)resultGroup->NumCerts); 224 } 225 if(resultGroup->NumCerts != certsToUse) { 226 printf("***resultGroup->NumCerts was %u, expected %u\n", 227 (unsigned)resultGroup->NumCerts, (unsigned)certsToUse); 228 rtn = testError(quiet); 229 goto abort; 230 } 231 for(certDex=0; certDex<certsToUse; certDex++) { 232 if(!appCompareCssmData(&certs[certDex], 233 &resultGroup->GroupList.CertList[certDex])) { 234 printf("***certs[%d] miscompare\n", certDex); 235 rtn = testError(quiet); 236 goto abort; 237 } 238 } 239abort: 240 /* free resurces */ 241 tpFreeCertGroup(&certGroupFrag, 242 CSSM_FALSE, // caller malloc'd the actual certs 243 CSSM_FALSE); // struct is on stack 244 tpFreeCertGroup(resultGroup, 245 CSSM_TRUE, // mallocd by TP 246 CSSM_TRUE); // ditto 247 #if TP_DB_ENABLE 248 if(dbList != NULL) { 249 unsigned i; 250 CSSM_RETURN crtn; 251 252 if(verbose) { 253 printf(" ...deleting all certs from DBs\n"); 254 } 255 for(i=0; i<dbList->NumHandles; i++) { 256 clDeleteAllCerts(dbList->DLDBHandle[i]); 257 } 258 if(publicRead) { 259 if(verbose) { 260 printf(" ...closing DBs\n"); 261 } 262 for(i=0; i<dbList->NumHandles; i++) { 263 crtn = CSSM_DL_DbClose(dbList->DLDBHandle[i]); 264 if(crtn) { 265 printError("CSSM_DL_DbClose", crtn); 266 if(testError(quiet)) { 267 return 1; 268 } 269 } 270 } 271 } 272 } 273 #endif 274 return rtn; 275} 276 277int main(int argc, char **argv) 278{ 279 int arg; 280 char *argp; 281 unsigned loop; 282 CSSM_TP_HANDLE tpHand = 0; 283 CSSM_CL_HANDLE clHand = 0; 284 CSSM_CSP_HANDLE cspHand = 0; 285 CSSM_DL_DB_LIST dbList = {0, NULL}; /* for storing certs */ 286 CSSM_DL_DB_LIST_PTR dbListPtr; /* pts to dbList or NULL */ 287 unsigned i; 288 char *notAfterStr; 289 char *notBeforeStr; 290 CSSM_DL_HANDLE dlHand; 291 292 /* all three of these are arrays with numCert elements */ 293 CSSM_KEY_PTR pubKeys = NULL; 294 CSSM_KEY_PTR privKeys = NULL; 295 CSSM_DATA_PTR certs = NULL; 296 297 /* Keys do NOT go in the cert DB */ 298 CSSM_DL_DB_HANDLE keyDb = {0, 0}; 299 300 /* 301 * User-spec'd params 302 */ 303 unsigned loops = LOOPS_DEF; 304 CSSM_BOOL verbose = CSSM_FALSE; 305 CSSM_BOOL quiet = CSSM_FALSE; 306 unsigned numCerts = NUM_CERTS_DEF; 307 uint32 keyGenAlg = KEYGEN_ALG_DEF; 308 uint32 sigAlg = SIG_ALG_DEF; 309 unsigned numDBs = NUM_DBS_DEF; 310 CSSM_BOOL allInDbs = CSSM_FALSE; 311 CSSM_BOOL skipFirstDb = CSSM_FALSE; 312 CSSM_BOOL publicRead = CSSM_FALSE; 313 CSSM_BOOL doPause = CSSM_FALSE; 314 uint32 keySizeInBits = CSP_KEY_SIZE_DEFAULT; 315 const char *fileBaseName = DB_NAME_BASE; 316 317 for(arg=1; arg<argc; arg++) { 318 argp = argv[arg]; 319 switch(argp[0]) { 320 case 'l': 321 loops = atoi(&argp[2]); 322 break; 323 case 'n': 324 numCerts = atoi(&argp[2]); 325 break; 326 case 'K': 327 keySizeInBits = atoi(&argp[2]); 328 break; 329 case 'v': 330 verbose = CSSM_TRUE; 331 break; 332 case 'q': 333 quiet = CSSM_TRUE; 334 break; 335 case 'a': 336 switch(argp[2]) { 337 case 'f': 338 keyGenAlg = CSSM_ALGID_FEE; 339 sigAlg = CSSM_ALGID_FEE_MD5; 340 break; 341 case 'F': 342 keyGenAlg = CSSM_ALGID_FEE; 343 sigAlg = CSSM_ALGID_FEE_SHA1; 344 break; 345 case 'e': 346 keyGenAlg = CSSM_ALGID_FEE; 347 sigAlg = CSSM_ALGID_SHA1WithECDSA; 348 break; 349 case 'E': 350 keyGenAlg = CSSM_ALGID_ECDSA; 351 sigAlg = CSSM_ALGID_SHA1WithECDSA; 352 break; 353 case 'r': 354 break; 355 default: 356 usage(argv); 357 } 358 break; 359 case 'd': 360 numDBs = atoi(&argp[2]); 361 break; 362 case 'A': 363 allInDbs = CSSM_TRUE; 364 break; 365 case 'k': 366 skipFirstDb = CSSM_TRUE; 367 break; 368 #if PUBLIC_READ_ENABLE 369 case 'p': 370 publicRead = CSSM_TRUE; 371 break; 372 #endif 373 case 'f': 374 fileBaseName = &argp[2]; 375 break; 376 case 'P': 377 doPause = CSSM_TRUE; 378 break; 379 case 'h': 380 default: 381 usage(argv); 382 } 383 } 384 385 /* attach to all the modules we need */ 386 cspHand = cspStartup(); 387 if(cspHand == 0) { 388 exit(1); 389 } 390 if(cspHand == 0) { 391 exit(1); 392 } 393 clHand = clStartup(); 394 if(clHand == 0) { 395 goto abort; 396 } 397 tpHand = tpStartup(); 398 if(tpHand == 0) { 399 goto abort; 400 } 401 402 /* malloc empty keys and certs */ 403 pubKeys = (CSSM_KEY_PTR)CSSM_CALLOC(numCerts, sizeof(CSSM_KEY)); 404 privKeys = (CSSM_KEY_PTR)CSSM_CALLOC(numCerts, sizeof(CSSM_KEY)); 405 certs = (CSSM_DATA_PTR)CSSM_CALLOC(numCerts, sizeof(CSSM_DATA)); 406 if((pubKeys == NULL) || (privKeys == NULL) || (certs == NULL)) { 407 printf("not enough memory for %u keys pairs and certs.\n", 408 numCerts); 409 goto abort; 410 } 411 412 printf("Starting cgConstruct; args: "); 413 for(i=1; i<(unsigned)argc; i++) { 414 printf("%s ", argv[i]); 415 } 416 printf("\n"); 417 418 /* generate key pairs */ 419 if(!quiet) { 420 printf("generating keys...\n"); 421 } 422 if(tpGenKeys(cspHand, 423 keyDb, 424 numCerts, 425 keyGenAlg, 426 keySizeInBits, 427 "cgConstruct", // keyLabelBase 428 pubKeys, 429 privKeys)) { 430 goto abort; 431 } 432 notBeforeStr = genTimeAtNowPlus(0); 433 notAfterStr = genTimeAtNowPlus(SECONDS_TO_LIVE); 434 435 #if TP_DB_ENABLE 436 /* create numDbs new DBs */ 437 if(numDBs != 0) { 438 dlHand = dlStartup(); 439 if(dlHand == 0) { 440 exit(1); 441 } 442 dbList.NumHandles = numDBs; 443 dbList.DLDBHandle = 444 (CSSM_DL_DB_HANDLE_PTR)CSSM_CALLOC(numDBs, sizeof(CSSM_DL_DB_HANDLE)); 445 if(!publicRead) { 446 /* 447 * In this case, this is the only time we open these DBs - they 448 * stay open for the duration of the test 449 */ 450 if(verbose) { 451 printf(" ...opening DBs read/write\n"); 452 } 453 if(doOpenDbs(dlHand, 454 fileBaseName, 455 dbList.DLDBHandle, 456 numDBs, 457 CSSM_FALSE, // publicReadOnly: this is create/write 458 quiet)) { 459 goto abort; 460 } 461 } 462 dbListPtr = &dbList; 463 } 464 else { 465 /* it's required anyway... */ 466 dbList.NumHandles = 0; 467 dbList.DLDBHandle = NULL; 468 dbListPtr = &dbList; 469 } 470 #else 471 /* it's required anyway... */ 472 dbList.NumHandles = 0; 473 dbList.DLDBHandle = NULL; 474 dbListPtr = &dbList; 475 #endif 476 477 for(loop=1; ; loop++) { 478 if(!quiet) { 479 printf("...loop %d\n", loop); 480 } 481 if(tpGenCerts(cspHand, 482 clHand, 483 numCerts, 484 sigAlg, 485 "cgConstruct", // nameBase 486 pubKeys, 487 privKeys, 488 certs, 489 notBeforeStr, 490 notAfterStr)) { 491 break; 492 } 493 if(doTest(tpHand, 494 clHand, 495 cspHand, 496 dlHand, 497 dbListPtr, 498 certs, 499 numCerts, 500 verbose, 501 allInDbs, 502 skipFirstDb, 503 publicRead, 504 fileBaseName, 505 quiet)) { 506 break; 507 } 508 for(i=0; i<numCerts; i++) { 509 appFreeCssmData(&certs[i], CSSM_FALSE); 510 } 511 memset(certs, 0, numCerts * sizeof(CSSM_DATA)); 512 513 if(loops && (loop == loops)) { 514 break; 515 } 516 if(doPause) { 517 printf("Hit CR to continue: "); 518 fpurge(stdin); 519 getchar(); 520 } 521 } 522 523abort: 524 /* free keys and certs */ 525 if(privKeys != NULL) { 526 for(i=0; i<numCerts; i++) { 527 if(privKeys[i].KeyData.Data != NULL) { 528 cspFreeKey(cspHand, &privKeys[i]); 529 } 530 } 531 CSSM_FREE(privKeys); 532 } 533 if(pubKeys != NULL) { 534 for(i=0; i<numCerts; i++) { 535 if(pubKeys[i].KeyData.Data != NULL) { 536 cspFreeKey(cspHand, &pubKeys[i]); 537 } 538 } 539 CSSM_FREE(pubKeys); 540 } 541 if(certs != NULL) { 542 for(i=0; i<numCerts; i++) { 543 appFreeCssmData(&certs[i], CSSM_FALSE); 544 } 545 CSSM_FREE(certs); 546 } 547 if(dbList.DLDBHandle != NULL) { 548 /* don't have to close, detach should do that */ 549 CSSM_FREE(dbList.DLDBHandle); 550 } 551 if(cspHand != 0) { 552 CSSM_ModuleDetach(cspHand); 553 } 554 if(clHand != 0) { 555 CSSM_ModuleDetach(clHand); 556 } 557 if(tpHand != 0) { 558 CSSM_ModuleDetach(tpHand); 559 } 560 561 if(!quiet) { 562 printf("%s test complete\n", argv[0]); 563 } 564 return 0; 565} 566