security/nss/cmd/rsaperf/rsaperf.c

changeset 0
6474c204b198
     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 +}

mercurial