Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(240)

Side by Side Diff: mozilla/security/nss/lib/pk11wrap/pk11cxt.c

Issue 14249009: Change the NSS and NSPR source tree to the new directory structure to be (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/nss/
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
21 static const SECItem pk11_null_params = { 0 };
22
23 /**********************************************************************
24 *
25 * Now Deal with Crypto Contexts
26 *
27 **********************************************************************/
28
29 /*
30 * the monitors...
31 */
32 void
33 PK11_EnterContextMonitor(PK11Context *cx) {
34 /* if we own the session and our slot is ThreadSafe, only monitor
35 * the Context */
36 if ((cx->ownSession) && (cx->slot->isThreadSafe)) {
37 /* Should this use monitors instead? */
38 PZ_Lock(cx->sessionLock);
39 } else {
40 PK11_EnterSlotMonitor(cx->slot);
41 }
42 }
43
44 void
45 PK11_ExitContextMonitor(PK11Context *cx) {
46 /* if we own the session and our slot is ThreadSafe, only monitor
47 * the Context */
48 if ((cx->ownSession) && (cx->slot->isThreadSafe)) {
49 /* Should this use monitors instead? */
50 PZ_Unlock(cx->sessionLock);
51 } else {
52 PK11_ExitSlotMonitor(cx->slot);
53 }
54 }
55
56 /*
57 * Free up a Cipher Context
58 */
59 void
60 PK11_DestroyContext(PK11Context *context, PRBool freeit)
61 {
62 pk11_CloseSession(context->slot,context->session,context->ownSession);
63 /* initialize the critical fields of the context */
64 if (context->savedData != NULL ) PORT_Free(context->savedData);
65 if (context->key) PK11_FreeSymKey(context->key);
66 if (context->param && context->param != &pk11_null_params)
67 SECITEM_FreeItem(context->param, PR_TRUE);
68 if (context->sessionLock) PZ_DestroyLock(context->sessionLock);
69 PK11_FreeSlot(context->slot);
70 if (freeit) PORT_Free(context);
71 }
72
73 /*
74 * save the current context. Allocate Space if necessary.
75 */
76 static unsigned char *
77 pk11_saveContextHelper(PK11Context *context, unsigned char *buffer,
78 unsigned long *savedLength)
79 {
80 CK_RV crv;
81
82 /* If buffer is NULL, this will get the length */
83 crv = PK11_GETTAB(context->slot)->C_GetOperationState(context->session,
84 (CK_BYTE_PTR)buffer,
85 savedLength);
86 if (!buffer || (crv == CKR_BUFFER_TOO_SMALL)) {
87 /* the given buffer wasn't big enough (or was NULL), but we
88 * have the length, so try again with a new buffer and the
89 * correct length
90 */
91 unsigned long bufLen = *savedLength;
92 buffer = PORT_Alloc(bufLen);
93 if (buffer == NULL) {
94 return (unsigned char *)NULL;
95 }
96 crv = PK11_GETTAB(context->slot)->C_GetOperationState(
97 context->session,
98 (CK_BYTE_PTR)buffer,
99 savedLength);
100 if (crv != CKR_OK) {
101 PORT_ZFree(buffer, bufLen);
102 }
103 }
104 if (crv != CKR_OK) {
105 PORT_SetError( PK11_MapError(crv) );
106 return (unsigned char *)NULL;
107 }
108 return buffer;
109 }
110
111 void *
112 pk11_saveContext(PK11Context *context, void *space, unsigned long *savedLength)
113 {
114 return pk11_saveContextHelper(context,
115 (unsigned char *)space, savedLength);
116 }
117
118 /*
119 * restore the current context
120 */
121 SECStatus
122 pk11_restoreContext(PK11Context *context,void *space, unsigned long savedLength)
123 {
124 CK_RV crv;
125 CK_OBJECT_HANDLE objectID = (context->key) ? context->key->objectID:
126 CK_INVALID_HANDLE;
127
128 PORT_Assert(space != NULL);
129 if (space == NULL) {
130 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
131 return SECFailure;
132 }
133 crv = PK11_GETTAB(context->slot)->C_SetOperationState(context->session,
134 (CK_BYTE_PTR)space, savedLength, objectID, 0);
135 if (crv != CKR_OK) {
136 PORT_SetError( PK11_MapError(crv));
137 return SECFailure;
138 }
139 return SECSuccess;
140 }
141
142 SECStatus pk11_Finalize(PK11Context *context);
143
144 /*
145 * Context initialization. Used by all flavors of CreateContext
146 */
147 static SECStatus
148 pk11_context_init(PK11Context *context, CK_MECHANISM *mech_info)
149 {
150 CK_RV crv;
151 PK11SymKey *symKey = context->key;
152 SECStatus rv = SECSuccess;
153
154 switch (context->operation) {
155 case CKA_ENCRYPT:
156 crv=PK11_GETTAB(context->slot)->C_EncryptInit(context->session,
157 mech_info, symKey->objectID);
158 break;
159 case CKA_DECRYPT:
160 if (context->fortezzaHack) {
161 CK_ULONG count = 0;;
162 /* generate the IV for fortezza */
163 crv=PK11_GETTAB(context->slot)->C_EncryptInit(context->session,
164 mech_info, symKey->objectID);
165 if (crv != CKR_OK) break;
166 PK11_GETTAB(context->slot)->C_EncryptFinal(context->session,
167 NULL, &count);
168 }
169 crv=PK11_GETTAB(context->slot)->C_DecryptInit(context->session,
170 mech_info, symKey->objectID);
171 break;
172 case CKA_SIGN:
173 crv=PK11_GETTAB(context->slot)->C_SignInit(context->session,
174 mech_info, symKey->objectID);
175 break;
176 case CKA_VERIFY:
177 crv=PK11_GETTAB(context->slot)->C_SignInit(context->session,
178 mech_info, symKey->objectID);
179 break;
180 case CKA_DIGEST:
181 crv=PK11_GETTAB(context->slot)->C_DigestInit(context->session,
182 mech_info);
183 break;
184 default:
185 crv = CKR_OPERATION_NOT_INITIALIZED;
186 break;
187 }
188
189 if (crv != CKR_OK) {
190 PORT_SetError( PK11_MapError(crv) );
191 return SECFailure;
192 }
193
194 /*
195 * handle session starvation case.. use our last session to multiplex
196 */
197 if (!context->ownSession) {
198 context->savedData = pk11_saveContext(context,context->savedData,
199 &context->savedLength);
200 if (context->savedData == NULL) rv = SECFailure;
201 /* clear out out session for others to use */
202 pk11_Finalize(context);
203 }
204 return rv;
205 }
206
207
208 /*
209 * Common Helper Function do come up with a new context.
210 */
211 static PK11Context *pk11_CreateNewContextInSlot(CK_MECHANISM_TYPE type,
212 PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey,
213 SECItem *param)
214 {
215 CK_MECHANISM mech_info;
216 PK11Context *context;
217 SECStatus rv;
218
219 PORT_Assert(slot != NULL);
220 if (!slot || (!symKey && ((operation != CKA_DIGEST) ||
221 (type == CKM_SKIPJACK_CBC64)))) {
222 PORT_SetError(SEC_ERROR_INVALID_ARGS);
223 return NULL;
224 }
225 context = (PK11Context *) PORT_Alloc(sizeof(PK11Context));
226 if (context == NULL) {
227 return NULL;
228 }
229
230 /* now deal with the fortezza hack... the fortezza hack is an attempt
231 * to get around the issue of the card not allowing you to do a FORTEZZA
232 * LoadIV/Encrypt, which was added because such a combination could be
233 * use to circumvent the key escrow system. Unfortunately SSL needs to
234 * do this kind of operation, so in SSL we do a loadIV (to verify it),
235 * Then GenerateIV, and through away the first 8 bytes on either side
236 * of the connection.*/
237 context->fortezzaHack = PR_FALSE;
238 if (type == CKM_SKIPJACK_CBC64) {
239 if (symKey->origin == PK11_OriginFortezzaHack) {
240 context->fortezzaHack = PR_TRUE;
241 }
242 }
243
244 /* initialize the critical fields of the context */
245 context->operation = operation;
246 context->key = symKey ? PK11_ReferenceSymKey(symKey) : NULL;
247 context->slot = PK11_ReferenceSlot(slot);
248 context->session = pk11_GetNewSession(slot,&context->ownSession);
249 context->cx = symKey ? symKey->cx : NULL;
250 /* get our session */
251 context->savedData = NULL;
252
253 /* save the parameters so that some digesting stuff can do multiple
254 * begins on a single context */
255 context->type = type;
256 if (param) {
257 if (param->len > 0) {
258 context->param = SECITEM_DupItem(param);
259 } else {
260 context->param = (SECItem *)&pk11_null_params;
261 }
262 } else {
263 PORT_SetError(SEC_ERROR_INVALID_ARGS);
264 context->param = NULL;
265 }
266 context->init = PR_FALSE;
267 context->sessionLock = PZ_NewLock(nssILockPK11cxt);
268 if ((context->param == NULL) || (context->sessionLock == NULL)) {
269 PK11_DestroyContext(context,PR_TRUE);
270 return NULL;
271 }
272
273 mech_info.mechanism = type;
274 mech_info.pParameter = param->data;
275 mech_info.ulParameterLen = param->len;
276 PK11_EnterContextMonitor(context);
277 rv = pk11_context_init(context,&mech_info);
278 PK11_ExitContextMonitor(context);
279
280 if (rv != SECSuccess) {
281 PK11_DestroyContext(context,PR_TRUE);
282 return NULL;
283 }
284 context->init = PR_TRUE;
285 return context;
286 }
287
288
289 /*
290 * put together the various PK11_Create_Context calls used by different
291 * parts of libsec.
292 */
293 PK11Context *
294 __PK11_CreateContextByRawKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
295 PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key,
296 SECItem *param, void *wincx)
297 {
298 PK11SymKey *symKey = NULL;
299 PK11Context *context = NULL;
300
301 /* first get a slot */
302 if (slot == NULL) {
303 slot = PK11_GetBestSlot(type,wincx);
304 if (slot == NULL) {
305 PORT_SetError( SEC_ERROR_NO_MODULE );
306 goto loser;
307 }
308 } else {
309 PK11_ReferenceSlot(slot);
310 }
311
312 /* now import the key */
313 symKey = PK11_ImportSymKey(slot, type, origin, operation, key, wincx);
314 if (symKey == NULL) goto loser;
315
316 context = PK11_CreateContextBySymKey(type, operation, symKey, param);
317
318 loser:
319 if (symKey) {
320 PK11_FreeSymKey(symKey);
321 }
322 if (slot) {
323 PK11_FreeSlot(slot);
324 }
325
326 return context;
327 }
328
329 PK11Context *
330 PK11_CreateContextByRawKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
331 PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key,
332 SECItem *param, void *wincx)
333 {
334 return __PK11_CreateContextByRawKey(slot, type, origin, operation,
335 key, param, wincx);
336 }
337
338
339 /*
340 * Create a context from a key. We really should make sure we aren't using
341 * the same key in multiple session!
342 */
343 PK11Context *
344 PK11_CreateContextBySymKey(CK_MECHANISM_TYPE type,CK_ATTRIBUTE_TYPE operation,
345 PK11SymKey *symKey, SECItem *param)
346 {
347 PK11SymKey *newKey;
348 PK11Context *context;
349
350 /* if this slot doesn't support the mechanism, go to a slot that does */
351 newKey = pk11_ForceSlot(symKey,type,operation);
352 if (newKey == NULL) {
353 PK11_ReferenceSymKey(symKey);
354 } else {
355 symKey = newKey;
356 }
357
358
359 /* Context Adopts the symKey.... */
360 context = pk11_CreateNewContextInSlot(type, symKey->slot, operation, symKey,
361 param);
362 PK11_FreeSymKey(symKey);
363 return context;
364 }
365
366 /*
367 * Digest contexts don't need keys, but the do need to find a slot.
368 * Macing should use PK11_CreateContextBySymKey.
369 */
370 PK11Context *
371 PK11_CreateDigestContext(SECOidTag hashAlg)
372 {
373 /* digesting has to work without authentication to the slot */
374 CK_MECHANISM_TYPE type;
375 PK11SlotInfo *slot;
376 PK11Context *context;
377 SECItem param;
378
379 type = PK11_AlgtagToMechanism(hashAlg);
380 slot = PK11_GetBestSlot(type, NULL);
381 if (slot == NULL) {
382 PORT_SetError( SEC_ERROR_NO_MODULE );
383 return NULL;
384 }
385
386 /* maybe should really be PK11_GenerateNewParam?? */
387 param.data = NULL;
388 param.len = 0;
389 param.type = 0;
390
391 context = pk11_CreateNewContextInSlot(type, slot, CKA_DIGEST, NULL, &param);
392 PK11_FreeSlot(slot);
393 return context;
394 }
395
396 /*
397 * create a new context which is the clone of the state of old context.
398 */
399 PK11Context * PK11_CloneContext(PK11Context *old)
400 {
401 PK11Context *newcx;
402 PRBool needFree = PR_FALSE;
403 SECStatus rv = SECSuccess;
404 void *data;
405 unsigned long len;
406
407 newcx = pk11_CreateNewContextInSlot(old->type, old->slot, old->operation,
408 old->key, old->param);
409 if (newcx == NULL) return NULL;
410
411 /* now clone the save state. First we need to find the save state
412 * of the old session. If the old context owns it's session,
413 * the state needs to be saved, otherwise the state is in saveData. */
414 if (old->ownSession) {
415 PK11_EnterContextMonitor(old);
416 data=pk11_saveContext(old,NULL,&len);
417 PK11_ExitContextMonitor(old);
418 needFree = PR_TRUE;
419 } else {
420 data = old->savedData;
421 len = old->savedLength;
422 }
423
424 if (data == NULL) {
425 PK11_DestroyContext(newcx,PR_TRUE);
426 return NULL;
427 }
428
429 /* now copy that state into our new context. Again we have different
430 * work if the new context owns it's own session. If it does, we
431 * restore the state gathered above. If it doesn't, we copy the
432 * saveData pointer... */
433 if (newcx->ownSession) {
434 PK11_EnterContextMonitor(newcx);
435 rv = pk11_restoreContext(newcx,data,len);
436 PK11_ExitContextMonitor(newcx);
437 } else {
438 PORT_Assert(newcx->savedData != NULL);
439 if ((newcx->savedData == NULL) || (newcx->savedLength < len)) {
440 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
441 rv = SECFailure;
442 } else {
443 PORT_Memcpy(newcx->savedData,data,len);
444 newcx->savedLength = len;
445 }
446 }
447
448 if (needFree) PORT_Free(data);
449
450 if (rv != SECSuccess) {
451 PK11_DestroyContext(newcx,PR_TRUE);
452 return NULL;
453 }
454 return newcx;
455 }
456
457 /*
458 * save the current context state into a variable. Required to make FORTEZZA
459 * work.
460 */
461 SECStatus
462 PK11_SaveContext(PK11Context *cx,unsigned char *save,int *len, int saveLength)
463 {
464 unsigned char * data = NULL;
465 CK_ULONG length = saveLength;
466
467 if (cx->ownSession) {
468 PK11_EnterContextMonitor(cx);
469 data = pk11_saveContextHelper(cx, save, &length);
470 PK11_ExitContextMonitor(cx);
471 if (data) *len = length;
472 } else if ((unsigned) saveLength >= cx->savedLength) {
473 data = (unsigned char*)cx->savedData;
474 if (cx->savedData) {
475 PORT_Memcpy(save,cx->savedData,cx->savedLength);
476 }
477 *len = cx->savedLength;
478 }
479 if (data != NULL) {
480 if (cx->ownSession) {
481 PORT_ZFree(data, length);
482 }
483 return SECSuccess;
484 } else {
485 return SECFailure;
486 }
487 }
488
489 /* same as above, but may allocate the return buffer. */
490 unsigned char *
491 PK11_SaveContextAlloc(PK11Context *cx,
492 unsigned char *preAllocBuf, unsigned int pabLen,
493 unsigned int *stateLen)
494 {
495 unsigned char *stateBuf = NULL;
496 unsigned long length = (unsigned long)pabLen;
497
498 if (cx->ownSession) {
499 PK11_EnterContextMonitor(cx);
500 stateBuf = pk11_saveContextHelper(cx, preAllocBuf, &length);
501 PK11_ExitContextMonitor(cx);
502 *stateLen = (stateBuf != NULL) ? length : 0;
503 } else {
504 if (pabLen < cx->savedLength) {
505 stateBuf = (unsigned char *)PORT_Alloc(cx->savedLength);
506 if (!stateBuf) {
507 return (unsigned char *)NULL;
508 }
509 } else {
510 stateBuf = preAllocBuf;
511 }
512 if (cx->savedData) {
513 PORT_Memcpy(stateBuf, cx->savedData, cx->savedLength);
514 }
515 *stateLen = cx->savedLength;
516 }
517 return stateBuf;
518 }
519
520 /*
521 * restore the context state into a new running context. Also required for
522 * FORTEZZA .
523 */
524 SECStatus
525 PK11_RestoreContext(PK11Context *cx,unsigned char *save,int len)
526 {
527 SECStatus rv = SECSuccess;
528 if (cx->ownSession) {
529 PK11_EnterContextMonitor(cx);
530 pk11_Finalize(cx);
531 rv = pk11_restoreContext(cx,save,len);
532 PK11_ExitContextMonitor(cx);
533 } else {
534 PORT_Assert(cx->savedData != NULL);
535 if ((cx->savedData == NULL) || (cx->savedLength < (unsigned) len)) {
536 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
537 rv = SECFailure;
538 } else {
539 PORT_Memcpy(cx->savedData,save,len);
540 cx->savedLength = len;
541 }
542 }
543 return rv;
544 }
545
546 /*
547 * This is to get FIPS compliance until we can convert
548 * libjar to use PK11_ hashing functions. It returns PR_FALSE
549 * if we can't get a PK11 Context.
550 */
551 PRBool
552 PK11_HashOK(SECOidTag algID) {
553 PK11Context *cx;
554
555 cx = PK11_CreateDigestContext(algID);
556 if (cx == NULL) return PR_FALSE;
557 PK11_DestroyContext(cx, PR_TRUE);
558 return PR_TRUE;
559 }
560
561
562
563 /*
564 * start a new digesting or Mac'ing operation on this context
565 */
566 SECStatus PK11_DigestBegin(PK11Context *cx)
567 {
568 CK_MECHANISM mech_info;
569 SECStatus rv;
570
571 if (cx->init == PR_TRUE) {
572 return SECSuccess;
573 }
574
575 /*
576 * make sure the old context is clear first
577 */
578 PK11_EnterContextMonitor(cx);
579 pk11_Finalize(cx);
580
581 mech_info.mechanism = cx->type;
582 mech_info.pParameter = cx->param->data;
583 mech_info.ulParameterLen = cx->param->len;
584 rv = pk11_context_init(cx,&mech_info);
585 PK11_ExitContextMonitor(cx);
586
587 if (rv != SECSuccess) {
588 return SECFailure;
589 }
590 cx->init = PR_TRUE;
591 return SECSuccess;
592 }
593
594 SECStatus
595 PK11_HashBuf(SECOidTag hashAlg, unsigned char *out, const unsigned char *in,
596 PRInt32 len) {
597 PK11Context *context;
598 unsigned int max_length;
599 unsigned int out_length;
600 SECStatus rv;
601
602 /* len will be passed to PK11_DigestOp as unsigned. */
603 if (len < 0) {
604 PORT_SetError(SEC_ERROR_INVALID_ARGS);
605 return SECFailure;
606 }
607
608 context = PK11_CreateDigestContext(hashAlg);
609 if (context == NULL) return SECFailure;
610
611 rv = PK11_DigestBegin(context);
612 if (rv != SECSuccess) {
613 PK11_DestroyContext(context, PR_TRUE);
614 return rv;
615 }
616
617 rv = PK11_DigestOp(context, in, len);
618 if (rv != SECSuccess) {
619 PK11_DestroyContext(context, PR_TRUE);
620 return rv;
621 }
622
623 /* XXX This really should have been an argument to this function! */
624 max_length = HASH_ResultLenByOidTag(hashAlg);
625 PORT_Assert(max_length);
626 if (!max_length)
627 max_length = HASH_LENGTH_MAX;
628
629 rv = PK11_DigestFinal(context,out,&out_length,max_length);
630 PK11_DestroyContext(context, PR_TRUE);
631 return rv;
632 }
633
634
635 /*
636 * execute a bulk encryption operation
637 */
638 SECStatus
639 PK11_CipherOp(PK11Context *context, unsigned char * out, int *outlen,
640 int maxout, const unsigned char *in, int inlen)
641 {
642 CK_RV crv = CKR_OK;
643 CK_ULONG length = maxout;
644 CK_ULONG offset =0;
645 SECStatus rv = SECSuccess;
646 unsigned char *saveOut = out;
647 unsigned char *allocOut = NULL;
648
649 /* if we ran out of session, we need to restore our previously stored
650 * state.
651 */
652 PK11_EnterContextMonitor(context);
653 if (!context->ownSession) {
654 rv = pk11_restoreContext(context,context->savedData,
655 context->savedLength);
656 if (rv != SECSuccess) {
657 PK11_ExitContextMonitor(context);
658 return rv;
659 }
660 }
661
662 /*
663 * The fortezza hack is to send 8 extra bytes on the first encrypted and
664 * lose them on the first decrypt.
665 */
666 if (context->fortezzaHack) {
667 unsigned char random[8];
668 if (context->operation == CKA_ENCRYPT) {
669 PK11_ExitContextMonitor(context);
670 rv = PK11_GenerateRandom(random,sizeof(random));
671 PK11_EnterContextMonitor(context);
672
673 /* since we are offseting the output, we can't encrypt back into
674 * the same buffer... allocate a temporary buffer just for this
675 * call. */
676 allocOut = out = (unsigned char*)PORT_Alloc(maxout);
677 if (out == NULL) {
678 PK11_ExitContextMonitor(context);
679 return SECFailure;
680 }
681 crv = PK11_GETTAB(context->slot)->C_EncryptUpdate(context->session,
682 random,sizeof(random),out,&length);
683
684 out += length;
685 maxout -= length;
686 offset = length;
687 } else if (context->operation == CKA_DECRYPT) {
688 length = sizeof(random);
689 crv = PK11_GETTAB(context->slot)->C_DecryptUpdate(context->session,
690 (CK_BYTE_PTR)in,sizeof(random),random,&length);
691 inlen -= length;
692 in += length;
693 context->fortezzaHack = PR_FALSE;
694 }
695 }
696
697 switch (context->operation) {
698 case CKA_ENCRYPT:
699 length = maxout;
700 crv=PK11_GETTAB(context->slot)->C_EncryptUpdate(context->session,
701 (CK_BYTE_PTR)in, inlen,
702 out, &length);
703 length += offset;
704 break;
705 case CKA_DECRYPT:
706 length = maxout;
707 crv=PK11_GETTAB(context->slot)->C_DecryptUpdate(context->session,
708 (CK_BYTE_PTR)in, inlen,
709 out, &length);
710 break;
711 default:
712 crv = CKR_OPERATION_NOT_INITIALIZED;
713 break;
714 }
715
716 if (crv != CKR_OK) {
717 PORT_SetError( PK11_MapError(crv) );
718 *outlen = 0;
719 rv = SECFailure;
720 } else {
721 *outlen = length;
722 }
723
724 if (context->fortezzaHack) {
725 if (context->operation == CKA_ENCRYPT) {
726 PORT_Assert(allocOut);
727 PORT_Memcpy(saveOut, allocOut, length);
728 PORT_Free(allocOut);
729 }
730 context->fortezzaHack = PR_FALSE;
731 }
732
733 /*
734 * handle session starvation case.. use our last session to multiplex
735 */
736 if (!context->ownSession) {
737 context->savedData = pk11_saveContext(context,context->savedData,
738 &context->savedLength);
739 if (context->savedData == NULL) rv = SECFailure;
740
741 /* clear out out session for others to use */
742 pk11_Finalize(context);
743 }
744 PK11_ExitContextMonitor(context);
745 return rv;
746 }
747
748 /*
749 * execute a digest/signature operation
750 */
751 SECStatus
752 PK11_DigestOp(PK11Context *context, const unsigned char * in, unsigned inLen)
753 {
754 CK_RV crv = CKR_OK;
755 SECStatus rv = SECSuccess;
756
757 if (!in) {
758 PORT_SetError(SEC_ERROR_INVALID_ARGS);
759 return SECFailure;
760 }
761
762 /* if we ran out of session, we need to restore our previously stored
763 * state.
764 */
765 context->init = PR_FALSE;
766 PK11_EnterContextMonitor(context);
767 if (!context->ownSession) {
768 rv = pk11_restoreContext(context,context->savedData,
769 context->savedLength);
770 if (rv != SECSuccess) {
771 PK11_ExitContextMonitor(context);
772 return rv;
773 }
774 }
775
776 switch (context->operation) {
777 /* also for MAC'ing */
778 case CKA_SIGN:
779 crv=PK11_GETTAB(context->slot)->C_SignUpdate(context->session,
780 (unsigned char *)in,
781 inLen);
782 break;
783 case CKA_VERIFY:
784 crv=PK11_GETTAB(context->slot)->C_VerifyUpdate(context->session,
785 (unsigned char *)in,
786 inLen);
787 break;
788 case CKA_DIGEST:
789 crv=PK11_GETTAB(context->slot)->C_DigestUpdate(context->session,
790 (unsigned char *)in,
791 inLen);
792 break;
793 default:
794 crv = CKR_OPERATION_NOT_INITIALIZED;
795 break;
796 }
797
798 if (crv != CKR_OK) {
799 PORT_SetError( PK11_MapError(crv) );
800 rv = SECFailure;
801 }
802
803 /*
804 * handle session starvation case.. use our last session to multiplex
805 */
806 if (!context->ownSession) {
807 context->savedData = pk11_saveContext(context,context->savedData,
808 &context->savedLength);
809 if (context->savedData == NULL) rv = SECFailure;
810
811 /* clear out out session for others to use */
812 pk11_Finalize(context);
813 }
814 PK11_ExitContextMonitor(context);
815 return rv;
816 }
817
818 /*
819 * Digest a key if possible./
820 */
821 SECStatus
822 PK11_DigestKey(PK11Context *context, PK11SymKey *key)
823 {
824 CK_RV crv = CKR_OK;
825 SECStatus rv = SECSuccess;
826 PK11SymKey *newKey = NULL;
827
828 if (!context || !key) {
829 PORT_SetError(SEC_ERROR_INVALID_ARGS);
830 return SECFailure;
831 }
832
833 /* if we ran out of session, we need to restore our previously stored
834 * state.
835 */
836 if (context->slot != key->slot) {
837 newKey = pk11_CopyToSlot(context->slot,CKM_SSL3_SHA1_MAC,CKA_SIGN,key);
838 } else {
839 newKey = PK11_ReferenceSymKey(key);
840 }
841
842 context->init = PR_FALSE;
843 PK11_EnterContextMonitor(context);
844 if (!context->ownSession) {
845 rv = pk11_restoreContext(context,context->savedData,
846 context->savedLength);
847 if (rv != SECSuccess) {
848 PK11_ExitContextMonitor(context);
849 PK11_FreeSymKey(newKey);
850 return rv;
851 }
852 }
853
854
855 if (newKey == NULL) {
856 crv = CKR_KEY_TYPE_INCONSISTENT;
857 if (key->data.data) {
858 crv=PK11_GETTAB(context->slot)->C_DigestUpdate(context->session,
859 key->data.data,key->data.len);
860 }
861 } else {
862 crv=PK11_GETTAB(context->slot)->C_DigestKey(context->session,
863 newKey->objectID);
864 }
865
866 if (crv != CKR_OK) {
867 PORT_SetError( PK11_MapError(crv) );
868 rv = SECFailure;
869 }
870
871 /*
872 * handle session starvation case.. use our last session to multiplex
873 */
874 if (!context->ownSession) {
875 context->savedData = pk11_saveContext(context,context->savedData,
876 &context->savedLength);
877 if (context->savedData == NULL) rv = SECFailure;
878
879 /* clear out out session for others to use */
880 pk11_Finalize(context);
881 }
882 PK11_ExitContextMonitor(context);
883 if (newKey) PK11_FreeSymKey(newKey);
884 return rv;
885 }
886
887 /*
888 * externally callable version of the lowercase pk11_finalize().
889 */
890 SECStatus
891 PK11_Finalize(PK11Context *context) {
892 SECStatus rv;
893
894 PK11_EnterContextMonitor(context);
895 rv = pk11_Finalize(context);
896 PK11_ExitContextMonitor(context);
897 return rv;
898 }
899
900 /*
901 * clean up a cipher operation, so the session can be used by
902 * someone new.
903 */
904 SECStatus
905 pk11_Finalize(PK11Context *context)
906 {
907 CK_ULONG count = 0;
908 CK_RV crv;
909 unsigned char stackBuf[256];
910 unsigned char *buffer = NULL;
911
912 if (!context->ownSession) {
913 return SECSuccess;
914 }
915
916 finalize:
917 switch (context->operation) {
918 case CKA_ENCRYPT:
919 crv=PK11_GETTAB(context->slot)->C_EncryptFinal(context->session,
920 buffer, &count);
921 break;
922 case CKA_DECRYPT:
923 crv = PK11_GETTAB(context->slot)->C_DecryptFinal(context->session,
924 buffer, &count);
925 break;
926 case CKA_SIGN:
927 crv=PK11_GETTAB(context->slot)->C_SignFinal(context->session,
928 buffer, &count);
929 break;
930 case CKA_VERIFY:
931 crv=PK11_GETTAB(context->slot)->C_VerifyFinal(context->session,
932 buffer, count);
933 break;
934 case CKA_DIGEST:
935 crv=PK11_GETTAB(context->slot)->C_DigestFinal(context->session,
936 buffer, &count);
937 break;
938 default:
939 crv = CKR_OPERATION_NOT_INITIALIZED;
940 break;
941 }
942
943 if (crv != CKR_OK) {
944 if (buffer != stackBuf) {
945 PORT_Free(buffer);
946 }
947 if (crv == CKR_OPERATION_NOT_INITIALIZED) {
948 /* if there's no operation, it is finalized */
949 return SECSuccess;
950 }
951 PORT_SetError( PK11_MapError(crv) );
952 return SECFailure;
953 }
954
955 /* try to finalize the session with a buffer */
956 if (buffer == NULL) {
957 if (count <= sizeof stackBuf) {
958 buffer = stackBuf;
959 } else {
960 buffer = PORT_Alloc(count);
961 if (buffer == NULL) {
962 PORT_SetError(SEC_ERROR_NO_MEMORY);
963 return SECFailure;
964 }
965 }
966 goto finalize;
967 }
968 if (buffer != stackBuf) {
969 PORT_Free(buffer);
970 }
971 return SECSuccess;
972 }
973
974 /*
975 * Return the final digested or signed data...
976 * this routine can either take pre initialized data, or allocate data
977 * either out of an arena or out of the standard heap.
978 */
979 SECStatus
980 PK11_DigestFinal(PK11Context *context,unsigned char *data,
981 unsigned int *outLen, unsigned int length)
982 {
983 CK_ULONG len;
984 CK_RV crv;
985 SECStatus rv;
986
987
988 /* if we ran out of session, we need to restore our previously stored
989 * state.
990 */
991 PK11_EnterContextMonitor(context);
992 if (!context->ownSession) {
993 rv = pk11_restoreContext(context,context->savedData,
994 context->savedLength);
995 if (rv != SECSuccess) {
996 PK11_ExitContextMonitor(context);
997 return rv;
998 }
999 }
1000
1001 len = length;
1002 switch (context->operation) {
1003 case CKA_SIGN:
1004 crv=PK11_GETTAB(context->slot)->C_SignFinal(context->session,
1005 data,&len);
1006 break;
1007 case CKA_VERIFY:
1008 crv=PK11_GETTAB(context->slot)->C_VerifyFinal(context->session,
1009 data,len);
1010 break;
1011 case CKA_DIGEST:
1012 crv=PK11_GETTAB(context->slot)->C_DigestFinal(context->session,
1013 data,&len);
1014 break;
1015 case CKA_ENCRYPT:
1016 crv=PK11_GETTAB(context->slot)->C_EncryptFinal(context->session,
1017 data, &len);
1018 break;
1019 case CKA_DECRYPT:
1020 crv = PK11_GETTAB(context->slot)->C_DecryptFinal(context->session,
1021 data, &len);
1022 break;
1023 default:
1024 crv = CKR_OPERATION_NOT_INITIALIZED;
1025 break;
1026 }
1027 PK11_ExitContextMonitor(context);
1028
1029 *outLen = (unsigned int) len;
1030 context->init = PR_FALSE; /* allow Begin to start up again */
1031
1032
1033 if (crv != CKR_OK) {
1034 PORT_SetError( PK11_MapError(crv) );
1035 return SECFailure;
1036 }
1037 return SECSuccess;
1038 }
1039
OLDNEW
« no previous file with comments | « mozilla/security/nss/lib/pk11wrap/pk11cert.c ('k') | mozilla/security/nss/lib/pk11wrap/pk11err.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698