]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTests/clxutils/cgConstruct/cgConstruct.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / cgConstruct / cgConstruct.cpp
diff --git a/SecurityTests/clxutils/cgConstruct/cgConstruct.cpp b/SecurityTests/clxutils/cgConstruct/cgConstruct.cpp
new file mode 100644 (file)
index 0000000..aa27de9
--- /dev/null
@@ -0,0 +1,565 @@
+/*
+ * cgConstruct.c - basic test of TP's CertGroupConstruct
+ *
+ * cook up array of n key pairs;
+ * cook up cert chain to go with them;
+ * main test loop {
+ *     pick a random spot to break the cert chain - half the time use the
+ *             whole chain, half the time break it;
+ *     cook up CertGroup frag big enough for the unbroken part of the chain;
+ *     put cert[0] in certGroup[0];
+ *     for each cert from cert[1] to break point {
+ *             roll the  dice and put the cert in either a random place
+ *                     in certGroup or in DB;
+ *     }
+ *  resultGroup = certGroupConstruct();
+ *  vfy result Grp is identical to unbroken part of chain;
+ *  delete certs from DB;
+ * }
+ */
+#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"   /* default */
+#define SECONDS_TO_LIVE                (60 * 60 * 24)  /* certs are valid for this long */
+
+/* Read-only access not supported */ 
+#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,         // 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++) {
+               dlDbPtr[i].DLHandle = dlHand;
+               sprintf(dbName, "%s%d", dbNameBase, i);
+               CSSM_RETURN crtn = tpKcOpen(dlHand, dbName, 
+                       dbName,                 // file name as pwd
+                       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,             // close/open with public access
+       const char                      *fileBaseName,
+       CSSM_BOOL                       quiet)
+{
+       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     TP_DB_ENABLE
+       if(publicRead && (dbList != NULL)) {
+               /* DBs are closed on entry, open r/w */
+               if(doOpenDbs(dlHand,
+                               fileBaseName,
+                               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             TP_DB_ENABLE
+                       dbList,
+                       #else
+                       NULL,
+                       #endif
+                       certs,
+                       certsToUse,
+                       &certGroupFrag,
+                       CSSM_TRUE,                      // firstCertIsSubject
+                       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) {
+               /* 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", crtn);
+                               if(testError(quiet)) {
+                                       return 1;
+                               }
+                       }
+               }
+               if(verbose) {
+                       printf("   ...opening DBs read-only\n");
+               }
+               if(doOpenDbs(dlHand,
+                               fileBaseName,
+                               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(quiet);
+       }
+       
+       /* 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("***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:
+       /* 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     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};     /* for storing certs */
+       CSSM_DL_DB_LIST_PTR     dbListPtr;                      /* pts to dbList or NULL */
+       unsigned                        i;
+       char                            *notAfterStr;
+       char                            *notBeforeStr;
+       CSSM_DL_HANDLE          dlHand;
+       
+       /* all three of these are arrays with numCert elements */
+       CSSM_KEY_PTR            pubKeys = NULL;
+       CSSM_KEY_PTR            privKeys = NULL;
+       CSSM_DATA_PTR           certs = NULL;
+       
+       /* Keys do NOT go in the cert DB */
+       CSSM_DL_DB_HANDLE       keyDb = {0, 0};
+
+       /*
+        * User-spec'd params
+        */
+       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);
+               }
+       }
+
+       /* attach to all the modules we need */
+       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;
+       }
+       
+       /* malloc empty keys and certs */
+       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");
+       
+       /* generate key pairs */
+       if(!quiet) {
+               printf("generating keys...\n");
+       }
+       if(tpGenKeys(cspHand,
+                       keyDb,
+                       numCerts,
+                       keyGenAlg, 
+                       keySizeInBits,
+                       "cgConstruct",          // keyLabelBase
+                       pubKeys,
+                       privKeys)) {
+               goto abort;
+       }
+       notBeforeStr = genTimeAtNowPlus(0);
+       notAfterStr = genTimeAtNowPlus(SECONDS_TO_LIVE);
+
+       #if     TP_DB_ENABLE
+       /* create numDbs new DBs */
+       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) {
+                       /*
+                        * In this case, this is the only time we open these DBs - they
+                        * stay open for the duration of the test
+                        */
+                       if(verbose) {
+                               printf("   ...opening DBs read/write\n");
+                       }
+                       if(doOpenDbs(dlHand,
+                                       fileBaseName,
+                                       dbList.DLDBHandle,
+                                       numDBs,
+                                       CSSM_FALSE,             // publicReadOnly: this is create/write
+                                       quiet)) {
+                               goto abort;
+                       }
+               }
+               dbListPtr = &dbList;
+       }               
+       else {
+               /* it's required anyway... */
+               dbList.NumHandles = 0;
+               dbList.DLDBHandle = NULL;
+               dbListPtr = &dbList;
+       }
+       #else
+       /* it's required anyway... */
+       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",  // nameBase
+                               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:
+       /* free keys and certs */
+       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) {
+               /* don't have to close, detach should do that */
+               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;
+}