]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/pbeTest/pbeTest.c
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / cspxutils / pbeTest / pbeTest.c
1 /* Copyright (c) 1998,2003-2005,2008 Apple Inc.
2 *
3 * pbeTest.c - test CSP PBE-style DeriveKey().
4 *
5 * Revision History
6 * ----------------
7 * 15 May 2000 Doug Mitchell
8 * Ported to X/CDSA2.
9 * 13 Aug 1998 Doug Mitchell at NeXT
10 * Created.
11 */
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <time.h>
15 #include <string.h>
16 #include <Security/cssm.h>
17 #include "cspwrap.h"
18 #include "common.h"
19 #include "cspdlTesting.h"
20
21 /* we need to know a little bit about AES for this test.... */
22 #define AES_BLOCK_SIZE 16 /* bytes */
23
24 /*
25 * Defaults.
26 */
27 #define LOOPS_DEF 10
28 #define MIN_PTEXT_SIZE AES_BLOCK_SIZE /* for non-padding tests */
29 #define MAX_PTEXT_SIZE 1000
30 #define MAX_PASSWORD_SIZE 64
31 #define MAX_SALT_SIZE 32
32 #define MIN_ITER_COUNT 1000
33 #define MAX_ITER_COUNT 2000
34 #define MAX_IV_SIZE AES_BLOCK_SIZE
35
36 /* min values not currently exported by CSP */
37 #define APPLE_PBE_MIN_PASSWORD 8
38 #define APPLE_PBE_MIN_SALT 8
39
40 /* static IV for derive algorithms which don't create one */
41 CSSM_DATA staticIv = {MAX_IV_SIZE, (uint8 *)"someIvOrOther..."};
42
43 /*
44 * Enumerate algs our own way to allow iteration.
45 */
46 typedef unsigned privAlg;
47 enum {
48 /* PBE algs */
49 pbe_pbkdf2 = 1,
50 // other unsupported for now
51 pbe_PKCS12 = 1,
52 pbe_MD5,
53 pbe_MD2,
54 pbe_SHA1,
55
56 /* key gen algs */
57 pka_ASC,
58 pka_RC4,
59 pka_DES,
60 pka_RC2,
61 pka_RC5,
62 pka_3DES,
63 pka_AES
64 };
65
66 #define PBE_ALG_FIRST pbe_pbkdf2
67 #define PBE_ALG_LAST pbe_pbkdf2
68 #define ENCR_ALG_FIRST pka_ASC
69 #define ENCR_ALG_LAST pka_AES
70 #define ENCR_ALG_LAST_EXPORT pka_RC5
71
72 /*
73 * Args passed to each test
74 */
75 typedef struct {
76 CSSM_CSP_HANDLE cspHand;
77 CSSM_ALGORITHMS keyAlg;
78 CSSM_ALGORITHMS encrAlg;
79 uint32 keySizeInBits;
80 uint32 effectiveKeySizeInBits; // 0 means not used
81 const char *keyAlgStr;
82 CSSM_ENCRYPT_MODE encrMode;
83 CSSM_PADDING encrPad;
84 CSSM_ALGORITHMS deriveAlg;
85 const char *deriveAlgStr;
86 CSSM_DATA_PTR ptext;
87 CSSM_DATA_PTR password;
88 CSSM_DATA_PTR salt;
89 uint32 iterCount;
90 CSSM_BOOL useInitVector; // encrypt needs an IV
91 uint32 ivSize;
92 CSSM_BOOL genInitVector; // DeriveKey generates an IV
93 CSSM_BOOL useRefKey;
94 CSSM_BOOL quiet;
95 } testArgs;
96
97 static void usage(char **argv)
98 {
99 printf("usage: %s [options]\n", argv[0]);
100 printf(" Options:\n");
101 printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF);
102 printf(" e(xport)\n");
103 printf(" r(epeatOnly)\n");
104 printf(" z(ero length password)\n");
105 printf(" p(ause after each loop)\n");
106 printf(" D (CSP/DL; default = bare CSP)\n");
107 printf(" q(uiet)\n");
108 printf(" h(elp)\n");
109 exit(1);
110 }
111
112 /*
113 * Given a privAlg value, return various associated stuff.
114 */
115 static void algInfo(privAlg alg, // pbe_MD5, etc.
116 CSSM_ALGORITHMS *cdsaAlg, // CSSM_ALGID_MD5_PBE, etc. RETURNED
117 // key alg for key gen algs
118 CSSM_ALGORITHMS *encrAlg, // encrypt/decrypt alg for key
119 // gen algs
120 CSSM_ENCRYPT_MODE *mode, // RETURNED
121 CSSM_PADDING *padding, // RETURNED
122 CSSM_BOOL *useInitVector, // RETURNED, for encrypt/decrypt
123 uint32 *ivSize, // RETURNED, in bytes
124 CSSM_BOOL *genInitVector, // RETURNED, for deriveKey
125 const char **algStr) // RETURNED
126 {
127 /* default or irrelevant fields */
128 *mode = CSSM_ALGMODE_NONE;
129 *useInitVector = CSSM_FALSE;
130 *genInitVector = CSSM_FALSE; // DeriveKey doesn't do this now
131 *padding = CSSM_PADDING_PKCS1;
132 *ivSize = 8; // thje usual size, if needed
133 *encrAlg = CSSM_ALGID_NONE;
134
135 switch(alg) {
136 case pbe_pbkdf2:
137 *cdsaAlg = CSSM_ALGID_PKCS5_PBKDF2;
138 *algStr = "PBKDF2";
139 return;
140 /* these are not supported */
141 #if 0
142 case pbe_PKCS12:
143 *cdsaAlg = CSSM_ALGID_SHA1_PBE_PKCS12;
144 *algStr = "PKCS12";
145 return;
146 case pbe_MD5:
147 *cdsaAlg = CSSM_ALGID_MD5_PBE;
148 *algStr = "MD5";
149 return;
150 case pbe_MD2:
151 *cdsaAlg = CSSM_ALGID_MD2_PBE;
152 *algStr = "MD2";
153 return;
154 case pbe_SHA1:
155 *cdsaAlg = CSSM_ALGID_SHA1_PBE;
156 *algStr = "SHA1";
157 return;
158 case pka_ASC:
159 *cdsaAlg = CSSM_ALGID_ASC;
160 *algStr = "ASC";
161 return;
162 #endif
163 case pka_DES:
164 *cdsaAlg = *encrAlg = CSSM_ALGID_DES;
165 *useInitVector = CSSM_TRUE;
166 *mode = CSSM_ALGMODE_CBCPadIV8;
167 *algStr = "DES";
168 return;
169 case pka_3DES:
170 *cdsaAlg = CSSM_ALGID_3DES_3KEY;
171 *encrAlg = CSSM_ALGID_3DES_3KEY_EDE;
172 *useInitVector = CSSM_TRUE;
173 *mode = CSSM_ALGMODE_CBCPadIV8;
174 *algStr = "3DES";
175 return;
176 case pka_AES:
177 *cdsaAlg = *encrAlg = CSSM_ALGID_AES;
178 *useInitVector = CSSM_TRUE;
179 *mode = CSSM_ALGMODE_CBCPadIV8;
180 *padding = CSSM_PADDING_PKCS5;
181 *ivSize = AES_BLOCK_SIZE; // per the default block size
182 *algStr = "AES";
183 return;
184 case pka_RC2:
185 *cdsaAlg = *encrAlg = CSSM_ALGID_RC2;
186 *useInitVector = CSSM_TRUE;
187 *mode = CSSM_ALGMODE_CBCPadIV8;
188 *algStr = "RC2";
189 return;
190 case pka_RC4:
191 *cdsaAlg = *encrAlg = CSSM_ALGID_RC4;
192 /* initVector false */
193 *mode = CSSM_ALGMODE_NONE;
194 *algStr = "RC4";
195 return;
196 case pka_RC5:
197 *cdsaAlg = *encrAlg = CSSM_ALGID_RC5;
198 *algStr = "RC5";
199 *mode = CSSM_ALGMODE_CBCPadIV8;
200 *useInitVector = CSSM_TRUE;
201 return;
202 case pka_ASC:
203 *cdsaAlg = *encrAlg = CSSM_ALGID_ASC;
204 /* initVector false */
205 *algStr = "ASC";
206 *mode = CSSM_ALGMODE_NONE;
207 return;
208 default:
209 printf("BRRZZZT! Update algInfo()!\n");
210 testError(CSSM_TRUE);
211 }
212 }
213
214 /* a handy "compare two CSSM_DATAs" ditty */
215 static CSSM_BOOL compareData(const CSSM_DATA_PTR d1,
216 const CSSM_DATA_PTR d2)
217 {
218 if(d1->Length != d2->Length) {
219 return CSSM_FALSE;
220 }
221 if(memcmp(d1->Data, d2->Data, d1->Length)) {
222 return CSSM_FALSE;
223 }
224 return CSSM_TRUE;
225 }
226
227 /* generate random one-bit byte */
228 static uint8 randBit()
229 {
230 return 1 << genRand(0, 7);
231 }
232
233 /*
234 * Writer debug - assertion failure when ctext[1].Data is NULL
235 * but length is nonzero
236 */
237 #define SAFE_CTEXT_ARRAY 0
238
239 /*
240 * Encrypt ptext using specified key, IV, effectiveKeySizeInBits
241 */
242 static int encryptCom(CSSM_CSP_HANDLE cspHand,
243 const char *testName,
244 CSSM_DATA_PTR ptext,
245 CSSM_KEY_PTR key,
246 CSSM_ALGORITHMS alg,
247 CSSM_ENCRYPT_MODE mode,
248 CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc.
249 CSSM_DATA_PTR iv, // may be NULL
250 uint32 effectiveKeySizeInBits, // may be 0
251 CSSM_DATA_PTR ctext, // RETURNED
252 CSSM_BOOL quiet)
253 {
254 CSSM_CC_HANDLE cryptHand;
255 CSSM_RETURN crtn;
256 CSSM_SIZE bytesEncrypted;
257 CSSM_DATA remData;
258 int rtn;
259 #if SAFE_CTEXT_ARRAY
260 CSSM_DATA safeCtext[2];
261 safeCtext[0] = *ctext;
262 safeCtext[1].Data = NULL;
263 safeCtext[1].Length = 10; // lie, but shouldn't use this!
264 #else
265 // printf("+++ ctext[0] = %d:0x%x; ctext[1] = %d:0x%x\n",
266 // ctext[0].Length, ctext[0].Data,
267 // ctext[1].Length, ctext[1].Data);
268 #endif
269
270 cryptHand = genCryptHandle(cspHand,
271 alg,
272 mode,
273 padding,
274 key,
275 NULL, // no 2nd key
276 iv, // InitVector
277 effectiveKeySizeInBits,
278 0); // rounds
279 if(cryptHand == 0) {
280 return testError(quiet);
281 }
282
283 remData.Data = NULL;
284 remData.Length = 0;
285 crtn = CSSM_EncryptData(cryptHand,
286 ptext,
287 1,
288 #if SAFE_CTEXT_ARRAY
289 &safeCtext[0],
290 #else
291 ctext,
292 #endif
293 1,
294 &bytesEncrypted,
295 &remData);
296 #if SAFE_CTEXT_ARRAY
297 *ctext = safeCtext[0];
298 #endif
299
300 if(crtn) {
301 printError("CSSM_EncryptData", crtn);
302 rtn = testError(quiet);
303 goto done;
304 }
305 if(remData.Length != 0) {
306 //printf("***WARNING: nonzero remData on encrypt!\n");
307 /* new for CDSA2 - possible remData even if we ask the CSP to
308 * malloc ctext */
309 ctext->Data = (uint8 *)appRealloc(ctext->Data, bytesEncrypted, NULL);
310 memmove(ctext->Data + ctext->Length,
311 remData.Data,
312 bytesEncrypted - ctext->Length);
313 appFreeCssmData(&remData, CSSM_FALSE);
314 }
315 /* new for CDSA 2 */
316 ctext->Length = bytesEncrypted;
317 rtn = 0;
318 done:
319 if(CSSM_DeleteContext(cryptHand)) {
320 printError("CSSM_DeleteContext", 0);
321 rtn = 1;
322 }
323 return rtn;
324 }
325
326 /*
327 * Decrypt ctext using specified key, IV, effectiveKeySizeInBits
328 */
329 static int decryptCom(CSSM_CSP_HANDLE cspHand,
330 const char *testName,
331 CSSM_DATA_PTR ctext,
332 CSSM_KEY_PTR key,
333 CSSM_ALGORITHMS alg,
334 CSSM_ENCRYPT_MODE mode,
335 CSSM_PADDING padding,
336 CSSM_DATA_PTR iv, // may be NULL
337 uint32 effectiveKeySizeInBits, // may be 0
338 CSSM_DATA_PTR ptext, // RETURNED
339 CSSM_BOOL quiet)
340 {
341 CSSM_CC_HANDLE cryptHand;
342 CSSM_RETURN crtn;
343 CSSM_SIZE bytesDecrypted;
344 CSSM_DATA remData;
345 int rtn;
346
347 cryptHand = genCryptHandle(cspHand,
348 alg,
349 mode,
350 padding,
351 key,
352 NULL, // no 2nd key
353 iv, // InitVector
354 effectiveKeySizeInBits,
355 0); // rounds
356 if(cryptHand == 0) {
357 return testError(quiet);
358 }
359 remData.Data = NULL;
360 remData.Length = 0;
361 crtn = CSSM_DecryptData(cryptHand,
362 ctext,
363 1,
364 ptext,
365 1,
366 &bytesDecrypted,
367 &remData);
368 if(crtn) {
369 printError("CSSM_DecryptData", crtn);
370 rtn = testError(quiet);
371 goto done;
372 }
373 if(remData.Length != 0) {
374 //printf("***WARNING: nonzero remData on decrypt!\n");
375 /* new for CDSA2 - possible remData even if we ask the CSP to
376 * malloc ptext */
377 ptext->Data = (uint8 *)appRealloc(ptext->Data, bytesDecrypted, NULL);
378 memmove(ptext->Data + ptext->Length,
379 remData.Data,
380 bytesDecrypted - ptext->Length);
381 appFreeCssmData(&remData, CSSM_FALSE);
382 }
383 /* new for CDSA 2 */
384 ptext->Length = bytesDecrypted;
385 rtn = 0;
386 done:
387 if(CSSM_DeleteContext(cryptHand)) {
388 printError("CSSM_DeleteContext", 0);
389 rtn = 1;
390 }
391 return rtn;
392 }
393
394 /*
395 * Common test portion
396 * encrypt ptext with key1, iv1
397 * encrypt ptext with key2, iv2
398 * compare 2 ctexts; expect failure;
399 */
400
401 #define TRAP_WRITER_ERR 1
402
403 static int testCommon(CSSM_CSP_HANDLE cspHand,
404 const char *testName,
405 CSSM_ALGORITHMS encrAlg,
406 CSSM_ENCRYPT_MODE encrMode,
407 CSSM_PADDING encrPad,
408 uint32 effectiveKeySizeInBits,
409 CSSM_DATA_PTR ptext,
410 CSSM_KEY_PTR key1,
411 CSSM_DATA_PTR iv1,
412 CSSM_KEY_PTR key2,
413 CSSM_DATA_PTR iv2,
414 CSSM_BOOL quiet)
415 {
416 CSSM_DATA ctext1;
417 CSSM_DATA ctext2;
418 ctext1.Data = NULL;
419 ctext1.Length = 0;
420 ctext2.Data = NULL;
421 ctext2.Length = 0;
422 if(encryptCom(cspHand,
423 testName,
424 ptext,
425 key1,
426 encrAlg,
427 encrMode,
428 encrPad,
429 iv1,
430 effectiveKeySizeInBits,
431 &ctext1,
432 quiet)) {
433 return 1;
434 }
435 #if TRAP_WRITER_ERR
436 if(ctext2.Data != NULL){
437 printf("Hey! encryptCom(ptext, ctext1 modified ctext2!\n");
438 if(testError(quiet)) {
439 return 1;
440 }
441 }
442 #endif
443 if(encryptCom(cspHand,
444 testName,
445 ptext,
446 key2,
447 encrAlg,
448 encrMode,
449 encrPad,
450 iv2,
451 effectiveKeySizeInBits,
452 &ctext2,
453 quiet)) {
454 return 1;
455 }
456 if(compareData(&ctext1, &ctext2)) {
457 printf("***%s: Unexpected Data compare!\n", testName);
458 return testError(quiet);
459 }
460 appFreeCssmData(&ctext1, CSSM_FALSE);
461 appFreeCssmData(&ctext2, CSSM_FALSE);
462 return 0;
463 }
464
465 /**
466 ** inidividual tests.
467 **/
468 #define KEY_LABEL1 "noLabel1"
469 #define KEY_LABEL2 "noLabel2"
470 #define KEY_LABEL_LEN strlen(KEY_LABEL1)
471 #define REPEAT_ON_ERROR 1
472
473 /* test repeatability - the only test here which actually decrypts */
474 static int repeatTest(testArgs *targs)
475 {
476 /*
477 generate two keys with same params;
478 encrypt ptext with key1;
479 decrypt ctext with key2;
480 compare; expect success;
481 */
482 CSSM_KEY_PTR key1;
483 CSSM_KEY_PTR key2;
484 CSSM_DATA iv1;
485 CSSM_DATA iv2;
486 CSSM_DATA_PTR ivp1;
487 CSSM_DATA_PTR ivp2;
488 CSSM_DATA ctext;
489 CSSM_DATA rptext;
490 CSSM_BOOL gotErr = CSSM_FALSE;
491
492 if(targs->useInitVector) {
493 if(targs->genInitVector) {
494 ivp1 = &iv1;
495 ivp2 = &iv2;
496 }
497 else {
498 staticIv.Length = targs->ivSize;
499 ivp1 = ivp2 = &staticIv;
500 }
501 }
502 else {
503 ivp1 = ivp2 = NULL;
504 }
505 /* these need to be init'd regardless */
506 iv1.Data = NULL;
507 iv1.Length = 0;
508 iv2.Data = NULL;
509 iv2.Length = 0;
510 ctext.Data = NULL;
511 ctext.Length = 0;
512 rptext.Data = NULL;
513 rptext.Length = 0;
514 repeatDerive:
515 key1 = cspDeriveKey(targs->cspHand,
516 targs->deriveAlg,
517 targs->keyAlg,
518 KEY_LABEL1,
519 KEY_LABEL_LEN,
520 CSSM_KEYUSE_ENCRYPT,
521 targs->keySizeInBits,
522 targs->useRefKey,
523 targs->password,
524 targs->salt,
525 targs->iterCount,
526 &iv1);
527 if(key1 == NULL) {
528 return testError(targs->quiet);
529 }
530 key2 = cspDeriveKey(targs->cspHand,
531 targs->deriveAlg,
532 targs->keyAlg,
533 KEY_LABEL2,
534 KEY_LABEL_LEN,
535 CSSM_KEYUSE_DECRYPT,
536 targs->keySizeInBits,
537 targs->useRefKey,
538 targs->password,
539 targs->salt,
540 targs->iterCount,
541 &iv2);
542 if(key2 == NULL) {
543 return testError(targs->quiet);
544 }
545 repeatEnc:
546 if(encryptCom(targs->cspHand,
547 "repeatTest",
548 targs->ptext,
549 key1,
550 targs->encrAlg,
551 targs->encrMode,
552 targs->encrPad,
553 ivp1,
554 targs->effectiveKeySizeInBits,
555 &ctext,
556 targs->quiet)) {
557 return 1;
558 }
559 if(decryptCom(targs->cspHand,
560 "repeatTest",
561 &ctext,
562 key2,
563 targs->encrAlg,
564 targs->encrMode,
565 targs->encrPad,
566 ivp2,
567 targs->effectiveKeySizeInBits,
568 &rptext,
569 targs->quiet)) {
570 return 1;
571 }
572 if(gotErr || !compareData(targs->ptext, &rptext)) {
573 printf("***Data miscompare in repeatTest\n");
574 if(REPEAT_ON_ERROR) {
575 char str;
576
577 gotErr = CSSM_TRUE;
578 fpurge(stdin);
579 printf("Repeat enc/dec (r), repeat derive (d), continue (c), abort (any)? ");
580 str = getchar();
581 switch(str) {
582 case 'r':
583 appFreeCssmData(&ctext, CSSM_FALSE);
584 appFreeCssmData(&rptext, CSSM_FALSE);
585 goto repeatEnc;
586 case 'd':
587 appFreeCssmData(&ctext, CSSM_FALSE);
588 appFreeCssmData(&rptext, CSSM_FALSE);
589 appFreeCssmData(&iv1, CSSM_FALSE);
590 appFreeCssmData(&iv2, CSSM_FALSE);
591 cspFreeKey(targs->cspHand, key1);
592 cspFreeKey(targs->cspHand, key2);
593 goto repeatDerive;
594 case 'c':
595 break;
596 default:
597 return 1;
598 }
599 }
600 else {
601 return testError(targs->quiet);
602 }
603 }
604 appFreeCssmData(&ctext, CSSM_FALSE);
605 appFreeCssmData(&rptext, CSSM_FALSE);
606 appFreeCssmData(&iv1, CSSM_FALSE);
607 appFreeCssmData(&iv2, CSSM_FALSE);
608 cspFreeKey(targs->cspHand, key1);
609 cspFreeKey(targs->cspHand, key2);
610 CSSM_FREE(key1);
611 CSSM_FREE(key2);
612 return 0;
613 }
614
615 /* ensure iterCount alters key */
616 static int iterTest(testArgs *targs)
617 {
618 /*
619 generate key1(iterCount), key2(iterCount+1);
620 encrypt ptext with key1;
621 encrypt ptext with key2;
622 compare 2 ctexts; expect failure;
623 */
624 CSSM_KEY_PTR key1;
625 CSSM_KEY_PTR key2;
626 CSSM_DATA iv1;
627 CSSM_DATA iv2;
628 CSSM_DATA_PTR ivp1;
629 CSSM_DATA_PTR ivp2;
630 if(targs->useInitVector) {
631 if(targs->genInitVector) {
632 ivp1 = &iv1;
633 ivp2 = &iv2;
634 }
635 else {
636 staticIv.Length = targs->ivSize;
637 ivp1 = ivp2 = &staticIv;
638 }
639 }
640 else {
641 ivp1 = ivp2 = NULL;
642 }
643 /* these need to be init'd regardless */
644 iv1.Data = NULL;
645 iv1.Length = 0;
646 iv2.Data = NULL;
647 iv2.Length = 0;
648 key1 = cspDeriveKey(targs->cspHand,
649 targs->deriveAlg,
650 targs->keyAlg,
651 KEY_LABEL1,
652 KEY_LABEL_LEN,
653 CSSM_KEYUSE_ENCRYPT,
654 targs->keySizeInBits,
655 targs->useRefKey,
656 targs->password,
657 targs->salt,
658 targs->iterCount,
659 &iv1);
660 if(key1 == NULL) {
661 return testError(targs->quiet);
662 }
663 key2 = cspDeriveKey(targs->cspHand,
664 targs->deriveAlg,
665 targs->keyAlg,
666 KEY_LABEL2,
667 KEY_LABEL_LEN,
668 CSSM_KEYUSE_ENCRYPT,
669 targs->keySizeInBits,
670 targs->useRefKey,
671 targs->password,
672 targs->salt,
673 targs->iterCount + 1, // the changed param
674 &iv2);
675 if(key2 == NULL) {
676 return testError(targs->quiet);
677 }
678 if(testCommon(targs->cspHand,
679 "iterTest",
680 targs->encrAlg,
681 targs->encrMode,
682 targs->encrPad,
683 targs->effectiveKeySizeInBits,
684 targs->ptext,
685 key1,
686 ivp1,
687 key2,
688 ivp2,
689 targs->quiet)) {
690 return 1;
691 }
692 appFreeCssmData(&iv1, CSSM_FALSE);
693 appFreeCssmData(&iv2, CSSM_FALSE);
694 cspFreeKey(targs->cspHand, key1);
695 cspFreeKey(targs->cspHand, key2);
696 CSSM_FREE(key1);
697 CSSM_FREE(key2);
698 return 0;
699 }
700
701 /* ensure password alters key */
702 static int passwordTest(testArgs *targs)
703 {
704 /*
705 generate key1(password), key2(munged password);
706 encrypt ptext with key1;
707 encrypt ptext with key2;
708 compare 2 ctexts; expect failure;
709 */
710 CSSM_KEY_PTR key1;
711 CSSM_KEY_PTR key2;
712 CSSM_DATA iv1;
713 CSSM_DATA iv2;
714 CSSM_DATA_PTR ivp1;
715 CSSM_DATA_PTR ivp2;
716 uint32 mungeDex;
717 uint32 mungeBits;
718 if(targs->useInitVector) {
719 if(targs->genInitVector) {
720 ivp1 = &iv1;
721 ivp2 = &iv2;
722 }
723 else {
724 staticIv.Length = targs->ivSize;
725 ivp1 = ivp2 = &staticIv;
726 }
727 }
728 else {
729 ivp1 = ivp2 = NULL;
730 }
731 /* these need to be init'd regardless */
732 iv1.Data = NULL;
733 iv1.Length = 0;
734 iv2.Data = NULL;
735 iv2.Length = 0;
736 key1 = cspDeriveKey(targs->cspHand,
737 targs->deriveAlg,
738 targs->keyAlg,
739 KEY_LABEL1,
740 KEY_LABEL_LEN,
741 CSSM_KEYUSE_ENCRYPT,
742 targs->keySizeInBits,
743 targs->useRefKey,
744 targs->password,
745 targs->salt,
746 targs->iterCount,
747 &iv1);
748 if(key1 == NULL) {
749 return testError(targs->quiet);
750 }
751 /* munge password */
752 mungeDex = genRand(0, targs->password->Length - 1);
753 mungeBits = randBit();
754 targs->password->Data[mungeDex] ^= mungeBits;
755 key2 = cspDeriveKey(targs->cspHand,
756 targs->deriveAlg,
757 targs->keyAlg,
758 KEY_LABEL2,
759 KEY_LABEL_LEN,
760 CSSM_KEYUSE_ENCRYPT,
761 targs->keySizeInBits,
762 targs->useRefKey,
763 targs->password, // the changed param
764 targs->salt,
765 targs->iterCount,
766 &iv2);
767 if(key2 == NULL) {
768 return testError(targs->quiet);
769 }
770 if(testCommon(targs->cspHand,
771 "passwordTest",
772 targs->encrAlg,
773 targs->encrMode,
774 targs->encrPad,
775 targs->effectiveKeySizeInBits,
776 targs->ptext,
777 key1,
778 ivp1,
779 key2,
780 ivp2,
781 targs->quiet)) {
782 return 1;
783 }
784 /* restore */
785 targs->password->Data[mungeDex] ^= mungeBits;
786 appFreeCssmData(&iv1, CSSM_FALSE);
787 appFreeCssmData(&iv2, CSSM_FALSE);
788 cspFreeKey(targs->cspHand, key1);
789 cspFreeKey(targs->cspHand, key2);
790 CSSM_FREE(key1);
791 CSSM_FREE(key2);
792 return 0;
793 }
794
795 /* ensure salt alters key */
796 static int saltTest(testArgs *targs)
797 {
798 /*
799 generate key1(seed), key2(munged seed);
800 encrypt ptext with key1;
801 encrypt ptext with key2;
802 compare 2 ctexts; expect failure;
803 */
804 CSSM_KEY_PTR key1;
805 CSSM_KEY_PTR key2;
806 CSSM_DATA iv1;
807 CSSM_DATA iv2;
808 CSSM_DATA_PTR ivp1;
809 CSSM_DATA_PTR ivp2;
810 uint32 mungeDex;
811 uint32 mungeBits;
812 if(targs->useInitVector) {
813 if(targs->genInitVector) {
814 ivp1 = &iv1;
815 ivp2 = &iv2;
816 }
817 else {
818 staticIv.Length = targs->ivSize;
819 ivp1 = ivp2 = &staticIv;
820 }
821 }
822 else {
823 ivp1 = ivp2 = NULL;
824 }
825 /* these need to be init'd regardless */
826 iv1.Data = NULL;
827 iv1.Length = 0;
828 iv2.Data = NULL;
829 iv2.Length = 0;
830 key1 = cspDeriveKey(targs->cspHand,
831 targs->deriveAlg,
832 targs->keyAlg,
833 KEY_LABEL1,
834 KEY_LABEL_LEN,
835 CSSM_KEYUSE_ENCRYPT,
836 targs->keySizeInBits,
837 targs->useRefKey,
838 targs->password,
839 targs->salt,
840 targs->iterCount,
841 &iv1);
842 if(key1 == NULL) {
843 return testError(targs->quiet);
844 }
845 /* munge salt */
846 mungeDex = genRand(0, targs->salt->Length - 1);
847 mungeBits = randBit();
848 targs->salt->Data[mungeDex] ^= mungeBits;
849 key2 = cspDeriveKey(targs->cspHand,
850 targs->deriveAlg,
851 targs->keyAlg,
852 KEY_LABEL2,
853 KEY_LABEL_LEN,
854 CSSM_KEYUSE_ENCRYPT,
855 targs->keySizeInBits,
856 targs->useRefKey,
857 targs->password,
858 targs->salt, // the changed param
859 targs->iterCount,
860 &iv2);
861 if(key2 == NULL) {
862 return testError(targs->quiet);
863 }
864 if(testCommon(targs->cspHand,
865 "saltTest",
866 targs->encrAlg,
867 targs->encrMode,
868 targs->encrPad,
869 targs->effectiveKeySizeInBits,
870 targs->ptext,
871 key1,
872 ivp1,
873 key2,
874 ivp2,
875 targs->quiet)) {
876 return 1;
877 }
878 /* restore */
879 targs->salt->Data[mungeDex] ^= mungeBits;
880 appFreeCssmData(&iv1, CSSM_FALSE);
881 appFreeCssmData(&iv2, CSSM_FALSE);
882 cspFreeKey(targs->cspHand, key1);
883 cspFreeKey(targs->cspHand, key2);
884 CSSM_FREE(key1);
885 CSSM_FREE(key2);
886 return 0;
887 }
888
889 /* ensure initVector alters ctext. This isn't testing PBE per se, but
890 * it's a handy place to verify this function. */
891 static int initVectTest(testArgs *targs)
892 {
893 /*
894 generate key1;
895 encrypt ptext with key1 and initVector;
896 encrypt ptext with key1 and munged initVector;
897 compare 2 ctexts; expect failure;
898 */
899 CSSM_KEY_PTR key1;
900 CSSM_DATA iv1;
901 CSSM_DATA iv2;
902 uint32 mungeDex;
903 uint32 mungeBits;
904
905 if(targs->genInitVector) {
906 iv1.Data = NULL;
907 iv1.Length = 0;
908 }
909 else {
910 iv1 = staticIv;
911 }
912 key1 = cspDeriveKey(targs->cspHand,
913 targs->deriveAlg,
914 targs->keyAlg,
915 KEY_LABEL1,
916 KEY_LABEL_LEN,
917 CSSM_KEYUSE_ENCRYPT,
918 targs->keySizeInBits,
919 targs->useRefKey,
920 targs->password,
921 targs->salt,
922 targs->iterCount,
923 &iv1);
924 if(key1 == NULL) {
925 return testError(targs->quiet);
926 }
927
928 /* get munged copy of iv */
929 iv2.Data = (uint8 *)CSSM_MALLOC(iv1.Length);
930 iv2.Length = iv1.Length;
931 memmove(iv2.Data, iv1.Data, iv1.Length);
932 mungeDex = genRand(0, iv1.Length - 1);
933 mungeBits = randBit();
934 iv2.Data[mungeDex] ^= mungeBits;
935 if(testCommon(targs->cspHand,
936 "initVectTest",
937 targs->encrAlg,
938 targs->encrMode,
939 targs->encrPad,
940 targs->effectiveKeySizeInBits,
941 targs->ptext,
942 key1,
943 &iv1,
944 key1,
945 &iv2, // the changed param
946 targs->quiet)) {
947 return 1;
948 }
949 if(targs->genInitVector) {
950 appFreeCssmData(&iv1, CSSM_FALSE);
951 }
952 appFreeCssmData(&iv2, CSSM_FALSE);
953 cspFreeKey(targs->cspHand, key1);
954 CSSM_FREE(key1);
955 return 0;
956 }
957
958 #if 0
959 /* only one algorithm supported */
960 /* ensure deriveAlg alters key */
961 static int deriveAlgTest(testArgs *targs)
962 {
963 /*
964 generate key1(deriveAlg), key2(some other deriveAlg);
965 encrypt ptext with key1;
966 encrypt ptext with key2;
967 compare 2 ctexts; expect failure;
968 */
969 CSSM_KEY_PTR key1;
970 CSSM_KEY_PTR key2;
971 CSSM_DATA iv1;
972 CSSM_DATA iv2;
973 CSSM_DATA_PTR ivp1;
974 CSSM_DATA_PTR ivp2;
975 uint32 mungeAlg;
976
977 if(targs->useInitVector) {
978 if(targs->genInitVector) {
979 ivp1 = &iv1;
980 ivp2 = &iv2;
981 }
982 else {
983 staticIv.Length = targs->ivSize;
984 ivp1 = ivp2 = &staticIv;
985 }
986 }
987 else {
988 ivp1 = ivp2 = NULL;
989 }
990
991 /* these need to be init'd regardless */
992 iv1.Data = NULL;
993 iv1.Length = 0;
994 iv2.Data = NULL;
995 iv2.Length = 0;
996 key1 = cspDeriveKey(targs->cspHand,
997 targs->deriveAlg,
998 targs->keyAlg,
999 KEY_LABEL1,
1000 KEY_LABEL_LEN,
1001 CSSM_KEYUSE_ENCRYPT,
1002 targs->keySizeInBits,
1003 targs->useRefKey,
1004 targs->password,
1005 targs->salt,
1006 targs->iterCount,
1007 &iv1);
1008 if(key1 == NULL) {
1009 return testError(quiet);
1010 }
1011
1012 /* munge deriveAlg */
1013 switch(targs->deriveAlg) {
1014 case CSSM_ALGID_MD5_PBE:
1015 mungeAlg = CSSM_ALGID_MD2_PBE;
1016 break;
1017 case CSSM_ALGID_MD2_PBE:
1018 mungeAlg = CSSM_ALGID_SHA1_PBE;
1019 break;
1020 case CSSM_ALGID_SHA1_PBE:
1021 mungeAlg = CSSM_ALGID_SHA1_PBE_PKCS12;
1022 break;
1023 case CSSM_ALGID_SHA1_PBE_PKCS12:
1024 mungeAlg = CSSM_ALGID_MD5_PBE;
1025 break;
1026 default:
1027 printf("BRRRZZZT! Update deriveAlgTest()!\n");
1028 return testError(quiet);
1029 }
1030 key2 = cspDeriveKey(targs->cspHand,
1031 mungeAlg, // the changed param
1032 targs->keyAlg,
1033 KEY_LABEL2,
1034 KEY_LABEL_LEN,
1035 CSSM_KEYUSE_ENCRYPT,
1036 targs->keySizeInBits,
1037 targs->useRefKey,
1038 targs->password, // the changed param
1039 targs->salt,
1040 targs->iterCount,
1041 &iv2);
1042 if(key2 == NULL) {
1043 return testError(quiet);
1044 }
1045 if(testCommon(targs->cspHand,
1046 "deriveAlgTest",
1047 targs->encrAlg,
1048 targs->encrMode,
1049 targs->encrPad,
1050 targs->effectiveKeySizeInBits,
1051 targs->ptext,
1052 key1,
1053 ivp1,
1054 key2,
1055 ivp2,
1056 targs->quiet)) {
1057 return 1;
1058 }
1059 appFreeCssmData(&iv1, CSSM_FALSE);
1060 appFreeCssmData(&iv2, CSSM_FALSE);
1061 cspFreeKey(targs->cspHand, key1);
1062 cspFreeKey(targs->cspHand, key2);
1063 CSSM_FREE(key1);
1064 CSSM_FREE(key2);
1065 return 0;
1066 }
1067 #endif
1068
1069 int main(int argc, char **argv)
1070 {
1071 int arg;
1072 char *argp;
1073 unsigned loop;
1074 CSSM_DATA ptext;
1075 testArgs targs;
1076 CSSM_DATA pwd;
1077 CSSM_DATA salt;
1078 privAlg pbeAlg;
1079 privAlg encrAlg;
1080 privAlg lastEncrAlg;
1081 int rtn = 0;
1082 CSSM_BOOL fooBool;
1083 CSSM_BOOL refKeysOnly = CSSM_FALSE;
1084 int i;
1085
1086 /*
1087 * User-spec'd params
1088 */
1089 unsigned loops = LOOPS_DEF;
1090 CSSM_BOOL quiet = CSSM_FALSE;
1091 CSSM_BOOL doPause = CSSM_FALSE;
1092 CSSM_BOOL doExport = CSSM_FALSE;
1093 CSSM_BOOL repeatOnly = CSSM_FALSE;
1094 CSSM_BOOL bareCsp = CSSM_TRUE;
1095 CSSM_BOOL zeroLenPassword = CSSM_FALSE;
1096
1097 #if macintosh
1098 argc = ccommand(&argv);
1099 #endif
1100 for(arg=1; arg<argc; arg++) {
1101 argp = argv[arg];
1102 switch(argp[0]) {
1103 case 'l':
1104 loops = atoi(&argp[2]);
1105 break;
1106 case 'q':
1107 quiet = CSSM_TRUE;
1108 break;
1109 case 'D':
1110 bareCsp = CSSM_FALSE;
1111 #if CSPDL_ALL_KEYS_ARE_REF
1112 refKeysOnly = CSSM_TRUE;
1113 #endif
1114 break;
1115 case 'p':
1116 doPause = CSSM_TRUE;
1117 break;
1118 case 'e':
1119 doExport = CSSM_TRUE;
1120 break;
1121 case 'r':
1122 repeatOnly = CSSM_TRUE;
1123 break;
1124 case 'z':
1125 zeroLenPassword = CSSM_TRUE;
1126 break;
1127 case 'h':
1128 default:
1129 usage(argv);
1130 }
1131 }
1132
1133 /* statically allocate ptext, password and seed; data and length
1134 * change in test loop */
1135 pwd.Data = (uint8 *)CSSM_MALLOC(MAX_PASSWORD_SIZE);
1136 ptext.Data = (uint8 *)CSSM_MALLOC(MAX_PTEXT_SIZE);
1137 salt.Data = (uint8 *)CSSM_MALLOC(MAX_SALT_SIZE);
1138 printf("Starting pbeTest; args: ");
1139 for(i=1; i<argc; i++) {
1140 printf("%s ", argv[i]);
1141 }
1142 printf("\n");
1143 targs.cspHand = cspDlDbStartup(bareCsp, NULL);
1144 if(targs.cspHand == 0) {
1145 exit(1);
1146 }
1147 targs.ptext = &ptext;
1148 targs.password = &pwd;
1149 targs.salt = &salt;
1150 targs.quiet = quiet;
1151 if(doExport) {
1152 lastEncrAlg = ENCR_ALG_LAST_EXPORT;
1153 }
1154 else {
1155 lastEncrAlg = ENCR_ALG_LAST;
1156 }
1157 for(loop=1; ; loop++) {
1158 if(!quiet) {
1159 printf("...loop %d\n", loop);
1160 }
1161 /* change once per outer loop */
1162 simpleGenData(&ptext, MIN_PTEXT_SIZE, MAX_PTEXT_SIZE);
1163 if(zeroLenPassword) {
1164 pwd.Length = 0; // fixed
1165 }
1166 else {
1167 simpleGenData(&pwd, APPLE_PBE_MIN_PASSWORD, MAX_PASSWORD_SIZE);
1168 }
1169 simpleGenData(&salt, APPLE_PBE_MIN_SALT, MAX_SALT_SIZE);
1170 targs.iterCount = genRand(MIN_ITER_COUNT, MAX_ITER_COUNT);
1171 if(refKeysOnly) {
1172 targs.useRefKey = CSSM_TRUE;
1173 }
1174 else {
1175 targs.useRefKey = (loop & 1) ? CSSM_FALSE : CSSM_TRUE;
1176 }
1177
1178 for(encrAlg=ENCR_ALG_FIRST; encrAlg<=lastEncrAlg; encrAlg++) {
1179 /* Cook up encryption-related args */
1180 algInfo(encrAlg,
1181 &targs.keyAlg,
1182 &targs.encrAlg,
1183 &targs.encrMode,
1184 &targs.encrPad,
1185 &targs.useInitVector,
1186 &targs.ivSize,
1187 &fooBool, // genInitVector
1188 &targs.keyAlgStr);
1189 /* random key size */
1190 targs.effectiveKeySizeInBits = randKeySizeBits(targs.keyAlg, OT_Encrypt);
1191 targs.keySizeInBits = (targs.effectiveKeySizeInBits + 7) & ~7;
1192 if(targs.keySizeInBits == targs.effectiveKeySizeInBits) {
1193 /* same size, ignore effective */
1194 targs.effectiveKeySizeInBits = 0;
1195 }
1196 if(!quiet) {
1197 printf(" ...Encrypt alg %s keySizeInBits %u effectKeySize %u\n",
1198 targs.keyAlgStr, (unsigned)targs.keySizeInBits,
1199 (unsigned)targs.effectiveKeySizeInBits);
1200 }
1201 for(pbeAlg=PBE_ALG_FIRST; pbeAlg<=PBE_ALG_LAST; pbeAlg++) {
1202 /* Cook up pbe-related args */
1203 uint32 foo;
1204 algInfo(pbeAlg,
1205 &targs.deriveAlg,
1206 &foo, // encrAlg
1207 &foo, // mode
1208 &foo,
1209 &fooBool, // useInitVector
1210 &foo, // ivSize
1211 &targs.genInitVector,
1212 &targs.deriveAlgStr);
1213 if(!quiet) {
1214 printf(" ...PBE alg %s\n", targs.deriveAlgStr);
1215 }
1216 /* grind thru the tests */
1217 if(repeatTest(&targs)) {
1218 rtn = 1;
1219 goto testDone;
1220 }
1221 if(repeatOnly) {
1222 continue;
1223 }
1224 if(iterTest(&targs)) {
1225 rtn = 1;
1226 goto testDone;
1227 }
1228 #if 0
1229 // not supported yet
1230 if(deriveAlgTest(&targs)) {
1231 rtn = 1;
1232 goto testDone;
1233 }
1234 #endif
1235 if(!zeroLenPassword) {
1236 /* won't work with zero length password */
1237 if(passwordTest(&targs)) {
1238 rtn = 1;
1239 goto testDone;
1240 }
1241 }
1242 if(saltTest(&targs)) {
1243 rtn = 1;
1244 goto testDone;
1245 }
1246 if(targs.useInitVector) {
1247 if(initVectTest(&targs)) {
1248 rtn = 1;
1249 goto testDone;
1250 }
1251 }
1252 } /* for pbeAlg */
1253 } /* for encrAlg */
1254 if(doPause) {
1255 if(testError(quiet)) {
1256 break;
1257 }
1258 }
1259 if(loops && (loop == loops)) {
1260 break;
1261 }
1262 } /* for loop */
1263
1264 testDone:
1265 CSSM_ModuleDetach(targs.cspHand);
1266 if(!quiet && (rtn == 0)) {
1267 printf("%s test complete\n", argv[0]);
1268 }
1269 return rtn;
1270 }