security/nss/cmd/rsaperf/rsaperf.c

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

     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/. */
     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"
    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
    25 extern NSSLOWKEYPrivateKey * getDefaultRSAPrivateKey(void);
    26 extern NSSLOWKEYPublicKey  * getDefaultRSAPublicKey(void);
    28 secuPWData pwData = { PW_NONE, NULL };
    30 typedef struct TimingContextStr TimingContext;
    32 struct TimingContextStr {
    33     PRTime start;
    34     PRTime end;
    35     PRTime interval;
    37     long  days;     
    38     int   hours;    
    39     int   minutes;  
    40     int   seconds;  
    41     int   millisecs;
    42 };
    44 TimingContext *CreateTimingContext(void) {
    45     return PORT_Alloc(sizeof(TimingContext));
    46 }
    48 void DestroyTimingContext(TimingContext *ctx) {
    49     PORT_Free(ctx);
    50 }
    52 void TimingBegin(TimingContext *ctx, PRTime begin) {
    53     ctx->start = begin;
    54 }
    56 static void timingUpdate(TimingContext *ctx) {
    57     PRInt64 tmp, remaining;
    58     PRInt64 L1000,L60,L24;
    60     LL_I2L(L1000,1000);
    61     LL_I2L(L60,60);
    62     LL_I2L(L24,24);
    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 }
    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 }
    87 void TimingDivide(TimingContext *ctx, int divisor) {
    88     PRInt64 tmp;
    90     LL_I2L(tmp, divisor);
    91     LL_DIV(ctx->interval, ctx->interval, tmp);
    93     timingUpdate(ctx);
    94 }
    96 char *TimingGenerateString(TimingContext *ctx) {
    97     char *buf = NULL;
    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 }
   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 }
   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 }
   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 }
   186 void
   187 printPrivKey(NSSLOWKEYPrivateKey * privKey)
   188 {
   189     RSAPrivateKey *rsa = &privKey->u.rsa;
   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 }
   202 typedef SECStatus (* RSAOp)(void *               key, 
   203 			    unsigned char *      output,
   204 		            unsigned char *      input);
   206 typedef struct {
   207     SECKEYPublicKey* pubKey;
   208     SECKEYPrivateKey* privKey;
   209 } PK11Keys;
   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 }
   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;
   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 };
   245 void ThreadExecFunction(void *data)
   246 {
   247     ThreadRunData *tdata = (ThreadRunData*)data;
   248     unsigned char buf2[BUFFER_BYTES];
   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 }
   281 #define INT_ARG(arg,def) atol(arg)>0?atol(arg):def
   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;
   330     progName = strrchr(argv[0], '/');
   331     if (!progName)
   332 	progName = strrchr(argv[0], '\\');
   333     progName = progName ? progName+1 : argv[0];
   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);
   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     }
   404     if (!doPriv && !doPub) doPriv = PR_TRUE;
   406     if (doIters && doTime) Usage(progName);
   408     if (!doTime) {
   409         doIters = PR_TRUE;
   410     }
   412     PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
   414     PK11_SetPasswordFunc(SECU_GetModulePassword);
   415     secDir = SECU_ConfigDirectory(secDir);
   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     }
   431     if (useTokenKey) {
   432         CK_OBJECT_HANDLE kh = CK_INVALID_HANDLE;
   433         CERTCertDBHandle* certdb = NULL;
   434 	certdb = CERT_GetDefaultCertDB();
   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         }
   448         if (doPub) {
   449             /* do public key ops */
   450             fn = (RSAOp)PK11_PublicKeyOp;
   451             rsaKey = (void *) pubHighKey;
   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             }
   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
   482     if (useSessionKey) {
   483         /* use PKCS#11 session key objects */
   484         PK11RSAGenParams   rsaparams;
   485         void             * params;
   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         }
   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         }
   500         printf("Using PKCS#11 with %ld bits session key in token %s.\n",
   501                keybits, PK11_GetTokenName(slot));
   503         rsaparams.keySizeInBits = keybits;
   504         rsaparams.pe = publicExponent;
   505         params = &rsaparams;
   507         fprintf(stderr,"\nGenerating RSA key. This may take a few moments.\n");
   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         }
   519         SECKEY_CacheStaticFlags(privHighKey);
   521         fprintf(stderr,"Keygen completed.\n");
   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
   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;
   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         }
   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     }
   600     memset(buf, 1, sizeof buf);
   601     rv = fn(rsaKey, buf2, buf);
   602     if (rv != SECSuccess) {
   603 	PRErrorCode errNum;
   604 	const char * errStr = NULL;
   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     }
   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);
   656     TimingEnd(timeCtx, PR_Now());
   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));
   665     if (pubHighKey) {
   666         SECKEY_DestroyPublicKey(pubHighKey);
   667     }
   669     if (privHighKey) {
   670          SECKEY_DestroyPrivateKey(privHighKey);
   671     }
   673     if (cert) {
   674         CERT_DestroyCertificate(cert);
   675     }
   677     if (NSS_Shutdown() != SECSuccess) {
   678         exit(1);
   679     }
   681     return 0;
   682 }

mercurial