tor-browser

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

pkcs11c.c (365580B)


      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 implements PKCS 11 on top of our existing security modules
      6 *
      7 * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
      8 *   This implementation has two slots:
      9 *      slot 1 is our generic crypto support. It does not require login.
     10 *   It supports Public Key ops, and all they bulk ciphers and hashes.
     11 *   It can also support Private Key ops for imported Private keys. It does
     12 *   not have any token storage.
     13 *      slot 2 is our private key support. It requires a login before use. It
     14 *   can store Private Keys and Certs as token objects. Currently only private
     15 *   keys and their associated Certificates are saved on the token.
     16 *
     17 *   In this implementation, session objects are only visible to the session
     18 *   that created or generated them.
     19 */
     20 
     21 #include <limits.h> /* for UINT_MAX and ULONG_MAX */
     22 
     23 #include "lowkeyti.h"
     24 #include "seccomon.h"
     25 #include "secitem.h"
     26 #include "secport.h"
     27 #include "blapi.h"
     28 /* we need to use the deprecated mechanisms values for backward compatibility */
     29 #include "pkcs11.h"
     30 #include "pkcs11i.h"
     31 #include "pkcs1sig.h"
     32 #include "lowkeyi.h"
     33 #include "secder.h"
     34 #include "secdig.h"
     35 #include "lowpbe.h" /* We do PBE below */
     36 #include "pkcs11t.h"
     37 #include "secoid.h"
     38 #include "cmac.h"
     39 #include "alghmac.h"
     40 #include "softoken.h"
     41 #include "secasn1.h"
     42 #include "secerr.h"
     43 #include "kem.h"
     44 #include "kyber.h"
     45 
     46 #include "prprf.h"
     47 #include "prenv.h"
     48 #include "prerror.h"
     49 
     50 #define __PASTE(x, y) x##y
     51 #define BAD_PARAM_CAST(pMech, typeSize) (!pMech->pParameter || pMech->ulParameterLen < typeSize)
     52 /*
     53 * we renamed all our internal functions, get the correct
     54 * definitions for them...
     55 */
     56 #undef CK_PKCS11_FUNCTION_INFO
     57 #undef CK_NEED_ARG_LIST
     58 
     59 #define CK_PKCS11_3_0 1
     60 
     61 #define CK_EXTERN extern
     62 #define CK_PKCS11_FUNCTION_INFO(func) \
     63    CK_RV __PASTE(NS, func)
     64 #define CK_NEED_ARG_LIST 1
     65 
     66 #include "pkcs11f.h"
     67 
     68 /* create a definition of SHA1 that's consistent
     69 * with the rest of the CKM_SHAxxx hashes*/
     70 #define CKM_SHA1 CKM_SHA_1
     71 #define CKM_SHA1_HMAC CKM_SHA_1_HMAC
     72 #define CKM_SHA1_HMAC_GENERAL CKM_SHA_1_HMAC_GENERAL
     73 
     74 typedef struct {
     75    PRUint8 client_version[2];
     76    PRUint8 random[46];
     77 } SSL3RSAPreMasterSecret;
     78 
     79 static void
     80 sftk_Null(void *data, PRBool freeit)
     81 {
     82    return;
     83 }
     84 
     85 /* fake hash end, the hashed data is already in the signature context,
     86 * return a NULL hash, which will be passed to the sign final and ignored */
     87 void
     88 sftk_NullHashEnd(void *info, unsigned char *data, unsigned int *lenp,
     89                 unsigned int maxlen)
     90 {
     91    *lenp = 0;
     92 }
     93 
     94 #ifdef EC_DEBUG
     95 #define SEC_PRINT(str1, str2, num, sitem)             \
     96    printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \
     97           str1, str2, num, sitem->len);              \
     98    for (i = 0; i < sitem->len; i++) {                \
     99        printf("%02x:", sitem->data[i]);              \
    100    }                                                 \
    101    printf("\n")
    102 #else
    103 #undef EC_DEBUG
    104 #define SEC_PRINT(a, b, c, d)
    105 #endif
    106 
    107 /* Wrappers to avoid undefined behavior calling functions through a pointer of incorrect type. */
    108 #define SFTKHashWrap(ctxtype, mmm)                                                        \
    109    static void                                                                           \
    110        SFTKHash_##mmm##_Update(void *vctx, const unsigned char *input, unsigned int len) \
    111    {                                                                                     \
    112        ctxtype *ctx = vctx;                                                              \
    113        mmm##_Update(ctx, input, len);                                                    \
    114    }                                                                                     \
    115    static void                                                                           \
    116        SFTKHash_##mmm##_End(void *vctx, unsigned char *digest,                           \
    117                             unsigned int *len, unsigned int maxLen)                      \
    118    {                                                                                     \
    119        ctxtype *ctx = vctx;                                                              \
    120        mmm##_End(ctx, digest, len, maxLen);                                              \
    121    }                                                                                     \
    122    static void                                                                           \
    123        SFTKHash_##mmm##_DestroyContext(void *vctx, PRBool freeit)                        \
    124    {                                                                                     \
    125        ctxtype *ctx = vctx;                                                              \
    126        mmm##_DestroyContext(ctx, freeit);                                                \
    127    }
    128 
    129 SFTKHashWrap(MD2Context, MD2);
    130 SFTKHashWrap(MD5Context, MD5);
    131 SFTKHashWrap(SHA1Context, SHA1);
    132 SFTKHashWrap(SHA224Context, SHA224);
    133 SFTKHashWrap(SHA256Context, SHA256);
    134 SFTKHashWrap(SHA384Context, SHA384);
    135 SFTKHashWrap(SHA512Context, SHA512);
    136 SFTKHashWrap(SHA3_224Context, SHA3_224);
    137 SFTKHashWrap(SHA3_256Context, SHA3_256);
    138 SFTKHashWrap(SHA3_384Context, SHA3_384);
    139 SFTKHashWrap(SHA3_512Context, SHA3_512);
    140 SFTKHashWrap(sftk_MACCtx, sftk_MAC);
    141 
    142 static void
    143 SFTKHash_SHA1_Begin(void *vctx)
    144 {
    145    SHA1Context *ctx = vctx;
    146    SHA1_Begin(ctx);
    147 }
    148 
    149 static void
    150 SFTKHash_MD5_Begin(void *vctx)
    151 {
    152    MD5Context *ctx = vctx;
    153    MD5_Begin(ctx);
    154 }
    155 
    156 #define SFTKCipherWrap(ctxtype, mmm)                                         \
    157    static SECStatus                                                         \
    158        SFTKCipher_##mmm(void *vctx, unsigned char *output,                  \
    159                         unsigned int *outputLen, unsigned int maxOutputLen, \
    160                         const unsigned char *input, unsigned int inputLen)  \
    161    {                                                                        \
    162        ctxtype *ctx = vctx;                                                 \
    163        return mmm(ctx, output, outputLen, maxOutputLen,                     \
    164                   input, inputLen);                                         \
    165    }
    166 
    167 SFTKCipherWrap(AESKeyWrapContext, AESKeyWrap_EncryptKWP);
    168 SFTKCipherWrap(AESKeyWrapContext, AESKeyWrap_DecryptKWP);
    169 
    170 #define SFTKCipherWrap2(ctxtype, mmm)                                        \
    171    SFTKCipherWrap(ctxtype, mmm##_Encrypt);                                  \
    172    SFTKCipherWrap(ctxtype, mmm##_Decrypt);                                  \
    173    static void SFTKCipher_##mmm##_DestroyContext(void *vctx, PRBool freeit) \
    174    {                                                                        \
    175        ctxtype *ctx = vctx;                                                 \
    176        mmm##_DestroyContext(ctx, freeit);                                   \
    177    }
    178 
    179 #ifndef NSS_DISABLE_DEPRECATED_RC2
    180 SFTKCipherWrap2(RC2Context, RC2);
    181 #endif
    182 SFTKCipherWrap2(RC4Context, RC4);
    183 SFTKCipherWrap2(DESContext, DES);
    184 #ifndef NSS_DISABLE_DEPRECATED_SEED
    185 SFTKCipherWrap2(SEEDContext, SEED);
    186 #endif
    187 SFTKCipherWrap2(CamelliaContext, Camellia);
    188 SFTKCipherWrap2(AESContext, AES);
    189 SFTKCipherWrap2(AESKeyWrapContext, AESKeyWrap);
    190 
    191 #if NSS_SOFTOKEN_DOES_RC5
    192 SFTKCipherWrap2(RC5Context, RC5);
    193 #endif
    194 
    195 /*
    196 * free routines.... Free local type  allocated data, and convert
    197 * other free routines to the destroy signature.
    198 */
    199 static void
    200 sftk_FreePrivKey(void *vkey, PRBool freeit)
    201 {
    202    NSSLOWKEYPrivateKey *key = vkey;
    203    nsslowkey_DestroyPrivateKey(key);
    204 }
    205 
    206 static void
    207 sftk_Space(void *data, PRBool freeit)
    208 {
    209    PORT_Free(data);
    210 }
    211 
    212 static void
    213 sftk_ZSpace(void *data, PRBool freeit)
    214 {
    215    size_t len = *(size_t *)data;
    216    PORT_ZFree(data, len);
    217 }
    218 
    219 /*
    220 * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by
    221 * Deprecating a full des key to 40 bit key strenth.
    222 */
    223 static CK_RV
    224 sftk_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey)
    225 {
    226    unsigned char key1[8] = { 0xc4, 0x08, 0xb0, 0x54, 0x0b, 0xa1, 0xe0, 0xae };
    227    unsigned char key2[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 };
    228    unsigned char enc_src[8];
    229    unsigned char enc_dest[8];
    230    unsigned int leng, i;
    231    DESContext *descx;
    232    SECStatus rv;
    233    CK_RV crv = CKR_OK;
    234 
    235    /* zero the parity bits */
    236    for (i = 0; i < 8; i++) {
    237        enc_src[i] = cdmfkey[i] & 0xfe;
    238    }
    239 
    240    /* encrypt with key 1 */
    241    descx = DES_CreateContext(key1, NULL, NSS_DES, PR_TRUE);
    242    if (descx == NULL) {
    243        crv = CKR_HOST_MEMORY;
    244        goto done;
    245    }
    246    rv = DES_Encrypt(descx, enc_dest, &leng, 8, enc_src, 8);
    247    DES_DestroyContext(descx, PR_TRUE);
    248    if (rv != SECSuccess) {
    249        crv = sftk_MapCryptError(PORT_GetError());
    250        goto done;
    251    }
    252 
    253    /* xor source with des, zero the parity bits and deprecate the key*/
    254    for (i = 0; i < 8; i++) {
    255        if (i & 1) {
    256            enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe;
    257        } else {
    258            enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e;
    259        }
    260    }
    261 
    262    /* encrypt with key 2 */
    263    descx = DES_CreateContext(key2, NULL, NSS_DES, PR_TRUE);
    264    if (descx == NULL) {
    265        crv = CKR_HOST_MEMORY;
    266        goto done;
    267    }
    268    rv = DES_Encrypt(descx, deskey, &leng, 8, enc_src, 8);
    269    DES_DestroyContext(descx, PR_TRUE);
    270    if (rv != SECSuccess) {
    271        crv = sftk_MapCryptError(PORT_GetError());
    272        goto done;
    273    }
    274 
    275    /* set the corret parity on our new des key */
    276    sftk_FormatDESKey(deskey, 8);
    277 done:
    278    PORT_Memset(enc_src, 0, sizeof enc_src);
    279    PORT_Memset(enc_dest, 0, sizeof enc_dest);
    280    return crv;
    281 }
    282 
    283 /* NSC_DestroyObject destroys an object. */
    284 CK_RV
    285 NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
    286 {
    287    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
    288    SFTKSession *session;
    289    SFTKObject *object;
    290    SFTKFreeStatus status;
    291 
    292    CHECK_FORK();
    293 
    294    if (slot == NULL) {
    295        return CKR_SESSION_HANDLE_INVALID;
    296    }
    297    /*
    298     * This whole block just makes sure we really can destroy the
    299     * requested object.
    300     */
    301    session = sftk_SessionFromHandle(hSession);
    302    if (session == NULL) {
    303        return CKR_SESSION_HANDLE_INVALID;
    304    }
    305 
    306    object = sftk_ObjectFromHandle(hObject, session);
    307    if (object == NULL) {
    308        sftk_FreeSession(session);
    309        return CKR_OBJECT_HANDLE_INVALID;
    310    }
    311 
    312    /* don't destroy a private object if we aren't logged in */
    313    if ((!slot->isLoggedIn) && (slot->needLogin) &&
    314        (sftk_isTrue(object, CKA_PRIVATE))) {
    315        sftk_FreeSession(session);
    316        sftk_FreeObject(object);
    317        return CKR_USER_NOT_LOGGED_IN;
    318    }
    319 
    320    /* don't destroy a token object if we aren't in a rw session */
    321 
    322    if (((session->info.flags & CKF_RW_SESSION) == 0) &&
    323        (sftk_isTrue(object, CKA_TOKEN))) {
    324        sftk_FreeSession(session);
    325        sftk_FreeObject(object);
    326        return CKR_SESSION_READ_ONLY;
    327    }
    328 
    329    sftk_DeleteObject(session, object);
    330 
    331    sftk_FreeSession(session);
    332 
    333    /*
    334     * get some indication if the object is destroyed. Note: this is not
    335     * 100%. Someone may have an object reference outstanding (though that
    336     * should not be the case by here. Also note that the object is "half"
    337     * destroyed. Our internal representation is destroyed, but it may still
    338     * be in the data base.
    339     */
    340    status = sftk_FreeObject(object);
    341 
    342    return (status != SFTK_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR;
    343 }
    344 
    345 /*
    346 * Returns true if "params" contains a valid set of PSS parameters
    347 */
    348 static PRBool
    349 sftk_ValidatePssParams(const CK_RSA_PKCS_PSS_PARAMS *params)
    350 {
    351    if (!params) {
    352        return PR_FALSE;
    353    }
    354    if (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL ||
    355        sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) {
    356        return PR_FALSE;
    357    }
    358    return PR_TRUE;
    359 }
    360 
    361 /*
    362 * Returns true if "params" contains a valid set of OAEP parameters
    363 */
    364 static PRBool
    365 sftk_ValidateOaepParams(const CK_RSA_PKCS_OAEP_PARAMS *params)
    366 {
    367    if (!params) {
    368        return PR_FALSE;
    369    }
    370    /* The requirements of ulSourceLen/pSourceData come from PKCS #11, which
    371     * state:
    372     *   If the parameter is empty, pSourceData must be NULL and
    373     *   ulSourceDataLen must be zero.
    374     */
    375    if (params->source != CKZ_DATA_SPECIFIED ||
    376        (sftk_GetHashTypeFromMechanism(params->hashAlg) == HASH_AlgNULL) ||
    377        (sftk_GetHashTypeFromMechanism(params->mgf) == HASH_AlgNULL) ||
    378        (params->ulSourceDataLen == 0 && params->pSourceData != NULL) ||
    379        (params->ulSourceDataLen != 0 && params->pSourceData == NULL)) {
    380        return PR_FALSE;
    381    }
    382    return PR_TRUE;
    383 }
    384 
    385 /*
    386 * return a context based on the SFTKContext type.
    387 */
    388 SFTKSessionContext *
    389 sftk_ReturnContextByType(SFTKSession *session, SFTKContextType type)
    390 {
    391    switch (type) {
    392        case SFTK_ENCRYPT:
    393        case SFTK_DECRYPT:
    394        case SFTK_MESSAGE_ENCRYPT:
    395        case SFTK_MESSAGE_DECRYPT:
    396            return session->enc_context;
    397        case SFTK_HASH:
    398            return session->hash_context;
    399        case SFTK_SIGN:
    400        case SFTK_SIGN_RECOVER:
    401        case SFTK_VERIFY:
    402        case SFTK_VERIFY_RECOVER:
    403        case SFTK_MESSAGE_SIGN:
    404        case SFTK_MESSAGE_VERIFY:
    405            return session->hash_context;
    406    }
    407    return NULL;
    408 }
    409 
    410 /*
    411 * change a context based on the SFTKContext type.
    412 */
    413 void
    414 sftk_SetContextByType(SFTKSession *session, SFTKContextType type,
    415                      SFTKSessionContext *context)
    416 {
    417    switch (type) {
    418        case SFTK_ENCRYPT:
    419        case SFTK_DECRYPT:
    420        case SFTK_MESSAGE_ENCRYPT:
    421        case SFTK_MESSAGE_DECRYPT:
    422            session->enc_context = context;
    423            break;
    424        case SFTK_HASH:
    425            session->hash_context = context;
    426            break;
    427        case SFTK_SIGN:
    428        case SFTK_SIGN_RECOVER:
    429        case SFTK_VERIFY:
    430        case SFTK_VERIFY_RECOVER:
    431        case SFTK_MESSAGE_SIGN:
    432        case SFTK_MESSAGE_VERIFY:
    433            session->hash_context = context;
    434            break;
    435    }
    436    return;
    437 }
    438 
    439 /*
    440 * code to grab the context. Needed by every C_XXXUpdate, C_XXXFinal,
    441 * and C_XXX function. The function takes a session handle, the context type,
    442 * and wether or not the session needs to be multipart. It returns the context,
    443 * and optionally returns the session pointer (if sessionPtr != NULL) if session
    444 * pointer is returned, the caller is responsible for freeing it.
    445 */
    446 CK_RV
    447 sftk_GetContext(CK_SESSION_HANDLE handle, SFTKSessionContext **contextPtr,
    448                SFTKContextType type, PRBool needMulti, SFTKSession **sessionPtr)
    449 {
    450    SFTKSession *session;
    451    SFTKSessionContext *context;
    452 
    453    session = sftk_SessionFromHandle(handle);
    454    if (session == NULL)
    455        return CKR_SESSION_HANDLE_INVALID;
    456    context = sftk_ReturnContextByType(session, type);
    457    /* make sure the context is valid */
    458    if ((context == NULL) || (context->type != type) || (needMulti && !(context->multi))) {
    459        sftk_FreeSession(session);
    460        return CKR_OPERATION_NOT_INITIALIZED;
    461    }
    462    *contextPtr = context;
    463    if (sessionPtr != NULL) {
    464        *sessionPtr = session;
    465    } else {
    466        sftk_FreeSession(session);
    467    }
    468    return CKR_OK;
    469 }
    470 
    471 /** Terminate operation (in the PKCS#11 spec sense).
    472 *  Intuitive name for FreeContext/SetNullContext pair.
    473 */
    474 void
    475 sftk_TerminateOp(SFTKSession *session, SFTKContextType ctype,
    476                 SFTKSessionContext *context)
    477 {
    478    session->lastOpWasFIPS = context->isFIPS;
    479    sftk_FreeContext(context);
    480    sftk_SetContextByType(session, ctype, NULL);
    481 }
    482 
    483 /*
    484 ************** Crypto Functions:     Encrypt ************************
    485 */
    486 
    487 /*
    488 * All the NSC_InitXXX functions have a set of common checks and processing they
    489 * all need to do at the beginning. This is done here.
    490 */
    491 CK_RV
    492 sftk_InitGeneric(SFTKSession *session, CK_MECHANISM *pMechanism,
    493                 SFTKSessionContext **contextPtr,
    494                 SFTKContextType ctype, SFTKObject **keyPtr,
    495                 CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr,
    496                 CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation)
    497 {
    498    SFTKObject *key = NULL;
    499    SFTKAttribute *att;
    500    SFTKSessionContext *context;
    501 
    502    /* We can only init if there is not current context active */
    503    if (sftk_ReturnContextByType(session, ctype) != NULL) {
    504        return CKR_OPERATION_ACTIVE;
    505    }
    506 
    507    /* find the key */
    508    if (keyPtr) {
    509        key = sftk_ObjectFromHandle(hKey, session);
    510        if (key == NULL) {
    511            return CKR_KEY_HANDLE_INVALID;
    512        }
    513 
    514        /* make sure it's a valid  key for this operation */
    515        if (((key->objclass != CKO_SECRET_KEY) &&
    516             (key->objclass != pubKeyType)) ||
    517            !sftk_isTrue(key, operation)) {
    518            sftk_FreeObject(key);
    519            return CKR_KEY_TYPE_INCONSISTENT;
    520        }
    521        /* get the key type */
    522        att = sftk_FindAttribute(key, CKA_KEY_TYPE);
    523        if (att == NULL) {
    524            sftk_FreeObject(key);
    525            return CKR_KEY_TYPE_INCONSISTENT;
    526        }
    527        PORT_Assert(att->attrib.ulValueLen == sizeof(CK_KEY_TYPE));
    528        if (att->attrib.ulValueLen != sizeof(CK_KEY_TYPE)) {
    529            sftk_FreeAttribute(att);
    530            sftk_FreeObject(key);
    531            return CKR_ATTRIBUTE_VALUE_INVALID;
    532        }
    533        PORT_Memcpy(keyTypePtr, att->attrib.pValue, sizeof(CK_KEY_TYPE));
    534        sftk_FreeAttribute(att);
    535        *keyPtr = key;
    536    }
    537 
    538    /* allocate the context structure */
    539    context = (SFTKSessionContext *)PORT_Alloc(sizeof(SFTKSessionContext));
    540    if (context == NULL) {
    541        if (key)
    542            sftk_FreeObject(key);
    543        return CKR_HOST_MEMORY;
    544    }
    545    context->type = ctype;
    546    context->multi = PR_TRUE;
    547    context->rsa = PR_FALSE;
    548    context->cipherInfo = NULL;
    549    context->hashInfo = NULL;
    550    context->doPad = PR_FALSE;
    551    context->padDataLength = 0;
    552    context->key = key;
    553    context->blockSize = 0;
    554    context->maxLen = 0;
    555    context->signature = NULL;
    556    context->isFIPS = sftk_operationIsFIPS(session->slot, pMechanism,
    557                                           operation, key);
    558    *contextPtr = context;
    559    return CKR_OK;
    560 }
    561 
    562 static int
    563 sftk_aes_mode(CK_MECHANISM_TYPE mechanism)
    564 {
    565    switch (mechanism) {
    566        case CKM_AES_CBC_PAD:
    567        case CKM_AES_CBC:
    568            return NSS_AES_CBC;
    569        case CKM_AES_ECB:
    570            return NSS_AES;
    571        case CKM_AES_CTS:
    572            return NSS_AES_CTS;
    573        case CKM_AES_CTR:
    574            return NSS_AES_CTR;
    575        case CKM_AES_GCM:
    576            return NSS_AES_GCM;
    577    }
    578    return -1;
    579 }
    580 
    581 static SECStatus
    582 sftk_RSAEncryptRaw(void *ctx, unsigned char *output,
    583                   unsigned int *outputLen, unsigned int maxLen,
    584                   const unsigned char *input, unsigned int inputLen)
    585 {
    586    NSSLOWKEYPublicKey *key = ctx;
    587    SECStatus rv = SECFailure;
    588 
    589    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
    590    if (key->keyType != NSSLOWKEYRSAKey) {
    591        PORT_SetError(SEC_ERROR_INVALID_KEY);
    592        return SECFailure;
    593    }
    594 
    595    rv = RSA_EncryptRaw(&key->u.rsa, output, outputLen, maxLen, input,
    596                        inputLen);
    597    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
    598        sftk_fatalError = PR_TRUE;
    599    }
    600 
    601    return rv;
    602 }
    603 
    604 static SECStatus
    605 sftk_RSADecryptRaw(void *ctx, unsigned char *output,
    606                   unsigned int *outputLen, unsigned int maxLen,
    607                   const unsigned char *input, unsigned int inputLen)
    608 {
    609    NSSLOWKEYPrivateKey *key = ctx;
    610    SECStatus rv = SECFailure;
    611 
    612    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
    613    if (key->keyType != NSSLOWKEYRSAKey) {
    614        PORT_SetError(SEC_ERROR_INVALID_KEY);
    615        return SECFailure;
    616    }
    617 
    618    rv = RSA_DecryptRaw(&key->u.rsa, output, outputLen, maxLen, input,
    619                        inputLen);
    620    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
    621        sftk_fatalError = PR_TRUE;
    622    }
    623 
    624    return rv;
    625 }
    626 
    627 static SECStatus
    628 sftk_RSAEncrypt(void *ctx, unsigned char *output,
    629                unsigned int *outputLen, unsigned int maxLen,
    630                const unsigned char *input, unsigned int inputLen)
    631 {
    632    NSSLOWKEYPublicKey *key = ctx;
    633    SECStatus rv = SECFailure;
    634 
    635    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
    636    if (key->keyType != NSSLOWKEYRSAKey) {
    637        PORT_SetError(SEC_ERROR_INVALID_KEY);
    638        return SECFailure;
    639    }
    640 
    641    rv = RSA_EncryptBlock(&key->u.rsa, output, outputLen, maxLen, input,
    642                          inputLen);
    643    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
    644        sftk_fatalError = PR_TRUE;
    645    }
    646 
    647    return rv;
    648 }
    649 
    650 static SECStatus
    651 sftk_RSADecrypt(void *ctx, unsigned char *output,
    652                unsigned int *outputLen, unsigned int maxLen,
    653                const unsigned char *input, unsigned int inputLen)
    654 {
    655    NSSLOWKEYPrivateKey *key = ctx;
    656    SECStatus rv = SECFailure;
    657 
    658    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
    659    if (key->keyType != NSSLOWKEYRSAKey) {
    660        PORT_SetError(SEC_ERROR_INVALID_KEY);
    661        return SECFailure;
    662    }
    663 
    664    rv = RSA_DecryptBlock(&key->u.rsa, output, outputLen, maxLen, input,
    665                          inputLen);
    666    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
    667        sftk_fatalError = PR_TRUE;
    668    }
    669 
    670    return rv;
    671 }
    672 
    673 static void
    674 sftk_freeRSAOAEPInfo(void *ctx, PRBool freeit)
    675 {
    676    SFTKOAEPInfo *info = ctx;
    677    PORT_ZFree(info->params.pSourceData, info->params.ulSourceDataLen);
    678    PORT_ZFree(info, sizeof(SFTKOAEPInfo));
    679 }
    680 
    681 static SECStatus
    682 sftk_RSAEncryptOAEP(void *ctx, unsigned char *output,
    683                    unsigned int *outputLen, unsigned int maxLen,
    684                    const unsigned char *input, unsigned int inputLen)
    685 {
    686    SFTKOAEPInfo *info = ctx;
    687    HASH_HashType hashAlg;
    688    HASH_HashType maskHashAlg;
    689 
    690    PORT_Assert(info->key.pub->keyType == NSSLOWKEYRSAKey);
    691    if (info->key.pub->keyType != NSSLOWKEYRSAKey) {
    692        PORT_SetError(SEC_ERROR_INVALID_KEY);
    693        return SECFailure;
    694    }
    695 
    696    hashAlg = sftk_GetHashTypeFromMechanism(info->params.hashAlg);
    697    maskHashAlg = sftk_GetHashTypeFromMechanism(info->params.mgf);
    698 
    699    return RSA_EncryptOAEP(&info->key.pub->u.rsa, hashAlg, maskHashAlg,
    700                           (const unsigned char *)info->params.pSourceData,
    701                           info->params.ulSourceDataLen, NULL, 0,
    702                           output, outputLen, maxLen, input, inputLen);
    703 }
    704 
    705 static SECStatus
    706 sftk_RSADecryptOAEP(void *ctx, unsigned char *output,
    707                    unsigned int *outputLen, unsigned int maxLen,
    708                    const unsigned char *input, unsigned int inputLen)
    709 {
    710    SFTKOAEPInfo *info = ctx;
    711    SECStatus rv = SECFailure;
    712    HASH_HashType hashAlg;
    713    HASH_HashType maskHashAlg;
    714 
    715    PORT_Assert(info->key.priv->keyType == NSSLOWKEYRSAKey);
    716    if (info->key.priv->keyType != NSSLOWKEYRSAKey) {
    717        PORT_SetError(SEC_ERROR_INVALID_KEY);
    718        return SECFailure;
    719    }
    720 
    721    hashAlg = sftk_GetHashTypeFromMechanism(info->params.hashAlg);
    722    maskHashAlg = sftk_GetHashTypeFromMechanism(info->params.mgf);
    723 
    724    rv = RSA_DecryptOAEP(&info->key.priv->u.rsa, hashAlg, maskHashAlg,
    725                         (const unsigned char *)info->params.pSourceData,
    726                         info->params.ulSourceDataLen,
    727                         output, outputLen, maxLen, input, inputLen);
    728    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
    729        sftk_fatalError = PR_TRUE;
    730    }
    731    return rv;
    732 }
    733 
    734 static SFTKChaCha20Poly1305Info *
    735 sftk_ChaCha20Poly1305_CreateContext(const unsigned char *key,
    736                                    unsigned int keyLen,
    737                                    const CK_NSS_AEAD_PARAMS *params)
    738 {
    739    SFTKChaCha20Poly1305Info *ctx;
    740 
    741    if (params->ulNonceLen != sizeof(ctx->nonce)) {
    742        PORT_SetError(SEC_ERROR_INPUT_LEN);
    743        return NULL;
    744    }
    745 
    746    ctx = PORT_New(SFTKChaCha20Poly1305Info);
    747    if (ctx == NULL) {
    748        return NULL;
    749    }
    750 
    751    if (ChaCha20Poly1305_InitContext(&ctx->freeblCtx, key, keyLen,
    752                                     params->ulTagLen) != SECSuccess) {
    753        PORT_Free(ctx);
    754        return NULL;
    755    }
    756 
    757    PORT_Memcpy(ctx->nonce, params->pNonce, sizeof(ctx->nonce));
    758 
    759    /* AAD data and length must both be null, or both non-null. */
    760    PORT_Assert((params->pAAD == NULL) == (params->ulAADLen == 0));
    761 
    762    if (params->ulAADLen > sizeof(ctx->ad)) {
    763        /* Need to allocate an overflow buffer for the additional data. */
    764        ctx->adOverflow = (unsigned char *)PORT_Alloc(params->ulAADLen);
    765        if (!ctx->adOverflow) {
    766            PORT_Free(ctx);
    767            return NULL;
    768        }
    769        PORT_Memcpy(ctx->adOverflow, params->pAAD, params->ulAADLen);
    770    } else {
    771        ctx->adOverflow = NULL;
    772        if (params->pAAD) {
    773            PORT_Memcpy(ctx->ad, params->pAAD, params->ulAADLen);
    774        }
    775    }
    776    ctx->adLen = params->ulAADLen;
    777 
    778    return ctx;
    779 }
    780 
    781 static void
    782 sftk_ChaCha20Poly1305_DestroyContext(void *vctx,
    783                                     PRBool freeit)
    784 {
    785    SFTKChaCha20Poly1305Info *ctx = vctx;
    786    ChaCha20Poly1305_DestroyContext(&ctx->freeblCtx, PR_FALSE);
    787    if (ctx->adOverflow != NULL) {
    788        PORT_ZFree(ctx->adOverflow, ctx->adLen);
    789        ctx->adOverflow = NULL;
    790    } else {
    791        PORT_Memset(ctx->ad, 0, ctx->adLen);
    792    }
    793    ctx->adLen = 0;
    794    if (freeit) {
    795        PORT_Free(ctx);
    796    }
    797 }
    798 
    799 static SECStatus
    800 sftk_ChaCha20Poly1305_Encrypt(void *vctx,
    801                              unsigned char *output, unsigned int *outputLen,
    802                              unsigned int maxOutputLen,
    803                              const unsigned char *input, unsigned int inputLen)
    804 {
    805    const SFTKChaCha20Poly1305Info *ctx = vctx;
    806    const unsigned char *ad = ctx->adOverflow;
    807 
    808    if (ad == NULL) {
    809        ad = ctx->ad;
    810    }
    811 
    812    return ChaCha20Poly1305_Seal(&ctx->freeblCtx, output, outputLen,
    813                                 maxOutputLen, input, inputLen, ctx->nonce,
    814                                 sizeof(ctx->nonce), ad, ctx->adLen);
    815 }
    816 
    817 static SECStatus
    818 sftk_ChaCha20Poly1305_Decrypt(void *vctx,
    819                              unsigned char *output, unsigned int *outputLen,
    820                              unsigned int maxOutputLen,
    821                              const unsigned char *input, unsigned int inputLen)
    822 {
    823    const SFTKChaCha20Poly1305Info *ctx = vctx;
    824    const unsigned char *ad = ctx->adOverflow;
    825 
    826    if (ad == NULL) {
    827        ad = ctx->ad;
    828    }
    829 
    830    return ChaCha20Poly1305_Open(&ctx->freeblCtx, output, outputLen,
    831                                 maxOutputLen, input, inputLen, ctx->nonce,
    832                                 sizeof(ctx->nonce), ad, ctx->adLen);
    833 }
    834 
    835 static SECStatus
    836 sftk_ChaCha20Ctr(void *vctx,
    837                 unsigned char *output, unsigned int *outputLen,
    838                 unsigned int maxOutputLen,
    839                 const unsigned char *input, unsigned int inputLen)
    840 {
    841    if (maxOutputLen < inputLen) {
    842        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
    843        return SECFailure;
    844    }
    845    SFTKChaCha20CtrInfo *ctx = vctx;
    846    ChaCha20_Xor(output, input, inputLen, ctx->key,
    847                 ctx->nonce, ctx->counter);
    848    *outputLen = inputLen;
    849    return SECSuccess;
    850 }
    851 
    852 static void
    853 sftk_ChaCha20Ctr_DestroyContext(void *vctx,
    854                                PRBool freeit)
    855 {
    856    SFTKChaCha20CtrInfo *ctx = vctx;
    857    memset(ctx, 0, sizeof(SFTKChaCha20CtrInfo));
    858    if (freeit) {
    859        PORT_Free(ctx);
    860    }
    861 }
    862 
    863 /** NSC_CryptInit initializes an encryption/Decryption operation.
    864 *
    865 * Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey.
    866 * Called by NSC_SignInit, NSC_VerifyInit (via sftk_InitCBCMac) only for block
    867 *  ciphers MAC'ing.
    868 */
    869 CK_RV
    870 sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
    871               CK_OBJECT_HANDLE hKey,
    872               CK_ATTRIBUTE_TYPE mechUsage, CK_ATTRIBUTE_TYPE keyUsage,
    873               SFTKContextType contextType, PRBool isEncrypt)
    874 {
    875    SFTKSession *session;
    876    SFTKObject *key;
    877    SFTKSessionContext *context;
    878    SFTKAttribute *att;
    879 #ifndef NSS_DISABLE_DEPRECATED_RC2
    880    CK_RC2_CBC_PARAMS *rc2_param;
    881    unsigned effectiveKeyLength;
    882 #endif
    883 #if NSS_SOFTOKEN_DOES_RC5
    884    CK_RC5_CBC_PARAMS *rc5_param;
    885    SECItem rc5Key;
    886 #endif
    887    CK_NSS_GCM_PARAMS nss_gcm_param;
    888    void *aes_param;
    889    CK_NSS_AEAD_PARAMS nss_aead_params;
    890    CK_NSS_AEAD_PARAMS *nss_aead_params_ptr = NULL;
    891    CK_KEY_TYPE key_type;
    892    CK_RV crv = CKR_OK;
    893    unsigned char newdeskey[24];
    894    PRBool useNewKey = PR_FALSE;
    895    int t;
    896 
    897    if (!pMechanism) {
    898        return CKR_MECHANISM_PARAM_INVALID;
    899    }
    900 
    901    crv = sftk_MechAllowsOperation(pMechanism->mechanism, mechUsage);
    902    if (crv != CKR_OK)
    903        return crv;
    904 
    905    session = sftk_SessionFromHandle(hSession);
    906    if (session == NULL)
    907        return CKR_SESSION_HANDLE_INVALID;
    908 
    909    crv = sftk_InitGeneric(session, pMechanism, &context, contextType, &key,
    910                           hKey, &key_type,
    911                           isEncrypt ? CKO_PUBLIC_KEY : CKO_PRIVATE_KEY,
    912                           keyUsage);
    913 
    914    if (crv != CKR_OK) {
    915        sftk_FreeSession(session);
    916        return crv;
    917    }
    918 
    919    context->doPad = PR_FALSE;
    920    switch (pMechanism->mechanism) {
    921        case CKM_RSA_PKCS:
    922        case CKM_RSA_X_509:
    923            if (key_type != CKK_RSA) {
    924                crv = CKR_KEY_TYPE_INCONSISTENT;
    925                break;
    926            }
    927            context->multi = PR_FALSE;
    928            context->rsa = PR_TRUE;
    929            if (isEncrypt) {
    930                NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key, CKK_RSA, &crv);
    931                if (pubKey == NULL) {
    932                    crv = CKR_KEY_HANDLE_INVALID;
    933                    break;
    934                }
    935                context->maxLen = nsslowkey_PublicModulusLen(pubKey);
    936                context->cipherInfo = (void *)pubKey;
    937                context->update = pMechanism->mechanism == CKM_RSA_X_509
    938                                      ? sftk_RSAEncryptRaw
    939                                      : sftk_RSAEncrypt;
    940            } else {
    941                NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key, CKK_RSA, &crv);
    942                if (privKey == NULL) {
    943                    crv = CKR_KEY_HANDLE_INVALID;
    944                    break;
    945                }
    946                context->maxLen = nsslowkey_PrivateModulusLen(privKey);
    947                context->cipherInfo = (void *)privKey;
    948                context->update = pMechanism->mechanism == CKM_RSA_X_509
    949                                      ? sftk_RSADecryptRaw
    950                                      : sftk_RSADecrypt;
    951            }
    952            context->destroy = sftk_Null;
    953            break;
    954        case CKM_RSA_PKCS_OAEP:
    955            if (key_type != CKK_RSA) {
    956                crv = CKR_KEY_TYPE_INCONSISTENT;
    957                break;
    958            }
    959            if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS) ||
    960                !sftk_ValidateOaepParams((CK_RSA_PKCS_OAEP_PARAMS *)pMechanism->pParameter)) {
    961                crv = CKR_MECHANISM_PARAM_INVALID;
    962                break;
    963            }
    964            context->multi = PR_FALSE;
    965            context->rsa = PR_TRUE;
    966            {
    967                SFTKOAEPInfo *info;
    968                CK_RSA_PKCS_OAEP_PARAMS *params =
    969                    (CK_RSA_PKCS_OAEP_PARAMS *)pMechanism->pParameter;
    970                /* make a copy of the source data value for future
    971                 * use (once the user has reclaimed his data in pParameter)*/
    972                void *newSource = NULL;
    973                if (params->pSourceData) {
    974                    newSource = PORT_Alloc(params->ulSourceDataLen);
    975                    if (newSource == NULL) {
    976                        crv = CKR_HOST_MEMORY;
    977                        break;
    978                    }
    979                    PORT_Memcpy(newSource, params->pSourceData, params->ulSourceDataLen);
    980                }
    981                info = PORT_New(SFTKOAEPInfo);
    982                if (info == NULL) {
    983                    PORT_ZFree(newSource, params->ulSourceDataLen);
    984                    crv = CKR_HOST_MEMORY;
    985                    break;
    986                }
    987                info->params = *params;
    988                info->params.pSourceData = newSource;
    989                info->isEncrypt = isEncrypt;
    990 
    991                /* now setup encryption and decryption contexts */
    992                if (isEncrypt) {
    993                    info->key.pub = sftk_GetPubKey(key, CKK_RSA, &crv);
    994                    if (info->key.pub == NULL) {
    995                        sftk_freeRSAOAEPInfo(info, PR_TRUE);
    996                        crv = CKR_KEY_HANDLE_INVALID;
    997                        break;
    998                    }
    999                    context->update = sftk_RSAEncryptOAEP;
   1000                    context->maxLen = nsslowkey_PublicModulusLen(info->key.pub);
   1001                } else {
   1002                    info->key.priv = sftk_GetPrivKey(key, CKK_RSA, &crv);
   1003                    if (info->key.priv == NULL) {
   1004                        sftk_freeRSAOAEPInfo(info, PR_TRUE);
   1005                        crv = CKR_KEY_HANDLE_INVALID;
   1006                        break;
   1007                    }
   1008                    context->update = sftk_RSADecryptOAEP;
   1009                    context->maxLen = nsslowkey_PrivateModulusLen(info->key.priv);
   1010                }
   1011                context->cipherInfo = info;
   1012            }
   1013            context->destroy = sftk_freeRSAOAEPInfo;
   1014            break;
   1015 #ifndef NSS_DISABLE_DEPRECATED_RC2
   1016        case CKM_RC2_CBC_PAD:
   1017            context->doPad = PR_TRUE;
   1018        /* fall thru */
   1019        case CKM_RC2_ECB:
   1020        case CKM_RC2_CBC:
   1021            context->blockSize = 8;
   1022            if (key_type != CKK_RC2) {
   1023                crv = CKR_KEY_TYPE_INCONSISTENT;
   1024                break;
   1025            }
   1026            att = sftk_FindAttribute(key, CKA_VALUE);
   1027            if (att == NULL) {
   1028                crv = CKR_KEY_HANDLE_INVALID;
   1029                break;
   1030            }
   1031 
   1032            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_CBC_PARAMS))) {
   1033                crv = CKR_MECHANISM_PARAM_INVALID;
   1034                break;
   1035            }
   1036            rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter;
   1037            effectiveKeyLength = (rc2_param->ulEffectiveBits + 7) / 8;
   1038            context->cipherInfo =
   1039                RC2_CreateContext((unsigned char *)att->attrib.pValue,
   1040                                  att->attrib.ulValueLen, rc2_param->iv,
   1041                                  pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 : NSS_RC2_CBC, effectiveKeyLength);
   1042            sftk_FreeAttribute(att);
   1043            if (context->cipherInfo == NULL) {
   1044                crv = CKR_HOST_MEMORY;
   1045                break;
   1046            }
   1047            context->update = isEncrypt ? SFTKCipher_RC2_Encrypt : SFTKCipher_RC2_Decrypt;
   1048            context->destroy = SFTKCipher_RC2_DestroyContext;
   1049            break;
   1050 #endif /* NSS_DISABLE_DEPRECATED_RC2 */
   1051 
   1052 #if NSS_SOFTOKEN_DOES_RC5
   1053        case CKM_RC5_CBC_PAD:
   1054            context->doPad = PR_TRUE;
   1055        /* fall thru */
   1056        case CKM_RC5_ECB:
   1057        case CKM_RC5_CBC:
   1058            if (key_type != CKK_RC5) {
   1059                crv = CKR_KEY_TYPE_INCONSISTENT;
   1060                break;
   1061            }
   1062            att = sftk_FindAttribute(key, CKA_VALUE);
   1063            if (att == NULL) {
   1064                crv = CKR_KEY_HANDLE_INVALID;
   1065                break;
   1066            }
   1067 
   1068            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_CBC_PARAMS))) {
   1069                crv = CKR_MECHANISM_PARAM_INVALID;
   1070                break;
   1071            }
   1072            rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter;
   1073            context->blockSize = rc5_param->ulWordsize * 2;
   1074            rc5Key.data = (unsigned char *)att->attrib.pValue;
   1075            rc5Key.len = att->attrib.ulValueLen;
   1076            context->cipherInfo = RC5_CreateContext(&rc5Key, rc5_param->ulRounds,
   1077                                                    rc5_param->ulWordsize, rc5_param->pIv,
   1078                                                    pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC);
   1079            sftk_FreeAttribute(att);
   1080            if (context->cipherInfo == NULL) {
   1081                crv = CKR_HOST_MEMORY;
   1082                break;
   1083            }
   1084            context->update = isEncrypt ? SFTKCipher_RC5_Encrypt : SFTKCipher_RC5_Decrypt;
   1085            context->destroy = SFTKCipher_RC5_DestroyContext;
   1086            break;
   1087 #endif
   1088        case CKM_RC4:
   1089            if (key_type != CKK_RC4) {
   1090                crv = CKR_KEY_TYPE_INCONSISTENT;
   1091                break;
   1092            }
   1093            att = sftk_FindAttribute(key, CKA_VALUE);
   1094            if (att == NULL) {
   1095                crv = CKR_KEY_HANDLE_INVALID;
   1096                break;
   1097            }
   1098            context->cipherInfo =
   1099                RC4_CreateContext((unsigned char *)att->attrib.pValue,
   1100                                  att->attrib.ulValueLen);
   1101            sftk_FreeAttribute(att);
   1102            if (context->cipherInfo == NULL) {
   1103                crv = CKR_HOST_MEMORY; /* WRONG !!! */
   1104                break;
   1105            }
   1106            context->update = isEncrypt ? SFTKCipher_RC4_Encrypt : SFTKCipher_RC4_Decrypt;
   1107            context->destroy = SFTKCipher_RC4_DestroyContext;
   1108            break;
   1109        case CKM_CDMF_CBC_PAD:
   1110            context->doPad = PR_TRUE;
   1111        /* fall thru */
   1112        case CKM_CDMF_ECB:
   1113        case CKM_CDMF_CBC:
   1114            if (key_type != CKK_CDMF) {
   1115                crv = CKR_KEY_TYPE_INCONSISTENT;
   1116                break;
   1117            }
   1118            t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC;
   1119            goto finish_des;
   1120        case CKM_DES_ECB:
   1121            if (key_type != CKK_DES) {
   1122                crv = CKR_KEY_TYPE_INCONSISTENT;
   1123                break;
   1124            }
   1125            t = NSS_DES;
   1126            goto finish_des;
   1127        case CKM_DES_CBC_PAD:
   1128            context->doPad = PR_TRUE;
   1129        /* fall thru */
   1130        case CKM_DES_CBC:
   1131            if (key_type != CKK_DES) {
   1132                crv = CKR_KEY_TYPE_INCONSISTENT;
   1133                break;
   1134            }
   1135            t = NSS_DES_CBC;
   1136            goto finish_des;
   1137        case CKM_DES3_ECB:
   1138            if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
   1139                crv = CKR_KEY_TYPE_INCONSISTENT;
   1140                break;
   1141            }
   1142            t = NSS_DES_EDE3;
   1143            goto finish_des;
   1144        case CKM_DES3_CBC_PAD:
   1145            context->doPad = PR_TRUE;
   1146        /* fall thru */
   1147        case CKM_DES3_CBC:
   1148            if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
   1149                crv = CKR_KEY_TYPE_INCONSISTENT;
   1150                break;
   1151            }
   1152            t = NSS_DES_EDE3_CBC;
   1153        finish_des:
   1154            if ((t != NSS_DES && t != NSS_DES_EDE3) && (pMechanism->pParameter == NULL ||
   1155                                                        pMechanism->ulParameterLen < 8)) {
   1156                crv = CKR_DOMAIN_PARAMS_INVALID;
   1157                break;
   1158            }
   1159            context->blockSize = 8;
   1160            att = sftk_FindAttribute(key, CKA_VALUE);
   1161            if (att == NULL) {
   1162                crv = CKR_KEY_HANDLE_INVALID;
   1163                break;
   1164            }
   1165            if (key_type == CKK_DES2 &&
   1166                (t == NSS_DES_EDE3_CBC || t == NSS_DES_EDE3)) {
   1167                /* extend DES2 key to DES3 key. */
   1168                memcpy(newdeskey, att->attrib.pValue, 16);
   1169                memcpy(newdeskey + 16, newdeskey, 8);
   1170                useNewKey = PR_TRUE;
   1171            } else if (key_type == CKK_CDMF) {
   1172                crv = sftk_cdmf2des((unsigned char *)att->attrib.pValue, newdeskey);
   1173                if (crv != CKR_OK) {
   1174                    sftk_FreeAttribute(att);
   1175                    break;
   1176                }
   1177                useNewKey = PR_TRUE;
   1178            }
   1179            context->cipherInfo = DES_CreateContext(
   1180                useNewKey ? newdeskey : (unsigned char *)att->attrib.pValue,
   1181                (unsigned char *)pMechanism->pParameter, t, isEncrypt);
   1182            if (useNewKey)
   1183                memset(newdeskey, 0, sizeof newdeskey);
   1184            sftk_FreeAttribute(att);
   1185            if (context->cipherInfo == NULL) {
   1186                crv = CKR_HOST_MEMORY;
   1187                break;
   1188            }
   1189            context->update = isEncrypt ? SFTKCipher_DES_Encrypt : SFTKCipher_DES_Decrypt;
   1190            context->destroy = SFTKCipher_DES_DestroyContext;
   1191            break;
   1192 #ifndef NSS_DISABLE_DEPRECATED_SEED
   1193        case CKM_SEED_CBC_PAD:
   1194            context->doPad = PR_TRUE;
   1195        /* fall thru */
   1196        case CKM_SEED_CBC:
   1197            if (!pMechanism->pParameter ||
   1198                pMechanism->ulParameterLen != 16) {
   1199                crv = CKR_MECHANISM_PARAM_INVALID;
   1200                break;
   1201            }
   1202        /* fall thru */
   1203        case CKM_SEED_ECB:
   1204            context->blockSize = 16;
   1205            if (key_type != CKK_SEED) {
   1206                crv = CKR_KEY_TYPE_INCONSISTENT;
   1207                break;
   1208            }
   1209            att = sftk_FindAttribute(key, CKA_VALUE);
   1210            if (att == NULL) {
   1211                crv = CKR_KEY_HANDLE_INVALID;
   1212                break;
   1213            }
   1214            context->cipherInfo = SEED_CreateContext(
   1215                (unsigned char *)att->attrib.pValue,
   1216                (unsigned char *)pMechanism->pParameter,
   1217                pMechanism->mechanism == CKM_SEED_ECB ? NSS_SEED : NSS_SEED_CBC,
   1218                isEncrypt);
   1219            sftk_FreeAttribute(att);
   1220            if (context->cipherInfo == NULL) {
   1221                crv = CKR_HOST_MEMORY;
   1222                break;
   1223            }
   1224            context->update = isEncrypt ? SFTKCipher_SEED_Encrypt : SFTKCipher_SEED_Decrypt;
   1225            context->destroy = SFTKCipher_SEED_DestroyContext;
   1226            break;
   1227 #endif /* NSS_DISABLE_DEPRECATED_SEED */
   1228        case CKM_CAMELLIA_CBC_PAD:
   1229            context->doPad = PR_TRUE;
   1230        /* fall thru */
   1231        case CKM_CAMELLIA_CBC:
   1232            if (!pMechanism->pParameter ||
   1233                pMechanism->ulParameterLen != 16) {
   1234                crv = CKR_MECHANISM_PARAM_INVALID;
   1235                break;
   1236            }
   1237        /* fall thru */
   1238        case CKM_CAMELLIA_ECB:
   1239            context->blockSize = 16;
   1240            if (key_type != CKK_CAMELLIA) {
   1241                crv = CKR_KEY_TYPE_INCONSISTENT;
   1242                break;
   1243            }
   1244            att = sftk_FindAttribute(key, CKA_VALUE);
   1245            if (att == NULL) {
   1246                crv = CKR_KEY_HANDLE_INVALID;
   1247                break;
   1248            }
   1249            context->cipherInfo = Camellia_CreateContext(
   1250                (unsigned char *)att->attrib.pValue,
   1251                (unsigned char *)pMechanism->pParameter,
   1252                pMechanism->mechanism ==
   1253                        CKM_CAMELLIA_ECB
   1254                    ? NSS_CAMELLIA
   1255                    : NSS_CAMELLIA_CBC,
   1256                isEncrypt, att->attrib.ulValueLen);
   1257            sftk_FreeAttribute(att);
   1258            if (context->cipherInfo == NULL) {
   1259                crv = CKR_HOST_MEMORY;
   1260                break;
   1261            }
   1262            context->update = isEncrypt ? SFTKCipher_Camellia_Encrypt : SFTKCipher_Camellia_Decrypt;
   1263            context->destroy = SFTKCipher_Camellia_DestroyContext;
   1264            break;
   1265 
   1266        case CKM_AES_CBC_PAD:
   1267            context->doPad = PR_TRUE;
   1268        /* fall thru */
   1269        case CKM_AES_ECB:
   1270        case CKM_AES_CBC:
   1271            context->blockSize = 16;
   1272        case CKM_AES_CTS:
   1273        case CKM_AES_CTR:
   1274        case CKM_AES_GCM:
   1275            aes_param = pMechanism->pParameter;
   1276            /*
   1277             *  Due to a mismatch between the documentation and the header
   1278             *  file, two different definitions for CK_GCM_PARAMS exist.
   1279             *  The header file is normative according to Oasis, but NSS used
   1280             *  the documentation. In PKCS #11 v3.0, this was reconciled in
   1281             *  favor of the header file definition. To maintain binary
   1282             *  compatibility, NSS now defines CK_GCM_PARAMS_V3 as the official
   1283             *  version v3 (V2.4 header file) and CK_NSS_GCM_PARAMS as the
   1284             *  legacy (V2.4 documentation, NSS version). CK_GCM_PARAMS
   1285             *  is defined as CK_GCM_PARAMS_V3 if NSS_PKCS11_2_0_COMPAT is not
   1286             *  defined and CK_NSS_GCM_PARAMS if it is. Internally
   1287             *  softoken continues to use the legacy version. The code below
   1288             *  automatically detects which parameter was passed in and
   1289             *  converts CK_GCM_PARAMS_V3 to the CK_NSS_GCM_PARAMS (legacy
   1290             *  version) on the fly. NSS proper will eventually start
   1291             *  using the CK_GCM_PARAMS_V3 version and fall back to the
   1292             *  CK_NSS_GCM_PARAMS if the CK_GCM_PARAMS_V3 version fails with
   1293             *  CKR_MECHANISM_PARAM_INVALID.
   1294             */
   1295            if (pMechanism->mechanism == CKM_AES_GCM) {
   1296                if (!aes_param) {
   1297                    crv = CKR_MECHANISM_PARAM_INVALID;
   1298                    break;
   1299                }
   1300                if (pMechanism->ulParameterLen == sizeof(CK_GCM_PARAMS_V3)) {
   1301                    /* convert the true V3 parameters into the old NSS parameters */
   1302                    CK_GCM_PARAMS_V3 *gcm_params = (CK_GCM_PARAMS_V3 *)aes_param;
   1303                    if (gcm_params->ulIvLen * 8 != gcm_params->ulIvBits) {
   1304                        /* only support byte aligned IV lengths */
   1305                        crv = CKR_MECHANISM_PARAM_INVALID;
   1306                        break;
   1307                    }
   1308                    aes_param = (void *)&nss_gcm_param;
   1309                    nss_gcm_param.pIv = gcm_params->pIv;
   1310                    nss_gcm_param.ulIvLen = gcm_params->ulIvLen;
   1311                    nss_gcm_param.pAAD = gcm_params->pAAD;
   1312                    nss_gcm_param.ulAADLen = gcm_params->ulAADLen;
   1313                    nss_gcm_param.ulTagBits = gcm_params->ulTagBits;
   1314                } else if (pMechanism->ulParameterLen != sizeof(CK_NSS_GCM_PARAMS)) {
   1315                    /* neither old nor new style params, must be invalid */
   1316                    crv = CKR_MECHANISM_PARAM_INVALID;
   1317                    break;
   1318                }
   1319            } else if ((pMechanism->mechanism == CKM_AES_CTR && BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CTR_PARAMS))) ||
   1320                       ((pMechanism->mechanism == CKM_AES_CBC || pMechanism->mechanism == CKM_AES_CTS) && BAD_PARAM_CAST(pMechanism, AES_BLOCK_SIZE))) {
   1321                crv = CKR_MECHANISM_PARAM_INVALID;
   1322                break;
   1323            }
   1324 
   1325            if (pMechanism->mechanism == CKM_AES_GCM) {
   1326                context->multi = PR_FALSE;
   1327            }
   1328            if (key_type != CKK_AES) {
   1329                crv = CKR_KEY_TYPE_INCONSISTENT;
   1330                break;
   1331            }
   1332            att = sftk_FindAttribute(key, CKA_VALUE);
   1333            if (att == NULL) {
   1334                crv = CKR_KEY_HANDLE_INVALID;
   1335                break;
   1336            }
   1337            context->cipherInfo = AES_CreateContext(
   1338                (unsigned char *)att->attrib.pValue,
   1339                (unsigned char *)aes_param,
   1340                sftk_aes_mode(pMechanism->mechanism),
   1341                isEncrypt, att->attrib.ulValueLen, 16);
   1342            sftk_FreeAttribute(att);
   1343            if (context->cipherInfo == NULL) {
   1344                crv = CKR_HOST_MEMORY;
   1345                break;
   1346            }
   1347            context->update = isEncrypt ? SFTKCipher_AES_Encrypt : SFTKCipher_AES_Decrypt;
   1348            context->destroy = SFTKCipher_AES_DestroyContext;
   1349            break;
   1350 
   1351        case CKM_NSS_CHACHA20_POLY1305:
   1352        case CKM_CHACHA20_POLY1305:
   1353            if (pMechanism->mechanism == CKM_NSS_CHACHA20_POLY1305) {
   1354                if (key_type != CKK_NSS_CHACHA20) {
   1355                    crv = CKR_KEY_TYPE_INCONSISTENT;
   1356                    break;
   1357                }
   1358                if ((pMechanism->pParameter == NULL) ||
   1359                    (pMechanism->ulParameterLen != sizeof(CK_NSS_AEAD_PARAMS))) {
   1360                    crv = CKR_MECHANISM_PARAM_INVALID;
   1361                    break;
   1362                }
   1363                nss_aead_params_ptr = (CK_NSS_AEAD_PARAMS *)pMechanism->pParameter;
   1364            } else {
   1365                CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR chacha_poly_params;
   1366                if (key_type != CKK_CHACHA20) {
   1367                    crv = CKR_KEY_TYPE_INCONSISTENT;
   1368                    break;
   1369                }
   1370                if ((pMechanism->pParameter == NULL) ||
   1371                    (pMechanism->ulParameterLen !=
   1372                     sizeof(CK_SALSA20_CHACHA20_POLY1305_PARAMS))) {
   1373                    crv = CKR_MECHANISM_PARAM_INVALID;
   1374                    break;
   1375                }
   1376                chacha_poly_params = (CK_SALSA20_CHACHA20_POLY1305_PARAMS_PTR)
   1377                                         pMechanism->pParameter;
   1378                nss_aead_params_ptr = &nss_aead_params;
   1379                nss_aead_params.pNonce = chacha_poly_params->pNonce;
   1380                nss_aead_params.ulNonceLen = chacha_poly_params->ulNonceLen;
   1381                nss_aead_params.pAAD = chacha_poly_params->pAAD;
   1382                nss_aead_params.ulAADLen = chacha_poly_params->ulAADLen;
   1383                nss_aead_params.ulTagLen = 16; /* Poly1305 is always 16 */
   1384            }
   1385 
   1386            context->multi = PR_FALSE;
   1387            att = sftk_FindAttribute(key, CKA_VALUE);
   1388            if (att == NULL) {
   1389                crv = CKR_KEY_HANDLE_INVALID;
   1390                break;
   1391            }
   1392            context->cipherInfo = sftk_ChaCha20Poly1305_CreateContext(
   1393                (unsigned char *)att->attrib.pValue, att->attrib.ulValueLen,
   1394                nss_aead_params_ptr);
   1395            sftk_FreeAttribute(att);
   1396            if (context->cipherInfo == NULL) {
   1397                crv = sftk_MapCryptError(PORT_GetError());
   1398                break;
   1399            }
   1400            context->update = isEncrypt ? sftk_ChaCha20Poly1305_Encrypt : sftk_ChaCha20Poly1305_Decrypt;
   1401            context->destroy = sftk_ChaCha20Poly1305_DestroyContext;
   1402            break;
   1403 
   1404        case CKM_NSS_CHACHA20_CTR: /* old NSS private version */
   1405        case CKM_CHACHA20:         /* PKCS #11 v3 version */
   1406        {
   1407            unsigned char *counter;
   1408            unsigned char *nonce;
   1409            unsigned long counter_len;
   1410            unsigned long nonce_len;
   1411            context->multi = PR_FALSE;
   1412            if (pMechanism->mechanism == CKM_NSS_CHACHA20_CTR) {
   1413                if (key_type != CKK_NSS_CHACHA20) {
   1414                    crv = CKR_KEY_TYPE_INCONSISTENT;
   1415                    break;
   1416                }
   1417                if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != 16) {
   1418                    crv = CKR_MECHANISM_PARAM_INVALID;
   1419                    break;
   1420                }
   1421                counter_len = 4;
   1422                counter = pMechanism->pParameter;
   1423                nonce = counter + 4;
   1424                nonce_len = 12;
   1425            } else {
   1426                CK_CHACHA20_PARAMS_PTR chacha20_param_ptr;
   1427                if (key_type != CKK_CHACHA20) {
   1428                    crv = CKR_KEY_TYPE_INCONSISTENT;
   1429                    break;
   1430                }
   1431                if (pMechanism->pParameter == NULL || pMechanism->ulParameterLen != sizeof(CK_CHACHA20_PARAMS)) {
   1432                    crv = CKR_MECHANISM_PARAM_INVALID;
   1433                    break;
   1434                }
   1435                chacha20_param_ptr = (CK_CHACHA20_PARAMS_PTR)pMechanism->pParameter;
   1436                if ((chacha20_param_ptr->blockCounterBits != 32) &&
   1437                    (chacha20_param_ptr->blockCounterBits != 64)) {
   1438                    crv = CKR_MECHANISM_PARAM_INVALID;
   1439                    break;
   1440                }
   1441                counter_len = chacha20_param_ptr->blockCounterBits / PR_BITS_PER_BYTE;
   1442                counter = chacha20_param_ptr->pBlockCounter;
   1443                nonce = chacha20_param_ptr->pNonce;
   1444                nonce_len = chacha20_param_ptr->ulNonceBits / PR_BITS_PER_BYTE;
   1445            }
   1446 
   1447            att = sftk_FindAttribute(key, CKA_VALUE);
   1448            if (att == NULL) {
   1449                crv = CKR_KEY_HANDLE_INVALID;
   1450                break;
   1451            }
   1452            SFTKChaCha20CtrInfo *ctx = PORT_ZNew(SFTKChaCha20CtrInfo);
   1453            if (!ctx) {
   1454                sftk_FreeAttribute(att);
   1455                crv = CKR_HOST_MEMORY;
   1456                break;
   1457            }
   1458            if (att->attrib.ulValueLen != sizeof(ctx->key)) {
   1459                sftk_FreeAttribute(att);
   1460                PORT_Free(ctx);
   1461                crv = CKR_KEY_HANDLE_INVALID;
   1462                break;
   1463            }
   1464            memcpy(ctx->key, att->attrib.pValue, att->attrib.ulValueLen);
   1465            sftk_FreeAttribute(att);
   1466 
   1467            /* make sure we don't overflow our parameters */
   1468            if ((sizeof(ctx->counter) < counter_len) ||
   1469                (sizeof(ctx->nonce) < nonce_len)) {
   1470                PORT_Free(ctx);
   1471                crv = CKR_MECHANISM_PARAM_INVALID;
   1472                break;
   1473            }
   1474 
   1475            /* The counter is little endian. */
   1476            int i = 0;
   1477            for (; i < counter_len; ++i) {
   1478                ctx->counter |= (PRUint32)counter[i] << (i * 8);
   1479            }
   1480            memcpy(ctx->nonce, nonce, nonce_len);
   1481            context->cipherInfo = ctx;
   1482            context->update = sftk_ChaCha20Ctr;
   1483            context->destroy = sftk_ChaCha20Ctr_DestroyContext;
   1484            break;
   1485        }
   1486 
   1487        case CKM_NSS_AES_KEY_WRAP_PAD:
   1488        case CKM_AES_KEY_WRAP_PAD:
   1489            context->doPad = PR_TRUE;
   1490        /* fall thru */
   1491        case CKM_NSS_AES_KEY_WRAP:
   1492        case CKM_AES_KEY_WRAP:
   1493            context->blockSize = 8;
   1494        case CKM_AES_KEY_WRAP_KWP:
   1495            context->multi = PR_FALSE;
   1496            if (key_type != CKK_AES) {
   1497                crv = CKR_KEY_TYPE_INCONSISTENT;
   1498                break;
   1499            }
   1500            att = sftk_FindAttribute(key, CKA_VALUE);
   1501            if (att == NULL) {
   1502                crv = CKR_KEY_HANDLE_INVALID;
   1503                break;
   1504            }
   1505            context->cipherInfo = AESKeyWrap_CreateContext(
   1506                (unsigned char *)att->attrib.pValue,
   1507                (unsigned char *)pMechanism->pParameter,
   1508                isEncrypt, att->attrib.ulValueLen);
   1509            sftk_FreeAttribute(att);
   1510            if (context->cipherInfo == NULL) {
   1511                crv = CKR_HOST_MEMORY;
   1512                break;
   1513            }
   1514            if (pMechanism->mechanism == CKM_AES_KEY_WRAP_KWP) {
   1515                context->update = isEncrypt ? SFTKCipher_AESKeyWrap_EncryptKWP
   1516                                            : SFTKCipher_AESKeyWrap_DecryptKWP;
   1517            } else {
   1518                context->update = isEncrypt ? SFTKCipher_AESKeyWrap_Encrypt
   1519                                            : SFTKCipher_AESKeyWrap_Decrypt;
   1520            }
   1521            context->destroy = SFTKCipher_AESKeyWrap_DestroyContext;
   1522            break;
   1523 
   1524        default:
   1525            crv = CKR_MECHANISM_INVALID;
   1526            break;
   1527    }
   1528 
   1529    if (crv != CKR_OK) {
   1530        sftk_FreeContext(context);
   1531        sftk_FreeSession(session);
   1532        return crv;
   1533    }
   1534    sftk_SetContextByType(session, contextType, context);
   1535    sftk_FreeSession(session);
   1536    return CKR_OK;
   1537 }
   1538 
   1539 /* NSC_EncryptInit initializes an encryption operation. */
   1540 CK_RV
   1541 NSC_EncryptInit(CK_SESSION_HANDLE hSession,
   1542                CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
   1543 {
   1544    CHECK_FORK();
   1545    return sftk_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, CKA_ENCRYPT,
   1546                          SFTK_ENCRYPT, PR_TRUE);
   1547 }
   1548 
   1549 /* NSC_EncryptUpdate continues a multiple-part encryption operation. */
   1550 CK_RV
   1551 NSC_EncryptUpdate(CK_SESSION_HANDLE hSession,
   1552                  CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
   1553                  CK_ULONG_PTR pulEncryptedPartLen)
   1554 {
   1555    SFTKSessionContext *context;
   1556    unsigned int outlen, i;
   1557    unsigned int padoutlen = 0;
   1558    unsigned int maxout = *pulEncryptedPartLen;
   1559    CK_RV crv;
   1560    SECStatus rv;
   1561 
   1562    CHECK_FORK();
   1563 
   1564    /* make sure we're legal */
   1565    crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, NULL);
   1566    if (crv != CKR_OK)
   1567        return crv;
   1568 
   1569    if (!pEncryptedPart) {
   1570        if (context->doPad) {
   1571            CK_ULONG totalDataAvailable = ulPartLen + context->padDataLength;
   1572            CK_ULONG blocksToSend = totalDataAvailable / context->blockSize;
   1573 
   1574            *pulEncryptedPartLen = blocksToSend * context->blockSize;
   1575            return CKR_OK;
   1576        }
   1577        *pulEncryptedPartLen = ulPartLen;
   1578        return CKR_OK;
   1579    }
   1580 
   1581    /* do padding */
   1582    if (context->doPad) {
   1583        /* deal with previous buffered data */
   1584        if (context->padDataLength != 0) {
   1585            /* fill in the padded to a full block size */
   1586            for (i = context->padDataLength;
   1587                 (ulPartLen != 0) && i < context->blockSize; i++) {
   1588                context->padBuf[i] = *pPart++;
   1589                ulPartLen--;
   1590                context->padDataLength++;
   1591            }
   1592 
   1593            /* not enough data to encrypt yet? then return */
   1594            if (context->padDataLength != context->blockSize) {
   1595                *pulEncryptedPartLen = 0;
   1596                return CKR_OK;
   1597            }
   1598            /* encrypt the current padded data */
   1599            rv = (*context->update)(context->cipherInfo, pEncryptedPart,
   1600                                    &padoutlen, maxout, context->padBuf,
   1601                                    context->blockSize);
   1602            if (rv != SECSuccess) {
   1603                return sftk_MapCryptError(PORT_GetError());
   1604            }
   1605            pEncryptedPart += padoutlen;
   1606            maxout -= padoutlen;
   1607        }
   1608        /* save the residual */
   1609        context->padDataLength = ulPartLen % context->blockSize;
   1610        if (context->padDataLength) {
   1611            PORT_Memcpy(context->padBuf,
   1612                        &pPart[ulPartLen - context->padDataLength],
   1613                        context->padDataLength);
   1614            ulPartLen -= context->padDataLength;
   1615        }
   1616        /* if we've exhausted our new buffer, we're done */
   1617        if (ulPartLen == 0) {
   1618            *pulEncryptedPartLen = padoutlen;
   1619            return CKR_OK;
   1620        }
   1621    }
   1622 
   1623    /* do it: NOTE: this assumes buf size in is >= buf size out! */
   1624    rv = (*context->update)(context->cipherInfo, pEncryptedPart,
   1625                            &outlen, maxout, pPart, ulPartLen);
   1626    if (rv != SECSuccess) {
   1627        return sftk_MapCryptError(PORT_GetError());
   1628    }
   1629    *pulEncryptedPartLen = (CK_ULONG)(outlen + padoutlen);
   1630    return CKR_OK;
   1631 }
   1632 
   1633 /* NSC_EncryptFinal finishes a multiple-part encryption operation. */
   1634 CK_RV
   1635 NSC_EncryptFinal(CK_SESSION_HANDLE hSession,
   1636                 CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen)
   1637 {
   1638    SFTKSession *session;
   1639    SFTKSessionContext *context;
   1640    unsigned int outlen, i;
   1641    unsigned int maxout = *pulLastEncryptedPartLen;
   1642    CK_RV crv;
   1643    SECStatus rv = SECSuccess;
   1644    PRBool contextFinished = PR_TRUE;
   1645 
   1646    CHECK_FORK();
   1647 
   1648    /* make sure we're legal */
   1649    crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_TRUE, &session);
   1650    if (crv != CKR_OK)
   1651        return crv;
   1652 
   1653    *pulLastEncryptedPartLen = 0;
   1654    if (!pLastEncryptedPart) {
   1655        /* caller is checking the amount of remaining data */
   1656        if (context->blockSize > 0 && context->doPad) {
   1657            *pulLastEncryptedPartLen = context->blockSize;
   1658            contextFinished = PR_FALSE; /* still have padding to go */
   1659        }
   1660        goto finish;
   1661    }
   1662 
   1663    /* do padding */
   1664    if (context->doPad) {
   1665        unsigned char padbyte = (unsigned char)(context->blockSize - context->padDataLength);
   1666        /* fill out rest of pad buffer with pad magic*/
   1667        for (i = context->padDataLength; i < context->blockSize; i++) {
   1668            context->padBuf[i] = padbyte;
   1669        }
   1670        rv = (*context->update)(context->cipherInfo, pLastEncryptedPart,
   1671                                &outlen, maxout, context->padBuf, context->blockSize);
   1672        if (rv == SECSuccess)
   1673            *pulLastEncryptedPartLen = (CK_ULONG)outlen;
   1674    }
   1675 
   1676 finish:
   1677    if (contextFinished)
   1678        sftk_TerminateOp(session, SFTK_ENCRYPT, context);
   1679    sftk_FreeSession(session);
   1680    return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
   1681 }
   1682 
   1683 /* NSC_Encrypt encrypts single-part data. */
   1684 CK_RV
   1685 NSC_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
   1686            CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
   1687            CK_ULONG_PTR pulEncryptedDataLen)
   1688 {
   1689    SFTKSession *session;
   1690    SFTKSessionContext *context;
   1691    unsigned int outlen;
   1692    unsigned int maxoutlen = *pulEncryptedDataLen;
   1693    CK_RV crv;
   1694    CK_RV crv2;
   1695    SECStatus rv = SECSuccess;
   1696    SECItem pText;
   1697 
   1698    pText.type = siBuffer;
   1699    pText.data = pData;
   1700    pText.len = ulDataLen;
   1701 
   1702    CHECK_FORK();
   1703 
   1704    /* make sure we're legal */
   1705    crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_FALSE, &session);
   1706    if (crv != CKR_OK)
   1707        return crv;
   1708 
   1709    if (!pEncryptedData) {
   1710        outlen = context->rsa ? context->maxLen : ulDataLen + 2 * context->blockSize;
   1711        goto done;
   1712    }
   1713 
   1714    if (context->doPad) {
   1715        if (context->multi) {
   1716            CK_ULONG updateLen = maxoutlen;
   1717            CK_ULONG finalLen;
   1718            /* padding is fairly complicated, have the update and final
   1719             * code deal with it */
   1720            sftk_FreeSession(session);
   1721            crv = NSC_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData,
   1722                                    &updateLen);
   1723            if (crv != CKR_OK) {
   1724                updateLen = 0;
   1725            }
   1726            maxoutlen -= updateLen;
   1727            pEncryptedData += updateLen;
   1728            finalLen = maxoutlen;
   1729            crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen);
   1730            if (crv == CKR_OK && crv2 == CKR_OK) {
   1731                *pulEncryptedDataLen = updateLen + finalLen;
   1732            }
   1733            return crv == CKR_OK ? crv2 : crv;
   1734        }
   1735        /* doPad without multi means that padding must be done on the first
   1736        ** and only update.  There will be no final.
   1737        */
   1738        PORT_Assert(context->blockSize > 1);
   1739        if (context->blockSize > 1) {
   1740            CK_ULONG remainder = ulDataLen % context->blockSize;
   1741            CK_ULONG padding = context->blockSize - remainder;
   1742            pText.len += padding;
   1743            pText.data = PORT_ZAlloc(pText.len);
   1744            if (pText.data) {
   1745                memcpy(pText.data, pData, ulDataLen);
   1746                memset(pText.data + ulDataLen, padding, padding);
   1747            } else {
   1748                crv = CKR_HOST_MEMORY;
   1749                goto fail;
   1750            }
   1751        }
   1752    }
   1753 
   1754    /* do it: NOTE: this assumes buf size is big enough. */
   1755    rv = (*context->update)(context->cipherInfo, pEncryptedData,
   1756                            &outlen, maxoutlen, pText.data, pText.len);
   1757    crv = (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
   1758    if (pText.data != pData)
   1759        PORT_ZFree(pText.data, pText.len);
   1760 fail:
   1761    sftk_TerminateOp(session, SFTK_ENCRYPT, context);
   1762 done:
   1763    sftk_FreeSession(session);
   1764    if (crv == CKR_OK) {
   1765        *pulEncryptedDataLen = (CK_ULONG)outlen;
   1766    }
   1767    return crv;
   1768 }
   1769 
   1770 /*
   1771 ************** Crypto Functions:     Decrypt ************************
   1772 */
   1773 
   1774 /* NSC_DecryptInit initializes a decryption operation. */
   1775 CK_RV
   1776 NSC_DecryptInit(CK_SESSION_HANDLE hSession,
   1777                CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
   1778 {
   1779    CHECK_FORK();
   1780    return sftk_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT, CKA_DECRYPT,
   1781                          SFTK_DECRYPT, PR_FALSE);
   1782 }
   1783 
   1784 /* NSC_DecryptUpdate continues a multiple-part decryption operation. */
   1785 CK_RV
   1786 NSC_DecryptUpdate(CK_SESSION_HANDLE hSession,
   1787                  CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
   1788                  CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
   1789 {
   1790    SFTKSessionContext *context;
   1791    unsigned int padoutlen = 0;
   1792    unsigned int outlen;
   1793    unsigned int maxout = *pulPartLen;
   1794    CK_RV crv;
   1795    SECStatus rv;
   1796 
   1797    CHECK_FORK();
   1798 
   1799    /* make sure we're legal */
   1800    crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, NULL);
   1801    if (crv != CKR_OK)
   1802        return crv;
   1803 
   1804    /* this can only happen on an NSS programming error */
   1805    PORT_Assert((context->padDataLength == 0) || context->padDataLength == context->blockSize);
   1806 
   1807    if (context->doPad) {
   1808        /* Check the data length for block ciphers. If we are padding,
   1809         * then we must be using a block cipher. In the non-padding case
   1810         * the error will be returned by the underlying decryption
   1811         * function when we do the actual decrypt. We need to do the
   1812         * check here to avoid returning a negative length to the caller
   1813         * or reading before the beginning of the pEncryptedPart buffer.
   1814         */
   1815        if ((ulEncryptedPartLen == 0) ||
   1816            (ulEncryptedPartLen % context->blockSize) != 0) {
   1817            return CKR_ENCRYPTED_DATA_LEN_RANGE;
   1818        }
   1819    }
   1820 
   1821    if (!pPart) {
   1822        if (context->doPad) {
   1823            *pulPartLen =
   1824                ulEncryptedPartLen + context->padDataLength - context->blockSize;
   1825            return CKR_OK;
   1826        }
   1827        /* for stream ciphers there is are no constraints on ulEncryptedPartLen.
   1828         * for block ciphers, it must be a multiple of blockSize. The error is
   1829         * detected when this function is called again do decrypt the output.
   1830         */
   1831        *pulPartLen = ulEncryptedPartLen;
   1832        return CKR_OK;
   1833    }
   1834 
   1835    if (context->doPad) {
   1836        /* first decrypt our saved buffer */
   1837        if (context->padDataLength != 0) {
   1838            rv = (*context->update)(context->cipherInfo, pPart, &padoutlen,
   1839                                    maxout, context->padBuf, context->blockSize);
   1840            if (rv != SECSuccess)
   1841                return sftk_MapDecryptError(PORT_GetError());
   1842            pPart += padoutlen;
   1843            maxout -= padoutlen;
   1844        }
   1845        /* now save the final block for the next decrypt or the final */
   1846        PORT_Memcpy(context->padBuf, &pEncryptedPart[ulEncryptedPartLen - context->blockSize],
   1847                    context->blockSize);
   1848        context->padDataLength = context->blockSize;
   1849        ulEncryptedPartLen -= context->padDataLength;
   1850    }
   1851 
   1852    /* do it: NOTE: this assumes buf size in is >= buf size out! */
   1853    rv = (*context->update)(context->cipherInfo, pPart, &outlen,
   1854                            maxout, pEncryptedPart, ulEncryptedPartLen);
   1855    if (rv != SECSuccess) {
   1856        return sftk_MapDecryptError(PORT_GetError());
   1857    }
   1858    *pulPartLen = (CK_ULONG)(outlen + padoutlen);
   1859    return CKR_OK;
   1860 }
   1861 
   1862 /* NSC_DecryptFinal finishes a multiple-part decryption operation. */
   1863 CK_RV
   1864 NSC_DecryptFinal(CK_SESSION_HANDLE hSession,
   1865                 CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen)
   1866 {
   1867    SFTKSession *session;
   1868    SFTKSessionContext *context;
   1869    unsigned int outlen;
   1870    unsigned int maxout = *pulLastPartLen;
   1871    CK_RV crv;
   1872    SECStatus rv = SECSuccess;
   1873 
   1874    CHECK_FORK();
   1875 
   1876    /* make sure we're legal */
   1877    crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_TRUE, &session);
   1878    if (crv != CKR_OK)
   1879        return crv;
   1880 
   1881    *pulLastPartLen = 0;
   1882    if (!pLastPart) {
   1883        /* caller is checking the amount of remaining data */
   1884        if (context->padDataLength > 0) {
   1885            *pulLastPartLen = context->padDataLength;
   1886        }
   1887        goto finish;
   1888    }
   1889 
   1890    if (context->doPad) {
   1891        /* decrypt our saved buffer */
   1892        if (context->padDataLength != 0) {
   1893            /* this assumes that pLastPart is big enough to hold the *whole*
   1894             * buffer!!! */
   1895            rv = (*context->update)(context->cipherInfo, pLastPart, &outlen,
   1896                                    maxout, context->padBuf, context->blockSize);
   1897            if (rv != SECSuccess) {
   1898                crv = sftk_MapDecryptError(PORT_GetError());
   1899            } else {
   1900                unsigned int padSize = 0;
   1901                crv = sftk_CheckCBCPadding(pLastPart, outlen,
   1902                                           context->blockSize, &padSize);
   1903                /* Update pulLastPartLen, in constant time, if crv is OK */
   1904                *pulLastPartLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulLastPartLen);
   1905            }
   1906        }
   1907    }
   1908 
   1909    sftk_TerminateOp(session, SFTK_DECRYPT, context);
   1910 finish:
   1911    sftk_FreeSession(session);
   1912    return crv;
   1913 }
   1914 
   1915 /* NSC_Decrypt decrypts encrypted data in a single part. */
   1916 CK_RV
   1917 NSC_Decrypt(CK_SESSION_HANDLE hSession,
   1918            CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
   1919            CK_ULONG_PTR pulDataLen)
   1920 {
   1921    SFTKSession *session;
   1922    SFTKSessionContext *context;
   1923    unsigned int outlen;
   1924    unsigned int maxoutlen = *pulDataLen;
   1925    CK_RV crv;
   1926    CK_RV crv2;
   1927    SECStatus rv = SECSuccess;
   1928 
   1929    CHECK_FORK();
   1930 
   1931    /* make sure we're legal */
   1932    crv = sftk_GetContext(hSession, &context, SFTK_DECRYPT, PR_FALSE, &session);
   1933    if (crv != CKR_OK)
   1934        return crv;
   1935 
   1936    if (!pData) {
   1937        *pulDataLen = (CK_ULONG)(ulEncryptedDataLen + context->blockSize);
   1938        goto done;
   1939    }
   1940 
   1941    if (context->doPad && context->multi) {
   1942        CK_ULONG updateLen = maxoutlen;
   1943        CK_ULONG finalLen;
   1944        /* padding is fairly complicated, have the update and final
   1945         * code deal with it */
   1946        sftk_FreeSession(session);
   1947        crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen,
   1948                                pData, &updateLen);
   1949        if (crv == CKR_OK) {
   1950            maxoutlen -= updateLen;
   1951            pData += updateLen;
   1952        }
   1953        finalLen = maxoutlen;
   1954        crv2 = NSC_DecryptFinal(hSession, pData, &finalLen);
   1955        if (crv == CKR_OK) {
   1956            *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv2), updateLen + finalLen, *pulDataLen);
   1957            return crv2;
   1958        } else {
   1959            return crv;
   1960        }
   1961    }
   1962 
   1963    rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
   1964                            pEncryptedData, ulEncryptedDataLen);
   1965    /* XXX need to do MUCH better error mapping than this. */
   1966    crv = (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError());
   1967    if (rv == SECSuccess) {
   1968        if (context->doPad) {
   1969            unsigned int padSize = 0;
   1970            crv = sftk_CheckCBCPadding(pData, outlen, context->blockSize,
   1971                                       &padSize);
   1972            /* Update pulDataLen, in constant time, if crv is OK */
   1973            *pulDataLen = PORT_CT_SEL(sftk_CKRVToMask(crv), outlen - padSize, *pulDataLen);
   1974        } else {
   1975            *pulDataLen = (CK_ULONG)outlen;
   1976        }
   1977    }
   1978    sftk_TerminateOp(session, SFTK_DECRYPT, context);
   1979 done:
   1980    sftk_FreeSession(session);
   1981    return crv;
   1982 }
   1983 
   1984 /*
   1985 ************** Crypto Functions:     Digest (HASH)  ************************
   1986 */
   1987 
   1988 /* NSC_DigestInit initializes a message-digesting operation. */
   1989 CK_RV
   1990 NSC_DigestInit(CK_SESSION_HANDLE hSession,
   1991               CK_MECHANISM_PTR pMechanism)
   1992 {
   1993    SFTKSession *session;
   1994    SFTKSessionContext *context;
   1995    CK_RV crv = CKR_OK;
   1996 
   1997    CHECK_FORK();
   1998 
   1999    session = sftk_SessionFromHandle(hSession);
   2000    if (session == NULL)
   2001        return CKR_SESSION_HANDLE_INVALID;
   2002    crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_HASH,
   2003                           NULL, 0, NULL, 0, CKA_DIGEST);
   2004    if (crv != CKR_OK) {
   2005        sftk_FreeSession(session);
   2006        return crv;
   2007    }
   2008 
   2009 #define INIT_MECH(mmm)                                         \
   2010    case CKM_##mmm: {                                          \
   2011        mmm##Context *mmm##_ctx = mmm##_NewContext();          \
   2012        context->cipherInfo = (void *)mmm##_ctx;               \
   2013        context->cipherInfoLen = mmm##_FlattenSize(mmm##_ctx); \
   2014        context->currentMech = CKM_##mmm;                      \
   2015        context->hashUpdate = SFTKHash_##mmm##_Update;         \
   2016        context->end = SFTKHash_##mmm##_End;                   \
   2017        context->destroy = SFTKHash_##mmm##_DestroyContext;    \
   2018        context->maxLen = mmm##_LENGTH;                        \
   2019        if (mmm##_ctx)                                         \
   2020            mmm##_Begin(mmm##_ctx);                            \
   2021        else                                                   \
   2022            crv = CKR_HOST_MEMORY;                             \
   2023        break;                                                 \
   2024    }
   2025 
   2026    switch (pMechanism->mechanism) {
   2027        INIT_MECH(MD2)
   2028        INIT_MECH(MD5)
   2029        INIT_MECH(SHA1)
   2030        INIT_MECH(SHA224)
   2031        INIT_MECH(SHA256)
   2032        INIT_MECH(SHA384)
   2033        INIT_MECH(SHA512)
   2034        INIT_MECH(SHA3_224)
   2035        INIT_MECH(SHA3_256)
   2036        INIT_MECH(SHA3_384)
   2037        INIT_MECH(SHA3_512)
   2038 
   2039        default:
   2040            crv = CKR_MECHANISM_INVALID;
   2041            break;
   2042    }
   2043 
   2044    if (crv != CKR_OK) {
   2045        sftk_FreeContext(context);
   2046        sftk_FreeSession(session);
   2047        return crv;
   2048    }
   2049    sftk_SetContextByType(session, SFTK_HASH, context);
   2050    sftk_FreeSession(session);
   2051    return CKR_OK;
   2052 }
   2053 
   2054 /* NSC_Digest digests data in a single part. */
   2055 CK_RV
   2056 NSC_Digest(CK_SESSION_HANDLE hSession,
   2057           CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest,
   2058           CK_ULONG_PTR pulDigestLen)
   2059 {
   2060    SFTKSession *session;
   2061    SFTKSessionContext *context;
   2062    unsigned int digestLen;
   2063    unsigned int maxout = *pulDigestLen;
   2064    CK_RV crv;
   2065 
   2066    CHECK_FORK();
   2067 
   2068    /* make sure we're legal */
   2069    crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_FALSE, &session);
   2070    if (crv != CKR_OK)
   2071        return crv;
   2072 
   2073    if (pDigest == NULL) {
   2074        *pulDigestLen = context->maxLen;
   2075        goto finish;
   2076    }
   2077 
   2078 #if (ULONG_MAX > UINT_MAX)
   2079    /* The context->hashUpdate function takes an unsigned int for its data
   2080     * length argument, but NSC_Digest takes an unsigned long. */
   2081    while (ulDataLen > UINT_MAX) {
   2082        (*context->hashUpdate)(context->cipherInfo, pData, UINT_MAX);
   2083        pData += UINT_MAX;
   2084        ulDataLen -= UINT_MAX;
   2085    }
   2086 #endif
   2087    (*context->hashUpdate)(context->cipherInfo, pData, ulDataLen);
   2088 
   2089    /*  NOTE: this assumes buf size is bigenough for the algorithm */
   2090    (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout);
   2091    *pulDigestLen = digestLen;
   2092 
   2093    sftk_TerminateOp(session, SFTK_HASH, context);
   2094 finish:
   2095    sftk_FreeSession(session);
   2096    return CKR_OK;
   2097 }
   2098 
   2099 /* NSC_DigestUpdate continues a multiple-part message-digesting operation. */
   2100 CK_RV
   2101 NSC_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
   2102                 CK_ULONG ulPartLen)
   2103 {
   2104    SFTKSessionContext *context;
   2105    CK_RV crv;
   2106 
   2107    CHECK_FORK();
   2108 
   2109    /* make sure we're legal */
   2110    crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, NULL);
   2111    if (crv != CKR_OK)
   2112        return crv;
   2113 
   2114 #if (ULONG_MAX > UINT_MAX)
   2115    /* The context->hashUpdate function takes an unsigned int for its data
   2116     * length argument, but NSC_DigestUpdate takes an unsigned long. */
   2117    while (ulPartLen > UINT_MAX) {
   2118        (*context->hashUpdate)(context->cipherInfo, pPart, UINT_MAX);
   2119        pPart += UINT_MAX;
   2120        ulPartLen -= UINT_MAX;
   2121    }
   2122 #endif
   2123    (*context->hashUpdate)(context->cipherInfo, pPart, ulPartLen);
   2124 
   2125    return CKR_OK;
   2126 }
   2127 
   2128 /* NSC_DigestFinal finishes a multiple-part message-digesting operation. */
   2129 CK_RV
   2130 NSC_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest,
   2131                CK_ULONG_PTR pulDigestLen)
   2132 {
   2133    SFTKSession *session;
   2134    SFTKSessionContext *context;
   2135    unsigned int maxout = *pulDigestLen;
   2136    unsigned int digestLen;
   2137    CK_RV crv;
   2138 
   2139    CHECK_FORK();
   2140 
   2141    /* make sure we're legal */
   2142    crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
   2143    if (crv != CKR_OK)
   2144        return crv;
   2145 
   2146    if (pDigest != NULL) {
   2147        (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout);
   2148        *pulDigestLen = digestLen;
   2149        sftk_TerminateOp(session, SFTK_HASH, context);
   2150    } else {
   2151        *pulDigestLen = context->maxLen;
   2152    }
   2153 
   2154    sftk_FreeSession(session);
   2155    return CKR_OK;
   2156 }
   2157 
   2158 /*
   2159 * these helper functions are used by Generic Macing and Signing functions
   2160 * that use hashes as part of their operations.
   2161 */
   2162 #define DOSUB(mmm)                                              \
   2163    static CK_RV                                                \
   2164        sftk_doSub##mmm(SFTKSessionContext *context)            \
   2165    {                                                           \
   2166        mmm##Context *mmm##_ctx = mmm##_NewContext();           \
   2167        context->hashInfo = (void *)mmm##_ctx;                  \
   2168        context->hashUpdate = SFTKHash_##mmm##_Update;          \
   2169        context->end = SFTKHash_##mmm##_End;                    \
   2170        context->hashdestroy = SFTKHash_##mmm##_DestroyContext; \
   2171        if (!context->hashInfo) {                               \
   2172            return CKR_HOST_MEMORY;                             \
   2173        }                                                       \
   2174        mmm##_Begin(mmm##_ctx);                                 \
   2175        return CKR_OK;                                          \
   2176    }
   2177 
   2178 DOSUB(MD2)
   2179 DOSUB(MD5)
   2180 DOSUB(SHA1)
   2181 DOSUB(SHA224)
   2182 DOSUB(SHA256)
   2183 DOSUB(SHA384)
   2184 DOSUB(SHA512)
   2185 
   2186 static SECStatus
   2187 sftk_SignCopy(
   2188    void *copyLen,
   2189    unsigned char *out, unsigned int *outLength,
   2190    unsigned int maxLength,
   2191    const unsigned char *hashResult,
   2192    unsigned int hashResultLength)
   2193 {
   2194    unsigned int toCopy = *(CK_ULONG *)copyLen;
   2195    if (toCopy > maxLength) {
   2196        toCopy = maxLength;
   2197    }
   2198    if (toCopy > hashResultLength) {
   2199        toCopy = hashResultLength;
   2200    }
   2201    memcpy(out, hashResult, toCopy);
   2202    if (outLength) {
   2203        *outLength = toCopy;
   2204    }
   2205    return SECSuccess;
   2206 }
   2207 
   2208 /* Verify is just a compare for HMAC */
   2209 static SECStatus
   2210 sftk_HMACCmp(void *copyLen, const unsigned char *sig, unsigned int sigLen,
   2211             const unsigned char *hash, unsigned int hashLen)
   2212 {
   2213    if (NSS_SecureMemcmp(sig, hash, *(CK_ULONG *)copyLen) == 0) {
   2214        return SECSuccess;
   2215    }
   2216 
   2217    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
   2218    return SECFailure;
   2219 }
   2220 
   2221 /*
   2222 * common HMAC + CMAC initialization routine
   2223 */
   2224 static CK_RV
   2225 sftk_doMACInit(CK_MECHANISM_TYPE mech, SFTKSessionContext *session,
   2226               SFTKObject *key, CK_ULONG mac_size)
   2227 {
   2228    CK_RV crv;
   2229    sftk_MACCtx *context;
   2230    CK_ULONG *intpointer;
   2231    PRBool isFIPS = sftk_isFIPS(key->slot->slotID);
   2232 
   2233    /* Set up the initial context. */
   2234    crv = sftk_MAC_Create(mech, key, &context);
   2235    if (crv != CKR_OK) {
   2236        return crv;
   2237    }
   2238 
   2239    session->hashInfo = context;
   2240    session->multi = PR_TRUE;
   2241 
   2242    /* Required by FIPS 198 Section 4. Delay this check until after the MAC
   2243     * has been initialized to steal the output size of the MAC. */
   2244    if (isFIPS && (mac_size < 4 || mac_size < context->mac_size / 2)) {
   2245        sftk_MAC_DestroyContext(context, PR_TRUE);
   2246        return CKR_BUFFER_TOO_SMALL;
   2247    }
   2248 
   2249    /* Configure our helper functions appropriately. Note that these casts
   2250     * ignore the return values. */
   2251    session->hashUpdate = SFTKHash_sftk_MAC_Update;
   2252    session->end = SFTKHash_sftk_MAC_End;
   2253    session->hashdestroy = SFTKHash_sftk_MAC_DestroyContext;
   2254 
   2255    intpointer = PORT_New(CK_ULONG);
   2256    if (intpointer == NULL) {
   2257        sftk_MAC_DestroyContext(context, PR_TRUE);
   2258        return CKR_HOST_MEMORY;
   2259    }
   2260    *intpointer = mac_size;
   2261    session->cipherInfo = intpointer;
   2262 
   2263    /* Since we're only "hashing", copy the result from session->end to the
   2264     * caller using sftk_SignCopy. */
   2265    session->update = sftk_SignCopy;
   2266    session->verify = sftk_HMACCmp;
   2267    session->destroy = sftk_Space;
   2268 
   2269    session->maxLen = context->mac_size;
   2270 
   2271    return CKR_OK;
   2272 }
   2273 
   2274 /*
   2275 *  SSL Macing support. SSL Macs are inited, then update with the base
   2276 * hashing algorithm, then finalized in sign and verify
   2277 */
   2278 
   2279 /*
   2280 * FROM SSL:
   2281 * 60 bytes is 3 times the maximum length MAC size that is supported.
   2282 * We probably should have one copy of this table. We still need this table
   2283 * in ssl to 'sign' the handshake hashes.
   2284 */
   2285 static unsigned char ssl_pad_1[60] = {
   2286    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
   2287    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
   2288    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
   2289    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
   2290    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
   2291    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
   2292    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
   2293    0x36, 0x36, 0x36, 0x36
   2294 };
   2295 static unsigned char ssl_pad_2[60] = {
   2296    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
   2297    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
   2298    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
   2299    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
   2300    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
   2301    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
   2302    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
   2303    0x5c, 0x5c, 0x5c, 0x5c
   2304 };
   2305 
   2306 static SECStatus
   2307 sftk_SSLMACSign(void *ctx, unsigned char *sig, unsigned int *sigLen,
   2308                unsigned int maxLen, const unsigned char *hash, unsigned int hashLen)
   2309 {
   2310    SFTKSSLMACInfo *info = ctx;
   2311    unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH];
   2312    unsigned int out;
   2313 
   2314    info->begin(info->hashContext);
   2315    info->update(info->hashContext, info->key, info->keySize);
   2316    info->update(info->hashContext, ssl_pad_2, info->padSize);
   2317    info->update(info->hashContext, hash, hashLen);
   2318    info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH);
   2319    PORT_Memcpy(sig, tmpBuf, info->macSize);
   2320    PORT_Memset(tmpBuf, 0, info->macSize);
   2321    *sigLen = info->macSize;
   2322    return SECSuccess;
   2323 }
   2324 
   2325 static SECStatus
   2326 sftk_SSLMACVerify(void *ctx, const unsigned char *sig, unsigned int sigLen,
   2327                  const unsigned char *hash, unsigned int hashLen)
   2328 {
   2329    SFTKSSLMACInfo *info = ctx;
   2330    unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH];
   2331    unsigned int out;
   2332    int cmp;
   2333 
   2334    info->begin(info->hashContext);
   2335    info->update(info->hashContext, info->key, info->keySize);
   2336    info->update(info->hashContext, ssl_pad_2, info->padSize);
   2337    info->update(info->hashContext, hash, hashLen);
   2338    info->end(info->hashContext, tmpBuf, &out, SFTK_MAX_MAC_LENGTH);
   2339    cmp = NSS_SecureMemcmp(sig, tmpBuf, info->macSize);
   2340    PORT_Memset(tmpBuf, 0, info->macSize);
   2341    return (cmp == 0) ? SECSuccess : SECFailure;
   2342 }
   2343 
   2344 /*
   2345 * common HMAC initalization routine
   2346 */
   2347 static CK_RV
   2348 sftk_doSSLMACInit(SFTKSessionContext *context, SECOidTag oid,
   2349                  SFTKObject *key, CK_ULONG mac_size)
   2350 {
   2351    SFTKAttribute *keyval;
   2352    SFTKBegin begin;
   2353    int padSize;
   2354    SFTKSSLMACInfo *sslmacinfo;
   2355    CK_RV crv = CKR_MECHANISM_INVALID;
   2356 
   2357    if (oid == SEC_OID_SHA1) {
   2358        crv = sftk_doSubSHA1(context);
   2359        if (crv != CKR_OK)
   2360            return crv;
   2361        begin = SFTKHash_SHA1_Begin;
   2362        padSize = 40;
   2363    } else {
   2364        crv = sftk_doSubMD5(context);
   2365        if (crv != CKR_OK)
   2366            return crv;
   2367        begin = SFTKHash_MD5_Begin;
   2368        padSize = 48;
   2369    }
   2370    context->multi = PR_TRUE;
   2371 
   2372    keyval = sftk_FindAttribute(key, CKA_VALUE);
   2373    if (keyval == NULL)
   2374        return CKR_KEY_SIZE_RANGE;
   2375 
   2376    context->hashUpdate(context->hashInfo, keyval->attrib.pValue,
   2377                        keyval->attrib.ulValueLen);
   2378    context->hashUpdate(context->hashInfo, ssl_pad_1, padSize);
   2379    sslmacinfo = (SFTKSSLMACInfo *)PORT_Alloc(sizeof(SFTKSSLMACInfo));
   2380    if (sslmacinfo == NULL) {
   2381        sftk_FreeAttribute(keyval);
   2382        return CKR_HOST_MEMORY;
   2383    }
   2384    sslmacinfo->size = sizeof(SFTKSSLMACInfo);
   2385    sslmacinfo->macSize = mac_size;
   2386    sslmacinfo->hashContext = context->hashInfo;
   2387    PORT_Memcpy(sslmacinfo->key, keyval->attrib.pValue,
   2388                keyval->attrib.ulValueLen);
   2389    sslmacinfo->keySize = keyval->attrib.ulValueLen;
   2390    sslmacinfo->begin = begin;
   2391    sslmacinfo->end = context->end;
   2392    sslmacinfo->update = context->hashUpdate;
   2393    sslmacinfo->padSize = padSize;
   2394    sftk_FreeAttribute(keyval);
   2395    context->cipherInfo = (void *)sslmacinfo;
   2396    context->destroy = sftk_ZSpace;
   2397    context->update = sftk_SSLMACSign;
   2398    context->verify = sftk_SSLMACVerify;
   2399    context->maxLen = mac_size;
   2400    return CKR_OK;
   2401 }
   2402 
   2403 /*
   2404 ************** Crypto Functions:     Sign  ************************
   2405 */
   2406 
   2407 /**
   2408 * Check if We're using CBCMacing and initialize the session context if we are.
   2409 *  @param contextType SFTK_SIGN or SFTK_VERIFY
   2410 *  @param keyUsage    check whether key allows this usage
   2411 */
   2412 static CK_RV
   2413 sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
   2414                CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage,
   2415                SFTKContextType contextType)
   2416 
   2417 {
   2418    CK_MECHANISM cbc_mechanism;
   2419    CK_ULONG mac_bytes = SFTK_INVALID_MAC_SIZE;
   2420 #ifndef NSS_DISABLE_DEPRECATED_RC2
   2421    CK_RC2_CBC_PARAMS rc2_params;
   2422 #endif
   2423 #if NSS_SOFTOKEN_DOES_RC5
   2424    CK_RC5_CBC_PARAMS rc5_params;
   2425    CK_RC5_MAC_GENERAL_PARAMS *rc5_mac;
   2426 #endif
   2427    unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE];
   2428    unsigned char k2[SFTK_MAX_BLOCK_SIZE];
   2429    unsigned char k3[SFTK_MAX_BLOCK_SIZE];
   2430    SFTKSessionContext *context;
   2431    CK_RV crv;
   2432    unsigned int blockSize;
   2433    PRBool isXCBC = PR_FALSE;
   2434 
   2435    if (!pMechanism) {
   2436        return CKR_MECHANISM_PARAM_INVALID;
   2437    }
   2438 
   2439    switch (pMechanism->mechanism) {
   2440 #ifndef NSS_DISABLE_DEPRECATED_RC2
   2441        case CKM_RC2_MAC_GENERAL:
   2442            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC2_MAC_GENERAL_PARAMS))) {
   2443                return CKR_MECHANISM_PARAM_INVALID;
   2444            }
   2445            mac_bytes =
   2446                ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
   2447        /* fall through */
   2448        case CKM_RC2_MAC:
   2449            /* this works because ulEffectiveBits is in the same place in both the
   2450             * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */
   2451            rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *)
   2452                                              pMechanism->pParameter)
   2453                                             ->ulEffectiveBits;
   2454            PORT_Memset(rc2_params.iv, 0, sizeof(rc2_params.iv));
   2455            cbc_mechanism.mechanism = CKM_RC2_CBC;
   2456            cbc_mechanism.pParameter = &rc2_params;
   2457            cbc_mechanism.ulParameterLen = sizeof(rc2_params);
   2458            blockSize = 8;
   2459            break;
   2460 #endif /* NSS_DISABLE_DEPRECATED_RC2 */
   2461 
   2462 #if NSS_SOFTOKEN_DOES_RC5
   2463        case CKM_RC5_MAC_GENERAL:
   2464            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) {
   2465                return CKR_MECHANISM_PARAM_INVALID;
   2466            }
   2467            mac_bytes =
   2468                ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
   2469        /* fall through */
   2470        case CKM_RC5_MAC:
   2471            /* this works because ulEffectiveBits is in the same place in both the
   2472             * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */
   2473            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_RC5_MAC_GENERAL_PARAMS))) {
   2474                return CKR_MECHANISM_PARAM_INVALID;
   2475            }
   2476            rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter;
   2477            rc5_params.ulWordsize = rc5_mac->ulWordsize;
   2478            rc5_params.ulRounds = rc5_mac->ulRounds;
   2479            rc5_params.pIv = ivBlock;
   2480            if ((blockSize = rc5_mac->ulWordsize * 2) > SFTK_MAX_BLOCK_SIZE)
   2481                return CKR_MECHANISM_PARAM_INVALID;
   2482            rc5_params.ulIvLen = blockSize;
   2483            PORT_Memset(ivBlock, 0, blockSize);
   2484            cbc_mechanism.mechanism = CKM_RC5_CBC;
   2485            cbc_mechanism.pParameter = &rc5_params;
   2486            cbc_mechanism.ulParameterLen = sizeof(rc5_params);
   2487            break;
   2488 #endif
   2489        /* add cast and idea later */
   2490        case CKM_DES_MAC_GENERAL:
   2491            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
   2492        /* fall through */
   2493        case CKM_DES_MAC:
   2494            blockSize = 8;
   2495            PORT_Memset(ivBlock, 0, blockSize);
   2496            cbc_mechanism.mechanism = CKM_DES_CBC;
   2497            cbc_mechanism.pParameter = &ivBlock;
   2498            cbc_mechanism.ulParameterLen = blockSize;
   2499            break;
   2500        case CKM_DES3_MAC_GENERAL:
   2501            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
   2502        /* fall through */
   2503        case CKM_DES3_MAC:
   2504            blockSize = 8;
   2505            PORT_Memset(ivBlock, 0, blockSize);
   2506            cbc_mechanism.mechanism = CKM_DES3_CBC;
   2507            cbc_mechanism.pParameter = &ivBlock;
   2508            cbc_mechanism.ulParameterLen = blockSize;
   2509            break;
   2510        case CKM_CDMF_MAC_GENERAL:
   2511            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
   2512        /* fall through */
   2513        case CKM_CDMF_MAC:
   2514            blockSize = 8;
   2515            PORT_Memset(ivBlock, 0, blockSize);
   2516            cbc_mechanism.mechanism = CKM_CDMF_CBC;
   2517            cbc_mechanism.pParameter = &ivBlock;
   2518            cbc_mechanism.ulParameterLen = blockSize;
   2519            break;
   2520 #ifndef NSS_DISABLE_DEPRECATED_SEED
   2521        case CKM_SEED_MAC_GENERAL:
   2522            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
   2523        /* fall through */
   2524        case CKM_SEED_MAC:
   2525            blockSize = 16;
   2526            PORT_Memset(ivBlock, 0, blockSize);
   2527            cbc_mechanism.mechanism = CKM_SEED_CBC;
   2528            cbc_mechanism.pParameter = &ivBlock;
   2529            cbc_mechanism.ulParameterLen = blockSize;
   2530            break;
   2531 #endif /* NSS_DISABLE_DEPRECATED_SEED */
   2532        case CKM_CAMELLIA_MAC_GENERAL:
   2533            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
   2534        /* fall through */
   2535        case CKM_CAMELLIA_MAC:
   2536            blockSize = 16;
   2537            PORT_Memset(ivBlock, 0, blockSize);
   2538            cbc_mechanism.mechanism = CKM_CAMELLIA_CBC;
   2539            cbc_mechanism.pParameter = &ivBlock;
   2540            cbc_mechanism.ulParameterLen = blockSize;
   2541            break;
   2542        case CKM_AES_MAC_GENERAL:
   2543            mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
   2544        /* fall through */
   2545        case CKM_AES_MAC:
   2546            blockSize = 16;
   2547            PORT_Memset(ivBlock, 0, blockSize);
   2548            cbc_mechanism.mechanism = CKM_AES_CBC;
   2549            cbc_mechanism.pParameter = &ivBlock;
   2550            cbc_mechanism.ulParameterLen = blockSize;
   2551            break;
   2552        case CKM_AES_XCBC_MAC_96:
   2553        case CKM_AES_XCBC_MAC:
   2554            /* The only difference between CKM_AES_XCBC_MAC
   2555             * and CKM_AES_XCBC_MAC_96 is the size of the returned mac. */
   2556            mac_bytes = pMechanism->mechanism == CKM_AES_XCBC_MAC_96 ? 12 : 16;
   2557            blockSize = 16;
   2558            PORT_Memset(ivBlock, 0, blockSize);
   2559            cbc_mechanism.mechanism = CKM_AES_CBC;
   2560            cbc_mechanism.pParameter = &ivBlock;
   2561            cbc_mechanism.ulParameterLen = blockSize;
   2562            /* is XCBC requires extra processing at the end of the operation */
   2563            isXCBC = PR_TRUE;
   2564            /* The input key is used to generate k1, k2, and k3. k2 and k3
   2565             * are used at the end in the pad step. k1 replaces the input
   2566             * key in the aes cbc mac */
   2567            crv = sftk_aes_xcbc_new_keys(hSession, hKey, &hKey, k2, k3);
   2568            if (crv != CKR_OK) {
   2569                return crv;
   2570            }
   2571            break;
   2572        default:
   2573            return CKR_FUNCTION_NOT_SUPPORTED;
   2574    }
   2575 
   2576    /* if MAC size is externally supplied, it should be checked.
   2577     */
   2578    if (mac_bytes == SFTK_INVALID_MAC_SIZE)
   2579        mac_bytes = blockSize >> 1;
   2580    else {
   2581        if (mac_bytes > blockSize) {
   2582            crv = CKR_MECHANISM_PARAM_INVALID;
   2583            goto fail;
   2584        }
   2585    }
   2586 
   2587    crv = sftk_CryptInit(hSession, &cbc_mechanism, hKey,
   2588                         CKA_ENCRYPT, /* CBC mech is able to ENCRYPT, not SIGN/VERIFY */
   2589                         keyUsage, contextType, PR_TRUE);
   2590    if (crv != CKR_OK)
   2591        goto fail;
   2592    crv = sftk_GetContext(hSession, &context, contextType, PR_TRUE, NULL);
   2593 
   2594    /* this shouldn't happen! */
   2595    PORT_Assert(crv == CKR_OK);
   2596    if (crv != CKR_OK)
   2597        goto fail;
   2598    context->blockSize = blockSize;
   2599    context->macSize = mac_bytes;
   2600    context->isXCBC = isXCBC;
   2601    if (isXCBC) {
   2602        /* save the xcbc specific parameters */
   2603        PORT_Memcpy(context->k2, k2, blockSize);
   2604        PORT_Memcpy(context->k3, k3, blockSize);
   2605        PORT_Memset(k2, 0, blockSize);
   2606        PORT_Memset(k3, 0, blockSize);
   2607        /* get rid of the temp key now that the context has been created */
   2608        NSC_DestroyObject(hSession, hKey);
   2609    }
   2610    return CKR_OK;
   2611 fail:
   2612    if (isXCBC) {
   2613        PORT_Memset(k2, 0, blockSize);
   2614        PORT_Memset(k3, 0, blockSize);
   2615        NSC_DestroyObject(hSession, hKey); /* get rid of our temp key */
   2616    }
   2617    return crv;
   2618 }
   2619 
   2620 /*
   2621 * encode RSA PKCS #1 Signature data before signing...
   2622 */
   2623 static SECStatus
   2624 sftk_RSAHashSign(void *ctx, unsigned char *sig,
   2625                 unsigned int *sigLen, unsigned int maxLen,
   2626                 const unsigned char *hash, unsigned int hashLen)
   2627 {
   2628    SFTKHashSignInfo *info = ctx;
   2629    PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
   2630    if (info->key->keyType != NSSLOWKEYRSAKey) {
   2631        PORT_SetError(SEC_ERROR_INVALID_KEY);
   2632        return SECFailure;
   2633    }
   2634 
   2635    return RSA_HashSign(info->hashOid, info->key, sig, sigLen, maxLen,
   2636                        hash, hashLen);
   2637 }
   2638 
   2639 /* XXX Old template; want to expunge it eventually. */
   2640 static DERTemplate SECAlgorithmIDTemplate[] = {
   2641    { DER_SEQUENCE,
   2642      0, NULL, sizeof(SECAlgorithmID) },
   2643    { DER_OBJECT_ID,
   2644      offsetof(SECAlgorithmID, algorithm) },
   2645    { DER_OPTIONAL | DER_ANY,
   2646      offsetof(SECAlgorithmID, parameters) },
   2647    { 0 }
   2648 };
   2649 
   2650 /*
   2651 * XXX OLD Template.  Once all uses have been switched over to new one,
   2652 * remove this.
   2653 */
   2654 static DERTemplate SGNDigestInfoTemplate[] = {
   2655    { DER_SEQUENCE,
   2656      0, NULL, sizeof(SGNDigestInfo) },
   2657    { DER_INLINE,
   2658      offsetof(SGNDigestInfo, digestAlgorithm),
   2659      SECAlgorithmIDTemplate },
   2660    { DER_OCTET_STRING,
   2661      offsetof(SGNDigestInfo, digest) },
   2662    { 0 }
   2663 };
   2664 
   2665 /*
   2666 * encode RSA PKCS #1 Signature data before signing...
   2667 */
   2668 SECStatus
   2669 RSA_HashSign(SECOidTag hashOid, NSSLOWKEYPrivateKey *key,
   2670             unsigned char *sig, unsigned int *sigLen, unsigned int maxLen,
   2671             const unsigned char *hash, unsigned int hashLen)
   2672 {
   2673    SECStatus rv = SECFailure;
   2674    SECItem digder;
   2675    PLArenaPool *arena = NULL;
   2676    SGNDigestInfo *di = NULL;
   2677 
   2678    digder.data = NULL;
   2679 
   2680    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   2681    if (!arena) {
   2682        goto loser;
   2683    }
   2684 
   2685    /* Construct digest info */
   2686    di = SGN_CreateDigestInfo(hashOid, hash, hashLen);
   2687    if (!di) {
   2688        goto loser;
   2689    }
   2690 
   2691    /* Der encode the digest as a DigestInfo */
   2692    rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di);
   2693    if (rv != SECSuccess) {
   2694        goto loser;
   2695    }
   2696 
   2697    /*
   2698    ** Encrypt signature after constructing appropriate PKCS#1 signature
   2699    ** block
   2700    */
   2701    rv = RSA_Sign(&key->u.rsa, sig, sigLen, maxLen, digder.data,
   2702                  digder.len);
   2703    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
   2704        sftk_fatalError = PR_TRUE;
   2705    }
   2706 
   2707 loser:
   2708    SGN_DestroyDigestInfo(di);
   2709    if (arena != NULL) {
   2710        PORT_FreeArena(arena, PR_TRUE);
   2711    }
   2712    return rv;
   2713 }
   2714 
   2715 static SECStatus
   2716 sftk_RSASign(void *ctx, unsigned char *output,
   2717             unsigned int *outputLen, unsigned int maxOutputLen,
   2718             const unsigned char *input, unsigned int inputLen)
   2719 {
   2720    NSSLOWKEYPrivateKey *key = ctx;
   2721    SECStatus rv = SECFailure;
   2722 
   2723    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
   2724    if (key->keyType != NSSLOWKEYRSAKey) {
   2725        PORT_SetError(SEC_ERROR_INVALID_KEY);
   2726        return SECFailure;
   2727    }
   2728 
   2729    rv = RSA_Sign(&key->u.rsa, output, outputLen, maxOutputLen, input,
   2730                  inputLen);
   2731    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
   2732        sftk_fatalError = PR_TRUE;
   2733    }
   2734    return rv;
   2735 }
   2736 
   2737 static SECStatus
   2738 sftk_RSASignRaw(void *ctx, unsigned char *output,
   2739                unsigned int *outputLen, unsigned int maxOutputLen,
   2740                const unsigned char *input, unsigned int inputLen)
   2741 {
   2742    NSSLOWKEYPrivateKey *key = ctx;
   2743    SECStatus rv = SECFailure;
   2744 
   2745    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
   2746    if (key->keyType != NSSLOWKEYRSAKey) {
   2747        PORT_SetError(SEC_ERROR_INVALID_KEY);
   2748        return SECFailure;
   2749    }
   2750 
   2751    rv = RSA_SignRaw(&key->u.rsa, output, outputLen, maxOutputLen, input,
   2752                     inputLen);
   2753    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
   2754        sftk_fatalError = PR_TRUE;
   2755    }
   2756    return rv;
   2757 }
   2758 
   2759 static SECStatus
   2760 sftk_RSASignPSS(void *ctx, unsigned char *sig,
   2761                unsigned int *sigLen, unsigned int maxLen,
   2762                const unsigned char *hash, unsigned int hashLen)
   2763 {
   2764    SFTKPSSSignInfo *info = ctx;
   2765    SECStatus rv = SECFailure;
   2766    HASH_HashType hashAlg;
   2767    HASH_HashType maskHashAlg;
   2768    CK_RSA_PKCS_PSS_PARAMS *params = &info->params;
   2769 
   2770    PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
   2771    if (info->key->keyType != NSSLOWKEYRSAKey) {
   2772        PORT_SetError(SEC_ERROR_INVALID_KEY);
   2773        return SECFailure;
   2774    }
   2775 
   2776    hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg);
   2777    maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf);
   2778 
   2779    rv = RSA_SignPSS(&info->key->u.rsa, hashAlg, maskHashAlg, NULL,
   2780                     params->sLen, sig, sigLen, maxLen, hash, hashLen);
   2781    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
   2782        sftk_fatalError = PR_TRUE;
   2783    }
   2784    return rv;
   2785 }
   2786 
   2787 #ifndef NSS_DISABLE_DSA
   2788 static SECStatus
   2789 nsc_DSA_Verify_Stub(void *ctx, const unsigned char *sigBuf, unsigned int sigLen,
   2790                    const unsigned char *dataBuf, unsigned int dataLen)
   2791 {
   2792    NSSLOWKEYPublicKey *key = ctx;
   2793    SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen };
   2794    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
   2795    return DSA_VerifyDigest(&(key->u.dsa), &signature, &digest);
   2796 }
   2797 
   2798 static SECStatus
   2799 nsc_DSA_Sign_Stub(void *ctx, unsigned char *sigBuf,
   2800                  unsigned int *sigLen, unsigned int maxSigLen,
   2801                  const unsigned char *dataBuf, unsigned int dataLen)
   2802 {
   2803    NSSLOWKEYPrivateKey *key = ctx;
   2804    SECItem signature = { siBuffer, (unsigned char *)sigBuf, maxSigLen };
   2805    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
   2806    SECStatus rv = DSA_SignDigest(&(key->u.dsa), &signature, &digest);
   2807    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
   2808        sftk_fatalError = PR_TRUE;
   2809    }
   2810    *sigLen = signature.len;
   2811    return rv;
   2812 }
   2813 #endif
   2814 
   2815 static SECStatus
   2816 nsc_ECDSAVerifyStub(void *ctx, const unsigned char *sigBuf, unsigned int sigLen,
   2817                    const unsigned char *dataBuf, unsigned int dataLen)
   2818 {
   2819    NSSLOWKEYPublicKey *key = ctx;
   2820    SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen };
   2821    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
   2822    return ECDSA_VerifyDigest(&(key->u.ec), &signature, &digest);
   2823 }
   2824 
   2825 static SECStatus
   2826 nsc_ECDSASignStub(void *ctx, unsigned char *sigBuf,
   2827                  unsigned int *sigLen, unsigned int maxSigLen,
   2828                  const unsigned char *dataBuf, unsigned int dataLen)
   2829 {
   2830    NSSLOWKEYPrivateKey *key = ctx;
   2831    SECItem signature = { siBuffer, sigBuf, maxSigLen };
   2832    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
   2833 
   2834    SECStatus rv = ECDSA_SignDigest(&(key->u.ec), &signature, &digest);
   2835    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
   2836        sftk_fatalError = PR_TRUE;
   2837    }
   2838    *sigLen = signature.len;
   2839    return rv;
   2840 }
   2841 
   2842 static SECStatus
   2843 nsc_EDDSAVerifyStub(void *ctx, const unsigned char *sigBuf, unsigned int sigLen,
   2844                    const unsigned char *dataBuf, unsigned int dataLen)
   2845 {
   2846    NSSLOWKEYPublicKey *key = ctx;
   2847    SECItem signature = { siBuffer, (unsigned char *)sigBuf, sigLen };
   2848    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
   2849    return ED_VerifyMessage(&(key->u.ec), &signature, &digest);
   2850 }
   2851 
   2852 static SECStatus
   2853 nsc_EDDSASignStub(void *ctx, unsigned char *sigBuf,
   2854                  unsigned int *sigLen, unsigned int maxSigLen,
   2855                  const unsigned char *dataBuf, unsigned int dataLen)
   2856 {
   2857    NSSLOWKEYPrivateKey *key = ctx;
   2858    SECItem signature = { siBuffer, sigBuf, maxSigLen };
   2859    SECItem digest = { siBuffer, (unsigned char *)dataBuf, dataLen };
   2860 
   2861    SECStatus rv = ED_SignMessage(&(key->u.ec), &signature, &digest);
   2862    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
   2863        sftk_fatalError = PR_TRUE;
   2864    }
   2865    *sigLen = signature.len;
   2866    return rv;
   2867 }
   2868 
   2869 void
   2870 sftk_MLDSASignUpdate(void *info, const unsigned char *data, unsigned int len)
   2871 {
   2872    MLDSAContext *ctptr = (MLDSAContext *)info;
   2873    const SECItem inData = { siBuffer, (unsigned char *)data, len };
   2874    (void)MLDSA_SignUpdate(ctptr, &inData);
   2875 }
   2876 
   2877 void
   2878 sftk_MLDSAVerifyUpdate(void *info, const unsigned char *data, unsigned int len)
   2879 {
   2880    MLDSAContext *ctptr = (MLDSAContext *)info;
   2881    const SECItem inData = { siBuffer, (unsigned char *)data, len };
   2882    (void)MLDSA_VerifyUpdate(ctptr, &inData);
   2883 }
   2884 
   2885 SECStatus
   2886 sftk_MLDSASignFinal(void *info, unsigned char *sig, unsigned int *sigLen,
   2887                    unsigned int maxLen, const unsigned char *data,
   2888                    unsigned int len)
   2889 {
   2890    MLDSAContext *ctptr = (MLDSAContext *)info;
   2891    SECItem sigOut = { siBuffer, sig, maxLen };
   2892    SECStatus rv;
   2893 
   2894    if (len != 0) {
   2895        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   2896        return SECFailure;
   2897    }
   2898 
   2899    rv = MLDSA_SignFinal(ctptr, &sigOut);
   2900    *sigLen = sigOut.len;
   2901    return rv;
   2902 }
   2903 
   2904 SECStatus
   2905 sftk_MLDSAVerifyFinal(void *info, const unsigned char *sig, unsigned int sigLen,
   2906                      const unsigned char *data, unsigned int len)
   2907 {
   2908    MLDSAContext *ctptr = (MLDSAContext *)info;
   2909    const SECItem sigIn = { siBuffer, (unsigned char *)sig, sigLen };
   2910 
   2911    if (len != 0) {
   2912        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   2913        return SECFailure;
   2914    }
   2915 
   2916    return MLDSA_VerifyFinal(ctptr, &sigIn);
   2917 }
   2918 
   2919 unsigned int
   2920 sftk_MLDSAGetSigLen(CK_ML_DSA_PARAMETER_SET_TYPE paramSet)
   2921 {
   2922    switch (paramSet) {
   2923        case CKP_ML_DSA_44:
   2924            return ML_DSA_44_SIGNATURE_LEN;
   2925        case CKP_ML_DSA_65:
   2926            return ML_DSA_65_SIGNATURE_LEN;
   2927        case CKP_ML_DSA_87:
   2928            return ML_DSA_87_SIGNATURE_LEN;
   2929    }
   2930    /* this is a programming error if we get a valid DSA key with an unknown
   2931     * parmaSet */
   2932    PORT_Assert(/* unknown param set */ 0);
   2933    return 0;
   2934 }
   2935 
   2936 /* NSC_SignInit setups up the signing operations. There are three basic
   2937 * types of signing:
   2938 *      (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied
   2939 *  to data in a single Sign operation (which often looks a lot like an
   2940 *  encrypt, with data coming in and data going out).
   2941 *      (2) Hash based signing, where we continually hash the data, then apply
   2942 *  some sort of signature to the end.
   2943 *      (3) Block Encryption CBC MAC's, where the Data is encrypted with a key,
   2944 *  and only the final block is part of the mac.
   2945 *
   2946 *  For case number 3, we initialize a context much like the Encryption Context
   2947 *  (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and
   2948 *  C_Final by the following method... if it's not multi-part, and it's doesn't
   2949 *  have a hash context, it must be a block Encryption CBC MAC.
   2950 *
   2951 *  For case number 2, we initialize a hash structure, as well as make it
   2952 *  multi-part. Updates are simple calls to the hash update function. Final
   2953 *  calls the hashend, then passes the result to the 'update' function (which
   2954 *  operates as a final signature function). In some hash based MAC'ing (as
   2955 *  opposed to hash base signatures), the update function is can be simply a
   2956 *  copy (as is the case with HMAC).
   2957 */
   2958 CK_RV
   2959 NSC_SignInit(CK_SESSION_HANDLE hSession,
   2960             CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
   2961 {
   2962    SFTKSession *session;
   2963    SFTKObject *key;
   2964    SFTKSessionContext *context;
   2965    CK_KEY_TYPE key_type;
   2966    CK_RV crv = CKR_OK;
   2967    NSSLOWKEYPrivateKey *privKey;
   2968    SFTKHashSignInfo *info = NULL;
   2969    SFTKPSSSignInfo *pinfo = NULL;
   2970 
   2971    CHECK_FORK();
   2972 
   2973    /* Block Cipher MACing Algorithms use a different Context init method..*/
   2974    crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, SFTK_SIGN);
   2975    if (crv != CKR_FUNCTION_NOT_SUPPORTED)
   2976        return crv;
   2977 
   2978    /* we're not using a block cipher mac */
   2979    session = sftk_SessionFromHandle(hSession);
   2980    if (session == NULL)
   2981        return CKR_SESSION_HANDLE_INVALID;
   2982    crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_SIGN, &key,
   2983                           hKey, &key_type, CKO_PRIVATE_KEY, CKA_SIGN);
   2984    if (crv != CKR_OK) {
   2985        sftk_FreeSession(session);
   2986        return crv;
   2987    }
   2988 
   2989    context->multi = PR_FALSE;
   2990 
   2991 #define INIT_RSA_SIGN_MECH(mmm)             \
   2992    case CKM_##mmm##_RSA_PKCS:              \
   2993        context->multi = PR_TRUE;           \
   2994        crv = sftk_doSub##mmm(context);     \
   2995        if (crv != CKR_OK)                  \
   2996            break;                          \
   2997        context->update = sftk_RSAHashSign; \
   2998        info = PORT_New(SFTKHashSignInfo);  \
   2999        if (info == NULL) {                 \
   3000            crv = CKR_HOST_MEMORY;          \
   3001            break;                          \
   3002        }                                   \
   3003        info->hashOid = SEC_OID_##mmm;      \
   3004        goto finish_rsa;
   3005 
   3006    switch (pMechanism->mechanism) {
   3007        INIT_RSA_SIGN_MECH(MD5)
   3008        INIT_RSA_SIGN_MECH(MD2)
   3009        INIT_RSA_SIGN_MECH(SHA1)
   3010        INIT_RSA_SIGN_MECH(SHA224)
   3011        INIT_RSA_SIGN_MECH(SHA256)
   3012        INIT_RSA_SIGN_MECH(SHA384)
   3013        INIT_RSA_SIGN_MECH(SHA512)
   3014 
   3015        case CKM_RSA_PKCS:
   3016            context->update = sftk_RSASign;
   3017            goto finish_rsa;
   3018        case CKM_RSA_X_509:
   3019            context->update = sftk_RSASignRaw;
   3020        finish_rsa:
   3021            if (key_type != CKK_RSA) {
   3022                crv = CKR_KEY_TYPE_INCONSISTENT;
   3023                break;
   3024            }
   3025            context->rsa = PR_TRUE;
   3026            privKey = sftk_GetPrivKey(key, CKK_RSA, &crv);
   3027            if (privKey == NULL) {
   3028                crv = CKR_KEY_TYPE_INCONSISTENT;
   3029                break;
   3030            }
   3031            /* OK, info is allocated only if we're doing hash and sign mechanism.
   3032             * It's necessary to be able to set the correct OID in the final
   3033             * signature.
   3034             */
   3035            if (info) {
   3036                info->key = privKey;
   3037                context->cipherInfo = info;
   3038                context->destroy = sftk_Space;
   3039            } else {
   3040                context->cipherInfo = privKey;
   3041                context->destroy = sftk_Null;
   3042            }
   3043            context->maxLen = nsslowkey_PrivateModulusLen(privKey);
   3044            break;
   3045 
   3046 #define INIT_RSA_PSS_SIG_MECH(mmm)                                                            \
   3047    case CKM_##mmm##_RSA_PKCS_PSS:                                                            \
   3048        context->multi = PR_TRUE;                                                             \
   3049        crv = sftk_doSub##mmm(context);                                                       \
   3050        if (crv != CKR_OK)                                                                    \
   3051            break;                                                                            \
   3052        if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS)) {                   \
   3053            crv = CKR_MECHANISM_PARAM_INVALID;                                                \
   3054            break;                                                                            \
   3055        }                                                                                     \
   3056        if (((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)->hashAlg != CKM_##mmm) { \
   3057            crv = CKR_MECHANISM_PARAM_INVALID;                                                \
   3058            break;                                                                            \
   3059        }                                                                                     \
   3060        goto finish_rsa_pss;
   3061            INIT_RSA_PSS_SIG_MECH(SHA1)
   3062            INIT_RSA_PSS_SIG_MECH(SHA224)
   3063            INIT_RSA_PSS_SIG_MECH(SHA256)
   3064            INIT_RSA_PSS_SIG_MECH(SHA384)
   3065            INIT_RSA_PSS_SIG_MECH(SHA512)
   3066        case CKM_RSA_PKCS_PSS:
   3067        finish_rsa_pss:
   3068            if (key_type != CKK_RSA) {
   3069                crv = CKR_KEY_TYPE_INCONSISTENT;
   3070                break;
   3071            }
   3072            context->rsa = PR_TRUE;
   3073            if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
   3074                !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) {
   3075                crv = CKR_MECHANISM_PARAM_INVALID;
   3076                break;
   3077            }
   3078            pinfo = PORT_New(SFTKPSSSignInfo);
   3079            if (pinfo == NULL) {
   3080                crv = CKR_HOST_MEMORY;
   3081                break;
   3082            }
   3083            pinfo->size = sizeof(SFTKPSSSignInfo);
   3084            pinfo->params = *(CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter;
   3085            pinfo->key = sftk_GetPrivKey(key, CKK_RSA, &crv);
   3086            if (pinfo->key == NULL) {
   3087                crv = CKR_KEY_TYPE_INCONSISTENT;
   3088                break;
   3089            }
   3090            context->cipherInfo = pinfo;
   3091            context->destroy = sftk_ZSpace;
   3092            context->update = sftk_RSASignPSS;
   3093            context->maxLen = nsslowkey_PrivateModulusLen(pinfo->key);
   3094            break;
   3095 
   3096 #ifndef NSS_DISABLE_DSA
   3097 #define INIT_DSA_SIG_MECH(mmm)          \
   3098    case CKM_DSA_##mmm:                 \
   3099        context->multi = PR_TRUE;       \
   3100        crv = sftk_doSub##mmm(context); \
   3101        if (crv != CKR_OK)              \
   3102            break;                      \
   3103        goto finish_dsa;
   3104            INIT_DSA_SIG_MECH(SHA1)
   3105            INIT_DSA_SIG_MECH(SHA224)
   3106            INIT_DSA_SIG_MECH(SHA256)
   3107            INIT_DSA_SIG_MECH(SHA384)
   3108            INIT_DSA_SIG_MECH(SHA512)
   3109        case CKM_DSA:
   3110        finish_dsa:
   3111            if (key_type != CKK_DSA) {
   3112                crv = CKR_KEY_TYPE_INCONSISTENT;
   3113                break;
   3114            }
   3115            privKey = sftk_GetPrivKey(key, CKK_DSA, &crv);
   3116            if (privKey == NULL) {
   3117                break;
   3118            }
   3119            context->cipherInfo = privKey;
   3120            context->update = nsc_DSA_Sign_Stub;
   3121            context->destroy = (privKey == key->objectInfo) ? sftk_Null : sftk_FreePrivKey;
   3122            context->maxLen = DSA_MAX_SIGNATURE_LEN;
   3123 
   3124            break;
   3125 #endif
   3126        case CKM_ML_DSA: {
   3127            /* set our defaults */
   3128            CK_HEDGE_TYPE hedgeType = CKH_HEDGE_PREFERRED;
   3129            SECItem signCtx = { siBuffer, NULL, 0 };
   3130            MLDSAContext *ctptr = NULL;
   3131            SECStatus rv;
   3132 
   3133            /* make sure we have the right key type */
   3134            if (key_type != CKK_ML_DSA) {
   3135                crv = CKR_KEY_TYPE_INCONSISTENT;
   3136                break;
   3137            }
   3138            /* fill in our parameters from the mechanism parameters if
   3139             * supplied */
   3140            if (pMechanism->ulParameterLen != 0) {
   3141                CK_SIGN_ADDITIONAL_CONTEXT *param;
   3142                if (pMechanism->ulParameterLen !=
   3143                    sizeof(CK_SIGN_ADDITIONAL_CONTEXT)) {
   3144                    crv = CKR_MECHANISM_PARAM_INVALID;
   3145                    break;
   3146                }
   3147                param = (CK_SIGN_ADDITIONAL_CONTEXT *)pMechanism->pParameter;
   3148                hedgeType = param->hedgeVariant;
   3149                signCtx.data = param->pContext;
   3150                signCtx.len = param->ulContextLen;
   3151            }
   3152            /* fetch the key */
   3153            privKey = sftk_GetPrivKey(key, key_type, &crv);
   3154            if (privKey == NULL) {
   3155                crv = CKR_HOST_MEMORY;
   3156                break;
   3157            }
   3158            /* now initialize it the signature */
   3159            rv = MLDSA_SignInit(&privKey->u.mldsa, hedgeType, &signCtx, &ctptr);
   3160            if (rv != SECSuccess) {
   3161                crv = sftk_MapCryptError(PORT_GetError());
   3162                if (privKey != key->objectInfo) {
   3163                    nsslowkey_DestroyPrivateKey(privKey);
   3164                }
   3165                break;
   3166            }
   3167            /* set up our cipher info. MLDSA is only a combined hash/sign
   3168             * so the hash update is our sign update, the hash end is a null
   3169             * function returning a zero length value, and the final gets our
   3170             * signature based on the context. Both the cipher context and the
   3171             * hash Info is the same. The MLDSA_SignFinal frees the context,
   3172             * so we don't have to */
   3173            context->multi = PR_TRUE;
   3174            context->cipherInfo = ctptr;
   3175            context->hashInfo = ctptr;
   3176            context->hashUpdate = sftk_MLDSASignUpdate;
   3177            context->end = sftk_NullHashEnd;
   3178            context->hashdestroy = sftk_Null;
   3179            context->destroy = sftk_Null;
   3180            context->update = sftk_MLDSASignFinal;
   3181            context->maxLen = sftk_MLDSAGetSigLen(privKey->u.mldsa.paramSet);
   3182            if (privKey != key->objectInfo) {
   3183                nsslowkey_DestroyPrivateKey(privKey);
   3184            }
   3185            break;
   3186        }
   3187 
   3188 #define INIT_ECDSA_SIG_MECH(mmm)        \
   3189    case CKM_ECDSA_##mmm:               \
   3190        context->multi = PR_TRUE;       \
   3191        crv = sftk_doSub##mmm(context); \
   3192        if (crv != CKR_OK)              \
   3193            break;                      \
   3194        goto finish_ecdsa;
   3195            INIT_ECDSA_SIG_MECH(SHA1)
   3196            INIT_ECDSA_SIG_MECH(SHA224)
   3197            INIT_ECDSA_SIG_MECH(SHA256)
   3198            INIT_ECDSA_SIG_MECH(SHA384)
   3199            INIT_ECDSA_SIG_MECH(SHA512)
   3200        case CKM_ECDSA:
   3201        finish_ecdsa:
   3202            if (key_type != CKK_EC) {
   3203                crv = CKR_KEY_TYPE_INCONSISTENT;
   3204                break;
   3205            }
   3206            privKey = sftk_GetPrivKey(key, CKK_EC, &crv);
   3207            if (privKey == NULL) {
   3208                crv = CKR_HOST_MEMORY;
   3209                break;
   3210            }
   3211            context->cipherInfo = privKey;
   3212            context->update = nsc_ECDSASignStub;
   3213            context->destroy = (privKey == key->objectInfo) ? sftk_Null : sftk_FreePrivKey;
   3214            context->maxLen = MAX_ECKEY_LEN * 2;
   3215 
   3216            break;
   3217 
   3218        case CKM_EDDSA:
   3219            if (key_type != CKK_EC_EDWARDS) {
   3220                crv = CKR_KEY_TYPE_INCONSISTENT;
   3221                break;
   3222            }
   3223 
   3224            if (pMechanism->pParameter) {
   3225                crv = CKR_MECHANISM_PARAM_INVALID;
   3226                break;
   3227            }
   3228 
   3229            privKey = sftk_GetPrivKey(key, CKK_EC_EDWARDS, &crv);
   3230            if (privKey == NULL) {
   3231                crv = CKR_HOST_MEMORY;
   3232                break;
   3233            }
   3234            context->cipherInfo = privKey;
   3235            context->update = nsc_EDDSASignStub;
   3236            context->destroy = (privKey == key->objectInfo) ? sftk_Null : sftk_FreePrivKey;
   3237            context->maxLen = MAX_ECKEY_LEN * 2;
   3238 
   3239            break;
   3240 
   3241 #define INIT_HMAC_MECH(mmm)                                        \
   3242    case CKM_##mmm##_HMAC_GENERAL:                                 \
   3243        PORT_Assert(pMechanism->pParameter);                       \
   3244        if (!pMechanism->pParameter) {                             \
   3245            crv = CKR_MECHANISM_PARAM_INVALID;                     \
   3246            break;                                                 \
   3247        }                                                          \
   3248        crv = sftk_doMACInit(pMechanism->mechanism, context, key,  \
   3249                             *(CK_ULONG *)pMechanism->pParameter); \
   3250        break;                                                     \
   3251    case CKM_##mmm##_HMAC:                                         \
   3252        crv = sftk_doMACInit(pMechanism->mechanism, context, key,  \
   3253                             mmm##_LENGTH);                        \
   3254        break;
   3255 
   3256            INIT_HMAC_MECH(MD2)
   3257            INIT_HMAC_MECH(MD5)
   3258            INIT_HMAC_MECH(SHA1)
   3259            INIT_HMAC_MECH(SHA224)
   3260            INIT_HMAC_MECH(SHA256)
   3261            INIT_HMAC_MECH(SHA384)
   3262            INIT_HMAC_MECH(SHA512)
   3263            INIT_HMAC_MECH(SHA3_224)
   3264            INIT_HMAC_MECH(SHA3_256)
   3265            INIT_HMAC_MECH(SHA3_384)
   3266            INIT_HMAC_MECH(SHA3_512)
   3267 
   3268        case CKM_AES_CMAC_GENERAL:
   3269            PORT_Assert(pMechanism->pParameter);
   3270            if (!pMechanism->pParameter || pMechanism->ulParameterLen != sizeof(CK_MAC_GENERAL_PARAMS)) {
   3271                crv = CKR_MECHANISM_PARAM_INVALID;
   3272                break;
   3273            }
   3274            crv = sftk_doMACInit(pMechanism->mechanism, context, key, *(CK_ULONG *)pMechanism->pParameter);
   3275            break;
   3276        case CKM_AES_CMAC:
   3277            crv = sftk_doMACInit(pMechanism->mechanism, context, key, AES_BLOCK_SIZE);
   3278            break;
   3279        case CKM_SSL3_MD5_MAC:
   3280            PORT_Assert(pMechanism->pParameter);
   3281            if (!pMechanism->pParameter) {
   3282                crv = CKR_MECHANISM_PARAM_INVALID;
   3283                break;
   3284            }
   3285            crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key,
   3286                                    *(CK_ULONG *)pMechanism->pParameter);
   3287            break;
   3288        case CKM_SSL3_SHA1_MAC:
   3289            PORT_Assert(pMechanism->pParameter);
   3290            if (!pMechanism->pParameter) {
   3291                crv = CKR_MECHANISM_PARAM_INVALID;
   3292                break;
   3293            }
   3294            crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key,
   3295                                    *(CK_ULONG *)pMechanism->pParameter);
   3296            break;
   3297        case CKM_TLS_PRF_GENERAL:
   3298            crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0);
   3299            break;
   3300        case CKM_TLS_MAC: {
   3301            CK_TLS_MAC_PARAMS *tls12_mac_params;
   3302            HASH_HashType tlsPrfHash;
   3303            const char *label;
   3304 
   3305            if (pMechanism->ulParameterLen != sizeof(CK_TLS_MAC_PARAMS)) {
   3306                crv = CKR_MECHANISM_PARAM_INVALID;
   3307                break;
   3308            }
   3309            tls12_mac_params = (CK_TLS_MAC_PARAMS *)pMechanism->pParameter;
   3310            if (tls12_mac_params->prfHashMechanism == CKM_TLS_PRF) {
   3311                /* The TLS 1.0 and 1.1 PRF */
   3312                tlsPrfHash = HASH_AlgNULL;
   3313                if (tls12_mac_params->ulMacLength != 12) {
   3314                    crv = CKR_MECHANISM_PARAM_INVALID;
   3315                    break;
   3316                }
   3317            } else {
   3318                /* The hash function for the TLS 1.2 PRF */
   3319                tlsPrfHash =
   3320                    sftk_GetHashTypeFromMechanism(tls12_mac_params->prfHashMechanism);
   3321                if (tlsPrfHash == HASH_AlgNULL ||
   3322                    tls12_mac_params->ulMacLength < 12) {
   3323                    crv = CKR_MECHANISM_PARAM_INVALID;
   3324                    break;
   3325                }
   3326            }
   3327            if (tls12_mac_params->ulServerOrClient == 1) {
   3328                label = "server finished";
   3329            } else if (tls12_mac_params->ulServerOrClient == 2) {
   3330                label = "client finished";
   3331            } else {
   3332                crv = CKR_MECHANISM_PARAM_INVALID;
   3333                break;
   3334            }
   3335            crv = sftk_TLSPRFInit(context, key, key_type, tlsPrfHash,
   3336                                  tls12_mac_params->ulMacLength);
   3337            if (crv == CKR_OK) {
   3338                context->hashUpdate(context->hashInfo, (unsigned char *)label, 15);
   3339            }
   3340            break;
   3341        }
   3342        case CKM_NSS_TLS_PRF_GENERAL_SHA256:
   3343            crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0);
   3344            break;
   3345 
   3346        case CKM_NSS_HMAC_CONSTANT_TIME: {
   3347            sftk_MACConstantTimeCtx *ctx =
   3348                sftk_HMACConstantTime_New(pMechanism, key);
   3349            CK_ULONG *intpointer;
   3350 
   3351            if (ctx == NULL) {
   3352                crv = CKR_ARGUMENTS_BAD;
   3353                break;
   3354            }
   3355            intpointer = PORT_New(CK_ULONG);
   3356            if (intpointer == NULL) {
   3357                PORT_Free(ctx);
   3358                crv = CKR_HOST_MEMORY;
   3359                break;
   3360            }
   3361            *intpointer = ctx->hash->length;
   3362 
   3363            context->cipherInfo = intpointer;
   3364            context->hashInfo = ctx;
   3365            context->currentMech = pMechanism->mechanism;
   3366            context->hashUpdate = sftk_HMACConstantTime_Update;
   3367            context->hashdestroy = sftk_MACConstantTime_DestroyContext;
   3368            context->end = sftk_MACConstantTime_EndHash;
   3369            context->update = sftk_SignCopy;
   3370            context->destroy = sftk_Space;
   3371            context->maxLen = 64;
   3372            context->multi = PR_TRUE;
   3373            break;
   3374        }
   3375 
   3376        case CKM_NSS_SSL3_MAC_CONSTANT_TIME: {
   3377            sftk_MACConstantTimeCtx *ctx =
   3378                sftk_SSLv3MACConstantTime_New(pMechanism, key);
   3379            CK_ULONG *intpointer;
   3380 
   3381            if (ctx == NULL) {
   3382                crv = CKR_ARGUMENTS_BAD;
   3383                break;
   3384            }
   3385            intpointer = PORT_New(CK_ULONG);
   3386            if (intpointer == NULL) {
   3387                PORT_Free(ctx);
   3388                crv = CKR_HOST_MEMORY;
   3389                break;
   3390            }
   3391            *intpointer = ctx->hash->length;
   3392 
   3393            context->cipherInfo = intpointer;
   3394            context->hashInfo = ctx;
   3395            context->currentMech = pMechanism->mechanism;
   3396            context->hashUpdate = sftk_SSLv3MACConstantTime_Update;
   3397            context->hashdestroy = sftk_MACConstantTime_DestroyContext;
   3398            context->end = sftk_MACConstantTime_EndHash;
   3399            context->update = sftk_SignCopy;
   3400            context->destroy = sftk_Space;
   3401            context->maxLen = 64;
   3402            context->multi = PR_TRUE;
   3403            break;
   3404        }
   3405 
   3406        default:
   3407            crv = CKR_MECHANISM_INVALID;
   3408            break;
   3409    }
   3410 
   3411    if (crv != CKR_OK) {
   3412        if (info)
   3413            PORT_Free(info);
   3414        if (pinfo)
   3415            PORT_ZFree(pinfo, pinfo->size);
   3416        sftk_FreeContext(context);
   3417        sftk_FreeSession(session);
   3418        return crv;
   3419    }
   3420    sftk_SetContextByType(session, SFTK_SIGN, context);
   3421    sftk_FreeSession(session);
   3422    return CKR_OK;
   3423 }
   3424 
   3425 /** MAC one block of data by block cipher
   3426 */
   3427 static CK_RV
   3428 sftk_MACBlock(SFTKSessionContext *ctx, void *blk)
   3429 {
   3430    unsigned int outlen;
   3431    return (SECSuccess == (ctx->update)(ctx->cipherInfo, ctx->macBuf, &outlen,
   3432                                        SFTK_MAX_BLOCK_SIZE, blk, ctx->blockSize))
   3433               ? CKR_OK
   3434               : sftk_MapCryptError(PORT_GetError());
   3435 }
   3436 
   3437 /** MAC last (incomplete) block of data by block cipher
   3438 *
   3439 *  Call once, then terminate MACing operation.
   3440 */
   3441 static CK_RV
   3442 sftk_MACFinal(SFTKSessionContext *ctx)
   3443 {
   3444    unsigned int padLen = ctx->padDataLength;
   3445    /* pad and proceed the residual */
   3446    if (ctx->isXCBC) {
   3447        CK_RV crv = sftk_xcbc_mac_pad(ctx->padBuf, padLen, ctx->blockSize,
   3448                                      ctx->k2, ctx->k3);
   3449        if (crv != CKR_OK)
   3450            return crv;
   3451        return sftk_MACBlock(ctx, ctx->padBuf);
   3452    }
   3453    if (padLen) {
   3454        /* shd clr ctx->padLen to make sftk_MACFinal idempotent */
   3455        PORT_Memset(ctx->padBuf + padLen, 0, ctx->blockSize - padLen);
   3456        return sftk_MACBlock(ctx, ctx->padBuf);
   3457    } else
   3458        return CKR_OK;
   3459 }
   3460 
   3461 /** The common implementation for {Sign,Verify}Update. (S/V only vary in their
   3462 * setup and final operations).
   3463 *
   3464 * A call which results in an error terminates the operation [PKCS#11,v2.11]
   3465 */
   3466 static CK_RV
   3467 sftk_MACUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
   3468               CK_ULONG ulPartLen, SFTKContextType type)
   3469 {
   3470    SFTKSession *session;
   3471    SFTKSessionContext *context;
   3472    CK_RV crv;
   3473 
   3474    /* make sure we're legal */
   3475    crv = sftk_GetContext(hSession, &context, type, PR_TRUE, &session);
   3476    if (crv != CKR_OK)
   3477        return crv;
   3478 
   3479    if (context->hashInfo) {
   3480 #if (ULONG_MAX > UINT_MAX)
   3481        while (ulPartLen > UINT_MAX) {
   3482            (*context->hashUpdate)(context->cipherInfo, pPart, UINT_MAX);
   3483            pPart += UINT_MAX;
   3484            ulPartLen -= UINT_MAX;
   3485        }
   3486 #endif
   3487        (*context->hashUpdate)(context->hashInfo, pPart, ulPartLen);
   3488    } else {
   3489        /* must be block cipher MACing */
   3490 
   3491        unsigned int blkSize = context->blockSize;
   3492        unsigned char *residual = /* free room in context->padBuf */
   3493            context->padBuf + context->padDataLength;
   3494        unsigned int minInput = /* min input for MACing at least one block */
   3495            blkSize - context->padDataLength;
   3496 
   3497        /* not enough data even for one block */
   3498        if (ulPartLen <= minInput) {
   3499            PORT_Memcpy(residual, pPart, ulPartLen);
   3500            context->padDataLength += ulPartLen;
   3501            goto cleanup;
   3502        }
   3503        /* MACing residual */
   3504        if (context->padDataLength) {
   3505            PORT_Memcpy(residual, pPart, minInput);
   3506            ulPartLen -= minInput;
   3507            pPart += minInput;
   3508            if (CKR_OK != (crv = sftk_MACBlock(context, context->padBuf)))
   3509                goto terminate;
   3510        }
   3511        /* MACing full blocks */
   3512        while (ulPartLen > blkSize) {
   3513            if (CKR_OK != (crv = sftk_MACBlock(context, pPart)))
   3514                goto terminate;
   3515            ulPartLen -= blkSize;
   3516            pPart += blkSize;
   3517        }
   3518        /* save the residual */
   3519        if ((context->padDataLength = ulPartLen))
   3520            PORT_Memcpy(context->padBuf, pPart, ulPartLen);
   3521    } /* blk cipher MACing */
   3522 
   3523    goto cleanup;
   3524 
   3525 terminate:
   3526    sftk_TerminateOp(session, type, context);
   3527 cleanup:
   3528    sftk_FreeSession(session);
   3529    return crv;
   3530 }
   3531 
   3532 /* NSC_SignUpdate continues a multiple-part signature operation,
   3533 * where the signature is (will be) an appendix to the data,
   3534 * and plaintext cannot be recovered from the signature
   3535 *
   3536 * A call which results in an error terminates the operation [PKCS#11,v2.11]
   3537 */
   3538 CK_RV
   3539 NSC_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
   3540               CK_ULONG ulPartLen)
   3541 {
   3542    CHECK_FORK();
   3543    return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_SIGN);
   3544 }
   3545 
   3546 struct SFTK_SESSION_FLAGS {
   3547    CK_FLAGS flag;
   3548    SFTKContextType type;
   3549 };
   3550 
   3551 const static struct SFTK_SESSION_FLAGS sftk_session_flags[] = {
   3552    { CKF_ENCRYPT, SFTK_ENCRYPT },
   3553    { CKF_DECRYPT, SFTK_DECRYPT },
   3554    { CKF_DIGEST, SFTK_HASH },
   3555    { CKF_SIGN, SFTK_SIGN },
   3556    { CKF_SIGN_RECOVER, SFTK_SIGN_RECOVER },
   3557    { CKF_VERIFY, SFTK_VERIFY },
   3558    { CKF_VERIFY_RECOVER, SFTK_VERIFY_RECOVER },
   3559    { CKF_MESSAGE_ENCRYPT, SFTK_MESSAGE_ENCRYPT },
   3560    { CKF_MESSAGE_DECRYPT, SFTK_MESSAGE_DECRYPT },
   3561    { CKF_MESSAGE_SIGN, SFTK_MESSAGE_SIGN },
   3562    { CKF_MESSAGE_VERIFY, SFTK_MESSAGE_VERIFY },
   3563 };
   3564 const static int sftk_flag_count = PR_ARRAY_SIZE(sftk_session_flags);
   3565 
   3566 /*
   3567 * Cancel one or more operations running on the existing session.
   3568 */
   3569 CK_RV
   3570 NSC_SessionCancel(CK_SESSION_HANDLE hSession, CK_FLAGS flags)
   3571 {
   3572    SFTKSession *session;
   3573    SFTKSessionContext *context;
   3574    CK_RV gcrv = CKR_OK;
   3575    CK_RV crv;
   3576    int i;
   3577 
   3578    for (i = 0; i < sftk_flag_count; i++) {
   3579        if (flags & sftk_session_flags[i].flag) {
   3580            flags &= ~sftk_session_flags[i].flag;
   3581            crv = sftk_GetContext(hSession, &context, sftk_session_flags[i].type, PR_TRUE, &session);
   3582            if (crv != CKR_OK) {
   3583                gcrv = CKR_OPERATION_CANCEL_FAILED;
   3584                continue;
   3585            }
   3586            sftk_TerminateOp(session, sftk_session_flags[i].type, context);
   3587        }
   3588    }
   3589    if (flags & CKF_FIND_OBJECTS) {
   3590        flags &= ~CKF_FIND_OBJECTS;
   3591        crv = NSC_FindObjectsFinal(hSession);
   3592        if (crv != CKR_OK) {
   3593            gcrv = CKR_OPERATION_CANCEL_FAILED;
   3594        }
   3595    }
   3596    if (flags) {
   3597        gcrv = CKR_OPERATION_CANCEL_FAILED;
   3598    }
   3599    return gcrv;
   3600 }
   3601 
   3602 /* NSC_SignFinal finishes a multiple-part signature operation,
   3603 * returning the signature. */
   3604 CK_RV
   3605 NSC_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
   3606              CK_ULONG_PTR pulSignatureLen)
   3607 {
   3608    SFTKSession *session;
   3609    SFTKSessionContext *context;
   3610    unsigned int outlen;
   3611    unsigned int maxoutlen = *pulSignatureLen;
   3612    CK_RV crv;
   3613 
   3614    CHECK_FORK();
   3615 
   3616    /* make sure we're legal */
   3617    crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_TRUE, &session);
   3618    if (crv != CKR_OK)
   3619        return crv;
   3620 
   3621    if (context->hashInfo) {
   3622        unsigned int digestLen;
   3623        unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH];
   3624 
   3625        if (!pSignature) {
   3626            outlen = context->maxLen;
   3627            goto finish;
   3628        }
   3629        (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
   3630        if (SECSuccess != (context->update)(context->cipherInfo, pSignature,
   3631                                            &outlen, maxoutlen, tmpbuf, digestLen))
   3632            crv = sftk_MapCryptError(PORT_GetError());
   3633        /* CKR_BUFFER_TOO_SMALL here isn't continuable, let operation terminate.
   3634         * Keeping "too small" CK_RV intact is a standard violation, but allows
   3635         * application read EXACT signature length */
   3636        PORT_Memset(tmpbuf, 0, sizeof tmpbuf);
   3637    } else {
   3638        /* must be block cipher MACing */
   3639        outlen = context->macSize;
   3640        /* null or "too small" buf doesn't terminate operation [PKCS#11,v2.11]*/
   3641        if (!pSignature || maxoutlen < outlen) {
   3642            if (pSignature)
   3643                crv = CKR_BUFFER_TOO_SMALL;
   3644            goto finish;
   3645        }
   3646        if (CKR_OK == (crv = sftk_MACFinal(context)))
   3647            PORT_Memcpy(pSignature, context->macBuf, outlen);
   3648    }
   3649 
   3650    sftk_TerminateOp(session, SFTK_SIGN, context);
   3651 finish:
   3652    *pulSignatureLen = outlen;
   3653    sftk_FreeSession(session);
   3654    return crv;
   3655 }
   3656 
   3657 /* NSC_Sign signs (encrypts with private key) data in a single part,
   3658 * where the signature is (will be) an appendix to the data,
   3659 * and plaintext cannot be recovered from the signature */
   3660 CK_RV
   3661 NSC_Sign(CK_SESSION_HANDLE hSession,
   3662         CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
   3663         CK_ULONG_PTR pulSignatureLen)
   3664 {
   3665    SFTKSession *session;
   3666    SFTKSessionContext *context;
   3667    CK_RV crv;
   3668 
   3669    CHECK_FORK();
   3670 
   3671    /* make sure we're legal */
   3672    crv = sftk_GetContext(hSession, &context, SFTK_SIGN, PR_FALSE, &session);
   3673    if (crv != CKR_OK)
   3674        return crv;
   3675 
   3676    if (!pSignature) {
   3677        /* see also how C_SignUpdate implements this */
   3678        *pulSignatureLen = (!context->multi || context->hashInfo)
   3679                               ? context->maxLen
   3680                               : context->macSize; /* must be block cipher MACing */
   3681        goto finish;
   3682    }
   3683 
   3684    /* multi part Signing are completely implemented by SignUpdate and
   3685     * sign Final */
   3686    if (context->multi) {
   3687        /* SignFinal can't follow failed SignUpdate */
   3688        if (CKR_OK == (crv = NSC_SignUpdate(hSession, pData, ulDataLen)))
   3689            crv = NSC_SignFinal(hSession, pSignature, pulSignatureLen);
   3690    } else {
   3691        /* single-part PKC signature (e.g. CKM_ECDSA) */
   3692        unsigned int outlen;
   3693        unsigned int maxoutlen = *pulSignatureLen;
   3694        if (SECSuccess != (*context->update)(context->cipherInfo, pSignature,
   3695                                             &outlen, maxoutlen, pData, ulDataLen))
   3696            crv = sftk_MapCryptError(PORT_GetError());
   3697        *pulSignatureLen = (CK_ULONG)outlen;
   3698        /*  "too small" here is certainly continuable */
   3699        if (crv != CKR_BUFFER_TOO_SMALL)
   3700            sftk_TerminateOp(session, SFTK_SIGN, context);
   3701    } /* single-part */
   3702 
   3703 finish:
   3704    sftk_FreeSession(session);
   3705    return crv;
   3706 }
   3707 
   3708 /*
   3709 ************** Crypto Functions:     Sign Recover  ************************
   3710 */
   3711 /* NSC_SignRecoverInit initializes a signature operation,
   3712 * where the (digest) data can be recovered from the signature.
   3713 * E.g. encryption with the user's private key */
   3714 CK_RV
   3715 NSC_SignRecoverInit(CK_SESSION_HANDLE hSession,
   3716                    CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
   3717 {
   3718    CHECK_FORK();
   3719 
   3720    switch (pMechanism->mechanism) {
   3721        case CKM_RSA_PKCS:
   3722        case CKM_RSA_X_509:
   3723            return NSC_SignInit(hSession, pMechanism, hKey);
   3724        default:
   3725            break;
   3726    }
   3727    return CKR_MECHANISM_INVALID;
   3728 }
   3729 
   3730 /* NSC_SignRecover signs data in a single operation
   3731 * where the (digest) data can be recovered from the signature.
   3732 * E.g. encryption with the user's private key */
   3733 CK_RV
   3734 NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
   3735                CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
   3736 {
   3737    CHECK_FORK();
   3738 
   3739    return NSC_Sign(hSession, pData, ulDataLen, pSignature, pulSignatureLen);
   3740 }
   3741 
   3742 /*
   3743 ************** Crypto Functions:     verify  ************************
   3744 */
   3745 
   3746 /* Handle RSA Signature formatting */
   3747 static SECStatus
   3748 sftk_hashCheckSign(void *ctx, const unsigned char *sig,
   3749                   unsigned int sigLen, const unsigned char *digest,
   3750                   unsigned int digestLen)
   3751 {
   3752    SFTKHashVerifyInfo *info = ctx;
   3753    PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
   3754    if (info->key->keyType != NSSLOWKEYRSAKey) {
   3755        PORT_SetError(SEC_ERROR_INVALID_KEY);
   3756        return SECFailure;
   3757    }
   3758 
   3759    return RSA_HashCheckSign(info->hashOid, info->key, sig, sigLen, digest,
   3760                             digestLen);
   3761 }
   3762 
   3763 SECStatus
   3764 RSA_HashCheckSign(SECOidTag digestOid, NSSLOWKEYPublicKey *key,
   3765                  const unsigned char *sig, unsigned int sigLen,
   3766                  const unsigned char *digestData, unsigned int digestLen)
   3767 {
   3768    unsigned char *pkcs1DigestInfoData;
   3769    SECItem pkcs1DigestInfo;
   3770    SECItem digest;
   3771    unsigned int bufferSize;
   3772    SECStatus rv;
   3773 
   3774    /* pkcs1DigestInfo.data must be less than key->u.rsa.modulus.len */
   3775    bufferSize = key->u.rsa.modulus.len;
   3776    pkcs1DigestInfoData = PORT_ZAlloc(bufferSize);
   3777    if (!pkcs1DigestInfoData) {
   3778        PORT_SetError(SEC_ERROR_NO_MEMORY);
   3779        return SECFailure;
   3780    }
   3781 
   3782    pkcs1DigestInfo.data = pkcs1DigestInfoData;
   3783    pkcs1DigestInfo.len = bufferSize;
   3784 
   3785    /* decrypt the block */
   3786    rv = RSA_CheckSignRecover(&key->u.rsa, pkcs1DigestInfo.data,
   3787                              &pkcs1DigestInfo.len, pkcs1DigestInfo.len,
   3788                              sig, sigLen);
   3789    if (rv != SECSuccess) {
   3790        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
   3791    } else {
   3792        digest.data = (PRUint8 *)digestData;
   3793        digest.len = digestLen;
   3794        rv = _SGN_VerifyPKCS1DigestInfo(
   3795            digestOid, &digest, &pkcs1DigestInfo,
   3796            PR_FALSE /*XXX: unsafeAllowMissingParameters*/);
   3797    }
   3798 
   3799    PORT_ZFree(pkcs1DigestInfoData, bufferSize);
   3800    return rv;
   3801 }
   3802 
   3803 static SECStatus
   3804 sftk_RSACheckSign(void *ctx, const unsigned char *sig,
   3805                  unsigned int sigLen, const unsigned char *digest,
   3806                  unsigned int digestLen)
   3807 {
   3808    NSSLOWKEYPublicKey *key = ctx;
   3809    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
   3810    if (key->keyType != NSSLOWKEYRSAKey) {
   3811        PORT_SetError(SEC_ERROR_INVALID_KEY);
   3812        return SECFailure;
   3813    }
   3814 
   3815    return RSA_CheckSign(&key->u.rsa, sig, sigLen, digest, digestLen);
   3816 }
   3817 
   3818 static SECStatus
   3819 sftk_RSACheckSignRaw(void *ctx, const unsigned char *sig,
   3820                     unsigned int sigLen, const unsigned char *digest,
   3821                     unsigned int digestLen)
   3822 {
   3823    NSSLOWKEYPublicKey *key = ctx;
   3824    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
   3825    if (key->keyType != NSSLOWKEYRSAKey) {
   3826        PORT_SetError(SEC_ERROR_INVALID_KEY);
   3827        return SECFailure;
   3828    }
   3829 
   3830    return RSA_CheckSignRaw(&key->u.rsa, sig, sigLen, digest, digestLen);
   3831 }
   3832 
   3833 static SECStatus
   3834 sftk_RSACheckSignPSS(void *ctx, const unsigned char *sig,
   3835                     unsigned int sigLen, const unsigned char *digest,
   3836                     unsigned int digestLen)
   3837 {
   3838    SFTKPSSVerifyInfo *info = ctx;
   3839    HASH_HashType hashAlg;
   3840    HASH_HashType maskHashAlg;
   3841    CK_RSA_PKCS_PSS_PARAMS *params = &info->params;
   3842 
   3843    PORT_Assert(info->key->keyType == NSSLOWKEYRSAKey);
   3844    if (info->key->keyType != NSSLOWKEYRSAKey) {
   3845        PORT_SetError(SEC_ERROR_INVALID_KEY);
   3846        return SECFailure;
   3847    }
   3848 
   3849    hashAlg = sftk_GetHashTypeFromMechanism(params->hashAlg);
   3850    maskHashAlg = sftk_GetHashTypeFromMechanism(params->mgf);
   3851 
   3852    return RSA_CheckSignPSS(&info->key->u.rsa, hashAlg, maskHashAlg,
   3853                            params->sLen, sig, sigLen, digest, digestLen);
   3854 }
   3855 
   3856 /* NSC_VerifyInit initializes a verification operation,
   3857 * where the signature is an appendix to the data,
   3858 * and plaintext cannot be recovered from the signature (e.g. DSA) */
   3859 CK_RV
   3860 NSC_VerifyInit(CK_SESSION_HANDLE hSession,
   3861               CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
   3862 {
   3863    SFTKSession *session;
   3864    SFTKObject *key;
   3865    SFTKSessionContext *context;
   3866    CK_KEY_TYPE key_type;
   3867    CK_RV crv = CKR_OK;
   3868    NSSLOWKEYPublicKey *pubKey;
   3869    SFTKHashVerifyInfo *info = NULL;
   3870    SFTKPSSVerifyInfo *pinfo = NULL;
   3871 
   3872    CHECK_FORK();
   3873 
   3874    /* Block Cipher MACing Algorithms use a different Context init method..*/
   3875    crv = sftk_InitCBCMac(hSession, pMechanism, hKey, CKA_VERIFY, SFTK_VERIFY);
   3876    if (crv != CKR_FUNCTION_NOT_SUPPORTED)
   3877        return crv;
   3878 
   3879    session = sftk_SessionFromHandle(hSession);
   3880    if (session == NULL)
   3881        return CKR_SESSION_HANDLE_INVALID;
   3882    crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY, &key,
   3883                           hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY);
   3884    if (crv != CKR_OK) {
   3885        sftk_FreeSession(session);
   3886        return crv;
   3887    }
   3888 
   3889    context->multi = PR_FALSE;
   3890 
   3891 #define INIT_RSA_VFY_MECH(mmm)                \
   3892    case CKM_##mmm##_RSA_PKCS:                \
   3893        context->multi = PR_TRUE;             \
   3894        crv = sftk_doSub##mmm(context);       \
   3895        if (crv != CKR_OK)                    \
   3896            break;                            \
   3897        context->verify = sftk_hashCheckSign; \
   3898        info = PORT_New(SFTKHashVerifyInfo);  \
   3899        if (info == NULL) {                   \
   3900            crv = CKR_HOST_MEMORY;            \
   3901            break;                            \
   3902        }                                     \
   3903        info->hashOid = SEC_OID_##mmm;        \
   3904        goto finish_rsa;
   3905 
   3906    switch (pMechanism->mechanism) {
   3907        INIT_RSA_VFY_MECH(MD5)
   3908        INIT_RSA_VFY_MECH(MD2)
   3909        INIT_RSA_VFY_MECH(SHA1)
   3910        INIT_RSA_VFY_MECH(SHA224)
   3911        INIT_RSA_VFY_MECH(SHA256)
   3912        INIT_RSA_VFY_MECH(SHA384)
   3913        INIT_RSA_VFY_MECH(SHA512)
   3914 
   3915        case CKM_RSA_PKCS:
   3916            context->verify = sftk_RSACheckSign;
   3917            goto finish_rsa;
   3918        case CKM_RSA_X_509:
   3919            context->verify = sftk_RSACheckSignRaw;
   3920        finish_rsa:
   3921            if (key_type != CKK_RSA) {
   3922                crv = CKR_KEY_TYPE_INCONSISTENT;
   3923                break;
   3924            }
   3925            context->rsa = PR_TRUE;
   3926            pubKey = sftk_GetPubKey(key, CKK_RSA, &crv);
   3927            if (pubKey == NULL) {
   3928                crv = CKR_KEY_TYPE_INCONSISTENT;
   3929                break;
   3930            }
   3931            if (info) {
   3932                info->key = pubKey;
   3933                context->cipherInfo = info;
   3934                context->destroy = sftk_Space;
   3935            } else {
   3936                context->cipherInfo = pubKey;
   3937                context->destroy = sftk_Null;
   3938            }
   3939            break;
   3940 
   3941            INIT_RSA_PSS_SIG_MECH(SHA1)
   3942            INIT_RSA_PSS_SIG_MECH(SHA224)
   3943            INIT_RSA_PSS_SIG_MECH(SHA256)
   3944            INIT_RSA_PSS_SIG_MECH(SHA384)
   3945            INIT_RSA_PSS_SIG_MECH(SHA512)
   3946        case CKM_RSA_PKCS_PSS:
   3947        finish_rsa_pss:
   3948            if (key_type != CKK_RSA) {
   3949                crv = CKR_KEY_TYPE_INCONSISTENT;
   3950                break;
   3951            }
   3952            context->rsa = PR_TRUE;
   3953            if (pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
   3954                !sftk_ValidatePssParams((const CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter)) {
   3955                crv = CKR_MECHANISM_PARAM_INVALID;
   3956                break;
   3957            }
   3958            pinfo = PORT_New(SFTKPSSVerifyInfo);
   3959            if (pinfo == NULL) {
   3960                crv = CKR_HOST_MEMORY;
   3961                break;
   3962            }
   3963            pinfo->size = sizeof(SFTKPSSVerifyInfo);
   3964            pinfo->params = *(CK_RSA_PKCS_PSS_PARAMS *)pMechanism->pParameter;
   3965            pinfo->key = sftk_GetPubKey(key, CKK_RSA, &crv);
   3966            if (pinfo->key == NULL) {
   3967                crv = CKR_KEY_TYPE_INCONSISTENT;
   3968                break;
   3969            }
   3970            context->cipherInfo = pinfo;
   3971            context->destroy = sftk_ZSpace;
   3972            context->verify = sftk_RSACheckSignPSS;
   3973            break;
   3974 
   3975 #ifndef NSS_DISABLE_DSA
   3976            INIT_DSA_SIG_MECH(SHA1)
   3977            INIT_DSA_SIG_MECH(SHA224)
   3978            INIT_DSA_SIG_MECH(SHA256)
   3979            INIT_DSA_SIG_MECH(SHA384)
   3980            INIT_DSA_SIG_MECH(SHA512)
   3981        case CKM_DSA:
   3982        finish_dsa:
   3983            if (key_type != CKK_DSA) {
   3984                crv = CKR_KEY_TYPE_INCONSISTENT;
   3985                break;
   3986            }
   3987            pubKey = sftk_GetPubKey(key, CKK_DSA, &crv);
   3988            if (pubKey == NULL) {
   3989                break;
   3990            }
   3991            context->cipherInfo = pubKey;
   3992            context->verify = nsc_DSA_Verify_Stub;
   3993            context->destroy = sftk_Null;
   3994            break;
   3995 #endif
   3996        case CKM_ML_DSA: {
   3997            /* set our defaults */
   3998            SECItem signCtx = { siBuffer, NULL, 0 };
   3999            MLDSAContext *ctptr = NULL;
   4000            SECStatus rv;
   4001 
   4002            /* make sure we have the right key type */
   4003            if (key_type != CKK_ML_DSA) {
   4004                crv = CKR_KEY_TYPE_INCONSISTENT;
   4005                break;
   4006            }
   4007            /* fill in our parameters from the mechanism parameters if
   4008             * supplied */
   4009            if (pMechanism->ulParameterLen != 0) {
   4010                CK_SIGN_ADDITIONAL_CONTEXT *param;
   4011                if (pMechanism->ulParameterLen !=
   4012                    sizeof(CK_SIGN_ADDITIONAL_CONTEXT)) {
   4013                    crv = CKR_MECHANISM_PARAM_INVALID;
   4014                    break;
   4015                }
   4016                param = (CK_SIGN_ADDITIONAL_CONTEXT *)pMechanism->pParameter;
   4017                signCtx.data = param->pContext;
   4018                signCtx.len = param->ulContextLen;
   4019            }
   4020            /* fetch the key */
   4021            pubKey = sftk_GetPubKey(key, key_type, &crv);
   4022            if (pubKey == NULL) {
   4023                /* crv already set */
   4024                break;
   4025            }
   4026            /* now initialize it the signature */
   4027            rv = MLDSA_VerifyInit(&(pubKey->u.mldsa), &signCtx, &ctptr);
   4028            if (rv != SECSuccess) {
   4029                crv = sftk_MapVerifyError(PORT_GetError());
   4030                break;
   4031            }
   4032            /* set up our cipher info. MLDSA is only a combined hash/sign
   4033             * so the hash update is our sign update, the hash end is a null
   4034             * function returning a zero length value, and the final gets our
   4035             * signature based on the context. Both the cipher context and the
   4036             * hash Info is the same. The MLDSA_VerifyFinal frees the context,
   4037             * so we don't have to */
   4038            context->multi = PR_TRUE;
   4039            context->cipherInfo = ctptr;
   4040            context->hashInfo = ctptr;
   4041            context->hashUpdate = sftk_MLDSAVerifyUpdate;
   4042            context->end = sftk_NullHashEnd;
   4043            context->hashdestroy = sftk_Null;
   4044            context->destroy = sftk_Null;
   4045            context->verify = sftk_MLDSAVerifyFinal;
   4046            context->maxLen = sftk_MLDSAGetSigLen(pubKey->u.mldsa.paramSet);
   4047            break;
   4048        }
   4049 
   4050            INIT_ECDSA_SIG_MECH(SHA1)
   4051            INIT_ECDSA_SIG_MECH(SHA224)
   4052            INIT_ECDSA_SIG_MECH(SHA256)
   4053            INIT_ECDSA_SIG_MECH(SHA384)
   4054            INIT_ECDSA_SIG_MECH(SHA512)
   4055        case CKM_ECDSA:
   4056        finish_ecdsa:
   4057            if (key_type != CKK_EC) {
   4058                crv = CKR_KEY_TYPE_INCONSISTENT;
   4059                break;
   4060            }
   4061            pubKey = sftk_GetPubKey(key, CKK_EC, &crv);
   4062            if (pubKey == NULL) {
   4063                crv = CKR_HOST_MEMORY;
   4064                break;
   4065            }
   4066            context->cipherInfo = pubKey;
   4067            context->verify = nsc_ECDSAVerifyStub;
   4068            context->destroy = sftk_Null;
   4069            break;
   4070 
   4071            INIT_HMAC_MECH(MD2)
   4072            INIT_HMAC_MECH(MD5)
   4073            INIT_HMAC_MECH(SHA1)
   4074            INIT_HMAC_MECH(SHA224)
   4075            INIT_HMAC_MECH(SHA256)
   4076            INIT_HMAC_MECH(SHA384)
   4077            INIT_HMAC_MECH(SHA512)
   4078            INIT_HMAC_MECH(SHA3_224)
   4079            INIT_HMAC_MECH(SHA3_256)
   4080            INIT_HMAC_MECH(SHA3_384)
   4081            INIT_HMAC_MECH(SHA3_512)
   4082 
   4083        case CKM_EDDSA:
   4084            if (key_type != CKK_EC_EDWARDS) {
   4085                crv = CKR_KEY_TYPE_INCONSISTENT;
   4086                break;
   4087            }
   4088            pubKey = sftk_GetPubKey(key, CKK_EC_EDWARDS, &crv);
   4089            if (pubKey == NULL) {
   4090                crv = CKR_HOST_MEMORY;
   4091                break;
   4092            }
   4093 
   4094            if (pMechanism->pParameter) {
   4095                crv = CKR_FUNCTION_NOT_SUPPORTED;
   4096                break;
   4097            }
   4098 
   4099            context->cipherInfo = pubKey;
   4100            context->verify = nsc_EDDSAVerifyStub;
   4101            context->destroy = sftk_Null;
   4102            break;
   4103 
   4104        case CKM_SSL3_MD5_MAC:
   4105            PORT_Assert(pMechanism->pParameter);
   4106            if (!pMechanism->pParameter) {
   4107                crv = CKR_MECHANISM_PARAM_INVALID;
   4108                break;
   4109            }
   4110            crv = sftk_doSSLMACInit(context, SEC_OID_MD5, key,
   4111                                    *(CK_ULONG *)pMechanism->pParameter);
   4112            break;
   4113        case CKM_SSL3_SHA1_MAC:
   4114            PORT_Assert(pMechanism->pParameter);
   4115            if (!pMechanism->pParameter) {
   4116                crv = CKR_MECHANISM_PARAM_INVALID;
   4117                break;
   4118            }
   4119            crv = sftk_doSSLMACInit(context, SEC_OID_SHA1, key,
   4120                                    *(CK_ULONG *)pMechanism->pParameter);
   4121            break;
   4122        case CKM_TLS_PRF_GENERAL:
   4123            crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgNULL, 0);
   4124            break;
   4125        case CKM_NSS_TLS_PRF_GENERAL_SHA256:
   4126            crv = sftk_TLSPRFInit(context, key, key_type, HASH_AlgSHA256, 0);
   4127            break;
   4128 
   4129        default:
   4130            crv = CKR_MECHANISM_INVALID;
   4131            break;
   4132    }
   4133 
   4134    if (crv != CKR_OK) {
   4135        if (info)
   4136            PORT_Free(info);
   4137        if (pinfo)
   4138            PORT_ZFree(pinfo, pinfo->size);
   4139        sftk_FreeContext(context);
   4140        sftk_FreeSession(session);
   4141        return crv;
   4142    }
   4143    sftk_SetContextByType(session, SFTK_VERIFY, context);
   4144    sftk_FreeSession(session);
   4145    return CKR_OK;
   4146 }
   4147 
   4148 /* NSC_Verify verifies a signature in a single-part operation,
   4149 * where the signature is an appendix to the data,
   4150 * and plaintext cannot be recovered from the signature */
   4151 CK_RV
   4152 NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
   4153           CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
   4154 {
   4155    SFTKSession *session;
   4156    SFTKSessionContext *context;
   4157    CK_RV crv;
   4158 
   4159    CHECK_FORK();
   4160 
   4161    /* make sure we're legal */
   4162    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_FALSE, &session);
   4163    if (crv != CKR_OK)
   4164        return crv;
   4165 
   4166    /* multi part Verifying are completely implemented by VerifyUpdate and
   4167     * VerifyFinal */
   4168    if (context->multi) {
   4169        /* VerifyFinal can't follow failed VerifyUpdate */
   4170        if (CKR_OK == (crv = NSC_VerifyUpdate(hSession, pData, ulDataLen)))
   4171            crv = NSC_VerifyFinal(hSession, pSignature, ulSignatureLen);
   4172    } else {
   4173        if (SECSuccess != (*context->verify)(context->cipherInfo, pSignature,
   4174                                             ulSignatureLen, pData, ulDataLen))
   4175            crv = sftk_MapCryptError(PORT_GetError());
   4176 
   4177        sftk_TerminateOp(session, SFTK_VERIFY, context);
   4178    }
   4179    sftk_FreeSession(session);
   4180    return crv;
   4181 }
   4182 
   4183 /* NSC_VerifyUpdate continues a multiple-part verification operation,
   4184 * where the signature is an appendix to the data,
   4185 * and plaintext cannot be recovered from the signature
   4186 *
   4187 * A call which results in an error terminates the operation [PKCS#11,v2.11]
   4188 */
   4189 CK_RV
   4190 NSC_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
   4191                 CK_ULONG ulPartLen)
   4192 {
   4193    CHECK_FORK();
   4194    return sftk_MACUpdate(hSession, pPart, ulPartLen, SFTK_VERIFY);
   4195 }
   4196 
   4197 /* NSC_VerifyFinal finishes a multiple-part verification operation,
   4198 * checking the signature. */
   4199 CK_RV
   4200 NSC_VerifyFinal(CK_SESSION_HANDLE hSession,
   4201                CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
   4202 {
   4203    SFTKSession *session;
   4204    SFTKSessionContext *context;
   4205    CK_RV crv;
   4206 
   4207    CHECK_FORK();
   4208 
   4209    if (!pSignature)
   4210        return CKR_ARGUMENTS_BAD;
   4211 
   4212    /* make sure we're legal */
   4213    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_TRUE, &session);
   4214    if (crv != CKR_OK)
   4215        return crv;
   4216 
   4217    if (context->hashInfo) {
   4218        unsigned int digestLen;
   4219        unsigned char tmpbuf[SFTK_MAX_MAC_LENGTH];
   4220 
   4221        (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
   4222        if (SECSuccess != (context->verify)(context->cipherInfo, pSignature,
   4223                                            ulSignatureLen, tmpbuf, digestLen))
   4224            crv = sftk_MapCryptError(PORT_GetError());
   4225        PORT_Memset(tmpbuf, 0, sizeof tmpbuf);
   4226    } else if (ulSignatureLen != context->macSize) {
   4227        /* must be block cipher MACing */
   4228        crv = CKR_SIGNATURE_LEN_RANGE;
   4229    } else if (CKR_OK == (crv = sftk_MACFinal(context))) {
   4230        if (NSS_SecureMemcmp(pSignature, context->macBuf, ulSignatureLen))
   4231            crv = CKR_SIGNATURE_INVALID;
   4232    }
   4233 
   4234    sftk_TerminateOp(session, SFTK_VERIFY, context);
   4235    sftk_FreeSession(session);
   4236    return crv;
   4237 }
   4238 
   4239 /*
   4240 ************** Crypto Functions:     Verify  Signature ************************
   4241 * some algorithms need the signature at the beginning of the verification,
   4242 * VerifySignature provides such and API. For algorithms that don't need
   4243 * the signature first, we stash the signature and just pass it to
   4244 * NSC_VerifyXXX.
   4245 */
   4246 CK_RV
   4247 NSC_VerifySignatureInit(CK_SESSION_HANDLE hSession,
   4248                        CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey,
   4249                        CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
   4250 {
   4251    SFTKSession *session;
   4252    SFTKSessionContext *context;
   4253    CK_RV crv;
   4254    SECItem tmpItem;
   4255 
   4256    crv = NSC_VerifyInit(hSession, pMechanism, hKey);
   4257    if (crv != CKR_OK) {
   4258        return crv;
   4259    }
   4260 
   4261    CHECK_FORK();
   4262 
   4263    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_FALSE, &session);
   4264    if (crv != CKR_OK)
   4265        return crv;
   4266 
   4267    tmpItem.type = siBuffer;
   4268    tmpItem.data = pSignature;
   4269    tmpItem.len = ulSignatureLen;
   4270    context->signature = SECITEM_DupItem(&tmpItem);
   4271    if (!context->signature) {
   4272        sftk_TerminateOp(session, SFTK_VERIFY, context);
   4273        sftk_FreeSession(session);
   4274        return CKR_HOST_MEMORY;
   4275    }
   4276    sftk_FreeSession(session);
   4277    return CKR_OK;
   4278 }
   4279 
   4280 CK_RV
   4281 NSC_VerifySignature(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
   4282                    CK_ULONG ulDataLen)
   4283 {
   4284    SFTKSession *session;
   4285    SFTKSessionContext *context;
   4286    CK_RV crv;
   4287 
   4288    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_FALSE, &session);
   4289    if (crv != CKR_OK)
   4290        return crv;
   4291 
   4292    /* make sure we're legal */
   4293    if (!context->signature) {
   4294        sftk_FreeSession(session);
   4295        return CKR_OPERATION_NOT_INITIALIZED;
   4296    }
   4297    crv = NSC_Verify(hSession, pData, ulDataLen,
   4298                     context->signature->data, context->signature->len);
   4299    /* we free the signature here because the context is part of the session and has
   4300     * a lifetime tied to the session. So we want to hold our reference to the
   4301     * session so it doesn't go away on us */
   4302    sftk_FreeSession(session);
   4303    return crv;
   4304 }
   4305 
   4306 CK_RV
   4307 NSC_VerifySignatureUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
   4308                          CK_ULONG ulPartLen)
   4309 {
   4310    SFTKSession *session;
   4311    SFTKSessionContext *context;
   4312    CK_RV crv;
   4313 
   4314    /* make sure we're legal */
   4315    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_TRUE, &session);
   4316    if (crv != CKR_OK)
   4317        return crv;
   4318 
   4319    /* like verify above, we bother keeping the session to make sure the context
   4320     * doesn't go way on use. there's little chance that it will since that application
   4321     * must protect against multiple threads calling the same same session at the same
   4322     * time (nss has session locks for this), but there are a couple of corner cases,
   4323     * (like close all sessions, or shutting down the whole module. Also if the
   4324     * application breaks the contract, we want to just fail rather than crash */
   4325    if (!context->signature) {
   4326        sftk_FreeSession(session);
   4327        return CKR_OPERATION_NOT_INITIALIZED;
   4328    }
   4329    sftk_FreeSession(session);
   4330    return NSC_VerifyUpdate(hSession, pPart, ulPartLen);
   4331 }
   4332 
   4333 CK_RV
   4334 NSC_VerifySignatureFinal(CK_SESSION_HANDLE hSession)
   4335 {
   4336    SFTKSession *session;
   4337    SFTKSessionContext *context;
   4338    CK_RV crv;
   4339 
   4340    /* make sure we're legal */
   4341    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY, PR_TRUE, &session);
   4342    if (crv != CKR_OK)
   4343        return crv;
   4344 
   4345    if (!context->signature) {
   4346        sftk_FreeSession(session);
   4347        return CKR_OPERATION_NOT_INITIALIZED;
   4348    }
   4349    crv = NSC_VerifyFinal(hSession, context->signature->data,
   4350                          context->signature->len);
   4351    /* see comment in NSC_VerifySignature() */
   4352    sftk_FreeSession(session);
   4353    return crv;
   4354 }
   4355 
   4356 /*
   4357 ************** Crypto Functions:     Verify  Recover ************************
   4358 */
   4359 static SECStatus
   4360 sftk_RSACheckSignRecover(void *ctx, unsigned char *data,
   4361                         unsigned int *dataLen, unsigned int maxDataLen,
   4362                         const unsigned char *sig, unsigned int sigLen)
   4363 {
   4364    NSSLOWKEYPublicKey *key = ctx;
   4365    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
   4366    if (key->keyType != NSSLOWKEYRSAKey) {
   4367        PORT_SetError(SEC_ERROR_INVALID_KEY);
   4368        return SECFailure;
   4369    }
   4370 
   4371    return RSA_CheckSignRecover(&key->u.rsa, data, dataLen, maxDataLen,
   4372                                sig, sigLen);
   4373 }
   4374 
   4375 static SECStatus
   4376 sftk_RSACheckSignRecoverRaw(void *ctx, unsigned char *data,
   4377                            unsigned int *dataLen, unsigned int maxDataLen,
   4378                            const unsigned char *sig, unsigned int sigLen)
   4379 {
   4380    NSSLOWKEYPublicKey *key = ctx;
   4381    PORT_Assert(key->keyType == NSSLOWKEYRSAKey);
   4382    if (key->keyType != NSSLOWKEYRSAKey) {
   4383        PORT_SetError(SEC_ERROR_INVALID_KEY);
   4384        return SECFailure;
   4385    }
   4386 
   4387    return RSA_CheckSignRecoverRaw(&key->u.rsa, data, dataLen, maxDataLen,
   4388                                   sig, sigLen);
   4389 }
   4390 
   4391 /* NSC_VerifyRecoverInit initializes a signature verification operation,
   4392 * where the data is recovered from the signature.
   4393 * E.g. Decryption with the user's public key */
   4394 CK_RV
   4395 NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession,
   4396                      CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
   4397 {
   4398    SFTKSession *session;
   4399    SFTKObject *key;
   4400    SFTKSessionContext *context;
   4401    CK_KEY_TYPE key_type;
   4402    CK_RV crv = CKR_OK;
   4403    NSSLOWKEYPublicKey *pubKey;
   4404 
   4405    CHECK_FORK();
   4406 
   4407    session = sftk_SessionFromHandle(hSession);
   4408    if (session == NULL)
   4409        return CKR_SESSION_HANDLE_INVALID;
   4410    crv = sftk_InitGeneric(session, pMechanism, &context, SFTK_VERIFY_RECOVER,
   4411                           &key, hKey, &key_type, CKO_PUBLIC_KEY, CKA_VERIFY_RECOVER);
   4412    if (crv != CKR_OK) {
   4413        sftk_FreeSession(session);
   4414        return crv;
   4415    }
   4416 
   4417    context->multi = PR_TRUE;
   4418 
   4419    switch (pMechanism->mechanism) {
   4420        case CKM_RSA_PKCS:
   4421        case CKM_RSA_X_509:
   4422            if (key_type != CKK_RSA) {
   4423                crv = CKR_KEY_TYPE_INCONSISTENT;
   4424                break;
   4425            }
   4426            context->multi = PR_FALSE;
   4427            context->rsa = PR_TRUE;
   4428            pubKey = sftk_GetPubKey(key, CKK_RSA, &crv);
   4429            if (pubKey == NULL) {
   4430                break;
   4431            }
   4432            context->cipherInfo = pubKey;
   4433            context->update = pMechanism->mechanism == CKM_RSA_X_509
   4434                                  ? sftk_RSACheckSignRecoverRaw
   4435                                  : sftk_RSACheckSignRecover;
   4436            context->destroy = sftk_Null;
   4437            break;
   4438        default:
   4439            crv = CKR_MECHANISM_INVALID;
   4440            break;
   4441    }
   4442 
   4443    if (crv != CKR_OK) {
   4444        PORT_Free(context);
   4445        sftk_FreeSession(session);
   4446        return crv;
   4447    }
   4448    sftk_SetContextByType(session, SFTK_VERIFY_RECOVER, context);
   4449    sftk_FreeSession(session);
   4450    return CKR_OK;
   4451 }
   4452 
   4453 /* NSC_VerifyRecover verifies a signature in a single-part operation,
   4454 * where the data is recovered from the signature.
   4455 * E.g. Decryption with the user's public key */
   4456 CK_RV
   4457 NSC_VerifyRecover(CK_SESSION_HANDLE hSession,
   4458                  CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen,
   4459                  CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
   4460 {
   4461    SFTKSession *session;
   4462    SFTKSessionContext *context;
   4463    unsigned int outlen;
   4464    unsigned int maxoutlen = *pulDataLen;
   4465    CK_RV crv;
   4466    SECStatus rv;
   4467 
   4468    CHECK_FORK();
   4469 
   4470    /* make sure we're legal */
   4471    crv = sftk_GetContext(hSession, &context, SFTK_VERIFY_RECOVER,
   4472                          PR_FALSE, &session);
   4473    if (crv != CKR_OK)
   4474        return crv;
   4475    if (pData == NULL) {
   4476        /* to return the actual size, we need  to do the decrypt, just return
   4477         * the max size, which is the size of the input signature. */
   4478        *pulDataLen = ulSignatureLen;
   4479        rv = SECSuccess;
   4480        goto finish;
   4481    }
   4482 
   4483    rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
   4484                            pSignature, ulSignatureLen);
   4485    *pulDataLen = (CK_ULONG)outlen;
   4486 
   4487    sftk_TerminateOp(session, SFTK_VERIFY_RECOVER, context);
   4488 finish:
   4489    sftk_FreeSession(session);
   4490    return (rv == SECSuccess) ? CKR_OK : sftk_MapVerifyError(PORT_GetError());
   4491 }
   4492 
   4493 /*
   4494 **************************** Random Functions:  ************************
   4495 */
   4496 
   4497 /* NSC_SeedRandom mixes additional seed material into the token's random number
   4498 * generator. */
   4499 CK_RV
   4500 NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed,
   4501               CK_ULONG ulSeedLen)
   4502 {
   4503    SECStatus rv;
   4504 
   4505    CHECK_FORK();
   4506 
   4507    rv = RNG_RandomUpdate(pSeed, ulSeedLen);
   4508    return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
   4509 }
   4510 
   4511 /* NSC_GenerateRandom generates random data. */
   4512 CK_RV
   4513 NSC_GenerateRandom(CK_SESSION_HANDLE hSession,
   4514                   CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
   4515 {
   4516    SECStatus rv;
   4517 
   4518    CHECK_FORK();
   4519 
   4520    rv = RNG_GenerateGlobalRandomBytes(pRandomData, ulRandomLen);
   4521    /*
   4522     * This may fail with SEC_ERROR_NEED_RANDOM, which means the RNG isn't
   4523     * seeded with enough entropy.
   4524     */
   4525    return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
   4526 }
   4527 
   4528 /*
   4529 **************************** Key Functions:  ************************
   4530 */
   4531 
   4532 /*
   4533 * generate a password based encryption key. This code uses
   4534 * PKCS5 to do the work.
   4535 */
   4536 static CK_RV
   4537 nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism,
   4538                void *buf, CK_ULONG *key_length, PRBool faulty3DES)
   4539 {
   4540    SECItem *pbe_key = NULL, iv, pwitem;
   4541    CK_PBE_PARAMS *pbe_params = NULL;
   4542    CK_PKCS5_PBKD2_PARAMS2 *pbkd2_params = NULL;
   4543 
   4544    *key_length = 0;
   4545    iv.data = NULL;
   4546    iv.len = 0;
   4547 
   4548    if (pMechanism->mechanism == CKM_PKCS5_PBKD2) {
   4549        pbkd2_params = (CK_PKCS5_PBKD2_PARAMS2 *)pMechanism->pParameter;
   4550        if (!pMechanism->pParameter) {
   4551            return CKR_MECHANISM_PARAM_INVALID;
   4552        }
   4553 
   4554 #ifdef SOFTOKEN_USE_PKCS5_PBKD2_PARAMS2_ONLY
   4555        if (pMechanism->ulParameterLen < sizeof(CK_PKCS5_PBKD2_PARAMS2)) {
   4556            return CKR_MECHANISM_PARAM_INVALID;
   4557        }
   4558        pwitem.len = pbkd2_params->ulPasswordLen;
   4559 #else
   4560        int v2;
   4561        if (pMechanism->ulParameterLen < PR_MIN(sizeof(CK_PKCS5_PBKD2_PARAMS),
   4562                                                sizeof(CK_PKCS5_PBKD2_PARAMS2))) {
   4563            return CKR_MECHANISM_PARAM_INVALID;
   4564        }
   4565 
   4566        if (sizeof(CK_PKCS5_PBKD2_PARAMS2) != sizeof(CK_PKCS5_PBKD2_PARAMS)) {
   4567            if (pMechanism->ulParameterLen == sizeof(CK_PKCS5_PBKD2_PARAMS)) {
   4568                v2 = 0;
   4569            } else if (pMechanism->ulParameterLen == sizeof(CK_PKCS5_PBKD2_PARAMS2)) {
   4570                v2 = 1;
   4571            } else {
   4572                return CKR_MECHANISM_PARAM_INVALID;
   4573            }
   4574        } else {
   4575            /* it's unlikely that the password will be longer than 8192 bytes, if so it is
   4576             * most likely a pointer => CK_PKCS5_PBKD2_PARAMS */
   4577            v2 = pbkd2_params->ulPasswordLen <= CK_PKCS5_PBKD2_PARAMS_PTR_BOUNDARY;
   4578        }
   4579        pwitem.len = v2 ? pbkd2_params->ulPasswordLen : *((CK_PKCS5_PBKD2_PARAMS *)pMechanism->pParameter)->ulPasswordLen;
   4580 #endif
   4581        pwitem.data = (unsigned char *)pbkd2_params->pPassword;
   4582    } else {
   4583        if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) {
   4584            return CKR_MECHANISM_PARAM_INVALID;
   4585        }
   4586        pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
   4587        pwitem.data = (unsigned char *)pbe_params->pPassword;
   4588        pwitem.len = pbe_params->ulPasswordLen;
   4589    }
   4590    pbe_key = nsspkcs5_ComputeKeyAndIV(pkcs5_pbe, &pwitem, &iv, faulty3DES);
   4591    if (pbe_key == NULL) {
   4592        return CKR_HOST_MEMORY;
   4593    }
   4594 
   4595    PORT_Memcpy(buf, pbe_key->data, pbe_key->len);
   4596    *key_length = pbe_key->len;
   4597    SECITEM_ZfreeItem(pbe_key, PR_TRUE);
   4598    pbe_key = NULL;
   4599 
   4600    if (iv.data) {
   4601        if (pbe_params && pbe_params->pInitVector != NULL) {
   4602            PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len);
   4603        }
   4604        PORT_Free(iv.data);
   4605    }
   4606 
   4607    return CKR_OK;
   4608 }
   4609 
   4610 /*
   4611 * this is coded for "full" support. These selections will be limitted to
   4612 * the official subset by freebl.
   4613 */
   4614 static unsigned int
   4615 sftk_GetSubPrimeFromPrime(unsigned int primeBits)
   4616 {
   4617    if (primeBits <= 1024) {
   4618        return 160;
   4619    } else if (primeBits <= 2048) {
   4620        return 224;
   4621    } else if (primeBits <= 3072) {
   4622        return 256;
   4623    } else if (primeBits <= 7680) {
   4624        return 384;
   4625    } else {
   4626        return 512;
   4627    }
   4628 }
   4629 
   4630 static CK_RV
   4631 nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key)
   4632 {
   4633    SFTKAttribute *attribute;
   4634    CK_ULONG counter;
   4635    unsigned int seedBits = 0;
   4636    unsigned int subprimeBits = 0;
   4637    unsigned int primeBits;
   4638    unsigned int j = 8; /* default to 1024 bits */
   4639    CK_RV crv = CKR_OK;
   4640    PQGParams *params = NULL;
   4641    PQGVerify *vfy = NULL;
   4642    SECStatus rv;
   4643 
   4644    attribute = sftk_FindAttribute(key, CKA_PRIME_BITS);
   4645    if (attribute == NULL) {
   4646        attribute = sftk_FindAttribute(key, CKA_PRIME);
   4647        if (attribute == NULL) {
   4648            return CKR_TEMPLATE_INCOMPLETE;
   4649        } else {
   4650            primeBits = attribute->attrib.ulValueLen;
   4651            sftk_FreeAttribute(attribute);
   4652        }
   4653    } else {
   4654        primeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue;
   4655        sftk_FreeAttribute(attribute);
   4656    }
   4657    if (primeBits < 1024) {
   4658        j = PQG_PBITS_TO_INDEX(primeBits);
   4659        if (j == (unsigned int)-1) {
   4660            return CKR_ATTRIBUTE_VALUE_INVALID;
   4661        }
   4662    }
   4663 
   4664    attribute = sftk_FindAttribute(key, CKA_NSS_PQG_SEED_BITS);
   4665    if (attribute != NULL) {
   4666        seedBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue;
   4667        sftk_FreeAttribute(attribute);
   4668    }
   4669 
   4670    attribute = sftk_FindAttribute(key, CKA_SUBPRIME_BITS);
   4671    if (attribute != NULL) {
   4672        subprimeBits = (unsigned int)*(CK_ULONG *)attribute->attrib.pValue;
   4673        sftk_FreeAttribute(attribute);
   4674    }
   4675 
   4676    /* if P and Q are supplied, we want to generate a new G */
   4677    attribute = sftk_FindAttribute(key, CKA_PRIME);
   4678    if (attribute != NULL) {
   4679        PLArenaPool *arena;
   4680 
   4681        sftk_FreeAttribute(attribute);
   4682        arena = PORT_NewArena(1024);
   4683        if (arena == NULL) {
   4684            crv = CKR_HOST_MEMORY;
   4685            goto loser;
   4686        }
   4687        params = PORT_ArenaAlloc(arena, sizeof(*params));
   4688        if (params == NULL) {
   4689            crv = CKR_HOST_MEMORY;
   4690            goto loser;
   4691        }
   4692        params->arena = arena;
   4693        crv = sftk_Attribute2SSecItem(arena, &params->prime, key, CKA_PRIME);
   4694        if (crv != CKR_OK) {
   4695            goto loser;
   4696        }
   4697        crv = sftk_Attribute2SSecItem(arena, &params->subPrime,
   4698                                      key, CKA_SUBPRIME);
   4699        if (crv != CKR_OK) {
   4700            goto loser;
   4701        }
   4702 
   4703        arena = PORT_NewArena(1024);
   4704        if (arena == NULL) {
   4705            crv = CKR_HOST_MEMORY;
   4706            goto loser;
   4707        }
   4708        vfy = PORT_ArenaAlloc(arena, sizeof(*vfy));
   4709        if (vfy == NULL) {
   4710            crv = CKR_HOST_MEMORY;
   4711            goto loser;
   4712        }
   4713        vfy->arena = arena;
   4714        crv = sftk_Attribute2SSecItem(arena, &vfy->seed, key, CKA_NSS_PQG_SEED);
   4715        if (crv != CKR_OK) {
   4716            goto loser;
   4717        }
   4718        crv = sftk_Attribute2SSecItem(arena, &vfy->h, key, CKA_NSS_PQG_H);
   4719        if (crv != CKR_OK) {
   4720            goto loser;
   4721        }
   4722        sftk_DeleteAttributeType(key, CKA_PRIME);
   4723        sftk_DeleteAttributeType(key, CKA_SUBPRIME);
   4724        sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED);
   4725        sftk_DeleteAttributeType(key, CKA_NSS_PQG_H);
   4726    }
   4727 
   4728    sftk_DeleteAttributeType(key, CKA_PRIME_BITS);
   4729    sftk_DeleteAttributeType(key, CKA_SUBPRIME_BITS);
   4730    sftk_DeleteAttributeType(key, CKA_NSS_PQG_SEED_BITS);
   4731 
   4732    /* use the old PQG interface if we have old input data */
   4733    if ((primeBits < 1024) || ((primeBits == 1024) && (subprimeBits == 0))) {
   4734        if (seedBits == 0) {
   4735            rv = PQG_ParamGen(j, &params, &vfy);
   4736        } else {
   4737            rv = PQG_ParamGenSeedLen(j, seedBits / 8, &params, &vfy);
   4738        }
   4739    } else {
   4740        if (subprimeBits == 0) {
   4741            subprimeBits = sftk_GetSubPrimeFromPrime(primeBits);
   4742        }
   4743        if (seedBits == 0) {
   4744            seedBits = primeBits;
   4745        }
   4746        rv = PQG_ParamGenV2(primeBits, subprimeBits, seedBits / 8, &params, &vfy);
   4747    }
   4748 
   4749    if (rv != SECSuccess) {
   4750        if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
   4751            sftk_fatalError = PR_TRUE;
   4752        }
   4753        return sftk_MapCryptError(PORT_GetError());
   4754    }
   4755    crv = sftk_AddAttributeType(key, CKA_PRIME,
   4756                                params->prime.data, params->prime.len);
   4757    if (crv != CKR_OK)
   4758        goto loser;
   4759    crv = sftk_AddAttributeType(key, CKA_SUBPRIME,
   4760                                params->subPrime.data, params->subPrime.len);
   4761    if (crv != CKR_OK)
   4762        goto loser;
   4763    crv = sftk_AddAttributeType(key, CKA_BASE,
   4764                                params->base.data, params->base.len);
   4765    if (crv != CKR_OK)
   4766        goto loser;
   4767    counter = vfy->counter;
   4768    crv = sftk_AddAttributeType(key, CKA_NSS_PQG_COUNTER,
   4769                                &counter, sizeof(counter));
   4770    if (crv != CKR_OK)
   4771        goto loser;
   4772    crv = sftk_AddAttributeType(key, CKA_NSS_PQG_SEED,
   4773                                vfy->seed.data, vfy->seed.len);
   4774    if (crv != CKR_OK)
   4775        goto loser;
   4776    crv = sftk_AddAttributeType(key, CKA_NSS_PQG_H,
   4777                                vfy->h.data, vfy->h.len);
   4778    if (crv != CKR_OK)
   4779        goto loser;
   4780 
   4781 loser:
   4782    if (params) {
   4783        PQG_DestroyParams(params);
   4784    }
   4785 
   4786    if (vfy) {
   4787        PQG_DestroyVerify(vfy);
   4788    }
   4789    return crv;
   4790 }
   4791 
   4792 static CK_RV
   4793 nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type,
   4794                    CK_ULONG *key_length)
   4795 {
   4796    CK_RV crv = CKR_OK;
   4797 
   4798    switch (mechanism) {
   4799 #ifndef NSS_DISABLE_DEPRECATED_RC2
   4800        case CKM_RC2_KEY_GEN:
   4801            *key_type = CKK_RC2;
   4802            if (*key_length == 0)
   4803                crv = CKR_TEMPLATE_INCOMPLETE;
   4804            break;
   4805 #endif /* NSS_DISABLE_DEPRECATED_RC2 */
   4806 #if NSS_SOFTOKEN_DOES_RC5
   4807        case CKM_RC5_KEY_GEN:
   4808            *key_type = CKK_RC5;
   4809            if (*key_length == 0)
   4810                crv = CKR_TEMPLATE_INCOMPLETE;
   4811            break;
   4812 #endif
   4813        case CKM_RC4_KEY_GEN:
   4814            *key_type = CKK_RC4;
   4815            if (*key_length == 0)
   4816                crv = CKR_TEMPLATE_INCOMPLETE;
   4817            break;
   4818        case CKM_GENERIC_SECRET_KEY_GEN:
   4819            *key_type = CKK_GENERIC_SECRET;
   4820            if (*key_length == 0)
   4821                crv = CKR_TEMPLATE_INCOMPLETE;
   4822            break;
   4823        case CKM_CDMF_KEY_GEN:
   4824            *key_type = CKK_CDMF;
   4825            *key_length = 8;
   4826            break;
   4827        case CKM_DES_KEY_GEN:
   4828            *key_type = CKK_DES;
   4829            *key_length = 8;
   4830            break;
   4831        case CKM_DES2_KEY_GEN:
   4832            *key_type = CKK_DES2;
   4833            *key_length = 16;
   4834            break;
   4835        case CKM_DES3_KEY_GEN:
   4836            *key_type = CKK_DES3;
   4837            *key_length = 24;
   4838            break;
   4839 #ifndef NSS_DISABLE_DEPRECATED_SEED
   4840        case CKM_SEED_KEY_GEN:
   4841            *key_type = CKK_SEED;
   4842            *key_length = 16;
   4843            break;
   4844 #endif /* NSS_DISABLE_DEPRECATED_SEED */
   4845        case CKM_CAMELLIA_KEY_GEN:
   4846            *key_type = CKK_CAMELLIA;
   4847            if (*key_length == 0)
   4848                crv = CKR_TEMPLATE_INCOMPLETE;
   4849            break;
   4850        case CKM_AES_KEY_GEN:
   4851            *key_type = CKK_AES;
   4852            if (*key_length == 0)
   4853                crv = CKR_TEMPLATE_INCOMPLETE;
   4854            break;
   4855        case CKM_NSS_CHACHA20_KEY_GEN:
   4856            *key_type = CKK_NSS_CHACHA20;
   4857            *key_length = 32;
   4858            break;
   4859        case CKM_CHACHA20_KEY_GEN:
   4860            *key_type = CKK_CHACHA20;
   4861            *key_length = 32;
   4862            break;
   4863        case CKM_HKDF_KEY_GEN:
   4864            *key_type = CKK_HKDF;
   4865            if (*key_length == 0)
   4866                crv = CKR_TEMPLATE_INCOMPLETE;
   4867            break;
   4868        default:
   4869            PORT_Assert(0);
   4870            crv = CKR_MECHANISM_INVALID;
   4871            break;
   4872    }
   4873 
   4874    return crv;
   4875 }
   4876 
   4877 CK_RV
   4878 nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe)
   4879 {
   4880    SECItem salt;
   4881    CK_PBE_PARAMS *pbe_params = NULL;
   4882    NSSPKCS5PBEParameter *params;
   4883    PLArenaPool *arena = NULL;
   4884    SECStatus rv;
   4885 
   4886    *pbe = NULL;
   4887 
   4888    arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
   4889    if (arena == NULL) {
   4890        return CKR_HOST_MEMORY;
   4891    }
   4892 
   4893    params = (NSSPKCS5PBEParameter *)PORT_ArenaZAlloc(arena,
   4894                                                      sizeof(NSSPKCS5PBEParameter));
   4895    if (params == NULL) {
   4896        PORT_FreeArena(arena, PR_TRUE);
   4897        return CKR_HOST_MEMORY;
   4898    }
   4899    if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) {
   4900        PORT_FreeArena(arena, PR_TRUE);
   4901        return CKR_MECHANISM_PARAM_INVALID;
   4902    }
   4903 
   4904    params->poolp = arena;
   4905    params->ivLen = 0;
   4906    params->pbeType = NSSPKCS5_PKCS12_V2;
   4907    params->hashType = HASH_AlgSHA1;
   4908    params->encAlg = SEC_OID_SHA1; /* any invalid value */
   4909    params->is2KeyDES = PR_FALSE;
   4910    params->keyID = pbeBitGenIntegrityKey;
   4911    pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
   4912    params->iter = pbe_params->ulIteration;
   4913 
   4914    salt.data = (unsigned char *)pbe_params->pSalt;
   4915    salt.len = (unsigned int)pbe_params->ulSaltLen;
   4916    salt.type = siBuffer;
   4917    rv = SECITEM_CopyItem(arena, &params->salt, &salt);
   4918    if (rv != SECSuccess) {
   4919        PORT_FreeArena(arena, PR_TRUE);
   4920        return CKR_HOST_MEMORY;
   4921    }
   4922    switch (pMechanism->mechanism) {
   4923        case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN:
   4924        case CKM_PBA_SHA1_WITH_SHA1_HMAC:
   4925            params->hashType = HASH_AlgSHA1;
   4926            params->keyLen = 20;
   4927            break;
   4928        case CKM_NSS_PBE_MD5_HMAC_KEY_GEN:
   4929            params->hashType = HASH_AlgMD5;
   4930            params->keyLen = 16;
   4931            break;
   4932        case CKM_NSS_PBE_MD2_HMAC_KEY_GEN:
   4933            params->hashType = HASH_AlgMD2;
   4934            params->keyLen = 16;
   4935            break;
   4936        case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN:
   4937            params->hashType = HASH_AlgSHA224;
   4938            params->keyLen = 28;
   4939            break;
   4940        case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN:
   4941            params->hashType = HASH_AlgSHA256;
   4942            params->keyLen = 32;
   4943            break;
   4944        case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN:
   4945            params->hashType = HASH_AlgSHA384;
   4946            params->keyLen = 48;
   4947            break;
   4948        case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN:
   4949            params->hashType = HASH_AlgSHA512;
   4950            params->keyLen = 64;
   4951            break;
   4952        default:
   4953            PORT_FreeArena(arena, PR_TRUE);
   4954            return CKR_MECHANISM_INVALID;
   4955    }
   4956    *pbe = params;
   4957    return CKR_OK;
   4958 }
   4959 
   4960 /* maybe this should be table driven? */
   4961 static CK_RV
   4962 nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe,
   4963                   CK_KEY_TYPE *key_type, CK_ULONG *key_length)
   4964 {
   4965    CK_RV crv = CKR_OK;
   4966    SECOidData *oid;
   4967    CK_PBE_PARAMS *pbe_params = NULL;
   4968    NSSPKCS5PBEParameter *params = NULL;
   4969    HASH_HashType hashType = HASH_AlgSHA1;
   4970    CK_PKCS5_PBKD2_PARAMS2 *pbkd2_params = NULL;
   4971    SECItem salt;
   4972    CK_ULONG iteration = 0;
   4973 
   4974    *pbe = NULL;
   4975 
   4976    oid = SECOID_FindOIDByMechanism(pMechanism->mechanism);
   4977    if (oid == NULL) {
   4978        return CKR_MECHANISM_INVALID;
   4979    }
   4980 
   4981    if (pMechanism->mechanism == CKM_PKCS5_PBKD2) {
   4982        if (pMechanism->ulParameterLen < PR_MIN(sizeof(CK_PKCS5_PBKD2_PARAMS2),
   4983                                                sizeof(CK_PKCS5_PBKD2_PARAMS))) {
   4984            return CKR_MECHANISM_PARAM_INVALID;
   4985        }
   4986        pbkd2_params = (CK_PKCS5_PBKD2_PARAMS2 *)pMechanism->pParameter;
   4987        switch (pbkd2_params->prf) {
   4988            case CKP_PKCS5_PBKD2_HMAC_SHA1:
   4989                hashType = HASH_AlgSHA1;
   4990                break;
   4991            case CKP_PKCS5_PBKD2_HMAC_SHA224:
   4992                hashType = HASH_AlgSHA224;
   4993                break;
   4994            case CKP_PKCS5_PBKD2_HMAC_SHA256:
   4995                hashType = HASH_AlgSHA256;
   4996                break;
   4997            case CKP_PKCS5_PBKD2_HMAC_SHA384:
   4998                hashType = HASH_AlgSHA384;
   4999                break;
   5000            case CKP_PKCS5_PBKD2_HMAC_SHA512:
   5001                hashType = HASH_AlgSHA512;
   5002                break;
   5003            default:
   5004                return CKR_MECHANISM_PARAM_INVALID;
   5005        }
   5006        if (pbkd2_params->saltSource != CKZ_SALT_SPECIFIED) {
   5007            return CKR_MECHANISM_PARAM_INVALID;
   5008        }
   5009        salt.data = (unsigned char *)pbkd2_params->pSaltSourceData;
   5010        salt.len = (unsigned int)pbkd2_params->ulSaltSourceDataLen;
   5011        iteration = pbkd2_params->iterations;
   5012    } else {
   5013        if (BAD_PARAM_CAST(pMechanism, sizeof(CK_PBE_PARAMS))) {
   5014            return CKR_MECHANISM_PARAM_INVALID;
   5015        }
   5016        pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
   5017        salt.data = (unsigned char *)pbe_params->pSalt;
   5018        salt.len = (unsigned int)pbe_params->ulSaltLen;
   5019        iteration = pbe_params->ulIteration;
   5020    }
   5021    params = nsspkcs5_NewParam(oid->offset, hashType, &salt, iteration);
   5022    if (params == NULL) {
   5023        return CKR_MECHANISM_INVALID;
   5024    }
   5025 
   5026    switch (params->encAlg) {
   5027        case SEC_OID_DES_CBC:
   5028            *key_type = CKK_DES;
   5029            *key_length = params->keyLen;
   5030            break;
   5031        case SEC_OID_DES_EDE3_CBC:
   5032            *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3;
   5033            *key_length = params->keyLen;
   5034            break;
   5035 #ifndef NSS_DISABLE_DEPRECATED_RC2
   5036        case SEC_OID_RC2_CBC:
   5037            *key_type = CKK_RC2;
   5038            *key_length = params->keyLen;
   5039            break;
   5040 #endif /* NSS_DISABLE_DEPRECATED_RC2 */
   5041        case SEC_OID_RC4:
   5042            *key_type = CKK_RC4;
   5043            *key_length = params->keyLen;
   5044            break;
   5045        case SEC_OID_PKCS5_PBKDF2:
   5046            /* key type must already be set */
   5047            if (*key_type == CKK_INVALID_KEY_TYPE) {
   5048                crv = CKR_TEMPLATE_INCOMPLETE;
   5049                break;
   5050            }
   5051            /* PBKDF2 needs to calculate the key length from the other parameters
   5052             */
   5053            if (*key_length == 0) {
   5054                *key_length = sftk_MapKeySize(*key_type);
   5055            }
   5056            if (*key_length == 0) {
   5057                crv = CKR_TEMPLATE_INCOMPLETE;
   5058                break;
   5059            }
   5060            params->keyLen = *key_length;
   5061            break;
   5062        default:
   5063            crv = CKR_MECHANISM_INVALID;
   5064            break;
   5065    }
   5066    if (crv == CKR_OK) {
   5067        *pbe = params;
   5068    } else {
   5069        nsspkcs5_DestroyPBEParameter(params);
   5070    }
   5071    return crv;
   5072 }
   5073 
   5074 /* NSC_GenerateKey generates a secret key, creating a new key object. */
   5075 CK_RV
   5076 NSC_GenerateKey(CK_SESSION_HANDLE hSession,
   5077                CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
   5078                CK_OBJECT_HANDLE_PTR phKey)
   5079 {
   5080    SFTKObject *key;
   5081    SFTKSession *session;
   5082    PRBool checkWeak = PR_FALSE;
   5083    CK_ULONG key_length = 0;
   5084    CK_KEY_TYPE key_type = CKK_INVALID_KEY_TYPE;
   5085    CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;
   5086    CK_RV crv = CKR_OK;
   5087    CK_BBOOL cktrue = CK_TRUE;
   5088    NSSPKCS5PBEParameter *pbe_param = NULL;
   5089    int i;
   5090    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
   5091    unsigned char buf[MAX_KEY_LEN];
   5092    enum { nsc_pbe,
   5093           nsc_ssl,
   5094           nsc_bulk,
   5095           nsc_param,
   5096           nsc_jpake } key_gen_type;
   5097    SSL3RSAPreMasterSecret *rsa_pms;
   5098    CK_VERSION *version;
   5099    /* in very old versions of NSS, there were implementation errors with key
   5100     * generation methods.  We want to beable to read these, but not
   5101     * produce them any more.  The affected algorithm was 3DES.
   5102     */
   5103    PRBool faultyPBE3DES = PR_FALSE;
   5104    HASH_HashType hashType = HASH_AlgNULL;
   5105 
   5106    CHECK_FORK();
   5107 
   5108    if (!slot) {
   5109        return CKR_SESSION_HANDLE_INVALID;
   5110    }
   5111    /*
   5112     * now lets create an object to hang the attributes off of
   5113     */
   5114    key = sftk_NewObject(slot); /* fill in the handle later */
   5115    if (key == NULL) {
   5116        return CKR_HOST_MEMORY;
   5117    }
   5118 
   5119    /*
   5120     * load the template values into the object
   5121     */
   5122    for (i = 0; i < (int)ulCount; i++) {
   5123        if (pTemplate[i].type == CKA_VALUE_LEN) {
   5124            key_length = *(CK_ULONG *)pTemplate[i].pValue;
   5125            continue;
   5126        }
   5127        /* some algorithms need keytype specified */
   5128        if (pTemplate[i].type == CKA_KEY_TYPE) {
   5129            key_type = *(CK_ULONG *)pTemplate[i].pValue;
   5130            continue;
   5131        }
   5132 
   5133        crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
   5134        if (crv != CKR_OK) {
   5135            break;
   5136        }
   5137    }
   5138    if (crv != CKR_OK) {
   5139        goto loser;
   5140    }
   5141 
   5142    /* make sure we don't have any class, key_type, or value fields */
   5143    sftk_DeleteAttributeType(key, CKA_CLASS);
   5144    sftk_DeleteAttributeType(key, CKA_KEY_TYPE);
   5145    sftk_DeleteAttributeType(key, CKA_VALUE);
   5146 
   5147    /* Now Set up the parameters to generate the key (based on mechanism) */
   5148    key_gen_type = nsc_bulk; /* bulk key by default */
   5149    switch (pMechanism->mechanism) {
   5150        case CKM_CDMF_KEY_GEN:
   5151        case CKM_DES_KEY_GEN:
   5152        case CKM_DES2_KEY_GEN:
   5153        case CKM_DES3_KEY_GEN:
   5154            checkWeak = PR_TRUE;
   5155 /* fall through */
   5156 #ifndef NSS_DISABLE_DEPRECATED_RC2
   5157        case CKM_RC2_KEY_GEN:
   5158 #endif
   5159        case CKM_RC4_KEY_GEN:
   5160        case CKM_GENERIC_SECRET_KEY_GEN:
   5161 #ifndef NSS_DISABLE_DEPRECATED_SEED
   5162        case CKM_SEED_KEY_GEN:
   5163 #endif
   5164        case CKM_CAMELLIA_KEY_GEN:
   5165        case CKM_AES_KEY_GEN:
   5166        case CKM_NSS_CHACHA20_KEY_GEN:
   5167        case CKM_CHACHA20_KEY_GEN:
   5168 #if NSS_SOFTOKEN_DOES_RC5
   5169        case CKM_RC5_KEY_GEN:
   5170 #endif
   5171            crv = nsc_SetupBulkKeyGen(pMechanism->mechanism, &key_type, &key_length);
   5172            break;
   5173        case CKM_SSL3_PRE_MASTER_KEY_GEN:
   5174            key_type = CKK_GENERIC_SECRET;
   5175            key_length = 48;
   5176            key_gen_type = nsc_ssl;
   5177            break;
   5178        case CKM_PBA_SHA1_WITH_SHA1_HMAC:
   5179        case CKM_NSS_PBE_SHA1_HMAC_KEY_GEN:
   5180        case CKM_NSS_PBE_MD5_HMAC_KEY_GEN:
   5181        case CKM_NSS_PBE_MD2_HMAC_KEY_GEN:
   5182        case CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN:
   5183        case CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN:
   5184        case CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN:
   5185        case CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN:
   5186            key_gen_type = nsc_pbe;
   5187            key_type = CKK_GENERIC_SECRET;
   5188            crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param);
   5189            break;
   5190        case CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC:
   5191            faultyPBE3DES = PR_TRUE;
   5192        /* fall through */
   5193        case CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC:
   5194 #ifndef NSS_DISABLE_DEPRECATED_RC2
   5195        case CKM_NSS_PBE_SHA1_40_BIT_RC2_CBC:
   5196        case CKM_NSS_PBE_SHA1_128_BIT_RC2_CBC:
   5197        case CKM_PBE_SHA1_RC2_128_CBC:
   5198        case CKM_PBE_SHA1_RC2_40_CBC:
   5199 #endif
   5200        case CKM_NSS_PBE_SHA1_DES_CBC:
   5201        case CKM_NSS_PBE_SHA1_40_BIT_RC4:
   5202        case CKM_NSS_PBE_SHA1_128_BIT_RC4:
   5203        case CKM_PBE_SHA1_DES3_EDE_CBC:
   5204        case CKM_PBE_SHA1_DES2_EDE_CBC:
   5205        case CKM_PBE_SHA1_RC4_128:
   5206        case CKM_PBE_SHA1_RC4_40:
   5207        case CKM_PBE_MD5_DES_CBC:
   5208        case CKM_PBE_MD2_DES_CBC:
   5209        case CKM_PKCS5_PBKD2:
   5210            key_gen_type = nsc_pbe;
   5211            crv = nsc_SetupPBEKeyGen(pMechanism, &pbe_param, &key_type, &key_length);
   5212            break;
   5213            /*#ifndef NSS_DISABLE_DSA */
   5214            /* some applications use CKM_DSA_PARAMETER_GEN for weak DH keys...
   5215             * most notably tests and even ssl... continue to allow it for now */
   5216        case CKM_DSA_PARAMETER_GEN:
   5217            key_gen_type = nsc_param;
   5218            key_type = CKK_DSA;
   5219            objclass = CKO_DOMAIN_PARAMETERS;
   5220            crv = CKR_OK;
   5221            break;
   5222            /* #endif */
   5223        case CKM_NSS_JPAKE_ROUND1_SHA1:
   5224            hashType = HASH_AlgSHA1;
   5225            goto jpake1;
   5226        case CKM_NSS_JPAKE_ROUND1_SHA256:
   5227            hashType = HASH_AlgSHA256;
   5228            goto jpake1;
   5229        case CKM_NSS_JPAKE_ROUND1_SHA384:
   5230            hashType = HASH_AlgSHA384;
   5231            goto jpake1;
   5232        case CKM_NSS_JPAKE_ROUND1_SHA512:
   5233            hashType = HASH_AlgSHA512;
   5234            goto jpake1;
   5235        jpake1:
   5236            key_gen_type = nsc_jpake;
   5237            key_type = CKK_NSS_JPAKE_ROUND1;
   5238            objclass = CKO_PRIVATE_KEY;
   5239            if (pMechanism->pParameter == NULL ||
   5240                pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound1Params)) {
   5241                crv = CKR_MECHANISM_PARAM_INVALID;
   5242                break;
   5243            }
   5244            if (sftk_isTrue(key, CKA_TOKEN)) {
   5245                crv = CKR_TEMPLATE_INCONSISTENT;
   5246                break;
   5247            }
   5248            crv = CKR_OK;
   5249            break;
   5250        default:
   5251            crv = CKR_MECHANISM_INVALID;
   5252            break;
   5253    }
   5254 
   5255    /* make sure we aren't going to overflow the buffer */
   5256    if (sizeof(buf) < key_length) {
   5257        /* someone is getting pretty optimistic about how big their key can
   5258         * be... */
   5259        crv = CKR_TEMPLATE_INCONSISTENT;
   5260    }
   5261 
   5262    if (crv != CKR_OK) {
   5263        if (pbe_param) {
   5264            nsspkcs5_DestroyPBEParameter(pbe_param);
   5265        }
   5266        goto loser;
   5267    }
   5268 
   5269    /* if there was no error,
   5270     * key_type *MUST* be set in the switch statement above */
   5271    PORT_Assert(key_type != CKK_INVALID_KEY_TYPE);
   5272 
   5273    /*
   5274     * now to the actual key gen.
   5275     */
   5276    switch (key_gen_type) {
   5277        case nsc_pbe:
   5278            crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length,
   5279                                  faultyPBE3DES);
   5280            nsspkcs5_DestroyPBEParameter(pbe_param);
   5281            break;
   5282        case nsc_ssl:
   5283            rsa_pms = (SSL3RSAPreMasterSecret *)buf;
   5284            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_VERSION))) {
   5285                crv = CKR_MECHANISM_PARAM_INVALID;
   5286                goto loser;
   5287            }
   5288            version = (CK_VERSION *)pMechanism->pParameter;
   5289            rsa_pms->client_version[0] = version->major;
   5290            rsa_pms->client_version[1] = version->minor;
   5291            crv =
   5292                NSC_GenerateRandom(0, &rsa_pms->random[0], sizeof(rsa_pms->random));
   5293            break;
   5294        case nsc_bulk:
   5295            /* get the key, check for weak keys and repeat if found */
   5296            do {
   5297                crv = NSC_GenerateRandom(0, buf, key_length);
   5298            } while (crv == CKR_OK && checkWeak && sftk_IsWeakKey(buf, key_type));
   5299            break;
   5300        case nsc_param:
   5301            /* generate parameters */
   5302            *buf = 0;
   5303            crv = nsc_parameter_gen(key_type, key);
   5304            break;
   5305        case nsc_jpake:
   5306            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_NSS_JPAKERound1Params))) {
   5307                crv = CKR_MECHANISM_PARAM_INVALID;
   5308                goto loser;
   5309            }
   5310            crv = jpake_Round1(hashType,
   5311                               (CK_NSS_JPAKERound1Params *)pMechanism->pParameter,
   5312                               key);
   5313            break;
   5314    }
   5315 
   5316    if (crv != CKR_OK) {
   5317        goto loser;
   5318    }
   5319 
   5320    /* Add the class, key_type, and value */
   5321    crv = sftk_AddAttributeType(key, CKA_CLASS, &objclass, sizeof(CK_OBJECT_CLASS));
   5322    if (crv != CKR_OK) {
   5323        goto loser;
   5324    }
   5325    crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &key_type, sizeof(CK_KEY_TYPE));
   5326    if (crv != CKR_OK) {
   5327        goto loser;
   5328    }
   5329    if (key_length != 0) {
   5330        crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length);
   5331        if (crv != CKR_OK) {
   5332            goto loser;
   5333        }
   5334    }
   5335 
   5336    /* get the session */
   5337    session = sftk_SessionFromHandle(hSession);
   5338    if (session == NULL) {
   5339        crv = CKR_SESSION_HANDLE_INVALID;
   5340        goto loser;
   5341    }
   5342 
   5343    /*
   5344     * handle the base object stuff
   5345     */
   5346    crv = sftk_handleObject(key, session);
   5347    sftk_FreeSession(session);
   5348    if (crv == CKR_OK && sftk_isTrue(key, CKA_SENSITIVE)) {
   5349        crv = sftk_forceAttribute(key, CKA_ALWAYS_SENSITIVE, &cktrue, sizeof(CK_BBOOL));
   5350    }
   5351    if (crv == CKR_OK && !sftk_isTrue(key, CKA_EXTRACTABLE)) {
   5352        crv = sftk_forceAttribute(key, CKA_NEVER_EXTRACTABLE, &cktrue, sizeof(CK_BBOOL));
   5353    }
   5354    if (crv == CKR_OK) {
   5355        *phKey = key->handle;
   5356    }
   5357 loser:
   5358    PORT_Memset(buf, 0, sizeof buf);
   5359    sftk_FreeObject(key);
   5360    return crv;
   5361 }
   5362 
   5363 /* takes raw sessions and key handles and determines if the keys
   5364 * have the same value. */
   5365 PRBool
   5366 sftk_compareKeysEqual(CK_SESSION_HANDLE hSession,
   5367                      CK_OBJECT_HANDLE key1, CK_OBJECT_HANDLE key2)
   5368 {
   5369    PRBool result = PR_FALSE;
   5370    SFTKSession *session;
   5371    SFTKObject *key1obj = NULL;
   5372    SFTKObject *key2obj = NULL;
   5373    SFTKAttribute *att1 = NULL;
   5374    SFTKAttribute *att2 = NULL;
   5375 
   5376    /* fetch the pkcs11 objects from the handles */
   5377    session = sftk_SessionFromHandle(hSession);
   5378    if (session == NULL) {
   5379        return CKR_SESSION_HANDLE_INVALID;
   5380    }
   5381 
   5382    key1obj = sftk_ObjectFromHandle(key1, session);
   5383    key2obj = sftk_ObjectFromHandle(key2, session);
   5384    sftk_FreeSession(session);
   5385    if ((key1obj == NULL) || (key2obj == NULL)) {
   5386        goto loser;
   5387    }
   5388    /* fetch the value attributes */
   5389    att1 = sftk_FindAttribute(key1obj, CKA_VALUE);
   5390    if (att1 == NULL) {
   5391        goto loser;
   5392    }
   5393    att2 = sftk_FindAttribute(key2obj, CKA_VALUE);
   5394    if (att2 == NULL) {
   5395        goto loser;
   5396    }
   5397    /* make sure that they are equal */
   5398    if (att1->attrib.ulValueLen != att2->attrib.ulValueLen) {
   5399        goto loser;
   5400    }
   5401    if (PORT_Memcmp(att1->attrib.pValue, att2->attrib.pValue,
   5402                    att1->attrib.ulValueLen) != 0) {
   5403        goto loser;
   5404    }
   5405    result = PR_TRUE;
   5406 loser:
   5407    if (key1obj) {
   5408        sftk_FreeObject(key1obj);
   5409    }
   5410    if (key2obj) {
   5411        sftk_FreeObject(key1obj);
   5412    }
   5413    if (att1) {
   5414        sftk_FreeAttribute(att1);
   5415    }
   5416    if (att2) {
   5417        sftk_FreeAttribute(att2);
   5418    }
   5419    return result;
   5420 }
   5421 
   5422 #define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */
   5423 
   5424 /*
   5425 * FIPS 140-3 pairwise consistency check utilized to validate key pair.
   5426 *
   5427 * This function returns
   5428 *   CKR_OK               if pairwise consistency check passed
   5429 *   CKR_GENERAL_ERROR    if pairwise consistency check failed
   5430 *   other error codes    if paiswise consistency check could not be
   5431 *                        performed, for example, CKR_HOST_MEMORY.
   5432 */
   5433 static CK_RV
   5434 sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, SFTKSlot *slot,
   5435                              SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType)
   5436 {
   5437    /*
   5438     *                      Key type    Mechanism type
   5439     *                      --------------------------------
   5440     * For encrypt/decrypt: CKK_RSA  => CKM_RSA_PKCS_OAEP
   5441     *                      others   => CKM_INVALID_MECHANISM
   5442     *
   5443     * For sign/verify:     CKK_RSA  => CKM_SHA256_RSA_PKCS_PSS
   5444     *                      CKK_DSA  => CKM_DSA_SHA256
   5445     *                      CKK_EC   => CKM_ECDSA_SHA256
   5446     *                      CKK_ML_DSA => CKM_ML_DSA
   5447     *                      others   => CKM_INVALID_MECHANISM
   5448     *
   5449     * None of these mechanisms has a parameter.
   5450     *
   5451     * For derive           CKK_DH   => CKM_DH_PKCS_DERIVE
   5452     *                      CKK_EC   => CKM_ECDH1_DERIVE
   5453     *                      CKK_EC_MONTGOMERY   => CKM_ECDH1_DERIVE
   5454     *                      others   => CKM_INVALID_MECHANISM
   5455     *
   5456     * For KEM mechanisms:
   5457     *                     CKK_NSS_KYBER   => don't
   5458     *                     CKK_NSS_ML_KEM  => don't
   5459     *                     CKK_ML_KEM      => CM_ML_KEM
   5460     *
   5461     * The parameters for these mechanisms is the public key.
   5462     */
   5463    CK_MECHANISM mech = { 0, NULL, 0 };
   5464 
   5465    CK_ULONG modulusLen = 0;
   5466 #ifndef NSS_DISABLE_DSA
   5467    CK_ULONG subPrimeLen = 0;
   5468 #endif
   5469    PRBool isEncryptable = PR_FALSE;
   5470    PRBool canSignVerify = PR_FALSE;
   5471    PRBool isDerivable = PR_FALSE;
   5472    PRBool isKEM = PR_FALSE;
   5473    CK_RV crv;
   5474 
   5475    /* Variables used for Encrypt/Decrypt functions. */
   5476    unsigned char *known_message = (unsigned char *)"Known Crypto Message";
   5477    unsigned char plaintext[PAIRWISE_MESSAGE_LENGTH];
   5478    CK_ULONG bytes_decrypted;
   5479    unsigned char *ciphertext;
   5480    unsigned char *text_compared;
   5481    CK_ULONG bytes_encrypted;
   5482    CK_ULONG bytes_compared;
   5483 
   5484    /* Variables used for Signature/Verification functions. */
   5485    unsigned char *signature;
   5486    CK_ULONG signature_length;
   5487    SFTKAttribute *attribute;
   5488 
   5489    switch (keyType) {
   5490        case CKK_RSA:
   5491            /* Get modulus length of private key. */
   5492            attribute = sftk_FindAttribute(privateKey, CKA_MODULUS);
   5493            if (attribute == NULL) {
   5494                return CKR_DEVICE_ERROR;
   5495            }
   5496            modulusLen = attribute->attrib.ulValueLen;
   5497            if (*(unsigned char *)attribute->attrib.pValue == 0) {
   5498                modulusLen--;
   5499            }
   5500            sftk_FreeAttribute(attribute);
   5501 #if RSA_MIN_MODULUS_BITS < 1023
   5502            /* if we allow weak RSA keys, and this is a weak RSA key and
   5503             * we aren't in FIPS mode, skip the tests, These keys are
   5504             * factorable anyway, the pairwise test doen't matter. */
   5505            if ((modulusLen < 1023) && !sftk_isFIPS(slot->slotID)) {
   5506                return CKR_OK;
   5507            }
   5508 #endif
   5509            break;
   5510 #ifndef NSS_DISABLE_DSA
   5511        case CKK_DSA:
   5512            /* Get subprime length of private key. */
   5513            attribute = sftk_FindAttribute(privateKey, CKA_SUBPRIME);
   5514            if (attribute == NULL) {
   5515                return CKR_DEVICE_ERROR;
   5516            }
   5517            subPrimeLen = attribute->attrib.ulValueLen;
   5518            if (subPrimeLen > 1 &&
   5519                *(unsigned char *)attribute->attrib.pValue == 0) {
   5520                subPrimeLen--;
   5521            }
   5522            sftk_FreeAttribute(attribute);
   5523            break;
   5524 #endif
   5525        case CKK_NSS_KYBER:
   5526        case CKK_NSS_ML_KEM:
   5527            /* these aren't FIPS. we use them to generate keys without a
   5528             * pairwise consistency check */
   5529            return CKR_OK;
   5530    }
   5531 
   5532    /**************************************************/
   5533    /* Pairwise Consistency Check of Encrypt/Decrypt. */
   5534    /**************************************************/
   5535 
   5536    isEncryptable = sftk_isTrue(privateKey, CKA_DECRYPT);
   5537 
   5538    /*
   5539     * If the decryption attribute is set, attempt to encrypt
   5540     * with the public key and decrypt with the private key.
   5541     */
   5542    if (isEncryptable) {
   5543        if (keyType != CKK_RSA) {
   5544            return CKR_DEVICE_ERROR;
   5545        }
   5546        bytes_encrypted = modulusLen;
   5547        mech.mechanism = CKM_RSA_PKCS_OAEP;
   5548        CK_RSA_PKCS_OAEP_PARAMS oaepParams;
   5549        oaepParams.hashAlg = CKM_SHA256;
   5550        oaepParams.mgf = CKG_MGF1_SHA256;
   5551        oaepParams.source = CKZ_DATA_SPECIFIED;
   5552        oaepParams.pSourceData = NULL;
   5553        oaepParams.ulSourceDataLen = 0;
   5554        mech.pParameter = &oaepParams;
   5555        mech.ulParameterLen = sizeof(oaepParams);
   5556 
   5557        /* Allocate space for ciphertext. */
   5558        ciphertext = (unsigned char *)PORT_ZAlloc(bytes_encrypted);
   5559        if (ciphertext == NULL) {
   5560            return CKR_HOST_MEMORY;
   5561        }
   5562 
   5563        /* Prepare for encryption using the public key. */
   5564        crv = NSC_EncryptInit(hSession, &mech, publicKey->handle);
   5565        if (crv != CKR_OK) {
   5566            PORT_Free(ciphertext);
   5567            return crv;
   5568        }
   5569 
   5570        /* Encrypt using the public key. */
   5571        crv = NSC_Encrypt(hSession,
   5572                          known_message,
   5573                          PAIRWISE_MESSAGE_LENGTH,
   5574                          ciphertext,
   5575                          &bytes_encrypted);
   5576        if (crv != CKR_OK) {
   5577            PORT_Free(ciphertext);
   5578            return crv;
   5579        }
   5580 
   5581        /* Always use the smaller of these two values . . . */
   5582        bytes_compared = PR_MIN(bytes_encrypted, PAIRWISE_MESSAGE_LENGTH);
   5583 
   5584        /*
   5585         * If there was a failure, the plaintext
   5586         * goes at the end, therefore . . .
   5587         */
   5588        text_compared = ciphertext + bytes_encrypted - bytes_compared;
   5589 
   5590        /*
   5591         * Check to ensure that ciphertext does
   5592         * NOT EQUAL known input message text
   5593         * per FIPS PUB 140-2 directive.
   5594         */
   5595        if (PORT_Memcmp(text_compared, known_message,
   5596                        bytes_compared) == 0) {
   5597            /* Set error to Invalid PRIVATE Key. */
   5598            PORT_SetError(SEC_ERROR_INVALID_KEY);
   5599            PORT_Free(ciphertext);
   5600            return CKR_GENERAL_ERROR;
   5601        }
   5602 
   5603        /* Prepare for decryption using the private key. */
   5604        crv = NSC_DecryptInit(hSession, &mech, privateKey->handle);
   5605        if (crv != CKR_OK) {
   5606            PORT_Free(ciphertext);
   5607            return crv;
   5608        }
   5609 
   5610        memset(plaintext, 0, PAIRWISE_MESSAGE_LENGTH);
   5611 
   5612        /*
   5613         * Initialize bytes decrypted to be the
   5614         * expected PAIRWISE_MESSAGE_LENGTH.
   5615         */
   5616        bytes_decrypted = PAIRWISE_MESSAGE_LENGTH;
   5617 
   5618        /*
   5619         * Decrypt using the private key.
   5620         * NOTE:  No need to reset the
   5621         *        value of bytes_encrypted.
   5622         */
   5623        crv = NSC_Decrypt(hSession,
   5624                          ciphertext,
   5625                          bytes_encrypted,
   5626                          plaintext,
   5627                          &bytes_decrypted);
   5628 
   5629        /* Finished with ciphertext; free it. */
   5630        PORT_Free(ciphertext);
   5631 
   5632        if (crv != CKR_OK) {
   5633            return crv;
   5634        }
   5635 
   5636        /*
   5637         * Check to ensure that the output plaintext
   5638         * does EQUAL known input message text.
   5639         */
   5640        if ((bytes_decrypted != PAIRWISE_MESSAGE_LENGTH) ||
   5641            (PORT_Memcmp(plaintext, known_message,
   5642                         PAIRWISE_MESSAGE_LENGTH) != 0)) {
   5643            /* Set error to Bad PUBLIC Key. */
   5644            PORT_SetError(SEC_ERROR_BAD_KEY);
   5645            return CKR_GENERAL_ERROR;
   5646        }
   5647    }
   5648 
   5649    /**********************************************/
   5650    /* Pairwise Consistency Check of Sign/Verify. */
   5651    /**********************************************/
   5652 
   5653    canSignVerify = sftk_isTrue(privateKey, CKA_SIGN);
   5654    /* Unfortunately CKA_SIGN is always true in lg dbs. We have to check the
   5655     * actual curve to determine if we can do sign/verify. */
   5656    if (canSignVerify && keyType == CKK_EC) {
   5657        NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(privateKey, CKK_EC, &crv);
   5658        if (privKey && privKey->u.ec.ecParams.name == ECCurve25519) {
   5659            canSignVerify = PR_FALSE;
   5660        }
   5661    }
   5662 
   5663    if (canSignVerify) {
   5664        CK_RSA_PKCS_PSS_PARAMS pssParams;
   5665        /* Determine length of signature. */
   5666        switch (keyType) {
   5667            case CKK_RSA:
   5668                signature_length = modulusLen;
   5669                mech.mechanism = CKM_SHA256_RSA_PKCS_PSS;
   5670                pssParams.hashAlg = CKM_SHA256;
   5671                pssParams.mgf = CKG_MGF1_SHA256;
   5672                pssParams.sLen = 0;
   5673                mech.pParameter = &pssParams;
   5674                mech.ulParameterLen = sizeof(pssParams);
   5675                break;
   5676 #ifndef NSS_DISABLE_DSA
   5677            case CKK_DSA:
   5678                signature_length = DSA_MAX_SIGNATURE_LEN;
   5679                mech.mechanism = CKM_DSA_SHA256;
   5680                break;
   5681 #endif
   5682            case CKK_EC:
   5683                signature_length = MAX_ECKEY_LEN * 2;
   5684                mech.mechanism = CKM_ECDSA_SHA256;
   5685                break;
   5686            case CKK_ML_DSA:
   5687                signature_length = MAX_ML_DSA_SIGNATURE_LEN;
   5688                mech.mechanism = CKM_ML_DSA;
   5689                break;
   5690            case CKK_EC_EDWARDS:
   5691                signature_length = ED25519_SIGN_LEN;
   5692                mech.mechanism = CKM_EDDSA;
   5693                break;
   5694            default:
   5695                return CKR_DEVICE_ERROR;
   5696        }
   5697 
   5698        /* Allocate space for signature data. */
   5699        signature = (unsigned char *)PORT_ZAlloc(signature_length);
   5700        if (signature == NULL) {
   5701            return CKR_HOST_MEMORY;
   5702        }
   5703 
   5704        /* Sign the known hash using the private key. */
   5705        crv = NSC_SignInit(hSession, &mech, privateKey->handle);
   5706        if (crv != CKR_OK) {
   5707            PORT_Free(signature);
   5708            return crv;
   5709        }
   5710 
   5711        crv = NSC_Sign(hSession,
   5712                       known_message,
   5713                       PAIRWISE_MESSAGE_LENGTH,
   5714                       signature,
   5715                       &signature_length);
   5716        if (crv != CKR_OK) {
   5717            PORT_Free(signature);
   5718            return crv;
   5719        }
   5720 
   5721        /* detect trivial signing transforms */
   5722        if ((signature_length >= PAIRWISE_MESSAGE_LENGTH) &&
   5723            (PORT_Memcmp(known_message, signature + (signature_length - PAIRWISE_MESSAGE_LENGTH), PAIRWISE_MESSAGE_LENGTH) == 0)) {
   5724            PORT_Free(signature);
   5725            return CKR_GENERAL_ERROR;
   5726        }
   5727 
   5728        /* Verify the known hash using the public key. */
   5729        crv = NSC_VerifyInit(hSession, &mech, publicKey->handle);
   5730        if (crv != CKR_OK) {
   5731            PORT_Free(signature);
   5732            return crv;
   5733        }
   5734 
   5735        crv = NSC_Verify(hSession,
   5736                         known_message,
   5737                         PAIRWISE_MESSAGE_LENGTH,
   5738                         signature,
   5739                         signature_length);
   5740 
   5741        /* Free signature data. */
   5742        PORT_Free(signature);
   5743 
   5744        if ((crv == CKR_SIGNATURE_LEN_RANGE) ||
   5745            (crv == CKR_SIGNATURE_INVALID)) {
   5746            return CKR_GENERAL_ERROR;
   5747        }
   5748        if (crv != CKR_OK) {
   5749            return crv;
   5750        }
   5751    }
   5752 
   5753    /**********************************************/
   5754    /* Pairwise Consistency Check for Derivation  */
   5755    /**********************************************/
   5756 
   5757    isDerivable = sftk_isTrue(privateKey, CKA_DERIVE);
   5758 
   5759    if (isDerivable) {
   5760        SFTKAttribute *pubAttribute = NULL;
   5761        PRBool isFIPS = sftk_isFIPS(slot->slotID);
   5762        NSSLOWKEYPrivateKey *lowPrivKey = NULL;
   5763        ECPrivateKey *ecPriv = NULL;
   5764        SECItem *lowPubValue = NULL;
   5765        SECItem item = { siBuffer, NULL, 0 };
   5766        SECStatus rv;
   5767 
   5768        crv = CKR_OK; /*paranoia, already get's set before we drop to the end */
   5769 
   5770        /* FIPS 140-3 requires we verify that the resulting key is a valid key
   5771         * by recalculating the public can an compare it to our own public
   5772         * key. */
   5773        lowPrivKey = sftk_GetPrivKey(privateKey, keyType, &crv);
   5774        if (lowPrivKey == NULL) {
   5775            return sftk_MapCryptError(PORT_GetError());
   5776        }
   5777        /* recalculate the public key from the private key */
   5778        switch (keyType) {
   5779            case CKK_DH:
   5780                rv = DH_Derive(&lowPrivKey->u.dh.base, &lowPrivKey->u.dh.prime,
   5781                               &lowPrivKey->u.dh.privateValue, &item, 0);
   5782                if (rv != SECSuccess) {
   5783                    return CKR_GENERAL_ERROR;
   5784                }
   5785                lowPubValue = SECITEM_DupItem(&item);
   5786                SECITEM_ZfreeItem(&item, PR_FALSE);
   5787                pubAttribute = sftk_FindAttribute(publicKey, CKA_VALUE);
   5788                break;
   5789            case CKK_EC_MONTGOMERY:
   5790            case CKK_EC:
   5791                rv = EC_NewKeyFromSeed(&lowPrivKey->u.ec.ecParams, &ecPriv,
   5792                                       lowPrivKey->u.ec.privateValue.data,
   5793                                       lowPrivKey->u.ec.privateValue.len);
   5794                if (rv != SECSuccess) {
   5795                    return CKR_GENERAL_ERROR;
   5796                }
   5797                /* make sure it has the same encoding */
   5798                if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") ||
   5799                    lowPrivKey->u.ec.ecParams.type != ec_params_named) {
   5800                    lowPubValue = SECITEM_DupItem(&ecPriv->publicValue);
   5801                } else {
   5802                    lowPubValue = SEC_ASN1EncodeItem(NULL, NULL, &ecPriv->publicValue,
   5803                                                     SEC_ASN1_GET(SEC_OctetStringTemplate));
   5804                }
   5805                pubAttribute = sftk_FindAttribute(publicKey, CKA_EC_POINT);
   5806                /* clear out our generated private key */
   5807                PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE);
   5808                break;
   5809            default:
   5810                return CKR_DEVICE_ERROR;
   5811        }
   5812 
   5813        /* now compare new public key with our already generated key */
   5814        if ((pubAttribute == NULL) || (lowPubValue == NULL) ||
   5815            (pubAttribute->attrib.ulValueLen != lowPubValue->len) ||
   5816            (PORT_Memcmp(pubAttribute->attrib.pValue, lowPubValue->data,
   5817                         lowPubValue->len) != 0)) {
   5818            if (pubAttribute)
   5819                sftk_FreeAttribute(pubAttribute);
   5820            if (lowPubValue)
   5821                SECITEM_ZfreeItem(lowPubValue, PR_TRUE);
   5822            PORT_SetError(SEC_ERROR_BAD_KEY);
   5823            return CKR_GENERAL_ERROR;
   5824        }
   5825        SECITEM_ZfreeItem(lowPubValue, PR_TRUE);
   5826 
   5827        /* FIPS requires full validation, but in fipx mode NSC_Derive
   5828         * only does partial validation with approved primes, now handle
   5829         * full validation */
   5830        if (isFIPS && keyType == CKK_DH) {
   5831            SECItem pubKey = { siBuffer, pubAttribute->attrib.pValue,
   5832                               pubAttribute->attrib.ulValueLen };
   5833            SECItem base = { siBuffer, NULL, 0 };
   5834            SECItem prime = { siBuffer, NULL, 0 };
   5835            SECItem subPrime = { siBuffer, NULL, 0 };
   5836            SECItem generator = { siBuffer, NULL, 0 };
   5837            const SECItem *subPrimePtr = &subPrime;
   5838 
   5839            crv = sftk_Attribute2SecItem(NULL, &prime, privateKey, CKA_PRIME);
   5840            if (crv != CKR_OK) {
   5841                goto done;
   5842            }
   5843            crv = sftk_Attribute2SecItem(NULL, &base, privateKey, CKA_BASE);
   5844            if (crv != CKR_OK) {
   5845                goto done;
   5846            }
   5847            /* we ignore the return code an only look at the length */
   5848            /* do we have a known prime ? */
   5849            subPrimePtr = sftk_VerifyDH_Prime(&prime, &generator, isFIPS);
   5850            if (subPrimePtr == NULL) {
   5851                if (subPrime.len == 0) {
   5852                    /* if not a known prime, subprime must be supplied */
   5853                    crv = CKR_ATTRIBUTE_VALUE_INVALID;
   5854                    goto done;
   5855                } else {
   5856                    /* not a known prime, check for primality of prime
   5857                     * and subPrime */
   5858                    if (!KEA_PrimeCheck(&prime)) {
   5859                        crv = CKR_ATTRIBUTE_VALUE_INVALID;
   5860                        goto done;
   5861                    }
   5862                    if (!KEA_PrimeCheck(&subPrime)) {
   5863                        crv = CKR_ATTRIBUTE_VALUE_INVALID;
   5864                        goto done;
   5865                    }
   5866                    /* if we aren't using a defined group, make sure base is in the
   5867                     * subgroup. If it's not, then our key could fail or succeed sometimes.
   5868                     * This makes the failure reliable */
   5869                    if (!KEA_Verify(&base, &prime, &subPrime)) {
   5870                        crv = CKR_ATTRIBUTE_VALUE_INVALID;
   5871                    }
   5872                }
   5873                subPrimePtr = &subPrime;
   5874            } else {
   5875                /* we're using a known group, make sure we are using the known generator for that group */
   5876                if (SECITEM_CompareItem(&generator, &base) != 0) {
   5877                    crv = CKR_ATTRIBUTE_VALUE_INVALID;
   5878                    goto done;
   5879                }
   5880                if (subPrime.len != 0) {
   5881                    /* we have a known prime and a supplied subPrime,
   5882                     * make sure the subPrime matches the subPrime for
   5883                     * the known Prime */
   5884                    if (SECITEM_CompareItem(subPrimePtr, &subPrime) != 0) {
   5885                        crv = CKR_ATTRIBUTE_VALUE_INVALID;
   5886                        goto done;
   5887                    }
   5888                }
   5889            }
   5890            if (!KEA_Verify(&pubKey, &prime, (SECItem *)subPrimePtr)) {
   5891                crv = CKR_ATTRIBUTE_VALUE_INVALID;
   5892            }
   5893        done:
   5894            SECITEM_ZfreeItem(&base, PR_FALSE);
   5895            SECITEM_ZfreeItem(&subPrime, PR_FALSE);
   5896            SECITEM_ZfreeItem(&prime, PR_FALSE);
   5897        }
   5898        /* clean up before we return */
   5899        sftk_FreeAttribute(pubAttribute);
   5900        if (crv != CKR_OK) {
   5901            return crv;
   5902        }
   5903    }
   5904 
   5905    isKEM = sftk_isTrue(privateKey, CKA_ENCAPSULATE);
   5906    if (isKEM) {
   5907        unsigned char *cipher_text = NULL;
   5908        CK_ULONG cipher_text_length = 0;
   5909        CK_OBJECT_HANDLE key1 = CK_INVALID_HANDLE;
   5910        CK_OBJECT_HANDLE key2 = CK_INVALID_HANDLE;
   5911        CK_KEY_TYPE genType = CKO_SECRET_KEY;
   5912        CK_ATTRIBUTE template = { CKA_KEY_TYPE, NULL, 0 };
   5913 
   5914        template.pValue = &genType;
   5915        template.ulValueLen = sizeof(genType);
   5916        crv = CKR_OK;
   5917        switch (keyType) {
   5918            case CKK_ML_KEM:
   5919                cipher_text_length = MAX_ML_KEM_CIPHER_LENGTH;
   5920                mech.mechanism = CKM_ML_KEM;
   5921                break;
   5922            default:
   5923                return CKR_DEVICE_ERROR;
   5924        }
   5925        /* Allocate space for kem cipher text. */
   5926        cipher_text = (unsigned char *)PORT_ZAlloc(cipher_text_length);
   5927        if (cipher_text == NULL) {
   5928            return CKR_HOST_MEMORY;
   5929        }
   5930        crv = NSC_Encapsulate(hSession, &mech, publicKey->handle, &template, 1,
   5931                              &key1, cipher_text, &cipher_text_length);
   5932        if (crv != CKR_OK) {
   5933            goto kem_done;
   5934        }
   5935        crv = NSC_Decapsulate(hSession, &mech, privateKey->handle,
   5936                              cipher_text, cipher_text_length, &template, 1,
   5937                              &key2);
   5938        if (crv != CKR_OK) {
   5939            goto kem_done;
   5940        }
   5941        if (!sftk_compareKeysEqual(hSession, key1, key2)) {
   5942            crv = CKR_DEVICE_ERROR;
   5943            goto kem_done;
   5944        }
   5945    kem_done:
   5946        /* PORT_Free already checks for NULL */
   5947        PORT_Free(cipher_text);
   5948        if (key1 != CK_INVALID_HANDLE) {
   5949            NSC_DestroyObject(hSession, key1);
   5950        }
   5951        if (key2 != CK_INVALID_HANDLE) {
   5952            NSC_DestroyObject(hSession, key2);
   5953        }
   5954        if (crv != CKR_OK) {
   5955            return CKR_DEVICE_ERROR;
   5956        }
   5957    }
   5958 
   5959    return CKR_OK;
   5960 }
   5961 
   5962 /* NSC_GenerateKeyPair generates a public-key/private-key pair,
   5963 * creating new key objects. */
   5964 CK_RV
   5965 NSC_GenerateKeyPair(CK_SESSION_HANDLE hSession,
   5966                    CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate,
   5967                    CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
   5968                    CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey,
   5969                    CK_OBJECT_HANDLE_PTR phPrivateKey)
   5970 {
   5971    SFTKObject *publicKey, *privateKey;
   5972    SFTKSession *session;
   5973    CK_KEY_TYPE key_type;
   5974    CK_RV crv = CKR_OK;
   5975    CK_BBOOL cktrue = CK_TRUE;
   5976    SECStatus rv;
   5977    CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
   5978    CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
   5979    int i;
   5980    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
   5981    unsigned int bitSize;
   5982 
   5983    /* RSA */
   5984    int public_modulus_bits = 0;
   5985    SECItem pubExp;
   5986    RSAPrivateKey *rsaPriv;
   5987 
   5988    DHParams dhParam;
   5989 #ifndef NSS_DISABLE_DSA
   5990    /* DSA */
   5991    PQGParams pqgParam;
   5992    DSAPrivateKey *dsaPriv;
   5993 #endif
   5994    MLDSAPrivateKey mldsaPriv;
   5995    MLDSAPublicKey mldsaPub;
   5996 
   5997    /* Diffie Hellman */
   5998    DHPrivateKey *dhPriv;
   5999 
   6000    /* Elliptic Curve Cryptography */
   6001    SECItem ecEncodedParams; /* DER Encoded parameters */
   6002    ECPrivateKey *ecPriv;
   6003    ECParams *ecParams;
   6004 
   6005    /* parameter set, mostly pq keys */
   6006    CK_ULONG genParamSet = 0;
   6007 
   6008    CHECK_FORK();
   6009 
   6010    if (!slot) {
   6011        return CKR_SESSION_HANDLE_INVALID;
   6012    }
   6013    /*
   6014     * now lets create an object to hang the attributes off of
   6015     */
   6016    publicKey = sftk_NewObject(slot); /* fill in the handle later */
   6017    if (publicKey == NULL) {
   6018        return CKR_HOST_MEMORY;
   6019    }
   6020 
   6021    /*
   6022     * load the template values into the publicKey
   6023     */
   6024    for (i = 0; i < (int)ulPublicKeyAttributeCount; i++) {
   6025        if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) {
   6026            public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue;
   6027            continue;
   6028        }
   6029 
   6030        if ((pPublicKeyTemplate[i].type == CKA_PARAMETER_SET) ||
   6031            (pPublicKeyTemplate[i].type == CKA_NSS_PARAMETER_SET)) {
   6032            genParamSet = *(CK_ULONG *)pPublicKeyTemplate[i].pValue;
   6033            continue;
   6034        }
   6035 
   6036        crv = sftk_AddAttributeType(publicKey,
   6037                                    sftk_attr_expand(&pPublicKeyTemplate[i]));
   6038        if (crv != CKR_OK)
   6039            break;
   6040    }
   6041 
   6042    if (crv != CKR_OK) {
   6043        sftk_FreeObject(publicKey);
   6044        return CKR_HOST_MEMORY;
   6045    }
   6046 
   6047    privateKey = sftk_NewObject(slot); /* fill in the handle later */
   6048    if (privateKey == NULL) {
   6049        sftk_FreeObject(publicKey);
   6050        return CKR_HOST_MEMORY;
   6051    }
   6052    /*
   6053     * now load the private key template
   6054     */
   6055    for (i = 0; i < (int)ulPrivateKeyAttributeCount; i++) {
   6056        if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) {
   6057            continue;
   6058        }
   6059 
   6060        crv = sftk_AddAttributeType(privateKey,
   6061                                    sftk_attr_expand(&pPrivateKeyTemplate[i]));
   6062        if (crv != CKR_OK)
   6063            break;
   6064    }
   6065 
   6066    if (crv != CKR_OK) {
   6067        sftk_FreeObject(publicKey);
   6068        sftk_FreeObject(privateKey);
   6069        return CKR_HOST_MEMORY;
   6070    }
   6071    sftk_DeleteAttributeType(privateKey, CKA_CLASS);
   6072    sftk_DeleteAttributeType(privateKey, CKA_KEY_TYPE);
   6073    sftk_DeleteAttributeType(privateKey, CKA_VALUE);
   6074    sftk_DeleteAttributeType(publicKey, CKA_CLASS);
   6075    sftk_DeleteAttributeType(publicKey, CKA_KEY_TYPE);
   6076    sftk_DeleteAttributeType(publicKey, CKA_VALUE);
   6077 
   6078    /* Now Set up the parameters to generate the key (based on mechanism) */
   6079    switch (pMechanism->mechanism) {
   6080        case CKM_RSA_PKCS_KEY_PAIR_GEN:
   6081            /* format the keys */
   6082            sftk_DeleteAttributeType(publicKey, CKA_MODULUS);
   6083            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
   6084            sftk_DeleteAttributeType(privateKey, CKA_MODULUS);
   6085            sftk_DeleteAttributeType(privateKey, CKA_PRIVATE_EXPONENT);
   6086            sftk_DeleteAttributeType(privateKey, CKA_PUBLIC_EXPONENT);
   6087            sftk_DeleteAttributeType(privateKey, CKA_PRIME_1);
   6088            sftk_DeleteAttributeType(privateKey, CKA_PRIME_2);
   6089            sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_1);
   6090            sftk_DeleteAttributeType(privateKey, CKA_EXPONENT_2);
   6091            sftk_DeleteAttributeType(privateKey, CKA_COEFFICIENT);
   6092            key_type = CKK_RSA;
   6093            if (public_modulus_bits == 0) {
   6094                crv = CKR_TEMPLATE_INCOMPLETE;
   6095                break;
   6096            }
   6097            if (public_modulus_bits < RSA_MIN_MODULUS_BITS) {
   6098                crv = CKR_ATTRIBUTE_VALUE_INVALID;
   6099                break;
   6100            }
   6101            if (public_modulus_bits % 2 != 0) {
   6102                crv = CKR_ATTRIBUTE_VALUE_INVALID;
   6103                break;
   6104            }
   6105 
   6106            /* extract the exponent */
   6107            crv = sftk_Attribute2SSecItem(NULL, &pubExp, publicKey, CKA_PUBLIC_EXPONENT);
   6108            if (crv != CKR_OK)
   6109                break;
   6110            bitSize = sftk_GetLengthInBits(pubExp.data, pubExp.len);
   6111            if (bitSize < 2) {
   6112                crv = CKR_ATTRIBUTE_VALUE_INVALID;
   6113                SECITEM_ZfreeItem(&pubExp, PR_FALSE);
   6114                break;
   6115            }
   6116            crv = sftk_AddAttributeType(privateKey, CKA_PUBLIC_EXPONENT,
   6117                                        sftk_item_expand(&pubExp));
   6118            if (crv != CKR_OK) {
   6119                SECITEM_ZfreeItem(&pubExp, PR_FALSE);
   6120                break;
   6121            }
   6122 
   6123            rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp);
   6124            SECITEM_ZfreeItem(&pubExp, PR_FALSE);
   6125            if (rsaPriv == NULL) {
   6126                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
   6127                    sftk_fatalError = PR_TRUE;
   6128                }
   6129                crv = sftk_MapCryptError(PORT_GetError());
   6130                break;
   6131            }
   6132            /* now fill in the RSA dependent paramenters in the public key */
   6133            crv = sftk_AddAttributeType(publicKey, CKA_MODULUS,
   6134                                        sftk_item_expand(&rsaPriv->modulus));
   6135            if (crv != CKR_OK)
   6136                goto kpg_done;
   6137            /* now fill in the RSA dependent paramenters in the private key */
   6138            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
   6139                                        sftk_item_expand(&rsaPriv->modulus));
   6140            if (crv != CKR_OK)
   6141                goto kpg_done;
   6142            crv = sftk_AddAttributeType(privateKey, CKA_MODULUS,
   6143                                        sftk_item_expand(&rsaPriv->modulus));
   6144            if (crv != CKR_OK)
   6145                goto kpg_done;
   6146            crv = sftk_AddAttributeType(privateKey, CKA_PRIVATE_EXPONENT,
   6147                                        sftk_item_expand(&rsaPriv->privateExponent));
   6148            if (crv != CKR_OK)
   6149                goto kpg_done;
   6150            crv = sftk_AddAttributeType(privateKey, CKA_PRIME_1,
   6151                                        sftk_item_expand(&rsaPriv->prime1));
   6152            if (crv != CKR_OK)
   6153                goto kpg_done;
   6154            crv = sftk_AddAttributeType(privateKey, CKA_PRIME_2,
   6155                                        sftk_item_expand(&rsaPriv->prime2));
   6156            if (crv != CKR_OK)
   6157                goto kpg_done;
   6158            crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_1,
   6159                                        sftk_item_expand(&rsaPriv->exponent1));
   6160            if (crv != CKR_OK)
   6161                goto kpg_done;
   6162            crv = sftk_AddAttributeType(privateKey, CKA_EXPONENT_2,
   6163                                        sftk_item_expand(&rsaPriv->exponent2));
   6164            if (crv != CKR_OK)
   6165                goto kpg_done;
   6166            crv = sftk_AddAttributeType(privateKey, CKA_COEFFICIENT,
   6167                                        sftk_item_expand(&rsaPriv->coefficient));
   6168        kpg_done:
   6169            /* Should zeroize the contents first, since this func doesn't. */
   6170            PORT_FreeArena(rsaPriv->arena, PR_TRUE);
   6171            break;
   6172 #ifndef NSS_DISABLE_DSA
   6173        case CKM_DSA_KEY_PAIR_GEN:
   6174            sftk_DeleteAttributeType(publicKey, CKA_VALUE);
   6175            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
   6176            sftk_DeleteAttributeType(privateKey, CKA_PRIME);
   6177            sftk_DeleteAttributeType(privateKey, CKA_SUBPRIME);
   6178            sftk_DeleteAttributeType(privateKey, CKA_BASE);
   6179            key_type = CKK_DSA;
   6180 
   6181            /* extract the necessary parameters and copy them to the private key */
   6182            crv = sftk_Attribute2SSecItem(NULL, &pqgParam.prime, publicKey, CKA_PRIME);
   6183            if (crv != CKR_OK)
   6184                break;
   6185            crv = sftk_Attribute2SSecItem(NULL, &pqgParam.subPrime, publicKey,
   6186                                          CKA_SUBPRIME);
   6187            if (crv != CKR_OK) {
   6188                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
   6189                break;
   6190            }
   6191            crv = sftk_Attribute2SSecItem(NULL, &pqgParam.base, publicKey, CKA_BASE);
   6192            if (crv != CKR_OK) {
   6193                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
   6194                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
   6195                break;
   6196            }
   6197            crv = sftk_AddAttributeType(privateKey, CKA_PRIME,
   6198                                        sftk_item_expand(&pqgParam.prime));
   6199            if (crv != CKR_OK) {
   6200                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
   6201                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
   6202                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
   6203                break;
   6204            }
   6205            crv = sftk_AddAttributeType(privateKey, CKA_SUBPRIME,
   6206                                        sftk_item_expand(&pqgParam.subPrime));
   6207            if (crv != CKR_OK) {
   6208                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
   6209                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
   6210                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
   6211                break;
   6212            }
   6213            crv = sftk_AddAttributeType(privateKey, CKA_BASE,
   6214                                        sftk_item_expand(&pqgParam.base));
   6215            if (crv != CKR_OK) {
   6216                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
   6217                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
   6218                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
   6219                break;
   6220            }
   6221 
   6222            /*
   6223             * these are checked by DSA_NewKey
   6224             */
   6225            bitSize = sftk_GetLengthInBits(pqgParam.subPrime.data,
   6226                                           pqgParam.subPrime.len);
   6227            if ((bitSize < DSA_MIN_Q_BITS) || (bitSize > DSA_MAX_Q_BITS)) {
   6228                crv = CKR_TEMPLATE_INCOMPLETE;
   6229                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
   6230                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
   6231                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
   6232                break;
   6233            }
   6234            bitSize = sftk_GetLengthInBits(pqgParam.prime.data, pqgParam.prime.len);
   6235            if ((bitSize < DSA_MIN_P_BITS) || (bitSize > DSA_MAX_P_BITS)) {
   6236                crv = CKR_TEMPLATE_INCOMPLETE;
   6237                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
   6238                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
   6239                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
   6240                break;
   6241            }
   6242            bitSize = sftk_GetLengthInBits(pqgParam.base.data, pqgParam.base.len);
   6243            if ((bitSize < 2) || (bitSize > DSA_MAX_P_BITS)) {
   6244                crv = CKR_TEMPLATE_INCOMPLETE;
   6245                SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
   6246                SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
   6247                SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
   6248                break;
   6249            }
   6250 
   6251            /* Generate the key */
   6252            rv = DSA_NewKey(&pqgParam, &dsaPriv);
   6253 
   6254            SECITEM_ZfreeItem(&pqgParam.prime, PR_FALSE);
   6255            SECITEM_ZfreeItem(&pqgParam.subPrime, PR_FALSE);
   6256            SECITEM_ZfreeItem(&pqgParam.base, PR_FALSE);
   6257 
   6258            if (rv != SECSuccess) {
   6259                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
   6260                    sftk_fatalError = PR_TRUE;
   6261                }
   6262                crv = sftk_MapCryptError(PORT_GetError());
   6263                break;
   6264            }
   6265 
   6266            /* store the generated key into the attributes */
   6267            crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
   6268                                        sftk_item_expand(&dsaPriv->publicValue));
   6269            if (crv != CKR_OK)
   6270                goto dsagn_done;
   6271 
   6272            /* now fill in the RSA dependent paramenters in the private key */
   6273            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
   6274                                        sftk_item_expand(&dsaPriv->publicValue));
   6275            if (crv != CKR_OK)
   6276                goto dsagn_done;
   6277            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
   6278                                        sftk_item_expand(&dsaPriv->privateValue));
   6279 
   6280        dsagn_done:
   6281            /* should zeroize, since this function doesn't. */
   6282            PORT_FreeArena(dsaPriv->params.arena, PR_TRUE);
   6283            break;
   6284 #endif
   6285        case CKM_DH_PKCS_KEY_PAIR_GEN:
   6286            sftk_DeleteAttributeType(privateKey, CKA_PRIME);
   6287            sftk_DeleteAttributeType(privateKey, CKA_BASE);
   6288            sftk_DeleteAttributeType(privateKey, CKA_VALUE);
   6289            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
   6290            key_type = CKK_DH;
   6291 
   6292            /* extract the necessary parameters and copy them to private keys */
   6293            crv = sftk_Attribute2SSecItem(NULL, &dhParam.prime, publicKey,
   6294                                          CKA_PRIME);
   6295            if (crv != CKR_OK)
   6296                break;
   6297            crv = sftk_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE);
   6298            if (crv != CKR_OK) {
   6299                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
   6300                break;
   6301            }
   6302            crv = sftk_AddAttributeType(privateKey, CKA_PRIME,
   6303                                        sftk_item_expand(&dhParam.prime));
   6304            if (crv != CKR_OK) {
   6305                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
   6306                SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
   6307                break;
   6308            }
   6309            crv = sftk_AddAttributeType(privateKey, CKA_BASE,
   6310                                        sftk_item_expand(&dhParam.base));
   6311            if (crv != CKR_OK) {
   6312                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
   6313                SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
   6314                break;
   6315            }
   6316            bitSize = sftk_GetLengthInBits(dhParam.prime.data, dhParam.prime.len);
   6317            if ((bitSize < DH_MIN_P_BITS) || (bitSize > DH_MAX_P_BITS)) {
   6318                crv = CKR_TEMPLATE_INCOMPLETE;
   6319                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
   6320                SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
   6321                break;
   6322            }
   6323            bitSize = sftk_GetLengthInBits(dhParam.base.data, dhParam.base.len);
   6324            if ((bitSize < 1) || (bitSize > DH_MAX_P_BITS)) {
   6325                crv = CKR_TEMPLATE_INCOMPLETE;
   6326                SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
   6327                SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
   6328                break;
   6329            }
   6330 
   6331            rv = DH_NewKey(&dhParam, &dhPriv);
   6332            SECITEM_ZfreeItem(&dhParam.prime, PR_FALSE);
   6333            SECITEM_ZfreeItem(&dhParam.base, PR_FALSE);
   6334            if (rv != SECSuccess) {
   6335                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
   6336                    sftk_fatalError = PR_TRUE;
   6337                }
   6338                crv = sftk_MapCryptError(PORT_GetError());
   6339                break;
   6340            }
   6341 
   6342            crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
   6343                                        sftk_item_expand(&dhPriv->publicValue));
   6344            if (crv != CKR_OK)
   6345                goto dhgn_done;
   6346 
   6347            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
   6348                                        sftk_item_expand(&dhPriv->publicValue));
   6349            if (crv != CKR_OK)
   6350                goto dhgn_done;
   6351 
   6352            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
   6353                                        sftk_item_expand(&dhPriv->privateValue));
   6354 
   6355        dhgn_done:
   6356            /* should zeroize, since this function doesn't. */
   6357            PORT_FreeArena(dhPriv->arena, PR_TRUE);
   6358            break;
   6359 
   6360        case CKM_EC_KEY_PAIR_GEN:
   6361        case CKM_NSS_ECDHE_NO_PAIRWISE_CHECK_KEY_PAIR_GEN:
   6362            sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS);
   6363            sftk_DeleteAttributeType(privateKey, CKA_VALUE);
   6364            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
   6365            key_type = CKK_EC;
   6366 
   6367            /* extract the necessary parameters and copy them to private keys */
   6368            crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey,
   6369                                          CKA_EC_PARAMS);
   6370            if (crv != CKR_OK)
   6371                break;
   6372 
   6373            crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS,
   6374                                        sftk_item_expand(&ecEncodedParams));
   6375            if (crv != CKR_OK) {
   6376                SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE);
   6377                break;
   6378            }
   6379 
   6380            /* Decode ec params before calling EC_NewKey */
   6381            rv = EC_DecodeParams(&ecEncodedParams, &ecParams);
   6382            SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE);
   6383            if (rv != SECSuccess) {
   6384                crv = sftk_MapCryptError(PORT_GetError());
   6385                break;
   6386            }
   6387            rv = EC_NewKey(ecParams, &ecPriv);
   6388            if (rv != SECSuccess) {
   6389                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
   6390                    sftk_fatalError = PR_TRUE;
   6391                }
   6392                PORT_FreeArena(ecParams->arena, PR_TRUE);
   6393                crv = sftk_MapCryptError(PORT_GetError());
   6394                break;
   6395            }
   6396 
   6397            if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT") ||
   6398                ecParams->type != ec_params_named) {
   6399                PORT_FreeArena(ecParams->arena, PR_TRUE);
   6400                crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
   6401                                            sftk_item_expand(&ecPriv->publicValue));
   6402            } else {
   6403                PORT_FreeArena(ecParams->arena, PR_TRUE);
   6404                SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL,
   6405                                                       &ecPriv->publicValue,
   6406                                                       SEC_ASN1_GET(SEC_OctetStringTemplate));
   6407                if (!pubValue) {
   6408                    crv = CKR_ARGUMENTS_BAD;
   6409                    goto ecgn_done;
   6410                }
   6411                crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
   6412                                            sftk_item_expand(pubValue));
   6413                SECITEM_ZfreeItem(pubValue, PR_TRUE);
   6414            }
   6415            if (crv != CKR_OK)
   6416                goto ecgn_done;
   6417 
   6418            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
   6419                                        sftk_item_expand(&ecPriv->privateValue));
   6420            if (crv != CKR_OK)
   6421                goto ecgn_done;
   6422 
   6423            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
   6424                                        sftk_item_expand(&ecPriv->publicValue));
   6425        ecgn_done:
   6426            /* should zeroize, since this function doesn't. */
   6427            PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE);
   6428            break;
   6429 
   6430 #ifndef NSS_DISABLE_KYBER
   6431        case CKM_NSS_KYBER_KEY_PAIR_GEN:
   6432            key_type = CKK_NSS_KYBER;
   6433            goto do_ml_kem;
   6434 #endif
   6435        case CKM_NSS_ML_KEM_KEY_PAIR_GEN:
   6436            key_type = CKK_NSS_ML_KEM;
   6437            goto do_ml_kem;
   6438 
   6439        case CKM_ML_KEM_KEY_PAIR_GEN:
   6440            key_type = CKK_ML_KEM;
   6441 
   6442        do_ml_kem:
   6443            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
   6444            SECItem privKey = { siBuffer, NULL, 0 };
   6445            SECItem pubKey = { siBuffer, NULL, 0 };
   6446            KyberParams kyberParams = sftk_kyber_PK11ParamToInternal(genParamSet);
   6447            if (!sftk_kyber_AllocPrivKeyItem(kyberParams, &privKey)) {
   6448                crv = CKR_HOST_MEMORY;
   6449                goto kyber_done;
   6450            }
   6451            if (!sftk_kyber_AllocPubKeyItem(kyberParams, &pubKey)) {
   6452                crv = CKR_HOST_MEMORY;
   6453                goto kyber_done;
   6454            }
   6455            rv = Kyber_NewKey(kyberParams, NULL, &privKey, &pubKey);
   6456            if (rv != SECSuccess) {
   6457                crv = sftk_MapCryptError(PORT_GetError());
   6458                goto kyber_done;
   6459            }
   6460 
   6461            crv = sftk_AddAttributeType(publicKey, CKA_VALUE, sftk_item_expand(&pubKey));
   6462            if (crv != CKR_OK) {
   6463                goto kyber_done;
   6464            }
   6465            crv = sftk_AddAttributeType(publicKey, CKA_PARAMETER_SET,
   6466                                        &genParamSet,
   6467                                        sizeof(CK_ML_KEM_PARAMETER_SET_TYPE));
   6468            if (crv != CKR_OK) {
   6469                goto kyber_done;
   6470            }
   6471            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
   6472                                        sftk_item_expand(&privKey));
   6473            if (crv != CKR_OK) {
   6474                goto kyber_done;
   6475            }
   6476            crv = sftk_AddAttributeType(privateKey, CKA_PARAMETER_SET,
   6477                                        &genParamSet,
   6478                                        sizeof(CK_ML_KEM_PARAMETER_SET_TYPE));
   6479            if (crv != CKR_OK) {
   6480                goto kyber_done;
   6481            }
   6482            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
   6483                                        sftk_item_expand(&pubKey));
   6484        kyber_done:
   6485            SECITEM_ZfreeItem(&privKey, PR_FALSE);
   6486            SECITEM_FreeItem(&pubKey, PR_FALSE);
   6487            break;
   6488 
   6489        case CKM_ML_DSA_KEY_PAIR_GEN:
   6490            sftk_DeleteAttributeType(publicKey, CKA_VALUE);
   6491            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
   6492            sftk_DeleteAttributeType(privateKey, CKA_SEED);
   6493            key_type = CKK_ML_DSA;
   6494 
   6495            /*
   6496             * the parameters are recognized by us
   6497             */
   6498            bitSize = sftk_MLDSAGetSigLen(genParamSet);
   6499            if (bitSize == 0) {
   6500                crv = CKR_TEMPLATE_INCOMPLETE;
   6501                break;
   6502            }
   6503 
   6504            /* Generate the key */
   6505            rv = MLDSA_NewKey(genParamSet, NULL, &mldsaPriv, &mldsaPub);
   6506 
   6507            if (rv != SECSuccess) {
   6508                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
   6509                    sftk_fatalError = PR_TRUE;
   6510                }
   6511                crv = sftk_MapCryptError(PORT_GetError());
   6512                break;
   6513            }
   6514 
   6515            /* store the generated key into the attributes */
   6516            crv = sftk_AddAttributeType(publicKey, CKA_VALUE,
   6517                                        mldsaPub.keyVal, mldsaPub.keyValLen);
   6518            if (crv != CKR_OK)
   6519                goto mldsagn_done;
   6520            crv = sftk_AddAttributeType(publicKey, CKA_PARAMETER_SET,
   6521                                        &genParamSet, sizeof(CK_ML_DSA_PARAMETER_SET_TYPE));
   6522            if (crv != CKR_OK) {
   6523                goto mldsagn_done;
   6524            }
   6525 
   6526            /* now fill in the ML-DSA specfic paramenters in the private key */
   6527            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
   6528                                        mldsaPub.keyVal, mldsaPub.keyValLen);
   6529            if (crv != CKR_OK)
   6530                goto mldsagn_done;
   6531 
   6532            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
   6533                                        mldsaPriv.keyVal,
   6534                                        mldsaPriv.keyValLen);
   6535            if (crv != CKR_OK)
   6536                goto mldsagn_done;
   6537            crv = sftk_AddAttributeType(privateKey, CKA_PARAMETER_SET,
   6538                                        &genParamSet, sizeof(CK_ML_DSA_PARAMETER_SET_TYPE));
   6539            if (crv != CKR_OK) {
   6540                goto mldsagn_done;
   6541            }
   6542 
   6543            if (mldsaPriv.seedLen != 0) {
   6544                crv = sftk_AddAttributeType(privateKey, CKA_SEED,
   6545                                            mldsaPriv.seed, mldsaPriv.seedLen);
   6546                if (crv != CKR_OK) {
   6547                    goto mldsagn_done;
   6548                }
   6549                /* pseudo attribute that says the seed came with the key
   6550                 * so don't try to regenerate the key in handleObject.
   6551                 * it will be removed before the object sees the light of
   6552                 * day. */
   6553                crv = sftk_AddAttributeType(privateKey, CKA_NSS_SEED_OK,
   6554                                            NULL, 0);
   6555                /* it was either this or  a comment 'fall through' which would
   6556                 * be cryptic to some users */
   6557                if (crv != CKR_OK) {
   6558                    goto mldsagn_done;
   6559                }
   6560            }
   6561        mldsagn_done:
   6562            PORT_SafeZero(&mldsaPriv, sizeof(mldsaPriv));
   6563            PORT_SafeZero(&mldsaPub, sizeof(mldsaPub));
   6564            break;
   6565 
   6566        case CKM_EC_MONTGOMERY_KEY_PAIR_GEN:
   6567        case CKM_EC_EDWARDS_KEY_PAIR_GEN:
   6568            sftk_DeleteAttributeType(privateKey, CKA_EC_PARAMS);
   6569            sftk_DeleteAttributeType(privateKey, CKA_VALUE);
   6570            sftk_DeleteAttributeType(privateKey, CKA_NSS_DB);
   6571            key_type = (pMechanism->mechanism == CKM_EC_EDWARDS_KEY_PAIR_GEN) ? CKK_EC_EDWARDS : CKK_EC_MONTGOMERY;
   6572 
   6573            /* extract the necessary parameters and copy them to private keys */
   6574            crv = sftk_Attribute2SSecItem(NULL, &ecEncodedParams, publicKey,
   6575                                          CKA_EC_PARAMS);
   6576            if (crv != CKR_OK) {
   6577                break;
   6578            }
   6579 
   6580            crv = sftk_AddAttributeType(privateKey, CKA_EC_PARAMS,
   6581                                        sftk_item_expand(&ecEncodedParams));
   6582            if (crv != CKR_OK) {
   6583                SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE);
   6584                break;
   6585            }
   6586 
   6587            /* Decode ec params before calling EC_NewKey */
   6588            rv = EC_DecodeParams(&ecEncodedParams, &ecParams);
   6589            SECITEM_ZfreeItem(&ecEncodedParams, PR_FALSE);
   6590            if (rv != SECSuccess) {
   6591                crv = sftk_MapCryptError(PORT_GetError());
   6592                break;
   6593            }
   6594 
   6595            rv = EC_NewKey(ecParams, &ecPriv);
   6596            if (rv != SECSuccess) {
   6597                if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) {
   6598                    sftk_fatalError = PR_TRUE;
   6599                }
   6600                PORT_FreeArena(ecParams->arena, PR_TRUE);
   6601                crv = sftk_MapCryptError(PORT_GetError());
   6602                break;
   6603            }
   6604            PORT_FreeArena(ecParams->arena, PR_TRUE);
   6605            crv = sftk_AddAttributeType(publicKey, CKA_EC_POINT,
   6606                                        sftk_item_expand(&ecPriv->publicValue));
   6607            if (crv != CKR_OK)
   6608                goto edgn_done;
   6609 
   6610            crv = sftk_AddAttributeType(privateKey, CKA_VALUE,
   6611                                        sftk_item_expand(&ecPriv->privateValue));
   6612            if (crv != CKR_OK)
   6613                goto edgn_done;
   6614 
   6615            crv = sftk_AddAttributeType(privateKey, CKA_NSS_DB,
   6616                                        sftk_item_expand(&ecPriv->publicValue));
   6617        edgn_done:
   6618            /* should zeroize, since this function doesn't. */
   6619            PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE);
   6620            break;
   6621 
   6622        default:
   6623            crv = CKR_MECHANISM_INVALID;
   6624    }
   6625 
   6626    if (crv != CKR_OK) {
   6627        sftk_FreeObject(privateKey);
   6628        sftk_FreeObject(publicKey);
   6629        return crv;
   6630    }
   6631 
   6632    /* Add the class, key_type The loop lets us check errors blow out
   6633     *  on errors and clean up at the bottom */
   6634    session = NULL; /* make pedtantic happy... session cannot leave the*/
   6635                    /* loop below NULL unless an error is set... */
   6636    do {
   6637        crv = sftk_AddAttributeType(privateKey, CKA_CLASS, &privClass,
   6638                                    sizeof(CK_OBJECT_CLASS));
   6639        if (crv != CKR_OK)
   6640            break;
   6641        crv = sftk_AddAttributeType(publicKey, CKA_CLASS, &pubClass,
   6642                                    sizeof(CK_OBJECT_CLASS));
   6643        if (crv != CKR_OK)
   6644            break;
   6645        crv = sftk_AddAttributeType(privateKey, CKA_KEY_TYPE, &key_type,
   6646                                    sizeof(CK_KEY_TYPE));
   6647        if (crv != CKR_OK)
   6648            break;
   6649        crv = sftk_AddAttributeType(publicKey, CKA_KEY_TYPE, &key_type,
   6650                                    sizeof(CK_KEY_TYPE));
   6651        if (crv != CKR_OK)
   6652            break;
   6653        session = sftk_SessionFromHandle(hSession);
   6654        if (session == NULL)
   6655            crv = CKR_SESSION_HANDLE_INVALID;
   6656    } while (0);
   6657 
   6658    if (crv != CKR_OK) {
   6659        sftk_FreeObject(privateKey);
   6660        sftk_FreeObject(publicKey);
   6661        return crv;
   6662    }
   6663 
   6664    /*
   6665     * handle the base object cleanup for the public Key
   6666     */
   6667    crv = sftk_handleObject(privateKey, session);
   6668    if (crv != CKR_OK) {
   6669        sftk_FreeSession(session);
   6670        sftk_FreeObject(privateKey);
   6671        sftk_FreeObject(publicKey);
   6672        return crv;
   6673    }
   6674 
   6675    /*
   6676     * handle the base object cleanup for the private Key
   6677     * If we have any problems, we destroy the public Key we've
   6678     * created and linked.
   6679     */
   6680    crv = sftk_handleObject(publicKey, session);
   6681    sftk_FreeSession(session);
   6682    if (crv != CKR_OK) {
   6683        sftk_FreeObject(publicKey);
   6684        NSC_DestroyObject(hSession, privateKey->handle);
   6685        sftk_FreeObject(privateKey);
   6686        return crv;
   6687    }
   6688    if (sftk_isTrue(privateKey, CKA_SENSITIVE)) {
   6689        crv = sftk_forceAttribute(privateKey, CKA_ALWAYS_SENSITIVE,
   6690                                  &cktrue, sizeof(CK_BBOOL));
   6691    }
   6692    if (crv == CKR_OK && sftk_isTrue(publicKey, CKA_SENSITIVE)) {
   6693        crv = sftk_forceAttribute(publicKey, CKA_ALWAYS_SENSITIVE,
   6694                                  &cktrue, sizeof(CK_BBOOL));
   6695    }
   6696    if (crv == CKR_OK && !sftk_isTrue(privateKey, CKA_EXTRACTABLE)) {
   6697        crv = sftk_forceAttribute(privateKey, CKA_NEVER_EXTRACTABLE,
   6698                                  &cktrue, sizeof(CK_BBOOL));
   6699    }
   6700    if (crv == CKR_OK && !sftk_isTrue(publicKey, CKA_EXTRACTABLE)) {
   6701        crv = sftk_forceAttribute(publicKey, CKA_NEVER_EXTRACTABLE,
   6702                                  &cktrue, sizeof(CK_BBOOL));
   6703    }
   6704 
   6705    if (crv == CKR_OK &&
   6706        pMechanism->mechanism != CKM_NSS_ECDHE_NO_PAIRWISE_CHECK_KEY_PAIR_GEN) {
   6707        /* Perform FIPS 140-2 pairwise consistency check. */
   6708        crv = sftk_PairwiseConsistencyCheck(hSession, slot,
   6709                                            publicKey, privateKey, key_type);
   6710        if (crv != CKR_OK) {
   6711            if (sftk_audit_enabled) {
   6712                char msg[128];
   6713                PR_snprintf(msg, sizeof msg,
   6714                            "C_GenerateKeyPair(hSession=0x%08lX, "
   6715                            "pMechanism->mechanism=0x%08lX)=0x%08lX "
   6716                            "self-test: pair-wise consistency test failed",
   6717                            (PRUint32)hSession, (PRUint32)pMechanism->mechanism,
   6718                            (PRUint32)crv);
   6719                sftk_LogAuditMessage(NSS_AUDIT_ERROR, NSS_AUDIT_SELF_TEST, msg);
   6720            }
   6721        }
   6722    }
   6723 
   6724    if (crv != CKR_OK) {
   6725        NSC_DestroyObject(hSession, publicKey->handle);
   6726        sftk_FreeObject(publicKey);
   6727        NSC_DestroyObject(hSession, privateKey->handle);
   6728        sftk_FreeObject(privateKey);
   6729        return crv;
   6730    }
   6731    *phPrivateKey = privateKey->handle;
   6732    *phPublicKey = publicKey->handle;
   6733    sftk_FreeObject(publicKey);
   6734    sftk_FreeObject(privateKey);
   6735 
   6736    return CKR_OK;
   6737 }
   6738 
   6739 static SECItem *
   6740 sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp)
   6741 {
   6742    NSSLOWKEYPrivateKey *lk = NULL;
   6743    NSSLOWKEYPrivateKeyInfo *pki = NULL;
   6744    SFTKAttribute *attribute = NULL;
   6745    PLArenaPool *arena = NULL;
   6746    SECOidTag algorithm = SEC_OID_UNKNOWN;
   6747    void *dummy, *param = NULL;
   6748    SECStatus rv = SECSuccess;
   6749    SECItem *encodedKey = NULL;
   6750 #ifdef EC_DEBUG
   6751    SECItem *fordebug;
   6752 #endif
   6753    int savelen;
   6754 
   6755    if (!key) {
   6756        *crvp = CKR_KEY_HANDLE_INVALID; /* really can't happen */
   6757        return NULL;
   6758    }
   6759 
   6760    attribute = sftk_FindAttribute(key, CKA_KEY_TYPE);
   6761    if (!attribute) {
   6762        *crvp = CKR_KEY_TYPE_INCONSISTENT;
   6763        return NULL;
   6764    }
   6765 
   6766    lk = sftk_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue, crvp);
   6767    sftk_FreeAttribute(attribute);
   6768    if (!lk) {
   6769        return NULL;
   6770    }
   6771 
   6772    arena = PORT_NewArena(2048); /* XXX different size? */
   6773    if (!arena) {
   6774        *crvp = CKR_HOST_MEMORY;
   6775        rv = SECFailure;
   6776        goto loser;
   6777    }
   6778 
   6779    pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena,
   6780                                                      sizeof(NSSLOWKEYPrivateKeyInfo));
   6781    if (!pki) {
   6782        *crvp = CKR_HOST_MEMORY;
   6783        rv = SECFailure;
   6784        goto loser;
   6785    }
   6786    pki->arena = arena;
   6787 
   6788    param = NULL;
   6789    switch (lk->keyType) {
   6790        case NSSLOWKEYRSAKey:
   6791            prepare_low_rsa_priv_key_for_asn1(lk);
   6792            dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
   6793                                       nsslowkey_RSAPrivateKeyTemplate);
   6794 
   6795            /* determine RSA key type from the CKA_PUBLIC_KEY_INFO if present */
   6796            attribute = sftk_FindAttribute(key, CKA_PUBLIC_KEY_INFO);
   6797            if (attribute) {
   6798                NSSLOWKEYSubjectPublicKeyInfo *publicKeyInfo;
   6799                SECItem spki;
   6800 
   6801                spki.data = attribute->attrib.pValue;
   6802                spki.len = attribute->attrib.ulValueLen;
   6803 
   6804                publicKeyInfo = PORT_ArenaZAlloc(arena,
   6805                                                 sizeof(NSSLOWKEYSubjectPublicKeyInfo));
   6806                if (!publicKeyInfo) {
   6807                    sftk_FreeAttribute(attribute);
   6808                    *crvp = CKR_HOST_MEMORY;
   6809                    rv = SECFailure;
   6810                    goto loser;
   6811                }
   6812                rv = SEC_QuickDERDecodeItem(arena, publicKeyInfo,
   6813                                            nsslowkey_SubjectPublicKeyInfoTemplate,
   6814                                            &spki);
   6815                if (rv != SECSuccess) {
   6816                    sftk_FreeAttribute(attribute);
   6817                    *crvp = CKR_KEY_TYPE_INCONSISTENT;
   6818                    goto loser;
   6819                }
   6820                algorithm = SECOID_GetAlgorithmTag(&publicKeyInfo->algorithm);
   6821                if (algorithm != SEC_OID_PKCS1_RSA_ENCRYPTION &&
   6822                    algorithm != SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
   6823                    sftk_FreeAttribute(attribute);
   6824                    rv = SECFailure;
   6825                    *crvp = CKR_KEY_TYPE_INCONSISTENT;
   6826                    goto loser;
   6827                }
   6828                param = SECITEM_DupItem(&publicKeyInfo->algorithm.parameters);
   6829                if (!param) {
   6830                    sftk_FreeAttribute(attribute);
   6831                    rv = SECFailure;
   6832                    *crvp = CKR_HOST_MEMORY;
   6833                    goto loser;
   6834                }
   6835                sftk_FreeAttribute(attribute);
   6836            } else {
   6837                /* default to PKCS #1 */
   6838                algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION;
   6839            }
   6840            break;
   6841        case NSSLOWKEYDSAKey:
   6842            prepare_low_dsa_priv_key_export_for_asn1(lk);
   6843            dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
   6844                                       nsslowkey_DSAPrivateKeyExportTemplate);
   6845            prepare_low_pqg_params_for_asn1(&lk->u.dsa.params);
   6846            param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params),
   6847                                       nsslowkey_PQGParamsTemplate);
   6848            algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE;
   6849            break;
   6850        case NSSLOWKEYECKey:
   6851            prepare_low_ec_priv_key_for_asn1(lk);
   6852            /* Public value is encoded as a bit string so adjust length
   6853             * to be in bits before ASN encoding and readjust
   6854             * immediately after.
   6855             *
   6856             * Since the SECG specification recommends not including the
   6857             * parameters as part of ECPrivateKey, we zero out the curveOID
   6858             * length before encoding and restore it later.
   6859             */
   6860            lk->u.ec.publicValue.len <<= 3;
   6861            savelen = lk->u.ec.ecParams.curveOID.len;
   6862            lk->u.ec.ecParams.curveOID.len = 0;
   6863            dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
   6864                                       nsslowkey_ECPrivateKeyTemplate);
   6865            lk->u.ec.ecParams.curveOID.len = savelen;
   6866            lk->u.ec.publicValue.len >>= 3;
   6867 
   6868 #ifdef EC_DEBUG
   6869            fordebug = &pki->privateKey;
   6870            SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKey", lk->keyType,
   6871                      fordebug);
   6872 #endif
   6873 
   6874            param = SECITEM_DupItem(&lk->u.ec.ecParams.DEREncoding);
   6875 
   6876            algorithm = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
   6877            break;
   6878        case NSSLOWKEYMLDSAKey: {
   6879            SECItem seed = { siBuffer, NULL, 0 };
   6880            SECItem keyVal = { siBuffer, NULL, 0 };
   6881            dummy = NULL;
   6882 
   6883            /* paramSet sets the algorithm */
   6884            switch (lk->u.mldsa.paramSet) {
   6885                case CKP_ML_DSA_44:
   6886                    algorithm = SEC_OID_ML_DSA_44_PUBLIC_KEY;
   6887                    break;
   6888                case CKP_ML_DSA_65:
   6889                    algorithm = SEC_OID_ML_DSA_65_PUBLIC_KEY;
   6890                    break;
   6891                case CKP_ML_DSA_87:
   6892                    algorithm = SEC_OID_ML_DSA_87_PUBLIC_KEY;
   6893                    break;
   6894                default:
   6895                    algorithm = SEC_OID_UNKNOWN;
   6896                    break;
   6897            }
   6898            if (algorithm == SEC_OID_UNKNOWN) {
   6899                break;
   6900            }
   6901 
   6902            /* if we have the seed, copy it */
   6903            if (lk->u.mldsa.seedLen != 0) {
   6904                rv = SECITEM_MakeItem(arena, &seed, lk->u.mldsa.seed,
   6905                                      lk->u.mldsa.seedLen);
   6906                if (rv != SECSuccess) {
   6907                    break;
   6908                }
   6909            }
   6910            rv = SECITEM_MakeItem(arena, &keyVal, lk->u.mldsa.keyVal,
   6911                                  lk->u.mldsa.keyValLen);
   6912            if (rv != SECSuccess) {
   6913                break;
   6914            }
   6915            if (lk == key->objectInfo) {
   6916                /* we have a cached key, and we are about to
   6917                 * overwrite it, let's get a duplicate first */
   6918                lk = nsslowkey_CopyPrivateKey(lk);
   6919                if (lk == NULL) {
   6920                    break;
   6921                }
   6922            }
   6923            /* this overwrites the mldsa data, but we don't need it any
   6924             * more because we are discarding lk once we encode */
   6925            lk->u.genpq.seedItem = seed;
   6926            lk->u.genpq.keyItem = keyVal;
   6927 
   6928            if (seed.len) {
   6929                dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
   6930                                           nsslowkey_PQBothSeedAndPrivateKeyTemplate);
   6931            } else {
   6932                dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
   6933                                           nsslowkey_PQPrivateKeyTemplate);
   6934            }
   6935        } break;
   6936 
   6937        case NSSLOWKEYDHKey:
   6938        default:
   6939            dummy = NULL;
   6940            break;
   6941    }
   6942 
   6943    if (!dummy || ((lk->keyType == NSSLOWKEYDSAKey) && !param)) {
   6944        *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
   6945        rv = SECFailure;
   6946        goto loser;
   6947    }
   6948 
   6949    rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm,
   6950                               (SECItem *)param);
   6951    if (rv != SECSuccess) {
   6952        *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
   6953        rv = SECFailure;
   6954        goto loser;
   6955    }
   6956 
   6957    dummy = SEC_ASN1EncodeInteger(arena, &pki->version,
   6958                                  NSSLOWKEY_PRIVATE_KEY_INFO_VERSION);
   6959    if (!dummy) {
   6960        *crvp = CKR_DEVICE_ERROR; /* should map NSS SECError */
   6961        rv = SECFailure;
   6962        goto loser;
   6963    }
   6964 
   6965    encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki,
   6966                                    nsslowkey_PrivateKeyInfoTemplate);
   6967    *crvp = encodedKey ? CKR_OK : CKR_DEVICE_ERROR;
   6968 
   6969 #ifdef EC_DEBUG
   6970    fordebug = encodedKey;
   6971    SEC_PRINT("sftk_PackagePrivateKey()", "PrivateKeyInfo", lk->keyType,
   6972              fordebug);
   6973 #endif
   6974 loser:
   6975    if (arena) {
   6976        PORT_FreeArena(arena, PR_TRUE);
   6977    }
   6978 
   6979    if (lk && (lk != key->objectInfo)) {
   6980        nsslowkey_DestroyPrivateKey(lk);
   6981    }
   6982 
   6983    if (param) {
   6984        SECITEM_ZfreeItem((SECItem *)param, PR_TRUE);
   6985    }
   6986 
   6987    if (rv != SECSuccess) {
   6988        return NULL;
   6989    }
   6990 
   6991    return encodedKey;
   6992 }
   6993 
   6994 /* it doesn't matter yet, since we colapse error conditions in the
   6995 * level above, but we really should map those few key error differences */
   6996 static CK_RV
   6997 sftk_mapWrap(CK_RV crv)
   6998 {
   6999    switch (crv) {
   7000        case CKR_ENCRYPTED_DATA_INVALID:
   7001            crv = CKR_WRAPPED_KEY_INVALID;
   7002            break;
   7003    }
   7004    return crv;
   7005 }
   7006 
   7007 /* NSC_WrapKey wraps (i.e., encrypts) a key. */
   7008 CK_RV
   7009 NSC_WrapKey(CK_SESSION_HANDLE hSession,
   7010            CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey,
   7011            CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey,
   7012            CK_ULONG_PTR pulWrappedKeyLen)
   7013 {
   7014    SFTKSession *session;
   7015    SFTKAttribute *attribute;
   7016    SFTKObject *key;
   7017    CK_RV crv;
   7018 
   7019    CHECK_FORK();
   7020 
   7021    session = sftk_SessionFromHandle(hSession);
   7022    if (session == NULL) {
   7023        return CKR_SESSION_HANDLE_INVALID;
   7024    }
   7025 
   7026    key = sftk_ObjectFromHandle(hKey, session);
   7027    if (key == NULL) {
   7028        sftk_FreeSession(session);
   7029        return CKR_KEY_HANDLE_INVALID;
   7030    }
   7031 
   7032    switch (key->objclass) {
   7033        case CKO_SECRET_KEY: {
   7034            SFTKSessionContext *context = NULL;
   7035            SECItem pText;
   7036 
   7037            attribute = sftk_FindAttribute(key, CKA_VALUE);
   7038 
   7039            if (attribute == NULL) {
   7040                crv = CKR_KEY_TYPE_INCONSISTENT;
   7041                break;
   7042            }
   7043            crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey,
   7044                                 CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE);
   7045            if (crv != CKR_OK) {
   7046                sftk_FreeAttribute(attribute);
   7047                break;
   7048            }
   7049 
   7050            pText.type = siBuffer;
   7051            pText.data = (unsigned char *)attribute->attrib.pValue;
   7052            pText.len = attribute->attrib.ulValueLen;
   7053 
   7054            /* Find out if this is a block cipher. */
   7055            crv = sftk_GetContext(hSession, &context, SFTK_ENCRYPT, PR_FALSE, NULL);
   7056            if (crv != CKR_OK || !context)
   7057                break;
   7058            if (context->blockSize > 1) {
   7059                unsigned int remainder = pText.len % context->blockSize;
   7060                if (!context->doPad && remainder) {
   7061                    /* When wrapping secret keys with unpadded block ciphers,
   7062                    ** the keys are zero padded, if necessary, to fill out
   7063                    ** a full block.
   7064                    */
   7065                    pText.len += context->blockSize - remainder;
   7066                    pText.data = PORT_ZAlloc(pText.len);
   7067                    if (pText.data)
   7068                        memcpy(pText.data, attribute->attrib.pValue,
   7069                               attribute->attrib.ulValueLen);
   7070                    else {
   7071                        crv = CKR_HOST_MEMORY;
   7072                        break;
   7073                    }
   7074                }
   7075            }
   7076 
   7077            crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)pText.data,
   7078                              pText.len, pWrappedKey, pulWrappedKeyLen);
   7079            /* always force a finalize, both on errors and when
   7080             * we are just getting the size */
   7081            if (crv != CKR_OK || pWrappedKey == NULL) {
   7082                CK_RV lcrv;
   7083                lcrv = sftk_GetContext(hSession, &context,
   7084                                       SFTK_ENCRYPT, PR_FALSE, NULL);
   7085                sftk_SetContextByType(session, SFTK_ENCRYPT, NULL);
   7086                if (lcrv == CKR_OK && context) {
   7087                    sftk_FreeContext(context);
   7088                }
   7089            }
   7090 
   7091            if (pText.data != (unsigned char *)attribute->attrib.pValue)
   7092                PORT_ZFree(pText.data, pText.len);
   7093            sftk_FreeAttribute(attribute);
   7094            break;
   7095        }
   7096 
   7097        case CKO_PRIVATE_KEY: {
   7098            SECItem *bpki = sftk_PackagePrivateKey(key, &crv);
   7099            SFTKSessionContext *context = NULL;
   7100 
   7101            if (!bpki) {
   7102                break;
   7103            }
   7104 
   7105            crv = sftk_CryptInit(hSession, pMechanism, hWrappingKey,
   7106                                 CKA_WRAP, CKA_WRAP, SFTK_ENCRYPT, PR_TRUE);
   7107            if (crv != CKR_OK) {
   7108                SECITEM_ZfreeItem(bpki, PR_TRUE);
   7109                crv = CKR_KEY_TYPE_INCONSISTENT;
   7110                break;
   7111            }
   7112 
   7113            crv = NSC_Encrypt(hSession, bpki->data, bpki->len,
   7114                              pWrappedKey, pulWrappedKeyLen);
   7115            /* always force a finalize */
   7116            if (crv != CKR_OK || pWrappedKey == NULL) {
   7117                CK_RV lcrv;
   7118                lcrv = sftk_GetContext(hSession, &context,
   7119                                       SFTK_ENCRYPT, PR_FALSE, NULL);
   7120                sftk_SetContextByType(session, SFTK_ENCRYPT, NULL);
   7121                if (lcrv == CKR_OK && context) {
   7122                    sftk_FreeContext(context);
   7123                }
   7124            }
   7125            SECITEM_ZfreeItem(bpki, PR_TRUE);
   7126            break;
   7127        }
   7128 
   7129        default:
   7130            crv = CKR_KEY_TYPE_INCONSISTENT;
   7131            break;
   7132    }
   7133    sftk_FreeObject(key);
   7134    sftk_FreeSession(session);
   7135    return sftk_mapWrap(crv);
   7136 }
   7137 
   7138 /*
   7139 * import a pprivate key info into the desired slot
   7140 */
   7141 static SECStatus
   7142 sftk_unwrapPrivateKey(SFTKObject *key, SECItem *bpki)
   7143 {
   7144    CK_BBOOL cktrue = CK_TRUE;
   7145    CK_BBOOL ckfalse = CK_FALSE;
   7146    CK_KEY_TYPE keyType = CKK_RSA;
   7147    SECStatus rv = SECFailure;
   7148    const SEC_ASN1Template *keyTemplate, *paramTemplate;
   7149    void *paramDest = NULL;
   7150    PLArenaPool *arena;
   7151    NSSLOWKEYPrivateKey *lpk = NULL;
   7152    NSSLOWKEYPrivateKeyInfo *pki = NULL;
   7153    CK_RV crv = CKR_KEY_TYPE_INCONSISTENT;
   7154    CK_ULONG paramSet = 0;
   7155 
   7156    arena = PORT_NewArena(2048);
   7157    if (!arena) {
   7158        return SECFailure;
   7159    }
   7160 
   7161    pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(arena,
   7162                                                      sizeof(NSSLOWKEYPrivateKeyInfo));
   7163    if (!pki) {
   7164        PORT_FreeArena(arena, PR_FALSE);
   7165        return SECFailure;
   7166    }
   7167 
   7168    if (SEC_ASN1DecodeItem(arena, pki, nsslowkey_PrivateKeyInfoTemplate, bpki) != SECSuccess) {
   7169        PORT_FreeArena(arena, PR_TRUE);
   7170        return SECFailure;
   7171    }
   7172 
   7173    lpk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(arena,
   7174                                                  sizeof(NSSLOWKEYPrivateKey));
   7175    if (lpk == NULL) {
   7176        goto loser;
   7177    }
   7178    lpk->arena = arena;
   7179 
   7180    switch (SECOID_GetAlgorithmTag(&pki->algorithm)) {
   7181        case SEC_OID_PKCS1_RSA_ENCRYPTION:
   7182        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
   7183            keyTemplate = nsslowkey_RSAPrivateKeyTemplate;
   7184            paramTemplate = NULL;
   7185            paramDest = NULL;
   7186            lpk->keyType = NSSLOWKEYRSAKey;
   7187            prepare_low_rsa_priv_key_for_asn1(lpk);
   7188            break;
   7189        case SEC_OID_ANSIX9_DSA_SIGNATURE:
   7190            keyTemplate = nsslowkey_DSAPrivateKeyExportTemplate;
   7191            paramTemplate = nsslowkey_PQGParamsTemplate;
   7192            paramDest = &(lpk->u.dsa.params);
   7193            lpk->keyType = NSSLOWKEYDSAKey;
   7194            prepare_low_dsa_priv_key_export_for_asn1(lpk);
   7195            prepare_low_pqg_params_for_asn1(&lpk->u.dsa.params);
   7196            break;
   7197        /* case NSSLOWKEYDHKey: */
   7198        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
   7199            keyTemplate = nsslowkey_ECPrivateKeyTemplate;
   7200            paramTemplate = NULL;
   7201            paramDest = &(lpk->u.ec.ecParams.DEREncoding);
   7202            lpk->keyType = NSSLOWKEYECKey;
   7203            prepare_low_ec_priv_key_for_asn1(lpk);
   7204            prepare_low_ecparams_for_asn1(&lpk->u.ec.ecParams);
   7205            break;
   7206        case SEC_OID_ML_DSA_44_PUBLIC_KEY:
   7207            paramSet = CKP_ML_DSA_44;
   7208            goto mldsa_next;
   7209        case SEC_OID_ML_DSA_65_PUBLIC_KEY:
   7210            paramSet = CKP_ML_DSA_65;
   7211            goto mldsa_next;
   7212        case SEC_OID_ML_DSA_87_PUBLIC_KEY:
   7213            paramSet = CKP_ML_DSA_87;
   7214        mldsa_next:
   7215            switch (pki->privateKey.data[0]) {
   7216                case SEC_ASN1_CONTEXT_SPECIFIC | 0:
   7217                    keyTemplate = nsslowkey_PQSeedTemplate;
   7218                    break;
   7219                case SEC_ASN1_OCTET_STRING:
   7220                    keyTemplate = nsslowkey_PQPrivateKeyTemplate;
   7221                    break;
   7222                case SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE:
   7223                    keyTemplate = nsslowkey_PQBothSeedAndPrivateKeyTemplate;
   7224                    break;
   7225                default:
   7226                    keyTemplate = NULL;
   7227                    break;
   7228            }
   7229 
   7230            paramTemplate = NULL;
   7231            paramDest = NULL;
   7232            lpk->keyType = NSSLOWKEYMLDSAKey;
   7233            /* genpq encodes ocect, not integer, so no need to prep it */
   7234            break;
   7235        default:
   7236            keyTemplate = NULL;
   7237            paramTemplate = NULL;
   7238            paramDest = NULL;
   7239            break;
   7240    }
   7241 
   7242    if (!keyTemplate) {
   7243        goto loser;
   7244    }
   7245 
   7246    /* decode the private key and any algorithm parameters */
   7247    rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey);
   7248 
   7249    if (lpk->keyType == NSSLOWKEYECKey) {
   7250        /* convert length in bits to length in bytes */
   7251        lpk->u.ec.publicValue.len >>= 3;
   7252        rv = SECITEM_CopyItem(arena,
   7253                              &(lpk->u.ec.ecParams.DEREncoding),
   7254                              &(pki->algorithm.parameters));
   7255        if (rv != SECSuccess) {
   7256            goto loser;
   7257        }
   7258    }
   7259 
   7260    if (rv != SECSuccess) {
   7261        goto loser;
   7262    }
   7263    if (paramDest && paramTemplate) {
   7264        rv = SEC_QuickDERDecodeItem(arena, paramDest, paramTemplate,
   7265                                    &(pki->algorithm.parameters));
   7266        if (rv != SECSuccess) {
   7267            goto loser;
   7268        }
   7269    }
   7270 
   7271    rv = SECFailure;
   7272 
   7273    switch (lpk->keyType) {
   7274        case NSSLOWKEYRSAKey:
   7275            keyType = CKK_RSA;
   7276            if (sftk_hasAttribute(key, CKA_NSS_DB)) {
   7277                sftk_DeleteAttributeType(key, CKA_NSS_DB);
   7278            }
   7279            crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
   7280                                        sizeof(keyType));
   7281            if (crv != CKR_OK)
   7282                break;
   7283            crv = sftk_AddAttributeType(key, CKA_UNWRAP, &cktrue,
   7284                                        sizeof(CK_BBOOL));
   7285            if (crv != CKR_OK)
   7286                break;
   7287            crv = sftk_AddAttributeType(key, CKA_DECRYPT, &cktrue,
   7288                                        sizeof(CK_BBOOL));
   7289            if (crv != CKR_OK)
   7290                break;
   7291            crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
   7292                                        sizeof(CK_BBOOL));
   7293            if (crv != CKR_OK)
   7294                break;
   7295            crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue,
   7296                                        sizeof(CK_BBOOL));
   7297            if (crv != CKR_OK)
   7298                break;
   7299            crv = sftk_AddAttributeType(key, CKA_MODULUS,
   7300                                        sftk_item_expand(&lpk->u.rsa.modulus));
   7301            if (crv != CKR_OK)
   7302                break;
   7303            crv = sftk_AddAttributeType(key, CKA_PUBLIC_EXPONENT,
   7304                                        sftk_item_expand(&lpk->u.rsa.publicExponent));
   7305            if (crv != CKR_OK)
   7306                break;
   7307            crv = sftk_AddAttributeType(key, CKA_PRIVATE_EXPONENT,
   7308                                        sftk_item_expand(&lpk->u.rsa.privateExponent));
   7309            if (crv != CKR_OK)
   7310                break;
   7311            crv = sftk_AddAttributeType(key, CKA_PRIME_1,
   7312                                        sftk_item_expand(&lpk->u.rsa.prime1));
   7313            if (crv != CKR_OK)
   7314                break;
   7315            crv = sftk_AddAttributeType(key, CKA_PRIME_2,
   7316                                        sftk_item_expand(&lpk->u.rsa.prime2));
   7317            if (crv != CKR_OK)
   7318                break;
   7319            crv = sftk_AddAttributeType(key, CKA_EXPONENT_1,
   7320                                        sftk_item_expand(&lpk->u.rsa.exponent1));
   7321            if (crv != CKR_OK)
   7322                break;
   7323            crv = sftk_AddAttributeType(key, CKA_EXPONENT_2,
   7324                                        sftk_item_expand(&lpk->u.rsa.exponent2));
   7325            if (crv != CKR_OK)
   7326                break;
   7327            crv = sftk_AddAttributeType(key, CKA_COEFFICIENT,
   7328                                        sftk_item_expand(&lpk->u.rsa.coefficient));
   7329            break;
   7330        case NSSLOWKEYDSAKey:
   7331            keyType = CKK_DSA;
   7332            crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT;
   7333            if (crv != CKR_OK)
   7334                break;
   7335            crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
   7336                                        sizeof(keyType));
   7337            if (crv != CKR_OK)
   7338                break;
   7339            crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
   7340                                        sizeof(CK_BBOOL));
   7341            if (crv != CKR_OK)
   7342                break;
   7343            crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &ckfalse,
   7344                                        sizeof(CK_BBOOL));
   7345            if (crv != CKR_OK)
   7346                break;
   7347            crv = sftk_AddAttributeType(key, CKA_PRIME,
   7348                                        sftk_item_expand(&lpk->u.dsa.params.prime));
   7349            if (crv != CKR_OK)
   7350                break;
   7351            crv = sftk_AddAttributeType(key, CKA_SUBPRIME,
   7352                                        sftk_item_expand(&lpk->u.dsa.params.subPrime));
   7353            if (crv != CKR_OK)
   7354                break;
   7355            crv = sftk_AddAttributeType(key, CKA_BASE,
   7356                                        sftk_item_expand(&lpk->u.dsa.params.base));
   7357            if (crv != CKR_OK)
   7358                break;
   7359            crv = sftk_AddAttributeType(key, CKA_VALUE,
   7360                                        sftk_item_expand(&lpk->u.dsa.privateValue));
   7361            if (crv != CKR_OK)
   7362                break;
   7363            break;
   7364        case NSSLOWKEYMLDSAKey:
   7365            keyType = CKK_ML_DSA;
   7366            crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT;
   7367            if (crv != CKR_OK)
   7368                break;
   7369            crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
   7370                                        sizeof(keyType));
   7371            if (crv != CKR_OK)
   7372                break;
   7373            crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
   7374                                        sizeof(CK_BBOOL));
   7375            if (crv != CKR_OK)
   7376                break;
   7377            crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &ckfalse,
   7378                                        sizeof(CK_BBOOL));
   7379            if (crv != CKR_OK)
   7380                break;
   7381            crv = sftk_AddAttributeType(key, CKA_PARAMETER_SET, &paramSet,
   7382                                        sizeof(CK_ML_DSA_PARAMETER_SET_TYPE));
   7383            if (crv != CKR_OK)
   7384                break;
   7385            if (lpk->u.genpq.seedItem.len != 0) {
   7386                crv = sftk_AddAttributeType(key, CKA_SEED,
   7387                                            sftk_item_expand(&lpk->u.genpq.seedItem));
   7388                if (crv != CKR_OK)
   7389                    break;
   7390            }
   7391 
   7392            /* if we were given just the seed, we'll regenerate the key
   7393             * from the seed in handleObject */
   7394            if (lpk->u.genpq.keyItem.len != 0) {
   7395                crv = sftk_AddAttributeType(key, CKA_VALUE,
   7396                                            sftk_item_expand(&lpk->u.genpq.keyItem));
   7397                /* I know,  this is redundant, but it would be too easy
   7398                 * for someone to add another sftk_AddAttributeType after
   7399                 * this without adding this check back because of the if */
   7400                if (crv != CKR_OK)
   7401                    break;
   7402            }
   7403            break;
   7404 #ifdef notdef
   7405        case NSSLOWKEYDHKey:
   7406            template = dhTemplate;
   7407            templateCount = sizeof(dhTemplate) / sizeof(CK_ATTRIBUTE);
   7408            keyType = CKK_DH;
   7409            break;
   7410 #endif
   7411        /* what about fortezza??? */
   7412        case NSSLOWKEYECKey:
   7413            keyType = CKK_EC;
   7414            crv = (sftk_hasAttribute(key, CKA_NSS_DB)) ? CKR_OK : CKR_KEY_TYPE_INCONSISTENT;
   7415            if (crv != CKR_OK)
   7416                break;
   7417            crv = sftk_AddAttributeType(key, CKA_KEY_TYPE, &keyType,
   7418                                        sizeof(keyType));
   7419            if (crv != CKR_OK)
   7420                break;
   7421            crv = sftk_AddAttributeType(key, CKA_SIGN, &cktrue,
   7422                                        sizeof(CK_BBOOL));
   7423            if (crv != CKR_OK)
   7424                break;
   7425            crv = sftk_AddAttributeType(key, CKA_SIGN_RECOVER, &ckfalse,
   7426                                        sizeof(CK_BBOOL));
   7427            if (crv != CKR_OK)
   7428                break;
   7429            crv = sftk_AddAttributeType(key, CKA_DERIVE, &cktrue,
   7430                                        sizeof(CK_BBOOL));
   7431            if (crv != CKR_OK)
   7432                break;
   7433            crv = sftk_AddAttributeType(key, CKA_EC_PARAMS,
   7434                                        sftk_item_expand(&lpk->u.ec.ecParams.DEREncoding));
   7435            if (crv != CKR_OK)
   7436                break;
   7437            crv = sftk_AddAttributeType(key, CKA_VALUE,
   7438                                        sftk_item_expand(&lpk->u.ec.privateValue));
   7439            if (crv != CKR_OK)
   7440                break;
   7441            /* XXX Do we need to decode the EC Params here ?? */
   7442            break;
   7443        default:
   7444            crv = CKR_KEY_TYPE_INCONSISTENT;
   7445            break;
   7446    }
   7447 
   7448    if (crv != CKR_OK) {
   7449        goto loser;
   7450    }
   7451 
   7452    /* For RSA-PSS, record the original algorithm parameters so
   7453     * they can be encrypted altoghether when wrapping */
   7454    if (SECOID_GetAlgorithmTag(&pki->algorithm) == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
   7455        NSSLOWKEYSubjectPublicKeyInfo spki;
   7456        NSSLOWKEYPublicKey pubk;
   7457        SECItem *publicKeyInfo;
   7458 
   7459        memset(&spki, 0, sizeof(NSSLOWKEYSubjectPublicKeyInfo));
   7460        rv = SECOID_CopyAlgorithmID(arena, &spki.algorithm, &pki->algorithm);
   7461        if (rv != SECSuccess) {
   7462            crv = CKR_HOST_MEMORY;
   7463            goto loser;
   7464        }
   7465 
   7466        prepare_low_rsa_pub_key_for_asn1(&pubk);
   7467 
   7468        rv = SECITEM_CopyItem(arena, &pubk.u.rsa.modulus, &lpk->u.rsa.modulus);
   7469        if (rv != SECSuccess) {
   7470            crv = CKR_HOST_MEMORY;
   7471            goto loser;
   7472        }
   7473        rv = SECITEM_CopyItem(arena, &pubk.u.rsa.publicExponent, &lpk->u.rsa.publicExponent);
   7474        if (rv != SECSuccess) {
   7475            crv = CKR_HOST_MEMORY;
   7476            goto loser;
   7477        }
   7478 
   7479        if (SEC_ASN1EncodeItem(arena, &spki.subjectPublicKey,
   7480                               &pubk, nsslowkey_RSAPublicKeyTemplate) == NULL) {
   7481            crv = CKR_HOST_MEMORY;
   7482            goto loser;
   7483        }
   7484 
   7485        publicKeyInfo = SEC_ASN1EncodeItem(arena, NULL,
   7486                                           &spki, nsslowkey_SubjectPublicKeyInfoTemplate);
   7487        if (!publicKeyInfo) {
   7488            crv = CKR_HOST_MEMORY;
   7489            goto loser;
   7490        }
   7491        crv = sftk_AddAttributeType(key, CKA_PUBLIC_KEY_INFO,
   7492                                    sftk_item_expand(publicKeyInfo));
   7493    }
   7494 
   7495 loser:
   7496    if (lpk) {
   7497        nsslowkey_DestroyPrivateKey(lpk);
   7498    }
   7499 
   7500    if (crv != CKR_OK) {
   7501        return SECFailure;
   7502    }
   7503 
   7504    return SECSuccess;
   7505 }
   7506 
   7507 /* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */
   7508 CK_RV
   7509 NSC_UnwrapKey(CK_SESSION_HANDLE hSession,
   7510              CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey,
   7511              CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
   7512              CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
   7513              CK_OBJECT_HANDLE_PTR phKey)
   7514 {
   7515    SFTKObject *key = NULL;
   7516    SFTKSession *session;
   7517    CK_ULONG key_length = 0;
   7518    unsigned char *buf = NULL;
   7519    CK_RV crv = CKR_OK;
   7520    int i;
   7521    CK_ULONG bsize = ulWrappedKeyLen;
   7522    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
   7523    SECItem bpki;
   7524    CK_OBJECT_CLASS target_type = CKO_SECRET_KEY;
   7525 
   7526    CHECK_FORK();
   7527 
   7528    if (!slot) {
   7529        return CKR_SESSION_HANDLE_INVALID;
   7530    }
   7531    /*
   7532     * now lets create an object to hang the attributes off of
   7533     */
   7534    key = sftk_NewObject(slot); /* fill in the handle later */
   7535    if (key == NULL) {
   7536        return CKR_HOST_MEMORY;
   7537    }
   7538 
   7539    /*
   7540     * load the template values into the object
   7541     */
   7542    for (i = 0; i < (int)ulAttributeCount; i++) {
   7543        if (pTemplate[i].type == CKA_VALUE_LEN) {
   7544            key_length = *(CK_ULONG *)pTemplate[i].pValue;
   7545            continue;
   7546        }
   7547        if (pTemplate[i].type == CKA_CLASS) {
   7548            target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue;
   7549        }
   7550        crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
   7551        if (crv != CKR_OK)
   7552            break;
   7553    }
   7554    if (crv != CKR_OK) {
   7555        sftk_FreeObject(key);
   7556        return crv;
   7557    }
   7558 
   7559    crv = sftk_CryptInit(hSession, pMechanism, hUnwrappingKey, CKA_UNWRAP,
   7560                         CKA_UNWRAP, SFTK_DECRYPT, PR_FALSE);
   7561    if (crv != CKR_OK) {
   7562        sftk_FreeObject(key);
   7563        return sftk_mapWrap(crv);
   7564    }
   7565 
   7566    /* allocate the buffer to decrypt into
   7567     * this assumes the unwrapped key is never larger than the
   7568     * wrapped key. For all the mechanisms we support this is true */
   7569    buf = (unsigned char *)PORT_Alloc(ulWrappedKeyLen);
   7570    bsize = ulWrappedKeyLen;
   7571 
   7572    crv = NSC_Decrypt(hSession, pWrappedKey, ulWrappedKeyLen, buf, &bsize);
   7573    if (crv != CKR_OK) {
   7574        sftk_FreeObject(key);
   7575        PORT_Free(buf);
   7576        return sftk_mapWrap(crv);
   7577    }
   7578 
   7579    switch (target_type) {
   7580        case CKO_SECRET_KEY:
   7581            if (!sftk_hasAttribute(key, CKA_KEY_TYPE)) {
   7582                crv = CKR_TEMPLATE_INCOMPLETE;
   7583                break;
   7584            }
   7585 
   7586            if (key_length == 0 || key_length > bsize) {
   7587                key_length = bsize;
   7588            }
   7589            if (key_length > MAX_KEY_LEN) {
   7590                crv = CKR_TEMPLATE_INCONSISTENT;
   7591                break;
   7592            }
   7593 
   7594            /* add the value */
   7595            crv = sftk_AddAttributeType(key, CKA_VALUE, buf, key_length);
   7596            break;
   7597        case CKO_PRIVATE_KEY:
   7598            bpki.data = (unsigned char *)buf;
   7599            bpki.len = bsize;
   7600            crv = CKR_OK;
   7601            if (sftk_unwrapPrivateKey(key, &bpki) != SECSuccess) {
   7602                crv = CKR_TEMPLATE_INCOMPLETE;
   7603            }
   7604            break;
   7605        default:
   7606            crv = CKR_TEMPLATE_INCONSISTENT;
   7607            break;
   7608    }
   7609 
   7610    PORT_ZFree(buf, bsize);
   7611    if (crv != CKR_OK) {
   7612        sftk_FreeObject(key);
   7613        return crv;
   7614    }
   7615 
   7616    /* get the session */
   7617    session = sftk_SessionFromHandle(hSession);
   7618    if (session == NULL) {
   7619        sftk_FreeObject(key);
   7620        return CKR_SESSION_HANDLE_INVALID;
   7621    }
   7622 
   7623    /* mark the key as FIPS if the previous operation was all FIPS */
   7624    sftk_setFIPS(key, session->lastOpWasFIPS);
   7625    /*
   7626     * handle the base object stuff
   7627     */
   7628    crv = sftk_handleObject(key, session);
   7629    *phKey = key->handle;
   7630    sftk_FreeSession(session);
   7631    sftk_FreeObject(key);
   7632 
   7633    return crv;
   7634 }
   7635 
   7636 CK_RV
   7637 NSC_WrapKeyAuthenticated(CK_SESSION_HANDLE hSession,
   7638                         CK_MECHANISM_PTR pMechanism,
   7639                         CK_OBJECT_HANDLE hWrappingKey,
   7640                         CK_OBJECT_HANDLE hKey,
   7641                         CK_BYTE_PTR pAssociatedData,
   7642                         CK_ULONG ulAssociatedDataLen,
   7643                         CK_BYTE_PTR pWrappedKey,
   7644                         CK_ULONG_PTR pulWrappedKeyLen)
   7645 {
   7646    CHECK_FORK();
   7647 
   7648    return CKR_FUNCTION_NOT_SUPPORTED;
   7649 }
   7650 
   7651 CK_RV
   7652 NSC_UnwrapKeyAuthenticated(CK_SESSION_HANDLE hSession,
   7653                           CK_MECHANISM_PTR pMechanism,
   7654                           CK_OBJECT_HANDLE hUnwrappingKey,
   7655                           CK_BYTE_PTR pWrappedKey,
   7656                           CK_ULONG ulWrappedKeyLen,
   7657                           CK_ATTRIBUTE_PTR pTemplate,
   7658                           CK_ULONG ulAttributeCount,
   7659                           CK_BYTE_PTR pAssociatedData,
   7660                           CK_ULONG ulAssociatedDataLen,
   7661                           CK_OBJECT_HANDLE_PTR phKey)
   7662 {
   7663    CHECK_FORK();
   7664 
   7665    return CKR_FUNCTION_NOT_SUPPORTED;
   7666 }
   7667 
   7668 /*
   7669 * The SSL key gen mechanism create's lots of keys. This function handles the
   7670 * details of each of these key creation.
   7671 */
   7672 static CK_RV
   7673 sftk_buildSSLKey(CK_SESSION_HANDLE hSession, SFTKObject *baseKey,
   7674                 PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize,
   7675                 CK_OBJECT_HANDLE *keyHandle)
   7676 {
   7677    SFTKObject *key;
   7678    SFTKSession *session;
   7679    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
   7680    CK_BBOOL cktrue = CK_TRUE;
   7681    CK_BBOOL ckfalse = CK_FALSE;
   7682    CK_RV crv = CKR_HOST_MEMORY;
   7683 
   7684    /*
   7685     * now lets create an object to hang the attributes off of
   7686     */
   7687    *keyHandle = CK_INVALID_HANDLE;
   7688    key = sftk_NewObject(baseKey->slot);
   7689    if (key == NULL)
   7690        return CKR_HOST_MEMORY;
   7691    sftk_narrowToSessionObject(key)->wasDerived = PR_TRUE;
   7692 
   7693    crv = sftk_CopyObject(key, baseKey);
   7694    if (crv != CKR_OK)
   7695        goto loser;
   7696    if (isMacKey) {
   7697        crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType));
   7698        if (crv != CKR_OK)
   7699            goto loser;
   7700        crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
   7701        if (crv != CKR_OK)
   7702            goto loser;
   7703        crv = sftk_forceAttribute(key, CKA_ENCRYPT, &ckfalse, sizeof(CK_BBOOL));
   7704        if (crv != CKR_OK)
   7705            goto loser;
   7706        crv = sftk_forceAttribute(key, CKA_DECRYPT, &ckfalse, sizeof(CK_BBOOL));
   7707        if (crv != CKR_OK)
   7708            goto loser;
   7709        crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
   7710        if (crv != CKR_OK)
   7711            goto loser;
   7712        crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
   7713        if (crv != CKR_OK)
   7714            goto loser;
   7715        crv = sftk_forceAttribute(key, CKA_WRAP, &ckfalse, sizeof(CK_BBOOL));
   7716        if (crv != CKR_OK)
   7717            goto loser;
   7718        crv = sftk_forceAttribute(key, CKA_UNWRAP, &ckfalse, sizeof(CK_BBOOL));
   7719        if (crv != CKR_OK)
   7720            goto loser;
   7721    }
   7722    crv = sftk_forceAttribute(key, CKA_VALUE, keyBlock, keySize);
   7723    if (crv != CKR_OK)
   7724        goto loser;
   7725 
   7726    /* get the session */
   7727    crv = CKR_HOST_MEMORY;
   7728    session = sftk_SessionFromHandle(hSession);
   7729    if (session == NULL) {
   7730        goto loser;
   7731    }
   7732 
   7733    crv = sftk_handleObject(key, session);
   7734    sftk_FreeSession(session);
   7735    *keyHandle = key->handle;
   7736 loser:
   7737    if (key)
   7738        sftk_FreeObject(key);
   7739    return crv;
   7740 }
   7741 
   7742 /*
   7743 * if there is an error, we need to free the keys we already created in SSL
   7744 * This is the routine that will do it..
   7745 */
   7746 static void
   7747 sftk_freeSSLKeys(CK_SESSION_HANDLE session,
   7748                 CK_SSL3_KEY_MAT_OUT *returnedMaterial)
   7749 {
   7750    if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) {
   7751        NSC_DestroyObject(session, returnedMaterial->hClientMacSecret);
   7752    }
   7753    if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) {
   7754        NSC_DestroyObject(session, returnedMaterial->hServerMacSecret);
   7755    }
   7756    if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) {
   7757        NSC_DestroyObject(session, returnedMaterial->hClientKey);
   7758    }
   7759    if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) {
   7760        NSC_DestroyObject(session, returnedMaterial->hServerKey);
   7761    }
   7762 }
   7763 
   7764 /*
   7765 * when deriving from sensitive and extractable keys, we need to preserve some
   7766 * of the semantics in the derived key. This helper routine maintains these
   7767 * semantics.
   7768 */
   7769 static CK_RV
   7770 sftk_DeriveSensitiveCheck(SFTKObject *baseKey, SFTKObject *destKey,
   7771                          PRBool canBeData)
   7772 {
   7773    PRBool hasSensitive;
   7774    PRBool sensitive = PR_FALSE;
   7775    CK_BBOOL bFalse = CK_FALSE;
   7776    PRBool hasExtractable;
   7777    PRBool extractable = PR_TRUE;
   7778    CK_BBOOL bTrue = CK_TRUE;
   7779    CK_RV crv = CKR_OK;
   7780    SFTKAttribute *att;
   7781    PRBool isData = PR_TRUE;
   7782 
   7783    if (canBeData) {
   7784        CK_OBJECT_CLASS objClass;
   7785 
   7786        /* if the target key is actually data, don't set the unexpected
   7787         * attributes */
   7788        crv = sftk_GetULongAttribute(destKey, CKA_CLASS, &objClass);
   7789        if (crv != CKR_OK) {
   7790            return crv;
   7791        }
   7792        if (objClass == CKO_DATA) {
   7793            return CKR_OK;
   7794        }
   7795 
   7796        /* if the base key is data, it doesn't have sensitive attributes,
   7797         * allow the destKey to get it's own */
   7798        crv = sftk_GetULongAttribute(baseKey, CKA_CLASS, &objClass);
   7799        if (crv != CKR_OK) {
   7800            return crv;
   7801        }
   7802        if (objClass == CKO_DATA) {
   7803            isData = PR_TRUE;
   7804        }
   7805    }
   7806 
   7807    hasSensitive = PR_FALSE;
   7808    att = sftk_FindAttribute(destKey, CKA_SENSITIVE);
   7809    if (att) {
   7810        hasSensitive = PR_TRUE;
   7811        sensitive = (PRBool) * (CK_BBOOL *)att->attrib.pValue;
   7812        sftk_FreeAttribute(att);
   7813    }
   7814 
   7815    hasExtractable = PR_FALSE;
   7816    att = sftk_FindAttribute(destKey, CKA_EXTRACTABLE);
   7817    if (att) {
   7818        hasExtractable = PR_TRUE;
   7819        extractable = (PRBool) * (CK_BBOOL *)att->attrib.pValue;
   7820        sftk_FreeAttribute(att);
   7821    }
   7822 
   7823    /* don't make a key more accessible */
   7824    if (sftk_isTrue(baseKey, CKA_SENSITIVE) && hasSensitive &&
   7825        (sensitive == PR_FALSE)) {
   7826        return CKR_KEY_FUNCTION_NOT_PERMITTED;
   7827    }
   7828    if (!sftk_isTrue(baseKey, CKA_EXTRACTABLE) && hasExtractable &&
   7829        (extractable == PR_TRUE)) {
   7830        return CKR_KEY_FUNCTION_NOT_PERMITTED;
   7831    }
   7832 
   7833    /* inherit parent's sensitivity */
   7834    if (!hasSensitive) {
   7835        att = sftk_FindAttribute(baseKey, CKA_SENSITIVE);
   7836        if (att != NULL) {
   7837            crv = sftk_defaultAttribute(destKey,
   7838                                        sftk_attr_expand(&att->attrib));
   7839            sftk_FreeAttribute(att);
   7840        } else if (isData) {
   7841            crv = sftk_defaultAttribute(destKey, CKA_SENSITIVE,
   7842                                        &bFalse, sizeof(bFalse));
   7843        } else {
   7844            return CKR_KEY_TYPE_INCONSISTENT;
   7845        }
   7846        if (crv != CKR_OK)
   7847            return crv;
   7848    }
   7849    if (!hasExtractable) {
   7850        att = sftk_FindAttribute(baseKey, CKA_EXTRACTABLE);
   7851        if (att != NULL) {
   7852            crv = sftk_defaultAttribute(destKey,
   7853                                        sftk_attr_expand(&att->attrib));
   7854            sftk_FreeAttribute(att);
   7855        } else if (isData) {
   7856            crv = sftk_defaultAttribute(destKey, CKA_EXTRACTABLE,
   7857                                        &bTrue, sizeof(bTrue));
   7858        } else {
   7859            return CKR_KEY_TYPE_INCONSISTENT;
   7860        }
   7861        if (crv != CKR_OK)
   7862            return crv;
   7863    }
   7864 
   7865    /* we should inherit the parent's always extractable/ never sensitive info,
   7866     * but handleObject always forces this attributes, so we would need to do
   7867     * something special. */
   7868    return CKR_OK;
   7869 }
   7870 
   7871 /*
   7872 * make known fixed PKCS #11 key types to their sizes in bytes
   7873 */
   7874 unsigned long
   7875 sftk_MapKeySize(CK_KEY_TYPE keyType)
   7876 {
   7877    switch (keyType) {
   7878        case CKK_CDMF:
   7879            return 8;
   7880        case CKK_DES:
   7881            return 8;
   7882        case CKK_DES2:
   7883            return 16;
   7884        case CKK_DES3:
   7885            return 24;
   7886        /* IDEA and CAST need to be added */
   7887        default:
   7888            break;
   7889    }
   7890    return 0;
   7891 }
   7892 
   7893 /* Inputs:
   7894 *  key_len: Length of derived key to be generated.
   7895 *  SharedSecret: a shared secret that is the output of a key agreement primitive.
   7896 *  SharedInfo: (Optional) some data shared by the entities computing the secret key.
   7897 *  SharedInfoLen: the length in octets of SharedInfo
   7898 *  Hash: The hash function to be used in the KDF
   7899 *  HashLen: the length in octets of the output of Hash
   7900 * Output:
   7901 *  key: Pointer to a buffer containing derived key, if return value is SECSuccess.
   7902 */
   7903 static CK_RV
   7904 sftk_compute_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len, SECItem *SharedSecret,
   7905                            CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen,
   7906                            SECStatus Hash(unsigned char *, const unsigned char *, PRUint32),
   7907                            CK_ULONG HashLen)
   7908 {
   7909    unsigned char *buffer = NULL, *output_buffer = NULL;
   7910    PRUint32 buffer_len, max_counter, i;
   7911    SECStatus rv;
   7912    CK_RV crv;
   7913 
   7914    /* Check that key_len isn't too long.  The maximum key length could be
   7915     * greatly increased if the code below did not limit the 4-byte counter
   7916     * to a maximum value of 255. */
   7917    if (key_len > 254 * HashLen)
   7918        return CKR_ARGUMENTS_BAD;
   7919 
   7920    if (SharedInfo == NULL)
   7921        SharedInfoLen = 0;
   7922 
   7923    buffer_len = SharedSecret->len + 4 + SharedInfoLen;
   7924    buffer = (CK_BYTE *)PORT_Alloc(buffer_len);
   7925    if (buffer == NULL) {
   7926        crv = CKR_HOST_MEMORY;
   7927        goto loser;
   7928    }
   7929 
   7930    max_counter = key_len / HashLen;
   7931    if (key_len > max_counter * HashLen)
   7932        max_counter++;
   7933 
   7934    output_buffer = (CK_BYTE *)PORT_Alloc(max_counter * HashLen);
   7935    if (output_buffer == NULL) {
   7936        crv = CKR_HOST_MEMORY;
   7937        goto loser;
   7938    }
   7939 
   7940    /* Populate buffer with SharedSecret || Counter || [SharedInfo]
   7941     * where Counter is 0x00000001 */
   7942    PORT_Memcpy(buffer, SharedSecret->data, SharedSecret->len);
   7943    buffer[SharedSecret->len] = 0;
   7944    buffer[SharedSecret->len + 1] = 0;
   7945    buffer[SharedSecret->len + 2] = 0;
   7946    buffer[SharedSecret->len + 3] = 1;
   7947    if (SharedInfo) {
   7948        PORT_Memcpy(&buffer[SharedSecret->len + 4], SharedInfo, SharedInfoLen);
   7949    }
   7950 
   7951    for (i = 0; i < max_counter; i++) {
   7952        rv = Hash(&output_buffer[i * HashLen], buffer, buffer_len);
   7953        if (rv != SECSuccess) {
   7954            /* 'Hash' should not fail. */
   7955            crv = CKR_FUNCTION_FAILED;
   7956            goto loser;
   7957        }
   7958 
   7959        /* Increment counter (assumes max_counter < 255) */
   7960        buffer[SharedSecret->len + 3]++;
   7961    }
   7962 
   7963    PORT_ZFree(buffer, buffer_len);
   7964    if (key_len < max_counter * HashLen) {
   7965        PORT_Memset(output_buffer + key_len, 0, max_counter * HashLen - key_len);
   7966    }
   7967    *key = output_buffer;
   7968 
   7969    return CKR_OK;
   7970 
   7971 loser:
   7972    if (buffer) {
   7973        PORT_ZFree(buffer, buffer_len);
   7974    }
   7975    if (output_buffer) {
   7976        PORT_ZFree(output_buffer, max_counter * HashLen);
   7977    }
   7978    return crv;
   7979 }
   7980 
   7981 static CK_RV
   7982 sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_ULONG key_len,
   7983                    SECItem *SharedSecret,
   7984                    CK_BYTE_PTR SharedInfo, CK_ULONG SharedInfoLen,
   7985                    CK_EC_KDF_TYPE kdf)
   7986 {
   7987    if (kdf == CKD_SHA1_KDF)
   7988        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
   7989                                           SharedInfoLen, SHA1_HashBuf, SHA1_LENGTH);
   7990    else if (kdf == CKD_SHA224_KDF)
   7991        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
   7992                                           SharedInfoLen, SHA224_HashBuf, SHA224_LENGTH);
   7993    else if (kdf == CKD_SHA256_KDF)
   7994        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
   7995                                           SharedInfoLen, SHA256_HashBuf, SHA256_LENGTH);
   7996    else if (kdf == CKD_SHA384_KDF)
   7997        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
   7998                                           SharedInfoLen, SHA384_HashBuf, SHA384_LENGTH);
   7999    else if (kdf == CKD_SHA512_KDF)
   8000        return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
   8001                                           SharedInfoLen, SHA512_HashBuf, SHA512_LENGTH);
   8002    else
   8003        return CKR_MECHANISM_INVALID;
   8004 }
   8005 
   8006 /*
   8007 *  Handle the derive from a block encryption cipher
   8008 */
   8009 CK_RV
   8010 sftk_DeriveEncrypt(SFTKCipher encrypt, void *cipherInfo,
   8011                   int blockSize, SFTKObject *key, CK_ULONG keySize,
   8012                   unsigned char *data, CK_ULONG len)
   8013 {
   8014    /* large enough for a 512-bit key */
   8015    unsigned char tmpdata[SFTK_MAX_DERIVE_KEY_SIZE];
   8016    SECStatus rv;
   8017    unsigned int outLen;
   8018    CK_RV crv;
   8019 
   8020    if ((len % blockSize) != 0) {
   8021        return CKR_MECHANISM_PARAM_INVALID;
   8022    }
   8023    if (len > SFTK_MAX_DERIVE_KEY_SIZE) {
   8024        return CKR_MECHANISM_PARAM_INVALID;
   8025    }
   8026    if (keySize && (len < keySize)) {
   8027        return CKR_MECHANISM_PARAM_INVALID;
   8028    }
   8029    if (keySize == 0) {
   8030        keySize = len;
   8031    }
   8032 
   8033    rv = (*encrypt)(cipherInfo, (unsigned char *)&tmpdata, &outLen, len, data, len);
   8034    if (rv != SECSuccess) {
   8035        crv = sftk_MapCryptError(PORT_GetError());
   8036        return crv;
   8037    }
   8038 
   8039    crv = sftk_forceAttribute(key, CKA_VALUE, tmpdata, keySize);
   8040    PORT_Memset(tmpdata, 0, sizeof tmpdata);
   8041    return crv;
   8042 }
   8043 
   8044 CK_RV
   8045 sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_SESSION_HANDLE hSession,
   8046          SFTKObject *sourceKey, const unsigned char *sourceKeyBytes,
   8047          int sourceKeyLen, SFTKObject *key, unsigned char *outKeyBytes,
   8048          int keySize, PRBool canBeData, PRBool isFIPS)
   8049 {
   8050    SFTKSession *session;
   8051    SFTKAttribute *saltKey_att = NULL;
   8052    const SECHashObject *rawHash;
   8053    unsigned hashLen;
   8054    unsigned genLen = 0;
   8055    unsigned char hashbuf[HASH_LENGTH_MAX];
   8056    unsigned char keyBlock[9 * SFTK_MAX_MAC_LENGTH];
   8057    unsigned char *keyBlockAlloc = NULL;    /* allocated keyBlock */
   8058    unsigned char *keyBlockData = keyBlock; /* pointer to current keyBlock */
   8059    const unsigned char *prk;               /* psuedo-random key */
   8060    CK_ULONG prkLen;
   8061    const unsigned char *okm; /* output keying material */
   8062    HASH_HashType hashType = sftk_GetHashTypeFromMechanism(params->prfHashMechanism);
   8063    SFTKObject *saltKey = NULL;
   8064    CK_RV crv = CKR_OK;
   8065 
   8066    /* Spec says it should be the base hash, but also accept the HMAC */
   8067    if (hashType == HASH_AlgNULL) {
   8068        hashType = sftk_HMACMechanismToHash(params->prfHashMechanism);
   8069    }
   8070    rawHash = HASH_GetRawHashObject(hashType);
   8071    if (rawHash == NULL || rawHash->length > sizeof(hashbuf)) {
   8072        return CKR_MECHANISM_INVALID;
   8073    }
   8074    hashLen = rawHash->length;
   8075 
   8076    if ((!params->bExpand && !params->bExtract) ||
   8077        (params->bExtract && params->ulSaltLen > 0 && !params->pSalt) ||
   8078        (params->bExpand && params->ulInfoLen > 0 && !params->pInfo)) {
   8079        return CKR_MECHANISM_PARAM_INVALID;
   8080    }
   8081    if ((params->bExpand && keySize == 0) ||
   8082        (!params->bExpand && keySize > hashLen) ||
   8083        (params->bExpand && keySize > 255 * hashLen)) {
   8084        return CKR_TEMPLATE_INCONSISTENT;
   8085    }
   8086 
   8087    /* sourceKey is NULL if we are called from the POST, skip the
   8088     * sensitiveCheck */
   8089    if (sourceKey != NULL) {
   8090        crv = sftk_DeriveSensitiveCheck(sourceKey, key, canBeData);
   8091        if (crv != CKR_OK)
   8092            return crv;
   8093    }
   8094 
   8095    /* HKDF-Extract(salt, base key value) */
   8096    if (params->bExtract) {
   8097        CK_BYTE *salt;
   8098        CK_ULONG saltLen;
   8099        HMACContext *hmac;
   8100        unsigned int bufLen;
   8101 
   8102        switch (params->ulSaltType) {
   8103            case CKF_HKDF_SALT_NULL:
   8104                saltLen = hashLen;
   8105                salt = hashbuf;
   8106                memset(salt, 0, saltLen);
   8107                break;
   8108            case CKF_HKDF_SALT_DATA:
   8109                salt = params->pSalt;
   8110                saltLen = params->ulSaltLen;
   8111                if ((salt == NULL) || (params->ulSaltLen == 0)) {
   8112                    return CKR_MECHANISM_PARAM_INVALID;
   8113                }
   8114                break;
   8115            case CKF_HKDF_SALT_KEY:
   8116                /* lookup key */
   8117                session = sftk_SessionFromHandle(hSession);
   8118                if (session == NULL) {
   8119                    return CKR_SESSION_HANDLE_INVALID;
   8120                }
   8121 
   8122                saltKey = sftk_ObjectFromHandle(params->hSaltKey, session);
   8123                sftk_FreeSession(session);
   8124                if (saltKey == NULL) {
   8125                    return CKR_KEY_HANDLE_INVALID;
   8126                }
   8127                /* if the base key is not fips, but the salt key is, the
   8128                 * resulting key can be fips */
   8129                if (isFIPS && !sftk_hasFIPS(key) && sftk_hasFIPS(saltKey)) {
   8130                    CK_MECHANISM mech;
   8131                    mech.mechanism = CKM_HKDF_DERIVE;
   8132                    mech.pParameter = params;
   8133                    mech.ulParameterLen = sizeof(*params);
   8134                    sftk_setFIPS(key, sftk_operationIsFIPS(saltKey->slot,
   8135                                                           &mech, CKA_DERIVE,
   8136                                                           saltKey));
   8137                }
   8138                saltKey_att = sftk_FindAttribute(saltKey, CKA_VALUE);
   8139                if (saltKey_att == NULL) {
   8140                    sftk_FreeObject(saltKey);
   8141                    return CKR_KEY_HANDLE_INVALID;
   8142                }
   8143                /* save the resulting salt */
   8144                salt = saltKey_att->attrib.pValue;
   8145                saltLen = saltKey_att->attrib.ulValueLen;
   8146                break;
   8147            default:
   8148                return CKR_MECHANISM_PARAM_INVALID;
   8149                break;
   8150        }
   8151 
   8152        hmac = HMAC_Create(rawHash, salt, saltLen, isFIPS);
   8153        if (saltKey_att) {
   8154            sftk_FreeAttribute(saltKey_att);
   8155        }
   8156        if (saltKey) {
   8157            sftk_FreeObject(saltKey);
   8158        }
   8159        if (!hmac) {
   8160            return CKR_HOST_MEMORY;
   8161        }
   8162        HMAC_Begin(hmac);
   8163        HMAC_Update(hmac, sourceKeyBytes, sourceKeyLen);
   8164        HMAC_Finish(hmac, hashbuf, &bufLen, sizeof(hashbuf));
   8165        HMAC_Destroy(hmac, PR_TRUE);
   8166        PORT_Assert(bufLen == rawHash->length);
   8167        prk = hashbuf;
   8168        prkLen = bufLen;
   8169    } else {
   8170        /* PRK = base key value */
   8171        prk = sourceKeyBytes;
   8172        prkLen = sourceKeyLen;
   8173    }
   8174 
   8175    /* HKDF-Expand */
   8176    if (!params->bExpand) {
   8177        okm = prk;
   8178        keySize = genLen = hashLen;
   8179    } else {
   8180        /* T(1) = HMAC-Hash(prk, "" | info | 0x01)
   8181         * T(n) = HMAC-Hash(prk, T(n-1) | info | n
   8182         * key material = T(1) | ... | T(n)
   8183         */
   8184        HMACContext *hmac;
   8185        CK_BYTE bi;
   8186        unsigned iterations;
   8187 
   8188        genLen = PR_ROUNDUP(keySize, hashLen);
   8189        iterations = genLen / hashLen;
   8190 
   8191        if (genLen > sizeof(keyBlock)) {
   8192            keyBlockAlloc = PORT_Alloc(genLen);
   8193            if (keyBlockAlloc == NULL) {
   8194                return CKR_HOST_MEMORY;
   8195            }
   8196            keyBlockData = keyBlockAlloc;
   8197        }
   8198        hmac = HMAC_Create(rawHash, prk, prkLen, isFIPS);
   8199        if (hmac == NULL) {
   8200            PORT_Free(keyBlockAlloc);
   8201            return CKR_HOST_MEMORY;
   8202        }
   8203        for (bi = 1; bi <= iterations && bi > 0; ++bi) {
   8204            unsigned len;
   8205            HMAC_Begin(hmac);
   8206            if (bi > 1) {
   8207                HMAC_Update(hmac, &keyBlockData[(bi - 2) * hashLen], hashLen);
   8208            }
   8209            if (params->ulInfoLen != 0) {
   8210                HMAC_Update(hmac, params->pInfo, params->ulInfoLen);
   8211            }
   8212            HMAC_Update(hmac, &bi, 1);
   8213            HMAC_Finish(hmac, &keyBlockData[(bi - 1) * hashLen], &len,
   8214                        hashLen);
   8215            PORT_Assert(len == hashLen);
   8216        }
   8217        HMAC_Destroy(hmac, PR_TRUE);
   8218        okm = &keyBlockData[0];
   8219    }
   8220    /* key material = okm */
   8221    crv = CKR_OK;
   8222    if (key) {
   8223        crv = sftk_forceAttribute(key, CKA_VALUE, okm, keySize);
   8224    } else {
   8225        PORT_Assert(outKeyBytes != NULL);
   8226        PORT_Memcpy(outKeyBytes, okm, keySize);
   8227    }
   8228    PORT_Memset(keyBlockData, 0, genLen);
   8229    PORT_Memset(hashbuf, 0, sizeof(hashbuf));
   8230    PORT_Free(keyBlockAlloc);
   8231    return crv;
   8232 }
   8233 
   8234 /*
   8235 * SSL Key generation given pre master secret
   8236 */
   8237 #define NUM_MIXERS 9
   8238 static const char *const mixers[NUM_MIXERS] = {
   8239    "A",
   8240    "BB",
   8241    "CCC",
   8242    "DDDD",
   8243    "EEEEE",
   8244    "FFFFFF",
   8245    "GGGGGGG",
   8246    "HHHHHHHH",
   8247    "IIIIIIIII"
   8248 };
   8249 #define SSL3_PMS_LENGTH 48
   8250 #define SSL3_MASTER_SECRET_LENGTH 48
   8251 #define SSL3_RANDOM_LENGTH 32
   8252 
   8253 /* NSC_DeriveKey derives a key from a base key, creating a new key object. */
   8254 CK_RV
   8255 NSC_DeriveKey(CK_SESSION_HANDLE hSession,
   8256              CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey,
   8257              CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
   8258              CK_OBJECT_HANDLE_PTR phKey)
   8259 {
   8260    SFTKSession *session;
   8261    SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
   8262    SFTKObject *key;
   8263    SFTKObject *sourceKey;
   8264    SFTKAttribute *att = NULL;
   8265    SFTKAttribute *att2 = NULL;
   8266    unsigned char *buf;
   8267    SHA1Context *sha;
   8268    MD5Context *md5;
   8269    MD2Context *md2;
   8270    CK_ULONG macSize;
   8271    CK_ULONG tmpKeySize;
   8272    CK_ULONG IVSize;
   8273    CK_ULONG keySize = 0;
   8274    CK_RV crv = CKR_OK;
   8275    CK_BBOOL cktrue = CK_TRUE;
   8276    CK_BBOOL ckfalse = CK_FALSE;
   8277    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
   8278    CK_OBJECT_CLASS classType = CKO_SECRET_KEY;
   8279    CK_KEY_DERIVATION_STRING_DATA *stringPtr;
   8280    PRBool isTLS = PR_FALSE;
   8281    PRBool isDH = PR_FALSE;
   8282    HASH_HashType tlsPrfHash = HASH_AlgNULL;
   8283    SECStatus rv;
   8284    int i;
   8285    unsigned int outLen;
   8286    unsigned char sha_out[SHA1_LENGTH];
   8287    unsigned char key_block[NUM_MIXERS * SFTK_MAX_MAC_LENGTH];
   8288    PRBool isFIPS;
   8289    HASH_HashType hashType;
   8290    CK_MECHANISM_TYPE hashMech;
   8291    PRBool extractValue = PR_TRUE;
   8292    CK_IKE1_EXTENDED_DERIVE_PARAMS ikeAppB;
   8293    CK_IKE1_EXTENDED_DERIVE_PARAMS *pIkeAppB;
   8294 
   8295    CHECK_FORK();
   8296 
   8297    if (!slot) {
   8298        return CKR_SESSION_HANDLE_INVALID;
   8299    }
   8300    if (!pMechanism) {
   8301        return CKR_MECHANISM_PARAM_INVALID;
   8302    }
   8303    CK_MECHANISM_TYPE mechanism = pMechanism->mechanism;
   8304 
   8305    /*
   8306     * now lets create an object to hang the attributes off of
   8307     */
   8308    if (phKey) {
   8309        *phKey = CK_INVALID_HANDLE;
   8310    }
   8311 
   8312    key = sftk_NewObject(slot); /* fill in the handle later */
   8313    if (key == NULL) {
   8314        return CKR_HOST_MEMORY;
   8315    }
   8316    isFIPS = sftk_isFIPS(slot->slotID);
   8317 
   8318    /*
   8319     * load the template values into the object
   8320     */
   8321    for (i = 0; i < (int)ulAttributeCount; i++) {
   8322        crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
   8323        if (crv != CKR_OK)
   8324            break;
   8325 
   8326        if (pTemplate[i].type == CKA_KEY_TYPE) {
   8327            keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue;
   8328        }
   8329        if (pTemplate[i].type == CKA_VALUE_LEN) {
   8330            keySize = *(CK_ULONG *)pTemplate[i].pValue;
   8331        }
   8332    }
   8333    if (crv != CKR_OK) {
   8334        sftk_FreeObject(key);
   8335        return crv;
   8336    }
   8337 
   8338    if (keySize == 0) {
   8339        keySize = sftk_MapKeySize(keyType);
   8340    }
   8341 
   8342    switch (mechanism) {
   8343        case CKM_NSS_JPAKE_ROUND2_SHA1:   /* fall through */
   8344        case CKM_NSS_JPAKE_ROUND2_SHA256: /* fall through */
   8345        case CKM_NSS_JPAKE_ROUND2_SHA384: /* fall through */
   8346        case CKM_NSS_JPAKE_ROUND2_SHA512:
   8347            extractValue = PR_FALSE;
   8348            classType = CKO_PRIVATE_KEY;
   8349            break;
   8350        case CKM_NSS_PUB_FROM_PRIV:
   8351            extractValue = PR_FALSE;
   8352            classType = CKO_PUBLIC_KEY;
   8353            break;
   8354        case CKM_HKDF_DATA:                              /* fall through */
   8355        case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA:  /* fall through */
   8356        case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA: /* fall through */
   8357        case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA:
   8358            classType = CKO_DATA;
   8359            break;
   8360        case CKM_NSS_JPAKE_FINAL_SHA1:   /* fall through */
   8361        case CKM_NSS_JPAKE_FINAL_SHA256: /* fall through */
   8362        case CKM_NSS_JPAKE_FINAL_SHA384: /* fall through */
   8363        case CKM_NSS_JPAKE_FINAL_SHA512:
   8364            extractValue = PR_FALSE;
   8365        /* fall through */
   8366        default:
   8367            classType = CKO_SECRET_KEY;
   8368    }
   8369 
   8370    crv = sftk_forceAttribute(key, CKA_CLASS, &classType, sizeof(classType));
   8371    if (crv != CKR_OK) {
   8372        sftk_FreeObject(key);
   8373        return crv;
   8374    }
   8375 
   8376    /* look up the base key we're deriving with */
   8377    session = sftk_SessionFromHandle(hSession);
   8378    if (session == NULL) {
   8379        sftk_FreeObject(key);
   8380        return CKR_SESSION_HANDLE_INVALID;
   8381    }
   8382 
   8383    sourceKey = sftk_ObjectFromHandle(hBaseKey, session);
   8384    sftk_FreeSession(session);
   8385    /* is this eventually succeeds, lastOpWasFIPS will be set the resulting key's
   8386     * FIPS state below. */
   8387    session->lastOpWasFIPS = PR_FALSE;
   8388    if (sourceKey == NULL) {
   8389        sftk_FreeObject(key);
   8390        return CKR_KEY_HANDLE_INVALID;
   8391    }
   8392 
   8393    if (extractValue) {
   8394        /* get the value of the base key */
   8395        att = sftk_FindAttribute(sourceKey, CKA_VALUE);
   8396        if (att == NULL) {
   8397            sftk_FreeObject(key);
   8398            sftk_FreeObject(sourceKey);
   8399            return CKR_KEY_HANDLE_INVALID;
   8400        }
   8401    }
   8402    sftk_setFIPS(key, sftk_operationIsFIPS(slot, pMechanism,
   8403                                           CKA_DERIVE, sourceKey));
   8404 
   8405    switch (mechanism) {
   8406        /* get a public key from a private key. nsslowkey_ConvertToPublickey()
   8407         * will generate the public portion if it doesn't already exist. */
   8408        case CKM_NSS_PUB_FROM_PRIV: {
   8409            NSSLOWKEYPrivateKey *privKey;
   8410            NSSLOWKEYPublicKey *pubKey;
   8411            int error;
   8412 
   8413            crv = sftk_GetULongAttribute(sourceKey, CKA_KEY_TYPE, &keyType);
   8414            if (crv != CKR_OK) {
   8415                break;
   8416            }
   8417 
   8418            /* privKey is stored in sourceKey and will be destroyed when
   8419             * the sourceKey is freed. */
   8420            privKey = sftk_GetPrivKey(sourceKey, keyType, &crv);
   8421            if (privKey == NULL) {
   8422                break;
   8423            }
   8424            pubKey = nsslowkey_ConvertToPublicKey(privKey);
   8425            if (pubKey == NULL) {
   8426                error = PORT_GetError();
   8427                crv = sftk_MapCryptError(error);
   8428                break;
   8429            }
   8430            crv = sftk_PutPubKey(key, sourceKey, keyType, pubKey);
   8431            nsslowkey_DestroyPublicKey(pubKey);
   8432            break;
   8433        }
   8434        case CKM_NSS_IKE_PRF_DERIVE:
   8435        case CKM_IKE_PRF_DERIVE:
   8436            if (pMechanism->ulParameterLen !=
   8437                sizeof(CK_IKE_PRF_DERIVE_PARAMS)) {
   8438                crv = CKR_MECHANISM_PARAM_INVALID;
   8439                break;
   8440            }
   8441            crv = sftk_ike_prf(hSession, att,
   8442                               (CK_IKE_PRF_DERIVE_PARAMS *)pMechanism->pParameter, key);
   8443            break;
   8444        case CKM_NSS_IKE1_PRF_DERIVE:
   8445        case CKM_IKE1_PRF_DERIVE:
   8446            if (pMechanism->ulParameterLen !=
   8447                sizeof(CK_IKE1_PRF_DERIVE_PARAMS)) {
   8448                crv = CKR_MECHANISM_PARAM_INVALID;
   8449                break;
   8450            }
   8451            crv = sftk_ike1_prf(hSession, att,
   8452                                (CK_IKE1_PRF_DERIVE_PARAMS *)pMechanism->pParameter,
   8453                                key, keySize);
   8454            break;
   8455        case CKM_NSS_IKE1_APP_B_PRF_DERIVE:
   8456        case CKM_IKE1_EXTENDED_DERIVE:
   8457            pIkeAppB = (CK_IKE1_EXTENDED_DERIVE_PARAMS *)pMechanism->pParameter;
   8458            if (pMechanism->ulParameterLen ==
   8459                sizeof(CK_MECHANISM_TYPE)) {
   8460                ikeAppB.prfMechanism = *(CK_MECHANISM_TYPE *)pMechanism->pParameter;
   8461                ikeAppB.bHasKeygxy = PR_FALSE;
   8462                ikeAppB.hKeygxy = CK_INVALID_HANDLE;
   8463                ikeAppB.pExtraData = NULL;
   8464                ikeAppB.ulExtraDataLen = 0;
   8465                pIkeAppB = &ikeAppB;
   8466            } else if (pMechanism->ulParameterLen !=
   8467                       sizeof(CK_IKE1_EXTENDED_DERIVE_PARAMS)) {
   8468                crv = CKR_MECHANISM_PARAM_INVALID;
   8469                break;
   8470            }
   8471            crv = sftk_ike1_appendix_b_prf(hSession, att, pIkeAppB, key,
   8472                                           keySize);
   8473            break;
   8474        case CKM_NSS_IKE_PRF_PLUS_DERIVE:
   8475        case CKM_IKE2_PRF_PLUS_DERIVE:
   8476            if (pMechanism->ulParameterLen !=
   8477                sizeof(CK_IKE2_PRF_PLUS_DERIVE_PARAMS)) {
   8478                crv = CKR_MECHANISM_PARAM_INVALID;
   8479                break;
   8480            }
   8481            crv = sftk_ike_prf_plus(hSession, att,
   8482                                    (CK_IKE2_PRF_PLUS_DERIVE_PARAMS *)pMechanism->pParameter,
   8483                                    key, keySize);
   8484            break;
   8485        /*
   8486         * generate the master secret
   8487         */
   8488        case CKM_TLS12_MASTER_KEY_DERIVE:
   8489        case CKM_TLS12_MASTER_KEY_DERIVE_DH:
   8490        case CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256:
   8491        case CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256:
   8492        case CKM_TLS_MASTER_KEY_DERIVE:
   8493        case CKM_TLS_MASTER_KEY_DERIVE_DH:
   8494        case CKM_SSL3_MASTER_KEY_DERIVE:
   8495        case CKM_SSL3_MASTER_KEY_DERIVE_DH: {
   8496            CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master;
   8497            SSL3RSAPreMasterSecret *rsa_pms;
   8498            unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
   8499 
   8500            if ((mechanism == CKM_TLS12_MASTER_KEY_DERIVE) ||
   8501                (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) {
   8502                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS))) {
   8503                    crv = CKR_MECHANISM_PARAM_INVALID;
   8504                    break;
   8505                }
   8506                CK_TLS12_MASTER_KEY_DERIVE_PARAMS *tls12_master =
   8507                    (CK_TLS12_MASTER_KEY_DERIVE_PARAMS *)pMechanism->pParameter;
   8508                tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_master->prfHashMechanism);
   8509                if (tlsPrfHash == HASH_AlgNULL) {
   8510                    crv = CKR_MECHANISM_PARAM_INVALID;
   8511                    break;
   8512                }
   8513            } else if ((mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256) ||
   8514                       (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256)) {
   8515                tlsPrfHash = HASH_AlgSHA256;
   8516            }
   8517 
   8518            if ((mechanism != CKM_SSL3_MASTER_KEY_DERIVE) &&
   8519                (mechanism != CKM_SSL3_MASTER_KEY_DERIVE_DH)) {
   8520                isTLS = PR_TRUE;
   8521            }
   8522            if ((mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) ||
   8523                (mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH) ||
   8524                (mechanism == CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256) ||
   8525                (mechanism == CKM_TLS12_MASTER_KEY_DERIVE_DH)) {
   8526                isDH = PR_TRUE;
   8527            }
   8528 
   8529            /* first do the consistency checks */
   8530            if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) {
   8531                crv = CKR_KEY_TYPE_INCONSISTENT;
   8532                break;
   8533            }
   8534            att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE);
   8535            if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
   8536                                   CKK_GENERIC_SECRET)) {
   8537                if (att2)
   8538                    sftk_FreeAttribute(att2);
   8539                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
   8540                break;
   8541            }
   8542            sftk_FreeAttribute(att2);
   8543            if (keyType != CKK_GENERIC_SECRET) {
   8544                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
   8545                break;
   8546            }
   8547            if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) {
   8548                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
   8549                break;
   8550            }
   8551 
   8552            /* finally do the key gen */
   8553            ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)
   8554                              pMechanism->pParameter;
   8555 
   8556            if (ssl3_master->pVersion) {
   8557                SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
   8558                rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue;
   8559                /* don't leak more key material then necessary for SSL to work */
   8560                if ((sessKey == NULL) || sessKey->wasDerived) {
   8561                    ssl3_master->pVersion->major = 0xff;
   8562                    ssl3_master->pVersion->minor = 0xff;
   8563                } else {
   8564                    ssl3_master->pVersion->major = rsa_pms->client_version[0];
   8565                    ssl3_master->pVersion->minor = rsa_pms->client_version[1];
   8566                }
   8567            }
   8568            if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) {
   8569                crv = CKR_MECHANISM_PARAM_INVALID;
   8570                break;
   8571            }
   8572            if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) {
   8573                crv = CKR_MECHANISM_PARAM_INVALID;
   8574                break;
   8575            }
   8576            PORT_Memcpy(crsrdata,
   8577                        ssl3_master->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
   8578            PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH,
   8579                        ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
   8580 
   8581            if (isTLS) {
   8582                SECStatus status;
   8583                SECItem crsr = { siBuffer, NULL, 0 };
   8584                SECItem master = { siBuffer, NULL, 0 };
   8585                SECItem pms = { siBuffer, NULL, 0 };
   8586 
   8587                crsr.data = crsrdata;
   8588                crsr.len = sizeof crsrdata;
   8589                master.data = key_block;
   8590                master.len = SSL3_MASTER_SECRET_LENGTH;
   8591                pms.data = (unsigned char *)att->attrib.pValue;
   8592                pms.len = att->attrib.ulValueLen;
   8593 
   8594                if (tlsPrfHash != HASH_AlgNULL) {
   8595                    status = TLS_P_hash(tlsPrfHash, &pms, "master secret",
   8596                                        &crsr, &master, isFIPS);
   8597                } else {
   8598                    status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS);
   8599                }
   8600                if (status != SECSuccess) {
   8601                    PORT_Memset(crsrdata, 0, sizeof crsrdata);
   8602                    crv = CKR_FUNCTION_FAILED;
   8603                    break;
   8604                }
   8605            } else {
   8606                /* now allocate the hash contexts */
   8607                md5 = MD5_NewContext();
   8608                if (md5 == NULL) {
   8609                    PORT_Memset(crsrdata, 0, sizeof crsrdata);
   8610                    crv = CKR_HOST_MEMORY;
   8611                    break;
   8612                }
   8613                sha = SHA1_NewContext();
   8614                if (sha == NULL) {
   8615                    PORT_Memset(crsrdata, 0, sizeof crsrdata);
   8616                    PORT_Free(md5);
   8617                    crv = CKR_HOST_MEMORY;
   8618                    break;
   8619                }
   8620                for (i = 0; i < 3; i++) {
   8621                    SHA1_Begin(sha);
   8622                    SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i]));
   8623                    SHA1_Update(sha, (const unsigned char *)att->attrib.pValue,
   8624                                att->attrib.ulValueLen);
   8625                    SHA1_Update(sha, crsrdata, sizeof crsrdata);
   8626                    SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
   8627                    PORT_Assert(outLen == SHA1_LENGTH);
   8628 
   8629                    MD5_Begin(md5);
   8630                    MD5_Update(md5, (const unsigned char *)att->attrib.pValue,
   8631                               att->attrib.ulValueLen);
   8632                    MD5_Update(md5, sha_out, outLen);
   8633                    MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH);
   8634                    PORT_Assert(outLen == MD5_LENGTH);
   8635                }
   8636                PORT_Free(md5);
   8637                PORT_Free(sha);
   8638                PORT_Memset(crsrdata, 0, sizeof crsrdata);
   8639                PORT_Memset(sha_out, 0, sizeof sha_out);
   8640            }
   8641 
   8642            /* store the results */
   8643            crv = sftk_forceAttribute(key, CKA_VALUE, key_block, SSL3_MASTER_SECRET_LENGTH);
   8644            PORT_Memset(key_block, 0, sizeof key_block);
   8645            if (crv != CKR_OK)
   8646                break;
   8647            keyType = CKK_GENERIC_SECRET;
   8648            crv = sftk_forceAttribute(key, CKA_KEY_TYPE, &keyType, sizeof(keyType));
   8649            if (isTLS) {
   8650                /* TLS's master secret is used to "sign" finished msgs with PRF. */
   8651                /* XXX This seems like a hack.   But SFTK_Derive only accepts
   8652                 * one "operation" argument. */
   8653                crv = sftk_forceAttribute(key, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
   8654                if (crv != CKR_OK)
   8655                    break;
   8656                crv = sftk_forceAttribute(key, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));
   8657                if (crv != CKR_OK)
   8658                    break;
   8659                /* While we're here, we might as well force this, too. */
   8660                crv = sftk_forceAttribute(key, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
   8661                if (crv != CKR_OK)
   8662                    break;
   8663            }
   8664            break;
   8665        }
   8666 
   8667        /* Extended master key derivation [draft-ietf-tls-session-hash] */
   8668        case CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE:
   8669        case CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE_DH:
   8670        case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE:
   8671        case CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH: {
   8672            CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS *ems_params;
   8673            SSL3RSAPreMasterSecret *rsa_pms;
   8674            SECStatus status;
   8675            SECItem pms = { siBuffer, NULL, 0 };
   8676            SECItem seed = { siBuffer, NULL, 0 };
   8677            SECItem master = { siBuffer, NULL, 0 };
   8678 
   8679            ems_params = (CK_TLS12_EXTENDED_MASTER_KEY_DERIVE_PARAMS *)
   8680                             pMechanism->pParameter;
   8681 
   8682            /* First do the consistency checks */
   8683            if (((mechanism == CKM_TLS12_EXTENDED_MASTER_KEY_DERIVE) ||
   8684                 (mechanism == CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE)) &&
   8685                (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) {
   8686                crv = CKR_KEY_TYPE_INCONSISTENT;
   8687                break;
   8688            }
   8689            att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE);
   8690            if ((att2 == NULL) ||
   8691                (*(CK_KEY_TYPE *)att2->attrib.pValue != CKK_GENERIC_SECRET)) {
   8692                if (att2)
   8693                    sftk_FreeAttribute(att2);
   8694                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
   8695                break;
   8696            }
   8697            sftk_FreeAttribute(att2);
   8698            if (keyType != CKK_GENERIC_SECRET) {
   8699                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
   8700                break;
   8701            }
   8702            if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) {
   8703                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
   8704                break;
   8705            }
   8706 
   8707            /* Do the key derivation */
   8708            pms.data = (unsigned char *)att->attrib.pValue;
   8709            pms.len = att->attrib.ulValueLen;
   8710            seed.data = ems_params->pSessionHash;
   8711            seed.len = ems_params->ulSessionHashLen;
   8712            master.data = key_block;
   8713            master.len = SSL3_MASTER_SECRET_LENGTH;
   8714            if (ems_params->prfHashMechanism == CKM_TLS_PRF) {
   8715                /*
   8716                 * In this case, the session hash is the concatenation of SHA-1
   8717                 * and MD5, so it should be 36 bytes long.
   8718                 */
   8719                if (seed.len != MD5_LENGTH + SHA1_LENGTH) {
   8720                    crv = CKR_TEMPLATE_INCONSISTENT;
   8721                    break;
   8722                }
   8723 
   8724                status = TLS_PRF(&pms, "extended master secret",
   8725                                 &seed, &master, isFIPS);
   8726            } else {
   8727                const SECHashObject *hashObj;
   8728 
   8729                tlsPrfHash = sftk_GetHashTypeFromMechanism(ems_params->prfHashMechanism);
   8730                if (tlsPrfHash == HASH_AlgNULL) {
   8731                    crv = CKR_MECHANISM_PARAM_INVALID;
   8732                    break;
   8733                }
   8734 
   8735                hashObj = HASH_GetRawHashObject(tlsPrfHash);
   8736                if (seed.len != hashObj->length) {
   8737                    crv = CKR_TEMPLATE_INCONSISTENT;
   8738                    break;
   8739                }
   8740 
   8741                status = TLS_P_hash(tlsPrfHash, &pms, "extended master secret",
   8742                                    &seed, &master, isFIPS);
   8743            }
   8744            if (status != SECSuccess) {
   8745                crv = CKR_FUNCTION_FAILED;
   8746                break;
   8747            }
   8748 
   8749            /* Reflect the version if required */
   8750            if (ems_params->pVersion) {
   8751                SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
   8752                rsa_pms = (SSL3RSAPreMasterSecret *)att->attrib.pValue;
   8753                /* don't leak more key material than necessary for SSL to work */
   8754                if ((sessKey == NULL) || sessKey->wasDerived) {
   8755                    ems_params->pVersion->major = 0xff;
   8756                    ems_params->pVersion->minor = 0xff;
   8757                } else {
   8758                    ems_params->pVersion->major = rsa_pms->client_version[0];
   8759                    ems_params->pVersion->minor = rsa_pms->client_version[1];
   8760                }
   8761            }
   8762 
   8763            /* Store the results */
   8764            crv = sftk_forceAttribute(key, CKA_VALUE, key_block,
   8765                                      SSL3_MASTER_SECRET_LENGTH);
   8766            PORT_Memset(key_block, 0, sizeof key_block);
   8767            break;
   8768        }
   8769 
   8770        case CKM_TLS12_KEY_AND_MAC_DERIVE:
   8771        case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256:
   8772        case CKM_TLS_KEY_AND_MAC_DERIVE:
   8773        case CKM_SSL3_KEY_AND_MAC_DERIVE: {
   8774            CK_SSL3_KEY_MAT_PARAMS *ssl3_keys;
   8775            CK_SSL3_KEY_MAT_OUT *ssl3_keys_out;
   8776            CK_ULONG effKeySize;
   8777            unsigned int block_needed;
   8778            unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2];
   8779 
   8780            if (mechanism == CKM_TLS12_KEY_AND_MAC_DERIVE) {
   8781                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_TLS12_KEY_MAT_PARAMS))) {
   8782                    crv = CKR_MECHANISM_PARAM_INVALID;
   8783                    break;
   8784                }
   8785                CK_TLS12_KEY_MAT_PARAMS *tls12_keys =
   8786                    (CK_TLS12_KEY_MAT_PARAMS *)pMechanism->pParameter;
   8787                tlsPrfHash = sftk_GetHashTypeFromMechanism(tls12_keys->prfHashMechanism);
   8788                if (tlsPrfHash == HASH_AlgNULL) {
   8789                    crv = CKR_MECHANISM_PARAM_INVALID;
   8790                    break;
   8791                }
   8792            } else if (mechanism == CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256) {
   8793                tlsPrfHash = HASH_AlgSHA256;
   8794            }
   8795 
   8796            if (mechanism != CKM_SSL3_KEY_AND_MAC_DERIVE) {
   8797                isTLS = PR_TRUE;
   8798            }
   8799 
   8800            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
   8801            if (crv != CKR_OK)
   8802                break;
   8803 
   8804            if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) {
   8805                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
   8806                break;
   8807            }
   8808            att2 = sftk_FindAttribute(sourceKey, CKA_KEY_TYPE);
   8809            if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
   8810                                   CKK_GENERIC_SECRET)) {
   8811                if (att2)
   8812                    sftk_FreeAttribute(att2);
   8813                crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
   8814                break;
   8815            }
   8816            sftk_FreeAttribute(att2);
   8817            md5 = MD5_NewContext();
   8818            if (md5 == NULL) {
   8819                crv = CKR_HOST_MEMORY;
   8820                break;
   8821            }
   8822            sha = SHA1_NewContext();
   8823            if (sha == NULL) {
   8824                MD5_DestroyContext(md5, PR_TRUE);
   8825                crv = CKR_HOST_MEMORY;
   8826                break;
   8827            }
   8828 
   8829            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_SSL3_KEY_MAT_PARAMS))) {
   8830                MD5_DestroyContext(md5, PR_TRUE);
   8831                SHA1_DestroyContext(sha, PR_TRUE);
   8832                crv = CKR_MECHANISM_PARAM_INVALID;
   8833                break;
   8834            }
   8835            ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *)pMechanism->pParameter;
   8836 
   8837            PORT_Memcpy(srcrdata,
   8838                        ssl3_keys->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
   8839            PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH,
   8840                        ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH);
   8841 
   8842            /*
   8843             * clear out our returned keys so we can recover on failure
   8844             */
   8845            ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial;
   8846            ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE;
   8847            ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE;
   8848            ssl3_keys_out->hClientKey = CK_INVALID_HANDLE;
   8849            ssl3_keys_out->hServerKey = CK_INVALID_HANDLE;
   8850 
   8851            /*
   8852             * How much key material do we need?
   8853             */
   8854            macSize = ssl3_keys->ulMacSizeInBits / 8;
   8855            effKeySize = ssl3_keys->ulKeySizeInBits / 8;
   8856            IVSize = ssl3_keys->ulIVSizeInBits / 8;
   8857            if (keySize == 0) {
   8858                effKeySize = keySize;
   8859            }
   8860 
   8861            /* bIsExport must be false. */
   8862            if (ssl3_keys->bIsExport) {
   8863                MD5_DestroyContext(md5, PR_TRUE);
   8864                SHA1_DestroyContext(sha, PR_TRUE);
   8865                PORT_Memset(srcrdata, 0, sizeof srcrdata);
   8866                crv = CKR_MECHANISM_PARAM_INVALID;
   8867                break;
   8868            }
   8869 
   8870            block_needed = 2 * (macSize + effKeySize + IVSize);
   8871            PORT_Assert(block_needed <= sizeof key_block);
   8872            if (block_needed > sizeof key_block)
   8873                block_needed = sizeof key_block;
   8874 
   8875            /*
   8876             * generate the key material: This looks amazingly similar to the
   8877             * PMS code, and is clearly crying out for a function to provide it.
   8878             */
   8879            if (isTLS) {
   8880                SECStatus status;
   8881                SECItem srcr = { siBuffer, NULL, 0 };
   8882                SECItem keyblk = { siBuffer, NULL, 0 };
   8883                SECItem master = { siBuffer, NULL, 0 };
   8884 
   8885                srcr.data = srcrdata;
   8886                srcr.len = sizeof srcrdata;
   8887                keyblk.data = key_block;
   8888                keyblk.len = block_needed;
   8889                master.data = (unsigned char *)att->attrib.pValue;
   8890                master.len = att->attrib.ulValueLen;
   8891 
   8892                if (tlsPrfHash != HASH_AlgNULL) {
   8893                    status = TLS_P_hash(tlsPrfHash, &master, "key expansion",
   8894                                        &srcr, &keyblk, isFIPS);
   8895                } else {
   8896                    status = TLS_PRF(&master, "key expansion", &srcr, &keyblk,
   8897                                     isFIPS);
   8898                }
   8899                if (status != SECSuccess) {
   8900                    goto key_and_mac_derive_fail;
   8901                }
   8902            } else {
   8903                unsigned int block_bytes = 0;
   8904                /* key_block =
   8905                 *     MD5(master_secret + SHA('A' + master_secret +
   8906                 *                      ServerHello.random + ClientHello.random)) +
   8907                 *     MD5(master_secret + SHA('BB' + master_secret +
   8908                 *                      ServerHello.random + ClientHello.random)) +
   8909                 *     MD5(master_secret + SHA('CCC' + master_secret +
   8910                 *                      ServerHello.random + ClientHello.random)) +
   8911                 *     [...];
   8912                 */
   8913                for (i = 0; i < NUM_MIXERS && block_bytes < block_needed; i++) {
   8914                    SHA1_Begin(sha);
   8915                    SHA1_Update(sha, (unsigned char *)mixers[i], strlen(mixers[i]));
   8916                    SHA1_Update(sha, (const unsigned char *)att->attrib.pValue,
   8917                                att->attrib.ulValueLen);
   8918                    SHA1_Update(sha, srcrdata, sizeof srcrdata);
   8919                    SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
   8920                    PORT_Assert(outLen == SHA1_LENGTH);
   8921                    MD5_Begin(md5);
   8922                    MD5_Update(md5, (const unsigned char *)att->attrib.pValue,
   8923                               att->attrib.ulValueLen);
   8924                    MD5_Update(md5, sha_out, outLen);
   8925                    MD5_End(md5, &key_block[i * MD5_LENGTH], &outLen, MD5_LENGTH);
   8926                    PORT_Assert(outLen == MD5_LENGTH);
   8927                    block_bytes += outLen;
   8928                }
   8929                PORT_Memset(sha_out, 0, sizeof sha_out);
   8930            }
   8931 
   8932            /*
   8933             * Put the key material where it goes.
   8934             */
   8935            i = 0; /* now shows how much consumed */
   8936 
   8937            /*
   8938             * The key_block is partitioned as follows:
   8939             * client_write_MAC_secret[CipherSpec.hash_size]
   8940             */
   8941            crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize,
   8942                                   &ssl3_keys_out->hClientMacSecret);
   8943            if (crv != CKR_OK)
   8944                goto key_and_mac_derive_fail;
   8945 
   8946            i += macSize;
   8947 
   8948            /*
   8949             * server_write_MAC_secret[CipherSpec.hash_size]
   8950             */
   8951            crv = sftk_buildSSLKey(hSession, key, PR_TRUE, &key_block[i], macSize,
   8952                                   &ssl3_keys_out->hServerMacSecret);
   8953            if (crv != CKR_OK) {
   8954                goto key_and_mac_derive_fail;
   8955            }
   8956            i += macSize;
   8957 
   8958            if (keySize) {
   8959                /*
   8960                ** Generate Domestic write keys and IVs.
   8961                ** client_write_key[CipherSpec.key_material]
   8962                */
   8963                crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i],
   8964                                       keySize, &ssl3_keys_out->hClientKey);
   8965                if (crv != CKR_OK) {
   8966                    goto key_and_mac_derive_fail;
   8967                }
   8968                i += keySize;
   8969 
   8970                /*
   8971                ** server_write_key[CipherSpec.key_material]
   8972                */
   8973                crv = sftk_buildSSLKey(hSession, key, PR_FALSE, &key_block[i],
   8974                                       keySize, &ssl3_keys_out->hServerKey);
   8975                if (crv != CKR_OK) {
   8976                    goto key_and_mac_derive_fail;
   8977                }
   8978                i += keySize;
   8979 
   8980                /*
   8981                ** client_write_IV[CipherSpec.IV_size]
   8982                */
   8983                if (IVSize > 0) {
   8984                    PORT_Memcpy(ssl3_keys_out->pIVClient,
   8985                                &key_block[i], IVSize);
   8986                    i += IVSize;
   8987                }
   8988 
   8989                /*
   8990                ** server_write_IV[CipherSpec.IV_size]
   8991                */
   8992                if (IVSize > 0) {
   8993                    PORT_Memcpy(ssl3_keys_out->pIVServer,
   8994                                &key_block[i], IVSize);
   8995                    i += IVSize;
   8996                }
   8997                PORT_Assert(i <= sizeof key_block);
   8998            }
   8999 
   9000            crv = CKR_OK;
   9001 
   9002            if (0) {
   9003            key_and_mac_derive_fail:
   9004                if (crv == CKR_OK)
   9005                    crv = CKR_FUNCTION_FAILED;
   9006                sftk_freeSSLKeys(hSession, ssl3_keys_out);
   9007            }
   9008            PORT_Memset(srcrdata, 0, sizeof srcrdata);
   9009            PORT_Memset(key_block, 0, sizeof key_block);
   9010            MD5_DestroyContext(md5, PR_TRUE);
   9011            SHA1_DestroyContext(sha, PR_TRUE);
   9012            sftk_FreeObject(key);
   9013            key = NULL;
   9014            break;
   9015        }
   9016 
   9017        case CKM_DES3_ECB_ENCRYPT_DATA:
   9018        case CKM_DES3_CBC_ENCRYPT_DATA: {
   9019            void *cipherInfo;
   9020            unsigned char des3key[MAX_DES3_KEY_SIZE];
   9021            CK_DES_CBC_ENCRYPT_DATA_PARAMS *desEncryptPtr;
   9022            int mode;
   9023            unsigned char *iv;
   9024            unsigned char *data;
   9025            CK_ULONG len;
   9026 
   9027            if (mechanism == CKM_DES3_ECB_ENCRYPT_DATA) {
   9028                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
   9029                    crv = CKR_MECHANISM_PARAM_INVALID;
   9030                    break;
   9031                }
   9032                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
   9033                                pMechanism->pParameter;
   9034                mode = NSS_DES_EDE3;
   9035                iv = NULL;
   9036                data = stringPtr->pData;
   9037                len = stringPtr->ulLen;
   9038            } else {
   9039                mode = NSS_DES_EDE3_CBC;
   9040                desEncryptPtr =
   9041                    (CK_DES_CBC_ENCRYPT_DATA_PARAMS *)
   9042                        pMechanism->pParameter;
   9043                iv = desEncryptPtr->iv;
   9044                data = desEncryptPtr->pData;
   9045                len = desEncryptPtr->length;
   9046            }
   9047            if (att->attrib.ulValueLen == 16) {
   9048                PORT_Memcpy(des3key, att->attrib.pValue, 16);
   9049                PORT_Memcpy(des3key + 16, des3key, 8);
   9050            } else if (att->attrib.ulValueLen == 24) {
   9051                PORT_Memcpy(des3key, att->attrib.pValue, 24);
   9052            } else {
   9053                crv = CKR_KEY_SIZE_RANGE;
   9054                break;
   9055            }
   9056            cipherInfo = DES_CreateContext(des3key, iv, mode, PR_TRUE);
   9057            PORT_Memset(des3key, 0, 24);
   9058            if (cipherInfo == NULL) {
   9059                crv = CKR_HOST_MEMORY;
   9060                break;
   9061            }
   9062            crv = sftk_DeriveEncrypt(SFTKCipher_DES_Encrypt,
   9063                                     cipherInfo, 8, key, keySize,
   9064                                     data, len);
   9065            DES_DestroyContext(cipherInfo, PR_TRUE);
   9066            break;
   9067        }
   9068 
   9069        case CKM_AES_ECB_ENCRYPT_DATA:
   9070        case CKM_AES_CBC_ENCRYPT_DATA: {
   9071            void *cipherInfo;
   9072            CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
   9073            int mode;
   9074            unsigned char *iv;
   9075            unsigned char *data;
   9076            CK_ULONG len;
   9077 
   9078            if (mechanism == CKM_AES_ECB_ENCRYPT_DATA) {
   9079                mode = NSS_AES;
   9080                iv = NULL;
   9081                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
   9082                    crv = CKR_MECHANISM_PARAM_INVALID;
   9083                    break;
   9084                }
   9085                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
   9086                data = stringPtr->pData;
   9087                len = stringPtr->ulLen;
   9088            } else {
   9089                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
   9090                    crv = CKR_MECHANISM_PARAM_INVALID;
   9091                    break;
   9092                }
   9093                aesEncryptPtr =
   9094                    (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)pMechanism->pParameter;
   9095                mode = NSS_AES_CBC;
   9096                iv = aesEncryptPtr->iv;
   9097                data = aesEncryptPtr->pData;
   9098                len = aesEncryptPtr->length;
   9099            }
   9100 
   9101            cipherInfo = AES_CreateContext((unsigned char *)att->attrib.pValue,
   9102                                           iv, mode, PR_TRUE,
   9103                                           att->attrib.ulValueLen, 16);
   9104            if (cipherInfo == NULL) {
   9105                crv = CKR_HOST_MEMORY;
   9106                break;
   9107            }
   9108            crv = sftk_DeriveEncrypt(SFTKCipher_AES_Encrypt,
   9109                                     cipherInfo, 16, key, keySize,
   9110                                     data, len);
   9111            AES_DestroyContext(cipherInfo, PR_TRUE);
   9112            break;
   9113        }
   9114 
   9115        case CKM_CAMELLIA_ECB_ENCRYPT_DATA:
   9116        case CKM_CAMELLIA_CBC_ENCRYPT_DATA: {
   9117            void *cipherInfo;
   9118            CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
   9119            int mode;
   9120            unsigned char *iv;
   9121            unsigned char *data;
   9122            CK_ULONG len;
   9123 
   9124            if (mechanism == CKM_CAMELLIA_ECB_ENCRYPT_DATA) {
   9125                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
   9126                    crv = CKR_MECHANISM_PARAM_INVALID;
   9127                    break;
   9128                }
   9129                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
   9130                                pMechanism->pParameter;
   9131                aesEncryptPtr = NULL;
   9132                mode = NSS_CAMELLIA;
   9133                data = stringPtr->pData;
   9134                len = stringPtr->ulLen;
   9135                iv = NULL;
   9136            } else {
   9137                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
   9138                    crv = CKR_MECHANISM_PARAM_INVALID;
   9139                    break;
   9140                }
   9141                stringPtr = NULL;
   9142                aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
   9143                                    pMechanism->pParameter;
   9144                mode = NSS_CAMELLIA_CBC;
   9145                iv = aesEncryptPtr->iv;
   9146                data = aesEncryptPtr->pData;
   9147                len = aesEncryptPtr->length;
   9148            }
   9149 
   9150            cipherInfo = Camellia_CreateContext((unsigned char *)att->attrib.pValue,
   9151                                                iv, mode, PR_TRUE,
   9152                                                att->attrib.ulValueLen);
   9153            if (cipherInfo == NULL) {
   9154                crv = CKR_HOST_MEMORY;
   9155                break;
   9156            }
   9157            crv = sftk_DeriveEncrypt(SFTKCipher_Camellia_Encrypt,
   9158                                     cipherInfo, 16, key, keySize,
   9159                                     data, len);
   9160            Camellia_DestroyContext(cipherInfo, PR_TRUE);
   9161            break;
   9162        }
   9163 
   9164 #ifndef NSS_DISABLE_DEPRECATED_SEED
   9165        case CKM_SEED_ECB_ENCRYPT_DATA:
   9166        case CKM_SEED_CBC_ENCRYPT_DATA: {
   9167            void *cipherInfo;
   9168            CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
   9169            int mode;
   9170            unsigned char *iv;
   9171            unsigned char *data;
   9172            CK_ULONG len;
   9173 
   9174            if (mechanism == CKM_SEED_ECB_ENCRYPT_DATA) {
   9175                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
   9176                    crv = CKR_MECHANISM_PARAM_INVALID;
   9177                    break;
   9178                }
   9179                mode = NSS_SEED;
   9180                stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)
   9181                                pMechanism->pParameter;
   9182                aesEncryptPtr = NULL;
   9183                data = stringPtr->pData;
   9184                len = stringPtr->ulLen;
   9185                iv = NULL;
   9186            } else {
   9187                if (BAD_PARAM_CAST(pMechanism, sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))) {
   9188                    crv = CKR_MECHANISM_PARAM_INVALID;
   9189                    break;
   9190                }
   9191                mode = NSS_SEED_CBC;
   9192                aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
   9193                                    pMechanism->pParameter;
   9194                iv = aesEncryptPtr->iv;
   9195                data = aesEncryptPtr->pData;
   9196                len = aesEncryptPtr->length;
   9197            }
   9198 
   9199            cipherInfo = SEED_CreateContext((unsigned char *)att->attrib.pValue,
   9200                                            iv, mode, PR_TRUE);
   9201            if (cipherInfo == NULL) {
   9202                crv = CKR_HOST_MEMORY;
   9203                break;
   9204            }
   9205            crv = sftk_DeriveEncrypt(SFTKCipher_SEED_Encrypt,
   9206                                     cipherInfo, 16, key, keySize,
   9207                                     data, len);
   9208            SEED_DestroyContext(cipherInfo, PR_TRUE);
   9209            break;
   9210        }
   9211 #endif /* NSS_DISABLE_DEPRECATED_SEED */
   9212 
   9213        case CKM_CONCATENATE_BASE_AND_KEY: {
   9214            SFTKObject *paramKey;
   9215 
   9216            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
   9217            if (crv != CKR_OK)
   9218                break;
   9219 
   9220            session = sftk_SessionFromHandle(hSession);
   9221            if (session == NULL) {
   9222                crv = CKR_SESSION_HANDLE_INVALID;
   9223                break;
   9224            }
   9225 
   9226            paramKey = sftk_ObjectFromHandle(*(CK_OBJECT_HANDLE *)
   9227                                                  pMechanism->pParameter,
   9228                                             session);
   9229            sftk_FreeSession(session);
   9230            if (paramKey == NULL) {
   9231                crv = CKR_KEY_HANDLE_INVALID;
   9232                break;
   9233            }
   9234 
   9235            if (sftk_isTrue(paramKey, CKA_SENSITIVE)) {
   9236                crv = sftk_forceAttribute(key, CKA_SENSITIVE, &cktrue,
   9237                                          sizeof(CK_BBOOL));
   9238                if (crv != CKR_OK) {
   9239                    sftk_FreeObject(paramKey);
   9240                    break;
   9241                }
   9242            }
   9243 
   9244            if (sftk_hasAttribute(paramKey, CKA_EXTRACTABLE) && !sftk_isTrue(paramKey, CKA_EXTRACTABLE)) {
   9245                crv = sftk_forceAttribute(key, CKA_EXTRACTABLE, &ckfalse, sizeof(CK_BBOOL));
   9246                if (crv != CKR_OK) {
   9247                    sftk_FreeObject(paramKey);
   9248                    break;
   9249                }
   9250            }
   9251 
   9252            att2 = sftk_FindAttribute(paramKey, CKA_VALUE);
   9253            if (att2 == NULL) {
   9254                sftk_FreeObject(paramKey);
   9255                crv = CKR_KEY_HANDLE_INVALID;
   9256                break;
   9257            }
   9258            tmpKeySize = att->attrib.ulValueLen + att2->attrib.ulValueLen;
   9259            if (keySize == 0)
   9260                keySize = tmpKeySize;
   9261            if (keySize > tmpKeySize) {
   9262                sftk_FreeObject(paramKey);
   9263                sftk_FreeAttribute(att2);
   9264                crv = CKR_TEMPLATE_INCONSISTENT;
   9265                break;
   9266            }
   9267            buf = (unsigned char *)PORT_Alloc(tmpKeySize);
   9268            if (buf == NULL) {
   9269                sftk_FreeAttribute(att2);
   9270                sftk_FreeObject(paramKey);
   9271                crv = CKR_HOST_MEMORY;
   9272                break;
   9273            }
   9274 
   9275            PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen);
   9276            PORT_Memcpy(buf + att->attrib.ulValueLen,
   9277                        att2->attrib.pValue, att2->attrib.ulValueLen);
   9278 
   9279            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
   9280            PORT_ZFree(buf, tmpKeySize);
   9281            sftk_FreeAttribute(att2);
   9282            sftk_FreeObject(paramKey);
   9283            break;
   9284        }
   9285 
   9286        case CKM_CONCATENATE_BASE_AND_DATA:
   9287            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
   9288            if (crv != CKR_OK)
   9289                break;
   9290 
   9291            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
   9292                crv = CKR_MECHANISM_PARAM_INVALID;
   9293                break;
   9294            }
   9295            stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
   9296            tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen;
   9297            if (keySize == 0)
   9298                keySize = tmpKeySize;
   9299            if (keySize > tmpKeySize) {
   9300                crv = CKR_TEMPLATE_INCONSISTENT;
   9301                break;
   9302            }
   9303            buf = (unsigned char *)PORT_Alloc(tmpKeySize);
   9304            if (buf == NULL) {
   9305                crv = CKR_HOST_MEMORY;
   9306                break;
   9307            }
   9308 
   9309            PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen);
   9310            PORT_Memcpy(buf + att->attrib.ulValueLen, stringPtr->pData,
   9311                        stringPtr->ulLen);
   9312 
   9313            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
   9314            PORT_ZFree(buf, tmpKeySize);
   9315            break;
   9316        case CKM_CONCATENATE_DATA_AND_BASE:
   9317            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
   9318            if (crv != CKR_OK)
   9319                break;
   9320 
   9321            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
   9322                crv = CKR_MECHANISM_PARAM_INVALID;
   9323                break;
   9324            }
   9325            stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
   9326            tmpKeySize = att->attrib.ulValueLen + stringPtr->ulLen;
   9327            if (keySize == 0)
   9328                keySize = tmpKeySize;
   9329            if (keySize > tmpKeySize) {
   9330                crv = CKR_TEMPLATE_INCONSISTENT;
   9331                break;
   9332            }
   9333            buf = (unsigned char *)PORT_Alloc(tmpKeySize);
   9334            if (buf == NULL) {
   9335                crv = CKR_HOST_MEMORY;
   9336                break;
   9337            }
   9338 
   9339            PORT_Memcpy(buf, stringPtr->pData, stringPtr->ulLen);
   9340            PORT_Memcpy(buf + stringPtr->ulLen, att->attrib.pValue,
   9341                        att->attrib.ulValueLen);
   9342 
   9343            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
   9344            PORT_ZFree(buf, tmpKeySize);
   9345            break;
   9346        case CKM_XOR_BASE_AND_DATA:
   9347            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
   9348            if (crv != CKR_OK)
   9349                break;
   9350 
   9351            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_KEY_DERIVATION_STRING_DATA))) {
   9352                crv = CKR_MECHANISM_PARAM_INVALID;
   9353                break;
   9354            }
   9355            stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
   9356            tmpKeySize = PR_MIN(att->attrib.ulValueLen, stringPtr->ulLen);
   9357            if (keySize == 0)
   9358                keySize = tmpKeySize;
   9359            if (keySize > tmpKeySize) {
   9360                crv = CKR_TEMPLATE_INCONSISTENT;
   9361                break;
   9362            }
   9363            buf = (unsigned char *)PORT_Alloc(keySize);
   9364            if (buf == NULL) {
   9365                crv = CKR_HOST_MEMORY;
   9366                break;
   9367            }
   9368 
   9369            PORT_Memcpy(buf, att->attrib.pValue, keySize);
   9370            for (i = 0; i < (int)keySize; i++) {
   9371                buf[i] ^= stringPtr->pData[i];
   9372            }
   9373 
   9374            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
   9375            PORT_ZFree(buf, keySize);
   9376            break;
   9377 
   9378        case CKM_EXTRACT_KEY_FROM_KEY: {
   9379            if (BAD_PARAM_CAST(pMechanism, sizeof(CK_EXTRACT_PARAMS))) {
   9380                crv = CKR_MECHANISM_PARAM_INVALID;
   9381                break;
   9382            }
   9383            /* the following assumes 8 bits per byte */
   9384            CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter;
   9385            CK_ULONG shift = extract & 0x7; /* extract mod 8 the fast way */
   9386            CK_ULONG offset = extract >> 3; /* extract div 8 the fast way */
   9387 
   9388            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
   9389            if (crv != CKR_OK)
   9390                break;
   9391 
   9392            if (keySize == 0) {
   9393                crv = CKR_TEMPLATE_INCOMPLETE;
   9394                break;
   9395            }
   9396            /* make sure we have enough bits in the original key */
   9397            if (att->attrib.ulValueLen <
   9398                (offset + keySize + ((shift != 0) ? 1 : 0))) {
   9399                crv = CKR_MECHANISM_PARAM_INVALID;
   9400                break;
   9401            }
   9402            buf = (unsigned char *)PORT_Alloc(keySize);
   9403            if (buf == NULL) {
   9404                crv = CKR_HOST_MEMORY;
   9405                break;
   9406            }
   9407 
   9408            /* copy the bits we need into the new key */
   9409            for (i = 0; i < (int)keySize; i++) {
   9410                unsigned char *value =
   9411                    ((unsigned char *)att->attrib.pValue) + offset + i;
   9412                if (shift) {
   9413                    buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift));
   9414                } else {
   9415                    buf[i] = value[0];
   9416                }
   9417            }
   9418 
   9419            crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
   9420            PORT_ZFree(buf, keySize);
   9421            break;
   9422        }
   9423        case CKM_MD2_KEY_DERIVATION:
   9424            if (keySize == 0)
   9425                keySize = MD2_LENGTH;
   9426            if (keySize > MD2_LENGTH) {
   9427                crv = CKR_TEMPLATE_INCONSISTENT;
   9428                break;
   9429            }
   9430            /* now allocate the hash contexts */
   9431            md2 = MD2_NewContext();
   9432            if (md2 == NULL) {
   9433                crv = CKR_HOST_MEMORY;
   9434                break;
   9435            }
   9436            MD2_Begin(md2);
   9437            MD2_Update(md2, (const unsigned char *)att->attrib.pValue,
   9438                       att->attrib.ulValueLen);
   9439            MD2_End(md2, key_block, &outLen, MD2_LENGTH);
   9440            MD2_DestroyContext(md2, PR_TRUE);
   9441 
   9442            crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize);
   9443            PORT_Memset(key_block, 0, MD2_LENGTH);
   9444            break;
   9445 #define DERIVE_KEY_HASH(hash)                                                \
   9446    case CKM_##hash##_KEY_DERIVATION:                                        \
   9447        if (keySize == 0)                                                    \
   9448            keySize = hash##_LENGTH;                                         \
   9449        if (keySize > hash##_LENGTH) {                                       \
   9450            crv = CKR_TEMPLATE_INCONSISTENT;                                 \
   9451            break;                                                           \
   9452        }                                                                    \
   9453        hash##_HashBuf(key_block, (const unsigned char *)att->attrib.pValue, \
   9454                       att->attrib.ulValueLen);                              \
   9455        crv = sftk_forceAttribute(key, CKA_VALUE, key_block, keySize);       \
   9456        PORT_Memset(key_block, 0, hash##_LENGTH);                            \
   9457        break;
   9458            DERIVE_KEY_HASH(MD5)
   9459            DERIVE_KEY_HASH(SHA1)
   9460            DERIVE_KEY_HASH(SHA224)
   9461            DERIVE_KEY_HASH(SHA256)
   9462            DERIVE_KEY_HASH(SHA384)
   9463            DERIVE_KEY_HASH(SHA512)
   9464            DERIVE_KEY_HASH(SHA3_224)
   9465            DERIVE_KEY_HASH(SHA3_256)
   9466            DERIVE_KEY_HASH(SHA3_384)
   9467            DERIVE_KEY_HASH(SHA3_512)
   9468 
   9469        case CKM_DH_PKCS_DERIVE: {
   9470            SECItem derived, dhPublic;
   9471            SECItem dhPrime, dhValue;
   9472            const SECItem *subPrime;
   9473            /* sourceKey - values for the local existing low key */
   9474            /* get prime and value attributes */
   9475            crv = sftk_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME);
   9476            if (crv != CKR_OK)
   9477                break;
   9478 
   9479            dhPublic.data = pMechanism->pParameter;
   9480            dhPublic.len = pMechanism->ulParameterLen;
   9481 
   9482            /* if the prime is an approved prime, we can skip all the other
   9483             * checks. */
   9484            subPrime = sftk_VerifyDH_Prime(&dhPrime, NULL, isFIPS);
   9485            if (subPrime == NULL) {
   9486                SECItem dhSubPrime;
   9487                /* If the caller set the subprime value, it means that
   9488                 * either the caller knows the subprime value and wants us
   9489                 * to validate the key against the subprime, or that the
   9490                 * caller wants us to verify that the prime is a safe prime
   9491                 * by passing in subprime = (prime-1)/2 */
   9492                dhSubPrime.data = NULL;
   9493                dhSubPrime.len = 0;
   9494                crv = sftk_Attribute2SecItem(NULL, &dhSubPrime,
   9495                                             sourceKey, CKA_SUBPRIME);
   9496                /* we ignore the value of crv here, We treat a valid
   9497                 * return of len = 0 and a failure to find a subrime the same
   9498                 * NOTE: we free the subprime in both cases depending on
   9499                 * PORT_Free of NULL to be a noop */
   9500                if (dhSubPrime.len != 0) {
   9501                    PRBool isSafe = PR_FALSE;
   9502 
   9503                    /* Callers can set dhSubPrime to q=(p-1)/2 to force
   9504                     * checks for safe primes. If so we only need to check
   9505                     * q and p for primality and skip the group test.  */
   9506                    rv = sftk_IsSafePrime(&dhPrime, &dhSubPrime, &isSafe);
   9507                    if (rv != SECSuccess) {
   9508                        /* either p or q was even and therefore not prime,
   9509                         * we can stop processing here and fail now */
   9510                        crv = CKR_ARGUMENTS_BAD;
   9511                        SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
   9512                        SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
   9513                        break;
   9514                    }
   9515 
   9516                    /* first make sure the primes are really prime */
   9517                    if (!KEA_PrimeCheck(&dhPrime)) {
   9518                        crv = CKR_ARGUMENTS_BAD;
   9519                        SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
   9520                        SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
   9521                        break;
   9522                    }
   9523                    if (!KEA_PrimeCheck(&dhSubPrime)) {
   9524                        crv = CKR_ARGUMENTS_BAD;
   9525                        SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
   9526                        SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
   9527                        break;
   9528                    }
   9529                    if (isFIPS || !isSafe) {
   9530                        /* With safe primes, there is only one other small
   9531                         * subgroup. As long as y isn't 0, 1, or -1 mod p,
   9532                         * any other y is safe. Only do the full check for
   9533                         * non-safe primes, except in FIPS mode we need
   9534                         * to do this check on all primes in which
   9535                         * we receive the subprime value */
   9536                        if (!KEA_Verify(&dhPublic, &dhPrime, &dhSubPrime)) {
   9537                            crv = CKR_ARGUMENTS_BAD;
   9538                            SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
   9539                            SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
   9540                            break;
   9541                        }
   9542                    }
   9543                } else if (isFIPS) {
   9544                    /* In FIPS mode we only accept approved primes, or
   9545                     * primes with the full subprime value */
   9546                    crv = CKR_ARGUMENTS_BAD;
   9547                    SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
   9548                    break;
   9549                }
   9550                /* checks are complete, no need for the subPrime any longer */
   9551                SECITEM_ZfreeItem(&dhSubPrime, PR_FALSE);
   9552            }
   9553 
   9554            /* now that the prime is validated, get the private value */
   9555            crv = sftk_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE);
   9556            if (crv != CKR_OK) {
   9557                SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
   9558                break;
   9559            }
   9560 
   9561            /* calculate private value - oct */
   9562            rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize);
   9563 
   9564            SECITEM_ZfreeItem(&dhPrime, PR_FALSE);
   9565            SECITEM_ZfreeItem(&dhValue, PR_FALSE);
   9566 
   9567            if (rv == SECSuccess) {
   9568                sftk_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
   9569                SECITEM_ZfreeItem(&derived, PR_FALSE);
   9570                crv = CKR_OK;
   9571            } else
   9572                crv = CKR_HOST_MEMORY;
   9573 
   9574            break;
   9575        }
   9576 
   9577        case CKM_ECDH1_DERIVE:
   9578        case CKM_ECDH1_COFACTOR_DERIVE: {
   9579            SECItem ecScalar, ecPoint;
   9580            SECItem tmp;
   9581            PRBool withCofactor = PR_FALSE;
   9582            unsigned char *secret;
   9583            unsigned char *keyData = NULL;
   9584            unsigned int secretlen, pubKeyLen;
   9585            CK_ECDH1_DERIVE_PARAMS *mechParams;
   9586            NSSLOWKEYPrivateKey *privKey;
   9587            PLArenaPool *arena = NULL;
   9588 
   9589            /* Check mechanism parameters */
   9590            mechParams = (CK_ECDH1_DERIVE_PARAMS *)pMechanism->pParameter;
   9591            if ((pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) ||
   9592                ((mechParams->kdf == CKD_NULL) &&
   9593                 ((mechParams->ulSharedDataLen != 0) ||
   9594                  (mechParams->pSharedData != NULL)))) {
   9595                crv = CKR_MECHANISM_PARAM_INVALID;
   9596                break;
   9597            }
   9598 
   9599            privKey = sftk_GetPrivKey(sourceKey, CKK_EC, &crv);
   9600            if (privKey == NULL) {
   9601                break;
   9602            }
   9603 
   9604            /* Now we are working with a non-NULL private key */
   9605            SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue);
   9606 
   9607            ecPoint.data = mechParams->pPublicData;
   9608            ecPoint.len = mechParams->ulPublicDataLen;
   9609 
   9610            pubKeyLen = EC_GetPointSize(&privKey->u.ec.ecParams);
   9611 
   9612            /* if the len is too large, might be an encoded point */
   9613            if (ecPoint.len > pubKeyLen) {
   9614                SECItem newPoint;
   9615 
   9616                arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   9617                if (arena == NULL) {
   9618                    goto ec_loser;
   9619                }
   9620 
   9621                rv = SEC_QuickDERDecodeItem(arena, &newPoint,
   9622                                            SEC_ASN1_GET(SEC_OctetStringTemplate),
   9623                                            &ecPoint);
   9624                if (rv != SECSuccess) {
   9625                    goto ec_loser;
   9626                }
   9627                ecPoint = newPoint;
   9628            }
   9629 
   9630            if (mechanism == CKM_ECDH1_COFACTOR_DERIVE) {
   9631                withCofactor = PR_TRUE;
   9632            }
   9633 
   9634            rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar,
   9635                             withCofactor, &tmp);
   9636            SECITEM_ZfreeItem(&ecScalar, PR_FALSE);
   9637            ecScalar.data = NULL;
   9638            if (privKey != sourceKey->objectInfo) {
   9639                nsslowkey_DestroyPrivateKey(privKey);
   9640                privKey = NULL;
   9641            }
   9642            if (arena) {
   9643                PORT_FreeArena(arena, PR_FALSE);
   9644                arena = NULL;
   9645            }
   9646 
   9647            if (rv != SECSuccess) {
   9648                crv = sftk_MapCryptError(PORT_GetError());
   9649                break;
   9650            }
   9651 
   9652            /*
   9653             * apply the kdf function.
   9654             */
   9655            if (mechParams->kdf == CKD_NULL) {
   9656                /*
   9657                 * tmp is the raw data created by ECDH_Derive,
   9658                 * secret and secretlen are the values we will
   9659                 * eventually pass as our generated key.
   9660                 */
   9661                secret = tmp.data;
   9662                secretlen = tmp.len;
   9663            } else {
   9664                secretlen = keySize;
   9665                crv = sftk_ANSI_X9_63_kdf(&secret, keySize,
   9666                                          &tmp, mechParams->pSharedData,
   9667                                          mechParams->ulSharedDataLen, mechParams->kdf);
   9668                PORT_ZFree(tmp.data, tmp.len);
   9669                if (crv != CKR_OK) {
   9670                    break;
   9671                }
   9672                tmp.data = secret;
   9673                tmp.len = secretlen;
   9674            }
   9675 
   9676            /*
   9677             * if keySize is supplied, then we are generating a key of a specific
   9678             * length. This is done by taking the least significant 'keySize'
   9679             * bytes from the unsigned value calculated by ECDH. Note: this may
   9680             * mean padding temp with extra leading zeros from what ECDH_Derive
   9681             * already returned (which itself may contain leading zeros).
   9682             */
   9683            if (keySize) {
   9684                if (secretlen < keySize) {
   9685                    keyData = PORT_ZAlloc(keySize);
   9686                    if (!keyData) {
   9687                        PORT_ZFree(tmp.data, tmp.len);
   9688                        crv = CKR_HOST_MEMORY;
   9689                        break;
   9690                    }
   9691                    PORT_Memcpy(&keyData[keySize - secretlen], secret, secretlen);
   9692                    secret = keyData;
   9693                } else {
   9694                    secret += (secretlen - keySize);
   9695                }
   9696                secretlen = keySize;
   9697            }
   9698 
   9699            sftk_forceAttribute(key, CKA_VALUE, secret, secretlen);
   9700            PORT_ZFree(tmp.data, tmp.len);
   9701            if (keyData) {
   9702                PORT_ZFree(keyData, keySize);
   9703            }
   9704            break;
   9705 
   9706        ec_loser:
   9707            crv = CKR_ARGUMENTS_BAD;
   9708            SECITEM_ZfreeItem(&ecScalar, PR_FALSE);
   9709            if (privKey != sourceKey->objectInfo)
   9710                nsslowkey_DestroyPrivateKey(privKey);
   9711            if (arena) {
   9712                PORT_FreeArena(arena, PR_TRUE);
   9713            }
   9714            break;
   9715        }
   9716        /* See RFC 5869 and CK_NSS_HKDFParams for documentation. */
   9717        case CKM_NSS_HKDF_SHA1:
   9718            hashMech = CKM_SHA_1;
   9719            goto hkdf;
   9720        case CKM_NSS_HKDF_SHA256:
   9721            hashMech = CKM_SHA256;
   9722            goto hkdf;
   9723        case CKM_NSS_HKDF_SHA384:
   9724            hashMech = CKM_SHA384;
   9725            goto hkdf;
   9726        case CKM_NSS_HKDF_SHA512:
   9727            hashMech = CKM_SHA512;
   9728            goto hkdf;
   9729        hkdf : {
   9730            const CK_NSS_HKDFParams *params =
   9731                (const CK_NSS_HKDFParams *)pMechanism->pParameter;
   9732            CK_HKDF_PARAMS hkdfParams;
   9733 
   9734            if (pMechanism->ulParameterLen != sizeof(CK_NSS_HKDFParams)) {
   9735                crv = CKR_MECHANISM_PARAM_INVALID;
   9736                break;
   9737            }
   9738            hkdfParams.bExtract = params->bExtract;
   9739            hkdfParams.bExpand = params->bExpand;
   9740            if (params->pSalt) {
   9741                hkdfParams.ulSaltType = CKF_HKDF_SALT_DATA;
   9742            } else {
   9743                hkdfParams.ulSaltType = CKF_HKDF_SALT_NULL;
   9744            }
   9745            hkdfParams.pSalt = params->pSalt;
   9746            hkdfParams.ulSaltLen = params->ulSaltLen;
   9747            hkdfParams.hSaltKey = CK_INVALID_HANDLE;
   9748            hkdfParams.pInfo = params->pInfo;
   9749            hkdfParams.ulInfoLen = params->ulInfoLen;
   9750            hkdfParams.prfHashMechanism = hashMech;
   9751 
   9752            crv = sftk_HKDF(&hkdfParams, hSession, sourceKey,
   9753                            att->attrib.pValue, att->attrib.ulValueLen,
   9754                            key, NULL, keySize, PR_FALSE, isFIPS);
   9755        } break;
   9756        case CKM_HKDF_DERIVE:
   9757        case CKM_HKDF_DATA: /* only difference is the class of key */
   9758            if ((pMechanism->pParameter == NULL) ||
   9759                (pMechanism->ulParameterLen != sizeof(CK_HKDF_PARAMS))) {
   9760                crv = CKR_MECHANISM_PARAM_INVALID;
   9761                break;
   9762            }
   9763            crv = sftk_HKDF((CK_HKDF_PARAMS_PTR)pMechanism->pParameter,
   9764                            hSession, sourceKey, att->attrib.pValue,
   9765                            att->attrib.ulValueLen, key, NULL, keySize, PR_TRUE,
   9766                            isFIPS);
   9767            break;
   9768        case CKM_NSS_JPAKE_ROUND2_SHA1:
   9769            hashType = HASH_AlgSHA1;
   9770            goto jpake2;
   9771        case CKM_NSS_JPAKE_ROUND2_SHA256:
   9772            hashType = HASH_AlgSHA256;
   9773            goto jpake2;
   9774        case CKM_NSS_JPAKE_ROUND2_SHA384:
   9775            hashType = HASH_AlgSHA384;
   9776            goto jpake2;
   9777        case CKM_NSS_JPAKE_ROUND2_SHA512:
   9778            hashType = HASH_AlgSHA512;
   9779            goto jpake2;
   9780        jpake2:
   9781            if (pMechanism->pParameter == NULL ||
   9782                pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKERound2Params))
   9783                crv = CKR_MECHANISM_PARAM_INVALID;
   9784            if (crv == CKR_OK && sftk_isTrue(key, CKA_TOKEN))
   9785                crv = CKR_TEMPLATE_INCONSISTENT;
   9786            if (crv == CKR_OK)
   9787                crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
   9788            if (crv == CKR_OK)
   9789                crv = jpake_Round2(hashType,
   9790                                   (CK_NSS_JPAKERound2Params *)pMechanism->pParameter,
   9791                                   sourceKey, key);
   9792            break;
   9793 
   9794        case CKM_NSS_JPAKE_FINAL_SHA1:
   9795            hashType = HASH_AlgSHA1;
   9796            goto jpakeFinal;
   9797        case CKM_NSS_JPAKE_FINAL_SHA256:
   9798            hashType = HASH_AlgSHA256;
   9799            goto jpakeFinal;
   9800        case CKM_NSS_JPAKE_FINAL_SHA384:
   9801            hashType = HASH_AlgSHA384;
   9802            goto jpakeFinal;
   9803        case CKM_NSS_JPAKE_FINAL_SHA512:
   9804            hashType = HASH_AlgSHA512;
   9805            goto jpakeFinal;
   9806        jpakeFinal:
   9807            if (pMechanism->pParameter == NULL ||
   9808                pMechanism->ulParameterLen != sizeof(CK_NSS_JPAKEFinalParams))
   9809                crv = CKR_MECHANISM_PARAM_INVALID;
   9810            /* We purposely do not do the derive sensitivity check; we want to be
   9811               able to derive non-sensitive keys while allowing the ROUND1 and
   9812               ROUND2 keys to be sensitive (which they always are, since they are
   9813               in the CKO_PRIVATE_KEY class). The caller must include CKA_SENSITIVE
   9814               in the template in order for the resultant keyblock key to be
   9815               sensitive.
   9816             */
   9817            if (crv == CKR_OK)
   9818                crv = jpake_Final(hashType,
   9819                                  (CK_NSS_JPAKEFinalParams *)pMechanism->pParameter,
   9820                                  sourceKey, key);
   9821            break;
   9822 
   9823        case CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA:         /* fall through */
   9824        case CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA:        /* fall through */
   9825        case CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA: /* fall through */
   9826        case CKM_SP800_108_COUNTER_KDF:                         /* fall through */
   9827        case CKM_SP800_108_FEEDBACK_KDF:                        /* fall through */
   9828        case CKM_SP800_108_DOUBLE_PIPELINE_KDF:
   9829            crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
   9830            if (crv != CKR_OK) {
   9831                break;
   9832            }
   9833 
   9834            crv = kbkdf_Dispatch(mechanism, hSession, pMechanism, sourceKey, key, keySize);
   9835            break;
   9836        default:
   9837            crv = CKR_MECHANISM_INVALID;
   9838    }
   9839    if (att) {
   9840        sftk_FreeAttribute(att);
   9841    }
   9842    sftk_FreeObject(sourceKey);
   9843    if (crv != CKR_OK) {
   9844        if (key)
   9845            sftk_FreeObject(key);
   9846        return crv;
   9847    }
   9848 
   9849    /* link the key object into the list */
   9850    if (key) {
   9851        SFTKSessionObject *sessKey = sftk_narrowToSessionObject(key);
   9852        PORT_Assert(sessKey);
   9853        /* get the session */
   9854        sessKey->wasDerived = PR_TRUE;
   9855        session = sftk_SessionFromHandle(hSession);
   9856        if (session == NULL) {
   9857            sftk_FreeObject(key);
   9858            return CKR_HOST_MEMORY;
   9859        }
   9860 
   9861        crv = sftk_handleObject(key, session);
   9862        session->lastOpWasFIPS = sftk_hasFIPS(key);
   9863        sftk_FreeSession(session);
   9864        if (phKey) {
   9865            *phKey = key->handle;
   9866        }
   9867        sftk_FreeObject(key);
   9868    }
   9869    return crv;
   9870 }
   9871 
   9872 /* NSC_GetFunctionStatus obtains an updated status of a function running
   9873 * in parallel with an application. */
   9874 CK_RV
   9875 NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession)
   9876 {
   9877    CHECK_FORK();
   9878 
   9879    return CKR_FUNCTION_NOT_PARALLEL;
   9880 }
   9881 
   9882 /* NSC_CancelFunction cancels a function running in parallel */
   9883 CK_RV
   9884 NSC_CancelFunction(CK_SESSION_HANDLE hSession)
   9885 {
   9886    CHECK_FORK();
   9887 
   9888    return CKR_FUNCTION_NOT_PARALLEL;
   9889 }
   9890 
   9891 /* NSC_GetOperationState saves the state of the cryptographic
   9892 * operation in a session.
   9893 * NOTE: This code only works for digest functions for now. eventually need
   9894 * to add full flatten/resurect to our state stuff so that all types of state
   9895 * can be saved */
   9896 CK_RV
   9897 NSC_GetOperationState(CK_SESSION_HANDLE hSession,
   9898                      CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen)
   9899 {
   9900    SFTKSessionContext *context;
   9901    SFTKSession *session;
   9902    CK_RV crv;
   9903    CK_ULONG pOSLen = *pulOperationStateLen;
   9904 
   9905    CHECK_FORK();
   9906 
   9907    /* make sure we're legal */
   9908    crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
   9909    if (crv != CKR_OK)
   9910        return crv;
   9911 
   9912    /* a zero cipherInfoLen signals that this context cannot be serialized */
   9913    if (context->cipherInfoLen == 0) {
   9914        return CKR_STATE_UNSAVEABLE;
   9915    }
   9916 
   9917    *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE) + sizeof(SFTKContextType);
   9918    if (pOperationState == NULL) {
   9919        sftk_FreeSession(session);
   9920        return CKR_OK;
   9921    } else {
   9922        if (pOSLen < *pulOperationStateLen) {
   9923            return CKR_BUFFER_TOO_SMALL;
   9924        }
   9925    }
   9926    PORT_Memcpy(pOperationState, &context->type, sizeof(SFTKContextType));
   9927    pOperationState += sizeof(SFTKContextType);
   9928    PORT_Memcpy(pOperationState, &context->currentMech,
   9929                sizeof(CK_MECHANISM_TYPE));
   9930    pOperationState += sizeof(CK_MECHANISM_TYPE);
   9931    PORT_Memcpy(pOperationState, context->cipherInfo, context->cipherInfoLen);
   9932    sftk_FreeSession(session);
   9933    return CKR_OK;
   9934 }
   9935 
   9936 #define sftk_Decrement(stateSize, len) \
   9937    stateSize = ((stateSize) > (CK_ULONG)(len)) ? ((stateSize) - (CK_ULONG)(len)) : 0;
   9938 
   9939 /* NSC_SetOperationState restores the state of the cryptographic
   9940 * operation in a session. This is coded like it can restore lots of
   9941 * states, but it only works for truly flat cipher structures. */
   9942 CK_RV
   9943 NSC_SetOperationState(CK_SESSION_HANDLE hSession,
   9944                      CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen,
   9945                      CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey)
   9946 {
   9947    SFTKSessionContext *context;
   9948    SFTKSession *session;
   9949    SFTKContextType type;
   9950    CK_MECHANISM mech;
   9951    CK_RV crv = CKR_OK;
   9952 
   9953    CHECK_FORK();
   9954 
   9955    while (ulOperationStateLen != 0) {
   9956        /* get what type of state we're dealing with... */
   9957        PORT_Memcpy(&type, pOperationState, sizeof(SFTKContextType));
   9958 
   9959        /* fix up session contexts based on type */
   9960        session = sftk_SessionFromHandle(hSession);
   9961        if (session == NULL)
   9962            return CKR_SESSION_HANDLE_INVALID;
   9963        context = sftk_ReturnContextByType(session, type);
   9964        sftk_SetContextByType(session, type, NULL);
   9965        if (context) {
   9966            sftk_FreeContext(context);
   9967        }
   9968        pOperationState += sizeof(SFTKContextType);
   9969        sftk_Decrement(ulOperationStateLen, sizeof(SFTKContextType));
   9970 
   9971        /* get the mechanism structure */
   9972        PORT_Memcpy(&mech.mechanism, pOperationState, sizeof(CK_MECHANISM_TYPE));
   9973        pOperationState += sizeof(CK_MECHANISM_TYPE);
   9974        sftk_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE));
   9975        /* should be filled in... but not necessary for hash */
   9976        mech.pParameter = NULL;
   9977        mech.ulParameterLen = 0;
   9978        switch (type) {
   9979            case SFTK_HASH:
   9980                crv = NSC_DigestInit(hSession, &mech);
   9981                if (crv != CKR_OK)
   9982                    break;
   9983                crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE,
   9984                                      NULL);
   9985                if (crv != CKR_OK)
   9986                    break;
   9987                if (context->cipherInfoLen == 0) {
   9988                    crv = CKR_SAVED_STATE_INVALID;
   9989                    break;
   9990                }
   9991                PORT_Memcpy(context->cipherInfo, pOperationState,
   9992                            context->cipherInfoLen);
   9993                pOperationState += context->cipherInfoLen;
   9994                sftk_Decrement(ulOperationStateLen, context->cipherInfoLen);
   9995                break;
   9996            default:
   9997                /* do sign/encrypt/decrypt later */
   9998                crv = CKR_SAVED_STATE_INVALID;
   9999        }
  10000        sftk_FreeSession(session);
  10001        if (crv != CKR_OK)
  10002            break;
  10003    }
  10004    return crv;
  10005 }
  10006 
  10007 /* Dual-function cryptographic operations */
  10008 
  10009 /* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption
  10010 * operation. */
  10011 CK_RV
  10012 NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
  10013                        CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
  10014                        CK_ULONG_PTR pulEncryptedPartLen)
  10015 {
  10016    CK_RV crv;
  10017 
  10018    CHECK_FORK();
  10019 
  10020    crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart,
  10021                            pulEncryptedPartLen);
  10022    if (crv != CKR_OK)
  10023        return crv;
  10024    crv = NSC_DigestUpdate(hSession, pPart, ulPartLen);
  10025 
  10026    return crv;
  10027 }
  10028 
  10029 /* NSC_DecryptDigestUpdate continues a multiple-part decryption and
  10030 * digesting operation. */
  10031 CK_RV
  10032 NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession,
  10033                        CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
  10034                        CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
  10035 {
  10036    CK_RV crv;
  10037 
  10038    CHECK_FORK();
  10039 
  10040    crv = NSC_DecryptUpdate(hSession, pEncryptedPart, ulEncryptedPartLen,
  10041                            pPart, pulPartLen);
  10042    if (crv != CKR_OK)
  10043        return crv;
  10044    crv = NSC_DigestUpdate(hSession, pPart, *pulPartLen);
  10045 
  10046    return crv;
  10047 }
  10048 
  10049 /* NSC_SignEncryptUpdate continues a multiple-part signing and
  10050 * encryption operation. */
  10051 CK_RV
  10052 NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
  10053                      CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
  10054                      CK_ULONG_PTR pulEncryptedPartLen)
  10055 {
  10056    CK_RV crv;
  10057 
  10058    CHECK_FORK();
  10059 
  10060    crv = NSC_EncryptUpdate(hSession, pPart, ulPartLen, pEncryptedPart,
  10061                            pulEncryptedPartLen);
  10062    if (crv != CKR_OK)
  10063        return crv;
  10064    crv = NSC_SignUpdate(hSession, pPart, ulPartLen);
  10065 
  10066    return crv;
  10067 }
  10068 
  10069 /* NSC_DecryptVerifyUpdate continues a multiple-part decryption
  10070 * and verify operation. */
  10071 CK_RV
  10072 NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession,
  10073                        CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
  10074                        CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
  10075 {
  10076    CK_RV crv;
  10077 
  10078    CHECK_FORK();
  10079 
  10080    crv = NSC_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen,
  10081                            pData, pulDataLen);
  10082    if (crv != CKR_OK)
  10083        return crv;
  10084    crv = NSC_VerifyUpdate(hSession, pData, *pulDataLen);
  10085 
  10086    return crv;
  10087 }
  10088 
  10089 /* NSC_DigestKey continues a multi-part message-digesting operation,
  10090 * by digesting the value of a secret key as part of the data already digested.
  10091 */
  10092 CK_RV
  10093 NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
  10094 {
  10095    SFTKSession *session = NULL;
  10096    SFTKObject *key = NULL;
  10097    SFTKAttribute *att;
  10098    CK_RV crv;
  10099 
  10100    CHECK_FORK();
  10101 
  10102    session = sftk_SessionFromHandle(hSession);
  10103    if (session == NULL)
  10104        return CKR_SESSION_HANDLE_INVALID;
  10105 
  10106    key = sftk_ObjectFromHandle(hKey, session);
  10107    sftk_FreeSession(session);
  10108    if (key == NULL)
  10109        return CKR_KEY_HANDLE_INVALID;
  10110 
  10111    /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */
  10112 
  10113    /* make sure it's a valid  key for this operation */
  10114    if (key->objclass != CKO_SECRET_KEY) {
  10115        sftk_FreeObject(key);
  10116        return CKR_KEY_TYPE_INCONSISTENT;
  10117    }
  10118    /* get the key value */
  10119    att = sftk_FindAttribute(key, CKA_VALUE);
  10120    sftk_FreeObject(key);
  10121    if (!att) {
  10122        return CKR_KEY_HANDLE_INVALID;
  10123    }
  10124    crv = NSC_DigestUpdate(hSession, (CK_BYTE_PTR)att->attrib.pValue,
  10125                           att->attrib.ulValueLen);
  10126    sftk_FreeAttribute(att);
  10127    return crv;
  10128 }