security/nss/cmd/certutil/keystuff.c

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

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

mercurial