1/*
2 * asymCompat.c - test compatibilty of two different implementations of a
3 * RSA and DSA - one in the standard AppleCSP, one in BSAFE.
4 */
5
6#include <stdlib.h>
7#include <stdio.h>
8#include <time.h>
9#include <Security/cssm.h>
10#include <Security/cssmapple.h>
11#include "cspwrap.h"
12#include "common.h"
13#include "bsafeUtils.h"
14#include <string.h>
15#include "cspdlTesting.h"
16
17/*
18 * Defaults.
19 */
20#define OLOOPS_DEF		10		/* outer loops, one set of keys per loop */
21#define SIG_LOOPS_DEF	100		/* sig loops */
22#define ENC_LOOPS_DEF	100		/* encrypt/decrypt loops */
23#define MAX_TEXT_SIZE	1025
24
25#define LOOP_NOTIFY		20
26
27static void usage(char **argv)
28{
29	printf("usage: %s [options]\n", argv[0]);
30	printf("   Options:\n");
31	printf("   a=algorithm (r=RSA; d=DSA; default=both)\n");
32	printf("   l=outerloops (default=%d; 0=forever)\n", OLOOPS_DEF);
33	printf("   s=sigLoops (default=%d)\n", SIG_LOOPS_DEF);
34	printf("   e=encryptLoops (default=%d)\n", ENC_LOOPS_DEF);
35	printf("   k=keySizeInBits; default is random\n");
36	printf("   S (sign/verify only)\n");
37	printf("   E (encrypt/decrypt only)\n");
38	printf("   r (generate ref keys)\n");
39	printf("   R (generate public ref keys)\n");
40	printf("   p=pauseInterval (default=0, no pause)\n");
41	printf("   D (CSP/DL; default = bare CSP)\n");
42	printf("   v(erbose)\n");
43	printf("   q(uiet)\n");
44	printf("   h(elp)\n");
45	exit(1);
46}
47
48static const char *algToStr(CSSM_ALGORITHMS sigAlg)
49{
50	switch(sigAlg) {
51		case CSSM_ALGID_RSA:			return "RSA";
52		case CSSM_ALGID_DSA:			return "DSA";
53		case CSSM_ALGID_SHA1WithRSA:	return "SHA1WithRSA";
54		case CSSM_ALGID_MD5WithRSA:		return "MD5WithRSA";
55		case CSSM_ALGID_SHA1WithDSA:	return "SHA1WithDSA";
56		default:
57			printf("***Unknown sigAlg\n");
58			exit(1);
59	}
60	/* NOT REACHED */
61	return "";
62}
63
64/*
65 * CDSA private key decrypt with blinding option.
66 */
67static CSSM_RETURN _cspDecrypt(CSSM_CSP_HANDLE cspHand,
68		uint32 algorithm,					// CSSM_ALGID_FEED, etc.
69		uint32 mode,						// CSSM_ALGMODE_CBC, etc. - only for symmetric algs
70		CSSM_PADDING padding,				// CSSM_PADDING_PKCS1, etc.
71		CSSM_BOOL blinding,
72		const CSSM_KEY *key,				// public or session key
73		const CSSM_DATA *ctext,
74		CSSM_DATA_PTR ptext)				// RETURNED
75{
76	CSSM_CC_HANDLE 	cryptHand;
77	CSSM_RETURN		crtn;
78	CSSM_RETURN		ocrtn = CSSM_OK;
79	CSSM_SIZE		bytesDecrypted;
80	CSSM_DATA		remData = {0, NULL};
81
82	cryptHand = genCryptHandle(cspHand,
83		algorithm,
84		mode,
85		padding,
86		key,
87		NULL,		// pubKey,
88		NULL,		// iv,
89		0,			// effectiveKeySizeInBits,
90		0);			// rounds
91	if(cryptHand == 0) {
92		return CSSMERR_CSP_INTERNAL_ERROR;
93	}
94	if(blinding) {
95		CSSM_CONTEXT_ATTRIBUTE	newAttr;
96		newAttr.AttributeType     = CSSM_ATTRIBUTE_RSA_BLINDING;
97		newAttr.AttributeLength   = sizeof(uint32);
98		newAttr.Attribute.Uint32  = 1;
99		crtn = CSSM_UpdateContextAttributes(cryptHand, 1, &newAttr);
100		if(crtn) {
101			printError("CSSM_UpdateContextAttributes", crtn);
102			return crtn;
103		}
104	}
105
106	crtn = CSSM_DecryptData(cryptHand,
107		ctext,
108		1,
109		ptext,
110		1,
111		&bytesDecrypted,
112		&remData);
113	if(crtn == CSSM_OK) {
114		// NOTE: We return the proper length in ptext....
115		ptext->Length = bytesDecrypted;
116
117		// FIXME - sometimes get mallocd RemData here, but never any valid data
118		// there...side effect of CSPFullPluginSession's buffer handling logic;
119		// but will we ever actually see valid data in RemData? So far we never
120		// have....
121		if(remData.Data != NULL) {
122			appFree(remData.Data, NULL);
123		}
124	}
125	else {
126		printError("CSSM_DecryptData", crtn);
127		ocrtn = crtn;
128	}
129	crtn = CSSM_DeleteContext(cryptHand);
130	if(crtn) {
131		printError("CSSM_DeleteContext", crtn);
132		ocrtn = crtn;
133	}
134	return ocrtn;
135}
136
137/* sign with RSA blinging option */
138static CSSM_RETURN _cspSign(CSSM_CSP_HANDLE cspHand,
139		uint32 algorithm,					// CSSM_ALGID_FEE_MD5, etc.
140		CSSM_KEY_PTR key,					// private key
141		const CSSM_DATA *text,
142		CSSM_BOOL rsaBlinding,
143		CSSM_DATA_PTR sig)					// RETURNED
144{
145	CSSM_CC_HANDLE	sigHand;
146	CSSM_RETURN		crtn;
147	CSSM_RETURN		ocrtn = CSSM_OK;
148	const CSSM_DATA	*ptext;
149	CSSM_DATA		digest = {0, NULL};
150	CSSM_ALGORITHMS	digestAlg = CSSM_ALGID_NONE;
151
152	/* handle special cases for raw sign */
153	switch(algorithm) {
154		case CSSM_ALGID_SHA1:
155			digestAlg = CSSM_ALGID_SHA1;
156			algorithm = CSSM_ALGID_RSA;
157			break;
158		case CSSM_ALGID_MD5:
159			digestAlg = CSSM_ALGID_MD5;
160			algorithm = CSSM_ALGID_RSA;
161			break;
162		case CSSM_ALGID_DSA:
163			digestAlg = CSSM_ALGID_SHA1;
164			algorithm = CSSM_ALGID_DSA;
165			break;
166		default:
167			break;
168	}
169	if(digestAlg != CSSM_ALGID_NONE) {
170		crtn = cspDigest(cspHand,
171			digestAlg,
172			CSSM_FALSE,			// mallocDigest
173			text,
174			&digest);
175		if(crtn) {
176			return crtn;
177		}
178		/* sign digest with raw RSA/DSA */
179		ptext = &digest;
180	}
181	else {
182		ptext = text;
183	}
184	crtn = CSSM_CSP_CreateSignatureContext(cspHand,
185		algorithm,
186		NULL,				// passPhrase
187		key,
188		&sigHand);
189	if(crtn) {
190		printError("CSSM_CSP_CreateSignatureContext (1)", crtn);
191		return crtn;
192	}
193	if(rsaBlinding) {
194		CSSM_CONTEXT_ATTRIBUTE	newAttr;
195		newAttr.AttributeType     = CSSM_ATTRIBUTE_RSA_BLINDING;
196		newAttr.AttributeLength   = sizeof(uint32);
197		newAttr.Attribute.Uint32  = 1;
198		crtn = CSSM_UpdateContextAttributes(sigHand, 1, &newAttr);
199		if(crtn) {
200			printError("CSSM_UpdateContextAttributes", crtn);
201			return crtn;
202		}
203	}
204	crtn = CSSM_SignData(sigHand,
205		ptext,
206		1,
207		digestAlg,
208		sig);
209	if(crtn) {
210		printError("CSSM_SignData", crtn);
211		ocrtn = crtn;
212	}
213	crtn = CSSM_DeleteContext(sigHand);
214	if(crtn) {
215		printError("CSSM_DeleteContext", crtn);
216		ocrtn = crtn;
217	}
218	if(digest.Data != NULL) {
219		CSSM_FREE(digest.Data);
220	}
221	return ocrtn;
222}
223
224
225/*
226 * Sign/verify test.
227 *
228 * for specified numLoops {
229 *		generate random text;
230 *		sign with BSAFE priv key, verify with CDSA pub key;
231 *		sign with CDSA priv key, verify with BSAFE pub key;
232 * }
233 */
234static int sigTest(
235	CSSM_CSP_HANDLE		cspHand,
236	unsigned			numLoops,
237
238	/* one matched key pair */
239	BU_KEY				bsafePrivKey,
240	CSSM_KEY_PTR		cdsaPubKey,
241
242	/* another matched key pair */
243	CSSM_KEY_PTR		cdsaPrivKey,
244	BU_KEY				bsafePubKey,
245
246	CSSM_DATA_PTR		ptext,
247	unsigned			maxPtextSize,
248	CSSM_ALGORITHMS		sigAlg,
249	CSSM_BOOL			rsaBlinding,
250	CSSM_BOOL			quiet,
251	CSSM_BOOL			verbose)
252{
253	CSSM_RETURN crtn;
254	CSSM_DATA	sig = {0, NULL};
255	unsigned	loop;
256	uint32		keySizeInBits = cdsaPrivKey->KeyHeader.LogicalKeySizeInBits;
257
258	if(!quiet) {
259		printf("   ...sig alg %s  keySize %u\n", algToStr(sigAlg), (unsigned)keySizeInBits);
260	}
261	for(loop=0; loop<numLoops; loop++) {
262		simpleGenData(ptext, 1, maxPtextSize);
263		if(!quiet) {
264			if(verbose || ((loop % LOOP_NOTIFY) == 0)) {
265				printf("      ...loop %d keySize %u textSize %lu\n",
266					loop, (unsigned)cdsaPrivKey->KeyHeader.LogicalKeySizeInBits,
267					(unsigned long)ptext->Length);
268			}
269		}
270
271		/* sign with BSAFE, verify with CDSA */
272		crtn = buSign(bsafePrivKey,
273			sigAlg,
274			ptext,
275			keySizeInBits,
276			&sig);
277		if(crtn) {
278			return testError(quiet);
279		}
280		crtn = cspSigVerify(cspHand,
281			sigAlg,
282			cdsaPubKey,
283			ptext,
284			&sig,
285			CSSM_OK);
286		if(crtn) {
287			printf("***ERROR: Sign with BSAFE, vfy with CDSA, alg %s\n",
288				algToStr(sigAlg));
289			if(testError(quiet)) {
290				return 1;
291			}
292		}
293		appFreeCssmData(&sig, CSSM_FALSE);
294
295		/* sign with CDSA, verify with BSAFE */
296		crtn = _cspSign(cspHand,
297			sigAlg,
298			cdsaPrivKey,
299			ptext,
300			rsaBlinding,
301			&sig);
302		if(crtn) {
303			return testError(quiet);
304		}
305		crtn = buVerify(bsafePubKey,
306			sigAlg,
307			ptext,
308			&sig);
309		if(crtn) {
310			printf("***ERROR: Sign with CDSA, vfy with BSAFE, alg %s\n",
311				algToStr(sigAlg));
312			if(testError(quiet)) {
313				return 1;
314			}
315		}
316		appFreeCssmData(&sig, CSSM_FALSE);
317	}
318	return CSSM_OK;
319}
320
321/*
322 * RSA Encrypt/decrypt test.
323 *
324 * for specified numLoops {
325 *		generate random text;
326 *		encrypt with BSAFE pub key, decrypt with CDSA priv key, verify;
327 *		encrypt with CDSA pub key, decrypt with BSAFE priv key, verify;
328 * }
329 */
330static int encryptTest(
331	CSSM_CSP_HANDLE		cspHand,
332	unsigned			numLoops,
333
334	/* one matched key pair */
335	BU_KEY				bsafePrivKey,
336	CSSM_KEY_PTR		cdsaPubKey,
337
338	/* another matched key pair */
339	CSSM_KEY_PTR		cdsaPrivKey,
340	BU_KEY				bsafePubKey,
341
342	CSSM_DATA_PTR		ptext,
343	unsigned			maxPtextSize,
344	CSSM_BOOL			rsaBlinding,
345	CSSM_BOOL			quiet,
346	CSSM_BOOL			verbose)
347{
348	CSSM_RETURN crtn;
349	CSSM_DATA	ctext = {0, NULL};
350	CSSM_DATA	rptext = {0, NULL};
351	unsigned	loop;
352	unsigned	actKeySizeBytes;
353
354	actKeySizeBytes = cdsaPrivKey->KeyHeader.LogicalKeySizeInBits / 8;
355	if(actKeySizeBytes < 12) {
356		printf("***Key with %u key bits is too small for RSA encrypt\n",
357			(unsigned)cdsaPrivKey->KeyHeader.LogicalKeySizeInBits);
358		return 1;
359	}
360	if(maxPtextSize > (actKeySizeBytes - 11)) {
361		maxPtextSize = actKeySizeBytes - 11;
362	}
363	if(!quiet) {
364		printf("   ...encr alg RSA\n");
365	}
366	for(loop=0; loop<numLoops; loop++) {
367		simpleGenData(ptext, 1, maxPtextSize);
368		if(!quiet) {
369			if(verbose || ((loop % LOOP_NOTIFY) == 0)) {
370				printf("      ...loop %d keySize %u textSize %lu\n",
371					loop, (unsigned)cdsaPrivKey->KeyHeader.LogicalKeySizeInBits,
372					(unsigned long)ptext->Length);
373			}
374		}
375
376		/* encrypt with BSAFE, decrypt with CDSA */
377		crtn = buEncryptDecrypt(bsafePubKey,
378			CSSM_TRUE,		// encrypt
379			CSSM_ALGID_RSA,
380			CSSM_ALGMODE_NONE,
381			NULL,			// iv
382			cdsaPrivKey->KeyHeader.LogicalKeySizeInBits,
383			0,				// rounds
384			ptext,
385			&ctext);
386		if(crtn) {
387			return testError(quiet);
388		}
389		crtn = _cspDecrypt(cspHand,
390			CSSM_ALGID_RSA,
391			CSSM_ALGMODE_NONE,
392			CSSM_PADDING_PKCS1,
393			rsaBlinding,
394			cdsaPrivKey,
395			&ctext,
396			&rptext);
397		if(crtn) {
398			printf("***ERROR: encrypt with BSAFE, decrypt with CDSA\n");
399			return testError(quiet);
400		}
401		if(!appCompareCssmData(ptext, &rptext)) {
402			printf("***DATA MISCOMPARE: encrypt with BSAFE, decrypt with CDSA\n");
403			return testError(quiet);
404		}
405		appFreeCssmData(&ctext, CSSM_FALSE);
406		appFreeCssmData(&rptext, CSSM_FALSE);
407
408		/* encrypt with CDSA, decrypt with BSAFE */
409		crtn = cspEncrypt(cspHand,
410			CSSM_ALGID_RSA,
411			CSSM_ALGMODE_NONE,
412			CSSM_PADDING_PKCS1,
413			cdsaPubKey,
414			NULL,					// (FEE) pub key
415			0,						// effectiveKeyBits
416			0,						// rounds
417			NULL,					// IV
418			ptext,
419			&ctext,
420			CSSM_FALSE);			// mallocCtext
421		if(crtn) {
422			return testError(quiet);
423		}
424		crtn = buEncryptDecrypt(bsafePrivKey,
425			CSSM_FALSE,		// encrypt
426			CSSM_ALGID_RSA,
427			CSSM_ALGMODE_NONE,
428			NULL,			// iv
429			cdsaPrivKey->KeyHeader.LogicalKeySizeInBits,
430			0,				// rounds
431			&ctext,
432			&rptext);
433		if(crtn) {
434			printf("***ERROR: encrypt with CDSA, decrypt with BSAFE\n");
435			return testError(quiet);
436		}
437		if(!appCompareCssmData(ptext, &rptext)) {
438			printf("***DATA MISCOMPARE: encrypt with CDSA, decrypt with BSAFE\n");
439			return testError(quiet);
440		}
441		appFreeCssmData(&ctext, CSSM_FALSE);
442		appFreeCssmData(&rptext, CSSM_FALSE);
443	}
444	return CSSM_OK;
445}
446
447static int doTest(
448	CSSM_CSP_HANDLE		cspHand,
449	CSSM_ALGORITHMS		keyAlg,				// RSA/DSA
450	CSSM_ALGORITHMS		sigAlg,
451	unsigned			sigLoops,			// may be zero
452	unsigned			encrLoops,			// ditto; it will be zero for DSA
453	CSSM_BOOL			rsaBlinding,
454	CSSM_DATA_PTR		ptext,
455	unsigned			maxPtextSize,
456	uint32				keySizeInBits,		// 0 --> random per alg
457	CSSM_BOOL			pubRefKeys,
458	CSSM_BOOL			privRefKeys,
459	CSSM_BOOL			bareCsp,			// for other workarounds
460	CSSM_BOOL			quiet,
461	CSSM_BOOL			verbose)
462{
463	CSSM_KEY			cdsaGenPubKey;
464	CSSM_KEY			cdsaGenPrivKey;		// only used to create bsafeDerivePrivKey
465	CSSM_KEY			cdsaTempKey;		// raw key if privRefKeys true
466	CSSM_KEY			cdsaDerivePrivKey;	// same as bsafeGenPrivKey
467	BU_KEY				bsafeGenPubKey;
468	BU_KEY				bsafeGenPrivKey;	// only used to create cdsaDerivePrivKey
469	BU_KEY				bsafeDerivePrivKey;	// same as cdsaGenPrivKey
470	unsigned			actKeySizeBits;
471	CSSM_RETURN			crtn;
472	int					rtn;
473
474	if(!keySizeInBits) {
475		/* random key size */
476		actKeySizeBits = randKeySizeBits(keyAlg, OT_Encrypt);
477	}
478	else {
479		/* caller/user specified */
480		actKeySizeBits = keySizeInBits;
481	}
482	if(verbose) {
483		printf("   ...generating %s key pair, keySize %d bits...\n",
484			algToStr(keyAlg), actKeySizeBits);
485	}
486
487	/*
488     * Generate two keypairs
489	 */
490	if(keyAlg == CSSM_ALGID_DSA) {
491		CSSM_BOOL doGenParams;
492
493		if(bareCsp || CSPDL_DSA_GEN_PARAMS) {
494			doGenParams = CSSM_TRUE;
495		}
496		else {
497			/* CSPDL - no gen params */
498			doGenParams = CSSM_FALSE;
499		}
500		crtn = cspGenDSAKeyPair(cspHand,
501			"foo",
502			3,
503			actKeySizeBits,
504			&cdsaGenPubKey,
505			pubRefKeys,
506			CSSM_KEYUSE_ANY,
507			CSSM_KEYBLOB_RAW_FORMAT_NONE,
508			&cdsaGenPrivKey,
509			privRefKeys,
510			CSSM_KEYUSE_SIGN,
511			CSSM_KEYBLOB_RAW_FORMAT_NONE,
512			doGenParams,		// genParams
513			NULL);				// params
514	}
515	else {
516		crtn = cspGenKeyPair(cspHand,
517			keyAlg,
518			"foo",
519			3,
520			actKeySizeBits,
521			&cdsaGenPubKey,
522			pubRefKeys,
523			CSSM_KEYUSE_ANY,
524			CSSM_KEYBLOB_RAW_FORMAT_NONE,
525			&cdsaGenPrivKey,
526			privRefKeys,
527			CSSM_KEYUSE_ANY,
528			CSSM_KEYBLOB_RAW_FORMAT_NONE,
529			CSSM_FALSE);					// genSeed not used
530	}
531	if(crtn) {
532		return testError(quiet);
533	}
534	crtn = buGenKeyPair(actKeySizeBits,
535		keyAlg,
536		&bsafeGenPubKey,
537		&bsafeGenPrivKey);
538	if(crtn) {
539		return testError(quiet);
540	}
541
542	/*
543	 * Convert private keys to other library.
544	 * NOTE: the reason we're only converting private keys is solely due to the
545	 * fact that BSAFE does not handle PKCS1 formatted public key blobs. Very odd.
546	 * But it's too much of a pain to re-implement that wheel here, and SSL and
547	 * cert handling in general verify the CSP's PKCS1-style public key handling.
548	 */
549	if(privRefKeys) {
550		/* first generate a temporary raw CDSA key */
551		crtn = buBsafePrivKeyToCdsa(keyAlg,
552			actKeySizeBits,
553			bsafeGenPrivKey,
554			&cdsaTempKey);
555		if(crtn) {
556			return testError(quiet);
557		}
558
559		/* convert it to the ref key we'll actually use */
560		crtn = cspRawKeyToRef(cspHand, &cdsaTempKey, &cdsaDerivePrivKey);
561		cspFreeKey(cspHand, &cdsaTempKey);
562	}
563	else {
564		crtn = buBsafePrivKeyToCdsa(keyAlg,
565			actKeySizeBits,
566			bsafeGenPrivKey,
567			&cdsaDerivePrivKey);
568	}
569	if(crtn) {
570		return testError(quiet);
571	}
572	if(privRefKeys) {
573		/* we have a CDSA priv ref key; convert it to raw format */
574		crtn = cspRefKeyToRaw(cspHand, &cdsaGenPrivKey, &cdsaTempKey);
575		if(crtn) {
576			return testError(quiet);
577		}
578		/* now convert it to BSAFE */
579		crtn = buCdsaPrivKeyToBsafe(&cdsaTempKey, &bsafeDerivePrivKey);
580		cspFreeKey(cspHand, &cdsaTempKey);
581	}
582	else {
583		crtn = buCdsaPrivKeyToBsafe(&cdsaGenPrivKey, &bsafeDerivePrivKey);
584	}
585	if(crtn) {
586		return testError(quiet);
587	}
588
589	if(sigLoops) {
590		rtn = sigTest(cspHand,
591			sigLoops,
592			bsafeDerivePrivKey,
593			&cdsaGenPubKey,
594			&cdsaDerivePrivKey,
595			bsafeGenPubKey,
596			ptext,
597			maxPtextSize,
598			sigAlg,
599			rsaBlinding,
600			quiet,
601			verbose);
602		if(rtn) {
603			return rtn;
604		}
605	}
606
607	if(encrLoops) {
608		rtn = encryptTest(cspHand,
609			encrLoops,
610			bsafeDerivePrivKey,
611			&cdsaGenPubKey,
612			&cdsaDerivePrivKey,
613			bsafeGenPubKey,
614			ptext,
615			maxPtextSize,
616			rsaBlinding,
617			quiet,
618			verbose);
619		if(rtn) {
620			return rtn;
621		}
622	}
623
624	/* free all six keys */
625	buFreeKey(bsafeGenPubKey);
626	buFreeKey(bsafeGenPrivKey);
627	buFreeKey(bsafeDerivePrivKey);
628	cspFreeKey(cspHand, &cdsaGenPubKey);
629	cspFreeKey(cspHand, &cdsaGenPrivKey);
630	cspFreeKey(cspHand, &cdsaDerivePrivKey);
631	return 0;
632}
633
634int main(int argc, char **argv)
635{
636	int					arg;
637	char				*argp;
638	unsigned			loop;
639	CSSM_DATA			ptext;
640	CSSM_CSP_HANDLE 	cspHand;
641	int					i;
642	int					rtn = 0;
643
644	/*
645	 * User-spec'd params
646	 */
647	uint32				keySizeInBits = 0;
648	unsigned			oloops = OLOOPS_DEF;
649	unsigned			sigLoops = SIG_LOOPS_DEF;
650	unsigned			encrLoops = ENC_LOOPS_DEF;
651	CSSM_BOOL			verbose = CSSM_FALSE;
652	CSSM_BOOL			quiet = CSSM_FALSE;
653	unsigned			pauseInterval = 0;
654	CSSM_BOOL			bareCsp = CSSM_TRUE;
655	CSSM_BOOL			doDSA = CSSM_TRUE;
656	CSSM_BOOL			doRSA = CSSM_TRUE;
657	CSSM_BOOL			pubRefKeys = CSSM_FALSE;
658	CSSM_BOOL			privRefKeys = CSSM_FALSE;
659
660	for(arg=1; arg<argc; arg++) {
661		argp = argv[arg];
662		switch(argp[0]) {
663			case 'a':
664				if(argp[1] != '=') {
665					usage(argv);
666				}
667				switch(argp[2]) {
668					case 'r':
669						doDSA = CSSM_FALSE;
670						break;
671					case 'd':
672						doRSA = CSSM_FALSE;
673						break;
674					default:
675						usage(argv);
676				}
677				break;
678		    case 'l':
679				oloops = atoi(&argp[2]);
680				break;
681		    case 's':
682				sigLoops = atoi(&argp[2]);
683				break;
684		    case 'e':
685				encrLoops = atoi(&argp[2]);
686				break;
687		    case 'k':
688		    	keySizeInBits = atoi(&argp[2]);
689				break;
690		    case 'v':
691		    	verbose = CSSM_TRUE;
692				break;
693			case 'r':
694				privRefKeys = CSSM_TRUE;
695				break;
696			case 'R':
697				pubRefKeys = CSSM_TRUE;
698				break;
699			case 'D':
700				bareCsp = CSSM_FALSE;
701				#if 	CSPDL_ALL_KEYS_ARE_REF
702				privRefKeys = CSSM_TRUE;
703				pubRefKeys = CSSM_TRUE;
704				#endif
705				break;
706		    case 'E':
707		    	sigLoops = 0;
708				break;
709			case 'S':
710				encrLoops = 0;
711				break;
712		    case 'q':
713		    	quiet = CSSM_TRUE;
714				break;
715		    case 'p':
716		    	pauseInterval = atoi(&argp[2]);;
717				break;
718		    case 'h':
719		    default:
720				usage(argv);
721		}
722	}
723	ptext.Data = (uint8 *)CSSM_MALLOC(MAX_TEXT_SIZE);
724	if(ptext.Data == NULL) {
725		printf("Insufficient heap space\n");
726		exit(1);
727	}
728	/* ptext length set in inner test loops */
729
730	printf("Starting asymCompat; args: ");
731	for(i=1; i<argc; i++) {
732		printf("%s ", argv[i]);
733	}
734	printf("\n");
735	cspHand = cspDlDbStartup(bareCsp, NULL);
736	if(cspHand == 0) {
737		exit(1);
738	}
739	if(pauseInterval) {
740		fpurge(stdin);
741		printf("Top of test; hit CR to proceed: ");
742		getchar();
743	}
744	for(loop=1; ; loop++) {
745		if(!quiet) {
746			if(verbose || ((loop % LOOP_NOTIFY) == 0)) {
747				printf("...oloop %d\n", loop);
748			}
749		}
750
751		if(doRSA) {
752			CSSM_ALGORITHMS	sigAlg;
753			if(loop & 1) {
754				sigAlg = CSSM_ALGID_SHA1WithRSA;
755			}
756			else {
757				sigAlg = CSSM_ALGID_MD5WithRSA;
758			}
759
760			/* enable RSA blinding on half the loops for RSA */
761			CSSM_BOOL rsaBlinding = CSSM_FALSE;
762			if(loop & 2) {
763				rsaBlinding = CSSM_TRUE;
764			}
765
766			rtn = doTest(cspHand,
767				CSSM_ALGID_RSA,
768				sigAlg,
769				sigLoops,
770				encrLoops,
771				rsaBlinding,
772				&ptext,
773				MAX_TEXT_SIZE,
774				keySizeInBits,
775				pubRefKeys,
776				privRefKeys,
777				bareCsp,
778				quiet,
779				verbose);
780			if(rtn) {
781				break;
782			}
783		}
784		if(doDSA) {
785			rtn = doTest(cspHand,
786				CSSM_ALGID_DSA,
787				CSSM_ALGID_SHA1WithDSA,
788				sigLoops,
789				0,					// encrLoops - none for DSA
790				CSSM_FALSE,			// blinding
791				&ptext,
792				MAX_TEXT_SIZE,
793				keySizeInBits,
794				pubRefKeys,
795				privRefKeys,
796				bareCsp,
797				quiet,
798				verbose);
799			if(rtn) {
800				break;
801			}
802		}
803		if(oloops && (loop == oloops)) {
804			break;
805		}
806		if(pauseInterval && (loop % pauseInterval) == 0) {
807			fpurge(stdin);
808			printf("hit CR to proceed: ");
809			getchar();
810		}
811	}
812
813	cspShutdown(cspHand, bareCsp);
814	if(pauseInterval) {
815		fpurge(stdin);
816		printf("ModuleDetach/Unload complete; hit CR to exit: ");
817		getchar();
818	}
819	if((rtn == 0) && !quiet) {
820		printf("%s test complete\n", argv[0]);
821	}
822	CSSM_FREE(ptext.Data);
823	return rtn;
824}
825
826
827