2 * Copyright (C) 2011 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
5 * Copyright (C) 2010 Martin Willi
6 * Copyright (C) 2010 revosec AG
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 #include "pkcs11_library.h"
25 #include <threading/mutex.h>
26 #include <utils/linked_list.h>
28 typedef struct private_pkcs11_library_t private_pkcs11_library_t
;
31 ENUM_BEGIN(ck_rv_names
, CKR_OK
, CKR_CANT_LOCK
,
41 "NEED_TO_CREATE_THREADS",
43 ENUM_NEXT(ck_rv_names
, CKR_ATTRIBUTE_READ_ONLY
, CKR_ATTRIBUTE_VALUE_INVALID
,
45 "ATTRIBUTE_READ_ONLY",
46 "ATTRIBUTE_SENSITIVE",
47 "ATTRIBUTE_TYPE_INVALID",
48 "ATTRIBUTE_VALUE_INVALID");
49 ENUM_NEXT(ck_rv_names
, CKR_DATA_INVALID
, CKR_DATA_LEN_RANGE
,
50 CKR_ATTRIBUTE_VALUE_INVALID
,
53 ENUM_NEXT(ck_rv_names
, CKR_DEVICE_ERROR
, CKR_DEVICE_REMOVED
,
58 ENUM_NEXT(ck_rv_names
, CKR_ENCRYPTED_DATA_INVALID
, CKR_ENCRYPTED_DATA_LEN_RANGE
,
60 "ENCRYPTED_DATA_INVALID",
61 "ENCRYPTED_DATA_LEN_RANGE");
62 ENUM_NEXT(ck_rv_names
, CKR_FUNCTION_CANCELED
, CKR_FUNCTION_NOT_SUPPORTED
,
63 CKR_ENCRYPTED_DATA_LEN_RANGE
,
65 "FUNCTION_NOT_PARALLEL",
68 "FUNCTION_NOT_SUPPORTED");
69 ENUM_NEXT(ck_rv_names
, CKR_KEY_HANDLE_INVALID
, CKR_KEY_UNEXTRACTABLE
,
70 CKR_FUNCTION_NOT_SUPPORTED
,
74 "KEY_TYPE_INCONSISTENT",
79 "KEY_FUNCTION_NOT_PERMITTED",
82 ENUM_NEXT(ck_rv_names
, CKR_MECHANISM_INVALID
, CKR_MECHANISM_PARAM_INVALID
,
83 CKR_KEY_UNEXTRACTABLE
,
85 "MECHANISM_PARAM_INVALID");
86 ENUM_NEXT(ck_rv_names
, CKR_OBJECT_HANDLE_INVALID
, CKR_OBJECT_HANDLE_INVALID
,
87 CKR_MECHANISM_PARAM_INVALID
,
88 "OBJECT_HANDLE_INVALID");
89 ENUM_NEXT(ck_rv_names
, CKR_OPERATION_ACTIVE
, CKR_OPERATION_NOT_INITIALIZED
,
90 CKR_OBJECT_HANDLE_INVALID
,
92 "OPERATION_NOT_INITIALIZED");
93 ENUM_NEXT(ck_rv_names
, CKR_PIN_INCORRECT
, CKR_PIN_LOCKED
,
94 CKR_OPERATION_NOT_INITIALIZED
,
100 ENUM_NEXT(ck_rv_names
, CKR_SESSION_CLOSED
, CKR_SESSION_READ_WRITE_SO_EXISTS
,
105 "SESSION_HANDLE_INVALID",
106 "SESSION_PARALLEL_NOT_SUPPORTED",
109 "SESSION_READ_ONLY_EXISTS",
110 "SESSION_READ_WRITE_SO_EXISTS");
111 ENUM_NEXT(ck_rv_names
, CKR_SIGNATURE_INVALID
, CKR_SIGNATURE_LEN_RANGE
,
112 CKR_SESSION_READ_WRITE_SO_EXISTS
,
114 "SIGNATURE_LEN_RANGE");
115 ENUM_NEXT(ck_rv_names
, CKR_TEMPLATE_INCOMPLETE
, CKR_TEMPLATE_INCONSISTENT
,
116 CKR_SIGNATURE_LEN_RANGE
,
117 "TEMPLATE_INCOMPLETE",
118 "TEMPLATE_INCONSISTENT",
120 ENUM_NEXT(ck_rv_names
, CKR_TOKEN_NOT_PRESENT
, CKR_TOKEN_WRITE_PROTECTED
,
121 CKR_TEMPLATE_INCONSISTENT
,
123 "TOKEN_NOT_RECOGNIZED",
124 "TOKEN_WRITE_PROTECTED");
125 ENUM_NEXT(ck_rv_names
, CKR_UNWRAPPING_KEY_HANDLE_INVALID
, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT
,
126 CKR_TOKEN_WRITE_PROTECTED
,
127 "UNWRAPPING_KEY_HANDLE_INVALID",
128 "UNWRAPPING_KEY_SIZE_RANGE",
129 "UNWRAPPING_KEY_TYPE_INCONSISTENT");
130 ENUM_NEXT(ck_rv_names
, CKR_USER_ALREADY_LOGGED_IN
, CKR_USER_TOO_MANY_TYPES
,
131 CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT
,
132 "USER_ALREADY_LOGGED_IN",
133 "USER_NOT_LOGGED_IN",
134 "USER_PIN_NOT_INITIALIZED",
136 "USER_ANOTHER_ALREADY_LOGGED_IN",
137 "USER_TOO_MANY_TYPES");
138 ENUM_NEXT(ck_rv_names
, CKR_WRAPPED_KEY_INVALID
, CKR_WRAPPING_KEY_TYPE_INCONSISTENT
,
139 CKR_USER_TOO_MANY_TYPES
,
140 "WRAPPED_KEY_INVALID",
142 "WRAPPED_KEY_LEN_RANGE",
143 "WRAPPING_KEY_HANDLE_INVALID",
144 "WRAPPING_KEY_SIZE_RANGE",
145 "WRAPPING_KEY_TYPE_INCONSISTENT");
146 ENUM_NEXT(ck_rv_names
, CKR_RANDOM_SEED_NOT_SUPPORTED
, CKR_RANDOM_NO_RNG
,
147 CKR_WRAPPING_KEY_TYPE_INCONSISTENT
,
148 "RANDOM_SEED_NOT_SUPPORTED",
150 ENUM_NEXT(ck_rv_names
, CKR_DOMAIN_PARAMS_INVALID
, CKR_DOMAIN_PARAMS_INVALID
,
152 "DOMAIN_PARAMS_INVALID");
153 ENUM_NEXT(ck_rv_names
, CKR_BUFFER_TOO_SMALL
, CKR_BUFFER_TOO_SMALL
,
154 CKR_DOMAIN_PARAMS_INVALID
,
156 ENUM_NEXT(ck_rv_names
, CKR_SAVED_STATE_INVALID
, CKR_SAVED_STATE_INVALID
,
157 CKR_BUFFER_TOO_SMALL
,
158 "SAVED_STATE_INVALID");
159 ENUM_NEXT(ck_rv_names
, CKR_INFORMATION_SENSITIVE
, CKR_INFORMATION_SENSITIVE
,
160 CKR_SAVED_STATE_INVALID
,
161 "INFORMATION_SENSITIVE");
162 ENUM_NEXT(ck_rv_names
, CKR_STATE_UNSAVEABLE
, CKR_STATE_UNSAVEABLE
,
163 CKR_INFORMATION_SENSITIVE
,
165 ENUM_NEXT(ck_rv_names
, CKR_CRYPTOKI_NOT_INITIALIZED
, CKR_CRYPTOKI_ALREADY_INITIALIZED
,
166 CKR_STATE_UNSAVEABLE
,
167 "CRYPTOKI_NOT_INITIALIZED",
168 "CRYPTOKI_ALREADY_INITIALIZED");
169 ENUM_NEXT(ck_rv_names
, CKR_MUTEX_BAD
, CKR_MUTEX_NOT_LOCKED
,
170 CKR_CRYPTOKI_ALREADY_INITIALIZED
,
173 ENUM_NEXT(ck_rv_names
, CKR_FUNCTION_REJECTED
, CKR_FUNCTION_REJECTED
,
174 CKR_MUTEX_NOT_LOCKED
,
175 "FUNCTION_REJECTED");
176 ENUM_END(ck_rv_names
, CKR_FUNCTION_REJECTED
);
179 ENUM_BEGIN(ck_mech_names
, CKM_RSA_PKCS_KEY_PAIR_GEN
, CKM_DSA_SHA1
,
180 "RSA_PKCS_KEY_PAIR_GEN",
187 "RIPEMD128_RSA_PKCS",
188 "RIPEMD160_RSA_PKCS",
190 "RSA_X9_31_KEY_PAIR_GEN",
199 ENUM_NEXT(ck_mech_names
, CKM_DH_PKCS_KEY_PAIR_GEN
, CKM_DH_PKCS_DERIVE
,
201 "DH_PKCS_KEY_PAIR_GEN",
203 ENUM_NEXT(ck_mech_names
, CKM_X9_42_DH_KEY_PAIR_GEN
, CKM_X9_42_MQV_DERIVE
,
205 "X9_42_DH_KEY_PAIR_GEN",
207 "X9_42_DH_HYBRID_DERIVE",
209 ENUM_NEXT(ck_mech_names
, CKM_SHA256_RSA_PKCS
, CKM_SHA512_RSA_PKCS_PSS
,
210 CKM_X9_42_MQV_DERIVE
,
214 "SHA256_RSA_PKCS_PSS",
215 "SHA384_RSA_PKCS_PSS",
216 "SHA512_RSA_PKCS_PSS");
217 ENUM_NEXT(ck_mech_names
, CKM_RC2_KEY_GEN
, CKM_RC2_CBC_PAD
,
218 CKM_SHA512_RSA_PKCS_PSS
,
225 ENUM_NEXT(ck_mech_names
, CKM_RC4_KEY_GEN
, CKM_RC4
,
229 ENUM_NEXT(ck_mech_names
, CKM_DES_KEY_GEN
, CKM_DES_CBC_PAD
,
237 ENUM_NEXT(ck_mech_names
, CKM_DES2_KEY_GEN
, CKM_DES3_CBC_PAD
,
246 ENUM_NEXT(ck_mech_names
, CKM_CDMF_KEY_GEN
, CKM_CDMF_CBC_PAD
,
254 ENUM_NEXT(ck_mech_names
, CKM_MD2
, CKM_MD2_HMAC_GENERAL
,
259 ENUM_NEXT(ck_mech_names
, CKM_MD5
, CKM_MD5_HMAC_GENERAL
,
260 CKM_MD2_HMAC_GENERAL
,
264 ENUM_NEXT(ck_mech_names
, CKM_SHA_1
, CKM_SHA_1_HMAC_GENERAL
,
265 CKM_MD5_HMAC_GENERAL
,
268 "SHA_1_HMAC_GENERAL");
269 ENUM_NEXT(ck_mech_names
, CKM_RIPEMD128
, CKM_RIPEMD128_HMAC_GENERAL
,
270 CKM_SHA_1_HMAC_GENERAL
,
273 "RIPEMD128_HMAC_GENERAL");
274 ENUM_NEXT(ck_mech_names
, CKM_RIPEMD160
, CKM_RIPEMD160_HMAC_GENERAL
,
275 CKM_RIPEMD128_HMAC_GENERAL
,
278 "RIPEMD160_HMAC_GENERAL");
279 ENUM_NEXT(ck_mech_names
, CKM_SHA256
, CKM_SHA256_HMAC_GENERAL
,
280 CKM_RIPEMD160_HMAC_GENERAL
,
283 "SHA256_HMAC_GENERAL");
284 ENUM_NEXT(ck_mech_names
, CKM_SHA384
, CKM_SHA384_HMAC_GENERAL
,
285 CKM_SHA256_HMAC_GENERAL
,
288 "SHA384_HMAC_GENERAL");
289 ENUM_NEXT(ck_mech_names
, CKM_SHA512
, CKM_SHA512_HMAC_GENERAL
,
290 CKM_SHA384_HMAC_GENERAL
,
293 "SHA512_HMAC_GENERAL");
294 ENUM_NEXT(ck_mech_names
, CKM_CAST_KEY_GEN
, CKM_CAST_CBC_PAD
,
295 CKM_SHA512_HMAC_GENERAL
,
302 ENUM_NEXT(ck_mech_names
, CKM_CAST3_KEY_GEN
, CKM_CAST3_CBC_PAD
,
310 ENUM_NEXT(ck_mech_names
, CKM_CAST128_KEY_GEN
, CKM_CAST128_CBC_PAD
,
316 "CAST128_MAC_GENERAL",
318 ENUM_NEXT(ck_mech_names
, CKM_RC5_KEY_GEN
, CKM_RC5_CBC_PAD
,
326 ENUM_NEXT(ck_mech_names
, CKM_IDEA_KEY_GEN
, CKM_IDEA_CBC_PAD
,
334 ENUM_NEXT(ck_mech_names
, CKM_GENERIC_SECRET_KEY_GEN
, CKM_GENERIC_SECRET_KEY_GEN
,
336 "GENERIC_SECRET_KEY_GEN");
337 ENUM_NEXT(ck_mech_names
, CKM_CONCATENATE_BASE_AND_KEY
, CKM_EXTRACT_KEY_FROM_KEY
,
338 CKM_GENERIC_SECRET_KEY_GEN
,
339 "CONCATENATE_BASE_AND_KEY",
341 "CONCATENATE_BASE_AND_DATA",
342 "CONCATENATE_DATA_AND_BASE",
344 "EXTRACT_KEY_FROM_KEY");
345 ENUM_NEXT(ck_mech_names
, CKM_SSL3_PRE_MASTER_KEY_GEN
, CKM_TLS_MASTER_KEY_DERIVE_DH
,
346 CKM_EXTRACT_KEY_FROM_KEY
,
347 "SSL3_PRE_MASTER_KEY_GEN",
348 "SSL3_MASTER_KEY_DERIVE",
349 "SSL3_KEY_AND_MAC_DERIVE",
350 "SSL3_MASTER_KEY_DERIVE_DH",
351 "TLS_PRE_MASTER_KEY_GEN",
352 "TLS_MASTER_KEY_DERIVE",
353 "TLS_KEY_AND_MAC_DERIVE",
354 "TLS_MASTER_KEY_DERIVE_DH");
355 ENUM_NEXT(ck_mech_names
, CKM_SSL3_MD5_MAC
, CKM_SSL3_SHA1_MAC
,
356 CKM_TLS_MASTER_KEY_DERIVE_DH
,
359 ENUM_NEXT(ck_mech_names
, CKM_MD5_KEY_DERIVATION
, CKM_SHA1_KEY_DERIVATION
,
361 "MD5_KEY_DERIVATION",
362 "MD2_KEY_DERIVATION",
363 "SHA1_KEY_DERIVATION");
364 ENUM_NEXT(ck_mech_names
, CKM_PBE_MD2_DES_CBC
, CKM_PBE_SHA1_RC2_40_CBC
,
365 CKM_SHA1_KEY_DERIVATION
,
370 "PBE_MD5_CAST128_CBC",
371 "PBE_SHA1_CAST128_CBC",
374 "PBE_SHA1_DES3_EDE_CBC",
375 "PBE_SHA1_DES2_EDE_CBC",
376 "PBE_SHA1_RC2_128_CBC",
377 "PBE_SHA1_RC2_40_CBC");
378 ENUM_NEXT(ck_mech_names
, CKM_PKCS5_PBKD2
, CKM_PKCS5_PBKD2
,
379 CKM_PBE_SHA1_RC2_40_CBC
,
381 ENUM_NEXT(ck_mech_names
, CKM_PBA_SHA1_WITH_SHA1_HMAC
, CKM_PBA_SHA1_WITH_SHA1_HMAC
,
383 "PBA_SHA1_WITH_SHA1_HMAC");
384 ENUM_NEXT(ck_mech_names
, CKM_KEY_WRAP_LYNKS
, CKM_KEY_WRAP_SET_OAEP
,
385 CKM_PBA_SHA1_WITH_SHA1_HMAC
,
387 "KEY_WRAP_SET_OAEP");
388 ENUM_NEXT(ck_mech_names
, CKM_SKIPJACK_KEY_GEN
, CKM_SKIPJACK_RELAYX
,
389 CKM_KEY_WRAP_SET_OAEP
,
399 "SKIPJACK_PRIVATE_WRAP",
401 ENUM_NEXT(ck_mech_names
, CKM_KEA_KEY_PAIR_GEN
, CKM_KEA_KEY_DERIVE
,
405 ENUM_NEXT(ck_mech_names
, CKM_FORTEZZA_TIMESTAMP
, CKM_FORTEZZA_TIMESTAMP
,
407 "FORTEZZA_TIMESTAMP");
408 ENUM_NEXT(ck_mech_names
, CKM_BATON_KEY_GEN
, CKM_BATON_WRAP
,
409 CKM_FORTEZZA_TIMESTAMP
,
417 ENUM_NEXT(ck_mech_names
, CKM_ECDSA_KEY_PAIR_GEN
, CKM_ECDSA_SHA1
,
419 "ECDSA_KEY_PAIR_GEN",
422 ENUM_NEXT(ck_mech_names
, CKM_ECDH1_DERIVE
, CKM_ECMQV_DERIVE
,
425 "ECDH1_COFACTOR_DERIVE",
427 ENUM_NEXT(ck_mech_names
, CKM_JUNIPER_KEY_GEN
, CKM_JUNIPER_WRAP
,
435 ENUM_NEXT(ck_mech_names
, CKM_FASTHASH
, CKM_FASTHASH
,
438 ENUM_NEXT(ck_mech_names
, CKM_AES_KEY_GEN
, CKM_AES_CBC_PAD
,
446 ENUM_NEXT(ck_mech_names
, CKM_DSA_PARAMETER_GEN
, CKM_X9_42_DH_PARAMETER_GEN
,
449 "DH_PKCS_PARAMETER_GEN",
450 "X9_42_DH_PARAMETER_GEN");
451 ENUM_END(ck_mech_names
, CKM_X9_42_DH_PARAMETER_GEN
);
454 ENUM_BEGIN(ck_attr_names
, CKA_CLASS
, CKA_LABEL
,
459 ENUM_NEXT(ck_attr_names
, CKA_APPLICATION
, CKA_OBJECT_ID
, CKA_LABEL
,
463 ENUM_NEXT(ck_attr_names
, CKA_CERTIFICATE_TYPE
, CKA_HASH_OF_ISSUER_PUBLIC_KEY
,
472 "CERTIFICATE_CATEGORY",
473 "JAVA_MIDP_SECURITY_DOMAIN",
475 "HASH_OF_SUBJECT_PUBLIC_KEY",
476 "HASH_OF_ISSUER_PUBLIC_KEY");
477 ENUM_NEXT(ck_attr_names
, CKA_CHECK_VALUE
, CKA_CHECK_VALUE
,
478 CKA_HASH_OF_ISSUER_PUBLIC_KEY
,
480 ENUM_NEXT(ck_attr_names
, CKA_KEY_TYPE
, CKA_DERIVE
, CKA_CHECK_VALUE
,
494 ENUM_NEXT(ck_attr_names
, CKA_START_DATE
, CKA_END_DATE
, CKA_DERIVE
,
497 ENUM_NEXT(ck_attr_names
, CKA_MODULUS
, CKA_COEFFICIENT
, CKA_END_DATE
,
507 ENUM_NEXT(ck_attr_names
, CKA_PRIME
, CKA_SUB_PRIME_BITS
, CKA_COEFFICIENT
,
513 ENUM_NEXT(ck_attr_names
, CKA_VALUE_BITS
, CKA_KEY_GEN_MECHANISM
,
521 "KEY_GEN_MECHANISM");
522 ENUM_NEXT(ck_attr_names
, CKA_MODIFIABLE
, CKA_MODIFIABLE
, CKA_KEY_GEN_MECHANISM
,
524 ENUM_NEXT(ck_attr_names
, CKA_EC_PARAMS
, CKA_EC_POINT
, CKA_MODIFIABLE
,
527 ENUM_NEXT(ck_attr_names
, CKA_SECONDARY_AUTH
, CKA_ALWAYS_AUTHENTICATE
,
531 "ALWAYS_AUTHENTICATE");
532 ENUM_NEXT(ck_attr_names
, CKA_WRAP_WITH_TRUSTED
, CKA_WRAP_WITH_TRUSTED
,
533 CKA_ALWAYS_AUTHENTICATE
,
534 "WRAP_WITH_TRUSTED");
535 ENUM_NEXT(ck_attr_names
, CKA_HW_FEATURE_TYPE
, CKA_HAS_RESET
,
536 CKA_WRAP_WITH_TRUSTED
,
540 ENUM_NEXT(ck_attr_names
, CKA_PIXEL_X
, CKA_BITS_PER_PIXEL
, CKA_HAS_RESET
,
547 ENUM_NEXT(ck_attr_names
, CKA_CHAR_SETS
, CKA_MIME_TYPES
, CKA_BITS_PER_PIXEL
,
551 ENUM_NEXT(ck_attr_names
, CKA_MECHANISM_TYPE
, CKA_SUPPORTED_CMS_ATTRIBUTES
,
554 "REQUIRED_CMS_ATTRIBUTES",
555 "DEFAULT_CMS_ATTRIBUTES",
556 "SUPPORTED_CMS_ATTRIBUTES");
557 ENUM_NEXT(ck_attr_names
, CKA_WRAP_TEMPLATE
, CKA_UNWRAP_TEMPLATE
,
558 CKA_SUPPORTED_CMS_ATTRIBUTES
,
561 ENUM_NEXT(ck_attr_names
, CKA_ALLOWED_MECHANISMS
, CKA_ALLOWED_MECHANISMS
,
563 "ALLOWED_MECHANISMS");
564 ENUM_END(ck_attr_names
, CKA_ALLOWED_MECHANISMS
);
565 /* the values in an enum_name_t are stored as int, thus CKA_VENDOR_DEFINED
566 * will overflow and is thus not defined here */
571 * Private data of an pkcs11_library_t object.
573 struct private_pkcs11_library_t
{
576 * Public pkcs11_library_t interface.
578 pkcs11_library_t
public;
586 * Name as passed to the constructor
591 * Supported feature set
593 pkcs11_feature_t features
;
596 METHOD(pkcs11_library_t
, get_name
, char*,
597 private_pkcs11_library_t
*this)
602 METHOD(pkcs11_library_t
, get_features
, pkcs11_feature_t
,
603 private_pkcs11_library_t
*this)
605 return this->features
;
612 /* implements enumerator_t */
615 CK_SESSION_HANDLE session
;
617 pkcs11_library_t
*lib
;
618 /* attributes to retrieve */
619 CK_ATTRIBUTE_PTR attr
;
620 /* number of attributes */
622 /* object handle in case of a single object */
623 CK_OBJECT_HANDLE object
;
624 /* currently allocated attributes, to free */
625 linked_list_t
*freelist
;
626 } object_enumerator_t
;
629 * Free contents of attributes in a list
631 static void free_attrs(object_enumerator_t
*this)
633 CK_ATTRIBUTE_PTR attr
;
635 while (this->freelist
->remove_last(this->freelist
, (void**)&attr
) == SUCCESS
)
639 attr
->ulValueLen
= 0;
644 * Get attributes for a given object during enumeration
646 static bool get_attributes(object_enumerator_t
*this, CK_OBJECT_HANDLE object
)
653 /* get length of objects first */
654 rv
= this->lib
->f
->C_GetAttributeValue(this->session
, object
,
655 this->attr
, this->count
);
658 DBG1(DBG_CFG
, "C_GetAttributeValue(NULL) error: %N", ck_rv_names
, rv
);
661 /* allocate required chunks */
662 for (i
= 0; i
< this->count
; i
++)
664 if (this->attr
[i
].pValue
== NULL
&&
665 this->attr
[i
].ulValueLen
!= 0 && this->attr
[i
].ulValueLen
!= -1)
667 this->attr
[i
].pValue
= malloc(this->attr
[i
].ulValueLen
);
668 this->freelist
->insert_last(this->freelist
, &this->attr
[i
]);
672 rv
= this->lib
->f
->C_GetAttributeValue(this->session
, object
,
673 this->attr
, this->count
);
677 DBG1(DBG_CFG
, "C_GetAttributeValue() error: %N", ck_rv_names
, rv
);
683 METHOD(enumerator_t
, object_enumerate
, bool,
684 object_enumerator_t
*this, CK_OBJECT_HANDLE
*out
)
686 CK_OBJECT_HANDLE object
;
692 rv
= this->lib
->f
->C_FindObjects(this->session
, &object
, 1, &found
);
695 DBG1(DBG_CFG
, "C_FindObjects() failed: %N", ck_rv_names
, rv
);
701 object
= this->object
;
708 if (!get_attributes(this, object
))
722 METHOD(enumerator_t
, object_destroy
, void,
723 object_enumerator_t
*this)
727 this->lib
->f
->C_FindObjectsFinal(this->session
);
730 this->freelist
->destroy(this->freelist
);
734 METHOD(pkcs11_library_t
, create_object_enumerator
, enumerator_t
*,
735 private_pkcs11_library_t
*this, CK_SESSION_HANDLE session
,
736 CK_ATTRIBUTE_PTR tmpl
, CK_ULONG tcount
,
737 CK_ATTRIBUTE_PTR attr
, CK_ULONG acount
)
739 object_enumerator_t
*enumerator
;
742 rv
= this->public.f
->C_FindObjectsInit(session
, tmpl
, tcount
);
745 DBG1(DBG_CFG
, "C_FindObjectsInit() failed: %N", ck_rv_names
, rv
);
746 return enumerator_create_empty();
751 .enumerate
= (void*)_object_enumerate
,
752 .destroy
= _object_destroy
,
755 .lib
= &this->public,
758 .freelist
= linked_list_create(),
760 return &enumerator
->public;
763 METHOD(pkcs11_library_t
, create_object_attr_enumerator
, enumerator_t
*,
764 private_pkcs11_library_t
*this, CK_SESSION_HANDLE session
,
765 CK_OBJECT_HANDLE object
, CK_ATTRIBUTE_PTR attr
, CK_ULONG count
)
767 object_enumerator_t
*enumerator
;
771 .enumerate
= (void*)_object_enumerate
,
772 .destroy
= _object_destroy
,
775 .lib
= &this->public,
779 .freelist
= linked_list_create(),
781 return &enumerator
->public;
785 * Enumerator over mechanisms
788 /* implements enumerator_t */
790 /* PKCS#11 library */
791 pkcs11_library_t
*lib
;
794 /* mechanism type list */
795 CK_MECHANISM_TYPE_PTR mechs
;
796 /* number of mechanism types */
798 /* current mechanism */
800 } mechanism_enumerator_t
;
802 METHOD(enumerator_t
, enumerate_mech
, bool,
803 mechanism_enumerator_t
*this, CK_MECHANISM_TYPE
* type
,
804 CK_MECHANISM_INFO
*info
)
808 if (this->current
>= this->count
)
814 rv
= this->lib
->f
->C_GetMechanismInfo(this->slot
,
815 this->mechs
[this->current
], info
);
818 DBG1(DBG_CFG
, "C_GetMechanismInfo() failed: %N", ck_rv_names
, rv
);
822 *type
= this->mechs
[this->current
++];
826 METHOD(enumerator_t
, destroy_mech
, void,
827 mechanism_enumerator_t
*this)
833 METHOD(pkcs11_library_t
, create_mechanism_enumerator
, enumerator_t
*,
834 private_pkcs11_library_t
*this, CK_SLOT_ID slot
)
836 mechanism_enumerator_t
*enumerator
;
841 .enumerate
= (void*)_enumerate_mech
,
842 .destroy
= _destroy_mech
,
844 .lib
= &this->public,
848 rv
= enumerator
->lib
->f
->C_GetMechanismList(slot
, NULL
, &enumerator
->count
);
851 DBG1(DBG_CFG
, "C_GetMechanismList() failed: %N", ck_rv_names
, rv
);
853 return enumerator_create_empty();
855 enumerator
->mechs
= malloc(sizeof(CK_MECHANISM_TYPE
) * enumerator
->count
);
856 enumerator
->lib
->f
->C_GetMechanismList(slot
, enumerator
->mechs
,
860 DBG1(DBG_CFG
, "C_GetMechanismList() failed: %N", ck_rv_names
, rv
);
861 destroy_mech(enumerator
);
862 return enumerator_create_empty();
864 return &enumerator
->public;
867 METHOD(pkcs11_library_t
, get_ck_attribute
, bool,
868 private_pkcs11_library_t
*this, CK_SESSION_HANDLE session
,
869 CK_OBJECT_HANDLE obj
, CK_ATTRIBUTE_TYPE type
, chunk_t
*data
)
871 CK_ATTRIBUTE attr
= { type
, NULL
, 0 };
873 rv
= this->public.f
->C_GetAttributeValue(session
, obj
, &attr
, 1);
876 DBG1(DBG_CFG
, "C_GetAttributeValue(%N) error: %N", ck_attr_names
, type
,
880 *data
= chunk_alloc(attr
.ulValueLen
);
881 attr
.pValue
= data
->ptr
;
882 rv
= this->public.f
->C_GetAttributeValue(session
, obj
, &attr
, 1);
885 DBG1(DBG_CFG
, "C_GetAttributeValue(%N) error: %N", ck_attr_names
, type
,
893 METHOD(pkcs11_library_t
, destroy
, void,
894 private_pkcs11_library_t
*this)
896 this->public.f
->C_Finalize(NULL
);
897 dlclose(this->handle
);
904 void pkcs11_library_trim(char *str
, int len
)
909 for (i
= len
- 2; i
> 0; i
--)
921 * Mutex creation callback
923 static CK_RV
CreateMutex(CK_VOID_PTR_PTR data
)
925 *data
= mutex_create(MUTEX_TYPE_RECURSIVE
);
930 * Mutex destruction callback
932 static CK_RV
DestroyMutex(CK_VOID_PTR data
)
934 mutex_t
*mutex
= (mutex_t
*)data
;
936 mutex
->destroy(mutex
);
941 * Mutex lock callback
943 static CK_RV
LockMutex(CK_VOID_PTR data
)
945 mutex_t
*mutex
= (mutex_t
*)data
;
952 * Mutex unlock callback
954 static CK_RV
UnlockMutex(CK_VOID_PTR data
)
956 mutex_t
*mutex
= (mutex_t
*)data
;
958 mutex
->unlock(mutex
);
963 * Check if the library has at least a given cryptoki version
965 static bool has_version(CK_INFO
*info
, int major
, int minor
)
967 return info
->cryptokiVersion
.major
> major
||
968 (info
->cryptokiVersion
.major
== major
&&
969 info
->cryptokiVersion
.minor
>= minor
);
973 * Check for optional PKCS#11 library functionality
975 static void check_features(private_pkcs11_library_t
*this, CK_INFO
*info
)
977 if (has_version(info
, 2, 20))
979 this->features
|= PKCS11_TRUSTED_CERTS
;
980 this->features
|= PKCS11_ALWAYS_AUTH_KEYS
;
985 * Initialize a PKCS#11 library
987 static bool initialize(private_pkcs11_library_t
*this, char *name
, char *file
,
990 CK_C_GetFunctionList pC_GetFunctionList
;
993 static CK_C_INITIALIZE_ARGS args
= {
994 .CreateMutex
= CreateMutex
,
995 .DestroyMutex
= DestroyMutex
,
996 .LockMutex
= LockMutex
,
997 .UnlockMutex
= UnlockMutex
,
999 static CK_C_INITIALIZE_ARGS args_os
= {
1000 .flags
= CKF_OS_LOCKING_OK
,
1003 pC_GetFunctionList
= dlsym(this->handle
, "C_GetFunctionList");
1004 if (!pC_GetFunctionList
)
1006 DBG1(DBG_CFG
, "C_GetFunctionList not found for '%s': %s", name
, dlerror());
1009 rv
= pC_GetFunctionList(&this->public.f
);
1012 DBG1(DBG_CFG
, "C_GetFunctionList() error for '%s': %N",
1013 name
, ck_rv_names
, rv
);
1022 rv
= this->public.f
->C_Initialize(&args
);
1024 if (rv
== CKR_CANT_LOCK
)
1025 { /* fallback to OS locking */
1027 rv
= this->public.f
->C_Initialize(&args_os
);
1031 DBG1(DBG_CFG
, "C_Initialize() error for '%s': %N",
1032 name
, ck_rv_names
, rv
);
1035 rv
= this->public.f
->C_GetInfo(&info
);
1038 DBG1(DBG_CFG
, "C_GetInfo() error for '%s': %N",
1039 name
, ck_rv_names
, rv
);
1040 this->public.f
->C_Finalize(NULL
);
1044 pkcs11_library_trim(info
.manufacturerID
,
1045 strnlen(info
.manufacturerID
, sizeof(info
.manufacturerID
)));
1046 pkcs11_library_trim(info
.libraryDescription
,
1047 strnlen(info
.libraryDescription
, sizeof(info
.libraryDescription
)));
1049 DBG1(DBG_CFG
, "loaded PKCS#11 v%d.%d library '%s' (%s)",
1050 info
.cryptokiVersion
.major
, info
.cryptokiVersion
.minor
, name
, file
);
1051 DBG1(DBG_CFG
, " %s: %s v%d.%d",
1052 info
.manufacturerID
, info
.libraryDescription
,
1053 info
.libraryVersion
.major
, info
.libraryVersion
.minor
);
1056 DBG1(DBG_CFG
, " uses OS locking functions");
1059 check_features(this, &info
);
1066 pkcs11_library_t
*pkcs11_library_create(char *name
, char *file
, bool os_locking
)
1068 private_pkcs11_library_t
*this;
1072 .get_name
= _get_name
,
1073 .get_features
= _get_features
,
1074 .create_object_enumerator
= _create_object_enumerator
,
1075 .create_object_attr_enumerator
= _create_object_attr_enumerator
,
1076 .create_mechanism_enumerator
= _create_mechanism_enumerator
,
1077 .get_ck_attribute
= _get_ck_attribute
,
1078 .destroy
= _destroy
,
1081 .handle
= dlopen(file
, RTLD_LAZY
),
1086 DBG1(DBG_CFG
, "opening PKCS#11 library failed: %s", dlerror());
1091 if (!initialize(this, name
, file
, os_locking
))
1093 dlclose(this->handle
);
1098 return &this->public;