]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/asymTest/asymTest.c
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / cspxutils / asymTest / asymTest.c
1 /* Copyright (c) 1998,2003-2006,2008 Apple Inc.
2 *
3 * asymTest.c - test CSP asymmetric encrypt/decrypt.
4 *
5 * Revision History
6 * ----------------
7 * 10 May 2000 Doug Mitchell
8 * Ported to X/CDSA2.
9 * 14 May 1998 Doug Mitchell at Apple
10 * Created.
11 */
12
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <time.h>
17 #include <Security/cssm.h>
18 #include "cspwrap.h"
19 #include "common.h"
20 #include "cspdlTesting.h"
21
22 #define USAGE_NAME "noUsage"
23 #define USAGE_NAME_LEN (strlen(USAGE_NAME))
24 #define USAGE2_NAME "noUsage2"
25 #define USAGE2_NAME_LEN (strlen(USAGE2_NAME))
26 #define LOOPS_DEF 10
27 #define MIN_EXP 2 /* for data size 10**exp */
28 #define DEFAULT_MAX_EXP 2
29 #define MAX_EXP 4
30
31 /*
32 * Enumerate algs our own way to allow iteration.
33 */
34 #define ALG_RSA 1
35 #define ALG_FEED 2
36 #define ALG_FEEDEXP 3
37 #define ALG_FEE_CFILE 4
38 #define ALG_FIRST ALG_RSA
39 #define ALG_LAST ALG_FEEDEXP
40 #define MAX_DATA_SIZE (10000 + 100) /* bytes */
41 #define FEE_PASSWD_LEN 32 /* private data length in bytes, FEE only */
42
43 #define DUMP_KEY_DATA 0
44
45 /*
46 * RSA encryption now allows arbitrary plaintext size. BSAFE was limited to
47 * primeSize - 11.
48 */
49 #define RSA_PLAINTEXT_LIMIT 0
50
51 static void usage(char **argv)
52 {
53 printf("usage: %s [options]\n", argv[0]);
54 printf(" Options:\n");
55 printf(" a=algorithm (f=FEED; x=FEEDExp; c=FEE_Cfile; r=RSA; default=all)\n");
56 printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF);
57 printf(" n=minExp (default=%d)\n", MIN_EXP);
58 printf(" x=maxExp (default=%d, max=%d)\n", DEFAULT_MAX_EXP, MAX_EXP);
59 printf(" k=keySize\n");
60 printf(" P=primeType (m=Mersenne, f=FEE, g=general; FEE only)\n");
61 printf(" C=curveType (m=Montgomery, w=Weierstrass, g=general; FEE only)\n");
62 printf(" e(xport)\n");
63 printf(" r(eference keys only)\n");
64 printf(" K (skip decrypt)\n");
65 printf(" N(o padding, RSA only)\n");
66 printf(" S (no staging)\n");
67 printf(" D (CSP/DL; default = bare CSP)\n");
68 printf(" p (pause on each loop)\n");
69 printf(" u (quick; small keys)\n");
70 printf(" t=plainTextSize; default=random\n");
71 printf(" z(ero data)\n");
72 printf(" v(erbose)\n");
73 printf(" q(uiet)\n");
74 printf(" h(elp)\n");
75 exit(1);
76 }
77
78 static int doTest(CSSM_CSP_HANDLE cspHand,
79 CSSM_ALGORITHMS alg, // CSSM_ALGID_xxx
80 CSSM_PADDING padding,
81 CSSM_DATA_PTR ptext,
82 CSSM_BOOL verbose,
83 CSSM_BOOL quiet,
84 uint32 keySizeInBits, // may be 0, i.e., default per alg
85 uint32 primeType, // FEE only
86 uint32 curveType, // ditto
87 CSSM_BOOL pubIsRef,
88 CSSM_KEYBLOB_FORMAT rawPubForm,
89 CSSM_BOOL privIsRef,
90 CSSM_KEYBLOB_FORMAT rawPrivForm,
91 CSSM_BOOL secondPubIsRaw, // FEED via CSPDL: 2nd key must be raw
92 CSSM_BOOL stagedEncr,
93 CSSM_BOOL stagedDecr,
94 CSSM_BOOL mallocPtext, // only meaningful if !stagedDecr
95 CSSM_BOOL mallocCtext, // only meaningful if !stagedEncr
96 CSSM_BOOL skipDecrypt,
97 CSSM_BOOL genSeed) // FEE keys only
98 {
99 // these two are always generated
100 CSSM_KEY recvPubKey;
101 CSSM_KEY recvPrivKey;
102 // these two are for two-key FEE algorithms only
103 CSSM_KEY sendPubKey;
104 CSSM_KEY sendPrivKey;
105 // these two are optionally created by cspRefKeyToRaw if (FEED && secondPubIsRaw)
106 CSSM_KEY sendPubKeyRaw;
107 CSSM_KEY recvPubKeyRaw;
108 CSSM_BOOL rawPubKeysCreated = CSSM_FALSE;
109
110 /* two-key FEE, CSP : &{send,recv}PubKey
111 * two-key FEE, CSPDL: &{send,recv}PubKeyRaw
112 * else : NULL, &recvPubKey
113 */
114 CSSM_KEY_PTR sendPubKeyPtr = NULL;
115 CSSM_KEY_PTR recvPubKeyPtr = NULL;
116
117 CSSM_DATA ctext = {0, NULL};
118 CSSM_DATA rptext = {0, NULL};
119 CSSM_RETURN crtn;
120 int rtn = 0;
121 uint32 keyGenAlg;
122 uint32 mode = CSSM_ALGMODE_NONE; // FIXME - does this need testing?
123 CSSM_BOOL twoKeys = CSSM_FALSE;
124
125 switch(alg) {
126 case CSSM_ALGID_FEED:
127 case CSSM_ALGID_FEECFILE:
128 twoKeys = CSSM_TRUE;
129 /* drop thru */
130 case CSSM_ALGID_FEEDEXP:
131 keyGenAlg = CSSM_ALGID_FEE;
132 break;
133 case CSSM_ALGID_RSA:
134 keyGenAlg = CSSM_ALGID_RSA;
135 break;
136 default:
137 printf("bogus algorithm\n");
138 return 1;
139 }
140
141 /* one key pair for all algs except CFILE and FEED, which need two */
142 if(keyGenAlg == CSSM_ALGID_FEE) {
143 uint8 passwd[FEE_PASSWD_LEN];
144 CSSM_DATA pwdData = {FEE_PASSWD_LEN, passwd};
145 CSSM_DATA_PTR pwdDataPtr;
146 if(genSeed) {
147 simpleGenData(&pwdData, FEE_PASSWD_LEN, FEE_PASSWD_LEN);
148 pwdDataPtr = &pwdData;
149 }
150 else {
151 pwdDataPtr = NULL;
152 }
153 /*
154 * Note we always generate public keys per the pubIsRef argument, even if
155 * secondPubIsRaw is true, 'cause the CSPDL can't generate raw keys.
156 */
157 rtn = cspGenFEEKeyPair(cspHand,
158 USAGE_NAME,
159 USAGE_NAME_LEN,
160 keySizeInBits,
161 primeType,
162 curveType,
163 &recvPubKey,
164 pubIsRef,
165 CSSM_KEYUSE_ANY,
166 CSSM_KEYBLOB_RAW_FORMAT_NONE,
167 &recvPrivKey,
168 privIsRef,
169 CSSM_KEYUSE_ANY,
170 CSSM_KEYBLOB_RAW_FORMAT_NONE,
171 pwdDataPtr);
172 if(rtn) {
173 /* leak */
174 return testError(quiet);
175 }
176 if(twoKeys) {
177 rtn = cspGenFEEKeyPair(cspHand,
178 USAGE2_NAME,
179 USAGE2_NAME_LEN,
180 keySizeInBits,
181 primeType,
182 curveType,
183 &sendPubKey,
184 pubIsRef,
185 CSSM_KEYUSE_ANY,
186 CSSM_KEYBLOB_RAW_FORMAT_NONE,
187 &sendPrivKey,
188 privIsRef,
189 CSSM_KEYUSE_ANY,
190 CSSM_KEYBLOB_RAW_FORMAT_NONE,
191 pwdDataPtr);
192 if(rtn) {
193 /* leak recv*Key */
194 return testError(quiet);
195 }
196 }
197 if(twoKeys) {
198 if(secondPubIsRaw && pubIsRef) {
199 /*
200 * Convert ref public keys to raw - they're going into a Context; the
201 * SecurityServer doesn't deal with ref keys there.
202 * Leak all sorts of stuff on any error here.
203 */
204 crtn = cspRefKeyToRaw(cspHand, &sendPubKey, &sendPubKeyRaw);
205 if(crtn) {
206 return testError(quiet);
207 }
208 crtn = cspRefKeyToRaw(cspHand, &recvPubKey, &recvPubKeyRaw);
209 if(crtn) {
210 return testError(quiet);
211 }
212 /* two keys, CSPDL */
213 sendPubKeyPtr = &sendPubKeyRaw;
214 recvPubKeyPtr = &recvPubKeyRaw;
215 rawPubKeysCreated = CSSM_TRUE;
216 }
217 else {
218 /* two keys, CSP */
219 sendPubKeyPtr = &sendPubKey;
220 recvPubKeyPtr = &recvPubKey;
221 }
222 }
223 else {
224 /* one key pair, standard config */
225 sendPubKeyPtr = NULL;
226 recvPubKeyPtr = &recvPubKey;
227 }
228 }
229 else {
230 CSSM_KEYBLOB_FORMAT expectPubForm = rawPubForm;
231 CSSM_KEYBLOB_FORMAT expectPrivForm = rawPrivForm;
232
233 rtn = cspGenKeyPair(cspHand,
234 keyGenAlg,
235 USAGE_NAME,
236 USAGE_NAME_LEN,
237 keySizeInBits,
238 &recvPubKey,
239 pubIsRef,
240 twoKeys ? CSSM_KEYUSE_ANY : CSSM_KEYUSE_ENCRYPT,
241 rawPubForm,
242 &recvPrivKey,
243 privIsRef,
244 twoKeys ? CSSM_KEYUSE_ANY : CSSM_KEYUSE_DECRYPT,
245 rawPrivForm,
246 genSeed);
247 if(rtn) {
248 return testError(quiet);
249 }
250 /* one key pair, standard config */
251 sendPubKeyPtr = NULL;
252 recvPubKeyPtr = &recvPubKey;
253
254 /* verify defaults - only for RSA */
255 if(!pubIsRef) {
256 if(rawPubForm == CSSM_KEYBLOB_RAW_FORMAT_NONE) {
257 expectPubForm = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
258 }
259 if(recvPubKey.KeyHeader.Format != expectPubForm) {
260 printf("***Bad raw RSA pub key format - exp %u got %u\n",
261 (unsigned)expectPubForm,
262 (unsigned)recvPubKey.KeyHeader.Format);
263 if(testError(quiet)) {
264 return 1;
265 }
266 }
267 }
268 if(!privIsRef) {
269 if(rawPrivForm == CSSM_KEYBLOB_RAW_FORMAT_NONE) {
270 expectPrivForm = CSSM_KEYBLOB_RAW_FORMAT_PKCS8;
271 }
272 if(recvPrivKey.KeyHeader.Format != expectPrivForm) {
273 printf("***Bad raw RSA priv key format - exp %u got %u\n",
274 (unsigned)expectPrivForm,
275 (unsigned)recvPrivKey.KeyHeader.Format);
276 if(testError(quiet)) {
277 return 1;
278 }
279 }
280 }
281 }
282 #if DUMP_KEY_DATA
283 dumpBuffer("Pub Key Data", recvPubKey.KeyData.Data, recvPubKey.KeyData.Length);
284 dumpBuffer("Priv Key Data", recvPrivKey.KeyData.Data, recvPrivKey.KeyData.Length);
285 #endif
286 if(stagedEncr) {
287 crtn = cspStagedEncrypt(cspHand,
288 alg,
289 mode,
290 padding,
291 /* Two keys: second must be pub */
292 twoKeys ? &sendPrivKey : &recvPubKey,
293 twoKeys ? recvPubKeyPtr : NULL,
294 0, // effectiveKeySize
295 0, // cipherBlockSize
296 0, // rounds
297 NULL, // initVector
298 ptext,
299 &ctext,
300 CSSM_TRUE); // multi
301 }
302 else {
303 crtn = cspEncrypt(cspHand,
304 alg,
305 mode,
306 padding,
307 /* Two keys: second must be pub */
308 twoKeys ? &sendPrivKey : &recvPubKey,
309 twoKeys ? recvPubKeyPtr : NULL,
310 0, // effectiveKeySize
311 0, // rounds
312 NULL, // initVector
313 ptext,
314 &ctext,
315 mallocCtext);
316 }
317 if(crtn) {
318 rtn = testError(quiet);
319 goto abort;
320 }
321 if(verbose) {
322 printf(" ..ptext size %lu ctext size %lu\n",
323 (unsigned long)ptext->Length, (unsigned long)ctext.Length);
324 }
325 if(skipDecrypt) {
326 goto abort;
327 }
328 if(stagedDecr) {
329 crtn = cspStagedDecrypt(cspHand,
330 alg,
331 mode,
332 padding,
333 /* Two keys: second must be pub */
334 &recvPrivKey,
335 sendPubKeyPtr,
336 0, // effectiveKeySize
337 0, // cipherBlockSize
338 0, // rounds
339 NULL, // initVector
340 &ctext,
341 &rptext,
342 CSSM_TRUE); // multi
343 }
344 else {
345 crtn = cspDecrypt(cspHand,
346 alg,
347 mode,
348 padding,
349 &recvPrivKey,
350 sendPubKeyPtr,
351 0, // effectiveKeySize
352 0, // rounds
353 NULL, // initVector
354 &ctext,
355 &rptext,
356 mallocPtext);
357 }
358 if(crtn) {
359 rtn = testError(quiet);
360 goto abort;
361 }
362 /* compare ptext, rptext */
363 if(ptext->Length != rptext.Length) {
364 printf("Ptext length mismatch: expect %lu, got %lu\n",
365 (unsigned long)ptext->Length, (unsigned long)rptext.Length);
366 rtn = testError(quiet);
367 if(rtn) {
368 goto abort;
369 }
370 }
371 if(memcmp(ptext->Data, rptext.Data, ptext->Length)) {
372 printf("***data miscompare\n");
373 rtn = testError(quiet);
374 }
375 abort:
376 /* free keys */
377 if(cspFreeKey(cspHand, &recvPubKey)) {
378 printf("Error freeing recvPubKey\n");
379 rtn = 1;
380 }
381 if(cspFreeKey(cspHand, &recvPrivKey)) {
382 printf("Error freeing recvPrivKey\n");
383 rtn = 1;
384 }
385 if(twoKeys) {
386 if(cspFreeKey(cspHand, &sendPubKey)) {
387 printf("Error freeing sendPubKey\n");
388 rtn = 1;
389 }
390 if(cspFreeKey(cspHand, &sendPrivKey)) {
391 printf("Error freeing sendPrivKey\n");
392 rtn = 1;
393 }
394 if(rawPubKeysCreated) {
395 if(cspFreeKey(cspHand, &sendPubKeyRaw)) {
396 printf("Error freeing sendPubKeyRaw\n");
397 rtn = 1;
398 }
399 if(cspFreeKey(cspHand, &recvPubKeyRaw)) {
400 printf("Error freeing recvPubKeyRaw\n");
401 rtn = 1;
402 }
403 }
404 }
405 /* free rptext, ctext */
406 appFreeCssmData(&rptext, CSSM_FALSE);
407 appFreeCssmData(&ctext, CSSM_FALSE);
408 return rtn;
409 }
410
411 static const char *formStr(
412 CSSM_KEYBLOB_FORMAT form)
413 {
414 switch(form) {
415 case CSSM_KEYBLOB_RAW_FORMAT_NONE: return "NONE";
416 case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: return "PKCS1";
417 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: return "PKCS8";
418 case CSSM_KEYBLOB_RAW_FORMAT_X509: return "X509";
419 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: return "SSH1";
420 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: return "SSH2";
421 default:
422 printf("***BRRRZAP! formStr needs work\n");
423 exit(1);
424 }
425 }
426
427 int main(int argc, char **argv)
428 {
429 int arg;
430 char *argp;
431 unsigned loop;
432 CSSM_DATA ptext;
433 CSSM_CSP_HANDLE cspHand;
434 CSSM_BOOL pubIsRef = CSSM_TRUE;
435 CSSM_BOOL privIsRef = CSSM_TRUE;
436 CSSM_BOOL stagedEncr;
437 CSSM_BOOL stagedDecr;
438 const char *algStr;
439 uint32 encAlg; // CSSM_ALGID_xxx
440 unsigned currAlg; // ALG_xxx
441 int i;
442 CSSM_BOOL mallocCtext;
443 CSSM_BOOL mallocPtext;
444 int rtn = 0;
445 CSSM_BOOL genSeed; // for FEE key gen
446 CSSM_PADDING padding;
447 CSSM_KEYBLOB_FORMAT rawPubFormat = CSSM_KEYBLOB_RAW_FORMAT_NONE;
448 CSSM_KEYBLOB_FORMAT rawPrivFormat = CSSM_KEYBLOB_RAW_FORMAT_NONE;
449
450 /*
451 * User-spec'd params
452 */
453 unsigned loops = LOOPS_DEF;
454 CSSM_BOOL verbose = CSSM_FALSE;
455 unsigned minExp = MIN_EXP;
456 unsigned maxExp = DEFAULT_MAX_EXP;
457 CSSM_BOOL quiet = CSSM_FALSE;
458 uint32 keySizeInBits = CSP_KEY_SIZE_DEFAULT;
459 CSSM_BOOL keySizeSpec = CSSM_FALSE;
460 unsigned minAlg = ALG_FIRST;
461 uint32 maxAlg = ALG_LAST;
462 CSSM_BOOL skipDecrypt = CSSM_FALSE;
463 CSSM_BOOL bareCsp = CSSM_TRUE;
464 CSSM_BOOL doPause = CSSM_FALSE;
465 CSSM_BOOL smallKeys = CSSM_FALSE;
466 uint32 primeType = CSSM_FEE_PRIME_TYPE_DEFAULT; // FEE only
467 uint32 curveType = CSSM_FEE_CURVE_TYPE_DEFAULT; // FEE only
468 uint32 ptextSize = 0; // 0 means random
469 dataType dtype = DT_Random;
470 CSSM_BOOL refKeysOnly = CSSM_FALSE;
471 CSSM_BOOL noPadding = CSSM_FALSE;
472 CSSM_BOOL stagingEnabled = CSSM_TRUE;
473
474 for(arg=1; arg<argc; arg++) {
475 argp = argv[arg];
476 switch(argp[0]) {
477 case 'a':
478 if(argp[1] != '=') {
479 usage(argv);
480 }
481 switch(argp[2]) {
482 case 'f':
483 minAlg = maxAlg = ALG_FEED;
484 break;
485 case 'x':
486 minAlg = maxAlg = ALG_FEEDEXP;
487 break;
488 case 'c':
489 minAlg = maxAlg = ALG_FEE_CFILE;
490 break;
491 case 'r':
492 minAlg = maxAlg = ALG_RSA;
493 break;
494 case 'a':
495 minAlg = ALG_FIRST;
496 maxAlg = ALG_LAST;
497 break;
498 default:
499 usage(argv);
500 }
501 break;
502 case 'l':
503 loops = atoi(&argp[2]);
504 break;
505 case 'n':
506 minExp = atoi(&argp[2]);
507 break;
508 case 'x':
509 maxExp = atoi(&argp[2]);
510 if(maxExp > MAX_EXP) {
511 usage(argv);
512 }
513 break;
514 case 'k':
515 keySizeInBits = atoi(&argv[arg][2]);
516 keySizeSpec = CSSM_TRUE;
517 break;
518 case 'K':
519 skipDecrypt = CSSM_TRUE;
520 break;
521 case 't':
522 ptextSize = atoi(&argp[2]);
523 break;
524 case 'D':
525 bareCsp = CSSM_FALSE;
526 #if CSPDL_ALL_KEYS_ARE_REF
527 refKeysOnly = CSSM_TRUE;
528 #endif
529 break;
530 case 'u':
531 smallKeys = CSSM_TRUE;
532 break;
533 case 'N':
534 noPadding = CSSM_TRUE;
535 break;
536 case 'z':
537 dtype = DT_Zero;
538 break;
539 case 'v':
540 verbose = CSSM_TRUE;
541 break;
542 case 'r':
543 refKeysOnly = CSSM_TRUE;
544 break;
545 case 'S':
546 stagingEnabled = CSSM_FALSE;
547 break;
548 case 'p':
549 doPause = CSSM_TRUE;
550 break;
551 case 'q':
552 quiet = CSSM_TRUE;
553 break;
554 case 'C':
555 switch(argp[2]) {
556 case 'm':
557 curveType = CSSM_FEE_CURVE_TYPE_MONTGOMERY;
558 break;
559 case 'w':
560 curveType = CSSM_FEE_CURVE_TYPE_WEIERSTRASS;
561 break;
562 default:
563 usage(argv);
564 }
565 break;
566 case 'P':
567 switch(argp[2]) {
568 case 'm':
569 primeType = CSSM_FEE_PRIME_TYPE_MERSENNE;
570 break;
571 case 'f':
572 primeType = CSSM_FEE_PRIME_TYPE_FEE;
573 break;
574 case 'g':
575 primeType = CSSM_FEE_PRIME_TYPE_GENERAL;
576 break;
577 default:
578 usage(argv);
579 }
580 break;
581 case 'h':
582 default:
583 usage(argv);
584 }
585 }
586 ptext.Data = (uint8 *)CSSM_MALLOC(MAX_DATA_SIZE);
587
588 /* length set in test loop */
589 if(ptext.Data == NULL) {
590 printf("Insufficient heap\n");
591 exit(1);
592 }
593 if(noPadding) {
594 if(ptextSize == 0) {
595 printf("**WARNING NoPad mode will fail with random plaintext size\n");
596 }
597 if(!keySizeSpec) {
598 printf("**WARNING NoPad mode will fail with random key size\n");
599 }
600 else {
601 uint32 keyBytes = keySizeInBits / 8;
602 if(ptextSize != keyBytes) {
603 /*
604 * FIXME: I actually do not understand why this fails, but
605 * doing raw RSA encryption with ptextSize != keySize results
606 * in random-looking failures, probably based on the plaintext
607 * itself (it doesn't fail with zero data).
608 */
609 printf("***WARNING NoPad mode requires plaintext size = key size\n");
610 }
611 }
612 }
613 printf("Starting asymTest; args: ");
614 for(i=1; i<argc; i++) {
615 printf("%s ", argv[i]);
616 }
617 printf("\n");
618 cspHand = cspDlDbStartup(bareCsp, NULL);
619 if(cspHand == 0) {
620 exit(1);
621 }
622 for(currAlg=minAlg; currAlg<=maxAlg; currAlg++) {
623 switch(currAlg) {
624 case ALG_FEED:
625 encAlg = CSSM_ALGID_FEED;
626 algStr = "FEED";
627 padding = CSSM_PADDING_NONE;
628 break;
629 case ALG_FEEDEXP:
630 encAlg = CSSM_ALGID_FEEDEXP;
631 algStr = "FEEDExp";
632 padding = CSSM_PADDING_NONE;
633 break;
634 case ALG_FEE_CFILE:
635 encAlg = CSSM_ALGID_FEECFILE;
636 algStr = "FEE_CFILE";
637 padding = CSSM_PADDING_NONE;
638 break;
639 case ALG_RSA:
640 encAlg = CSSM_ALGID_RSA;
641 algStr = "RSA";
642 if(noPadding) {
643 padding = CSSM_PADDING_NONE;
644 }
645 else {
646 padding = CSSM_PADDING_PKCS1;
647 }
648 break;
649 }
650 if(!quiet) {
651 printf("Testing alg %s\n", algStr);
652 }
653 for(loop=1; ; loop++) {
654 if(doPause) {
655 fpurge(stdin);
656 printf("Top of loop; hit CR to proceed: ");
657 getchar();
658 }
659 if(ptextSize) {
660 if(dtype == DT_Zero) {
661 memset(ptext.Data, 0, ptextSize);
662 ptext.Length = ptextSize;
663 }
664 else {
665 simpleGenData(&ptext, ptextSize, ptextSize);
666 }
667 }
668 else {
669 ptext.Length = genData(ptext.Data, minExp, maxExp, dtype);
670 }
671
672 /* raw RSA, no padding, ensure top two bits are zero */
673 if((encAlg == CSSM_ALGID_RSA) && (padding == CSSM_PADDING_NONE)) {
674 ptext.Data[0] &= 0x3f;
675 }
676
677 if(!keySizeSpec) {
678 /* random per alg unless user overrides */
679 if(encAlg == CSSM_ALGID_RSA) {
680 if(smallKeys) {
681 keySizeInBits = CSP_RSA_KEY_SIZE_DEFAULT;
682 }
683 else {
684 keySizeInBits = randKeySizeBits(CSSM_ALGID_RSA, OT_Encrypt);
685 }
686 }
687 else {
688 /* FEED, FEEDExp */
689 if(smallKeys) {
690 keySizeInBits = 127;
691 /* default curveType = Weierstrass */
692 }
693 else {
694 randFeeKeyParams(encAlg,
695 &keySizeInBits,
696 &primeType,
697 &curveType);
698 }
699 }
700 }
701 #if RSA_PLAINTEXT_LIMIT
702 if(encAlg == CSSM_ALGID_RSA) {
703 /* total ptext size can't exceed (modulus size - 11) */
704 /* we should probably get this from the CSP, but this
705 * whole thing is such a kludge. What's the point?
706 * Only RSA encrypt/decrypt has a max total size.
707 */
708 unsigned modSize;
709 unsigned maxSize;
710 if(keySizeInBits == CSP_KEY_SIZE_DEFAULT) {
711 modSize = CSP_RSA_KEY_SIZE_DEFAULT / 8;
712 }
713 else {
714 modSize = keySizeInBits / 8;
715 }
716 maxSize = modSize - 11;
717 ptext.Length = genRand(1, maxSize);
718 }
719 #endif
720 if(!quiet) {
721 if(encAlg == CSSM_ALGID_RSA) {
722 printf("..loop %d text size %lu keySize %u\n",
723 loop, (unsigned long)ptext.Length, (unsigned)keySizeInBits);
724 }
725 else {
726 printf("..loop %d text size %lu keySize %u primeType %s "
727 "curveType %s\n",
728 loop, (unsigned long)ptext.Length, (unsigned)keySizeInBits,
729 primeTypeStr(primeType), curveTypeStr(curveType));
730 }
731 }
732
733 /* mix up some ref and data keys, as well as staging and mallocing */
734 if(!refKeysOnly) {
735 pubIsRef = (loop & 1) ? CSSM_TRUE : CSSM_FALSE;
736 privIsRef = (loop & 8) ? CSSM_TRUE : CSSM_FALSE;
737 }
738 if((currAlg == ALG_FEE_CFILE) || !stagingEnabled) {
739 /* staged ops unsupported */
740 stagedEncr = CSSM_FALSE;
741 stagedDecr = CSSM_FALSE;
742 }
743 else {
744 stagedEncr = (loop & 2) ? CSSM_TRUE : CSSM_FALSE;
745 stagedDecr = (loop & 4) ? CSSM_TRUE : CSSM_FALSE;
746 }
747 if(!stagedEncr) {
748 mallocCtext = (ptext.Data[0] & 1) ? CSSM_TRUE : CSSM_FALSE;
749 }
750 else {
751 mallocCtext = CSSM_FALSE;
752 }
753 if(!stagedDecr) {
754 mallocPtext = (ptext.Data[0] & 2) ? CSSM_TRUE : CSSM_FALSE;
755 }
756 else {
757 mallocPtext = CSSM_FALSE;
758 }
759 switch(currAlg) {
760 case ALG_FEED:
761 case ALG_FEEDEXP:
762 genSeed = (ptext.Data[0] & 4) ? CSSM_TRUE : CSSM_FALSE;
763 break;
764 default:
765 genSeed = CSSM_FALSE;
766 }
767 rawPubFormat = rawPrivFormat = CSSM_KEYBLOB_RAW_FORMAT_NONE;
768 if(currAlg == ALG_RSA) {
769 /* mix up raw key formats */
770 unsigned die;
771 if(!pubIsRef) {
772 /* five formats */
773 die = ptext.Data[1] % 5;
774 switch(die) {
775 case 0:
776 rawPubFormat = CSSM_KEYBLOB_RAW_FORMAT_NONE;
777 break;
778 case 1:
779 rawPubFormat = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
780 break;
781 case 2:
782 rawPubFormat = CSSM_KEYBLOB_RAW_FORMAT_OPENSSH;
783 break;
784 case 3:
785 rawPubFormat = CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2;
786 break;
787 default:
788 rawPubFormat = CSSM_KEYBLOB_RAW_FORMAT_X509;
789 break;
790 }
791 }
792 if(!privIsRef) {
793 /* four formats */
794 die = ptext.Data[2] % 4;
795 switch(die) {
796 case 0:
797 rawPrivFormat = CSSM_KEYBLOB_RAW_FORMAT_NONE;
798 break;
799 case 1:
800 rawPrivFormat = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
801 break;
802 case 2:
803 rawPrivFormat = CSSM_KEYBLOB_RAW_FORMAT_OPENSSH;
804 break;
805 default:
806 rawPrivFormat = CSSM_KEYBLOB_RAW_FORMAT_PKCS8;
807 break;
808 }
809 }
810 }
811 #if 0
812 if(encAlg == CSSM_ALGID_RSA) {
813 /* FIXME - another restriction - the MS bits of each block
814 * of plaintext must be zero, to make the numerical value of the
815 * block less than the modulus!
816 * Aug 7 1998: Now that we're using AI_PKCS_RSA{Public,Private}, the
817 * numerical value of the data no longer has to be less than
818 * the modulus.
819 */
820 stagedEncr = stagedDecr = CSSM_TRUE;
821 }
822 #endif
823
824 if(!quiet) {
825 printf(" pubRef %d privRef %d stgEncr %d stgdDecr %d "
826 "malPtext %d malCtext %d genSeed %d pubForm %s privForm %s\n",
827 (int)pubIsRef, (int)privIsRef, (int)stagedEncr, (int)stagedDecr,
828 (int)mallocPtext, (int)mallocCtext, (int)genSeed,
829 formStr(rawPubFormat), formStr(rawPrivFormat));
830 }
831 if(doTest(cspHand,
832 encAlg,
833 padding,
834 &ptext,
835 verbose,
836 quiet,
837 keySizeInBits,
838 primeType,
839 curveType,
840 pubIsRef,
841 rawPubFormat,
842 privIsRef,
843 rawPrivFormat,
844 #if CSPDL_2ND_PUB_KEY_IS_RAW
845 /* secondPubIsRaw */
846 bareCsp ? CSSM_FALSE : CSSM_TRUE,
847 #else
848 CSSM_FALSE,
849 #endif
850 stagedEncr,
851 stagedDecr,
852 mallocCtext,
853 mallocPtext,
854 skipDecrypt,
855 genSeed)) {
856 rtn = 1;
857 goto testDone;
858 }
859 if(loops && (loop == loops)) {
860 break;
861 }
862 } /* for loop */
863 } /* for alg */
864 testDone:
865 CSSM_ModuleDetach(cspHand);
866 if((rtn == 0) && !quiet) {
867 printf("%s test complete\n", argv[0]);
868 }
869 return rtn;
870 }