1/*
2 * atomTime.c - measure performance of digital signature primitives (not incluing
3 * digest)
4 */
5
6#include "ckconfig.h"
7#include "ckutilsPlatform.h"
8#include "CryptKitSA.h"
9#include "curveParams.h"
10#include "falloc.h"
11#include <stdlib.h>
12#include <stdio.h>
13#include <time.h>
14
15#define SIGN_LOOPS_DEF		    100
16#define VFY_LOOPS_DEF		    100
17#define PRIV_KEY_SIZE_BYTES	    32
18#define DIGEST_SIZE_BYTES	    20	    /* e.g., SHA1 */
19#define NUM_KEYS		    10
20
21static void usage(char **argv)
22{
23	printf("Usage: %s [option...]\n", argv[0]);
24	printf("Options:\n");
25	printf("  s=signLoops      -- default %d\n", SIGN_LOOPS_DEF);
26	printf("  v=verifyLoops    -- default %d\n", VFY_LOOPS_DEF);
27	printf("  D=depth          -- default is ALL\n");
28	exit(1);
29}
30
31typedef struct {
32    unsigned char *data;
33    unsigned length;
34} FeeData;
35
36/*
37 * Fill numDatas with random data of length bits. Caller has mallocd referents.
38 */
39static void genRandData(FeeData *datas,
40	unsigned numDatas,
41	unsigned numBytes,
42	feeRand rand)
43{
44	unsigned i;
45	FeeData *fd;
46	for(i=0; i<numDatas; i++) {
47		fd = &datas[i];
48		fd->length = numBytes;
49		feeRandBytes(rand, fd->data, numBytes);
50	}
51	return;
52}
53
54static void mallocData(
55    FeeData *fd,
56    unsigned numBytes)
57{
58    fd->data = (unsigned char *)fmalloc(numBytes);
59    fd->length = numBytes;
60}
61
62/* common random callback */
63feeReturn randCallback(
64    void *ref,
65    unsigned char *bytes,
66    unsigned numBytes)
67{
68    feeRand frand = (feeRand)ref;
69    feeRandBytes(frand, bytes, numBytes);
70    return FR_Success;
71}
72
73int main(int argc, char **argv)
74{
75	int 		arg;
76	char 		*argp;
77	unsigned 	sigLoops = SIGN_LOOPS_DEF;
78	unsigned	vfyLoops = VFY_LOOPS_DEF;
79	unsigned	numKeys = NUM_KEYS; // might be less for very small loops
80	unsigned	depth;
81	feeRand 	rand;
82
83	feePubKey	keys[NUM_KEYS];
84	/* sigLoops copies of each of {digestData, sigData} */
85	FeeData		*digestData;
86	FeeData		*sigData;
87
88	unsigned 	seed;
89	unsigned	i;
90	PLAT_TIME	startTime;
91	PLAT_TIME	endTime;
92	double		elapsed;
93	curveParams	*cp;
94	unsigned	minDepth = 0;
95	unsigned	maxDepth = FEE_DEPTH_MAX;
96	unsigned	basePrimeLen;
97	char		*curveType;
98	feeReturn	frtn;
99
100	for(arg=1; arg<argc; arg++) {
101		argp = argv[arg];
102		switch(argp[0]) {
103		    case 's':
104		    	sigLoops = atoi(&argp[2]);
105			break;
106		    case 'v':
107		    	vfyLoops = atoi(&argp[2]);
108			break;
109		    case 'D':
110		    	minDepth = maxDepth = atoi(&argp[2]);
111			break;
112		    default:
113		    	usage(argv);
114			break;
115		}
116	}
117
118	/*
119	 * Common random generator
120	 */
121	time((time_t *)&seed);
122	rand = feeRandAllocWithSeed(seed);
123
124	if(numKeys > sigLoops) {
125	    numKeys = sigLoops;
126	}
127	digestData = (FeeData *)fmalloc(sizeof(FeeData) * sigLoops);
128	sigData    = (FeeData *)fmalloc(sizeof(FeeData) * sigLoops);
129
130	/* alloc the data, once, for largest private key or "digest" we'll use */
131	for(i=0; i<sigLoops; i++) {
132	    mallocData(&digestData[i], PRIV_KEY_SIZE_BYTES);
133	}
134	for(depth=minDepth; depth<=maxDepth; depth++) {
135
136		/*
137		 * Get curve params for this depth
138	 	 */
139		cp = curveParamsForDepth(depth);
140		if(cp == NULL) {
141			printf("malloc failure\n");
142			exit(1);
143		}
144		switch(cp->curveType) {
145		    case FCT_Montgomery:
146		    	curveType = "FCT_Montgomery";
147			break;
148		    case FCT_Weierstrass:
149			curveType = "FCT_Weierstrass";
150			break;
151		    case FCT_General:
152		    	curveType = "FCT_General";
153			break;
154		    default:
155		    	printf("***Unknown curveType!\n");
156			exit(1);
157		}
158
159		switch(cp->primeType) {
160		    case FPT_General:
161		    	printf("depth=%d; FPT_General, %s; keysize=%d;\n",
162				depth, curveType, bitlen(cp->basePrime));
163			break;
164		    case FPT_Mersenne:
165			printf("depth=%d; FPT_Mersenne, %s; q=%d\n",
166				depth, curveType, cp->q);
167			break;
168		    default:
169			printf("depth=%d; FPT_FEE, %s; q=%d k=%d\n",
170				depth, curveType, cp->q, cp->k);
171			break;
172		}
173		basePrimeLen = bitlen(cp->basePrime);
174
175		/* one set of random data as private keys */
176		unsigned privSize = (basePrimeLen + 8) / 8;
177		genRandData(digestData, numKeys, privSize, rand);
178
179		/* generate the keys (no hash - we've got that covered) */
180		for(i=0; i<numKeys; i++) {
181		    keys[i] = feePubKeyAlloc();
182		    feePubKeyInitFromPrivDataDepth(keys[i], digestData[i].data, privSize,
183			depth, 0);
184		}
185
186		/* now different data to actually sign */
187		genRandData(digestData, sigLoops, DIGEST_SIZE_BYTES, rand);
188
189		/*
190		 * sign
191		 */
192		PLAT_GET_TIME(startTime);
193		for(i=0; i<sigLoops; i++) {
194		    FeeData *digst = &digestData[i];
195		    FeeData *sig   = &sigData[i];
196		    feePubKey fkey = keys[i % numKeys];
197
198		    feeSig fs = feeSigNewWithKey(fkey, randCallback, rand);
199		    frtn = feeSigSign(fs, digst->data, digst->length, fkey);
200		    if(frtn) {
201			printf("***Error %d on feeSigSign\n", (int)frtn);
202			break;
203		    }
204		    frtn = feeSigData(fs, &sig->data, &sig->length);
205		    if(frtn) {
206			printf("***Error %d on feeSigData\n", (int)frtn);
207			break;
208		    }
209		    feeSigFree(fs);
210		}
211		PLAT_GET_TIME(endTime);
212		elapsed = PLAT_GET_US(startTime, endTime);
213		printf("   sign:   %12.2f us per op\n",
214			elapsed / sigLoops);
215
216		/*
217		 * verify - might be doing more of these than we have
218		 * valid signatures.....
219		 */
220		unsigned dex=0;
221		PLAT_GET_TIME(startTime);
222		for(i=0; i<vfyLoops; i++) {
223		    FeeData *digst = &digestData[dex];
224		    FeeData *sig   = &sigData[dex];
225		    feePubKey fkey = keys[dex % numKeys];
226
227		    feeSig fs;
228		    frtn = feeSigParse(sig->data, sig->length, &fs);
229		    if(frtn) {
230			printf("***Error %d on feeSigParse\n", (int)frtn);
231			break;
232		    }
233		    frtn = feeSigVerify(fs, digst->data, digst->length, fkey);
234		    if(frtn) {
235			printf("***Error %d on feeSigVerify\n", (int)frtn);
236			break;
237		    }
238		    feeSigFree(fs);
239		    dex++;
240		    if(dex == sigLoops) {
241			/* that's all the data we have, recycle */
242			dex = 0;
243		    }
244		}
245		PLAT_GET_TIME(endTime);
246		elapsed = PLAT_GET_US(startTime, endTime);
247		printf("   verify: %12.2f us per op\n",
248			elapsed / vfyLoops);
249
250		freeCurveParams(cp);
251		/* possibly limited number of signatures.... */
252		for(i=0; i<sigLoops; i++) {
253		    ffree(sigData[i].data);	// mallocd by feeSigData()
254		}
255		for(i=0; i<numKeys; i++) {
256		    feePubKeyFree(keys[i]);
257		}
258	}
259
260	feeRandFree(rand);
261	for(i=0; i<sigLoops; i++) {
262	    ffree(digestData[i].data);
263	}
264	ffree(digestData);
265	ffree(sigData);
266
267	return 0;
268}
269
270