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