• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /macosx-10.10.1/Security-57031.1.35/Security/libsecurity_cryptkit/ckutils/cfileTest/
1/*
2 * Copyright (c) 1997,2011,2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25#include "ckutilsPlatform.h"
26#include "Crypt.h"
27#include "feeCipherFile.h"
28#include <stdlib.h>
29#include <stdio.h>
30#include <time.h>
31
32static unsigned char *dataPool;		/* plaintext comes from here */
33
34#undef	BOOL
35#undef	YES
36#undef	NO
37#define BOOL	int
38#define YES	1
39#define NO	0
40
41#define LOOPS_DEF	100
42#define MIN_EXP		2		/* for data size 10**exp */
43#define MAX_EXP		3		/* FEED is very slow with ptext larger than this... */
44#define DEPTH_DEFAULT	FEE_DEPTH_DEFAULT
45#define MIN_OFFSET	0
46#define MAX_OFFSET	99
47
48#define PASSWD_LENGTH	10
49
50static void usage(char **argv)
51{
52	printf("usage: %s [options]\n", argv[0]);
53	printf("Options:\n");
54	printf("   l==loops (default=%d)\n", LOOPS_DEF);
55	printf("   n=minExp (default=%d)\n", MIN_EXP);
56	printf("   x=maxExp (default=max=%d)\n", MAX_EXP);
57	printf("   D=depth (default=%d)\n", DEPTH_DEFAULT);
58	printf("   N=minOffset (default=%d)\n", MIN_OFFSET);
59	printf("   q(uiet)           v(erbose)\n");
60	printf("   h(elp)            I(ncrementing offset)\n");
61	exit(1);
62}
63
64/*
65 * ...min <= return <= max
66 */
67static int genRand(int min, int max)
68{
69
70    /* note random() only yields a 31-bit number... */
71
72    if(max == min)			/* avoid % 1 ! */
73	return(max);
74    else
75	return(min + (RAND() % (max-min+1)));
76}
77
78/* end of feeLib routines */
79
80#define MIN_ASCII	' '
81#define MAX_ASCII	'~'
82
83static void genPasswd(unsigned char *passwd,
84	unsigned passwdLen, BOOL ascii)
85{
86	unsigned *ip = (unsigned *)passwd;
87	unsigned intCount = passwdLen / 4;
88	int i;
89	unsigned char *cp;
90	unsigned residue = passwdLen & 0x3;
91	char ac;
92
93	if(ascii) {
94		cp = passwd;
95		ac = MIN_ASCII;
96		for(i=0; i<passwdLen; i++) {
97			*cp++ = ac++;
98			if(ac > MAX_ASCII) {
99				ac = MIN_ASCII;
100			}
101		}
102	}
103	else {
104		for (i=0; i<intCount; i++) {
105			*ip++ = RAND();
106		}
107		cp = (unsigned char *)ip;
108		for(i=0; i<residue; i++) {
109			*cp = (unsigned char)RAND();
110		}
111	}
112}
113
114/*
115 * Calculate random data size, fill dataPool with that many random bytes.
116 */
117typedef enum {
118	DT_Random,
119	DT_Zero,
120	DT_ASCII,
121	DT_None			/* data irrelevant; use existing pool */
122} dataType;
123
124static void fillDataPool(unsigned size, dataType type)
125{
126	#ifdef	__LITTLE_ENDIAN__
127	unsigned 	*ip;
128	unsigned 	intCount;
129	unsigned 	residue;
130	#endif
131	unsigned char	*cp;
132	int 		i;
133	unsigned char	ac;
134
135	switch(type) {
136	    case DT_Zero:
137		bzero(dataPool, size);
138		break;
139	    case DT_ASCII:
140	    	ac = MIN_ASCII;
141		cp = dataPool;
142	    	for(i=0; i<size; i++) {
143		 	*cp++ = ac++;
144			if(ac > MAX_ASCII) {
145				ac = MIN_ASCII;
146			}
147		}
148		break;
149	    case DT_Random:
150	    	#ifdef	__LITTLE_ENDIAN__
151		    intCount = size >> 2;
152		    ip = (unsigned *)dataPool;
153		    for(i=0; i<intCount; i++) {
154			    *ip++ = RAND();
155		    }
156
157		    residue = size & 0x3;
158		    cp = (unsigned char *)ip;
159		    for(i=0; i<residue; i++) {
160			    *cp++ = (unsigned char)RAND();
161		    }
162	    	#else	__LITTLE_ENDIAN__
163		    cp = dataPool;
164		    for(i=0; i<size; i++) {
165			    *cp++ = (char)RAND();
166		    }
167		#endif	__LITTLE_ENDIAN__
168		break;
169	    case DT_None:
170	    	printf("fillDataPool(DT_None)\n");
171		exit(1);
172	}
173}
174
175static unsigned dataSizeFromExp(unsigned maxExp)
176{
177	int size = 1;
178	while(maxExp--) {			// size = 10 ** exp
179		size *= 10;
180	}
181	return size;
182}
183
184static int	sizeOffset = MIN_OFFSET;
185
186static unsigned char *genData(unsigned minExp,
187	unsigned maxExp,
188	dataType type,
189	BOOL incrOffset,
190	unsigned minOffset,
191	unsigned *dataLen)		// RETURNED
192{
193	int 		exp;
194	int 		offset;
195	int 		size;
196
197	/*
198	 * Calculate "random" size : (10 ** (random exponent)) + random offset
199	 */
200	exp = genRand(minExp, maxExp);
201	if(incrOffset) {
202		offset = sizeOffset++;
203		if(sizeOffset == MAX_OFFSET) {
204			sizeOffset = minOffset;
205		}
206	}
207	else {
208		offset = genRand(minOffset, MAX_OFFSET);
209	}
210	size = dataSizeFromExp(exp) + offset;
211	if(type != DT_None) {
212		fillDataPool(size, type);
213	}
214	*dataLen = size;
215	return dataPool;
216}
217
218static feePubKey genPrivKey(const unsigned char *privKeyData,
219	unsigned privDataLen,
220	int depth)
221{
222	feePubKey 	privKey;		// generic key object
223	feeReturn	frtn;
224
225	privKey = feePubKeyAlloc();
226	frtn = feePubKeyInitFromPrivDataDepth(privKey,
227		(unsigned char *)privKeyData,
228		privDataLen,
229		depth,
230		1);
231	if(frtn) {
232		printf("pubKeyFromPrivDataDepth: Can't create new key (%s)\n",
233			feeReturnString(frtn));
234		exit(1);
235	}
236	return privKey;
237}
238
239static feePubKey genPubKey(feePubKey privKey)
240{
241	feePubKey 	pubKey;			// generic key object
242	feeReturn	frtn;
243	char		*pubString;
244	unsigned	pubStringLen;
245
246	frtn = feePubKeyCreateKeyString(privKey, &pubString, &pubStringLen);
247	if(frtn) {
248		printf("feePubKeyCreateKeyString: Can't get key string (%s)\n",
249			feeReturnString(frtn));
250		exit(1);
251	}
252	pubKey = feePubKeyAlloc();
253	frtn = feePubKeyInitFromKeyString(pubKey, pubString, pubStringLen);
254	if(frtn) {
255		printf("feePubKeyInitFromKeyString: Can't create new key "
256			"(%s)\n",
257			feeReturnString(frtn));
258		feePubKeyFree(pubKey);
259		exit(1);
260	}
261	ffree(pubString);
262	return pubKey;
263}
264
265static char *stringFromEncrType(cipherFileEncrType encrType)
266{
267	switch(encrType) {
268	    case CFE_PublicDES: return "CFE_PublicDES";
269	    case CFE_RandDES: 	return "CFE_RandDES";
270	    case CFE_FEED: 	return "CFE_FEED";
271	    case CFE_FEEDExp: 	return "CFE_FEEDExp";
272	    default:		return "Bogus encrType";
273	}
274}
275
276#define SIG_NO		0
277#define SIG_YES		1
278#define EXPLICIT_NO	0
279#define EXPLICIT_YES	1
280#define EXPLICIT_ERR	2
281
282static void doTest(unsigned char *ptext,
283	unsigned ptextLen,
284	feePubKey myPrivKey,
285	feePubKey myPubKey,
286	feePubKey theirPrivKey,
287	feePubKey theirPubKey,
288	cipherFileEncrType encrType,
289	int doEnc64,
290	int doSig,
291	int doExplicitKey)	/* EXPLICIT_ERR means do one with
292				 * bad verify key */
293{
294	feeReturn 		frtn;
295	unsigned char 		*ctext;
296	unsigned 		ctextLen;
297	unsigned char 		*dectext;
298	unsigned 		dectextLen;
299	unsigned 		outUserData = 0x1234567;
300	unsigned 		inUserData;
301	cipherFileEncrType 	inEncrType;
302	feeSigStatus		sigStatus;
303	int 			abort = 0;
304	char			instr[100];
305	feeSigStatus		expSigStatus = SS_PresentValid;
306	int			valid64;
307
308	/*
309	 * These are tailored to specific encrTypes and doExplicitKeys
310	 */
311	feePubKey sendPrivKey = myPrivKey;
312	feePubKey sendPubKey = myPubKey;
313	feePubKey recvPrivKey = theirPrivKey;
314	feePubKey recvPubKey = theirPubKey;
315
316	switch(encrType) {
317	    case CFE_RandDES:
318	    case CFE_FEEDExp:
319	    	if(!doSig) {
320		    sendPrivKey = NULL;		// not needed
321		}
322		break;
323	    case CFE_PublicDES:
324	    case CFE_FEED:
325		break;
326	    default:
327	    	printf("Hey bozo! Give me a real encrType!\n");
328		exit(1);
329	}
330	if(!doSig) {
331	    sendPubKey = NULL;			// never needed
332	    expSigStatus = SS_NotPresent;
333	}
334	else switch(doExplicitKey) {
335	    case EXPLICIT_NO:
336	        sendPubKey = NULL;		// get it from cipherfile
337		break;
338	    case EXPLICIT_YES:
339	    	break;				// use myPubKey
340	    case EXPLICIT_ERR:
341	    	if(feePubKeyIsEqual(myPubKey, theirPubKey)) {
342			printf("myPubKey = theirPubKey!\n");
343			goto errOut;
344		}
345	    	sendPubKey = theirPubKey;	// hopefully != myPubKey!
346		expSigStatus = SS_PresentInvalid;
347		break;
348	    default:
349	    	printf("BOGUS doExplicitKey\n");
350		exit(1);
351	}
352
353	frtn = createCipherFile(sendPrivKey,
354		recvPubKey,
355		encrType,
356		ptext,
357		ptextLen,
358		doSig,
359		doEnc64,
360		outUserData,
361		&ctext,
362		&ctextLen);
363	if(frtn) {
364		printf("createCipherFile: %s\n", feeReturnString(frtn));
365		goto errOut;
366	}
367
368	valid64 = isValidEnc64(ctext, ctextLen);
369	if(valid64 != doEnc64) {
370		printf("valid64 mismatch! exp %d got %d\n", doEnc64, valid64);
371		abort = 1;
372	}
373	frtn = parseCipherFile(recvPrivKey,
374		sendPubKey,
375		ctext,
376		ctextLen,
377		doEnc64,
378		&inEncrType,
379		&dectext,
380		&dectextLen,
381		&sigStatus,
382		&inUserData);
383	if(frtn) {
384		printf("parseCipherFile: %s\n", feeReturnString(frtn));
385		goto errOut;
386	}
387	if(inEncrType != encrType) {
388		printf("encrType mismatch exp %d got %d\n",
389			encrType, inEncrType);
390		abort = 1;
391	}
392	if(inUserData != outUserData) {
393		printf("userData mismatch exp %d got %d\n",
394			outUserData, inUserData);
395		abort = 1;
396	}
397	if(sigStatus != expSigStatus) {
398	        printf("Bad sigStatus exp %d got %d\n",
399			expSigStatus, sigStatus);
400		abort = 1;
401	}
402	if(ptextLen != dectextLen) {
403		printf("ptextLen mismatch exp %d got %d\n",
404			ptextLen, dectextLen);
405		abort = 1;
406	}
407	if(bcmp(ptext, dectext, ptextLen)) {
408		printf("Data Miscompare\n");
409		abort = 1;
410	}
411	ffree(dectext);
412	ffree(ctext);
413	if(!abort) {
414		return;
415	}
416errOut:
417	/* dump params */
418	printf("attach with debugger for more info; enter CR to quit: ");
419	gets(instr);
420	exit(1);
421
422}
423
424int main(int argc, char **argv)
425{
426	int		arg;
427	char		*argp;
428	int		loop;
429	unsigned char	*ptext;
430	unsigned	ptextLen;
431	unsigned char	passwd1[PASSWD_LENGTH];
432	unsigned char	passwd2[PASSWD_LENGTH];
433	int		encrType;
434	int		doEnc64;
435	feePubKey	myPrivKey;
436	feePubKey	theirPrivKey;
437	feePubKey	myPubKey;
438	feePubKey	theirPubKey;
439	unsigned 	maxSize;
440
441	/*
442	 * User-spec'd params
443	 */
444	unsigned	loops = LOOPS_DEF;
445	BOOL		seedSpec = NO;
446	unsigned	seed;
447	BOOL		quiet = NO;
448	BOOL		verbose = NO;
449	unsigned	minExp = MIN_EXP;
450	unsigned	maxExp = MAX_EXP;
451	BOOL		incrOffset = NO;
452	unsigned	depth = DEPTH_DEFAULT;
453	unsigned	minOffset = MIN_OFFSET;
454
455	#if	macintosh
456	argc = ccommand(&argv);
457	#endif
458
459	for(arg=1; arg<argc; arg++) {
460		argp = argv[arg];
461		switch(argp[0]) {
462		    case 'l':
463			loops = atoi(&argp[2]);
464			break;
465		    case 'n':
466			minExp = atoi(&argp[2]);
467			break;
468		    case 'D':
469			depth = atoi(&argp[2]);
470			break;
471		    case 'N':
472			minOffset = atoi(&argp[2]);
473			if(minOffset > MAX_OFFSET) {
474				minOffset = MIN_OFFSET;
475			}
476			sizeOffset = minOffset;
477			break;
478		    case 'x':
479			maxExp = atoi(&argp[2]);
480			if(maxExp > MAX_EXP) {
481				usage(argv);
482			}
483			break;
484		    case 's':
485			seed = atoi(&argp[2]);
486			seedSpec = YES;
487			break;
488		    case 'I':
489		    	incrOffset = YES;
490			break;
491		    case 'q':
492		    	quiet = YES;
493			break;
494		    case 'v':
495		    	verbose = YES;
496			break;
497		    case 'h':
498		    default:
499			usage(argv);
500		}
501	}
502
503	if(seedSpec == NO) {
504		time((unsigned long *)(&seed));
505	}
506	SRAND(seed);
507	maxSize = dataSizeFromExp(maxExp) + MAX_OFFSET + 8;
508	dataPool = fmalloc(maxSize);
509
510	printf("Starting cfileTest: loops %d seed %d depth %d\n",
511		loops, seed, depth);
512
513	for(loop=1; ; loop++) {
514
515	    ptext = genData(minExp, maxExp, DT_Random, incrOffset,
516		    minOffset, &ptextLen);
517	    if(!quiet) {
518		    printf("..loop %d plaintext size %d\n", loop, ptextLen);
519	    }
520
521	    /*
522	     * Generate a whole bunch of keys
523	     */
524	    genPasswd(passwd1, PASSWD_LENGTH, NO);	// not ascii!
525	    genPasswd(passwd2, PASSWD_LENGTH, NO);
526	    myPrivKey 	 = genPrivKey(passwd1, PASSWD_LENGTH, depth);
527	    theirPrivKey = genPrivKey(passwd2, PASSWD_LENGTH, depth);
528	    myPubKey 	 = genPubKey(myPrivKey);
529	    theirPubKey  = genPubKey(theirPrivKey);
530
531	    for(encrType=CFE_PublicDES;
532		encrType<=CFE_FEEDExp;
533		encrType++) {
534
535		if(verbose) {
536		    printf("  ..%s\n", stringFromEncrType(encrType));
537		}
538		for(doEnc64=0; doEnc64<2; doEnc64++) {
539		    if(verbose) {
540		        printf("    ..doEnc64 %d\n", doEnc64);
541		    }
542
543		    if(verbose) {
544		        printf("      ..no sig\n");
545		    }
546	    	    doTest(ptext, ptextLen, myPrivKey, myPubKey,
547		    	theirPrivKey, theirPubKey,
548			encrType, doEnc64, SIG_NO, EXPLICIT_NO);
549
550		    if(verbose) {
551		        printf("      ..sig, implicit sendPubKey\n");
552		    }
553		    doTest(ptext, ptextLen, myPrivKey, myPubKey,
554		    	theirPrivKey, theirPubKey,
555			encrType, doEnc64, SIG_YES, EXPLICIT_NO);
556
557		    if(verbose) {
558		        printf("      ..sig, explicit sendPubKey\n");
559		    }
560		    doTest(ptext, ptextLen, myPrivKey, myPubKey,
561		    	theirPrivKey, theirPubKey,
562			encrType, doEnc64, SIG_YES, EXPLICIT_YES);
563
564		    if(verbose) {
565		        printf("      ..sig, force error\n");
566		    }
567		    doTest(ptext, ptextLen, myPrivKey, myPubKey,
568		    	theirPrivKey, theirPubKey,
569			encrType, doEnc64, SIG_YES, EXPLICIT_ERR);
570
571		} /* for doEnc64 */
572	    }	  /* for encrType */
573
574	    feePubKeyFree(myPrivKey);
575	    feePubKeyFree(myPubKey);
576	    feePubKeyFree(theirPrivKey);
577	    feePubKeyFree(theirPubKey);
578	    if(loops) {
579		    if(loop == loops) {
580			    break;
581		    }
582	    }
583	}	/* main loop */
584
585	if(!quiet) {
586		printf("cfile test complete\n");
587	}
588	return 0;
589}
590