michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include michael@0: #include michael@0: #include "secutil.h" michael@0: michael@0: #if defined(XP_UNIX) michael@0: #include michael@0: #include michael@0: #include michael@0: #endif michael@0: michael@0: #if defined(XP_WIN) || defined (XP_PC) michael@0: #include michael@0: #include michael@0: #endif michael@0: michael@0: #if defined(__sun) && !defined(SVR4) michael@0: extern int fclose(FILE*); michael@0: extern int fprintf(FILE *, char *, ...); michael@0: extern int isatty(int); michael@0: extern char *sys_errlist[]; michael@0: #define strerror(errno) sys_errlist[errno] michael@0: #endif michael@0: michael@0: #include "nspr.h" michael@0: #include "prtypes.h" michael@0: #include "prtime.h" michael@0: #include "prlong.h" michael@0: michael@0: #include "pk11func.h" michael@0: michael@0: #define NUM_KEYSTROKES 120 michael@0: #define RAND_BUF_SIZE 60 michael@0: michael@0: #define ERROR_BREAK rv = SECFailure;break; michael@0: michael@0: const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = { michael@0: { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) }, michael@0: { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,prime) }, michael@0: { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,subPrime) }, michael@0: { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams,base) }, michael@0: { 0, } michael@0: }; michael@0: michael@0: /* returns 0 for success, -1 for failure (EOF encountered) */ michael@0: static int michael@0: UpdateRNG(void) michael@0: { michael@0: char randbuf[RAND_BUF_SIZE]; michael@0: int fd, count; michael@0: int c; michael@0: int rv = 0; michael@0: #ifdef XP_UNIX michael@0: cc_t orig_cc_min; michael@0: cc_t orig_cc_time; michael@0: tcflag_t orig_lflag; michael@0: struct termios tio; michael@0: #endif michael@0: char meter[] = { michael@0: "\r| |" }; michael@0: michael@0: #define FPS fprintf(stderr, michael@0: FPS "\n"); michael@0: FPS "A random seed must be generated that will be used in the\n"); michael@0: FPS "creation of your key. One of the easiest ways to create a\n"); michael@0: FPS "random seed is to use the timing of keystrokes on a keyboard.\n"); michael@0: FPS "\n"); michael@0: FPS "To begin, type keys on the keyboard until this progress meter\n"); michael@0: FPS "is full. DO NOT USE THE AUTOREPEAT FUNCTION ON YOUR KEYBOARD!\n"); michael@0: FPS "\n"); michael@0: FPS "\n"); michael@0: FPS "Continue typing until the progress meter is full:\n\n"); michael@0: FPS "%s", meter); michael@0: FPS "\r|"); michael@0: michael@0: /* turn off echo on stdin & return on 1 char instead of NL */ michael@0: fd = fileno(stdin); michael@0: michael@0: #if defined(XP_UNIX) michael@0: tcgetattr(fd, &tio); michael@0: orig_lflag = tio.c_lflag; michael@0: orig_cc_min = tio.c_cc[VMIN]; michael@0: orig_cc_time = tio.c_cc[VTIME]; michael@0: tio.c_lflag &= ~ECHO; michael@0: tio.c_lflag &= ~ICANON; michael@0: tio.c_cc[VMIN] = 1; michael@0: tio.c_cc[VTIME] = 0; michael@0: tcsetattr(fd, TCSAFLUSH, &tio); michael@0: #endif michael@0: michael@0: /* Get random noise from keyboard strokes */ michael@0: count = 0; michael@0: while (count < sizeof randbuf) { michael@0: #if defined(XP_UNIX) michael@0: c = getc(stdin); michael@0: #else michael@0: c = getch(); michael@0: #endif michael@0: if (c == EOF) { michael@0: rv = -1; michael@0: break; michael@0: } michael@0: randbuf[count] = c; michael@0: if (count == 0 || c != randbuf[count-1]) { michael@0: count++; michael@0: FPS "*"); michael@0: } michael@0: } michael@0: PK11_RandomUpdate(randbuf, sizeof randbuf); michael@0: memset(randbuf, 0, sizeof randbuf); michael@0: michael@0: FPS "\n\n"); michael@0: FPS "Finished. Press enter to continue: "); michael@0: while ((c = getc(stdin)) != '\n' && c != EOF) michael@0: ; michael@0: if (c == EOF) michael@0: rv = -1; michael@0: FPS "\n"); michael@0: michael@0: #undef FPS michael@0: michael@0: #if defined(XP_UNIX) michael@0: /* set back termio the way it was */ michael@0: tio.c_lflag = orig_lflag; michael@0: tio.c_cc[VMIN] = orig_cc_min; michael@0: tio.c_cc[VTIME] = orig_cc_time; michael@0: tcsetattr(fd, TCSAFLUSH, &tio); michael@0: #endif michael@0: return rv; michael@0: } michael@0: michael@0: static const unsigned char P[] = { 0, michael@0: 0x98, 0xef, 0x3a, 0xae, 0x70, 0x98, 0x9b, 0x44, michael@0: 0xdb, 0x35, 0x86, 0xc1, 0xb6, 0xc2, 0x47, 0x7c, michael@0: 0xb4, 0xff, 0x99, 0xe8, 0xae, 0x44, 0xf2, 0xeb, michael@0: 0xc3, 0xbe, 0x23, 0x0f, 0x65, 0xd0, 0x4c, 0x04, michael@0: 0x82, 0x90, 0xa7, 0x9d, 0x4a, 0xc8, 0x93, 0x7f, michael@0: 0x41, 0xdf, 0xf8, 0x80, 0x6b, 0x0b, 0x68, 0x7f, michael@0: 0xaf, 0xe4, 0xa8, 0xb5, 0xb2, 0x99, 0xc3, 0x69, michael@0: 0xfb, 0x3f, 0xe7, 0x1b, 0xd0, 0x0f, 0xa9, 0x7a, michael@0: 0x4a, 0x04, 0xbf, 0x50, 0x9e, 0x22, 0x33, 0xb8, michael@0: 0x89, 0x53, 0x24, 0x10, 0xf9, 0x68, 0x77, 0xad, michael@0: 0xaf, 0x10, 0x68, 0xb8, 0xd3, 0x68, 0x5d, 0xa3, michael@0: 0xc3, 0xeb, 0x72, 0x3b, 0xa0, 0x0b, 0x73, 0x65, michael@0: 0xc5, 0xd1, 0xfa, 0x8c, 0xc0, 0x7d, 0xaa, 0x52, michael@0: 0x29, 0x34, 0x44, 0x01, 0xbf, 0x12, 0x25, 0xfe, michael@0: 0x18, 0x0a, 0xc8, 0x3f, 0xc1, 0x60, 0x48, 0xdb, michael@0: 0xad, 0x93, 0xb6, 0x61, 0x67, 0xd7, 0xa8, 0x2d }; michael@0: static const unsigned char Q[] = { 0, michael@0: 0xb5, 0xb0, 0x84, 0x8b, 0x44, 0x29, 0xf6, 0x33, michael@0: 0x59, 0xa1, 0x3c, 0xbe, 0xd2, 0x7f, 0x35, 0xa1, michael@0: 0x76, 0x27, 0x03, 0x81 }; michael@0: static const unsigned char G[] = { michael@0: 0x04, 0x0e, 0x83, 0x69, 0xf1, 0xcd, 0x7d, 0xe5, michael@0: 0x0c, 0x78, 0x93, 0xd6, 0x49, 0x6f, 0x00, 0x04, michael@0: 0x4e, 0x0e, 0x6c, 0x37, 0xaa, 0x38, 0x22, 0x47, michael@0: 0xd2, 0x58, 0xec, 0x83, 0x12, 0x95, 0xf9, 0x9c, michael@0: 0xf1, 0xf4, 0x27, 0xff, 0xd7, 0x99, 0x57, 0x35, michael@0: 0xc6, 0x64, 0x4c, 0xc0, 0x47, 0x12, 0x31, 0x50, michael@0: 0x82, 0x3c, 0x2a, 0x07, 0x03, 0x01, 0xef, 0x30, michael@0: 0x09, 0x89, 0x82, 0x41, 0x76, 0x71, 0xda, 0x9e, michael@0: 0x57, 0x8b, 0x76, 0x38, 0x37, 0x5f, 0xa5, 0xcd, michael@0: 0x32, 0x84, 0x45, 0x8d, 0x4c, 0x17, 0x54, 0x2b, michael@0: 0x5d, 0xc2, 0x6b, 0xba, 0x3e, 0xa0, 0x7b, 0x95, michael@0: 0xd7, 0x00, 0x42, 0xf7, 0x08, 0xb8, 0x83, 0x87, michael@0: 0x60, 0xe1, 0xe5, 0xf4, 0x1a, 0x54, 0xc2, 0x20, michael@0: 0xda, 0x38, 0x3a, 0xd1, 0xb6, 0x10, 0xf4, 0xcb, michael@0: 0x35, 0xda, 0x97, 0x92, 0x87, 0xd6, 0xa5, 0x37, michael@0: 0x62, 0xb4, 0x93, 0x4a, 0x15, 0x21, 0xa5, 0x10 }; michael@0: michael@0: /* h: michael@0: * 4a:76:30:89:eb:e1:81:7c:99:0b:39:7f:95:4a:65:72: michael@0: * c6:b4:05:92:48:6c:3c:b2:7e:e7:39:f3:92:7d:c1:3f: michael@0: * bf:e1:fd:b3:4a:46:3e:ce:29:80:e3:d6:f4:59:c6:92: michael@0: * 16:2b:0e:d7:d6:bb:ef:94:36:31:c2:66:46:c5:4a:77: michael@0: * aa:95:84:ef:99:7e:e3:9c:d9:a0:32:42:09:b6:4e:d0: michael@0: * b3:c8:5e:06:df:a1:ac:4d:2d:f9:08:c2:cb:4b:a4:42: michael@0: * db:8a:5b:de:25:6e:2b:5b:ca:00:75:2c:57:00:18:aa: michael@0: * 68:59:a1:94:03:07:94:78:38:bc:f8:7c:1e:1c:a3:2e michael@0: * SEED: michael@0: * b5:44:66:c9:0f:f1:ca:1c:95:45:ce:90:74:89:14:f2: michael@0: * 13:3e:23:5a:b0:6a:bf:86:ad:cb:a0:7d:ce:3b:c8:16: michael@0: * 7f:2d:a2:1a:cb:33:7d:c1:e7:d7:07:aa:1b:a2:d7:89: michael@0: * f5:a4:db:f7:8b:50:00:cd:b4:7d:25:81:3f:f8:a8:dd: michael@0: * 6c:46:e5:77:b5:60:7e:75:79:b8:99:57:c1:c4:f3:f7: michael@0: * 17:ca:43:00:b8:33:b6:06:8f:4d:91:ed:23:a5:66:1b: michael@0: * ef:14:d7:bc:21:2b:82:d8:ab:fa:fd:a7:c3:4d:bf:52: michael@0: * af:8e:57:59:61:1a:4e:65:c6:90:d6:a6:ff:0b:15:b1 michael@0: * g: 1024 michael@0: * counter: 1003 michael@0: */ michael@0: michael@0: static const SECKEYPQGParams default_pqg_params = { michael@0: NULL, michael@0: { 0, (unsigned char *)P, sizeof(P) }, michael@0: { 0, (unsigned char *)Q, sizeof(Q) }, michael@0: { 0, (unsigned char *)G, sizeof(G) } michael@0: }; michael@0: michael@0: static SECKEYPQGParams * michael@0: decode_pqg_params(const char *str) michael@0: { michael@0: char *buf; michael@0: unsigned int len; michael@0: PLArenaPool *arena; michael@0: SECKEYPQGParams *params; michael@0: SECStatus status; michael@0: michael@0: arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); michael@0: if (arena == NULL) michael@0: return NULL; michael@0: michael@0: params = PORT_ArenaZAlloc(arena, sizeof(SECKEYPQGParams)); michael@0: if (params == NULL) michael@0: goto loser; michael@0: params->arena = arena; michael@0: michael@0: buf = (char *)ATOB_AsciiToData(str, &len); michael@0: if ((buf == NULL) || (len == 0)) michael@0: goto loser; michael@0: michael@0: status = SEC_ASN1Decode(arena, params, SECKEY_PQGParamsTemplate, buf, len); michael@0: if (status != SECSuccess) michael@0: goto loser; michael@0: michael@0: return params; michael@0: michael@0: loser: michael@0: if (arena != NULL) michael@0: PORT_FreeArena(arena, PR_FALSE); michael@0: return NULL; michael@0: } michael@0: michael@0: void michael@0: CERTUTIL_DestroyParamsPQG(SECKEYPQGParams *params) michael@0: { michael@0: if (params->arena) { michael@0: PORT_FreeArena(params->arena, PR_FALSE); michael@0: } michael@0: } michael@0: michael@0: static int michael@0: pqg_prime_bits(const SECKEYPQGParams *params) michael@0: { michael@0: int primeBits = 0; michael@0: michael@0: if (params != NULL) { michael@0: int i; michael@0: for (i = 0; params->prime.data[i] == 0; i++) { michael@0: /* empty */; michael@0: } michael@0: primeBits = (params->prime.len - i) * 8; michael@0: } michael@0: michael@0: return primeBits; michael@0: } michael@0: michael@0: static char * michael@0: getPQGString(const char *filename) michael@0: { michael@0: unsigned char *buf = NULL; michael@0: PRFileDesc *src; michael@0: PRInt32 numBytes; michael@0: PRStatus prStatus; michael@0: PRFileInfo info; michael@0: michael@0: src = PR_Open(filename, PR_RDONLY, 0); michael@0: if (!src) { michael@0: fprintf(stderr, "Failed to open PQG file %s\n", filename); michael@0: return NULL; michael@0: } michael@0: michael@0: prStatus = PR_GetOpenFileInfo(src, &info); michael@0: michael@0: if (prStatus == PR_SUCCESS) { michael@0: buf = (unsigned char*)PORT_Alloc(info.size + 1); michael@0: } michael@0: if (!buf) { michael@0: PR_Close(src); michael@0: fprintf(stderr, "Failed to read PQG file %s\n", filename); michael@0: return NULL; michael@0: } michael@0: michael@0: numBytes = PR_Read(src, buf, info.size); michael@0: PR_Close(src); michael@0: if (numBytes != info.size) { michael@0: PORT_Free(buf); michael@0: fprintf(stderr, "Failed to read PQG file %s\n", filename); michael@0: PORT_SetError(SEC_ERROR_IO); michael@0: return NULL; michael@0: } michael@0: michael@0: if (buf[numBytes-1] == '\n') michael@0: numBytes--; michael@0: if (buf[numBytes-1] == '\r') michael@0: numBytes--; michael@0: buf[numBytes] = 0; michael@0: michael@0: return (char *)buf; michael@0: } michael@0: michael@0: static SECKEYPQGParams* michael@0: getpqgfromfile(int keyBits, const char *pqgFile) michael@0: { michael@0: char *end, *str, *pqgString; michael@0: SECKEYPQGParams* params = NULL; michael@0: michael@0: str = pqgString = getPQGString(pqgFile); michael@0: if (!str) michael@0: return NULL; michael@0: michael@0: do { michael@0: end = PORT_Strchr(str, ','); michael@0: if (end) michael@0: *end = '\0'; michael@0: params = decode_pqg_params(str); michael@0: if (params) { michael@0: int primeBits = pqg_prime_bits(params); michael@0: if (keyBits == primeBits) michael@0: break; michael@0: CERTUTIL_DestroyParamsPQG(params); michael@0: params = NULL; michael@0: } michael@0: if (end) michael@0: str = end + 1; michael@0: } while (end); michael@0: michael@0: PORT_Free(pqgString); michael@0: return params; michael@0: } michael@0: michael@0: static SECStatus michael@0: CERTUTIL_FileForRNG(const char *noise) michael@0: { michael@0: char buf[2048]; michael@0: PRFileDesc *fd; michael@0: PRInt32 count; michael@0: michael@0: fd = PR_Open(noise,PR_RDONLY,0); michael@0: if (!fd) { michael@0: fprintf(stderr, "failed to open noise file."); michael@0: return SECFailure; michael@0: } michael@0: michael@0: do { michael@0: count = PR_Read(fd,buf,sizeof(buf)); michael@0: if (count > 0) { michael@0: PK11_RandomUpdate(buf,count); michael@0: } michael@0: } while (count > 0); michael@0: michael@0: PR_Close(fd); michael@0: return SECSuccess; michael@0: } michael@0: michael@0: #ifndef NSS_DISABLE_ECC michael@0: typedef struct curveNameTagPairStr { michael@0: char *curveName; michael@0: SECOidTag curveOidTag; michael@0: } CurveNameTagPair; michael@0: michael@0: #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1 michael@0: /* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */ michael@0: michael@0: static CurveNameTagPair nameTagPair[] = michael@0: { michael@0: { "sect163k1", SEC_OID_SECG_EC_SECT163K1}, michael@0: { "nistk163", SEC_OID_SECG_EC_SECT163K1}, michael@0: { "sect163r1", SEC_OID_SECG_EC_SECT163R1}, michael@0: { "sect163r2", SEC_OID_SECG_EC_SECT163R2}, michael@0: { "nistb163", SEC_OID_SECG_EC_SECT163R2}, michael@0: { "sect193r1", SEC_OID_SECG_EC_SECT193R1}, michael@0: { "sect193r2", SEC_OID_SECG_EC_SECT193R2}, michael@0: { "sect233k1", SEC_OID_SECG_EC_SECT233K1}, michael@0: { "nistk233", SEC_OID_SECG_EC_SECT233K1}, michael@0: { "sect233r1", SEC_OID_SECG_EC_SECT233R1}, michael@0: { "nistb233", SEC_OID_SECG_EC_SECT233R1}, michael@0: { "sect239k1", SEC_OID_SECG_EC_SECT239K1}, michael@0: { "sect283k1", SEC_OID_SECG_EC_SECT283K1}, michael@0: { "nistk283", SEC_OID_SECG_EC_SECT283K1}, michael@0: { "sect283r1", SEC_OID_SECG_EC_SECT283R1}, michael@0: { "nistb283", SEC_OID_SECG_EC_SECT283R1}, michael@0: { "sect409k1", SEC_OID_SECG_EC_SECT409K1}, michael@0: { "nistk409", SEC_OID_SECG_EC_SECT409K1}, michael@0: { "sect409r1", SEC_OID_SECG_EC_SECT409R1}, michael@0: { "nistb409", SEC_OID_SECG_EC_SECT409R1}, michael@0: { "sect571k1", SEC_OID_SECG_EC_SECT571K1}, michael@0: { "nistk571", SEC_OID_SECG_EC_SECT571K1}, michael@0: { "sect571r1", SEC_OID_SECG_EC_SECT571R1}, michael@0: { "nistb571", SEC_OID_SECG_EC_SECT571R1}, michael@0: { "secp160k1", SEC_OID_SECG_EC_SECP160K1}, michael@0: { "secp160r1", SEC_OID_SECG_EC_SECP160R1}, michael@0: { "secp160r2", SEC_OID_SECG_EC_SECP160R2}, michael@0: { "secp192k1", SEC_OID_SECG_EC_SECP192K1}, michael@0: { "secp192r1", SEC_OID_SECG_EC_SECP192R1}, michael@0: { "nistp192", SEC_OID_SECG_EC_SECP192R1}, michael@0: { "secp224k1", SEC_OID_SECG_EC_SECP224K1}, michael@0: { "secp224r1", SEC_OID_SECG_EC_SECP224R1}, michael@0: { "nistp224", SEC_OID_SECG_EC_SECP224R1}, michael@0: { "secp256k1", SEC_OID_SECG_EC_SECP256K1}, michael@0: { "secp256r1", SEC_OID_SECG_EC_SECP256R1}, michael@0: { "nistp256", SEC_OID_SECG_EC_SECP256R1}, michael@0: { "secp384r1", SEC_OID_SECG_EC_SECP384R1}, michael@0: { "nistp384", SEC_OID_SECG_EC_SECP384R1}, michael@0: { "secp521r1", SEC_OID_SECG_EC_SECP521R1}, michael@0: { "nistp521", SEC_OID_SECG_EC_SECP521R1}, michael@0: michael@0: { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 }, michael@0: { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 }, michael@0: { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 }, michael@0: { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 }, michael@0: { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 }, michael@0: { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 }, michael@0: michael@0: { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 }, michael@0: { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 }, michael@0: { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 }, michael@0: { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 }, michael@0: { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 }, michael@0: { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 }, michael@0: { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 }, michael@0: { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 }, michael@0: { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 }, michael@0: { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 }, michael@0: { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 }, michael@0: { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 }, michael@0: { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 }, michael@0: { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 }, michael@0: { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 }, michael@0: { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 }, michael@0: { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 }, michael@0: { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 }, michael@0: { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 }, michael@0: { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 }, michael@0: michael@0: { "secp112r1", SEC_OID_SECG_EC_SECP112R1}, michael@0: { "secp112r2", SEC_OID_SECG_EC_SECP112R2}, michael@0: { "secp128r1", SEC_OID_SECG_EC_SECP128R1}, michael@0: { "secp128r2", SEC_OID_SECG_EC_SECP128R2}, michael@0: michael@0: { "sect113r1", SEC_OID_SECG_EC_SECT113R1}, michael@0: { "sect113r2", SEC_OID_SECG_EC_SECT113R2}, michael@0: { "sect131r1", SEC_OID_SECG_EC_SECT131R1}, michael@0: { "sect131r2", SEC_OID_SECG_EC_SECT131R2}, michael@0: }; michael@0: michael@0: static SECKEYECParams * michael@0: getECParams(const char *curve) michael@0: { michael@0: SECKEYECParams *ecparams; michael@0: SECOidData *oidData = NULL; michael@0: SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */ michael@0: int i, numCurves; michael@0: michael@0: if (curve != NULL) { michael@0: numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair); michael@0: for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); michael@0: i++) { michael@0: if (PL_strcmp(curve, nameTagPair[i].curveName) == 0) michael@0: curveOidTag = nameTagPair[i].curveOidTag; michael@0: } michael@0: } michael@0: michael@0: /* Return NULL if curve name is not recognized */ michael@0: if ((curveOidTag == SEC_OID_UNKNOWN) || michael@0: (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) { michael@0: fprintf(stderr, "Unrecognized elliptic curve %s\n", curve); michael@0: return NULL; michael@0: } michael@0: michael@0: ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len)); michael@0: michael@0: /* michael@0: * ecparams->data needs to contain the ASN encoding of an object ID (OID) michael@0: * representing the named curve. The actual OID is in michael@0: * oidData->oid.data so we simply prepend 0x06 and OID length michael@0: */ michael@0: ecparams->data[0] = SEC_ASN1_OBJECT_ID; michael@0: ecparams->data[1] = oidData->oid.len; michael@0: memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len); michael@0: michael@0: return ecparams; michael@0: } michael@0: #endif /* NSS_DISABLE_ECC */ michael@0: michael@0: SECKEYPrivateKey * michael@0: CERTUTIL_GeneratePrivateKey(KeyType keytype, PK11SlotInfo *slot, int size, michael@0: int publicExponent, const char *noise, michael@0: SECKEYPublicKey **pubkeyp, const char *pqgFile, michael@0: PK11AttrFlags attrFlags, CK_FLAGS opFlagsOn, michael@0: CK_FLAGS opFlagsOff, secuPWData *pwdata) michael@0: { michael@0: CK_MECHANISM_TYPE mechanism; michael@0: SECOidTag algtag; michael@0: PK11RSAGenParams rsaparams; michael@0: SECKEYPQGParams * dsaparams = NULL; michael@0: void * params; michael@0: SECKEYPrivateKey * privKey = NULL; michael@0: michael@0: if (slot == NULL) michael@0: return NULL; michael@0: michael@0: if (PK11_Authenticate(slot, PR_TRUE, pwdata) != SECSuccess) michael@0: return NULL; michael@0: michael@0: /* michael@0: * Do some random-number initialization. michael@0: */ michael@0: michael@0: if (noise) { michael@0: SECStatus rv = CERTUTIL_FileForRNG(noise); michael@0: if (rv != SECSuccess) { michael@0: PORT_SetError(PR_END_OF_FILE_ERROR); /* XXX */ michael@0: return NULL; michael@0: } michael@0: } else { michael@0: int rv = UpdateRNG(); michael@0: if (rv) { michael@0: PORT_SetError(PR_END_OF_FILE_ERROR); michael@0: return NULL; michael@0: } michael@0: } michael@0: michael@0: switch (keytype) { michael@0: case rsaKey: michael@0: rsaparams.keySizeInBits = size; michael@0: rsaparams.pe = publicExponent; michael@0: mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; michael@0: algtag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION; michael@0: params = &rsaparams; michael@0: break; michael@0: case dsaKey: michael@0: mechanism = CKM_DSA_KEY_PAIR_GEN; michael@0: algtag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; michael@0: if (pqgFile) { michael@0: dsaparams = getpqgfromfile(size, pqgFile); michael@0: if (dsaparams == NULL) michael@0: return NULL; michael@0: params = dsaparams; michael@0: } else { michael@0: /* cast away const, and don't set dsaparams */ michael@0: params = (void *)&default_pqg_params; michael@0: } michael@0: break; michael@0: #ifndef NSS_DISABLE_ECC michael@0: case ecKey: michael@0: mechanism = CKM_EC_KEY_PAIR_GEN; michael@0: /* For EC keys, PQGFile determines EC parameters */ michael@0: if ((params = (void *) getECParams(pqgFile)) == NULL) michael@0: return NULL; michael@0: break; michael@0: #endif /* NSS_DISABLE_ECC */ michael@0: default: michael@0: return NULL; michael@0: } michael@0: michael@0: fprintf(stderr, "\n\n"); michael@0: fprintf(stderr, "Generating key. This may take a few moments...\n\n"); michael@0: michael@0: privKey = PK11_GenerateKeyPairWithOpFlags(slot, mechanism, params, pubkeyp, michael@0: attrFlags, opFlagsOn, opFlagsOn|opFlagsOff, michael@0: pwdata /*wincx*/); michael@0: /* free up the params */ michael@0: switch (keytype) { michael@0: case dsaKey: if (dsaparams) CERTUTIL_DestroyParamsPQG(dsaparams); michael@0: break; michael@0: #ifndef NSS_DISABLE_ECC michael@0: case ecKey: SECITEM_FreeItem((SECItem *)params, PR_TRUE); break; michael@0: #endif michael@0: default: /* nothing to free */ break; michael@0: } michael@0: return privKey; michael@0: }