1 #if defined(XP_UNIX)
2 #include <unistd.h>
3 #endif
4 #include <stdio.h>
5 #include <nss.h>
6 #include <prtypes.h>
7 #include <prerr.h>
8 #include <prerror.h>
9 #include <prthread.h>
10 #include <pk11pub.h>
11 #include <keyhi.h>
12
13 #define MAX_THREAD_COUNT 100
14
15 /* globals */
16 int THREAD_COUNT = 30;
17 int FAILED = 0;
18 int ERROR = 0;
19 int LOOP_COUNT = 100;
20 int KEY_SIZE = 3072;
21 int STACK_SIZE = 0;
22 int VERBOSE = 0;
23 char *NSSDIR = ".";
24 PRBool ISTOKEN = PR_TRUE;
25 CK_MECHANISM_TYPE MECHANISM = CKM_RSA_PKCS_KEY_PAIR_GEN;
26
27 void
usage(char * prog,char * error)28 usage(char *prog, char *error)
29 {
30 if (error) {
31 fprintf(stderr, "Bad Arguments: %s", error);
32 }
33 fprintf(stderr, "usage: %s [-l loop_count] [-t thread_count] "
34 "[-k key_size] [-s stack_size] [-d nss_dir] [-e] [-v] [-h]\n",
35 prog);
36 fprintf(stderr, " loop_count -- "
37 "number of keys to generate on each thread (default=%d)\n",
38 LOOP_COUNT);
39 fprintf(stderr, " thread_count -- "
40 "number of of concurrent threads to run (def=%d,max=%d)\n",
41 THREAD_COUNT, MAX_THREAD_COUNT);
42 fprintf(stderr, " key_size -- "
43 "rsa key size in bits (default=%d)\n",
44 KEY_SIZE);
45 fprintf(stderr, " stack_size -- "
46 "thread stack size in bytes, 0=optimal (default=%d)\n",
47 STACK_SIZE);
48 fprintf(stderr, " nss_dir -- "
49 "location of the nss directory (default=%s)\n",
50 NSSDIR);
51 fprintf(stderr, " -e use session keys rather than token keys\n");
52 fprintf(stderr, " -v verbose, print progress indicators\n");
53 fprintf(stderr, " -h print this message\n");
54 exit(2);
55 }
56
57 void
create_key_loop(void * arg)58 create_key_loop(void *arg)
59 {
60 int i;
61 PK11SlotInfo *slot = PK11_GetInternalKeySlot();
62 PK11RSAGenParams param;
63 int threadnumber = *(int *)arg;
64 int failures = 0;
65 int progress = 5;
66 PRIntervalTime epoch = PR_IntervalNow();
67 param.keySizeInBits = KEY_SIZE;
68 param.pe = 0x10001L;
69 printf(" - thread %d starting\n", threadnumber);
70 progress = 30 / THREAD_COUNT;
71 if (progress < 2)
72 progress = 2;
73 for (i = 0; i < LOOP_COUNT; i++) {
74 SECKEYPrivateKey *privKey;
75 SECKEYPublicKey *pubKey;
76 privKey = PK11_GenerateKeyPair(slot, MECHANISM, ¶m, &pubKey,
77 ISTOKEN, PR_TRUE, NULL);
78 if (privKey == NULL) {
79 fprintf(stderr,
80 "keypair gen in thread %d failed %s\n", threadnumber,
81 PORT_ErrorToString(PORT_GetError()));
82 FAILED++;
83 failures++;
84 }
85 if (VERBOSE && (i % progress) == 0) {
86 PRIntervalTime current = PR_IntervalNow();
87 PRIntervalTime interval = current - epoch;
88 int seconds = (interval / PR_TicksPerSecond());
89 int mseconds = ((interval * 1000) / PR_TicksPerSecond()) - (seconds * 1000);
90 epoch = current;
91 printf(" - thread %d @ %d iterations %d.%03d sec\n", threadnumber,
92 i, seconds, mseconds);
93 }
94 if (ISTOKEN && privKey) {
95 SECKEY_DestroyPublicKey(pubKey);
96 SECKEY_DestroyPrivateKey(privKey);
97 }
98 }
99 PK11_FreeSlot(slot);
100 printf(" * thread %d ending with %d failures\n", threadnumber, failures);
101 return;
102 }
103
104 int
main(int argc,char ** argv)105 main(int argc, char **argv)
106 {
107 PRThread *thread[MAX_THREAD_COUNT];
108 int threadnumber[MAX_THREAD_COUNT];
109 int i;
110 PRStatus status;
111 SECStatus rv;
112 char *prog = *argv++;
113 char buf[2048];
114 char *arg;
115
116 while ((arg = *argv++) != NULL) {
117 if (*arg == '-') {
118 switch (arg[1]) {
119 case 'l':
120 if (*argv == NULL)
121 usage(prog, "missing loop count");
122 LOOP_COUNT = atoi(*argv++);
123 break;
124 case 'k':
125 if (*argv == NULL)
126 usage(prog, "missing key size");
127 KEY_SIZE = atoi(*argv++);
128 break;
129 case 's':
130 if (*argv == NULL)
131 usage(prog, "missing stack size");
132 STACK_SIZE = atoi(*argv++);
133 break;
134 case 't':
135 if (*argv == NULL)
136 usage(prog, "missing thread count");
137 THREAD_COUNT = atoi(*argv++);
138 if (THREAD_COUNT > MAX_THREAD_COUNT) {
139 usage(prog, "max thread count exceeded");
140 }
141 break;
142 case 'v':
143 VERBOSE = 1;
144 break;
145 case 'd':
146 if (*argv == NULL)
147 usage(prog, "missing directory");
148 NSSDIR = *argv++;
149 break;
150 case 'e':
151 ISTOKEN = PR_FALSE;
152 break;
153 case 'h':
154 usage(prog, NULL);
155 break;
156 default:
157 sprintf(buf, "unknown option %c", arg[1]);
158 usage(prog, buf);
159 }
160 } else {
161 sprintf(buf, "unknown argument %s", arg);
162 usage(prog, buf);
163 }
164 }
165 /* initialize NSS */
166 rv = NSS_InitReadWrite(NSSDIR);
167 if (rv != SECSuccess) {
168 fprintf(stderr,
169 "NSS_InitReadWrite(%s) failed(%s)\n", NSSDIR,
170 PORT_ErrorToString(PORT_GetError()));
171 exit(2);
172 }
173
174 /* need to initialize the database here if it's not already */
175
176 printf("creating %d threads\n", THREAD_COUNT);
177 for (i = 0; i < THREAD_COUNT; i++) {
178 threadnumber[i] = i;
179 thread[i] = PR_CreateThread(PR_USER_THREAD, create_key_loop,
180 &threadnumber[i], PR_PRIORITY_NORMAL,
181 PR_GLOBAL_THREAD,
182 PR_JOINABLE_THREAD, STACK_SIZE);
183 if (thread[i] == NULL) {
184 ERROR++;
185 fprintf(stderr,
186 "PR_CreateThread failed iteration %d, %s\n", i,
187 PORT_ErrorToString(PORT_GetError()));
188 }
189 }
190 printf("waiting on %d threads\n", THREAD_COUNT);
191 for (i = 0; i < THREAD_COUNT; i++) {
192 if (thread[i] == NULL) {
193 continue;
194 }
195 status = PR_JoinThread(thread[i]);
196 if (status != PR_SUCCESS) {
197 ERROR++;
198 fprintf(stderr,
199 "PR_CreateThread filed iteration %d, %s\n", i,
200 PORT_ErrorToString(PORT_GetError()));
201 }
202 }
203 if (NSS_Shutdown() != SECSuccess) {
204 ERROR++;
205 fprintf(stderr, "NSS_Shutdown failed: %s\n",
206 PORT_ErrorToString(PORT_GetError()));
207 }
208 printf("%d failures and %d errors found\n", FAILED, ERROR);
209 /* clean up */
210 if (FAILED) {
211 exit(1);
212 }
213 if (ERROR) {
214 exit(2);
215 }
216 exit(0);
217 }
218