1/* cgConstructThr.cpp - simple version CertGroupConstruct test */ 2 3#include "testParams.h" 4#include <Security/cssm.h> 5#include <utilLib/common.h> 6#include <utilLib/cspwrap.h> 7#include <clAppUtils/clutils.h> 8#include <clAppUtils/tpUtils.h> 9#include <clAppUtils/timeStr.h> 10#include <stdio.h> 11#include <stdlib.h> 12#include <time.h> 13#include <string.h> 14 15/* for memory leak debug only, with only one thread running */ 16#define DO_PAUSE 0 17 18/*** start of code directly copied from ../cgConstruct/cgConstruct.cpp ***/ 19#define NUM_CERTS_MIN 4 20#define NUM_DBS_DEF 3 21#define KEYGEN_ALG_DEF CSSM_ALGID_RSA 22#define SIG_ALG_DEF CSSM_ALGID_SHA1WithRSA 23#define LOOPS_DEF 10 24#define DB_NAME_BASE "cgConstruct" 25#define CG_KEY_SIZE_DEFAULT CSP_RSA_KEY_SIZE_DEFAULT 26#define SECONDS_TO_LIVE (60 * 60 * 24) /* certs are valid for this long */ 27 28#define CG_CONSTRUCT_TP_DB 0 29 30static int testError() 31{ 32 char resp; 33 34 fpurge(stdin); 35 printf("Attach via debugger for more info.\n"); 36 printf("a to abort, c to continue: "); 37 resp = getchar(); 38 return (resp == 'a'); 39} 40 41#if CG_CONSTRUCT_TP_DB 42static int doOpenDbs( 43 CSSM_DL_HANDLE dlHand, 44 char *dbNameBase, 45 CSSM_DL_DB_HANDLE_PTR dlDbPtr, 46 unsigned numDbs, 47 CSSM_BOOL publicReadOnly, // ignored if !PUBLIC_READ_ENABLE 48 CSSM_BOOL quiet) 49{ 50 unsigned i; 51 char dbName[20]; 52 CSSM_BOOL doCreate = (publicReadOnly ? CSSM_FALSE : CSSM_TRUE); 53 54 for(i=0; i<numDbs; i++) { 55 sprintf(dbName, "%s%d", dbNameBase, i); 56 CSSM_RETURN crtn = tpKcOpen(dbName, 57 &dlDbPtr[i], 58 doCreate, 59 dlHand); 60 if(crtn) { 61 printf("Can't create %d DBs\n", numDbs); 62 return testError(quiet); 63 } 64 } 65 return 0; 66} 67#endif 68 69static int doTest( 70 CSSM_TP_HANDLE tpHand, 71 CSSM_CL_HANDLE clHand, 72 CSSM_CSP_HANDLE cspHand, 73 CSSM_DL_DB_LIST_PTR dbList, 74 CSSM_DATA_PTR certs, 75 unsigned numCerts, 76 CSSM_BOOL verbose, 77 CSSM_BOOL allInDbs, 78 CSSM_BOOL skipFirstDb, 79 CSSM_BOOL publicRead) // close/open with public access 80{ 81 unsigned certsToUse; // # of certs we actually use 82 CSSM_CERTGROUP certGroupFrag; // INPUT to CertGroupConstruct 83 CSSM_CERTGROUP_PTR resultGroup; // OUTPUT from " 84 unsigned certDex; 85 int rtn = 0; 86 CSSM_RETURN crtn; 87 88 #if CG_CONSTRUCT_TP_DB 89 if(publicRead && (dbList != NULL)) { 90 /* DBs are closed on entry, open r/w */ 91 if(doOpenDbs(0, 92 DB_NAME_BASE, 93 dbList->DLDBHandle, 94 dbList->NumHandles, 95 CSSM_FALSE, 96 quiet)) { // publicReadOnly: this is create/write 97 return 1; 98 } 99 } 100 /* else DBs are already open and stay that way */ 101 #endif 102 103 /* 104 * Pick a random spot to break the cert chain - half the time use the 105 * whole chain, half the time break it. 106 */ 107 certsToUse = genRand(1, numCerts * 2); 108 if(certsToUse > numCerts) { 109 /* use the whole chain */ 110 certsToUse = numCerts; 111 } 112 if(verbose) { 113 printf(" ...numCerts %d certsToUse %d\n", numCerts, certsToUse); 114 } 115 116 if(tpMakeRandCertGroup(clHand, 117 #if CG_CONSTRUCT_TP_DB 118 dbList, 119 #else 120 NULL, 121 #endif 122 certs, 123 certsToUse, 124 &certGroupFrag, 125 CSSM_TRUE, // firstCertIsSubject 126 verbose, 127 allInDbs, 128 skipFirstDb)) { 129 printf("\nError in tpMakeRandCertGroup\n"); 130 return testError(); 131 } 132 133 if(certGroupFrag.NumCerts > certsToUse) { 134 printf("Error NOMAD sterlize\n"); 135 exit(1); 136 } 137 138 #if CG_CONSTRUCT_TP_DB 139 if(publicRead) { 140 /* close existing DBs and open again read-only */ 141 142 unsigned i; 143 CSSM_RETURN crtn; 144 145 if(verbose) { 146 printf(" ...closing DBs\n"); 147 } 148 for(i=0; i<dbList->NumHandles; i++) { 149 crtn = CSSM_DL_DbClose(dbList->DLDBHandle[i]); 150 if(crtn) { 151 printError("CSSM_DL_DbClose"); 152 if(testError()) { 153 return 1; 154 } 155 } 156 } 157 if(verbose) { 158 printf(" ...opening DBs read-only\n"); 159 } 160 if(doOpenDbs(0, 161 DB_NAME_BASE, 162 dbList->DLDBHandle, 163 dbList->NumHandles, 164 CSSM_TRUE, // publicReadOnly: this is read only 165 quiet)) { 166 return 1; 167 } 168 } 169 #endif 170 171 /* 172 * Okay, some of the certs we were given are in the DB, some are in 173 * random places in certGroupFrag, some are nowhere (if certsToUse is 174 * less than numCerts). Have the TP construct us an ordered verified 175 * group. 176 */ 177 crtn = CSSM_TP_CertGroupConstruct( 178 tpHand, 179 clHand, 180 cspHand, 181 dbList, 182 NULL, // ConstructParams 183 &certGroupFrag, 184 &resultGroup); 185 if(crtn) { 186 printError("CSSM_TP_CertGroupConstruct", crtn); 187 return testError(); 188 } 189 190 /* vfy resultGroup is identical to unbroken part of chain */ 191 if(verbose) { 192 printf(" ...CSSM_TP_CertGroupConstruct returned %u certs\n", 193 (unsigned)resultGroup->NumCerts); 194 } 195 if(resultGroup->NumCerts != certsToUse) { 196 printf("\n***cgConstruct: resultGroup->NumCerts was %u, expected %u\n", 197 (unsigned)resultGroup->NumCerts, (unsigned)certsToUse); 198 rtn = testError(); 199 goto abort; 200 } 201 for(certDex=0; certDex<certsToUse; certDex++) { 202 if(!appCompareCssmData(&certs[certDex], 203 &resultGroup->GroupList.CertList[certDex])) { 204 printf("\ncgConstruct: ***certs[%d] miscompare\n", certDex); 205 rtn = testError(); 206 goto abort; 207 } 208 } 209abort: 210 /* free resurces */ 211 tpFreeCertGroup(&certGroupFrag, 212 CSSM_FALSE, // caller malloc'd the actual certs 213 CSSM_FALSE); // struct is on stack 214 tpFreeCertGroup(resultGroup, 215 CSSM_TRUE, // mallocd by TP 216 CSSM_TRUE); // ditto 217 #if CG_CONSTRUCT_TP_DB 218 if(dbList != NULL) { 219 int i; 220 CSSM_RETURN crtn; 221 222 if(verbose) { 223 printf(" ...deleting all certs from DBs\n"); 224 } 225 for(i=0; i<dbList->NumHandles; i++) { 226 clDeleteAllCerts(dbList->DLDBHandle[i]); 227 } 228 if(publicRead) { 229 if(verbose) { 230 printf(" ...closing DBs\n"); 231 } 232 for(i=0; i<dbList->NumHandles; i++) { 233 crtn = CSSM_DL_DbClose(dbList->DLDBHandle[i]); 234 if(crtn) { 235 printError("CSSM_DL_DbClose"); 236 if(testError()) { 237 return 1; 238 } 239 } 240 } 241 } 242 } 243 #endif 244 return rtn; 245} 246/*** end of code directly copied from ../cgConstruct/cgConstruct.cpp ***/ 247 248/* 249 * key pairs - created in cgConstructInit, stored in testParams->perThread 250 */ 251typedef struct { 252 CSSM_KEY_PTR pubKeys; 253 CSSM_KEY_PTR privKeys; 254 unsigned numKeys; 255 char *notBeforeStr; // to use thread-safe tpGenCerts() 256 char *notAfterStr; // to use thread-safe tpGenCerts() 257} TT_KeyPairs; 258 259int cgConstructInit(TestParams *testParams) 260{ 261 unsigned numKeys = NUM_CERTS_MIN + testParams->threadNum; 262 TT_KeyPairs *keyPairs; 263 264 if(testParams->verbose) { 265 printf("cgConstruct thread %d: generating keys...\n", 266 testParams->threadNum); 267 } 268 keyPairs = (TT_KeyPairs *)CSSM_MALLOC(sizeof(TT_KeyPairs)); 269 keyPairs->numKeys = numKeys; 270 keyPairs->pubKeys = (CSSM_KEY_PTR)CSSM_CALLOC(numKeys, sizeof(CSSM_KEY)); 271 keyPairs->privKeys = (CSSM_KEY_PTR)CSSM_CALLOC(numKeys, sizeof(CSSM_KEY)); 272 CSSM_DL_DB_HANDLE nullDb = {0, 0}; 273 if(tpGenKeys(testParams->cspHand, 274 nullDb, // dbHand 275 numKeys, 276 KEYGEN_ALG_DEF, 277 CG_KEY_SIZE_DEFAULT, 278 "cgConstruct", // keyLabelBase 279 keyPairs->pubKeys, 280 keyPairs->privKeys)) { 281 goto abort; 282 } 283 keyPairs->notBeforeStr = genTimeAtNowPlus(0); 284 keyPairs->notAfterStr = genTimeAtNowPlus(SECONDS_TO_LIVE); 285 286 testParams->perThread = keyPairs; 287 return 0; 288 289abort: 290 printf("Error generating keys; aborting\n"); 291 CSSM_FREE(keyPairs->pubKeys); 292 CSSM_FREE(keyPairs->privKeys); 293 CSSM_FREE(keyPairs); 294 return 1; 295} 296 297int cgConstruct(TestParams *testParams) 298{ 299 unsigned loopNum; 300 int status = -1; // exit status, default = error 301 TT_KeyPairs *keyPairs = (TT_KeyPairs *)testParams->perThread; 302 unsigned dex; 303 304 /* all three of these are arrays with numCert elements */ 305 CSSM_KEY_PTR pubKeys = keyPairs->pubKeys; 306 CSSM_KEY_PTR privKeys = keyPairs->privKeys; 307 CSSM_DATA_PTR certs = NULL; 308 309 unsigned numCerts = keyPairs->numKeys; 310 uint32 sigAlg = SIG_ALG_DEF; 311 CSSM_DL_DB_LIST dbList = {0, NULL}; /* for storing certs */ 312 CSSM_DL_DB_LIST_PTR dbListPtr; /* pts to dbList or NULL */ 313 CSSM_BOOL publicRead = CSSM_FALSE; 314 CSSM_BOOL allInDbs = CSSM_FALSE; 315 CSSM_BOOL skipFirstDb = CSSM_FALSE; 316 317 /* malloc empty certs */ 318 certs = (CSSM_DATA_PTR)CSSM_CALLOC(numCerts, sizeof(CSSM_DATA)); 319 if(certs == NULL) { 320 printf("not enough memory for %u certs.\n", numCerts); 321 goto abort; 322 } 323 memset(certs, 0, numCerts * sizeof(CSSM_DATA)); 324 325 dbList.NumHandles = 0; 326 dbList.DLDBHandle = NULL; 327 dbListPtr = &dbList; 328 for(loopNum=0; loopNum<testParams->numLoops; loopNum++) { 329 330 /* generate certs */ 331 if(testParams->verbose) { 332 printf("cgConstruct thread %d: generating certs...\n", 333 testParams->threadNum); 334 } 335 else if(!testParams->quiet) { 336 printChar(testParams->progressChar); 337 } 338 if(tpGenCerts(testParams->cspHand, 339 testParams->clHand, 340 numCerts, 341 sigAlg, 342 "cgConstruct", // nameBase 343 pubKeys, 344 privKeys, 345 certs, 346 keyPairs->notBeforeStr, 347 keyPairs->notAfterStr)) { 348 status = 1; 349 goto abort; 350 } 351 352 status = doTest(testParams->tpHand, 353 testParams->clHand, 354 testParams->cspHand, 355 dbListPtr, 356 certs, 357 numCerts, 358 testParams->verbose, 359 allInDbs, 360 skipFirstDb, 361 publicRead); 362 if(status) { 363 break; 364 } 365 366 /* free certs */ 367 for(dex=0; dex<numCerts; dex++) { 368 CSSM_FREE(certs[dex].Data); 369 } 370 memset(certs, 0, numCerts * sizeof(CSSM_DATA)); 371 372 #if DO_PAUSE 373 fpurge(stdin); 374 printf("Hit CR to proceed: "); 375 getchar(); 376 #endif 377 } 378abort: 379 /* free resources */ 380 for(dex=0; dex<numCerts; dex++) { 381 if(certs[dex].Data) { 382 CSSM_FREE(certs[dex].Data); 383 } 384 } 385 CSSM_FREE(keyPairs->pubKeys); 386 CSSM_FREE(keyPairs->privKeys); 387 CSSM_FREE(keyPairs); 388 return status; 389} 390 391