diff options
Diffstat (limited to 'src/pluto/smartcard.c')
-rw-r--r-- | src/pluto/smartcard.c | 2746 |
1 files changed, 1380 insertions, 1366 deletions
diff --git a/src/pluto/smartcard.c b/src/pluto/smartcard.c index 937c3f93a..7e4452d89 100644 --- a/src/pluto/smartcard.c +++ b/src/pluto/smartcard.c @@ -6,7 +6,7 @@ * Copyright (C) 2005 Michael Joosten * * Copyright (C) 2005 Andreas Steffen - * Hochschule für Technik Rapperswil, Switzerland + * Hochschule fuer Technik Rapperswil, Switzerland * * 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 @@ -17,8 +17,6 @@ * 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. - * - * RCSID $Id: smartcard.c 3686 2008-03-28 11:48:14Z martin $ */ #include <stdio.h> @@ -30,7 +28,9 @@ #include <dlfcn.h> #include <freeswan.h> -#include <ipsec_policy.h> + +#include <asn1/asn1.h> +#include <credentials/keys/public_key.h> #include "constants.h" @@ -40,7 +40,6 @@ #endif #include "defs.h" -#include "mp_defs.h" #include "log.h" #include "x509.h" #include "ca.h" @@ -50,7 +49,7 @@ #include "whack.h" #include "fetch.h" -#define DEFAULT_BASE 16 +#define DEFAULT_BASE 16 /* chained list of smartcard records */ static smartcard_t *smartcards = NULL; @@ -59,30 +58,30 @@ static smartcard_t *smartcards = NULL; static int sc_number = 0; const smartcard_t empty_sc = { - NULL , /* next */ - 0 , /* last_load */ - { CERT_NONE, {NULL} }, /* last_cert */ - 0 , /* count */ - 0 , /* number */ - 999999 , /* slot */ - NULL , /* id */ - NULL , /* label */ - { NULL, 0 } , /* pin */ - FALSE , /* pinpad */ - FALSE , /* valid */ - FALSE , /* session_opened */ - FALSE , /* logged_in */ - TRUE , /* any_slot */ - 0L , /* session */ + NULL , /* next */ + 0 , /* last_load */ + { CERT_NONE, {NULL} }, /* last_cert */ + 0 , /* count */ + 0 , /* number */ + 999999 , /* slot */ + NULL , /* id */ + NULL , /* label */ + { NULL, 0 } , /* pin */ + FALSE , /* pinpad */ + FALSE , /* valid */ + FALSE , /* session_opened */ + FALSE , /* logged_in */ + TRUE , /* any_slot */ + 0L , /* session */ }; -#ifdef SMARTCARD /* compile with smartcard support */ +#ifdef SMARTCARD /* compile with smartcard support */ -#define SCX_MAGIC 0xd00bed00 +#define SCX_MAGIC 0xd00bed00 struct scx_pkcs11_module { - u_int _magic; - void *handle; + u_int _magic; + void *handle; }; typedef struct scx_pkcs11_module scx_pkcs11_module_t; @@ -95,292 +94,292 @@ static CK_FUNCTION_LIST_PTR pkcs11_functions = NULL_PTR; /* crytoki v2.11 - return values of PKCS #11 functions*/ static const char *const pkcs11_return_name[] = { - "CKR_OK", - "CKR_CANCEL", - "CKR_HOST_MEMORY", - "CKR_SLOT_ID_INVALID", - "CKR_FLAGS_INVALID", - "CKR_GENERAL_ERROR", - "CKR_FUNCTION_FAILED", - "CKR_ARGUMENTS_BAD", - "CKR_NO_EVENT", - "CKR_NEED_TO_CREATE_THREADS", - "CKR_CANT_LOCK" - }; + "CKR_OK", + "CKR_CANCEL", + "CKR_HOST_MEMORY", + "CKR_SLOT_ID_INVALID", + "CKR_FLAGS_INVALID", + "CKR_GENERAL_ERROR", + "CKR_FUNCTION_FAILED", + "CKR_ARGUMENTS_BAD", + "CKR_NO_EVENT", + "CKR_NEED_TO_CREATE_THREADS", + "CKR_CANT_LOCK" + }; static const char *const pkcs11_return_name_10[] = { - "CKR_ATTRIBUTE_READ_ONLY", - "CKR_ATTRIBUTE_SENSITIVE", - "CKR_ATTRIBUTE_TYPE_INVALID", - "CKR_ATTRIBUTE_VALUE_INVALID" - }; + "CKR_ATTRIBUTE_READ_ONLY", + "CKR_ATTRIBUTE_SENSITIVE", + "CKR_ATTRIBUTE_TYPE_INVALID", + "CKR_ATTRIBUTE_VALUE_INVALID" + }; static const char *const pkcs11_return_name_20[] = { - "CKR_DATA_INVALID", - "CKR_DATA_LEN_RANGE" - }; + "CKR_DATA_INVALID", + "CKR_DATA_LEN_RANGE" + }; static const char *const pkcs11_return_name_30[] = { - "CKR_DEVICE_ERROR", - "CKR_DEVICE_MEMORY", - "CKR_DEVICE_REMOVED" - }; + "CKR_DEVICE_ERROR", + "CKR_DEVICE_MEMORY", + "CKR_DEVICE_REMOVED" + }; static const char *const pkcs11_return_name_40[] = { - "CKR_ENCRYPTED_DATA_INVALID", - "CKR_ENCRYPTED_DATA_LEN_RANGE" - }; + "CKR_ENCRYPTED_DATA_INVALID", + "CKR_ENCRYPTED_DATA_LEN_RANGE" + }; static const char *const pkcs11_return_name_50[] = { - "CKR_FUNCTION_CANCELED", - "CKR_FUNCTION_NOT_PARALLEL", - "CKR_0x52_UNDEFINED", - "CKR_0x53_UNDEFINED", - "CKR_FUNCTION_NOT_SUPPORTED" - }; + "CKR_FUNCTION_CANCELED", + "CKR_FUNCTION_NOT_PARALLEL", + "CKR_0x52_UNDEFINED", + "CKR_0x53_UNDEFINED", + "CKR_FUNCTION_NOT_SUPPORTED" + }; static const char *const pkcs11_return_name_60[] = { - "CKR_KEY_HANDLE_INVALID", - "CKR_KEY_SENSITIVE", - "CKR_KEY_SIZE_RANGE", - "CKR_KEY_TYPE_INCONSISTENT", - "CKR_KEY_NOT_NEEDED", - "CKR_KEY_CHANGED", - "CKR_KEY_NEEDED", - "CKR_KEY_INDIGESTIBLE", - "CKR_KEY_FUNCTION_NOT_PERMITTED", - "CKR_KEY_NOT_WRAPPABLE", - "CKR_KEY_UNEXTRACTABLE" - }; + "CKR_KEY_HANDLE_INVALID", + "CKR_KEY_SENSITIVE", + "CKR_KEY_SIZE_RANGE", + "CKR_KEY_TYPE_INCONSISTENT", + "CKR_KEY_NOT_NEEDED", + "CKR_KEY_CHANGED", + "CKR_KEY_NEEDED", + "CKR_KEY_INDIGESTIBLE", + "CKR_KEY_FUNCTION_NOT_PERMITTED", + "CKR_KEY_NOT_WRAPPABLE", + "CKR_KEY_UNEXTRACTABLE" + }; static const char *const pkcs11_return_name_70[] = { - "CKR_MECHANISM_INVALID", - "CKR_MECHANISM_PARAM_INVALID" - }; + "CKR_MECHANISM_INVALID", + "CKR_MECHANISM_PARAM_INVALID" + }; static const char *const pkcs11_return_name_80[] = { - "CKR_OBJECT_HANDLE_INVALID" - }; + "CKR_OBJECT_HANDLE_INVALID" + }; static const char *const pkcs11_return_name_90[] = { - "CKR_OPERATION_ACTIVE", - "CKR_OPERATION_NOT_INITIALIZED" - }; + "CKR_OPERATION_ACTIVE", + "CKR_OPERATION_NOT_INITIALIZED" + }; static const char *const pkcs11_return_name_A0[] = { - "CKR_PIN_INCORRECT", - "CKR_PIN_INVALID", - "CKR_PIN_LEN_RANGE", - "CKR_PIN_EXPIRED", - "CKR_PIN_LOCKED" - }; + "CKR_PIN_INCORRECT", + "CKR_PIN_INVALID", + "CKR_PIN_LEN_RANGE", + "CKR_PIN_EXPIRED", + "CKR_PIN_LOCKED" + }; static const char *const pkcs11_return_name_B0[] = { - "CKR_SESSION_CLOSED", - "CKR_SESSION_COUNT", - "CKR_0xB2_UNDEFINED", - "CKR_SESSION_HANDLE_INVALID", - "CKR_SESSION_PARALLEL_NOT_SUPPORTED", - "CKR_SESSION_READ_ONLY", - "CKR_SESSION_EXISTS", - "CKR_SESSION_READ_ONLY_EXISTS", - "CKR_SESSION_READ_WRITE_SO_EXISTS" - }; + "CKR_SESSION_CLOSED", + "CKR_SESSION_COUNT", + "CKR_0xB2_UNDEFINED", + "CKR_SESSION_HANDLE_INVALID", + "CKR_SESSION_PARALLEL_NOT_SUPPORTED", + "CKR_SESSION_READ_ONLY", + "CKR_SESSION_EXISTS", + "CKR_SESSION_READ_ONLY_EXISTS", + "CKR_SESSION_READ_WRITE_SO_EXISTS" + }; static const char *const pkcs11_return_name_C0[] = { - "CKR_SIGNATURE_INVALID", - "CKR_SIGNATURE_LEN_RANGE" - }; + "CKR_SIGNATURE_INVALID", + "CKR_SIGNATURE_LEN_RANGE" + }; static const char *const pkcs11_return_name_D0[] = { - "CKR_TEMPLATE_INCOMPLETE", - "CKR_TEMPLATE_INCONSISTENT" - }; + "CKR_TEMPLATE_INCOMPLETE", + "CKR_TEMPLATE_INCONSISTENT" + }; static const char *const pkcs11_return_name_E0[] = { - "CKR_TOKEN_NOT_PRESENT", - "CKR_TOKEN_NOT_RECOGNIZED", - "CKR_TOKEN_WRITE_PROTECTED" - }; + "CKR_TOKEN_NOT_PRESENT", + "CKR_TOKEN_NOT_RECOGNIZED", + "CKR_TOKEN_WRITE_PROTECTED" + }; static const char *const pkcs11_return_name_F0[] = { - "CKR_UNWRAPPING_KEY_HANDLE_INVALID", - "CKR_UNWRAPPING_KEY_SIZE_RANGE", - "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT" - }; + "CKR_UNWRAPPING_KEY_HANDLE_INVALID", + "CKR_UNWRAPPING_KEY_SIZE_RANGE", + "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT" + }; static const char *const pkcs11_return_name_100[] = { - "CKR_USER_ALREADY_LOGGED_IN", - "CKR_USER_NOT_LOGGED_IN", - "CKR_USER_PIN_NOT_INITIALIZED", - "CKR_USER_TYPE_INVALID", - "CKR_USER_ANOTHER_ALREADY_LOGGED_IN", - "CKR_USER_TOO_MANY_TYPES" - }; + "CKR_USER_ALREADY_LOGGED_IN", + "CKR_USER_NOT_LOGGED_IN", + "CKR_USER_PIN_NOT_INITIALIZED", + "CKR_USER_TYPE_INVALID", + "CKR_USER_ANOTHER_ALREADY_LOGGED_IN", + "CKR_USER_TOO_MANY_TYPES" + }; static const char *const pkcs11_return_name_110[] = { - "CKR_WRAPPED_KEY_INVALID", - "CKR_0x111_UNDEFINED", - "CKR_WRAPPED_KEY_LEN_RANGE", - "CKR_WRAPPING_KEY_HANDLE_INVALID", - "CKR_WRAPPING_KEY_SIZE_RANGE", - "CKR_WRAPPING_KEY_TYPE_INCONSISTENT" - }; + "CKR_WRAPPED_KEY_INVALID", + "CKR_0x111_UNDEFINED", + "CKR_WRAPPED_KEY_LEN_RANGE", + "CKR_WRAPPING_KEY_HANDLE_INVALID", + "CKR_WRAPPING_KEY_SIZE_RANGE", + "CKR_WRAPPING_KEY_TYPE_INCONSISTENT" + }; static const char *const pkcs11_return_name_120[] = { - "CKR_RANDOM_SEED_NOT_SUPPORTED", - "CKR_RANDOM_NO_RNG" - }; + "CKR_RANDOM_SEED_NOT_SUPPORTED", + "CKR_RANDOM_NO_RNG" + }; static const char *const pkcs11_return_name_130[] = { - "CKR_DOMAIN_PARAMS_INVALID" - }; + "CKR_DOMAIN_PARAMS_INVALID" + }; static const char *const pkcs11_return_name_150[] = { - "CKR_BUFFER_TOO_SMALL" - }; + "CKR_BUFFER_TOO_SMALL" + }; static const char *const pkcs11_return_name_160[] = { - "CKR_SAVED_STATE_INVALID" - }; + "CKR_SAVED_STATE_INVALID" + }; static const char *const pkcs11_return_name_170[] = { - "CKR_INFORMATION_SENSITIVE" - }; + "CKR_INFORMATION_SENSITIVE" + }; static const char *const pkcs11_return_name_180[] = { - "CKR_STATE_UNSAVEABLE" - }; + "CKR_STATE_UNSAVEABLE" + }; static const char *const pkcs11_return_name_190[] = { - "CKR_CRYPTOKI_NOT_INITIALIZED", - "CKR_CRYPTOKI_ALREADY_INITIALIZED" - }; + "CKR_CRYPTOKI_NOT_INITIALIZED", + "CKR_CRYPTOKI_ALREADY_INITIALIZED" + }; static const char *const pkcs11_return_name_1A0[] = { - "CKR_MUTEX_BAD", - "CKR_MUTEX_NOT_LOCKED" - }; + "CKR_MUTEX_BAD", + "CKR_MUTEX_NOT_LOCKED" + }; static const char *const pkcs11_return_name_200[] = { - "CKR_FUNCTION_REJECTED" - }; + "CKR_FUNCTION_REJECTED" + }; static const char *const pkcs11_return_name_vendor[] = { - "CKR_VENDOR_DEFINED" - }; + "CKR_VENDOR_DEFINED" + }; static enum_names pkcs11_return_names_vendor = - { CKR_VENDOR_DEFINED, CKR_VENDOR_DEFINED - , pkcs11_return_name_vendor, NULL }; + { CKR_VENDOR_DEFINED, CKR_VENDOR_DEFINED + , pkcs11_return_name_vendor, NULL }; static enum_names pkcs11_return_names_200 = - { CKR_FUNCTION_REJECTED, CKR_FUNCTION_REJECTED - , pkcs11_return_name_200, &pkcs11_return_names_vendor }; + { CKR_FUNCTION_REJECTED, CKR_FUNCTION_REJECTED + , pkcs11_return_name_200, &pkcs11_return_names_vendor }; static enum_names pkcs11_return_names_1A0 = - { CKR_MUTEX_BAD, CKR_MUTEX_NOT_LOCKED - , pkcs11_return_name_1A0, &pkcs11_return_names_200 }; + { CKR_MUTEX_BAD, CKR_MUTEX_NOT_LOCKED + , pkcs11_return_name_1A0, &pkcs11_return_names_200 }; static enum_names pkcs11_return_names_190 = - { CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CRYPTOKI_ALREADY_INITIALIZED - , pkcs11_return_name_190, &pkcs11_return_names_1A0 }; + { CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CRYPTOKI_ALREADY_INITIALIZED + , pkcs11_return_name_190, &pkcs11_return_names_1A0 }; static enum_names pkcs11_return_names_180 = - { CKR_STATE_UNSAVEABLE, CKR_STATE_UNSAVEABLE - , pkcs11_return_name_180, &pkcs11_return_names_190 }; + { CKR_STATE_UNSAVEABLE, CKR_STATE_UNSAVEABLE + , pkcs11_return_name_180, &pkcs11_return_names_190 }; static enum_names pkcs11_return_names_170 = - { CKR_INFORMATION_SENSITIVE, CKR_INFORMATION_SENSITIVE - , pkcs11_return_name_170, &pkcs11_return_names_180 }; + { CKR_INFORMATION_SENSITIVE, CKR_INFORMATION_SENSITIVE + , pkcs11_return_name_170, &pkcs11_return_names_180 }; static enum_names pkcs11_return_names_160 = - { CKR_SAVED_STATE_INVALID, CKR_SAVED_STATE_INVALID - , pkcs11_return_name_160, &pkcs11_return_names_170 }; + { CKR_SAVED_STATE_INVALID, CKR_SAVED_STATE_INVALID + , pkcs11_return_name_160, &pkcs11_return_names_170 }; static enum_names pkcs11_return_names_150 = - { CKR_BUFFER_TOO_SMALL, CKR_BUFFER_TOO_SMALL - , pkcs11_return_name_150, &pkcs11_return_names_160 }; + { CKR_BUFFER_TOO_SMALL, CKR_BUFFER_TOO_SMALL + , pkcs11_return_name_150, &pkcs11_return_names_160 }; static enum_names pkcs11_return_names_130 = - { CKR_DOMAIN_PARAMS_INVALID, CKR_DOMAIN_PARAMS_INVALID - , pkcs11_return_name_130, &pkcs11_return_names_150 }; + { CKR_DOMAIN_PARAMS_INVALID, CKR_DOMAIN_PARAMS_INVALID + , pkcs11_return_name_130, &pkcs11_return_names_150 }; static enum_names pkcs11_return_names_120 = - { CKR_RANDOM_SEED_NOT_SUPPORTED, CKR_RANDOM_NO_RNG - , pkcs11_return_name_120, &pkcs11_return_names_130 }; + { CKR_RANDOM_SEED_NOT_SUPPORTED, CKR_RANDOM_NO_RNG + , pkcs11_return_name_120, &pkcs11_return_names_130 }; static enum_names pkcs11_return_names_110 = - { CKR_WRAPPED_KEY_INVALID, CKR_WRAPPING_KEY_TYPE_INCONSISTENT - , pkcs11_return_name_110, &pkcs11_return_names_120 }; + { CKR_WRAPPED_KEY_INVALID, CKR_WRAPPING_KEY_TYPE_INCONSISTENT + , pkcs11_return_name_110, &pkcs11_return_names_120 }; static enum_names pkcs11_return_names_100 = - { CKR_USER_ALREADY_LOGGED_IN, CKR_USER_TOO_MANY_TYPES - , pkcs11_return_name_100, &pkcs11_return_names_110 }; + { CKR_USER_ALREADY_LOGGED_IN, CKR_USER_TOO_MANY_TYPES + , pkcs11_return_name_100, &pkcs11_return_names_110 }; static enum_names pkcs11_return_names_F0 = - { CKR_UNWRAPPING_KEY_HANDLE_INVALID, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT - , pkcs11_return_name_F0, &pkcs11_return_names_100 }; + { CKR_UNWRAPPING_KEY_HANDLE_INVALID, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT + , pkcs11_return_name_F0, &pkcs11_return_names_100 }; static enum_names pkcs11_return_names_E0 = - { CKR_TOKEN_NOT_PRESENT, CKR_TOKEN_WRITE_PROTECTED - , pkcs11_return_name_E0, &pkcs11_return_names_F0 }; + { CKR_TOKEN_NOT_PRESENT, CKR_TOKEN_WRITE_PROTECTED + , pkcs11_return_name_E0, &pkcs11_return_names_F0 }; static enum_names pkcs11_return_names_D0 = - { CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT - , pkcs11_return_name_D0,&pkcs11_return_names_E0 }; + { CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT + , pkcs11_return_name_D0,&pkcs11_return_names_E0 }; static enum_names pkcs11_return_names_C0 = - { CKR_SIGNATURE_INVALID, CKR_SIGNATURE_LEN_RANGE - , pkcs11_return_name_C0, &pkcs11_return_names_D0 }; + { CKR_SIGNATURE_INVALID, CKR_SIGNATURE_LEN_RANGE + , pkcs11_return_name_C0, &pkcs11_return_names_D0 }; static enum_names pkcs11_return_names_B0 = - { CKR_SESSION_CLOSED, CKR_SESSION_READ_WRITE_SO_EXISTS - , pkcs11_return_name_B0, &pkcs11_return_names_C0 }; + { CKR_SESSION_CLOSED, CKR_SESSION_READ_WRITE_SO_EXISTS + , pkcs11_return_name_B0, &pkcs11_return_names_C0 }; static enum_names pkcs11_return_names_A0 = - { CKR_PIN_INCORRECT, CKR_PIN_LOCKED - , pkcs11_return_name_A0, &pkcs11_return_names_B0 }; + { CKR_PIN_INCORRECT, CKR_PIN_LOCKED + , pkcs11_return_name_A0, &pkcs11_return_names_B0 }; static enum_names pkcs11_return_names_90 = - { CKR_OPERATION_ACTIVE, CKR_OPERATION_NOT_INITIALIZED - , pkcs11_return_name_90, &pkcs11_return_names_A0 }; + { CKR_OPERATION_ACTIVE, CKR_OPERATION_NOT_INITIALIZED + , pkcs11_return_name_90, &pkcs11_return_names_A0 }; static enum_names pkcs11_return_names_80 = - { CKR_OBJECT_HANDLE_INVALID, CKR_OBJECT_HANDLE_INVALID - , pkcs11_return_name_80, &pkcs11_return_names_90 }; + { CKR_OBJECT_HANDLE_INVALID, CKR_OBJECT_HANDLE_INVALID + , pkcs11_return_name_80, &pkcs11_return_names_90 }; static enum_names pkcs11_return_names_70 = - { CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID - , pkcs11_return_name_70, &pkcs11_return_names_80 }; + { CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID + , pkcs11_return_name_70, &pkcs11_return_names_80 }; static enum_names pkcs11_return_names_60 = - { CKR_KEY_HANDLE_INVALID, CKR_KEY_UNEXTRACTABLE - , pkcs11_return_name_60, &pkcs11_return_names_70 }; + { CKR_KEY_HANDLE_INVALID, CKR_KEY_UNEXTRACTABLE + , pkcs11_return_name_60, &pkcs11_return_names_70 }; static enum_names pkcs11_return_names_50 = - { CKR_FUNCTION_CANCELED, CKR_FUNCTION_NOT_SUPPORTED - , pkcs11_return_name_50, &pkcs11_return_names_60 }; + { CKR_FUNCTION_CANCELED, CKR_FUNCTION_NOT_SUPPORTED + , pkcs11_return_name_50, &pkcs11_return_names_60 }; static enum_names pkcs11_return_names_40 = - { CKR_ENCRYPTED_DATA_INVALID, CKR_ENCRYPTED_DATA_LEN_RANGE - , pkcs11_return_name_40, &pkcs11_return_names_50 }; + { CKR_ENCRYPTED_DATA_INVALID, CKR_ENCRYPTED_DATA_LEN_RANGE + , pkcs11_return_name_40, &pkcs11_return_names_50 }; static enum_names pkcs11_return_names_30 = - { CKR_DEVICE_ERROR, CKR_DEVICE_REMOVED - , pkcs11_return_name_30, &pkcs11_return_names_40 }; + { CKR_DEVICE_ERROR, CKR_DEVICE_REMOVED + , pkcs11_return_name_30, &pkcs11_return_names_40 }; static enum_names pkcs11_return_names_20 = - { CKR_DATA_INVALID, CKR_DATA_LEN_RANGE - , pkcs11_return_name_20, &pkcs11_return_names_30 }; + { CKR_DATA_INVALID, CKR_DATA_LEN_RANGE + , pkcs11_return_name_20, &pkcs11_return_names_30 }; static enum_names pkcs11_return_names_10 = - { CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_VALUE_INVALID - , pkcs11_return_name_10, &pkcs11_return_names_20}; + { CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_VALUE_INVALID + , pkcs11_return_name_10, &pkcs11_return_names_20}; static enum_names pkcs11_return_names = - { CKR_OK, CKR_CANT_LOCK - , pkcs11_return_name, &pkcs11_return_names_10}; + { CKR_OK, CKR_CANT_LOCK + , pkcs11_return_name, &pkcs11_return_names_10}; /* * Unload a PKCS#11 module. @@ -390,49 +389,49 @@ static enum_names pkcs11_return_names = static CK_RV scx_unload_pkcs11_module(scx_pkcs11_module_t *mod) { - if (!mod || mod->_magic != SCX_MAGIC) - return CKR_ARGUMENTS_BAD; + if (!mod || mod->_magic != SCX_MAGIC) + return CKR_ARGUMENTS_BAD; - if (dlclose(mod->handle) < 0) - return CKR_FUNCTION_FAILED; + if (dlclose(mod->handle) < 0) + return CKR_FUNCTION_FAILED; - memset(mod, 0, sizeof(*mod)); - pfree(mod); - return CKR_OK; + memset(mod, 0, sizeof(*mod)); + free(mod); + return CKR_OK; } static scx_pkcs11_module_t* scx_load_pkcs11_module(const char *name, CK_FUNCTION_LIST_PTR_PTR funcs) { - CK_RV (*c_get_function_list)(CK_FUNCTION_LIST_PTR_PTR); - scx_pkcs11_module_t *mod; - void *handle; - int rv; + CK_RV (*c_get_function_list)(CK_FUNCTION_LIST_PTR_PTR); + scx_pkcs11_module_t *mod; + void *handle; + int rv; - if (name == NULL || *name == '\0') - return NULL; + if (name == NULL || *name == '\0') + return NULL; - /* Try to load PKCS#11 library module*/ - handle = dlopen(name, RTLD_NOW); - if (handle == NULL) - return NULL; + /* Try to load PKCS#11 library module*/ + handle = dlopen(name, RTLD_NOW); + if (handle == NULL) + return NULL; - mod = alloc_thing(scx_pkcs11_module_t, "scx_pkcs11_module"); - mod->_magic = SCX_MAGIC; - mod->handle = handle; + mod = malloc_thing(scx_pkcs11_module_t); + mod->_magic = SCX_MAGIC; + mod->handle = handle; /* Get the list of function pointers */ - c_get_function_list = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR)) - dlsym(mod->handle, "C_GetFunctionList"); - if (!c_get_function_list) - goto failed; + c_get_function_list = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR)) + dlsym(mod->handle, "C_GetFunctionList"); + if (!c_get_function_list) + goto failed; - rv = c_get_function_list(funcs); - if (rv == CKR_OK) - return mod; + rv = c_get_function_list(funcs); + if (rv == CKR_OK) + return mod; failed: scx_unload_pkcs11_module(mod); - return NULL; + return NULL; } /* @@ -442,78 +441,78 @@ static bool scx_find_cert_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object , smartcard_t *sc, cert_t *cert) { - size_t hex_len, label_len; - u_char *hex_id = NULL; - chunk_t blob; - x509cert_t *x509cert; - - CK_ATTRIBUTE attr[] = { - { CKA_ID, NULL_PTR, 0L }, - { CKA_LABEL, NULL_PTR, 0L }, - { CKA_VALUE, NULL_PTR, 0L } - }; - - /* initialize the return argument */ - *cert = empty_cert; - - /* get the length of the attributes first */ - CK_RV rv = pkcs11_functions->C_GetAttributeValue(session, object, attr, 3); - if (rv != CKR_OK) - { - plog("couldn't read the attribute sizes: %s" - , enum_show(&pkcs11_return_names, rv)); - return FALSE; - } - - pfreeany(sc->label); - - hex_id = alloc_bytes(attr[0].ulValueLen, "hex id"); - hex_len = attr[0].ulValueLen; - sc->label = alloc_bytes(attr[1].ulValueLen + 1, "sc label"); - label_len = attr[1].ulValueLen; - blob.ptr = alloc_bytes(attr[2].ulValueLen, "x509cert blob"); - blob.len = attr[2].ulValueLen; - - attr[0].pValue = hex_id; - attr[1].pValue = sc->label; - attr[2].pValue = blob.ptr; - - /* now get the attributes */ - rv = pkcs11_functions->C_GetAttributeValue(session, object, attr, 3); - if (rv != CKR_OK) - { - plog("couldn't read the attributes: %s" - , enum_show(&pkcs11_return_names, rv)); - pfree(hex_id); - pfreeany(sc->label); - pfree(blob.ptr); - return FALSE; - } + size_t hex_len, label_len; + u_char *hex_id = NULL; + chunk_t blob; + x509cert_t *x509cert; + + CK_ATTRIBUTE attr[] = { + { CKA_ID, NULL_PTR, 0L }, + { CKA_LABEL, NULL_PTR, 0L }, + { CKA_VALUE, NULL_PTR, 0L } + }; + + /* initialize the return argument */ + *cert = cert_empty; + + /* get the length of the attributes first */ + CK_RV rv = pkcs11_functions->C_GetAttributeValue(session, object, attr, 3); + if (rv != CKR_OK) + { + plog("couldn't read the attribute sizes: %s" + , enum_show(&pkcs11_return_names, rv)); + return FALSE; + } + + free(sc->label); + + hex_id = malloc(attr[0].ulValueLen); + hex_len = attr[0].ulValueLen; + sc->label = malloc(attr[1].ulValueLen + 1); + label_len = attr[1].ulValueLen; + blob.ptr = malloc(attr[2].ulValueLen); + blob.len = attr[2].ulValueLen; + + attr[0].pValue = hex_id; + attr[1].pValue = sc->label; + attr[2].pValue = blob.ptr; + + /* now get the attributes */ + rv = pkcs11_functions->C_GetAttributeValue(session, object, attr, 3); + if (rv != CKR_OK) + { + plog("couldn't read the attributes: %s" + , enum_show(&pkcs11_return_names, rv)); + free(hex_id); + free(sc->label); + free(blob.ptr); + return FALSE; + } - pfreeany(sc->id); + free(sc->id); - /* convert id from hex to ASCII */ - sc->id = alloc_bytes(2*hex_len + 1, " sc id"); - datatot(hex_id, hex_len, 16, sc->id, 2*hex_len + 1); - pfree(hex_id); + /* convert id from hex to ASCII */ + sc->id = malloc(2*hex_len + 1); + datatot(hex_id, hex_len, 16, sc->id, 2*hex_len + 1); + free(hex_id); - /* safeguard in case the label is not null terminated */ - sc->label[label_len] = '\0'; + /* safeguard in case the label is not null terminated */ + sc->label[label_len] = '\0'; - /* parse the retrieved cert */ - x509cert = alloc_thing(x509cert_t, "x509cert"); - *x509cert = empty_x509cert; - x509cert->smartcard = TRUE; + /* parse the retrieved cert */ + x509cert = malloc_thing(x509cert_t); + *x509cert = empty_x509cert; + x509cert->smartcard = TRUE; - if (!parse_x509cert(blob, 0, x509cert)) - { - plog("failed to load cert from smartcard, error in X.509 certificate"); - free_x509cert(x509cert); - return FALSE; - } - cert->type = CERT_X509_SIGNATURE; - cert->u.x509 = x509cert; - return TRUE; + if (!parse_x509cert(blob, 0, x509cert)) + { + plog("failed to load cert from smartcard, error in X.509 certificate"); + free_x509cert(x509cert); + return FALSE; + } + cert->type = CERT_X509_SIGNATURE; + cert->u.x509 = x509cert; + return TRUE; } /* @@ -522,96 +521,96 @@ scx_find_cert_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object static void scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session) { - CK_RV rv; - CK_OBJECT_CLASS class = CKO_CERTIFICATE; - CK_ATTRIBUTE attr[] = {{ CKA_CLASS, &class, sizeof(class) }}; - - rv = pkcs11_functions->C_FindObjectsInit(session, attr, 1); - if (rv != CKR_OK) - { - plog("error in C_FindObjectsInit: %s" - , enum_show(&pkcs11_return_names, rv)); - return; - } - - for (;;) - { - CK_OBJECT_HANDLE object; - CK_ULONG obj_count = 0; - err_t ugh; - time_t valid_until; - smartcard_t *sc; - x509cert_t *cert; + CK_RV rv; + CK_OBJECT_CLASS class = CKO_CERTIFICATE; + CK_ATTRIBUTE attr[] = {{ CKA_CLASS, &class, sizeof(class) }}; - rv = pkcs11_functions->C_FindObjects(session, &object, 1, &obj_count); + rv = pkcs11_functions->C_FindObjectsInit(session, attr, 1); if (rv != CKR_OK) { - plog("error in C_FindObjects: %s" - , enum_show(&pkcs11_return_names, rv)); - break; - } - - /* no objects left */ - if (obj_count == 0) - break; - - /* create and initialize a new smartcard object */ - sc = alloc_thing(smartcard_t, "smartcard"); - *sc = empty_sc; - sc->any_slot = FALSE; - sc->slot = slot; - - if (!scx_find_cert_object(session, object, sc, &sc->last_cert)) - { - scx_free(sc); - continue; + plog("error in C_FindObjectsInit: %s" + , enum_show(&pkcs11_return_names, rv)); + return; } - DBG(DBG_CONTROL, - DBG_log("found cert in %s with id: %s, label: '%s'" - , scx_print_slot(sc, ""), sc->id, sc->label) - ) - /* check validity of certificate */ - cert = sc->last_cert.u.x509; - valid_until = cert->notAfter; - ugh = check_validity(cert, &valid_until); - if (ugh != NULL) - { - plog(" %s", ugh); - free_x509cert(cert); - scx_free(sc); - continue; - } - else + for (;;) { - DBG(DBG_CONTROL, - DBG_log(" certificate is valid") - ) + CK_OBJECT_HANDLE object; + CK_ULONG obj_count = 0; + err_t ugh; + time_t valid_until; + smartcard_t *sc; + x509cert_t *cert; + + rv = pkcs11_functions->C_FindObjects(session, &object, 1, &obj_count); + if (rv != CKR_OK) + { + plog("error in C_FindObjects: %s" + , enum_show(&pkcs11_return_names, rv)); + break; + } + + /* no objects left */ + if (obj_count == 0) + break; + + /* create and initialize a new smartcard object */ + sc = malloc_thing(smartcard_t); + *sc = empty_sc; + sc->any_slot = FALSE; + sc->slot = slot; + + if (!scx_find_cert_object(session, object, sc, &sc->last_cert)) + { + scx_free(sc); + continue; + } + DBG(DBG_CONTROL, + DBG_log("found cert in %s with id: %s, label: '%s'" + , scx_print_slot(sc, ""), sc->id, sc->label) + ) + + /* check validity of certificate */ + cert = sc->last_cert.u.x509; + valid_until = cert->notAfter; + ugh = check_validity(cert, &valid_until); + if (ugh != NULL) + { + plog(" %s", ugh); + free_x509cert(cert); + scx_free(sc); + continue; + } + else + { + DBG(DBG_CONTROL, + DBG_log(" certificate is valid") + ) + } + + sc = scx_add(sc); + + /* put end entity and ca certificates into different chains */ + if (cert->isCA) + { + sc->last_cert.u.x509 = add_authcert(cert, AUTH_CA); + } + else + { + add_x509_public_key(cert, valid_until, DAL_LOCAL); + sc->last_cert.u.x509 = add_x509cert(cert); + } + + share_cert(sc->last_cert); + time(&sc->last_load); } - sc = scx_add(sc); - - /* put end entity and ca certificates into different chains */ - if (cert->isCA) - { - sc->last_cert.u.x509 = add_authcert(cert, AUTH_CA); - } - else + rv = pkcs11_functions->C_FindObjectsFinal(session); + if (rv != CKR_OK) { - add_x509_public_key(cert, valid_until, DAL_LOCAL); - sc->last_cert.u.x509 = add_x509cert(cert); + plog("error in C_FindObjectsFinal: %s" + , enum_show(&pkcs11_return_names, rv)); } - - share_cert(sc->last_cert); - time(&sc->last_load); - } - - rv = pkcs11_functions->C_FindObjectsFinal(session); - if (rv != CKR_OK) - { - plog("error in C_FindObjectsFinal: %s" - , enum_show(&pkcs11_return_names, rv)); - } } /* @@ -620,74 +619,74 @@ scx_find_cert_objects(CK_SLOT_ID slot, CK_SESSION_HANDLE session) static void scx_find_all_cert_objects(void) { - CK_RV rv; - CK_SLOT_ID_PTR slots = NULL_PTR; - CK_ULONG slot_count = 0; - CK_ULONG i; - - if (!scx_initialized) - { - plog("pkcs11 module not initialized"); - return; - } - - /* read size, always returns CKR_OK ! */ - rv = pkcs11_functions->C_GetSlotList(FALSE, NULL_PTR, &slot_count); - - /* allocate memory for the slots */ - slots = (CK_SLOT_ID *)alloc_bytes(slot_count * sizeof(CK_SLOT_ID), "slots"); - - rv = pkcs11_functions->C_GetSlotList(FALSE, slots, &slot_count); - if (rv != CKR_OK) - { - plog("error in C_GetSlotList: %s", enum_show(&pkcs11_return_names, rv)); - pfreeany(slots); - return; - } - - /* look in every slot for certificate objects */ - for (i = 0; i < slot_count; i++) - { - CK_SLOT_ID slot = slots[i]; - CK_SLOT_INFO info; - CK_SESSION_HANDLE session; - - rv = pkcs11_functions->C_GetSlotInfo(slot, &info); + CK_RV rv; + CK_SLOT_ID_PTR slots = NULL_PTR; + CK_ULONG slot_count = 0; + CK_ULONG i; - if (rv != CKR_OK) + if (!scx_initialized) { - plog("error in C_GetSlotInfo: %s" - , enum_show(&pkcs11_return_names, rv)); - continue; - } - - if (!(info.flags & CKF_TOKEN_PRESENT)) - { - plog("no token present in slot %lu", slot); - continue; + plog("pkcs11 module not initialized"); + return; } - rv = pkcs11_functions->C_OpenSession(slot - , CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session); + /* read size, always returns CKR_OK ! */ + rv = pkcs11_functions->C_GetSlotList(FALSE, NULL_PTR, &slot_count); + + /* allocate memory for the slots */ + slots = (CK_SLOT_ID *)malloc(slot_count * sizeof(CK_SLOT_ID)); + + rv = pkcs11_functions->C_GetSlotList(FALSE, slots, &slot_count); if (rv != CKR_OK) { - plog("failed to open a session on slot %lu: %s" - , slot, enum_show(&pkcs11_return_names, rv)); - continue; + plog("error in C_GetSlotList: %s", enum_show(&pkcs11_return_names, rv)); + free(slots); + return; } - DBG(DBG_CONTROLMORE, - DBG_log("pkcs11 session #%ld for searching slot %lu", session, slot) - ) - scx_find_cert_objects(slot, session); - rv = pkcs11_functions->C_CloseSession(session); - if (rv != CKR_OK) + /* look in every slot for certificate objects */ + for (i = 0; i < slot_count; i++) { - plog("error in C_CloseSession: %s" - , enum_show(&pkcs11_return_names, rv)); + CK_SLOT_ID slot = slots[i]; + CK_SLOT_INFO info; + CK_SESSION_HANDLE session; + + rv = pkcs11_functions->C_GetSlotInfo(slot, &info); + + if (rv != CKR_OK) + { + plog("error in C_GetSlotInfo: %s" + , enum_show(&pkcs11_return_names, rv)); + continue; + } + + if (!(info.flags & CKF_TOKEN_PRESENT)) + { + plog("no token present in slot %lu", slot); + continue; + } + + rv = pkcs11_functions->C_OpenSession(slot + , CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session); + if (rv != CKR_OK) + { + plog("failed to open a session on slot %lu: %s" + , slot, enum_show(&pkcs11_return_names, rv)); + continue; + } + DBG(DBG_CONTROLMORE, + DBG_log("pkcs11 session #%ld for searching slot %lu", session, slot) + ) + scx_find_cert_objects(slot, session); + + rv = pkcs11_functions->C_CloseSession(session); + if (rv != CKR_OK) + { + plog("error in C_CloseSession: %s" + , enum_show(&pkcs11_return_names, rv)); + } } - } - pfreeany(slots); + free(slots); } #endif @@ -701,52 +700,52 @@ void scx_init(const char* module, const char *init_args) { #ifdef SMARTCARD - CK_C_INITIALIZE_ARGS args = { .pReserved = (char *)init_args, }; - CK_RV rv; + CK_C_INITIALIZE_ARGS args = { .pReserved = (char *)init_args, }; + CK_RV rv; - if (scx_initialized) - { - plog("weird - pkcs11 module seems already to be initialized"); - return; - } + if (scx_initialized) + { + plog("weird - pkcs11 module seems already to be initialized"); + return; + } - if (module == NULL) + if (module == NULL) #ifdef PKCS11_DEFAULT_LIB - module = PKCS11_DEFAULT_LIB; + module = PKCS11_DEFAULT_LIB; #else - { - plog("no pkcs11 module defined"); - return; - } + { + plog("no pkcs11 module defined"); + return; + } #endif - DBG(DBG_CONTROL | DBG_CRYPT, - DBG_log("pkcs11 module '%s' loading...", module) - ) - pkcs11_module = scx_load_pkcs11_module(module, &pkcs11_functions); - if (pkcs11_module == NULL) - { - plog("failed to load pkcs11 module '%s'", module); - return; - } - - DBG(DBG_CONTROL | DBG_CRYPT, - DBG_log("pkcs11 module initializing...") - ) - rv = pkcs11_functions->C_Initialize(init_args ? &args : NULL); - if (rv != CKR_OK) - { - plog("failed to initialize pkcs11 module: %s" - , enum_show(&pkcs11_return_names, rv)); - return; - } - - scx_initialized = TRUE; - DBG(DBG_CONTROL | DBG_CRYPT, - DBG_log("pkcs11 module loaded and initialized") - ) - - scx_find_all_cert_objects(); + DBG(DBG_CONTROL | DBG_CRYPT, + DBG_log("pkcs11 module '%s' loading...", module) + ) + pkcs11_module = scx_load_pkcs11_module(module, &pkcs11_functions); + if (pkcs11_module == NULL) + { + plog("failed to load pkcs11 module '%s'", module); + return; + } + + DBG(DBG_CONTROL | DBG_CRYPT, + DBG_log("pkcs11 module initializing...") + ) + rv = pkcs11_functions->C_Initialize(init_args ? &args : NULL); + if (rv != CKR_OK) + { + plog("failed to initialize pkcs11 module: %s" + , enum_show(&pkcs11_return_names, rv)); + return; + } + + scx_initialized = TRUE; + DBG(DBG_CONTROL | DBG_CRYPT, + DBG_log("pkcs11 module loaded and initialized") + ) + + scx_find_all_cert_objects(); #endif } @@ -757,27 +756,27 @@ void scx_finalize(void) { #ifdef SMARTCARD - while (smartcards != NULL) - { - scx_release(smartcards); - } - - if (pkcs11_functions != NULL_PTR) - { - pkcs11_functions->C_Finalize(NULL_PTR); - pkcs11_functions = NULL_PTR; - } - - if (pkcs11_module != NULL) - { - scx_unload_pkcs11_module(pkcs11_module); - pkcs11_module = NULL; - } - - scx_initialized = FALSE; - DBG(DBG_CONTROL | DBG_CRYPT, - DBG_log("pkcs11 module finalized and unloaded") - ) + while (smartcards != NULL) + { + scx_release(smartcards); + } + + if (pkcs11_functions != NULL_PTR) + { + pkcs11_functions->C_Finalize(NULL_PTR); + pkcs11_functions = NULL_PTR; + } + + if (pkcs11_module != NULL) + { + scx_unload_pkcs11_module(pkcs11_module); + pkcs11_module = NULL; + } + + scx_initialized = FALSE; + DBG(DBG_CONTROL | DBG_CRYPT, + DBG_log("pkcs11 module finalized and unloaded") + ) #endif } @@ -787,7 +786,7 @@ scx_finalize(void) bool scx_on_smartcard(const char *filename) { - return strncmp(filename, SCX_TOKEN, strlen(SCX_TOKEN)) == 0; + return strneq(filename, SCX_TOKEN, strlen(SCX_TOKEN)); } #ifdef SMARTCARD @@ -795,55 +794,55 @@ scx_on_smartcard(const char *filename) * find a specific object on the smartcard */ static bool -scx_pkcs11_find_object( CK_SESSION_HANDLE session, - CK_OBJECT_HANDLE_PTR object, - CK_OBJECT_CLASS class, - const char* id) +scx_pkcs11_find_object( CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE_PTR object, + CK_OBJECT_CLASS class, + const char* id) { - size_t len; - char buf[BUF_LEN]; - CK_RV rv; - CK_ULONG obj_count = 0; - CK_ULONG attr_count = 1; - - CK_ATTRIBUTE attr[] = { - { CKA_CLASS, &class, sizeof(class) }, - { CKA_ID, &buf, 0L } - }; - - if (id != NULL) - { - ttodata(id, strlen(id), 16, buf, BUF_LEN, &len); - attr[1].ulValueLen = len; - attr_count = 2; - } - - /* get info for certificate with id */ - rv = pkcs11_functions->C_FindObjectsInit(session, attr, attr_count); - if (rv != CKR_OK) - { - plog("error in C_FindObjectsInit: %s" - , enum_show(&pkcs11_return_names, rv)); - return FALSE; - } + size_t len; + char buf[BUF_LEN]; + CK_RV rv; + CK_ULONG obj_count = 0; + CK_ULONG attr_count = 1; - rv = pkcs11_functions->C_FindObjects(session, object, 1, &obj_count); - if (rv != CKR_OK) - { - plog("error in C_FindObjects: %s" - , enum_show(&pkcs11_return_names, rv)); - return FALSE; - } + CK_ATTRIBUTE attr[] = { + { CKA_CLASS, &class, sizeof(class) }, + { CKA_ID, &buf, 0L } + }; - rv = pkcs11_functions->C_FindObjectsFinal(session); - if (rv != CKR_OK) - { - plog("error in C_FindObjectsFinal: %s" - , enum_show(&pkcs11_return_names, rv)); - return FALSE; - } + if (id != NULL) + { + ttodata(id, strlen(id), 16, buf, BUF_LEN, &len); + attr[1].ulValueLen = len; + attr_count = 2; + } + + /* get info for certificate with id */ + rv = pkcs11_functions->C_FindObjectsInit(session, attr, attr_count); + if (rv != CKR_OK) + { + plog("error in C_FindObjectsInit: %s" + , enum_show(&pkcs11_return_names, rv)); + return FALSE; + } + + rv = pkcs11_functions->C_FindObjects(session, object, 1, &obj_count); + if (rv != CKR_OK) + { + plog("error in C_FindObjects: %s" + , enum_show(&pkcs11_return_names, rv)); + return FALSE; + } - return (obj_count != 0); + rv = pkcs11_functions->C_FindObjectsFinal(session); + if (rv != CKR_OK) + { + plog("error in C_FindObjectsFinal: %s" + , enum_show(&pkcs11_return_names, rv)); + return FALSE; + } + + return (obj_count != 0); } /* @@ -852,54 +851,54 @@ scx_pkcs11_find_object( CK_SESSION_HANDLE session, static bool scx_find_cert_id_in_slot(smartcard_t *sc, CK_SLOT_ID slot) { - CK_SESSION_HANDLE session; - CK_OBJECT_HANDLE object; - CK_SLOT_INFO info; - - CK_RV rv = pkcs11_functions->C_GetSlotInfo(slot, &info); - - if (rv != CKR_OK) - { - plog("error in C_GetSlotInfo: %s" - , enum_show(&pkcs11_return_names, rv)); - return FALSE; - } - - if (!(info.flags & CKF_TOKEN_PRESENT)) - { - plog("no token present in slot %lu", slot); - return FALSE; - } - - rv = pkcs11_functions->C_OpenSession(slot - , CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session); - if (rv != CKR_OK) - { - plog("failed to open a session on slot %lu: %s" - , slot, enum_show(&pkcs11_return_names, rv)); + CK_SESSION_HANDLE session; + CK_OBJECT_HANDLE object; + CK_SLOT_INFO info; + + CK_RV rv = pkcs11_functions->C_GetSlotInfo(slot, &info); + + if (rv != CKR_OK) + { + plog("error in C_GetSlotInfo: %s" + , enum_show(&pkcs11_return_names, rv)); + return FALSE; + } + + if (!(info.flags & CKF_TOKEN_PRESENT)) + { + plog("no token present in slot %lu", slot); + return FALSE; + } + + rv = pkcs11_functions->C_OpenSession(slot + , CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session); + if (rv != CKR_OK) + { + plog("failed to open a session on slot %lu: %s" + , slot, enum_show(&pkcs11_return_names, rv)); + return FALSE; + } + DBG(DBG_CONTROLMORE, + DBG_log("pkcs11 session #%ld for searching slot %lu", session, slot) + ) + + /* check if there is a certificate on the card in the specified slot */ + if (scx_pkcs11_find_object(session, &object, CKO_CERTIFICATE, sc->id)) + { + sc->slot = slot; + sc->any_slot = FALSE; + sc->session = session; + sc->session_opened = TRUE; + return TRUE; + } + + rv = pkcs11_functions->C_CloseSession(session); + if (rv != CKR_OK) + { + plog("error in C_CloseSession: %s" + , enum_show(&pkcs11_return_names, rv)); + } return FALSE; - } - DBG(DBG_CONTROLMORE, - DBG_log("pkcs11 session #%ld for searching slot %lu", session, slot) - ) - - /* check if there is a certificate on the card in the specified slot */ - if (scx_pkcs11_find_object(session, &object, CKO_CERTIFICATE, sc->id)) - { - sc->slot = slot; - sc->any_slot = FALSE; - sc->session = session; - sc->session_opened = TRUE; - return TRUE; - } - - rv = pkcs11_functions->C_CloseSession(session); - if (rv != CKR_OK) - { - plog("error in C_CloseSession: %s" - , enum_show(&pkcs11_return_names, rv)); - } - return FALSE; } #endif @@ -910,74 +909,74 @@ bool scx_establish_context(smartcard_t *sc) { #ifdef SMARTCARD - bool id_found = FALSE; - - if (!scx_initialized) - { - plog("pkcs11 module not initialized"); - return FALSE; - } + bool id_found = FALSE; - if (sc->session_opened) - { - DBG(DBG_CONTROL | DBG_CRYPT, - DBG_log("pkcs11 session #%ld already open", sc->session) - ) - return TRUE; - } - - if (!sc->any_slot) - id_found = scx_find_cert_id_in_slot(sc, sc->slot); - - if (!id_found) - { - CK_RV rv; - CK_SLOT_ID slot; - CK_SLOT_ID_PTR slots = NULL_PTR; - CK_ULONG slot_count = 0; - CK_ULONG i; + if (!scx_initialized) + { + plog("pkcs11 module not initialized"); + return FALSE; + } - /* read size, always returns CKR_OK ! */ - rv = pkcs11_functions->C_GetSlotList(FALSE, NULL_PTR, &slot_count); + if (sc->session_opened) + { + DBG(DBG_CONTROL | DBG_CRYPT, + DBG_log("pkcs11 session #%ld already open", sc->session) + ) + return TRUE; + } - /* allocate memory for the slots */ - slots = (CK_SLOT_ID *)alloc_bytes(slot_count * sizeof(CK_SLOT_ID), "slots"); + if (!sc->any_slot) + id_found = scx_find_cert_id_in_slot(sc, sc->slot); - rv = pkcs11_functions->C_GetSlotList(FALSE, slots, &slot_count); - if (rv != CKR_OK) + if (!id_found) { - plog("error in C_GetSlotList: %s" - , enum_show(&pkcs11_return_names, rv)); - pfreeany(slots); - return FALSE; - } + CK_RV rv; + CK_SLOT_ID slot; + CK_SLOT_ID_PTR slots = NULL_PTR; + CK_ULONG slot_count = 0; + CK_ULONG i; + + /* read size, always returns CKR_OK ! */ + rv = pkcs11_functions->C_GetSlotList(FALSE, NULL_PTR, &slot_count); + + /* allocate memory for the slots */ + slots = (CK_SLOT_ID *)malloc(slot_count * sizeof(CK_SLOT_ID)); + + rv = pkcs11_functions->C_GetSlotList(FALSE, slots, &slot_count); + if (rv != CKR_OK) + { + plog("error in C_GetSlotList: %s" + , enum_show(&pkcs11_return_names, rv)); + free(slots); + return FALSE; + } + + /* look in every slot for a certificate with a given object ID */ + for (i = 0; i < slot_count; i++) + { + slot = slots[i]; + id_found = scx_find_cert_id_in_slot(sc, slot); + if (id_found) + break; + } + free(slots); + } - /* look in every slot for a certificate with a given object ID */ - for (i = 0; i < slot_count; i++) + if (id_found) { - slot = slots[i]; - id_found = scx_find_cert_id_in_slot(sc, slot); - if (id_found) - break; - } - pfreeany(slots) - } - - if (id_found) - { - DBG(DBG_CONTROL | DBG_CRYPT, - DBG_log("found token with id %s in slot %lu", sc->id, sc->slot); - DBG_log("pkcs11 session #%ld opened", sc->session) - ) - } - else - { - plog(" no certificate with id %s found on smartcard", sc->id); - } - return id_found; + DBG(DBG_CONTROL | DBG_CRYPT, + DBG_log("found token with id %s in slot %lu", sc->id, sc->slot); + DBG_log("pkcs11 session #%ld opened", sc->session) + ) + } + else + { + plog(" no certificate with id %s found on smartcard", sc->id); + } + return id_found; #else - plog("warning: SMARTCARD support is deactivated in pluto/Makefile!"); - return FALSE; + plog("warning: SMARTCARD support is deactivated in pluto/Makefile!"); + return FALSE; #endif } @@ -988,41 +987,41 @@ bool scx_login(smartcard_t *sc) { #ifdef SMARTCARD - CK_RV rv; + CK_RV rv; + + if (sc->logged_in) + { + DBG(DBG_CONTROL | DBG_CRYPT, + DBG_log("pkcs11 session #%ld login already done", sc->session) + ) + return TRUE; + } + + if (sc->pin.ptr == NULL) + { + plog("unable to log in without PIN!"); + return FALSE; + } + + if (!sc->session_opened) + { + plog("session not opened"); + return FALSE; + } - if (sc->logged_in) - { + rv = pkcs11_functions->C_Login(sc->session, CKU_USER + , (CK_UTF8CHAR *) sc->pin.ptr, sc->pin.len); + if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) + { + plog("unable to login: %s" + , enum_show(&pkcs11_return_names, rv)); + return FALSE; + } DBG(DBG_CONTROL | DBG_CRYPT, - DBG_log("pkcs11 session #%ld login already done", sc->session) + DBG_log("pkcs11 session #%ld login successful", sc->session) ) + sc->logged_in = TRUE; return TRUE; - } - - if (sc->pin.ptr == NULL) - { - plog("unable to log in without PIN!"); - return FALSE; - } - - if (!sc->session_opened) - { - plog("session not opened"); - return FALSE; - } - - rv = pkcs11_functions->C_Login(sc->session, CKU_USER - , (CK_UTF8CHAR *) sc->pin.ptr, sc->pin.len); - if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) - { - plog("unable to login: %s" - , enum_show(&pkcs11_return_names, rv)); - return FALSE; - } - DBG(DBG_CONTROL | DBG_CRYPT, - DBG_log("pkcs11 session #%ld login successful", sc->session) - ) - sc->logged_in = TRUE; - return TRUE; #else return FALSE; #endif @@ -1035,17 +1034,17 @@ scx_login(smartcard_t *sc) static void scx_logout(smartcard_t *sc) { - CK_RV rv; - - rv = pkcs11_functions->C_Logout(sc->session); - if (rv != CKR_OK) - plog("error in C_Logout: %s" - , enum_show(&pkcs11_return_names, rv)); - else - DBG(DBG_CONTROL | DBG_CRYPT, - DBG_log("pkcs11 session #%ld logout", sc->session) - ) - sc->logged_in = FALSE; + CK_RV rv; + + rv = pkcs11_functions->C_Logout(sc->session); + if (rv != CKR_OK) + plog("error in C_Logout: %s" + , enum_show(&pkcs11_return_names, rv)); + else + DBG(DBG_CONTROL | DBG_CRYPT, + DBG_log("pkcs11 session #%ld logout", sc->session) + ) + sc->logged_in = FALSE; } #endif @@ -1057,27 +1056,27 @@ void scx_release_context(smartcard_t *sc) { #ifdef SMARTCARD - CK_RV rv; - - if (!scx_initialized) - return; + CK_RV rv; - if (sc->session_opened) - { - if (sc->logged_in) - scx_logout(sc); + if (!scx_initialized) + return; - sc->session_opened = FALSE; - - rv = pkcs11_functions->C_CloseSession(sc->session); - if (rv != CKR_OK) - plog("error in C_CloseSession: %s" - , enum_show(&pkcs11_return_names, rv)); - else - DBG(DBG_CONTROL | DBG_CRYPT, - DBG_log("pkcs11 session #%ld closed", sc->session) - ) - } + if (sc->session_opened) + { + if (sc->logged_in) + scx_logout(sc); + + sc->session_opened = FALSE; + + rv = pkcs11_functions->C_CloseSession(sc->session); + if (rv != CKR_OK) + plog("error in C_CloseSession: %s" + , enum_show(&pkcs11_return_names, rv)); + else + DBG(DBG_CONTROL | DBG_CRYPT, + DBG_log("pkcs11 session #%ld closed", sc->session) + ) + } #endif } @@ -1088,64 +1087,64 @@ bool scx_load_cert(const char *filename, smartcard_t **scp, cert_t *cert , bool *cached) { -#ifdef SMARTCARD /* compile with smartcard support */ - CK_OBJECT_HANDLE object; +#ifdef SMARTCARD /* compile with smartcard support */ + CK_OBJECT_HANDLE object; - const char *number_slot_id = filename + strlen(SCX_TOKEN); + const char *number_slot_id = filename + strlen(SCX_TOKEN); - smartcard_t *sc = scx_add(scx_parse_number_slot_id(number_slot_id)); + smartcard_t *sc = scx_add(scx_parse_number_slot_id(number_slot_id)); - /* return the smartcard object */ - *scp = sc; + /* return the smartcard object */ + *scp = sc; - /* is there a cached smartcard certificate? */ - *cached = sc->last_cert.type != CERT_NONE - && (time(NULL) - sc->last_load) < SCX_CERT_CACHE_INTERVAL; + /* is there a cached smartcard certificate? */ + *cached = sc->last_cert.type != CERT_NONE + && (time(NULL) - sc->last_load) < SCX_CERT_CACHE_INTERVAL; - if (*cached) - { - *cert = sc->last_cert; - plog(" using cached cert from smartcard #%d (%s, id: %s, label: '%s')" - , sc->number - , scx_print_slot(sc, "") - , sc->id - , sc->label); - return TRUE; - } + if (*cached) + { + *cert = sc->last_cert; + plog(" using cached cert from smartcard #%d (%s, id: %s, label: '%s')" + , sc->number + , scx_print_slot(sc, "") + , sc->id + , sc->label); + return TRUE; + } - if (!scx_establish_context(sc)) - { - scx_release_context(sc); - return FALSE; - } + if (!scx_establish_context(sc)) + { + scx_release_context(sc); + return FALSE; + } - /* find the certificate object */ - if (!scx_pkcs11_find_object(sc->session, &object, CKO_CERTIFICATE, sc->id)) - { - scx_release_context(sc); - return FALSE; - } + /* find the certificate object */ + if (!scx_pkcs11_find_object(sc->session, &object, CKO_CERTIFICATE, sc->id)) + { + scx_release_context(sc); + return FALSE; + } - /* retrieve the certificate object */ - if (!scx_find_cert_object(sc->session, object, sc, cert)) - { - scx_release_context(sc); - return FALSE; - } + /* retrieve the certificate object */ + if (!scx_find_cert_object(sc->session, object, sc, cert)) + { + scx_release_context(sc); + return FALSE; + } - if (!pkcs11_keep_state) - scx_release_context(sc); + if (!pkcs11_keep_state) + scx_release_context(sc); - plog(" loaded cert from smartcard #%d (%s, id: %s, label: '%s')" - , sc->number - , scx_print_slot(sc, "") - , sc->id - , sc->label); + plog(" loaded cert from smartcard #%d (%s, id: %s, label: '%s')" + , sc->number + , scx_print_slot(sc, "") + , sc->id + , sc->label); - return TRUE; + return TRUE; #else - plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!"); - return FALSE; + plog(" warning: SMARTCARD support is deactivated in pluto/Makefile!"); + return FALSE; #endif } @@ -1162,58 +1161,58 @@ scx_load_cert(const char *filename, smartcard_t **scp, cert_t *cert smartcard_t* scx_parse_number_slot_id(const char *number_slot_id) { - int len = strlen(number_slot_id); - smartcard_t *sc = alloc_thing(smartcard_t, "smartcard"); - - /* assign default values */ - *sc = empty_sc; - - if (len == 0) /* default: use certificate #1 */ - { - sc->number = 1; - } - else if (*number_slot_id == '#') /* #number scheme */ - { - err_t ugh; - unsigned long ul; - - ugh = atoul(number_slot_id+1, len-1 , 10, &ul); - if (ugh == NULL) - sc->number = (int)ul; - else - plog("error parsing smartcard number: %s", ugh); - } - else /* slot:id scheme */ - { - int slot_len = len; - char *p = strchr(number_slot_id, ':'); - - if (p != NULL) - { - int id_len = len - (p + 1 - number_slot_id); - slot_len -= (1 + id_len); - - if (id_len > 0) /* we have an id */ - sc->id = p + 1; - } - if (slot_len > 0) /* we have a slot */ - { - err_t ugh = NULL; - unsigned long ul; - - ugh = atoul(number_slot_id, slot_len, 10, &ul); - if (ugh == NULL) - { - sc->slot = ul; - sc->any_slot = FALSE; - } - else - plog("error parsing smartcard slot number: %s", ugh); - } - } - /* unshare the id string */ - sc->id = clone_str(sc->id, "key id"); - return sc; + int len = strlen(number_slot_id); + smartcard_t *sc = malloc_thing(smartcard_t); + + /* assign default values */ + *sc = empty_sc; + + if (len == 0) /* default: use certificate #1 */ + { + sc->number = 1; + } + else if (*number_slot_id == '#') /* #number scheme */ + { + err_t ugh; + unsigned long ul; + + ugh = atoul(number_slot_id+1, len-1 , 10, &ul); + if (ugh == NULL) + sc->number = (int)ul; + else + plog("error parsing smartcard number: %s", ugh); + } + else /* slot:id scheme */ + { + int slot_len = len; + char *p = strchr(number_slot_id, ':'); + + if (p != NULL) + { + int id_len = len - (p + 1 - number_slot_id); + slot_len -= (1 + id_len); + + if (id_len > 0) /* we have an id */ + sc->id = p + 1; + } + if (slot_len > 0) /* we have a slot */ + { + err_t ugh = NULL; + unsigned long ul; + + ugh = atoul(number_slot_id, slot_len, 10, &ul); + if (ugh == NULL) + { + sc->slot = ul; + sc->any_slot = FALSE; + } + else + plog("error parsing smartcard slot number: %s", ugh); + } + } + /* unshare the id string */ + sc->id = clone_str(sc->id); + return sc; } /* @@ -1223,49 +1222,49 @@ bool scx_verify_pin(smartcard_t *sc) { #ifdef SMARTCARD - CK_RV rv; - - if (!sc->pinpad) - sc->valid = FALSE; + CK_RV rv; + + if (!sc->pinpad) + sc->valid = FALSE; - if (sc->pin.ptr == NULL) - { - plog("unable to verify without PIN"); - return FALSE; - } + if (sc->pin.ptr == NULL) + { + plog("unable to verify without PIN"); + return FALSE; + } - /* establish context */ - if (!scx_establish_context(sc)) - { - scx_release_context(sc); - return FALSE; - } + /* establish context */ + if (!scx_establish_context(sc)) + { + scx_release_context(sc); + return FALSE; + } - rv = pkcs11_functions->C_Login(sc->session, CKU_USER, - (CK_UTF8CHAR *) sc->pin.ptr, sc->pin.len); - if (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN) - { - sc->valid = TRUE; - sc->logged_in = TRUE; - DBG(DBG_CONTROL | DBG_CRYPT, - DBG_log((rv == CKR_OK) - ? "PIN code correct" - : "already logged in, no PIN entry required"); - DBG_log("pkcs11 session #%ld login successful", sc->session) - ) - } - else - { - DBG(DBG_CONTROL | DBG_CRYPT, - DBG_log("PIN code incorrect") - ) - } - if (!pkcs11_keep_state) - scx_release_context(sc); + rv = pkcs11_functions->C_Login(sc->session, CKU_USER, + (CK_UTF8CHAR *) sc->pin.ptr, sc->pin.len); + if (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN) + { + sc->valid = TRUE; + sc->logged_in = TRUE; + DBG(DBG_CONTROL | DBG_CRYPT, + DBG_log((rv == CKR_OK) + ? "PIN code correct" + : "already logged in, no PIN entry required"); + DBG_log("pkcs11 session #%ld login successful", sc->session) + ) + } + else + { + DBG(DBG_CONTROL | DBG_CRYPT, + DBG_log("PIN code incorrect") + ) + } + if (!pkcs11_keep_state) + scx_release_context(sc); #else - sc->valid = FALSE; + sc->valid = FALSE; #endif - return sc->valid; + return sc->valid; } /* @@ -1276,105 +1275,105 @@ scx_sign_hash(smartcard_t *sc, const u_char *in, size_t inlen , u_char *out, size_t outlen) { #ifdef SMARTCARD - CK_RV rv; - CK_OBJECT_HANDLE object; - CK_ULONG siglen = (CK_ULONG)outlen; - CK_BBOOL sign_flag, decrypt_flag; - CK_ATTRIBUTE attr[] = { - { CKA_SIGN, &sign_flag, sizeof(sign_flag) }, - { CKA_DECRYPT, &decrypt_flag, sizeof(decrypt_flag) } - }; - - if (!sc->logged_in) - return FALSE; - - if (!scx_pkcs11_find_object(sc->session, &object, CKO_PRIVATE_KEY, sc->id)) - { - plog("unable to find private key with id '%s'", sc->id); - return FALSE; - } + CK_RV rv; + CK_OBJECT_HANDLE object; + CK_ULONG siglen = (CK_ULONG)outlen; + CK_BBOOL sign_flag, decrypt_flag; + CK_ATTRIBUTE attr[] = { + { CKA_SIGN, &sign_flag, sizeof(sign_flag) }, + { CKA_DECRYPT, &decrypt_flag, sizeof(decrypt_flag) } + }; + + if (!sc->logged_in) + return FALSE; - rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 2); - if (rv != CKR_OK) - { - plog("couldn't read the private key attributes: %s" - , enum_show(&pkcs11_return_names, rv)); - return FALSE; - } - DBG(DBG_CONTROL, - DBG_log("RSA key flags: sign = %s, decrypt = %s" - , (sign_flag)? "true":"false" - , (decrypt_flag)? "true":"false") - ) - - if (sign_flag) - { - CK_MECHANISM mech = { CKM_RSA_PKCS, NULL_PTR, 0 }; - - rv = pkcs11_functions->C_SignInit(sc->session, &mech, object); - if (rv != CKR_OK) + if (!scx_pkcs11_find_object(sc->session, &object, CKO_PRIVATE_KEY, sc->id)) { - plog("error in C_SignInit: %s" - , enum_show(&pkcs11_return_names, rv)); - return FALSE; + plog("unable to find private key with id '%s'", sc->id); + return FALSE; } - rv = pkcs11_functions->C_Sign(sc->session, (CK_BYTE_PTR)in, inlen - , out, &siglen); + rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 2); if (rv != CKR_OK) { - plog("error in C_Sign: %s" - , enum_show(&pkcs11_return_names, rv)); - return FALSE; - } - } - else if (decrypt_flag) - { - CK_MECHANISM mech = { CKM_RSA_X_509, NULL_PTR, 0 }; - size_t padlen; - u_char *p = out ; - - /* PKCS#1 v1.5 8.1 encryption-block formatting */ - *p++ = 0x00; - *p++ = 0x01; /* BT (block type) 01 */ - padlen = outlen - 3 - inlen; - memset(p, 0xFF, padlen); - p += padlen; - *p++ = 0x00; - memcpy(p, in, inlen); + plog("couldn't read the private key attributes: %s" + , enum_show(&pkcs11_return_names, rv)); + return FALSE; + } + DBG(DBG_CONTROL, + DBG_log("RSA key flags: sign = %s, decrypt = %s" + , (sign_flag)? "true":"false" + , (decrypt_flag)? "true":"false") + ) - rv = pkcs11_functions->C_DecryptInit(sc->session, &mech, object); - if (rv != CKR_OK) + if (sign_flag) { - plog("error in C_DecryptInit: %s" - , enum_show(&pkcs11_return_names, rv)); - return FALSE; - } - - rv = pkcs11_functions->C_Decrypt(sc->session, out, outlen - , out, &siglen); - if (rv != CKR_OK) - { - plog("error in C_Decrypt: %s" - , enum_show(&pkcs11_return_names, rv)); - return FALSE; - } - } - else - { - plog("private key has neither sign nor decrypt flag set"); - return FALSE; - } + CK_MECHANISM mech = { CKM_RSA_PKCS, NULL_PTR, 0 }; + + rv = pkcs11_functions->C_SignInit(sc->session, &mech, object); + if (rv != CKR_OK) + { + plog("error in C_SignInit: %s" + , enum_show(&pkcs11_return_names, rv)); + return FALSE; + } + + rv = pkcs11_functions->C_Sign(sc->session, (CK_BYTE_PTR)in, inlen + , out, &siglen); + if (rv != CKR_OK) + { + plog("error in C_Sign: %s" + , enum_show(&pkcs11_return_names, rv)); + return FALSE; + } + } + else if (decrypt_flag) + { + CK_MECHANISM mech = { CKM_RSA_X_509, NULL_PTR, 0 }; + size_t padlen; + u_char *p = out ; + + /* PKCS#1 v1.5 8.1 encryption-block formatting */ + *p++ = 0x00; + *p++ = 0x01; /* BT (block type) 01 */ + padlen = outlen - 3 - inlen; + memset(p, 0xFF, padlen); + p += padlen; + *p++ = 0x00; + memcpy(p, in, inlen); + + rv = pkcs11_functions->C_DecryptInit(sc->session, &mech, object); + if (rv != CKR_OK) + { + plog("error in C_DecryptInit: %s" + , enum_show(&pkcs11_return_names, rv)); + return FALSE; + } + + rv = pkcs11_functions->C_Decrypt(sc->session, out, outlen + , out, &siglen); + if (rv != CKR_OK) + { + plog("error in C_Decrypt: %s" + , enum_show(&pkcs11_return_names, rv)); + return FALSE; + } + } + else + { + plog("private key has neither sign nor decrypt flag set"); + return FALSE; + } - if (siglen > (CK_ULONG)outlen) - { - plog("signature length (%lu) larger than allocated buffer (%d)" - , siglen, (int)outlen); - return FALSE; - } - return TRUE; + if (siglen > (CK_ULONG)outlen) + { + plog("signature length (%lu) larger than allocated buffer (%d)" + , siglen, (int)outlen); + return FALSE; + } + return TRUE; #else - return FALSE; + return FALSE; #endif } @@ -1386,132 +1385,146 @@ scx_encrypt(smartcard_t *sc, const u_char *in, size_t inlen , u_char *out, size_t *outlen) { #ifdef SMARTCARD - CK_RV rv; - CK_OBJECT_HANDLE object; - CK_ULONG len = (CK_ULONG)(*outlen); - CK_BBOOL encrypt_flag; - CK_ATTRIBUTE attr[] = { - { CKA_MODULUS, NULL_PTR, 0L }, - { CKA_PUBLIC_EXPONENT, NULL_PTR, 0L }, - { CKA_ENCRYPT, &encrypt_flag, sizeof(encrypt_flag) } - }; - CK_MECHANISM mech = { CKM_RSA_PKCS, NULL_PTR, 0 }; - - if (!scx_establish_context(sc)) - { - scx_release_context(sc); - return FALSE; - } - - if (!scx_pkcs11_find_object(sc->session, &object, CKO_PUBLIC_KEY, sc->id)) - { - plog("unable to find public key with id '%s'", sc->id); - return FALSE; - } - - rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 3); - if (rv != CKR_OK) - { - plog("couldn't read the public key attributes: %s" - , enum_show(&pkcs11_return_names, rv)); - scx_release_context(sc); - return FALSE; - } + CK_RV rv; + CK_OBJECT_HANDLE object; + CK_ULONG len = (CK_ULONG)(*outlen); + CK_BBOOL encrypt_flag; + CK_ATTRIBUTE attr[] = { + { CKA_MODULUS, NULL_PTR, 0L }, + { CKA_PUBLIC_EXPONENT, NULL_PTR, 0L }, + { CKA_ENCRYPT, &encrypt_flag, sizeof(encrypt_flag) } + }; + CK_MECHANISM mech = { CKM_RSA_PKCS, NULL_PTR, 0 }; + + if (!scx_establish_context(sc)) + { + scx_release_context(sc); + return FALSE; + } - if (!encrypt_flag) - { - plog("public key cannot be used for encryption"); - scx_release_context(sc); - return FALSE; - } - - /* there must be enough space left for the PKCS#1 v1.5 padding */ - if (inlen > attr[0].ulValueLen - 11) - { - plog("smartcard input data length (%d) exceeds maximum of %lu bytes" - , (int)inlen, attr[0].ulValueLen - 11); - if (!pkcs11_keep_state) - scx_release_context(sc); - return FALSE; - } - - rv = pkcs11_functions->C_EncryptInit(sc->session, &mech, object); - - if (rv != CKR_OK) - { - if (rv == CKR_FUNCTION_NOT_SUPPORTED) - { - RSA_public_key_t rsa; - chunk_t plain_text = {(u_char*)in, inlen}; - chunk_t cipher_text; - - DBG(DBG_CONTROL, - DBG_log("doing RSA encryption in software") - ) - attr[0].pValue = alloc_bytes(attr[0].ulValueLen, "modulus"); - attr[1].pValue = alloc_bytes(attr[1].ulValueLen, "exponent"); - - rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 2); - if (rv != CKR_OK) - { - plog("couldn't read modulus and public exponent: %s" - , enum_show(&pkcs11_return_names, rv)); - pfree(attr[0].pValue); - pfree(attr[1].pValue); + if (!scx_pkcs11_find_object(sc->session, &object, CKO_PUBLIC_KEY, sc->id)) + { + plog("unable to find public key with id '%s'", sc->id); + return FALSE; + } + + rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 3); + if (rv != CKR_OK) + { + plog("couldn't read the public key attributes: %s" + , enum_show(&pkcs11_return_names, rv)); scx_release_context(sc); return FALSE; - } - rsa.k = attr[0].ulValueLen; - n_to_mpz(&rsa.n, attr[0].pValue, attr[0].ulValueLen); - n_to_mpz(&rsa.e, attr[1].pValue, attr[1].ulValueLen); - pfree(attr[0].pValue); - pfree(attr[1].pValue); - - cipher_text = RSA_encrypt(&rsa, plain_text); - free_RSA_public_content(&rsa); - if (cipher_text.ptr == NULL) - { - plog("smartcard input data length is too large"); - if (!pkcs11_keep_state) - scx_release_context(sc); - return FALSE; - } - - memcpy(out, cipher_text.ptr, cipher_text.len); - *outlen = cipher_text.len; - freeanychunk(cipher_text); - if (!pkcs11_keep_state) + } + + if (!encrypt_flag) + { + plog("public key cannot be used for encryption"); scx_release_context(sc); - return TRUE; + return FALSE; } - else + + /* there must be enough space left for the PKCS#1 v1.5 padding */ + if (inlen > attr[0].ulValueLen - 11) { - plog("error in C_EncryptInit: %s" - , enum_show(&pkcs11_return_names, rv)); - scx_release_context(sc); - return FALSE; - } - } - - DBG(DBG_CONTROL, - DBG_log("doing RSA encryption on smartcard") - ) - rv = pkcs11_functions->C_Encrypt(sc->session, (u_char*)in, inlen - , out, &len); - if (rv != CKR_OK) - { - plog("error in C_Encrypt: %s" - , enum_show(&pkcs11_return_names, rv)); - scx_release_context(sc); - return FALSE; - } - if (!pkcs11_keep_state) - scx_release_context(sc); + plog("smartcard input data length (%d) exceeds maximum of %lu bytes" + , (int)inlen, attr[0].ulValueLen - 11); + if (!pkcs11_keep_state) + scx_release_context(sc); + return FALSE; + } + + rv = pkcs11_functions->C_EncryptInit(sc->session, &mech, object); + + if (rv != CKR_OK) + { + if (rv == CKR_FUNCTION_NOT_SUPPORTED) + { + public_key_t *key; + chunk_t rsa_modulus, rsa_exponent, rsa_key, cipher_text; + chunk_t plain_text = {(u_char*)in, inlen}; + + DBG(DBG_CONTROL, + DBG_log("doing RSA encryption in software") + ) + attr[0].pValue = malloc(attr[0].ulValueLen); + attr[1].pValue = malloc(attr[1].ulValueLen); + + rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 2); + if (rv != CKR_OK) + { + plog("couldn't read modulus and public exponent: %s" + , enum_show(&pkcs11_return_names, rv)); + free(attr[0].pValue); + free(attr[1].pValue); + scx_release_context(sc); + return FALSE; + } + rsa_modulus = chunk_create((u_char*) attr[0].pValue, + (size_t) attr[0].ulValueLen); + rsa_exponent = chunk_create((u_char*) attr[1].pValue, + (size_t) attr[1].ulValueLen); + rsa_key = asn1_wrap(ASN1_SEQUENCE, "mm", + asn1_integer("m", rsa_modulus), + asn1_integer("m", rsa_exponent)); + key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, + BUILD_BLOB_ASN1_DER, rsa_key, BUILD_END); + free(rsa_key.ptr); + if (key == NULL) + { + return FALSE; + } + key->encrypt(key, plain_text, &cipher_text); + key->destroy(key); + + if (cipher_text.ptr == NULL) + { + plog("smartcard input data length is too large"); + if (!pkcs11_keep_state) + { + scx_release_context(sc); + } + return FALSE; + } + + memcpy(out, cipher_text.ptr, cipher_text.len); + *outlen = cipher_text.len; + free(cipher_text.ptr); + + if (!pkcs11_keep_state) + { + scx_release_context(sc); + } + return TRUE; + } + else + { + plog("error in C_EncryptInit: %s" + , enum_show(&pkcs11_return_names, rv)); + scx_release_context(sc); + return FALSE; + } + } - *outlen = (size_t)len; - return TRUE; + DBG(DBG_CONTROL, + DBG_log("doing RSA encryption on smartcard") + ) + rv = pkcs11_functions->C_Encrypt(sc->session, (u_char*)in, inlen + , out, &len); + if (rv != CKR_OK) + { + plog("error in C_Encrypt: %s" + , enum_show(&pkcs11_return_names, rv)); + scx_release_context(sc); + return FALSE; + } + if (!pkcs11_keep_state) + scx_release_context(sc); + + *outlen = (size_t)len; + return TRUE; #else - return FALSE; + return FALSE; #endif } /* @@ -1522,70 +1535,70 @@ scx_decrypt(smartcard_t *sc, const u_char *in, size_t inlen , u_char *out, size_t *outlen) { #ifdef SMARTCARD - CK_RV rv; - CK_OBJECT_HANDLE object; - CK_ULONG len = (CK_ULONG)(*outlen); - CK_BBOOL decrypt_flag; - CK_ATTRIBUTE attr[] = { - { CKA_DECRYPT, &decrypt_flag, sizeof(decrypt_flag) } - }; - CK_MECHANISM mech = { CKM_RSA_PKCS, NULL_PTR, 0 }; - - if (!scx_establish_context(sc) || !scx_login(sc)) - { - scx_release_context(sc); - return FALSE; - } - - if (!scx_pkcs11_find_object(sc->session, &object, CKO_PRIVATE_KEY, sc->id)) - { - plog("unable to find private key with id '%s'", sc->id); - return FALSE; - } + CK_RV rv; + CK_OBJECT_HANDLE object; + CK_ULONG len = (CK_ULONG)(*outlen); + CK_BBOOL decrypt_flag; + CK_ATTRIBUTE attr[] = { + { CKA_DECRYPT, &decrypt_flag, sizeof(decrypt_flag) } + }; + CK_MECHANISM mech = { CKM_RSA_PKCS, NULL_PTR, 0 }; + + if (!scx_establish_context(sc) || !scx_login(sc)) + { + scx_release_context(sc); + return FALSE; + } - rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 1); - if (rv != CKR_OK) - { - plog("couldn't read the private key attributes: %s" - , enum_show(&pkcs11_return_names, rv)); - return FALSE; - } + if (!scx_pkcs11_find_object(sc->session, &object, CKO_PRIVATE_KEY, sc->id)) + { + plog("unable to find private key with id '%s'", sc->id); + return FALSE; + } - if (!decrypt_flag) - { - plog("private key cannot be used for decryption"); - scx_release_context(sc); - return FALSE; - } - - DBG(DBG_CONTROL, - DBG_log("doing RSA decryption on smartcard") - ) - rv = pkcs11_functions->C_DecryptInit(sc->session, &mech, object); - if (rv != CKR_OK) - { - plog("error in C_DecryptInit: %s" - , enum_show(&pkcs11_return_names, rv)); - scx_release_context(sc); - return FALSE; - } - - rv = pkcs11_functions->C_Decrypt(sc->session, (u_char*)in, inlen - , out, &len); - if (rv != CKR_OK) - { - plog("error in C_Decrypt: %s" - , enum_show(&pkcs11_return_names, rv)); - scx_release_context(sc); - return FALSE; - } - if (!pkcs11_keep_state) - scx_release_context(sc); + rv = pkcs11_functions->C_GetAttributeValue(sc->session, object, attr, 1); + if (rv != CKR_OK) + { + plog("couldn't read the private key attributes: %s" + , enum_show(&pkcs11_return_names, rv)); + return FALSE; + } - *outlen = (size_t)len; - return TRUE; + if (!decrypt_flag) + { + plog("private key cannot be used for decryption"); + scx_release_context(sc); + return FALSE; + } + + DBG(DBG_CONTROL, + DBG_log("doing RSA decryption on smartcard") + ) + rv = pkcs11_functions->C_DecryptInit(sc->session, &mech, object); + if (rv != CKR_OK) + { + plog("error in C_DecryptInit: %s" + , enum_show(&pkcs11_return_names, rv)); + scx_release_context(sc); + return FALSE; + } + + rv = pkcs11_functions->C_Decrypt(sc->session, (u_char*)in, inlen + , out, &len); + if (rv != CKR_OK) + { + plog("error in C_Decrypt: %s" + , enum_show(&pkcs11_return_names, rv)); + scx_release_context(sc); + return FALSE; + } + if (!pkcs11_keep_state) + scx_release_context(sc); + + *outlen = (size_t)len; + return TRUE; #else - return FALSE; + return FALSE; #endif } @@ -1597,92 +1610,92 @@ bool scx_op_via_whack(const char* msg, int inbase, int outbase, sc_op_t op , const char* keyid, int whackfd) { - char inbuf[RSA_MAX_OCTETS]; - char outbuf[2*RSA_MAX_OCTETS + 1]; - size_t outlen = sizeof(inbuf); - size_t inlen; - smartcard_t *sc,*sc_new; + char inbuf[RSA_MAX_OCTETS]; + char outbuf[2*RSA_MAX_OCTETS + 1]; + size_t outlen = sizeof(inbuf); + size_t inlen; + smartcard_t *sc,*sc_new; - const char *number_slot_id = ""; + const char *number_slot_id = ""; - err_t ugh = ttodata(msg, 0, inbase, inbuf, sizeof(inbuf), &inlen); + err_t ugh = ttodata(msg, 0, inbase, inbuf, sizeof(inbuf), &inlen); - /* no prefix - use default base */ - if (ugh != NULL && inbase == 0) - ugh = ttodata(msg, 0, DEFAULT_BASE, inbuf, sizeof(inbuf), &inlen); + /* no prefix - use default base */ + if (ugh != NULL && inbase == 0) + ugh = ttodata(msg, 0, DEFAULT_BASE, inbuf, sizeof(inbuf), &inlen); - if (ugh != NULL) - { - plog("format error in smartcard input data: %s", ugh); - return FALSE; - } - - if (keyid != NULL) - { - number_slot_id = (strncmp(keyid, SCX_TOKEN, strlen(SCX_TOKEN)) == 0) - ? keyid + strlen(SCX_TOKEN) : keyid; - } - - sc_new = scx_parse_number_slot_id(number_slot_id); - sc = scx_add(sc_new); - if (sc == sc_new) - scx_share(sc); - - DBG((op == SC_OP_ENCRYPT)? DBG_PRIVATE:DBG_RAW, - DBG_dump("smartcard input data:\n", inbuf, inlen) - ) - - if (op == SC_OP_DECRYPT) - { - if (!sc->valid && whackfd != NULL_FD) - scx_get_pin(sc, whackfd); - - if (!sc->valid) - { - loglog(RC_NOVALIDPIN, "cannot decrypt without valid PIN"); - return FALSE; - } - } - - DBG(DBG_CONTROL | DBG_CRYPT, - DBG_log("using RSA key from smartcard (slot: %d, id: %s)" - , (int)sc->slot, sc->id) - ) - - switch (op) - { - case SC_OP_ENCRYPT: - if (!scx_encrypt(sc, inbuf, inlen, inbuf, &outlen)) - return FALSE; - break; - case SC_OP_DECRYPT: - if (!scx_decrypt(sc, inbuf, inlen, inbuf, &outlen)) - return FALSE; - break; - default: - break; - } - - DBG((op == SC_OP_DECRYPT)? DBG_PRIVATE:DBG_RAW, - DBG_dump("smartcard output data:\n", inbuf, outlen) - ) - - if (outbase == 0) /* use default base */ - outbase = DEFAULT_BASE; - - if (outbase == 256) /* ascii plain text */ - whack_log(RC_COMMENT, "%.*s", (int)outlen, inbuf); - else - { - outlen = datatot(inbuf, outlen, outbase, outbuf, sizeof(outbuf)); - if (outlen == 0) - { - plog("error in output format conversion"); - return FALSE; - } - whack_log(RC_COMMENT, "%s", outbuf); - } - return TRUE; + if (ugh != NULL) + { + plog("format error in smartcard input data: %s", ugh); + return FALSE; + } + + if (keyid != NULL) + { + number_slot_id = (strneq(keyid, SCX_TOKEN, strlen(SCX_TOKEN))) + ? keyid + strlen(SCX_TOKEN) : keyid; + } + + sc_new = scx_parse_number_slot_id(number_slot_id); + sc = scx_add(sc_new); + if (sc == sc_new) + scx_share(sc); + + DBG((op == SC_OP_ENCRYPT)? DBG_PRIVATE:DBG_RAW, + DBG_dump("smartcard input data:\n", inbuf, inlen) + ) + + if (op == SC_OP_DECRYPT) + { + if (!sc->valid && whackfd != NULL_FD) + scx_get_pin(sc, whackfd); + + if (!sc->valid) + { + loglog(RC_NOVALIDPIN, "cannot decrypt without valid PIN"); + return FALSE; + } + } + + DBG(DBG_CONTROL | DBG_CRYPT, + DBG_log("using RSA key from smartcard (slot: %d, id: %s)" + , (int)sc->slot, sc->id) + ) + + switch (op) + { + case SC_OP_ENCRYPT: + if (!scx_encrypt(sc, inbuf, inlen, inbuf, &outlen)) + return FALSE; + break; + case SC_OP_DECRYPT: + if (!scx_decrypt(sc, inbuf, inlen, inbuf, &outlen)) + return FALSE; + break; + default: + break; + } + + DBG((op == SC_OP_DECRYPT)? DBG_PRIVATE:DBG_RAW, + DBG_dump("smartcard output data:\n", inbuf, outlen) + ) + + if (outbase == 0) /* use default base */ + outbase = DEFAULT_BASE; + + if (outbase == 256) /* ascii plain text */ + whack_log(RC_COMMENT, "%.*s", (int)outlen, inbuf); + else + { + outlen = datatot(inbuf, outlen, outbase, outbuf, sizeof(outbuf)); + if (outlen == 0) + { + plog("error in output format conversion"); + return FALSE; + } + whack_log(RC_COMMENT, "%s", outbuf); + } + return TRUE; } /* @@ -1692,32 +1705,32 @@ size_t scx_get_keylength(smartcard_t *sc) { #ifdef SMARTCARD - CK_RV rv; - CK_OBJECT_HANDLE object; - CK_ATTRIBUTE attr[] = {{ CKA_MODULUS, NULL_PTR, 0}}; + CK_RV rv; + CK_OBJECT_HANDLE object; + CK_ATTRIBUTE attr[] = {{ CKA_MODULUS, NULL_PTR, 0}}; - if (!sc->logged_in) - return FALSE; + if (!sc->logged_in) + return FALSE; - if (!scx_pkcs11_find_object(sc->session, &object, CKO_PRIVATE_KEY, sc->id)) - { - plog("unable to find private key with id '%s'", sc->id); - return FALSE; - } - - /* get the length of the private key */ - rv = pkcs11_functions->C_GetAttributeValue(sc->session, object - , (CK_ATTRIBUTE_PTR)&attr, 1); - if (rv != CKR_OK) - { - plog("failed to get key length: %s" - , enum_show(&pkcs11_return_names, rv)); - return FALSE; - } + if (!scx_pkcs11_find_object(sc->session, &object, CKO_PRIVATE_KEY, sc->id)) + { + plog("unable to find private key with id '%s'", sc->id); + return FALSE; + } + + /* get the length of the private key */ + rv = pkcs11_functions->C_GetAttributeValue(sc->session, object + , (CK_ATTRIBUTE_PTR)&attr, 1); + if (rv != CKR_OK) + { + plog("failed to get key length: %s" + , enum_show(&pkcs11_return_names, rv)); + return FALSE; + } - return attr[0].ulValueLen; /*Return key length in bytes */ + return attr[0].ulValueLen; /*Return key length in bytes */ #else - return 0; + return 0; #endif } @@ -1728,54 +1741,55 @@ bool scx_get_pin(smartcard_t *sc, int whackfd) { #ifdef SMARTCARD - char pin[BUF_LEN]; - int i, n; + char pin[BUF_LEN]; + int i, n; - whack_log(RC_ENTERSECRET, "need PIN for #%d (%s, id: %s, label: '%s')" - , sc->number, scx_print_slot(sc, ""), sc->id, sc->label); + whack_log(RC_ENTERSECRET, "need PIN for #%d (%s, id: %s, label: '%s')" + , sc->number, scx_print_slot(sc, ""), sc->id, sc->label); - for (i = 0; i < SCX_MAX_PIN_TRIALS; i++) - { - if (i > 0) - whack_log(RC_ENTERSECRET, "invalid PIN, please try again"); - - n = read(whackfd, pin, BUF_LEN); - - if (n == -1) + for (i = 0; i < SCX_MAX_PIN_TRIALS; i++) { - whack_log(RC_LOG_SERIOUS, "read(whackfd) failed"); - return FALSE; + if (i > 0) + whack_log(RC_ENTERSECRET, "invalid PIN, please try again"); + + n = read(whackfd, pin, BUF_LEN); + + if (n == -1) + { + whack_log(RC_LOG_SERIOUS, "read(whackfd) failed"); + return FALSE; + } + + if (strlen(pin) == 0) + { + whack_log(RC_LOG_SERIOUS, "no PIN entered, aborted"); + return FALSE; + } + + sc->pin.ptr = pin; + sc->pin.len = strlen(pin); + + /* verify the pin */ + if (scx_verify_pin(sc)) + { + sc->pin = chunk_create(pin, strlen(pin)); + sc->pin = chunk_clone(sc->pin); + break; + } + + /* wrong pin - we try another round */ + sc->pin = chunk_empty; } - if (strlen(pin) == 0) - { - whack_log(RC_LOG_SERIOUS, "no PIN entered, aborted"); - return FALSE; - } - - sc->pin.ptr = pin; - sc->pin.len = strlen(pin); - - /* verify the pin */ - if (scx_verify_pin(sc)) - { - clonetochunk(sc->pin, pin, strlen(pin), "pin"); - break; - } - - /* wrong pin - we try another round */ - sc->pin = empty_chunk; - } - - if (sc->valid) - whack_log(RC_SUCCESS, "valid PIN"); - else - whack_log(RC_LOG_SERIOUS, "invalid PIN, too many trials"); + if (sc->valid) + whack_log(RC_SUCCESS, "valid PIN"); + else + whack_log(RC_LOG_SERIOUS, "invalid PIN, too many trials"); #else - sc->valid = FALSE; - whack_log(RC_LOG_SERIOUS, "SMARTCARD support is deactivated in pluto/Makefile!"); + sc->valid = FALSE; + whack_log(RC_LOG_SERIOUS, "SMARTCARD support is deactivated in pluto/Makefile!"); #endif - return sc->valid; + return sc->valid; } @@ -1785,13 +1799,13 @@ scx_get_pin(smartcard_t *sc, int whackfd) void scx_free_pin(chunk_t *pin) { - if (pin->ptr != NULL) - { - /* clear pin field in memory */ - memset(pin->ptr, '\0', pin->len); - pfree(pin->ptr); - *pin = empty_chunk; - } + if (pin->ptr != NULL) + { + /* clear pin field in memory */ + memset(pin->ptr, '\0', pin->len); + free(pin->ptr); + *pin = chunk_empty; + } } /* @@ -1800,14 +1814,14 @@ scx_free_pin(chunk_t *pin) void scx_free(smartcard_t *sc) { - if (sc != NULL) - { - scx_release_context(sc); - pfreeany(sc->id); - pfreeany(sc->label); - scx_free_pin(&sc->pin); - pfree(sc); - } + if (sc != NULL) + { + scx_release_context(sc); + free(sc->id); + free(sc->label); + scx_free_pin(&sc->pin); + free(sc); + } } /* release of a smartcard record decreases the count by one @@ -1816,15 +1830,15 @@ scx_free(smartcard_t *sc) void scx_release(smartcard_t *sc) { - if (sc != NULL && --sc->count == 0) - { - smartcard_t **pp = &smartcards; - while (*pp != sc) - pp = &(*pp)->next; - *pp = sc->next; - release_cert(sc->last_cert); - scx_free(sc); - } + if (sc != NULL && --sc->count == 0) + { + smartcard_t **pp = &smartcards; + while (*pp != sc) + pp = &(*pp)->next; + *pp = sc->next; + release_cert(sc->last_cert); + scx_free(sc); + } } /* @@ -1833,17 +1847,17 @@ scx_release(smartcard_t *sc) static bool scx_same(smartcard_t *a, smartcard_t *b) { - if (a->number && b->number) - { - /* same number */ - return a->number == b->number; - } - else - { - /* same id and/or same slot */ - return (!a->id || (b->id && streq(a->id, b->id))) - && (a->any_slot || b->any_slot || a->slot == b->slot); - } + if (a->number && b->number) + { + /* same number */ + return a->number == b->number; + } + else + { + /* same id and/or same slot */ + return (!a->id || (b->id && streq(a->id, b->id))) + && (a->any_slot || b->any_slot || a->slot == b->slot); + } } /* for each link pointing to the smartcard record @@ -1852,8 +1866,8 @@ scx_same(smartcard_t *a, smartcard_t *b) void scx_share(smartcard_t *sc) { - if (sc != NULL) - sc->count++; + if (sc != NULL) + sc->count++; } /* @@ -1862,28 +1876,28 @@ scx_share(smartcard_t *sc) smartcard_t* scx_add(smartcard_t *smartcard) { - smartcard_t *sc = smartcards; - smartcard_t **psc = &smartcards; - - while (sc != NULL) - { - if (scx_same(smartcard, sc)) /* already in chain, free smartcard record */ - { - scx_free(smartcard); - return sc; - } - psc = &sc->next; - sc = sc->next; - } - - /* insert new smartcard record at the end of the chain */ - *psc = smartcard; - smartcard->number = ++sc_number; - smartcard->count = 1; - DBG(DBG_CONTROL | DBG_PARSING, - DBG_log(" smartcard #%d added", sc_number) - ) - return smartcard; + smartcard_t *sc = smartcards; + smartcard_t **psc = &smartcards; + + while (sc != NULL) + { + if (scx_same(smartcard, sc)) /* already in chain, free smartcard record */ + { + scx_free(smartcard); + return sc; + } + psc = &sc->next; + sc = sc->next; + } + + /* insert new smartcard record at the end of the chain */ + *psc = smartcard; + smartcard->number = ++sc_number; + smartcard->count = 1; + DBG(DBG_CONTROL | DBG_PARSING, + DBG_log(" smartcard #%d added", sc_number) + ) + return smartcard; } /* @@ -1892,15 +1906,15 @@ scx_add(smartcard_t *smartcard) smartcard_t* scx_get(x509cert_t *cert) { - smartcard_t *sc = smartcards; - - while (sc != NULL) - { - if (sc->last_cert.u.x509 == cert) - return sc; - sc = sc->next; - } - return NULL; + smartcard_t *sc = smartcards; + + while (sc != NULL) + { + if (sc->last_cert.u.x509 == cert) + return sc; + sc = sc->next; + } + return NULL; } /* @@ -1909,13 +1923,13 @@ scx_get(x509cert_t *cert) char * scx_print_slot(smartcard_t *sc, const char *whitespace) { - char *buf = temporary_cyclic_buffer(); + char *buf = temporary_cyclic_buffer(); - if (sc->any_slot) - snprintf(buf, BUF_LEN, "any slot"); - else - snprintf(buf, BUF_LEN, "slot: %s%lu", whitespace, sc->slot); - return buf; + if (sc->any_slot) + snprintf(buf, BUF_LEN, "any slot"); + else + snprintf(buf, BUF_LEN, "slot: %s%lu", whitespace, sc->slot); + return buf; } /* @@ -1924,39 +1938,39 @@ scx_print_slot(smartcard_t *sc, const char *whitespace) void scx_list(bool utc) { - smartcard_t *sc = smartcards; - - if (sc != NULL) - { - whack_log(RC_COMMENT, " "); - whack_log(RC_COMMENT, "List of Smartcard Objects:"); - whack_log(RC_COMMENT, " "); - } - - while (sc != NULL) - { - whack_log(RC_COMMENT, "%s, #%d, count: %d" - , timetoa(&sc->last_load, utc) - , sc->number - , sc->count); - whack_log(RC_COMMENT, " %s, session %s, logged %s, has %s" - , scx_print_slot(sc, " ") - , sc->session_opened? "opened" : "closed" - , sc->logged_in? "in" : "out" - , sc->pinpad? "pin pad" - : ((sc->pin.ptr == NULL)? "no pin" - : sc->valid? "valid pin" : "invalid pin")); - if (sc->id != NULL) - whack_log(RC_COMMENT, " id: %s", sc->id); - if (sc->label != NULL) - whack_log(RC_COMMENT, " label: '%s'", sc->label); - if (sc->last_cert.type == CERT_X509_SIGNATURE) - { - char buf[BUF_LEN]; - - dntoa(buf, BUF_LEN, sc->last_cert.u.x509->subject); - whack_log(RC_COMMENT, " subject: '%s'", buf); - } - sc = sc->next; - } + smartcard_t *sc = smartcards; + + if (sc != NULL) + { + whack_log(RC_COMMENT, " "); + whack_log(RC_COMMENT, "List of Smartcard Objects:"); + whack_log(RC_COMMENT, " "); + } + + while (sc != NULL) + { + whack_log(RC_COMMENT, "%T, #%d, count: %d" + , &sc->last_load, utc + , sc->number + , sc->count); + whack_log(RC_COMMENT, " %s, session %s, logged %s, has %s" + , scx_print_slot(sc, " ") + , sc->session_opened? "opened" : "closed" + , sc->logged_in? "in" : "out" + , sc->pinpad? "pin pad" + : ((sc->pin.ptr == NULL)? "no pin" + : sc->valid? "valid pin" : "invalid pin")); + if (sc->id != NULL) + whack_log(RC_COMMENT, " id: %s", sc->id); + if (sc->label != NULL) + whack_log(RC_COMMENT, " label: '%s'", sc->label); + if (sc->last_cert.type == CERT_X509_SIGNATURE) + { + char buf[BUF_LEN]; + + dntoa(buf, BUF_LEN, sc->last_cert.u.x509->subject); + whack_log(RC_COMMENT, " subject: '%s'", buf); + } + sc = sc->next; + } } |