PK11_GetTokenName(privHighKey->pkcs11Slot));
PK11_GetTokenName(slot));
main(int argc, char **argv){    TimingContext *	  timeCtx       = NULL;    SECKEYPublicKey *	  pubHighKey    = NULL;    SECKEYPrivateKey *    privHighKey   = NULL;    NSSLOWKEYPrivateKey * privKey       = NULL;    NSSLOWKEYPublicKey *  pubKey        = NULL;    CERTCertificate *	  cert          = NULL;    char *		  progName      = NULL;    char *		  secDir 	= NULL;    char *		  nickname 	= NULL;    char *                slotname      = NULL;    char *                password      = NULL;    long                  keybits     = 0;    RSAOp                 fn;    void *                rsaKey        = NULL;    PLOptState *          optstate;    PLOptStatus           optstatus;    long 		  iters 	= DEFAULT_ITERS;    int		 	  i;    PRBool 		  doPriv 	= PR_FALSE;    PRBool 		  doPub 	= PR_FALSE;    int 		  rv;    unsigned char 	  buf[BUFFER_BYTES];    unsigned char 	  buf2[BUFFER_BYTES];    int                   seconds       = DEFAULT_DURATION;    PRBool                doIters       = PR_FALSE;    PRBool                doTime        = PR_FALSE;    PRBool                useTokenKey   = PR_FALSE; /* use PKCS#11 token                                                       object key */    PRBool                useSessionKey = PR_FALSE; /* use PKCS#11 session                                                       object key */    PRBool                useBLKey = PR_FALSE;      /* use freebl */    PK11SlotInfo*         slot          = NULL;     /* slot for session                                                       object key operations */    PRBool                doKeyGen      = PR_FALSE;    int                   publicExponent  = DEFAULT_EXPONENT;    PK11Keys keys;    int peCount = 0;    CK_BYTE pubEx[4];    SECItem pe;    RSAPublicKey          pubKeyStr;    int                   threadNum     = DEFAULT_THREADS;    ThreadRunData      ** runDataArr = NULL;    PRThread           ** threadsArr = NULL;    int                   calcThreads = 0;    progName = strrchr(argv[0], '/');    if (!progName)	progName = strrchr(argv[0], '\\');    progName = progName ? progName+1 : argv[0];    optstate = PL_CreateOptState(argc, argv, "d:i:sen:p:t:h:k:w:gx:");    while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {	switch (optstate->option) {	case '?':	    Usage(progName);	    break;	case 'd':	    secDir = PORT_Strdup(optstate->value);	    break;	case 'i':	    iters = INT_ARG(optstate->value, DEFAULT_ITERS);	    doIters = PR_TRUE;	    break;	case 's':	    doPriv = PR_TRUE;	    break;	case 'e':	    doPub = PR_TRUE;	    break;	case 'g':	    doKeyGen = PR_TRUE;	    break;	case 'n':	    nickname = PORT_Strdup(optstate->value);            /* for compatibility, nickname of "none" means go to freebl */            if (nickname && strcmp(nickname, "none")) {	        useTokenKey = PR_TRUE;            } else {                useBLKey = PR_TRUE;            }	    break;	case 'p':	    seconds = INT_ARG(optstate->value, DEFAULT_DURATION);	    doTime = PR_TRUE;            break;	case 'h':	    slotname = PORT_Strdup(optstate->value);	    useSessionKey = PR_TRUE;	    break;	case 'k':	    keybits = INT_ARG(optstate->value, DEFAULT_KEY_BITS);	    break;	case 'w':	    password = PORT_Strdup(optstate->value);	    pwData.data = password;	    pwData.source = PW_PLAINTEXT;	    break;	case 'x':	    /*  -x public exponent (for RSA keygen)  */	    publicExponent = INT_ARG(optstate->value, DEFAULT_EXPONENT);	    break;	case 't':	    threadNum = INT_ARG(optstate->value, DEFAULT_THREADS);	    break;	}    }    if (optstatus == PL_OPT_BAD)	Usage(progName);    if ((doPriv && doPub) || (doIters && doTime) ||        ((useTokenKey + useSessionKey + useBLKey) != PR_TRUE) ||        (useTokenKey && keybits) || (useTokenKey && doKeyGen) ||        (keybits && (keybits<MIN_KEY_BITS || keybits>MAX_KEY_BITS))) {        Usage(progName);    }    if (!doPriv && !doPub) doPriv = PR_TRUE;    if (doIters && doTime) Usage(progName);    if (!doTime) {        doIters = PR_TRUE;    }    PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);    PK11_SetPasswordFunc(SECU_GetModulePassword);    secDir = SECU_ConfigDirectory(secDir);    if (useTokenKey || useSessionKey) {	rv = NSS_Init(secDir);	if (rv != SECSuccess) {	    fprintf(stderr, "NSS_Init failed.\n");	    exit(1);	}    } else {	rv = NSS_NoDB_Init(NULL);	if (rv != SECSuccess) {	    fprintf(stderr, "NSS_NoDB_Init failed.\n");	    exit(1);	}    }    if (useTokenKey) {        CK_OBJECT_HANDLE kh = CK_INVALID_HANDLE;        CERTCertDBHandle* certdb = NULL;	certdb = CERT_GetDefaultCertDB();                cert = CERT_FindCertByNickname(certdb, nickname);        if (cert == NULL) {            fprintf(stderr,                    "Can't find certificate by name \"%s\"\n", nickname);            exit(1);        }        pubHighKey = CERT_ExtractPublicKey(cert);        if (pubHighKey == NULL) {            fprintf(stderr, "Can't extract public key from certificate");            exit(1);        }        if (doPub) {            /* do public key ops */            fn = (RSAOp)PK11_PublicKeyOp;            rsaKey = (void *) pubHighKey;                            kh = PK11_ImportPublicKey(cert->slot, pubHighKey, PR_FALSE);            if (CK_INVALID_HANDLE == kh) {                fprintf(stderr,                        "Unable to import public key to certificate slot.");                exit(1);            }            pubHighKey->pkcs11Slot = PK11_ReferenceSlot(cert->slot);            pubHighKey->pkcs11ID = kh;            printf("Using PKCS#11 for RSA encryption with token %s.\n",                   PK11_GetTokenName(cert->slot));        } else {            /* do private key ops */            privHighKey = PK11_FindKeyByAnyCert(cert, &pwData);            if (privHighKey == NULL) {                fprintf(stderr,                        "Can't find private key by name \"%s\"\n", nickname);                exit(1);            }                SECKEY_CacheStaticFlags(privHighKey);            fn = (RSAOp)PK11_PrivateKeyOp;            keys.privKey = privHighKey;            keys.pubKey = pubHighKey;            rsaKey = (void *) &keys;            printf("Using PKCS#11 for RSA decryption with token %s.\n",                   PK11_GetTokenName(privHighKey->pkcs11Slot));        }            } else    if (useSessionKey) {        /* use PKCS#11 session key objects */        PK11RSAGenParams   rsaparams;        void             * params;        slot = PK11_FindSlotByName(slotname); /* locate target slot */        if (!slot) {            fprintf(stderr, "Can't find slot \"%s\"\n", slotname);            exit(1);        }        doKeyGen = PR_TRUE; /* Always do a keygen for session keys.                               Import of hardcoded key is not supported */        /* do a temporary keygen in selected slot */                if (!keybits) {            keybits = DEFAULT_KEY_BITS;        }        printf("Using PKCS#11 with %ld bits session key in token %s.\n",               keybits, PK11_GetTokenName(slot));        rsaparams.keySizeInBits = keybits;        rsaparams.pe = publicExponent;        params = &rsaparams;        fprintf(stderr,"\nGenerating RSA key. This may take a few moments.\n");        privHighKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN,                                           params, &pubHighKey, PR_FALSE,                                           PR_FALSE, (void*)&pwData);        if (!privHighKey) {            fprintf(stderr,                    "Key generation failed in token \"%s\"\n",                    PK11_GetTokenName(privHighKey->pkcs11Slot));            exit(1);        }        SECKEY_CacheStaticFlags(privHighKey);                fprintf(stderr,"Keygen completed.\n");        if (doPub) {            /* do public key operations */            fn = (RSAOp)PK11_PublicKeyOp;            rsaKey = (void *) pubHighKey;        } else {            /* do private key operations */            fn = (RSAOp)PK11_PrivateKeyOp;            keys.privKey = privHighKey;            keys.pubKey = pubHighKey;            rsaKey = (void *) &keys;        }            } else            {        /* use freebl directly */        if (!keybits) {            keybits = DEFAULT_KEY_BITS;        }        if (!doKeyGen) {            if (keybits != DEFAULT_KEY_BITS) {                doKeyGen = PR_TRUE;            }        }        printf("Using freebl with %ld bits key.\n", keybits);        if (doKeyGen) {            fprintf(stderr,"\nGenerating RSA key. "                    "This may take a few moments.\n");            for (i=0; i < 4; i++) {                if (peCount || (publicExponent & ((unsigned long)0xff000000L >>                                                  (i*8)))) {                    pubEx[peCount] =  (CK_BYTE)((publicExponent >>                                                 (3-i)*8) & 0xff);                    peCount++;                }            }            pe.len = peCount;            pe.data = &pubEx[0];            pe.type = siBuffer;            rsaKey = RSA_NewKey(keybits, &pe);            fprintf(stderr,"Keygen completed.\n");        } else {            /* use a hardcoded key */            printf("Using hardcoded %ld bits key.\n", keybits);            if (doPub) {                pubKey = getDefaultRSAPublicKey();            } else {                privKey = getDefaultRSAPrivateKey();            }        }        if (doPub) {            /* do public key operations */            fn = (RSAOp)RSA_PublicKeyOp;            if (rsaKey) {                /* convert the RSAPrivateKey to RSAPublicKey */                pubKeyStr.arena = NULL;                pubKeyStr.modulus = ((RSAPrivateKey*)rsaKey)->modulus;                pubKeyStr.publicExponent =                    ((RSAPrivateKey*)rsaKey)->publicExponent;                rsaKey = &pubKeyStr;            } else {                /* convert NSSLOWKeyPublicKey to RSAPublicKey */                rsaKey = (void *)(&pubKey->u.rsa);            }            PORT_Assert(rsaKey);        } else {            /* do private key operations */            fn = (RSAOp)RSA_PrivateKeyOp;            if (privKey) {                /* convert NSSLOWKeyPrivateKey to RSAPrivateKey */                rsaKey = (void *)(&privKey->u.rsa);            }            PORT_Assert(rsaKey);        }    }    memset(buf, 1, sizeof buf);    rv = fn(rsaKey, buf2, buf);    if (rv != SECSuccess) {	PRErrorCode errNum;	const char * errStr = NULL;	errNum = PORT_GetError();	if (errNum)	    errStr = SECU_Strerror(errNum);	else	    errNum = rv;	if (!errStr)	    errStr = "(null)";	fprintf(stderr, "Error in RSA operation: %d : %s\n", errNum, errStr);	exit(1);    }    threadsArr = (PRThread**)PORT_Alloc(threadNum*sizeof(PRThread*));    runDataArr = (ThreadRunData**)PORT_Alloc(threadNum*sizeof(ThreadRunData*));    timeCtx = CreateTimingContext();    TimingBegin(timeCtx, PR_Now());    for (i = 0;i < threadNum;i++) {        runDataArr[i] = (ThreadRunData*)PORT_Alloc(sizeof(ThreadRunData));        runDataArr[i]->fn = fn;        runDataArr[i]->buf = buf;        runDataArr[i]->doIters = &doIters;        runDataArr[i]->rsaKey = rsaKey;        runDataArr[i]->seconds = seconds;        runDataArr[i]->iters = iters;        threadsArr[i] =             PR_CreateThread(PR_USER_THREAD,                 ThreadExecFunction,                 (void*) runDataArr[i],                 PR_PRIORITY_NORMAL,                 PR_GLOBAL_THREAD,                 PR_JOINABLE_THREAD,                 0);    }    iters = 0;    calcThreads = 0;    for (i = 0;i < threadNum;i++, calcThreads++)    {        PR_JoinThread(threadsArr[i]);        if (runDataArr[i]->status != SECSuccess) {            const char * errStr = SECU_Strerror(runDataArr[i]->errNum);            fprintf(stderr, "Thread %d: Error in RSA operation: %d : %s\n",                    i, runDataArr[i]->errNum, errStr);            calcThreads -= 1;        } else {            iters += runDataArr[i]->iterRes;        }        PORT_Free((void*)runDataArr[i]);    }    PORT_Free(runDataArr);    PORT_Free(threadsArr);    TimingEnd(timeCtx, PR_Now());        printf("%ld iterations in %s\n",	   iters, TimingGenerateString(timeCtx));    printf("%.2f operations/s .\n", ((double)(iters)*(double)1000000.0) /           (double)timeCtx->interval );    TimingDivide(timeCtx, iters);    printf("one operation every %s\n", TimingGenerateString(timeCtx));    if (pubHighKey) {        SECKEY_DestroyPublicKey(pubHighKey);    }    if (privHighKey) {         SECKEY_DestroyPrivateKey(privHighKey);    }    if (cert) {        CERT_DestroyCertificate(cert);    }    if (NSS_Shutdown() != SECSuccess) {        exit(1);    }    return 0;}