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