tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }