1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
14 * The Original Code is the Netscape security libraries.
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.
22 * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
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.
36 * ***** END LICENSE BLOCK ***** */
38 * Deal with PKCS #11 Slots.
55 /*************************************************************
56 * local static and global data
57 *************************************************************/
60 * This array helps parsing between names, mechanisms, and flags.
61 * to make the config files understand more entries, add them
62 * to this table. (NOTE: we need function to export this table and it's size)
64 PK11DefaultArrayEntry PK11_DefaultArray
[] = {
65 { "RSA", SECMOD_RSA_FLAG
, CKM_RSA_PKCS
},
66 { "DSA", SECMOD_DSA_FLAG
, CKM_DSA
},
67 { "DH", SECMOD_DH_FLAG
, CKM_DH_PKCS_DERIVE
},
68 { "RC2", SECMOD_RC2_FLAG
, CKM_RC2_CBC
},
69 { "RC4", SECMOD_RC4_FLAG
, CKM_RC4
},
70 { "DES", SECMOD_DES_FLAG
, CKM_DES_CBC
},
71 { "AES", SECMOD_AES_FLAG
, CKM_AES_CBC
},
72 { "Camellia", SECMOD_CAMELLIA_FLAG
, CKM_CAMELLIA_CBC
},
73 { "RC5", SECMOD_RC5_FLAG
, CKM_RC5_CBC
},
74 { "SHA-1", SECMOD_SHA1_FLAG
, CKM_SHA_1
},
75 { "SHA256", SECMOD_SHA256_FLAG
, CKM_SHA256
},
76 /* { "SHA384", SECMOD_SHA512_FLAG, CKM_SHA384 }, */
77 { "SHA512", SECMOD_SHA512_FLAG
, CKM_SHA512
},
78 { "MD5", SECMOD_MD5_FLAG
, CKM_MD5
},
79 { "MD2", SECMOD_MD2_FLAG
, CKM_MD2
},
80 { "SSL", SECMOD_SSL_FLAG
, CKM_SSL3_PRE_MASTER_KEY_GEN
},
81 { "TLS", SECMOD_TLS_FLAG
, CKM_TLS_MASTER_KEY_DERIVE
},
82 { "SKIPJACK", SECMOD_FORTEZZA_FLAG
, CKM_SKIPJACK_CBC64
},
83 { "Publicly-readable certs", SECMOD_FRIENDLY_FLAG
, CKM_INVALID_MECHANISM
},
84 { "Random Num Generator", SECMOD_RANDOM_FLAG
, CKM_FAKE_RANDOM
},
86 const int num_pk11_default_mechanisms
=
87 sizeof(PK11_DefaultArray
) / sizeof(PK11_DefaultArray
[0]);
89 PK11DefaultArrayEntry
*
90 PK11_GetDefaultArray(int *size
)
93 *size
= num_pk11_default_mechanisms
;
95 return PK11_DefaultArray
;
99 * These slotlists are lists of modules which provide default support for
100 * a given algorithm or mechanism.
102 static PK11SlotList pk11_camelliaSlotList
,
120 pk11_sha512SlotList
; /* slots do SHA512 and SHA384 */
122 /************************************************************
123 * Generic Slot List and Slot List element manipulations
124 ************************************************************/
127 * allocate a new list
130 PK11_NewSlotList(void)
134 list
= (PK11SlotList
*)PORT_Alloc(sizeof(PK11SlotList
));
135 if (list
== NULL
) return NULL
;
138 list
->lock
= PZ_NewLock(nssILockList
);
139 if (list
->lock
== NULL
) {
148 * free a list element when all the references go away.
151 PK11_FreeSlotListElement(PK11SlotList
*list
, PK11SlotListElement
*le
)
153 PRBool freeit
= PR_FALSE
;
155 if (list
== NULL
|| le
== NULL
) {
156 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
161 if (le
->refCount
-- == 1) {
164 PZ_Unlock(list
->lock
);
166 PK11_FreeSlot(le
->slot
);
173 pk11_FreeSlotListStatic(PK11SlotList
*list
)
175 PK11SlotListElement
*le
, *next
;
176 if (list
== NULL
) return;
178 for (le
= list
->head
; le
; le
= next
) {
180 PK11_FreeSlotListElement(list
,le
);
183 PZ_DestroyLock(list
->lock
);
190 * if we are freeing the list, we must be the only ones with a pointer
194 PK11_FreeSlotList(PK11SlotList
*list
)
196 pk11_FreeSlotListStatic(list
);
201 * add a slot to a list
204 PK11_AddSlotToList(PK11SlotList
*list
,PK11SlotInfo
*slot
)
206 PK11SlotListElement
*le
;
208 le
= (PK11SlotListElement
*) PORT_Alloc(sizeof(PK11SlotListElement
));
209 if (le
== NULL
) return SECFailure
;
211 le
->slot
= PK11_ReferenceSlot(slot
);
215 if (list
->head
) list
->head
->prev
= le
; else list
->tail
= le
;
216 le
->next
= list
->head
;
218 PZ_Unlock(list
->lock
);
224 * remove a slot entry from the list
227 PK11_DeleteSlotFromList(PK11SlotList
*list
,PK11SlotListElement
*le
)
230 if (le
->prev
) le
->prev
->next
= le
->next
; else list
->head
= le
->next
;
231 if (le
->next
) le
->next
->prev
= le
->prev
; else list
->tail
= le
->prev
;
232 le
->next
= le
->prev
= NULL
;
233 PZ_Unlock(list
->lock
);
234 PK11_FreeSlotListElement(list
,le
);
239 * Move a list to the end of the target list. NOTE: There is no locking
240 * here... This assumes BOTH lists are private copy lists.
243 PK11_MoveListToList(PK11SlotList
*target
,PK11SlotList
*src
)
245 if (src
->head
== NULL
) return SECSuccess
;
247 if (target
->tail
== NULL
) {
248 target
->head
= src
->head
;
250 target
->tail
->next
= src
->head
;
252 src
->head
->prev
= target
->tail
;
253 target
->tail
= src
->tail
;
254 src
->head
= src
->tail
= NULL
;
259 * get an element from the list with a reference. You must own the list.
261 PK11SlotListElement
*
262 PK11_GetFirstRef(PK11SlotList
*list
)
264 PK11SlotListElement
*le
;
267 if (le
!= NULL
) (le
)->refCount
++;
272 * get the next element from the list with a reference. You must own the list.
274 PK11SlotListElement
*
275 PK11_GetNextRef(PK11SlotList
*list
, PK11SlotListElement
*le
, PRBool restart
)
277 PK11SlotListElement
*new_le
;
279 if (new_le
) new_le
->refCount
++;
280 PK11_FreeSlotListElement(list
,le
);
285 * get an element safely from the list. This just makes sure that if
286 * this element is not deleted while we deal with it.
288 PK11SlotListElement
*
289 PK11_GetFirstSafe(PK11SlotList
*list
)
291 PK11SlotListElement
*le
;
295 if (le
!= NULL
) (le
)->refCount
++;
296 PZ_Unlock(list
->lock
);
301 * NOTE: if this element gets deleted, we can no longer safely traverse using
302 * it's pointers. We can either terminate the loop, or restart from the
303 * beginning. This is controlled by the restart option.
305 PK11SlotListElement
*
306 PK11_GetNextSafe(PK11SlotList
*list
, PK11SlotListElement
*le
, PRBool restart
)
308 PK11SlotListElement
*new_le
;
311 if (le
->next
== NULL
) {
312 /* if the prev and next fields are NULL then either this element
313 * has been removed and we need to walk the list again (if restart
314 * is true) or this was the only element on the list */
315 if ((le
->prev
== NULL
) && restart
&& (list
->head
!= le
)) {
319 if (new_le
) new_le
->refCount
++;
320 PZ_Unlock(list
->lock
);
321 PK11_FreeSlotListElement(list
,le
);
327 * Find the element that holds this slot
329 PK11SlotListElement
*
330 PK11_FindSlotElement(PK11SlotList
*list
,PK11SlotInfo
*slot
)
332 PK11SlotListElement
*le
;
334 for (le
= PK11_GetFirstSafe(list
); le
;
335 le
= PK11_GetNextSafe(list
,le
,PR_TRUE
)) {
336 if (le
->slot
== slot
) return le
;
341 /************************************************************
342 * Generic Slot Utilities
343 ************************************************************/
345 * Create a new slot structure
348 PK11_NewSlotInfo(SECMODModule
*mod
)
352 slot
= (PK11SlotInfo
*)PORT_Alloc(sizeof(PK11SlotInfo
));
353 if (slot
== NULL
) return slot
;
355 slot
->sessionLock
= mod
->isThreadSafe
?
356 PZ_NewLock(nssILockSession
) : mod
->refLock
;
357 if (slot
->sessionLock
== NULL
) {
361 slot
->freeListLock
= PZ_NewLock(nssILockFreelist
);
362 if (slot
->freeListLock
== NULL
) {
363 if (mod
->isThreadSafe
) {
364 PZ_DestroyLock(slot
->sessionLock
);
369 slot
->freeSymKeysWithSessionHead
= NULL
;
370 slot
->freeSymKeysHead
= NULL
;
372 slot
->maxKeyCount
= 0;
373 slot
->functionList
= NULL
;
374 slot
->needTest
= PR_TRUE
;
375 slot
->isPerm
= PR_FALSE
;
376 slot
->isHW
= PR_FALSE
;
377 slot
->isInternal
= PR_FALSE
;
378 slot
->isThreadSafe
= PR_FALSE
;
379 slot
->disabled
= PR_FALSE
;
382 slot
->wrapMechanism
= CKM_INVALID_MECHANISM
;
383 slot
->refKeys
[0] = CK_INVALID_HANDLE
;
384 slot
->reason
= PK11_DIS_NONE
;
385 slot
->readOnly
= PR_TRUE
;
386 slot
->needLogin
= PR_FALSE
;
387 slot
->hasRandom
= PR_FALSE
;
388 slot
->defRWSession
= PR_FALSE
;
389 slot
->protectedAuthPath
= PR_FALSE
;
391 slot
->session
= CK_INVALID_SESSION
;
393 slot
->defaultFlags
= 0;
397 slot
->mechanismList
= NULL
;
398 slot
->mechanismCount
= 0;
399 slot
->cert_array
= NULL
;
400 slot
->cert_count
= 0;
401 slot
->slot_name
[0] = 0;
402 slot
->token_name
[0] = 0;
403 PORT_Memset(slot
->serial
,' ',sizeof(slot
->serial
));
405 slot
->authTransact
= 0;
406 slot
->authTime
= LL_ZERO
;
407 slot
->minPassword
= 0;
408 slot
->maxPassword
= 0;
409 slot
->hasRootCerts
= PR_FALSE
;
410 slot
->nssToken
= NULL
;
414 /* create a new reference to a slot so it doesn't go away */
416 PK11_ReferenceSlot(PK11SlotInfo
*slot
)
418 PR_AtomicIncrement(&slot
->refCount
);
422 /* Destroy all info on a slot we have built up */
424 PK11_DestroySlot(PK11SlotInfo
*slot
)
426 /* free up the cached keys and sessions */
427 PK11_CleanKeyList(slot
);
429 /* free up all the sessions on this slot */
430 if (slot
->functionList
) {
431 PK11_GETTAB(slot
)->C_CloseAllSessions(slot
->slotID
);
434 if (slot
->mechanismList
) {
435 PORT_Free(slot
->mechanismList
);
437 if (slot
->isThreadSafe
&& slot
->sessionLock
) {
438 PZ_DestroyLock(slot
->sessionLock
);
440 slot
->sessionLock
= NULL
;
441 if (slot
->freeListLock
) {
442 PZ_DestroyLock(slot
->freeListLock
);
443 slot
->freeListLock
= NULL
;
446 /* finally Tell our parent module that we've gone away so it can unload */
448 SECMOD_SlotDestroyModule(slot
->module
,PR_TRUE
);
451 /* ok, well not quit finally... now we free the memory */
456 /* We're all done with the slot, free it */
458 PK11_FreeSlot(PK11SlotInfo
*slot
)
460 if (PR_AtomicDecrement(&slot
->refCount
) == 0) {
461 PK11_DestroySlot(slot
);
466 PK11_EnterSlotMonitor(PK11SlotInfo
*slot
) {
467 PZ_Lock(slot
->sessionLock
);
471 PK11_ExitSlotMonitor(PK11SlotInfo
*slot
) {
472 PZ_Unlock(slot
->sessionLock
);
475 /***********************************************************
476 * Functions to find specific slots.
477 ***********************************************************/
479 SECMOD_HasRootCerts(void)
481 SECMODModuleList
*mlp
;
482 SECMODModuleList
*modules
= SECMOD_GetDefaultModuleList();
483 SECMODListLock
*moduleLock
= SECMOD_GetDefaultModuleListLock();
485 PRBool found
= PR_FALSE
;
487 /* work through all the slots */
488 SECMOD_GetReadLock(moduleLock
);
489 for(mlp
= modules
; mlp
!= NULL
; mlp
= mlp
->next
) {
490 for (i
=0; i
< mlp
->module
->slotCount
; i
++) {
491 PK11SlotInfo
*tmpSlot
= mlp
->module
->slots
[i
];
492 if (PK11_IsPresent(tmpSlot
)) {
493 if (tmpSlot
->hasRootCerts
) {
501 SECMOD_ReleaseReadLock(moduleLock
);
506 /***********************************************************
507 * Functions to find specific slots.
508 ***********************************************************/
510 PK11_FindSlotsByNames(const char *dllName
, const char* slotName
,
511 const char* tokenName
, PRBool presentOnly
)
513 SECMODModuleList
*mlp
;
514 SECMODModuleList
*modules
= SECMOD_GetDefaultModuleList();
515 SECMODListLock
*moduleLock
= SECMOD_GetDefaultModuleListLock();
517 PK11SlotList
* slotList
= NULL
;
518 PRUint32 slotcount
= 0;
519 SECStatus rv
= SECSuccess
;
521 slotList
= PK11_NewSlotList();
523 PORT_SetError(SEC_ERROR_NO_MEMORY
);
527 if ( ((NULL
== dllName
) || (0 == *dllName
)) &&
528 ((NULL
== slotName
) || (0 == *slotName
)) &&
529 ((NULL
== tokenName
) || (0 == *tokenName
)) ) {
530 /* default to softoken */
531 PK11_AddSlotToList(slotList
, PK11_GetInternalKeySlot());
535 /* work through all the slots */
536 SECMOD_GetReadLock(moduleLock
);
537 for (mlp
= modules
; mlp
!= NULL
; mlp
= mlp
->next
) {
538 PORT_Assert(mlp
->module
);
543 if ((!dllName
) || (mlp
->module
->dllName
&&
544 (0 == PORT_Strcmp(mlp
->module
->dllName
, dllName
)))) {
545 for (i
=0; i
< mlp
->module
->slotCount
; i
++) {
546 PK11SlotInfo
*tmpSlot
= (mlp
->module
->slots
?mlp
->module
->slots
[i
]:NULL
);
547 PORT_Assert(tmpSlot
);
552 if ((PR_FALSE
== presentOnly
|| PK11_IsPresent(tmpSlot
)) &&
553 ( (!tokenName
) || (tmpSlot
->token_name
&&
554 (0==PORT_Strcmp(tmpSlot
->token_name
, tokenName
)))) &&
555 ( (!slotName
) || (tmpSlot
->slot_name
&&
556 (0==PORT_Strcmp(tmpSlot
->slot_name
, slotName
)))) ) {
557 PK11SlotInfo
* slot
= PK11_ReferenceSlot(tmpSlot
);
559 PK11_AddSlotToList(slotList
, slot
);
566 SECMOD_ReleaseReadLock(moduleLock
);
568 if ( (0 == slotcount
) || (SECFailure
== rv
) ) {
569 PORT_SetError(SEC_ERROR_NO_TOKEN
);
570 PK11_FreeSlotList(slotList
);
574 if (SECFailure
== rv
) {
575 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE
);
582 PK11_FindSlotByName(const char *name
)
584 SECMODModuleList
*mlp
;
585 SECMODModuleList
*modules
= SECMOD_GetDefaultModuleList();
586 SECMODListLock
*moduleLock
= SECMOD_GetDefaultModuleListLock();
588 PK11SlotInfo
*slot
= NULL
;
590 if ((name
== NULL
) || (*name
== 0)) {
591 return PK11_GetInternalKeySlot();
594 /* work through all the slots */
595 SECMOD_GetReadLock(moduleLock
);
596 for(mlp
= modules
; mlp
!= NULL
; mlp
= mlp
->next
) {
597 for (i
=0; i
< mlp
->module
->slotCount
; i
++) {
598 PK11SlotInfo
*tmpSlot
= mlp
->module
->slots
[i
];
599 if (PK11_IsPresent(tmpSlot
)) {
600 if (PORT_Strcmp(tmpSlot
->token_name
,name
) == 0) {
601 slot
= PK11_ReferenceSlot(tmpSlot
);
606 if (slot
!= NULL
) break;
608 SECMOD_ReleaseReadLock(moduleLock
);
611 PORT_SetError(SEC_ERROR_NO_TOKEN
);
619 PK11_FindSlotBySerial(char *serial
)
621 SECMODModuleList
*mlp
;
622 SECMODModuleList
*modules
= SECMOD_GetDefaultModuleList();
623 SECMODListLock
*moduleLock
= SECMOD_GetDefaultModuleListLock();
625 PK11SlotInfo
*slot
= NULL
;
627 /* work through all the slots */
628 SECMOD_GetReadLock(moduleLock
);
629 for(mlp
= modules
; mlp
!= NULL
; mlp
= mlp
->next
) {
630 for (i
=0; i
< mlp
->module
->slotCount
; i
++) {
631 PK11SlotInfo
*tmpSlot
= mlp
->module
->slots
[i
];
632 if (PK11_IsPresent(tmpSlot
)) {
633 if (PORT_Memcmp(tmpSlot
->serial
,serial
,
634 sizeof(tmpSlot
->serial
)) == 0) {
635 slot
= PK11_ReferenceSlot(tmpSlot
);
640 if (slot
!= NULL
) break;
642 SECMOD_ReleaseReadLock(moduleLock
);
645 PORT_SetError(SEC_ERROR_NO_TOKEN
);
652 * notification stub. If we ever get interested in any events that
653 * the pkcs11 functions may pass back to use, we can catch them here...
654 * currently pdata is a slotinfo structure.
656 CK_RV
pk11_notify(CK_SESSION_HANDLE session
, CK_NOTIFICATION event
,
663 * grab a new RW session
664 * !!! has a side effect of grabbing the Monitor if either the slot's default
665 * session is RW or the slot is not thread safe. Monitor is release in function
668 CK_SESSION_HANDLE
PK11_GetRWSession(PK11SlotInfo
*slot
)
670 CK_SESSION_HANDLE rwsession
;
672 PRBool haveMonitor
= PR_FALSE
;
674 if (!slot
->isThreadSafe
|| slot
->defRWSession
) {
675 PK11_EnterSlotMonitor(slot
);
676 haveMonitor
= PR_TRUE
;
678 if (slot
->defRWSession
) {
679 PORT_Assert(slot
->session
!= CK_INVALID_SESSION
);
680 if (slot
->session
!= CK_INVALID_SESSION
)
681 return slot
->session
;
684 crv
= PK11_GETTAB(slot
)->C_OpenSession(slot
->slotID
,
685 CKF_RW_SESSION
|CKF_SERIAL_SESSION
,
686 slot
, pk11_notify
,&rwsession
);
687 PORT_Assert(rwsession
!= CK_INVALID_SESSION
|| crv
!= CKR_OK
);
688 if (crv
!= CKR_OK
|| rwsession
== CK_INVALID_SESSION
) {
690 crv
= CKR_DEVICE_ERROR
;
692 PK11_ExitSlotMonitor(slot
);
693 PORT_SetError(PK11_MapError(crv
));
694 return CK_INVALID_SESSION
;
696 if (slot
->defRWSession
) { /* we have the monitor */
697 slot
->session
= rwsession
;
703 PK11_RWSessionHasLock(PK11SlotInfo
*slot
,CK_SESSION_HANDLE session_handle
)
706 hasLock
= (PRBool
)(!slot
->isThreadSafe
||
707 (slot
->defRWSession
&& slot
->session
!= CK_INVALID_SESSION
));
712 pk11_RWSessionIsDefault(PK11SlotInfo
*slot
,CK_SESSION_HANDLE rwsession
)
715 isDefault
= (PRBool
)(slot
->session
== rwsession
&&
716 slot
->defRWSession
&&
717 slot
->session
!= CK_INVALID_SESSION
);
722 * close the rwsession and restore our readonly session
723 * !!! has a side effect of releasing the Monitor if either the slot's default
724 * session is RW or the slot is not thread safe.
727 PK11_RestoreROSession(PK11SlotInfo
*slot
,CK_SESSION_HANDLE rwsession
)
729 PORT_Assert(rwsession
!= CK_INVALID_SESSION
);
730 if (rwsession
!= CK_INVALID_SESSION
) {
731 PRBool doExit
= PK11_RWSessionHasLock(slot
, rwsession
);
732 if (!pk11_RWSessionIsDefault(slot
, rwsession
))
733 PK11_GETTAB(slot
)->C_CloseSession(rwsession
);
735 PK11_ExitSlotMonitor(slot
);
739 /************************************************************
740 * Manage the built-In Slot Lists
741 ************************************************************/
743 /* Init the static built int slot list (should actually integrate
744 * with PK11_NewSlotList */
746 pk11_InitSlotListStatic(PK11SlotList
*list
)
748 list
->lock
= PZ_NewLock(nssILockList
);
753 /* initialize the system slotlists */
755 PK11_InitSlotLists(void)
757 pk11_InitSlotListStatic(&pk11_camelliaSlotList
);
758 pk11_InitSlotListStatic(&pk11_aesSlotList
);
759 pk11_InitSlotListStatic(&pk11_desSlotList
);
760 pk11_InitSlotListStatic(&pk11_rc4SlotList
);
761 pk11_InitSlotListStatic(&pk11_rc2SlotList
);
762 pk11_InitSlotListStatic(&pk11_rc5SlotList
);
763 pk11_InitSlotListStatic(&pk11_md5SlotList
);
764 pk11_InitSlotListStatic(&pk11_md2SlotList
);
765 pk11_InitSlotListStatic(&pk11_sha1SlotList
);
766 pk11_InitSlotListStatic(&pk11_rsaSlotList
);
767 pk11_InitSlotListStatic(&pk11_dsaSlotList
);
768 pk11_InitSlotListStatic(&pk11_dhSlotList
);
769 pk11_InitSlotListStatic(&pk11_ecSlotList
);
770 pk11_InitSlotListStatic(&pk11_ideaSlotList
);
771 pk11_InitSlotListStatic(&pk11_sslSlotList
);
772 pk11_InitSlotListStatic(&pk11_tlsSlotList
);
773 pk11_InitSlotListStatic(&pk11_randomSlotList
);
774 pk11_InitSlotListStatic(&pk11_sha256SlotList
);
775 pk11_InitSlotListStatic(&pk11_sha512SlotList
);
780 PK11_DestroySlotLists(void)
782 pk11_FreeSlotListStatic(&pk11_camelliaSlotList
);
783 pk11_FreeSlotListStatic(&pk11_aesSlotList
);
784 pk11_FreeSlotListStatic(&pk11_desSlotList
);
785 pk11_FreeSlotListStatic(&pk11_rc4SlotList
);
786 pk11_FreeSlotListStatic(&pk11_rc2SlotList
);
787 pk11_FreeSlotListStatic(&pk11_rc5SlotList
);
788 pk11_FreeSlotListStatic(&pk11_md5SlotList
);
789 pk11_FreeSlotListStatic(&pk11_md2SlotList
);
790 pk11_FreeSlotListStatic(&pk11_sha1SlotList
);
791 pk11_FreeSlotListStatic(&pk11_rsaSlotList
);
792 pk11_FreeSlotListStatic(&pk11_dsaSlotList
);
793 pk11_FreeSlotListStatic(&pk11_dhSlotList
);
794 pk11_FreeSlotListStatic(&pk11_ecSlotList
);
795 pk11_FreeSlotListStatic(&pk11_ideaSlotList
);
796 pk11_FreeSlotListStatic(&pk11_sslSlotList
);
797 pk11_FreeSlotListStatic(&pk11_tlsSlotList
);
798 pk11_FreeSlotListStatic(&pk11_randomSlotList
);
799 pk11_FreeSlotListStatic(&pk11_sha256SlotList
);
800 pk11_FreeSlotListStatic(&pk11_sha512SlotList
);
804 /* return a system slot list based on mechanism */
806 PK11_GetSlotList(CK_MECHANISM_TYPE type
)
808 /* XXX a workaround for Bugzilla bug #55267 */
809 #if defined(HPUX) && defined(__LP64__)
810 if (CKM_INVALID_MECHANISM
== type
)
814 case CKM_CAMELLIA_CBC
:
815 case CKM_CAMELLIA_ECB
:
816 return &pk11_camelliaSlotList
;
819 return &pk11_aesSlotList
;
824 return &pk11_desSlotList
;
826 return &pk11_rc4SlotList
;
828 return &pk11_rc5SlotList
;
830 return &pk11_sha1SlotList
;
832 return &pk11_sha256SlotList
;
835 return &pk11_sha512SlotList
;
837 return &pk11_md5SlotList
;
839 return &pk11_md2SlotList
;
842 return &pk11_rc2SlotList
;
844 case CKM_RSA_PKCS_KEY_PAIR_GEN
:
846 return &pk11_rsaSlotList
;
848 return &pk11_dsaSlotList
;
849 case CKM_DH_PKCS_KEY_PAIR_GEN
:
850 case CKM_DH_PKCS_DERIVE
:
851 return &pk11_dhSlotList
;
854 case CKM_EC_KEY_PAIR_GEN
: /* aka CKM_ECDSA_KEY_PAIR_GEN */
855 case CKM_ECDH1_DERIVE
:
856 return &pk11_ecSlotList
;
857 case CKM_SSL3_PRE_MASTER_KEY_GEN
:
858 case CKM_SSL3_MASTER_KEY_DERIVE
:
859 case CKM_SSL3_SHA1_MAC
:
860 case CKM_SSL3_MD5_MAC
:
861 return &pk11_sslSlotList
;
862 case CKM_TLS_MASTER_KEY_DERIVE
:
863 case CKM_TLS_KEY_AND_MAC_DERIVE
:
864 return &pk11_tlsSlotList
;
867 return &pk11_ideaSlotList
;
868 case CKM_FAKE_RANDOM
:
869 return &pk11_randomSlotList
;
875 * load the static SlotInfo structures used to select a PKCS11 slot.
876 * preSlotInfo has a list of all the default flags for the slots on this
880 PK11_LoadSlotList(PK11SlotInfo
*slot
, PK11PreSlotInfo
*psi
, int count
)
884 for (i
=0; i
< count
; i
++) {
885 if (psi
[i
].slotID
== slot
->slotID
)
889 if (i
== count
) return;
891 slot
->defaultFlags
= psi
[i
].defaultFlags
;
892 slot
->askpw
= psi
[i
].askpw
;
893 slot
->timeout
= psi
[i
].timeout
;
894 slot
->hasRootCerts
= psi
[i
].hasRootCerts
;
896 /* if the slot is already disabled, don't load them into the
897 * default slot lists. We get here so we can save the default
899 if (slot
->disabled
) return;
901 /* if the user has disabled us, don't load us in */
902 if (slot
->defaultFlags
& PK11_DISABLE_FLAG
) {
903 slot
->disabled
= PR_TRUE
;
904 slot
->reason
= PK11_DIS_USER_SELECTED
;
905 /* free up sessions and things?? */
909 for (i
=0; i
< num_pk11_default_mechanisms
; i
++) {
910 if (slot
->defaultFlags
& PK11_DefaultArray
[i
].flag
) {
911 CK_MECHANISM_TYPE mechanism
= PK11_DefaultArray
[i
].mechanism
;
912 PK11SlotList
*slotList
= PK11_GetSlotList(mechanism
);
914 if (slotList
) PK11_AddSlotToList(slotList
,slot
);
923 * update a slot to its new attribute according to the slot list
924 * returns: SECSuccess if nothing to do or add/delete is successful
927 PK11_UpdateSlotAttribute(PK11SlotInfo
*slot
, PK11DefaultArrayEntry
*entry
,
929 /* add: PR_TRUE if want to turn on */
931 SECStatus result
= SECSuccess
;
932 PK11SlotList
*slotList
= PK11_GetSlotList(entry
->mechanism
);
934 if (add
) { /* trying to turn on a mechanism */
936 /* turn on the default flag in the slot */
937 slot
->defaultFlags
|= entry
->flag
;
939 /* add this slot to the list */
941 result
= PK11_AddSlotToList(slotList
, slot
);
943 } else { /* trying to turn off */
945 /* turn OFF the flag in the slot */
946 slot
->defaultFlags
&= ~entry
->flag
;
949 /* find the element in the list & delete it */
950 PK11SlotListElement
*le
= PK11_FindSlotElement(slotList
, slot
);
952 /* remove the slot from the list */
954 result
= PK11_DeleteSlotFromList(slotList
, le
);
961 * clear a slot off of all of it's default list
964 PK11_ClearSlotList(PK11SlotInfo
*slot
)
968 if (slot
->disabled
) return;
969 if (slot
->defaultFlags
== 0) return;
971 for (i
=0; i
< num_pk11_default_mechanisms
; i
++) {
972 if (slot
->defaultFlags
& PK11_DefaultArray
[i
].flag
) {
973 CK_MECHANISM_TYPE mechanism
= PK11_DefaultArray
[i
].mechanism
;
974 PK11SlotList
*slotList
= PK11_GetSlotList(mechanism
);
975 PK11SlotListElement
*le
= NULL
;
977 if (slotList
) le
= PK11_FindSlotElement(slotList
,slot
);
980 PK11_DeleteSlotFromList(slotList
,le
);
981 PK11_FreeSlotListElement(slotList
,le
);
988 /******************************************************************
989 * Slot initialization
990 ******************************************************************/
992 * turn a PKCS11 Static Label into a string
995 PK11_MakeString(PRArenaPool
*arena
,char *space
,
996 char *staticString
,int stringLen
)
1000 for(i
=(stringLen
-1); i
>= 0; i
--) {
1001 if (staticString
[i
] != ' ') break;
1003 /* move i to point to the last space */
1006 newString
= (char*)PORT_ArenaAlloc(arena
,i
+1 /* space for NULL */);
1010 newString
= (char*)PORT_Alloc(i
+1 /* space for NULL */);
1012 if (newString
== NULL
) return NULL
;
1014 if (i
) PORT_Memcpy(newString
,staticString
, i
);
1021 * verify that slot implements Mechanism mech properly by checking against
1022 * our internal implementation
1025 PK11_VerifyMechanism(PK11SlotInfo
*slot
,PK11SlotInfo
*intern
,
1026 CK_MECHANISM_TYPE mech
, SECItem
*data
, SECItem
*iv
)
1028 PK11Context
*test
= NULL
, *reference
= NULL
;
1029 PK11SymKey
*symKey
= NULL
, *testKey
= NULL
;
1030 SECItem
*param
= NULL
;
1031 unsigned char encTest
[8];
1032 unsigned char encRef
[8];
1033 int outLenTest
,outLenRef
;
1035 PRBool verify
= PR_FALSE
;
1038 if ((mech
== CKM_RC2_CBC
) || (mech
== CKM_RC2_ECB
) || (mech
== CKM_RC4
)) {
1042 /* initialize the mechanism parameter */
1043 param
= PK11_ParamFromIV(mech
,iv
);
1044 if (param
== NULL
) goto loser
;
1046 /* load the keys and contexts */
1047 symKey
= PK11_KeyGen(intern
,mech
,NULL
, key_size
, NULL
);
1048 if (symKey
== NULL
) goto loser
;
1050 reference
= PK11_CreateContextBySymKey(mech
, CKA_ENCRYPT
, symKey
, param
);
1051 if (reference
== NULL
) goto loser
;
1053 testKey
= pk11_CopyToSlot(slot
, mech
, CKA_ENCRYPT
, symKey
);
1054 if (testKey
== NULL
) goto loser
;
1056 test
= PK11_CreateContextBySymKey(mech
, CKA_ENCRYPT
, testKey
, param
);
1057 if (test
== NULL
) goto loser
;
1058 SECITEM_FreeItem(param
,PR_TRUE
); param
= NULL
;
1060 /* encrypt the test data */
1061 rv
= PK11_CipherOp(test
,encTest
,&outLenTest
,sizeof(encTest
),
1062 data
->data
,data
->len
);
1063 if (rv
!= SECSuccess
) goto loser
;
1064 rv
= PK11_CipherOp(reference
,encRef
,&outLenRef
,sizeof(encRef
),
1065 data
->data
,data
->len
);
1066 if (rv
!= SECSuccess
) goto loser
;
1068 PK11_DestroyContext(reference
,PR_TRUE
); reference
= NULL
;
1069 PK11_DestroyContext(test
,PR_TRUE
); test
= NULL
;
1071 if (outLenTest
!= outLenRef
) goto loser
;
1072 if (PORT_Memcmp(encTest
, encRef
, outLenTest
) != 0) goto loser
;
1077 if (test
) PK11_DestroyContext(test
,PR_TRUE
);
1078 if (symKey
) PK11_FreeSymKey(symKey
);
1079 if (testKey
) PK11_FreeSymKey(testKey
);
1080 if (reference
) PK11_DestroyContext(reference
,PR_TRUE
);
1081 if (param
) SECITEM_FreeItem(param
,PR_TRUE
);
1087 * this code verifies that the advertised mechanisms are what they
1090 #define MAX_MECH_LIST_SIZE 30 /* we only know of about 30 odd mechanisms */
1092 PK11_VerifySlotMechanisms(PK11SlotInfo
*slot
)
1094 CK_MECHANISM_TYPE mechListArray
[MAX_MECH_LIST_SIZE
];
1095 CK_MECHANISM_TYPE
*mechList
= mechListArray
;
1096 static SECItem data
;
1098 static unsigned char dataV
[8];
1099 static unsigned char ivV
[8];
1100 static PRBool generated
= PR_FALSE
;
1105 PRBool alloced
= PR_FALSE
;
1106 PK11SlotInfo
*intern
= PK11_GetInternalSlot();
1108 /* if we couldn't initialize an internal module,
1109 * we can't check external ones */
1110 if (intern
== NULL
) return PR_FALSE
;
1112 /* first get the count of mechanisms */
1113 if (!slot
->isThreadSafe
) PK11_EnterSlotMonitor(slot
);
1114 crv
= PK11_GETTAB(slot
)->C_GetMechanismList(slot
->slotID
,NULL
,&count
);
1115 if (!slot
->isThreadSafe
) PK11_ExitSlotMonitor(slot
);
1116 if (crv
!= CKR_OK
) {
1117 PK11_FreeSlot(intern
);
1122 /* don't blow up just because the card supports more mechanisms than
1123 * we know about, just alloc space for them */
1124 if (count
> MAX_MECH_LIST_SIZE
) {
1125 mechList
= (CK_MECHANISM_TYPE
*)
1126 PORT_Alloc(count
*sizeof(CK_MECHANISM_TYPE
));
1128 if (mechList
== NULL
) {
1129 PK11_FreeSlot(intern
);
1134 if (!slot
->isThreadSafe
) PK11_EnterSlotMonitor(slot
);
1135 crv
=PK11_GETTAB(slot
)->C_GetMechanismList(slot
->slotID
, mechList
, &count
);
1136 if (!slot
->isThreadSafe
) PK11_ExitSlotMonitor(slot
);
1137 if (crv
!= CKR_OK
) {
1138 if (alloced
) PORT_Free(mechList
);
1139 PK11_FreeSlot(intern
);
1145 data
.len
= sizeof(dataV
);
1147 iv
.len
= sizeof(ivV
);
1148 /* ok, this is a cheat, we know our internal random number generater
1150 PK11_GETTAB(intern
)->C_GenerateRandom(intern
->session
,
1151 data
.data
, data
.len
);
1152 PK11_GETTAB(intern
)->C_GenerateRandom(intern
->session
,
1155 for (i
=0; i
< (int) count
; i
++) {
1156 switch (mechList
[i
]) {
1162 if (!PK11_VerifyMechanism(slot
,intern
,mechList
[i
],&data
,&iv
)){
1163 if (alloced
) PORT_Free(mechList
);
1164 PK11_FreeSlot(intern
);
1169 if (alloced
) PORT_Free(mechList
);
1170 PK11_FreeSlot(intern
);
1175 * See if we need to run the verify test, do so if necessary. If we fail,
1179 pk11_CheckVerifyTest(PK11SlotInfo
*slot
)
1181 PK11_EnterSlotMonitor(slot
);
1182 if (slot
->needTest
) {
1183 slot
->needTest
= PR_FALSE
;
1184 PK11_ExitSlotMonitor(slot
);
1185 if (!PK11_VerifySlotMechanisms(slot
)) {
1186 (void)PK11_GETTAB(slot
)->C_CloseSession(slot
->session
);
1187 slot
->session
= CK_INVALID_SESSION
;
1188 PK11_ClearSlotList(slot
);
1189 slot
->disabled
= PR_TRUE
;
1190 slot
->reason
= PK11_DIS_TOKEN_VERIFY_FAILED
;
1191 slot
->needTest
= PR_TRUE
;
1192 PORT_SetError(SEC_ERROR_IO
);
1196 PK11_ExitSlotMonitor(slot
);
1202 * Reads in the slots mechanism list for later use
1205 PK11_ReadMechanismList(PK11SlotInfo
*slot
)
1211 if (slot
->mechanismList
) {
1212 PORT_Free(slot
->mechanismList
);
1213 slot
->mechanismList
= NULL
;
1215 slot
->mechanismCount
= 0;
1217 if (!slot
->isThreadSafe
) PK11_EnterSlotMonitor(slot
);
1218 crv
= PK11_GETTAB(slot
)->C_GetMechanismList(slot
->slotID
,NULL
,&count
);
1219 if (crv
!= CKR_OK
) {
1220 if (!slot
->isThreadSafe
) PK11_ExitSlotMonitor(slot
);
1221 PORT_SetError(PK11_MapError(crv
));
1225 slot
->mechanismList
= (CK_MECHANISM_TYPE
*)
1226 PORT_Alloc(count
*sizeof(CK_MECHANISM_TYPE
));
1227 if (slot
->mechanismList
== NULL
) {
1228 if (!slot
->isThreadSafe
) PK11_ExitSlotMonitor(slot
);
1231 crv
= PK11_GETTAB(slot
)->C_GetMechanismList(slot
->slotID
,
1232 slot
->mechanismList
, &count
);
1233 if (!slot
->isThreadSafe
) PK11_ExitSlotMonitor(slot
);
1234 if (crv
!= CKR_OK
) {
1235 PORT_Free(slot
->mechanismList
);
1236 slot
->mechanismList
= NULL
;
1237 PORT_SetError(PK11_MapError(crv
));
1240 slot
->mechanismCount
= count
;
1241 PORT_Memset(slot
->mechanismBits
, 0, sizeof(slot
->mechanismBits
));
1243 for (i
=0; i
< count
; i
++) {
1244 CK_MECHANISM_TYPE mech
= slot
->mechanismList
[i
];
1246 slot
->mechanismBits
[mech
& 0xff] |= 1 << (mech
>> 8);
1253 * initialize a new token
1254 * unlike initialize slot, this can be called multiple times in the lifetime
1255 * of NSS. It reads the information associated with a card or token,
1256 * that is not going to change unless the card or token changes.
1259 PK11_InitToken(PK11SlotInfo
*slot
, PRBool loadCerts
)
1261 CK_TOKEN_INFO tokenInfo
;
1266 /* set the slot flags to the current token values */
1267 if (!slot
->isThreadSafe
) PK11_EnterSlotMonitor(slot
);
1268 crv
= PK11_GETTAB(slot
)->C_GetTokenInfo(slot
->slotID
,&tokenInfo
);
1269 if (!slot
->isThreadSafe
) PK11_ExitSlotMonitor(slot
);
1270 if (crv
!= CKR_OK
) {
1271 PORT_SetError(PK11_MapError(crv
));
1275 /* set the slot flags to the current token values */
1276 slot
->series
++; /* allow other objects to detect that the
1277 * slot is different */
1278 slot
->flags
= tokenInfo
.flags
;
1279 slot
->needLogin
= ((tokenInfo
.flags
& CKF_LOGIN_REQUIRED
) ?
1280 PR_TRUE
: PR_FALSE
);
1281 slot
->readOnly
= ((tokenInfo
.flags
& CKF_WRITE_PROTECTED
) ?
1282 PR_TRUE
: PR_FALSE
);
1283 slot
->hasRandom
= ((tokenInfo
.flags
& CKF_RNG
) ? PR_TRUE
: PR_FALSE
);
1284 slot
->protectedAuthPath
=
1285 ((tokenInfo
.flags
& CKF_PROTECTED_AUTHENTICATION_PATH
)
1286 ? PR_TRUE
: PR_FALSE
);
1287 slot
->lastLoginCheck
= 0;
1288 slot
->lastState
= 0;
1289 /* on some platforms Active Card incorrectly sets the
1290 * CKF_PROTECTED_AUTHENTICATION_PATH bit when it doesn't mean to. */
1291 if (slot
->isActiveCard
) {
1292 slot
->protectedAuthPath
= PR_FALSE
;
1294 tmp
= PK11_MakeString(NULL
,slot
->token_name
,
1295 (char *)tokenInfo
.label
, sizeof(tokenInfo
.label
));
1296 slot
->minPassword
= tokenInfo
.ulMinPinLen
;
1297 slot
->maxPassword
= tokenInfo
.ulMaxPinLen
;
1298 PORT_Memcpy(slot
->serial
,tokenInfo
.serialNumber
,sizeof(slot
->serial
));
1300 nssToken_UpdateName(slot
->nssToken
);
1302 slot
->defRWSession
= (PRBool
)((!slot
->readOnly
) &&
1303 (tokenInfo
.ulMaxSessionCount
== 1));
1304 rv
= PK11_ReadMechanismList(slot
);
1305 if (rv
!= SECSuccess
) return rv
;
1307 slot
->hasRSAInfo
= PR_FALSE
;
1308 slot
->RSAInfoFlags
= 0;
1310 /* initialize the maxKeyCount value */
1311 if (tokenInfo
.ulMaxSessionCount
== 0) {
1312 slot
->maxKeyCount
= 800; /* should be #define or a config param */
1313 } else if (tokenInfo
.ulMaxSessionCount
< 20) {
1314 /* don't have enough sessions to keep that many keys around */
1315 slot
->maxKeyCount
= 0;
1317 slot
->maxKeyCount
= tokenInfo
.ulMaxSessionCount
/2;
1320 /* Make sure our session handle is valid */
1321 if (slot
->session
== CK_INVALID_SESSION
) {
1322 /* we know we don't have a valid session, go get one */
1323 CK_SESSION_HANDLE session
;
1325 /* session should be Readonly, serial */
1326 if (!slot
->isThreadSafe
) PK11_EnterSlotMonitor(slot
);
1327 crv
= PK11_GETTAB(slot
)->C_OpenSession(slot
->slotID
,
1328 (slot
->defRWSession
? CKF_RW_SESSION
: 0) | CKF_SERIAL_SESSION
,
1329 slot
,pk11_notify
,&session
);
1330 if (!slot
->isThreadSafe
) PK11_ExitSlotMonitor(slot
);
1331 if (crv
!= CKR_OK
) {
1332 PORT_SetError(PK11_MapError(crv
));
1335 slot
->session
= session
;
1337 /* The session we have may be defunct (the token associated with it)
1338 * has been removed */
1339 CK_SESSION_INFO sessionInfo
;
1341 if (!slot
->isThreadSafe
) PK11_EnterSlotMonitor(slot
);
1342 crv
= PK11_GETTAB(slot
)->C_GetSessionInfo(slot
->session
,&sessionInfo
);
1343 if (crv
== CKR_DEVICE_ERROR
) {
1344 PK11_GETTAB(slot
)->C_CloseSession(slot
->session
);
1345 crv
= CKR_SESSION_CLOSED
;
1347 if ((crv
==CKR_SESSION_CLOSED
) || (crv
==CKR_SESSION_HANDLE_INVALID
)) {
1348 crv
=PK11_GETTAB(slot
)->C_OpenSession(slot
->slotID
,
1349 (slot
->defRWSession
? CKF_RW_SESSION
: 0) | CKF_SERIAL_SESSION
,
1350 slot
,pk11_notify
,&slot
->session
);
1351 if (crv
!= CKR_OK
) {
1352 PORT_SetError(PK11_MapError(crv
));
1353 slot
->session
= CK_INVALID_SESSION
;
1354 if (!slot
->isThreadSafe
) PK11_ExitSlotMonitor(slot
);
1358 if (!slot
->isThreadSafe
) PK11_ExitSlotMonitor(slot
);
1361 nssToken_Refresh(slot
->nssToken
);
1363 if (!(slot
->needLogin
)) {
1364 return pk11_CheckVerifyTest(slot
);
1368 if (!(slot
->isInternal
) && (slot
->hasRandom
)) {
1369 /* if this slot has a random number generater, use it to add entropy
1370 * to the internal slot. */
1371 PK11SlotInfo
*int_slot
= PK11_GetInternalSlot();
1374 unsigned char random_bytes
[32];
1376 /* if this slot can issue random numbers, get some entropy from
1377 * that random number generater and give it to our internal token.
1379 PK11_EnterSlotMonitor(slot
);
1380 crv
= PK11_GETTAB(slot
)->C_GenerateRandom
1381 (slot
->session
,random_bytes
, sizeof(random_bytes
));
1382 PK11_ExitSlotMonitor(slot
);
1383 if (crv
== CKR_OK
) {
1384 PK11_EnterSlotMonitor(int_slot
);
1385 PK11_GETTAB(int_slot
)->C_SeedRandom(int_slot
->session
,
1386 random_bytes
, sizeof(random_bytes
));
1387 PK11_ExitSlotMonitor(int_slot
);
1390 /* Now return the favor and send entropy to the token's random
1391 * number generater */
1392 PK11_EnterSlotMonitor(int_slot
);
1393 crv
= PK11_GETTAB(int_slot
)->C_GenerateRandom(int_slot
->session
,
1394 random_bytes
, sizeof(random_bytes
));
1395 PK11_ExitSlotMonitor(int_slot
);
1396 if (crv
== CKR_OK
) {
1397 PK11_EnterSlotMonitor(slot
);
1398 PK11_GETTAB(slot
)->C_SeedRandom(slot
->session
,
1399 random_bytes
, sizeof(random_bytes
));
1400 PK11_ExitSlotMonitor(slot
);
1402 PK11_FreeSlot(int_slot
);
1411 * initialize a new token
1412 * unlike initialize slot, this can be called multiple times in the lifetime
1413 * of NSS. It reads the information associated with a card or token,
1414 * that is not going to change unless the card or token changes.
1417 PK11_TokenRefresh(PK11SlotInfo
*slot
)
1419 CK_TOKEN_INFO tokenInfo
;
1422 /* set the slot flags to the current token values */
1423 if (!slot
->isThreadSafe
) PK11_EnterSlotMonitor(slot
);
1424 crv
= PK11_GETTAB(slot
)->C_GetTokenInfo(slot
->slotID
,&tokenInfo
);
1425 if (!slot
->isThreadSafe
) PK11_ExitSlotMonitor(slot
);
1426 if (crv
!= CKR_OK
) {
1427 PORT_SetError(PK11_MapError(crv
));
1431 slot
->flags
= tokenInfo
.flags
;
1432 slot
->needLogin
= ((tokenInfo
.flags
& CKF_LOGIN_REQUIRED
) ?
1433 PR_TRUE
: PR_FALSE
);
1434 slot
->readOnly
= ((tokenInfo
.flags
& CKF_WRITE_PROTECTED
) ?
1435 PR_TRUE
: PR_FALSE
);
1436 slot
->hasRandom
= ((tokenInfo
.flags
& CKF_RNG
) ? PR_TRUE
: PR_FALSE
);
1437 slot
->protectedAuthPath
=
1438 ((tokenInfo
.flags
& CKF_PROTECTED_AUTHENTICATION_PATH
)
1439 ? PR_TRUE
: PR_FALSE
);
1440 /* on some platforms Active Card incorrectly sets the
1441 * CKF_PROTECTED_AUTHENTICATION_PATH bit when it doesn't mean to. */
1442 if (slot
->isActiveCard
) {
1443 slot
->protectedAuthPath
= PR_FALSE
;
1449 pk11_isRootSlot(PK11SlotInfo
*slot
)
1451 CK_ATTRIBUTE findTemp
[1];
1452 CK_ATTRIBUTE
*attrs
;
1453 CK_OBJECT_CLASS oclass
= CKO_NETSCAPE_BUILTIN_ROOT_LIST
;
1455 CK_OBJECT_HANDLE handle
;
1458 PK11_SETATTRS(attrs
, CKA_CLASS
, &oclass
, sizeof(oclass
)); attrs
++;
1459 tsize
= attrs
- findTemp
;
1460 PORT_Assert(tsize
<= sizeof(findTemp
)/sizeof(CK_ATTRIBUTE
));
1462 handle
= pk11_FindObjectByTemplate(slot
,findTemp
,tsize
);
1463 if (handle
== CK_INVALID_HANDLE
) {
1470 * Initialize the slot :
1471 * This initialization code is called on each slot a module supports when
1472 * it is loaded. It does the bringup initialization. The difference between
1473 * this and InitToken is Init slot does those one time initialization stuff,
1474 * usually associated with the reader, while InitToken may get called multiple
1475 * times as tokens are removed and re-inserted.
1478 PK11_InitSlot(SECMODModule
*mod
,CK_SLOT_ID slotID
,PK11SlotInfo
*slot
)
1482 CK_SLOT_INFO slotInfo
;
1484 slot
->functionList
= mod
->functionList
;
1485 slot
->isInternal
= mod
->internal
;
1486 slot
->slotID
= slotID
;
1487 slot
->isThreadSafe
= mod
->isThreadSafe
;
1488 slot
->hasRSAInfo
= PR_FALSE
;
1490 if (PK11_GETTAB(slot
)->C_GetSlotInfo(slotID
,&slotInfo
) != CKR_OK
) {
1491 slot
->disabled
= PR_TRUE
;
1492 slot
->reason
= PK11_DIS_COULD_NOT_INIT_TOKEN
;
1496 /* test to make sure claimed mechanism work */
1497 slot
->needTest
= mod
->internal
? PR_FALSE
: PR_TRUE
;
1498 slot
->module
= mod
; /* NOTE: we don't make a reference here because
1499 * modules have references to their slots. This
1500 * works because modules keep implicit references
1501 * from their slots, and won't unload and disappear
1502 * until all their slots have been freed */
1503 tmp
= PK11_MakeString(NULL
,slot
->slot_name
,
1504 (char *)slotInfo
.slotDescription
, sizeof(slotInfo
.slotDescription
));
1505 slot
->isHW
= (PRBool
)((slotInfo
.flags
& CKF_HW_SLOT
) == CKF_HW_SLOT
);
1506 #define ACTIVE_CARD "ActivCard SA"
1507 slot
->isActiveCard
= (PRBool
)(PORT_Strncmp((char *)slotInfo
.manufacturerID
,
1508 ACTIVE_CARD
, sizeof(ACTIVE_CARD
)-1) == 0);
1509 if ((slotInfo
.flags
& CKF_REMOVABLE_DEVICE
) == 0) {
1510 slot
->isPerm
= PR_TRUE
;
1511 /* permanment slots must have the token present always */
1512 if ((slotInfo
.flags
& CKF_TOKEN_PRESENT
) == 0) {
1513 slot
->disabled
= PR_TRUE
;
1514 slot
->reason
= PK11_DIS_TOKEN_NOT_PRESENT
;
1515 return; /* nothing else to do */
1518 /* if the token is present, initialize it */
1519 if ((slotInfo
.flags
& CKF_TOKEN_PRESENT
) != 0) {
1520 rv
= PK11_InitToken(slot
,PR_TRUE
);
1521 /* the only hard failures are on permanent devices, or function
1522 * verify failures... function verify failures are already handled
1524 if ((rv
!= SECSuccess
) && (slot
->isPerm
) && (!slot
->disabled
)) {
1525 slot
->disabled
= PR_TRUE
;
1526 slot
->reason
= PK11_DIS_COULD_NOT_INIT_TOKEN
;
1529 if (pk11_isRootSlot(slot
)) {
1530 if (!slot
->hasRootCerts
) {
1531 slot
->module
->trustOrder
= 100;
1533 slot
->hasRootCerts
= PR_TRUE
;
1539 /*********************************************************************
1540 * Slot mapping utility functions.
1541 *********************************************************************/
1544 * determine if the token is present. If the token is present, make sure
1545 * we have a valid session handle. Also set the value of needLogin
1549 pk11_IsPresentCertLoad(PK11SlotInfo
*slot
, PRBool loadCerts
)
1551 CK_SLOT_INFO slotInfo
;
1552 CK_SESSION_INFO sessionInfo
;
1555 /* disabled slots are never present */
1556 if (slot
->disabled
) {
1560 /* permanent slots are always present */
1561 if (slot
->isPerm
&& (slot
->session
!= CK_INVALID_SESSION
)) {
1565 if (slot
->nssToken
) {
1566 return nssToken_IsPresent(slot
->nssToken
);
1569 /* removable slots have a flag that says they are present */
1570 if (!slot
->isThreadSafe
) PK11_EnterSlotMonitor(slot
);
1571 if (PK11_GETTAB(slot
)->C_GetSlotInfo(slot
->slotID
,&slotInfo
) != CKR_OK
) {
1572 if (!slot
->isThreadSafe
) PK11_ExitSlotMonitor(slot
);
1575 if ((slotInfo
.flags
& CKF_TOKEN_PRESENT
) == 0) {
1576 /* if the slot is no longer present, close the session */
1577 if (slot
->session
!= CK_INVALID_SESSION
) {
1578 PK11_GETTAB(slot
)->C_CloseSession(slot
->session
);
1579 slot
->session
= CK_INVALID_SESSION
;
1581 if (!slot
->isThreadSafe
) PK11_ExitSlotMonitor(slot
);
1585 /* use the session Info to determine if the card has been removed and then
1587 if (slot
->session
!= CK_INVALID_SESSION
) {
1588 if (slot
->isThreadSafe
) PK11_EnterSlotMonitor(slot
);
1589 crv
= PK11_GETTAB(slot
)->C_GetSessionInfo(slot
->session
, &sessionInfo
);
1590 if (crv
!= CKR_OK
) {
1591 PK11_GETTAB(slot
)->C_CloseSession(slot
->session
);
1592 slot
->session
= CK_INVALID_SESSION
;
1594 if (slot
->isThreadSafe
) PK11_ExitSlotMonitor(slot
);
1596 if (!slot
->isThreadSafe
) PK11_ExitSlotMonitor(slot
);
1598 /* card has not been removed, current token info is correct */
1599 if (slot
->session
!= CK_INVALID_SESSION
) return PR_TRUE
;
1601 /* initialize the token info state */
1602 if (PK11_InitToken(slot
,loadCerts
) != SECSuccess
) {
1610 * old version of the routine
1613 PK11_IsPresent(PK11SlotInfo
*slot
) {
1614 return pk11_IsPresentCertLoad(slot
,PR_TRUE
);
1617 /* is the slot disabled? */
1619 PK11_IsDisabled(PK11SlotInfo
*slot
)
1621 return slot
->disabled
;
1626 PK11_GetDisabledReason(PK11SlotInfo
*slot
)
1628 return slot
->reason
;
1631 /* returns PR_TRUE if successfully disable the slot */
1632 /* returns PR_FALSE otherwise */
1633 PRBool
PK11_UserDisableSlot(PK11SlotInfo
*slot
) {
1635 slot
->defaultFlags
|= PK11_DISABLE_FLAG
;
1636 slot
->disabled
= PR_TRUE
;
1637 slot
->reason
= PK11_DIS_USER_SELECTED
;
1642 PRBool
PK11_UserEnableSlot(PK11SlotInfo
*slot
) {
1644 slot
->defaultFlags
&= ~PK11_DISABLE_FLAG
;
1645 slot
->disabled
= PR_FALSE
;
1646 slot
->reason
= PK11_DIS_NONE
;
1650 PRBool
PK11_HasRootCerts(PK11SlotInfo
*slot
) {
1651 return slot
->hasRootCerts
;
1654 /* Get the module this slot is attached to */
1656 PK11_GetModule(PK11SlotInfo
*slot
)
1658 return slot
->module
;
1661 /* return the default flags of a slot */
1663 PK11_GetDefaultFlags(PK11SlotInfo
*slot
)
1665 return slot
->defaultFlags
;
1669 * The following wrapper functions allow us to export an opaque slot
1670 * function to the rest of libsec and the world... */
1672 PK11_IsReadOnly(PK11SlotInfo
*slot
)
1674 return slot
->readOnly
;
1678 PK11_IsHW(PK11SlotInfo
*slot
)
1684 PK11_IsInternal(PK11SlotInfo
*slot
)
1686 return slot
->isInternal
;
1690 PK11_NeedLogin(PK11SlotInfo
*slot
)
1692 return slot
->needLogin
;
1696 PK11_IsFriendly(PK11SlotInfo
*slot
)
1698 /* internal slot always has public readable certs */
1699 return (PRBool
)(slot
->isInternal
||
1700 ((slot
->defaultFlags
& SECMOD_FRIENDLY_FLAG
) ==
1701 SECMOD_FRIENDLY_FLAG
));
1705 PK11_GetTokenName(PK11SlotInfo
*slot
)
1707 return slot
->token_name
;
1711 PK11_GetSlotName(PK11SlotInfo
*slot
)
1713 return slot
->slot_name
;
1717 PK11_GetSlotSeries(PK11SlotInfo
*slot
)
1719 return slot
->series
;
1723 PK11_GetCurrentWrapIndex(PK11SlotInfo
*slot
)
1725 return slot
->wrapKey
;
1729 PK11_GetSlotID(PK11SlotInfo
*slot
)
1731 return slot
->slotID
;
1735 PK11_GetModuleID(PK11SlotInfo
*slot
)
1737 return slot
->module
->moduleID
;
1741 pk11_zeroTerminatedToBlankPadded(CK_CHAR
*buffer
, size_t buffer_size
)
1743 CK_CHAR
*walk
= buffer
;
1744 CK_CHAR
*end
= buffer
+ buffer_size
;
1747 while (walk
< end
&& *walk
!= '\0') {
1751 /* clear out the buffer */
1752 while (walk
< end
) {
1757 /* return the slot info structure */
1759 PK11_GetSlotInfo(PK11SlotInfo
*slot
, CK_SLOT_INFO
*info
)
1763 if (!slot
->isThreadSafe
) PK11_EnterSlotMonitor(slot
);
1765 * some buggy drivers do not fill the buffer completely,
1766 * erase the buffer first
1768 PORT_Memset(info
->slotDescription
,' ',sizeof(info
->slotDescription
));
1769 PORT_Memset(info
->manufacturerID
,' ',sizeof(info
->manufacturerID
));
1770 crv
= PK11_GETTAB(slot
)->C_GetSlotInfo(slot
->slotID
,info
);
1771 pk11_zeroTerminatedToBlankPadded(info
->slotDescription
,
1772 sizeof(info
->slotDescription
));
1773 pk11_zeroTerminatedToBlankPadded(info
->manufacturerID
,
1774 sizeof(info
->manufacturerID
));
1775 if (!slot
->isThreadSafe
) PK11_ExitSlotMonitor(slot
);
1776 if (crv
!= CKR_OK
) {
1777 PORT_SetError(PK11_MapError(crv
));
1783 /* return the token info structure */
1785 PK11_GetTokenInfo(PK11SlotInfo
*slot
, CK_TOKEN_INFO
*info
)
1788 if (!slot
->isThreadSafe
) PK11_EnterSlotMonitor(slot
);
1790 * some buggy drivers do not fill the buffer completely,
1791 * erase the buffer first
1793 PORT_Memset(info
->label
,' ',sizeof(info
->label
));
1794 PORT_Memset(info
->manufacturerID
,' ',sizeof(info
->manufacturerID
));
1795 PORT_Memset(info
->model
,' ',sizeof(info
->model
));
1796 PORT_Memset(info
->serialNumber
,' ',sizeof(info
->serialNumber
));
1797 crv
= PK11_GETTAB(slot
)->C_GetTokenInfo(slot
->slotID
,info
);
1798 pk11_zeroTerminatedToBlankPadded(info
->label
,sizeof(info
->label
));
1799 pk11_zeroTerminatedToBlankPadded(info
->manufacturerID
,
1800 sizeof(info
->manufacturerID
));
1801 pk11_zeroTerminatedToBlankPadded(info
->model
,sizeof(info
->model
));
1802 pk11_zeroTerminatedToBlankPadded(info
->serialNumber
,
1803 sizeof(info
->serialNumber
));
1804 if (!slot
->isThreadSafe
) PK11_ExitSlotMonitor(slot
);
1805 if (crv
!= CKR_OK
) {
1806 PORT_SetError(PK11_MapError(crv
));
1812 /* Find out if we need to initialize the user's pin */
1814 PK11_NeedUserInit(PK11SlotInfo
*slot
)
1816 PRBool needUserInit
= (PRBool
) ((slot
->flags
& CKF_USER_PIN_INITIALIZED
)
1823 /* see if token has been initialized off line */
1824 rv
= PK11_GetTokenInfo(slot
, &info
);
1825 if (rv
== SECSuccess
) {
1826 slot
->flags
= info
.flags
;
1829 return (PRBool
)((slot
->flags
& CKF_USER_PIN_INITIALIZED
) == 0);
1832 /* get the internal key slot. FIPS has only one slot for both key slots and
1835 PK11_GetInternalKeySlot(void)
1837 SECMODModule
*mod
= SECMOD_GetInternalModule();
1838 PORT_Assert(mod
!= NULL
);
1840 PORT_SetError( SEC_ERROR_NO_MODULE
);
1843 return PK11_ReferenceSlot(mod
->isFIPS
? mod
->slots
[0] : mod
->slots
[1]);
1846 /* get the internal default slot */
1848 PK11_GetInternalSlot(void)
1850 SECMODModule
* mod
= SECMOD_GetInternalModule();
1851 PORT_Assert(mod
!= NULL
);
1853 PORT_SetError( SEC_ERROR_NO_MODULE
);
1856 return PK11_ReferenceSlot(mod
->slots
[0]);
1860 * check if a given slot supports the requested mechanism
1863 PK11_DoesMechanism(PK11SlotInfo
*slot
, CK_MECHANISM_TYPE type
)
1867 /* CKM_FAKE_RANDOM is not a real PKCS mechanism. It's a marker to
1868 * tell us we're looking form someone that has implemented get
1870 if (type
== CKM_FAKE_RANDOM
) {
1871 return slot
->hasRandom
;
1874 /* for most mechanism, bypass the linear lookup */
1876 return (slot
->mechanismBits
[type
& 0xff] & (1 << (type
>> 8))) ?
1880 for (i
=0; i
< (int) slot
->mechanismCount
; i
++) {
1881 if (slot
->mechanismList
[i
] == type
) return PR_TRUE
;
1887 * Return true if a token that can do the desired mechanism exists.
1888 * This allows us to have hardware tokens that can do function XYZ magically
1889 * allow SSL Ciphers to appear if they are plugged in.
1892 PK11_TokenExists(CK_MECHANISM_TYPE type
)
1894 SECMODModuleList
*mlp
;
1895 SECMODModuleList
*modules
= SECMOD_GetDefaultModuleList();
1896 SECMODListLock
*moduleLock
= SECMOD_GetDefaultModuleListLock();
1898 PRBool found
= PR_FALSE
;
1901 /* we only need to know if there is a token that does this mechanism.
1902 * check the internal module first because it's fast, and supports
1903 * almost everything. */
1904 slot
= PK11_GetInternalSlot();
1906 found
= PK11_DoesMechanism(slot
,type
);
1907 PK11_FreeSlot(slot
);
1909 if (found
) return PR_TRUE
; /* bypass getting module locks */
1911 SECMOD_GetReadLock(moduleLock
);
1912 for(mlp
= modules
; mlp
!= NULL
&& (!found
); mlp
= mlp
->next
) {
1913 for (i
=0; i
< mlp
->module
->slotCount
; i
++) {
1914 slot
= mlp
->module
->slots
[i
];
1915 if (PK11_IsPresent(slot
)) {
1916 if (PK11_DoesMechanism(slot
,type
)) {
1923 SECMOD_ReleaseReadLock(moduleLock
);
1928 * get all the currently available tokens in a list.
1929 * that can perform the given mechanism. If mechanism is CKM_INVALID_MECHANISM,
1930 * get all the tokens. Make sure tokens that need authentication are put at
1931 * the end of this list.
1934 PK11_GetAllTokens(CK_MECHANISM_TYPE type
, PRBool needRW
, PRBool loadCerts
,
1937 PK11SlotList
* list
= PK11_NewSlotList();
1938 PK11SlotList
* loginList
= PK11_NewSlotList();
1939 PK11SlotList
* friendlyList
= PK11_NewSlotList();
1940 SECMODModuleList
* mlp
;
1941 SECMODModuleList
* modules
= SECMOD_GetDefaultModuleList();
1942 SECMODListLock
* moduleLock
= SECMOD_GetDefaultModuleListLock();
1944 #if defined( XP_WIN32 )
1949 if ((list
== NULL
) || (loginList
== NULL
) || (friendlyList
== NULL
)) {
1950 if (list
) PK11_FreeSlotList(list
);
1951 if (loginList
) PK11_FreeSlotList(loginList
);
1952 if (friendlyList
) PK11_FreeSlotList(friendlyList
);
1956 SECMOD_GetReadLock(moduleLock
);
1957 for(mlp
= modules
; mlp
!= NULL
; mlp
= mlp
->next
) {
1959 #if defined( XP_WIN32 )
1960 /* This is works around some horrible cache/page thrashing problems
1961 ** on Win32. Without this, this loop can take up to 6 seconds at
1962 ** 100% CPU on a Pentium-Pro 200. The thing this changes is to
1963 ** increase the size of the stack frame and modify it.
1964 ** Moving the loop code itself seems to have no effect.
1965 ** Dunno why this combination makes a difference, but it does.
1967 waste
[ j
& 0xf] = j
++;
1970 for (i
= 0; i
< mlp
->module
->slotCount
; i
++) {
1971 PK11SlotInfo
*slot
= mlp
->module
->slots
[i
];
1973 if (pk11_IsPresentCertLoad(slot
, loadCerts
)) {
1974 if (needRW
&& slot
->readOnly
) continue;
1975 if ((type
== CKM_INVALID_MECHANISM
)
1976 || PK11_DoesMechanism(slot
, type
)) {
1977 if (pk11_LoginStillRequired(slot
,wincx
)) {
1978 if (PK11_IsFriendly(slot
)) {
1979 PK11_AddSlotToList(friendlyList
, slot
);
1981 PK11_AddSlotToList(loginList
, slot
);
1984 PK11_AddSlotToList(list
, slot
);
1990 SECMOD_ReleaseReadLock(moduleLock
);
1992 PK11_MoveListToList(list
,friendlyList
);
1993 PK11_FreeSlotList(friendlyList
);
1994 PK11_MoveListToList(list
,loginList
);
1995 PK11_FreeSlotList(loginList
);
2001 * NOTE: This routine is working from a private List generated by
2002 * PK11_GetAllTokens. That is why it does not need to lock.
2005 PK11_GetPrivateKeyTokens(CK_MECHANISM_TYPE type
,PRBool needRW
,void *wincx
)
2007 PK11SlotList
*list
= PK11_GetAllTokens(type
,needRW
,PR_TRUE
,wincx
);
2008 PK11SlotListElement
*le
, *next
;
2011 if (list
== NULL
) return list
;
2013 for (le
= list
->head
; le
; le
= next
) {
2014 next
= le
->next
; /* save the pointer here in case we have to
2015 * free the element later */
2016 rv
= PK11_Authenticate(le
->slot
,PR_TRUE
,wincx
);
2017 if (rv
!= SECSuccess
) {
2018 PK11_DeleteSlotFromList(list
,le
);
2027 * find the best slot which supports the given
2028 * Mechanism. In normal cases this should grab the first slot on the list
2032 PK11_GetBestSlotMultiple(CK_MECHANISM_TYPE
*type
, int mech_count
, void *wincx
)
2034 PK11SlotList
*list
= NULL
;
2035 PK11SlotListElement
*le
;
2036 PK11SlotInfo
*slot
= NULL
;
2037 PRBool freeit
= PR_FALSE
;
2038 PRBool listNeedLogin
= PR_FALSE
;
2042 list
= PK11_GetSlotList(type
[0]);
2044 if ((list
== NULL
) || (list
->head
== NULL
)) {
2045 /* We need to look up all the tokens for the mechanism */
2046 list
= PK11_GetAllTokens(type
[0],PR_FALSE
,PR_TRUE
,wincx
);
2050 /* no one can do it! */
2052 PORT_SetError(SEC_ERROR_NO_TOKEN
);
2059 listNeedLogin
= PR_FALSE
;
2060 for (i
=0; i
< mech_count
; i
++) {
2061 if ((type
[i
] != CKM_FAKE_RANDOM
) &&
2062 (type
[i
] != CKM_SHA_1
) &&
2063 (type
[i
] != CKM_SHA256
) &&
2064 (type
[i
] != CKM_SHA384
) &&
2065 (type
[i
] != CKM_SHA512
) &&
2066 (type
[i
] != CKM_MD5
) &&
2067 (type
[i
] != CKM_MD2
)) {
2068 listNeedLogin
= PR_TRUE
;
2073 for (le
= PK11_GetFirstSafe(list
); le
;
2074 le
= PK11_GetNextSafe(list
,le
,PR_TRUE
)) {
2075 if (PK11_IsPresent(le
->slot
)) {
2076 PRBool doExit
= PR_FALSE
;
2077 for (i
=0; i
< mech_count
; i
++) {
2078 if (!PK11_DoesMechanism(le
->slot
,type
[i
])) {
2083 if (doExit
) continue;
2085 if (listNeedLogin
&& le
->slot
->needLogin
) {
2086 rv
= PK11_Authenticate(le
->slot
,PR_TRUE
,wincx
);
2087 if (rv
!= SECSuccess
) continue;
2090 PK11_ReferenceSlot(slot
);
2091 PK11_FreeSlotListElement(list
,le
);
2092 if (freeit
) { PK11_FreeSlotList(list
); }
2096 if (freeit
) { PK11_FreeSlotList(list
); }
2097 if (PORT_GetError() == 0) {
2098 PORT_SetError(SEC_ERROR_NO_TOKEN
);
2103 /* original get best slot now calls the multiple version with only one type */
2105 PK11_GetBestSlot(CK_MECHANISM_TYPE type
, void *wincx
)
2107 return PK11_GetBestSlotMultiple(&type
, 1, wincx
);
2111 PK11_GetBestKeyLength(PK11SlotInfo
*slot
,CK_MECHANISM_TYPE mechanism
)
2113 CK_MECHANISM_INFO mechanism_info
;
2116 if (!slot
->isThreadSafe
) PK11_EnterSlotMonitor(slot
);
2117 crv
= PK11_GETTAB(slot
)->C_GetMechanismInfo(slot
->slotID
,
2118 mechanism
,&mechanism_info
);
2119 if (!slot
->isThreadSafe
) PK11_ExitSlotMonitor(slot
);
2120 if (crv
!= CKR_OK
) return 0;
2122 if (mechanism_info
.ulMinKeySize
== mechanism_info
.ulMaxKeySize
)
2124 return mechanism_info
.ulMaxKeySize
;
2129 * This function uses the existing PKCS #11 module to find the
2130 * longest supported key length in the preferred token for a mechanism.
2131 * This varies from the above function in that 1) it returns the key length
2132 * even for fixed key algorithms, and 2) it looks through the tokens
2133 * generally rather than for a specific token. This is used in liu of
2134 * a PK11_GetKeyLength function in pk11mech.c since we can actually read
2135 * supported key lengths from PKCS #11.
2137 * For symmetric key operations the length is returned in bytes.
2140 PK11_GetMaxKeyLength(CK_MECHANISM_TYPE mechanism
)
2142 CK_MECHANISM_INFO mechanism_info
;
2143 PK11SlotList
*list
= NULL
;
2144 PK11SlotListElement
*le
;
2145 PRBool freeit
= PR_FALSE
;
2148 list
= PK11_GetSlotList(mechanism
);
2150 if ((list
== NULL
) || (list
->head
== NULL
)) {
2151 /* We need to look up all the tokens for the mechanism */
2152 list
= PK11_GetAllTokens(mechanism
,PR_FALSE
,PR_FALSE
,NULL
);
2156 /* no tokens recognize this mechanism */
2158 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM
);
2162 for (le
= PK11_GetFirstSafe(list
); le
;
2163 le
= PK11_GetNextSafe(list
,le
,PR_TRUE
)) {
2164 PK11SlotInfo
*slot
= le
->slot
;
2166 if (PK11_IsPresent(slot
)) {
2167 if (!slot
->isThreadSafe
) PK11_EnterSlotMonitor(slot
);
2168 crv
= PK11_GETTAB(slot
)->C_GetMechanismInfo(slot
->slotID
,
2169 mechanism
,&mechanism_info
);
2170 if (!slot
->isThreadSafe
) PK11_ExitSlotMonitor(slot
);
2171 if ((crv
== CKR_OK
) && (mechanism_info
.ulMaxKeySize
!= 0)
2172 && (mechanism_info
.ulMaxKeySize
!= 0xffffffff)) {
2173 keyLength
= mechanism_info
.ulMaxKeySize
;
2178 if (freeit
) { PK11_FreeSlotList(list
); }
2183 PK11_SeedRandom(PK11SlotInfo
*slot
, unsigned char *data
, int len
) {
2186 PK11_EnterSlotMonitor(slot
);
2187 crv
= PK11_GETTAB(slot
)->C_SeedRandom(slot
->session
, data
, (CK_ULONG
)len
);
2188 PK11_ExitSlotMonitor(slot
);
2189 if (crv
!= CKR_OK
) {
2190 PORT_SetError(PK11_MapError(crv
));
2198 PK11_GenerateRandomOnSlot(PK11SlotInfo
*slot
, unsigned char *data
, int len
) {
2201 if (!slot
->isInternal
) PK11_EnterSlotMonitor(slot
);
2202 crv
= PK11_GETTAB(slot
)->C_GenerateRandom(slot
->session
,data
,
2204 if (!slot
->isInternal
) PK11_ExitSlotMonitor(slot
);
2205 if (crv
!= CKR_OK
) {
2206 PORT_SetError(PK11_MapError(crv
));
2212 /* Attempts to update the Best Slot for "FAKE RANDOM" generation.
2213 ** If that's not the internal slot, then it also attempts to update the
2215 ** The return value indicates if the INTERNAL slot was updated OK.
2218 PK11_RandomUpdate(void *data
, size_t bytes
)
2221 PRBool bestIsInternal
;
2224 slot
= PK11_GetBestSlot(CKM_FAKE_RANDOM
, NULL
);
2226 slot
= PK11_GetInternalSlot();
2231 bestIsInternal
= PK11_IsInternal(slot
);
2232 status
= PK11_SeedRandom(slot
, data
, bytes
);
2233 PK11_FreeSlot(slot
);
2235 if (!bestIsInternal
) {
2236 /* do internal slot, too. */
2237 slot
= PK11_GetInternalSlot(); /* can't fail */
2238 status
= PK11_SeedRandom(slot
, data
, bytes
);
2239 PK11_FreeSlot(slot
);
2246 PK11_GenerateRandom(unsigned char *data
,int len
) {
2250 slot
= PK11_GetBestSlot(CKM_FAKE_RANDOM
,NULL
);
2251 if (slot
== NULL
) return SECFailure
;
2253 rv
= PK11_GenerateRandomOnSlot(slot
, data
, len
);
2254 PK11_FreeSlot(slot
);
2259 * Reset the token to it's initial state. For the internal module, this will
2260 * Purge your keydb, and reset your cert db certs to USER_INIT.
2263 PK11_ResetToken(PK11SlotInfo
*slot
, char *sso_pwd
)
2265 unsigned char tokenName
[32];
2269 /* reconstruct the token name */
2270 tokenNameLen
= PORT_Strlen(slot
->token_name
);
2271 if (tokenNameLen
> sizeof(tokenName
)) {
2272 tokenNameLen
= sizeof(tokenName
);
2275 PORT_Memcpy(tokenName
,slot
->token_name
,tokenNameLen
);
2276 if (tokenNameLen
< sizeof(tokenName
)) {
2277 PORT_Memset(&tokenName
[tokenNameLen
],' ',
2278 sizeof(tokenName
)-tokenNameLen
);
2281 /* initialize the token */
2282 PK11_EnterSlotMonitor(slot
);
2284 /* first shutdown the token. Existing sessions will get closed here */
2285 PK11_GETTAB(slot
)->C_CloseAllSessions(slot
->slotID
);
2286 slot
->session
= CK_INVALID_SESSION
;
2288 /* now re-init the token */
2289 crv
= PK11_GETTAB(slot
)->C_InitToken(slot
->slotID
,
2290 (unsigned char *)sso_pwd
, sso_pwd
? PORT_Strlen(sso_pwd
): 0, tokenName
);
2292 /* finally bring the token back up */
2293 PK11_InitToken(slot
,PR_TRUE
);
2294 PK11_ExitSlotMonitor(slot
);
2295 if (crv
!= CKR_OK
) {
2296 PORT_SetError(PK11_MapError(crv
));
2299 nssTrustDomain_UpdateCachedTokenCerts(slot
->nssToken
->trustDomain
,
2304 PK11Slot_SetNSSToken(PK11SlotInfo
*sl
, NSSToken
*nsst
)
2306 sl
->nssToken
= nsst
;
2310 PK11Slot_GetNSSToken(PK11SlotInfo
*sl
)
2312 return sl
->nssToken
;
2316 * wait for a token to change it's state. The application passes in the expected
2317 * new state in event.
2320 PK11_WaitForTokenEvent(PK11SlotInfo
*slot
, PK11TokenEvent event
,
2321 PRIntervalTime timeout
, PRIntervalTime latency
, int series
)
2323 PRIntervalTime first_time
= 0;
2324 PRBool first_time_set
= PR_FALSE
;
2325 PRBool waitForRemoval
;
2328 return PK11TokenNotRemovable
;
2331 latency
= PR_SecondsToInterval(5);
2333 waitForRemoval
= (PRBool
) (event
== PK11TokenRemovedOrChangedEvent
);
2336 series
= PK11_GetSlotSeries(slot
);
2338 while (PK11_IsPresent(slot
) == waitForRemoval
) {
2339 PRIntervalTime interval
;
2341 if (waitForRemoval
&& series
!= PK11_GetSlotSeries(slot
)) {
2342 return PK11TokenChanged
;
2344 if (timeout
== PR_INTERVAL_NO_WAIT
) {
2345 return waitForRemoval
? PK11TokenPresent
: PK11TokenRemoved
;
2347 if (timeout
!= PR_INTERVAL_NO_TIMEOUT
) {
2348 interval
= PR_IntervalNow();
2349 if (!first_time_set
) {
2350 first_time
= interval
;
2351 first_time_set
= PR_TRUE
;
2353 if ((interval
-first_time
) > timeout
) {
2354 return waitForRemoval
? PK11TokenPresent
: PK11TokenRemoved
;
2359 return waitForRemoval
? PK11TokenRemoved
: PK11TokenPresent
;