Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 | } |