Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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/. */
5 #include <stdio.h>
6 #include <string.h>
7 #include "secutil.h"
9 #if defined(XP_UNIX)
10 #include <unistd.h>
11 #include <sys/time.h>
12 #include <termios.h>
13 #endif
15 #if defined(XP_WIN) || defined (XP_PC)
16 #include <time.h>
17 #include <conio.h>
18 #endif
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
28 #include "nspr.h"
29 #include "prtypes.h"
30 #include "prtime.h"
31 #include "prlong.h"
33 #include "pk11func.h"
35 #define NUM_KEYSTROKES 120
36 #define RAND_BUF_SIZE 60
38 #define ERROR_BREAK rv = SECFailure;break;
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 };
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| |" };
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|");
79 /* turn off echo on stdin & return on 1 char instead of NL */
80 fd = fileno(stdin);
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
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);
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");
123 #undef FPS
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 }
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 };
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 */
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 };
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;
212 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
213 if (arena == NULL)
214 return NULL;
216 params = PORT_ArenaZAlloc(arena, sizeof(SECKEYPQGParams));
217 if (params == NULL)
218 goto loser;
219 params->arena = arena;
221 buf = (char *)ATOB_AsciiToData(str, &len);
222 if ((buf == NULL) || (len == 0))
223 goto loser;
225 status = SEC_ASN1Decode(arena, params, SECKEY_PQGParamsTemplate, buf, len);
226 if (status != SECSuccess)
227 goto loser;
229 return params;
231 loser:
232 if (arena != NULL)
233 PORT_FreeArena(arena, PR_FALSE);
234 return NULL;
235 }
237 void
238 CERTUTIL_DestroyParamsPQG(SECKEYPQGParams *params)
239 {
240 if (params->arena) {
241 PORT_FreeArena(params->arena, PR_FALSE);
242 }
243 }
245 static int
246 pqg_prime_bits(const SECKEYPQGParams *params)
247 {
248 int primeBits = 0;
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 }
258 return primeBits;
259 }
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;
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 }
276 prStatus = PR_GetOpenFileInfo(src, &info);
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 }
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 }
296 if (buf[numBytes-1] == '\n')
297 numBytes--;
298 if (buf[numBytes-1] == '\r')
299 numBytes--;
300 buf[numBytes] = 0;
302 return (char *)buf;
303 }
305 static SECKEYPQGParams*
306 getpqgfromfile(int keyBits, const char *pqgFile)
307 {
308 char *end, *str, *pqgString;
309 SECKEYPQGParams* params = NULL;
311 str = pqgString = getPQGString(pqgFile);
312 if (!str)
313 return NULL;
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);
331 PORT_Free(pqgString);
332 return params;
333 }
335 static SECStatus
336 CERTUTIL_FileForRNG(const char *noise)
337 {
338 char buf[2048];
339 PRFileDesc *fd;
340 PRInt32 count;
342 fd = PR_Open(noise,PR_RDONLY,0);
343 if (!fd) {
344 fprintf(stderr, "failed to open noise file.");
345 return SECFailure;
346 }
348 do {
349 count = PR_Read(fd,buf,sizeof(buf));
350 if (count > 0) {
351 PK11_RandomUpdate(buf,count);
352 }
353 } while (count > 0);
355 PR_Close(fd);
356 return SECSuccess;
357 }
359 #ifndef NSS_DISABLE_ECC
360 typedef struct curveNameTagPairStr {
361 char *curveName;
362 SECOidTag curveOidTag;
363 } CurveNameTagPair;
365 #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1
366 /* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */
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},
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 },
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 },
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},
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 };
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;
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 }
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 }
474 ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
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);
485 return ecparams;
486 }
487 #endif /* NSS_DISABLE_ECC */
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;
503 if (slot == NULL)
504 return NULL;
506 if (PK11_Authenticate(slot, PR_TRUE, pwdata) != SECSuccess)
507 return NULL;
509 /*
510 * Do some random-number initialization.
511 */
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 }
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 }
560 fprintf(stderr, "\n\n");
561 fprintf(stderr, "Generating key. This may take a few moments...\n\n");
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 }