|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include "seccomon.h" |
|
6 #include "cert.h" |
|
7 #include "secutil.h" |
|
8 #include "nspr.h" |
|
9 #include "nss.h" |
|
10 #include "blapi.h" |
|
11 #include "plgetopt.h" |
|
12 #include "lowkeyi.h" |
|
13 #include "pk11pub.h" |
|
14 |
|
15 |
|
16 #define DEFAULT_ITERS 10 |
|
17 #define DEFAULT_DURATION 10 |
|
18 #define DEFAULT_KEY_BITS 1024 |
|
19 #define MIN_KEY_BITS 512 |
|
20 #define MAX_KEY_BITS 65536 |
|
21 #define BUFFER_BYTES MAX_KEY_BITS / 8 |
|
22 #define DEFAULT_THREADS 1 |
|
23 #define DEFAULT_EXPONENT 0x10001 |
|
24 |
|
25 extern NSSLOWKEYPrivateKey * getDefaultRSAPrivateKey(void); |
|
26 extern NSSLOWKEYPublicKey * getDefaultRSAPublicKey(void); |
|
27 |
|
28 secuPWData pwData = { PW_NONE, NULL }; |
|
29 |
|
30 typedef struct TimingContextStr TimingContext; |
|
31 |
|
32 struct TimingContextStr { |
|
33 PRTime start; |
|
34 PRTime end; |
|
35 PRTime interval; |
|
36 |
|
37 long days; |
|
38 int hours; |
|
39 int minutes; |
|
40 int seconds; |
|
41 int millisecs; |
|
42 }; |
|
43 |
|
44 TimingContext *CreateTimingContext(void) { |
|
45 return PORT_Alloc(sizeof(TimingContext)); |
|
46 } |
|
47 |
|
48 void DestroyTimingContext(TimingContext *ctx) { |
|
49 PORT_Free(ctx); |
|
50 } |
|
51 |
|
52 void TimingBegin(TimingContext *ctx, PRTime begin) { |
|
53 ctx->start = begin; |
|
54 } |
|
55 |
|
56 static void timingUpdate(TimingContext *ctx) { |
|
57 PRInt64 tmp, remaining; |
|
58 PRInt64 L1000,L60,L24; |
|
59 |
|
60 LL_I2L(L1000,1000); |
|
61 LL_I2L(L60,60); |
|
62 LL_I2L(L24,24); |
|
63 |
|
64 LL_DIV(remaining, ctx->interval, L1000); |
|
65 LL_MOD(tmp, remaining, L1000); |
|
66 LL_L2I(ctx->millisecs, tmp); |
|
67 LL_DIV(remaining, remaining, L1000); |
|
68 LL_MOD(tmp, remaining, L60); |
|
69 LL_L2I(ctx->seconds, tmp); |
|
70 LL_DIV(remaining, remaining, L60); |
|
71 LL_MOD(tmp, remaining, L60); |
|
72 LL_L2I(ctx->minutes, tmp); |
|
73 LL_DIV(remaining, remaining, L60); |
|
74 LL_MOD(tmp, remaining, L24); |
|
75 LL_L2I(ctx->hours, tmp); |
|
76 LL_DIV(remaining, remaining, L24); |
|
77 LL_L2I(ctx->days, remaining); |
|
78 } |
|
79 |
|
80 void TimingEnd(TimingContext *ctx, PRTime end) { |
|
81 ctx->end = end; |
|
82 LL_SUB(ctx->interval, ctx->end, ctx->start); |
|
83 PORT_Assert(LL_GE_ZERO(ctx->interval)); |
|
84 timingUpdate(ctx); |
|
85 } |
|
86 |
|
87 void TimingDivide(TimingContext *ctx, int divisor) { |
|
88 PRInt64 tmp; |
|
89 |
|
90 LL_I2L(tmp, divisor); |
|
91 LL_DIV(ctx->interval, ctx->interval, tmp); |
|
92 |
|
93 timingUpdate(ctx); |
|
94 } |
|
95 |
|
96 char *TimingGenerateString(TimingContext *ctx) { |
|
97 char *buf = NULL; |
|
98 |
|
99 if (ctx->days != 0) { |
|
100 buf = PR_sprintf_append(buf, "%d days", ctx->days); |
|
101 } |
|
102 if (ctx->hours != 0) { |
|
103 if (buf != NULL) buf = PR_sprintf_append(buf, ", "); |
|
104 buf = PR_sprintf_append(buf, "%d hours", ctx->hours); |
|
105 } |
|
106 if (ctx->minutes != 0) { |
|
107 if (buf != NULL) buf = PR_sprintf_append(buf, ", "); |
|
108 buf = PR_sprintf_append(buf, "%d minutes", ctx->minutes); |
|
109 } |
|
110 if (buf != NULL) buf = PR_sprintf_append(buf, ", and "); |
|
111 if (!buf && ctx->seconds == 0) { |
|
112 int interval; |
|
113 LL_L2I(interval, ctx->interval); |
|
114 if (ctx->millisecs < 100) |
|
115 buf = PR_sprintf_append(buf, "%d microseconds", interval); |
|
116 else |
|
117 buf = PR_sprintf_append(buf, "%d milliseconds", ctx->millisecs); |
|
118 } else if (ctx->millisecs == 0) { |
|
119 buf = PR_sprintf_append(buf, "%d seconds", ctx->seconds); |
|
120 } else { |
|
121 buf = PR_sprintf_append(buf, "%d.%03d seconds", |
|
122 ctx->seconds, ctx->millisecs); |
|
123 } |
|
124 return buf; |
|
125 } |
|
126 |
|
127 void |
|
128 Usage(char *progName) |
|
129 { |
|
130 fprintf(stderr, "Usage: %s [-s | -e] [-i iterations | -p period] " |
|
131 "[-t threads]\n[-n none [-k keylength] [ [-g] -x exponent] |\n" |
|
132 " -n token:nickname [-d certdir] [-w password] |\n" |
|
133 " -h token [-d certdir] [-w password] [-g] [-k keylength] " |
|
134 "[-x exponent] [-f pwfile]\n", |
|
135 progName); |
|
136 fprintf(stderr, "%-20s Cert database directory (default is ~/.netscape)\n", |
|
137 "-d certdir"); |
|
138 fprintf(stderr, "%-20s How many operations to perform\n", "-i iterations"); |
|
139 fprintf(stderr, "%-20s How many seconds to run\n", "-p period"); |
|
140 fprintf(stderr, "%-20s Perform signing (private key) operations\n", "-s"); |
|
141 fprintf(stderr, "%-20s Perform encryption (public key) operations\n","-e"); |
|
142 fprintf(stderr, "%-20s Nickname of certificate or key, prefixed " |
|
143 "by optional token name\n", "-n nickname"); |
|
144 fprintf(stderr, "%-20s PKCS#11 token to perform operation with.\n", |
|
145 "-h token"); |
|
146 fprintf(stderr, "%-20s key size in bits, from %d to %d\n", "-k keylength", |
|
147 MIN_KEY_BITS, MAX_KEY_BITS); |
|
148 fprintf(stderr, "%-20s token password\n", "-w password"); |
|
149 fprintf(stderr, "%-20s temporary key generation. Not for token keys.\n", |
|
150 "-g"); |
|
151 fprintf(stderr, "%-20s set public exponent for keygen\n", "-x"); |
|
152 fprintf(stderr, "%-20s Number of execution threads (default 1)\n", |
|
153 "-t threads"); |
|
154 exit(-1); |
|
155 } |
|
156 |
|
157 static void |
|
158 dumpBytes( unsigned char * b, int l) |
|
159 { |
|
160 int i; |
|
161 if (l <= 0) |
|
162 return; |
|
163 for (i = 0; i < l; ++i) { |
|
164 if (i % 16 == 0) |
|
165 printf("\t"); |
|
166 printf(" %02x", b[i]); |
|
167 if (i % 16 == 15) |
|
168 printf("\n"); |
|
169 } |
|
170 if ((i % 16) != 0) |
|
171 printf("\n"); |
|
172 } |
|
173 |
|
174 static void |
|
175 dumpItem( SECItem * item, const char * description) |
|
176 { |
|
177 if (item->len & 1 && item->data[0] == 0) { |
|
178 printf("%s: (%d bytes)\n", description, item->len - 1); |
|
179 dumpBytes(item->data + 1, item->len - 1); |
|
180 } else { |
|
181 printf("%s: (%d bytes)\n", description, item->len); |
|
182 dumpBytes(item->data, item->len); |
|
183 } |
|
184 } |
|
185 |
|
186 void |
|
187 printPrivKey(NSSLOWKEYPrivateKey * privKey) |
|
188 { |
|
189 RSAPrivateKey *rsa = &privKey->u.rsa; |
|
190 |
|
191 dumpItem( &rsa->modulus, "n"); |
|
192 dumpItem( &rsa->publicExponent, "e"); |
|
193 dumpItem( &rsa->privateExponent, "d"); |
|
194 dumpItem( &rsa->prime1, "P"); |
|
195 dumpItem( &rsa->prime2, "Q"); |
|
196 dumpItem( &rsa->exponent1, "d % (P-1)"); |
|
197 dumpItem( &rsa->exponent2, "d % (Q-1)"); |
|
198 dumpItem( &rsa->coefficient, "(Q ** -1) % P"); |
|
199 puts(""); |
|
200 } |
|
201 |
|
202 typedef SECStatus (* RSAOp)(void * key, |
|
203 unsigned char * output, |
|
204 unsigned char * input); |
|
205 |
|
206 typedef struct { |
|
207 SECKEYPublicKey* pubKey; |
|
208 SECKEYPrivateKey* privKey; |
|
209 } PK11Keys; |
|
210 |
|
211 |
|
212 SECStatus PK11_PublicKeyOp (SECKEYPublicKey* key, |
|
213 unsigned char * output, |
|
214 unsigned char * input) |
|
215 { |
|
216 return PK11_PubEncryptRaw(key, output, input, key->u.rsa.modulus.len, |
|
217 NULL); |
|
218 } |
|
219 |
|
220 SECStatus PK11_PrivateKeyOp (PK11Keys* keys, |
|
221 unsigned char * output, |
|
222 unsigned char * input) |
|
223 { |
|
224 unsigned outLen = 0; |
|
225 return PK11_PrivDecryptRaw(keys->privKey, |
|
226 output, &outLen, |
|
227 keys->pubKey->u.rsa.modulus.len, input, |
|
228 keys->pubKey->u.rsa.modulus.len); |
|
229 } |
|
230 typedef struct ThreadRunDataStr ThreadRunData; |
|
231 |
|
232 struct ThreadRunDataStr { |
|
233 const PRBool *doIters; |
|
234 const void *rsaKey; |
|
235 const unsigned char *buf; |
|
236 RSAOp fn; |
|
237 int seconds; |
|
238 long iters; |
|
239 long iterRes; |
|
240 PRErrorCode errNum; |
|
241 SECStatus status; |
|
242 }; |
|
243 |
|
244 |
|
245 void ThreadExecFunction(void *data) |
|
246 { |
|
247 ThreadRunData *tdata = (ThreadRunData*)data; |
|
248 unsigned char buf2[BUFFER_BYTES]; |
|
249 |
|
250 tdata->status = SECSuccess; |
|
251 if (*tdata->doIters) { |
|
252 long i = tdata->iters; |
|
253 tdata->iterRes = 0; |
|
254 while (i--) { |
|
255 SECStatus rv = tdata->fn((void*)tdata->rsaKey, buf2, |
|
256 (unsigned char*)tdata->buf); |
|
257 if (rv != SECSuccess) { |
|
258 tdata->errNum = PORT_GetError(); |
|
259 tdata->status = rv; |
|
260 break; |
|
261 } |
|
262 tdata->iterRes++; |
|
263 } |
|
264 } else { |
|
265 PRIntervalTime total = PR_SecondsToInterval(tdata->seconds); |
|
266 PRIntervalTime start = PR_IntervalNow(); |
|
267 tdata->iterRes = 0; |
|
268 while (PR_IntervalNow() - start < total) { |
|
269 SECStatus rv = tdata->fn((void*)tdata->rsaKey, buf2, |
|
270 (unsigned char*)tdata->buf); |
|
271 if (rv != SECSuccess) { |
|
272 tdata->errNum = PORT_GetError(); |
|
273 tdata->status = rv; |
|
274 break; |
|
275 } |
|
276 tdata->iterRes++; |
|
277 } |
|
278 } |
|
279 } |
|
280 |
|
281 #define INT_ARG(arg,def) atol(arg)>0?atol(arg):def |
|
282 |
|
283 int |
|
284 main(int argc, char **argv) |
|
285 { |
|
286 TimingContext * timeCtx = NULL; |
|
287 SECKEYPublicKey * pubHighKey = NULL; |
|
288 SECKEYPrivateKey * privHighKey = NULL; |
|
289 NSSLOWKEYPrivateKey * privKey = NULL; |
|
290 NSSLOWKEYPublicKey * pubKey = NULL; |
|
291 CERTCertificate * cert = NULL; |
|
292 char * progName = NULL; |
|
293 char * secDir = NULL; |
|
294 char * nickname = NULL; |
|
295 char * slotname = NULL; |
|
296 long keybits = 0; |
|
297 RSAOp fn; |
|
298 void * rsaKey = NULL; |
|
299 PLOptState * optstate; |
|
300 PLOptStatus optstatus; |
|
301 long iters = DEFAULT_ITERS; |
|
302 int i; |
|
303 PRBool doPriv = PR_FALSE; |
|
304 PRBool doPub = PR_FALSE; |
|
305 int rv; |
|
306 unsigned char buf[BUFFER_BYTES]; |
|
307 unsigned char buf2[BUFFER_BYTES]; |
|
308 int seconds = DEFAULT_DURATION; |
|
309 PRBool doIters = PR_FALSE; |
|
310 PRBool doTime = PR_FALSE; |
|
311 PRBool useTokenKey = PR_FALSE; /* use PKCS#11 token |
|
312 object key */ |
|
313 PRBool useSessionKey = PR_FALSE; /* use PKCS#11 session |
|
314 object key */ |
|
315 PRBool useBLKey = PR_FALSE; /* use freebl */ |
|
316 PK11SlotInfo* slot = NULL; /* slot for session |
|
317 object key operations */ |
|
318 PRBool doKeyGen = PR_FALSE; |
|
319 int publicExponent = DEFAULT_EXPONENT; |
|
320 PK11Keys keys; |
|
321 int peCount = 0; |
|
322 CK_BYTE pubEx[4]; |
|
323 SECItem pe; |
|
324 RSAPublicKey pubKeyStr; |
|
325 int threadNum = DEFAULT_THREADS; |
|
326 ThreadRunData ** runDataArr = NULL; |
|
327 PRThread ** threadsArr = NULL; |
|
328 int calcThreads = 0; |
|
329 |
|
330 progName = strrchr(argv[0], '/'); |
|
331 if (!progName) |
|
332 progName = strrchr(argv[0], '\\'); |
|
333 progName = progName ? progName+1 : argv[0]; |
|
334 |
|
335 optstate = PL_CreateOptState(argc, argv, "d:ef:gh:i:k:n:p:st:w:x:"); |
|
336 while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) { |
|
337 switch (optstate->option) { |
|
338 case '?': |
|
339 Usage(progName); |
|
340 break; |
|
341 case 'd': |
|
342 secDir = PORT_Strdup(optstate->value); |
|
343 break; |
|
344 case 'i': |
|
345 iters = INT_ARG(optstate->value, DEFAULT_ITERS); |
|
346 doIters = PR_TRUE; |
|
347 break; |
|
348 case 's': |
|
349 doPriv = PR_TRUE; |
|
350 break; |
|
351 case 'e': |
|
352 doPub = PR_TRUE; |
|
353 break; |
|
354 case 'g': |
|
355 doKeyGen = PR_TRUE; |
|
356 break; |
|
357 case 'n': |
|
358 nickname = PORT_Strdup(optstate->value); |
|
359 /* for compatibility, nickname of "none" means go to freebl */ |
|
360 if (nickname && strcmp(nickname, "none")) { |
|
361 useTokenKey = PR_TRUE; |
|
362 } else { |
|
363 useBLKey = PR_TRUE; |
|
364 } |
|
365 break; |
|
366 case 'p': |
|
367 seconds = INT_ARG(optstate->value, DEFAULT_DURATION); |
|
368 doTime = PR_TRUE; |
|
369 break; |
|
370 case 'h': |
|
371 slotname = PORT_Strdup(optstate->value); |
|
372 useSessionKey = PR_TRUE; |
|
373 break; |
|
374 case 'k': |
|
375 keybits = INT_ARG(optstate->value, DEFAULT_KEY_BITS); |
|
376 break; |
|
377 case 'w': |
|
378 pwData.data = PORT_Strdup(optstate->value);; |
|
379 pwData.source = PW_PLAINTEXT; |
|
380 break; |
|
381 case 'f': |
|
382 pwData.data = PORT_Strdup(optstate->value); |
|
383 pwData.source = PW_FROMFILE; |
|
384 break; |
|
385 case 'x': |
|
386 /* -x public exponent (for RSA keygen) */ |
|
387 publicExponent = INT_ARG(optstate->value, DEFAULT_EXPONENT); |
|
388 break; |
|
389 case 't': |
|
390 threadNum = INT_ARG(optstate->value, DEFAULT_THREADS); |
|
391 break; |
|
392 } |
|
393 } |
|
394 if (optstatus == PL_OPT_BAD) |
|
395 Usage(progName); |
|
396 |
|
397 if ((doPriv && doPub) || (doIters && doTime) || |
|
398 ((useTokenKey + useSessionKey + useBLKey) != PR_TRUE) || |
|
399 (useTokenKey && keybits) || (useTokenKey && doKeyGen) || |
|
400 (keybits && (keybits<MIN_KEY_BITS || keybits>MAX_KEY_BITS))) { |
|
401 Usage(progName); |
|
402 } |
|
403 |
|
404 if (!doPriv && !doPub) doPriv = PR_TRUE; |
|
405 |
|
406 if (doIters && doTime) Usage(progName); |
|
407 |
|
408 if (!doTime) { |
|
409 doIters = PR_TRUE; |
|
410 } |
|
411 |
|
412 PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); |
|
413 |
|
414 PK11_SetPasswordFunc(SECU_GetModulePassword); |
|
415 secDir = SECU_ConfigDirectory(secDir); |
|
416 |
|
417 if (useTokenKey || useSessionKey) { |
|
418 rv = NSS_Init(secDir); |
|
419 if (rv != SECSuccess) { |
|
420 fprintf(stderr, "NSS_Init failed.\n"); |
|
421 exit(1); |
|
422 } |
|
423 } else { |
|
424 rv = NSS_NoDB_Init(NULL); |
|
425 if (rv != SECSuccess) { |
|
426 fprintf(stderr, "NSS_NoDB_Init failed.\n"); |
|
427 exit(1); |
|
428 } |
|
429 } |
|
430 |
|
431 if (useTokenKey) { |
|
432 CK_OBJECT_HANDLE kh = CK_INVALID_HANDLE; |
|
433 CERTCertDBHandle* certdb = NULL; |
|
434 certdb = CERT_GetDefaultCertDB(); |
|
435 |
|
436 cert = PK11_FindCertFromNickname(nickname, &pwData); |
|
437 if (cert == NULL) { |
|
438 fprintf(stderr, |
|
439 "Can't find certificate by name \"%s\"\n", nickname); |
|
440 exit(1); |
|
441 } |
|
442 pubHighKey = CERT_ExtractPublicKey(cert); |
|
443 if (pubHighKey == NULL) { |
|
444 fprintf(stderr, "Can't extract public key from certificate"); |
|
445 exit(1); |
|
446 } |
|
447 |
|
448 if (doPub) { |
|
449 /* do public key ops */ |
|
450 fn = (RSAOp)PK11_PublicKeyOp; |
|
451 rsaKey = (void *) pubHighKey; |
|
452 |
|
453 kh = PK11_ImportPublicKey(cert->slot, pubHighKey, PR_FALSE); |
|
454 if (CK_INVALID_HANDLE == kh) { |
|
455 fprintf(stderr, |
|
456 "Unable to import public key to certificate slot."); |
|
457 exit(1); |
|
458 } |
|
459 pubHighKey->pkcs11Slot = PK11_ReferenceSlot(cert->slot); |
|
460 pubHighKey->pkcs11ID = kh; |
|
461 printf("Using PKCS#11 for RSA encryption with token %s.\n", |
|
462 PK11_GetTokenName(cert->slot)); |
|
463 } else { |
|
464 /* do private key ops */ |
|
465 privHighKey = PK11_FindKeyByAnyCert(cert, &pwData); |
|
466 if (privHighKey == NULL) { |
|
467 fprintf(stderr, |
|
468 "Can't find private key by name \"%s\"\n", nickname); |
|
469 exit(1); |
|
470 } |
|
471 |
|
472 SECKEY_CacheStaticFlags(privHighKey); |
|
473 fn = (RSAOp)PK11_PrivateKeyOp; |
|
474 keys.privKey = privHighKey; |
|
475 keys.pubKey = pubHighKey; |
|
476 rsaKey = (void *) &keys; |
|
477 printf("Using PKCS#11 for RSA decryption with token %s.\n", |
|
478 PK11_GetTokenName(privHighKey->pkcs11Slot)); |
|
479 } |
|
480 } else |
|
481 |
|
482 if (useSessionKey) { |
|
483 /* use PKCS#11 session key objects */ |
|
484 PK11RSAGenParams rsaparams; |
|
485 void * params; |
|
486 |
|
487 slot = PK11_FindSlotByName(slotname); /* locate target slot */ |
|
488 if (!slot) { |
|
489 fprintf(stderr, "Can't find slot \"%s\"\n", slotname); |
|
490 exit(1); |
|
491 } |
|
492 |
|
493 doKeyGen = PR_TRUE; /* Always do a keygen for session keys. |
|
494 Import of hardcoded key is not supported */ |
|
495 /* do a temporary keygen in selected slot */ |
|
496 if (!keybits) { |
|
497 keybits = DEFAULT_KEY_BITS; |
|
498 } |
|
499 |
|
500 printf("Using PKCS#11 with %ld bits session key in token %s.\n", |
|
501 keybits, PK11_GetTokenName(slot)); |
|
502 |
|
503 rsaparams.keySizeInBits = keybits; |
|
504 rsaparams.pe = publicExponent; |
|
505 params = &rsaparams; |
|
506 |
|
507 fprintf(stderr,"\nGenerating RSA key. This may take a few moments.\n"); |
|
508 |
|
509 privHighKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, |
|
510 params, &pubHighKey, PR_FALSE, |
|
511 PR_FALSE, (void*)&pwData); |
|
512 if (!privHighKey) { |
|
513 fprintf(stderr, |
|
514 "Key generation failed in token \"%s\"\n", |
|
515 PK11_GetTokenName(slot)); |
|
516 exit(1); |
|
517 } |
|
518 |
|
519 SECKEY_CacheStaticFlags(privHighKey); |
|
520 |
|
521 fprintf(stderr,"Keygen completed.\n"); |
|
522 |
|
523 if (doPub) { |
|
524 /* do public key operations */ |
|
525 fn = (RSAOp)PK11_PublicKeyOp; |
|
526 rsaKey = (void *) pubHighKey; |
|
527 } else { |
|
528 /* do private key operations */ |
|
529 fn = (RSAOp)PK11_PrivateKeyOp; |
|
530 keys.privKey = privHighKey; |
|
531 keys.pubKey = pubHighKey; |
|
532 rsaKey = (void *) &keys; |
|
533 } |
|
534 } else |
|
535 |
|
536 { |
|
537 /* use freebl directly */ |
|
538 if (!keybits) { |
|
539 keybits = DEFAULT_KEY_BITS; |
|
540 } |
|
541 if (!doKeyGen) { |
|
542 if (keybits != DEFAULT_KEY_BITS) { |
|
543 doKeyGen = PR_TRUE; |
|
544 } |
|
545 } |
|
546 printf("Using freebl with %ld bits key.\n", keybits); |
|
547 if (doKeyGen) { |
|
548 fprintf(stderr,"\nGenerating RSA key. " |
|
549 "This may take a few moments.\n"); |
|
550 for (i=0; i < 4; i++) { |
|
551 if (peCount || (publicExponent & ((unsigned long)0xff000000L >> |
|
552 (i*8)))) { |
|
553 pubEx[peCount] = (CK_BYTE)((publicExponent >> |
|
554 (3-i)*8) & 0xff); |
|
555 peCount++; |
|
556 } |
|
557 } |
|
558 pe.len = peCount; |
|
559 pe.data = &pubEx[0]; |
|
560 pe.type = siBuffer; |
|
561 |
|
562 rsaKey = RSA_NewKey(keybits, &pe); |
|
563 fprintf(stderr,"Keygen completed.\n"); |
|
564 } else { |
|
565 /* use a hardcoded key */ |
|
566 printf("Using hardcoded %ld bits key.\n", keybits); |
|
567 if (doPub) { |
|
568 pubKey = getDefaultRSAPublicKey(); |
|
569 } else { |
|
570 privKey = getDefaultRSAPrivateKey(); |
|
571 } |
|
572 } |
|
573 |
|
574 if (doPub) { |
|
575 /* do public key operations */ |
|
576 fn = (RSAOp)RSA_PublicKeyOp; |
|
577 if (rsaKey) { |
|
578 /* convert the RSAPrivateKey to RSAPublicKey */ |
|
579 pubKeyStr.arena = NULL; |
|
580 pubKeyStr.modulus = ((RSAPrivateKey*)rsaKey)->modulus; |
|
581 pubKeyStr.publicExponent = |
|
582 ((RSAPrivateKey*)rsaKey)->publicExponent; |
|
583 rsaKey = &pubKeyStr; |
|
584 } else { |
|
585 /* convert NSSLOWKeyPublicKey to RSAPublicKey */ |
|
586 rsaKey = (void *)(&pubKey->u.rsa); |
|
587 } |
|
588 PORT_Assert(rsaKey); |
|
589 } else { |
|
590 /* do private key operations */ |
|
591 fn = (RSAOp)RSA_PrivateKeyOp; |
|
592 if (privKey) { |
|
593 /* convert NSSLOWKeyPrivateKey to RSAPrivateKey */ |
|
594 rsaKey = (void *)(&privKey->u.rsa); |
|
595 } |
|
596 PORT_Assert(rsaKey); |
|
597 } |
|
598 } |
|
599 |
|
600 memset(buf, 1, sizeof buf); |
|
601 rv = fn(rsaKey, buf2, buf); |
|
602 if (rv != SECSuccess) { |
|
603 PRErrorCode errNum; |
|
604 const char * errStr = NULL; |
|
605 |
|
606 errNum = PORT_GetError(); |
|
607 if (errNum) |
|
608 errStr = SECU_Strerror(errNum); |
|
609 else |
|
610 errNum = rv; |
|
611 if (!errStr) |
|
612 errStr = "(null)"; |
|
613 fprintf(stderr, "Error in RSA operation: %d : %s\n", errNum, errStr); |
|
614 exit(1); |
|
615 } |
|
616 |
|
617 threadsArr = (PRThread**)PORT_Alloc(threadNum*sizeof(PRThread*)); |
|
618 runDataArr = (ThreadRunData**)PORT_Alloc(threadNum*sizeof(ThreadRunData*)); |
|
619 timeCtx = CreateTimingContext(); |
|
620 TimingBegin(timeCtx, PR_Now()); |
|
621 for (i = 0;i < threadNum;i++) { |
|
622 runDataArr[i] = (ThreadRunData*)PORT_Alloc(sizeof(ThreadRunData)); |
|
623 runDataArr[i]->fn = fn; |
|
624 runDataArr[i]->buf = buf; |
|
625 runDataArr[i]->doIters = &doIters; |
|
626 runDataArr[i]->rsaKey = rsaKey; |
|
627 runDataArr[i]->seconds = seconds; |
|
628 runDataArr[i]->iters = iters; |
|
629 threadsArr[i] = |
|
630 PR_CreateThread(PR_USER_THREAD, |
|
631 ThreadExecFunction, |
|
632 (void*) runDataArr[i], |
|
633 PR_PRIORITY_NORMAL, |
|
634 PR_GLOBAL_THREAD, |
|
635 PR_JOINABLE_THREAD, |
|
636 0); |
|
637 } |
|
638 iters = 0; |
|
639 calcThreads = 0; |
|
640 for (i = 0;i < threadNum;i++, calcThreads++) |
|
641 { |
|
642 PR_JoinThread(threadsArr[i]); |
|
643 if (runDataArr[i]->status != SECSuccess) { |
|
644 const char * errStr = SECU_Strerror(runDataArr[i]->errNum); |
|
645 fprintf(stderr, "Thread %d: Error in RSA operation: %d : %s\n", |
|
646 i, runDataArr[i]->errNum, errStr); |
|
647 calcThreads -= 1; |
|
648 } else { |
|
649 iters += runDataArr[i]->iterRes; |
|
650 } |
|
651 PORT_Free((void*)runDataArr[i]); |
|
652 } |
|
653 PORT_Free(runDataArr); |
|
654 PORT_Free(threadsArr); |
|
655 |
|
656 TimingEnd(timeCtx, PR_Now()); |
|
657 |
|
658 printf("%ld iterations in %s\n", |
|
659 iters, TimingGenerateString(timeCtx)); |
|
660 printf("%.2f operations/s .\n", ((double)(iters)*(double)1000000.0) / |
|
661 (double)timeCtx->interval ); |
|
662 TimingDivide(timeCtx, iters); |
|
663 printf("one operation every %s\n", TimingGenerateString(timeCtx)); |
|
664 |
|
665 if (pubHighKey) { |
|
666 SECKEY_DestroyPublicKey(pubHighKey); |
|
667 } |
|
668 |
|
669 if (privHighKey) { |
|
670 SECKEY_DestroyPrivateKey(privHighKey); |
|
671 } |
|
672 |
|
673 if (cert) { |
|
674 CERT_DestroyCertificate(cert); |
|
675 } |
|
676 |
|
677 if (NSS_Shutdown() != SECSuccess) { |
|
678 exit(1); |
|
679 } |
|
680 |
|
681 return 0; |
|
682 } |