Bug Summary

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