1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
* The contents of this file are subject to the Mozilla Public License Version
5
* 1.1 (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
7
* http://www.mozilla.org/MPL/
9
* Software distributed under the License is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
* for the specific language governing rights and limitations under the
14
* The Original Code is the Netscape security libraries.
16
* The Initial Developer of the Original Code is
17
* Netscape Communications Corporation.
18
* Portions created by the Initial Developer are Copyright (C) 1994-2000
19
* the Initial Developer. All Rights Reserved.
22
* Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
24
* Alternatively, the contents of this file may be used under the terms of
25
* either the GNU General Public License Version 2 or later (the "GPL"), or
26
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
* in which case the provisions of the GPL or the LGPL are applicable instead
28
* of those above. If you wish to allow use of your version of this file only
29
* under the terms of either the GPL or the LGPL, and not to allow others to
30
* use your version of this file under the terms of the MPL, indicate your
31
* decision by deleting the provisions above and replace them with the notice
32
* and other provisions required by the GPL or the LGPL. If you do not delete
33
* the provisions above, a recipient may use your version of this file under
34
* the terms of any one of the MPL, the GPL or the LGPL.
36
* ***** END LICENSE BLOCK ***** */
48
#if defined(XP_WIN) || defined (XP_PC)
53
#if defined(__sun) && !defined(SVR4)
54
extern int fclose(FILE*);
55
extern int fprintf(FILE *, char *, ...);
56
extern int isatty(int);
57
extern char *sys_errlist[];
58
#define strerror(errno) sys_errlist[errno]
68
#define NUM_KEYSTROKES 120
69
#define RAND_BUF_SIZE 60
71
#define ERROR_BREAK rv = SECFailure;break;
73
const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = {
74
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) },
75
{ SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,prime) },
76
{ SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,subPrime) },
77
{ SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,base) },
81
/* returns 0 for success, -1 for failure (EOF encountered) */
96
#define FPS fprintf(stderr,
98
FPS "A random seed must be generated that will be used in the\n");
99
FPS "creation of your key. One of the easiest ways to create a\n");
100
FPS "random seed is to use the timing of keystrokes on a keyboard.\n");
102
FPS "To begin, type keys on the keyboard until this progress meter\n");
103
FPS "is full. DO NOT USE THE AUTOREPEAT FUNCTION ON YOUR KEYBOARD!\n");
106
FPS "Continue typing until the progress meter is full:\n\n");
109
/* turn off echo on stdin & return on 1 char instead of NL */
112
#if defined(XP_UNIX) && !defined(VMS)
114
orig_lflag = tio.c_lflag;
115
orig_cc_min = tio.c_cc[VMIN];
116
orig_cc_time = tio.c_cc[VTIME];
117
tio.c_lflag &= ~ECHO;
118
tio.c_lflag &= ~ICANON;
121
tcsetattr(fd, TCSAFLUSH, &tio);
124
/* Get random noise from keyboard strokes */
125
randbuf = (char *) PORT_Alloc(RAND_BUF_SIZE);
127
while (count < NUM_KEYSTROKES+1) {
129
c = GENERIC_GETCHAR_NOECHO();
139
PK11_RandomUpdate(randbuf, sizeof(randbuf));
140
if (c != randbuf[0]) {
143
for (i=0; i<count/(NUM_KEYSTROKES/RAND_BUF_SIZE); i++) {
146
if (count%(NUM_KEYSTROKES/RAND_BUF_SIZE) == 1)
154
FPS "Finished. Press enter to continue: ");
156
while((c = GENERIC_GETCHAR_NO_ECHO()) != '\r' && c != EOF)
159
while ((c = getc(stdin)) != '\n' && c != EOF)
168
#if defined(XP_UNIX) && !defined(VMS)
169
/* set back termio the way it was */
170
tio.c_lflag = orig_lflag;
171
tio.c_cc[VMIN] = orig_cc_min;
172
tio.c_cc[VTIME] = orig_cc_time;
173
tcsetattr(fd, TCSAFLUSH, &tio);
179
static const unsigned char P[] =
180
{ 0x00, 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76,
181
0xaa, 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69,
182
0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c,
183
0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82,
184
0xe5, 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e,
185
0xaf, 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a,
186
0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
187
0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02,
189
static const unsigned char Q[] =
190
{ 0x00, 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8,
191
0xee, 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4,
192
0x8e, 0xda, 0xce, 0x91, 0x5f };
193
static const unsigned char G[] =
194
{ 0x00, 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a,
195
0x13, 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5,
196
0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef,
197
0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c,
198
0x2e, 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba,
199
0xbf, 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c,
200
0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
201
0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88,
204
static const SECKEYPQGParams default_pqg_params = {
206
{ 0, (unsigned char *)P, sizeof(P) },
207
{ 0, (unsigned char *)Q, sizeof(Q) },
208
{ 0, (unsigned char *)G, sizeof(G) }
211
static SECKEYPQGParams *
212
decode_pqg_params(const char *str)
217
SECKEYPQGParams *params;
220
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
224
params = PORT_ArenaZAlloc(arena, sizeof(SECKEYPQGParams));
227
params->arena = arena;
229
buf = (char *)ATOB_AsciiToData(str, &len);
230
if ((buf == NULL) || (len == 0))
233
status = SEC_ASN1Decode(arena, params, SECKEY_PQGParamsTemplate, buf, len);
234
if (status != SECSuccess)
241
PORT_FreeArena(arena, PR_FALSE);
246
CERTUTIL_DestroyParamsPQG(SECKEYPQGParams *params)
249
PORT_FreeArena(params->arena, PR_FALSE);
254
pqg_prime_bits(const SECKEYPQGParams *params)
258
if (params != NULL) {
260
for (i = 0; params->prime.data[i] == 0; i++) {
263
primeBits = (params->prime.len - i) * 8;
270
getPQGString(const char *filename)
272
unsigned char *buf = NULL;
278
src = PR_Open(filename, PR_RDONLY, 0);
280
fprintf(stderr, "Failed to open PQG file %s\n", filename);
284
prStatus = PR_GetOpenFileInfo(src, &info);
286
if (prStatus == PR_SUCCESS) {
287
buf = (unsigned char*)PORT_Alloc(info.size + 1);
291
fprintf(stderr, "Failed to read PQG file %s\n", filename);
295
numBytes = PR_Read(src, buf, info.size);
297
if (numBytes != info.size) {
299
fprintf(stderr, "Failed to read PQG file %s\n", filename);
300
PORT_SetError(SEC_ERROR_IO);
304
if (buf[numBytes-1] == '\n')
306
if (buf[numBytes-1] == '\r')
313
static SECKEYPQGParams*
314
getpqgfromfile(int keyBits, const char *pqgFile)
316
char *end, *str, *pqgString;
317
SECKEYPQGParams* params = NULL;
319
str = pqgString = getPQGString(pqgFile);
324
end = PORT_Strchr(str, ',');
327
params = decode_pqg_params(str);
329
int primeBits = pqg_prime_bits(params);
330
if (keyBits == primeBits)
332
CERTUTIL_DestroyParamsPQG(params);
339
PORT_Free(pqgString);
344
CERTUTIL_FileForRNG(const char *noise)
350
fd = PR_Open(noise,PR_RDONLY,0);
352
fprintf(stderr, "failed to open noise file.");
357
count = PR_Read(fd,buf,sizeof(buf));
359
PK11_RandomUpdate(buf,count);
367
#ifdef NSS_ENABLE_ECC
368
typedef struct curveNameTagPairStr {
370
SECOidTag curveOidTag;
373
#define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1
374
/* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */
376
static CurveNameTagPair nameTagPair[] =
378
{ "sect163k1", SEC_OID_SECG_EC_SECT163K1},
379
{ "nistk163", SEC_OID_SECG_EC_SECT163K1},
380
{ "sect163r1", SEC_OID_SECG_EC_SECT163R1},
381
{ "sect163r2", SEC_OID_SECG_EC_SECT163R2},
382
{ "nistb163", SEC_OID_SECG_EC_SECT163R2},
383
{ "sect193r1", SEC_OID_SECG_EC_SECT193R1},
384
{ "sect193r2", SEC_OID_SECG_EC_SECT193R2},
385
{ "sect233k1", SEC_OID_SECG_EC_SECT233K1},
386
{ "nistk233", SEC_OID_SECG_EC_SECT233K1},
387
{ "sect233r1", SEC_OID_SECG_EC_SECT233R1},
388
{ "nistb233", SEC_OID_SECG_EC_SECT233R1},
389
{ "sect239k1", SEC_OID_SECG_EC_SECT239K1},
390
{ "sect283k1", SEC_OID_SECG_EC_SECT283K1},
391
{ "nistk283", SEC_OID_SECG_EC_SECT283K1},
392
{ "sect283r1", SEC_OID_SECG_EC_SECT283R1},
393
{ "nistb283", SEC_OID_SECG_EC_SECT283R1},
394
{ "sect409k1", SEC_OID_SECG_EC_SECT409K1},
395
{ "nistk409", SEC_OID_SECG_EC_SECT409K1},
396
{ "sect409r1", SEC_OID_SECG_EC_SECT409R1},
397
{ "nistb409", SEC_OID_SECG_EC_SECT409R1},
398
{ "sect571k1", SEC_OID_SECG_EC_SECT571K1},
399
{ "nistk571", SEC_OID_SECG_EC_SECT571K1},
400
{ "sect571r1", SEC_OID_SECG_EC_SECT571R1},
401
{ "nistb571", SEC_OID_SECG_EC_SECT571R1},
402
{ "secp160k1", SEC_OID_SECG_EC_SECP160K1},
403
{ "secp160r1", SEC_OID_SECG_EC_SECP160R1},
404
{ "secp160r2", SEC_OID_SECG_EC_SECP160R2},
405
{ "secp192k1", SEC_OID_SECG_EC_SECP192K1},
406
{ "secp192r1", SEC_OID_SECG_EC_SECP192R1},
407
{ "nistp192", SEC_OID_SECG_EC_SECP192R1},
408
{ "secp224k1", SEC_OID_SECG_EC_SECP224K1},
409
{ "secp224r1", SEC_OID_SECG_EC_SECP224R1},
410
{ "nistp224", SEC_OID_SECG_EC_SECP224R1},
411
{ "secp256k1", SEC_OID_SECG_EC_SECP256K1},
412
{ "secp256r1", SEC_OID_SECG_EC_SECP256R1},
413
{ "nistp256", SEC_OID_SECG_EC_SECP256R1},
414
{ "secp384r1", SEC_OID_SECG_EC_SECP384R1},
415
{ "nistp384", SEC_OID_SECG_EC_SECP384R1},
416
{ "secp521r1", SEC_OID_SECG_EC_SECP521R1},
417
{ "nistp521", SEC_OID_SECG_EC_SECP521R1},
419
{ "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 },
420
{ "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 },
421
{ "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 },
422
{ "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 },
423
{ "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 },
424
{ "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 },
426
{ "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 },
427
{ "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 },
428
{ "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 },
429
{ "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 },
430
{ "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 },
431
{ "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 },
432
{ "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 },
433
{ "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 },
434
{ "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 },
435
{ "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 },
436
{ "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 },
437
{ "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 },
438
{ "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 },
439
{ "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 },
440
{ "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 },
441
{ "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 },
442
{ "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 },
443
{ "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 },
444
{ "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 },
445
{ "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 },
447
{ "secp112r1", SEC_OID_SECG_EC_SECP112R1},
448
{ "secp112r2", SEC_OID_SECG_EC_SECP112R2},
449
{ "secp128r1", SEC_OID_SECG_EC_SECP128R1},
450
{ "secp128r2", SEC_OID_SECG_EC_SECP128R2},
452
{ "sect113r1", SEC_OID_SECG_EC_SECT113R1},
453
{ "sect113r2", SEC_OID_SECG_EC_SECT113R2},
454
{ "sect131r1", SEC_OID_SECG_EC_SECT131R1},
455
{ "sect131r2", SEC_OID_SECG_EC_SECT131R2},
458
static SECKEYECParams *
459
getECParams(const char *curve)
461
SECKEYECParams *ecparams;
462
SECOidData *oidData = NULL;
463
SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
467
numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair);
468
for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN));
470
if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
471
curveOidTag = nameTagPair[i].curveOidTag;
475
/* Return NULL if curve name is not recognized */
476
if ((curveOidTag == SEC_OID_UNKNOWN) ||
477
(oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) {
478
fprintf(stderr, "Unrecognized elliptic curve %s\n", curve);
482
ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
485
* ecparams->data needs to contain the ASN encoding of an object ID (OID)
486
* representing the named curve. The actual OID is in
487
* oidData->oid.data so we simply prepend 0x06 and OID length
489
ecparams->data[0] = SEC_ASN1_OBJECT_ID;
490
ecparams->data[1] = oidData->oid.len;
491
memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len);
495
#endif /* NSS_ENABLE_ECC */
498
CERTUTIL_GeneratePrivateKey(KeyType keytype, PK11SlotInfo *slot, int size,
499
int publicExponent, const char *noise,
500
SECKEYPublicKey **pubkeyp, const char *pqgFile,
503
CK_MECHANISM_TYPE mechanism;
505
PK11RSAGenParams rsaparams;
506
SECKEYPQGParams * dsaparams = NULL;
508
SECKEYPrivateKey * privKey = NULL;
513
if (PK11_Authenticate(slot, PR_TRUE, pwdata) != SECSuccess)
517
* Do some random-number initialization.
521
SECStatus rv = CERTUTIL_FileForRNG(noise);
522
if (rv != SECSuccess) {
523
PORT_SetError(PR_END_OF_FILE_ERROR); /* XXX */
527
int rv = UpdateRNG();
529
PORT_SetError(PR_END_OF_FILE_ERROR);
536
rsaparams.keySizeInBits = size;
537
rsaparams.pe = publicExponent;
538
mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
539
algtag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
543
mechanism = CKM_DSA_KEY_PAIR_GEN;
544
algtag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
546
dsaparams = getpqgfromfile(size, pqgFile);
547
if (dsaparams == NULL)
551
/* cast away const, and don't set dsaparams */
552
params = (void *)&default_pqg_params;
555
#ifdef NSS_ENABLE_ECC
557
mechanism = CKM_EC_KEY_PAIR_GEN;
558
/* For EC keys, PQGFile determines EC parameters */
559
if ((params = (void *) getECParams(pqgFile)) == NULL)
562
#endif /* NSS_ENABLE_ECC */
567
fprintf(stderr, "\n\n");
568
fprintf(stderr, "Generating key. This may take a few moments...\n\n");
570
privKey = PK11_GenerateKeyPair(slot, mechanism, params, pubkeyp,
571
PR_TRUE /*isPerm*/, PR_TRUE /*isSensitive*/,
573
/* free up the params */
575
case rsaKey: /* nothing to free */ break;
576
case dsaKey: if (dsaparams) CERTUTIL_DestroyParamsPQG(dsaparams);
578
#ifdef NSS_ENABLE_ECC
579
case ecKey: SECITEM_FreeItem((SECItem *)params, PR_TRUE); break;