1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/pk11wrap/pk11slot.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2406 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +/* 1.8 + * Deal with PKCS #11 Slots. 1.9 + */ 1.10 +#include "seccomon.h" 1.11 +#include "secmod.h" 1.12 +#include "nssilock.h" 1.13 +#include "secmodi.h" 1.14 +#include "secmodti.h" 1.15 +#include "pkcs11t.h" 1.16 +#include "pk11func.h" 1.17 +#include "secitem.h" 1.18 +#include "secerr.h" 1.19 + 1.20 +#include "dev.h" 1.21 +#include "dev3hack.h" 1.22 +#include "pkim.h" 1.23 +#include "utilpars.h" 1.24 + 1.25 + 1.26 +/************************************************************* 1.27 + * local static and global data 1.28 + *************************************************************/ 1.29 + 1.30 +/* 1.31 + * This array helps parsing between names, mechanisms, and flags. 1.32 + * to make the config files understand more entries, add them 1.33 + * to this table. 1.34 + */ 1.35 +const PK11DefaultArrayEntry PK11_DefaultArray[] = { 1.36 + { "RSA", SECMOD_RSA_FLAG, CKM_RSA_PKCS }, 1.37 + { "DSA", SECMOD_DSA_FLAG, CKM_DSA }, 1.38 + { "ECC", SECMOD_ECC_FLAG, CKM_ECDSA }, 1.39 + { "DH", SECMOD_DH_FLAG, CKM_DH_PKCS_DERIVE }, 1.40 + { "RC2", SECMOD_RC2_FLAG, CKM_RC2_CBC }, 1.41 + { "RC4", SECMOD_RC4_FLAG, CKM_RC4 }, 1.42 + { "DES", SECMOD_DES_FLAG, CKM_DES_CBC }, 1.43 + { "AES", SECMOD_AES_FLAG, CKM_AES_CBC }, 1.44 + { "Camellia", SECMOD_CAMELLIA_FLAG, CKM_CAMELLIA_CBC }, 1.45 + { "SEED", SECMOD_SEED_FLAG, CKM_SEED_CBC }, 1.46 + { "RC5", SECMOD_RC5_FLAG, CKM_RC5_CBC }, 1.47 + { "SHA-1", SECMOD_SHA1_FLAG, CKM_SHA_1 }, 1.48 +/* { "SHA224", SECMOD_SHA256_FLAG, CKM_SHA224 }, */ 1.49 + { "SHA256", SECMOD_SHA256_FLAG, CKM_SHA256 }, 1.50 +/* { "SHA384", SECMOD_SHA512_FLAG, CKM_SHA384 }, */ 1.51 + { "SHA512", SECMOD_SHA512_FLAG, CKM_SHA512 }, 1.52 + { "MD5", SECMOD_MD5_FLAG, CKM_MD5 }, 1.53 + { "MD2", SECMOD_MD2_FLAG, CKM_MD2 }, 1.54 + { "SSL", SECMOD_SSL_FLAG, CKM_SSL3_PRE_MASTER_KEY_GEN }, 1.55 + { "TLS", SECMOD_TLS_FLAG, CKM_TLS_MASTER_KEY_DERIVE }, 1.56 + { "SKIPJACK", SECMOD_FORTEZZA_FLAG, CKM_SKIPJACK_CBC64 }, 1.57 + { "Publicly-readable certs", SECMOD_FRIENDLY_FLAG, CKM_INVALID_MECHANISM }, 1.58 + { "Random Num Generator", SECMOD_RANDOM_FLAG, CKM_FAKE_RANDOM }, 1.59 +}; 1.60 +const int num_pk11_default_mechanisms = 1.61 + sizeof(PK11_DefaultArray) / sizeof(PK11_DefaultArray[0]); 1.62 + 1.63 +const PK11DefaultArrayEntry * 1.64 +PK11_GetDefaultArray(int *size) 1.65 +{ 1.66 + if (size) { 1.67 + *size = num_pk11_default_mechanisms; 1.68 + } 1.69 + return PK11_DefaultArray; 1.70 +} 1.71 + 1.72 +/* 1.73 + * These slotlists are lists of modules which provide default support for 1.74 + * a given algorithm or mechanism. 1.75 + */ 1.76 +static PK11SlotList 1.77 + pk11_seedSlotList, 1.78 + pk11_camelliaSlotList, 1.79 + pk11_aesSlotList, 1.80 + pk11_desSlotList, 1.81 + pk11_rc4SlotList, 1.82 + pk11_rc2SlotList, 1.83 + pk11_rc5SlotList, 1.84 + pk11_sha1SlotList, 1.85 + pk11_md5SlotList, 1.86 + pk11_md2SlotList, 1.87 + pk11_rsaSlotList, 1.88 + pk11_dsaSlotList, 1.89 + pk11_dhSlotList, 1.90 + pk11_ecSlotList, 1.91 + pk11_ideaSlotList, 1.92 + pk11_sslSlotList, 1.93 + pk11_tlsSlotList, 1.94 + pk11_randomSlotList, 1.95 + pk11_sha256SlotList, 1.96 + pk11_sha512SlotList; /* slots do SHA512 and SHA384 */ 1.97 + 1.98 +/************************************************************ 1.99 + * Generic Slot List and Slot List element manipulations 1.100 + ************************************************************/ 1.101 + 1.102 +/* 1.103 + * allocate a new list 1.104 + */ 1.105 +PK11SlotList * 1.106 +PK11_NewSlotList(void) 1.107 +{ 1.108 + PK11SlotList *list; 1.109 + 1.110 + list = (PK11SlotList *)PORT_Alloc(sizeof(PK11SlotList)); 1.111 + if (list == NULL) return NULL; 1.112 + list->head = NULL; 1.113 + list->tail = NULL; 1.114 + list->lock = PZ_NewLock(nssILockList); 1.115 + if (list->lock == NULL) { 1.116 + PORT_Free(list); 1.117 + return NULL; 1.118 + } 1.119 + 1.120 + return list; 1.121 +} 1.122 + 1.123 +/* 1.124 + * free a list element when all the references go away. 1.125 + */ 1.126 +SECStatus 1.127 +PK11_FreeSlotListElement(PK11SlotList *list, PK11SlotListElement *le) 1.128 +{ 1.129 + PRBool freeit = PR_FALSE; 1.130 + 1.131 + if (list == NULL || le == NULL) { 1.132 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.133 + return SECFailure; 1.134 + } 1.135 + 1.136 + PZ_Lock(list->lock); 1.137 + if (le->refCount-- == 1) { 1.138 + freeit = PR_TRUE; 1.139 + } 1.140 + PZ_Unlock(list->lock); 1.141 + if (freeit) { 1.142 + PK11_FreeSlot(le->slot); 1.143 + PORT_Free(le); 1.144 + } 1.145 + return SECSuccess; 1.146 +} 1.147 + 1.148 +static void 1.149 +pk11_FreeSlotListStatic(PK11SlotList *list) 1.150 +{ 1.151 + PK11SlotListElement *le, *next ; 1.152 + if (list == NULL) return; 1.153 + 1.154 + for (le = list->head ; le; le = next) { 1.155 + next = le->next; 1.156 + PK11_FreeSlotListElement(list,le); 1.157 + } 1.158 + if (list->lock) { 1.159 + PZ_DestroyLock(list->lock); 1.160 + } 1.161 + list->lock = NULL; 1.162 + list->head = NULL; 1.163 +} 1.164 + 1.165 +/* 1.166 + * if we are freeing the list, we must be the only ones with a pointer 1.167 + * to the list. 1.168 + */ 1.169 +void 1.170 +PK11_FreeSlotList(PK11SlotList *list) 1.171 +{ 1.172 + pk11_FreeSlotListStatic(list); 1.173 + PORT_Free(list); 1.174 +} 1.175 + 1.176 +/* 1.177 + * add a slot to a list 1.178 + * "slot" is the slot to be added. Ownership is not transferred. 1.179 + * "sorted" indicates whether or not the slot should be inserted according to 1.180 + * cipherOrder of the associated module. PR_FALSE indicates that the slot 1.181 + * should be inserted to the head of the list. 1.182 + */ 1.183 +SECStatus 1.184 +PK11_AddSlotToList(PK11SlotList *list,PK11SlotInfo *slot, PRBool sorted) 1.185 +{ 1.186 + PK11SlotListElement *le; 1.187 + PK11SlotListElement *element; 1.188 + 1.189 + le = (PK11SlotListElement *) PORT_Alloc(sizeof(PK11SlotListElement)); 1.190 + if (le == NULL) return SECFailure; 1.191 + 1.192 + le->slot = PK11_ReferenceSlot(slot); 1.193 + le->prev = NULL; 1.194 + le->refCount = 1; 1.195 + PZ_Lock(list->lock); 1.196 + element = list->head; 1.197 + /* Insertion sort, with higher cipherOrders are sorted first in the list */ 1.198 + while (element && sorted && (element->slot->module->cipherOrder > 1.199 + le->slot->module->cipherOrder)) { 1.200 + element = element->next; 1.201 + } 1.202 + if (element) { 1.203 + le->prev = element->prev; 1.204 + element->prev = le; 1.205 + le->next = element; 1.206 + } else { 1.207 + le->prev = list->tail; 1.208 + le->next = NULL; 1.209 + list->tail = le; 1.210 + } 1.211 + if (le->prev) le->prev->next = le; 1.212 + if (list->head == element) list->head = le; 1.213 + PZ_Unlock(list->lock); 1.214 + 1.215 + return SECSuccess; 1.216 +} 1.217 + 1.218 +/* 1.219 + * remove a slot entry from the list 1.220 + */ 1.221 +SECStatus 1.222 +PK11_DeleteSlotFromList(PK11SlotList *list,PK11SlotListElement *le) 1.223 +{ 1.224 + PZ_Lock(list->lock); 1.225 + if (le->prev) le->prev->next = le->next; else list->head = le->next; 1.226 + if (le->next) le->next->prev = le->prev; else list->tail = le->prev; 1.227 + le->next = le->prev = NULL; 1.228 + PZ_Unlock(list->lock); 1.229 + PK11_FreeSlotListElement(list,le); 1.230 + return SECSuccess; 1.231 +} 1.232 + 1.233 +/* 1.234 + * Move a list to the end of the target list. 1.235 + * NOTE: There is no locking here... This assumes BOTH lists are private copy 1.236 + * lists. It also does not re-sort the target list. 1.237 + */ 1.238 +SECStatus 1.239 +pk11_MoveListToList(PK11SlotList *target,PK11SlotList *src) 1.240 +{ 1.241 + if (src->head == NULL) return SECSuccess; 1.242 + 1.243 + if (target->tail == NULL) { 1.244 + target->head = src->head; 1.245 + } else { 1.246 + target->tail->next = src->head; 1.247 + } 1.248 + src->head->prev = target->tail; 1.249 + target->tail = src->tail; 1.250 + src->head = src->tail = NULL; 1.251 + return SECSuccess; 1.252 +} 1.253 + 1.254 +/* 1.255 + * get an element from the list with a reference. You must own the list. 1.256 + */ 1.257 +PK11SlotListElement * 1.258 +PK11_GetFirstRef(PK11SlotList *list) 1.259 +{ 1.260 + PK11SlotListElement *le; 1.261 + 1.262 + le = list->head; 1.263 + if (le != NULL) (le)->refCount++; 1.264 + return le; 1.265 +} 1.266 + 1.267 +/* 1.268 + * get the next element from the list with a reference. You must own the list. 1.269 + */ 1.270 +PK11SlotListElement * 1.271 +PK11_GetNextRef(PK11SlotList *list, PK11SlotListElement *le, PRBool restart) 1.272 +{ 1.273 + PK11SlotListElement *new_le; 1.274 + new_le = le->next; 1.275 + if (new_le) new_le->refCount++; 1.276 + PK11_FreeSlotListElement(list,le); 1.277 + return new_le; 1.278 +} 1.279 + 1.280 +/* 1.281 + * get an element safely from the list. This just makes sure that if 1.282 + * this element is not deleted while we deal with it. 1.283 + */ 1.284 +PK11SlotListElement * 1.285 +PK11_GetFirstSafe(PK11SlotList *list) 1.286 +{ 1.287 + PK11SlotListElement *le; 1.288 + 1.289 + PZ_Lock(list->lock); 1.290 + le = list->head; 1.291 + if (le != NULL) (le)->refCount++; 1.292 + PZ_Unlock(list->lock); 1.293 + return le; 1.294 +} 1.295 + 1.296 +/* 1.297 + * NOTE: if this element gets deleted, we can no longer safely traverse using 1.298 + * it's pointers. We can either terminate the loop, or restart from the 1.299 + * beginning. This is controlled by the restart option. 1.300 + */ 1.301 +PK11SlotListElement * 1.302 +PK11_GetNextSafe(PK11SlotList *list, PK11SlotListElement *le, PRBool restart) 1.303 +{ 1.304 + PK11SlotListElement *new_le; 1.305 + PZ_Lock(list->lock); 1.306 + new_le = le->next; 1.307 + if (le->next == NULL) { 1.308 + /* if the prev and next fields are NULL then either this element 1.309 + * has been removed and we need to walk the list again (if restart 1.310 + * is true) or this was the only element on the list */ 1.311 + if ((le->prev == NULL) && restart && (list->head != le)) { 1.312 + new_le = list->head; 1.313 + } 1.314 + } 1.315 + if (new_le) new_le->refCount++; 1.316 + PZ_Unlock(list->lock); 1.317 + PK11_FreeSlotListElement(list,le); 1.318 + return new_le; 1.319 +} 1.320 + 1.321 + 1.322 +/* 1.323 + * Find the element that holds this slot 1.324 + */ 1.325 +PK11SlotListElement * 1.326 +PK11_FindSlotElement(PK11SlotList *list,PK11SlotInfo *slot) 1.327 +{ 1.328 + PK11SlotListElement *le; 1.329 + 1.330 + for (le = PK11_GetFirstSafe(list); le; 1.331 + le = PK11_GetNextSafe(list,le,PR_TRUE)) { 1.332 + if (le->slot == slot) return le; 1.333 + } 1.334 + return NULL; 1.335 +} 1.336 + 1.337 +/************************************************************ 1.338 + * Generic Slot Utilities 1.339 + ************************************************************/ 1.340 +/* 1.341 + * Create a new slot structure 1.342 + */ 1.343 +PK11SlotInfo * 1.344 +PK11_NewSlotInfo(SECMODModule *mod) 1.345 +{ 1.346 + PK11SlotInfo *slot; 1.347 + 1.348 + slot = (PK11SlotInfo *)PORT_Alloc(sizeof(PK11SlotInfo)); 1.349 + if (slot == NULL) return slot; 1.350 + 1.351 + slot->sessionLock = mod->isThreadSafe ? 1.352 + PZ_NewLock(nssILockSession) : mod->refLock; 1.353 + if (slot->sessionLock == NULL) { 1.354 + PORT_Free(slot); 1.355 + return NULL; 1.356 + } 1.357 + slot->freeListLock = PZ_NewLock(nssILockFreelist); 1.358 + if (slot->freeListLock == NULL) { 1.359 + if (mod->isThreadSafe) { 1.360 + PZ_DestroyLock(slot->sessionLock); 1.361 + } 1.362 + PORT_Free(slot); 1.363 + return NULL; 1.364 + } 1.365 + slot->freeSymKeysWithSessionHead = NULL; 1.366 + slot->freeSymKeysHead = NULL; 1.367 + slot->keyCount = 0; 1.368 + slot->maxKeyCount = 0; 1.369 + slot->functionList = NULL; 1.370 + slot->needTest = PR_TRUE; 1.371 + slot->isPerm = PR_FALSE; 1.372 + slot->isHW = PR_FALSE; 1.373 + slot->isInternal = PR_FALSE; 1.374 + slot->isThreadSafe = PR_FALSE; 1.375 + slot->disabled = PR_FALSE; 1.376 + slot->series = 1; 1.377 + slot->wrapKey = 0; 1.378 + slot->wrapMechanism = CKM_INVALID_MECHANISM; 1.379 + slot->refKeys[0] = CK_INVALID_HANDLE; 1.380 + slot->reason = PK11_DIS_NONE; 1.381 + slot->readOnly = PR_TRUE; 1.382 + slot->needLogin = PR_FALSE; 1.383 + slot->hasRandom = PR_FALSE; 1.384 + slot->defRWSession = PR_FALSE; 1.385 + slot->protectedAuthPath = PR_FALSE; 1.386 + slot->flags = 0; 1.387 + slot->session = CK_INVALID_SESSION; 1.388 + slot->slotID = 0; 1.389 + slot->defaultFlags = 0; 1.390 + slot->refCount = 1; 1.391 + slot->askpw = 0; 1.392 + slot->timeout = 0; 1.393 + slot->mechanismList = NULL; 1.394 + slot->mechanismCount = 0; 1.395 + slot->cert_array = NULL; 1.396 + slot->cert_count = 0; 1.397 + slot->slot_name[0] = 0; 1.398 + slot->token_name[0] = 0; 1.399 + PORT_Memset(slot->serial,' ',sizeof(slot->serial)); 1.400 + slot->module = NULL; 1.401 + slot->authTransact = 0; 1.402 + slot->authTime = LL_ZERO; 1.403 + slot->minPassword = 0; 1.404 + slot->maxPassword = 0; 1.405 + slot->hasRootCerts = PR_FALSE; 1.406 + slot->nssToken = NULL; 1.407 + return slot; 1.408 +} 1.409 + 1.410 +/* create a new reference to a slot so it doesn't go away */ 1.411 +PK11SlotInfo * 1.412 +PK11_ReferenceSlot(PK11SlotInfo *slot) 1.413 +{ 1.414 + PR_ATOMIC_INCREMENT(&slot->refCount); 1.415 + return slot; 1.416 +} 1.417 + 1.418 +/* Destroy all info on a slot we have built up */ 1.419 +void 1.420 +PK11_DestroySlot(PK11SlotInfo *slot) 1.421 +{ 1.422 + /* free up the cached keys and sessions */ 1.423 + PK11_CleanKeyList(slot); 1.424 + 1.425 + /* free up all the sessions on this slot */ 1.426 + if (slot->functionList) { 1.427 + PK11_GETTAB(slot)->C_CloseAllSessions(slot->slotID); 1.428 + } 1.429 + 1.430 + if (slot->mechanismList) { 1.431 + PORT_Free(slot->mechanismList); 1.432 + } 1.433 + if (slot->isThreadSafe && slot->sessionLock) { 1.434 + PZ_DestroyLock(slot->sessionLock); 1.435 + } 1.436 + slot->sessionLock = NULL; 1.437 + if (slot->freeListLock) { 1.438 + PZ_DestroyLock(slot->freeListLock); 1.439 + slot->freeListLock = NULL; 1.440 + } 1.441 + 1.442 + /* finally Tell our parent module that we've gone away so it can unload */ 1.443 + if (slot->module) { 1.444 + SECMOD_SlotDestroyModule(slot->module,PR_TRUE); 1.445 + } 1.446 + 1.447 + /* ok, well not quit finally... now we free the memory */ 1.448 + PORT_Free(slot); 1.449 +} 1.450 + 1.451 + 1.452 +/* We're all done with the slot, free it */ 1.453 +void 1.454 +PK11_FreeSlot(PK11SlotInfo *slot) 1.455 +{ 1.456 + if (PR_ATOMIC_DECREMENT(&slot->refCount) == 0) { 1.457 + PK11_DestroySlot(slot); 1.458 + } 1.459 +} 1.460 + 1.461 +void 1.462 +PK11_EnterSlotMonitor(PK11SlotInfo *slot) { 1.463 + PZ_Lock(slot->sessionLock); 1.464 +} 1.465 + 1.466 +void 1.467 +PK11_ExitSlotMonitor(PK11SlotInfo *slot) { 1.468 + PZ_Unlock(slot->sessionLock); 1.469 +} 1.470 + 1.471 +/*********************************************************** 1.472 + * Functions to find specific slots. 1.473 + ***********************************************************/ 1.474 +PRBool 1.475 +SECMOD_HasRootCerts(void) 1.476 +{ 1.477 + SECMODModuleList *mlp; 1.478 + SECMODModuleList *modules; 1.479 + SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); 1.480 + int i; 1.481 + PRBool found = PR_FALSE; 1.482 + 1.483 + if (!moduleLock) { 1.484 + PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 1.485 + return found; 1.486 + } 1.487 + 1.488 + /* work through all the slots */ 1.489 + SECMOD_GetReadLock(moduleLock); 1.490 + modules = SECMOD_GetDefaultModuleList(); 1.491 + for(mlp = modules; mlp != NULL; mlp = mlp->next) { 1.492 + for (i=0; i < mlp->module->slotCount; i++) { 1.493 + PK11SlotInfo *tmpSlot = mlp->module->slots[i]; 1.494 + if (PK11_IsPresent(tmpSlot)) { 1.495 + if (tmpSlot->hasRootCerts) { 1.496 + found = PR_TRUE; 1.497 + break; 1.498 + } 1.499 + } 1.500 + } 1.501 + if (found) break; 1.502 + } 1.503 + SECMOD_ReleaseReadLock(moduleLock); 1.504 + 1.505 + return found; 1.506 +} 1.507 + 1.508 +/*********************************************************** 1.509 + * Functions to find specific slots. 1.510 + ***********************************************************/ 1.511 +PK11SlotList * 1.512 +PK11_FindSlotsByNames(const char *dllName, const char* slotName, 1.513 + const char* tokenName, PRBool presentOnly) 1.514 +{ 1.515 + SECMODModuleList *mlp; 1.516 + SECMODModuleList *modules; 1.517 + SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); 1.518 + int i; 1.519 + PK11SlotList* slotList = NULL; 1.520 + PRUint32 slotcount = 0; 1.521 + SECStatus rv = SECSuccess; 1.522 + 1.523 + if (!moduleLock) { 1.524 + PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 1.525 + return slotList; 1.526 + } 1.527 + 1.528 + slotList = PK11_NewSlotList(); 1.529 + if (!slotList) { 1.530 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.531 + return slotList; 1.532 + } 1.533 + 1.534 + if ( ((NULL == dllName) || (0 == *dllName)) && 1.535 + ((NULL == slotName) || (0 == *slotName)) && 1.536 + ((NULL == tokenName) || (0 == *tokenName)) ) { 1.537 + /* default to softoken */ 1.538 + PK11_AddSlotToList(slotList, PK11_GetInternalKeySlot(), PR_TRUE); 1.539 + return slotList; 1.540 + } 1.541 + 1.542 + /* work through all the slots */ 1.543 + SECMOD_GetReadLock(moduleLock); 1.544 + modules = SECMOD_GetDefaultModuleList(); 1.545 + for (mlp = modules; mlp != NULL; mlp = mlp->next) { 1.546 + PORT_Assert(mlp->module); 1.547 + if (!mlp->module) { 1.548 + rv = SECFailure; 1.549 + break; 1.550 + } 1.551 + if ((!dllName) || (mlp->module->dllName && 1.552 + (0 == PORT_Strcmp(mlp->module->dllName, dllName)))) { 1.553 + for (i=0; i < mlp->module->slotCount; i++) { 1.554 + PK11SlotInfo *tmpSlot = (mlp->module->slots?mlp->module->slots[i]:NULL); 1.555 + PORT_Assert(tmpSlot); 1.556 + if (!tmpSlot) { 1.557 + rv = SECFailure; 1.558 + break; 1.559 + } 1.560 + if ((PR_FALSE == presentOnly || PK11_IsPresent(tmpSlot)) && 1.561 + ( (!tokenName) || (tmpSlot->token_name && 1.562 + (0==PORT_Strcmp(tmpSlot->token_name, tokenName)))) && 1.563 + ( (!slotName) || (tmpSlot->slot_name && 1.564 + (0==PORT_Strcmp(tmpSlot->slot_name, slotName)))) ) { 1.565 + if (tmpSlot) { 1.566 + PK11_AddSlotToList(slotList, tmpSlot, PR_TRUE); 1.567 + slotcount++; 1.568 + } 1.569 + } 1.570 + } 1.571 + } 1.572 + } 1.573 + SECMOD_ReleaseReadLock(moduleLock); 1.574 + 1.575 + if ( (0 == slotcount) || (SECFailure == rv) ) { 1.576 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.577 + PK11_FreeSlotList(slotList); 1.578 + slotList = NULL; 1.579 + } 1.580 + 1.581 + if (SECFailure == rv) { 1.582 + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1.583 + } 1.584 + 1.585 + return slotList; 1.586 +} 1.587 + 1.588 +PK11SlotInfo * 1.589 +PK11_FindSlotByName(const char *name) 1.590 +{ 1.591 + SECMODModuleList *mlp; 1.592 + SECMODModuleList *modules; 1.593 + SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); 1.594 + int i; 1.595 + PK11SlotInfo *slot = NULL; 1.596 + 1.597 + if (!moduleLock) { 1.598 + PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 1.599 + return slot; 1.600 + } 1.601 + if ((name == NULL) || (*name == 0)) { 1.602 + return PK11_GetInternalKeySlot(); 1.603 + } 1.604 + 1.605 + /* work through all the slots */ 1.606 + SECMOD_GetReadLock(moduleLock); 1.607 + modules = SECMOD_GetDefaultModuleList(); 1.608 + for(mlp = modules; mlp != NULL; mlp = mlp->next) { 1.609 + for (i=0; i < mlp->module->slotCount; i++) { 1.610 + PK11SlotInfo *tmpSlot = mlp->module->slots[i]; 1.611 + if (PK11_IsPresent(tmpSlot)) { 1.612 + if (PORT_Strcmp(tmpSlot->token_name,name) == 0) { 1.613 + slot = PK11_ReferenceSlot(tmpSlot); 1.614 + break; 1.615 + } 1.616 + } 1.617 + } 1.618 + if (slot != NULL) break; 1.619 + } 1.620 + SECMOD_ReleaseReadLock(moduleLock); 1.621 + 1.622 + if (slot == NULL) { 1.623 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.624 + } 1.625 + 1.626 + return slot; 1.627 +} 1.628 + 1.629 + 1.630 +PK11SlotInfo * 1.631 +PK11_FindSlotBySerial(char *serial) 1.632 +{ 1.633 + SECMODModuleList *mlp; 1.634 + SECMODModuleList *modules; 1.635 + SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); 1.636 + int i; 1.637 + PK11SlotInfo *slot = NULL; 1.638 + 1.639 + if (!moduleLock) { 1.640 + PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 1.641 + return slot; 1.642 + } 1.643 + /* work through all the slots */ 1.644 + SECMOD_GetReadLock(moduleLock); 1.645 + modules = SECMOD_GetDefaultModuleList(); 1.646 + for(mlp = modules; mlp != NULL; mlp = mlp->next) { 1.647 + for (i=0; i < mlp->module->slotCount; i++) { 1.648 + PK11SlotInfo *tmpSlot = mlp->module->slots[i]; 1.649 + if (PK11_IsPresent(tmpSlot)) { 1.650 + if (PORT_Memcmp(tmpSlot->serial,serial, 1.651 + sizeof(tmpSlot->serial)) == 0) { 1.652 + slot = PK11_ReferenceSlot(tmpSlot); 1.653 + break; 1.654 + } 1.655 + } 1.656 + } 1.657 + if (slot != NULL) break; 1.658 + } 1.659 + SECMOD_ReleaseReadLock(moduleLock); 1.660 + 1.661 + if (slot == NULL) { 1.662 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.663 + } 1.664 + 1.665 + return slot; 1.666 +} 1.667 + 1.668 +/* 1.669 + * notification stub. If we ever get interested in any events that 1.670 + * the pkcs11 functions may pass back to use, we can catch them here... 1.671 + * currently pdata is a slotinfo structure. 1.672 + */ 1.673 +CK_RV pk11_notify(CK_SESSION_HANDLE session, CK_NOTIFICATION event, 1.674 + CK_VOID_PTR pdata) 1.675 +{ 1.676 + return CKR_OK; 1.677 +} 1.678 + 1.679 +/* 1.680 + * grab a new RW session 1.681 + * !!! has a side effect of grabbing the Monitor if either the slot's default 1.682 + * session is RW or the slot is not thread safe. Monitor is release in function 1.683 + * below 1.684 + */ 1.685 +CK_SESSION_HANDLE PK11_GetRWSession(PK11SlotInfo *slot) 1.686 +{ 1.687 + CK_SESSION_HANDLE rwsession; 1.688 + CK_RV crv; 1.689 + PRBool haveMonitor = PR_FALSE; 1.690 + 1.691 + if (!slot->isThreadSafe || slot->defRWSession) { 1.692 + PK11_EnterSlotMonitor(slot); 1.693 + haveMonitor = PR_TRUE; 1.694 + } 1.695 + if (slot->defRWSession) { 1.696 + PORT_Assert(slot->session != CK_INVALID_SESSION); 1.697 + if (slot->session != CK_INVALID_SESSION) 1.698 + return slot->session; 1.699 + } 1.700 + 1.701 + crv = PK11_GETTAB(slot)->C_OpenSession(slot->slotID, 1.702 + CKF_RW_SESSION|CKF_SERIAL_SESSION, 1.703 + slot, pk11_notify,&rwsession); 1.704 + PORT_Assert(rwsession != CK_INVALID_SESSION || crv != CKR_OK); 1.705 + if (crv != CKR_OK || rwsession == CK_INVALID_SESSION) { 1.706 + if (crv == CKR_OK) 1.707 + crv = CKR_DEVICE_ERROR; 1.708 + if (haveMonitor) 1.709 + PK11_ExitSlotMonitor(slot); 1.710 + PORT_SetError(PK11_MapError(crv)); 1.711 + return CK_INVALID_SESSION; 1.712 + } 1.713 + if (slot->defRWSession) { /* we have the monitor */ 1.714 + slot->session = rwsession; 1.715 + } 1.716 + return rwsession; 1.717 +} 1.718 + 1.719 +PRBool 1.720 +PK11_RWSessionHasLock(PK11SlotInfo *slot,CK_SESSION_HANDLE session_handle) 1.721 +{ 1.722 + PRBool hasLock; 1.723 + hasLock = (PRBool)(!slot->isThreadSafe || 1.724 + (slot->defRWSession && slot->session != CK_INVALID_SESSION)); 1.725 + return hasLock; 1.726 +} 1.727 + 1.728 +static PRBool 1.729 +pk11_RWSessionIsDefault(PK11SlotInfo *slot,CK_SESSION_HANDLE rwsession) 1.730 +{ 1.731 + PRBool isDefault; 1.732 + isDefault = (PRBool)(slot->session == rwsession && 1.733 + slot->defRWSession && 1.734 + slot->session != CK_INVALID_SESSION); 1.735 + return isDefault; 1.736 +} 1.737 + 1.738 +/* 1.739 + * close the rwsession and restore our readonly session 1.740 + * !!! has a side effect of releasing the Monitor if either the slot's default 1.741 + * session is RW or the slot is not thread safe. 1.742 + */ 1.743 +void 1.744 +PK11_RestoreROSession(PK11SlotInfo *slot,CK_SESSION_HANDLE rwsession) 1.745 +{ 1.746 + PORT_Assert(rwsession != CK_INVALID_SESSION); 1.747 + if (rwsession != CK_INVALID_SESSION) { 1.748 + PRBool doExit = PK11_RWSessionHasLock(slot, rwsession); 1.749 + if (!pk11_RWSessionIsDefault(slot, rwsession)) 1.750 + PK11_GETTAB(slot)->C_CloseSession(rwsession); 1.751 + if (doExit) 1.752 + PK11_ExitSlotMonitor(slot); 1.753 + } 1.754 +} 1.755 + 1.756 +/************************************************************ 1.757 + * Manage the built-In Slot Lists 1.758 + ************************************************************/ 1.759 + 1.760 +/* Init the static built int slot list (should actually integrate 1.761 + * with PK11_NewSlotList */ 1.762 +static void 1.763 +pk11_InitSlotListStatic(PK11SlotList *list) 1.764 +{ 1.765 + list->lock = PZ_NewLock(nssILockList); 1.766 + list->head = NULL; 1.767 +} 1.768 + 1.769 + 1.770 +/* initialize the system slotlists */ 1.771 +SECStatus 1.772 +PK11_InitSlotLists(void) 1.773 +{ 1.774 + pk11_InitSlotListStatic(&pk11_seedSlotList); 1.775 + pk11_InitSlotListStatic(&pk11_camelliaSlotList); 1.776 + pk11_InitSlotListStatic(&pk11_aesSlotList); 1.777 + pk11_InitSlotListStatic(&pk11_desSlotList); 1.778 + pk11_InitSlotListStatic(&pk11_rc4SlotList); 1.779 + pk11_InitSlotListStatic(&pk11_rc2SlotList); 1.780 + pk11_InitSlotListStatic(&pk11_rc5SlotList); 1.781 + pk11_InitSlotListStatic(&pk11_md5SlotList); 1.782 + pk11_InitSlotListStatic(&pk11_md2SlotList); 1.783 + pk11_InitSlotListStatic(&pk11_sha1SlotList); 1.784 + pk11_InitSlotListStatic(&pk11_rsaSlotList); 1.785 + pk11_InitSlotListStatic(&pk11_dsaSlotList); 1.786 + pk11_InitSlotListStatic(&pk11_dhSlotList); 1.787 + pk11_InitSlotListStatic(&pk11_ecSlotList); 1.788 + pk11_InitSlotListStatic(&pk11_ideaSlotList); 1.789 + pk11_InitSlotListStatic(&pk11_sslSlotList); 1.790 + pk11_InitSlotListStatic(&pk11_tlsSlotList); 1.791 + pk11_InitSlotListStatic(&pk11_randomSlotList); 1.792 + pk11_InitSlotListStatic(&pk11_sha256SlotList); 1.793 + pk11_InitSlotListStatic(&pk11_sha512SlotList); 1.794 + return SECSuccess; 1.795 +} 1.796 + 1.797 +void 1.798 +PK11_DestroySlotLists(void) 1.799 +{ 1.800 + pk11_FreeSlotListStatic(&pk11_seedSlotList); 1.801 + pk11_FreeSlotListStatic(&pk11_camelliaSlotList); 1.802 + pk11_FreeSlotListStatic(&pk11_aesSlotList); 1.803 + pk11_FreeSlotListStatic(&pk11_desSlotList); 1.804 + pk11_FreeSlotListStatic(&pk11_rc4SlotList); 1.805 + pk11_FreeSlotListStatic(&pk11_rc2SlotList); 1.806 + pk11_FreeSlotListStatic(&pk11_rc5SlotList); 1.807 + pk11_FreeSlotListStatic(&pk11_md5SlotList); 1.808 + pk11_FreeSlotListStatic(&pk11_md2SlotList); 1.809 + pk11_FreeSlotListStatic(&pk11_sha1SlotList); 1.810 + pk11_FreeSlotListStatic(&pk11_rsaSlotList); 1.811 + pk11_FreeSlotListStatic(&pk11_dsaSlotList); 1.812 + pk11_FreeSlotListStatic(&pk11_dhSlotList); 1.813 + pk11_FreeSlotListStatic(&pk11_ecSlotList); 1.814 + pk11_FreeSlotListStatic(&pk11_ideaSlotList); 1.815 + pk11_FreeSlotListStatic(&pk11_sslSlotList); 1.816 + pk11_FreeSlotListStatic(&pk11_tlsSlotList); 1.817 + pk11_FreeSlotListStatic(&pk11_randomSlotList); 1.818 + pk11_FreeSlotListStatic(&pk11_sha256SlotList); 1.819 + pk11_FreeSlotListStatic(&pk11_sha512SlotList); 1.820 + return; 1.821 +} 1.822 + 1.823 +/* return a system slot list based on mechanism */ 1.824 +PK11SlotList * 1.825 +PK11_GetSlotList(CK_MECHANISM_TYPE type) 1.826 +{ 1.827 +/* XXX a workaround for Bugzilla bug #55267 */ 1.828 +#if defined(HPUX) && defined(__LP64__) 1.829 + if (CKM_INVALID_MECHANISM == type) 1.830 + return NULL; 1.831 +#endif 1.832 + switch (type) { 1.833 + case CKM_SEED_CBC: 1.834 + case CKM_SEED_ECB: 1.835 + return &pk11_seedSlotList; 1.836 + case CKM_CAMELLIA_CBC: 1.837 + case CKM_CAMELLIA_ECB: 1.838 + return &pk11_camelliaSlotList; 1.839 + case CKM_AES_CBC: 1.840 + case CKM_AES_CCM: 1.841 + case CKM_AES_CTR: 1.842 + case CKM_AES_CTS: 1.843 + case CKM_AES_GCM: 1.844 + case CKM_AES_ECB: 1.845 + return &pk11_aesSlotList; 1.846 + case CKM_DES_CBC: 1.847 + case CKM_DES_ECB: 1.848 + case CKM_DES3_ECB: 1.849 + case CKM_DES3_CBC: 1.850 + return &pk11_desSlotList; 1.851 + case CKM_RC4: 1.852 + return &pk11_rc4SlotList; 1.853 + case CKM_RC5_CBC: 1.854 + return &pk11_rc5SlotList; 1.855 + case CKM_SHA_1: 1.856 + return &pk11_sha1SlotList; 1.857 + case CKM_SHA224: 1.858 + case CKM_SHA256: 1.859 + return &pk11_sha256SlotList; 1.860 + case CKM_SHA384: 1.861 + case CKM_SHA512: 1.862 + return &pk11_sha512SlotList; 1.863 + case CKM_MD5: 1.864 + return &pk11_md5SlotList; 1.865 + case CKM_MD2: 1.866 + return &pk11_md2SlotList; 1.867 + case CKM_RC2_ECB: 1.868 + case CKM_RC2_CBC: 1.869 + return &pk11_rc2SlotList; 1.870 + case CKM_RSA_PKCS: 1.871 + case CKM_RSA_PKCS_KEY_PAIR_GEN: 1.872 + case CKM_RSA_X_509: 1.873 + return &pk11_rsaSlotList; 1.874 + case CKM_DSA: 1.875 + return &pk11_dsaSlotList; 1.876 + case CKM_DH_PKCS_KEY_PAIR_GEN: 1.877 + case CKM_DH_PKCS_DERIVE: 1.878 + return &pk11_dhSlotList; 1.879 + case CKM_ECDSA: 1.880 + case CKM_ECDSA_SHA1: 1.881 + case CKM_EC_KEY_PAIR_GEN: /* aka CKM_ECDSA_KEY_PAIR_GEN */ 1.882 + case CKM_ECDH1_DERIVE: 1.883 + return &pk11_ecSlotList; 1.884 + case CKM_SSL3_PRE_MASTER_KEY_GEN: 1.885 + case CKM_SSL3_MASTER_KEY_DERIVE: 1.886 + case CKM_SSL3_SHA1_MAC: 1.887 + case CKM_SSL3_MD5_MAC: 1.888 + return &pk11_sslSlotList; 1.889 + case CKM_TLS_MASTER_KEY_DERIVE: 1.890 + case CKM_TLS_KEY_AND_MAC_DERIVE: 1.891 + case CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256: 1.892 + return &pk11_tlsSlotList; 1.893 + case CKM_IDEA_CBC: 1.894 + case CKM_IDEA_ECB: 1.895 + return &pk11_ideaSlotList; 1.896 + case CKM_FAKE_RANDOM: 1.897 + return &pk11_randomSlotList; 1.898 + } 1.899 + return NULL; 1.900 +} 1.901 + 1.902 +/* 1.903 + * load the static SlotInfo structures used to select a PKCS11 slot. 1.904 + * preSlotInfo has a list of all the default flags for the slots on this 1.905 + * module. 1.906 + */ 1.907 +void 1.908 +PK11_LoadSlotList(PK11SlotInfo *slot, PK11PreSlotInfo *psi, int count) 1.909 +{ 1.910 + int i; 1.911 + 1.912 + for (i=0; i < count; i++) { 1.913 + if (psi[i].slotID == slot->slotID) 1.914 + break; 1.915 + } 1.916 + 1.917 + if (i == count) return; 1.918 + 1.919 + slot->defaultFlags = psi[i].defaultFlags; 1.920 + slot->askpw = psi[i].askpw; 1.921 + slot->timeout = psi[i].timeout; 1.922 + slot->hasRootCerts = psi[i].hasRootCerts; 1.923 + 1.924 + /* if the slot is already disabled, don't load them into the 1.925 + * default slot lists. We get here so we can save the default 1.926 + * list value. */ 1.927 + if (slot->disabled) return; 1.928 + 1.929 + /* if the user has disabled us, don't load us in */ 1.930 + if (slot->defaultFlags & PK11_DISABLE_FLAG) { 1.931 + slot->disabled = PR_TRUE; 1.932 + slot->reason = PK11_DIS_USER_SELECTED; 1.933 + /* free up sessions and things?? */ 1.934 + return; 1.935 + } 1.936 + 1.937 + for (i=0; i < num_pk11_default_mechanisms; i++) { 1.938 + if (slot->defaultFlags & PK11_DefaultArray[i].flag) { 1.939 + CK_MECHANISM_TYPE mechanism = PK11_DefaultArray[i].mechanism; 1.940 + PK11SlotList *slotList = PK11_GetSlotList(mechanism); 1.941 + 1.942 + if (slotList) PK11_AddSlotToList(slotList,slot,PR_FALSE); 1.943 + } 1.944 + } 1.945 + 1.946 + return; 1.947 +} 1.948 + 1.949 + 1.950 +/* 1.951 + * update a slot to its new attribute according to the slot list 1.952 + * returns: SECSuccess if nothing to do or add/delete is successful 1.953 + */ 1.954 +SECStatus 1.955 +PK11_UpdateSlotAttribute(PK11SlotInfo *slot, 1.956 + const PK11DefaultArrayEntry *entry, 1.957 + PRBool add) 1.958 + /* add: PR_TRUE if want to turn on */ 1.959 +{ 1.960 + SECStatus result = SECSuccess; 1.961 + PK11SlotList *slotList = PK11_GetSlotList(entry->mechanism); 1.962 + 1.963 + if (add) { /* trying to turn on a mechanism */ 1.964 + 1.965 + /* turn on the default flag in the slot */ 1.966 + slot->defaultFlags |= entry->flag; 1.967 + 1.968 + /* add this slot to the list */ 1.969 + if (slotList!=NULL) 1.970 + result = PK11_AddSlotToList(slotList, slot, PR_FALSE); 1.971 + 1.972 + } else { /* trying to turn off */ 1.973 + 1.974 + /* turn OFF the flag in the slot */ 1.975 + slot->defaultFlags &= ~entry->flag; 1.976 + 1.977 + if (slotList) { 1.978 + /* find the element in the list & delete it */ 1.979 + PK11SlotListElement *le = PK11_FindSlotElement(slotList, slot); 1.980 + 1.981 + /* remove the slot from the list */ 1.982 + if (le) 1.983 + result = PK11_DeleteSlotFromList(slotList, le); 1.984 + } 1.985 + } 1.986 + return result; 1.987 +} 1.988 + 1.989 +/* 1.990 + * clear a slot off of all of it's default list 1.991 + */ 1.992 +void 1.993 +PK11_ClearSlotList(PK11SlotInfo *slot) 1.994 +{ 1.995 + int i; 1.996 + 1.997 + if (slot->disabled) return; 1.998 + if (slot->defaultFlags == 0) return; 1.999 + 1.1000 + for (i=0; i < num_pk11_default_mechanisms; i++) { 1.1001 + if (slot->defaultFlags & PK11_DefaultArray[i].flag) { 1.1002 + CK_MECHANISM_TYPE mechanism = PK11_DefaultArray[i].mechanism; 1.1003 + PK11SlotList *slotList = PK11_GetSlotList(mechanism); 1.1004 + PK11SlotListElement *le = NULL; 1.1005 + 1.1006 + if (slotList) le = PK11_FindSlotElement(slotList,slot); 1.1007 + 1.1008 + if (le) { 1.1009 + PK11_DeleteSlotFromList(slotList,le); 1.1010 + PK11_FreeSlotListElement(slotList,le); 1.1011 + } 1.1012 + } 1.1013 + } 1.1014 +} 1.1015 + 1.1016 + 1.1017 +/****************************************************************** 1.1018 + * Slot initialization 1.1019 + ******************************************************************/ 1.1020 +/* 1.1021 + * turn a PKCS11 Static Label into a string 1.1022 + */ 1.1023 +char * 1.1024 +PK11_MakeString(PLArenaPool *arena,char *space, 1.1025 + char *staticString,int stringLen) 1.1026 +{ 1.1027 + int i; 1.1028 + char *newString; 1.1029 + for(i=(stringLen-1); i >= 0; i--) { 1.1030 + if (staticString[i] != ' ') break; 1.1031 + } 1.1032 + /* move i to point to the last space */ 1.1033 + i++; 1.1034 + if (arena) { 1.1035 + newString = (char*)PORT_ArenaAlloc(arena,i+1 /* space for NULL */); 1.1036 + } else if (space) { 1.1037 + newString = space; 1.1038 + } else { 1.1039 + newString = (char*)PORT_Alloc(i+1 /* space for NULL */); 1.1040 + } 1.1041 + if (newString == NULL) return NULL; 1.1042 + 1.1043 + if (i) PORT_Memcpy(newString,staticString, i); 1.1044 + newString[i] = 0; 1.1045 + 1.1046 + return newString; 1.1047 +} 1.1048 + 1.1049 +/* 1.1050 + * Reads in the slots mechanism list for later use 1.1051 + */ 1.1052 +SECStatus 1.1053 +PK11_ReadMechanismList(PK11SlotInfo *slot) 1.1054 +{ 1.1055 + CK_ULONG count; 1.1056 + CK_RV crv; 1.1057 + PRUint32 i; 1.1058 + 1.1059 + if (slot->mechanismList) { 1.1060 + PORT_Free(slot->mechanismList); 1.1061 + slot->mechanismList = NULL; 1.1062 + } 1.1063 + slot->mechanismCount = 0; 1.1064 + 1.1065 + if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); 1.1066 + crv = PK11_GETTAB(slot)->C_GetMechanismList(slot->slotID,NULL,&count); 1.1067 + if (crv != CKR_OK) { 1.1068 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.1069 + PORT_SetError(PK11_MapError(crv)); 1.1070 + return SECFailure; 1.1071 + } 1.1072 + 1.1073 + slot->mechanismList = (CK_MECHANISM_TYPE *) 1.1074 + PORT_Alloc(count *sizeof(CK_MECHANISM_TYPE)); 1.1075 + if (slot->mechanismList == NULL) { 1.1076 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.1077 + return SECFailure; 1.1078 + } 1.1079 + crv = PK11_GETTAB(slot)->C_GetMechanismList(slot->slotID, 1.1080 + slot->mechanismList, &count); 1.1081 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.1082 + if (crv != CKR_OK) { 1.1083 + PORT_Free(slot->mechanismList); 1.1084 + slot->mechanismList = NULL; 1.1085 + PORT_SetError(PK11_MapError(crv)); 1.1086 + return SECSuccess; 1.1087 + } 1.1088 + slot->mechanismCount = count; 1.1089 + PORT_Memset(slot->mechanismBits, 0, sizeof(slot->mechanismBits)); 1.1090 + 1.1091 + for (i=0; i < count; i++) { 1.1092 + CK_MECHANISM_TYPE mech = slot->mechanismList[i]; 1.1093 + if (mech < 0x7ff) { 1.1094 + slot->mechanismBits[mech & 0xff] |= 1 << (mech >> 8); 1.1095 + } 1.1096 + } 1.1097 + return SECSuccess; 1.1098 +} 1.1099 + 1.1100 +/* 1.1101 + * initialize a new token 1.1102 + * unlike initialize slot, this can be called multiple times in the lifetime 1.1103 + * of NSS. It reads the information associated with a card or token, 1.1104 + * that is not going to change unless the card or token changes. 1.1105 + */ 1.1106 +SECStatus 1.1107 +PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts) 1.1108 +{ 1.1109 + CK_TOKEN_INFO tokenInfo; 1.1110 + CK_RV crv; 1.1111 + char *tmp; 1.1112 + SECStatus rv; 1.1113 + PRStatus status; 1.1114 + 1.1115 + /* set the slot flags to the current token values */ 1.1116 + if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); 1.1117 + crv = PK11_GETTAB(slot)->C_GetTokenInfo(slot->slotID,&tokenInfo); 1.1118 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.1119 + if (crv != CKR_OK) { 1.1120 + PORT_SetError(PK11_MapError(crv)); 1.1121 + return SECFailure; 1.1122 + } 1.1123 + 1.1124 + /* set the slot flags to the current token values */ 1.1125 + slot->series++; /* allow other objects to detect that the 1.1126 + * slot is different */ 1.1127 + slot->flags = tokenInfo.flags; 1.1128 + slot->needLogin = ((tokenInfo.flags & CKF_LOGIN_REQUIRED) ? 1.1129 + PR_TRUE : PR_FALSE); 1.1130 + slot->readOnly = ((tokenInfo.flags & CKF_WRITE_PROTECTED) ? 1.1131 + PR_TRUE : PR_FALSE); 1.1132 + 1.1133 + 1.1134 + slot->hasRandom = ((tokenInfo.flags & CKF_RNG) ? PR_TRUE : PR_FALSE); 1.1135 + slot->protectedAuthPath = 1.1136 + ((tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) 1.1137 + ? PR_TRUE : PR_FALSE); 1.1138 + slot->lastLoginCheck = 0; 1.1139 + slot->lastState = 0; 1.1140 + /* on some platforms Active Card incorrectly sets the 1.1141 + * CKF_PROTECTED_AUTHENTICATION_PATH bit when it doesn't mean to. */ 1.1142 + if (slot->isActiveCard) { 1.1143 + slot->protectedAuthPath = PR_FALSE; 1.1144 + } 1.1145 + tmp = PK11_MakeString(NULL,slot->token_name, 1.1146 + (char *)tokenInfo.label, sizeof(tokenInfo.label)); 1.1147 + slot->minPassword = tokenInfo.ulMinPinLen; 1.1148 + slot->maxPassword = tokenInfo.ulMaxPinLen; 1.1149 + PORT_Memcpy(slot->serial,tokenInfo.serialNumber,sizeof(slot->serial)); 1.1150 + 1.1151 + nssToken_UpdateName(slot->nssToken); 1.1152 + 1.1153 + slot->defRWSession = (PRBool)((!slot->readOnly) && 1.1154 + (tokenInfo.ulMaxSessionCount == 1)); 1.1155 + rv = PK11_ReadMechanismList(slot); 1.1156 + if (rv != SECSuccess) return rv; 1.1157 + 1.1158 + slot->hasRSAInfo = PR_FALSE; 1.1159 + slot->RSAInfoFlags = 0; 1.1160 + 1.1161 + /* initialize the maxKeyCount value */ 1.1162 + if (tokenInfo.ulMaxSessionCount == 0) { 1.1163 + slot->maxKeyCount = 800; /* should be #define or a config param */ 1.1164 + } else if (tokenInfo.ulMaxSessionCount < 20) { 1.1165 + /* don't have enough sessions to keep that many keys around */ 1.1166 + slot->maxKeyCount = 0; 1.1167 + } else { 1.1168 + slot->maxKeyCount = tokenInfo.ulMaxSessionCount/2; 1.1169 + } 1.1170 + 1.1171 + /* Make sure our session handle is valid */ 1.1172 + if (slot->session == CK_INVALID_SESSION) { 1.1173 + /* we know we don't have a valid session, go get one */ 1.1174 + CK_SESSION_HANDLE session; 1.1175 + 1.1176 + /* session should be Readonly, serial */ 1.1177 + if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); 1.1178 + crv = PK11_GETTAB(slot)->C_OpenSession(slot->slotID, 1.1179 + (slot->defRWSession ? CKF_RW_SESSION : 0) | CKF_SERIAL_SESSION, 1.1180 + slot,pk11_notify,&session); 1.1181 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.1182 + if (crv != CKR_OK) { 1.1183 + PORT_SetError(PK11_MapError(crv)); 1.1184 + return SECFailure; 1.1185 + } 1.1186 + slot->session = session; 1.1187 + } else { 1.1188 + /* The session we have may be defunct (the token associated with it) 1.1189 + * has been removed */ 1.1190 + CK_SESSION_INFO sessionInfo; 1.1191 + 1.1192 + if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); 1.1193 + crv = PK11_GETTAB(slot)->C_GetSessionInfo(slot->session,&sessionInfo); 1.1194 + if (crv == CKR_DEVICE_ERROR) { 1.1195 + PK11_GETTAB(slot)->C_CloseSession(slot->session); 1.1196 + crv = CKR_SESSION_CLOSED; 1.1197 + } 1.1198 + if ((crv==CKR_SESSION_CLOSED) || (crv==CKR_SESSION_HANDLE_INVALID)) { 1.1199 + crv =PK11_GETTAB(slot)->C_OpenSession(slot->slotID, 1.1200 + (slot->defRWSession ? CKF_RW_SESSION : 0) | CKF_SERIAL_SESSION, 1.1201 + slot,pk11_notify,&slot->session); 1.1202 + if (crv != CKR_OK) { 1.1203 + PORT_SetError(PK11_MapError(crv)); 1.1204 + slot->session = CK_INVALID_SESSION; 1.1205 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.1206 + return SECFailure; 1.1207 + } 1.1208 + } 1.1209 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.1210 + } 1.1211 + 1.1212 + status = nssToken_Refresh(slot->nssToken); 1.1213 + if (status != PR_SUCCESS) 1.1214 + return SECFailure; 1.1215 + 1.1216 + if (!(slot->isInternal) && (slot->hasRandom)) { 1.1217 + /* if this slot has a random number generater, use it to add entropy 1.1218 + * to the internal slot. */ 1.1219 + PK11SlotInfo *int_slot = PK11_GetInternalSlot(); 1.1220 + 1.1221 + if (int_slot) { 1.1222 + unsigned char random_bytes[32]; 1.1223 + 1.1224 + /* if this slot can issue random numbers, get some entropy from 1.1225 + * that random number generater and give it to our internal token. 1.1226 + */ 1.1227 + PK11_EnterSlotMonitor(slot); 1.1228 + crv = PK11_GETTAB(slot)->C_GenerateRandom 1.1229 + (slot->session,random_bytes, sizeof(random_bytes)); 1.1230 + PK11_ExitSlotMonitor(slot); 1.1231 + if (crv == CKR_OK) { 1.1232 + PK11_EnterSlotMonitor(int_slot); 1.1233 + PK11_GETTAB(int_slot)->C_SeedRandom(int_slot->session, 1.1234 + random_bytes, sizeof(random_bytes)); 1.1235 + PK11_ExitSlotMonitor(int_slot); 1.1236 + } 1.1237 + 1.1238 + /* Now return the favor and send entropy to the token's random 1.1239 + * number generater */ 1.1240 + PK11_EnterSlotMonitor(int_slot); 1.1241 + crv = PK11_GETTAB(int_slot)->C_GenerateRandom(int_slot->session, 1.1242 + random_bytes, sizeof(random_bytes)); 1.1243 + PK11_ExitSlotMonitor(int_slot); 1.1244 + if (crv == CKR_OK) { 1.1245 + PK11_EnterSlotMonitor(slot); 1.1246 + crv = PK11_GETTAB(slot)->C_SeedRandom(slot->session, 1.1247 + random_bytes, sizeof(random_bytes)); 1.1248 + PK11_ExitSlotMonitor(slot); 1.1249 + } 1.1250 + PK11_FreeSlot(int_slot); 1.1251 + } 1.1252 + } 1.1253 + /* work around a problem in softoken where it incorrectly 1.1254 + * reports databases opened read only as read/write. */ 1.1255 + if (slot->isInternal && !slot->readOnly) { 1.1256 + CK_SESSION_HANDLE session = CK_INVALID_SESSION; 1.1257 + 1.1258 + /* try to open a R/W session */ 1.1259 + crv =PK11_GETTAB(slot)->C_OpenSession(slot->slotID, 1.1260 + CKF_RW_SESSION|CKF_SERIAL_SESSION, slot, pk11_notify ,&session); 1.1261 + /* what a well behaved token should return if you open 1.1262 + * a RW session on a read only token */ 1.1263 + if (crv == CKR_TOKEN_WRITE_PROTECTED) { 1.1264 + slot->readOnly = PR_TRUE; 1.1265 + } else if (crv == CKR_OK) { 1.1266 + CK_SESSION_INFO sessionInfo; 1.1267 + 1.1268 + /* Because of a second bug in softoken, which silently returns 1.1269 + * a RO session, we need to check what type of session we got. */ 1.1270 + crv = PK11_GETTAB(slot)->C_GetSessionInfo(session, &sessionInfo); 1.1271 + if (crv == CKR_OK) { 1.1272 + if ((sessionInfo.flags & CKF_RW_SESSION) == 0) { 1.1273 + /* session was readonly, so this softoken slot must be * readonly */ 1.1274 + slot->readOnly = PR_TRUE; 1.1275 + } 1.1276 + } 1.1277 + PK11_GETTAB(slot)->C_CloseSession(session); 1.1278 + } 1.1279 + } 1.1280 + 1.1281 + return SECSuccess; 1.1282 +} 1.1283 + 1.1284 +/* 1.1285 + * initialize a new token 1.1286 + * unlike initialize slot, this can be called multiple times in the lifetime 1.1287 + * of NSS. It reads the information associated with a card or token, 1.1288 + * that is not going to change unless the card or token changes. 1.1289 + */ 1.1290 +SECStatus 1.1291 +PK11_TokenRefresh(PK11SlotInfo *slot) 1.1292 +{ 1.1293 + CK_TOKEN_INFO tokenInfo; 1.1294 + CK_RV crv; 1.1295 + 1.1296 + /* set the slot flags to the current token values */ 1.1297 + if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); 1.1298 + crv = PK11_GETTAB(slot)->C_GetTokenInfo(slot->slotID,&tokenInfo); 1.1299 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.1300 + if (crv != CKR_OK) { 1.1301 + PORT_SetError(PK11_MapError(crv)); 1.1302 + return SECFailure; 1.1303 + } 1.1304 + 1.1305 + slot->flags = tokenInfo.flags; 1.1306 + slot->needLogin = ((tokenInfo.flags & CKF_LOGIN_REQUIRED) ? 1.1307 + PR_TRUE : PR_FALSE); 1.1308 + slot->readOnly = ((tokenInfo.flags & CKF_WRITE_PROTECTED) ? 1.1309 + PR_TRUE : PR_FALSE); 1.1310 + slot->hasRandom = ((tokenInfo.flags & CKF_RNG) ? PR_TRUE : PR_FALSE); 1.1311 + slot->protectedAuthPath = 1.1312 + ((tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) 1.1313 + ? PR_TRUE : PR_FALSE); 1.1314 + /* on some platforms Active Card incorrectly sets the 1.1315 + * CKF_PROTECTED_AUTHENTICATION_PATH bit when it doesn't mean to. */ 1.1316 + if (slot->isActiveCard) { 1.1317 + slot->protectedAuthPath = PR_FALSE; 1.1318 + } 1.1319 + return SECSuccess; 1.1320 +} 1.1321 + 1.1322 +static PRBool 1.1323 +pk11_isRootSlot(PK11SlotInfo *slot) 1.1324 +{ 1.1325 + CK_ATTRIBUTE findTemp[1]; 1.1326 + CK_ATTRIBUTE *attrs; 1.1327 + CK_OBJECT_CLASS oclass = CKO_NETSCAPE_BUILTIN_ROOT_LIST; 1.1328 + int tsize; 1.1329 + CK_OBJECT_HANDLE handle; 1.1330 + 1.1331 + attrs = findTemp; 1.1332 + PK11_SETATTRS(attrs, CKA_CLASS, &oclass, sizeof(oclass)); attrs++; 1.1333 + tsize = attrs - findTemp; 1.1334 + PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE)); 1.1335 + 1.1336 + handle = pk11_FindObjectByTemplate(slot,findTemp,tsize); 1.1337 + if (handle == CK_INVALID_HANDLE) { 1.1338 + return PR_FALSE; 1.1339 + } 1.1340 + return PR_TRUE; 1.1341 +} 1.1342 + 1.1343 +/* 1.1344 + * Initialize the slot : 1.1345 + * This initialization code is called on each slot a module supports when 1.1346 + * it is loaded. It does the bringup initialization. The difference between 1.1347 + * this and InitToken is Init slot does those one time initialization stuff, 1.1348 + * usually associated with the reader, while InitToken may get called multiple 1.1349 + * times as tokens are removed and re-inserted. 1.1350 + */ 1.1351 +void 1.1352 +PK11_InitSlot(SECMODModule *mod, CK_SLOT_ID slotID, PK11SlotInfo *slot) 1.1353 +{ 1.1354 + SECStatus rv; 1.1355 + char *tmp; 1.1356 + CK_SLOT_INFO slotInfo; 1.1357 + 1.1358 + slot->functionList = mod->functionList; 1.1359 + slot->isInternal = mod->internal; 1.1360 + slot->slotID = slotID; 1.1361 + slot->isThreadSafe = mod->isThreadSafe; 1.1362 + slot->hasRSAInfo = PR_FALSE; 1.1363 + 1.1364 + if (PK11_GETTAB(slot)->C_GetSlotInfo(slotID,&slotInfo) != CKR_OK) { 1.1365 + slot->disabled = PR_TRUE; 1.1366 + slot->reason = PK11_DIS_COULD_NOT_INIT_TOKEN; 1.1367 + return; 1.1368 + } 1.1369 + 1.1370 + /* test to make sure claimed mechanism work */ 1.1371 + slot->needTest = mod->internal ? PR_FALSE : PR_TRUE; 1.1372 + slot->module = mod; /* NOTE: we don't make a reference here because 1.1373 + * modules have references to their slots. This 1.1374 + * works because modules keep implicit references 1.1375 + * from their slots, and won't unload and disappear 1.1376 + * until all their slots have been freed */ 1.1377 + tmp = PK11_MakeString(NULL,slot->slot_name, 1.1378 + (char *)slotInfo.slotDescription, sizeof(slotInfo.slotDescription)); 1.1379 + slot->isHW = (PRBool)((slotInfo.flags & CKF_HW_SLOT) == CKF_HW_SLOT); 1.1380 +#define ACTIVE_CARD "ActivCard SA" 1.1381 + slot->isActiveCard = (PRBool)(PORT_Strncmp((char *)slotInfo.manufacturerID, 1.1382 + ACTIVE_CARD, sizeof(ACTIVE_CARD)-1) == 0); 1.1383 + if ((slotInfo.flags & CKF_REMOVABLE_DEVICE) == 0) { 1.1384 + slot->isPerm = PR_TRUE; 1.1385 + /* permanment slots must have the token present always */ 1.1386 + if ((slotInfo.flags & CKF_TOKEN_PRESENT) == 0) { 1.1387 + slot->disabled = PR_TRUE; 1.1388 + slot->reason = PK11_DIS_TOKEN_NOT_PRESENT; 1.1389 + return; /* nothing else to do */ 1.1390 + } 1.1391 + } 1.1392 + /* if the token is present, initialize it */ 1.1393 + if ((slotInfo.flags & CKF_TOKEN_PRESENT) != 0) { 1.1394 + rv = PK11_InitToken(slot,PR_TRUE); 1.1395 + /* the only hard failures are on permanent devices, or function 1.1396 + * verify failures... function verify failures are already handled 1.1397 + * by tokenInit */ 1.1398 + if ((rv != SECSuccess) && (slot->isPerm) && (!slot->disabled)) { 1.1399 + slot->disabled = PR_TRUE; 1.1400 + slot->reason = PK11_DIS_COULD_NOT_INIT_TOKEN; 1.1401 + } 1.1402 + if (rv == SECSuccess && pk11_isRootSlot(slot)) { 1.1403 + if (!slot->hasRootCerts) { 1.1404 + slot->module->trustOrder = 100; 1.1405 + } 1.1406 + slot->hasRootCerts= PR_TRUE; 1.1407 + } 1.1408 + } 1.1409 +} 1.1410 + 1.1411 + 1.1412 + 1.1413 +/********************************************************************* 1.1414 + * Slot mapping utility functions. 1.1415 + *********************************************************************/ 1.1416 + 1.1417 +/* 1.1418 + * determine if the token is present. If the token is present, make sure 1.1419 + * we have a valid session handle. Also set the value of needLogin 1.1420 + * appropriately. 1.1421 + */ 1.1422 +static PRBool 1.1423 +pk11_IsPresentCertLoad(PK11SlotInfo *slot, PRBool loadCerts) 1.1424 +{ 1.1425 + CK_SLOT_INFO slotInfo; 1.1426 + CK_SESSION_INFO sessionInfo; 1.1427 + CK_RV crv; 1.1428 + 1.1429 + /* disabled slots are never present */ 1.1430 + if (slot->disabled) { 1.1431 + return PR_FALSE; 1.1432 + } 1.1433 + 1.1434 + /* permanent slots are always present */ 1.1435 + if (slot->isPerm && (slot->session != CK_INVALID_SESSION)) { 1.1436 + return PR_TRUE; 1.1437 + } 1.1438 + 1.1439 + if (slot->nssToken) { 1.1440 + return nssToken_IsPresent(slot->nssToken); 1.1441 + } 1.1442 + 1.1443 + /* removable slots have a flag that says they are present */ 1.1444 + if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); 1.1445 + if (PK11_GETTAB(slot)->C_GetSlotInfo(slot->slotID,&slotInfo) != CKR_OK) { 1.1446 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.1447 + return PR_FALSE; 1.1448 + } 1.1449 + if ((slotInfo.flags & CKF_TOKEN_PRESENT) == 0) { 1.1450 + /* if the slot is no longer present, close the session */ 1.1451 + if (slot->session != CK_INVALID_SESSION) { 1.1452 + PK11_GETTAB(slot)->C_CloseSession(slot->session); 1.1453 + slot->session = CK_INVALID_SESSION; 1.1454 + } 1.1455 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.1456 + return PR_FALSE; 1.1457 + } 1.1458 + 1.1459 + /* use the session Info to determine if the card has been removed and then 1.1460 + * re-inserted */ 1.1461 + if (slot->session != CK_INVALID_SESSION) { 1.1462 + if (slot->isThreadSafe) PK11_EnterSlotMonitor(slot); 1.1463 + crv = PK11_GETTAB(slot)->C_GetSessionInfo(slot->session, &sessionInfo); 1.1464 + if (crv != CKR_OK) { 1.1465 + PK11_GETTAB(slot)->C_CloseSession(slot->session); 1.1466 + slot->session = CK_INVALID_SESSION; 1.1467 + } 1.1468 + if (slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.1469 + } 1.1470 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.1471 + 1.1472 + /* card has not been removed, current token info is correct */ 1.1473 + if (slot->session != CK_INVALID_SESSION) return PR_TRUE; 1.1474 + 1.1475 + /* initialize the token info state */ 1.1476 + if (PK11_InitToken(slot,loadCerts) != SECSuccess) { 1.1477 + return PR_FALSE; 1.1478 + } 1.1479 + 1.1480 + return PR_TRUE; 1.1481 +} 1.1482 + 1.1483 +/* 1.1484 + * old version of the routine 1.1485 + */ 1.1486 +PRBool 1.1487 +PK11_IsPresent(PK11SlotInfo *slot) { 1.1488 + return pk11_IsPresentCertLoad(slot,PR_TRUE); 1.1489 +} 1.1490 + 1.1491 +/* is the slot disabled? */ 1.1492 +PRBool 1.1493 +PK11_IsDisabled(PK11SlotInfo *slot) 1.1494 +{ 1.1495 + return slot->disabled; 1.1496 +} 1.1497 + 1.1498 +/* and why? */ 1.1499 +PK11DisableReasons 1.1500 +PK11_GetDisabledReason(PK11SlotInfo *slot) 1.1501 +{ 1.1502 + return slot->reason; 1.1503 +} 1.1504 + 1.1505 +/* returns PR_TRUE if successfully disable the slot */ 1.1506 +/* returns PR_FALSE otherwise */ 1.1507 +PRBool PK11_UserDisableSlot(PK11SlotInfo *slot) { 1.1508 + 1.1509 + /* Prevent users from disabling the internal module. */ 1.1510 + if (slot->isInternal) { 1.1511 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.1512 + return PR_FALSE; 1.1513 + } 1.1514 + 1.1515 + slot->defaultFlags |= PK11_DISABLE_FLAG; 1.1516 + slot->disabled = PR_TRUE; 1.1517 + slot->reason = PK11_DIS_USER_SELECTED; 1.1518 + 1.1519 + return PR_TRUE; 1.1520 +} 1.1521 + 1.1522 +PRBool PK11_UserEnableSlot(PK11SlotInfo *slot) { 1.1523 + 1.1524 + slot->defaultFlags &= ~PK11_DISABLE_FLAG; 1.1525 + slot->disabled = PR_FALSE; 1.1526 + slot->reason = PK11_DIS_NONE; 1.1527 + return PR_TRUE; 1.1528 +} 1.1529 + 1.1530 +PRBool PK11_HasRootCerts(PK11SlotInfo *slot) { 1.1531 + return slot->hasRootCerts; 1.1532 +} 1.1533 + 1.1534 +/* Get the module this slot is attached to */ 1.1535 +SECMODModule * 1.1536 +PK11_GetModule(PK11SlotInfo *slot) 1.1537 +{ 1.1538 + return slot->module; 1.1539 +} 1.1540 + 1.1541 +/* return the default flags of a slot */ 1.1542 +unsigned long 1.1543 +PK11_GetDefaultFlags(PK11SlotInfo *slot) 1.1544 +{ 1.1545 + return slot->defaultFlags; 1.1546 +} 1.1547 + 1.1548 +/* 1.1549 + * The following wrapper functions allow us to export an opaque slot 1.1550 + * function to the rest of libsec and the world... */ 1.1551 +PRBool 1.1552 +PK11_IsReadOnly(PK11SlotInfo *slot) 1.1553 +{ 1.1554 + return slot->readOnly; 1.1555 +} 1.1556 + 1.1557 +PRBool 1.1558 +PK11_IsHW(PK11SlotInfo *slot) 1.1559 +{ 1.1560 + return slot->isHW; 1.1561 +} 1.1562 + 1.1563 +PRBool 1.1564 +PK11_IsRemovable(PK11SlotInfo *slot) 1.1565 +{ 1.1566 + return !slot->isPerm; 1.1567 +} 1.1568 + 1.1569 +PRBool 1.1570 +PK11_IsInternal(PK11SlotInfo *slot) 1.1571 +{ 1.1572 + return slot->isInternal; 1.1573 +} 1.1574 + 1.1575 +PRBool 1.1576 +PK11_IsInternalKeySlot(PK11SlotInfo *slot) 1.1577 +{ 1.1578 + PK11SlotInfo *int_slot; 1.1579 + PRBool result; 1.1580 + 1.1581 + if (!slot->isInternal) { 1.1582 + return PR_FALSE; 1.1583 + } 1.1584 + 1.1585 + int_slot = PK11_GetInternalKeySlot(); 1.1586 + result = (int_slot == slot) ? PR_TRUE : PR_FALSE; 1.1587 + PK11_FreeSlot(int_slot); 1.1588 + return result; 1.1589 +} 1.1590 + 1.1591 +PRBool 1.1592 +PK11_NeedLogin(PK11SlotInfo *slot) 1.1593 +{ 1.1594 + return slot->needLogin; 1.1595 +} 1.1596 + 1.1597 +PRBool 1.1598 +PK11_IsFriendly(PK11SlotInfo *slot) 1.1599 +{ 1.1600 + /* internal slot always has public readable certs */ 1.1601 + return (PRBool)(slot->isInternal || 1.1602 + ((slot->defaultFlags & SECMOD_FRIENDLY_FLAG) == 1.1603 + SECMOD_FRIENDLY_FLAG)); 1.1604 +} 1.1605 + 1.1606 +char * 1.1607 +PK11_GetTokenName(PK11SlotInfo *slot) 1.1608 +{ 1.1609 + return slot->token_name; 1.1610 +} 1.1611 + 1.1612 +char * 1.1613 +PK11_GetSlotName(PK11SlotInfo *slot) 1.1614 +{ 1.1615 + return slot->slot_name; 1.1616 +} 1.1617 + 1.1618 +int 1.1619 +PK11_GetSlotSeries(PK11SlotInfo *slot) 1.1620 +{ 1.1621 + return slot->series; 1.1622 +} 1.1623 + 1.1624 +int 1.1625 +PK11_GetCurrentWrapIndex(PK11SlotInfo *slot) 1.1626 +{ 1.1627 + return slot->wrapKey; 1.1628 +} 1.1629 + 1.1630 +CK_SLOT_ID 1.1631 +PK11_GetSlotID(PK11SlotInfo *slot) 1.1632 +{ 1.1633 + return slot->slotID; 1.1634 +} 1.1635 + 1.1636 +SECMODModuleID 1.1637 +PK11_GetModuleID(PK11SlotInfo *slot) 1.1638 +{ 1.1639 + return slot->module->moduleID; 1.1640 +} 1.1641 + 1.1642 +static void 1.1643 +pk11_zeroTerminatedToBlankPadded(CK_CHAR *buffer, size_t buffer_size) 1.1644 +{ 1.1645 + CK_CHAR *walk = buffer; 1.1646 + CK_CHAR *end = buffer + buffer_size; 1.1647 + 1.1648 + /* find the NULL */ 1.1649 + while (walk < end && *walk != '\0') { 1.1650 + walk++; 1.1651 + } 1.1652 + 1.1653 + /* clear out the buffer */ 1.1654 + while (walk < end) { 1.1655 + *walk++ = ' '; 1.1656 + } 1.1657 +} 1.1658 + 1.1659 +/* return the slot info structure */ 1.1660 +SECStatus 1.1661 +PK11_GetSlotInfo(PK11SlotInfo *slot, CK_SLOT_INFO *info) 1.1662 +{ 1.1663 + CK_RV crv; 1.1664 + 1.1665 + if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); 1.1666 + /* 1.1667 + * some buggy drivers do not fill the buffer completely, 1.1668 + * erase the buffer first 1.1669 + */ 1.1670 + PORT_Memset(info->slotDescription,' ',sizeof(info->slotDescription)); 1.1671 + PORT_Memset(info->manufacturerID,' ',sizeof(info->manufacturerID)); 1.1672 + crv = PK11_GETTAB(slot)->C_GetSlotInfo(slot->slotID,info); 1.1673 + pk11_zeroTerminatedToBlankPadded(info->slotDescription, 1.1674 + sizeof(info->slotDescription)); 1.1675 + pk11_zeroTerminatedToBlankPadded(info->manufacturerID, 1.1676 + sizeof(info->manufacturerID)); 1.1677 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.1678 + if (crv != CKR_OK) { 1.1679 + PORT_SetError(PK11_MapError(crv)); 1.1680 + return SECFailure; 1.1681 + } 1.1682 + return SECSuccess; 1.1683 +} 1.1684 + 1.1685 +/* return the token info structure */ 1.1686 +SECStatus 1.1687 +PK11_GetTokenInfo(PK11SlotInfo *slot, CK_TOKEN_INFO *info) 1.1688 +{ 1.1689 + CK_RV crv; 1.1690 + if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); 1.1691 + /* 1.1692 + * some buggy drivers do not fill the buffer completely, 1.1693 + * erase the buffer first 1.1694 + */ 1.1695 + PORT_Memset(info->label,' ',sizeof(info->label)); 1.1696 + PORT_Memset(info->manufacturerID,' ',sizeof(info->manufacturerID)); 1.1697 + PORT_Memset(info->model,' ',sizeof(info->model)); 1.1698 + PORT_Memset(info->serialNumber,' ',sizeof(info->serialNumber)); 1.1699 + crv = PK11_GETTAB(slot)->C_GetTokenInfo(slot->slotID,info); 1.1700 + pk11_zeroTerminatedToBlankPadded(info->label,sizeof(info->label)); 1.1701 + pk11_zeroTerminatedToBlankPadded(info->manufacturerID, 1.1702 + sizeof(info->manufacturerID)); 1.1703 + pk11_zeroTerminatedToBlankPadded(info->model,sizeof(info->model)); 1.1704 + pk11_zeroTerminatedToBlankPadded(info->serialNumber, 1.1705 + sizeof(info->serialNumber)); 1.1706 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.1707 + if (crv != CKR_OK) { 1.1708 + PORT_SetError(PK11_MapError(crv)); 1.1709 + return SECFailure; 1.1710 + } 1.1711 + return SECSuccess; 1.1712 +} 1.1713 + 1.1714 +/* Find out if we need to initialize the user's pin */ 1.1715 +PRBool 1.1716 +PK11_NeedUserInit(PK11SlotInfo *slot) 1.1717 +{ 1.1718 + PRBool needUserInit = (PRBool) ((slot->flags & CKF_USER_PIN_INITIALIZED) 1.1719 + == 0); 1.1720 + 1.1721 + if (needUserInit) { 1.1722 + CK_TOKEN_INFO info; 1.1723 + SECStatus rv; 1.1724 + 1.1725 + /* see if token has been initialized off line */ 1.1726 + rv = PK11_GetTokenInfo(slot, &info); 1.1727 + if (rv == SECSuccess) { 1.1728 + slot->flags = info.flags; 1.1729 + } 1.1730 + } 1.1731 + return (PRBool)((slot->flags & CKF_USER_PIN_INITIALIZED) == 0); 1.1732 +} 1.1733 + 1.1734 +static PK11SlotInfo *pk11InternalKeySlot = NULL; 1.1735 + 1.1736 +/* 1.1737 + * Set a new default internal keyslot. If one has already been set, clear it. 1.1738 + * Passing NULL falls back to the NSS normally selected default internal key 1.1739 + * slot. 1.1740 + */ 1.1741 +void 1.1742 +pk11_SetInternalKeySlot(PK11SlotInfo *slot) 1.1743 +{ 1.1744 + if (pk11InternalKeySlot) { 1.1745 + PK11_FreeSlot(pk11InternalKeySlot); 1.1746 + } 1.1747 + pk11InternalKeySlot = slot ? PK11_ReferenceSlot(slot) : NULL; 1.1748 +} 1.1749 + 1.1750 +/* 1.1751 + * Set a new default internal keyslot if the normal key slot has not already 1.1752 + * been overridden. Subsequent calls to this function will be ignored unless 1.1753 + * pk11_SetInternalKeySlot is used to clear the current default. 1.1754 + */ 1.1755 +void 1.1756 +pk11_SetInternalKeySlotIfFirst(PK11SlotInfo *slot) 1.1757 +{ 1.1758 + if (pk11InternalKeySlot) { 1.1759 + return; 1.1760 + } 1.1761 + pk11InternalKeySlot = slot ? PK11_ReferenceSlot(slot) : NULL; 1.1762 +} 1.1763 + 1.1764 +/* 1.1765 + * Swap out a default internal keyslot. Caller owns the Slot Reference 1.1766 + */ 1.1767 +PK11SlotInfo * 1.1768 +pk11_SwapInternalKeySlot(PK11SlotInfo *slot) 1.1769 +{ 1.1770 + PK11SlotInfo *swap = pk11InternalKeySlot; 1.1771 + 1.1772 + pk11InternalKeySlot = slot ? PK11_ReferenceSlot(slot) : NULL; 1.1773 + return swap; 1.1774 +} 1.1775 + 1.1776 + 1.1777 +/* get the internal key slot. FIPS has only one slot for both key slots and 1.1778 + * default slots */ 1.1779 +PK11SlotInfo * 1.1780 +PK11_GetInternalKeySlot(void) 1.1781 +{ 1.1782 + SECMODModule *mod; 1.1783 + 1.1784 + if (pk11InternalKeySlot) { 1.1785 + return PK11_ReferenceSlot(pk11InternalKeySlot); 1.1786 + } 1.1787 + 1.1788 + mod = SECMOD_GetInternalModule(); 1.1789 + PORT_Assert(mod != NULL); 1.1790 + if (!mod) { 1.1791 + PORT_SetError( SEC_ERROR_NO_MODULE ); 1.1792 + return NULL; 1.1793 + } 1.1794 + return PK11_ReferenceSlot(mod->isFIPS ? mod->slots[0] : mod->slots[1]); 1.1795 +} 1.1796 + 1.1797 +/* get the internal default slot */ 1.1798 +PK11SlotInfo * 1.1799 +PK11_GetInternalSlot(void) 1.1800 +{ 1.1801 + SECMODModule * mod = SECMOD_GetInternalModule(); 1.1802 + PORT_Assert(mod != NULL); 1.1803 + if (!mod) { 1.1804 + PORT_SetError( SEC_ERROR_NO_MODULE ); 1.1805 + return NULL; 1.1806 + } 1.1807 + if (mod->isFIPS) { 1.1808 + return PK11_GetInternalKeySlot(); 1.1809 + } 1.1810 + return PK11_ReferenceSlot(mod->slots[0]); 1.1811 +} 1.1812 + 1.1813 +/* 1.1814 + * check if a given slot supports the requested mechanism 1.1815 + */ 1.1816 +PRBool 1.1817 +PK11_DoesMechanism(PK11SlotInfo *slot, CK_MECHANISM_TYPE type) 1.1818 +{ 1.1819 + int i; 1.1820 + 1.1821 + /* CKM_FAKE_RANDOM is not a real PKCS mechanism. It's a marker to 1.1822 + * tell us we're looking form someone that has implemented get 1.1823 + * random bits */ 1.1824 + if (type == CKM_FAKE_RANDOM) { 1.1825 + return slot->hasRandom; 1.1826 + } 1.1827 + 1.1828 + /* for most mechanism, bypass the linear lookup */ 1.1829 + if (type < 0x7ff) { 1.1830 + return (slot->mechanismBits[type & 0xff] & (1 << (type >> 8))) ? 1.1831 + PR_TRUE : PR_FALSE; 1.1832 + } 1.1833 + 1.1834 + for (i=0; i < (int) slot->mechanismCount; i++) { 1.1835 + if (slot->mechanismList[i] == type) return PR_TRUE; 1.1836 + } 1.1837 + return PR_FALSE; 1.1838 +} 1.1839 + 1.1840 +/* 1.1841 + * Return true if a token that can do the desired mechanism exists. 1.1842 + * This allows us to have hardware tokens that can do function XYZ magically 1.1843 + * allow SSL Ciphers to appear if they are plugged in. 1.1844 + */ 1.1845 +PRBool 1.1846 +PK11_TokenExists(CK_MECHANISM_TYPE type) 1.1847 +{ 1.1848 + SECMODModuleList *mlp; 1.1849 + SECMODModuleList *modules; 1.1850 + SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); 1.1851 + PK11SlotInfo *slot; 1.1852 + PRBool found = PR_FALSE; 1.1853 + int i; 1.1854 + 1.1855 + if (!moduleLock) { 1.1856 + PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 1.1857 + return found; 1.1858 + } 1.1859 + /* we only need to know if there is a token that does this mechanism. 1.1860 + * check the internal module first because it's fast, and supports 1.1861 + * almost everything. */ 1.1862 + slot = PK11_GetInternalSlot(); 1.1863 + if (slot) { 1.1864 + found = PK11_DoesMechanism(slot,type); 1.1865 + PK11_FreeSlot(slot); 1.1866 + } 1.1867 + if (found) return PR_TRUE; /* bypass getting module locks */ 1.1868 + 1.1869 + SECMOD_GetReadLock(moduleLock); 1.1870 + modules = SECMOD_GetDefaultModuleList(); 1.1871 + for(mlp = modules; mlp != NULL && (!found); mlp = mlp->next) { 1.1872 + for (i=0; i < mlp->module->slotCount; i++) { 1.1873 + slot = mlp->module->slots[i]; 1.1874 + if (PK11_IsPresent(slot)) { 1.1875 + if (PK11_DoesMechanism(slot,type)) { 1.1876 + found = PR_TRUE; 1.1877 + break; 1.1878 + } 1.1879 + } 1.1880 + } 1.1881 + } 1.1882 + SECMOD_ReleaseReadLock(moduleLock); 1.1883 + return found; 1.1884 +} 1.1885 + 1.1886 +/* 1.1887 + * get all the currently available tokens in a list. 1.1888 + * that can perform the given mechanism. If mechanism is CKM_INVALID_MECHANISM, 1.1889 + * get all the tokens. Make sure tokens that need authentication are put at 1.1890 + * the end of this list. 1.1891 + */ 1.1892 +PK11SlotList * 1.1893 +PK11_GetAllTokens(CK_MECHANISM_TYPE type, PRBool needRW, PRBool loadCerts, 1.1894 + void *wincx) 1.1895 +{ 1.1896 + PK11SlotList * list; 1.1897 + PK11SlotList * loginList; 1.1898 + PK11SlotList * friendlyList; 1.1899 + SECMODModuleList * mlp; 1.1900 + SECMODModuleList * modules; 1.1901 + SECMODListLock * moduleLock; 1.1902 + int i; 1.1903 +#if defined( XP_WIN32 ) 1.1904 + int j = 0; 1.1905 + PRInt32 waste[16]; 1.1906 +#endif 1.1907 + 1.1908 + moduleLock = SECMOD_GetDefaultModuleListLock(); 1.1909 + if (!moduleLock) { 1.1910 + PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 1.1911 + return NULL; 1.1912 + } 1.1913 + 1.1914 + list = PK11_NewSlotList(); 1.1915 + loginList = PK11_NewSlotList(); 1.1916 + friendlyList = PK11_NewSlotList(); 1.1917 + if ((list == NULL) || (loginList == NULL) || (friendlyList == NULL)) { 1.1918 + if (list) PK11_FreeSlotList(list); 1.1919 + if (loginList) PK11_FreeSlotList(loginList); 1.1920 + if (friendlyList) PK11_FreeSlotList(friendlyList); 1.1921 + return NULL; 1.1922 + } 1.1923 + 1.1924 + SECMOD_GetReadLock(moduleLock); 1.1925 + 1.1926 + modules = SECMOD_GetDefaultModuleList(); 1.1927 + for(mlp = modules; mlp != NULL; mlp = mlp->next) { 1.1928 + 1.1929 +#if defined( XP_WIN32 ) 1.1930 + /* This is works around some horrible cache/page thrashing problems 1.1931 + ** on Win32. Without this, this loop can take up to 6 seconds at 1.1932 + ** 100% CPU on a Pentium-Pro 200. The thing this changes is to 1.1933 + ** increase the size of the stack frame and modify it. 1.1934 + ** Moving the loop code itself seems to have no effect. 1.1935 + ** Dunno why this combination makes a difference, but it does. 1.1936 + */ 1.1937 + waste[ j & 0xf] = j++; 1.1938 +#endif 1.1939 + 1.1940 + for (i = 0; i < mlp->module->slotCount; i++) { 1.1941 + PK11SlotInfo *slot = mlp->module->slots[i]; 1.1942 + 1.1943 + if (pk11_IsPresentCertLoad(slot, loadCerts)) { 1.1944 + if (needRW && slot->readOnly) continue; 1.1945 + if ((type == CKM_INVALID_MECHANISM) 1.1946 + || PK11_DoesMechanism(slot, type)) { 1.1947 + if (pk11_LoginStillRequired(slot,wincx)) { 1.1948 + if (PK11_IsFriendly(slot)) { 1.1949 + PK11_AddSlotToList(friendlyList, slot, PR_TRUE); 1.1950 + } else { 1.1951 + PK11_AddSlotToList(loginList, slot, PR_TRUE); 1.1952 + } 1.1953 + } else { 1.1954 + PK11_AddSlotToList(list, slot, PR_TRUE); 1.1955 + } 1.1956 + } 1.1957 + } 1.1958 + } 1.1959 + } 1.1960 + SECMOD_ReleaseReadLock(moduleLock); 1.1961 + 1.1962 + pk11_MoveListToList(list,friendlyList); 1.1963 + PK11_FreeSlotList(friendlyList); 1.1964 + pk11_MoveListToList(list,loginList); 1.1965 + PK11_FreeSlotList(loginList); 1.1966 + 1.1967 + return list; 1.1968 +} 1.1969 + 1.1970 +/* 1.1971 + * NOTE: This routine is working from a private List generated by 1.1972 + * PK11_GetAllTokens. That is why it does not need to lock. 1.1973 + */ 1.1974 +PK11SlotList * 1.1975 +PK11_GetPrivateKeyTokens(CK_MECHANISM_TYPE type,PRBool needRW,void *wincx) 1.1976 +{ 1.1977 + PK11SlotList *list = PK11_GetAllTokens(type,needRW,PR_TRUE,wincx); 1.1978 + PK11SlotListElement *le, *next ; 1.1979 + SECStatus rv; 1.1980 + 1.1981 + if (list == NULL) return list; 1.1982 + 1.1983 + for (le = list->head ; le; le = next) { 1.1984 + next = le->next; /* save the pointer here in case we have to 1.1985 + * free the element later */ 1.1986 + rv = PK11_Authenticate(le->slot,PR_TRUE,wincx); 1.1987 + if (rv != SECSuccess) { 1.1988 + PK11_DeleteSlotFromList(list,le); 1.1989 + continue; 1.1990 + } 1.1991 + } 1.1992 + return list; 1.1993 +} 1.1994 + 1.1995 +/* 1.1996 + * returns true if the slot doesn't conform to the requested attributes 1.1997 + */ 1.1998 +PRBool 1.1999 +pk11_filterSlot(PK11SlotInfo *slot, CK_MECHANISM_TYPE mechanism, 1.2000 + CK_FLAGS mechanismInfoFlags, unsigned int keySize) 1.2001 +{ 1.2002 + CK_MECHANISM_INFO mechanism_info; 1.2003 + CK_RV crv = CKR_OK; 1.2004 + 1.2005 + /* handle the only case where we don't actually fetch the mechanisms 1.2006 + * on the fly */ 1.2007 + if ((keySize == 0) && (mechanism == CKM_RSA_PKCS) && (slot->hasRSAInfo)) { 1.2008 + mechanism_info.flags = slot->RSAInfoFlags; 1.2009 + } else { 1.2010 + if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); 1.2011 + crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID, mechanism, 1.2012 + &mechanism_info); 1.2013 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.2014 + /* if we were getting the RSA flags, save them */ 1.2015 + if ((crv == CKR_OK) && (mechanism == CKM_RSA_PKCS) 1.2016 + && (!slot->hasRSAInfo)) { 1.2017 + slot->RSAInfoFlags = mechanism_info.flags; 1.2018 + slot->hasRSAInfo = PR_TRUE; 1.2019 + } 1.2020 + } 1.2021 + /* couldn't get the mechanism info */ 1.2022 + if (crv != CKR_OK ) { 1.2023 + return PR_TRUE; 1.2024 + } 1.2025 + if (keySize && ((mechanism_info.ulMinKeySize > keySize) 1.2026 + || (mechanism_info.ulMaxKeySize < keySize)) ) { 1.2027 + /* Token can do mechanism, but not at the key size we 1.2028 + * want */ 1.2029 + return PR_TRUE; 1.2030 + } 1.2031 + if (mechanismInfoFlags && ((mechanism_info.flags & mechanismInfoFlags) != 1.2032 + mechanismInfoFlags) ) { 1.2033 + return PR_TRUE; 1.2034 + } 1.2035 + return PR_FALSE; 1.2036 +} 1.2037 + 1.2038 + 1.2039 +/* 1.2040 + * Find the best slot which supports the given set of mechanisms and key sizes. 1.2041 + * In normal cases this should grab the first slot on the list with no fuss. 1.2042 + * The size array is presumed to match one for one with the mechanism type 1.2043 + * array, which allows you to specify the required key size for each 1.2044 + * mechanism in the list. Whether key size is in bits or bytes is mechanism 1.2045 + * dependent. Typically asymetric keys are in bits and symetric keys are in 1.2046 + * bytes. 1.2047 + */ 1.2048 +PK11SlotInfo * 1.2049 +PK11_GetBestSlotMultipleWithAttributes(CK_MECHANISM_TYPE *type, 1.2050 + CK_FLAGS *mechanismInfoFlags, unsigned int *keySize, 1.2051 + unsigned int mech_count, void *wincx) 1.2052 +{ 1.2053 + PK11SlotList *list = NULL; 1.2054 + PK11SlotListElement *le ; 1.2055 + PK11SlotInfo *slot = NULL; 1.2056 + PRBool freeit = PR_FALSE; 1.2057 + PRBool listNeedLogin = PR_FALSE; 1.2058 + int i; 1.2059 + SECStatus rv; 1.2060 + 1.2061 + list = PK11_GetSlotList(type[0]); 1.2062 + 1.2063 + if ((list == NULL) || (list->head == NULL)) { 1.2064 + /* We need to look up all the tokens for the mechanism */ 1.2065 + list = PK11_GetAllTokens(type[0],PR_FALSE,PR_TRUE,wincx); 1.2066 + freeit = PR_TRUE; 1.2067 + } 1.2068 + 1.2069 + /* no one can do it! */ 1.2070 + if (list == NULL) { 1.2071 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.2072 + return NULL; 1.2073 + } 1.2074 + 1.2075 + PORT_SetError(0); 1.2076 + 1.2077 + 1.2078 + listNeedLogin = PR_FALSE; 1.2079 + for (i=0; i < mech_count; i++) { 1.2080 + if ((type[i] != CKM_FAKE_RANDOM) && 1.2081 + (type[i] != CKM_SHA_1) && 1.2082 + (type[i] != CKM_SHA224) && 1.2083 + (type[i] != CKM_SHA256) && 1.2084 + (type[i] != CKM_SHA384) && 1.2085 + (type[i] != CKM_SHA512) && 1.2086 + (type[i] != CKM_MD5) && 1.2087 + (type[i] != CKM_MD2)) { 1.2088 + listNeedLogin = PR_TRUE; 1.2089 + break; 1.2090 + } 1.2091 + } 1.2092 + 1.2093 + for (le = PK11_GetFirstSafe(list); le; 1.2094 + le = PK11_GetNextSafe(list,le,PR_TRUE)) { 1.2095 + if (PK11_IsPresent(le->slot)) { 1.2096 + PRBool doExit = PR_FALSE; 1.2097 + for (i=0; i < mech_count; i++) { 1.2098 + if (!PK11_DoesMechanism(le->slot,type[i])) { 1.2099 + doExit = PR_TRUE; 1.2100 + break; 1.2101 + } 1.2102 + if ((mechanismInfoFlags && mechanismInfoFlags[i]) || 1.2103 + (keySize && keySize[i])) { 1.2104 + if (pk11_filterSlot(le->slot, type[i], 1.2105 + mechanismInfoFlags ? mechanismInfoFlags[i] : 0, 1.2106 + keySize ? keySize[i] : 0)) { 1.2107 + doExit = PR_TRUE; 1.2108 + break; 1.2109 + } 1.2110 + } 1.2111 + } 1.2112 + 1.2113 + if (doExit) continue; 1.2114 + 1.2115 + if (listNeedLogin && le->slot->needLogin) { 1.2116 + rv = PK11_Authenticate(le->slot,PR_TRUE,wincx); 1.2117 + if (rv != SECSuccess) continue; 1.2118 + } 1.2119 + slot = le->slot; 1.2120 + PK11_ReferenceSlot(slot); 1.2121 + PK11_FreeSlotListElement(list,le); 1.2122 + if (freeit) { PK11_FreeSlotList(list); } 1.2123 + return slot; 1.2124 + } 1.2125 + } 1.2126 + if (freeit) { PK11_FreeSlotList(list); } 1.2127 + if (PORT_GetError() == 0) { 1.2128 + PORT_SetError(SEC_ERROR_NO_TOKEN); 1.2129 + } 1.2130 + return NULL; 1.2131 +} 1.2132 + 1.2133 +PK11SlotInfo * 1.2134 +PK11_GetBestSlotMultiple(CK_MECHANISM_TYPE *type, 1.2135 + unsigned int mech_count, void *wincx) 1.2136 +{ 1.2137 + return PK11_GetBestSlotMultipleWithAttributes(type, NULL, NULL, 1.2138 + mech_count, wincx); 1.2139 +} 1.2140 + 1.2141 +/* original get best slot now calls the multiple version with only one type */ 1.2142 +PK11SlotInfo * 1.2143 +PK11_GetBestSlot(CK_MECHANISM_TYPE type, void *wincx) 1.2144 +{ 1.2145 + return PK11_GetBestSlotMultipleWithAttributes(&type, NULL, NULL, 1, wincx); 1.2146 +} 1.2147 + 1.2148 +PK11SlotInfo * 1.2149 +PK11_GetBestSlotWithAttributes(CK_MECHANISM_TYPE type, CK_FLAGS mechanismFlags, 1.2150 + unsigned int keySize, void *wincx) 1.2151 +{ 1.2152 + return PK11_GetBestSlotMultipleWithAttributes(&type, &mechanismFlags, 1.2153 + &keySize, 1, wincx); 1.2154 +} 1.2155 + 1.2156 +int 1.2157 +PK11_GetBestKeyLength(PK11SlotInfo *slot,CK_MECHANISM_TYPE mechanism) 1.2158 +{ 1.2159 + CK_MECHANISM_INFO mechanism_info; 1.2160 + CK_RV crv; 1.2161 + 1.2162 + if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); 1.2163 + crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID, 1.2164 + mechanism,&mechanism_info); 1.2165 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.2166 + if (crv != CKR_OK) return 0; 1.2167 + 1.2168 + if (mechanism_info.ulMinKeySize == mechanism_info.ulMaxKeySize) 1.2169 + return 0; 1.2170 + return mechanism_info.ulMaxKeySize; 1.2171 +} 1.2172 + 1.2173 + 1.2174 +/* 1.2175 + * This function uses the existing PKCS #11 module to find the 1.2176 + * longest supported key length in the preferred token for a mechanism. 1.2177 + * This varies from the above function in that 1) it returns the key length 1.2178 + * even for fixed key algorithms, and 2) it looks through the tokens 1.2179 + * generally rather than for a specific token. This is used in liu of 1.2180 + * a PK11_GetKeyLength function in pk11mech.c since we can actually read 1.2181 + * supported key lengths from PKCS #11. 1.2182 + * 1.2183 + * For symmetric key operations the length is returned in bytes. 1.2184 + */ 1.2185 +int 1.2186 +PK11_GetMaxKeyLength(CK_MECHANISM_TYPE mechanism) 1.2187 +{ 1.2188 + CK_MECHANISM_INFO mechanism_info; 1.2189 + PK11SlotList *list = NULL; 1.2190 + PK11SlotListElement *le ; 1.2191 + PRBool freeit = PR_FALSE; 1.2192 + int keyLength = 0; 1.2193 + 1.2194 + list = PK11_GetSlotList(mechanism); 1.2195 + 1.2196 + if ((list == NULL) || (list->head == NULL)) { 1.2197 + /* We need to look up all the tokens for the mechanism */ 1.2198 + list = PK11_GetAllTokens(mechanism,PR_FALSE,PR_FALSE,NULL); 1.2199 + freeit = PR_TRUE; 1.2200 + } 1.2201 + 1.2202 + /* no tokens recognize this mechanism */ 1.2203 + if (list == NULL) { 1.2204 + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 1.2205 + return 0; 1.2206 + } 1.2207 + 1.2208 + for (le = PK11_GetFirstSafe(list); le; 1.2209 + le = PK11_GetNextSafe(list,le,PR_TRUE)) { 1.2210 + PK11SlotInfo *slot = le->slot; 1.2211 + CK_RV crv; 1.2212 + if (PK11_IsPresent(slot)) { 1.2213 + if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); 1.2214 + crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID, 1.2215 + mechanism,&mechanism_info); 1.2216 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.2217 + if ((crv == CKR_OK) && (mechanism_info.ulMaxKeySize != 0) 1.2218 + && (mechanism_info.ulMaxKeySize != 0xffffffff)) { 1.2219 + keyLength = mechanism_info.ulMaxKeySize; 1.2220 + break; 1.2221 + } 1.2222 + } 1.2223 + } 1.2224 + if (le) 1.2225 + PK11_FreeSlotListElement(list, le); 1.2226 + if (freeit) 1.2227 + PK11_FreeSlotList(list); 1.2228 + return keyLength; 1.2229 +} 1.2230 + 1.2231 +SECStatus 1.2232 +PK11_SeedRandom(PK11SlotInfo *slot, unsigned char *data, int len) { 1.2233 + CK_RV crv; 1.2234 + 1.2235 + PK11_EnterSlotMonitor(slot); 1.2236 + crv = PK11_GETTAB(slot)->C_SeedRandom(slot->session, data, (CK_ULONG)len); 1.2237 + PK11_ExitSlotMonitor(slot); 1.2238 + if (crv != CKR_OK) { 1.2239 + PORT_SetError(PK11_MapError(crv)); 1.2240 + return SECFailure; 1.2241 + } 1.2242 + return SECSuccess; 1.2243 +} 1.2244 + 1.2245 + 1.2246 +SECStatus 1.2247 +PK11_GenerateRandomOnSlot(PK11SlotInfo *slot, unsigned char *data, int len) { 1.2248 + CK_RV crv; 1.2249 + 1.2250 + if (!slot->isInternal) PK11_EnterSlotMonitor(slot); 1.2251 + crv = PK11_GETTAB(slot)->C_GenerateRandom(slot->session,data, 1.2252 + (CK_ULONG)len); 1.2253 + if (!slot->isInternal) PK11_ExitSlotMonitor(slot); 1.2254 + if (crv != CKR_OK) { 1.2255 + PORT_SetError(PK11_MapError(crv)); 1.2256 + return SECFailure; 1.2257 + } 1.2258 + return SECSuccess; 1.2259 +} 1.2260 + 1.2261 +/* Attempts to update the Best Slot for "FAKE RANDOM" generation. 1.2262 +** If that's not the internal slot, then it also attempts to update the 1.2263 +** internal slot. 1.2264 +** The return value indicates if the INTERNAL slot was updated OK. 1.2265 +*/ 1.2266 +SECStatus 1.2267 +PK11_RandomUpdate(void *data, size_t bytes) 1.2268 +{ 1.2269 + PK11SlotInfo *slot; 1.2270 + PRBool bestIsInternal; 1.2271 + SECStatus status; 1.2272 + 1.2273 + slot = PK11_GetBestSlot(CKM_FAKE_RANDOM, NULL); 1.2274 + if (slot == NULL) { 1.2275 + slot = PK11_GetInternalSlot(); 1.2276 + if (!slot) 1.2277 + return SECFailure; 1.2278 + } 1.2279 + 1.2280 + bestIsInternal = PK11_IsInternal(slot); 1.2281 + status = PK11_SeedRandom(slot, data, bytes); 1.2282 + PK11_FreeSlot(slot); 1.2283 + 1.2284 + if (!bestIsInternal) { 1.2285 + /* do internal slot, too. */ 1.2286 + slot = PK11_GetInternalSlot(); /* can't fail */ 1.2287 + status = PK11_SeedRandom(slot, data, bytes); 1.2288 + PK11_FreeSlot(slot); 1.2289 + } 1.2290 + return status; 1.2291 +} 1.2292 + 1.2293 + 1.2294 +SECStatus 1.2295 +PK11_GenerateRandom(unsigned char *data,int len) { 1.2296 + PK11SlotInfo *slot; 1.2297 + SECStatus rv; 1.2298 + 1.2299 + slot = PK11_GetBestSlot(CKM_FAKE_RANDOM,NULL); 1.2300 + if (slot == NULL) return SECFailure; 1.2301 + 1.2302 + rv = PK11_GenerateRandomOnSlot(slot, data, len); 1.2303 + PK11_FreeSlot(slot); 1.2304 + return rv; 1.2305 +} 1.2306 + 1.2307 +/* 1.2308 + * Reset the token to it's initial state. For the internal module, this will 1.2309 + * Purge your keydb, and reset your cert db certs to USER_INIT. 1.2310 + */ 1.2311 +SECStatus 1.2312 +PK11_ResetToken(PK11SlotInfo *slot, char *sso_pwd) 1.2313 +{ 1.2314 + unsigned char tokenName[32]; 1.2315 + int tokenNameLen; 1.2316 + CK_RV crv; 1.2317 + 1.2318 + /* reconstruct the token name */ 1.2319 + tokenNameLen = PORT_Strlen(slot->token_name); 1.2320 + if (tokenNameLen > sizeof(tokenName)) { 1.2321 + tokenNameLen = sizeof(tokenName); 1.2322 + } 1.2323 + 1.2324 + PORT_Memcpy(tokenName,slot->token_name,tokenNameLen); 1.2325 + if (tokenNameLen < sizeof(tokenName)) { 1.2326 + PORT_Memset(&tokenName[tokenNameLen],' ', 1.2327 + sizeof(tokenName)-tokenNameLen); 1.2328 + } 1.2329 + 1.2330 + /* initialize the token */ 1.2331 + PK11_EnterSlotMonitor(slot); 1.2332 + 1.2333 + /* first shutdown the token. Existing sessions will get closed here */ 1.2334 + PK11_GETTAB(slot)->C_CloseAllSessions(slot->slotID); 1.2335 + slot->session = CK_INVALID_SESSION; 1.2336 + 1.2337 + /* now re-init the token */ 1.2338 + crv = PK11_GETTAB(slot)->C_InitToken(slot->slotID, 1.2339 + (unsigned char *)sso_pwd, sso_pwd ? PORT_Strlen(sso_pwd): 0, tokenName); 1.2340 + 1.2341 + /* finally bring the token back up */ 1.2342 + PK11_InitToken(slot,PR_TRUE); 1.2343 + PK11_ExitSlotMonitor(slot); 1.2344 + if (crv != CKR_OK) { 1.2345 + PORT_SetError(PK11_MapError(crv)); 1.2346 + return SECFailure; 1.2347 + } 1.2348 + nssTrustDomain_UpdateCachedTokenCerts(slot->nssToken->trustDomain, 1.2349 + slot->nssToken); 1.2350 + return SECSuccess; 1.2351 +} 1.2352 +void 1.2353 +PK11Slot_SetNSSToken(PK11SlotInfo *sl, NSSToken *nsst) 1.2354 +{ 1.2355 + sl->nssToken = nsst; 1.2356 +} 1.2357 + 1.2358 +NSSToken * 1.2359 +PK11Slot_GetNSSToken(PK11SlotInfo *sl) 1.2360 +{ 1.2361 + return sl->nssToken; 1.2362 +} 1.2363 + 1.2364 +/* 1.2365 + * wait for a token to change it's state. The application passes in the expected 1.2366 + * new state in event. 1.2367 + */ 1.2368 +PK11TokenStatus 1.2369 +PK11_WaitForTokenEvent(PK11SlotInfo *slot, PK11TokenEvent event, 1.2370 + PRIntervalTime timeout, PRIntervalTime latency, int series) 1.2371 +{ 1.2372 + PRIntervalTime first_time = 0; 1.2373 + PRBool first_time_set = PR_FALSE; 1.2374 + PRBool waitForRemoval; 1.2375 + 1.2376 + if (slot->isPerm) { 1.2377 + return PK11TokenNotRemovable; 1.2378 + } 1.2379 + if (latency == 0) { 1.2380 + latency = PR_SecondsToInterval(5); 1.2381 + } 1.2382 + waitForRemoval = (PRBool) (event == PK11TokenRemovedOrChangedEvent); 1.2383 + 1.2384 + if (series == 0) { 1.2385 + series = PK11_GetSlotSeries(slot); 1.2386 + } 1.2387 + while (PK11_IsPresent(slot) == waitForRemoval ) { 1.2388 + PRIntervalTime interval; 1.2389 + 1.2390 + if (waitForRemoval && series != PK11_GetSlotSeries(slot)) { 1.2391 + return PK11TokenChanged; 1.2392 + } 1.2393 + if (timeout == PR_INTERVAL_NO_WAIT) { 1.2394 + return waitForRemoval ? PK11TokenPresent : PK11TokenRemoved; 1.2395 + } 1.2396 + if (timeout != PR_INTERVAL_NO_TIMEOUT ) { 1.2397 + interval = PR_IntervalNow(); 1.2398 + if (!first_time_set) { 1.2399 + first_time = interval; 1.2400 + first_time_set = PR_TRUE; 1.2401 + } 1.2402 + if ((interval-first_time) > timeout) { 1.2403 + return waitForRemoval ? PK11TokenPresent : PK11TokenRemoved; 1.2404 + } 1.2405 + } 1.2406 + PR_Sleep(latency); 1.2407 + } 1.2408 + return waitForRemoval ? PK11TokenRemoved : PK11TokenPresent; 1.2409 +}