Bug Summary

File:root/firefox-clang/security/nss/lib/pk11wrap/pk11slot.c
Warning:line 1488, column 17
Value stored to 'crv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pk11slot.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/pk11wrap/pk11wrap_pk11wrap -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/pk11wrap/pk11wrap_pk11wrap -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG -D SHLIB_SUFFIX="so" -D SHLIB_PREFIX="lib" -D NSS_SHLIB_VERSION="3" -D SOFTOKEN_SHLIB_VERSION="3" -D NSS_FIPS_DISABLED -D NSS_NO_INIT_SUPPORT -D NSS_X86_OR_X64 -D NSS_X64 -D NSS_USE_64 -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -D LINUX2_1 -D LINUX -D linux -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D HAVE_STRERROR -D XP_UNIX -D _REENTRANT -D NSS_DISABLE_DBM -D NSS_DISABLE_LIBPKIX -D NSS_USE_PKCS5_PBKD2_PARAMS2_ONLY -D SOFTOKEN_USE_PKCS5_PBKD2_PARAMS2_ONLY -I /root/firefox-clang/security/nss/lib/pk11wrap -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/lib/pk11wrap/pk11wrap_pk11wrap -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/private/nss -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-character-conversion -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-10-17-231001-351276-1 -x c /root/firefox-clang/security/nss/lib/pk11wrap/pk11slot.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 * Deal with PKCS #11 Slots.
6 */
7
8#include <stddef.h>
9
10#include "seccomon.h"
11#include "secmod.h"
12#include "secmodi.h"
13#include "secmodti.h"
14#include "pkcs11t.h"
15#include "pk11func.h"
16#include "secitem.h"
17#include "secerr.h"
18
19#include "dev.h"
20#include "dev3hack.h"
21#include "pkim.h"
22#include "utilpars.h"
23#include "pkcs11uri.h"
24
25/*************************************************************
26 * local static and global data
27 *************************************************************/
28
29/*
30 * This array helps parsing between names, mechanisms, and flags.
31 * to make the config files understand more entries, add them
32 * to this table.
33 */
34const PK11DefaultArrayEntry PK11_DefaultArray[] = {
35 { "RSA", SECMOD_RSA_FLAG0x00000001L, CKM_RSA_PKCS0x00000001UL },
36 { "DSA", SECMOD_DSA_FLAG0x00000002L, CKM_DSA0x00000011UL },
37 { "ECC", SECMOD_ECC_FLAG0x00040000L, CKM_ECDSA0x00001041UL },
38 { "EDDSA", SECMOD_ECC_FLAG0x00040000L, CKM_EDDSA0x00001057UL },
39 { "DH", SECMOD_DH_FLAG0x00000020L, CKM_DH_PKCS_DERIVE0x00000021UL },
40 { "RC2", SECMOD_RC2_FLAG0x00000004L, CKM_RC2_CBC0x00000102UL },
41 { "RC4", SECMOD_RC4_FLAG0x00000008L, CKM_RC40x00000111UL },
42 { "DES", SECMOD_DES_FLAG0x00000010L, CKM_DES_CBC0x00000122UL },
43 { "AES", SECMOD_AES_FLAG0x00002000L, CKM_AES_CBC0x00001082UL },
44 { "Camellia", SECMOD_CAMELLIA_FLAG0x00010000L, CKM_CAMELLIA_CBC0x00000552UL },
45 { "SEED", SECMOD_SEED_FLAG0x00020000L, CKM_SEED_CBC0x00000652UL },
46 { "RC5", SECMOD_RC5_FLAG0x00000080L, CKM_RC5_CBC0x00000332UL },
47 { "SHA-1", SECMOD_SHA1_FLAG0x00000100L, CKM_SHA_10x00000220UL },
48 /* { "SHA224", SECMOD_SHA256_FLAG, CKM_SHA224 }, */
49 { "SHA256", SECMOD_SHA256_FLAG0x00004000L, CKM_SHA2560x00000250UL },
50 /* { "SHA384", SECMOD_SHA512_FLAG, CKM_SHA384 }, */
51 { "SHA512", SECMOD_SHA512_FLAG0x00008000L, CKM_SHA5120x00000270UL },
52 { "MD5", SECMOD_MD5_FLAG0x00000200L, CKM_MD50x00000210UL },
53 { "MD2", SECMOD_MD2_FLAG0x00000400L, CKM_MD20x00000200UL },
54 { "SSL", SECMOD_SSL_FLAG0x00000800L, CKM_SSL3_PRE_MASTER_KEY_GEN0x00000370UL },
55 { "TLS", SECMOD_TLS_FLAG0x00001000L, CKM_TLS_MASTER_KEY_DERIVE0x00000375UL },
56 { "SKIPJACK", SECMOD_FORTEZZA_FLAG0x00000040L, CKM_SKIPJACK_CBC640x00001002UL },
57 { "Publicly-readable certs", SECMOD_FRIENDLY_FLAG0x10000000L, CKM_INVALID_MECHANISM0xffffffffUL },
58 { "Random Num Generator", SECMOD_RANDOM_FLAG0x80000000L, CKM_FAKE_RANDOM0x80000efeUL },
59 { "ML-DSA", SECMOD_MLDSA_FLAG0x00080000L, CKM_ML_DSA0x0000001dUL },
60};
61const int num_pk11_default_mechanisms =
62 sizeof(PK11_DefaultArray) / sizeof(PK11_DefaultArray[0]);
63
64const PK11DefaultArrayEntry *
65PK11_GetDefaultArray(int *size)
66{
67 if (size) {
68 *size = num_pk11_default_mechanisms;
69 }
70 return PK11_DefaultArray;
71}
72
73/*
74 * These slotlists are lists of modules which provide default support for
75 * a given algorithm or mechanism.
76 */
77static PK11SlotList
78 pk11_seedSlotList,
79 pk11_camelliaSlotList,
80 pk11_aesSlotList,
81 pk11_desSlotList,
82 pk11_rc4SlotList,
83 pk11_rc2SlotList,
84 pk11_rc5SlotList,
85 pk11_sha1SlotList,
86 pk11_md5SlotList,
87 pk11_md2SlotList,
88 pk11_rsaSlotList,
89 pk11_dsaSlotList,
90 pk11_dhSlotList,
91 pk11_ecSlotList,
92 pk11_ideaSlotList,
93 pk11_sslSlotList,
94 pk11_tlsSlotList,
95 pk11_randomSlotList,
96 pk11_sha256SlotList,
97 pk11_sha512SlotList, /* slots do SHA512 and SHA384 */
98 pk11_mldsaSlotList;
99
100/************************************************************
101 * Generic Slot List and Slot List element manipulations
102 ************************************************************/
103
104/*
105 * allocate a new list
106 */
107PK11SlotList *
108PK11_NewSlotList(void)
109{
110 PK11SlotList *list;
111
112 list = (PK11SlotList *)PORT_AllocPORT_Alloc_Util(sizeof(PK11SlotList));
113 if (list == NULL((void*)0))
114 return NULL((void*)0);
115 list->head = NULL((void*)0);
116 list->tail = NULL((void*)0);
117 list->lock = PR_NewLock();
118 if (list->lock == NULL((void*)0)) {
119 PORT_FreePORT_Free_Util(list);
120 return NULL((void*)0);
121 }
122
123 return list;
124}
125
126/*
127 * free a list element when all the references go away.
128 */
129SECStatus
130PK11_FreeSlotListElement(PK11SlotList *list, PK11SlotListElement *le)
131{
132 PRBool freeit = PR_FALSE0;
133
134 if (list == NULL((void*)0) || le == NULL((void*)0)) {
135 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
136 return SECFailure;
137 }
138
139 PR_Lock(list->lock);
140 PORT_ReleaseAssert(le->refCount > 0)((le->refCount > 0) ? ((void)0) : PR_Assert("le->refCount > 0"
, "/root/firefox-clang/security/nss/lib/pk11wrap/pk11slot.c",
140))
;
141 if (le->refCount-- == 1) {
142 freeit = PR_TRUE1;
143 }
144 PR_Unlock(list->lock);
145 if (freeit) {
146 PK11_FreeSlot(le->slot);
147 PORT_FreePORT_Free_Util(le);
148 }
149 return SECSuccess;
150}
151
152static void
153pk11_FreeSlotListStatic(PK11SlotList *list)
154{
155 PK11SlotListElement *le, *next;
156 if (list == NULL((void*)0))
157 return;
158
159 for (le = list->head; le; le = next) {
160 next = le->next;
161 PK11_FreeSlotListElement(list, le);
162 }
163 if (list->lock) {
164 PR_DestroyLock(list->lock);
165 }
166 list->lock = NULL((void*)0);
167 list->head = NULL((void*)0);
168 list->tail = NULL((void*)0);
169}
170
171/*
172 * if we are freeing the list, we must be the only ones with a pointer
173 * to the list.
174 */
175void
176PK11_FreeSlotList(PK11SlotList *list)
177{
178 pk11_FreeSlotListStatic(list);
179 PORT_FreePORT_Free_Util(list);
180}
181
182/*
183 * add a slot to a list
184 * "slot" is the slot to be added. Ownership is not transferred.
185 * "sorted" indicates whether or not the slot should be inserted according to
186 * cipherOrder of the associated module. PR_FALSE indicates that the slot
187 * should be inserted to the head of the list.
188 */
189SECStatus
190PK11_AddSlotToList(PK11SlotList *list, PK11SlotInfo *slot, PRBool sorted)
191{
192 PK11SlotListElement *le;
193 PK11SlotListElement *element;
194
195 le = (PK11SlotListElement *)PORT_AllocPORT_Alloc_Util(sizeof(PK11SlotListElement));
196 if (le == NULL((void*)0))
197 return SECFailure;
198
199 le->slot = PK11_ReferenceSlot(slot);
200 le->prev = NULL((void*)0);
201 le->refCount = 1;
202 PR_Lock(list->lock);
203 element = list->head;
204 /* Insertion sort, with higher cipherOrders are sorted first in the list */
205 while (element && sorted && (element->slot->module->cipherOrder > le->slot->module->cipherOrder)) {
206 element = element->next;
207 }
208 if (element) {
209 le->prev = element->prev;
210 element->prev = le;
211 le->next = element;
212 } else {
213 le->prev = list->tail;
214 le->next = NULL((void*)0);
215 list->tail = le;
216 }
217 if (le->prev)
218 le->prev->next = le;
219 if (list->head == element)
220 list->head = le;
221 PR_Unlock(list->lock);
222
223 return SECSuccess;
224}
225
226/*
227 * remove a slot entry from the list
228 */
229SECStatus
230PK11_DeleteSlotFromList(PK11SlotList *list, PK11SlotListElement *le)
231{
232 PR_Lock(list->lock);
233 if (le->prev)
234 le->prev->next = le->next;
235 else
236 list->head = le->next;
237 if (le->next)
238 le->next->prev = le->prev;
239 else
240 list->tail = le->prev;
241 le->next = le->prev = NULL((void*)0);
242 PR_Unlock(list->lock);
243 PK11_FreeSlotListElement(list, le);
244 return SECSuccess;
245}
246
247/*
248 * Move a list to the end of the target list.
249 * NOTE: There is no locking here... This assumes BOTH lists are private copy
250 * lists. It also does not re-sort the target list.
251 */
252SECStatus
253pk11_MoveListToList(PK11SlotList *target, PK11SlotList *src)
254{
255 if (src->head == NULL((void*)0))
256 return SECSuccess;
257
258 if (target->tail == NULL((void*)0)) {
259 target->head = src->head;
260 } else {
261 target->tail->next = src->head;
262 }
263 src->head->prev = target->tail;
264 target->tail = src->tail;
265 src->head = src->tail = NULL((void*)0);
266 return SECSuccess;
267}
268
269/*
270 * get an element safely from the list. This just makes sure that if
271 * this element is not deleted while we deal with it.
272 */
273PK11SlotListElement *
274PK11_GetFirstSafe(PK11SlotList *list)
275{
276 PK11SlotListElement *le;
277
278 PR_Lock(list->lock);
279 le = list->head;
280 if (le != NULL((void*)0))
281 (le)->refCount++;
282 PR_Unlock(list->lock);
283 return le;
284}
285
286/*
287 * NOTE: if this element gets deleted, we can no longer safely traverse using
288 * it's pointers. We can either terminate the loop, or restart from the
289 * beginning. This is controlled by the restart option.
290 */
291PK11SlotListElement *
292PK11_GetNextSafe(PK11SlotList *list, PK11SlotListElement *le, PRBool restart)
293{
294 PK11SlotListElement *new_le;
295 PR_Lock(list->lock);
296 new_le = le->next;
297 if (le->next == NULL((void*)0)) {
298 /* if the prev and next fields are NULL then either this element
299 * has been removed and we need to walk the list again (if restart
300 * is true) or this was the only element on the list */
301 if ((le->prev == NULL((void*)0)) && restart && (list->head != le)) {
302 new_le = list->head;
303 }
304 }
305 if (new_le)
306 new_le->refCount++;
307 PR_Unlock(list->lock);
308 PK11_FreeSlotListElement(list, le);
309 return new_le;
310}
311
312/*
313 * Find the element that holds this slot
314 */
315PK11SlotListElement *
316PK11_FindSlotElement(PK11SlotList *list, PK11SlotInfo *slot)
317{
318 PK11SlotListElement *le;
319
320 for (le = PK11_GetFirstSafe(list); le;
321 le = PK11_GetNextSafe(list, le, PR_TRUE1)) {
322 if (le->slot == slot)
323 return le;
324 }
325 return NULL((void*)0);
326}
327
328/* like PORT_Memcmp, return -1 if the version is less then the
329 * passed in version, 0 if it's equal to and 1 if it's greater than
330 * the passed in version, PKCS #11 returns versions in 2 places,
331 * once in the function table and once in the module. the former
332 * is good to determine if it is safe to call a new function,
333 * the latter is good for module functionality */
334PRInt32
335PK11_CheckPKCS11Version(PK11SlotInfo *slot, CK_BYTE major, CK_BYTE minor,
336 PRBool useFunctionTable)
337{
338 CK_VERSION version = useFunctionTable ? PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->version : slot->module->cryptokiVersion;
339
340 if (version.major < major) {
341 return -1;
342 } else if (version.major > major) {
343 return 1;
344 } else if (version.minor < minor) {
345 return -1;
346 } else if (version.minor > minor) {
347 return 1;
348 }
349 /* if we get here, they must both be equal */
350 return 0;
351}
352
353/************************************************************
354 * Generic Slot Utilities
355 ************************************************************/
356/*
357 * Create a new slot structure
358 */
359PK11SlotInfo *
360PK11_NewSlotInfo(SECMODModule *mod)
361{
362 PK11SlotInfo *slot;
363
364 slot = (PK11SlotInfo *)PORT_AllocPORT_Alloc_Util(sizeof(PK11SlotInfo));
365 if (slot == NULL((void*)0)) {
366 return slot;
367 }
368 slot->freeListLock = PR_NewLock();
369 if (slot->freeListLock == NULL((void*)0)) {
370 PORT_FreePORT_Free_Util(slot);
371 return NULL((void*)0);
372 }
373 slot->nssTokenLock = PR_NewLock();
374 if (slot->nssTokenLock == NULL((void*)0)) {
375 PR_DestroyLock(slot->freeListLock);
376 PORT_FreePORT_Free_Util(slot);
377 return NULL((void*)0);
378 }
379 slot->sessionLock = mod->isThreadSafe ? PR_NewLock() : mod->refLock;
380 if (slot->sessionLock == NULL((void*)0)) {
381 PR_DestroyLock(slot->nssTokenLock);
382 PR_DestroyLock(slot->freeListLock);
383 PORT_FreePORT_Free_Util(slot);
384 return NULL((void*)0);
385 }
386 slot->freeSymKeysWithSessionHead = NULL((void*)0);
387 slot->freeSymKeysHead = NULL((void*)0);
388 slot->keyCount = 0;
389 slot->maxKeyCount = 0;
390 slot->functionList = NULL((void*)0);
391 slot->needTest = PR_TRUE1;
392 slot->isPerm = PR_FALSE0;
393 slot->isHW = PR_FALSE0;
394 slot->isInternal = PR_FALSE0;
395 slot->isThreadSafe = PR_FALSE0;
396 slot->disabled = PR_FALSE0;
397 slot->series = 1;
398 slot->flagSeries = 0;
399 slot->flagState = PR_FALSE0;
400 slot->wrapKey = 0;
401 slot->wrapMechanism = CKM_INVALID_MECHANISM0xffffffffUL;
402 slot->refKeys[0] = CK_INVALID_HANDLE0;
403 slot->reason = PK11_DIS_NONE;
404 slot->readOnly = PR_TRUE1;
405 slot->needLogin = PR_FALSE0;
406 slot->hasRandom = PR_FALSE0;
407 slot->defRWSession = PR_FALSE0;
408 slot->protectedAuthPath = PR_FALSE0;
409 slot->flags = 0;
410 slot->session = CK_INVALID_HANDLE0;
411 slot->slotID = 0;
412 slot->defaultFlags = 0;
413 slot->refCount = 1;
414 slot->askpw = 0;
415 slot->timeout = 0;
416 slot->mechanismList = NULL((void*)0);
417 slot->mechanismCount = 0;
418 slot->cert_array = NULL((void*)0);
419 slot->cert_count = 0;
420 slot->slot_name[0] = 0;
421 slot->token_name[0] = 0;
422 PORT_Memsetmemset(slot->serial, ' ', sizeof(slot->serial));
423 PORT_Memsetmemset(&slot->tokenInfo, 0, sizeof(slot->tokenInfo));
424 slot->module = NULL((void*)0);
425 slot->authTime = LL_ZERO0L;
426 slot->minPassword = 0;
427 slot->maxPassword = 0;
428 slot->hasRootCerts = PR_FALSE0;
429 slot->hasRootTrust = PR_FALSE0;
430 slot->nssToken = NULL((void*)0);
431 slot->profileList = NULL((void*)0);
432 slot->profileCount = 0;
433 slot->validationFIPSFlags = 0;
434 return slot;
435}
436
437/* create a new reference to a slot so it doesn't go away */
438PK11SlotInfo *
439PK11_ReferenceSlot(PK11SlotInfo *slot)
440{
441 PRInt32 refCount = PR_ATOMIC_INCREMENT(&slot->refCount)__sync_add_and_fetch(&slot->refCount, 1);
442 PORT_ReleaseAssert(refCount > 1)((refCount > 1) ? ((void)0) : PR_Assert("refCount > 1",
"/root/firefox-clang/security/nss/lib/pk11wrap/pk11slot.c", 442
))
;
443 return slot;
444}
445
446/* Destroy all info on a slot we have built up */
447void
448PK11_DestroySlot(PK11SlotInfo *slot)
449{
450 /* free up the cached keys and sessions */
451 PK11_CleanKeyList(slot);
452
453 if (slot->functionList) {
454 /* Destroy any cached wrapping keys (see PK11_SetWrapKey). */
455 for (unsigned int i = 0; i < PR_ARRAY_SIZE(slot->refKeys)(sizeof(slot->refKeys) / sizeof((slot->refKeys)[0])); i++) {
456 if (slot->refKeys[i] != CK_INVALID_HANDLE0) {
457 (void)PK11_DestroyObject(slot, slot->refKeys[i]);
458 slot->refKeys[i] = CK_INVALID_HANDLE0;
459 }
460 }
461
462 /* free up all the sessions on this slot */
463 PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))
464 ->C_CloseAllSessions(slot->slotID);
465 }
466
467 if (slot->mechanismList) {
468 PORT_FreePORT_Free_Util(slot->mechanismList);
469 }
470 if (slot->profileList) {
471 PORT_FreePORT_Free_Util(slot->profileList);
472 }
473 if (slot->isThreadSafe && slot->sessionLock) {
474 PR_DestroyLock(slot->sessionLock);
475 }
476 slot->sessionLock = NULL((void*)0);
477 if (slot->freeListLock) {
478 PR_DestroyLock(slot->freeListLock);
479 slot->freeListLock = NULL((void*)0);
480 }
481 if (slot->nssTokenLock) {
482 PR_DestroyLock(slot->nssTokenLock);
483 slot->nssTokenLock = NULL((void*)0);
484 }
485
486 /* finally Tell our parent module that we've gone away so it can unload */
487 if (slot->module) {
488 SECMOD_SlotDestroyModule(slot->module, PR_TRUE1);
489 }
490
491 /* ok, well not quit finally... now we free the memory */
492 PORT_FreePORT_Free_Util(slot);
493}
494
495/* We're all done with the slot, free it */
496void
497PK11_FreeSlot(PK11SlotInfo *slot)
498{
499 PRInt32 refCount = PR_ATOMIC_DECREMENT(&slot->refCount)__sync_sub_and_fetch(&slot->refCount, 1);
500 PORT_ReleaseAssert(refCount >= 0)((refCount >= 0) ? ((void)0) : PR_Assert("refCount >= 0"
, "/root/firefox-clang/security/nss/lib/pk11wrap/pk11slot.c",
500))
;
501 if (refCount == 0) {
502 PK11_DestroySlot(slot);
503 }
504}
505
506void
507PK11_EnterSlotMonitor(PK11SlotInfo *slot)
508{
509 PR_Lock(slot->sessionLock);
510}
511
512void
513PK11_ExitSlotMonitor(PK11SlotInfo *slot)
514{
515 PR_Unlock(slot->sessionLock);
516}
517
518/***********************************************************
519 * Functions to find specific slots.
520 ***********************************************************/
521PRBool
522SECMOD_HasRootCerts(void)
523{
524 SECMODModuleList *mlp;
525 SECMODModuleList *modules;
526 SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
527 int i;
528 PRBool found = PR_FALSE0;
529
530 if (!moduleLock) {
531 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NOT_INITIALIZED);
532 return found;
533 }
534
535 /* work through all the slots */
536 SECMOD_GetReadLock(moduleLock);
537 modules = SECMOD_GetDefaultModuleList();
538 for (mlp = modules; mlp != NULL((void*)0); mlp = mlp->next) {
539 for (i = 0; i < mlp->module->slotCount; i++) {
540 PK11SlotInfo *tmpSlot = mlp->module->slots[i];
541 if (PK11_IsPresent(tmpSlot)) {
542 if (tmpSlot->hasRootCerts) {
543 found = PR_TRUE1;
544 break;
545 }
546 }
547 }
548 if (found)
549 break;
550 }
551 SECMOD_ReleaseReadLock(moduleLock);
552
553 return found;
554}
555
556/***********************************************************
557 * Functions to find specific slots.
558 ***********************************************************/
559PK11SlotList *
560PK11_FindSlotsByNames(const char *dllName, const char *slotName,
561 const char *tokenName, PRBool presentOnly)
562{
563 SECMODModuleList *mlp;
564 SECMODModuleList *modules;
565 SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
566 int i;
567 PK11SlotList *slotList = NULL((void*)0);
568 PRUint32 slotcount = 0;
569 SECStatus rv = SECSuccess;
570
571 if (!moduleLock) {
572 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NOT_INITIALIZED);
573 return slotList;
574 }
575
576 slotList = PK11_NewSlotList();
577 if (!slotList) {
578 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY);
579 return slotList;
580 }
581
582 if (((NULL((void*)0) == dllName) || (0 == *dllName)) &&
583 ((NULL((void*)0) == slotName) || (0 == *slotName)) &&
584 ((NULL((void*)0) == tokenName) || (0 == *tokenName))) {
585 /* default to softoken */
586 /* PK11_GetInternalKeySlot increments the refcount on the internal slot,
587 * but so does PK11_AddSlotToList. To avoid erroneously increasing the
588 * refcount twice, we get our own reference to the internal slot and
589 * decrement its refcount when we're done with it. */
590 PK11SlotInfo *internalKeySlot = PK11_GetInternalKeySlot();
591 PK11_AddSlotToList(slotList, internalKeySlot, PR_TRUE1);
592 PK11_FreeSlot(internalKeySlot);
593 return slotList;
594 }
595
596 /* work through all the slots */
597 SECMOD_GetReadLock(moduleLock);
598 modules = SECMOD_GetDefaultModuleList();
599 for (mlp = modules; mlp != NULL((void*)0); mlp = mlp->next) {
600 PORT_Assert(mlp->module)((mlp->module) ? ((void)0) : PR_Assert("mlp->module", "/root/firefox-clang/security/nss/lib/pk11wrap/pk11slot.c"
, 600))
;
601 if (!mlp->module) {
602 rv = SECFailure;
603 break;
604 }
605 if ((!dllName) || (mlp->module->dllName &&
606 (0 == PORT_Strcmpstrcmp(mlp->module->dllName, dllName)))) {
607 for (i = 0; i < mlp->module->slotCount; i++) {
608 PK11SlotInfo *tmpSlot = (mlp->module->slots ? mlp->module->slots[i] : NULL((void*)0));
609 PORT_Assert(tmpSlot)((tmpSlot) ? ((void)0) : PR_Assert("tmpSlot", "/root/firefox-clang/security/nss/lib/pk11wrap/pk11slot.c"
, 609))
;
610 if (!tmpSlot) {
611 rv = SECFailure;
612 break;
613 }
614 if ((PR_FALSE0 == presentOnly || PK11_IsPresent(tmpSlot)) &&
615 ((!tokenName) ||
616 (0 == PORT_Strcmpstrcmp(tmpSlot->token_name, tokenName))) &&
617 ((!slotName) ||
618 (0 == PORT_Strcmpstrcmp(tmpSlot->slot_name, slotName)))) {
619 PK11_AddSlotToList(slotList, tmpSlot, PR_TRUE1);
620 slotcount++;
621 }
622 }
623 }
624 }
625 SECMOD_ReleaseReadLock(moduleLock);
626
627 if ((0 == slotcount) || (SECFailure == rv)) {
628 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_TOKEN);
629 PK11_FreeSlotList(slotList);
630 slotList = NULL((void*)0);
631 }
632
633 if (SECFailure == rv) {
634 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_LIBRARY_FAILURE);
635 }
636
637 return slotList;
638}
639
640typedef PRBool (*PK11SlotMatchFunc)(PK11SlotInfo *slot, const void *arg);
641
642static PRBool
643pk11_MatchSlotByTokenName(PK11SlotInfo *slot, const void *arg)
644{
645 return PORT_Strcmpstrcmp(slot->token_name, arg) == 0;
646}
647
648static PRBool
649pk11_MatchSlotByTokenURI(PK11SlotInfo *slot, const void *arg)
650{
651 return pk11_MatchUriTokenInfo(slot, (PK11URI *)arg);
652}
653
654static PK11SlotInfo *
655pk11_FindSlot(const void *arg, PK11SlotMatchFunc func)
656{
657 SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
658 SECMODModuleList *mlp;
659 SECMODModuleList *modules;
660 int i;
661 PK11SlotInfo *slot = NULL((void*)0);
662
663 if (!moduleLock) {
664 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NOT_INITIALIZED);
665 return slot;
666 }
667 /* work through all the slots */
668 SECMOD_GetReadLock(moduleLock);
669 modules = SECMOD_GetDefaultModuleList();
670 for (mlp = modules; mlp != NULL((void*)0); mlp = mlp->next) {
671 for (i = 0; i < mlp->module->slotCount; i++) {
672 PK11SlotInfo *tmpSlot = mlp->module->slots[i];
673 if (PK11_IsPresent(tmpSlot)) {
674 if (func(tmpSlot, arg)) {
675 slot = PK11_ReferenceSlot(tmpSlot);
676 break;
677 }
678 }
679 }
680 if (slot != NULL((void*)0))
681 break;
682 }
683 SECMOD_ReleaseReadLock(moduleLock);
684
685 if (slot == NULL((void*)0)) {
686 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_TOKEN);
687 }
688
689 return slot;
690}
691
692static PK11SlotInfo *
693pk11_FindSlotByTokenURI(const char *uriString)
694{
695 PK11SlotInfo *slot = NULL((void*)0);
696 PK11URI *uri;
697
698 uri = PK11URI_ParseURI(uriString);
699 if (!uri) {
700 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
701 return slot;
702 }
703
704 slot = pk11_FindSlot(uri, pk11_MatchSlotByTokenURI);
705 PK11URI_DestroyURI(uri);
706 return slot;
707}
708
709PK11SlotInfo *
710PK11_FindSlotByName(const char *name)
711{
712 if ((name == NULL((void*)0)) || (*name == 0)) {
713 return PK11_GetInternalKeySlot();
714 }
715
716 if (!PORT_StrncasecmpPL_strncasecmp(name, "pkcs11:", strlen("pkcs11:"))) {
717 return pk11_FindSlotByTokenURI(name);
718 }
719
720 return pk11_FindSlot(name, pk11_MatchSlotByTokenName);
721}
722
723/*
724 * notification stub. If we ever get interested in any events that
725 * the pkcs11 functions may pass back to use, we can catch them here...
726 * currently pdata is a slotinfo structure.
727 */
728CK_RV
729pk11_notify(CK_SESSION_HANDLE session, CK_NOTIFICATION event,
730 CK_VOID_PTR pdata)
731{
732 return CKR_OK0x00000000UL;
733}
734
735/*
736 * grab a new RW session
737 * !!! has a side effect of grabbing the Monitor if either the slot's default
738 * session is RW or the slot is not thread safe. Monitor is release in function
739 * below
740 */
741CK_SESSION_HANDLE
742PK11_GetRWSession(PK11SlotInfo *slot)
743{
744 CK_SESSION_HANDLE rwsession;
745 CK_RV crv;
746 PRBool haveMonitor = PR_FALSE0;
747
748 if (!slot->isThreadSafe || slot->defRWSession) {
749 PK11_EnterSlotMonitor(slot);
750 haveMonitor = PR_TRUE1;
751 }
752 if (slot->defRWSession) {
753 PORT_Assert(slot->session != CK_INVALID_HANDLE)((slot->session != 0) ? ((void)0) : PR_Assert("slot->session != CK_INVALID_HANDLE"
, "/root/firefox-clang/security/nss/lib/pk11wrap/pk11slot.c",
753))
;
754 if (slot->session != CK_INVALID_HANDLE0)
755 return slot->session;
756 }
757
758 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_OpenSession(slot->slotID,
759 CKF_RW_SESSION0x00000002UL | CKF_SERIAL_SESSION0x00000004UL,
760 slot, pk11_notify, &rwsession);
761 PORT_Assert(rwsession != CK_INVALID_HANDLE || crv != CKR_OK)((rwsession != 0 || crv != 0x00000000UL) ? ((void)0) : PR_Assert
("rwsession != CK_INVALID_HANDLE || crv != CKR_OK", "/root/firefox-clang/security/nss/lib/pk11wrap/pk11slot.c"
, 761))
;
762 if (crv != CKR_OK0x00000000UL || rwsession == CK_INVALID_HANDLE0) {
763 if (crv == CKR_OK0x00000000UL)
764 crv = CKR_DEVICE_ERROR0x00000030UL;
765 if (haveMonitor)
766 PK11_ExitSlotMonitor(slot);
767 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
768 return CK_INVALID_HANDLE0;
769 }
770 if (slot->defRWSession) { /* we have the monitor */
771 slot->session = rwsession;
772 }
773 return rwsession;
774}
775
776PRBool
777PK11_RWSessionHasLock(PK11SlotInfo *slot, CK_SESSION_HANDLE session_handle)
778{
779 PRBool hasLock;
780 hasLock = (PRBool)(!slot->isThreadSafe ||
781 (slot->defRWSession && slot->session != CK_INVALID_HANDLE0));
782 return hasLock;
783}
784
785static PRBool
786pk11_RWSessionIsDefault(PK11SlotInfo *slot, CK_SESSION_HANDLE rwsession)
787{
788 PRBool isDefault;
789 isDefault = (PRBool)(slot->session == rwsession &&
790 slot->defRWSession &&
791 slot->session != CK_INVALID_HANDLE0);
792 return isDefault;
793}
794
795/*
796 * close the rwsession and restore our readonly session
797 * !!! has a side effect of releasing the Monitor if either the slot's default
798 * session is RW or the slot is not thread safe.
799 */
800void
801PK11_RestoreROSession(PK11SlotInfo *slot, CK_SESSION_HANDLE rwsession)
802{
803 PORT_Assert(rwsession != CK_INVALID_HANDLE)((rwsession != 0) ? ((void)0) : PR_Assert("rwsession != CK_INVALID_HANDLE"
, "/root/firefox-clang/security/nss/lib/pk11wrap/pk11slot.c",
803))
;
804 if (rwsession != CK_INVALID_HANDLE0) {
805 PRBool doExit = PK11_RWSessionHasLock(slot, rwsession);
806 if (!pk11_RWSessionIsDefault(slot, rwsession))
807 PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))
808 ->C_CloseSession(rwsession);
809 if (doExit)
810 PK11_ExitSlotMonitor(slot);
811 }
812}
813
814/************************************************************
815 * Manage the built-In Slot Lists
816 ************************************************************/
817
818/* Init the static built int slot list (should actually integrate
819 * with PK11_NewSlotList */
820static void
821pk11_InitSlotListStatic(PK11SlotList *list)
822{
823 list->lock = PR_NewLock();
824 list->head = NULL((void*)0);
825 list->tail = NULL((void*)0);
826}
827
828/* initialize the system slotlists */
829SECStatus
830PK11_InitSlotLists(void)
831{
832 pk11_InitSlotListStatic(&pk11_seedSlotList);
833 pk11_InitSlotListStatic(&pk11_camelliaSlotList);
834 pk11_InitSlotListStatic(&pk11_aesSlotList);
835 pk11_InitSlotListStatic(&pk11_desSlotList);
836 pk11_InitSlotListStatic(&pk11_rc4SlotList);
837 pk11_InitSlotListStatic(&pk11_rc2SlotList);
838 pk11_InitSlotListStatic(&pk11_rc5SlotList);
839 pk11_InitSlotListStatic(&pk11_md5SlotList);
840 pk11_InitSlotListStatic(&pk11_md2SlotList);
841 pk11_InitSlotListStatic(&pk11_sha1SlotList);
842 pk11_InitSlotListStatic(&pk11_rsaSlotList);
843 pk11_InitSlotListStatic(&pk11_dsaSlotList);
844 pk11_InitSlotListStatic(&pk11_dhSlotList);
845 pk11_InitSlotListStatic(&pk11_ecSlotList);
846 pk11_InitSlotListStatic(&pk11_ideaSlotList);
847 pk11_InitSlotListStatic(&pk11_sslSlotList);
848 pk11_InitSlotListStatic(&pk11_tlsSlotList);
849 pk11_InitSlotListStatic(&pk11_randomSlotList);
850 pk11_InitSlotListStatic(&pk11_sha256SlotList);
851 pk11_InitSlotListStatic(&pk11_sha512SlotList);
852 pk11_InitSlotListStatic(&pk11_mldsaSlotList);
853 return SECSuccess;
854}
855
856void
857PK11_DestroySlotLists(void)
858{
859 pk11_FreeSlotListStatic(&pk11_seedSlotList);
860 pk11_FreeSlotListStatic(&pk11_camelliaSlotList);
861 pk11_FreeSlotListStatic(&pk11_aesSlotList);
862 pk11_FreeSlotListStatic(&pk11_desSlotList);
863 pk11_FreeSlotListStatic(&pk11_rc4SlotList);
864 pk11_FreeSlotListStatic(&pk11_rc2SlotList);
865 pk11_FreeSlotListStatic(&pk11_rc5SlotList);
866 pk11_FreeSlotListStatic(&pk11_md5SlotList);
867 pk11_FreeSlotListStatic(&pk11_md2SlotList);
868 pk11_FreeSlotListStatic(&pk11_sha1SlotList);
869 pk11_FreeSlotListStatic(&pk11_rsaSlotList);
870 pk11_FreeSlotListStatic(&pk11_dsaSlotList);
871 pk11_FreeSlotListStatic(&pk11_dhSlotList);
872 pk11_FreeSlotListStatic(&pk11_ecSlotList);
873 pk11_FreeSlotListStatic(&pk11_ideaSlotList);
874 pk11_FreeSlotListStatic(&pk11_sslSlotList);
875 pk11_FreeSlotListStatic(&pk11_tlsSlotList);
876 pk11_FreeSlotListStatic(&pk11_randomSlotList);
877 pk11_FreeSlotListStatic(&pk11_sha256SlotList);
878 pk11_FreeSlotListStatic(&pk11_sha512SlotList);
879 pk11_FreeSlotListStatic(&pk11_mldsaSlotList);
880 return;
881}
882
883/* return a system slot list based on mechanism */
884PK11SlotList *
885PK11_GetSlotList(CK_MECHANISM_TYPE type)
886{
887/* XXX a workaround for Bugzilla bug #55267 */
888#if defined(HPUX) && defined(__LP64__1)
889 if (CKM_INVALID_MECHANISM0xffffffffUL == type)
890 return NULL((void*)0);
891#endif
892 switch (type) {
893 case CKM_SEED_CBC0x00000652UL:
894 case CKM_SEED_ECB0x00000651UL:
895 return &pk11_seedSlotList;
896 case CKM_CAMELLIA_CBC0x00000552UL:
897 case CKM_CAMELLIA_ECB0x00000551UL:
898 return &pk11_camelliaSlotList;
899 case CKM_AES_CBC0x00001082UL:
900 case CKM_AES_CCM0x00001088UL:
901 case CKM_AES_CTR0x00001086UL:
902 case CKM_AES_CTS0x00001089UL:
903 case CKM_AES_GCM0x00001087UL:
904 case CKM_AES_ECB0x00001081UL:
905 return &pk11_aesSlotList;
906 case CKM_DES_CBC0x00000122UL:
907 case CKM_DES_ECB0x00000121UL:
908 case CKM_DES3_ECB0x00000132UL:
909 case CKM_DES3_CBC0x00000133UL:
910 return &pk11_desSlotList;
911 case CKM_RC40x00000111UL:
912 return &pk11_rc4SlotList;
913 case CKM_RC5_CBC0x00000332UL:
914 return &pk11_rc5SlotList;
915 case CKM_SHA_10x00000220UL:
916 return &pk11_sha1SlotList;
917 case CKM_SHA2240x00000255UL:
918 case CKM_SHA2560x00000250UL:
919 case CKM_SHA3_2240x000002B5UL:
920 case CKM_SHA3_2560x000002B0UL:
921 return &pk11_sha256SlotList;
922 case CKM_SHA3840x00000260UL:
923 case CKM_SHA5120x00000270UL:
924 case CKM_SHA3_3840x000002C0UL:
925 case CKM_SHA3_5120x000002D0UL:
926 return &pk11_sha512SlotList;
927 case CKM_MD50x00000210UL:
928 return &pk11_md5SlotList;
929 case CKM_MD20x00000200UL:
930 return &pk11_md2SlotList;
931 case CKM_RC2_ECB0x00000101UL:
932 case CKM_RC2_CBC0x00000102UL:
933 return &pk11_rc2SlotList;
934 case CKM_RSA_PKCS0x00000001UL:
935 case CKM_RSA_PKCS_KEY_PAIR_GEN0x00000000UL:
936 case CKM_RSA_X_5090x00000003UL:
937 return &pk11_rsaSlotList;
938 case CKM_DSA0x00000011UL:
939 return &pk11_dsaSlotList;
940 case CKM_DH_PKCS_KEY_PAIR_GEN0x00000020UL:
941 case CKM_DH_PKCS_DERIVE0x00000021UL:
942 return &pk11_dhSlotList;
943 case CKM_EDDSA0x00001057UL:
944 case CKM_EC_EDWARDS_KEY_PAIR_GEN0x00001055UL:
945 case CKM_ECDSA0x00001041UL:
946 case CKM_ECDSA_SHA10x00001042UL:
947 case CKM_EC_KEY_PAIR_GEN0x00001040UL: /* aka CKM_ECDSA_KEY_PAIR_GEN */
948 case CKM_NSS_ECDHE_NO_PAIRWISE_CHECK_KEY_PAIR_GEN((0x80000000UL | 0x4E534350) + 47):
949 case CKM_ECDH1_DERIVE0x00001050UL:
950 case CKM_NSS_KYBER_KEY_PAIR_GEN((0x80000000UL | 0x4E534350) + 45): /* Bug 1893029 */
951 case CKM_NSS_KYBER((0x80000000UL | 0x4E534350) + 46):
952 case CKM_NSS_ML_KEM_KEY_PAIR_GEN((0x80000000UL | 0x4E534350) + 48): /* Bug 1893029 */
953 case CKM_NSS_ML_KEM((0x80000000UL | 0x4E534350) + 49):
954 case CKM_ML_KEM_KEY_PAIR_GEN0x0000000fUL: /* Bug 1893029 */
955 case CKM_ML_KEM0x00000017UL:
956 return &pk11_ecSlotList;
957 case CKM_SSL3_PRE_MASTER_KEY_GEN0x00000370UL:
958 case CKM_SSL3_MASTER_KEY_DERIVE0x00000371UL:
959 case CKM_SSL3_SHA1_MAC0x00000381UL:
960 case CKM_SSL3_MD5_MAC0x00000380UL:
961 return &pk11_sslSlotList;
962 case CKM_TLS_MASTER_KEY_DERIVE0x00000375UL:
963 case CKM_TLS_KEY_AND_MAC_DERIVE0x00000376UL:
964 case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256((0x80000000UL | 0x4E534350) + 23):
965 return &pk11_tlsSlotList;
966 case CKM_IDEA_CBC0x00000342UL:
967 case CKM_IDEA_ECB0x00000341UL:
968 return &pk11_ideaSlotList;
969 case CKM_FAKE_RANDOM0x80000efeUL:
970 return &pk11_randomSlotList;
971 case CKM_ML_DSA0x0000001dUL:
972 return &pk11_mldsaSlotList;
973 }
974 return NULL((void*)0);
975}
976
977/*
978 * load the static SlotInfo structures used to select a PKCS11 slot.
979 * preSlotInfo has a list of all the default flags for the slots on this
980 * module.
981 */
982void
983PK11_LoadSlotList(PK11SlotInfo *slot, PK11PreSlotInfo *psi, int count)
984{
985 int i;
986
987 for (i = 0; i < count; i++) {
988 if (psi[i].slotID == slot->slotID)
989 break;
990 }
991
992 if (i == count)
993 return;
994
995 slot->defaultFlags = psi[i].defaultFlags;
996 slot->askpw = psi[i].askpw;
997 slot->timeout = psi[i].timeout;
998 slot->hasRootCerts = psi[i].hasRootCerts;
999
1000 /* if the slot is already disabled, don't load them into the
1001 * default slot lists. We get here so we can save the default
1002 * list value. */
1003 if (slot->disabled)
1004 return;
1005
1006 /* if the user has disabled us, don't load us in */
1007 if (slot->defaultFlags & PK11_DISABLE_FLAG0x40000000L) {
1008 slot->disabled = PR_TRUE1;
1009 slot->reason = PK11_DIS_USER_SELECTED;
1010 /* free up sessions and things?? */
1011 return;
1012 }
1013
1014 for (i = 0; i < num_pk11_default_mechanisms; i++) {
1015 if (slot->defaultFlags & PK11_DefaultArray[i].flag) {
1016 CK_MECHANISM_TYPE mechanism = PK11_DefaultArray[i].mechanism;
1017 PK11SlotList *slotList = PK11_GetSlotList(mechanism);
1018
1019 if (slotList)
1020 PK11_AddSlotToList(slotList, slot, PR_FALSE0);
1021 }
1022 }
1023
1024 return;
1025}
1026
1027/*
1028 * update a slot to its new attribute according to the slot list
1029 * returns: SECSuccess if nothing to do or add/delete is successful
1030 */
1031SECStatus
1032PK11_UpdateSlotAttribute(PK11SlotInfo *slot,
1033 const PK11DefaultArrayEntry *entry,
1034 PRBool add)
1035/* add: PR_TRUE if want to turn on */
1036{
1037 SECStatus result = SECSuccess;
1038 PK11SlotList *slotList = PK11_GetSlotList(entry->mechanism);
1039
1040 if (add) { /* trying to turn on a mechanism */
1041
1042 /* turn on the default flag in the slot */
1043 slot->defaultFlags |= entry->flag;
1044
1045 /* add this slot to the list */
1046 if (slotList != NULL((void*)0))
1047 result = PK11_AddSlotToList(slotList, slot, PR_FALSE0);
1048
1049 } else { /* trying to turn off */
1050
1051 /* turn OFF the flag in the slot */
1052 slot->defaultFlags &= ~entry->flag;
1053
1054 if (slotList) {
1055 /* find the element in the list & delete it */
1056 PK11SlotListElement *le = PK11_FindSlotElement(slotList, slot);
1057
1058 /* remove the slot from the list */
1059 if (le)
1060 result = PK11_DeleteSlotFromList(slotList, le);
1061 }
1062 }
1063 return result;
1064}
1065
1066/*
1067 * clear a slot off of all of it's default list
1068 */
1069void
1070PK11_ClearSlotList(PK11SlotInfo *slot)
1071{
1072 int i;
1073
1074 if (slot->disabled)
1075 return;
1076 if (slot->defaultFlags == 0)
1077 return;
1078
1079 for (i = 0; i < num_pk11_default_mechanisms; i++) {
1080 if (slot->defaultFlags & PK11_DefaultArray[i].flag) {
1081 CK_MECHANISM_TYPE mechanism = PK11_DefaultArray[i].mechanism;
1082 PK11SlotList *slotList = PK11_GetSlotList(mechanism);
1083 PK11SlotListElement *le = NULL((void*)0);
1084
1085 if (slotList)
1086 le = PK11_FindSlotElement(slotList, slot);
1087
1088 if (le) {
1089 PK11_DeleteSlotFromList(slotList, le);
1090 PK11_FreeSlotListElement(slotList, le);
1091 }
1092 }
1093 }
1094}
1095
1096/******************************************************************
1097 * Slot initialization
1098 ******************************************************************/
1099/*
1100 * turn a PKCS11 Static Label into a string
1101 */
1102char *
1103PK11_MakeString(PLArenaPool *arena, char *space,
1104 char *staticString, int stringLen)
1105{
1106 int i;
1107 char *newString;
1108 for (i = (stringLen - 1); i >= 0; i--) {
1109 if (staticString[i] != ' ')
1110 break;
1111 }
1112 /* move i to point to the last space */
1113 i++;
1114 if (arena) {
1115 newString = (char *)PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, i + 1 /* space for NULL */);
1116 } else if (space) {
1117 newString = space;
1118 } else {
1119 newString = (char *)PORT_AllocPORT_Alloc_Util(i + 1 /* space for NULL */);
1120 }
1121 if (newString == NULL((void*)0))
1122 return NULL((void*)0);
1123
1124 if (i)
1125 PORT_Memcpymemcpy(newString, staticString, i);
1126 newString[i] = 0;
1127
1128 return newString;
1129}
1130
1131/*
1132 * check if a null-terminated string matches with a PKCS11 Static Label
1133 */
1134PRBool
1135pk11_MatchString(const char *string,
1136 const char *staticString, size_t staticStringLen)
1137{
1138 size_t i = staticStringLen;
1139
1140 /* move i to point to the last space */
1141 while (i > 0) {
1142 if (staticString[i - 1] != ' ')
1143 break;
1144 i--;
1145 }
1146
1147 if (strlen(string) == i && memcmp(string, staticString, i) == 0) {
1148 return PR_TRUE1;
1149 }
1150
1151 return PR_FALSE0;
1152}
1153
1154/*
1155 * Reads in the slots mechanism list for later use
1156 */
1157SECStatus
1158PK11_ReadMechanismList(PK11SlotInfo *slot)
1159{
1160 CK_ULONG count;
1161 CK_RV crv;
1162 PRUint32 i;
1163
1164 if (slot->mechanismList) {
1165 PORT_FreePORT_Free_Util(slot->mechanismList);
1166 slot->mechanismList = NULL((void*)0);
1167 }
1168 slot->mechanismCount = 0;
1169
1170 if (!slot->isThreadSafe)
1171 PK11_EnterSlotMonitor(slot);
1172 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetMechanismList(slot->slotID, NULL((void*)0), &count);
1173 if (crv != CKR_OK0x00000000UL) {
1174 if (!slot->isThreadSafe)
1175 PK11_ExitSlotMonitor(slot);
1176 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1177 return SECFailure;
1178 }
1179
1180 slot->mechanismList = (CK_MECHANISM_TYPE *)
1181 PORT_AllocPORT_Alloc_Util(count * sizeof(CK_MECHANISM_TYPE));
1182 if (slot->mechanismList == NULL((void*)0)) {
1183 if (!slot->isThreadSafe)
1184 PK11_ExitSlotMonitor(slot);
1185 return SECFailure;
1186 }
1187 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetMechanismList(slot->slotID,
1188 slot->mechanismList, &count);
1189 if (!slot->isThreadSafe)
1190 PK11_ExitSlotMonitor(slot);
1191 if (crv != CKR_OK0x00000000UL) {
1192 PORT_FreePORT_Free_Util(slot->mechanismList);
1193 slot->mechanismList = NULL((void*)0);
1194 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1195 return SECSuccess;
1196 }
1197 slot->mechanismCount = count;
1198 PORT_Memsetmemset(slot->mechanismBits, 0, sizeof(slot->mechanismBits));
1199
1200 for (i = 0; i < count; i++) {
1201 CK_MECHANISM_TYPE mech = slot->mechanismList[i];
1202 if (mech < 0x7ff) {
1203 slot->mechanismBits[mech & 0xff] |= 1 << (mech >> 8);
1204 }
1205 }
1206 return SECSuccess;
1207}
1208
1209static SECStatus
1210pk11_ReadProfileList(PK11SlotInfo *slot)
1211{
1212 CK_ATTRIBUTE findTemp[2];
1213 CK_ATTRIBUTE *attrs;
1214 CK_BBOOL cktrue = CK_TRUE1;
1215 CK_OBJECT_CLASS oclass = CKO_PROFILE0x00000009UL;
1216 size_t tsize;
1217 int objCount;
1218 CK_OBJECT_HANDLE *handles = NULL((void*)0);
1219 int i;
1220
1221 attrs = findTemp;
1222 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue))(attrs)->type = (0x00000001UL); (attrs)->pValue = (&
cktrue); (attrs)->ulValueLen = (sizeof(cktrue));
;
1223 attrs++;
1224 PK11_SETATTRS(attrs, CKA_CLASS, &oclass, sizeof(oclass))(attrs)->type = (0x00000000UL); (attrs)->pValue = (&
oclass); (attrs)->ulValueLen = (sizeof(oclass));
;
1225 attrs++;
1226 tsize = attrs - findTemp;
1227 PORT_Assert(tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE))((tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE)) ? ((void
)0) : PR_Assert("tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE)"
, "/root/firefox-clang/security/nss/lib/pk11wrap/pk11slot.c",
1227))
;
1228
1229 if (slot->profileList) {
1230 PORT_FreePORT_Free_Util(slot->profileList);
1231 slot->profileList = NULL((void*)0);
1232 }
1233 slot->profileCount = 0;
1234
1235 objCount = 0;
1236 handles = pk11_FindObjectsByTemplate(slot, findTemp, tsize, &objCount);
1237 if (handles == NULL((void*)0)) {
1238 if (objCount < 0) {
1239 return SECFailure; /* error code is set */
1240 }
1241 PORT_Assert(objCount == 0)((objCount == 0) ? ((void)0) : PR_Assert("objCount == 0", "/root/firefox-clang/security/nss/lib/pk11wrap/pk11slot.c"
, 1241))
;
1242 return SECSuccess;
1243 }
1244
1245 slot->profileList = (CK_PROFILE_ID *)
1246 PORT_AllocPORT_Alloc_Util(objCount * sizeof(CK_PROFILE_ID));
1247 if (slot->profileList == NULL((void*)0)) {
1248 PORT_FreePORT_Free_Util(handles);
1249 return SECFailure; /* error code is set */
1250 }
1251
1252 for (i = 0; i < objCount; i++) {
1253 CK_ULONG value;
1254
1255 value = PK11_ReadULongAttribute(slot, handles[i], CKA_PROFILE_ID0x00000601UL);
1256 if (value == CK_UNAVAILABLE_INFORMATION(~0UL)) {
1257 continue;
1258 }
1259 slot->profileList[slot->profileCount++] = value;
1260 }
1261
1262 PORT_FreePORT_Free_Util(handles);
1263 return SECSuccess;
1264}
1265
1266static PRBool
1267pk11_HasProfile(PK11SlotInfo *slot, CK_PROFILE_ID id)
1268{
1269 int i;
1270
1271 for (i = 0; i < slot->profileCount; i++) {
1272 if (slot->profileList[i] == id) {
1273 return PR_TRUE1;
1274 }
1275 }
1276 return PR_FALSE0;
1277}
1278
1279static CK_FLAGS
1280pk11_GetValidationFlags(PK11SlotInfo *slot, CK_VALIDATION_AUTHORITY_TYPE auth)
1281{
1282 CK_ATTRIBUTE findTemp[2];
1283 CK_ATTRIBUTE *attrs;
1284 CK_OBJECT_CLASS oclass = CKO_VALIDATION0x0000000aUL;
1285 size_t tsize;
1286 int objCount;
1287 CK_OBJECT_HANDLE *handles = NULL((void*)0);
1288 CK_FLAGS validation_flags = 0;
1289 int i;
1290
1291 /* only used with tokens with verison >= 3.2 */
1292 if (PK11_CheckPKCS11Version(slot, 3, 2, PR_FALSE0) < 0) {
1293 return validation_flags;
1294 }
1295
1296 attrs = findTemp;
1297 PK11_SETATTRS(attrs, CKA_CLASS, &oclass, sizeof(oclass))(attrs)->type = (0x00000000UL); (attrs)->pValue = (&
oclass); (attrs)->ulValueLen = (sizeof(oclass));
;
1298 attrs++;
1299 PK11_SETATTRS(attrs, CKA_VALIDATION_AUTHORITY_TYPE, &auth, sizeof(auth))(attrs)->type = (0x00000624UL); (attrs)->pValue = (&
auth); (attrs)->ulValueLen = (sizeof(auth));
;
1300 attrs++;
1301 tsize = attrs - findTemp;
1302 PORT_Assert(tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE))((tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE)) ? ((void
)0) : PR_Assert("tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE)"
, "/root/firefox-clang/security/nss/lib/pk11wrap/pk11slot.c",
1302))
;
1303
1304 objCount = 0;
1305 handles = pk11_FindObjectsByTemplate(slot, findTemp, tsize, &objCount);
1306 if (handles == NULL((void*)0)) {
1307 /* none found, return or empty flags */
1308 return validation_flags;
1309 }
1310
1311 for (i = 0; i < objCount; i++) {
1312 CK_FLAGS value;
1313 value = PK11_ReadULongAttribute(slot, handles[i], CKA_VALIDATION_FLAG0x00000623UL);
1314 if (value == CK_UNAVAILABLE_INFORMATION(~0UL)) {
1315 continue;
1316 }
1317 validation_flags |= value;
1318 }
1319
1320 PORT_FreePORT_Free_Util(handles);
1321 return validation_flags;
1322}
1323
1324/*
1325 * initialize a new token
1326 * unlike initialize slot, this can be called multiple times in the lifetime
1327 * of NSS. It reads the information associated with a card or token,
1328 * that is not going to change unless the card or token changes.
1329 */
1330SECStatus
1331PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts)
1332{
1333 CK_RV crv;
1334 SECStatus rv;
1335 PRStatus status;
1336 NSSToken *nssToken;
1337
1338 /* set the slot flags to the current token values */
1339 if (!slot->isThreadSafe)
1340 PK11_EnterSlotMonitor(slot);
1341 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetTokenInfo(slot->slotID, &slot->tokenInfo);
1342 if (!slot->isThreadSafe)
1343 PK11_ExitSlotMonitor(slot);
1344 if (crv != CKR_OK0x00000000UL) {
1345 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1346 return SECFailure;
1347 }
1348
1349 /* set the slot flags to the current token values */
1350 slot->series++; /* allow other objects to detect that the
1351 * slot is different */
1352 slot->flags = slot->tokenInfo.flags;
1353 slot->needLogin = ((slot->tokenInfo.flags & CKF_LOGIN_REQUIRED0x00000004UL) ? PR_TRUE1 : PR_FALSE0);
1354 slot->readOnly = ((slot->tokenInfo.flags & CKF_WRITE_PROTECTED0x00000002UL) ? PR_TRUE1 : PR_FALSE0);
1355
1356 slot->hasRandom = ((slot->tokenInfo.flags & CKF_RNG0x00000001UL) ? PR_TRUE1 : PR_FALSE0);
1357 slot->protectedAuthPath =
1358 ((slot->tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH0x00000100UL)
1359 ? PR_TRUE1
1360 : PR_FALSE0);
1361 pk11_SetLastLoginCheck(slot, 0);
1362 slot->lastState = 0;
1363 /* on some platforms Active Card incorrectly sets the
1364 * CKF_PROTECTED_AUTHENTICATION_PATH bit when it doesn't mean to. */
1365 if (slot->isActiveCard) {
1366 slot->protectedAuthPath = PR_FALSE0;
1367 }
1368 (void)PK11_MakeString(NULL((void*)0), slot->token_name,
1369 (char *)slot->tokenInfo.label, sizeof(slot->tokenInfo.label));
1370 slot->minPassword = slot->tokenInfo.ulMinPinLen;
1371 slot->maxPassword = slot->tokenInfo.ulMaxPinLen;
1372 PORT_Memcpymemcpy(slot->serial, slot->tokenInfo.serialNumber, sizeof(slot->serial));
1373
1374 nssToken = PK11Slot_GetNSSToken(slot);
1375 nssToken_UpdateName(nssToken); /* null token is OK */
1376 (void)nssToken_Destroy(nssToken);
1377
1378 slot->defRWSession = (PRBool)((!slot->readOnly) &&
1379 (slot->tokenInfo.ulMaxSessionCount == 1));
1380 rv = PK11_ReadMechanismList(slot);
1381 if (rv != SECSuccess)
1382 return rv;
1383
1384 slot->hasRSAInfo = PR_FALSE0;
1385 slot->RSAInfoFlags = 0;
1386
1387 /* initialize the maxKeyCount value */
1388 PR_Lock(slot->freeListLock);
1389 if (slot->tokenInfo.ulMaxSessionCount == 0) {
1390 slot->maxKeyCount = 800; /* should be #define or a config param */
1391 } else if (slot->tokenInfo.ulMaxSessionCount < 20) {
1392 /* don't have enough sessions to keep that many keys around */
1393 slot->maxKeyCount = 0;
1394 } else {
1395 slot->maxKeyCount = slot->tokenInfo.ulMaxSessionCount / 2;
1396 }
1397 PR_Unlock(slot->freeListLock);
1398
1399 /* Make sure our session handle is valid */
1400 if (slot->session == CK_INVALID_HANDLE0) {
1401 /* we know we don't have a valid session, go get one */
1402 CK_SESSION_HANDLE session;
1403
1404 /* session should be Readonly, serial */
1405 if (!slot->isThreadSafe)
1406 PK11_EnterSlotMonitor(slot);
1407 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_OpenSession(slot->slotID,
1408 (slot->defRWSession ? CKF_RW_SESSION0x00000002UL : 0) | CKF_SERIAL_SESSION0x00000004UL,
1409 slot, pk11_notify, &session);
1410 if (!slot->isThreadSafe)
1411 PK11_ExitSlotMonitor(slot);
1412 if (crv != CKR_OK0x00000000UL) {
1413 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1414 return SECFailure;
1415 }
1416 slot->session = session;
1417 } else {
1418 /* The session we have may be defunct (the token associated with it)
1419 * has been removed */
1420 CK_SESSION_INFO sessionInfo;
1421
1422 if (!slot->isThreadSafe)
1423 PK11_EnterSlotMonitor(slot);
1424 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetSessionInfo(slot->session, &sessionInfo);
1425 if (crv == CKR_DEVICE_ERROR0x00000030UL) {
1426 PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))
1427 ->C_CloseSession(slot->session);
1428 crv = CKR_SESSION_CLOSED0x000000B0UL;
1429 }
1430 if ((crv == CKR_SESSION_CLOSED0x000000B0UL) || (crv == CKR_SESSION_HANDLE_INVALID0x000000B3UL)) {
1431 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_OpenSession(slot->slotID,
1432 (slot->defRWSession ? CKF_RW_SESSION0x00000002UL : 0) | CKF_SERIAL_SESSION0x00000004UL,
1433 slot, pk11_notify, &slot->session);
1434 if (crv != CKR_OK0x00000000UL) {
1435 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1436 slot->session = CK_INVALID_HANDLE0;
1437 if (!slot->isThreadSafe)
1438 PK11_ExitSlotMonitor(slot);
1439 return SECFailure;
1440 }
1441 }
1442 if (!slot->isThreadSafe)
1443 PK11_ExitSlotMonitor(slot);
1444 }
1445
1446 nssToken = PK11Slot_GetNSSToken(slot);
1447 status = nssToken_Refresh(nssToken); /* null token is OK */
1448 (void)nssToken_Destroy(nssToken);
1449 if (status != PR_SUCCESS)
1450 return SECFailure;
1451
1452 /* Not all tokens have profile objects or even recognize what profile
1453 * objects are it's OK for pk11_ReadProfileList to fail */
1454 (void)pk11_ReadProfileList(slot);
1455 slot->validationFIPSFlags =
1456 pk11_GetValidationFlags(slot, CKV_AUTHORITY_TYPE_NIST_CMVP0x00000001UL);
1457
1458 if (!(slot->isInternal) && (slot->hasRandom)) {
1459 /* if this slot has a random number generater, use it to add entropy
1460 * to the internal slot. */
1461 PK11SlotInfo *int_slot = PK11_GetInternalSlot();
1462
1463 if (int_slot) {
1464 unsigned char random_bytes[32];
1465
1466 /* if this slot can issue random numbers, get some entropy from
1467 * that random number generater and give it to our internal token.
1468 */
1469 PK11_EnterSlotMonitor(slot);
1470 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GenerateRandom(slot->session, random_bytes, sizeof(random_bytes));
1471 PK11_ExitSlotMonitor(slot);
1472 if (crv == CKR_OK0x00000000UL) {
1473 PK11_EnterSlotMonitor(int_slot);
1474 PK11_GETTAB(int_slot)((CK_FUNCTION_LIST_3_2_PTR)((int_slot)->functionList))
1475 ->C_SeedRandom(int_slot->session,
1476 random_bytes, sizeof(random_bytes));
1477 PK11_ExitSlotMonitor(int_slot);
1478 }
1479
1480 /* Now return the favor and send entropy to the token's random
1481 * number generater */
1482 PK11_EnterSlotMonitor(int_slot);
1483 crv = PK11_GETTAB(int_slot)((CK_FUNCTION_LIST_3_2_PTR)((int_slot)->functionList))->C_GenerateRandom(int_slot->session,
1484 random_bytes, sizeof(random_bytes));
1485 PK11_ExitSlotMonitor(int_slot);
1486 if (crv == CKR_OK0x00000000UL) {
1487 PK11_EnterSlotMonitor(slot);
1488 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_SeedRandom(slot->session,
Value stored to 'crv' is never read
1489 random_bytes, sizeof(random_bytes));
1490 PK11_ExitSlotMonitor(slot);
1491 }
1492 PK11_FreeSlot(int_slot);
1493 }
1494 }
1495 /* work around a problem in softoken where it incorrectly
1496 * reports databases opened read only as read/write. */
1497 if (slot->isInternal && !slot->readOnly) {
1498 CK_SESSION_HANDLE session = CK_INVALID_HANDLE0;
1499
1500 /* try to open a R/W session */
1501 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_OpenSession(slot->slotID,
1502 CKF_RW_SESSION0x00000002UL | CKF_SERIAL_SESSION0x00000004UL, slot, pk11_notify, &session);
1503 /* what a well behaved token should return if you open
1504 * a RW session on a read only token */
1505 if (crv == CKR_TOKEN_WRITE_PROTECTED0x000000E2UL) {
1506 slot->readOnly = PR_TRUE1;
1507 } else if (crv == CKR_OK0x00000000UL) {
1508 CK_SESSION_INFO sessionInfo;
1509
1510 /* Because of a second bug in softoken, which silently returns
1511 * a RO session, we need to check what type of session we got. */
1512 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetSessionInfo(session, &sessionInfo);
1513 if (crv == CKR_OK0x00000000UL) {
1514 if ((sessionInfo.flags & CKF_RW_SESSION0x00000002UL) == 0) {
1515 /* session was readonly, so this softoken slot must be readonly */
1516 slot->readOnly = PR_TRUE1;
1517 }
1518 }
1519 PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))
1520 ->C_CloseSession(session);
1521 }
1522 }
1523
1524 return SECSuccess;
1525}
1526
1527/*
1528 * initialize a new token
1529 * unlike initialize slot, this can be called multiple times in the lifetime
1530 * of NSS. It reads the information associated with a card or token,
1531 * that is not going to change unless the card or token changes.
1532 */
1533SECStatus
1534PK11_TokenRefresh(PK11SlotInfo *slot)
1535{
1536 CK_RV crv;
1537
1538 /* set the slot flags to the current token values */
1539 if (!slot->isThreadSafe)
1540 PK11_EnterSlotMonitor(slot);
1541 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetTokenInfo(slot->slotID, &slot->tokenInfo);
1542 if (!slot->isThreadSafe)
1543 PK11_ExitSlotMonitor(slot);
1544 if (crv != CKR_OK0x00000000UL) {
1545 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
1546 return SECFailure;
1547 }
1548
1549 slot->flags = slot->tokenInfo.flags;
1550 slot->needLogin = ((slot->tokenInfo.flags & CKF_LOGIN_REQUIRED0x00000004UL) ? PR_TRUE1 : PR_FALSE0);
1551 slot->readOnly = ((slot->tokenInfo.flags & CKF_WRITE_PROTECTED0x00000002UL) ? PR_TRUE1 : PR_FALSE0);
1552 slot->hasRandom = ((slot->tokenInfo.flags & CKF_RNG0x00000001UL) ? PR_TRUE1 : PR_FALSE0);
1553 slot->protectedAuthPath =
1554 ((slot->tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH0x00000100UL)
1555 ? PR_TRUE1
1556 : PR_FALSE0);
1557 /* on some platforms Active Card incorrectly sets the
1558 * CKF_PROTECTED_AUTHENTICATION_PATH bit when it doesn't mean to. */
1559 if (slot->isActiveCard) {
1560 slot->protectedAuthPath = PR_FALSE0;
1561 }
1562 return SECSuccess;
1563}
1564
1565static PRBool
1566pk11_isRootSlot(PK11SlotInfo *slot)
1567{
1568 CK_ATTRIBUTE findTemp[1];
1569 CK_ATTRIBUTE *attrs;
1570 CK_OBJECT_CLASS oclass = CKO_NSS_BUILTIN_ROOT_LIST((0x80000000UL | 0x4E534350) + 4);
1571 size_t tsize;
1572 CK_OBJECT_HANDLE handle;
1573
1574 attrs = findTemp;
1575 PK11_SETATTRS(attrs, CKA_CLASS, &oclass, sizeof(oclass))(attrs)->type = (0x00000000UL); (attrs)->pValue = (&
oclass); (attrs)->ulValueLen = (sizeof(oclass));
;
1576 attrs++;
1577 tsize = attrs - findTemp;
1578 PORT_Assert(tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE))((tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE)) ? ((void
)0) : PR_Assert("tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE)"
, "/root/firefox-clang/security/nss/lib/pk11wrap/pk11slot.c",
1578))
;
1579
1580 handle = pk11_FindObjectByTemplate(slot, findTemp, tsize);
1581 if (handle == CK_INVALID_HANDLE0) {
1582 return PR_FALSE0;
1583 }
1584 return PR_TRUE1;
1585}
1586
1587/*
1588 * Initialize the slot :
1589 * This initialization code is called on each slot a module supports when
1590 * it is loaded. It does the bringup initialization. The difference between
1591 * this and InitToken is Init slot does those one time initialization stuff,
1592 * usually associated with the reader, while InitToken may get called multiple
1593 * times as tokens are removed and re-inserted.
1594 */
1595void
1596PK11_InitSlot(SECMODModule *mod, CK_SLOT_ID slotID, PK11SlotInfo *slot)
1597{
1598 SECStatus rv;
1599 CK_SLOT_INFO slotInfo;
1600
1601 slot->functionList = mod->functionList;
1602 slot->isInternal = mod->internal;
1603 slot->slotID = slotID;
1604 slot->isThreadSafe = mod->isThreadSafe;
1605 slot->hasRSAInfo = PR_FALSE0;
1606 slot->module = mod; /* NOTE: we don't make a reference here because
1607 * modules have references to their slots. This
1608 * works because modules keep implicit references
1609 * from their slots, and won't unload and disappear
1610 * until all their slots have been freed */
1611
1612 if (PK11_GetSlotInfo(slot, &slotInfo) != SECSuccess) {
1613 slot->disabled = PR_TRUE1;
1614 slot->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
1615 return;
1616 }
1617
1618 /* test to make sure claimed mechanism work */
1619 slot->needTest = mod->internal ? PR_FALSE0 : PR_TRUE1;
1620 (void)PK11_MakeString(NULL((void*)0), slot->slot_name,
1621 (char *)slotInfo.slotDescription, sizeof(slotInfo.slotDescription));
1622 slot->isHW = (PRBool)((slotInfo.flags & CKF_HW_SLOT0x00000004UL) == CKF_HW_SLOT0x00000004UL);
1623#define ACTIVE_CARD"ActivCard SA" "ActivCard SA"
1624 slot->isActiveCard = (PRBool)(PORT_Strncmpstrncmp((char *)slotInfo.manufacturerID,
1625 ACTIVE_CARD"ActivCard SA", sizeof(ACTIVE_CARD"ActivCard SA") - 1) == 0);
1626 if ((slotInfo.flags & CKF_REMOVABLE_DEVICE0x00000002UL) == 0) {
1627 slot->isPerm = PR_TRUE1;
1628 /* permanment slots must have the token present always */
1629 if ((slotInfo.flags & CKF_TOKEN_PRESENT0x00000001UL) == 0) {
1630 slot->disabled = PR_TRUE1;
1631 slot->reason = PK11_DIS_TOKEN_NOT_PRESENT;
1632 return; /* nothing else to do */
1633 }
1634 }
1635 /* if the token is present, initialize it */
1636 if ((slotInfo.flags & CKF_TOKEN_PRESENT0x00000001UL) != 0) {
1637 rv = PK11_InitToken(slot, PR_TRUE1);
1638 /* the only hard failures are on permanent devices, or function
1639 * verify failures... function verify failures are already handled
1640 * by tokenInit */
1641 if ((rv != SECSuccess) && (slot->isPerm) && (!slot->disabled)) {
1642 slot->disabled = PR_TRUE1;
1643 slot->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
1644 }
1645 if (rv == SECSuccess && pk11_isRootSlot(slot)) {
1646 if (!slot->hasRootCerts) {
1647 slot->module->trustOrder = 100;
1648 }
1649 slot->hasRootCerts = PR_TRUE1;
1650 }
1651 }
1652 if ((slotInfo.flags & CKF_USER_PIN_INITIALIZED0x00000008UL) != 0) {
1653 slot->flags |= CKF_USER_PIN_INITIALIZED0x00000008UL;
1654 }
1655}
1656
1657/*********************************************************************
1658 * Slot mapping utility functions.
1659 *********************************************************************/
1660
1661/*
1662 * determine if the token is present. If the token is present, make sure
1663 * we have a valid session handle. Also set the value of needLogin
1664 * appropriately.
1665 */
1666static PRBool
1667pk11_IsPresentCertLoad(PK11SlotInfo *slot, PRBool loadCerts)
1668{
1669 CK_SLOT_INFO slotInfo;
1670 CK_SESSION_INFO sessionInfo;
1671 CK_RV crv;
1672
1673 /* disabled slots are never present */
1674 if (slot->disabled) {
1675 return PR_FALSE0;
1676 }
1677
1678 /* permanent slots are always present */
1679 if (slot->isPerm && (slot->session != CK_INVALID_HANDLE0)) {
1680 return PR_TRUE1;
1681 }
1682
1683 NSSToken *nssToken = PK11Slot_GetNSSToken(slot);
1684 if (nssToken) {
1685 PRBool present = nssToken_IsPresent(nssToken);
1686 (void)nssToken_Destroy(nssToken);
1687 return present;
1688 }
1689
1690 /* removable slots have a flag that says they are present */
1691 if (PK11_GetSlotInfo(slot, &slotInfo) != SECSuccess) {
1692 return PR_FALSE0;
1693 }
1694
1695 if ((slotInfo.flags & CKF_TOKEN_PRESENT0x00000001UL) == 0) {
1696 /* if the slot is no longer present, close the session */
1697 if (slot->session != CK_INVALID_HANDLE0) {
1698 if (!slot->isThreadSafe) {
1699 PK11_EnterSlotMonitor(slot);
1700 }
1701 PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))
1702 ->C_CloseSession(slot->session);
1703 slot->session = CK_INVALID_HANDLE0;
1704 if (!slot->isThreadSafe) {
1705 PK11_ExitSlotMonitor(slot);
1706 }
1707 }
1708 return PR_FALSE0;
1709 }
1710
1711 /* use the session Info to determine if the card has been removed and then
1712 * re-inserted */
1713 if (slot->session != CK_INVALID_HANDLE0) {
1714 if (slot->isThreadSafe) {
1715 PK11_EnterSlotMonitor(slot);
1716 }
1717 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetSessionInfo(slot->session, &sessionInfo);
1718 if (crv != CKR_OK0x00000000UL) {
1719 PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))
1720 ->C_CloseSession(slot->session);
1721 slot->session = CK_INVALID_HANDLE0;
1722 }
1723 if (slot->isThreadSafe) {
1724 PK11_ExitSlotMonitor(slot);
1725 }
1726 }
1727
1728 /* card has not been removed, current token info is correct */
1729 if (slot->session != CK_INVALID_HANDLE0)
1730 return PR_TRUE1;
1731
1732 /* initialize the token info state */
1733 if (PK11_InitToken(slot, loadCerts) != SECSuccess) {
1734 return PR_FALSE0;
1735 }
1736
1737 return PR_TRUE1;
1738}
1739
1740/*
1741 * old version of the routine
1742 */
1743PRBool
1744PK11_IsPresent(PK11SlotInfo *slot)
1745{
1746 return pk11_IsPresentCertLoad(slot, PR_TRUE1);
1747}
1748
1749/* is the slot disabled? */
1750PRBool
1751PK11_IsDisabled(PK11SlotInfo *slot)
1752{
1753 return slot->disabled;
1754}
1755
1756/* and why? */
1757PK11DisableReasons
1758PK11_GetDisabledReason(PK11SlotInfo *slot)
1759{
1760 return slot->reason;
1761}
1762
1763/* returns PR_TRUE if successfully disable the slot */
1764/* returns PR_FALSE otherwise */
1765PRBool
1766PK11_UserDisableSlot(PK11SlotInfo *slot)
1767{
1768
1769 /* Prevent users from disabling the internal module. */
1770 if (slot->isInternal) {
1771 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
1772 return PR_FALSE0;
1773 }
1774
1775 slot->defaultFlags |= PK11_DISABLE_FLAG0x40000000L;
1776 slot->disabled = PR_TRUE1;
1777 slot->reason = PK11_DIS_USER_SELECTED;
1778
1779 return PR_TRUE1;
1780}
1781
1782PRBool
1783PK11_UserEnableSlot(PK11SlotInfo *slot)
1784{
1785
1786 slot->defaultFlags &= ~PK11_DISABLE_FLAG0x40000000L;
1787 slot->disabled = PR_FALSE0;
1788 slot->reason = PK11_DIS_NONE;
1789 return PR_TRUE1;
1790}
1791
1792PRBool
1793PK11_HasRootCerts(PK11SlotInfo *slot)
1794{
1795 return slot->hasRootCerts;
1796}
1797
1798/* Get the module this slot is attached to */
1799SECMODModule *
1800PK11_GetModule(PK11SlotInfo *slot)
1801{
1802 return slot->module;
1803}
1804
1805/* return the default flags of a slot */
1806unsigned long
1807PK11_GetDefaultFlags(PK11SlotInfo *slot)
1808{
1809 return slot->defaultFlags;
1810}
1811
1812/*
1813 * The following wrapper functions allow us to export an opaque slot
1814 * function to the rest of libsec and the world... */
1815PRBool
1816PK11_IsReadOnly(PK11SlotInfo *slot)
1817{
1818 return slot->readOnly;
1819}
1820
1821PRBool
1822PK11_IsHW(PK11SlotInfo *slot)
1823{
1824 return slot->isHW;
1825}
1826
1827PRBool
1828PK11_IsRemovable(PK11SlotInfo *slot)
1829{
1830 return !slot->isPerm;
1831}
1832
1833PRBool
1834PK11_IsInternal(PK11SlotInfo *slot)
1835{
1836 return slot->isInternal;
1837}
1838
1839PRBool
1840PK11_IsInternalKeySlot(PK11SlotInfo *slot)
1841{
1842 PK11SlotInfo *int_slot;
1843 PRBool result;
1844
1845 if (!slot->isInternal) {
1846 return PR_FALSE0;
1847 }
1848
1849 int_slot = PK11_GetInternalKeySlot();
1850 result = (int_slot == slot) ? PR_TRUE1 : PR_FALSE0;
1851 PK11_FreeSlot(int_slot);
1852 return result;
1853}
1854
1855PRBool
1856PK11_NeedLogin(PK11SlotInfo *slot)
1857{
1858 return slot->needLogin;
1859}
1860
1861PRBool
1862PK11_IsFriendly(PK11SlotInfo *slot)
1863{
1864 /* internal slot always has public readable certs */
1865 return (PRBool)(slot->isInternal ||
1866 pk11_HasProfile(slot, CKP_PUBLIC_CERTIFICATES_TOKEN0x00000004UL) ||
1867 ((slot->defaultFlags & SECMOD_FRIENDLY_FLAG0x10000000L) ==
1868 SECMOD_FRIENDLY_FLAG0x10000000L));
1869}
1870
1871char *
1872PK11_GetTokenName(PK11SlotInfo *slot)
1873{
1874 return slot->token_name;
1875}
1876
1877char *
1878PK11_GetTokenURI(PK11SlotInfo *slot)
1879{
1880 PK11URI *uri;
1881 char *ret = NULL((void*)0);
1882 char label[32 + 1], manufacturer[32 + 1], serial[16 + 1], model[16 + 1];
1883 PK11URIAttribute attrs[4];
1884 size_t nattrs = 0;
1885
1886 PK11_MakeString(NULL((void*)0), label, (char *)slot->tokenInfo.label,
1887 sizeof(slot->tokenInfo.label));
1888 if (*label != '\0') {
1889 attrs[nattrs].name = PK11URI_PATTR_TOKEN"token";
1890 attrs[nattrs].value = label;
1891 nattrs++;
1892 }
1893
1894 PK11_MakeString(NULL((void*)0), manufacturer, (char *)slot->tokenInfo.manufacturerID,
1895 sizeof(slot->tokenInfo.manufacturerID));
1896 if (*manufacturer != '\0') {
1897 attrs[nattrs].name = PK11URI_PATTR_MANUFACTURER"manufacturer";
1898 attrs[nattrs].value = manufacturer;
1899 nattrs++;
1900 }
1901
1902 PK11_MakeString(NULL((void*)0), serial, (char *)slot->tokenInfo.serialNumber,
1903 sizeof(slot->tokenInfo.serialNumber));
1904 if (*serial != '\0') {
1905 attrs[nattrs].name = PK11URI_PATTR_SERIAL"serial";
1906 attrs[nattrs].value = serial;
1907 nattrs++;
1908 }
1909
1910 PK11_MakeString(NULL((void*)0), model, (char *)slot->tokenInfo.model,
1911 sizeof(slot->tokenInfo.model));
1912 if (*model != '\0') {
1913 attrs[nattrs].name = PK11URI_PATTR_MODEL"model";
1914 attrs[nattrs].value = model;
1915 nattrs++;
1916 }
1917
1918 uri = PK11URI_CreateURI(attrs, nattrs, NULL((void*)0), 0);
1919 if (uri == NULL((void*)0)) {
1920 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_LIBRARY_FAILURE);
1921 return NULL((void*)0);
1922 }
1923
1924 ret = PK11URI_FormatURI(NULL((void*)0), uri);
1925 PK11URI_DestroyURI(uri);
1926
1927 if (ret == NULL((void*)0)) {
1928 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_LIBRARY_FAILURE);
1929 }
1930
1931 return ret;
1932}
1933
1934char *
1935PK11_GetSlotName(PK11SlotInfo *slot)
1936{
1937 return slot->slot_name;
1938}
1939
1940int
1941PK11_GetSlotSeries(PK11SlotInfo *slot)
1942{
1943 return slot->series;
1944}
1945
1946int
1947PK11_GetCurrentWrapIndex(PK11SlotInfo *slot)
1948{
1949 return slot->wrapKey;
1950}
1951
1952CK_SLOT_ID
1953PK11_GetSlotID(PK11SlotInfo *slot)
1954{
1955 return slot->slotID;
1956}
1957
1958SECMODModuleID
1959PK11_GetModuleID(PK11SlotInfo *slot)
1960{
1961 return slot->module->moduleID;
1962}
1963
1964static void
1965pk11_zeroTerminatedToBlankPadded(CK_CHAR *buffer, size_t buffer_size)
1966{
1967 CK_CHAR *walk = buffer;
1968 CK_CHAR *end = buffer + buffer_size;
1969
1970 /* find the NULL */
1971 while (walk < end && *walk != '\0') {
1972 walk++;
1973 }
1974
1975 /* clear out the buffer */
1976 while (walk < end) {
1977 *walk++ = ' ';
1978 }
1979}
1980
1981/* return the slot info structure */
1982SECStatus
1983PK11_GetSlotInfo(PK11SlotInfo *slot, CK_SLOT_INFO *info)
1984{
1985 CK_RV crv;
1986
1987 if (!slot->isThreadSafe)
1988 PK11_EnterSlotMonitor(slot);
1989 /*
1990 * some buggy drivers do not fill the buffer completely,
1991 * erase the buffer first
1992 */
1993 PORT_Memsetmemset(info->slotDescription, ' ', sizeof(info->slotDescription));
1994 PORT_Memsetmemset(info->manufacturerID, ' ', sizeof(info->manufacturerID));
1995 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetSlotInfo(slot->slotID, info);
1996 pk11_zeroTerminatedToBlankPadded(info->slotDescription,
1997 sizeof(info->slotDescription));
1998 pk11_zeroTerminatedToBlankPadded(info->manufacturerID,
1999 sizeof(info->manufacturerID));
2000 if (!slot->isThreadSafe)
2001 PK11_ExitSlotMonitor(slot);
2002 if (crv != CKR_OK0x00000000UL) {
2003 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2004 return SECFailure;
2005 }
2006 return SECSuccess;
2007}
2008
2009/* return the token info structure */
2010SECStatus
2011PK11_GetTokenInfo(PK11SlotInfo *slot, CK_TOKEN_INFO *info)
2012{
2013 CK_RV crv;
2014 if (!slot->isThreadSafe)
2015 PK11_EnterSlotMonitor(slot);
2016 /*
2017 * some buggy drivers do not fill the buffer completely,
2018 * erase the buffer first
2019 */
2020 PORT_Memsetmemset(info->label, ' ', sizeof(info->label));
2021 PORT_Memsetmemset(info->manufacturerID, ' ', sizeof(info->manufacturerID));
2022 PORT_Memsetmemset(info->model, ' ', sizeof(info->model));
2023 PORT_Memsetmemset(info->serialNumber, ' ', sizeof(info->serialNumber));
2024 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetTokenInfo(slot->slotID, info);
2025 pk11_zeroTerminatedToBlankPadded(info->label, sizeof(info->label));
2026 pk11_zeroTerminatedToBlankPadded(info->manufacturerID,
2027 sizeof(info->manufacturerID));
2028 pk11_zeroTerminatedToBlankPadded(info->model, sizeof(info->model));
2029 pk11_zeroTerminatedToBlankPadded(info->serialNumber,
2030 sizeof(info->serialNumber));
2031 if (!slot->isThreadSafe)
2032 PK11_ExitSlotMonitor(slot);
2033 if (crv != CKR_OK0x00000000UL) {
2034 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2035 return SECFailure;
2036 }
2037 return SECSuccess;
2038}
2039
2040PRBool
2041pk11_MatchUriTokenInfo(PK11SlotInfo *slot, PK11URI *uri)
2042{
2043 const char *value;
2044
2045 value = PK11URI_GetPathAttribute(uri, PK11URI_PATTR_TOKEN"token");
2046 if (value) {
2047 if (!pk11_MatchString(value, (char *)slot->tokenInfo.label,
2048 sizeof(slot->tokenInfo.label))) {
2049 return PR_FALSE0;
2050 }
2051 }
2052
2053 value = PK11URI_GetPathAttribute(uri, PK11URI_PATTR_MANUFACTURER"manufacturer");
2054 if (value) {
2055 if (!pk11_MatchString(value, (char *)slot->tokenInfo.manufacturerID,
2056 sizeof(slot->tokenInfo.manufacturerID))) {
2057 return PR_FALSE0;
2058 }
2059 }
2060
2061 value = PK11URI_GetPathAttribute(uri, PK11URI_PATTR_SERIAL"serial");
2062 if (value) {
2063 if (!pk11_MatchString(value, (char *)slot->tokenInfo.serialNumber,
2064 sizeof(slot->tokenInfo.serialNumber))) {
2065 return PR_FALSE0;
2066 }
2067 }
2068
2069 value = PK11URI_GetPathAttribute(uri, PK11URI_PATTR_MODEL"model");
2070 if (value) {
2071 if (!pk11_MatchString(value, (char *)slot->tokenInfo.model,
2072 sizeof(slot->tokenInfo.model))) {
2073 return PR_FALSE0;
2074 }
2075 }
2076
2077 return PR_TRUE1;
2078}
2079
2080/* Find out if we need to initialize the user's pin */
2081PRBool
2082PK11_NeedUserInit(PK11SlotInfo *slot)
2083{
2084 PRBool needUserInit = (PRBool)((slot->flags & CKF_USER_PIN_INITIALIZED0x00000008UL) == 0);
2085
2086 if (needUserInit) {
2087 CK_TOKEN_INFO info;
2088 SECStatus rv;
2089
2090 /* see if token has been initialized off line */
2091 rv = PK11_GetTokenInfo(slot, &info);
2092 if (rv == SECSuccess) {
2093 slot->flags = info.flags;
2094 }
2095 }
2096 return (PRBool)((slot->flags & CKF_USER_PIN_INITIALIZED0x00000008UL) == 0);
2097}
2098
2099static PK11SlotInfo *pk11InternalKeySlot = NULL((void*)0);
2100
2101/*
2102 * Set a new default internal keyslot. If one has already been set, clear it.
2103 * Passing NULL falls back to the NSS normally selected default internal key
2104 * slot.
2105 */
2106void
2107pk11_SetInternalKeySlot(PK11SlotInfo *slot)
2108{
2109 if (pk11InternalKeySlot) {
2110 PK11_FreeSlot(pk11InternalKeySlot);
2111 }
2112 pk11InternalKeySlot = slot ? PK11_ReferenceSlot(slot) : NULL((void*)0);
2113}
2114
2115/*
2116 * Set a new default internal keyslot if the normal key slot has not already
2117 * been overridden. Subsequent calls to this function will be ignored unless
2118 * pk11_SetInternalKeySlot is used to clear the current default.
2119 */
2120void
2121pk11_SetInternalKeySlotIfFirst(PK11SlotInfo *slot)
2122{
2123 if (pk11InternalKeySlot) {
2124 return;
2125 }
2126 pk11InternalKeySlot = slot ? PK11_ReferenceSlot(slot) : NULL((void*)0);
2127}
2128
2129/*
2130 * Swap out a default internal keyslot. Caller owns the Slot Reference
2131 */
2132PK11SlotInfo *
2133pk11_SwapInternalKeySlot(PK11SlotInfo *slot)
2134{
2135 PK11SlotInfo *swap = pk11InternalKeySlot;
2136
2137 pk11InternalKeySlot = slot ? PK11_ReferenceSlot(slot) : NULL((void*)0);
2138 return swap;
2139}
2140
2141/* get the internal key slot. FIPS has only one slot for both key slots and
2142 * default slots */
2143PK11SlotInfo *
2144PK11_GetInternalKeySlot(void)
2145{
2146 SECMODModule *mod;
2147
2148 if (pk11InternalKeySlot) {
2149 return PK11_ReferenceSlot(pk11InternalKeySlot);
2150 }
2151
2152 mod = SECMOD_GetInternalModule();
2153 PORT_Assert(mod != NULL)((mod != ((void*)0)) ? ((void)0) : PR_Assert("mod != NULL", "/root/firefox-clang/security/nss/lib/pk11wrap/pk11slot.c"
, 2153))
;
2154 if (!mod) {
2155 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MODULE);
2156 return NULL((void*)0);
2157 }
2158 return PK11_ReferenceSlot(mod->isFIPS ? mod->slots[0] : mod->slots[1]);
2159}
2160
2161/* get the internal default slot */
2162PK11SlotInfo *
2163PK11_GetInternalSlot(void)
2164{
2165 SECMODModule *mod = SECMOD_GetInternalModule();
2166 PORT_Assert(mod != NULL)((mod != ((void*)0)) ? ((void)0) : PR_Assert("mod != NULL", "/root/firefox-clang/security/nss/lib/pk11wrap/pk11slot.c"
, 2166))
;
2167 if (!mod) {
2168 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MODULE);
2169 return NULL((void*)0);
2170 }
2171 if (mod->isFIPS) {
2172 return PK11_GetInternalKeySlot();
2173 }
2174 return PK11_ReferenceSlot(mod->slots[0]);
2175}
2176
2177/*
2178 * check if a given slot supports the requested mechanism
2179 */
2180PRBool
2181PK11_DoesMechanism(PK11SlotInfo *slot, CK_MECHANISM_TYPE type)
2182{
2183 int i;
2184
2185 /* CKM_FAKE_RANDOM is not a real PKCS mechanism. It's a marker to
2186 * tell us we're looking form someone that has implemented get
2187 * random bits */
2188 if (type == CKM_FAKE_RANDOM0x80000efeUL) {
2189 return slot->hasRandom;
2190 }
2191
2192 /* for most mechanism, bypass the linear lookup */
2193 if (type < 0x7ff) {
2194 return (slot->mechanismBits[type & 0xff] & (1 << (type >> 8))) ? PR_TRUE1 : PR_FALSE0;
2195 }
2196
2197 for (i = 0; i < (int)slot->mechanismCount; i++) {
2198 if (slot->mechanismList[i] == type)
2199 return PR_TRUE1;
2200 }
2201 return PR_FALSE0;
2202}
2203
2204PRBool pk11_filterSlot(PK11SlotInfo *slot, CK_MECHANISM_TYPE mechanism,
2205 CK_FLAGS mechanismInfoFlags, unsigned int keySize);
2206/*
2207 * Check that the given mechanism has the appropriate flags. This function
2208 * presumes that slot can already do the given mechanism.
2209 */
2210PRBool
2211PK11_DoesMechanismFlag(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
2212 CK_FLAGS flags)
2213{
2214 return !pk11_filterSlot(slot, type, flags, 0);
2215}
2216
2217/*
2218 * Return true if a token that can do the desired mechanism exists.
2219 * This allows us to have hardware tokens that can do function XYZ magically
2220 * allow SSL Ciphers to appear if they are plugged in.
2221 */
2222PRBool
2223PK11_TokenExists(CK_MECHANISM_TYPE type)
2224{
2225 SECMODModuleList *mlp;
2226 SECMODModuleList *modules;
2227 SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
2228 PK11SlotInfo *slot;
2229 PRBool found = PR_FALSE0;
2230 int i;
2231
2232 if (!moduleLock) {
2233 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NOT_INITIALIZED);
2234 return found;
2235 }
2236 /* we only need to know if there is a token that does this mechanism.
2237 * check the internal module first because it's fast, and supports
2238 * almost everything. */
2239 slot = PK11_GetInternalSlot();
2240 if (slot) {
2241 found = PK11_DoesMechanism(slot, type);
2242 PK11_FreeSlot(slot);
2243 }
2244 if (found)
2245 return PR_TRUE1; /* bypass getting module locks */
2246
2247 SECMOD_GetReadLock(moduleLock);
2248 modules = SECMOD_GetDefaultModuleList();
2249 for (mlp = modules; mlp != NULL((void*)0) && (!found); mlp = mlp->next) {
2250 for (i = 0; i < mlp->module->slotCount; i++) {
2251 slot = mlp->module->slots[i];
2252 if (PK11_IsPresent(slot)) {
2253 if (PK11_DoesMechanism(slot, type)) {
2254 found = PR_TRUE1;
2255 break;
2256 }
2257 }
2258 }
2259 }
2260 SECMOD_ReleaseReadLock(moduleLock);
2261 return found;
2262}
2263
2264/*
2265 * get all the currently available tokens in a list.
2266 * that can perform the given mechanism. If mechanism is CKM_INVALID_MECHANISM,
2267 * get all the tokens. Make sure tokens that need authentication are put at
2268 * the end of this list.
2269 */
2270PK11SlotList *
2271PK11_GetAllTokens(CK_MECHANISM_TYPE type, PRBool needRW, PRBool loadCerts,
2272 void *wincx)
2273{
2274 PK11SlotList *list;
2275 PK11SlotList *loginList;
2276 PK11SlotList *friendlyList;
2277 SECMODModuleList *mlp;
2278 SECMODModuleList *modules;
2279 SECMODListLock *moduleLock;
2280 int i;
2281
2282 moduleLock = SECMOD_GetDefaultModuleListLock();
2283 if (!moduleLock) {
2284 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NOT_INITIALIZED);
2285 return NULL((void*)0);
2286 }
2287
2288 list = PK11_NewSlotList();
2289 loginList = PK11_NewSlotList();
2290 friendlyList = PK11_NewSlotList();
2291 if ((list == NULL((void*)0)) || (loginList == NULL((void*)0)) || (friendlyList == NULL((void*)0))) {
2292 if (list)
2293 PK11_FreeSlotList(list);
2294 if (loginList)
2295 PK11_FreeSlotList(loginList);
2296 if (friendlyList)
2297 PK11_FreeSlotList(friendlyList);
2298 return NULL((void*)0);
2299 }
2300
2301 SECMOD_GetReadLock(moduleLock);
2302
2303 modules = SECMOD_GetDefaultModuleList();
2304 for (mlp = modules; mlp != NULL((void*)0); mlp = mlp->next) {
2305 for (i = 0; i < mlp->module->slotCount; i++) {
2306 PK11SlotInfo *slot = mlp->module->slots[i];
2307
2308 if (pk11_IsPresentCertLoad(slot, loadCerts)) {
2309 if (needRW && slot->readOnly)
2310 continue;
2311 if ((type == CKM_INVALID_MECHANISM0xffffffffUL) || PK11_DoesMechanism(slot, type)) {
2312 if (pk11_LoginStillRequired(slot, wincx)) {
2313 if (PK11_IsFriendly(slot)) {
2314 PK11_AddSlotToList(friendlyList, slot, PR_TRUE1);
2315 } else {
2316 PK11_AddSlotToList(loginList, slot, PR_TRUE1);
2317 }
2318 } else {
2319 PK11_AddSlotToList(list, slot, PR_TRUE1);
2320 }
2321 }
2322 }
2323 }
2324 }
2325 SECMOD_ReleaseReadLock(moduleLock);
2326
2327 pk11_MoveListToList(list, friendlyList);
2328 PK11_FreeSlotList(friendlyList);
2329 pk11_MoveListToList(list, loginList);
2330 PK11_FreeSlotList(loginList);
2331
2332 return list;
2333}
2334
2335/*
2336 * returns true if the slot doesn't conform to the requested attributes
2337 */
2338PRBool
2339pk11_filterSlot(PK11SlotInfo *slot, CK_MECHANISM_TYPE mechanism,
2340 CK_FLAGS mechanismInfoFlags, unsigned int keySize)
2341{
2342 CK_MECHANISM_INFO mechanism_info;
2343 CK_RV crv = CKR_OK0x00000000UL;
2344
2345 /* handle the only case where we don't actually fetch the mechanisms
2346 * on the fly */
2347 if ((keySize == 0) && (mechanism == CKM_RSA_PKCS0x00000001UL) && (slot->hasRSAInfo)) {
2348 mechanism_info.flags = slot->RSAInfoFlags;
2349 } else {
2350 if (!slot->isThreadSafe)
2351 PK11_EnterSlotMonitor(slot);
2352 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetMechanismInfo(slot->slotID, mechanism,
2353 &mechanism_info);
2354 if (!slot->isThreadSafe)
2355 PK11_ExitSlotMonitor(slot);
2356 /* if we were getting the RSA flags, save them */
2357 if ((crv == CKR_OK0x00000000UL) && (mechanism == CKM_RSA_PKCS0x00000001UL) && (!slot->hasRSAInfo)) {
2358 slot->RSAInfoFlags = mechanism_info.flags;
2359 slot->hasRSAInfo = PR_TRUE1;
2360 }
2361 }
2362 /* couldn't get the mechanism info */
2363 if (crv != CKR_OK0x00000000UL) {
2364 return PR_TRUE1;
2365 }
2366 if (keySize && ((mechanism_info.ulMinKeySize > keySize) || (mechanism_info.ulMaxKeySize < keySize))) {
2367 /* Token can do mechanism, but not at the key size we
2368 * want */
2369 return PR_TRUE1;
2370 }
2371 if (mechanismInfoFlags && ((mechanism_info.flags & mechanismInfoFlags) !=
2372 mechanismInfoFlags)) {
2373 return PR_TRUE1;
2374 }
2375 return PR_FALSE0;
2376}
2377
2378/*
2379 * Find the best slot which supports the given set of mechanisms and key sizes.
2380 * In normal cases this should grab the first slot on the list with no fuss.
2381 * The size array is presumed to match one for one with the mechanism type
2382 * array, which allows you to specify the required key size for each
2383 * mechanism in the list. Whether key size is in bits or bytes is mechanism
2384 * dependent. Typically asymetric keys are in bits and symetric keys are in
2385 * bytes.
2386 */
2387PK11SlotInfo *
2388PK11_GetBestSlotMultipleWithAttributes(CK_MECHANISM_TYPE *type,
2389 CK_FLAGS *mechanismInfoFlags, unsigned int *keySize,
2390 unsigned int mech_count, void *wincx)
2391{
2392 PK11SlotList *list = NULL((void*)0);
2393 PK11SlotListElement *le;
2394 PK11SlotInfo *slot = NULL((void*)0);
2395 PRBool freeit = PR_FALSE0;
2396 PRBool listNeedLogin = PR_FALSE0;
2397 unsigned int i;
2398 SECStatus rv;
2399
2400 list = PK11_GetSlotList(type[0]);
2401
2402 if ((list == NULL((void*)0)) || (list->head == NULL((void*)0))) {
2403 /* We need to look up all the tokens for the mechanism */
2404 list = PK11_GetAllTokens(type[0], PR_FALSE0, PR_TRUE1, wincx);
2405 freeit = PR_TRUE1;
2406 }
2407
2408 /* no one can do it! */
2409 if (list == NULL((void*)0)) {
2410 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_TOKEN);
2411 return NULL((void*)0);
2412 }
2413
2414 PORT_SetErrorPORT_SetError_Util(0);
2415
2416 listNeedLogin = PR_FALSE0;
2417 for (i = 0; i < mech_count; i++) {
2418 if ((type[i] != CKM_FAKE_RANDOM0x80000efeUL) &&
2419 (type[i] != CKM_SHA_10x00000220UL) &&
2420 (type[i] != CKM_SHA2240x00000255UL) &&
2421 (type[i] != CKM_SHA2560x00000250UL) &&
2422 (type[i] != CKM_SHA3840x00000260UL) &&
2423 (type[i] != CKM_SHA5120x00000270UL) &&
2424 (type[i] != CKM_MD50x00000210UL) &&
2425 (type[i] != CKM_MD20x00000200UL)) {
2426 listNeedLogin = PR_TRUE1;
2427 break;
2428 }
2429 }
2430
2431 for (le = PK11_GetFirstSafe(list); le;
2432 le = PK11_GetNextSafe(list, le, PR_TRUE1)) {
2433 if (PK11_IsPresent(le->slot)) {
2434 PRBool doExit = PR_FALSE0;
2435 for (i = 0; i < mech_count; i++) {
2436 if (!PK11_DoesMechanism(le->slot, type[i])) {
2437 doExit = PR_TRUE1;
2438 break;
2439 }
2440 if ((mechanismInfoFlags && mechanismInfoFlags[i]) ||
2441 (keySize && keySize[i])) {
2442 if (pk11_filterSlot(le->slot, type[i],
2443 mechanismInfoFlags ? mechanismInfoFlags[i] : 0,
2444 keySize ? keySize[i] : 0)) {
2445 doExit = PR_TRUE1;
2446 break;
2447 }
2448 }
2449 }
2450
2451 if (doExit)
2452 continue;
2453
2454 if (listNeedLogin && le->slot->needLogin) {
2455 rv = PK11_Authenticate(le->slot, PR_TRUE1, wincx);
2456 if (rv != SECSuccess)
2457 continue;
2458 }
2459 slot = le->slot;
2460 PK11_ReferenceSlot(slot);
2461 PK11_FreeSlotListElement(list, le);
2462 if (freeit) {
2463 PK11_FreeSlotList(list);
2464 }
2465 return slot;
2466 }
2467 }
2468 if (freeit) {
2469 PK11_FreeSlotList(list);
2470 }
2471 if (PORT_GetErrorPORT_GetError_Util() == 0) {
2472 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_TOKEN);
2473 }
2474 return NULL((void*)0);
2475}
2476
2477PK11SlotInfo *
2478PK11_GetBestSlotMultiple(CK_MECHANISM_TYPE *type,
2479 unsigned int mech_count, void *wincx)
2480{
2481 return PK11_GetBestSlotMultipleWithAttributes(type, NULL((void*)0), NULL((void*)0),
2482 mech_count, wincx);
2483}
2484
2485/* original get best slot now calls the multiple version with only one type */
2486PK11SlotInfo *
2487PK11_GetBestSlot(CK_MECHANISM_TYPE type, void *wincx)
2488{
2489 return PK11_GetBestSlotMultipleWithAttributes(&type, NULL((void*)0), NULL((void*)0), 1, wincx);
2490}
2491
2492PK11SlotInfo *
2493PK11_GetBestSlotWithAttributes(CK_MECHANISM_TYPE type, CK_FLAGS mechanismFlags,
2494 unsigned int keySize, void *wincx)
2495{
2496 return PK11_GetBestSlotMultipleWithAttributes(&type, &mechanismFlags,
2497 &keySize, 1, wincx);
2498}
2499
2500int
2501PK11_GetBestKeyLength(PK11SlotInfo *slot, CK_MECHANISM_TYPE mechanism)
2502{
2503 CK_MECHANISM_INFO mechanism_info;
2504 CK_RV crv;
2505
2506 if (!slot->isThreadSafe)
2507 PK11_EnterSlotMonitor(slot);
2508 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetMechanismInfo(slot->slotID,
2509 mechanism, &mechanism_info);
2510 if (!slot->isThreadSafe)
2511 PK11_ExitSlotMonitor(slot);
2512 if (crv != CKR_OK0x00000000UL)
2513 return 0;
2514
2515 if (mechanism_info.ulMinKeySize == mechanism_info.ulMaxKeySize)
2516 return 0;
2517 return mechanism_info.ulMaxKeySize;
2518}
2519
2520/*
2521 * This function uses the existing PKCS #11 module to find the
2522 * longest supported key length in the preferred token for a mechanism.
2523 * This varies from the above function in that 1) it returns the key length
2524 * even for fixed key algorithms, and 2) it looks through the tokens
2525 * generally rather than for a specific token. This is used in liu of
2526 * a PK11_GetKeyLength function in pk11mech.c since we can actually read
2527 * supported key lengths from PKCS #11.
2528 *
2529 * For symmetric key operations the length is returned in bytes.
2530 */
2531int
2532PK11_GetMaxKeyLength(CK_MECHANISM_TYPE mechanism)
2533{
2534 CK_MECHANISM_INFO mechanism_info;
2535 PK11SlotList *list = NULL((void*)0);
2536 PK11SlotListElement *le;
2537 PRBool freeit = PR_FALSE0;
2538 int keyLength = 0;
2539
2540 list = PK11_GetSlotList(mechanism);
2541
2542 if ((list == NULL((void*)0)) || (list->head == NULL((void*)0))) {
2543 /* We need to look up all the tokens for the mechanism */
2544 list = PK11_GetAllTokens(mechanism, PR_FALSE0, PR_FALSE0, NULL((void*)0));
2545 freeit = PR_TRUE1;
2546 }
2547
2548 /* no tokens recognize this mechanism */
2549 if (list == NULL((void*)0)) {
2550 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ALGORITHM);
2551 return 0;
2552 }
2553
2554 for (le = PK11_GetFirstSafe(list); le;
2555 le = PK11_GetNextSafe(list, le, PR_TRUE1)) {
2556 PK11SlotInfo *slot = le->slot;
2557 CK_RV crv;
2558 if (PK11_IsPresent(slot)) {
2559 if (!slot->isThreadSafe)
2560 PK11_EnterSlotMonitor(slot);
2561 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetMechanismInfo(slot->slotID,
2562 mechanism, &mechanism_info);
2563 if (!slot->isThreadSafe)
2564 PK11_ExitSlotMonitor(slot);
2565 if ((crv == CKR_OK0x00000000UL) && (mechanism_info.ulMaxKeySize != 0) && (mechanism_info.ulMaxKeySize != 0xffffffff)) {
2566 keyLength = mechanism_info.ulMaxKeySize;
2567 break;
2568 }
2569 }
2570 }
2571
2572 /* fallback to pk11_GetPredefinedKeyLength for fixed key size algorithms */
2573 if (keyLength == 0) {
2574 CK_KEY_TYPE keyType;
2575 keyType = PK11_GetKeyType(mechanism, 0);
2576 keyLength = pk11_GetPredefinedKeyLength(keyType);
2577 }
2578
2579 if (le)
2580 PK11_FreeSlotListElement(list, le);
2581 if (freeit)
2582 PK11_FreeSlotList(list);
2583 return keyLength;
2584}
2585
2586SECStatus
2587PK11_SeedRandom(PK11SlotInfo *slot, unsigned char *data, int len)
2588{
2589 CK_RV crv;
2590
2591 PK11_EnterSlotMonitor(slot);
2592 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_SeedRandom(slot->session, data, (CK_ULONG)len);
2593 PK11_ExitSlotMonitor(slot);
2594 if (crv != CKR_OK0x00000000UL) {
2595 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2596 return SECFailure;
2597 }
2598 return SECSuccess;
2599}
2600
2601SECStatus
2602PK11_GenerateRandomOnSlot(PK11SlotInfo *slot, unsigned char *data, int len)
2603{
2604 CK_RV crv;
2605
2606 if (!slot->isInternal)
2607 PK11_EnterSlotMonitor(slot);
2608 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GenerateRandom(slot->session, data,
2609 (CK_ULONG)len);
2610 if (!slot->isInternal)
2611 PK11_ExitSlotMonitor(slot);
2612 if (crv != CKR_OK0x00000000UL) {
2613 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2614 return SECFailure;
2615 }
2616 return SECSuccess;
2617}
2618
2619/* Attempts to update the Best Slot for "FAKE RANDOM" generation.
2620** If that's not the internal slot, then it also attempts to update the
2621** internal slot.
2622** The return value indicates if the INTERNAL slot was updated OK.
2623*/
2624SECStatus
2625PK11_RandomUpdate(void *data, size_t bytes)
2626{
2627 PK11SlotInfo *slot;
2628 PRBool bestIsInternal;
2629 SECStatus status;
2630
2631 slot = PK11_GetBestSlot(CKM_FAKE_RANDOM0x80000efeUL, NULL((void*)0));
2632 if (slot == NULL((void*)0)) {
2633 slot = PK11_GetInternalSlot();
2634 if (!slot)
2635 return SECFailure;
2636 }
2637
2638 bestIsInternal = PK11_IsInternal(slot);
2639 status = PK11_SeedRandom(slot, data, bytes);
2640 PK11_FreeSlot(slot);
2641
2642 if (!bestIsInternal) {
2643 /* do internal slot, too. */
2644 slot = PK11_GetInternalSlot();
2645 PORT_Assert(slot)((slot) ? ((void)0) : PR_Assert("slot", "/root/firefox-clang/security/nss/lib/pk11wrap/pk11slot.c"
, 2645))
;
2646 if (!slot) {
2647 return SECFailure;
2648 }
2649 status = PK11_SeedRandom(slot, data, bytes);
2650 PK11_FreeSlot(slot);
2651 }
2652 return status;
2653}
2654
2655SECStatus
2656PK11_GenerateRandom(unsigned char *data, int len)
2657{
2658 PK11SlotInfo *slot;
2659 SECStatus rv;
2660
2661 slot = PK11_GetBestSlot(CKM_FAKE_RANDOM0x80000efeUL, NULL((void*)0));
2662 if (slot == NULL((void*)0))
2663 return SECFailure;
2664
2665 rv = PK11_GenerateRandomOnSlot(slot, data, len);
2666 PK11_FreeSlot(slot);
2667 return rv;
2668}
2669
2670/*
2671 * Reset the token to it's initial state. For the internal module, this will
2672 * Purge your keydb, and reset your cert db certs to USER_INIT.
2673 */
2674SECStatus
2675PK11_ResetToken(PK11SlotInfo *slot, char *sso_pwd)
2676{
2677 unsigned char tokenName[32];
2678 size_t tokenNameLen;
2679 CK_RV crv;
2680
2681 /* reconstruct the token name */
2682 tokenNameLen = PORT_Strlen(slot->token_name)strlen(slot->token_name);
2683 if (tokenNameLen > sizeof(tokenName)) {
2684 tokenNameLen = sizeof(tokenName);
2685 }
2686
2687 PORT_Memcpymemcpy(tokenName, slot->token_name, tokenNameLen);
2688 if (tokenNameLen < sizeof(tokenName)) {
2689 PORT_Memsetmemset(&tokenName[tokenNameLen], ' ',
2690 sizeof(tokenName) - tokenNameLen);
2691 }
2692
2693 /* initialize the token */
2694 PK11_EnterSlotMonitor(slot);
2695
2696 /* first shutdown the token. Existing sessions will get closed here */
2697 PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))
2698 ->C_CloseAllSessions(slot->slotID);
2699 slot->session = CK_INVALID_HANDLE0;
2700
2701 /* now re-init the token */
2702 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_InitToken(slot->slotID,
2703 (unsigned char *)sso_pwd, sso_pwd ? PORT_Strlen(sso_pwd)strlen(sso_pwd) : 0, tokenName);
2704 PK11_ExitSlotMonitor(slot);
2705
2706 /* finally bring the token back up. PK11_InitToken takes the slot monitor
2707 * itself, so it must be called without the monitor held. */
2708 PK11_InitToken(slot, PR_TRUE1);
2709 if (crv != CKR_OK0x00000000UL) {
2710 PORT_SetErrorPORT_SetError_Util(PK11_MapError(crv));
2711 return SECFailure;
2712 }
2713 NSSToken *token = PK11Slot_GetNSSToken(slot);
2714 if (token) {
2715 nssTrustDomain_UpdateCachedTokenCerts(token->trustDomain, token);
2716 (void)nssToken_Destroy(token);
2717 }
2718 return SECSuccess;
2719}
2720
2721void
2722PK11Slot_SetNSSToken(PK11SlotInfo *sl, NSSToken *nsst)
2723{
2724 NSSToken *old;
2725 if (nsst) {
2726 nsst = nssToken_AddRef(nsst);
2727 }
2728
2729 PR_Lock(sl->nssTokenLock);
2730 old = sl->nssToken;
2731 sl->nssToken = nsst;
2732 PR_Unlock(sl->nssTokenLock);
2733
2734 if (old) {
2735 (void)nssToken_Destroy(old);
2736 }
2737}
2738
2739NSSToken *
2740PK11Slot_GetNSSToken(PK11SlotInfo *sl)
2741{
2742 NSSToken *rv = NULL((void*)0);
2743
2744 PR_Lock(sl->nssTokenLock);
2745 if (sl->nssToken) {
2746 rv = nssToken_AddRef(sl->nssToken);
2747 }
2748 PR_Unlock(sl->nssTokenLock);
2749
2750 return rv;
2751}
2752
2753PRBool
2754pk11slot_GetFIPSStatus(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
2755 CK_OBJECT_HANDLE object, CK_ULONG operationType)
2756{
2757 SECMODModule *mod = slot->module;
2758 CK_RV crv;
2759 CK_ULONG fipsState = CKS_NSS_FIPS_NOT_OK0UL;
2760
2761 if (PK11_CheckPKCS11Version(slot, 3, 2, PR_TRUE1) >= 0) {
2762 CK_FLAGS validationFlags = 0;
2763
2764 /* module isn't validated */
2765 if (slot->validationFIPSFlags == 0) {
2766 return PR_FALSE0;
2767 }
2768 switch (operationType) {
2769 /* in pkcs #11, these are equivalent */
2770 case CKT_NSS_SESSION_LAST_CHECK4UL:
2771 case CKT_NSS_SESSION_CHECK1UL:
2772 crv = PK11_GETTAB(slot)((CK_FUNCTION_LIST_3_2_PTR)((slot)->functionList))->C_GetSessionValidationFlags(session,
2773 CKS_LAST_VALIDATION_OK0x00000001UL, &validationFlags);
2774 if (crv != CKR_OK0x00000000UL) {
2775 return PR_FALSE0;
2776 }
2777 break;
2778 case CKT_NSS_OBJECT_CHECK2UL:
2779 validationFlags = PK11_ReadULongAttribute(slot, object,
2780 CKA_OBJECT_VALIDATION_FLAGS0x0000061eUL);
2781 if (validationFlags == CK_UNAVAILABLE_INFORMATION(~0UL)) {
2782 return PR_FALSE0;
2783 }
2784 break;
2785 default:
2786 return PR_FALSE0;
2787 }
2788 return (PRBool)(validationFlags & slot->validationFIPSFlags) != 0;
2789 }
2790 /* handle the NSS vendor specific indicators, for older modules */
2791 /* handle the obvious conditions:
2792 * 1) the module doesn't have a fipsIndicator - fips state must be false */
2793 if (mod->fipsIndicator == NULL((void*)0)) {
2794 return PR_FALSE0;
2795 }
2796 /* 2) the session doesn't exist - fips state must be false */
2797 if (session == CK_INVALID_HANDLE0) {
2798 return PR_FALSE0;
2799 }
2800
2801 /* go fetch the state */
2802 crv = mod->fipsIndicator(session, object, operationType, &fipsState);
2803 if (crv != CKR_OK0x00000000UL) {
2804 return PR_FALSE0;
2805 }
2806 return (fipsState == CKS_NSS_FIPS_OK1UL) ? PR_TRUE1 : PR_FALSE0;
2807}
2808
2809PRBool
2810PK11_SlotGetLastFIPSStatus(PK11SlotInfo *slot)
2811{
2812 return pk11slot_GetFIPSStatus(slot, slot->session, CK_INVALID_HANDLE0,
2813 CKT_NSS_SESSION_LAST_CHECK4UL);
2814}
2815
2816/*
2817 * wait for a token to change it's state. The application passes in the expected
2818 * new state in event.
2819 */
2820PK11TokenStatus
2821PK11_WaitForTokenEvent(PK11SlotInfo *slot, PK11TokenEvent event,
2822 PRIntervalTime timeout, PRIntervalTime latency, int series)
2823{
2824 PRIntervalTime first_time = 0;
2825 PRBool first_time_set = PR_FALSE0;
2826 PRBool waitForRemoval;
2827
2828 if (slot->isPerm) {
2829 return PK11TokenNotRemovable;
2830 }
2831 if (latency == 0) {
2832 latency = PR_SecondsToInterval(5);
2833 }
2834 waitForRemoval = (PRBool)(event == PK11TokenRemovedOrChangedEvent);
2835
2836 if (series == 0) {
2837 series = PK11_GetSlotSeries(slot);
2838 }
2839 while (PK11_IsPresent(slot) == waitForRemoval) {
2840 PRIntervalTime interval;
2841
2842 if (waitForRemoval && series != PK11_GetSlotSeries(slot)) {
2843 return PK11TokenChanged;
2844 }
2845 if (timeout == PR_INTERVAL_NO_WAIT0UL) {
2846 return waitForRemoval ? PK11TokenPresent : PK11TokenRemoved;
2847 }
2848 if (timeout != PR_INTERVAL_NO_TIMEOUT0xffffffffUL) {
2849 interval = PR_IntervalNow();
2850 if (!first_time_set) {
2851 first_time = interval;
2852 first_time_set = PR_TRUE1;
2853 }
2854 if ((interval - first_time) > timeout) {
2855 return waitForRemoval ? PK11TokenPresent : PK11TokenRemoved;
2856 }
2857 }
2858 PR_Sleep(latency);
2859 }
2860 return waitForRemoval ? PK11TokenRemoved : PK11TokenPresent;
2861}