#if defined(XP_UNIX) #include #endif #include #include #include #include #include #include #include #include #define MAX_THREAD_COUNT 100 /* globals */ int THREAD_COUNT = 30; int FAILED = 0; int ERROR = 0; int LOOP_COUNT = 100; int KEY_SIZE = 3072; int STACK_SIZE = 0; int VERBOSE = 0; char *NSSDIR = "."; PRBool ISTOKEN = PR_TRUE; CK_MECHANISM_TYPE MECHANISM = CKM_RSA_PKCS_KEY_PAIR_GEN; void usage(char *prog, char *error) { if (error) { fprintf(stderr, "Bad Arguments: %s", error); } fprintf(stderr, "usage: %s [-l loop_count] [-t thread_count] " "[-k key_size] [-s stack_size] [-d nss_dir] [-e] [-v] [-h]\n", prog); fprintf(stderr, " loop_count -- " "number of keys to generate on each thread (default=%d)\n", LOOP_COUNT); fprintf(stderr, " thread_count -- " "number of of concurrent threads to run (def=%d,max=%d)\n", THREAD_COUNT, MAX_THREAD_COUNT); fprintf(stderr, " key_size -- " "rsa key size in bits (default=%d)\n", KEY_SIZE); fprintf(stderr, " stack_size -- " "thread stack size in bytes, 0=optimal (default=%d)\n", STACK_SIZE); fprintf(stderr, " nss_dir -- " "location of the nss directory (default=%s)\n", NSSDIR); fprintf(stderr, " -e use session keys rather than token keys\n"); fprintf(stderr, " -v verbose, print progress indicators\n"); fprintf(stderr, " -h print this message\n"); exit(2); } void create_key_loop(void *arg) { int i; PK11SlotInfo *slot = PK11_GetInternalKeySlot(); PK11RSAGenParams param; int threadnumber = *(int *)arg; int failures = 0; int progress = 5; PRIntervalTime epoch = PR_IntervalNow(); param.keySizeInBits = KEY_SIZE; param.pe = 0x10001L; printf(" - thread %d starting\n", threadnumber); progress = 30 / THREAD_COUNT; if (progress < 2) progress = 2; for (i = 0; i < LOOP_COUNT; i++) { SECKEYPrivateKey *privKey; SECKEYPublicKey *pubKey; privKey = PK11_GenerateKeyPair(slot, MECHANISM, ¶m, &pubKey, ISTOKEN, PR_TRUE, NULL); if (privKey == NULL) { fprintf(stderr, "keypair gen in thread %d failed %s\n", threadnumber, PORT_ErrorToString(PORT_GetError())); FAILED++; failures++; } if (VERBOSE && (i % progress) == 0) { PRIntervalTime current = PR_IntervalNow(); PRIntervalTime interval = current - epoch; int seconds = (interval / PR_TicksPerSecond()); int mseconds = ((interval * 1000) / PR_TicksPerSecond()) - (seconds * 1000); epoch = current; printf(" - thread %d @ %d iterations %d.%03d sec\n", threadnumber, i, seconds, mseconds); } if (ISTOKEN && privKey) { SECKEY_DestroyPublicKey(pubKey); SECKEY_DestroyPrivateKey(privKey); } } PK11_FreeSlot(slot); printf(" * thread %d ending with %d failures\n", threadnumber, failures); return; } int main(int argc, char **argv) { PRThread *thread[MAX_THREAD_COUNT]; int threadnumber[MAX_THREAD_COUNT]; int i; PRStatus status; SECStatus rv; char *prog = *argv++; char buf[2048]; char *arg; while ((arg = *argv++) != NULL) { if (*arg == '-') { switch (arg[1]) { case 'l': if (*argv == NULL) usage(prog, "missing loop count"); LOOP_COUNT = atoi(*argv++); break; case 'k': if (*argv == NULL) usage(prog, "missing key size"); KEY_SIZE = atoi(*argv++); break; case 's': if (*argv == NULL) usage(prog, "missing stack size"); STACK_SIZE = atoi(*argv++); break; case 't': if (*argv == NULL) usage(prog, "missing thread count"); THREAD_COUNT = atoi(*argv++); if (THREAD_COUNT > MAX_THREAD_COUNT) { usage(prog, "max thread count exceeded"); } break; case 'v': VERBOSE = 1; break; case 'd': if (*argv == NULL) usage(prog, "missing directory"); NSSDIR = *argv++; break; case 'e': ISTOKEN = PR_FALSE; break; case 'h': usage(prog, NULL); break; default: snprintf(buf, sizeof(buf), "unknown option %c", arg[1]); usage(prog, buf); } } else { snprintf(buf, sizeof(buf), "unknown argument %s", arg); usage(prog, buf); } } /* initialize NSS */ rv = NSS_InitReadWrite(NSSDIR); if (rv != SECSuccess) { fprintf(stderr, "NSS_InitReadWrite(%s) failed(%s)\n", NSSDIR, PORT_ErrorToString(PORT_GetError())); exit(2); } /* need to initialize the database here if it's not already */ printf("creating %d threads\n", THREAD_COUNT); for (i = 0; i < THREAD_COUNT; i++) { threadnumber[i] = i; thread[i] = PR_CreateThread(PR_USER_THREAD, create_key_loop, &threadnumber[i], PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, STACK_SIZE); if (thread[i] == NULL) { ERROR++; fprintf(stderr, "PR_CreateThread failed iteration %d, %s\n", i, PORT_ErrorToString(PORT_GetError())); } } printf("waiting on %d threads\n", THREAD_COUNT); for (i = 0; i < THREAD_COUNT; i++) { if (thread[i] == NULL) { continue; } status = PR_JoinThread(thread[i]); if (status != PR_SUCCESS) { ERROR++; fprintf(stderr, "PR_CreateThread filed iteration %d, %s\n", i, PORT_ErrorToString(PORT_GetError())); } } if (NSS_Shutdown() != SECSuccess) { ERROR++; fprintf(stderr, "NSS_Shutdown failed: %s\n", PORT_ErrorToString(PORT_GetError())); } printf("%d failures and %d errors found\n", FAILED, ERROR); /* clean up */ if (FAILED) { exit(1); } if (ERROR) { exit(2); } exit(0); }