]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTests/cspxutils/symReference/symReference.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / cspxutils / symReference / symReference.cpp
diff --git a/SecurityTests/cspxutils/symReference/symReference.cpp b/SecurityTests/cspxutils/symReference/symReference.cpp
new file mode 100644 (file)
index 0000000..f472471
--- /dev/null
@@ -0,0 +1,464 @@
+/* 
+ * symReference.c - write keys and ciphertext blobs, read them back
+ *                  and decrypt on (possibly) a different platfrom.
+ *                                     Intended for use in testing multiplatform
+ *                                     compatibility (e.g. encrypt on 32 bit G4, decrypt
+ *                                     on 64-bit G5). 
+ *
+ * Created by Doug Mitchell 10/31/05. 
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <Security/cssm.h>
+#include <Security/cssmapple.h>
+#include "cspwrap.h"
+#include <security_cdsa_utils/cuFileIo.h>
+#include "common.h"
+#include <string.h>
+#include "cspdlTesting.h"
+#include <unistd.h>
+
+/*
+ * Defaults.
+ */
+#define LOOPS_DEF              200
+#define PTEXT_SIZE_DEF 256
+#define BLOCK_SIZE_MAX 32              /* bytes */
+
+/*
+ * Enumerate algs our own way to allow iteration.
+ */
+typedef enum {
+       ALG_ASC = 0,            /* first must be 0 */
+       ALG_DES,
+       ALG_RC2,
+       ALG_RC4,
+       ALG_RC5,
+       ALG_3DES,
+       ALG_AES,
+       ALG_AES192,
+       ALG_AES256,
+       ALG_BFISH,
+       ALG_CAST
+} SymAlg;
+
+#define ALG_FIRST                      ALG_ASC
+#define ALG_LAST                       ALG_CAST
+
+static void usage(char **argv)
+{
+       printf("usage: %s e|d dirName [options]\n", argv[0]);
+       printf("  e=encrypt, d=decrypt; blobs read/written in dirName\n");
+       printf("   Options:\n");
+       printf("   a=algorithm (d=DES; 3=3DES3; 2=RC2; 4=RC4; 5=RC5; a=AES; b=Blowfish; \n");
+       printf("                c=CAST; s=ASC, default=all)\n");
+       printf("   p=ptextSize (default=%d)\n", PTEXT_SIZE_DEF);
+       printf("   D (CSP/DL; default = bare CSP)\n");
+       printf("   v(erbose)\n");
+       printf("   q(uiet)\n");
+       printf("   h(elp)\n");
+       exit(1);
+}
+
+/*
+ * map SymAlg to test params
+ */
+typedef struct {
+       SymAlg                          alg;
+       const char                      *algStr;
+       CSSM_ALGORITHMS         cssmAlg;
+       CSSM_ENCRYPT_MODE       mode;
+       CSSM_PADDING            padding;
+       CSSM_SIZE                       keySizeBits;
+       CSSM_SIZE                       ivLen;          // in bytes
+} SymAlgParams;
+
+static const SymAlgParams symAlgParams[] = 
+{
+       { ALG_ASC, "ASC", CSSM_ALGID_ASC, CSSM_ALGMODE_NONE, CSSM_PADDING_NONE, 
+               CSP_ASC_KEY_SIZE_DEFAULT, 0 },
+       { ALG_DES, "DES", CSSM_ALGID_DES, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5, 
+               CSP_DES_KEY_SIZE_DEFAULT, 8 },
+       { ALG_RC2, "RC2", CSSM_ALGID_RC2, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5, 
+               CSP_RC2_KEY_SIZE_DEFAULT, 8 },
+       { ALG_RC4, "RC4", CSSM_ALGID_RC4, CSSM_ALGMODE_NONE, CSSM_PADDING_NONE, 
+               CSP_RC4_KEY_SIZE_DEFAULT, 0 },
+       { ALG_RC5, "RC5", CSSM_ALGID_RC5, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5, 
+               CSP_RC5_KEY_SIZE_DEFAULT, 8 },
+       { ALG_3DES, "3DES", CSSM_ALGID_3DES_3KEY_EDE, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5, 
+               CSP_DES3_KEY_SIZE_DEFAULT, 8 },
+       { ALG_AES, "AES", CSSM_ALGID_AES, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5, 
+               CSP_AES_KEY_SIZE_DEFAULT, 16 },
+       { ALG_AES192, "AES192", CSSM_ALGID_AES, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5, 
+               192, 24 },
+       { ALG_AES256, "AES256", CSSM_ALGID_AES, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5, 
+               256, 32 },
+       { ALG_BFISH, "Blowfish", CSSM_ALGID_BLOWFISH, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5,
+               CSP_BFISH_KEY_SIZE_DEFAULT,  8 },
+       { ALG_CAST, "CAST", CSSM_ALGID_CAST, CSSM_ALGMODE_CBCPadIV8, CSSM_PADDING_PKCS5, 
+               CSP_CAST_KEY_SIZE_DEFAULT,  8 }
+};
+
+static void genFileNames(
+       const char      *algStr,
+       char            *keyFile,
+       char            *ptextFile,
+       char            *ctextFile,
+       char            *ivFile)
+{
+       sprintf(keyFile,        "key_%s", algStr);
+       sprintf(ptextFile,      "ptext_%s", algStr);
+       sprintf(ctextFile,      "ctext_%s", algStr);
+       sprintf(ivFile,         "iv_%s", algStr);
+}
+       
+/* encrypt, write blobs (key, plaintext, ciphertext, optional IV) to disk */
+static int doEncrypt(
+       CSSM_CSP_HANDLE         cspHand,
+       const SymAlgParams      *algParams,
+       CSSM_DATA                       *ptext,         // mallocd, length valid, we fill data
+       CSSM_BOOL                       quiet,
+       CSSM_BOOL                       verbose)
+{
+       CSSM_KEY_PTR    symKey = NULL;
+       CSSM_KEY                rawKey;
+       CSSM_RETURN             crtn;
+       CSSM_DATA               ctext = {0, NULL};
+       uint8                   iv[BLOCK_SIZE_MAX];
+       CSSM_DATA               ivd = {BLOCK_SIZE_MAX, iv};
+       CSSM_DATA               *ivp = NULL;
+       uint32                  blockSize = 0;
+       char                    keyFile[FILENAME_MAX];
+       char                    ptextFile[FILENAME_MAX];
+       char                    ctextFile[FILENAME_MAX];
+       char                    ivFile[FILENAME_MAX];
+       
+       if(!quiet) {
+               printf("...encrypting, alg %s\n", algParams->algStr);
+       }
+
+       /* generate reference key (works with CSPDL) */
+       symKey = cspGenSymKey(cspHand, algParams->cssmAlg,
+               "noLabel", 7,
+               CSSM_KEYUSE_ANY, algParams->keySizeBits, CSSM_TRUE);
+       if(symKey == NULL) {
+               printf("***Error generating key for alg %s size %u bits\n",
+                       algParams->algStr, (unsigned)algParams->keySizeBits);
+               return testError(quiet);
+       }
+       
+       /* get key in raw format (to get the raw blob we write to disk) */
+       crtn = cspRefKeyToRaw(cspHand, symKey, &rawKey);
+       if(crtn) {
+               printf("***Error generating raw key for alg %s size %u bits\n",
+                       algParams->algStr, (unsigned)algParams->keySizeBits);
+               return testError(quiet);
+       }
+       
+       appGetRandomBytes(ptext->Data, (unsigned)ptext->Length);
+       
+       /* 
+        * Hack: we only need to specify block size for AES192 and AES256, which 
+        * we detect by their having an ivLen of greater than 16.
+        */
+       if(algParams->ivLen > 16) {
+               blockSize = algParams->ivLen;
+       }
+       if(algParams->ivLen) {
+               appGetRandomBytes(iv, algParams->ivLen);
+               ivd.Length = algParams->ivLen;
+               ivp = &ivd;
+       }
+       
+       crtn = cspStagedEncrypt(cspHand,
+               algParams->cssmAlg, algParams->mode, algParams->padding,
+               symKey, NULL,
+               0, blockSize, 0,
+               ivp, ptext,
+               &ctext, 
+               CSSM_FALSE);
+       if(crtn) {
+               printf("***Error encrypting for alg %s size %u bits\n",
+                       algParams->algStr, (unsigned)algParams->keySizeBits);
+               return testError(quiet);
+       }
+
+       /* write: key, IV, ptext, ctext */
+       genFileNames(algParams->algStr, keyFile, ptextFile, ctextFile, ivFile);
+       if(writeFile(keyFile, rawKey.KeyData.Data, (unsigned)rawKey.KeyData.Length) ||
+          writeFile(ptextFile, ptext->Data, (unsigned)ptext->Length) ||
+          writeFile(ctextFile, ctext.Data, (unsigned)ctext.Length)) {
+               printf("***Error writing result of alg %s size %u bits\n",
+                       algParams->algStr, (unsigned)algParams->keySizeBits);
+               return testError(quiet);
+       }
+       if(ivp != NULL) {
+               if(writeFile(ivFile, ivp->Data, (unsigned)ivp->Length)) {
+                       printf("***Error writing IV for alg %s size %u bits\n",
+                               algParams->algStr, (unsigned)algParams->keySizeBits);
+                       return testError(quiet);
+               }
+       }
+       
+       /* Free resources */
+       CSSM_FreeKey(cspHand, NULL, symKey, CSSM_FALSE);
+       CSSM_FreeKey(cspHand, NULL, &rawKey, CSSM_FALSE);
+       CSSM_FREE(ctext.Data);
+       return 0;
+}
+
+/* read blobs (key, plaintext, ciphertext, optional IV) from disk, decrypt, compare plaintext */
+static int doDecrypt(
+       CSSM_CSP_HANDLE         cspHand,
+       const SymAlgParams      *algParams,
+       CSSM_BOOL                       quiet,
+       CSSM_BOOL                       verbose)
+{
+       CSSM_KEY                symKey;
+       uint8                   *symKeyBits;
+       unsigned                symKeyLen;                              // in bytes
+       CSSM_DATA               symKeyData;
+       CSSM_RETURN             crtn;
+       uint8                   *ctextChars;
+       unsigned                ctextLen = 0;
+       CSSM_DATA               ctext;
+       CSSM_DATA               rptext = {0, NULL};             // recovered/decrytped
+       uint8                   *refPTextChars;
+       unsigned                refPtextLen;
+       CSSM_DATA               refPtext = {0, NULL};   // expected
+       uint8                   *iv = NULL;
+       unsigned                ivLen;
+       CSSM_DATA               ivd = {BLOCK_SIZE_MAX, iv};
+       CSSM_DATA               *ivp = NULL;
+       uint32                  blockSize = 0;
+       char                    keyFile[FILENAME_MAX];
+       char                    ptextFile[FILENAME_MAX];
+       char                    ctextFile[FILENAME_MAX];
+       char                    ivFile[FILENAME_MAX];
+       
+       if(!quiet) {
+               printf("...decrypting, alg %s\n", algParams->algStr);
+       }
+       
+       /* 
+        * Hack: we only need to specify block size for AES192 and AES256, which 
+        * we detect by their having an ivLen of greater than 16.
+        */
+       if(algParams->ivLen > 16) {
+               blockSize = algParams->ivLen;
+       }
+       if(algParams->ivLen) {
+               ivp = &ivd;
+               ivd.Length = algParams->ivLen;
+       }
+
+       /* read: key, IV, ptext, ctext */
+       genFileNames(algParams->algStr, keyFile, ptextFile, ctextFile, ivFile);
+       if(readFile(keyFile, &symKeyBits, &symKeyLen) ||
+          readFile(ptextFile, &refPTextChars, &refPtextLen) ||
+          readFile(ctextFile, &ctextChars, &ctextLen)) {
+               printf("***Error reading reference blobs for alg %s size %u bits\n",
+                       algParams->algStr, (unsigned)algParams->keySizeBits);
+               return testError(quiet);
+       }
+       if(ivp != NULL) {
+               if(readFile(ivFile, &iv, &ivLen)) {
+                       printf("***Error writing IV for alg %s size %u bits\n",
+                               algParams->algStr, (unsigned)algParams->keySizeBits);
+                       return testError(quiet);
+               }
+               if(ivLen != algParams->ivLen) {
+                       printf("***Unexpected IV length: expect %u found %u\n",
+                               (unsigned)algParams->ivLen, (unsigned)ivLen);
+                       if(testError(quiet)) {
+                               return 1;
+                       }
+               }
+               ivd.Data = iv;
+       }
+       ctext.Data = ctextChars;
+       ctext.Length = ctextLen;
+       refPtext.Data = refPTextChars;
+       refPtext.Length = refPtextLen;
+       
+       /* generate key */
+       symKeyData.Data = symKeyBits;
+       symKeyData.Length = symKeyLen;
+       
+       crtn = cspGenSymKeyWithBits(cspHand, algParams->cssmAlg,
+               CSSM_KEYUSE_ANY, &symKeyData, symKeyLen, &symKey);
+       if(crtn) {
+               printf("***Error creating key for alg %s keySize %u\n",
+                       algParams->algStr, (unsigned)algParams->keySizeBits);
+               return testError(quiet);
+       }
+       
+       crtn = cspStagedDecrypt(cspHand,
+               algParams->cssmAlg, algParams->mode, algParams->padding,
+               &symKey, NULL,
+               0, blockSize, 0,
+               ivp, &ctext,
+               &rptext, 
+               CSSM_FALSE);
+       if(crtn) {
+               printf("***Error decrypting for alg %s size %u bits\n",
+                       algParams->algStr, (unsigned)algParams->keySizeBits);
+               return testError(quiet);
+       }
+
+       /* moment of truth */
+       if(!appCompareCssmData(&rptext, &refPtext)) {
+               printf("***DATA MISCOMPARE AFTER DECRYPT alg %s size %u bits\n",
+                       algParams->algStr, (unsigned)algParams->keySizeBits);
+               return testError(quiet);
+       }
+       
+       /* Free resources */
+       CSSM_FreeKey(cspHand, NULL, &symKey, CSSM_FALSE);
+       free(symKeyBits);               // mallocd by readFile()
+       free(refPTextChars);
+       free(ctextChars);
+       CSSM_FREE(rptext.Data); // mallocd by CSP
+       if(iv) {
+               free(iv);
+       }
+       return 0;
+}
+
+
+int main(int argc, char **argv)
+{
+       int                                     arg;
+       char                            *argp;
+       CSSM_DATA                       ptext;
+       CSSM_CSP_HANDLE         cspHand;
+       unsigned                        currAlg;                                // ALG_xxx
+       int                                     rtn = 0;
+
+       /*
+        * User-spec'd params
+        */
+       unsigned        minAlg = ALG_FIRST;
+       unsigned        maxAlg = ALG_LAST;
+       CSSM_BOOL       verbose = CSSM_FALSE;
+       CSSM_BOOL       quiet = CSSM_FALSE;
+       CSSM_BOOL       bareCsp = CSSM_TRUE;
+       bool            encrypt = false;
+       unsigned        ptextSize = PTEXT_SIZE_DEF;
+       char            *dirName;
+               
+       if(argc < 3) {
+               usage(argv);
+       }
+       switch(argv[1][0]) {
+               case 'e':
+                       encrypt = true;
+                       break;
+               case 'd':
+                       encrypt = false;
+                       break;
+               default:
+                       usage(argv);
+       }
+       dirName = argv[2];
+       
+       for(arg=3; arg<argc; arg++) {
+               argp = argv[arg];
+               switch(argp[0]) {
+                       case 'a':
+                               if(argp[1] != '=') {
+                                       usage(argv);
+                               }
+                               switch(argp[2]) {
+                                       case 's':
+                                               minAlg = maxAlg = ALG_ASC;
+                                               break;
+                                       case 'd':
+                                               minAlg = maxAlg = ALG_DES;
+                                               break;
+                                       case '3':
+                                               minAlg = maxAlg = ALG_3DES;
+                                               break;
+                                       case '2':
+                                               minAlg = maxAlg = ALG_RC2;
+                                               break;
+                                       case '4':
+                                               minAlg = maxAlg = ALG_RC4;
+                                               break;
+                                       case '5':
+                                               minAlg = maxAlg = ALG_RC5;
+                                               break;
+                                       case 'a':
+                                               minAlg = maxAlg = ALG_AES;
+                                               break;
+                                       case 'b':
+                                               minAlg = maxAlg = ALG_BFISH;
+                                               break;
+                                       case 'c':
+                                               minAlg = maxAlg = ALG_CAST;
+                                               break;
+                                       default:
+                                               usage(argv);
+                               }
+                               break;
+                   case 'v':
+                       verbose = CSSM_TRUE;
+                               break;
+                       case 'D':
+                               bareCsp = CSSM_FALSE;
+                               break;
+                       case 'p':
+                               ptextSize = atoi(&argp[2]);
+                               break;
+                   case 'q':
+                       quiet = CSSM_TRUE;
+                               break;
+                   case 'h':
+                   default:
+                               usage(argv);
+               }
+       }
+       ptext.Data = (uint8 *)CSSM_MALLOC(ptextSize);
+       if(ptext.Data == NULL) {
+               printf("Insufficient heap space\n");
+               exit(1);
+       }
+       ptext.Length = ptextSize;
+
+       testStartBanner("symReference", argc, argv);
+
+       cspHand = cspDlDbStartup(bareCsp, NULL);
+       if(cspHand == 0) {
+               exit(1);
+       }
+
+       if(chdir(dirName)) {
+               perror(dirName);
+               printf("Error accessing directory %s. Aborting.\n", dirName);
+               exit(1);
+       }
+       for(currAlg=minAlg; currAlg<=maxAlg; currAlg++) {
+               const SymAlgParams *algParams = &symAlgParams[currAlg];
+
+               if(encrypt) {
+                       rtn = doEncrypt(cspHand, algParams, &ptext, quiet, verbose);
+               }
+               else {
+                       rtn = doDecrypt(cspHand, algParams, quiet, verbose);
+               }
+               if(rtn) {
+                       break;
+               }
+       }       /* for algs */
+       
+       cspShutdown(cspHand, bareCsp);
+       if((rtn == 0) && !quiet) {
+               printf("%s test complete\n", argv[0]);
+       }
+       CSSM_FREE(ptext.Data);
+       return rtn;
+}
+
+