tor-browser

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

ecp_secp384r1.c (9364B)


      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 "ecl-priv.h"
     10 #include "secitem.h"
     11 #include "secerr.h"
     12 #include "secmpi.h"
     13 #include "../verified/Hacl_P384.h"
     14 
     15 /*
     16 * Point Validation for P-384.
     17 */
     18 
     19 SECStatus
     20 ec_secp384r1_pt_validate(const SECItem *pt)
     21 {
     22    SECStatus res = SECSuccess;
     23    if (!pt || !pt->data) {
     24        PORT_SetError(SEC_ERROR_INVALID_ARGS);
     25        res = SECFailure;
     26        return res;
     27    }
     28 
     29    if (pt->len != 97) {
     30        PORT_SetError(SEC_ERROR_BAD_KEY);
     31        res = SECFailure;
     32        return res;
     33    }
     34 
     35    if (pt->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
     36        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
     37        res = SECFailure;
     38        return res;
     39    }
     40 
     41 #ifndef UNSAFE_FUZZER_MODE
     42    bool b = Hacl_P384_validate_public_key(pt->data + 1);
     43 #else
     44    bool b = PR_TRUE;
     45 #endif
     46 
     47    if (!b) {
     48        PORT_SetError(SEC_ERROR_BAD_KEY);
     49        res = SECFailure;
     50    }
     51    return res;
     52 }
     53 
     54 /*
     55 * Scalar Validation for P-384.
     56 */
     57 
     58 SECStatus
     59 ec_secp384r1_scalar_validate(const SECItem *scalar)
     60 {
     61    SECStatus res = SECSuccess;
     62    if (!scalar || !scalar->data) {
     63        PORT_SetError(SEC_ERROR_INVALID_ARGS);
     64        res = SECFailure;
     65        return res;
     66    }
     67 
     68    if (scalar->len != 48) {
     69        PORT_SetError(SEC_ERROR_BAD_KEY);
     70        res = SECFailure;
     71        return res;
     72    }
     73 
     74 #ifndef UNSAFE_FUZZER_MODE
     75    bool b = Hacl_P384_validate_private_key(scalar->data);
     76 #else
     77    bool b = PR_TRUE;
     78 #endif
     79 
     80    if (!b) {
     81        PORT_SetError(SEC_ERROR_BAD_KEY);
     82        res = SECFailure;
     83    }
     84    return res;
     85 }
     86 
     87 /*
     88 * Scalar multiplication for P-384.
     89 * If P == NULL, the base point is used.
     90 * Returns X = k*P
     91 */
     92 
     93 SECStatus
     94 ec_secp384r1_pt_mul(SECItem *X, SECItem *k, SECItem *P)
     95 {
     96    SECStatus res = SECSuccess;
     97    if (!P) {
     98        uint8_t derived[96] = { 0 };
     99 
    100        if (!X || !k || !X->data || !k->data ||
    101            X->len < 97 || k->len != 48) {
    102            PORT_SetError(SEC_ERROR_INVALID_ARGS);
    103            res = SECFailure;
    104            return res;
    105        }
    106 
    107 #ifndef UNSAFE_FUZZER_MODE
    108        bool b = Hacl_P384_dh_initiator(derived, k->data);
    109 #else
    110        bool b = PR_TRUE;
    111 #endif
    112 
    113        if (!b) {
    114            PORT_SetError(SEC_ERROR_BAD_KEY);
    115            res = SECFailure;
    116            return res;
    117        }
    118 
    119        X->len = 97;
    120        X->data[0] = EC_POINT_FORM_UNCOMPRESSED;
    121        memcpy(X->data + 1, derived, 96);
    122 
    123    } else {
    124        uint8_t full_key[48] = { 0 };
    125        uint8_t *key;
    126        uint8_t derived[96] = { 0 };
    127 
    128        if (!X || !k || !P || !X->data || !k->data || !P->data ||
    129            X->len < 48 || P->len != 97 ||
    130            P->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
    131            PORT_SetError(SEC_ERROR_INVALID_ARGS);
    132            res = SECFailure;
    133            return res;
    134        }
    135 
    136        /* We consider keys of up to size 48, or of size 49 with a single leading 0 */
    137        if (k->len < 48) {
    138            memcpy(full_key + 48 - k->len, k->data, k->len);
    139            key = full_key;
    140        } else if (k->len == 48) {
    141            key = k->data;
    142        } else if (k->len == 49 && k->data[0] == 0) {
    143            key = k->data + 1;
    144        } else {
    145            PORT_SetError(SEC_ERROR_INVALID_ARGS);
    146            res = SECFailure;
    147            return res;
    148        }
    149 
    150 #ifndef UNSAFE_FUZZER_MODE
    151        bool b = Hacl_P384_dh_responder(derived, P->data + 1, key);
    152 #else
    153        bool b = key != NULL; /* Avoiding unused variable warnings */
    154 #endif
    155 
    156        if (!b) {
    157            PORT_SetError(SEC_ERROR_BAD_KEY);
    158            res = SECFailure;
    159            return res;
    160        }
    161 
    162        X->len = 48;
    163        memcpy(X->data, derived, 48);
    164    }
    165 
    166    return res;
    167 }
    168 
    169 /*
    170 * ECDSA Signature for P-384
    171 */
    172 
    173 SECStatus
    174 ec_secp384r1_sign_digest(ECPrivateKey *ecPrivKey, SECItem *signature,
    175                         const SECItem *digest, const unsigned char *kb,
    176                         const unsigned int kblen)
    177 {
    178    SECStatus res = SECSuccess;
    179 
    180    if (!ecPrivKey || !signature || !digest || !kb ||
    181        !ecPrivKey->privateValue.data ||
    182        !signature->data || !digest->data ||
    183        ecPrivKey->ecParams.name != ECCurve_NIST_P384) {
    184        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    185        res = SECFailure;
    186        return res;
    187    }
    188 
    189    if (kblen == 0 || digest->len == 0 || signature->len < 96) {
    190        PORT_SetError(SEC_ERROR_INPUT_LEN);
    191        res = SECFailure;
    192        return res;
    193    }
    194 
    195    // Private keys should be 48 bytes, but some software trims leading zeros,
    196    // and some software produces 49 byte keys with a leading zero. We'll
    197    // accept these variants.
    198    uint8_t padded_key_data[48] = { 0 };
    199    uint8_t *key;
    200    SECItem *privKey = &ecPrivKey->privateValue;
    201    if (privKey->len == 48) {
    202        key = privKey->data;
    203    } else if (privKey->len == 49 && privKey->data[0] == 0) {
    204        key = privKey->data + 1;
    205    } else if (privKey->len < 48) {
    206        memcpy(padded_key_data + 48 - privKey->len, privKey->data, privKey->len);
    207        key = padded_key_data;
    208    } else {
    209        PORT_SetError(SEC_ERROR_INPUT_LEN);
    210        return SECFailure;
    211    }
    212 
    213    uint8_t hash[48] = { 0 };
    214    if (digest->len < 48) {
    215        memcpy(hash + 48 - digest->len, digest->data, digest->len);
    216    } else {
    217        memcpy(hash, digest->data, 48);
    218    }
    219 
    220    uint8_t nonce[48] = { 0 };
    221    if (kblen < 48) {
    222        memcpy(nonce + 48 - kblen, kb, kblen);
    223    } else {
    224        memcpy(nonce, kb, 48);
    225    }
    226 
    227 #ifndef UNSAFE_FUZZER_MODE
    228    bool b = Hacl_P384_ecdsa_sign_p384_without_hash(
    229        signature->data, 48, hash, key, nonce);
    230 #else
    231    bool b = key != NULL;     /* Avoiding unused variable warnings */
    232 #endif
    233 
    234    if (!b) {
    235        PORT_SetError(SEC_ERROR_BAD_KEY);
    236        res = SECFailure;
    237        return res;
    238    }
    239 
    240    signature->len = 96;
    241    return res;
    242 }
    243 
    244 /*
    245 * ECDSA Signature Verification for P-384
    246 */
    247 
    248 SECStatus
    249 ec_secp384r1_verify_digest(ECPublicKey *key, const SECItem *signature,
    250                           const SECItem *digest)
    251 {
    252    SECStatus res = SECSuccess;
    253 
    254    if (!key || !signature || !digest ||
    255        !key->publicValue.data ||
    256        !signature->data || !digest->data ||
    257        key->ecParams.name != ECCurve_NIST_P384) {
    258        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    259        res = SECFailure;
    260        return res;
    261    }
    262 
    263    if (signature->len == 0 || signature->len % 2 != 0 ||
    264        signature->len > 96 || digest->len == 0 ||
    265        key->publicValue.len != 97) {
    266        PORT_SetError(SEC_ERROR_INPUT_LEN);
    267        res = SECFailure;
    268        return res;
    269    }
    270 
    271    if (key->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
    272        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
    273        res = SECFailure;
    274        return res;
    275    }
    276 
    277    // Signatures should be 96 bytes, but some software produces short signatures.
    278    // Pad components with zeros if necessary.
    279    uint8_t paddedSigData[96] = { 0 };
    280    uint8_t *sig;
    281    if (signature->len != 96) {
    282        size_t split = signature->len / 2;
    283 
    284        memcpy(paddedSigData + 48 - split, signature->data, split);
    285        memcpy(paddedSigData + 96 - split, signature->data + split, split);
    286 
    287        sig = paddedSigData;
    288    } else {
    289        sig = signature->data;
    290    }
    291 
    292    uint8_t hash[48] = { 0 };
    293    if (digest->len < 48) {
    294        memcpy(hash + 48 - digest->len, digest->data, digest->len);
    295    } else {
    296        memcpy(hash, digest->data, 48);
    297    }
    298 
    299 #ifndef UNSAFE_FUZZER_MODE
    300    bool b = Hacl_P384_ecdsa_verif_without_hash(
    301        48, hash, key->publicValue.data + 1, sig, sig + 48);
    302 #else
    303    bool b = sig != NULL;     /* Avoiding unused variable warnings */
    304 #endif
    305 
    306    if (!b) {
    307        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
    308        res = SECFailure;
    309        return res;
    310    }
    311 
    312    return res;
    313 }
    314 
    315 /*
    316    Point decompression for P-384.
    317 
    318    publicCompressed must be 49 bytes (1 byte for a sign and 48 bytes for the x coordinate.
    319    publicUncompressed must be 96 bytes (48 * 2).
    320    The function returns SECSuccess if the decompression was success and the decompresse
    321    point is a valid P-384 curve point.
    322 */
    323 
    324 SECStatus
    325 ec_secp384r1_decompress(const SECItem *publicCompressed, SECItem *publicUncompressed)
    326 {
    327    if (!publicCompressed || !publicCompressed->data) {
    328        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    329        return SECFailure;
    330    }
    331 
    332    if (publicCompressed->len != 49) {
    333        PORT_SetError(SEC_ERROR_BAD_KEY);
    334        return SECFailure;
    335    }
    336 
    337    if (!publicUncompressed || !publicUncompressed->data) {
    338        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    339        return SECFailure;
    340    }
    341 
    342    if (publicUncompressed->len != 97) {
    343        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    344        return SECFailure;
    345    }
    346 
    347    if (publicCompressed->data[0] != EC_POINT_FORM_COMPRESSED_Y0 &&
    348        publicCompressed->data[0] != EC_POINT_FORM_COMPRESSED_Y1) {
    349        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
    350        return SECFailure;
    351    }
    352 
    353    bool b = Hacl_P384_compressed_to_raw(publicCompressed->data, publicUncompressed->data + 1);
    354 
    355    if (!b) {
    356        PORT_SetError(SEC_ERROR_BAD_KEY);
    357        return SECFailure;
    358    }
    359 
    360    publicUncompressed->data[0] = EC_POINT_FORM_UNCOMPRESSED;
    361    return SECSuccess;
    362 }