1/*
2 * rawSig.c - Test compatiblity of (hash+sign) ops vs. manual digest followed
3 * by raw sign.
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 "cspdlTesting.h"
15#include <string.h>
16
17/*
18 * Defaults.
19 */
20#define OLOOPS_DEF		10		/* outer loops, one key pair per loop */
21#define ILOOPS_DEF		10		/* sig loops */
22#define MAX_TEXT_SIZE	1024
23
24#define LOOP_NOTIFY		20
25
26/*
27 * Enumerate algs our own way to allow iteration.
28 */
29#define ALG_RSA_MD5			1
30#define ALG_RSA_SHA1		2
31#define ALG_RSA_MD2			3
32#define ALG_FEE_MD5			4
33#define ALG_FEE_SHA1		5
34#define ALG_ECDSA_SHA1		6
35#define ALG_DSA_SHA1		7
36#define ALG_ANSI_ECDSA_SHA1	8
37#define ALG_ECDSA_SHA256	9
38#define ALG_ECDSA_SHA384	10
39#define ALG_ECDSA_SHA512	11
40#define ALG_FIRST			ALG_RSA_MD5
41#define ALG_LAST			ALG_ECDSA_SHA512
42
43static void usage(char **argv)
44{
45	printf("usage: %s [options]\n", argv[0]);
46	printf("   Options:\n");
47	printf("   a=alg (5=RSA/MD5; 2=RSA/MD2; R=RSA/SHA1; d=DSA/SHA1; f=FEE/MD5; F=FEE/SHA1; \n");
48	printf("   e=ECDSA/SHA1; E=ANSI_ECDSA/SHA1; 7=ECDSA/SHA256; 8=ECDSA/SHA384; 9=ECDSA/512; default=all)\n");
49	printf("   l=outerloops (default=%d; 0=forever)\n", OLOOPS_DEF);
50	printf("   i=innerLoops (default=%d)\n", ILOOPS_DEF);
51	printf("   k=keySizeInBits; default is random\n");
52	printf("   p=pauseInterval (default=0, no pause)\n");
53	printf("   s(mall keys)\n");
54	printf("   D (CSP/DL; default = bare CSP)\n");
55	printf("   v(erbose)\n");
56	printf("   q(uiet)\n");
57	printf("   h(elp)\n");
58	exit(1);
59}
60
61int main(int argc, char **argv)
62{
63	int					arg;
64	char				*argp;
65	unsigned			oloop;
66	unsigned			iloop;
67	CSSM_DATA			ptext = {0, NULL};
68	CSSM_CSP_HANDLE 	cspHand;
69	int					i;
70	int					rtn = 0;
71	uint32				keySizeInBits = 0;
72	CSSM_KEY			pubKey;
73	CSSM_KEY			privKey;
74	CSSM_DATA			sig = {0, NULL};
75	CSSM_DATA			digest = {0, NULL};
76	CSSM_RETURN			crtn;
77	unsigned			currAlg;
78
79	/* current alg (e.g. ALG_FEE_SHA1) parsed to come up with these */
80	CSSM_ALGORITHMS		digestAlg;
81	CSSM_ALGORITHMS		rawSigAlg;
82	CSSM_ALGORITHMS		sigAlg;
83	CSSM_ALGORITHMS		keyGenAlg;
84	const char			*sigAlgStr;
85
86	/*
87	 * User-spec'd params
88	 */
89	CSSM_BOOL			keySizeSpec = CSSM_FALSE;
90	unsigned			oloops = OLOOPS_DEF;
91	unsigned			iloops = ILOOPS_DEF;
92	CSSM_BOOL			verbose = CSSM_FALSE;
93	CSSM_BOOL			quiet = CSSM_FALSE;
94	unsigned			pauseInterval = 0;
95	CSSM_BOOL			bareCsp = CSSM_TRUE;
96	unsigned			minAlg = ALG_FIRST;
97	uint32				maxAlg = ALG_LAST;
98	CSSM_BOOL			smallKeys = CSSM_FALSE;
99
100	for(arg=1; arg<argc; arg++) {
101		argp = argv[arg];
102		switch(argp[0]) {
103			case 'a':
104				switch(argp[2]) {
105					case 'f':
106						minAlg = maxAlg = ALG_FEE_MD5;
107						break;
108					case 'F':
109						minAlg = maxAlg = ALG_FEE_SHA1;
110						break;
111					case 'e':
112						minAlg = maxAlg = ALG_ECDSA_SHA1;
113						break;
114					case '5':
115						minAlg = maxAlg = ALG_RSA_MD5;
116						break;
117					case '2':
118						minAlg = maxAlg = ALG_RSA_MD2;
119						break;
120					case 'R':
121						minAlg = maxAlg = ALG_RSA_SHA1;
122						break;
123					case 'd':
124						minAlg = maxAlg = ALG_DSA_SHA1;
125						break;
126					case 'E':
127						minAlg = maxAlg = ALG_ANSI_ECDSA_SHA1;
128						break;
129					case '7':
130						minAlg = maxAlg = ALG_ECDSA_SHA256;
131						break;
132					case '8':
133						minAlg = maxAlg = ALG_ECDSA_SHA384;
134						break;
135					case '9':
136						minAlg = maxAlg = ALG_ECDSA_SHA512;
137						break;
138					default:
139						usage(argv);
140				}
141				break;
142		    case 'l':
143				oloops = atoi(&argp[2]);
144				break;
145		    case 'i':
146				iloops = atoi(&argp[2]);
147				break;
148		    case 'k':
149		    	keySizeInBits = atoi(&argp[2]);
150				keySizeSpec = CSSM_TRUE;
151				break;
152		    case 'v':
153		    	verbose = CSSM_TRUE;
154				break;
155			case 'D':
156				bareCsp = CSSM_FALSE;
157				break;
158		    case 'q':
159		    	quiet = CSSM_TRUE;
160				break;
161		    case 's':
162		    	smallKeys = CSSM_TRUE;
163				break;
164		    case 'p':
165		    	pauseInterval = atoi(&argp[2]);;
166				break;
167		    case 'h':
168		    default:
169				usage(argv);
170		}
171	}
172
173	ptext.Data = (uint8 *)CSSM_MALLOC(MAX_TEXT_SIZE);
174	if(ptext.Data == NULL) {
175		printf("Insufficient heap space\n");
176		exit(1);
177	}
178	/* ptext length set in inner test loop */
179
180	printf("Starting rawSig; args: ");
181	for(i=1; i<argc; i++) {
182		printf("%s ", argv[i]);
183	}
184	printf("\n");
185	cspHand = cspDlDbStartup(bareCsp, NULL);
186	if(cspHand == 0) {
187		exit(1);
188	}
189	if(pauseInterval) {
190		fpurge(stdin);
191		printf("Top of test; hit CR to proceed: ");
192		getchar();
193	}
194	for(currAlg=minAlg; currAlg<=maxAlg; currAlg++) {
195		/* get current algs */
196		switch(currAlg) {
197			case ALG_RSA_MD5:
198				digestAlg = CSSM_ALGID_MD5;
199				rawSigAlg = CSSM_ALGID_RSA;
200				sigAlg    = CSSM_ALGID_MD5WithRSA;
201				keyGenAlg = CSSM_ALGID_RSA;
202				sigAlgStr = "MD5WithRSA";
203				break;
204			case ALG_RSA_MD2:
205				digestAlg = CSSM_ALGID_MD2;
206				rawSigAlg = CSSM_ALGID_RSA;
207				sigAlg    = CSSM_ALGID_MD2WithRSA;
208				keyGenAlg = CSSM_ALGID_RSA;
209				sigAlgStr = "MD2WithRSA";
210				break;
211			case ALG_RSA_SHA1:
212				digestAlg = CSSM_ALGID_SHA1;
213				rawSigAlg = CSSM_ALGID_RSA;
214				sigAlg    = CSSM_ALGID_SHA1WithRSA;
215				keyGenAlg = CSSM_ALGID_RSA;
216				sigAlgStr = "SHA1WithRSA";
217				break;
218			case ALG_DSA_SHA1:
219				digestAlg = CSSM_ALGID_SHA1;
220				rawSigAlg = CSSM_ALGID_DSA;
221				sigAlg    = CSSM_ALGID_SHA1WithDSA;
222				keyGenAlg = CSSM_ALGID_DSA;
223				sigAlgStr = "SHA1WithDSA";
224				break;
225			case ALG_FEE_MD5:
226				digestAlg = CSSM_ALGID_MD5;
227				rawSigAlg = CSSM_ALGID_FEE;
228				sigAlg    = CSSM_ALGID_FEE_MD5;
229				keyGenAlg = CSSM_ALGID_FEE;
230				sigAlgStr = "MD5WithFEE";
231				break;
232			case ALG_FEE_SHA1:
233				digestAlg = CSSM_ALGID_SHA1;
234				rawSigAlg = CSSM_ALGID_FEE;
235				sigAlg    = CSSM_ALGID_FEE_SHA1;
236				keyGenAlg = CSSM_ALGID_FEE;
237				sigAlgStr = "SHA1WithFEE";
238				break;
239			case ALG_ECDSA_SHA1:
240				digestAlg = CSSM_ALGID_SHA1;
241				rawSigAlg = CSSM_ALGID_ECDSA;
242				sigAlg    = CSSM_ALGID_SHA1WithECDSA;
243				keyGenAlg = CSSM_ALGID_FEE;
244				sigAlgStr = "SHA1WithECDSA";
245				break;
246			case ALG_ANSI_ECDSA_SHA1:
247				digestAlg = CSSM_ALGID_SHA1;
248				rawSigAlg = CSSM_ALGID_ECDSA;
249				sigAlg    = CSSM_ALGID_SHA1WithECDSA;
250				keyGenAlg = CSSM_ALGID_ECDSA;
251				sigAlgStr = "ANSI ECDSA";
252				break;
253			case ALG_ECDSA_SHA256:
254				digestAlg = CSSM_ALGID_SHA256;
255				rawSigAlg = CSSM_ALGID_ECDSA;
256				sigAlg    = CSSM_ALGID_SHA256WithECDSA;
257				keyGenAlg = CSSM_ALGID_ECDSA;
258				sigAlgStr = "ECDSA/SHA256";
259				break;
260			case ALG_ECDSA_SHA384:
261				digestAlg = CSSM_ALGID_SHA384;
262				rawSigAlg = CSSM_ALGID_ECDSA;
263				sigAlg    = CSSM_ALGID_SHA384WithECDSA;
264				keyGenAlg = CSSM_ALGID_ECDSA;
265				sigAlgStr = "ECDSA/SHA384";
266				break;
267			case ALG_ECDSA_SHA512:
268				digestAlg = CSSM_ALGID_SHA512;
269				rawSigAlg = CSSM_ALGID_ECDSA;
270				sigAlg    = CSSM_ALGID_SHA512WithECDSA;
271				keyGenAlg = CSSM_ALGID_ECDSA;
272				sigAlgStr = "ECDSA/SHA512";
273				break;
274			default:
275				printf("BRRZAP!\n");
276				exit(1);
277		}
278		if(!quiet) {
279			printf("Testing alg %s...\n", sigAlgStr);
280		}
281		for(oloop=0; ; oloop++) {
282
283			/* key size? */
284			if(smallKeys) {
285				keySizeInBits = cspDefaultKeySize(keyGenAlg);
286			}
287			else if(!keySizeSpec) {
288				/* random key size */
289				keySizeInBits = randKeySizeBits(rawSigAlg, OT_Sign);
290			}
291
292			if(!quiet) {
293				if(verbose || ((oloop % LOOP_NOTIFY) == 0)) {
294					printf("   ...oloop %d   keySize %u\n", oloop, (unsigned)keySizeInBits);
295				}
296			}
297
298			/* generate a key pair */
299			if(currAlg == ALG_DSA_SHA1) {
300				CSSM_BOOL doGenParams;
301
302				if(bareCsp || CSPDL_DSA_GEN_PARAMS) {
303					doGenParams = CSSM_TRUE;
304				}
305				else {
306					/* CSPDL - no gen params */
307					doGenParams = CSSM_FALSE;
308				}
309				crtn = cspGenDSAKeyPair(cspHand,
310					"foo",
311					3,
312					keySizeInBits,
313					&pubKey,
314					CSSM_TRUE,				// all keys ref for speed
315					CSSM_KEYUSE_VERIFY,
316					CSSM_KEYBLOB_RAW_FORMAT_NONE,
317					&privKey,
318					CSSM_TRUE,
319					CSSM_KEYUSE_SIGN,
320					CSSM_KEYBLOB_RAW_FORMAT_NONE,
321					doGenParams,			// genParams
322					NULL);					// params
323			}
324			else {
325				crtn = cspGenKeyPair(cspHand,
326					keyGenAlg,
327					"foo",
328					3,
329					keySizeInBits,
330					&pubKey,
331					CSSM_TRUE,						// all keys ref for speed
332					CSSM_KEYUSE_VERIFY,
333					CSSM_KEYBLOB_RAW_FORMAT_NONE,
334					&privKey,
335					CSSM_TRUE,
336					CSSM_KEYUSE_SIGN,
337					CSSM_KEYBLOB_RAW_FORMAT_NONE,
338					CSSM_FALSE);					// genSeed not used
339			}
340			if(crtn) {
341				return testError(quiet);
342			}
343
344			for(iloop=0; iloop<iloops; iloop++) {
345				CSSM_CC_HANDLE		sigHand;
346
347				/* new plaintext each inner loop */
348				simpleGenData(&ptext, 1, MAX_TEXT_SIZE);
349				if(!quiet) {
350					if(verbose || ((iloop % LOOP_NOTIFY) == 0)) {
351						printf("      ...iloop %d  text size %lu\n",
352							iloop, ptext.Length);
353					}
354				}
355
356				/*** phase 1 ***/
357
358				/* digest+sign */
359				crtn = cspStagedSign(cspHand,
360					sigAlg,
361					&privKey,
362					&ptext,
363					CSSM_TRUE,			// multiUpdates
364					&sig);
365				if(crtn && testError(quiet)) {
366					goto abort;
367				}
368
369				/* manual digest */
370				crtn = cspStagedDigest(cspHand,
371					digestAlg,
372					CSSM_FALSE,			// mallocDigest
373					CSSM_TRUE,			// multiUpdates
374					&ptext,
375					&digest);
376				if(crtn && testError(quiet)) {
377					goto abort;
378				}
379
380				/* raw verify of the digest */
381				crtn = CSSM_CSP_CreateSignatureContext(cspHand,
382					rawSigAlg,
383					NULL,				// passPhrase
384					&pubKey,
385					&sigHand);
386				if(crtn) {
387					printError("CSSM_CSP_CreateSignatureContext (1)", crtn);
388					return crtn;
389				}
390				crtn = CSSM_VerifyData(sigHand,
391					&digest,
392					1,
393					digestAlg,
394					&sig);
395				if(crtn) {
396					printError("CSSM_VerifyData(raw)", crtn);
397					if(testError(quiet)) {
398						goto abort;
399					}
400				}
401
402				/* free resources - reuse the digest for raw sign */
403				appFreeCssmData(&sig, CSSM_FALSE);
404				CSSM_DeleteContext(sigHand);
405
406				/*** phase 2 ***/
407
408				/* raw sign the digest */
409				crtn = CSSM_CSP_CreateSignatureContext(cspHand,
410					rawSigAlg,
411					NULL,				// passPhrase
412					&privKey,
413					&sigHand);
414				if(crtn) {
415					printError("CSSM_CSP_CreateSignatureContext (2)", crtn);
416					return crtn;
417				}
418				crtn = CSSM_SignData(sigHand,
419					&digest,
420					1,
421					digestAlg,
422					&sig);
423				if(crtn) {
424					printError("CSSM_SignData(raw)", crtn);
425					if(testError(quiet)) {
426						goto abort;
427					}
428				}
429
430				/* all-in-one verify */
431				crtn = cspStagedSigVerify(cspHand,
432					sigAlg,
433					&pubKey,
434					&ptext,
435					&sig,
436					CSSM_TRUE,			// multiUpdates
437					CSSM_OK);
438				if(crtn && testError(quiet)) {
439					goto abort;
440				}
441
442				/* clean up */
443				appFreeCssmData(&sig, CSSM_FALSE);
444				appFreeCssmData(&digest, CSSM_FALSE);
445				CSSM_DeleteContext(sigHand);
446			}	/* end of inner loop */
447
448			/* free keys */
449			cspFreeKey(cspHand, &pubKey);
450			cspFreeKey(cspHand, &privKey);
451
452			if(oloops && (oloop == oloops)) {
453				break;
454			}
455			if(pauseInterval && ((oloop % pauseInterval) == 0)) {
456				fpurge(stdin);
457				printf("hit CR to proceed: ");
458				getchar();
459			}
460		}	/* oloop */
461	}		/* for alg */
462
463abort:
464	cspShutdown(cspHand, bareCsp);
465	if(pauseInterval) {
466		fpurge(stdin);
467		printf("ModuleDetach/Unload complete; hit CR to exit: ");
468		getchar();
469	}
470	if((rtn == 0) && !quiet) {
471		printf("%s test complete\n", argv[0]);
472	}
473	CSSM_FREE(ptext.Data);
474	return rtn;
475}
476
477
478