Bug Summary

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