]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTests/cspxutils/hashTest/hashTest.c
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / cspxutils / hashTest / hashTest.c
diff --git a/SecurityTests/cspxutils/hashTest/hashTest.c b/SecurityTests/cspxutils/hashTest/hashTest.c
new file mode 100644 (file)
index 0000000..b791b8a
--- /dev/null
@@ -0,0 +1,397 @@
+/* Copyright (c) 1998,2003-2006,2008 Apple Inc.
+ *
+ * hashTest.c - test CDSA digest functions.
+ *
+ * Revision History
+ * ----------------
+ *   4 May 2000  Doug Mitchell
+ *             Ported to X/CDSA2. 
+ *  12 May 1998        Doug Mitchell at Apple
+ *             Created.
+ */
+/*
+ * text size =       {random, from 100 bytes to 100k, in
+ *                   geometrical steps, i.e. the number of
+ *                   bytes would be 10^r, where r is random out of
+ *                   {2,3,4,5,6}, plus a random integer in {0,..99}};
+ *
+ * for loop_count
+ *     text contents = {random data, random size as specified above};
+ *     generate digest in one shot;
+ *        generate digest with multiple random-sized updates;
+ *     verify digests compare;
+ *     for various bytes of text {
+ *        corrupt text byte;
+ *               generate digest in one shot;
+ *               veridy digest is different;
+ *        restore corrupted byte;
+ *     }
+ *  }
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <string.h>
+#include <Security/cssm.h>
+#include "cspwrap.h"
+#include <Security/cssm.h>
+#include <Security/cssmapple.h>
+#include "cspwrap.h"
+#include "common.h"
+
+/*
+ * Defaults.
+ */
+#define LOOPS_DEF              50
+#define MIN_EXP                        2               /* for data size 10**exp */
+#define DEFAULT_MAX_EXP        3
+#define MAX_EXP                        5
+#define INCR_DEFAULT   0               /* munge every incr bytes - zero means
+                                                                * "adjust per ptext size" */
+typedef enum {
+       ALG_MD2 = 1,
+       ALG_MD5,
+       ALG_SHA1,
+       ALG_SHA224,
+       ALG_SHA256,
+       ALG_SHA384,
+       ALG_SHA512
+};
+
+#define ALG_FIRST              ALG_MD2
+#define ALG_LAST               ALG_SHA512
+#define MAX_DATA_SIZE  (100000 + 100)  /* bytes */
+#define LOOP_NOTIFY            20
+
+static void usage(char **argv)
+{
+       printf("usage: %s [options]\n", argv[0]);
+       printf("   Options:\n");
+       printf("   a=algorithm (s=SHA1; m=MD5; M=MD2; 4=SHA224; 2=SHA256; 3=SHA384; 5=SHA512; "
+                                       "default=all\n");
+       printf("   l=loops (default=%d; 0=forever)\n", LOOPS_DEF);
+       printf("   n=minExp (default=%d)\n", MIN_EXP);
+       printf("   x=maxExp (default=%d, max=%d)\n", DEFAULT_MAX_EXP, MAX_EXP);
+       printf("   i=increment (default=%d)\n", INCR_DEFAULT);
+       printf("   p=pauseInterval (default=0, no pause)\n");
+       printf("   z (zero data)\n");
+       printf("   I (incrementing data)\n");
+       printf("   g (good digest only)\n");
+       printf("   D (CSP/DL; default = bare CSP)\n");
+       printf("   v(erbose)\n");
+       printf("   q(uiet)\n");
+       printf("   h(elp)\n");
+       exit(1);
+}
+
+#define LOG_FREQ       20
+
+static int doTest(CSSM_CSP_HANDLE cspHand,
+       uint32 alg,
+       CSSM_DATA_PTR ptext,
+       CSSM_BOOL verbose,
+       CSSM_BOOL quiet,
+       CSSM_BOOL mallocDigest,
+       unsigned incr,
+       CSSM_BOOL goodOnly)
+{
+       CSSM_DATA               refDigest = {0, NULL};
+       CSSM_DATA               testDigest = {0, NULL};
+       unsigned                length;
+       unsigned                byte;
+       unsigned char   *data;
+       unsigned char   origData;
+       unsigned char   bits;
+       int                             rtn = 0;
+       CSSM_RETURN             crtn;
+       unsigned                loop = 0;
+       
+       /*
+        *     generate digest in one shot;
+        *         generate digest with multiple random-sized updates;
+        *     verify digests compare;
+        *     for various bytes of ptext {
+        *        corrupt ptext byte;
+        *                generate digest in one shot;
+        *                verify digest is different;
+        *        restore corrupted byte;
+        *     }
+        */
+       crtn = cspDigest(cspHand,
+               alg,
+               mallocDigest,
+               ptext,
+               &refDigest);
+       if(crtn) {
+               rtn = testError(quiet);
+               goto abort;
+       }
+       crtn = cspStagedDigest(cspHand,
+               alg,
+               mallocDigest,
+               CSSM_TRUE,                      // multi updates
+               ptext,
+               &testDigest);
+       if(crtn) {
+               rtn = testError(quiet);
+               goto abort;
+       }
+       if(refDigest.Length != testDigest.Length) {
+               printf("Digest length mismatch (1)\n");
+               rtn = testError(quiet);
+               goto abort;
+       }
+       if(memcmp(refDigest.Data, testDigest.Data, refDigest.Length)) {
+               printf("Digest miscompare (1)\n");
+               rtn = testError(quiet);
+               if(rtn) {
+                       goto abort;
+               }
+       }
+       if(goodOnly) {
+               rtn = 0;
+               goto abort;
+       }
+       appFreeCssmData(&testDigest, CSSM_FALSE);
+       testDigest.Length = 0;
+       data = (unsigned char *)ptext->Data;
+       length = ptext->Length;
+       for(byte=0; byte<length; byte += incr) {
+               if(verbose && ((loop++ % LOG_FREQ) == 0)) {
+                       printf("....byte %d\n", byte);
+               }
+               origData = data[byte];
+               /*
+                * Generate random non-zero byte
+                */
+               do {
+                       bits = genRand(1, 0xff) & 0xff;
+               } while(bits == 0);
+               data[byte] ^= bits;
+               crtn = cspDigest(cspHand,
+                       alg,
+                       mallocDigest,
+                       ptext,
+                       &testDigest);
+               if(crtn) {
+                       rtn = testError(quiet);
+                       break;
+               }
+               if(!memcmp(refDigest.Data, testDigest.Data, refDigest.Length)) {
+                       printf("Unexpected digest compare\n");
+                       rtn = testError(quiet);
+                       break;
+               }
+               appFreeCssmData(&testDigest, CSSM_FALSE);
+               testDigest.Length = 0;
+               data[byte] = origData;
+       }
+abort:
+       /* free digests */
+       if(refDigest.Length) {
+               appFreeCssmData(&refDigest, CSSM_FALSE);
+       }
+       if(testDigest.Length) {
+               appFreeCssmData(&testDigest, CSSM_FALSE);
+       }
+       return rtn;
+}
+
+int main(int argc, char **argv)
+{
+       int                                     arg;
+       char                            *argp;
+       unsigned                        loop;
+       CSSM_DATA                       ptext;
+       CSSM_CSP_HANDLE         cspHand;
+       CSSM_BOOL                       mallocDigest;
+       const char                      *algStr;
+       uint32                          alg;            // ALG_MD5, etc.
+       uint32                          cssmAlg;        // CSSM_ALGID_MD5, etc.
+       unsigned                        actualIncr;
+       int                                     i;
+       
+       /*
+        * User-spec'd params
+        */
+       unsigned        loops = LOOPS_DEF;
+       CSSM_BOOL       verbose = CSSM_FALSE;
+       unsigned        minExp = MIN_EXP;
+       unsigned        maxExp = DEFAULT_MAX_EXP;
+       CSSM_BOOL       quiet = CSSM_FALSE;
+       unsigned        incr = INCR_DEFAULT;
+       unsigned        minAlg = ALG_FIRST;
+       unsigned        maxAlg = ALG_LAST;
+       unsigned        pauseInterval = 0;
+       dataType        dt;
+       CSSM_BOOL       goodOnly = CSSM_FALSE;
+       CSSM_BOOL       bareCsp = CSSM_TRUE;
+       
+       for(arg=1; arg<argc; arg++) {
+               argp = argv[arg];
+               switch(argp[0]) {
+                       case 'a':
+                               if(argp[1] != '=') {
+                                       usage(argv);
+                               }
+                               switch(argp[2]) {
+                                       case 's':
+                                               minAlg = maxAlg = ALG_SHA1;
+                                               break;
+                                       case 'm':
+                                               minAlg = maxAlg = ALG_MD5;
+                                               break;
+                                       case 'M':
+                                               minAlg = maxAlg = ALG_MD2;
+                                               break;
+                                       case '4':
+                                               minAlg = maxAlg = ALG_SHA224;
+                                               break;
+                                       case '2':
+                                               minAlg = maxAlg = ALG_SHA256;
+                                               break;
+                                       case '3':
+                                               minAlg = maxAlg = ALG_SHA384;
+                                               break;
+                                       case '5':
+                                               minAlg = maxAlg = ALG_SHA512;
+                                               break;
+                                       default:
+                                               usage(argv);
+                               }
+                               break;
+                   case 'l':
+                               loops = atoi(&argp[2]);
+                               break;
+                   case 'n':
+                               minExp = atoi(&argp[2]);
+                               break;
+                   case 'x':
+                               maxExp = atoi(&argp[2]);
+                               if(maxExp > MAX_EXP) {
+                                       usage(argv);
+                               }
+                               break;
+                   case 'i':
+                               incr = atoi(&argp[2]);
+                               break;
+                   case 'p':
+                       pauseInterval = atoi(&argp[2]);;
+                               break;
+                   case 'v':
+                       verbose = CSSM_TRUE;
+                               break;
+                   case 'q':
+                       quiet = CSSM_TRUE;
+                               break;
+                       case 'D':
+                               bareCsp = CSSM_FALSE;
+                               break;
+                       case 'z':
+                               dt = DT_Zero;
+                               break;
+                       case 'I':
+                               dt = DT_Increment;
+                               break;
+                       case 'g':
+                               goodOnly = CSSM_TRUE;
+                               break;
+                   case 'h':
+                   default:
+                               usage(argv);
+               }
+       }
+       ptext.Data = (uint8 *)CSSM_MALLOC(MAX_DATA_SIZE);
+       /* length set in test loop */
+       if(ptext.Data == NULL) {
+               printf("Insufficient heap\n");
+               exit(1);
+       }
+       
+       printf("Starting hashTest; args: ");
+       for(i=1; i<argc; i++) {
+               printf("%s ", argv[i]);
+       }
+       printf("\n");
+       cspHand = cspDlDbStartup(bareCsp, NULL);
+       if(cspHand == 0) {
+               exit(1);
+       }
+       
+       for(alg=minAlg; alg<=maxAlg; alg++) {
+               switch(alg) {
+                       case ALG_MD5:
+                               algStr = "MD5";
+                               cssmAlg = CSSM_ALGID_MD5;
+                               break;
+                       case ALG_MD2:
+                               algStr = "MD2";
+                               cssmAlg = CSSM_ALGID_MD2;
+                               break;
+                       case ALG_SHA1:
+                               algStr = "SHA1";
+                               cssmAlg = CSSM_ALGID_SHA1;
+                               break;
+                       case ALG_SHA224:
+                               algStr = "SHA224";
+                               cssmAlg = CSSM_ALGID_SHA224;
+                               break;
+                       case ALG_SHA256:
+                               algStr = "SHA256";
+                               cssmAlg = CSSM_ALGID_SHA256;
+                               break;
+                       case ALG_SHA384:
+                               algStr = "SHA384";
+                               cssmAlg = CSSM_ALGID_SHA384;
+                               break;
+                       case ALG_SHA512:
+                               algStr = "SHA512";
+                               cssmAlg = CSSM_ALGID_SHA512;
+                               break;
+               }
+               if(!quiet) {
+                       printf("Testing alg %s\n", algStr);
+               }
+               for(loop=1; ; loop++) {
+                       ptext.Length = genData(ptext.Data, minExp, maxExp, dt);
+                       if(incr == 0) {
+                               /* adjust increment as appropriate */
+                               actualIncr = (ptext.Length / 50) + 1;
+                       }
+                       else {
+                               actualIncr = incr;
+                       }
+                       /* mix up mallocing */
+                       mallocDigest = (loop & 1) ? CSSM_TRUE : CSSM_FALSE;
+                       if(!quiet) {
+                               if(verbose || ((loop % LOOP_NOTIFY) == 0)) {
+                                       printf("..loop %d text size %lu mallocDigest %d\n",
+                                               loop, (unsigned long)ptext.Length, (int)mallocDigest);
+                               }
+                       }
+                       if(doTest(cspHand,
+                                       cssmAlg,
+                                       &ptext,
+                                       verbose,
+                                       quiet,
+                                       mallocDigest,
+                                       actualIncr,
+                                       goodOnly)) {
+                               exit(1);
+                       }
+                       if(loops && (loop == loops)) {
+                               break;
+                       }
+                       if(pauseInterval && ((loop % pauseInterval) == 0)) {
+                               fpurge(stdin);
+                               printf("Hit CR to proceed: ");
+                               getchar();
+                       }
+               }
+       }
+       if(!quiet) {
+               printf("%s test complete\n", argv[0]);
+       }
+       return 0;
+}