1/* Copyright (c) 1997,2003-2006,2008 Apple Inc.
2 *
3 * badsig.c - Verify bad signature detect, CDSA version.
4 *
5 * Revision History
6 * ----------------
7 *   4 May 2000 Doug Mitchell
8 *		Ported to X/CDSA2.
9 *  28 Apr 1998	Doug Mitchell at Apple
10 *		Ported to CDSA 1.2, new Apple CSP.
11 *  15 Aug 1997	Doug Mitchell at Apple
12 *		Ported from CryptKit ObjC version
13 *  26 Aug 1996	Doug Mitchell at NeXT
14 *		Created.
15 */
16/*
17 * text size =       {random, from 100 bytes to 1 megabyte, in
18 *                   geometrical steps, i.e. the number of
19 *                   bytes would be 10^r, where r is random out of
20 *                   {2,3,4,5,6}, plus a random integer in {0,..99}};
21 *
22 * for loop_count
23 *     text contents = {random data, random size as specified above};
24 *     generate key pair;
25 *     generate signature, validate;
26 *     for various bytes of ptext {
27 *        corrupt text byte;
28 *        verify bad signature;
29 *        restore corrupted byte;
30 *     }
31 *  }
32 */
33
34#include <stdlib.h>
35#include <stdio.h>
36#include <time.h>
37#include <string.h>
38#include <Security/cssm.h>
39#include "cspwrap.h"
40#include <Security/cssm.h>
41#include "cspwrap.h"
42#include "common.h"
43#include "cspdlTesting.h"
44
45#define USAGE_NAME		"noUsage"
46#define USAGE_NAME_LEN	(strlen(USAGE_NAME))
47
48/*
49 * Defaults.
50 */
51#define LOOPS_DEF			10
52#define MIN_EXP				2		/* for data size 10**exp */
53#define DEFAULT_MAX_EXP		2
54#define MAX_EXP				5
55#define INCR_DEFAULT		0		/* munge every incr bytes - zero means
56									 * "adjust per ptext size" */
57#define FEE_PASSWD_LEN		32		/* private data length in bytes, FEE only */
58
59
60/*
61 * Enumerate algs our own way to allow iteration.
62 */
63#define ALG_FEE_MD5			1
64#define ALG_FEE_SHA1		2
65#define ALG_ECDSA			3
66#define ALG_ANSI_ECDSA		4
67#define ALG_RSA				5
68#define ALG_DSA				6
69#define ALG_RAW_RSA_SHA1	7
70#define ALG_RAW_DSA_SHA1	8
71#define ALG_RSA_SHA224		9
72#define ALG_RSA_SHA256		10
73#define ALG_RSA_SHA384		11
74#define ALG_RSA_SHA512		12
75#define ALG_ECDSA_SHA256	13
76#define ALG_ECDSA_SHA384	14
77#define ALG_ECDSA_SHA512	15
78
79
80#define ALG_FIRST			ALG_FEE_MD5
81#define ALG_LAST			ALG_ECDSA_SHA512
82#define MAX_DATA_SIZE		(100000 + 100)	/* bytes */
83
84static void usage(char **argv)
85{
86	printf("usage: %s [options]\n", argv[0]);
87	printf("   Options:\n");
88	printf("   a=algorithm (f=FEE/MD5; F=FEE/SHA1; e=ECDSA; r=RSA; d=DSA; R=raw RSA; \n");
89	printf("       D=raw DSA; 2=RSA/SHA224; 6=RSA/SHA256; 3=RSA/SHA384; 5=RSA/SHA512; default=all)\n");
90	printf("       E=ECDSA/ANSI; 7=ECDSA/SHA256; 8=ECDSA/SHA384; 9=ECDSA/512; default=all\n");
91	printf("   l=loops (default=%d; 0=forever)\n", LOOPS_DEF);
92	printf("   n=minExp (default=%d)\n", MIN_EXP);
93	printf("   x=maxExp (default=%d, max=%d)\n", DEFAULT_MAX_EXP, MAX_EXP);
94	printf("   k=keySize (r=random; default fixed per algorithm)\n");
95	printf("   i=increment (default=%d)\n", INCR_DEFAULT);
96	printf("   R(ef keys only)\n");
97	printf("   p=pauseInterval (default=0, no pause)\n");
98	printf("   P=primeType (m=Mersenne, f=FEE, g=general; FEE only)\n");
99	printf("   C=curveType (m=Montgomery, w=Weierstrass, g=general; FEE only)\n");
100	printf("   D (CSP/DL; default = bare CSP)\n");
101	printf("   v(erbose)\n");
102	printf("   q(uiet)\n");
103	printf("   h(elp)\n");
104	exit(1);
105}
106
107#define LOG_FREQ	20
108
109static int doTest(CSSM_CSP_HANDLE cspHand,
110	CSSM_ALGORITHMS sigAlg,		// CSSM_ALGID_xxx signature algorithm
111	CSSM_ALGORITHMS keyGenAlg,
112	CSSM_DATA_PTR ptext,
113	CSSM_BOOL verbose,
114	CSSM_BOOL quiet,
115	CSSM_BOOL randKeySize,
116	uint32 keySize,
117	unsigned incr,
118	CSSM_BOOL pubIsRef,
119	CSSM_KEYBLOB_FORMAT pubFormat,
120	CSSM_BOOL privIsRef,
121	CSSM_KEYBLOB_FORMAT privFormat,
122	CSSM_BOOL stagedSign,
123	CSSM_BOOL stagedVerify,
124	CSSM_BOOL genSeed,
125	uint32 primeType,		// CSSM_FEE_PRIME_TYPE_xxx, FEE only
126	uint32 curveType,		// CSSM_FEE_CURVE_TYPE_xxx, FEE only
127	CSSM_BOOL genParams)	// DSA only
128{
129	CSSM_KEY		pubKey;
130	CSSM_KEY		privKey;
131	CSSM_DATA 		sig = {0, NULL};
132	unsigned		length;
133	unsigned		byte;
134	unsigned char	*data;
135	unsigned char	origData;
136	unsigned char	bits;
137	int				rtn = 0;
138	CSSM_RETURN		crtn;
139	unsigned		loop = 0;
140
141	if(keyGenAlg == CSSM_ALGID_FEE) {
142		uint8 			passwd[FEE_PASSWD_LEN];
143		CSSM_DATA		pwdData = {FEE_PASSWD_LEN, passwd};
144		CSSM_DATA_PTR	pwdDataPtr;
145
146		if(randKeySize) {
147			/* random params for this op */
148			randFeeKeyParams(sigAlg, &keySize, &primeType, &curveType);
149		}
150		/* else use caller's size, primeType, curveType */
151
152		if(genSeed) {
153			simpleGenData(&pwdData, FEE_PASSWD_LEN, FEE_PASSWD_LEN);
154			pwdDataPtr = &pwdData;
155		}
156		else {
157			pwdDataPtr = NULL;
158		}
159		if(verbose) {
160			printf("  key size %u  primeType %s  curveType %s\n",
161				(unsigned)keySize, primeTypeStr(primeType), curveTypeStr(curveType));
162		}	/* verbose */
163		rtn = cspGenFEEKeyPair(cspHand,
164				USAGE_NAME,
165				USAGE_NAME_LEN,
166				keySize,
167				primeType,
168				curveType,
169				&pubKey,
170				pubIsRef,
171				CSSM_KEYUSE_VERIFY,
172				pubFormat,
173				&privKey,
174				privIsRef,
175				CSSM_KEYUSE_SIGN,
176				privFormat,
177				pwdDataPtr);
178	}	/* FEE */
179	else {
180		if(randKeySize) {
181			keySize = randKeySizeBits(keyGenAlg, OT_Sign);
182		}
183		if(verbose) {
184			printf("  key size %u\n", (unsigned)keySize);
185		}
186		if(keyGenAlg == CSSM_ALGID_DSA) {
187			rtn = cspGenDSAKeyPair(cspHand,
188				USAGE_NAME,
189				USAGE_NAME_LEN,
190				keySize,
191				&pubKey,
192				pubIsRef,
193				CSSM_KEYUSE_VERIFY,
194				pubFormat,
195				&privKey,
196				privIsRef,
197				CSSM_KEYUSE_SIGN,
198				privFormat,
199				genParams,
200				NULL);
201		}
202		else {
203			rtn = cspGenKeyPair(cspHand,
204				keyGenAlg,
205				USAGE_NAME,
206				USAGE_NAME_LEN,
207				keySize,
208				&pubKey,
209				pubIsRef,
210				CSSM_KEYUSE_VERIFY,
211				pubFormat,
212				&privKey,
213				privIsRef,
214				CSSM_KEYUSE_SIGN,
215				privFormat,
216				genSeed);
217		}
218	}
219	if(rtn) {
220		rtn = testError(quiet);
221		goto abort;
222	}
223	if(stagedSign) {
224		crtn = cspStagedSign(cspHand,
225			sigAlg,
226			&privKey,
227			ptext,
228			CSSM_TRUE,			// multi
229			&sig);
230	}
231	else {
232		crtn = cspSign(cspHand,
233			sigAlg,
234			&privKey,
235			ptext,
236			&sig);
237	}
238	if(crtn) {
239		rtn = 1;
240		goto abort;
241	}
242	if(stagedVerify) {
243		crtn = cspStagedSigVerify(cspHand,
244			sigAlg,
245			&pubKey,
246			ptext,
247			&sig,
248			CSSM_TRUE,			// multi
249			CSSM_OK);
250	}
251	else {
252		crtn = cspSigVerify(cspHand,
253			sigAlg,
254			&pubKey,
255			ptext,
256			&sig,
257			CSSM_OK);
258	}
259	if(crtn) {
260		printf("**Unexpected BAD signature\n");
261		return testError(quiet);
262	}
263	data = (unsigned char *)ptext->Data;
264	length = ptext->Length;
265	for(byte=0; byte<length; byte += incr) {
266		if(verbose && ((loop++ % LOG_FREQ) == 0)) {
267			printf("  ..byte %d\n", byte);
268		}
269		origData = data[byte];
270		/*
271		 * Generate random non-zero byte
272		 */
273		do {
274			bits = genRand(1, 0xff) & 0xff;
275		} while(bits == 0);
276		data[byte] ^= bits;
277		if(stagedVerify) {
278			crtn = cspStagedSigVerify(cspHand,
279				sigAlg,
280				&pubKey,
281				ptext,
282				&sig,
283				CSSM_TRUE,			// multi
284				CSSMERR_CSP_VERIFY_FAILED);		// expect failure
285		}
286		else {
287			crtn = cspSigVerify(cspHand,
288				sigAlg,
289				&pubKey,
290				ptext,
291				&sig,
292				CSSMERR_CSP_VERIFY_FAILED);
293		}
294		if(crtn) {
295			return testError(quiet);
296		}
297		data[byte] = origData;
298	}
299abort:
300	/* free/delete keys */
301	if(cspFreeKey(cspHand, &privKey)) {
302		printf("Error freeing privKey\n");
303		rtn = 1;
304	}
305	if(cspFreeKey(cspHand, &pubKey)) {
306		printf("Error freeing pubKey\n");
307		rtn = 1;
308	}
309	CSSM_FREE(sig.Data);
310	return rtn;
311}
312
313int main(int argc, char **argv)
314{
315	int					arg;
316	char				*argp;
317	unsigned			loop;
318	CSSM_DATA			ptext;
319	CSSM_CSP_HANDLE 	CSPHandle;
320	CSSM_BOOL			pubIsRef = CSSM_TRUE;
321	CSSM_BOOL			privIsRef = CSSM_TRUE;
322	CSSM_BOOL			stagedSign;
323	CSSM_BOOL 			stagedVfy;
324	const char 			*algStr;
325	unsigned			actualIncr;
326	CSSM_ALGORITHMS		sigAlg;			// CSSM_ALGID_xxx
327	CSSM_ALGORITHMS 	keyGenAlg;
328	unsigned			currAlg;		// ALG_xxx
329	int					i;
330	int					rtn = 0;
331	CSSM_BOOL			genSeed;		// for FEE
332	CSSM_BOOL			genParams;		// for DSA
333	CSSM_KEYBLOB_FORMAT	pubFormat = 0;
334	CSSM_KEYBLOB_FORMAT privFormat = 0;
335	const char			*pubFormStr = "none";
336	const char			*privFormStr = "none";
337
338	/*
339	 * User-spec'd params
340	 */
341	unsigned	loops = LOOPS_DEF;
342	CSSM_BOOL	verbose = CSSM_FALSE;
343	unsigned	minExp = MIN_EXP;
344	unsigned	maxExp = DEFAULT_MAX_EXP;
345	CSSM_BOOL	quiet = CSSM_FALSE;
346	CSSM_BOOL	randKeySize = CSSM_FALSE;
347	uint32		keySizeInBits = CSP_KEY_SIZE_DEFAULT;
348	unsigned	incr = INCR_DEFAULT;
349	unsigned	minAlg = ALG_FIRST;
350	uint32		maxAlg = ALG_LAST;
351	unsigned	pauseInterval = 0;
352	CSSM_BOOL	bareCsp = CSSM_TRUE;
353	uint32		primeType = CSSM_FEE_PRIME_TYPE_DEFAULT;	// FEE only
354	uint32		curveType = CSSM_FEE_CURVE_TYPE_DEFAULT;	// FEE only
355	CSSM_BOOL	refKeysOnly = CSSM_FALSE;
356
357	for(arg=1; arg<argc; arg++) {
358		argp = argv[arg];
359		switch(argp[0]) {
360			case 'a':
361				if(argp[1] != '=') {
362					usage(argv);
363				}
364				switch(argp[2]) {
365					case 'f':
366						minAlg = maxAlg = ALG_FEE_MD5;
367						break;
368					case 'F':
369						minAlg = maxAlg = ALG_FEE_SHA1;
370						break;
371					case 'e':
372						minAlg = maxAlg = ALG_ECDSA;
373						break;
374					case 'E':
375						minAlg = maxAlg = ALG_ANSI_ECDSA;
376						break;
377					case '7':
378						minAlg = maxAlg = ALG_ECDSA_SHA256;
379						break;
380					case '8':
381						minAlg = maxAlg = ALG_ECDSA_SHA384;
382						break;
383					case '9':
384						minAlg = maxAlg = ALG_ECDSA_SHA512;
385						break;
386					case 'r':
387						minAlg = maxAlg = ALG_RSA;
388						break;
389					case 'd':
390						minAlg = maxAlg = ALG_DSA;
391						break;
392					case 'R':
393						minAlg = maxAlg = ALG_RAW_RSA_SHA1;
394						break;
395					case 'D':
396						minAlg = maxAlg = ALG_RAW_DSA_SHA1;
397						break;
398					case '2':
399						minAlg = maxAlg = ALG_RSA_SHA224;
400						break;
401					case '6':
402						minAlg = maxAlg = ALG_RSA_SHA256;
403						break;
404					case '3':
405						minAlg = maxAlg = ALG_RSA_SHA384;
406						break;
407					case '5':
408						minAlg = maxAlg = ALG_RSA_SHA512;
409						break;
410					case 'a':
411						minAlg = ALG_FIRST;
412						maxAlg = ALG_LAST;
413						break;
414					default:
415						usage(argv);
416				}
417				break;
418		    case 'l':
419				loops = atoi(&argp[2]);
420				break;
421		    case 'n':
422				minExp = atoi(&argp[2]);
423				break;
424		    case 'x':
425				maxExp = atoi(&argp[2]);
426				if(maxExp > MAX_EXP) {
427					usage(argv);
428				}
429				break;
430			case 'k':
431				if(argp[2] == 'r') {
432					randKeySize = CSSM_TRUE;
433				}
434				else {
435					keySizeInBits = atoi(&argp[2]);
436				}
437				break;
438		    case 'i':
439				incr = atoi(&argp[2]);
440				break;
441		    case 'p':
442				pauseInterval = atoi(&argp[2]);
443				break;
444		    case 'R':
445				refKeysOnly = CSSM_TRUE;
446				break;
447			case 'C':
448				switch(argp[2]) {
449					case 'm':
450						curveType = CSSM_FEE_CURVE_TYPE_MONTGOMERY;
451						break;
452					case 'w':
453						curveType = CSSM_FEE_CURVE_TYPE_WEIERSTRASS;
454						break;
455					default:
456						usage(argv);
457				}
458				break;
459			case 'P':
460				switch(argp[2]) {
461					case 'm':
462						primeType = CSSM_FEE_PRIME_TYPE_MERSENNE;
463						break;
464					case 'f':
465						primeType = CSSM_FEE_PRIME_TYPE_FEE;
466						break;
467					case 'g':
468						primeType = CSSM_FEE_PRIME_TYPE_GENERAL;
469						break;
470					default:
471						usage(argv);
472				}
473				break;
474			case 'D':
475				bareCsp = CSSM_FALSE;
476				#if CSPDL_ALL_KEYS_ARE_REF
477				refKeysOnly = CSSM_TRUE;
478				#endif
479				break;
480		    case 'v':
481		    	verbose = CSSM_TRUE;
482				break;
483		    case 'q':
484		    	quiet = CSSM_TRUE;
485				break;
486		    case 'h':
487		    default:
488				usage(argv);
489		}
490	}
491	ptext.Data = (uint8 *)CSSM_MALLOC(MAX_DATA_SIZE);
492	/* length set in test loop */
493	if(ptext.Data == NULL) {
494		printf("Insufficient heap\n");
495		exit(1);
496	}
497	printf("Starting badsig; args: ");
498	for(i=1; i<argc; i++) {
499		printf("%s ", argv[i]);
500	}
501	printf("\n");
502	CSPHandle = cspDlDbStartup(bareCsp, NULL);
503	if(CSPHandle == 0) {
504		exit(1);
505	}
506	for(currAlg=minAlg; currAlg<=maxAlg; currAlg++) {
507		switch(currAlg) {
508			case ALG_FEE_MD5:
509				sigAlg = CSSM_ALGID_FEE_MD5;
510				algStr = "FEE/MD5";
511				keyGenAlg = CSSM_ALGID_FEE;
512				break;
513			case ALG_FEE_SHA1:
514				sigAlg = CSSM_ALGID_FEE_SHA1;
515				algStr = "FEE/SHA1";
516				keyGenAlg = CSSM_ALGID_FEE;
517				break;
518			case ALG_ECDSA:
519				sigAlg = CSSM_ALGID_SHA1WithECDSA;
520				algStr = "ECDSA";
521				keyGenAlg = CSSM_ALGID_FEE;
522				break;
523			case ALG_ANSI_ECDSA:
524				sigAlg = CSSM_ALGID_SHA1WithECDSA;
525				algStr = "ANSI_ECDSA";
526				keyGenAlg = CSSM_ALGID_ECDSA;
527				break;
528			case ALG_ECDSA_SHA256:
529				sigAlg = CSSM_ALGID_SHA256WithECDSA;
530				algStr = "ANSI_ECDSA_SHA256";
531				keyGenAlg = CSSM_ALGID_ECDSA;
532				break;
533			case ALG_ECDSA_SHA384:
534				sigAlg = CSSM_ALGID_SHA384WithECDSA;
535				algStr = "ANSI_ECDSA_SHA384";
536				keyGenAlg = CSSM_ALGID_ECDSA;
537				break;
538			case ALG_ECDSA_SHA512:
539				sigAlg = CSSM_ALGID_SHA512WithECDSA;
540				algStr = "ANSI_ECDSA_SHA512";
541				keyGenAlg = CSSM_ALGID_ECDSA;
542				break;
543			case ALG_RSA:
544				sigAlg = CSSM_ALGID_SHA1WithRSA;
545				algStr = "RSA/SHA1";
546				keyGenAlg = CSSM_ALGID_RSA;
547				break;
548			case ALG_DSA:
549				sigAlg = CSSM_ALGID_SHA1WithDSA;
550				algStr = "DSA";
551				keyGenAlg = CSSM_ALGID_DSA;
552				break;
553			case ALG_RAW_RSA_SHA1:
554				sigAlg = CSSM_ALGID_SHA1;
555				algStr = "Raw RSA/SHA1";
556				keyGenAlg = CSSM_ALGID_RSA;
557				break;
558			case ALG_RAW_DSA_SHA1:
559				sigAlg = CSSM_ALGID_DSA;
560				algStr = "Raw DSA/SHA1";
561				keyGenAlg = CSSM_ALGID_DSA;
562				break;
563			case ALG_RSA_SHA224:
564				sigAlg = CSSM_ALGID_SHA224WithRSA;
565				algStr = "RSA/SHA224";
566				keyGenAlg = CSSM_ALGID_RSA;
567				break;
568			case ALG_RSA_SHA256:
569				sigAlg = CSSM_ALGID_SHA256WithRSA;
570				algStr = "RSA/SHA256";
571				keyGenAlg = CSSM_ALGID_RSA;
572				break;
573			case ALG_RSA_SHA384:
574				sigAlg = CSSM_ALGID_SHA384WithRSA;
575				algStr = "RSA/SHA384";
576				keyGenAlg = CSSM_ALGID_RSA;
577				break;
578			case ALG_RSA_SHA512:
579				sigAlg = CSSM_ALGID_SHA512WithRSA;
580				algStr = "RSA/SHA512";
581				keyGenAlg = CSSM_ALGID_RSA;
582				break;
583			default:
584				printf("***BRRZAP! alg parsing needs work.\n");
585				exit(1);
586		}
587		if(!quiet) {
588			printf("Testing alg %s\n", algStr);
589		}
590		for(loop=1; ; loop++) {
591			ptext.Length = genData(ptext.Data, minExp, maxExp, DT_Random);
592			if(!quiet) {
593				printf("..loop %d text size %lu\n", loop, ptext.Length);
594			}
595			if(incr == 0) {
596				/* adjust increment as appropriate */
597				actualIncr = (ptext.Length / 50) + 1;
598			}
599			else {
600				actualIncr = incr;
601			}
602			/* mix up some ref and data keys, as well as staging */
603			if(!refKeysOnly) {
604				pubIsRef   = (loop & 1) ? CSSM_TRUE : CSSM_FALSE;
605				privIsRef  = (loop & 2) ? CSSM_TRUE : CSSM_FALSE;
606			}
607
608			/* variable alg-specific params */
609			switch(currAlg) {
610				case ALG_RAW_RSA_SHA1:
611				case ALG_RAW_DSA_SHA1:
612					/* staging not supported */
613					stagedSign = 0;
614					stagedVfy = 0;
615					break;
616				default:
617					stagedSign = (loop & 4) ? CSSM_TRUE : CSSM_FALSE;
618					stagedVfy  = (loop & 8) ? CSSM_TRUE : CSSM_FALSE;
619					break;
620			}
621			genSeed = CSSM_FALSE;
622			switch(currAlg) {
623				case ALG_FEE_MD5:
624				case ALG_FEE_SHA1:
625				case ALG_ECDSA:
626					/* FEE keys */
627					genSeed = (ptext.Data[0] & 1) ? CSSM_TRUE : CSSM_FALSE;
628					break;
629				case ALG_DSA:
630				case ALG_RAW_DSA_SHA1:
631					/* DSA */
632					if(bareCsp || CSPDL_DSA_GEN_PARAMS) {
633						/* alternate this one */
634						genParams = (ptext.Data[0] & 2) ? CSSM_TRUE : CSSM_FALSE;;
635					}
636					else {
637						/* CSPDL - no gen params */
638						genParams = CSSM_FALSE;
639					}
640					break;
641				default:
642					break;
643			}
644
645			/* random raw key formats */
646			pubFormat = CSSM_KEYBLOB_RAW_FORMAT_NONE;
647			pubFormStr = "None";
648			if(!pubIsRef) {
649				unsigned die;
650				switch(keyGenAlg) {
651					case CSSM_ALGID_FEE:
652						/* NONE, OCTET_STRING */
653						die = genRand(1,2);
654						if(die == 2) {
655							pubFormat = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
656							pubFormStr = "OctetString";
657						}
658						break;
659					case CSSM_ALGID_RSA:
660						/* NONE, PKCS1, X509, OPENSSH, OPENSSHv2 */
661						die = genRand(1, 5);
662						switch(die) {
663							case 1:
664								break;	// none/default, set above */
665							case 2:
666								pubFormat = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
667								pubFormStr = "PKCS1";
668								break;
669							case 3:
670								pubFormat = CSSM_KEYBLOB_RAW_FORMAT_X509;
671								pubFormStr = "X509";
672								break;
673							case 4:
674								pubFormat = CSSM_KEYBLOB_RAW_FORMAT_OPENSSH;
675								pubFormStr = "SSH1";
676								break;
677							case 5:
678								pubFormat = CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2;
679								pubFormStr = "SSH2";
680								break;
681						}
682						break;
683					case CSSM_ALGID_DSA:
684						/* NONE, X509, FIPS186, OPENSSHv2 */
685						die = genRand(1, 4);
686						switch(die) {
687							case 1:
688								break;	// none/default, set above */
689							case 2:
690								pubFormat = CSSM_KEYBLOB_RAW_FORMAT_X509;
691								pubFormStr = "X509";
692								break;
693							case 3:
694								pubFormat = CSSM_KEYBLOB_RAW_FORMAT_FIPS186;
695								pubFormStr = "FIPS186";
696								break;
697							case 4:
698								pubFormat = CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2;
699								pubFormStr = "SSH2";
700								break;
701						}
702						break;
703					case CSSM_ALGID_ECDSA:
704						/* no options - default is CSSM_KEYBLOB_RAW_FORMAT_NONE, X509 */
705						pubFormStr = "X509";
706						break;
707					default:
708						printf("***BRRRZAP! Key alg processing needed\n");
709						exit(1);
710				}
711			}
712			privFormat = CSSM_KEYBLOB_RAW_FORMAT_NONE;
713			privFormStr = "None";
714			if(!privIsRef) {
715				unsigned die;
716				switch(keyGenAlg) {
717					case CSSM_ALGID_FEE:
718						/* NONE, OCTET_STRING */
719						die = genRand(1,2);
720						if(die == 2) {
721							privFormat = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
722							privFormStr = "OctetString";
723						}
724						break;
725					case CSSM_ALGID_RSA:
726						/* NONE, PKCS1, PKCS8, OPENSSH */
727						die = genRand(1, 4);
728						switch(die) {
729							case 1:
730								break;	// none/default, set above */
731							case 2:
732								privFormat = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
733								privFormStr = "PKCS1";
734								break;
735							case 3:
736								privFormat = CSSM_KEYBLOB_RAW_FORMAT_PKCS8;
737								privFormStr = "PKCS8";
738								break;
739							case 4:
740								privFormat = CSSM_KEYBLOB_RAW_FORMAT_OPENSSH;
741								privFormStr = "SSH1";
742								break;
743						}
744						break;
745					case CSSM_ALGID_DSA:
746						/* NONE, FIPS186, PKCS8 */
747						die = genRand(1, 3);
748						switch(die) {
749							case 1:
750								break;	// none/default, set above */
751							case 2:
752								privFormat = CSSM_KEYBLOB_RAW_FORMAT_FIPS186;
753								privFormStr = "FIPS186";
754								break;
755							case 3:
756								privFormat = CSSM_KEYBLOB_RAW_FORMAT_PKCS8;
757								privFormStr = "PKCS8";
758								break;
759						}
760						break;
761					case CSSM_ALGID_ECDSA:
762						/* no options */
763						privFormStr = "PKCS8";
764						break;
765					default:
766						printf("***BRRRZAP! Key alg processing needed\n");
767						exit(1);
768				}
769			}
770
771			if(!quiet) {
772				printf("  pubIsRef %d  pubForm %s  privIsRef %d  privForm %s  stagedSign %d  stagedVfy %d"
773					" genSeed %d\n",
774					 (int)pubIsRef, pubFormStr, (int)privIsRef, privFormStr,
775					 (int)stagedSign, (int)stagedVfy, (int)genSeed);
776			}
777
778			if(doTest(CSPHandle,
779					sigAlg,
780					keyGenAlg,
781					&ptext,
782					verbose,
783					quiet,
784					randKeySize,
785					keySizeInBits,
786					actualIncr,
787					pubIsRef,
788					pubFormat,
789					privIsRef,
790					privFormat,
791					stagedSign,
792					stagedVfy,
793					genSeed,
794					primeType,
795					curveType,
796					genParams)) {
797				rtn = 1;
798				goto testDone;
799			}
800			if(loops && (loop == loops)) {
801				break;
802			}
803			if(pauseInterval && ((loop % pauseInterval) == 0)) {
804				char inch;
805				fpurge(stdin);
806				printf("Hit CR to proceed or q to quit: ");
807				inch = getchar();
808				if(inch == 'q') {
809					goto testDone;
810				}
811			}
812		}	/* for loop */
813	}		/* for alg */
814testDone:
815	CSSM_ModuleDetach(CSPHandle);
816	if((rtn == 0) && !quiet) {
817		printf("%s test complete\n", argv[0]);
818	}
819	return rtn;
820}
821