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