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

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

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 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
« no previous file with comments | « nss/lib/pk11wrap/pk11cert.c ('k') | nss/lib/pk11wrap/pk11err.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 (inLen == 0) {
758 return SECSuccess;
759 }
760 if (!in) {
761 PORT_SetError(SEC_ERROR_INVALID_ARGS);
762 return SECFailure;
763 }
764
765 /* if we ran out of session, we need to restore our previously stored
766 * state.
767 */
768 context->init = PR_FALSE;
769 PK11_EnterContextMonitor(context);
770 if (!context->ownSession) {
771 rv = pk11_restoreContext(context,context->savedData,
772 context->savedLength);
773 if (rv != SECSuccess) {
774 PK11_ExitContextMonitor(context);
775 return rv;
776 }
777 }
778
779 switch (context->operation) {
780 /* also for MAC'ing */
781 case CKA_SIGN:
782 crv=PK11_GETTAB(context->slot)->C_SignUpdate(context->session,
783 (unsigned char *)in,
784 inLen);
785 break;
786 case CKA_VERIFY:
787 crv=PK11_GETTAB(context->slot)->C_VerifyUpdate(context->session,
788 (unsigned char *)in,
789 inLen);
790 break;
791 case CKA_DIGEST:
792 crv=PK11_GETTAB(context->slot)->C_DigestUpdate(context->session,
793 (unsigned char *)in,
794 inLen);
795 break;
796 default:
797 crv = CKR_OPERATION_NOT_INITIALIZED;
798 break;
799 }
800
801 if (crv != CKR_OK) {
802 PORT_SetError( PK11_MapError(crv) );
803 rv = SECFailure;
804 }
805
806 /*
807 * handle session starvation case.. use our last session to multiplex
808 */
809 if (!context->ownSession) {
810 context->savedData = pk11_saveContext(context,context->savedData,
811 &context->savedLength);
812 if (context->savedData == NULL) rv = SECFailure;
813
814 /* clear out out session for others to use */
815 pk11_Finalize(context);
816 }
817 PK11_ExitContextMonitor(context);
818 return rv;
819 }
820
821 /*
822 * Digest a key if possible./
823 */
824 SECStatus
825 PK11_DigestKey(PK11Context *context, PK11SymKey *key)
826 {
827 CK_RV crv = CKR_OK;
828 SECStatus rv = SECSuccess;
829 PK11SymKey *newKey = NULL;
830
831 if (!context || !key) {
832 PORT_SetError(SEC_ERROR_INVALID_ARGS);
833 return SECFailure;
834 }
835
836 /* if we ran out of session, we need to restore our previously stored
837 * state.
838 */
839 if (context->slot != key->slot) {
840 newKey = pk11_CopyToSlot(context->slot,CKM_SSL3_SHA1_MAC,CKA_SIGN,key);
841 } else {
842 newKey = PK11_ReferenceSymKey(key);
843 }
844
845 context->init = PR_FALSE;
846 PK11_EnterContextMonitor(context);
847 if (!context->ownSession) {
848 rv = pk11_restoreContext(context,context->savedData,
849 context->savedLength);
850 if (rv != SECSuccess) {
851 PK11_ExitContextMonitor(context);
852 PK11_FreeSymKey(newKey);
853 return rv;
854 }
855 }
856
857
858 if (newKey == NULL) {
859 crv = CKR_KEY_TYPE_INCONSISTENT;
860 if (key->data.data) {
861 crv=PK11_GETTAB(context->slot)->C_DigestUpdate(context->session,
862 key->data.data,key->data.len);
863 }
864 } else {
865 crv=PK11_GETTAB(context->slot)->C_DigestKey(context->session,
866 newKey->objectID);
867 }
868
869 if (crv != CKR_OK) {
870 PORT_SetError( PK11_MapError(crv) );
871 rv = SECFailure;
872 }
873
874 /*
875 * handle session starvation case.. use our last session to multiplex
876 */
877 if (!context->ownSession) {
878 context->savedData = pk11_saveContext(context,context->savedData,
879 &context->savedLength);
880 if (context->savedData == NULL) rv = SECFailure;
881
882 /* clear out out session for others to use */
883 pk11_Finalize(context);
884 }
885 PK11_ExitContextMonitor(context);
886 if (newKey) PK11_FreeSymKey(newKey);
887 return rv;
888 }
889
890 /*
891 * externally callable version of the lowercase pk11_finalize().
892 */
893 SECStatus
894 PK11_Finalize(PK11Context *context) {
895 SECStatus rv;
896
897 PK11_EnterContextMonitor(context);
898 rv = pk11_Finalize(context);
899 PK11_ExitContextMonitor(context);
900 return rv;
901 }
902
903 /*
904 * clean up a cipher operation, so the session can be used by
905 * someone new.
906 */
907 SECStatus
908 pk11_Finalize(PK11Context *context)
909 {
910 CK_ULONG count = 0;
911 CK_RV crv;
912 unsigned char stackBuf[256];
913 unsigned char *buffer = NULL;
914
915 if (!context->ownSession) {
916 return SECSuccess;
917 }
918
919 finalize:
920 switch (context->operation) {
921 case CKA_ENCRYPT:
922 crv=PK11_GETTAB(context->slot)->C_EncryptFinal(context->session,
923 buffer, &count);
924 break;
925 case CKA_DECRYPT:
926 crv = PK11_GETTAB(context->slot)->C_DecryptFinal(context->session,
927 buffer, &count);
928 break;
929 case CKA_SIGN:
930 crv=PK11_GETTAB(context->slot)->C_SignFinal(context->session,
931 buffer, &count);
932 break;
933 case CKA_VERIFY:
934 crv=PK11_GETTAB(context->slot)->C_VerifyFinal(context->session,
935 buffer, count);
936 break;
937 case CKA_DIGEST:
938 crv=PK11_GETTAB(context->slot)->C_DigestFinal(context->session,
939 buffer, &count);
940 break;
941 default:
942 crv = CKR_OPERATION_NOT_INITIALIZED;
943 break;
944 }
945
946 if (crv != CKR_OK) {
947 if (buffer != stackBuf) {
948 PORT_Free(buffer);
949 }
950 if (crv == CKR_OPERATION_NOT_INITIALIZED) {
951 /* if there's no operation, it is finalized */
952 return SECSuccess;
953 }
954 PORT_SetError( PK11_MapError(crv) );
955 return SECFailure;
956 }
957
958 /* try to finalize the session with a buffer */
959 if (buffer == NULL) {
960 if (count <= sizeof stackBuf) {
961 buffer = stackBuf;
962 } else {
963 buffer = PORT_Alloc(count);
964 if (buffer == NULL) {
965 PORT_SetError(SEC_ERROR_NO_MEMORY);
966 return SECFailure;
967 }
968 }
969 goto finalize;
970 }
971 if (buffer != stackBuf) {
972 PORT_Free(buffer);
973 }
974 return SECSuccess;
975 }
976
977 /*
978 * Return the final digested or signed data...
979 * this routine can either take pre initialized data, or allocate data
980 * either out of an arena or out of the standard heap.
981 */
982 SECStatus
983 PK11_DigestFinal(PK11Context *context,unsigned char *data,
984 unsigned int *outLen, unsigned int length)
985 {
986 CK_ULONG len;
987 CK_RV crv;
988 SECStatus rv;
989
990
991 /* if we ran out of session, we need to restore our previously stored
992 * state.
993 */
994 PK11_EnterContextMonitor(context);
995 if (!context->ownSession) {
996 rv = pk11_restoreContext(context,context->savedData,
997 context->savedLength);
998 if (rv != SECSuccess) {
999 PK11_ExitContextMonitor(context);
1000 return rv;
1001 }
1002 }
1003
1004 len = length;
1005 switch (context->operation) {
1006 case CKA_SIGN:
1007 crv=PK11_GETTAB(context->slot)->C_SignFinal(context->session,
1008 data,&len);
1009 break;
1010 case CKA_VERIFY:
1011 crv=PK11_GETTAB(context->slot)->C_VerifyFinal(context->session,
1012 data,len);
1013 break;
1014 case CKA_DIGEST:
1015 crv=PK11_GETTAB(context->slot)->C_DigestFinal(context->session,
1016 data,&len);
1017 break;
1018 case CKA_ENCRYPT:
1019 crv=PK11_GETTAB(context->slot)->C_EncryptFinal(context->session,
1020 data, &len);
1021 break;
1022 case CKA_DECRYPT:
1023 crv = PK11_GETTAB(context->slot)->C_DecryptFinal(context->session,
1024 data, &len);
1025 break;
1026 default:
1027 crv = CKR_OPERATION_NOT_INITIALIZED;
1028 break;
1029 }
1030 PK11_ExitContextMonitor(context);
1031
1032 *outLen = (unsigned int) len;
1033 context->init = PR_FALSE; /* allow Begin to start up again */
1034
1035
1036 if (crv != CKR_OK) {
1037 PORT_SetError( PK11_MapError(crv) );
1038 return SECFailure;
1039 }
1040 return SECSuccess;
1041 }
1042
OLDNEW
« no previous file with comments | « nss/lib/pk11wrap/pk11cert.c ('k') | nss/lib/pk11wrap/pk11err.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698