security/nss/cmd/rsaperf/rsaperf.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial