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