~ubuntu-branches/ubuntu/lucid/seamonkey/lucid-security

« back to all changes in this revision

Viewing changes to security/nss-fips/cmd/certutil/keystuff.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabien Tassin
  • Date: 2008-07-29 21:29:02 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20080729212902-spm9kpvchp9udwbw
Tags: 1.1.11+nobinonly-0ubuntu1
* New security upstream release: 1.1.11 (LP: #218534)
  Fixes USN-602-1, USN-619-1, USN-623-1 and USN-629-1
* Refresh diverged patch:
  - update debian/patches/80_security_build.patch
* Fix FTBFS with missing -lfontconfig
  - add debian/patches/11_fix_ftbfs_with_fontconfig.patch
  - update debian/patches/series
* Build with default gcc (hardy: 4.2, intrepid: 4.3)
  - update debian/rules
  - update debian/control

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ***** BEGIN LICENSE BLOCK *****
 
2
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
3
 *
 
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/
 
8
 *
 
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
 
12
 * License.
 
13
 *
 
14
 * The Original Code is the Netscape security libraries.
 
15
 *
 
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.
 
20
 *
 
21
 * Contributor(s):
 
22
 *   Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
 
23
 *
 
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.
 
35
 *
 
36
 * ***** END LICENSE BLOCK ***** */
 
37
 
 
38
#include <stdio.h>
 
39
#include <string.h>
 
40
#include "secutil.h"
 
41
 
 
42
#if defined(XP_UNIX)
 
43
#include <unistd.h>
 
44
#include <sys/time.h>
 
45
#include <termios.h>
 
46
#endif
 
47
 
 
48
#if defined(XP_WIN) || defined (XP_PC)
 
49
#include <time.h>
 
50
#include <conio.h>
 
51
#endif
 
52
 
 
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]
 
59
#endif
 
60
 
 
61
#include "nspr.h"
 
62
#include "prtypes.h"
 
63
#include "prtime.h"
 
64
#include "prlong.h"
 
65
 
 
66
#include "pk11func.h"
 
67
 
 
68
#define NUM_KEYSTROKES 120
 
69
#define RAND_BUF_SIZE 60
 
70
 
 
71
#define ERROR_BREAK rv = SECFailure;break;
 
72
 
 
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) },
 
78
    { 0, }
 
79
};
 
80
 
 
81
/* returns 0 for success, -1 for failure (EOF encountered) */
 
82
static int
 
83
UpdateRNG(void)
 
84
{
 
85
    char *         randbuf;
 
86
    int            fd, i, count;
 
87
    int            c;
 
88
    int            rv           = 0;
 
89
#ifdef XP_UNIX
 
90
    cc_t           orig_cc_min;
 
91
    cc_t           orig_cc_time;
 
92
    tcflag_t       orig_lflag;
 
93
    struct termios tio;
 
94
#endif
 
95
 
 
96
#define FPS fprintf(stderr, 
 
97
    FPS "\n");
 
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");
 
101
    FPS "\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");
 
104
    FPS "\n");
 
105
    FPS "\n");
 
106
    FPS "Continue typing until the progress meter is full:\n\n");
 
107
    FPS "|                                                            |\r");
 
108
 
 
109
    /* turn off echo on stdin & return on 1 char instead of NL */
 
110
    fd = fileno(stdin);
 
111
 
 
112
#if defined(XP_UNIX) && !defined(VMS)
 
113
    tcgetattr(fd, &tio);
 
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;
 
119
    tio.c_cc[VMIN] = 1;
 
120
    tio.c_cc[VTIME] = 0;
 
121
    tcsetattr(fd, TCSAFLUSH, &tio);
 
122
#endif
 
123
 
 
124
    /* Get random noise from keyboard strokes */
 
125
    randbuf = (char *) PORT_Alloc(RAND_BUF_SIZE);
 
126
    count = 0;
 
