--- /dev/null
+/* cgConstructThr.cpp - simple version CertGroupConstruct test */
+
+#include "testParams.h"
+#include <Security/cssm.h>
+#include <utilLib/common.h>
+#include <utilLib/cspwrap.h>
+#include <clAppUtils/clutils.h>
+#include <clAppUtils/tpUtils.h>
+#include <clAppUtils/timeStr.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+
+/* for memory leak debug only, with only one thread running */
+#define DO_PAUSE 0
+
+/*** start of code directly copied from ../cgConstruct/cgConstruct.cpp ***/
+#define NUM_CERTS_MIN 4
+#define NUM_DBS_DEF 3
+#define KEYGEN_ALG_DEF CSSM_ALGID_RSA
+#define SIG_ALG_DEF CSSM_ALGID_SHA1WithRSA
+#define LOOPS_DEF 10
+#define DB_NAME_BASE "cgConstruct"
+#define CG_KEY_SIZE_DEFAULT CSP_RSA_KEY_SIZE_DEFAULT
+#define SECONDS_TO_LIVE (60 * 60 * 24) /* certs are valid for this long */
+
+#define CG_CONSTRUCT_TP_DB 0
+
+static int testError()
+{
+ char resp;
+
+ fpurge(stdin);
+ printf("Attach via debugger for more info.\n");
+ printf("a to abort, c to continue: ");
+ resp = getchar();
+ return (resp == 'a');
+}
+
+#if CG_CONSTRUCT_TP_DB
+static int doOpenDbs(
+ CSSM_DL_HANDLE dlHand,
+ char *dbNameBase,
+ CSSM_DL_DB_HANDLE_PTR dlDbPtr,
+ unsigned numDbs,
+ CSSM_BOOL publicReadOnly, // ignored if !PUBLIC_READ_ENABLE
+ CSSM_BOOL quiet)
+{
+ unsigned i;
+ char dbName[20];
+ CSSM_BOOL doCreate = (publicReadOnly ? CSSM_FALSE : CSSM_TRUE);
+
+ for(i=0; i<numDbs; i++) {
+ sprintf(dbName, "%s%d", dbNameBase, i);
+ CSSM_RETURN crtn = tpKcOpen(dbName,
+ &dlDbPtr[i],
+ doCreate,
+ dlHand);
+ if(crtn) {
+ printf("Can't create %d DBs\n", numDbs);
+ return testError(quiet);
+ }
+ }
+ return 0;
+}
+#endif
+
+static int doTest(
+ CSSM_TP_HANDLE tpHand,
+ CSSM_CL_HANDLE clHand,
+ CSSM_CSP_HANDLE cspHand,
+ CSSM_DL_DB_LIST_PTR dbList,
+ CSSM_DATA_PTR certs,
+ unsigned numCerts,
+ CSSM_BOOL verbose,
+ CSSM_BOOL allInDbs,
+ CSSM_BOOL skipFirstDb,
+ CSSM_BOOL publicRead) // close/open with public access
+{
+ unsigned certsToUse; // # of certs we actually use
+ CSSM_CERTGROUP certGroupFrag; // INPUT to CertGroupConstruct
+ CSSM_CERTGROUP_PTR resultGroup; // OUTPUT from "
+ unsigned certDex;
+ int rtn = 0;
+ CSSM_RETURN crtn;
+
+ #if CG_CONSTRUCT_TP_DB
+ if(publicRead && (dbList != NULL)) {
+ /* DBs are closed on entry, open r/w */
+ if(doOpenDbs(0,
+ DB_NAME_BASE,
+ dbList->DLDBHandle,
+ dbList->NumHandles,
+ CSSM_FALSE,
+ quiet)) { // publicReadOnly: this is create/write
+ return 1;
+ }
+ }
+ /* else DBs are already open and stay that way */
+ #endif
+
+ /*
+ * Pick a random spot to break the cert chain - half the time use the
+ * whole chain, half the time break it.
+ */
+ certsToUse = genRand(1, numCerts * 2);
+ if(certsToUse > numCerts) {
+ /* use the whole chain */
+ certsToUse = numCerts;
+ }
+ if(verbose) {
+ printf(" ...numCerts %d certsToUse %d\n", numCerts, certsToUse);
+ }
+
+ if(tpMakeRandCertGroup(clHand,
+ #if CG_CONSTRUCT_TP_DB
+ dbList,
+ #else
+ NULL,
+ #endif
+ certs,
+ certsToUse,
+ &certGroupFrag,
+ CSSM_TRUE, // firstCertIsSubject
+ verbose,
+ allInDbs,
+ skipFirstDb)) {
+ printf("\nError in tpMakeRandCertGroup\n");
+ return testError();
+ }
+
+ if(certGroupFrag.NumCerts > certsToUse) {
+ printf("Error NOMAD sterlize\n");
+ exit(1);
+ }
+
+ #if CG_CONSTRUCT_TP_DB
+ if(publicRead) {
+ /* close existing DBs and open again read-only */
+
+ unsigned i;
+ CSSM_RETURN crtn;
+
+ if(verbose) {
+ printf(" ...closing DBs\n");
+ }
+ for(i=0; i<dbList->NumHandles; i++) {
+ crtn = CSSM_DL_DbClose(dbList->DLDBHandle[i]);
+ if(crtn) {
+ printError("CSSM_DL_DbClose");
+ if(testError()) {
+ return 1;
+ }
+ }
+ }
+ if(verbose) {
+ printf(" ...opening DBs read-only\n");
+ }
+ if(doOpenDbs(0,
+ DB_NAME_BASE,
+ dbList->DLDBHandle,
+ dbList->NumHandles,
+ CSSM_TRUE, // publicReadOnly: this is read only
+ quiet)) {
+ return 1;
+ }
+ }
+ #endif
+
+ /*
+ * Okay, some of the certs we were given are in the DB, some are in
+ * random places in certGroupFrag, some are nowhere (if certsToUse is
+ * less than numCerts). Have the TP construct us an ordered verified
+ * group.
+ */
+ crtn = CSSM_TP_CertGroupConstruct(
+ tpHand,
+ clHand,
+ cspHand,
+ dbList,
+ NULL, // ConstructParams
+ &certGroupFrag,
+ &resultGroup);
+ if(crtn) {
+ printError("CSSM_TP_CertGroupConstruct", crtn);
+ return testError();
+ }
+
+ /* vfy resultGroup is identical to unbroken part of chain */
+ if(verbose) {
+ printf(" ...CSSM_TP_CertGroupConstruct returned %u certs\n",
+ (unsigned)resultGroup->NumCerts);
+ }
+ if(resultGroup->NumCerts != certsToUse) {
+ printf("\n***cgConstruct: resultGroup->NumCerts was %u, expected %u\n",
+ (unsigned)resultGroup->NumCerts, (unsigned)certsToUse);
+ rtn = testError();
+ goto abort;
+ }
+ for(certDex=0; certDex<certsToUse; certDex++) {
+ if(!appCompareCssmData(&certs[certDex],
+ &resultGroup->GroupList.CertList[certDex])) {
+ printf("\ncgConstruct: ***certs[%d] miscompare\n", certDex);
+ rtn = testError();
+ goto abort;
+ }
+ }
+abort:
+ /* free resurces */
+ tpFreeCertGroup(&certGroupFrag,
+ CSSM_FALSE, // caller malloc'd the actual certs
+ CSSM_FALSE); // struct is on stack
+ tpFreeCertGroup(resultGroup,
+ CSSM_TRUE, // mallocd by TP
+ CSSM_TRUE); // ditto
+ #if CG_CONSTRUCT_TP_DB
+ if(dbList != NULL) {
+ int i;
+ CSSM_RETURN crtn;
+
+ if(verbose) {
+ printf(" ...deleting all certs from DBs\n");
+ }
+ for(i=0; i<dbList->NumHandles; i++) {
+ clDeleteAllCerts(dbList->DLDBHandle[i]);
+ }
+ if(publicRead) {
+ if(verbose) {
+ printf(" ...closing DBs\n");
+ }
+ for(i=0; i<dbList->NumHandles; i++) {
+ crtn = CSSM_DL_DbClose(dbList->DLDBHandle[i]);
+ if(crtn) {
+ printError("CSSM_DL_DbClose");
+ if(testError()) {
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ #endif
+ return rtn;
+}
+/*** end of code directly copied from ../cgConstruct/cgConstruct.cpp ***/
+
+/*
+ * key pairs - created in cgConstructInit, stored in testParams->perThread
+ */
+typedef struct {
+ CSSM_KEY_PTR pubKeys;
+ CSSM_KEY_PTR privKeys;
+ unsigned numKeys;
+ char *notBeforeStr; // to use thread-safe tpGenCerts()
+ char *notAfterStr; // to use thread-safe tpGenCerts()
+} TT_KeyPairs;
+
+int cgConstructInit(TestParams *testParams)
+{
+ unsigned numKeys = NUM_CERTS_MIN + testParams->threadNum;
+ TT_KeyPairs *keyPairs;
+
+ if(testParams->verbose) {
+ printf("cgConstruct thread %d: generating keys...\n",
+ testParams->threadNum);
+ }
+ keyPairs = (TT_KeyPairs *)CSSM_MALLOC(sizeof(TT_KeyPairs));
+ keyPairs->numKeys = numKeys;
+ keyPairs->pubKeys = (CSSM_KEY_PTR)CSSM_CALLOC(numKeys, sizeof(CSSM_KEY));
+ keyPairs->privKeys = (CSSM_KEY_PTR)CSSM_CALLOC(numKeys, sizeof(CSSM_KEY));
+ CSSM_DL_DB_HANDLE nullDb = {0, 0};
+ if(tpGenKeys(testParams->cspHand,
+ nullDb, // dbHand
+ numKeys,
+ KEYGEN_ALG_DEF,
+ CG_KEY_SIZE_DEFAULT,
+ "cgConstruct", // keyLabelBase
+ keyPairs->pubKeys,
+ keyPairs->privKeys)) {
+ goto abort;
+ }
+ keyPairs->notBeforeStr = genTimeAtNowPlus(0);
+ keyPairs->notAfterStr = genTimeAtNowPlus(SECONDS_TO_LIVE);
+
+ testParams->perThread = keyPairs;
+ return 0;
+
+abort:
+ printf("Error generating keys; aborting\n");
+ CSSM_FREE(keyPairs->pubKeys);
+ CSSM_FREE(keyPairs->privKeys);
+ CSSM_FREE(keyPairs);
+ return 1;
+}
+
+int cgConstruct(TestParams *testParams)
+{
+ unsigned loopNum;
+ int status = -1; // exit status, default = error
+ TT_KeyPairs *keyPairs = (TT_KeyPairs *)testParams->perThread;
+ unsigned dex;
+
+ /* all three of these are arrays with numCert elements */
+ CSSM_KEY_PTR pubKeys = keyPairs->pubKeys;
+ CSSM_KEY_PTR privKeys = keyPairs->privKeys;
+ CSSM_DATA_PTR certs = NULL;
+
+ unsigned numCerts = keyPairs->numKeys;
+ uint32 sigAlg = SIG_ALG_DEF;
+ CSSM_DL_DB_LIST dbList = {0, NULL}; /* for storing certs */
+ CSSM_DL_DB_LIST_PTR dbListPtr; /* pts to dbList or NULL */
+ CSSM_BOOL publicRead = CSSM_FALSE;
+ CSSM_BOOL allInDbs = CSSM_FALSE;
+ CSSM_BOOL skipFirstDb = CSSM_FALSE;
+
+ /* malloc empty certs */
+ certs = (CSSM_DATA_PTR)CSSM_CALLOC(numCerts, sizeof(CSSM_DATA));
+ if(certs == NULL) {
+ printf("not enough memory for %u certs.\n", numCerts);
+ goto abort;
+ }
+ memset(certs, 0, numCerts * sizeof(CSSM_DATA));
+
+ dbList.NumHandles = 0;
+ dbList.DLDBHandle = NULL;
+ dbListPtr = &dbList;
+ for(loopNum=0; loopNum<testParams->numLoops; loopNum++) {
+
+ /* generate certs */
+ if(testParams->verbose) {
+ printf("cgConstruct thread %d: generating certs...\n",
+ testParams->threadNum);
+ }
+ else if(!testParams->quiet) {
+ printChar(testParams->progressChar);
+ }
+ if(tpGenCerts(testParams->cspHand,
+ testParams->clHand,
+ numCerts,
+ sigAlg,
+ "cgConstruct", // nameBase
+ pubKeys,
+ privKeys,
+ certs,
+ keyPairs->notBeforeStr,
+ keyPairs->notAfterStr)) {
+ status = 1;
+ goto abort;
+ }
+
+ status = doTest(testParams->tpHand,
+ testParams->clHand,
+ testParams->cspHand,
+ dbListPtr,
+ certs,
+ numCerts,
+ testParams->verbose,
+ allInDbs,
+ skipFirstDb,
+ publicRead);
+ if(status) {
+ break;
+ }
+
+ /* free certs */
+ for(dex=0; dex<numCerts; dex++) {
+ CSSM_FREE(certs[dex].Data);
+ }
+ memset(certs, 0, numCerts * sizeof(CSSM_DATA));
+
+ #if DO_PAUSE
+ fpurge(stdin);
+ printf("Hit CR to proceed: ");
+ getchar();
+ #endif
+ }
+abort:
+ /* free resources */
+ for(dex=0; dex<numCerts; dex++) {
+ if(certs[dex].Data) {
+ CSSM_FREE(certs[dex].Data);
+ }
+ }
+ CSSM_FREE(keyPairs->pubKeys);
+ CSSM_FREE(keyPairs->privKeys);
+ CSSM_FREE(keyPairs);
+ return status;
+}
+