|
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/. */ |
|
4 |
|
5 #include <stdio.h> |
|
6 #include <string.h> |
|
7 #include "secutil.h" |
|
8 |
|
9 #if defined(XP_UNIX) |
|
10 #include <unistd.h> |
|
11 #include <sys/time.h> |
|
12 #include <termios.h> |
|
13 #endif |
|
14 |
|
15 #if defined(XP_WIN) || defined (XP_PC) |
|
16 #include <time.h> |
|
17 #include <conio.h> |
|
18 #endif |
|
19 |
|
20 #if defined(__sun) && !defined(SVR4) |
|
21 extern int fclose(FILE*); |
|
22 extern int fprintf(FILE *, char *, ...); |
|
23 extern int isatty(int); |
|
24 extern char *sys_errlist[]; |
|
25 #define strerror(errno) sys_errlist[errno] |
|
26 #endif |
|
27 |
|
28 #include "nspr.h" |
|
29 #include "prtypes.h" |
|
30 #include "prtime.h" |
|
31 #include "prlong.h" |
|
32 |
|
33 #include "pk11func.h" |
|
34 |
|
35 #define NUM_KEYSTROKES 120 |
|
36 #define RAND_BUF_SIZE 60 |
|
37 |
|
38 #define ERROR_BREAK rv = SECFailure;break; |
|
39 |
|
40 const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = { |
|
41 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) }, |
|
42 { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,prime) }, |
|
43 { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,subPrime) }, |
|
44 { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,base) }, |
|
45 { 0, } |
|
46 }; |
|
47 |
|
48 /* returns 0 for success, -1 for failure (EOF encountered) */ |
|
49 static int |
|
50 UpdateRNG(void) |
|
51 { |
|
52 char randbuf[RAND_BUF_SIZE]; |
|
53 int fd, count; |
|
54 int c; |
|
55 int rv = 0; |
|
56 #ifdef XP_UNIX |
|
57 cc_t orig_cc_min; |
|
58 cc_t orig_cc_time; |
|
59 tcflag_t orig_lflag; |
|
60 struct termios tio; |
|
61 #endif |
|
62 char meter[] = { |
|
63 "\r| |" }; |
|
64 |
|
65 #define FPS fprintf(stderr, |
|
66 FPS "\n"); |
|
67 FPS "A random seed must be generated that will be used in the\n"); |
|
68 FPS "creation of your key. One of the easiest ways to create a\n"); |
|
69 FPS "random seed is to use the timing of keystrokes on a keyboard.\n"); |
|
70 FPS "\n"); |
|
71 FPS "To begin, type keys on the keyboard until this progress meter\n"); |
|
72 FPS "is full. DO NOT USE THE AUTOREPEAT FUNCTION ON YOUR KEYBOARD!\n"); |
|
73 FPS "\n"); |
|
74 FPS "\n"); |
|
75 FPS "Continue typing until the progress meter is full:\n\n"); |
|
76 FPS "%s", meter); |
|
77 FPS "\r|"); |
|
78 |
|
79 /* turn off echo on stdin & return on 1 char instead of NL */ |
|
80 fd = fileno(stdin); |
|
81 |
|
82 #if defined(XP_UNIX) |
|
83 tcgetattr(fd, &tio); |
|
84 orig_lflag = tio.c_lflag; |
|
85 orig_cc_min = tio.c_cc[VMIN]; |
|
86 orig_cc_time = tio.c_cc[VTIME]; |
|
87 tio.c_lflag &= ~ECHO; |
|
88 tio.c_lflag &= ~ICANON; |
|
89 tio.c_cc[VMIN] = 1; |
|
90 tio.c_cc[VTIME] = 0; |
|
91 tcsetattr(fd, TCSAFLUSH, &tio); |
|
92 #endif |
|
93 |
|
94 /* Get random noise from keyboard strokes */ |
|
95 count = 0; |
|
96 while (count < sizeof randbuf) { |
|
97 #if defined(XP_UNIX) |
|
98 c = getc(stdin); |
|
99 #else |
|
100 c = getch(); |
|
101 #endif |
|
102 if (c == EOF) { |
|
103 rv = -1; |
|
104 break; |
|
105 } |
|
106 randbuf[count] = c; |
|
107 if (count == 0 || c != randbuf[count-1]) { |
|
108 count++; |
|
109 FPS "*"); |
|
110 } |
|
111 } |
|
112 PK11_RandomUpdate(randbuf, sizeof randbuf); |
|
113 memset(randbuf, 0, sizeof randbuf); |
|
114 |
|
115 FPS "\n\n"); |
|
116 FPS "Finished. Press enter to continue: "); |
|
117 while ((c = getc(stdin)) != '\n' && c != EOF) |
|
118 ; |
|
119 if (c == EOF) |
|
120 rv = -1; |
|
121 FPS "\n"); |
|
122 |
|
123 #undef FPS |
|
124 |
|
125 #if defined(XP_UNIX) |
|
126 /* set back termio the way it was */ |
|
127 tio.c_lflag = orig_lflag; |
|
128 tio.c_cc[VMIN] = orig_cc_min; |
|
129 tio.c_cc[VTIME] = orig_cc_time; |
|
130 tcsetattr(fd, TCSAFLUSH, &tio); |
|
131 #endif |
|
132 return rv; |
|
133 } |
|
134 |
|
135 static const unsigned char P[] = { 0, |
|
136 0x98, 0xef, 0x3a, 0xae, 0x70, 0x98, 0x9b, 0x44, |
|
137 0xdb, 0x35, 0x86, 0xc1, 0xb6, 0xc2, 0x47, 0x7c, |
|
138 0xb4, 0xff, 0x99, 0xe8, 0xae, 0x44, 0xf2, 0xeb, |
|
139 0xc3, 0xbe, 0x23, 0x0f, 0x65, 0xd0, 0x4c, 0x04, |
|
140 0x82, 0x90, 0xa7, 0x9d, 0x4a, 0xc8, 0x93, 0x7f, |
|
141 0x41, 0xdf, 0xf8, 0x80, 0x6b, 0x0b, 0x68, 0x7f, |
|
142 0xaf, 0xe4, 0xa8, 0xb5, 0xb2, 0x99, 0xc3, 0x69, |
|
143 0xfb, 0x3f, 0xe7, 0x1b, 0xd0, 0x0f, 0xa9, 0x7a, |
|
144 0x4a, 0x04, 0xbf, 0x50, 0x9e, 0x22, 0x33, 0xb8, |
|
145 0x89, 0x53, 0x24, 0x10, 0xf9, 0x68, 0x77, 0xad, |
|
146 0xaf, 0x10, 0x68, 0xb8, 0xd3, 0x68, 0x5d, 0xa3, |
|
147 0xc3, 0xeb, 0x72, 0x3b, 0xa0, 0x0b, 0x73, 0x65, |
|
148 0xc5, 0xd1, 0xfa, 0x8c, 0xc0, 0x7d, 0xaa, 0x52, |
|
149 0x29, 0x34, 0x44, 0x01, 0xbf, 0x12, 0x25, 0xfe, |
|
150 0x18, 0x0a, 0xc8, 0x3f, 0xc1, 0x60, 0x48, 0xdb, |
|
151 0xad, 0x93, 0xb6, 0x61, 0x67, 0xd7, 0xa8, 0x2d }; |
|
152 static const unsigned char Q[] = { 0, |
|
153 0xb5, 0xb0, 0x84, 0x8b, 0x44, 0x29, 0xf6, 0x33, |
|
154 0x59, 0xa1, 0x3c, 0xbe, 0xd2, 0x7f, 0x35, 0xa1, |
|
155 0x76, 0x27, 0x03, 0x81 }; |
|
156 static const unsigned char G[] = { |
|
157 0x04, 0x0e, 0x83, 0x69, 0xf1, 0xcd, 0x7d, 0xe5, |
|
158 0x0c, 0x78, 0x93, 0xd6, 0x49, 0x6f, 0x00, 0x04, |
|
159 0x4e, 0x0e, 0x6c, 0x37, 0xaa, 0x38, 0x22, 0x47, |
|
160 0xd2, 0x58, 0xec, 0x83, 0x12, 0x95, 0xf9, 0x9c, |
|
161 0xf1, 0xf4, 0x27, 0xff, 0xd7, 0x99, 0x57, 0x35, |
|
162 0xc6, 0x64, 0x4c, 0xc0, 0x47, 0x12, 0x31, 0x50, |
|
163 0x82, 0x3c, 0x2a, 0x07, 0x03, 0x01, 0xef, 0x30, |
|
164 0x09, 0x89, 0x82, 0x41, 0x76, 0x71, 0xda, 0x9e, |
|
165 0x57, 0x8b, 0x76, 0x38, 0x37, 0x5f, 0xa5, 0xcd, |
|
166 0x32, 0x84, 0x45, 0x8d, 0x4c, 0x17, 0x54, 0x2b, |
|
167 0x5d, 0xc2, 0x6b, 0xba, 0x3e, 0xa0, 0x7b, 0x95, |
|
168 0xd7, 0x00, 0x42, 0xf7, 0x08, 0xb8, 0x83, 0x87, |
|
169 0x60, 0xe1, 0xe5, 0xf4, 0x1a, 0x54, 0xc2, 0x20, |
|
170 0xda, 0x38, 0x3a, 0xd1, 0xb6, 0x10, 0xf4, 0xcb, |
|
171 0x35, 0xda, 0x97, 0x92, 0x87, 0xd6, 0xa5, 0x37, |
|
172 0x62, 0xb4, 0x93, 0x4a, 0x15, 0x21, 0xa5, 0x10 }; |
|
173 |
|
174 /* h: |
|
175 * 4a:76:30:89:eb:e1:81:7c:99:0b:39:7f:95:4a:65:72: |
|
176 * c6:b4:05:92:48:6c:3c:b2:7e:e7:39:f3:92:7d:c1:3f: |
|
177 * bf:e1:fd:b3:4a:46:3e:ce:29:80:e3:d6:f4:59:c6:92: |
|
178 * 16:2b:0e:d7:d6:bb:ef:94:36:31:c2:66:46:c5:4a:77: |
|
179 * aa:95:84:ef:99:7e:e3:9c:d9:a0:32:42:09:b6:4e:d0: |
|
180 * b3:c8:5e:06:df:a1:ac:4d:2d:f9:08:c2:cb:4b:a4:42: |
|
181 * db:8a:5b:de:25:6e:2b:5b:ca:00:75:2c:57:00:18:aa: |
|
182 * 68:59:a1:94:03:07:94:78:38:bc:f8:7c:1e:1c:a3:2e |
|
183 * SEED: |
|
184 * b5:44:66:c9:0f:f1:ca:1c:95:45:ce:90:74:89:14:f2: |
|
185 * 13:3e:23:5a:b0:6a:bf:86:ad:cb:a0:7d:ce:3b:c8:16: |
|
186 * 7f:2d:a2:1a:cb:33:7d:c1:e7:d7:07:aa:1b:a2:d7:89: |
|
187 * f5:a4:db:f7:8b:50:00:cd:b4:7d:25:81:3f:f8:a8:dd: |
|
188 * 6c:46:e5:77:b5:60:7e:75:79:b8:99:57:c1:c4:f3:f7: |
|
189 * 17:ca:43:00:b8:33:b6:06:8f:4d:91:ed:23:a5:66:1b: |
|
190 * ef:14:d7:bc:21:2b:82:d8:ab:fa:fd:a7:c3:4d:bf:52: |
|
191 * af:8e:57:59:61:1a:4e:65:c6:90:d6:a6:ff:0b:15:b1 |
|
192 * g: 1024 |
|
193 * counter: 1003 |
|
194 */ |
|
195 |
|
196 static const SECKEYPQGParams default_pqg_params = { |
|
197 NULL, |
|
198 { 0, (unsigned char *)P, sizeof(P) }, |
|
199 { 0, (unsigned char *)Q, sizeof(Q) }, |
|
200 { 0, (unsigned char *)G, sizeof(G) } |
|
201 }; |
|
202 |
|
203 static SECKEYPQGParams * |
|
204 decode_pqg_params(const char *str) |
|
205 { |
|
206 char *buf; |
|
207 unsigned int len; |
|
208 PLArenaPool *arena; |
|
209 SECKEYPQGParams *params; |
|
210 SECStatus status; |
|
211 |
|
212 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
|
213 if (arena == NULL) |
|
214 return NULL; |
|
215 |
|
216 params = PORT_ArenaZAlloc(arena, sizeof(SECKEYPQGParams)); |
|
217 if (params == NULL) |
|
218 goto loser; |
|
219 params->arena = arena; |
|
220 |
|
221 buf = (char *)ATOB_AsciiToData(str, &len); |
|
222 if ((buf == NULL) || (len == 0)) |
|
223 goto loser; |
|
224 |
|
225 status = SEC_ASN1Decode(arena, params, SECKEY_PQGParamsTemplate, buf, len); |
|
226 if (status != SECSuccess) |
|
227 goto loser; |
|
228 |
|
229 return params; |
|
230 |
|
231 loser: |
|
232 if (arena != NULL) |
|
233 PORT_FreeArena(arena, PR_FALSE); |
|
234 return NULL; |
|
235 } |
|
236 |
|
237 void |
|
238 CERTUTIL_DestroyParamsPQG(SECKEYPQGParams *params) |
|
239 { |
|
240 if (params->arena) { |
|
241 PORT_FreeArena(params->arena, PR_FALSE); |
|
242 } |
|
243 } |
|
244 |
|
245 static int |
|
246 pqg_prime_bits(const SECKEYPQGParams *params) |
|
247 { |
|
248 int primeBits = 0; |
|
249 |
|
250 if (params != NULL) { |
|
251 int i; |
|
252 for (i = 0; params->prime.data[i] == 0; i++) { |
|
253 /* empty */; |
|
254 } |
|
255 primeBits = (params->prime.len - i) * 8; |
|
256 } |
|
257 |
|
258 return primeBits; |
|
259 } |
|
260 |
|
261 static char * |
|
262 getPQGString(const char *filename) |
|
263 { |
|
264 unsigned char *buf = NULL; |
|
265 PRFileDesc *src; |
|
266 PRInt32 numBytes; |
|
267 PRStatus prStatus; |
|
268 PRFileInfo info; |
|
269 |
|
270 src = PR_Open(filename, PR_RDONLY, 0); |
|
271 if (!src) { |
|
272 fprintf(stderr, "Failed to open PQG file %s\n", filename); |
|
273 return NULL; |
|
274 } |
|
275 |
|
276 prStatus = PR_GetOpenFileInfo(src, &info); |
|
277 |
|
278 if (prStatus == PR_SUCCESS) { |
|
279 buf = (unsigned char*)PORT_Alloc(info.size + 1); |
|
280 } |
|
281 if (!buf) { |
|
282 PR_Close(src); |
|
283 fprintf(stderr, "Failed to read PQG file %s\n", filename); |
|
284 return NULL; |
|
285 } |
|
286 |
|
287 numBytes = PR_Read(src, buf, info.size); |
|
288 PR_Close(src); |
|
289 if (numBytes != info.size) { |
|
290 PORT_Free(buf); |
|
291 fprintf(stderr, "Failed to read PQG file %s\n", filename); |
|
292 PORT_SetError(SEC_ERROR_IO); |
|
293 return NULL; |
|
294 } |
|
295 |
|
296 if (buf[numBytes-1] == '\n') |
|
297 numBytes--; |
|
298 if (buf[numBytes-1] == '\r') |
|
299 numBytes--; |
|
300 buf[numBytes] = 0; |
|
301 |
|
302 return (char *)buf; |
|
303 } |
|
304 |
|
305 static SECKEYPQGParams* |
|
306 getpqgfromfile(int keyBits, const char *pqgFile) |
|
307 { |
|
308 char *end, *str, *pqgString; |
|
309 SECKEYPQGParams* params = NULL; |
|
310 |
|
311 str = pqgString = getPQGString(pqgFile); |
|
312 if (!str) |
|
313 return NULL; |
|
314 |
|
315 do { |
|
316 end = PORT_Strchr(str, ','); |
|
317 if (end) |
|
318 *end = '\0'; |
|
319 params = decode_pqg_params(str); |
|
320 if (params) { |
|
321 int primeBits = pqg_prime_bits(params); |
|
322 if (keyBits == primeBits) |
|
323 break; |
|
324 CERTUTIL_DestroyParamsPQG(params); |
|
325 params = NULL; |
|
326 } |
|
327 if (end) |
|
328 str = end + 1; |
|
329 } while (end); |
|
330 |
|
331 PORT_Free(pqgString); |
|
332 return params; |
|
333 } |
|
334 |
|
335 static SECStatus |
|
336 CERTUTIL_FileForRNG(const char *noise) |
|
337 { |
|
338 char buf[2048]; |
|
339 PRFileDesc *fd; |
|
340 PRInt32 count; |
|
341 |
|
342 fd = PR_Open(noise,PR_RDONLY,0); |
|
343 if (!fd) { |
|
344 fprintf(stderr, "failed to open noise file."); |
|
345 return SECFailure; |
|
346 } |
|
347 |
|
348 do { |
|
349 count = PR_Read(fd,buf,sizeof(buf)); |
|
350 if (count > 0) { |
|
351 PK11_RandomUpdate(buf,count); |
|
352 } |
|
353 } while (count > 0); |
|
354 |
|
355 PR_Close(fd); |
|
356 return SECSuccess; |
|
357 } |
|
358 |
|
359 #ifndef NSS_DISABLE_ECC |
|
360 typedef struct curveNameTagPairStr { |
|
361 char *curveName; |
|
362 SECOidTag curveOidTag; |
|
363 } CurveNameTagPair; |
|
364 |
|
365 #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1 |
|
366 /* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */ |
|
367 |
|
368 static CurveNameTagPair nameTagPair[] = |
|
369 { |
|
370 { "sect163k1", SEC_OID_SECG_EC_SECT163K1}, |
|
371 { "nistk163", SEC_OID_SECG_EC_SECT163K1}, |
|
372 { "sect163r1", SEC_OID_SECG_EC_SECT163R1}, |
|
373 { "sect163r2", SEC_OID_SECG_EC_SECT163R2}, |
|
374 { "nistb163", SEC_OID_SECG_EC_SECT163R2}, |
|
375 { "sect193r1", SEC_OID_SECG_EC_SECT193R1}, |
|
376 { "sect193r2", SEC_OID_SECG_EC_SECT193R2}, |
|
377 { "sect233k1", SEC_OID_SECG_EC_SECT233K1}, |
|
378 { "nistk233", SEC_OID_SECG_EC_SECT233K1}, |
|
379 { "sect233r1", SEC_OID_SECG_EC_SECT233R1}, |
|
380 { "nistb233", SEC_OID_SECG_EC_SECT233R1}, |
|
381 { "sect239k1", SEC_OID_SECG_EC_SECT239K1}, |
|
382 { "sect283k1", SEC_OID_SECG_EC_SECT283K1}, |
|
383 { "nistk283", SEC_OID_SECG_EC_SECT283K1}, |
|
384 { "sect283r1", SEC_OID_SECG_EC_SECT283R1}, |
|
385 { "nistb283", SEC_OID_SECG_EC_SECT283R1}, |
|
386 { "sect409k1", SEC_OID_SECG_EC_SECT409K1}, |
|
387 { "nistk409", SEC_OID_SECG_EC_SECT409K1}, |
|
388 { "sect409r1", SEC_OID_SECG_EC_SECT409R1}, |
|
389 { "nistb409", SEC_OID_SECG_EC_SECT409R1}, |
|
390 { "sect571k1", SEC_OID_SECG_EC_SECT571K1}, |
|
391 { "nistk571", SEC_OID_SECG_EC_SECT571K1}, |
|
392 { "sect571r1", SEC_OID_SECG_EC_SECT571R1}, |
|
393 { "nistb571", SEC_OID_SECG_EC_SECT571R1}, |
|
394 { "secp160k1", SEC_OID_SECG_EC_SECP160K1}, |
|
395 { "secp160r1", SEC_OID_SECG_EC_SECP160R1}, |
|
396 { "secp160r2", SEC_OID_SECG_EC_SECP160R2}, |
|
397 { "secp192k1", SEC_OID_SECG_EC_SECP192K1}, |
|
398 { "secp192r1", SEC_OID_SECG_EC_SECP192R1}, |
|
399 { "nistp192", SEC_OID_SECG_EC_SECP192R1}, |
|
400 { "secp224k1", SEC_OID_SECG_EC_SECP224K1}, |
|
401 { "secp224r1", SEC_OID_SECG_EC_SECP224R1}, |
|
402 { "nistp224", SEC_OID_SECG_EC_SECP224R1}, |
|
403 { "secp256k1", SEC_OID_SECG_EC_SECP256K1}, |
|
404 { "secp256r1", SEC_OID_SECG_EC_SECP256R1}, |
|
405 { "nistp256", SEC_OID_SECG_EC_SECP256R1}, |
|
406 { "secp384r1", SEC_OID_SECG_EC_SECP384R1}, |
|
407 { "nistp384", SEC_OID_SECG_EC_SECP384R1}, |
|
408 { "secp521r1", SEC_OID_SECG_EC_SECP521R1}, |
|
409 { "nistp521", SEC_OID_SECG_EC_SECP521R1}, |
|
410 |
|
411 { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 }, |
|
412 { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 }, |
|
413 { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 }, |
|
414 { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 }, |
|
415 { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 }, |
|
416 { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 }, |
|
417 |
|
418 { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 }, |
|
419 { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 }, |
|
420 { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 }, |
|
421 { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 }, |
|
422 { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 }, |
|
423 { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 }, |
|
424 { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 }, |
|
425 { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 }, |
|
426 { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 }, |
|
427 { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 }, |
|
428 { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 }, |
|
429 { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 }, |
|
430 { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 }, |
|
431 { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 }, |
|
432 { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 }, |
|
433 { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 }, |
|
434 { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 }, |
|
435 { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 }, |
|
436 { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 }, |
|
437 { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 }, |
|
438 |
|
439 { "secp112r1", SEC_OID_SECG_EC_SECP112R1}, |
|
440 { "secp112r2", SEC_OID_SECG_EC_SECP112R2}, |
|
441 { "secp128r1", SEC_OID_SECG_EC_SECP128R1}, |
|
442 { "secp128r2", SEC_OID_SECG_EC_SECP128R2}, |
|
443 |
|
444 { "sect113r1", SEC_OID_SECG_EC_SECT113R1}, |
|
445 { "sect113r2", SEC_OID_SECG_EC_SECT113R2}, |
|
446 { "sect131r1", SEC_OID_SECG_EC_SECT131R1}, |
|
447 { "sect131r2", SEC_OID_SECG_EC_SECT131R2}, |
|
448 }; |
|
449 |
|
450 static SECKEYECParams * |
|
451 getECParams(const char *curve) |
|
452 { |
|
453 SECKEYECParams *ecparams; |
|
454 SECOidData *oidData = NULL; |
|
455 SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */ |
|
456 int i, numCurves; |
|
457 |
|
458 if (curve != NULL) { |
|
459 numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair); |
|
460 for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); |
|
461 i++) { |
|
462 if (PL_strcmp(curve, nameTagPair[i].curveName) == 0) |
|
463 curveOidTag = nameTagPair[i].curveOidTag; |
|
464 } |
|
465 } |
|
466 |
|
467 /* Return NULL if curve name is not recognized */ |
|
468 if ((curveOidTag == SEC_OID_UNKNOWN) || |
|
469 (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) { |
|
470 fprintf(stderr, "Unrecognized elliptic curve %s\n", curve); |
|
471 return NULL; |
|
472 } |
|
473 |
|
474 ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len)); |
|
475 |
|
476 /* |
|
477 * ecparams->data needs to contain the ASN encoding of an object ID (OID) |
|
478 * representing the named curve. The actual OID is in |
|
479 * oidData->oid.data so we simply prepend 0x06 and OID length |
|
480 */ |
|
481 ecparams->data[0] = SEC_ASN1_OBJECT_ID; |
|
482 ecparams->data[1] = oidData->oid.len; |
|
483 memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len); |
|
484 |
|
485 return ecparams; |
|
486 } |
|
487 #endif /* NSS_DISABLE_ECC */ |
|
488 |
|
489 SECKEYPrivateKey * |
|
490 CERTUTIL_GeneratePrivateKey(KeyType keytype, PK11SlotInfo *slot, int size, |
|
491 int publicExponent, const char *noise, |
|
492 SECKEYPublicKey **pubkeyp, const char *pqgFile, |
|
493 PK11AttrFlags attrFlags, CK_FLAGS opFlagsOn, |
|
494 CK_FLAGS opFlagsOff, secuPWData *pwdata) |
|
495 { |
|
496 CK_MECHANISM_TYPE mechanism; |
|
497 SECOidTag algtag; |
|
498 PK11RSAGenParams rsaparams; |
|
499 SECKEYPQGParams * dsaparams = NULL; |
|
500 void * params; |
|
501 SECKEYPrivateKey * privKey = NULL; |
|
502 |
|
503 if (slot == NULL) |
|
504 return NULL; |
|
505 |
|
506 if (PK11_Authenticate(slot, PR_TRUE, pwdata) != SECSuccess) |
|
507 return NULL; |
|
508 |
|
509 /* |
|
510 * Do some random-number initialization. |
|
511 */ |
|
512 |
|
513 if (noise) { |
|
514 SECStatus rv = CERTUTIL_FileForRNG(noise); |
|
515 if (rv != SECSuccess) { |
|
516 PORT_SetError(PR_END_OF_FILE_ERROR); /* XXX */ |
|
517 return NULL; |
|
518 } |
|
519 } else { |
|
520 int rv = UpdateRNG(); |
|
521 if (rv) { |
|
522 PORT_SetError(PR_END_OF_FILE_ERROR); |
|
523 return NULL; |
|
524 } |
|
525 } |
|
526 |
|
527 switch (keytype) { |
|
528 case rsaKey: |
|
529 rsaparams.keySizeInBits = size; |
|
530 rsaparams.pe = publicExponent; |
|
531 mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; |
|
532 algtag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION; |
|
533 params = &rsaparams; |
|
534 break; |
|
535 case dsaKey: |
|
536 mechanism = CKM_DSA_KEY_PAIR_GEN; |
|
537 algtag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; |
|
538 if (pqgFile) { |
|
539 dsaparams = getpqgfromfile(size, pqgFile); |
|
540 if (dsaparams == NULL) |
|
541 return NULL; |
|
542 params = dsaparams; |
|
543 } else { |
|
544 /* cast away const, and don't set dsaparams */ |
|
545 params = (void *)&default_pqg_params; |
|
546 } |
|
547 break; |
|
548 #ifndef NSS_DISABLE_ECC |
|
549 case ecKey: |
|
550 mechanism = CKM_EC_KEY_PAIR_GEN; |
|
551 /* For EC keys, PQGFile determines EC parameters */ |
|
552 if ((params = (void *) getECParams(pqgFile)) == NULL) |
|
553 return NULL; |
|
554 break; |
|
555 #endif /* NSS_DISABLE_ECC */ |
|
556 default: |
|
557 return NULL; |
|
558 } |
|
559 |
|
560 fprintf(stderr, "\n\n"); |
|
561 fprintf(stderr, "Generating key. This may take a few moments...\n\n"); |
|
562 |
|
563 privKey = PK11_GenerateKeyPairWithOpFlags(slot, mechanism, params, pubkeyp, |
|
564 attrFlags, opFlagsOn, opFlagsOn|opFlagsOff, |
|
565 pwdata /*wincx*/); |
|
566 /* free up the params */ |
|
567 switch (keytype) { |
|
568 case dsaKey: if (dsaparams) CERTUTIL_DestroyParamsPQG(dsaparams); |
|
569 break; |
|
570 #ifndef NSS_DISABLE_ECC |
|
571 case ecKey: SECITEM_FreeItem((SECItem *)params, PR_TRUE); break; |
|
572 #endif |
|
573 default: /* nothing to free */ break; |
|
574 } |
|
575 return privKey; |
|
576 } |