127
    while (count < NUM_KEYSTROKES+1) {
 
128
#ifdef VMS
 
129
        c = GENERIC_GETCHAR_NOECHO();
 
130
#elif XP_UNIX
 
131
        c = getc(stdin);
 
132
#else
 
133
        c = getch();
 
134
#endif
 
135
        if (c == EOF) {
 
136
            rv = -1;
 
137
            break;
 
138
        }
 
139
        PK11_RandomUpdate(randbuf, sizeof(randbuf));
 
140
        if (c != randbuf[0]) {
 
141
            randbuf[0] = c;
 
142
            FPS "\r|");
 
143
            for (i=0; i<count/(NUM_KEYSTROKES/RAND_BUF_SIZE); i++) {
 
144
                FPS "*");
 
145
            }
 
146
            if (count%(NUM_KEYSTROKES/RAND_BUF_SIZE) == 1)
 
147
                FPS "/");
 
148
            count++;
 
149
        }
 
150
    }
 
151
    free(randbuf); 
 
152
 
 
153
    FPS "\n\n");
 
154
    FPS "Finished.  Press enter to continue: ");
 
155
#if defined(VMS)
 
156
    while((c = GENERIC_GETCHAR_NO_ECHO()) != '\r' && c != EOF)
 
157
        ;
 
158
#else
 
159
    while ((c = getc(stdin)) != '\n' && c != EOF)
 
160
        ;
 
161
#endif
 
162
    if (c == EOF) 
 
163
        rv = -1;
 
164
    FPS "\n");
 
165
 
 
166
#undef FPS
 
167
 
 
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);
 
174
#endif
 
175
    return rv;
 
176
}
 
177
 
 
178
 
 
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,
 
188
                             0x91 };
 
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,
 
202
                             0x02 };
 
203
 
 
204
static const SECKEYPQGParams default_pqg_params = {
 
205
    NULL,
 
206
    { 0, (unsigned char *)P, sizeof(P) },
 
207
    { 0, (unsigned char *)Q, sizeof(Q) },
 
208
    { 0, (unsigned char *)G, sizeof(G) }
 
209
};
 
210
 
 
211
static SECKEYPQGParams *
 
212
decode_pqg_params(const char *str)
 
213
{
 
214
    char *buf;
 
215
    unsigned int len;
 
216
    PRArenaPool *arena;
 
217
    SECKEYPQGParams *params;
 
218
    SECStatus status;
 
219
 
 
220
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 
221
    if (arena == NULL)
 
222
        return NULL;
 
223
 
 
224
    params = PORT_ArenaZAlloc(arena, sizeof(SECKEYPQGParams));
 
225
    if (params == NULL)
 
226
        goto loser;
 
227
    params->arena = arena;
 
228
 
 
229
    buf = (char *)ATOB_AsciiToData(str, &len);
 
230
    if ((buf == NULL) || (len == 0))
 
231
        goto loser;
 
232
 
 
233
    status = SEC_ASN1Decode(arena, params, SECKEY_PQGParamsTemplate, buf, len);
 
234
    if (status != SECSuccess)
 
235
        goto loser;
 
236
 
 
237
    return params;
 
238
 
 
239
loser:
 
240
    if (arena != NULL)
 
241
        PORT_FreeArena(arena, PR_FALSE);
 
242
    return NULL;
 
243
}
 
244
 
 
245
void  
 
246
CERTUTIL_DestroyParamsPQG(SECKEYPQGParams *params)
 
247
{
 
248
    if (params->arena) {
 
249
        PORT_FreeArena(params->arena, PR_FALSE);
 
250
    }
 
251
}
 
252
 
 
253
static int
 
254
pqg_prime_bits(const SECKEYPQGParams *params)
 
255
{
 
256
    int primeBits = 0;
 
257
 
 
258
    if (params != NULL) {
 
259
        int i;
 
260
        for (i = 0; params->prime.data[i] == 0; i++) {
 
261
            /* empty */;
 
262
        }
 
263
        primeBits = (params->prime.len - i) * 8;
 
264
    }
 
265
 
 
266
    return primeBits;
 
267
}
 
268
 
 
269
static char *
 
270
getPQGString(const char *filename)
 
