Bug Summary

File:root/firefox-clang/security/nss/lib/pk11wrap/pk11obj.c
Warning:line 1760, column 5
Value stored to 'nextObject' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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