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