271
{
 
272
    unsigned char *buf      = NULL;
 
273
    PRFileDesc    *src;
 
274
    PRInt32        numBytes;
 
275
    PRStatus       prStatus;
 
276
    PRFileInfo     info;
 
277
 
 
278
    src   = PR_Open(filename, PR_RDONLY, 0);
 
279
    if (!src) {
 
280
        fprintf(stderr, "Failed to open PQG file %s\n", filename);
 
281
        return NULL;
 
282
    }
 
283
 
 
284
    prStatus = PR_GetOpenFileInfo(src, &info);
 
285
 
 
286
    if (prStatus == PR_SUCCESS) {
 
287
        buf = (unsigned char*)PORT_Alloc(info.size + 1);
 
288
    }
 
289
    if (!buf) {
 
290
        PR_Close(src);
 
291
        fprintf(stderr, "Failed to read PQG file %s\n", filename);
 
292
        return NULL;
 
293
    }
 
294
 
 
295
    numBytes = PR_Read(src, buf, info.size);
 
296
    PR_Close(src);
 
297
    if (numBytes != info.size) {
 
298
        PORT_Free(buf);
 
299
        fprintf(stderr, "Failed to read PQG file %s\n", filename);
 
300
        PORT_SetError(SEC_ERROR_IO);
 
301
        return NULL;
 
302
    }
 
303
 
 
304
    if (buf[numBytes-1] == '\n') 
 
305
        numBytes--;
 
306
    if (buf[numBytes-1] == '\r') 
 
307
        numBytes--;
 
308
    buf[numBytes] = 0;
 
309
    
 
310
    return (char *)buf;
 
311
}
 
312
 
 
313
static SECKEYPQGParams*
 
314
getpqgfromfile(int keyBits, const char *pqgFile)
 
315
{
 
316
    char *end, *str, *pqgString;
 
317
    SECKEYPQGParams* params = NULL;
 
318
 
 
319
    str = pqgString = getPQGString(pqgFile);
 
320
    if (!str) 
 
321
        return NULL;
 
322
 
 
323
    do {
 
324
        end = PORT_Strchr(str, ',');
 
325
        if (end)
 
326
            *end = '\0';
 
327
        params = decode_pqg_params(str);
 
328
        if (params) {
 
329
            int primeBits = pqg_prime_bits(params);
 
330
            if (keyBits == primeBits)
 
331
                break;
 
332
            CERTUTIL_DestroyParamsPQG(params);
 
333
            params = NULL;
 
334
        }
 
335
        if (end)
 
336
            str = end + 1;
 
337
    } while (end);
 
338
 
 
339
    PORT_Free(pqgString);
 
340
    return params;
 
341
}
 
342
 
 
343
static SECStatus 
 
344
CERTUTIL_FileForRNG(const char *noise)
 
345
{
 
346
    char buf[2048];
 
347
    PRFileDesc *fd;
 
348
    PRInt32 count;
 
349
 
 
350
    fd = PR_Open(noise,PR_RDONLY,0);
 
351
    if (!fd) {
 
352
        fprintf(stderr, "failed to open noise file.");
 
353
        return SECFailure;
 
354
    }
 
355
 
 
356
    do {
 
357
        count = PR_Read(fd,buf,sizeof(buf));
 
358
        if (count > 0) {
 
359
            PK11_RandomUpdate(buf,count);
 
360
        }
 
361
    } while (count > 0);
 
362
 
 
363
    PR_Close(fd);
 
364
    return SECSuccess;
 
365
}
 
366
 
 
367
#ifdef NSS_ENABLE_ECC
 
368
typedef struct curveNameTagPairStr {
 
369
    char *curveName;
 
370
    SECOidTag curveOidTag;
 
371
} CurveNameTagPair;
 
372
 
 
373
#define DEFAULT_CURVE_OID_TAG  SEC_OID_SECG_EC_SECP192R1
 
374
/* #define DEFAULT_CURVE_OID_TAG  SEC_OID_SECG_EC_SECP160R1 */
 
375
 
 
376
static CurveNameTagPair nameTagPair[] =
 
377
 
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},
 
418
 
 
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 },
 
425
 
 
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 },
 
446
 
 
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},
 
451
 
 
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},
 
456
};
 
457
 
 
458
static SECKEYECParams * 
 
459
getECParams(const char *curve)
 
460
{
 
461
    SECKEYECParams *ecparams;
 
462
    SECOidData *oidData = NULL;
 
463
    SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
 
464
    int i, numCurves;
 
465
 
 
466
    if (curve != NULL) {
 
467
        numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair);
 
468
        for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); 
 
