tor-browser

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

fbectest.c (7527B)


      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 "blapi.h"
      6 #include "ec.h"
      7 #include "ecl-curve.h"
      8 #include "prprf.h"
      9 #include "basicutil.h"
     10 #include "secder.h"
     11 #include "secitem.h"
     12 #include "nspr.h"
     13 #include <stdio.h>
     14 
     15 typedef struct {
     16    ECCurveName curve;
     17    int iterations;
     18    char *privhex;
     19    char *our_pubhex;
     20    char *their_pubhex;
     21    char *common_key;
     22    char *name;
     23 } ECDH_KAT;
     24 
     25 typedef struct {
     26    ECCurveName curve;
     27    char *point;
     28    char *name;
     29 } ECDH_BAD;
     30 
     31 #include "testvecs.h"
     32 
     33 void
     34 printBuf(const SECItem *item)
     35 {
     36    int i;
     37    if (!item || !item->len) {
     38        printf("(null)\n");
     39        return;
     40    }
     41 
     42    for (i = 0; i < item->len; i++) {
     43        printf("%02x", item->data[i]);
     44    }
     45    printf("\n");
     46 }
     47 
     48 /* Initialise test with basic curve populate with only the necessary things */
     49 SECStatus
     50 init_params(ECParams *ecParams, ECCurveName curve, PLArenaPool **arena)
     51 {
     52    if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve)) {
     53        return SECFailure;
     54    }
     55    *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     56    if (!*arena) {
     57        return SECFailure;
     58    }
     59    ecParams->name = curve;
     60    ecParams->type = ec_params_named;
     61    ecParams->curveOID.data = NULL;
     62    ecParams->curveOID.len = 0;
     63    ecParams->curve.seed.data = NULL;
     64    ecParams->curve.seed.len = 0;
     65    ecParams->DEREncoding.data = NULL;
     66    ecParams->DEREncoding.len = 0;
     67    ecParams->arena = *arena;
     68    ecParams->fieldID.size = ecCurve_map[curve]->size;
     69    ecParams->fieldID.type = ec_field_plain;
     70    ecParams->cofactor = ecCurve_map[curve]->cofactor;
     71 
     72    return SECSuccess;
     73 }
     74 
     75 SECStatus
     76 ectest_ecdh_kat(ECDH_KAT *kat)
     77 {
     78    ECCurveName curve = kat->curve;
     79    ECParams ecParams = { 0 };
     80    ECPrivateKey *ecPriv = NULL;
     81    SECItem theirKey = { siBuffer, NULL, 0 };
     82    SECStatus rv = SECFailure;
     83    PLArenaPool *arena = NULL;
     84    SECItem seed = { siBuffer, NULL, 0 };
     85    SECItem answer = { siBuffer, NULL, 0 };
     86    SECItem answer2 = { siBuffer, NULL, 0 };
     87    SECItem derived = { siBuffer, NULL, 0 };
     88    SECItem ecEncodedParams = { siBuffer, NULL, 0 };
     89    int i;
     90 
     91    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     92    if (!arena) {
     93        return SECFailure;
     94    }
     95 
     96    rv = SECU_ecName2params(curve, &ecEncodedParams);
     97    if (rv != SECSuccess) {
     98        goto cleanup;
     99    }
    100    EC_FillParams(arena, &ecEncodedParams, &ecParams);
    101 
    102    if (kat->our_pubhex) {
    103        SECU_HexString2SECItem(arena, &answer, kat->our_pubhex);
    104    }
    105    SECU_HexString2SECItem(arena, &seed, kat->privhex);
    106    rv = EC_NewKeyFromSeed(&ecParams, &ecPriv, seed.data, seed.len);
    107    if (rv != SECSuccess) {
    108        rv = SECFailure;
    109        goto cleanup;
    110    }
    111    if (kat->our_pubhex) {
    112        if (SECITEM_CompareItem(&answer, &ecPriv->publicValue) != SECEqual) {
    113            rv = SECFailure;
    114            goto cleanup;
    115        }
    116    }
    117 
    118    SECU_HexString2SECItem(arena, &theirKey, kat->their_pubhex);
    119    SECU_HexString2SECItem(arena, &answer2, kat->common_key);
    120 
    121    rv = EC_ValidatePublicKey(&ecParams, &theirKey);
    122    if (rv != SECSuccess) {
    123        printf("EC_ValidatePublicKey failed\n");
    124        goto cleanup;
    125    }
    126 
    127    for (i = 0; i < kat->iterations; ++i) {
    128        rv = ECDH_Derive(&theirKey, &ecParams, &ecPriv->privateValue, PR_TRUE, &derived);
    129        if (rv != SECSuccess) {
    130            rv = SECFailure;
    131            goto cleanup;
    132        }
    133        rv = SECITEM_CopyItem(ecParams.arena, &theirKey, &ecPriv->privateValue);
    134        if (rv != SECSuccess) {
    135            goto cleanup;
    136        }
    137        rv = SECITEM_CopyItem(ecParams.arena, &ecPriv->privateValue, &derived);
    138        if (rv != SECSuccess) {
    139            goto cleanup;
    140        }
    141        SECITEM_FreeItem(&derived, PR_FALSE);
    142    }
    143 
    144    if (SECITEM_CompareItem(&answer2, &ecPriv->privateValue) != SECEqual) {
    145        printf("expected: ");
    146        printBuf(&answer2);
    147        printf("derived:  ");
    148        printBuf(&ecPriv->privateValue);
    149        rv = SECFailure;
    150        goto cleanup;
    151    }
    152 
    153 cleanup:
    154    SECITEM_FreeItem(&ecEncodedParams, PR_FALSE);
    155    PORT_FreeArena(arena, PR_FALSE);
    156    if (ecPriv) {
    157        PORT_FreeArena(ecPriv->ecParams.arena, PR_FALSE);
    158    }
    159    if (derived.data) {
    160        SECITEM_FreeItem(&derived, PR_FALSE);
    161    }
    162    return rv;
    163 }
    164 
    165 SECStatus
    166 ectest_validate_point(ECDH_BAD *bad)
    167 {
    168    ECParams ecParams = { 0 };
    169    SECItem point = { siBuffer, NULL, 0 };
    170    SECStatus rv = SECFailure;
    171    PLArenaPool *arena = NULL;
    172 
    173    rv = init_params(&ecParams, bad->curve, &arena);
    174    if (rv != SECSuccess) {
    175        return rv;
    176    }
    177 
    178    SECU_HexString2SECItem(arena, &point, bad->point);
    179    rv = EC_ValidatePublicKey(&ecParams, &point);
    180 
    181    PORT_FreeArena(arena, PR_FALSE);
    182    return rv;
    183 }
    184 
    185 void
    186 printUsage(char *prog)
    187 {
    188    printf("Usage: %s [-fp] [-nd]\n"
    189           "\t-n: NIST curves\n"
    190           "\t-d: non-NIST curves\n"
    191           "You have to specify at at least one of n or d.\n"
    192           "By default no tests are executed.\n",
    193           prog);
    194 }
    195 
    196 /* Performs tests of elliptic curve cryptography over prime fields If
    197 * tests fail, then it prints an error message, aborts, and returns an
    198 * error code. Otherwise, returns 0. */
    199 int
    200 main(int argv, char **argc)
    201 {
    202    SECStatus rv = SECSuccess;
    203    int numkats = 0;
    204    int i = 0;
    205    int nist = 0;
    206    int nonnist = 0;
    207 
    208    for (i = 1; i < argv; i++) {
    209        if (PL_strcasecmp(argc[i], "-n") == 0) {
    210            nist = 1;
    211        } else if (PL_strcasecmp(argc[i], "-d") == 0) {
    212            nonnist = 1;
    213        } else {
    214            printUsage(argc[0]);
    215            return 1;
    216        }
    217    }
    218    if (!nist && !nonnist) {
    219        printUsage(argc[0]);
    220        return 1;
    221    }
    222 
    223    rv = SECOID_Init();
    224    if (rv != SECSuccess) {
    225        SECU_PrintError("Error:", "SECOID_Init");
    226        goto cleanup;
    227    }
    228 
    229    /* Test P256, P384, P521 */
    230    if (nist) {
    231        while (ecdh_testvecs[numkats].curve != ECCurve_pastLastCurve) {
    232            numkats++;
    233        }
    234        printf("1..%d\n", numkats);
    235        for (i = 0; ecdh_testvecs[i].curve != ECCurve_pastLastCurve; i++) {
    236            if (ectest_ecdh_kat(&ecdh_testvecs[i]) != SECSuccess) {
    237                printf("not okay %d - %s\n", i + 1, ecdh_testvecs[i].name);
    238                rv = SECFailure;
    239            } else {
    240                printf("okay %d - %s\n", i + 1, ecdh_testvecs[i].name);
    241            }
    242        }
    243    }
    244 
    245    /* Test KAT for non-NIST curves */
    246    if (nonnist) {
    247        for (i = 0; nonnist_testvecs[i].curve != ECCurve_pastLastCurve; i++) {
    248            if (ectest_ecdh_kat(&nonnist_testvecs[i]) != SECSuccess) {
    249                printf("not okay %d - %s\n", i + 1, nonnist_testvecs[i].name);
    250                rv = SECFailure;
    251            } else {
    252                printf("okay %d - %s\n", i + 1, nonnist_testvecs[i].name);
    253            }
    254        }
    255        for (i = 0; nonnist_testvecs_bad_values[i].curve != ECCurve_pastLastCurve; i++) {
    256            if (ectest_validate_point(&nonnist_testvecs_bad_values[i]) == SECSuccess) {
    257                printf("not okay %d - %s\n", i + 1, nonnist_testvecs_bad_values[i].name);
    258                rv = SECFailure;
    259            } else {
    260                printf("okay %d - %s\n", i + 1, nonnist_testvecs_bad_values[i].name);
    261            }
    262        }
    263    }
    264 
    265 cleanup:
    266    rv |= SECOID_Shutdown();
    267 
    268    if (rv != SECSuccess) {
    269        printf("Error: exiting with error value\n");
    270    }
    271    return rv;
    272 }