michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "seccomon.h" michael@0: #include "cert.h" michael@0: #include "secutil.h" michael@0: #include "nspr.h" michael@0: #include "nss.h" michael@0: #include "blapi.h" michael@0: #include "plgetopt.h" michael@0: #include "lowkeyi.h" michael@0: #include "pk11pub.h" michael@0: michael@0: michael@0: #define DEFAULT_ITERS 10 michael@0: #define DEFAULT_DURATION 10 michael@0: #define DEFAULT_KEY_BITS 1024 michael@0: #define MIN_KEY_BITS 512 michael@0: #define MAX_KEY_BITS 65536 michael@0: #define BUFFER_BYTES MAX_KEY_BITS / 8 michael@0: #define DEFAULT_THREADS 1 michael@0: #define DEFAULT_EXPONENT 0x10001 michael@0: michael@0: extern NSSLOWKEYPrivateKey * getDefaultRSAPrivateKey(void); michael@0: extern NSSLOWKEYPublicKey * getDefaultRSAPublicKey(void); michael@0: michael@0: secuPWData pwData = { PW_NONE, NULL }; michael@0: michael@0: typedef struct TimingContextStr TimingContext; michael@0: michael@0: struct TimingContextStr { michael@0: PRTime start; michael@0: PRTime end; michael@0: PRTime interval; michael@0: michael@0: long days; michael@0: int hours; michael@0: int minutes; michael@0: int seconds; michael@0: int millisecs; michael@0: }; michael@0: michael@0: TimingContext *CreateTimingContext(void) { michael@0: return PORT_Alloc(sizeof(TimingContext)); michael@0: } michael@0: michael@0: void DestroyTimingContext(TimingContext *ctx) { michael@0: PORT_Free(ctx); michael@0: } michael@0: michael@0: void TimingBegin(TimingContext *ctx, PRTime begin) { michael@0: ctx->start = begin; michael@0: } michael@0: michael@0: static void timingUpdate(TimingContext *ctx) { michael@0: PRInt64 tmp, remaining; michael@0: PRInt64 L1000,L60,L24; michael@0: michael@0: LL_I2L(L1000,1000); michael@0: LL_I2L(L60,60); michael@0: LL_I2L(L24,24); michael@0: michael@0: LL_DIV(remaining, ctx->interval, L1000); michael@0: LL_MOD(tmp, remaining, L1000); michael@0: LL_L2I(ctx->millisecs, tmp); michael@0: LL_DIV(remaining, remaining, L1000); michael@0: LL_MOD(tmp, remaining, L60); michael@0: LL_L2I(ctx->seconds, tmp); michael@0: LL_DIV(remaining, remaining, L60); michael@0: LL_MOD(tmp, remaining, L60); michael@0: LL_L2I(ctx->minutes, tmp); michael@0: LL_DIV(remaining, remaining, L60); michael@0: LL_MOD(tmp, remaining, L24); michael@0: LL_L2I(ctx->hours, tmp); michael@0: LL_DIV(remaining, remaining, L24); michael@0: LL_L2I(ctx->days, remaining); michael@0: } michael@0: michael@0: void TimingEnd(TimingContext *ctx, PRTime end) { michael@0: ctx->end = end; michael@0: LL_SUB(ctx->interval, ctx->end, ctx->start); michael@0: PORT_Assert(LL_GE_ZERO(ctx->interval)); michael@0: timingUpdate(ctx); michael@0: } michael@0: michael@0: void TimingDivide(TimingContext *ctx, int divisor) { michael@0: PRInt64 tmp; michael@0: michael@0: LL_I2L(tmp, divisor); michael@0: LL_DIV(ctx->interval, ctx->interval, tmp); michael@0: michael@0: timingUpdate(ctx); michael@0: } michael@0: michael@0: char *TimingGenerateString(TimingContext *ctx) { michael@0: char *buf = NULL; michael@0: michael@0: if (ctx->days != 0) { michael@0: buf = PR_sprintf_append(buf, "%d days", ctx->days); michael@0: } michael@0: if (ctx->hours != 0) { michael@0: if (buf != NULL) buf = PR_sprintf_append(buf, ", "); michael@0: buf = PR_sprintf_append(buf, "%d hours", ctx->hours); michael@0: } michael@0: if (ctx->minutes != 0) { michael@0: if (buf != NULL) buf = PR_sprintf_append(buf, ", "); michael@0: buf = PR_sprintf_append(buf, "%d minutes", ctx->minutes); michael@0: } michael@0: if (buf != NULL) buf = PR_sprintf_append(buf, ", and "); michael@0: if (!buf && ctx->seconds == 0) { michael@0: int interval; michael@0: LL_L2I(interval, ctx->interval); michael@0: if (ctx->millisecs < 100) michael@0: buf = PR_sprintf_append(buf, "%d microseconds", interval); michael@0: else michael@0: buf = PR_sprintf_append(buf, "%d milliseconds", ctx->millisecs); michael@0: } else if (ctx->millisecs == 0) { michael@0: buf = PR_sprintf_append(buf, "%d seconds", ctx->seconds); michael@0: } else { michael@0: buf = PR_sprintf_append(buf, "%d.%03d seconds", michael@0: ctx->seconds, ctx->millisecs); michael@0: } michael@0: return buf; michael@0: } michael@0: michael@0: void michael@0: Usage(char *progName) michael@0: { michael@0: fprintf(stderr, "Usage: %s [-s | -e] [-i iterations | -p period] " michael@0: "[-t threads]\n[-n none [-k keylength] [ [-g] -x exponent] |\n" michael@0: " -n token:nickname [-d certdir] [-w password] |\n" michael@0: " -h token [-d certdir] [-w password] [-g] [-k keylength] " michael@0: "[-x exponent] [-f pwfile]\n", michael@0: progName); michael@0: fprintf(stderr, "%-20s Cert database directory (default is ~/.netscape)\n", michael@0: "-d certdir"); michael@0: fprintf(stderr, "%-20s How many operations to perform\n", "-i iterations"); michael@0: fprintf(stderr, "%-20s How many seconds to run\n", "-p period"); michael@0: fprintf(stderr, "%-20s Perform signing (private key) operations\n", "-s"); michael@0: fprintf(stderr, "%-20s Perform encryption (public key) operations\n","-e"); michael@0: fprintf(stderr, "%-20s Nickname of certificate or key, prefixed " michael@0: "by optional token name\n", "-n nickname"); michael@0: fprintf(stderr, "%-20s PKCS#11 token to perform operation with.\n", michael@0: "-h token"); michael@0: fprintf(stderr, "%-20s key size in bits, from %d to %d\n", "-k keylength", michael@0: MIN_KEY_BITS, MAX_KEY_BITS); michael@0: fprintf(stderr, "%-20s token password\n", "-w password"); michael@0: fprintf(stderr, "%-20s temporary key generation. Not for token keys.\n", michael@0: "-g"); michael@0: fprintf(stderr, "%-20s set public exponent for keygen\n", "-x"); michael@0: fprintf(stderr, "%-20s Number of execution threads (default 1)\n", michael@0: "-t threads"); michael@0: exit(-1); michael@0: } michael@0: michael@0: static void michael@0: dumpBytes( unsigned char * b, int l) michael@0: { michael@0: int i; michael@0: if (l <= 0) michael@0: return; michael@0: for (i = 0; i < l; ++i) { michael@0: if (i % 16 == 0) michael@0: printf("\t"); michael@0: printf(" %02x", b[i]); michael@0: if (i % 16 == 15) michael@0: printf("\n"); michael@0: } michael@0: if ((i % 16) != 0) michael@0: printf("\n"); michael@0: } michael@0: michael@0: static void michael@0: dumpItem( SECItem * item, const char * description) michael@0: { michael@0: if (item->len & 1 && item->data[0] == 0) { michael@0: printf("%s: (%d bytes)\n", description, item->len - 1); michael@0: dumpBytes(item->data + 1, item->len - 1); michael@0: } else { michael@0: printf("%s: (%d bytes)\n", description, item->len); michael@0: dumpBytes(item->data, item->len); michael@0: } michael@0: } michael@0: michael@0: void michael@0: printPrivKey(NSSLOWKEYPrivateKey * privKey) michael@0: { michael@0: RSAPrivateKey *rsa = &privKey->u.rsa; michael@0: michael@0: dumpItem( &rsa->modulus, "n"); michael@0: dumpItem( &rsa->publicExponent, "e"); michael@0: dumpItem( &rsa->privateExponent, "d"); michael@0: dumpItem( &rsa->prime1, "P"); michael@0: dumpItem( &rsa->prime2, "Q"); michael@0: dumpItem( &rsa->exponent1, "d % (P-1)"); michael@0: dumpItem( &rsa->exponent2, "d % (Q-1)"); michael@0: dumpItem( &rsa->coefficient, "(Q ** -1) % P"); michael@0: puts(""); michael@0: } michael@0: michael@0: typedef SECStatus (* RSAOp)(void * key, michael@0: unsigned char * output, michael@0: unsigned char * input); michael@0: michael@0: typedef struct { michael@0: SECKEYPublicKey* pubKey; michael@0: SECKEYPrivateKey* privKey; michael@0: } PK11Keys; michael@0: michael@0: michael@0: SECStatus PK11_PublicKeyOp (SECKEYPublicKey* key, michael@0: unsigned char * output, michael@0: unsigned char * input) michael@0: { michael@0: return PK11_PubEncryptRaw(key, output, input, key->u.rsa.modulus.len, michael@0: NULL); michael@0: } michael@0: michael@0: SECStatus PK11_PrivateKeyOp (PK11Keys* keys, michael@0: unsigned char * output, michael@0: unsigned char * input) michael@0: { michael@0: unsigned outLen = 0; michael@0: return PK11_PrivDecryptRaw(keys->privKey, michael@0: output, &outLen, michael@0: keys->pubKey->u.rsa.modulus.len, input, michael@0: keys->pubKey->u.rsa.modulus.len); michael@0: } michael@0: typedef struct ThreadRunDataStr ThreadRunData; michael@0: michael@0: struct ThreadRunDataStr { michael@0: const PRBool *doIters; michael@0: const void *rsaKey; michael@0: const unsigned char *buf; michael@0: RSAOp fn; michael@0: int seconds; michael@0: long iters; michael@0: long iterRes; michael@0: PRErrorCode errNum; michael@0: SECStatus status; michael@0: }; michael@0: michael@0: michael@0: void ThreadExecFunction(void *data) michael@0: { michael@0: ThreadRunData *tdata = (ThreadRunData*)data; michael@0: unsigned char buf2[BUFFER_BYTES]; michael@0: michael@0: tdata->status = SECSuccess; michael@0: if (*tdata->doIters) { michael@0: long i = tdata->iters; michael@0: tdata->iterRes = 0; michael@0: while (i--) { michael@0: SECStatus rv = tdata->fn((void*)tdata->rsaKey, buf2, michael@0: (unsigned char*)tdata->buf); michael@0: if (rv != SECSuccess) { michael@0: tdata->errNum = PORT_GetError(); michael@0: tdata->status = rv; michael@0: break; michael@0: } michael@0: tdata->iterRes++; michael@0: } michael@0: } else { michael@0: PRIntervalTime total = PR_SecondsToInterval(tdata->seconds); michael@0: PRIntervalTime start = PR_IntervalNow(); michael@0: tdata->iterRes = 0; michael@0: while (PR_IntervalNow() - start < total) { michael@0: SECStatus rv = tdata->fn((void*)tdata->rsaKey, buf2, michael@0: (unsigned char*)tdata->buf); michael@0: if (rv != SECSuccess) { michael@0: tdata->errNum = PORT_GetError(); michael@0: tdata->status = rv; michael@0: break; michael@0: } michael@0: tdata->iterRes++; michael@0: } michael@0: } michael@0: } michael@0: michael@0: #define INT_ARG(arg,def) atol(arg)>0?atol(arg):def michael@0: michael@0: int michael@0: main(int argc, char **argv) michael@0: { michael@0: TimingContext * timeCtx = NULL; michael@0: SECKEYPublicKey * pubHighKey = NULL; michael@0: SECKEYPrivateKey * privHighKey = NULL; michael@0: NSSLOWKEYPrivateKey * privKey = NULL; michael@0: NSSLOWKEYPublicKey * pubKey = NULL; michael@0: CERTCertificate * cert = NULL; michael@0: char * progName = NULL; michael@0: char * secDir = NULL; michael@0: char * nickname = NULL; michael@0: char * slotname = NULL; michael@0: long keybits = 0; michael@0: RSAOp fn; michael@0: void * rsaKey = NULL; michael@0: PLOptState * optstate; michael@0: PLOptStatus optstatus; michael@0: long iters = DEFAULT_ITERS; michael@0: int i; michael@0: PRBool doPriv = PR_FALSE; michael@0: PRBool doPub = PR_FALSE; michael@0: int rv; michael@0: unsigned char buf[BUFFER_BYTES]; michael@0: unsigned char buf2[BUFFER_BYTES]; michael@0: int seconds = DEFAULT_DURATION; michael@0: PRBool doIters = PR_FALSE; michael@0: PRBool doTime = PR_FALSE; michael@0: PRBool useTokenKey = PR_FALSE; /* use PKCS#11 token michael@0: object key */ michael@0: PRBool useSessionKey = PR_FALSE; /* use PKCS#11 session michael@0: object key */ michael@0: PRBool useBLKey = PR_FALSE; /* use freebl */ michael@0: PK11SlotInfo* slot = NULL; /* slot for session michael@0: object key operations */ michael@0: PRBool doKeyGen = PR_FALSE; michael@0: int publicExponent = DEFAULT_EXPONENT; michael@0: PK11Keys keys; michael@0: int peCount = 0; michael@0: CK_BYTE pubEx[4]; michael@0: SECItem pe; michael@0: RSAPublicKey pubKeyStr; michael@0: int threadNum = DEFAULT_THREADS; michael@0: ThreadRunData ** runDataArr = NULL; michael@0: PRThread ** threadsArr = NULL; michael@0: int calcThreads = 0; michael@0: michael@0: progName = strrchr(argv[0], '/'); michael@0: if (!progName) michael@0: progName = strrchr(argv[0], '\\'); michael@0: progName = progName ? progName+1 : argv[0]; michael@0: michael@0: optstate = PL_CreateOptState(argc, argv, "d:ef:gh:i:k:n:p:st:w:x:"); michael@0: while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) { michael@0: switch (optstate->option) { michael@0: case '?': michael@0: Usage(progName); michael@0: break; michael@0: case 'd': michael@0: secDir = PORT_Strdup(optstate->value); michael@0: break; michael@0: case 'i': michael@0: iters = INT_ARG(optstate->value, DEFAULT_ITERS); michael@0: doIters = PR_TRUE; michael@0: break; michael@0: case 's': michael@0: doPriv = PR_TRUE; michael@0: break; michael@0: case 'e': michael@0: doPub = PR_TRUE; michael@0: break; michael@0: case 'g': michael@0: doKeyGen = PR_TRUE; michael@0: break; michael@0: case 'n': michael@0: nickname = PORT_Strdup(optstate->value); michael@0: /* for compatibility, nickname of "none" means go to freebl */ michael@0: if (nickname && strcmp(nickname, "none")) { michael@0: useTokenKey = PR_TRUE; michael@0: } else { michael@0: useBLKey = PR_TRUE; michael@0: } michael@0: break; michael@0: case 'p': michael@0: seconds = INT_ARG(optstate->value, DEFAULT_DURATION); michael@0: doTime = PR_TRUE; michael@0: break; michael@0: case 'h': michael@0: slotname = PORT_Strdup(optstate->value); michael@0: useSessionKey = PR_TRUE; michael@0: break; michael@0: case 'k': michael@0: keybits = INT_ARG(optstate->value, DEFAULT_KEY_BITS); michael@0: break; michael@0: case 'w': michael@0: pwData.data = PORT_Strdup(optstate->value);; michael@0: pwData.source = PW_PLAINTEXT; michael@0: break; michael@0: case 'f': michael@0: pwData.data = PORT_Strdup(optstate->value); michael@0: pwData.source = PW_FROMFILE; michael@0: break; michael@0: case 'x': michael@0: /* -x public exponent (for RSA keygen) */ michael@0: publicExponent = INT_ARG(optstate->value, DEFAULT_EXPONENT); michael@0: break; michael@0: case 't': michael@0: threadNum = INT_ARG(optstate->value, DEFAULT_THREADS); michael@0: break; michael@0: } michael@0: } michael@0: if (optstatus == PL_OPT_BAD) michael@0: Usage(progName); michael@0: michael@0: if ((doPriv && doPub) || (doIters && doTime) || michael@0: ((useTokenKey + useSessionKey + useBLKey) != PR_TRUE) || michael@0: (useTokenKey && keybits) || (useTokenKey && doKeyGen) || michael@0: (keybits && (keybitsMAX_KEY_BITS))) { michael@0: Usage(progName); michael@0: } michael@0: michael@0: if (!doPriv && !doPub) doPriv = PR_TRUE; michael@0: michael@0: if (doIters && doTime) Usage(progName); michael@0: michael@0: if (!doTime) { michael@0: doIters = PR_TRUE; michael@0: } michael@0: michael@0: PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); michael@0: michael@0: PK11_SetPasswordFunc(SECU_GetModulePassword); michael@0: secDir = SECU_ConfigDirectory(secDir); michael@0: michael@0: if (useTokenKey || useSessionKey) { michael@0: rv = NSS_Init(secDir); michael@0: if (rv != SECSuccess) { michael@0: fprintf(stderr, "NSS_Init failed.\n"); michael@0: exit(1); michael@0: } michael@0: } else { michael@0: rv = NSS_NoDB_Init(NULL); michael@0: if (rv != SECSuccess) { michael@0: fprintf(stderr, "NSS_NoDB_Init failed.\n"); michael@0: exit(1); michael@0: } michael@0: } michael@0: michael@0: if (useTokenKey) { michael@0: CK_OBJECT_HANDLE kh = CK_INVALID_HANDLE; michael@0: CERTCertDBHandle* certdb = NULL; michael@0: certdb = CERT_GetDefaultCertDB(); michael@0: michael@0: cert = PK11_FindCertFromNickname(nickname, &pwData); michael@0: if (cert == NULL) { michael@0: fprintf(stderr, michael@0: "Can't find certificate by name \"%s\"\n", nickname); michael@0: exit(1); michael@0: } michael@0: pubHighKey = CERT_ExtractPublicKey(cert); michael@0: if (pubHighKey == NULL) { michael@0: fprintf(stderr, "Can't extract public key from certificate"); michael@0: exit(1); michael@0: } michael@0: michael@0: if (doPub) { michael@0: /* do public key ops */ michael@0: fn = (RSAOp)PK11_PublicKeyOp; michael@0: rsaKey = (void *) pubHighKey; michael@0: michael@0: kh = PK11_ImportPublicKey(cert->slot, pubHighKey, PR_FALSE); michael@0: if (CK_INVALID_HANDLE == kh) { michael@0: fprintf(stderr, michael@0: "Unable to import public key to certificate slot."); michael@0: exit(1); michael@0: } michael@0: pubHighKey->pkcs11Slot = PK11_ReferenceSlot(cert->slot); michael@0: pubHighKey->pkcs11ID = kh; michael@0: printf("Using PKCS#11 for RSA encryption with token %s.\n", michael@0: PK11_GetTokenName(cert->slot)); michael@0: } else { michael@0: /* do private key ops */ michael@0: privHighKey = PK11_FindKeyByAnyCert(cert, &pwData); michael@0: if (privHighKey == NULL) { michael@0: fprintf(stderr, michael@0: "Can't find private key by name \"%s\"\n", nickname); michael@0: exit(1); michael@0: } michael@0: michael@0: SECKEY_CacheStaticFlags(privHighKey); michael@0: fn = (RSAOp)PK11_PrivateKeyOp; michael@0: keys.privKey = privHighKey; michael@0: keys.pubKey = pubHighKey; michael@0: rsaKey = (void *) &keys; michael@0: printf("Using PKCS#11 for RSA decryption with token %s.\n", michael@0: PK11_GetTokenName(privHighKey->pkcs11Slot)); michael@0: } michael@0: } else michael@0: michael@0: if (useSessionKey) { michael@0: /* use PKCS#11 session key objects */ michael@0: PK11RSAGenParams rsaparams; michael@0: void * params; michael@0: michael@0: slot = PK11_FindSlotByName(slotname); /* locate target slot */ michael@0: if (!slot) { michael@0: fprintf(stderr, "Can't find slot \"%s\"\n", slotname); michael@0: exit(1); michael@0: } michael@0: michael@0: doKeyGen = PR_TRUE; /* Always do a keygen for session keys. michael@0: Import of hardcoded key is not supported */ michael@0: /* do a temporary keygen in selected slot */ michael@0: if (!keybits) { michael@0: keybits = DEFAULT_KEY_BITS; michael@0: } michael@0: michael@0: printf("Using PKCS#11 with %ld bits session key in token %s.\n", michael@0: keybits, PK11_GetTokenName(slot)); michael@0: michael@0: rsaparams.keySizeInBits = keybits; michael@0: rsaparams.pe = publicExponent; michael@0: params = &rsaparams; michael@0: michael@0: fprintf(stderr,"\nGenerating RSA key. This may take a few moments.\n"); michael@0: michael@0: privHighKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, michael@0: params, &pubHighKey, PR_FALSE, michael@0: PR_FALSE, (void*)&pwData); michael@0: if (!privHighKey) { michael@0: fprintf(stderr, michael@0: "Key generation failed in token \"%s\"\n", michael@0: PK11_GetTokenName(slot)); michael@0: exit(1); michael@0: } michael@0: michael@0: SECKEY_CacheStaticFlags(privHighKey); michael@0: michael@0: fprintf(stderr,"Keygen completed.\n"); michael@0: michael@0: if (doPub) { michael@0: /* do public key operations */ michael@0: fn = (RSAOp)PK11_PublicKeyOp; michael@0: rsaKey = (void *) pubHighKey; michael@0: } else { michael@0: /* do private key operations */ michael@0: fn = (RSAOp)PK11_PrivateKeyOp; michael@0: keys.privKey = privHighKey; michael@0: keys.pubKey = pubHighKey; michael@0: rsaKey = (void *) &keys; michael@0: } michael@0: } else michael@0: michael@0: { michael@0: /* use freebl directly */ michael@0: if (!keybits) { michael@0: keybits = DEFAULT_KEY_BITS; michael@0: } michael@0: if (!doKeyGen) { michael@0: if (keybits != DEFAULT_KEY_BITS) { michael@0: doKeyGen = PR_TRUE; michael@0: } michael@0: } michael@0: printf("Using freebl with %ld bits key.\n", keybits); michael@0: if (doKeyGen) { michael@0: fprintf(stderr,"\nGenerating RSA key. " michael@0: "This may take a few moments.\n"); michael@0: for (i=0; i < 4; i++) { michael@0: if (peCount || (publicExponent & ((unsigned long)0xff000000L >> michael@0: (i*8)))) { michael@0: pubEx[peCount] = (CK_BYTE)((publicExponent >> michael@0: (3-i)*8) & 0xff); michael@0: peCount++; michael@0: } michael@0: } michael@0: pe.len = peCount; michael@0: pe.data = &pubEx[0]; michael@0: pe.type = siBuffer; michael@0: michael@0: rsaKey = RSA_NewKey(keybits, &pe); michael@0: fprintf(stderr,"Keygen completed.\n"); michael@0: } else { michael@0: /* use a hardcoded key */ michael@0: printf("Using hardcoded %ld bits key.\n", keybits); michael@0: if (doPub) { michael@0: pubKey = getDefaultRSAPublicKey(); michael@0: } else { michael@0: privKey = getDefaultRSAPrivateKey(); michael@0: } michael@0: } michael@0: michael@0: if (doPub) { michael@0: /* do public key operations */ michael@0: fn = (RSAOp)RSA_PublicKeyOp; michael@0: if (rsaKey) { michael@0: /* convert the RSAPrivateKey to RSAPublicKey */ michael@0: pubKeyStr.arena = NULL; michael@0: pubKeyStr.modulus = ((RSAPrivateKey*)rsaKey)->modulus; michael@0: pubKeyStr.publicExponent = michael@0: ((RSAPrivateKey*)rsaKey)->publicExponent; michael@0: rsaKey = &pubKeyStr; michael@0: } else { michael@0: /* convert NSSLOWKeyPublicKey to RSAPublicKey */ michael@0: rsaKey = (void *)(&pubKey->u.rsa); michael@0: } michael@0: PORT_Assert(rsaKey); michael@0: } else { michael@0: /* do private key operations */ michael@0: fn = (RSAOp)RSA_PrivateKeyOp; michael@0: if (privKey) { michael@0: /* convert NSSLOWKeyPrivateKey to RSAPrivateKey */ michael@0: rsaKey = (void *)(&privKey->u.rsa); michael@0: } michael@0: PORT_Assert(rsaKey); michael@0: } michael@0: } michael@0: michael@0: memset(buf, 1, sizeof buf); michael@0: rv = fn(rsaKey, buf2, buf); michael@0: if (rv != SECSuccess) { michael@0: PRErrorCode errNum; michael@0: const char * errStr = NULL; michael@0: michael@0: errNum = PORT_GetError(); michael@0: if (errNum) michael@0: errStr = SECU_Strerror(errNum); michael@0: else michael@0: errNum = rv; michael@0: if (!errStr) michael@0: errStr = "(null)"; michael@0: fprintf(stderr, "Error in RSA operation: %d : %s\n", errNum, errStr); michael@0: exit(1); michael@0: } michael@0: michael@0: threadsArr = (PRThread**)PORT_Alloc(threadNum*sizeof(PRThread*)); michael@0: runDataArr = (ThreadRunData**)PORT_Alloc(threadNum*sizeof(ThreadRunData*)); michael@0: timeCtx = CreateTimingContext(); michael@0: TimingBegin(timeCtx, PR_Now()); michael@0: for (i = 0;i < threadNum;i++) { michael@0: runDataArr[i] = (ThreadRunData*)PORT_Alloc(sizeof(ThreadRunData)); michael@0: runDataArr[i]->fn = fn; michael@0: runDataArr[i]->buf = buf; michael@0: runDataArr[i]->doIters = &doIters; michael@0: runDataArr[i]->rsaKey = rsaKey; michael@0: runDataArr[i]->seconds = seconds; michael@0: runDataArr[i]->iters = iters; michael@0: threadsArr[i] = michael@0: PR_CreateThread(PR_USER_THREAD, michael@0: ThreadExecFunction, michael@0: (void*) runDataArr[i], michael@0: PR_PRIORITY_NORMAL, michael@0: PR_GLOBAL_THREAD, michael@0: PR_JOINABLE_THREAD, michael@0: 0); michael@0: } michael@0: iters = 0; michael@0: calcThreads = 0; michael@0: for (i = 0;i < threadNum;i++, calcThreads++) michael@0: { michael@0: PR_JoinThread(threadsArr[i]); michael@0: if (runDataArr[i]->status != SECSuccess) { michael@0: const char * errStr = SECU_Strerror(runDataArr[i]->errNum); michael@0: fprintf(stderr, "Thread %d: Error in RSA operation: %d : %s\n", michael@0: i, runDataArr[i]->errNum, errStr); michael@0: calcThreads -= 1; michael@0: } else { michael@0: iters += runDataArr[i]->iterRes; michael@0: } michael@0: PORT_Free((void*)runDataArr[i]); michael@0: } michael@0: PORT_Free(runDataArr); michael@0: PORT_Free(threadsArr); michael@0: michael@0: TimingEnd(timeCtx, PR_Now()); michael@0: michael@0: printf("%ld iterations in %s\n", michael@0: iters, TimingGenerateString(timeCtx)); michael@0: printf("%.2f operations/s .\n", ((double)(iters)*(double)1000000.0) / michael@0: (double)timeCtx->interval ); michael@0: TimingDivide(timeCtx, iters); michael@0: printf("one operation every %s\n", TimingGenerateString(timeCtx)); michael@0: michael@0: if (pubHighKey) { michael@0: SECKEY_DestroyPublicKey(pubHighKey); michael@0: } michael@0: michael@0: if (privHighKey) { michael@0: SECKEY_DestroyPrivateKey(privHighKey); michael@0: } michael@0: michael@0: if (cert) { michael@0: CERT_DestroyCertificate(cert); michael@0: } michael@0: michael@0: if (NSS_Shutdown() != SECSuccess) { michael@0: exit(1); michael@0: } michael@0: michael@0: return 0; michael@0: }