1/*
2 * rawRsaSig.c - Test compatiblity of CSSM_ALGID_{SHA1,MD5}WithRSA and
3 * manual digest followed by raw RSA 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 <string.h>
15
16/*
17 * Defaults.
18 */
19#define OLOOPS_DEF		10		/* outer loops, one key pair per loop */
20#define ILOOPS_DEF		10		/* sig loops */
21#define MAX_TEXT_SIZE	1024
22
23#define LOOP_NOTIFY		20
24#define DO_MULTI_UPDATE	CSSM_TRUE
25
26static void usage(char **argv)
27{
28	printf("usage: %s [options]\n", argv[0]);
29	printf("   Options:\n");
30	printf("   a=alg (r=RSA, d=DSA; default=RSA)\n");
31	printf("   l=outerloops (default=%d; 0=forever)\n", OLOOPS_DEF);
32	printf("   i=innerLoops (default=%d)\n", ILOOPS_DEF);
33	printf("   k=keySizeInBits; default is random\n");
34	printf("   p=pauseInterval (default=0, no pause)\n");
35	printf("   D (CSP/DL; default = bare CSP)\n");
36	printf("   v(erbose)\n");
37	printf("   q(uiet)\n");
38	printf("   h(elp)\n");
39	exit(1);
40}
41
42int main(int argc, char **argv)
43{
44	int					arg;
45	char				*argp;
46	unsigned			oloop;
47	unsigned			iloop;
48	CSSM_DATA			ptext = {0, NULL};
49	CSSM_CSP_HANDLE 	cspHand;
50	int					i;
51	int					rtn = 0;
52	uint32				keySizeInBits = 0;
53	CSSM_KEY			pubKey;
54	CSSM_KEY			privKey;
55	CSSM_DATA			sig = {0, NULL};
56	CSSM_DATA			digest = {0, NULL};
57	CSSM_RETURN			crtn;
58	const char			*digestStr;
59
60	/*
61	 * User-spec'd params
62	 */
63	CSSM_BOOL			keySizeSpec = CSSM_FALSE;
64	unsigned			oloops = OLOOPS_DEF;
65	unsigned			iloops = ILOOPS_DEF;
66	CSSM_BOOL			verbose = CSSM_FALSE;
67	CSSM_BOOL			quiet = CSSM_FALSE;
68	unsigned			pauseInterval = 0;
69	CSSM_BOOL			bareCsp = CSSM_TRUE;
70	CSSM_ALGORITHMS		rawSigAlg = CSSM_ALGID_RSA;
71
72	for(arg=1; arg<argc; arg++) {
73		argp = argv[arg];
74		switch(argp[0]) {
75			case 'a':
76				switch(argp[2]) {
77					case 'r':
78						rawSigAlg = CSSM_ALGID_RSA;
79						break;
80					case 'd':
81						rawSigAlg = CSSM_ALGID_DSA;
82						break;
83					default:
84						usage(argv);
85				}
86				break;
87		    case 'l':
88				oloops = atoi(&argp[2]);
89				break;
90		    case 'i':
91				iloops = atoi(&argp[2]);
92				break;
93		    case 'k':
94		    	keySizeInBits = atoi(&argp[2]);
95				keySizeSpec = CSSM_TRUE;
96				break;
97		    case 'v':
98		    	verbose = CSSM_TRUE;
99				break;
100			case 'D':
101				bareCsp = CSSM_FALSE;
102				break;
103		    case 'q':
104		    	quiet = CSSM_TRUE;
105				break;
106		    case 'p':
107		    	pauseInterval = atoi(&argp[2]);;
108				break;
109		    case 'h':
110		    default:
111				usage(argv);
112		}
113	}
114
115	ptext.Data = (uint8 *)CSSM_MALLOC(MAX_TEXT_SIZE);
116	if(ptext.Data == NULL) {
117		printf("Insufficient heap space\n");
118		exit(1);
119	}
120	/* ptext length set in inner test loop */
121
122	printf("Starting rawRsaSig; args: ");
123	for(i=1; i<argc; i++) {
124		printf("%s ", argv[i]);
125	}
126	printf("\n");
127	cspHand = cspDlDbStartup(bareCsp, NULL);
128	if(cspHand == 0) {
129		exit(1);
130	}
131	if(pauseInterval) {
132		fpurge(stdin);
133		printf("Top of test; hit CR to proceed: ");
134		getchar();
135	}
136	for(oloop=0; ; oloop++) {
137
138		/* key size? */
139		if(!keySizeSpec) {
140			/* random key size */
141			keySizeInBits = randKeySizeBits(rawSigAlg, OT_Sign);
142		}
143
144		if(!quiet) {
145			if(verbose || ((oloop % LOOP_NOTIFY) == 0)) {
146				printf("...oloop %d   keySize %u\n", oloop, (unsigned)keySizeInBits);
147			}
148		}
149
150		/* generate a key pair */
151		crtn = cspGenKeyPair(cspHand,
152			rawSigAlg,
153			"foo",
154			3,
155			keySizeInBits,
156			&pubKey,
157			CSSM_TRUE,						// all keys ref for speed
158			CSSM_KEYUSE_VERIFY,
159			CSSM_KEYBLOB_RAW_FORMAT_NONE,
160			&privKey,
161			CSSM_TRUE,
162			CSSM_KEYUSE_SIGN,
163			CSSM_KEYBLOB_RAW_FORMAT_NONE,
164			CSSM_FALSE);					// genSeed not used
165		if(crtn) {
166			return testError(quiet);
167		}
168
169		for(iloop=0; iloop<iloops; iloop++) {
170
171			CSSM_ALGORITHMS		sigAlg;
172			CSSM_ALGORITHMS		digestAlg;
173			CSSM_CC_HANDLE		sigHand;
174
175			/* alternate digest algs for RSA */
176			if(rawSigAlg == CSSM_ALGID_RSA) {
177				if(iloop & 1) {
178					sigAlg = CSSM_ALGID_SHA1WithRSA;
179					digestAlg = CSSM_ALGID_SHA1;
180					digestStr = "SHA1";
181				}
182				else {
183					sigAlg = CSSM_ALGID_MD5WithRSA;
184					digestAlg = CSSM_ALGID_MD5;
185					digestStr = "MD5 ";
186				}
187			}
188			else {
189				sigAlg = CSSM_ALGID_SHA1WithDSA;
190				digestAlg = CSSM_ALGID_SHA1;
191				digestStr = "SHA1";
192			}
193
194			/* new plaintext each inner loop */
195			simpleGenData(&ptext, 1, MAX_TEXT_SIZE);
196			if(!quiet) {
197				if(verbose || ((iloop % LOOP_NOTIFY) == 0)) {
198					printf("   ...iloop %d  digest %s  text size %lu\n",
199						iloop, digestStr, ptext.Length);
200				}
201			}
202
203			/*** phase 1 ***/
204
205			/* digest+sign */
206			crtn = cspStagedSign(cspHand,
207				sigAlg,
208				&privKey,
209				&ptext,
210				DO_MULTI_UPDATE,			// multiUpdates
211				&sig);
212			if(crtn && testError(quiet)) {
213				goto abort;
214			}
215
216			/* digest */
217			crtn = cspStagedDigest(cspHand,
218				digestAlg,
219				CSSM_FALSE,			// mallocDigest
220				DO_MULTI_UPDATE,	// multiUpdates
221				&ptext,
222				&digest);
223			if(crtn && testError(quiet)) {
224				goto abort;
225			}
226
227			/* raw RSA/DSA verify */
228			crtn = CSSM_CSP_CreateSignatureContext(cspHand,
229				rawSigAlg,
230				NULL,				// passPhrase
231				&pubKey,
232				&sigHand);
233			if(crtn) {
234				printError("CSSM_CSP_CreateSignatureContext (1)", crtn);
235				return crtn;
236			}
237			crtn = CSSM_VerifyData(sigHand,
238				&digest,
239				1,
240				digestAlg,
241				&sig);
242			if(crtn) {
243				printError("CSSM_VerifyData(raw RSA)", crtn);
244				if(testError(quiet)) {
245					goto abort;
246				}
247			}
248
249			/* free resources - reuse the digest for raw sign */
250			appFreeCssmData(&sig, CSSM_FALSE);
251			CSSM_DeleteContext(sigHand);
252
253			/*** phase 2 ***/
254
255			/* raw RSA/DSA sign */
256			crtn = CSSM_CSP_CreateSignatureContext(cspHand,
257				rawSigAlg,
258				NULL,				// passPhrase
259				&privKey,
260				&sigHand);
261			if(crtn) {
262				printError("CSSM_CSP_CreateSignatureContext (1)", crtn);
263				return crtn;
264			}
265			crtn = CSSM_SignData(sigHand,
266				&digest,
267				1,
268				digestAlg,
269				&sig);
270			if(crtn) {
271				printError("CSSM_SignData(raw RSA)", crtn);
272				if(testError(quiet)) {
273					goto abort;
274				}
275			}
276
277			/* all-in-one verify */
278			crtn = cspStagedSigVerify(cspHand,
279				sigAlg,
280				&pubKey,
281				&ptext,
282				&sig,
283				DO_MULTI_UPDATE,		// multiUpdates
284				CSSM_OK);
285			if(crtn && testError(quiet)) {
286				goto abort;
287			}
288
289			/* clean up */
290			appFreeCssmData(&sig, CSSM_FALSE);
291			appFreeCssmData(&digest, CSSM_FALSE);
292			CSSM_DeleteContext(sigHand);
293		}	/* end of inner loop */
294
295		/* free keys */
296		cspFreeKey(cspHand, &pubKey);
297		cspFreeKey(cspHand, &privKey);
298
299		if(oloops && (oloop == oloops)) {
300			break;
301		}
302		if(pauseInterval && ((oloop % pauseInterval) == 0)) {
303			fpurge(stdin);
304			printf("hit CR to proceed: ");
305			getchar();
306		}
307	}
308
309abort:
310	cspShutdown(cspHand, bareCsp);
311	if(pauseInterval) {
312		fpurge(stdin);
313		printf("ModuleDetach/Unload complete; hit CR to exit: ");
314		getchar();
315	}
316	if((rtn == 0) && !quiet) {
317		printf("%s test complete\n", argv[0]);
318	}
319	CSSM_FREE(ptext.Data);
320	return rtn;
321}
322
323
324