tor-browser

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

makepqg.c (10462B)


      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 "prtypes.h"
      6 #include "prtime.h"
      7 #include "prlong.h"
      8 
      9 #include "nss.h"
     10 #include "secutil.h"
     11 #include "secitem.h"
     12 #include "pk11func.h"
     13 #include "pk11pqg.h"
     14 
     15 #if defined(XP_UNIX)
     16 #include <unistd.h>
     17 #endif
     18 
     19 #include "plgetopt.h"
     20 
     21 #define BPB 8 /* bits per byte. */
     22 
     23 char *progName;
     24 
     25 const SEC_ASN1Template seckey_PQGParamsTemplate[] = {
     26    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) },
     27    { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, prime) },
     28    { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, subPrime) },
     29    { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, base) },
     30    { 0 }
     31 };
     32 
     33 void
     34 Usage(void)
     35 {
     36    fprintf(stderr, "Usage:  %s\n", progName);
     37    fprintf(stderr,
     38            "-a   Output DER-encoded PQG params, BTOA encoded.\n"
     39            "-b   Output DER-encoded PQG params in binary\n"
     40            "-r   Output P, Q and G in ASCII hexadecimal. \n"
     41            "  -l prime-length       Length of prime in bits (1024 is default)\n"
     42            "  -n subprime-length    Length of subprime in bits\n"
     43            "  -o file               Output to this file (default is stdout)\n"
     44            "  -g bits               Generate SEED this many bits long.\n");
     45    exit(-1);
     46 }
     47 
     48 SECStatus
     49 outputPQGParams(PQGParams *pqgParams, PRBool output_binary, PRBool output_raw,
     50                FILE *outFile)
     51 {
     52    PLArenaPool *arena = NULL;
     53    char *PQG;
     54    SECItem *pItem;
     55    int cc;
     56    SECStatus rv;
     57    SECItem encodedParams;
     58 
     59    if (output_raw) {
     60        SECItem item;
     61 
     62        rv = PK11_PQG_GetPrimeFromParams(pqgParams, &item);
     63        if (rv) {
     64            SECU_PrintError(progName, "PK11_PQG_GetPrimeFromParams");
     65            return rv;
     66        }
     67        SECU_PrintInteger(outFile, &item, "Prime", 1);
     68        SECITEM_FreeItem(&item, PR_FALSE);
     69 
     70        rv = PK11_PQG_GetSubPrimeFromParams(pqgParams, &item);
     71        if (rv) {
     72            SECU_PrintError(progName, "PK11_PQG_GetPrimeFromParams");
     73            return rv;
     74        }
     75        SECU_PrintInteger(outFile, &item, "Subprime", 1);
     76        SECITEM_FreeItem(&item, PR_FALSE);
     77 
     78        rv = PK11_PQG_GetBaseFromParams(pqgParams, &item);
     79        if (rv) {
     80            SECU_PrintError(progName, "PK11_PQG_GetPrimeFromParams");
     81            return rv;
     82        }
     83        SECU_PrintInteger(outFile, &item, "Base", 1);
     84        SECITEM_FreeItem(&item, PR_FALSE);
     85 
     86        fprintf(outFile, "\n");
     87        return SECSuccess;
     88    }
     89 
     90    encodedParams.data = NULL;
     91    encodedParams.len = 0;
     92    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     93    if (!arena) {
     94        SECU_PrintError(progName, "PORT_NewArena");
     95        return SECFailure;
     96    }
     97    pItem = SEC_ASN1EncodeItem(arena, &encodedParams, pqgParams,
     98                               seckey_PQGParamsTemplate);
     99    if (!pItem) {
    100        SECU_PrintError(progName, "SEC_ASN1EncodeItem");
    101        PORT_FreeArena(arena, PR_FALSE);
    102        return SECFailure;
    103    }
    104    if (output_binary) {
    105        size_t len;
    106        len = fwrite(encodedParams.data, 1, encodedParams.len, outFile);
    107        PORT_FreeArena(arena, PR_FALSE);
    108        if (len != encodedParams.len) {
    109            fprintf(stderr, "%s: fwrite failed\n", progName);
    110            return SECFailure;
    111        }
    112        return SECSuccess;
    113    }
    114 
    115    /* must be output ASCII */
    116    PQG = BTOA_DataToAscii(encodedParams.data, encodedParams.len);
    117    PORT_FreeArena(arena, PR_FALSE);
    118    if (!PQG) {
    119        SECU_PrintError(progName, "BTOA_DataToAscii");
    120        return SECFailure;
    121    }
    122 
    123    cc = fprintf(outFile, "%s\n", PQG);
    124    PORT_Free(PQG);
    125    if (cc <= 0) {
    126        fprintf(stderr, "%s: fprintf failed\n", progName);
    127        return SECFailure;
    128    }
    129    return SECSuccess;
    130 }
    131 
    132 SECStatus
    133 outputPQGVerify(PQGVerify *pqgVerify, PRBool output_binary, PRBool output_raw,
    134                FILE *outFile)
    135 {
    136    SECStatus rv = SECSuccess;
    137    if (output_raw) {
    138        SECItem item;
    139        unsigned int counter;
    140 
    141        rv = PK11_PQG_GetHFromVerify(pqgVerify, &item);
    142        if (rv) {
    143            SECU_PrintError(progName, "PK11_PQG_GetHFromVerify");
    144            return rv;
    145        }
    146        SECU_PrintInteger(outFile, &item, "h", 1);
    147        SECITEM_FreeItem(&item, PR_FALSE);
    148 
    149        rv = PK11_PQG_GetSeedFromVerify(pqgVerify, &item);
    150        if (rv) {
    151            SECU_PrintError(progName, "PK11_PQG_GetSeedFromVerify");
    152            return rv;
    153        }
    154        SECU_PrintInteger(outFile, &item, "SEED", 1);
    155        fprintf(outFile, "    g:       %d\n", item.len * BPB);
    156        SECITEM_FreeItem(&item, PR_FALSE);
    157 
    158        counter = PK11_PQG_GetCounterFromVerify(pqgVerify);
    159        fprintf(outFile, "    counter: %d\n", counter);
    160        fprintf(outFile, "\n");
    161    }
    162    return rv;
    163 }
    164 
    165 int
    166 main(int argc, char **argv)
    167 {
    168    FILE *outFile = NULL;
    169    char *outFileName = NULL;
    170    PQGParams *pqgParams = NULL;
    171    PQGVerify *pqgVerify = NULL;
    172    int keySizeInBits = 1024;
    173    int j = 8;
    174    int g = 0;
    175    int gMax = 0;
    176    int qSizeInBits = 0;
    177    SECStatus rv = 0;
    178    SECStatus passed = 0;
    179    PRBool output_ascii = PR_FALSE;
    180    PRBool output_binary = PR_FALSE;
    181    PRBool output_raw = PR_FALSE;
    182    PLOptState *optstate;
    183    PLOptStatus status;
    184 
    185    progName = strrchr(argv[0], '/');
    186    if (!progName)
    187        progName = strrchr(argv[0], '\\');
    188    progName = progName ? progName + 1 : argv[0];
    189 
    190    /* Parse command line arguments */
    191    optstate = PL_CreateOptState(argc, argv, "?abg:l:n:o:r");
    192    while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
    193        switch (optstate->option) {
    194 
    195            case 'l':
    196                keySizeInBits = atoi(optstate->value);
    197                break;
    198 
    199            case 'n':
    200                qSizeInBits = atoi(optstate->value);
    201                break;
    202 
    203            case 'a':
    204                output_ascii = PR_TRUE;
    205                break;
    206 
    207            case 'b':
    208                output_binary = PR_TRUE;
    209                break;
    210 
    211            case 'r':
    212                output_raw = PR_TRUE;
    213                break;
    214 
    215            case 'o':
    216                if (outFileName) {
    217                    PORT_Free(outFileName);
    218                }
    219                outFileName = PORT_Strdup(optstate->value);
    220                if (!outFileName) {
    221                    rv = -1;
    222                }
    223                break;
    224 
    225            case 'g':
    226                g = atoi(optstate->value);
    227                break;
    228 
    229            default:
    230            case '?':
    231                Usage();
    232                break;
    233        }
    234    }
    235    PL_DestroyOptState(optstate);
    236 
    237    if (status == PL_OPT_BAD) {
    238        Usage();
    239    }
    240 
    241    /* exactly 1 of these options must be set. */
    242    if (1 != ((output_ascii != PR_FALSE) +
    243              (output_binary != PR_FALSE) +
    244              (output_raw != PR_FALSE))) {
    245        Usage();
    246    }
    247 
    248    gMax = 2 * keySizeInBits;
    249    if (keySizeInBits < 1024) {
    250        j = PQG_PBITS_TO_INDEX(keySizeInBits);
    251        if (j < 0) {
    252            fprintf(stderr, "%s: Illegal prime length, \n"
    253                            "\tacceptable values are between 512 and 1024,\n"
    254                            "\tand divisible by 64, or 2048 or 3072\n",
    255                    progName);
    256            return 2;
    257        }
    258        gMax = 2048;
    259        if ((qSizeInBits != 0) && (qSizeInBits != 160)) {
    260            fprintf(stderr, "%s: Illegal subprime length, \n"
    261                            "\tonly 160 is acceptible for primes <= 1024\n",
    262                    progName);
    263            return 2;
    264        }
    265        /* this forces keysizes less than 1024 into the DSA1 generation
    266         * code. Whether 1024 uses DSA2 or not is triggered by qSizeInBits
    267         * being non-zero. All larger keysizes will use DSA2.
    268         */
    269        qSizeInBits = 0;
    270    }
    271    if (g != 0 && (g < 160 || g >= gMax || g % 8 != 0)) {
    272        fprintf(stderr, "%s: Illegal g bits, \n"
    273                        "\tacceptable values are between 160 and %d,\n"
    274                        "\tand divisible by 8\n",
    275                progName, gMax);
    276        return 3;
    277    }
    278 
    279    if (!rv && outFileName) {
    280        outFile = fopen(outFileName, output_binary ? "wb" : "w");
    281        if (!outFile) {
    282            fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
    283                    progName, outFileName);
    284            rv = -1;
    285        }
    286    }
    287    if (outFileName) {
    288        PORT_Free(outFileName);
    289    }
    290    if (rv != 0) {
    291        return 1;
    292    }
    293 
    294    if (outFile == NULL) {
    295        outFile = stdout;
    296    }
    297 
    298    if (NSS_NoDB_Init(NULL) != SECSuccess) {
    299        return 1;
    300    }
    301 
    302    if (keySizeInBits > 1024 || qSizeInBits != 0) {
    303        rv = PK11_PQG_ParamGenV2((unsigned)keySizeInBits,
    304                                 (unsigned)qSizeInBits, (unsigned)(g / 8),
    305                                 &pqgParams, &pqgVerify);
    306    } else if (g) {
    307        rv = PK11_PQG_ParamGenSeedLen((unsigned)j, (unsigned)(g / 8),
    308                                      &pqgParams, &pqgVerify);
    309    } else {
    310        rv = PK11_PQG_ParamGen((unsigned)j, &pqgParams, &pqgVerify);
    311    }
    312    /* below here, must go to loser */
    313 
    314    if (rv != SECSuccess || pqgParams == NULL || pqgVerify == NULL) {
    315        SECU_PrintError(progName, "PQG parameter generation failed.\n");
    316        goto loser;
    317    }
    318    fprintf(stderr, "%s: PQG parameter generation completed.\n", progName);
    319 
    320    rv = outputPQGParams(pqgParams, output_binary, output_raw, outFile);
    321    if (rv) {
    322        fprintf(stderr, "%s: failed to output PQG params.\n", progName);
    323        goto loser;
    324    }
    325    rv = outputPQGVerify(pqgVerify, output_binary, output_raw, outFile);
    326    if (rv) {
    327        fprintf(stderr, "%s: failed to output PQG Verify.\n", progName);
    328        goto loser;
    329    }
    330 
    331    rv = PK11_PQG_VerifyParams(pqgParams, pqgVerify, &passed);
    332    if (rv != SECSuccess) {
    333        fprintf(stderr, "%s: PQG parameter verification aborted.\n", progName);
    334        goto loser;
    335    }
    336    if (passed != SECSuccess) {
    337        fprintf(stderr, "%s: PQG parameters failed verification.\n", progName);
    338        goto loser;
    339    }
    340    fprintf(stderr, "%s: PQG parameters passed verification.\n", progName);
    341 
    342    PK11_PQG_DestroyParams(pqgParams);
    343    PK11_PQG_DestroyVerify(pqgVerify);
    344    if (NSS_Shutdown() != SECSuccess) {
    345        return 1;
    346    }
    347    return 0;
    348 
    349 loser:
    350    PK11_PQG_DestroyParams(pqgParams);
    351    PK11_PQG_DestroyVerify(pqgVerify);
    352    return 1;
    353 }