Bug Summary

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