469
             i++) {
 
470
            if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
 
471
                curveOidTag = nameTagPair[i].curveOidTag;
 
472
        }
 
473
    }
 
474
 
 
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);
 
479
        return NULL;
 
480
    }
 
481
 
 
482
    ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
 
483
 
 
484
    /* 
 
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
 
488
     */
 
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);
 
492
 
 
493
    return ecparams;
 
494
}
 
495
#endif /* NSS_ENABLE_ECC */
 
496
 
 
497
SECKEYPrivateKey *
 
498
CERTUTIL_GeneratePrivateKey(KeyType keytype, PK11SlotInfo *slot, int size,
 
499
                            int publicExponent, const char *noise, 
 
500
                            SECKEYPublicKey **pubkeyp, const char *pqgFile,
 
501
                            secuPWData *pwdata)
 
502
{
 
503
    CK_MECHANISM_TYPE  mechanism;
 
504
    SECOidTag          algtag;
 
505
    PK11RSAGenParams   rsaparams;
 
506
    SECKEYPQGParams  * dsaparams = NULL;
 
507
    void             * params;
 
508
    SECKEYPrivateKey * privKey = NULL;
 
509
 
 
510
    if (slot == NULL)
 
511
        return NULL;
 
512
 
 
513
    if (PK11_Authenticate(slot, PR_TRUE, pwdata) != SECSuccess)
 
514
        return NULL;
 
515
 
 
516
    /*
 
517
     * Do some random-number initialization.
 
518
     */
 
519
 
 
520
    if (noise) {
 
521
        SECStatus rv = CERTUTIL_FileForRNG(noise);
 
522
        if (rv != SECSuccess) {
 
523
            PORT_SetError(PR_END_OF_FILE_ERROR); /* XXX */
 
524
            return NULL;
 
525
        }
 
526
    } else {
 
527
        int rv = UpdateRNG();
 
528
        if (rv) {
 
529
            PORT_SetError(PR_END_OF_FILE_ERROR);
 
530
            return NULL;
 
531
        }
 
532
    }
 
533
 
 
534
    switch (keytype) {
 
535
    case rsaKey:
 
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;
 
540
        params = &rsaparams;
 
541
        break;
 
542
    case dsaKey:
 
543
        mechanism = CKM_DSA_KEY_PAIR_GEN;
 
544
        algtag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
 
545
        if (pqgFile) {
 
546
            dsaparams = getpqgfromfile(size, pqgFile);
 
547
            if (dsaparams == NULL)
 
548
                return NULL;
 
549
            params = dsaparams;
 
550
        } else {
 
551
            /* cast away const, and don't set dsaparams */
 
552
            params = (void *)&default_pqg_params;
 
553
        }
 
554
        break;
 
555
#ifdef NSS_ENABLE_ECC
 
556
    case ecKey:
 
557
        mechanism = CKM_EC_KEY_PAIR_GEN;
 
558
        /* For EC keys, PQGFile determines EC parameters */
 
559
        if ((params = (void *) getECParams(pqgFile)) == NULL)
 
560
            return NULL;
 
561
        break;
 
562
#endif /* NSS_ENABLE_ECC */
 
563
    default:
 
564
        return NULL;
 
565
    }
 
566
 
 
567
    fprintf(stderr, "\n\n");
 
568
    fprintf(stderr, "Generating key.  This may take a few moments...\n\n");
 
569
 
 
570
    privKey = PK11_GenerateKeyPair(slot, mechanism, params, pubkeyp,
 
571
                                PR_TRUE /*isPerm*/, PR_TRUE /*isSensitive*/, 
 
572
                                pwdata /*wincx*/);
 
573
    /* free up the params */
 
574
    switch (keytype) {
 
575
    case rsaKey: /* nothing to free */                        break;
 
576
    case dsaKey: if (dsaparams) CERTUTIL_DestroyParamsPQG(dsaparams); 
 
577
                                                              break;
 
578
#ifdef NSS_ENABLE_ECC
 
579
    case ecKey: SECITEM_FreeItem((SECItem *)params, PR_TRUE); break;
 
580
#endif
 
581
    }
 
582
    return privKey;
 
583
}