]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/wrapTest/wrapTest.c
Security-57740.31.2.tar.gz
[apple/security.git] / SecurityTests / cspxutils / wrapTest / wrapTest.c
1 /* Copyright (c) 1998,2003-2005,2008 Apple Inc.
2 *
3 * wrapTest.c - wrap/unwrap exerciser.
4 *
5 * Revision History
6 * ----------------
7 * 4 May 2000 Doug Mitchell
8 * Ported to X/CDSA2.
9 * 6 Aug 1998 Doug Mitchell at Apple
10 * Created.
11 */
12
13 #include <string.h>
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <time.h>
17 #include <Security/cssm.h>
18 #include "cspwrap.h"
19 #include "common.h"
20 #include "cspdlTesting.h"
21
22 /*
23 * Currently the CSP can use wrapping keys flagged exclusively for wrapping
24 * (CSSM_KEYUSE_{WRAP,UNWRAP} for the actual wrap sinceƊthe wrp/unwrap op is
25 * done with an encrypt/decrypt op. The WrapKey op doesn't even see the
26 * wrapping key - it's in the context we pass it. Thus for now wrap/unwrap
27 * keys have to be marked with CSSM_KEYUSE_ANY.
28 */
29 #define WRAP_USAGE_ANY 0
30
31 /*
32 * When false, the CMS wrap algorithm can't deal with RSA encryption - we
33 * have to encrypt something twice with the same key. An impossibility with
34 * BSAFE-based RSA encryption because the output of the first encrypt is
35 * the size of the key modulus, and you can't encrypt something that big
36 * with that key.
37 * This is not a limitation with openssl-based RSA.
38 */
39 #define WRAP_WITH_RSA 1
40
41 /*
42 * When false, can't wrap with RC4 because the RC4 context is stateful
43 * but doesn't get reinit'd for the second CMS encrypt.
44 */
45 #define WRAP_WITH_RC4 1
46
47 /*
48 * Temporary hack to use CSSM_KEYBLOB_WRAPPED_FORMAT_{PKCS7,PKCS8}, which
49 * are no longer supported as of 7/28/00
50 */
51 #define PKCS7_FORMAT_ENABLE 1 // for wrapping symmetric keys
52 #define PKCS8_FORMAT_ENABLE 1 // for wrapping private keys
53
54
55 #define ENCR_LABEL "encrKey"
56 #define ENCR_LABEL_LEN (strlen(ENCR_LABEL))
57 #define WRAP_LABEL "wrapKey"
58 #define WRAP_LABEL_LEN (strlen(WRAP_LABEL))
59 #define LOOPS_DEF 10
60 #define MAX_PTEXT_SIZE 100
61 #define LOOP_PAUSE 100
62 #define MAX_DESC_DATA_SIZE 16
63
64 /*
65 * Enumerate algorithms our way to allow loop interations.
66 */
67 typedef unsigned PrivAlg;
68 enum {
69 ALG_DES = 1,
70 ALG_3DES,
71 ALG_RC2,
72 ALG_RC4,
73 ALG_RSA,
74 ALG_NULL,
75 ALG_FEEDEXP,
76 ALG_ASC,
77 ALG_AES
78 };
79
80 #define ALG_MIN ALG_DES
81 #define ALG_MAX_WRAP ALG_AES
82 #define ALG_MAX_ENCR ALG_AES
83
84 static void usage(char **argv)
85 {
86 printf("usage: %s [options]\n", argv[0]);
87 printf(" Options:\n");
88 printf(" w=wrapAlg (d=DES, 3=3DES, f=FEEDEXP, r=RSA, A=ASC, 4=RC4, "
89 "a=AES, n=null)\n");
90 printf(" e=encrAlg (d=DES, 3=3DES, f=FEEDEXP, r=RSA, A=ASC, 4=RC4, "
91 "a=AES)\n");
92 printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF);
93 printf(" r (ref keys only)\n");
94 printf(" p(ause every loop)\n");
95 printf(" D (CSP/DL; default = bare CSP)\n");
96 printf(" v(erbose)\n");
97 printf(" k (quick; small keys)\n");
98 printf(" h(elp)\n");
99 exit(1);
100 }
101
102 /* wrapped format to string */
103 static const char *formatString(CSSM_KEYBLOB_FORMAT format)
104 {
105 static char noform[100];
106
107 switch(format) {
108 case CSSM_KEYBLOB_WRAPPED_FORMAT_NONE:
109 return "NONE (default)";
110 case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7:
111 return "PKCS7";
112 case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8:
113 return "PKCS8";
114 case CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM:
115 return "APPLE_CUSTOM";
116 default:
117 sprintf(noform, "***UNKNOWN (%u)***", (unsigned)format);
118 return noform;
119 }
120 }
121
122 static int vfyWrapHeader(
123 const CSSM_KEYHEADER *srcHdr,
124 const CSSM_KEYHEADER *dstHdr,
125 CSSM_KEYBLOB_TYPE expectBlob,
126 const char *op,
127 CSSM_BOOL bareCsp,
128 int quiet)
129 {
130 if(dstHdr->BlobType != expectBlob) {
131 printf("***%s.BlobType error: expect %u got %u\n",
132 op, (unsigned)expectBlob, (unsigned)dstHdr->BlobType);
133 if(testError(quiet)) {
134 return 1;
135 }
136 }
137 if(srcHdr->KeyClass != dstHdr->KeyClass) {
138 printf("***%s.KeyClass error: expect %u got %u\n",
139 op, (unsigned)srcHdr->KeyClass, (unsigned)dstHdr->KeyClass);
140 if(testError(quiet)) {
141 return 1;
142 }
143 }
144 if(srcHdr->AlgorithmId != dstHdr->AlgorithmId) {
145 printf("***%s.AlgorithmId error: expect %u got %u\n",
146 op, (unsigned)srcHdr->AlgorithmId, (unsigned)dstHdr->AlgorithmId);
147 if(testError(quiet)) {
148 return 1;
149 }
150 }
151 if(srcHdr->KeyUsage != dstHdr->KeyUsage) {
152 printf("***%s.KeyUsage error: expect 0x%x got 0x%x\n",
153 op, (unsigned)srcHdr->KeyUsage, (unsigned)dstHdr->KeyUsage);
154 if(testError(quiet)) {
155 return 1;
156 }
157 }
158 if(bareCsp) {
159 /* GUIDs must match */
160 if(memcmp(&srcHdr->CspId, &dstHdr->CspId, sizeof(CSSM_GUID))) {
161 printf("***%s.CspId mismatch\n", op);
162 if(testError(quiet)) {
163 return 1;
164 }
165 }
166 }
167 else {
168 /* CSPDL - GUIDs do NOT match - ref keys are in the CSPDL's domain;
169 * wrapped keys are in the bare CSP's domain. */
170 if(!memcmp(&srcHdr->CspId, &dstHdr->CspId, sizeof(CSSM_GUID))) {
171 printf("***Unexpected %s.CspId compare\n", op);
172 if(testError(quiet)) {
173 return 1;
174 }
175 }
176 }
177 return 0;
178 }
179
180 #define UNWRAPPED_LABEL "unwrapped thing"
181 #define SHOW_WRAP_FORMAT 0
182
183 /* not all algs need this */
184 CSSM_DATA initVector = {16, (uint8 *)"SomeReallyStrangeInitVect"};
185
186 static int doTest(CSSM_CSP_HANDLE cspHand,
187 CSSM_KEY_PTR encrKey,
188 CSSM_BOOL wrapEncrKey, // wrap encrKey before using
189 CSSM_KEY_PTR decrKey, // we wrap this one
190 CSSM_KEY_PTR wrappingKey, // ...using this key
191 CSSM_KEY_PTR unwrappingKey,
192 CSSM_ALGORITHMS wrapAlg,
193 CSSM_ENCRYPT_MODE wrapMode,
194 CSSM_KEYBLOB_FORMAT wrapFormat, // NONE, PKCS7, PKCS8, APPLE_CUSTOM
195 CSSM_KEYBLOB_FORMAT expectFormat, // PKCS7, PKCS8, APPLE_CUSTOM
196 CSSM_PADDING wrapPad,
197 uint32 wrapIvSize,
198 CSSM_ALGORITHMS encrAlg,
199 CSSM_ENCRYPT_MODE encrMode,
200 CSSM_PADDING encrPad,
201 uint32 encrIvSize,
202 uint32 effectiveKeySizeInBits, // for encr/decr - 0 means none specified
203 CSSM_DATA_PTR ptext,
204 CSSM_DATA_PTR descData,
205 CSSM_BOOL quiet,
206 CSSM_BOOL bareCsp)
207 {
208 CSSM_DATA ctext;
209 CSSM_DATA rptext;
210 CSSM_KEY wrappedDecrKey;
211 CSSM_KEY unwrappedDecrKey;
212 CSSM_KEY wrappedEncrKey;
213 CSSM_RETURN crtn;
214 CSSM_KEY_PTR actualEncrKey;
215 uint32 maxPtextSize = MAX_PTEXT_SIZE;
216 CSSM_DATA outDescData1 = {0, NULL}; // for encr key
217 CSSM_DATA outDescData2 = {0, NULL}; // for decr key, must match descData
218 CSSM_DATA nullInitVect = {0, NULL}; // for custom unwrap
219 CSSM_DATA_PTR wrapIvp;
220 CSSM_DATA_PTR encrIvp;
221
222 /* Hack to deal with RSA's max encrypt size */
223 #if 0
224 /* no more */
225 if(encrAlg == CSSM_ALGID_RSA) {
226 uint32 keySizeBytes = encrKey->KeyHeader.LogicalKeySizeInBits / 8;
227 maxPtextSize = keySizeBytes - 11;
228 if(maxPtextSize > MAX_PTEXT_SIZE) {
229 maxPtextSize = MAX_PTEXT_SIZE;
230 }
231 }
232 else {
233 maxPtextSize = MAX_PTEXT_SIZE;
234 }
235 #endif
236 simpleGenData(ptext, 1, maxPtextSize);
237
238 /*
239 * Optionaly wrap/unwrap encrKey. If encrKey is a ref key, do a
240 * NULL wrap. If encrKey is a raw key, do a NULL unwrap.
241 */
242 if(wrapEncrKey) {
243 CSSM_KEYBLOB_TYPE expectBlob;
244
245 if(encrKey->KeyHeader.BlobType == CSSM_KEYBLOB_REFERENCE) {
246 crtn = cspWrapKey(cspHand,
247 encrKey,
248 NULL, // wrappingKey
249 CSSM_ALGID_NONE,
250 CSSM_ALGMODE_NONE,
251 wrapFormat,
252 CSSM_PADDING_NONE,
253 NULL, // iv
254 descData,
255 &wrappedEncrKey);
256 expectBlob = CSSM_KEYBLOB_RAW;
257 }
258 else {
259 crtn = cspUnwrapKey(cspHand,
260 encrKey,
261 NULL, // unwrappingKey
262 CSSM_ALGID_NONE,
263 CSSM_ALGMODE_NONE,
264 CSSM_PADDING_NONE,
265 NULL, // iv
266 &wrappedEncrKey,
267 &outDescData1,
268 WRAP_LABEL,
269 WRAP_LABEL_LEN);
270 expectBlob = CSSM_KEYBLOB_REFERENCE;
271 }
272 if(crtn) {
273 return testError(quiet);
274 }
275 if(vfyWrapHeader(&encrKey->KeyHeader,
276 &wrappedEncrKey.KeyHeader,
277 expectBlob,
278 "wrappedEncrKey",
279 bareCsp,
280 quiet)) {
281 return 1;
282 }
283 actualEncrKey = &wrappedEncrKey;
284 }
285 else {
286 actualEncrKey = encrKey;
287 }
288 /* encrypt using actualEncrKey ==> ctext */
289 ctext.Data = NULL;
290 ctext.Length = 0;
291 if(encrIvSize) {
292 initVector.Length = encrIvSize;
293 encrIvp = &initVector;
294 }
295 else {
296 encrIvp = NULL;
297 }
298 crtn = cspEncrypt(cspHand,
299 encrAlg,
300 encrMode,
301 encrPad,
302 actualEncrKey,
303 NULL, // no 2nd key
304 effectiveKeySizeInBits,
305 0, // rounds
306 encrIvp,
307 ptext,
308 &ctext,
309 CSSM_TRUE); // mallocCtext
310 if(crtn) {
311 return testError(quiet);
312 }
313 /* wrap decrKey using wrappingKey ==> wrappedDecrKey */
314 /* Note that APPLE_CUSTOM wrap alg REQUIRES an 8-byte IV */
315 if(expectFormat == CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM) {
316 initVector.Length = 8;
317 }
318 else {
319 initVector.Length = wrapIvSize;
320 }
321 crtn = cspWrapKey(cspHand,
322 decrKey,
323 wrappingKey,
324 wrapAlg,
325 wrapMode,
326 wrapFormat,
327 wrapPad,
328 &initVector,
329 descData,
330 &wrappedDecrKey);
331 if(crtn) {
332 return testError(quiet);
333 }
334 if(wrapAlg != CSSM_ALGID_NONE) {
335 if(wrappedDecrKey.KeyHeader.Format != expectFormat) {
336 printf("***Wrap format mismatch expect %s got %s\n",
337 formatString(wrappedDecrKey.KeyHeader.Format),
338 formatString(expectFormat));
339 if(testError(quiet)) {
340 return 1;
341 }
342 }
343 }
344
345 if(vfyWrapHeader(&decrKey->KeyHeader,
346 &wrappedDecrKey.KeyHeader,
347 (wrapAlg == CSSM_ALGID_NONE) ? CSSM_KEYBLOB_RAW : CSSM_KEYBLOB_WRAPPED,
348 "wrappedDecrKey",
349 bareCsp,
350 quiet)) {
351 return 1;
352 }
353
354 if(wrappedDecrKey.KeyHeader.Format == CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM) {
355 /* special case - no IV needed - test it */
356 wrapIvp = &nullInitVect;
357 }
358 else {
359 wrapIvp = &initVector;
360 initVector.Length = wrapIvSize;
361 }
362
363 /* unwrap wrappedDecrKey using unwrappingKey ==> unwrappedDecrKey; */
364 crtn = cspUnwrapKey(cspHand,
365 &wrappedDecrKey,
366 unwrappingKey,
367 wrapAlg,
368 wrapMode,
369 wrapPad,
370 wrapIvp,
371 &unwrappedDecrKey,
372 &outDescData2,
373 "unwrapped thing",
374 15);
375 if(crtn) {
376 return testError(quiet);
377 }
378
379 if(vfyWrapHeader(&wrappedDecrKey.KeyHeader,
380 &unwrappedDecrKey.KeyHeader,
381 CSSM_KEYBLOB_REFERENCE,
382 "unwrappedDecrKey",
383 bareCsp,
384 quiet)) {
385 return 1;
386 }
387
388 /* compare descData to outDescData2 */
389 if(descData) {
390 if(descData->Length != outDescData2.Length) {
391 printf("descData length mismatch\n");
392 if(testError(quiet)) {
393 return 1;
394 }
395 }
396 if(memcmp(descData->Data, outDescData2.Data, outDescData2.Length)) {
397 printf("***descDatadata miscompare\n");
398 if(testError(quiet)) {
399 return 1;
400 }
401 }
402 }
403
404 /* decrypt ctext with unwrappedDecrKey ==> rptext; */
405 rptext.Data = NULL;
406 rptext.Length = 0;
407 if(encrIvSize) {
408 initVector.Length = encrIvSize;
409 }
410 crtn = cspDecrypt(cspHand,
411 encrAlg,
412 encrMode,
413 encrPad,
414 &unwrappedDecrKey,
415 NULL, // no 2nd key
416 effectiveKeySizeInBits,
417 0, // rounds
418 &initVector,
419 &ctext,
420 &rptext,
421 CSSM_TRUE);
422 if(crtn) {
423 return testError(quiet);
424 }
425 /* compare ptext vs. rptext; */
426 if(ptext->Length != rptext.Length) {
427 printf("ptext length mismatch\n");
428 return testError(quiet);
429 }
430 if(memcmp(ptext->Data, rptext.Data, ptext->Length)) {
431 printf("***data miscompare\n");
432 return testError(quiet);
433 }
434 /* free resources */
435 cspFreeKey(cspHand, &wrappedDecrKey);
436 cspFreeKey(cspHand, &unwrappedDecrKey);
437 if(wrapEncrKey) {
438 cspFreeKey(cspHand, actualEncrKey);
439 }
440 CSSM_FREE(ctext.Data);
441 CSSM_FREE(rptext.Data);
442 if(outDescData2.Data != NULL) {
443 CSSM_FREE(outDescData2.Data);
444 }
445 if(outDescData1.Data != NULL) {
446 CSSM_FREE(outDescData1.Data);
447 }
448 return 0;
449 }
450
451 /*
452 * values associated with a private algorithm (e.g., ALG_DES).
453 */
454 typedef enum {
455 WT_Symmetric,
456 WT_Asymmetric,
457 WT_Null
458 } wrapType;
459
460 typedef struct {
461 uint32 keyGenAlg;
462 wrapType wtype;
463 CSSM_ALGORITHMS encrAlg;
464 CSSM_ENCRYPT_MODE encrMode;
465 CSSM_PADDING encrPad;
466 uint32 ivSize; // in bytes; 0 means no IV
467 const char *algName;
468 } AlgInfo;
469
470 /*
471 * Convert our private alg to CDSA keygen alg, encr alg, encr mode, pad
472 */
473 static void getAlgInfo(PrivAlg privAlg, // e.g., ALG_DES
474 AlgInfo *algInfo)
475 {
476 switch(privAlg) {
477 case ALG_DES:
478 algInfo->keyGenAlg = CSSM_ALGID_DES;
479 algInfo->wtype = WT_Symmetric;
480 algInfo->encrAlg = CSSM_ALGID_DES;
481 algInfo->encrMode = CSSM_ALGMODE_CBCPadIV8;
482 algInfo->encrPad = CSSM_PADDING_PKCS5;
483 algInfo->ivSize = 8;
484 algInfo->algName = "DES";
485 break;
486 case ALG_3DES:
487 algInfo->keyGenAlg = CSSM_ALGID_3DES_3KEY;
488 algInfo->wtype = WT_Symmetric;
489 algInfo->encrAlg = CSSM_ALGID_3DES_3KEY_EDE;
490 algInfo->encrMode = CSSM_ALGMODE_CBCPadIV8;
491 algInfo->encrPad = CSSM_PADDING_PKCS5;
492 algInfo->ivSize = 8;
493 algInfo->algName = "3DES";
494 break;
495 case ALG_FEEDEXP:
496 algInfo->keyGenAlg = CSSM_ALGID_FEE;
497 algInfo->wtype = WT_Asymmetric;
498 algInfo->encrAlg = CSSM_ALGID_FEEDEXP;
499 algInfo->encrMode = CSSM_ALGMODE_NONE;
500 algInfo->encrPad = CSSM_PADDING_NONE;
501 algInfo->ivSize = 0;
502 algInfo->algName = "FEEDEXP";
503 break;
504 case ALG_RSA:
505 algInfo->keyGenAlg = CSSM_ALGID_RSA;
506 algInfo->wtype = WT_Asymmetric;
507 algInfo->encrAlg = CSSM_ALGID_RSA;
508 algInfo->encrMode = CSSM_ALGMODE_NONE;
509 algInfo->encrPad = CSSM_PADDING_PKCS1;
510 algInfo->ivSize = 0;
511 algInfo->algName = "RSA";
512 break;
513 case ALG_ASC:
514 algInfo->keyGenAlg = CSSM_ALGID_ASC;
515 algInfo->wtype = WT_Symmetric;
516 algInfo->encrAlg = CSSM_ALGID_ASC;
517 algInfo->encrMode = CSSM_ALGMODE_NONE;
518 algInfo->encrPad = CSSM_PADDING_NONE;
519 algInfo->ivSize = 0;
520 algInfo->algName = "ASC";
521 break;
522 case ALG_RC2:
523 algInfo->keyGenAlg = CSSM_ALGID_RC2;
524 algInfo->wtype = WT_Symmetric;
525 algInfo->encrAlg = CSSM_ALGID_RC2;
526 algInfo->encrMode = CSSM_ALGMODE_CBCPadIV8;
527 algInfo->encrPad = CSSM_PADDING_PKCS5;
528 algInfo->ivSize = 8;
529 algInfo->algName = "RC2";
530 break;
531 case ALG_RC4:
532 algInfo->keyGenAlg = CSSM_ALGID_RC4;
533 algInfo->wtype = WT_Symmetric;
534 algInfo->encrAlg = CSSM_ALGID_RC4;
535 algInfo->encrMode = CSSM_ALGMODE_CBCPadIV8;
536 algInfo->encrPad = CSSM_PADDING_PKCS5;
537 algInfo->ivSize = 0;
538 algInfo->algName = "RC4";
539 break;
540 case ALG_NULL:
541 algInfo->keyGenAlg = CSSM_ALGID_NONE;
542 algInfo->wtype = WT_Null;
543 algInfo->encrAlg = CSSM_ALGID_NONE;
544 algInfo->encrMode = CSSM_ALGMODE_NONE;
545 algInfo->encrPad = CSSM_PADDING_NONE;
546 algInfo->ivSize = 0;
547 algInfo->algName = "Null";
548 break;
549 case ALG_AES:
550 algInfo->keyGenAlg = CSSM_ALGID_AES;
551 algInfo->wtype = WT_Symmetric;
552 algInfo->encrAlg = CSSM_ALGID_AES;
553 algInfo->encrMode = CSSM_ALGMODE_CBCPadIV8;
554 algInfo->encrPad = CSSM_PADDING_PKCS7;
555 algInfo->ivSize = 16;
556 algInfo->algName = "AES";
557 break;
558 default:
559 printf("Bogus privAlg\n");
560 exit(1);
561 }
562 return;
563 }
564
565 /* argv letter to private alg */
566 static PrivAlg letterToAlg(char **argv, char letter)
567 {
568 switch(letter) {
569 case 'd': return ALG_DES;
570 case '3': return ALG_3DES;
571 case 'f': return ALG_FEEDEXP;
572 case 'r': return ALG_RSA;
573 case 'A': return ALG_ASC;
574 case '4': return ALG_RC4;
575 case 'a': return ALG_AES;
576 default:
577 usage(argv);
578 return 0;
579 }
580 }
581
582 /*
583 * Null wrapping of symmetric keys now allowed
584 */
585 #define SYMM_NULL_WRAP_ENABLE 1
586
587 /* indices into algInfo[] */
588 #define AI_WRAP 0
589 #define AI_ENCR 1
590
591 int main(int argc, char **argv)
592 {
593 int arg;
594 char *argp;
595 unsigned loop;
596 CSSM_CSP_HANDLE cspHand;
597 CSSM_RETURN crtn;
598 CSSM_DATA ptext;
599 uint32 encrKeySizeBits; // well aligned
600 uint32 wrapKeySizeBits;
601 uint32 effectiveKeySizeInBits; // for encr, may be odd
602 int rtn = 0;
603 uint32 maxRsaKeySize = 1024;
604 uint32 maxFeeKeySize = 192;
605 CSSM_KEYBLOB_FORMAT wrapFormat; // NONE, PKCS7, PKCS8, APPLE_CUSTOM
606 CSSM_KEYBLOB_FORMAT expectFormat; // PKCS7, PKCS8, APPLE_CUSTOM
607 CSSM_DATA descData = {0, NULL};
608 CSSM_DATA_PTR descDataP;
609
610 /*
611 * key pointers passed to doTest() - for symmetric algs, the pairs
612 * might point to the same key
613 */
614 CSSM_KEY_PTR encrKeyPtr;
615 CSSM_KEY_PTR decrKeyPtr;
616 CSSM_KEY_PTR wrapKeyPtr;
617 CSSM_KEY_PTR unwrapKeyPtr;
618
619 /* persistent asymmetric keys - symm keys are dynamically allocated */
620 CSSM_KEY pubEncrKey;
621 CSSM_KEY privEncrKey;
622 CSSM_KEY pubWrapKey;
623 CSSM_KEY privWrapKey;
624
625 /* we iterate these values thru all possible algs */
626 PrivAlg privEncrAlg; // ALG_xxx
627 PrivAlg privWrapAlg;
628
629 /* two AlgInfo which contain everything we need to know per alg */
630 AlgInfo algInfo[2];
631 AlgInfo *encrInfo;
632 AlgInfo *wrapInfo;
633 CSSM_BOOL wrapEncrKey = CSSM_FALSE; // varies loop-to-loop
634 CSSM_BOOL encrKeyIsRef = CSSM_TRUE; // ditto
635
636 CSSM_BOOL genSeed; // for FEE key gen
637 int i;
638
639 /* user-specified vars */
640 unsigned loops = LOOPS_DEF;
641 CSSM_BOOL pause = CSSM_FALSE;
642 CSSM_BOOL verbose = CSSM_FALSE;
643 PrivAlg minWrapAlg = ALG_MIN;
644 PrivAlg maxWrapAlg = ALG_MAX_WRAP;
645 PrivAlg minEncrAlg = ALG_MIN;
646 PrivAlg maxEncrAlg = ALG_MAX_ENCR;
647 CSSM_BOOL quick = CSSM_FALSE;
648 CSSM_BOOL quiet = CSSM_FALSE;
649 CSSM_BOOL bareCsp = CSSM_TRUE;
650 CSSM_BOOL refKeysOnly = CSSM_FALSE;
651
652 for(arg=1; arg<argc; arg++) {
653 argp = argv[arg];
654 switch(argp[0]) {
655 case 'w':
656 if(argp[2] == 'n') {
657 minWrapAlg = maxWrapAlg = ALG_NULL;
658 }
659 else {
660 minWrapAlg = maxWrapAlg = letterToAlg(argv, argp[2]);
661 }
662 break;
663 case 'e':
664 minEncrAlg = maxEncrAlg = letterToAlg(argv, argp[2]);
665 break;
666 case 'l':
667 loops = atoi(&argp[2]);
668 break;
669 case 'p':
670 pause = CSSM_TRUE;
671 break;
672 case 'v':
673 verbose = CSSM_TRUE;
674 break;
675 case 'D':
676 bareCsp = CSSM_FALSE;
677 #if CSPDL_ALL_KEYS_ARE_REF
678 refKeysOnly = CSSM_TRUE;
679 #endif
680 break;
681 case 'r':
682 refKeysOnly = CSSM_TRUE;
683 break;
684 case 'q':
685 quiet = CSSM_TRUE;
686 break;
687 case 'k':
688 quick = CSSM_TRUE;
689 maxRsaKeySize = 512;
690 maxFeeKeySize = 127;
691 break;
692 default:
693 usage(argv);
694 }
695 }
696 cspHand = cspDlDbStartup(bareCsp, NULL);
697 if(cspHand == 0) {
698 exit(1);
699 }
700 wrapInfo = &algInfo[AI_WRAP];
701 encrInfo = &algInfo[AI_ENCR];
702
703 /* cook up ptext, descData */
704 ptext.Data = (uint8 *)CSSM_MALLOC(MAX_PTEXT_SIZE);
705 descData.Data = (uint8 *)CSSM_MALLOC(MAX_DESC_DATA_SIZE);
706
707 printf("Starting wrapTest; args: ");
708 for(i=1; i<argc; i++) {
709 printf("%s ", argv[i]);
710 }
711 printf("\n");
712
713 for(loop=0; loop<loops; loop++) {
714 if(!quiet) {
715 printf("...loop %d\n", loop);
716 }
717 if(pause) {
718 fpurge(stdin);
719 printf("Hit CR to proceed: ");
720 getchar();
721 }
722
723 /* iterate thru all encryption algs */
724 for(privEncrAlg=minEncrAlg; privEncrAlg<=maxEncrAlg; privEncrAlg++) {
725 /* handle disabled algs */
726 switch(privEncrAlg) {
727 case ALG_NULL: /* just skip this one, it's just for wrap */
728 continue;
729 default:
730 break;
731 }
732
733 /* generate key(s) to be wrapped */
734 getAlgInfo(privEncrAlg, encrInfo);
735 effectiveKeySizeInBits = randKeySizeBits(encrInfo->keyGenAlg, OT_Encrypt);
736 if(!refKeysOnly) {
737 encrKeyIsRef = (loop & 2) ? CSSM_TRUE : CSSM_FALSE;
738 }
739
740 switch(encrInfo->wtype) {
741 case WT_Symmetric:
742 /* round up to even byte */
743 encrKeySizeBits = (effectiveKeySizeInBits + 7) & ~7;
744 if(encrKeySizeBits == effectiveKeySizeInBits) {
745 effectiveKeySizeInBits = 0;
746 }
747 encrKeyPtr = decrKeyPtr = cspGenSymKey(cspHand,
748 encrInfo->keyGenAlg,
749 ENCR_LABEL,
750 ENCR_LABEL_LEN,
751 CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT,
752 encrKeySizeBits,
753 encrKeyIsRef);
754 if(encrKeyPtr == NULL) {
755 rtn = 1;
756 goto testDone;
757 }
758 #if SYMM_NULL_WRAP_ENABLE
759 /* wrapEncrKey every other loop */
760 if(!refKeysOnly) {
761 wrapEncrKey = (loop & 1) ? CSSM_TRUE : CSSM_FALSE;
762 }
763 #else
764 wrapEncrKey = CSSM_FALSE;
765 #endif /* SYMM_NULL_WRAP_ENABLE */
766 break;
767 case WT_Asymmetric:
768 /* handle alg-specific cases */
769 genSeed = CSSM_FALSE;
770 switch(privEncrAlg) {
771 case ALG_RSA:
772 if(effectiveKeySizeInBits > maxRsaKeySize) {
773 effectiveKeySizeInBits = maxRsaKeySize;
774 }
775 break;
776 case ALG_FEEDEXP:
777 if(effectiveKeySizeInBits > maxFeeKeySize) {
778 effectiveKeySizeInBits = maxFeeKeySize;
779 }
780 if(loop & 4) {
781 genSeed = CSSM_TRUE;
782 }
783 break;
784 default:
785 break;
786 }
787 encrKeySizeBits = effectiveKeySizeInBits;
788 effectiveKeySizeInBits = 0; // i.e., not specified
789 crtn = cspGenKeyPair(cspHand,
790 encrInfo->keyGenAlg,
791 ENCR_LABEL,
792 ENCR_LABEL_LEN,
793 encrKeySizeBits,
794 &pubEncrKey,
795 encrKeyIsRef, // pubIsRef
796 CSSM_KEYUSE_ENCRYPT,
797 CSSM_KEYBLOB_RAW_FORMAT_NONE,
798 &privEncrKey,
799 CSSM_TRUE, // privIsRef
800 CSSM_KEYUSE_DECRYPT,
801 CSSM_KEYBLOB_RAW_FORMAT_NONE,
802 genSeed);
803 if(crtn) {
804 rtn = testError(quiet);
805 goto testDone;
806 }
807 encrKeyPtr = &pubEncrKey;
808 decrKeyPtr = &privEncrKey;
809 /* wrapEncrKey every other loop */
810 if(!refKeysOnly) {
811 wrapEncrKey = (loop & 1) ? CSSM_TRUE : CSSM_FALSE;
812 }
813 break;
814 case WT_Null:
815 printf("***BRRZAP: can't do null encrypt\n");
816 goto testDone;
817 }
818 if(verbose) {
819 printf(" ...encrAlg %s wrapEncrKey %d encrKeyIsRef %d size %u "
820 "bits effectSize %u\n",
821 encrInfo->algName, (int)wrapEncrKey, (int)encrKeyIsRef,
822 (unsigned)encrKeySizeBits, (unsigned)effectiveKeySizeInBits);
823 }
824 /* iterate thru all wrap algs */
825 for(privWrapAlg=minWrapAlg; privWrapAlg<=maxWrapAlg; privWrapAlg++) {
826 /* handle disabled algs */
827 if((privWrapAlg == ALG_AES) && (privEncrAlg == ALG_FEEDEXP)) {
828 /*
829 * Can't do it. FEED can't do PKCS8 because it doesn't
830 * support PKCS8 private key format, and AES can't
831 * do APPLE_CUSTOM because AES needs a 16-byte IV.
832 */
833 continue;
834 }
835 /* any other restrictions/ */
836
837 /* generate wrapping key(s) */
838 getAlgInfo(privWrapAlg, wrapInfo);
839 switch(wrapInfo->wtype) {
840 case WT_Symmetric:
841 /* note we can't do odd-size wrapping keys */
842 wrapKeySizeBits = randKeySizeBits(wrapInfo->keyGenAlg,
843 OT_KeyExch);
844 wrapKeySizeBits &= ~7;
845 wrapKeyPtr = unwrapKeyPtr = cspGenSymKey(cspHand,
846 wrapInfo->keyGenAlg,
847 WRAP_LABEL,
848 WRAP_LABEL_LEN,
849 WRAP_USAGE_ANY ? CSSM_KEYUSE_ANY :
850 CSSM_KEYUSE_WRAP | CSSM_KEYUSE_UNWRAP,
851 wrapKeySizeBits,
852 CSSM_TRUE);
853 if(wrapKeyPtr == NULL) {
854 rtn = 1;
855 goto testDone;
856 }
857 break;
858 case WT_Asymmetric:
859 wrapKeySizeBits = randKeySizeBits(wrapInfo->keyGenAlg,
860 OT_KeyExch);
861 genSeed = CSSM_FALSE;
862 switch(privWrapAlg) {
863 case ALG_RSA:
864 if(wrapKeySizeBits > maxRsaKeySize) {
865 wrapKeySizeBits = maxRsaKeySize;
866 }
867 break;
868 case ALG_FEEDEXP:
869 if(wrapKeySizeBits > maxFeeKeySize) {
870 wrapKeySizeBits = maxFeeKeySize;
871 }
872 if(loop & 2) {
873 genSeed = CSSM_TRUE;
874 }
875 break;
876 default:
877 break;
878 }
879 crtn = cspGenKeyPair(cspHand,
880 wrapInfo->keyGenAlg,
881 WRAP_LABEL,
882 WRAP_LABEL_LEN,
883 wrapKeySizeBits,
884 &pubWrapKey,
885 CSSM_TRUE, // pubIsRef
886 WRAP_USAGE_ANY ? CSSM_KEYUSE_ANY : CSSM_KEYUSE_WRAP,
887 CSSM_KEYBLOB_RAW_FORMAT_NONE,
888 &privWrapKey,
889 CSSM_TRUE, // privIsRef
890 WRAP_USAGE_ANY ? CSSM_KEYUSE_ANY : CSSM_KEYUSE_UNWRAP,
891 CSSM_KEYBLOB_RAW_FORMAT_NONE,
892 genSeed);
893 if(crtn) {
894 rtn = testError(quiet);
895 goto testDone;
896 }
897 wrapKeyPtr = &pubWrapKey;
898 unwrapKeyPtr = &privWrapKey;
899 break;
900 case WT_Null:
901 #if !SYMM_NULL_WRAP_ENABLE
902 if(encrInfo->wtype == WT_Symmetric) {
903 /* can't do null wrap of symmetric key */
904 continue;
905 }
906 #endif
907 wrapKeySizeBits = 0;
908 wrapKeyPtr = NULL;
909 unwrapKeyPtr = NULL;
910 break;
911 }
912
913 /* special case for 3DES/3DES */
914 #if 0
915 if((wrapKeyPtr != NULL) &&
916 (wrapKeyPtr->KeyHeader.AlgorithmId == CSSM_ALGID_3DES_3KEY) &&
917 (decrKeyPtr->KeyHeader.AlgorithmId == CSSM_ALGID_3DES_3KEY)) {
918 isAppleCustom = CSSM_TRUE;
919 }
920 else {
921 isAppleCustom = CSSM_FALSE;
922 }
923 #endif
924
925 /* cook up a wrapFormat - every other loop use default, others
926 * specify a reasonable one */
927 if(wrapInfo->wtype == WT_Null) {
928 wrapFormat = expectFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_NONE;
929 }
930 else if((loop & 1)) {
931 /*
932 * FORMAT_NONE - default - figure out expected format;
933 * this has to track CSP behavior
934 */
935 wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_NONE;
936 switch(encrInfo->wtype) {
937 case WT_Symmetric:
938 expectFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7;
939 break;
940 case WT_Asymmetric:
941 if(privEncrAlg == ALG_FEEDEXP) {
942 expectFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM;
943 }
944 else {
945 expectFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8;
946 }
947 break;
948 default:
949 /* NULL encr not done */
950 printf("**GAK! Internal error\n");
951 }
952 }
953 else {
954 /* pick a good explicit one - this encapsulates the
955 * range of legal wrap formats per wrap/encrypt alg */
956 int die = loop & 2;
957 switch(encrInfo->wtype) {
958 case WT_Symmetric:
959 if(privWrapAlg == ALG_AES) {
960 /* can't do APPLE_CUSTOM - 16 byte IV */
961 wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7;
962 }
963 else if(die) {
964 wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7;
965 }
966 else {
967 wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM;
968 }
969 break;
970 case WT_Asymmetric:
971 /* Can't wrap FEE key with AES no way, no how -
972 * this is detected at the top of the privWrapAlg
973 * loop
974 */
975 if(privEncrAlg == ALG_FEEDEXP) {
976 /* FEE doesn't do PKCS8 private key format */
977 wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM;
978 }
979 else if(die) {
980 wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8;
981 }
982 else if(privWrapAlg == ALG_AES) {
983 /* AES can't do APPLE_CUSTOM - 16 byte IV */
984 wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8;
985 }
986 else {
987 wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM;
988 }
989 break;
990 default:
991 /* NULL encr not done */
992 printf("***GAK! Internal error\n");
993 exit(1);
994 }
995 expectFormat = wrapFormat;
996 }
997
998 /*
999 * If wrapping with apple custom - either by default or
1000 * explicitly - generate some descriptive data.
1001 */
1002 if(expectFormat == CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM) {
1003 simpleGenData(&descData, 1, MAX_DESC_DATA_SIZE);
1004 descDataP = &descData;
1005 }
1006 else {
1007 descDataP = NULL;
1008 }
1009
1010 if(verbose) {
1011 printf(" ...wrapAlg = %s size %u bits format %s expect %s\n",
1012 wrapInfo->algName, (unsigned)wrapKeySizeBits, formatString(wrapFormat),
1013 formatString(expectFormat));
1014 }
1015 /* OK, here we go! */
1016 if(doTest(cspHand,
1017 encrKeyPtr,
1018 wrapEncrKey,
1019 decrKeyPtr,
1020 wrapKeyPtr,
1021 unwrapKeyPtr,
1022 wrapInfo->encrAlg,
1023 wrapInfo->encrMode,
1024 wrapFormat,
1025 expectFormat,
1026 wrapInfo->encrPad,
1027 wrapInfo->ivSize,
1028 encrInfo->encrAlg,
1029 encrInfo->encrMode,
1030 encrInfo->encrPad,
1031 encrInfo->ivSize,
1032 effectiveKeySizeInBits,
1033 &ptext,
1034 descDataP,
1035 quiet,
1036 bareCsp)) {
1037 rtn = 1;
1038 goto testDone;
1039 }
1040 /* end of wrap alg loop - free/delete wrap key(s) */
1041 switch(wrapInfo->wtype) {
1042 case WT_Symmetric:
1043 cspFreeKey(cspHand, wrapKeyPtr);
1044 /* mallocd by cspGenSymKey */
1045 CSSM_FREE(wrapKeyPtr);
1046 break;
1047 case WT_Asymmetric:
1048 cspFreeKey(cspHand, wrapKeyPtr);
1049 cspFreeKey(cspHand, unwrapKeyPtr);
1050 break;
1051 default:
1052 break;
1053 }
1054 } /* for wrapAlg */
1055 /* end of encr alg loop - free encr key(s) */
1056 cspFreeKey(cspHand, encrKeyPtr);
1057 if(encrInfo->wtype == WT_Symmetric) {
1058 /* mallocd by cspGenSymKey */
1059 CSSM_FREE(decrKeyPtr);
1060 }
1061 else {
1062 cspFreeKey(cspHand, decrKeyPtr);
1063 }
1064 }
1065 }
1066 testDone:
1067 cspShutdown(cspHand, bareCsp);
1068 if(pause) {
1069 fpurge(stdin);
1070 printf("ModuleDetach/Unload complete; hit CR to exit: ");
1071 getchar();
1072 }
1073 if((rtn == 0) && !quiet) {
1074 printf("%s test complete\n", argv[0]);
1075 }
1076 return rtn;
1077 }