pk11util.c (52149B)
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 * Initialize the PCKS 11 subsystem 6 */ 7 #include "seccomon.h" 8 #include "secmod.h" 9 #include "nssilock.h" 10 #include "secmodi.h" 11 #include "secmodti.h" 12 #include "pk11func.h" 13 #include "pki3hack.h" 14 #include "secerr.h" 15 #include "dev.h" 16 #include "dev3hack.h" 17 #include "utilpars.h" 18 #include "pkcs11uri.h" 19 20 /* these are for displaying error messages */ 21 22 static SECMODModuleList *modules = NULL; 23 static SECMODModuleList *modulesDB = NULL; 24 static SECMODModuleList *modulesUnload = NULL; 25 static SECMODModule *internalModule = NULL; 26 static SECMODModule *defaultDBModule = NULL; 27 static SECMODModule *pendingModule = NULL; 28 static SECMODListLock *moduleLock = NULL; 29 30 int secmod_PrivateModuleCount = 0; 31 32 extern const PK11DefaultArrayEntry PK11_DefaultArray[]; 33 extern const int num_pk11_default_mechanisms; 34 35 void 36 SECMOD_Init() 37 { 38 /* don't initialize twice */ 39 if (moduleLock) 40 return; 41 42 moduleLock = SECMOD_NewListLock(); 43 PK11_InitSlotLists(); 44 } 45 46 SECStatus 47 SECMOD_Shutdown() 48 { 49 /* destroy the lock */ 50 if (moduleLock) { 51 SECMOD_DestroyListLock(moduleLock); 52 moduleLock = NULL; 53 } 54 /* free the internal module */ 55 if (internalModule) { 56 SECMOD_DestroyModule(internalModule); 57 internalModule = NULL; 58 } 59 60 /* free the default database module */ 61 if (defaultDBModule) { 62 SECMOD_DestroyModule(defaultDBModule); 63 defaultDBModule = NULL; 64 } 65 66 /* destroy the list */ 67 if (modules) { 68 SECMOD_DestroyModuleList(modules); 69 modules = NULL; 70 } 71 72 if (modulesDB) { 73 SECMOD_DestroyModuleList(modulesDB); 74 modulesDB = NULL; 75 } 76 77 if (modulesUnload) { 78 SECMOD_DestroyModuleList(modulesUnload); 79 modulesUnload = NULL; 80 } 81 82 /* make all the slots and the lists go away */ 83 PK11_DestroySlotLists(); 84 85 nss_DumpModuleLog(); 86 87 #ifdef DEBUG 88 if (PR_GetEnvSecure("NSS_STRICT_SHUTDOWN")) { 89 PORT_Assert(secmod_PrivateModuleCount == 0); 90 } 91 #endif 92 if (secmod_PrivateModuleCount) { 93 PORT_SetError(SEC_ERROR_BUSY); 94 return SECFailure; 95 } 96 return SECSuccess; 97 } 98 99 PRBool 100 SECMOD_GetSystemFIPSEnabled(void) 101 { 102 return NSS_GetSystemFIPSEnabled(); 103 } 104 105 /* 106 * retrieve the internal module 107 */ 108 SECMODModule * 109 SECMOD_GetInternalModule(void) 110 { 111 return internalModule; 112 } 113 114 SECStatus 115 secmod_AddModuleToList(SECMODModuleList **moduleList, SECMODModule *newModule) 116 { 117 SECMODModuleList *mlp, *newListElement, *last = NULL; 118 119 newListElement = SECMOD_NewModuleListElement(); 120 if (newListElement == NULL) { 121 return SECFailure; 122 } 123 124 newListElement->module = SECMOD_ReferenceModule(newModule); 125 126 SECMOD_GetWriteLock(moduleLock); 127 /* Added it to the end (This is very inefficient, but Adding a module 128 * on the fly should happen maybe 2-3 times through the life this program 129 * on a given computer, and this list should be *SHORT*. */ 130 for (mlp = *moduleList; mlp != NULL; mlp = mlp->next) { 131 last = mlp; 132 } 133 134 if (last == NULL) { 135 *moduleList = newListElement; 136 } else { 137 SECMOD_AddList(last, newListElement, NULL); 138 } 139 SECMOD_ReleaseWriteLock(moduleLock); 140 return SECSuccess; 141 } 142 143 SECStatus 144 SECMOD_AddModuleToList(SECMODModule *newModule) 145 { 146 if (newModule->internal && !internalModule) { 147 internalModule = SECMOD_ReferenceModule(newModule); 148 } 149 return secmod_AddModuleToList(&modules, newModule); 150 } 151 152 SECStatus 153 SECMOD_AddModuleToDBOnlyList(SECMODModule *newModule) 154 { 155 if (defaultDBModule && SECMOD_GetDefaultModDBFlag(newModule)) { 156 SECMOD_DestroyModule(defaultDBModule); 157 defaultDBModule = SECMOD_ReferenceModule(newModule); 158 } else if (defaultDBModule == NULL) { 159 defaultDBModule = SECMOD_ReferenceModule(newModule); 160 } 161 return secmod_AddModuleToList(&modulesDB, newModule); 162 } 163 164 SECStatus 165 SECMOD_AddModuleToUnloadList(SECMODModule *newModule) 166 { 167 return secmod_AddModuleToList(&modulesUnload, newModule); 168 } 169 170 /* 171 * get the list of PKCS11 modules that are available. 172 */ 173 SECMODModuleList * 174 SECMOD_GetDefaultModuleList() 175 { 176 return modules; 177 } 178 SECMODModuleList * 179 SECMOD_GetDeadModuleList() 180 { 181 return modulesUnload; 182 } 183 SECMODModuleList * 184 SECMOD_GetDBModuleList() 185 { 186 return modulesDB; 187 } 188 189 /* 190 * This lock protects the global module lists. 191 * it also protects changes to the slot array (module->slots[]) and slot count 192 * (module->slotCount) in each module. It is a read/write lock with multiple 193 * readers or one writer. Writes are uncommon. 194 * Because of legacy considerations protection of the slot array and count is 195 * only necessary in applications if the application calls 196 * SECMOD_UpdateSlotList() or SECMOD_WaitForAnyTokenEvent(), though all new 197 * applications are encouraged to acquire this lock when reading the 198 * slot array information directly. 199 */ 200 SECMODListLock * 201 SECMOD_GetDefaultModuleListLock() 202 { 203 return moduleLock; 204 } 205 206 /* 207 * find a module by name, and add a reference to it. 208 * return that module. 209 */ 210 SECMODModule * 211 SECMOD_FindModule(const char *name) 212 { 213 SECMODModuleList *mlp; 214 SECMODModule *module = NULL; 215 216 if (!moduleLock) { 217 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 218 return module; 219 } 220 SECMOD_GetReadLock(moduleLock); 221 for (mlp = modules; mlp != NULL; mlp = mlp->next) { 222 if (PORT_Strcmp(name, mlp->module->commonName) == 0) { 223 module = mlp->module; 224 SECMOD_ReferenceModule(module); 225 break; 226 } 227 } 228 if (module) { 229 goto found; 230 } 231 for (mlp = modulesUnload; mlp != NULL; mlp = mlp->next) { 232 if (PORT_Strcmp(name, mlp->module->commonName) == 0) { 233 module = mlp->module; 234 SECMOD_ReferenceModule(module); 235 break; 236 } 237 } 238 239 found: 240 SECMOD_ReleaseReadLock(moduleLock); 241 242 return module; 243 } 244 245 /* 246 * find a module by ID, and add a reference to it. 247 * return that module. 248 */ 249 SECMODModule * 250 SECMOD_FindModuleByID(SECMODModuleID id) 251 { 252 SECMODModuleList *mlp; 253 SECMODModule *module = NULL; 254 255 if (!moduleLock) { 256 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 257 return module; 258 } 259 SECMOD_GetReadLock(moduleLock); 260 for (mlp = modules; mlp != NULL; mlp = mlp->next) { 261 if (id == mlp->module->moduleID) { 262 module = mlp->module; 263 SECMOD_ReferenceModule(module); 264 break; 265 } 266 } 267 SECMOD_ReleaseReadLock(moduleLock); 268 if (module == NULL) { 269 PORT_SetError(SEC_ERROR_NO_MODULE); 270 } 271 return module; 272 } 273 274 /* 275 * find the function pointer. 276 */ 277 SECMODModule * 278 secmod_FindModuleByFuncPtr(void *funcPtr) 279 { 280 SECMODModuleList *mlp; 281 SECMODModule *module = NULL; 282 283 SECMOD_GetReadLock(moduleLock); 284 for (mlp = modules; mlp != NULL; mlp = mlp->next) { 285 /* paranoia, shouldn't ever happen */ 286 if (!mlp->module) { 287 continue; 288 } 289 if (funcPtr == mlp->module->functionList) { 290 module = mlp->module; 291 SECMOD_ReferenceModule(module); 292 break; 293 } 294 } 295 SECMOD_ReleaseReadLock(moduleLock); 296 if (module == NULL) { 297 PORT_SetError(SEC_ERROR_NO_MODULE); 298 } 299 return module; 300 } 301 302 /* 303 * Find the Slot based on ID and the module. 304 */ 305 PK11SlotInfo * 306 SECMOD_FindSlotByID(SECMODModule *module, CK_SLOT_ID slotID) 307 { 308 int i; 309 PK11SlotInfo *slot = NULL; 310 311 if (!moduleLock) { 312 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 313 return slot; 314 } 315 SECMOD_GetReadLock(moduleLock); 316 for (i = 0; i < module->slotCount; i++) { 317 PK11SlotInfo *cSlot = module->slots[i]; 318 319 if (cSlot->slotID == slotID) { 320 slot = PK11_ReferenceSlot(cSlot); 321 break; 322 } 323 } 324 SECMOD_ReleaseReadLock(moduleLock); 325 326 if (slot == NULL) { 327 PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED); 328 } 329 return slot; 330 } 331 332 /* 333 * lookup the Slot module based on it's module ID and slot ID. 334 */ 335 PK11SlotInfo * 336 SECMOD_LookupSlot(SECMODModuleID moduleID, CK_SLOT_ID slotID) 337 { 338 SECMODModule *module; 339 PK11SlotInfo *slot; 340 341 module = SECMOD_FindModuleByID(moduleID); 342 if (module == NULL) 343 return NULL; 344 345 slot = SECMOD_FindSlotByID(module, slotID); 346 SECMOD_DestroyModule(module); 347 return slot; 348 } 349 350 /* 351 * find a module by name or module pointer and delete it off the module list. 352 * optionally remove it from secmod.db. 353 */ 354 SECStatus 355 SECMOD_DeleteModuleEx(const char *name, SECMODModule *mod, 356 int *type, PRBool permdb) 357 { 358 SECMODModuleList *mlp; 359 SECMODModuleList **mlpp; 360 SECStatus rv = SECFailure; 361 362 if (!moduleLock) { 363 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 364 return rv; 365 } 366 367 *type = SECMOD_EXTERNAL; 368 369 SECMOD_GetWriteLock(moduleLock); 370 for (mlpp = &modules, mlp = modules; 371 mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) { 372 if ((name && (PORT_Strcmp(name, mlp->module->commonName) == 0)) || 373 mod == mlp->module) { 374 /* don't delete the internal module */ 375 if (!mlp->module->internal) { 376 SECMOD_RemoveList(mlpp, mlp); 377 /* delete it after we release the lock */ 378 rv = STAN_RemoveModuleFromDefaultTrustDomain(mlp->module); 379 } else if (mlp->module->isFIPS) { 380 *type = SECMOD_FIPS; 381 } else { 382 *type = SECMOD_INTERNAL; 383 } 384 break; 385 } 386 } 387 if (mlp) { 388 goto found; 389 } 390 /* not on the internal list, check the unload list */ 391 for (mlpp = &modulesUnload, mlp = modulesUnload; 392 mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) { 393 if ((name && (PORT_Strcmp(name, mlp->module->commonName) == 0)) || 394 mod == mlp->module) { 395 /* don't delete the internal module */ 396 if (!mlp->module->internal) { 397 SECMOD_RemoveList(mlpp, mlp); 398 rv = SECSuccess; 399 } else if (mlp->module->isFIPS) { 400 *type = SECMOD_FIPS; 401 } else { 402 *type = SECMOD_INTERNAL; 403 } 404 break; 405 } 406 } 407 found: 408 SECMOD_ReleaseWriteLock(moduleLock); 409 410 if (rv == SECSuccess) { 411 if (permdb) { 412 SECMOD_DeletePermDB(mlp->module); 413 } 414 SECMOD_DestroyModuleListElement(mlp); 415 } 416 return rv; 417 } 418 419 /* 420 * find a module by name and delete it off the module list 421 */ 422 SECStatus 423 SECMOD_DeleteModule(const char *name, int *type) 424 { 425 return SECMOD_DeleteModuleEx(name, NULL, type, PR_TRUE); 426 } 427 428 /* 429 * find a module by name and delete it off the module list 430 */ 431 SECStatus 432 SECMOD_DeleteInternalModule(const char *name) 433 { 434 #ifndef NSS_FIPS_DISABLED 435 SECMODModuleList *mlp; 436 SECMODModuleList **mlpp; 437 #endif 438 SECStatus rv = SECFailure; 439 440 if (SECMOD_GetSystemFIPSEnabled() || pendingModule) { 441 PORT_SetError(SEC_ERROR_MODULE_STUCK); 442 return rv; 443 } 444 if (!moduleLock) { 445 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 446 return rv; 447 } 448 449 #ifdef NSS_FIPS_DISABLED 450 PORT_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR); 451 return rv; 452 #else 453 SECMOD_GetWriteLock(moduleLock); 454 for (mlpp = &modules, mlp = modules; 455 mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) { 456 if (PORT_Strcmp(name, mlp->module->commonName) == 0) { 457 /* don't delete the internal module */ 458 if (mlp->module->internal) { 459 SECMOD_RemoveList(mlpp, mlp); 460 rv = STAN_RemoveModuleFromDefaultTrustDomain(mlp->module); 461 } 462 break; 463 } 464 } 465 SECMOD_ReleaseWriteLock(moduleLock); 466 467 if (rv == SECSuccess) { 468 SECMODModule *newModule, *oldModule; 469 470 if (mlp->module->isFIPS) { 471 newModule = SECMOD_CreateModule(NULL, SECMOD_INT_NAME, 472 NULL, SECMOD_INT_FLAGS); 473 } else { 474 newModule = SECMOD_CreateModule(NULL, SECMOD_FIPS_NAME, 475 NULL, SECMOD_FIPS_FLAGS); 476 } 477 if (newModule) { 478 PK11SlotInfo *slot; 479 newModule->libraryParams = 480 PORT_ArenaStrdup(newModule->arena, mlp->module->libraryParams); 481 /* if an explicit internal key slot has been set, reset it */ 482 slot = pk11_SwapInternalKeySlot(NULL); 483 if (slot) { 484 secmod_SetInternalKeySlotFlag(newModule, PR_TRUE); 485 } 486 rv = SECMOD_AddModule(newModule); 487 if (rv != SECSuccess) { 488 /* load failed, restore the internal key slot */ 489 pk11_SetInternalKeySlot(slot); 490 SECMOD_DestroyModule(newModule); 491 newModule = NULL; 492 } 493 /* free the old explicit internal key slot, we now have a new one */ 494 if (slot) { 495 PK11_FreeSlot(slot); 496 } 497 } 498 if (newModule == NULL) { 499 SECMODModuleList *last = NULL, *mlp2; 500 /* we're in pretty deep trouble if this happens...Security 501 * not going to work well... try to put the old module back on 502 * the list */ 503 SECMOD_GetWriteLock(moduleLock); 504 for (mlp2 = modules; mlp2 != NULL; mlp2 = mlp->next) { 505 last = mlp2; 506 } 507 508 if (last == NULL) { 509 modules = mlp; 510 } else { 511 SECMOD_AddList(last, mlp, NULL); 512 } 513 SECMOD_ReleaseWriteLock(moduleLock); 514 return SECFailure; 515 } 516 pendingModule = oldModule = internalModule; 517 internalModule = NULL; 518 SECMOD_DestroyModule(oldModule); 519 SECMOD_DeletePermDB(mlp->module); 520 SECMOD_DestroyModuleListElement(mlp); 521 internalModule = newModule; /* adopt the module */ 522 } 523 return rv; 524 #endif 525 } 526 527 SECStatus 528 SECMOD_AddModule(SECMODModule *newModule) 529 { 530 SECStatus rv; 531 SECMODModule *oldModule; 532 533 /* Test if a module w/ the same name already exists */ 534 /* and return SECWouldBlock if so. */ 535 /* We should probably add a new return value such as */ 536 /* SECDublicateModule, but to minimize ripples, I'll */ 537 /* give SECWouldBlock a new meaning */ 538 if ((oldModule = SECMOD_FindModule(newModule->commonName)) != NULL) { 539 SECMOD_DestroyModule(oldModule); 540 return SECWouldBlock; 541 /* module already exists. */ 542 } 543 544 rv = secmod_LoadPKCS11Module(newModule, NULL); 545 if (rv != SECSuccess) { 546 return rv; 547 } 548 549 if (newModule->parent == NULL) { 550 newModule->parent = SECMOD_ReferenceModule(defaultDBModule); 551 } 552 553 SECMOD_AddPermDB(newModule); 554 SECMOD_AddModuleToList(newModule); 555 556 rv = STAN_AddModuleToDefaultTrustDomain(newModule); 557 558 return rv; 559 } 560 561 PK11SlotInfo * 562 SECMOD_FindSlot(SECMODModule *module, const char *name) 563 { 564 int i; 565 char *string; 566 PK11SlotInfo *retSlot = NULL; 567 568 if (!moduleLock) { 569 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 570 return retSlot; 571 } 572 SECMOD_GetReadLock(moduleLock); 573 for (i = 0; i < module->slotCount; i++) { 574 PK11SlotInfo *slot = module->slots[i]; 575 576 if (PK11_IsPresent(slot)) { 577 string = PK11_GetTokenName(slot); 578 } else { 579 string = PK11_GetSlotName(slot); 580 } 581 if (PORT_Strcmp(name, string) == 0) { 582 retSlot = PK11_ReferenceSlot(slot); 583 break; 584 } 585 } 586 SECMOD_ReleaseReadLock(moduleLock); 587 588 if (retSlot == NULL) { 589 PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED); 590 } 591 return retSlot; 592 } 593 594 SECStatus 595 PK11_GetModInfo(SECMODModule *mod, CK_INFO *info) 596 { 597 CK_RV crv; 598 599 if (mod->functionList == NULL) 600 return SECFailure; 601 crv = PK11_GETTAB(mod)->C_GetInfo(info); 602 if (crv != CKR_OK) { 603 PORT_SetError(PK11_MapError(crv)); 604 } 605 return (crv == CKR_OK) ? SECSuccess : SECFailure; 606 } 607 608 char * 609 PK11_GetModuleURI(SECMODModule *mod) 610 { 611 CK_INFO info; 612 PK11URI *uri; 613 char *ret = NULL; 614 PK11URIAttribute attrs[3]; 615 size_t nattrs = 0; 616 char libraryManufacturer[32 + 1], libraryDescription[32 + 1], libraryVersion[8]; 617 618 if (PK11_GetModInfo(mod, &info) == SECFailure) { 619 return NULL; 620 } 621 622 PK11_MakeString(NULL, libraryManufacturer, (char *)info.manufacturerID, 623 sizeof(info.manufacturerID)); 624 if (*libraryManufacturer != '\0') { 625 attrs[nattrs].name = PK11URI_PATTR_LIBRARY_MANUFACTURER; 626 attrs[nattrs].value = libraryManufacturer; 627 nattrs++; 628 } 629 630 PK11_MakeString(NULL, libraryDescription, (char *)info.libraryDescription, 631 sizeof(info.libraryDescription)); 632 if (*libraryDescription != '\0') { 633 attrs[nattrs].name = PK11URI_PATTR_LIBRARY_DESCRIPTION; 634 attrs[nattrs].value = libraryDescription; 635 nattrs++; 636 } 637 638 PR_snprintf(libraryVersion, sizeof(libraryVersion), "%d.%d", 639 info.libraryVersion.major, info.libraryVersion.minor); 640 attrs[nattrs].name = PK11URI_PATTR_LIBRARY_VERSION; 641 attrs[nattrs].value = libraryVersion; 642 nattrs++; 643 644 uri = PK11URI_CreateURI(attrs, nattrs, NULL, 0); 645 if (uri == NULL) { 646 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 647 return NULL; 648 } 649 650 ret = PK11URI_FormatURI(NULL, uri); 651 PK11URI_DestroyURI(uri); 652 if (ret == NULL) { 653 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 654 return NULL; 655 } 656 657 return ret; 658 } 659 660 /* Determine if we have the FIP's module loaded as the default 661 * module to trigger other bogus FIPS requirements in PKCS #12 and 662 * SSL 663 */ 664 PRBool 665 PK11_IsFIPS(void) 666 { 667 SECMODModule *mod = SECMOD_GetInternalModule(); 668 669 if (mod && mod->internal) { 670 return mod->isFIPS; 671 } 672 673 return PR_FALSE; 674 } 675 676 /* combines NewModule() & AddModule */ 677 /* give a string for the module name & the full-path for the dll, */ 678 /* installs the PKCS11 module & update registry */ 679 SECStatus 680 SECMOD_AddNewModuleEx(const char *moduleName, const char *dllPath, 681 unsigned long defaultMechanismFlags, 682 unsigned long cipherEnableFlags, 683 char *modparms, char *nssparms) 684 { 685 SECMODModule *module; 686 SECStatus result = SECFailure; 687 int s, i; 688 PK11SlotInfo *slot; 689 690 PR_SetErrorText(0, NULL); 691 if (!moduleLock) { 692 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 693 return result; 694 } 695 696 module = SECMOD_CreateModule(dllPath, moduleName, modparms, nssparms); 697 698 if (module == NULL) { 699 return result; 700 } 701 702 if (module->dllName != NULL) { 703 if (module->dllName[0] != 0) { 704 result = SECMOD_AddModule(module); 705 if (result == SECSuccess) { 706 /* turn on SSL cipher enable flags */ 707 module->ssl[0] = cipherEnableFlags; 708 709 SECMOD_GetReadLock(moduleLock); 710 /* check each slot to turn on appropriate mechanisms */ 711 for (s = 0; s < module->slotCount; s++) { 712 slot = (module->slots)[s]; 713 /* for each possible mechanism */ 714 for (i = 0; i < num_pk11_default_mechanisms; i++) { 715 /* we are told to turn it on by default ? */ 716 PRBool add = 717 (PK11_DefaultArray[i].flag & defaultMechanismFlags) ? PR_TRUE : PR_FALSE; 718 result = PK11_UpdateSlotAttribute(slot, 719 &(PK11_DefaultArray[i]), add); 720 if (result != SECSuccess) { 721 SECMOD_ReleaseReadLock(moduleLock); 722 SECMOD_DestroyModule(module); 723 return result; 724 } 725 } /* for each mechanism */ 726 /* disable each slot if the defaultFlags say so */ 727 if (defaultMechanismFlags & PK11_DISABLE_FLAG) { 728 PK11_UserDisableSlot(slot); 729 } 730 } /* for each slot of this module */ 731 SECMOD_ReleaseReadLock(moduleLock); 732 733 /* delete and re-add module in order to save changes 734 * to the module */ 735 result = SECMOD_UpdateModule(module); 736 } 737 } 738 } 739 SECMOD_DestroyModule(module); 740 return result; 741 } 742 743 SECStatus 744 SECMOD_AddNewModule(const char *moduleName, const char *dllPath, 745 unsigned long defaultMechanismFlags, 746 unsigned long cipherEnableFlags) 747 { 748 return SECMOD_AddNewModuleEx(moduleName, dllPath, defaultMechanismFlags, 749 cipherEnableFlags, 750 NULL, NULL); /* don't pass module or nss params */ 751 } 752 753 SECStatus 754 SECMOD_UpdateModule(SECMODModule *module) 755 { 756 SECStatus result; 757 758 result = SECMOD_DeletePermDB(module); 759 760 if (result == SECSuccess) { 761 result = SECMOD_AddPermDB(module); 762 } 763 return result; 764 } 765 766 /* Public & Internal(Security Library) representation of 767 * encryption mechanism flags conversion */ 768 769 /* Currently, the only difference is that internal representation 770 * puts RANDOM_FLAG at bit 31 (Most-significant bit), but 771 * public representation puts this bit at bit 28 772 */ 773 unsigned long 774 SECMOD_PubMechFlagstoInternal(unsigned long publicFlags) 775 { 776 unsigned long internalFlags = publicFlags; 777 778 if (publicFlags & PUBLIC_MECH_RANDOM_FLAG) { 779 internalFlags &= ~PUBLIC_MECH_RANDOM_FLAG; 780 internalFlags |= SECMOD_RANDOM_FLAG; 781 } 782 return internalFlags; 783 } 784 785 unsigned long 786 SECMOD_InternaltoPubMechFlags(unsigned long internalFlags) 787 { 788 unsigned long publicFlags = internalFlags; 789 790 if (internalFlags & SECMOD_RANDOM_FLAG) { 791 publicFlags &= ~SECMOD_RANDOM_FLAG; 792 publicFlags |= PUBLIC_MECH_RANDOM_FLAG; 793 } 794 return publicFlags; 795 } 796 797 /* Public & Internal(Security Library) representation of */ 798 /* cipher flags conversion */ 799 /* Note: currently they are just stubs */ 800 unsigned long 801 SECMOD_PubCipherFlagstoInternal(unsigned long publicFlags) 802 { 803 return publicFlags; 804 } 805 806 unsigned long 807 SECMOD_InternaltoPubCipherFlags(unsigned long internalFlags) 808 { 809 return internalFlags; 810 } 811 812 /* Funtion reports true if module of modType is installed/configured */ 813 PRBool 814 SECMOD_IsModulePresent(unsigned long int pubCipherEnableFlags) 815 { 816 PRBool result = PR_FALSE; 817 SECMODModuleList *mods; 818 819 if (!moduleLock) { 820 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 821 return result; 822 } 823 SECMOD_GetReadLock(moduleLock); 824 mods = SECMOD_GetDefaultModuleList(); 825 for (; mods != NULL; mods = mods->next) { 826 if (mods->module->ssl[0] & 827 SECMOD_PubCipherFlagstoInternal(pubCipherEnableFlags)) { 828 result = PR_TRUE; 829 } 830 } 831 832 SECMOD_ReleaseReadLock(moduleLock); 833 return result; 834 } 835 836 /* create a new ModuleListElement */ 837 SECMODModuleList * 838 SECMOD_NewModuleListElement(void) 839 { 840 SECMODModuleList *newModList; 841 842 newModList = (SECMODModuleList *)PORT_Alloc(sizeof(SECMODModuleList)); 843 if (newModList) { 844 newModList->next = NULL; 845 newModList->module = NULL; 846 } 847 return newModList; 848 } 849 850 /* 851 * make a new reference to a module so It doesn't go away on us 852 */ 853 SECMODModule * 854 SECMOD_ReferenceModule(SECMODModule *module) 855 { 856 PZ_Lock(module->refLock); 857 PORT_Assert(module->refCount > 0); 858 859 module->refCount++; 860 PZ_Unlock(module->refLock); 861 return module; 862 } 863 864 /* destroy an existing module */ 865 void 866 SECMOD_DestroyModule(SECMODModule *module) 867 { 868 PRBool willfree = PR_FALSE; 869 int slotCount; 870 int i; 871 872 PZ_Lock(module->refLock); 873 if (module->refCount-- == 1) { 874 willfree = PR_TRUE; 875 } 876 PORT_Assert(willfree || (module->refCount > 0)); 877 PZ_Unlock(module->refLock); 878 879 if (!willfree) { 880 return; 881 } 882 883 if (module->parent != NULL) { 884 SECMODModule *parent = module->parent; 885 /* paranoia, don't loop forever if the modules are looped */ 886 module->parent = NULL; 887 SECMOD_DestroyModule(parent); 888 } 889 890 /* slots can't really disappear until our module starts freeing them, 891 * so this check is safe */ 892 slotCount = module->slotCount; 893 if (slotCount == 0) { 894 SECMOD_SlotDestroyModule(module, PR_FALSE); 895 return; 896 } 897 898 /* now free all out slots, when they are done, they will cause the 899 * module to disappear altogether */ 900 for (i = 0; i < slotCount; i++) { 901 if (!module->slots[i]->disabled) { 902 PK11_ClearSlotList(module->slots[i]); 903 } 904 PK11_FreeSlot(module->slots[i]); 905 } 906 /* WARNING: once the last slot has been freed is it possible (even likely) 907 * that module is no more... touching it now is a good way to go south */ 908 } 909 910 /* we can only get here if we've destroyed the module, or some one has 911 * erroneously freed a slot that wasn't referenced. */ 912 void 913 SECMOD_SlotDestroyModule(SECMODModule *module, PRBool fromSlot) 914 { 915 PRBool willfree = PR_FALSE; 916 if (fromSlot) { 917 PORT_Assert(module->refCount == 0); 918 PZ_Lock(module->refLock); 919 if (module->slotCount-- == 1) { 920 willfree = PR_TRUE; 921 } 922 PORT_Assert(willfree || (module->slotCount > 0)); 923 PZ_Unlock(module->refLock); 924 if (!willfree) 925 return; 926 } 927 928 if (module == pendingModule) { 929 pendingModule = NULL; 930 } 931 932 if (module->loaded) { 933 SECMOD_UnloadModule(module); 934 } 935 PZ_DestroyLock(module->refLock); 936 PORT_FreeArena(module->arena, PR_FALSE); 937 secmod_PrivateModuleCount--; 938 } 939 940 /* destroy a list element 941 * this destroys a single element, and returns the next element 942 * on the chain. It makes it easy to implement for loops to delete 943 * the chain. It also make deleting a single element easy */ 944 SECMODModuleList * 945 SECMOD_DestroyModuleListElement(SECMODModuleList *element) 946 { 947 SECMODModuleList *next = element->next; 948 949 if (element->module) { 950 SECMOD_DestroyModule(element->module); 951 element->module = NULL; 952 } 953 PORT_Free(element); 954 return next; 955 } 956 957 /* 958 * Destroy an entire module list 959 */ 960 void 961 SECMOD_DestroyModuleList(SECMODModuleList *list) 962 { 963 SECMODModuleList *lp; 964 965 for (lp = list; lp != NULL; lp = SECMOD_DestroyModuleListElement(lp)) 966 ; 967 } 968 969 PRBool 970 SECMOD_CanDeleteInternalModule(void) 971 { 972 #ifdef NSS_FIPS_DISABLED 973 return PR_FALSE; 974 #else 975 return (PRBool)((pendingModule == NULL) && !SECMOD_GetSystemFIPSEnabled()); 976 #endif 977 } 978 979 /* 980 * check to see if the module has added new slots. PKCS 11 v2.20 allows for 981 * modules to add new slots, but never remove them. Slots cannot be added 982 * between a call to C_GetSlotLlist(Flag, NULL, &count) and the subsequent 983 * C_GetSlotList(flag, &data, &count) so that the array doesn't accidently 984 * grow on the caller. It is permissible for the slots to increase between 985 * successive calls with NULL to get the size. 986 * 987 * Caller must not hold a module list read lock. 988 */ 989 SECStatus 990 SECMOD_UpdateSlotList(SECMODModule *mod) 991 { 992 CK_RV crv; 993 CK_ULONG count; 994 CK_ULONG i, oldCount; 995 PRBool freeRef = PR_FALSE; 996 void *mark = NULL; 997 CK_ULONG *slotIDs = NULL; 998 PK11SlotInfo **newSlots = NULL; 999 PK11SlotInfo **oldSlots = NULL; 1000 1001 if (!moduleLock) { 1002 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 1003 return SECFailure; 1004 } 1005 1006 /* C_GetSlotList is not a session function, make sure 1007 * calls are serialized */ 1008 PZ_Lock(mod->refLock); 1009 freeRef = PR_TRUE; 1010 /* see if the number of slots have changed */ 1011 crv = PK11_GETTAB(mod)->C_GetSlotList(PR_FALSE, NULL, &count); 1012 if (crv != CKR_OK) { 1013 PORT_SetError(PK11_MapError(crv)); 1014 goto loser; 1015 } 1016 /* nothing new, blow out early, we want this function to be quick 1017 * and cheap in the normal case */ 1018 if (count == mod->slotCount) { 1019 PZ_Unlock(mod->refLock); 1020 return SECSuccess; 1021 } 1022 if (count < (CK_ULONG)mod->slotCount) { 1023 /* shouldn't happen with a properly functioning PKCS #11 module */ 1024 PORT_SetError(SEC_ERROR_INCOMPATIBLE_PKCS11); 1025 goto loser; 1026 } 1027 1028 /* get the new slot list */ 1029 slotIDs = PORT_NewArray(CK_SLOT_ID, count); 1030 if (slotIDs == NULL) { 1031 goto loser; 1032 } 1033 1034 crv = PK11_GETTAB(mod)->C_GetSlotList(PR_FALSE, slotIDs, &count); 1035 if (crv != CKR_OK) { 1036 PORT_SetError(PK11_MapError(crv)); 1037 goto loser; 1038 } 1039 freeRef = PR_FALSE; 1040 PZ_Unlock(mod->refLock); 1041 mark = PORT_ArenaMark(mod->arena); 1042 if (mark == NULL) { 1043 goto loser; 1044 } 1045 newSlots = PORT_ArenaZNewArray(mod->arena, PK11SlotInfo *, count); 1046 1047 /* walk down the new slot ID list returned from the module. We keep 1048 * the old slots which match a returned ID, and we initialize the new 1049 * slots. */ 1050 for (i = 0; i < count; i++) { 1051 PK11SlotInfo *slot = SECMOD_FindSlotByID(mod, slotIDs[i]); 1052 1053 if (!slot) { 1054 /* we have a new slot create a new slot data structure */ 1055 slot = PK11_NewSlotInfo(mod); 1056 if (!slot) { 1057 goto loser; 1058 } 1059 PK11_InitSlot(mod, slotIDs[i], slot); 1060 STAN_InitTokenForSlotInfo(NULL, slot); 1061 } 1062 newSlots[i] = slot; 1063 } 1064 STAN_ResetTokenInterator(NULL); 1065 PORT_Free(slotIDs); 1066 slotIDs = NULL; 1067 PORT_ArenaUnmark(mod->arena, mark); 1068 1069 /* until this point we're still using the old slot list. Now we update 1070 * module slot list. We update the slots (array) first then the count, 1071 * since we've already guarrenteed that count has increased (just in case 1072 * someone is looking at the slots field of module without holding the 1073 * moduleLock */ 1074 SECMOD_GetWriteLock(moduleLock); 1075 oldCount = mod->slotCount; 1076 oldSlots = mod->slots; 1077 mod->slots = newSlots; /* typical arena 'leak'... old mod->slots is 1078 * allocated out of the module arena and won't 1079 * be freed until the module is freed */ 1080 mod->slotCount = count; 1081 SECMOD_ReleaseWriteLock(moduleLock); 1082 /* free our old references before forgetting about oldSlot*/ 1083 for (i = 0; i < oldCount; i++) { 1084 PK11_FreeSlot(oldSlots[i]); 1085 } 1086 return SECSuccess; 1087 1088 loser: 1089 if (freeRef) { 1090 PZ_Unlock(mod->refLock); 1091 } 1092 if (slotIDs) { 1093 PORT_Free(slotIDs); 1094 } 1095 /* free all the slots we allocated. newSlots are part of the 1096 * mod arena. NOTE: the newSlots array contain both new and old 1097 * slots, but we kept a reference to the old slots when we built the new 1098 * array, so we need to free all the slots in newSlots array. */ 1099 if (newSlots) { 1100 for (i = 0; i < count; i++) { 1101 if (newSlots[i] == NULL) { 1102 break; /* hit the last one */ 1103 } 1104 PK11_FreeSlot(newSlots[i]); 1105 } 1106 } 1107 /* must come after freeing newSlots */ 1108 if (mark) { 1109 PORT_ArenaRelease(mod->arena, mark); 1110 } 1111 return SECFailure; 1112 } 1113 1114 /* 1115 * this handles modules that do not support C_WaitForSlotEvent(). 1116 * The internal flags are stored. Note that C_WaitForSlotEvent() does not 1117 * have a timeout, so we don't have one for handleWaitForSlotEvent() either. 1118 */ 1119 PK11SlotInfo * 1120 secmod_HandleWaitForSlotEvent(SECMODModule *mod, unsigned long flags, 1121 PRIntervalTime latency) 1122 { 1123 PRBool removableSlotsFound = PR_FALSE; 1124 int i; 1125 int error = SEC_ERROR_NO_EVENT; 1126 1127 if (!moduleLock) { 1128 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 1129 return NULL; 1130 } 1131 PZ_Lock(mod->refLock); 1132 if (mod->evControlMask & SECMOD_END_WAIT) { 1133 mod->evControlMask &= ~SECMOD_END_WAIT; 1134 PZ_Unlock(mod->refLock); 1135 PORT_SetError(SEC_ERROR_NO_EVENT); 1136 return NULL; 1137 } 1138 mod->evControlMask |= SECMOD_WAIT_SIMULATED_EVENT; 1139 while (mod->evControlMask & SECMOD_WAIT_SIMULATED_EVENT) { 1140 PZ_Unlock(mod->refLock); 1141 /* now is a good time to see if new slots have been added */ 1142 SECMOD_UpdateSlotList(mod); 1143 1144 /* loop through all the slots on a module */ 1145 SECMOD_GetReadLock(moduleLock); 1146 for (i = 0; i < mod->slotCount; i++) { 1147 PK11SlotInfo *slot = mod->slots[i]; 1148 PRUint16 series; 1149 PRBool present; 1150 1151 /* perm modules do not change */ 1152 if (slot->isPerm) { 1153 continue; 1154 } 1155 removableSlotsFound = PR_TRUE; 1156 /* simulate the PKCS #11 module flags. are the flags different 1157 * from the last time we called? */ 1158 series = slot->series; 1159 present = PK11_IsPresent(slot); 1160 if ((slot->flagSeries != series) || (slot->flagState != present)) { 1161 slot->flagState = present; 1162 slot->flagSeries = series; 1163 SECMOD_ReleaseReadLock(moduleLock); 1164 PZ_Lock(mod->refLock); 1165 mod->evControlMask &= ~SECMOD_END_WAIT; 1166 PZ_Unlock(mod->refLock); 1167 return PK11_ReferenceSlot(slot); 1168 } 1169 } 1170 SECMOD_ReleaseReadLock(moduleLock); 1171 /* if everything was perm modules, don't lock up forever */ 1172 if ((mod->slotCount != 0) && !removableSlotsFound) { 1173 error = SEC_ERROR_NO_SLOT_SELECTED; 1174 PZ_Lock(mod->refLock); 1175 break; 1176 } 1177 if (flags & CKF_DONT_BLOCK) { 1178 PZ_Lock(mod->refLock); 1179 break; 1180 } 1181 PR_Sleep(latency); 1182 PZ_Lock(mod->refLock); 1183 } 1184 mod->evControlMask &= ~SECMOD_END_WAIT; 1185 PZ_Unlock(mod->refLock); 1186 PORT_SetError(error); 1187 return NULL; 1188 } 1189 1190 /* 1191 * this function waits for a token event on any slot of a given module 1192 * This function should not be called from more than one thread of the 1193 * same process (though other threads can make other library calls 1194 * on this module while this call is blocked). 1195 */ 1196 PK11SlotInfo * 1197 SECMOD_WaitForAnyTokenEvent(SECMODModule *mod, unsigned long flags, 1198 PRIntervalTime latency) 1199 { 1200 CK_SLOT_ID id; 1201 CK_RV crv; 1202 PK11SlotInfo *slot; 1203 1204 if (!pk11_getFinalizeModulesOption() || 1205 ((mod->cryptokiVersion.major == 2) && 1206 (mod->cryptokiVersion.minor < 1))) { 1207 /* if we are sharing the module with other software in our 1208 * address space, we can't reliably use C_WaitForSlotEvent(), 1209 * and if the module is version 2.0, C_WaitForSlotEvent() doesn't 1210 * exist */ 1211 return secmod_HandleWaitForSlotEvent(mod, flags, latency); 1212 } 1213 /* first the the PKCS #11 call */ 1214 PZ_Lock(mod->refLock); 1215 if (mod->evControlMask & SECMOD_END_WAIT) { 1216 goto end_wait; 1217 } 1218 mod->evControlMask |= SECMOD_WAIT_PKCS11_EVENT; 1219 PZ_Unlock(mod->refLock); 1220 crv = PK11_GETTAB(mod)->C_WaitForSlotEvent(flags, &id, NULL); 1221 PZ_Lock(mod->refLock); 1222 mod->evControlMask &= ~SECMOD_WAIT_PKCS11_EVENT; 1223 /* if we are in end wait, short circuit now, don't even risk 1224 * going into secmod_HandleWaitForSlotEvent */ 1225 if (mod->evControlMask & SECMOD_END_WAIT) { 1226 goto end_wait; 1227 } 1228 PZ_Unlock(mod->refLock); 1229 if (crv == CKR_FUNCTION_NOT_SUPPORTED) { 1230 /* module doesn't support that call, simulate it */ 1231 return secmod_HandleWaitForSlotEvent(mod, flags, latency); 1232 } 1233 if (crv != CKR_OK) { 1234 /* we can get this error if finalize was called while we were 1235 * still running. This is the only way to force a C_WaitForSlotEvent() 1236 * to return in PKCS #11. In this case, just return that there 1237 * was no event. */ 1238 if (crv == CKR_CRYPTOKI_NOT_INITIALIZED) { 1239 PORT_SetError(SEC_ERROR_NO_EVENT); 1240 } else { 1241 PORT_SetError(PK11_MapError(crv)); 1242 } 1243 return NULL; 1244 } 1245 slot = SECMOD_FindSlotByID(mod, id); 1246 if (slot == NULL) { 1247 /* possibly a new slot that was added? */ 1248 SECMOD_UpdateSlotList(mod); 1249 slot = SECMOD_FindSlotByID(mod, id); 1250 } 1251 /* if we are in the delay period for the "isPresent" call, reset 1252 * the delay since we know things have probably changed... */ 1253 if (slot) { 1254 NSSToken *nssToken = PK11Slot_GetNSSToken(slot); 1255 if (nssToken) { 1256 if (nssToken->slot) { 1257 nssSlot_ResetDelay(nssToken->slot); 1258 } 1259 (void)nssToken_Destroy(nssToken); 1260 } 1261 } 1262 return slot; 1263 1264 /* must be called with the lock on. */ 1265 end_wait: 1266 mod->evControlMask &= ~SECMOD_END_WAIT; 1267 PZ_Unlock(mod->refLock); 1268 PORT_SetError(SEC_ERROR_NO_EVENT); 1269 return NULL; 1270 } 1271 1272 /* 1273 * This function "wakes up" WaitForAnyTokenEvent. It's a pretty drastic 1274 * function, possibly bringing down the pkcs #11 module in question. This 1275 * should be OK because 1) it does reinitialize, and 2) it should only be 1276 * called when we are on our way to tear the whole system down anyway. 1277 */ 1278 SECStatus 1279 SECMOD_CancelWait(SECMODModule *mod) 1280 { 1281 unsigned long controlMask; 1282 SECStatus rv = SECSuccess; 1283 CK_RV crv; 1284 1285 PZ_Lock(mod->refLock); 1286 mod->evControlMask |= SECMOD_END_WAIT; 1287 controlMask = mod->evControlMask; 1288 if (controlMask & SECMOD_WAIT_PKCS11_EVENT) { 1289 if (!pk11_getFinalizeModulesOption()) { 1290 /* can't get here unless pk11_getFinalizeModulesOption is set */ 1291 PORT_Assert(0); 1292 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1293 rv = SECFailure; 1294 goto loser; 1295 } 1296 /* NOTE: this call will drop all transient keys, in progress 1297 * operations, and any authentication. This is the only documented 1298 * way to get WaitForSlotEvent to return. Also note: for non-thread 1299 * safe tokens, we need to hold the module lock, this is not yet at 1300 * system shutdown/startup time, so we need to protect these calls */ 1301 crv = PK11_GETTAB(mod)->C_Finalize(NULL); 1302 /* ok, we slammed the module down, now we need to reinit it in case 1303 * we intend to use it again */ 1304 if (CKR_OK == crv) { 1305 PRBool alreadyLoaded; 1306 secmod_ModuleInit(mod, NULL, &alreadyLoaded); 1307 } else { 1308 /* Finalized failed for some reason, notify the application 1309 * so maybe it has a prayer of recovering... */ 1310 PORT_SetError(PK11_MapError(crv)); 1311 rv = SECFailure; 1312 } 1313 } else if (controlMask & SECMOD_WAIT_SIMULATED_EVENT) { 1314 mod->evControlMask &= ~SECMOD_WAIT_SIMULATED_EVENT; 1315 /* Simulated events will eventually timeout 1316 * and wake up in the loop */ 1317 } 1318 loser: 1319 PZ_Unlock(mod->refLock); 1320 return rv; 1321 } 1322 1323 /* 1324 * check to see if the module has removable slots that we may need to 1325 * watch for. 1326 */ 1327 PRBool 1328 SECMOD_HasRemovableSlots(SECMODModule *mod) 1329 { 1330 PRBool ret = PR_FALSE; 1331 if (!moduleLock) { 1332 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 1333 return ret; 1334 } 1335 SECMOD_GetReadLock(moduleLock); 1336 ret = SECMOD_LockedModuleHasRemovableSlots(mod); 1337 SECMOD_ReleaseReadLock(moduleLock); 1338 return ret; 1339 } 1340 1341 PRBool 1342 SECMOD_LockedModuleHasRemovableSlots(SECMODModule *mod) 1343 { 1344 int i; 1345 PRBool ret; 1346 if (mod->slotCount == 0) { 1347 return PR_TRUE; 1348 } 1349 1350 ret = PR_FALSE; 1351 for (i = 0; i < mod->slotCount; i++) { 1352 PK11SlotInfo *slot = mod->slots[i]; 1353 /* perm modules are not inserted or removed */ 1354 if (slot->isPerm) { 1355 continue; 1356 } 1357 ret = PR_TRUE; 1358 break; 1359 } 1360 return ret; 1361 } 1362 1363 /* 1364 * helper function to actually create and destroy user defined slots 1365 */ 1366 static SECStatus 1367 secmod_UserDBOp(PK11SlotInfo *slot, CK_OBJECT_CLASS objClass, 1368 const char *sendSpec) 1369 { 1370 CK_OBJECT_HANDLE dummy; 1371 CK_ATTRIBUTE template[2]; 1372 CK_ATTRIBUTE *attrs = template; 1373 CK_RV crv; 1374 1375 PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass)); 1376 attrs++; 1377 PK11_SETATTRS(attrs, CKA_NSS_MODULE_SPEC, (unsigned char *)sendSpec, 1378 strlen(sendSpec) + 1); 1379 attrs++; 1380 1381 PORT_Assert(attrs - template <= 2); 1382 1383 PK11_EnterSlotMonitor(slot); 1384 crv = PK11_CreateNewObject(slot, slot->session, 1385 template, attrs - template, PR_FALSE, &dummy); 1386 PK11_ExitSlotMonitor(slot); 1387 1388 if (crv != CKR_OK) { 1389 PORT_SetError(PK11_MapError(crv)); 1390 return SECFailure; 1391 } 1392 return SECMOD_UpdateSlotList(slot->module); 1393 } 1394 1395 /* 1396 * return true if the selected slot ID is not present or doesn't exist 1397 */ 1398 static PRBool 1399 secmod_SlotIsEmpty(SECMODModule *mod, CK_SLOT_ID slotID) 1400 { 1401 PK11SlotInfo *slot = SECMOD_LookupSlot(mod->moduleID, slotID); 1402 if (slot) { 1403 PRBool present = PK11_IsPresent(slot); 1404 PK11_FreeSlot(slot); 1405 if (present) { 1406 return PR_FALSE; 1407 } 1408 } 1409 /* it doesn't exist or isn't present, it's available */ 1410 return PR_TRUE; 1411 } 1412 1413 /* 1414 * Find an unused slot id in module. 1415 */ 1416 static CK_SLOT_ID 1417 secmod_FindFreeSlot(SECMODModule *mod) 1418 { 1419 CK_SLOT_ID i, minSlotID, maxSlotID; 1420 1421 /* look for a free slot id on the internal module */ 1422 if (mod->internal && mod->isFIPS) { 1423 minSlotID = SFTK_MIN_FIPS_USER_SLOT_ID; 1424 maxSlotID = SFTK_MAX_FIPS_USER_SLOT_ID; 1425 } else { 1426 minSlotID = SFTK_MIN_USER_SLOT_ID; 1427 maxSlotID = SFTK_MAX_USER_SLOT_ID; 1428 } 1429 for (i = minSlotID; i < maxSlotID; i++) { 1430 if (secmod_SlotIsEmpty(mod, i)) { 1431 return i; 1432 } 1433 } 1434 PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED); 1435 return (CK_SLOT_ID)-1; 1436 } 1437 1438 /* 1439 * Attempt to open a new slot. 1440 * 1441 * This works the same os OpenUserDB except it can be called against 1442 * any module that understands the softoken protocol for opening new 1443 * slots, not just the softoken itself. If the selected module does not 1444 * understand the protocol, C_CreateObject will fail with 1445 * CKR_INVALID_ATTRIBUTE, and SECMOD_OpenNewSlot will return NULL and set 1446 * SEC_ERROR_BAD_DATA. 1447 * 1448 * NewSlots can be closed with SECMOD_CloseUserDB(); 1449 * 1450 * Modulespec is module dependent. 1451 */ 1452 PK11SlotInfo * 1453 SECMOD_OpenNewSlot(SECMODModule *mod, const char *moduleSpec) 1454 { 1455 CK_SLOT_ID slotID = 0; 1456 PK11SlotInfo *slot; 1457 char *escSpec; 1458 char *sendSpec; 1459 SECStatus rv; 1460 1461 slotID = secmod_FindFreeSlot(mod); 1462 if (slotID == (CK_SLOT_ID)-1) { 1463 return NULL; 1464 } 1465 1466 if (mod->slotCount == 0) { 1467 return NULL; 1468 } 1469 1470 /* just grab the first slot in the module, any present slot should work */ 1471 slot = PK11_ReferenceSlot(mod->slots[0]); 1472 if (slot == NULL) { 1473 return NULL; 1474 } 1475 1476 /* we've found the slot, now build the moduleSpec */ 1477 escSpec = NSSUTIL_DoubleEscape(moduleSpec, '>', ']'); 1478 if (escSpec == NULL) { 1479 PK11_FreeSlot(slot); 1480 return NULL; 1481 } 1482 sendSpec = PR_smprintf("tokens=[0x%x=<%s>]", slotID, escSpec); 1483 PORT_Free(escSpec); 1484 1485 if (sendSpec == NULL) { 1486 /* PR_smprintf does not set SEC_ERROR_NO_MEMORY on failure. */ 1487 PK11_FreeSlot(slot); 1488 PORT_SetError(SEC_ERROR_NO_MEMORY); 1489 return NULL; 1490 } 1491 rv = secmod_UserDBOp(slot, CKO_NSS_NEWSLOT, sendSpec); 1492 PR_smprintf_free(sendSpec); 1493 PK11_FreeSlot(slot); 1494 if (rv != SECSuccess) { 1495 return NULL; 1496 } 1497 1498 slot = SECMOD_FindSlotByID(mod, slotID); 1499 if (slot) { 1500 /* if we are in the delay period for the "isPresent" call, reset 1501 * the delay since we know things have probably changed... */ 1502 NSSToken *nssToken = PK11Slot_GetNSSToken(slot); 1503 if (nssToken) { 1504 if (nssToken->slot) { 1505 nssSlot_ResetDelay(nssToken->slot); 1506 } 1507 (void)nssToken_Destroy(nssToken); 1508 } 1509 /* force the slot info structures to properly reset */ 1510 (void)PK11_IsPresent(slot); 1511 } 1512 return slot; 1513 } 1514 1515 /* 1516 * given a module spec, find the slot in the module for it. 1517 */ 1518 PK11SlotInfo * 1519 secmod_FindSlotFromModuleSpec(const char *moduleSpec, SECMODModule *module) 1520 { 1521 CK_SLOT_ID slot_id = secmod_GetSlotIDFromModuleSpec(moduleSpec, module); 1522 if (slot_id == -1) { 1523 return NULL; 1524 } 1525 1526 return SECMOD_FindSlotByID(module, slot_id); 1527 } 1528 1529 /* 1530 * Open a new database using the softoken. The caller is responsible for making 1531 * sure the module spec is correct and usable. The caller should ask for one 1532 * new database per call if the caller wants to get meaningful information 1533 * about the new database. 1534 * 1535 * moduleSpec is the same data that you would pass to softoken at 1536 * initialization time under the 'tokens' options. For example, if you were 1537 * to specify tokens=<0x4=[configdir='./mybackup' tokenDescription='Backup']> 1538 * You would specify "configdir='./mybackup' tokenDescription='Backup'" as your 1539 * module spec here. The slot ID will be calculated for you by 1540 * SECMOD_OpenUserDB(). 1541 * 1542 * Typical parameters here are configdir, tokenDescription and flags. 1543 * 1544 * a Full list is below: 1545 * 1546 * 1547 * configDir - The location of the databases for this token. If configDir is 1548 * not specified, and noCertDB and noKeyDB is not specified, the load 1549 * will fail. 1550 * certPrefix - Cert prefix for this token. 1551 * keyPrefix - Prefix for the key database for this token. (if not specified, 1552 * certPrefix will be used). 1553 * tokenDescription - The label value for this token returned in the 1554 * CK_TOKEN_INFO structure with an internationalize string (UTF8). 1555 * This value will be truncated at 32 bytes (no NULL, partial UTF8 1556 * characters dropped). You should specify a user friendly name here 1557 * as this is the value the token will be referred to in most 1558 * application UI's. You should make sure tokenDescription is unique. 1559 * slotDescription - The slotDescription value for this token returned 1560 * in the CK_SLOT_INFO structure with an internationalize string 1561 * (UTF8). This value will be truncated at 64 bytes (no NULL, partial 1562 * UTF8 characters dropped). This name will not change after the 1563 * database is closed. It should have some number to make this unique. 1564 * minPWLen - minimum password length for this token. 1565 * flags - comma separated list of flag values, parsed case-insensitive. 1566 * Valid flags are: 1567 * readOnly - Databases should be opened read only. 1568 * noCertDB - Don't try to open a certificate database. 1569 * noKeyDB - Don't try to open a key database. 1570 * forceOpen - Don't fail to initialize the token if the 1571 * databases could not be opened. 1572 * passwordRequired - zero length passwords are not acceptable 1573 * (valid only if there is a keyDB). 1574 * optimizeSpace - allocate smaller hash tables and lock tables. 1575 * When this flag is not specified, Softoken will allocate 1576 * large tables to prevent lock contention. 1577 */ 1578 PK11SlotInfo * 1579 SECMOD_OpenUserDB(const char *moduleSpec) 1580 { 1581 SECMODModule *mod; 1582 SECMODConfigList *conflist = NULL; 1583 int count = 0; 1584 1585 if (moduleSpec == NULL) { 1586 return NULL; 1587 } 1588 1589 /* NOTE: unlike most PK11 function, this does not return a reference 1590 * to the module */ 1591 mod = SECMOD_GetInternalModule(); 1592 if (!mod) { 1593 /* shouldn't happen */ 1594 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1595 return NULL; 1596 } 1597 1598 /* make sure we don't open the same database twice. We only understand 1599 * the moduleSpec for internal databases well enough to do this, so only 1600 * do this in OpenUserDB */ 1601 conflist = secmod_GetConfigList(mod->isFIPS, mod->libraryParams, &count); 1602 if (conflist) { 1603 PK11SlotInfo *slot = NULL; 1604 if (secmod_MatchConfigList(moduleSpec, conflist, count)) { 1605 slot = secmod_FindSlotFromModuleSpec(moduleSpec, mod); 1606 } 1607 secmod_FreeConfigList(conflist, count); 1608 if (slot) { 1609 return slot; 1610 } 1611 } 1612 return SECMOD_OpenNewSlot(mod, moduleSpec); 1613 } 1614 1615 /* 1616 * close an already opened user database. NOTE: the database must be 1617 * in the internal token, and must be one created with SECMOD_OpenUserDB(). 1618 * Once the database is closed, the slot will remain as an empty slot 1619 * until it's used again with SECMOD_OpenUserDB() or SECMOD_OpenNewSlot(). 1620 */ 1621 SECStatus 1622 SECMOD_CloseUserDB(PK11SlotInfo *slot) 1623 { 1624 SECStatus rv; 1625 char *sendSpec; 1626 1627 sendSpec = PR_smprintf("tokens=[0x%x=<>]", slot->slotID); 1628 if (sendSpec == NULL) { 1629 /* PR_smprintf does not set no memory error */ 1630 PORT_SetError(SEC_ERROR_NO_MEMORY); 1631 return SECFailure; 1632 } 1633 rv = secmod_UserDBOp(slot, CKO_NSS_DELSLOT, sendSpec); 1634 PR_smprintf_free(sendSpec); 1635 /* if we are in the delay period for the "isPresent" call, reset 1636 * the delay since we know things have probably changed... */ 1637 NSSToken *nssToken = PK11Slot_GetNSSToken(slot); 1638 if (nssToken) { 1639 if (nssToken->slot) { 1640 nssSlot_ResetDelay(nssToken->slot); 1641 } 1642 (void)nssToken_Destroy(nssToken); 1643 /* force the slot info structures to properly reset */ 1644 (void)PK11_IsPresent(slot); 1645 } 1646 return rv; 1647 } 1648 1649 /* 1650 * Restart PKCS #11 modules after a fork(). See secmod.h for more information. 1651 */ 1652 SECStatus 1653 SECMOD_RestartModules(PRBool force) 1654 { 1655 SECMODModuleList *mlp; 1656 SECStatus rrv = SECSuccess; 1657 int lastError = 0; 1658 1659 if (!moduleLock) { 1660 PORT_SetError(SEC_ERROR_NOT_INITIALIZED); 1661 return SECFailure; 1662 } 1663 1664 /* Only need to restart the PKCS #11 modules that were initialized */ 1665 SECMOD_GetReadLock(moduleLock); 1666 for (mlp = modules; mlp != NULL; mlp = mlp->next) { 1667 SECMODModule *mod = mlp->module; 1668 CK_ULONG count; 1669 SECStatus rv; 1670 int i; 1671 1672 /* If the module needs to be reset, do so */ 1673 if (force || (PK11_GETTAB(mod)->C_GetSlotList(CK_FALSE, NULL, &count) != CKR_OK)) { 1674 PRBool alreadyLoaded; 1675 /* first call Finalize. This is not required by PKCS #11, but some 1676 * older modules require it, and it doesn't hurt (compliant modules 1677 * will return CKR_NOT_INITIALIZED */ 1678 (void)PK11_GETTAB(mod)->C_Finalize(NULL); 1679 /* now initialize the module, this function reinitializes 1680 * a module in place, preserving existing slots (even if they 1681 * no longer exist) */ 1682 rv = secmod_ModuleInit(mod, NULL, &alreadyLoaded); 1683 if (rv != SECSuccess) { 1684 /* save the last error code */ 1685 lastError = PORT_GetError(); 1686 rrv = rv; 1687 /* couldn't reinit the module, disable all its slots */ 1688 for (i = 0; i < mod->slotCount; i++) { 1689 mod->slots[i]->disabled = PR_TRUE; 1690 mod->slots[i]->reason = PK11_DIS_COULD_NOT_INIT_TOKEN; 1691 } 1692 continue; 1693 } 1694 for (i = 0; i < mod->slotCount; i++) { 1695 /* get new token sessions, bump the series up so that 1696 * we refresh other old sessions. This will tell much of 1697 * NSS to flush cached handles it may hold as well */ 1698 rv = PK11_InitToken(mod->slots[i], PR_TRUE); 1699 /* PK11_InitToken could fail if the slot isn't present. 1700 * If it is present, though, something is wrong and we should 1701 * disable the slot and let the caller know. */ 1702 if (rv != SECSuccess && PK11_IsPresent(mod->slots[i])) { 1703 /* save the last error code */ 1704 lastError = PORT_GetError(); 1705 rrv = rv; 1706 /* disable the token */ 1707 mod->slots[i]->disabled = PR_TRUE; 1708 mod->slots[i]->reason = PK11_DIS_COULD_NOT_INIT_TOKEN; 1709 } 1710 } 1711 } 1712 } 1713 SECMOD_ReleaseReadLock(moduleLock); 1714 1715 /* 1716 * on multiple failures, we are only returning the lastError. The caller 1717 * can determine which slots are bad by calling PK11_IsDisabled(). 1718 */ 1719 if (rrv != SECSuccess) { 1720 /* restore the last error code */ 1721 PORT_SetError(lastError); 1722 } 1723 1724 return rrv; 1725 }