summaryrefslogtreecommitdiff
path: root/src/libstrongswan/plugins/pkcs11/pkcs11_library.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/plugins/pkcs11/pkcs11_library.c')
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_library.c869
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;
+}