Bug Summary

File:root/firefox-clang/security/nss/lib/pk11wrap/pk11obj.c
Warning:line 1757, column 5
Value stored to 'nextObject' 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 pk11obj.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/pk11obj.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 manages object type indepentent functions.
6 */
7#include <limits.h>
8#include <stddef.h>
9
10#include "seccomon.h"
11#include "secder.h"
12#include "secmod.h"
13#include "secmodi.h"
14#include "secmodti.h"
15#include "pkcs11.h"
16#include "pkcs11t.h"
17#include "pk11func.h"
18#include "keyhi.h"
19#include "keyi.h"
20#include "secitem.h"
21#include "secerr.h"
22#include "sslerr.h"
23
24#define PK11_SEARCH_CHUNKSIZE10 10
25
26/*
27 * Build a block big enough to hold the data
28 */
29SECItem *
30PK11_BlockData(SECItem *data, unsigned long size)
31{
32 SECItem *newData;
33
34 if (size == 0u)
35 return NULL((void*)0);
36
37 newData = (SECItem *)PORT_AllocPORT_Alloc_Util(sizeof(SECItem));
38 if (newData == NULL((void*)0))
39 return NULL((void*)0);
40
41 newData->len = (data->len + (size - 1)) / size;
42 newData->len *= size;
43
44 newData->data = (unsigned char *)PORT_ZAllocPORT_ZAlloc_Util(newData->len);
45 if (newData->data == NULL((void*)0)) {
46 PORT_FreePORT_Free_Util(newData);
47 return NULL((void*)0);
48 }
49 PORT_Memsetmemset(newData->data, newData->len - data->len, newData->len);
50 PORT_Memcpymemcpy(newData->data, data->data, data->len);
51 return newData;
52}
53
54SECStatus
55PK11_DestroyObject(PK11SlotInfo *slot, CK_OBJECT_HANDLE object)
56{
57 CK_RV crv;
58
59 PK11_EnterSlotMonitor(slot);
60 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_DestroyObject(slot->session, object);
61 PK11_ExitSlotMonitor(slot);
62 if (crv != CKR_OK0x00000000UL) {
63 return SECFailure;
64 }
65 return SECSuccess;
66}
67
68SECStatus
69PK11_DestroyTokenObject(PK11SlotInfo *slot, CK_OBJECT_HANDLE object)
70{
71 CK_RV crv;
72 SECStatus rv = SECSuccess;
73 CK_SESSION_HANDLE rwsession;
74
75 rwsession = PK11_GetRWSession(slot);
76 if (rwsession == CK_INVALID_HANDLE0) {
77 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DATA);
78 return SECFailure;
79 }
80
81 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_DestroyObject(rwsession, object);
82 if (crv != CKR_OK0x00000000UL) {
83 rv = SECFailure;
84 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
85 }
86 PK11_RestoreROSession(slot, rwsession);
87 return rv;
88}
89
90/*
91 * Read in a single attribute into a SECItem. Allocate space for it with
92 * PORT_Alloc unless an arena is supplied. In the latter case use the arena
93 * to allocate the space.
94 *
95 * PK11_ReadAttribute sets the 'data' and 'len' fields of the SECItem but
96 * does not modify its 'type' field.
97 */
98SECStatus
99PK11_ReadAttribute(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
100 CK_ATTRIBUTE_TYPE type, PLArenaPool *arena, SECItem *result)
101{
102 CK_ATTRIBUTE attr = { 0, NULL((void*)0), 0 };
103 CK_RV crv;
104
105 attr.type = type;
106
107 PK11_EnterSlotMonitor(slot);
108 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetAttributeValue(slot->session, id, &attr, 1);
109 if (crv != CKR_OK0x00000000UL) {
110 PK11_ExitSlotMonitor(slot);
111 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
112 return SECFailure;
113 }
114 if (arena) {
115 attr.pValue = PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, attr.ulValueLen);
116 } else {
117 attr.pValue = PORT_AllocPORT_Alloc_Util(attr.ulValueLen);
118 }
119 if (attr.pValue == NULL((void*)0)) {
120 PK11_ExitSlotMonitor(slot);
121 return SECFailure;
122 }
123 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetAttributeValue(slot->session, id, &attr, 1);
124 PK11_ExitSlotMonitor(slot);
125 if (crv != CKR_OK0x00000000UL) {
126 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
127 if (!arena)
128 PORT_FreePORT_Free_Util(attr.pValue);
129 return SECFailure;
130 }
131
132 result->data = (unsigned char *)attr.pValue;
133 result->len = attr.ulValueLen;
134
135 return SECSuccess;
136}
137
138/*
139 * Read in a single attribute into a Ulong.
140 */
141CK_ULONG
142PK11_ReadULongAttribute(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
143 CK_ATTRIBUTE_TYPE type)
144{
145 CK_ATTRIBUTE attr;
146 CK_ULONG value = CK_UNAVAILABLE_INFORMATION(~0UL);
147 CK_RV crv;
148
149 PK11_SETATTRS(&attr, type, &value, sizeof(value))(&attr)->type = (type); (&attr)->pValue = (&
value); (&attr)->ulValueLen = (sizeof(value));
;
150
151 PK11_EnterSlotMonitor(slot);
152 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetAttributeValue(slot->session, id, &attr, 1);
153 PK11_ExitSlotMonitor(slot);
154 if (crv != CKR_OK0x00000000UL) {
155 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
156 }
157 return value;
158}
159
160/*
161 * check to see if a bool has been set.
162 */
163CK_BBOOL
164pk11_HasAttributeSet_Lock(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
165 CK_ATTRIBUTE_TYPE type, PRBool haslock)
166{
167 CK_BBOOL ckvalue = CK_FALSE0;
168 CK_ATTRIBUTE theTemplate;
169 CK_RV crv;
170
171 /* Prepare to retrieve the attribute. */
172 PK11_SETATTRS(&theTemplate, type, &ckvalue, sizeof(CK_BBOOL))(&theTemplate)->type = (type); (&theTemplate)->
pValue = (&ckvalue); (&theTemplate)->ulValueLen = (
sizeof(CK_BBOOL));
;
173
174 /* Retrieve attribute value. */
175 if (!haslock)
176 PK11_EnterSlotMonitor(slot);
177 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetAttributeValue(slot->session, id,
178 &theTemplate, 1);
179 if (!haslock)
180 PK11_ExitSlotMonitor(slot);
181 if (crv != CKR_OK0x00000000UL) {
182 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
183 return CK_FALSE0;
184 }
185
186 return ckvalue;
187}
188
189CK_BBOOL
190PK11_HasAttributeSet(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
191 CK_ATTRIBUTE_TYPE type, PRBool haslock)
192{
193 PR_ASSERT(haslock == PR_FALSE)((haslock == 0) ? ((void)0) : PR_Assert("haslock == PR_FALSE"
, "/root/firefox-clang/security/nss/lib/pk11wrap/pk11obj.c", 193
))
;
194 return pk11_HasAttributeSet_Lock(slot, id, type, PR_FALSE0);
195}
196
197/*
198 * returns a full list of attributes. Allocate space for them. If an arena is
199 * provided, allocate space out of the arena.
200 */
201CK_RV
202PK11_GetAttributes(PLArenaPool *arena, PK11SlotInfo *slot,
203 CK_OBJECT_HANDLE obj, CK_ATTRIBUTE *attr, int count)
204{
205 int i;
206 /* make pedantic happy... note that it's only used arena != NULL */
207 void *mark = NULL((void*)0);
208 CK_RV crv;
209 if (slot->session == CK_INVALID_HANDLE0)
210 return CKR_SESSION_HANDLE_INVALID0x000000B3UL;
211
212 /*
213 * first get all the lengths of the parameters.
214 */
215 PK11_EnterSlotMonitor(slot);
216 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetAttributeValue(slot->session, obj, attr, count);
217 if (crv != CKR_OK0x00000000UL) {
218 PK11_ExitSlotMonitor(slot);
219 return crv;
220 }
221
222 if (arena) {
223 mark = PORT_ArenaMarkPORT_ArenaMark_Util(arena);
224 if (mark == NULL((void*)0))
225 return CKR_HOST_MEMORY0x00000002UL;
226 }
227
228 /*
229 * now allocate space to store the results.
230 */
231 for (i = 0; i < count; i++) {
232 if (attr[i].ulValueLen == 0)
233 continue;
234 if (arena) {
235 attr[i].pValue = PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, attr[i].ulValueLen);
236 if (attr[i].pValue == NULL((void*)0)) {
237 /* arena failures, just release the mark */
238 PORT_ArenaReleasePORT_ArenaRelease_Util(arena, mark);
239 PK11_ExitSlotMonitor(slot);
240 return CKR_HOST_MEMORY0x00000002UL;
241 }
242 } else {
243 attr[i].pValue = PORT_AllocPORT_Alloc_Util(attr[i].ulValueLen);
244 if (attr[i].pValue == NULL((void*)0)) {
245 /* Separate malloc failures, loop to release what we have
246 * so far */
247 int j;
248 for (j = 0; j < i; j++) {
249 PORT_FreePORT_Free_Util(attr[j].pValue);
250 /* don't give the caller pointers to freed memory */
251 attr[j].pValue = NULL((void*)0);
252 }
253 PK11_ExitSlotMonitor(slot);
254 return CKR_HOST_MEMORY0x00000002UL;
255 }
256 }
257 }
258
259 /*
260 * finally get the results.
261 */
262 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetAttributeValue(slot->session, obj, attr, count);
263 PK11_ExitSlotMonitor(slot);
264 if (crv != CKR_OK0x00000000UL) {
265 if (arena) {
266 PORT_ArenaReleasePORT_ArenaRelease_Util(arena, mark);
267 } else {
268 for (i = 0; i < count; i++) {
269 PORT_FreePORT_Free_Util(attr[i].pValue);
270 /* don't give the caller pointers to freed memory */
271 attr[i].pValue = NULL((void*)0);
272 }
273 }
274 } else if (arena && mark) {
275 PORT_ArenaUnmarkPORT_ArenaUnmark_Util(arena, mark);
276 }
277 return crv;
278}
279
280PRBool
281PK11_IsPermObject(PK11SlotInfo *slot, CK_OBJECT_HANDLE handle)
282{
283 return (PRBool)PK11_HasAttributeSet(slot, handle, CKA_TOKEN0x00000001UL, PR_FALSE0);
284}
285
286char *
287PK11_GetObjectNickname(PK11SlotInfo *slot, CK_OBJECT_HANDLE id)
288{
289 char *nickname = NULL((void*)0);
290 SECItem result;
291 SECStatus rv;
292
293 rv = PK11_ReadAttribute(slot, id, CKA_LABEL0x00000003UL, NULL((void*)0), &result);
294 if (rv != SECSuccess) {
295 return NULL((void*)0);
296 }
297
298 nickname = PORT_ZAllocPORT_ZAlloc_Util(result.len + 1);
299 if (nickname == NULL((void*)0)) {
300 PORT_FreePORT_Free_Util(result.data);
301 return NULL((void*)0);
302 }
303 PORT_Memcpymemcpy(nickname, result.data, result.len);
304 PORT_FreePORT_Free_Util(result.data);
305 return nickname;
306}
307
308SECStatus
309PK11_SetObjectNickname(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
310 const char *nickname)
311{
312 int len = PORT_Strlen(nickname)strlen(nickname);
313 CK_ATTRIBUTE setTemplate;
314 CK_RV crv;
315 CK_SESSION_HANDLE rwsession;
316
317 if (len < 0) {
318 return SECFailure;
319 }
320
321 PK11_SETATTRS(&setTemplate, CKA_LABEL, (CK_CHAR *)nickname, len)(&setTemplate)->type = (0x00000003UL); (&setTemplate
)->pValue = ((CK_CHAR *)nickname); (&setTemplate)->
ulValueLen = (len);
;
322 rwsession = PK11_GetRWSession(slot);
323 if (rwsession == CK_INVALID_HANDLE0) {
324 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DATA);
325 return SECFailure;
326 }
327 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_SetAttributeValue(rwsession, id,
328 &setTemplate, 1);
329 PK11_RestoreROSession(slot, rwsession);
330 if (crv != CKR_OK0x00000000UL) {
331 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
332 return SECFailure;
333 }
334 return SECSuccess;
335}
336
337/*
338 * strip leading zero's from key material
339 */
340void
341pk11_SignedToUnsigned(CK_ATTRIBUTE *attrib)
342{
343 char *ptr = (char *)attrib->pValue;
344 unsigned long len = attrib->ulValueLen;
345
346 while ((len > 1) && (*ptr == 0)) {
347 len--;
348 ptr++;
349 }
350 attrib->pValue = ptr;
351 attrib->ulValueLen = len;
352}
353
354/*
355 * get a new session on a slot. If we run out of session, use the slot's
356 * 'exclusive' session. In this case owner becomes false.
357 */
358CK_SESSION_HANDLE
359pk11_GetNewSession(PK11SlotInfo *slot, PRBool *owner)
360{
361 CK_SESSION_HANDLE session;
362 *owner = PR_TRUE1;
363 if (!slot->isThreadSafe)
364 PK11_EnterSlotMonitor(slot);
365 if (PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_OpenSession(slot->slotID, CKF_SERIAL_SESSION0x00000004UL,
366 slot, pk11_notify, &session) != CKR_OK0x00000000UL) {
367 *owner = PR_FALSE0;
368 session = slot->session;
369 }
370 if (!slot->isThreadSafe)
371 PK11_ExitSlotMonitor(slot);
372
373 return session;
374}
375
376void
377pk11_CloseSession(PK11SlotInfo *slot, CK_SESSION_HANDLE session, PRBool owner)
378{
379 if (!owner)
380 return;
381 if (!slot->isThreadSafe)
382 PK11_EnterSlotMonitor(slot);
383 (void)PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_CloseSession(session);
384 if (!slot->isThreadSafe)
385 PK11_ExitSlotMonitor(slot);
386}
387
388SECStatus
389PK11_CreateNewObject(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
390 const CK_ATTRIBUTE *theTemplate, int count,
391 PRBool token, CK_OBJECT_HANDLE *objectID)
392{
393 CK_SESSION_HANDLE rwsession;
394 CK_RV crv;
395 SECStatus rv = SECSuccess;
396
397 rwsession = session;
398 if (token) {
399 rwsession = PK11_GetRWSession(slot);
400 } else if (rwsession == CK_INVALID_HANDLE0) {
401 rwsession = slot->session;
402 if (rwsession != CK_INVALID_HANDLE0)
403 PK11_EnterSlotMonitor(slot);
404 }
405 if (rwsession == CK_INVALID_HANDLE0) {
406 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DATA);
407 return SECFailure;
408 }
409 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_CreateObject(rwsession,
410 /* cast away const :-( */ (CK_ATTRIBUTE_PTR)theTemplate,
411 count, objectID);
412 if (crv != CKR_OK0x00000000UL) {
413 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
414 rv = SECFailure;
415 }
416 if (token) {
417 PK11_RestoreROSession(slot, rwsession);
418 } else if (session == CK_INVALID_HANDLE0) {
419 PK11_ExitSlotMonitor(slot);
420 }
421
422 return rv;
423}
424
425/* This function may add a maximum of 9 attributes. */
426unsigned int
427pk11_OpFlagsToAttributes(CK_FLAGS flags, CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue)
428{
429
430 const static CK_ATTRIBUTE_TYPE attrTypes[12] = {
431 CKA_ENCRYPT0x00000104UL, CKA_DECRYPT0x00000105UL, 0 /* DIGEST */, CKA_SIGN0x00000108UL,
432 CKA_SIGN_RECOVER0x00000109UL, CKA_VERIFY0x0000010AUL, CKA_VERIFY_RECOVER0x0000010BUL, 0 /* GEN */,
433 0 /* GEN PAIR */, CKA_WRAP0x00000106UL, CKA_UNWRAP0x00000107UL, CKA_DERIVE0x0000010CUL
434 };
435
436 const CK_ATTRIBUTE_TYPE *pType = attrTypes;
437 CK_ATTRIBUTE *attr = attrs;
438 CK_FLAGS test = CKF_ENCRYPT0x00000100UL;
439
440 PR_ASSERT(!(flags & ~CKF_KEY_OPERATION_FLAGS))((!(flags & ~0x000e7b00UL)) ? ((void)0) : PR_Assert("!(flags & ~CKF_KEY_OPERATION_FLAGS)"
, "/root/firefox-clang/security/nss/lib/pk11wrap/pk11obj.c", 440
))
;
441 flags &= CKF_KEY_OPERATION_FLAGS0x000e7b00UL;
442
443 for (; flags && test <= CKF_DERIVE0x00080000UL; test <<= 1, ++pType) {
444 if (test & flags) {
445 flags ^= test;
446 PR_ASSERT(*pType)((*pType) ? ((void)0) : PR_Assert("*pType", "/root/firefox-clang/security/nss/lib/pk11wrap/pk11obj.c"
, 446))
;
447 PK11_SETATTRS(attr, *pType, ckTrue, sizeof *ckTrue)(attr)->type = (*pType); (attr)->pValue = (ckTrue); (attr
)->ulValueLen = (sizeof *ckTrue);
;
448 ++attr;
449 }
450 }
451 return (attr - attrs);
452}
453
454/*
455 * Check for conflicting flags, for example, if both PK11_ATTR_PRIVATE
456 * and PK11_ATTR_PUBLIC are set.
457 */
458PRBool
459pk11_BadAttrFlags(PK11AttrFlags attrFlags)
460{
461 PK11AttrFlags trueFlags = attrFlags & 0x55555555;
462 PK11AttrFlags falseFlags = (attrFlags >> 1) & 0x55555555;
463 return ((trueFlags & falseFlags) != 0);
464}
465
466/*
467 * This function may add a maximum of 5 attributes.
468 * The caller must make sure the attribute flags don't have conflicts.
469 */
470unsigned int
471pk11_AttrFlagsToAttributes(PK11AttrFlags attrFlags, CK_ATTRIBUTE *attrs,
472 CK_BBOOL *ckTrue, CK_BBOOL *ckFalse)
473{
474 const static CK_ATTRIBUTE_TYPE attrTypes[5] = {
475 CKA_TOKEN0x00000001UL, CKA_PRIVATE0x00000002UL, CKA_MODIFIABLE0x00000170UL, CKA_SENSITIVE0x00000103UL,
476 CKA_EXTRACTABLE0x00000162UL
477 };
478
479 const CK_ATTRIBUTE_TYPE *pType = attrTypes;
480 CK_ATTRIBUTE *attr = attrs;
481 PK11AttrFlags test = PK11_ATTR_TOKEN0x00000001L;
482
483 PR_ASSERT(!pk11_BadAttrFlags(attrFlags))((!pk11_BadAttrFlags(attrFlags)) ? ((void)0) : PR_Assert("!pk11_BadAttrFlags(attrFlags)"
, "/root/firefox-clang/security/nss/lib/pk11wrap/pk11obj.c", 483
))
;
484
485 /* we test two related bitflags in each iteration */
486 for (; attrFlags && test <= PK11_ATTR_EXTRACTABLE0x00000100L; test <<= 2, ++pType) {
487 if (test & attrFlags) {
488 attrFlags ^= test;
489 PK11_SETATTRS(attr, *pType, ckTrue, sizeof *ckTrue)(attr)->type = (*pType); (attr)->pValue = (ckTrue); (attr
)->ulValueLen = (sizeof *ckTrue);
;
490 ++attr;
491 } else if ((test << 1) & attrFlags) {
492 attrFlags ^= (test << 1);
493 PK11_SETATTRS(attr, *pType, ckFalse, sizeof *ckFalse)(attr)->type = (*pType); (attr)->pValue = (ckFalse); (attr
)->ulValueLen = (sizeof *ckFalse);
;
494 ++attr;
495 }
496 }
497 return (attr - attrs);
498}
499
500/*
501 * Some non-compliant PKCS #11 vendors do not give us the modulus, so actually
502 * set up a signature to get the signaure length.
503 */
504static int
505pk11_backupGetSignLength(SECKEYPrivateKey *key)
506{
507 PK11SlotInfo *slot = key->pkcs11Slot;
508 CK_MECHANISM mech = { 0, NULL((void*)0), 0 };
509 PRBool owner = PR_TRUE1;
510 CK_SESSION_HANDLE session;
511 CK_ULONG len;
512 CK_RV crv;
513 unsigned char h_data[20] = { 0 };
514 unsigned char buf[20]; /* obviously to small */
515 CK_ULONG smallLen = sizeof(buf);
516
517 mech.mechanism = PK11_MapSignKeyType(key->keyType);
518
519 session = pk11_GetNewSession(slot, &owner);
520 if (!owner || !(slot->isThreadSafe))
521 PK11_EnterSlotMonitor(slot);
522 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_SignInit(session, &mech, key->pkcs11ID);
523 if (crv != CKR_OK0x00000000UL) {
524 if (!owner || !(slot->isThreadSafe))
525 PK11_ExitSlotMonitor(slot);
526 pk11_CloseSession(slot, session, owner);
527 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
528 return -1;
529 }
530 len = 0;
531 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_Sign(session, h_data, sizeof(h_data),
532 NULL((void*)0), &len);
533 /* now call C_Sign with too small a buffer to clear the session state */
534 (void)PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_Sign(session, h_data, sizeof(h_data), buf, &smallLen);
535
536 if (!owner || !(slot->isThreadSafe))
537 PK11_ExitSlotMonitor(slot);
538 pk11_CloseSession(slot, session, owner);
539 if (crv != CKR_OK0x00000000UL) {
540 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
541 return -1;
542 }
543 return len;
544}
545
546/*
547 * get the length of a signature object based on the key
548 */
549int
550PK11_SignatureLen(SECKEYPrivateKey *key)
551{
552 int val;
553 SECItem attributeItem = { siBuffer, NULL((void*)0), 0 };
554 SECStatus rv;
555 int length;
556 SECOidTag paramSet;
557
558 switch (key->keyType) {
559 case rsaKey:
560 case rsaPssKey:
561 val = PK11_GetPrivateModulusLen(key);
562 if (val == -1) {
563 return pk11_backupGetSignLength(key);
564 }
565 return (unsigned long)val;
566
567 case fortezzaKey:
568 return 40;
569
570 case dsaKey:
571 rv = PK11_ReadAttribute(key->pkcs11Slot, key->pkcs11ID, CKA_SUBPRIME0x00000131UL,
572 NULL((void*)0), &attributeItem);
573 if (rv == SECSuccess) {
574 length = attributeItem.len;
575 if ((length > 0) && attributeItem.data[0] == 0) {
576 length--;
577 }
578 PORT_FreePORT_Free_Util(attributeItem.data);
579 return length * 2;
580 }
581 return pk11_backupGetSignLength(key);
582 case ecKey:
583 case edKey:
584 rv = PK11_ReadAttribute(key->pkcs11Slot, key->pkcs11ID, CKA_EC_PARAMS0x00000180UL,
585 NULL((void*)0), &attributeItem);
586 if (rv == SECSuccess) {
587 length = SECKEY_ECParamsToBasePointOrderLen(&attributeItem);
588 PORT_FreePORT_Free_Util(attributeItem.data);
589 if (length != 0) {
590 length = ((length + 7) / 8) * 2;
591 return length;
592 }
593 }
594 return pk11_backupGetSignLength(key);
595 case mldsaKey:
596 paramSet = seckey_GetParameterSet(key);
597 if (paramSet == SEC_OID_UNKNOWN) {
598 break;
599 }
600
601 return SECKEY_MLDSAOidParamsToLen(paramSet, SECKEYSignatureType);
602 default:
603 break;
604 }
605 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_KEY);
606 return 0;
607}
608
609/*
610 * copy a key (or any other object) on a token
611 */
612CK_OBJECT_HANDLE
613PK11_CopyKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE srcObject)
614{
615 CK_OBJECT_HANDLE destObject;
616 CK_RV crv;
617
618 PK11_EnterSlotMonitor(slot);
619 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_CopyObject(slot->session, srcObject, NULL((void*)0), 0,
620 &destObject);
621 PK11_ExitSlotMonitor(slot);
622 if (crv == CKR_OK0x00000000UL)
623 return destObject;
624 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
625 return CK_INVALID_HANDLE0;
626}
627
628PRBool
629pk11_FindAttrInTemplate(CK_ATTRIBUTE *attr, unsigned int numAttrs,
630 CK_ATTRIBUTE_TYPE target)
631{
632 for (; numAttrs > 0; ++attr, --numAttrs) {
633 if (attr->type == target)
634 return PR_TRUE1;
635 }
636 return PR_FALSE0;
637}
638
639/*
640 * Recover the Signed data. We need this because our old verify can't
641 * figure out which hash algorithm to use until we decryptted this.
642 */
643SECStatus
644PK11_VerifyRecover(SECKEYPublicKey *key, const SECItem *sig,
645 SECItem *dsig, void *wincx)
646{
647 PK11SlotInfo *slot = key->pkcs11Slot;
648 CK_OBJECT_HANDLE id = key->pkcs11ID;
649 CK_MECHANISM mech = { 0, NULL((void*)0), 0 };
650 PRBool owner = PR_TRUE1;
651 CK_SESSION_HANDLE session;
652 CK_ULONG len;
653 CK_RV crv;
654
655 mech.mechanism = PK11_MapSignKeyType(key->keyType);
656
657 if (slot == NULL((void*)0)) {
658 slot = PK11_GetBestSlotWithAttributes(mech.mechanism,
659 CKF_VERIFY_RECOVER0x00004000UL, 0, wincx);
660 if (slot == NULL((void*)0)) {
661 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MODULE);
662 return SECFailure;
663 }
664 id = PK11_ImportPublicKey(slot, key, PR_FALSE0);
665 } else {
666 PK11_ReferenceSlot(slot);
667 }
668
669 if (id == CK_INVALID_HANDLE0) {
670 PK11_FreeSlot(slot);
671 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_KEY);
672 return SECFailure;
673 }
674
675 session = pk11_GetNewSession(slot, &owner);
676 if (!owner || !(slot->isThreadSafe))
677 PK11_EnterSlotMonitor(slot);
678 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_VerifyRecoverInit(session, &mech, id);
679 if (crv != CKR_OK0x00000000UL) {
680 if (!owner || !(slot->isThreadSafe))
681 PK11_ExitSlotMonitor(slot);
682 pk11_CloseSession(slot, session, owner);
683 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
684 PK11_FreeSlot(slot);
685 return SECFailure;
686 }
687 len = dsig->len;
688 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_VerifyRecover(session, sig->data,
689 sig->len, dsig->data, &len);
690 if (!owner || !(slot->isThreadSafe))
691 PK11_ExitSlotMonitor(slot);
692 pk11_CloseSession(slot, session, owner);
693 dsig->len = len;
694 if (crv != CKR_OK0x00000000UL) {
695 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
696 PK11_FreeSlot(slot);
697 return SECFailure;
698 }
699 PK11_FreeSlot(slot);
700 return SECSuccess;
701}
702
703/*
704 * verify a signature from its hash.
705 */
706SECStatus
707PK11_Verify(SECKEYPublicKey *key, const SECItem *sig, const SECItem *hash,
708 void *wincx)
709{
710 CK_MECHANISM_TYPE mech = PK11_MapSignKeyType(key->keyType);
711 return PK11_VerifyWithMechanism(key, mech, NULL((void*)0), sig, hash, wincx);
712}
713
714/*
715 * Verify a signature from its hash using the given algorithm.
716 */
717SECStatus
718PK11_VerifyWithMechanism(SECKEYPublicKey *key, CK_MECHANISM_TYPE mechanism,
719 const SECItem *param, const SECItem *sig,
720 const SECItem *hash, void *wincx)
721{
722 PK11SlotInfo *slot = key->pkcs11Slot;
723 CK_OBJECT_HANDLE id = key->pkcs11ID;
724 CK_MECHANISM mech = { 0, NULL((void*)0), 0 };
725 PRBool owner = PR_TRUE1;
726 CK_SESSION_HANDLE session;
727 CK_RV crv;
728
729 mech.mechanism = mechanism;
730 if (param) {
731 mech.pParameter = param->data;
732 mech.ulParameterLen = param->len;
733 }
734
735 if (slot == NULL((void*)0)) {
736 unsigned int length = 0;
737 if ((mech.mechanism == CKM_DSA0x00000011UL) &&
738 /* 129 is 1024 bits translated to bytes and
739 * padded with an optional '0' to maintain a
740 * positive sign */
741 (key->u.dsa.params.prime.len > 129)) {
742 /* we need to get a slot that not only can do DSA, but can do DSA2
743 * key lengths */
744 length = key->u.dsa.params.prime.len;
745 if (key->u.dsa.params.prime.data[0] == 0) {
746 length--;
747 }
748 /* convert keysize to bits for slot lookup */
749 length *= 8;
750 }
751 slot = PK11_GetBestSlotWithAttributes(mech.mechanism,
752 CKF_VERIFY0x00002000, length, wincx);
753 if (slot == NULL((void*)0)) {
754 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MODULE);
755 return SECFailure;
756 }
757 id = PK11_ImportPublicKey(slot, key, PR_FALSE0);
758
759 } else {
760 PK11_ReferenceSlot(slot);
761 }
762
763 if (id == CK_INVALID_HANDLE0) {
764 PK11_FreeSlot(slot);
765 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_KEY);
766 return SECFailure;
767 }
768
769 session = pk11_GetNewSession(slot, &owner);
770 if (!owner || !(slot->isThreadSafe))
771 PK11_EnterSlotMonitor(slot);
772 if (PK11_CheckPKCS11Version(slot, 3, 2, PR_TRUE1) >= 0) {
773 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_VerifySignatureInit(session, &mech, id,
774 sig->data, sig->len);
775 if (crv != CKR_OK0x00000000UL) {
776 if (!owner || !(slot->isThreadSafe))
777 PK11_ExitSlotMonitor(slot);
778 pk11_CloseSession(slot, session, owner);
779 PK11_FreeSlot(slot);
780 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
781 return SECFailure;
782 }
783 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_VerifySignature(session, hash->data,
784 hash->len);
785 } else {
786 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_VerifyInit(session, &mech, id);
787 if (crv != CKR_OK0x00000000UL) {
788 if (!owner || !(slot->isThreadSafe))
789 PK11_ExitSlotMonitor(slot);
790 pk11_CloseSession(slot, session, owner);
791 PK11_FreeSlot(slot);
792 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
793 return SECFailure;
794 }
795 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_Verify(session, hash->data,
796 hash->len, sig->data, sig->len);
797 }
798 if (!owner || !(slot->isThreadSafe))
799 PK11_ExitSlotMonitor(slot);
800
801 pk11_CloseSession(slot, session, owner);
802 PK11_FreeSlot(slot);
803 if (crv != CKR_OK0x00000000UL) {
804 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
805 return SECFailure;
806 }
807 return SECSuccess;
808}
809
810/*
811 * sign a hash. The algorithm is determined by the key.
812 */
813SECStatus
814PK11_Sign(SECKEYPrivateKey *key, SECItem *sig, const SECItem *hash)
815{
816 CK_MECHANISM_TYPE mech = PK11_MapSignKeyType(key->keyType);
817 return PK11_SignWithMechanism(key, mech, NULL((void*)0), sig, hash);
818}
819
820/*
821 * Sign a hash using the given algorithm.
822 */
823SECStatus
824PK11_SignWithMechanism(SECKEYPrivateKey *key, CK_MECHANISM_TYPE mechanism,
825 const SECItem *param, SECItem *sig, const SECItem *hash)
826{
827 PK11SlotInfo *slot = key->pkcs11Slot;
828 CK_MECHANISM mech = { 0, NULL((void*)0), 0 };
829 PRBool owner = PR_TRUE1;
830 CK_SESSION_HANDLE session;
831 PRBool haslock = PR_FALSE0;
832 CK_ULONG len;
833 CK_RV crv;
834
835 mech.mechanism = mechanism;
836 if (param) {
837 mech.pParameter = param->data;
838 mech.ulParameterLen = param->len;
839 }
840
841 if (SECKEY_HAS_ATTRIBUTE_SET(key, CKA_PRIVATE)(0 != (key->staticflags & 0x1)) ? (0 != (key->staticflags
& (1U << 1))) : PK11_HasAttributeSet(key->pkcs11Slot
, key->pkcs11ID, 0x00000002UL, 0)
) {
842 PK11_HandlePasswordCheck(slot, key->wincx);
843 }
844
845 session = pk11_GetNewSession(slot, &owner);
846 haslock = (!owner || !(slot->isThreadSafe));
847 if (haslock)
848 PK11_EnterSlotMonitor(slot);
849 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_SignInit(session, &mech, key->pkcs11ID);
850 if (crv != CKR_OK0x00000000UL) {
851 if (haslock)
852 PK11_ExitSlotMonitor(slot);
853 pk11_CloseSession(slot, session, owner);
854 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
855 return SECFailure;
856 }
857
858 /* PKCS11 2.20 says if CKA_ALWAYS_AUTHENTICATE then
859 * do C_Login with CKU_CONTEXT_SPECIFIC
860 * between C_SignInit and C_Sign */
861 if (SECKEY_HAS_ATTRIBUTE_SET_LOCK(key, CKA_ALWAYS_AUTHENTICATE, haslock)(0 != (key->staticflags & 0x1)) ? (0 != (key->staticflags
& (1U << 2))) : pk11_HasAttributeSet_Lock(key->
pkcs11Slot, key->pkcs11ID, 0x00000202UL, haslock)
) {
862 PK11_DoPassword(slot, session, PR_FALSE0, key->wincx, haslock, PR_TRUE1);
863 }
864
865 len = sig->len;
866 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_Sign(session, hash->data,
867 hash->len, sig->data, &len);
868 if (haslock)
869 PK11_ExitSlotMonitor(slot);
870 pk11_CloseSession(slot, session, owner);
871 if (crv != CKR_OK0x00000000UL) {
872 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
873 return SECFailure;
874 }
875 sig->len = len;
876 return SECSuccess;
877}
878
879/*
880 * sign data with a MAC key.
881 */
882SECStatus
883PK11_SignWithSymKey(PK11SymKey *symKey, CK_MECHANISM_TYPE mechanism,
884 SECItem *param, SECItem *sig, const SECItem *data)
885{
886 PK11SlotInfo *slot = symKey->slot;
887 CK_MECHANISM mech = { 0, NULL((void*)0), 0 };
888 PRBool owner = PR_TRUE1;
889 CK_SESSION_HANDLE session;
890 PRBool haslock = PR_FALSE0;
891 CK_ULONG len;
892 CK_RV crv;
893
894 mech.mechanism = mechanism;
895 if (param) {
896 mech.pParameter = param->data;
897 mech.ulParameterLen = param->len;
898 }
899
900 session = pk11_GetNewSession(slot, &owner);
901 haslock = (!owner || !(slot->isThreadSafe));
902 if (haslock)
903 PK11_EnterSlotMonitor(slot);
904 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_SignInit(session, &mech, symKey->objectID);
905 if (crv != CKR_OK0x00000000UL) {
906 if (haslock)
907 PK11_ExitSlotMonitor(slot);
908 pk11_CloseSession(slot, session, owner);
909 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
910 return SECFailure;
911 }
912
913 len = sig->len;
914 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_Sign(session, data->data,
915 data->len, sig->data, &len);
916 if (haslock)
917 PK11_ExitSlotMonitor(slot);
918 pk11_CloseSession(slot, session, owner);
919 sig->len = len;
920 if (crv != CKR_OK0x00000000UL) {
921 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
922 return SECFailure;
923 }
924 return SECSuccess;
925}
926
927SECStatus
928PK11_Decrypt(PK11SymKey *symKey,
929 CK_MECHANISM_TYPE mechanism, SECItem *param,
930 unsigned char *out, unsigned int *outLen,
931 unsigned int maxLen,
932 const unsigned char *enc, unsigned encLen)
933{
934 PK11SlotInfo *slot = symKey->slot;
935 CK_MECHANISM mech = { 0, NULL((void*)0), 0 };
936 CK_ULONG len = maxLen;
937 PRBool owner = PR_TRUE1;
938 CK_SESSION_HANDLE session;
939 PRBool haslock = PR_FALSE0;
940 CK_RV crv;
941
942 mech.mechanism = mechanism;
943 if (param) {
944 mech.pParameter = param->data;
945 mech.ulParameterLen = param->len;
946 }
947
948 session = pk11_GetNewSession(slot, &owner);
949 haslock = (!owner || !slot->isThreadSafe);
950 if (haslock)
951 PK11_EnterSlotMonitor(slot);
952 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_DecryptInit(session, &mech, symKey->objectID);
953 if (crv != CKR_OK0x00000000UL) {
954 if (haslock)
955 PK11_ExitSlotMonitor(slot);
956 pk11_CloseSession(slot, session, owner);
957 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
958 return SECFailure;
959 }
960
961 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_Decrypt(session, (unsigned char *)enc, encLen,
962 out, &len);
963 if (haslock)
964 PK11_ExitSlotMonitor(slot);
965 pk11_CloseSession(slot, session, owner);
966 if (crv != CKR_OK0x00000000UL) {
967 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
968 return SECFailure;
969 }
970 *outLen = len;
971 return SECSuccess;
972}
973
974SECStatus
975PK11_Encrypt(PK11SymKey *symKey,
976 CK_MECHANISM_TYPE mechanism, SECItem *param,
977 unsigned char *out, unsigned int *outLen,
978 unsigned int maxLen,
979 const unsigned char *data, unsigned int dataLen)
980{
981 PK11SlotInfo *slot = symKey->slot;
982 CK_MECHANISM mech = { 0, NULL((void*)0), 0 };
983 CK_ULONG len = maxLen;
984 PRBool owner = PR_TRUE1;
985 CK_SESSION_HANDLE session;
986 PRBool haslock = PR_FALSE0;
987 CK_RV crv;
988
989 mech.mechanism = mechanism;
990 if (param) {
991 mech.pParameter = param->data;
992 mech.ulParameterLen = param->len;
993 }
994
995 session = pk11_GetNewSession(slot, &owner);
996 haslock = (!owner || !slot->isThreadSafe);
997 if (haslock)
998 PK11_EnterSlotMonitor(slot);
999 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_EncryptInit(session, &mech, symKey->objectID);
1000 if (crv != CKR_OK0x00000000UL) {
1001 if (haslock)
1002 PK11_ExitSlotMonitor(slot);
1003 pk11_CloseSession(slot, session, owner);
1004 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1005 return SECFailure;
1006 }
1007 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_Encrypt(session, (unsigned char *)data,
1008 dataLen, out, &len);
1009 if (haslock)
1010 PK11_ExitSlotMonitor(slot);
1011 pk11_CloseSession(slot, session, owner);
1012 if (crv != CKR_OK0x00000000UL) {
1013 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1014 return SECFailure;
1015 }
1016 *outLen = len;
1017 return SECSuccess;
1018}
1019
1020static SECStatus
1021pk11_PrivDecryptRaw(SECKEYPrivateKey *key,
1022 unsigned char *data, unsigned *outLen, unsigned int maxLen,
1023 const unsigned char *enc, unsigned encLen,
1024 CK_MECHANISM_PTR mech)
1025{
1026 PK11SlotInfo *slot = key->pkcs11Slot;
1027 CK_ULONG out = maxLen;
1028 PRBool owner = PR_TRUE1;
1029 CK_SESSION_HANDLE session;
1030 PRBool haslock = PR_FALSE0;
1031 CK_RV crv;
1032
1033 if (key->keyType != rsaKey) {
1034 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_KEY);
1035 return SECFailure;
1036 }
1037
1038 /* Why do we do a PK11_handle check here? for simple
1039 * decryption? .. because the user may have asked for 'ask always'
1040 * and this is a private key operation. In practice, thought, it's mute
1041 * since only servers wind up using this function */
1042 if (SECKEY_HAS_ATTRIBUTE_SET(key, CKA_PRIVATE)(0 != (key->staticflags & 0x1)) ? (0 != (key->staticflags
& (1U << 1))) : PK11_HasAttributeSet(key->pkcs11Slot
, key->pkcs11ID, 0x00000002UL, 0)
) {
1043 PK11_HandlePasswordCheck(slot, key->wincx);
1044 }
1045 session = pk11_GetNewSession(slot, &owner);
1046 haslock = (!owner || !(slot->isThreadSafe));
1047 if (haslock)
1048 PK11_EnterSlotMonitor(slot);
1049 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_DecryptInit(session, mech, key->pkcs11ID);
1050 if (crv != CKR_OK0x00000000UL) {
1051 if (haslock)
1052 PK11_ExitSlotMonitor(slot);
1053 pk11_CloseSession(slot, session, owner);
1054 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1055 return SECFailure;
1056 }
1057
1058 /* PKCS11 2.20 says if CKA_ALWAYS_AUTHENTICATE then
1059 * do C_Login with CKU_CONTEXT_SPECIFIC
1060 * between C_DecryptInit and C_Decrypt
1061 * ... But see note above about servers */
1062 if (SECKEY_HAS_ATTRIBUTE_SET_LOCK(key, CKA_ALWAYS_AUTHENTICATE, haslock)(0 != (key->staticflags & 0x1)) ? (0 != (key->staticflags
& (1U << 2))) : pk11_HasAttributeSet_Lock(key->
pkcs11Slot, key->pkcs11ID, 0x00000202UL, haslock)
) {
1063 PK11_DoPassword(slot, session, PR_FALSE0, key->wincx, haslock, PR_TRUE1);
1064 }
1065
1066 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_Decrypt(session, (unsigned char *)enc, encLen,
1067 data, &out);
1068 if (haslock)
1069 PK11_ExitSlotMonitor(slot);
1070 pk11_CloseSession(slot, session, owner);
1071 *outLen = out;
1072 if (crv != CKR_OK0x00000000UL) {
1073 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1074 return SECFailure;
1075 }
1076 return SECSuccess;
1077}
1078
1079SECStatus
1080PK11_PubDecryptRaw(SECKEYPrivateKey *key,
1081 unsigned char *data, unsigned *outLen, unsigned int maxLen,
1082 const unsigned char *enc, unsigned encLen)
1083{
1084 CK_MECHANISM mech = { CKM_RSA_X_5090x00000003UL, NULL((void*)0), 0 };
1085 return pk11_PrivDecryptRaw(key, data, outLen, maxLen, enc, encLen, &mech);
1086}
1087
1088SECStatus
1089PK11_PrivDecryptPKCS1(SECKEYPrivateKey *key,
1090 unsigned char *data, unsigned *outLen, unsigned int maxLen,
1091 const unsigned char *enc, unsigned encLen)
1092{
1093 CK_MECHANISM mech = { CKM_RSA_PKCS0x00000001UL, NULL((void*)0), 0 };
1094 return pk11_PrivDecryptRaw(key, data, outLen, maxLen, enc, encLen, &mech);
1095}
1096
1097static SECStatus
1098pk11_PubEncryptRaw(SECKEYPublicKey *key,
1099 unsigned char *out, unsigned int *outLen,
1100 unsigned int maxLen,
1101 const unsigned char *data, unsigned dataLen,
1102 CK_MECHANISM_PTR mech, void *wincx)
1103{
1104 PK11SlotInfo *slot;
1105 CK_OBJECT_HANDLE id;
1106 CK_ULONG len = maxLen;
1107 PRBool owner = PR_TRUE1;
1108 CK_SESSION_HANDLE session;
1109 CK_RV crv;
1110
1111 slot = PK11_GetBestSlotWithAttributes(mech->mechanism, CKF_ENCRYPT0x00000100UL, 0, wincx);
1112 if (slot == NULL((void*)0)) {
1113 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MODULE);
1114 return SECFailure;
1115 }
1116
1117 id = PK11_ImportPublicKey(slot, key, PR_FALSE0);
1118
1119 if (id == CK_INVALID_HANDLE0) {
1120 PK11_FreeSlot(slot);
1121 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_KEY);
1122 return SECFailure;
1123 }
1124
1125 session = pk11_GetNewSession(slot, &owner);
1126 if (!owner || !(slot->isThreadSafe))
1127 PK11_EnterSlotMonitor(slot);
1128 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_EncryptInit(session, mech, id);
1129 if (crv != CKR_OK0x00000000UL) {
1130 if (!owner || !(slot->isThreadSafe))
1131 PK11_ExitSlotMonitor(slot);
1132 pk11_CloseSession(slot, session, owner);
1133 PK11_FreeSlot(slot);
1134 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1135 return SECFailure;
1136 }
1137 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_Encrypt(session, (unsigned char *)data, dataLen,
1138 out, &len);
1139 if (!owner || !(slot->isThreadSafe))
1140 PK11_ExitSlotMonitor(slot);
1141 pk11_CloseSession(slot, session, owner);
1142 PK11_FreeSlot(slot);
1143 *outLen = len;
1144 if (crv != CKR_OK0x00000000UL) {
1145 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1146 return SECFailure;
1147 }
1148 return SECSuccess;
1149}
1150
1151SECStatus
1152PK11_PubEncryptRaw(SECKEYPublicKey *key,
1153 unsigned char *enc,
1154 const unsigned char *data, unsigned dataLen,
1155 void *wincx)
1156{
1157 CK_MECHANISM mech = { CKM_RSA_X_5090x00000003UL, NULL((void*)0), 0 };
1158 unsigned int outLen;
1159 if (!key || key->keyType != rsaKey) {
1160 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_KEY);
1161 return SECFailure;
1162 }
1163 outLen = SECKEY_PublicKeyStrength(key);
1164 return pk11_PubEncryptRaw(key, enc, &outLen, outLen, data, dataLen, &mech,
1165 wincx);
1166}
1167
1168SECStatus
1169PK11_PubEncryptPKCS1(SECKEYPublicKey *key,
1170 unsigned char *enc,
1171 const unsigned char *data, unsigned dataLen,
1172 void *wincx)
1173{
1174 CK_MECHANISM mech = { CKM_RSA_PKCS0x00000001UL, NULL((void*)0), 0 };
1175 unsigned int outLen;
1176 if (!key || key->keyType != rsaKey) {
1177 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_KEY);
1178 return SECFailure;
1179 }
1180 outLen = SECKEY_PublicKeyStrength(key);
1181 return pk11_PubEncryptRaw(key, enc, &outLen, outLen, data, dataLen, &mech,
1182 wincx);
1183}
1184
1185SECStatus
1186PK11_PrivDecrypt(SECKEYPrivateKey *key,
1187 CK_MECHANISM_TYPE mechanism, SECItem *param,
1188 unsigned char *out, unsigned int *outLen,
1189 unsigned int maxLen,
1190 const unsigned char *enc, unsigned encLen)
1191{
1192 CK_MECHANISM mech = { mechanism, NULL((void*)0), 0 };
1193 if (param) {
1194 mech.pParameter = param->data;
1195 mech.ulParameterLen = param->len;
1196 }
1197 return pk11_PrivDecryptRaw(key, out, outLen, maxLen, enc, encLen, &mech);
1198}
1199
1200SECStatus
1201PK11_PubEncrypt(SECKEYPublicKey *key,
1202 CK_MECHANISM_TYPE mechanism, SECItem *param,
1203 unsigned char *out, unsigned int *outLen,
1204 unsigned int maxLen,
1205 const unsigned char *data, unsigned dataLen,
1206 void *wincx)
1207{
1208 CK_MECHANISM mech = { mechanism, NULL((void*)0), 0 };
1209 if (param) {
1210 mech.pParameter = param->data;
1211 mech.ulParameterLen = param->len;
1212 }
1213 return pk11_PubEncryptRaw(key, out, outLen, maxLen, data, dataLen, &mech,
1214 wincx);
1215}
1216
1217SECKEYPrivateKey *
1218PK11_UnwrapPrivKey(PK11SlotInfo *slot, PK11SymKey *wrappingKey,
1219 CK_MECHANISM_TYPE wrapType, SECItem *param,
1220 SECItem *wrappedKey, SECItem *label,
1221 const SECItem *idValue, PRBool perm, PRBool sensitive,
1222 CK_KEY_TYPE keyType, CK_ATTRIBUTE_TYPE *usage,
1223 int usageCount, void *wincx)
1224{
1225 CK_BBOOL cktrue = CK_TRUE1;
1226 CK_BBOOL ckfalse = CK_FALSE0;
1227 CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY0x00000003UL;
1228 CK_ATTRIBUTE keyTemplate[15];
1229 int templateCount = 0;
1230 CK_OBJECT_HANDLE privKeyID;
1231 CK_MECHANISM mechanism;
1232 CK_ATTRIBUTE *attrs = keyTemplate;
1233 SECItem *param_free = NULL((void*)0), *ck_id = NULL((void*)0);
1234 CK_RV crv;
1235 CK_SESSION_HANDLE rwsession;
1236 PK11SymKey *newKey = NULL((void*)0);
1237 SECKEYPrivateKey *privKey = NULL((void*)0);
1238 SECKEYPublicKey *pubKey = NULL((void*)0);
1239 int i;
1240
1241 if (!slot || !wrappedKey) {
1242 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1243 return NULL((void*)0);
1244 }
1245
1246 if (usageCount < 0 ||
1247 usageCount > (int)(PR_ARRAY_SIZE(keyTemplate)(sizeof(keyTemplate) / sizeof((keyTemplate)[0])) - 8)) {
1248 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1249 return NULL((void*)0);
1250 }
1251
1252 if (idValue) {
1253 ck_id = PK11_MakeIDFromPubKey(idValue);
1254 if (!ck_id) {
1255 return NULL((void*)0);
1256 }
1257 }
1258
1259 PK11_SETATTRS(attrs, CKA_TOKEN, perm ? &cktrue : &ckfalse,(attrs)->type = (0x00000001UL); (attrs)->pValue = (perm
? &cktrue : &ckfalse); (attrs)->ulValueLen = (sizeof
(cktrue));
1260 sizeof(cktrue))(attrs)->type = (0x00000001UL); (attrs)->pValue = (perm
? &cktrue : &ckfalse); (attrs)->ulValueLen = (sizeof
(cktrue));
;
1261 attrs++;
1262 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass))(attrs)->type = (0x00000000UL); (attrs)->pValue = (&
keyClass); (attrs)->ulValueLen = (sizeof(keyClass));
;
1263 attrs++;
1264 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType))(attrs)->type = (0x00000100UL); (attrs)->pValue = (&
keyType); (attrs)->ulValueLen = (sizeof(keyType));
;
1265 attrs++;
1266 PK11_SETATTRS(attrs, CKA_PRIVATE, sensitive ? &cktrue : &ckfalse,(attrs)->type = (0x00000002UL); (attrs)->pValue = (sensitive
? &cktrue : &ckfalse); (attrs)->ulValueLen = (sizeof
(cktrue));
1267 sizeof(cktrue))(attrs)->type = (0x00000002UL); (attrs)->pValue = (sensitive
? &cktrue : &ckfalse); (attrs)->ulValueLen = (sizeof
(cktrue));
;
1268 attrs++;
1269 PK11_SETATTRS(attrs, CKA_SENSITIVE, sensitive ? &cktrue : &ckfalse,(attrs)->type = (0x00000103UL); (attrs)->pValue = (sensitive
? &cktrue : &ckfalse); (attrs)->ulValueLen = (sizeof
(cktrue));
1270 sizeof(cktrue))(attrs)->type = (0x00000103UL); (attrs)->pValue = (sensitive
? &cktrue : &ckfalse); (attrs)->ulValueLen = (sizeof
(cktrue));
;
1271 attrs++;
1272 if (label && label->data) {
1273 PK11_SETATTRS(attrs, CKA_LABEL, label->data, label->len)(attrs)->type = (0x00000003UL); (attrs)->pValue = (label
->data); (attrs)->ulValueLen = (label->len);
;
1274 attrs++;
1275 }
1276 if (ck_id) {
1277 PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len)(attrs)->type = (0x00000102UL); (attrs)->pValue = (ck_id
->data); (attrs)->ulValueLen = (ck_id->len);
;
1278 attrs++;
1279 }
1280 for (i = 0; i < usageCount; i++) {
1281 PK11_SETATTRS(attrs, usage[i], &cktrue, sizeof(cktrue))(attrs)->type = (usage[i]); (attrs)->pValue = (&cktrue
); (attrs)->ulValueLen = (sizeof(cktrue));
;
1282 attrs++;
1283 }
1284
1285 if (idValue && PK11_IsInternal(slot)) {
1286 PK11_SETATTRS(attrs, CKA_NSS_DB, idValue->data,(attrs)->type = (0xD5A0DB00L); (attrs)->pValue = (idValue
->data); (attrs)->ulValueLen = (idValue->len);
1287 idValue->len)(attrs)->type = (0xD5A0DB00L); (attrs)->pValue = (idValue
->data); (attrs)->ulValueLen = (idValue->len);
;
1288 attrs++;
1289 }
1290
1291 templateCount = attrs - keyTemplate;
1292 PR_ASSERT(templateCount <= (sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)))((templateCount <= (sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE
))) ? ((void)0) : PR_Assert("templateCount <= (sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE))"
, "/root/firefox-clang/security/nss/lib/pk11wrap/pk11obj.c", 1292
))
;
1293
1294 mechanism.mechanism = wrapType;
1295 if (!param)
1296 param = param_free = PK11_ParamFromIV(wrapType, NULL((void*)0));
1297 if (param) {
1298 mechanism.pParameter = param->data;
1299 mechanism.ulParameterLen = param->len;
1300 } else {
1301 mechanism.pParameter = NULL((void*)0);
1302 mechanism.ulParameterLen = 0;
1303 }
1304
1305 if (wrappingKey->slot != slot) {
1306 newKey = pk11_CopyToSlot(slot, wrapType, CKA_UNWRAP0x00000107UL, wrappingKey);
1307 } else {
1308 newKey = PK11_ReferenceSymKey(wrappingKey);
1309 }
1310
1311 if (newKey) {
1312 if (perm) {
1313 /* Get RW Session will either lock the monitor if necessary,
1314 * or return a thread safe session handle, or fail. */
1315 rwsession = PK11_GetRWSession(slot);
1316 } else {
1317 rwsession = slot->session;
1318 if (rwsession != CK_INVALID_HANDLE0)
1319 PK11_EnterSlotMonitor(slot);
1320 }
1321 /* This is a lot a work to deal with fussy PKCS #11 modules
1322 * that can't bother to return BAD_DATA when presented with an
1323 * invalid session! */
1324 if (rwsession == CK_INVALID_HANDLE0) {
1325 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DATA);
1326 goto loser;
1327 }
1328 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_UnwrapKey(rwsession, &mechanism,
1329 newKey->objectID,
1330 wrappedKey->data,
1331 wrappedKey->len, keyTemplate,
1332 templateCount, &privKeyID);
1333
1334 if (perm) {
1335 PK11_RestoreROSession(slot, rwsession);
1336 } else {
1337 PK11_ExitSlotMonitor(slot);
1338 }
1339 PK11_FreeSymKey(newKey);
1340 newKey = NULL((void*)0);
1341 } else {
1342 crv = CKR_FUNCTION_NOT_SUPPORTED0x00000054UL;
1343 }
1344
1345 SECITEM_FreeItemSECITEM_FreeItem_Util(ck_id, PR_TRUE1);
1346 ck_id = NULL((void*)0);
1347
1348 if (crv != CKR_OK0x00000000UL) {
1349 /* we couldn't unwrap the key, use the internal module to do the
1350 * unwrap, then load the new key into the token */
1351 PK11SlotInfo *int_slot = PK11_GetInternalSlot();
1352
1353 if (int_slot && (slot != int_slot)) {
1354 privKey = PK11_UnwrapPrivKey(int_slot, wrappingKey, wrapType,
1355 param, wrappedKey, label,
1356 idValue, PR_FALSE0, PR_FALSE0,
1357 keyType, usage, usageCount, wincx);
1358 if (privKey) {
1359 SECKEYPrivateKey *newPrivKey = PK11_LoadPrivKey(slot, privKey,
1360 NULL((void*)0), perm, sensitive);
1361 SECKEY_DestroyPrivateKey(privKey);
1362 PK11_FreeSlot(int_slot);
1363 SECITEM_FreeItemSECITEM_FreeItem_Util(param_free, PR_TRUE1);
1364 return newPrivKey;
1365 }
1366 }
1367 if (int_slot)
1368 PK11_FreeSlot(int_slot);
1369 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1370 SECITEM_FreeItemSECITEM_FreeItem_Util(param_free, PR_TRUE1);
1371 return NULL((void*)0);
1372 }
1373 SECITEM_FreeItemSECITEM_FreeItem_Util(param_free, PR_TRUE1);
1374 privKey = pk11_MakePrivKey(slot, nullKey, !perm /*isOwner*/, privKeyID, wincx);
1375 if (!privKey) {
1376 goto loser;
1377 }
1378 /* we weren't given the public key, get it from the key itself so we
1379 * can set the CKA_ID */
1380 if (idValue == NULL((void*)0)) {
1381 SECStatus rv;
1382 pubKey = SECKEY_ConvertToPublicKey(privKey);
1383 if (pubKey == NULL((void*)0)) {
1384 goto loser;
1385 }
1386 idValue = PK11_GetPublicValueFromPublicKey(pubKey);
1387 if (idValue == NULL((void*)0)) {
1388 goto loser;
1389 }
1390 ck_id = PK11_MakeIDFromPubKey(idValue);
1391 if (ck_id == NULL((void*)0)) {
1392 goto loser;
1393 }
1394 rv = PK11_WriteRawAttribute(PK11_TypePrivKey, privKey, CKA_ID0x00000102UL, ck_id);
1395 if (rv != SECSuccess) {
1396 goto loser;
1397 }
1398 if (pubKey->pkcs11Slot) {
1399 rv = PK11_WriteRawAttribute(PK11_TypePubKey, pubKey, CKA_ID0x00000102UL, ck_id);
1400 if (rv != SECSuccess) {
1401 goto loser;
1402 }
1403 }
1404 /* try to import the public key but if it doesn't work,
1405 * it's not fatal */
1406 if (!pubKey->pkcs11Slot ||
1407 !PK11_IsPermObject(pubKey->pkcs11Slot, pubKey->pkcs11ID)) {
1408 (void)PK11_ImportPublicKey(privKey->pkcs11Slot, pubKey, PR_TRUE1);
1409 }
1410 SECKEY_DestroyPublicKey(pubKey);
1411 SECITEM_FreeItemSECITEM_FreeItem_Util(ck_id, PR_TRUE1);
1412 }
1413 return privKey;
1414
1415loser:
1416 if (newKey) {
1417 PK11_FreeSymKey(newKey);
1418 }
1419 if (privKey)
1420 SECKEY_DestroyPrivateKey(privKey);
1421 if (pubKey)
1422 SECKEY_DestroyPublicKey(pubKey);
1423 SECITEM_FreeItemSECITEM_FreeItem_Util(ck_id, PR_TRUE1);
1424 SECITEM_FreeItemSECITEM_FreeItem_Util(param_free, PR_TRUE1);
1425 return NULL((void*)0);
1426}
1427
1428/*
1429 * PK11_UnwrapPrivKeyByKeyType is like PK11_UnwrapPrivKey but uses the
1430 * keyType and the keyUsage to determine what usage attributes to set.
1431 */
1432#define _MAX_USAGE6 6
1433SECKEYPrivateKey *
1434PK11_UnwrapPrivKeyByKeyType(PK11SlotInfo *slot, PK11SymKey *wrappingKey,
1435 CK_MECHANISM_TYPE wrapType, SECItem *param,
1436 SECItem *wrappedKey, SECItem *label,
1437 const SECItem *idValue, PRBool perm, PRBool sensitive,
1438 KeyType keyType, unsigned int keyUsage, void *wincx)
1439{
1440 CK_KEY_TYPE pk11KeyType = pk11_getPKCS11KeyTypeFromKeyType(keyType);
1441 CK_ATTRIBUTE_TYPE usage[_MAX_USAGE6];
1442 int usageCount = 0;
1443 PRBool needKeyUsage = PR_FALSE0;
1444
1445 /* RSA and ecKeys can be used in more than one usage, use the
1446 * key usage to determine which usage to actual set */
1447 if ((keyType == rsaKey) || (keyType == ecKey)) {
1448 needKeyUsage = PR_TRUE1;
1449 }
1450
1451 /* use the pk11_mapXXXXKeyType functions to determine what kind
1452 * of attributes to set on the key. Using these functions reduces
1453 * the number of places we need to update to add new key types */
1454 if ((pk11_mapWrapKeyType(keyType) != CKM_INVALID_MECHANISM0xffffffffUL) &&
1455 (!needKeyUsage || keyUsage & KU_KEY_ENCIPHERMENT(0x20))) {
1456 usage[usageCount++] = CKA_UNWRAP0x00000107UL;
1457 usage[usageCount++] = CKA_DECRYPT0x00000105UL;
1458 }
1459 if ((pk11_mapKemKeyType(keyType) != CKM_INVALID_MECHANISM0xffffffffUL) &&
1460 (!needKeyUsage || keyUsage & KU_KEY_AGREEMENT(0x08))) {
1461 usage[usageCount++] = CKA_DECAPSULATE0x00000634UL;
1462 }
1463 if ((PK11_MapSignKeyType(keyType) != CKM_INVALID_MECHANISM0xffffffffUL) &&
1464 (!needKeyUsage || keyUsage & KU_DIGITAL_SIGNATURE(0x80))) {
1465 usage[usageCount++] = CKA_SIGN0x00000108UL;
1466 if (keyType == rsaKey) {
1467 usage[usageCount++] = CKA_SIGN_RECOVER0x00000109UL;
1468 }
1469 }
1470 if ((pk11_mapDeriveKeyType(keyType) != CKM_INVALID_MECHANISM0xffffffffUL) &&
1471 (!needKeyUsage || keyUsage & KU_KEY_AGREEMENT(0x08))) {
1472 usage[usageCount++] = CKA_DERIVE0x0000010CUL;
1473 }
1474
1475 PORT_Assert(usageCount <= _MAX_USAGE)((usageCount <= 6) ? ((void)0) : PR_Assert("usageCount <= _MAX_USAGE"
, "/root/firefox-clang/security/nss/lib/pk11wrap/pk11obj.c", 1475
))
;
1476
1477 if (usageCount == 0) {
1478 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1479 }
1480 return PK11_UnwrapPrivKey(slot, wrappingKey, wrapType, param, wrappedKey,
1481 label, idValue, perm, sensitive, pk11KeyType,
1482 usage, usageCount, wincx);
1483}
1484
1485/*
1486 * Now we're going to wrap a SECKEYPrivateKey with a PK11SymKey
1487 * The strategy is to get both keys to reside in the same slot,
1488 * one that can perform the desired crypto mechanism and then
1489 * call C_WrapKey after all the setup has taken place.
1490 */
1491SECStatus
1492PK11_WrapPrivKey(PK11SlotInfo *slot, PK11SymKey *wrappingKey,
1493 SECKEYPrivateKey *privKey, CK_MECHANISM_TYPE wrapType,
1494 SECItem *param, SECItem *wrappedKey, void *wincx)
1495{
1496 PK11SlotInfo *privSlot = privKey->pkcs11Slot; /* The slot where
1497 * the private key
1498 * we are going to
1499 * wrap lives.
1500 */
1501 PK11SymKey *newSymKey = NULL((void*)0);
1502 SECKEYPrivateKey *newPrivKey = NULL((void*)0);
1503 SECItem *param_free = NULL((void*)0);
1504 CK_ULONG len = wrappedKey->len;
1505 CK_MECHANISM mech;
1506 CK_RV crv;
1507
1508 if (!privSlot || !PK11_DoesMechanism(privSlot, wrapType)) {
1509 /* Figure out a slot that does the mechanism and try to import
1510 * the private key onto that slot.
1511 */
1512 PK11SlotInfo *int_slot = PK11_GetInternalSlot();
1513
1514 privSlot = int_slot; /* The private key has a new home */
1515 newPrivKey = PK11_LoadPrivKey(privSlot, privKey, NULL((void*)0), PR_FALSE0, PR_FALSE0);
1516 /* newPrivKey has allocated its own reference to the slot, so it's
1517 * safe until we destroy newPrivkey.
1518 */
1519 PK11_FreeSlot(int_slot);
1520 if (newPrivKey == NULL((void*)0)) {
1521 return SECFailure;
1522 }
1523 privKey = newPrivKey;
1524 }
1525
1526 if (privSlot != wrappingKey->slot) {
1527 newSymKey = pk11_CopyToSlot(privSlot, wrapType, CKA_WRAP0x00000106UL,
1528 wrappingKey);
1529 wrappingKey = newSymKey;
1530 }
1531
1532 if (wrappingKey == NULL((void*)0)) {
1533 if (newPrivKey) {
1534 SECKEY_DestroyPrivateKey(newPrivKey);
1535 }
1536 return SECFailure;
1537 }
1538 mech.mechanism = wrapType;
1539 if (!param) {
1540 param = param_free = PK11_ParamFromIV(wrapType, NULL((void*)0));
1541 }
1542 if (param) {
1543 mech.pParameter = param->data;
1544 mech.ulParameterLen = param->len;
1545 } else {
1546 mech.pParameter = NULL((void*)0);
1547 mech.ulParameterLen = 0;
1548 }
1549
1550 PK11_EnterSlotMonitor(privSlot);
1551 crv = PK11_GETTAB(privSlot)((CK_FUNCTION_LIST_3_2_PTR)((privSlot)->functionList))->C_WrapKey(privSlot->session, &mech,
1552 wrappingKey->objectID,
1553 privKey->pkcs11ID,
1554 wrappedKey->data, &len);
1555 PK11_ExitSlotMonitor(privSlot);
1556
1557 if (newSymKey) {
1558 PK11_FreeSymKey(newSymKey);
1559 }
1560 if (newPrivKey) {
1561 SECKEY_DestroyPrivateKey(newPrivKey);
1562 }
1563 if (param_free) {
1564 SECITEM_FreeItemSECITEM_FreeItem_Util(param_free, PR_TRUE1);
1565 }
1566
1567 if (crv != CKR_OK0x00000000UL) {
1568 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1569 return SECFailure;
1570 }
1571
1572 wrappedKey->len = len;
1573 return SECSuccess;
1574}
1575
1576#if 0
1577/*
1578 * Sample code relating to linked list returned by PK11_FindGenericObjects
1579 */
1580
1581/*
1582 * You can walk the list with the following code:
1583 */
1584 firstObj = PK11_FindGenericObjects(slot, objClass);
1585 for (thisObj=firstObj;
1586 thisObj;
1587 thisObj=PK11_GetNextGenericObject(thisObj)) {
1588 /* operate on thisObj */
1589 }
1590/*
1591 * If you want a particular object from the list...
1592 */
1593 firstObj = PK11_FindGenericObjects(slot, objClass);
1594 for (thisObj=firstObj;
1595 thisObj;
1596 thisObj=PK11_GetNextGenericObject(thisObj)) {
1597 if (isMyObj(thisObj)) {
1598 if ( thisObj == firstObj) {
1599 /* NOTE: firstObj could be NULL at this point */
1600 firstObj = PK11_GetNextGenericObject(thsObj);
1601 }
1602 PK11_UnlinkGenericObject(thisObj);
1603 myObj = thisObj;
1604 break;
1605 }
1606 }
1607
1608 PK11_DestroyGenericObjects(firstObj);
1609
1610 /* use myObj */
1611
1612 PK11_DestroyGenericObject(myObj);
1613#endif /* sample code */
1614
1615/*
1616 * return a linked, non-circular list of generic objects.
1617 * If you are only interested
1618 * in one object, just use the first object in the list. To find the
1619 * rest of the list use PK11_GetNextGenericObject() to return the next object.
1620 */
1621PK11GenericObject *
1622PK11_FindGenericObjects(PK11SlotInfo *slot, CK_OBJECT_CLASS objClass)
1623{
1624 CK_ATTRIBUTE template[1];
1625 CK_ATTRIBUTE *attrs = template;
1626 CK_OBJECT_HANDLE *objectIDs = NULL((void*)0);
1627 PK11GenericObject *lastObj = NULL((void*)0), *obj;
1628 PK11GenericObject *firstObj = NULL((void*)0);
1629 int i, count = 0;
1630
1631 PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass))(attrs)->type = (0x00000000UL); (attrs)->pValue = (&
objClass); (attrs)->ulValueLen = (sizeof(objClass));
;
1632 attrs++;
1633
1634 objectIDs = pk11_FindObjectsByTemplate(slot, template, 1, &count);
1635 if (objectIDs == NULL((void*)0)) {
1636 return NULL((void*)0);
1637 }
1638
1639 /* where we connect our object once we've created it.. */
1640 for (i = 0; i < count; i++) {
1641 obj = PORT_New(PK11GenericObject)(PK11GenericObject *)PORT_Alloc_Util(sizeof(PK11GenericObject
))
;
1642 if (!obj) {
1643 if (firstObj) {
1644 PK11_DestroyGenericObjects(firstObj);
1645 }
1646 PORT_FreePORT_Free_Util(objectIDs);
1647 return NULL((void*)0);
1648 }
1649 /* initialize it */
1650 obj->slot = PK11_ReferenceSlot(slot);
1651 obj->objectID = objectIDs[i];
1652 obj->owner = PR_FALSE0;
1653 obj->next = NULL((void*)0);
1654 obj->prev = NULL((void*)0);
1655
1656 /* link it in */
1657 if (firstObj == NULL((void*)0)) {
1658 firstObj = obj;
1659 } else {
1660 PK11_LinkGenericObject(lastObj, obj);
1661 }
1662 lastObj = obj;
1663 }
1664 PORT_FreePORT_Free_Util(objectIDs);
1665 return firstObj;
1666}
1667
1668/*
1669 * get the Next Object in the list.
1670 */
1671PK11GenericObject *
1672PK11_GetNextGenericObject(PK11GenericObject *object)
1673{
1674 return object->next;
1675}
1676
1677PK11GenericObject *
1678PK11_GetPrevGenericObject(PK11GenericObject *object)
1679{
1680 return object->prev;
1681}
1682
1683/*
1684 * Link a single object into a new list.
1685 * if the object is already in another list, remove it first.
1686 */
1687SECStatus
1688PK11_LinkGenericObject(PK11GenericObject *list, PK11GenericObject *object)
1689{
1690 PK11_UnlinkGenericObject(object);
1691 object->prev = list;
1692 object->next = list->next;
1693 list->next = object;
1694 if (object->next != NULL((void*)0)) {
1695 object->next->prev = object;
1696 }
1697 return SECSuccess;
1698}
1699
1700/*
1701 * remove an object from the list. If the object isn't already in
1702 * a list unlink becomes a noop.
1703 */
1704SECStatus
1705PK11_UnlinkGenericObject(PK11GenericObject *object)
1706{
1707 if (object->prev != NULL((void*)0)) {
1708 object->prev->next = object->next;
1709 }
1710 if (object->next != NULL((void*)0)) {
1711 object->next->prev = object->prev;
1712 }
1713
1714 object->next = NULL((void*)0);
1715 object->prev = NULL((void*)0);
1716 return SECSuccess;
1717}
1718
1719/*
1720 * This function removes a single object from the list and destroys it.
1721 * For an already unlinked object there is no difference between
1722 * PK11_DestroyGenericObject and PK11_DestroyGenericObjects
1723 */
1724SECStatus
1725PK11_DestroyGenericObject(PK11GenericObject *object)
1726{
1727 if (object == NULL((void*)0)) {
1728 return SECSuccess;
1729 }
1730
1731 PK11_UnlinkGenericObject(object);
1732 if (object->slot) {
1733 if (object->owner) {
1734 PK11_DestroyObject(object->slot, object->objectID);
1735 }
1736 PK11_FreeSlot(object->slot);
1737 }
1738 PORT_FreePORT_Free_Util(object);
1739 return SECSuccess;
1740}
1741
1742/*
1743 * walk down a link list of generic objects destroying them.
1744 * This will destroy all objects in a list that the object is linked into.
1745 * (the list is traversed in both directions).
1746 */
1747SECStatus
1748PK11_DestroyGenericObjects(PK11GenericObject *objects)
1749{
1750 PK11GenericObject *nextObject;
1751 PK11GenericObject *prevObject;
1752
1753 if (objects == NULL((void*)0)) {
1754 return SECSuccess;
1755 }
1756
1757 nextObject = objects->next;
Value stored to 'nextObject' is never read
1758 prevObject = objects->prev;
1759
1760 /* delete all the objects after it in the list */
1761 for (; objects; objects = nextObject) {
1762 nextObject = objects->next;
1763 PK11_DestroyGenericObject(objects);
1764 }
1765 /* delete all the objects before it in the list */
1766 for (objects = prevObject; objects; objects = prevObject) {
1767 prevObject = objects->prev;
1768 PK11_DestroyGenericObject(objects);
1769 }
1770 return SECSuccess;
1771}
1772
1773/*
1774 * Hand Create a new object and return the Generic object for our new object.
1775 */
1776PK11GenericObject *
1777pk11_CreateGenericObjectHelper(PK11SlotInfo *slot,
1778 const CK_ATTRIBUTE *pTemplate,
1779 int count, PRBool token, PRBool owner)
1780{
1781 CK_OBJECT_HANDLE objectID;
1782 PK11GenericObject *obj;
1783 CK_RV crv;
1784
1785 PK11_EnterSlotMonitor(slot);
1786 crv = PK11_CreateNewObject(slot, slot->session, pTemplate, count,
1787 token, &objectID);
1788 PK11_ExitSlotMonitor(slot);
1789 if (crv != CKR_OK0x00000000UL) {
1790 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1791 return NULL((void*)0);
1792 }
1793
1794 obj = PORT_New(PK11GenericObject)(PK11GenericObject *)PORT_Alloc_Util(sizeof(PK11GenericObject
))
;
1795 if (!obj) {
1796 /* error set by PORT_New */
1797 return NULL((void*)0);
1798 }
1799
1800 /* initialize it */
1801 obj->slot = PK11_ReferenceSlot(slot);
1802 obj->objectID = objectID;
1803 obj->owner = owner;
1804 obj->next = NULL((void*)0);
1805 obj->prev = NULL((void*)0);
1806 return obj;
1807}
1808
1809/* This is the classic interface. Applications would call this function to
1810 * create new object that would not be destroyed later. This lead to resource
1811 * leaks (and thus memory leaks in the PKCS #11 module). To solve this we have
1812 * a new interface that automatically marks objects created on the fly to be
1813 * destroyed later.
1814 * The old interface is preserved because applications like Mozilla purposefully
1815 * leak the reference to be found later with PK11_FindGenericObjects. New
1816 * applications should use the new interface PK11_CreateManagedGenericObject */
1817PK11GenericObject *
1818PK11_CreateGenericObject(PK11SlotInfo *slot, const CK_ATTRIBUTE *pTemplate,
1819 int count, PRBool token)
1820{
1821 return pk11_CreateGenericObjectHelper(slot, pTemplate, count, token,
1822 PR_FALSE0);
1823}
1824
1825/* Use this interface. It will automatically destroy any temporary objects
1826 * (token = PR_FALSE) when the PK11GenericObject is freed. Permanent objects still
1827 * need to be destroyed by hand with PK11_DestroyTokenObject.
1828 */
1829PK11GenericObject *
1830PK11_CreateManagedGenericObject(PK11SlotInfo *slot,
1831 const CK_ATTRIBUTE *pTemplate, int count, PRBool token)
1832{
1833 return pk11_CreateGenericObjectHelper(slot, pTemplate, count, token,
1834 !token);
1835}
1836
1837CK_OBJECT_HANDLE
1838PK11_GetObjectHandle(PK11ObjectType objType, void *objSpec,
1839 PK11SlotInfo **slotp)
1840{
1841 CK_OBJECT_HANDLE handle = CK_INVALID_HANDLE0;
1842 PK11SlotInfo *slot = NULL((void*)0);
1843
1844 switch (objType) {
1845 case PK11_TypeGeneric:
1846 slot = ((PK11GenericObject *)objSpec)->slot;
1847 handle = ((PK11GenericObject *)objSpec)->objectID;
1848 break;
1849 case PK11_TypePrivKey:
1850 slot = ((SECKEYPrivateKey *)objSpec)->pkcs11Slot;
1851 handle = ((SECKEYPrivateKey *)objSpec)->pkcs11ID;
1852 break;
1853 case PK11_TypePubKey:
1854 slot = ((SECKEYPublicKey *)objSpec)->pkcs11Slot;
1855 handle = ((SECKEYPublicKey *)objSpec)->pkcs11ID;
1856 break;
1857 case PK11_TypeSymKey:
1858 slot = ((PK11SymKey *)objSpec)->slot;
1859 handle = ((PK11SymKey *)objSpec)->objectID;
1860 break;
1861 case PK11_TypeCert:
1862 handle = PK11_FindObjectForCert((CERTCertificate *)objSpec, NULL((void*)0),
1863 &slot);
1864 break;
1865 default:
1866 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_UNKNOWN_OBJECT_TYPE);
1867 break;
1868 }
1869 if (slotp) {
1870 *slotp = slot;
1871 }
1872 /* paranoia. If the object doesn't have a slot, then it's handle isn't
1873 * valid either */
1874 if (slot == NULL((void*)0)) {
1875 handle = CK_INVALID_HANDLE0;
1876 }
1877 return handle;
1878}
1879
1880/*
1881 * Change an attribute on a raw object
1882 */
1883SECStatus
1884PK11_WriteRawAttribute(PK11ObjectType objType, void *objSpec,
1885 CK_ATTRIBUTE_TYPE attrType, SECItem *item)
1886{
1887 PK11SlotInfo *slot = NULL((void*)0);
1888 CK_OBJECT_HANDLE handle = 0;
1889 CK_ATTRIBUTE setTemplate;
1890 CK_RV crv;
1891 CK_SESSION_HANDLE rwsession;
1892
1893 handle = PK11_GetObjectHandle(objType, objSpec, &slot);
1894 if (handle == CK_INVALID_HANDLE0) {
1895 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_UNKNOWN_OBJECT_TYPE);
1896 return SECFailure;
1897 }
1898
1899 PK11_SETATTRS(&setTemplate, attrType, (CK_CHAR *)item->data, item->len)(&setTemplate)->type = (attrType); (&setTemplate)->
pValue = ((CK_CHAR *)item->data); (&setTemplate)->ulValueLen
= (item->len);
;
1900 rwsession = PK11_GetRWSession(slot);
1901 if (rwsession == CK_INVALID_HANDLE0) {
1902 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DATA);
1903 return SECFailure;
1904 }
1905 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_SetAttributeValue(rwsession, handle,
1906 &setTemplate, 1);
1907 PK11_RestoreROSession(slot, rwsession);
1908 if (crv != CKR_OK0x00000000UL) {
1909 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1910 return SECFailure;
1911 }
1912 return SECSuccess;
1913}
1914
1915SECStatus
1916PK11_ReadRawAttribute(PK11ObjectType objType, void *objSpec,
1917 CK_ATTRIBUTE_TYPE attrType, SECItem *item)
1918{
1919 PK11SlotInfo *slot = NULL((void*)0);
1920 CK_OBJECT_HANDLE handle = 0;
1921
1922 handle = PK11_GetObjectHandle(objType, objSpec, &slot);
1923 if (handle == CK_INVALID_HANDLE0) {
1924 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_UNKNOWN_OBJECT_TYPE);
1925 return SECFailure;
1926 }
1927
1928 return PK11_ReadAttribute(slot, handle, attrType, NULL((void*)0), item);
1929}
1930
1931SECStatus
1932PK11_ReadRawAttributes(PLArenaPool *arena, PK11ObjectType objType, void *objSpec,
1933 CK_ATTRIBUTE *pTemplate, unsigned int count)
1934{
1935 PK11SlotInfo *slot = NULL((void*)0);
1936 CK_OBJECT_HANDLE handle = 0;
1937
1938 handle = PK11_GetObjectHandle(objType, objSpec, &slot);
1939 if (handle == CK_INVALID_HANDLE0) {
1940 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_UNKNOWN_OBJECT_TYPE);
1941 return SECFailure;
1942 }
1943 CK_RV crv = PK11_GetAttributes(arena, slot, handle, pTemplate, count);
1944 if (crv != CKR_OK0x00000000UL) {
1945 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1946 return SECFailure;
1947 }
1948 return SECSuccess;
1949}
1950
1951SECStatus
1952PK11_ReadDistrustAfterAttribute(PK11SlotInfo *slot,
1953 CK_OBJECT_HANDLE object,
1954 CK_ATTRIBUTE_TYPE type,
1955 /* out */ PRBool *distrusted,
1956 /* out */ PRTime *time)
1957{
1958 if (!slot || !distrusted || !time) {
1959 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1960 return SECFailure;
1961 }
1962
1963 if (type != CKA_NSS_SERVER_DISTRUST_AFTER((0x80000000UL | 0x4E534350) + 35) && type != CKA_NSS_EMAIL_DISTRUST_AFTER((0x80000000UL | 0x4E534350) + 36)) {
1964 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1965 return SECFailure;
1966 }
1967
1968 // The CKA_NSS_SERVER_DISTRUST_AFTER and CKA_NSS_EMAIL_DISTRUST_AFTER
1969 // attributes have either a 13 byte UTCTime value or a 1 byte value
1970 // (equal to 0) indicating that no distrust after date is set.
1971 unsigned char buf[13] = { 0 };
1972 CK_ATTRIBUTE attr = { .type = type, .pValue = buf, .ulValueLen = sizeof buf };
1973 CK_RV crv;
1974
1975 PK11_EnterSlotMonitor(slot);
1976 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetAttributeValue(slot->session, object, &attr, 1);
1977 PK11_ExitSlotMonitor(slot);
1978 if (crv != CKR_OK0x00000000UL) {
1979 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1980 return SECFailure;
1981 }
1982
1983 if (attr.ulValueLen == 1 && buf[0] == 0) {
1984 // The distrust after date is not set.
1985 *distrusted = PR_FALSE0;
1986 return SECSuccess;
1987 }
1988
1989 if (attr.ulValueLen != sizeof buf) {
1990 // Ensure the date is encoded in the expected 13 byte format.
1991 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_TIME);
1992 return SECFailure;
1993 }
1994
1995 *distrusted = PR_TRUE1;
1996 SECItem item = { siUTCTime, buf, sizeof buf };
1997 return DER_UTCTimeToTimeDER_UTCTimeToTime_Util(time, &item);
1998}
1999
2000/*
2001 * return the object handle that matches the template
2002 */
2003CK_OBJECT_HANDLE
2004pk11_FindObjectByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *theTemplate, size_t tsize)
2005{
2006 CK_OBJECT_HANDLE object;
2007 CK_RV crv = CKR_SESSION_HANDLE_INVALID0x000000B3UL;
2008 CK_ULONG objectCount;
2009
2010 /*
2011 * issue the find
2012 */
2013 PK11_EnterSlotMonitor(slot);
2014 if (slot->session != CK_INVALID_HANDLE0) {
2015 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_FindObjectsInit(slot->session,
2016 theTemplate, tsize);
2017 }
2018 if (crv != CKR_OK0x00000000UL) {
2019 PK11_ExitSlotMonitor(slot);
2020 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2021 return CK_INVALID_HANDLE0;
2022 }
2023
2024 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_FindObjects(slot->session, &object, 1, &objectCount);
2025 PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_FindObjectsFinal(slot->session);
2026 PK11_ExitSlotMonitor(slot);
2027 if ((crv != CKR_OK0x00000000UL) || (objectCount < 1)) {
2028 /* shouldn't use SSL_ERROR... here */
2029 PORT_SetErrorPORT_SetError_Util(crv != CKR_OK0x00000000UL ? PK11_MapError(crv) : SSL_ERROR_NO_CERTIFICATE);
2030 return CK_INVALID_HANDLE0;
2031 }
2032
2033 /* blow up if the PKCS #11 module returns us and invalid object handle */
2034 PORT_Assert(object != CK_INVALID_HANDLE)((object != 0) ? ((void)0) : PR_Assert("object != CK_INVALID_HANDLE"
, "/root/firefox-clang/security/nss/lib/pk11wrap/pk11obj.c", 2034
))
;
2035 return object;
2036}
2037
2038/*
2039 * return all the object handles that matches the template
2040 */
2041CK_OBJECT_HANDLE *
2042pk11_FindObjectsByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate,
2043 size_t templCount, int *object_count)
2044{
2045 CK_OBJECT_HANDLE *objID = NULL((void*)0);
2046 CK_ULONG returned_count = 0;
2047 PRBool owner = PR_TRUE1;
2048 CK_SESSION_HANDLE session;
2049 PRBool haslock = PR_FALSE0;
2050 CK_RV crv = CKR_SESSION_HANDLE_INVALID0x000000B3UL;
2051
2052 session = pk11_GetNewSession(slot, &owner);
2053 haslock = (!owner || !(slot->isThreadSafe));
2054 if (haslock) {
2055 PK11_EnterSlotMonitor(slot);
2056 }
2057 if (session != CK_INVALID_HANDLE0) {
2058 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_FindObjectsInit(session,
2059 findTemplate, templCount);
2060 }
2061 if (crv != CKR_OK0x00000000UL) {
2062 if (haslock)
2063 PK11_ExitSlotMonitor(slot);
2064 pk11_CloseSession(slot, session, owner);
2065 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2066 *object_count = -1;
2067 return NULL((void*)0);
2068 }
2069
2070 /*
2071 * collect all the Matching Objects
2072 */
2073 do {
2074 CK_OBJECT_HANDLE *oldObjID = objID;
2075
2076 if (objID == NULL((void*)0)) {
2077 objID = (CK_OBJECT_HANDLE *)PORT_AllocPORT_Alloc_Util(sizeof(CK_OBJECT_HANDLE) *
2078 (*object_count + PK11_SEARCH_CHUNKSIZE10));
2079 } else {
2080 objID = (CK_OBJECT_HANDLE *)PORT_ReallocPORT_Realloc_Util(objID,
2081 sizeof(CK_OBJECT_HANDLE) * (*object_count + PK11_SEARCH_CHUNKSIZE10));
2082 }
2083
2084 if (objID == NULL((void*)0)) {
2085 if (oldObjID)
2086 PORT_FreePORT_Free_Util(oldObjID);
2087 break;
2088 }
2089 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_FindObjects(session,
2090 &objID[*object_count], PK11_SEARCH_CHUNKSIZE10, &returned_count);
2091 if (crv != CKR_OK0x00000000UL) {
2092 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2093 PORT_FreePORT_Free_Util(objID);
2094 objID = NULL((void*)0);
2095 break;
2096 }
2097 *object_count += returned_count;
2098 } while (returned_count == PK11_SEARCH_CHUNKSIZE10);
2099
2100 PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_FindObjectsFinal(session);
2101 if (haslock) {
2102 PK11_ExitSlotMonitor(slot);
2103 }
2104 pk11_CloseSession(slot, session, owner);
2105
2106 if (objID && (*object_count == 0)) {
2107 PORT_FreePORT_Free_Util(objID);
2108 return NULL((void*)0);
2109 }
2110 if (objID == NULL((void*)0))
2111 *object_count = -1;
2112 return objID;
2113}
2114
2115SECStatus
2116PK11_FindRawCertsWithSubject(PK11SlotInfo *slot, SECItem *derSubject,
2117 CERTCertificateList **results)
2118{
2119 if (!slot || !derSubject || !results) {
2120 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2121 return SECFailure;
2122 }
2123 *results = NULL((void*)0);
2124
2125 // derSubject->data may be null. If so, derSubject->len must be 0.
2126 if (!derSubject->data && derSubject->len != 0) {
2127 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2128 return SECFailure;
2129 }
2130
2131 CK_CERTIFICATE_TYPE ckc_x_509 = CKC_X_5090x00000000UL;
2132 CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE0x00000001UL;
2133 CK_ATTRIBUTE subjectTemplate[] = {
2134 { CKA_CERTIFICATE_TYPE0x00000080UL, &ckc_x_509, sizeof(ckc_x_509) },
2135 { CKA_CLASS0x00000000UL, &cko_certificate, sizeof(cko_certificate) },
2136 { CKA_SUBJECT0x00000101UL, derSubject->data, derSubject->len },
2137 };
2138 const size_t templateCount = sizeof(subjectTemplate) / sizeof(subjectTemplate[0]);
2139 int handleCount = 0;
2140 CK_OBJECT_HANDLE *handles =
2141 pk11_FindObjectsByTemplate(slot, subjectTemplate, templateCount,
2142 &handleCount);
2143 if (!handles) {
2144 // pk11_FindObjectsByTemplate indicates there was an error by setting
2145 // handleCount to -1 (and it has set an error with PORT_SetError).
2146 if (handleCount == -1) {
2147 return SECFailure;
2148 }
2149 return SECSuccess;
2150 }
2151 PORT_Assert(handleCount > 0)((handleCount > 0) ? ((void)0) : PR_Assert("handleCount > 0"
, "/root/firefox-clang/security/nss/lib/pk11wrap/pk11obj.c", 2151
))
;
2152 if (handleCount <= 0) {
2153 PORT_FreePORT_Free_Util(handles);
2154 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_LIBRARY_FAILURE);
2155 return SECFailure;
2156 }
2157 if (handleCount > INT_MAX2147483647 / sizeof(SECItem)) {
2158 PORT_FreePORT_Free_Util(handles);
2159 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_LIBRARY_FAILURE);
2160 return SECFailure;
2161 }
2162 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2163 if (!arena) {
2164 PORT_FreePORT_Free_Util(handles);
2165 return SECFailure;
2166 }
2167 CERTCertificateList *rawCertificates =
2168 PORT_ArenaNew(arena, CERTCertificateList)(CERTCertificateList *)PORT_ArenaAlloc_Util(arena, sizeof(CERTCertificateList
))
;
2169 if (!rawCertificates) {
2170 PORT_FreePORT_Free_Util(handles);
2171 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
2172 return SECFailure;
2173 }
2174 rawCertificates->arena = arena;
2175 rawCertificates->certs = PORT_ArenaNewArray(arena, SECItem, handleCount)(SECItem *)PORT_ArenaAlloc_Util(arena, sizeof(SECItem) * (handleCount
))
;
2176 if (!rawCertificates->certs) {
2177 PORT_FreePORT_Free_Util(handles);
2178 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
2179 return SECFailure;
2180 }
2181 rawCertificates->len = handleCount;
2182 int handleIndex;
2183 for (handleIndex = 0; handleIndex < handleCount; handleIndex++) {
2184 SECStatus rv =
2185 PK11_ReadAttribute(slot, handles[handleIndex], CKA_VALUE0x00000011UL, arena,
2186 &rawCertificates->certs[handleIndex]);
2187 if (rv != SECSuccess) {
2188 PORT_FreePORT_Free_Util(handles);
2189 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
2190 return SECFailure;
2191 }
2192 if (!rawCertificates->certs[handleIndex].data) {
2193 PORT_FreePORT_Free_Util(handles);
2194 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
2195 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_LIBRARY_FAILURE);
2196 return SECFailure;
2197 }
2198 }
2199 PORT_FreePORT_Free_Util(handles);
2200 *results = rawCertificates;
2201 return SECSuccess;
2202}
2203
2204/*
2205 * given a PKCS #11 object, match it's peer based on the KeyID. searchID
2206 * is typically a privateKey or a certificate while the peer is the opposite
2207 */
2208CK_OBJECT_HANDLE
2209PK11_MatchItem(PK11SlotInfo *slot, CK_OBJECT_HANDLE searchID,
2210 CK_OBJECT_CLASS matchclass)
2211{
2212 CK_ATTRIBUTE theTemplate[] = {
2213 { CKA_ID0x00000102UL, NULL((void*)0), 0 },
2214 { CKA_CLASS0x00000000UL, NULL((void*)0), 0 }
2215 };
2216 /* if you change the array, change the variable below as well */
2217 CK_ATTRIBUTE *keyclass = &theTemplate[1];
2218 const size_t tsize = sizeof(theTemplate) / sizeof(theTemplate[0]);
2219 /* if you change the array, change the variable below as well */
2220 CK_OBJECT_HANDLE peerID;
2221 PORTCheapArenaPool tmpArena;
2222 CK_RV crv;
2223
2224 /* now we need to create space for the public key */
2225 PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE(2048));
2226
2227 crv = PK11_GetAttributes(&tmpArena.arena, slot, searchID, theTemplate, tsize);
2228 if (crv != CKR_OK0x00000000UL) {
2229 PORT_DestroyCheapArena(&tmpArena);
2230 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2231 return CK_INVALID_HANDLE0;
2232 }
2233
2234 if ((theTemplate[0].ulValueLen == 0) || (theTemplate[0].ulValueLen == -1)) {
2235 PORT_DestroyCheapArena(&tmpArena);
2236 if (matchclass == CKO_CERTIFICATE0x00000001UL) {
2237 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_KEY);
2238 } else {
2239 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_KEY);
2240 }
2241 return CK_INVALID_HANDLE0;
2242 }
2243
2244 /*
2245 * issue the find
2246 */
2247 *(CK_OBJECT_CLASS *)(keyclass->pValue) = matchclass;
2248
2249 peerID = pk11_FindObjectByTemplate(slot, theTemplate, tsize);
2250 PORT_DestroyCheapArena(&tmpArena);
2251
2252 return peerID;
2253}
2254
2255/*
2256 * count the number of objects that match the template.
2257 */
2258int
2259PK11_NumberObjectsFor(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate,
2260 int templCount)
2261{
2262 CK_OBJECT_HANDLE objID[PK11_SEARCH_CHUNKSIZE10];
2263 int object_count = 0;
2264 CK_ULONG returned_count = 0;
2265 CK_RV crv = CKR_SESSION_HANDLE_INVALID0x000000B3UL;
2266
2267 PK11_EnterSlotMonitor(slot);
2268 if (slot->session != CK_INVALID_HANDLE0) {
2269 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_FindObjectsInit(slot->session,
2270 findTemplate, templCount);
2271 }
2272 if (crv != CKR_OK0x00000000UL) {
2273 PK11_ExitSlotMonitor(slot);
2274 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2275 return object_count;
2276 }
2277
2278 /*
2279 * collect all the Matching Objects
2280 */
2281 do {
2282 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_FindObjects(slot->session, objID,
2283 PK11_SEARCH_CHUNKSIZE10,
2284 &returned_count);
2285 if (crv != CKR_OK0x00000000UL) {
2286 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2287 break;
2288 }
2289 object_count += returned_count;
2290 } while (returned_count == PK11_SEARCH_CHUNKSIZE10);
2291
2292 PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_FindObjectsFinal(slot->session);
2293 PK11_ExitSlotMonitor(slot);
2294 return object_count;
2295}
2296
2297/*
2298 * Traverse all the objects in a given slot.
2299 */
2300SECStatus
2301PK11_TraverseSlot(PK11SlotInfo *slot, void *arg)
2302{
2303 int i;
2304 CK_OBJECT_HANDLE *objID = NULL((void*)0);
2305 int object_count = 0;
2306 pk11TraverseSlot *slotcb = (pk11TraverseSlot *)arg;
2307
2308 objID = pk11_FindObjectsByTemplate(slot, slotcb->findTemplate,
2309 slotcb->templateCount, &object_count);
2310
2311 /*Actually this isn't a failure... there just were no objs to be found*/
2312 if (object_count == 0) {
2313 return SECSuccess;
2314 }
2315
2316 if (objID == NULL((void*)0)) {
2317 return SECFailure;
2318 }
2319
2320 for (i = 0; i < object_count; i++) {
2321 (*slotcb->callback)(slot, objID[i], slotcb->callbackArg);
2322 }
2323 PORT_FreePORT_Free_Util(objID);
2324 return SECSuccess;
2325}
2326
2327/*
2328 * Traverse all the objects in all slots.
2329 */
2330SECStatus
2331pk11_TraverseAllSlots(SECStatus (*callback)(PK11SlotInfo *, void *),
2332 void *arg, PRBool forceLogin, void *wincx)
2333{
2334 PK11SlotList *list;
2335 PK11SlotListElement *le;
2336 SECStatus rv;
2337
2338 /* get them all! */
2339 list = PK11_GetAllTokens(CKM_INVALID_MECHANISM0xffffffffUL, PR_FALSE0, PR_FALSE0, wincx);
2340 if (list == NULL((void*)0))
2341 return SECFailure;
2342
2343 /* look at each slot and authenticate as necessary */
2344 for (le = list->head; le; le = le->next) {
2345 if (forceLogin) {
2346 rv = pk11_AuthenticateUnfriendly(le->slot, PR_FALSE0, wincx);
2347 if (rv != SECSuccess) {
2348 continue;
2349 }
2350 }
2351 if (callback) {
2352 (*callback)(le->slot, arg);
2353 }
2354 }
2355
2356 PK11_FreeSlotList(list);
2357
2358 return SECSuccess;
2359}
2360
2361CK_OBJECT_HANDLE *
2362PK11_FindObjectsFromNickname(char *nickname, PK11SlotInfo **slotptr,
2363 CK_OBJECT_CLASS objclass, int *returnCount, void *wincx)
2364{
2365 char *tokenName;
2366 char *delimit;
2367 PK11SlotInfo *slot;
2368 CK_OBJECT_HANDLE *objID;
2369 CK_ATTRIBUTE findTemplate[] = {
2370 { CKA_LABEL0x00000003UL, NULL((void*)0), 0 },
2371 { CKA_CLASS0x00000000UL, NULL((void*)0), 0 },
2372 };
2373 const size_t findCount = sizeof(findTemplate) / sizeof(findTemplate[0]);
2374 SECStatus rv;
2375 PK11_SETATTRS(&findTemplate[1], CKA_CLASS, &objclass, sizeof(objclass))(&findTemplate[1])->type = (0x00000000UL); (&findTemplate
[1])->pValue = (&objclass); (&findTemplate[1])->
ulValueLen = (sizeof(objclass));
;
2376
2377 *slotptr = slot = NULL((void*)0);
2378 *returnCount = 0;
2379 /* first find the slot associated with this nickname */
2380 if ((delimit = PORT_Strchrstrchr(nickname, ':')) != NULL((void*)0)) {
2381 int len = delimit - nickname;
2382 tokenName = (char *)PORT_AllocPORT_Alloc_Util(len + 1);
2383 if (!tokenName) {
2384 return CK_INVALID_HANDLE0;
2385 }
2386 PORT_Memcpymemcpy(tokenName, nickname, len);
2387 tokenName[len] = 0;
2388
2389 slot = *slotptr = PK11_FindSlotByName(tokenName);
2390 PORT_FreePORT_Free_Util(tokenName);
2391 /* if we couldn't find a slot, assume the nickname is an internal cert
2392 * with no proceding slot name */
2393 if (slot == NULL((void*)0)) {
2394 slot = *slotptr = PK11_GetInternalKeySlot();
2395 } else {
2396 nickname = delimit + 1;
2397 }
2398 } else {
2399 *slotptr = slot = PK11_GetInternalKeySlot();
2400 }
2401 if (slot == NULL((void*)0)) {
2402 return CK_INVALID_HANDLE0;
2403 }
2404
2405 rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE1, wincx);
2406 if (rv != SECSuccess) {
2407 PK11_FreeSlot(slot);
2408 *slotptr = NULL((void*)0);
2409 return CK_INVALID_HANDLE0;
2410 }
2411
2412 findTemplate[0].pValue = nickname;
2413 findTemplate[0].ulValueLen = PORT_Strlen(nickname)strlen(nickname);
2414 objID = pk11_FindObjectsByTemplate(slot, findTemplate, findCount, returnCount);
2415 if (objID == NULL((void*)0)) {
2416 /* PKCS #11 isn't clear on whether or not the NULL is
2417 * stored in the template.... try the find again with the
2418 * full null terminated string. */
2419 findTemplate[0].ulValueLen += 1;
2420 objID = pk11_FindObjectsByTemplate(slot, findTemplate, findCount,
2421 returnCount);
2422 if (objID == NULL((void*)0)) {
2423 /* Well that's the best we can do. It's just not here */
2424 /* what about faked nicknames? */
2425 PK11_FreeSlot(slot);
2426 *slotptr = NULL((void*)0);
2427 *returnCount = 0;
2428 }
2429 }
2430
2431 return objID;
2432}
2433
2434SECItem *
2435pk11_GetLowLevelKeyFromHandle(PK11SlotInfo *slot, CK_OBJECT_HANDLE handle)
2436{
2437 CK_ATTRIBUTE theTemplate[] = {
2438 { CKA_ID0x00000102UL, NULL((void*)0), 0 },
2439 };
2440 int tsize = sizeof(theTemplate) / sizeof(theTemplate[0]);
2441 CK_RV crv;
2442 SECItem *item;
2443
2444 item = SECITEM_AllocItemSECITEM_AllocItem_Util(NULL((void*)0), NULL((void*)0), 0);
2445
2446 if (item == NULL((void*)0)) {
2447 return NULL((void*)0);
2448 }
2449
2450 crv = PK11_GetAttributes(NULL((void*)0), slot, handle, theTemplate, tsize);
2451 if (crv != CKR_OK0x00000000UL) {
2452 SECITEM_FreeItemSECITEM_FreeItem_Util(item, PR_TRUE1);
2453 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2454 return NULL((void*)0);
2455 }
2456
2457 item->data = (unsigned char *)theTemplate[0].pValue;
2458 item->len = theTemplate[0].ulValueLen;
2459
2460 return item;
2461}
2462
2463PRBool
2464PK11_ObjectGetFIPSStatus(PK11ObjectType objType, void *objSpec)
2465{
2466 PK11SlotInfo *slot = NULL((void*)0);
2467 CK_OBJECT_HANDLE handle = 0;
2468
2469 handle = PK11_GetObjectHandle(objType, objSpec, &slot);
2470 if (handle == CK_INVALID_HANDLE0) {
2471 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_UNKNOWN_OBJECT_TYPE);
2472 return PR_FALSE0;
2473 }
2474 return pk11slot_GetFIPSStatus(slot, slot->session, handle,
2475 CKT_NSS_OBJECT_CHECK2UL);
2476}