1/*
2 * Copyright (c) 1998,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 "Crypt.h"
26#include "falloc.h"
27#include <stdlib.h>
28#include <stdio.h>
29#include <time.h>
30#include "ckutilsPlatform.h"
31
32#define MIN_PASSWD_LENGTH	4
33#define MAX_PASSWD_LENGTH	20
34#define DEPTH_DEFAULT		FEE_DEPTH_DEFAULT
35
36#undef	BOOL
37#undef	YES
38#undef	NO
39#define BOOL	int
40#define YES	1
41#define NO	0
42
43static unsigned char *passwdPool;
44
45static unsigned doBlobTest(unsigned minPasswdLen,
46	unsigned maxPasswdLen,
47	BOOL verbose,
48	unsigned depth);
49static void usage(char **argv);
50
51int main(int argc, char **argv)
52{
53	BOOL 		seedSpec = NO;		// YES ==> user specified
54	unsigned 	loopNum;
55	int 		arg;
56	char 		*argp;
57
58	/*
59	 * User-spec'd variables
60	 */
61	unsigned 	minPasswordLen = MIN_PASSWD_LENGTH;
62	unsigned 	maxPasswordLen = MAX_PASSWD_LENGTH;
63	int 		seed = 0;
64	unsigned 	loops = 1;
65	BOOL		quiet = NO;
66	BOOL		verbose = NO;
67	unsigned	depth = DEPTH_DEFAULT;
68
69	#if	macintosh
70	argc = ccommand(&argv);
71	#endif
72	for(arg=1; arg<argc; arg++) {
73		argp = argv[arg];
74		switch(argp[0]) {
75		    case 'n':
76			minPasswordLen = atoi(&argp[2]);
77			break;
78		    case 'x':
79			maxPasswordLen = atoi(&argp[2]);
80			break;
81		    case 's':
82			seed = atoi(&argp[2]);
83			seedSpec = YES;
84			break;
85		    case 'l':
86			loops = atoi(&argp[2]);
87			break;
88		    case 'D':
89			depth = atoi(&argp[2]);
90			break;
91		    case 'q':
92		    	quiet = YES;
93			break;
94		    case 'v':
95		    	verbose = YES;
96			break;
97		    case 'h':
98		    default:
99			usage(argv);
100		}
101	}
102	if(seedSpec == NO) {
103		unsigned long	tim;
104		time(&tim);
105		seed = (unsigned)tim;
106	}
107	SRAND(seed);
108
109	passwdPool = fmalloc(maxPasswordLen + 4);
110
111	printf("Starting %s: minPasswd %d maxPasswd %d seed %d depth %d\n",
112		argv[0],
113		minPasswordLen, maxPasswordLen, seed, depth);
114
115	for(loopNum=1; ; loopNum++) {
116		if(!quiet) {
117			printf("..loop %d\n", loopNum);
118		}
119		if(doBlobTest(minPasswordLen, maxPasswordLen, verbose,
120				depth)) {
121			return 1;
122		}
123		if(loops && (loopNum == loops)) {
124			break;
125		}
126	}
127	if(!quiet) {
128		printf("%s test complete\n", argv[0]);
129	}
130	return 0;
131}
132
133static void usage(char **argv)
134{
135	printf("usage: %s [options]\n", argv[0]);
136	printf("   Options:\n");
137	printf("   l=loops (0=forever)\n");
138	printf("   n=minPasswordLen\n");
139	printf("   x=maxPasswdLen\n");
140	printf("   s=seed\n");
141	printf("   D=depth (default=%d)\n", DEPTH_DEFAULT);
142	printf("   q(uiet)\n");
143	printf("   v(erbose)\n");
144	printf("   h(elp)\n");
145	exit(1);
146}
147
148static unsigned char *genPasswd(unsigned passwdLength)
149{
150	unsigned *ip = (unsigned *)passwdPool;
151	unsigned intCount = (passwdLength + 3) / 4;
152	int i;
153	unsigned char *rtn;
154
155	for (i=0; i<intCount; i++) {
156		*ip++ = RAND();
157	}
158	rtn = fmalloc(passwdLength);
159	bcopy(passwdPool, rtn, passwdLength);
160	return rtn;
161}
162
163static unsigned doBlobTest(unsigned minPasswdLen,
164	unsigned maxPasswdLen,
165	BOOL verbose,
166	unsigned depth)
167{
168	unsigned char 	*myPasswd = NULL;
169	unsigned 	myPasswdLen;
170	feePubKey 	myPrivate = NULL;
171	feePubKey 	myPrivateCopy = NULL;	// from blob
172	feePubKey 	myPublic = NULL;	// from blob from myPrivate
173	feePubKey 	myPublicCopy = NULL;	// from blob from myPublic
174	unsigned	rtn = 0;
175	feeReturn	frtn;
176	unsigned char 	*privBlob = NULL;
177	unsigned	privBlobLen;
178	unsigned char 	*pubBlob = NULL;
179	unsigned	pubBlobLen;
180
181	for(myPasswdLen=minPasswdLen;
182	    myPasswdLen<maxPasswdLen;
183	    myPasswdLen++) {
184
185	    	if(verbose) {
186		    printf("....myPasswdLen %d\n", myPasswdLen);
187		}
188
189		/*
190		 * my private password
191		 */
192		myPasswd = genPasswd(myPasswdLen);
193
194		/*
195		 * Fully capable Public Key object
196		 */
197		myPrivate = feePubKeyAlloc();
198		frtn = feePubKeyInitFromPrivDataDepth(myPrivate,
199			myPasswd,
200			myPasswdLen,
201			depth,
202			1);
203		if(frtn) {
204			printf("feePubKeyInitFromPrivDataDepth: %s\n",
205				feeReturnString(frtn));
206			rtn = 1;
207			goto out;
208		}
209
210		/* private blob */
211		frtn = feePubKeyCreatePrivBlob(myPrivate,
212			&privBlob,
213			&privBlobLen);
214		if(frtn) {
215			printf("feePubKeyCreatePrivBlob: %s\n",
216				feeReturnString(frtn));
217			rtn = 1;
218			goto out;
219		}
220
221		/* private key from private blob */
222		myPrivateCopy = feePubKeyAlloc();
223		frtn = feePubKeyInitFromPrivBlob(myPrivateCopy,
224			privBlob,
225			privBlobLen);
226		if(frtn) {
227			printf("feePubKeyInitFromKeyBlob (private): %s\n",
228				feeReturnString(frtn));
229			rtn = 1;
230			goto out;
231		}
232		if(!feePubKeyIsPrivate(myPrivateCopy)) {
233			printf("Unexpected !feePubKeyIsPrivate!\n");
234			rtn = 1;
235			goto out;
236		}
237
238		/* public blob from private key */
239		frtn = feePubKeyCreatePubBlob(myPrivate,
240			&pubBlob,
241			&pubBlobLen);
242		if(frtn) {
243			printf("feePubKeyCreatePubBlob (1): %s\n",
244				feeReturnString(frtn));
245			rtn = 1;
246			goto out;
247		}
248
249		/* public key from public blob */
250		myPublic = feePubKeyAlloc();
251		frtn = feePubKeyInitFromPubBlob(myPublic,
252			pubBlob,
253			pubBlobLen);
254		if(frtn) {
255			printf("feePubKeyInitFromKeyBlob (pub 1): %s\n",
256				feeReturnString(frtn));
257			rtn = 1;
258			goto out;
259		}
260		if(feePubKeyIsPrivate(myPublic)) {
261			printf("Unexpected feePubKeyIsPrivate (1)!\n");
262			rtn = 1;
263			goto out;
264		}
265		ffree(pubBlob);
266		pubBlob = NULL;
267
268		/* public blob from public key */
269		frtn = feePubKeyCreatePubBlob(myPublic,
270			&pubBlob,
271			&pubBlobLen);
272		if(frtn) {
273			printf("feePubKeyCreatePubBlob (2): %s\n",
274				feeReturnString(frtn));
275			rtn = 1;
276			goto out;
277		}
278
279		/* public key from public blob */
280		myPublicCopy = feePubKeyAlloc();
281		frtn = feePubKeyInitFromPubBlob(myPublicCopy,
282			pubBlob,
283			pubBlobLen);
284		if(frtn) {
285			printf("feePubKeyInitFromKeyBlob (pub 2): %s\n",
286				feeReturnString(frtn));
287			rtn = 1;
288			goto out;
289		}
290		if(feePubKeyIsPrivate(myPublicCopy)) {
291			printf("Unexpected feePubKeyIsPrivate (2)!\n");
292			rtn = 1;
293			goto out;
294		}
295
296		/* private blob from pub key - should fail */
297		frtn = feePubKeyCreatePrivBlob(myPublic,
298			&pubBlob,
299			&pubBlobLen);
300		if(frtn == FR_Success) {
301		    printf("Unexpected feePubKeyCreatePrivBlob success\n");
302		    rtn = 1;
303		    goto out;
304		}
305
306		/*
307		 * OK, we have four keys; they should all be equal (in
308		 * terms of their actual public data).
309		 */
310		if(!feePubKeyIsEqual(myPrivate, myPrivateCopy)) {
311			printf("myPrivate != myPrivateCopy\n");
312			rtn = 1;
313			goto out;
314		}
315		if(!feePubKeyIsEqual(myPrivate, myPublic)) {
316			printf("myPrivate != myPublic\n");
317			rtn = 1;
318			goto out;
319		}
320		if(!feePubKeyIsEqual(myPrivate, myPublicCopy)) {
321			printf("myPrivate != myPublicCopy\n");
322			rtn = 1;
323			goto out;
324		}
325		if(!feePubKeyIsEqual(myPublic, myPublicCopy)) {
326			printf("myPublic != myPublicCopy\n");
327			rtn = 1;
328			goto out;
329		}
330	    out:
331		if(myPasswd) {
332			ffree(myPasswd);
333		}
334		if(myPrivate) {
335			feePubKeyFree(myPrivate);
336		}
337		if(myPrivateCopy) {
338			feePubKeyFree(myPrivateCopy);
339		}
340		if(myPublic) {
341			feePubKeyFree(myPublic);
342		}
343		if(myPublic) {
344			feePubKeyFree(myPublicCopy);
345		}
346		if(privBlob) {
347			ffree(privBlob);
348		}
349		if(pubBlob) {
350			ffree(pubBlob);
351		}
352		if(rtn) {
353			break;
354		}
355	}
356	return rtn;
357}
358
359