1/*
2 * asymPerform.c - measure performance of RSA and FEE encrypt and decrypt
3 */
4
5#include <stdlib.h>
6#include <stdio.h>
7#include <time.h>
8#include <Security/cssm.h>
9#include <Security/cssmapple.h>
10#include "cspwrap.h"
11#include "common.h"
12#include <string.h>
13#include <CoreFoundation/CoreFoundation.h>
14
15/*
16 * Defaults.
17 */
18#define ENC_LOOPS_DEF	1000
19#define KEYSIZE_DEF		1024
20#define PTEXT_SIZE		20			/* e.g., a SHA1 digest */
21
22static void usage(char **argv)
23{
24	printf("usage: %s [options]\n", argv[0]);
25	printf("   Options:\n");
26	printf("   a=algorithm (r=RSA; f=FEED; F=FEEDExp; default=RSA)\n");
27	printf("   l=numLoop (default=%d)\n", ENC_LOOPS_DEF);
28	printf("   k=keySizeInBits; default=%d\n", KEYSIZE_DEF);
29	printf("   D (CSP/DL; default = bare CSP)\n");
30	printf("   b (RSA blinding enabled)\n");
31	printf("   v(erbose)\n");
32	printf("   q(uiet)\n");
33	printf("   h(elp)\n");
34	exit(1);
35}
36
37
38int main(int argc, char **argv)
39{
40	int					arg;
41	char				*argp;
42	CSSM_CSP_HANDLE 	cspHand;
43	unsigned			i;
44	CSSM_KEY			pubKey;
45	CSSM_KEY			privKey;
46	CSSM_DATA_PTR		ptext;		// different for each loop
47	CSSM_DATA_PTR		ctext;		// ditto
48	CSSM_DATA_PTR		rptext;		// ditto
49	CSSM_RETURN			crtn;
50	CFAbsoluteTime 		start, end;
51	CSSM_CC_HANDLE		ccHand;
52	unsigned			ctextSize;
53	CSSM_ACCESS_CREDENTIALS	creds;
54	CSSM_SIZE			processed;
55	CSSM_DATA			remData;
56
57	/*
58	 * User-spec'd params
59	 */
60	uint32				keySizeInBits = KEYSIZE_DEF;
61	unsigned			encLoops = ENC_LOOPS_DEF;
62	CSSM_BOOL			verbose = CSSM_FALSE;
63	CSSM_BOOL			quiet = CSSM_FALSE;
64	CSSM_BOOL			bareCsp = CSSM_TRUE;
65	CSSM_BOOL			rsaBlinding = CSSM_FALSE;
66	CSSM_ALGORITHMS		keyAlg = CSSM_ALGID_RSA;
67	CSSM_ALGORITHMS		encrAlg = CSSM_ALGID_RSA;
68	CSSM_PADDING		padding = CSSM_PADDING_PKCS1;
69
70	for(arg=1; arg<argc; arg++) {
71		argp = argv[arg];
72		switch(argp[0]) {
73			case 'a':
74				if(argp[1] != '=') {
75					usage(argv);
76				}
77				switch(argp[2]) {
78					case 'r':
79						encrAlg = keyAlg = CSSM_ALGID_RSA;
80						break;
81					case 'f':
82						encrAlg = CSSM_ALGID_FEED;
83						keyAlg = CSSM_ALGID_FEE;
84						padding = CSSM_PADDING_NONE;
85						break;
86					case 'F':
87						encrAlg = CSSM_ALGID_FEEDEXP;
88						keyAlg = CSSM_ALGID_FEE;
89						padding = CSSM_PADDING_NONE;
90						break;
91					default:
92						usage(argv);
93				}
94				break;
95		    case 'l':
96				encLoops = atoi(&argp[2]);
97				break;
98		    case 'k':
99		    	keySizeInBits = atoi(&argp[2]);
100				break;
101		    case 'v':
102		    	verbose = CSSM_TRUE;
103				break;
104			case 'D':
105				bareCsp = CSSM_FALSE;
106				break;
107			case 'b':
108				rsaBlinding = CSSM_TRUE;
109				break;
110		    case 'q':
111		    	quiet = CSSM_TRUE;
112				break;
113		    case 'h':
114		    default:
115				usage(argv);
116		}
117	}
118
119	cspHand = cspDlDbStartup(bareCsp, NULL);
120	if(cspHand == 0) {
121		exit(1);
122	}
123
124	/* malloc encLoops ptext and ctext structs and the data they contain */
125	ptext = (CSSM_DATA_PTR)CSSM_MALLOC(encLoops * sizeof(CSSM_DATA));
126	ctext = (CSSM_DATA_PTR)CSSM_MALLOC(encLoops * sizeof(CSSM_DATA));
127	rptext = (CSSM_DATA_PTR)CSSM_MALLOC(encLoops * sizeof(CSSM_DATA));
128	memset(ptext, 0, encLoops * sizeof(CSSM_DATA));
129	memset(ctext, 0, encLoops * sizeof(CSSM_DATA));
130	memset(rptext, 0, encLoops * sizeof(CSSM_DATA));
131	ctextSize = (keySizeInBits + 7) / 8;
132	if(keyAlg != CSSM_ALGID_RSA) {
133		ctextSize *= 8;
134	}
135	for(i=0; i<encLoops; i++) {
136		appSetupCssmData(&ptext[i], PTEXT_SIZE);
137		appSetupCssmData(&ctext[i], ctextSize);
138	}
139
140	/* generate random "digests" */
141	for(i=0; i<encLoops; i++) {
142		simpleGenData(&ptext[i], PTEXT_SIZE, PTEXT_SIZE);
143	}
144
145	printf("Generating keys....\n");
146	crtn = cspGenKeyPair(cspHand,
147		keyAlg,
148		"foo",
149		3,
150		keySizeInBits,
151		&pubKey,
152		CSSM_TRUE,						// reference key for speed
153		CSSM_KEYUSE_ANY,
154		CSSM_KEYBLOB_RAW_FORMAT_NONE,
155		&privKey,
156		CSSM_TRUE,
157		CSSM_KEYUSE_ANY,
158		CSSM_KEYBLOB_RAW_FORMAT_NONE,
159		CSSM_FALSE);					// genSeed not used
160	if(crtn) {
161		return testError(quiet);
162	}
163
164	printf("Encrypting....\n");
165
166	/* set up a reusable crypt context */
167	memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
168	crtn = CSSM_CSP_CreateAsymmetricContext(cspHand,
169				encrAlg,
170				&creds,
171				(encrAlg == CSSM_ALGID_FEED) ? &privKey : &pubKey,
172				padding,
173				&ccHand);
174	if(crtn) {
175		printError("CSSM_CSP_CreateAsymmetricContext (1)", crtn);
176		return 1;
177	}
178	if(encrAlg == CSSM_ALGID_FEED) {
179		AddContextAttribute(ccHand, CSSM_ATTRIBUTE_PUBLIC_KEY,
180			sizeof(CSSM_KEY), CAT_Ptr, &pubKey, 0);
181	}
182
183	/* go - critical encrypt loop */
184	start = CFAbsoluteTimeGetCurrent();
185	for(i=0; i<encLoops; i++) {
186		crtn = CSSM_EncryptData(ccHand,
187			&ptext[i],
188			1,
189			&ctext[i],
190			1,
191			&processed,
192			&remData);
193		ctext[i].Length = processed;
194		if(crtn) {
195			printError("CSSM_EncryptData", crtn);
196			return 1;
197		}
198	}
199	end = CFAbsoluteTimeGetCurrent();
200	printf("%d encr ops in %f seconds, %f ms/op\n", encLoops, end-start,
201		((end - start) * 1000.0) / encLoops);
202
203	CSSM_DeleteContext(ccHand);
204
205	/* set up a reusable encryption context */
206	crtn = CSSM_CSP_CreateAsymmetricContext(cspHand,
207				encrAlg,
208				&creds,
209				&privKey,
210				padding,
211				&ccHand);
212	if(crtn) {
213		printError("CSSM_CSP_CreateAsymmetricContext (2)", crtn);
214		return 1;
215	}
216	if(rsaBlinding) {
217		CSSM_CONTEXT_ATTRIBUTE	newAttr;
218		newAttr.AttributeType     = CSSM_ATTRIBUTE_RSA_BLINDING;
219		newAttr.AttributeLength   = sizeof(uint32);
220		newAttr.Attribute.Uint32  = 1;
221		crtn = CSSM_UpdateContextAttributes(ccHand, 1, &newAttr);
222		if(crtn) {
223			printError("CSSM_UpdateContextAttributes", crtn);
224			return crtn;
225		}
226	}
227	if(encrAlg == CSSM_ALGID_FEED) {
228		AddContextAttribute(ccHand, CSSM_ATTRIBUTE_PUBLIC_KEY,
229			sizeof(CSSM_KEY), CAT_Ptr, &pubKey, 0);
230	}
231
232	/* go - critical decrypt loop */
233	start = CFAbsoluteTimeGetCurrent();
234	for(i=0; i<encLoops; i++) {
235		crtn = CSSM_DecryptData(ccHand,
236			&ctext[i],
237			1,
238			&rptext[i],
239			1,
240			&processed,
241			&remData);
242		if(crtn) {
243			printError("CSSM_DecryptData", crtn);
244			return 1;
245		}
246	}
247	end = CFAbsoluteTimeGetCurrent();
248	printf("%d decr ops in %f seconds, %f ms/op\n", encLoops, end-start,
249		((end - start) * 1000.0) / encLoops);
250	CSSM_DeleteContext(ccHand);
251
252	cspFreeKey(cspHand, &privKey);
253	cspFreeKey(cspHand, &pubKey);
254	for(i=0; i<encLoops; i++) {
255		appFreeCssmData(&ptext[i], CSSM_FALSE);
256		appFreeCssmData(&ctext[i], CSSM_FALSE);
257		appFreeCssmData(&rptext[i], CSSM_FALSE);
258	}
259	CSSM_FREE(ptext);
260	CSSM_FREE(ctext);
261	CSSM_FREE(rptext);
262	cspShutdown(cspHand, bareCsp);
263	return 0;
264}
265
266
267