tor-browser

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

pk11cxt.c (63598B)


      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 PK11Contexts which are  used in multipart hashing,
      6 * encryption/decryption, and signing/verication operations.
      7 */
      8 
      9 #include "seccomon.h"
     10 #include "secmod.h"
     11 #include "nssilock.h"
     12 #include "secmodi.h"
     13 #include "secmodti.h"
     14 #include "pkcs11.h"
     15 #include "pk11func.h"
     16 #include "secitem.h"
     17 #include "secoid.h"
     18 #include "sechash.h"
     19 #include "secerr.h"
     20 #include "blapit.h"
     21 #include "secport.h"
     22 
     23 static const SECItem pk11_null_params = { 0 };
     24 
     25 /**********************************************************************
     26 *
     27 *                   Now Deal with Crypto Contexts
     28 *
     29 **********************************************************************/
     30 
     31 /*
     32 * the monitors...
     33 */
     34 void
     35 PK11_EnterContextMonitor(PK11Context *cx)
     36 {
     37    /* if we own the session and our slot is ThreadSafe, only monitor
     38     * the Context */
     39    if ((cx->ownSession) && (cx->slot->isThreadSafe)) {
     40        /* Should this use monitors instead? */
     41        PZ_Lock(cx->sessionLock);
     42    } else {
     43        PK11_EnterSlotMonitor(cx->slot);
     44    }
     45 }
     46 
     47 void
     48 PK11_ExitContextMonitor(PK11Context *cx)
     49 {
     50    /* if we own the session and our slot is ThreadSafe, only monitor
     51     * the Context */
     52    if ((cx->ownSession) && (cx->slot->isThreadSafe)) {
     53        /* Should this use monitors instead? */
     54        PZ_Unlock(cx->sessionLock);
     55    } else {
     56        PK11_ExitSlotMonitor(cx->slot);
     57    }
     58 }
     59 
     60 /*
     61 * Free up a Cipher Context
     62 */
     63 void
     64 PK11_DestroyContext(PK11Context *context, PRBool freeit)
     65 {
     66    pk11_CloseSession(context->slot, context->session, context->ownSession);
     67    /* initialize the critical fields of the context */
     68    if (context->savedData != NULL)
     69        PORT_Free(context->savedData);
     70    if (context->key)
     71        PK11_FreeSymKey(context->key);
     72    if (context->param && context->param != &pk11_null_params)
     73        SECITEM_FreeItem(context->param, PR_TRUE);
     74    if (context->sessionLock)
     75        PZ_DestroyLock(context->sessionLock);
     76    PK11_FreeSlot(context->slot);
     77    if (freeit)
     78        PORT_Free(context);
     79 }
     80 
     81 /*
     82 * save the current context. Allocate Space if necessary.
     83 */
     84 static unsigned char *
     85 pk11_saveContextHelper(PK11Context *context, unsigned char *buffer,
     86                       unsigned long *savedLength)
     87 {
     88    CK_RV crv;
     89 
     90    /* If buffer is NULL, this will get the length */
     91    crv = PK11_GETTAB(context->slot)->C_GetOperationState(context->session, (CK_BYTE_PTR)buffer, savedLength);
     92    if (!buffer || (crv == CKR_BUFFER_TOO_SMALL)) {
     93        /* the given buffer wasn't big enough (or was NULL), but we
     94         * have the length, so try again with a new buffer and the
     95         * correct length
     96         */
     97        unsigned long bufLen = *savedLength;
     98        buffer = PORT_Alloc(bufLen);
     99        if (buffer == NULL) {
    100            return (unsigned char *)NULL;
    101        }
    102        crv = PK11_GETTAB(context->slot)->C_GetOperationState(context->session, (CK_BYTE_PTR)buffer, savedLength);
    103        if (crv != CKR_OK) {
    104            PORT_ZFree(buffer, bufLen);
    105        }
    106    }
    107    if (crv != CKR_OK) {
    108        PORT_SetError(PK11_MapError(crv));
    109        return (unsigned char *)NULL;
    110    }
    111    return buffer;
    112 }
    113 
    114 void *
    115 pk11_saveContext(PK11Context *context, void *space, unsigned long *savedLength)
    116 {
    117    return pk11_saveContextHelper(context,
    118                                  (unsigned char *)space, savedLength);
    119 }
    120 
    121 /*
    122 * restore the current context
    123 */
    124 SECStatus
    125 pk11_restoreContext(PK11Context *context, void *space, unsigned long savedLength)
    126 {
    127    CK_RV crv;
    128    CK_OBJECT_HANDLE objectID = context->objectID;
    129 
    130    PORT_Assert(space != NULL);
    131    if (space == NULL) {
    132        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
    133        return SECFailure;
    134    }
    135    crv = PK11_GETTAB(context->slot)->C_SetOperationState(context->session, (CK_BYTE_PTR)space, savedLength, objectID, 0);
    136    if (crv != CKR_OK) {
    137        PORT_SetError(PK11_MapError(crv));
    138        return SECFailure;
    139    }
    140    return SECSuccess;
    141 }
    142 
    143 SECStatus pk11_Finalize(PK11Context *context);
    144 
    145 /*
    146 *  Initialize a Message function. Particular function is passed in as a
    147 *  function pointer. Since all C_Message*Init funcitons have the same
    148 *  prototype, we just pick one of the the prototypes to declare our init
    149 *  function.
    150 */
    151 static CK_RV
    152 pk11_contextInitMessage(PK11Context *context, CK_MECHANISM_PTR mech,
    153                        CK_C_MessageEncryptInit initFunc,
    154                        CK_FLAGS flags, CK_RV scrv)
    155 {
    156    PK11SlotInfo *slot = context->slot;
    157    CK_RV crv = CKR_OK;
    158 
    159    context->ivCounter = 0;
    160    context->ivMaxCount = 0;
    161    context->ivFixedBits = 0;
    162    context->ivLen = 0;
    163    context->ivGen = CKG_NO_GENERATE;
    164    context->simulate_mechanism = (mech)->mechanism;
    165    context->simulate_message = PR_FALSE;
    166    /* check that we can do the Message interface. We need to check
    167     * for either 1) are we using a PKCS #11 v3 interface and 2) is the
    168     * Message flag set on the mechanism. If either is false we simulate
    169     * the message interface for the Encrypt and Decrypt cases using the
    170     * PKCS #11 V2 interface.
    171     * Sign and verify do not have V2 interfaces, so we go ahead and fail
    172     * if those cases */
    173    if ((PK11_CheckPKCS11Version(slot, 3, 0, PR_TRUE) >= 0) &&
    174        PK11_DoesMechanismFlag(slot, (mech)->mechanism, flags)) {
    175        PK11_EnterContextMonitor(context);
    176        crv = (*initFunc)((context)->session, (mech), (context)->objectID);
    177        PK11_ExitContextMonitor(context);
    178        if ((crv == CKR_FUNCTION_NOT_SUPPORTED) ||
    179            (crv == CKR_MECHANISM_INVALID)) {
    180            /* we have a 3.0 interface, and the flag was set (or ignored)
    181             * but the implementation was not there, use the V2 interface */
    182            crv = (scrv);
    183            context->simulate_message = PR_TRUE;
    184        }
    185    } else {
    186        crv = (scrv);
    187        context->simulate_message = PR_TRUE;
    188    }
    189    return crv;
    190 }
    191 
    192 /*
    193 * Context initialization. Used by all flavors of CreateContext
    194 */
    195 static SECStatus
    196 pk11_context_init(PK11Context *context, CK_MECHANISM *mech_info,
    197                  const SECItem *sig)
    198 {
    199    CK_RV crv;
    200    SECStatus rv = SECSuccess;
    201 
    202    context->simulate_message = PR_FALSE;
    203    switch (context->operation) {
    204        case CKA_ENCRYPT:
    205            PK11_EnterContextMonitor(context);
    206            crv = PK11_GETTAB(context->slot)->C_EncryptInit(context->session, mech_info, context->objectID);
    207            PK11_ExitContextMonitor(context);
    208            break;
    209        case CKA_DECRYPT:
    210            PK11_EnterContextMonitor(context);
    211            if (context->fortezzaHack) {
    212                CK_ULONG count = 0;
    213                /* generate the IV for fortezza */
    214                crv = PK11_GETTAB(context->slot)->C_EncryptInit(context->session, mech_info, context->objectID);
    215                if (crv != CKR_OK) {
    216                    PK11_ExitContextMonitor(context);
    217                    break;
    218                }
    219                PK11_GETTAB(context->slot)
    220                    ->C_EncryptFinal(context->session,
    221                                     NULL, &count);
    222            }
    223            crv = PK11_GETTAB(context->slot)->C_DecryptInit(context->session, mech_info, context->objectID);
    224            PK11_ExitContextMonitor(context);
    225            break;
    226        case CKA_SIGN:
    227            PK11_EnterContextMonitor(context);
    228            crv = PK11_GETTAB(context->slot)->C_SignInit(context->session, mech_info, context->objectID);
    229            PK11_ExitContextMonitor(context);
    230            break;
    231        case CKA_VERIFY:
    232            /* NOTE: we previously has this set to C_SignInit for Macing.
    233             * It turns out now one could possibly use it that way, though,
    234             * because PK11_HashOp() always called C_VerifyUpdate on CKA_VERIFY,
    235             * which would have failed. So everyone just calls us with CKA_SIGN
    236             * when Macing even when they are verifying, no need to 'do it
    237             * for them'. It needs to be VerifyInit now so that we can do
    238             * PKCS #11 hash/Verify combo operations. */
    239            PK11_EnterContextMonitor(context);
    240            crv = PK11_GETTAB(context->slot)->C_VerifyInit(context->session, mech_info, context->objectID);
    241            PK11_ExitContextMonitor(context);
    242            break;
    243        /* fake attibute to distingush CKA_VERIFY from CKA_VERIFY_SIGNAGURE */
    244        case CKA_NSS_VERIFY_SIGNATURE:
    245            if (!sig || !sig->data) {
    246                PORT_SetError(SEC_ERROR_INVALID_ARGS);
    247                return SECFailure;
    248            }
    249            PK11_EnterContextMonitor(context);
    250            crv = PK11_GETTAB(context->slot)->C_VerifySignatureInit(context->session, mech_info, context->objectID, sig->data, sig->len);
    251            PK11_ExitContextMonitor(context);
    252            break;
    253        case CKA_DIGEST:
    254            PK11_EnterContextMonitor(context);
    255            crv = PK11_GETTAB(context->slot)->C_DigestInit(context->session, mech_info);
    256            PK11_ExitContextMonitor(context);
    257            break;
    258 
    259        case CKA_NSS_MESSAGE | CKA_ENCRYPT:
    260            crv = pk11_contextInitMessage(context, mech_info,
    261                                          PK11_GETTAB(context->slot)->C_MessageEncryptInit,
    262                                          CKF_MESSAGE_ENCRYPT, CKR_OK);
    263            break;
    264        case CKA_NSS_MESSAGE | CKA_DECRYPT:
    265            crv = pk11_contextInitMessage(context, mech_info,
    266                                          PK11_GETTAB(context->slot)->C_MessageDecryptInit,
    267                                          CKF_MESSAGE_DECRYPT, CKR_OK);
    268            break;
    269        case CKA_NSS_MESSAGE | CKA_SIGN:
    270            crv = pk11_contextInitMessage(context, mech_info,
    271                                          PK11_GETTAB(context->slot)->C_MessageSignInit,
    272                                          CKF_MESSAGE_SIGN, CKR_FUNCTION_NOT_SUPPORTED);
    273            break;
    274        case CKA_NSS_MESSAGE | CKA_VERIFY:
    275            crv = pk11_contextInitMessage(context, mech_info,
    276                                          PK11_GETTAB(context->slot)->C_MessageVerifyInit,
    277                                          CKF_MESSAGE_VERIFY, CKR_FUNCTION_NOT_SUPPORTED);
    278            break;
    279        default:
    280            crv = CKR_OPERATION_NOT_INITIALIZED;
    281            break;
    282    }
    283 
    284    if (crv != CKR_OK) {
    285        PORT_SetError(PK11_MapError(crv));
    286        return SECFailure;
    287    }
    288 
    289    /* handle the case where the token is using the old NSS mechanism */
    290    if (context->simulate_message &&
    291        !PK11_DoesMechanism(context->slot, context->simulate_mechanism)) {
    292        if ((context->simulate_mechanism == CKM_CHACHA20_POLY1305) &&
    293            PK11_DoesMechanism(context->slot, CKM_NSS_CHACHA20_POLY1305)) {
    294            context->simulate_mechanism = CKM_NSS_CHACHA20_POLY1305;
    295        } else {
    296            PORT_SetError(PK11_MapError(CKR_MECHANISM_INVALID));
    297            return SECFailure;
    298        }
    299    }
    300 
    301    /*
    302     * handle session starvation case.. use our last session to multiplex
    303     */
    304    if (!context->ownSession) {
    305        PK11_EnterContextMonitor(context);
    306        context->savedData = pk11_saveContext(context, context->savedData,
    307                                              &context->savedLength);
    308        if (context->savedData == NULL)
    309            rv = SECFailure;
    310        /* clear out out session for others to use */
    311        pk11_Finalize(context);
    312        PK11_ExitContextMonitor(context);
    313    }
    314    return rv;
    315 }
    316 
    317 /*
    318 * Testing interfaces, not for general use. This function forces
    319 * an AEAD context into simulation mode even though the target token
    320 * can already do PKCS #11 v3.0 Message (i.e. softoken).
    321 */
    322 SECStatus
    323 _PK11_ContextSetAEADSimulation(PK11Context *context)
    324 {
    325    CK_RV crv;
    326    /* only message encrypt and message decrypt contexts can be simulated */
    327    if ((context->operation != (CKA_NSS_MESSAGE | CKA_ENCRYPT)) &&
    328        (context->operation != (CKA_NSS_MESSAGE | CKA_DECRYPT))) {
    329        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    330        return SECFailure;
    331    }
    332    /* if we are already simulating, return */
    333    if (context->simulate_message) {
    334        return SECSuccess;
    335    }
    336    /* we need to shutdown the existing AEAD operation */
    337    switch (context->operation) {
    338        case CKA_NSS_MESSAGE | CKA_ENCRYPT:
    339            crv = PK11_GETTAB(context->slot)->C_MessageEncryptFinal(context->session);
    340            break;
    341        case CKA_NSS_MESSAGE | CKA_DECRYPT:
    342            crv = PK11_GETTAB(context->slot)->C_MessageDecryptFinal(context->session);
    343            break;
    344        default:
    345            PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
    346            return SECFailure;
    347    }
    348    if (crv != CKR_OK) {
    349        PORT_SetError(PK11_MapError(crv));
    350        return SECFailure;
    351    }
    352    context->simulate_message = PR_TRUE;
    353    return SECSuccess;
    354 }
    355 
    356 PRBool
    357 _PK11_ContextGetAEADSimulation(PK11Context *context)
    358 {
    359    return context->simulate_message;
    360 }
    361 
    362 /*
    363 * Common Helper Function do come up with a new context.
    364 */
    365 static PK11Context *
    366 pk11_CreateNewContextInSlot(CK_MECHANISM_TYPE type,
    367                            PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation,
    368                            PK11SymKey *symKey, CK_OBJECT_HANDLE objectID,
    369                            const SECItem *param, const SECItem *sig,
    370                            void *pwArg)
    371 {
    372    CK_MECHANISM mech_info;
    373    PK11Context *context;
    374    SECStatus rv;
    375 
    376    PORT_Assert(slot != NULL);
    377    if (!slot || ((objectID == CK_INVALID_HANDLE) && ((operation != CKA_DIGEST) ||
    378                                                      (type == CKM_SKIPJACK_CBC64)))) {
    379        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    380        return NULL;
    381    }
    382    context = (PK11Context *)PORT_Alloc(sizeof(PK11Context));
    383    if (context == NULL) {
    384        return NULL;
    385    }
    386 
    387    /* now deal with the fortezza hack... the fortezza hack is an attempt
    388     * to get around the issue of the card not allowing you to do a FORTEZZA
    389     * LoadIV/Encrypt, which was added because such a combination could be
    390     * use to circumvent the key escrow system. Unfortunately SSL needs to
    391     * do this kind of operation, so in SSL we do a loadIV (to verify it),
    392     * Then GenerateIV, and through away the first 8 bytes on either side
    393     * of the connection.*/
    394    context->fortezzaHack = PR_FALSE;
    395    if (type == CKM_SKIPJACK_CBC64) {
    396        if (symKey && (symKey->origin == PK11_OriginFortezzaHack)) {
    397            context->fortezzaHack = PR_TRUE;
    398        }
    399    }
    400 
    401    /* initialize the critical fields of the context */
    402    context->operation = operation;
    403    /* If we were given a symKey, keep our own reference to it so
    404     * that the key doesn't disappear in the middle of the operation
    405     * if the caller frees it. Public and Private keys are not reference
    406     * counted, so the caller just has to keep his copies around until
    407     * the operation completes */
    408    context->key = symKey ? PK11_ReferenceSymKey(symKey) : NULL;
    409    context->objectID = objectID;
    410    context->slot = PK11_ReferenceSlot(slot);
    411    context->session = pk11_GetNewSession(slot, &context->ownSession);
    412    context->pwArg = pwArg;
    413    /* get our session */
    414    context->savedData = NULL;
    415 
    416    /* save the parameters so that some digesting stuff can do multiple
    417     * begins on a single context */
    418    context->type = type;
    419    if (param) {
    420        if (param->len > 0) {
    421            context->param = SECITEM_DupItem(param);
    422        } else {
    423            context->param = (SECItem *)&pk11_null_params;
    424        }
    425    } else {
    426        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    427        context->param = NULL;
    428    }
    429    context->init = PR_FALSE;
    430    context->sessionLock = PZ_NewLock(nssILockPK11cxt);
    431    if ((context->param == NULL) || (context->sessionLock == NULL)) {
    432        PK11_DestroyContext(context, PR_TRUE);
    433        return NULL;
    434    }
    435 
    436    mech_info.mechanism = type;
    437    mech_info.pParameter = param->data;
    438    mech_info.ulParameterLen = param->len;
    439    rv = pk11_context_init(context, &mech_info, sig);
    440 
    441    if (rv != SECSuccess) {
    442        PK11_DestroyContext(context, PR_TRUE);
    443        return NULL;
    444    }
    445    context->init = PR_TRUE;
    446    return context;
    447 }
    448 
    449 /*
    450 * put together the various PK11_Create_Context calls used by different
    451 * parts of libsec.
    452 */
    453 PK11Context *
    454 __PK11_CreateContextByRawKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
    455                             PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key,
    456                             SECItem *param, void *wincx)
    457 {
    458    PK11SymKey *symKey = NULL;
    459    PK11Context *context = NULL;
    460 
    461    /* first get a slot */
    462    if (slot == NULL) {
    463        slot = PK11_GetBestSlot(type, wincx);
    464        if (slot == NULL) {
    465            PORT_SetError(SEC_ERROR_NO_MODULE);
    466            goto loser;
    467        }
    468    } else {
    469        PK11_ReferenceSlot(slot);
    470    }
    471 
    472    /* now import the key */
    473    symKey = PK11_ImportSymKey(slot, type, origin, operation, key, wincx);
    474    if (symKey == NULL)
    475        goto loser;
    476 
    477    context = PK11_CreateContextBySymKey(type, operation, symKey, param);
    478 
    479 loser:
    480    if (symKey) {
    481        PK11_FreeSymKey(symKey);
    482    }
    483    if (slot) {
    484        PK11_FreeSlot(slot);
    485    }
    486 
    487    return context;
    488 }
    489 
    490 PK11Context *
    491 PK11_CreateContextByRawKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
    492                           PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key,
    493                           SECItem *param, void *wincx)
    494 {
    495    return __PK11_CreateContextByRawKey(slot, type, origin, operation,
    496                                        key, param, wincx);
    497 }
    498 
    499 /*
    500 * Create a context from a key. We really should make sure we aren't using
    501 * the same key in multiple sessions!
    502 */
    503 PK11Context *
    504 PK11_CreateContextBySymKey(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation,
    505                           PK11SymKey *symKey, const SECItem *param)
    506 {
    507    PK11SymKey *newKey;
    508    PK11Context *context;
    509 
    510    /* if this slot doesn't support the mechanism, go to a slot that does */
    511    newKey = pk11_ForceSlot(symKey, type, operation);
    512    if (newKey == NULL) {
    513        PK11_ReferenceSymKey(symKey);
    514    } else {
    515        symKey = newKey;
    516    }
    517 
    518    /* Context keeps its reference to the symKey, so it's safe to
    519     * free our reference we we are through, even though we may have
    520     * created the key using pk11_ForceSlot. */
    521    context = pk11_CreateNewContextInSlot(type, symKey->slot, operation, symKey,
    522                                          symKey->objectID, param, NULL,
    523                                          symKey->cx);
    524    PK11_FreeSymKey(symKey);
    525    return context;
    526 }
    527 
    528 /* To support multipart public key operations (like hash/verify operations),
    529 * we need to create contexts with public keys. */
    530 PK11Context *
    531 PK11_CreateSignatureContextByPubKey(CK_MECHANISM_TYPE type,
    532                                    CK_ATTRIBUTE_TYPE operation,
    533                                    SECKEYPublicKey *pubKey, const SECItem *param,
    534                                    const SECItem *sig, void *pwArg)
    535 {
    536    PK11SlotInfo *slot = pubKey->pkcs11Slot;
    537    SECItem nullparam = { 0, 0, 0 };
    538 
    539    /* if this slot doesn't support the mechanism, go to a slot that does */
    540    /* public keys have all their data in the public key data structure,
    541     * so there's no need to export the old key, just  import this one. The
    542     * import manages consistancy of the public key data structure */
    543    if (slot == NULL || !PK11_DoesMechanism(slot, type)) {
    544        CK_OBJECT_HANDLE objectID;
    545        slot = PK11_GetBestSlot(type, NULL);
    546        if (slot == NULL) {
    547            return NULL;
    548        }
    549        objectID = PK11_ImportPublicKey(slot, pubKey, PR_FALSE);
    550        PK11_FreeSlot(slot);
    551        if (objectID == CK_INVALID_HANDLE) {
    552            return NULL;
    553        }
    554    }
    555 
    556    /* unlike symkeys, we accept a NULL parameter. map a null parameter
    557     * to the empty parameter. This matches the semantics of
    558     * PK11_VerifyWithMechanism */
    559    return pk11_CreateNewContextInSlot(type, pubKey->pkcs11Slot, operation,
    560                                       NULL, pubKey->pkcs11ID,
    561                                       param ? param : &nullparam, sig, pwArg);
    562 }
    563 
    564 /* traditional PK11_CreateContextByPubKey just doesn't have the signature.
    565 * This will work unless operation is CKA_NSS_VERIFY_SIGNATURE */
    566 PK11Context *
    567 PK11_CreateContextByPubKey(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation,
    568                           SECKEYPublicKey *pubKey, const SECItem *param,
    569                           void *pwArg)
    570 {
    571    return PK11_CreateSignatureContextByPubKey(type, operation, pubKey, param,
    572                                               NULL, pwArg);
    573 }
    574 
    575 /* To support multipart private key operations (like hash/sign operations),
    576 * we need to create contexts with private keys. */
    577 PK11Context *
    578 PK11_CreateContextByPrivKey(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation,
    579                            SECKEYPrivateKey *privKey, const SECItem *param)
    580 {
    581    SECItem nullparam = { 0, 0, 0 };
    582    /* Private keys are generally not movable. If the token the
    583     * private key lives on can't do the operation, generally we are
    584     * stuck anyway. So no need to try to manipulate the key into
    585     * another token */
    586 
    587    /* if this slot doesn't support the mechanism, go to a slot that does */
    588    /* unlike symkeys, we accept a NULL parameter. map a null parameter
    589     * to the empty parameter. This matches the semantics of
    590     * PK11_SignWithMechanism */
    591    return pk11_CreateNewContextInSlot(type, privKey->pkcs11Slot, operation,
    592                                       NULL, privKey->pkcs11ID,
    593                                       param ? param : &nullparam, NULL,
    594                                       privKey->wincx);
    595 }
    596 
    597 /*
    598 * Digest contexts don't need keys, but the do need to find a slot.
    599 * Macing should use PK11_CreateContextBySymKey.
    600 */
    601 PK11Context *
    602 PK11_CreateDigestContext(SECOidTag hashAlg)
    603 {
    604    /* digesting has to work without authentication to the slot */
    605    CK_MECHANISM_TYPE type;
    606    PK11SlotInfo *slot;
    607    PK11Context *context;
    608    SECItem param;
    609 
    610    type = PK11_AlgtagToMechanism(hashAlg);
    611    slot = PK11_GetBestSlot(type, NULL);
    612    if (slot == NULL) {
    613        PORT_SetError(SEC_ERROR_NO_MODULE);
    614        return NULL;
    615    }
    616 
    617    /* maybe should really be PK11_GenerateNewParam?? */
    618    param.data = NULL;
    619    param.len = 0;
    620    param.type = 0;
    621 
    622    context = pk11_CreateNewContextInSlot(type, slot, CKA_DIGEST, NULL,
    623                                          CK_INVALID_HANDLE, &param, NULL, NULL);
    624    PK11_FreeSlot(slot);
    625    return context;
    626 }
    627 
    628 /*
    629 * create a new context which is the clone of the state of old context.
    630 */
    631 PK11Context *
    632 PK11_CloneContext(PK11Context *old)
    633 {
    634    PK11Context *newcx;
    635    PRBool needFree = PR_FALSE;
    636    SECStatus rv = SECSuccess;
    637    void *data;
    638    unsigned long len;
    639 
    640    newcx = pk11_CreateNewContextInSlot(old->type, old->slot, old->operation,
    641                                        old->key, old->objectID, old->param,
    642                                        NULL, old->pwArg);
    643    if (newcx == NULL)
    644        return NULL;
    645 
    646    /* now clone the save state. First we need to find the save state
    647     * of the old session. If the old context owns it's session,
    648     * the state needs to be saved, otherwise the state is in saveData. */
    649    if (old->ownSession) {
    650        PK11_EnterContextMonitor(old);
    651        data = pk11_saveContext(old, NULL, &len);
    652        PK11_ExitContextMonitor(old);
    653        needFree = PR_TRUE;
    654    } else {
    655        data = old->savedData;
    656        len = old->savedLength;
    657    }
    658 
    659    if (data == NULL) {
    660        PK11_DestroyContext(newcx, PR_TRUE);
    661        return NULL;
    662    }
    663 
    664    /* now copy that state into our new context. Again we have different
    665     * work if the new context owns it's own session. If it does, we
    666     * restore the state gathered above. If it doesn't, we copy the
    667     * saveData pointer... */
    668    if (newcx->ownSession) {
    669        PK11_EnterContextMonitor(newcx);
    670        rv = pk11_restoreContext(newcx, data, len);
    671        PK11_ExitContextMonitor(newcx);
    672    } else {
    673        PORT_Assert(newcx->savedData != NULL);
    674        if ((newcx->savedData == NULL) || (newcx->savedLength < len)) {
    675            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
    676            rv = SECFailure;
    677        } else {
    678            PORT_Memcpy(newcx->savedData, data, len);
    679            newcx->savedLength = len;
    680        }
    681    }
    682 
    683    if (needFree)
    684        PORT_Free(data);
    685 
    686    if (rv != SECSuccess) {
    687        PK11_DestroyContext(newcx, PR_TRUE);
    688        return NULL;
    689    }
    690    return newcx;
    691 }
    692 
    693 /*
    694 * save the current context state into a variable. Required to make FORTEZZA
    695 * work.
    696 */
    697 SECStatus
    698 PK11_SaveContext(PK11Context *cx, unsigned char *save, int *len, int saveLength)
    699 {
    700    unsigned char *data = NULL;
    701    CK_ULONG length = saveLength;
    702 
    703    if (cx->ownSession) {
    704        PK11_EnterContextMonitor(cx);
    705        data = pk11_saveContextHelper(cx, save, &length);
    706        PK11_ExitContextMonitor(cx);
    707        if (data)
    708            *len = length;
    709    } else if ((unsigned)saveLength >= cx->savedLength) {
    710        data = (unsigned char *)cx->savedData;
    711        if (cx->savedData) {
    712            PORT_Memcpy(save, cx->savedData, cx->savedLength);
    713        }
    714        *len = cx->savedLength;
    715    }
    716    if (data != NULL) {
    717        if (cx->ownSession) {
    718            PORT_ZFree(data, length);
    719        }
    720        return SECSuccess;
    721    } else {
    722        return SECFailure;
    723    }
    724 }
    725 
    726 /* same as above, but may allocate the return buffer. */
    727 unsigned char *
    728 PK11_SaveContextAlloc(PK11Context *cx,
    729                      unsigned char *preAllocBuf, unsigned int pabLen,
    730                      unsigned int *stateLen)
    731 {
    732    unsigned char *stateBuf = NULL;
    733    unsigned long length = (unsigned long)pabLen;
    734 
    735    if (cx->ownSession) {
    736        PK11_EnterContextMonitor(cx);
    737        stateBuf = pk11_saveContextHelper(cx, preAllocBuf, &length);
    738        PK11_ExitContextMonitor(cx);
    739        *stateLen = (stateBuf != NULL) ? length : 0;
    740    } else {
    741        if (pabLen < cx->savedLength) {
    742            stateBuf = (unsigned char *)PORT_Alloc(cx->savedLength);
    743            if (!stateBuf) {
    744                return (unsigned char *)NULL;
    745            }
    746        } else {
    747            stateBuf = preAllocBuf;
    748        }
    749        if (cx->savedData) {
    750            PORT_Memcpy(stateBuf, cx->savedData, cx->savedLength);
    751        }
    752        *stateLen = cx->savedLength;
    753    }
    754    return stateBuf;
    755 }
    756 
    757 /*
    758 * restore the context state into a new running context. Also required for
    759 * FORTEZZA .
    760 */
    761 SECStatus
    762 PK11_RestoreContext(PK11Context *cx, unsigned char *save, int len)
    763 {
    764    SECStatus rv = SECSuccess;
    765    if (cx->ownSession) {
    766        PK11_EnterContextMonitor(cx);
    767        pk11_Finalize(cx);
    768        rv = pk11_restoreContext(cx, save, len);
    769        PK11_ExitContextMonitor(cx);
    770    } else {
    771        PORT_Assert(cx->savedData != NULL);
    772        if ((cx->savedData == NULL) || (cx->savedLength < (unsigned)len)) {
    773            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
    774            rv = SECFailure;
    775        } else {
    776            PORT_Memcpy(cx->savedData, save, len);
    777            cx->savedLength = len;
    778        }
    779    }
    780    return rv;
    781 }
    782 
    783 /*
    784 * This is  to get FIPS compliance until we can convert
    785 * libjar to use PK11_ hashing functions. It returns PR_FALSE
    786 * if we can't get a PK11 Context.
    787 */
    788 PRBool
    789 PK11_HashOK(SECOidTag algID)
    790 {
    791    PK11Context *cx;
    792 
    793    cx = PK11_CreateDigestContext(algID);
    794    if (cx == NULL)
    795        return PR_FALSE;
    796    PK11_DestroyContext(cx, PR_TRUE);
    797    return PR_TRUE;
    798 }
    799 
    800 /*
    801 * start a new digesting or Mac'ing operation on this context
    802 */
    803 SECStatus
    804 PK11_DigestBegin(PK11Context *cx)
    805 {
    806    CK_MECHANISM mech_info;
    807    SECStatus rv;
    808 
    809    if (cx->init == PR_TRUE) {
    810        return SECSuccess;
    811    }
    812 
    813    /*
    814     * make sure the old context is clear first
    815     */
    816    PK11_EnterContextMonitor(cx);
    817    pk11_Finalize(cx);
    818    PK11_ExitContextMonitor(cx);
    819 
    820    mech_info.mechanism = cx->type;
    821    mech_info.pParameter = cx->param->data;
    822    mech_info.ulParameterLen = cx->param->len;
    823    rv = pk11_context_init(cx, &mech_info, NULL);
    824 
    825    if (rv != SECSuccess) {
    826        return SECFailure;
    827    }
    828    cx->init = PR_TRUE;
    829    return SECSuccess;
    830 }
    831 
    832 SECStatus
    833 PK11_HashBuf(SECOidTag hashAlg, unsigned char *out, const unsigned char *in,
    834             PRInt32 len)
    835 {
    836    PK11Context *context;
    837    unsigned int max_length;
    838    unsigned int out_length;
    839    SECStatus rv;
    840 
    841    /* len will be passed to PK11_DigestOp as unsigned. */
    842    if (len < 0) {
    843        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    844        return SECFailure;
    845    }
    846 
    847    context = PK11_CreateDigestContext(hashAlg);
    848    if (context == NULL)
    849        return SECFailure;
    850 
    851    rv = PK11_DigestBegin(context);
    852    if (rv != SECSuccess) {
    853        PK11_DestroyContext(context, PR_TRUE);
    854        return rv;
    855    }
    856 
    857    rv = PK11_DigestOp(context, in, len);
    858    if (rv != SECSuccess) {
    859        PK11_DestroyContext(context, PR_TRUE);
    860        return rv;
    861    }
    862 
    863    /* XXX This really should have been an argument to this function! */
    864    max_length = HASH_ResultLenByOidTag(hashAlg);
    865    PORT_Assert(max_length);
    866    if (!max_length)
    867        max_length = HASH_LENGTH_MAX;
    868 
    869    rv = PK11_DigestFinal(context, out, &out_length, max_length);
    870    PK11_DestroyContext(context, PR_TRUE);
    871    return rv;
    872 }
    873 
    874 /*
    875 * execute a bulk encryption operation
    876 */
    877 SECStatus
    878 PK11_CipherOp(PK11Context *context, unsigned char *out, int *outlen,
    879              int maxout, const unsigned char *in, int inlen)
    880 {
    881    CK_RV crv = CKR_OK;
    882    CK_ULONG length = maxout;
    883    CK_ULONG offset = 0;
    884    SECStatus rv = SECSuccess;
    885    unsigned char *saveOut = out;
    886    unsigned char *allocOut = NULL;
    887 
    888    /* if we ran out of session, we need to restore our previously stored
    889     * state.
    890     */
    891    PK11_EnterContextMonitor(context);
    892    if (!context->ownSession) {
    893        rv = pk11_restoreContext(context, context->savedData,
    894                                 context->savedLength);
    895        if (rv != SECSuccess) {
    896            PK11_ExitContextMonitor(context);
    897            return rv;
    898        }
    899    }
    900 
    901    /*
    902     * The fortezza hack is to send 8 extra bytes on the first encrypted and
    903     * lose them on the first decrypt.
    904     */
    905    if (context->fortezzaHack) {
    906        unsigned char random[8];
    907        if (context->operation == CKA_ENCRYPT) {
    908            PK11_ExitContextMonitor(context);
    909            rv = PK11_GenerateRandom(random, sizeof(random));
    910            PK11_EnterContextMonitor(context);
    911 
    912            /* since we are offseting the output, we can't encrypt back into
    913             * the same buffer... allocate a temporary buffer just for this
    914             * call. */
    915            allocOut = out = (unsigned char *)PORT_Alloc(maxout);
    916            if (out == NULL) {
    917                PK11_ExitContextMonitor(context);
    918                return SECFailure;
    919            }
    920            crv = PK11_GETTAB(context->slot)->C_EncryptUpdate(context->session, random, sizeof(random), out, &length);
    921 
    922            out += length;
    923            maxout -= length;
    924            offset = length;
    925        } else if (context->operation == CKA_DECRYPT) {
    926            length = sizeof(random);
    927            crv = PK11_GETTAB(context->slot)->C_DecryptUpdate(context->session, (CK_BYTE_PTR)in, sizeof(random), random, &length);
    928            inlen -= length;
    929            in += length;
    930            context->fortezzaHack = PR_FALSE;
    931        }
    932    }
    933 
    934    switch (context->operation) {
    935        case CKA_ENCRYPT:
    936            length = maxout;
    937            crv = PK11_GETTAB(context->slot)->C_EncryptUpdate(context->session, (CK_BYTE_PTR)in, inlen, out, &length);
    938            length += offset;
    939            break;
    940        case CKA_DECRYPT:
    941            length = maxout;
    942            crv = PK11_GETTAB(context->slot)->C_DecryptUpdate(context->session, (CK_BYTE_PTR)in, inlen, out, &length);
    943            break;
    944        default:
    945            crv = CKR_OPERATION_NOT_INITIALIZED;
    946            break;
    947    }
    948 
    949    if (crv != CKR_OK) {
    950        PORT_SetError(PK11_MapError(crv));
    951        *outlen = 0;
    952        rv = SECFailure;
    953    } else {
    954        *outlen = length;
    955    }
    956 
    957    if (context->fortezzaHack) {
    958        if (context->operation == CKA_ENCRYPT) {
    959            PORT_Assert(allocOut);
    960            PORT_Memcpy(saveOut, allocOut, length);
    961            PORT_Free(allocOut);
    962        }
    963        context->fortezzaHack = PR_FALSE;
    964    }
    965 
    966    /*
    967     * handle session starvation case.. use our last session to multiplex
    968     */
    969    if (!context->ownSession) {
    970        context->savedData = pk11_saveContext(context, context->savedData,
    971                                              &context->savedLength);
    972        if (context->savedData == NULL)
    973            rv = SECFailure;
    974 
    975        /* clear out out session for others to use */
    976        pk11_Finalize(context);
    977    }
    978    PK11_ExitContextMonitor(context);
    979    return rv;
    980 }
    981 
    982 /*
    983 * Simulate the IV generation that normally would happen in the token.
    984 *
    985 * This is a modifed copy of what is in freebl/gcm.c. We can't use the
    986 * version in freebl because of layering, since freebl is inside the token
    987 * boundary. These issues are traditionally handled by moving them to util,
    988 * but we also have two different Random functions we have two switch between.
    989 * Since this is primarily here for tokens that don't support the PKCS #11
    990 * Message Interface, it's OK if they diverge a bit. Slight semantic
    991 * differences from the freebl/gcm.c version shouldn't be much more than the
    992 * sematic differences between freebl and other tokens which do implement the
    993 * Message Interface. */
    994 static SECStatus
    995 pk11_GenerateIV(PK11Context *context, CK_GENERATOR_FUNCTION ivgen,
    996                int fixedBits, unsigned char *iv, int ivLen)
    997 {
    998    unsigned int i;
    999    unsigned int flexBits;
   1000    unsigned int ivOffset;
   1001    unsigned int ivNewCount;
   1002    unsigned char ivMask;
   1003    unsigned char ivSave;
   1004    SECStatus rv;
   1005 
   1006    if (context->ivCounter != 0) {
   1007        /* If we've already generated a message, make sure all subsequent
   1008         * messages are using the same generator */
   1009        if ((context->ivGen != ivgen) ||
   1010            (context->ivFixedBits != fixedBits) ||
   1011            (context->ivLen != ivLen)) {
   1012            PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1013            return SECFailure;
   1014        }
   1015    } else {
   1016        /* remember these values */
   1017        context->ivGen = ivgen;
   1018        context->ivFixedBits = fixedBits;
   1019        context->ivLen = ivLen;
   1020        /* now calculate how may bits of IV we have to supply */
   1021        flexBits = ivLen * PR_BITS_PER_BYTE;
   1022        /* first make sure we aren't going to overflow */
   1023        if (flexBits < fixedBits) {
   1024            PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1025            return SECFailure;
   1026        }
   1027        flexBits -= fixedBits;
   1028        /* if we are generating a random number reduce the acceptable bits to
   1029         * avoid birthday attacks */
   1030        if (ivgen == CKG_GENERATE_RANDOM) {
   1031            if (flexBits <= GCMIV_RANDOM_BIRTHDAY_BITS) {
   1032                PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1033                return SECFailure;
   1034            }
   1035            /* see freebl/blapit.h for how GCMIV_RANDOM_BIRTHDAY_BITS is
   1036             * calculated. */
   1037            flexBits -= GCMIV_RANDOM_BIRTHDAY_BITS;
   1038            flexBits = flexBits >> 1;
   1039        }
   1040        if (flexBits == 0) {
   1041            PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1042            return SECFailure;
   1043        }
   1044        /* Turn those bits into the number of IV's we can safely return */
   1045        if (flexBits >= sizeof(context->ivMaxCount) * PR_BITS_PER_BYTE) {
   1046            context->ivMaxCount = PR_UINT64(0xffffffffffffffff);
   1047        } else {
   1048            context->ivMaxCount = (PR_UINT64(1) << flexBits);
   1049        }
   1050    }
   1051 
   1052    /* no generate, accept the IV from the source */
   1053    if (ivgen == CKG_NO_GENERATE) {
   1054        context->ivCounter = 1;
   1055        return SECSuccess;
   1056    }
   1057 
   1058    /* make sure we haven't exceeded the number of IVs we can return
   1059     * for this key, generator, and IV size */
   1060    if (context->ivCounter >= context->ivMaxCount) {
   1061        /* use a unique error from just bad user input */
   1062        PORT_SetError(SEC_ERROR_EXTRA_INPUT);
   1063        return SECFailure;
   1064    }
   1065 
   1066    /* build to mask to handle the first byte of the IV */
   1067    ivOffset = fixedBits / PR_BITS_PER_BYTE;
   1068    ivMask = 0xff >> ((PR_BITS_PER_BYTE - (fixedBits & 7)) & 7);
   1069    ivNewCount = ivLen - ivOffset;
   1070 
   1071    /* finally generate the IV */
   1072    switch (ivgen) {
   1073        case CKG_GENERATE: /* default to counter */
   1074        case CKG_GENERATE_COUNTER:
   1075            iv[ivOffset] = (iv[ivOffset] & ~ivMask) |
   1076                           (PORT_GET_BYTE_BE(context->ivCounter, 0, ivNewCount) & ivMask);
   1077            for (i = 1; i < ivNewCount; i++) {
   1078                iv[ivOffset + i] =
   1079                    PORT_GET_BYTE_BE(context->ivCounter, i, ivNewCount);
   1080            }
   1081            break;
   1082        case CKG_GENERATE_COUNTER_XOR:
   1083            iv[ivOffset] ^=
   1084                (PORT_GET_BYTE_BE(context->ivCounter, 0, ivNewCount) & ivMask);
   1085            for (i = 1; i < ivNewCount; i++) {
   1086                iv[ivOffset + i] ^=
   1087                    PORT_GET_BYTE_BE(context->ivCounter, i, ivNewCount);
   1088            }
   1089            break;
   1090        case CKG_GENERATE_RANDOM:
   1091            ivSave = iv[ivOffset] & ~ivMask;
   1092            rv = PK11_GenerateRandom(iv + ivOffset, ivNewCount);
   1093            iv[ivOffset] = ivSave | (iv[ivOffset] & ivMask);
   1094            if (rv != SECSuccess) {
   1095                return rv;
   1096            }
   1097            break;
   1098    }
   1099    context->ivCounter++;
   1100    return SECSuccess;
   1101 }
   1102 
   1103 /*
   1104 * PKCS #11 v2.40 did not have a message interface. If our module can't
   1105 * do the message interface use the old method of doing AEAD */
   1106 static SECStatus
   1107 pk11_AEADSimulateOp(PK11Context *context, void *params, int paramslen,
   1108                    const unsigned char *aad, int aadlen,
   1109                    unsigned char *out, int *outlen,
   1110                    int maxout, const unsigned char *in, int inlen)
   1111 {
   1112    unsigned int length = maxout;
   1113    SECStatus rv = SECSuccess;
   1114    unsigned char *saveOut = out;
   1115    unsigned char *allocOut = NULL;
   1116 
   1117    /*
   1118     * first we need to convert the single shot (v2.40) parameters into
   1119     * the message version of the parameters. This usually involves
   1120     * copying the Nonce or IV, setting the AAD from our parameter list
   1121     * and handling the tag differences */
   1122    CK_GCM_PARAMS_V3 gcm;
   1123    CK_GCM_MESSAGE_PARAMS *gcm_message;
   1124    CK_CCM_PARAMS ccm;
   1125    CK_CCM_MESSAGE_PARAMS *ccm_message;
   1126    CK_SALSA20_CHACHA20_POLY1305_PARAMS chacha_poly;
   1127    CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS *chacha_poly_message;
   1128    CK_NSS_AEAD_PARAMS nss_chacha_poly;
   1129    CK_MECHANISM_TYPE mechanism = context->simulate_mechanism;
   1130    SECItem sim_params = { 0, NULL, 0 };
   1131    unsigned char *tag = NULL;
   1132    unsigned int taglen;
   1133    PRBool encrypt;
   1134 
   1135    *outlen = 0;
   1136    /* figure out if we are encrypting or decrypting, as tags are
   1137     * handled differently in both */
   1138    switch (context->operation) {
   1139        case CKA_NSS_MESSAGE | CKA_ENCRYPT:
   1140            encrypt = PR_TRUE;
   1141            break;
   1142        case CKA_NSS_MESSAGE | CKA_DECRYPT:
   1143            encrypt = PR_FALSE;
   1144            break;
   1145        default:
   1146            PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1147            return SECFailure;
   1148    }
   1149 
   1150    switch (mechanism) {
   1151        case CKM_CHACHA20_POLY1305:
   1152        case CKM_SALSA20_POLY1305:
   1153            if (paramslen != sizeof(CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS)) {
   1154                PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1155                return SECFailure;
   1156            }
   1157            chacha_poly_message =
   1158                (CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS *)params;
   1159            chacha_poly.pNonce = chacha_poly_message->pNonce;
   1160            chacha_poly.ulNonceLen = chacha_poly_message->ulNonceLen;
   1161            chacha_poly.pAAD = (CK_BYTE_PTR)aad;
   1162            chacha_poly.ulAADLen = aadlen;
   1163            tag = chacha_poly_message->pTag;
   1164            taglen = 16;
   1165            sim_params.data = (unsigned char *)&chacha_poly;
   1166            sim_params.len = sizeof(chacha_poly);
   1167            /* SALSA20_POLY1305 and CHACHA20_POLY1305 do not generate the iv
   1168             * internally, don't simulate it either */
   1169            break;
   1170        case CKM_NSS_CHACHA20_POLY1305:
   1171            if (paramslen != sizeof(CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS)) {
   1172                PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1173                return SECFailure;
   1174            }
   1175            chacha_poly_message =
   1176                (CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS *)params;
   1177            tag = chacha_poly_message->pTag;
   1178            taglen = 16;
   1179            nss_chacha_poly.pNonce = chacha_poly_message->pNonce;
   1180            nss_chacha_poly.ulNonceLen = chacha_poly_message->ulNonceLen;
   1181            nss_chacha_poly.pAAD = (CK_BYTE_PTR)aad;
   1182            nss_chacha_poly.ulAADLen = aadlen;
   1183            nss_chacha_poly.ulTagLen = taglen;
   1184            sim_params.data = (unsigned char *)&nss_chacha_poly;
   1185            sim_params.len = sizeof(nss_chacha_poly);
   1186            /* CKM_NSS_CHACHA20_POLY1305 does not generate the iv
   1187             * internally, don't simulate it either */
   1188            break;
   1189        case CKM_AES_CCM:
   1190            if (paramslen != sizeof(CK_CCM_MESSAGE_PARAMS)) {
   1191                PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1192                return SECFailure;
   1193            }
   1194            ccm_message = (CK_CCM_MESSAGE_PARAMS *)params;
   1195            ccm.ulDataLen = ccm_message->ulDataLen;
   1196            ccm.pNonce = ccm_message->pNonce;
   1197            ccm.ulNonceLen = ccm_message->ulNonceLen;
   1198            ccm.pAAD = (CK_BYTE_PTR)aad;
   1199            ccm.ulAADLen = aadlen;
   1200            ccm.ulMACLen = ccm_message->ulMACLen;
   1201            tag = ccm_message->pMAC;
   1202            taglen = ccm_message->ulMACLen;
   1203            sim_params.data = (unsigned char *)&ccm;
   1204            sim_params.len = sizeof(ccm);
   1205            if (encrypt) {
   1206                /* simulate generating the IV */
   1207                rv = pk11_GenerateIV(context, ccm_message->nonceGenerator,
   1208                                     ccm_message->ulNonceFixedBits,
   1209                                     ccm_message->pNonce,
   1210                                     ccm_message->ulNonceLen);
   1211                if (rv != SECSuccess) {
   1212                    return rv;
   1213                }
   1214            }
   1215            break;
   1216        case CKM_AES_GCM:
   1217            if (paramslen != sizeof(CK_GCM_MESSAGE_PARAMS)) {
   1218                PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1219                return SECFailure;
   1220            }
   1221            gcm_message = (CK_GCM_MESSAGE_PARAMS *)params;
   1222            gcm.pIv = gcm_message->pIv;
   1223            gcm.ulIvLen = gcm_message->ulIvLen;
   1224            gcm.ulIvBits = gcm.ulIvLen * PR_BITS_PER_BYTE;
   1225            gcm.pAAD = (CK_BYTE_PTR)aad;
   1226            gcm.ulAADLen = aadlen;
   1227            gcm.ulTagBits = gcm_message->ulTagBits;
   1228            tag = gcm_message->pTag;
   1229            taglen = (gcm_message->ulTagBits + (PR_BITS_PER_BYTE - 1)) / PR_BITS_PER_BYTE;
   1230            sim_params.data = (unsigned char *)&gcm;
   1231            sim_params.len = sizeof(gcm);
   1232            if (encrypt) {
   1233                /* simulate generating the IV */
   1234                rv = pk11_GenerateIV(context, gcm_message->ivGenerator,
   1235                                     gcm_message->ulIvFixedBits,
   1236                                     gcm_message->pIv, gcm_message->ulIvLen);
   1237                if (rv != SECSuccess) {
   1238                    return rv;
   1239                }
   1240            }
   1241            break;
   1242        default:
   1243            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
   1244            return SECFailure;
   1245    }
   1246    /* now handle the tag. The message interface separates the tag from
   1247     * the data, while the single shot gets and puts the tag at the end of
   1248     * the encrypted data. */
   1249    if (!encrypt) {
   1250        /* In the decrypt case, if the tag is already at the end of the
   1251         * input buffer we are golden, otherwise we'll need a new input
   1252         * buffer and copy the tag at the end of it */
   1253        if (tag != in + inlen) {
   1254            allocOut = PORT_Alloc(inlen + taglen);
   1255            if (allocOut == NULL) {
   1256                return SECFailure;
   1257            }
   1258            PORT_Memcpy(allocOut, in, inlen);
   1259            PORT_Memcpy(allocOut + inlen, tag, taglen);
   1260            in = allocOut;
   1261        }
   1262        inlen = inlen + taglen;
   1263    } else {
   1264        /* if we end up allocating, we don't want to overrun this buffer,
   1265         * so we fail early here */
   1266        if (maxout < inlen) {
   1267            PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1268            return SECFailure;
   1269        }
   1270        /* in the encrypt case, we are fine if maxout is big enough to hold
   1271         * the tag. We'll copy the tag after the operation */
   1272        if (maxout < inlen + taglen) {
   1273            allocOut = PORT_Alloc(inlen + taglen);
   1274            if (allocOut == NULL) {
   1275                return SECFailure;
   1276            }
   1277            out = allocOut;
   1278            length = maxout = inlen + taglen;
   1279        }
   1280    }
   1281    /* now do the operation */
   1282    if (encrypt) {
   1283        rv = PK11_Encrypt(context->key, mechanism, &sim_params, out, &length,
   1284                          maxout, in, inlen);
   1285    } else {
   1286        rv = PK11_Decrypt(context->key, mechanism, &sim_params, out, &length,
   1287                          maxout, in, inlen);
   1288    }
   1289    if (rv != SECSuccess) {
   1290        /* If the mechanism was CKM_AES_GCM, the module may have been
   1291         * following the same error as old versions of NSS. Retry with
   1292         * the CK_NSS_GCM_PARAMS */
   1293        if ((mechanism == CKM_AES_GCM) &&
   1294            (PORT_GetError() == SEC_ERROR_BAD_DATA)) {
   1295            CK_NSS_GCM_PARAMS gcm_nss;
   1296            gcm_message = (CK_GCM_MESSAGE_PARAMS *)params;
   1297            gcm_nss.pIv = gcm_message->pIv;
   1298            gcm_nss.ulIvLen = gcm_message->ulIvLen;
   1299            gcm_nss.pAAD = (CK_BYTE_PTR)aad;
   1300            gcm_nss.ulAADLen = aadlen;
   1301            gcm_nss.ulTagBits = gcm_message->ulTagBits;
   1302            sim_params.data = (unsigned char *)&gcm_nss;
   1303            sim_params.len = sizeof(gcm_nss);
   1304            if (encrypt) {
   1305                rv = PK11_Encrypt(context->key, mechanism, &sim_params, out,
   1306                                  &length, maxout, in, inlen);
   1307            } else {
   1308                rv = PK11_Decrypt(context->key, mechanism, &sim_params, out,
   1309                                  &length, maxout, in, inlen);
   1310            }
   1311            if (rv != SECSuccess) {
   1312                goto fail;
   1313            }
   1314        } else {
   1315            goto fail;
   1316        }
   1317    }
   1318 
   1319    /* on encrypt, separate the output buffer from the tag */
   1320    if (encrypt) {
   1321        if ((length < taglen) || (length > inlen + taglen)) {
   1322            /* PKCS #11 module should not return a length smaller than
   1323             * taglen, or bigger than inlen+taglen */
   1324            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1325            rv = SECFailure;
   1326            goto fail;
   1327        }
   1328        length = length - taglen;
   1329        if (allocOut) {
   1330            /*
   1331             * If we used a temporary buffer, copy it out to the original
   1332             * buffer.
   1333             */
   1334            PORT_Memcpy(saveOut, allocOut, length);
   1335        }
   1336        /* if the tag isn't in the right place, copy it out */
   1337        if (tag != out + length) {
   1338            PORT_Memcpy(tag, out + length, taglen);
   1339        }
   1340    }
   1341    *outlen = length;
   1342    rv = SECSuccess;
   1343 fail:
   1344    if (allocOut) {
   1345        PORT_Free(allocOut);
   1346    }
   1347    return rv;
   1348 }
   1349 
   1350 /*
   1351 * Do an AEAD operation. This function optionally returns
   1352 * and IV on Encrypt for all mechanism. NSS knows which mechanisms
   1353 * generate IV's in the token and which don't. This allows the
   1354 * applications to make a single call without special handling for
   1355 * each AEAD mechanism (the special handling is all contained here.
   1356 */
   1357 SECStatus
   1358 PK11_AEADOp(PK11Context *context, CK_GENERATOR_FUNCTION ivgen,
   1359            int fixedbits, unsigned char *iv, int ivlen,
   1360            const unsigned char *aad, int aadlen,
   1361            unsigned char *out, int *outlen,
   1362            int maxout, unsigned char *tag, int taglen,
   1363            const unsigned char *in, int inlen)
   1364 {
   1365    CK_GCM_MESSAGE_PARAMS gcm_message;
   1366    CK_CCM_MESSAGE_PARAMS ccm_message;
   1367    CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS chacha_poly_message;
   1368    void *params;
   1369    int paramslen;
   1370    SECStatus rv;
   1371 
   1372    switch (context->simulate_mechanism) {
   1373        case CKM_CHACHA20_POLY1305:
   1374        case CKM_SALSA20_POLY1305:
   1375        case CKM_NSS_CHACHA20_POLY1305:
   1376            chacha_poly_message.pNonce = iv;
   1377            chacha_poly_message.ulNonceLen = ivlen;
   1378            chacha_poly_message.pTag = tag;
   1379            params = &chacha_poly_message;
   1380            paramslen = sizeof(CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS);
   1381            /* SALSA20_POLY1305 and CHACHA20_POLY1305 do not generate the iv
   1382             * internally, Do it here. */
   1383            if (context->operation == (CKA_NSS_MESSAGE | CKA_ENCRYPT)) {
   1384                /* simulate generating the IV */
   1385                rv = pk11_GenerateIV(context, ivgen, fixedbits, iv, ivlen);
   1386                if (rv != SECSuccess) {
   1387                    return rv;
   1388                }
   1389            }
   1390            break;
   1391        case CKM_AES_GCM:
   1392            gcm_message.pIv = iv;
   1393            gcm_message.ulIvLen = ivlen;
   1394            gcm_message.ivGenerator = ivgen;
   1395            gcm_message.ulIvFixedBits = fixedbits;
   1396            gcm_message.pTag = tag;
   1397            gcm_message.ulTagBits = taglen * 8;
   1398            params = &gcm_message;
   1399            paramslen = sizeof(CK_GCM_MESSAGE_PARAMS);
   1400            /* GCM generates IV internally */
   1401            break;
   1402        case CKM_AES_CCM:
   1403            ccm_message.ulDataLen = inlen;
   1404            ccm_message.pNonce = iv;
   1405            ccm_message.ulNonceLen = ivlen;
   1406            ccm_message.nonceGenerator = ivgen;
   1407            ccm_message.ulNonceFixedBits = fixedbits;
   1408            ccm_message.pMAC = tag;
   1409            ccm_message.ulMACLen = taglen;
   1410            params = &ccm_message;
   1411            paramslen = sizeof(CK_GCM_MESSAGE_PARAMS);
   1412            /* CCM generates IV internally */
   1413            break;
   1414 
   1415        default:
   1416            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
   1417            return SECFailure;
   1418    }
   1419    return PK11_AEADRawOp(context, params, paramslen, aad, aadlen, out, outlen,
   1420                          maxout, in, inlen);
   1421 }
   1422 
   1423 /* Do and AED operation. The application builds the params on it's own
   1424 * and passes them in. This allows applications direct access to the params
   1425 * so they can use mechanisms not yet understood by, NSS, or get semantics
   1426 * not suppied by PK11_AEAD. */
   1427 SECStatus
   1428 PK11_AEADRawOp(PK11Context *context, void *params, int paramslen,
   1429               const unsigned char *aad, int aadlen,
   1430               unsigned char *out, int *outlen,
   1431               int maxout, const unsigned char *in, int inlen)
   1432 {
   1433    CK_RV crv = CKR_OK;
   1434    CK_ULONG length = maxout;
   1435    SECStatus rv = SECSuccess;
   1436 
   1437    PORT_Assert(outlen != NULL);
   1438    *outlen = 0;
   1439    if (((context->operation) & CKA_NSS_MESSAGE_MASK) != CKA_NSS_MESSAGE) {
   1440        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1441        return SECFailure;
   1442    }
   1443 
   1444    /*
   1445     * The PKCS 11 module does not support the message interface, fall
   1446     * back to using single shot operation */
   1447    if (context->simulate_message) {
   1448        return pk11_AEADSimulateOp(context, params, paramslen, aad, aadlen,
   1449                                   out, outlen, maxout, in, inlen);
   1450    }
   1451 
   1452    /* if we ran out of session, we need to restore our previously stored
   1453     * state.
   1454     */
   1455    PK11_EnterContextMonitor(context);
   1456    if (!context->ownSession) {
   1457        rv = pk11_restoreContext(context, context->savedData,
   1458                                 context->savedLength);
   1459        if (rv != SECSuccess) {
   1460            PK11_ExitContextMonitor(context);
   1461            return rv;
   1462        }
   1463    }
   1464 
   1465    switch (context->operation) {
   1466        case CKA_NSS_MESSAGE | CKA_ENCRYPT:
   1467            length = maxout;
   1468            crv = PK11_GETTAB(context->slot)->C_EncryptMessage(context->session, params, paramslen, (CK_BYTE_PTR)aad, aadlen, (CK_BYTE_PTR)in, inlen, out, &length);
   1469            break;
   1470        case CKA_NSS_MESSAGE | CKA_DECRYPT:
   1471            length = maxout;
   1472            crv = PK11_GETTAB(context->slot)->C_DecryptMessage(context->session, params, paramslen, (CK_BYTE_PTR)aad, aadlen, (CK_BYTE_PTR)in, inlen, out, &length);
   1473            break;
   1474        case CKA_NSS_MESSAGE | CKA_SIGN:
   1475            length = maxout;
   1476            crv = PK11_GETTAB(context->slot)->C_SignMessage(context->session, params, paramslen, (CK_BYTE_PTR)in, inlen, out, &length);
   1477            break;
   1478        case CKA_NSS_MESSAGE | CKA_VERIFY:
   1479            length = maxout; /* sig length */
   1480            crv = PK11_GETTAB(context->slot)->C_VerifyMessage(context->session, params, paramslen, (CK_BYTE_PTR)in, inlen, out /* sig */, length);
   1481            break;
   1482        default:
   1483            crv = CKR_OPERATION_NOT_INITIALIZED;
   1484            break;
   1485    }
   1486 
   1487    if (crv != CKR_OK) {
   1488        PORT_SetError(PK11_MapError(crv));
   1489        rv = SECFailure;
   1490    } else {
   1491        *outlen = length;
   1492    }
   1493 
   1494    /*
   1495     * handle session starvation case.. use our last session to multiplex
   1496     */
   1497    if (!context->ownSession) {
   1498        context->savedData = pk11_saveContext(context, context->savedData,
   1499                                              &context->savedLength);
   1500        if (context->savedData == NULL)
   1501            rv = SECFailure;
   1502 
   1503        /* clear out out session for others to use */
   1504        pk11_Finalize(context);
   1505    }
   1506    PK11_ExitContextMonitor(context);
   1507    return rv;
   1508 }
   1509 
   1510 /*
   1511 * execute a digest/signature operation
   1512 */
   1513 SECStatus
   1514 PK11_DigestOp(PK11Context *context, const unsigned char *in, unsigned inLen)
   1515 {
   1516    CK_RV crv = CKR_OK;
   1517    SECStatus rv = SECSuccess;
   1518 
   1519    if (inLen == 0) {
   1520        return SECSuccess;
   1521    }
   1522    if (!in) {
   1523        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1524        return SECFailure;
   1525    }
   1526 
   1527    /* if we ran out of session, we need to restore our previously stored
   1528     * state.
   1529     */
   1530    context->init = PR_FALSE;
   1531    PK11_EnterContextMonitor(context);
   1532    if (!context->ownSession) {
   1533        rv = pk11_restoreContext(context, context->savedData,
   1534                                 context->savedLength);
   1535        if (rv != SECSuccess) {
   1536            PK11_ExitContextMonitor(context);
   1537            return rv;
   1538        }
   1539    }
   1540 
   1541    switch (context->operation) {
   1542        /* also for MAC'ing */
   1543        case CKA_SIGN:
   1544            crv = PK11_GETTAB(context->slot)->C_SignUpdate(context->session, (unsigned char *)in, inLen);
   1545            break;
   1546        case CKA_VERIFY:
   1547            crv = PK11_GETTAB(context->slot)->C_VerifyUpdate(context->session, (unsigned char *)in, inLen);
   1548            break;
   1549        case CKA_NSS_VERIFY_SIGNATURE:
   1550            crv = PK11_GETTAB(context->slot)->C_VerifySignatureUpdate(context->session, (unsigned char *)in, inLen);
   1551            break;
   1552        case CKA_DIGEST:
   1553            crv = PK11_GETTAB(context->slot)->C_DigestUpdate(context->session, (unsigned char *)in, inLen);
   1554            break;
   1555        default:
   1556            crv = CKR_OPERATION_NOT_INITIALIZED;
   1557            break;
   1558    }
   1559 
   1560    if (crv != CKR_OK) {
   1561        PORT_SetError(PK11_MapError(crv));
   1562        rv = SECFailure;
   1563    }
   1564 
   1565    /*
   1566     * handle session starvation case.. use our last session to multiplex
   1567     */
   1568    if (!context->ownSession) {
   1569        context->savedData = pk11_saveContext(context, context->savedData,
   1570                                              &context->savedLength);
   1571        if (context->savedData == NULL)
   1572            rv = SECFailure;
   1573 
   1574        /* clear out out session for others to use */
   1575        pk11_Finalize(context);
   1576    }
   1577    PK11_ExitContextMonitor(context);
   1578    return rv;
   1579 }
   1580 
   1581 /*
   1582 * Digest a key if possible./
   1583 */
   1584 SECStatus
   1585 PK11_DigestKey(PK11Context *context, PK11SymKey *key)
   1586 {
   1587    CK_RV crv = CKR_OK;
   1588    SECStatus rv = SECSuccess;
   1589    PK11SymKey *newKey = NULL;
   1590 
   1591    if (!context || !key) {
   1592        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1593        return SECFailure;
   1594    }
   1595 
   1596    /* if we ran out of session, we need to restore our previously stored
   1597     * state.
   1598     */
   1599    if (context->slot != key->slot) {
   1600        newKey = pk11_CopyToSlot(context->slot, CKM_SSL3_SHA1_MAC, CKA_SIGN, key);
   1601    } else {
   1602        newKey = PK11_ReferenceSymKey(key);
   1603    }
   1604 
   1605    context->init = PR_FALSE;
   1606    PK11_EnterContextMonitor(context);
   1607    if (!context->ownSession) {
   1608        rv = pk11_restoreContext(context, context->savedData,
   1609                                 context->savedLength);
   1610        if (rv != SECSuccess) {
   1611            PK11_ExitContextMonitor(context);
   1612            PK11_FreeSymKey(newKey);
   1613            return rv;
   1614        }
   1615    }
   1616 
   1617    if (newKey == NULL) {
   1618        crv = CKR_KEY_TYPE_INCONSISTENT;
   1619        if (key->data.data) {
   1620            crv = PK11_GETTAB(context->slot)->C_DigestUpdate(context->session, key->data.data, key->data.len);
   1621        }
   1622    } else {
   1623        crv = PK11_GETTAB(context->slot)->C_DigestKey(context->session, newKey->objectID);
   1624    }
   1625 
   1626    if (crv != CKR_OK) {
   1627        PORT_SetError(PK11_MapError(crv));
   1628        rv = SECFailure;
   1629    }
   1630 
   1631    /*
   1632     * handle session starvation case.. use our last session to multiplex
   1633     */
   1634    if (!context->ownSession) {
   1635        context->savedData = pk11_saveContext(context, context->savedData,
   1636                                              &context->savedLength);
   1637        if (context->savedData == NULL)
   1638            rv = SECFailure;
   1639 
   1640        /* clear out out session for others to use */
   1641        pk11_Finalize(context);
   1642    }
   1643    PK11_ExitContextMonitor(context);
   1644    if (newKey)
   1645        PK11_FreeSymKey(newKey);
   1646    return rv;
   1647 }
   1648 
   1649 /*
   1650 * externally callable version of the lowercase pk11_finalize().
   1651 */
   1652 SECStatus
   1653 PK11_Finalize(PK11Context *context)
   1654 {
   1655    SECStatus rv;
   1656 
   1657    PK11_EnterContextMonitor(context);
   1658    rv = pk11_Finalize(context);
   1659    PK11_ExitContextMonitor(context);
   1660    return rv;
   1661 }
   1662 
   1663 /*
   1664 * clean up a cipher operation, so the session can be used by
   1665 * someone new.
   1666 */
   1667 SECStatus
   1668 pk11_Finalize(PK11Context *context)
   1669 {
   1670    CK_ULONG count = 0;
   1671    CK_RV crv;
   1672    unsigned char stackBuf[256];
   1673    unsigned char *buffer = NULL;
   1674 
   1675    if (!context->ownSession) {
   1676        return SECSuccess;
   1677    }
   1678 
   1679 finalize:
   1680    switch (context->operation) {
   1681        case CKA_ENCRYPT:
   1682            crv = PK11_GETTAB(context->slot)->C_EncryptFinal(context->session, buffer, &count);
   1683            break;
   1684        case CKA_DECRYPT:
   1685            crv = PK11_GETTAB(context->slot)->C_DecryptFinal(context->session, buffer, &count);
   1686            break;
   1687        case CKA_SIGN:
   1688            crv = PK11_GETTAB(context->slot)->C_SignFinal(context->session, buffer, &count);
   1689            break;
   1690        case CKA_VERIFY:
   1691            crv = PK11_GETTAB(context->slot)->C_VerifyFinal(context->session, buffer, count);
   1692            break;
   1693        case CKA_NSS_VERIFY_SIGNATURE:
   1694            crv = PK11_GETTAB(context->slot)->C_VerifySignatureFinal(context->session);
   1695            break;
   1696        case CKA_DIGEST:
   1697            crv = PK11_GETTAB(context->slot)->C_DigestFinal(context->session, buffer, &count);
   1698            break;
   1699        case CKA_NSS_MESSAGE | CKA_ENCRYPT:
   1700            crv = PK11_GETTAB(context->slot)->C_MessageEncryptFinal(context->session);
   1701            break;
   1702        case CKA_NSS_MESSAGE | CKA_DECRYPT:
   1703            crv = PK11_GETTAB(context->slot)->C_MessageDecryptFinal(context->session);
   1704            break;
   1705        case CKA_NSS_MESSAGE | CKA_SIGN:
   1706            crv = PK11_GETTAB(context->slot)->C_MessageSignFinal(context->session);
   1707            break;
   1708        case CKA_NSS_MESSAGE | CKA_VERIFY:
   1709            crv = PK11_GETTAB(context->slot)->C_MessageVerifyFinal(context->session);
   1710            break;
   1711        default:
   1712            crv = CKR_OPERATION_NOT_INITIALIZED;
   1713            break;
   1714    }
   1715 
   1716    if (crv != CKR_OK) {
   1717        if (buffer != stackBuf) {
   1718            PORT_Free(buffer);
   1719        }
   1720        if (crv == CKR_OPERATION_NOT_INITIALIZED) {
   1721            /* if there's no operation, it is finalized */
   1722            return SECSuccess;
   1723        }
   1724        PORT_SetError(PK11_MapError(crv));
   1725        return SECFailure;
   1726    }
   1727 
   1728    /* Message interface does not need to allocate a final buffer */
   1729    /* nor does CKA_NSS_VERIFY_SIGNATURE. We could use a clever trick
   1730     * here to include the CKA_NSS_SIGNATURE addition, but this form is
   1731     * more clear to  the reader what is happenning */
   1732    if ((((context->operation) & CKA_NSS_MESSAGE_MASK) == CKA_NSS_MESSAGE) ||
   1733        ((context->operation) == CKA_NSS_VERIFY_SIGNATURE)) {
   1734        return SECSuccess;
   1735    }
   1736 
   1737    /* try to finalize the session with a buffer */
   1738    if (buffer == NULL) {
   1739        if (count <= sizeof stackBuf) {
   1740            buffer = stackBuf;
   1741        } else {
   1742            buffer = PORT_Alloc(count);
   1743            if (buffer == NULL) {
   1744                return SECFailure;
   1745            }
   1746        }
   1747        goto finalize;
   1748    }
   1749    if (buffer != stackBuf) {
   1750        PORT_Free(buffer);
   1751    }
   1752    return SECSuccess;
   1753 }
   1754 
   1755 /*
   1756 *  Return the final digested or signed data...
   1757 *  this routine can either take pre initialized data, or allocate data
   1758 *  either out of an arena or out of the standard heap.
   1759 */
   1760 SECStatus
   1761 PK11_DigestFinal(PK11Context *context, unsigned char *data,
   1762                 unsigned int *outLen, unsigned int length)
   1763 {
   1764    CK_ULONG len;
   1765    CK_RV crv;
   1766    SECStatus rv;
   1767 
   1768    /* message interface returns no data on Final, Should not use DigestFinal
   1769     * in this case */
   1770    if (((context->operation) & CKA_NSS_MESSAGE_MASK) == CKA_NSS_MESSAGE) {
   1771        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1772        return SECFailure;
   1773    }
   1774 
   1775    /* if we ran out of session, we need to restore our previously stored
   1776     * state.
   1777     */
   1778    PK11_EnterContextMonitor(context);
   1779    if (!context->ownSession) {
   1780        rv = pk11_restoreContext(context, context->savedData,
   1781                                 context->savedLength);
   1782        if (rv != SECSuccess) {
   1783            PK11_ExitContextMonitor(context);
   1784            return rv;
   1785        }
   1786    }
   1787 
   1788    len = length;
   1789    switch (context->operation) {
   1790        case CKA_SIGN:
   1791            crv = PK11_GETTAB(context->slot)->C_SignFinal(context->session, data, &len);
   1792            break;
   1793        case CKA_VERIFY:
   1794            crv = PK11_GETTAB(context->slot)->C_VerifyFinal(context->session, data, len);
   1795            break;
   1796        case CKA_NSS_VERIFY_SIGNATURE:
   1797            crv = PK11_GETTAB(context->slot)->C_VerifySignatureFinal(context->session);
   1798            break;
   1799        case CKA_DIGEST:
   1800            crv = PK11_GETTAB(context->slot)->C_DigestFinal(context->session, data, &len);
   1801            break;
   1802        case CKA_ENCRYPT:
   1803            crv = PK11_GETTAB(context->slot)->C_EncryptFinal(context->session, data, &len);
   1804            break;
   1805        case CKA_DECRYPT:
   1806            crv = PK11_GETTAB(context->slot)->C_DecryptFinal(context->session, data, &len);
   1807            break;
   1808        default:
   1809            crv = CKR_OPERATION_NOT_INITIALIZED;
   1810            break;
   1811    }
   1812    PK11_ExitContextMonitor(context);
   1813 
   1814    context->init = PR_FALSE; /* allow Begin to start up again */
   1815 
   1816    if (crv != CKR_OK) {
   1817        PORT_SetError(PK11_MapError(crv));
   1818        return SECFailure;
   1819    }
   1820    *outLen = (unsigned int)len;
   1821    return SECSuccess;
   1822 }
   1823 
   1824 PRBool
   1825 PK11_ContextGetFIPSStatus(PK11Context *context)
   1826 {
   1827    if (context->slot == NULL) {
   1828        return PR_FALSE;
   1829    }
   1830    return pk11slot_GetFIPSStatus(context->slot, context->session,
   1831                                  CK_INVALID_HANDLE, context->init ? CKT_NSS_SESSION_CHECK : CKT_NSS_SESSION_LAST_CHECK);
   1832 }