#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>
#define NUM_CERTS_DEF 10
#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 SECONDS_TO_LIVE (60 * 60 * 24)
#define PUBLIC_READ_ENABLE 0
static void usage(char **argv)
{
printf("Usage: %s [options]\n", argv[0]);
printf(" Options:\n");
printf(" n=numCerts; default = %d\n", NUM_CERTS_DEF);
printf(" l=loops; default=%d; 0=forever\n", LOOPS_DEF);
printf(" a=alg (f=FEE/MD5, f=FEE/SHA1, e=FEE/ECDSA, r=RSA, E=ANSI ECDSA; default = RSA\n");
printf(" K=keySizeInBits\n");
#if TP_DB_ENABLE
printf(" d=numDBs, default = %d\n", NUM_DBS_DEF);
printf(" A(ll certs to DBs)\n");
printf(" k (skip first DB when storing)\n");
#if PUBLIC_READ_ENABLE
printf(" p(ublic access open on read)\n");
#endif
#endif
printf(" f=fileNameBase (default = %s)\n", DB_NAME_BASE);
printf(" P(ause on each loop)\n");
printf(" v(erbose)\n");
printf(" q(uiet)\n");
printf(" h(elp)\n");
exit(1);
}
#if TP_DB_ENABLE
static int doOpenDbs(
CSSM_DL_HANDLE dlHand,
const char *dbNameBase,
CSSM_DL_DB_HANDLE_PTR dlDbPtr,
unsigned numDbs,
CSSM_BOOL publicReadOnly, CSSM_BOOL quiet)
{
unsigned i;
char dbName[20];
CSSM_BOOL doCreate = (publicReadOnly ? CSSM_FALSE : CSSM_TRUE);
for(i=0; i<numDbs; i++) {
dlDbPtr[i].DLHandle = dlHand;
sprintf(dbName, "%s%d", dbNameBase, i);
CSSM_RETURN crtn = tpKcOpen(dlHand, dbName,
dbName, doCreate,
&dlDbPtr[i].DBHandle);
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_HANDLE dlHand,
CSSM_DL_DB_LIST_PTR dbList,
CSSM_DATA_PTR certs,
unsigned numCerts,
CSSM_BOOL verbose,
CSSM_BOOL allInDbs,
CSSM_BOOL skipFirstDb,
CSSM_BOOL publicRead, const char *fileBaseName,
CSSM_BOOL quiet)
{
unsigned certsToUse; CSSM_CERTGROUP certGroupFrag; CSSM_CERTGROUP_PTR resultGroup; unsigned certDex;
int rtn = 0;
CSSM_RETURN crtn;
#if TP_DB_ENABLE
if(publicRead && (dbList != NULL)) {
if(doOpenDbs(dlHand,
fileBaseName,
dbList->DLDBHandle,
dbList->NumHandles,
CSSM_FALSE,
quiet)) { return 1;
}
}
#endif
certsToUse = genRand(1, numCerts * 2);
if(certsToUse > numCerts) {
certsToUse = numCerts;
}
if(verbose) {
printf(" ...numCerts %d certsToUse %d\n", numCerts, certsToUse);
}
if(tpMakeRandCertGroup(clHand,
#if TP_DB_ENABLE
dbList,
#else
NULL,
#endif
certs,
certsToUse,
&certGroupFrag,
CSSM_TRUE, verbose,
allInDbs,
skipFirstDb)) {
printf("Error in tpMakeRandCertGroup\n");
return testError(quiet);
}
if(certGroupFrag.NumCerts > certsToUse) {
printf("Error NOMAD sterlize\n");
exit(1);
}
#if TP_DB_ENABLE
if(publicRead) {
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", crtn);
if(testError(quiet)) {
return 1;
}
}
}
if(verbose) {
printf(" ...opening DBs read-only\n");
}
if(doOpenDbs(dlHand,
fileBaseName,
dbList->DLDBHandle,
dbList->NumHandles,
CSSM_TRUE, quiet)) {
return 1;
}
}
#endif
crtn = CSSM_TP_CertGroupConstruct(
tpHand,
clHand,
cspHand,
dbList,
NULL, &certGroupFrag,
&resultGroup);
if(crtn) {
printError("CSSM_TP_CertGroupConstruct", crtn);
return testError(quiet);
}
if(verbose) {
printf(" ...CSSM_TP_CertGroupConstruct returned %u certs\n",
(unsigned)resultGroup->NumCerts);
}
if(resultGroup->NumCerts != certsToUse) {
printf("***resultGroup->NumCerts was %u, expected %u\n",
(unsigned)resultGroup->NumCerts, (unsigned)certsToUse);
rtn = testError(quiet);
goto abort;
}
for(certDex=0; certDex<certsToUse; certDex++) {
if(!appCompareCssmData(&certs[certDex],
&resultGroup->GroupList.CertList[certDex])) {
printf("***certs[%d] miscompare\n", certDex);
rtn = testError(quiet);
goto abort;
}
}
abort:
tpFreeCertGroup(&certGroupFrag,
CSSM_FALSE, CSSM_FALSE); tpFreeCertGroup(resultGroup,
CSSM_TRUE, CSSM_TRUE); #if TP_DB_ENABLE
if(dbList != NULL) {
unsigned 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", crtn);
if(testError(quiet)) {
return 1;
}
}
}
}
}
#endif
return rtn;
}
int main(int argc, char **argv)
{
int arg;
char *argp;
unsigned loop;
CSSM_TP_HANDLE tpHand = 0;
CSSM_CL_HANDLE clHand = 0;
CSSM_CSP_HANDLE cspHand = 0;
CSSM_DL_DB_LIST dbList = {0, NULL};
CSSM_DL_DB_LIST_PTR dbListPtr;
unsigned i;
char *notAfterStr;
char *notBeforeStr;
CSSM_DL_HANDLE dlHand;
CSSM_KEY_PTR pubKeys = NULL;
CSSM_KEY_PTR privKeys = NULL;
CSSM_DATA_PTR certs = NULL;
CSSM_DL_DB_HANDLE keyDb = {0, 0};
unsigned loops = LOOPS_DEF;
CSSM_BOOL verbose = CSSM_FALSE;
CSSM_BOOL quiet = CSSM_FALSE;
unsigned numCerts = NUM_CERTS_DEF;
uint32 keyGenAlg = KEYGEN_ALG_DEF;
uint32 sigAlg = SIG_ALG_DEF;
unsigned numDBs = NUM_DBS_DEF;
CSSM_BOOL allInDbs = CSSM_FALSE;
CSSM_BOOL skipFirstDb = CSSM_FALSE;
CSSM_BOOL publicRead = CSSM_FALSE;
CSSM_BOOL doPause = CSSM_FALSE;
uint32 keySizeInBits = CSP_KEY_SIZE_DEFAULT;
const char *fileBaseName = DB_NAME_BASE;
for(arg=1; arg<argc; arg++) {
argp = argv[arg];
switch(argp[0]) {
case 'l':
loops = atoi(&argp[2]);
break;
case 'n':
numCerts = atoi(&argp[2]);
break;
case 'K':
keySizeInBits = atoi(&argp[2]);
break;
case 'v':
verbose = CSSM_TRUE;
break;
case 'q':
quiet = CSSM_TRUE;
break;
case 'a':
switch(argp[2]) {
case 'f':
keyGenAlg = CSSM_ALGID_FEE;
sigAlg = CSSM_ALGID_FEE_MD5;
break;
case 'F':
keyGenAlg = CSSM_ALGID_FEE;
sigAlg = CSSM_ALGID_FEE_SHA1;
break;
case 'e':
keyGenAlg = CSSM_ALGID_FEE;
sigAlg = CSSM_ALGID_SHA1WithECDSA;
break;
case 'E':
keyGenAlg = CSSM_ALGID_ECDSA;
sigAlg = CSSM_ALGID_SHA1WithECDSA;
break;
case 'r':
break;
default:
usage(argv);
}
break;
case 'd':
numDBs = atoi(&argp[2]);
break;
case 'A':
allInDbs = CSSM_TRUE;
break;
case 'k':
skipFirstDb = CSSM_TRUE;
break;
#if PUBLIC_READ_ENABLE
case 'p':
publicRead = CSSM_TRUE;
break;
#endif
case 'f':
fileBaseName = &argp[2];
break;
case 'P':
doPause = CSSM_TRUE;
break;
case 'h':
default:
usage(argv);
}
}
cspHand = cspStartup();
if(cspHand == 0) {
exit(1);
}
if(cspHand == 0) {
exit(1);
}
clHand = clStartup();
if(clHand == 0) {
goto abort;
}
tpHand = tpStartup();
if(tpHand == 0) {
goto abort;
}
pubKeys = (CSSM_KEY_PTR)CSSM_CALLOC(numCerts, sizeof(CSSM_KEY));
privKeys = (CSSM_KEY_PTR)CSSM_CALLOC(numCerts, sizeof(CSSM_KEY));
certs = (CSSM_DATA_PTR)CSSM_CALLOC(numCerts, sizeof(CSSM_DATA));
if((pubKeys == NULL) || (privKeys == NULL) || (certs == NULL)) {
printf("not enough memory for %u keys pairs and certs.\n",
numCerts);
goto abort;
}
printf("Starting cgConstruct; args: ");
for(i=1; i<(unsigned)argc; i++) {
printf("%s ", argv[i]);
}
printf("\n");
if(!quiet) {
printf("generating keys...\n");
}
if(tpGenKeys(cspHand,
keyDb,
numCerts,
keyGenAlg,
keySizeInBits,
"cgConstruct", pubKeys,
privKeys)) {
goto abort;
}
notBeforeStr = genTimeAtNowPlus(0);
notAfterStr = genTimeAtNowPlus(SECONDS_TO_LIVE);
#if TP_DB_ENABLE
if(numDBs != 0) {
dlHand = dlStartup();
if(dlHand == 0) {
exit(1);
}
dbList.NumHandles = numDBs;
dbList.DLDBHandle =
(CSSM_DL_DB_HANDLE_PTR)CSSM_CALLOC(numDBs, sizeof(CSSM_DL_DB_HANDLE));
if(!publicRead) {
if(verbose) {
printf(" ...opening DBs read/write\n");
}
if(doOpenDbs(dlHand,
fileBaseName,
dbList.DLDBHandle,
numDBs,
CSSM_FALSE, quiet)) {
goto abort;
}
}
dbListPtr = &dbList;
}
else {
dbList.NumHandles = 0;
dbList.DLDBHandle = NULL;
dbListPtr = &dbList;
}
#else
dbList.NumHandles = 0;
dbList.DLDBHandle = NULL;
dbListPtr = &dbList;
#endif
for(loop=1; ; loop++) {
if(!quiet) {
printf("...loop %d\n", loop);
}
if(tpGenCerts(cspHand,
clHand,
numCerts,
sigAlg,
"cgConstruct", pubKeys,
privKeys,
certs,
notBeforeStr,
notAfterStr)) {
break;
}
if(doTest(tpHand,
clHand,
cspHand,
dlHand,
dbListPtr,
certs,
numCerts,
verbose,
allInDbs,
skipFirstDb,
publicRead,
fileBaseName,
quiet)) {
break;
}
for(i=0; i<numCerts; i++) {
appFreeCssmData(&certs[i], CSSM_FALSE);
}
memset(certs, 0, numCerts * sizeof(CSSM_DATA));
if(loops && (loop == loops)) {
break;
}
if(doPause) {
printf("Hit CR to continue: ");
fpurge(stdin);
getchar();
}
}
abort:
if(privKeys != NULL) {
for(i=0; i<numCerts; i++) {
if(privKeys[i].KeyData.Data != NULL) {
cspFreeKey(cspHand, &privKeys[i]);
}
}
CSSM_FREE(privKeys);
}
if(pubKeys != NULL) {
for(i=0; i<numCerts; i++) {
if(pubKeys[i].KeyData.Data != NULL) {
cspFreeKey(cspHand, &pubKeys[i]);
}
}
CSSM_FREE(pubKeys);
}
if(certs != NULL) {
for(i=0; i<numCerts; i++) {
appFreeCssmData(&certs[i], CSSM_FALSE);
}
CSSM_FREE(certs);
}
if(dbList.DLDBHandle != NULL) {
CSSM_FREE(dbList.DLDBHandle);
}
if(cspHand != 0) {
CSSM_ModuleDetach(cspHand);
}
if(clHand != 0) {
CSSM_ModuleDetach(clHand);
}
if(tpHand != 0) {
CSSM_ModuleDetach(tpHand);
}
if(!quiet) {
printf("%s test complete\n", argv[0]);
}
return 0;
}