Bug Summary

File:root/firefox-clang/security/nss/lib/softoken/pkcs11u.c
Warning:line 2104, column 17
Null pointer passed to 1st parameter expecting 'nonnull'

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 pkcs11u.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/softoken/softoken_softokn -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/softoken/softoken_softokn -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 SOFTOKEN_LIB_NAME="libsoftokn3.so" -D 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/softoken -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/softoken/softoken_softokn -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/softoken/pkcs11u.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 * Internal PKCS #11 functions. Should only be called by pkcs11.c
6 */
7#include "pkcs11.h"
8#include "pkcs11i.h"
9#include "lowkeyi.h"
10#include "secasn1.h"
11#include "blapi.h"
12#include "secerr.h"
13#include "prnetdb.h" /* for PR_ntohl */
14#include "sftkdb.h"
15#include "softoken.h"
16#include "secoid.h"
17#include "softkver.h"
18
19#if !defined(NSS_FIPS_DISABLED1) && defined(NSS_ENABLE_FIPS_INDICATORS)
20/* handle special cases. Classes require existing code to already be
21 * in place for that class */
22typedef enum {
23 SFTKFIPSNone = 0,
24 SFTKFIPSDH, /* allow only specific primes */
25 SFTKFIPSECC, /* not just keys but specific curves */
26 SFTKFIPSAEAD, /* single shot AEAD functions not allowed in FIPS mode */
27 SFTKFIPSRSAPSS, /* make sure salt isn't too big */
28 SFTKFIPSPBKDF2, /* handle pbkdf2 FIPS restrictions */
29 SFTKFIPSTlsKeyCheck, /* check the output of TLS prf functions */
30 SFTKFIPSChkHash, /* make sure the base hash of KDF functions is FIPS */
31 SFTKFIPSChkHashTls, /* make sure the base hash of TLS KDF functions is FIPS */
32 SFTKFIPSChkHashSp800, /* make sure the base hash of SP-800-108 KDF functions is FIPS */
33 SFTKFIPSRSAOAEP, /* make sure that both hashes use the same FIPS compliant algorithm */
34} SFTKFIPSSpecialClass;
35
36typedef struct SFTKFIPSAlgorithmListStr SFTKFIPSAlgorithmList;
37struct SFTKFIPSAlgorithmListStr {
38 CK_MECHANISM_TYPE type;
39 CK_MECHANISM_INFO info;
40 CK_ULONG step;
41 SFTKFIPSSpecialClass special;
42 size_t offset;
43};
44/* this file should be supplied by the vendor and include all the
45 * algorithms which have Algorithm certs and have been reviewed by
46 * the lab. A blank file is included for the base so that FIPS mode
47 * will still be compiled and run, but FIPS indicators will always
48 * return PR_FALSE
49 */
50#include "fips_algorithms.h"
51
52#ifndef SFTKFIPS_PBKDF2_MIN_PW_LEN /* allow fips_algorithms.h to override */
53#define SFTKFIPS_PBKDF2_MIN_PW_LEN 8
54#endif
55#define NSS_HAS_FIPS_INDICATORS 1
56#endif
57
58/*
59 * ******************** Error mapping *******************************
60 */
61/*
62 * map all the SEC_ERROR_xxx error codes that may be returned by freebl
63 * functions to CKR_xxx. return CKR_DEVICE_ERROR by default for backward
64 * compatibility.
65 */
66CK_RV
67sftk_MapCryptError(int error)
68{
69 switch (error) {
70 case SEC_ERROR_INVALID_ARGS:
71 case SEC_ERROR_BAD_DATA: /* MP_RANGE gets mapped to this */
72 return CKR_ARGUMENTS_BAD0x00000007UL;
73 case SEC_ERROR_INPUT_LEN:
74 return CKR_DATA_LEN_RANGE0x00000021UL;
75 case SEC_ERROR_OUTPUT_LEN:
76 return CKR_BUFFER_TOO_SMALL0x00000150UL;
77 case SEC_ERROR_LIBRARY_FAILURE:
78 return CKR_GENERAL_ERROR0x00000005UL;
79 case SEC_ERROR_NO_MEMORY:
80 return CKR_HOST_MEMORY0x00000002UL;
81 case SEC_ERROR_BAD_SIGNATURE:
82 return CKR_SIGNATURE_INVALID0x000000C0UL;
83 case SEC_ERROR_INVALID_KEY:
84 return CKR_KEY_SIZE_RANGE0x00000062UL;
85 case SEC_ERROR_BAD_KEY: /* an EC public key that fails validation */
86 return CKR_KEY_SIZE_RANGE0x00000062UL; /* the closest error code */
87 case SEC_ERROR_UNSUPPORTED_EC_POINT_FORM:
88 return CKR_TEMPLATE_INCONSISTENT0x000000D1UL;
89 case SEC_ERROR_UNSUPPORTED_KEYALG:
90 return CKR_MECHANISM_INVALID0x00000070UL;
91 case SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE:
92 return CKR_DOMAIN_PARAMS_INVALID0x00000130UL;
93 /* key pair generation failed after max number of attempts */
94 case SEC_ERROR_NEED_RANDOM:
95 return CKR_FUNCTION_FAILED0x00000006UL;
96 }
97 return CKR_DEVICE_ERROR0x00000030UL;
98}
99
100/*
101 * functions which adjust the mapping based on different contexts
102 * (Decrypt or Verify).
103 */
104
105/* used by Decrypt and UnwrapKey (indirectly) and Decrypt message */
106CK_RV
107sftk_MapDecryptError(int error)
108{
109 switch (error) {
110 /* usually a padding error, or aead tag mismatch */
111 case SEC_ERROR_BAD_DATA:
112 return CKR_ENCRYPTED_DATA_INVALID0x00000040UL;
113 default:
114 return sftk_MapCryptError(error);
115 }
116}
117
118/*
119 * return CKR_SIGNATURE_INVALID instead of CKR_DEVICE_ERROR by default for
120 * backward compatibilty.
121 */
122CK_RV
123sftk_MapVerifyError(int error)
124{
125 CK_RV crv = sftk_MapCryptError(error);
126 if (crv == CKR_DEVICE_ERROR0x00000030UL)
127 crv = CKR_SIGNATURE_INVALID0x000000C0UL;
128 return crv;
129}
130
131/*
132 * ******************** Attribute Utilities *******************************
133 */
134
135/*
136 * create a new attribute with type, value, and length. Space is allocated
137 * to hold value.
138 */
139static SFTKAttribute *
140sftk_InitAttribute(SFTKSessionObject *so, int index,
141 CK_ATTRIBUTE_TYPE type, const void *value, CK_ULONG len)
142{
143 SFTKAttribute *attribute;
144
145 PORT_Assert(index < MAX_OBJS_ATTRS)((index < 45) ? ((void)0) : PR_Assert("index < MAX_OBJS_ATTRS"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 145
))
;
146 if (index >= MAX_OBJS_ATTRS45)
147 return NULL((void*)0);
148
149 attribute = &so->attrList[index];
150 attribute->attrib.type = type;
151 attribute->freeAttr = PR_FALSE0;
152 attribute->freeData = PR_FALSE0;
153 if (value) {
154 if (len <= ATTR_SPACE50) {
155 attribute->attrib.pValue = attribute->space;
156 } else {
157 attribute->attrib.pValue = PORT_AllocPORT_Alloc_Util(len);
158 attribute->freeData = PR_TRUE1;
159 }
160 if (attribute->attrib.pValue == NULL((void*)0)) {
161 return NULL((void*)0);
162 }
163 PORT_Memcpymemcpy(attribute->attrib.pValue, value, len);
164 attribute->attrib.ulValueLen = len;
165 } else {
166 attribute->attrib.pValue = NULL((void*)0);
167 attribute->attrib.ulValueLen = 0;
168 }
169 attribute->attrib.type = type;
170 attribute->handle = type;
171 attribute->next = attribute->prev = NULL((void*)0);
172 return attribute;
173}
174
175static SFTKAttribute *
176sftk_NewAttribute(SFTKObject *object,
177 CK_ATTRIBUTE_TYPE type, const void *value, CK_ULONG len)
178{
179 SFTKSessionObject *so = sftk_narrowToSessionObject(object);
180 int index;
181
182 if (so == NULL((void*)0)) {
183 /* allocate new attribute in a buffer */
184 PORT_Assert(0)((0) ? ((void)0) : PR_Assert("0", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 184))
;
185 return NULL((void*)0);
186 }
187 /*
188 * We attempt to keep down contention on Malloc and Arena locks by
189 * limiting the number of these calls on high traversed paths. This
190 * is done for attributes by 'allocating' them from a pool already
191 * allocated by the parent object.
192 */
193 PR_Lock(so->attributeLock);
194 index = so->nextAttr++;
195 PR_Unlock(so->attributeLock);
196 return sftk_InitAttribute(so, index, type, value, len);
197}
198
199/*
200 * Free up all the memory associated with an attribute. Reference count
201 * must be zero to call this.
202 */
203static void
204sftk_DestroyAttribute(SFTKAttribute *attribute)
205{
206 if (attribute->attrib.pValue) {
207 /* clear out the data in the attribute value... it may have been
208 * sensitive data */
209 PORT_Memsetmemset(attribute->attrib.pValue, 0, attribute->attrib.ulValueLen);
210 if (attribute->freeData) {
211 PORT_FreePORT_Free_Util(attribute->attrib.pValue);
212 attribute->attrib.pValue = NULL((void*)0);
213 attribute->freeData = PR_FALSE0;
214 }
215 }
216 if (attribute->freeAttr) {
217 PORT_FreePORT_Free_Util(attribute);
218 }
219}
220
221/*
222 * release a reference to an attribute structure
223 */
224void
225sftk_FreeAttribute(SFTKAttribute *attribute)
226{
227 if (attribute && attribute->freeAttr) {
228 sftk_DestroyAttribute(attribute);
229 return;
230 }
231}
232
233static SFTKAttribute *
234sftk_FindTokenAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
235{
236 SFTKAttribute *myattribute = NULL((void*)0);
237 SFTKDBHandle *dbHandle = NULL((void*)0);
238 CK_RV crv = CKR_HOST_MEMORY0x00000002UL;
239
240 if (object == NULL((void*)0)) {
241 return NULL((void*)0);
242 }
243 myattribute = (SFTKAttribute *)PORT_AllocPORT_Alloc_Util(sizeof(SFTKAttribute));
244 if (myattribute == NULL((void*)0)) {
245 goto loser;
246 }
247
248 dbHandle = sftk_getDBForTokenObject(object->obj.slot, object->obj.handle);
249
250 myattribute->handle = type;
251 myattribute->attrib.type = type;
252 myattribute->attrib.pValue = myattribute->space;
253 myattribute->attrib.ulValueLen = ATTR_SPACE50;
254 myattribute->next = myattribute->prev = NULL((void*)0);
255 myattribute->freeAttr = PR_TRUE1;
256 myattribute->freeData = PR_FALSE0;
257
258 crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle,
259 &myattribute->attrib, 1);
260
261 /* attribute is bigger than our attribute space buffer, malloc it */
262 if (crv == CKR_BUFFER_TOO_SMALL0x00000150UL) {
263 myattribute->attrib.pValue = NULL((void*)0);
264 crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle,
265 &myattribute->attrib, 1);
266 if (crv != CKR_OK0x00000000UL) {
267 goto loser;
268 }
269 myattribute->attrib.pValue = PORT_AllocPORT_Alloc_Util(myattribute->attrib.ulValueLen);
270 if (myattribute->attrib.pValue == NULL((void*)0)) {
271 crv = CKR_HOST_MEMORY0x00000002UL;
272 goto loser;
273 }
274 myattribute->freeData = PR_TRUE1;
275 crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle,
276 &myattribute->attrib, 1);
277 }
278loser:
279 if (dbHandle) {
280 sftk_freeDB(dbHandle);
281 }
282 if (crv != CKR_OK0x00000000UL) {
283 if (myattribute) {
284 myattribute->attrib.ulValueLen = 0;
285 sftk_FreeAttribute(myattribute);
286 myattribute = NULL((void*)0);
287 }
288 }
289 return myattribute;
290}
291
292/*
293 * Make a detached, owned copy of a session object's attribute. Must be
294 * called with sessObject->attributeLock held so the (pValue, ulValueLen)
295 * pair is captured atomically with respect to sftk_forceAttribute() and
296 * friends. The copy carries freeAttr = PR_TRUE, so sftk_FreeAttribute()
297 * releases it; callers may read it without holding any lock.
298 */
299static SFTKAttribute *
300sftk_CopyAttribute(const SFTKAttribute *attribute)
301{
302 SFTKAttribute *copy = (SFTKAttribute *)PORT_AllocPORT_Alloc_Util(sizeof(SFTKAttribute));
303 if (copy == NULL((void*)0)) {
19
Assuming 'copy' is not equal to NULL
20
Taking false branch
304 return NULL((void*)0);
305 }
306 copy->next = copy->prev = NULL((void*)0);
307 copy->freeAttr = PR_TRUE1;
308 copy->freeData = PR_FALSE0;
309 copy->handle = attribute->handle;
310 copy->attrib.type = attribute->attrib.type;
311 if (attribute->attrib.pValue == NULL((void*)0)) {
21
Assuming field 'pValue' is equal to NULL
22
Taking true branch
312 copy->attrib.pValue = NULL((void*)0);
23
Null pointer value stored to field 'pValue'
313 copy->attrib.ulValueLen = 0;
314 return copy;
315 }
316 if (attribute->attrib.ulValueLen <= ATTR_SPACE50) {
317 copy->attrib.pValue = copy->space;
318 } else {
319 copy->attrib.pValue = PORT_AllocPORT_Alloc_Util(attribute->attrib.ulValueLen);
320 if (copy->attrib.pValue == NULL((void*)0)) {
321 PORT_FreePORT_Free_Util(copy);
322 return NULL((void*)0);
323 }
324 copy->freeData = PR_TRUE1;
325 }
326 PORT_Memcpymemcpy(copy->attrib.pValue, attribute->attrib.pValue,
327 attribute->attrib.ulValueLen);
328 copy->attrib.ulValueLen = attribute->attrib.ulValueLen;
329 return copy;
330}
331
332/*
333 * look up and attribute structure from a type and Object structure.
334 * The returned attribute is referenced and needs to be freed when
335 * it is no longer needed.
336 */
337SFTKAttribute *
338sftk_FindAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type)
339{
340 SFTKAttribute *attribute;
341 SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
342
343 /* validation flags are stored as FIPS indicators */
344 if (type == CKA_OBJECT_VALIDATION_FLAGS0x0000061eUL) {
9
Assuming 'type' is not equal to CKA_OBJECT_VALIDATION_FLAGS
10
Taking false branch
345 return &object->validation_attribute;
346 }
347
348 if (sessObject
10.1
'sessObject' is not equal to NULL
== NULL((void*)0)) {
11
Taking false branch
349 return sftk_FindTokenAttribute(sftk_narrowToTokenObject(object), type);
350 }
351
352 /* Return a detached copy rather than the live pool entry: callers
353 * dereference attrib.pValue after the lock is dropped, while a
354 * concurrent sftk_forceAttribute() may free and reassign it.
355 * Snapshotting under the lock gives the caller a stable,
356 * private value (this matches the token-object path above). */
357 PR_Lock(sessObject->attributeLock);
358 sftkqueue_find(attribute, type, sessObject->head, sessObject->hashSize)for ((attribute) = (sessObject->head)[((PRUint32)((type) *
1791398085) & (sessObject->hashSize - 1))]; (attribute
) != ((void*)0); (attribute) = (attribute)->next) { if ((attribute
)->handle == (type)) { break; } }
;
12
Assuming 'attribute' is not equal to null
13
Loop condition is true. Entering loop body
14
Assuming 'type' is equal to field 'handle'
15
Taking true branch
359 if (attribute
16.1
'attribute' is not equal to NULL
!= NULL((void*)0)) {
16
Execution continues on line 359
17
Taking true branch
360 attribute = sftk_CopyAttribute(attribute);
18
Calling 'sftk_CopyAttribute'
24
Returning from 'sftk_CopyAttribute'
361 }
362 PR_Unlock(sessObject->attributeLock);
363
364 return (attribute);
365}
366
367/*
368 * Look up an attribute while the caller holds the object's attributeLock.
369 * Returns a BORROWED reference to the live node in sessObject->head[] (or
370 * the object's embedded validation attribute): valid only until the lock is
371 * released, and never to be passed to sftk_FreeAttribute().
372 *
373 * This is only valid for session objects (and CKA_OBJECT_VALIDATION_FLAGS).
374 * Token objects have no live node; callers that may see one must fall back
375 * to sftk_FindAttribute(). Returns NULL if the attribute is absent.
376 *
377 * The lock is NOT reentrant: while holding it, the caller must not call any
378 * attribute API that takes it itself (sftk_FindAttribute,
379 * sftk_AddAttributeType, sftk_forceAttribute, sftk_DeleteAttributeType).
380 */
381static SFTKAttribute *
382sftk_FindAttributeLocked(SFTKObject *object, CK_ATTRIBUTE_TYPE type)
383{
384 SFTKSessionObject *sessObject;
385 SFTKAttribute *attribute;
386
387 /* validation flags are stored as FIPS indicators */
388 if (type == CKA_OBJECT_VALIDATION_FLAGS0x0000061eUL) {
389 return &object->validation_attribute;
390 }
391
392 sessObject = sftk_narrowToSessionObject(object);
393 PORT_Assert(sessObject != NULL)((sessObject != ((void*)0)) ? ((void)0) : PR_Assert("sessObject != NULL"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 393
))
;
394 if (sessObject == NULL((void*)0)) {
395 return NULL((void*)0);
396 }
397
398 sftkqueue_find(attribute, type, sessObject->head, sessObject->hashSize)for ((attribute) = (sessObject->head)[((PRUint32)((type) *
1791398085) & (sessObject->hashSize - 1))]; (attribute
) != ((void*)0); (attribute) = (attribute)->next) { if ((attribute
)->handle == (type)) { break; } }
;
399 return attribute;
400}
401
402/*
403 * Take a buffer and it's length and return it's true size in bits;
404 */
405unsigned int
406sftk_GetLengthInBits(unsigned char *buf, unsigned int bufLen)
407{
408 unsigned int size = bufLen * 8;
409 unsigned int i;
410
411 /* Get the real length in bytes */
412 for (i = 0; i < bufLen; i++) {
413 unsigned char c = *buf++;
414 if (c != 0) {
415 unsigned char m;
416 for (m = 0x80; m > 0; m = m >> 1) {
417 if ((c & m) != 0) {
418 break;
419 }
420 size--;
421 }
422 break;
423 }
424 size -= 8;
425 }
426 return size;
427}
428
429/*
430 * Constrain a big num attribute. to size and padding
431 * minLength means length of the object must be greater than equal to minLength
432 * maxLength means length of the object must be less than equal to maxLength
433 * minMultiple means that object length mod minMultiple must equal 0.
434 * all input sizes are in bits.
435 * if any constraint is '0' that constraint is not checked.
436 */
437CK_RV
438sftk_ConstrainAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
439 int minLength, int maxLength, int minMultiple)
440{
441 SFTKAttribute *attribute;
442 int size = 0;
443 unsigned char *ptr;
444 SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
445 CK_RV crv = CKR_OK0x00000000UL;
446
447 if (sessObject != NULL((void*)0)) {
448 PR_Lock(sessObject->attributeLock);
449 attribute = sftk_FindAttributeLocked(object, type);
450 } else {
451 attribute = sftk_FindAttribute(object, type);
452 }
453
454 if (!attribute) {
455 crv = CKR_TEMPLATE_INCOMPLETE0x000000D0UL;
456 } else {
457 ptr = (unsigned char *)attribute->attrib.pValue;
458 if (ptr == NULL((void*)0)) {
459 crv = CKR_ATTRIBUTE_VALUE_INVALID0x00000013UL;
460 } else {
461 size = sftk_GetLengthInBits(ptr, attribute->attrib.ulValueLen);
462 }
463 }
464
465 if (sessObject != NULL((void*)0)) {
466 PR_Unlock(sessObject->attributeLock);
467 } else {
468 sftk_FreeAttribute(attribute);
469 }
470 if (crv != CKR_OK0x00000000UL) {
471 return crv;
472 }
473
474 if ((minLength != 0) && (size < minLength)) {
475 return CKR_ATTRIBUTE_VALUE_INVALID0x00000013UL;
476 }
477 if ((maxLength != 0) && (size > maxLength)) {
478 return CKR_ATTRIBUTE_VALUE_INVALID0x00000013UL;
479 }
480 if ((minMultiple != 0) && ((size % minMultiple) != 0)) {
481 return CKR_ATTRIBUTE_VALUE_INVALID0x00000013UL;
482 }
483 return CKR_OK0x00000000UL;
484}
485
486PRBool
487sftk_hasAttributeToken(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
488{
489 CK_ATTRIBUTE template;
490 CK_RV crv;
491 SFTKDBHandle *dbHandle;
492
493 if (object == NULL((void*)0)) {
494 return PR_FALSE0;
495 }
496 dbHandle = sftk_getDBForTokenObject(object->obj.slot, object->obj.handle);
497 template.type = type;
498 template.pValue = NULL((void*)0);
499 template.ulValueLen = 0;
500
501 crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle, &template, 1);
502 sftk_freeDB(dbHandle);
503
504 /* attribute is bigger than our attribute space buffer, malloc it */
505 return (crv == CKR_OK0x00000000UL) ? PR_TRUE1 : PR_FALSE0;
506}
507
508/*
509 * return true if object has attribute
510 */
511PRBool
512sftk_hasAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type)
513{
514 SFTKAttribute *attribute;
515 SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
516
517 if (sessObject == NULL((void*)0)) {
518 return sftk_hasAttributeToken(sftk_narrowToTokenObject(object), type);
519 }
520
521 PR_Lock(sessObject->attributeLock);
522 sftkqueue_find(attribute, type, sessObject->head, sessObject->hashSize)for ((attribute) = (sessObject->head)[((PRUint32)((type) *
1791398085) & (sessObject->hashSize - 1))]; (attribute
) != ((void*)0); (attribute) = (attribute)->next) { if ((attribute
)->handle == (type)) { break; } }
;
523 PR_Unlock(sessObject->attributeLock);
524
525 return (PRBool)(attribute != NULL((void*)0));
526}
527
528/*
529 * add an attribute to an object
530 */
531static void
532sftk_AddAttribute(SFTKObject *object, SFTKAttribute *attribute)
533{
534 SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
535
536 if (sessObject == NULL((void*)0))
537 return;
538 PR_Lock(sessObject->attributeLock);
539 sftkqueue_add(attribute, attribute->handle,{ int tmp = ((PRUint32)((attribute->handle) * 1791398085) &
(sessObject->hashSize - 1)); (attribute)->next = (sessObject
->head)[tmp]; (attribute)->prev = ((void*)0); if ((sessObject
->head)[tmp]) (sessObject->head)[tmp]->prev = (attribute
); (sessObject->head)[tmp] = (attribute); }
540 sessObject->head, sessObject->hashSize){ int tmp = ((PRUint32)((attribute->handle) * 1791398085) &
(sessObject->hashSize - 1)); (attribute)->next = (sessObject
->head)[tmp]; (attribute)->prev = ((void*)0); if ((sessObject
->head)[tmp]) (sessObject->head)[tmp]->prev = (attribute
); (sessObject->head)[tmp] = (attribute); }
;
541 PR_Unlock(sessObject->attributeLock);
542}
543
544/*
545 * copy an unsigned attribute into a SECItem. Secitem is allocated in
546 * the specified arena.
547 */
548CK_RV
549sftk_Attribute2SSecItem(PLArenaPool *arena, SECItem *item, SFTKObject *object,
550 CK_ATTRIBUTE_TYPE type)
551{
552 SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
553 SFTKAttribute *attribute;
554 CK_RV crv = CKR_OK0x00000000UL;
555
556 item->data = NULL((void*)0);
557
558 if (sessObject != NULL((void*)0)) {
559 PR_Lock(sessObject->attributeLock);
560 attribute = sftk_FindAttributeLocked(object, type);
561 } else {
562 attribute = sftk_FindAttribute(object, type);
563 }
564
565 if (attribute == NULL((void*)0)) {
566 crv = CKR_TEMPLATE_INCOMPLETE0x000000D0UL;
567 } else {
568 (void)SECITEM_AllocItemSECITEM_AllocItem_Util(arena, item, attribute->attrib.ulValueLen);
569 if (item->data == NULL((void*)0)) {
570 crv = CKR_HOST_MEMORY0x00000002UL;
571 } else {
572 PORT_Memcpymemcpy(item->data, attribute->attrib.pValue, item->len);
573 }
574 }
575
576 if (sessObject != NULL((void*)0)) {
577 PR_Unlock(sessObject->attributeLock);
578 } else {
579 sftk_FreeAttribute(attribute);
580 }
581 return crv;
582}
583
584/*
585 * fetch multiple attributes into SECItems. Secitem data is allocated in
586 * the specified arena.
587 */
588CK_RV
589sftk_MultipleAttribute2SecItem(PLArenaPool *arena, SFTKObject *object,
590 SFTKItemTemplate *itemTemplate, int itemTemplateCount)
591{
592
593 CK_RV crv = CKR_OK0x00000000UL;
594 CK_ATTRIBUTE templateSpace[SFTK_MAX_ITEM_TEMPLATE10];
595 CK_ATTRIBUTE *template;
596 SFTKTokenObject *tokObject;
597 SFTKDBHandle *dbHandle = NULL((void*)0);
598 int i;
599
600 tokObject = sftk_narrowToTokenObject(object);
601
602 /* session objects, just loop through the list */
603 if (tokObject == NULL((void*)0)) {
604 for (i = 0; i < itemTemplateCount; i++) {
605 crv = sftk_Attribute2SecItem(arena, itemTemplate[i].item, object,
606 itemTemplate[i].type);
607 if (crv != CKR_OK0x00000000UL) {
608 return crv;
609 }
610 }
611 return CKR_OK0x00000000UL;
612 }
613
614 /* don't do any work if none is required */
615 if (itemTemplateCount == 0) {
616 return CKR_OK0x00000000UL;
617 }
618
619 /* don't allocate the template unless we need it */
620 if (itemTemplateCount > SFTK_MAX_ITEM_TEMPLATE10) {
621 template = PORT_NewArray(CK_ATTRIBUTE, itemTemplateCount)(CK_ATTRIBUTE *)PORT_Alloc_Util(sizeof(CK_ATTRIBUTE) * (itemTemplateCount
))
;
622 } else {
623 template = templateSpace;
624 }
625
626 if (template == NULL((void*)0)) {
627 crv = CKR_HOST_MEMORY0x00000002UL;
628 goto loser;
629 }
630
631 dbHandle = sftk_getDBForTokenObject(object->slot, object->handle);
632 if (dbHandle == NULL((void*)0)) {
633 crv = CKR_OBJECT_HANDLE_INVALID0x00000082UL;
634 goto loser;
635 }
636
637 /* set up the PKCS #11 template */
638 for (i = 0; i < itemTemplateCount; i++) {
639 template[i].type = itemTemplate[i].type;
640 template[i].pValue = NULL((void*)0);
641 template[i].ulValueLen = 0;
642 }
643
644 /* fetch the attribute lengths */
645 crv = sftkdb_GetAttributeValue(dbHandle, object->handle,
646 template, itemTemplateCount);
647 if (crv != CKR_OK0x00000000UL) {
648 goto loser;
649 }
650
651 /* allocate space for the attributes */
652 for (i = 0; i < itemTemplateCount; i++) {
653 template[i].pValue = PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, template[i].ulValueLen);
654 if (template[i].pValue == NULL((void*)0)) {
655 crv = CKR_HOST_MEMORY0x00000002UL;
656 goto loser;
657 }
658 }
659
660 /* fetch the attributes */
661 crv = sftkdb_GetAttributeValue(dbHandle, object->handle,
662 template, itemTemplateCount);
663 if (crv != CKR_OK0x00000000UL) {
664 goto loser;
665 }
666
667 /* Fill in the items */
668 for (i = 0; i < itemTemplateCount; i++) {
669 itemTemplate[i].item->data = template[i].pValue;
670 itemTemplate[i].item->len = template[i].ulValueLen;
671 }
672
673loser:
674 if (template != templateSpace) {
675 PORT_FreePORT_Free_Util(template);
676 }
677 if (dbHandle) {
678 sftk_freeDB(dbHandle);
679 }
680
681 return crv;
682}
683
684/*
685 * this is only valid for CK_BBOOL type attributes. Return the state
686 * of that attribute.
687 */
688PRBool
689sftk_isTrue(SFTKObject *object, CK_ATTRIBUTE_TYPE type)
690{
691 SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
692 SFTKAttribute *attribute;
693 PRBool tok = PR_FALSE0;
694
695 /* For a session object read the live single-byte value under the lock
696 * rather than copying it out (this is a very hot path); for a token
697 * object fall back to a freed copy. */
698 if (sessObject != NULL((void*)0)) {
699 PR_Lock(sessObject->attributeLock);
700 attribute = sftk_FindAttributeLocked(object, type);
701 } else {
702 attribute = sftk_FindAttribute(object, type);
703 }
704
705 if (attribute != NULL((void*)0) && attribute->attrib.pValue != NULL((void*)0)) {
706 tok = (PRBool)(*(CK_BBOOL *)attribute->attrib.pValue);
707 }
708
709 if (sessObject != NULL((void*)0)) {
710 PR_Unlock(sessObject->attributeLock);
711 } else {
712 sftk_FreeAttribute(attribute);
713 }
714
715 return tok;
716}
717
718static CK_RV
719sftk_forceTokenAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
720 const void *value, unsigned int len)
721{
722 CK_ATTRIBUTE attribute;
723 SFTKDBHandle *dbHandle = NULL((void*)0);
724 SFTKTokenObject *to = sftk_narrowToTokenObject(object);
725 CK_RV crv;
726
727 PORT_Assert(to)((to) ? ((void)0) : PR_Assert("to", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 727))
;
728 if (to == NULL((void*)0)) {
729 return CKR_DEVICE_ERROR0x00000030UL;
730 }
731
732 dbHandle = sftk_getDBForTokenObject(object->slot, object->handle);
733
734 attribute.type = type;
735 attribute.pValue = (void *)value;
736 attribute.ulValueLen = len;
737
738 crv = sftkdb_SetAttributeValue(dbHandle, object, &attribute, 1);
739 sftk_freeDB(dbHandle);
740 return crv;
741}
742
743/*
744 * force an attribute to a specifc value.
745 */
746CK_RV
747sftk_forceAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
748 const void *value, unsigned int len)
749{
750 SFTKAttribute *attribute;
751 void *att_val = NULL((void*)0);
752 PRBool freeData = PR_FALSE0;
753
754 PORT_Assert(object)((object) ? ((void)0) : PR_Assert("object", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 754))
;
755 PORT_Assert(object->refCount)((object->refCount) ? ((void)0) : PR_Assert("object->refCount"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 755
))
;
756 PORT_Assert(object->slot)((object->slot) ? ((void)0) : PR_Assert("object->slot",
"/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 756
))
;
757 if (!object ||
758 !object->refCount ||
759 !object->slot) {
760 return CKR_DEVICE_ERROR0x00000030UL;
761 }
762 /* validation flags are stored as FIPS indicators,
763 * don't send them through the general attribute
764 * parsing */
765 if (type == CKA_OBJECT_VALIDATION_FLAGS0x0000061eUL) {
766 CK_FLAGS validation;
767 if (len != sizeof(CK_FLAGS)) {
768 return CKR_ATTRIBUTE_VALUE_INVALID0x00000013UL;
769 }
770 validation = *(CK_FLAGS *)value;
771 /* we only understand FIPS currently, don't allow setting
772 * other flags */
773 if ((validation & ~SFTK_VALIDATION_FIPS_FLAG0x00000001L) != 0) {
774 return CKR_ATTRIBUTE_VALUE_INVALID0x00000013UL;
775 }
776 object->validation_value = validation;
777 return CKR_OK0x00000000UL;
778 }
779 if (sftk_isToken(object->handle)(((object->handle) & 0x80000000L) == 0x80000000L)) {
780 return sftk_forceTokenAttribute(object, type, value, len);
781 }
782 /* After the token/validation dispatch above, this is a session
783 * object. Look up and mutate the live node under attributeLock so the
784 * (pValue, ulValueLen) pair stays consistent for concurrent readers,
785 * which snapshot it under the same lock in sftk_FindAttribute(). */
786 SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
787 PORT_Assert(sessObject)((sessObject) ? ((void)0) : PR_Assert("sessObject", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 787))
;
788 if (sessObject == NULL((void*)0)) {
789 return CKR_DEVICE_ERROR0x00000030UL;
790 }
791
792 PR_Lock(sessObject->attributeLock);
793 sftkqueue_find(attribute, type, sessObject->head, sessObject->hashSize)for ((attribute) = (sessObject->head)[((PRUint32)((type) *
1791398085) & (sessObject->hashSize - 1))]; (attribute
) != ((void*)0); (attribute) = (attribute)->next) { if ((attribute
)->handle == (type)) { break; } }
;
794 if (attribute == NULL((void*)0)) {
795 PR_Unlock(sessObject->attributeLock);
796 return sftk_AddAttributeType(object, type, value, len);
797 }
798
799 if (value) {
800 if (len <= ATTR_SPACE50) {
801 att_val = attribute->space;
802 } else {
803 att_val = PORT_AllocPORT_Alloc_Util(len);
804 freeData = PR_TRUE1;
805 }
806 if (att_val == NULL((void*)0)) {
807 PR_Unlock(sessObject->attributeLock);
808 return CKR_HOST_MEMORY0x00000002UL;
809 }
810 if (attribute->attrib.pValue == att_val) {
811 PORT_Memsetmemset(attribute->attrib.pValue, 0,
812 attribute->attrib.ulValueLen);
813 }
814 PORT_Memcpymemcpy(att_val, value, len);
815 }
816 if (attribute->attrib.pValue != NULL((void*)0)) {
817 if (attribute->attrib.pValue != att_val) {
818 PORT_Memsetmemset(attribute->attrib.pValue, 0,
819 attribute->attrib.ulValueLen);
820 }
821 if (attribute->freeData) {
822 PORT_ReleaseAssert(attribute->attrib.pValue != att_val)((attribute->attrib.pValue != att_val) ? ((void)0) : PR_Assert
("attribute->attrib.pValue != att_val", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 822))
;
823 PORT_FreePORT_Free_Util(attribute->attrib.pValue);
824 }
825 attribute->freeData = PR_FALSE0;
826 attribute->attrib.pValue = NULL((void*)0);
827 attribute->attrib.ulValueLen = 0;
828 }
829 if (att_val) {
830 attribute->attrib.pValue = att_val;
831 attribute->attrib.ulValueLen = len;
832 attribute->freeData = freeData;
833 }
834 PR_Unlock(sessObject->attributeLock);
835 return CKR_OK0x00000000UL;
836}
837
838/*
839 * decode when a particular attribute may be modified
840 * SFTK_NEVER: This attribute must be set at object creation time and
841 * can never be modified.
842 * SFTK_ONCOPY: This attribute may be modified only when you copy the
843 * object.
844 * SFTK_SENSITIVE: The CKA_SENSITIVE attribute can only be changed from
845 * CK_FALSE to CK_TRUE.
846 * SFTK_ALWAYS: This attribute can always be modified.
847 * Some attributes vary their modification type based on the class of the
848 * object.
849 */
850SFTKModifyType
851sftk_modifyType(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass)
852{
853 /* if we don't know about it, user user defined, always allow modify */
854 SFTKModifyType mtype = SFTK_ALWAYS;
855
856 switch (type) {
857 /* NEVER */
858 case CKA_CLASS0x00000000UL:
859 case CKA_CERTIFICATE_TYPE0x00000080UL:
860 case CKA_KEY_TYPE0x00000100UL:
861 case CKA_MODULUS0x00000120UL:
862 case CKA_MODULUS_BITS0x00000121UL:
863 case CKA_PUBLIC_EXPONENT0x00000122UL:
864 case CKA_PRIVATE_EXPONENT0x00000123UL:
865 case CKA_PRIME0x00000130UL:
866 case CKA_BASE0x00000132UL:
867 case CKA_PRIME_10x00000124UL:
868 case CKA_PRIME_20x00000125UL:
869 case CKA_EXPONENT_10x00000126UL:
870 case CKA_EXPONENT_20x00000127UL:
871 case CKA_COEFFICIENT0x00000128UL:
872 case CKA_SEED0x00000637UL:
873 case CKA_PARAMETER_SET0x0000061dUL:
874 case CKA_VALUE_LEN0x00000161UL:
875 case CKA_ALWAYS_SENSITIVE0x00000165UL:
876 case CKA_NEVER_EXTRACTABLE0x00000164UL:
877 case CKA_NSS_DB0xD5A0DB00L:
878 mtype = SFTK_NEVER;
879 break;
880
881 /* ONCOPY */
882 case CKA_TOKEN0x00000001UL:
883 case CKA_PRIVATE0x00000002UL:
884 case CKA_MODIFIABLE0x00000170UL:
885 mtype = SFTK_ONCOPY;
886 break;
887
888 /* SENSITIVE */
889 case CKA_SENSITIVE0x00000103UL:
890 case CKA_EXTRACTABLE0x00000162UL:
891 mtype = SFTK_SENSITIVE;
892 break;
893
894 /* ALWAYS */
895 case CKA_LABEL0x00000003UL:
896 case CKA_APPLICATION0x00000010UL:
897 case CKA_ID0x00000102UL:
898 case CKA_SERIAL_NUMBER0x00000082UL:
899 case CKA_START_DATE0x00000110UL:
900 case CKA_END_DATE0x00000111UL:
901 case CKA_DERIVE0x0000010CUL:
902 case CKA_ENCRYPT0x00000104UL:
903 case CKA_DECRYPT0x00000105UL:
904 case CKA_SIGN0x00000108UL:
905 case CKA_VERIFY0x0000010AUL:
906 case CKA_SIGN_RECOVER0x00000109UL:
907 case CKA_VERIFY_RECOVER0x0000010BUL:
908 case CKA_WRAP0x00000106UL:
909 case CKA_UNWRAP0x00000107UL:
910 mtype = SFTK_ALWAYS;
911 break;
912
913 /* DEPENDS ON CLASS */
914 case CKA_VALUE0x00000011UL:
915 mtype = (inClass == CKO_DATA0x00000000UL) ? SFTK_ALWAYS : SFTK_NEVER;
916 break;
917
918 case CKA_SUBPRIME0x00000131UL:
919 /* allow the CKA_SUBPRIME to be added to dh private keys */
920 mtype = (inClass == CKO_PRIVATE_KEY0x00000003UL) ? SFTK_ALWAYS : SFTK_NEVER;
921 break;
922
923 case CKA_SUBJECT0x00000101UL:
924 mtype = (inClass == CKO_CERTIFICATE0x00000001UL) ? SFTK_NEVER : SFTK_ALWAYS;
925 break;
926 default:
927 break;
928 }
929 return mtype;
930}
931
932/* decode if a particular attribute is sensitive (cannot be read
933 * back to the user of if the object is set to SENSITIVE) */
934PRBool
935sftk_isSensitive(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass)
936{
937 switch (type) {
938 /* ALWAYS */
939 case CKA_PRIVATE_EXPONENT0x00000123UL:
940 case CKA_PRIME_10x00000124UL:
941 case CKA_PRIME_20x00000125UL:
942 case CKA_EXPONENT_10x00000126UL:
943 case CKA_EXPONENT_20x00000127UL:
944 case CKA_COEFFICIENT0x00000128UL:
945 case CKA_SEED0x00000637UL:
946 return PR_TRUE1;
947
948 /* DEPENDS ON CLASS */
949 case CKA_VALUE0x00000011UL:
950 /* PRIVATE and SECRET KEYS have SENSITIVE values */
951 return (PRBool)((inClass == CKO_PRIVATE_KEY0x00000003UL) || (inClass == CKO_SECRET_KEY0x00000004UL));
952
953 default:
954 break;
955 }
956 return PR_FALSE0;
957}
958
959/*
960 * copy an attribute into a SECItem. Secitem is allocated in the specified
961 * arena.
962 */
963CK_RV
964sftk_Attribute2SecItem(PLArenaPool *arena, SECItem *item, SFTKObject *object,
965 CK_ATTRIBUTE_TYPE type)
966{
967 SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
968 SFTKAttribute *attribute;
969 CK_RV crv = CKR_OK0x00000000UL;
970 int len;
971
972 if (sessObject != NULL((void*)0)) {
973 PR_Lock(sessObject->attributeLock);
974 attribute = sftk_FindAttributeLocked(object, type);
975 } else {
976 attribute = sftk_FindAttribute(object, type);
977 }
978
979 if (attribute == NULL((void*)0)) {
980 crv = CKR_TEMPLATE_INCOMPLETE0x000000D0UL;
981 } else {
982 len = attribute->attrib.ulValueLen;
983 if (arena) {
984 item->data = (unsigned char *)PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, len);
985 } else {
986 item->data = (unsigned char *)PORT_AllocPORT_Alloc_Util(len);
987 }
988 if (item->data == NULL((void*)0)) {
989 crv = CKR_HOST_MEMORY0x00000002UL;
990 } else {
991 item->len = len;
992 PORT_Memcpymemcpy(item->data, attribute->attrib.pValue, len);
993 }
994 }
995
996 if (sessObject != NULL((void*)0)) {
997 PR_Unlock(sessObject->attributeLock);
998 } else {
999 sftk_FreeAttribute(attribute);
1000 }
1001 return crv;
1002}
1003
1004CK_RV
1005sftk_GetULongAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
1006 CK_ULONG *longData)
1007{
1008 SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
1009 SFTKAttribute *attribute;
1010 CK_RV crv = CKR_OK0x00000000UL;
1011
1012 /* For a session object read the live value under the lock instead of
1013 * copying it out; for a token object fall back to a freed copy. */
1014 if (sessObject != NULL((void*)0)) {
1015 PR_Lock(sessObject->attributeLock);
1016 attribute = sftk_FindAttributeLocked(object, type);
1017 } else {
1018 attribute = sftk_FindAttribute(object, type);
1019 }
1020
1021 if (attribute == NULL((void*)0)) {
1022 crv = CKR_TEMPLATE_INCOMPLETE0x000000D0UL;
1023 } else if (attribute->attrib.ulValueLen != sizeof(CK_ULONG)) {
1024 crv = CKR_ATTRIBUTE_VALUE_INVALID0x00000013UL;
1025 } else {
1026 *longData = *(CK_ULONG *)attribute->attrib.pValue;
1027 }
1028
1029 if (sessObject != NULL((void*)0)) {
1030 PR_Unlock(sessObject->attributeLock);
1031 } else {
1032 sftk_FreeAttribute(attribute);
1033 }
1034 return crv;
1035}
1036
1037CK_RV
1038sftk_ReadAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
1039 unsigned char *data, unsigned int maxLen, unsigned int *lenp)
1040{
1041 SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
1042 SFTKAttribute *attribute;
1043 CK_RV crv = CKR_OK0x00000000UL;
1044
1045 /* For a session object read the live value under the lock instead of
1046 * copying it out; for a token object fall back to a freed copy. */
1047 if (sessObject != NULL((void*)0)) {
1048 PR_Lock(sessObject->attributeLock);
1049 attribute = sftk_FindAttributeLocked(object, type);
1050 } else {
1051 attribute = sftk_FindAttribute(object, type);
1052 }
1053
1054 if (attribute == NULL((void*)0)) {
1055 crv = CKR_TEMPLATE_INCOMPLETE0x000000D0UL;
1056 } else {
1057 *lenp = attribute->attrib.ulValueLen;
1058 if (*lenp > maxLen) {
1059 /* normally would be CKR_BUFFER_TOO_SMALL, but
1060 * it used with internal buffers, so if the value is
1061 * to long, the original attribute was invalid */
1062 crv = CKR_ATTRIBUTE_VALUE_INVALID0x00000013UL;
1063 } else {
1064 PORT_Memcpymemcpy(data, attribute->attrib.pValue, *lenp);
1065 }
1066 }
1067
1068 if (sessObject != NULL((void*)0)) {
1069 PR_Unlock(sessObject->attributeLock);
1070 } else {
1071 sftk_FreeAttribute(attribute);
1072 }
1073 return crv;
1074}
1075
1076void
1077sftk_DeleteAttributeType(SFTKObject *object, CK_ATTRIBUTE_TYPE type)
1078{
1079 SFTKAttribute *attribute;
1080 SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
1081
1082 if (sessObject == NULL((void*)0)) {
1083 return;
1084 }
1085
1086 /* Find, unlink, and destroy the live node atomically under the lock.
1087 * Once unlinked from head[] the node is unreachable by any other
1088 * thread (readers snapshot copies under the same lock), so destroying
1089 * it here cannot race a concurrent reader or a second deleter. */
1090 PR_Lock(sessObject->attributeLock);
1091 sftkqueue_find(attribute, type, sessObject->head, sessObject->hashSize)for ((attribute) = (sessObject->head)[((PRUint32)((type) *
1791398085) & (sessObject->hashSize - 1))]; (attribute
) != ((void*)0); (attribute) = (attribute)->next) { if ((attribute
)->handle == (type)) { break; } }
;
1092 if (attribute != NULL((void*)0)) {
1093 if (sftkqueue_is_queued(attribute, attribute->handle,(((attribute)->next) || ((attribute)->prev) || ((sessObject
->head)[((PRUint32)((attribute->handle) * 1791398085) &
(sessObject->hashSize - 1))] == (attribute)))
1094 sessObject->head, sessObject->hashSize)(((attribute)->next) || ((attribute)->prev) || ((sessObject
->head)[((PRUint32)((attribute->handle) * 1791398085) &
(sessObject->hashSize - 1))] == (attribute)))
) {
1095 sftkqueue_delete(attribute, attribute->handle,if ((attribute)->next) (attribute)->next->prev = (attribute
)->prev; if ((attribute)->prev) (attribute)->prev->
next = (attribute)->next; else (sessObject->head)[((PRUint32
)((attribute->handle) * 1791398085) & (sessObject->
hashSize - 1))] = ((attribute)->next); (attribute)->next
= ((void*)0); (attribute)->prev = ((void*)0);
1096 sessObject->head, sessObject->hashSize)if ((attribute)->next) (attribute)->next->prev = (attribute
)->prev; if ((attribute)->prev) (attribute)->prev->
next = (attribute)->next; else (sessObject->head)[((PRUint32
)((attribute->handle) * 1791398085) & (sessObject->
hashSize - 1))] = ((attribute)->next); (attribute)->next
= ((void*)0); (attribute)->prev = ((void*)0);
;
1097 }
1098 sftk_DestroyAttribute(attribute);
1099 }
1100 PR_Unlock(sessObject->attributeLock);
1101}
1102
1103CK_RV
1104sftk_AddAttributeType(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
1105 const void *valPtr, CK_ULONG length)
1106{
1107 SFTKAttribute *attribute;
1108 attribute = sftk_NewAttribute(object, type, valPtr, length);
1109 if (attribute == NULL((void*)0)) {
1110 return CKR_HOST_MEMORY0x00000002UL;
1111 }
1112 sftk_AddAttribute(object, attribute);
1113 return CKR_OK0x00000000UL;
1114}
1115
1116/*
1117 * ******************** Object Utilities *******************************
1118 */
1119
1120/* must be called holding sftk_tokenKeyLock(slot) */
1121static SECItem *
1122sftk_lookupTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle)
1123{
1124 return (SECItem *)PL_HashTableLookup(slot->tokObjHashTable, (void *)(uintptr_t)handle);
1125}
1126
1127/*
1128 * use the refLock. This operations should be very rare, so the added
1129 * contention on the ref lock should be lower than the overhead of adding
1130 * a new lock. We use separate functions for this just in case I'm wrong.
1131 */
1132static void
1133sftk_tokenKeyLock(SFTKSlot *slot)
1134{
1135 SKIP_AFTER_FORK(PR_Lock(slot->objectLock))PR_Lock(slot->objectLock);
1136}
1137
1138static void
1139sftk_tokenKeyUnlock(SFTKSlot *slot)
1140{
1141 SKIP_AFTER_FORK(PR_Unlock(slot->objectLock))PR_Unlock(slot->objectLock);
1142}
1143
1144static PRIntn
1145sftk_freeHashItem(PLHashEntry *entry, PRIntn index, void *arg)
1146{
1147 SECItem *item = (SECItem *)entry->value;
1148
1149 SECITEM_FreeItemSECITEM_FreeItem_Util(item, PR_TRUE1);
1150 return HT_ENUMERATE_NEXT0;
1151}
1152
1153CK_RV
1154SFTK_ClearTokenKeyHashTable(SFTKSlot *slot)
1155{
1156 sftk_tokenKeyLock(slot);
1157 PORT_Assert(!slot->present)((!slot->present) ? ((void)0) : PR_Assert("!slot->present"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 1157
))
;
1158 PL_HashTableEnumerateEntries(slot->tokObjHashTable, sftk_freeHashItem, NULL((void*)0));
1159 sftk_tokenKeyUnlock(slot);
1160 return CKR_OK0x00000000UL;
1161}
1162
1163/* allocation hooks that allow us to recycle old object structures */
1164static SFTKObjectFreeList sessionObjectList = { NULL((void*)0), NULL((void*)0), 0 };
1165static SFTKObjectFreeList tokenObjectList = { NULL((void*)0), NULL((void*)0), 0 };
1166
1167SFTKObject *
1168sftk_GetObjectFromList(PRBool *hasLocks, PRBool optimizeSpace,
1169 SFTKObjectFreeList *list, unsigned int hashSize, PRBool isSessionObject)
1170{
1171 SFTKObject *object;
1172 int size = 0;
1173
1174 if (!optimizeSpace) {
1175 PR_Lock(list->lock);
1176 object = list->head;
1177 if (object) {
1178 list->head = object->next;
1179 list->count--;
1180 }
1181 PR_Unlock(list->lock);
1182 if (object) {
1183 /* A live object on the free list means it was destroyed
1184 * twice; some other thread still holds a pointer to it and
1185 * will corrupt it if it is handed out again. */
1186 PORT_ReleaseAssert(object->refCount == 0)((object->refCount == 0) ? ((void)0) : PR_Assert("object->refCount == 0"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 1186
))
;
1187 object->next = object->prev = NULL((void*)0);
1188 *hasLocks = PR_TRUE1;
1189 return object;
1190 }
1191 }
1192 size = isSessionObject ? sizeof(SFTKSessionObject) + hashSize * sizeof(SFTKAttribute *) : sizeof(SFTKTokenObject);
1193
1194 object = (SFTKObject *)PORT_ZAllocPORT_ZAlloc_Util(size);
1195 if (isSessionObject && object) {
1196 ((SFTKSessionObject *)object)->hashSize = hashSize;
1197 }
1198 *hasLocks = PR_FALSE0;
1199 return object;
1200}
1201
1202static void
1203sftk_PutObjectToList(SFTKObject *object, SFTKObjectFreeList *list,
1204 PRBool isSessionObject)
1205{
1206
1207 /* the code below is equivalent to :
1208 * optimizeSpace = isSessionObject ? object->optimizeSpace : PR_FALSE;
1209 * just faster.
1210 */
1211 PRBool optimizeSpace = isSessionObject &&
1212 ((SFTKSessionObject *)object)->optimizeSpace;
1213 if (object->refLock && !optimizeSpace) {
1214 PR_Lock(list->lock);
1215 if (list->count < MAX_OBJECT_LIST_SIZE800) {
1216 object->next = list->head;
1217 list->head = object;
1218 list->count++;
1219 PR_Unlock(list->lock);
1220 return;
1221 }
1222 PR_Unlock(list->lock);
1223 }
1224 if (isSessionObject) {
1225 SFTKSessionObject *so = (SFTKSessionObject *)object;
1226 PR_DestroyLock(so->attributeLock);
1227 so->attributeLock = NULL((void*)0);
1228 }
1229 if (object->refLock) {
1230 PR_DestroyLock(object->refLock);
1231 object->refLock = NULL((void*)0);
1232 }
1233 PORT_FreePORT_Free_Util(object);
1234}
1235
1236static SFTKObject *
1237sftk_freeObjectData(SFTKObject *object)
1238{
1239 SFTKObject *next = object->next;
1240
1241 PORT_FreePORT_Free_Util(object);
1242 return next;
1243}
1244
1245static void
1246sftk_InitFreeList(SFTKObjectFreeList *list)
1247{
1248 if (!list->lock) {
1249 list->lock = PR_NewLock();
1250 }
1251}
1252
1253void
1254sftk_InitFreeLists(void)
1255{
1256 sftk_InitFreeList(&sessionObjectList);
1257 sftk_InitFreeList(&tokenObjectList);
1258}
1259
1260static void
1261sftk_CleanupFreeList(SFTKObjectFreeList *list, PRBool isSessionList)
1262{
1263 SFTKObject *object;
1264
1265 if (!list->lock) {
1266 return;
1267 }
1268 SKIP_AFTER_FORK(PR_Lock(list->lock))PR_Lock(list->lock);
1269 for (object = list->head; object != NULL((void*)0);
1270 object = sftk_freeObjectData(object)) {
1271 PR_DestroyLock(object->refLock);
1272 if (isSessionList) {
1273 PR_DestroyLock(((SFTKSessionObject *)object)->attributeLock);
1274 }
1275 }
1276 list->count = 0;
1277 list->head = NULL((void*)0);
1278 SKIP_AFTER_FORK(PR_Unlock(list->lock))PR_Unlock(list->lock);
1279 SKIP_AFTER_FORK(PR_DestroyLock(list->lock))PR_DestroyLock(list->lock);
1280 list->lock = NULL((void*)0);
1281}
1282
1283void
1284sftk_CleanupFreeLists(void)
1285{
1286 sftk_CleanupFreeList(&sessionObjectList, PR_TRUE1);
1287 sftk_CleanupFreeList(&tokenObjectList, PR_FALSE0);
1288}
1289
1290/*
1291 * Create a new object
1292 */
1293SFTKObject *
1294sftk_NewObject(SFTKSlot *slot)
1295{
1296 SFTKObject *object;
1297 SFTKSessionObject *sessObject;
1298 PRBool hasLocks = PR_FALSE0;
1299 unsigned int i;
1300 unsigned int hashSize = 0;
1301
1302 hashSize = (slot->optimizeSpace) ? SPACE_ATTRIBUTE_HASH_SIZE32 : TIME_ATTRIBUTE_HASH_SIZE32;
1303
1304 object = sftk_GetObjectFromList(&hasLocks, slot->optimizeSpace,
1305 &sessionObjectList, hashSize, PR_TRUE1);
1306 if (object == NULL((void*)0)) {
1307 return NULL((void*)0);
1308 }
1309 sessObject = (SFTKSessionObject *)object;
1310 sessObject->nextAttr = 0;
1311
1312 for (i = 0; i < MAX_OBJS_ATTRS45; i++) {
1313 sessObject->attrList[i].attrib.pValue = NULL((void*)0);
1314 sessObject->attrList[i].freeData = PR_FALSE0;
1315 }
1316 sessObject->optimizeSpace = slot->optimizeSpace;
1317
1318 object->handle = 0;
1319 object->next = object->prev = NULL((void*)0);
1320 object->slot = slot;
1321 /* set up the validation flags */
1322 object->validation_value = 0;
1323 object->validation_attribute.next = NULL((void*)0);
1324 object->validation_attribute.prev = NULL((void*)0);
1325 object->validation_attribute.freeAttr = PR_FALSE0;
1326 object->validation_attribute.freeData = PR_FALSE0;
1327 object->validation_attribute.handle = CKA_OBJECT_VALIDATION_FLAGS0x0000061eUL;
1328 object->validation_attribute.attrib.type = CKA_OBJECT_VALIDATION_FLAGS0x0000061eUL;
1329 object->validation_attribute.attrib.pValue = &object->validation_value;
1330 object->validation_attribute.attrib.ulValueLen = sizeof(object->validation_value);
1331 /* initialize the FIPS flag properly */
1332 sftk_setFIPS(object, sftk_isFIPS(slot->slotID)(((slot->slotID) == 3) || ((slot->slotID) >= 101)));
1333 object->source = SFTK_SOURCE_DEFAULT;
1334
1335 object->refCount = 1;
1336 object->type = SFTK_SESSION_OBJECT_TYPE0xFFFFFFFFU;
1337 sessObject->sessionList.next = NULL((void*)0);
1338 sessObject->sessionList.prev = NULL((void*)0);
1339 sessObject->sessionList.parent = object;
1340 sessObject->session = NULL((void*)0);
1341 sessObject->wasDerived = PR_FALSE0;
1342 if (!hasLocks)
1343 object->refLock = PR_NewLock();
1344 if (object->refLock == NULL((void*)0)) {
1345 PORT_FreePORT_Free_Util(object);
1346 return NULL((void*)0);
1347 }
1348 if (!hasLocks)
1349 sessObject->attributeLock = PR_NewLock();
1350 if (sessObject->attributeLock == NULL((void*)0)) {
1351 PR_DestroyLock(object->refLock);
1352 PORT_FreePORT_Free_Util(object);
1353 return NULL((void*)0);
1354 }
1355 for (i = 0; i < sessObject->hashSize; i++) {
1356 sessObject->head[i] = NULL((void*)0);
1357 }
1358 object->objectInfo = NULL((void*)0);
1359 object->infoFree = NULL((void*)0);
1360 return object;
1361}
1362
1363static CK_RV
1364sftk_DestroySessionObjectData(SFTKSessionObject *so)
1365{
1366 int i;
1367
1368 for (i = 0; i < MAX_OBJS_ATTRS45; i++) {
1369 unsigned char *value = so->attrList[i].attrib.pValue;
1370 if (value) {
1371 /* An attribute value lives in the attribute's inline space
1372 * unless the attribute owns a heap allocation for it. Anything
1373 * else means this object was already destroyed and its memory
1374 * reused; abort rather than zeroize through a wild pointer. */
1375 PORT_ReleaseAssert(so->attrList[i].freeData ||((so->attrList[i].freeData || (value == so->attrList[i]
.space && so->attrList[i].attrib.ulValueLen <= 50
)) ? ((void)0) : PR_Assert("so->attrList[i].freeData || (value == so->attrList[i].space && so->attrList[i].attrib.ulValueLen <= ATTR_SPACE)"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 1377
))
1376 (value == so->attrList[i].space &&((so->attrList[i].freeData || (value == so->attrList[i]
.space && so->attrList[i].attrib.ulValueLen <= 50
)) ? ((void)0) : PR_Assert("so->attrList[i].freeData || (value == so->attrList[i].space && so->attrList[i].attrib.ulValueLen <= ATTR_SPACE)"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 1377
))
1377 so->attrList[i].attrib.ulValueLen <= ATTR_SPACE))((so->attrList[i].freeData || (value == so->attrList[i]
.space && so->attrList[i].attrib.ulValueLen <= 50
)) ? ((void)0) : PR_Assert("so->attrList[i].freeData || (value == so->attrList[i].space && so->attrList[i].attrib.ulValueLen <= ATTR_SPACE)"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 1377
))
;
1378 PORT_Memsetmemset(value, 0, so->attrList[i].attrib.ulValueLen);
1379 if (so->attrList[i].freeData) {
1380 PORT_FreePORT_Free_Util(value);
1381 }
1382 so->attrList[i].attrib.pValue = NULL((void*)0);
1383 so->attrList[i].attrib.ulValueLen = 0;
1384 so->attrList[i].freeData = PR_FALSE0;
1385 }
1386 }
1387 /* PR_DestroyLock(so->attributeLock);*/
1388 return CKR_OK0x00000000UL;
1389}
1390
1391/*
1392 * free all the data associated with an object. Object reference count must
1393 * be 'zero'.
1394 */
1395static CK_RV
1396sftk_DestroyObject(SFTKObject *object)
1397{
1398 CK_RV crv = CKR_OK0x00000000UL;
1399 SFTKSessionObject *so = sftk_narrowToSessionObject(object);
1400 SFTKTokenObject *to = sftk_narrowToTokenObject(object);
1401
1402 PORT_Assert(object->refCount == 0)((object->refCount == 0) ? ((void)0) : PR_Assert("object->refCount == 0"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 1402
))
;
1403
1404 /* delete the database value */
1405 if (to) {
1406 if (to->dbKey.data) {
1407 PORT_FreePORT_Free_Util(to->dbKey.data);
1408 to->dbKey.data = NULL((void*)0);
1409 }
1410 }
1411 if (so) {
1412 sftk_DestroySessionObjectData(so);
1413 }
1414 if (object->objectInfo) {
1415 (*object->infoFree)(object->objectInfo);
1416 object->objectInfo = NULL((void*)0);
1417 object->infoFree = NULL((void*)0);
1418 }
1419 if (so) {
1420 sftk_PutObjectToList(object, &sessionObjectList, PR_TRUE1);
1421 } else {
1422 sftk_PutObjectToList(object, &tokenObjectList, PR_FALSE0);
1423 }
1424 return crv;
1425}
1426
1427void
1428sftk_ReferenceObject(SFTKObject *object)
1429{
1430 PR_Lock(object->refLock);
1431 /* A zero count means this object has already been destroyed; abort
1432 * before the new reference is used to operate on freed memory. */
1433 PORT_ReleaseAssert(object->refCount > 0)((object->refCount > 0) ? ((void)0) : PR_Assert("object->refCount > 0"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 1433
))
;
1434 object->refCount++;
1435 PR_Unlock(object->refLock);
1436}
1437
1438static SFTKObject *
1439sftk_ObjectFromHandleOnSlot(CK_OBJECT_HANDLE handle, SFTKSlot *slot)
1440{
1441 SFTKObject *object;
1442 PRUint32 index = sftk_hash(handle, slot->sessObjHashSize)((PRUint32)((handle) * 1791398085) & (slot->sessObjHashSize
- 1))
;
1443
1444 if (sftk_isToken(handle)(((handle) & 0x80000000L) == 0x80000000L)) {
1445 return sftk_NewTokenObject(slot, NULL((void*)0), handle);
1446 }
1447
1448 PR_Lock(slot->objectLock);
1449 sftkqueue_find2(object, handle, index, slot->sessObjHashTable)for ((object) = (slot->sessObjHashTable)[index]; (object) !=
((void*)0); (object) = (object)->next) { if ((object)->
handle == (handle)) { break; } }
;
1450 if (object) {
1451 sftk_ReferenceObject(object);
1452 }
1453 PR_Unlock(slot->objectLock);
1454
1455 return (object);
1456}
1457/*
1458 * look up and object structure from a handle. OBJECT_Handles only make
1459 * sense in terms of a given session. make a reference to that object
1460 * structure returned.
1461 */
1462SFTKObject *
1463sftk_ObjectFromHandle(CK_OBJECT_HANDLE handle, SFTKSession *session)
1464{
1465 SFTKSlot *slot = sftk_SlotFromSession(session)((session)->slot);
1466
1467 return sftk_ObjectFromHandleOnSlot(handle, slot);
1468}
1469
1470/*
1471 * release a reference to an object handle
1472 */
1473SFTKFreeStatus
1474sftk_FreeObject(SFTKObject *object)
1475{
1476 PRBool destroy = PR_FALSE0;
1477 CK_RV crv;
1478
1479 PR_Lock(object->refLock);
1480 /* A zero count means this object has already been destroyed. Abort,
1481 * like an allocator that detects a double free, rather than tear the
1482 * object down a second time. */
1483 PORT_ReleaseAssert(object->refCount > 0)((object->refCount > 0) ? ((void)0) : PR_Assert("object->refCount > 0"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 1483
))
;
1484 if (object->refCount == 1)
1485 destroy = PR_TRUE1;
1486 object->refCount--;
1487 PR_Unlock(object->refLock);
1488
1489 if (destroy) {
1490 crv = sftk_DestroyObject(object);
1491 if (crv != CKR_OK0x00000000UL) {
1492 return SFTK_DestroyFailure;
1493 }
1494 return SFTK_Destroyed;
1495 }
1496 return SFTK_Busy;
1497}
1498
1499/* find the next available object handle that isn't currently in use */
1500/* NOTE: This function could loop forever if we've exhausted all
1501 * 3^31-1 handles. This is highly unlikely (NSS has been running for
1502 * decades with this code) uless we start increasing the size of the
1503 * SFTK_TOKEN_MASK (which is just the high bit currently). */
1504CK_OBJECT_HANDLE
1505sftk_getNextHandle(SFTKSlot *slot)
1506{
1507 CK_OBJECT_HANDLE handle;
1508 SFTKObject *duplicateObject = NULL((void*)0);
1509 do {
1510 PRUint32 wrappedAround;
1511
1512 duplicateObject = NULL((void*)0);
1513 PR_Lock(slot->objectLock);
1514 wrappedAround = slot->sessionObjectHandleCount & SFTK_TOKEN_MASK0x80000000L;
1515 handle = slot->sessionObjectHandleCount & ~SFTK_TOKEN_MASK0x80000000L;
1516 if (!handle) /* don't allow zero handle */
1517 handle = NSC_MIN_SESSION_OBJECT_HANDLE1U;
1518 slot->sessionObjectHandleCount = (handle + 1U) | wrappedAround;
1519 /* Is there already a session object with this handle? */
1520 if (wrappedAround) {
1521 sftkqueue_find(duplicateObject, handle, slot->sessObjHashTable,for ((duplicateObject) = (slot->sessObjHashTable)[((PRUint32
)((handle) * 1791398085) & (slot->sessObjHashSize - 1)
)]; (duplicateObject) != ((void*)0); (duplicateObject) = (duplicateObject
)->next) { if ((duplicateObject)->handle == (handle)) {
break; } }
1522 slot->sessObjHashSize)for ((duplicateObject) = (slot->sessObjHashTable)[((PRUint32
)((handle) * 1791398085) & (slot->sessObjHashSize - 1)
)]; (duplicateObject) != ((void*)0); (duplicateObject) = (duplicateObject
)->next) { if ((duplicateObject)->handle == (handle)) {
break; } }
;
1523 }
1524 PR_Unlock(slot->objectLock);
1525 } while (duplicateObject != NULL((void*)0));
1526 return handle;
1527}
1528
1529/*
1530 * Claim the right to remove a session object from the slot's object hash.
1531 * Must be called with slot->objectLock held.
1532 *
1533 * Several threads can reach the same object: handles are slot-global, so any
1534 * session can resolve one through sftk_ObjectFromHandle, and
1535 * sftk_ClearSession claims removals too when the owning session is closed.
1536 * Only the thread that finds the object still queued unlinks it; without that,
1537 * each would unlink again and drop the queues' reference a second time.
1538 *
1539 * Returns PR_TRUE if this caller owns the removal, and with it the reference
1540 * the queues held. Drop that reference with sftk_FreeObject() after releasing
1541 * slot->objectLock.
1542 */
1543static PRBool
1544sftk_ClaimObjectRemovalLocked(SFTKSlot *slot, SFTKObject *object)
1545{
1546 PRUint32 index = sftk_hash(object->handle, slot->sessObjHashSize)((PRUint32)((object->handle) * 1791398085) & (slot->
sessObjHashSize - 1))
;
1547
1548 if (!object->next && !object->prev &&
1549 slot->sessObjHashTable[index] != object) {
1550 return PR_FALSE0;
1551 }
1552 sftkqueue_delete2(object, object->handle, index, slot->sessObjHashTable)if ((object)->next) (object)->next->prev = (object)->
prev; if ((object)->prev) (object)->prev->next = (object
)->next; else (slot->sessObjHashTable)[index] = ((object
)->next);
;
1553 /* sftkqueue_delete2 patches the neighbours but leaves object->next/prev
1554 * pointing at them. Clear them here so the next thread to take the lock
1555 * sees an unqueued object and does not re-claim the removal. */
1556 sftkqueue_clear_deleted_element(object)(object)->next = ((void*)0); (object)->prev = ((void*)0
);
;
1557 return PR_TRUE1;
1558}
1559
1560/*
1561 * add an object to the slot's object hash and to its session's object list
1562 */
1563void
1564sftk_AddObject(SFTKSession *session, SFTKObject *object)
1565{
1566 SFTKSlot *slot = sftk_SlotFromSession(session)((session)->slot);
1567 SFTKSessionObject *so = sftk_narrowToSessionObject(object);
1568 PRUint32 index = sftk_hash(object->handle, slot->sessObjHashSize)((PRUint32)((object->handle) * 1791398085) & (slot->
sessObjHashSize - 1))
;
1569
1570 /* the reference the queues hold, taken before the object is reachable */
1571 sftk_ReferenceObject(object);
1572
1573 /* Both queues are linked under slot->objectLock in one critical section.
1574 * That gives the invariant the teardown paths depend on: a session object
1575 * is on its owning session's list if and only if it is in the slot's
1576 * object hash. See sftk_DeleteObject(). */
1577 sftkqueue_init_element(object)(object)->prev = ((void*)0);;
1578 PR_Lock(slot->objectLock);
1579 if (so) {
1580 so->session = session;
1581 sftkqueue_add(&so->sessionList, 0, session->objects, 0){ int tmp = ((PRUint32)((0) * 1791398085) & (0 - 1)); (&
so->sessionList)->next = (session->objects)[tmp]; (&
so->sessionList)->prev = ((void*)0); if ((session->objects
)[tmp]) (session->objects)[tmp]->prev = (&so->sessionList
); (session->objects)[tmp] = (&so->sessionList); }
;
1582 }
1583 sftkqueue_add2(object, object->handle, index, slot->sessObjHashTable){ (object)->next = (slot->sessObjHashTable)[index]; if (
(slot->sessObjHashTable)[index]) (slot->sessObjHashTable
)[index]->prev = (object); (slot->sessObjHashTable)[index
] = (object); }
;
1584 PR_Unlock(slot->objectLock);
1585}
1586
1587/*
1588 * delete an object from a slot and session queue
1589 */
1590CK_RV
1591sftk_DeleteObject(SFTKSession *session, SFTKObject *object)
1592{
1593 SFTKSlot *slot = sftk_SlotFromSession(session)((session)->slot);
1594 SFTKSessionObject *so = sftk_narrowToSessionObject(object);
1595 CK_RV crv = CKR_OK0x00000000UL;
1596
1597 /* Handle Token case */
1598 if (so && so->session) {
1599 PRBool ownsRemove;
1600
1601 /* so->session is the session that created the object; it need not be
1602 * the caller's session, and we hold no reference on it. Winning the
1603 * claim is what makes it safe to touch: the object was still in the
1604 * slot hash, so by the invariant in sftk_AddObject() it is still on
1605 * so->session's list, so sftk_ClearSession() has not run for that
1606 * session and the session has not been freed. */
1607 PR_Lock(slot->objectLock);
1608 ownsRemove = sftk_ClaimObjectRemovalLocked(slot, object);
1609 if (ownsRemove) {
1610 PORT_Assert(sftkqueue_is_queued(&so->sessionList, 0,(((((&so->sessionList)->next) || ((&so->sessionList
)->prev) || ((so->session->objects)[((PRUint32)((0) *
1791398085) & (0 - 1))] == (&so->sessionList)))) ?
((void)0) : PR_Assert("sftkqueue_is_queued(&so->sessionList, 0, so->session->objects, 0)"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 1611
))
1611 so->session->objects, 0))(((((&so->sessionList)->next) || ((&so->sessionList
)->prev) || ((so->session->objects)[((PRUint32)((0) *
1791398085) & (0 - 1))] == (&so->sessionList)))) ?
((void)0) : PR_Assert("sftkqueue_is_queued(&so->sessionList, 0, so->session->objects, 0)"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 1611
))
;
1612 sftkqueue_delete(&so->sessionList, 0, so->session->objects, 0)if ((&so->sessionList)->next) (&so->sessionList
)->next->prev = (&so->sessionList)->prev; if (
(&so->sessionList)->prev) (&so->sessionList)
->prev->next = (&so->sessionList)->next; else
(so->session->objects)[((PRUint32)((0) * 1791398085) &
(0 - 1))] = ((&so->sessionList)->next); (&so->
sessionList)->next = ((void*)0); (&so->sessionList)
->prev = ((void*)0);
;
1613 }
1614 PR_Unlock(slot->objectLock);
1615
1616 if (ownsRemove) {
1617 sftk_FreeObject(object); /* drop the queues' reference */
1618 }
1619 } else {
1620 SFTKDBHandle *handle = sftk_getDBForTokenObject(slot, object->handle);
1621#ifdef DEBUG1
1622 SFTKTokenObject *to = sftk_narrowToTokenObject(object);
1623 PORT_Assert(to)((to) ? ((void)0) : PR_Assert("to", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 1623))
;
1624#endif
1625 crv = sftkdb_DestroyObject(handle, object->handle, object->objclass);
1626 sftk_freeDB(handle);
1627 }
1628 return crv;
1629}
1630
1631/*
1632 * Token objects don't explicitly store their attributes, so we need to know
1633 * what attributes make up a particular token object before we can copy it.
1634 * below are the tables by object type.
1635 */
1636static const CK_ATTRIBUTE_TYPE commonAttrs[] = {
1637 CKA_CLASS0x00000000UL, CKA_TOKEN0x00000001UL, CKA_PRIVATE0x00000002UL, CKA_LABEL0x00000003UL, CKA_MODIFIABLE0x00000170UL
1638};
1639static const CK_ULONG commonAttrsCount =
1640 sizeof(commonAttrs) / sizeof(commonAttrs[0]);
1641
1642static const CK_ATTRIBUTE_TYPE commonKeyAttrs[] = {
1643 CKA_ID0x00000102UL, CKA_START_DATE0x00000110UL, CKA_END_DATE0x00000111UL, CKA_DERIVE0x0000010CUL, CKA_LOCAL0x00000163UL, CKA_KEY_TYPE0x00000100UL
1644};
1645static const CK_ULONG commonKeyAttrsCount =
1646 sizeof(commonKeyAttrs) / sizeof(commonKeyAttrs[0]);
1647
1648static const CK_ATTRIBUTE_TYPE secretKeyAttrs[] = {
1649 CKA_SENSITIVE0x00000103UL, CKA_EXTRACTABLE0x00000162UL, CKA_ENCRYPT0x00000104UL, CKA_DECRYPT0x00000105UL, CKA_SIGN0x00000108UL,
1650 CKA_VERIFY0x0000010AUL, CKA_WRAP0x00000106UL, CKA_UNWRAP0x00000107UL, CKA_VALUE0x00000011UL
1651};
1652static const CK_ULONG secretKeyAttrsCount =
1653 sizeof(secretKeyAttrs) / sizeof(secretKeyAttrs[0]);
1654
1655static const CK_ATTRIBUTE_TYPE commonPubKeyAttrs[] = {
1656 CKA_ENCRYPT0x00000104UL, CKA_VERIFY0x0000010AUL, CKA_VERIFY_RECOVER0x0000010BUL, CKA_WRAP0x00000106UL, CKA_SUBJECT0x00000101UL
1657};
1658static const CK_ULONG commonPubKeyAttrsCount =
1659 sizeof(commonPubKeyAttrs) / sizeof(commonPubKeyAttrs[0]);
1660
1661static const CK_ATTRIBUTE_TYPE rsaPubKeyAttrs[] = {
1662 CKA_MODULUS0x00000120UL, CKA_PUBLIC_EXPONENT0x00000122UL
1663};
1664static const CK_ULONG rsaPubKeyAttrsCount =
1665 sizeof(rsaPubKeyAttrs) / sizeof(rsaPubKeyAttrs[0]);
1666
1667static const CK_ATTRIBUTE_TYPE dsaPubKeyAttrs[] = {
1668 CKA_SUBPRIME0x00000131UL, CKA_PRIME0x00000130UL, CKA_BASE0x00000132UL, CKA_VALUE0x00000011UL
1669};
1670static const CK_ULONG dsaPubKeyAttrsCount =
1671 sizeof(dsaPubKeyAttrs) / sizeof(dsaPubKeyAttrs[0]);
1672
1673static const CK_ATTRIBUTE_TYPE dhPubKeyAttrs[] = {
1674 CKA_PRIME0x00000130UL, CKA_BASE0x00000132UL, CKA_VALUE0x00000011UL
1675};
1676static const CK_ULONG dhPubKeyAttrsCount =
1677 sizeof(dhPubKeyAttrs) / sizeof(dhPubKeyAttrs[0]);
1678static const CK_ATTRIBUTE_TYPE ecPubKeyAttrs[] = {
1679 CKA_EC_PARAMS0x00000180UL, CKA_EC_POINT0x00000181UL
1680};
1681static const CK_ULONG ecPubKeyAttrsCount =
1682 sizeof(ecPubKeyAttrs) / sizeof(ecPubKeyAttrs[0]);
1683
1684static const CK_ATTRIBUTE_TYPE mldsaPubKeyAttrs[] = {
1685 CKA_PARAMETER_SET0x0000061dUL, CKA_VALUE0x00000011UL
1686};
1687static const CK_ULONG mldsaPubKeyAttrsCount = PR_ARRAY_SIZE(mldsaPubKeyAttrs)(sizeof(mldsaPubKeyAttrs) / sizeof((mldsaPubKeyAttrs)[0]));
1688
1689/* the vendor ML-KEM key types carry CKA_NSS_PARAMETER_SET rather than
1690 * CKA_PARAMETER_SET; list both and let the missing one be skipped */
1691static const CK_ATTRIBUTE_TYPE mlkemPubKeyAttrs[] = {
1692 CKA_PARAMETER_SET0x0000061dUL, CKA_NSS_PARAMETER_SET((0x80000000UL | 0x4E534350) + 40), CKA_VALUE0x00000011UL
1693};
1694static const CK_ULONG mlkemPubKeyAttrsCount = PR_ARRAY_SIZE(mlkemPubKeyAttrs)(sizeof(mlkemPubKeyAttrs) / sizeof((mlkemPubKeyAttrs)[0]));
1695
1696static const CK_ATTRIBUTE_TYPE commonPrivKeyAttrs[] = {
1697 CKA_DECRYPT0x00000105UL, CKA_SIGN0x00000108UL, CKA_SIGN_RECOVER0x00000109UL, CKA_UNWRAP0x00000107UL, CKA_SUBJECT0x00000101UL,
1698 CKA_SENSITIVE0x00000103UL, CKA_EXTRACTABLE0x00000162UL, CKA_NSS_DB0xD5A0DB00L, CKA_PUBLIC_KEY_INFO0x00000129UL
1699};
1700static const CK_ULONG commonPrivKeyAttrsCount =
1701 sizeof(commonPrivKeyAttrs) / sizeof(commonPrivKeyAttrs[0]);
1702
1703static const CK_ATTRIBUTE_TYPE rsaPrivKeyAttrs[] = {
1704 CKA_MODULUS0x00000120UL, CKA_PUBLIC_EXPONENT0x00000122UL, CKA_PRIVATE_EXPONENT0x00000123UL,
1705 CKA_PRIME_10x00000124UL, CKA_PRIME_20x00000125UL, CKA_EXPONENT_10x00000126UL, CKA_EXPONENT_20x00000127UL, CKA_COEFFICIENT0x00000128UL
1706};
1707static const CK_ULONG rsaPrivKeyAttrsCount =
1708 sizeof(rsaPrivKeyAttrs) / sizeof(rsaPrivKeyAttrs[0]);
1709
1710static const CK_ATTRIBUTE_TYPE dsaPrivKeyAttrs[] = {
1711 CKA_SUBPRIME0x00000131UL, CKA_PRIME0x00000130UL, CKA_BASE0x00000132UL, CKA_VALUE0x00000011UL
1712};
1713static const CK_ULONG dsaPrivKeyAttrsCount =
1714 sizeof(dsaPrivKeyAttrs) / sizeof(dsaPrivKeyAttrs[0]);
1715
1716static const CK_ATTRIBUTE_TYPE dhPrivKeyAttrs[] = {
1717 CKA_PRIME0x00000130UL, CKA_BASE0x00000132UL, CKA_VALUE0x00000011UL
1718};
1719static const CK_ULONG dhPrivKeyAttrsCount =
1720 sizeof(dhPrivKeyAttrs) / sizeof(dhPrivKeyAttrs[0]);
1721static const CK_ATTRIBUTE_TYPE ecPrivKeyAttrs[] = {
1722 CKA_EC_PARAMS0x00000180UL, CKA_VALUE0x00000011UL
1723};
1724static const CK_ULONG ecPrivKeyAttrsCount =
1725 sizeof(ecPrivKeyAttrs) / sizeof(ecPrivKeyAttrs[0]);
1726
1727static const CK_ATTRIBUTE_TYPE mldsaPrivKeyAttrs[] = {
1728 CKA_PARAMETER_SET0x0000061dUL, CKA_VALUE0x00000011UL, CKA_SEED0x00000637UL
1729};
1730static const CK_ULONG mldsaPrivKeyAttrsCount = PR_ARRAY_SIZE(mldsaPrivKeyAttrs)(sizeof(mldsaPrivKeyAttrs) / sizeof((mldsaPrivKeyAttrs)[0]));
1731
1732static const CK_ATTRIBUTE_TYPE mlkemPrivKeyAttrs[] = {
1733 CKA_PARAMETER_SET0x0000061dUL, CKA_NSS_PARAMETER_SET((0x80000000UL | 0x4E534350) + 40), CKA_VALUE0x00000011UL, CKA_SEED0x00000637UL
1734};
1735static const CK_ULONG mlkemPrivKeyAttrsCount = PR_ARRAY_SIZE(mlkemPrivKeyAttrs)(sizeof(mlkemPrivKeyAttrs) / sizeof((mlkemPrivKeyAttrs)[0]));
1736
1737static const CK_ATTRIBUTE_TYPE certAttrs[] = {
1738 CKA_CERTIFICATE_TYPE0x00000080UL, CKA_VALUE0x00000011UL, CKA_SUBJECT0x00000101UL, CKA_ISSUER0x00000081UL, CKA_SERIAL_NUMBER0x00000082UL
1739};
1740static const CK_ULONG certAttrsCount =
1741 sizeof(certAttrs) / sizeof(certAttrs[0]);
1742
1743static const CK_ATTRIBUTE_TYPE nssTrustAttrs[] = {
1744 CKA_ISSUER0x00000081UL, CKA_SERIAL_NUMBER0x00000082UL, CKA_NSS_CERT_SHA1_HASH(((0x80000000UL | 0x4E534350) + 0x2000) + 100),
1745 CKA_NSS_CERT_MD5_HASH(((0x80000000UL | 0x4E534350) + 0x2000) + 101), CKA_NSS_TRUST_SERVER_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 8), CKA_NSS_TRUST_CLIENT_AUTH(((0x80000000UL | 0x4E534350) + 0x2000) + 9),
1746 CKA_NSS_TRUST_EMAIL_PROTECTION(((0x80000000UL | 0x4E534350) + 0x2000) + 11), CKA_NSS_TRUST_CODE_SIGNING(((0x80000000UL | 0x4E534350) + 0x2000) + 10),
1747 CKA_NSS_TRUST_STEP_UP_APPROVED(((0x80000000UL | 0x4E534350) + 0x2000) + 16)
1748};
1749static const CK_ULONG nssTrustAttrsCount =
1750 sizeof(nssTrustAttrs) / sizeof(nssTrustAttrs[0]);
1751
1752static const CK_ATTRIBUTE_TYPE trustAttrs[] = {
1753 CKA_ISSUER0x00000081UL, CKA_SERIAL_NUMBER0x00000082UL, CKA_HASH_OF_CERTIFICATE0x00000635UL,
1754 CKA_NAME_HASH_ALGORITHM0x0000008cUL, CKA_PKCS_TRUST_SERVER_AUTH0x0000062cUL,
1755 CKA_PKCS_TRUST_CLIENT_AUTH0x0000062dUL, CKA_PKCS_TRUST_EMAIL_PROTECTION0x0000062fUL,
1756 CKA_PKCS_TRUST_CODE_SIGNING0x0000062eUL
1757};
1758static const CK_ULONG trustAttrsCount =
1759 sizeof(trustAttrs) / sizeof(trustAttrs[0]);
1760
1761static const CK_ATTRIBUTE_TYPE smimeAttrs[] = {
1762 CKA_SUBJECT0x00000101UL, CKA_NSS_EMAIL((0x80000000UL | 0x4E534350) + 2), CKA_NSS_SMIME_TIMESTAMP((0x80000000UL | 0x4E534350) + 4), CKA_VALUE0x00000011UL
1763};
1764static const CK_ULONG smimeAttrsCount =
1765 sizeof(smimeAttrs) / sizeof(smimeAttrs[0]);
1766
1767static const CK_ATTRIBUTE_TYPE crlAttrs[] = {
1768 CKA_SUBJECT0x00000101UL, CKA_VALUE0x00000011UL, CKA_NSS_URL((0x80000000UL | 0x4E534350) + 1), CKA_NSS_KRL((0x80000000UL | 0x4E534350) + 8)
1769};
1770static const CK_ULONG crlAttrsCount =
1771 sizeof(crlAttrs) / sizeof(crlAttrs[0]);
1772
1773/* copy an object based on it's table */
1774CK_RV
1775stfk_CopyTokenAttributes(SFTKObject *destObject, SFTKTokenObject *src_to,
1776 const CK_ATTRIBUTE_TYPE *attrArray, CK_ULONG attrCount)
1777{
1778 SFTKAttribute *attribute;
1779 SFTKAttribute *newAttribute;
1780 CK_RV crv = CKR_OK0x00000000UL;
1781 unsigned int i;
1782
1783 for (i = 0; i < attrCount; i++) {
1784 if (!sftk_hasAttribute(destObject, attrArray[i])) {
1785 attribute = sftk_FindAttribute(&src_to->obj, attrArray[i]);
1786 if (!attribute) {
1787 continue; /* return CKR_ATTRIBUTE_VALUE_INVALID; */
1788 }
1789 /* we need to copy the attribute since each attribute
1790 * only has one set of link list pointers */
1791 newAttribute = sftk_NewAttribute(destObject,
1792 sftk_attr_expand(&attribute->attrib)(&attribute->attrib)->type, (&attribute->attrib
)->pValue, (&attribute->attrib)->ulValueLen
);
1793 sftk_FreeAttribute(attribute); /* free the old attribute */
1794 if (!newAttribute) {
1795 return CKR_HOST_MEMORY0x00000002UL;
1796 }
1797 sftk_AddAttribute(destObject, newAttribute);
1798 }
1799 }
1800 return crv;
1801}
1802
1803CK_RV
1804stfk_CopyTokenPrivateKey(SFTKObject *destObject, SFTKTokenObject *src_to)
1805{
1806 CK_RV crv;
1807 CK_KEY_TYPE key_type;
1808 SFTKAttribute *attribute;
1809
1810 /* copy the common attributes for all keys first */
1811 crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs,
1812 commonKeyAttrsCount);
1813 if (crv != CKR_OK0x00000000UL) {
1814 goto fail;
1815 }
1816 /* copy the common attributes for all private keys next */
1817 crv = stfk_CopyTokenAttributes(destObject, src_to, commonPrivKeyAttrs,
1818 commonPrivKeyAttrsCount);
1819 if (crv != CKR_OK0x00000000UL) {
1820 goto fail;
1821 }
1822 attribute = sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE0x00000100UL);
1823 PORT_Assert(attribute)((attribute) ? ((void)0) : PR_Assert("attribute", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 1823))
; /* if it wasn't here, ww should have failed
1824 * copying the common attributes */
1825 if (!attribute) {
1826 /* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but
1827 * the fact is, the only reason we couldn't get the attribute would
1828 * be a memory error or database error (an error in the 'device').
1829 * if we have a database error code, we could return it here */
1830 crv = CKR_DEVICE_ERROR0x00000030UL;
1831 goto fail;
1832 }
1833 key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue;
1834 sftk_FreeAttribute(attribute);
1835
1836 /* finally copy the attributes for various private key types */
1837 switch (key_type) {
1838 case CKK_RSA0x00000000UL:
1839 crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPrivKeyAttrs,
1840 rsaPrivKeyAttrsCount);
1841 break;
1842 case CKK_DSA0x00000001UL:
1843 crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPrivKeyAttrs,
1844 dsaPrivKeyAttrsCount);
1845 break;
1846 case CKK_ML_DSA0x0000004aUL:
1847 crv = stfk_CopyTokenAttributes(destObject, src_to, mldsaPrivKeyAttrs,
1848 mldsaPrivKeyAttrsCount);
1849 break;
1850 case CKK_NSS_ML_KEM((0x80000000UL | 0x4E534350) + 6):
1851 case CKK_ML_KEM0x00000049UL:
1852 crv = stfk_CopyTokenAttributes(destObject, src_to, mlkemPrivKeyAttrs,
1853 mlkemPrivKeyAttrsCount);
1854 break;
1855 case CKK_DH0x00000002UL:
1856 crv = stfk_CopyTokenAttributes(destObject, src_to, dhPrivKeyAttrs,
1857 dhPrivKeyAttrsCount);
1858 break;
1859 case CKK_EC0x00000003UL:
1860 case CKK_EC_EDWARDS0x00000040UL:
1861 case CKK_EC_MONTGOMERY0x00000041UL:
1862 crv = stfk_CopyTokenAttributes(destObject, src_to, ecPrivKeyAttrs,
1863 ecPrivKeyAttrsCount);
1864 break;
1865 default:
1866 crv = CKR_DEVICE_ERROR0x00000030UL; /* shouldn't happen unless we store more types
1867 * of token keys into our database. */
1868 }
1869fail:
1870 return crv;
1871}
1872
1873CK_RV
1874stfk_CopyTokenPublicKey(SFTKObject *destObject, SFTKTokenObject *src_to)
1875{
1876 CK_RV crv;
1877 CK_KEY_TYPE key_type;
1878 SFTKAttribute *attribute;
1879
1880 /* copy the common attributes for all keys first */
1881 crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs,
1882 commonKeyAttrsCount);
1883 if (crv != CKR_OK0x00000000UL) {
1884 goto fail;
1885 }
1886
1887 /* copy the common attributes for all public keys next */
1888 crv = stfk_CopyTokenAttributes(destObject, src_to, commonPubKeyAttrs,
1889 commonPubKeyAttrsCount);
1890 if (crv != CKR_OK0x00000000UL) {
1891 goto fail;
1892 }
1893 attribute = sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE0x00000100UL);
1894 PORT_Assert(attribute)((attribute) ? ((void)0) : PR_Assert("attribute", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 1894))
; /* if it wasn't here, ww should have failed
1895 * copying the common attributes */
1896 if (!attribute) {
1897 /* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but
1898 * the fact is, the only reason we couldn't get the attribute would
1899 * be a memory error or database error (an error in the 'device').
1900 * if we have a database error code, we could return it here */
1901 crv = CKR_DEVICE_ERROR0x00000030UL;
1902 goto fail;
1903 }
1904 key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue;
1905 sftk_FreeAttribute(attribute);
1906
1907 /* finally copy the attributes for various public key types */
1908 switch (key_type) {
1909 case CKK_RSA0x00000000UL:
1910 crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPubKeyAttrs,
1911 rsaPubKeyAttrsCount);
1912 break;
1913 case CKK_DSA0x00000001UL:
1914 crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPubKeyAttrs,
1915 dsaPubKeyAttrsCount);
1916 break;
1917 case CKK_ML_DSA0x0000004aUL:
1918 crv = stfk_CopyTokenAttributes(destObject, src_to, mldsaPubKeyAttrs,
1919 mldsaPubKeyAttrsCount);
1920 break;
1921 case CKK_NSS_ML_KEM((0x80000000UL | 0x4E534350) + 6):
1922 case CKK_ML_KEM0x00000049UL:
1923 crv = stfk_CopyTokenAttributes(destObject, src_to, mlkemPubKeyAttrs,
1924 mlkemPubKeyAttrsCount);
1925 break;
1926 case CKK_DH0x00000002UL:
1927 crv = stfk_CopyTokenAttributes(destObject, src_to, dhPubKeyAttrs,
1928 dhPubKeyAttrsCount);
1929 break;
1930 case CKK_EC0x00000003UL:
1931 case CKK_EC_EDWARDS0x00000040UL:
1932 case CKK_EC_MONTGOMERY0x00000041UL:
1933 crv = stfk_CopyTokenAttributes(destObject, src_to, ecPubKeyAttrs,
1934 ecPubKeyAttrsCount);
1935 break;
1936 default:
1937 crv = CKR_DEVICE_ERROR0x00000030UL; /* shouldn't happen unless we store more types
1938 * of token keys into our database. */
1939 }
1940fail:
1941 return crv;
1942}
1943CK_RV
1944stfk_CopyTokenSecretKey(SFTKObject *destObject, SFTKTokenObject *src_to)
1945{
1946 CK_RV crv;
1947 crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs,
1948 commonKeyAttrsCount);
1949 if (crv != CKR_OK0x00000000UL) {
1950 goto fail;
1951 }
1952 crv = stfk_CopyTokenAttributes(destObject, src_to, secretKeyAttrs,
1953 secretKeyAttrsCount);
1954fail:
1955 return crv;
1956}
1957
1958/*
1959 * Copy a token object. We need to explicitly copy the relevant
1960 * attributes since token objects don't store those attributes in
1961 * the token itself.
1962 */
1963CK_RV
1964sftk_CopyTokenObject(SFTKObject *destObject, SFTKObject *srcObject)
1965{
1966 SFTKTokenObject *src_to = sftk_narrowToTokenObject(srcObject);
1967 CK_RV crv;
1968
1969 PORT_Assert(src_to)((src_to) ? ((void)0) : PR_Assert("src_to", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 1969))
;
1970 if (src_to == NULL((void*)0)) {
1971 return CKR_DEVICE_ERROR0x00000030UL; /* internal state inconsistant */
1972 }
1973
1974 crv = stfk_CopyTokenAttributes(destObject, src_to, commonAttrs,
1975 commonAttrsCount);
1976 if (crv != CKR_OK0x00000000UL) {
1977 goto fail;
1978 }
1979 switch (src_to->obj.objclass) {
1980 case CKO_CERTIFICATE0x00000001UL:
1981 crv = stfk_CopyTokenAttributes(destObject, src_to, certAttrs,
1982 certAttrsCount);
1983 break;
1984 case CKO_NSS_TRUST((0x80000000UL | 0x4E534350) + 3):
1985 crv = stfk_CopyTokenAttributes(destObject, src_to, nssTrustAttrs,
1986 nssTrustAttrsCount);
1987 break;
1988 case CKO_TRUST0x0000000bUL:
1989 crv = stfk_CopyTokenAttributes(destObject, src_to, trustAttrs,
1990 trustAttrsCount);
1991 break;
1992 case CKO_NSS_SMIME((0x80000000UL | 0x4E534350) + 2):
1993 crv = stfk_CopyTokenAttributes(destObject, src_to, smimeAttrs,
1994 smimeAttrsCount);
1995 break;
1996 case CKO_NSS_CRL((0x80000000UL | 0x4E534350) + 1):
1997 crv = stfk_CopyTokenAttributes(destObject, src_to, crlAttrs,
1998 crlAttrsCount);
1999 break;
2000 case CKO_PRIVATE_KEY0x00000003UL:
2001 crv = stfk_CopyTokenPrivateKey(destObject, src_to);
2002 break;
2003 case CKO_PUBLIC_KEY0x00000002UL:
2004 crv = stfk_CopyTokenPublicKey(destObject, src_to);
2005 break;
2006 case CKO_SECRET_KEY0x00000004UL:
2007 crv = stfk_CopyTokenSecretKey(destObject, src_to);
2008 break;
2009 default:
2010 crv = CKR_DEVICE_ERROR0x00000030UL; /* shouldn't happen unless we store more types
2011 * of token keys into our database. */
2012 }
2013fail:
2014 return crv;
2015}
2016
2017/*
2018 * copy the attributes from one object to another. Don't overwrite existing
2019 * attributes. NOTE: This is a pretty expensive operation since it
2020 * grabs the attribute locks for the src object for a *long* time.
2021 */
2022CK_RV
2023sftk_CopyObject(SFTKObject *destObject, SFTKObject *srcObject)
2024{
2025 SFTKAttribute *attribute;
2026 SFTKSessionObject *src_so = sftk_narrowToSessionObject(srcObject);
2027 SFTKSessionObject *dest_so = sftk_narrowToSessionObject(destObject);
2028 unsigned int i;
2029
2030 destObject->validation_value = srcObject->validation_value;
2031 destObject->source = srcObject->source;
2032 if (src_so == NULL((void*)0)) {
2033 return sftk_CopyTokenObject(destObject, srcObject);
2034 }
2035 PORT_Assert(dest_so != NULL)((dest_so != ((void*)0)) ? ((void)0) : PR_Assert("dest_so != NULL"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 2035
))
;
2036 if (dest_so == NULL((void*)0)) {
2037 return CKR_ARGUMENTS_BAD0x00000007UL;
2038 }
2039
2040 PR_Lock(src_so->attributeLock);
2041 for (i = 0; i < src_so->hashSize; i++) {
2042 attribute = src_so->head[i];
2043 do {
2044 if (attribute) {
2045 SFTKAttribute *existing;
2046 sftkqueue_find(existing, attribute->handle,for ((existing) = (dest_so->head)[((PRUint32)((attribute->
handle) * 1791398085) & (dest_so->hashSize - 1))]; (existing
) != ((void*)0); (existing) = (existing)->next) { if ((existing
)->handle == (attribute->handle)) { break; } }
2047 dest_so->head, dest_so->hashSize)for ((existing) = (dest_so->head)[((PRUint32)((attribute->
handle) * 1791398085) & (dest_so->hashSize - 1))]; (existing
) != ((void*)0); (existing) = (existing)->next) { if ((existing
)->handle == (attribute->handle)) { break; } }
;
2048 if (!existing) {
2049 /* we need to copy the attribute since each attribute
2050 * only has one set of link list pointers */
2051 SFTKAttribute *newAttribute = sftk_InitAttribute(
2052 dest_so, dest_so->nextAttr++,
2053 sftk_attr_expand(&attribute->attrib)(&attribute->attrib)->type, (&attribute->attrib
)->pValue, (&attribute->attrib)->ulValueLen
);
2054 if (newAttribute == NULL((void*)0)) {
2055 PR_Unlock(src_so->attributeLock);
2056 return CKR_HOST_MEMORY0x00000002UL;
2057 }
2058 sftkqueue_add(newAttribute, newAttribute->handle,{ int tmp = ((PRUint32)((newAttribute->handle) * 1791398085
) & (dest_so->hashSize - 1)); (newAttribute)->next =
(dest_so->head)[tmp]; (newAttribute)->prev = ((void*)0
); if ((dest_so->head)[tmp]) (dest_so->head)[tmp]->prev
= (newAttribute); (dest_so->head)[tmp] = (newAttribute); }
2059 dest_so->head, dest_so->hashSize){ int tmp = ((PRUint32)((newAttribute->handle) * 1791398085
) & (dest_so->hashSize - 1)); (newAttribute)->next =
(dest_so->head)[tmp]; (newAttribute)->prev = ((void*)0
); if ((dest_so->head)[tmp]) (dest_so->head)[tmp]->prev
= (newAttribute); (dest_so->head)[tmp] = (newAttribute); }
;
2060 }
2061 attribute = attribute->next;
2062 }
2063 } while (attribute != NULL((void*)0));
2064 }
2065 PR_Unlock(src_so->attributeLock);
2066
2067 return CKR_OK0x00000000UL;
2068}
2069
2070/*
2071 * ******************** Search Utilities *******************************
2072 */
2073
2074/* add an object to a search list */
2075CK_RV
2076AddToList(SFTKObjectListElement **list, SFTKObject *object)
2077{
2078 SFTKObjectListElement *newElem =
2079 (SFTKObjectListElement *)PORT_AllocPORT_Alloc_Util(sizeof(SFTKObjectListElement));
2080
2081 if (newElem == NULL((void*)0))
2082 return CKR_HOST_MEMORY0x00000002UL;
2083
2084 newElem->next = *list;
2085 newElem->object = object;
2086 sftk_ReferenceObject(object);
2087
2088 *list = newElem;
2089 return CKR_OK0x00000000UL;
2090}
2091
2092/* return true if the object matches the template */
2093PRBool
2094sftk_objectMatch(SFTKObject *object, CK_ATTRIBUTE_PTR theTemplate, int count)
2095{
2096 int i;
2097
2098 for (i = 0; i < count; i++) {
6
Assuming 'i' is < 'count'
7
Loop condition is true. Entering loop body
2099 SFTKAttribute *attribute = sftk_FindAttribute(object, theTemplate[i].type);
8
Calling 'sftk_FindAttribute'
25
Returning from 'sftk_FindAttribute'
2100 if (attribute
25.1
'attribute' is not equal to NULL
== NULL((void*)0)) {
26
Taking false branch
2101 return PR_FALSE0;
2102 }
2103 if (attribute->attrib.ulValueLen == theTemplate[i].ulValueLen) {
27
Assuming 'attribute->attrib.ulValueLen' is equal to 'theTemplate[i].ulValueLen'
28
Taking true branch
2104 if (PORT_Memcmpmemcmp(attribute->attrib.pValue, theTemplate[i].pValue,
29
Null pointer passed to 1st parameter expecting 'nonnull'
2105 theTemplate[i].ulValueLen) == 0) {
2106 sftk_FreeAttribute(attribute);
2107 continue;
2108 }
2109 }
2110 sftk_FreeAttribute(attribute);
2111 return PR_FALSE0;
2112 }
2113 return PR_TRUE1;
2114}
2115
2116/* search through all the objects in the queue and return the template matches
2117 * in the object list.
2118 */
2119CK_RV
2120sftk_searchObjectList(SFTKSearchResults *search, SFTKObject **head,
2121 unsigned int size, PRLock *lock, CK_ATTRIBUTE_PTR theTemplate,
2122 int count, PRBool isLoggedIn)
2123{
2124 unsigned int i;
2125 SFTKObject *object;
2126 CK_RV crv = CKR_OK0x00000000UL;
2127
2128 PR_Lock(lock);
2129 for (i = 0; i < size; i++) {
1
Assuming 'i' is < 'size'
2
Loop condition is true. Entering loop body
2130 for (object = head[i]; object != NULL((void*)0); object = object->next) {
3
Assuming 'object' is not equal to NULL
4
Loop condition is true. Entering loop body
2131 if (sftk_objectMatch(object, theTemplate, count)) {
5
Calling 'sftk_objectMatch'
2132 /* don't return objects that aren't yet visible */
2133 if ((!isLoggedIn) && sftk_isTrue(object, CKA_PRIVATE0x00000002UL))
2134 continue;
2135 sftk_addHandle(search, object->handle);
2136 }
2137 }
2138 }
2139 PR_Unlock(lock);
2140 return crv;
2141}
2142
2143/*
2144 * free a single list element. Return the Next object in the list.
2145 */
2146SFTKObjectListElement *
2147sftk_FreeObjectListElement(SFTKObjectListElement *objectList)
2148{
2149 SFTKObjectListElement *ol = objectList->next;
2150
2151 sftk_FreeObject(objectList->object);
2152 PORT_FreePORT_Free_Util(objectList);
2153 return ol;
2154}
2155
2156/* free an entire object list */
2157void
2158sftk_FreeObjectList(SFTKObjectListElement *objectList)
2159{
2160 SFTKObjectListElement *ol;
2161
2162 for (ol = objectList; ol != NULL((void*)0); ol = sftk_FreeObjectListElement(ol)) {
2163 }
2164}
2165
2166/*
2167 * free a search structure
2168 */
2169void
2170sftk_FreeSearch(SFTKSearchResults *search)
2171{
2172 if (search->handles) {
2173 PORT_FreePORT_Free_Util(search->handles);
2174 }
2175 PORT_FreePORT_Free_Util(search);
2176}
2177
2178/*
2179 * ******************** Session Utilities *******************************
2180 */
2181
2182/* update the sessions state based in it's flags and wether or not it's
2183 * logged in */
2184void
2185sftk_update_state(SFTKSlot *slot, SFTKSession *session)
2186{
2187 PR_Lock(slot->slotLock);
2188 if (slot->isLoggedIn) {
2189 if (slot->ssoLoggedIn) {
2190 session->info.state = CKS_RW_SO_FUNCTIONS4;
2191 } else if (session->info.flags & CKF_RW_SESSION0x00000002UL) {
2192 session->info.state = CKS_RW_USER_FUNCTIONS3;
2193 } else {
2194 session->info.state = CKS_RO_USER_FUNCTIONS1;
2195 }
2196 } else {
2197 if (session->info.flags & CKF_RW_SESSION0x00000002UL) {
2198 session->info.state = CKS_RW_PUBLIC_SESSION2;
2199 } else {
2200 session->info.state = CKS_RO_PUBLIC_SESSION0;
2201 }
2202 }
2203 PR_Unlock(slot->slotLock);
2204}
2205
2206/* update the state of all the sessions on a slot */
2207void
2208sftk_update_all_states(SFTKSlot *slot)
2209{
2210 unsigned int i;
2211 SFTKSession *session;
2212
2213 for (i = 0; i < slot->sessHashSize; i++) {
2214 PRLock *lock = SFTK_HEAD_BUCKET_LOCK(slot, i)((slot)->sessionLock[((i) >> 0) & (slot)->sessionLockMask
])
;
2215 PR_Lock(lock);
2216 for (session = slot->head[i]; session; session = session->next) {
2217 sftk_update_state(slot, session);
2218 }
2219 PR_Unlock(lock);
2220 }
2221}
2222
2223/*
2224 * context are cipher and digest contexts that are associated with a session
2225 */
2226void
2227sftk_FreeContext(SFTKSessionContext *context)
2228{
2229 if (context->cipherInfo) {
2230 (*context->destroy)(context->cipherInfo, PR_TRUE1);
2231 }
2232 if (context->hashInfo) {
2233 (*context->hashdestroy)(context->hashInfo, PR_TRUE1);
2234 }
2235 if (context->key) {
2236 sftk_FreeObject(context->key);
2237 context->key = NULL((void*)0);
2238 }
2239 if (context->signature) {
2240 SECITEM_FreeItemSECITEM_FreeItem_Util(context->signature, PR_TRUE1);
2241 context->signature = NULL((void*)0);
2242 }
2243 PORT_FreePORT_Free_Util(context);
2244}
2245
2246/*
2247 * Init a new session. NOTE: The session handle is not set, and the
2248 * session is not added to the slot's session queue.
2249 */
2250CK_RV
2251sftk_InitSession(SFTKSession *session, SFTKSlot *slot, CK_SLOT_ID slotID,
2252 CK_NOTIFY notify, CK_VOID_PTR pApplication, CK_FLAGS flags)
2253{
2254 session->next = session->prev = NULL((void*)0);
2255 session->refCount = 1;
2256 session->enc_context = NULL((void*)0);
2257 session->hash_context = NULL((void*)0);
2258 session->search = NULL((void*)0);
2259 session->objectIDCount = 1;
2260 /* session->objects[] is protected by slot->objectLock, not by a
2261 * per-session lock -- see the lock notes on SFTKSlotStr. */
2262 session->objects[0] = NULL((void*)0);
2263
2264 session->slot = slot;
2265 session->notify = notify;
2266 session->appData = pApplication;
2267 session->info.flags = flags;
2268 session->info.slotID = slotID;
2269 session->info.ulDeviceError = 0;
2270 sftk_update_state(slot, session);
2271 /* no ops completed yet, so the last one couldn't be a FIPS op */
2272 session->lastOpWasFIPS = PR_FALSE0;
2273 return CKR_OK0x00000000UL;
2274}
2275
2276/*
2277 * Create a new session and init it.
2278 */
2279SFTKSession *
2280sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication,
2281 CK_FLAGS flags)
2282{
2283 SFTKSession *session;
2284 SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE0);
2285 CK_RV crv;
2286
2287 if (slot == NULL((void*)0))
2288 return NULL((void*)0);
2289
2290 session = (SFTKSession *)PORT_AllocPORT_Alloc_Util(sizeof(SFTKSession));
2291 if (session == NULL((void*)0))
2292 return NULL((void*)0);
2293
2294 crv = sftk_InitSession(session, slot, slotID, notify, pApplication, flags);
2295 if (crv != CKR_OK0x00000000UL) {
2296 PORT_FreePORT_Free_Util(session);
2297 return NULL((void*)0);
2298 }
2299 return session;
2300}
2301
2302/* free all the data associated with a session. */
2303void
2304sftk_ClearSession(SFTKSession *session)
2305{
2306 SFTKSlot *slot = sftk_SlotFromSession(session)((session)->slot);
2307 SFTKObjectList *op, *next;
2308 SFTKObjectList *toFree = NULL((void*)0);
2309
2310 /* Detach every object this session still owns.
2311 *
2312 * No one references the session any more, but that does not make it safe
2313 * to walk this chain unlocked: object handles are slot-global, so a
2314 * C_DestroyObject on any other session may be removing one of these
2315 * objects right now. slot->objectLock arbitrates both queues and belongs
2316 * to the slot, which outlives every session on it.
2317 */
2318 PR_Lock(slot->objectLock);
2319 for (op = session->objects[0]; op != NULL((void*)0); op = next) {
2320 next = op->next;
2321 /* Unlink by hand: we are discarding the whole list, so there is no
2322 * point patching neighbours. */
2323 op->next = op->prev = NULL((void*)0);
2324 /* Everything on this list is still in the slot hash -- a claimant
2325 * unlinks it from both under this lock -- so the claim normally
2326 * succeeds. The test guards against a path that ever removes an
2327 * object from only one queue. */
2328 if (sftk_ClaimObjectRemovalLocked(slot, op->parent)) {
2329 /* We own the queues' reference, so the object stays alive until
2330 * we drop it; chain the unlinked element up and free below. */
2331 op->next = toFree;
2332 toFree = op;
2333 }
2334 }
2335 session->objects[0] = NULL((void*)0);
2336 PR_Unlock(slot->objectLock);
2337
2338 /* An object that outlives us -- because another thread still holds a
2339 * reference -- keeps a stale so->session pointing here. That is safe:
2340 * so->session is only dereferenced under slot->objectLock by a thread
2341 * that has just won the removal claim, and the claim can no longer
2342 * succeed for an object we have already pulled out of the slot hash. */
2343 for (op = toFree; op != NULL((void*)0); op = next) {
2344 next = op->next;
2345 op->next = NULL((void*)0);
2346 sftk_FreeObject(op->parent); /* drop the queues' reference */
2347 }
2348
2349 if (session->enc_context) {
2350 sftk_FreeContext(session->enc_context);
2351 session->enc_context = NULL((void*)0);
2352 }
2353 if (session->hash_context) {
2354 sftk_FreeContext(session->hash_context);
2355 session->hash_context = NULL((void*)0);
2356 }
2357 if (session->search) {
2358 sftk_FreeSearch(session->search);
2359 session->search = NULL((void*)0);
2360 }
2361}
2362
2363/* free the data associated with the session, and the session.
2364 * Caller must have driven refCount to 0; reachable only via sftk_FreeSession. */
2365static void
2366sftk_DestroySession(SFTKSession *session)
2367{
2368 PORT_ReleaseAssert(session->refCount == 0)((session->refCount == 0) ? ((void)0) : PR_Assert("session->refCount == 0"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 2368
))
;
2369 sftk_ClearSession(session);
2370 PORT_FreePORT_Free_Util(session);
2371}
2372
2373/*
2374 * look up a session structure from a session handle
2375 * generate a reference to it.
2376 */
2377SFTKSession *
2378sftk_SessionFromHandle(CK_SESSION_HANDLE handle)
2379{
2380 SFTKSlot *slot = sftk_SlotFromSessionHandle(handle);
2381 SFTKSession *session;
2382 PRLock *lock;
2383
2384 if (!slot)
2385 return NULL((void*)0);
2386 lock = SFTK_SESSION_LOCK(slot, handle)((slot)->sessionLock[((((PRUint32)(((handle)) * 1791398085
) & ((slot)->sessHashSize - 1))) >> 0) & (slot
)->sessionLockMask])
;
2387
2388 PR_Lock(lock);
2389 sftkqueue_find(session, handle, slot->head, slot->sessHashSize)for ((session) = (slot->head)[((PRUint32)((handle) * 1791398085
) & (slot->sessHashSize - 1))]; (session) != ((void*)0
); (session) = (session)->next) { if ((session)->handle
== (handle)) { break; } }
;
2390 if (session)
2391 session->refCount++;
2392 PR_Unlock(lock);
2393
2394 return (session);
2395}
2396
2397/*
2398 * release a reference to a session. The slot's session bucket holds the
2399 * initial reference (created by sftk_InitSession); sftk_SessionFromHandle
2400 * adds another for the duration of the caller's use. NSC_CloseSession and
2401 * sftk_CloseAllSessions drop the bucket's reference once the session has
2402 * been removed from the queue. The thread that drives refCount to 0
2403 * destroys the session.
2404 */
2405void
2406sftk_FreeSession(SFTKSession *session)
2407{
2408 PRBool destroy = PR_FALSE0;
2409 SFTKSlot *slot = sftk_SlotFromSession(session)((session)->slot);
2410 PRLock *lock = SFTK_SESSION_LOCK(slot, session->handle)((slot)->sessionLock[((((PRUint32)(((session->handle)) *
1791398085) & ((slot)->sessHashSize - 1))) >> 0
) & (slot)->sessionLockMask])
;
2411
2412 PR_Lock(lock);
2413 PORT_ReleaseAssert(session->refCount > 0)((session->refCount > 0) ? ((void)0) : PR_Assert("session->refCount > 0"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 2413
))
;
2414 if (session->refCount == 1)
2415 destroy = PR_TRUE1;
2416 session->refCount--;
2417 PR_Unlock(lock);
2418
2419 if (destroy)
2420 sftk_DestroySession(session);
2421}
2422
2423void
2424sftk_addHandle(SFTKSearchResults *search, CK_OBJECT_HANDLE handle)
2425{
2426 if (search->handles == NULL((void*)0)) {
2427 return;
2428 }
2429 if (search->size >= search->array_size) {
2430 search->array_size += NSC_SEARCH_BLOCK_SIZE5;
2431 search->handles = (CK_OBJECT_HANDLE *)PORT_ReallocPORT_Realloc_Util(search->handles,
2432 sizeof(CK_OBJECT_HANDLE) * search->array_size);
2433 if (search->handles == NULL((void*)0)) {
2434 return;
2435 }
2436 }
2437 search->handles[search->size] = handle;
2438 search->size++;
2439}
2440
2441static CK_RV
2442handleToClass(SFTKSlot *slot, CK_OBJECT_HANDLE handle,
2443 CK_OBJECT_CLASS *objClass)
2444{
2445 SFTKDBHandle *dbHandle = sftk_getDBForTokenObject(slot, handle);
2446 CK_ATTRIBUTE objClassTemplate;
2447 CK_RV crv;
2448
2449 *objClass = CKO_DATA0x00000000UL;
2450 objClassTemplate.type = CKA_CLASS0x00000000UL;
2451 objClassTemplate.pValue = objClass;
2452 objClassTemplate.ulValueLen = sizeof(*objClass);
2453 crv = sftkdb_GetAttributeValue(dbHandle, handle, &objClassTemplate, 1);
2454 sftk_freeDB(dbHandle);
2455 return crv;
2456}
2457
2458SFTKObject *
2459sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle)
2460{
2461 SFTKObject *object = NULL((void*)0);
2462 PRBool hasLocks = PR_FALSE0;
2463 CK_RV crv;
2464
2465 object = sftk_GetObjectFromList(&hasLocks, PR_FALSE0, &tokenObjectList, 0,
2466 PR_FALSE0);
2467 if (object == NULL((void*)0)) {
2468 return NULL((void*)0);
2469 }
2470
2471 object->handle = handle;
2472 /* every object must have a class, if we can't get it, the object
2473 * doesn't exist */
2474 crv = handleToClass(slot, handle, &object->objclass);
2475 if (crv != CKR_OK0x00000000UL) {
2476 goto loser;
2477 }
2478 object->slot = slot;
2479 /* set up the validation flags */
2480 object->validation_value = 0;
2481 object->validation_attribute.next = NULL((void*)0);
2482 object->validation_attribute.prev = NULL((void*)0);
2483 object->validation_attribute.freeAttr = PR_FALSE0;
2484 object->validation_attribute.freeData = PR_FALSE0;
2485 object->validation_attribute.handle = CKA_OBJECT_VALIDATION_FLAGS0x0000061eUL;
2486 object->validation_attribute.attrib.type = CKA_OBJECT_VALIDATION_FLAGS0x0000061eUL;
2487 object->validation_attribute.attrib.pValue = &object->validation_value;
2488 object->validation_attribute.attrib.ulValueLen = sizeof(object->validation_value);
2489 /* initialize the FIPS flag properly */
2490 sftk_setFIPS(object, sftk_isFIPS(slot->slotID)(((slot->slotID) == 3) || ((slot->slotID) >= 101)));
2491 object->source = SFTK_SOURCE_DEFAULT;
2492 object->objectInfo = NULL((void*)0);
2493 object->infoFree = NULL((void*)0);
2494 if (!hasLocks) {
2495 object->refLock = PR_NewLock();
2496 }
2497 if (object->refLock == NULL((void*)0)) {
2498 goto loser;
2499 }
2500 object->refCount = 1;
2501 object->type = SFTK_TOKEN_OBJECT_TYPE0x00000000U;
2502
2503 return object;
2504loser:
2505 (void)sftk_DestroyObject(object);
2506 return NULL((void*)0);
2507}
2508
2509CK_RV
2510sftk_convertSessionToToken(SFTKObject *obj)
2511{
2512 SECItem *dbKey;
2513 SFTKSessionObject *so = (SFTKSessionObject *)obj;
2514 SFTKTokenObject *to = sftk_narrowToTokenObject(obj);
2515 CK_RV crv;
2516
2517 sftk_DestroySessionObjectData(so);
2518 PR_DestroyLock(so->attributeLock);
2519
2520 sftk_tokenKeyLock(so->obj.slot);
2521 dbKey = sftk_lookupTokenKeyByHandle(so->obj.slot, so->obj.handle);
2522 if (dbKey && SECFailure == SECITEM_CopyItemSECITEM_CopyItem_Util(NULL((void*)0), &to->dbKey, dbKey)) {
2523 crv = CKR_HOST_MEMORY0x00000002UL;
2524 } else {
2525 crv = CKR_OK0x00000000UL;
2526 }
2527 sftk_tokenKeyUnlock(so->obj.slot);
2528 return crv;
2529}
2530
2531SFTKSessionObject *
2532sftk_narrowToSessionObject(SFTKObject *obj)
2533{
2534 PRBool handleSaysSession = !sftk_isToken(obj->handle)(((obj->handle) & 0x80000000L) == 0x80000000L);
2535 PRBool typeSaysSession = obj->type == SFTK_SESSION_OBJECT_TYPE0xFFFFFFFFU;
2536 if (handleSaysSession != typeSaysSession) {
2537 PORT_Assert(0)((0) ? ((void)0) : PR_Assert("0", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 2537))
;
2538 return NULL((void*)0);
2539 }
2540 return handleSaysSession ? (SFTKSessionObject *)obj : NULL((void*)0);
2541}
2542
2543SFTKTokenObject *
2544sftk_narrowToTokenObject(SFTKObject *obj)
2545{
2546 PRBool handleSaysToken = sftk_isToken(obj->handle)(((obj->handle) & 0x80000000L) == 0x80000000L);
2547 PRBool typeSaysToken = obj->type == SFTK_TOKEN_OBJECT_TYPE0x00000000U;
2548 if (handleSaysToken != typeSaysToken) {
2549 PORT_Assert(0)((0) ? ((void)0) : PR_Assert("0", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 2549))
;
2550 return NULL((void*)0);
2551 }
2552 return handleSaysToken ? (SFTKTokenObject *)obj : NULL((void*)0);
2553}
2554
2555/* Constant time helper functions */
2556
2557/* sftk_CKRVToMask returns, in constant time, a mask value of
2558 * all ones if rv == CKR_OK. Otherwise it returns zero. */
2559unsigned int
2560sftk_CKRVToMask(CK_RV rv)
2561{
2562 PR_STATIC_ASSERT(CKR_OK == 0)extern void pr_static_assert(int arg[(0x00000000UL == 0) ? 1 :
-1])
;
2563 return ~PORT_CT_NOT_ZERO(rv)(((PRUint32)((PRInt32)(((rv) | (0 - (rv)))) >> (sizeof(
PRInt32) * 8 - 1))))
;
2564}
2565
2566/* sftk_CheckCBCPadding checks, in constant time, the padding validity and
2567 * accordingly sets the pad length. */
2568CK_RV
2569sftk_CheckCBCPadding(CK_BYTE_PTR pBuf, unsigned int bufLen,
2570 unsigned int blockSize, unsigned int *outPadSize)
2571{
2572 PORT_Assert(outPadSize)((outPadSize) ? ((void)0) : PR_Assert("outPadSize", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 2572))
;
2573
2574 /* CBC-padded plaintext is always at least one full block */
2575 if (bufLen < blockSize || blockSize == 0) {
2576 *outPadSize = 0;
2577 return CKR_ENCRYPTED_DATA_INVALID0x00000040UL;
2578 }
2579
2580 unsigned int padSize = (unsigned int)pBuf[bufLen - 1];
2581
2582 /* If padSize <= blockSize, set goodPad to all-1s and all-0s otherwise.*/
2583 unsigned int goodPad = PORT_CT_DUPLICATE_MSB_TO_ALL(~(blockSize - padSize))((PRUint32)((PRInt32)(~(blockSize - padSize)) >> (sizeof
(PRInt32) * 8 - 1)))
;
2584 /* padSize should not be 0 */
2585 goodPad &= PORT_CT_NOT_ZERO(padSize)(((PRUint32)((PRInt32)(((padSize) | (0 - (padSize)))) >>
(sizeof(PRInt32) * 8 - 1))))
;
2586
2587 unsigned int i;
2588 for (i = 0; i < blockSize; i++) {
2589 /* If i < padSize, set loopMask to all-1s and all-0s otherwise.*/
2590 unsigned int loopMask = PORT_CT_DUPLICATE_MSB_TO_ALL(~(padSize - 1 - i))((PRUint32)((PRInt32)(~(padSize - 1 - i)) >> (sizeof(PRInt32
) * 8 - 1)))
;
2591 /* Get the padding value (should be padSize) from buffer */
2592 unsigned int padVal = pBuf[bufLen - 1 - i];
2593 /* Update goodPad only if i < padSize */
2594 goodPad &= PORT_CT_SEL(loopMask, ~(padVal ^ padSize), goodPad)(((loopMask) & (~(padVal ^ padSize))) | (~(loopMask) &
(goodPad)))
;
2595 }
2596
2597 /* If any of the final padding bytes had the wrong value, one or more
2598 * of the lower eight bits of |goodPad| will be cleared. We AND the
2599 * bottom 8 bits together and duplicate the result to all the bits. */
2600 goodPad &= goodPad >> 4;
2601 goodPad &= goodPad >> 2;
2602 goodPad &= goodPad >> 1;
2603 goodPad <<= sizeof(goodPad) * 8 - 1;
2604 goodPad = PORT_CT_DUPLICATE_MSB_TO_ALL(goodPad)((PRUint32)((PRInt32)(goodPad) >> (sizeof(PRInt32) * 8 -
1)))
;
2605
2606 /* Set outPadSize to padSize or 0 */
2607 *outPadSize = PORT_CT_SEL(goodPad, padSize, 0)(((goodPad) & (padSize)) | (~(goodPad) & (0)));
2608 /* Return OK if the pad is valid */
2609 return PORT_CT_SEL(goodPad, CKR_OK, CKR_ENCRYPTED_DATA_INVALID)(((goodPad) & (0x00000000UL)) | (~(goodPad) & (0x00000040UL
)))
;
2610}
2611
2612void
2613sftk_EncodeInteger(PRUint64 integer, CK_ULONG num_bits, CK_BBOOL littleEndian,
2614 CK_BYTE_PTR output, CK_ULONG_PTR output_len)
2615{
2616 if (output_len) {
2617 *output_len = (num_bits / 8);
2618 }
2619
2620 PR_ASSERT(num_bits > 0 && num_bits <= 64 && (num_bits % 8) == 0)((num_bits > 0 && num_bits <= 64 && (num_bits
% 8) == 0) ? ((void)0) : PR_Assert("num_bits > 0 && num_bits <= 64 && (num_bits % 8) == 0"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 2620
))
;
2621
2622 if (littleEndian == CK_TRUE1) {
2623 for (size_t offset = 0; offset < num_bits / 8; offset++) {
2624 output[offset] = (unsigned char)((integer >> (offset * 8)) & 0xFF);
2625 }
2626 } else {
2627 for (size_t offset = 0; offset < num_bits / 8; offset++) {
2628 PRUint64 shift = num_bits - (offset + 1) * 8;
2629 output[offset] = (unsigned char)((integer >> shift) & 0xFF);
2630 }
2631 }
2632}
2633
2634CK_FLAGS
2635sftk_AttributeToFlags(CK_ATTRIBUTE_TYPE op)
2636{
2637 CK_FLAGS flags = 0;
2638
2639 switch (op) {
2640 case CKA_ENCRYPT0x00000104UL:
2641 flags = CKF_ENCRYPT0x00000100UL;
2642 break;
2643 case CKA_DECRYPT0x00000105UL:
2644 flags = CKF_DECRYPT0x00000200UL;
2645 break;
2646 case CKA_WRAP0x00000106UL:
2647 flags = CKF_WRAP0x00020000UL;
2648 break;
2649 case CKA_UNWRAP0x00000107UL:
2650 flags = CKF_UNWRAP0x00040000UL;
2651 break;
2652 case CKA_SIGN0x00000108UL:
2653 flags = CKF_SIGN0x00000800UL;
2654 break;
2655 case CKA_SIGN_RECOVER0x00000109UL:
2656 flags = CKF_SIGN_RECOVER0x00001000UL;
2657 break;
2658 case CKA_VERIFY0x0000010AUL:
2659 flags = CKF_VERIFY0x00002000;
2660 break;
2661 case CKA_VERIFY_RECOVER0x0000010BUL:
2662 flags = CKF_VERIFY_RECOVER0x00004000UL;
2663 break;
2664 case CKA_DERIVE0x0000010CUL:
2665 flags = CKF_DERIVE0x00080000UL;
2666 break;
2667 /* fake attribute to select digesting */
2668 case CKA_DIGEST0x81000000L:
2669 flags = CKF_DIGEST0x00000400UL;
2670 break;
2671 /* fake attribute to select key gen */
2672 case CKA_NSS_GENERATE0x81000001L:
2673 flags = CKF_GENERATE0x00008000UL;
2674 break;
2675 /* fake attribute to select key pair gen */
2676 case CKA_NSS_GENERATE_KEY_PAIR0x81000002L:
2677 flags = CKF_GENERATE_KEY_PAIR0x00010000UL;
2678 break;
2679 /* fake attributes to to handle MESSAGE* flags */
2680 case CKA_NSS_MESSAGE0x82000000L | CKA_ENCRYPT0x00000104UL:
2681 flags = CKF_MESSAGE_ENCRYPT0x00000002UL;
2682 break;
2683 case CKA_NSS_MESSAGE0x82000000L | CKA_DECRYPT0x00000105UL:
2684 flags = CKF_MESSAGE_DECRYPT0x00000004UL;
2685 break;
2686 case CKA_NSS_MESSAGE0x82000000L | CKA_SIGN0x00000108UL:
2687 flags = CKF_MESSAGE_SIGN0x00000008UL;
2688 break;
2689 case CKA_NSS_MESSAGE0x82000000L | CKA_VERIFY0x0000010AUL:
2690 flags = CKF_MESSAGE_VERIFY0x00000010UL;
2691 break;
2692 default:
2693 break;
2694 }
2695 return flags;
2696}
2697
2698/*
2699 * ******************** Hash Utilities **************************
2700 */
2701/*
2702 * Utility function for converting PSS/OAEP parameter types into
2703 * HASH_HashTypes. Note: Only SHA family functions are defined in RFC 3447.
2704 */
2705HASH_HashType
2706sftk_GetHashTypeFromMechanism(CK_MECHANISM_TYPE mech)
2707{
2708 switch (mech) {
2709 case CKM_SHA_10x00000220UL:
2710 case CKG_MGF1_SHA10x00000001UL:
2711 return HASH_AlgSHA1;
2712 case CKM_SHA2240x00000255UL:
2713 case CKG_MGF1_SHA2240x00000005UL:
2714 return HASH_AlgSHA224;
2715 case CKM_SHA2560x00000250UL:
2716 case CKG_MGF1_SHA2560x00000002UL:
2717 return HASH_AlgSHA256;
2718 case CKM_SHA3840x00000260UL:
2719 case CKG_MGF1_SHA3840x00000003UL:
2720 return HASH_AlgSHA384;
2721 case CKM_SHA5120x00000270UL:
2722 case CKG_MGF1_SHA5120x00000004UL:
2723 return HASH_AlgSHA512;
2724 default:
2725 return HASH_AlgNULL;
2726 }
2727}
2728
2729#ifdef NSS_HAS_FIPS_INDICATORS
2730/**************** FIPS Indicator Utilities *************************/
2731/* sigh, we probably need a version of this in secutil so that both
2732 * softoken and NSS can use it */
2733static SECOidTag
2734sftk_quickGetECCCurveOid(SFTKObject *source)
2735{
2736 SFTKAttribute *attribute = sftk_FindAttribute(source, CKA_EC_PARAMS0x00000180UL);
2737 unsigned char *encoded;
2738 int len;
2739 SECItem oid;
2740 SECOidTag tag;
2741
2742 if (attribute == NULL((void*)0)) {
2743 return SEC_OID_UNKNOWN;
2744 }
2745 encoded = attribute->attrib.pValue;
2746 len = attribute->attrib.ulValueLen;
2747 if ((len < 2) || (encoded[0] != SEC_ASN1_OBJECT_ID0x06) ||
2748 (len != encoded[1] + 2)) {
2749 sftk_FreeAttribute(attribute);
2750 return SEC_OID_UNKNOWN;
2751 }
2752 oid.data = encoded + 2;
2753 oid.len = len - 2;
2754 tag = SECOID_FindOIDTagSECOID_FindOIDTag_Util(&oid);
2755 sftk_FreeAttribute(attribute);
2756 return tag;
2757}
2758
2759/* This function currently only returns valid lengths for
2760 * FIPS approved ECC curves. If we want to make this generic
2761 * in the future, that Curve determination can be done in
2762 * the sftk_handleSpecial. Since it's currently only used
2763 * in FIPS indicators, it's currently only compiled with
2764 * the FIPS indicator code */
2765static CK_ULONG
2766sftk_getKeyLength(SFTKObject *source)
2767{
2768 CK_KEY_TYPE keyType = CKK_INVALID_KEY_TYPE0xffffffffUL;
2769 CK_ATTRIBUTE_TYPE keyAttribute;
2770 CK_ULONG keyLength = 0;
2771 SFTKAttribute *attribute;
2772 CK_RV crv;
2773
2774 /* If we don't have a key, then it doesn't have a length.
2775 * this may be OK (say we are hashing). The mech info will
2776 * sort this out because algorithms which expect no keys
2777 * will accept zero length for the keys */
2778 if (source == NULL((void*)0)) {
2779 return 0;
2780 }
2781
2782 crv = sftk_GetULongAttribute(source, CKA_KEY_TYPE0x00000100UL, &keyType);
2783 if (crv != CKR_OK0x00000000UL) {
2784 /* sometimes we're passed a data object, in that case the
2785 * key length is CKA_VALUE, which is the default */
2786 keyType = CKK_INVALID_KEY_TYPE0xffffffffUL;
2787 }
2788 if ((keyType == CKK_EC0x00000003UL) || (keyType == CKK_EC_EDWARDS0x00000040UL) ||
2789 (keyType == CKK_EC_MONTGOMERY0x00000041UL)) {
2790 SECOidTag curve = sftk_quickGetECCCurveOid(source);
2791 switch (curve) {
2792 case SEC_OID_CURVE25519:
2793 /* change when we start algorithm testing on curve25519 */
2794 return 0;
2795 case SEC_OID_SECG_EC_SECP256R1SEC_OID_ANSIX962_EC_PRIME256V1:
2796 return 256;
2797 case SEC_OID_SECG_EC_SECP384R1:
2798 return 384;
2799 case SEC_OID_SECG_EC_SECP521R1:
2800 /* this is a lie, but it makes the table easier. We don't
2801 * have to have a double entry for every ECC mechanism */
2802 return 512;
2803 default:
2804 break;
2805 }
2806 /* other curves aren't NIST approved, returning 0 will cause these
2807 * curves to fail FIPS length criteria */
2808 return 0;
2809 }
2810
2811 switch (keyType) {
2812 case CKK_RSA0x00000000UL:
2813 keyAttribute = CKA_MODULUS0x00000120UL;
2814 break;
2815 case CKK_DSA0x00000001UL:
2816 case CKK_DH0x00000002UL:
2817 keyAttribute = CKA_PRIME0x00000130UL;
2818 break;
2819 default:
2820 keyAttribute = CKA_VALUE0x00000011UL;
2821 break;
2822 }
2823 attribute = sftk_FindAttribute(source, keyAttribute);
2824 if (attribute) {
2825 keyLength = attribute->attrib.ulValueLen * 8;
2826 sftk_FreeAttribute(attribute);
2827 }
2828 return keyLength;
2829}
2830
2831static PRBool
2832sftk_checkKeyLength(CK_ULONG keyLength, CK_ULONG min,
2833 CK_ULONG max, CK_ULONG step)
2834{
2835 if (keyLength > max) {
2836 return PR_FALSE0;
2837 }
2838 if (keyLength < min) {
2839 return PR_FALSE0;
2840 }
2841 if (step == 0) {
2842 return PR_TRUE1;
2843 }
2844 if (((keyLength - min) % step) != 0) {
2845 return PR_FALSE0;
2846 }
2847 return PR_TRUE1;
2848}
2849
2850PRBool
2851sftk_checkFIPSHash(CK_MECHANISM_TYPE hash, PRBool allowSmall, PRBool allowCMAC)
2852{
2853 switch (hash) {
2854 case CKM_AES_CMAC0x0000108AUL:
2855 return allowCMAC;
2856 case CKM_SHA_10x00000220UL:
2857 case CKM_SHA_1_HMAC0x00000221UL:
2858 case CKM_SHA2240x00000255UL:
2859 case CKM_SHA224_HMAC0x00000256UL:
2860 return allowSmall;
2861 case CKM_SHA2560x00000250UL:
2862 case CKM_SHA256_HMAC0x00000251UL:
2863 case CKM_SHA3840x00000260UL:
2864 case CKM_SHA384_HMAC0x00000261UL:
2865 case CKM_SHA5120x00000270UL:
2866 case CKM_SHA512_HMAC0x00000271UL:
2867 return PR_TRUE1;
2868 }
2869 return PR_FALSE0;
2870}
2871
2872/*
2873 * handle specialized FIPS semantics that are too complicated to
2874 * handle with just a table. NOTE: this means any additional semantics
2875 * would have to be coded here before they can be added to the table */
2876static PRBool
2877sftk_handleSpecial(SFTKSlot *slot, CK_MECHANISM *mech,
2878 SFTKFIPSAlgorithmList *mechInfo, SFTKObject *source,
2879 CK_ULONG keyLength, CK_ULONG targetKeyLength)
2880{
2881 PRBool allowSmall = PR_FALSE0;
2882 PRBool allowCMAC = PR_FALSE0;
2883 switch (mechInfo->special) {
2884 case SFTKFIPSDH: {
2885 SECItem dhPrime;
2886 SECItem dhBase;
2887 SECItem dhGenerator;
2888 PRBool fipsOk = PR_FALSE0;
2889 const SECItem *dhSubPrime;
2890 CK_RV crv = sftk_Attribute2SecItem(NULL((void*)0), &dhPrime,
2891 source, CKA_PRIME0x00000130UL);
2892 if (crv != CKR_OK0x00000000UL) {
2893 return PR_FALSE0;
2894 }
2895 crv = sftk_Attribute2SecItem(NULL((void*)0), &dhBase, source, CKA_BASE0x00000132UL);
2896 if (crv != CKR_OK0x00000000UL) {
2897 return PR_FALSE0;
2898 }
2899 dhSubPrime = sftk_VerifyDH_Prime(&dhPrime, &dhGenerator, PR_TRUE1);
2900 fipsOk = (dhSubPrime) ? PR_TRUE1 : PR_FALSE0;
2901 if (fipsOk && (SECITEM_CompareItemSECITEM_CompareItem_Util(&dhBase, &dhGenerator) != 0)) {
2902 fipsOk = PR_FALSE0;
2903 }
2904
2905 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&dhPrime, PR_FALSE0);
2906 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&dhBase, PR_FALSE0);
2907 return fipsOk;
2908 }
2909 case SFTKFIPSNone:
2910 return PR_FALSE0;
2911 case SFTKFIPSECC:
2912 /* we've already handled the curve selection in the 'getlength'
2913 * function */
2914 return PR_TRUE1;
2915 case SFTKFIPSAEAD: {
2916 if (mech->ulParameterLen == 0) {
2917 /* AEAD ciphers are only in FIPS mode if we are using the
2918 * MESSAGE interface. This takes an empty parameter
2919 * in the init function */
2920 return PR_TRUE1;
2921 }
2922 return PR_FALSE0;
2923 }
2924 case SFTKFIPSRSAPSS: {
2925 /* PSS salt must not be longer than the underlying hash.
2926 * We verify that the underlying hash of the
2927 * parameters matches Hash of the combined hash mechanisms, so
2928 * we don't need to look at the specific PSS mechanism */
2929 CK_RSA_PKCS_PSS_PARAMS *pss = (CK_RSA_PKCS_PSS_PARAMS *)
2930 mech->pParameter;
2931 const SECHashObject *hashObj = NULL((void*)0);
2932 if (mech->ulParameterLen != sizeof(*pss)) {
2933 return PR_FALSE0;
2934 }
2935 /* we use the existing hash utilities to find the length of
2936 * the hash */
2937 hashObj = HASH_GetRawHashObject(sftk_GetHashTypeFromMechanism(
2938 pss->hashAlg));
2939 if (hashObj == NULL((void*)0)) {
2940 return PR_FALSE0;
2941 }
2942 /* cap the salt for legacy keys */
2943 if ((keyLength <= 1024) && (pss->sLen > 63)) {
2944 return PR_FALSE0;
2945 }
2946 /* cap the salt based on the hash */
2947 if (pss->sLen > hashObj->length) {
2948 return PR_FALSE0;
2949 }
2950 return PR_TRUE1;
2951 }
2952 case SFTKFIPSPBKDF2: {
2953 /* from NIST SP 800-132
2954 * PBKDF2 must have the following addition restrictions
2955 * (independent of keysize).
2956 * 1. iteration count must be at least 1000.
2957 * 2. salt must be at least 128 bits (16 bytes).
2958 * 3. password must match the length specified in the SP
2959 */
2960 CK_PKCS5_PBKD2_PARAMS2 *pbkdf2 = (CK_PKCS5_PBKD2_PARAMS2 *)
2961 mech->pParameter;
2962 if (mech->ulParameterLen != sizeof(*pbkdf2)) {
2963 return PR_FALSE0;
2964 }
2965 if (pbkdf2 == NULL((void*)0)) {
2966 return PR_FALSE0;
2967 }
2968 if (pbkdf2->iterations < 1000) {
2969 return PR_FALSE0;
2970 }
2971 if (pbkdf2->ulSaltSourceDataLen < 16) {
2972 return PR_FALSE0;
2973 }
2974 if (pbkdf2->ulPasswordLen < SFTKFIPS_PBKDF2_MIN_PW_LEN) {
2975 return PR_FALSE0;
2976 }
2977 return PR_TRUE1;
2978 }
2979 /* check the hash mechanisms to make sure they themselves are FIPS */
2980 case SFTKFIPSChkHashSp800:
2981 allowCMAC = PR_TRUE1;
2982 /* fallthrough... will pick up allowSmall as well */
2983 case SFTKFIPSChkHash:
2984 allowSmall = PR_TRUE1;
2985 /* fallthrough */
2986 case SFTKFIPSChkHashTls:
2987 if (mech->ulParameterLen < mechInfo->offset + sizeof(CK_ULONG)) {
2988 return PR_FALSE0;
2989 }
2990 return sftk_checkFIPSHash(*(CK_MECHANISM_TYPE *)(((char *)mech->pParameter) + mechInfo->offset),
2991 allowSmall, allowCMAC);
2992 case SFTKFIPSTlsKeyCheck:
2993 if (mech->mechanism != CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256((0x80000000UL | 0x4E534350) + 23)) {
2994 /* unless the mechnism has a built-in hash, check the hash */
2995 if (mech->ulParameterLen < mechInfo->offset + sizeof(CK_ULONG)) {
2996 return PR_FALSE0;
2997 }
2998 if (!sftk_checkFIPSHash(*(CK_MECHANISM_TYPE *)(((char *)mech->pParameter) + mechInfo->offset),
2999 PR_FALSE0, PR_FALSE0)) {
3000 return PR_FALSE0;
3001 }
3002 }
3003 return sftk_checkKeyLength(targetKeyLength, 112, 512, 1);
3004 case SFTKFIPSRSAOAEP: {
3005 CK_RSA_PKCS_OAEP_PARAMS *rsaoaep = (CK_RSA_PKCS_OAEP_PARAMS *)
3006 mech->pParameter;
3007
3008 HASH_HashType hash_msg = sftk_GetHashTypeFromMechanism(rsaoaep->hashAlg);
3009 HASH_HashType hash_pad = sftk_GetHashTypeFromMechanism(rsaoaep->mgf);
3010 /* message hash and mask generation function must be the same */
3011 if (hash_pad != hash_msg)
3012 return PR_FALSE0;
3013
3014 return sftk_checkFIPSHash(rsaoaep->hashAlg, PR_FALSE0, PR_FALSE0);
3015 }
3016 default:
3017 break;
3018 }
3019 /* if we didn't understand the special processing, mark it non-fips */
3020 return PR_FALSE0;
3021}
3022#endif
3023
3024PRBool
3025sftk_operationIsFIPS(SFTKSlot *slot, CK_MECHANISM *mech, CK_ATTRIBUTE_TYPE op,
3026 SFTKObject *source, CK_ULONG targetKeyLength)
3027{
3028#ifndef NSS_HAS_FIPS_INDICATORS
3029 return PR_FALSE0;
3030#else
3031 int i;
3032 CK_FLAGS opFlags;
3033 CK_ULONG keyLength;
3034
3035 /* handle all the quick stuff first */
3036 if (!sftk_isFIPS(slot->slotID)(((slot->slotID) == 3) || ((slot->slotID) >= 101))) {
3037 return PR_FALSE0;
3038 }
3039 if (source && !sftk_hasFIPS(source)) {
3040 return PR_FALSE0;
3041 }
3042 if (mech == NULL((void*)0)) {
3043 return PR_FALSE0;
3044 }
3045
3046 /* now get the calculated values */
3047 opFlags = sftk_AttributeToFlags(op);
3048 if (opFlags == 0) {
3049 return PR_FALSE0;
3050 }
3051 keyLength = sftk_getKeyLength(source);
3052
3053 /* check against our algorithm array */
3054 for (i = 0; i < SFTK_NUMBER_FIPS_ALGORITHMS; i++) {
3055 SFTKFIPSAlgorithmList *mechs = &sftk_fips_mechs[i];
3056 /* if we match the number of records exactly, then we are an
3057 * approved algorithm in the approved mode with an approved key */
3058 if ((mech->mechanism == mechs->type) &&
3059 (opFlags == (mechs->info.flags & opFlags)) &&
3060 sftk_checkKeyLength(keyLength, mechs->info.ulMinKeySize,
3061 mechs->info.ulMaxKeySize, mechs->step) &&
3062 ((targetKeyLength == 0) || (mechs->special == SFTKFIPSTlsKeyCheck) || sftk_checkKeyLength(targetKeyLength, mechs->info.ulMinKeySize, mechs->info.ulMaxKeySize, mechs->step)) &&
3063 ((mechs->special == SFTKFIPSNone) ||
3064 sftk_handleSpecial(slot, mech, mechs, source, keyLength, targetKeyLength))) {
3065 return PR_TRUE1;
3066 }
3067 }
3068 return PR_FALSE0;
3069#endif
3070}
3071
3072void
3073sftk_setFIPS(SFTKObject *obj, PRBool isFIPS)
3074{
3075 if (isFIPS) {
3076 obj->validation_value |= SFTK_VALIDATION_FIPS_FLAG0x00000001L;
3077 } else {
3078 obj->validation_value &= ~SFTK_VALIDATION_FIPS_FLAG0x00000001L;
3079 }
3080}
3081
3082PRBool
3083sftk_hasFIPS(SFTKObject *obj)
3084{
3085 return (obj->validation_value & SFTK_VALIDATION_FIPS_FLAG0x00000001L) ? PR_TRUE1 : PR_FALSE0;
3086}
3087
3088/*
3089 * create the FIPS Validation objects. If the vendor
3090 * doesn't supply an NSS_FIPS_MODULE_ID, at compile time,
3091 * then we assumethis is an unvalidated module.
3092 */
3093CK_RV
3094sftk_CreateValidationObjects(SFTKSlot *slot)
3095{
3096 const char *module_id;
3097 int module_id_len;
3098 CK_RV crv = CKR_OK0x00000000UL;
3099 /* we currently use both vendor specific values and PKCS #11 v3.2
3100 * values for compatibility for a couple more ESR releases. Then we can
3101 * drop the vendor specific ones */
3102 CK_OBJECT_CLASS cko_nss_validation = CKO_NSS_VALIDATION((0x80000000UL | 0x4E534350) + 7);
3103 CK_OBJECT_CLASS cko_validation = CKO_VALIDATION0x0000000aUL;
3104 CK_NSS_VALIDATION_TYPE ckv_fips = CKV_NSS_FIPS_140((0x80000000UL | 0x4E534350) + 1);
3105 CK_FLAGS fipsFlag = SFTK_VALIDATION_FIPS_FLAG0x00000001L;
3106 CK_VALIDATION_TYPE swValidationType = CKV_TYPE_SOFTWARE0x00000001UL;
3107 CK_VALIDATION_AUTHORITY_TYPE nistValidationAuthority =
3108 CKV_AUTHORITY_TYPE_NIST_CMVP0x00000001UL;
3109 CK_UTF8CHAR us[] = { 'U', 'S' };
3110 CK_VERSION fips_version = { 3, 0 }; /* FIPS-140-3 */
3111 CK_ULONG fips_level = 1; /* or 2 if you validated at level 2 */
3112
3113#ifndef NSS_FIPS_MODULE_ID"Generic NSS " "3.132" " Basic ECC" " Beta" " Unvalidated"
3114#define NSS_FIPS_MODULE_ID"Generic NSS " "3.132" " Basic ECC" " Beta" " Unvalidated" "Generic NSS " SOFTOKEN_VERSION"3.132" " Basic ECC" " Beta" " Unvalidated"
3115#endif
3116 module_id = NSS_FIPS_MODULE_ID"Generic NSS " "3.132" " Basic ECC" " Beta" " Unvalidated";
3117 module_id_len = sizeof(NSS_FIPS_MODULE_ID"Generic NSS " "3.132" " Basic ECC" " Beta" " Unvalidated") - 1;
3118 SFTKObject *object;
3119
3120 object = sftk_NewObject(slot); /* fill in the handle later */
3121 if (object == NULL((void*)0)) {
3122 return CKR_HOST_MEMORY0x00000002UL;
3123 }
3124 sftk_setFIPS(object, PR_FALSE0);
3125
3126 crv = sftk_AddAttributeType(object, CKA_CLASS0x00000000UL, &cko_nss_validation,
3127 sizeof(cko_nss_validation));
3128 if (crv != CKR_OK0x00000000UL) {
3129 goto loser;
3130 }
3131 crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_TYPE((0x80000000UL | 0x4E534350) + 36),
3132 &ckv_fips, sizeof(ckv_fips));
3133 if (crv != CKR_OK0x00000000UL) {
3134 goto loser;
3135 }
3136 crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_VERSION((0x80000000UL | 0x4E534350) + 37),
3137 &fips_version, sizeof(fips_version));
3138 if (crv != CKR_OK0x00000000UL) {
3139 goto loser;
3140 }
3141 crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_LEVEL((0x80000000UL | 0x4E534350) + 38),
3142 &fips_level, sizeof(fips_level));
3143 if (crv != CKR_OK0x00000000UL) {
3144 goto loser;
3145 }
3146 crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_MODULE_ID((0x80000000UL | 0x4E534350) + 39),
3147 module_id, module_id_len);
3148 if (crv != CKR_OK0x00000000UL) {
3149 goto loser;
3150 }
3151
3152 object->handle = sftk_getNextHandle(slot);
3153 object->slot = slot;
3154 sftk_AddObject(&slot->moduleObjects, object);
3155 sftk_FreeObject(object);
3156
3157 object = sftk_NewObject(slot); /* fill in the handle later */
3158 if (object == NULL((void*)0)) {
3159 return CKR_HOST_MEMORY0x00000002UL;
3160 }
3161 sftk_setFIPS(object, PR_FALSE0);
3162 crv = sftk_AddAttributeType(object, CKA_CLASS0x00000000UL, &cko_validation,
3163 sizeof(cko_validation));
3164 if (crv != CKR_OK0x00000000UL) {
3165 goto loser;
3166 }
3167 crv = sftk_AddAttributeType(object, CKA_VALIDATION_TYPE0x0000061fUL,
3168 &swValidationType, sizeof(swValidationType));
3169 if (crv != CKR_OK0x00000000UL) {
3170 goto loser;
3171 }
3172 crv = sftk_AddAttributeType(object, CKA_VALIDATION_VERSION0x00000620UL,
3173 &fips_version, sizeof(fips_version));
3174 if (crv != CKR_OK0x00000000UL) {
3175 goto loser;
3176 }
3177 crv = sftk_AddAttributeType(object, CKA_VALIDATION_LEVEL0x00000621UL,
3178 &fips_level, sizeof(fips_level));
3179 if (crv != CKR_OK0x00000000UL) {
3180 goto loser;
3181 }
3182 crv = sftk_AddAttributeType(object, CKA_VALIDATION_MODULE_ID0x00000622UL,
3183 module_id, module_id_len);
3184 if (crv != CKR_OK0x00000000UL) {
3185 goto loser;
3186 }
3187 crv = sftk_AddAttributeType(object, CKA_VALIDATION_FLAG0x00000623UL,
3188 &fipsFlag, sizeof(fipsFlag));
3189 if (crv != CKR_OK0x00000000UL) {
3190 goto loser;
3191 }
3192 crv = sftk_AddAttributeType(object, CKA_VALIDATION_AUTHORITY_TYPE0x00000624UL,
3193 &nistValidationAuthority,
3194 sizeof(nistValidationAuthority));
3195 if (crv != CKR_OK0x00000000UL) {
3196 goto loser;
3197 }
3198 crv = sftk_AddAttributeType(object, CKA_VALIDATION_COUNTRY0x00000625UL, us, sizeof(us));
3199 if (crv != CKR_OK0x00000000UL) {
3200 goto loser;
3201 }
3202 crv = sftk_AddAttributeType(object, CKA_VALIDATION_CERTIFICATE_IDENTIFIER0x00000626UL,
3203 NULL((void*)0), 0);
3204 if (crv != CKR_OK0x00000000UL) {
3205 goto loser;
3206 }
3207 crv = sftk_AddAttributeType(object, CKA_VALIDATION_CERTIFICATE_URI0x00000627UL,
3208 NULL((void*)0), 0);
3209 if (crv != CKR_OK0x00000000UL) {
3210 goto loser;
3211 }
3212 crv = sftk_AddAttributeType(object, CKA_VALIDATION_PROFILE0x00000629UL,
3213 NULL((void*)0), 0);
3214 if (crv != CKR_OK0x00000000UL) {
3215 goto loser;
3216 }
3217 crv = sftk_AddAttributeType(object, CKA_VALIDATION_VENDOR_URI0x00000628UL,
3218 NULL((void*)0), 0);
3219 if (crv != CKR_OK0x00000000UL) {
3220 goto loser;
3221 }
3222 /* future, fill in validation certificate information from a supplied
3223 * pointer to a config file */
3224 object->handle = sftk_getNextHandle(slot);
3225 object->slot = slot;
3226 sftk_AddObject(&slot->moduleObjects, object);
3227loser:
3228 sftk_FreeObject(object);
3229
3230 return crv;
3231}