security/nss/cmd/certutil/keystuff.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/cmd/certutil/keystuff.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,576 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#include <stdio.h>
     1.9 +#include <string.h>
    1.10 +#include "secutil.h"
    1.11 +
    1.12 +#if defined(XP_UNIX)
    1.13 +#include <unistd.h>
    1.14 +#include <sys/time.h>
    1.15 +#include <termios.h>
    1.16 +#endif
    1.17 +
    1.18 +#if defined(XP_WIN) || defined (XP_PC)
    1.19 +#include <time.h>
    1.20 +#include <conio.h>
    1.21 +#endif
    1.22 +
    1.23 +#if defined(__sun) && !defined(SVR4)
    1.24 +extern int fclose(FILE*);
    1.25 +extern int fprintf(FILE *, char *, ...);
    1.26 +extern int isatty(int);
    1.27 +extern char *sys_errlist[];
    1.28 +#define strerror(errno) sys_errlist[errno]
    1.29 +#endif
    1.30 +
    1.31 +#include "nspr.h"
    1.32 +#include "prtypes.h"
    1.33 +#include "prtime.h"
    1.34 +#include "prlong.h"
    1.35 +
    1.36 +#include "pk11func.h"
    1.37 +
    1.38 +#define NUM_KEYSTROKES 120
    1.39 +#define RAND_BUF_SIZE 60
    1.40 +
    1.41 +#define ERROR_BREAK rv = SECFailure;break;
    1.42 +
    1.43 +const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = {
    1.44 +    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) },
    1.45 +    { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,prime) },
    1.46 +    { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,subPrime) },
    1.47 +    { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,base) },
    1.48 +    { 0, }
    1.49 +};
    1.50 +
    1.51 +/* returns 0 for success, -1 for failure (EOF encountered) */
    1.52 +static int
    1.53 +UpdateRNG(void)
    1.54 +{
    1.55 +    char           randbuf[RAND_BUF_SIZE];
    1.56 +    int            fd,  count;
    1.57 +    int            c;
    1.58 +    int            rv		= 0;
    1.59 +#ifdef XP_UNIX
    1.60 +    cc_t           orig_cc_min;
    1.61 +    cc_t           orig_cc_time;
    1.62 +    tcflag_t       orig_lflag;
    1.63 +    struct termios tio;
    1.64 +#endif
    1.65 +    char meter[] = { 
    1.66 +      "\r|                                                            |" };
    1.67 +
    1.68 +#define FPS fprintf(stderr, 
    1.69 +    FPS "\n");
    1.70 +    FPS "A random seed must be generated that will be used in the\n");
    1.71 +    FPS "creation of your key.  One of the easiest ways to create a\n");
    1.72 +    FPS "random seed is to use the timing of keystrokes on a keyboard.\n");
    1.73 +    FPS "\n");
    1.74 +    FPS "To begin, type keys on the keyboard until this progress meter\n");
    1.75 +    FPS "is full.  DO NOT USE THE AUTOREPEAT FUNCTION ON YOUR KEYBOARD!\n");
    1.76 +    FPS "\n");
    1.77 +    FPS "\n");
    1.78 +    FPS "Continue typing until the progress meter is full:\n\n");
    1.79 +    FPS "%s", meter);
    1.80 +    FPS "\r|");
    1.81 +
    1.82 +    /* turn off echo on stdin & return on 1 char instead of NL */
    1.83 +    fd = fileno(stdin);
    1.84 +
    1.85 +#if defined(XP_UNIX)
    1.86 +    tcgetattr(fd, &tio);
    1.87 +    orig_lflag = tio.c_lflag;
    1.88 +    orig_cc_min = tio.c_cc[VMIN];
    1.89 +    orig_cc_time = tio.c_cc[VTIME];
    1.90 +    tio.c_lflag &= ~ECHO;
    1.91 +    tio.c_lflag &= ~ICANON;
    1.92 +    tio.c_cc[VMIN] = 1;
    1.93 +    tio.c_cc[VTIME] = 0;
    1.94 +    tcsetattr(fd, TCSAFLUSH, &tio);
    1.95 +#endif
    1.96 +
    1.97 +    /* Get random noise from keyboard strokes */
    1.98 +    count = 0;
    1.99 +    while (count < sizeof randbuf) {
   1.100 +#if defined(XP_UNIX)
   1.101 +	c = getc(stdin);
   1.102 +#else
   1.103 +	c = getch();
   1.104 +#endif
   1.105 +	if (c == EOF) {
   1.106 +	    rv = -1;
   1.107 +	    break;
   1.108 +	}
   1.109 +	randbuf[count] = c;
   1.110 +	if (count == 0 || c != randbuf[count-1]) {
   1.111 +	    count++;
   1.112 +	    FPS "*");
   1.113 +	}
   1.114 +    }
   1.115 +    PK11_RandomUpdate(randbuf, sizeof randbuf);
   1.116 +    memset(randbuf, 0, sizeof randbuf);
   1.117 +
   1.118 +    FPS "\n\n");
   1.119 +    FPS "Finished.  Press enter to continue: ");
   1.120 +    while ((c = getc(stdin)) != '\n' && c != EOF)
   1.121 +	;
   1.122 +    if (c == EOF) 
   1.123 +	rv = -1;
   1.124 +    FPS "\n");
   1.125 +
   1.126 +#undef FPS
   1.127 +
   1.128 +#if defined(XP_UNIX)
   1.129 +    /* set back termio the way it was */
   1.130 +    tio.c_lflag = orig_lflag;
   1.131 +    tio.c_cc[VMIN] = orig_cc_min;
   1.132 +    tio.c_cc[VTIME] = orig_cc_time;
   1.133 +    tcsetattr(fd, TCSAFLUSH, &tio);
   1.134 +#endif
   1.135 +    return rv;
   1.136 +}
   1.137 +
   1.138 +static const unsigned char P[] = { 0, 
   1.139 +       0x98, 0xef, 0x3a, 0xae, 0x70, 0x98, 0x9b, 0x44, 
   1.140 +       0xdb, 0x35, 0x86, 0xc1, 0xb6, 0xc2, 0x47, 0x7c, 
   1.141 +       0xb4, 0xff, 0x99, 0xe8, 0xae, 0x44, 0xf2, 0xeb, 
   1.142 +       0xc3, 0xbe, 0x23, 0x0f, 0x65, 0xd0, 0x4c, 0x04, 
   1.143 +       0x82, 0x90, 0xa7, 0x9d, 0x4a, 0xc8, 0x93, 0x7f, 
   1.144 +       0x41, 0xdf, 0xf8, 0x80, 0x6b, 0x0b, 0x68, 0x7f, 
   1.145 +       0xaf, 0xe4, 0xa8, 0xb5, 0xb2, 0x99, 0xc3, 0x69, 
   1.146 +       0xfb, 0x3f, 0xe7, 0x1b, 0xd0, 0x0f, 0xa9, 0x7a, 
   1.147 +       0x4a, 0x04, 0xbf, 0x50, 0x9e, 0x22, 0x33, 0xb8, 
   1.148 +       0x89, 0x53, 0x24, 0x10, 0xf9, 0x68, 0x77, 0xad, 
   1.149 +       0xaf, 0x10, 0x68, 0xb8, 0xd3, 0x68, 0x5d, 0xa3, 
   1.150 +       0xc3, 0xeb, 0x72, 0x3b, 0xa0, 0x0b, 0x73, 0x65, 
   1.151 +       0xc5, 0xd1, 0xfa, 0x8c, 0xc0, 0x7d, 0xaa, 0x52, 
   1.152 +       0x29, 0x34, 0x44, 0x01, 0xbf, 0x12, 0x25, 0xfe, 
   1.153 +       0x18, 0x0a, 0xc8, 0x3f, 0xc1, 0x60, 0x48, 0xdb, 
   1.154 +       0xad, 0x93, 0xb6, 0x61, 0x67, 0xd7, 0xa8, 0x2d };
   1.155 +static const unsigned char Q[] = { 0,
   1.156 +       0xb5, 0xb0, 0x84, 0x8b, 0x44, 0x29, 0xf6, 0x33, 
   1.157 +       0x59, 0xa1, 0x3c, 0xbe, 0xd2, 0x7f, 0x35, 0xa1, 
   1.158 +       0x76, 0x27, 0x03, 0x81                         };
   1.159 +static const unsigned char G[] = { 
   1.160 +       0x04, 0x0e, 0x83, 0x69, 0xf1, 0xcd, 0x7d, 0xe5, 
   1.161 +       0x0c, 0x78, 0x93, 0xd6, 0x49, 0x6f, 0x00, 0x04, 
   1.162 +       0x4e, 0x0e, 0x6c, 0x37, 0xaa, 0x38, 0x22, 0x47, 
   1.163 +       0xd2, 0x58, 0xec, 0x83, 0x12, 0x95, 0xf9, 0x9c, 
   1.164 +       0xf1, 0xf4, 0x27, 0xff, 0xd7, 0x99, 0x57, 0x35, 
   1.165 +       0xc6, 0x64, 0x4c, 0xc0, 0x47, 0x12, 0x31, 0x50, 
   1.166 +       0x82, 0x3c, 0x2a, 0x07, 0x03, 0x01, 0xef, 0x30, 
   1.167 +       0x09, 0x89, 0x82, 0x41, 0x76, 0x71, 0xda, 0x9e, 
   1.168 +       0x57, 0x8b, 0x76, 0x38, 0x37, 0x5f, 0xa5, 0xcd, 
   1.169 +       0x32, 0x84, 0x45, 0x8d, 0x4c, 0x17, 0x54, 0x2b, 
   1.170 +       0x5d, 0xc2, 0x6b, 0xba, 0x3e, 0xa0, 0x7b, 0x95, 
   1.171 +       0xd7, 0x00, 0x42, 0xf7, 0x08, 0xb8, 0x83, 0x87, 
   1.172 +       0x60, 0xe1, 0xe5, 0xf4, 0x1a, 0x54, 0xc2, 0x20, 
   1.173 +       0xda, 0x38, 0x3a, 0xd1, 0xb6, 0x10, 0xf4, 0xcb, 
   1.174 +       0x35, 0xda, 0x97, 0x92, 0x87, 0xd6, 0xa5, 0x37, 
   1.175 +       0x62, 0xb4, 0x93, 0x4a, 0x15, 0x21, 0xa5, 0x10 };
   1.176 +
   1.177 +/*  h:
   1.178 + *      4a:76:30:89:eb:e1:81:7c:99:0b:39:7f:95:4a:65:72:
   1.179 + *      c6:b4:05:92:48:6c:3c:b2:7e:e7:39:f3:92:7d:c1:3f:
   1.180 + *      bf:e1:fd:b3:4a:46:3e:ce:29:80:e3:d6:f4:59:c6:92:
   1.181 + *      16:2b:0e:d7:d6:bb:ef:94:36:31:c2:66:46:c5:4a:77:
   1.182 + *      aa:95:84:ef:99:7e:e3:9c:d9:a0:32:42:09:b6:4e:d0:
   1.183 + *      b3:c8:5e:06:df:a1:ac:4d:2d:f9:08:c2:cb:4b:a4:42:
   1.184 + *      db:8a:5b:de:25:6e:2b:5b:ca:00:75:2c:57:00:18:aa:
   1.185 + *      68:59:a1:94:03:07:94:78:38:bc:f8:7c:1e:1c:a3:2e
   1.186 + *  SEED:
   1.187 + *      b5:44:66:c9:0f:f1:ca:1c:95:45:ce:90:74:89:14:f2:
   1.188 + *      13:3e:23:5a:b0:6a:bf:86:ad:cb:a0:7d:ce:3b:c8:16:
   1.189 + *      7f:2d:a2:1a:cb:33:7d:c1:e7:d7:07:aa:1b:a2:d7:89:
   1.190 + *      f5:a4:db:f7:8b:50:00:cd:b4:7d:25:81:3f:f8:a8:dd:
   1.191 + *      6c:46:e5:77:b5:60:7e:75:79:b8:99:57:c1:c4:f3:f7:
   1.192 + *      17:ca:43:00:b8:33:b6:06:8f:4d:91:ed:23:a5:66:1b:
   1.193 + *      ef:14:d7:bc:21:2b:82:d8:ab:fa:fd:a7:c3:4d:bf:52:
   1.194 + *      af:8e:57:59:61:1a:4e:65:c6:90:d6:a6:ff:0b:15:b1
   1.195 + *  g:       1024
   1.196 + *  counter: 1003
   1.197 + */
   1.198 +
   1.199 +static const SECKEYPQGParams default_pqg_params = {
   1.200 +    NULL,
   1.201 +    { 0, (unsigned char *)P, sizeof(P) },
   1.202 +    { 0, (unsigned char *)Q, sizeof(Q) },
   1.203 +    { 0, (unsigned char *)G, sizeof(G) }
   1.204 +};
   1.205 +
   1.206 +static SECKEYPQGParams *
   1.207 +decode_pqg_params(const char *str)
   1.208 +{
   1.209 +    char *buf;
   1.210 +    unsigned int len;
   1.211 +    PLArenaPool *arena;
   1.212 +    SECKEYPQGParams *params;
   1.213 +    SECStatus status;
   1.214 + 
   1.215 +    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   1.216 +    if (arena == NULL)
   1.217 +        return NULL;
   1.218 + 
   1.219 +    params = PORT_ArenaZAlloc(arena, sizeof(SECKEYPQGParams));
   1.220 +    if (params == NULL)
   1.221 +        goto loser;
   1.222 +    params->arena = arena;
   1.223 + 
   1.224 +    buf = (char *)ATOB_AsciiToData(str, &len);
   1.225 +    if ((buf == NULL) || (len == 0))
   1.226 +        goto loser;
   1.227 + 
   1.228 +    status = SEC_ASN1Decode(arena, params, SECKEY_PQGParamsTemplate, buf, len);
   1.229 +    if (status != SECSuccess)
   1.230 +        goto loser;
   1.231 + 
   1.232 +    return params;
   1.233 + 
   1.234 +loser:
   1.235 +    if (arena != NULL)
   1.236 +        PORT_FreeArena(arena, PR_FALSE);
   1.237 +    return NULL;
   1.238 +}
   1.239 +
   1.240 +void  
   1.241 +CERTUTIL_DestroyParamsPQG(SECKEYPQGParams *params)
   1.242 +{
   1.243 +    if (params->arena) {
   1.244 +        PORT_FreeArena(params->arena, PR_FALSE);
   1.245 +    }
   1.246 +}
   1.247 +
   1.248 +static int
   1.249 +pqg_prime_bits(const SECKEYPQGParams *params)
   1.250 +{
   1.251 +    int primeBits = 0;
   1.252 + 
   1.253 +    if (params != NULL) {
   1.254 +	int i;
   1.255 +	for (i = 0; params->prime.data[i] == 0; i++) {
   1.256 +	    /* empty */;
   1.257 +	}
   1.258 +	primeBits = (params->prime.len - i) * 8;
   1.259 +    }
   1.260 + 
   1.261 +    return primeBits;
   1.262 +}
   1.263 +
   1.264 +static char *
   1.265 +getPQGString(const char *filename)
   1.266 +{
   1.267 +    unsigned char *buf      = NULL;
   1.268 +    PRFileDesc    *src;
   1.269 +    PRInt32        numBytes;
   1.270 +    PRStatus       prStatus;
   1.271 +    PRFileInfo     info;
   1.272 +
   1.273 +    src   = PR_Open(filename, PR_RDONLY, 0);
   1.274 +    if (!src) {
   1.275 +    	fprintf(stderr, "Failed to open PQG file %s\n", filename);
   1.276 +	return NULL;
   1.277 +    }
   1.278 +
   1.279 +    prStatus = PR_GetOpenFileInfo(src, &info);
   1.280 +
   1.281 +    if (prStatus == PR_SUCCESS) {
   1.282 +	buf = (unsigned char*)PORT_Alloc(info.size + 1);
   1.283 +    }
   1.284 +    if (!buf) {
   1.285 +	PR_Close(src);
   1.286 +    	fprintf(stderr, "Failed to read PQG file %s\n", filename);
   1.287 +	return NULL;
   1.288 +    }
   1.289 +
   1.290 +    numBytes = PR_Read(src, buf, info.size);
   1.291 +    PR_Close(src);
   1.292 +    if (numBytes != info.size) {
   1.293 +	PORT_Free(buf);
   1.294 +    	fprintf(stderr, "Failed to read PQG file %s\n", filename);
   1.295 +	PORT_SetError(SEC_ERROR_IO);
   1.296 +	return NULL;
   1.297 +    }
   1.298 +
   1.299 +    if (buf[numBytes-1] == '\n') 
   1.300 +    	numBytes--;
   1.301 +    if (buf[numBytes-1] == '\r') 
   1.302 +    	numBytes--;
   1.303 +    buf[numBytes] = 0;
   1.304 +    
   1.305 +    return (char *)buf;
   1.306 +}
   1.307 +
   1.308 +static SECKEYPQGParams*
   1.309 +getpqgfromfile(int keyBits, const char *pqgFile)
   1.310 +{
   1.311 +    char *end, *str, *pqgString;
   1.312 +    SECKEYPQGParams* params = NULL;
   1.313 +
   1.314 +    str = pqgString = getPQGString(pqgFile);
   1.315 +    if (!str) 
   1.316 +	return NULL;
   1.317 +
   1.318 +    do {
   1.319 +	end = PORT_Strchr(str, ',');
   1.320 +	if (end)
   1.321 +	    *end = '\0';
   1.322 +	params = decode_pqg_params(str);
   1.323 +	if (params) {
   1.324 +	    int primeBits = pqg_prime_bits(params);
   1.325 +	    if (keyBits == primeBits)
   1.326 +		break;
   1.327 +	    CERTUTIL_DestroyParamsPQG(params);
   1.328 +	    params = NULL;
   1.329 +	}
   1.330 +	if (end)
   1.331 +	    str = end + 1;
   1.332 +    } while (end);
   1.333 +
   1.334 +    PORT_Free(pqgString);
   1.335 +    return params;
   1.336 +}
   1.337 +
   1.338 +static SECStatus 
   1.339 +CERTUTIL_FileForRNG(const char *noise)
   1.340 +{
   1.341 +    char buf[2048];
   1.342 +    PRFileDesc *fd;
   1.343 +    PRInt32 count;
   1.344 +
   1.345 +    fd = PR_Open(noise,PR_RDONLY,0);
   1.346 +    if (!fd) {
   1.347 +	fprintf(stderr, "failed to open noise file.");
   1.348 +	return SECFailure;
   1.349 +    }
   1.350 +
   1.351 +    do {
   1.352 +	count = PR_Read(fd,buf,sizeof(buf));
   1.353 +	if (count > 0) {
   1.354 +	    PK11_RandomUpdate(buf,count);
   1.355 +	}
   1.356 +    } while (count > 0);
   1.357 +
   1.358 +    PR_Close(fd);
   1.359 +    return SECSuccess;
   1.360 +}
   1.361 +
   1.362 +#ifndef NSS_DISABLE_ECC
   1.363 +typedef struct curveNameTagPairStr {
   1.364 +    char *curveName;
   1.365 +    SECOidTag curveOidTag;
   1.366 +} CurveNameTagPair;
   1.367 +
   1.368 +#define DEFAULT_CURVE_OID_TAG  SEC_OID_SECG_EC_SECP192R1
   1.369 +/* #define DEFAULT_CURVE_OID_TAG  SEC_OID_SECG_EC_SECP160R1 */
   1.370 +
   1.371 +static CurveNameTagPair nameTagPair[] =
   1.372 +{ 
   1.373 +  { "sect163k1", SEC_OID_SECG_EC_SECT163K1},
   1.374 +  { "nistk163", SEC_OID_SECG_EC_SECT163K1},
   1.375 +  { "sect163r1", SEC_OID_SECG_EC_SECT163R1},
   1.376 +  { "sect163r2", SEC_OID_SECG_EC_SECT163R2},
   1.377 +  { "nistb163", SEC_OID_SECG_EC_SECT163R2},
   1.378 +  { "sect193r1", SEC_OID_SECG_EC_SECT193R1},
   1.379 +  { "sect193r2", SEC_OID_SECG_EC_SECT193R2},
   1.380 +  { "sect233k1", SEC_OID_SECG_EC_SECT233K1},
   1.381 +  { "nistk233", SEC_OID_SECG_EC_SECT233K1},
   1.382 +  { "sect233r1", SEC_OID_SECG_EC_SECT233R1},
   1.383 +  { "nistb233", SEC_OID_SECG_EC_SECT233R1},
   1.384 +  { "sect239k1", SEC_OID_SECG_EC_SECT239K1},
   1.385 +  { "sect283k1", SEC_OID_SECG_EC_SECT283K1},
   1.386 +  { "nistk283", SEC_OID_SECG_EC_SECT283K1},
   1.387 +  { "sect283r1", SEC_OID_SECG_EC_SECT283R1},
   1.388 +  { "nistb283", SEC_OID_SECG_EC_SECT283R1},
   1.389 +  { "sect409k1", SEC_OID_SECG_EC_SECT409K1},
   1.390 +  { "nistk409", SEC_OID_SECG_EC_SECT409K1},
   1.391 +  { "sect409r1", SEC_OID_SECG_EC_SECT409R1},
   1.392 +  { "nistb409", SEC_OID_SECG_EC_SECT409R1},
   1.393 +  { "sect571k1", SEC_OID_SECG_EC_SECT571K1},
   1.394 +  { "nistk571", SEC_OID_SECG_EC_SECT571K1},
   1.395 +  { "sect571r1", SEC_OID_SECG_EC_SECT571R1},
   1.396 +  { "nistb571", SEC_OID_SECG_EC_SECT571R1},
   1.397 +  { "secp160k1", SEC_OID_SECG_EC_SECP160K1},
   1.398 +  { "secp160r1", SEC_OID_SECG_EC_SECP160R1},
   1.399 +  { "secp160r2", SEC_OID_SECG_EC_SECP160R2},
   1.400 +  { "secp192k1", SEC_OID_SECG_EC_SECP192K1},
   1.401 +  { "secp192r1", SEC_OID_SECG_EC_SECP192R1},
   1.402 +  { "nistp192", SEC_OID_SECG_EC_SECP192R1},
   1.403 +  { "secp224k1", SEC_OID_SECG_EC_SECP224K1},
   1.404 +  { "secp224r1", SEC_OID_SECG_EC_SECP224R1},
   1.405 +  { "nistp224", SEC_OID_SECG_EC_SECP224R1},
   1.406 +  { "secp256k1", SEC_OID_SECG_EC_SECP256K1},
   1.407 +  { "secp256r1", SEC_OID_SECG_EC_SECP256R1},
   1.408 +  { "nistp256", SEC_OID_SECG_EC_SECP256R1},
   1.409 +  { "secp384r1", SEC_OID_SECG_EC_SECP384R1},
   1.410 +  { "nistp384", SEC_OID_SECG_EC_SECP384R1},
   1.411 +  { "secp521r1", SEC_OID_SECG_EC_SECP521R1},
   1.412 +  { "nistp521", SEC_OID_SECG_EC_SECP521R1},
   1.413 +
   1.414 +  { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 },
   1.415 +  { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 },
   1.416 +  { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 },
   1.417 +  { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 },
   1.418 +  { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 },
   1.419 +  { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 },
   1.420 +
   1.421 +  { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 },
   1.422 +  { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 },
   1.423 +  { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 },
   1.424 +  { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 },
   1.425 +  { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 },
   1.426 +  { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 },
   1.427 +  { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 },
   1.428 +  { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 },
   1.429 +  { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 },
   1.430 +  { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 },
   1.431 +  { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 },
   1.432 +  { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 },
   1.433 +  { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 },
   1.434 +  { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 },
   1.435 +  { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 },
   1.436 +  { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 },
   1.437 +  { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 },
   1.438 +  { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 },
   1.439 +  { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 },
   1.440 +  { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 },
   1.441 +
   1.442 +  { "secp112r1", SEC_OID_SECG_EC_SECP112R1},
   1.443 +  { "secp112r2", SEC_OID_SECG_EC_SECP112R2},
   1.444 +  { "secp128r1", SEC_OID_SECG_EC_SECP128R1},
   1.445 +  { "secp128r2", SEC_OID_SECG_EC_SECP128R2},
   1.446 +
   1.447 +  { "sect113r1", SEC_OID_SECG_EC_SECT113R1},
   1.448 +  { "sect113r2", SEC_OID_SECG_EC_SECT113R2},
   1.449 +  { "sect131r1", SEC_OID_SECG_EC_SECT131R1},
   1.450 +  { "sect131r2", SEC_OID_SECG_EC_SECT131R2},
   1.451 +};
   1.452 +
   1.453 +static SECKEYECParams * 
   1.454 +getECParams(const char *curve)
   1.455 +{
   1.456 +    SECKEYECParams *ecparams;
   1.457 +    SECOidData *oidData = NULL;
   1.458 +    SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */
   1.459 +    int i, numCurves;
   1.460 +
   1.461 +    if (curve != NULL) {
   1.462 +        numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair);
   1.463 +	for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); 
   1.464 +	     i++) {
   1.465 +	    if (PL_strcmp(curve, nameTagPair[i].curveName) == 0)
   1.466 +	        curveOidTag = nameTagPair[i].curveOidTag;
   1.467 +	}
   1.468 +    }
   1.469 +
   1.470 +    /* Return NULL if curve name is not recognized */
   1.471 +    if ((curveOidTag == SEC_OID_UNKNOWN) || 
   1.472 +	(oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) {
   1.473 +        fprintf(stderr, "Unrecognized elliptic curve %s\n", curve);
   1.474 +	return NULL;
   1.475 +    }
   1.476 +
   1.477 +    ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len));
   1.478 +
   1.479 +    /* 
   1.480 +     * ecparams->data needs to contain the ASN encoding of an object ID (OID)
   1.481 +     * representing the named curve. The actual OID is in 
   1.482 +     * oidData->oid.data so we simply prepend 0x06 and OID length
   1.483 +     */
   1.484 +    ecparams->data[0] = SEC_ASN1_OBJECT_ID;
   1.485 +    ecparams->data[1] = oidData->oid.len;
   1.486 +    memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len);
   1.487 +
   1.488 +    return ecparams;
   1.489 +}
   1.490 +#endif /* NSS_DISABLE_ECC */
   1.491 +
   1.492 +SECKEYPrivateKey *
   1.493 +CERTUTIL_GeneratePrivateKey(KeyType keytype, PK11SlotInfo *slot, int size,
   1.494 +			    int publicExponent, const char *noise, 
   1.495 +			    SECKEYPublicKey **pubkeyp, const char *pqgFile,
   1.496 +			    PK11AttrFlags attrFlags, CK_FLAGS opFlagsOn,
   1.497 +			    CK_FLAGS opFlagsOff, secuPWData *pwdata)
   1.498 +{
   1.499 +    CK_MECHANISM_TYPE  mechanism;
   1.500 +    SECOidTag          algtag;
   1.501 +    PK11RSAGenParams   rsaparams;
   1.502 +    SECKEYPQGParams  * dsaparams = NULL;
   1.503 +    void             * params;
   1.504 +    SECKEYPrivateKey * privKey = NULL;
   1.505 +
   1.506 +    if (slot == NULL)
   1.507 +	return NULL;
   1.508 +
   1.509 +    if (PK11_Authenticate(slot, PR_TRUE, pwdata) != SECSuccess)
   1.510 +	return NULL;
   1.511 +
   1.512 +    /*
   1.513 +     * Do some random-number initialization.
   1.514 +     */
   1.515 +
   1.516 +    if (noise) {
   1.517 +    	SECStatus rv = CERTUTIL_FileForRNG(noise);
   1.518 +	if (rv != SECSuccess) {
   1.519 +	    PORT_SetError(PR_END_OF_FILE_ERROR); /* XXX */
   1.520 +	    return NULL;
   1.521 +    	}
   1.522 +    } else {
   1.523 +	int rv = UpdateRNG();
   1.524 +	if (rv) {
   1.525 +	    PORT_SetError(PR_END_OF_FILE_ERROR);
   1.526 +	    return NULL;
   1.527 +	}
   1.528 +    }
   1.529 +
   1.530 +    switch (keytype) {
   1.531 +    case rsaKey:
   1.532 +	rsaparams.keySizeInBits = size;
   1.533 +	rsaparams.pe = publicExponent;
   1.534 +	mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
   1.535 +	algtag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
   1.536 +	params = &rsaparams;
   1.537 +	break;
   1.538 +    case dsaKey:
   1.539 +	mechanism = CKM_DSA_KEY_PAIR_GEN;
   1.540 +	algtag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
   1.541 +	if (pqgFile) {
   1.542 +	    dsaparams = getpqgfromfile(size, pqgFile);
   1.543 +	    if (dsaparams == NULL)
   1.544 +	    	return NULL;
   1.545 +	    params = dsaparams;
   1.546 +	} else {
   1.547 +	    /* cast away const, and don't set dsaparams */
   1.548 +	    params = (void *)&default_pqg_params;
   1.549 +	}
   1.550 +	break;
   1.551 +#ifndef NSS_DISABLE_ECC
   1.552 +    case ecKey:
   1.553 +	mechanism = CKM_EC_KEY_PAIR_GEN;
   1.554 +	/* For EC keys, PQGFile determines EC parameters */
   1.555 +	if ((params = (void *) getECParams(pqgFile)) == NULL)
   1.556 +	    return NULL;
   1.557 +	break;
   1.558 +#endif /* NSS_DISABLE_ECC */
   1.559 +    default:
   1.560 +	return NULL;
   1.561 +    }
   1.562 +
   1.563 +    fprintf(stderr, "\n\n");
   1.564 +    fprintf(stderr, "Generating key.  This may take a few moments...\n\n");
   1.565 +
   1.566 +    privKey = PK11_GenerateKeyPairWithOpFlags(slot, mechanism, params, pubkeyp,
   1.567 +				attrFlags, opFlagsOn, opFlagsOn|opFlagsOff,
   1.568 +				pwdata /*wincx*/);
   1.569 +    /* free up the params */
   1.570 +    switch (keytype) {
   1.571 +    case dsaKey: if (dsaparams) CERTUTIL_DestroyParamsPQG(dsaparams); 
   1.572 +	                                                      break;
   1.573 +#ifndef NSS_DISABLE_ECC
   1.574 +    case ecKey: SECITEM_FreeItem((SECItem *)params, PR_TRUE); break;
   1.575 +#endif
   1.576 +    default: /* nothing to free */                            break;
   1.577 +    }
   1.578 +    return privKey;
   1.579 +}

mercurial