tor-browser

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

ecdecode.c (8886B)


      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 #ifdef FREEBL_NO_DEPEND
      6 #include "stubs.h"
      7 #endif
      8 
      9 #include "blapi.h"
     10 #include "secoid.h"
     11 #include "secitem.h"
     12 #include "secerr.h"
     13 #include "ec.h"
     14 #include "ecl-curve.h"
     15 
     16 #define CHECK_OK(func) \
     17    if (func == NULL)  \
     18    goto cleanup
     19 #define CHECK_SEC_OK(func)         \
     20    if (SECSuccess != (rv = func)) \
     21    goto cleanup
     22 
     23 /* Copy all of the fields from srcParams into dstParams
     24 */
     25 SECStatus
     26 EC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
     27              const ECParams *srcParams)
     28 {
     29    SECStatus rv = SECFailure;
     30 
     31    dstParams->arena = arena;
     32    dstParams->type = srcParams->type;
     33    dstParams->fieldID.size = srcParams->fieldID.size;
     34    dstParams->fieldID.type = srcParams->fieldID.type;
     35    CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.prime,
     36                                  &srcParams->fieldID.u.prime));
     37    dstParams->fieldID.k1 = srcParams->fieldID.k1;
     38    dstParams->fieldID.k2 = srcParams->fieldID.k2;
     39    dstParams->fieldID.k3 = srcParams->fieldID.k3;
     40    CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.a,
     41                                  &srcParams->curve.a));
     42    CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.b,
     43                                  &srcParams->curve.b));
     44    CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.seed,
     45                                  &srcParams->curve.seed));
     46    CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->base,
     47                                  &srcParams->base));
     48    CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->order,
     49                                  &srcParams->order));
     50    CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->DEREncoding,
     51                                  &srcParams->DEREncoding));
     52    dstParams->name = srcParams->name;
     53    CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curveOID,
     54                                  &srcParams->curveOID));
     55    dstParams->cofactor = srcParams->cofactor;
     56 
     57    return SECSuccess;
     58 
     59 cleanup:
     60    return SECFailure;
     61 }
     62 
     63 static SECStatus
     64 gf_populate_params_bytes(ECCurveName name, ECFieldType field_type, ECParams *params)
     65 {
     66    SECStatus rv = SECFailure;
     67    const ECCurveBytes *curveParams;
     68 
     69    if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve))
     70        goto cleanup;
     71    params->name = name;
     72    curveParams = ecCurve_map[params->name];
     73    CHECK_OK(curveParams);
     74    params->fieldID.size = curveParams->size;
     75    params->fieldID.type = field_type;
     76    if (field_type != ec_field_plain) {
     77        return SECFailure;
     78    }
     79    params->fieldID.u.prime.len = curveParams->scalarSize;
     80    params->fieldID.u.prime.data = (unsigned char *)curveParams->irr;
     81    params->curve.a.len = curveParams->scalarSize;
     82    params->curve.a.data = (unsigned char *)curveParams->curvea;
     83    params->curve.b.len = curveParams->scalarSize;
     84    params->curve.b.data = (unsigned char *)curveParams->curveb;
     85    params->base.len = curveParams->pointSize;
     86    params->base.data = (unsigned char *)curveParams->base;
     87    params->order.len = curveParams->scalarSize;
     88    params->order.data = (unsigned char *)curveParams->order;
     89    params->cofactor = curveParams->cofactor;
     90 
     91    rv = SECSuccess;
     92 
     93 cleanup:
     94    return rv;
     95 }
     96 
     97 SECStatus
     98 EC_FillParams(PLArenaPool *arena, const SECItem *encodedParams,
     99              ECParams *params)
    100 {
    101    SECStatus rv = SECFailure;
    102    SECOidTag tag;
    103    SECItem oid = { siBuffer, NULL, 0 };
    104 
    105 #if EC_DEBUG
    106    int i;
    107 
    108    printf("Encoded params in EC_DecodeParams: ");
    109    for (i = 0; i < encodedParams->len; i++) {
    110        printf("%02x:", encodedParams->data[i]);
    111    }
    112    printf("\n");
    113 #endif
    114 
    115    if ((encodedParams->len != ANSI_X962_CURVE_OID_TOTAL_LEN) &&
    116        (encodedParams->len != SECG_CURVE_OID_TOTAL_LEN) &&
    117        (encodedParams->len != PKIX_NEWCURVES_OID_TOTAL_LEN) &&
    118        (encodedParams->len != ED25519_OID_TOTAL_LEN)) {
    119        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
    120        return SECFailure;
    121    };
    122 
    123    oid.len = encodedParams->len - 2;
    124    oid.data = encodedParams->data + 2;
    125    if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) ||
    126        ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) {
    127        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
    128        return SECFailure;
    129    }
    130 
    131    params->arena = arena;
    132    params->cofactor = 0;
    133    params->type = ec_params_named;
    134    params->name = ECCurve_noName;
    135 
    136    /* Fill out curveOID */
    137    params->curveOID.len = oid.len;
    138    params->curveOID.data = (unsigned char *)PORT_ArenaAlloc(arena, oid.len);
    139    if (params->curveOID.data == NULL)
    140        goto cleanup;
    141    memcpy(params->curveOID.data, oid.data, oid.len);
    142 
    143 #if EC_DEBUG
    144    printf("Curve: %s\n", SECOID_FindOIDTagDescription(tag));
    145 #endif
    146 
    147    switch (tag) {
    148        case SEC_OID_ANSIX962_EC_PRIME256V1:
    149            /* Populate params for prime256v1 aka secp256r1
    150             * (the NIST P-256 curve)
    151             */
    152            CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_X9_62_PRIME_256V1,
    153                                                  ec_field_plain, params));
    154            break;
    155 
    156        case SEC_OID_SECG_EC_SECP384R1:
    157            /* Populate params for secp384r1
    158             * (the NIST P-384 curve)
    159             */
    160            CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_SECG_PRIME_384R1,
    161                                                  ec_field_plain, params));
    162            break;
    163 
    164        case SEC_OID_SECG_EC_SECP521R1:
    165            /* Populate params for secp521r1
    166             * (the NIST P-521 curve)
    167             */
    168            CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_SECG_PRIME_521R1,
    169                                                  ec_field_plain, params));
    170            break;
    171 
    172        case SEC_OID_ED25519_PUBLIC_KEY:
    173            params->type = ec_params_edwards_named;
    174            CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_Ed25519,
    175                                                  ec_field_plain, params));
    176 
    177            break;
    178 
    179        case SEC_OID_X25519:
    180        case SEC_OID_CURVE25519:
    181            /* Populate params for Curve25519 */
    182            params->type = ec_params_montgomery_named;
    183            CHECK_SEC_OK(gf_populate_params_bytes(ECCurve25519,
    184                                                  ec_field_plain,
    185                                                  params));
    186            break;
    187 
    188        default:
    189            break;
    190    };
    191 
    192 cleanup:
    193    if (!params->cofactor) {
    194        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
    195 #if EC_DEBUG
    196        printf("Unrecognized curve, returning NULL params\n");
    197 #endif
    198    }
    199 
    200    return rv;
    201 }
    202 
    203 SECStatus
    204 EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams)
    205 {
    206    PLArenaPool *arena;
    207    ECParams *params;
    208    SECStatus rv = SECFailure;
    209 
    210    /* Initialize an arena for the ECParams structure */
    211    if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
    212        return SECFailure;
    213 
    214    params = (ECParams *)PORT_ArenaZAlloc(arena, sizeof(ECParams));
    215    if (!params) {
    216        PORT_FreeArena(arena, PR_TRUE);
    217        return SECFailure;
    218    }
    219 
    220    /* Copy the encoded params */
    221    SECITEM_AllocItem(arena, &(params->DEREncoding),
    222                      encodedParams->len);
    223    memcpy(params->DEREncoding.data, encodedParams->data, encodedParams->len);
    224 
    225    /* Fill out the rest of the ECParams structure based on
    226     * the encoded params
    227     */
    228    rv = EC_FillParams(arena, encodedParams, params);
    229    if (rv == SECFailure) {
    230        PORT_FreeArena(arena, PR_TRUE);
    231        return SECFailure;
    232    } else {
    233        *ecparams = params;
    234        ;
    235        return SECSuccess;
    236    }
    237 }
    238 
    239 int
    240 EC_GetPointSize(const ECParams *params)
    241 {
    242    ECCurveName name = params->name;
    243    const ECCurveBytes *curveParams;
    244 
    245    if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve) ||
    246        ((curveParams = ecCurve_map[name]) == NULL)) {
    247        /* unknown curve, calculate point size from params. assume standard curves with 2 points
    248         * and a point compression indicator byte */
    249        int sizeInBytes = (params->fieldID.size + 7) / 8;
    250        return sizeInBytes * 2 + 1;
    251    }
    252 
    253    if (params->type == ec_params_edwards_named || params->type == ec_params_montgomery_named) {
    254        return curveParams->scalarSize;
    255    }
    256 
    257    return curveParams->pointSize - 1;
    258 }
    259 
    260 int
    261 EC_GetScalarSize(const ECParams *params)
    262 {
    263    ECCurveName name = params->name;
    264    const ECCurveBytes *curveParams;
    265 
    266    if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve) ||
    267        ((curveParams = ecCurve_map[name]) == NULL)) {
    268        /* unknown curve, calculate scalar size from field size in params */
    269        int sizeInBytes = (params->fieldID.size + 7) / 8;
    270        return sizeInBytes;
    271    }
    272    return curveParams->scalarSize;
    273 }