4 * This is free software; see Copyright file in the source
5 * distribution for preciese wording.
7 * Copyright..................................
9 * Contributor(s): _____________________________
14 * In order to ensure that particular crypto operation is performed on
15 * particular crypto device, a subclass of xmlSecList is used to store slot and
16 * mechanism information.
18 * In the list, a slot is bound with a mechanism. If the mechanism is available,
19 * this mechanism only can perform on the slot; otherwise, it can perform on
20 * every eligibl slot in the list.
22 * When try to find a slot for a particular mechanism, the slot bound with
23 * available mechanism will be looked up firstly.
28 #include <xmlsec/xmlsec.h>
29 #include <xmlsec/errors.h>
30 #include <xmlsec/list.h>
32 #include <xmlsec/nss/tokens.h>
35 xmlSecNssKeySlotSetMechList(
36 xmlSecNssKeySlotPtr keySlot
,
37 CK_MECHANISM_TYPE_PTR mechanismList
41 xmlSecAssert2( keySlot
!= NULL
, -1 ) ;
43 if( keySlot
->mechanismList
!= CK_NULL_PTR
) {
44 xmlFree( keySlot
->mechanismList
) ;
46 for( counter
= 0 ; *( mechanismList
+ counter
) != CKM_INVALID_MECHANISM
; counter
++ ) ;
47 keySlot
->mechanismList
= ( CK_MECHANISM_TYPE_PTR
)xmlMalloc( ( counter
+ 1 ) * sizeof( CK_MECHANISM_TYPE
) ) ;
48 if( keySlot
->mechanismList
== NULL
) {
49 xmlSecError( XMLSEC_ERRORS_HERE
,
52 XMLSEC_ERRORS_R_XMLSEC_FAILED
,
53 XMLSEC_ERRORS_NO_MESSAGE
) ;
56 for( ; counter
>= 0 ; counter
-- )
57 *( keySlot
->mechanismList
+ counter
) = *( mechanismList
+ counter
) ;
64 xmlSecNssKeySlotEnableMech(
65 xmlSecNssKeySlotPtr keySlot
,
66 CK_MECHANISM_TYPE mechanism
69 CK_MECHANISM_TYPE_PTR newList
;
71 xmlSecAssert2( keySlot
!= NULL
, -1 ) ;
73 if( mechanism
!= CKM_INVALID_MECHANISM
) {
74 for( counter
= 0 ; *( keySlot
->mechanismList
+ counter
) != CKM_INVALID_MECHANISM
; counter
++ ) ;
75 newList
= ( CK_MECHANISM_TYPE_PTR
)xmlMalloc( ( counter
+ 1 + 1 ) * sizeof( CK_MECHANISM_TYPE
) ) ;
76 if( newList
== NULL
) {
77 xmlSecError( XMLSEC_ERRORS_HERE
,
80 XMLSEC_ERRORS_R_XMLSEC_FAILED
,
81 XMLSEC_ERRORS_NO_MESSAGE
) ;
84 *( newList
+ counter
+ 1 ) = CKM_INVALID_MECHANISM
;
85 *( newList
+ counter
) = mechanism
;
86 for( counter
-= 1 ; counter
>= 0 ; counter
-- )
87 *( newList
+ counter
) = *( keySlot
->mechanismList
+ counter
) ;
89 xmlFree( keySlot
->mechanismList
) ;
90 keySlot
->mechanismList
= newList
;
97 xmlSecNssKeySlotDisableMech(
98 xmlSecNssKeySlotPtr keySlot
,
99 CK_MECHANISM_TYPE mechanism
103 xmlSecAssert2( keySlot
!= NULL
, -1 ) ;
105 for( counter
= 0 ; *( keySlot
->mechanismList
+ counter
) != CKM_INVALID_MECHANISM
; counter
++ ) {
106 if( *( keySlot
->mechanismList
+ counter
) == mechanism
) {
107 for( ; *( keySlot
->mechanismList
+ counter
) != CKM_INVALID_MECHANISM
; counter
++ ) {
108 *( keySlot
->mechanismList
+ counter
) = *( keySlot
->mechanismList
+ counter
+ 1 ) ;
118 CK_MECHANISM_TYPE_PTR
119 xmlSecNssKeySlotGetMechList(
120 xmlSecNssKeySlotPtr keySlot
122 if( keySlot
!= NULL
)
123 return keySlot
->mechanismList
;
129 xmlSecNssKeySlotSetSlot(
130 xmlSecNssKeySlotPtr keySlot
,
133 xmlSecAssert2( keySlot
!= NULL
, -1 ) ;
135 if( slot
!= NULL
&& keySlot
->slot
!= slot
) {
136 if( keySlot
->slot
!= NULL
)
137 PK11_FreeSlot( keySlot
->slot
) ;
139 if( keySlot
->mechanismList
!= NULL
) {
140 xmlFree( keySlot
->mechanismList
) ;
141 keySlot
->mechanismList
= NULL
;
144 keySlot
->slot
= PK11_ReferenceSlot( slot
) ;
151 xmlSecNssKeySlotInitialize(
152 xmlSecNssKeySlotPtr keySlot
,
155 xmlSecAssert2( keySlot
!= NULL
, -1 ) ;
156 xmlSecAssert2( keySlot
->slot
== NULL
, -1 ) ;
157 xmlSecAssert2( keySlot
->mechanismList
== NULL
, -1 ) ;
160 keySlot
->slot
= PK11_ReferenceSlot( slot
) ;
167 xmlSecNssKeySlotFinalize(
168 xmlSecNssKeySlotPtr keySlot
170 xmlSecAssert( keySlot
!= NULL
) ;
172 if( keySlot
->mechanismList
!= NULL
) {
173 xmlFree( keySlot
->mechanismList
) ;
174 keySlot
->mechanismList
= NULL
;
177 if( keySlot
->slot
!= NULL
) {
178 PK11_FreeSlot( keySlot
->slot
) ;
179 keySlot
->slot
= NULL
;
185 xmlSecNssKeySlotGetSlot(
186 xmlSecNssKeySlotPtr keySlot
188 if( keySlot
!= NULL
)
189 return keySlot
->slot
;
195 xmlSecNssKeySlotCreate() {
196 xmlSecNssKeySlotPtr keySlot
;
198 /* Allocates a new xmlSecNssKeySlot and fill the fields */
199 keySlot
= ( xmlSecNssKeySlotPtr
)xmlMalloc( sizeof( xmlSecNssKeySlot
) ) ;
200 if( keySlot
== NULL
) {
201 xmlSecError( XMLSEC_ERRORS_HERE
,
204 XMLSEC_ERRORS_R_XMLSEC_FAILED
,
205 XMLSEC_ERRORS_NO_MESSAGE
) ;
208 memset( keySlot
, 0, sizeof( xmlSecNssKeySlot
) ) ;
214 xmlSecNssKeySlotCopy(
215 xmlSecNssKeySlotPtr newKeySlot
,
216 xmlSecNssKeySlotPtr keySlot
218 CK_MECHANISM_TYPE_PTR mech
;
221 xmlSecAssert2( newKeySlot
!= NULL
, -1 ) ;
222 xmlSecAssert2( keySlot
!= NULL
, -1 ) ;
224 if( keySlot
->slot
!= NULL
&& newKeySlot
->slot
!= keySlot
->slot
) {
225 if( newKeySlot
->slot
!= NULL
)
226 PK11_FreeSlot( newKeySlot
->slot
) ;
228 newKeySlot
->slot
= PK11_ReferenceSlot( keySlot
->slot
) ;
231 if( keySlot
->mechanismList
!= CK_NULL_PTR
) {
232 xmlFree( newKeySlot
->mechanismList
) ;
234 for( counter
= 0 ; *( keySlot
->mechanismList
+ counter
) != CKM_INVALID_MECHANISM
; counter
++ ) ;
235 newKeySlot
->mechanismList
= ( CK_MECHANISM_TYPE_PTR
)xmlMalloc( ( counter
+ 1 ) * sizeof( CK_MECHANISM_TYPE
) ) ;
236 if( newKeySlot
->mechanismList
== NULL
) {
237 xmlSecError( XMLSEC_ERRORS_HERE
,
240 XMLSEC_ERRORS_R_XMLSEC_FAILED
,
241 XMLSEC_ERRORS_NO_MESSAGE
) ;
244 for( ; counter
>= 0 ; counter
-- )
245 *( newKeySlot
->mechanismList
+ counter
) = *( keySlot
->mechanismList
+ counter
) ;
252 xmlSecNssKeySlotDuplicate(
253 xmlSecNssKeySlotPtr keySlot
255 xmlSecNssKeySlotPtr newKeySlot
;
258 xmlSecAssert2( keySlot
!= NULL
, NULL
) ;
260 newKeySlot
= xmlSecNssKeySlotCreate() ;
261 if( newKeySlot
== NULL
) {
262 xmlSecError( XMLSEC_ERRORS_HERE
,
265 XMLSEC_ERRORS_R_XMLSEC_FAILED
,
266 XMLSEC_ERRORS_NO_MESSAGE
) ;
270 if( xmlSecNssKeySlotCopy( newKeySlot
, keySlot
) < 0 ) {
271 xmlSecError( XMLSEC_ERRORS_HERE
,
274 XMLSEC_ERRORS_R_XMLSEC_FAILED
,
275 XMLSEC_ERRORS_NO_MESSAGE
) ;
279 return( newKeySlot
);
283 xmlSecNssKeySlotDestroy(
284 xmlSecNssKeySlotPtr keySlot
286 xmlSecAssert( keySlot
!= NULL
) ;
288 if( keySlot
->mechanismList
!= NULL
)
289 xmlFree( keySlot
->mechanismList
) ;
291 if( keySlot
->slot
!= NULL
)
292 PK11_FreeSlot( keySlot
->slot
) ;
298 xmlSecNssKeySlotBindMech(
299 xmlSecNssKeySlotPtr keySlot
,
300 CK_MECHANISM_TYPE type
304 xmlSecAssert2( keySlot
!= NULL
, 0 ) ;
305 xmlSecAssert2( keySlot
->slot
!= NULL
, 0 ) ;
306 xmlSecAssert2( type
!= CKM_INVALID_MECHANISM
, 0 ) ;
308 for( counter
= 0 ; *( keySlot
->mechanismList
+ counter
) != CKM_INVALID_MECHANISM
; counter
++ ) {
309 if( *( keySlot
->mechanismList
+ counter
) == type
)
317 xmlSecNssKeySlotSupportMech(
318 xmlSecNssKeySlotPtr keySlot
,
319 CK_MECHANISM_TYPE type
321 xmlSecAssert2( keySlot
!= NULL
, 0 ) ;
322 xmlSecAssert2( keySlot
->slot
!= NULL
, 0 ) ;
323 xmlSecAssert2( type
!= CKM_INVALID_MECHANISM
, 0 ) ;
325 if( PK11_DoesMechanism( keySlot
->slot
, type
) == PR_TRUE
) {
332 xmlSecNssKeySlotDebugDump(
333 xmlSecNssKeySlotPtr keySlot
,
336 xmlSecAssert( keySlot
!= NULL
) ;
337 xmlSecAssert( output
!= NULL
) ;
339 fprintf( output
, "== KEY SLOT\n" );
343 xmlSecNssKeySlotDebugXmlDump(
344 xmlSecNssKeySlotPtr keySlot
,
352 #ifdef __MINGW32__ // for runtime-pseudo-reloc
353 static struct _xmlSecPtrListKlass xmlSecNssKeySlotPtrListKlass
= {
355 static xmlSecPtrListKlass xmlSecNssKeySlotPtrListKlass
= {
357 BAD_CAST
"mechanism-list",
358 (xmlSecPtrDuplicateItemMethod
)xmlSecNssKeySlotDuplicate
,
359 (xmlSecPtrDestroyItemMethod
)xmlSecNssKeySlotDestroy
,
360 (xmlSecPtrDebugDumpItemMethod
)xmlSecNssKeySlotDebugDump
,
361 (xmlSecPtrDebugDumpItemMethod
)xmlSecNssKeySlotDebugXmlDump
,
365 xmlSecNssKeySlotListGetKlass(void) {
366 return(&xmlSecNssKeySlotPtrListKlass
);
371 * Global PKCS#11 crypto token repository -- Key slot list
373 static xmlSecPtrListPtr _xmlSecNssKeySlotList
= NULL
;
377 CK_MECHANISM_TYPE type
379 PK11SlotInfo
* slot
= NULL
;
380 xmlSecNssKeySlotPtr keySlot
;
385 if( _xmlSecNssKeySlotList
== NULL
) {
386 slot
= PK11_GetBestSlot( type
, NULL
) ;
388 ksSize
= xmlSecPtrListGetSize( _xmlSecNssKeySlotList
) ;
391 * Firstly, checking whether the mechanism is bound with a special slot.
392 * If no bound slot, we try to find the first eligible slot in the list.
394 for( flag
= 0, ksPos
= 0 ; ksPos
< ksSize
; ksPos
++ ) {
395 keySlot
= ( xmlSecNssKeySlotPtr
)xmlSecPtrListGetItem( _xmlSecNssKeySlotList
, ksPos
) ;
396 if( keySlot
!= NULL
&& xmlSecNssKeySlotBindMech( keySlot
, type
) ) {
397 slot
= xmlSecNssKeySlotGetSlot( keySlot
) ;
399 } else if( flag
== 0 && xmlSecNssKeySlotSupportMech( keySlot
, type
) ) {
400 slot
= xmlSecNssKeySlotGetSlot( keySlot
) ;
408 slot
= PK11_ReferenceSlot( slot
) ;
411 if( slot
!= NULL
&& PK11_NeedLogin( slot
) ) {
412 if( PK11_Authenticate( slot
, PR_TRUE
, NULL
) != SECSuccess
) {
413 xmlSecError( XMLSEC_ERRORS_HERE
,
416 XMLSEC_ERRORS_R_XMLSEC_FAILED
,
417 XMLSEC_ERRORS_NO_MESSAGE
) ;
418 PK11_FreeSlot( slot
) ;
427 xmlSecNssSlotInitialize(
430 if( _xmlSecNssKeySlotList
!= NULL
) {
431 xmlSecPtrListDestroy( _xmlSecNssKeySlotList
) ;
432 _xmlSecNssKeySlotList
= NULL
;
435 _xmlSecNssKeySlotList
= xmlSecPtrListCreate( xmlSecNssKeySlotListId
) ;
436 if( _xmlSecNssKeySlotList
== NULL
) {
437 xmlSecError( XMLSEC_ERRORS_HERE
,
440 XMLSEC_ERRORS_R_XMLSEC_FAILED
,
441 XMLSEC_ERRORS_NO_MESSAGE
) ;
449 xmlSecNssSlotShutdown(
452 if( _xmlSecNssKeySlotList
!= NULL
) {
453 xmlSecPtrListDestroy( _xmlSecNssKeySlotList
) ;
454 _xmlSecNssKeySlotList
= NULL
;
461 CK_MECHANISM_TYPE type
463 xmlSecNssKeySlotPtr keySlot
;
468 xmlSecAssert2( _xmlSecNssKeySlotList
!= NULL
, -1 ) ;
469 xmlSecAssert2( slot
!= NULL
, -1 ) ;
471 ksSize
= xmlSecPtrListGetSize( _xmlSecNssKeySlotList
) ;
474 * Firstly, checking whether the slot is in the repository already.
477 for( ksPos
= 0 ; ksPos
< ksSize
; ksPos
++ ) {
478 keySlot
= ( xmlSecNssKeySlotPtr
)xmlSecPtrListGetItem( _xmlSecNssKeySlotList
, ksPos
) ;
479 /* If find the slot in the list */
480 if( keySlot
!= NULL
&& xmlSecNssKeySlotGetSlot( keySlot
) == slot
) {
481 /* If mechnism type is valid, bind the slot with the mechanism */
482 if( type
!= CKM_INVALID_MECHANISM
) {
483 if( xmlSecNssKeySlotEnableMech( keySlot
, type
) < 0 ) {
484 xmlSecError( XMLSEC_ERRORS_HERE
,
487 XMLSEC_ERRORS_R_XMLSEC_FAILED
,
488 XMLSEC_ERRORS_NO_MESSAGE
) ;
497 /* If the slot do not in the list, add a new item to the list */
499 /* Create a new KeySlot */
500 keySlot
= xmlSecNssKeySlotCreate() ;
501 if( keySlot
== NULL
) {
502 xmlSecError( XMLSEC_ERRORS_HERE
,
505 XMLSEC_ERRORS_R_XMLSEC_FAILED
,
506 XMLSEC_ERRORS_NO_MESSAGE
) ;
510 /* Initialize the keySlot with a slot */
511 if( xmlSecNssKeySlotInitialize( keySlot
, slot
) < 0 ) {
512 xmlSecError( XMLSEC_ERRORS_HERE
,
515 XMLSEC_ERRORS_R_XMLSEC_FAILED
,
516 XMLSEC_ERRORS_NO_MESSAGE
) ;
517 xmlSecNssKeySlotDestroy( keySlot
) ;
521 /* If mechnism type is valid, bind the slot with the mechanism */
522 if( type
!= CKM_INVALID_MECHANISM
) {
523 if( xmlSecNssKeySlotEnableMech( keySlot
, type
) < 0 ) {
524 xmlSecError( XMLSEC_ERRORS_HERE
,
527 XMLSEC_ERRORS_R_XMLSEC_FAILED
,
528 XMLSEC_ERRORS_NO_MESSAGE
) ;
529 xmlSecNssKeySlotDestroy( keySlot
) ;
534 /* Add keySlot into the list */
535 if( xmlSecPtrListAdd( _xmlSecNssKeySlotList
, keySlot
) < 0 ) {
536 xmlSecError( XMLSEC_ERRORS_HERE
,
539 XMLSEC_ERRORS_R_XMLSEC_FAILED
,
540 XMLSEC_ERRORS_NO_MESSAGE
) ;
541 xmlSecNssKeySlotDestroy( keySlot
) ;