Bug Summary

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