tor-browser

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

lowkey.c (14193B)


      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 #include "lowkeyi.h"
      5 #include "secoid.h"
      6 #include "secitem.h"
      7 #include "secder.h"
      8 #include "secasn1.h"
      9 #include "secerr.h"
     10 
     11 SEC_ASN1_MKSUB(SEC_AnyTemplate)
     12 SEC_ASN1_MKSUB(SEC_BitStringTemplate)
     13 SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
     14 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
     15 
     16 static const SEC_ASN1Template nsslowkey_AttributeTemplate[] = {
     17    { SEC_ASN1_SEQUENCE,
     18      0, NULL, sizeof(NSSLOWKEYAttribute) },
     19    { SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) },
     20    { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(NSSLOWKEYAttribute, attrValue),
     21      SEC_ASN1_SUB(SEC_AnyTemplate) },
     22    { 0 }
     23 };
     24 
     25 static const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = {
     26    { SEC_ASN1_SET_OF, 0, nsslowkey_AttributeTemplate },
     27 };
     28 /* ASN1 Templates for new decoder/encoder */
     29 const SEC_ASN1Template lg_nsslowkey_PrivateKeyInfoTemplate[] = {
     30    { SEC_ASN1_SEQUENCE,
     31      0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) },
     32    { SEC_ASN1_INTEGER,
     33      offsetof(NSSLOWKEYPrivateKeyInfo, version) },
     34    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
     35      offsetof(NSSLOWKEYPrivateKeyInfo, algorithm),
     36      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
     37    { SEC_ASN1_OCTET_STRING,
     38      offsetof(NSSLOWKEYPrivateKeyInfo, privateKey) },
     39    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
     40      offsetof(NSSLOWKEYPrivateKeyInfo, attributes),
     41      nsslowkey_SetOfAttributeTemplate },
     42    { 0 }
     43 };
     44 
     45 const SEC_ASN1Template lg_nsslowkey_PQGParamsTemplate[] = {
     46    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },
     47    { SEC_ASN1_INTEGER, offsetof(PQGParams, prime) },
     48    { SEC_ASN1_INTEGER, offsetof(PQGParams, subPrime) },
     49    { SEC_ASN1_INTEGER, offsetof(PQGParams, base) },
     50    { 0 }
     51 };
     52 
     53 const SEC_ASN1Template lg_nsslowkey_RSAPrivateKeyTemplate[] = {
     54    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
     55    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.version) },
     56    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.modulus) },
     57    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.publicExponent) },
     58    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.privateExponent) },
     59    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime1) },
     60    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime2) },
     61    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent1) },
     62    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent2) },
     63    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.coefficient) },
     64    { 0 }
     65 };
     66 
     67 /*
     68 * Allows u.rsa.modulus to be zero length for secret keys with an empty
     69 * CKA_ID incorrectly generated in NSS 3.13.3 or earlier.  Only used for
     70 * decoding.  See bug 715073.
     71 */
     72 const SEC_ASN1Template lg_nsslowkey_RSAPrivateKeyTemplate2[] = {
     73    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
     74    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.version) },
     75    { SEC_ASN1_ANY, offsetof(NSSLOWKEYPrivateKey, u.rsa.modulus) },
     76    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.publicExponent) },
     77    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.privateExponent) },
     78    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime1) },
     79    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime2) },
     80    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent1) },
     81    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent2) },
     82    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.coefficient) },
     83    { 0 }
     84 };
     85 
     86 const SEC_ASN1Template lg_nsslowkey_DSAPrivateKeyTemplate[] = {
     87    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
     88    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dsa.publicValue) },
     89    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dsa.privateValue) },
     90    { 0 }
     91 };
     92 
     93 const SEC_ASN1Template lg_nsslowkey_DHPrivateKeyTemplate[] = {
     94    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
     95    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.publicValue) },
     96    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.privateValue) },
     97    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.base) },
     98    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.prime) },
     99    { 0 }
    100 };
    101 
    102 /* NOTE: The SECG specification allows the private key structure
    103 * to contain curve parameters but recommends that they be stored
    104 * in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo
    105 * instead.
    106 */
    107 const SEC_ASN1Template lg_nsslowkey_ECPrivateKeyTemplate[] = {
    108    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
    109    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.ec.version) },
    110    { SEC_ASN1_OCTET_STRING,
    111      offsetof(NSSLOWKEYPrivateKey, u.ec.privateValue) },
    112    /* We only support named curves for which the parameters are
    113     * encoded as an object ID.
    114     */
    115    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
    116          SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
    117      offsetof(NSSLOWKEYPrivateKey, u.ec.ecParams.curveOID),
    118      SEC_ASN1_SUB(SEC_ObjectIDTemplate) },
    119    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
    120          SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC |
    121          SEC_ASN1_XTRN | 1,
    122      offsetof(NSSLOWKEYPrivateKey, u.ec.publicValue),
    123      SEC_ASN1_SUB(SEC_BitStringTemplate) },
    124    { 0 }
    125 };
    126 
    127 /*
    128 * smaller version of EC_FillParams. In this code, we only need
    129 * oid and DER data.
    130 */
    131 SECStatus
    132 LGEC_FillParams(PLArenaPool *arena, const SECItem *encodedParams,
    133                ECParams *params)
    134 {
    135    SECOidTag tag;
    136    SECItem oid = { siBuffer, NULL, 0 };
    137 
    138 #if EC_DEBUG
    139    int i;
    140 
    141    printf("Encoded params in EC_DecodeParams: ");
    142    for (i = 0; i < encodedParams->len; i++) {
    143        printf("%02x:", encodedParams->data[i]);
    144    }
    145    printf("\n");
    146 #endif
    147 
    148    oid.len = encodedParams->len - 2;
    149    oid.data = encodedParams->data + 2;
    150    if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) ||
    151        ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)) {
    152        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
    153        return SECFailure;
    154    }
    155 
    156    params->arena = arena;
    157 
    158    /* For named curves, fill out curveOID */
    159    params->curveOID.len = oid.len;
    160    params->curveOID.data = (unsigned char *)PORT_ArenaAlloc(arena, oid.len);
    161    if (params->curveOID.data == NULL) {
    162        return SECFailure;
    163    }
    164    memcpy(params->curveOID.data, oid.data, oid.len);
    165 
    166    return SECSuccess;
    167 }
    168 
    169 /* Copy all of the fields from srcParams into dstParams
    170 */
    171 SECStatus
    172 LGEC_CopyParams(PLArenaPool *arena, ECParams *dstParams,
    173                const ECParams *srcParams)
    174 {
    175    SECStatus rv = SECFailure;
    176 
    177    dstParams->arena = arena;
    178    rv = SECITEM_CopyItem(arena, &dstParams->DEREncoding,
    179                          &srcParams->DEREncoding);
    180    if (rv != SECSuccess) {
    181        goto loser;
    182    }
    183    rv = SECITEM_CopyItem(arena, &dstParams->curveOID,
    184                          &srcParams->curveOID);
    185    if (rv != SECSuccess) {
    186        goto loser;
    187    }
    188 
    189    return SECSuccess;
    190 
    191 loser:
    192    return SECFailure;
    193 }
    194 /*
    195 * See bugzilla bug 125359
    196 * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
    197 * all of the templates above that en/decode into integers must be converted
    198 * from ASN.1's signed integer type.  This is done by marking either the
    199 * source or destination (encoding or decoding, respectively) type as
    200 * siUnsignedInteger.
    201 */
    202 
    203 void
    204 lg_prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
    205 {
    206    key->u.rsa.modulus.type = siUnsignedInteger;
    207    key->u.rsa.publicExponent.type = siUnsignedInteger;
    208    key->u.rsa.privateExponent.type = siUnsignedInteger;
    209    key->u.rsa.prime1.type = siUnsignedInteger;
    210    key->u.rsa.prime2.type = siUnsignedInteger;
    211    key->u.rsa.exponent1.type = siUnsignedInteger;
    212    key->u.rsa.exponent2.type = siUnsignedInteger;
    213    key->u.rsa.coefficient.type = siUnsignedInteger;
    214 }
    215 
    216 void
    217 lg_prepare_low_pqg_params_for_asn1(PQGParams *params)
    218 {
    219    params->prime.type = siUnsignedInteger;
    220    params->subPrime.type = siUnsignedInteger;
    221    params->base.type = siUnsignedInteger;
    222 }
    223 
    224 void
    225 lg_prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
    226 {
    227    key->u.dsa.publicValue.type = siUnsignedInteger;
    228    key->u.dsa.privateValue.type = siUnsignedInteger;
    229    key->u.dsa.params.prime.type = siUnsignedInteger;
    230    key->u.dsa.params.subPrime.type = siUnsignedInteger;
    231    key->u.dsa.params.base.type = siUnsignedInteger;
    232 }
    233 
    234 void
    235 lg_prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
    236 {
    237    key->u.dh.prime.type = siUnsignedInteger;
    238    key->u.dh.base.type = siUnsignedInteger;
    239    key->u.dh.publicValue.type = siUnsignedInteger;
    240    key->u.dh.privateValue.type = siUnsignedInteger;
    241 }
    242 
    243 void
    244 lg_prepare_low_ecparams_for_asn1(ECParams *params)
    245 {
    246    params->DEREncoding.type = siUnsignedInteger;
    247    params->curveOID.type = siUnsignedInteger;
    248 }
    249 
    250 void
    251 lg_prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
    252 {
    253    key->u.ec.version.type = siUnsignedInteger;
    254    key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger;
    255    key->u.ec.ecParams.curveOID.type = siUnsignedInteger;
    256    key->u.ec.privateValue.type = siUnsignedInteger;
    257    key->u.ec.publicValue.type = siUnsignedInteger;
    258 }
    259 
    260 void
    261 lg_nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk)
    262 {
    263    if (privk && privk->arena) {
    264        PORT_FreeArena(privk->arena, PR_TRUE);
    265    }
    266 }
    267 
    268 void
    269 lg_nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk)
    270 {
    271    if (pubk && pubk->arena) {
    272        PORT_FreeArena(pubk->arena, PR_FALSE);
    273    }
    274 }
    275 
    276 NSSLOWKEYPublicKey *
    277 lg_nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
    278 {
    279    NSSLOWKEYPublicKey *pubk;
    280    PLArenaPool *arena;
    281 
    282    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    283    if (arena == NULL) {
    284        PORT_SetError(SEC_ERROR_NO_MEMORY);
    285        return NULL;
    286    }
    287 
    288    switch (privk->keyType) {
    289        case NSSLOWKEYRSAKey:
    290        case NSSLOWKEYNullKey:
    291            pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
    292                                                          sizeof(NSSLOWKEYPublicKey));
    293            if (pubk != NULL) {
    294                SECStatus rv;
    295 
    296                pubk->arena = arena;
    297                pubk->keyType = privk->keyType;
    298                if (privk->keyType == NSSLOWKEYNullKey)
    299                    return pubk;
    300                rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus,
    301                                      &privk->u.rsa.modulus);
    302                if (rv == SECSuccess) {
    303                    rv = SECITEM_CopyItem(arena, &pubk->u.rsa.publicExponent,
    304                                          &privk->u.rsa.publicExponent);
    305                    if (rv == SECSuccess)
    306                        return pubk;
    307                }
    308            } else {
    309                PORT_SetError(SEC_ERROR_NO_MEMORY);
    310            }
    311            break;
    312        case NSSLOWKEYDSAKey:
    313            pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
    314                                                          sizeof(NSSLOWKEYPublicKey));
    315            if (pubk != NULL) {
    316                SECStatus rv;
    317 
    318                pubk->arena = arena;
    319                pubk->keyType = privk->keyType;
    320                rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
    321                                      &privk->u.dsa.publicValue);
    322                if (rv != SECSuccess)
    323                    break;
    324                rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
    325                                      &privk->u.dsa.params.prime);
    326                if (rv != SECSuccess)
    327                    break;
    328                rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
    329                                      &privk->u.dsa.params.subPrime);
    330                if (rv != SECSuccess)
    331                    break;
    332                rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
    333                                      &privk->u.dsa.params.base);
    334                if (rv == SECSuccess)
    335                    return pubk;
    336            }
    337            break;
    338        case NSSLOWKEYDHKey:
    339            pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
    340                                                          sizeof(NSSLOWKEYPublicKey));
    341            if (pubk != NULL) {
    342                SECStatus rv;
    343 
    344                pubk->arena = arena;
    345                pubk->keyType = privk->keyType;
    346                rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
    347                                      &privk->u.dh.publicValue);
    348                if (rv != SECSuccess)
    349                    break;
    350                rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime,
    351                                      &privk->u.dh.prime);
    352                if (rv != SECSuccess)
    353                    break;
    354                rv = SECITEM_CopyItem(arena, &pubk->u.dh.base,
    355                                      &privk->u.dh.base);
    356                if (rv == SECSuccess)
    357                    return pubk;
    358            }
    359            break;
    360        case NSSLOWKEYECKey:
    361            pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
    362                                                          sizeof(NSSLOWKEYPublicKey));
    363            if (pubk != NULL) {
    364                SECStatus rv;
    365 
    366                pubk->arena = arena;
    367                pubk->keyType = privk->keyType;
    368                rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue,
    369                                      &privk->u.ec.publicValue);
    370                if (rv != SECSuccess)
    371                    break;
    372                pubk->u.ec.ecParams.arena = arena;
    373                /* Copy the rest of the params */
    374                rv = LGEC_CopyParams(arena, &(pubk->u.ec.ecParams),
    375                                     &(privk->u.ec.ecParams));
    376                if (rv == SECSuccess)
    377                    return pubk;
    378            }
    379            break;
    380        /* No Fortezza in Low Key implementations (Fortezza keys aren't
    381         * stored in our data base */
    382        default:
    383            break;
    384    }
    385 
    386    PORT_FreeArena(arena, PR_FALSE);
    387    return NULL;
    388 }