]>
Commit | Line | Data |
---|---|---|
d8f41ccd A |
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 | } |