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 +}