]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/cgConstruct/cgConstruct.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / cgConstruct / cgConstruct.cpp
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
43 static 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
68 static 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
96 static 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 }
239 abort:
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
277 int 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
523 abort:
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 }