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 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
295 context
->param
= NULL
;
297 context
->init
= PR_FALSE
;
298 context
->sessionLock
= PZ_NewLock(nssILockPK11cxt
);
299 if ((context
->param
== NULL
) || (context
->sessionLock
== NULL
)) {
300 PK11_DestroyContext(context
,PR_TRUE
);
304 mech_info
.mechanism
= type
;
305 mech_info
.pParameter
= param
->data
;
306 mech_info
.ulParameterLen
= param
->len
;
307 PK11_EnterContextMonitor(context
);
308 rv
= pk11_context_init(context
,&mech_info
);
309 PK11_ExitContextMonitor(context
);
311 if (rv
!= SECSuccess
) {
312 PK11_DestroyContext(context
,PR_TRUE
);
315 context
->init
= PR_TRUE
;
321 * put together the various PK11_Create_Context calls used by different
325 __PK11_CreateContextByRawKey(PK11SlotInfo
*slot
, CK_MECHANISM_TYPE type
,
326 PK11Origin origin
, CK_ATTRIBUTE_TYPE operation
, SECItem
*key
,
327 SECItem
*param
, void *wincx
)
329 PK11SymKey
*symKey
= NULL
;
330 PK11Context
*context
= NULL
;
332 /* first get a slot */
334 slot
= PK11_GetBestSlot(type
,wincx
);
336 PORT_SetError( SEC_ERROR_NO_MODULE
);
340 PK11_ReferenceSlot(slot
);
343 /* now import the key */
344 symKey
= PK11_ImportSymKey(slot
, type
, origin
, operation
, key
, wincx
);
345 if (symKey
== NULL
) goto loser
;
347 context
= PK11_CreateContextBySymKey(type
, operation
, symKey
, param
);
351 PK11_FreeSymKey(symKey
);
361 PK11_CreateContextByRawKey(PK11SlotInfo
*slot
, CK_MECHANISM_TYPE type
,
362 PK11Origin origin
, CK_ATTRIBUTE_TYPE operation
, SECItem
*key
,
363 SECItem
*param
, void *wincx
)
365 return __PK11_CreateContextByRawKey(slot
, type
, origin
, operation
,
371 * Create a context from a key. We really should make sure we aren't using
372 * the same key in multiple session!
375 PK11_CreateContextBySymKey(CK_MECHANISM_TYPE type
,CK_ATTRIBUTE_TYPE operation
,
376 PK11SymKey
*symKey
, SECItem
*param
)
379 PK11Context
*context
;
381 /* if this slot doesn't support the mechanism, go to a slot that does */
382 newKey
= pk11_ForceSlot(symKey
,type
,operation
);
383 if (newKey
== NULL
) {
384 PK11_ReferenceSymKey(symKey
);
390 /* Context Adopts the symKey.... */
391 context
= pk11_CreateNewContextInSlot(type
, symKey
->slot
, operation
, symKey
,
393 PK11_FreeSymKey(symKey
);
398 * Digest contexts don't need keys, but the do need to find a slot.
399 * Macing should use PK11_CreateContextBySymKey.
402 PK11_CreateDigestContext(SECOidTag hashAlg
)
404 /* digesting has to work without authentication to the slot */
405 CK_MECHANISM_TYPE type
;
407 PK11Context
*context
;
410 type
= PK11_AlgtagToMechanism(hashAlg
);
411 slot
= PK11_GetBestSlot(type
, NULL
);
413 PORT_SetError( SEC_ERROR_NO_MODULE
);
417 /* maybe should really be PK11_GenerateNewParam?? */
422 context
= pk11_CreateNewContextInSlot(type
, slot
, CKA_DIGEST
, NULL
, ¶m
);
428 * create a new context which is the clone of the state of old context.
430 PK11Context
* PK11_CloneContext(PK11Context
*old
)
433 PRBool needFree
= PR_FALSE
;
434 SECStatus rv
= SECSuccess
;
438 newcx
= pk11_CreateNewContextInSlot(old
->type
, old
->slot
, old
->operation
,
439 old
->key
, old
->param
);
440 if (newcx
== NULL
) return NULL
;
442 /* now clone the save state. First we need to find the save state
443 * of the old session. If the old context owns it's session,
444 * the state needs to be saved, otherwise the state is in saveData. */
445 if (old
->ownSession
) {
446 PK11_EnterContextMonitor(old
);
447 data
=pk11_saveContext(old
,NULL
,&len
);
448 PK11_ExitContextMonitor(old
);
451 data
= old
->savedData
;
452 len
= old
->savedLength
;
456 PK11_DestroyContext(newcx
,PR_TRUE
);
460 /* now copy that state into our new context. Again we have different
461 * work if the new context owns it's own session. If it does, we
462 * restore the state gathered above. If it doesn't, we copy the
463 * saveData pointer... */
464 if (newcx
->ownSession
) {
465 PK11_EnterContextMonitor(newcx
);
466 rv
= pk11_restoreContext(newcx
,data
,len
);
467 PK11_ExitContextMonitor(newcx
);
469 PORT_Assert(newcx
->savedData
!= NULL
);
470 if ((newcx
->savedData
== NULL
) || (newcx
->savedLength
< len
)) {
471 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE
);
474 PORT_Memcpy(newcx
->savedData
,data
,len
);
475 newcx
->savedLength
= len
;
479 if (needFree
) PORT_Free(data
);
481 if (rv
!= SECSuccess
) {
482 PK11_DestroyContext(newcx
,PR_TRUE
);
489 * save the current context state into a variable. Required to make FORTEZZA
493 PK11_SaveContext(PK11Context
*cx
,unsigned char *save
,int *len
, int saveLength
)
495 unsigned char * data
= NULL
;
496 CK_ULONG length
= saveLength
;
498 if (cx
->ownSession
) {
499 PK11_EnterContextMonitor(cx
);
500 data
= pk11_saveContextHelper(cx
, save
, &length
);
501 PK11_ExitContextMonitor(cx
);
502 if (data
) *len
= length
;
503 } else if ((unsigned) saveLength
>= cx
->savedLength
) {
504 data
= (unsigned char*)cx
->savedData
;
506 PORT_Memcpy(save
,cx
->savedData
,cx
->savedLength
);
508 *len
= cx
->savedLength
;
511 if (cx
->ownSession
) {
512 PORT_ZFree(data
, length
);
520 /* same as above, but may allocate the return buffer. */
522 PK11_SaveContextAlloc(PK11Context
*cx
,
523 unsigned char *preAllocBuf
, unsigned int pabLen
,
524 unsigned int *stateLen
)
526 unsigned char *stateBuf
= NULL
;
527 unsigned long length
= (unsigned long)pabLen
;
529 if (cx
->ownSession
) {
530 PK11_EnterContextMonitor(cx
);
531 stateBuf
= pk11_saveContextHelper(cx
, preAllocBuf
, &length
);
532 PK11_ExitContextMonitor(cx
);
533 *stateLen
= (stateBuf
!= NULL
) ? length
: 0;
535 if (pabLen
< cx
->savedLength
) {
536 stateBuf
= (unsigned char *)PORT_Alloc(cx
->savedLength
);
538 return (unsigned char *)NULL
;
541 stateBuf
= preAllocBuf
;
544 PORT_Memcpy(stateBuf
, cx
->savedData
, cx
->savedLength
);
546 *stateLen
= cx
->savedLength
;
552 * restore the context state into a new running context. Also required for
556 PK11_RestoreContext(PK11Context
*cx
,unsigned char *save
,int len
)
558 SECStatus rv
= SECSuccess
;
559 if (cx
->ownSession
) {
560 PK11_EnterContextMonitor(cx
);
562 rv
= pk11_restoreContext(cx
,save
,len
);
563 PK11_ExitContextMonitor(cx
);
565 PORT_Assert(cx
->savedData
!= NULL
);
566 if ((cx
->savedData
== NULL
) || (cx
->savedLength
< (unsigned) len
)) {
567 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE
);
570 PORT_Memcpy(cx
->savedData
,save
,len
);
571 cx
->savedLength
= len
;
578 * This is to get FIPS compliance until we can convert
579 * libjar to use PK11_ hashing functions. It returns PR_FALSE
580 * if we can't get a PK11 Context.
583 PK11_HashOK(SECOidTag algID
) {
586 cx
= PK11_CreateDigestContext(algID
);
587 if (cx
== NULL
) return PR_FALSE
;
588 PK11_DestroyContext(cx
, PR_TRUE
);
595 * start a new digesting or Mac'ing operation on this context
597 SECStatus
PK11_DigestBegin(PK11Context
*cx
)
599 CK_MECHANISM mech_info
;
602 if (cx
->init
== PR_TRUE
) {
607 * make sure the old context is clear first
609 PK11_EnterContextMonitor(cx
);
612 mech_info
.mechanism
= cx
->type
;
613 mech_info
.pParameter
= cx
->param
->data
;
614 mech_info
.ulParameterLen
= cx
->param
->len
;
615 rv
= pk11_context_init(cx
,&mech_info
);
616 PK11_ExitContextMonitor(cx
);
618 if (rv
!= SECSuccess
) {
626 PK11_HashBuf(SECOidTag hashAlg
, unsigned char *out
, unsigned char *in
,
628 PK11Context
*context
;
629 unsigned int max_length
;
630 unsigned int out_length
;
633 /* len will be passed to PK11_DigestOp as unsigned. */
635 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
639 context
= PK11_CreateDigestContext(hashAlg
);
640 if (context
== NULL
) return SECFailure
;
642 rv
= PK11_DigestBegin(context
);
643 if (rv
!= SECSuccess
) {
644 PK11_DestroyContext(context
, PR_TRUE
);
648 rv
= PK11_DigestOp(context
, in
, len
);
649 if (rv
!= SECSuccess
) {
650 PK11_DestroyContext(context
, PR_TRUE
);
654 /* XXX This really should have been an argument to this function! */
655 max_length
= HASH_ResultLenByOidTag(hashAlg
);
656 PORT_Assert(max_length
);
658 max_length
= HASH_LENGTH_MAX
;
660 rv
= PK11_DigestFinal(context
,out
,&out_length
,max_length
);
661 PK11_DestroyContext(context
, PR_TRUE
);
667 * execute a bulk encryption operation
670 PK11_CipherOp(PK11Context
*context
, unsigned char * out
, int *outlen
,
671 int maxout
, unsigned char *in
, int inlen
)
674 CK_ULONG length
= maxout
;
676 SECStatus rv
= SECSuccess
;
677 unsigned char *saveOut
= out
;
678 unsigned char *allocOut
= NULL
;
680 /* if we ran out of session, we need to restore our previously stored
683 PK11_EnterContextMonitor(context
);
684 if (!context
->ownSession
) {
685 rv
= pk11_restoreContext(context
,context
->savedData
,
686 context
->savedLength
);
687 if (rv
!= SECSuccess
) {
688 PK11_ExitContextMonitor(context
);
694 * The fortezza hack is to send 8 extra bytes on the first encrypted and
695 * loose them on the first decrypt.
697 if (context
->fortezzaHack
) {
698 unsigned char random
[8];
699 if (context
->operation
== CKA_ENCRYPT
) {
700 PK11_ExitContextMonitor(context
);
701 rv
= PK11_GenerateRandom(random
,sizeof(random
));
702 PK11_EnterContextMonitor(context
);
704 /* since we are offseting the output, we can't encrypt back into
705 * the same buffer... allocate a temporary buffer just for this
707 allocOut
= out
= (unsigned char*)PORT_Alloc(maxout
);
709 PK11_ExitContextMonitor(context
);
712 crv
= PK11_GETTAB(context
->slot
)->C_EncryptUpdate(context
->session
,
713 random
,sizeof(random
),out
,&length
);
718 } else if (context
->operation
== CKA_DECRYPT
) {
719 length
= sizeof(random
);
720 crv
= PK11_GETTAB(context
->slot
)->C_DecryptUpdate(context
->session
,
721 in
,sizeof(random
),random
,&length
);
724 context
->fortezzaHack
= PR_FALSE
;
728 switch (context
->operation
) {
731 crv
=PK11_GETTAB(context
->slot
)->C_EncryptUpdate(context
->session
,
732 in
, inlen
, out
, &length
);
737 crv
=PK11_GETTAB(context
->slot
)->C_DecryptUpdate(context
->session
,
738 in
, inlen
, out
, &length
);
741 crv
= CKR_OPERATION_NOT_INITIALIZED
;
746 PORT_SetError( PK11_MapError(crv
) );
753 if (context
->fortezzaHack
) {
754 if (context
->operation
== CKA_ENCRYPT
) {
755 PORT_Assert(allocOut
);
756 PORT_Memcpy(saveOut
, allocOut
, length
);
759 context
->fortezzaHack
= PR_FALSE
;
763 * handle session starvation case.. use our last session to multiplex
765 if (!context
->ownSession
) {
766 context
->savedData
= pk11_saveContext(context
,context
->savedData
,
767 &context
->savedLength
);
768 if (context
->savedData
== NULL
) rv
= SECFailure
;
770 /* clear out out session for others to use */
771 pk11_Finalize(context
);
773 PK11_ExitContextMonitor(context
);
778 * execute a digest/signature operation
781 PK11_DigestOp(PK11Context
*context
, const unsigned char * in
, unsigned inLen
)
784 SECStatus rv
= SECSuccess
;
787 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
791 /* if we ran out of session, we need to restore our previously stored
794 context
->init
= PR_FALSE
;
795 PK11_EnterContextMonitor(context
);
796 if (!context
->ownSession
) {
797 rv
= pk11_restoreContext(context
,context
->savedData
,
798 context
->savedLength
);
799 if (rv
!= SECSuccess
) {
800 PK11_ExitContextMonitor(context
);
805 switch (context
->operation
) {
806 /* also for MAC'ing */
808 crv
=PK11_GETTAB(context
->slot
)->C_SignUpdate(context
->session
,
813 crv
=PK11_GETTAB(context
->slot
)->C_VerifyUpdate(context
->session
,
818 crv
=PK11_GETTAB(context
->slot
)->C_DigestUpdate(context
->session
,
823 crv
= CKR_OPERATION_NOT_INITIALIZED
;
828 PORT_SetError( PK11_MapError(crv
) );
833 * handle session starvation case.. use our last session to multiplex
835 if (!context
->ownSession
) {
836 context
->savedData
= pk11_saveContext(context
,context
->savedData
,
837 &context
->savedLength
);
838 if (context
->savedData
== NULL
) rv
= SECFailure
;
840 /* clear out out session for others to use */
841 pk11_Finalize(context
);
843 PK11_ExitContextMonitor(context
);
848 * Digest a key if possible./
851 PK11_DigestKey(PK11Context
*context
, PK11SymKey
*key
)
854 SECStatus rv
= SECSuccess
;
855 PK11SymKey
*newKey
= NULL
;
857 if (!context
|| !key
) {
858 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
862 /* if we ran out of session, we need to restore our previously stored
865 if (context
->slot
!= key
->slot
) {
866 newKey
= pk11_CopyToSlot(context
->slot
,CKM_SSL3_SHA1_MAC
,CKA_SIGN
,key
);
868 newKey
= PK11_ReferenceSymKey(key
);
871 context
->init
= PR_FALSE
;
872 PK11_EnterContextMonitor(context
);
873 if (!context
->ownSession
) {
874 rv
= pk11_restoreContext(context
,context
->savedData
,
875 context
->savedLength
);
876 if (rv
!= SECSuccess
) {
877 PK11_ExitContextMonitor(context
);
878 PK11_FreeSymKey(newKey
);
884 if (newKey
== NULL
) {
885 crv
= CKR_KEY_TYPE_INCONSISTENT
;
886 if (key
->data
.data
) {
887 crv
=PK11_GETTAB(context
->slot
)->C_DigestUpdate(context
->session
,
888 key
->data
.data
,key
->data
.len
);
891 crv
=PK11_GETTAB(context
->slot
)->C_DigestKey(context
->session
,
896 PORT_SetError( PK11_MapError(crv
) );
901 * handle session starvation case.. use our last session to multiplex
903 if (!context
->ownSession
) {
904 context
->savedData
= pk11_saveContext(context
,context
->savedData
,
905 &context
->savedLength
);
906 if (context
->savedData
== NULL
) rv
= SECFailure
;
908 /* clear out out session for others to use */
909 pk11_Finalize(context
);
911 PK11_ExitContextMonitor(context
);
912 if (newKey
) PK11_FreeSymKey(newKey
);
917 * externally callable version of the lowercase pk11_finalize().
920 PK11_Finalize(PK11Context
*context
) {
923 PK11_EnterContextMonitor(context
);
924 rv
= pk11_Finalize(context
);
925 PK11_ExitContextMonitor(context
);
930 * clean up a cipher operation, so the session can be used by
934 pk11_Finalize(PK11Context
*context
)
938 unsigned char stackBuf
[256];
939 unsigned char *buffer
= NULL
;
941 if (!context
->ownSession
) {
946 switch (context
->operation
) {
948 crv
=PK11_GETTAB(context
->slot
)->C_EncryptFinal(context
->session
,
952 crv
= PK11_GETTAB(context
->slot
)->C_DecryptFinal(context
->session
,
956 crv
=PK11_GETTAB(context
->slot
)->C_SignFinal(context
->session
,
960 crv
=PK11_GETTAB(context
->slot
)->C_VerifyFinal(context
->session
,
964 crv
=PK11_GETTAB(context
->slot
)->C_DigestFinal(context
->session
,
968 crv
= CKR_OPERATION_NOT_INITIALIZED
;
973 if (buffer
!= stackBuf
) {
976 if (crv
== CKR_OPERATION_NOT_INITIALIZED
) {
977 /* if there's no operation, it is finalized */
980 PORT_SetError( PK11_MapError(crv
) );
984 /* try to finalize the session with a buffer */
985 if (buffer
== NULL
) {
986 if (count
<= sizeof stackBuf
) {
989 buffer
= PORT_Alloc(count
);
990 if (buffer
== NULL
) {
991 PORT_SetError(SEC_ERROR_NO_MEMORY
);
997 if (buffer
!= stackBuf
) {
1004 * Return the final digested or signed data...
1005 * this routine can either take pre initialized data, or allocate data
1006 * either out of an arena or out of the standard heap.
1009 PK11_DigestFinal(PK11Context
*context
,unsigned char *data
,
1010 unsigned int *outLen
, unsigned int length
)
1017 /* if we ran out of session, we need to restore our previously stored
1020 PK11_EnterContextMonitor(context
);
1021 if (!context
->ownSession
) {
1022 rv
= pk11_restoreContext(context
,context
->savedData
,
1023 context
->savedLength
);
1024 if (rv
!= SECSuccess
) {
1025 PK11_ExitContextMonitor(context
);
1031 switch (context
->operation
) {
1033 crv
=PK11_GETTAB(context
->slot
)->C_SignFinal(context
->session
,
1037 crv
=PK11_GETTAB(context
->slot
)->C_VerifyFinal(context
->session
,
1041 crv
=PK11_GETTAB(context
->slot
)->C_DigestFinal(context
->session
,
1045 crv
=PK11_GETTAB(context
->slot
)->C_EncryptFinal(context
->session
,
1049 crv
= PK11_GETTAB(context
->slot
)->C_DecryptFinal(context
->session
,
1053 crv
= CKR_OPERATION_NOT_INITIALIZED
;
1056 PK11_ExitContextMonitor(context
);
1058 *outLen
= (unsigned int) len
;
1059 context
->init
= PR_FALSE
; /* allow Begin to start up again */
1062 if (crv
!= CKR_OK
) {
1063 PORT_SetError( PK11_MapError(crv
) );