/security/nss/lib/pk11wrap/pk11util.c

http://github.com/zpao/v8monkey · C · 1597 lines · 1074 code · 167 blank · 356 comment · 270 complexity · c29ee9a980eda84ac22ed798a550d4ff MD5 · raw file

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