diff options
Diffstat (limited to 'src/libstrongswan/plugins/pkcs11/pkcs11_library.c')
-rw-r--r-- | src/libstrongswan/plugins/pkcs11/pkcs11_library.c | 869 |
1 files changed, 869 insertions, 0 deletions
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_library.c b/src/libstrongswan/plugins/pkcs11/pkcs11_library.c new file mode 100644 index 000000000..9fb1b7769 --- /dev/null +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_library.c @@ -0,0 +1,869 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "pkcs11_library.h" + +#include <dlfcn.h> + +#include <library.h> +#include <debug.h> +#include <threading/mutex.h> +#include <utils/linked_list.h> + +typedef struct private_pkcs11_library_t private_pkcs11_library_t; + + +ENUM_BEGIN(ck_rv_names, CKR_OK, CKR_CANT_LOCK, + "OK", + "CANCEL", + "HOST_MEMORY", + "SLOT_ID_INVALID", + "(0x04)", + "GENERAL_ERROR", + "FUNCTION_FAILED", + "ARGUMENTS_BAD", + "NO_EVENT", + "NEED_TO_CREATE_THREADS", + "CANT_LOCK"); +ENUM_NEXT(ck_rv_names, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_VALUE_INVALID, + CKR_CANT_LOCK, + "ATTRIBUTE_READ_ONLY", + "ATTRIBUTE_SENSITIVE", + "ATTRIBUTE_TYPE_INVALID", + "ATTRIBUTE_VALUE_INVALID"); +ENUM_NEXT(ck_rv_names, CKR_DATA_INVALID, CKR_DATA_LEN_RANGE, + CKR_ATTRIBUTE_VALUE_INVALID, + "DATA_INVALID" + "DATA_LEN_RANGE"); +ENUM_NEXT(ck_rv_names, CKR_DEVICE_ERROR, CKR_DEVICE_REMOVED, + CKR_DATA_LEN_RANGE, + "DEVICE_ERROR", + "DEVICE_MEMORY", + "DEVICE_REMOVED"); +ENUM_NEXT(ck_rv_names, CKR_ENCRYPTED_DATA_INVALID, CKR_ENCRYPTED_DATA_LEN_RANGE, + CKR_DEVICE_REMOVED, + "ENCRYPTED_DATA_INVALID", + "ENCRYPTED_DATA_LEN_RANGE"); +ENUM_NEXT(ck_rv_names, CKR_FUNCTION_CANCELED, CKR_FUNCTION_NOT_SUPPORTED, + CKR_ENCRYPTED_DATA_LEN_RANGE, + "FUNCTION_CANCELED", + "FUNCTION_NOT_PARALLEL", + "(0x52)", + "(0x53)", + "FUNCTION_NOT_SUPPORTED"); +ENUM_NEXT(ck_rv_names, CKR_KEY_HANDLE_INVALID, CKR_KEY_UNEXTRACTABLE, + CKR_FUNCTION_NOT_SUPPORTED, + "KEY_HANDLE_INVALID", + "(0x61)", + "KEY_SIZE_RANGE", + "KEY_TYPE_INCONSISTENT", + "KEY_NOT_NEEDED", + "KEY_CHANGED", + "KEY_NEEDED", + "KEY_INDIGESTIBLE", + "KEY_FUNCTION_NOT_PERMITTED", + "KEY_NOT_WRAPPABLE", + "KEY_UNEXTRACTABLE"); +ENUM_NEXT(ck_rv_names, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID, + CKR_KEY_UNEXTRACTABLE, + "MECHANISM_INVALID", + "MECHANISM_PARAM_INVALID"); +ENUM_NEXT(ck_rv_names, CKR_OBJECT_HANDLE_INVALID, CKR_OBJECT_HANDLE_INVALID, + CKR_MECHANISM_PARAM_INVALID, + "OBJECT_HANDLE_INVALID"); +ENUM_NEXT(ck_rv_names, CKR_OPERATION_ACTIVE, CKR_OPERATION_NOT_INITIALIZED, + CKR_OBJECT_HANDLE_INVALID, + "OPERATION_ACTIVE", + "OPERATION_NOT_INITIALIZED"); +ENUM_NEXT(ck_rv_names, CKR_PIN_INCORRECT, CKR_PIN_LOCKED, + CKR_OPERATION_NOT_INITIALIZED, + "PIN_INCORRECT", + "PIN_INVALID", + "PIN_LEN_RANGE", + "PIN_EXPIRED", + "PIN_LOCKED"); +ENUM_NEXT(ck_rv_names, CKR_SESSION_CLOSED, CKR_SESSION_READ_WRITE_SO_EXISTS, + CKR_PIN_LOCKED, + "SESSION_CLOSED", + "SESSION_COUNT", + "(0xb2)", + "SESSION_HANDLE_INVALID", + "SESSION_PARALLEL_NOT_SUPPORTED", + "SESSION_READ_ONLY", + "SESSION_EXISTS", + "SESSION_READ_ONLY_EXISTS", + "SESSION_READ_WRITE_SO_EXISTS"); +ENUM_NEXT(ck_rv_names, CKR_SIGNATURE_INVALID, CKR_SIGNATURE_LEN_RANGE, + CKR_SESSION_READ_WRITE_SO_EXISTS, + "SIGNATURE_INVALID", + "SIGNATURE_LEN_RANGE"); +ENUM_NEXT(ck_rv_names, CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT, + CKR_SIGNATURE_LEN_RANGE, + "TEMPLATE_INCOMPLETE", + "TEMPLATE_INCONSISTENT", +); +ENUM_NEXT(ck_rv_names, CKR_TOKEN_NOT_PRESENT, CKR_TOKEN_WRITE_PROTECTED, + CKR_TEMPLATE_INCONSISTENT, + "TOKEN_NOT_PRESENT", + "TOKEN_NOT_RECOGNIZED", + "TOKEN_WRITE_PROTECTED"); +ENUM_NEXT(ck_rv_names, CKR_UNWRAPPING_KEY_HANDLE_INVALID, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, + CKR_TOKEN_WRITE_PROTECTED, + "UNWRAPPING_KEY_HANDLE_INVALID", + "UNWRAPPING_KEY_SIZE_RANGE", + "UNWRAPPING_KEY_TYPE_INCONSISTENT"); +ENUM_NEXT(ck_rv_names, CKR_USER_ALREADY_LOGGED_IN, CKR_USER_TOO_MANY_TYPES, + CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, + "USER_ALREADY_LOGGED_IN", + "USER_NOT_LOGGED_IN", + "USER_PIN_NOT_INITIALIZED", + "USER_TYPE_INVALID", + "USER_ANOTHER_ALREADY_LOGGED_IN", + "USER_TOO_MANY_TYPES"); +ENUM_NEXT(ck_rv_names, CKR_WRAPPED_KEY_INVALID, CKR_WRAPPING_KEY_TYPE_INCONSISTENT, + CKR_USER_TOO_MANY_TYPES, + "WRAPPED_KEY_INVALID", + "(0x111)", + "WRAPPED_KEY_LEN_RANGE", + "WRAPPING_KEY_HANDLE_INVALID", + "WRAPPING_KEY_SIZE_RANGE", + "WRAPPING_KEY_TYPE_INCONSISTENT"); +ENUM_NEXT(ck_rv_names, CKR_RANDOM_SEED_NOT_SUPPORTED, CKR_RANDOM_NO_RNG, + CKR_WRAPPING_KEY_TYPE_INCONSISTENT, + "RANDOM_SEED_NOT_SUPPORTED", + "RANDOM_NO_RNG"); +ENUM_NEXT(ck_rv_names, CKR_DOMAIN_PARAMS_INVALID, CKR_DOMAIN_PARAMS_INVALID, + CKR_RANDOM_NO_RNG, + "DOMAIN_PARAMS_INVALID"); +ENUM_NEXT(ck_rv_names, CKR_BUFFER_TOO_SMALL, CKR_BUFFER_TOO_SMALL, + CKR_DOMAIN_PARAMS_INVALID, + "BUFFER_TOO_SMALL"); +ENUM_NEXT(ck_rv_names, CKR_SAVED_STATE_INVALID, CKR_SAVED_STATE_INVALID, + CKR_BUFFER_TOO_SMALL, + "SAVED_STATE_INVALID"); +ENUM_NEXT(ck_rv_names, CKR_INFORMATION_SENSITIVE, CKR_INFORMATION_SENSITIVE, + CKR_SAVED_STATE_INVALID, + "INFORMATION_SENSITIVE"); +ENUM_NEXT(ck_rv_names, CKR_STATE_UNSAVEABLE, CKR_STATE_UNSAVEABLE, + CKR_INFORMATION_SENSITIVE, + "STATE_UNSAVEABLE"); +ENUM_NEXT(ck_rv_names, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CRYPTOKI_ALREADY_INITIALIZED, + CKR_STATE_UNSAVEABLE, + "CRYPTOKI_NOT_INITIALIZED", + "CRYPTOKI_ALREADY_INITIALIZED"); +ENUM_NEXT(ck_rv_names, CKR_MUTEX_BAD, CKR_MUTEX_NOT_LOCKED, + CKR_CRYPTOKI_ALREADY_INITIALIZED, + "MUTEX_BAD", + "MUTEX_NOT_LOCKED"); +ENUM_NEXT(ck_rv_names, CKR_FUNCTION_REJECTED, CKR_FUNCTION_REJECTED, + CKR_MUTEX_NOT_LOCKED, + "FUNCTION_REJECTED"); +ENUM_END(ck_rv_names, CKR_FUNCTION_REJECTED); + + +ENUM_BEGIN(ck_mech_names, CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_DSA_SHA1, + "RSA_PKCS_KEY_PAIR_GEN", + "RSA_PKCS", + "RSA_9796", + "RSA_X_509", + "MD2_RSA_PKCS", + "MD5_RSA_PKCS", + "SHA1_RSA_PKCS", + "RIPEMD128_RSA_PKCS", + "RIPEMD160_RSA_PKCS", + "RSA_PKCS_OAEP", + "RSA_X9_31_KEY_PAIR_GEN", + "RSA_X9_31", + "SHA1_RSA_X9_31", + "RSA_PKCS_PSS", + "SHA1_RSA_PKCS_PSS", + "(0xf)", + "DSA_KEY_PAIR_GEN", + "DSA", + "DSA_SHA1"); +ENUM_NEXT(ck_mech_names, CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE, + CKM_DSA_SHA1, + "DH_PKCS_KEY_PAIR_GEN", + "DH_PKCS_DERIVE"); +ENUM_NEXT(ck_mech_names, CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_MQV_DERIVE, + CKM_DH_PKCS_DERIVE, + "X9_42_DH_KEY_PAIR_GEN", + "X9_42_DH_DERIVE", + "X9_42_DH_HYBRID_DERIVE", + "X9_42_MQV_DERIVE"); +ENUM_NEXT(ck_mech_names, CKM_SHA256_RSA_PKCS, CKM_SHA512_RSA_PKCS_PSS, + CKM_X9_42_MQV_DERIVE, + "SHA256_RSA_PKCS", + "SHA384_RSA_PKCS", + "SHA512_RSA_PKCS", + "SHA256_RSA_PKCS_PSS", + "SHA384_RSA_PKCS_PSS", + "SHA512_RSA_PKCS_PSS"); +ENUM_NEXT(ck_mech_names, CKM_RC2_KEY_GEN, CKM_RC2_CBC_PAD, + CKM_SHA512_RSA_PKCS_PSS, + "RC2_KEY_GEN", + "RC2_ECB", + "RC2_CBC", + "RC2_MAC", + "RC2_MAC_GENERAL", + "RC2_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_RC4_KEY_GEN, CKM_RC4, + CKM_RC2_CBC_PAD, + "RC4_KEY_GEN", + "RC4"); +ENUM_NEXT(ck_mech_names, CKM_DES_KEY_GEN, CKM_DES_CBC_PAD, + CKM_RC4, + "DES_KEY_GEN", + "DES_ECB", + "DES_CBC", + "DES_MAC", + "DES_MAC_GENERAL", + "DES_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_DES2_KEY_GEN, CKM_DES3_CBC_PAD, + CKM_DES_CBC_PAD, + "DES2_KEY_GEN", + "DES3_KEY_GEN", + "DES3_ECB", + "DES3_CBC", + "DES3_MAC", + "DES3_MAC_GENERAL", + "DES3_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_CDMF_KEY_GEN, CKM_CDMF_CBC_PAD, + CKM_DES3_CBC_PAD, + "CDMF_KEY_GEN", + "CDMF_ECB", + "CDMF_CBC", + "CDMF_MAC", + "CDMF_MAC_GENERAL", + "CDMF_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_MD2, CKM_MD2_HMAC_GENERAL, + CKM_CDMF_CBC_PAD, + "MD2", + "MD2_HMAC", + "MD2_HMAC_GENERAL"); +ENUM_NEXT(ck_mech_names, CKM_MD5, CKM_MD5_HMAC_GENERAL, + CKM_MD2_HMAC_GENERAL, + "MD5", + "MD5_HMAC", + "MD5_HMAC_GENERAL"); +ENUM_NEXT(ck_mech_names, CKM_SHA_1, CKM_SHA_1_HMAC_GENERAL, + CKM_MD5_HMAC_GENERAL, + "SHA_1", + "SHA_1_HMAC", + "SHA_1_HMAC_GENERAL"); +ENUM_NEXT(ck_mech_names, CKM_RIPEMD128, CKM_RIPEMD128_HMAC_GENERAL, + CKM_SHA_1_HMAC_GENERAL, + "RIPEMD128", + "RIPEMD128_HMAC", + "RIPEMD128_HMAC_GENERAL"); +ENUM_NEXT(ck_mech_names, CKM_RIPEMD160, CKM_RIPEMD160_HMAC_GENERAL, + CKM_RIPEMD128_HMAC_GENERAL, + "RIPEMD160", + "RIPEMD160_HMAC", + "RIPEMD160_HMAC_GENERAL"); +ENUM_NEXT(ck_mech_names, CKM_SHA256, CKM_SHA256_HMAC_GENERAL, + CKM_RIPEMD160_HMAC_GENERAL, + "SHA256", + "SHA256_HMAC", + "SHA256_HMAC_GENERAL"); +ENUM_NEXT(ck_mech_names, CKM_SHA384, CKM_SHA384_HMAC_GENERAL, + CKM_SHA256_HMAC_GENERAL, + "SHA384", + "SHA384_HMAC", + "SHA384_HMAC_GENERAL"); +ENUM_NEXT(ck_mech_names, CKM_SHA512, CKM_SHA512_HMAC_GENERAL, + CKM_SHA384_HMAC_GENERAL , + "SHA512", + "SHA512_HMAC", + "SHA512_HMAC_GENERAL"); +ENUM_NEXT(ck_mech_names, CKM_CAST_KEY_GEN, CKM_CAST_CBC_PAD, + CKM_SHA512_HMAC_GENERAL, + "CAST_KEY_GEN", + "CAST_ECB", + "CAST_CBC", + "CAST_MAC", + "CAST_MAC_GENERAL", + "CAST_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_CAST3_KEY_GEN, CKM_CAST3_CBC_PAD, + CKM_CAST_CBC_PAD, + "CAST3_KEY_GEN", + "CAST3_ECB", + "CAST3_CBC", + "CAST3_MAC", + "CAST3_MAC_GENERAL", + "CAST3_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_CAST128_KEY_GEN, CKM_CAST128_CBC_PAD, + CKM_CAST3_CBC_PAD, + "CAST128_KEY_GEN", + "CAST128_ECB", + "CAST128_CBC", + "CAST128_MAC", + "CAST128_MAC_GENERAL", + "CAST128_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_RC5_KEY_GEN, CKM_RC5_CBC_PAD, + CKM_CAST128_CBC_PAD, + "RC5_KEY_GEN", + "RC5_ECB", + "RC5_CBC", + "RC5_MAC", + "RC5_MAC_GENERAL", + "RC5_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_IDEA_KEY_GEN, CKM_IDEA_CBC_PAD, + CKM_RC5_CBC_PAD, + "IDEA_KEY_GEN", + "IDEA_ECB", + "IDEA_CBC", + "IDEA_MAC", + "IDEA_MAC_GENERAL", + "IDEA_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_GENERIC_SECRET_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN, + CKM_IDEA_CBC_PAD, + "GENERIC_SECRET_KEY_GEN"); +ENUM_NEXT(ck_mech_names, CKM_CONCATENATE_BASE_AND_KEY, CKM_EXTRACT_KEY_FROM_KEY, + CKM_GENERIC_SECRET_KEY_GEN, + "CONCATENATE_BASE_AND_KEY", + "(0x361)", + "CONCATENATE_BASE_AND_DATA", + "CONCATENATE_DATA_AND_BASE", + "XOR_BASE_AND_DATA", + "EXTRACT_KEY_FROM_KEY"); +ENUM_NEXT(ck_mech_names, CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_MASTER_KEY_DERIVE_DH, + CKM_EXTRACT_KEY_FROM_KEY, + "SSL3_PRE_MASTER_KEY_GEN", + "SSL3_MASTER_KEY_DERIVE", + "SSL3_KEY_AND_MAC_DERIVE", + "SSL3_MASTER_KEY_DERIVE_DH", + "TLS_PRE_MASTER_KEY_GEN", + "TLS_MASTER_KEY_DERIVE", + "TLS_KEY_AND_MAC_DERIVE", + "TLS_MASTER_KEY_DERIVE_DH"); +ENUM_NEXT(ck_mech_names, CKM_SSL3_MD5_MAC, CKM_SSL3_SHA1_MAC, + CKM_TLS_MASTER_KEY_DERIVE_DH, + "SSL3_MD5_MAC", + "SSL3_SHA1_MAC"); +ENUM_NEXT(ck_mech_names, CKM_MD5_KEY_DERIVATION, CKM_SHA1_KEY_DERIVATION, + CKM_SSL3_SHA1_MAC, + "MD5_KEY_DERIVATION", + "MD2_KEY_DERIVATION", + "SHA1_KEY_DERIVATION"); +ENUM_NEXT(ck_mech_names, CKM_PBE_MD2_DES_CBC, CKM_PBE_SHA1_RC2_40_CBC, + CKM_SHA1_KEY_DERIVATION, + "PBE_MD2_DES_CBC", + "PBE_MD5_DES_CBC", + "PBE_MD5_CAST_CBC", + "PBE_MD5_CAST3_CBC", + "PBE_MD5_CAST128_CBC", + "PBE_SHA1_CAST128_CBC", + "PBE_SHA1_RC4_128", + "PBE_SHA1_RC4_40", + "PBE_SHA1_DES3_EDE_CBC", + "PBE_SHA1_DES2_EDE_CBC", + "PBE_SHA1_RC2_128_CBC", + "PBE_SHA1_RC2_40_CBC"); +ENUM_NEXT(ck_mech_names, CKM_PKCS5_PBKD2, CKM_PKCS5_PBKD2, + CKM_PBE_SHA1_RC2_40_CBC, + "PKCS5_PBKD2"); +ENUM_NEXT(ck_mech_names, CKM_PBA_SHA1_WITH_SHA1_HMAC, CKM_PBA_SHA1_WITH_SHA1_HMAC, + CKM_PKCS5_PBKD2, + "PBA_SHA1_WITH_SHA1_HMAC"); +ENUM_NEXT(ck_mech_names, CKM_KEY_WRAP_LYNKS, CKM_KEY_WRAP_SET_OAEP, + CKM_PBA_SHA1_WITH_SHA1_HMAC, + "KEY_WRAP_LYNKS", + "KEY_WRAP_SET_OAEP"); +ENUM_NEXT(ck_mech_names, CKM_SKIPJACK_KEY_GEN, CKM_SKIPJACK_RELAYX, + CKM_KEY_WRAP_SET_OAEP, + "SKIPJACK_KEY_GEN", + "SKIPJACK_ECB64", + "SKIPJACK_CBC64", + "SKIPJACK_OFB64", + "SKIPJACK_CFB64", + "SKIPJACK_CFB32", + "SKIPJACK_CFB16", + "SKIPJACK_CFB8", + "SKIPJACK_WRAP", + "SKIPJACK_PRIVATE_WRAP", + "SKIPJACK_RELAYX"); +ENUM_NEXT(ck_mech_names, CKM_KEA_KEY_PAIR_GEN, CKM_KEA_KEY_DERIVE, + CKM_SKIPJACK_RELAYX, + "KEA_KEY_PAIR_GEN", + "KEA_KEY_DERIVE"); +ENUM_NEXT(ck_mech_names, CKM_FORTEZZA_TIMESTAMP, CKM_FORTEZZA_TIMESTAMP, + CKM_KEA_KEY_DERIVE, + "FORTEZZA_TIMESTAMP"); +ENUM_NEXT(ck_mech_names, CKM_BATON_KEY_GEN, CKM_BATON_WRAP, + CKM_FORTEZZA_TIMESTAMP, + "BATON_KEY_GEN", + "BATON_ECB128", + "BATON_ECB96", + "BATON_CBC128", + "BATON_COUNTER", + "BATON_SHUFFLE", + "BATON_WRAP"); +ENUM_NEXT(ck_mech_names, CKM_ECDSA_KEY_PAIR_GEN, CKM_ECDSA_SHA1, + CKM_BATON_WRAP, + "ECDSA_KEY_PAIR_GEN", + "ECDSA", + "ECDSA_SHA1"); +ENUM_NEXT(ck_mech_names, CKM_ECDH1_DERIVE, CKM_ECMQV_DERIVE, + CKM_ECDSA_SHA1, + "ECDH1_DERIVE", + "ECDH1_COFACTOR_DERIVE", + "ECMQV_DERIVE"); +ENUM_NEXT(ck_mech_names, CKM_JUNIPER_KEY_GEN, CKM_JUNIPER_WRAP, + CKM_ECMQV_DERIVE, + "JUNIPER_KEY_GEN", + "JUNIPER_ECB128", + "JUNIPER_CBC128", + "JUNIPER_COUNTER", + "JUNIPER_SHUFFLE", + "JUNIPER_WRAP"); +ENUM_NEXT(ck_mech_names, CKM_FASTHASH, CKM_FASTHASH, + CKM_JUNIPER_WRAP, + "FASTHASH"); +ENUM_NEXT(ck_mech_names, CKM_AES_KEY_GEN, CKM_AES_CBC_PAD, + CKM_FASTHASH, + "AES_KEY_GEN", + "AES_ECB", + "AES_CBC", + "AES_MAC", + "AES_MAC_GENERAL", + "AES_CBC_PAD"); +ENUM_NEXT(ck_mech_names, CKM_DSA_PARAMETER_GEN, CKM_X9_42_DH_PARAMETER_GEN, + CKM_AES_CBC_PAD, + "DSA_PARAMETER_GEN", + "DH_PKCS_PARAMETER_GEN", + "X9_42_DH_PARAMETER_GEN"); +ENUM_END(ck_mech_names, CKM_X9_42_DH_PARAMETER_GEN); + +/** + * Private data of an pkcs11_library_t object. + */ +struct private_pkcs11_library_t { + + /** + * Public pkcs11_library_t interface. + */ + pkcs11_library_t public; + + /** + * dlopen() handle + */ + void *handle; + + /** + * Name as passed to the constructor + */ + char *name; +}; + +METHOD(pkcs11_library_t, get_name, char*, + private_pkcs11_library_t *this) +{ + return this->name; +} + +/** + * Object enumerator + */ +typedef struct { + /* implements enumerator_t */ + enumerator_t public; + /* session */ + CK_SESSION_HANDLE session; + /* pkcs11 library */ + pkcs11_library_t *lib; + /* attributes to retreive */ + CK_ATTRIBUTE_PTR attr; + /* number of attributes */ + CK_ULONG count; + /* currently allocated attributes, to free */ + linked_list_t *freelist; +} object_enumerator_t; + +/** + * Free contents of attributes in a list + */ +static void free_attrs(object_enumerator_t *this) +{ + CK_ATTRIBUTE_PTR attr; + + while (this->freelist->remove_last(this->freelist, (void**)&attr) == SUCCESS) + { + free(attr->pValue); + attr->pValue = NULL; + attr->ulValueLen = 0; + } +} + +/** + * Get attributes for a given object during enumeration + */ +static bool get_attributes(object_enumerator_t *this, CK_OBJECT_HANDLE object) +{ + CK_RV rv; + int i; + + free_attrs(this); + + /* get length of objects first */ + rv = this->lib->f->C_GetAttributeValue(this->session, object, + this->attr, this->count); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_GetAttributeValue(NULL) error: %N", ck_rv_names, rv); + return FALSE; + } + /* allocate required chunks */ + for (i = 0; i < this->count; i++) + { + if (this->attr[i].pValue == NULL && + this->attr[i].ulValueLen != 0 && this->attr[i].ulValueLen != -1) + { + this->attr[i].pValue = malloc(this->attr[i].ulValueLen); + this->freelist->insert_last(this->freelist, &this->attr[i]); + } + } + /* get the data */ + rv = this->lib->f->C_GetAttributeValue(this->session, object, + this->attr, this->count); + if (rv != CKR_OK) + { + free_attrs(this); + DBG1(DBG_CFG, "C_GetAttributeValue(NULL) error: %N", ck_rv_names, rv); + return FALSE; + } + return TRUE; +} + +METHOD(enumerator_t, object_enumerate, bool, + object_enumerator_t *this, CK_OBJECT_HANDLE *out) +{ + CK_OBJECT_HANDLE object; + CK_ULONG found; + CK_RV rv; + + rv = this->lib->f->C_FindObjects(this->session, &object, 1, &found); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_FindObjects() failed: %N", ck_rv_names, rv); + return FALSE; + } + if (found) + { + if (this->attr) + { + if (!get_attributes(this, object)) + { + return FALSE; + } + } + *out = object; + return TRUE; + } + return FALSE; +} + +METHOD(enumerator_t, object_destroy, void, + object_enumerator_t *this) +{ + this->lib->f->C_FindObjectsFinal(this->session); + free_attrs(this); + this->freelist->destroy(this->freelist); + free(this); +} + +METHOD(pkcs11_library_t, create_object_enumerator, enumerator_t*, + private_pkcs11_library_t *this, CK_SESSION_HANDLE session, + CK_ATTRIBUTE_PTR tmpl, CK_ULONG tcount, + CK_ATTRIBUTE_PTR attr, CK_ULONG acount) +{ + object_enumerator_t *enumerator; + CK_RV rv; + + rv = this->public.f->C_FindObjectsInit(session, tmpl, tcount); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_FindObjectsInit() failed: %N", ck_rv_names, rv); + return enumerator_create_empty(); + } + + INIT(enumerator, + .public = { + .enumerate = (void*)_object_enumerate, + .destroy = _object_destroy, + }, + .session = session, + .lib = &this->public, + .attr = attr, + .count = acount, + .freelist = linked_list_create(), + ); + return &enumerator->public; +} + +/** + * Enumerator over mechanisms + */ +typedef struct { + /* implements enumerator_t */ + enumerator_t public; + /* PKCS#11 library */ + pkcs11_library_t *lib; + /* slot of token */ + CK_SLOT_ID slot; + /* mechanism type list */ + CK_MECHANISM_TYPE_PTR mechs; + /* number of mechanism types */ + CK_ULONG count; + /* current mechanism */ + CK_ULONG current; +} mechanism_enumerator_t; + +METHOD(enumerator_t, enumerate_mech, bool, + mechanism_enumerator_t *this, CK_MECHANISM_TYPE* type, + CK_MECHANISM_INFO *info) +{ + CK_RV rv; + + if (this->current >= this->count) + { + return FALSE; + } + if (info) + { + rv = this->lib->f->C_GetMechanismInfo(this->slot, + this->mechs[this->current], info); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_GetMechanismInfo() failed: %N", ck_rv_names, rv); + return FALSE; + } + } + *type = this->mechs[this->current++]; + return TRUE; +} + +METHOD(enumerator_t, destroy_mech, void, + mechanism_enumerator_t *this) +{ + free(this->mechs); + free(this); +} + +METHOD(pkcs11_library_t, create_mechanism_enumerator, enumerator_t*, + private_pkcs11_library_t *this, CK_SLOT_ID slot) +{ + mechanism_enumerator_t *enumerator; + CK_RV rv; + + INIT(enumerator, + .public = { + .enumerate = (void*)_enumerate_mech, + .destroy = _destroy_mech, + }, + .lib = &this->public, + .slot = slot, + ); + + rv = enumerator->lib->f->C_GetMechanismList(slot, NULL, &enumerator->count); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_GetMechanismList() failed: %N", ck_rv_names, rv); + free(enumerator); + return enumerator_create_empty(); + } + enumerator->mechs = malloc(sizeof(CK_MECHANISM_TYPE) * enumerator->count); + enumerator->lib->f->C_GetMechanismList(slot, enumerator->mechs, + &enumerator->count); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_GetMechanismList() failed: %N", ck_rv_names, rv); + destroy_mech(enumerator); + return enumerator_create_empty(); + } + return &enumerator->public; +} + +METHOD(pkcs11_library_t, destroy, void, + private_pkcs11_library_t *this) +{ + this->public.f->C_Finalize(NULL); + dlclose(this->handle); + free(this); +} + +/** + * See header + */ +void pkcs11_library_trim(char *str, int len) +{ + int i; + + str[len - 1] = '\0'; + for (i = len - 2; i > 0; i--) + { + if (str[i] == ' ') + { + str[i] = '\0'; + continue; + } + break; + } +} + +/** + * Mutex creation callback + */ +static CK_RV CreateMutex(CK_VOID_PTR_PTR data) +{ + *data = mutex_create(MUTEX_TYPE_DEFAULT); + return CKR_OK; +} + +/** + * Mutex destruction callback + */ +static CK_RV DestroyMutex(CK_VOID_PTR data) +{ + mutex_t *mutex = (mutex_t*)data; + + mutex->destroy(mutex); + return CKR_OK; +} + +/** + * Mutex lock callback + */ +static CK_RV LockMutex(CK_VOID_PTR data) +{ + mutex_t *mutex = (mutex_t*)data; + + mutex->lock(mutex); + return CKR_OK; +} + +/** + * Mutex unlock callback + */ +static CK_RV UnlockMutex(CK_VOID_PTR data) +{ + mutex_t *mutex = (mutex_t*)data; + + mutex->unlock(mutex); + return CKR_OK; +} + +/** + * Initialize a PKCS#11 library + */ +static bool initialize(private_pkcs11_library_t *this, char *name, char *file) +{ + CK_C_GetFunctionList pC_GetFunctionList; + CK_INFO info; + CK_RV rv; + CK_C_INITIALIZE_ARGS args = { + .CreateMutex = CreateMutex, + .DestroyMutex = DestroyMutex, + .LockMutex = LockMutex, + .UnlockMutex = UnlockMutex, + }; + + pC_GetFunctionList = dlsym(this->handle, "C_GetFunctionList"); + if (!pC_GetFunctionList) + { + DBG1(DBG_CFG, "C_GetFunctionList not found for '%s': %s", name, dlerror()); + return FALSE; + } + rv = pC_GetFunctionList(&this->public.f); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_GetFunctionList() error for '%s': %N", + name, ck_rv_names, rv); + return FALSE; + } + + rv = this->public.f->C_Initialize(&args); + if (rv == CKR_CANT_LOCK) + { /* try OS locking */ + memset(&args, 0, sizeof(args)); + args.flags = CKF_OS_LOCKING_OK; + rv = this->public.f->C_Initialize(&args); + } + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_Initialize() error for '%s': %N", + name, ck_rv_names, rv); + return FALSE; + } + rv = this->public.f->C_GetInfo(&info); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "C_GetInfo() error for '%s': %N", + name, ck_rv_names, rv); + this->public.f->C_Finalize(NULL); + return FALSE; + } + + pkcs11_library_trim(info.manufacturerID, + strnlen(info.manufacturerID, sizeof(info.manufacturerID))); + pkcs11_library_trim(info.libraryDescription, + strnlen(info.libraryDescription, sizeof(info.libraryDescription))); + + DBG1(DBG_CFG, "loaded PKCS#11 v%d.%d library '%s' (%s)", + info.cryptokiVersion.major, info.cryptokiVersion.minor, name, file); + DBG1(DBG_CFG, " %s: %s v%d.%d", + info.manufacturerID, info.libraryDescription, + info.libraryVersion.major, info.libraryVersion.minor); + if (args.flags & CKF_OS_LOCKING_OK) + { + DBG1(DBG_CFG, " uses OS locking functions"); + } + return TRUE; +} + +/** + * See header + */ +pkcs11_library_t *pkcs11_library_create(char *name, char *file) +{ + private_pkcs11_library_t *this; + + INIT(this, + .public = { + .get_name = _get_name, + .create_object_enumerator = _create_object_enumerator, + .create_mechanism_enumerator = _create_mechanism_enumerator, + .destroy = _destroy, + }, + .name = name, + .handle = dlopen(file, RTLD_LAZY), + ); + + if (!this->handle) + { + DBG1(DBG_CFG, "opening PKCS#11 library failed: %s", dlerror()); + free(this); + return NULL; + } + + if (!initialize(this, name, file)) + { + dlclose(this->handle); + free(this); + return NULL; + } + + return &this->public; +} |