PageRenderTime 27ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/security/nss/lib/pk11wrap/pk11slot.c

https://bitbucket.org/mkato/mozilla-1.9.0-win64
C | 2193 lines | 1599 code | 246 blank | 348 comment | 438 complexity | 98738b11d55c3e59ca570e2c53ba611d MD5 | raw file
Possible License(s): LGPL-3.0, MIT, BSD-3-Clause, MPL-2.0-no-copyleft-exception, GPL-2.0, LGPL-2.1
  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. * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
  23. *
  24. * Alternatively, the contents of this file may be used under the terms of
  25. * either the GNU General Public License Version 2 or later (the "GPL"), or
  26. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27. * in which case the provisions of the GPL or the LGPL are applicable instead
  28. * of those above. If you wish to allow use of your version of this file only
  29. * under the terms of either the GPL or the LGPL, and not to allow others to
  30. * use your version of this file under the terms of the MPL, indicate your
  31. * decision by deleting the provisions above and replace them with the notice
  32. * and other provisions required by the GPL or the LGPL. If you do not delete
  33. * the provisions above, a recipient may use your version of this file under
  34. * the terms of any one of the MPL, the GPL or the LGPL.
  35. *
  36. * ***** END LICENSE BLOCK ***** */
  37. /*
  38. * Deal with PKCS #11 Slots.
  39. */
  40. #include "seccomon.h"
  41. #include "secmod.h"
  42. #include "nssilock.h"
  43. #include "secmodi.h"
  44. #include "secmodti.h"
  45. #include "pkcs11t.h"
  46. #include "pk11func.h"
  47. #include "secitem.h"
  48. #include "secerr.h"
  49. #include "dev.h"
  50. #include "dev3hack.h"
  51. #include "pkim.h"
  52. /*************************************************************
  53. * local static and global data
  54. *************************************************************/
  55. /*
  56. * This array helps parsing between names, mechanisms, and flags.
  57. * to make the config files understand more entries, add them
  58. * to this table. (NOTE: we need function to export this table and it's size)
  59. */
  60. PK11DefaultArrayEntry PK11_DefaultArray[] = {
  61. { "RSA", SECMOD_RSA_FLAG, CKM_RSA_PKCS },
  62. { "DSA", SECMOD_DSA_FLAG, CKM_DSA },
  63. { "DH", SECMOD_DH_FLAG, CKM_DH_PKCS_DERIVE },
  64. { "RC2", SECMOD_RC2_FLAG, CKM_RC2_CBC },
  65. { "RC4", SECMOD_RC4_FLAG, CKM_RC4 },
  66. { "DES", SECMOD_DES_FLAG, CKM_DES_CBC },
  67. { "AES", SECMOD_AES_FLAG, CKM_AES_CBC },
  68. { "Camellia", SECMOD_CAMELLIA_FLAG, CKM_CAMELLIA_CBC },
  69. { "SEED", SECMOD_SEED_FLAG, CKM_SEED_CBC },
  70. { "RC5", SECMOD_RC5_FLAG, CKM_RC5_CBC },
  71. { "SHA-1", SECMOD_SHA1_FLAG, CKM_SHA_1 },
  72. { "SHA256", SECMOD_SHA256_FLAG, CKM_SHA256 },
  73. /* { "SHA384", SECMOD_SHA512_FLAG, CKM_SHA384 }, */
  74. { "SHA512", SECMOD_SHA512_FLAG, CKM_SHA512 },
  75. { "MD5", SECMOD_MD5_FLAG, CKM_MD5 },
  76. { "MD2", SECMOD_MD2_FLAG, CKM_MD2 },
  77. { "SSL", SECMOD_SSL_FLAG, CKM_SSL3_PRE_MASTER_KEY_GEN },
  78. { "TLS", SECMOD_TLS_FLAG, CKM_TLS_MASTER_KEY_DERIVE },
  79. { "SKIPJACK", SECMOD_FORTEZZA_FLAG, CKM_SKIPJACK_CBC64 },
  80. { "Publicly-readable certs", SECMOD_FRIENDLY_FLAG, CKM_INVALID_MECHANISM },
  81. { "Random Num Generator", SECMOD_RANDOM_FLAG, CKM_FAKE_RANDOM },
  82. };
  83. const int num_pk11_default_mechanisms =
  84. sizeof(PK11_DefaultArray) / sizeof(PK11_DefaultArray[0]);
  85. PK11DefaultArrayEntry *
  86. PK11_GetDefaultArray(int *size)
  87. {
  88. if (size) {
  89. *size = num_pk11_default_mechanisms;
  90. }
  91. return PK11_DefaultArray;
  92. }
  93. /*
  94. * These slotlists are lists of modules which provide default support for
  95. * a given algorithm or mechanism.
  96. */
  97. static PK11SlotList
  98. pk11_seedSlotList,
  99. pk11_camelliaSlotList,
  100. pk11_aesSlotList,
  101. pk11_desSlotList,
  102. pk11_rc4SlotList,
  103. pk11_rc2SlotList,
  104. pk11_rc5SlotList,
  105. pk11_sha1SlotList,
  106. pk11_md5SlotList,
  107. pk11_md2SlotList,
  108. pk11_rsaSlotList,
  109. pk11_dsaSlotList,
  110. pk11_dhSlotList,
  111. pk11_ecSlotList,
  112. pk11_ideaSlotList,
  113. pk11_sslSlotList,
  114. pk11_tlsSlotList,
  115. pk11_randomSlotList,
  116. pk11_sha256SlotList,
  117. pk11_sha512SlotList; /* slots do SHA512 and SHA384 */
  118. /************************************************************
  119. * Generic Slot List and Slot List element manipulations
  120. ************************************************************/
  121. /*
  122. * allocate a new list
  123. */
  124. PK11SlotList *
  125. PK11_NewSlotList(void)
  126. {
  127. PK11SlotList *list;
  128. list = (PK11SlotList *)PORT_Alloc(sizeof(PK11SlotList));
  129. if (list == NULL) return NULL;
  130. list->head = NULL;
  131. list->tail = NULL;
  132. list->lock = PZ_NewLock(nssILockList);
  133. if (list->lock == NULL) {
  134. PORT_Free(list);
  135. return NULL;
  136. }
  137. return list;
  138. }
  139. /*
  140. * free a list element when all the references go away.
  141. */
  142. SECStatus
  143. PK11_FreeSlotListElement(PK11SlotList *list, PK11SlotListElement *le)
  144. {
  145. PRBool freeit = PR_FALSE;
  146. if (list == NULL || le == NULL) {
  147. PORT_SetError(SEC_ERROR_INVALID_ARGS);
  148. return SECFailure;
  149. }
  150. PZ_Lock(list->lock);
  151. if (le->refCount-- == 1) {
  152. freeit = PR_TRUE;
  153. }
  154. PZ_Unlock(list->lock);
  155. if (freeit) {
  156. PK11_FreeSlot(le->slot);
  157. PORT_Free(le);
  158. }
  159. return SECSuccess;
  160. }
  161. static void
  162. pk11_FreeSlotListStatic(PK11SlotList *list)
  163. {
  164. PK11SlotListElement *le, *next ;
  165. if (list == NULL) return;
  166. for (le = list->head ; le; le = next) {
  167. next = le->next;
  168. PK11_FreeSlotListElement(list,le);
  169. }
  170. if (list->lock) {
  171. PZ_DestroyLock(list->lock);
  172. }
  173. list->lock = NULL;
  174. list->head = NULL;
  175. }
  176. /*
  177. * if we are freeing the list, we must be the only ones with a pointer
  178. * to the list.
  179. */
  180. void
  181. PK11_FreeSlotList(PK11SlotList *list)
  182. {
  183. pk11_FreeSlotListStatic(list);
  184. PORT_Free(list);
  185. }
  186. /*
  187. * add a slot to a list
  188. */
  189. SECStatus
  190. PK11_AddSlotToList(PK11SlotList *list,PK11SlotInfo *slot)
  191. {
  192. PK11SlotListElement *le;
  193. le = (PK11SlotListElement *) PORT_Alloc(sizeof(PK11SlotListElement));
  194. if (le == NULL) return SECFailure;
  195. le->slot = PK11_ReferenceSlot(slot);
  196. le->prev = NULL;
  197. le->refCount = 1;
  198. PZ_Lock(list->lock);
  199. if (list->head) list->head->prev = le; else list->tail = le;
  200. le->next = list->head;
  201. list->head = le;
  202. PZ_Unlock(list->lock);
  203. return SECSuccess;
  204. }
  205. /*
  206. * remove a slot entry from the list
  207. */
  208. SECStatus
  209. PK11_DeleteSlotFromList(PK11SlotList *list,PK11SlotListElement *le)
  210. {
  211. PZ_Lock(list->lock);
  212. if (le->prev) le->prev->next = le->next; else list->head = le->next;
  213. if (le->next) le->next->prev = le->prev; else list->tail = le->prev;
  214. le->next = le->prev = NULL;
  215. PZ_Unlock(list->lock);
  216. PK11_FreeSlotListElement(list,le);
  217. return SECSuccess;
  218. }
  219. /*
  220. * Move a list to the end of the target list. NOTE: There is no locking
  221. * here... This assumes BOTH lists are private copy lists.
  222. */
  223. SECStatus
  224. PK11_MoveListToList(PK11SlotList *target,PK11SlotList *src)
  225. {
  226. if (src->head == NULL) return SECSuccess;
  227. if (target->tail == NULL) {
  228. target->head = src->head;
  229. } else {
  230. target->tail->next = src->head;
  231. }
  232. src->head->prev = target->tail;
  233. target->tail = src->tail;
  234. src->head = src->tail = NULL;
  235. return SECSuccess;
  236. }
  237. /*
  238. * get an element from the list with a reference. You must own the list.
  239. */
  240. PK11SlotListElement *
  241. PK11_GetFirstRef(PK11SlotList *list)
  242. {
  243. PK11SlotListElement *le;
  244. le = list->head;
  245. if (le != NULL) (le)->refCount++;
  246. return le;
  247. }
  248. /*
  249. * get the next element from the list with a reference. You must own the list.
  250. */
  251. PK11SlotListElement *
  252. PK11_GetNextRef(PK11SlotList *list, PK11SlotListElement *le, PRBool restart)
  253. {
  254. PK11SlotListElement *new_le;
  255. new_le = le->next;
  256. if (new_le) new_le->refCount++;
  257. PK11_FreeSlotListElement(list,le);
  258. return new_le;
  259. }
  260. /*
  261. * get an element safely from the list. This just makes sure that if
  262. * this element is not deleted while we deal with it.
  263. */
  264. PK11SlotListElement *
  265. PK11_GetFirstSafe(PK11SlotList *list)
  266. {
  267. PK11SlotListElement *le;
  268. PZ_Lock(list->lock);
  269. le = list->head;
  270. if (le != NULL) (le)->refCount++;
  271. PZ_Unlock(list->lock);
  272. return le;
  273. }
  274. /*
  275. * NOTE: if this element gets deleted, we can no longer safely traverse using
  276. * it's pointers. We can either terminate the loop, or restart from the
  277. * beginning. This is controlled by the restart option.
  278. */
  279. PK11SlotListElement *
  280. PK11_GetNextSafe(PK11SlotList *list, PK11SlotListElement *le, PRBool restart)
  281. {
  282. PK11SlotListElement *new_le;
  283. PZ_Lock(list->lock);
  284. new_le = le->next;
  285. if (le->next == NULL) {
  286. /* if the prev and next fields are NULL then either this element
  287. * has been removed and we need to walk the list again (if restart
  288. * is true) or this was the only element on the list */
  289. if ((le->prev == NULL) && restart && (list->head != le)) {
  290. new_le = list->head;
  291. }
  292. }
  293. if (new_le) new_le->refCount++;
  294. PZ_Unlock(list->lock);
  295. PK11_FreeSlotListElement(list,le);
  296. return new_le;
  297. }
  298. /*
  299. * Find the element that holds this slot
  300. */
  301. PK11SlotListElement *
  302. PK11_FindSlotElement(PK11SlotList *list,PK11SlotInfo *slot)
  303. {
  304. PK11SlotListElement *le;
  305. for (le = PK11_GetFirstSafe(list); le;
  306. le = PK11_GetNextSafe(list,le,PR_TRUE)) {
  307. if (le->slot == slot) return le;
  308. }
  309. return NULL;
  310. }
  311. /************************************************************
  312. * Generic Slot Utilities
  313. ************************************************************/
  314. /*
  315. * Create a new slot structure
  316. */
  317. PK11SlotInfo *
  318. PK11_NewSlotInfo(SECMODModule *mod)
  319. {
  320. PK11SlotInfo *slot;
  321. slot = (PK11SlotInfo *)PORT_Alloc(sizeof(PK11SlotInfo));
  322. if (slot == NULL) return slot;
  323. slot->sessionLock = mod->isThreadSafe ?
  324. PZ_NewLock(nssILockSession) : mod->refLock;
  325. if (slot->sessionLock == NULL) {
  326. PORT_Free(slot);
  327. return NULL;
  328. }
  329. slot->freeListLock = PZ_NewLock(nssILockFreelist);
  330. if (slot->freeListLock == NULL) {
  331. if (mod->isThreadSafe) {
  332. PZ_DestroyLock(slot->sessionLock);
  333. }
  334. PORT_Free(slot);
  335. return NULL;
  336. }
  337. slot->freeSymKeysWithSessionHead = NULL;
  338. slot->freeSymKeysHead = NULL;
  339. slot->keyCount = 0;
  340. slot->maxKeyCount = 0;
  341. slot->functionList = NULL;
  342. slot->needTest = PR_TRUE;
  343. slot->isPerm = PR_FALSE;
  344. slot->isHW = PR_FALSE;
  345. slot->isInternal = PR_FALSE;
  346. slot->isThreadSafe = PR_FALSE;
  347. slot->disabled = PR_FALSE;
  348. slot->series = 1;
  349. slot->wrapKey = 0;
  350. slot->wrapMechanism = CKM_INVALID_MECHANISM;
  351. slot->refKeys[0] = CK_INVALID_HANDLE;
  352. slot->reason = PK11_DIS_NONE;
  353. slot->readOnly = PR_TRUE;
  354. slot->needLogin = PR_FALSE;
  355. slot->hasRandom = PR_FALSE;
  356. slot->defRWSession = PR_FALSE;
  357. slot->protectedAuthPath = PR_FALSE;
  358. slot->flags = 0;
  359. slot->session = CK_INVALID_SESSION;
  360. slot->slotID = 0;
  361. slot->defaultFlags = 0;
  362. slot->refCount = 1;
  363. slot->askpw = 0;
  364. slot->timeout = 0;
  365. slot->mechanismList = NULL;
  366. slot->mechanismCount = 0;
  367. slot->cert_array = NULL;
  368. slot->cert_count = 0;
  369. slot->slot_name[0] = 0;
  370. slot->token_name[0] = 0;
  371. PORT_Memset(slot->serial,' ',sizeof(slot->serial));
  372. slot->module = NULL;
  373. slot->authTransact = 0;
  374. slot->authTime = LL_ZERO;
  375. slot->minPassword = 0;
  376. slot->maxPassword = 0;
  377. slot->hasRootCerts = PR_FALSE;
  378. slot->nssToken = NULL;
  379. return slot;
  380. }
  381. /* create a new reference to a slot so it doesn't go away */
  382. PK11SlotInfo *
  383. PK11_ReferenceSlot(PK11SlotInfo *slot)
  384. {
  385. PR_AtomicIncrement(&slot->refCount);
  386. return slot;
  387. }
  388. /* Destroy all info on a slot we have built up */
  389. void
  390. PK11_DestroySlot(PK11SlotInfo *slot)
  391. {
  392. /* free up the cached keys and sessions */
  393. PK11_CleanKeyList(slot);
  394. /* free up all the sessions on this slot */
  395. if (slot->functionList) {
  396. PK11_GETTAB(slot)->C_CloseAllSessions(slot->slotID);
  397. }
  398. if (slot->mechanismList) {
  399. PORT_Free(slot->mechanismList);
  400. }
  401. if (slot->isThreadSafe && slot->sessionLock) {
  402. PZ_DestroyLock(slot->sessionLock);
  403. }
  404. slot->sessionLock = NULL;
  405. if (slot->freeListLock) {
  406. PZ_DestroyLock(slot->freeListLock);
  407. slot->freeListLock = NULL;
  408. }
  409. /* finally Tell our parent module that we've gone away so it can unload */
  410. if (slot->module) {
  411. SECMOD_SlotDestroyModule(slot->module,PR_TRUE);
  412. }
  413. /* ok, well not quit finally... now we free the memory */
  414. PORT_Free(slot);
  415. }
  416. /* We're all done with the slot, free it */
  417. void
  418. PK11_FreeSlot(PK11SlotInfo *slot)
  419. {
  420. if (PR_AtomicDecrement(&slot->refCount) == 0) {
  421. PK11_DestroySlot(slot);
  422. }
  423. }
  424. void
  425. PK11_EnterSlotMonitor(PK11SlotInfo *slot) {
  426. PZ_Lock(slot->sessionLock);
  427. }
  428. void
  429. PK11_ExitSlotMonitor(PK11SlotInfo *slot) {
  430. PZ_Unlock(slot->sessionLock);
  431. }
  432. /***********************************************************
  433. * Functions to find specific slots.
  434. ***********************************************************/
  435. PRBool
  436. SECMOD_HasRootCerts(void)
  437. {
  438. SECMODModuleList *mlp;
  439. SECMODModuleList *modules = SECMOD_GetDefaultModuleList();
  440. SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
  441. int i;
  442. PRBool found = PR_FALSE;
  443. /* work through all the slots */
  444. SECMOD_GetReadLock(moduleLock);
  445. for(mlp = modules; mlp != NULL; mlp = mlp->next) {
  446. for (i=0; i < mlp->module->slotCount; i++) {
  447. PK11SlotInfo *tmpSlot = mlp->module->slots[i];
  448. if (PK11_IsPresent(tmpSlot)) {
  449. if (tmpSlot->hasRootCerts) {
  450. found = PR_TRUE;
  451. break;
  452. }
  453. }
  454. }
  455. if (found) break;
  456. }
  457. SECMOD_ReleaseReadLock(moduleLock);
  458. return found;
  459. }
  460. /***********************************************************
  461. * Functions to find specific slots.
  462. ***********************************************************/
  463. PK11SlotList *
  464. PK11_FindSlotsByNames(const char *dllName, const char* slotName,
  465. const char* tokenName, PRBool presentOnly)
  466. {
  467. SECMODModuleList *mlp;
  468. SECMODModuleList *modules = SECMOD_GetDefaultModuleList();
  469. SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
  470. int i;
  471. PK11SlotList* slotList = NULL;
  472. PRUint32 slotcount = 0;
  473. SECStatus rv = SECSuccess;
  474. slotList = PK11_NewSlotList();
  475. if (!slotList) {
  476. PORT_SetError(SEC_ERROR_NO_MEMORY);
  477. return NULL;
  478. }
  479. if ( ((NULL == dllName) || (0 == *dllName)) &&
  480. ((NULL == slotName) || (0 == *slotName)) &&
  481. ((NULL == tokenName) || (0 == *tokenName)) ) {
  482. /* default to softoken */
  483. PK11_AddSlotToList(slotList, PK11_GetInternalKeySlot());
  484. return slotList;
  485. }
  486. /* work through all the slots */
  487. SECMOD_GetReadLock(moduleLock);
  488. for (mlp = modules; mlp != NULL; mlp = mlp->next) {
  489. PORT_Assert(mlp->module);
  490. if (!mlp->module) {
  491. rv = SECFailure;
  492. break;
  493. }
  494. if ((!dllName) || (mlp->module->dllName &&
  495. (0 == PORT_Strcmp(mlp->module->dllName, dllName)))) {
  496. for (i=0; i < mlp->module->slotCount; i++) {
  497. PK11SlotInfo *tmpSlot = (mlp->module->slots?mlp->module->slots[i]:NULL);
  498. PORT_Assert(tmpSlot);
  499. if (!tmpSlot) {
  500. rv = SECFailure;
  501. break;
  502. }
  503. if ((PR_FALSE == presentOnly || PK11_IsPresent(tmpSlot)) &&
  504. ( (!tokenName) || (tmpSlot->token_name &&
  505. (0==PORT_Strcmp(tmpSlot->token_name, tokenName)))) &&
  506. ( (!slotName) || (tmpSlot->slot_name &&
  507. (0==PORT_Strcmp(tmpSlot->slot_name, slotName)))) ) {
  508. if (tmpSlot) {
  509. PK11_AddSlotToList(slotList, tmpSlot);
  510. slotcount++;
  511. }
  512. }
  513. }
  514. }
  515. }
  516. SECMOD_ReleaseReadLock(moduleLock);
  517. if ( (0 == slotcount) || (SECFailure == rv) ) {
  518. PORT_SetError(SEC_ERROR_NO_TOKEN);
  519. PK11_FreeSlotList(slotList);
  520. slotList = NULL;
  521. }
  522. if (SECFailure == rv) {
  523. PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
  524. }
  525. return slotList;
  526. }
  527. PK11SlotInfo *
  528. PK11_FindSlotByName(const char *name)
  529. {
  530. SECMODModuleList *mlp;
  531. SECMODModuleList *modules = SECMOD_GetDefaultModuleList();
  532. SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
  533. int i;
  534. PK11SlotInfo *slot = NULL;
  535. if ((name == NULL) || (*name == 0)) {
  536. return PK11_GetInternalKeySlot();
  537. }
  538. /* work through all the slots */
  539. SECMOD_GetReadLock(moduleLock);
  540. for(mlp = modules; mlp != NULL; mlp = mlp->next) {
  541. for (i=0; i < mlp->module->slotCount; i++) {
  542. PK11SlotInfo *tmpSlot = mlp->module->slots[i];
  543. if (PK11_IsPresent(tmpSlot)) {
  544. if (PORT_Strcmp(tmpSlot->token_name,name) == 0) {
  545. slot = PK11_ReferenceSlot(tmpSlot);
  546. break;
  547. }
  548. }
  549. }
  550. if (slot != NULL) break;
  551. }
  552. SECMOD_ReleaseReadLock(moduleLock);
  553. if (slot == NULL) {
  554. PORT_SetError(SEC_ERROR_NO_TOKEN);
  555. }
  556. return slot;
  557. }
  558. PK11SlotInfo *
  559. PK11_FindSlotBySerial(char *serial)
  560. {
  561. SECMODModuleList *mlp;
  562. SECMODModuleList *modules = SECMOD_GetDefaultModuleList();
  563. SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
  564. int i;
  565. PK11SlotInfo *slot = NULL;
  566. /* work through all the slots */
  567. SECMOD_GetReadLock(moduleLock);
  568. for(mlp = modules; mlp != NULL; mlp = mlp->next) {
  569. for (i=0; i < mlp->module->slotCount; i++) {
  570. PK11SlotInfo *tmpSlot = mlp->module->slots[i];
  571. if (PK11_IsPresent(tmpSlot)) {
  572. if (PORT_Memcmp(tmpSlot->serial,serial,
  573. sizeof(tmpSlot->serial)) == 0) {
  574. slot = PK11_ReferenceSlot(tmpSlot);
  575. break;
  576. }
  577. }
  578. }
  579. if (slot != NULL) break;
  580. }
  581. SECMOD_ReleaseReadLock(moduleLock);
  582. if (slot == NULL) {
  583. PORT_SetError(SEC_ERROR_NO_TOKEN);
  584. }
  585. return slot;
  586. }
  587. /*
  588. * notification stub. If we ever get interested in any events that
  589. * the pkcs11 functions may pass back to use, we can catch them here...
  590. * currently pdata is a slotinfo structure.
  591. */
  592. CK_RV pk11_notify(CK_SESSION_HANDLE session, CK_NOTIFICATION event,
  593. CK_VOID_PTR pdata)
  594. {
  595. return CKR_OK;
  596. }
  597. /*
  598. * grab a new RW session
  599. * !!! has a side effect of grabbing the Monitor if either the slot's default
  600. * session is RW or the slot is not thread safe. Monitor is release in function
  601. * below
  602. */
  603. CK_SESSION_HANDLE PK11_GetRWSession(PK11SlotInfo *slot)
  604. {
  605. CK_SESSION_HANDLE rwsession;
  606. CK_RV crv;
  607. PRBool haveMonitor = PR_FALSE;
  608. if (!slot->isThreadSafe || slot->defRWSession) {
  609. PK11_EnterSlotMonitor(slot);
  610. haveMonitor = PR_TRUE;
  611. }
  612. if (slot->defRWSession) {
  613. PORT_Assert(slot->session != CK_INVALID_SESSION);
  614. if (slot->session != CK_INVALID_SESSION)
  615. return slot->session;
  616. }
  617. crv = PK11_GETTAB(slot)->C_OpenSession(slot->slotID,
  618. CKF_RW_SESSION|CKF_SERIAL_SESSION,
  619. slot, pk11_notify,&rwsession);
  620. PORT_Assert(rwsession != CK_INVALID_SESSION || crv != CKR_OK);
  621. if (crv != CKR_OK || rwsession == CK_INVALID_SESSION) {
  622. if (crv == CKR_OK)
  623. crv = CKR_DEVICE_ERROR;
  624. if (haveMonitor)
  625. PK11_ExitSlotMonitor(slot);
  626. PORT_SetError(PK11_MapError(crv));
  627. return CK_INVALID_SESSION;
  628. }
  629. if (slot->defRWSession) { /* we have the monitor */
  630. slot->session = rwsession;
  631. }
  632. return rwsession;
  633. }
  634. PRBool
  635. PK11_RWSessionHasLock(PK11SlotInfo *slot,CK_SESSION_HANDLE session_handle)
  636. {
  637. PRBool hasLock;
  638. hasLock = (PRBool)(!slot->isThreadSafe ||
  639. (slot->defRWSession && slot->session != CK_INVALID_SESSION));
  640. return hasLock;
  641. }
  642. static PRBool
  643. pk11_RWSessionIsDefault(PK11SlotInfo *slot,CK_SESSION_HANDLE rwsession)
  644. {
  645. PRBool isDefault;
  646. isDefault = (PRBool)(slot->session == rwsession &&
  647. slot->defRWSession &&
  648. slot->session != CK_INVALID_SESSION);
  649. return isDefault;
  650. }
  651. /*
  652. * close the rwsession and restore our readonly session
  653. * !!! has a side effect of releasing the Monitor if either the slot's default
  654. * session is RW or the slot is not thread safe.
  655. */
  656. void
  657. PK11_RestoreROSession(PK11SlotInfo *slot,CK_SESSION_HANDLE rwsession)
  658. {
  659. PORT_Assert(rwsession != CK_INVALID_SESSION);
  660. if (rwsession != CK_INVALID_SESSION) {
  661. PRBool doExit = PK11_RWSessionHasLock(slot, rwsession);
  662. if (!pk11_RWSessionIsDefault(slot, rwsession))
  663. PK11_GETTAB(slot)->C_CloseSession(rwsession);
  664. if (doExit)
  665. PK11_ExitSlotMonitor(slot);
  666. }
  667. }
  668. /************************************************************
  669. * Manage the built-In Slot Lists
  670. ************************************************************/
  671. /* Init the static built int slot list (should actually integrate
  672. * with PK11_NewSlotList */
  673. static void
  674. pk11_InitSlotListStatic(PK11SlotList *list)
  675. {
  676. list->lock = PZ_NewLock(nssILockList);
  677. list->head = NULL;
  678. }
  679. /* initialize the system slotlists */
  680. SECStatus
  681. PK11_InitSlotLists(void)
  682. {
  683. pk11_InitSlotListStatic(&pk11_seedSlotList);
  684. pk11_InitSlotListStatic(&pk11_camelliaSlotList);
  685. pk11_InitSlotListStatic(&pk11_aesSlotList);
  686. pk11_InitSlotListStatic(&pk11_desSlotList);
  687. pk11_InitSlotListStatic(&pk11_rc4SlotList);
  688. pk11_InitSlotListStatic(&pk11_rc2SlotList);
  689. pk11_InitSlotListStatic(&pk11_rc5SlotList);
  690. pk11_InitSlotListStatic(&pk11_md5SlotList);
  691. pk11_InitSlotListStatic(&pk11_md2SlotList);
  692. pk11_InitSlotListStatic(&pk11_sha1SlotList);
  693. pk11_InitSlotListStatic(&pk11_rsaSlotList);
  694. pk11_InitSlotListStatic(&pk11_dsaSlotList);
  695. pk11_InitSlotListStatic(&pk11_dhSlotList);
  696. pk11_InitSlotListStatic(&pk11_ecSlotList);
  697. pk11_InitSlotListStatic(&pk11_ideaSlotList);
  698. pk11_InitSlotListStatic(&pk11_sslSlotList);
  699. pk11_InitSlotListStatic(&pk11_tlsSlotList);
  700. pk11_InitSlotListStatic(&pk11_randomSlotList);
  701. pk11_InitSlotListStatic(&pk11_sha256SlotList);
  702. pk11_InitSlotListStatic(&pk11_sha512SlotList);
  703. return SECSuccess;
  704. }
  705. void
  706. PK11_DestroySlotLists(void)
  707. {
  708. pk11_FreeSlotListStatic(&pk11_seedSlotList);
  709. pk11_FreeSlotListStatic(&pk11_camelliaSlotList);
  710. pk11_FreeSlotListStatic(&pk11_aesSlotList);
  711. pk11_FreeSlotListStatic(&pk11_desSlotList);
  712. pk11_FreeSlotListStatic(&pk11_rc4SlotList);
  713. pk11_FreeSlotListStatic(&pk11_rc2SlotList);
  714. pk11_FreeSlotListStatic(&pk11_rc5SlotList);
  715. pk11_FreeSlotListStatic(&pk11_md5SlotList);
  716. pk11_FreeSlotListStatic(&pk11_md2SlotList);
  717. pk11_FreeSlotListStatic(&pk11_sha1SlotList);
  718. pk11_FreeSlotListStatic(&pk11_rsaSlotList);
  719. pk11_FreeSlotListStatic(&pk11_dsaSlotList);
  720. pk11_FreeSlotListStatic(&pk11_dhSlotList);
  721. pk11_FreeSlotListStatic(&pk11_ecSlotList);
  722. pk11_FreeSlotListStatic(&pk11_ideaSlotList);
  723. pk11_FreeSlotListStatic(&pk11_sslSlotList);
  724. pk11_FreeSlotListStatic(&pk11_tlsSlotList);
  725. pk11_FreeSlotListStatic(&pk11_randomSlotList);
  726. pk11_FreeSlotListStatic(&pk11_sha256SlotList);
  727. pk11_FreeSlotListStatic(&pk11_sha512SlotList);
  728. return;
  729. }
  730. /* return a system slot list based on mechanism */
  731. PK11SlotList *
  732. PK11_GetSlotList(CK_MECHANISM_TYPE type)
  733. {
  734. /* XXX a workaround for Bugzilla bug #55267 */
  735. #if defined(HPUX) && defined(__LP64__)
  736. if (CKM_INVALID_MECHANISM == type)
  737. return NULL;
  738. #endif
  739. switch (type) {
  740. case CKM_SEED_CBC:
  741. case CKM_SEED_ECB:
  742. return &pk11_seedSlotList;
  743. case CKM_CAMELLIA_CBC:
  744. case CKM_CAMELLIA_ECB:
  745. return &pk11_camelliaSlotList;
  746. case CKM_AES_CBC:
  747. case CKM_AES_ECB:
  748. return &pk11_aesSlotList;
  749. case CKM_DES_CBC:
  750. case CKM_DES_ECB:
  751. case CKM_DES3_ECB:
  752. case CKM_DES3_CBC:
  753. return &pk11_desSlotList;
  754. case CKM_RC4:
  755. return &pk11_rc4SlotList;
  756. case CKM_RC5_CBC:
  757. return &pk11_rc5SlotList;
  758. case CKM_SHA_1:
  759. return &pk11_sha1SlotList;
  760. case CKM_SHA256:
  761. return &pk11_sha256SlotList;
  762. case CKM_SHA384:
  763. case CKM_SHA512:
  764. return &pk11_sha512SlotList;
  765. case CKM_MD5:
  766. return &pk11_md5SlotList;
  767. case CKM_MD2:
  768. return &pk11_md2SlotList;
  769. case CKM_RC2_ECB:
  770. case CKM_RC2_CBC:
  771. return &pk11_rc2SlotList;
  772. case CKM_RSA_PKCS:
  773. case CKM_RSA_PKCS_KEY_PAIR_GEN:
  774. case CKM_RSA_X_509:
  775. return &pk11_rsaSlotList;
  776. case CKM_DSA:
  777. return &pk11_dsaSlotList;
  778. case CKM_DH_PKCS_KEY_PAIR_GEN:
  779. case CKM_DH_PKCS_DERIVE:
  780. return &pk11_dhSlotList;
  781. case CKM_ECDSA:
  782. case CKM_ECDSA_SHA1:
  783. case CKM_EC_KEY_PAIR_GEN: /* aka CKM_ECDSA_KEY_PAIR_GEN */
  784. case CKM_ECDH1_DERIVE:
  785. return &pk11_ecSlotList;
  786. case CKM_SSL3_PRE_MASTER_KEY_GEN:
  787. case CKM_SSL3_MASTER_KEY_DERIVE:
  788. case CKM_SSL3_SHA1_MAC:
  789. case CKM_SSL3_MD5_MAC:
  790. return &pk11_sslSlotList;
  791. case CKM_TLS_MASTER_KEY_DERIVE:
  792. case CKM_TLS_KEY_AND_MAC_DERIVE:
  793. return &pk11_tlsSlotList;
  794. case CKM_IDEA_CBC:
  795. case CKM_IDEA_ECB:
  796. return &pk11_ideaSlotList;
  797. case CKM_FAKE_RANDOM:
  798. return &pk11_randomSlotList;
  799. }
  800. return NULL;
  801. }
  802. /*
  803. * load the static SlotInfo structures used to select a PKCS11 slot.
  804. * preSlotInfo has a list of all the default flags for the slots on this
  805. * module.
  806. */
  807. void
  808. PK11_LoadSlotList(PK11SlotInfo *slot, PK11PreSlotInfo *psi, int count)
  809. {
  810. int i;
  811. for (i=0; i < count; i++) {
  812. if (psi[i].slotID == slot->slotID)
  813. break;
  814. }
  815. if (i == count) return;
  816. slot->defaultFlags = psi[i].defaultFlags;
  817. slot->askpw = psi[i].askpw;
  818. slot->timeout = psi[i].timeout;
  819. slot->hasRootCerts = psi[i].hasRootCerts;
  820. /* if the slot is already disabled, don't load them into the
  821. * default slot lists. We get here so we can save the default
  822. * list value. */
  823. if (slot->disabled) return;
  824. /* if the user has disabled us, don't load us in */
  825. if (slot->defaultFlags & PK11_DISABLE_FLAG) {
  826. slot->disabled = PR_TRUE;
  827. slot->reason = PK11_DIS_USER_SELECTED;
  828. /* free up sessions and things?? */
  829. return;
  830. }
  831. for (i=0; i < num_pk11_default_mechanisms; i++) {
  832. if (slot->defaultFlags & PK11_DefaultArray[i].flag) {
  833. CK_MECHANISM_TYPE mechanism = PK11_DefaultArray[i].mechanism;
  834. PK11SlotList *slotList = PK11_GetSlotList(mechanism);
  835. if (slotList) PK11_AddSlotToList(slotList,slot);
  836. }
  837. }
  838. return;
  839. }
  840. /*
  841. * update a slot to its new attribute according to the slot list
  842. * returns: SECSuccess if nothing to do or add/delete is successful
  843. */
  844. SECStatus
  845. PK11_UpdateSlotAttribute(PK11SlotInfo *slot, PK11DefaultArrayEntry *entry,
  846. PRBool add)
  847. /* add: PR_TRUE if want to turn on */
  848. {
  849. SECStatus result = SECSuccess;
  850. PK11SlotList *slotList = PK11_GetSlotList(entry->mechanism);
  851. if (add) { /* trying to turn on a mechanism */
  852. /* turn on the default flag in the slot */
  853. slot->defaultFlags |= entry->flag;
  854. /* add this slot to the list */
  855. if (slotList!=NULL)
  856. result = PK11_AddSlotToList(slotList, slot);
  857. } else { /* trying to turn off */
  858. /* turn OFF the flag in the slot */
  859. slot->defaultFlags &= ~entry->flag;
  860. if (slotList) {
  861. /* find the element in the list & delete it */
  862. PK11SlotListElement *le = PK11_FindSlotElement(slotList, slot);
  863. /* remove the slot from the list */
  864. if (le)
  865. result = PK11_DeleteSlotFromList(slotList, le);
  866. }
  867. }
  868. return result;
  869. }
  870. /*
  871. * clear a slot off of all of it's default list
  872. */
  873. void
  874. PK11_ClearSlotList(PK11SlotInfo *slot)
  875. {
  876. int i;
  877. if (slot->disabled) return;
  878. if (slot->defaultFlags == 0) return;
  879. for (i=0; i < num_pk11_default_mechanisms; i++) {
  880. if (slot->defaultFlags & PK11_DefaultArray[i].flag) {
  881. CK_MECHANISM_TYPE mechanism = PK11_DefaultArray[i].mechanism;
  882. PK11SlotList *slotList = PK11_GetSlotList(mechanism);
  883. PK11SlotListElement *le = NULL;
  884. if (slotList) le = PK11_FindSlotElement(slotList,slot);
  885. if (le) {
  886. PK11_DeleteSlotFromList(slotList,le);
  887. PK11_FreeSlotListElement(slotList,le);
  888. }
  889. }
  890. }
  891. }
  892. /******************************************************************
  893. * Slot initialization
  894. ******************************************************************/
  895. /*
  896. * turn a PKCS11 Static Label into a string
  897. */
  898. char *
  899. PK11_MakeString(PRArenaPool *arena,char *space,
  900. char *staticString,int stringLen)
  901. {
  902. int i;
  903. char *newString;
  904. for(i=(stringLen-1); i >= 0; i--) {
  905. if (staticString[i] != ' ') break;
  906. }
  907. /* move i to point to the last space */
  908. i++;
  909. if (arena) {
  910. newString = (char*)PORT_ArenaAlloc(arena,i+1 /* space for NULL */);
  911. } else if (space) {
  912. newString = space;
  913. } else {
  914. newString = (char*)PORT_Alloc(i+1 /* space for NULL */);
  915. }
  916. if (newString == NULL) return NULL;
  917. if (i) PORT_Memcpy(newString,staticString, i);
  918. newString[i] = 0;
  919. return newString;
  920. }
  921. /*
  922. * Reads in the slots mechanism list for later use
  923. */
  924. SECStatus
  925. PK11_ReadMechanismList(PK11SlotInfo *slot)
  926. {
  927. CK_ULONG count;
  928. CK_RV crv;
  929. PRUint32 i;
  930. if (slot->mechanismList) {
  931. PORT_Free(slot->mechanismList);
  932. slot->mechanismList = NULL;
  933. }
  934. slot->mechanismCount = 0;
  935. if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
  936. crv = PK11_GETTAB(slot)->C_GetMechanismList(slot->slotID,NULL,&count);
  937. if (crv != CKR_OK) {
  938. if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
  939. PORT_SetError(PK11_MapError(crv));
  940. return SECFailure;
  941. }
  942. slot->mechanismList = (CK_MECHANISM_TYPE *)
  943. PORT_Alloc(count *sizeof(CK_MECHANISM_TYPE));
  944. if (slot->mechanismList == NULL) {
  945. if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
  946. return SECFailure;
  947. }
  948. crv = PK11_GETTAB(slot)->C_GetMechanismList(slot->slotID,
  949. slot->mechanismList, &count);
  950. if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
  951. if (crv != CKR_OK) {
  952. PORT_Free(slot->mechanismList);
  953. slot->mechanismList = NULL;
  954. PORT_SetError(PK11_MapError(crv));
  955. return SECSuccess;
  956. }
  957. slot->mechanismCount = count;
  958. PORT_Memset(slot->mechanismBits, 0, sizeof(slot->mechanismBits));
  959. for (i=0; i < count; i++) {
  960. CK_MECHANISM_TYPE mech = slot->mechanismList[i];
  961. if (mech < 0x7ff) {
  962. slot->mechanismBits[mech & 0xff] |= 1 << (mech >> 8);
  963. }
  964. }
  965. return SECSuccess;
  966. }
  967. /*
  968. * initialize a new token
  969. * unlike initialize slot, this can be called multiple times in the lifetime
  970. * of NSS. It reads the information associated with a card or token,
  971. * that is not going to change unless the card or token changes.
  972. */
  973. SECStatus
  974. PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts)
  975. {
  976. CK_TOKEN_INFO tokenInfo;
  977. CK_RV crv;
  978. char *tmp;
  979. SECStatus rv;
  980. PRStatus status;
  981. /* set the slot flags to the current token values */
  982. if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
  983. crv = PK11_GETTAB(slot)->C_GetTokenInfo(slot->slotID,&tokenInfo);
  984. if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
  985. if (crv != CKR_OK) {
  986. PORT_SetError(PK11_MapError(crv));
  987. return SECFailure;
  988. }
  989. /* set the slot flags to the current token values */
  990. slot->series++; /* allow other objects to detect that the
  991. * slot is different */
  992. slot->flags = tokenInfo.flags;
  993. slot->needLogin = ((tokenInfo.flags & CKF_LOGIN_REQUIRED) ?
  994. PR_TRUE : PR_FALSE);
  995. slot->readOnly = ((tokenInfo.flags & CKF_WRITE_PROTECTED) ?
  996. PR_TRUE : PR_FALSE);
  997. slot->hasRandom = ((tokenInfo.flags & CKF_RNG) ? PR_TRUE : PR_FALSE);
  998. slot->protectedAuthPath =
  999. ((tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
  1000. ? PR_TRUE : PR_FALSE);
  1001. slot->lastLoginCheck = 0;
  1002. slot->lastState = 0;
  1003. /* on some platforms Active Card incorrectly sets the
  1004. * CKF_PROTECTED_AUTHENTICATION_PATH bit when it doesn't mean to. */
  1005. if (slot->isActiveCard) {
  1006. slot->protectedAuthPath = PR_FALSE;
  1007. }
  1008. tmp = PK11_MakeString(NULL,slot->token_name,
  1009. (char *)tokenInfo.label, sizeof(tokenInfo.label));
  1010. slot->minPassword = tokenInfo.ulMinPinLen;
  1011. slot->maxPassword = tokenInfo.ulMaxPinLen;
  1012. PORT_Memcpy(slot->serial,tokenInfo.serialNumber,sizeof(slot->serial));
  1013. nssToken_UpdateName(slot->nssToken);
  1014. slot->defRWSession = (PRBool)((!slot->readOnly) &&
  1015. (tokenInfo.ulMaxSessionCount == 1));
  1016. rv = PK11_ReadMechanismList(slot);
  1017. if (rv != SECSuccess) return rv;
  1018. slot->hasRSAInfo = PR_FALSE;
  1019. slot->RSAInfoFlags = 0;
  1020. /* initialize the maxKeyCount value */
  1021. if (tokenInfo.ulMaxSessionCount == 0) {
  1022. slot->maxKeyCount = 800; /* should be #define or a config param */
  1023. } else if (tokenInfo.ulMaxSessionCount < 20) {
  1024. /* don't have enough sessions to keep that many keys around */
  1025. slot->maxKeyCount = 0;
  1026. } else {
  1027. slot->maxKeyCount = tokenInfo.ulMaxSessionCount/2;
  1028. }
  1029. /* Make sure our session handle is valid */
  1030. if (slot->session == CK_INVALID_SESSION) {
  1031. /* we know we don't have a valid session, go get one */
  1032. CK_SESSION_HANDLE session;
  1033. /* session should be Readonly, serial */
  1034. if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
  1035. crv = PK11_GETTAB(slot)->C_OpenSession(slot->slotID,
  1036. (slot->defRWSession ? CKF_RW_SESSION : 0) | CKF_SERIAL_SESSION,
  1037. slot,pk11_notify,&session);
  1038. if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
  1039. if (crv != CKR_OK) {
  1040. PORT_SetError(PK11_MapError(crv));
  1041. return SECFailure;
  1042. }
  1043. slot->session = session;
  1044. } else {
  1045. /* The session we have may be defunct (the token associated with it)
  1046. * has been removed */
  1047. CK_SESSION_INFO sessionInfo;
  1048. if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
  1049. crv = PK11_GETTAB(slot)->C_GetSessionInfo(slot->session,&sessionInfo);
  1050. if (crv == CKR_DEVICE_ERROR) {
  1051. PK11_GETTAB(slot)->C_CloseSession(slot->session);
  1052. crv = CKR_SESSION_CLOSED;
  1053. }
  1054. if ((crv==CKR_SESSION_CLOSED) || (crv==CKR_SESSION_HANDLE_INVALID)) {
  1055. crv =PK11_GETTAB(slot)->C_OpenSession(slot->slotID,
  1056. (slot->defRWSession ? CKF_RW_SESSION : 0) | CKF_SERIAL_SESSION,
  1057. slot,pk11_notify,&slot->session);
  1058. if (crv != CKR_OK) {
  1059. PORT_SetError(PK11_MapError(crv));
  1060. slot->session = CK_INVALID_SESSION;
  1061. if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
  1062. return SECFailure;
  1063. }
  1064. }
  1065. if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
  1066. }
  1067. status = nssToken_Refresh(slot->nssToken);
  1068. if (status != PR_SUCCESS)
  1069. return SECFailure;
  1070. if (!(slot->isInternal) && (slot->hasRandom)) {
  1071. /* if this slot has a random number generater, use it to add entropy
  1072. * to the internal slot. */
  1073. PK11SlotInfo *int_slot = PK11_GetInternalSlot();
  1074. if (int_slot) {
  1075. unsigned char random_bytes[32];
  1076. /* if this slot can issue random numbers, get some entropy from
  1077. * that random number generater and give it to our internal token.
  1078. */
  1079. PK11_EnterSlotMonitor(slot);
  1080. crv = PK11_GETTAB(slot)->C_GenerateRandom
  1081. (slot->session,random_bytes, sizeof(random_bytes));
  1082. PK11_ExitSlotMonitor(slot);
  1083. if (crv == CKR_OK) {
  1084. PK11_EnterSlotMonitor(int_slot);
  1085. PK11_GETTAB(int_slot)->C_SeedRandom(int_slot->session,
  1086. random_bytes, sizeof(random_bytes));
  1087. PK11_ExitSlotMonitor(int_slot);
  1088. }
  1089. /* Now return the favor and send entropy to the token's random
  1090. * number generater */
  1091. PK11_EnterSlotMonitor(int_slot);
  1092. crv = PK11_GETTAB(int_slot)->C_GenerateRandom(int_slot->session,
  1093. random_bytes, sizeof(random_bytes));
  1094. PK11_ExitSlotMonitor(int_slot);
  1095. if (crv == CKR_OK) {
  1096. PK11_EnterSlotMonitor(slot);
  1097. crv = PK11_GETTAB(slot)->C_SeedRandom(slot->session,
  1098. random_bytes, sizeof(random_bytes));
  1099. PK11_ExitSlotMonitor(slot);
  1100. }
  1101. PK11_FreeSlot(int_slot);
  1102. }
  1103. }
  1104. return SECSuccess;
  1105. }
  1106. /*
  1107. * initialize a new token
  1108. * unlike initialize slot, this can be called multiple times in the lifetime
  1109. * of NSS. It reads the information associated with a card or token,
  1110. * that is not going to change unless the card or token changes.
  1111. */
  1112. SECStatus
  1113. PK11_TokenRefresh(PK11SlotInfo *slot)
  1114. {
  1115. CK_TOKEN_INFO tokenInfo;
  1116. CK_RV crv;
  1117. /* set the slot flags to the current token values */
  1118. if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
  1119. crv = PK11_GETTAB(slot)->C_GetTokenInfo(slot->slotID,&tokenInfo);
  1120. if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
  1121. if (crv != CKR_OK) {
  1122. PORT_SetError(PK11_MapError(crv));
  1123. return SECFailure;
  1124. }
  1125. slot->flags = tokenInfo.flags;
  1126. slot->needLogin = ((tokenInfo.flags & CKF_LOGIN_REQUIRED) ?
  1127. PR_TRUE : PR_FALSE);
  1128. slot->readOnly = ((tokenInfo.flags & CKF_WRITE_PROTECTED) ?
  1129. PR_TRUE : PR_FALSE);
  1130. slot->hasRandom = ((tokenInfo.flags & CKF_RNG) ? PR_TRUE : PR_FALSE);
  1131. slot->protectedAuthPath =
  1132. ((tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
  1133. ? PR_TRUE : PR_FALSE);
  1134. /* on some platforms Active Card incorrectly sets the
  1135. * CKF_PROTECTED_AUTHENTICATION_PATH bit when it doesn't mean to. */
  1136. if (slot->isActiveCard) {
  1137. slot->protectedAuthPath = PR_FALSE;
  1138. }
  1139. return SECSuccess;
  1140. }
  1141. static PRBool
  1142. pk11_isRootSlot(PK11SlotInfo *slot)
  1143. {
  1144. CK_ATTRIBUTE findTemp[1];
  1145. CK_ATTRIBUTE *attrs;
  1146. CK_OBJECT_CLASS oclass = CKO_NETSCAPE_BUILTIN_ROOT_LIST;
  1147. int tsize;
  1148. CK_OBJECT_HANDLE handle;
  1149. attrs = findTemp;
  1150. PK11_SETATTRS(attrs, CKA_CLASS, &oclass, sizeof(oclass)); attrs++;
  1151. tsize = attrs - findTemp;
  1152. PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE));
  1153. handle = pk11_FindObjectByTemplate(slot,findTemp,tsize);
  1154. if (handle == CK_INVALID_HANDLE) {
  1155. return PR_FALSE;
  1156. }
  1157. return PR_TRUE;
  1158. }
  1159. /*
  1160. * Initialize the slot :
  1161. * This initialization code is called on each slot a module supports when
  1162. * it is loaded. It does the bringup initialization. The difference between
  1163. * this and InitToken is Init slot does those one time initialization stuff,
  1164. * usually associated with the reader, while InitToken may get called multiple
  1165. * times as tokens are removed and re-inserted.
  1166. */
  1167. void
  1168. PK11_InitSlot(SECMODModule *mod,CK_SLOT_ID slotID,PK11SlotInfo *slot)
  1169. {
  1170. SECStatus rv;
  1171. char *tmp;
  1172. CK_SLOT_INFO slotInfo;
  1173. slot->functionList = mod->functionList;
  1174. slot->isInternal = mod->internal;
  1175. slot->slotID = slotID;
  1176. slot->isThreadSafe = mod->isThreadSafe;
  1177. slot->hasRSAInfo = PR_FALSE;
  1178. if (PK11_GETTAB(slot)->C_GetSlotInfo(slotID,&slotInfo) != CKR_OK) {
  1179. slot->disabled = PR_TRUE;
  1180. slot->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
  1181. return;
  1182. }
  1183. /* test to make sure claimed mechanism work */
  1184. slot->needTest = mod->internal ? PR_FALSE : PR_TRUE;
  1185. slot->module = mod; /* NOTE: we don't make a reference here because
  1186. * modules have references to their slots. This
  1187. * works because modules keep implicit references
  1188. * from their slots, and won't unload and disappear
  1189. * until all their slots have been freed */
  1190. tmp = PK11_MakeString(NULL,slot->slot_name,
  1191. (char *)slotInfo.slotDescription, sizeof(slotInfo.slotDescription));
  1192. slot->isHW = (PRBool)((slotInfo.flags & CKF_HW_SLOT) == CKF_HW_SLOT);
  1193. #define ACTIVE_CARD "ActivCard SA"
  1194. slot->isActiveCard = (PRBool)(PORT_Strncmp((char *)slotInfo.manufacturerID,
  1195. ACTIVE_CARD, sizeof(ACTIVE_CARD)-1) == 0);
  1196. if ((slotInfo.flags & CKF_REMOVABLE_DEVICE) == 0) {
  1197. slot->isPerm = PR_TRUE;
  1198. /* permanment slots must have the token present always */
  1199. if ((slotInfo.flags & CKF_TOKEN_PRESENT) == 0) {
  1200. slot->disabled = PR_TRUE;
  1201. slot->reason = PK11_DIS_TOKEN_NOT_PRESENT;
  1202. return; /* nothing else to do */
  1203. }
  1204. }
  1205. /* if the token is present, initialize it */
  1206. if ((slotInfo.flags & CKF_TOKEN_PRESENT) != 0) {
  1207. rv = PK11_InitToken(slot,PR_TRUE);
  1208. /* the only hard failures are on permanent devices, or function
  1209. * verify failures... function verify failures are already handled
  1210. * by tokenInit */
  1211. if ((rv != SECSuccess) && (slot->isPerm) && (!slot->disabled)) {
  1212. slot->disabled = PR_TRUE;
  1213. slot->reason = PK11_DIS_COULD_NOT_INIT_TOKEN;
  1214. }
  1215. if (rv == SECSuccess && pk11_isRootSlot(slot)) {
  1216. if (!slot->hasRootCerts) {
  1217. slot->module->trustOrder = 100;
  1218. }
  1219. slot->hasRootCerts= PR_TRUE;
  1220. }
  1221. }
  1222. }
  1223. /*********************************************************************
  1224. * Slot mapping utility functions.
  1225. *********************************************************************/
  1226. /*
  1227. * determine if the token is present. If the token is present, make sure
  1228. * we have a valid session handle. Also set the value of needLogin
  1229. * appropriately.
  1230. */
  1231. static PRBool
  1232. pk11_IsPresentCertLoad(PK11SlotInfo *slot, PRBool loadCerts)
  1233. {
  1234. CK_SLOT_INFO slotInfo;
  1235. CK_SESSION_INFO sessionInfo;
  1236. CK_RV crv;
  1237. /* disabled slots are never present */
  1238. if (slot->disabled) {
  1239. return PR_FALSE;
  1240. }
  1241. /* permanent slots are always present */
  1242. if (slot->isPerm && (slot->session != CK_INVALID_SESSION)) {
  1243. return PR_TRUE;
  1244. }
  1245. if (slot->nssToken) {
  1246. return nssToken_IsPresent(slot->nssToken);
  1247. }
  1248. /* removable slots have a flag that says they are present */
  1249. if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
  1250. if (PK11_GETTAB(slot)->C_GetSlotInfo(slot->slotID,&slotInfo) != CKR_OK) {
  1251. if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
  1252. return PR_FALSE;
  1253. }
  1254. if ((slotInfo.flags & CKF_TOKEN_PRESENT) == 0) {
  1255. /* if the slot is no longer present, close the session */
  1256. if (slot->session != CK_INVALID_SESSION) {
  1257. PK11_GETTAB(slot)->C_CloseSession(slot->session);
  1258. slot->session = CK_INVALID_SESSION;
  1259. }
  1260. if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
  1261. return PR_FALSE;
  1262. }
  1263. /* use the session Info to determine if the card has been removed and then
  1264. * re-inserted */
  1265. if (slot->session != CK_INVALID_SESSION) {
  1266. if (slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
  1267. crv = PK11_GETTAB(slot)->C_GetSessionInfo(slot->session, &sessionInfo);
  1268. if (crv != CKR_OK) {
  1269. PK11_GETTAB(slot)->C_CloseSession(slot->session);
  1270. slot->session = CK_INVALID_SESSION;
  1271. }
  1272. if (slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
  1273. }
  1274. if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
  1275. /* card has not been removed, current token info is correct */
  1276. if (slot->session != CK_INVALID_SESSION) return PR_TRUE;
  1277. /* initialize the token info state */
  1278. if (PK11_InitToken(slot,loadCerts) != SECSuccess) {
  1279. return PR_FALSE;
  1280. }
  1281. return PR_TRUE;
  1282. }
  1283. /*
  1284. * old version of the routine
  1285. */
  1286. PRBool
  1287. PK11_IsPresent(PK11SlotInfo *slot) {
  1288. return pk11_IsPresentCertLoad(slot,PR_TRUE);
  1289. }
  1290. /* is the slot disabled? */
  1291. PRBool
  1292. PK11_IsDisabled(PK11SlotInfo *slot)
  1293. {
  1294. return slot->disabled;
  1295. }
  1296. /* and why? */
  1297. PK11DisableReasons
  1298. PK11_GetDisabledReason(PK11SlotInfo *slot)
  1299. {
  1300. return slot->reason;
  1301. }
  1302. /* returns PR_TRUE if successfully disable the slot */
  1303. /* returns PR_FALSE otherwise */
  1304. PRBool PK11_UserDisableSlot(PK11SlotInfo *slot) {
  1305. slot->defaultFlags |= PK11_DISABLE_FLAG;
  1306. slot->disabled = PR_TRUE;
  1307. slot->reason = PK11_DIS_USER_SELECTED;
  1308. return PR_TRUE;
  1309. }
  1310. PRBool PK11_UserEnableSlot(PK11SlotInfo *slot) {
  1311. slot->defaultFlags &= ~PK11_DISABLE_FLAG;
  1312. slot->disabled = PR_FALSE;
  1313. slot->reason = PK11_DIS_NONE;
  1314. return PR_TRUE;
  1315. }
  1316. PRBool PK11_HasRootCerts(PK11SlotInfo *slot) {
  1317. return slot->hasRootCerts;
  1318. }
  1319. /* Get the module this slot is attached to */
  1320. SECMODModule *
  1321. PK11_GetModule(PK11SlotInfo *slot)
  1322. {
  1323. return slot->module;
  1324. }
  1325. /* return the default flags of a slot */
  1326. unsigned long
  1327. PK11_GetDefaultFlags(PK11SlotInfo *slot)
  1328. {
  1329. return slot->defaultFlags;
  1330. }
  1331. /*
  1332. * The following wrapper functions allow us to export an opaque slot
  1333. * function to the rest of libsec and the world... */
  1334. PRBool
  1335. PK11_IsReadOnly(PK11SlotInfo *slot)
  1336. {
  1337. return slot->readOnly;
  1338. }
  1339. PRBool
  1340. PK11_IsHW(PK11SlotInfo *slot)
  1341. {
  1342. return slot->isHW;
  1343. }
  1344. PRBool
  1345. PK11_IsRemovable(PK11SlotInfo *slot)
  1346. {
  1347. return !slot->isPerm;
  1348. }
  1349. PRBool
  1350. PK11_IsInternal(PK11SlotInfo *slot)
  1351. {
  1352. return slot->isInternal;
  1353. }
  1354. PRBool
  1355. PK11_NeedLogin(PK11SlotInfo *slot)
  1356. {
  1357. return slot->needLogin;
  1358. }
  1359. PRBool
  1360. PK11_IsFriendly(PK11SlotInfo *slot)
  1361. {
  1362. /* internal slot always has public readable certs */
  1363. return (PRBool)(slot->isInternal ||
  1364. ((slot->defaultFlags & SECMOD_FRIENDLY_FLAG) ==
  1365. SECMOD_FRIENDLY_FLAG));
  1366. }
  1367. char *
  1368. PK11_GetTokenName(PK11SlotInfo *slot)
  1369. {
  1370. return slot->token_name;
  1371. }
  1372. char *
  1373. PK11_GetSlotName(PK11SlotInfo *slot)
  1374. {
  1375. return slot->slot_name;
  1376. }
  1377. int
  1378. PK11_GetSlotSeries(PK11SlotInfo *slot)
  1379. {
  1380. return slot->series;
  1381. }
  1382. int
  1383. PK11_GetCurrentWrapIndex(PK11SlotInfo *slot)
  1384. {
  1385. return slot->wrapKey;
  1386. }
  1387. CK_SLOT_ID
  1388. PK11_GetSlotID(PK11SlotInfo *slot)
  1389. {
  1390. return slot->slotID;
  1391. }
  1392. SECMODModuleID
  1393. PK11_GetModuleID(PK11SlotInfo *slot)
  1394. {
  1395. return slot->module->moduleID;
  1396. }
  1397. static void
  1398. pk11_zeroTerminatedToBlankPadded(CK_CHAR *buffer, size_t buffer_size)
  1399. {
  1400. CK_CHAR *walk = buffer;
  1401. CK_CHAR *end = buffer + buffer_size;
  1402. /* find the NULL */
  1403. while (walk < end && *walk != '\0') {
  1404. walk++;
  1405. }
  1406. /* clear out the buffer */
  1407. while (walk < end) {
  1408. *walk++ = ' ';
  1409. }
  1410. }
  1411. /* return the slot info structure */
  1412. SECStatus
  1413. PK11_GetSlotInfo(PK11SlotInfo *slot, CK_SLOT_INFO *info)
  1414. {
  1415. CK_RV crv;
  1416. if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
  1417. /*
  1418. * some buggy drivers do not fill the buffer completely,
  1419. * erase the buffer first
  1420. */
  1421. PORT_Memset(info->slotDescription,' ',sizeof(info->slotDescription));
  1422. PORT_Memset(info->manufacturerID,' ',sizeof(info->manufacturerID));
  1423. crv = PK11_GETTAB(slot)->C_GetSlotInfo(slot->slotID,info);
  1424. pk11_zeroTerminatedToBlankPadded(info->slotDescription,
  1425. sizeof(info->slotDescription));
  1426. pk11_zeroTerminatedToBlankPadded(info->manufacturerID,
  1427. sizeof(info->manufacturerID));
  1428. if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
  1429. if (crv != CKR_OK) {
  1430. PORT_SetError(PK11_MapError(crv));
  1431. return SECFailure;
  1432. }
  1433. return SECSuccess;
  1434. }
  1435. /* return the token info structure */
  1436. SECStatus
  1437. PK11_GetTokenInfo(PK11SlotInfo *slot, CK_TOKEN_INFO *info)
  1438. {
  1439. CK_RV crv;
  1440. if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
  1441. /*
  1442. * some buggy drivers do not fill the buffer completely,
  1443. * erase the buffer first
  1444. */
  1445. PORT_Memset(info->label,' ',sizeof(info->label));
  1446. PORT_Memset(info->manufacturerID,' ',sizeof(info->manufacturerID));
  1447. PORT_Memset(info->model,' ',sizeof(info->model));
  1448. PORT_Memset(info->serialNumber,' ',sizeof(info->serialNumber));
  1449. crv = PK11_GETTAB(slot)->C_GetTokenInfo(slot->slotID,info);
  1450. pk11_zeroTerminatedToBlankPadded(info->label,sizeof(info->label));
  1451. pk11_zeroTerminatedToBlankPadded(info->manufacturerID,
  1452. sizeof(info->manufacturerID));
  1453. pk11_zeroTerminatedToBlankPadded(info->model,sizeof(info->model));
  1454. pk11_zeroTerminatedToBlankPadded(info->serialNumber,
  1455. sizeof(info->serialNumber));
  1456. if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
  1457. if (crv != CKR_OK) {
  1458. PORT_SetError(PK11_MapError(crv));
  1459. return SECFailure;
  1460. }
  1461. return SECSuccess;
  1462. }
  1463. /* Find out if we need to initialize the user's pin */
  1464. PRBool
  1465. PK11_NeedUserInit(PK11SlotInfo *slot)
  1466. {
  1467. PRBool needUserInit = (PRBool) ((slot->flags & CKF_USER_PIN_INITIALIZED)
  1468. == 0);
  1469. if (needUserInit) {
  1470. CK_TOKEN_INFO info;
  1471. SECStatus rv;
  1472. /* see if token has been initialized off line */
  1473. rv = PK11_GetTokenInfo(slot, &info);
  1474. if (rv == SECSuccess) {
  1475. slot->flags = info.flags;
  1476. }
  1477. }
  1478. return (PRBool)((slot->flags & CKF_USER_PIN_INITIALIZED) == 0);
  1479. }
  1480. /* get the internal key slot. FIPS has only one slot for both key slots and
  1481. * default slots */
  1482. PK11SlotInfo *
  1483. PK11_GetInternalKeySlot(void)
  1484. {
  1485. SECMODModule *mod = SECMOD_GetInternalModule();
  1486. PORT_Assert(mod != NULL);
  1487. if (!mod) {
  1488. PORT_SetError( SEC_ERROR_NO_MODULE );
  1489. return NULL;
  1490. }
  1491. return PK11_ReferenceSlot(mod->isFIPS ? mod->slots[0] : mod->slots[1]);
  1492. }
  1493. /* get the internal default slot */
  1494. PK11SlotInfo *
  1495. PK11_GetInternalSlot(void)
  1496. {
  1497. SECMODModule * mod = SECMOD_GetInternalModule();
  1498. PORT_Assert(mod != NULL);
  1499. if (!mod) {
  1500. PORT_SetError( SEC_ERROR_NO_MODULE );
  1501. return NULL;
  1502. }
  1503. return PK11_ReferenceSlot(mod->slots[0]);
  1504. }
  1505. /*
  1506. * check if a given slot supports the requested mechanism
  1507. */
  1508. PRBool
  1509. PK11_DoesMechanism(PK11SlotInfo *slot, CK_MECHANISM_TYPE type)
  1510. {
  1511. int i;
  1512. /* CKM_FAKE_RANDOM is not a real PKCS mechanism. It's a marker to
  1513. * tell us we're looking form someone that has implemented get
  1514. * random bits */
  1515. if (type == CKM_FAKE_RANDOM) {
  1516. return slot->hasRandom;
  1517. }
  1518. /* for most mechanism, bypass the linear lookup */
  1519. if (type < 0x7ff) {
  1520. return (slot->mechanismBits[type & 0xff] & (1 << (type >> 8))) ?
  1521. PR_TRUE : PR_FALSE;
  1522. }
  1523. for (i=0; i < (int) slot->mechanismCount; i++) {
  1524. if (slot->mechanismList[i] == type) return PR_TRUE;
  1525. }
  1526. return PR_FALSE;
  1527. }
  1528. /*
  1529. * Return true if a token that can do the desired mechanism exists.
  1530. * This allows us to have hardware tokens that can do function XYZ magically
  1531. * allow SSL Ciphers to appear if they are plugged in.
  1532. */
  1533. PRBool
  1534. PK11_TokenExists(CK_MECHANISM_TYPE type)
  1535. {
  1536. SECMODModuleList *mlp;
  1537. SECMODModuleList *modules = SECMOD_GetDefaultModuleList();
  1538. SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
  1539. PK11SlotInfo *slot;
  1540. PRBool found = PR_FALSE;
  1541. int i;
  1542. /* we only need to know if there is a token that does this mechanism.
  1543. * check the internal module first because it's fast, and supports
  1544. * almost everything. */
  1545. slot = PK11_GetInternalSlot();
  1546. if (slot) {
  1547. found = PK11_DoesMechanism(slot,type);
  1548. PK11_FreeSlot(slot);
  1549. }
  1550. if (found) return PR_TRUE; /* bypass getting module locks */
  1551. SECMOD_GetReadLock(moduleLock);
  1552. for(mlp = modules; mlp != NULL && (!found); mlp = mlp->next) {
  1553. for (i=0; i < mlp->module->slotCount; i++) {
  1554. slot = mlp->module->slots[i];
  1555. if (PK11_IsPresent(slot)) {
  1556. if (PK11_DoesMechanism(slot,type)) {
  1557. found = PR_TRUE;
  1558. break;
  1559. }
  1560. }
  1561. }
  1562. }
  1563. SECMOD_ReleaseReadLock(moduleLock);
  1564. return found;
  1565. }
  1566. /*
  1567. * get all the currently available tokens in a list.
  1568. * that can perform the given mechanism. If mechanism is CKM_INVALID_MECHANISM,
  1569. * get all the tokens. Make sure tokens that need authentication are put at
  1570. * the end of this list.
  1571. */
  1572. PK11SlotList *
  1573. PK11_GetAllTokens(CK_MECHANISM_TYPE type, PRBool needRW, PRBool loadCerts,
  1574. void *wincx)
  1575. {
  1576. PK11SlotList * list = PK11_NewSlotList();
  1577. PK11SlotList * loginList = PK11_NewSlotList();
  1578. PK11SlotList * friendlyList = PK11_NewSlotList();
  1579. SECMODModuleList * mlp;
  1580. SECMODModuleList * modules = SECMOD_GetDefaultModuleList();
  1581. SECMODListLock * moduleLock = SECMOD_GetDefaultModuleListLock();
  1582. int i;
  1583. #if defined( XP_WIN32 )
  1584. int j = 0;
  1585. PRInt32 waste[16];
  1586. #endif
  1587. if ((list == NULL) || (loginList == NULL) || (friendlyList == NULL)) {
  1588. if (list) PK11_FreeSlotList(list);
  1589. if (loginList) PK11_FreeSlotList(loginList);
  1590. if (friendlyList) PK11_FreeSlotList(friendlyList);
  1591. return NULL;
  1592. }
  1593. SECMOD_GetReadLock(moduleLock);
  1594. for(mlp = modules; mlp != NULL; mlp = mlp->next) {
  1595. #if defined( XP_WIN32 )
  1596. /* This is works around some horrible cache/page thrashing problems
  1597. ** on Win32. Without this, this loop can take up to 6 seconds at
  1598. ** 100% CPU on a Pentium-Pro 200. The thing this changes is to
  1599. ** increase the size of the stack frame and modify it.
  1600. ** Moving the loop code itself seems to have no effect.
  1601. ** Dunno why this combination makes a difference, but it does.
  1602. */
  1603. waste[ j & 0xf] = j++;
  1604. #endif
  1605. for (i = 0; i < mlp->module->slotCount; i++) {
  1606. PK11SlotInfo *slot = mlp->module->slots[i];
  1607. if (pk11_IsPresentCertLoad(slot, loadCerts)) {
  1608. if (needRW && slot->readOnly) continue;
  1609. if ((type == CKM_INVALID_MECHANISM)
  1610. || PK11_DoesMechanism(slot, type)) {
  1611. if (pk11_LoginStillRequired(slot,wincx)) {
  1612. if (PK11_IsFriendly(slot)) {
  1613. PK11_AddSlotToList(friendlyList, slot);
  1614. } else {
  1615. PK11_AddSlotToList(loginList, slot);
  1616. }
  1617. } else {
  1618. PK11_AddSlotToList(list, slot);
  1619. }
  1620. }
  1621. }
  1622. }
  1623. }
  1624. SECMOD_ReleaseReadLock(moduleLock);
  1625. PK11_MoveListToList(list,friendlyList);
  1626. PK11_FreeSlotList(friendlyList);
  1627. PK11_MoveListToList(list,loginList);
  1628. PK11_FreeSlotList(loginList);
  1629. return list;
  1630. }
  1631. /*
  1632. * NOTE: This routine is working from a private List generated by
  1633. * PK11_GetAllTokens. That is why it does not need to lock.
  1634. */
  1635. PK11SlotList *
  1636. PK11_GetPrivateKeyTokens(CK_MECHANISM_TYPE type,PRBool needRW,void *wincx)
  1637. {
  1638. PK11SlotList *list = PK11_GetAllTokens(type,needRW,PR_TRUE,wincx);
  1639. PK11SlotListElement *le, *next ;
  1640. SECStatus rv;
  1641. if (list == NULL) return list;
  1642. for (le = list->head ; le; le = next) {
  1643. next = le->next; /* save the pointer here in case we have to
  1644. * free the element later */
  1645. rv = PK11_Authenticate(le->slot,PR_TRUE,wincx);
  1646. if (rv != SECSuccess) {
  1647. PK11_DeleteSlotFromList(list,le);
  1648. continue;
  1649. }
  1650. }
  1651. return list;
  1652. }
  1653. /*
  1654. * find the best slot which supports the given
  1655. * Mechanism. In normal cases this should grab the first slot on the list
  1656. * with no fuss.
  1657. */
  1658. PK11SlotInfo *
  1659. PK11_GetBestSlotMultiple(CK_MECHANISM_TYPE *type, int mech_count, void *wincx)
  1660. {
  1661. PK11SlotList *list = NULL;
  1662. PK11SlotListElement *le ;
  1663. PK11SlotInfo *slot = NULL;
  1664. PRBool freeit = PR_FALSE;
  1665. PRBool listNeedLogin = PR_FALSE;
  1666. int i;
  1667. SECStatus rv;
  1668. list = PK11_GetSlotList(type[0]);
  1669. if ((list == NULL) || (list->head == NULL)) {
  1670. /* We need to look up all the tokens for the mechanism */
  1671. list = PK11_GetAllTokens(type[0],PR_FALSE,PR_TRUE,wincx);
  1672. freeit = PR_TRUE;
  1673. }
  1674. /* no one can do it! */
  1675. if (list == NULL) {
  1676. PORT_SetError(SEC_ERROR_NO_TOKEN);
  1677. return NULL;
  1678. }
  1679. PORT_SetError(0);
  1680. listNeedLogin = PR_FALSE;
  1681. for (i=0; i < mech_count; i++) {
  1682. if ((type[i] != CKM_FAKE_RANDOM) &&
  1683. (type[i] != CKM_SHA_1) &&
  1684. (type[i] != CKM_SHA256) &&
  1685. (type[i] != CKM_SHA384) &&
  1686. (type[i] != CKM_SHA512) &&
  1687. (type[i] != CKM_MD5) &&
  1688. (type[i] != CKM_MD2)) {
  1689. listNeedLogin = PR_TRUE;
  1690. break;
  1691. }
  1692. }
  1693. for (le = PK11_GetFirstSafe(list); le;
  1694. le = PK11_GetNextSafe(list,le,PR_TRUE)) {
  1695. if (PK11_IsPresent(le->slot)) {
  1696. PRBool doExit = PR_FALSE;
  1697. for (i=0; i < mech_count; i++) {
  1698. if (!PK11_DoesMechanism(le->slot,type[i])) {
  1699. doExit = PR_TRUE;
  1700. break;
  1701. }
  1702. }
  1703. if (doExit) continue;
  1704. if (listNeedLogin && le->slot->needLogin) {
  1705. rv = PK11_Authenticate(le->slot,PR_TRUE,wincx);
  1706. if (rv != SECSuccess) continue;
  1707. }
  1708. slot = le->slot;
  1709. PK11_ReferenceSlot(slot);
  1710. PK11_FreeSlotListElement(list,le);
  1711. if (freeit) { PK11_FreeSlotList(list); }
  1712. return slot;
  1713. }
  1714. }
  1715. if (freeit) { PK11_FreeSlotList(list); }
  1716. if (PORT_GetError() == 0) {
  1717. PORT_SetError(SEC_ERROR_NO_TOKEN);
  1718. }
  1719. return NULL;
  1720. }
  1721. /* original get best slot now calls the multiple version with only one type */
  1722. PK11SlotInfo *
  1723. PK11_GetBestSlot(CK_MECHANISM_TYPE type, void *wincx)
  1724. {
  1725. return PK11_GetBestSlotMultiple(&type, 1, wincx);
  1726. }
  1727. int
  1728. PK11_GetBestKeyLength(PK11SlotInfo *slot,CK_MECHANISM_TYPE mechanism)
  1729. {
  1730. CK_MECHANISM_INFO mechanism_info;
  1731. CK_RV crv;
  1732. if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
  1733. crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,
  1734. mechanism,&mechanism_info);
  1735. if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
  1736. if (crv != CKR_OK) return 0;
  1737. if (mechanism_info.ulMinKeySize == mechanism_info.ulMaxKeySize)
  1738. return 0;
  1739. return mechanism_info.ulMaxKeySize;
  1740. }
  1741. /*
  1742. * This function uses the existing PKCS #11 module to find the
  1743. * longest supported key length in the preferred token for a mechanism.
  1744. * This varies from the above function in that 1) it returns the key length
  1745. * even for fixed key algorithms, and 2) it looks through the tokens
  1746. * generally rather than for a specific token. This is used in liu of
  1747. * a PK11_GetKeyLength function in pk11mech.c since we can actually read
  1748. * supported key lengths from PKCS #11.
  1749. *
  1750. * For symmetric key operations the length is returned in bytes.
  1751. */
  1752. int
  1753. PK11_GetMaxKeyLength(CK_MECHANISM_TYPE mechanism)
  1754. {
  1755. CK_MECHANISM_INFO mechanism_info;
  1756. PK11SlotList *list = NULL;
  1757. PK11SlotListElement *le ;
  1758. PRBool freeit = PR_FALSE;
  1759. int keyLength = 0;
  1760. list = PK11_GetSlotList(mechanism);
  1761. if ((list == NULL) || (list->head == NULL)) {
  1762. /* We need to look up all the tokens for the mechanism */
  1763. list = PK11_GetAllTokens(mechanism,PR_FALSE,PR_FALSE,NULL);
  1764. freeit = PR_TRUE;
  1765. }
  1766. /* no tokens recognize this mechanism */
  1767. if (list == NULL) {
  1768. PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
  1769. return 0;
  1770. }
  1771. for (le = PK11_GetFirstSafe(list); le;
  1772. le = PK11_GetNextSafe(list,le,PR_TRUE)) {
  1773. PK11SlotInfo *slot = le->slot;
  1774. CK_RV crv;
  1775. if (PK11_IsPresent(slot)) {
  1776. if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
  1777. crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,
  1778. mechanism,&mechanism_info);
  1779. if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
  1780. if ((crv == CKR_OK) && (mechanism_info.ulMaxKeySize != 0)
  1781. && (mechanism_info.ulMaxKeySize != 0xffffffff)) {
  1782. keyLength = mechanism_info.ulMaxKeySize;
  1783. break;
  1784. }
  1785. }
  1786. }
  1787. if (le)
  1788. PK11_FreeSlotListElement(list, le);
  1789. if (freeit)
  1790. PK11_FreeSlotList(list);
  1791. return keyLength;
  1792. }
  1793. SECStatus
  1794. PK11_SeedRandom(PK11SlotInfo *slot, unsigned char *data, int len) {
  1795. CK_RV crv;
  1796. PK11_EnterSlotMonitor(slot);
  1797. crv = PK11_GETTAB(slot)->C_SeedRandom(slot->session, data, (CK_ULONG)len);
  1798. PK11_ExitSlotMonitor(slot);
  1799. if (crv != CKR_OK) {
  1800. PORT_SetError(PK11_MapError(crv));
  1801. return SECFailure;
  1802. }
  1803. return SECSuccess;
  1804. }
  1805. SECStatus
  1806. PK11_GenerateRandomOnSlot(PK11SlotInfo *slot, unsigned char *data, int len) {
  1807. CK_RV crv;
  1808. if (!slot->isInternal) PK11_EnterSlotMonitor(slot);
  1809. crv = PK11_GETTAB(slot)->C_GenerateRandom(slot->session,data,
  1810. (CK_ULONG)len);
  1811. if (!slot->isInternal) PK11_ExitSlotMonitor(slot);
  1812. if (crv != CKR_OK) {
  1813. PORT_SetError(PK11_MapError(crv));
  1814. return SECFailure;
  1815. }
  1816. return SECSuccess;
  1817. }
  1818. /* Attempts to update the Best Slot for "FAKE RANDOM" generation.
  1819. ** If that's not the internal slot, then it also attempts to update the
  1820. ** internal slot.
  1821. ** The return value indicates if the INTERNAL slot was updated OK.
  1822. */
  1823. SECStatus
  1824. PK11_RandomUpdate(void *data, size_t bytes)
  1825. {
  1826. PK11SlotInfo *slot;
  1827. PRBool bestIsInternal;
  1828. SECStatus status;
  1829. slot = PK11_GetBestSlot(CKM_FAKE_RANDOM, NULL);
  1830. if (slot == NULL) {
  1831. slot = PK11_GetInternalSlot();
  1832. if (!slot)
  1833. return SECFailure;
  1834. }
  1835. bestIsInternal = PK11_IsInternal(slot);
  1836. status = PK11_SeedRandom(slot, data, bytes);
  1837. PK11_FreeSlot(slot);
  1838. if (!bestIsInternal) {
  1839. /* do internal slot, too. */
  1840. slot = PK11_GetInternalSlot(); /* can't fail */
  1841. status = PK11_SeedRandom(slot, data, bytes);
  1842. PK11_FreeSlot(slot);
  1843. }
  1844. return status;
  1845. }
  1846. SECStatus
  1847. PK11_GenerateRandom(unsigned char *data,int len) {
  1848. PK11SlotInfo *slot;
  1849. SECStatus rv;
  1850. slot = PK11_GetBestSlot(CKM_FAKE_RANDOM,NULL);
  1851. if (slot == NULL) return SECFailure;
  1852. rv = PK11_GenerateRandomOnSlot(slot, data, len);
  1853. PK11_FreeSlot(slot);
  1854. return rv;
  1855. }
  1856. /*
  1857. * Reset the token to it's initial state. For the internal module, this will
  1858. * Purge your keydb, and reset your cert db certs to USER_INIT.
  1859. */
  1860. SECStatus
  1861. PK11_ResetToken(PK11SlotInfo *slot, char *sso_pwd)
  1862. {
  1863. unsigned char tokenName[32];
  1864. int tokenNameLen;
  1865. CK_RV crv;
  1866. /* reconstruct the token name */
  1867. tokenNameLen = PORT_Strlen(slot->token_name);
  1868. if (tokenNameLen > sizeof(tokenName)) {
  1869. tokenNameLen = sizeof(tokenName);
  1870. }
  1871. PORT_Memcpy(tokenName,slot->token_name,tokenNameLen);
  1872. if (tokenNameLen < sizeof(tokenName)) {
  1873. PORT_Memset(&tokenName[tokenNameLen],' ',
  1874. sizeof(tokenName)-tokenNameLen);
  1875. }
  1876. /* initialize the token */
  1877. PK11_EnterSlotMonitor(slot);
  1878. /* first shutdown the token. Existing sessions will get closed here */
  1879. PK11_GETTAB(slot)->C_CloseAllSessions(slot->slotID);
  1880. slot->session = CK_INVALID_SESSION;
  1881. /* now re-init the token */
  1882. crv = PK11_GETTAB(slot)->C_InitToken(slot->slotID,
  1883. (unsigned char *)sso_pwd, sso_pwd ? PORT_Strlen(sso_pwd): 0, tokenName);
  1884. /* finally bring the token back up */
  1885. PK11_InitToken(slot,PR_TRUE);
  1886. PK11_ExitSlotMonitor(slot);
  1887. if (crv != CKR_OK) {
  1888. PORT_SetError(PK11_MapError(crv));
  1889. return SECFailure;
  1890. }
  1891. nssTrustDomain_UpdateCachedTokenCerts(slot->nssToken->trustDomain,
  1892. slot->nssToken);
  1893. return SECSuccess;
  1894. }
  1895. void
  1896. PK11Slot_SetNSSToken(PK11SlotInfo *sl, NSSToken *nsst)
  1897. {
  1898. sl->nssToken = nsst;
  1899. }
  1900. NSSToken *
  1901. PK11Slot_GetNSSToken(PK11SlotInfo *sl)
  1902. {
  1903. return sl->nssToken;
  1904. }
  1905. /*
  1906. * wait for a token to change it's state. The application passes in the expected
  1907. * new state in event.
  1908. */
  1909. PK11TokenStatus
  1910. PK11_WaitForTokenEvent(PK11SlotInfo *slot, PK11TokenEvent event,
  1911. PRIntervalTime timeout, PRIntervalTime latency, int series)
  1912. {
  1913. PRIntervalTime first_time = 0;
  1914. PRBool first_time_set = PR_FALSE;
  1915. PRBool waitForRemoval;
  1916. if (slot->isPerm) {
  1917. return PK11TokenNotRemovable;
  1918. }
  1919. if (latency == 0) {
  1920. latency = PR_SecondsToInterval(5);
  1921. }
  1922. waitForRemoval = (PRBool) (event == PK11TokenRemovedOrChangedEvent);
  1923. if (series == 0) {
  1924. series = PK11_GetSlotSeries(slot);
  1925. }
  1926. while (PK11_IsPresent(slot) == waitForRemoval ) {
  1927. PRIntervalTime interval;
  1928. if (waitForRemoval && series != PK11_GetSlotSeries(slot)) {
  1929. return PK11TokenChanged;
  1930. }
  1931. if (timeout == PR_INTERVAL_NO_WAIT) {
  1932. return waitForRemoval ? PK11TokenPresent : PK11TokenRemoved;
  1933. }
  1934. if (timeout != PR_INTERVAL_NO_TIMEOUT ) {
  1935. interval = PR_IntervalNow();
  1936. if (!first_time_set) {
  1937. first_time = interval;
  1938. first_time_set = PR_TRUE;
  1939. }
  1940. if ((interval-first_time) > timeout) {
  1941. return waitForRemoval ? PK11TokenPresent : PK11TokenRemoved;
  1942. }
  1943. }
  1944. PR_Sleep(latency);
  1945. }
  1946. return waitForRemoval ? PK11TokenRemoved : PK11TokenPresent;
  1947. }