]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cryptkit/ckutils/cfileTest/cfileTest.c
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / libsecurity_cryptkit / ckutils / cfileTest / cfileTest.c
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
32 static 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
50 static 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 */
67 static 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
83 static 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 */
117 typedef enum {
118 DT_Random,
119 DT_Zero,
120 DT_ASCII,
121 DT_None /* data irrelevant; use existing pool */
122 } dataType;
123
124 static 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
175 static unsigned dataSizeFromExp(unsigned maxExp)
176 {
177 int size = 1;
178 while(maxExp--) { // size = 10 ** exp
179 size *= 10;
180 }
181 return size;
182 }
183
184 static int sizeOffset = MIN_OFFSET;
185
186 static 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
218 static 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
239 static 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
265 static 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
282 static 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 }
416 errOut:
417 /* dump params */
418 printf("attach with debugger for more info; enter CR to quit: ");
419 gets(instr);
420 exit(1);
421
422 }
423
424 int 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 }