--- /dev/null
+/*
+ * 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;
+}