1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
37 * This file PK11Contexts which are used in multipart hashing,
38 * encryption/decryption, and signing/verication operations.
53 static const SECItem pk11_null_params
= { 0 };
55 /**********************************************************************
57 * Now Deal with Crypto Contexts
59 **********************************************************************/
65 PK11_EnterContextMonitor(PK11Context
*cx
) {
66 /* if we own the session and our slot is ThreadSafe, only monitor
68 if ((cx
->ownSession
) && (cx
->slot
->isThreadSafe
)) {
69 /* Should this use monitors instead? */
70 PZ_Lock(cx
->sessionLock
);
72 PK11_EnterSlotMonitor(cx
->slot
);
77 PK11_ExitContextMonitor(PK11Context
*cx
) {
78 /* if we own the session and our slot is ThreadSafe, only monitor
80 if ((cx
->ownSession
) && (cx
->slot
->isThreadSafe
)) {
81 /* Should this use monitors instead? */
82 PZ_Unlock(cx
->sessionLock
);
84 PK11_ExitSlotMonitor(cx
->slot
);
89 * Free up a Cipher Context
92 PK11_DestroyContext(PK11Context
*context
, PRBool freeit
)
94 pk11_CloseSession(context
->slot
,context
->session
,context
->ownSession
);
95 /* initialize the critical fields of the context */
96 if (context
->savedData
!= NULL
) PORT_Free(context
->savedData
);
97 if (context
->key
) PK11_FreeSymKey(context
->key
);
98 if (context
->param
&& context
->param
!= &pk11_null_params
)
99 SECITEM_FreeItem(context
->param
, PR_TRUE
);
100 if (context
->sessionLock
) PZ_DestroyLock(context
->sessionLock
);
101 PK11_FreeSlot(context
->slot
);
102 if (freeit
) PORT_Free(context
);
106 * save the current context. Allocate Space if necessary.
108 static unsigned char *
109 pk11_saveContextHelper(PK11Context
*context
, unsigned char *buffer
,
110 unsigned long *savedLength
)
114 /* If buffer is NULL, this will get the length */
115 crv
= PK11_GETTAB(context
->slot
)->C_GetOperationState(context
->session
,
118 if (!buffer
|| (crv
== CKR_BUFFER_TOO_SMALL
)) {
119 /* the given buffer wasn't big enough (or was NULL), but we
120 * have the length, so try again with a new buffer and the
123 unsigned long bufLen
= *savedLength
;
124 buffer
= PORT_Alloc(bufLen
);
125 if (buffer
== NULL
) {
126 return (unsigned char *)NULL
;
128 crv
= PK11_GETTAB(context
->slot
)->C_GetOperationState(
133 PORT_ZFree(buffer
, bufLen
);
137 PORT_SetError( PK11_MapError(crv
) );
138 return (unsigned char *)NULL
;
144 pk11_saveContext(PK11Context
*context
, void *space
, unsigned long *savedLength
)
146 return pk11_saveContextHelper(context
,
147 (unsigned char *)space
, savedLength
);
151 * restore the current context
154 pk11_restoreContext(PK11Context
*context
,void *space
, unsigned long savedLength
)
157 CK_OBJECT_HANDLE objectID
= (context
->key
) ? context
->key
->objectID
:
160 PORT_Assert(space
!= NULL
);
162 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE
);
165 crv
= PK11_GETTAB(context
->slot
)->C_SetOperationState(context
->session
,
166 (CK_BYTE_PTR
)space
, savedLength
, objectID
, 0);
168 PORT_SetError( PK11_MapError(crv
));
174 SECStatus
pk11_Finalize(PK11Context
*context
);
177 * Context initialization. Used by all flavors of CreateContext
180 pk11_context_init(PK11Context
*context
, CK_MECHANISM
*mech_info
)
183 PK11SymKey
*symKey
= context
->key
;
184 SECStatus rv
= SECSuccess
;
186 switch (context
->operation
) {
188 crv
=PK11_GETTAB(context
->slot
)->C_EncryptInit(context
->session
,
189 mech_info
, symKey
->objectID
);
192 if (context
->fortezzaHack
) {
194 /* generate the IV for fortezza */
195 crv
=PK11_GETTAB(context
->slot
)->C_EncryptInit(context
->session
,
196 mech_info
, symKey
->objectID
);
197 if (crv
!= CKR_OK
) break;
198 PK11_GETTAB(context
->slot
)->C_EncryptFinal(context
->session
,
201 crv
=PK11_GETTAB(context
->slot
)->C_DecryptInit(context
->session
,
202 mech_info
, symKey
->objectID
);
205 crv
=PK11_GETTAB(context
->slot
)->C_SignInit(context
->session
,
206 mech_info
, symKey
->objectID
);
209 crv
=PK11_GETTAB(context
->slot
)->C_SignInit(context
->session
,
210 mech_info
, symKey
->objectID
);
213 crv
=PK11_GETTAB(context
->slot
)->C_DigestInit(context
->session
,
217 crv
= CKR_OPERATION_NOT_INITIALIZED
;
222 PORT_SetError( PK11_MapError(crv
) );
227 * handle session starvation case.. use our last session to multiplex
229 if (!context
->ownSession
) {
230 context
->savedData
= pk11_saveContext(context
,context
->savedData
,
231 &context
->savedLength
);
232 if (context
->savedData
== NULL
) rv
= SECFailure
;
233 /* clear out out session for others to use */
234 pk11_Finalize(context
);
241 * Common Helper Function do come up with a new context.
243 static PK11Context
*pk11_CreateNewContextInSlot(CK_MECHANISM_TYPE type
,
244 PK11SlotInfo
*slot
, CK_ATTRIBUTE_TYPE operation
, PK11SymKey
*symKey
,
247 CK_MECHANISM mech_info
;
248 PK11Context
*context
;
251 PORT_Assert(slot
!= NULL
);
252 if (!slot
|| (!symKey
&& operation
!= CKA_DIGEST
)) {
253 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
256 context
= (PK11Context
*) PORT_Alloc(sizeof(PK11Context
));
257 if (context
== NULL
) {
261 /* now deal with the fortezza hack... the fortezza hack is an attempt
262 * to get around the issue of the card not allowing you to do a FORTEZZA
263 * LoadIV/Encrypt, which was added because such a combination could be
264 * use to circumvent the key escrow system. Unfortunately SSL needs to
265 * do this kind of operation, so in SSL we do a loadIV (to verify it),
266 * Then GenerateIV, and through away the first 8 bytes on either side
267 * of the connection.*/
268 context
->fortezzaHack
= PR_FALSE
;
269 if (type
== CKM_SKIPJACK_CBC64
) {
270 if (symKey
->origin
== PK11_OriginFortezzaHack
) {
271 context
->fortezzaHack
= PR_TRUE
;
275 /* initialize the critical fields of the context */
276 context
->operation
= operation
;
277 context
->key
= symKey
? PK11_ReferenceSymKey(symKey
) : NULL
;
278 context
->slot
= PK11_ReferenceSlot(slot
);
279 context
->session
= pk11_GetNewSession(slot
,&context
->ownSession
);
280 context
->cx
= symKey
? symKey
->cx
: NULL
;
281 /* get our session */
282 context
->savedData
= NULL
;
284 /* save the parameters so that some digesting stuff can do multiple
285 * begins on a single context */
286 context
->type
= type
;
288 if (param
->len
> 0) {
289 context
->param
= SECITEM_DupItem(param
);
291 context
->param
= (SECItem
*)&pk11_null_params
;
294 context
->param
= NULL
;
296 context
->init
= PR_FALSE
;
297 context
->sessionLock
= PZ_NewLock(nssILockPK11cxt
);
298 if ((context
->param
== NULL
) || (context
->sessionLock
== NULL
)) {
299 PK11_DestroyContext(context
,PR_TRUE
);
303 mech_info
.mechanism
= type
;
304 mech_info
.pParameter
= param
->data
;
305 mech_info
.ulParameterLen
= param
->len
;
306 PK11_EnterContextMonitor(context
);
307 rv
= pk11_context_init(context
,&mech_info
);
308 PK11_ExitContextMonitor(context
);
310 if (rv
!= SECSuccess
) {
311 PK11_DestroyContext(context
,PR_TRUE
);
314 context
->init
= PR_TRUE
;
320 * put together the various PK11_Create_Context calls used by different
324 __PK11_CreateContextByRawKey(PK11SlotInfo
*slot
, CK_MECHANISM_TYPE type
,
325 PK11Origin origin
, CK_ATTRIBUTE_TYPE operation
, SECItem
*key
,
326 SECItem
*param
, void *wincx
)
328 PK11SymKey
*symKey
= NULL
;
329 PK11Context
*context
= NULL
;
331 /* first get a slot */
333 slot
= PK11_GetBestSlot(type
,wincx
);
335 PORT_SetError( SEC_ERROR_NO_MODULE
);
339 PK11_ReferenceSlot(slot
);
342 /* now import the key */
343 symKey
= PK11_ImportSymKey(slot
, type
, origin
, operation
, key
, wincx
);
344 if (symKey
== NULL
) goto loser
;
346 context
= PK11_CreateContextBySymKey(type
, operation
, symKey
, param
);
350 PK11_FreeSymKey(symKey
);
360 PK11_CreateContextByRawKey(PK11SlotInfo
*slot
, CK_MECHANISM_TYPE type
,
361 PK11Origin origin
, CK_ATTRIBUTE_TYPE operation
, SECItem
*key
,
362 SECItem
*param
, void *wincx
)
364 return __PK11_CreateContextByRawKey(slot
, type
, origin
, operation
,
370 * Create a context from a key. We really should make sure we aren't using
371 * the same key in multiple session!
374 PK11_CreateContextBySymKey(CK_MECHANISM_TYPE type
,CK_ATTRIBUTE_TYPE operation
,
375 PK11SymKey
*symKey
, SECItem
*param
)
378 PK11Context
*context
;
380 /* if this slot doesn't support the mechanism, go to a slot that does */
381 newKey
= pk11_ForceSlot(symKey
,type
,operation
);
382 if (newKey
== NULL
) {
383 PK11_ReferenceSymKey(symKey
);
389 /* Context Adopts the symKey.... */
390 context
= pk11_CreateNewContextInSlot(type
, symKey
->slot
, operation
, symKey
,
392 PK11_FreeSymKey(symKey
);
397 * Digest contexts don't need keys, but the do need to find a slot.
398 * Macing should use PK11_CreateContextBySymKey.
401 PK11_CreateDigestContext(SECOidTag hashAlg
)
403 /* digesting has to work without authentication to the slot */
404 CK_MECHANISM_TYPE type
;
406 PK11Context
*context
;
409 type
= PK11_AlgtagToMechanism(hashAlg
);
410 slot
= PK11_GetBestSlot(type
, NULL
);
412 PORT_SetError( SEC_ERROR_NO_MODULE
);
416 /* maybe should really be PK11_GenerateNewParam?? */
421 context
= pk11_CreateNewContextInSlot(type
, slot
, CKA_DIGEST
, NULL
, ¶m
);
427 * create a new context which is the clone of the state of old context.
429 PK11Context
* PK11_CloneContext(PK11Context
*old
)
432 PRBool needFree
= PR_FALSE
;
433 SECStatus rv
= SECSuccess
;
437 newcx
= pk11_CreateNewContextInSlot(old
->type
, old
->slot
, old
->operation
,
438 old
->key
, old
->param
);
439 if (newcx
== NULL
) return NULL
;
441 /* now clone the save state. First we need to find the save state
442 * of the old session. If the old context owns it's session,
443 * the state needs to be saved, otherwise the state is in saveData. */
444 if (old
->ownSession
) {
445 PK11_EnterContextMonitor(old
);
446 data
=pk11_saveContext(old
,NULL
,&len
);
447 PK11_ExitContextMonitor(old
);
450 data
= old
->savedData
;
451 len
= old
->savedLength
;
455 PK11_DestroyContext(newcx
,PR_TRUE
);
459 /* now copy that state into our new context. Again we have different
460 * work if the new context owns it's own session. If it does, we
461 * restore the state gathered above. If it doesn't, we copy the
462 * saveData pointer... */
463 if (newcx
->ownSession
) {
464 PK11_EnterContextMonitor(newcx
);
465 rv
= pk11_restoreContext(newcx
,data
,len
);
466 PK11_ExitContextMonitor(newcx
);
468 PORT_Assert(newcx
->savedData
!= NULL
);
469 if ((newcx
->savedData
== NULL
) || (newcx
->savedLength
< len
)) {
470 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE
);
473 PORT_Memcpy(newcx
->savedData
,data
,len
);
474 newcx
->savedLength
= len
;
478 if (needFree
) PORT_Free(data
);
480 if (rv
!= SECSuccess
) {
481 PK11_DestroyContext(newcx
,PR_TRUE
);
488 * save the current context state into a variable. Required to make FORTEZZA
492 PK11_SaveContext(PK11Context
*cx
,unsigned char *save
,int *len
, int saveLength
)
494 unsigned char * data
= NULL
;
495 CK_ULONG length
= saveLength
;
497 if (cx
->ownSession
) {
498 PK11_EnterContextMonitor(cx
);
499 data
= pk11_saveContextHelper(cx
, save
, &length
);
500 PK11_ExitContextMonitor(cx
);
501 if (data
) *len
= length
;
502 } else if ((unsigned) saveLength
>= cx
->savedLength
) {
503 data
= (unsigned char*)cx
->savedData
;
505 PORT_Memcpy(save
,cx
->savedData
,cx
->savedLength
);
507 *len
= cx
->savedLength
;
510 if (cx
->ownSession
) {
511 PORT_ZFree(data
, length
);
519 /* same as above, but may allocate the return buffer. */
521 PK11_SaveContextAlloc(PK11Context
*cx
,
522 unsigned char *preAllocBuf
, unsigned int pabLen
,
523 unsigned int *stateLen
)
525 unsigned char *stateBuf
= NULL
;
526 unsigned long length
= (unsigned long)pabLen
;
528 if (cx
->ownSession
) {
529 PK11_EnterContextMonitor(cx
);
530 stateBuf
= pk11_saveContextHelper(cx
, preAllocBuf
, &length
);
531 PK11_ExitContextMonitor(cx
);
532 *stateLen
= (stateBuf
!= NULL
) ? length
: 0;
534 if (pabLen
< cx
->savedLength
) {
535 stateBuf
= (unsigned char *)PORT_Alloc(cx
->savedLength
);
537 return (unsigned char *)NULL
;
540 stateBuf
= preAllocBuf
;
543 PORT_Memcpy(stateBuf
, cx
->savedData
, cx
->savedLength
);
545 *stateLen
= cx
->savedLength
;
551 * restore the context state into a new running context. Also required for
555 PK11_RestoreContext(PK11Context
*cx
,unsigned char *save
,int len
)
557 SECStatus rv
= SECSuccess
;
558 if (cx
->ownSession
) {
559 PK11_EnterContextMonitor(cx
);
561 rv
= pk11_restoreContext(cx
,save
,len
);
562 PK11_ExitContextMonitor(cx
);
564 PORT_Assert(cx
->savedData
!= NULL
);
565 if ((cx
->savedData
== NULL
) || (cx
->savedLength
< (unsigned) len
)) {
566 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE
);
569 PORT_Memcpy(cx
->savedData
,save
,len
);
570 cx
->savedLength
= len
;
577 * This is to get FIPS compliance until we can convert
578 * libjar to use PK11_ hashing functions. It returns PR_FALSE
579 * if we can't get a PK11 Context.
582 PK11_HashOK(SECOidTag algID
) {
585 cx
= PK11_CreateDigestContext(algID
);
586 if (cx
== NULL
) return PR_FALSE
;
587 PK11_DestroyContext(cx
, PR_TRUE
);
594 * start a new digesting or Mac'ing operation on this context
596 SECStatus
PK11_DigestBegin(PK11Context
*cx
)
598 CK_MECHANISM mech_info
;
601 if (cx
->init
== PR_TRUE
) {
606 * make sure the old context is clear first
608 PK11_EnterContextMonitor(cx
);
611 mech_info
.mechanism
= cx
->type
;
612 mech_info
.pParameter
= cx
->param
->data
;
613 mech_info
.ulParameterLen
= cx
->param
->len
;
614 rv
= pk11_context_init(cx
,&mech_info
);
615 PK11_ExitContextMonitor(cx
);
617 if (rv
!= SECSuccess
) {
625 PK11_HashBuf(SECOidTag hashAlg
, unsigned char *out
, unsigned char *in
,
627 PK11Context
*context
;
628 unsigned int max_length
;
629 unsigned int out_length
;
632 /* len will be passed to PK11_DigestOp as unsigned. */
634 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
638 context
= PK11_CreateDigestContext(hashAlg
);
639 if (context
== NULL
) return SECFailure
;
641 rv
= PK11_DigestBegin(context
);
642 if (rv
!= SECSuccess
) {
643 PK11_DestroyContext(context
, PR_TRUE
);
647 rv
= PK11_DigestOp(context
, in
, len
);
648 if (rv
!= SECSuccess
) {
649 PK11_DestroyContext(context
, PR_TRUE
);
653 /* XXX This really should have been an argument to this function! */
654 max_length
= HASH_ResultLenByOidTag(hashAlg
);
655 PORT_Assert(max_length
);
657 max_length
= HASH_LENGTH_MAX
;
659 rv
= PK11_DigestFinal(context
,out
,&out_length
,max_length
);
660 PK11_DestroyContext(context
, PR_TRUE
);
666 * execute a bulk encryption operation
669 PK11_CipherOp(PK11Context
*context
, unsigned char * out
, int *outlen
,
670 int maxout
, unsigned char *in
, int inlen
)
673 CK_ULONG length
= maxout
;
675 SECStatus rv
= SECSuccess
;
676 unsigned char *saveOut
= out
;
677 unsigned char *allocOut
= NULL
;
679 /* if we ran out of session, we need to restore our previously stored
682 PK11_EnterContextMonitor(context
);
683 if (!context
->ownSession
) {
684 rv
= pk11_restoreContext(context
,context
->savedData
,
685 context
->savedLength
);
686 if (rv
!= SECSuccess
) {
687 PK11_ExitContextMonitor(context
);
693 * The fortezza hack is to send 8 extra bytes on the first encrypted and
694 * loose them on the first decrypt.
696 if (context
->fortezzaHack
) {
697 unsigned char random
[8];
698 if (context
->operation
== CKA_ENCRYPT
) {
699 PK11_ExitContextMonitor(context
);
700 rv
= PK11_GenerateRandom(random
,sizeof(random
));
701 PK11_EnterContextMonitor(context
);
703 /* since we are offseting the output, we can't encrypt back into
704 * the same buffer... allocate a temporary buffer just for this
706 allocOut
= out
= (unsigned char*)PORT_Alloc(maxout
);
708 PK11_ExitContextMonitor(context
);
711 crv
= PK11_GETTAB(context
->slot
)->C_EncryptUpdate(context
->session
,
712 random
,sizeof(random
),out
,&length
);
717 } else if (context
->operation
== CKA_DECRYPT
) {
718 length
= sizeof(random
);
719 crv
= PK11_GETTAB(context
->slot
)->C_DecryptUpdate(context
->session
,
720 in
,sizeof(random
),random
,&length
);
723 context
->fortezzaHack
= PR_FALSE
;
727 switch (context
->operation
) {
730 crv
=PK11_GETTAB(context
->slot
)->C_EncryptUpdate(context
->session
,
731 in
, inlen
, out
, &length
);
736 crv
=PK11_GETTAB(context
->slot
)->C_DecryptUpdate(context
->session
,
737 in
, inlen
, out
, &length
);
740 crv
= CKR_OPERATION_NOT_INITIALIZED
;
745 PORT_SetError( PK11_MapError(crv
) );
752 if (context
->fortezzaHack
) {
753 if (context
->operation
== CKA_ENCRYPT
) {
754 PORT_Assert(allocOut
);
755 PORT_Memcpy(saveOut
, allocOut
, length
);
758 context
->fortezzaHack
= PR_FALSE
;
762 * handle session starvation case.. use our last session to multiplex
764 if (!context
->ownSession
) {
765 context
->savedData
= pk11_saveContext(context
,context
->savedData
,
766 &context
->savedLength
);
767 if (context
->savedData
== NULL
) rv
= SECFailure
;
769 /* clear out out session for others to use */
770 pk11_Finalize(context
);
772 PK11_ExitContextMonitor(context
);
777 * execute a digest/signature operation
780 PK11_DigestOp(PK11Context
*context
, const unsigned char * in
, unsigned inLen
)
783 SECStatus rv
= SECSuccess
;
786 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
790 /* if we ran out of session, we need to restore our previously stored
793 context
->init
= PR_FALSE
;
794 PK11_EnterContextMonitor(context
);
795 if (!context
->ownSession
) {
796 rv
= pk11_restoreContext(context
,context
->savedData
,
797 context
->savedLength
);
798 if (rv
!= SECSuccess
) {
799 PK11_ExitContextMonitor(context
);
804 switch (context
->operation
) {
805 /* also for MAC'ing */
807 crv
=PK11_GETTAB(context
->slot
)->C_SignUpdate(context
->session
,
812 crv
=PK11_GETTAB(context
->slot
)->C_VerifyUpdate(context
->session
,
817 crv
=PK11_GETTAB(context
->slot
)->C_DigestUpdate(context
->session
,
822 crv
= CKR_OPERATION_NOT_INITIALIZED
;
827 PORT_SetError( PK11_MapError(crv
) );
832 * handle session starvation case.. use our last session to multiplex
834 if (!context
->ownSession
) {
835 context
->savedData
= pk11_saveContext(context
,context
->savedData
,
836 &context
->savedLength
);
837 if (context
->savedData
== NULL
) rv
= SECFailure
;
839 /* clear out out session for others to use */
840 pk11_Finalize(context
);
842 PK11_ExitContextMonitor(context
);
847 * Digest a key if possible./
850 PK11_DigestKey(PK11Context
*context
, PK11SymKey
*key
)
853 SECStatus rv
= SECSuccess
;
854 PK11SymKey
*newKey
= NULL
;
856 if (!context
|| !key
) {
857 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
861 /* if we ran out of session, we need to restore our previously stored
864 if (context
->slot
!= key
->slot
) {
865 newKey
= pk11_CopyToSlot(context
->slot
,CKM_SSL3_SHA1_MAC
,CKA_SIGN
,key
);
867 newKey
= PK11_ReferenceSymKey(key
);
870 context
->init
= PR_FALSE
;
871 PK11_EnterContextMonitor(context
);
872 if (!context
->ownSession
) {
873 rv
= pk11_restoreContext(context
,context
->savedData
,
874 context
->savedLength
);
875 if (rv
!= SECSuccess
) {
876 PK11_ExitContextMonitor(context
);
877 PK11_FreeSymKey(newKey
);
883 if (newKey
== NULL
) {
884 crv
= CKR_KEY_TYPE_INCONSISTENT
;
885 if (key
->data
.data
) {
886 crv
=PK11_GETTAB(context
->slot
)->C_DigestUpdate(context
->session
,
887 key
->data
.data
,key
->data
.len
);
890 crv
=PK11_GETTAB(context
->slot
)->C_DigestKey(context
->session
,
895 PORT_SetError( PK11_MapError(crv
) );
900 * handle session starvation case.. use our last session to multiplex
902 if (!context
->ownSession
) {
903 context
->savedData
= pk11_saveContext(context
,context
->savedData
,
904 &context
->savedLength
);
905 if (context
->savedData
== NULL
) rv
= SECFailure
;
907 /* clear out out session for others to use */
908 pk11_Finalize(context
);
910 PK11_ExitContextMonitor(context
);
911 if (newKey
) PK11_FreeSymKey(newKey
);
916 * externally callable version of the lowercase pk11_finalize().
919 PK11_Finalize(PK11Context
*context
) {
922 PK11_EnterContextMonitor(context
);
923 rv
= pk11_Finalize(context
);
924 PK11_ExitContextMonitor(context
);
929 * clean up a cipher operation, so the session can be used by
933 pk11_Finalize(PK11Context
*context
)
937 unsigned char stackBuf
[256];
938 unsigned char *buffer
= NULL
;
940 if (!context
->ownSession
) {
945 switch (context
->operation
) {
947 crv
=PK11_GETTAB(context
->slot
)->C_EncryptFinal(context
->session
,
951 crv
= PK11_GETTAB(context
->slot
)->C_DecryptFinal(context
->session
,
955 crv
=PK11_GETTAB(context
->slot
)->C_SignFinal(context
->session
,
959 crv
=PK11_GETTAB(context
->slot
)->C_VerifyFinal(context
->session
,
963 crv
=PK11_GETTAB(context
->slot
)->C_DigestFinal(context
->session
,
967 crv
= CKR_OPERATION_NOT_INITIALIZED
;
972 if (buffer
!= stackBuf
) {
975 if (crv
== CKR_OPERATION_NOT_INITIALIZED
) {
976 /* if there's no operation, it is finalized */
979 PORT_SetError( PK11_MapError(crv
) );
983 /* try to finalize the session with a buffer */
984 if (buffer
== NULL
) {
985 if (count
<= sizeof stackBuf
) {
988 buffer
= PORT_Alloc(count
);
989 if (buffer
== NULL
) {
990 PORT_SetError(SEC_ERROR_NO_MEMORY
);
996 if (buffer
!= stackBuf
) {
1003 * Return the final digested or signed data...
1004 * this routine can either take pre initialized data, or allocate data
1005 * either out of an arena or out of the standard heap.
1008 PK11_DigestFinal(PK11Context
*context
,unsigned char *data
,
1009 unsigned int *outLen
, unsigned int length
)
1016 /* if we ran out of session, we need to restore our previously stored
1019 PK11_EnterContextMonitor(context
);
1020 if (!context
->ownSession
) {
1021 rv
= pk11_restoreContext(context
,context
->savedData
,
1022 context
->savedLength
);
1023 if (rv
!= SECSuccess
) {
1024 PK11_ExitContextMonitor(context
);
1030 switch (context
->operation
) {
1032 crv
=PK11_GETTAB(context
->slot
)->C_SignFinal(context
->session
,
1036 crv
=PK11_GETTAB(context
->slot
)->C_VerifyFinal(context
->session
,
1040 crv
=PK11_GETTAB(context
->slot
)->C_DigestFinal(context
->session
,
1044 crv
=PK11_GETTAB(context
->slot
)->C_EncryptFinal(context
->session
,
1048 crv
= PK11_GETTAB(context
->slot
)->C_DecryptFinal(context
->session
,
1052 crv
= CKR_OPERATION_NOT_INITIALIZED
;
1055 PK11_ExitContextMonitor(context
);
1057 *outLen
= (unsigned int) len
;
1058 context
->init
= PR_FALSE
; /* allow Begin to start up again */
1061 if (crv
!= CKR_OK
) {
1062 PORT_SetError( PK11_MapError(crv
) );