Bug Summary

File:root/firefox-clang/security/nss/lib/softoken/pkcs11u.c
Warning:line 2076, 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-09-01-224014-2642839-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_Assert(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 // As a safeguard against misuse of the library, ensure we don't
1184 // hand out live objects that somehow land in the free list.
1185 PORT_Assert(object->refCount == 0)((object->refCount == 0) ? ((void)0) : PR_Assert("object->refCount == 0"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 1185
))
;
1186 if (object->refCount == 0) {
1187 object->next = object->prev = NULL((void*)0);
1188 *hasLocks = PR_TRUE1;
1189 return object;
1190 }
1191 }
1192 }
1193 size = isSessionObject ? sizeof(SFTKSessionObject) + hashSize * sizeof(SFTKAttribute *) : sizeof(SFTKTokenObject);
1194
1195 object = (SFTKObject *)PORT_ZAllocPORT_ZAlloc_Util(size);
1196 if (isSessionObject && object) {
1197 ((SFTKSessionObject *)object)->hashSize = hashSize;
1198 }
1199 *hasLocks = PR_FALSE0;
1200 return object;
1201}
1202
1203static void
1204sftk_PutObjectToList(SFTKObject *object, SFTKObjectFreeList *list,
1205 PRBool isSessionObject)
1206{
1207
1208 /* the code below is equivalent to :
1209 * optimizeSpace = isSessionObject ? object->optimizeSpace : PR_FALSE;
1210 * just faster.
1211 */
1212 PRBool optimizeSpace = isSessionObject &&
1213 ((SFTKSessionObject *)object)->optimizeSpace;
1214 if (object->refLock && !optimizeSpace) {
1215 PR_Lock(list->lock);
1216 if (list->count < MAX_OBJECT_LIST_SIZE800) {
1217 object->next = list->head;
1218 list->head = object;
1219 list->count++;
1220 PR_Unlock(list->lock);
1221 return;
1222 }
1223 PR_Unlock(list->lock);
1224 }
1225 if (isSessionObject) {
1226 SFTKSessionObject *so = (SFTKSessionObject *)object;
1227 PR_DestroyLock(so->attributeLock);
1228 so->attributeLock = NULL((void*)0);
1229 }
1230 if (object->refLock) {
1231 PR_DestroyLock(object->refLock);
1232 object->refLock = NULL((void*)0);
1233 }
1234 PORT_FreePORT_Free_Util(object);
1235}
1236
1237static SFTKObject *
1238sftk_freeObjectData(SFTKObject *object)
1239{
1240 SFTKObject *next = object->next;
1241
1242 PORT_FreePORT_Free_Util(object);
1243 return next;
1244}
1245
1246static void
1247sftk_InitFreeList(SFTKObjectFreeList *list)
1248{
1249 if (!list->lock) {
1250 list->lock = PR_NewLock();
1251 }
1252}
1253
1254void
1255sftk_InitFreeLists(void)
1256{
1257 sftk_InitFreeList(&sessionObjectList);
1258 sftk_InitFreeList(&tokenObjectList);
1259}
1260
1261static void
1262sftk_CleanupFreeList(SFTKObjectFreeList *list, PRBool isSessionList)
1263{
1264 SFTKObject *object;
1265
1266 if (!list->lock) {
1267 return;
1268 }
1269 SKIP_AFTER_FORK(PR_Lock(list->lock))PR_Lock(list->lock);
1270 for (object = list->head; object != NULL((void*)0);
1271 object = sftk_freeObjectData(object)) {
1272 PR_DestroyLock(object->refLock);
1273 if (isSessionList) {
1274 PR_DestroyLock(((SFTKSessionObject *)object)->attributeLock);
1275 }
1276 }
1277 list->count = 0;
1278 list->head = NULL((void*)0);
1279 SKIP_AFTER_FORK(PR_Unlock(list->lock))PR_Unlock(list->lock);
1280 SKIP_AFTER_FORK(PR_DestroyLock(list->lock))PR_DestroyLock(list->lock);
1281 list->lock = NULL((void*)0);
1282}
1283
1284void
1285sftk_CleanupFreeLists(void)
1286{
1287 sftk_CleanupFreeList(&sessionObjectList, PR_TRUE1);
1288 sftk_CleanupFreeList(&tokenObjectList, PR_FALSE0);
1289}
1290
1291/*
1292 * Create a new object
1293 */
1294SFTKObject *
1295sftk_NewObject(SFTKSlot *slot)
1296{
1297 SFTKObject *object;
1298 SFTKSessionObject *sessObject;
1299 PRBool hasLocks = PR_FALSE0;
1300 unsigned int i;
1301 unsigned int hashSize = 0;
1302
1303 hashSize = (slot->optimizeSpace) ? SPACE_ATTRIBUTE_HASH_SIZE32 : TIME_ATTRIBUTE_HASH_SIZE32;
1304
1305 object = sftk_GetObjectFromList(&hasLocks, slot->optimizeSpace,
1306 &sessionObjectList, hashSize, PR_TRUE1);
1307 if (object == NULL((void*)0)) {
1308 return NULL((void*)0);
1309 }
1310 sessObject = (SFTKSessionObject *)object;
1311 sessObject->nextAttr = 0;
1312
1313 for (i = 0; i < MAX_OBJS_ATTRS45; i++) {
1314 sessObject->attrList[i].attrib.pValue = NULL((void*)0);
1315 sessObject->attrList[i].freeData = PR_FALSE0;
1316 }
1317 sessObject->optimizeSpace = slot->optimizeSpace;
1318
1319 object->handle = 0;
1320 object->next = object->prev = NULL((void*)0);
1321 object->slot = slot;
1322 /* set up the validation flags */
1323 object->validation_value = 0;
1324 object->validation_attribute.next = NULL((void*)0);
1325 object->validation_attribute.prev = NULL((void*)0);
1326 object->validation_attribute.freeAttr = PR_FALSE0;
1327 object->validation_attribute.freeData = PR_FALSE0;
1328 object->validation_attribute.handle = CKA_OBJECT_VALIDATION_FLAGS0x0000061eUL;
1329 object->validation_attribute.attrib.type = CKA_OBJECT_VALIDATION_FLAGS0x0000061eUL;
1330 object->validation_attribute.attrib.pValue = &object->validation_value;
1331 object->validation_attribute.attrib.ulValueLen = sizeof(object->validation_value);
1332 /* initialize the FIPS flag properly */
1333 sftk_setFIPS(object, sftk_isFIPS(slot->slotID)(((slot->slotID) == 3) || ((slot->slotID) >= 101)));
1334 object->source = SFTK_SOURCE_DEFAULT;
1335
1336 object->refCount = 1;
1337 object->type = SFTK_SESSION_OBJECT_TYPE0xFFFFFFFFU;
1338 sessObject->sessionList.next = NULL((void*)0);
1339 sessObject->sessionList.prev = NULL((void*)0);
1340 sessObject->sessionList.parent = object;
1341 sessObject->session = NULL((void*)0);
1342 sessObject->wasDerived = PR_FALSE0;
1343 if (!hasLocks)
1344 object->refLock = PR_NewLock();
1345 if (object->refLock == NULL((void*)0)) {
1346 PORT_FreePORT_Free_Util(object);
1347 return NULL((void*)0);
1348 }
1349 if (!hasLocks)
1350 sessObject->attributeLock = PR_NewLock();
1351 if (sessObject->attributeLock == NULL((void*)0)) {
1352 PR_DestroyLock(object->refLock);
1353 PORT_FreePORT_Free_Util(object);
1354 return NULL((void*)0);
1355 }
1356 for (i = 0; i < sessObject->hashSize; i++) {
1357 sessObject->head[i] = NULL((void*)0);
1358 }
1359 object->objectInfo = NULL((void*)0);
1360 object->infoFree = NULL((void*)0);
1361 return object;
1362}
1363
1364static CK_RV
1365sftk_DestroySessionObjectData(SFTKSessionObject *so)
1366{
1367 int i;
1368
1369 for (i = 0; i < MAX_OBJS_ATTRS45; i++) {
1370 unsigned char *value = so->attrList[i].attrib.pValue;
1371 if (value) {
1372 PORT_Memsetmemset(value, 0, so->attrList[i].attrib.ulValueLen);
1373 if (so->attrList[i].freeData) {
1374 PORT_FreePORT_Free_Util(value);
1375 }
1376 so->attrList[i].attrib.pValue = NULL((void*)0);
1377 so->attrList[i].freeData = PR_FALSE0;
1378 }
1379 }
1380 /* PR_DestroyLock(so->attributeLock);*/
1381 return CKR_OK0x00000000UL;
1382}
1383
1384/*
1385 * free all the data associated with an object. Object reference count must
1386 * be 'zero'.
1387 */
1388static CK_RV
1389sftk_DestroyObject(SFTKObject *object)
1390{
1391 CK_RV crv = CKR_OK0x00000000UL;
1392 SFTKSessionObject *so = sftk_narrowToSessionObject(object);
1393 SFTKTokenObject *to = sftk_narrowToTokenObject(object);
1394
1395 PORT_Assert(object->refCount == 0)((object->refCount == 0) ? ((void)0) : PR_Assert("object->refCount == 0"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 1395
))
;
1396
1397 /* delete the database value */
1398 if (to) {
1399 if (to->dbKey.data) {
1400 PORT_FreePORT_Free_Util(to->dbKey.data);
1401 to->dbKey.data = NULL((void*)0);
1402 }
1403 }
1404 if (so) {
1405 sftk_DestroySessionObjectData(so);
1406 }
1407 if (object->objectInfo) {
1408 (*object->infoFree)(object->objectInfo);
1409 object->objectInfo = NULL((void*)0);
1410 object->infoFree = NULL((void*)0);
1411 }
1412 if (so) {
1413 sftk_PutObjectToList(object, &sessionObjectList, PR_TRUE1);
1414 } else {
1415 sftk_PutObjectToList(object, &tokenObjectList, PR_FALSE0);
1416 }
1417 return crv;
1418}
1419
1420void
1421sftk_ReferenceObject(SFTKObject *object)
1422{
1423 PR_Lock(object->refLock);
1424 PORT_Assert(object->refCount > 0)((object->refCount > 0) ? ((void)0) : PR_Assert("object->refCount > 0"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 1424
))
;
1425 object->refCount++;
1426 PR_Unlock(object->refLock);
1427}
1428
1429static SFTKObject *
1430sftk_ObjectFromHandleOnSlot(CK_OBJECT_HANDLE handle, SFTKSlot *slot)
1431{
1432 SFTKObject *object;
1433 PRUint32 index = sftk_hash(handle, slot->sessObjHashSize)((PRUint32)((handle) * 1791398085) & (slot->sessObjHashSize
- 1))
;
1434
1435 if (sftk_isToken(handle)(((handle) & 0x80000000L) == 0x80000000L)) {
1436 return sftk_NewTokenObject(slot, NULL((void*)0), handle);
1437 }
1438
1439 PR_Lock(slot->objectLock);
1440 sftkqueue_find2(object, handle, index, slot->sessObjHashTable)for ((object) = (slot->sessObjHashTable)[index]; (object) !=
((void*)0); (object) = (object)->next) { if ((object)->
handle == (handle)) { break; } }
;
1441 if (object) {
1442 sftk_ReferenceObject(object);
1443 }
1444 PR_Unlock(slot->objectLock);
1445
1446 return (object);
1447}
1448/*
1449 * look up and object structure from a handle. OBJECT_Handles only make
1450 * sense in terms of a given session. make a reference to that object
1451 * structure returned.
1452 */
1453SFTKObject *
1454sftk_ObjectFromHandle(CK_OBJECT_HANDLE handle, SFTKSession *session)
1455{
1456 SFTKSlot *slot = sftk_SlotFromSession(session)((session)->slot);
1457
1458 return sftk_ObjectFromHandleOnSlot(handle, slot);
1459}
1460
1461/*
1462 * release a reference to an object handle
1463 */
1464SFTKFreeStatus
1465sftk_FreeObject(SFTKObject *object)
1466{
1467 PRBool destroy = PR_FALSE0;
1468 CK_RV crv;
1469
1470 PR_Lock(object->refLock);
1471 if (object->refCount == 1)
1472 destroy = PR_TRUE1;
1473 object->refCount--;
1474 PR_Unlock(object->refLock);
1475
1476 if (destroy) {
1477 crv = sftk_DestroyObject(object);
1478 if (crv != CKR_OK0x00000000UL) {
1479 return SFTK_DestroyFailure;
1480 }
1481 return SFTK_Destroyed;
1482 }
1483 return SFTK_Busy;
1484}
1485
1486/* find the next available object handle that isn't currently in use */
1487/* NOTE: This function could loop forever if we've exhausted all
1488 * 3^31-1 handles. This is highly unlikely (NSS has been running for
1489 * decades with this code) uless we start increasing the size of the
1490 * SFTK_TOKEN_MASK (which is just the high bit currently). */
1491CK_OBJECT_HANDLE
1492sftk_getNextHandle(SFTKSlot *slot)
1493{
1494 CK_OBJECT_HANDLE handle;
1495 SFTKObject *duplicateObject = NULL((void*)0);
1496 do {
1497 PRUint32 wrappedAround;
1498
1499 duplicateObject = NULL((void*)0);
1500 PR_Lock(slot->objectLock);
1501 wrappedAround = slot->sessionObjectHandleCount & SFTK_TOKEN_MASK0x80000000L;
1502 handle = slot->sessionObjectHandleCount & ~SFTK_TOKEN_MASK0x80000000L;
1503 if (!handle) /* don't allow zero handle */
1504 handle = NSC_MIN_SESSION_OBJECT_HANDLE1U;
1505 slot->sessionObjectHandleCount = (handle + 1U) | wrappedAround;
1506 /* Is there already a session object with this handle? */
1507 if (wrappedAround) {
1508 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; } }
1509 slot->sessObjHashSize)for ((duplicateObject) = (slot->sessObjHashTable)[((PRUint32
)((handle) * 1791398085) & (slot->sessObjHashSize - 1)
)]; (duplicateObject) != ((void*)0); (duplicateObject) = (duplicateObject
)->next) { if ((duplicateObject)->handle == (handle)) {
break; } }
;
1510 }
1511 PR_Unlock(slot->objectLock);
1512 } while (duplicateObject != NULL((void*)0));
1513 return handle;
1514}
1515
1516/*
1517 * add an object to a slot and session queue. These two functions
1518 * adopt the object.
1519 */
1520void
1521sftk_AddSlotObject(SFTKSlot *slot, SFTKObject *object)
1522{
1523 PRUint32 index = sftk_hash(object->handle, slot->sessObjHashSize)((PRUint32)((object->handle) * 1791398085) & (slot->
sessObjHashSize - 1))
;
1524 sftkqueue_init_element(object)(object)->prev = ((void*)0);;
1525 PR_Lock(slot->objectLock);
1526 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); }
;
1527 PR_Unlock(slot->objectLock);
1528}
1529
1530void
1531sftk_AddObject(SFTKSession *session, SFTKObject *object)
1532{
1533 SFTKSlot *slot = sftk_SlotFromSession(session)((session)->slot);
1534 SFTKSessionObject *so = sftk_narrowToSessionObject(object);
1535
1536 if (so) {
1537 PR_Lock(session->objectLock);
1538 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); }
;
1539 so->session = session;
1540 PR_Unlock(session->objectLock);
1541 }
1542 sftk_AddSlotObject(slot, object);
1543 sftk_ReferenceObject(object);
1544}
1545
1546/*
1547 * delete an object from a slot and session queue
1548 */
1549CK_RV
1550sftk_DeleteObject(SFTKSession *session, SFTKObject *object)
1551{
1552 SFTKSlot *slot = sftk_SlotFromSession(session)((session)->slot);
1553 SFTKSessionObject *so = sftk_narrowToSessionObject(object);
1554 CK_RV crv = CKR_OK0x00000000UL;
1555 PRUint32 index = sftk_hash(object->handle, slot->sessObjHashSize)((PRUint32)((object->handle) * 1791398085) & (slot->
sessObjHashSize - 1))
;
1556
1557 /* Handle Token case */
1558 if (so && so->session) {
1559 /* Atomically claim the right to remove this object. Two threads
1560 * can race here via NSC_DestroyObject after both succeed in
1561 * sftk_ObjectFromHandle; without the claim each would unlink
1562 * the queue entry and drop the queue's reference, leading to a
1563 * double sftk_FreeObject (and on the second pass, a use-after-
1564 * free when sftk_FreeObject reads object->refLock). */
1565 PRBool ownsRemove = PR_FALSE0;
1566 PR_Lock(slot->objectLock);
1567 if (object->next || object->prev ||
1568 slot->sessObjHashTable[index] == object) {
1569 sftkqueue_delete2(object, object->handle, index,if ((object)->next) (object)->next->prev = (object)->
prev; if ((object)->prev) (object)->prev->next = (object
)->next; else (slot->sessObjHashTable)[index] = ((object
)->next);
1570 slot->sessObjHashTable)if ((object)->next) (object)->next->prev = (object)->
prev; if ((object)->prev) (object)->prev->next = (object
)->next; else (slot->sessObjHashTable)[index] = ((object
)->next);
;
1571 /* sftkqueue_delete2 patches the neighbour pointers but
1572 * leaves object->next/prev pointing at their old neighbours.
1573 * Clear them inside the slot lock so a racing thread that
1574 * acquires the lock next sees an empty-looking object and
1575 * doesn't re-claim ownership, which would lead to a double
1576 * sftk_FreeObject of the queue's reference. */
1577 sftkqueue_clear_deleted_element(object)(object)->next = ((void*)0); (object)->prev = ((void*)0
);
;
1578 ownsRemove = PR_TRUE1;
1579 }
1580 PR_Unlock(slot->objectLock);
1581
1582 if (ownsRemove) {
1583 session = so->session;
1584 PR_Lock(session->objectLock);
1585 sftkqueue_delete(&so->sessionList, 0, 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
(session->objects)[((PRUint32)((0) * 1791398085) & (0
- 1))] = ((&so->sessionList)->next); (&so->
sessionList)->next = ((void*)0); (&so->sessionList)
->prev = ((void*)0);
;
1586 PR_Unlock(session->objectLock);
1587 sftk_FreeObject(object); /* drop the queue's reference */
1588 }
1589 } else {
1590 SFTKDBHandle *handle = sftk_getDBForTokenObject(slot, object->handle);
1591#ifdef DEBUG1
1592 SFTKTokenObject *to = sftk_narrowToTokenObject(object);
1593 PORT_Assert(to)((to) ? ((void)0) : PR_Assert("to", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 1593))
;
1594#endif
1595 crv = sftkdb_DestroyObject(handle, object->handle, object->objclass);
1596 sftk_freeDB(handle);
1597 }
1598 return crv;
1599}
1600
1601/*
1602 * Token objects don't explicitly store their attributes, so we need to know
1603 * what attributes make up a particular token object before we can copy it.
1604 * below are the tables by object type.
1605 */
1606static const CK_ATTRIBUTE_TYPE commonAttrs[] = {
1607 CKA_CLASS0x00000000UL, CKA_TOKEN0x00000001UL, CKA_PRIVATE0x00000002UL, CKA_LABEL0x00000003UL, CKA_MODIFIABLE0x00000170UL
1608};
1609static const CK_ULONG commonAttrsCount =
1610 sizeof(commonAttrs) / sizeof(commonAttrs[0]);
1611
1612static const CK_ATTRIBUTE_TYPE commonKeyAttrs[] = {
1613 CKA_ID0x00000102UL, CKA_START_DATE0x00000110UL, CKA_END_DATE0x00000111UL, CKA_DERIVE0x0000010CUL, CKA_LOCAL0x00000163UL, CKA_KEY_TYPE0x00000100UL
1614};
1615static const CK_ULONG commonKeyAttrsCount =
1616 sizeof(commonKeyAttrs) / sizeof(commonKeyAttrs[0]);
1617
1618static const CK_ATTRIBUTE_TYPE secretKeyAttrs[] = {
1619 CKA_SENSITIVE0x00000103UL, CKA_EXTRACTABLE0x00000162UL, CKA_ENCRYPT0x00000104UL, CKA_DECRYPT0x00000105UL, CKA_SIGN0x00000108UL,
1620 CKA_VERIFY0x0000010AUL, CKA_WRAP0x00000106UL, CKA_UNWRAP0x00000107UL, CKA_VALUE0x00000011UL
1621};
1622static const CK_ULONG secretKeyAttrsCount =
1623 sizeof(secretKeyAttrs) / sizeof(secretKeyAttrs[0]);
1624
1625static const CK_ATTRIBUTE_TYPE commonPubKeyAttrs[] = {
1626 CKA_ENCRYPT0x00000104UL, CKA_VERIFY0x0000010AUL, CKA_VERIFY_RECOVER0x0000010BUL, CKA_WRAP0x00000106UL, CKA_SUBJECT0x00000101UL
1627};
1628static const CK_ULONG commonPubKeyAttrsCount =
1629 sizeof(commonPubKeyAttrs) / sizeof(commonPubKeyAttrs[0]);
1630
1631static const CK_ATTRIBUTE_TYPE rsaPubKeyAttrs[] = {
1632 CKA_MODULUS0x00000120UL, CKA_PUBLIC_EXPONENT0x00000122UL
1633};
1634static const CK_ULONG rsaPubKeyAttrsCount =
1635 sizeof(rsaPubKeyAttrs) / sizeof(rsaPubKeyAttrs[0]);
1636
1637static const CK_ATTRIBUTE_TYPE dsaPubKeyAttrs[] = {
1638 CKA_SUBPRIME0x00000131UL, CKA_PRIME0x00000130UL, CKA_BASE0x00000132UL, CKA_VALUE0x00000011UL
1639};
1640static const CK_ULONG dsaPubKeyAttrsCount =
1641 sizeof(dsaPubKeyAttrs) / sizeof(dsaPubKeyAttrs[0]);
1642
1643static const CK_ATTRIBUTE_TYPE dhPubKeyAttrs[] = {
1644 CKA_PRIME0x00000130UL, CKA_BASE0x00000132UL, CKA_VALUE0x00000011UL
1645};
1646static const CK_ULONG dhPubKeyAttrsCount =
1647 sizeof(dhPubKeyAttrs) / sizeof(dhPubKeyAttrs[0]);
1648static const CK_ATTRIBUTE_TYPE ecPubKeyAttrs[] = {
1649 CKA_EC_PARAMS0x00000180UL, CKA_EC_POINT0x00000181UL
1650};
1651static const CK_ULONG ecPubKeyAttrsCount =
1652 sizeof(ecPubKeyAttrs) / sizeof(ecPubKeyAttrs[0]);
1653
1654static const CK_ATTRIBUTE_TYPE mldsaPubKeyAttrs[] = {
1655 CKA_PARAMETER_SET0x0000061dUL, CKA_VALUE0x00000011UL
1656};
1657static const CK_ULONG mldsaPubKeyAttrsCount = PR_ARRAY_SIZE(mldsaPubKeyAttrs)(sizeof(mldsaPubKeyAttrs) / sizeof((mldsaPubKeyAttrs)[0]));
1658
1659/* the vendor ML-KEM key types carry CKA_NSS_PARAMETER_SET rather than
1660 * CKA_PARAMETER_SET; list both and let the missing one be skipped */
1661static const CK_ATTRIBUTE_TYPE mlkemPubKeyAttrs[] = {
1662 CKA_PARAMETER_SET0x0000061dUL, CKA_NSS_PARAMETER_SET((0x80000000UL | 0x4E534350) + 40), CKA_VALUE0x00000011UL
1663};
1664static const CK_ULONG mlkemPubKeyAttrsCount = PR_ARRAY_SIZE(mlkemPubKeyAttrs)(sizeof(mlkemPubKeyAttrs) / sizeof((mlkemPubKeyAttrs)[0]));
1665
1666static const CK_ATTRIBUTE_TYPE commonPrivKeyAttrs[] = {
1667 CKA_DECRYPT0x00000105UL, CKA_SIGN0x00000108UL, CKA_SIGN_RECOVER0x00000109UL, CKA_UNWRAP0x00000107UL, CKA_SUBJECT0x00000101UL,
1668 CKA_SENSITIVE0x00000103UL, CKA_EXTRACTABLE0x00000162UL, CKA_NSS_DB0xD5A0DB00L, CKA_PUBLIC_KEY_INFO0x00000129UL
1669};
1670static const CK_ULONG commonPrivKeyAttrsCount =
1671 sizeof(commonPrivKeyAttrs) / sizeof(commonPrivKeyAttrs[0]);
1672
1673static const CK_ATTRIBUTE_TYPE rsaPrivKeyAttrs[] = {
1674 CKA_MODULUS0x00000120UL, CKA_PUBLIC_EXPONENT0x00000122UL, CKA_PRIVATE_EXPONENT0x00000123UL,
1675 CKA_PRIME_10x00000124UL, CKA_PRIME_20x00000125UL, CKA_EXPONENT_10x00000126UL, CKA_EXPONENT_20x00000127UL, CKA_COEFFICIENT0x00000128UL
1676};
1677static const CK_ULONG rsaPrivKeyAttrsCount =
1678 sizeof(rsaPrivKeyAttrs) / sizeof(rsaPrivKeyAttrs[0]);
1679
1680static const CK_ATTRIBUTE_TYPE dsaPrivKeyAttrs[] = {
1681 CKA_SUBPRIME0x00000131UL, CKA_PRIME0x00000130UL, CKA_BASE0x00000132UL, CKA_VALUE0x00000011UL
1682};
1683static const CK_ULONG dsaPrivKeyAttrsCount =
1684 sizeof(dsaPrivKeyAttrs) / sizeof(dsaPrivKeyAttrs[0]);
1685
1686static const CK_ATTRIBUTE_TYPE dhPrivKeyAttrs[] = {
1687 CKA_PRIME0x00000130UL, CKA_BASE0x00000132UL, CKA_VALUE0x00000011UL
1688};
1689static const CK_ULONG dhPrivKeyAttrsCount =
1690 sizeof(dhPrivKeyAttrs) / sizeof(dhPrivKeyAttrs[0]);
1691static const CK_ATTRIBUTE_TYPE ecPrivKeyAttrs[] = {
1692 CKA_EC_PARAMS0x00000180UL, CKA_VALUE0x00000011UL
1693};
1694static const CK_ULONG ecPrivKeyAttrsCount =
1695 sizeof(ecPrivKeyAttrs) / sizeof(ecPrivKeyAttrs[0]);
1696
1697static const CK_ATTRIBUTE_TYPE mldsaPrivKeyAttrs[] = {
1698 CKA_PARAMETER_SET0x0000061dUL, CKA_VALUE0x00000011UL, CKA_SEED0x00000637UL
1699};
1700static const CK_ULONG mldsaPrivKeyAttrsCount = PR_ARRAY_SIZE(mldsaPrivKeyAttrs)(sizeof(mldsaPrivKeyAttrs) / sizeof((mldsaPrivKeyAttrs)[0]));
1701
1702static const CK_ATTRIBUTE_TYPE mlkemPrivKeyAttrs[] = {
1703 CKA_PARAMETER_SET0x0000061dUL, CKA_NSS_PARAMETER_SET((0x80000000UL | 0x4E534350) + 40), CKA_VALUE0x00000011UL, CKA_SEED0x00000637UL
1704};
1705static const CK_ULONG mlkemPrivKeyAttrsCount = PR_ARRAY_SIZE(mlkemPrivKeyAttrs)(sizeof(mlkemPrivKeyAttrs) / sizeof((mlkemPrivKeyAttrs)[0]));
1706
1707static const CK_ATTRIBUTE_TYPE certAttrs[] = {
1708 CKA_CERTIFICATE_TYPE0x00000080UL, CKA_VALUE0x00000011UL, CKA_SUBJECT0x00000101UL, CKA_ISSUER0x00000081UL, CKA_SERIAL_NUMBER0x00000082UL
1709};
1710static const CK_ULONG certAttrsCount =
1711 sizeof(certAttrs) / sizeof(certAttrs[0]);
1712
1713static const CK_ATTRIBUTE_TYPE nssTrustAttrs[] = {
1714 CKA_ISSUER0x00000081UL, CKA_SERIAL_NUMBER0x00000082UL, CKA_NSS_CERT_SHA1_HASH(((0x80000000UL | 0x4E534350) + 0x2000) + 100),
1715 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),
1716 CKA_NSS_TRUST_EMAIL_PROTECTION(((0x80000000UL | 0x4E534350) + 0x2000) + 11), CKA_NSS_TRUST_CODE_SIGNING(((0x80000000UL | 0x4E534350) + 0x2000) + 10),
1717 CKA_NSS_TRUST_STEP_UP_APPROVED(((0x80000000UL | 0x4E534350) + 0x2000) + 16)
1718};
1719static const CK_ULONG nssTrustAttrsCount =
1720 sizeof(nssTrustAttrs) / sizeof(nssTrustAttrs[0]);
1721
1722static const CK_ATTRIBUTE_TYPE trustAttrs[] = {
1723 CKA_ISSUER0x00000081UL, CKA_SERIAL_NUMBER0x00000082UL, CKA_HASH_OF_CERTIFICATE0x00000635UL,
1724 CKA_NAME_HASH_ALGORITHM0x0000008cUL, CKA_PKCS_TRUST_SERVER_AUTH0x0000062cUL,
1725 CKA_PKCS_TRUST_CLIENT_AUTH0x0000062dUL, CKA_PKCS_TRUST_EMAIL_PROTECTION0x0000062fUL,
1726 CKA_PKCS_TRUST_CODE_SIGNING0x0000062eUL
1727};
1728static const CK_ULONG trustAttrsCount =
1729 sizeof(trustAttrs) / sizeof(trustAttrs[0]);
1730
1731static const CK_ATTRIBUTE_TYPE smimeAttrs[] = {
1732 CKA_SUBJECT0x00000101UL, CKA_NSS_EMAIL((0x80000000UL | 0x4E534350) + 2), CKA_NSS_SMIME_TIMESTAMP((0x80000000UL | 0x4E534350) + 4), CKA_VALUE0x00000011UL
1733};
1734static const CK_ULONG smimeAttrsCount =
1735 sizeof(smimeAttrs) / sizeof(smimeAttrs[0]);
1736
1737static const CK_ATTRIBUTE_TYPE crlAttrs[] = {
1738 CKA_SUBJECT0x00000101UL, CKA_VALUE0x00000011UL, CKA_NSS_URL((0x80000000UL | 0x4E534350) + 1), CKA_NSS_KRL((0x80000000UL | 0x4E534350) + 8)
1739};
1740static const CK_ULONG crlAttrsCount =
1741 sizeof(crlAttrs) / sizeof(crlAttrs[0]);
1742
1743/* copy an object based on it's table */
1744CK_RV
1745stfk_CopyTokenAttributes(SFTKObject *destObject, SFTKTokenObject *src_to,
1746 const CK_ATTRIBUTE_TYPE *attrArray, CK_ULONG attrCount)
1747{
1748 SFTKAttribute *attribute;
1749 SFTKAttribute *newAttribute;
1750 CK_RV crv = CKR_OK0x00000000UL;
1751 unsigned int i;
1752
1753 for (i = 0; i < attrCount; i++) {
1754 if (!sftk_hasAttribute(destObject, attrArray[i])) {
1755 attribute = sftk_FindAttribute(&src_to->obj, attrArray[i]);
1756 if (!attribute) {
1757 continue; /* return CKR_ATTRIBUTE_VALUE_INVALID; */
1758 }
1759 /* we need to copy the attribute since each attribute
1760 * only has one set of link list pointers */
1761 newAttribute = sftk_NewAttribute(destObject,
1762 sftk_attr_expand(&attribute->attrib)(&attribute->attrib)->type, (&attribute->attrib
)->pValue, (&attribute->attrib)->ulValueLen
);
1763 sftk_FreeAttribute(attribute); /* free the old attribute */
1764 if (!newAttribute) {
1765 return CKR_HOST_MEMORY0x00000002UL;
1766 }
1767 sftk_AddAttribute(destObject, newAttribute);
1768 }
1769 }
1770 return crv;
1771}
1772
1773CK_RV
1774stfk_CopyTokenPrivateKey(SFTKObject *destObject, SFTKTokenObject *src_to)
1775{
1776 CK_RV crv;
1777 CK_KEY_TYPE key_type;
1778 SFTKAttribute *attribute;
1779
1780 /* copy the common attributes for all keys first */
1781 crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs,
1782 commonKeyAttrsCount);
1783 if (crv != CKR_OK0x00000000UL) {
1784 goto fail;
1785 }
1786 /* copy the common attributes for all private keys next */
1787 crv = stfk_CopyTokenAttributes(destObject, src_to, commonPrivKeyAttrs,
1788 commonPrivKeyAttrsCount);
1789 if (crv != CKR_OK0x00000000UL) {
1790 goto fail;
1791 }
1792 attribute = sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE0x00000100UL);
1793 PORT_Assert(attribute)((attribute) ? ((void)0) : PR_Assert("attribute", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 1793))
; /* if it wasn't here, ww should have failed
1794 * copying the common attributes */
1795 if (!attribute) {
1796 /* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but
1797 * the fact is, the only reason we couldn't get the attribute would
1798 * be a memory error or database error (an error in the 'device').
1799 * if we have a database error code, we could return it here */
1800 crv = CKR_DEVICE_ERROR0x00000030UL;
1801 goto fail;
1802 }
1803 key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue;
1804 sftk_FreeAttribute(attribute);
1805
1806 /* finally copy the attributes for various private key types */
1807 switch (key_type) {
1808 case CKK_RSA0x00000000UL:
1809 crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPrivKeyAttrs,
1810 rsaPrivKeyAttrsCount);
1811 break;
1812 case CKK_DSA0x00000001UL:
1813 crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPrivKeyAttrs,
1814 dsaPrivKeyAttrsCount);
1815 break;
1816 case CKK_ML_DSA0x0000004aUL:
1817 crv = stfk_CopyTokenAttributes(destObject, src_to, mldsaPrivKeyAttrs,
1818 mldsaPrivKeyAttrsCount);
1819 break;
1820#ifndef NSS_DISABLE_KYBER
1821 case CKK_NSS_KYBER((0x80000000UL | 0x4E534350) + 5):
1822#endif
1823 case CKK_NSS_ML_KEM((0x80000000UL | 0x4E534350) + 6):
1824 case CKK_ML_KEM0x00000049UL:
1825 crv = stfk_CopyTokenAttributes(destObject, src_to, mlkemPrivKeyAttrs,
1826 mlkemPrivKeyAttrsCount);
1827 break;
1828 case CKK_DH0x00000002UL:
1829 crv = stfk_CopyTokenAttributes(destObject, src_to, dhPrivKeyAttrs,
1830 dhPrivKeyAttrsCount);
1831 break;
1832 case CKK_EC0x00000003UL:
1833 crv = stfk_CopyTokenAttributes(destObject, src_to, ecPrivKeyAttrs,
1834 ecPrivKeyAttrsCount);
1835 break;
1836 default:
1837 crv = CKR_DEVICE_ERROR0x00000030UL; /* shouldn't happen unless we store more types
1838 * of token keys into our database. */
1839 }
1840fail:
1841 return crv;
1842}
1843
1844CK_RV
1845stfk_CopyTokenPublicKey(SFTKObject *destObject, SFTKTokenObject *src_to)
1846{
1847 CK_RV crv;
1848 CK_KEY_TYPE key_type;
1849 SFTKAttribute *attribute;
1850
1851 /* copy the common attributes for all keys first */
1852 crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs,
1853 commonKeyAttrsCount);
1854 if (crv != CKR_OK0x00000000UL) {
1855 goto fail;
1856 }
1857
1858 /* copy the common attributes for all public keys next */
1859 crv = stfk_CopyTokenAttributes(destObject, src_to, commonPubKeyAttrs,
1860 commonPubKeyAttrsCount);
1861 if (crv != CKR_OK0x00000000UL) {
1862 goto fail;
1863 }
1864 attribute = sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE0x00000100UL);
1865 PORT_Assert(attribute)((attribute) ? ((void)0) : PR_Assert("attribute", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 1865))
; /* if it wasn't here, ww should have failed
1866 * copying the common attributes */
1867 if (!attribute) {
1868 /* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but
1869 * the fact is, the only reason we couldn't get the attribute would
1870 * be a memory error or database error (an error in the 'device').
1871 * if we have a database error code, we could return it here */
1872 crv = CKR_DEVICE_ERROR0x00000030UL;
1873 goto fail;
1874 }
1875 key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue;
1876 sftk_FreeAttribute(attribute);
1877
1878 /* finally copy the attributes for various public key types */
1879 switch (key_type) {
1880 case CKK_RSA0x00000000UL:
1881 crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPubKeyAttrs,
1882 rsaPubKeyAttrsCount);
1883 break;
1884 case CKK_DSA0x00000001UL:
1885 crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPubKeyAttrs,
1886 dsaPubKeyAttrsCount);
1887 break;
1888 case CKK_ML_DSA0x0000004aUL:
1889 crv = stfk_CopyTokenAttributes(destObject, src_to, mldsaPubKeyAttrs,
1890 mldsaPubKeyAttrsCount);
1891 break;
1892#ifndef NSS_DISABLE_KYBER
1893 case CKK_NSS_KYBER((0x80000000UL | 0x4E534350) + 5):
1894#endif
1895 case CKK_NSS_ML_KEM((0x80000000UL | 0x4E534350) + 6):
1896 case CKK_ML_KEM0x00000049UL:
1897 crv = stfk_CopyTokenAttributes(destObject, src_to, mlkemPubKeyAttrs,
1898 mlkemPubKeyAttrsCount);
1899 break;
1900 case CKK_DH0x00000002UL:
1901 crv = stfk_CopyTokenAttributes(destObject, src_to, dhPubKeyAttrs,
1902 dhPubKeyAttrsCount);
1903 break;
1904 case CKK_EC0x00000003UL:
1905 crv = stfk_CopyTokenAttributes(destObject, src_to, ecPubKeyAttrs,
1906 ecPubKeyAttrsCount);
1907 break;
1908 default:
1909 crv = CKR_DEVICE_ERROR0x00000030UL; /* shouldn't happen unless we store more types
1910 * of token keys into our database. */
1911 }
1912fail:
1913 return crv;
1914}
1915CK_RV
1916stfk_CopyTokenSecretKey(SFTKObject *destObject, SFTKTokenObject *src_to)
1917{
1918 CK_RV crv;
1919 crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs,
1920 commonKeyAttrsCount);
1921 if (crv != CKR_OK0x00000000UL) {
1922 goto fail;
1923 }
1924 crv = stfk_CopyTokenAttributes(destObject, src_to, secretKeyAttrs,
1925 secretKeyAttrsCount);
1926fail:
1927 return crv;
1928}
1929
1930/*
1931 * Copy a token object. We need to explicitly copy the relevant
1932 * attributes since token objects don't store those attributes in
1933 * the token itself.
1934 */
1935CK_RV
1936sftk_CopyTokenObject(SFTKObject *destObject, SFTKObject *srcObject)
1937{
1938 SFTKTokenObject *src_to = sftk_narrowToTokenObject(srcObject);
1939 CK_RV crv;
1940
1941 PORT_Assert(src_to)((src_to) ? ((void)0) : PR_Assert("src_to", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 1941))
;
1942 if (src_to == NULL((void*)0)) {
1943 return CKR_DEVICE_ERROR0x00000030UL; /* internal state inconsistant */
1944 }
1945
1946 crv = stfk_CopyTokenAttributes(destObject, src_to, commonAttrs,
1947 commonAttrsCount);
1948 if (crv != CKR_OK0x00000000UL) {
1949 goto fail;
1950 }
1951 switch (src_to->obj.objclass) {
1952 case CKO_CERTIFICATE0x00000001UL:
1953 crv = stfk_CopyTokenAttributes(destObject, src_to, certAttrs,
1954 certAttrsCount);
1955 break;
1956 case CKO_NSS_TRUST((0x80000000UL | 0x4E534350) + 3):
1957 crv = stfk_CopyTokenAttributes(destObject, src_to, nssTrustAttrs,
1958 nssTrustAttrsCount);
1959 break;
1960 case CKO_TRUST0x0000000bUL:
1961 crv = stfk_CopyTokenAttributes(destObject, src_to, trustAttrs,
1962 trustAttrsCount);
1963 break;
1964 case CKO_NSS_SMIME((0x80000000UL | 0x4E534350) + 2):
1965 crv = stfk_CopyTokenAttributes(destObject, src_to, smimeAttrs,
1966 smimeAttrsCount);
1967 break;
1968 case CKO_NSS_CRL((0x80000000UL | 0x4E534350) + 1):
1969 crv = stfk_CopyTokenAttributes(destObject, src_to, crlAttrs,
1970 crlAttrsCount);
1971 break;
1972 case CKO_PRIVATE_KEY0x00000003UL:
1973 crv = stfk_CopyTokenPrivateKey(destObject, src_to);
1974 break;
1975 case CKO_PUBLIC_KEY0x00000002UL:
1976 crv = stfk_CopyTokenPublicKey(destObject, src_to);
1977 break;
1978 case CKO_SECRET_KEY0x00000004UL:
1979 crv = stfk_CopyTokenSecretKey(destObject, src_to);
1980 break;
1981 default:
1982 crv = CKR_DEVICE_ERROR0x00000030UL; /* shouldn't happen unless we store more types
1983 * of token keys into our database. */
1984 }
1985fail:
1986 return crv;
1987}
1988
1989/*
1990 * copy the attributes from one object to another. Don't overwrite existing
1991 * attributes. NOTE: This is a pretty expensive operation since it
1992 * grabs the attribute locks for the src object for a *long* time.
1993 */
1994CK_RV
1995sftk_CopyObject(SFTKObject *destObject, SFTKObject *srcObject)
1996{
1997 SFTKAttribute *attribute;
1998 SFTKSessionObject *src_so = sftk_narrowToSessionObject(srcObject);
1999 SFTKSessionObject *dest_so = sftk_narrowToSessionObject(destObject);
2000 unsigned int i;
2001
2002 destObject->validation_value = srcObject->validation_value;
2003 destObject->source = srcObject->source;
2004 if (src_so == NULL((void*)0)) {
2005 return sftk_CopyTokenObject(destObject, srcObject);
2006 }
2007 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", 2007
))
;
2008 if (dest_so == NULL((void*)0)) {
2009 return CKR_ARGUMENTS_BAD0x00000007UL;
2010 }
2011
2012 PR_Lock(src_so->attributeLock);
2013 for (i = 0; i < src_so->hashSize; i++) {
2014 attribute = src_so->head[i];
2015 do {
2016 if (attribute) {
2017 SFTKAttribute *existing;
2018 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; } }
2019 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; } }
;
2020 if (!existing) {
2021 /* we need to copy the attribute since each attribute
2022 * only has one set of link list pointers */
2023 SFTKAttribute *newAttribute = sftk_InitAttribute(
2024 dest_so, dest_so->nextAttr++,
2025 sftk_attr_expand(&attribute->attrib)(&attribute->attrib)->type, (&attribute->attrib
)->pValue, (&attribute->attrib)->ulValueLen
);
2026 if (newAttribute == NULL((void*)0)) {
2027 PR_Unlock(src_so->attributeLock);
2028 return CKR_HOST_MEMORY0x00000002UL;
2029 }
2030 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); }
2031 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); }
;
2032 }
2033 attribute = attribute->next;
2034 }
2035 } while (attribute != NULL((void*)0));
2036 }
2037 PR_Unlock(src_so->attributeLock);
2038
2039 return CKR_OK0x00000000UL;
2040}
2041
2042/*
2043 * ******************** Search Utilities *******************************
2044 */
2045
2046/* add an object to a search list */
2047CK_RV
2048AddToList(SFTKObjectListElement **list, SFTKObject *object)
2049{
2050 SFTKObjectListElement *newElem =
2051 (SFTKObjectListElement *)PORT_AllocPORT_Alloc_Util(sizeof(SFTKObjectListElement));
2052
2053 if (newElem == NULL((void*)0))
2054 return CKR_HOST_MEMORY0x00000002UL;
2055
2056 newElem->next = *list;
2057 newElem->object = object;
2058 sftk_ReferenceObject(object);
2059
2060 *list = newElem;
2061 return CKR_OK0x00000000UL;
2062}
2063
2064/* return true if the object matches the template */
2065PRBool
2066sftk_objectMatch(SFTKObject *object, CK_ATTRIBUTE_PTR theTemplate, int count)
2067{
2068 int i;
2069
2070 for (i = 0; i < count; i++) {
6
Assuming 'i' is < 'count'
7
Loop condition is true. Entering loop body
2071 SFTKAttribute *attribute = sftk_FindAttribute(object, theTemplate[i].type);
8
Calling 'sftk_FindAttribute'
25
Returning from 'sftk_FindAttribute'
2072 if (attribute
25.1
'attribute' is not equal to NULL
== NULL((void*)0)) {
26
Taking false branch
2073 return PR_FALSE0;
2074 }
2075 if (attribute->attrib.ulValueLen == theTemplate[i].ulValueLen) {
27
Assuming 'attribute->attrib.ulValueLen' is equal to 'theTemplate[i].ulValueLen'
28
Taking true branch
2076 if (PORT_Memcmpmemcmp(attribute->attrib.pValue, theTemplate[i].pValue,
29
Null pointer passed to 1st parameter expecting 'nonnull'
2077 theTemplate[i].ulValueLen) == 0) {
2078 sftk_FreeAttribute(attribute);
2079 continue;
2080 }
2081 }
2082 sftk_FreeAttribute(attribute);
2083 return PR_FALSE0;
2084 }
2085 return PR_TRUE1;
2086}
2087
2088/* search through all the objects in the queue and return the template matches
2089 * in the object list.
2090 */
2091CK_RV
2092sftk_searchObjectList(SFTKSearchResults *search, SFTKObject **head,
2093 unsigned int size, PRLock *lock, CK_ATTRIBUTE_PTR theTemplate,
2094 int count, PRBool isLoggedIn)
2095{
2096 unsigned int i;
2097 SFTKObject *object;
2098 CK_RV crv = CKR_OK0x00000000UL;
2099
2100 PR_Lock(lock);
2101 for (i = 0; i < size; i++) {
1
Assuming 'i' is < 'size'
2
Loop condition is true. Entering loop body
2102 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
2103 if (sftk_objectMatch(object, theTemplate, count)) {
5
Calling 'sftk_objectMatch'
2104 /* don't return objects that aren't yet visible */
2105 if ((!isLoggedIn) && sftk_isTrue(object, CKA_PRIVATE0x00000002UL))
2106 continue;
2107 sftk_addHandle(search, object->handle);
2108 }
2109 }
2110 }
2111 PR_Unlock(lock);
2112 return crv;
2113}
2114
2115/*
2116 * free a single list element. Return the Next object in the list.
2117 */
2118SFTKObjectListElement *
2119sftk_FreeObjectListElement(SFTKObjectListElement *objectList)
2120{
2121 SFTKObjectListElement *ol = objectList->next;
2122
2123 sftk_FreeObject(objectList->object);
2124 PORT_FreePORT_Free_Util(objectList);
2125 return ol;
2126}
2127
2128/* free an entire object list */
2129void
2130sftk_FreeObjectList(SFTKObjectListElement *objectList)
2131{
2132 SFTKObjectListElement *ol;
2133
2134 for (ol = objectList; ol != NULL((void*)0); ol = sftk_FreeObjectListElement(ol)) {
2135 }
2136}
2137
2138/*
2139 * free a search structure
2140 */
2141void
2142sftk_FreeSearch(SFTKSearchResults *search)
2143{
2144 if (search->handles) {
2145 PORT_FreePORT_Free_Util(search->handles);
2146 }
2147 PORT_FreePORT_Free_Util(search);
2148}
2149
2150/*
2151 * ******************** Session Utilities *******************************
2152 */
2153
2154/* update the sessions state based in it's flags and wether or not it's
2155 * logged in */
2156void
2157sftk_update_state(SFTKSlot *slot, SFTKSession *session)
2158{
2159 PR_Lock(slot->slotLock);
2160 if (slot->isLoggedIn) {
2161 if (slot->ssoLoggedIn) {
2162 session->info.state = CKS_RW_SO_FUNCTIONS4;
2163 } else if (session->info.flags & CKF_RW_SESSION0x00000002UL) {
2164 session->info.state = CKS_RW_USER_FUNCTIONS3;
2165 } else {
2166 session->info.state = CKS_RO_USER_FUNCTIONS1;
2167 }
2168 } else {
2169 if (session->info.flags & CKF_RW_SESSION0x00000002UL) {
2170 session->info.state = CKS_RW_PUBLIC_SESSION2;
2171 } else {
2172 session->info.state = CKS_RO_PUBLIC_SESSION0;
2173 }
2174 }
2175 PR_Unlock(slot->slotLock);
2176}
2177
2178/* update the state of all the sessions on a slot */
2179void
2180sftk_update_all_states(SFTKSlot *slot)
2181{
2182 unsigned int i;
2183 SFTKSession *session;
2184
2185 for (i = 0; i < slot->sessHashSize; i++) {
2186 PRLock *lock = SFTK_HEAD_BUCKET_LOCK(slot, i)((slot)->sessionLock[((i) >> 0) & (slot)->sessionLockMask
])
;
2187 PR_Lock(lock);
2188 for (session = slot->head[i]; session; session = session->next) {
2189 sftk_update_state(slot, session);
2190 }
2191 PR_Unlock(lock);
2192 }
2193}
2194
2195/*
2196 * context are cipher and digest contexts that are associated with a session
2197 */
2198void
2199sftk_FreeContext(SFTKSessionContext *context)
2200{
2201 if (context->cipherInfo) {
2202 (*context->destroy)(context->cipherInfo, PR_TRUE1);
2203 }
2204 if (context->hashInfo) {
2205 (*context->hashdestroy)(context->hashInfo, PR_TRUE1);
2206 }
2207 if (context->key) {
2208 sftk_FreeObject(context->key);
2209 context->key = NULL((void*)0);
2210 }
2211 if (context->signature) {
2212 SECITEM_FreeItemSECITEM_FreeItem_Util(context->signature, PR_TRUE1);
2213 context->signature = NULL((void*)0);
2214 }
2215 PORT_FreePORT_Free_Util(context);
2216}
2217
2218/*
2219 * Init a new session. NOTE: The session handle is not set, and the
2220 * session is not added to the slot's session queue.
2221 */
2222CK_RV
2223sftk_InitSession(SFTKSession *session, SFTKSlot *slot, CK_SLOT_ID slotID,
2224 CK_NOTIFY notify, CK_VOID_PTR pApplication, CK_FLAGS flags)
2225{
2226 session->next = session->prev = NULL((void*)0);
2227 session->refCount = 1;
2228 session->enc_context = NULL((void*)0);
2229 session->hash_context = NULL((void*)0);
2230 session->search = NULL((void*)0);
2231 session->objectIDCount = 1;
2232 session->objectLock = PR_NewLock();
2233 if (session->objectLock == NULL((void*)0)) {
2234 return CKR_HOST_MEMORY0x00000002UL;
2235 }
2236 session->objects[0] = NULL((void*)0);
2237
2238 session->slot = slot;
2239 session->notify = notify;
2240 session->appData = pApplication;
2241 session->info.flags = flags;
2242 session->info.slotID = slotID;
2243 session->info.ulDeviceError = 0;
2244 sftk_update_state(slot, session);
2245 /* no ops completed yet, so the last one couldn't be a FIPS op */
2246 session->lastOpWasFIPS = PR_FALSE0;
2247 return CKR_OK0x00000000UL;
2248}
2249
2250/*
2251 * Create a new session and init it.
2252 */
2253SFTKSession *
2254sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication,
2255 CK_FLAGS flags)
2256{
2257 SFTKSession *session;
2258 SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE0);
2259 CK_RV crv;
2260
2261 if (slot == NULL((void*)0))
2262 return NULL((void*)0);
2263
2264 session = (SFTKSession *)PORT_AllocPORT_Alloc_Util(sizeof(SFTKSession));
2265 if (session == NULL((void*)0))
2266 return NULL((void*)0);
2267
2268 crv = sftk_InitSession(session, slot, slotID, notify, pApplication, flags);
2269 if (crv != CKR_OK0x00000000UL) {
2270 PORT_FreePORT_Free_Util(session);
2271 return NULL((void*)0);
2272 }
2273 return session;
2274}
2275
2276/* free all the data associated with a session. */
2277void
2278sftk_ClearSession(SFTKSession *session)
2279{
2280 SFTKObjectList *op, *next;
2281
2282 /* clean out the attributes */
2283 /* since no one is referencing us, it's safe to walk the chain
2284 * without a lock */
2285 for (op = session->objects[0]; op != NULL((void*)0); op = next) {
2286 next = op->next;
2287 /* paranoia */
2288 op->next = op->prev = NULL((void*)0);
2289 sftk_DeleteObject(session, op->parent);
2290 }
2291 PR_DestroyLock(session->objectLock);
2292 if (session->enc_context) {
2293 sftk_FreeContext(session->enc_context);
2294 session->enc_context = NULL((void*)0);
2295 }
2296 if (session->hash_context) {
2297 sftk_FreeContext(session->hash_context);
2298 session->hash_context = NULL((void*)0);
2299 }
2300 if (session->search) {
2301 sftk_FreeSearch(session->search);
2302 session->search = NULL((void*)0);
2303 }
2304}
2305
2306/* free the data associated with the session, and the session.
2307 * Caller must have driven refCount to 0; reachable only via sftk_FreeSession. */
2308static void
2309sftk_DestroySession(SFTKSession *session)
2310{
2311 PORT_Assert(session->refCount == 0)((session->refCount == 0) ? ((void)0) : PR_Assert("session->refCount == 0"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 2311
))
;
2312 sftk_ClearSession(session);
2313 PORT_FreePORT_Free_Util(session);
2314}
2315
2316/*
2317 * look up a session structure from a session handle
2318 * generate a reference to it.
2319 */
2320SFTKSession *
2321sftk_SessionFromHandle(CK_SESSION_HANDLE handle)
2322{
2323 SFTKSlot *slot = sftk_SlotFromSessionHandle(handle);
2324 SFTKSession *session;
2325 PRLock *lock;
2326
2327 if (!slot)
2328 return NULL((void*)0);
2329 lock = SFTK_SESSION_LOCK(slot, handle)((slot)->sessionLock[((((PRUint32)(((handle)) * 1791398085
) & ((slot)->sessHashSize - 1))) >> 0) & (slot
)->sessionLockMask])
;
2330
2331 PR_Lock(lock);
2332 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; } }
;
2333 if (session)
2334 session->refCount++;
2335 PR_Unlock(lock);
2336
2337 return (session);
2338}
2339
2340/*
2341 * release a reference to a session. The slot's session bucket holds the
2342 * initial reference (created by sftk_InitSession); sftk_SessionFromHandle
2343 * adds another for the duration of the caller's use. NSC_CloseSession and
2344 * sftk_CloseAllSessions drop the bucket's reference once the session has
2345 * been removed from the queue. The thread that drives refCount to 0
2346 * destroys the session.
2347 */
2348void
2349sftk_FreeSession(SFTKSession *session)
2350{
2351 PRBool destroy = PR_FALSE0;
2352 SFTKSlot *slot = sftk_SlotFromSession(session)((session)->slot);
2353 PRLock *lock = SFTK_SESSION_LOCK(slot, session->handle)((slot)->sessionLock[((((PRUint32)(((session->handle)) *
1791398085) & ((slot)->sessHashSize - 1))) >> 0
) & (slot)->sessionLockMask])
;
2354
2355 PR_Lock(lock);
2356 PORT_Assert(session->refCount > 0)((session->refCount > 0) ? ((void)0) : PR_Assert("session->refCount > 0"
, "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c", 2356
))
;
2357 if (session->refCount == 1)
2358 destroy = PR_TRUE1;
2359 session->refCount--;
2360 PR_Unlock(lock);
2361
2362 if (destroy)
2363 sftk_DestroySession(session);
2364}
2365
2366void
2367sftk_addHandle(SFTKSearchResults *search, CK_OBJECT_HANDLE handle)
2368{
2369 if (search->handles == NULL((void*)0)) {
2370 return;
2371 }
2372 if (search->size >= search->array_size) {
2373 search->array_size += NSC_SEARCH_BLOCK_SIZE5;
2374 search->handles = (CK_OBJECT_HANDLE *)PORT_ReallocPORT_Realloc_Util(search->handles,
2375 sizeof(CK_OBJECT_HANDLE) * search->array_size);
2376 if (search->handles == NULL((void*)0)) {
2377 return;
2378 }
2379 }
2380 search->handles[search->size] = handle;
2381 search->size++;
2382}
2383
2384static CK_RV
2385handleToClass(SFTKSlot *slot, CK_OBJECT_HANDLE handle,
2386 CK_OBJECT_CLASS *objClass)
2387{
2388 SFTKDBHandle *dbHandle = sftk_getDBForTokenObject(slot, handle);
2389 CK_ATTRIBUTE objClassTemplate;
2390 CK_RV crv;
2391
2392 *objClass = CKO_DATA0x00000000UL;
2393 objClassTemplate.type = CKA_CLASS0x00000000UL;
2394 objClassTemplate.pValue = objClass;
2395 objClassTemplate.ulValueLen = sizeof(*objClass);
2396 crv = sftkdb_GetAttributeValue(dbHandle, handle, &objClassTemplate, 1);
2397 sftk_freeDB(dbHandle);
2398 return crv;
2399}
2400
2401SFTKObject *
2402sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle)
2403{
2404 SFTKObject *object = NULL((void*)0);
2405 PRBool hasLocks = PR_FALSE0;
2406 CK_RV crv;
2407
2408 object = sftk_GetObjectFromList(&hasLocks, PR_FALSE0, &tokenObjectList, 0,
2409 PR_FALSE0);
2410 if (object == NULL((void*)0)) {
2411 return NULL((void*)0);
2412 }
2413
2414 object->handle = handle;
2415 /* every object must have a class, if we can't get it, the object
2416 * doesn't exist */
2417 crv = handleToClass(slot, handle, &object->objclass);
2418 if (crv != CKR_OK0x00000000UL) {
2419 goto loser;
2420 }
2421 object->slot = slot;
2422 /* set up the validation flags */
2423 object->validation_value = 0;
2424 object->validation_attribute.next = NULL((void*)0);
2425 object->validation_attribute.prev = NULL((void*)0);
2426 object->validation_attribute.freeAttr = PR_FALSE0;
2427 object->validation_attribute.freeData = PR_FALSE0;
2428 object->validation_attribute.handle = CKA_OBJECT_VALIDATION_FLAGS0x0000061eUL;
2429 object->validation_attribute.attrib.type = CKA_OBJECT_VALIDATION_FLAGS0x0000061eUL;
2430 object->validation_attribute.attrib.pValue = &object->validation_value;
2431 object->validation_attribute.attrib.ulValueLen = sizeof(object->validation_value);
2432 /* initialize the FIPS flag properly */
2433 sftk_setFIPS(object, sftk_isFIPS(slot->slotID)(((slot->slotID) == 3) || ((slot->slotID) >= 101)));
2434 object->source = SFTK_SOURCE_DEFAULT;
2435 object->objectInfo = NULL((void*)0);
2436 object->infoFree = NULL((void*)0);
2437 if (!hasLocks) {
2438 object->refLock = PR_NewLock();
2439 }
2440 if (object->refLock == NULL((void*)0)) {
2441 goto loser;
2442 }
2443 object->refCount = 1;
2444 object->type = SFTK_TOKEN_OBJECT_TYPE0x00000000U;
2445
2446 return object;
2447loser:
2448 (void)sftk_DestroyObject(object);
2449 return NULL((void*)0);
2450}
2451
2452CK_RV
2453sftk_convertSessionToToken(SFTKObject *obj)
2454{
2455 SECItem *dbKey;
2456 SFTKSessionObject *so = (SFTKSessionObject *)obj;
2457 SFTKTokenObject *to = sftk_narrowToTokenObject(obj);
2458 CK_RV crv;
2459
2460 sftk_DestroySessionObjectData(so);
2461 PR_DestroyLock(so->attributeLock);
2462
2463 sftk_tokenKeyLock(so->obj.slot);
2464 dbKey = sftk_lookupTokenKeyByHandle(so->obj.slot, so->obj.handle);
2465 if (dbKey && SECFailure == SECITEM_CopyItemSECITEM_CopyItem_Util(NULL((void*)0), &to->dbKey, dbKey)) {
2466 crv = CKR_HOST_MEMORY0x00000002UL;
2467 } else {
2468 crv = CKR_OK0x00000000UL;
2469 }
2470 sftk_tokenKeyUnlock(so->obj.slot);
2471 return crv;
2472}
2473
2474SFTKSessionObject *
2475sftk_narrowToSessionObject(SFTKObject *obj)
2476{
2477 PRBool handleSaysSession = !sftk_isToken(obj->handle)(((obj->handle) & 0x80000000L) == 0x80000000L);
2478 PRBool typeSaysSession = obj->type == SFTK_SESSION_OBJECT_TYPE0xFFFFFFFFU;
2479 if (handleSaysSession != typeSaysSession) {
2480 PORT_Assert(0)((0) ? ((void)0) : PR_Assert("0", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 2480))
;
2481 return NULL((void*)0);
2482 }
2483 return handleSaysSession ? (SFTKSessionObject *)obj : NULL((void*)0);
2484}
2485
2486SFTKTokenObject *
2487sftk_narrowToTokenObject(SFTKObject *obj)
2488{
2489 PRBool handleSaysToken = sftk_isToken(obj->handle)(((obj->handle) & 0x80000000L) == 0x80000000L);
2490 PRBool typeSaysToken = obj->type == SFTK_TOKEN_OBJECT_TYPE0x00000000U;
2491 if (handleSaysToken != typeSaysToken) {
2492 PORT_Assert(0)((0) ? ((void)0) : PR_Assert("0", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 2492))
;
2493 return NULL((void*)0);
2494 }
2495 return handleSaysToken ? (SFTKTokenObject *)obj : NULL((void*)0);
2496}
2497
2498/* Constant time helper functions */
2499
2500/* sftk_CKRVToMask returns, in constant time, a mask value of
2501 * all ones if rv == CKR_OK. Otherwise it returns zero. */
2502unsigned int
2503sftk_CKRVToMask(CK_RV rv)
2504{
2505 PR_STATIC_ASSERT(CKR_OK == 0)extern void pr_static_assert(int arg[(0x00000000UL == 0) ? 1 :
-1])
;
2506 return ~PORT_CT_NOT_ZERO(rv)(((PRUint32)((PRInt32)(((rv) | (0 - (rv)))) >> (sizeof(
PRInt32) * 8 - 1))))
;
2507}
2508
2509/* sftk_CheckCBCPadding checks, in constant time, the padding validity and
2510 * accordingly sets the pad length. */
2511CK_RV
2512sftk_CheckCBCPadding(CK_BYTE_PTR pBuf, unsigned int bufLen,
2513 unsigned int blockSize, unsigned int *outPadSize)
2514{
2515 PORT_Assert(outPadSize)((outPadSize) ? ((void)0) : PR_Assert("outPadSize", "/root/firefox-clang/security/nss/lib/softoken/pkcs11u.c"
, 2515))
;
2516
2517 /* CBC-padded plaintext is always at least one full block */
2518 if (bufLen < blockSize || blockSize == 0) {
2519 *outPadSize = 0;
2520 return CKR_ENCRYPTED_DATA_INVALID0x00000040UL;
2521 }
2522
2523 unsigned int padSize = (unsigned int)pBuf[bufLen - 1];
2524
2525 /* If padSize <= blockSize, set goodPad to all-1s and all-0s otherwise.*/
2526 unsigned int goodPad = PORT_CT_DUPLICATE_MSB_TO_ALL(~(blockSize - padSize))((PRUint32)((PRInt32)(~(blockSize - padSize)) >> (sizeof
(PRInt32) * 8 - 1)))
;
2527 /* padSize should not be 0 */
2528 goodPad &= PORT_CT_NOT_ZERO(padSize)(((PRUint32)((PRInt32)(((padSize) | (0 - (padSize)))) >>
(sizeof(PRInt32) * 8 - 1))))
;
2529
2530 unsigned int i;
2531 for (i = 0; i < blockSize; i++) {
2532 /* If i < padSize, set loopMask to all-1s and all-0s otherwise.*/
2533 unsigned int loopMask = PORT_CT_DUPLICATE_MSB_TO_ALL(~(padSize - 1 - i))((PRUint32)((PRInt32)(~(padSize - 1 - i)) >> (sizeof(PRInt32
) * 8 - 1)))
;
2534 /* Get the padding value (should be padSize) from buffer */
2535 unsigned int padVal = pBuf[bufLen - 1 - i];
2536 /* Update goodPad only if i < padSize */
2537 goodPad &= PORT_CT_SEL(loopMask, ~(padVal ^ padSize), goodPad)(((loopMask) & (~(padVal ^ padSize))) | (~(loopMask) &
(goodPad)))
;
2538 }
2539
2540 /* If any of the final padding bytes had the wrong value, one or more
2541 * of the lower eight bits of |goodPad| will be cleared. We AND the
2542 * bottom 8 bits together and duplicate the result to all the bits. */
2543 goodPad &= goodPad >> 4;
2544 goodPad &= goodPad >> 2;
2545 goodPad &= goodPad >> 1;
2546 goodPad <<= sizeof(goodPad) * 8 - 1;
2547 goodPad = PORT_CT_DUPLICATE_MSB_TO_ALL(goodPad)((PRUint32)((PRInt32)(goodPad) >> (sizeof(PRInt32) * 8 -
1)))
;
2548
2549 /* Set outPadSize to padSize or 0 */
2550 *outPadSize = PORT_CT_SEL(goodPad, padSize, 0)(((goodPad) & (padSize)) | (~(goodPad) & (0)));
2551 /* Return OK if the pad is valid */
2552 return PORT_CT_SEL(goodPad, CKR_OK, CKR_ENCRYPTED_DATA_INVALID)(((goodPad) & (0x00000000UL)) | (~(goodPad) & (0x00000040UL
)))
;
2553}
2554
2555void
2556sftk_EncodeInteger(PRUint64 integer, CK_ULONG num_bits, CK_BBOOL littleEndian,
2557 CK_BYTE_PTR output, CK_ULONG_PTR output_len)
2558{
2559 if (output_len) {
2560 *output_len = (num_bits / 8);
2561 }
2562
2563 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", 2563
))
;
2564
2565 if (littleEndian == CK_TRUE1) {
2566 for (size_t offset = 0; offset < num_bits / 8; offset++) {
2567 output[offset] = (unsigned char)((integer >> (offset * 8)) & 0xFF);
2568 }
2569 } else {
2570 for (size_t offset = 0; offset < num_bits / 8; offset++) {
2571 PRUint64 shift = num_bits - (offset + 1) * 8;
2572 output[offset] = (unsigned char)((integer >> shift) & 0xFF);
2573 }
2574 }
2575}
2576
2577CK_FLAGS
2578sftk_AttributeToFlags(CK_ATTRIBUTE_TYPE op)
2579{
2580 CK_FLAGS flags = 0;
2581
2582 switch (op) {
2583 case CKA_ENCRYPT0x00000104UL:
2584 flags = CKF_ENCRYPT0x00000100UL;
2585 break;
2586 case CKA_DECRYPT0x00000105UL:
2587 flags = CKF_DECRYPT0x00000200UL;
2588 break;
2589 case CKA_WRAP0x00000106UL:
2590 flags = CKF_WRAP0x00020000UL;
2591 break;
2592 case CKA_UNWRAP0x00000107UL:
2593 flags = CKF_UNWRAP0x00040000UL;
2594 break;
2595 case CKA_SIGN0x00000108UL:
2596 flags = CKF_SIGN0x00000800UL;
2597 break;
2598 case CKA_SIGN_RECOVER0x00000109UL:
2599 flags = CKF_SIGN_RECOVER0x00001000UL;
2600 break;
2601 case CKA_VERIFY0x0000010AUL:
2602 flags = CKF_VERIFY0x00002000;
2603 break;
2604 case CKA_VERIFY_RECOVER0x0000010BUL:
2605 flags = CKF_VERIFY_RECOVER0x00004000UL;
2606 break;
2607 case CKA_DERIVE0x0000010CUL:
2608 flags = CKF_DERIVE0x00080000UL;
2609 break;
2610 /* fake attribute to select digesting */
2611 case CKA_DIGEST0x81000000L:
2612 flags = CKF_DIGEST0x00000400UL;
2613 break;
2614 /* fake attribute to select key gen */
2615 case CKA_NSS_GENERATE0x81000001L:
2616 flags = CKF_GENERATE0x00008000UL;
2617 break;
2618 /* fake attribute to select key pair gen */
2619 case CKA_NSS_GENERATE_KEY_PAIR0x81000002L:
2620 flags = CKF_GENERATE_KEY_PAIR0x00010000UL;
2621 break;
2622 /* fake attributes to to handle MESSAGE* flags */
2623 case CKA_NSS_MESSAGE0x82000000L | CKA_ENCRYPT0x00000104UL:
2624 flags = CKF_MESSAGE_ENCRYPT0x00000002UL;
2625 break;
2626 case CKA_NSS_MESSAGE0x82000000L | CKA_DECRYPT0x00000105UL:
2627 flags = CKF_MESSAGE_DECRYPT0x00000004UL;
2628 break;
2629 case CKA_NSS_MESSAGE0x82000000L | CKA_SIGN0x00000108UL:
2630 flags = CKF_MESSAGE_SIGN0x00000008UL;
2631 break;
2632 case CKA_NSS_MESSAGE0x82000000L | CKA_VERIFY0x0000010AUL:
2633 flags = CKF_MESSAGE_VERIFY0x00000010UL;
2634 break;
2635 default:
2636 break;
2637 }
2638 return flags;
2639}
2640
2641/*
2642 * ******************** Hash Utilities **************************
2643 */
2644/*
2645 * Utility function for converting PSS/OAEP parameter types into
2646 * HASH_HashTypes. Note: Only SHA family functions are defined in RFC 3447.
2647 */
2648HASH_HashType
2649sftk_GetHashTypeFromMechanism(CK_MECHANISM_TYPE mech)
2650{
2651 switch (mech) {
2652 case CKM_SHA_10x00000220UL:
2653 case CKG_MGF1_SHA10x00000001UL:
2654 return HASH_AlgSHA1;
2655 case CKM_SHA2240x00000255UL:
2656 case CKG_MGF1_SHA2240x00000005UL:
2657 return HASH_AlgSHA224;
2658 case CKM_SHA2560x00000250UL:
2659 case CKG_MGF1_SHA2560x00000002UL:
2660 return HASH_AlgSHA256;
2661 case CKM_SHA3840x00000260UL:
2662 case CKG_MGF1_SHA3840x00000003UL:
2663 return HASH_AlgSHA384;
2664 case CKM_SHA5120x00000270UL:
2665 case CKG_MGF1_SHA5120x00000004UL:
2666 return HASH_AlgSHA512;
2667 default:
2668 return HASH_AlgNULL;
2669 }
2670}
2671
2672#ifdef NSS_HAS_FIPS_INDICATORS
2673/**************** FIPS Indicator Utilities *************************/
2674/* sigh, we probably need a version of this in secutil so that both
2675 * softoken and NSS can use it */
2676static SECOidTag
2677sftk_quickGetECCCurveOid(SFTKObject *source)
2678{
2679 SFTKAttribute *attribute = sftk_FindAttribute(source, CKA_EC_PARAMS0x00000180UL);
2680 unsigned char *encoded;
2681 int len;
2682 SECItem oid;
2683 SECOidTag tag;
2684
2685 if (attribute == NULL((void*)0)) {
2686 return SEC_OID_UNKNOWN;
2687 }
2688 encoded = attribute->attrib.pValue;
2689 len = attribute->attrib.ulValueLen;
2690 if ((len < 2) || (encoded[0] != SEC_ASN1_OBJECT_ID0x06) ||
2691 (len != encoded[1] + 2)) {
2692 sftk_FreeAttribute(attribute);
2693 return SEC_OID_UNKNOWN;
2694 }
2695 oid.data = encoded + 2;
2696 oid.len = len - 2;
2697 tag = SECOID_FindOIDTagSECOID_FindOIDTag_Util(&oid);
2698 sftk_FreeAttribute(attribute);
2699 return tag;
2700}
2701
2702/* This function currently only returns valid lengths for
2703 * FIPS approved ECC curves. If we want to make this generic
2704 * in the future, that Curve determination can be done in
2705 * the sftk_handleSpecial. Since it's currently only used
2706 * in FIPS indicators, it's currently only compiled with
2707 * the FIPS indicator code */
2708static CK_ULONG
2709sftk_getKeyLength(SFTKObject *source)
2710{
2711 CK_KEY_TYPE keyType = CKK_INVALID_KEY_TYPE0xffffffffUL;
2712 CK_ATTRIBUTE_TYPE keyAttribute;
2713 CK_ULONG keyLength = 0;
2714 SFTKAttribute *attribute;
2715 CK_RV crv;
2716
2717 /* If we don't have a key, then it doesn't have a length.
2718 * this may be OK (say we are hashing). The mech info will
2719 * sort this out because algorithms which expect no keys
2720 * will accept zero length for the keys */
2721 if (source == NULL((void*)0)) {
2722 return 0;
2723 }
2724
2725 crv = sftk_GetULongAttribute(source, CKA_KEY_TYPE0x00000100UL, &keyType);
2726 if (crv != CKR_OK0x00000000UL) {
2727 /* sometimes we're passed a data object, in that case the
2728 * key length is CKA_VALUE, which is the default */
2729 keyType = CKK_INVALID_KEY_TYPE0xffffffffUL;
2730 }
2731 if ((keyType == CKK_EC0x00000003UL) || (keyType == CKK_EC_EDWARDS0x00000040UL) ||
2732 (keyType == CKK_EC_MONTGOMERY0x00000041UL)) {
2733 SECOidTag curve = sftk_quickGetECCCurveOid(source);
2734 switch (curve) {
2735 case SEC_OID_CURVE25519:
2736 /* change when we start algorithm testing on curve25519 */
2737 return 0;
2738 case SEC_OID_SECG_EC_SECP256R1SEC_OID_ANSIX962_EC_PRIME256V1:
2739 return 256;
2740 case SEC_OID_SECG_EC_SECP384R1:
2741 return 384;
2742 case SEC_OID_SECG_EC_SECP521R1:
2743 /* this is a lie, but it makes the table easier. We don't
2744 * have to have a double entry for every ECC mechanism */
2745 return 512;
2746 default:
2747 break;
2748 }
2749 /* other curves aren't NIST approved, returning 0 will cause these
2750 * curves to fail FIPS length criteria */
2751 return 0;
2752 }
2753
2754 switch (keyType) {
2755 case CKK_RSA0x00000000UL:
2756 keyAttribute = CKA_MODULUS0x00000120UL;
2757 break;
2758 case CKK_DSA0x00000001UL:
2759 case CKK_DH0x00000002UL:
2760 keyAttribute = CKA_PRIME0x00000130UL;
2761 break;
2762 default:
2763 keyAttribute = CKA_VALUE0x00000011UL;
2764 break;
2765 }
2766 attribute = sftk_FindAttribute(source, keyAttribute);
2767 if (attribute) {
2768 keyLength = attribute->attrib.ulValueLen * 8;
2769 sftk_FreeAttribute(attribute);
2770 }
2771 return keyLength;
2772}
2773
2774static PRBool
2775sftk_checkKeyLength(CK_ULONG keyLength, CK_ULONG min,
2776 CK_ULONG max, CK_ULONG step)
2777{
2778 if (keyLength > max) {
2779 return PR_FALSE0;
2780 }
2781 if (keyLength < min) {
2782 return PR_FALSE0;
2783 }
2784 if (step == 0) {
2785 return PR_TRUE1;
2786 }
2787 if (((keyLength - min) % step) != 0) {
2788 return PR_FALSE0;
2789 }
2790 return PR_TRUE1;
2791}
2792
2793PRBool
2794sftk_checkFIPSHash(CK_MECHANISM_TYPE hash, PRBool allowSmall, PRBool allowCMAC)
2795{
2796 switch (hash) {
2797 case CKM_AES_CMAC0x0000108AUL:
2798 return allowCMAC;
2799 case CKM_SHA_10x00000220UL:
2800 case CKM_SHA_1_HMAC0x00000221UL:
2801 case CKM_SHA2240x00000255UL:
2802 case CKM_SHA224_HMAC0x00000256UL:
2803 return allowSmall;
2804 case CKM_SHA2560x00000250UL:
2805 case CKM_SHA256_HMAC0x00000251UL:
2806 case CKM_SHA3840x00000260UL:
2807 case CKM_SHA384_HMAC0x00000261UL:
2808 case CKM_SHA5120x00000270UL:
2809 case CKM_SHA512_HMAC0x00000271UL:
2810 return PR_TRUE1;
2811 }
2812 return PR_FALSE0;
2813}
2814
2815/*
2816 * handle specialized FIPS semantics that are too complicated to
2817 * handle with just a table. NOTE: this means any additional semantics
2818 * would have to be coded here before they can be added to the table */
2819static PRBool
2820sftk_handleSpecial(SFTKSlot *slot, CK_MECHANISM *mech,
2821 SFTKFIPSAlgorithmList *mechInfo, SFTKObject *source,
2822 CK_ULONG keyLength, CK_ULONG targetKeyLength)
2823{
2824 PRBool allowSmall = PR_FALSE0;
2825 PRBool allowCMAC = PR_FALSE0;
2826 switch (mechInfo->special) {
2827 case SFTKFIPSDH: {
2828 SECItem dhPrime;
2829 SECItem dhBase;
2830 SECItem dhGenerator;
2831 PRBool fipsOk = PR_FALSE0;
2832 const SECItem *dhSubPrime;
2833 CK_RV crv = sftk_Attribute2SecItem(NULL((void*)0), &dhPrime,
2834 source, CKA_PRIME0x00000130UL);
2835 if (crv != CKR_OK0x00000000UL) {
2836 return PR_FALSE0;
2837 }
2838 crv = sftk_Attribute2SecItem(NULL((void*)0), &dhBase, source, CKA_BASE0x00000132UL);
2839 if (crv != CKR_OK0x00000000UL) {
2840 return PR_FALSE0;
2841 }
2842 dhSubPrime = sftk_VerifyDH_Prime(&dhPrime, &dhGenerator, PR_TRUE1);
2843 fipsOk = (dhSubPrime) ? PR_TRUE1 : PR_FALSE0;
2844 if (fipsOk && (SECITEM_CompareItemSECITEM_CompareItem_Util(&dhBase, &dhGenerator) != 0)) {
2845 fipsOk = PR_FALSE0;
2846 }
2847
2848 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&dhPrime, PR_FALSE0);
2849 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(&dhBase, PR_FALSE0);
2850 return fipsOk;
2851 }
2852 case SFTKFIPSNone:
2853 return PR_FALSE0;
2854 case SFTKFIPSECC:
2855 /* we've already handled the curve selection in the 'getlength'
2856 * function */
2857 return PR_TRUE1;
2858 case SFTKFIPSAEAD: {
2859 if (mech->ulParameterLen == 0) {
2860 /* AEAD ciphers are only in FIPS mode if we are using the
2861 * MESSAGE interface. This takes an empty parameter
2862 * in the init function */
2863 return PR_TRUE1;
2864 }
2865 return PR_FALSE0;
2866 }
2867 case SFTKFIPSRSAPSS: {
2868 /* PSS salt must not be longer than the underlying hash.
2869 * We verify that the underlying hash of the
2870 * parameters matches Hash of the combined hash mechanisms, so
2871 * we don't need to look at the specific PSS mechanism */
2872 CK_RSA_PKCS_PSS_PARAMS *pss = (CK_RSA_PKCS_PSS_PARAMS *)
2873 mech->pParameter;
2874 const SECHashObject *hashObj = NULL((void*)0);
2875 if (mech->ulParameterLen != sizeof(*pss)) {
2876 return PR_FALSE0;
2877 }
2878 /* we use the existing hash utilities to find the length of
2879 * the hash */
2880 hashObj = HASH_GetRawHashObject(sftk_GetHashTypeFromMechanism(
2881 pss->hashAlg));
2882 if (hashObj == NULL((void*)0)) {
2883 return PR_FALSE0;
2884 }
2885 /* cap the salt for legacy keys */
2886 if ((keyLength <= 1024) && (pss->sLen > 63)) {
2887 return PR_FALSE0;
2888 }
2889 /* cap the salt based on the hash */
2890 if (pss->sLen > hashObj->length) {
2891 return PR_FALSE0;
2892 }
2893 return PR_TRUE1;
2894 }
2895 case SFTKFIPSPBKDF2: {
2896 /* from NIST SP 800-132
2897 * PBKDF2 must have the following addition restrictions
2898 * (independent of keysize).
2899 * 1. iteration count must be at least 1000.
2900 * 2. salt must be at least 128 bits (16 bytes).
2901 * 3. password must match the length specified in the SP
2902 */
2903 CK_PKCS5_PBKD2_PARAMS2 *pbkdf2 = (CK_PKCS5_PBKD2_PARAMS2 *)
2904 mech->pParameter;
2905 if (mech->ulParameterLen != sizeof(*pbkdf2)) {
2906 return PR_FALSE0;
2907 }
2908 if (pbkdf2 == NULL((void*)0)) {
2909 return PR_FALSE0;
2910 }
2911 if (pbkdf2->iterations < 1000) {
2912 return PR_FALSE0;
2913 }
2914 if (pbkdf2->ulSaltSourceDataLen < 16) {
2915 return PR_FALSE0;
2916 }
2917 if (pbkdf2->ulPasswordLen < SFTKFIPS_PBKDF2_MIN_PW_LEN) {
2918 return PR_FALSE0;
2919 }
2920 return PR_TRUE1;
2921 }
2922 /* check the hash mechanisms to make sure they themselves are FIPS */
2923 case SFTKFIPSChkHashSp800:
2924 allowCMAC = PR_TRUE1;
2925 /* fallthrough... will pick up allowSmall as well */
2926 case SFTKFIPSChkHash:
2927 allowSmall = PR_TRUE1;
2928 /* fallthrough */
2929 case SFTKFIPSChkHashTls:
2930 if (mech->ulParameterLen < mechInfo->offset + sizeof(CK_ULONG)) {
2931 return PR_FALSE0;
2932 }
2933 return sftk_checkFIPSHash(*(CK_MECHANISM_TYPE *)(((char *)mech->pParameter) + mechInfo->offset),
2934 allowSmall, allowCMAC);
2935 case SFTKFIPSTlsKeyCheck:
2936 if (mech->mechanism != CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256((0x80000000UL | 0x4E534350) + 23)) {
2937 /* unless the mechnism has a built-in hash, check the hash */
2938 if (mech->ulParameterLen < mechInfo->offset + sizeof(CK_ULONG)) {
2939 return PR_FALSE0;
2940 }
2941 if (!sftk_checkFIPSHash(*(CK_MECHANISM_TYPE *)(((char *)mech->pParameter) + mechInfo->offset),
2942 PR_FALSE0, PR_FALSE0)) {
2943 return PR_FALSE0;
2944 }
2945 }
2946 return sftk_checkKeyLength(targetKeyLength, 112, 512, 1);
2947 case SFTKFIPSRSAOAEP: {
2948 CK_RSA_PKCS_OAEP_PARAMS *rsaoaep = (CK_RSA_PKCS_OAEP_PARAMS *)
2949 mech->pParameter;
2950
2951 HASH_HashType hash_msg = sftk_GetHashTypeFromMechanism(rsaoaep->hashAlg);
2952 HASH_HashType hash_pad = sftk_GetHashTypeFromMechanism(rsaoaep->mgf);
2953 /* message hash and mask generation function must be the same */
2954 if (hash_pad != hash_msg)
2955 return PR_FALSE0;
2956
2957 return sftk_checkFIPSHash(rsaoaep->hashAlg, PR_FALSE0, PR_FALSE0);
2958 }
2959 default:
2960 break;
2961 }
2962 /* if we didn't understand the special processing, mark it non-fips */
2963 return PR_FALSE0;
2964}
2965#endif
2966
2967PRBool
2968sftk_operationIsFIPS(SFTKSlot *slot, CK_MECHANISM *mech, CK_ATTRIBUTE_TYPE op,
2969 SFTKObject *source, CK_ULONG targetKeyLength)
2970{
2971#ifndef NSS_HAS_FIPS_INDICATORS
2972 return PR_FALSE0;
2973#else
2974 int i;
2975 CK_FLAGS opFlags;
2976 CK_ULONG keyLength;
2977
2978 /* handle all the quick stuff first */
2979 if (!sftk_isFIPS(slot->slotID)(((slot->slotID) == 3) || ((slot->slotID) >= 101))) {
2980 return PR_FALSE0;
2981 }
2982 if (source && !sftk_hasFIPS(source)) {
2983 return PR_FALSE0;
2984 }
2985 if (mech == NULL((void*)0)) {
2986 return PR_FALSE0;
2987 }
2988
2989 /* now get the calculated values */
2990 opFlags = sftk_AttributeToFlags(op);
2991 if (opFlags == 0) {
2992 return PR_FALSE0;
2993 }
2994 keyLength = sftk_getKeyLength(source);
2995
2996 /* check against our algorithm array */
2997 for (i = 0; i < SFTK_NUMBER_FIPS_ALGORITHMS; i++) {
2998 SFTKFIPSAlgorithmList *mechs = &sftk_fips_mechs[i];
2999 /* if we match the number of records exactly, then we are an
3000 * approved algorithm in the approved mode with an approved key */
3001 if ((mech->mechanism == mechs->type) &&
3002 (opFlags == (mechs->info.flags & opFlags)) &&
3003 sftk_checkKeyLength(keyLength, mechs->info.ulMinKeySize,
3004 mechs->info.ulMaxKeySize, mechs->step) &&
3005 ((targetKeyLength == 0) || (mechs->special == SFTKFIPSTlsKeyCheck) || sftk_checkKeyLength(targetKeyLength, mechs->info.ulMinKeySize, mechs->info.ulMaxKeySize, mechs->step)) &&
3006 ((mechs->special == SFTKFIPSNone) ||
3007 sftk_handleSpecial(slot, mech, mechs, source, keyLength, targetKeyLength))) {
3008 return PR_TRUE1;
3009 }
3010 }
3011 return PR_FALSE0;
3012#endif
3013}
3014
3015void
3016sftk_setFIPS(SFTKObject *obj, PRBool isFIPS)
3017{
3018 if (isFIPS) {
3019 obj->validation_value |= SFTK_VALIDATION_FIPS_FLAG0x00000001L;
3020 } else {
3021 obj->validation_value &= ~SFTK_VALIDATION_FIPS_FLAG0x00000001L;
3022 }
3023}
3024
3025PRBool
3026sftk_hasFIPS(SFTKObject *obj)
3027{
3028 return (obj->validation_value & SFTK_VALIDATION_FIPS_FLAG0x00000001L) ? PR_TRUE1 : PR_FALSE0;
3029}
3030
3031/*
3032 * create the FIPS Validation objects. If the vendor
3033 * doesn't supply an NSS_FIPS_MODULE_ID, at compile time,
3034 * then we assumethis is an unvalidated module.
3035 */
3036CK_RV
3037sftk_CreateValidationObjects(SFTKSlot *slot)
3038{
3039 const char *module_id;
3040 int module_id_len;
3041 CK_RV crv = CKR_OK0x00000000UL;
3042 /* we currently use both vendor specific values and PKCS #11 v3.2
3043 * values for compatibility for a couple more ESR releases. Then we can
3044 * drop the vendor specific ones */
3045 CK_OBJECT_CLASS cko_nss_validation = CKO_NSS_VALIDATION((0x80000000UL | 0x4E534350) + 7);
3046 CK_OBJECT_CLASS cko_validation = CKO_VALIDATION0x0000000aUL;
3047 CK_NSS_VALIDATION_TYPE ckv_fips = CKV_NSS_FIPS_140((0x80000000UL | 0x4E534350) + 1);
3048 CK_FLAGS fipsFlag = SFTK_VALIDATION_FIPS_FLAG0x00000001L;
3049 CK_VALIDATION_TYPE swValidationType = CKV_TYPE_SOFTWARE0x00000001UL;
3050 CK_VALIDATION_AUTHORITY_TYPE nistValidationAuthority =
3051 CKV_AUTHORITY_TYPE_NIST_CMVP0x00000001UL;
3052 CK_UTF8CHAR us[] = { 'U', 'S' };
3053 CK_VERSION fips_version = { 3, 0 }; /* FIPS-140-3 */
3054 CK_ULONG fips_level = 1; /* or 2 if you validated at level 2 */
3055
3056#ifndef NSS_FIPS_MODULE_ID"Generic NSS " "3.128" " Basic ECC" " Unvalidated"
3057#define NSS_FIPS_MODULE_ID"Generic NSS " "3.128" " Basic ECC" " Unvalidated" "Generic NSS " SOFTOKEN_VERSION"3.128" " Basic ECC" " Unvalidated"
3058#endif
3059 module_id = NSS_FIPS_MODULE_ID"Generic NSS " "3.128" " Basic ECC" " Unvalidated";
3060 module_id_len = sizeof(NSS_FIPS_MODULE_ID"Generic NSS " "3.128" " Basic ECC" " Unvalidated") - 1;
3061 SFTKObject *object;
3062
3063 object = sftk_NewObject(slot); /* fill in the handle later */
3064 if (object == NULL((void*)0)) {
3065 return CKR_HOST_MEMORY0x00000002UL;
3066 }
3067 sftk_setFIPS(object, PR_FALSE0);
3068
3069 crv = sftk_AddAttributeType(object, CKA_CLASS0x00000000UL, &cko_nss_validation,
3070 sizeof(cko_nss_validation));
3071 if (crv != CKR_OK0x00000000UL) {
3072 goto loser;
3073 }
3074 crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_TYPE((0x80000000UL | 0x4E534350) + 36),
3075 &ckv_fips, sizeof(ckv_fips));
3076 if (crv != CKR_OK0x00000000UL) {
3077 goto loser;
3078 }
3079 crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_VERSION((0x80000000UL | 0x4E534350) + 37),
3080 &fips_version, sizeof(fips_version));
3081 if (crv != CKR_OK0x00000000UL) {
3082 goto loser;
3083 }
3084 crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_LEVEL((0x80000000UL | 0x4E534350) + 38),
3085 &fips_level, sizeof(fips_level));
3086 if (crv != CKR_OK0x00000000UL) {
3087 goto loser;
3088 }
3089 crv = sftk_AddAttributeType(object, CKA_NSS_VALIDATION_MODULE_ID((0x80000000UL | 0x4E534350) + 39),
3090 module_id, module_id_len);
3091 if (crv != CKR_OK0x00000000UL) {
3092 goto loser;
3093 }
3094
3095 object->handle = sftk_getNextHandle(slot);
3096 object->slot = slot;
3097 sftk_AddObject(&slot->moduleObjects, object);
3098 sftk_FreeObject(object);
3099
3100 object = sftk_NewObject(slot); /* fill in the handle later */
3101 if (object == NULL((void*)0)) {
3102 return CKR_HOST_MEMORY0x00000002UL;
3103 }
3104 sftk_setFIPS(object, PR_FALSE0);
3105 crv = sftk_AddAttributeType(object, CKA_CLASS0x00000000UL, &cko_validation,
3106 sizeof(cko_validation));
3107 if (crv != CKR_OK0x00000000UL) {
3108 goto loser;
3109 }
3110 crv = sftk_AddAttributeType(object, CKA_VALIDATION_TYPE0x0000061fUL,
3111 &swValidationType, sizeof(swValidationType));
3112 if (crv != CKR_OK0x00000000UL) {
3113 goto loser;
3114 }
3115 crv = sftk_AddAttributeType(object, CKA_VALIDATION_VERSION0x00000620UL,
3116 &fips_version, sizeof(fips_version));
3117 if (crv != CKR_OK0x00000000UL) {
3118 goto loser;
3119 }
3120 crv = sftk_AddAttributeType(object, CKA_VALIDATION_LEVEL0x00000621UL,
3121 &fips_level, sizeof(fips_level));
3122 if (crv != CKR_OK0x00000000UL) {
3123 goto loser;
3124 }
3125 crv = sftk_AddAttributeType(object, CKA_VALIDATION_MODULE_ID0x00000622UL,
3126 module_id, module_id_len);
3127 if (crv != CKR_OK0x00000000UL) {
3128 goto loser;
3129 }
3130 crv = sftk_AddAttributeType(object, CKA_VALIDATION_FLAG0x00000623UL,
3131 &fipsFlag, sizeof(fipsFlag));
3132 if (crv != CKR_OK0x00000000UL) {
3133 goto loser;
3134 }
3135 crv = sftk_AddAttributeType(object, CKA_VALIDATION_AUTHORITY_TYPE0x00000624UL,
3136 &nistValidationAuthority,
3137 sizeof(nistValidationAuthority));
3138 if (crv != CKR_OK0x00000000UL) {
3139 goto loser;
3140 }
3141 crv = sftk_AddAttributeType(object, CKA_VALIDATION_COUNTRY0x00000625UL, us, sizeof(us));
3142 if (crv != CKR_OK0x00000000UL) {
3143 goto loser;
3144 }
3145 crv = sftk_AddAttributeType(object, CKA_VALIDATION_CERTIFICATE_IDENTIFIER0x00000626UL,
3146 NULL((void*)0), 0);
3147 if (crv != CKR_OK0x00000000UL) {
3148 goto loser;
3149 }
3150 crv = sftk_AddAttributeType(object, CKA_VALIDATION_CERTIFICATE_URI0x00000627UL,
3151 NULL((void*)0), 0);
3152 if (crv != CKR_OK0x00000000UL) {
3153 goto loser;
3154 }
3155 crv = sftk_AddAttributeType(object, CKA_VALIDATION_PROFILE0x00000629UL,
3156 NULL((void*)0), 0);
3157 if (crv != CKR_OK0x00000000UL) {
3158 goto loser;
3159 }
3160 crv = sftk_AddAttributeType(object, CKA_VALIDATION_VENDOR_URI0x00000628UL,
3161 NULL((void*)0), 0);
3162 if (crv != CKR_OK0x00000000UL) {
3163 goto loser;
3164 }
3165 /* future, fill in validation certificate information from a supplied
3166 * pointer to a config file */
3167 object->handle = sftk_getNextHandle(slot);
3168 object->slot = slot;
3169 sftk_AddObject(&slot->moduleObjects, object);
3170loser:
3171 sftk_FreeObject(object);
3172
3173 return crv;
3174}