Bug Summary

File:root/firefox-clang/security/nss/lib/pk11wrap/pk11cxt.c
Warning:line 912, 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-10-17-231001-351276-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 * start a new digesting or Mac'ing operation on this context
787 */
788SECStatus
789PK11_DigestBegin(PK11Context *cx)
790{
791 CK_MECHANISM mech_info;
792 SECStatus rv;
793
794 if (cx->init == PR_TRUE1) {
795 return SECSuccess;
796 }
797
798 /*
799 * make sure the old context is clear first
800 */
801 PK11_EnterContextMonitor(cx);
802 pk11_Finalize(cx);
803 PK11_ExitContextMonitor(cx);
804
805 mech_info.mechanism = cx->type;
806 mech_info.pParameter = cx->param->data;
807 mech_info.ulParameterLen = cx->param->len;
808 rv = pk11_context_init(cx, &mech_info, NULL((void*)0));
809
810 if (rv != SECSuccess) {
811 return SECFailure;
812 }
813 cx->init = PR_TRUE1;
814 return SECSuccess;
815}
816
817SECStatus
818PK11_HashBuf(SECOidTag hashAlg, unsigned char *out, const unsigned char *in,
819 PRInt32 len)
820{
821 PK11Context *context;
822 unsigned int max_length;
823 unsigned int out_length;
824 SECStatus rv;
825
826 /* len will be passed to PK11_DigestOp as unsigned. */
827 if (len < 0) {
828 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
829 return SECFailure;
830 }
831
832 context = PK11_CreateDigestContext(hashAlg);
833 if (context == NULL((void*)0))
834 return SECFailure;
835
836 rv = PK11_DigestBegin(context);
837 if (rv != SECSuccess) {
838 PK11_DestroyContext(context, PR_TRUE1);
839 return rv;
840 }
841
842 rv = PK11_DigestOp(context, in, len);
843 if (rv != SECSuccess) {
844 PK11_DestroyContext(context, PR_TRUE1);
845 return rv;
846 }
847
848 /* XXX This really should have been an argument to this function! */
849 max_length = HASH_ResultLenByOidTag(hashAlg);
850 PORT_Assert(max_length)((max_length) ? ((void)0) : PR_Assert("max_length", "/root/firefox-clang/security/nss/lib/pk11wrap/pk11cxt.c"
, 850))
;
851 if (!max_length)
852 max_length = HASH_LENGTH_MAX64;
853
854 rv = PK11_DigestFinal(context, out, &out_length, max_length);
855 PK11_DestroyContext(context, PR_TRUE1);
856 return rv;
857}
858
859/*
860 * execute a bulk encryption operation
861 */
862SECStatus
863PK11_CipherOp(PK11Context *context, unsigned char *out, int *outlen,
864 int maxout, const unsigned char *in, int inlen)
865{
866 CK_RV crv = CKR_OK0x00000000UL;
867 CK_ULONG length = maxout;
868 CK_ULONG offset = 0;
869 SECStatus rv = SECSuccess;
870 unsigned char *saveOut = out;
871 unsigned char *allocOut = NULL((void*)0);
872
873 /* if we ran out of session, we need to restore our previously stored
874 * state.
875 */
876 PK11_EnterContextMonitor(context);
877 if (!context->ownSession) {
878 rv = pk11_restoreContext(context, context->savedData,
879 context->savedLength);
880 if (rv != SECSuccess) {
881 PK11_ExitContextMonitor(context);
882 return rv;
883 }
884 }
885
886 /*
887 * The fortezza hack is to send 8 extra bytes on the first encrypted and
888 * lose them on the first decrypt.
889 */
890 if (context->fortezzaHack) {
891 unsigned char random[8];
892 if (context->operation == CKA_ENCRYPT0x00000104UL) {
893 PK11_ExitContextMonitor(context);
894 rv = PK11_GenerateRandom(random, sizeof(random));
895 PK11_EnterContextMonitor(context);
896
897 /* since we are offseting the output, we can't encrypt back into
898 * the same buffer... allocate a temporary buffer just for this
899 * call. */
900 allocOut = out = (unsigned char *)PORT_AllocPORT_Alloc_Util(maxout);
901 if (out == NULL((void*)0)) {
902 PK11_ExitContextMonitor(context);
903 return SECFailure;
904 }
905 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_EncryptUpdate(context->session, random, sizeof(random), out, &length);
906
907 out += length;
908 maxout -= length;
909 offset = length;
910 } else if (context->operation == CKA_DECRYPT0x00000105UL) {
911 length = sizeof(random);
912 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
913 inlen -= length;
914 in += length;
915 context->fortezzaHack = PR_FALSE0;
916 }
917 }
918
919 switch (context->operation) {
920 case CKA_ENCRYPT0x00000104UL:
921 length = maxout;
922 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);
923 length += offset;
924 break;
925 case CKA_DECRYPT0x00000105UL:
926 length = maxout;
927 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);
928 break;
929 default:
930 crv = CKR_OPERATION_NOT_INITIALIZED0x00000091UL;
931 break;
932 }
933
934 if (crv != CKR_OK0x00000000UL) {
935 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
936 *outlen = 0;
937 rv = SECFailure;
938 } else {
939 *outlen = length;
940 }
941
942 if (context->fortezzaHack) {
943 if (context->operation == CKA_ENCRYPT0x00000104UL) {
944 PORT_Assert(allocOut)((allocOut) ? ((void)0) : PR_Assert("allocOut", "/root/firefox-clang/security/nss/lib/pk11wrap/pk11cxt.c"
, 944))
;
945 PORT_Memcpymemcpy(saveOut, allocOut, length);
946 PORT_FreePORT_Free_Util(allocOut);
947 }
948 context->fortezzaHack = PR_FALSE0;
949 }
950
951 /*
952 * handle session starvation case.. use our last session to multiplex
953 */
954 if (!context->ownSession) {
955 context->savedData = pk11_saveContext(context, context->savedData,
956 &context->savedLength);
957 if (context->savedData == NULL((void*)0))
958 rv = SECFailure;
959
960 /* clear out out session for others to use */
961 pk11_Finalize(context);
962 }
963 PK11_ExitContextMonitor(context);
964 return rv;
965}
966
967/*
968 * Simulate the IV generation that normally would happen in the token.
969 *
970 * This is a modifed copy of what is in freebl/gcm.c. We can't use the
971 * version in freebl because of layering, since freebl is inside the token
972 * boundary. These issues are traditionally handled by moving them to util,
973 * but we also have two different Random functions we have two switch between.
974 * Since this is primarily here for tokens that don't support the PKCS #11
975 * Message Interface, it's OK if they diverge a bit. Slight semantic
976 * differences from the freebl/gcm.c version shouldn't be much more than the
977 * sematic differences between freebl and other tokens which do implement the
978 * Message Interface. */
979static SECStatus
980pk11_GenerateIV(PK11Context *context, CK_GENERATOR_FUNCTION ivgen,
981 int fixedBits, unsigned char *iv, int ivLen)
982{
983 unsigned int i;
984 unsigned int flexBits;
985 unsigned int ivOffset;
986 unsigned int ivNewCount;
987 unsigned char ivMask;
988 unsigned char ivSave;
989 SECStatus rv;
990
991 if (context->ivCounter != 0) {
992 /* If we've already generated a message, make sure all subsequent
993 * messages are using the same generator */
994 if ((context->ivGen != ivgen) ||
995 (context->ivFixedBits != fixedBits) ||
996 (context->ivLen != ivLen)) {
997 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
998 return SECFailure;
999 }
1000 } else {
1001 /* remember these values */
1002 context->ivGen = ivgen;
1003 context->ivFixedBits = fixedBits;
1004 context->ivLen = ivLen;
1005 /* now calculate how may bits of IV we have to supply */
1006 flexBits = ivLen * PR_BITS_PER_BYTE8;
1007 /* first make sure we aren't going to overflow */
1008 if (flexBits < fixedBits) {
1009 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1010 return SECFailure;
1011 }
1012 flexBits -= fixedBits;
1013 /* if we are generating a random number reduce the acceptable bits to
1014 * avoid birthday attacks */
1015 if (ivgen == CKG_GENERATE_RANDOM0x00000003UL) {
1016 if (flexBits <= GCMIV_RANDOM_BIRTHDAY_BITS64) {
1017 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1018 return SECFailure;
1019 }
1020 /* see freebl/blapit.h for how GCMIV_RANDOM_BIRTHDAY_BITS is
1021 * calculated. */
1022 flexBits -= GCMIV_RANDOM_BIRTHDAY_BITS64;
1023 flexBits = flexBits >> 1;
1024 }
1025 if (flexBits == 0) {
1026 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1027 return SECFailure;
1028 }
1029 /* Turn those bits into the number of IV's we can safely return */
1030 if (flexBits >= sizeof(context->ivMaxCount) * PR_BITS_PER_BYTE8) {
1031 context->ivMaxCount = PR_UINT64(0xffffffffffffffff)0xffffffffffffffffUL;
1032 } else {
1033 context->ivMaxCount = (PR_UINT64(1)1UL << flexBits);
1034 }
1035 }
1036
1037 /* no generate, accept the IV from the source */
1038 if (ivgen == CKG_NO_GENERATE0x00000000UL) {
1039 context->ivCounter = 1;
1040 return SECSuccess;
1041 }
1042
1043 /* make sure we haven't exceeded the number of IVs we can return
1044 * for this key, generator, and IV size */
1045 if (context->ivCounter >= context->ivMaxCount) {
1046 /* use a unique error from just bad user input */
1047 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_EXTRA_INPUT);
1048 return SECFailure;
1049 }
1050
1051 /* build to mask to handle the first byte of the IV */
1052 ivOffset = fixedBits / PR_BITS_PER_BYTE8;
1053 ivMask = 0xff >> ((PR_BITS_PER_BYTE8 - (fixedBits & 7)) & 7);
1054 ivNewCount = ivLen - ivOffset;
1055
1056 /* finally generate the IV */
1057 switch (ivgen) {
1058 case CKG_GENERATE0x00000001UL: /* default to counter */
1059 case CKG_GENERATE_COUNTER0x00000002UL:
1060 iv[ivOffset] = (iv[ivOffset] & ~ivMask) |
1061 (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);
1062 for (i = 1; i < ivNewCount; i++) {
1063 iv[ivOffset + i] =
1064 PORT_GET_BYTE_BE(context->ivCounter, i, ivNewCount)((unsigned char)(((ivNewCount) - (i) - 1) >= sizeof(context
->ivCounter) ? 0 : (((context->ivCounter) >> (((ivNewCount
) - (i) - 1) * 8)) & 0xff)))
;
1065 }
1066 break;
1067 case CKG_GENERATE_COUNTER_XOR0x00000004UL:
1068 iv[ivOffset] ^=
1069 (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);
1070 for (i = 1; i < ivNewCount; i++) {
1071 iv[ivOffset + i] ^=
1072 PORT_GET_BYTE_BE(context->ivCounter, i, ivNewCount)((unsigned char)(((ivNewCount) - (i) - 1) >= sizeof(context
->ivCounter) ? 0 : (((context->ivCounter) >> (((ivNewCount
) - (i) - 1) * 8)) & 0xff)))
;
1073 }
1074 break;
1075 case CKG_GENERATE_RANDOM0x00000003UL:
1076 ivSave = iv[ivOffset] & ~ivMask;
1077 rv = PK11_GenerateRandom(iv + ivOffset, ivNewCount);
1078 iv[ivOffset] = ivSave | (iv[ivOffset] & ivMask);
1079 if (rv != SECSuccess) {
1080 return rv;
1081 }
1082 break;
1083 }
1084 context->ivCounter++;
1085 return SECSuccess;
1086}
1087
1088/*
1089 * PKCS #11 v2.40 did not have a message interface. If our module can't
1090 * do the message interface use the old method of doing AEAD */
1091static SECStatus
1092pk11_AEADSimulateOp(PK11Context *context, void *params, int paramslen,
1093 const unsigned char *aad, int aadlen,
1094 unsigned char *out, int *outlen,
1095 int maxout, const unsigned char *in, int inlen)
1096{
1097 unsigned int length = maxout;
1098 SECStatus rv = SECSuccess;
1099 unsigned char *saveOut = out;
1100 unsigned char *allocOut = NULL((void*)0);
1101
1102 /*
1103 * first we need to convert the single shot (v2.40) parameters into
1104 * the message version of the parameters. This usually involves
1105 * copying the Nonce or IV, setting the AAD from our parameter list
1106 * and handling the tag differences */
1107 CK_GCM_PARAMS_V3 gcm;
1108 CK_GCM_MESSAGE_PARAMS *gcm_message;
1109 CK_CCM_PARAMS ccm;
1110 CK_CCM_MESSAGE_PARAMS *ccm_message;
1111 CK_SALSA20_CHACHA20_POLY1305_PARAMS chacha_poly;
1112 CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS *chacha_poly_message;
1113 CK_NSS_AEAD_PARAMS nss_chacha_poly;
1114 CK_MECHANISM_TYPE mechanism = context->simulate_mechanism;
1115 SECItem sim_params = { 0, NULL((void*)0), 0 };
1116 unsigned char *tag = NULL((void*)0);
1117 unsigned int taglen;
1118 PRBool encrypt;
1119
1120 *outlen = 0;
1121 /* figure out if we are encrypting or decrypting, as tags are
1122 * handled differently in both */
1123 switch (context->operation) {
1124 case CKA_NSS_MESSAGE0x82000000L | CKA_ENCRYPT0x00000104UL:
1125 encrypt = PR_TRUE1;
1126 break;
1127 case CKA_NSS_MESSAGE0x82000000L | CKA_DECRYPT0x00000105UL:
1128 encrypt = PR_FALSE0;
1129 break;
1130 default:
1131 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1132 return SECFailure;
1133 }
1134
1135 switch (mechanism) {
1136 case CKM_CHACHA20_POLY13050x00004021UL:
1137 case CKM_SALSA20_POLY13050x00004022UL:
1138 if (paramslen != sizeof(CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS)) {
1139 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1140 return SECFailure;
1141 }
1142 chacha_poly_message =
1143 (CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS *)params;
1144 chacha_poly.pNonce = chacha_poly_message->pNonce;
1145 chacha_poly.ulNonceLen = chacha_poly_message->ulNonceLen;
1146 chacha_poly.pAAD = (CK_BYTE_PTR)aad;
1147 chacha_poly.ulAADLen = aadlen;
1148 tag = chacha_poly_message->pTag;
1149 taglen = 16;
1150 sim_params.data = (unsigned char *)&chacha_poly;
1151 sim_params.len = sizeof(chacha_poly);
1152 /* SALSA20_POLY1305 and CHACHA20_POLY1305 do not generate the iv
1153 * internally, don't simulate it either */
1154 break;
1155 case CKM_NSS_CHACHA20_POLY1305((0x80000000UL | 0x4E534350) + 28):
1156 if (paramslen != sizeof(CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS)) {
1157 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1158 return SECFailure;
1159 }
1160 chacha_poly_message =
1161 (CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS *)params;
1162 tag = chacha_poly_message->pTag;
1163 taglen = 16;
1164 nss_chacha_poly.pNonce = chacha_poly_message->pNonce;
1165 nss_chacha_poly.ulNonceLen = chacha_poly_message->ulNonceLen;
1166 nss_chacha_poly.pAAD = (CK_BYTE_PTR)aad;
1167 nss_chacha_poly.ulAADLen = aadlen;
1168 nss_chacha_poly.ulTagLen = taglen;
1169 sim_params.data = (unsigned char *)&nss_chacha_poly;
1170 sim_params.len = sizeof(nss_chacha_poly);
1171 /* CKM_NSS_CHACHA20_POLY1305 does not generate the iv
1172 * internally, don't simulate it either */
1173 break;
1174 case CKM_AES_CCM0x00001088UL:
1175 if (paramslen != sizeof(CK_CCM_MESSAGE_PARAMS)) {
1176 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1177 return SECFailure;
1178 }
1179 ccm_message = (CK_CCM_MESSAGE_PARAMS *)params;
1180 if (ccm_message->ulMACLen > 16) {
1181 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1182 return SECFailure;
1183 }
1184 ccm.ulDataLen = ccm_message->ulDataLen;
1185 ccm.pNonce = ccm_message->pNonce;
1186 ccm.ulNonceLen = ccm_message->ulNonceLen;
1187 ccm.pAAD = (CK_BYTE_PTR)aad;
1188 ccm.ulAADLen = aadlen;
1189 ccm.ulMACLen = ccm_message->ulMACLen;
1190 tag = ccm_message->pMAC;
1191 taglen = ccm_message->ulMACLen;
1192 sim_params.data = (unsigned char *)&ccm;
1193 sim_params.len = sizeof(ccm);
1194 if (encrypt) {
1195 /* simulate generating the IV */
1196 rv = pk11_GenerateIV(context, ccm_message->nonceGenerator,
1197 ccm_message->ulNonceFixedBits,
1198 ccm_message->pNonce,
1199 ccm_message->ulNonceLen);
1200 if (rv != SECSuccess) {
1201 return rv;
1202 }
1203 }
1204 break;
1205 case CKM_AES_GCM0x00001087UL:
1206 if (paramslen != sizeof(CK_GCM_MESSAGE_PARAMS)) {
1207 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1208 return SECFailure;
1209 }
1210 gcm_message = (CK_GCM_MESSAGE_PARAMS *)params;
1211 if (gcm_message->ulTagBits > 128) {
1212 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1213 return SECFailure;
1214 }
1215 gcm.pIv = gcm_message->pIv;
1216 gcm.ulIvLen = gcm_message->ulIvLen;
1217 gcm.ulIvBits = gcm.ulIvLen * PR_BITS_PER_BYTE8;
1218 gcm.pAAD = (CK_BYTE_PTR)aad;
1219 gcm.ulAADLen = aadlen;
1220 gcm.ulTagBits = gcm_message->ulTagBits;
1221 tag = gcm_message->pTag;
1222 taglen = (gcm_message->ulTagBits + (PR_BITS_PER_BYTE8 - 1)) / PR_BITS_PER_BYTE8;
1223 sim_params.data = (unsigned char *)&gcm;
1224 sim_params.len = sizeof(gcm);
1225 if (encrypt) {
1226 /* simulate generating the IV */
1227 rv = pk11_GenerateIV(context, gcm_message->ivGenerator,
1228 gcm_message->ulIvFixedBits,
1229 gcm_message->pIv, gcm_message->ulIvLen);
1230 if (rv != SECSuccess) {
1231 return rv;
1232 }
1233 }
1234 break;
1235 default:
1236 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ALGORITHM);
1237 return SECFailure;
1238 }
1239 /* now handle the tag. The message interface separates the tag from
1240 * the data, while the single shot gets and puts the tag at the end of
1241 * the encrypted data. */
1242 if (!encrypt) {
1243 /* In the decrypt case, if the tag is already at the end of the
1244 * input buffer we are golden, otherwise we'll need a new input
1245 * buffer and copy the tag at the end of it */
1246 if (tag != in + inlen) {
1247 allocOut = PORT_AllocPORT_Alloc_Util(inlen + taglen);
1248 if (allocOut == NULL((void*)0)) {
1249 return SECFailure;
1250 }
1251 PORT_Memcpymemcpy(allocOut, in, inlen);
1252 PORT_Memcpymemcpy(allocOut + inlen, tag, taglen);
1253 in = allocOut;
1254 }
1255 inlen = inlen + taglen;
1256 } else {
1257 /* if we end up allocating, we don't want to overrun this buffer,
1258 * so we fail early here */
1259 if (maxout < inlen) {
1260 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1261 return SECFailure;
1262 }
1263 /* in the encrypt case, we are fine if maxout is big enough to hold
1264 * the tag. We'll copy the tag after the operation */
1265 if (maxout < inlen + taglen) {
1266 allocOut = PORT_AllocPORT_Alloc_Util(inlen + taglen);
1267 if (allocOut == NULL((void*)0)) {
1268 return SECFailure;
1269 }
1270 out = allocOut;
1271 length = maxout = inlen + taglen;
1272 }
1273 }
1274 /* now do the operation */
1275 if (encrypt) {
1276 rv = PK11_Encrypt(context->key, mechanism, &sim_params, out, &length,
1277 maxout, in, inlen);
1278 } else {
1279 rv = PK11_Decrypt(context->key, mechanism, &sim_params, out, &length,
1280 maxout, in, inlen);
1281 }
1282 if (rv != SECSuccess) {
1283 /* If the mechanism was CKM_AES_GCM, the module may have been
1284 * following the same error as old versions of NSS. Retry with
1285 * the CK_NSS_GCM_PARAMS */
1286 if ((mechanism == CKM_AES_GCM0x00001087UL) &&
1287 (PORT_GetErrorPORT_GetError_Util() == SEC_ERROR_BAD_DATA)) {
1288 CK_NSS_GCM_PARAMS gcm_nss;
1289 gcm_message = (CK_GCM_MESSAGE_PARAMS *)params;
1290 gcm_nss.pIv = gcm_message->pIv;
1291 gcm_nss.ulIvLen = gcm_message->ulIvLen;
1292 gcm_nss.pAAD = (CK_BYTE_PTR)aad;
1293 gcm_nss.ulAADLen = aadlen;
1294 gcm_nss.ulTagBits = gcm_message->ulTagBits;
1295 sim_params.data = (unsigned char *)&gcm_nss;
1296 sim_params.len = sizeof(gcm_nss);
1297 if (encrypt) {
1298 rv = PK11_Encrypt(context->key, mechanism, &sim_params, out,
1299 &length, maxout, in, inlen);
1300 } else {
1301 rv = PK11_Decrypt(context->key, mechanism, &sim_params, out,
1302 &length, maxout, in, inlen);
1303 }
1304 if (rv != SECSuccess) {
1305 goto fail;
1306 }
1307 } else {
1308 goto fail;
1309 }
1310 }
1311
1312 /* on encrypt, separate the output buffer from the tag */
1313 if (encrypt) {
1314 if ((length < taglen) || (length > inlen + taglen)) {
1315 /* PKCS #11 module should not return a length smaller than
1316 * taglen, or bigger than inlen+taglen */
1317 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_LIBRARY_FAILURE);
1318 rv = SECFailure;
1319 goto fail;
1320 }
1321 length = length - taglen;
1322 if (allocOut) {
1323 /*
1324 * If we used a temporary buffer, copy it out to the original
1325 * buffer.
1326 */
1327 PORT_Memcpymemcpy(saveOut, allocOut, length);
1328 }
1329 /* if the tag isn't in the right place, copy it out */
1330 if (tag != out + length) {
1331 PORT_Memcpymemcpy(tag, out + length, taglen);
1332 }
1333 }
1334 *outlen = length;
1335 rv = SECSuccess;
1336fail:
1337 if (allocOut) {
1338 PORT_FreePORT_Free_Util(allocOut);
1339 }
1340 return rv;
1341}
1342
1343/*
1344 * Do an AEAD operation. This function optionally returns
1345 * and IV on Encrypt for all mechanism. NSS knows which mechanisms
1346 * generate IV's in the token and which don't. This allows the
1347 * applications to make a single call without special handling for
1348 * each AEAD mechanism (the special handling is all contained here.
1349 */
1350SECStatus
1351PK11_AEADOp(PK11Context *context, CK_GENERATOR_FUNCTION ivgen,
1352 int fixedbits, unsigned char *iv, int ivlen,
1353 const unsigned char *aad, int aadlen,
1354 unsigned char *out, int *outlen,
1355 int maxout, unsigned char *tag, int taglen,
1356 const unsigned char *in, int inlen)
1357{
1358 CK_GCM_MESSAGE_PARAMS gcm_message;
1359 CK_CCM_MESSAGE_PARAMS ccm_message;
1360 CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS chacha_poly_message;
1361 void *params;
1362 int paramslen;
1363 SECStatus rv;
1364
1365 switch (context->simulate_mechanism) {
1366 case CKM_CHACHA20_POLY13050x00004021UL:
1367 case CKM_SALSA20_POLY13050x00004022UL:
1368 case CKM_NSS_CHACHA20_POLY1305((0x80000000UL | 0x4E534350) + 28):
1369 if (taglen != 16) {
1370 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1371 return SECFailure;
1372 }
1373 chacha_poly_message.pNonce = iv;
1374 chacha_poly_message.ulNonceLen = ivlen;
1375 chacha_poly_message.pTag = tag;
1376 params = &chacha_poly_message;
1377 paramslen = sizeof(CK_SALSA20_CHACHA20_POLY1305_MSG_PARAMS);
1378 /* SALSA20_POLY1305 and CHACHA20_POLY1305 do not generate the iv
1379 * internally, Do it here. */
1380 if (context->operation == (CKA_NSS_MESSAGE0x82000000L | CKA_ENCRYPT0x00000104UL)) {
1381 /* simulate generating the IV */
1382 rv = pk11_GenerateIV(context, ivgen, fixedbits, iv, ivlen);
1383 if (rv != SECSuccess) {
1384 return rv;
1385 }
1386 }
1387 break;
1388 case CKM_AES_GCM0x00001087UL:
1389 gcm_message.pIv = iv;
1390 gcm_message.ulIvLen = ivlen;
1391 gcm_message.ivGenerator = ivgen;
1392 gcm_message.ulIvFixedBits = fixedbits;
1393 gcm_message.pTag = tag;
1394 gcm_message.ulTagBits = taglen * 8;
1395 params = &gcm_message;
1396 paramslen = sizeof(CK_GCM_MESSAGE_PARAMS);
1397 /* GCM generates IV internally */
1398 break;
1399 case CKM_AES_CCM0x00001088UL:
1400 ccm_message.ulDataLen = inlen;
1401 ccm_message.pNonce = iv;
1402 ccm_message.ulNonceLen = ivlen;
1403 ccm_message.nonceGenerator = ivgen;
1404 ccm_message.ulNonceFixedBits = fixedbits;
1405 ccm_message.pMAC = tag;
1406 ccm_message.ulMACLen = taglen;
1407 params = &ccm_message;
1408 paramslen = sizeof(CK_GCM_MESSAGE_PARAMS);
1409 /* CCM generates IV internally */
1410 break;
1411
1412 default:
1413 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ALGORITHM);
1414 return SECFailure;
1415 }
1416 return PK11_AEADRawOp(context, params, paramslen, aad, aadlen, out, outlen,
1417 maxout, in, inlen);
1418}
1419
1420/* Do and AED operation. The application builds the params on it's own
1421 * and passes them in. This allows applications direct access to the params
1422 * so they can use mechanisms not yet understood by, NSS, or get semantics
1423 * not suppied by PK11_AEAD. */
1424SECStatus
1425PK11_AEADRawOp(PK11Context *context, void *params, int paramslen,
1426 const unsigned char *aad, int aadlen,
1427 unsigned char *out, int *outlen,
1428 int maxout, const unsigned char *in, int inlen)
1429{
1430 CK_RV crv = CKR_OK0x00000000UL;
1431 CK_ULONG length = maxout;
1432 SECStatus rv = SECSuccess;
1433
1434 PORT_Assert(outlen != NULL)((outlen != ((void*)0)) ? ((void)0) : PR_Assert("outlen != NULL"
, "/root/firefox-clang/security/nss/lib/pk11wrap/pk11cxt.c", 1434
))
;
1435 *outlen = 0;
1436 if (((context->operation) & CKA_NSS_MESSAGE_MASK0xff000000L) != CKA_NSS_MESSAGE0x82000000L) {
1437 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1438 return SECFailure;
1439 }
1440
1441 /*
1442 * The PKCS 11 module does not support the message interface, fall
1443 * back to using single shot operation */
1444 if (context->simulate_message) {
1445 return pk11_AEADSimulateOp(context, params, paramslen, aad, aadlen,
1446 out, outlen, maxout, in, inlen);
1447 }
1448
1449 /* if we ran out of session, we need to restore our previously stored
1450 * state.
1451 */
1452 PK11_EnterContextMonitor(context);
1453 if (!context->ownSession) {
1454 rv = pk11_restoreContext(context, context->savedData,
1455 context->savedLength);
1456 if (rv != SECSuccess) {
1457 PK11_ExitContextMonitor(context);
1458 return rv;
1459 }
1460 }
1461
1462 switch (context->operation) {
1463 case CKA_NSS_MESSAGE0x82000000L | CKA_ENCRYPT0x00000104UL:
1464 length = maxout;
1465 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);
1466 break;
1467 case CKA_NSS_MESSAGE0x82000000L | CKA_DECRYPT0x00000105UL:
1468 length = maxout;
1469 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);
1470 break;
1471 case CKA_NSS_MESSAGE0x82000000L | CKA_SIGN0x00000108UL:
1472 length = maxout;
1473 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);
1474 break;
1475 case CKA_NSS_MESSAGE0x82000000L | CKA_VERIFY0x0000010AUL:
1476 length = maxout; /* sig length */
1477 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);
1478 break;
1479 default:
1480 crv = CKR_OPERATION_NOT_INITIALIZED0x00000091UL;
1481 break;
1482 }
1483
1484 if (crv != CKR_OK0x00000000UL) {
1485 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1486 rv = SECFailure;
1487 } else {
1488 *outlen = length;
1489 }
1490
1491 /*
1492 * handle session starvation case.. use our last session to multiplex
1493 */
1494 if (!context->ownSession) {
1495 context->savedData = pk11_saveContext(context, context->savedData,
1496 &context->savedLength);
1497 if (context->savedData == NULL((void*)0))
1498 rv = SECFailure;
1499
1500 /* clear out out session for others to use */
1501 pk11_Finalize(context);
1502 }
1503 PK11_ExitContextMonitor(context);
1504 return rv;
1505}
1506
1507/*
1508 * execute a digest/signature operation
1509 */
1510SECStatus
1511PK11_DigestOp(PK11Context *context, const unsigned char *in, unsigned inLen)
1512{
1513 CK_RV crv = CKR_OK0x00000000UL;
1514 SECStatus rv = SECSuccess;
1515
1516 if (inLen == 0) {
1517 return SECSuccess;
1518 }
1519 if (!in) {
1520 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1521 return SECFailure;
1522 }
1523
1524 /* if we ran out of session, we need to restore our previously stored
1525 * state.
1526 */
1527 context->init = PR_FALSE0;
1528 PK11_EnterContextMonitor(context);
1529 if (!context->ownSession) {
1530 rv = pk11_restoreContext(context, context->savedData,
1531 context->savedLength);
1532 if (rv != SECSuccess) {
1533 PK11_ExitContextMonitor(context);
1534 return rv;
1535 }
1536 }
1537
1538 switch (context->operation) {
1539 /* also for MAC'ing */
1540 case CKA_SIGN0x00000108UL:
1541 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_SignUpdate(context->session, (unsigned char *)in, inLen);
1542 break;
1543 case CKA_VERIFY0x0000010AUL:
1544 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_VerifyUpdate(context->session, (unsigned char *)in, inLen);
1545 break;
1546 case CKA_NSS_VERIFY_SIGNATURE(0x83000000L | 0x0000010AUL):
1547 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_VerifySignatureUpdate(context->session, (unsigned char *)in, inLen);
1548 break;
1549 case CKA_DIGEST0x81000000L:
1550 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_DigestUpdate(context->session, (unsigned char *)in, inLen);
1551 break;
1552 default:
1553 crv = CKR_OPERATION_NOT_INITIALIZED0x00000091UL;
1554 break;
1555 }
1556
1557 if (crv != CKR_OK0x00000000UL) {
1558 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1559 rv = SECFailure;
1560 }
1561
1562 /*
1563 * handle session starvation case.. use our last session to multiplex
1564 */
1565 if (!context->ownSession) {
1566 context->savedData = pk11_saveContext(context, context->savedData,
1567 &context->savedLength);
1568 if (context->savedData == NULL((void*)0))
1569 rv = SECFailure;
1570
1571 /* clear out out session for others to use */
1572 pk11_Finalize(context);
1573 }
1574 PK11_ExitContextMonitor(context);
1575 return rv;
1576}
1577
1578/*
1579 * Digest a key if possible./
1580 */
1581SECStatus
1582PK11_DigestKey(PK11Context *context, PK11SymKey *key)
1583{
1584 CK_RV crv = CKR_OK0x00000000UL;
1585 SECStatus rv = SECSuccess;
1586 PK11SymKey *newKey = NULL((void*)0);
1587
1588 if (!context || !key) {
1589 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1590 return SECFailure;
1591 }
1592
1593 /* if we ran out of session, we need to restore our previously stored
1594 * state.
1595 */
1596 if (context->slot != key->slot) {
1597 newKey = pk11_CopyToSlot(context->slot, CKM_SSL3_SHA1_MAC0x00000381UL, CKA_SIGN0x00000108UL, key);
1598 } else {
1599 newKey = PK11_ReferenceSymKey(key);
1600 }
1601
1602 context->init = PR_FALSE0;
1603 PK11_EnterContextMonitor(context);
1604 if (!context->ownSession) {
1605 rv = pk11_restoreContext(context, context->savedData,
1606 context->savedLength);
1607 if (rv != SECSuccess) {
1608 PK11_ExitContextMonitor(context);
1609 PK11_FreeSymKey(newKey);
1610 return rv;
1611 }
1612 }
1613
1614 if (newKey == NULL((void*)0)) {
1615 crv = CKR_KEY_TYPE_INCONSISTENT0x00000063UL;
1616 if (key->data.data) {
1617 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_DigestUpdate(context->session, key->data.data, key->data.len);
1618 }
1619 } else {
1620 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_DigestKey(context->session, newKey->objectID);
1621 }
1622
1623 if (crv != CKR_OK0x00000000UL) {
1624 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1625 rv = SECFailure;
1626 }
1627
1628 /*
1629 * handle session starvation case.. use our last session to multiplex
1630 */
1631 if (!context->ownSession) {
1632 context->savedData = pk11_saveContext(context, context->savedData,
1633 &context->savedLength);
1634 if (context->savedData == NULL((void*)0))
1635 rv = SECFailure;
1636
1637 /* clear out out session for others to use */
1638 pk11_Finalize(context);
1639 }
1640 PK11_ExitContextMonitor(context);
1641 if (newKey)
1642 PK11_FreeSymKey(newKey);
1643 return rv;
1644}
1645
1646/*
1647 * externally callable version of the lowercase pk11_finalize().
1648 */
1649SECStatus
1650PK11_Finalize(PK11Context *context)
1651{
1652 SECStatus rv;
1653
1654 PK11_EnterContextMonitor(context);
1655 rv = pk11_Finalize(context);
1656 PK11_ExitContextMonitor(context);
1657 return rv;
1658}
1659
1660/*
1661 * clean up a cipher operation, so the session can be used by
1662 * someone new.
1663 */
1664SECStatus
1665pk11_Finalize(PK11Context *context)
1666{
1667 CK_ULONG count = 0;
1668 CK_RV crv;
1669 unsigned char stackBuf[256];
1670 unsigned char *buffer = NULL((void*)0);
1671
1672 if (!context->ownSession) {
1673 return SECSuccess;
1674 }
1675
1676finalize:
1677 switch (context->operation) {
1678 case CKA_ENCRYPT0x00000104UL:
1679 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_EncryptFinal(context->session, buffer, &count);
1680 break;
1681 case CKA_DECRYPT0x00000105UL:
1682 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_DecryptFinal(context->session, buffer, &count);
1683 break;
1684 case CKA_SIGN0x00000108UL:
1685 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_SignFinal(context->session, buffer, &count);
1686 break;
1687 case CKA_VERIFY0x0000010AUL:
1688 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_VerifyFinal(context->session, buffer, count);
1689 break;
1690 case CKA_NSS_VERIFY_SIGNATURE(0x83000000L | 0x0000010AUL):
1691 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_VerifySignatureFinal(context->session);
1692 break;
1693 case CKA_DIGEST0x81000000L:
1694 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_DigestFinal(context->session, buffer, &count);
1695 break;
1696 case CKA_NSS_MESSAGE0x82000000L | CKA_ENCRYPT0x00000104UL:
1697 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_MessageEncryptFinal(context->session);
1698 break;
1699 case CKA_NSS_MESSAGE0x82000000L | CKA_DECRYPT0x00000105UL:
1700 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_MessageDecryptFinal(context->session);
1701 break;
1702 case CKA_NSS_MESSAGE0x82000000L | CKA_SIGN0x00000108UL:
1703 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_MessageSignFinal(context->session);
1704 break;
1705 case CKA_NSS_MESSAGE0x82000000L | CKA_VERIFY0x0000010AUL:
1706 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_MessageVerifyFinal(context->session);
1707 break;
1708 default:
1709 crv = CKR_OPERATION_NOT_INITIALIZED0x00000091UL;
1710 break;
1711 }
1712
1713 if (crv != CKR_OK0x00000000UL) {
1714 if (buffer != stackBuf) {
1715 PORT_FreePORT_Free_Util(buffer);
1716 }
1717 if (crv == CKR_OPERATION_NOT_INITIALIZED0x00000091UL) {
1718 /* if there's no operation, it is finalized */
1719 return SECSuccess;
1720 }
1721 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1722 return SECFailure;
1723 }
1724
1725 /* Message interface does not need to allocate a final buffer */
1726 /* nor does CKA_NSS_VERIFY_SIGNATURE. We could use a clever trick
1727 * here to include the CKA_NSS_SIGNATURE addition, but this form is
1728 * more clear to the reader what is happenning */
1729 if ((((context->operation) & CKA_NSS_MESSAGE_MASK0xff000000L) == CKA_NSS_MESSAGE0x82000000L) ||
1730 ((context->operation) == CKA_NSS_VERIFY_SIGNATURE(0x83000000L | 0x0000010AUL))) {
1731 return SECSuccess;
1732 }
1733
1734 /* try to finalize the session with a buffer */
1735 if (buffer == NULL((void*)0)) {
1736 if (count <= sizeof stackBuf) {
1737 buffer = stackBuf;
1738 } else {
1739 buffer = PORT_AllocPORT_Alloc_Util(count);
1740 if (buffer == NULL((void*)0)) {
1741 return SECFailure;
1742 }
1743 }
1744 goto finalize;
1745 }
1746 if (buffer != stackBuf) {
1747 PORT_FreePORT_Free_Util(buffer);
1748 }
1749 return SECSuccess;
1750}
1751
1752/*
1753 * Return the final digested or signed data...
1754 * this routine can either take pre initialized data, or allocate data
1755 * either out of an arena or out of the standard heap.
1756 */
1757SECStatus
1758PK11_DigestFinal(PK11Context *context, unsigned char *data,
1759 unsigned int *outLen, unsigned int length)
1760{
1761 CK_ULONG len;
1762 CK_RV crv;
1763 SECStatus rv;
1764
1765 /* message interface returns no data on Final, Should not use DigestFinal
1766 * in this case */
1767 if (((context->operation) & CKA_NSS_MESSAGE_MASK0xff000000L) == CKA_NSS_MESSAGE0x82000000L) {
1768 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1769 return SECFailure;
1770 }
1771
1772 /* if we ran out of session, we need to restore our previously stored
1773 * state.
1774 */
1775 PK11_EnterContextMonitor(context);
1776 if (!context->ownSession) {
1777 rv = pk11_restoreContext(context, context->savedData,
1778 context->savedLength);
1779 if (rv != SECSuccess) {
1780 PK11_ExitContextMonitor(context);
1781 return rv;
1782 }
1783 }
1784
1785 len = length;
1786 switch (context->operation) {
1787 case CKA_SIGN0x00000108UL:
1788 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_SignFinal(context->session, data, &len);
1789 break;
1790 case CKA_VERIFY0x0000010AUL:
1791 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_VerifyFinal(context->session, data, len);
1792 break;
1793 case CKA_NSS_VERIFY_SIGNATURE(0x83000000L | 0x0000010AUL):
1794 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_VerifySignatureFinal(context->session);
1795 break;
1796 case CKA_DIGEST0x81000000L:
1797 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_DigestFinal(context->session, data, &len);
1798 break;
1799 case CKA_ENCRYPT0x00000104UL:
1800 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_EncryptFinal(context->session, data, &len);
1801 break;
1802 case CKA_DECRYPT0x00000105UL:
1803 crv = PK11_GETTAB(context->slot)((CK_FUNCTION_LIST_3_2_PTR)((context->slot)->functionList
))
->C_DecryptFinal(context->session, data, &len);
1804 break;
1805 default:
1806 crv = CKR_OPERATION_NOT_INITIALIZED0x00000091UL;
1807 break;
1808 }
1809 PK11_ExitContextMonitor(context);
1810
1811 context->init = PR_FALSE0; /* allow Begin to start up again */
1812
1813 if (crv != CKR_OK0x00000000UL) {
1814 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1815 return SECFailure;
1816 }
1817 *outLen = (unsigned int)len;
1818 return SECSuccess;
1819}
1820
1821PRBool
1822PK11_ContextGetFIPSStatus(PK11Context *context)
1823{
1824 if (context->slot == NULL((void*)0)) {
1825 return PR_FALSE0;
1826 }
1827 return pk11slot_GetFIPSStatus(context->slot, context->session,
1828 CK_INVALID_HANDLE0, context->init ? CKT_NSS_SESSION_CHECK1UL : CKT_NSS_SESSION_LAST_CHECK4UL);
1829}