Bug Summary

File:s/lib/pk11wrap/pk11cxt.c
Warning:line 896, column 13
Value stored to 'crv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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