tor-browser

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

pk11akey.c (104801B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 /*
      5 * This file contains functions to manage asymetric keys, (public and
      6 * private keys).
      7 */
      8 #include <stddef.h>
      9 
     10 #include "seccomon.h"
     11 #include "secmod.h"
     12 #include "secmodi.h"
     13 #include "secmodti.h"
     14 #include "pkcs11.h"
     15 #include "pkcs11t.h"
     16 #include "pk11func.h"
     17 #include "cert.h"
     18 #include "keyhi.h"
     19 #include "keyi.h"
     20 #include "secitem.h"
     21 #include "secasn1.h"
     22 #include "secoid.h"
     23 #include "secerr.h"
     24 #include "sechash.h"
     25 
     26 #include "secpkcs5.h"
     27 #include "blapit.h"
     28 
     29 const SECItem *
     30 PK11_GetPublicValueFromPublicKey(const SECKEYPublicKey *pubKey)
     31 {
     32    /* set the ID to the public key so we can find it again */
     33    const SECItem *pubKeyIndex = NULL;
     34    switch (pubKey->keyType) {
     35        case rsaKey:
     36        case rsaPssKey:
     37        case rsaOaepKey:
     38            pubKeyIndex = &pubKey->u.rsa.modulus;
     39            break;
     40        case dsaKey:
     41            pubKeyIndex = &pubKey->u.dsa.publicValue;
     42            break;
     43        case dhKey:
     44            pubKeyIndex = &pubKey->u.dh.publicValue;
     45            break;
     46        case edKey:
     47        case ecKey:
     48        case ecMontKey:
     49            pubKeyIndex = &pubKey->u.ec.publicValue;
     50            break;
     51        case kyberKey:
     52            pubKeyIndex = &pubKey->u.kyber.publicValue;
     53            break;
     54        case mldsaKey:
     55            pubKeyIndex = &pubKey->u.mldsa.publicValue;
     56            break;
     57        /* explicitly put unsupported keys here. The
     58         * compiler will  tell you when you need to
     59         * add switch statements */
     60        case fortezzaKey:
     61        case keaKey:
     62        case nullKey:
     63            return NULL;
     64    }
     65    PORT_Assert(pubKeyIndex != NULL);
     66 
     67    return pubKeyIndex;
     68 }
     69 
     70 KeyType
     71 pk11_getKeyTypeFromPKCS11KeyType(CK_KEY_TYPE pk11KeyType)
     72 {
     73    KeyType keyType = nullKey;
     74    switch (pk11KeyType) {
     75        case CKK_RSA:
     76            keyType = rsaKey;
     77            break;
     78        case CKK_DSA:
     79            keyType = dsaKey;
     80            break;
     81        case CKK_DH:
     82            keyType = dhKey;
     83            break;
     84        case CKK_EC:
     85            keyType = ecKey;
     86            break;
     87        case CKK_EC_MONTGOMERY:
     88            keyType = ecMontKey;
     89            break;
     90        case CKK_EC_EDWARDS:
     91            keyType = edKey;
     92            break;
     93        case CKK_NSS_KYBER:
     94        case CKK_NSS_ML_KEM:
     95        case CKK_ML_KEM:
     96            keyType = kyberKey;
     97            break;
     98        case CKK_ML_DSA:
     99            keyType = mldsaKey;
    100            break;
    101        default:
    102            PORT_SetError(SEC_ERROR_BAD_KEY);
    103            break;
    104    }
    105    return keyType;
    106 }
    107 
    108 CK_KEY_TYPE
    109 pk11_getPKCS11KeyTypeFromKeyType(KeyType keyType)
    110 {
    111    CK_KEY_TYPE pk11KeyType = CKK_INVALID_KEY_TYPE;
    112    switch (keyType) {
    113        case rsaKey:
    114        case rsaPssKey:
    115        case rsaOaepKey:
    116            pk11KeyType = CKK_RSA;
    117            break;
    118        case dsaKey:
    119            pk11KeyType = CKK_DSA;
    120            break;
    121        case dhKey:
    122            pk11KeyType = CKK_DH;
    123            break;
    124        case ecKey:
    125            pk11KeyType = CKK_EC;
    126            break;
    127        case ecMontKey:
    128            pk11KeyType = CKK_EC_MONTGOMERY;
    129            break;
    130        case edKey:
    131            pk11KeyType = CKK_EC_EDWARDS;
    132            break;
    133        case kyberKey:
    134            pk11KeyType = CKK_ML_KEM;
    135            break;
    136        case mldsaKey:
    137            pk11KeyType = CKK_ML_DSA;
    138            break;
    139        /* explicitly put unsupported keys here. The
    140         * compiler will  tell you when you need to
    141         * add switch statements */
    142        case fortezzaKey:
    143        case keaKey:
    144        case nullKey:
    145            break;
    146    }
    147    if (pk11KeyType == CKK_INVALID_KEY_TYPE) {
    148        PORT_SetError(SEC_ERROR_BAD_KEY);
    149    }
    150    return pk11KeyType;
    151 }
    152 
    153 SECItem *
    154 pk11_MakeIDFromPublicKey(const SECKEYPublicKey *pubKey)
    155 {
    156    /* set the ID to the public key so we can find it again */
    157    const SECItem *pubKeyIndex = PK11_GetPublicValueFromPublicKey(pubKey);
    158    PORT_Assert(pubKeyIndex != NULL);
    159 
    160    return PK11_MakeIDFromPubKey(pubKeyIndex);
    161 }
    162 
    163 /*
    164 * import a public key into the desired slot
    165 *
    166 * This function takes a public key structure and creates a public key in a
    167 * given slot. If isToken is set, then a persistant public key is created.
    168 *
    169 * Note: it is possible for this function to return a handle for a key which
    170 * is persistant, even if isToken is not set.
    171 */
    172 CK_OBJECT_HANDLE
    173 PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey,
    174                     PRBool isToken)
    175 {
    176    CK_BBOOL cktrue = CK_TRUE;
    177    CK_BBOOL ckfalse = CK_FALSE;
    178    CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
    179    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
    180    CK_OBJECT_HANDLE objectID;
    181    CK_ATTRIBUTE theTemplate[11];
    182    CK_ATTRIBUTE *signedattr = NULL;
    183    CK_ATTRIBUTE *attrs = theTemplate;
    184    CK_NSS_KEM_PARAMETER_SET_TYPE kemParams;
    185    SECItem *ckaId = NULL;
    186    SECItem *pubValue = NULL;
    187    int signedcount = 0;
    188    unsigned int templateCount = 0;
    189    SECStatus rv;
    190    CK_ML_DSA_PARAMETER_SET_TYPE paramSet;
    191 
    192    /* if we already have an object in the desired slot, use it */
    193    if (!isToken && pubKey->pkcs11Slot == slot) {
    194        return pubKey->pkcs11ID;
    195    }
    196 
    197    /* free the existing key */
    198    if (pubKey->pkcs11Slot != NULL) {
    199        PK11SlotInfo *oSlot = pubKey->pkcs11Slot;
    200        if (!PK11_IsPermObject(pubKey->pkcs11Slot, pubKey->pkcs11ID)) {
    201            PK11_EnterSlotMonitor(oSlot);
    202            (void)PK11_GETTAB(oSlot)->C_DestroyObject(oSlot->session,
    203                                                      pubKey->pkcs11ID);
    204            PK11_ExitSlotMonitor(oSlot);
    205        }
    206        PK11_FreeSlot(oSlot);
    207        pubKey->pkcs11Slot = NULL;
    208    }
    209    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
    210    attrs++;
    211    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
    212    attrs++;
    213    PK11_SETATTRS(attrs, CKA_TOKEN, isToken ? &cktrue : &ckfalse,
    214                  sizeof(CK_BBOOL));
    215    attrs++;
    216    if (isToken) {
    217        ckaId = pk11_MakeIDFromPublicKey(pubKey);
    218        if (ckaId == NULL) {
    219            PORT_SetError(SEC_ERROR_BAD_KEY);
    220            return CK_INVALID_HANDLE;
    221        }
    222        PK11_SETATTRS(attrs, CKA_ID, ckaId->data, ckaId->len);
    223        attrs++;
    224    }
    225 
    226    /* now import the key */
    227    {
    228        switch (pubKey->keyType) {
    229            case rsaKey:
    230                keyType = CKK_RSA;
    231                PK11_SETATTRS(attrs, CKA_WRAP, &cktrue, sizeof(CK_BBOOL));
    232                attrs++;
    233                PK11_SETATTRS(attrs, CKA_ENCRYPT, &cktrue,
    234                              sizeof(CK_BBOOL));
    235                attrs++;
    236                PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
    237                attrs++;
    238                signedattr = attrs;
    239                PK11_SETATTRS(attrs, CKA_MODULUS, pubKey->u.rsa.modulus.data,
    240                              pubKey->u.rsa.modulus.len);
    241                attrs++;
    242                PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT,
    243                              pubKey->u.rsa.publicExponent.data,
    244                              pubKey->u.rsa.publicExponent.len);
    245                attrs++;
    246                break;
    247            case dsaKey:
    248                keyType = CKK_DSA;
    249                PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
    250                attrs++;
    251                signedattr = attrs;
    252                PK11_SETATTRS(attrs, CKA_PRIME, pubKey->u.dsa.params.prime.data,
    253                              pubKey->u.dsa.params.prime.len);
    254                attrs++;
    255                PK11_SETATTRS(attrs, CKA_SUBPRIME, pubKey->u.dsa.params.subPrime.data,
    256                              pubKey->u.dsa.params.subPrime.len);
    257                attrs++;
    258                PK11_SETATTRS(attrs, CKA_BASE, pubKey->u.dsa.params.base.data,
    259                              pubKey->u.dsa.params.base.len);
    260                attrs++;
    261                PK11_SETATTRS(attrs, CKA_VALUE, pubKey->u.dsa.publicValue.data,
    262                              pubKey->u.dsa.publicValue.len);
    263                attrs++;
    264                break;
    265            case fortezzaKey:
    266                keyType = CKK_DSA;
    267                PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
    268                attrs++;
    269                signedattr = attrs;
    270                PK11_SETATTRS(attrs, CKA_PRIME, pubKey->u.fortezza.params.prime.data,
    271                              pubKey->u.fortezza.params.prime.len);
    272                attrs++;
    273                PK11_SETATTRS(attrs, CKA_SUBPRIME,
    274                              pubKey->u.fortezza.params.subPrime.data,
    275                              pubKey->u.fortezza.params.subPrime.len);
    276                attrs++;
    277                PK11_SETATTRS(attrs, CKA_BASE, pubKey->u.fortezza.params.base.data,
    278                              pubKey->u.fortezza.params.base.len);
    279                attrs++;
    280                PK11_SETATTRS(attrs, CKA_VALUE, pubKey->u.fortezza.DSSKey.data,
    281                              pubKey->u.fortezza.DSSKey.len);
    282                attrs++;
    283                break;
    284            case dhKey:
    285                keyType = CKK_DH;
    286                PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
    287                attrs++;
    288                signedattr = attrs;
    289                PK11_SETATTRS(attrs, CKA_PRIME, pubKey->u.dh.prime.data,
    290                              pubKey->u.dh.prime.len);
    291                attrs++;
    292                PK11_SETATTRS(attrs, CKA_BASE, pubKey->u.dh.base.data,
    293                              pubKey->u.dh.base.len);
    294                attrs++;
    295                PK11_SETATTRS(attrs, CKA_VALUE, pubKey->u.dh.publicValue.data,
    296                              pubKey->u.dh.publicValue.len);
    297                attrs++;
    298                break;
    299            case edKey:
    300                keyType = CKK_EC_EDWARDS;
    301                PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
    302                attrs++;
    303                PK11_SETATTRS(attrs, CKA_EC_PARAMS,
    304                              pubKey->u.ec.DEREncodedParams.data,
    305                              pubKey->u.ec.DEREncodedParams.len);
    306                attrs++;
    307                PK11_SETATTRS(attrs, CKA_EC_POINT,
    308                              pubKey->u.ec.publicValue.data,
    309                              pubKey->u.ec.publicValue.len);
    310                attrs++;
    311                break;
    312            case ecMontKey:
    313                keyType = CKK_EC_MONTGOMERY;
    314                PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
    315                attrs++;
    316                PK11_SETATTRS(attrs, CKA_EC_PARAMS,
    317                              pubKey->u.ec.DEREncodedParams.data,
    318                              pubKey->u.ec.DEREncodedParams.len);
    319                attrs++;
    320                PK11_SETATTRS(attrs, CKA_EC_POINT,
    321                              pubKey->u.ec.publicValue.data,
    322                              pubKey->u.ec.publicValue.len);
    323                attrs++;
    324                break;
    325            case ecKey:
    326                keyType = CKK_EC;
    327                PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
    328                attrs++;
    329                PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
    330                attrs++;
    331                PK11_SETATTRS(attrs, CKA_EC_PARAMS,
    332                              pubKey->u.ec.DEREncodedParams.data,
    333                              pubKey->u.ec.DEREncodedParams.len);
    334                attrs++;
    335                if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT")) {
    336                    PK11_SETATTRS(attrs, CKA_EC_POINT,
    337                                  pubKey->u.ec.publicValue.data,
    338                                  pubKey->u.ec.publicValue.len);
    339                    attrs++;
    340                } else {
    341                    pubValue = SEC_ASN1EncodeItem(NULL, NULL,
    342                                                  &pubKey->u.ec.publicValue,
    343                                                  SEC_ASN1_GET(SEC_OctetStringTemplate));
    344                    if (pubValue == NULL) {
    345                        if (ckaId) {
    346                            SECITEM_FreeItem(ckaId, PR_TRUE);
    347                        }
    348                        return CK_INVALID_HANDLE;
    349                    }
    350                    PK11_SETATTRS(attrs, CKA_EC_POINT,
    351                                  pubValue->data, pubValue->len);
    352                    attrs++;
    353                }
    354                break;
    355            case kyberKey:
    356                switch (pubKey->u.kyber.params) {
    357 #ifndef NSS_DISABLE_KYBER
    358                    case params_kyber768_round3:
    359                    case params_kyber768_round3_test_mode:
    360                        keyType = CKK_NSS_KYBER;
    361                        kemParams = CKP_NSS_KYBER_768_ROUND3;
    362                        break;
    363 #endif
    364                    case params_ml_kem768:
    365                    case params_ml_kem768_test_mode:
    366                        keyType = CKK_ML_KEM;
    367                        kemParams = CKP_ML_KEM_768;
    368                        break;
    369                    case params_ml_kem1024:
    370                    case params_ml_kem1024_test_mode:
    371                        keyType = CKK_ML_KEM;
    372                        kemParams = CKP_ML_KEM_1024;
    373                        break;
    374                    default:
    375                        kemParams = CKP_INVALID_ID;
    376                        break;
    377                }
    378                PK11_SETATTRS(attrs, CKA_NSS_PARAMETER_SET,
    379                              &kemParams,
    380                              sizeof(CK_NSS_KEM_PARAMETER_SET_TYPE));
    381                attrs++;
    382                PK11_SETATTRS(attrs, CKA_VALUE, pubKey->u.kyber.publicValue.data,
    383                              pubKey->u.kyber.publicValue.len);
    384                attrs++;
    385                break;
    386            case mldsaKey:
    387                keyType = CKK_ML_DSA;
    388                PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
    389                attrs++;
    390                paramSet = SECKEY_GetMLDSAPkcs11ParamSetByOidTag(pubKey->u.mldsa.paramSet);
    391                if (paramSet == CKP_INVALID_ID) {
    392                    PORT_SetError(SEC_ERROR_BAD_KEY);
    393                    return CK_INVALID_HANDLE;
    394                }
    395                PK11_SETATTRS(attrs, CKA_PARAMETER_SET, &paramSet,
    396                              sizeof(CK_ML_DSA_PARAMETER_SET_TYPE));
    397                attrs++;
    398                PK11_SETATTRS(attrs, CKA_VALUE, pubKey->u.mldsa.publicValue.data,
    399                              pubKey->u.mldsa.publicValue.len);
    400                attrs++;
    401                break;
    402            default:
    403                if (ckaId) {
    404                    SECITEM_FreeItem(ckaId, PR_TRUE);
    405                }
    406                PORT_SetError(SEC_ERROR_BAD_KEY);
    407                return CK_INVALID_HANDLE;
    408        }
    409        templateCount = attrs - theTemplate;
    410        PORT_Assert(templateCount <= (sizeof(theTemplate) / sizeof(CK_ATTRIBUTE)));
    411        if (signedattr) {
    412            signedcount = attrs - signedattr;
    413            for (attrs = signedattr; signedcount; attrs++, signedcount--) {
    414                pk11_SignedToUnsigned(attrs);
    415            }
    416        }
    417        rv = PK11_CreateNewObject(slot, CK_INVALID_HANDLE, theTemplate,
    418                                  templateCount, isToken, &objectID);
    419        if (ckaId) {
    420            SECITEM_FreeItem(ckaId, PR_TRUE);
    421        }
    422        if (pubValue) {
    423            SECITEM_FreeItem(pubValue, PR_TRUE);
    424        }
    425        if (rv != SECSuccess) {
    426            return CK_INVALID_HANDLE;
    427        }
    428    }
    429 
    430    pubKey->pkcs11ID = objectID;
    431    pubKey->pkcs11Slot = PK11_ReferenceSlot(slot);
    432 
    433    return objectID;
    434 }
    435 
    436 /*
    437 * take an attribute and copy it into a secitem
    438 */
    439 static CK_RV
    440 pk11_Attr2SecItem(PLArenaPool *arena, const CK_ATTRIBUTE *attr, SECItem *item)
    441 {
    442    item->data = NULL;
    443 
    444    (void)SECITEM_AllocItem(arena, item, attr->ulValueLen);
    445    if (item->data == NULL) {
    446        return CKR_HOST_MEMORY;
    447    }
    448    PORT_Memcpy(item->data, attr->pValue, item->len);
    449    return CKR_OK;
    450 }
    451 
    452 /*
    453 * get a curve length from a set of ecParams.
    454 *
    455 * We need this so we can reliably determine if the ecPoint passed to us
    456 * was encoded or not. With out this, for many curves, we would incorrectly
    457 * identify an unencoded curve as an encoded curve 1 in 65536 times, and for
    458 * a few we would make that same mistake 1 in 32768 times. These are bad
    459 * numbers since they are rare enough to pass tests, but common enough to
    460 * be tripped over in the field.
    461 *
    462 * This function will only work for curves we recognized as of March 2009.
    463 * The assumption is curves in use after March of 2009 would be supplied by
    464 * PKCS #11 modules that already pass the correct encoding to us.
    465 *
    466 * Point length = (Roundup(curveLenInBits/8)*2+1)
    467 */
    468 static int
    469 pk11_get_EC_PointLenInBytes(PLArenaPool *arena, const SECItem *ecParams,
    470                            PRBool *plain)
    471 {
    472    SECItem oid;
    473    SECOidTag tag;
    474    SECStatus rv;
    475 
    476    /* decode the OID tag */
    477    rv = SEC_QuickDERDecodeItem(arena, &oid,
    478                                SEC_ASN1_GET(SEC_ObjectIDTemplate), ecParams);
    479    if (rv != SECSuccess) {
    480        /* could be explict curves, allow them to work if the
    481         * PKCS #11 module support them. If we try to parse the
    482         * explicit curve value in the future, we may return -1 here
    483         * to indicate an invalid parameter if the explicit curve
    484         * decode fails. */
    485        return 0;
    486    }
    487 
    488    *plain = PR_FALSE;
    489    tag = SECOID_FindOIDTag(&oid);
    490    switch (tag) {
    491        case SEC_OID_SECG_EC_SECP112R1:
    492        case SEC_OID_SECG_EC_SECP112R2:
    493            return 29; /* curve len in bytes = 14 bytes */
    494        case SEC_OID_SECG_EC_SECT113R1:
    495        case SEC_OID_SECG_EC_SECT113R2:
    496            return 31; /* curve len in bytes = 15 bytes */
    497        case SEC_OID_SECG_EC_SECP128R1:
    498        case SEC_OID_SECG_EC_SECP128R2:
    499            return 33; /* curve len in bytes = 16 bytes */
    500        case SEC_OID_SECG_EC_SECT131R1:
    501        case SEC_OID_SECG_EC_SECT131R2:
    502            return 35; /* curve len in bytes = 17 bytes */
    503        case SEC_OID_SECG_EC_SECP160K1:
    504        case SEC_OID_SECG_EC_SECP160R1:
    505        case SEC_OID_SECG_EC_SECP160R2:
    506            return 41; /* curve len in bytes = 20 bytes */
    507        case SEC_OID_SECG_EC_SECT163K1:
    508        case SEC_OID_SECG_EC_SECT163R1:
    509        case SEC_OID_SECG_EC_SECT163R2:
    510        case SEC_OID_ANSIX962_EC_C2PNB163V1:
    511        case SEC_OID_ANSIX962_EC_C2PNB163V2:
    512        case SEC_OID_ANSIX962_EC_C2PNB163V3:
    513            return 43; /* curve len in bytes = 21 bytes */
    514        case SEC_OID_ANSIX962_EC_C2PNB176V1:
    515            return 45; /* curve len in bytes = 22 bytes */
    516        case SEC_OID_ANSIX962_EC_C2TNB191V1:
    517        case SEC_OID_ANSIX962_EC_C2TNB191V2:
    518        case SEC_OID_ANSIX962_EC_C2TNB191V3:
    519        case SEC_OID_SECG_EC_SECP192K1:
    520        case SEC_OID_ANSIX962_EC_PRIME192V1:
    521        case SEC_OID_ANSIX962_EC_PRIME192V2:
    522        case SEC_OID_ANSIX962_EC_PRIME192V3:
    523            return 49; /*curve len in bytes = 24 bytes */
    524        case SEC_OID_SECG_EC_SECT193R1:
    525        case SEC_OID_SECG_EC_SECT193R2:
    526            return 51; /*curve len in bytes = 25 bytes */
    527        case SEC_OID_ANSIX962_EC_C2PNB208W1:
    528            return 53; /*curve len in bytes = 26 bytes */
    529        case SEC_OID_SECG_EC_SECP224K1:
    530        case SEC_OID_SECG_EC_SECP224R1:
    531            return 57; /*curve len in bytes = 28 bytes */
    532        case SEC_OID_SECG_EC_SECT233K1:
    533        case SEC_OID_SECG_EC_SECT233R1:
    534        case SEC_OID_SECG_EC_SECT239K1:
    535        case SEC_OID_ANSIX962_EC_PRIME239V1:
    536        case SEC_OID_ANSIX962_EC_PRIME239V2:
    537        case SEC_OID_ANSIX962_EC_PRIME239V3:
    538        case SEC_OID_ANSIX962_EC_C2TNB239V1:
    539        case SEC_OID_ANSIX962_EC_C2TNB239V2:
    540        case SEC_OID_ANSIX962_EC_C2TNB239V3:
    541            return 61; /*curve len in bytes = 30 bytes */
    542        case SEC_OID_ANSIX962_EC_PRIME256V1:
    543        case SEC_OID_SECG_EC_SECP256K1:
    544            return 65; /*curve len in bytes = 32 bytes */
    545        case SEC_OID_ANSIX962_EC_C2PNB272W1:
    546            return 69; /*curve len in bytes = 34 bytes */
    547        case SEC_OID_SECG_EC_SECT283K1:
    548        case SEC_OID_SECG_EC_SECT283R1:
    549            return 73; /*curve len in bytes = 36 bytes */
    550        case SEC_OID_ANSIX962_EC_C2PNB304W1:
    551            return 77; /*curve len in bytes = 38 bytes */
    552        case SEC_OID_ANSIX962_EC_C2TNB359V1:
    553            return 91; /*curve len in bytes = 45 bytes */
    554        case SEC_OID_ANSIX962_EC_C2PNB368W1:
    555            return 93; /*curve len in bytes = 46 bytes */
    556        case SEC_OID_SECG_EC_SECP384R1:
    557            return 97; /*curve len in bytes = 48 bytes */
    558        case SEC_OID_SECG_EC_SECT409K1:
    559        case SEC_OID_SECG_EC_SECT409R1:
    560            return 105; /*curve len in bytes = 52 bytes */
    561        case SEC_OID_ANSIX962_EC_C2TNB431R1:
    562            return 109; /*curve len in bytes = 54 bytes */
    563        case SEC_OID_SECG_EC_SECP521R1:
    564            return 133; /*curve len in bytes = 66 bytes */
    565        case SEC_OID_SECG_EC_SECT571K1:
    566        case SEC_OID_SECG_EC_SECT571R1:
    567            return 145; /*curve len in bytes = 72 bytes */
    568        case SEC_OID_X25519:
    569        case SEC_OID_CURVE25519:
    570        case SEC_OID_ED25519_PUBLIC_KEY:
    571            *plain = PR_TRUE;
    572            return 32; /* curve len in bytes = 32 bytes (only X) */
    573        /* unknown or unrecognized OIDs. return unknown length */
    574        default:
    575            break;
    576    }
    577    return 0;
    578 }
    579 
    580 /*
    581 * returns the decoded point. In some cases the point may already be decoded.
    582 * this function tries to detect those cases and return the point in
    583 * publicKeyValue. In other cases it's DER encoded. In those cases the point
    584 * is first decoded and returned. Space for the point is allocated out of
    585 * the passed in arena.
    586 */
    587 static CK_RV
    588 pk11_get_Decoded_ECPoint(PLArenaPool *arena, const SECItem *ecParams,
    589                         const CK_ATTRIBUTE *ecPoint, SECItem *publicKeyValue)
    590 {
    591    SECItem encodedPublicValue;
    592    SECStatus rv;
    593    int keyLen;
    594    PRBool plain = PR_FALSE;
    595 
    596    if (ecPoint->ulValueLen == 0) {
    597        return CKR_ATTRIBUTE_VALUE_INVALID;
    598    }
    599 
    600    /*
    601     * The PKCS #11 spec requires ecPoints to be encoded as a DER OCTET String.
    602     * NSS has mistakenly passed unencoded values, and some PKCS #11 vendors
    603     * followed that mistake. Now we need to detect which encoding we were
    604     * passed in. The task is made more complicated by the fact the the
    605     * DER encoding byte (SEC_ASN_OCTET_STRING) is the same as the
    606     * EC_POINT_FORM_UNCOMPRESSED byte (0x04), so we can't use that to
    607     * determine which curve we are using.
    608     */
    609 
    610    /* get the expected key length for the passed in curve.
    611     * pk11_get_EC_PointLenInBytes only returns valid values for curves
    612     * NSS has traditionally recognized. If the curve is not recognized,
    613     * it will return '0', and we have to figure out if the key was
    614     * encoded or not heuristically. If the ecParams are invalid, it
    615     * will return -1 for the keyLen.
    616     */
    617    keyLen = pk11_get_EC_PointLenInBytes(arena, ecParams, &plain);
    618    if (keyLen < 0) {
    619        return CKR_ATTRIBUTE_VALUE_INVALID;
    620    }
    621 
    622    /*
    623     * Some curves are not encoded but we don't have the name here.
    624     * Instead, pk11_get_EC_PointLenInBytes returns true plain if this is the
    625     * case.
    626     */
    627    if (plain && ecPoint->ulValueLen == (unsigned int)keyLen) {
    628        return pk11_Attr2SecItem(arena, ecPoint, publicKeyValue);
    629    }
    630 
    631    /* If the point is uncompressed and the lengths match, it
    632     * must be an unencoded point */
    633    if ((*((char *)ecPoint->pValue) == EC_POINT_FORM_UNCOMPRESSED) &&
    634        (ecPoint->ulValueLen == (unsigned int)keyLen)) {
    635        return pk11_Attr2SecItem(arena, ecPoint, publicKeyValue);
    636    }
    637 
    638    /* now assume the key passed to us was encoded and decode it */
    639    if (*((char *)ecPoint->pValue) == SEC_ASN1_OCTET_STRING) {
    640        /* OK, now let's try to decode it and see if it's valid */
    641        encodedPublicValue.data = ecPoint->pValue;
    642        encodedPublicValue.len = ecPoint->ulValueLen;
    643        rv = SEC_QuickDERDecodeItem(arena, publicKeyValue,
    644                                    SEC_ASN1_GET(SEC_OctetStringTemplate), &encodedPublicValue);
    645 
    646        /* it coded correctly & we know the key length (and they match)
    647         * then we are done, return the results. */
    648        if (keyLen && rv == SECSuccess && publicKeyValue->len == (unsigned int)keyLen) {
    649            return CKR_OK;
    650        }
    651 
    652        /* if we know the key length, one of the above tests should have
    653         * succeded. If it doesn't the module gave us bad data */
    654        if (keyLen) {
    655            return CKR_ATTRIBUTE_VALUE_INVALID;
    656        }
    657 
    658        /* We don't know the key length, so we don't know deterministically
    659         * which encoding was used. We now will try to pick the most likely
    660         * form that's correct, with a preference for the encoded form if we
    661         * can't determine for sure. We do this by checking the key we got
    662         * back from SEC_QuickDERDecodeItem for defects. If no defects are
    663         * found, we assume the encoded parameter was was passed to us.
    664         * our defect tests include:
    665         *   1) it didn't decode.
    666         *   2) The decode key had an invalid length (must be odd).
    667         *   3) The decoded key wasn't an UNCOMPRESSED key.
    668         *   4) The decoded key didn't include the entire encoded block
    669         *   except the DER encoding values. (fixing DER length to one
    670         *   particular value).
    671         */
    672        if ((rv != SECSuccess) || ((publicKeyValue->len & 1) != 1) ||
    673            (publicKeyValue->data[0] != EC_POINT_FORM_UNCOMPRESSED) ||
    674            (PORT_Memcmp(&encodedPublicValue.data[encodedPublicValue.len - publicKeyValue->len],
    675                         publicKeyValue->data,
    676                         publicKeyValue->len) != 0)) {
    677            /* The decoded public key was flawed, the original key must have
    678             * already been in decoded form. Do a quick sanity check then
    679             * return the original key value.
    680             */
    681            if ((encodedPublicValue.len & 1) == 0) {
    682                return CKR_ATTRIBUTE_VALUE_INVALID;
    683            }
    684            return pk11_Attr2SecItem(arena, ecPoint, publicKeyValue);
    685        }
    686 
    687        /* as best we can figure, the passed in key was encoded, and we've
    688         * now decoded it. Note: there is a chance this could be wrong if the
    689         * following conditions hold:
    690         *  1) The first byte or bytes of the X point looks like a valid length
    691         * of precisely the right size (2*curveSize -1). this means for curves
    692         * less than 512 bits (64 bytes), this will happen 1 in 256 times*.
    693         * for curves between 512 and 1024, this will happen 1 in 65,536 times*
    694         * for curves between 1024 and 256K this will happen 1 in 16 million*
    695         *  2) The length of the 'DER length field' is odd
    696         * (making both the encoded and decode
    697         * values an odd length. this is true of all curves less than 512,
    698         * as well as curves between 1024 and 256K).
    699         *  3) The X[length of the 'DER length field'] == 0x04, 1 in 256.
    700         *
    701         *  (* assuming all values are equally likely in the first byte,
    702         * This isn't true if the curve length is not a multiple of 8. In these
    703         * cases, if the DER length is possible, it's more likely,
    704         * if it's not possible, then we have no false decodes).
    705         *
    706         * For reference here are the odds for the various curves we currently
    707         * have support for (and the only curves SSL will negotiate at this
    708         * time). NOTE: None of the supported curves will show up here
    709         * because we return a valid length for all of these curves.
    710         * The only way to get here is to have some application (not SSL)
    711         * which supports some unknown curve and have some vendor supplied
    712         * PKCS #11 module support that curve. NOTE: in this case, one
    713         * presumes that that pkcs #11 module is likely to be using the
    714         * correct encodings.
    715         *
    716         * Prime Curves (GFp):
    717         *   Bit    False       Odds of
    718         *  Size    DER Len  False Decode Positive
    719         *  112     27     1 in 65536
    720         *  128     31     1 in 65536
    721         *  160     39     1 in 65536
    722         *  192     47     1 in 65536
    723         *  224     55     1 in 65536
    724         *  239     59     1 in 32768 (top byte can only be 0-127)
    725         *  256     63     1 in 65536
    726         *  521     129,131      0        (decoded value would be even)
    727         *
    728         * Binary curves (GF2m).
    729         *   Bit    False       Odds of
    730         *  Size    DER Len  False Decode Positive
    731         *  131     33       0        (top byte can only be 0-7)
    732         *  163     41       0        (top byte can only be 0-7)
    733         *  176     43     1 in 65536
    734         *  191     47     1 in 32768 (top byte can only be 0-127)
    735         *  193     49       0        (top byte can only be 0-1)
    736         *  208     51     1 in 65536
    737         *  233     59       0        (top byte can only be 0-1)
    738         *  239     59     1 in 32768 (top byte can only be 0-127)
    739         *  272     67     1 in 65536
    740         *  283     71       0        (top byte can only be 0-7)
    741         *  304     75     1 in 65536
    742         *  359     89     1 in 32768 (top byte can only be 0-127)
    743         *  368     91     1 in 65536
    744         *  409     103      0        (top byte can only be 0-1)
    745         *  431     107    1 in 32768 (top byte can only be 0-127)
    746         *  571     129,143      0        (decoded value would be even)
    747         *
    748         */
    749 
    750        return CKR_OK;
    751    }
    752 
    753    /* In theory, we should handle the case where the curve == 0 and
    754     * the first byte is EC_POINT_FORM_UNCOMPRESSED, (which would be
    755     * handled by doing a santity check on the key length and returning
    756     * pk11_Attr2SecItem() to copy the ecPoint to the publicKeyValue).
    757     *
    758     * This test is unnecessary, however, due to the fact that
    759     * EC_POINT_FORM_UNCOMPRESSED == SEC_ASIN1_OCTET_STRING, that case is
    760     * handled in the above if. That means if we get here, the initial
    761     * byte of our ecPoint value was invalid, so we can safely return.
    762     * invalid attribute.
    763     */
    764 
    765    return CKR_ATTRIBUTE_VALUE_INVALID;
    766 }
    767 
    768 /*
    769 * extract a public key from a slot and id
    770 */
    771 SECKEYPublicKey *
    772 PK11_ExtractPublicKey(PK11SlotInfo *slot, KeyType keyType, CK_OBJECT_HANDLE id)
    773 {
    774    CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
    775    PLArenaPool *arena;
    776    PLArenaPool *tmp_arena;
    777    SECKEYPublicKey *pubKey;
    778    unsigned int templateCount = 0;
    779    CK_KEY_TYPE pk11KeyType;
    780    CK_RV crv;
    781    CK_ATTRIBUTE template[8];
    782    CK_ATTRIBUTE *attrs = template;
    783    CK_ATTRIBUTE *modulus, *exponent, *base, *prime, *subprime, *value;
    784    CK_ATTRIBUTE *ecparams, *kemParams, *mldsaParams;
    785 
    786    /* if we didn't know the key type, get it */
    787    if (keyType == nullKey) {
    788        pk11KeyType = PK11_ReadULongAttribute(slot, id, CKA_KEY_TYPE);
    789        if (pk11KeyType == CK_UNAVAILABLE_INFORMATION) {
    790            return NULL;
    791        }
    792        keyType = pk11_getKeyTypeFromPKCS11KeyType(pk11KeyType);
    793        if (keyType == nullKey) {
    794            return NULL;
    795        }
    796    }
    797 
    798    /* now we need to create space for the public key */
    799    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    800    if (arena == NULL)
    801        return NULL;
    802    tmp_arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    803    if (tmp_arena == NULL) {
    804        PORT_FreeArena(arena, PR_FALSE);
    805        return NULL;
    806    }
    807 
    808    pubKey = (SECKEYPublicKey *)
    809        PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
    810    if (pubKey == NULL) {
    811        PORT_FreeArena(arena, PR_FALSE);
    812        PORT_FreeArena(tmp_arena, PR_FALSE);
    813        return NULL;
    814    }
    815 
    816    pubKey->arena = arena;
    817    pubKey->keyType = keyType;
    818    pubKey->pkcs11Slot = PK11_ReferenceSlot(slot);
    819    pubKey->pkcs11ID = id;
    820    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass,
    821                  sizeof(keyClass));
    822    attrs++;
    823    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &pk11KeyType,
    824                  sizeof(pk11KeyType));
    825    attrs++;
    826    switch (pubKey->keyType) {
    827        case rsaKey:
    828            modulus = attrs;
    829            PK11_SETATTRS(attrs, CKA_MODULUS, NULL, 0);
    830            attrs++;
    831            exponent = attrs;
    832            PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, NULL, 0);
    833            attrs++;
    834 
    835            templateCount = attrs - template;
    836            PR_ASSERT(templateCount <= sizeof(template) / sizeof(CK_ATTRIBUTE));
    837            crv = PK11_GetAttributes(tmp_arena, slot, id, template, templateCount);
    838            if (crv != CKR_OK)
    839                break;
    840 
    841            if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_RSA)) {
    842                crv = CKR_OBJECT_HANDLE_INVALID;
    843                break;
    844            }
    845            crv = pk11_Attr2SecItem(arena, modulus, &pubKey->u.rsa.modulus);
    846            if (crv != CKR_OK)
    847                break;
    848            crv = pk11_Attr2SecItem(arena, exponent, &pubKey->u.rsa.publicExponent);
    849            if (crv != CKR_OK)
    850                break;
    851            break;
    852        case dsaKey:
    853            prime = attrs;
    854            PK11_SETATTRS(attrs, CKA_PRIME, NULL, 0);
    855            attrs++;
    856            subprime = attrs;
    857            PK11_SETATTRS(attrs, CKA_SUBPRIME, NULL, 0);
    858            attrs++;
    859            base = attrs;
    860            PK11_SETATTRS(attrs, CKA_BASE, NULL, 0);
    861            attrs++;
    862            value = attrs;
    863            PK11_SETATTRS(attrs, CKA_VALUE, NULL, 0);
    864            attrs++;
    865            templateCount = attrs - template;
    866            PR_ASSERT(templateCount <= sizeof(template) / sizeof(CK_ATTRIBUTE));
    867            crv = PK11_GetAttributes(tmp_arena, slot, id, template, templateCount);
    868            if (crv != CKR_OK)
    869                break;
    870 
    871            if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_DSA)) {
    872                crv = CKR_OBJECT_HANDLE_INVALID;
    873                break;
    874            }
    875            crv = pk11_Attr2SecItem(arena, prime, &pubKey->u.dsa.params.prime);
    876            if (crv != CKR_OK)
    877                break;
    878            crv = pk11_Attr2SecItem(arena, subprime, &pubKey->u.dsa.params.subPrime);
    879            if (crv != CKR_OK)
    880                break;
    881            crv = pk11_Attr2SecItem(arena, base, &pubKey->u.dsa.params.base);
    882            if (crv != CKR_OK)
    883                break;
    884            crv = pk11_Attr2SecItem(arena, value, &pubKey->u.dsa.publicValue);
    885            if (crv != CKR_OK)
    886                break;
    887            break;
    888        case dhKey:
    889            prime = attrs;
    890            PK11_SETATTRS(attrs, CKA_PRIME, NULL, 0);
    891            attrs++;
    892            base = attrs;
    893            PK11_SETATTRS(attrs, CKA_BASE, NULL, 0);
    894            attrs++;
    895            value = attrs;
    896            PK11_SETATTRS(attrs, CKA_VALUE, NULL, 0);
    897            attrs++;
    898            templateCount = attrs - template;
    899            PR_ASSERT(templateCount <= sizeof(template) / sizeof(CK_ATTRIBUTE));
    900            crv = PK11_GetAttributes(tmp_arena, slot, id, template, templateCount);
    901            if (crv != CKR_OK)
    902                break;
    903 
    904            if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_DH)) {
    905                crv = CKR_OBJECT_HANDLE_INVALID;
    906                break;
    907            }
    908            crv = pk11_Attr2SecItem(arena, prime, &pubKey->u.dh.prime);
    909            if (crv != CKR_OK)
    910                break;
    911            crv = pk11_Attr2SecItem(arena, base, &pubKey->u.dh.base);
    912            if (crv != CKR_OK)
    913                break;
    914            crv = pk11_Attr2SecItem(arena, value, &pubKey->u.dh.publicValue);
    915            if (crv != CKR_OK)
    916                break;
    917            break;
    918        case edKey:
    919        case ecKey:
    920        case ecMontKey:
    921            pubKey->u.ec.size = 0;
    922            ecparams = attrs;
    923            PK11_SETATTRS(attrs, CKA_EC_PARAMS, NULL, 0);
    924            attrs++;
    925            value = attrs;
    926            PK11_SETATTRS(attrs, CKA_EC_POINT, NULL, 0);
    927            attrs++;
    928            templateCount = attrs - template;
    929            PR_ASSERT(templateCount <= sizeof(template) / sizeof(CK_ATTRIBUTE));
    930            crv = PK11_GetAttributes(arena, slot, id, template, templateCount);
    931            if (crv != CKR_OK)
    932                break;
    933 
    934            if ((keyClass != CKO_PUBLIC_KEY) ||
    935                (pubKey->keyType == ecKey && pk11KeyType != CKK_EC) ||
    936                (pubKey->keyType == edKey && pk11KeyType != CKK_EC_EDWARDS) ||
    937                (pubKey->keyType == ecMontKey && pk11KeyType != CKK_EC_MONTGOMERY)) {
    938                crv = CKR_OBJECT_HANDLE_INVALID;
    939                break;
    940            }
    941 
    942            crv = pk11_Attr2SecItem(arena, ecparams,
    943                                    &pubKey->u.ec.DEREncodedParams);
    944            if (crv != CKR_OK)
    945                break;
    946            pubKey->u.ec.encoding = ECPoint_Undefined;
    947            crv = pk11_get_Decoded_ECPoint(arena,
    948                                           &pubKey->u.ec.DEREncodedParams, value,
    949                                           &pubKey->u.ec.publicValue);
    950            break;
    951        case mldsaKey:
    952            value = attrs;
    953            PK11_SETATTRS(attrs, CKA_VALUE, NULL, 0);
    954            attrs++;
    955            mldsaParams = attrs;
    956            PK11_SETATTRS(attrs, CKA_PARAMETER_SET, NULL, 0);
    957            attrs++;
    958            templateCount = attrs - template;
    959            PR_ASSERT(templateCount <= sizeof(template) / sizeof(CK_ATTRIBUTE));
    960            crv = PK11_GetAttributes(tmp_arena, slot, id, template, templateCount);
    961            if (crv != CKR_OK)
    962                break;
    963 
    964            if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_ML_DSA)) {
    965                crv = CKR_OBJECT_HANDLE_INVALID;
    966                break;
    967            }
    968 
    969            if (mldsaParams->ulValueLen != sizeof(CK_ML_DSA_PARAMETER_SET_TYPE)) {
    970                crv = CKR_OBJECT_HANDLE_INVALID;
    971                break;
    972            }
    973            pubKey->u.mldsa.paramSet = SECKEY_GetMLDSAOidTagByPkcs11ParamSet(
    974                *(CK_ML_DSA_PARAMETER_SET_TYPE *)mldsaParams->pValue);
    975 
    976            crv = pk11_Attr2SecItem(arena, value, &pubKey->u.mldsa.publicValue);
    977            if (crv != CKR_OK)
    978                break;
    979            break;
    980        case kyberKey:
    981            value = attrs;
    982            PK11_SETATTRS(attrs, CKA_VALUE, NULL, 0);
    983            attrs++;
    984            kemParams = attrs;
    985            PK11_SETATTRS(attrs, CKA_PARAMETER_SET, NULL, 0);
    986            attrs++;
    987            templateCount = attrs - template;
    988            PR_ASSERT(templateCount <= sizeof(template) / sizeof(CK_ATTRIBUTE));
    989 
    990            crv = PK11_GetAttributes(arena, slot, id, template, templateCount);
    991            if (crv != CKR_OK) {
    992                kemParams->type = CKA_NSS_PARAMETER_SET;
    993                crv = PK11_GetAttributes(arena, slot, id, template,
    994                                         templateCount);
    995                if (crv != CKR_OK) {
    996                    break;
    997                }
    998            }
    999 
   1000            if (keyClass != CKO_PUBLIC_KEY) {
   1001                crv = CKR_OBJECT_HANDLE_INVALID;
   1002                break;
   1003            }
   1004 
   1005            switch (pk11KeyType) {
   1006 #ifndef NSS_DISABLE_KYBER
   1007                case CKK_NSS_KYBER:
   1008 #endif
   1009                case CKK_NSS_ML_KEM:
   1010                case CKK_ML_KEM:
   1011                    break;
   1012                default:
   1013                    crv = CKR_OBJECT_HANDLE_INVALID;
   1014                    break;
   1015            }
   1016            if (crv != CKR_OK) {
   1017                break;
   1018            }
   1019 
   1020            if (kemParams->ulValueLen != sizeof(CK_NSS_KEM_PARAMETER_SET_TYPE)) {
   1021                crv = CKR_OBJECT_HANDLE_INVALID;
   1022                break;
   1023            }
   1024            CK_NSS_KEM_PARAMETER_SET_TYPE *pPK11Params = kemParams->pValue;
   1025            switch (*pPK11Params) {
   1026 #ifndef NSS_DISABLE_KYBER
   1027                case CKP_NSS_KYBER_768_ROUND3:
   1028                    pubKey->u.kyber.params = params_kyber768_round3;
   1029                    break;
   1030 #endif
   1031                case CKP_NSS_ML_KEM_768:
   1032                case CKP_ML_KEM_768:
   1033                    pubKey->u.kyber.params = params_ml_kem768;
   1034                    break;
   1035                case CKP_ML_KEM_1024:
   1036                    pubKey->u.kyber.params = params_ml_kem1024;
   1037                    break;
   1038                default:
   1039                    pubKey->u.kyber.params = params_kyber_invalid;
   1040                    break;
   1041            }
   1042            crv = pk11_Attr2SecItem(arena, value, &pubKey->u.kyber.publicValue);
   1043            break;
   1044        case fortezzaKey:
   1045        case nullKey:
   1046        default:
   1047            crv = CKR_OBJECT_HANDLE_INVALID;
   1048            break;
   1049    }
   1050 
   1051    PORT_FreeArena(tmp_arena, PR_FALSE);
   1052 
   1053    if (crv != CKR_OK) {
   1054        PORT_FreeArena(arena, PR_FALSE);
   1055        PK11_FreeSlot(slot);
   1056        PORT_SetError(PK11_MapError(crv));
   1057        return NULL;
   1058    }
   1059 
   1060    return pubKey;
   1061 }
   1062 
   1063 /*
   1064 * Build a Private Key structure from raw PKCS #11 information.
   1065 */
   1066 SECKEYPrivateKey *
   1067 PK11_MakePrivKey(PK11SlotInfo *slot, KeyType keyType,
   1068                 PRBool isTemp, CK_OBJECT_HANDLE privID, void *wincx)
   1069 {
   1070    PLArenaPool *arena;
   1071    SECKEYPrivateKey *privKey;
   1072    PRBool isPrivate;
   1073    SECStatus rv;
   1074 
   1075    /* don't know? look it up */
   1076    if (keyType == nullKey) {
   1077        CK_KEY_TYPE pk11Type = CKK_RSA;
   1078 
   1079        pk11Type = PK11_ReadULongAttribute(slot, privID, CKA_KEY_TYPE);
   1080        isTemp = (PRBool)!PK11_HasAttributeSet(slot, privID, CKA_TOKEN, PR_FALSE);
   1081        keyType = pk11_getKeyTypeFromPKCS11KeyType(pk11Type);
   1082        if (keyType == nullKey) {
   1083            return NULL;
   1084        }
   1085    }
   1086 
   1087    /* if the key is private, make sure we are authenticated to the
   1088     * token before we try to use it */
   1089    isPrivate = (PRBool)PK11_HasAttributeSet(slot, privID, CKA_PRIVATE, PR_FALSE);
   1090    if (isPrivate) {
   1091        rv = PK11_Authenticate(slot, PR_TRUE, wincx);
   1092        if (rv != SECSuccess) {
   1093            return NULL;
   1094        }
   1095    }
   1096 
   1097    /* now we need to create space for the private key */
   1098    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   1099    if (arena == NULL)
   1100        return NULL;
   1101 
   1102    privKey = (SECKEYPrivateKey *)
   1103        PORT_ArenaZAlloc(arena, sizeof(SECKEYPrivateKey));
   1104    if (privKey == NULL) {
   1105        PORT_FreeArena(arena, PR_FALSE);
   1106        return NULL;
   1107    }
   1108 
   1109    privKey->arena = arena;
   1110    privKey->keyType = keyType;
   1111    privKey->pkcs11Slot = PK11_ReferenceSlot(slot);
   1112    privKey->pkcs11ID = privID;
   1113    privKey->pkcs11IsTemp = isTemp;
   1114    privKey->wincx = wincx;
   1115 
   1116    return privKey;
   1117 }
   1118 
   1119 PK11SlotInfo *
   1120 PK11_GetSlotFromPrivateKey(SECKEYPrivateKey *key)
   1121 {
   1122    PK11SlotInfo *slot = key->pkcs11Slot;
   1123    slot = PK11_ReferenceSlot(slot);
   1124    return slot;
   1125 }
   1126 
   1127 /*
   1128 * Get the modulus length for raw parsing
   1129 */
   1130 int
   1131 PK11_GetPrivateModulusLen(SECKEYPrivateKey *key)
   1132 {
   1133    CK_ATTRIBUTE theTemplate = { CKA_MODULUS, NULL, 0 };
   1134    PK11SlotInfo *slot = key->pkcs11Slot;
   1135    CK_RV crv;
   1136    int length;
   1137 
   1138    switch (key->keyType) {
   1139        case rsaKey:
   1140            crv = PK11_GetAttributes(NULL, slot, key->pkcs11ID, &theTemplate, 1);
   1141            if (crv != CKR_OK) {
   1142                PORT_SetError(PK11_MapError(crv));
   1143                return -1;
   1144            }
   1145            if (theTemplate.pValue == NULL) {
   1146                PORT_SetError(PK11_MapError(CKR_ATTRIBUTE_VALUE_INVALID));
   1147                return -1;
   1148            }
   1149            length = theTemplate.ulValueLen;
   1150            if (*(unsigned char *)theTemplate.pValue == 0) {
   1151                length--;
   1152            }
   1153            PORT_Free(theTemplate.pValue);
   1154            return (int)length;
   1155        default:
   1156            break;
   1157    }
   1158    if (theTemplate.pValue != NULL)
   1159        PORT_Free(theTemplate.pValue);
   1160    PORT_SetError(SEC_ERROR_INVALID_KEY);
   1161    return -1;
   1162 }
   1163 
   1164 /*
   1165 * take a private key in one pkcs11 module and load it into another:
   1166 *  NOTE: the source private key is a rare animal... it can't be sensitive.
   1167 *  This is used to do a key gen using one pkcs11 module and storing the
   1168 *  result into another.
   1169 */
   1170 static SECKEYPrivateKey *
   1171 pk11_loadPrivKeyWithFlags(PK11SlotInfo *slot, SECKEYPrivateKey *privKey,
   1172                          SECKEYPublicKey *pubKey, PK11AttrFlags attrFlags)
   1173 {
   1174    CK_ATTRIBUTE privTemplate[] = {
   1175        /* class must be first */
   1176        { CKA_CLASS, NULL, 0 },
   1177        { CKA_KEY_TYPE, NULL, 0 },
   1178        { CKA_ID, NULL, 0 },
   1179        /* RSA - the attributes below will be replaced for other
   1180         *       key types.
   1181         */
   1182        { CKA_MODULUS, NULL, 0 },
   1183        { CKA_PRIVATE_EXPONENT, NULL, 0 },
   1184        { CKA_PUBLIC_EXPONENT, NULL, 0 },
   1185        { CKA_PRIME_1, NULL, 0 },
   1186        { CKA_PRIME_2, NULL, 0 },
   1187        { CKA_EXPONENT_1, NULL, 0 },
   1188        { CKA_EXPONENT_2, NULL, 0 },
   1189        { CKA_COEFFICIENT, NULL, 0 },
   1190        { CKA_DECRYPT, NULL, 0 },
   1191        { CKA_DERIVE, NULL, 0 },
   1192        { CKA_SIGN, NULL, 0 },
   1193        { CKA_SIGN_RECOVER, NULL, 0 },
   1194        { CKA_UNWRAP, NULL, 0 },
   1195        { CKA_DECAPSULATE, NULL, 0 },
   1196        /* reserve space for the attributes that may be
   1197         * specified in attrFlags */
   1198        { CKA_TOKEN, NULL, 0 },
   1199        { CKA_PRIVATE, NULL, 0 },
   1200        { CKA_MODIFIABLE, NULL, 0 },
   1201        { CKA_SENSITIVE, NULL, 0 },
   1202        { CKA_EXTRACTABLE, NULL, 0 },
   1203        { CKA_PARAMETER_SET, NULL, 0 },
   1204        { CKA_SEED, NULL, 0 },
   1205 #define NUM_RESERVED_ATTRS 5 /* number of reserved attributes above */
   1206    };
   1207    CK_BBOOL cktrue = CK_TRUE;
   1208    CK_BBOOL ckfalse = CK_FALSE;
   1209    CK_ATTRIBUTE *attrs = NULL, *ap;
   1210    const int templateSize = sizeof(privTemplate) / sizeof(privTemplate[0]);
   1211    PLArenaPool *arena;
   1212    CK_OBJECT_HANDLE objectID;
   1213    int i, count = 0;
   1214    int extra_count = 0; /* count of signed attributes */
   1215    CK_RV crv;
   1216    SECStatus rv;
   1217    PRBool token = ((attrFlags & PK11_ATTR_TOKEN) != 0);
   1218 
   1219    if (pk11_BadAttrFlags(attrFlags)) {
   1220        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1221        return NULL;
   1222    }
   1223 
   1224    for (i = 0; i < templateSize; i++) {
   1225        if (privTemplate[i].type == CKA_MODULUS) {
   1226            attrs = &privTemplate[i];
   1227            count = i;
   1228            break;
   1229        }
   1230    }
   1231    PORT_Assert(attrs != NULL);
   1232    if (attrs == NULL) {
   1233        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1234        return NULL;
   1235    }
   1236 
   1237    ap = attrs;
   1238 
   1239    switch (privKey->keyType) {
   1240        case rsaKey:
   1241            count = templateSize - NUM_RESERVED_ATTRS;
   1242            extra_count = count - (attrs - privTemplate);
   1243            break;
   1244        case dsaKey:
   1245            ap->type = CKA_PRIME;
   1246            ap++;
   1247            count++;
   1248            extra_count++;
   1249            ap->type = CKA_SUBPRIME;
   1250            ap++;
   1251            count++;
   1252            extra_count++;
   1253            ap->type = CKA_BASE;
   1254            ap++;
   1255            count++;
   1256            extra_count++;
   1257            ap->type = CKA_VALUE;
   1258            ap++;
   1259            count++;
   1260            extra_count++;
   1261            ap->type = CKA_SIGN;
   1262            ap++;
   1263            count++;
   1264            extra_count++;
   1265            break;
   1266        case dhKey:
   1267            ap->type = CKA_PRIME;
   1268            ap++;
   1269            count++;
   1270            extra_count++;
   1271            ap->type = CKA_BASE;
   1272            ap++;
   1273            count++;
   1274            extra_count++;
   1275            ap->type = CKA_VALUE;
   1276            ap++;
   1277            count++;
   1278            extra_count++;
   1279            ap->type = CKA_DERIVE;
   1280            ap++;
   1281            count++;
   1282            extra_count++;
   1283            break;
   1284        case mldsaKey:
   1285            ap->type = CKA_PARAMETER_SET;
   1286            ap++;
   1287            count++;
   1288            ap->type = CKA_SEED;
   1289            ap++;
   1290            count++;
   1291            ap->type = CKA_VALUE;
   1292            ap++;
   1293            count++;
   1294            ap->type = CKA_SIGN;
   1295            ap++;
   1296            count++;
   1297            break;
   1298        case ecKey:
   1299        case edKey:
   1300        case ecMontKey:
   1301            ap->type = CKA_EC_PARAMS;
   1302            ap++;
   1303            count++;
   1304            ap->type = CKA_VALUE;
   1305            ap++;
   1306            count++;
   1307            if (privKey->keyType == ecKey) {
   1308                ap->type = CKA_DERIVE;
   1309                ap++;
   1310                count++;
   1311            }
   1312 
   1313            ap->type = CKA_SIGN;
   1314            ap++;
   1315            count++;
   1316            break;
   1317        default:
   1318            count = 0;
   1319            extra_count = 0;
   1320            break;
   1321    }
   1322 
   1323    if (count == 0) {
   1324        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1325        return NULL;
   1326    }
   1327 
   1328    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   1329    if (arena == NULL)
   1330        return NULL;
   1331    /*
   1332     * read out the old attributes.
   1333     */
   1334    crv = PK11_GetAttributes(arena, privKey->pkcs11Slot, privKey->pkcs11ID,
   1335                             privTemplate, count);
   1336    if (crv != CKR_OK) {
   1337        PORT_SetError(PK11_MapError(crv));
   1338        PORT_FreeArena(arena, PR_TRUE);
   1339        return NULL;
   1340    }
   1341 
   1342    /* Set token, private, modifiable, sensitive, and extractable */
   1343    count += pk11_AttrFlagsToAttributes(attrFlags, &privTemplate[count],
   1344                                        &cktrue, &ckfalse);
   1345 
   1346    /* Not everyone can handle zero padded key values, give
   1347     * them the raw data as unsigned. Where the values are encoded or
   1348     * zero-preserving per-RFC5915. NOTE Most new algorithms are
   1349     * OCTET strings, not signed integers, so this conversion
   1350     * isn't necessary for them. */
   1351    if (extra_count) {
   1352        for (ap = attrs; extra_count; ap++, extra_count--) {
   1353            pk11_SignedToUnsigned(ap);
   1354        }
   1355    }
   1356 
   1357    /* now Store the puppies */
   1358    rv = PK11_CreateNewObject(slot, CK_INVALID_HANDLE, privTemplate,
   1359                              count, token, &objectID);
   1360    PORT_FreeArena(arena, PR_TRUE);
   1361    if (rv != SECSuccess) {
   1362        return NULL;
   1363    }
   1364 
   1365    /* try loading the public key */
   1366    if (pubKey) {
   1367        PK11_ImportPublicKey(slot, pubKey, token);
   1368        if (pubKey->pkcs11Slot) {
   1369            PK11_FreeSlot(pubKey->pkcs11Slot);
   1370            pubKey->pkcs11Slot = NULL;
   1371            pubKey->pkcs11ID = CK_INVALID_HANDLE;
   1372        }
   1373    }
   1374 
   1375    /* build new key structure */
   1376    return PK11_MakePrivKey(slot, privKey->keyType, !token,
   1377                            objectID, privKey->wincx);
   1378 }
   1379 
   1380 static SECKEYPrivateKey *
   1381 pk11_loadPrivKey(PK11SlotInfo *slot, SECKEYPrivateKey *privKey,
   1382                 SECKEYPublicKey *pubKey, PRBool token, PRBool sensitive)
   1383 {
   1384    PK11AttrFlags attrFlags = 0;
   1385    if (token) {
   1386        attrFlags |= (PK11_ATTR_TOKEN | PK11_ATTR_PRIVATE);
   1387    } else {
   1388        attrFlags |= (PK11_ATTR_SESSION | PK11_ATTR_PUBLIC);
   1389    }
   1390    if (sensitive) {
   1391        attrFlags |= PK11_ATTR_SENSITIVE;
   1392    } else {
   1393        attrFlags |= PK11_ATTR_INSENSITIVE;
   1394    }
   1395    return pk11_loadPrivKeyWithFlags(slot, privKey, pubKey, attrFlags);
   1396 }
   1397 
   1398 /*
   1399 * export this for PSM
   1400 */
   1401 SECKEYPrivateKey *
   1402 PK11_LoadPrivKey(PK11SlotInfo *slot, SECKEYPrivateKey *privKey,
   1403                 SECKEYPublicKey *pubKey, PRBool token, PRBool sensitive)
   1404 {
   1405    return pk11_loadPrivKey(slot, privKey, pubKey, token, sensitive);
   1406 }
   1407 
   1408 /*
   1409 * Use the token to generate a key pair.
   1410 */
   1411 SECKEYPrivateKey *
   1412 PK11_GenerateKeyPairWithOpFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
   1413                                void *param, SECKEYPublicKey **pubKey, PK11AttrFlags attrFlags,
   1414                                CK_FLAGS opFlags, CK_FLAGS opFlagsMask, void *wincx)
   1415 {
   1416    /* we have to use these native types because when we call PKCS 11 modules
   1417     * we have to make sure that we are using the correct sizes for all the
   1418     * parameters. */
   1419    CK_BBOOL ckfalse = CK_FALSE;
   1420    CK_BBOOL cktrue = CK_TRUE;
   1421    CK_ULONG modulusBits;
   1422    CK_BYTE publicExponent[4];
   1423    CK_ATTRIBUTE privTemplate[] = {
   1424        { CKA_SENSITIVE, NULL, 0 },
   1425        { CKA_TOKEN, NULL, 0 },
   1426        { CKA_PRIVATE, NULL, 0 },
   1427        { CKA_DERIVE, NULL, 0 },
   1428        { CKA_UNWRAP, NULL, 0 },
   1429        { CKA_SIGN, NULL, 0 },
   1430        { CKA_DECRYPT, NULL, 0 },
   1431        { CKA_EXTRACTABLE, NULL, 0 },
   1432        { CKA_MODIFIABLE, NULL, 0 },
   1433        { CKA_DECAPSULATE, NULL, 0 },
   1434    };
   1435    CK_ATTRIBUTE rsaPubTemplate[] = {
   1436        { CKA_MODULUS_BITS, NULL, 0 },
   1437        { CKA_PUBLIC_EXPONENT, NULL, 0 },
   1438        { CKA_TOKEN, NULL, 0 },
   1439        { CKA_DERIVE, NULL, 0 },
   1440        { CKA_WRAP, NULL, 0 },
   1441        { CKA_VERIFY, NULL, 0 },
   1442        { CKA_VERIFY_RECOVER, NULL, 0 },
   1443        { CKA_ENCRYPT, NULL, 0 },
   1444        { CKA_MODIFIABLE, NULL, 0 },
   1445        { CKA_ENCAPSULATE, NULL, 0 },
   1446    };
   1447    CK_ATTRIBUTE dsaPubTemplate[] = {
   1448        { CKA_PRIME, NULL, 0 },
   1449        { CKA_SUBPRIME, NULL, 0 },
   1450        { CKA_BASE, NULL, 0 },
   1451        { CKA_TOKEN, NULL, 0 },
   1452        { CKA_DERIVE, NULL, 0 },
   1453        { CKA_WRAP, NULL, 0 },
   1454        { CKA_VERIFY, NULL, 0 },
   1455        { CKA_VERIFY_RECOVER, NULL, 0 },
   1456        { CKA_ENCRYPT, NULL, 0 },
   1457        { CKA_MODIFIABLE, NULL, 0 },
   1458        { CKA_ENCAPSULATE, NULL, 0 },
   1459    };
   1460    CK_ATTRIBUTE dhPubTemplate[] = {
   1461        { CKA_PRIME, NULL, 0 },
   1462        { CKA_BASE, NULL, 0 },
   1463        { CKA_TOKEN, NULL, 0 },
   1464        { CKA_DERIVE, NULL, 0 },
   1465        { CKA_WRAP, NULL, 0 },
   1466        { CKA_VERIFY, NULL, 0 },
   1467        { CKA_VERIFY_RECOVER, NULL, 0 },
   1468        { CKA_ENCRYPT, NULL, 0 },
   1469        { CKA_MODIFIABLE, NULL, 0 },
   1470        { CKA_ENCAPSULATE, NULL, 0 },
   1471    };
   1472    CK_ATTRIBUTE ecPubTemplate[] = {
   1473        { CKA_EC_PARAMS, NULL, 0 },
   1474        { CKA_TOKEN, NULL, 0 },
   1475        { CKA_DERIVE, NULL, 0 },
   1476        { CKA_WRAP, NULL, 0 },
   1477        { CKA_VERIFY, NULL, 0 },
   1478        { CKA_VERIFY_RECOVER, NULL, 0 },
   1479        { CKA_ENCRYPT, NULL, 0 },
   1480        { CKA_MODIFIABLE, NULL, 0 },
   1481        { CKA_ENCAPSULATE, NULL, 0 },
   1482    };
   1483    SECKEYECParams *ecParams;
   1484 
   1485    CK_ATTRIBUTE mlDsaPubTemplate[] = {
   1486        { CKA_PARAMETER_SET, NULL, 0 },
   1487        { CKA_TOKEN, NULL, 0 },
   1488        { CKA_DERIVE, NULL, 0 },
   1489        { CKA_WRAP, NULL, 0 },
   1490        { CKA_VERIFY, NULL, 0 },
   1491        { CKA_VERIFY_RECOVER, NULL, 0 },
   1492        { CKA_ENCRYPT, NULL, 0 },
   1493        { CKA_MODIFIABLE, NULL, 0 },
   1494    };
   1495 
   1496    CK_ATTRIBUTE kyberPubTemplate[] = {
   1497        { CKA_NSS_PARAMETER_SET, NULL, 0 },
   1498        { CKA_TOKEN, NULL, 0 },
   1499        { CKA_DERIVE, NULL, 0 },
   1500        { CKA_WRAP, NULL, 0 },
   1501        { CKA_VERIFY, NULL, 0 },
   1502        { CKA_VERIFY_RECOVER, NULL, 0 },
   1503        { CKA_ENCRYPT, NULL, 0 },
   1504        { CKA_MODIFIABLE, NULL, 0 },
   1505        { CKA_ENCAPSULATE, NULL, 0 },
   1506    };
   1507 
   1508    /*CK_ULONG key_size = 0;*/
   1509    CK_ATTRIBUTE *pubTemplate;
   1510    int privCount = 0;
   1511    int pubCount = 0;
   1512    PK11RSAGenParams *rsaParams;
   1513    SECKEYPQGParams *dsaParams;
   1514    SECKEYDHParams *dhParams;
   1515    CK_NSS_KEM_PARAMETER_SET_TYPE *kemParams;
   1516    CK_ML_DSA_PARAMETER_SET_TYPE *mldsaParams;
   1517    CK_MECHANISM mechanism;
   1518    CK_MECHANISM test_mech;
   1519    CK_MECHANISM test_mech2;
   1520    CK_SESSION_HANDLE session_handle;
   1521    CK_RV crv;
   1522    CK_OBJECT_HANDLE privID, pubID;
   1523    SECKEYPrivateKey *privKey;
   1524    KeyType keyType;
   1525    PRBool restore;
   1526    int peCount, i;
   1527    CK_ATTRIBUTE *attrs;
   1528    CK_ATTRIBUTE *privattrs;
   1529    CK_ATTRIBUTE setTemplate;
   1530    CK_MECHANISM_INFO mechanism_info;
   1531    CK_OBJECT_CLASS keyClass;
   1532    SECItem *cka_id;
   1533    PRBool haslock = PR_FALSE;
   1534    PRBool pubIsToken = PR_FALSE;
   1535    PRBool token = ((attrFlags & PK11_ATTR_TOKEN) != 0);
   1536    /* subset of attrFlags applicable to the public key */
   1537    PK11AttrFlags pubKeyAttrFlags = attrFlags &
   1538                                    (PK11_ATTR_TOKEN | PK11_ATTR_SESSION | PK11_ATTR_MODIFIABLE | PK11_ATTR_UNMODIFIABLE);
   1539 
   1540    if (pk11_BadAttrFlags(attrFlags)) {
   1541        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1542        return NULL;
   1543    }
   1544 
   1545    if (!param) {
   1546        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1547        return NULL;
   1548    }
   1549 
   1550    /*
   1551     * The opFlags and opFlagMask parameters allow us to control the
   1552     * settings of the key usage attributes (CKA_ENCRYPT and friends).
   1553     * opFlagMask is set to one if the flag is specified in opFlags and
   1554     *  zero if it is to take on a default value calculated by
   1555     *  PK11_GenerateKeyPairWithOpFlags.
   1556     * opFlags specifies the actual value of the flag 1 or 0.
   1557     *   Bits not corresponding to one bits in opFlagMask should be zero.
   1558     */
   1559 
   1560    /* if we are trying to turn on a flag, it better be in the mask */
   1561    PORT_Assert((opFlags & ~opFlagsMask) == 0);
   1562    opFlags &= opFlagsMask;
   1563 
   1564    PORT_Assert(slot != NULL);
   1565    if (slot == NULL) {
   1566        PORT_SetError(SEC_ERROR_NO_MODULE);
   1567        return NULL;
   1568    }
   1569 
   1570    /* if our slot really doesn't do this mechanism, Generate the key
   1571     * in our internal token and write it out */
   1572    if (!PK11_DoesMechanism(slot, type)) {
   1573        PK11SlotInfo *int_slot = PK11_GetInternalSlot();
   1574 
   1575        /* don't loop forever looking for a slot */
   1576        if (slot == int_slot) {
   1577            PK11_FreeSlot(int_slot);
   1578            /* if we don't have support in softoken, then the mechanism
   1579             * just isnt' supported */
   1580            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
   1581            return NULL;
   1582        }
   1583 
   1584        /* if there isn't a suitable slot, then we can't do the keygen */
   1585        if (int_slot == NULL) {
   1586            PORT_SetError(SEC_ERROR_NO_MODULE);
   1587            return NULL;
   1588        }
   1589 
   1590        /* generate the temporary key to load */
   1591        privKey = PK11_GenerateKeyPair(int_slot, type, param, pubKey, PR_FALSE,
   1592                                       PR_FALSE, wincx);
   1593        PK11_FreeSlot(int_slot);
   1594 
   1595        /* if successful, load the temp key into the new token */
   1596        if (privKey != NULL) {
   1597            SECKEYPrivateKey *newPrivKey = pk11_loadPrivKeyWithFlags(slot,
   1598                                                                     privKey, *pubKey, attrFlags);
   1599            SECKEY_DestroyPrivateKey(privKey);
   1600            if (newPrivKey == NULL) {
   1601                SECKEY_DestroyPublicKey(*pubKey);
   1602                *pubKey = NULL;
   1603            }
   1604            return newPrivKey;
   1605        }
   1606        return NULL;
   1607    }
   1608 
   1609    mechanism.mechanism = type;
   1610    mechanism.pParameter = NULL;
   1611    mechanism.ulParameterLen = 0;
   1612    test_mech.pParameter = NULL;
   1613    test_mech.ulParameterLen = 0;
   1614    test_mech2.mechanism = CKM_INVALID_MECHANISM;
   1615    test_mech2.pParameter = NULL;
   1616    test_mech2.ulParameterLen = 0;
   1617 
   1618    /* set up the private key template */
   1619    privattrs = privTemplate;
   1620    privattrs += pk11_AttrFlagsToAttributes(attrFlags, privattrs,
   1621                                            &cktrue, &ckfalse);
   1622 
   1623    /* set up the mechanism specific info */
   1624    switch (type) {
   1625        case CKM_RSA_PKCS_KEY_PAIR_GEN:
   1626        case CKM_RSA_X9_31_KEY_PAIR_GEN:
   1627            rsaParams = (PK11RSAGenParams *)param;
   1628            if (rsaParams->pe == 0) {
   1629                PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1630                return NULL;
   1631            }
   1632            modulusBits = rsaParams->keySizeInBits;
   1633            peCount = 0;
   1634 
   1635            /* convert pe to a PKCS #11 string */
   1636            for (i = 0; i < 4; i++) {
   1637                if (peCount || (rsaParams->pe &
   1638                                ((unsigned long)0xff000000L >> (i * 8)))) {
   1639                    publicExponent[peCount] =
   1640                        (CK_BYTE)((rsaParams->pe >> (3 - i) * 8) & 0xff);
   1641                    peCount++;
   1642                }
   1643            }
   1644            PORT_Assert(peCount != 0);
   1645            attrs = rsaPubTemplate;
   1646            PK11_SETATTRS(attrs, CKA_MODULUS_BITS,
   1647                          &modulusBits, sizeof(modulusBits));
   1648            attrs++;
   1649            PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT,
   1650                          publicExponent, peCount);
   1651            attrs++;
   1652            pubTemplate = rsaPubTemplate;
   1653            keyType = rsaKey;
   1654            test_mech.mechanism = CKM_RSA_PKCS;
   1655            break;
   1656        case CKM_DSA_KEY_PAIR_GEN:
   1657            dsaParams = (SECKEYPQGParams *)param;
   1658            attrs = dsaPubTemplate;
   1659            PK11_SETATTRS(attrs, CKA_PRIME, dsaParams->prime.data,
   1660                          dsaParams->prime.len);
   1661            attrs++;
   1662            PK11_SETATTRS(attrs, CKA_SUBPRIME, dsaParams->subPrime.data,
   1663                          dsaParams->subPrime.len);
   1664            attrs++;
   1665            PK11_SETATTRS(attrs, CKA_BASE, dsaParams->base.data,
   1666                          dsaParams->base.len);
   1667            attrs++;
   1668            pubTemplate = dsaPubTemplate;
   1669            keyType = dsaKey;
   1670            test_mech.mechanism = CKM_DSA;
   1671            break;
   1672        case CKM_DH_PKCS_KEY_PAIR_GEN:
   1673            dhParams = (SECKEYDHParams *)param;
   1674            attrs = dhPubTemplate;
   1675            PK11_SETATTRS(attrs, CKA_PRIME, dhParams->prime.data,
   1676                          dhParams->prime.len);
   1677            attrs++;
   1678            PK11_SETATTRS(attrs, CKA_BASE, dhParams->base.data,
   1679                          dhParams->base.len);
   1680            attrs++;
   1681            pubTemplate = dhPubTemplate;
   1682            keyType = dhKey;
   1683            test_mech.mechanism = CKM_DH_PKCS_DERIVE;
   1684            break;
   1685        case CKM_EC_KEY_PAIR_GEN:
   1686        case CKM_NSS_ECDHE_NO_PAIRWISE_CHECK_KEY_PAIR_GEN:
   1687            ecParams = (SECKEYECParams *)param;
   1688            attrs = ecPubTemplate;
   1689            PK11_SETATTRS(attrs, CKA_EC_PARAMS, ecParams->data,
   1690                          ecParams->len);
   1691            attrs++;
   1692            pubTemplate = ecPubTemplate;
   1693            keyType = ecKey;
   1694            /*
   1695             * ECC supports 2 different mechanism types (unlike RSA, which
   1696             * supports different usages with the same mechanism).
   1697             * We may need to query both mechanism types and or the results
   1698             * together -- but we only do that if either the user has
   1699             * requested both usages, or not specified any usages.
   1700             */
   1701            if ((opFlags & (CKF_SIGN | CKF_DERIVE)) == (CKF_SIGN | CKF_DERIVE)) {
   1702                /* We've explicitly turned on both flags, use both mechanism */
   1703                test_mech.mechanism = CKM_ECDH1_DERIVE;
   1704                test_mech2.mechanism = CKM_ECDSA;
   1705            } else if (opFlags & CKF_SIGN) {
   1706                /* just do signing */
   1707                test_mech.mechanism = CKM_ECDSA;
   1708            } else if (opFlags & CKF_DERIVE) {
   1709                /* just do ECDH */
   1710                test_mech.mechanism = CKM_ECDH1_DERIVE;
   1711            } else {
   1712                /* neither was specified default to both */
   1713                test_mech.mechanism = CKM_ECDH1_DERIVE;
   1714                test_mech2.mechanism = CKM_ECDSA;
   1715            }
   1716            break;
   1717 #ifndef NSS_DISABLE_KYBER
   1718        case CKM_NSS_KYBER_KEY_PAIR_GEN:
   1719 #endif
   1720        case CKM_NSS_ML_KEM_KEY_PAIR_GEN:
   1721        case CKM_ML_KEM_KEY_PAIR_GEN:
   1722            kemParams = (CK_NSS_KEM_PARAMETER_SET_TYPE *)param;
   1723            attrs = kyberPubTemplate;
   1724            PK11_SETATTRS(attrs, CKA_PARAMETER_SET,
   1725                          kemParams,
   1726                          sizeof(CK_NSS_KEM_PARAMETER_SET_TYPE));
   1727            attrs++;
   1728            pubTemplate = kyberPubTemplate;
   1729            keyType = kyberKey;
   1730            test_mech.mechanism = CKM_ML_KEM;
   1731            break;
   1732        case CKM_EC_MONTGOMERY_KEY_PAIR_GEN:
   1733            ecParams = (SECKEYECParams *)param;
   1734            attrs = ecPubTemplate;
   1735            PK11_SETATTRS(attrs, CKA_EC_PARAMS, ecParams->data,
   1736                          ecParams->len);
   1737            attrs++;
   1738            pubTemplate = ecPubTemplate;
   1739            keyType = ecMontKey;
   1740            test_mech.mechanism = CKM_ECDH1_DERIVE;
   1741            break;
   1742        case CKM_EC_EDWARDS_KEY_PAIR_GEN:
   1743            ecParams = (SECKEYECParams *)param;
   1744            attrs = ecPubTemplate;
   1745            PK11_SETATTRS(attrs, CKA_EC_PARAMS, ecParams->data,
   1746                          ecParams->len);
   1747            attrs++;
   1748            pubTemplate = ecPubTemplate;
   1749            keyType = edKey;
   1750            test_mech.mechanism = CKM_EDDSA;
   1751            break;
   1752        case CKM_ML_DSA_KEY_PAIR_GEN:
   1753            mldsaParams = (CK_ML_DSA_PARAMETER_SET_TYPE *)param;
   1754            attrs = mlDsaPubTemplate;
   1755            PK11_SETATTRS(attrs,
   1756                          CKA_PARAMETER_SET,
   1757                          mldsaParams,
   1758                          sizeof(CK_ML_DSA_PARAMETER_SET_TYPE));
   1759            attrs++;
   1760            pubTemplate = mlDsaPubTemplate;
   1761            keyType = mldsaKey;
   1762            test_mech.mechanism = CKM_ML_DSA;
   1763            break;
   1764        default:
   1765            PORT_SetError(SEC_ERROR_BAD_KEY);
   1766            return NULL;
   1767    }
   1768 
   1769    /* now query the slot to find out how "good" a key we can generate */
   1770    if (!slot->isThreadSafe)
   1771        PK11_EnterSlotMonitor(slot);
   1772    crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,
   1773                                                test_mech.mechanism, &mechanism_info);
   1774    /*
   1775     * EC keys are used in multiple different types of mechanism, if we
   1776     * are using dual use keys, we need to query the second mechanism
   1777     * as well.
   1778     */
   1779    if (test_mech2.mechanism != CKM_INVALID_MECHANISM) {
   1780        CK_MECHANISM_INFO mechanism_info2;
   1781        CK_RV crv2;
   1782 
   1783        if (crv != CKR_OK) {
   1784            /* the first failed, make sure there is no trash in the
   1785             * mechanism flags when we or it below */
   1786            mechanism_info.flags = 0;
   1787        }
   1788        crv2 = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,
   1789                                                     test_mech2.mechanism, &mechanism_info2);
   1790        if (crv2 == CKR_OK) {
   1791            crv = CKR_OK; /* succeed if either mechnaism info succeeds */
   1792            /* combine the 2 sets of mechnanism flags */
   1793            mechanism_info.flags |= mechanism_info2.flags;
   1794        }
   1795    }
   1796    if (!slot->isThreadSafe)
   1797        PK11_ExitSlotMonitor(slot);
   1798    if ((crv != CKR_OK) || (mechanism_info.flags == 0)) {
   1799        /* must be old module... guess what it should be... */
   1800        switch (test_mech.mechanism) {
   1801            case CKM_RSA_PKCS:
   1802                mechanism_info.flags = (CKF_SIGN | CKF_DECRYPT |
   1803                                        CKF_WRAP | CKF_VERIFY_RECOVER | CKF_ENCRYPT | CKF_WRAP);
   1804                break;
   1805            case CKM_DSA:
   1806            case CKM_ECDSA:
   1807            case CKM_EDDSA:
   1808            case CKM_ML_DSA:
   1809                mechanism_info.flags = CKF_SIGN | CKF_VERIFY;
   1810                break;
   1811            case CKM_DH_PKCS_DERIVE:
   1812                mechanism_info.flags = CKF_DERIVE;
   1813                break;
   1814            case CKM_ECDH1_DERIVE:
   1815                mechanism_info.flags = CKF_DERIVE;
   1816                if (test_mech2.mechanism == CKM_ECDSA) {
   1817                    mechanism_info.flags |= CKF_SIGN | CKF_VERIFY;
   1818                }
   1819                break;
   1820            case CKM_NSS_KYBER:
   1821            case CKM_NSS_ML_KEM:
   1822            case CKM_ML_KEM:
   1823                mechanism_info.flags = CKF_ENCAPSULATE | CKF_DECAPSULATE;
   1824                break;
   1825            default:
   1826                break;
   1827        }
   1828    }
   1829    /* now adjust our flags according to the user's key usage passed to us */
   1830    mechanism_info.flags = (mechanism_info.flags & (~opFlagsMask)) | opFlags;
   1831    /* set the public key attributes */
   1832    attrs += pk11_AttrFlagsToAttributes(pubKeyAttrFlags, attrs,
   1833                                        &cktrue, &ckfalse);
   1834    PK11_SETATTRS(attrs, CKA_DERIVE,
   1835                  mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse,
   1836                  sizeof(CK_BBOOL));
   1837    attrs++;
   1838    PK11_SETATTRS(attrs, CKA_WRAP,
   1839                  mechanism_info.flags & CKF_WRAP ? &cktrue : &ckfalse,
   1840                  sizeof(CK_BBOOL));
   1841    attrs++;
   1842    PK11_SETATTRS(attrs, CKA_VERIFY,
   1843                  mechanism_info.flags & CKF_VERIFY ? &cktrue : &ckfalse,
   1844                  sizeof(CK_BBOOL));
   1845    attrs++;
   1846    PK11_SETATTRS(attrs, CKA_VERIFY_RECOVER,
   1847                  mechanism_info.flags & CKF_VERIFY_RECOVER ? &cktrue : &ckfalse,
   1848                  sizeof(CK_BBOOL));
   1849    attrs++;
   1850    PK11_SETATTRS(attrs, CKA_ENCRYPT,
   1851                  mechanism_info.flags & CKF_ENCRYPT ? &cktrue : &ckfalse,
   1852                  sizeof(CK_BBOOL));
   1853    attrs++;
   1854    /* only set encapsulate if it's requested and shows up in the mechanism
   1855     * list, that way we don't confuse pre-3.2 PKCS #11 modules */
   1856    if (mechanism_info.flags & CKF_ENCAPSULATE) {
   1857        PK11_SETATTRS(attrs, CKA_ENCAPSULATE, &cktrue, sizeof(CK_BBOOL));
   1858        attrs++;
   1859    }
   1860 
   1861    /* set the private key attributes */
   1862    PK11_SETATTRS(privattrs, CKA_DERIVE,
   1863                  mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse,
   1864                  sizeof(CK_BBOOL));
   1865    privattrs++;
   1866    PK11_SETATTRS(privattrs, CKA_UNWRAP,
   1867                  mechanism_info.flags & CKF_UNWRAP ? &cktrue : &ckfalse,
   1868                  sizeof(CK_BBOOL));
   1869    privattrs++;
   1870    PK11_SETATTRS(privattrs, CKA_SIGN,
   1871                  mechanism_info.flags & CKF_SIGN ? &cktrue : &ckfalse,
   1872                  sizeof(CK_BBOOL));
   1873    privattrs++;
   1874    PK11_SETATTRS(privattrs, CKA_DECRYPT,
   1875                  mechanism_info.flags & CKF_DECRYPT ? &cktrue : &ckfalse,
   1876                  sizeof(CK_BBOOL));
   1877    privattrs++;
   1878    /* only set it if the attribute exists so we don't confuse old modules */
   1879    if (mechanism_info.flags & CKF_DECAPSULATE) {
   1880        PK11_SETATTRS(privattrs, CKA_DECAPSULATE, &cktrue, sizeof(CK_BBOOL));
   1881        privattrs++;
   1882    }
   1883 
   1884    if (token) {
   1885        session_handle = PK11_GetRWSession(slot);
   1886        haslock = PK11_RWSessionHasLock(slot, session_handle);
   1887        restore = PR_TRUE;
   1888    } else {
   1889        session_handle = slot->session;
   1890        if (session_handle != CK_INVALID_HANDLE)
   1891            PK11_EnterSlotMonitor(slot);
   1892        restore = PR_FALSE;
   1893        haslock = PR_TRUE;
   1894    }
   1895 
   1896    if (session_handle == CK_INVALID_HANDLE) {
   1897        PORT_SetError(SEC_ERROR_BAD_DATA);
   1898        return NULL;
   1899    }
   1900    privCount = privattrs - privTemplate;
   1901    pubCount = attrs - pubTemplate;
   1902    crv = PK11_GETTAB(slot)->C_GenerateKeyPair(session_handle, &mechanism,
   1903                                               pubTemplate, pubCount, privTemplate, privCount, &pubID, &privID);
   1904 
   1905    if (crv != CKR_OK) {
   1906        if (restore) {
   1907            PK11_RestoreROSession(slot, session_handle);
   1908        } else
   1909            PK11_ExitSlotMonitor(slot);
   1910        PORT_SetError(PK11_MapError(crv));
   1911        return NULL;
   1912    }
   1913    /* This locking code is dangerous and needs to be more thought
   1914     * out... the real problem is that we're holding the mutex open this long
   1915     */
   1916    if (haslock) {
   1917        PK11_ExitSlotMonitor(slot);
   1918    }
   1919 
   1920    /* swap around the ID's for older PKCS #11 modules */
   1921    keyClass = PK11_ReadULongAttribute(slot, pubID, CKA_CLASS);
   1922    if (keyClass != CKO_PUBLIC_KEY) {
   1923        CK_OBJECT_HANDLE tmp = pubID;
   1924        pubID = privID;
   1925        privID = tmp;
   1926    }
   1927 
   1928    *pubKey = PK11_ExtractPublicKey(slot, keyType, pubID);
   1929    if (*pubKey == NULL) {
   1930        if (restore) {
   1931            /* we may have to restore the mutex so it get's exited properly
   1932             * in RestoreROSession */
   1933            if (haslock)
   1934                PK11_EnterSlotMonitor(slot);
   1935            PK11_RestoreROSession(slot, session_handle);
   1936        }
   1937        PK11_DestroyObject(slot, pubID);
   1938        PK11_DestroyObject(slot, privID);
   1939        return NULL;
   1940    }
   1941 
   1942    /* set the ID to the public key so we can find it again */
   1943    cka_id = pk11_MakeIDFromPublicKey(*pubKey);
   1944    pubIsToken = (PRBool)PK11_HasAttributeSet(slot, pubID, CKA_TOKEN, PR_FALSE);
   1945 
   1946    PK11_SETATTRS(&setTemplate, CKA_ID, cka_id->data, cka_id->len);
   1947 
   1948    if (haslock) {
   1949        PK11_EnterSlotMonitor(slot);
   1950    }
   1951    crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, privID,
   1952                                                 &setTemplate, 1);
   1953 
   1954    if (crv == CKR_OK && pubIsToken) {
   1955        crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, pubID,
   1956                                                     &setTemplate, 1);
   1957    }
   1958 
   1959    if (restore) {
   1960        PK11_RestoreROSession(slot, session_handle);
   1961    } else {
   1962        PK11_ExitSlotMonitor(slot);
   1963    }
   1964    SECITEM_FreeItem(cka_id, PR_TRUE);
   1965 
   1966    if (crv != CKR_OK) {
   1967        PK11_DestroyObject(slot, pubID);
   1968        PK11_DestroyObject(slot, privID);
   1969        PORT_SetError(PK11_MapError(crv));
   1970        *pubKey = NULL;
   1971        return NULL;
   1972    }
   1973 
   1974    privKey = PK11_MakePrivKey(slot, keyType, !token, privID, wincx);
   1975    if (privKey == NULL) {
   1976        SECKEY_DestroyPublicKey(*pubKey);
   1977        PK11_DestroyObject(slot, privID);
   1978        *pubKey = NULL;
   1979        return NULL;
   1980    }
   1981 
   1982    return privKey;
   1983 }
   1984 
   1985 SECKEYPrivateKey *
   1986 PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
   1987                              void *param, SECKEYPublicKey **pubKey, PK11AttrFlags attrFlags, void *wincx)
   1988 {
   1989    return PK11_GenerateKeyPairWithOpFlags(slot, type, param, pubKey, attrFlags,
   1990                                           0, 0, wincx);
   1991 }
   1992 
   1993 /*
   1994 * Use the token to generate a key pair.
   1995 */
   1996 SECKEYPrivateKey *
   1997 PK11_GenerateKeyPair(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
   1998                     void *param, SECKEYPublicKey **pubKey, PRBool token,
   1999                     PRBool sensitive, void *wincx)
   2000 {
   2001    PK11AttrFlags attrFlags = 0;
   2002 
   2003    if (token) {
   2004        attrFlags |= PK11_ATTR_TOKEN;
   2005    } else {
   2006        attrFlags |= PK11_ATTR_SESSION;
   2007    }
   2008    if (sensitive) {
   2009        attrFlags |= (PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE);
   2010    } else {
   2011        attrFlags |= (PK11_ATTR_INSENSITIVE | PK11_ATTR_PUBLIC);
   2012    }
   2013    return PK11_GenerateKeyPairWithFlags(slot, type, param, pubKey,
   2014                                         attrFlags, wincx);
   2015 }
   2016 
   2017 /* build a public KEA key from the public value */
   2018 SECKEYPublicKey *
   2019 PK11_MakeKEAPubKey(unsigned char *keyData, int length)
   2020 {
   2021    SECKEYPublicKey *pubk;
   2022    SECItem pkData;
   2023    SECStatus rv;
   2024    PLArenaPool *arena;
   2025 
   2026    pkData.data = keyData;
   2027    pkData.len = length;
   2028    pkData.type = siBuffer;
   2029 
   2030    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   2031    if (arena == NULL)
   2032        return NULL;
   2033 
   2034    pubk = (SECKEYPublicKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
   2035    if (pubk == NULL) {
   2036        PORT_FreeArena(arena, PR_FALSE);
   2037        return NULL;
   2038    }
   2039 
   2040    pubk->arena = arena;
   2041    pubk->pkcs11Slot = 0;
   2042    pubk->pkcs11ID = CK_INVALID_HANDLE;
   2043    pubk->keyType = fortezzaKey;
   2044    rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.KEAKey, &pkData);
   2045    if (rv != SECSuccess) {
   2046        PORT_FreeArena(arena, PR_FALSE);
   2047        return NULL;
   2048    }
   2049    return pubk;
   2050 }
   2051 
   2052 SECStatus
   2053 SECKEY_SetPublicValue(SECKEYPrivateKey *privKey, const SECItem *publicValue)
   2054 {
   2055    SECStatus rv;
   2056    SECKEYPublicKey pubKey;
   2057    PLArenaPool *arena;
   2058    PK11SlotInfo *slot;
   2059    CK_OBJECT_HANDLE privKeyID;
   2060    CK_ULONG paramSet;
   2061 
   2062    if (privKey == NULL || publicValue == NULL ||
   2063        publicValue->data == NULL || publicValue->len == 0) {
   2064        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   2065        return SECFailure;
   2066    }
   2067 
   2068    pubKey.arena = NULL;
   2069    pubKey.keyType = privKey->keyType;
   2070    pubKey.pkcs11Slot = NULL;
   2071    pubKey.pkcs11ID = CK_INVALID_HANDLE;
   2072    /* can't use PORT_InitCheapArena here becase SECKEY_DestroyPublic is used
   2073     * to free it, and it uses PORT_FreeArena which not only frees the
   2074     * underlying arena, it also frees the allocated arena struct. */
   2075    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   2076    pubKey.arena = arena;
   2077    if (arena == NULL) {
   2078        return SECFailure;
   2079    }
   2080 
   2081    slot = privKey->pkcs11Slot;
   2082    privKeyID = privKey->pkcs11ID;
   2083    rv = SECFailure;
   2084    switch (privKey->keyType) {
   2085        default:
   2086            /* error code already set to SECFailure */
   2087            break;
   2088        case rsaKey:
   2089            pubKey.u.rsa.modulus = *publicValue;
   2090            rv = PK11_ReadAttribute(slot, privKeyID, CKA_PUBLIC_EXPONENT,
   2091                                    arena, &pubKey.u.rsa.publicExponent);
   2092            break;
   2093        case dsaKey:
   2094            pubKey.u.dsa.publicValue = *publicValue;
   2095            rv = PK11_ReadAttribute(slot, privKeyID, CKA_PRIME,
   2096                                    arena, &pubKey.u.dsa.params.prime);
   2097            if (rv != SECSuccess) {
   2098                break;
   2099            }
   2100            rv = PK11_ReadAttribute(slot, privKeyID, CKA_SUBPRIME,
   2101                                    arena, &pubKey.u.dsa.params.subPrime);
   2102            if (rv != SECSuccess) {
   2103                break;
   2104            }
   2105            rv = PK11_ReadAttribute(slot, privKeyID, CKA_BASE,
   2106                                    arena, &pubKey.u.dsa.params.base);
   2107            break;
   2108        case dhKey:
   2109            pubKey.u.dh.publicValue = *publicValue;
   2110            rv = PK11_ReadAttribute(slot, privKeyID, CKA_PRIME,
   2111                                    arena, &pubKey.u.dh.prime);
   2112            if (rv != SECSuccess) {
   2113                break;
   2114            }
   2115            rv = PK11_ReadAttribute(slot, privKeyID, CKA_BASE,
   2116                                    arena, &pubKey.u.dh.base);
   2117            break;
   2118        case ecKey:
   2119        case edKey:
   2120        case ecMontKey:
   2121            pubKey.u.ec.publicValue = *publicValue;
   2122            pubKey.u.ec.encoding = ECPoint_Undefined;
   2123            pubKey.u.ec.size = 0;
   2124            rv = PK11_ReadAttribute(slot, privKeyID, CKA_EC_PARAMS,
   2125                                    arena, &pubKey.u.ec.DEREncodedParams);
   2126            break;
   2127        case mldsaKey:
   2128            pubKey.u.mldsa.publicValue = *publicValue;
   2129            paramSet = PK11_ReadULongAttribute(slot, privKeyID,
   2130                                               CKA_PARAMETER_SET);
   2131            if (paramSet == CK_UNAVAILABLE_INFORMATION) {
   2132                PORT_SetError(SEC_ERROR_BAD_KEY);
   2133                break;
   2134            }
   2135            pubKey.u.mldsa.paramSet = SECKEY_GetMLDSAPkcs11ParamSetByOidTag(paramSet);
   2136            if (pubKey.u.mldsa.paramSet == SEC_OID_UNKNOWN) {
   2137                PORT_SetError(SEC_ERROR_BAD_KEY);
   2138                break;
   2139            }
   2140            rv = SECSuccess;
   2141            break;
   2142    }
   2143    if (rv == SECSuccess) {
   2144        rv = PK11_ImportPublicKey(slot, &pubKey, PR_TRUE);
   2145    }
   2146    /* Even though pubKey is stored on the stack, we've allocated
   2147     * some of it's data from the arena. SECKEY_DestroyPublicKey
   2148     * destroys keys by freeing the arena, so this will clean up all
   2149     * the data we allocated specifically for the key above. It will
   2150     * also free any slot references which we may have picked up in
   2151     * PK11_ImportPublicKey. It won't delete the underlying key if
   2152     * its a Token/Permanent key (which it will be if
   2153     * PK11_ImportPublicKey succeeds). */
   2154    SECKEY_DestroyPublicKey(&pubKey);
   2155 
   2156    return rv;
   2157 }
   2158 
   2159 /*
   2160 * NOTE: This function doesn't return a SECKEYPrivateKey struct to represent
   2161 * the new private key object.  If it were to create a session object that
   2162 * could later be looked up by its nickname, it would leak a SECKEYPrivateKey.
   2163 * So isPerm must be true.
   2164 */
   2165 SECStatus
   2166 PK11_ImportEncryptedPrivateKeyInfo(PK11SlotInfo *slot,
   2167                                   SECKEYEncryptedPrivateKeyInfo *epki, SECItem *pwitem,
   2168                                   SECItem *nickname, const SECItem *publicValue, PRBool isPerm,
   2169                                   PRBool isPrivate, KeyType keyType,
   2170                                   unsigned int keyUsage, void *wincx)
   2171 {
   2172    if (!isPerm) {
   2173        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   2174        return SECFailure;
   2175    }
   2176    return PK11_ImportEncryptedPrivateKeyInfoAndReturnKey(slot, epki,
   2177                                                          pwitem, nickname, publicValue, isPerm, isPrivate, keyType,
   2178                                                          keyUsage, NULL, wincx);
   2179 }
   2180 
   2181 SECStatus
   2182 PK11_ImportEncryptedPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
   2183                                               SECKEYEncryptedPrivateKeyInfo *epki, SECItem *pwitem,
   2184                                               SECItem *nickname, const SECItem *publicValue, PRBool isPerm,
   2185                                               PRBool isPrivate, KeyType keyType,
   2186                                               unsigned int keyUsage, SECKEYPrivateKey **privk,
   2187                                               void *wincx)
   2188 {
   2189    CK_MECHANISM_TYPE pbeMechType;
   2190    SECItem *crypto_param = NULL;
   2191    PK11SymKey *key = NULL;
   2192    SECStatus rv = SECSuccess;
   2193    CK_MECHANISM_TYPE cryptoMechType;
   2194    SECKEYPrivateKey *privKey = NULL;
   2195    PRBool faulty3DES = PR_FALSE;
   2196    if ((epki == NULL) || (pwitem == NULL))
   2197        return SECFailure;
   2198 
   2199    pbeMechType = PK11_AlgtagToMechanism(SECOID_FindOIDTag(
   2200        &epki->algorithm.algorithm));
   2201 
   2202 try_faulty_3des:
   2203 
   2204    key = PK11_PBEKeyGen(slot, &epki->algorithm, pwitem, faulty3DES, wincx);
   2205    if (key == NULL) {
   2206        rv = SECFailure;
   2207        goto done;
   2208    }
   2209    cryptoMechType = pk11_GetPBECryptoMechanism(&epki->algorithm,
   2210                                                &crypto_param, pwitem, faulty3DES);
   2211    if (cryptoMechType == CKM_INVALID_MECHANISM) {
   2212        rv = SECFailure;
   2213        goto done;
   2214    }
   2215 
   2216    cryptoMechType = PK11_GetPadMechanism(cryptoMechType);
   2217 
   2218    privKey = PK11_UnwrapPrivKeyByKeyType(slot, key, cryptoMechType,
   2219                                          crypto_param, &epki->encryptedData,
   2220                                          nickname, publicValue, isPerm,
   2221                                          isPrivate, keyType, keyUsage, wincx);
   2222    if (privKey) {
   2223        rv = SECSuccess;
   2224        goto done;
   2225    }
   2226 
   2227    /* if we are unable to import the key and the pbeMechType is
   2228     * CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC, then it is possible that
   2229     * the encrypted blob was created with a buggy key generation method
   2230     * which is described in the PKCS 12 implementation notes.  So we
   2231     * need to try importing via that method.
   2232     */
   2233    if ((pbeMechType == CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC) && (!faulty3DES)) {
   2234        /* clean up after ourselves before redoing the key generation. */
   2235 
   2236        PK11_FreeSymKey(key);
   2237        key = NULL;
   2238 
   2239        if (crypto_param) {
   2240            SECITEM_ZfreeItem(crypto_param, PR_TRUE);
   2241            crypto_param = NULL;
   2242        }
   2243 
   2244        faulty3DES = PR_TRUE;
   2245        goto try_faulty_3des;
   2246    }
   2247 
   2248    /* key import really did fail */
   2249    rv = SECFailure;
   2250 
   2251 done:
   2252    if ((rv == SECSuccess) && isPerm) {
   2253        /* If we are importing a token object,
   2254         * create the corresponding public key.
   2255         * If this fails, just continue as the target
   2256         * token simply might not support persistant
   2257         * public keys. Such tokens are usable, but
   2258         * need to be authenticated before searching
   2259         * for user certs. */
   2260        (void)SECKEY_SetPublicValue(privKey, publicValue);
   2261    }
   2262 
   2263    if (privKey) {
   2264        if (privk) {
   2265            *privk = privKey;
   2266        } else {
   2267            SECKEY_DestroyPrivateKey(privKey);
   2268        }
   2269        privKey = NULL;
   2270    }
   2271    if (crypto_param != NULL) {
   2272        SECITEM_ZfreeItem(crypto_param, PR_TRUE);
   2273    }
   2274 
   2275    if (key != NULL) {
   2276        PK11_FreeSymKey(key);
   2277    }
   2278 
   2279    return rv;
   2280 }
   2281 
   2282 SECKEYPrivateKeyInfo *
   2283 PK11_ExportPrivateKeyInfo(CERTCertificate *cert, void *wincx)
   2284 {
   2285    SECKEYPrivateKeyInfo *pki = NULL;
   2286    SECKEYPrivateKey *pk = PK11_FindKeyByAnyCert(cert, wincx);
   2287    if (pk != NULL) {
   2288        pki = PK11_ExportPrivKeyInfo(pk, wincx);
   2289        SECKEY_DestroyPrivateKey(pk);
   2290    }
   2291    return pki;
   2292 }
   2293 
   2294 /* V2 refers to PKCS #5 V2 here. If a PKCS #5 v1 or PKCS #12 pbe is passed
   2295 * for pbeTag, then encTag and hashTag are ignored. If pbe is an encryption
   2296 * algorithm, then PKCS #5 V2 is used with prfTag for the prf. If prfTag isn't
   2297 * supplied prf will be SEC_OID_HMAC_SHA1 */
   2298 SECKEYEncryptedPrivateKeyInfo *
   2299 PK11_ExportEncryptedPrivKeyInfoV2(
   2300    PK11SlotInfo *slot,   /* optional, encrypt key in this slot */
   2301    SECOidTag pbeAlg,     /* PBE algorithm to encrypt the with key */
   2302    SECOidTag encAlg,     /* Encryption algorithm to Encrypt the key with */
   2303    SECOidTag prfAlg,     /* Hash algorithm for PRF */
   2304    SECItem *pwitem,      /* password for PBE encryption */
   2305    SECKEYPrivateKey *pk, /* encrypt this private key */
   2306    int iteration,        /* interations for PBE alg */
   2307    void *pwArg)          /* context for password callback */
   2308 {
   2309    SECKEYEncryptedPrivateKeyInfo *epki = NULL;
   2310    PLArenaPool *arena = NULL;
   2311    SECAlgorithmID *algid;
   2312    SECOidTag pbeAlgTag = SEC_OID_UNKNOWN;
   2313    SECItem *crypto_param = NULL;
   2314    PK11SymKey *key = NULL;
   2315    SECKEYPrivateKey *tmpPK = NULL;
   2316    SECStatus rv = SECSuccess;
   2317    CK_RV crv;
   2318    CK_ULONG encBufLen;
   2319    CK_MECHANISM_TYPE pbeMechType;
   2320    CK_MECHANISM_TYPE cryptoMechType;
   2321    CK_MECHANISM cryptoMech;
   2322 
   2323    if (!pwitem || !pk) {
   2324        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   2325        return NULL;
   2326    }
   2327 
   2328    algid = sec_pkcs5CreateAlgorithmID(pbeAlg, encAlg, prfAlg,
   2329                                       &pbeAlgTag, 0, NULL, iteration);
   2330    if (algid == NULL) {
   2331        return NULL;
   2332    }
   2333 
   2334    arena = PORT_NewArena(2048);
   2335    if (arena)
   2336        epki = PORT_ArenaZNew(arena, SECKEYEncryptedPrivateKeyInfo);
   2337    if (epki == NULL) {
   2338        rv = SECFailure;
   2339        goto loser;
   2340    }
   2341    epki->arena = arena;
   2342 
   2343    /* if we didn't specify a slot, use the slot the private key was in */
   2344    if (!slot) {
   2345        slot = pk->pkcs11Slot;
   2346    }
   2347 
   2348    /* if we specified a different slot, and the private key slot can do the
   2349     * pbe key gen, generate the key in the private key slot so we don't have
   2350     * to move it later */
   2351    pbeMechType = PK11_AlgtagToMechanism(pbeAlgTag);
   2352    if (slot != pk->pkcs11Slot) {
   2353        if (PK11_DoesMechanism(pk->pkcs11Slot, pbeMechType)) {
   2354            slot = pk->pkcs11Slot;
   2355        }
   2356    }
   2357    key = PK11_PBEKeyGen(slot, algid, pwitem, PR_FALSE, pwArg);
   2358    if (key == NULL) {
   2359        rv = SECFailure;
   2360        goto loser;
   2361    }
   2362 
   2363    cryptoMechType = PK11_GetPBECryptoMechanism(algid, &crypto_param, pwitem);
   2364    if (cryptoMechType == CKM_INVALID_MECHANISM) {
   2365        rv = SECFailure;
   2366        goto loser;
   2367    }
   2368 
   2369    cryptoMech.mechanism = PK11_GetPadMechanism(cryptoMechType);
   2370    cryptoMech.pParameter = crypto_param ? crypto_param->data : NULL;
   2371    cryptoMech.ulParameterLen = crypto_param ? crypto_param->len : 0;
   2372 
   2373    /* If the key isn't in the private key slot, move it */
   2374    if (key->slot != pk->pkcs11Slot) {
   2375        PK11SymKey *newkey = pk11_CopyToSlot(pk->pkcs11Slot,
   2376                                             key->type, CKA_WRAP, key);
   2377        if (newkey == NULL) {
   2378            /* couldn't import the wrapping key, try exporting the
   2379             * private key */
   2380            tmpPK = pk11_loadPrivKey(key->slot, pk, NULL, PR_FALSE, PR_TRUE);
   2381            if (tmpPK == NULL) {
   2382                rv = SECFailure;
   2383                goto loser;
   2384            }
   2385            pk = tmpPK;
   2386        } else {
   2387            /* free the old key and use the new key */
   2388            PK11_FreeSymKey(key);
   2389            key = newkey;
   2390        }
   2391    }
   2392 
   2393    /* we are extracting an encrypted privateKey structure.
   2394     * which needs to be freed along with the buffer into which it is
   2395     * returned.  eventually, we should retrieve an encrypted key using
   2396     * pkcs8/pkcs5.
   2397     */
   2398    encBufLen = 0;
   2399    PK11_EnterSlotMonitor(pk->pkcs11Slot);
   2400    crv = PK11_GETTAB(pk->pkcs11Slot)->C_WrapKey(pk->pkcs11Slot->session, &cryptoMech, key->objectID, pk->pkcs11ID, NULL, &encBufLen);
   2401    PK11_ExitSlotMonitor(pk->pkcs11Slot);
   2402    if (crv != CKR_OK) {
   2403        rv = SECFailure;
   2404        goto loser;
   2405    }
   2406    epki->encryptedData.data = PORT_ArenaAlloc(arena, encBufLen);
   2407    if (!epki->encryptedData.data) {
   2408        rv = SECFailure;
   2409        goto loser;
   2410    }
   2411    PK11_EnterSlotMonitor(pk->pkcs11Slot);
   2412    crv = PK11_GETTAB(pk->pkcs11Slot)->C_WrapKey(pk->pkcs11Slot->session, &cryptoMech, key->objectID, pk->pkcs11ID, epki->encryptedData.data, &encBufLen);
   2413    PK11_ExitSlotMonitor(pk->pkcs11Slot);
   2414    epki->encryptedData.len = (unsigned int)encBufLen;
   2415    if (crv != CKR_OK) {
   2416        rv = SECFailure;
   2417        goto loser;
   2418    }
   2419 
   2420    if (!epki->encryptedData.len) {
   2421        rv = SECFailure;
   2422        goto loser;
   2423    }
   2424 
   2425    rv = SECOID_CopyAlgorithmID(arena, &epki->algorithm, algid);
   2426 
   2427 loser:
   2428    if (crypto_param != NULL) {
   2429        SECITEM_ZfreeItem(crypto_param, PR_TRUE);
   2430        crypto_param = NULL;
   2431    }
   2432 
   2433    if (key != NULL) {
   2434        PK11_FreeSymKey(key);
   2435    }
   2436    if (tmpPK != NULL) {
   2437        SECKEY_DestroyPrivateKey(tmpPK);
   2438    }
   2439    SECOID_DestroyAlgorithmID(algid, PR_TRUE);
   2440 
   2441    if (rv == SECFailure) {
   2442        if (arena != NULL) {
   2443            PORT_FreeArena(arena, PR_TRUE);
   2444        }
   2445        epki = NULL;
   2446    }
   2447 
   2448    return epki;
   2449 }
   2450 
   2451 SECKEYEncryptedPrivateKeyInfo *
   2452 PK11_ExportEncryptedPrivKeyInfo(
   2453    PK11SlotInfo *slot,   /* optional, encrypt key in this slot */
   2454    SECOidTag algTag,     /* PBE algorithm to encrypt the with key */
   2455    SECItem *pwitem,      /* password for PBE encryption */
   2456    SECKEYPrivateKey *pk, /* encrypt this private key */
   2457    int iteration,        /* interations for PBE alg */
   2458    void *pwArg)          /* context for password callback */
   2459 {
   2460    return PK11_ExportEncryptedPrivKeyInfoV2(slot, algTag, SEC_OID_UNKNOWN,
   2461                                             SEC_OID_UNKNOWN, pwitem, pk,
   2462                                             iteration, pwArg);
   2463 }
   2464 
   2465 /* V2 refers to PKCS #5 V2 here. If a PKCS #5 v1 or PKCS #12 pbe is passed
   2466 * for pbeTag, then encTag and hashTag are ignored. If pbe is an encryption
   2467 * algorithm, then PKCS #5 V2 is used with prfTag for the prf. If prfTag isn't
   2468 * supplied prf will be SEC_OID_HMAC_SHA1 */
   2469 SECKEYEncryptedPrivateKeyInfo *
   2470 PK11_ExportEncryptedPrivateKeyInfoV2(
   2471    PK11SlotInfo *slot,    /* optional, encrypt key in this slot */
   2472    SECOidTag pbeAlg,      /* PBE algorithm to encrypt the with key */
   2473    SECOidTag encAlg,      /* Encryption algorithm to Encrypt the key with */
   2474    SECOidTag prfAlg,      /* HMAC algorithm for PRF*/
   2475    SECItem *pwitem,       /* password for PBE encryption */
   2476    CERTCertificate *cert, /* wrap priv key for this user cert */
   2477    int iteration,         /* interations for PBE alg */
   2478    void *pwArg)           /* context for password callback */
   2479 {
   2480    SECKEYEncryptedPrivateKeyInfo *epki = NULL;
   2481    SECKEYPrivateKey *pk = PK11_FindKeyByAnyCert(cert, pwArg);
   2482    if (pk != NULL) {
   2483        epki = PK11_ExportEncryptedPrivKeyInfoV2(slot, pbeAlg, encAlg, prfAlg,
   2484                                                 pwitem, pk, iteration,
   2485                                                 pwArg);
   2486        SECKEY_DestroyPrivateKey(pk);
   2487    }
   2488    return epki;
   2489 }
   2490 
   2491 SECKEYEncryptedPrivateKeyInfo *
   2492 PK11_ExportEncryptedPrivateKeyInfo(
   2493    PK11SlotInfo *slot,    /* optional, encrypt key in this slot */
   2494    SECOidTag algTag,      /* encrypt key with this algorithm */
   2495    SECItem *pwitem,       /* password for PBE encryption */
   2496    CERTCertificate *cert, /* wrap priv key for this user cert */
   2497    int iteration,         /* interations for PBE alg */
   2498    void *pwArg)           /* context for password callback */
   2499 {
   2500    return PK11_ExportEncryptedPrivateKeyInfoV2(slot, algTag, SEC_OID_UNKNOWN,
   2501                                                SEC_OID_UNKNOWN, pwitem, cert,
   2502                                                iteration, pwArg);
   2503 }
   2504 
   2505 SECItem *
   2506 PK11_DEREncodePublicKey(const SECKEYPublicKey *pubk)
   2507 {
   2508    return SECKEY_EncodeDERSubjectPublicKeyInfo(pubk);
   2509 }
   2510 
   2511 char *
   2512 PK11_GetPrivateKeyNickname(SECKEYPrivateKey *privKey)
   2513 {
   2514    return PK11_GetObjectNickname(privKey->pkcs11Slot, privKey->pkcs11ID);
   2515 }
   2516 
   2517 char *
   2518 PK11_GetPublicKeyNickname(SECKEYPublicKey *pubKey)
   2519 {
   2520    return PK11_GetObjectNickname(pubKey->pkcs11Slot, pubKey->pkcs11ID);
   2521 }
   2522 
   2523 SECStatus
   2524 PK11_SetPrivateKeyNickname(SECKEYPrivateKey *privKey, const char *nickname)
   2525 {
   2526    return PK11_SetObjectNickname(privKey->pkcs11Slot,
   2527                                  privKey->pkcs11ID, nickname);
   2528 }
   2529 
   2530 SECStatus
   2531 PK11_SetPublicKeyNickname(SECKEYPublicKey *pubKey, const char *nickname)
   2532 {
   2533    return PK11_SetObjectNickname(pubKey->pkcs11Slot,
   2534                                  pubKey->pkcs11ID, nickname);
   2535 }
   2536 
   2537 SECKEYPQGParams *
   2538 PK11_GetPQGParamsFromPrivateKey(SECKEYPrivateKey *privKey)
   2539 {
   2540    CK_ATTRIBUTE pTemplate[] = {
   2541        { CKA_PRIME, NULL, 0 },
   2542        { CKA_SUBPRIME, NULL, 0 },
   2543        { CKA_BASE, NULL, 0 },
   2544    };
   2545    int pTemplateLen = sizeof(pTemplate) / sizeof(pTemplate[0]);
   2546    PLArenaPool *arena = NULL;
   2547    SECKEYPQGParams *params;
   2548    CK_RV crv;
   2549 
   2550    arena = PORT_NewArena(2048);
   2551    if (arena == NULL) {
   2552        goto loser;
   2553    }
   2554    params = (SECKEYPQGParams *)PORT_ArenaZAlloc(arena, sizeof(SECKEYPQGParams));
   2555    if (params == NULL) {
   2556        goto loser;
   2557    }
   2558 
   2559    crv = PK11_GetAttributes(arena, privKey->pkcs11Slot, privKey->pkcs11ID,
   2560                             pTemplate, pTemplateLen);
   2561    if (crv != CKR_OK) {
   2562        PORT_SetError(PK11_MapError(crv));
   2563        goto loser;
   2564    }
   2565 
   2566    params->arena = arena;
   2567    params->prime.data = pTemplate[0].pValue;
   2568    params->prime.len = pTemplate[0].ulValueLen;
   2569    params->subPrime.data = pTemplate[1].pValue;
   2570    params->subPrime.len = pTemplate[1].ulValueLen;
   2571    params->base.data = pTemplate[2].pValue;
   2572    params->base.len = pTemplate[2].ulValueLen;
   2573 
   2574    return params;
   2575 
   2576 loser:
   2577    if (arena != NULL) {
   2578        PORT_FreeArena(arena, PR_FALSE);
   2579    }
   2580    return NULL;
   2581 }
   2582 
   2583 SECKEYPrivateKey *
   2584 PK11_CopyTokenPrivKeyToSessionPrivKey(PK11SlotInfo *destSlot,
   2585                                      SECKEYPrivateKey *privKey)
   2586 {
   2587    CK_RV crv;
   2588    CK_OBJECT_HANDLE newKeyID;
   2589 
   2590    static const CK_BBOOL ckfalse = CK_FALSE;
   2591    static const CK_ATTRIBUTE template[1] = {
   2592        { CKA_TOKEN, (CK_BBOOL *)&ckfalse, sizeof ckfalse }
   2593    };
   2594 
   2595    if (destSlot && destSlot != privKey->pkcs11Slot) {
   2596        SECKEYPrivateKey *newKey =
   2597            pk11_loadPrivKey(destSlot,
   2598                             privKey,
   2599                             NULL,      /* pubKey    */
   2600                             PR_FALSE,  /* token     */
   2601                             PR_FALSE); /* sensitive */
   2602        if (newKey)
   2603            return newKey;
   2604    }
   2605    destSlot = privKey->pkcs11Slot;
   2606    PK11_Authenticate(destSlot, PR_TRUE, privKey->wincx);
   2607    PK11_EnterSlotMonitor(destSlot);
   2608    crv = PK11_GETTAB(destSlot)->C_CopyObject(destSlot->session,
   2609                                              privKey->pkcs11ID,
   2610                                              (CK_ATTRIBUTE *)template,
   2611                                              1, &newKeyID);
   2612    PK11_ExitSlotMonitor(destSlot);
   2613 
   2614    if (crv != CKR_OK) {
   2615        PORT_SetError(PK11_MapError(crv));
   2616        return NULL;
   2617    }
   2618 
   2619    return PK11_MakePrivKey(destSlot, privKey->keyType, PR_TRUE /*isTemp*/,
   2620                            newKeyID, privKey->wincx);
   2621 }
   2622 
   2623 SECKEYPrivateKey *
   2624 PK11_ConvertSessionPrivKeyToTokenPrivKey(SECKEYPrivateKey *privk, void *wincx)
   2625 {
   2626    PK11SlotInfo *slot = privk->pkcs11Slot;
   2627    CK_ATTRIBUTE template[1];
   2628    CK_ATTRIBUTE *attrs = template;
   2629    CK_BBOOL cktrue = CK_TRUE;
   2630    CK_RV crv;
   2631    CK_OBJECT_HANDLE newKeyID;
   2632    CK_SESSION_HANDLE rwsession;
   2633 
   2634    PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue));
   2635    attrs++;
   2636 
   2637    PK11_Authenticate(slot, PR_TRUE, wincx);
   2638    rwsession = PK11_GetRWSession(slot);
   2639    if (rwsession == CK_INVALID_HANDLE) {
   2640        PORT_SetError(SEC_ERROR_BAD_DATA);
   2641        return NULL;
   2642    }
   2643    crv = PK11_GETTAB(slot)->C_CopyObject(rwsession, privk->pkcs11ID,
   2644                                          template, 1, &newKeyID);
   2645    PK11_RestoreROSession(slot, rwsession);
   2646 
   2647    if (crv != CKR_OK) {
   2648        PORT_SetError(PK11_MapError(crv));
   2649        return NULL;
   2650    }
   2651 
   2652    return PK11_MakePrivKey(slot, nullKey /*KeyType*/, PR_FALSE /*isTemp*/,
   2653                            newKeyID, NULL /*wincx*/);
   2654 }
   2655 
   2656 /*
   2657 * destroy a private key if there are no matching certs.
   2658 * this function also frees the privKey structure.
   2659 */
   2660 SECStatus
   2661 PK11_DeleteTokenPrivateKey(SECKEYPrivateKey *privKey, PRBool force)
   2662 {
   2663    CERTCertificate *cert = PK11_GetCertFromPrivateKey(privKey);
   2664    SECStatus rv = SECWouldBlock;
   2665 
   2666    if (!cert || force) {
   2667        /* now, then it's safe for the key to go away */
   2668        rv = PK11_DestroyTokenObject(privKey->pkcs11Slot, privKey->pkcs11ID);
   2669    }
   2670    if (cert) {
   2671        CERT_DestroyCertificate(cert);
   2672    }
   2673    SECKEY_DestroyPrivateKey(privKey);
   2674    return rv;
   2675 }
   2676 
   2677 /*
   2678 * destroy a private key if there are no matching certs.
   2679 * this function also frees the privKey structure.
   2680 */
   2681 SECStatus
   2682 PK11_DeleteTokenPublicKey(SECKEYPublicKey *pubKey)
   2683 {
   2684    /* now, then it's safe for the key to go away */
   2685    if (pubKey->pkcs11Slot == NULL) {
   2686        return SECFailure;
   2687    }
   2688    PK11_DestroyTokenObject(pubKey->pkcs11Slot, pubKey->pkcs11ID);
   2689    SECKEY_DestroyPublicKey(pubKey);
   2690    return SECSuccess;
   2691 }
   2692 
   2693 /*
   2694 * key call back structure.
   2695 */
   2696 typedef struct pk11KeyCallbackStr {
   2697    SECStatus (*callback)(SECKEYPrivateKey *, void *);
   2698    void *callbackArg;
   2699    void *wincx;
   2700 } pk11KeyCallback;
   2701 
   2702 /*
   2703 * callback to map Object Handles to Private Keys;
   2704 */
   2705 SECStatus
   2706 pk11_DoKeys(PK11SlotInfo *slot, CK_OBJECT_HANDLE keyHandle, void *arg)
   2707 {
   2708    SECStatus rv = SECSuccess;
   2709    SECKEYPrivateKey *privKey;
   2710    pk11KeyCallback *keycb = (pk11KeyCallback *)arg;
   2711    if (!arg) {
   2712        return SECFailure;
   2713    }
   2714 
   2715    privKey = PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, keycb->wincx);
   2716 
   2717    if (privKey == NULL) {
   2718        return SECFailure;
   2719    }
   2720 
   2721    if (keycb->callback) {
   2722        rv = (*keycb->callback)(privKey, keycb->callbackArg);
   2723    }
   2724 
   2725    SECKEY_DestroyPrivateKey(privKey);
   2726    return rv;
   2727 }
   2728 
   2729 /***********************************************************************
   2730 * PK11_TraversePrivateKeysInSlot
   2731 *
   2732 * Traverses all the private keys on a slot.
   2733 *
   2734 * INPUTS
   2735 *      slot
   2736 *          The PKCS #11 slot whose private keys you want to traverse.
   2737 *      callback
   2738 *          A callback function that will be called for each key.
   2739 *      arg
   2740 *          An argument that will be passed to the callback function.
   2741 */
   2742 SECStatus
   2743 PK11_TraversePrivateKeysInSlot(PK11SlotInfo *slot,
   2744                               SECStatus (*callback)(SECKEYPrivateKey *, void *), void *arg)
   2745 {
   2746    pk11KeyCallback perKeyCB;
   2747    pk11TraverseSlot perObjectCB;
   2748    CK_OBJECT_CLASS privkClass = CKO_PRIVATE_KEY;
   2749    CK_BBOOL ckTrue = CK_TRUE;
   2750    CK_ATTRIBUTE theTemplate[2];
   2751    int templateSize = 2;
   2752 
   2753    theTemplate[0].type = CKA_CLASS;
   2754    theTemplate[0].pValue = &privkClass;
   2755    theTemplate[0].ulValueLen = sizeof(privkClass);
   2756    theTemplate[1].type = CKA_TOKEN;
   2757    theTemplate[1].pValue = &ckTrue;
   2758    theTemplate[1].ulValueLen = sizeof(ckTrue);
   2759 
   2760    if (slot == NULL) {
   2761        return SECSuccess;
   2762    }
   2763 
   2764    perObjectCB.callback = pk11_DoKeys;
   2765    perObjectCB.callbackArg = &perKeyCB;
   2766    perObjectCB.findTemplate = theTemplate;
   2767    perObjectCB.templateCount = templateSize;
   2768    perKeyCB.callback = callback;
   2769    perKeyCB.callbackArg = arg;
   2770    perKeyCB.wincx = NULL;
   2771 
   2772    return PK11_TraverseSlot(slot, &perObjectCB);
   2773 }
   2774 
   2775 /*
   2776 * return the private key with the given ID
   2777 */
   2778 CK_OBJECT_HANDLE
   2779 pk11_FindPrivateKeyFromCertID(PK11SlotInfo *slot, SECItem *keyID)
   2780 {
   2781    CK_OBJECT_CLASS privKey = CKO_PRIVATE_KEY;
   2782    CK_ATTRIBUTE theTemplate[] = {
   2783        { CKA_ID, NULL, 0 },
   2784        { CKA_CLASS, NULL, 0 },
   2785    };
   2786    /* if you change the array, change the variable below as well */
   2787    int tsize = sizeof(theTemplate) / sizeof(theTemplate[0]);
   2788    CK_ATTRIBUTE *attrs = theTemplate;
   2789 
   2790    PK11_SETATTRS(attrs, CKA_ID, keyID->data, keyID->len);
   2791    attrs++;
   2792    PK11_SETATTRS(attrs, CKA_CLASS, &privKey, sizeof(privKey));
   2793 
   2794    return pk11_FindObjectByTemplate(slot, theTemplate, tsize);
   2795 }
   2796 
   2797 SECKEYPrivateKey *
   2798 PK11_FindKeyByKeyID(PK11SlotInfo *slot, SECItem *keyID, void *wincx)
   2799 {
   2800    CK_OBJECT_HANDLE keyHandle;
   2801    SECKEYPrivateKey *privKey;
   2802 
   2803    keyHandle = pk11_FindPrivateKeyFromCertID(slot, keyID);
   2804    if (keyHandle == CK_INVALID_HANDLE) {
   2805        return NULL;
   2806    }
   2807    privKey = PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx);
   2808    return privKey;
   2809 }
   2810 
   2811 /*
   2812 * Generate a CKA_ID from the relevant public key data. The CKA_ID is generated
   2813 * from the pubKeyData by SHA1_Hashing it to produce a smaller CKA_ID (to make
   2814 * smart cards happy.
   2815 */
   2816 SECItem *
   2817 PK11_MakeIDFromPubKey(const SECItem *pubKeyData)
   2818 {
   2819    PK11Context *context;
   2820    SECItem *certCKA_ID;
   2821    SECStatus rv;
   2822 
   2823    if (pubKeyData->len <= SHA1_LENGTH) {
   2824        /* probably an already hashed value. The strongest known public
   2825         * key values <= 160 bits would be less than 40 bit symetric in
   2826         * strength. Don't hash them, just return the value. There are
   2827         * none at the time of this writing supported by previous versions
   2828         * of NSS, so change is binary compatible safe */
   2829        return SECITEM_DupItem(pubKeyData);
   2830    }
   2831 
   2832    context = PK11_CreateDigestContext(SEC_OID_SHA1);
   2833    if (context == NULL) {
   2834        return NULL;
   2835    }
   2836 
   2837    rv = PK11_DigestBegin(context);
   2838    if (rv == SECSuccess) {
   2839        rv = PK11_DigestOp(context, pubKeyData->data, pubKeyData->len);
   2840    }
   2841    if (rv != SECSuccess) {
   2842        PK11_DestroyContext(context, PR_TRUE);
   2843        return NULL;
   2844    }
   2845 
   2846    certCKA_ID = (SECItem *)PORT_Alloc(sizeof(SECItem));
   2847    if (certCKA_ID == NULL) {
   2848        PK11_DestroyContext(context, PR_TRUE);
   2849        return NULL;
   2850    }
   2851 
   2852    certCKA_ID->len = SHA1_LENGTH;
   2853    certCKA_ID->data = (unsigned char *)PORT_Alloc(certCKA_ID->len);
   2854    if (certCKA_ID->data == NULL) {
   2855        PORT_Free(certCKA_ID);
   2856        PK11_DestroyContext(context, PR_TRUE);
   2857        return NULL;
   2858    }
   2859 
   2860    rv = PK11_DigestFinal(context, certCKA_ID->data, &certCKA_ID->len,
   2861                          SHA1_LENGTH);
   2862    PK11_DestroyContext(context, PR_TRUE);
   2863    if (rv != SECSuccess) {
   2864        SECITEM_FreeItem(certCKA_ID, PR_TRUE);
   2865        return NULL;
   2866    }
   2867 
   2868    return certCKA_ID;
   2869 }
   2870 
   2871 /* Looking for PK11_GetKeyIDFromPrivateKey?
   2872 * Call PK11_GetLowLevelKeyIDForPrivateKey instead.
   2873 */
   2874 
   2875 SECItem *
   2876 PK11_GetLowLevelKeyIDForPrivateKey(SECKEYPrivateKey *privKey)
   2877 {
   2878    return pk11_GetLowLevelKeyFromHandle(privKey->pkcs11Slot, privKey->pkcs11ID);
   2879 }
   2880 
   2881 static SECStatus
   2882 privateKeyListCallback(SECKEYPrivateKey *key, void *arg)
   2883 {
   2884    SECKEYPrivateKeyList *list = (SECKEYPrivateKeyList *)arg;
   2885    return SECKEY_AddPrivateKeyToListTail(list, SECKEY_CopyPrivateKey(key));
   2886 }
   2887 
   2888 SECKEYPrivateKeyList *
   2889 PK11_ListPrivateKeysInSlot(PK11SlotInfo *slot)
   2890 {
   2891    SECStatus status;
   2892    SECKEYPrivateKeyList *keys;
   2893 
   2894    keys = SECKEY_NewPrivateKeyList();
   2895    if (keys == NULL)
   2896        return NULL;
   2897 
   2898    status = PK11_TraversePrivateKeysInSlot(slot, privateKeyListCallback,
   2899                                            (void *)keys);
   2900 
   2901    if (status != SECSuccess) {
   2902        SECKEY_DestroyPrivateKeyList(keys);
   2903        keys = NULL;
   2904    }
   2905 
   2906    return keys;
   2907 }
   2908 
   2909 SECKEYPublicKeyList *
   2910 PK11_ListPublicKeysInSlot(PK11SlotInfo *slot, char *nickname)
   2911 {
   2912    CK_ATTRIBUTE findTemp[4];
   2913    CK_ATTRIBUTE *attrs;
   2914    CK_BBOOL ckTrue = CK_TRUE;
   2915    CK_OBJECT_CLASS keyclass = CKO_PUBLIC_KEY;
   2916    size_t tsize = 0;
   2917    int objCount = 0;
   2918    CK_OBJECT_HANDLE *key_ids;
   2919    SECKEYPublicKeyList *keys;
   2920    int i, len;
   2921 
   2922    attrs = findTemp;
   2923    PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass));
   2924    attrs++;
   2925    PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue));
   2926    attrs++;
   2927    if (nickname) {
   2928        len = PORT_Strlen(nickname);
   2929        PK11_SETATTRS(attrs, CKA_LABEL, nickname, len);
   2930        attrs++;
   2931    }
   2932    tsize = attrs - findTemp;
   2933    PORT_Assert(tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE));
   2934 
   2935    key_ids = pk11_FindObjectsByTemplate(slot, findTemp, tsize, &objCount);
   2936    if (key_ids == NULL) {
   2937        return NULL;
   2938    }
   2939    keys = SECKEY_NewPublicKeyList();
   2940    if (keys == NULL) {
   2941        PORT_Free(key_ids);
   2942        return NULL;
   2943    }
   2944 
   2945    for (i = 0; i < objCount; i++) {
   2946        SECKEYPublicKey *pubKey =
   2947            PK11_ExtractPublicKey(slot, nullKey, key_ids[i]);
   2948        if (pubKey) {
   2949            SECKEY_AddPublicKeyToListTail(keys, pubKey);
   2950        }
   2951    }
   2952 
   2953    PORT_Free(key_ids);
   2954    return keys;
   2955 }
   2956 
   2957 SECKEYPrivateKeyList *
   2958 PK11_ListPrivKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx)
   2959 {
   2960    CK_ATTRIBUTE findTemp[4];
   2961    CK_ATTRIBUTE *attrs;
   2962    CK_BBOOL ckTrue = CK_TRUE;
   2963    CK_OBJECT_CLASS keyclass = CKO_PRIVATE_KEY;
   2964    size_t tsize = 0;
   2965    int objCount = 0;
   2966    CK_OBJECT_HANDLE *key_ids;
   2967    SECKEYPrivateKeyList *keys;
   2968    int i, len;
   2969 
   2970    attrs = findTemp;
   2971    PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass));
   2972    attrs++;
   2973    PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue));
   2974    attrs++;
   2975    if (nickname) {
   2976        len = PORT_Strlen(nickname);
   2977        PK11_SETATTRS(attrs, CKA_LABEL, nickname, len);
   2978        attrs++;
   2979    }
   2980    tsize = attrs - findTemp;
   2981    PORT_Assert(tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE));
   2982 
   2983    key_ids = pk11_FindObjectsByTemplate(slot, findTemp, tsize, &objCount);
   2984    if (key_ids == NULL) {
   2985        return NULL;
   2986    }
   2987    keys = SECKEY_NewPrivateKeyList();
   2988    if (keys == NULL) {
   2989        PORT_Free(key_ids);
   2990        return NULL;
   2991    }
   2992 
   2993    for (i = 0; i < objCount; i++) {
   2994        SECKEYPrivateKey *privKey =
   2995            PK11_MakePrivKey(slot, nullKey, PR_TRUE, key_ids[i], wincx);
   2996        SECKEY_AddPrivateKeyToListTail(keys, privKey);
   2997    }
   2998 
   2999    PORT_Free(key_ids);
   3000    return keys;
   3001 }