]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_cryptkit/ckutils/cfileTest/cfileTest.c
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurity_cryptkit / ckutils / cfileTest / cfileTest.c
diff --git a/Security/libsecurity_cryptkit/ckutils/cfileTest/cfileTest.c b/Security/libsecurity_cryptkit/ckutils/cfileTest/cfileTest.c
new file mode 100644 (file)
index 0000000..e0951b6
--- /dev/null
@@ -0,0 +1,589 @@
+/*
+ * Copyright (c) 1997,2011,2014 Apple Inc. All Rights Reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+#include "ckutilsPlatform.h"
+#include "Crypt.h"
+#include "feeCipherFile.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+static unsigned char *dataPool;                /* plaintext comes from here */
+
+#undef BOOL
+#undef YES
+#undef NO
+#define BOOL   int
+#define YES    1
+#define NO     0
+
+#define LOOPS_DEF      100
+#define MIN_EXP                2               /* for data size 10**exp */
+#define MAX_EXP                3               /* FEED is very slow with ptext larger than this... */          
+#define DEPTH_DEFAULT  FEE_DEPTH_DEFAULT
+#define MIN_OFFSET     0
+#define MAX_OFFSET     99
+
+#define PASSWD_LENGTH  10
+
+static void usage(char **argv) 
+{
+       printf("usage: %s [options]\n", argv[0]);
+       printf("Options:\n");
+       printf("   l==loops (default=%d)\n", LOOPS_DEF);
+       printf("   n=minExp (default=%d)\n", MIN_EXP);
+       printf("   x=maxExp (default=max=%d)\n", MAX_EXP);
+       printf("   D=depth (default=%d)\n", DEPTH_DEFAULT);
+       printf("   N=minOffset (default=%d)\n", MIN_OFFSET);
+       printf("   q(uiet)           v(erbose)\n");
+       printf("   h(elp)            I(ncrementing offset)\n");
+       exit(1);
+}
+
+/*
+ * ...min <= return <= max 
+ */
+static int genRand(int min, int max) 
+{      
+
+    /* note random() only yields a 31-bit number... */
+       
+    if(max == min)                     /* avoid % 1 ! */
+       return(max);
+    else
+       return(min + (RAND() % (max-min+1)));
+}
+
+/* end of feeLib routines */
+
+#define MIN_ASCII      ' '
+#define MAX_ASCII      '~'
+
+static void genPasswd(unsigned char *passwd,
+       unsigned passwdLen, BOOL ascii) 
+{
+       unsigned *ip = (unsigned *)passwd;
+       unsigned intCount = passwdLen / 4;
+       int i;
+       unsigned char *cp;
+       unsigned residue = passwdLen & 0x3;
+       char ac;
+       
+       if(ascii) {
+               cp = passwd;
+               ac = MIN_ASCII;
+               for(i=0; i<passwdLen; i++) {
+                       *cp++ = ac++;
+                       if(ac > MAX_ASCII) {
+                               ac = MIN_ASCII;
+                       }
+               }
+       }
+       else {
+               for (i=0; i<intCount; i++) {
+                       *ip++ = RAND();
+               }
+               cp = (unsigned char *)ip;
+               for(i=0; i<residue; i++) {
+                       *cp = (unsigned char)RAND();
+               }
+       }
+}
+
+/*
+ * Calculate random data size, fill dataPool with that many random bytes. 
+ */
+typedef enum {
+       DT_Random,
+       DT_Zero,
+       DT_ASCII,
+       DT_None                 /* data irrelevant; use existing pool */
+} dataType;
+
+static void fillDataPool(unsigned size, dataType type)
+{
+       #ifdef  __LITTLE_ENDIAN__
+       unsigned        *ip;
+       unsigned        intCount;
+       unsigned        residue;
+       #endif
+       unsigned char   *cp;
+       int             i;
+       unsigned char   ac;
+       
+       switch(type) {  
+           case DT_Zero:
+               bzero(dataPool, size);
+               break;
+           case DT_ASCII:
+               ac = MIN_ASCII;
+               cp = dataPool;
+               for(i=0; i<size; i++) {
+                       *cp++ = ac++;
+                       if(ac > MAX_ASCII) {
+                               ac = MIN_ASCII;
+                       }
+               }
+               break;
+           case DT_Random:
+               #ifdef  __LITTLE_ENDIAN__
+                   intCount = size >> 2;
+                   ip = (unsigned *)dataPool;
+                   for(i=0; i<intCount; i++) {
+                           *ip++ = RAND();
+                   }
+                   
+                   residue = size & 0x3;
+                   cp = (unsigned char *)ip;
+                   for(i=0; i<residue; i++) {
+                           *cp++ = (unsigned char)RAND();
+                   }
+               #else   __LITTLE_ENDIAN__
+                   cp = dataPool;
+                   for(i=0; i<size; i++) {
+                           *cp++ = (char)RAND();
+                   }
+               #endif  __LITTLE_ENDIAN__
+               break;
+           case DT_None:
+               printf("fillDataPool(DT_None)\n");
+               exit(1);
+       }
+}
+
+static unsigned dataSizeFromExp(unsigned maxExp)
+{
+       int size = 1;
+       while(maxExp--) {                       // size = 10 ** exp
+               size *= 10;
+       }
+       return size;
+}
+
+static int     sizeOffset = MIN_OFFSET;
+
+static unsigned char *genData(unsigned minExp, 
+       unsigned maxExp, 
+       dataType type,
+       BOOL incrOffset,
+       unsigned minOffset,
+       unsigned *dataLen)              // RETURNED
+{
+       int             exp;
+       int             offset;
+       int             size;
+       
+       /*
+        * Calculate "random" size : (10 ** (random exponent)) + random offset
+        */
+       exp = genRand(minExp, maxExp);
+       if(incrOffset) {
+               offset = sizeOffset++;
+               if(sizeOffset == MAX_OFFSET) {
+                       sizeOffset = minOffset;
+               }
+       }
+       else {
+               offset = genRand(minOffset, MAX_OFFSET);
+       }
+       size = dataSizeFromExp(exp) + offset;
+       if(type != DT_None) {
+               fillDataPool(size, type);
+       }
+       *dataLen = size;
+       return dataPool;
+}
+
+static feePubKey genPrivKey(const unsigned char *privKeyData, 
+       unsigned privDataLen, 
+       int depth)
+{
+       feePubKey       privKey;                // generic key object
+       feeReturn       frtn;
+       
+       privKey = feePubKeyAlloc();
+       frtn = feePubKeyInitFromPrivDataDepth(privKey,
+               (unsigned char *)privKeyData,
+               privDataLen,
+               depth,
+               1);
+       if(frtn) {
+               printf("pubKeyFromPrivDataDepth: Can't create new key (%s)\n",
+                       feeReturnString(frtn));
+               exit(1);
+       }
+       return privKey;
+}
+
+static feePubKey genPubKey(feePubKey privKey)
+{
+       feePubKey       pubKey;                 // generic key object
+       feeReturn       frtn;
+       char            *pubString;
+       unsigned        pubStringLen;
+       
+       frtn = feePubKeyCreateKeyString(privKey, &pubString, &pubStringLen);
+       if(frtn) {
+               printf("feePubKeyCreateKeyString: Can't get key string (%s)\n",
+                       feeReturnString(frtn));
+               exit(1);
+       }
+       pubKey = feePubKeyAlloc();
+       frtn = feePubKeyInitFromKeyString(pubKey, pubString, pubStringLen);
+       if(frtn) {
+               printf("feePubKeyInitFromKeyString: Can't create new key "
+                       "(%s)\n",
+                       feeReturnString(frtn));
+               feePubKeyFree(pubKey);
+               exit(1);
+       }
+       ffree(pubString);
+       return pubKey;
+}
+
+static char *stringFromEncrType(cipherFileEncrType encrType) 
+{
+       switch(encrType) {
+           case CFE_PublicDES: return "CFE_PublicDES";
+           case CFE_RandDES:   return "CFE_RandDES";
+           case CFE_FEED:      return "CFE_FEED";
+           case CFE_FEEDExp:   return "CFE_FEEDExp";
+           default:            return "Bogus encrType";
+       }
+}
+
+#define SIG_NO         0
+#define SIG_YES                1
+#define EXPLICIT_NO    0
+#define EXPLICIT_YES   1
+#define EXPLICIT_ERR   2
+
+static void doTest(unsigned char *ptext, 
+       unsigned ptextLen, 
+       feePubKey myPrivKey, 
+       feePubKey myPubKey, 
+       feePubKey theirPrivKey, 
+       feePubKey theirPubKey,
+       cipherFileEncrType encrType, 
+       int doEnc64, 
+       int doSig,
+       int doExplicitKey)      /* EXPLICIT_ERR means do one with 
+                                * bad verify key */
+{
+       feeReturn               frtn;
+       unsigned char           *ctext;
+       unsigned                ctextLen;
+       unsigned char           *dectext;
+       unsigned                dectextLen;
+       unsigned                outUserData = 0x1234567;
+       unsigned                inUserData;
+       cipherFileEncrType      inEncrType;
+       feeSigStatus            sigStatus;
+       int                     abort = 0;
+       char                    instr[100];
+       feeSigStatus            expSigStatus = SS_PresentValid;
+       int                     valid64;
+       
+       /*
+        * These are tailored to specific encrTypes and doExplicitKeys
+        */
+       feePubKey sendPrivKey = myPrivKey;
+       feePubKey sendPubKey = myPubKey;
+       feePubKey recvPrivKey = theirPrivKey;
+       feePubKey recvPubKey = theirPubKey;
+       
+       switch(encrType) {
+           case CFE_RandDES:
+           case CFE_FEEDExp:
+               if(!doSig) {
+                   sendPrivKey = NULL;         // not needed
+               }
+               break;
+           case CFE_PublicDES:
+           case CFE_FEED:
+               break;
+           default:
+               printf("Hey bozo! Give me a real encrType!\n");
+               exit(1);
+       }
+       if(!doSig) {
+           sendPubKey = NULL;                  // never needed
+           expSigStatus = SS_NotPresent;
+       }
+       else switch(doExplicitKey) {
+           case EXPLICIT_NO:
+               sendPubKey = NULL;              // get it from cipherfile
+               break;
+           case EXPLICIT_YES:
+               break;                          // use myPubKey
+           case EXPLICIT_ERR:          
+               if(feePubKeyIsEqual(myPubKey, theirPubKey)) {
+                       printf("myPubKey = theirPubKey!\n");
+                       goto errOut;
+               }
+               sendPubKey = theirPubKey;       // hopefully != myPubKey!
+               expSigStatus = SS_PresentInvalid;
+               break;
+           default:
+               printf("BOGUS doExplicitKey\n");
+               exit(1);
+       }
+
+       frtn = createCipherFile(sendPrivKey,
+               recvPubKey,
+               encrType,
+               ptext,
+               ptextLen,
+               doSig,
+               doEnc64,
+               outUserData,
+               &ctext,
+               &ctextLen);
+       if(frtn) {
+               printf("createCipherFile: %s\n", feeReturnString(frtn));
+               goto errOut;
+       }
+       
+       valid64 = isValidEnc64(ctext, ctextLen);
+       if(valid64 != doEnc64) {
+               printf("valid64 mismatch! exp %d got %d\n", doEnc64, valid64);
+               abort = 1;
+       }
+       frtn = parseCipherFile(recvPrivKey,
+               sendPubKey,
+               ctext,
+               ctextLen,
+               doEnc64,
+               &inEncrType,
+               &dectext,
+               &dectextLen,
+               &sigStatus,
+               &inUserData);
+       if(frtn) {
+               printf("parseCipherFile: %s\n", feeReturnString(frtn));
+               goto errOut;
+       }
+       if(inEncrType != encrType) {
+               printf("encrType mismatch exp %d got %d\n", 
+                       encrType, inEncrType);
+               abort = 1;
+       }
+       if(inUserData != outUserData) {
+               printf("userData mismatch exp %d got %d\n", 
+                       outUserData, inUserData);
+               abort = 1;
+       }
+       if(sigStatus != expSigStatus) {
+               printf("Bad sigStatus exp %d got %d\n", 
+                       expSigStatus, sigStatus);
+               abort = 1;
+       }
+       if(ptextLen != dectextLen) {
+               printf("ptextLen mismatch exp %d got %d\n", 
+                       ptextLen, dectextLen);
+               abort = 1;
+       }
+       if(bcmp(ptext, dectext, ptextLen)) {
+               printf("Data Miscompare\n");
+               abort = 1;
+       }
+       ffree(dectext);
+       ffree(ctext);
+       if(!abort) {
+               return;
+       }
+errOut:
+       /* dump params */
+       printf("attach with debugger for more info; enter CR to quit: ");
+       gets(instr);
+       exit(1);
+               
+}
+
+int main(int argc, char **argv)
+{
+       int             arg;
+       char            *argp;
+       int             loop;
+       unsigned char   *ptext;
+       unsigned        ptextLen;
+       unsigned char   passwd1[PASSWD_LENGTH];
+       unsigned char   passwd2[PASSWD_LENGTH];
+       int             encrType;
+       int             doEnc64;
+       feePubKey       myPrivKey;
+       feePubKey       theirPrivKey;
+       feePubKey       myPubKey;
+       feePubKey       theirPubKey;
+       unsigned        maxSize;
+       
+       /*
+        * User-spec'd params
+        */
+       unsigned        loops = LOOPS_DEF;
+       BOOL            seedSpec = NO;
+       unsigned        seed;
+       BOOL            quiet = NO;
+       BOOL            verbose = NO;
+       unsigned        minExp = MIN_EXP;
+       unsigned        maxExp = MAX_EXP;
+       BOOL            incrOffset = NO;
+       unsigned        depth = DEPTH_DEFAULT;
+       unsigned        minOffset = MIN_OFFSET;
+       
+       #if     macintosh
+       argc = ccommand(&argv);
+       #endif
+
+       for(arg=1; arg<argc; arg++) {
+               argp = argv[arg];
+               switch(argp[0]) {
+                   case 'l':
+                       loops = atoi(&argp[2]);
+                       break;
+                   case 'n':
+                       minExp = atoi(&argp[2]);
+                       break;
+                   case 'D':
+                       depth = atoi(&argp[2]);
+                       break;
+                   case 'N':
+                       minOffset = atoi(&argp[2]);
+                       if(minOffset > MAX_OFFSET) {
+                               minOffset = MIN_OFFSET;
+                       }
+                       sizeOffset = minOffset;
+                       break;
+                   case 'x':
+                       maxExp = atoi(&argp[2]);
+                       if(maxExp > MAX_EXP) {
+                               usage(argv);
+                       }
+                       break;
+                   case 's':
+                       seed = atoi(&argp[2]);
+                       seedSpec = YES;
+                       break;
+                   case 'I':
+                       incrOffset = YES;
+                       break;
+                   case 'q':
+                       quiet = YES;
+                       break;
+                   case 'v':
+                       verbose = YES;
+                       break;
+                   case 'h':
+                   default:
+                       usage(argv);
+               }
+       }
+       
+       if(seedSpec == NO) {
+               time((unsigned long *)(&seed));
+       }
+       SRAND(seed);
+       maxSize = dataSizeFromExp(maxExp) + MAX_OFFSET + 8;
+       dataPool = fmalloc(maxSize);
+       
+       printf("Starting cfileTest: loops %d seed %d depth %d\n",
+               loops, seed, depth);
+
+       for(loop=1; ; loop++) {
+       
+           ptext = genData(minExp, maxExp, DT_Random, incrOffset, 
+                   minOffset, &ptextLen);
+           if(!quiet) {
+                   printf("..loop %d plaintext size %d\n", loop, ptextLen);
+           }
+           
+           /*
+            * Generate a whole bunch of keys
+            */
+           genPasswd(passwd1, PASSWD_LENGTH, NO);      // not ascii!
+           genPasswd(passwd2, PASSWD_LENGTH, NO);
+           myPrivKey    = genPrivKey(passwd1, PASSWD_LENGTH, depth);
+           theirPrivKey = genPrivKey(passwd2, PASSWD_LENGTH, depth);
+           myPubKey     = genPubKey(myPrivKey);
+           theirPubKey  = genPubKey(theirPrivKey);
+           
+           for(encrType=CFE_PublicDES; 
+               encrType<=CFE_FEEDExp; 
+               encrType++) {
+               
+               if(verbose) {
+                   printf("  ..%s\n", stringFromEncrType(encrType));
+               }
+               for(doEnc64=0; doEnc64<2; doEnc64++) { 
+                   if(verbose) {
+                       printf("    ..doEnc64 %d\n", doEnc64);
+                   }   
+                   
+                   if(verbose) {
+                       printf("      ..no sig\n");
+                   }   
+                   doTest(ptext, ptextLen, myPrivKey, myPubKey, 
+                       theirPrivKey, theirPubKey,
+                       encrType, doEnc64, SIG_NO, EXPLICIT_NO);
+                       
+                   if(verbose) {
+                       printf("      ..sig, implicit sendPubKey\n");
+                   }   
+                   doTest(ptext, ptextLen, myPrivKey, myPubKey, 
+                       theirPrivKey, theirPubKey,
+                       encrType, doEnc64, SIG_YES, EXPLICIT_NO);
+                       
+                   if(verbose) {
+                       printf("      ..sig, explicit sendPubKey\n");
+                   }   
+                   doTest(ptext, ptextLen, myPrivKey, myPubKey, 
+                       theirPrivKey, theirPubKey,
+                       encrType, doEnc64, SIG_YES, EXPLICIT_YES);
+                       
+                   if(verbose) {
+                       printf("      ..sig, force error\n");
+                   }   
+                   doTest(ptext, ptextLen, myPrivKey, myPubKey, 
+                       theirPrivKey, theirPubKey,
+                       encrType, doEnc64, SIG_YES, EXPLICIT_ERR);
+                       
+               } /* for doEnc64 */
+           }     /* for encrType */
+           
+           feePubKeyFree(myPrivKey);
+           feePubKeyFree(myPubKey);
+           feePubKeyFree(theirPrivKey);
+           feePubKeyFree(theirPubKey);
+           if(loops) {
+                   if(loop == loops) {
+                           break;
+                   }
+           }
+       }       /* main loop */
+       
+       if(!quiet) {
+               printf("cfile test complete\n");
+       }
+       return 0;
+}