2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include "pkcs11_library.h"
22 #include <threading/mutex.h>
23 #include <utils/linked_list.h>
25 typedef struct private_pkcs11_library_t private_pkcs11_library_t
;
28 ENUM_BEGIN(ck_rv_names
, CKR_OK
, CKR_CANT_LOCK
,
38 "NEED_TO_CREATE_THREADS",
40 ENUM_NEXT(ck_rv_names
, CKR_ATTRIBUTE_READ_ONLY
, CKR_ATTRIBUTE_VALUE_INVALID
,
42 "ATTRIBUTE_READ_ONLY",
43 "ATTRIBUTE_SENSITIVE",
44 "ATTRIBUTE_TYPE_INVALID",
45 "ATTRIBUTE_VALUE_INVALID");
46 ENUM_NEXT(ck_rv_names
, CKR_DATA_INVALID
, CKR_DATA_LEN_RANGE
,
47 CKR_ATTRIBUTE_VALUE_INVALID
,
50 ENUM_NEXT(ck_rv_names
, CKR_DEVICE_ERROR
, CKR_DEVICE_REMOVED
,
55 ENUM_NEXT(ck_rv_names
, CKR_ENCRYPTED_DATA_INVALID
, CKR_ENCRYPTED_DATA_LEN_RANGE
,
57 "ENCRYPTED_DATA_INVALID",
58 "ENCRYPTED_DATA_LEN_RANGE");
59 ENUM_NEXT(ck_rv_names
, CKR_FUNCTION_CANCELED
, CKR_FUNCTION_NOT_SUPPORTED
,
60 CKR_ENCRYPTED_DATA_LEN_RANGE
,
62 "FUNCTION_NOT_PARALLEL",
65 "FUNCTION_NOT_SUPPORTED");
66 ENUM_NEXT(ck_rv_names
, CKR_KEY_HANDLE_INVALID
, CKR_KEY_UNEXTRACTABLE
,
67 CKR_FUNCTION_NOT_SUPPORTED
,
71 "KEY_TYPE_INCONSISTENT",
76 "KEY_FUNCTION_NOT_PERMITTED",
79 ENUM_NEXT(ck_rv_names
, CKR_MECHANISM_INVALID
, CKR_MECHANISM_PARAM_INVALID
,
80 CKR_KEY_UNEXTRACTABLE
,
82 "MECHANISM_PARAM_INVALID");
83 ENUM_NEXT(ck_rv_names
, CKR_OBJECT_HANDLE_INVALID
, CKR_OBJECT_HANDLE_INVALID
,
84 CKR_MECHANISM_PARAM_INVALID
,
85 "OBJECT_HANDLE_INVALID");
86 ENUM_NEXT(ck_rv_names
, CKR_OPERATION_ACTIVE
, CKR_OPERATION_NOT_INITIALIZED
,
87 CKR_OBJECT_HANDLE_INVALID
,
89 "OPERATION_NOT_INITIALIZED");
90 ENUM_NEXT(ck_rv_names
, CKR_PIN_INCORRECT
, CKR_PIN_LOCKED
,
91 CKR_OPERATION_NOT_INITIALIZED
,
97 ENUM_NEXT(ck_rv_names
, CKR_SESSION_CLOSED
, CKR_SESSION_READ_WRITE_SO_EXISTS
,
102 "SESSION_HANDLE_INVALID",
103 "SESSION_PARALLEL_NOT_SUPPORTED",
106 "SESSION_READ_ONLY_EXISTS",
107 "SESSION_READ_WRITE_SO_EXISTS");
108 ENUM_NEXT(ck_rv_names
, CKR_SIGNATURE_INVALID
, CKR_SIGNATURE_LEN_RANGE
,
109 CKR_SESSION_READ_WRITE_SO_EXISTS
,
111 "SIGNATURE_LEN_RANGE");
112 ENUM_NEXT(ck_rv_names
, CKR_TEMPLATE_INCOMPLETE
, CKR_TEMPLATE_INCONSISTENT
,
113 CKR_SIGNATURE_LEN_RANGE
,
114 "TEMPLATE_INCOMPLETE",
115 "TEMPLATE_INCONSISTENT",
117 ENUM_NEXT(ck_rv_names
, CKR_TOKEN_NOT_PRESENT
, CKR_TOKEN_WRITE_PROTECTED
,
118 CKR_TEMPLATE_INCONSISTENT
,
120 "TOKEN_NOT_RECOGNIZED",
121 "TOKEN_WRITE_PROTECTED");
122 ENUM_NEXT(ck_rv_names
, CKR_UNWRAPPING_KEY_HANDLE_INVALID
, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT
,
123 CKR_TOKEN_WRITE_PROTECTED
,
124 "UNWRAPPING_KEY_HANDLE_INVALID",
125 "UNWRAPPING_KEY_SIZE_RANGE",
126 "UNWRAPPING_KEY_TYPE_INCONSISTENT");
127 ENUM_NEXT(ck_rv_names
, CKR_USER_ALREADY_LOGGED_IN
, CKR_USER_TOO_MANY_TYPES
,
128 CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT
,
129 "USER_ALREADY_LOGGED_IN",
130 "USER_NOT_LOGGED_IN",
131 "USER_PIN_NOT_INITIALIZED",
133 "USER_ANOTHER_ALREADY_LOGGED_IN",
134 "USER_TOO_MANY_TYPES");
135 ENUM_NEXT(ck_rv_names
, CKR_WRAPPED_KEY_INVALID
, CKR_WRAPPING_KEY_TYPE_INCONSISTENT
,
136 CKR_USER_TOO_MANY_TYPES
,
137 "WRAPPED_KEY_INVALID",
139 "WRAPPED_KEY_LEN_RANGE",
140 "WRAPPING_KEY_HANDLE_INVALID",
141 "WRAPPING_KEY_SIZE_RANGE",
142 "WRAPPING_KEY_TYPE_INCONSISTENT");
143 ENUM_NEXT(ck_rv_names
, CKR_RANDOM_SEED_NOT_SUPPORTED
, CKR_RANDOM_NO_RNG
,
144 CKR_WRAPPING_KEY_TYPE_INCONSISTENT
,
145 "RANDOM_SEED_NOT_SUPPORTED",
147 ENUM_NEXT(ck_rv_names
, CKR_DOMAIN_PARAMS_INVALID
, CKR_DOMAIN_PARAMS_INVALID
,
149 "DOMAIN_PARAMS_INVALID");
150 ENUM_NEXT(ck_rv_names
, CKR_BUFFER_TOO_SMALL
, CKR_BUFFER_TOO_SMALL
,
151 CKR_DOMAIN_PARAMS_INVALID
,
153 ENUM_NEXT(ck_rv_names
, CKR_SAVED_STATE_INVALID
, CKR_SAVED_STATE_INVALID
,
154 CKR_BUFFER_TOO_SMALL
,
155 "SAVED_STATE_INVALID");
156 ENUM_NEXT(ck_rv_names
, CKR_INFORMATION_SENSITIVE
, CKR_INFORMATION_SENSITIVE
,
157 CKR_SAVED_STATE_INVALID
,
158 "INFORMATION_SENSITIVE");
159 ENUM_NEXT(ck_rv_names
, CKR_STATE_UNSAVEABLE
, CKR_STATE_UNSAVEABLE
,
160 CKR_INFORMATION_SENSITIVE
,
162 ENUM_NEXT(ck_rv_names
, CKR_CRYPTOKI_NOT_INITIALIZED
, CKR_CRYPTOKI_ALREADY_INITIALIZED
,
163 CKR_STATE_UNSAVEABLE
,
164 "CRYPTOKI_NOT_INITIALIZED",
165 "CRYPTOKI_ALREADY_INITIALIZED");
166 ENUM_NEXT(ck_rv_names
, CKR_MUTEX_BAD
, CKR_MUTEX_NOT_LOCKED
,
167 CKR_CRYPTOKI_ALREADY_INITIALIZED
,
170 ENUM_NEXT(ck_rv_names
, CKR_FUNCTION_REJECTED
, CKR_FUNCTION_REJECTED
,
171 CKR_MUTEX_NOT_LOCKED
,
172 "FUNCTION_REJECTED");
173 ENUM_END(ck_rv_names
, CKR_FUNCTION_REJECTED
);
176 ENUM_BEGIN(ck_mech_names
, CKM_RSA_PKCS_KEY_PAIR_GEN
, CKM_DSA_SHA1
,
177 "RSA_PKCS_KEY_PAIR_GEN",
184 "RIPEMD128_RSA_PKCS",
185 "RIPEMD160_RSA_PKCS",
187 "RSA_X9_31_KEY_PAIR_GEN",
196 ENUM_NEXT(ck_mech_names
, CKM_DH_PKCS_KEY_PAIR_GEN
, CKM_DH_PKCS_DERIVE
,
198 "DH_PKCS_KEY_PAIR_GEN",
200 ENUM_NEXT(ck_mech_names
, CKM_X9_42_DH_KEY_PAIR_GEN
, CKM_X9_42_MQV_DERIVE
,
202 "X9_42_DH_KEY_PAIR_GEN",
204 "X9_42_DH_HYBRID_DERIVE",
206 ENUM_NEXT(ck_mech_names
, CKM_SHA256_RSA_PKCS
, CKM_SHA512_RSA_PKCS_PSS
,
207 CKM_X9_42_MQV_DERIVE
,
211 "SHA256_RSA_PKCS_PSS",
212 "SHA384_RSA_PKCS_PSS",
213 "SHA512_RSA_PKCS_PSS");
214 ENUM_NEXT(ck_mech_names
, CKM_RC2_KEY_GEN
, CKM_RC2_CBC_PAD
,
215 CKM_SHA512_RSA_PKCS_PSS
,
222 ENUM_NEXT(ck_mech_names
, CKM_RC4_KEY_GEN
, CKM_RC4
,
226 ENUM_NEXT(ck_mech_names
, CKM_DES_KEY_GEN
, CKM_DES_CBC_PAD
,
234 ENUM_NEXT(ck_mech_names
, CKM_DES2_KEY_GEN
, CKM_DES3_CBC_PAD
,
243 ENUM_NEXT(ck_mech_names
, CKM_CDMF_KEY_GEN
, CKM_CDMF_CBC_PAD
,
251 ENUM_NEXT(ck_mech_names
, CKM_MD2
, CKM_MD2_HMAC_GENERAL
,
256 ENUM_NEXT(ck_mech_names
, CKM_MD5
, CKM_MD5_HMAC_GENERAL
,
257 CKM_MD2_HMAC_GENERAL
,
261 ENUM_NEXT(ck_mech_names
, CKM_SHA_1
, CKM_SHA_1_HMAC_GENERAL
,
262 CKM_MD5_HMAC_GENERAL
,
265 "SHA_1_HMAC_GENERAL");
266 ENUM_NEXT(ck_mech_names
, CKM_RIPEMD128
, CKM_RIPEMD128_HMAC_GENERAL
,
267 CKM_SHA_1_HMAC_GENERAL
,
270 "RIPEMD128_HMAC_GENERAL");
271 ENUM_NEXT(ck_mech_names
, CKM_RIPEMD160
, CKM_RIPEMD160_HMAC_GENERAL
,
272 CKM_RIPEMD128_HMAC_GENERAL
,
275 "RIPEMD160_HMAC_GENERAL");
276 ENUM_NEXT(ck_mech_names
, CKM_SHA256
, CKM_SHA256_HMAC_GENERAL
,
277 CKM_RIPEMD160_HMAC_GENERAL
,
280 "SHA256_HMAC_GENERAL");
281 ENUM_NEXT(ck_mech_names
, CKM_SHA384
, CKM_SHA384_HMAC_GENERAL
,
282 CKM_SHA256_HMAC_GENERAL
,
285 "SHA384_HMAC_GENERAL");
286 ENUM_NEXT(ck_mech_names
, CKM_SHA512
, CKM_SHA512_HMAC_GENERAL
,
287 CKM_SHA384_HMAC_GENERAL
,
290 "SHA512_HMAC_GENERAL");
291 ENUM_NEXT(ck_mech_names
, CKM_CAST_KEY_GEN
, CKM_CAST_CBC_PAD
,
292 CKM_SHA512_HMAC_GENERAL
,
299 ENUM_NEXT(ck_mech_names
, CKM_CAST3_KEY_GEN
, CKM_CAST3_CBC_PAD
,
307 ENUM_NEXT(ck_mech_names
, CKM_CAST128_KEY_GEN
, CKM_CAST128_CBC_PAD
,
313 "CAST128_MAC_GENERAL",
315 ENUM_NEXT(ck_mech_names
, CKM_RC5_KEY_GEN
, CKM_RC5_CBC_PAD
,
323 ENUM_NEXT(ck_mech_names
, CKM_IDEA_KEY_GEN
, CKM_IDEA_CBC_PAD
,
331 ENUM_NEXT(ck_mech_names
, CKM_GENERIC_SECRET_KEY_GEN
, CKM_GENERIC_SECRET_KEY_GEN
,
333 "GENERIC_SECRET_KEY_GEN");
334 ENUM_NEXT(ck_mech_names
, CKM_CONCATENATE_BASE_AND_KEY
, CKM_EXTRACT_KEY_FROM_KEY
,
335 CKM_GENERIC_SECRET_KEY_GEN
,
336 "CONCATENATE_BASE_AND_KEY",
338 "CONCATENATE_BASE_AND_DATA",
339 "CONCATENATE_DATA_AND_BASE",
341 "EXTRACT_KEY_FROM_KEY");
342 ENUM_NEXT(ck_mech_names
, CKM_SSL3_PRE_MASTER_KEY_GEN
, CKM_TLS_MASTER_KEY_DERIVE_DH
,
343 CKM_EXTRACT_KEY_FROM_KEY
,
344 "SSL3_PRE_MASTER_KEY_GEN",
345 "SSL3_MASTER_KEY_DERIVE",
346 "SSL3_KEY_AND_MAC_DERIVE",
347 "SSL3_MASTER_KEY_DERIVE_DH",
348 "TLS_PRE_MASTER_KEY_GEN",
349 "TLS_MASTER_KEY_DERIVE",
350 "TLS_KEY_AND_MAC_DERIVE",
351 "TLS_MASTER_KEY_DERIVE_DH");
352 ENUM_NEXT(ck_mech_names
, CKM_SSL3_MD5_MAC
, CKM_SSL3_SHA1_MAC
,
353 CKM_TLS_MASTER_KEY_DERIVE_DH
,
356 ENUM_NEXT(ck_mech_names
, CKM_MD5_KEY_DERIVATION
, CKM_SHA1_KEY_DERIVATION
,
358 "MD5_KEY_DERIVATION",
359 "MD2_KEY_DERIVATION",
360 "SHA1_KEY_DERIVATION");
361 ENUM_NEXT(ck_mech_names
, CKM_PBE_MD2_DES_CBC
, CKM_PBE_SHA1_RC2_40_CBC
,
362 CKM_SHA1_KEY_DERIVATION
,
367 "PBE_MD5_CAST128_CBC",
368 "PBE_SHA1_CAST128_CBC",
371 "PBE_SHA1_DES3_EDE_CBC",
372 "PBE_SHA1_DES2_EDE_CBC",
373 "PBE_SHA1_RC2_128_CBC",
374 "PBE_SHA1_RC2_40_CBC");
375 ENUM_NEXT(ck_mech_names
, CKM_PKCS5_PBKD2
, CKM_PKCS5_PBKD2
,
376 CKM_PBE_SHA1_RC2_40_CBC
,
378 ENUM_NEXT(ck_mech_names
, CKM_PBA_SHA1_WITH_SHA1_HMAC
, CKM_PBA_SHA1_WITH_SHA1_HMAC
,
380 "PBA_SHA1_WITH_SHA1_HMAC");
381 ENUM_NEXT(ck_mech_names
, CKM_KEY_WRAP_LYNKS
, CKM_KEY_WRAP_SET_OAEP
,
382 CKM_PBA_SHA1_WITH_SHA1_HMAC
,
384 "KEY_WRAP_SET_OAEP");
385 ENUM_NEXT(ck_mech_names
, CKM_SKIPJACK_KEY_GEN
, CKM_SKIPJACK_RELAYX
,
386 CKM_KEY_WRAP_SET_OAEP
,
396 "SKIPJACK_PRIVATE_WRAP",
398 ENUM_NEXT(ck_mech_names
, CKM_KEA_KEY_PAIR_GEN
, CKM_KEA_KEY_DERIVE
,
402 ENUM_NEXT(ck_mech_names
, CKM_FORTEZZA_TIMESTAMP
, CKM_FORTEZZA_TIMESTAMP
,
404 "FORTEZZA_TIMESTAMP");
405 ENUM_NEXT(ck_mech_names
, CKM_BATON_KEY_GEN
, CKM_BATON_WRAP
,
406 CKM_FORTEZZA_TIMESTAMP
,
414 ENUM_NEXT(ck_mech_names
, CKM_ECDSA_KEY_PAIR_GEN
, CKM_ECDSA_SHA1
,
416 "ECDSA_KEY_PAIR_GEN",
419 ENUM_NEXT(ck_mech_names
, CKM_ECDH1_DERIVE
, CKM_ECMQV_DERIVE
,
422 "ECDH1_COFACTOR_DERIVE",
424 ENUM_NEXT(ck_mech_names
, CKM_JUNIPER_KEY_GEN
, CKM_JUNIPER_WRAP
,
432 ENUM_NEXT(ck_mech_names
, CKM_FASTHASH
, CKM_FASTHASH
,
435 ENUM_NEXT(ck_mech_names
, CKM_AES_KEY_GEN
, CKM_AES_CBC_PAD
,
443 ENUM_NEXT(ck_mech_names
, CKM_DSA_PARAMETER_GEN
, CKM_X9_42_DH_PARAMETER_GEN
,
446 "DH_PKCS_PARAMETER_GEN",
447 "X9_42_DH_PARAMETER_GEN");
448 ENUM_END(ck_mech_names
, CKM_X9_42_DH_PARAMETER_GEN
);
451 * Private data of an pkcs11_library_t object.
453 struct private_pkcs11_library_t
{
456 * Public pkcs11_library_t interface.
458 pkcs11_library_t
public;
466 * Name as passed to the constructor
471 * Supported feature set
473 pkcs11_feature_t features
;
476 METHOD(pkcs11_library_t
, get_name
, char*,
477 private_pkcs11_library_t
*this)
482 METHOD(pkcs11_library_t
, get_features
, pkcs11_feature_t
,
483 private_pkcs11_library_t
*this)
485 return this->features
;
492 /* implements enumerator_t */
495 CK_SESSION_HANDLE session
;
497 pkcs11_library_t
*lib
;
498 /* attributes to retrieve */
499 CK_ATTRIBUTE_PTR attr
;
500 /* number of attributes */
502 /* currently allocated attributes, to free */
503 linked_list_t
*freelist
;
504 } object_enumerator_t
;
507 * Free contents of attributes in a list
509 static void free_attrs(object_enumerator_t
*this)
511 CK_ATTRIBUTE_PTR attr
;
513 while (this->freelist
->remove_last(this->freelist
, (void**)&attr
) == SUCCESS
)
517 attr
->ulValueLen
= 0;
522 * Get attributes for a given object during enumeration
524 static bool get_attributes(object_enumerator_t
*this, CK_OBJECT_HANDLE object
)
531 /* get length of objects first */
532 rv
= this->lib
->f
->C_GetAttributeValue(this->session
, object
,
533 this->attr
, this->count
);
536 DBG1(DBG_CFG
, "C_GetAttributeValue(NULL) error: %N", ck_rv_names
, rv
);
539 /* allocate required chunks */
540 for (i
= 0; i
< this->count
; i
++)
542 if (this->attr
[i
].pValue
== NULL
&&
543 this->attr
[i
].ulValueLen
!= 0 && this->attr
[i
].ulValueLen
!= -1)
545 this->attr
[i
].pValue
= malloc(this->attr
[i
].ulValueLen
);
546 this->freelist
->insert_last(this->freelist
, &this->attr
[i
]);
550 rv
= this->lib
->f
->C_GetAttributeValue(this->session
, object
,
551 this->attr
, this->count
);
555 DBG1(DBG_CFG
, "C_GetAttributeValue() error: %N", ck_rv_names
, rv
);
561 METHOD(enumerator_t
, object_enumerate
, bool,
562 object_enumerator_t
*this, CK_OBJECT_HANDLE
*out
)
564 CK_OBJECT_HANDLE object
;
568 rv
= this->lib
->f
->C_FindObjects(this->session
, &object
, 1, &found
);
571 DBG1(DBG_CFG
, "C_FindObjects() failed: %N", ck_rv_names
, rv
);
578 if (!get_attributes(this, object
))
589 METHOD(enumerator_t
, object_destroy
, void,
590 object_enumerator_t
*this)
592 this->lib
->f
->C_FindObjectsFinal(this->session
);
594 this->freelist
->destroy(this->freelist
);
598 METHOD(pkcs11_library_t
, create_object_enumerator
, enumerator_t
*,
599 private_pkcs11_library_t
*this, CK_SESSION_HANDLE session
,
600 CK_ATTRIBUTE_PTR tmpl
, CK_ULONG tcount
,
601 CK_ATTRIBUTE_PTR attr
, CK_ULONG acount
)
603 object_enumerator_t
*enumerator
;
606 rv
= this->public.f
->C_FindObjectsInit(session
, tmpl
, tcount
);
609 DBG1(DBG_CFG
, "C_FindObjectsInit() failed: %N", ck_rv_names
, rv
);
610 return enumerator_create_empty();
615 .enumerate
= (void*)_object_enumerate
,
616 .destroy
= _object_destroy
,
619 .lib
= &this->public,
622 .freelist
= linked_list_create(),
624 return &enumerator
->public;
628 * Enumerator over mechanisms
631 /* implements enumerator_t */
633 /* PKCS#11 library */
634 pkcs11_library_t
*lib
;
637 /* mechanism type list */
638 CK_MECHANISM_TYPE_PTR mechs
;
639 /* number of mechanism types */
641 /* current mechanism */
643 } mechanism_enumerator_t
;
645 METHOD(enumerator_t
, enumerate_mech
, bool,
646 mechanism_enumerator_t
*this, CK_MECHANISM_TYPE
* type
,
647 CK_MECHANISM_INFO
*info
)
651 if (this->current
>= this->count
)
657 rv
= this->lib
->f
->C_GetMechanismInfo(this->slot
,
658 this->mechs
[this->current
], info
);
661 DBG1(DBG_CFG
, "C_GetMechanismInfo() failed: %N", ck_rv_names
, rv
);
665 *type
= this->mechs
[this->current
++];
669 METHOD(enumerator_t
, destroy_mech
, void,
670 mechanism_enumerator_t
*this)
676 METHOD(pkcs11_library_t
, create_mechanism_enumerator
, enumerator_t
*,
677 private_pkcs11_library_t
*this, CK_SLOT_ID slot
)
679 mechanism_enumerator_t
*enumerator
;
684 .enumerate
= (void*)_enumerate_mech
,
685 .destroy
= _destroy_mech
,
687 .lib
= &this->public,
691 rv
= enumerator
->lib
->f
->C_GetMechanismList(slot
, NULL
, &enumerator
->count
);
694 DBG1(DBG_CFG
, "C_GetMechanismList() failed: %N", ck_rv_names
, rv
);
696 return enumerator_create_empty();
698 enumerator
->mechs
= malloc(sizeof(CK_MECHANISM_TYPE
) * enumerator
->count
);
699 enumerator
->lib
->f
->C_GetMechanismList(slot
, enumerator
->mechs
,
703 DBG1(DBG_CFG
, "C_GetMechanismList() failed: %N", ck_rv_names
, rv
);
704 destroy_mech(enumerator
);
705 return enumerator_create_empty();
707 return &enumerator
->public;
710 METHOD(pkcs11_library_t
, destroy
, void,
711 private_pkcs11_library_t
*this)
713 this->public.f
->C_Finalize(NULL
);
714 dlclose(this->handle
);
721 void pkcs11_library_trim(char *str
, int len
)
726 for (i
= len
- 2; i
> 0; i
--)
738 * Mutex creation callback
740 static CK_RV
CreateMutex(CK_VOID_PTR_PTR data
)
742 *data
= mutex_create(MUTEX_TYPE_RECURSIVE
);
747 * Mutex destruction callback
749 static CK_RV
DestroyMutex(CK_VOID_PTR data
)
751 mutex_t
*mutex
= (mutex_t
*)data
;
753 mutex
->destroy(mutex
);
758 * Mutex lock callback
760 static CK_RV
LockMutex(CK_VOID_PTR data
)
762 mutex_t
*mutex
= (mutex_t
*)data
;
769 * Mutex unlock callback
771 static CK_RV
UnlockMutex(CK_VOID_PTR data
)
773 mutex_t
*mutex
= (mutex_t
*)data
;
775 mutex
->unlock(mutex
);
780 * Check if the library has at least a given cryptoki version
782 static bool has_version(CK_INFO
*info
, int major
, int minor
)
784 return info
->cryptokiVersion
.major
> major
||
785 (info
->cryptokiVersion
.major
== major
&&
786 info
->cryptokiVersion
.minor
>= minor
);
790 * Check for optional PKCS#11 library functionality
792 static void check_features(private_pkcs11_library_t
*this, CK_INFO
*info
)
794 if (has_version(info
, 2, 20))
796 this->features
|= PKCS11_TRUSTED_CERTS
;
797 this->features
|= PKCS11_ALWAYS_AUTH_KEYS
;
802 * Initialize a PKCS#11 library
804 static bool initialize(private_pkcs11_library_t
*this, char *name
, char *file
,
807 CK_C_GetFunctionList pC_GetFunctionList
;
810 static CK_C_INITIALIZE_ARGS args
= {
811 .CreateMutex
= CreateMutex
,
812 .DestroyMutex
= DestroyMutex
,
813 .LockMutex
= LockMutex
,
814 .UnlockMutex
= UnlockMutex
,
816 static CK_C_INITIALIZE_ARGS args_os
= {
817 .flags
= CKF_OS_LOCKING_OK
,
820 pC_GetFunctionList
= dlsym(this->handle
, "C_GetFunctionList");
821 if (!pC_GetFunctionList
)
823 DBG1(DBG_CFG
, "C_GetFunctionList not found for '%s': %s", name
, dlerror());
826 rv
= pC_GetFunctionList(&this->public.f
);
829 DBG1(DBG_CFG
, "C_GetFunctionList() error for '%s': %N",
830 name
, ck_rv_names
, rv
);
839 rv
= this->public.f
->C_Initialize(&args
);
841 if (rv
== CKR_CANT_LOCK
)
842 { /* fallback to OS locking */
844 rv
= this->public.f
->C_Initialize(&args_os
);
848 DBG1(DBG_CFG
, "C_Initialize() error for '%s': %N",
849 name
, ck_rv_names
, rv
);
852 rv
= this->public.f
->C_GetInfo(&info
);
855 DBG1(DBG_CFG
, "C_GetInfo() error for '%s': %N",
856 name
, ck_rv_names
, rv
);
857 this->public.f
->C_Finalize(NULL
);
861 pkcs11_library_trim(info
.manufacturerID
,
862 strnlen(info
.manufacturerID
, sizeof(info
.manufacturerID
)));
863 pkcs11_library_trim(info
.libraryDescription
,
864 strnlen(info
.libraryDescription
, sizeof(info
.libraryDescription
)));
866 DBG1(DBG_CFG
, "loaded PKCS#11 v%d.%d library '%s' (%s)",
867 info
.cryptokiVersion
.major
, info
.cryptokiVersion
.minor
, name
, file
);
868 DBG1(DBG_CFG
, " %s: %s v%d.%d",
869 info
.manufacturerID
, info
.libraryDescription
,
870 info
.libraryVersion
.major
, info
.libraryVersion
.minor
);
873 DBG1(DBG_CFG
, " uses OS locking functions");
876 check_features(this, &info
);
883 pkcs11_library_t
*pkcs11_library_create(char *name
, char *file
, bool os_locking
)
885 private_pkcs11_library_t
*this;
889 .get_name
= _get_name
,
890 .get_features
= _get_features
,
891 .create_object_enumerator
= _create_object_enumerator
,
892 .create_mechanism_enumerator
= _create_mechanism_enumerator
,
896 .handle
= dlopen(file
, RTLD_LAZY
),
901 DBG1(DBG_CFG
, "opening PKCS#11 library failed: %s", dlerror());
906 if (!initialize(this, name
, file
, os_locking
))
908 dlclose(this->handle
);
913 return &this->public;