tor-browser

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

seckey.c (86681B)


      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 "cryptohi.h"
      5 #include "keyhi.h"
      6 #include "pkcs11t.h"
      7 #include "secoid.h"
      8 #include "secitem.h"
      9 #include "secder.h"
     10 #include "base64.h"
     11 #include "secasn1.h"
     12 #include "cert.h"
     13 #include "pk11func.h"
     14 #include "secerr.h"
     15 #include "secdig.h"
     16 #include "prtime.h"
     17 #include "keyi.h"
     18 #include "nss.h"
     19 
     20 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
     21 SEC_ASN1_MKSUB(SEC_IntegerTemplate)
     22 
     23 const SEC_ASN1Template CERT_SubjectPublicKeyInfoTemplate[] = {
     24    { SEC_ASN1_SEQUENCE,
     25      0, NULL, sizeof(CERTSubjectPublicKeyInfo) },
     26    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
     27      offsetof(CERTSubjectPublicKeyInfo, algorithm),
     28      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
     29    { SEC_ASN1_BIT_STRING,
     30      offsetof(CERTSubjectPublicKeyInfo, subjectPublicKey) },
     31    { 0 }
     32 };
     33 
     34 const SEC_ASN1Template CERT_PublicKeyAndChallengeTemplate[] = {
     35    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTPublicKeyAndChallenge) },
     36    { SEC_ASN1_ANY, offsetof(CERTPublicKeyAndChallenge, spki) },
     37    { SEC_ASN1_IA5_STRING, offsetof(CERTPublicKeyAndChallenge, challenge) },
     38    { 0 }
     39 };
     40 
     41 const SEC_ASN1Template SECKEY_RSAPublicKeyTemplate[] = {
     42    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) },
     43    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey, u.rsa.modulus) },
     44    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey, u.rsa.publicExponent) },
     45    { 0 }
     46 };
     47 
     48 static const SEC_ASN1Template seckey_PointerToAlgorithmIDTemplate[] = {
     49    { SEC_ASN1_POINTER | SEC_ASN1_XTRN, 0,
     50      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }
     51 };
     52 
     53 /* Parameters for SEC_OID_PKCS1_RSA_PSS_SIGNATURE */
     54 const SEC_ASN1Template SECKEY_RSAPSSParamsTemplate[] = {
     55    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRSAPSSParams) },
     56    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
     57          SEC_ASN1_CONTEXT_SPECIFIC | 0,
     58      offsetof(SECKEYRSAPSSParams, hashAlg),
     59      seckey_PointerToAlgorithmIDTemplate },
     60    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
     61          SEC_ASN1_CONTEXT_SPECIFIC | 1,
     62      offsetof(SECKEYRSAPSSParams, maskAlg),
     63      seckey_PointerToAlgorithmIDTemplate },
     64    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
     65          SEC_ASN1_XTRN | SEC_ASN1_CONTEXT_SPECIFIC | 2,
     66      offsetof(SECKEYRSAPSSParams, saltLength),
     67      SEC_ASN1_SUB(SEC_IntegerTemplate) },
     68    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT |
     69          SEC_ASN1_XTRN | SEC_ASN1_CONTEXT_SPECIFIC | 3,
     70      offsetof(SECKEYRSAPSSParams, trailerField),
     71      SEC_ASN1_SUB(SEC_IntegerTemplate) },
     72    { 0 }
     73 };
     74 
     75 const SEC_ASN1Template SECKEY_DSAPublicKeyTemplate[] = {
     76    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey, u.dsa.publicValue) },
     77    { 0 }
     78 };
     79 
     80 const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = {
     81    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPQGParams) },
     82    { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, prime) },
     83    { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, subPrime) },
     84    { SEC_ASN1_INTEGER, offsetof(SECKEYPQGParams, base) },
     85    { 0 }
     86 };
     87 
     88 const SEC_ASN1Template SECKEY_DHPublicKeyTemplate[] = {
     89    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey, u.dh.publicValue) },
     90    { 0 }
     91 };
     92 
     93 const SEC_ASN1Template SECKEY_DHParamKeyTemplate[] = {
     94    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPublicKey) },
     95    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey, u.dh.prime) },
     96    { SEC_ASN1_INTEGER, offsetof(SECKEYPublicKey, u.dh.base) },
     97    /* XXX chrisk: this needs to be expanded for decoding of j and validationParms (RFC2459 7.3.2) */
     98    { SEC_ASN1_SKIP_REST },
     99    { 0 }
    100 };
    101 
    102 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_DSAPublicKeyTemplate)
    103 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPublicKeyTemplate)
    104 SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_RSAPSSParamsTemplate)
    105 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_SubjectPublicKeyInfoTemplate)
    106 
    107 /*
    108 * See bugzilla bug 125359
    109 * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
    110 * all of the templates above that en/decode into integers must be converted
    111 * from ASN.1's signed integer type.  This is done by marking either the
    112 * source or destination (encoding or decoding, respectively) type as
    113 * siUnsignedInteger.
    114 */
    115 static void
    116 prepare_rsa_pub_key_for_asn1(SECKEYPublicKey *pubk)
    117 {
    118    pubk->u.rsa.modulus.type = siUnsignedInteger;
    119    pubk->u.rsa.publicExponent.type = siUnsignedInteger;
    120 }
    121 
    122 static void
    123 prepare_dsa_pub_key_for_asn1(SECKEYPublicKey *pubk)
    124 {
    125    pubk->u.dsa.publicValue.type = siUnsignedInteger;
    126 }
    127 
    128 static void
    129 prepare_pqg_params_for_asn1(SECKEYPQGParams *params)
    130 {
    131    params->prime.type = siUnsignedInteger;
    132    params->subPrime.type = siUnsignedInteger;
    133    params->base.type = siUnsignedInteger;
    134 }
    135 
    136 static void
    137 prepare_dh_pub_key_for_asn1(SECKEYPublicKey *pubk)
    138 {
    139    pubk->u.dh.prime.type = siUnsignedInteger;
    140    pubk->u.dh.base.type = siUnsignedInteger;
    141    pubk->u.dh.publicValue.type = siUnsignedInteger;
    142 }
    143 
    144 static const char *const keyTypeName[] = {
    145    "null", "rsa", "dsa", "fortezza", "dh", "kea", "ec", "rsaPss", "rsaOaep",
    146    "mlkem", "ed", "ecMont", "mldsa"
    147 };
    148 static size_t keyTypeNameMax = PR_ARRAY_SIZE(keyTypeName);
    149 
    150 const char *
    151 SECKEY_GetKeyTypeString(KeyType keyType)
    152 {
    153    if (keyType < keyTypeNameMax) {
    154        return keyTypeName[keyType];
    155    }
    156    return "unknown";
    157 }
    158 
    159 /* Create an RSA key pair is any slot able to do so.
    160 ** The created keys are "session" (temporary), not "token" (permanent),
    161 ** and they are "sensitive", which makes them costly to move to another token.
    162 */
    163 SECKEYPrivateKey *
    164 SECKEY_CreateRSAPrivateKey(int keySizeInBits, SECKEYPublicKey **pubk, void *cx)
    165 {
    166    SECKEYPrivateKey *privk;
    167    PK11RSAGenParams param;
    168    PK11SlotInfo *slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN, cx);
    169    if (!slot) {
    170        return NULL;
    171    }
    172 
    173    param.keySizeInBits = keySizeInBits;
    174    param.pe = 65537L;
    175 
    176    privk = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &param, pubk,
    177                                 PR_FALSE, PR_TRUE, cx);
    178    PK11_FreeSlot(slot);
    179    return (privk);
    180 }
    181 
    182 /* Create a DH key pair in any slot able to do so,
    183 ** This is a "session" (temporary), not "token" (permanent) key.
    184 ** Because of the high probability that this key will need to be moved to
    185 ** another token, and the high cost of moving "sensitive" keys, we attempt
    186 ** to create this key pair without the "sensitive" attribute, but revert to
    187 ** creating a "sensitive" key if necessary.
    188 */
    189 SECKEYPrivateKey *
    190 SECKEY_CreateDHPrivateKey(SECKEYDHParams *param, SECKEYPublicKey **pubk, void *cx)
    191 {
    192    SECKEYPrivateKey *privk;
    193    PK11SlotInfo *slot;
    194 
    195    if (!param || !param->base.data || !param->prime.data ||
    196        SECKEY_BigIntegerBitLength(&param->prime) < DH_MIN_P_BITS ||
    197        param->base.len == 0 || param->base.len > param->prime.len + 1 ||
    198        (param->base.len == 1 && param->base.data[0] == 0)) {
    199        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    200        return NULL;
    201    }
    202 
    203    slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN, cx);
    204    if (!slot) {
    205        return NULL;
    206    }
    207 
    208    privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param,
    209                                 pubk, PR_FALSE, PR_FALSE, cx);
    210    if (!privk)
    211        privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, param,
    212                                     pubk, PR_FALSE, PR_TRUE, cx);
    213 
    214    PK11_FreeSlot(slot);
    215    return (privk);
    216 }
    217 
    218 /* Create an EC key pair in any slot able to do so,
    219 ** This is a "session" (temporary), not "token" (permanent) key.
    220 ** Because of the high probability that this key will need to be moved to
    221 ** another token, and the high cost of moving "sensitive" keys, we attempt
    222 ** to create this key pair without the "sensitive" attribute, but revert to
    223 ** creating a "sensitive" key if necessary.
    224 */
    225 SECKEYPrivateKey *
    226 SECKEY_CreateECPrivateKey(SECKEYECParams *param, SECKEYPublicKey **pubk, void *cx)
    227 {
    228    SECKEYPrivateKey *privk;
    229    PK11SlotInfo *slot = PK11_GetBestSlot(CKM_EC_KEY_PAIR_GEN, cx);
    230    if (!slot) {
    231        return NULL;
    232    }
    233 
    234    privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN,
    235                                            param, pubk,
    236                                            PK11_ATTR_SESSION |
    237                                                PK11_ATTR_INSENSITIVE |
    238                                                PK11_ATTR_PUBLIC,
    239                                            CKF_DERIVE, CKF_DERIVE | CKF_SIGN,
    240                                            cx);
    241    if (!privk)
    242        privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_KEY_PAIR_GEN,
    243                                                param, pubk,
    244                                                PK11_ATTR_SESSION |
    245                                                    PK11_ATTR_SENSITIVE |
    246                                                    PK11_ATTR_PRIVATE,
    247                                                CKF_DERIVE, CKF_DERIVE | CKF_SIGN,
    248                                                cx);
    249 
    250    PK11_FreeSlot(slot);
    251    return (privk);
    252 }
    253 
    254 SECKEYPrivateKey *
    255 SECKEY_CreateEDPrivateKey(SECKEYECParams *param, SECKEYPublicKey **pubk, void *cx)
    256 {
    257    SECKEYPrivateKey *privk;
    258    PK11SlotInfo *slot = PK11_GetBestSlot(CKM_EC_EDWARDS_KEY_PAIR_GEN, cx);
    259    if (!slot) {
    260        return NULL;
    261    }
    262 
    263    privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_EDWARDS_KEY_PAIR_GEN,
    264                                            param, pubk,
    265                                            PK11_ATTR_SESSION |
    266                                                PK11_ATTR_INSENSITIVE |
    267                                                PK11_ATTR_PUBLIC,
    268                                            CKF_SIGN, CKF_SIGN, cx);
    269    if (!privk)
    270        privk = PK11_GenerateKeyPairWithOpFlags(slot, CKM_EC_EDWARDS_KEY_PAIR_GEN,
    271                                                param, pubk,
    272                                                PK11_ATTR_SESSION |
    273                                                    PK11_ATTR_SENSITIVE |
    274                                                    PK11_ATTR_PRIVATE,
    275                                                CKF_SIGN, CKF_SIGN, cx);
    276 
    277    PK11_FreeSlot(slot);
    278    return (privk);
    279 }
    280 
    281 void
    282 SECKEY_DestroyPrivateKey(SECKEYPrivateKey *privk)
    283 {
    284    if (privk) {
    285        if (privk->pkcs11Slot) {
    286            if (privk->pkcs11IsTemp) {
    287                PK11_DestroyObject(privk->pkcs11Slot, privk->pkcs11ID);
    288            }
    289            PK11_FreeSlot(privk->pkcs11Slot);
    290        }
    291        if (privk->arena) {
    292            PORT_FreeArena(privk->arena, PR_TRUE);
    293        }
    294    }
    295 }
    296 
    297 void
    298 SECKEY_DestroyPublicKey(SECKEYPublicKey *pubk)
    299 {
    300    if (pubk) {
    301        if (pubk->pkcs11Slot) {
    302            if (!PK11_IsPermObject(pubk->pkcs11Slot, pubk->pkcs11ID)) {
    303                PK11_DestroyObject(pubk->pkcs11Slot, pubk->pkcs11ID);
    304            }
    305            PK11_FreeSlot(pubk->pkcs11Slot);
    306        }
    307        if (pubk->arena) {
    308            PORT_FreeArena(pubk->arena, PR_FALSE);
    309        }
    310    }
    311 }
    312 
    313 SECStatus
    314 SECKEY_CopySubjectPublicKeyInfo(PLArenaPool *arena,
    315                                CERTSubjectPublicKeyInfo *to,
    316                                CERTSubjectPublicKeyInfo *from)
    317 {
    318    SECStatus rv;
    319    SECItem spk;
    320 
    321    rv = SECOID_CopyAlgorithmID(arena, &to->algorithm, &from->algorithm);
    322    if (rv == SECSuccess) {
    323        /*
    324         * subjectPublicKey is a bit string, whose length is in bits.
    325         * Convert the length from bits to bytes for SECITEM_CopyItem.
    326         */
    327        spk = from->subjectPublicKey;
    328        DER_ConvertBitString(&spk);
    329        rv = SECITEM_CopyItem(arena, &to->subjectPublicKey, &spk);
    330        /* Set the length back to bits. */
    331        if (rv == SECSuccess) {
    332            to->subjectPublicKey.len = from->subjectPublicKey.len;
    333        }
    334    }
    335 
    336    return rv;
    337 }
    338 
    339 /* Procedure to update the pqg parameters for a cert's public key.
    340 * pqg parameters only need to be updated for DSA certificates.
    341 * The procedure uses calls to itself recursively to update a certificate
    342 * issuer's pqg parameters.  Some important rules are:
    343 *    - Do nothing if the cert already has PQG parameters.
    344 *    - If the cert does not have PQG parameters, obtain them from the issuer.
    345 *    - A valid cert chain cannot have a DSA cert without
    346 *      pqg parameters that has a parent that is not a DSA cert.  */
    347 
    348 static SECStatus
    349 seckey_UpdateCertPQGChain(CERTCertificate *subjectCert, int count)
    350 {
    351    SECStatus rv;
    352    SECOidData *oid = NULL;
    353    int tag;
    354    CERTSubjectPublicKeyInfo *subjectSpki = NULL;
    355    CERTSubjectPublicKeyInfo *issuerSpki = NULL;
    356    CERTCertificate *issuerCert = NULL;
    357 
    358    /* increment cert chain length counter*/
    359    count++;
    360 
    361    /* check if cert chain length exceeds the maximum length*/
    362    if (count > CERT_MAX_CERT_CHAIN) {
    363        return SECFailure;
    364    }
    365 
    366    oid = SECOID_FindOID(&subjectCert->subjectPublicKeyInfo.algorithm.algorithm);
    367    if (oid != NULL) {
    368        tag = oid->offset;
    369 
    370        /* Check if cert has a DSA or EC public key. If not, return
    371         * success since no PQG params need to be updated.
    372         *
    373         * Question: do we really need to do this for EC keys. They don't have
    374         * PQG parameters, but they do have parameters. The question is does
    375         * the child cert inherit those parameters for EC from the parent, or
    376         * do we always include those parameters in each cert.
    377         */
    378 
    379        if ((tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
    380            (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
    381            (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST) &&
    382            (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST) &&
    383            (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
    384            (tag != SEC_OID_SDN702_DSA_SIGNATURE) &&
    385            (tag != SEC_OID_ED25519_PUBLIC_KEY) &&
    386            (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY)) {
    387 
    388            return SECSuccess;
    389        }
    390    } else {
    391        return SECFailure; /* return failure if oid is NULL */
    392    }
    393 
    394    /* if cert has PQG parameters, return success */
    395 
    396    subjectSpki = &subjectCert->subjectPublicKeyInfo;
    397 
    398    if (subjectSpki->algorithm.parameters.len != 0) {
    399        return SECSuccess;
    400    }
    401 
    402    /* check if the cert is self-signed */
    403    if (subjectCert->isRoot) {
    404        /* fail since cert is self-signed and has no pqg params. */
    405        return SECFailure;
    406    }
    407 
    408    /* get issuer cert */
    409    issuerCert = CERT_FindCertIssuer(subjectCert, PR_Now(), certUsageAnyCA);
    410    if (!issuerCert) {
    411        return SECFailure;
    412    }
    413 
    414    /* if parent is not DSA, return failure since
    415       we don't allow this case. */
    416 
    417    oid = SECOID_FindOID(&issuerCert->subjectPublicKeyInfo.algorithm.algorithm);
    418    if (oid != NULL) {
    419        tag = oid->offset;
    420 
    421        /* Check if issuer cert has a DSA public key. If not,
    422         * return failure.   */
    423 
    424        if ((tag != SEC_OID_ANSIX9_DSA_SIGNATURE) &&
    425            (tag != SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
    426            (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST) &&
    427            (tag != SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST) &&
    428            (tag != SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) &&
    429            (tag != SEC_OID_SDN702_DSA_SIGNATURE) &&
    430            (tag != SEC_OID_ED25519_PUBLIC_KEY) &&
    431            (tag != SEC_OID_ANSIX962_EC_PUBLIC_KEY)) {
    432            rv = SECFailure;
    433            goto loser;
    434        }
    435    } else {
    436        rv = SECFailure; /* return failure if oid is NULL */
    437        goto loser;
    438    }
    439 
    440    /* at this point the subject cert has no pqg parameters and the
    441     * issuer cert has a DSA public key.  Update the issuer's
    442     * pqg parameters with a recursive call to this same function. */
    443 
    444    rv = seckey_UpdateCertPQGChain(issuerCert, count);
    445    if (rv != SECSuccess) {
    446        rv = SECFailure;
    447        goto loser;
    448    }
    449 
    450    /* ensure issuer has pqg parameters */
    451 
    452    issuerSpki = &issuerCert->subjectPublicKeyInfo;
    453    if (issuerSpki->algorithm.parameters.len == 0) {
    454        rv = SECFailure;
    455    }
    456 
    457    /* if update was successful and pqg params present, then copy the
    458     * parameters to the subject cert's key. */
    459 
    460    if (rv == SECSuccess) {
    461        rv = SECITEM_CopyItem(subjectCert->arena,
    462                              &subjectSpki->algorithm.parameters,
    463                              &issuerSpki->algorithm.parameters);
    464    }
    465 
    466 loser:
    467    if (issuerCert) {
    468        CERT_DestroyCertificate(issuerCert);
    469    }
    470    return rv;
    471 }
    472 
    473 SECStatus
    474 SECKEY_UpdateCertPQG(CERTCertificate *subjectCert)
    475 {
    476    if (!subjectCert) {
    477        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    478        return SECFailure;
    479    }
    480    return seckey_UpdateCertPQGChain(subjectCert, 0);
    481 }
    482 
    483 /* Decode the DSA PQG parameters.  The params could be stored in two
    484 * possible formats, the old fortezza-only wrapped format or
    485 * the normal standard format.  Store the decoded parameters in
    486 * a V3 certificate data structure.  */
    487 
    488 static SECStatus
    489 seckey_DSADecodePQG(PLArenaPool *arena, SECKEYPublicKey *pubk,
    490                    const SECItem *params)
    491 {
    492    SECStatus rv;
    493    SECItem newparams;
    494 
    495    if (params == NULL)
    496        return SECFailure;
    497 
    498    if (params->data == NULL)
    499        return SECFailure;
    500 
    501    PORT_Assert(arena);
    502 
    503    /* make a copy of the data into the arena so QuickDER output is valid */
    504    rv = SECITEM_CopyItem(arena, &newparams, params);
    505 
    506    /* Check if params use the standard format.
    507     * The value 0xa1 will appear in the first byte of the parameter data
    508     * if the PQG parameters are not using the standard format.  This
    509     * code should be changed to use a better method to detect non-standard
    510     * parameters.    */
    511 
    512    if ((newparams.data[0] != 0xa1) &&
    513        (newparams.data[0] != 0xa0)) {
    514 
    515        if (SECSuccess == rv) {
    516            /* PQG params are in the standard format */
    517            prepare_pqg_params_for_asn1(&pubk->u.dsa.params);
    518            rv = SEC_QuickDERDecodeItem(arena, &pubk->u.dsa.params,
    519                                        SECKEY_PQGParamsTemplate,
    520                                        &newparams);
    521        }
    522    } else {
    523 
    524        if (SECSuccess == rv) {
    525            /* else the old fortezza-only wrapped format is used. */
    526            PORT_SetError(SEC_ERROR_BAD_DER);
    527            rv = SECFailure;
    528        }
    529    }
    530    return rv;
    531 }
    532 
    533 /* Function used to make an oid tag to a key type */
    534 KeyType
    535 seckey_GetKeyType(SECOidTag tag)
    536 {
    537    KeyType keyType;
    538 
    539    switch (tag) {
    540        case SEC_OID_X500_RSA_ENCRYPTION:
    541        case SEC_OID_PKCS1_RSA_ENCRYPTION:
    542            keyType = rsaKey;
    543            break;
    544        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
    545            keyType = rsaPssKey;
    546            break;
    547        case SEC_OID_PKCS1_RSA_OAEP_ENCRYPTION:
    548            keyType = rsaOaepKey;
    549            break;
    550        case SEC_OID_ANSIX9_DSA_SIGNATURE:
    551            keyType = dsaKey;
    552            break;
    553        case SEC_OID_MISSI_KEA_DSS_OLD:
    554        case SEC_OID_MISSI_KEA_DSS:
    555        case SEC_OID_MISSI_DSS_OLD:
    556        case SEC_OID_MISSI_DSS:
    557            keyType = fortezzaKey;
    558            break;
    559        case SEC_OID_MISSI_KEA:
    560        case SEC_OID_MISSI_ALT_KEA:
    561            keyType = keaKey;
    562            break;
    563        case SEC_OID_X942_DIFFIE_HELMAN_KEY:
    564            keyType = dhKey;
    565            break;
    566        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
    567            keyType = ecKey;
    568            break;
    569        case SEC_OID_ED25519_PUBLIC_KEY:
    570            keyType = edKey;
    571            break;
    572        case SEC_OID_ML_DSA_44_PUBLIC_KEY:
    573        case SEC_OID_ML_DSA_65_PUBLIC_KEY:
    574        case SEC_OID_ML_DSA_87_PUBLIC_KEY:
    575            keyType = mldsaKey;
    576            break;
    577        /* accommodate applications that hand us a signature type when they
    578         * should be handing us a cipher type */
    579        case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
    580        case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
    581        case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
    582        case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
    583        case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
    584        case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
    585            keyType = rsaKey;
    586            break;
    587        default:
    588            keyType = nullKey;
    589    }
    590    return keyType;
    591 }
    592 
    593 /* Function used to determine what kind of cert we are dealing with. */
    594 KeyType
    595 CERT_GetCertKeyType(const CERTSubjectPublicKeyInfo *spki)
    596 {
    597    return seckey_GetKeyType(SECOID_GetAlgorithmTag(&spki->algorithm));
    598 }
    599 
    600 /* Ensure pubKey contains an OID */
    601 static SECStatus
    602 seckey_HasCurveOID(const SECKEYPublicKey *pubKey)
    603 {
    604    SECItem oid;
    605    SECStatus rv;
    606    PORTCheapArenaPool tmpArena;
    607 
    608    PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
    609    /* If we can decode it, an OID is available. */
    610    rv = SEC_QuickDERDecodeItem(&tmpArena.arena, &oid,
    611                                SEC_ASN1_GET(SEC_ObjectIDTemplate),
    612                                &pubKey->u.ec.DEREncodedParams);
    613    PORT_DestroyCheapArena(&tmpArena);
    614    return rv;
    615 }
    616 
    617 CK_ML_DSA_PARAMETER_SET_TYPE
    618 SECKEY_GetMLDSAPkcs11ParamSetByOidTag(SECOidTag tag)
    619 {
    620    switch (tag) {
    621        case SEC_OID_ML_DSA_44:
    622            return CKP_ML_DSA_44;
    623        case SEC_OID_ML_DSA_65:
    624            return CKP_ML_DSA_65;
    625        case SEC_OID_ML_DSA_87:
    626            return CKP_ML_DSA_87;
    627        default:
    628            return CKP_INVALID_ID;
    629    }
    630 }
    631 
    632 SECOidTag
    633 SECKEY_GetMLDSAOidTagByPkcs11ParamSet(CK_ML_DSA_PARAMETER_SET_TYPE paramSet)
    634 {
    635    switch (paramSet) {
    636        case CKP_ML_DSA_44:
    637            return SEC_OID_ML_DSA_44;
    638        case CKP_ML_DSA_65:
    639            return SEC_OID_ML_DSA_65;
    640        case CKP_ML_DSA_87:
    641            return SEC_OID_ML_DSA_87;
    642        default:
    643            return SEC_OID_UNKNOWN;
    644    }
    645 }
    646 
    647 unsigned int
    648 SECKEY_MLDSAOidParamsToLen(SECOidTag oid, SECKEYSizeType type)
    649 {
    650    switch (type) {
    651        case SECKEYPubKeyType:
    652            switch (oid) {
    653                case SEC_OID_ML_DSA_44:
    654                    return ML_DSA_44_PUBLICKEY_LEN;
    655                case SEC_OID_ML_DSA_65:
    656                    return ML_DSA_65_PUBLICKEY_LEN;
    657                case SEC_OID_ML_DSA_87:
    658                    return ML_DSA_87_PUBLICKEY_LEN;
    659                default:
    660                    break;
    661            }
    662            break;
    663        case SECKEYPrivKeyType:
    664            switch (oid) {
    665                case SEC_OID_ML_DSA_44:
    666                    return ML_DSA_44_PRIVATEKEY_LEN;
    667                case SEC_OID_ML_DSA_65:
    668                    return ML_DSA_65_PRIVATEKEY_LEN;
    669                case SEC_OID_ML_DSA_87:
    670                    return ML_DSA_87_PRIVATEKEY_LEN;
    671                default:
    672                    break;
    673            }
    674            break;
    675        case SECKEYSignatureType:
    676            switch (oid) {
    677                case SEC_OID_ML_DSA_44:
    678                    return ML_DSA_44_SIGNATURE_LEN;
    679                case SEC_OID_ML_DSA_65:
    680                    return ML_DSA_65_SIGNATURE_LEN;
    681                case SEC_OID_ML_DSA_87:
    682                    return ML_DSA_87_SIGNATURE_LEN;
    683                default:
    684                    break;
    685            }
    686            break;
    687        default:
    688            break;
    689    }
    690    return 0;
    691 }
    692 
    693 /* make this function generic. multiple key types will be able to use
    694 * it (ml-kem, ml=dsa, shl-dsa, fn-dsa, etc. ) */
    695 SECOidTag
    696 seckey_GetParameterSet(const SECKEYPrivateKey *key)
    697 {
    698    CK_ULONG paramSet = PK11_ReadULongAttribute(key->pkcs11Slot,
    699                                                key->pkcs11ID,
    700                                                CKA_PARAMETER_SET);
    701    if (paramSet == CK_UNAVAILABLE_INFORMATION) {
    702        return SEC_OID_UNKNOWN;
    703    }
    704    switch (key->keyType) {
    705        case mldsaKey:
    706            return SECKEY_GetMLDSAOidTagByPkcs11ParamSet(paramSet);
    707        default:
    708            break;
    709    }
    710    return SEC_OID_UNKNOWN;
    711 }
    712 
    713 SECOidTag
    714 SECKEY_MLDSAOidParamsFromLen(unsigned int len, SECKEYSizeType type)
    715 {
    716    switch (type) {
    717        case SECKEYPubKeyType:
    718            switch (len) {
    719                case ML_DSA_44_PUBLICKEY_LEN:
    720                    return SEC_OID_ML_DSA_44;
    721                case ML_DSA_65_PUBLICKEY_LEN:
    722                    return SEC_OID_ML_DSA_65;
    723                case ML_DSA_87_PUBLICKEY_LEN:
    724                    return SEC_OID_ML_DSA_87;
    725                default:
    726                    break;
    727            }
    728            break;
    729        case SECKEYPrivKeyType:
    730            switch (len) {
    731                case ML_DSA_44_PRIVATEKEY_LEN:
    732                    return SEC_OID_ML_DSA_44;
    733                case ML_DSA_65_PRIVATEKEY_LEN:
    734                    return SEC_OID_ML_DSA_65;
    735                case ML_DSA_87_PRIVATEKEY_LEN:
    736                    return SEC_OID_ML_DSA_87;
    737                default:
    738                    break;
    739            }
    740            break;
    741        case SECKEYSignatureType:
    742            switch (len) {
    743                case ML_DSA_44_SIGNATURE_LEN:
    744                    return SEC_OID_ML_DSA_44;
    745                case ML_DSA_65_SIGNATURE_LEN:
    746                    return SEC_OID_ML_DSA_65;
    747                case ML_DSA_87_SIGNATURE_LEN:
    748                    return SEC_OID_ML_DSA_87;
    749                default:
    750                    break;
    751            }
    752            break;
    753        default:
    754            break;
    755    }
    756    return SEC_OID_UNKNOWN;
    757 }
    758 
    759 static SECKEYPublicKey *
    760 seckey_ExtractPublicKey(const CERTSubjectPublicKeyInfo *spki)
    761 {
    762    SECKEYPublicKey *pubk;
    763    SECItem os, newOs, newParms;
    764    SECStatus rv;
    765    PLArenaPool *arena;
    766    SECOidTag tag;
    767 
    768    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    769    if (arena == NULL)
    770        return NULL;
    771 
    772    pubk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
    773    if (pubk == NULL) {
    774        PORT_FreeArena(arena, PR_FALSE);
    775        return NULL;
    776    }
    777 
    778    pubk->arena = arena;
    779    pubk->pkcs11Slot = 0;
    780    pubk->pkcs11ID = CK_INVALID_HANDLE;
    781 
    782    /* Convert bit string length from bits to bytes */
    783    os = spki->subjectPublicKey;
    784    DER_ConvertBitString(&os);
    785 
    786    tag = SECOID_GetAlgorithmTag(&spki->algorithm);
    787 
    788    /* copy the DER into the arena, since Quick DER returns data that points
    789       into the DER input, which may get freed by the caller */
    790    rv = SECITEM_CopyItem(arena, &newOs, &os);
    791    if (rv == SECSuccess)
    792        switch (tag) {
    793            case SEC_OID_X500_RSA_ENCRYPTION:
    794            case SEC_OID_PKCS1_RSA_ENCRYPTION:
    795            case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
    796                pubk->keyType = rsaKey;
    797                prepare_rsa_pub_key_for_asn1(pubk);
    798                rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_RSAPublicKeyTemplate, &newOs);
    799                if (rv == SECSuccess)
    800                    return pubk;
    801                break;
    802            case SEC_OID_ANSIX9_DSA_SIGNATURE:
    803            case SEC_OID_SDN702_DSA_SIGNATURE:
    804                pubk->keyType = dsaKey;
    805                prepare_dsa_pub_key_for_asn1(pubk);
    806                rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DSAPublicKeyTemplate, &newOs);
    807                if (rv != SECSuccess)
    808                    break;
    809 
    810                rv = seckey_DSADecodePQG(arena, pubk,
    811                                         &spki->algorithm.parameters);
    812 
    813                if (rv == SECSuccess)
    814                    return pubk;
    815                break;
    816            case SEC_OID_X942_DIFFIE_HELMAN_KEY:
    817                pubk->keyType = dhKey;
    818                prepare_dh_pub_key_for_asn1(pubk);
    819                rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHPublicKeyTemplate, &newOs);
    820                if (rv != SECSuccess)
    821                    break;
    822 
    823                /* copy the DER into the arena, since Quick DER returns data that points
    824                   into the DER input, which may get freed by the caller */
    825                rv = SECITEM_CopyItem(arena, &newParms, &spki->algorithm.parameters);
    826                if (rv != SECSuccess)
    827                    break;
    828 
    829                rv = SEC_QuickDERDecodeItem(arena, pubk, SECKEY_DHParamKeyTemplate,
    830                                            &newParms);
    831 
    832                if (rv == SECSuccess)
    833                    return pubk;
    834                break;
    835            case SEC_OID_ML_DSA_44_PUBLIC_KEY:
    836            case SEC_OID_ML_DSA_65_PUBLIC_KEY:
    837            case SEC_OID_ML_DSA_87_PUBLIC_KEY:
    838                /* A basic consistency check on inputs. */
    839                if (spki->algorithm.parameters.len != 0 && newOs.len == 0) {
    840                    PORT_SetError(SEC_ERROR_INPUT_LEN);
    841                    break;
    842                }
    843 
    844                pubk->keyType = mldsaKey;
    845                pubk->u.mldsa.paramSet = tag;
    846 
    847                /* newOS is already in the arena, we can just copy the data */
    848                pubk->u.mldsa.publicValue = newOs;
    849                return pubk;
    850            case SEC_OID_X25519:
    851            case SEC_OID_ED25519_PUBLIC_KEY:
    852                /* A basic consistency check on inputs. */
    853                if (newOs.len == 0) {
    854                    PORT_SetError(SEC_ERROR_INPUT_LEN);
    855                    break;
    856                }
    857 
    858                /* Currently supporting only (Pure)Ed25519 .*/
    859                if (spki->algorithm.parameters.len != 0) {
    860                    PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
    861                    break;
    862                }
    863 
    864                /* edKey corresponds to Ed25519 mechanism.
    865                 * ecMontKey corresponds to X25519 mechanism.
    866                 * The other options are not supported. */
    867                if (tag == SEC_OID_X25519) {
    868                    pubk->keyType = ecMontKey;
    869                } else {
    870                    /* tag == SEC_OID_ED25519_PUBLIC_KEY */
    871                    pubk->keyType = edKey;
    872                }
    873 
    874                pubk->u.ec.size = 0;
    875 
    876                SECOidData *oid25519 = SECOID_FindOIDByTag(tag);
    877                if (!oid25519) {
    878                    break;
    879                }
    880 
    881                if (!SECITEM_AllocItem(arena, &pubk->u.ec.DEREncodedParams, oid25519->oid.len + 2)) {
    882                    break;
    883                }
    884                pubk->u.ec.DEREncodedParams.data[0] = SEC_ASN1_OBJECT_ID;
    885                pubk->u.ec.DEREncodedParams.data[1] = oid25519->oid.len;
    886                PORT_Memcpy(pubk->u.ec.DEREncodedParams.data + 2, oid25519->oid.data, oid25519->oid.len);
    887 
    888                rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &newOs);
    889                if (rv != SECSuccess) {
    890                    break;
    891                }
    892                return pubk;
    893            case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
    894                /* A basic sanity check on inputs. */
    895                if (spki->algorithm.parameters.len == 0 || newOs.len == 0) {
    896                    PORT_SetError(SEC_ERROR_INPUT_LEN);
    897                    break;
    898                }
    899                pubk->keyType = ecKey;
    900                pubk->u.ec.size = 0;
    901 
    902                /* Since PKCS#11 directly takes the DER encoding of EC params
    903                 * and public value, we don't need any decoding here.
    904                 */
    905                rv = SECITEM_CopyItem(arena, &pubk->u.ec.DEREncodedParams,
    906                                      &spki->algorithm.parameters);
    907                if (rv != SECSuccess) {
    908                    break;
    909                }
    910                rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &newOs);
    911                if (rv != SECSuccess) {
    912                    break;
    913                }
    914                pubk->u.ec.encoding = ECPoint_Undefined;
    915                rv = seckey_HasCurveOID(pubk);
    916                if (rv == SECSuccess) {
    917                    return pubk;
    918                }
    919                break;
    920 
    921            default:
    922                PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
    923                break;
    924        }
    925 
    926    SECKEY_DestroyPublicKey(pubk);
    927    return NULL;
    928 }
    929 
    930 /* required for JSS */
    931 SECKEYPublicKey *
    932 SECKEY_ExtractPublicKey(const CERTSubjectPublicKeyInfo *spki)
    933 {
    934    return seckey_ExtractPublicKey(spki);
    935 }
    936 
    937 SECKEYPublicKey *
    938 CERT_ExtractPublicKey(CERTCertificate *cert)
    939 {
    940    return seckey_ExtractPublicKey(&cert->subjectPublicKeyInfo);
    941 }
    942 
    943 int
    944 SECKEY_ECParamsToKeySize(const SECItem *encodedParams)
    945 {
    946    SECOidTag tag;
    947    SECItem oid = { siBuffer, NULL, 0 };
    948 
    949    /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID),
    950     * followed by the length of the curve oid and the curve oid.
    951     */
    952    oid.len = encodedParams->data[1];
    953    oid.data = encodedParams->data + 2;
    954    if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)
    955        return 0;
    956 
    957    switch (tag) {
    958        case SEC_OID_SECG_EC_SECP112R1:
    959        case SEC_OID_SECG_EC_SECP112R2:
    960            return 112;
    961 
    962        case SEC_OID_SECG_EC_SECT113R1:
    963        case SEC_OID_SECG_EC_SECT113R2:
    964            return 113;
    965 
    966        case SEC_OID_SECG_EC_SECP128R1:
    967        case SEC_OID_SECG_EC_SECP128R2:
    968            return 128;
    969 
    970        case SEC_OID_SECG_EC_SECT131R1:
    971        case SEC_OID_SECG_EC_SECT131R2:
    972            return 131;
    973 
    974        case SEC_OID_SECG_EC_SECP160K1:
    975        case SEC_OID_SECG_EC_SECP160R1:
    976        case SEC_OID_SECG_EC_SECP160R2:
    977            return 160;
    978 
    979        case SEC_OID_SECG_EC_SECT163K1:
    980        case SEC_OID_SECG_EC_SECT163R1:
    981        case SEC_OID_SECG_EC_SECT163R2:
    982        case SEC_OID_ANSIX962_EC_C2PNB163V1:
    983        case SEC_OID_ANSIX962_EC_C2PNB163V2:
    984        case SEC_OID_ANSIX962_EC_C2PNB163V3:
    985            return 163;
    986 
    987        case SEC_OID_ANSIX962_EC_C2PNB176V1:
    988            return 176;
    989 
    990        case SEC_OID_ANSIX962_EC_C2TNB191V1:
    991        case SEC_OID_ANSIX962_EC_C2TNB191V2:
    992        case SEC_OID_ANSIX962_EC_C2TNB191V3:
    993        case SEC_OID_ANSIX962_EC_C2ONB191V4:
    994        case SEC_OID_ANSIX962_EC_C2ONB191V5:
    995            return 191;
    996 
    997        case SEC_OID_SECG_EC_SECP192K1:
    998        case SEC_OID_ANSIX962_EC_PRIME192V1:
    999        case SEC_OID_ANSIX962_EC_PRIME192V2:
   1000        case SEC_OID_ANSIX962_EC_PRIME192V3:
   1001            return 192;
   1002 
   1003        case SEC_OID_SECG_EC_SECT193R1:
   1004        case SEC_OID_SECG_EC_SECT193R2:
   1005            return 193;
   1006 
   1007        case SEC_OID_ANSIX962_EC_C2PNB208W1:
   1008            return 208;
   1009 
   1010        case SEC_OID_SECG_EC_SECP224K1:
   1011        case SEC_OID_SECG_EC_SECP224R1:
   1012            return 224;
   1013 
   1014        case SEC_OID_SECG_EC_SECT233K1:
   1015        case SEC_OID_SECG_EC_SECT233R1:
   1016            return 233;
   1017 
   1018        case SEC_OID_SECG_EC_SECT239K1:
   1019        case SEC_OID_ANSIX962_EC_C2TNB239V1:
   1020        case SEC_OID_ANSIX962_EC_C2TNB239V2:
   1021        case SEC_OID_ANSIX962_EC_C2TNB239V3:
   1022        case SEC_OID_ANSIX962_EC_C2ONB239V4:
   1023        case SEC_OID_ANSIX962_EC_C2ONB239V5:
   1024        case SEC_OID_ANSIX962_EC_PRIME239V1:
   1025        case SEC_OID_ANSIX962_EC_PRIME239V2:
   1026        case SEC_OID_ANSIX962_EC_PRIME239V3:
   1027            return 239;
   1028 
   1029        case SEC_OID_SECG_EC_SECP256K1:
   1030        case SEC_OID_ANSIX962_EC_PRIME256V1:
   1031            return 256;
   1032 
   1033        case SEC_OID_ANSIX962_EC_C2PNB272W1:
   1034            return 272;
   1035 
   1036        case SEC_OID_SECG_EC_SECT283K1:
   1037        case SEC_OID_SECG_EC_SECT283R1:
   1038            return 283;
   1039 
   1040        case SEC_OID_ANSIX962_EC_C2PNB304W1:
   1041            return 304;
   1042 
   1043        case SEC_OID_ANSIX962_EC_C2TNB359V1:
   1044            return 359;
   1045 
   1046        case SEC_OID_ANSIX962_EC_C2PNB368W1:
   1047            return 368;
   1048 
   1049        case SEC_OID_SECG_EC_SECP384R1:
   1050            return 384;
   1051 
   1052        case SEC_OID_SECG_EC_SECT409K1:
   1053        case SEC_OID_SECG_EC_SECT409R1:
   1054            return 409;
   1055 
   1056        case SEC_OID_ANSIX962_EC_C2TNB431R1:
   1057            return 431;
   1058 
   1059        case SEC_OID_SECG_EC_SECP521R1:
   1060            return 521;
   1061 
   1062        case SEC_OID_SECG_EC_SECT571K1:
   1063        case SEC_OID_SECG_EC_SECT571R1:
   1064            return 571;
   1065 
   1066        case SEC_OID_X25519:
   1067        case SEC_OID_CURVE25519:
   1068        case SEC_OID_ED25519_PUBLIC_KEY:
   1069            return 255;
   1070 
   1071        default:
   1072            PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
   1073            return 0;
   1074    }
   1075 }
   1076 
   1077 int
   1078 SECKEY_ECParamsToBasePointOrderLen(const SECItem *encodedParams)
   1079 {
   1080    SECOidTag tag;
   1081    SECItem oid = { siBuffer, NULL, 0 };
   1082 
   1083    /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID),
   1084     * followed by the length of the curve oid and the curve oid.
   1085     */
   1086    oid.len = encodedParams->data[1];
   1087    oid.data = encodedParams->data + 2;
   1088    if ((tag = SECOID_FindOIDTag(&oid)) == SEC_OID_UNKNOWN)
   1089        return 0;
   1090 
   1091    switch (tag) {
   1092        case SEC_OID_SECG_EC_SECP112R1:
   1093            return 112;
   1094        case SEC_OID_SECG_EC_SECP112R2:
   1095            return 110;
   1096 
   1097        case SEC_OID_SECG_EC_SECT113R1:
   1098        case SEC_OID_SECG_EC_SECT113R2:
   1099            return 113;
   1100 
   1101        case SEC_OID_SECG_EC_SECP128R1:
   1102            return 128;
   1103        case SEC_OID_SECG_EC_SECP128R2:
   1104            return 126;
   1105 
   1106        case SEC_OID_SECG_EC_SECT131R1:
   1107        case SEC_OID_SECG_EC_SECT131R2:
   1108            return 131;
   1109 
   1110        case SEC_OID_SECG_EC_SECP160K1:
   1111        case SEC_OID_SECG_EC_SECP160R1:
   1112        case SEC_OID_SECG_EC_SECP160R2:
   1113            return 161;
   1114 
   1115        case SEC_OID_SECG_EC_SECT163K1:
   1116            return 163;
   1117        case SEC_OID_SECG_EC_SECT163R1:
   1118            return 162;
   1119        case SEC_OID_SECG_EC_SECT163R2:
   1120        case SEC_OID_ANSIX962_EC_C2PNB163V1:
   1121            return 163;
   1122        case SEC_OID_ANSIX962_EC_C2PNB163V2:
   1123        case SEC_OID_ANSIX962_EC_C2PNB163V3:
   1124            return 162;
   1125 
   1126        case SEC_OID_ANSIX962_EC_C2PNB176V1:
   1127            return 161;
   1128 
   1129        case SEC_OID_ANSIX962_EC_C2TNB191V1:
   1130            return 191;
   1131        case SEC_OID_ANSIX962_EC_C2TNB191V2:
   1132            return 190;
   1133        case SEC_OID_ANSIX962_EC_C2TNB191V3:
   1134            return 189;
   1135        case SEC_OID_ANSIX962_EC_C2ONB191V4:
   1136            return 191;
   1137        case SEC_OID_ANSIX962_EC_C2ONB191V5:
   1138            return 188;
   1139 
   1140        case SEC_OID_SECG_EC_SECP192K1:
   1141        case SEC_OID_ANSIX962_EC_PRIME192V1:
   1142        case SEC_OID_ANSIX962_EC_PRIME192V2:
   1143        case SEC_OID_ANSIX962_EC_PRIME192V3:
   1144            return 192;
   1145 
   1146        case SEC_OID_SECG_EC_SECT193R1:
   1147        case SEC_OID_SECG_EC_SECT193R2:
   1148            return 193;
   1149 
   1150        case SEC_OID_ANSIX962_EC_C2PNB208W1:
   1151            return 193;
   1152 
   1153        case SEC_OID_SECG_EC_SECP224K1:
   1154            return 225;
   1155        case SEC_OID_SECG_EC_SECP224R1:
   1156            return 224;
   1157 
   1158        case SEC_OID_SECG_EC_SECT233K1:
   1159            return 232;
   1160        case SEC_OID_SECG_EC_SECT233R1:
   1161            return 233;
   1162 
   1163        case SEC_OID_SECG_EC_SECT239K1:
   1164        case SEC_OID_ANSIX962_EC_C2TNB239V1:
   1165            return 238;
   1166        case SEC_OID_ANSIX962_EC_C2TNB239V2:
   1167            return 237;
   1168        case SEC_OID_ANSIX962_EC_C2TNB239V3:
   1169            return 236;
   1170        case SEC_OID_ANSIX962_EC_C2ONB239V4:
   1171            return 238;
   1172        case SEC_OID_ANSIX962_EC_C2ONB239V5:
   1173            return 237;
   1174        case SEC_OID_ANSIX962_EC_PRIME239V1:
   1175        case SEC_OID_ANSIX962_EC_PRIME239V2:
   1176        case SEC_OID_ANSIX962_EC_PRIME239V3:
   1177            return 239;
   1178 
   1179        case SEC_OID_SECG_EC_SECP256K1:
   1180        case SEC_OID_ANSIX962_EC_PRIME256V1:
   1181            return 256;
   1182 
   1183        case SEC_OID_ANSIX962_EC_C2PNB272W1:
   1184            return 257;
   1185 
   1186        case SEC_OID_SECG_EC_SECT283K1:
   1187            return 281;
   1188        case SEC_OID_SECG_EC_SECT283R1:
   1189            return 282;
   1190 
   1191        case SEC_OID_ANSIX962_EC_C2PNB304W1:
   1192            return 289;
   1193 
   1194        case SEC_OID_ANSIX962_EC_C2TNB359V1:
   1195            return 353;
   1196 
   1197        case SEC_OID_ANSIX962_EC_C2PNB368W1:
   1198            return 353;
   1199 
   1200        case SEC_OID_SECG_EC_SECP384R1:
   1201            return 384;
   1202 
   1203        case SEC_OID_SECG_EC_SECT409K1:
   1204            return 407;
   1205        case SEC_OID_SECG_EC_SECT409R1:
   1206            return 409;
   1207 
   1208        case SEC_OID_ANSIX962_EC_C2TNB431R1:
   1209            return 418;
   1210 
   1211        case SEC_OID_SECG_EC_SECP521R1:
   1212            return 521;
   1213 
   1214        case SEC_OID_SECG_EC_SECT571K1:
   1215        case SEC_OID_SECG_EC_SECT571R1:
   1216            return 570;
   1217 
   1218        case SEC_OID_X25519:
   1219        case SEC_OID_CURVE25519:
   1220        case SEC_OID_ED25519_PUBLIC_KEY:
   1221            return 255;
   1222 
   1223        default:
   1224            PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
   1225            return 0;
   1226    }
   1227 }
   1228 
   1229 /* The number of bits in the number from the first non-zero bit onward. */
   1230 unsigned
   1231 SECKEY_BigIntegerBitLength(const SECItem *number)
   1232 {
   1233    const unsigned char *p;
   1234    unsigned octets;
   1235    unsigned bits;
   1236 
   1237    if (!number || !number->data) {
   1238        PORT_SetError(SEC_ERROR_INVALID_KEY);
   1239        return 0;
   1240    }
   1241 
   1242    p = number->data;
   1243    octets = number->len;
   1244    while (octets > 0 && !*p) {
   1245        ++p;
   1246        --octets;
   1247    }
   1248    if (octets == 0) {
   1249        return 0;
   1250    }
   1251    /* bits = 7..1 because we know at least one bit is set already */
   1252    /* Note: This could do a binary search, but this is faster for keys if we
   1253     * assume that good keys will have the MSB set. */
   1254    for (bits = 7; bits > 0; --bits) {
   1255        if (*p & (1 << bits)) {
   1256            break;
   1257        }
   1258    }
   1259    return octets * 8 + bits - 7;
   1260 }
   1261 
   1262 /* returns key strength in bytes (not bits) */
   1263 unsigned
   1264 SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk)
   1265 {
   1266    return (SECKEY_PublicKeyStrengthInBits(pubk) + 7) / 8;
   1267 }
   1268 
   1269 /* returns key strength in bits */
   1270 unsigned
   1271 SECKEY_PublicKeyStrengthInBits(const SECKEYPublicKey *pubk)
   1272 {
   1273    unsigned bitSize = 0;
   1274 
   1275    if (!pubk) {
   1276        PORT_SetError(SEC_ERROR_INVALID_KEY);
   1277        return 0;
   1278    }
   1279 
   1280    /* interpret modulus length as key strength */
   1281    switch (pubk->keyType) {
   1282        case rsaKey:
   1283            bitSize = SECKEY_BigIntegerBitLength(&pubk->u.rsa.modulus);
   1284            break;
   1285        case dsaKey:
   1286            bitSize = SECKEY_BigIntegerBitLength(&pubk->u.dsa.params.prime);
   1287            break;
   1288        case dhKey:
   1289            bitSize = SECKEY_BigIntegerBitLength(&pubk->u.dh.prime);
   1290            break;
   1291        case ecKey:
   1292        case edKey:
   1293        case ecMontKey:
   1294            bitSize = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
   1295            break;
   1296        case mldsaKey:
   1297            bitSize = SECKEY_MLDSAOidParamsToLen(pubk->u.mldsa.paramSet,
   1298                                                 SECKEYPubKeyType) *
   1299                      8;
   1300            break;
   1301        default:
   1302            PORT_SetError(SEC_ERROR_INVALID_KEY);
   1303            break;
   1304    }
   1305    return bitSize;
   1306 }
   1307 
   1308 unsigned
   1309 SECKEY_PrivateKeyStrengthInBits(const SECKEYPrivateKey *privk)
   1310 {
   1311    unsigned bitSize = 0;
   1312    SECItem params = { siBuffer, NULL, 0 };
   1313    SECStatus rv;
   1314    SECOidTag paramSetOid;
   1315 
   1316    if (!privk) {
   1317        PORT_SetError(SEC_ERROR_INVALID_KEY);
   1318        return 0;
   1319    }
   1320 
   1321    /* interpret modulus length as key strength */
   1322    switch (privk->keyType) {
   1323        case rsaKey:
   1324        case rsaPssKey:
   1325        case rsaOaepKey:
   1326            rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
   1327                                    CKA_MODULUS, NULL, &params);
   1328            if ((rv != SECSuccess) || (params.data == NULL)) {
   1329                /* some tokens don't export CKA_MODULUS on the private key,
   1330                 * PK11_SignatureLen works around this if necessary. This
   1331                 * method is less percise because it returns bytes instead
   1332                 * of bits, so we only do it if we can't get the modulus */
   1333                bitSize = PK11_SignatureLen((SECKEYPrivateKey *)privk) * PR_BITS_PER_BYTE;
   1334                if (bitSize == -1) {
   1335                    return 0;
   1336                }
   1337                return bitSize;
   1338            }
   1339            bitSize = SECKEY_BigIntegerBitLength(&params);
   1340            PORT_Free(params.data);
   1341            return bitSize;
   1342        case dsaKey:
   1343        case fortezzaKey:
   1344        case dhKey:
   1345        case keaKey:
   1346            rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
   1347                                    CKA_PRIME, NULL, &params);
   1348            if ((rv != SECSuccess) || (params.data == NULL)) {
   1349                PORT_SetError(SEC_ERROR_INVALID_KEY);
   1350                return 0;
   1351            }
   1352            bitSize = SECKEY_BigIntegerBitLength(&params);
   1353            PORT_Free(params.data);
   1354            return bitSize;
   1355        case ecKey:
   1356            rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
   1357                                    CKA_EC_PARAMS, NULL, &params);
   1358            if ((rv != SECSuccess) || (params.data == NULL)) {
   1359                return 0;
   1360            }
   1361            bitSize = SECKEY_ECParamsToKeySize(&params);
   1362            PORT_Free(params.data);
   1363            return bitSize;
   1364        case mldsaKey:
   1365            paramSetOid = seckey_GetParameterSet(privk);
   1366            if (paramSetOid == SEC_OID_UNKNOWN) {
   1367                break;
   1368            }
   1369            return SECKEY_MLDSAOidParamsToLen(paramSetOid, SECKEYPrivKeyType) *
   1370                   8;
   1371            break;
   1372        default:
   1373            break;
   1374    }
   1375    PORT_SetError(SEC_ERROR_INVALID_KEY);
   1376    return 0;
   1377 }
   1378 
   1379 /* returns signature length in bytes (not bits) */
   1380 unsigned
   1381 SECKEY_SignatureLen(const SECKEYPublicKey *pubk)
   1382 {
   1383    unsigned size;
   1384 
   1385    switch (pubk->keyType) {
   1386        case rsaKey:
   1387        case rsaPssKey:
   1388            if (pubk->u.rsa.modulus.len == 0) {
   1389                return 0;
   1390            }
   1391            if (pubk->u.rsa.modulus.data[0] == 0) {
   1392                return pubk->u.rsa.modulus.len - 1;
   1393            }
   1394            return pubk->u.rsa.modulus.len;
   1395        case dsaKey:
   1396            return pubk->u.dsa.params.subPrime.len * 2;
   1397        case ecKey:
   1398        case edKey:
   1399        case ecMontKey:
   1400            /* Get the base point order length in bits and adjust */
   1401            size = SECKEY_ECParamsToBasePointOrderLen(
   1402                &pubk->u.ec.DEREncodedParams);
   1403            return ((size + 7) / 8) * 2;
   1404        case mldsaKey:
   1405            return SECKEY_MLDSAOidParamsToLen(pubk->u.mldsa.paramSet,
   1406                                              SECKEYSignatureType);
   1407            break;
   1408        default:
   1409            break;
   1410    }
   1411    PORT_SetError(SEC_ERROR_INVALID_KEY);
   1412    return 0;
   1413 }
   1414 
   1415 SECKEYPrivateKey *
   1416 SECKEY_CopyPrivateKey(const SECKEYPrivateKey *privk)
   1417 {
   1418    SECKEYPrivateKey *copyk;
   1419    PLArenaPool *arena;
   1420 
   1421    if (!privk || !privk->pkcs11Slot) {
   1422        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1423        return NULL;
   1424    }
   1425 
   1426    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   1427    if (arena == NULL) {
   1428        return NULL;
   1429    }
   1430 
   1431    copyk = (SECKEYPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYPrivateKey));
   1432    if (copyk) {
   1433        copyk->arena = arena;
   1434        copyk->keyType = privk->keyType;
   1435 
   1436        /* copy the PKCS #11 parameters */
   1437        copyk->pkcs11Slot = PK11_ReferenceSlot(privk->pkcs11Slot);
   1438        /* if the key we're referencing was a temparary key we have just
   1439         * created, that we want to go away when we're through, we need
   1440         * to make a copy of it */
   1441        if (privk->pkcs11IsTemp) {
   1442            copyk->pkcs11ID =
   1443                PK11_CopyKey(privk->pkcs11Slot, privk->pkcs11ID);
   1444            if (copyk->pkcs11ID == CK_INVALID_HANDLE)
   1445                goto fail;
   1446        } else {
   1447            copyk->pkcs11ID = privk->pkcs11ID;
   1448        }
   1449        copyk->pkcs11IsTemp = privk->pkcs11IsTemp;
   1450        copyk->wincx = privk->wincx;
   1451        copyk->staticflags = privk->staticflags;
   1452        return copyk;
   1453    } else {
   1454        PORT_SetError(SEC_ERROR_NO_MEMORY);
   1455    }
   1456 
   1457 fail:
   1458    PORT_FreeArena(arena, PR_FALSE);
   1459    return NULL;
   1460 }
   1461 
   1462 SECKEYPublicKey *
   1463 SECKEY_CopyPublicKey(const SECKEYPublicKey *pubk)
   1464 {
   1465    SECKEYPublicKey *copyk;
   1466    PLArenaPool *arena;
   1467    SECStatus rv = SECSuccess;
   1468 
   1469    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   1470    if (arena == NULL) {
   1471        PORT_SetError(SEC_ERROR_NO_MEMORY);
   1472        return NULL;
   1473    }
   1474 
   1475    copyk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
   1476    if (!copyk) {
   1477        PORT_FreeArena(arena, PR_FALSE);
   1478        PORT_SetError(SEC_ERROR_NO_MEMORY);
   1479        return NULL;
   1480    }
   1481 
   1482    copyk->arena = arena;
   1483    copyk->keyType = pubk->keyType;
   1484    if (pubk->pkcs11Slot &&
   1485        PK11_IsPermObject(pubk->pkcs11Slot, pubk->pkcs11ID)) {
   1486        copyk->pkcs11Slot = PK11_ReferenceSlot(pubk->pkcs11Slot);
   1487        copyk->pkcs11ID = pubk->pkcs11ID;
   1488    } else {
   1489        copyk->pkcs11Slot = NULL; /* go get own reference */
   1490        copyk->pkcs11ID = CK_INVALID_HANDLE;
   1491    }
   1492    switch (pubk->keyType) {
   1493        case rsaKey:
   1494            rv = SECITEM_CopyItem(arena, &copyk->u.rsa.modulus,
   1495                                  &pubk->u.rsa.modulus);
   1496            if (rv == SECSuccess) {
   1497                rv = SECITEM_CopyItem(arena, &copyk->u.rsa.publicExponent,
   1498                                      &pubk->u.rsa.publicExponent);
   1499                if (rv == SECSuccess)
   1500                    return copyk;
   1501            }
   1502            break;
   1503        case dsaKey:
   1504            rv = SECITEM_CopyItem(arena, &copyk->u.dsa.publicValue,
   1505                                  &pubk->u.dsa.publicValue);
   1506            if (rv != SECSuccess)
   1507                break;
   1508            rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.prime,
   1509                                  &pubk->u.dsa.params.prime);
   1510            if (rv != SECSuccess)
   1511                break;
   1512            rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.subPrime,
   1513                                  &pubk->u.dsa.params.subPrime);
   1514            if (rv != SECSuccess)
   1515                break;
   1516            rv = SECITEM_CopyItem(arena, &copyk->u.dsa.params.base,
   1517                                  &pubk->u.dsa.params.base);
   1518            break;
   1519        case dhKey:
   1520            rv = SECITEM_CopyItem(arena, &copyk->u.dh.prime, &pubk->u.dh.prime);
   1521            if (rv != SECSuccess)
   1522                break;
   1523            rv = SECITEM_CopyItem(arena, &copyk->u.dh.base, &pubk->u.dh.base);
   1524            if (rv != SECSuccess)
   1525                break;
   1526            rv = SECITEM_CopyItem(arena, &copyk->u.dh.publicValue,
   1527                                  &pubk->u.dh.publicValue);
   1528            break;
   1529        case ecKey:
   1530        case edKey:
   1531        case ecMontKey:
   1532            copyk->u.ec.size = pubk->u.ec.size;
   1533            rv = seckey_HasCurveOID(pubk);
   1534            if (rv != SECSuccess) {
   1535                break;
   1536            }
   1537            rv = SECITEM_CopyItem(arena, &copyk->u.ec.DEREncodedParams,
   1538                                  &pubk->u.ec.DEREncodedParams);
   1539            if (rv != SECSuccess) {
   1540                break;
   1541            }
   1542            copyk->u.ec.encoding = ECPoint_Undefined;
   1543            rv = SECITEM_CopyItem(arena, &copyk->u.ec.publicValue,
   1544                                  &pubk->u.ec.publicValue);
   1545            break;
   1546        case mldsaKey:
   1547            copyk->u.mldsa.paramSet = pubk->u.mldsa.paramSet;
   1548            rv = SECITEM_CopyItem(arena, &copyk->u.mldsa.publicValue,
   1549                                  &pubk->u.mldsa.publicValue);
   1550            break;
   1551        case nullKey:
   1552            return copyk;
   1553        case kyberKey:
   1554            copyk->u.kyber.params = pubk->u.kyber.params;
   1555            rv = SECITEM_CopyItem(arena, &copyk->u.kyber.publicValue,
   1556                                  &pubk->u.kyber.publicValue);
   1557            break;
   1558        default:
   1559            PORT_SetError(SEC_ERROR_INVALID_KEY);
   1560            rv = SECFailure;
   1561            break;
   1562    }
   1563    if (rv == SECSuccess)
   1564        return copyk;
   1565 
   1566    SECKEY_DestroyPublicKey(copyk);
   1567    return NULL;
   1568 }
   1569 
   1570 /*
   1571 * Check that a given key meets the policy limits for the given key
   1572 * size.
   1573 */
   1574 SECStatus
   1575 SECKEY_EnforceKeySize(KeyType keyType, unsigned keyLength, SECErrorCodes error)
   1576 {
   1577    PRInt32 opt = -1;
   1578    PRInt32 optVal;
   1579    SECStatus rv;
   1580 
   1581    switch (keyType) {
   1582        case rsaKey:
   1583        case rsaPssKey:
   1584        case rsaOaepKey:
   1585            opt = NSS_RSA_MIN_KEY_SIZE;
   1586            break;
   1587        case dsaKey:
   1588        case fortezzaKey:
   1589            opt = NSS_DSA_MIN_KEY_SIZE;
   1590            break;
   1591        case dhKey:
   1592        case keaKey:
   1593            opt = NSS_DH_MIN_KEY_SIZE;
   1594            break;
   1595        case ecKey:
   1596            opt = NSS_ECC_MIN_KEY_SIZE;
   1597            break;
   1598        case mldsaKey:
   1599            return SECSuccess; /* mldsa handles key size policy
   1600                                * by having separate controls on
   1601                                * key params */
   1602        case nullKey:
   1603        default:
   1604            PORT_SetError(SEC_ERROR_INVALID_KEY);
   1605            return SECFailure;
   1606    }
   1607    PORT_Assert(opt != -1);
   1608    rv = NSS_OptionGet(opt, &optVal);
   1609    if (rv != SECSuccess) {
   1610        return rv;
   1611    }
   1612    if (optVal > keyLength) {
   1613        PORT_SetError(error);
   1614        return SECFailure;
   1615    }
   1616    return SECSuccess;
   1617 }
   1618 
   1619 /*
   1620 * Use the private key to find a public key handle. The handle will be on
   1621 * the same slot as the private key.
   1622 */
   1623 static CK_OBJECT_HANDLE
   1624 seckey_FindPublicKeyHandle(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk)
   1625 {
   1626    CK_OBJECT_HANDLE keyID;
   1627 
   1628    /* this helper function is only used below. If we want to make this more
   1629     * general, we would need to free up any already cached handles if the
   1630     * slot doesn't match up with the private key slot */
   1631    PORT_Assert(pubk->pkcs11ID == CK_INVALID_HANDLE);
   1632 
   1633    /* first look for a matching public key */
   1634    keyID = PK11_MatchItem(privk->pkcs11Slot, privk->pkcs11ID, CKO_PUBLIC_KEY);
   1635    if (keyID != CK_INVALID_HANDLE) {
   1636        return keyID;
   1637    }
   1638 
   1639    /* none found, create a temp one, make the pubk the owner */
   1640    pubk->pkcs11ID = PK11_DerivePubKeyFromPrivKey(privk);
   1641    if (pubk->pkcs11ID == CK_INVALID_HANDLE) {
   1642        /* end of the road. Token doesn't have matching public key, nor can
   1643         * token regenerate a new public key from and existing private key. */
   1644        return CK_INVALID_HANDLE;
   1645    }
   1646    pubk->pkcs11Slot = PK11_ReferenceSlot(privk->pkcs11Slot);
   1647    return pubk->pkcs11ID;
   1648 }
   1649 
   1650 SECKEYPublicKey *
   1651 SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk)
   1652 {
   1653    SECKEYPublicKey *pubk;
   1654    PLArenaPool *arena;
   1655    CERTCertificate *cert;
   1656    SECStatus rv;
   1657    CK_OBJECT_HANDLE pubKeyHandle;
   1658    SECItem decodedPoint;
   1659 
   1660    /*
   1661     * First try to look up the cert.
   1662     */
   1663    cert = PK11_GetCertFromPrivateKey(privk);
   1664    if (cert) {
   1665        pubk = CERT_ExtractPublicKey(cert);
   1666        CERT_DestroyCertificate(cert);
   1667        return pubk;
   1668    }
   1669 
   1670    /* couldn't find the cert, build pub key by hand */
   1671    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   1672    if (arena == NULL) {
   1673        PORT_SetError(SEC_ERROR_NO_MEMORY);
   1674        return NULL;
   1675    }
   1676    pubk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena,
   1677                                               sizeof(SECKEYPublicKey));
   1678    if (pubk == NULL) {
   1679        PORT_FreeArena(arena, PR_FALSE);
   1680        return NULL;
   1681    }
   1682    pubk->keyType = privk->keyType;
   1683    pubk->pkcs11Slot = NULL;
   1684    pubk->pkcs11ID = CK_INVALID_HANDLE;
   1685    pubk->arena = arena;
   1686 
   1687    switch (privk->keyType) {
   1688        case nullKey:
   1689            /* Nothing to query, if the cert isn't there, we're done -- no way
   1690             * to get the public key */
   1691            break;
   1692        case dsaKey:
   1693            pubKeyHandle = seckey_FindPublicKeyHandle(privk, pubk);
   1694            if (pubKeyHandle == CK_INVALID_HANDLE)
   1695                break;
   1696            rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
   1697                                    CKA_BASE, arena, &pubk->u.dsa.params.base);
   1698            if (rv != SECSuccess)
   1699                break;
   1700            rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
   1701                                    CKA_PRIME, arena, &pubk->u.dsa.params.prime);
   1702            if (rv != SECSuccess)
   1703                break;
   1704            rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
   1705                                    CKA_SUBPRIME, arena, &pubk->u.dsa.params.subPrime);
   1706            if (rv != SECSuccess)
   1707                break;
   1708            rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
   1709                                    CKA_VALUE, arena, &pubk->u.dsa.publicValue);
   1710            if (rv != SECSuccess)
   1711                break;
   1712            return pubk;
   1713        case dhKey:
   1714            pubKeyHandle = seckey_FindPublicKeyHandle(privk, pubk);
   1715            if (pubKeyHandle == CK_INVALID_HANDLE)
   1716                break;
   1717            rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
   1718                                    CKA_BASE, arena, &pubk->u.dh.base);
   1719            if (rv != SECSuccess)
   1720                break;
   1721            rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
   1722                                    CKA_PRIME, arena, &pubk->u.dh.prime);
   1723            if (rv != SECSuccess)
   1724                break;
   1725            rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
   1726                                    CKA_VALUE, arena, &pubk->u.dh.publicValue);
   1727            if (rv != SECSuccess)
   1728                break;
   1729            return pubk;
   1730        case rsaKey:
   1731            rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
   1732                                    CKA_MODULUS, arena, &pubk->u.rsa.modulus);
   1733            if (rv != SECSuccess)
   1734                break;
   1735            rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
   1736                                    CKA_PUBLIC_EXPONENT, arena, &pubk->u.rsa.publicExponent);
   1737            if (rv != SECSuccess)
   1738                break;
   1739            return pubk;
   1740        case ecKey:
   1741            rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
   1742                                    CKA_EC_PARAMS, arena, &pubk->u.ec.DEREncodedParams);
   1743            if (rv != SECSuccess) {
   1744                break;
   1745            }
   1746            rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
   1747                                    CKA_EC_POINT, arena, &pubk->u.ec.publicValue);
   1748            if (rv != SECSuccess || pubk->u.ec.publicValue.len == 0) {
   1749                pubKeyHandle = seckey_FindPublicKeyHandle(privk, pubk);
   1750                if (pubKeyHandle == CK_INVALID_HANDLE)
   1751                    break;
   1752                rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
   1753                                        CKA_EC_POINT, arena, &pubk->u.ec.publicValue);
   1754                if (rv != SECSuccess)
   1755                    break;
   1756            }
   1757            /* ec.publicValue should be decoded, PKCS #11 defines CKA_EC_POINT
   1758             * as encoded, but it's not always. try do decoded it and if it
   1759             * succeeds store the decoded value */
   1760            rv = SEC_QuickDERDecodeItem(arena, &decodedPoint,
   1761                                        SEC_ASN1_GET(SEC_OctetStringTemplate), &pubk->u.ec.publicValue);
   1762            if (rv == SECSuccess) {
   1763                /* both values are in the public key arena, so it's safe to
   1764                 * overwrite  the old value */
   1765                pubk->u.ec.publicValue = decodedPoint;
   1766            }
   1767 
   1768            pubk->u.ec.encoding = ECPoint_Undefined;
   1769            return pubk;
   1770        case edKey:
   1771        case ecMontKey:
   1772            rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
   1773                                    CKA_EC_PARAMS, arena, &pubk->u.ec.DEREncodedParams);
   1774            if (rv != SECSuccess) {
   1775                break;
   1776            }
   1777            rv = PK11_ReadAttribute(privk->pkcs11Slot, privk->pkcs11ID,
   1778                                    CKA_EC_POINT, arena, &pubk->u.ec.publicValue);
   1779            if (rv != SECSuccess || pubk->u.ec.publicValue.len == 0) {
   1780                pubKeyHandle = seckey_FindPublicKeyHandle(privk, pubk);
   1781                if (pubKeyHandle == CK_INVALID_HANDLE) {
   1782                    break;
   1783                }
   1784                rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
   1785                                        CKA_EC_POINT, arena, &pubk->u.ec.publicValue);
   1786                if (rv != SECSuccess) {
   1787                    break;
   1788                }
   1789            }
   1790            pubk->u.ec.encoding = ECPoint_Undefined;
   1791            return pubk;
   1792        case mldsaKey:
   1793            pubKeyHandle = seckey_FindPublicKeyHandle(privk, pubk);
   1794            if (pubKeyHandle == CK_INVALID_HANDLE) {
   1795                break;
   1796            }
   1797            pubk->u.mldsa.paramSet = seckey_GetParameterSet(privk);
   1798            if (pubk->u.mldsa.paramSet == SEC_OID_UNKNOWN) {
   1799                break;
   1800            }
   1801            rv = PK11_ReadAttribute(privk->pkcs11Slot, pubKeyHandle,
   1802                                    CKA_VALUE, arena, &pubk->u.mldsa.publicValue);
   1803            if (rv != SECSuccess) {
   1804                break;
   1805            }
   1806            return pubk;
   1807 
   1808        default:
   1809            break;
   1810    }
   1811 
   1812    /* must use Destroy public key here, because some paths create temporary
   1813     * PKCS #11 objects which need to be freed */
   1814    SECKEY_DestroyPublicKey(pubk);
   1815    return NULL;
   1816 }
   1817 
   1818 static CERTSubjectPublicKeyInfo *
   1819 seckey_CreateSubjectPublicKeyInfo_helper(SECKEYPublicKey *pubk)
   1820 {
   1821    CERTSubjectPublicKeyInfo *spki;
   1822    PLArenaPool *arena;
   1823    SECItem params = { siBuffer, NULL, 0 };
   1824    SECOidTag tag;
   1825 
   1826    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   1827    if (arena == NULL) {
   1828        PORT_SetError(SEC_ERROR_NO_MEMORY);
   1829        return NULL;
   1830    }
   1831 
   1832    spki = (CERTSubjectPublicKeyInfo *)PORT_ArenaZAlloc(arena, sizeof(*spki));
   1833    if (spki != NULL) {
   1834        SECStatus rv;
   1835        SECItem *rv_item;
   1836 
   1837        spki->arena = arena;
   1838        switch (pubk->keyType) {
   1839            case rsaKey:
   1840                rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
   1841                                           SEC_OID_PKCS1_RSA_ENCRYPTION, 0);
   1842                if (rv == SECSuccess) {
   1843                    /*
   1844                     * DER encode the public key into the subjectPublicKeyInfo.
   1845                     */
   1846                    prepare_rsa_pub_key_for_asn1(pubk);
   1847                    rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
   1848                                                 pubk, SECKEY_RSAPublicKeyTemplate);
   1849                    if (rv_item != NULL) {
   1850                        /*
   1851                         * The stored value is supposed to be a BIT_STRING,
   1852                         * so convert the length.
   1853                         */
   1854                        spki->subjectPublicKey.len <<= 3;
   1855                        /*
   1856                         * We got a good one; return it.
   1857                         */
   1858                        return spki;
   1859                    }
   1860                }
   1861                break;
   1862            case dsaKey:
   1863                /* DER encode the params. */
   1864                prepare_pqg_params_for_asn1(&pubk->u.dsa.params);
   1865                rv_item = SEC_ASN1EncodeItem(arena, &params, &pubk->u.dsa.params,
   1866                                             SECKEY_PQGParamsTemplate);
   1867                if (rv_item != NULL) {
   1868                    rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
   1869                                               SEC_OID_ANSIX9_DSA_SIGNATURE,
   1870                                               &params);
   1871                    if (rv == SECSuccess) {
   1872                        /*
   1873                         * DER encode the public key into the subjectPublicKeyInfo.
   1874                         */
   1875                        prepare_dsa_pub_key_for_asn1(pubk);
   1876                        rv_item = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey,
   1877                                                     pubk,
   1878                                                     SECKEY_DSAPublicKeyTemplate);
   1879                        if (rv_item != NULL) {
   1880                            /*
   1881                             * The stored value is supposed to be a BIT_STRING,
   1882                             * so convert the length.
   1883                             */
   1884                            spki->subjectPublicKey.len <<= 3;
   1885                            /*
   1886                             * We got a good one; return it.
   1887                             */
   1888                            return spki;
   1889                        }
   1890                    }
   1891                }
   1892                SECITEM_FreeItem(&params, PR_FALSE);
   1893                break;
   1894            case ecKey:
   1895                rv = SECITEM_CopyItem(arena, &params,
   1896                                      &pubk->u.ec.DEREncodedParams);
   1897                if (rv != SECSuccess) {
   1898                    break;
   1899                }
   1900 
   1901                tag = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
   1902                rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
   1903                                           tag,
   1904                                           &params);
   1905                if (rv != SECSuccess) {
   1906                    break;
   1907                }
   1908 
   1909                rv = SECITEM_CopyItem(arena, &spki->subjectPublicKey,
   1910                                      &pubk->u.ec.publicValue);
   1911 
   1912                if (rv == SECSuccess) {
   1913                    /*
   1914                     * The stored value is supposed to be a BIT_STRING,
   1915                     * so convert the length.
   1916                     */
   1917                    spki->subjectPublicKey.len <<= 3;
   1918                    /*
   1919                     * We got a good one; return it.
   1920                     */
   1921                    return spki;
   1922                }
   1923                break;
   1924            case edKey:
   1925            case ecMontKey:
   1926                tag = SECKEY_GetECCOid(&pubk->u.ec.DEREncodedParams);
   1927                rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
   1928                                           tag,
   1929                                           &params);
   1930                if (rv != SECSuccess) {
   1931                    break;
   1932                }
   1933 
   1934                rv = SECITEM_CopyItem(arena, &spki->subjectPublicKey,
   1935                                      &pubk->u.ec.publicValue);
   1936 
   1937                if (rv == SECSuccess) {
   1938                    /*
   1939                     * The stored value is supposed to be a BIT_STRING,
   1940                     * so convert the length.
   1941                     */
   1942                    spki->subjectPublicKey.len <<= 3;
   1943                    /*
   1944                     * We got a good one; return it.
   1945                     */
   1946                    return spki;
   1947                }
   1948                break;
   1949            case mldsaKey:
   1950                tag = pubk->u.mldsa.paramSet;
   1951                rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
   1952                                           tag, NULL);
   1953                if (rv != SECSuccess) {
   1954                    break;
   1955                }
   1956 
   1957                rv = SECITEM_CopyItem(arena, &spki->subjectPublicKey,
   1958                                      &pubk->u.mldsa.publicValue);
   1959 
   1960                if (rv == SECSuccess) {
   1961                    /*
   1962                     * The stored value is supposed to be a BIT_STRING,
   1963                     * so convert the length.
   1964                     */
   1965                    spki->subjectPublicKey.len <<= 3;
   1966                    /*
   1967                     * We got a good one; return it.
   1968                     */
   1969                    return spki;
   1970                }
   1971                break;
   1972            case dhKey: /* later... */
   1973 
   1974                break;
   1975            default:
   1976                break;
   1977        }
   1978    } else {
   1979        PORT_SetError(SEC_ERROR_NO_MEMORY);
   1980    }
   1981 
   1982    PORT_FreeArena(arena, PR_FALSE);
   1983    return NULL;
   1984 }
   1985 
   1986 CERTSubjectPublicKeyInfo *
   1987 SECKEY_CreateSubjectPublicKeyInfo(const SECKEYPublicKey *pubk)
   1988 {
   1989    CERTSubjectPublicKeyInfo *spki;
   1990    SECKEYPublicKey *tempKey;
   1991 
   1992    if (!pubk) {
   1993        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1994        return NULL;
   1995    }
   1996 
   1997    tempKey = SECKEY_CopyPublicKey(pubk);
   1998    if (!tempKey) {
   1999        return NULL;
   2000    }
   2001    spki = seckey_CreateSubjectPublicKeyInfo_helper(tempKey);
   2002    SECKEY_DestroyPublicKey(tempKey);
   2003    return spki;
   2004 }
   2005 
   2006 void
   2007 SECKEY_DestroySubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki)
   2008 {
   2009    if (spki && spki->arena) {
   2010        PORT_FreeArena(spki->arena, PR_FALSE);
   2011    }
   2012 }
   2013 
   2014 SECItem *
   2015 SECKEY_EncodeDERSubjectPublicKeyInfo(const SECKEYPublicKey *pubk)
   2016 {
   2017    CERTSubjectPublicKeyInfo *spki = NULL;
   2018    SECItem *spkiDER = NULL;
   2019 
   2020    /* get the subjectpublickeyinfo */
   2021    spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
   2022    if (spki == NULL) {
   2023        goto finish;
   2024    }
   2025 
   2026    /* DER-encode the subjectpublickeyinfo */
   2027    spkiDER = SEC_ASN1EncodeItem(NULL /*arena*/, NULL /*dest*/, spki,
   2028                                 CERT_SubjectPublicKeyInfoTemplate);
   2029 
   2030    SECKEY_DestroySubjectPublicKeyInfo(spki);
   2031 
   2032 finish:
   2033    return spkiDER;
   2034 }
   2035 
   2036 CERTSubjectPublicKeyInfo *
   2037 SECKEY_DecodeDERSubjectPublicKeyInfo(const SECItem *spkider)
   2038 {
   2039    PLArenaPool *arena;
   2040    CERTSubjectPublicKeyInfo *spki;
   2041    SECStatus rv;
   2042    SECItem newSpkider;
   2043 
   2044    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   2045    if (arena == NULL) {
   2046        PORT_SetError(SEC_ERROR_NO_MEMORY);
   2047        return NULL;
   2048    }
   2049 
   2050    spki = (CERTSubjectPublicKeyInfo *)
   2051        PORT_ArenaZAlloc(arena, sizeof(CERTSubjectPublicKeyInfo));
   2052    if (spki != NULL) {
   2053        spki->arena = arena;
   2054 
   2055        /* copy the DER into the arena, since Quick DER returns data that points
   2056           into the DER input, which may get freed by the caller */
   2057        rv = SECITEM_CopyItem(arena, &newSpkider, spkider);
   2058        if (rv == SECSuccess) {
   2059            rv = SEC_QuickDERDecodeItem(arena, spki,
   2060                                        CERT_SubjectPublicKeyInfoTemplate, &newSpkider);
   2061        }
   2062        if (rv == SECSuccess) {
   2063            return spki;
   2064        }
   2065    } else {
   2066        PORT_SetError(SEC_ERROR_NO_MEMORY);
   2067    }
   2068 
   2069    PORT_FreeArena(arena, PR_FALSE);
   2070    return NULL;
   2071 }
   2072 
   2073 /*
   2074 * Decode a base64 ascii encoded DER encoded subject public key info.
   2075 */
   2076 CERTSubjectPublicKeyInfo *
   2077 SECKEY_ConvertAndDecodeSubjectPublicKeyInfo(const char *spkistr)
   2078 {
   2079    CERTSubjectPublicKeyInfo *spki;
   2080    SECStatus rv;
   2081    SECItem der;
   2082 
   2083    rv = ATOB_ConvertAsciiToItem(&der, spkistr);
   2084    if (rv != SECSuccess)
   2085        return NULL;
   2086 
   2087    spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der);
   2088 
   2089    PORT_Free(der.data);
   2090    return spki;
   2091 }
   2092 
   2093 /*
   2094 * Decode a base64 ascii encoded DER encoded public key and challenge
   2095 * Verify digital signature and make sure challenge matches
   2096 */
   2097 CERTSubjectPublicKeyInfo *
   2098 SECKEY_ConvertAndDecodePublicKeyAndChallenge(char *pkacstr, char *challenge,
   2099                                             void *wincx)
   2100 {
   2101    CERTSubjectPublicKeyInfo *spki = NULL;
   2102    CERTPublicKeyAndChallenge pkac;
   2103    SECStatus rv;
   2104    SECItem signedItem;
   2105    PLArenaPool *arena = NULL;
   2106    CERTSignedData sd;
   2107    SECItem sig;
   2108    SECKEYPublicKey *pubKey = NULL;
   2109    unsigned int len;
   2110 
   2111    signedItem.data = NULL;
   2112 
   2113    /* convert the base64 encoded data to binary */
   2114    rv = ATOB_ConvertAsciiToItem(&signedItem, pkacstr);
   2115    if (rv != SECSuccess) {
   2116        goto loser;
   2117    }
   2118 
   2119    /* create an arena */
   2120    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   2121    if (arena == NULL) {
   2122        goto loser;
   2123    }
   2124 
   2125    /* decode the outer wrapping of signed data */
   2126    PORT_Memset(&sd, 0, sizeof(CERTSignedData));
   2127    rv = SEC_QuickDERDecodeItem(arena, &sd, CERT_SignedDataTemplate, &signedItem);
   2128    if (rv) {
   2129        goto loser;
   2130    }
   2131 
   2132    /* decode the public key and challenge wrapper */
   2133    PORT_Memset(&pkac, 0, sizeof(CERTPublicKeyAndChallenge));
   2134    rv = SEC_QuickDERDecodeItem(arena, &pkac, CERT_PublicKeyAndChallengeTemplate,
   2135                                &sd.data);
   2136    if (rv) {
   2137        goto loser;
   2138    }
   2139 
   2140    /* decode the subject public key info */
   2141    spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&pkac.spki);
   2142    if (spki == NULL) {
   2143        goto loser;
   2144    }
   2145 
   2146    /* get the public key */
   2147    pubKey = seckey_ExtractPublicKey(spki);
   2148    if (pubKey == NULL) {
   2149        goto loser;
   2150    }
   2151 
   2152    /* check the signature */
   2153    sig = sd.signature;
   2154    DER_ConvertBitString(&sig);
   2155    rv = VFY_VerifyDataWithAlgorithmID(sd.data.data, sd.data.len, pubKey, &sig,
   2156                                       &(sd.signatureAlgorithm), NULL, wincx);
   2157    if (rv != SECSuccess) {
   2158        goto loser;
   2159    }
   2160 
   2161    /* check the challenge */
   2162    if (challenge) {
   2163        len = PORT_Strlen(challenge);
   2164        /* length is right */
   2165        if (len != pkac.challenge.len) {
   2166            goto loser;
   2167        }
   2168        /* actual data is right */
   2169        if (PORT_Memcmp(challenge, pkac.challenge.data, len) != 0) {
   2170            goto loser;
   2171        }
   2172    }
   2173    goto done;
   2174 
   2175 loser:
   2176    /* make sure that we return null if we got an error */
   2177    if (spki) {
   2178        SECKEY_DestroySubjectPublicKeyInfo(spki);
   2179    }
   2180    spki = NULL;
   2181 
   2182 done:
   2183    if (signedItem.data) {
   2184        PORT_Free(signedItem.data);
   2185    }
   2186    if (arena) {
   2187        PORT_FreeArena(arena, PR_FALSE);
   2188    }
   2189    if (pubKey) {
   2190        SECKEY_DestroyPublicKey(pubKey);
   2191    }
   2192 
   2193    return spki;
   2194 }
   2195 
   2196 void
   2197 SECKEY_DestroyPrivateKeyInfo(SECKEYPrivateKeyInfo *pvk,
   2198                             PRBool freeit)
   2199 {
   2200    PLArenaPool *poolp;
   2201 
   2202    if (pvk != NULL) {
   2203        if (pvk->arena) {
   2204            poolp = pvk->arena;
   2205            /* zero structure since PORT_FreeArena does not support
   2206             * this yet.
   2207             */
   2208            PORT_Memset(pvk->privateKey.data, 0, pvk->privateKey.len);
   2209            PORT_Memset(pvk, 0, sizeof(*pvk));
   2210            if (freeit == PR_TRUE) {
   2211                PORT_FreeArena(poolp, PR_TRUE);
   2212            } else {
   2213                pvk->arena = poolp;
   2214            }
   2215        } else {
   2216            SECITEM_ZfreeItem(&pvk->version, PR_FALSE);
   2217            SECITEM_ZfreeItem(&pvk->privateKey, PR_FALSE);
   2218            SECOID_DestroyAlgorithmID(&pvk->algorithm, PR_FALSE);
   2219            PORT_Memset(pvk, 0, sizeof(*pvk));
   2220            if (freeit == PR_TRUE) {
   2221                PORT_Free(pvk);
   2222            }
   2223        }
   2224    }
   2225 }
   2226 
   2227 void
   2228 SECKEY_DestroyEncryptedPrivateKeyInfo(SECKEYEncryptedPrivateKeyInfo *epki,
   2229                                      PRBool freeit)
   2230 {
   2231    PLArenaPool *poolp;
   2232 
   2233    if (epki != NULL) {
   2234        if (epki->arena) {
   2235            poolp = epki->arena;
   2236            /* zero structure since PORT_FreeArena does not support
   2237             * this yet.
   2238             */
   2239            PORT_Memset(epki->encryptedData.data, 0, epki->encryptedData.len);
   2240            PORT_Memset(epki, 0, sizeof(*epki));
   2241            if (freeit == PR_TRUE) {
   2242                PORT_FreeArena(poolp, PR_TRUE);
   2243            } else {
   2244                epki->arena = poolp;
   2245            }
   2246        } else {
   2247            SECITEM_ZfreeItem(&epki->encryptedData, PR_FALSE);
   2248            SECOID_DestroyAlgorithmID(&epki->algorithm, PR_FALSE);
   2249            PORT_Memset(epki, 0, sizeof(*epki));
   2250            if (freeit == PR_TRUE) {
   2251                PORT_Free(epki);
   2252            }
   2253        }
   2254    }
   2255 }
   2256 
   2257 SECStatus
   2258 SECKEY_CopyPrivateKeyInfo(PLArenaPool *poolp,
   2259                          SECKEYPrivateKeyInfo *to,
   2260                          const SECKEYPrivateKeyInfo *from)
   2261 {
   2262    SECStatus rv = SECFailure;
   2263 
   2264    if ((to == NULL) || (from == NULL)) {
   2265        return SECFailure;
   2266    }
   2267 
   2268    rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm);
   2269    if (rv != SECSuccess) {
   2270        return SECFailure;
   2271    }
   2272    rv = SECITEM_CopyItem(poolp, &to->privateKey, &from->privateKey);
   2273    if (rv != SECSuccess) {
   2274        return SECFailure;
   2275    }
   2276    rv = SECITEM_CopyItem(poolp, &to->version, &from->version);
   2277 
   2278    return rv;
   2279 }
   2280 
   2281 SECStatus
   2282 SECKEY_CopyEncryptedPrivateKeyInfo(PLArenaPool *poolp,
   2283                                   SECKEYEncryptedPrivateKeyInfo *to,
   2284                                   const SECKEYEncryptedPrivateKeyInfo *from)
   2285 {
   2286    SECStatus rv = SECFailure;
   2287 
   2288    if ((to == NULL) || (from == NULL)) {
   2289        return SECFailure;
   2290    }
   2291 
   2292    rv = SECOID_CopyAlgorithmID(poolp, &to->algorithm, &from->algorithm);
   2293    if (rv != SECSuccess) {
   2294        return SECFailure;
   2295    }
   2296    rv = SECITEM_CopyItem(poolp, &to->encryptedData, &from->encryptedData);
   2297 
   2298    return rv;
   2299 }
   2300 
   2301 KeyType
   2302 SECKEY_GetPrivateKeyType(const SECKEYPrivateKey *privKey)
   2303 {
   2304    return privKey->keyType;
   2305 }
   2306 
   2307 KeyType
   2308 SECKEY_GetPublicKeyType(const SECKEYPublicKey *pubKey)
   2309 {
   2310    return pubKey->keyType;
   2311 }
   2312 
   2313 SECKEYPublicKey *
   2314 SECKEY_ImportDERPublicKey(const SECItem *derKey, CK_KEY_TYPE type)
   2315 {
   2316    SECKEYPublicKey *pubk = NULL;
   2317    SECStatus rv = SECFailure;
   2318    SECItem newDerKey;
   2319    PLArenaPool *arena = NULL;
   2320 
   2321    if (!derKey) {
   2322        return NULL;
   2323    }
   2324 
   2325    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   2326    if (arena == NULL) {
   2327        PORT_SetError(SEC_ERROR_NO_MEMORY);
   2328        goto finish;
   2329    }
   2330 
   2331    pubk = PORT_ArenaZNew(arena, SECKEYPublicKey);
   2332    if (pubk == NULL) {
   2333        goto finish;
   2334    }
   2335    pubk->arena = arena;
   2336 
   2337    rv = SECITEM_CopyItem(pubk->arena, &newDerKey, derKey);
   2338    if (SECSuccess != rv) {
   2339        goto finish;
   2340    }
   2341 
   2342    pubk->pkcs11Slot = NULL;
   2343    pubk->pkcs11ID = CK_INVALID_HANDLE;
   2344 
   2345    switch (type) {
   2346        case CKK_RSA:
   2347            prepare_rsa_pub_key_for_asn1(pubk);
   2348            rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_RSAPublicKeyTemplate, &newDerKey);
   2349            pubk->keyType = rsaKey;
   2350            break;
   2351        case CKK_DSA:
   2352            prepare_dsa_pub_key_for_asn1(pubk);
   2353            rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DSAPublicKeyTemplate, &newDerKey);
   2354            pubk->keyType = dsaKey;
   2355            break;
   2356        case CKK_DH:
   2357            prepare_dh_pub_key_for_asn1(pubk);
   2358            rv = SEC_QuickDERDecodeItem(pubk->arena, pubk, SECKEY_DHPublicKeyTemplate, &newDerKey);
   2359            pubk->keyType = dhKey;
   2360            break;
   2361        case CKK_ML_DSA:
   2362            pubk->keyType = mldsaKey;
   2363            /* ml_dsa has no derencoding */
   2364            pubk->u.mldsa.publicValue = newDerKey;
   2365            pubk->u.mldsa.paramSet = SECKEY_MLDSAOidParamsFromLen(newDerKey.len,
   2366                                                                  SECKEYPubKeyType);
   2367            if (pubk->u.mldsa.paramSet == SEC_OID_UNKNOWN) {
   2368                PORT_SetError(SEC_ERROR_BAD_KEY);
   2369                rv = SECFailure;
   2370            }
   2371            break;
   2372        default:
   2373            rv = SECFailure;
   2374            break;
   2375    }
   2376 
   2377 finish:
   2378    if (rv != SECSuccess) {
   2379        if (arena != NULL) {
   2380            PORT_FreeArena(arena, PR_FALSE);
   2381        }
   2382        pubk = NULL;
   2383    }
   2384    return pubk;
   2385 }
   2386 
   2387 SECKEYPrivateKeyList *
   2388 SECKEY_NewPrivateKeyList(void)
   2389 {
   2390    PLArenaPool *arena = NULL;
   2391    SECKEYPrivateKeyList *ret = NULL;
   2392 
   2393    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   2394    if (arena == NULL) {
   2395        goto loser;
   2396    }
   2397 
   2398    ret = (SECKEYPrivateKeyList *)PORT_ArenaZAlloc(arena,
   2399                                                   sizeof(SECKEYPrivateKeyList));
   2400    if (ret == NULL) {
   2401        goto loser;
   2402    }
   2403 
   2404    ret->arena = arena;
   2405 
   2406    PR_INIT_CLIST(&ret->list);
   2407 
   2408    return (ret);
   2409 
   2410 loser:
   2411    if (arena != NULL) {
   2412        PORT_FreeArena(arena, PR_FALSE);
   2413    }
   2414 
   2415    return (NULL);
   2416 }
   2417 
   2418 void
   2419 SECKEY_DestroyPrivateKeyList(SECKEYPrivateKeyList *keys)
   2420 {
   2421    while (!PR_CLIST_IS_EMPTY(&keys->list)) {
   2422        SECKEY_RemovePrivateKeyListNode(
   2423            (SECKEYPrivateKeyListNode *)(PR_LIST_HEAD(&keys->list)));
   2424    }
   2425 
   2426    PORT_FreeArena(keys->arena, PR_FALSE);
   2427 
   2428    return;
   2429 }
   2430 
   2431 void
   2432 SECKEY_RemovePrivateKeyListNode(SECKEYPrivateKeyListNode *node)
   2433 {
   2434    PR_ASSERT(node->key);
   2435    SECKEY_DestroyPrivateKey(node->key);
   2436    node->key = NULL;
   2437    PR_REMOVE_LINK(&node->links);
   2438    return;
   2439 }
   2440 
   2441 SECStatus
   2442 SECKEY_AddPrivateKeyToListTail(SECKEYPrivateKeyList *list,
   2443                               SECKEYPrivateKey *key)
   2444 {
   2445    SECKEYPrivateKeyListNode *node;
   2446 
   2447    node = (SECKEYPrivateKeyListNode *)PORT_ArenaZAlloc(list->arena,
   2448                                                        sizeof(SECKEYPrivateKeyListNode));
   2449    if (node == NULL) {
   2450        goto loser;
   2451    }
   2452 
   2453    PR_INSERT_BEFORE(&node->links, &list->list);
   2454    node->key = key;
   2455    return (SECSuccess);
   2456 
   2457 loser:
   2458    return (SECFailure);
   2459 }
   2460 
   2461 SECKEYPublicKeyList *
   2462 SECKEY_NewPublicKeyList(void)
   2463 {
   2464    PLArenaPool *arena = NULL;
   2465    SECKEYPublicKeyList *ret = NULL;
   2466 
   2467    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   2468    if (arena == NULL) {
   2469        goto loser;
   2470    }
   2471 
   2472    ret = (SECKEYPublicKeyList *)PORT_ArenaZAlloc(arena,
   2473                                                  sizeof(SECKEYPublicKeyList));
   2474    if (ret == NULL) {
   2475        goto loser;
   2476    }
   2477 
   2478    ret->arena = arena;
   2479 
   2480    PR_INIT_CLIST(&ret->list);
   2481 
   2482    return (ret);
   2483 
   2484 loser:
   2485    if (arena != NULL) {
   2486        PORT_FreeArena(arena, PR_FALSE);
   2487    }
   2488 
   2489    return (NULL);
   2490 }
   2491 
   2492 void
   2493 SECKEY_DestroyPublicKeyList(SECKEYPublicKeyList *keys)
   2494 {
   2495    while (!PR_CLIST_IS_EMPTY(&keys->list)) {
   2496        SECKEY_RemovePublicKeyListNode(
   2497            (SECKEYPublicKeyListNode *)(PR_LIST_HEAD(&keys->list)));
   2498    }
   2499 
   2500    PORT_FreeArena(keys->arena, PR_FALSE);
   2501 
   2502    return;
   2503 }
   2504 
   2505 void
   2506 SECKEY_RemovePublicKeyListNode(SECKEYPublicKeyListNode *node)
   2507 {
   2508    PR_ASSERT(node->key);
   2509    SECKEY_DestroyPublicKey(node->key);
   2510    node->key = NULL;
   2511    PR_REMOVE_LINK(&node->links);
   2512    return;
   2513 }
   2514 
   2515 SECStatus
   2516 SECKEY_AddPublicKeyToListTail(SECKEYPublicKeyList *list,
   2517                              SECKEYPublicKey *key)
   2518 {
   2519    SECKEYPublicKeyListNode *node;
   2520 
   2521    node = (SECKEYPublicKeyListNode *)PORT_ArenaZAlloc(list->arena,
   2522                                                       sizeof(SECKEYPublicKeyListNode));
   2523    if (node == NULL) {
   2524        goto loser;
   2525    }
   2526 
   2527    PR_INSERT_BEFORE(&node->links, &list->list);
   2528    node->key = key;
   2529    return (SECSuccess);
   2530 
   2531 loser:
   2532    return (SECFailure);
   2533 }
   2534 
   2535 #define SECKEY_CacheAttribute(key, attribute)                                                   \
   2536    if (CK_TRUE == PK11_HasAttributeSet(key->pkcs11Slot, key->pkcs11ID, attribute, PR_FALSE)) { \
   2537        key->staticflags |= SECKEY_##attribute;                                                 \
   2538    } else {                                                                                    \
   2539        key->staticflags &= (~SECKEY_##attribute);                                              \
   2540    }
   2541 
   2542 SECStatus
   2543 SECKEY_CacheStaticFlags(SECKEYPrivateKey *key)
   2544 {
   2545    SECStatus rv = SECFailure;
   2546    if (key && key->pkcs11Slot && key->pkcs11ID) {
   2547        key->staticflags |= SECKEY_Attributes_Cached;
   2548        SECKEY_CacheAttribute(key, CKA_PRIVATE);
   2549        SECKEY_CacheAttribute(key, CKA_ALWAYS_AUTHENTICATE);
   2550        rv = SECSuccess;
   2551    }
   2552    return rv;
   2553 }
   2554 
   2555 SECOidTag
   2556 SECKEY_GetECCOid(const SECKEYECParams *params)
   2557 {
   2558    SECItem oid = { siBuffer, NULL, 0 };
   2559    SECOidData *oidData = NULL;
   2560 
   2561    /*
   2562     * params->data needs to contain the ASN encoding of an object ID (OID)
   2563     * representing a named curve. Here, we strip away everything
   2564     * before the actual OID and use the OID to look up a named curve.
   2565     */
   2566    if (params->data[0] != SEC_ASN1_OBJECT_ID)
   2567        return 0;
   2568    oid.len = params->len - 2;
   2569    oid.data = params->data + 2;
   2570    if ((oidData = SECOID_FindOID(&oid)) == NULL)
   2571        return 0;
   2572 
   2573    return oidData->offset;
   2574 }
   2575 
   2576 static CK_MECHANISM_TYPE
   2577 sec_GetHashMechanismByOidTag(SECOidTag tag)
   2578 {
   2579    switch (tag) {
   2580        case SEC_OID_SHA512:
   2581            return CKM_SHA512;
   2582        case SEC_OID_SHA384:
   2583            return CKM_SHA384;
   2584        case SEC_OID_SHA256:
   2585            return CKM_SHA256;
   2586        case SEC_OID_SHA224:
   2587            return CKM_SHA224;
   2588        case SEC_OID_SHA1:
   2589            return CKM_SHA_1;
   2590        default:
   2591            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
   2592            return CKM_INVALID_MECHANISM;
   2593    }
   2594 }
   2595 
   2596 CK_RSA_PKCS_MGF_TYPE
   2597 SEC_GetMgfTypeByOidTag(SECOidTag tag)
   2598 {
   2599    switch (tag) {
   2600        case SEC_OID_SHA3_512:
   2601            return CKG_MGF1_SHA3_512;
   2602        case SEC_OID_SHA3_384:
   2603            return CKG_MGF1_SHA3_384;
   2604        case SEC_OID_SHA3_256:
   2605            return CKG_MGF1_SHA3_256;
   2606        case SEC_OID_SHA3_224:
   2607            return CKG_MGF1_SHA3_224;
   2608        case SEC_OID_SHA512:
   2609            return CKG_MGF1_SHA512;
   2610        case SEC_OID_SHA384:
   2611            return CKG_MGF1_SHA384;
   2612        case SEC_OID_SHA256:
   2613            return CKG_MGF1_SHA256;
   2614        case SEC_OID_SHA224:
   2615            return CKG_MGF1_SHA224;
   2616        case SEC_OID_SHA1:
   2617            return CKG_MGF1_SHA1;
   2618        default:
   2619            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
   2620            return 0;
   2621    }
   2622 }
   2623 
   2624 SECStatus
   2625 sec_DecodeRSAPSSParams(PLArenaPool *arena,
   2626                       const SECItem *params,
   2627                       SECOidTag *retHashAlg, SECOidTag *retMaskHashAlg,
   2628                       unsigned long *retSaltLength)
   2629 {
   2630    SECKEYRSAPSSParams pssParams;
   2631    SECOidTag hashAlg;
   2632    SECOidTag maskHashAlg;
   2633    unsigned long saltLength;
   2634    unsigned long trailerField;
   2635    SECStatus rv;
   2636 
   2637    PORT_Memset(&pssParams, 0, sizeof(pssParams));
   2638    rv = SEC_QuickDERDecodeItem(arena, &pssParams,
   2639                                SECKEY_RSAPSSParamsTemplate,
   2640                                params);
   2641    if (rv != SECSuccess) {
   2642        return rv;
   2643    }
   2644 
   2645    if (pssParams.hashAlg) {
   2646        hashAlg = SECOID_GetAlgorithmTag(pssParams.hashAlg);
   2647    } else {
   2648        hashAlg = SEC_OID_SHA1; /* default, SHA-1 */
   2649    }
   2650 
   2651    if (pssParams.maskAlg) {
   2652        SECAlgorithmID algId;
   2653 
   2654        if (SECOID_GetAlgorithmTag(pssParams.maskAlg) != SEC_OID_PKCS1_MGF1) {
   2655            /* only MGF1 is known to PKCS#11 */
   2656            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
   2657            return SECFailure;
   2658        }
   2659 
   2660        rv = SEC_QuickDERDecodeItem(arena, &algId,
   2661                                    SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
   2662                                    &pssParams.maskAlg->parameters);
   2663        if (rv != SECSuccess) {
   2664            return rv;
   2665        }
   2666        maskHashAlg = SECOID_GetAlgorithmTag(&algId);
   2667    } else {
   2668        maskHashAlg = SEC_OID_SHA1; /* default, MGF1 with SHA-1 */
   2669    }
   2670 
   2671    if (pssParams.saltLength.data) {
   2672        rv = SEC_ASN1DecodeInteger((SECItem *)&pssParams.saltLength, &saltLength);
   2673        if (rv != SECSuccess) {
   2674            return rv;
   2675        }
   2676    } else {
   2677        saltLength = 20; /* default, 20 */
   2678    }
   2679 
   2680    if (pssParams.trailerField.data) {
   2681        rv = SEC_ASN1DecodeInteger((SECItem *)&pssParams.trailerField, &trailerField);
   2682        if (rv != SECSuccess) {
   2683            return rv;
   2684        }
   2685        if (trailerField != 1) {
   2686            /* the value must be 1, which represents the trailer field
   2687             * with hexadecimal value 0xBC */
   2688            PORT_SetError(SEC_ERROR_INVALID_ARGS);
   2689            return SECFailure;
   2690        }
   2691    }
   2692 
   2693    if (retHashAlg) {
   2694        *retHashAlg = hashAlg;
   2695    }
   2696    if (retMaskHashAlg) {
   2697        *retMaskHashAlg = maskHashAlg;
   2698    }
   2699    if (retSaltLength) {
   2700        *retSaltLength = saltLength;
   2701    }
   2702 
   2703    return SECSuccess;
   2704 }
   2705 
   2706 SECStatus
   2707 sec_DecodeRSAPSSParamsToMechanism(PLArenaPool *arena,
   2708                                  const SECItem *params,
   2709                                  CK_RSA_PKCS_PSS_PARAMS *mech,
   2710                                  SECOidTag *hashAlgp)
   2711 {
   2712    SECOidTag hashAlg;
   2713    SECOidTag maskHashAlg;
   2714    unsigned long saltLength;
   2715    SECStatus rv;
   2716 
   2717    rv = sec_DecodeRSAPSSParams(arena, params,
   2718                                &hashAlg, &maskHashAlg, &saltLength);
   2719    if (rv != SECSuccess) {
   2720        return SECFailure;
   2721    }
   2722    *hashAlgp = hashAlg;
   2723 
   2724    mech->hashAlg = sec_GetHashMechanismByOidTag(hashAlg);
   2725    if (mech->hashAlg == CKM_INVALID_MECHANISM) {
   2726        return SECFailure;
   2727    }
   2728 
   2729    mech->mgf = SEC_GetMgfTypeByOidTag(maskHashAlg);
   2730    if (mech->mgf == 0) {
   2731        return SECFailure;
   2732    }
   2733 
   2734    mech->sLen = saltLength;
   2735 
   2736    return SECSuccess;
   2737 }