]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTests/clxutils/threadTest/cgVerifyThr.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / threadTest / cgVerifyThr.cpp
diff --git a/SecurityTests/clxutils/threadTest/cgVerifyThr.cpp b/SecurityTests/clxutils/threadTest/cgVerifyThr.cpp
new file mode 100644 (file)
index 0000000..ffd333e
--- /dev/null
@@ -0,0 +1,453 @@
+/* cgVerifyThr.cpp - simple version CertGroupVerify 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>
+#include <Security/oidsalg.h>
+
+/* for memory leak debug only, with only one thread running */
+#define DO_PAUSE                       0
+
+/*** start of code directly copied from ../cgVerify/cgVerify.cpp ***/
+#define NUM_CERTS_MIN          4
+#define KEYGEN_ALG_DEF         CSSM_ALGID_RSA
+#define SIG_ALG_DEF                    CSSM_ALGID_SHA1WithRSA
+#define LOOPS_DEF                      10
+#define CG_KEY_SIZE_DEFAULT    CSP_RSA_KEY_SIZE_DEFAULT
+#define SECONDS_TO_LIVE                (60 * 60 * 24)          /* certs are valid for this long */
+
+#define CERT_IN_DB             0
+
+/*
+ * How we define the "expected result".
+ */
+typedef enum {
+       ER_InvalidAnchor,               // root in certGroup, not found in AnchorCerts
+       ER_RootInCertGroup,             // root in certGroup, copy in AnchorCerts
+       ER_AnchorVerify,                // end of chain verified by an anchor
+       ER_NoRoot                               // no root, no anchor verify
+} ExpectResult;
+
+static int testError()
+{
+       char resp;
+
+       printf("Attach via debugger for more info.\n");
+       printf("a to abort, c to continue: ");
+       resp = getchar();
+       return (resp == 'a');
+}
+
+static int doTest(
+       CSSM_TP_HANDLE  tpHand,
+       CSSM_CL_HANDLE  clHand,
+       CSSM_CSP_HANDLE cspHand,
+       CSSM_DL_DB_HANDLE dlDb,
+       CSSM_DATA_PTR   certs,
+       unsigned                numCerts,
+       CSSM_BOOL               useDb,
+       ExpectResult    expectResult,   
+       CSSM_BOOL               verbose)
+{
+       unsigned                        cgEnd;                          // last cert in certGroupFrag
+       unsigned                        anchorStart;            // first cert in anchorGroup
+       unsigned                        anchorEnd;                      // last cert in anchorGroup
+       CSSM_CERTGROUP          certGroupFrag;          // INPUT to CertGroupVerify
+       CSSM_CERTGROUP          anchorCerts;            // ditto 
+       unsigned                        die;                            // random number
+       CSSM_DL_DB_LIST         dbList;
+       CSSM_DL_DB_LIST_PTR     dbListPtr;
+       CSSM_DL_DB_HANDLE_PTR   dlDbPtr;
+       CSSM_RETURN                     expErr;                         // expected rtn from GroupVfy()
+       int                                     rtn = 0;
+       const char                      *expResStr;
+       uint32                          expEvidenceSize;        // expected evidenceSize
+       unsigned                        evidenceSize;           // actual evidence size
+       CSSM_TP_VERIFY_CONTEXT_RESULT   vfyResult;
+       CSSM_CERTGROUP_PTR      outGrp = NULL;
+       CSSM_RETURN                     crtn;
+       
+       memset(&vfyResult, 0, sizeof(CSSM_TP_VERIFY_CONTEXT_RESULT));
+       
+       if(useDb) {
+               dlDbPtr = &dlDb;
+               dbList.NumHandles = 1;
+               dbList.DLDBHandle = &dlDb;
+               dbListPtr = &dbList;
+       }
+       else {
+               /* not yet */
+               dlDbPtr = NULL;
+               dbListPtr = NULL;
+       }
+       
+       /* the four test cases */
+       switch(expectResult) {
+               case ER_InvalidAnchor:          
+                       /* root in certGroup, not found in AnchorCerts */
+                       cgEnd = numCerts - 1;           // certGroupFrag is the whole pile
+                       anchorStart = 0;                        // anchors = all except root
+                       anchorEnd = numCerts - 2;
+                       expErr = CSSMERR_TP_INVALID_ANCHOR_CERT;
+                       expEvidenceSize = numCerts;
+                       expResStr = "InvalidAnchor (root in certGroup but not in anchors)";
+                       break;
+                       
+               case ER_RootInCertGroup:                
+                       /* root in certGroup, copy in AnchorCerts */
+                       cgEnd = numCerts - 1;           // certGroupFrag = the whole pile
+                       anchorStart = 0;                        // anchors = the whole pile
+                       anchorEnd = numCerts - 1;
+                       expErr = CSSM_OK;
+                       expEvidenceSize = numCerts;
+                       expResStr = "Good (root in certGroup AND in anchors)";
+                       break;
+
+               case ER_AnchorVerify:   
+                       /* non-root end of chain verified by an anchor */
+                       /* break chain at random place other than start and end-2 */
+                       die = genRand(1, numCerts-3);
+                       cgEnd = die;                            // certGroupFrag up to break point
+                       anchorStart = 0;                        // anchors = all
+                       anchorEnd = numCerts - 1;
+                       expErr = CSSM_OK;
+                       /* size = # certs in certGroupFrag, plus one anchor */ 
+                       expEvidenceSize = die + 2;
+                       expResStr = "Good (root ONLY in anchors)";
+                       break;
+                       
+               case ER_NoRoot:                 
+                       /* no root, no anchor verify */
+                       /* break chain at random place other than start and end-1 */
+                       die = genRand(1, numCerts-2);
+                       cgEnd = die;                            // certGroupFrag up to break point
+                       /* and skip one cert */
+                       anchorStart = die + 2;          // anchors = n+1...numCerts-2
+                                                                               // may be empty if n == numCerts-2
+                       anchorEnd = numCerts - 1;
+                       expErr = CSSMERR_TP_NOT_TRUSTED;
+                       expEvidenceSize = die + 1;
+                       expResStr = "Not Trusted (no root, no anchor verify)";
+                       break;
+       }
+       
+       if(verbose) {
+               printf("   ...expectResult = %s\n", expResStr);
+       }
+       
+       /* cook up two cert groups */
+       if(verbose) {
+               printf("   ...building certGroupFrag from certs[0..%d]\n",
+                       cgEnd);
+       }
+       if(tpMakeRandCertGroup(clHand,
+                       dbListPtr,
+                       certs,                          // certGroupFrag always starts at 0
+                       cgEnd+1,                        // # of certs
+                       &certGroupFrag,
+                       CSSM_TRUE,                      // firstCertIsSubject
+                       verbose,
+                       CSSM_FALSE,                     // allInDbs
+                       CSSM_FALSE)) {          // skipFirstDb
+               printf("\nError in tpMakeRandCertGroup\n");
+               return 1;               
+       }
+       
+       if(anchorStart > anchorEnd) {
+               /* legal for ER_NoRoot */
+               if((expectResult != ER_NoRoot) || (anchorStart != numCerts)) {
+                       printf("Try again, pal.\n");
+                       exit(1);
+               }
+       }
+       if(verbose) {
+               printf("   ...building anchorCerts from certs[%d..%d]\n",
+                       anchorStart, anchorEnd);
+       }
+       if(anchorEnd > (numCerts - 1)) {
+               printf("anchorEnd overflow\n");
+               exit(1);
+       } 
+       /* anchors do not go in DB */
+       if(tpMakeRandCertGroup(clHand,
+                       NULL,
+                       certs + anchorStart,
+                       anchorEnd - anchorStart + 1,                    // # of certs
+                       &anchorCerts,
+                       CSSM_FALSE,                     // firstCertIsSubject
+                       verbose,
+                       CSSM_FALSE,                     // allInDbs
+                       CSSM_FALSE)) {          // skipFirstDb
+               printf("\nError in tpMakeRandCertGroup\n");
+               return 1;               
+       }
+       
+       crtn = tpCertGroupVerify(
+               tpHand,
+               clHand,
+               cspHand,
+               dbListPtr,
+               &CSSMOID_APPLE_X509_BASIC,      // Policy
+               NULL,                                           // fieldOpts
+               NULL,                                           // actionData
+               NULL,                                           // policyOpts
+               &certGroupFrag,
+               anchorCerts.GroupList.CertList, // passed as CSSM_DATA_PTR, not CERTGROUP....
+               anchorCerts.NumCerts, 
+               CSSM_TP_STOP_ON_POLICY,
+               NULL,                                   // cssmTimeStr
+               &vfyResult);
+               
+       /* first verify format of result */
+       if( (vfyResult.NumberOfEvidences != 3) ||
+           (vfyResult.Evidence == NULL) ||
+               (vfyResult.Evidence[0].EvidenceForm != CSSM_EVIDENCE_FORM_APPLE_HEADER) ||
+               (vfyResult.Evidence[1].EvidenceForm != CSSM_EVIDENCE_FORM_APPLE_CERTGROUP) ||
+               (vfyResult.Evidence[2].EvidenceForm != CSSM_EVIDENCE_FORM_APPLE_CERT_INFO) ||
+               (vfyResult.Evidence[0].Evidence == NULL) ||
+               (vfyResult.Evidence[1].Evidence == NULL) ||
+               (vfyResult.Evidence[2].Evidence == NULL)) {
+               printf("***Malformed VerifyContextResult\n");
+               return 1;
+       }
+       if((vfyResult.Evidence != NULL) && (vfyResult.Evidence[1].Evidence != NULL)) {
+               outGrp = (CSSM_CERTGROUP_PTR)vfyResult.Evidence[1].Evidence;
+               evidenceSize = outGrp->NumCerts;
+       }
+       else {
+               /* in case no evidence returned */
+               evidenceSize = 0;
+       }
+
+       /* %%% since non-root anchors are permitted as of <rdar://5685316>,
+        * the test assumptions have become invalid: these tests generate
+        * an anchors list which always includes the full chain, so by
+        * definition, the evidence chain will never be longer than 2,
+        * since the leaf's issuer is always an anchor.
+        * %%% need to revisit and rewrite these tests. -kcm
+        */
+       if ((evidenceSize > 1) && (evidenceSize < expEvidenceSize) &&
+               (crtn == CSSM_OK || crtn == CSSMERR_TP_CERTIFICATE_CANT_OPERATE)) {
+               /* ignore, for now */
+               expErr = crtn;
+               expEvidenceSize = evidenceSize;
+       }
+       
+       if((crtn != expErr) || 
+          (evidenceSize != expEvidenceSize)) {
+               printf("\n***cgVerify: Error on tpCertGroupVerify expectResult %s\n", 
+                       expResStr);
+               printf("   err  %s   expErr  %s\n", 
+                       cssmErrToStr(crtn), cssmErrToStr(expErr));
+               printf("   evidenceSize  %d   expEvidenceSize  %u\n", 
+                       evidenceSize, (unsigned)expEvidenceSize);
+               printf("   numCerts %d  cgEnd %d  anchorStart %d  anchorEnd %d\n",
+                       numCerts, cgEnd, anchorStart, anchorEnd);
+               rtn = testError();
+       }
+       else {
+               rtn = 0;
+       }
+
+       /* free resources */
+       tpFreeCertGroup(&certGroupFrag, 
+               CSSM_FALSE,                     // caller malloc'd the actual certs 
+               CSSM_FALSE);            // struct is on stack
+       tpFreeCertGroup(&anchorCerts, 
+               CSSM_FALSE,                     // caller malloc'd the actual certs 
+               CSSM_FALSE);            // struct is on stack
+       freeVfyResult(&vfyResult);
+       if(useDb) {
+               clDeleteAllCerts(dlDb);
+       }
+       return rtn;
+}
+
+/*** end of code directly copied from ../cgVerify/cgVerify.cpp ***/
+
+/*
+ * For debug only - ensure that the given array of public keys are all unique 
+ * Only saw this when using FEE RNG (i.e., no SecurityServer running).
+ */
+int comparePubKeys(
+       unsigned numKeys,
+       const CSSM_KEY *pubKeys)        
+{
+       unsigned i,j;
+       
+       for(i=0; i<numKeys-1; i++) {
+               for(j=i+1; j<numKeys; j++) {
+                       if(appCompareCssmData(&pubKeys[i].KeyData, &pubKeys[j].KeyData)) {
+                               printf("***HEY! DUPLICATE PUBLIC KEYS in cgVerify!\n");
+                               return testError();
+                       }
+               }
+       }
+       return 0;
+}
+
+/*
+ * 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 cgVerifyInit(TestParams *testParams)
+{
+       unsigned                        numKeys = NUM_CERTS_MIN + testParams->threadNum;
+       TT_KeyPairs                     *keyPairs;
+       
+       if(testParams->verbose) {
+               printf("cgVerify 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       dlDbHand = {0, 0};
+       if(tpGenKeys(testParams->cspHand,
+                       dlDbHand,
+                       numKeys,
+                       KEYGEN_ALG_DEF, 
+                       CG_KEY_SIZE_DEFAULT,
+                       "cgVerify",                     // keyLabelBase
+                       keyPairs->pubKeys,
+                       keyPairs->privKeys)) {
+               goto abort;
+       }
+       if(comparePubKeys(numKeys, keyPairs->pubKeys)) {
+               return 1;
+       }
+       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 cgVerify(TestParams *testParams)
+{
+       unsigned                        loopNum;
+       int                                     status = -1;            // exit status
+       unsigned                        dex;
+       
+       TT_KeyPairs                     *keyPairs = (TT_KeyPairs *)testParams->perThread;
+
+       /* 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;
+       ExpectResult            expectResult;
+       #if     CERT_IN_DB
+       CSSM_BOOL                       useDb = CSSM_TRUE;
+       #else
+       CSSM_BOOL                       useDb = CSSM_FALSE;
+       #endif
+       CSSM_DL_DB_HANDLE       dlDbHand = {0, 0};
+       
+       /* 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));
+
+       for(loopNum=0; loopNum<testParams->numLoops; loopNum++) {
+               /* generate certs */
+               if(testParams->verbose) {
+                       printf("generating certs...\n");
+               }
+               else if(!testParams->quiet) {
+                       printChar(testParams->progressChar);
+               }
+               if(tpGenCerts(testParams->cspHand,
+                               testParams->clHand,
+                               numCerts,
+                               sigAlg, 
+                               "cgConstruct",  // nameBase
+                               pubKeys,
+                               privKeys,
+                               certs,
+                               keyPairs->notBeforeStr,
+                               keyPairs->notAfterStr)) {
+                       goto abort;
+               }
+
+               /* cycle thru test scenarios */
+               switch(loopNum % 4) {
+                       case 0:
+                               expectResult = ER_InvalidAnchor;
+                               break;
+                       case 1:
+                               expectResult = ER_RootInCertGroup;
+                               break;
+                       case 2:
+                               expectResult = ER_AnchorVerify;
+                               break;
+                       case 3:
+                               expectResult = ER_NoRoot;
+                               break;
+               }
+               status = doTest(testParams->tpHand,
+                               testParams->clHand,
+                               testParams->cspHand,
+                               dlDbHand,
+                               certs,
+                               numCerts,
+                               useDb,
+                               expectResult,
+                               testParams->verbose);
+               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;
+}
+