keystuff.c (19918B)
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/. */ 4 5 #include <stdio.h> 6 #include <string.h> 7 #include "secutil.h" 8 9 #if defined(XP_UNIX) 10 #include <unistd.h> 11 #include <sys/time.h> 12 #include <termios.h> 13 #endif 14 15 #if defined(XP_WIN) || defined(XP_PC) 16 #include <time.h> 17 #include <conio.h> 18 #endif 19 20 #include "nspr.h" 21 #include "prtypes.h" 22 #include "prtime.h" 23 #include "prlong.h" 24 25 #include "pk11func.h" 26 27 #define NUM_KEYSTROKES 120 28 #define RAND_BUF_SIZE 60 29 30 #define ERROR_BREAK \ 31 rv = SECFailure; \ 32 break; 33 34 const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = { 35 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) }, 36 { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, prime) }, 37 { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, subPrime) }, 38 { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, base) }, 39 { 0 } 40 }; 41 42 /* returns 0 for success, -1 for failure (EOF encountered) */ 43 static int 44 UpdateRNG(void) 45 { 46 char randbuf[RAND_BUF_SIZE]; 47 #ifdef XP_UNIX 48 int fd; 49 #endif 50 int c; 51 int rv = 0; 52 size_t count; 53 #ifdef XP_UNIX 54 cc_t orig_cc_min; 55 cc_t orig_cc_time; 56 tcflag_t orig_lflag; 57 struct termios tio; 58 #endif 59 char meter[] = { 60 "\r| |" 61 }; 62 63 #define FPS fprintf(stderr, 64 FPS "\n"); 65 FPS "A random seed must be generated that will be used in the\n"); 66 FPS "creation of your key. One of the easiest ways to create a\n"); 67 FPS "random seed is to use the timing of keystrokes on a keyboard.\n"); 68 FPS "\n"); 69 FPS "To begin, type keys on the keyboard until this progress meter\n"); 70 FPS "is full. DO NOT USE THE AUTOREPEAT FUNCTION ON YOUR KEYBOARD!\n"); 71 FPS "\n"); 72 FPS "\n"); 73 FPS "Continue typing until the progress meter is full:\n\n"); 74 FPS "%s", meter); 75 FPS "\r|"); 76 77 #if defined(XP_UNIX) 78 /* turn off echo on stdin & return on 1 char instead of NL */ 79 fd = fileno(stdin); 80 81 tcgetattr(fd, &tio); 82 orig_lflag = tio.c_lflag; 83 orig_cc_min = tio.c_cc[VMIN]; 84 orig_cc_time = tio.c_cc[VTIME]; 85 tio.c_lflag &= ~ECHO; 86 tio.c_lflag &= ~ICANON; 87 tio.c_cc[VMIN] = 1; 88 tio.c_cc[VTIME] = 0; 89 tcsetattr(fd, TCSAFLUSH, &tio); 90 #endif 91 92 /* Get random noise from keyboard strokes */ 93 count = 0; 94 while (count < sizeof randbuf) { 95 #if defined(XP_UNIX) 96 c = getc(stdin); 97 #else 98 c = getch(); 99 #endif 100 if (c == EOF) { 101 rv = -1; 102 break; 103 } 104 randbuf[count] = c; 105 if (count == 0 || c != randbuf[count - 1]) { 106 count++; 107 FPS "*"); 108 } 109 } 110 PK11_RandomUpdate(randbuf, sizeof randbuf); 111 memset(randbuf, 0, sizeof randbuf); 112 113 FPS "\n\n"); 114 FPS "Finished. Press enter to continue: "); 115 while ((c = getc(stdin)) != '\n' && c != EOF) 116 ; 117 if (c == EOF) 118 rv = -1; 119 FPS "\n"); 120 121 #undef FPS 122 123 #if defined(XP_UNIX) 124 /* set back termio the way it was */ 125 tio.c_lflag = orig_lflag; 126 tio.c_cc[VMIN] = orig_cc_min; 127 tio.c_cc[VTIME] = orig_cc_time; 128 tcsetattr(fd, TCSAFLUSH, &tio); 129 #endif 130 return rv; 131 } 132 133 static const unsigned char P[] = { 0, 134 0xc6, 0x2a, 0x47, 0x73, 0xea, 0x78, 0xfa, 0x65, 135 0x47, 0x69, 0x39, 0x10, 0x08, 0x55, 0x6a, 0xdd, 136 0xbf, 0x77, 0xe1, 0x9a, 0x69, 0x73, 0xba, 0x66, 137 0x37, 0x08, 0x93, 0x9e, 0xdb, 0x5d, 0x01, 0x08, 138 0xb8, 0x3a, 0x73, 0xe9, 0x85, 0x5f, 0xa7, 0x2b, 139 0x63, 0x7f, 0xd0, 0xc6, 0x4c, 0xdc, 0xfc, 0x8b, 140 0xa6, 0x03, 0xc9, 0x9c, 0x80, 0x5e, 0xec, 0xc6, 141 0x21, 0x23, 0xf7, 0x8e, 0xa4, 0x7b, 0x77, 0x83, 142 0x02, 0x44, 0xf8, 0x05, 0xd7, 0x36, 0x52, 0x13, 143 0x57, 0x78, 0x97, 0xf3, 0x7b, 0xcf, 0x1f, 0xc9, 144 0x2a, 0xa4, 0x71, 0x9d, 0xa8, 0xd8, 0x5d, 0xc5, 145 0x3b, 0x64, 0x3a, 0x72, 0x60, 0x62, 0xb0, 0xb8, 146 0xf3, 0xb1, 0xe7, 0xb9, 0x76, 0xdf, 0x74, 0xbe, 147 0x87, 0x6a, 0xd2, 0xf1, 0xa9, 0x44, 0x8b, 0x63, 148 0x76, 0x4f, 0x5d, 0x21, 0x63, 0xb5, 0x4f, 0x3c, 149 0x7b, 0x61, 0xb2, 0xf3, 0xea, 0xc5, 0xd8, 0xef, 150 0x30, 0x50, 0x59, 0x33, 0x61, 0xc0, 0xf3, 0x6e, 151 0x21, 0xcf, 0x15, 0x35, 0x4a, 0x87, 0x2b, 0xc3, 152 0xf6, 0x5a, 0x1f, 0x24, 0x22, 0xc5, 0xeb, 0x47, 153 0x34, 0x4a, 0x1b, 0xb5, 0x2e, 0x71, 0x52, 0x8f, 154 0x2d, 0x7d, 0xa9, 0x96, 0x8a, 0x7c, 0x61, 0xdb, 155 0xc0, 0xdc, 0xf1, 0xca, 0x28, 0x69, 0x1c, 0x97, 156 0xad, 0xea, 0x0d, 0x9e, 0x02, 0xe6, 0xe5, 0x7d, 157 0xad, 0xe0, 0x42, 0x91, 0x4d, 0xfa, 0xe2, 0x81, 158 0x16, 0x2b, 0xc2, 0x96, 0x3b, 0x32, 0x8c, 0x20, 159 0x69, 0x8b, 0x5b, 0x17, 0x3c, 0xf9, 0x13, 0x6c, 160 0x98, 0x27, 0x1c, 0xca, 0xcf, 0x33, 0xaa, 0x93, 161 0x21, 0xaf, 0x17, 0x6e, 0x5e, 0x00, 0x37, 0xd9, 162 0x34, 0x8a, 0x47, 0xd2, 0x1c, 0x67, 0x32, 0x60, 163 0xb6, 0xc7, 0xb0, 0xfd, 0x32, 0x90, 0x93, 0x32, 164 0xaa, 0x11, 0xba, 0x23, 0x19, 0x39, 0x6a, 0x42, 165 0x7c, 0x1f, 0xb7, 0x28, 0xdb, 0x64, 0xad, 0xd9 }; 166 static const unsigned char Q[] = { 0, 167 0xe6, 0xa3, 0xc9, 0xc6, 0x51, 0x92, 0x8b, 0xb3, 168 0x98, 0x8f, 0x97, 0xb8, 0x31, 0x0d, 0x4a, 0x03, 169 0x1e, 0xba, 0x4e, 0xe6, 0xc8, 0x90, 0x98, 0x1d, 170 0x3a, 0x95, 0xf4, 0xf1 }; 171 static const unsigned char G[] = { 172 0x70, 0x32, 0x58, 0x5d, 0xb3, 0xbf, 0xc3, 0x62, 173 0x63, 0x0b, 0xf8, 0xa5, 0xe1, 0xed, 0xeb, 0x79, 174 0xac, 0x18, 0x41, 0x64, 0xb3, 0xda, 0x4c, 0xa7, 175 0x92, 0x63, 0xb1, 0x33, 0x7c, 0xcb, 0x43, 0xdc, 176 0x1f, 0x38, 0x63, 0x5e, 0x0e, 0x6d, 0x45, 0xd1, 177 0xc9, 0x67, 0xf3, 0xcf, 0x3d, 0x2d, 0x16, 0x4e, 178 0x92, 0x16, 0x06, 0x59, 0x29, 0x89, 0x6f, 0x54, 179 0xff, 0xc5, 0x71, 0xc8, 0x3a, 0x95, 0x84, 0xb6, 180 0x7e, 0x7b, 0x1e, 0x8b, 0x47, 0x9d, 0x7a, 0x3a, 181 0x36, 0x9b, 0x70, 0x2f, 0xd1, 0xbd, 0xef, 0xe8, 182 0x3a, 0x41, 0xd4, 0xf3, 0x1f, 0x81, 0xc7, 0x1f, 183 0x96, 0x7c, 0x30, 0xab, 0xf4, 0x7a, 0xac, 0x93, 184 0xed, 0x6f, 0x67, 0xb0, 0xc9, 0x5b, 0xf3, 0x83, 185 0x9d, 0xa0, 0xd7, 0xb9, 0x01, 0xed, 0x28, 0xae, 186 0x1c, 0x6e, 0x2e, 0x48, 0xac, 0x9f, 0x7d, 0xf3, 187 0x00, 0x48, 0xee, 0x0e, 0xfb, 0x7e, 0x5e, 0xcb, 188 0xf5, 0x39, 0xd8, 0x92, 0x90, 0x61, 0x2d, 0x1e, 189 0x3c, 0xd3, 0x55, 0x0d, 0x34, 0xd1, 0x81, 0xc4, 190 0x89, 0xea, 0x94, 0x2b, 0x56, 0x33, 0x73, 0x58, 191 0x48, 0xbf, 0x23, 0x72, 0x19, 0x5f, 0x19, 0xac, 192 0xff, 0x09, 0xc8, 0xcd, 0xab, 0x71, 0xef, 0x9e, 193 0x20, 0xfd, 0xe3, 0xb8, 0x27, 0x9e, 0x65, 0xb1, 194 0x85, 0xcd, 0x88, 0xfe, 0xd4, 0xd7, 0x64, 0x4d, 195 0xe1, 0xe8, 0xa6, 0xe5, 0x96, 0xc8, 0x5d, 0x9c, 196 0xc6, 0x70, 0x6b, 0xba, 0x77, 0x4e, 0x90, 0x4a, 197 0xb0, 0x96, 0xc5, 0xa0, 0x9e, 0x2c, 0x01, 0x03, 198 0xbe, 0xbd, 0x71, 0xba, 0x0a, 0x6f, 0x9f, 0xe5, 199 0xdb, 0x04, 0x08, 0xf2, 0x9e, 0x0f, 0x1b, 0xac, 200 0xcd, 0xbb, 0x65, 0x12, 0xcf, 0x77, 0xc9, 0x7d, 201 0xbe, 0x94, 0x4b, 0x9c, 0x5b, 0xde, 0x0d, 0xfa, 202 0x57, 0xdd, 0x77, 0x32, 0xf0, 0x5b, 0x34, 0xfd, 203 0x19, 0x95, 0x33, 0x60, 0x87, 0xe2, 0xa2, 0xf4 204 }; 205 206 /* P, Q, G have been generated using the NSS makepqg utility: 207 * makepqg -l 2048 -g 224 -r 208 * (see also: bug 1170322) 209 * 210 * h: 1 (0x1) 211 * SEED: 212 * d2:0b:c5:63:1b:af:dc:36:b7:7c:b9:3e:36:01:a0:8f: 213 * 0e:be:d0:38:e4:78:d5:3c:7c:9e:a9:9a:d2:0b:c5:63: 214 * 1b:af:dc:36:b7:7c:b9:3e:36:01:a0:8f:0e:be:d0:38: 215 * e4:78:d5:3c:7c:9e:c7:70:d2:0b:c5:63:1b:af:dc:36: 216 * b7:7c:b9:3e:36:01:a0:8f:0e:be:d0:38:e4:78:d5:3c: 217 * 7c:9e:aa:3e 218 * g: 672 219 * counter: 0 220 */ 221 222 static const SECKEYPQGParams default_pqg_params = { 223 NULL, 224 { 0, (unsigned char *)P, sizeof(P) }, 225 { 0, (unsigned char *)Q, sizeof(Q) }, 226 { 0, (unsigned char *)G, sizeof(G) } 227 }; 228 229 static SECKEYPQGParams * 230 decode_pqg_params(const char *str) 231 { 232 char *buf; 233 unsigned int len; 234 PLArenaPool *arena; 235 SECKEYPQGParams *params; 236 SECStatus status; 237 238 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 239 if (arena == NULL) 240 return NULL; 241 242 params = PORT_ArenaZAlloc(arena, sizeof(SECKEYPQGParams)); 243 if (params == NULL) 244 goto loser; 245 params->arena = arena; 246 247 buf = (char *)ATOB_AsciiToData(str, &len); 248 if ((buf == NULL) || (len == 0)) 249 goto loser; 250 251 status = SEC_ASN1Decode(arena, params, SECKEY_PQGParamsTemplate, buf, len); 252 if (status != SECSuccess) 253 goto loser; 254 255 return params; 256 257 loser: 258 if (arena != NULL) 259 PORT_FreeArena(arena, PR_FALSE); 260 return NULL; 261 } 262 263 void 264 CERTUTIL_DestroyParamsPQG(SECKEYPQGParams *params) 265 { 266 if (params->arena) { 267 PORT_FreeArena(params->arena, PR_FALSE); 268 } 269 } 270 271 static int 272 pqg_prime_bits(const SECKEYPQGParams *params) 273 { 274 int primeBits = 0; 275 276 if (params != NULL) { 277 int i; 278 for (i = 0; params->prime.data[i] == 0; i++) { 279 /* empty */; 280 } 281 primeBits = (params->prime.len - i) * 8; 282 } 283 284 return primeBits; 285 } 286 287 static char * 288 getPQGString(const char *filename) 289 { 290 unsigned char *buf = NULL; 291 PRFileDesc *src; 292 PRInt32 numBytes; 293 PRStatus prStatus; 294 PRFileInfo info; 295 296 src = PR_Open(filename, PR_RDONLY, 0); 297 if (!src) { 298 fprintf(stderr, "Failed to open PQG file %s\n", filename); 299 return NULL; 300 } 301 302 prStatus = PR_GetOpenFileInfo(src, &info); 303 304 if (prStatus == PR_SUCCESS) { 305 buf = (unsigned char *)PORT_Alloc(info.size + 1); 306 } 307 if (!buf) { 308 PR_Close(src); 309 fprintf(stderr, "Failed to read PQG file %s\n", filename); 310 return NULL; 311 } 312 313 numBytes = PR_Read(src, buf, info.size); 314 PR_Close(src); 315 if (numBytes != info.size) { 316 PORT_Free(buf); 317 fprintf(stderr, "Failed to read PQG file %s\n", filename); 318 PORT_SetError(SEC_ERROR_IO); 319 return NULL; 320 } 321 322 if (buf[numBytes - 1] == '\n') 323 numBytes--; 324 if (buf[numBytes - 1] == '\r') 325 numBytes--; 326 buf[numBytes] = 0; 327 328 return (char *)buf; 329 } 330 331 static SECKEYPQGParams * 332 getpqgfromfile(int keyBits, const char *pqgFile) 333 { 334 char *end, *str, *pqgString; 335 SECKEYPQGParams *params = NULL; 336 337 str = pqgString = getPQGString(pqgFile); 338 if (!str) 339 return NULL; 340 341 do { 342 end = PORT_Strchr(str, ','); 343 if (end) 344 *end = '\0'; 345 params = decode_pqg_params(str); 346 if (params) { 347 int primeBits = pqg_prime_bits(params); 348 if (keyBits == primeBits) 349 break; 350 CERTUTIL_DestroyParamsPQG(params); 351 params = NULL; 352 } 353 if (end) 354 str = end + 1; 355 } while (end); 356 357 PORT_Free(pqgString); 358 return params; 359 } 360 361 static SECStatus 362 CERTUTIL_FileForRNG(const char *noise) 363 { 364 char buf[2048]; 365 PRFileDesc *fd; 366 PRInt32 count; 367 368 fd = PR_Open(noise, PR_RDONLY, 0); 369 if (!fd) { 370 fprintf(stderr, "failed to open noise file."); 371 return SECFailure; 372 } 373 374 do { 375 count = PR_Read(fd, buf, sizeof(buf)); 376 if (count > 0) { 377 PK11_RandomUpdate(buf, count); 378 } 379 } while (count > 0); 380 381 PR_Close(fd); 382 return SECSuccess; 383 } 384 385 typedef struct curveNameTagPairStr { 386 char *curveName; 387 SECOidTag curveOidTag; 388 } CurveNameTagPair; 389 390 static CurveNameTagPair nameTagPair[] = { 391 { "sect163k1", SEC_OID_SECG_EC_SECT163K1 }, 392 { "nistk163", SEC_OID_SECG_EC_SECT163K1 }, 393 { "sect163r1", SEC_OID_SECG_EC_SECT163R1 }, 394 { "sect163r2", SEC_OID_SECG_EC_SECT163R2 }, 395 { "nistb163", SEC_OID_SECG_EC_SECT163R2 }, 396 { "sect193r1", SEC_OID_SECG_EC_SECT193R1 }, 397 { "sect193r2", SEC_OID_SECG_EC_SECT193R2 }, 398 { "sect233k1", SEC_OID_SECG_EC_SECT233K1 }, 399 { "nistk233", SEC_OID_SECG_EC_SECT233K1 }, 400 { "sect233r1", SEC_OID_SECG_EC_SECT233R1 }, 401 { "nistb233", SEC_OID_SECG_EC_SECT233R1 }, 402 { "sect239k1", SEC_OID_SECG_EC_SECT239K1 }, 403 { "sect283k1", SEC_OID_SECG_EC_SECT283K1 }, 404 { "nistk283", SEC_OID_SECG_EC_SECT283K1 }, 405 { "sect283r1", SEC_OID_SECG_EC_SECT283R1 }, 406 { "nistb283", SEC_OID_SECG_EC_SECT283R1 }, 407 { "sect409k1", SEC_OID_SECG_EC_SECT409K1 }, 408 { "nistk409", SEC_OID_SECG_EC_SECT409K1 }, 409 { "sect409r1", SEC_OID_SECG_EC_SECT409R1 }, 410 { "nistb409", SEC_OID_SECG_EC_SECT409R1 }, 411 { "sect571k1", SEC_OID_SECG_EC_SECT571K1 }, 412 { "nistk571", SEC_OID_SECG_EC_SECT571K1 }, 413 { "sect571r1", SEC_OID_SECG_EC_SECT571R1 }, 414 { "nistb571", SEC_OID_SECG_EC_SECT571R1 }, 415 { "secp160k1", SEC_OID_SECG_EC_SECP160K1 }, 416 { "secp160r1", SEC_OID_SECG_EC_SECP160R1 }, 417 { "secp160r2", SEC_OID_SECG_EC_SECP160R2 }, 418 { "secp192k1", SEC_OID_SECG_EC_SECP192K1 }, 419 { "secp192r1", SEC_OID_SECG_EC_SECP192R1 }, 420 { "nistp192", SEC_OID_SECG_EC_SECP192R1 }, 421 { "secp224k1", SEC_OID_SECG_EC_SECP224K1 }, 422 { "secp224r1", SEC_OID_SECG_EC_SECP224R1 }, 423 { "nistp224", SEC_OID_SECG_EC_SECP224R1 }, 424 { "secp256k1", SEC_OID_SECG_EC_SECP256K1 }, 425 { "secp256r1", SEC_OID_SECG_EC_SECP256R1 }, 426 { "nistp256", SEC_OID_SECG_EC_SECP256R1 }, 427 { "secp384r1", SEC_OID_SECG_EC_SECP384R1 }, 428 { "nistp384", SEC_OID_SECG_EC_SECP384R1 }, 429 { "secp521r1", SEC_OID_SECG_EC_SECP521R1 }, 430 { "nistp521", SEC_OID_SECG_EC_SECP521R1 }, 431 432 { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 }, 433 { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 }, 434 { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 }, 435 { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 }, 436 { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 }, 437 { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 }, 438 439 { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 }, 440 { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 }, 441 { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 }, 442 { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 }, 443 { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 }, 444 { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 }, 445 { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 }, 446 { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 }, 447 { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 }, 448 { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 }, 449 { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 }, 450 { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 }, 451 { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 }, 452 { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 }, 453 { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 }, 454 { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 }, 455 { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 }, 456 { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 }, 457 { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 }, 458 { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 }, 459 460 { "secp112r1", SEC_OID_SECG_EC_SECP112R1 }, 461 { "secp112r2", SEC_OID_SECG_EC_SECP112R2 }, 462 { "secp128r1", SEC_OID_SECG_EC_SECP128R1 }, 463 { "secp128r2", SEC_OID_SECG_EC_SECP128R2 }, 464 465 { "sect113r1", SEC_OID_SECG_EC_SECT113R1 }, 466 { "sect113r2", SEC_OID_SECG_EC_SECT113R2 }, 467 { "sect131r1", SEC_OID_SECG_EC_SECT131R1 }, 468 { "sect131r2", SEC_OID_SECG_EC_SECT131R2 }, 469 { "curve25519", SEC_OID_CURVE25519 }, 470 }; 471 472 static SECKEYECParams * 473 getECParams(const char *curve) 474 { 475 SECKEYECParams *ecparams; 476 SECOidData *oidData = NULL; 477 SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */ 478 int i, numCurves; 479 480 if (curve != NULL) { 481 numCurves = sizeof(nameTagPair) / sizeof(CurveNameTagPair); 482 for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); 483 i++) { 484 if (PL_strcmp(curve, nameTagPair[i].curveName) == 0) 485 curveOidTag = nameTagPair[i].curveOidTag; 486 } 487 } 488 489 /* Return NULL if curve name is not recognized */ 490 if ((curveOidTag == SEC_OID_UNKNOWN) || 491 (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) { 492 fprintf(stderr, "Unrecognized elliptic curve %s\n", curve); 493 return NULL; 494 } 495 496 ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len)); 497 498 /* 499 * ecparams->data needs to contain the ASN encoding of an object ID (OID) 500 * representing the named curve. The actual OID is in 501 * oidData->oid.data so we simply prepend 0x06 and OID length 502 */ 503 ecparams->data[0] = SEC_ASN1_OBJECT_ID; 504 ecparams->data[1] = oidData->oid.len; 505 memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len); 506 507 return ecparams; 508 } 509 510 SECKEYPrivateKey * 511 CERTUTIL_GeneratePrivateKey(KeyType keytype, PK11SlotInfo *slot, int size, 512 int publicExponent, const char *noise, 513 SECKEYPublicKey **pubkeyp, const char *pqgFile, 514 PK11AttrFlags attrFlags, CK_FLAGS opFlagsOn, 515 CK_FLAGS opFlagsOff, secuPWData *pwdata) 516 { 517 CK_MECHANISM_TYPE mechanism; 518 PK11RSAGenParams rsaparams; 519 SECKEYPQGParams *dsaparams = NULL; 520 void *params; 521 SECKEYPrivateKey *privKey = NULL; 522 523 if (slot == NULL) 524 return NULL; 525 526 if (PK11_Authenticate(slot, PR_TRUE, pwdata) != SECSuccess) 527 return NULL; 528 529 /* 530 * Do some random-number initialization. 531 */ 532 533 if (noise) { 534 SECStatus rv = CERTUTIL_FileForRNG(noise); 535 if (rv != SECSuccess) { 536 PORT_SetError(PR_END_OF_FILE_ERROR); /* XXX */ 537 return NULL; 538 } 539 } else { 540 int rv = UpdateRNG(); 541 if (rv) { 542 PORT_SetError(PR_END_OF_FILE_ERROR); 543 return NULL; 544 } 545 } 546 547 switch (keytype) { 548 case rsaKey: 549 rsaparams.keySizeInBits = size; 550 rsaparams.pe = publicExponent; 551 mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; 552 params = &rsaparams; 553 break; 554 case dsaKey: 555 mechanism = CKM_DSA_KEY_PAIR_GEN; 556 if (pqgFile) { 557 dsaparams = getpqgfromfile(size, pqgFile); 558 if (dsaparams == NULL) 559 return NULL; 560 params = dsaparams; 561 } else { 562 /* cast away const, and don't set dsaparams */ 563 params = (void *)&default_pqg_params; 564 } 565 break; 566 case ecKey: 567 mechanism = CKM_EC_KEY_PAIR_GEN; 568 /* For EC keys, PQGFile determines EC parameters */ 569 if ((params = (void *)getECParams(pqgFile)) == NULL) 570 return NULL; 571 break; 572 default: 573 return NULL; 574 } 575 576 fprintf(stderr, "\n\n"); 577 fprintf(stderr, "Generating key. This may take a few moments...\n\n"); 578 579 privKey = PK11_GenerateKeyPairWithOpFlags(slot, mechanism, params, pubkeyp, 580 attrFlags, opFlagsOn, opFlagsOn | opFlagsOff, 581 pwdata /*wincx*/); 582 /* free up the params */ 583 switch (keytype) { 584 case dsaKey: 585 if (dsaparams) 586 CERTUTIL_DestroyParamsPQG(dsaparams); 587 break; 588 case ecKey: 589 SECITEM_FreeItem((SECItem *)params, PR_TRUE); 590 break; 591 default: /* nothing to free */ 592 break; 593 } 594 return privKey; 595 }