1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/cmd/rsaperf/rsaperf.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,682 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "seccomon.h" 1.9 +#include "cert.h" 1.10 +#include "secutil.h" 1.11 +#include "nspr.h" 1.12 +#include "nss.h" 1.13 +#include "blapi.h" 1.14 +#include "plgetopt.h" 1.15 +#include "lowkeyi.h" 1.16 +#include "pk11pub.h" 1.17 + 1.18 + 1.19 +#define DEFAULT_ITERS 10 1.20 +#define DEFAULT_DURATION 10 1.21 +#define DEFAULT_KEY_BITS 1024 1.22 +#define MIN_KEY_BITS 512 1.23 +#define MAX_KEY_BITS 65536 1.24 +#define BUFFER_BYTES MAX_KEY_BITS / 8 1.25 +#define DEFAULT_THREADS 1 1.26 +#define DEFAULT_EXPONENT 0x10001 1.27 + 1.28 +extern NSSLOWKEYPrivateKey * getDefaultRSAPrivateKey(void); 1.29 +extern NSSLOWKEYPublicKey * getDefaultRSAPublicKey(void); 1.30 + 1.31 +secuPWData pwData = { PW_NONE, NULL }; 1.32 + 1.33 +typedef struct TimingContextStr TimingContext; 1.34 + 1.35 +struct TimingContextStr { 1.36 + PRTime start; 1.37 + PRTime end; 1.38 + PRTime interval; 1.39 + 1.40 + long days; 1.41 + int hours; 1.42 + int minutes; 1.43 + int seconds; 1.44 + int millisecs; 1.45 +}; 1.46 + 1.47 +TimingContext *CreateTimingContext(void) { 1.48 + return PORT_Alloc(sizeof(TimingContext)); 1.49 +} 1.50 + 1.51 +void DestroyTimingContext(TimingContext *ctx) { 1.52 + PORT_Free(ctx); 1.53 +} 1.54 + 1.55 +void TimingBegin(TimingContext *ctx, PRTime begin) { 1.56 + ctx->start = begin; 1.57 +} 1.58 + 1.59 +static void timingUpdate(TimingContext *ctx) { 1.60 + PRInt64 tmp, remaining; 1.61 + PRInt64 L1000,L60,L24; 1.62 + 1.63 + LL_I2L(L1000,1000); 1.64 + LL_I2L(L60,60); 1.65 + LL_I2L(L24,24); 1.66 + 1.67 + LL_DIV(remaining, ctx->interval, L1000); 1.68 + LL_MOD(tmp, remaining, L1000); 1.69 + LL_L2I(ctx->millisecs, tmp); 1.70 + LL_DIV(remaining, remaining, L1000); 1.71 + LL_MOD(tmp, remaining, L60); 1.72 + LL_L2I(ctx->seconds, tmp); 1.73 + LL_DIV(remaining, remaining, L60); 1.74 + LL_MOD(tmp, remaining, L60); 1.75 + LL_L2I(ctx->minutes, tmp); 1.76 + LL_DIV(remaining, remaining, L60); 1.77 + LL_MOD(tmp, remaining, L24); 1.78 + LL_L2I(ctx->hours, tmp); 1.79 + LL_DIV(remaining, remaining, L24); 1.80 + LL_L2I(ctx->days, remaining); 1.81 +} 1.82 + 1.83 +void TimingEnd(TimingContext *ctx, PRTime end) { 1.84 + ctx->end = end; 1.85 + LL_SUB(ctx->interval, ctx->end, ctx->start); 1.86 + PORT_Assert(LL_GE_ZERO(ctx->interval)); 1.87 + timingUpdate(ctx); 1.88 +} 1.89 + 1.90 +void TimingDivide(TimingContext *ctx, int divisor) { 1.91 + PRInt64 tmp; 1.92 + 1.93 + LL_I2L(tmp, divisor); 1.94 + LL_DIV(ctx->interval, ctx->interval, tmp); 1.95 + 1.96 + timingUpdate(ctx); 1.97 +} 1.98 + 1.99 +char *TimingGenerateString(TimingContext *ctx) { 1.100 + char *buf = NULL; 1.101 + 1.102 + if (ctx->days != 0) { 1.103 + buf = PR_sprintf_append(buf, "%d days", ctx->days); 1.104 + } 1.105 + if (ctx->hours != 0) { 1.106 + if (buf != NULL) buf = PR_sprintf_append(buf, ", "); 1.107 + buf = PR_sprintf_append(buf, "%d hours", ctx->hours); 1.108 + } 1.109 + if (ctx->minutes != 0) { 1.110 + if (buf != NULL) buf = PR_sprintf_append(buf, ", "); 1.111 + buf = PR_sprintf_append(buf, "%d minutes", ctx->minutes); 1.112 + } 1.113 + if (buf != NULL) buf = PR_sprintf_append(buf, ", and "); 1.114 + if (!buf && ctx->seconds == 0) { 1.115 + int interval; 1.116 + LL_L2I(interval, ctx->interval); 1.117 + if (ctx->millisecs < 100) 1.118 + buf = PR_sprintf_append(buf, "%d microseconds", interval); 1.119 + else 1.120 + buf = PR_sprintf_append(buf, "%d milliseconds", ctx->millisecs); 1.121 + } else if (ctx->millisecs == 0) { 1.122 + buf = PR_sprintf_append(buf, "%d seconds", ctx->seconds); 1.123 + } else { 1.124 + buf = PR_sprintf_append(buf, "%d.%03d seconds", 1.125 + ctx->seconds, ctx->millisecs); 1.126 + } 1.127 + return buf; 1.128 +} 1.129 + 1.130 +void 1.131 +Usage(char *progName) 1.132 +{ 1.133 + fprintf(stderr, "Usage: %s [-s | -e] [-i iterations | -p period] " 1.134 + "[-t threads]\n[-n none [-k keylength] [ [-g] -x exponent] |\n" 1.135 + " -n token:nickname [-d certdir] [-w password] |\n" 1.136 + " -h token [-d certdir] [-w password] [-g] [-k keylength] " 1.137 + "[-x exponent] [-f pwfile]\n", 1.138 + progName); 1.139 + fprintf(stderr, "%-20s Cert database directory (default is ~/.netscape)\n", 1.140 + "-d certdir"); 1.141 + fprintf(stderr, "%-20s How many operations to perform\n", "-i iterations"); 1.142 + fprintf(stderr, "%-20s How many seconds to run\n", "-p period"); 1.143 + fprintf(stderr, "%-20s Perform signing (private key) operations\n", "-s"); 1.144 + fprintf(stderr, "%-20s Perform encryption (public key) operations\n","-e"); 1.145 + fprintf(stderr, "%-20s Nickname of certificate or key, prefixed " 1.146 + "by optional token name\n", "-n nickname"); 1.147 + fprintf(stderr, "%-20s PKCS#11 token to perform operation with.\n", 1.148 + "-h token"); 1.149 + fprintf(stderr, "%-20s key size in bits, from %d to %d\n", "-k keylength", 1.150 + MIN_KEY_BITS, MAX_KEY_BITS); 1.151 + fprintf(stderr, "%-20s token password\n", "-w password"); 1.152 + fprintf(stderr, "%-20s temporary key generation. Not for token keys.\n", 1.153 + "-g"); 1.154 + fprintf(stderr, "%-20s set public exponent for keygen\n", "-x"); 1.155 + fprintf(stderr, "%-20s Number of execution threads (default 1)\n", 1.156 + "-t threads"); 1.157 + exit(-1); 1.158 +} 1.159 + 1.160 +static void 1.161 +dumpBytes( unsigned char * b, int l) 1.162 +{ 1.163 + int i; 1.164 + if (l <= 0) 1.165 + return; 1.166 + for (i = 0; i < l; ++i) { 1.167 + if (i % 16 == 0) 1.168 + printf("\t"); 1.169 + printf(" %02x", b[i]); 1.170 + if (i % 16 == 15) 1.171 + printf("\n"); 1.172 + } 1.173 + if ((i % 16) != 0) 1.174 + printf("\n"); 1.175 +} 1.176 + 1.177 +static void 1.178 +dumpItem( SECItem * item, const char * description) 1.179 +{ 1.180 + if (item->len & 1 && item->data[0] == 0) { 1.181 + printf("%s: (%d bytes)\n", description, item->len - 1); 1.182 + dumpBytes(item->data + 1, item->len - 1); 1.183 + } else { 1.184 + printf("%s: (%d bytes)\n", description, item->len); 1.185 + dumpBytes(item->data, item->len); 1.186 + } 1.187 +} 1.188 + 1.189 +void 1.190 +printPrivKey(NSSLOWKEYPrivateKey * privKey) 1.191 +{ 1.192 + RSAPrivateKey *rsa = &privKey->u.rsa; 1.193 + 1.194 + dumpItem( &rsa->modulus, "n"); 1.195 + dumpItem( &rsa->publicExponent, "e"); 1.196 + dumpItem( &rsa->privateExponent, "d"); 1.197 + dumpItem( &rsa->prime1, "P"); 1.198 + dumpItem( &rsa->prime2, "Q"); 1.199 + dumpItem( &rsa->exponent1, "d % (P-1)"); 1.200 + dumpItem( &rsa->exponent2, "d % (Q-1)"); 1.201 + dumpItem( &rsa->coefficient, "(Q ** -1) % P"); 1.202 + puts(""); 1.203 +} 1.204 + 1.205 +typedef SECStatus (* RSAOp)(void * key, 1.206 + unsigned char * output, 1.207 + unsigned char * input); 1.208 + 1.209 +typedef struct { 1.210 + SECKEYPublicKey* pubKey; 1.211 + SECKEYPrivateKey* privKey; 1.212 +} PK11Keys; 1.213 + 1.214 + 1.215 +SECStatus PK11_PublicKeyOp (SECKEYPublicKey* key, 1.216 + unsigned char * output, 1.217 + unsigned char * input) 1.218 +{ 1.219 + return PK11_PubEncryptRaw(key, output, input, key->u.rsa.modulus.len, 1.220 + NULL); 1.221 +} 1.222 + 1.223 +SECStatus PK11_PrivateKeyOp (PK11Keys* keys, 1.224 + unsigned char * output, 1.225 + unsigned char * input) 1.226 +{ 1.227 + unsigned outLen = 0; 1.228 + return PK11_PrivDecryptRaw(keys->privKey, 1.229 + output, &outLen, 1.230 + keys->pubKey->u.rsa.modulus.len, input, 1.231 + keys->pubKey->u.rsa.modulus.len); 1.232 +} 1.233 +typedef struct ThreadRunDataStr ThreadRunData; 1.234 + 1.235 +struct ThreadRunDataStr { 1.236 + const PRBool *doIters; 1.237 + const void *rsaKey; 1.238 + const unsigned char *buf; 1.239 + RSAOp fn; 1.240 + int seconds; 1.241 + long iters; 1.242 + long iterRes; 1.243 + PRErrorCode errNum; 1.244 + SECStatus status; 1.245 +}; 1.246 + 1.247 + 1.248 +void ThreadExecFunction(void *data) 1.249 +{ 1.250 + ThreadRunData *tdata = (ThreadRunData*)data; 1.251 + unsigned char buf2[BUFFER_BYTES]; 1.252 + 1.253 + tdata->status = SECSuccess; 1.254 + if (*tdata->doIters) { 1.255 + long i = tdata->iters; 1.256 + tdata->iterRes = 0; 1.257 + while (i--) { 1.258 + SECStatus rv = tdata->fn((void*)tdata->rsaKey, buf2, 1.259 + (unsigned char*)tdata->buf); 1.260 + if (rv != SECSuccess) { 1.261 + tdata->errNum = PORT_GetError(); 1.262 + tdata->status = rv; 1.263 + break; 1.264 + } 1.265 + tdata->iterRes++; 1.266 + } 1.267 + } else { 1.268 + PRIntervalTime total = PR_SecondsToInterval(tdata->seconds); 1.269 + PRIntervalTime start = PR_IntervalNow(); 1.270 + tdata->iterRes = 0; 1.271 + while (PR_IntervalNow() - start < total) { 1.272 + SECStatus rv = tdata->fn((void*)tdata->rsaKey, buf2, 1.273 + (unsigned char*)tdata->buf); 1.274 + if (rv != SECSuccess) { 1.275 + tdata->errNum = PORT_GetError(); 1.276 + tdata->status = rv; 1.277 + break; 1.278 + } 1.279 + tdata->iterRes++; 1.280 + } 1.281 + } 1.282 +} 1.283 + 1.284 +#define INT_ARG(arg,def) atol(arg)>0?atol(arg):def 1.285 + 1.286 +int 1.287 +main(int argc, char **argv) 1.288 +{ 1.289 + TimingContext * timeCtx = NULL; 1.290 + SECKEYPublicKey * pubHighKey = NULL; 1.291 + SECKEYPrivateKey * privHighKey = NULL; 1.292 + NSSLOWKEYPrivateKey * privKey = NULL; 1.293 + NSSLOWKEYPublicKey * pubKey = NULL; 1.294 + CERTCertificate * cert = NULL; 1.295 + char * progName = NULL; 1.296 + char * secDir = NULL; 1.297 + char * nickname = NULL; 1.298 + char * slotname = NULL; 1.299 + long keybits = 0; 1.300 + RSAOp fn; 1.301 + void * rsaKey = NULL; 1.302 + PLOptState * optstate; 1.303 + PLOptStatus optstatus; 1.304 + long iters = DEFAULT_ITERS; 1.305 + int i; 1.306 + PRBool doPriv = PR_FALSE; 1.307 + PRBool doPub = PR_FALSE; 1.308 + int rv; 1.309 + unsigned char buf[BUFFER_BYTES]; 1.310 + unsigned char buf2[BUFFER_BYTES]; 1.311 + int seconds = DEFAULT_DURATION; 1.312 + PRBool doIters = PR_FALSE; 1.313 + PRBool doTime = PR_FALSE; 1.314 + PRBool useTokenKey = PR_FALSE; /* use PKCS#11 token 1.315 + object key */ 1.316 + PRBool useSessionKey = PR_FALSE; /* use PKCS#11 session 1.317 + object key */ 1.318 + PRBool useBLKey = PR_FALSE; /* use freebl */ 1.319 + PK11SlotInfo* slot = NULL; /* slot for session 1.320 + object key operations */ 1.321 + PRBool doKeyGen = PR_FALSE; 1.322 + int publicExponent = DEFAULT_EXPONENT; 1.323 + PK11Keys keys; 1.324 + int peCount = 0; 1.325 + CK_BYTE pubEx[4]; 1.326 + SECItem pe; 1.327 + RSAPublicKey pubKeyStr; 1.328 + int threadNum = DEFAULT_THREADS; 1.329 + ThreadRunData ** runDataArr = NULL; 1.330 + PRThread ** threadsArr = NULL; 1.331 + int calcThreads = 0; 1.332 + 1.333 + progName = strrchr(argv[0], '/'); 1.334 + if (!progName) 1.335 + progName = strrchr(argv[0], '\\'); 1.336 + progName = progName ? progName+1 : argv[0]; 1.337 + 1.338 + optstate = PL_CreateOptState(argc, argv, "d:ef:gh:i:k:n:p:st:w:x:"); 1.339 + while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) { 1.340 + switch (optstate->option) { 1.341 + case '?': 1.342 + Usage(progName); 1.343 + break; 1.344 + case 'd': 1.345 + secDir = PORT_Strdup(optstate->value); 1.346 + break; 1.347 + case 'i': 1.348 + iters = INT_ARG(optstate->value, DEFAULT_ITERS); 1.349 + doIters = PR_TRUE; 1.350 + break; 1.351 + case 's': 1.352 + doPriv = PR_TRUE; 1.353 + break; 1.354 + case 'e': 1.355 + doPub = PR_TRUE; 1.356 + break; 1.357 + case 'g': 1.358 + doKeyGen = PR_TRUE; 1.359 + break; 1.360 + case 'n': 1.361 + nickname = PORT_Strdup(optstate->value); 1.362 + /* for compatibility, nickname of "none" means go to freebl */ 1.363 + if (nickname && strcmp(nickname, "none")) { 1.364 + useTokenKey = PR_TRUE; 1.365 + } else { 1.366 + useBLKey = PR_TRUE; 1.367 + } 1.368 + break; 1.369 + case 'p': 1.370 + seconds = INT_ARG(optstate->value, DEFAULT_DURATION); 1.371 + doTime = PR_TRUE; 1.372 + break; 1.373 + case 'h': 1.374 + slotname = PORT_Strdup(optstate->value); 1.375 + useSessionKey = PR_TRUE; 1.376 + break; 1.377 + case 'k': 1.378 + keybits = INT_ARG(optstate->value, DEFAULT_KEY_BITS); 1.379 + break; 1.380 + case 'w': 1.381 + pwData.data = PORT_Strdup(optstate->value);; 1.382 + pwData.source = PW_PLAINTEXT; 1.383 + break; 1.384 + case 'f': 1.385 + pwData.data = PORT_Strdup(optstate->value); 1.386 + pwData.source = PW_FROMFILE; 1.387 + break; 1.388 + case 'x': 1.389 + /* -x public exponent (for RSA keygen) */ 1.390 + publicExponent = INT_ARG(optstate->value, DEFAULT_EXPONENT); 1.391 + break; 1.392 + case 't': 1.393 + threadNum = INT_ARG(optstate->value, DEFAULT_THREADS); 1.394 + break; 1.395 + } 1.396 + } 1.397 + if (optstatus == PL_OPT_BAD) 1.398 + Usage(progName); 1.399 + 1.400 + if ((doPriv && doPub) || (doIters && doTime) || 1.401 + ((useTokenKey + useSessionKey + useBLKey) != PR_TRUE) || 1.402 + (useTokenKey && keybits) || (useTokenKey && doKeyGen) || 1.403 + (keybits && (keybits<MIN_KEY_BITS || keybits>MAX_KEY_BITS))) { 1.404 + Usage(progName); 1.405 + } 1.406 + 1.407 + if (!doPriv && !doPub) doPriv = PR_TRUE; 1.408 + 1.409 + if (doIters && doTime) Usage(progName); 1.410 + 1.411 + if (!doTime) { 1.412 + doIters = PR_TRUE; 1.413 + } 1.414 + 1.415 + PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); 1.416 + 1.417 + PK11_SetPasswordFunc(SECU_GetModulePassword); 1.418 + secDir = SECU_ConfigDirectory(secDir); 1.419 + 1.420 + if (useTokenKey || useSessionKey) { 1.421 + rv = NSS_Init(secDir); 1.422 + if (rv != SECSuccess) { 1.423 + fprintf(stderr, "NSS_Init failed.\n"); 1.424 + exit(1); 1.425 + } 1.426 + } else { 1.427 + rv = NSS_NoDB_Init(NULL); 1.428 + if (rv != SECSuccess) { 1.429 + fprintf(stderr, "NSS_NoDB_Init failed.\n"); 1.430 + exit(1); 1.431 + } 1.432 + } 1.433 + 1.434 + if (useTokenKey) { 1.435 + CK_OBJECT_HANDLE kh = CK_INVALID_HANDLE; 1.436 + CERTCertDBHandle* certdb = NULL; 1.437 + certdb = CERT_GetDefaultCertDB(); 1.438 + 1.439 + cert = PK11_FindCertFromNickname(nickname, &pwData); 1.440 + if (cert == NULL) { 1.441 + fprintf(stderr, 1.442 + "Can't find certificate by name \"%s\"\n", nickname); 1.443 + exit(1); 1.444 + } 1.445 + pubHighKey = CERT_ExtractPublicKey(cert); 1.446 + if (pubHighKey == NULL) { 1.447 + fprintf(stderr, "Can't extract public key from certificate"); 1.448 + exit(1); 1.449 + } 1.450 + 1.451 + if (doPub) { 1.452 + /* do public key ops */ 1.453 + fn = (RSAOp)PK11_PublicKeyOp; 1.454 + rsaKey = (void *) pubHighKey; 1.455 + 1.456 + kh = PK11_ImportPublicKey(cert->slot, pubHighKey, PR_FALSE); 1.457 + if (CK_INVALID_HANDLE == kh) { 1.458 + fprintf(stderr, 1.459 + "Unable to import public key to certificate slot."); 1.460 + exit(1); 1.461 + } 1.462 + pubHighKey->pkcs11Slot = PK11_ReferenceSlot(cert->slot); 1.463 + pubHighKey->pkcs11ID = kh; 1.464 + printf("Using PKCS#11 for RSA encryption with token %s.\n", 1.465 + PK11_GetTokenName(cert->slot)); 1.466 + } else { 1.467 + /* do private key ops */ 1.468 + privHighKey = PK11_FindKeyByAnyCert(cert, &pwData); 1.469 + if (privHighKey == NULL) { 1.470 + fprintf(stderr, 1.471 + "Can't find private key by name \"%s\"\n", nickname); 1.472 + exit(1); 1.473 + } 1.474 + 1.475 + SECKEY_CacheStaticFlags(privHighKey); 1.476 + fn = (RSAOp)PK11_PrivateKeyOp; 1.477 + keys.privKey = privHighKey; 1.478 + keys.pubKey = pubHighKey; 1.479 + rsaKey = (void *) &keys; 1.480 + printf("Using PKCS#11 for RSA decryption with token %s.\n", 1.481 + PK11_GetTokenName(privHighKey->pkcs11Slot)); 1.482 + } 1.483 + } else 1.484 + 1.485 + if (useSessionKey) { 1.486 + /* use PKCS#11 session key objects */ 1.487 + PK11RSAGenParams rsaparams; 1.488 + void * params; 1.489 + 1.490 + slot = PK11_FindSlotByName(slotname); /* locate target slot */ 1.491 + if (!slot) { 1.492 + fprintf(stderr, "Can't find slot \"%s\"\n", slotname); 1.493 + exit(1); 1.494 + } 1.495 + 1.496 + doKeyGen = PR_TRUE; /* Always do a keygen for session keys. 1.497 + Import of hardcoded key is not supported */ 1.498 + /* do a temporary keygen in selected slot */ 1.499 + if (!keybits) { 1.500 + keybits = DEFAULT_KEY_BITS; 1.501 + } 1.502 + 1.503 + printf("Using PKCS#11 with %ld bits session key in token %s.\n", 1.504 + keybits, PK11_GetTokenName(slot)); 1.505 + 1.506 + rsaparams.keySizeInBits = keybits; 1.507 + rsaparams.pe = publicExponent; 1.508 + params = &rsaparams; 1.509 + 1.510 + fprintf(stderr,"\nGenerating RSA key. This may take a few moments.\n"); 1.511 + 1.512 + privHighKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, 1.513 + params, &pubHighKey, PR_FALSE, 1.514 + PR_FALSE, (void*)&pwData); 1.515 + if (!privHighKey) { 1.516 + fprintf(stderr, 1.517 + "Key generation failed in token \"%s\"\n", 1.518 + PK11_GetTokenName(slot)); 1.519 + exit(1); 1.520 + } 1.521 + 1.522 + SECKEY_CacheStaticFlags(privHighKey); 1.523 + 1.524 + fprintf(stderr,"Keygen completed.\n"); 1.525 + 1.526 + if (doPub) { 1.527 + /* do public key operations */ 1.528 + fn = (RSAOp)PK11_PublicKeyOp; 1.529 + rsaKey = (void *) pubHighKey; 1.530 + } else { 1.531 + /* do private key operations */ 1.532 + fn = (RSAOp)PK11_PrivateKeyOp; 1.533 + keys.privKey = privHighKey; 1.534 + keys.pubKey = pubHighKey; 1.535 + rsaKey = (void *) &keys; 1.536 + } 1.537 + } else 1.538 + 1.539 + { 1.540 + /* use freebl directly */ 1.541 + if (!keybits) { 1.542 + keybits = DEFAULT_KEY_BITS; 1.543 + } 1.544 + if (!doKeyGen) { 1.545 + if (keybits != DEFAULT_KEY_BITS) { 1.546 + doKeyGen = PR_TRUE; 1.547 + } 1.548 + } 1.549 + printf("Using freebl with %ld bits key.\n", keybits); 1.550 + if (doKeyGen) { 1.551 + fprintf(stderr,"\nGenerating RSA key. " 1.552 + "This may take a few moments.\n"); 1.553 + for (i=0; i < 4; i++) { 1.554 + if (peCount || (publicExponent & ((unsigned long)0xff000000L >> 1.555 + (i*8)))) { 1.556 + pubEx[peCount] = (CK_BYTE)((publicExponent >> 1.557 + (3-i)*8) & 0xff); 1.558 + peCount++; 1.559 + } 1.560 + } 1.561 + pe.len = peCount; 1.562 + pe.data = &pubEx[0]; 1.563 + pe.type = siBuffer; 1.564 + 1.565 + rsaKey = RSA_NewKey(keybits, &pe); 1.566 + fprintf(stderr,"Keygen completed.\n"); 1.567 + } else { 1.568 + /* use a hardcoded key */ 1.569 + printf("Using hardcoded %ld bits key.\n", keybits); 1.570 + if (doPub) { 1.571 + pubKey = getDefaultRSAPublicKey(); 1.572 + } else { 1.573 + privKey = getDefaultRSAPrivateKey(); 1.574 + } 1.575 + } 1.576 + 1.577 + if (doPub) { 1.578 + /* do public key operations */ 1.579 + fn = (RSAOp)RSA_PublicKeyOp; 1.580 + if (rsaKey) { 1.581 + /* convert the RSAPrivateKey to RSAPublicKey */ 1.582 + pubKeyStr.arena = NULL; 1.583 + pubKeyStr.modulus = ((RSAPrivateKey*)rsaKey)->modulus; 1.584 + pubKeyStr.publicExponent = 1.585 + ((RSAPrivateKey*)rsaKey)->publicExponent; 1.586 + rsaKey = &pubKeyStr; 1.587 + } else { 1.588 + /* convert NSSLOWKeyPublicKey to RSAPublicKey */ 1.589 + rsaKey = (void *)(&pubKey->u.rsa); 1.590 + } 1.591 + PORT_Assert(rsaKey); 1.592 + } else { 1.593 + /* do private key operations */ 1.594 + fn = (RSAOp)RSA_PrivateKeyOp; 1.595 + if (privKey) { 1.596 + /* convert NSSLOWKeyPrivateKey to RSAPrivateKey */ 1.597 + rsaKey = (void *)(&privKey->u.rsa); 1.598 + } 1.599 + PORT_Assert(rsaKey); 1.600 + } 1.601 + } 1.602 + 1.603 + memset(buf, 1, sizeof buf); 1.604 + rv = fn(rsaKey, buf2, buf); 1.605 + if (rv != SECSuccess) { 1.606 + PRErrorCode errNum; 1.607 + const char * errStr = NULL; 1.608 + 1.609 + errNum = PORT_GetError(); 1.610 + if (errNum) 1.611 + errStr = SECU_Strerror(errNum); 1.612 + else 1.613 + errNum = rv; 1.614 + if (!errStr) 1.615 + errStr = "(null)"; 1.616 + fprintf(stderr, "Error in RSA operation: %d : %s\n", errNum, errStr); 1.617 + exit(1); 1.618 + } 1.619 + 1.620 + threadsArr = (PRThread**)PORT_Alloc(threadNum*sizeof(PRThread*)); 1.621 + runDataArr = (ThreadRunData**)PORT_Alloc(threadNum*sizeof(ThreadRunData*)); 1.622 + timeCtx = CreateTimingContext(); 1.623 + TimingBegin(timeCtx, PR_Now()); 1.624 + for (i = 0;i < threadNum;i++) { 1.625 + runDataArr[i] = (ThreadRunData*)PORT_Alloc(sizeof(ThreadRunData)); 1.626 + runDataArr[i]->fn = fn; 1.627 + runDataArr[i]->buf = buf; 1.628 + runDataArr[i]->doIters = &doIters; 1.629 + runDataArr[i]->rsaKey = rsaKey; 1.630 + runDataArr[i]->seconds = seconds; 1.631 + runDataArr[i]->iters = iters; 1.632 + threadsArr[i] = 1.633 + PR_CreateThread(PR_USER_THREAD, 1.634 + ThreadExecFunction, 1.635 + (void*) runDataArr[i], 1.636 + PR_PRIORITY_NORMAL, 1.637 + PR_GLOBAL_THREAD, 1.638 + PR_JOINABLE_THREAD, 1.639 + 0); 1.640 + } 1.641 + iters = 0; 1.642 + calcThreads = 0; 1.643 + for (i = 0;i < threadNum;i++, calcThreads++) 1.644 + { 1.645 + PR_JoinThread(threadsArr[i]); 1.646 + if (runDataArr[i]->status != SECSuccess) { 1.647 + const char * errStr = SECU_Strerror(runDataArr[i]->errNum); 1.648 + fprintf(stderr, "Thread %d: Error in RSA operation: %d : %s\n", 1.649 + i, runDataArr[i]->errNum, errStr); 1.650 + calcThreads -= 1; 1.651 + } else { 1.652 + iters += runDataArr[i]->iterRes; 1.653 + } 1.654 + PORT_Free((void*)runDataArr[i]); 1.655 + } 1.656 + PORT_Free(runDataArr); 1.657 + PORT_Free(threadsArr); 1.658 + 1.659 + TimingEnd(timeCtx, PR_Now()); 1.660 + 1.661 + printf("%ld iterations in %s\n", 1.662 + iters, TimingGenerateString(timeCtx)); 1.663 + printf("%.2f operations/s .\n", ((double)(iters)*(double)1000000.0) / 1.664 + (double)timeCtx->interval ); 1.665 + TimingDivide(timeCtx, iters); 1.666 + printf("one operation every %s\n", TimingGenerateString(timeCtx)); 1.667 + 1.668 + if (pubHighKey) { 1.669 + SECKEY_DestroyPublicKey(pubHighKey); 1.670 + } 1.671 + 1.672 + if (privHighKey) { 1.673 + SECKEY_DestroyPrivateKey(privHighKey); 1.674 + } 1.675 + 1.676 + if (cert) { 1.677 + CERT_DestroyCertificate(cert); 1.678 + } 1.679 + 1.680 + if (NSS_Shutdown() != SECSuccess) { 1.681 + exit(1); 1.682 + } 1.683 + 1.684 + return 0; 1.685 +}