]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTests/cspxutils/hashTimeLibCrypt/hashTimeLibCrypt.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / cspxutils / hashTimeLibCrypt / hashTimeLibCrypt.cpp
diff --git a/SecurityTests/cspxutils/hashTimeLibCrypt/hashTimeLibCrypt.cpp b/SecurityTests/cspxutils/hashTimeLibCrypt/hashTimeLibCrypt.cpp
new file mode 100644 (file)
index 0000000..f8cfd3b
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * hashTimeLibCrypt.cpp - measure performance of libcrypt digest ops.
+ * 
+ * Thjis is obsolete; hashTime does this a lot better,a dn it also measures raw
+ * CommonCrypto and CryptKit versions. 
+ */
+#include <openssl/sha.h>
+#include <openssl/md5.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "cputime.h"
+#include "cspwrap.h"
+#include "common.h"
+#include "pbkdDigest.h"
+
+/* enumerate digest algorithms our way */
+typedef int HT_Alg;
+enum {
+       HA_MD5 = 0,
+       HA_SHA1
+};
+
+#define FIRST_ALG      HA_MD5
+#define LAST_ALG       HA_SHA1
+
+static void usage(char **argv)
+{
+    printf("Usage: %s [option ...]\n", argv[0]);
+    printf("Options:\n");
+       printf("   t=testspec; default=all\n");
+       printf("     test specs: c digest context setup/teardown\n");
+       printf("                 b basic single block digest\n");
+       printf("                 d digest lots of data\n");
+       printf("   l=loops (only valid if testspec is given)\n");
+       exit(1);
+}
+
+/* passed to each test */      
+typedef struct {
+       unsigned                        loops;
+       bool                            isSha;
+} TestParams;
+
+/* just digest context setup/teardown */
+/* returns nonzero on error */
+static int hashContext(
+       TestParams      *params)
+{
+       unsigned                loop;
+       CPUTime                 startTime;
+       double                  timeSpentMs;
+       DigestCtx               ctx;
+       int                             rtn;
+       
+       startTime = CPUTimeRead();
+       for(loop=0; loop<params->loops; loop++) {
+               rtn = DigestCtxInit(&ctx, params->isSha);
+               if(!rtn) {
+                       return -1;
+               }
+       }
+       timeSpentMs = CPUTimeDeltaMs(startTime, CPUTimeRead());
+
+       printf("   context setup/delete : %u ops in %.2f ms; %f ms/op\n",
+               params->loops, timeSpentMs, timeSpentMs / (double)params->loops);
+       return 0;
+}
+
+/* Minimal init/digest/final */
+#define BASIC_BLOCK_SIZE       64              // to digest in bytes
+#define MAX_DIGEST_SIZE                20              // we provide, no malloc below CSSM
+
+static int hashBasic(
+       TestParams      *params)
+{
+       unsigned                loop;
+       CPUTime                 startTime;
+       double                  timeSpentMs;
+       uint8                   ptext[BASIC_BLOCK_SIZE];
+       uint8                   digest[MAX_DIGEST_SIZE];
+       DigestCtx               ctx;
+       int                     rtn;
+       
+       /* random data, const thru the loops */
+       appGetRandomBytes(ptext, BASIC_BLOCK_SIZE);
+       
+       /* start critical timing loop */
+       startTime = CPUTimeRead();
+       for(loop=0; loop<params->loops; loop++) {
+               rtn = DigestCtxInit(&ctx, params->isSha);
+               if(!rtn) {
+                       return -1;
+               }
+               rtn = DigestCtxUpdate(&ctx, ptext, BASIC_BLOCK_SIZE);
+               if(!rtn) {
+                       return -1;
+               }
+               rtn = DigestCtxFinal(&ctx, digest);
+               if(!rtn) {
+                       return -1;
+               }
+       }
+       DigestCtxFree(&ctx);
+       timeSpentMs = CPUTimeDeltaMs(startTime, CPUTimeRead());
+       printf("   Digest one %u byte block : %u ops in %.2f ms; %f ms/op\n",
+               BASIC_BLOCK_SIZE, params->loops, 
+               timeSpentMs, timeSpentMs / (double)params->loops);
+       return 0;
+}
+
+/* Lots of data */
+#define PTEXT_SIZE                     1000            // to digest in bytes
+#define INNER_LOOPS                    1000
+
+static int hashDataRate(
+       TestParams      *params)
+{
+       unsigned                loop;
+       unsigned                iloop;
+       CPUTime                 startTime;
+       double                  timeSpent, timeSpentMs;
+       uint8                   ptext[PTEXT_SIZE];
+       uint8                   digest[MAX_DIGEST_SIZE];
+       DigestCtx               ctx;
+       int                             rtn;
+       
+       /* random data, const thru the loops */
+       appGetRandomBytes(ptext, PTEXT_SIZE);
+       
+       /* start critical timing loop */
+       startTime = CPUTimeRead();
+       for(loop=0; loop<params->loops; loop++) {
+               rtn = DigestCtxInit(&ctx, params->isSha);
+               if(!rtn) {
+                       return -1;
+               }
+               for(iloop=0; iloop<INNER_LOOPS; iloop++) {
+                       rtn = DigestCtxUpdate(&ctx, ptext, PTEXT_SIZE);
+                       if(!rtn) {
+                               return -1;
+                       }
+               }
+               rtn = DigestCtxFinal(&ctx, digest);
+               if(!rtn) {
+                       return -1;
+               }
+       }
+       timeSpentMs = CPUTimeDeltaMs(startTime, CPUTimeRead());
+       timeSpent = timeSpentMs / 1000.0;
+       
+       float bytesPerLoop = INNER_LOOPS * PTEXT_SIZE;
+       float totalBytes   = params->loops * bytesPerLoop;
+       
+       /* careful, KByte = 1024, ms = 1/1000 */
+       printf("   Digest %.0f bytes : %u ops in %.2f ms; %f ms/op, %.0f KBytes/s\n",
+               bytesPerLoop, params->loops, 
+               timeSpentMs, timeSpentMs / (double)params->loops,
+               ((float)totalBytes / 1024.0) / timeSpent);
+       return 0;
+}
+
+
+typedef int (*testRunFcn)(TestParams *testParams);
+
+/*
+ * Static declaration of a test
+ */
+typedef struct {
+       const char                      *testName;
+       unsigned                        loops;
+       testRunFcn                      run;
+       char                            testSpec;               // for t=xxx cmd line opt
+} TestDefs;
+
+static TestDefs testDefs[] = 
+{
+       {       "Digest context setup/teardown",
+               100000,
+               hashContext,
+               'c',
+       },
+       {       "Basic single block digest",
+               100000,
+               hashBasic,
+               'b',
+       },
+       {       "Large data digest",
+               1000,
+               hashDataRate,
+               'd',
+       },
+};
+
+static void algToAlgId(
+       HT_Alg                  alg,
+       bool                    *isSha,
+       const char              **algStr)
+{
+       switch(alg) {
+               case HA_MD5:
+                       *isSha = false;
+                       *algStr = "MD5";
+                       break;
+               case HA_SHA1:
+                       *isSha = true;
+                       *algStr = "SHA1";
+                       break;
+               default:
+                       printf("***algToAlgId screwup\n");
+                       exit(1);
+       }
+}
+
+#define NUM_TESTS      (sizeof(testDefs) / sizeof(testDefs[0]))
+
+int main(int argc, char **argv)
+{
+       TestParams              testParams;
+       TestDefs                *testDef;
+       int                             rtn;
+       int                     arg;
+       char                    *argp;
+       unsigned                cmdLoops = 0;           // can be specified in cmd line
+                                                                               // if not, use TestDefs.loops
+       char                    testSpec = '\0';        // allows specification of one test
+                                                                               // otherwise run all
+       HT_Alg                  alg;
+       const char              *algStr;
+       
+       for(arg=1; arg<argc; arg++) {
+               argp = argv[arg];
+               switch(argp[0]) {
+                       case 't':
+                               testSpec = argp[2];
+                               break;
+                       case 'l':
+                               cmdLoops = atoi(&argp[2]);
+                               break;
+                       default:
+                               usage(argv);
+               }
+       }
+
+       for(unsigned testNum=0; testNum<NUM_TESTS; testNum++) {
+               testDef = &testDefs[testNum];
+               
+               if(testSpec && (testDef->testSpec != testSpec)) {
+                       continue;
+               }
+               printf("%s:\n", testDef->testName);
+               if(cmdLoops) {
+                       /* user specified */
+                       testParams.loops = cmdLoops;
+               }       
+               else {
+                       /* default */
+                       testParams.loops = testDef->loops;
+               }
+               for(alg=FIRST_ALG; alg<=LAST_ALG; alg++) {
+                       algToAlgId(alg, &testParams.isSha, &algStr);
+                       printf("   === %s ===\n", algStr);
+                       rtn = testDef->run(&testParams);
+                       if(rtn) {
+                               printf("Test returned error\n");
+                               exit(1);
+                       }
+               }
+       }
+       return 0;
+}