summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>2006-04-05 07:17:02 +0000
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>2006-04-05 07:17:02 +0000
commit18597b93f7b43f63173f373fbd8548f2d08e25bb (patch)
tree31287d7784477dff653e5b92daee22872f58cab2
parentbe9150b693345134142d1d58fac9b251d7e7ba5d (diff)
downloadopenvpn-18597b93f7b43f63173f373fbd8548f2d08e25bb.tar.gz
openvpn-18597b93f7b43f63173f373fbd8548f2d08e25bb.tar.xz
openvpn-18597b93f7b43f63173f373fbd8548f2d08e25bb.zip
I've recently worked on a better version of pkcs11-helper. I've also merged
it into QCA (Qt Cryptographic Architecture), so that KDE 4 will finally be able to use smartcards. The changes allows the following features: 1. Thread safe, is activated if USE_PTHREAD. 2. Slot event - Will allow us in the future to disconnect VPN when smartcard is removed. In order to support this OpenVPN must support threading... At least SIGUSR1 from a different thread. Threading should be supported in both Windows and Linux. -- currently disabled. When I talk about threading support it is just support in configuration script and that the method that SIGUSR1 self can be called from a different thread. I already handle the monitor threads. 3. Certificate enumeration - Will allow us to finally have one configuration file for all users! When you add the plugin GUI stuff you talked about, we will be able to display a list of available certificates for the user to select. -- currently disabled. 4. Data object manipulation - Will allow us to store tls-auth on the smartcard as well. -- currently disabled. 5. Many other minor improvements. Alon Bar-Lev git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@990 e7ae566f-a301-0410-adde-c780ea21d3b5
-rw-r--r--init.c5
-rw-r--r--openvpn.8101
-rw-r--r--options.c70
-rw-r--r--options.h6
-rw-r--r--pkcs11-helper-config.h67
-rw-r--r--pkcs11-helper.c10314
-rw-r--r--pkcs11-helper.h884
-rw-r--r--pkcs11.c315
-rw-r--r--pkcs11.h11
-rw-r--r--ssl.c2
10 files changed, 9422 insertions, 2353 deletions
diff --git a/init.c b/init.c
index 589cd03..de0a40b 100644
--- a/init.c
+++ b/init.c
@@ -140,9 +140,10 @@ context_init_1 (struct context *c)
#if defined(ENABLE_PKCS11)
if (c->first_time) {
int i;
- pkcs11_initialize (c->options.pkcs11_pin_cache_period);
+ pkcs11_initialize (true, c->options.pkcs11_pin_cache_period);
for (i=0;i<MAX_PARMS && c->options.pkcs11_providers[i] != NULL;i++)
- pkcs11_addProvider (c->options.pkcs11_providers[i], c->options.pkcs11_sign_mode[i]);
+ pkcs11_addProvider (c->options.pkcs11_providers[i], c->options.pkcs11_protected_authentication[i],
+ c->options.pkcs11_sign_mode[i], c->options.pkcs11_cert_private[i]);
}
#endif
diff --git a/openvpn.8 b/openvpn.8
index e87609d..499d802 100644
--- a/openvpn.8
+++ b/openvpn.8
@@ -205,15 +205,15 @@ openvpn \- secure IP tunnel daemon.
[\ \fB\-\-ping\-restart\fR\ \fIn\fR\ ]
[\ \fB\-\-ping\-timer\-rem\fR\ ]
[\ \fB\-\-ping\fR\ \fIn\fR\ ]
+[\ \fB\-\-pkcs11\-cert\-private\fR\ \fI[0|1]...\fR\ ]
+[\ \fB\-\-pkcs11\-id\fR\ \fIname\fR\ ]
+[\ \fB\-\-pkcs11\-id\-type\fR\ \fItype\fR\ ]
+[\ \fB\-\-pkcs11\-pin\-cache\fR\ \fIseconds\fR\ ]
+[\ \fB\-\-pkcs11\-protected\-authentication\fR\ \fI[0|1]...\fR\ ]
[\ \fB\-\-pkcs11\-providers\fR\ \fIprovider...\fR\ ]
[\ \fB\-\-pkcs11\-sign\-mode\fR\ \fImode...\fR\ ]
-[\ \fB\-\-pkcs11\-slot\-type\fR\ \fItype\fR\ ]
[\ \fB\-\-pkcs11\-slot\fR\ \fIname\fR\ ]
-[\ \fB\-\-pkcs11\-id\-type\fR\ \fItype\fR\ ]
-[\ \fB\-\-pkcs11\-id\fR\ \fIname\fR\ ]
-[\ \fB\-\-pkcs11\-pin\-cache\fR\ \fIseconds\fR\ ]
-[\ \fB\-\-pkcs11\-protected\-authentication\fR\ ]
-[\ \fB\-\-pkcs11\-cert\-private\fR\ ]
+[\ \fB\-\-pkcs11\-slot\-type\fR\ \fItype\fR\ ]
[\ \fB\-\-pkcs12\fR\ \fIfile\fR\ ]
[\ \fB\-\-plugin\fR\ \fImodule\-pathname\ init\-string\fR\ ]
[\ \fB\-\-port\fR\ \fIport\fR\ ]
@@ -257,8 +257,8 @@ openvpn \- secure IP tunnel daemon.
[\ \fB\-\-show\-ciphers\fR\ ]
[\ \fB\-\-show\-digests\fR\ ]
[\ \fB\-\-show\-engines\fR\ ]
-[\ \fB\-\-show\-pkcs11\-slots\fR\ \fIprovider\fR\ ]
[\ \fB\-\-show\-pkcs11\-objects\fR\ \fIprovider\ slot\fR\ ]
+[\ \fB\-\-show\-pkcs11\-slots\fR\ \fIprovider\fR\ ]
[\ \fB\-\-show\-net\-up\fR\ ]
[\ \fB\-\-show\-net\fR\ ]
[\ \fB\-\-show\-tls\fR\ ]
@@ -3620,6 +3620,39 @@ and
.B --key.
.\"*********************************************************
.TP
+.B --pkcs11-cert-private [0|1]...
+Set if access to certificate object should be performed after login.
+Every provider has its own setting.
+.\"*********************************************************
+.TP
+.B --pkcs11-id name
+Specify a name of the object to search for.
+.\"*********************************************************
+.TP
+.B --pkcs11-id-type type
+Specify how to locate the correct objects. Type can be one of the following:
+
+.B 'id'
+-- Locate by the id attribte, name should be hex encoded string.
+.br
+.B 'label'
+-- Locate by the label attribute, name should be string.
+.br
+.B 'subject'
+-- Locate by certificate subject attribute, name should be string.
+.br
+.\"*********************************************************
+.TP
+.B --pkcs11-pin-cache seconds
+Specify how many seconds the PIN can be cached, the default is until the token is removed.
+.\"*********************************************************
+.TP
+.B --pkcs11-protected-authentication [0|1]...
+Use PKCS#11 protected authentication path, useful for biometric and external
+keypad devices.
+Every provider has its own setting.
+.\"*********************************************************
+.TP
.B --pkcs11-providers provider...
Specify a RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki) providers
to load.
@@ -3636,21 +3669,30 @@ for each provider. Mode can be one of the following:
.B 'auto'
(default) -- Try to determind automatically.
.br
+.B 'sign'
+-- Use Sign.
+.br
.B 'recover'
-- Use SignRecover.
.br
-.B 'sign'
--- Use Sign.
+.B 'any'
+-- Use Sign and if not supported use SignRecover.
.br
.\"*********************************************************
.TP
+.B --pkcs11-slot name
+Specify a name of the slot to search for.
+.\"*********************************************************
+.TP
.B --pkcs11-slot-type type
Specify how to locate the correct slot. Type can be one of the following:
.B 'id'
--- Locate the slot by a numeric id. The format is [provider:]id, for example, slot 2 of provider 1
-is encoded as 1:2. If you have only one provider you can omit the provider number.
-The provider number is set by the order specified in the --pkcs11-providers option.
+-- Locate the slot by a numeric id. The format is [provider:]id, for example, slot 2 of provider a.so
+should be encoded as a.so:2. If you have only one provider you can omit the provider name.
+The provider name is set by the name specified in the
+.B --pkcs11-providers
+option.
.br
.B 'name'
-- Locate the slot by its name.
@@ -3660,41 +3702,6 @@ The provider number is set by the order specified in the --pkcs11-providers opti
.br
.\"*********************************************************
.TP
-.B --pkcs11-slot name
-Specify a name of the slot to search for.
-.\"*********************************************************
-.TP
-.B --pkcs11-id-type type
-Specify how to locate the correct objects. Type can be one of the following:
-
-.B 'id'
--- Locate by the id attribte, name should be hex encoded string.
-.br
-.B 'label'
--- Locate by the label attribute, name should be string.
-.br
-.B 'subject'
--- Locate by certificate subject attribute, name should be string.
-.br
-.\"*********************************************************
-.TP
-.B --pkcs11-id name
-Specify a name of the object to search for.
-.\"*********************************************************
-.TP
-.B --pkcs11-pin-cache seconds
-Specify how many seconds the PIN can be cached, the default is until the token is removed.
-.\"*********************************************************
-.TP
-.B --pkcs11-protected-authentication
-Use PKCS#11 protected authentication path, useful for biometric and external
-keypad devices.
-.\"*********************************************************
-.TP
-.B --pkcs11-cert-private
-Set if access to certificate object should be performed after login.
-.\"*********************************************************
-.TP
.B --cryptoapicert select-string
Load the certificate and private key from the
Windows Certificate System Store (Windows Only).
diff --git a/options.c b/options.c
index a889eb5..793ae66 100644
--- a/options.c
+++ b/options.c
@@ -492,12 +492,19 @@ static const char usage_message[] =
"\n"
"PKCS#11 Options:\n"
"--pkcs11-providers provider ... : PKCS#11 provider to load.\n"
+ "--pkcs11-protected-authentication [0|1] ... : Use PKCS#11 protected authentication\n"
+ " path. Set for each provider.\n"
"--pkcs11-sign-mode mode ... : PKCS#11 signature method.\n"
" auto : Try to determind automatically (default).\n"
- " recover : Use SignRecover.\n"
" sign : Use Sign.\n"
+ " recover : Use SignRecover.\n"
+ " any : Use Sign and then SignRecover.\n"
+ "--pkcs11-cert-private [0|1] ... : Set if login should be performed before\n"
+ " certificate can be accessed. Set for each provider.\n"
+ "--pkcs11-pin-cache seconds : Number of seconds to cache PIN. The default is -1\n"
+ " cache until token is removed.\n"
"--pkcs11-slot-type method : Slot locate method:\n"
- " id : By slot id (numeric [prov#:]slot#).\n"
+ " id : By slot id (numeric [prov:]slot#).\n"
" name : By slot name.\n"
" label : By the card label that resides in slot.\n"
"--pkcs11-slot name : The slot name.\n"
@@ -506,11 +513,6 @@ static const char usage_message[] =
" label : By the object label (string).\n"
" subject : By certificate subject (String).\n"
"--pkcs11-id name : The object name.\n"
- "--pkcs11-pin-cache seconds : Number of seconds to cache PIN. The default is -1\n"
- " cache until token removed.\n"
- "--pkcs11-protected-authentication : Use PKCS#11 protected authentication path.\n"
- "--pkcs11-cert-private : Set if login should be performed before\n"
- " certificate can be accessed.\n"
#endif /* ENABLE_PKCS11 */
"\n"
"SSL Library information:\n"
@@ -688,8 +690,6 @@ init_options (struct options *o)
#endif
#ifdef ENABLE_PKCS11
o->pkcs11_pin_cache_period = -1;
- o->pkcs11_protected_authentication = false;
- o->pkcs11_cert_private = false;
#endif /* ENABLE_PKCS11 */
}
@@ -1265,16 +1265,24 @@ show_settings (const struct options *o)
}
{
int i;
+ for (i=0;i<MAX_PARMS;i++)
+ SHOW_PARM (pkcs11_protected_authentication, o->pkcs11_protected_authentication[i] ? "ENABLED" : "DISABLED", "%s");
+ }
+ {
+ int i;
for (i=0;i<MAX_PARMS && o->pkcs11_sign_mode[i] != NULL;i++)
SHOW_PARM (pkcs11_sign_mode, o->pkcs11_sign_mode[i], "%s");
}
+ {
+ int i;
+ for (i=0;i<MAX_PARMS;i++)
+ SHOW_PARM (pkcs11_cert_private, o->pkcs11_cert_private[i] ? "ENABLED" : "DISABLED", "%s");
+ }
+ SHOW_INT (pkcs11_pin_cache_period);
SHOW_STR (pkcs11_slot_type);
SHOW_STR (pkcs11_slot);
SHOW_STR (pkcs11_id_type);
SHOW_STR (pkcs11_id);
- SHOW_INT (pkcs11_pin_cache_period);
- SHOW_BOOL (pkcs11_protected_authentication);
- SHOW_BOOL (pkcs11_cert_private);
#endif /* ENABLE_PKCS11 */
#if P2MP
@@ -5080,6 +5088,15 @@ add_option (struct options *options,
for (j = 1; j < MAX_PARMS && p[j] != NULL; ++j)
options->pkcs11_providers[j-1] = p[j];
}
+ else if (streq (p[0], "pkcs11-protected-authentication"))
+ {
+ int j;
+
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+
+ for (j = 1; j < MAX_PARMS && p[j] != NULL; ++j)
+ options->pkcs11_protected_authentication[j-1] = atoi (p[j]) != 0 ? 1 : 0;
+ }
else if (streq (p[0], "pkcs11-sign-mode") && p[1])
{
int j;
@@ -5089,6 +5106,20 @@ add_option (struct options *options,
for (j = 1; j < MAX_PARMS && p[j] != NULL; ++j)
options->pkcs11_sign_mode[j-1] = p[j];
}
+ else if (streq (p[0], "pkcs11-cert-private"))
+ {
+ int j;
+
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+
+ for (j = 1; j < MAX_PARMS && p[j] != NULL; ++j)
+ options->pkcs11_cert_private[j-1] = atoi (p[j]) != 0 ? 1 : 0;
+ }
+ else if (streq (p[0], "pkcs11-pin-cache") && p[1])
+ {
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ options->pkcs11_pin_cache_period = atoi (p[1]);
+ }
else if (streq (p[0], "pkcs11-slot-type") && p[1])
{
VERIFY_PERMISSION (OPT_P_GENERAL);
@@ -5109,21 +5140,6 @@ add_option (struct options *options,
VERIFY_PERMISSION (OPT_P_GENERAL);
options->pkcs11_id = p[1];
}
- else if (streq (p[0], "pkcs11-pin-cache") && p[1])
- {
- VERIFY_PERMISSION (OPT_P_GENERAL);
- options->pkcs11_pin_cache_period = atoi (p[1]);
- }
- else if (streq (p[0], "pkcs11-protected-authentication"))
- {
- VERIFY_PERMISSION (OPT_P_GENERAL);
- options->pkcs11_protected_authentication = true;
- }
- else if (streq (p[0], "pkcs11-cert-private"))
- {
- VERIFY_PERMISSION (OPT_P_GENERAL);
- options->pkcs11_cert_private = true;
- }
#endif
#ifdef TUNSETPERSIST
else if (streq (p[0], "rmtun"))
diff --git a/options.h b/options.h
index 4bf1139..4349f7d 100644
--- a/options.h
+++ b/options.h
@@ -409,13 +409,13 @@ struct options
#ifdef ENABLE_PKCS11
const char *pkcs11_providers[MAX_PARMS];
const char *pkcs11_sign_mode[MAX_PARMS];
+ bool pkcs11_protected_authentication[MAX_PARMS];
+ bool pkcs11_cert_private[MAX_PARMS];
+ int pkcs11_pin_cache_period;
const char *pkcs11_slot_type;
const char *pkcs11_slot;
const char *pkcs11_id_type;
const char *pkcs11_id;
- int pkcs11_pin_cache_period;
- bool pkcs11_protected_authentication;
- bool pkcs11_cert_private;
#endif
#ifdef WIN32
diff --git a/pkcs11-helper-config.h b/pkcs11-helper-config.h
index f5d4608..d3276ed 100644
--- a/pkcs11-helper-config.h
+++ b/pkcs11-helper-config.h
@@ -22,10 +22,10 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef __PKCS11_HELPER_CONFIG_H
-#define __PKCS11_HELPER_CONFIG_H
+#ifndef __PKCS11H_HELPER_CONFIG_H
+#define __PKCS11H_HELPER_CONFIG_H
-#if!defined(PKCS11H_NO_NEED_INCLUDE_CONFIG)
+#if !defined(PKCS11H_NO_NEED_INCLUDE_CONFIG)
#if defined(WIN32)
#include "config-win32.h"
@@ -38,33 +38,26 @@
#endif /* PKCS11H_NO_NEED_INCLUDE_CONFIG */
#ifdef ENABLE_PKCS11
-#define PKCS11H_ENABLE_HELPER
+#define ENABLE_PKCS11H_HELPER
#endif
-#ifdef PKCS11H_ENABLE_HELPER
+#ifdef ENABLE_PKCS11H_HELPER
#include "error.h"
#include "misc.h"
#include "ssl.h"
-#define PKCS11ASSERT ASSERT
-#define PKCS11LOG msg
-#define PKCS11DLOG dmsg
-#define PKCS11_LOG_DEBUG2 D_PKCS11_DEBUG
-#define PKCS11_LOG_DEBUG1 D_SHOW_PKCS11
-#define PKCS11_LOG_INFO M_INFO
-#define PKCS11_LOG_WARN M_WARN
-#define PKCS11_LOG_ERROR M_FATAL
+#undef PKCS11H_USE_CYGWIN /* cygwin is not supported in openvpn */
-#undef PKCS11_USE_CYGWIN
-
-#if !defined(false)
-#define false 0
+#if !defined(FALSE)
+#define FALSE false
#endif
-#if !defined(true)
-#define true (!false)
+#if !defined(TRUE)
+#define TRUE true
#endif
+typedef bool PKCS11H_BOOL;
+
#if !defined(IN)
#define IN
#endif
@@ -72,18 +65,34 @@
#define OUT
#endif
-#define PKCS11_PRM_SLOT_TYPE "--pkcs11-slot-type"
-#define PKCS11_PRM_SLOT_ID "--pkcs11-slot"
-#define PKCS11_PRM_OBJ_TYPE "--pkcs11-id-type"
-#define PKCS11_PRM_OBJ_ID "--pkcs11-id"
-
-#define PKCS11_TIME openvpn_time
-
-#if defined(WIN32) || defined(PKCS11_USE_CYGWIN)
+#ifdef ENABLE_DEBUG
+#define ENABLE_PKCS11H_DEBUG
+#endif
+#ifdef USE_PTHREAD
+#define ENABLE_PKCS11H_THREADING
+#endif
+#undef ENABLE_PKCS11H_TOKEN
+#undef ENABLE_PKCS11H_DATA
+#define ENABLE_PKCS11H_CERTIFICATE
+#define ENABLE_PKCS11H_LOCATE
+#undef ENABLE_PKCS11H_ENUM
+#undef ENABLE_PKCS11H_SLOTEVENT
+#define ENABLE_PKCS11H_OPENSSL
+#define ENABLE_PKCS11H_STANDALONE
+
+#define PKCS11H_PRM_SLOT_TYPE "--pkcs11-slot-type"
+#define PKCS11H_PRM_SLOT_ID "--pkcs11-slot"
+#define PKCS11H_PRM_OBJ_TYPE "--pkcs11-id-type"
+#define PKCS11H_PRM_OBJ_ID "--pkcs11-id"
+
+#define PKCS11H_ASSERT ASSERT
+#define PKCS11H_TIME openvpn_time
+
+#if defined(WIN32) || defined(PKCS11H_USE_CYGWIN)
#include "cryptoki-win32.h"
#else
#include "cryptoki.h"
#endif
-#endif /* PKCS11H_ENABLE_HELPER */
-#endif /* __PKCS11_HELPER_CONFIG_H */
+#endif /* PKCS11_ENABLE_HELPER */
+#endif /* __PKCS11H_HELPER_CONFIG_H */
diff --git a/pkcs11-helper.c b/pkcs11-helper.c
index 04af86a..111dbdb 100644
--- a/pkcs11-helper.c
+++ b/pkcs11-helper.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005 Alon Bar-Lev <alon.barlev@gmail.com>
+ * Copyright (c) 2005-2006 Alon Bar-Lev <alon.barlev@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifi-
@@ -36,7 +36,7 @@
#include "pkcs11-helper-config.h"
-#if defined(PKCS11H_ENABLE_HELPER)
+#if defined(ENABLE_PKCS11H_HELPER)
#include "pkcs11-helper.h"
@@ -44,12 +44,6 @@
* Constants
*/
-#if OPENSSL_VERSION_NUMBER < 0x00908000L
-typedef unsigned char *pkcs11_openssl_d2i_t;
-#else
-typedef const unsigned char *pkcs11_openssl_d2i_t;
-#endif
-
#if OPENSSL_VERSION_NUMBER < 0x00907000L && defined(CRYPTO_LOCK_ENGINE)
# define RSA_get_default_method RSA_get_default_openssl_method
#else
@@ -65,69 +59,382 @@ typedef const unsigned char *pkcs11_openssl_d2i_t;
#define PKCS11H_INVALID_SESSION_HANDLE ((CK_SESSION_HANDLE)-1)
#define PKCS11H_INVALID_OBJECT_HANDLE ((CK_OBJECT_HANDLE)-1)
+#define PKCS11H_DEFAULT_SLOTEVENT_POLL 5000
+#define PKCS11H_DEFAULT_MAX_LOGIN_RETRY 3
+#define PKCS11H_DEFAULT_PIN_CACHE_PERIOD PKCS11H_PIN_CACHE_INFINITE
+
+enum _pkcs11h_private_op_e {
+ _pkcs11h_private_op_sign=0,
+ _pkcs11h_private_op_sign_recover,
+ _pkcs11h_private_op_decrypt
+};
+
+/*===========================================
+ * Macros
+ */
+
+#define PKCS11H_MSG_LEVEL_TEST(flags) (((unsigned int)flags) <= s_pkcs11h_loglevel)
+
+#if defined(HAVE_CPP_VARARG_MACRO_ISO) && !defined(__LCLINT__)
+# define PKCS11H_LOG(flags, ...) do { if (PKCS11H_MSG_LEVEL_TEST(flags)) _pkcs11h_log((flags), __VA_ARGS__); } while (FALSE)
+# ifdef ENABLE_PKCS11H_DEBUG
+# define PKCS11H_DEBUG(flags, ...) do { if (PKCS11H_MSG_LEVEL_TEST(flags)) _pkcs11h_log((flags), __VA_ARGS__); } while (FALSE)
+# else
+# define PKCS11H_DEBUG(flags, ...)
+# endif
+#elif defined(HAVE_CPP_VARARG_MACRO_GCC) && !defined(__LCLINT__)
+# define PKCS11H_LOG(flags, args...) do { if (PKCS11H_MSG_LEVEL_TEST(flags)) _pkcs11h_log((flags), args); } while (FALSE)
+# ifdef ENABLE_PKCS11H_DEBUG
+# define PKCS11H_DEBUG(flags, args...) do { if (PKCS11H_MSG_LEVEL_TEST(flags)) _pkcs11h_log((flags), args); } while (FALSE)
+# else
+# define PKCS11H_DEBUG(flags, args...)
+# endif
+#else
+# define PKCS11H_LOG _pkcs11h_log
+# define PKCS11H_DEBUG _pkcs11h_log
+#endif
+
/*===========================================
- * Low level prototypes
+ * Types
*/
+struct pkcs11h_provider_s;
+struct pkcs11h_session_s;
+struct pkcs11h_data_s;
+typedef struct pkcs11h_provider_s *pkcs11h_provider_t;
+typedef struct pkcs11h_session_s *pkcs11h_session_t;
+typedef struct pkcs11h_data_s *pkcs11h_data_t;
+
+#if OPENSSL_VERSION_NUMBER < 0x00908000L
+typedef unsigned char *pkcs11_openssl_d2i_t;
+#else
+typedef const unsigned char *pkcs11_openssl_d2i_t;
+#endif
+
+#if defined(ENABLE_PKCS11H_THREADING)
+
+#define PKCS11H_COND_INFINITE 0xffffffff
+
+#if defined(WIN32)
+#define PKCS11H_THREAD_NULL NULL
+typedef HANDLE pkcs11h_cond_t;
+typedef HANDLE pkcs11h_mutex_t;
+typedef HANDLE pkcs11h_thread_t;
+#else
+#define PKCS11H_THREAD_NULL 0l
+typedef pthread_mutex_t pkcs11h_mutex_t;
+typedef pthread_t pkcs11h_thread_t;
+
+typedef struct {
+ pthread_cond_t cond;
+ pthread_mutex_t mut;
+} pkcs11h_cond_t;
+
+typedef struct __pkcs11h_mutex_entry_s {
+ struct __pkcs11h_mutex_entry_s *next;
+ pkcs11h_mutex_t *p_mutex;
+ PKCS11H_BOOL fLocked;
+} *__pkcs11h_mutex_entry_t;
+#endif
+
+typedef void * (*pkcs11h_thread_start_t)(void *);
+
+typedef struct {
+ pkcs11h_thread_start_t start;
+ void *data;
+} __pkcs11h_thread_data_t;
+
+#endif /* ENABLE_PKCS11H_THREADING */
+
+struct pkcs11h_provider_s {
+ pkcs11h_provider_t next;
+
+ PKCS11H_BOOL fEnabled;
+ char szReferenceName[1024];
+ char manufacturerID[sizeof (((CK_TOKEN_INFO *)NULL)->manufacturerID)+1];
+
+#if defined(WIN32)
+ HANDLE hLibrary;
+#else
+ void *hLibrary;
+#endif
+
+ CK_FUNCTION_LIST_PTR f;
+ PKCS11H_BOOL fShouldFinalize;
+ PKCS11H_BOOL fProtectedAuthentication;
+ PKCS11H_BOOL fCertIsPrivate;
+ unsigned maskSignMode;
+ int nSlotEventMethod;
+ int nSlotEventPollInterval;
+
+#if defined(ENABLE_PKCS11H_SLOTEVENT)
+ pkcs11h_thread_t threadSlotEvent;
+#endif
+};
+
+struct pkcs11h_session_s {
+ pkcs11h_session_t next;
+
+ int nReferenceCount;
+ PKCS11H_BOOL fValid;
+
+ pkcs11h_provider_t provider;
+
+ pkcs11h_token_id_t token_id;
+
+ CK_SESSION_HANDLE hSession;
+
+ PKCS11H_BOOL fProtectedAuthenticationSupported;
+ int nPINCachePeriod;
+ time_t timePINExpire;
+
+#if defined(ENABLE_PKCS11H_ENUM)
+#if defined(ENABLE_PKCS11H_CERTIFICATE)
+ pkcs11h_certificate_id_list_t cached_certs;
+ PKCS11H_BOOL fTouch;
+#endif
+#endif
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ pkcs11h_mutex_t mutexSession;
+#endif
+};
+
+#if defined (ENABLE_PKCS11H_CERTIFICATE)
+
+struct pkcs11h_certificate_s {
+
+ pkcs11h_certificate_id_t id;
+ int nPINCachePeriod;
+
+ unsigned maskSignMode;
+
+ pkcs11h_session_t session;
+ CK_OBJECT_HANDLE hKey;
+
+ PKCS11H_BOOL fOperationActive;
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ pkcs11h_mutex_t mutexCertificate;
+#endif
+};
+
+#endif /* ENABLE_PKCS11H_CERTIFICATE */
+
+struct pkcs11h_data_s {
+ PKCS11H_BOOL fInitialized;
+ int nPINCachePeriod;
+
+ pkcs11h_provider_t providers;
+ pkcs11h_session_t sessions;
+
+ struct {
+ void *log_data;
+ void *slotevent_data;
+ void *token_prompt_data;
+ void *pin_prompt_data;
+ pkcs11h_hook_log_t log;
+ pkcs11h_hook_slotevent_t slotevent;
+ pkcs11h_hook_token_prompt_t token_prompt;
+ pkcs11h_hook_pin_prompt_t pin_prompt;
+ } hooks;
+
+ PKCS11H_BOOL fProtectedAuthentication;
+ int nMaxLoginRetries;
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ pkcs11h_mutex_t mutexGlobal;
+ pkcs11h_mutex_t mutexSession;
+ pkcs11h_mutex_t mutexCache;
+#endif
+
+#if defined(ENABLE_PKCS11H_SLOTEVENT)
+ PKCS11H_BOOL fSlotEventInitialized;
+ PKCS11H_BOOL fSlotEventShouldTerminate;
+ PKCS11H_BOOL fSlotEventSkipEvent;
+ pkcs11h_cond_t condSlotEvent;
+ pkcs11h_thread_t threadSlotEvent;
+#endif
+};
+
+#if defined(ENABLE_PKCS11H_OPENSSL)
+struct pkcs11h_openssl_session_s {
+ int nReferenceCount;
+ PKCS11H_BOOL fInitialized;
+ X509 *x509;
+ RSA_METHOD smart_rsa;
+ int (*orig_finish)(RSA *rsa);
+ pkcs11h_certificate_t certificate;
+};
+#endif
+
+/*======================================================================*
+ * MEMORY INTERFACE
+ *======================================================================*/
+
+static
+CK_RV
+_pkcs11h_malloc (
+ OUT const void ** const p,
+ IN const size_t s
+);
+static
+CK_RV
+_pkcs11h_free (
+ IN const void ** const p
+);
+static
+CK_RV
+_pkcs11h_dupmem (
+ OUT const void ** const dest,
+ OUT size_t * const dest_size,
+ IN const void * const src,
+ IN const size_t mem_size
+);
+
+#if defined(ENABLE_PKCS11H_THREADING)
+/*======================================================================*
+ * THREADING INTERFACE
+ *======================================================================*/
+
+static
+void
+_pkcs11h_sleep (
+ IN const unsigned milli
+);
+static
+CK_RV
+_pkcs11h_mutexInit (
+ OUT pkcs11h_mutex_t * const mutex
+);
+static
+CK_RV
+_pkcs11h_mutexLock (
+ IN OUT pkcs11h_mutex_t *const mutex
+);
+static
+CK_RV
+_pkcs11h_mutexRelease (
+ IN OUT pkcs11h_mutex_t *const mutex
+);
+static
+CK_RV
+_pkcs11h_mutexFree (
+ IN OUT pkcs11h_mutex_t *const mutex
+);
+#if !defined(WIN32)
+static
+void
+__pkcs1h_mutexLockAll ();
+static
+void
+__pkcs1h_mutexReleaseAll ();
+#endif
+static
+CK_RV
+_pkcs11h_condSignal (
+ IN OUT pkcs11h_cond_t *const cond
+);
+static
+CK_RV
+_pkcs11h_condInit (
+ OUT pkcs11h_cond_t * const cond
+);
+static
+CK_RV
+_pkcs11h_condWait (
+ IN OUT pkcs11h_cond_t *const cond,
+ IN const unsigned milli
+);
+static
+CK_RV
+_pkcs11h_condFree (
+ IN OUT pkcs11h_cond_t *const cond
+);
+static
+CK_RV
+_pkcs11h_threadStart (
+ OUT pkcs11h_thread_t * const thread,
+ IN pkcs11h_thread_start_t const start,
+ IN void * data
+);
+static
+CK_RV
+_pkcs11h_threadJoin (
+ IN pkcs11h_thread_t * const thread
+);
+#endif /* ENABLE_PKCS11H_THREADING */
+
+/*======================================================================*
+ * COMMON INTERNAL INTERFACE
+ *======================================================================*/
+
static
void
_pkcs11h_fixupFixedString (
- IN const char * const szSource,
OUT char * const szTarget, /* MUST BE >= nLength+1 */
+ IN const char * const szSource,
IN const size_t nLength /* FIXED STRING LENGTH */
);
static
void
-_hexToBinary (
- IN const char * const szSource,
- OUT unsigned char * const target,
- IN OUT size_t * const target_size
+_pkcs11h_log (
+ IN const unsigned flags,
+ IN const char * const szFormat,
+ IN ...
+)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+ ;
+
+static
+CK_RV
+_pkcs11h_getSlotList (
+ IN const pkcs11h_provider_t provider,
+ IN const CK_BBOOL tokenPresent,
+ OUT CK_SLOT_ID_PTR * const pSlotList,
+ OUT CK_ULONG_PTR pulCount
);
static
-bool
-_isBetterCertificate (
- IN const unsigned char * const pCurrent,
- IN const size_t nCurrentSize,
- IN const unsigned char * const pNew,
- IN const size_t nNewSize
+CK_RV
+_pkcs11h_getObjectAttributes (
+ IN const pkcs11h_session_t session,
+ IN const CK_OBJECT_HANDLE object,
+ IN OUT const CK_ATTRIBUTE_PTR attrs,
+ IN const unsigned count
);
static
CK_RV
-_pkcs11h_getSlotById (
- IN const char * const szSlot,
- OUT pkcs11h_provider_t * const provider,
- OUT CK_SLOT_ID * const slot
+_pkcs11h_freeObjectAttributes (
+ IN OUT const CK_ATTRIBUTE_PTR attrs,
+ IN const unsigned count
);
static
CK_RV
-_pkcs11h_getSlotByName (
- IN const char * const szName,
- OUT pkcs11h_provider_t * const provider,
- OUT CK_SLOT_ID * const slot
+_pkcs11h_findObjects (
+ IN const pkcs11h_session_t session,
+ IN const CK_ATTRIBUTE * const filter,
+ IN const CK_ULONG filter_attrs,
+ OUT CK_OBJECT_HANDLE **const p_objects,
+ OUT CK_ULONG *p_objects_found
);
static
CK_RV
-_pkcs11h_getSlotByLabel (
- IN const char * const szLabel,
- OUT pkcs11h_provider_t * const provider,
- OUT CK_SLOT_ID * const slot
+_pkcs11h_getTokenId (
+ IN const CK_TOKEN_INFO_PTR info,
+ OUT pkcs11h_token_id_t * const p_token_id
);
static
CK_RV
-_pkcs11h_getSlot (
- IN const char * const szSlotType,
- IN const char * const szSlot,
- OUT pkcs11h_provider_t * const provider,
- OUT CK_SLOT_ID * const slot
+_pkcs11h_newTokenId (
+ OUT pkcs11h_token_id_t * const token_id
);
static
CK_RV
-_pkcs11h_getSession (
- IN const char * const szSlotType,
- IN const char * const szSlot,
- IN const bool fProtectedAuthentication,
- IN const int nPINCachePeriod,
- OUT pkcs11h_session_t * const session
+_pkcs11h_getSessionByTokenId (
+ IN const pkcs11h_token_id_t token_id,
+ OUT pkcs11h_session_t * const p_session
);
static
CK_RV
@@ -138,16 +445,17 @@ static
CK_RV
_pkcs11h_resetSession (
IN const pkcs11h_session_t session,
- OUT CK_SLOT_ID * const slot
+ IN const unsigned maskPrompt,
+ OUT CK_SLOT_ID * const p_slot
);
static
CK_RV
_pkcs11h_getObjectById (
- IN const pkcs11h_session_t pkcs11h_certificate,
+ IN const pkcs11h_session_t certificate,
IN const CK_OBJECT_CLASS class,
- IN const unsigned char * const id,
+ IN const CK_BYTE_PTR id,
IN const size_t id_size,
- OUT CK_OBJECT_HANDLE * const handle
+ OUT CK_OBJECT_HANDLE * const p_handle
);
static
CK_RV
@@ -158,34 +466,241 @@ static
CK_RV
_pkcs11h_login (
IN const pkcs11h_session_t session,
- IN const bool fPublicOnly
+ IN const PKCS11H_BOOL fPublicOnly,
+ IN const PKCS11H_BOOL fReadOnly,
+ IN const unsigned maskPrompt
);
static
CK_RV
_pkcs11h_logout (
IN const pkcs11h_session_t session
);
+
+static
+void
+_pkcs11h_hooks_default_log (
+ IN const void * pData,
+ IN const unsigned flags,
+ IN const char * const szFormat,
+ IN va_list args
+);
+
+static
+PKCS11H_BOOL
+_pkcs11h_hooks_default_token_prompt (
+ IN const void * pData,
+ IN const pkcs11h_token_id_t token
+);
+
+static
+PKCS11H_BOOL
+_pkcs11h_hooks_default_pin_prompt (
+ IN const void * pData,
+ IN const pkcs11h_token_id_t token,
+ OUT char * const szPIN,
+ IN const size_t nMaxPIN
+);
+
+#if !defined(WIN32)
+#if defined(ENABLE_PKCS11H_THREADING)
+static
+void
+__pkcs11h_atfork_prepare ();
+static
+void
+__pkcs11h_atfork_parent ();
+static
+void
+__pkcs11h_atfork_child ();
+#endif
static
CK_RV
-_pkcs11h_setCertificateSession_Certificate (
- IN const pkcs11h_certificate_t pkcs11h_certificate,
- IN const char * const szIdType,
- IN const char * const szId
+_pkcs11h_forkFixup ();
+#endif
+
+#if defined(ENABLE_PKCS11H_CERTIFICATE)
+/*======================================================================*
+ * CERTIFICATE INTERFACE
+ *======================================================================*/
+
+static
+void
+_pkcs11h_isBetterCertificate_getExpiration (
+ IN const unsigned char * const pCertificate,
+ IN const size_t nCertificateSize,
+ OUT char * const szNotBefore,
+ IN const int nNotBeforeSize
+);
+static
+PKCS11H_BOOL
+_pkcs11h_isBetterCertificate (
+ IN const unsigned char * const pCurrent,
+ IN const size_t nCurrentSize,
+ IN const unsigned char * const pNew,
+ IN const size_t nNewSize
);
static
CK_RV
-_pkcs11h_resetCertificateSession (
- IN const pkcs11h_certificate_t pkcs11h_certificate
+_pkcs11h_newCertificateId (
+ OUT pkcs11h_certificate_id_t * const certificate_id
+);
+static
+CK_RV
+_pkcs11h_loadCertificate (
+ IN const pkcs11h_certificate_t certificate
+);
+static
+CK_RV
+_pkcs11h_updateCertificateIdDescription (
+ IN OUT pkcs11h_certificate_id_t certificate_id
+);
+static
+CK_RV
+_pkcs11h_ensureCertificateBlob (
+ IN const pkcs11h_certificate_t certificate
);
static
CK_RV
_pkcs11h_getCertificateKeyAttributes (
- IN const pkcs11h_certificate_t pkcs11h_certificate
+ IN const pkcs11h_certificate_t certificate
+);
+static
+CK_RV
+_pkcs11h_validateCertificateSession (
+ IN const pkcs11h_certificate_t certificate
+);
+static
+CK_RV
+_pkcs11h_resetCertificateSession (
+ IN const pkcs11h_certificate_t certificate,
+ IN const PKCS11H_BOOL fPublicOnly,
+ IN const unsigned maskPrompt
);
+static
+CK_RV
+_pkcs11h_certificate_private_op (
+ IN const pkcs11h_certificate_t certificate,
+ IN const enum _pkcs11h_private_op_e op,
+ IN const CK_MECHANISM_TYPE mech_type,
+ IN const unsigned char * const source,
+ IN const size_t source_size,
+ OUT unsigned char * const target,
+ IN OUT size_t * const p_target_size
+);
+#endif /* ENABLE_PKCS11H_CERTIFICATE */
-/*==========================================
- * openssl interface
- */
+#if defined(ENABLE_PKCS11H_LOCATE)
+/*======================================================================*
+ * LOCATE INTERFACE
+ *======================================================================*/
+
+static
+CK_RV
+_pkcs11h_locate_getTokenIdBySlotId (
+ IN const char * const szSlot,
+ OUT pkcs11h_token_id_t * const p_token_id
+);
+static
+CK_RV
+_pkcs11h_locate_getTokenIdBySlotName (
+ IN const char * const szName,
+ OUT pkcs11h_token_id_t * const p_token_id
+);
+static
+CK_RV
+_pkcs11h_locate_getTokenIdByLabel (
+ IN const char * const szLabel,
+ OUT pkcs11h_token_id_t * const p_token_id
+);
+
+#if defined(ENABLE_PKCS11H_CERTIFICATE)
+
+static
+void
+_pkcs11h_locate_hexToBinary (
+ OUT unsigned char * const target,
+ IN const char * const szSource,
+ IN OUT size_t * const p_target_size
+);
+static
+CK_RV
+_pkcs11h_locate_getCertificateIdByLabel (
+ IN const pkcs11h_session_t session,
+ IN OUT const pkcs11h_certificate_id_t certificate_id,
+ IN const char * const szLabel
+);
+static
+CK_RV
+_pkcs11h_locate_getCertificateIdBySubject (
+ IN const pkcs11h_session_t session,
+ IN OUT const pkcs11h_certificate_id_t certificate_id,
+ IN const char * const szSubject
+);
+
+#endif /* ENABLE_PKCS11H_CERTIFICATE */
+#endif /* ENABLE_PKCS11H_LOCATE */
+
+#if defined(ENABLE_PKCS11H_ENUM)
+/*======================================================================*
+ * ENUM INTERFACE
+ *======================================================================*/
+
+#if defined(ENABLE_PKCS11H_CERTIFICATE)
+
+static
+CK_RV
+_pkcs11h_enum_getSessionCertificates (
+ IN const pkcs11h_session_t session
+);
+static
+CK_RV
+_pkcs11h_enum_splitCertificateIdList (
+ IN const pkcs11h_certificate_id_list_t cert_id_all,
+ OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,
+ OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list
+);
+
+#endif /* ENABLE_PKCS11H_CERTIFICATE */
+
+#endif /* ENABLE_PKCS11H_ENUM */
+
+#if defined(ENABLE_PKCS11H_SLOTEVENT)
+/*======================================================================*
+ * SLOTEVENT INTERFACE
+ *======================================================================*/
+
+static
+unsigned long
+_pkcs11h_slotevent_checksum (
+ IN const unsigned char * const p,
+ IN const size_t s
+);
+static
+void *
+_pkcs11h_slotevent_provider (
+ IN void *p
+);
+static
+void *
+_pkcs11h_slotevent_manager (
+ IN void *p
+);
+static
+CK_RV
+_pkcs11h_slotevent_init ();
+static
+CK_RV
+_pkcs11h_slotevent_notify ();
+static
+CK_RV
+_pkcs11h_slotevent_terminate ();
+
+#endif /* ENABLE_PKCS11H_SLOTEVENT */
+
+#if defined(ENABLE_PKCS11H_OPENSSL)
+/*======================================================================*
+ * OPENSSL INTERFACE
+ *======================================================================*/
static
int
@@ -235,7 +750,7 @@ _pkcs11h_openssl_sign (
#endif
static
pkcs11h_openssl_session_t
-_pkcs11h_openssl_get_pkcs11h_openssl_session (
+_pkcs11h_openssl_get_openssl_session (
IN OUT const RSA *rsa
);
static
@@ -243,501 +758,1691 @@ pkcs11h_certificate_t
_pkcs11h_openssl_get_pkcs11h_certificate (
IN OUT const RSA *rsa
);
+#endif /* ENABLE_PKCS11H_OPENSSL */
/*==========================================
* Static data
*/
-pkcs11h_data_t pkcs11h_data = NULL;
+#if defined(ENABLE_PKCS11H_THREADING)
+#if !defined(WIN32)
+static struct {
+ pkcs11h_mutex_t mutex;
+ __pkcs11h_mutex_entry_t head;
+} __s_pkcs11h_mutex_list = {
+ PTHREAD_MUTEX_INITIALIZER,
+ NULL
+};
+#endif
+#endif
-/*==========================================
- * Internal utility functions
- */
+pkcs11h_data_t s_pkcs11h_data = NULL;
+unsigned int s_pkcs11h_loglevel = PKCS11H_LOG_INFO;
-static
-void
-_pkcs11h_fixupFixedString (
- IN const char * const szSource,
- OUT char * const szTarget, /* MUST BE >= nLength+1 */
- IN const size_t nLength /* FIXED STRING LENGTH */
+/*======================================================================*
+ * PUBLIC INTERFACE
+ *======================================================================*/
+
+char *
+pkcs11h_getMessage (
+ IN const int rv
) {
- char *p;
+ switch (rv) {
+ case CKR_OK: return "CKR_OK";
+ case CKR_CANCEL: return "CKR_CANCEL";
+ case CKR_HOST_MEMORY: return "CKR_HOST_MEMORY";
+ case CKR_SLOT_ID_INVALID: return "CKR_SLOT_ID_INVALID";
+ case CKR_GENERAL_ERROR: return "CKR_GENERAL_ERROR";
+ case CKR_FUNCTION_FAILED: return "CKR_FUNCTION_FAILED";
+ case CKR_ARGUMENTS_BAD: return "CKR_ARGUMENTS_BAD";
+ case CKR_NO_EVENT: return "CKR_NO_EVENT";
+ case CKR_NEED_TO_CREATE_THREADS: return "CKR_NEED_TO_CREATE_THREADS";
+ case CKR_CANT_LOCK: return "CKR_CANT_LOCK";
+ case CKR_ATTRIBUTE_READ_ONLY: return "CKR_ATTRIBUTE_READ_ONLY";
+ case CKR_ATTRIBUTE_SENSITIVE: return "CKR_ATTRIBUTE_SENSITIVE";
+ case CKR_ATTRIBUTE_TYPE_INVALID: return "CKR_ATTRIBUTE_TYPE_INVALID";
+ case CKR_ATTRIBUTE_VALUE_INVALID: return "CKR_ATTRIBUTE_VALUE_INVALID";
+ case CKR_DATA_INVALID: return "CKR_DATA_INVALID";
+ case CKR_DATA_LEN_RANGE: return "CKR_DATA_LEN_RANGE";
+ case CKR_DEVICE_ERROR: return "CKR_DEVICE_ERROR";
+ case CKR_DEVICE_MEMORY: return "CKR_DEVICE_MEMORY";
+ case CKR_DEVICE_REMOVED: return "CKR_DEVICE_REMOVED";
+ case CKR_ENCRYPTED_DATA_INVALID: return "CKR_ENCRYPTED_DATA_INVALID";
+ case CKR_ENCRYPTED_DATA_LEN_RANGE: return "CKR_ENCRYPTED_DATA_LEN_RANGE";
+ case CKR_FUNCTION_CANCELED: return "CKR_FUNCTION_CANCELED";
+ case CKR_FUNCTION_NOT_PARALLEL: return "CKR_FUNCTION_NOT_PARALLEL";
+ case CKR_FUNCTION_NOT_SUPPORTED: return "CKR_FUNCTION_NOT_SUPPORTED";
+ case CKR_KEY_HANDLE_INVALID: return "CKR_KEY_HANDLE_INVALID";
+ case CKR_KEY_SIZE_RANGE: return "CKR_KEY_SIZE_RANGE";
+ case CKR_KEY_TYPE_INCONSISTENT: return "CKR_KEY_TYPE_INCONSISTENT";
+ case CKR_KEY_NOT_NEEDED: return "CKR_KEY_NOT_NEEDED";
+ case CKR_KEY_CHANGED: return "CKR_KEY_CHANGED";
+ case CKR_KEY_NEEDED: return "CKR_KEY_NEEDED";
+ case CKR_KEY_INDIGESTIBLE: return "CKR_KEY_INDIGESTIBLE";
+ case CKR_KEY_FUNCTION_NOT_PERMITTED: return "CKR_KEY_FUNCTION_NOT_PERMITTED";
+ case CKR_KEY_NOT_WRAPPABLE: return "CKR_KEY_NOT_WRAPPABLE";
+ case CKR_KEY_UNEXTRACTABLE: return "CKR_KEY_UNEXTRACTABLE";
+ case CKR_MECHANISM_INVALID: return "CKR_MECHANISM_INVALID";
+ case CKR_MECHANISM_PARAM_INVALID: return "CKR_MECHANISM_PARAM_INVALID";
+ case CKR_OBJECT_HANDLE_INVALID: return "CKR_OBJECT_HANDLE_INVALID";
+ case CKR_OPERATION_ACTIVE: return "CKR_OPERATION_ACTIVE";
+ case CKR_OPERATION_NOT_INITIALIZED: return "CKR_OPERATION_NOT_INITIALIZED";
+ case CKR_PIN_INCORRECT: return "CKR_PIN_INCORRECT";
+ case CKR_PIN_INVALID: return "CKR_PIN_INVALID";
+ case CKR_PIN_LEN_RANGE: return "CKR_PIN_LEN_RANGE";
+ case CKR_PIN_EXPIRED: return "CKR_PIN_EXPIRED";
+ case CKR_PIN_LOCKED: return "CKR_PIN_LOCKED";
+ case CKR_SESSION_CLOSED: return "CKR_SESSION_CLOSED";
+ case CKR_SESSION_COUNT: return "CKR_SESSION_COUNT";
+ case CKR_SESSION_HANDLE_INVALID: return "CKR_SESSION_HANDLE_INVALID";
+ case CKR_SESSION_PARALLEL_NOT_SUPPORTED: return "CKR_SESSION_PARALLEL_NOT_SUPPORTED";
+ case CKR_SESSION_READ_ONLY: return "CKR_SESSION_READ_ONLY";
+ case CKR_SESSION_EXISTS: return "CKR_SESSION_EXISTS";
+ case CKR_SESSION_READ_ONLY_EXISTS: return "CKR_SESSION_READ_ONLY_EXISTS";
+ case CKR_SESSION_READ_WRITE_SO_EXISTS: return "CKR_SESSION_READ_WRITE_SO_EXISTS";
+ case CKR_SIGNATURE_INVALID: return "CKR_SIGNATURE_INVALID";
+ case CKR_SIGNATURE_LEN_RANGE: return "CKR_SIGNATURE_LEN_RANGE";
+ case CKR_TEMPLATE_INCOMPLETE: return "CKR_TEMPLATE_INCOMPLETE";
+ case CKR_TEMPLATE_INCONSISTENT: return "CKR_TEMPLATE_INCONSISTENT";
+ case CKR_TOKEN_NOT_PRESENT: return "CKR_TOKEN_NOT_PRESENT";
+ case CKR_TOKEN_NOT_RECOGNIZED: return "CKR_TOKEN_NOT_RECOGNIZED";
+ case CKR_TOKEN_WRITE_PROTECTED: return "CKR_TOKEN_WRITE_PROTECTED";
+ case CKR_UNWRAPPING_KEY_HANDLE_INVALID: return "CKR_UNWRAPPING_KEY_HANDLE_INVALID";
+ case CKR_UNWRAPPING_KEY_SIZE_RANGE: return "CKR_UNWRAPPING_KEY_SIZE_RANGE";
+ case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT: return "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT";
+ case CKR_USER_ALREADY_LOGGED_IN: return "CKR_USER_ALREADY_LOGGED_IN";
+ case CKR_USER_NOT_LOGGED_IN: return "CKR_USER_NOT_LOGGED_IN";
+ case CKR_USER_PIN_NOT_INITIALIZED: return "CKR_USER_PIN_NOT_INITIALIZED";
+ case CKR_USER_TYPE_INVALID: return "CKR_USER_TYPE_INVALID";
+ case CKR_USER_ANOTHER_ALREADY_LOGGED_IN: return "CKR_USER_ANOTHER_ALREADY_LOGGED_IN";
+ case CKR_USER_TOO_MANY_TYPES: return "CKR_USER_TOO_MANY_TYPES";
+ case CKR_WRAPPED_KEY_INVALID: return "CKR_WRAPPED_KEY_INVALID";
+ case CKR_WRAPPED_KEY_LEN_RANGE: return "CKR_WRAPPED_KEY_LEN_RANGE";
+ case CKR_WRAPPING_KEY_HANDLE_INVALID: return "CKR_WRAPPING_KEY_HANDLE_INVALID";
+ case CKR_WRAPPING_KEY_SIZE_RANGE: return "CKR_WRAPPING_KEY_SIZE_RANGE";
+ case CKR_WRAPPING_KEY_TYPE_INCONSISTENT: return "CKR_WRAPPING_KEY_TYPE_INCONSISTENT";
+ case CKR_RANDOM_SEED_NOT_SUPPORTED: return "CKR_RANDOM_SEED_NOT_SUPPORTED";
+ case CKR_RANDOM_NO_RNG: return "CKR_RANDOM_NO_RNG";
+ case CKR_DOMAIN_PARAMS_INVALID: return "CKR_DOMAIN_PARAMS_INVALID";
+ case CKR_BUFFER_TOO_SMALL: return "CKR_BUFFER_TOO_SMALL";
+ case CKR_SAVED_STATE_INVALID: return "CKR_SAVED_STATE_INVALID";
+ case CKR_INFORMATION_SENSITIVE: return "CKR_INFORMATION_SENSITIVE";
+ case CKR_STATE_UNSAVEABLE: return "CKR_STATE_UNSAVEABLE";
+ case CKR_CRYPTOKI_NOT_INITIALIZED: return "CKR_CRYPTOKI_NOT_INITIALIZED";
+ case CKR_CRYPTOKI_ALREADY_INITIALIZED: return "CKR_CRYPTOKI_ALREADY_INITIALIZED";
+ case CKR_MUTEX_BAD: return "CKR_MUTEX_BAD";
+ case CKR_MUTEX_NOT_LOCKED: return "CKR_MUTEX_NOT_LOCKED";
+ case CKR_FUNCTION_REJECTED: return "CKR_FUNCTION_REJECTED";
+ case CKR_VENDOR_DEFINED: return "CKR_VENDOR_DEFINED";
+ default: return "Unknown PKCS#11 error";
+ }
+}
+
+CK_RV
+pkcs11h_initialize () {
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_initialize entry"
+ );
+
+ pkcs11h_terminate ();
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_malloc ((void*)&s_pkcs11h_data, sizeof (struct pkcs11h_data_s));
+ }
- PKCS11ASSERT (szSource!=NULL);
- PKCS11ASSERT (szTarget!=NULL);
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_mutexInit (&s_pkcs11h_data->mutexGlobal);
+ }
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_mutexInit (&s_pkcs11h_data->mutexSession);
+ }
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_mutexInit (&s_pkcs11h_data->mutexCache);
+ }
+#if !defined(WIN32)
+ if (
+ rv == CKR_OK &&
+ pthread_atfork (
+ __pkcs11h_atfork_prepare,
+ __pkcs11h_atfork_parent,
+ __pkcs11h_atfork_child
+ )
+ ) {
+ rv = CKR_FUNCTION_FAILED;
+ }
+#endif
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&s_pkcs11h_data->mutexGlobal)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
+ if (rv == CKR_OK) {
+ s_pkcs11h_data->nMaxLoginRetries = PKCS11H_DEFAULT_MAX_LOGIN_RETRY;
+ s_pkcs11h_data->fProtectedAuthentication = TRUE;
+ s_pkcs11h_data->nPINCachePeriod = PKCS11H_DEFAULT_PIN_CACHE_PERIOD;
+ s_pkcs11h_data->fInitialized = TRUE;
+ }
+
+ if (rv == CKR_OK) {
+ pkcs11h_setLogHook (_pkcs11h_hooks_default_log, NULL);
+ pkcs11h_setTokenPromptHook (_pkcs11h_hooks_default_token_prompt, NULL);
+ pkcs11h_setPINPromptHook (_pkcs11h_hooks_default_pin_prompt, NULL);
+ }
- p = szTarget+nLength;
- memmove (szTarget, szSource, nLength);
- *p = '\0';
- p--;
- while (p >= szTarget && *p == ' ') {
- *p = '\0';
- p--;
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&s_pkcs11h_data->mutexGlobal);
+ fMutexLocked = FALSE;
}
+#endif
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_initialize return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
}
-static
-void
-_hexToBinary (
- IN const char * const szSource,
- OUT unsigned char * const target,
- IN OUT size_t * const target_size
-) {
- size_t target_max_size;
- const char *p;
- char buf[3] = {'\0', '\0', '\0'};
- int i = 0;
+CK_RV
+pkcs11h_terminate () {
- PKCS11ASSERT (szSource!=NULL);
- PKCS11ASSERT (target!=NULL);
- PKCS11ASSERT (target_size!=NULL);
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_terminate entry"
+ );
- target_max_size = *target_size;
- p = szSource;
- *target_size = 0;
+ if (s_pkcs11h_data != NULL) {
+ pkcs11h_provider_t current_provider = NULL;
- while (*p != '\0' && *target_size < target_max_size) {
- if (isxdigit (*p)) {
- buf[i%2] = *p;
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Removing providers"
+ );
- if ((i%2) == 1) {
- unsigned v;
- if (sscanf (buf, "%x", &v) != 1) {
- v = 0;
- }
- target[*target_size] = v & 0xff;
- (*target_size)++;
+ for (
+ current_provider = s_pkcs11h_data->providers;
+ current_provider != NULL;
+ current_provider = current_provider->next
+ ) {
+ pkcs11h_removeProvider (current_provider->szReferenceName);
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ _pkcs11h_mutexLock (&s_pkcs11h_data->mutexCache);
+ _pkcs11h_mutexLock (&s_pkcs11h_data->mutexSession);
+ _pkcs11h_mutexLock (&s_pkcs11h_data->mutexGlobal);
+#endif
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Releasing sessions"
+ );
+
+ while (s_pkcs11h_data->sessions != NULL) {
+ pkcs11h_session_t current = s_pkcs11h_data->sessions;
+ s_pkcs11h_data->sessions = s_pkcs11h_data->sessions->next;
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ _pkcs11h_mutexLock (&current->mutexSession);
+#endif
+
+ current->fValid = FALSE;
+
+ if (current->nReferenceCount != 0) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Warning: Found session with references"
+ );
}
- i++;
+ if (current->token_id != NULL) {
+ pkcs11h_freeTokenId (current->token_id);
+ current->token_id = NULL;
+ }
+
+#if defined(ENABLE_PKCS11H_ENUM)
+#if defined(ENABLE_PKCS11H_CERTIFICATE)
+ pkcs11h_freeCertificateIdList (current->cached_certs);
+#endif
+#endif
+
+ current->provider = NULL;
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ _pkcs11h_mutexFree (&current->mutexSession);
+#endif
+
+ _pkcs11h_free ((void *)&current);
}
- p++;
+
+#if defined(ENABLE_PKCS11H_SLOTEVENT)
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Terminating slotevent"
+ );
+
+ _pkcs11h_slotevent_terminate ();
+#endif
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Marking as uninitialized"
+ );
+
+ s_pkcs11h_data->fInitialized = FALSE;
+
+ while (s_pkcs11h_data->providers != NULL) {
+ pkcs11h_provider_t current = s_pkcs11h_data->providers;
+ s_pkcs11h_data->providers = s_pkcs11h_data->providers->next;
+
+ _pkcs11h_free ((void *)&current);
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ _pkcs11h_mutexFree (&s_pkcs11h_data->mutexCache);
+ _pkcs11h_mutexFree (&s_pkcs11h_data->mutexGlobal);
+ _pkcs11h_mutexFree (&s_pkcs11h_data->mutexSession);
+#endif
+
+ _pkcs11h_free ((void *)&s_pkcs11h_data);
}
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_terminate return"
+ );
+
+ return CKR_OK;
}
-static
void
-_isBetterCertificate_getExpiration (
- IN const unsigned char * const pCertificate,
- IN const size_t nCertificateSize,
- OUT char * const szNotBefore,
- IN const int nNotBeforeSize
+pkcs11h_setLogLevel (
+ IN const unsigned flags
) {
- /*
- * This function compare the notBefore
- * and select the most recent certificate
- * it does not deal with timezones...
- * When openssl will have ASN1_TIME compare function
- * it should be used.
- */
+ s_pkcs11h_loglevel = flags;
+}
- X509 *x509 = NULL;
+unsigned
+pkcs11h_getLogLevel () {
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
- PKCS11ASSERT (pCertificate!=NULL);
- PKCS11ASSERT (szNotBefore!=NULL);
- PKCS11ASSERT (nNotBeforeSize>0);
+ return s_pkcs11h_loglevel;
+}
- szNotBefore[0] = '\0';
+CK_RV
+pkcs11h_setLogHook (
+ IN const pkcs11h_hook_log_t hook,
+ IN void * const pData
+) {
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (hook!=NULL);
- x509 = X509_new ();
+ s_pkcs11h_data->hooks.log = hook;
+ s_pkcs11h_data->hooks.log_data = pData;
- if (x509 != NULL) {
- pkcs11_openssl_d2i_t d2i = (pkcs11_openssl_d2i_t)pCertificate;
+ return CKR_OK;
+}
- if (
- d2i_X509 (&x509, &d2i, nCertificateSize)
- ) {
- ASN1_TIME *notBefore = X509_get_notBefore (x509);
- ASN1_TIME *notAfter = X509_get_notAfter (x509);
+CK_RV
+pkcs11h_setSlotEventHook (
+ IN const pkcs11h_hook_slotevent_t hook,
+ IN void * const pData
+) {
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (hook!=NULL);
- if (
- notBefore != NULL &&
- X509_cmp_current_time (notBefore) <= 0 &&
- X509_cmp_current_time (notAfter) >= 0 &&
- notBefore->length < nNotBeforeSize - 1
- ) {
- memmove (szNotBefore, notBefore->data, notBefore->length);
- szNotBefore[notBefore->length] = '\0';
- }
- }
- }
+#if defined(ENABLE_PKCS11H_SLOTEVENT)
+ s_pkcs11h_data->hooks.slotevent = hook;
+ s_pkcs11h_data->hooks.slotevent_data = pData;
- if (x509 != NULL) {
- X509_free (x509);
- x509 = NULL;
- }
+ return _pkcs11h_slotevent_init ();
+#else
+ return CKR_FUNCTION_NOT_SUPPORTED;
+#endif
}
-static
-bool
-_isBetterCertificate (
- IN const unsigned char * const pCurrent,
- IN const size_t nCurrentSize,
- IN const unsigned char * const pNew,
- IN const size_t nNewSize
+CK_RV
+pkcs11h_setPINPromptHook (
+ IN const pkcs11h_hook_pin_prompt_t hook,
+ IN void * const pData
) {
- /*
- * This function compare the notBefore
- * and select the most recent certificate
- * it does not deal with timezones...
- * When openssl will have ASN1_TIME compare function
- * it should be used.
- */
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (hook!=NULL);
- bool fBetter = false;
+ s_pkcs11h_data->hooks.pin_prompt = hook;
+ s_pkcs11h_data->hooks.pin_prompt_data = pData;
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _isBetterCertificate entry pCurrent=%p, nCurrentSize=%u, pNew=%p, nNewSize=%u",
- pCurrent,
- nCurrentSize,
- pNew,
- nNewSize
+ return CKR_OK;
+}
+
+CK_RV
+pkcs11h_setTokenPromptHook (
+ IN const pkcs11h_hook_token_prompt_t hook,
+ IN void * const pData
+) {
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (hook!=NULL);
+
+ s_pkcs11h_data->hooks.token_prompt = hook;
+ s_pkcs11h_data->hooks.token_prompt_data = pData;
+
+ return CKR_OK;
+}
+
+CK_RV
+pkcs11h_setPINCachePeriod (
+ IN const int nPINCachePeriod
+) {
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+
+ s_pkcs11h_data->nPINCachePeriod = nPINCachePeriod;
+
+ return CKR_OK;
+}
+
+CK_RV
+pkcs11h_setMaxLoginRetries (
+ IN const int nMaxLoginRetries
+) {
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+
+ s_pkcs11h_data->nMaxLoginRetries = nMaxLoginRetries;
+
+ return CKR_OK;
+}
+
+CK_RV
+pkcs11h_setProtectedAuthentication (
+ IN const PKCS11H_BOOL fProtectedAuthentication
+) {
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+
+ s_pkcs11h_data->fProtectedAuthentication = fProtectedAuthentication;
+
+ return CKR_OK;
+}
+
+CK_RV
+pkcs11h_addProvider (
+ IN const char * const szReferenceName,
+ IN const char * const szProvider,
+ IN const PKCS11H_BOOL fProtectedAuthentication,
+ IN const unsigned maskSignMode,
+ IN const int nSlotEventMethod,
+ IN const int nSlotEventPollInterval,
+ IN const PKCS11H_BOOL fCertIsPrivate
+) {
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+#if defined(WIN32)
+ int mypid = 0;
+#else
+ pid_t mypid = getpid ();
+#endif
+ pkcs11h_provider_t provider = NULL;
+ CK_C_GetFunctionList gfl = NULL;
+ CK_INFO info;
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (szProvider!=NULL);
+ /*PKCS11H_ASSERT (szSignMode!=NULL); NOT NEEDED*/
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_addProvider entry pid=%d, szReferenceName=%s, szProvider='%s', fProtectedAuthentication=%d, maskSignMode=%08x, fCertIsPrivate=%d",
+ mypid,
+ szReferenceName,
+ szProvider,
+ fProtectedAuthentication ? 1 : 0,
+ maskSignMode,
+ fCertIsPrivate ? 1 : 0
);
- /*
- * First certificae
- * always select
- */
- if (nCurrentSize == 0) {
- fBetter = true;
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Adding provider '%s'-'%s'",
+ szReferenceName,
+ szProvider
+ );
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&s_pkcs11h_data->mutexGlobal)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
}
- else {
- char szNotBeforeCurrent[1024], szNotBeforeNew[1024];
+#endif
- _isBetterCertificate_getExpiration (
- pCurrent,
- nCurrentSize,
- szNotBeforeCurrent,
- sizeof (szNotBeforeCurrent)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_malloc ((void *)&provider, sizeof (struct pkcs11h_provider_s))) == CKR_OK
+ ) {
+ strncpy (
+ provider->szReferenceName,
+ szReferenceName,
+ sizeof (provider->szReferenceName)-1
);
- _isBetterCertificate_getExpiration (
- pNew,
- nNewSize,
- szNotBeforeNew,
- sizeof (szNotBeforeNew)
+ provider->szReferenceName[sizeof (provider->szReferenceName)-1] = '\x0';
+ strncpy (
+ provider->manufacturerID,
+ (
+ strlen (szProvider) < sizeof (provider->manufacturerID) ?
+ szProvider :
+ szProvider+strlen (szProvider)-sizeof (provider->manufacturerID)+1
+ ),
+ sizeof (provider->manufacturerID)-1
);
+ provider->manufacturerID[sizeof (provider->manufacturerID)-1] = '\x0';
+ provider->fProtectedAuthentication = fProtectedAuthentication;
+ provider->maskSignMode = maskSignMode;
+ provider->nSlotEventMethod = nSlotEventMethod;
+ provider->nSlotEventPollInterval = nSlotEventPollInterval;
+ provider->fCertIsPrivate = fCertIsPrivate;
+ }
+
+ if (rv == CKR_OK) {
+#if defined(WIN32)
+ provider->hLibrary = LoadLibraryA (szProvider);
+#else
+ provider->hLibrary = dlopen (szProvider, RTLD_NOW);
+#endif
+ if (provider->hLibrary == NULL) {
+ rv = CKR_FUNCTION_FAILED;
+ }
+ }
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _isBetterCertificate szNotBeforeCurrent=%s, szNotBeforeNew=%s",
- szNotBeforeCurrent,
- szNotBeforeNew
+ if (rv == CKR_OK) {
+#if defined(WIN32)
+ gfl = (CK_C_GetFunctionList)GetProcAddress (
+ provider->hLibrary,
+ "C_GetFunctionList"
+ );
+#else
+ /*
+ * Make compiler happy!
+ */
+ void *p = dlsym (
+ provider->hLibrary,
+ "C_GetFunctionList"
+ );
+ memmove (
+ &gfl,
+ &p,
+ sizeof (void *)
);
+#endif
+ if (gfl == NULL) {
+ rv = CKR_FUNCTION_FAILED;
+ }
+ }
- fBetter = strcmp (szNotBeforeCurrent, szNotBeforeNew) < 0;
+ if (rv == CKR_OK) {
+ rv = gfl (&provider->f);
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _isBetterCertificate return fBetter=%d",
- fBetter ? 1 : 0
- );
+ if (rv == CKR_OK) {
+ if ((rv = provider->f->C_Initialize (NULL)) != CKR_OK) {
+ if (rv == CKR_CRYPTOKI_ALREADY_INITIALIZED) {
+ rv = CKR_OK;
+ }
+ }
+ else {
+ provider->fShouldFinalize = TRUE;
+ }
+ }
+
+ if (
+ rv == CKR_OK &&
+ (rv = provider->f->C_GetInfo (&info)) == CKR_OK
+ ) {
+ _pkcs11h_fixupFixedString (
+ provider->manufacturerID,
+ (char *)info.manufacturerID,
+ sizeof (info.manufacturerID)
+ );
+ }
+
+ if (rv == CKR_OK) {
+ provider->fEnabled = TRUE;
+ }
+
+ if (provider != NULL) {
+ if (s_pkcs11h_data->providers == NULL) {
+ s_pkcs11h_data->providers = provider;
+ }
+ else {
+ pkcs11h_provider_t last = NULL;
- return fBetter;
-}
+ for (
+ last = s_pkcs11h_data->providers;
+ last->next != NULL;
+ last = last->next
+ );
+ last->next = provider;
+ }
+ }
-/*========================================
- * Low level PKCS#11 functions
- */
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&s_pkcs11h_data->mutexGlobal);
+ fMutexLocked = FALSE;
+ }
+#endif
+
+#if defined(ENABLE_PKCS11H_SLOTEVENT)
+ _pkcs11h_slotevent_notify ();
+#endif
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Provider '%s' added rv=%ld-'%s'",
+ szReferenceName,
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_addProvider return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
-static
CK_RV
-_pkcs11h_getSlotById (
- IN const char * const szSlot,
- OUT pkcs11h_provider_t * const provider,
- OUT CK_SLOT_ID * const slot
+pkcs11h_removeProvider (
+ IN const char * const szReferenceName
) {
- int provider_number;
- int slot_number;
+#if defined(ENABLE_PKCS11H_THREADING)
+ pkcs11h_session_t current_session = NULL;
+#endif
+ pkcs11h_provider_t provider = NULL;
CK_RV rv = CKR_OK;
- PKCS11ASSERT (szSlot!=NULL);
- PKCS11ASSERT (provider!=NULL);
- PKCS11ASSERT (slot!=NULL);
+ PKCS11H_ASSERT (szReferenceName!=NULL);
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_getSlotById entry szSlot=%s, provider=%p, slot=%p",
- szSlot,
- (void *)provider,
- (void *)slot
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_removeProvider entry szReferenceName='%s'",
+ szReferenceName
+ );
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Removing provider '%s'",
+ szReferenceName
);
+#if defined(ENABLE_PKCS11H_THREADING)
+ _pkcs11h_mutexLock (&s_pkcs11h_data->mutexCache);
+ _pkcs11h_mutexLock (&s_pkcs11h_data->mutexSession);
+ _pkcs11h_mutexLock (&s_pkcs11h_data->mutexGlobal);
+
+ for (
+ current_session = s_pkcs11h_data->sessions;
+ current_session != NULL;
+ current_session = current_session->next
+ ) {
+ _pkcs11h_mutexLock (&current_session->mutexSession);
+ }
+#endif
+
+ provider = s_pkcs11h_data->providers;
+ while (
+ rv == CKR_OK &&
+ provider != NULL &&
+ strcmp (szReferenceName, provider->szReferenceName)
+ ) {
+ provider = provider->next;
+ }
+
+ if (rv == CKR_OK && provider == NULL) {
+ rv = CKR_OBJECT_HANDLE_INVALID;
+ }
+
if (rv == CKR_OK) {
- if (strchr (szSlot, ':') == NULL) {
- provider_number = 0;
- slot_number = atoi (szSlot);
+ provider->fEnabled = FALSE;
+ provider->szReferenceName[0] = '\0';
+
+ if (provider->fShouldFinalize) {
+ provider->f->C_Finalize (NULL);
+ provider->fShouldFinalize = FALSE;
}
- else {
- if (sscanf (szSlot, "%d:%d", &provider_number, &slot_number) != 2) {
- rv = CKR_FUNCTION_FAILED;
- }
+
+#if defined(ENABLE_PKCS11H_SLOTEVENT)
+ _pkcs11h_slotevent_notify ();
+
+ /*
+ * Wait until manager join this thread
+ * this happens saldom so I can poll
+ */
+ while (provider->threadSlotEvent != PKCS11H_THREAD_NULL) {
+ _pkcs11h_sleep (500);
}
+#endif
+
+ if (provider->f != NULL) {
+ provider->f = NULL;
+ }
+
+ if (provider->hLibrary != NULL) {
+#if defined(WIN32)
+ FreeLibrary (provider->hLibrary);
+#else
+ dlclose (provider->hLibrary);
+#endif
+ provider->hLibrary = NULL;
+ }
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ for (
+ current_session = s_pkcs11h_data->sessions;
+ current_session != NULL;
+ current_session = current_session->next
+ ) {
+ _pkcs11h_mutexRelease (&current_session->mutexSession);
}
+
+ _pkcs11h_mutexRelease (&s_pkcs11h_data->mutexCache);
+ _pkcs11h_mutexRelease (&s_pkcs11h_data->mutexSession);
+ _pkcs11h_mutexRelease (&s_pkcs11h_data->mutexGlobal);
+#endif
- if (rv == CKR_OK) {
- pkcs11h_provider_t current_provider;
- int i;
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_removeProvider return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+CK_RV
+pkcs11h_forkFixup () {
+#if defined(WIN32)
+ return CKR_OK;
+#else
+#if defined(ENABLE_PKCS11H_THREADING)
+ return CKR_OK;
+#else
+ return _pkcs11h_forkFixup ();
+#endif
+#endif
+}
+
+CK_RV
+pkcs11h_plugAndPlay () {
+#if defined(WIN32)
+ int mypid = 0;
+#else
+ pid_t mypid = getpid ();
+#endif
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_forkFixup entry pid=%d",
+ mypid
+ );
+
+ if (s_pkcs11h_data != NULL && s_pkcs11h_data->fInitialized) {
+ pkcs11h_provider_t current;
+#if defined(ENABLE_PKCS11H_SLOTEVENT)
+ PKCS11H_BOOL fSlotEventActive = FALSE;
+#endif
+#if defined(ENABLE_PKCS11H_THREADING)
+ _pkcs11h_mutexLock (&s_pkcs11h_data->mutexGlobal);
+#endif
for (
- i=0, current_provider=pkcs11h_data->providers;
- (
- i < provider_number &&
- current_provider != NULL &&
- rv == CKR_OK
- );
- i++, current_provider = current_provider->next
+ current = s_pkcs11h_data->providers;
+ current != NULL;
+ current = current->next
+ ) {
+ if (current->fEnabled) {
+ current->f->C_Finalize (NULL);
+ }
+ }
+
+#if defined(ENABLE_PKCS11H_SLOTEVENT)
+ if (s_pkcs11h_data->fSlotEventInitialized) {
+ fSlotEventActive = TRUE;
+ _pkcs11h_slotevent_terminate ();
+ }
+#endif
+
+ for (
+ current = s_pkcs11h_data->providers;
+ current != NULL;
+ current = current->next
+ ) {
+ if (current->fEnabled) {
+ current->f->C_Initialize (NULL);
+ }
+ }
+
+#if defined(ENABLE_PKCS11H_SLOTEVENT)
+ if (fSlotEventActive) {
+ _pkcs11h_slotevent_init ();
+ }
+#endif
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ _pkcs11h_mutexRelease (&s_pkcs11h_data->mutexGlobal);
+#endif
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_forkFixup return"
+ );
+
+ return CKR_OK;
+}
+
+CK_RV
+pkcs11h_freeTokenId (
+ IN pkcs11h_token_id_t token_id
+) {
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (token_id!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_freeTokenId entry certificate_id=%p",
+ (void *)token_id
+ );
+
+ _pkcs11h_free ((void *)&token_id);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_freeTokenId return"
+ );
+
+ return CKR_OK;
+}
+
+CK_RV
+pkcs11h_duplicateTokenId (
+ OUT pkcs11h_token_id_t * const to,
+ IN const pkcs11h_token_id_t from
+) {
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (to!=NULL);
+ PKCS11H_ASSERT (from!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_duplicateTokenId entry to=%p form=%p",
+ (void *)to,
+ (void *)from
+ );
+
+ *to = NULL;
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_dupmem (
+ (void*)to,
+ NULL,
+ from,
+ sizeof (struct pkcs11h_token_id_s)
);
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_duplicateTokenId return rv=%ld-'%s', *to=%p",
+ rv,
+ pkcs11h_getMessage (rv),
+ (void *)*to
+ );
+ return rv;
+}
+
+PKCS11H_BOOL
+pkcs11h_sameTokenId (
+ IN const pkcs11h_token_id_t a,
+ IN const pkcs11h_token_id_t b
+) {
+ PKCS11H_ASSERT (a!=NULL);
+ PKCS11H_ASSERT (b!=NULL);
+
+ return (
+ !strcmp (a->manufacturerID, b->manufacturerID) &&
+ !strcmp (a->model, b->model) &&
+ !strcmp (a->serialNumber, b->serialNumber)
+ );
+}
+
+/*======================================================================*
+ * MEMORY INTERFACE
+ *======================================================================*/
+
+static
+CK_RV
+_pkcs11h_malloc (
+ OUT const void ** const p,
+ IN const size_t s
+) {
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (p!=NULL);
+ PKCS11H_ASSERT (s!=0);
+
+ *p = NULL;
+
+ if (s > 0) {
if (
- current_provider == NULL ||
- (
- current_provider != NULL &&
- !current_provider->fEnabled
- )
+ (*p = (void *)malloc (s)) == NULL
) {
- rv = CKR_SLOT_ID_INVALID;
+ rv = CKR_HOST_MEMORY;
}
else {
- *provider = current_provider;
- *slot = slot_number;
+ memset ((void *)*p, 0, s);
}
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_getSlotById return rv=%ld-'%s'",
- rv,
- pkcs11h_getMessage (rv)
- );
-
return rv;
}
static
CK_RV
-_pkcs11h_getSlotByName (
- IN const char * const szName,
- OUT pkcs11h_provider_t * const provider,
- OUT CK_SLOT_ID * const slot
+_pkcs11h_free (
+ IN const void ** const p
+) {
+ PKCS11H_ASSERT (p!=NULL);
+
+ free ((void *)*p);
+ *p = NULL;
+
+ return CKR_OK;
+}
+
+static
+CK_RV
+_pkcs11h_dupmem (
+ OUT const void ** const dest,
+ OUT size_t * const p_dest_size,
+ IN const void * const src,
+ IN const size_t mem_size
) {
CK_RV rv = CKR_OK;
- pkcs11h_provider_t current_provider;
- bool fFound = false;
+ PKCS11H_ASSERT (dest!=NULL);
+ /*PKCS11H_ASSERT (dest_size!=NULL); NOT NEEDED*/
+ PKCS11H_ASSERT (!(mem_size!=0&&src==NULL));
- PKCS11ASSERT (szName!=NULL);
- PKCS11ASSERT (provider!=NULL);
- PKCS11ASSERT (slot!=NULL);
+ *dest = NULL;
+ if (p_dest_size != NULL) {
+ *p_dest_size = 0;
+ }
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_getSlotByName entry szName=%s, provider=%p, slot=%p",
- szName,
- (void *)provider,
- (void *)slot
- );
+ if (src != NULL) {
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_malloc (dest, mem_size)) == CKR_OK
+ ) {
+ if (p_dest_size != NULL) {
+ *p_dest_size = mem_size;
+ }
+ memmove ((void*)*dest, src, mem_size);
+ }
+ }
- for (
- current_provider = pkcs11h_data->providers;
- (
- current_provider != NULL &&
- !fFound
- );
- current_provider = current_provider->next
+ return rv;
+}
+
+#if defined(ENABLE_PKCS11H_THREADING)
+/*======================================================================*
+ * THREADING INTERFACE
+ *======================================================================*/
+
+static
+void
+_pkcs11h_sleep (
+ IN const unsigned milli
+) {
+#if defined(WIN32)
+ Sleep (milli);
+#else
+ usleep (milli*1000);
+#endif
+}
+
+static
+CK_RV
+_pkcs11h_mutexInit (
+ OUT pkcs11h_mutex_t * const mutex
+) {
+ CK_RV rv = CKR_OK;
+#if defined(WIN32)
+ if (
+ rv == CKR_OK &&
+ (*mutex = CreateMutex (NULL, FALSE, NULL)) == NULL
) {
- CK_SLOT_ID slots[1024];
- CK_ULONG slotnum;
+ rv = CKR_FUNCTION_FAILED;
+ }
+#else
+ {
+ __pkcs11h_mutex_entry_t entry = NULL;
+ PKCS11H_BOOL fMutexLocked = FALSE;
- if (!current_provider->fEnabled) {
- continue;
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&__s_pkcs11h_mutex_list.mutex)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_malloc (
+ (void *)&entry,
+ sizeof (struct __pkcs11h_mutex_entry_s)
+ );
}
- slotnum = sizeof (slots) / sizeof (CK_SLOT_ID);
if (
- (rv = current_provider->f->C_GetSlotList (
- TRUE,
- slots,
- &slotnum
- )) == CKR_OK
+ rv == CKR_OK &&
+ pthread_mutex_init (mutex, NULL)
) {
- CK_SLOT_ID s;
+ rv = CKR_FUNCTION_FAILED;
+ }
- for (s=0;!fFound && s<slotnum;s++) {
- CK_SLOT_INFO info;
+ if (rv == CKR_OK) {
+ entry->p_mutex = mutex;
+ entry->next = __s_pkcs11h_mutex_list.head;
+ __s_pkcs11h_mutex_list.head = entry;
+ entry = NULL;
+ }
- if (
- (rv = current_provider->f->C_GetSlotInfo (
- slots[s],
- &info
- )) == CKR_OK
- ) {
- char szCurrentName[sizeof (info.slotDescription)+1];
-
- _pkcs11h_fixupFixedString (
- (char *)info.slotDescription,
- szCurrentName,
- sizeof (info.slotDescription)
- );
+ if (entry != NULL) {
+ _pkcs11h_free ((void *)&entry);
+ }
- if (!strcmp (szCurrentName, szName)) {
- fFound = true;
- *provider = current_provider;
- *slot = slots[s];
- }
- }
- }
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&__s_pkcs11h_mutex_list.mutex);
+ fMutexLocked = FALSE;
}
}
+#endif
+ return rv;
+}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_getSlotByName return fFound=%d-'%s'",
- fFound ? 1 : 0,
- pkcs11h_getMessage (rv)
- );
+static
+CK_RV
+_pkcs11h_mutexLock (
+ IN OUT pkcs11h_mutex_t *const mutex
+) {
+ CK_RV rv = CKR_OK;
+#if defined(WIN32)
+ if (
+ rv == CKR_OK &&
+ WaitForSingleObject (*mutex, INFINITE) == WAIT_FAILED
+ ) {
+ rv = CKR_FUNCTION_FAILED;
+ }
+#else
+ if (
+ rv == CKR_OK &&
+ pthread_mutex_lock (mutex)
+ ) {
+ rv = CKR_FUNCTION_FAILED;
+ }
+#endif
+ return rv;
+}
- return fFound ? CKR_OK : CKR_SLOT_ID_INVALID;
+static
+CK_RV
+_pkcs11h_mutexRelease (
+ IN OUT pkcs11h_mutex_t *const mutex
+) {
+ CK_RV rv = CKR_OK;
+#if defined(WIN32)
+ if (
+ rv == CKR_OK &&
+ !ReleaseMutex (*mutex)
+ ) {
+ rv = CKR_FUNCTION_FAILED;
+ }
+#else
+ if (
+ rv == CKR_OK &&
+ pthread_mutex_unlock (mutex)
+ ) {
+ rv = CKR_FUNCTION_FAILED;
+ }
+#endif
+ return rv;
}
static
CK_RV
-_pkcs11h_getSlotByLabel (
- IN const char * const szLabel,
- OUT pkcs11h_provider_t * const provider,
- OUT CK_SLOT_ID * const slot
+_pkcs11h_mutexFree (
+ IN OUT pkcs11h_mutex_t *const mutex
) {
- CK_RV rv;
+#if defined(WIN32)
+ if (*mutex != NULL) {
+ CloseHandle (*mutex);
+ *mutex = NULL;
+ }
+#else
+ {
+ __pkcs11h_mutex_entry_t last = NULL;
+ __pkcs11h_mutex_entry_t entry = NULL;
+ PKCS11H_BOOL fMutexLocked = FALSE;
- pkcs11h_provider_t current_provider;
- bool fFound = false;
+ if (_pkcs11h_mutexLock (&__s_pkcs11h_mutex_list.mutex) == CKR_OK) {
+ fMutexLocked = TRUE;
+ }
- PKCS11ASSERT (szLabel!=NULL);
- PKCS11ASSERT (provider!=NULL);
- PKCS11ASSERT (slot!=NULL);
+ entry = __s_pkcs11h_mutex_list.head;
+ while (
+ entry != NULL &&
+ entry->p_mutex != mutex
+ ) {
+ last = entry;
+ entry = entry->next;
+ }
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_getSlotByLabel entry szLabel=%s, provider=%p, slot=%p",
- szLabel,
- (void *)provider,
- (void *)slot
- );
+ if (entry != NULL) {
+ if (last == NULL) {
+ __s_pkcs11h_mutex_list.head = entry->next;
+ }
+ else {
+ last->next = entry->next;
+ }
+ _pkcs11h_free ((void *)&entry);
+ }
+
+ pthread_mutex_destroy (mutex);
+
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&__s_pkcs11h_mutex_list.mutex);
+ fMutexLocked = FALSE;
+ }
+ }
+#endif
+ return CKR_OK;
+}
+
+#if !defined(WIN32)
+/*
+ * This function is required in order
+ * to lock all mutexes before fork is called,
+ * and to avoid dedlocks.
+ * The loop is required because there is no
+ * way to lock all mutex in one system call...
+ */
+static
+void
+__pkcs1h_mutexLockAll () {
+ __pkcs11h_mutex_entry_t entry = NULL;
+ PKCS11H_BOOL fMutexLocked = FALSE;
+ PKCS11H_BOOL fAllLocked = FALSE;
+
+ if (_pkcs11h_mutexLock (&__s_pkcs11h_mutex_list.mutex) == CKR_OK) {
+ fMutexLocked = TRUE;
+ }
for (
- current_provider = pkcs11h_data->providers;
+ entry = __s_pkcs11h_mutex_list.head;
+ entry != NULL;
+ entry = entry->next
+ ) {
+ entry->fLocked = FALSE;
+ }
+
+ while (!fAllLocked) {
+ PKCS11H_BOOL fOK = TRUE;
+
+ for (
+ entry = __s_pkcs11h_mutex_list.head;
+ entry != NULL && fOK;
+ entry = entry->next
+ ) {
+ if (!pthread_mutex_trylock (entry->p_mutex)) {
+ entry->fLocked = TRUE;
+ }
+ else {
+ fOK = FALSE;
+ }
+ }
+
+ if (!fOK) {
+ for (
+ entry = __s_pkcs11h_mutex_list.head;
+ entry != NULL;
+ entry = entry->next
+ ) {
+ if (entry->fLocked == TRUE) {
+ pthread_mutex_unlock (entry->p_mutex);
+ entry->fLocked = FALSE;
+ }
+ }
+
+ _pkcs11h_mutexRelease (&__s_pkcs11h_mutex_list.mutex);
+ _pkcs11h_sleep (1000);
+ _pkcs11h_mutexLock (&__s_pkcs11h_mutex_list.mutex);
+ }
+ else {
+ fAllLocked = TRUE;
+ }
+ }
+
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&__s_pkcs11h_mutex_list.mutex);
+ fMutexLocked = FALSE;
+ }
+}
+
+static
+void
+__pkcs1h_mutexReleaseAll () {
+ __pkcs11h_mutex_entry_t entry = NULL;
+ PKCS11H_BOOL fMutexLocked = FALSE;
+
+ if (_pkcs11h_mutexLock (&__s_pkcs11h_mutex_list.mutex) == CKR_OK) {
+ fMutexLocked = TRUE;
+ }
+
+ for (
+ entry = __s_pkcs11h_mutex_list.head;
+ entry != NULL;
+ entry = entry->next
+ ) {
+ pthread_mutex_unlock (entry->p_mutex);
+ entry->fLocked = FALSE;
+ }
+
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&__s_pkcs11h_mutex_list.mutex);
+ fMutexLocked = FALSE;
+ }
+}
+#endif
+
+CK_RV
+_pkcs11h_condSignal (
+ IN OUT pkcs11h_cond_t *const cond
+) {
+ CK_RV rv = CKR_OK;
+#if defined(WIN32)
+ if (
+ rv == CKR_OK &&
+ !SetEvent (*cond)
+ ) {
+ rv = CKR_FUNCTION_FAILED;
+ }
+#else
+ if (
+ rv == CKR_OK &&
(
- current_provider != NULL &&
- !fFound
- );
- current_provider = current_provider->next
+ pthread_mutex_lock (&cond->mut) ||
+ pthread_cond_signal (&cond->cond) ||
+ pthread_mutex_unlock (&cond->mut)
+ )
) {
- CK_SLOT_ID slots[1024];
- CK_ULONG slotnum;
+ rv = CKR_FUNCTION_FAILED;
+ }
+#endif
- if (!current_provider->fEnabled) {
- continue;
+ return rv;
+}
+
+static
+CK_RV
+_pkcs11h_condInit (
+ OUT pkcs11h_cond_t * const cond
+) {
+ CK_RV rv = CKR_OK;
+#if defined(WIN32)
+ if (
+ rv == CKR_OK &&
+ (*cond = CreateEvent (NULL, FALSE, FALSE, NULL)) == NULL
+ ) {
+ rv = CKR_FUNCTION_FAILED;
+ }
+#else
+ if (
+ rv == CKR_OK &&
+ (
+ pthread_mutex_init (&cond->mut, NULL) ||
+ pthread_cond_init (&cond->cond, NULL) ||
+ pthread_mutex_lock (&cond->mut)
+ )
+ ) {
+ rv = CKR_FUNCTION_FAILED;
+ }
+#endif
+ return rv;
+}
+
+static
+CK_RV
+_pkcs11h_condWait (
+ IN OUT pkcs11h_cond_t *const cond,
+ IN const unsigned milli
+) {
+ CK_RV rv = CKR_OK;
+
+#if defined(WIN32)
+ DWORD dwMilli;
+
+ if (milli == PKCS11H_COND_INFINITE) {
+ dwMilli = INFINITE;
+ }
+ else {
+ dwMilli = milli;
+ }
+
+ if (
+ rv == CKR_OK &&
+ WaitForSingleObject (*cond, dwMilli) == WAIT_FAILED
+ ) {
+ rv = CKR_FUNCTION_FAILED;
+ }
+#else
+ if (milli == PKCS11H_COND_INFINITE) {
+ if (
+ rv == CKR_OK &&
+ pthread_cond_wait (&cond->cond, &cond->mut)
+ ) {
+ rv = CKR_FUNCTION_FAILED;
}
+ }
+ else {
+ struct timeval now;
+ struct timespec timeout;
- slotnum = sizeof (slots) / sizeof (CK_SLOT_ID);
if (
- (rv = current_provider->f->C_GetSlotList (
- TRUE,
- slots,
- &slotnum
- )) == CKR_OK
+ rv == CKR_OK &&
+ gettimeofday (&now, NULL)
) {
- CK_SLOT_ID s;
+ rv = CKR_FUNCTION_FAILED;
+ }
+
+ if (rv == CKR_OK) {
+ timeout.tv_sec = now.tv_sec + milli/1000;
+ timeout.tv_nsec = now.tv_usec*1000 + milli%1000;
+ }
+
+ if (
+ rv == CKR_OK &&
+ pthread_cond_timedwait (&cond->cond, &cond->mut, &timeout)
+ ) {
+ rv = CKR_FUNCTION_FAILED;
+ }
+ }
+#endif
+ return rv;
+}
- for (s=0;!fFound && s<slotnum;s++) {
- CK_TOKEN_INFO info;
+static
+CK_RV
+_pkcs11h_condFree (
+ IN OUT pkcs11h_cond_t *const cond
+) {
+#if defined(WIN32)
+ CloseHandle (*cond);
+ *cond = NULL;
+#else
+ pthread_mutex_unlock (&cond->mut);
+#endif
+ return CKR_OK;
+}
- if (
- (rv = current_provider->f->C_GetTokenInfo (
- slots[s],
- &info
- )) == CKR_OK
- ) {
- char szCurrentLabel[sizeof (info.label)+1];
-
- _pkcs11h_fixupFixedString (
- (char *)info.label,
- szCurrentLabel,
- sizeof (info.label)
- );
+#if defined(WIN32)
+static
+unsigned
+__stdcall
+__pkcs11h_thread_start (void *p) {
+ __pkcs11h_thread_data_t *_data = (__pkcs11h_thread_data_t *)p;
+ unsigned ret;
- if (!strcmp (szCurrentLabel, szLabel)) {
- fFound = true;
- *provider = current_provider;
- *slot = slots[s];
- }
- }
- }
+ ret = (unsigned)_data->start (_data->data);
+
+ _pkcs11h_free ((void *)&_data);
+
+ return ret;
+}
+#else
+static
+void *
+__pkcs11h_thread_start (void *p) {
+ __pkcs11h_thread_data_t *_data = (__pkcs11h_thread_data_t *)p;
+ void *ret;
+ int i;
+
+ /*
+ * Ignore any signal in
+ * this thread
+ */
+ for (i=1;i<16;i++) {
+ signal (i, SIG_IGN);
+ }
+
+ ret = _data->start (_data->data);
+
+ _pkcs11h_free ((void *)&_data);
+
+ return ret;
+}
+#endif
+
+static
+CK_RV
+_pkcs11h_threadStart (
+ OUT pkcs11h_thread_t * const thread,
+ IN pkcs11h_thread_start_t const start,
+ IN void * data
+) {
+ __pkcs11h_thread_data_t *_data = NULL;
+ CK_RV rv = CKR_OK;
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_malloc (
+ (void *)&_data,
+ sizeof (__pkcs11h_thread_data_t)
+ );
+ }
+
+ if (rv == CKR_OK) {
+ _data->start = start;
+ _data->data = data;
+ }
+
+#if defined(WIN32)
+ {
+ unsigned tmp;
+
+ if (
+ rv == CKR_OK &&
+ (*thread = (HANDLE)_beginthreadex (
+ NULL,
+ 0,
+ __pkcs11h_thread_start,
+ _data,
+ 0,
+ &tmp
+ )) == NULL
+ ) {
+ rv = CKR_FUNCTION_FAILED;
}
}
+#else
+ if (
+ rv == CKR_OK &&
+ pthread_create (thread, NULL, __pkcs11h_thread_start, _data)
+ ) {
+ rv = CKR_FUNCTION_FAILED;
+ }
+#endif
+ return rv;
+}
+
+static
+CK_RV
+_pkcs11h_threadJoin (
+ IN pkcs11h_thread_t * const thread
+) {
+#if defined(WIN32)
+ WaitForSingleObject (*thread, INFINITE);
+ CloseHandle (*thread);
+ *thread = NULL;
+#else
+ pthread_join (*thread, NULL);
+ *thread = 0l;
+#endif
+ return CKR_OK;
+}
+
+#endif /* ENABLE_PKCS11H_THREADING */
+
+/*======================================================================*
+ * COMMON INTERNAL INTERFACE
+ *======================================================================*/
+
+static
+void
+_pkcs11h_fixupFixedString (
+ OUT char * const szTarget, /* MUST BE >= nLength+1 */
+ IN const char * const szSource,
+ IN const size_t nLength /* FIXED STRING LENGTH */
+) {
+ char *p;
+
+ PKCS11H_ASSERT (szSource!=NULL);
+ PKCS11H_ASSERT (szTarget!=NULL);
+
+ p = szTarget+nLength;
+ memmove (szTarget, szSource, nLength);
+ *p = '\0';
+ p--;
+ while (p >= szTarget && *p == ' ') {
+ *p = '\0';
+ p--;
+ }
+}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_getSlotByLabel return fFound=%d",
- fFound ? 1 : 0
- );
+static
+void
+_pkcs11h_log (
+ IN const unsigned flags,
+ IN const char * const szFormat,
+ IN ...
+) {
+ va_list args;
- return fFound ? CKR_OK : CKR_SLOT_ID_INVALID;
+ PKCS11H_ASSERT (szFormat!=NULL);
+
+ va_start (args, szFormat);
+
+ if (
+ s_pkcs11h_data != NULL &&
+ s_pkcs11h_data->fInitialized
+ ) {
+ if (PKCS11H_MSG_LEVEL_TEST (flags)) {
+ if (s_pkcs11h_data->hooks.log == NULL) {
+ _pkcs11h_hooks_default_log (
+ NULL,
+ flags,
+ szFormat,
+ args
+ );
+ }
+ else {
+ s_pkcs11h_data->hooks.log (
+ s_pkcs11h_data->hooks.log_data,
+ flags,
+ szFormat,
+ args
+ );
+ }
+ }
+ }
+
+ va_end (args);
}
static
CK_RV
-_pkcs11h_getSlot (
- IN const char * const szSlotType,
- IN const char * const szSlot,
- OUT pkcs11h_provider_t * const provider,
- OUT CK_SLOT_ID * const slot
+_pkcs11h_getSlotList (
+ IN const pkcs11h_provider_t provider,
+ IN const CK_BBOOL tokenPresent,
+ OUT CK_SLOT_ID_PTR * const pSlotList,
+ OUT CK_ULONG_PTR pulCount
) {
+ CK_SLOT_ID_PTR _slots = NULL;
+ CK_ULONG _slotnum = 0;
CK_RV rv = CKR_OK;
- PKCS11ASSERT (szSlotType!=NULL);
- PKCS11ASSERT (szSlot!=NULL);
- PKCS11ASSERT (provider!=NULL);
- PKCS11ASSERT (slot!=NULL);
+ PKCS11H_ASSERT (provider!=NULL);
+ PKCS11H_ASSERT (pSlotList!=NULL);
+ PKCS11H_ASSERT (pulCount!=NULL);
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_getSlot entry szSlotType=%s, szSlot=%s, provider=%p, slot=%p",
- szSlotType,
- szSlot,
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_getSlotList entry provider=%p, tokenPresent=%d, pSlotList=%p, pulCount=%p",
(void *)provider,
- (void *)slot
+ tokenPresent,
+ (void *)pSlotList,
+ (void *)pulCount
);
- if (!strcmp (szSlotType, "id")) {
- rv = _pkcs11h_getSlotById (
- szSlot,
- provider,
- slot
+ *pSlotList = NULL;
+ *pulCount = 0;
+
+ if (rv == CKR_OK) {
+ rv = provider->f->C_GetSlotList (
+ tokenPresent,
+ NULL_PTR,
+ &_slotnum
);
}
- else if (!strcmp (szSlotType, "name")) {
- rv = _pkcs11h_getSlotByName (
- szSlot,
- provider,
- slot
+
+ if (rv == CKR_OK && _slotnum > 0) {
+ rv = _pkcs11h_malloc ((void *)&_slots, _slotnum * sizeof (CK_SLOT_ID));
+ }
+
+ if (rv == CKR_OK && _slotnum > 0) {
+ rv = provider->f->C_GetSlotList (
+ tokenPresent,
+ _slots,
+ &_slotnum
);
}
- else if (!strcmp (szSlotType, "label")) {
- rv = _pkcs11h_getSlotByLabel (
- szSlot,
- provider,
- slot
+
+ if (rv == CKR_OK) {
+ *pSlotList = _slots;
+ _slots = NULL;
+ *pulCount = _slotnum;
+ }
+
+ if (_slots != NULL) {
+ _pkcs11h_free ((void *)&_slots);
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_getSlotList return rv=%ld-'%s' *pulCount=%ld",
+ rv,
+ pkcs11h_getMessage (rv),
+ *pulCount
+ );
+
+ return rv;
+}
+
+static
+CK_RV
+_pkcs11h_getObjectAttributes (
+ IN const pkcs11h_session_t session,
+ IN const CK_OBJECT_HANDLE object,
+ IN OUT const CK_ATTRIBUTE_PTR attrs,
+ IN const unsigned count
+) {
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (attrs!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_getObjectAttributes entry session=%p, object=%ld, attrs=%p, count=%d",
+ (void *)session,
+ object,
+ (void *)attrs,
+ count
+ );
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&session->mutexSession)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
+ if (
+ rv == CKR_OK &&
+ (rv = session->provider->f->C_GetAttributeValue (
+ session->hSession,
+ object,
+ attrs,
+ count
+ )) == CKR_OK
+ ) {
+ unsigned i;
+ for (i=0;rv == CKR_OK && i<count;i++) {
+ if (attrs[i].ulValueLen == (CK_ULONG)-1) {
+ rv = CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ else {
+ rv = _pkcs11h_malloc (
+ (void *)&attrs[i].pValue,
+ attrs[i].ulValueLen
+ );
+ }
+ }
+ }
+
+ if (rv == CKR_OK) {
+ rv = session->provider->f->C_GetAttributeValue (
+ session->hSession,
+ object,
+ attrs,
+ count
);
}
- else {
- rv = CKR_ARGUMENTS_BAD;
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&session->mutexSession);
+ fMutexLocked = FALSE;
}
+#endif
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_getSlot return rv=%ld-'%s'",
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_getObjectAttributes return rv=%ld-'%s'",
rv,
pkcs11h_getMessage (rv)
);
@@ -747,177 +2452,424 @@ _pkcs11h_getSlot (
static
CK_RV
-_pkcs11h_getSession (
- IN const char * const szSlotType,
- IN const char * const szSlot,
- IN const bool fProtectedAuthentication,
- IN const int nPINCachePeriod,
- OUT pkcs11h_session_t * const session
+_pkcs11h_freeObjectAttributes (
+ IN OUT const CK_ATTRIBUTE_PTR attrs,
+ IN const unsigned count
) {
- CK_TOKEN_INFO info;
- CK_SLOT_ID slot = PKCS11H_INVALID_SLOT_ID;
+ unsigned i;
+
CK_RV rv = CKR_OK;
- pkcs11h_provider_t provider = NULL;
+ PKCS11H_ASSERT (attrs!=NULL);
- PKCS11ASSERT (szSlotType!=NULL);
- PKCS11ASSERT (szSlot!=NULL);
- PKCS11ASSERT (session!=NULL);
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_freeObjectAttributes entry attrs=%p, count=%d",
+ (void *)attrs,
+ count
+ );
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_getSession entry szSlotType=%s, szSlot=%s, fProtectedAuthentication=%d, nPINCachePeriod=%d, session=%p",
- szSlotType,
- szSlot,
- fProtectedAuthentication ? 1 : 0,
- nPINCachePeriod,
- (void *)session
+ for (i=0;i<count;i++) {
+ if (attrs[i].pValue != NULL) {
+ _pkcs11h_free ((void *)&attrs[i].pValue);
+ attrs[i].pValue = NULL;
+ }
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_freeObjectAttributes return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
);
- if (rv == CKR_OK) {
- do {
- rv = _pkcs11h_getSlot (
- szSlotType,
- szSlot,
- &provider,
- &slot
- );
-
- if (rv == CKR_SLOT_ID_INVALID) {
- char szLabel[1024];
- strcpy (szLabel, "SLOT(");
- strncat (szLabel, szSlotType, sizeof (szLabel)-1-strlen (szLabel));
- strncat (szLabel, "=", sizeof (szLabel)-1-strlen (szLabel));
- strncat (szLabel, szSlot, sizeof (szLabel)-1-strlen (szLabel));
- strncat (szLabel, ")", sizeof (szLabel)-1-strlen (szLabel));
- szLabel[sizeof (szLabel)-1] = 0;
- PKCS11DLOG (
- PKCS11_LOG_DEBUG1,
- "PKCS#11: Calling card_prompt hook for %s",
- szLabel
- );
- if (
- !pkcs11h_data->hooks->card_prompt (
- pkcs11h_data->hooks->card_prompt_data,
- szLabel
- )
- ) {
- rv = CKR_CANCEL;
- }
- PKCS11DLOG (
- PKCS11_LOG_DEBUG1,
- "PKCS#11: card_prompt returned rv=%ld",
- rv
+ return rv;
+}
+
+static
+CK_RV
+_pkcs11h_findObjects (
+ IN const pkcs11h_session_t session,
+ IN const CK_ATTRIBUTE * const filter,
+ IN const CK_ULONG filter_attrs,
+ OUT CK_OBJECT_HANDLE **const p_objects,
+ OUT CK_ULONG *p_objects_found
+) {
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+ PKCS11H_BOOL fShouldFindObjectFinal = FALSE;
+
+ CK_OBJECT_HANDLE *objects = NULL;
+ CK_ULONG objects_size = 0;
+ CK_OBJECT_HANDLE objects_buffer[100];
+ CK_ULONG objects_found;
+ CK_OBJECT_HANDLE oLast = PKCS11H_INVALID_OBJECT_HANDLE;
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (session!=NULL);
+ PKCS11H_ASSERT (!(filter==NULL && filter_attrs!=0) || filter!=NULL);
+ PKCS11H_ASSERT (p_objects!=NULL);
+ PKCS11H_ASSERT (p_objects_found!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_findObjects entry session=%p, filter=%p, filter_attrs=%ld, p_objects=%p, p_objects_found=%p",
+ (void *)session,
+ (void *)filter,
+ filter_attrs,
+ (void *)p_objects,
+ (void *)p_objects_found
+ );
+
+ *p_objects = NULL;
+ *p_objects_found = 0;
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&session->mutexSession)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
+ if (
+ rv == CKR_OK &&
+ (rv = session->provider->f->C_FindObjectsInit (
+ session->hSession,
+ (CK_ATTRIBUTE *)filter,
+ filter_attrs
+ )) == CKR_OK
+ ) {
+ fShouldFindObjectFinal = TRUE;
+ }
+
+ while (
+ rv == CKR_OK &&
+ (rv = session->provider->f->C_FindObjects (
+ session->hSession,
+ objects_buffer,
+ sizeof (objects_buffer) / sizeof (CK_OBJECT_HANDLE),
+ &objects_found
+ )) == CKR_OK &&
+ objects_found > 0
+ ) {
+ CK_OBJECT_HANDLE *temp = NULL;
+
+ /*
+ * Begin workaround
+ *
+ * Workaround iKey bug
+ * It returns the same objects over and over
+ */
+ if (oLast == objects_buffer[0]) {
+ PKCS11H_LOG (
+ PKCS11H_LOG_WARN,
+ "PKCS#11: Bad PKCS#11 C_FindObjects implementation detected, workaround applied"
+ );
+ break;
+ }
+ oLast = objects_buffer[0];
+ /* End workaround */
+
+ if (
+ (rv = _pkcs11h_malloc (
+ (void *)&temp,
+ (objects_size+objects_found) * sizeof (CK_OBJECT_HANDLE)
+ )) == CKR_OK
+ ) {
+ if (objects != NULL) {
+ memmove (
+ temp,
+ objects,
+ objects_size * sizeof (CK_OBJECT_HANDLE)
);
}
- } while (rv == CKR_SLOT_ID_INVALID);
+ memmove (
+ temp + objects_size,
+ objects_buffer,
+ objects_found * sizeof (CK_OBJECT_HANDLE)
+ );
+ }
+
+ if (rv == CKR_OK) {
+ _pkcs11h_free ((void *)&objects);
+ objects = temp;
+ objects_size += objects_found;
+ temp = NULL;
+ }
+
+ if (temp != NULL) {
+ _pkcs11h_free ((void *)&temp);
+ temp = NULL;
+ }
}
+ if (fShouldFindObjectFinal) {
+ session->provider->f->C_FindObjectsFinal (
+ session->hSession
+ );
+ fShouldFindObjectFinal = FALSE;
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&session->mutexSession);
+ fMutexLocked = FALSE;
+ }
+#endif
+
if (rv == CKR_OK) {
- rv = provider->f->C_GetTokenInfo (
- slot,
- &info
+ *p_objects = objects;
+ *p_objects_found = objects_size;
+ objects = NULL;
+ objects_size = 0;
+ }
+
+ if (objects != NULL) {
+ _pkcs11h_free ((void *)&objects);
+ objects = NULL;
+ objects_size = 0;
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_findObjects return rv=%ld-'%s', *p_objects_found=%ld",
+ rv,
+ pkcs11h_getMessage (rv),
+ *p_objects_found
+ );
+
+ return rv;
+}
+
+static
+CK_RV
+_pkcs11h_getTokenId (
+ IN const CK_TOKEN_INFO_PTR info,
+ OUT pkcs11h_token_id_t * const p_token_id
+) {
+ pkcs11h_token_id_t token_id;
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (info!=NULL);
+ PKCS11H_ASSERT (p_token_id!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_getTokenId entry p_token_id=%p",
+ (void *)p_token_id
+ );
+
+ *p_token_id = NULL;
+
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_newTokenId (&token_id)) == CKR_OK
+ ) {
+ _pkcs11h_fixupFixedString (
+ token_id->label,
+ (char *)info->label,
+ sizeof (info->label)
+ );
+ _pkcs11h_fixupFixedString (
+ token_id->manufacturerID,
+ (char *)info->manufacturerID,
+ sizeof (info->manufacturerID)
);
+ _pkcs11h_fixupFixedString (
+ token_id->model,
+ (char *)info->model,
+ sizeof (info->model)
+ );
+ _pkcs11h_fixupFixedString (
+ token_id->serialNumber,
+ (char *)info->serialNumber,
+ sizeof (info->serialNumber)
+ );
+ }
+
+ if (rv == CKR_OK) {
+ *p_token_id = token_id;
+ token_id = NULL;
+ }
+
+ if (token_id != NULL) {
+ _pkcs11h_free ((void *)&token_id);
}
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_getTokenId return rv=%ld-'%s', *p_token_id=%p",
+ rv,
+ pkcs11h_getMessage (rv),
+ (void *)*p_token_id
+ );
+
+ return rv;
+}
+
+static
+CK_RV
+_pkcs11h_newTokenId (
+ OUT pkcs11h_token_id_t * const p_token_id
+) {
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (p_token_id!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_newTokenId entry p_token_id=%p",
+ (void *)p_token_id
+ );
+
+ *p_token_id = NULL;
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_malloc ((void *)p_token_id, sizeof (struct pkcs11h_token_id_s));
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_newTokenId return rv=%ld-'%s', *p_token_id=%p",
+ rv,
+ pkcs11h_getMessage (rv),
+ (void *)*p_token_id
+ );
+
+ return rv;
+}
+
+static
+CK_RV
+_pkcs11h_getSessionByTokenId (
+ IN const pkcs11h_token_id_t token_id,
+ OUT pkcs11h_session_t * const p_session
+) {
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+ pkcs11h_session_t session = NULL;
+ PKCS11H_BOOL fNewSession = FALSE;
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (token_id!=NULL);
+ PKCS11H_ASSERT (p_session!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_getSessionByTokenId entry token_id=%p, p_session=%p",
+ (void *)token_id,
+ (void *)p_session
+ );
+
+ *p_session = NULL;
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&s_pkcs11h_data->mutexSession)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
if (rv == CKR_OK) {
pkcs11h_session_t current_session;
for (
- current_session = pkcs11h_data->sessions, *session=NULL;
- current_session != NULL && *session == NULL;
+ current_session = s_pkcs11h_data->sessions;
+ current_session != NULL && session == NULL;
current_session = current_session->next
) {
if (
- current_session->provider == provider &&
- !memcmp (
- current_session->serialNumber,
- info.serialNumber,
- sizeof (current_session->serialNumber)
+ pkcs11h_sameTokenId (
+ current_session->token_id,
+ token_id
)
) {
- *session = current_session;
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Using cached session"
+ );
+ session = current_session;
+ session->nReferenceCount++;
}
}
}
- if (rv == CKR_OK) {
- if (*session == NULL) {
-
- if (
- rv == CKR_OK &&
- (*session = (pkcs11h_session_t)malloc (
- sizeof (struct pkcs11h_session_s)
- )) == NULL
- ) {
- rv = CKR_HOST_MEMORY;
- }
+ if (
+ rv == CKR_OK &&
+ session == NULL
+ ) {
+ fNewSession = TRUE;
+ }
- if (rv == CKR_OK) {
- memset (*session, 0, sizeof (struct pkcs11h_session_s));
+ if (fNewSession) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Creating a new session"
+ );
- (*session)->fValid = true;
- (*session)->nReferenceCount = 1;
- (*session)->fProtectedAuthentication = fProtectedAuthentication;
- (*session)->hSession = PKCS11H_INVALID_SESSION_HANDLE;
-
- (*session)->provider = provider;
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_malloc ((void *)&session, sizeof (struct pkcs11h_session_s))) == CKR_OK
+ ) {
+ session->nReferenceCount = 1;
+ session->hSession = PKCS11H_INVALID_SESSION_HANDLE;
+
+ session->nPINCachePeriod = s_pkcs11h_data->nPINCachePeriod;
- if (nPINCachePeriod == PKCS11H_PIN_CACHE_INFINITE) {
- (*session)->nPINCachePeriod = pkcs11h_data->nPINCachePeriod;
- }
- else {
- (*session)->nPINCachePeriod = nPINCachePeriod;
- }
+ }
- provider = NULL;
-
- _pkcs11h_fixupFixedString (
- (char *)info.label,
- (*session)->szLabel,
- sizeof (info.label)
- );
-
- memmove (
- (*session)->serialNumber,
- info.serialNumber,
- sizeof (info.serialNumber)
- );
+ if (rv == CKR_OK) {
+ rv = pkcs11h_duplicateTokenId (
+ &session->token_id,
+ token_id
+ );
+ }
- (*session)->next = pkcs11h_data->sessions;
- pkcs11h_data->sessions = *session;
- }
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_mutexInit (&session->mutexSession);
+ }
+#endif
+
+ if (rv == CKR_OK) {
+ session->fValid = TRUE;
+ session->next = s_pkcs11h_data->sessions;
+ s_pkcs11h_data->sessions = session;
}
else {
- (*session)->nReferenceCount++;
- if (nPINCachePeriod != PKCS11H_PIN_CACHE_INFINITE) {
- if ((*session)->nPINCachePeriod != PKCS11H_PIN_CACHE_INFINITE) {
- if ((*session)->nPINCachePeriod > nPINCachePeriod) {
- (*session)->timePINExpire = (
- (*session)->timePINExpire -
- (time_t)(*session)->nPINCachePeriod +
- (time_t)nPINCachePeriod
- );
- (*session)->nPINCachePeriod = nPINCachePeriod;
- }
- }
- else {
- (*session)->timePINExpire = (
- PKCS11_TIME (NULL) +
- (time_t)nPINCachePeriod
- );
- (*session)->nPINCachePeriod = nPINCachePeriod;
- }
- rv = _pkcs11h_validateSession (*session);
- }
+#if defined(ENABLE_PKCS11H_THREADING)
+ _pkcs11h_mutexFree (&session->mutexSession);
+#endif
+ _pkcs11h_free ((void *)&session);
}
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_getSession return rv=%ld-'%s'",
+ if (rv == CKR_OK) {
+ *p_session = session;
+ session = NULL;
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&s_pkcs11h_data->mutexSession);
+ fMutexLocked = FALSE;
+ }
+#endif
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_getSessionByTokenId return rv=%ld-'%s', *p_session=%p",
rv,
- pkcs11h_getMessage (rv)
+ pkcs11h_getMessage (rv),
+ (void *)*p_session
);
return rv;
@@ -928,114 +2880,269 @@ CK_RV
_pkcs11h_releaseSession (
IN const pkcs11h_session_t session
) {
- PKCS11ASSERT (session!=NULL);
- PKCS11ASSERT (session->nReferenceCount>=0);
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+ CK_RV rv = CKR_OK;
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
+ PKCS11H_ASSERT (session!=NULL);
+ PKCS11H_ASSERT (session->nReferenceCount>=0);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
"PKCS#11: _pkcs11h_releaseSession session=%p",
(void *)session
);
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&session->mutexSession)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
/*
* Never logout for now
*/
-
- if (session->nReferenceCount > 0) {
- session->nReferenceCount--;
+ if (rv == CKR_OK) {
+ if (session->nReferenceCount > 0) {
+ session->nReferenceCount--;
+ }
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_releaseSession return"
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&session->mutexSession);
+ fMutexLocked = FALSE;
+ }
+#endif
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_releaseSession return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
);
- return CKR_OK;
+ return rv;
}
static
CK_RV
_pkcs11h_resetSession (
IN const pkcs11h_session_t session,
- OUT CK_SLOT_ID * const slot
+ IN const unsigned maskPrompt,
+ OUT CK_SLOT_ID * const p_slot
) {
- CK_SLOT_ID slots[1024];
- CK_ULONG slotnum;
- CK_RV rv;
- bool fFound = false;
- bool fCancel = false;
+ /*
+ * This function MUST NOT touch session
+ */
+ PKCS11H_BOOL fFound = FALSE;
+
+ CK_RV rv = CKR_OK;
- PKCS11ASSERT (session!=NULL);
- PKCS11ASSERT (slot!=NULL);
+ PKCS11H_ASSERT (session!=NULL);
+ PKCS11H_ASSERT (p_slot!=NULL);
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_resetSession entry session=%p, slot=%p",
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_resetSession entry session=%p, maskPrompt=%08x, p_slot=%p",
(void *)session,
- (void *)slot
+ maskPrompt,
+ (void *)p_slot
);
- do {
- slotnum = sizeof (slots) / sizeof (CK_SLOT_ID);
+ *p_slot = PKCS11H_INVALID_SLOT_ID;
+
+ while (
+ rv == CKR_OK &&
+ !fFound
+ ) {
+ pkcs11h_provider_t current_provider = NULL;
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+
+#if defined(ENABLE_PKCS11H_THREADING)
if (
- (rv = session->provider->f->C_GetSlotList (
- TRUE,
- slots,
- &slotnum
- )) == CKR_OK
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&session->mutexSession)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
+ for (
+ current_provider = s_pkcs11h_data->providers;
+ (
+ rv == CKR_OK &&
+ current_provider != NULL &&
+ !fFound
+ );
+ current_provider = current_provider->next
) {
- CK_SLOT_ID s;
+ CK_SLOT_ID_PTR slots = NULL;
+ CK_ULONG slotnum;
+ CK_SLOT_ID slot_index;
+
+ /*
+ * Skip disabled providers
+ * Skip all other providers,
+ * if one was set in the past
+ */
+ if (session->provider != NULL) {
+ if (!session->provider->fEnabled) {
+ continue;
+ }
+ if (session->provider != current_provider) {
+ continue;
+ }
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_getSlotList (
+ current_provider,
+ CK_TRUE,
+ &slots,
+ &slotnum
+ );
+ }
- for (s=0;!fFound && s<slotnum;s++) {
+ for (
+ slot_index=0;
+ (
+ slot_index < slotnum &&
+ rv == CKR_OK &&
+ !fFound
+ );
+ slot_index++
+ ) {
+ pkcs11h_token_id_t token_id = NULL;
CK_TOKEN_INFO info;
- if (
- (rv = session->provider->f->C_GetTokenInfo (
- slots[s],
+ if (rv == CKR_OK) {
+ rv = current_provider->f->C_GetTokenInfo (
+ slots[slot_index],
&info
- )) == CKR_OK
+ );
+ }
+
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_getTokenId (
+ &info,
+ &token_id
+ )) == CKR_OK &&
+ pkcs11h_sameTokenId (
+ session->token_id,
+ token_id
+ )
) {
- if (
- !memcmp (
- session->serialNumber,
- info.serialNumber,
- sizeof (session->serialNumber)
- )
- ) {
- *slot = slots[s];
- fFound = true;
+ fFound = TRUE;
+ *p_slot = slots[slot_index];
+ if (session->provider == NULL) {
+ session->provider = current_provider;
+ _pkcs11h_fixupFixedString (
+ token_id->label,
+ (char *)info.label,
+ sizeof (info.label)
+ );
+ session->fProtectedAuthenticationSupported = (info.flags & CKF_PROTECTED_AUTHENTICATION_PATH) != 0;
}
}
+
+ if (rv != CKR_OK) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Cannot get token information for provider '%s' slot %ld rv=%ld-'%s'",
+ current_provider->manufacturerID,
+ slots[slot_index],
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ /*
+ * Ignore error
+ */
+ rv = CKR_OK;
+ }
+
+ if (token_id != NULL) {
+ pkcs11h_freeTokenId (token_id);
+ }
+ }
+
+ if (rv != CKR_OK) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Cannot get slot list for provider '%s' rv=%ld-'%s'",
+ current_provider->manufacturerID,
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ /*
+ * Ignore error
+ */
+ rv = CKR_OK;
+ }
+
+ if (slots != NULL) {
+ _pkcs11h_free ((void *)&slots);
+ slots = NULL;
}
}
- if (!fFound) {
- PKCS11DLOG (
- PKCS11_LOG_DEBUG1,
- "PKCS#11: Calling card_prompt hook for %s",
- session->szLabel
- );
-
- fCancel = !pkcs11h_data->hooks->card_prompt (
- pkcs11h_data->hooks->card_prompt_data,
- session->szLabel
- );
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&session->mutexSession);
+ fMutexLocked = FALSE;
+ }
+#endif
- PKCS11DLOG (
- PKCS11_LOG_DEBUG1,
- "PKCS#11: card_prompt returned %d",
- fCancel ? 1 : 0
- );
+ if (
+ rv == CKR_OK &&
+ !fFound
+ ) {
+ if ((maskPrompt & PKCS11H_PROMPT_MAST_ALLOW_CARD_PROMPT) != 0) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Calling token_prompt hook for '%s'",
+ session->token_id->label
+ );
+
+ if (
+ !s_pkcs11h_data->hooks.token_prompt (
+ s_pkcs11h_data->hooks.token_prompt_data,
+ session->token_id
+ )
+ ) {
+ rv = CKR_CANCEL;
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: token_prompt returned %ld",
+ rv
+ );
+ }
+ else {
+ rv = CKR_TOKEN_NOT_PRESENT;
+ }
}
- } while (!fFound && !fCancel);
+ }
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_resetSession return fFound=%d",
- fFound ? 1 : 0
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_resetSession return rv=%ld-'%s', *p_slot=%ld",
+ rv,
+ pkcs11h_getMessage (rv),
+ *p_slot
);
- return fFound ? CKR_OK : CKR_SLOT_ID_INVALID;
+ return rv;
}
static
@@ -1043,73 +3150,69 @@ CK_RV
_pkcs11h_getObjectById (
IN const pkcs11h_session_t session,
IN const CK_OBJECT_CLASS class,
- IN const unsigned char * const id,
+ IN const CK_BYTE_PTR id,
IN const size_t id_size,
- OUT CK_OBJECT_HANDLE * const handle
+ OUT CK_OBJECT_HANDLE * const p_handle
) {
- CK_ULONG count;
- CK_RV rv = CKR_OK;
-
CK_ATTRIBUTE filter[] = {
{CKA_CLASS, (void *)&class, sizeof (class)},
{CKA_ID, (void *)id, id_size}
};
+ CK_OBJECT_HANDLE *objects = NULL;
+ CK_ULONG objects_found = 0;
+ CK_RV rv = CKR_OK;
- PKCS11ASSERT (session!=NULL);
- PKCS11ASSERT (id!=NULL);
- PKCS11ASSERT (handle!=NULL);
+ /*PKCS11H_ASSERT (session!=NULL); NOT NEEDED*/
+ PKCS11H_ASSERT (id!=NULL);
+ PKCS11H_ASSERT (p_handle!=NULL);
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_getObjectById entry session=%p, class=%ld, id=%p, id_size=%u, handle=%p",
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_getObjectById entry session=%p, class=%ld, id=%p, id_size=%u, p_handle=%p",
(void *)session,
class,
id,
id_size,
- (void *)handle
+ (void *)p_handle
);
- /*
- * Don't try invalid session
- */
- if (
- rv == CKR_OK &&
- session->hSession == PKCS11H_INVALID_SESSION_HANDLE
- ) {
- rv = CKR_SESSION_HANDLE_INVALID;
- }
+ *p_handle = PKCS11H_INVALID_OBJECT_HANDLE;
if (rv == CKR_OK) {
- rv = session->provider->f->C_FindObjectsInit (
- session->hSession,
- filter,
- sizeof (filter) / sizeof (CK_ATTRIBUTE)
- );
+ rv = _pkcs11h_validateSession (session);
}
- if (rv == CKR_OK) {
- rv = session->provider->f->C_FindObjects (
- session->hSession,
- handle,
- 1,
- &count
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_findObjects (
+ session,
+ filter,
+ sizeof (filter) / sizeof (CK_ATTRIBUTE),
+ &objects,
+ &objects_found
);
}
if (
rv == CKR_OK &&
- count == 0
+ objects_found == 0
) {
rv = CKR_FUNCTION_REJECTED;
}
- session->provider->f->C_FindObjectsFinal (session->hSession);
+ if (rv == CKR_OK) {
+ *p_handle = objects[0];
+ }
+
+ if (objects != NULL) {
+ _pkcs11h_free ((void *)&objects);
+ }
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_getObjectById return rv=%ld-'%s'",
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_getObjectById return rv=%ld-'%s', *p_handle=%p",
rv,
- pkcs11h_getMessage (rv)
+ pkcs11h_getMessage (rv),
+ (void *)*p_handle
);
return rv;
@@ -1120,43 +3223,99 @@ CK_RV
_pkcs11h_validateSession (
IN const pkcs11h_session_t session
) {
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+ CK_RV rv = CKR_OK;
+
+ /*PKCS11H_ASSERT (session!=NULL); NOT NEEDED*/
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
"PKCS#11: _pkcs11h_validateSession entry session=%p",
(void *)session
);
if (
+ rv == CKR_OK &&
+ session == NULL
+ ) {
+ rv = CKR_SESSION_HANDLE_INVALID;
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&session->mutexSession)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
+ if (
+ rv == CKR_OK &&
+ (
+ session->provider == NULL ||
+ !session->provider->fEnabled ||
+ session->hSession == PKCS11H_INVALID_SESSION_HANDLE
+ )
+ ) {
+ rv = CKR_SESSION_HANDLE_INVALID;
+ }
+
+ if (
+ rv == CKR_OK &&
session->timePINExpire != (time_t)0 &&
- session->timePINExpire < PKCS11_TIME (NULL)
+ session->timePINExpire < PKCS11H_TIME (NULL)
) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Forcing logout due to pin timeout"
+ );
_pkcs11h_logout (session);
+ rv = CKR_SESSION_HANDLE_INVALID;
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_validateSession return"
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&session->mutexSession);
+ fMutexLocked = FALSE;
+ }
+#endif
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_validateSession return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
);
- return CKR_OK;
+ return rv;
}
static
CK_RV
_pkcs11h_login (
IN const pkcs11h_session_t session,
- IN const bool fPublicOnly
+ IN const PKCS11H_BOOL fPublicOnly,
+ IN const PKCS11H_BOOL fReadOnly,
+ IN const unsigned maskPrompt
) {
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
CK_SLOT_ID slot = PKCS11H_INVALID_SLOT_ID;
CK_RV rv = CKR_OK;
- PKCS11ASSERT (session!=NULL);
+ PKCS11H_ASSERT (session!=NULL);
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_login entry session=%p, fPublicOnly=%d",
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_login entry session=%p, fPublicOnly=%d, fReadOnly=%d, maskPrompt=%08x",
(void *)session,
- fPublicOnly ? 1 : 0
+ fPublicOnly ? 1 : 0,
+ fReadOnly ? 1 : 0,
+ maskPrompt
);
if (rv == CKR_OK) {
@@ -1164,104 +3323,150 @@ _pkcs11h_login (
}
if (rv == CKR_OK) {
- rv = _pkcs11h_resetSession (session, &slot);
+ rv = _pkcs11h_resetSession (session, maskPrompt, &slot);
}
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&session->mutexSession)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
if (rv == CKR_OK) {
rv = session->provider->f->C_OpenSession (
slot,
- CKF_SERIAL_SESSION,
+ (
+ CKF_SERIAL_SESSION |
+ (fReadOnly ? 0 : CKF_RW_SESSION)
+ ),
NULL_PTR,
NULL_PTR,
&session->hSession
);
}
- if (rv == CKR_OK) {
- if (!fPublicOnly) {
- int nRetryCount = 0;
- do {
- CK_UTF8CHAR_PTR utfPIN = NULL;
- CK_ULONG lPINLength = 0;
- char szPIN[1024];
+ if (
+ rv == CKR_OK &&
+ (
+ !fPublicOnly ||
+ session->provider->fCertIsPrivate
+ )
+ ) {
+ PKCS11H_BOOL fSuccessLogin = FALSE;
+ int nRetryCount = 0;
- /*
- * Assume OK for next iteration
- */
- rv = CKR_OK;
+ if ((maskPrompt & PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT) == 0) {
+ rv = CKR_USER_NOT_LOGGED_IN;
- if (
- rv == CKR_OK &&
- !session->fProtectedAuthentication
- ) {
- PKCS11DLOG (
- PKCS11_LOG_DEBUG1,
- "PKCS#11: Calling pin_prompt hook for %s",
- session->szLabel
- );
-
- if (
- !pkcs11h_data->hooks->pin_prompt (
- pkcs11h_data->hooks->pin_prompt_data,
- session->szLabel,
- szPIN,
- sizeof (szPIN)
- )
- ) {
- rv = CKR_FUNCTION_FAILED;
- }
- else {
- utfPIN = (CK_UTF8CHAR_PTR)szPIN;
- lPINLength = strlen (szPIN);
- }
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Calling pin_prompt hook denied because of prompt mask"
+ );
+ }
- PKCS11DLOG (
- PKCS11_LOG_DEBUG1,
- "PKCS#11: pin_prompt hook return rv=%ld",
- rv
- );
-
- }
+ while (
+ rv == CKR_OK &&
+ !fSuccessLogin &&
+ nRetryCount++ < s_pkcs11h_data->nMaxLoginRetries
+ ) {
+ CK_UTF8CHAR_PTR utfPIN = NULL;
+ CK_ULONG lPINLength = 0;
+ char szPIN[1024];
- if (session->nPINCachePeriod == PKCS11H_PIN_CACHE_INFINITE) {
- session->timePINExpire = 0;
+ if (
+ rv == CKR_OK &&
+ !(
+ s_pkcs11h_data->fProtectedAuthentication &&
+ session->provider->fProtectedAuthentication &&
+ session->fProtectedAuthenticationSupported
+ )
+ ) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Calling pin_prompt hook for '%s'",
+ session->token_id->label
+ );
+
+ if (
+ !s_pkcs11h_data->hooks.pin_prompt (
+ s_pkcs11h_data->hooks.pin_prompt_data,
+ session->token_id,
+ szPIN,
+ sizeof (szPIN)
+ )
+ ) {
+ rv = CKR_CANCEL;
}
else {
- session->timePINExpire = (
- PKCS11_TIME (NULL) +
- (time_t)session->nPINCachePeriod
- );
+ utfPIN = (CK_UTF8CHAR_PTR)szPIN;
+ lPINLength = strlen (szPIN);
}
- if (
- rv == CKR_OK &&
- (rv = session->provider->f->C_Login (
- session->hSession,
- CKU_USER,
- utfPIN,
- lPINLength
- )) != CKR_OK
- ) {
- if (rv == CKR_USER_ALREADY_LOGGED_IN) {
- rv = CKR_OK;
- }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: pin_prompt hook return rv=%ld",
+ rv
+ );
+
+ }
+
+ if (session->nPINCachePeriod == PKCS11H_PIN_CACHE_INFINITE) {
+ session->timePINExpire = 0;
+ }
+ else {
+ session->timePINExpire = (
+ PKCS11H_TIME (NULL) +
+ (time_t)session->nPINCachePeriod
+ );
+ }
+
+ if (
+ rv == CKR_OK &&
+ (rv = session->provider->f->C_Login (
+ session->hSession,
+ CKU_USER,
+ utfPIN,
+ lPINLength
+ )) != CKR_OK
+ ) {
+ if (rv == CKR_USER_ALREADY_LOGGED_IN) {
+ rv = CKR_OK;
}
+ }
+ /*
+ * Clean PIN buffer
+ */
+ memset (szPIN, 0, sizeof (szPIN));
+
+ if (rv == CKR_OK) {
+ fSuccessLogin = TRUE;
+ }
+ else if (
+ rv == CKR_PIN_INCORRECT ||
+ rv == CKR_PIN_INVALID
+ ) {
/*
- * Clean PIN buffer
+ * Ignore these errors
+ * so retry can be performed
*/
- memset (szPIN, 0, sizeof (szPIN));
- } while (
- ++nRetryCount < 3 &&
- (
- rv == CKR_PIN_INCORRECT ||
- rv == CKR_PIN_INVALID
- )
- );
+ rv = CKR_OK;
+ }
}
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&session->mutexSession);
+ fMutexLocked = FALSE;
+ }
+#endif
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
"PKCS#11: _pkcs11h_login return rv=%ld-'%s'",
rv,
pkcs11h_getMessage (rv)
@@ -1275,22 +3480,50 @@ CK_RV
_pkcs11h_logout (
IN const pkcs11h_session_t session
) {
- PKCS11ASSERT (session!=NULL);
+ /*PKCS11H_ASSERT (session!=NULL); NOT NEEDED*/
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
"PKCS#11: _pkcs11h_logout entry session=%p",
(void *)session
);
- if (session->hSession != PKCS11H_INVALID_SESSION_HANDLE) {
- session->provider->f->C_Logout (session->hSession);
- session->provider->f->C_CloseSession (session->hSession);
- session->hSession = PKCS11H_INVALID_SESSION_HANDLE;
+ if (
+ session != NULL &&
+ session->hSession != PKCS11H_INVALID_SESSION_HANDLE
+ ) {
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+ CK_RV rv = CKR_OK;
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&session->mutexSession)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
+ if (rv == CKR_OK) {
+ if (session->provider != NULL) {
+ session->provider->f->C_Logout (session->hSession);
+ session->provider->f->C_CloseSession (session->hSession);
+ }
+ session->hSession = PKCS11H_INVALID_SESSION_HANDLE;
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&session->mutexSession);
+ fMutexLocked = FALSE;
+ }
+#endif
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
"PKCS#11: _pkcs11h_logout return"
);
@@ -1298,234 +3531,1127 @@ _pkcs11h_logout (
}
static
+void
+_pkcs11h_hooks_default_log (
+ IN const void * pData,
+ IN const unsigned flags,
+ IN const char * const szFormat,
+ IN va_list args
+) {
+ (void)pData;
+ (void)flags;
+ (void)szFormat;
+ (void)args;
+}
+
+static
+PKCS11H_BOOL
+_pkcs11h_hooks_default_token_prompt (
+ IN const void * pData,
+ IN const pkcs11h_token_id_t token
+) {
+ PKCS11H_ASSERT (token!=NULL);
+
+ (void)pData;
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_hooks_default_token_prompt pData=%p, szLabel='%s'",
+ pData,
+ token->label
+ );
+
+ return FALSE;
+}
+
+static
+PKCS11H_BOOL
+_pkcs11h_hooks_default_pin_prompt (
+ IN const void * pData,
+ IN const pkcs11h_token_id_t token,
+ OUT char * const szPIN,
+ IN const size_t nMaxPIN
+) {
+ PKCS11H_ASSERT (token!=NULL);
+
+ (void)pData;
+ (void)szPIN;
+ (void)nMaxPIN;
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_hooks_default_pin_prompt pData=%p, szLabel='%s'",
+ pData,
+ token->label
+ );
+
+ return FALSE;
+}
+
+#if !defined(WIN32)
+#if defined(ENABLE_PKCS11H_THREADING)
+
+static
+void
+__pkcs11h_atfork_prepare () {
+ __pkcs1h_mutexLockAll ();
+}
+static
+void
+__pkcs11h_atfork_parent () {
+ __pkcs1h_mutexReleaseAll ();
+}
+static
+void
+__pkcs11h_atfork_child () {
+ __pkcs1h_mutexReleaseAll ();
+ _pkcs11h_forkFixup ();
+}
+
+#endif /* ENABLE_PKCS11H_THREADING */
+
+static
CK_RV
-_pkcs11h_setCertificateSession_Certificate (
- IN const pkcs11h_certificate_t pkcs11h_certificate,
- IN const char * const szIdType,
- IN const char * const szId
+_pkcs11h_forkFixup () {
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+ pid_t mypid = getpid ();
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_forkFixup entry pid=%d",
+ mypid
+ );
+
+ if (s_pkcs11h_data != NULL && s_pkcs11h_data->fInitialized) {
+ pkcs11h_provider_t current;
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (_pkcs11h_mutexLock (&s_pkcs11h_data->mutexGlobal) == CKR_OK) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
+ for (
+ current = s_pkcs11h_data->providers;
+ current != NULL;
+ current = current->next
+ ) {
+ if (current->fEnabled) {
+ current->f->C_Initialize (NULL);
+ }
+
+#if defined(ENABLE_PKCS11H_SLOTEVENT)
+ /*
+ * After fork we have no threads...
+ * So just initialized.
+ */
+ if (s_pkcs11h_data->fSlotEventInitialized) {
+ s_pkcs11h_data->fSlotEventInitialized = FALSE;
+ _pkcs11h_slotevent_init ();
+ }
+#endif
+ }
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&s_pkcs11h_data->mutexGlobal);
+ fMutexLocked = FALSE;
+ }
+#endif
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_forkFixup return"
+ );
+
+ return CKR_OK;
+}
+
+#endif /* !WIN32 */
+
+#if defined(ENABLE_PKCS11H_TOKEN)
+/*======================================================================*
+ * TOKEN INTERFACE
+ *======================================================================*/
+
+CK_RV
+pkcs11h_token_ensureAccess (
+ IN const pkcs11h_token_id_t token_id,
+ IN const unsigned maskPrompt
) {
+ pkcs11h_session_t session = NULL;
CK_RV rv = CKR_OK;
- unsigned char selected_id[PKCS11H_MAX_ATTRIBUTE_SIZE];
- int selected_id_size = 0;
- unsigned char selected_certificate[PKCS11H_MAX_ATTRIBUTE_SIZE];
- int selected_certificate_size = 0;
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (token_id!=NULL);
- CK_OBJECT_CLASS cert_filter_class = CKO_CERTIFICATE;
- unsigned char cert_filter_by[PKCS11H_MAX_ATTRIBUTE_SIZE];
- CK_ATTRIBUTE cert_filter[] = {
- {CKA_CLASS, &cert_filter_class, sizeof (cert_filter_class)},
- {0, cert_filter_by, 0}
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_token_ensureAccess entry token_id=%p, maskPrompt=%08x",
+ (void *)token_id,
+ maskPrompt
+ );
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_getSessionByTokenId (
+ token_id,
+ &session
+ );
+ }
+
+ if (rv == CKR_OK) {
+ CK_SLOT_ID slot;
+
+ rv = _pkcs11h_resetSession (
+ session,
+ maskPrompt,
+ &slot
+ );
+ }
+
+ if (session != NULL) {
+ _pkcs11h_releaseSession (session);
+ session = NULL;
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_token_ensureAccess return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+#endif /* ENABLE_PKCS11H_TOKEN */
+
+#if defined(ENABLE_PKCS11H_DATA)
+/*======================================================================*
+ * DATA INTERFACE
+ *======================================================================*/
+
+static
+CK_RV
+_pkcs11h_data_getObject (
+ IN const pkcs11h_session_t session,
+ IN const char * const szApplication,
+ IN const char * const szLabel,
+ OUT CK_OBJECT_HANDLE * const p_handle
+) {
+ CK_OBJECT_CLASS class = CKO_DATA;
+ CK_ATTRIBUTE filter[] = {
+ {CKA_CLASS, (void *)&class, sizeof (class)},
+ {CKA_APPLICATION, (void *)szApplication, szApplication == NULL ? 0 : strlen (szApplication)},
+ {CKA_LABEL, (void *)szLabel, szLabel == NULL ? 0 : strlen (szLabel)}
};
- int cert_filter_num = 1;
+ CK_OBJECT_HANDLE *objects = NULL;
+ CK_ULONG objects_found = 0;
+ CK_RV rv = CKR_OK;
+
+ /*PKCS11H_ASSERT (session!=NULL); NOT NEEDED*/
+ PKCS11H_ASSERT (szApplication!=NULL);
+ PKCS11H_ASSERT (szLabel!=NULL);
- PKCS11ASSERT (pkcs11h_certificate!=NULL);
- PKCS11ASSERT (szIdType!=NULL);
- PKCS11ASSERT (szId!=NULL);
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_data_getObject entry session=%p, szApplication='%s', szLabel='%s', p_handle=%p",
+ (void *)session,
+ szApplication,
+ szLabel,
+ (void *)p_handle
+ );
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_setCertificateSession_Certificate entry pkcs11h_certificate=%p, szIdType=%s, szId=%s",
- (void *)pkcs11h_certificate,
- szIdType,
- szId
+ *p_handle = PKCS11H_INVALID_OBJECT_HANDLE;
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_validateSession (session);
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_findObjects (
+ session,
+ filter,
+ sizeof (filter) / sizeof (CK_ATTRIBUTE),
+ &objects,
+ &objects_found
+ );
+ }
+
+ if (
+ rv == CKR_OK &&
+ objects_found == 0
+ ) {
+ rv = CKR_FUNCTION_REJECTED;
+ }
+
+ if (rv == CKR_OK) {
+ *p_handle = objects[0];
+ }
+
+ if (objects != NULL) {
+ _pkcs11h_free ((void *)&objects);
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_data_getObject return rv=%ld-'%s', *p_handle=%p",
+ rv,
+ pkcs11h_getMessage (rv),
+ (void *)*p_handle
+ );
+
+ return rv;
+}
+
+CK_RV
+pkcs11h_data_get (
+ IN const pkcs11h_token_id_t token_id,
+ IN const PKCS11H_BOOL fPublic,
+ IN const char * const szApplication,
+ IN const char * const szLabel,
+ OUT char * const blob,
+ IN OUT size_t * const p_blob_size
+) {
+ CK_ATTRIBUTE attrs[] = {
+ {CKA_VALUE, NULL, 0}
+ };
+ CK_OBJECT_HANDLE handle = PKCS11H_INVALID_OBJECT_HANDLE;
+ CK_RV rv = CKR_OK;
+
+ pkcs11h_session_t session = NULL;
+ size_t blob_size_max;
+ PKCS11H_BOOL fOpSuccess = FALSE;
+ PKCS11H_BOOL fLoginRetry = FALSE;
+ PKCS11H_BOOL fMutexLocked = FALSE;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (token_id!=NULL);
+ PKCS11H_ASSERT (szApplication!=NULL);
+ PKCS11H_ASSERT (szLabel!=NULL);
+ /*PKCS11H_ASSERT (blob!=NULL); NOT NEEDED*/
+ PKCS11H_ASSERT (p_blob_size!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_data_get entry token_id=%p, szApplication='%s', szLabel='%s', blob=%p, p_blob_size=%p",
+ (void *)token_id,
+ szApplication,
+ szLabel,
+ blob,
+ (void *)p_blob_size
);
+ blob_size_max = *p_blob_size;
+ *p_blob_size = 0;
+
if (rv == CKR_OK) {
- if (!strcmp (szIdType, "label")) {
- cert_filter[1].type = CKA_LABEL;
- cert_filter[1].ulValueLen = (CK_ULONG)(
- strlen (szId) < sizeof (cert_filter_by) ?
- strlen (szId) :
- sizeof (cert_filter_by)
- );
- memmove (
- cert_filter_by,
- szId,
- cert_filter[1].ulValueLen
+ rv = _pkcs11h_getSessionByTokenId (
+ token_id,
+ &session
+ );
+ }
+
+ while (rv == CKR_OK && !fOpSuccess) {
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_validateSession (session);
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&session->mutexSession)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_data_getObject (
+ session,
+ szApplication,
+ szLabel,
+ &handle
);
- cert_filter_num++;
}
- else if (!strcmp (szIdType, "id")) {
- size_t s = sizeof (cert_filter_by);
-
- cert_filter[1].type = CKA_ID;
- _hexToBinary (
- szId,
- cert_filter_by,
- &s
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_getObjectAttributes (
+ session,
+ handle,
+ attrs,
+ sizeof (attrs)/sizeof (CK_ATTRIBUTE)
);
- cert_filter[1].ulValueLen = s;
- cert_filter_num++;
}
- else if (!strcmp (szIdType, "subject")) {
- memmove (&cert_filter[1], &cert_filter[0], sizeof (CK_ATTRIBUTE));
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&session->mutexSession);
+ fMutexLocked = FALSE;
+ }
+#endif
+
+ if (rv == CKR_OK) {
+ fOpSuccess = TRUE;
}
else {
- rv = CKR_ARGUMENTS_BAD;
+ if (!fLoginRetry) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Read data object failed rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+ fLoginRetry = TRUE;
+ rv = _pkcs11h_login (
+ session,
+ fPublic,
+ TRUE,
+ (
+ PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT |
+ PKCS11H_PROMPT_MAST_ALLOW_CARD_PROMPT
+ )
+ );
+ }
}
}
-
+
if (rv == CKR_OK) {
- rv = pkcs11h_certificate->session->provider->f->C_FindObjectsInit (
- pkcs11h_certificate->session->hSession,
- cert_filter,
- cert_filter_num
+ *p_blob_size = attrs[0].ulValueLen;
+ }
+
+ if (rv == CKR_OK) {
+ if (blob != NULL) {
+ if (*p_blob_size > blob_size_max) {
+ rv = CKR_BUFFER_TOO_SMALL;
+ }
+ else {
+ memmove (blob, attrs[0].pValue, *p_blob_size);
+ }
+ }
+ }
+
+ _pkcs11h_freeObjectAttributes (
+ attrs,
+ sizeof (attrs)/sizeof (CK_ATTRIBUTE)
+ );
+
+ if (session != NULL) {
+ _pkcs11h_releaseSession (session);
+ session = NULL;
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_data_get return rv=%ld-'%s', *p_blob_size=%d",
+ rv,
+ pkcs11h_getMessage (rv),
+ *p_blob_size
+ );
+
+ return rv;
+}
+
+CK_RV
+pkcs11h_data_put (
+ IN const pkcs11h_token_id_t token_id,
+ IN const PKCS11H_BOOL fPublic,
+ IN const char * const szApplication,
+ IN const char * const szLabel,
+ OUT char * const blob,
+ IN const size_t blob_size
+) {
+ CK_OBJECT_CLASS class = CKO_DATA;
+ CK_BBOOL ck_true = CK_TRUE;
+ CK_BBOOL ck_false = CK_FALSE;
+
+ CK_ATTRIBUTE attrs[] = {
+ {CKA_CLASS, &class, sizeof (class)},
+ {CKA_TOKEN, &ck_true, sizeof (ck_true)},
+ {CKA_PRIVATE, fPublic ? &ck_false : &ck_true, sizeof (CK_BBOOL)},
+ {CKA_APPLICATION, (void *)szApplication, strlen (szApplication)},
+ {CKA_LABEL, (void *)szLabel, strlen (szLabel)},
+ {CKA_VALUE, blob, blob_size}
+ };
+
+ CK_OBJECT_HANDLE handle = PKCS11H_INVALID_OBJECT_HANDLE;
+ CK_RV rv = CKR_OK;
+
+ pkcs11h_session_t session = NULL;
+ PKCS11H_BOOL fOpSuccess = FALSE;
+ PKCS11H_BOOL fLoginRetry = FALSE;
+ PKCS11H_BOOL fMutexLocked = FALSE;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (token_id!=NULL);
+ PKCS11H_ASSERT (szApplication!=NULL);
+ PKCS11H_ASSERT (szLabel!=NULL);
+ PKCS11H_ASSERT (blob!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_data_put entry token_id=%p, szApplication='%s', szLabel='%s', blob=%p, blob_size=%d",
+ (void *)token_id,
+ szApplication,
+ szLabel,
+ blob,
+ blob_size
+ );
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_getSessionByTokenId (
+ token_id,
+ &session
);
}
+ while (rv == CKR_OK && !fOpSuccess) {
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_validateSession (session);
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&session->mutexSession)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
+ if (rv == CKR_OK) {
+ rv = session->provider->f->C_CreateObject (
+ session->hSession,
+ attrs,
+ sizeof (attrs)/sizeof (CK_ATTRIBUTE),
+ &handle
+ );
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&session->mutexSession);
+ fMutexLocked = FALSE;
+ }
+#endif
+
+ if (rv == CKR_OK) {
+ fOpSuccess = TRUE;
+ }
+ else {
+ if (!fLoginRetry) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Write data object failed rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+ fLoginRetry = TRUE;
+ rv = _pkcs11h_login (
+ session,
+ fPublic,
+ FALSE,
+ (
+ PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT |
+ PKCS11H_PROMPT_MAST_ALLOW_CARD_PROMPT
+ )
+ );
+ }
+ }
+ }
+
+ if (session != NULL) {
+ _pkcs11h_releaseSession (session);
+ session = NULL;
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_data_put return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+CK_RV
+pkcs11h_data_del (
+ IN const pkcs11h_token_id_t token_id,
+ IN const PKCS11H_BOOL fPublic,
+ IN const char * const szApplication,
+ IN const char * const szLabel
+) {
+ CK_OBJECT_HANDLE handle = PKCS11H_INVALID_OBJECT_HANDLE;
+ CK_RV rv = CKR_OK;
+
+ pkcs11h_session_t session = NULL;
+ PKCS11H_BOOL fOpSuccess = FALSE;
+ PKCS11H_BOOL fLoginRetry = FALSE;
+ PKCS11H_BOOL fMutexLocked = FALSE;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (token_id!=NULL);
+ PKCS11H_ASSERT (szApplication!=NULL);
+ PKCS11H_ASSERT (szLabel!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_data_del entry token_id=%p, szApplication='%s', szLabel='%s'",
+ (void *)token_id,
+ szApplication,
+ szLabel
+ );
+
if (rv == CKR_OK) {
- CK_OBJECT_HANDLE objects[10];
- CK_ULONG objects_found;
- CK_OBJECT_HANDLE oLast = PKCS11H_INVALID_OBJECT_HANDLE;
+ rv = _pkcs11h_getSessionByTokenId (
+ token_id,
+ &session
+ );
+ }
- while (
- (rv = pkcs11h_certificate->session->provider->f->C_FindObjects (
- pkcs11h_certificate->session->hSession,
- objects,
- sizeof (objects) / sizeof (CK_OBJECT_HANDLE),
- &objects_found
- )) == CKR_OK &&
- objects_found > 0
- ) {
- CK_ULONG i;
+ while (rv == CKR_OK && !fOpSuccess) {
- /*
- * Begin workaround
- *
- * Workaround iKey bug
- * It returns the same objects over and over
- */
- if (oLast == objects[0]) {
- PKCS11LOG (
- PKCS11_LOG_WARN,
- "PKCS#11: Bad PKCS#11 C_FindObjects implementation detected, workaround applied"
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_validateSession (session);
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_data_getObject (
+ session,
+ szApplication,
+ szLabel,
+ &handle
+ );
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&session->mutexSession)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
+ if (rv == CKR_OK) {
+ rv = session->provider->f->C_DestroyObject (
+ session->hSession,
+ handle
+ );
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&session->mutexSession);
+ fMutexLocked = FALSE;
+ }
+#endif
+
+ if (rv == CKR_OK) {
+ fOpSuccess = TRUE;
+ }
+ else {
+ if (!fLoginRetry) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Remove data object failed rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+ fLoginRetry = TRUE;
+ rv = _pkcs11h_login (
+ session,
+ fPublic,
+ FALSE,
+ (
+ PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT |
+ PKCS11H_PROMPT_MAST_ALLOW_CARD_PROMPT
+ )
);
- break;
}
- oLast = objects[0];
- /* End workaround */
-
- for (i=0;i<objects_found;i++) {
- unsigned char attrs_id[PKCS11H_MAX_ATTRIBUTE_SIZE];
- unsigned char attrs_value[PKCS11H_MAX_ATTRIBUTE_SIZE];
- CK_ATTRIBUTE attrs[] = {
- {CKA_ID, attrs_id, sizeof (attrs_id)},
- {CKA_VALUE, attrs_value, sizeof (attrs_value)}
- };
-
- if (
- pkcs11h_certificate->session->provider->f->C_GetAttributeValue (
- pkcs11h_certificate->session->hSession,
- objects[i],
- attrs,
- sizeof (attrs) / sizeof (CK_ATTRIBUTE)
- ) == CKR_OK
- ) {
- bool fSelected = false;
-
- if (!strcmp (szIdType, "subject")) {
- X509 *x509 = NULL;
- char szSubject[1024];
- pkcs11_openssl_d2i_t d2i1;
-
- x509 = X509_new ();
-
- d2i1 = (pkcs11_openssl_d2i_t)attrs_value;
- if (d2i_X509 (&x509, &d2i1, attrs[1].ulValueLen)) {
- X509_NAME_oneline (
- X509_get_subject_name (x509),
- szSubject,
- sizeof (szSubject)
- );
- szSubject[sizeof (szSubject) - 1] = '\0';
- }
-
- if (x509 != NULL) {
- X509_free (x509);
- x509 = NULL;
- }
+ }
+ }
+
+ if (session != NULL) {
+ _pkcs11h_releaseSession (session);
+ session = NULL;
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_data_del return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+#endif /* ENABLE_PKCS11H_DATA */
+
+#if defined(ENABLE_PKCS11H_CERTIFICATE)
+/*======================================================================*
+ * CERTIFICATE INTERFACE
+ *======================================================================*/
+
+static
+void
+_pkcs11h_isBetterCertificate_getExpiration (
+ IN const unsigned char * const pCertificate,
+ IN const size_t nCertificateSize,
+ OUT char * const szNotBefore,
+ IN const int nNotBeforeSize
+) {
+ /*
+ * This function compare the notBefore
+ * and select the most recent certificate
+ * it does not deal with timezones...
+ * When openssl will have ASN1_TIME compare function
+ * it should be used.
+ */
+
+ X509 *x509 = NULL;
+
+ PKCS11H_ASSERT (pCertificate!=NULL);
+ PKCS11H_ASSERT (szNotBefore!=NULL);
+ PKCS11H_ASSERT (nNotBeforeSize>0);
+
+ szNotBefore[0] = '\0';
+
+ x509 = X509_new ();
+
+ if (x509 != NULL) {
+ pkcs11_openssl_d2i_t d2i = (pkcs11_openssl_d2i_t)pCertificate;
+
+ if (
+ d2i_X509 (&x509, &d2i, nCertificateSize)
+ ) {
+ ASN1_TIME *notBefore = X509_get_notBefore (x509);
+ ASN1_TIME *notAfter = X509_get_notAfter (x509);
+
+ if (
+ notBefore != NULL &&
+ X509_cmp_current_time (notBefore) <= 0 &&
+ X509_cmp_current_time (notAfter) >= 0 &&
+ notBefore->length < nNotBeforeSize - 1
+ ) {
+ memmove (szNotBefore, notBefore->data, notBefore->length);
+ szNotBefore[notBefore->length] = '\0';
+ }
+ }
+ }
+
+ if (x509 != NULL) {
+ X509_free (x509);
+ x509 = NULL;
+ }
+}
+
+static
+PKCS11H_BOOL
+_pkcs11h_isBetterCertificate (
+ IN const unsigned char * const pCurrent,
+ IN const size_t nCurrentSize,
+ IN const unsigned char * const pNew,
+ IN const size_t nNewSize
+) {
+ /*
+ * This function compare the notBefore
+ * and select the most recent certificate
+ * it does not deal with timezones...
+ * When openssl will have ASN1_TIME compare function
+ * it should be used.
+ */
+
+ PKCS11H_BOOL fBetter = FALSE;
+
+ /*PKCS11H_ASSERT (pCurrent!=NULL); NOT NEEDED */
+ PKCS11H_ASSERT (pNew!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_isBetterCertificate entry pCurrent=%p, nCurrentSize=%u, pNew=%p, nNewSize=%u",
+ pCurrent,
+ nCurrentSize,
+ pNew,
+ nNewSize
+ );
+
+ /*
+ * First certificae
+ * always select
+ */
+ if (nCurrentSize == 0 || pCurrent == NULL) {
+ fBetter = TRUE;
+ }
+ else {
+ char szNotBeforeCurrent[1024], szNotBeforeNew[1024];
+
+ _pkcs11h_isBetterCertificate_getExpiration (
+ pCurrent,
+ nCurrentSize,
+ szNotBeforeCurrent,
+ sizeof (szNotBeforeCurrent)
+ );
+ _pkcs11h_isBetterCertificate_getExpiration (
+ pNew,
+ nNewSize,
+ szNotBeforeNew,
+ sizeof (szNotBeforeNew)
+ );
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_isBetterCertificate szNotBeforeCurrent='%s', szNotBeforeNew='%s'",
+ szNotBeforeCurrent,
+ szNotBeforeNew
+ );
+
+ fBetter = strcmp (szNotBeforeCurrent, szNotBeforeNew) < 0;
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_isBetterCertificate return fBetter=%d",
+ fBetter ? 1 : 0
+ );
- if (!strcmp (szId, szSubject)) {
- fSelected = true;
- }
- }
- else {
- fSelected = true;
- }
+ return fBetter;
+}
+
+static
+CK_RV
+_pkcs11h_newCertificateId (
+ OUT pkcs11h_certificate_id_t * const p_certificate_id
+) {
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (p_certificate_id!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_newCertificateId entry p_certificate_id=%p",
+ (void *)p_certificate_id
+ );
+
+ *p_certificate_id = NULL;
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_malloc ((void *)p_certificate_id, sizeof (struct pkcs11h_certificate_id_s));
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_newCertificateId return rv=%ld-'%s', *p_certificate_id=%p",
+ rv,
+ pkcs11h_getMessage (rv),
+ (void *)*p_certificate_id
+ );
+
+ return rv;
+}
+
+static
+CK_RV
+_pkcs11h_loadCertificate (
+ IN const pkcs11h_certificate_t certificate
+) {
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+ CK_OBJECT_CLASS cert_filter_class = CKO_CERTIFICATE;
+ CK_ATTRIBUTE cert_filter[] = {
+ {CKA_CLASS, &cert_filter_class, sizeof (cert_filter_class)},
+ {CKA_ID, NULL, 0}
+ };
+
+ CK_OBJECT_HANDLE *objects = NULL;
+ CK_ULONG objects_found = 0;
+ CK_RV rv = CKR_OK;
+
+ CK_ULONG i;
+
+ PKCS11H_ASSERT (certificate!=NULL);
+ PKCS11H_ASSERT (certificate->id!=NULL);
- if (
- fSelected &&
- _isBetterCertificate (
- selected_certificate,
- selected_certificate_size,
- attrs_value,
- attrs[1].ulValueLen
- )
- ) {
- selected_certificate_size = attrs[1].ulValueLen;
- memmove (
- selected_certificate,
- attrs_value,
- selected_certificate_size
- );
- selected_id_size = attrs[0].ulValueLen;
- memmove (
- selected_id,
- attrs_id,
- selected_id_size
- );
- }
+ /* Must be after assert */
+ cert_filter[1].pValue = certificate->id->attrCKA_ID;
+ cert_filter[1].ulValueLen = certificate->id->attrCKA_ID_size;
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_loadCertificate entry certificate=%p",
+ (void *)certificate
+ );
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_validateSession (certificate->session);
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&certificate->mutexCertificate)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_findObjects (
+ certificate->session,
+ cert_filter,
+ sizeof (cert_filter) / sizeof (CK_ATTRIBUTE),
+ &objects,
+ &objects_found
+ );
+ }
+
+ for (i=0;rv == CKR_OK && i < objects_found;i++) {
+ CK_ATTRIBUTE attrs[] = {
+ {CKA_VALUE, NULL, 0}
+ };
+
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_getObjectAttributes (
+ certificate->session,
+ objects[i],
+ attrs,
+ sizeof (attrs) / sizeof (CK_ATTRIBUTE)
+ )) == CKR_OK
+ ) {
+ if (
+ _pkcs11h_isBetterCertificate (
+ certificate->id->certificate_blob,
+ certificate->id->certificate_blob_size,
+ attrs[0].pValue,
+ attrs[0].ulValueLen
+ )
+ ) {
+ if (certificate->id->certificate_blob != NULL) {
+ _pkcs11h_free ((void *)&certificate->id->certificate_blob);
}
+
+ rv = _pkcs11h_dupmem (
+ (void*)&certificate->id->certificate_blob,
+ &certificate->id->certificate_blob_size,
+ attrs[0].pValue,
+ attrs[0].ulValueLen
+ );
}
}
-
- pkcs11h_certificate->session->provider->f->C_FindObjectsFinal (
- pkcs11h_certificate->session->hSession
+
+ if (rv != CKR_OK) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Cannot get object attribute for provider '%s' object %ld rv=%ld-'%s'",
+ certificate->session->provider->manufacturerID,
+ objects[i],
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ /*
+ * Ignore error
+ */
+ rv = CKR_OK;
+ }
+
+ _pkcs11h_freeObjectAttributes (
+ attrs,
+ sizeof (attrs) / sizeof (CK_ATTRIBUTE)
);
- rv = CKR_OK;
}
-
+
if (
rv == CKR_OK &&
- selected_certificate_size == 0
+ certificate->id->certificate_blob == NULL
) {
rv = CKR_ATTRIBUTE_VALUE_INVALID;
}
+ if (objects != NULL) {
+ _pkcs11h_free ((void *)&objects);
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&certificate->mutexCertificate);
+ fMutexLocked = FALSE;
+ }
+#endif
+
+ /*
+ * No need to free allocated objects
+ * on error, since the certificate_id
+ * should be free by caller.
+ */
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_loadCertificate return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+static
+CK_RV
+_pkcs11h_updateCertificateIdDescription (
+ IN OUT pkcs11h_certificate_id_t certificate_id
+) {
+ static const char * szSeparator = " on ";
+ static const char * szUnknown = "UNKNOWN";
+ X509 *x509 = NULL;
+ pkcs11_openssl_d2i_t d2i1;
+
+ PKCS11H_ASSERT (certificate_id!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_updateCertificateIdDescription entry certificate_id=%p",
+ (void *)certificate_id
+ );
+
+ x509 = X509_new ();
+
+ d2i1 = (pkcs11_openssl_d2i_t)certificate_id->certificate_blob;
+ if (d2i_X509 (&x509, &d2i1, certificate_id->certificate_blob_size)) {
+ X509_NAME_oneline (
+ X509_get_subject_name (x509),
+ certificate_id->displayName,
+ sizeof (certificate_id->displayName)
+ );
+ }
+ else {
+ strncpy (
+ certificate_id->displayName,
+ szUnknown,
+ sizeof (certificate_id->displayName)-1
+ );
+ }
+
+ if (x509 != NULL) {
+ X509_free (x509);
+ x509 = NULL;
+ }
+
+ /*
+ * Try to avoid using snprintf,
+ * may be unavailable
+ */
+ strncat (
+ certificate_id->displayName,
+ szSeparator,
+ sizeof (certificate_id->displayName)-1-strlen (certificate_id->displayName)
+ );
+ strncat (
+ certificate_id->displayName,
+ certificate_id->token_id->label,
+ sizeof (certificate_id->displayName)-1-strlen (certificate_id->displayName)
+ );
+ certificate_id->displayName[sizeof (certificate_id->displayName) - 1] = '\0';
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_updateCertificateIdDescription return displayName=%s",
+ certificate_id->displayName
+ );
+
+ return CKR_OK;
+}
+
+static
+CK_RV
+_pkcs11h_ensureCertificateBlob (
+ IN const pkcs11h_certificate_t certificate
+) {
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+ PKCS11H_BOOL fOpSuccess = FALSE;
+ PKCS11H_BOOL fLoginRetry = FALSE;
+
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (certificate!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_ensureCertificateBlob entry certificate=%p",
+ (void *)certificate
+ );
+
+#if defined(ENABLE_PKCS11H_THREADING)
if (
rv == CKR_OK &&
- (pkcs11h_certificate->certificate_id = (unsigned char *)malloc (selected_id_size)) == NULL
+ (rv = _pkcs11h_mutexLock (&certificate->mutexCertificate)) == CKR_OK
) {
- rv = CKR_HOST_MEMORY;
+ fMutexLocked = TRUE;
}
+#endif
+
+ if (certificate->id->certificate_blob == NULL) {
+ fOpSuccess = FALSE;
+ fLoginRetry = FALSE;
+ while (rv == CKR_OK && !fOpSuccess) {
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_loadCertificate (certificate);
+ }
- if ( /* should be last on none failure */
+ if (rv == CKR_OK) {
+ fOpSuccess = TRUE;
+ }
+ else {
+ if (!fLoginRetry) {
+ fLoginRetry = TRUE;
+ rv = _pkcs11h_resetCertificateSession (
+ certificate,
+ TRUE,
+ (
+ PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT |
+ PKCS11H_PROMPT_MAST_ALLOW_CARD_PROMPT
+ )
+ );
+ }
+ }
+ }
+ }
+
+ if (
rv == CKR_OK &&
- (pkcs11h_certificate->certificate = (unsigned char *)malloc (selected_certificate_size)) == NULL
+ certificate->id->certificate_blob == NULL
) {
- rv = CKR_HOST_MEMORY;
+ rv = CKR_FUNCTION_REJECTED;
}
if (rv == CKR_OK) {
- pkcs11h_certificate->certificate_size = selected_certificate_size;
- memmove (
- pkcs11h_certificate->certificate,
- selected_certificate,
- selected_certificate_size
- );
+ _pkcs11h_updateCertificateIdDescription (certificate->id);
+ }
- pkcs11h_certificate->certificate_id_size = selected_id_size;
- memmove (
- pkcs11h_certificate->certificate_id,
- selected_id,
- selected_id_size
- );
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&certificate->mutexCertificate);
+ fMutexLocked = FALSE;
}
-
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_setCertificateSession_Certificate return rv=%ld-'%s'",
+#endif
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_ensureCertificateBlob return rv=%ld-'%s'",
rv,
pkcs11h_getMessage (rv)
);
@@ -1536,101 +4662,132 @@ _pkcs11h_setCertificateSession_Certificate (
static
CK_RV
_pkcs11h_getCertificateKeyAttributes (
- IN const pkcs11h_certificate_t pkcs11h_certificate
+ IN const pkcs11h_certificate_t certificate
) {
CK_RV rv = CKR_OK;
- CK_BBOOL key_attrs_sign_recover;
- CK_BBOOL key_attrs_sign;
- CK_ATTRIBUTE key_attrs[] = {
- {CKA_SIGN, &key_attrs_sign_recover, sizeof (key_attrs_sign_recover)},
- {CKA_SIGN_RECOVER, &key_attrs_sign, sizeof (key_attrs_sign)}
- };
-
- bool fOpSuccess = false;
- bool fLoginRetry = false;
+ PKCS11H_BOOL fOpSuccess = FALSE;
+ PKCS11H_BOOL fLoginRetry = FALSE;
- PKCS11ASSERT (pkcs11h_certificate!=NULL);
+ PKCS11H_ASSERT (certificate!=NULL);
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_getCertificateKeyAttributes entry pkcs11h_certificate=%p",
- (void *)pkcs11h_certificate
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_getCertificateKeyAttributes entry certificate=%p",
+ (void *)certificate
);
+ certificate->maskSignMode = 0;
+
while (rv == CKR_OK && !fOpSuccess) {
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+ CK_ATTRIBUTE key_attrs[] = {
+ {CKA_SIGN, NULL, 0},
+ {CKA_SIGN_RECOVER, NULL, 0}
+ };
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&certificate->mutexCertificate)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
+ /*
+ * Don't try invalid object
+ */
+ if (
+ rv == CKR_OK &&
+ certificate->hKey == PKCS11H_INVALID_OBJECT_HANDLE
+ ) {
+ rv = CKR_OBJECT_HANDLE_INVALID;
+ }
if (rv == CKR_OK) {
- rv = _pkcs11h_getObjectById (
- pkcs11h_certificate->session,
- CKO_PRIVATE_KEY,
- pkcs11h_certificate->certificate_id,
- pkcs11h_certificate->certificate_id_size,
- &pkcs11h_certificate->hKey
+ if (certificate->session->provider->maskSignMode != 0) {
+ certificate->maskSignMode = certificate->session->provider->maskSignMode;
+ fOpSuccess = TRUE;
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Key attributes enforced by provider (%08x)",
+ certificate->maskSignMode
+ );
+ }
+ }
+
+ if (rv == CKR_OK && !fOpSuccess) {
+ rv = _pkcs11h_getObjectAttributes (
+ certificate->session,
+ certificate->hKey,
+ key_attrs,
+ sizeof (key_attrs) / sizeof (CK_ATTRIBUTE)
);
}
- if (pkcs11h_certificate->signmode == pkcs11h_signmode_none) {
- if (!strcmp (pkcs11h_certificate->session->provider->szSignMode, "recover")) {
- pkcs11h_certificate->signmode = pkcs11h_signmode_recover;
+ if (rv == CKR_OK && !fOpSuccess) {
+ CK_BBOOL *key_attrs_sign = (CK_BBOOL *)key_attrs[0].pValue;
+ CK_BBOOL *key_attrs_sign_recover = (CK_BBOOL *)key_attrs[1].pValue;
+
+ if (key_attrs_sign != NULL && *key_attrs_sign != CK_FALSE) {
+ certificate->maskSignMode |= PKCS11H_SIGNMODE_MASK_SIGN;
}
- else if (!strcmp (pkcs11h_certificate->session->provider->szSignMode, "sign")) {
- pkcs11h_certificate->signmode = pkcs11h_signmode_sign;
+ if (key_attrs_sign_recover != NULL && *key_attrs_sign_recover != CK_FALSE) {
+ certificate->maskSignMode |= PKCS11H_SIGNMODE_MASK_RECOVER;
}
- else {
- if (rv == CKR_OK) {
- rv = pkcs11h_certificate->session->provider->f->C_GetAttributeValue (
- pkcs11h_certificate->session->hSession,
- pkcs11h_certificate->hKey,
- key_attrs,
- sizeof (key_attrs) / sizeof (CK_ATTRIBUTE)
- );
- }
-
- if (rv == CKR_OK) {
- if (key_attrs_sign != CK_FALSE) {
- pkcs11h_certificate->signmode = pkcs11h_signmode_sign;
- }
- else if (key_attrs_sign_recover != CK_FALSE) {
- pkcs11h_certificate->signmode = pkcs11h_signmode_recover;
- }
- else {
- rv = CKR_KEY_TYPE_INCONSISTENT;
- }
-
- PKCS11DLOG (
- PKCS11_LOG_DEBUG1,
- "PKCS#11: Signature mode selected: %d",
- pkcs11h_certificate->signmode
- );
- }
+ if (certificate->maskSignMode == 0) {
+ rv = CKR_KEY_TYPE_INCONSISTENT;
}
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Key attributes loaded (%08x)",
+ certificate->maskSignMode
+ );
}
+ _pkcs11h_freeObjectAttributes (
+ key_attrs,
+ sizeof (key_attrs) / sizeof (CK_ATTRIBUTE)
+ );
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&certificate->mutexCertificate);
+ fMutexLocked = FALSE;
+ }
+#endif
+
if (rv == CKR_OK) {
- fOpSuccess = true;
+ fOpSuccess = TRUE;
}
else {
if (!fLoginRetry) {
- PKCS11DLOG (
- PKCS11_LOG_DEBUG1,
- "PKCS#11: Get key attributes failed: %ld:'%s'",
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Get private key attributes failed: %ld:'%s'",
rv,
pkcs11h_getMessage (rv)
);
- rv = _pkcs11h_login (
- pkcs11h_certificate->session,
- false
+ rv = _pkcs11h_resetCertificateSession (
+ certificate,
+ FALSE,
+ (
+ PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT |
+ PKCS11H_PROMPT_MAST_ALLOW_CARD_PROMPT
+ )
);
- fLoginRetry = true;
+
+ fLoginRetry = TRUE;
}
}
}
-
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
"PKCS#11: _pkcs11h_getCertificateKeyAttributes return rv=%ld-'%s'",
rv,
pkcs11h_getMessage (rv)
@@ -1639,121 +4796,937 @@ _pkcs11h_getCertificateKeyAttributes (
return rv;
}
+static
CK_RV
-_pkcs11h_resetCertificateSession (
- IN const pkcs11h_certificate_t pkcs11h_certificate
+_pkcs11h_validateCertificateSession (
+ IN const pkcs11h_certificate_t certificate
) {
CK_RV rv = CKR_OK;
-
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_resetCertificateSession entry pkcs11h_certificate=%p",
- (void *)pkcs11h_certificate
+
+ PKCS11H_ASSERT (certificate!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_validateCertificateSession entry certificate=%p",
+ (void *)certificate
);
if (rv == CKR_OK) {
- rv = _pkcs11h_login (
- pkcs11h_certificate->session,
- false
- );
+ rv = _pkcs11h_validateSession (certificate->session);
}
if (rv == CKR_OK) {
- /*
- * Will be performed only once
- */
- rv = _pkcs11h_getCertificateKeyAttributes (pkcs11h_certificate);
+ if (certificate->hKey == PKCS11H_INVALID_OBJECT_HANDLE) {
+ rv = CKR_OBJECT_HANDLE_INVALID;
+ }
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_freeCertificateSession return"
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_validateCertificateSession return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
);
- return CKR_OK;
+ return rv;
}
-/*=======================================
- * Simplified PKCS#11 functions
- */
+CK_RV
+_pkcs11h_resetCertificateSession (
+ IN const pkcs11h_certificate_t certificate,
+ IN const PKCS11H_BOOL fPublicOnly,
+ IN const unsigned maskPrompt
+) {
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+ PKCS11H_BOOL fKeyValid = FALSE;
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (certificate!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_resetCertificateSession entry certificate=%p, fPublicOnly=%d, maskPrompt=%08x",
+ (void *)certificate,
+ fPublicOnly ? 1 : 0,
+ maskPrompt
+ );
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&certificate->mutexCertificate)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
+ if (
+ !fKeyValid &&
+ rv == CKR_OK &&
+ certificate->session == NULL &&
+ (rv = _pkcs11h_getSessionByTokenId (certificate->id->token_id, &certificate->session)) == CKR_OK
+ ) {
+ if (certificate->nPINCachePeriod != PKCS11H_PIN_CACHE_INFINITE) {
+ if (certificate->session->nPINCachePeriod != PKCS11H_PIN_CACHE_INFINITE) {
+ if (certificate->session->nPINCachePeriod > certificate->nPINCachePeriod) {
+ certificate->session->timePINExpire = (
+ certificate->session->timePINExpire -
+ (time_t)certificate->session->nPINCachePeriod +
+ (time_t)certificate->nPINCachePeriod
+ );
+ certificate->session->nPINCachePeriod = certificate->nPINCachePeriod;
+ }
+ }
+ else {
+ certificate->session->timePINExpire = (
+ PKCS11H_TIME (NULL) +
+ (time_t)certificate->nPINCachePeriod
+ );
+ certificate->session->nPINCachePeriod = certificate->nPINCachePeriod;
+ }
+ }
+ }
+
+ /*
+ * First, if session seems to be valid
+ * and key handle is invalid (hard-set),
+ * try to fetch key handle,
+ * maybe the token is already logged in
+ */
+ if (rv == CKR_OK) {
+ if (
+ certificate->session->hSession != PKCS11H_INVALID_SESSION_HANDLE &&
+ certificate->hKey == PKCS11H_INVALID_OBJECT_HANDLE &&
+ !fPublicOnly
+ ) {
+ if (
+ (rv = _pkcs11h_getObjectById (
+ certificate->session,
+ CKO_PRIVATE_KEY,
+ certificate->id->attrCKA_ID,
+ certificate->id->attrCKA_ID_size,
+ &certificate->hKey
+ )) == CKR_OK
+ ) {
+ fKeyValid = TRUE;
+ }
+ else {
+ /*
+ * Ignore error
+ */
+ rv = CKR_OK;
+ certificate->hKey = PKCS11H_INVALID_OBJECT_HANDLE;
+ }
+ }
+ }
+
+ if (
+ !fKeyValid &&
+ rv == CKR_OK &&
+ (rv = _pkcs11h_login (
+ certificate->session,
+ fPublicOnly,
+ TRUE,
+ maskPrompt
+ )) == CKR_OK
+ ) {
+ rv = _pkcs11h_updateCertificateIdDescription (certificate->id);
+ }
+
+ if (
+ !fKeyValid &&
+ rv == CKR_OK &&
+ !fPublicOnly &&
+ (rv = _pkcs11h_getObjectById (
+ certificate->session,
+ CKO_PRIVATE_KEY,
+ certificate->id->attrCKA_ID,
+ certificate->id->attrCKA_ID_size,
+ &certificate->hKey
+ )) == CKR_OK
+ ) {
+ fKeyValid = TRUE;
+ }
+
+ if (
+ rv == CKR_OK &&
+ !fPublicOnly &&
+ !fKeyValid
+ ) {
+ rv = CKR_FUNCTION_REJECTED;
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&certificate->mutexCertificate);
+ fMutexLocked = FALSE;
+ }
+#endif
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_resetCertificateSession return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
static
-bool
-_pkcs11h_hooks_card_prompt_default (
- IN const void * pData,
- IN const char * const szLabel
+CK_RV
+_pkcs11h_certificate_private_op (
+ IN const pkcs11h_certificate_t certificate,
+ IN const enum _pkcs11h_private_op_e op,
+ IN const CK_MECHANISM_TYPE mech_type,
+ IN const unsigned char * const source,
+ IN const size_t source_size,
+ OUT unsigned char * const target,
+ IN OUT size_t * const p_target_size
) {
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_hooks_card_prompt_default pData=%p, szLabel=%s",
- pData,
- szLabel
+ CK_MECHANISM mech = {
+ mech_type, NULL, 0
+ };
+
+ CK_RV rv = CKR_OK;
+ PKCS11H_BOOL fLoginRetry = FALSE;
+ PKCS11H_BOOL fOpSuccess = FALSE;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (certificate!=NULL);
+ PKCS11H_ASSERT (source!=NULL);
+ /*PKCS11H_ASSERT (target); NOT NEEDED*/
+ PKCS11H_ASSERT (p_target_size!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_private_op entry certificate=%p, op=%d, mech_type=%ld, source=%p, source_size=%u, target=%p, p_target_size=%p",
+ (void *)certificate,
+ op,
+ mech_type,
+ source,
+ source_size,
+ target,
+ (void *)p_target_size
+ );
+
+ if (target == NULL) {
+ *p_target_size = 0;
+ }
+
+ while (rv == CKR_OK && !fOpSuccess) {
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+
+ if (rv == CKR_OK && !certificate->fOperationActive) {
+ rv = _pkcs11h_validateCertificateSession (certificate);
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&certificate->session->mutexSession)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
+ if (rv == CKR_OK && !certificate->fOperationActive) {
+ switch (op) {
+ case _pkcs11h_private_op_sign:
+ rv = certificate->session->provider->f->C_SignInit (
+ certificate->session->hSession,
+ &mech,
+ certificate->hKey
+ );
+ break;
+ case _pkcs11h_private_op_sign_recover:
+ rv = certificate->session->provider->f->C_SignRecoverInit (
+ certificate->session->hSession,
+ &mech,
+ certificate->hKey
+ );
+ break;
+ case _pkcs11h_private_op_decrypt:
+ rv = certificate->session->provider->f->C_DecryptInit (
+ certificate->session->hSession,
+ &mech,
+ certificate->hKey
+ );
+ break;
+ default:
+ rv = CKR_ARGUMENTS_BAD;
+ break;
+ }
+ }
+
+ if (rv == CKR_OK) {
+ CK_ULONG size = *p_target_size;
+
+ switch (op) {
+ case _pkcs11h_private_op_sign:
+ rv = certificate->session->provider->f->C_Sign (
+ certificate->session->hSession,
+ (CK_BYTE_PTR)source,
+ source_size,
+ (CK_BYTE_PTR)target,
+ &size
+ );
+ break;
+ case _pkcs11h_private_op_sign_recover:
+ rv = certificate->session->provider->f->C_SignRecover (
+ certificate->session->hSession,
+ (CK_BYTE_PTR)source,
+ source_size,
+ (CK_BYTE_PTR)target,
+ &size
+ );
+ break;
+ case _pkcs11h_private_op_decrypt:
+ rv = certificate->session->provider->f->C_Decrypt (
+ certificate->session->hSession,
+ (CK_BYTE_PTR)source,
+ source_size,
+ (CK_BYTE_PTR)target,
+ &size
+ );
+ break;
+ default:
+ rv = CKR_ARGUMENTS_BAD;
+ break;
+ }
+
+ *p_target_size = size;
+ }
+
+ if (
+ target == NULL &&
+ (
+ rv == CKR_BUFFER_TOO_SMALL ||
+ rv == CKR_OK
+ )
+ ) {
+ certificate->fOperationActive = TRUE;
+ rv = CKR_OK;
+ }
+ else {
+ certificate->fOperationActive = FALSE;
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&certificate->session->mutexSession);
+ fMutexLocked = FALSE;
+ }
+#endif
+
+ if (rv == CKR_OK) {
+ fOpSuccess = TRUE;
+ }
+ else {
+ if (!fLoginRetry) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Private key operation failed rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+ fLoginRetry = TRUE;
+ rv = _pkcs11h_resetCertificateSession (
+ certificate,
+ FALSE,
+ (
+ PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT |
+ PKCS11H_PROMPT_MAST_ALLOW_CARD_PROMPT
+ )
+ );
+ }
+ }
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_private_op return rv=%ld-'%s', *p_target_size=%d",
+ rv,
+ pkcs11h_getMessage (rv),
+ *p_target_size
+ );
+
+ return rv;
+}
+
+CK_RV
+pkcs11h_freeCertificateId (
+ IN pkcs11h_certificate_id_t certificate_id
+) {
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (certificate_id!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_freeCertificateId entry certificate_id=%p",
+ (void *)certificate_id
);
- return false;
+ if (certificate_id->attrCKA_ID != NULL) {
+ _pkcs11h_free ((void *)&certificate_id->attrCKA_ID);
+ }
+ if (certificate_id->certificate_blob != NULL) {
+ _pkcs11h_free ((void *)&certificate_id->certificate_blob);
+ }
+ if (certificate_id->token_id != NULL) {
+ pkcs11h_freeTokenId (certificate_id->token_id);
+ certificate_id->token_id = NULL;
+ }
+ _pkcs11h_free ((void *)&certificate_id);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_freeCertificateId return"
+ );
+
+ return CKR_OK;
}
-static
-bool
-_pkcs11h_hooks_pin_prompt_default (
- IN const void * pData,
- IN const char * const szLabel,
- OUT char * const szPIN,
- IN const size_t nMaxPIN
+CK_RV
+pkcs11h_duplicateCertificateId (
+ OUT pkcs11h_certificate_id_t * const to,
+ IN const pkcs11h_certificate_id_t from
) {
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: _pkcs11h_hooks_pin_prompt_default pData=%p, szLabel=%s",
- pData,
- szLabel
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (to!=NULL);
+ PKCS11H_ASSERT (from!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_duplicateCertificateId entry to=%p form=%p",
+ (void *)to,
+ (void *)from
+ );
+
+ *to = NULL;
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_dupmem (
+ (void*)to,
+ NULL,
+ from,
+ sizeof (struct pkcs11h_certificate_id_s)
+ );
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_dupmem (
+ (void*)&(*to)->token_id,
+ NULL,
+ from->token_id,
+ sizeof (struct pkcs11h_token_id_s)
+ );
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_dupmem (
+ (void*)&(*to)->attrCKA_ID,
+ &(*to)->attrCKA_ID_size,
+ from->attrCKA_ID,
+ from->attrCKA_ID_size
+ );
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_dupmem (
+ (void*)&(*to)->certificate_blob,
+ &(*to)->certificate_blob_size,
+ from->certificate_blob,
+ from->certificate_blob_size
+ );
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_duplicateCertificateId return rv=%ld-'%s', *to=%p",
+ rv,
+ pkcs11h_getMessage (rv),
+ (void *)*to
);
- return false;
+ return rv;
}
CK_RV
-pkcs11h_initialize () {
+pkcs11h_freeCertificate (
+ IN pkcs11h_certificate_t certificate
+) {
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_freeCertificate entry certificate=%p",
+ (void *)certificate
+ );
+
+ if (certificate != NULL) {
+ if (certificate->session != NULL) {
+ _pkcs11h_releaseSession (certificate->session);
+ }
+ pkcs11h_freeCertificateId (certificate->id);
+ certificate->id = NULL;
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ _pkcs11h_mutexFree (&certificate->mutexCertificate);
+#endif
+
+ _pkcs11h_free ((void *)&certificate);
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_freeCertificate return"
+ );
+ return CKR_OK;
+}
+
+CK_RV
+pkcs11h_certificate_sign (
+ IN const pkcs11h_certificate_t certificate,
+ IN const CK_MECHANISM_TYPE mech_type,
+ IN const unsigned char * const source,
+ IN const size_t source_size,
+ OUT unsigned char * const target,
+ IN OUT size_t * const p_target_size
+) {
CK_RV rv = CKR_OK;
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_initialize entry"
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (certificate!=NULL);
+ PKCS11H_ASSERT (source!=NULL);
+ /*PKCS11H_ASSERT (target); NOT NEEDED*/
+ PKCS11H_ASSERT (p_target_size!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_sign entry certificate=%p, mech_type=%ld, source=%p, source_size=%u, target=%p, p_target_size=%p",
+ (void *)certificate,
+ mech_type,
+ source,
+ source_size,
+ target,
+ (void *)p_target_size
);
- pkcs11h_terminate ();
+ if (target == NULL) {
+ *p_target_size = 0;
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_certificate_private_op (
+ certificate,
+ _pkcs11h_private_op_sign,
+ mech_type,
+ source,
+ source_size,
+ target,
+ p_target_size
+ );
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_sign return rv=%ld-'%s', *p_target_size=%d",
+ rv,
+ pkcs11h_getMessage (rv),
+ *p_target_size
+ );
+
+ return rv;
+}
+
+CK_RV
+pkcs11h_certificate_signRecover (
+ IN const pkcs11h_certificate_t certificate,
+ IN const CK_MECHANISM_TYPE mech_type,
+ IN const unsigned char * const source,
+ IN const size_t source_size,
+ OUT unsigned char * const target,
+ IN OUT size_t * const p_target_size
+) {
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (certificate!=NULL);
+ PKCS11H_ASSERT (source!=NULL);
+ /*PKCS11H_ASSERT (target); NOT NEEDED*/
+ PKCS11H_ASSERT (p_target_size!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_signRecover entry certificate=%p, mech_type=%ld, source=%p, source_size=%u, target=%p, p_target_size=%p",
+ (void *)certificate,
+ mech_type,
+ source,
+ source_size,
+ target,
+ (void *)p_target_size
+ );
+
+ if (target == NULL) {
+ *p_target_size = 0;
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_certificate_private_op (
+ certificate,
+ _pkcs11h_private_op_sign_recover,
+ mech_type,
+ source,
+ source_size,
+ target,
+ p_target_size
+ );
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_signRecover return rv=%ld-'%s', *p_target_size=%d",
+ rv,
+ pkcs11h_getMessage (rv),
+ *p_target_size
+ );
+
+ return rv;
+}
+
+CK_RV
+pkcs11h_certificate_signAny (
+ IN const pkcs11h_certificate_t certificate,
+ IN const CK_MECHANISM_TYPE mech_type,
+ IN const unsigned char * const source,
+ IN const size_t source_size,
+ OUT unsigned char * const target,
+ IN OUT size_t * const p_target_size
+) {
+ CK_RV rv = CKR_OK;
+ PKCS11H_BOOL fSigned = FALSE;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (certificate!=NULL);
+ PKCS11H_ASSERT (source!=NULL);
+ /*PKCS11H_ASSERT (target); NOT NEEDED*/
+ PKCS11H_ASSERT (p_target_size!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_signAny entry certificate=%p, mech_type=%ld, source=%p, source_size=%u, target=%p, p_target_size=%p",
+ (void *)certificate,
+ mech_type,
+ source,
+ source_size,
+ target,
+ (void *)p_target_size
+ );
if (
rv == CKR_OK &&
- (pkcs11h_data = (pkcs11h_data_t)malloc (sizeof (struct pkcs11h_data_s))) == NULL
+ certificate->maskSignMode == 0
) {
- rv = CKR_HOST_MEMORY;
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Getting key attributes"
+ );
+ rv = _pkcs11h_getCertificateKeyAttributes (certificate);
}
- if (rv == CKR_OK) {
- memset (pkcs11h_data, 0, sizeof (struct pkcs11h_data_s));
+ if (
+ rv == CKR_OK &&
+ !fSigned &&
+ (certificate->maskSignMode & PKCS11H_SIGNMODE_MASK_SIGN) != 0
+ ) {
+ rv = pkcs11h_certificate_sign (
+ certificate,
+ mech_type,
+ source,
+ source_size,
+ target,
+ p_target_size
+ );
+
+ if (rv == CKR_OK) {
+ fSigned = TRUE;
+ }
+ else if (
+ rv == CKR_FUNCTION_NOT_SUPPORTED ||
+ rv == CKR_KEY_FUNCTION_NOT_PERMITTED
+ ) {
+ certificate->maskSignMode &= ~PKCS11H_SIGNMODE_MASK_SIGN;
+ rv = CKR_OK;
+ }
+ }
+
+ if (
+ rv == CKR_OK &&
+ !fSigned &&
+ (certificate->maskSignMode & PKCS11H_SIGNMODE_MASK_RECOVER) != 0
+ ) {
+ rv = pkcs11h_certificate_signRecover (
+ certificate,
+ mech_type,
+ source,
+ source_size,
+ target,
+ p_target_size
+ );
+
+ if (rv == CKR_OK) {
+ fSigned = TRUE;
+ }
+ else if (
+ rv == CKR_FUNCTION_NOT_SUPPORTED ||
+ rv == CKR_KEY_FUNCTION_NOT_PERMITTED
+ ) {
+ certificate->maskSignMode &= ~PKCS11H_SIGNMODE_MASK_RECOVER;
+ rv = CKR_OK;
+ }
+ }
+
+ if (!fSigned) {
+ rv = CKR_FUNCTION_FAILED;
}
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_signAny return rv=%ld-'%s', *p_target_size=%p",
+ rv,
+ pkcs11h_getMessage (rv),
+ (void *)*p_target_size
+ );
+
+ return rv;
+}
+
+CK_RV
+pkcs11h_certificate_decrypt (
+ IN const pkcs11h_certificate_t certificate,
+ IN const CK_MECHANISM_TYPE mech_type,
+ IN const unsigned char * const source,
+ IN const size_t source_size,
+ OUT unsigned char * const target,
+ IN OUT size_t * const p_target_size
+) {
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (certificate!=NULL);
+ PKCS11H_ASSERT (source!=NULL);
+ /*PKCS11H_ASSERT (target); NOT NEEDED*/
+ PKCS11H_ASSERT (p_target_size!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_decrypt entry certificate=%p, mech_type=%ld, source=%p, source_size=%u, target=%p, p_target_size=%p",
+ (void *)certificate,
+ mech_type,
+ source,
+ source_size,
+ target,
+ (void *)p_target_size
+ );
+
+ if (target == NULL) {
+ *p_target_size = 0;
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_certificate_private_op (
+ certificate,
+ _pkcs11h_private_op_decrypt,
+ mech_type,
+ source,
+ source_size,
+ target,
+ p_target_size
+ );
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_decrypt return rv=%ld-'%s', *p_target_size=%d",
+ rv,
+ pkcs11h_getMessage (rv),
+ *p_target_size
+ );
+
+ return rv;
+}
+
+CK_RV
+pkcs11h_certificate_create (
+ IN const pkcs11h_certificate_id_t certificate_id,
+ IN const int nPINCachePeriod,
+ OUT pkcs11h_certificate_t * const p_certificate
+) {
+ pkcs11h_certificate_t certificate = NULL;
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (p_certificate!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_create entry certificate_id=%p, nPINCachePeriod=%d, p_certificate=%p",
+ (void *)certificate_id,
+ nPINCachePeriod,
+ (void *)p_certificate
+ );
+
+ *p_certificate = NULL;
+
if (
rv == CKR_OK &&
- (pkcs11h_data->hooks = (pkcs11h_hooks_t)malloc (sizeof (struct pkcs11h_hooks_s))) == NULL
+ (rv = _pkcs11h_malloc ((void*)&certificate, sizeof (struct pkcs11h_certificate_s))) == CKR_OK
) {
- rv = CKR_HOST_MEMORY;
+ certificate->hKey = PKCS11H_INVALID_OBJECT_HANDLE;
+ certificate->nPINCachePeriod = nPINCachePeriod;
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_mutexInit (&certificate->mutexCertificate);
}
+#endif
if (rv == CKR_OK) {
- memset (pkcs11h_data->hooks, 0, sizeof (struct pkcs11h_hooks_s));
+ rv = pkcs11h_duplicateCertificateId (&certificate->id, certificate_id);
+ }
+
+ if (rv == CKR_OK) {
+ *p_certificate = certificate;
+ certificate = NULL;
+ }
+
+ if (certificate != NULL) {
+#if defined(ENABLE_PKCS11H_THREADING)
+ _pkcs11h_mutexFree (&certificate->mutexCertificate);
+#endif
+ _pkcs11h_free ((void *)&certificate);
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_create return rv=%ld-'%s' *p_certificate=%p",
+ rv,
+ pkcs11h_getMessage (rv),
+ (void *)*p_certificate
+ );
- pkcs11h_data->fInitialized = true;
- pkcs11h_data->nPINCachePeriod = PKCS11H_PIN_CACHE_INFINITE;
+ return rv;
+}
+
+CK_RV
+pkcs11h_certificate_getCertificateId (
+ IN const pkcs11h_certificate_t certificate,
+ OUT pkcs11h_certificate_id_t * const p_certificate_id
+) {
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (certificate!=NULL);
+ PKCS11H_ASSERT (p_certificate_id!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_getCertificateId entry certificate=%p, certificate_id=%p",
+ (void *)certificate,
+ (void *)p_certificate_id
+ );
+
+ if (rv == CKR_OK) {
+ rv = pkcs11h_duplicateCertificateId (
+ p_certificate_id,
+ certificate->id
+ );
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_getCertificateId return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+CK_RV
+pkcs11h_certificate_getCertificateBlob (
+ IN const pkcs11h_certificate_t certificate,
+ OUT unsigned char * const certificate_blob,
+ IN OUT size_t * const p_certificate_blob_size
+) {
+ size_t certifiate_blob_size_max = 0;
+
+ CK_RV rv = CKR_OK;
- pkcs11h_setCardPromptHook (_pkcs11h_hooks_card_prompt_default, NULL);
- pkcs11h_setPINPromptHook (_pkcs11h_hooks_pin_prompt_default, NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (certificate!=NULL);
+ /*PKCS11H_ASSERT (certificate_blob!=NULL); NOT NEEDED */
+ PKCS11H_ASSERT (p_certificate_blob_size!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_getCertificateBlob entry certificate=%p, certificate_blob=%p, p_certificate_blob_size=%p",
+ (void *)certificate,
+ certificate_blob,
+ (void *)p_certificate_blob_size
+ );
+
+ certifiate_blob_size_max = *p_certificate_blob_size;
+ *p_certificate_blob_size = 0;
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_ensureCertificateBlob (certificate);
}
+
+ if (rv == CKR_OK) {
+ *p_certificate_blob_size = certificate->id->certificate_blob_size;
+ }
+
+ if (certificate_blob != NULL) {
+ if (
+ rv == CKR_OK &&
+ certifiate_blob_size_max > certificate->id->certificate_blob_size
+ ) {
+ rv = CKR_BUFFER_TOO_SMALL;
+ }
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_initialize return rv=%ld-'%s'",
+ if (rv == CKR_OK) {
+ memmove (
+ certificate_blob,
+ certificate->id->certificate_blob,
+ *p_certificate_blob_size
+ );
+ }
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_getCertificateBlob return rv=%ld-'%s'",
rv,
pkcs11h_getMessage (rv)
);
@@ -1762,262 +5735,863 @@ pkcs11h_initialize () {
}
CK_RV
-pkcs11h_terminate () {
+pkcs11h_certificate_ensureCertificateAccess (
+ IN const pkcs11h_certificate_t certificate,
+ IN const unsigned maskPrompt
+) {
+ PKCS11H_BOOL fValidCert = FALSE;
+ CK_RV rv = CKR_OK;
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_terminate entry"
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (certificate!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_ensureCertificateAccess entry certificate=%p, maskPrompt=%08x",
+ (void *)certificate,
+ maskPrompt
);
- if (pkcs11h_data != NULL) {
- pkcs11h_provider_t p_last = NULL;
- pkcs11h_session_t s_last = NULL;
+ if (!fValidCert && rv == CKR_OK) {
+ CK_OBJECT_HANDLE h = PKCS11H_INVALID_OBJECT_HANDLE;
- for (
- ;
- pkcs11h_data->sessions != NULL;
- pkcs11h_data->sessions = pkcs11h_data->sessions->next
+ if (
+ (rv = _pkcs11h_getObjectById (
+ certificate->session,
+ CKO_CERTIFICATE,
+ certificate->id->attrCKA_ID,
+ certificate->id->attrCKA_ID_size,
+ &h
+ )) == CKR_OK
) {
- if (s_last != NULL) {
- if (s_last->nReferenceCount == 0) {
- free (s_last);
- }
- }
- s_last = pkcs11h_data->sessions;
-
- _pkcs11h_logout (s_last);
- s_last->fValid = false;
- s_last->provider = NULL;
+ fValidCert = TRUE;
}
- if (s_last != NULL) {
- if (s_last->nReferenceCount == 0) {
- free (s_last);
- }
+ if (rv != CKR_OK) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Cannot access existing object rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ /*
+ * Ignore error
+ */
+ rv = CKR_OK;
}
+ }
- for (
- ;
- pkcs11h_data->providers != NULL;
- pkcs11h_data->providers = pkcs11h_data->providers->next
+ if (!fValidCert && rv == CKR_OK) {
+ if (
+ (rv = _pkcs11h_resetCertificateSession (
+ certificate,
+ TRUE,
+ maskPrompt
+ )) == CKR_OK
) {
- if (p_last != NULL) {
- free (p_last);
- }
- p_last = pkcs11h_data->providers;
-
- if (p_last->szName != NULL) {
- free (p_last->szName);
- p_last->szName = NULL;
- }
+ fValidCert = TRUE;
+ }
+ }
- if (p_last->szSignMode != NULL) {
- free (p_last->szSignMode);
- p_last->szSignMode = NULL;
- }
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_ensureCertificateAccess return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
- if (p_last->fShouldFinalize) {
- p_last->f->C_Finalize (NULL);
- p_last->fShouldFinalize = false;
- }
+ return rv;
+}
- if (p_last->f != NULL) {
- p_last->f = NULL;
- }
-
- if (p_last->hLibrary != NULL) {
-#if defined(WIN32)
- FreeLibrary (p_last->hLibrary);
-#else
- dlclose (p_last->hLibrary);
-#endif
- p_last->hLibrary = NULL;
- }
- }
+CK_RV
+pkcs11h_certificate_ensureKeyAccess (
+ IN const pkcs11h_certificate_t certificate,
+ IN const unsigned maskPrompt
+) {
+ CK_RV rv = CKR_OK;
+ PKCS11H_BOOL fValidKey = FALSE;
- if (p_last != NULL) {
- free (p_last);
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (certificate!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_ensureKeyAccess entry certificate=%p, maskPrompt=%08x",
+ (void *)certificate,
+ maskPrompt
+ );
+
+ if (!fValidKey && rv == CKR_OK) {
+ if (
+ (rv = _pkcs11h_getObjectById (
+ certificate->session,
+ CKO_PRIVATE_KEY,
+ certificate->id->attrCKA_ID,
+ certificate->id->attrCKA_ID_size,
+ &certificate->hKey
+ )) == CKR_OK
+ ) {
+ fValidKey = TRUE;
}
- if (pkcs11h_data->hooks != NULL) {
- free (pkcs11h_data->hooks);
- pkcs11h_data->hooks = NULL;
+ if (rv != CKR_OK) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Cannot access existing object rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ /*
+ * Ignore error
+ */
+ rv = CKR_OK;
+ certificate->hKey = PKCS11H_INVALID_OBJECT_HANDLE;
}
+ }
- free (pkcs11h_data);
- pkcs11h_data = NULL;
+ if (!fValidKey && rv == CKR_OK) {
+ if (
+ (rv = _pkcs11h_resetCertificateSession (
+ certificate,
+ FALSE,
+ maskPrompt
+ )) == CKR_OK
+ ) {
+ fValidKey = TRUE;
+ }
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_terminate return"
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_certificate_ensureKeyAccess return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
);
-
- return CKR_OK;
+
+ return rv;
}
+#endif /* ENABLE_PKCS11H_CERTIFICATE */
+
+#if defined(ENABLE_PKCS11H_LOCATE)
+/*======================================================================*
+ * LOCATE INTERFACE
+ *======================================================================*/
+
+#if defined(ENABLE_PKCS11H_TOKEN) || defined(ENABLE_PKCS11H_CERTIFICATE)
+
+static
CK_RV
-pkcs11h_setPINPromptHook (
- IN const pkcs11h_hook_pin_prompt_t hook,
- IN void * const pData
+_pkcs11h_locate_getTokenIdBySlotId (
+ IN const char * const szSlot,
+ OUT pkcs11h_token_id_t * const p_token_id
) {
- PKCS11ASSERT (pkcs11h_data!=NULL);
- PKCS11ASSERT (pkcs11h_data->fInitialized);
+ pkcs11h_provider_t current_provider = NULL;
+ char szReferenceName[sizeof (((pkcs11h_provider_t)NULL)->szReferenceName)];
- pkcs11h_data->hooks->pin_prompt = hook;
- pkcs11h_data->hooks->pin_prompt_data = pData;
+ CK_SLOT_ID selected_slot = PKCS11H_INVALID_SLOT_ID;
+ CK_TOKEN_INFO info;
+ CK_RV rv = CKR_OK;
- return CKR_OK;
+ PKCS11H_ASSERT (szSlot!=NULL);
+ PKCS11H_ASSERT (p_token_id!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_locate_getTokenIdBySlotId entry szSlot='%s', p_token_id=%p",
+ szSlot,
+ (void *)p_token_id
+ );
+
+ *p_token_id = NULL;
+
+ if (rv == CKR_OK) {
+ if (strchr (szSlot, ':') == NULL) {
+ szReferenceName[0] = '\0';
+ selected_slot = atol (szSlot);
+ }
+ else {
+ char *p;
+
+ strncpy (szReferenceName, szSlot, sizeof (szReferenceName));
+ szReferenceName[sizeof (szReferenceName)-1] = '\0';
+
+ p = strchr (szReferenceName, ':');
+
+ *p = '\0';
+ p++;
+ selected_slot = atol (p);
+ }
+ }
+
+ if (rv == CKR_OK) {
+ current_provider=s_pkcs11h_data->providers;
+ while (
+ current_provider != NULL &&
+ szReferenceName[0] != '\0' && /* So first provider will be selected */
+ strcmp (current_provider->szReferenceName, szReferenceName)
+ ) {
+ current_provider = current_provider->next;
+ }
+
+ if (
+ current_provider == NULL ||
+ (
+ current_provider != NULL &&
+ !current_provider->fEnabled
+ )
+ ) {
+ rv = CKR_SLOT_ID_INVALID;
+ }
+ }
+
+ if (
+ rv == CKR_OK &&
+ (rv = current_provider->f->C_GetTokenInfo (selected_slot, &info)) == CKR_OK
+ ) {
+ rv = _pkcs11h_getTokenId (
+ &info,
+ p_token_id
+ );
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_locate_getTokenIdBySlotId return rv=%ld-'%s', *p_token_id=%p",
+ rv,
+ pkcs11h_getMessage (rv),
+ (void *)*p_token_id
+ );
+
+ return rv;
}
+static
CK_RV
-pkcs11h_setCardPromptHook (
- IN const pkcs11h_hook_card_prompt_t hook,
- IN void * const pData
+_pkcs11h_locate_getTokenIdBySlotName (
+ IN const char * const szName,
+ OUT pkcs11h_token_id_t * const p_token_id
) {
- PKCS11ASSERT (pkcs11h_data!=NULL);
- PKCS11ASSERT (pkcs11h_data->fInitialized);
+ pkcs11h_provider_t current_provider = NULL;
+
+ CK_SLOT_ID selected_slot = PKCS11H_INVALID_SLOT_ID;
+ CK_TOKEN_INFO info;
+ CK_RV rv = CKR_OK;
- pkcs11h_data->hooks->card_prompt = hook;
- pkcs11h_data->hooks->card_prompt_data = pData;
+ PKCS11H_BOOL fFound = FALSE;
- return CKR_OK;
+ PKCS11H_ASSERT (szName!=NULL);
+ PKCS11H_ASSERT (p_token_id!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_locate_getTokenIdBySlotName entry szName='%s', p_token_id=%p",
+ szName,
+ (void *)p_token_id
+ );
+
+ *p_token_id = NULL;
+
+ current_provider = s_pkcs11h_data->providers;
+ while (
+ current_provider != NULL &&
+ rv == CKR_OK &&
+ !fFound
+ ) {
+ CK_SLOT_ID_PTR slots = NULL;
+ CK_ULONG slotnum;
+ CK_SLOT_ID slot_index;
+
+ if (!current_provider->fEnabled) {
+ continue;
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_getSlotList (
+ current_provider,
+ CK_TRUE,
+ &slots,
+ &slotnum
+ );
+ }
+
+ for (
+ slot_index=0;
+ (
+ slot_index < slotnum &&
+ rv == CKR_OK &&
+ !fFound
+ );
+ slot_index++
+ ) {
+ CK_SLOT_INFO info;
+
+ if (
+ (rv = current_provider->f->C_GetSlotInfo (
+ slots[slot_index],
+ &info
+ )) == CKR_OK
+ ) {
+ char szCurrentName[sizeof (info.slotDescription)+1];
+
+ _pkcs11h_fixupFixedString (
+ szCurrentName,
+ (char *)info.slotDescription,
+ sizeof (info.slotDescription)
+ );
+
+ if (!strcmp (szCurrentName, szName)) {
+ fFound = TRUE;
+ selected_slot = slots[slot_index];
+ }
+ }
+
+ if (rv != CKR_OK) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Cannot get slot information for provider '%s' slot %ld rv=%ld-'%s'",
+ current_provider->manufacturerID,
+ slots[slot_index],
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ /*
+ * Ignore error
+ */
+ rv = CKR_OK;
+ }
+ }
+
+ if (rv != CKR_OK) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Cannot get slot list for provider '%s' rv=%ld-'%s'",
+ current_provider->manufacturerID,
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ /*
+ * Ignore error
+ */
+ rv = CKR_OK;
+ }
+
+ if (slots != NULL) {
+ _pkcs11h_free ((void *)&slots);
+ slots = NULL;
+ }
+
+ if (!fFound) {
+ current_provider = current_provider->next;
+ }
+ }
+
+ if (rv == CKR_OK && !fFound) {
+ rv = CKR_SLOT_ID_INVALID;
+ }
+
+ if (
+ rv == CKR_OK &&
+ (rv = current_provider->f->C_GetTokenInfo (selected_slot, &info)) == CKR_OK
+ ) {
+ rv = _pkcs11h_getTokenId (
+ &info,
+ p_token_id
+ );
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_locate_getTokenIdBySlotName return rv=%ld-'%s' *p_token_id=%p",
+ rv,
+ pkcs11h_getMessage (rv),
+ (void *)*p_token_id
+ );
+
+ return rv;
}
+static
CK_RV
-pkcs11h_setPINCachePeriod (
- IN const int nPINCachePeriod
+_pkcs11h_locate_getTokenIdByLabel (
+ IN const char * const szLabel,
+ OUT pkcs11h_token_id_t * const p_token_id
) {
- PKCS11ASSERT (pkcs11h_data!=NULL);
- PKCS11ASSERT (pkcs11h_data->fInitialized);
+ pkcs11h_provider_t current_provider = NULL;
- pkcs11h_data->nPINCachePeriod = nPINCachePeriod;
+ CK_SLOT_ID selected_slot = PKCS11H_INVALID_SLOT_ID;
+ CK_TOKEN_INFO info;
+ CK_RV rv = CKR_OK;
- return CKR_OK;
+ PKCS11H_BOOL fFound = FALSE;
+
+ PKCS11H_ASSERT (szLabel!=NULL);
+ PKCS11H_ASSERT (p_token_id!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_locate_getTokenIdByLabel entry szLabel='%s', p_token_id=%p",
+ szLabel,
+ (void *)p_token_id
+ );
+
+ *p_token_id = NULL;
+
+ current_provider = s_pkcs11h_data->providers;
+ while (
+ current_provider != NULL &&
+ rv == CKR_OK &&
+ !fFound
+ ) {
+ CK_SLOT_ID_PTR slots = NULL;
+ CK_ULONG slotnum;
+ CK_SLOT_ID slot_index;
+
+ if (!current_provider->fEnabled) {
+ continue;
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_getSlotList (
+ current_provider,
+ CK_TRUE,
+ &slots,
+ &slotnum
+ );
+ }
+
+ for (
+ slot_index=0;
+ (
+ slot_index < slotnum &&
+ rv == CKR_OK &&
+ !fFound
+ );
+ slot_index++
+ ) {
+ CK_TOKEN_INFO info;
+
+ if (rv == CKR_OK) {
+ rv = current_provider->f->C_GetTokenInfo (
+ slots[slot_index],
+ &info
+ );
+ }
+
+ if (rv == CKR_OK) {
+ char szCurrentLabel[sizeof (info.label)+1];
+
+ _pkcs11h_fixupFixedString (
+ szCurrentLabel,
+ (char *)info.label,
+ sizeof (info.label)
+ );
+
+ if (!strcmp (szCurrentLabel, szLabel)) {
+ fFound = TRUE;
+ selected_slot = slots[slot_index];
+ }
+ }
+
+ if (rv != CKR_OK) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Cannot get token information for provider '%s' slot %ld rv=%ld-'%s'",
+ current_provider->manufacturerID,
+ slots[slot_index],
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ /*
+ * Ignore error
+ */
+ rv = CKR_OK;
+ }
+ }
+
+ if (rv != CKR_OK) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Cannot get slot list for provider '%s' rv=%ld-'%s'",
+ current_provider->manufacturerID,
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ /*
+ * Ignore error
+ */
+ rv = CKR_OK;
+ }
+
+ if (slots != NULL) {
+ _pkcs11h_free ((void *)&slots);
+ slots = NULL;
+ }
+
+ if (!fFound) {
+ current_provider = current_provider->next;
+ }
+ }
+
+ if (rv == CKR_OK && !fFound) {
+ rv = CKR_SLOT_ID_INVALID;
+ }
+
+ if (
+ rv == CKR_OK &&
+ (rv = current_provider->f->C_GetTokenInfo (selected_slot, &info)) == CKR_OK
+ ) {
+ rv = _pkcs11h_getTokenId (
+ &info,
+ p_token_id
+ );
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_locate_getTokenIdByLabel return rv=%ld-'%s', *p_token_id=%p",
+ rv,
+ pkcs11h_getMessage (rv),
+ (void *)*p_token_id
+ );
+
+ return rv;
}
CK_RV
-pkcs11h_addProvider (
- IN const char * const szProvider,
- IN const char * const szSignMode
+pkcs11h_locate_token (
+ IN const char * const szSlotType,
+ IN const char * const szSlot,
+ OUT pkcs11h_token_id_t * const p_token_id
) {
- pkcs11h_provider_t provider = NULL;
- CK_C_GetFunctionList gfl = NULL;
-#if defined(WIN32)
- int mypid = 0;
-#else
- pid_t mypid = getpid ();
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
#endif
+
+ pkcs11h_token_id_t dummy_token_id = NULL;
+ pkcs11h_token_id_t token_id = NULL;
+ PKCS11H_BOOL fFound = FALSE;
+
CK_RV rv = CKR_OK;
- PKCS11ASSERT (pkcs11h_data!=NULL);
- PKCS11ASSERT (pkcs11h_data->fInitialized);
- PKCS11ASSERT (szProvider!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (szSlotType!=NULL);
+ PKCS11H_ASSERT (szSlot!=NULL);
+ PKCS11H_ASSERT (p_token_id!=NULL);
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_addProvider entry pid=%d, szProvider=%s, szSignMode=%s",
- mypid,
- szProvider,
- szSignMode
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_locate_token entry szSlotType='%s', szSlot='%s', p_token_id=%p",
+ szSlotType,
+ szSlot,
+ (void *)p_token_id
);
+ *p_token_id = NULL;
+
+#if defined(ENABLE_PKCS11H_THREADING)
if (
rv == CKR_OK &&
- (provider = (pkcs11h_provider_t)malloc (sizeof (struct pkcs11h_provider_s))) == NULL
+ (rv = _pkcs11h_mutexLock (&s_pkcs11h_data->mutexGlobal)) == CKR_OK
) {
- rv = CKR_HOST_MEMORY;
+ fMutexLocked = TRUE;
}
+#endif
- if (rv == CKR_OK) {
- memset (provider, 0, sizeof (struct pkcs11h_provider_s));
- provider->szName = strdup (szProvider);
-
- if (szSignMode == NULL) {
- provider->szSignMode = strdup ("auto");
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_newTokenId (&dummy_token_id)) == CKR_OK
+ ) {
+ /*
+ * Temperary slot id
+ */
+ strcpy (dummy_token_id->label, "SLOT(");
+ strncat (dummy_token_id->label, szSlotType, sizeof (dummy_token_id->label)-1-strlen (dummy_token_id->label));
+ strncat (dummy_token_id->label, "=", sizeof (dummy_token_id->label)-1-strlen (dummy_token_id->label));
+ strncat (dummy_token_id->label, szSlot, sizeof (dummy_token_id->label)-1-strlen (dummy_token_id->label));
+ strncat (dummy_token_id->label, ")", sizeof (dummy_token_id->label)-1-strlen (dummy_token_id->label));
+ dummy_token_id->label[sizeof (dummy_token_id->label)-1] = 0;
+ }
+
+ while (rv == CKR_OK && !fFound) {
+ if (!strcmp (szSlotType, "id")) {
+ rv = _pkcs11h_locate_getTokenIdBySlotId (
+ szSlot,
+ &token_id
+ );
+ }
+ else if (!strcmp (szSlotType, "name")) {
+ rv = _pkcs11h_locate_getTokenIdBySlotName (
+ szSlot,
+ &token_id
+ );
+ }
+ else if (!strcmp (szSlotType, "label")) {
+ rv = _pkcs11h_locate_getTokenIdByLabel (
+ szSlot,
+ &token_id
+ );
}
else {
- provider->szSignMode = strdup (szSignMode);
+ rv = CKR_ARGUMENTS_BAD;
}
- if (provider->szSignMode == NULL) {
- rv = CKR_HOST_MEMORY;
+
+ if (rv == CKR_OK) {
+ fFound = TRUE;
}
- }
-
- if (rv == CKR_OK) {
-#if defined(WIN32)
- provider->hLibrary = LoadLibrary (szProvider);
-#else
- provider->hLibrary = dlopen (szProvider, RTLD_NOW);
-#endif
- if (provider->hLibrary == NULL) {
- rv = CKR_FUNCTION_FAILED;
+
+ if (!fFound && rv != CKR_ARGUMENTS_BAD) {
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: pkcs11h_locate_token failed rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ /*
+ * Ignore error
+ */
+ rv = CKR_OK;
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Calling token_prompt hook for '%s'",
+ dummy_token_id->label
+ );
+
+ if (
+ !s_pkcs11h_data->hooks.token_prompt (
+ s_pkcs11h_data->hooks.token_prompt_data,
+ dummy_token_id
+ )
+ ) {
+ rv = CKR_CANCEL;
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: token_prompt returned %ld",
+ rv
+ );
}
}
- if (rv == CKR_OK) {
-#if defined(WIN32)
- gfl = (CK_C_GetFunctionList)GetProcAddress (
- provider->hLibrary,
- "C_GetFunctionList"
- );
-#else
- /*
- * Make compiler happy!
- */
- void *p = dlsym (
- provider->hLibrary,
- "C_GetFunctionList"
- );
- memmove (
- &gfl,
- &p,
- sizeof (void *)
- );
-#endif
- if (gfl == NULL) {
- rv = CKR_FUNCTION_FAILED;
- }
+ if (rv == CKR_OK && !fFound) {
+ rv = CKR_SLOT_ID_INVALID;
}
if (rv == CKR_OK) {
- rv = gfl (&provider->f);
+ *p_token_id = token_id;
+ token_id = NULL;
}
- if (rv == CKR_OK) {
- if ((rv = provider->f->C_Initialize (NULL)) != CKR_OK) {
- if (rv == CKR_CRYPTOKI_ALREADY_INITIALIZED) {
- rv = CKR_OK;
+ if (dummy_token_id != NULL) {
+ pkcs11h_freeTokenId (dummy_token_id);
+ dummy_token_id = NULL;
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&s_pkcs11h_data->mutexGlobal);
+ fMutexLocked = FALSE;
+ }
+#endif
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_locate_token return rv=%ld-'%s', *p_token_id=%p",
+ rv,
+ pkcs11h_getMessage (rv),
+ (void *)*p_token_id
+ );
+
+ return rv;
+}
+
+#endif /* ENABLE_PKCS11H_TOKEN || ENABLE_PKCS11H_CERTIFICATE */
+
+#if defined(ENABLE_PKCS11H_CERTIFICATE)
+
+static
+void
+_pkcs11h_locate_hexToBinary (
+ OUT unsigned char * const target,
+ IN const char * const szSource,
+ IN OUT size_t * const p_target_size
+) {
+ size_t target_max_size;
+ const char *p;
+ char buf[3] = {'\0', '\0', '\0'};
+ int i = 0;
+
+ PKCS11H_ASSERT (szSource!=NULL);
+ PKCS11H_ASSERT (target!=NULL);
+ PKCS11H_ASSERT (p_target_size!=NULL);
+
+ target_max_size = *p_target_size;
+ p = szSource;
+ *p_target_size = 0;
+
+ while (*p != '\0' && *p_target_size < target_max_size) {
+ if (isxdigit (*p)) {
+ buf[i%2] = *p;
+
+ if ((i%2) == 1) {
+ unsigned v;
+ if (sscanf (buf, "%x", &v) != 1) {
+ v = 0;
+ }
+ target[*p_target_size] = v & 0xff;
+ (*p_target_size)++;
}
+
+ i++;
}
- else {
- provider->fShouldFinalize = true;
- }
+ p++;
}
+}
+
+static
+CK_RV
+_pkcs11h_locate_getCertificateIdByLabel (
+ IN const pkcs11h_session_t session,
+ IN OUT const pkcs11h_certificate_id_t certificate_id,
+ IN const char * const szLabel
+) {
+ CK_OBJECT_CLASS cert_filter_class = CKO_CERTIFICATE;
+ CK_ATTRIBUTE cert_filter[] = {
+ {CKA_CLASS, &cert_filter_class, sizeof (cert_filter_class)},
+ {CKA_LABEL, (CK_BYTE_PTR)szLabel, strlen (szLabel)}
+ };
+
+ CK_OBJECT_HANDLE *objects = NULL;
+ CK_ULONG objects_found = 0;
+ CK_RV rv = CKR_OK;
+
+ CK_ULONG i;
+
+ PKCS11H_ASSERT (session!=NULL);
+ PKCS11H_ASSERT (certificate_id!=NULL);
+ PKCS11H_ASSERT (szLabel!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_locate_getCertificateIdByLabel entry session=%p, certificate_id=%p, szLabel='%s'",
+ (void *)session,
+ (void *)certificate_id,
+ szLabel
+ );
if (rv == CKR_OK) {
- provider->fEnabled = true;
+ rv = _pkcs11h_validateSession (session);
}
- if (provider != NULL) {
- if (pkcs11h_data->providers == NULL) {
- pkcs11h_data->providers = provider;
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_findObjects (
+ session,
+ cert_filter,
+ sizeof (cert_filter) / sizeof (CK_ATTRIBUTE),
+ &objects,
+ &objects_found
+ );
+ }
+
+ for (i=0;rv == CKR_OK && i < objects_found;i++) {
+ CK_ATTRIBUTE attrs[] = {
+ {CKA_ID, NULL, 0},
+ {CKA_VALUE, NULL, 0}
+ };
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_getObjectAttributes (
+ session,
+ objects[i],
+ attrs,
+ sizeof (attrs) / sizeof (CK_ATTRIBUTE)
+ );
}
- else {
- pkcs11h_provider_t last = NULL;
-
- for (
- last = pkcs11h_data->providers;
- last->next != NULL;
- last = last->next
+
+ if (
+ rv == CKR_OK &&
+ _pkcs11h_isBetterCertificate (
+ certificate_id->certificate_blob,
+ certificate_id->certificate_blob_size,
+ attrs[1].pValue,
+ attrs[1].ulValueLen
+ )
+ ) {
+ if (certificate_id->attrCKA_ID != NULL) {
+ _pkcs11h_free ((void *)&certificate_id->attrCKA_ID);
+ }
+ if (certificate_id->certificate_blob != NULL) {
+ _pkcs11h_free ((void *)&certificate_id->certificate_blob);
+ }
+ rv = _pkcs11h_dupmem (
+ (void *)&certificate_id->attrCKA_ID,
+ &certificate_id->attrCKA_ID_size,
+ attrs[0].pValue,
+ attrs[0].ulValueLen
);
- last->next = provider;
+ rv = _pkcs11h_dupmem (
+ (void *)&certificate_id->certificate_blob,
+ &certificate_id->certificate_blob_size,
+ attrs[1].pValue,
+ attrs[1].ulValueLen
+ );
+ }
+
+ if (rv != CKR_OK) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Cannot get object attribute for provider '%s' object %ld rv=%ld-'%s'",
+ session->provider->manufacturerID,
+ objects[i],
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ /*
+ * Ignore error
+ */
+ rv = CKR_OK;
}
+
+ _pkcs11h_freeObjectAttributes (
+ attrs,
+ sizeof (attrs) / sizeof (CK_ATTRIBUTE)
+ );
+ }
+
+ if (
+ rv == CKR_OK &&
+ certificate_id->certificate_blob == NULL
+ ) {
+ rv = CKR_ATTRIBUTE_VALUE_INVALID;
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_addProvider return rv=%ld-'%s'",
+ if (objects != NULL) {
+ _pkcs11h_free ((void *)&objects);
+ }
+
+ /*
+ * No need to free allocated objects
+ * on error, since the certificate_id
+ * should be free by caller.
+ */
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_locate_getCertificateIdByLabel return rv=%ld-'%s'",
rv,
pkcs11h_getMessage (rv)
);
@@ -2025,371 +6599,1001 @@ pkcs11h_addProvider (
return rv;
}
+static
CK_RV
-pkcs11h_forkFixup () {
-#if defined(WIN32)
- int mypid = 0;
-#else
- pid_t mypid = getpid ();
-#endif
+_pkcs11h_locate_getCertificateIdBySubject (
+ IN const pkcs11h_session_t session,
+ IN OUT const pkcs11h_certificate_id_t certificate_id,
+ IN const char * const szSubject
+) {
+ CK_OBJECT_CLASS cert_filter_class = CKO_CERTIFICATE;
+ CK_ATTRIBUTE cert_filter[] = {
+ {CKA_CLASS, &cert_filter_class, sizeof (cert_filter_class)}
+ };
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_forkFixup entry pid=%d",
- mypid
+ CK_OBJECT_HANDLE *objects = NULL;
+ CK_ULONG objects_found = 0;
+ CK_RV rv = CKR_OK;
+
+ CK_ULONG i;
+
+ PKCS11H_ASSERT (session!=NULL);
+ PKCS11H_ASSERT (certificate_id!=NULL);
+ PKCS11H_ASSERT (szSubject!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_locate_getCertificateIdBySubject entry session=%p, certificate_id=%p, szSubject=%s",
+ (void *)session,
+ (void *)certificate_id,
+ szSubject
);
- if (pkcs11h_data != NULL && pkcs11h_data->fInitialized) {
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_validateSession (session);
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_findObjects (
+ session,
+ cert_filter,
+ sizeof (cert_filter) / sizeof (CK_ATTRIBUTE),
+ &objects,
+ &objects_found
+ );
+ }
- pkcs11h_provider_t current;
+ for (i=0;rv == CKR_OK && i < objects_found;i++) {
+ CK_ATTRIBUTE attrs[] = {
+ {CKA_ID, NULL, 0},
+ {CKA_VALUE, NULL, 0}
+ };
+ char szCurrentSubject[1024];
+ szCurrentSubject[0] = '\0';
- for (
- current = pkcs11h_data->providers;
- current != NULL;
- current = current->next
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_getObjectAttributes (
+ session,
+ objects[i],
+ attrs,
+ sizeof (attrs) / sizeof (CK_ATTRIBUTE)
+ );
+ }
+
+ if (rv == CKR_OK) {
+ X509 *x509 = NULL;
+ pkcs11_openssl_d2i_t d2i1;
+
+ x509 = X509_new ();
+
+ d2i1 = (pkcs11_openssl_d2i_t)attrs[1].pValue;
+ if (d2i_X509 (&x509, &d2i1, attrs[1].ulValueLen)) {
+ X509_NAME_oneline (
+ X509_get_subject_name (x509),
+ szCurrentSubject,
+ sizeof (szCurrentSubject)
+ );
+ szCurrentSubject[sizeof (szCurrentSubject) - 1] = '\0';
+ }
+
+ if (x509 != NULL) {
+ X509_free (x509);
+ x509 = NULL;
+ }
+ }
+
+ if (
+ rv == CKR_OK &&
+ !strcmp (szSubject, szCurrentSubject) &&
+ _pkcs11h_isBetterCertificate (
+ certificate_id->certificate_blob,
+ certificate_id->certificate_blob_size,
+ attrs[1].pValue,
+ attrs[1].ulValueLen
+ )
) {
- if (current->fEnabled) {
- current->f->C_Initialize (NULL);
+ if (certificate_id->attrCKA_ID != NULL) {
+ _pkcs11h_free ((void *)&certificate_id->attrCKA_ID);
+ }
+ if (certificate_id->certificate_blob != NULL) {
+ _pkcs11h_free ((void *)&certificate_id->certificate_blob);
}
+ rv = _pkcs11h_dupmem (
+ (void *)&certificate_id->attrCKA_ID,
+ &certificate_id->attrCKA_ID_size,
+ attrs[0].pValue,
+ attrs[0].ulValueLen
+ );
+ rv = _pkcs11h_dupmem (
+ (void *)&certificate_id->certificate_blob,
+ &certificate_id->certificate_blob_size,
+ attrs[1].pValue,
+ attrs[1].ulValueLen
+ );
+ }
+
+ if (rv != CKR_OK) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Cannot get object attribute for provider '%s' object %ld rv=%ld-'%s'",
+ session->provider->manufacturerID,
+ objects[i],
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ /*
+ * Ignore error
+ */
+ rv = CKR_OK;
}
+
+ _pkcs11h_freeObjectAttributes (
+ attrs,
+ sizeof (attrs) / sizeof (CK_ATTRIBUTE)
+ );
+ }
+
+ if (
+ rv == CKR_OK &&
+ certificate_id->certificate_blob == NULL
+ ) {
+ rv = CKR_ATTRIBUTE_VALUE_INVALID;
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_forkFixup return"
+ if (objects != NULL) {
+ _pkcs11h_free ((void *)&objects);
+ }
+
+ /*
+ * No need to free allocated objects
+ * on error, since the certificate_id
+ * should be free by caller.
+ */
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_locate_getCertificateIdBySubject return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
);
- return CKR_OK;
+ return rv;
}
CK_RV
-pkcs11h_createCertificateSession (
+pkcs11h_locate_certificate (
IN const char * const szSlotType,
IN const char * const szSlot,
IN const char * const szIdType,
IN const char * const szId,
- IN const bool fProtectedAuthentication,
- IN const bool fCertPrivate,
- IN const int nPINCachePeriod,
- OUT pkcs11h_certificate_t * const p_pkcs11h_certificate
+ OUT pkcs11h_certificate_id_t * const p_certificate_id
) {
- pkcs11h_certificate_t pkcs11h_certificate = NULL;
+ pkcs11h_certificate_id_t certificate_id = NULL;
+ pkcs11h_session_t session = NULL;
+ PKCS11H_BOOL fOpSuccess = FALSE;
+ PKCS11H_BOOL fLoginRetry = FALSE;
+
CK_RV rv = CKR_OK;
- bool fOpSuccess = false;
- bool fLogonRetry = false;
-
- PKCS11ASSERT (pkcs11h_data!=NULL);
- PKCS11ASSERT (pkcs11h_data->fInitialized);
- PKCS11ASSERT (szSlotType!=NULL);
- PKCS11ASSERT (szSlot!=NULL);
- PKCS11ASSERT (szIdType!=NULL);
- PKCS11ASSERT (szId!=NULL);
- PKCS11ASSERT (p_pkcs11h_certificate!=NULL);
-
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_createSession entry szSlotType=%s, szSlot=%s, szIdType=%s, szId=%s, fProtectedAuthentication=%d, fCertPrivate=%d, nPINCachePeriod=%d, p_pkcs11h_certificate=%p",
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (szSlotType!=NULL);
+ PKCS11H_ASSERT (szSlot!=NULL);
+ PKCS11H_ASSERT (szIdType!=NULL);
+ PKCS11H_ASSERT (szId!=NULL);
+ PKCS11H_ASSERT (p_certificate_id!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_locateCertificate entry szSlotType='%s', szSlot='%s', szIdType='%s', szId='%s', p_certificate_id=%p",
szSlotType,
szSlot,
szIdType,
szId,
- fProtectedAuthentication ? 1 : 0,
- fCertPrivate ? 1 : 0,
- nPINCachePeriod,
- (void *)p_pkcs11h_certificate
+ (void *)p_certificate_id
);
- if (
- rv == CKR_OK &&
- (pkcs11h_certificate = (pkcs11h_certificate_t)malloc (sizeof (struct pkcs11h_certificate_s))) == NULL
- ) {
- rv = CKR_HOST_MEMORY;
- }
+ *p_certificate_id = NULL;
if (rv == CKR_OK) {
- *p_pkcs11h_certificate = pkcs11h_certificate;
- memset (pkcs11h_certificate, 0, sizeof (struct pkcs11h_certificate_s));
- }
-
- if (rv == CKR_OK) {
- pkcs11h_certificate->hKey = PKCS11H_INVALID_OBJECT_HANDLE;
- pkcs11h_certificate->fCertPrivate = fCertPrivate;
+ rv = _pkcs11h_newCertificateId (&certificate_id);
}
if (rv == CKR_OK) {
- rv = _pkcs11h_getSession (
+ rv = pkcs11h_locate_token (
szSlotType,
szSlot,
- fProtectedAuthentication,
- nPINCachePeriod,
- &pkcs11h_certificate->session
+ &certificate_id->token_id
+ );
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_getSessionByTokenId (
+ certificate_id->token_id,
+ &session
);
}
- fOpSuccess = false;
- fLogonRetry = false;
while (rv == CKR_OK && !fOpSuccess) {
- if (rv == CKR_OK) {
- /*
- * Don't repeat this if succeeded in
- * unauthenticated session
- */
- if (pkcs11h_certificate->certificate == NULL) {
- rv = _pkcs11h_setCertificateSession_Certificate (
- pkcs11h_certificate,
- szIdType,
- szId
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&s_pkcs11h_data->mutexGlobal)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
+ if (!strcmp (szIdType, "id")) {
+ certificate_id->attrCKA_ID_size = strlen (szId)/2;
+
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_malloc (
+ (void*)&certificate_id->attrCKA_ID,
+ certificate_id->attrCKA_ID_size
+ )) == CKR_OK
+ ) {
+ _pkcs11h_locate_hexToBinary (
+ certificate_id->attrCKA_ID,
+ szId,
+ &certificate_id->attrCKA_ID_size
);
}
}
+ else if (!strcmp (szIdType, "label")) {
+ rv = _pkcs11h_locate_getCertificateIdByLabel (
+ session,
+ certificate_id,
+ szId
+ );
+ }
+ else if (!strcmp (szIdType, "subject")) {
+ rv = _pkcs11h_locate_getCertificateIdBySubject (
+ session,
+ certificate_id,
+ szId
+ );
+ }
+ else {
+ rv = CKR_ARGUMENTS_BAD;
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&s_pkcs11h_data->mutexGlobal);
+ fMutexLocked = FALSE;
+ }
+#endif
if (rv == CKR_OK) {
- fOpSuccess = true;
+ fOpSuccess = TRUE;
}
else {
- if (!fLogonRetry) {
- fLogonRetry = true;
+ if (!fLoginRetry) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Get certificate failed: %ld:'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
rv = _pkcs11h_login (
- pkcs11h_certificate->session,
- !pkcs11h_certificate->fCertPrivate
+ session,
+ TRUE,
+ TRUE,
+ (
+ PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT |
+ PKCS11H_PROMPT_MAST_ALLOW_CARD_PROMPT
+ )
);
+
+ fLoginRetry = TRUE;
}
}
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_createSession return rv=%ld-'%s'",
+ if (rv == CKR_OK) {
+ *p_certificate_id = certificate_id;
+ certificate_id = NULL;
+ }
+
+ if (certificate_id != NULL) {
+ pkcs11h_freeCertificateId (certificate_id);
+ certificate_id = NULL;
+ }
+
+ if (session != NULL) {
+ _pkcs11h_releaseSession (session);
+ session = NULL;
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_locateCertificate return rv=%ld-'%s' *p_certificate_id=%p",
rv,
- pkcs11h_getMessage (rv)
+ pkcs11h_getMessage (rv),
+ (void *)*p_certificate_id
);
return rv;
}
+#endif /* ENABLE_PKCS11H_CERTIFICATE */
+
+#endif /* ENABLE_PKCS11H_LOCATE */
+
+#if defined(ENABLE_PKCS11H_ENUM)
+/*======================================================================*
+ * ENUM INTERFACE
+ *======================================================================*/
+
+#if defined(ENABLE_PKCS11H_TOKEN)
+
+CK_RV
+pkcs11h_freeTokenIdList (
+ IN const pkcs11h_token_id_list_t token_id_list
+) {
+ pkcs11h_token_id_list_t _id = token_id_list;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ /*PKCS11H_ASSERT (token_id_list!=NULL); NOT NEEDED*/
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_freeTokenIdList entry token_id_list=%p",
+ (void *)token_id_list
+ );
+
+ while (_id != NULL) {
+ pkcs11h_token_id_list_t x = _id;
+ _id = _id->next;
+ if (x->token_id != NULL) {
+ pkcs11h_freeTokenId (x->token_id);
+ }
+ x->next = NULL;
+ _pkcs11h_free ((void *)&x);
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_freeTokenIdList return"
+ );
+
+ return CKR_OK;
+}
+
CK_RV
-pkcs11h_freeCertificateSession (
- IN const pkcs11h_certificate_t pkcs11h_certificate
+pkcs11h_enum_getTokenIds (
+ IN const int method,
+ OUT pkcs11h_token_id_list_t * const p_token_id_list
) {
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_freeCertificateSession entry pkcs11h_certificate=%p",
- (void *)pkcs11h_certificate
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+
+ pkcs11h_token_id_list_t token_id_list = NULL;
+ pkcs11h_provider_t current_provider;
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (p_token_id_list!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_enum_getTokenIds entry p_token_id_list=%p",
+ (void *)p_token_id_list
);
- if (pkcs11h_certificate != NULL) {
- if (pkcs11h_certificate->session != NULL) {
- _pkcs11h_releaseSession (pkcs11h_certificate->session);
+ *p_token_id_list = NULL;
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&s_pkcs11h_data->mutexGlobal)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
+ for (
+ current_provider = s_pkcs11h_data->providers;
+ (
+ current_provider != NULL &&
+ rv == CKR_OK
+ );
+ current_provider = current_provider->next
+ ) {
+ CK_SLOT_ID_PTR slots = NULL;
+ CK_ULONG slotnum;
+ CK_SLOT_ID slot_index;
+
+ if (!current_provider->fEnabled) {
+ continue;
}
- if (pkcs11h_certificate->certificate != NULL) {
- free (pkcs11h_certificate->certificate);
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_getSlotList (
+ current_provider,
+ CK_TRUE,
+ &slots,
+ &slotnum
+ );
}
- if (pkcs11h_certificate->certificate_id != NULL) {
- free (pkcs11h_certificate->certificate_id);
+
+ for (
+ slot_index=0;
+ (
+ slot_index < slotnum &&
+ rv == CKR_OK
+ );
+ slot_index++
+ ) {
+ pkcs11h_token_id_list_t entry = NULL;
+ CK_TOKEN_INFO info;
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_malloc ((void *)&entry, sizeof (struct pkcs11h_token_id_list_s));
+ }
+
+ if (rv == CKR_OK) {
+ rv = current_provider->f->C_GetTokenInfo (
+ slots[slot_index],
+ &info
+ );
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_getTokenId (
+ &info,
+ &entry->token_id
+ );
+ }
+
+ if (rv == CKR_OK) {
+ entry->next = token_id_list;
+ token_id_list = entry;
+ entry = NULL;
+ }
+
+ if (entry != NULL) {
+ pkcs11h_freeTokenIdList (entry);
+ entry = NULL;
+ }
+ }
+
+ if (rv != CKR_OK) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Cannot get slot list for provider '%s' rv=%ld-'%s'",
+ current_provider->manufacturerID,
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ /*
+ * Ignore error
+ */
+ rv = CKR_OK;
+ }
+
+ if (slots != NULL) {
+ _pkcs11h_free ((void *)&slots);
+ slots = NULL;
+ }
+ }
+
+ if (rv == CKR_OK && method == PKCS11H_ENUM_METHOD_CACHE) {
+ pkcs11h_session_t session = NULL;
+
+ for (
+ session = s_pkcs11h_data->sessions;
+ session != NULL && rv == CKR_OK;
+ session = session->next
+ ) {
+ pkcs11h_token_id_list_t entry = NULL;
+ PKCS11H_BOOL fFound = FALSE;
+
+ for (
+ entry = token_id_list;
+ entry != NULL && !fFound;
+ entry = entry->next
+ ) {
+ if (
+ pkcs11h_sameTokenId (
+ session->token_id,
+ entry->token_id
+ )
+ ) {
+ fFound = TRUE;
+ }
+ }
+
+ if (!fFound) {
+ entry = NULL;
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_malloc (
+ (void *)&entry,
+ sizeof (struct pkcs11h_token_id_list_s)
+ );
+ }
+
+ if (rv == CKR_OK) {
+ rv = pkcs11h_duplicateTokenId (
+ &entry->token_id,
+ session->token_id
+ );
+ }
+
+ if (rv == CKR_OK) {
+ entry->next = token_id_list;
+ token_id_list = entry;
+ entry = NULL;
+ }
+
+ if (entry != NULL) {
+ if (entry->token_id != NULL) {
+ pkcs11h_freeTokenId (entry->token_id);
+ }
+ _pkcs11h_free ((void *)&entry);
+ }
+ }
}
+ }
- free (pkcs11h_certificate);
+ if (rv == CKR_OK) {
+ *p_token_id_list = token_id_list;
+ token_id_list = NULL;
+ }
+
+ if (token_id_list != NULL) {
+ pkcs11h_freeTokenIdList (token_id_list);
+ token_id_list = NULL;
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_freeCertificateSession return"
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ rv = _pkcs11h_mutexRelease (&s_pkcs11h_data->mutexGlobal);
+ fMutexLocked = FALSE;
+ }
+#endif
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_enum_getTokenIds return rv=%ld-'%s', *p_token_id_list=%p",
+ rv,
+ pkcs11h_getMessage (rv),
+ (void *)p_token_id_list
+ );
+
+ return rv;
+}
+
+#endif
+
+#if defined(ENABLE_PKCS11H_DATA)
+
+CK_RV
+pkcs11h_freeDataIdList (
+ IN const pkcs11h_data_id_list_t data_id_list
+) {
+ pkcs11h_data_id_list_t _id = data_id_list;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ /*PKCS11H_ASSERT (data_id_list!=NULL); NOT NEEDED*/
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_freeDataIdList entry token_id_list=%p",
+ (void *)data_id_list
+ );
+
+ while (_id != NULL) {
+ pkcs11h_data_id_list_t x = _id;
+ _id = _id->next;
+
+ if (x->application != NULL) {
+ _pkcs11h_free ((void *)&x->application);
+ }
+ if (x->label != NULL) {
+ _pkcs11h_free ((void *)&x->label);
+ }
+ _pkcs11h_free ((void *)&x);
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_freeDataIdList return"
);
return CKR_OK;
}
CK_RV
-pkcs11h_sign (
- IN const pkcs11h_certificate_t pkcs11h_certificate,
- IN const CK_MECHANISM_TYPE mech_type,
- IN const unsigned char * const source,
- IN const size_t source_size,
- OUT unsigned char * const target,
- IN OUT size_t * const target_size
+pkcs11h_enumDataObjects (
+ IN const pkcs11h_token_id_t token_id,
+ IN const PKCS11H_BOOL fPublic,
+ OUT pkcs11h_data_id_list_t * const p_data_id_list
) {
- CK_MECHANISM mech = {
- mech_type, NULL, 0
- };
-
+ pkcs11h_session_t session = NULL;
+ pkcs11h_data_id_list_t data_id_list = NULL;
CK_RV rv = CKR_OK;
- bool fLogonRetry = false;
- bool fOpSuccess = false;
- PKCS11ASSERT (pkcs11h_data!=NULL);
- PKCS11ASSERT (pkcs11h_data->fInitialized);
- PKCS11ASSERT (pkcs11h_certificate!=NULL);
- PKCS11ASSERT (source!=NULL);
- PKCS11ASSERT (target_size!=NULL);
+ PKCS11H_BOOL fOpSuccess = FALSE;
+ PKCS11H_BOOL fLoginRetry = FALSE;
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_sign entry pkcs11h_certificate=%p, mech_type=%ld, source=%p, source_size=%u, target=%p, target_size=%p",
- (void *)pkcs11h_certificate,
- mech_type,
- source,
- source_size,
- target,
- (void *)target_size
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (p_data_id_list!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_enumDataObjects entry p_data_id_list=%p",
+ (void *)p_data_id_list
);
+ *p_data_id_list = NULL;
+
if (rv == CKR_OK) {
- rv = _pkcs11h_validateSession (pkcs11h_certificate->session);
+ rv = _pkcs11h_getSessionByTokenId (
+ token_id,
+ &session
+ );
}
while (rv == CKR_OK && !fOpSuccess) {
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
- /*
- * Don't try invalid object
- */
+ CK_OBJECT_CLASS class = CKO_DATA;
+ CK_ATTRIBUTE filter[] = {
+ {CKA_CLASS, (void *)&class, sizeof (class)}
+ };
+ CK_OBJECT_HANDLE *objects = NULL;
+ CK_ULONG objects_found = 0;
+
+ CK_ULONG i;
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_validateSession (session);
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
if (
rv == CKR_OK &&
- pkcs11h_certificate->hKey == PKCS11H_INVALID_OBJECT_HANDLE
+ (rv = _pkcs11h_mutexLock (&session->mutexSession)) == CKR_OK
) {
- rv = CKR_OBJECT_HANDLE_INVALID;
+ fMutexLocked = TRUE;
}
+#endif
if (rv == CKR_OK) {
- rv = pkcs11h_certificate->session->provider->f->C_SignInit (
- pkcs11h_certificate->session->hSession,
- &mech,
- pkcs11h_certificate->hKey
+ rv = _pkcs11h_findObjects (
+ session,
+ filter,
+ sizeof (filter) / sizeof (CK_ATTRIBUTE),
+ &objects,
+ &objects_found
);
}
- if (rv == CKR_OK) {
- CK_ULONG size = *target_size;
- rv = pkcs11h_certificate->session->provider->f->C_Sign (
- pkcs11h_certificate->session->hSession,
- (CK_BYTE_PTR)source,
- source_size,
- (CK_BYTE_PTR)target,
- &size
+ for (i = 0;rv == CKR_OK && i < objects_found;i++) {
+ pkcs11h_data_id_list_t entry = NULL;
+
+ CK_ATTRIBUTE attrs[] = {
+ {CKA_APPLICATION, NULL, 0},
+ {CKA_LABEL, NULL, 0}
+ };
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_getObjectAttributes (
+ session,
+ objects[i],
+ attrs,
+ sizeof (attrs) / sizeof (CK_ATTRIBUTE)
+ );
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_malloc (
+ (void *)&entry,
+ sizeof (struct pkcs11h_data_id_list_s)
+ );
+ }
+
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_malloc (
+ (void *)&entry->application,
+ attrs[0].ulValueLen+1
+ )) == CKR_OK
+ ) {
+ memmove (entry->application, attrs[0].pValue, attrs[0].ulValueLen);
+ entry->application[attrs[0].ulValueLen] = '\0';
+ }
+
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_malloc (
+ (void *)&entry->label,
+ attrs[1].ulValueLen+1
+ )) == CKR_OK
+ ) {
+ memmove (entry->label, attrs[1].pValue, attrs[1].ulValueLen);
+ entry->label[attrs[1].ulValueLen] = '\0';
+ }
+
+ if (rv == CKR_OK) {
+ entry->next = data_id_list;
+ data_id_list = entry;
+ entry = NULL;
+ }
+
+ _pkcs11h_freeObjectAttributes (
+ attrs,
+ sizeof (attrs) / sizeof (CK_ATTRIBUTE)
);
- *target_size = (int)size;
+ if (entry != NULL) {
+ if (entry->application != NULL) {
+ _pkcs11h_free ((void *)&entry->application);
+ }
+ if (entry->label != NULL) {
+ _pkcs11h_free ((void *)&entry->label);
+ }
+ _pkcs11h_free ((void *)&entry);
+ }
+ }
+
+ if (objects != NULL) {
+ _pkcs11h_free ((void *)&objects);
}
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&session->mutexSession);
+ fMutexLocked = FALSE;
+ }
+#endif
if (rv == CKR_OK) {
- fOpSuccess = true;
+ fOpSuccess = TRUE;
}
else {
- if (!fLogonRetry) {
- PKCS11DLOG (
- PKCS11_LOG_DEBUG1,
- "PKCS#11: Private key operation failed rv=%ld-'%s'",
+ if (!fLoginRetry) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Enumerate data objects failed rv=%ld-'%s'",
rv,
pkcs11h_getMessage (rv)
);
- fLogonRetry = true;
- rv = _pkcs11h_resetCertificateSession (pkcs11h_certificate);
+ fLoginRetry = TRUE;
+ rv = _pkcs11h_login (
+ session,
+ fPublic,
+ TRUE,
+ (
+ PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT |
+ PKCS11H_PROMPT_MAST_ALLOW_CARD_PROMPT
+ )
+ );
}
}
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_sign return rv=%ld-'%s'",
+ if (rv == CKR_OK) {
+ *p_data_id_list = data_id_list;
+ data_id_list = NULL;
+ }
+
+ if (session != NULL) {
+ _pkcs11h_releaseSession (session);
+ session = NULL;
+ }
+
+ if (data_id_list != NULL) {
+ pkcs11h_freeDataIdList (data_id_list);
+ data_id_list = NULL;
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_data_id_list_t return rv=%ld-'%s', *p_data_id_list=%p",
rv,
- pkcs11h_getMessage (rv)
+ pkcs11h_getMessage (rv),
+ (void *)*p_data_id_list
);
return rv;
}
+#endif /* ENABLE_PKCS11H_DATA */
+
+#if defined(ENABLE_PKCS11H_CERTIFICATE)
+
+static
CK_RV
-pkcs11h_signRecover (
- IN const pkcs11h_certificate_t pkcs11h_certificate,
- IN const CK_MECHANISM_TYPE mech_type,
- IN const unsigned char * const source,
- IN const size_t source_size,
- OUT unsigned char * const target,
- IN OUT size_t * const target_size
+_pkcs11h_enum_getSessionCertificates (
+ IN const pkcs11h_session_t session
) {
- CK_MECHANISM mech = {
- mech_type, NULL, 0
- };
+ PKCS11H_BOOL fOpSuccess = FALSE;
+ PKCS11H_BOOL fLoginRetry = FALSE;
+
CK_RV rv = CKR_OK;
- bool fLogonRetry = false;
- bool fOpSuccess = false;
- PKCS11ASSERT (pkcs11h_data!=NULL);
- PKCS11ASSERT (pkcs11h_data->fInitialized);
- PKCS11ASSERT (pkcs11h_certificate!=NULL);
- PKCS11ASSERT (source!=NULL);
- PKCS11ASSERT (target_size!=NULL);
+ PKCS11H_ASSERT (session!=NULL);
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_signRecover entry pkcs11h_certificate=%p, mech_type=%ld, source=%p, source_size=%u, target=%p, target_size=%p",
- (void *)pkcs11h_certificate,
- mech_type,
- source,
- source_size,
- target,
- (void *)target_size
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_enum_getSessionCertificates entry session=%p",
+ (void *)session
);
-
- if (rv == CKR_OK) {
- rv = _pkcs11h_validateSession (pkcs11h_certificate->session);
- }
+
+ /* THREADS: NO NEED TO LOCK, GLOBAL CACHE IS LOCKED */
while (rv == CKR_OK && !fOpSuccess) {
+ CK_OBJECT_CLASS cert_filter_class = CKO_CERTIFICATE;
+ CK_ATTRIBUTE cert_filter[] = {
+ {CKA_CLASS, &cert_filter_class, sizeof (cert_filter_class)}
+ };
- /*
- * Don't try invalid object
- */
- if (
- rv == CKR_OK &&
- pkcs11h_certificate->hKey == PKCS11H_INVALID_OBJECT_HANDLE
- ) {
- rv = CKR_OBJECT_HANDLE_INVALID;
+ CK_OBJECT_HANDLE *objects = NULL;
+ CK_ULONG objects_found = 0;
+
+ CK_ULONG i;
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_validateSession (session);
}
if (rv == CKR_OK) {
- rv = pkcs11h_certificate->session->provider->f->C_SignRecoverInit (
- pkcs11h_certificate->session->hSession,
- &mech,
- pkcs11h_certificate->hKey
+ rv = _pkcs11h_findObjects (
+ session,
+ cert_filter,
+ sizeof (cert_filter) / sizeof (CK_ATTRIBUTE),
+ &objects,
+ &objects_found
);
}
+
+ for (i=0;rv == CKR_OK && i < objects_found;i++) {
+ pkcs11h_certificate_id_t certificate_id = NULL;
+ pkcs11h_certificate_id_list_t new_element = NULL;
+
+ CK_ATTRIBUTE attrs[] = {
+ {CKA_ID, NULL, 0},
+ {CKA_VALUE, NULL, 0}
+ };
- if (rv == CKR_OK) {
- CK_ULONG size = *target_size;
- rv = pkcs11h_certificate->session->provider->f->C_SignRecover (
- pkcs11h_certificate->session->hSession,
- (CK_BYTE_PTR)source,
- source_size,
- (CK_BYTE_PTR)target,
- &size
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_getObjectAttributes (
+ session,
+ objects[i],
+ attrs,
+ sizeof (attrs) / sizeof (CK_ATTRIBUTE)
+ );
+ }
+
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_newCertificateId (&certificate_id)) == CKR_OK
+ ) {
+ rv = pkcs11h_duplicateTokenId (
+ &certificate_id->token_id,
+ session->token_id
+ );
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_dupmem (
+ (void*)&certificate_id->attrCKA_ID,
+ &certificate_id->attrCKA_ID_size,
+ attrs[0].pValue,
+ attrs[0].ulValueLen
+ );
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_dupmem (
+ (void*)&certificate_id->certificate_blob,
+ &certificate_id->certificate_blob_size,
+ attrs[1].pValue,
+ attrs[1].ulValueLen
+ );
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_updateCertificateIdDescription (certificate_id);
+ }
+
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_malloc (
+ (void *)&new_element,
+ sizeof (struct pkcs11h_certificate_id_list_s)
+ )) == CKR_OK
+ ) {
+ new_element->next = session->cached_certs;
+ new_element->certificate_id = certificate_id;
+ certificate_id = NULL;
+
+ session->cached_certs = new_element;
+ new_element = NULL;
+ }
+
+ if (certificate_id != NULL) {
+ pkcs11h_freeCertificateId (certificate_id);
+ certificate_id = NULL;
+ }
+
+ if (new_element != NULL) {
+ _pkcs11h_free ((void *)&new_element);
+ new_element = NULL;
+ }
+
+ _pkcs11h_freeObjectAttributes (
+ attrs,
+ sizeof (attrs) / sizeof (CK_ATTRIBUTE)
);
- *target_size = (int)size;
+ if (rv != CKR_OK) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Cannot get object attribute for provider '%s' object %ld rv=%ld-'%s'",
+ session->provider->manufacturerID,
+ objects[i],
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ /*
+ * Ignore error
+ */
+ rv = CKR_OK;
+ }
}
+ if (objects != NULL) {
+ _pkcs11h_free ((void *)&objects);
+ }
if (rv == CKR_OK) {
- fOpSuccess = true;
+ fOpSuccess = TRUE;
}
else {
- if (!fLogonRetry) {
- PKCS11DLOG (
- PKCS11_LOG_DEBUG1,
- "PKCS#11: Private key operation failed rv=%ld-'%s'",
+ if (!fLoginRetry) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Get certificate attributes failed: %ld:'%s'",
rv,
pkcs11h_getMessage (rv)
);
- fLogonRetry = true;
- rv = _pkcs11h_resetCertificateSession (pkcs11h_certificate);
+
+ rv = _pkcs11h_login (
+ session,
+ TRUE,
+ TRUE,
+ PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT
+ );
+
+ fLoginRetry = TRUE;
}
}
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_signRecover return rv=%ld-'%s'",
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_enum_getSessionCertificates return rv=%ld-'%s'",
rv,
pkcs11h_getMessage (rv)
);
@@ -2397,97 +7601,205 @@ pkcs11h_signRecover (
return rv;
}
+static
CK_RV
-pkcs11h_decrypt (
- IN const pkcs11h_certificate_t pkcs11h_certificate,
- IN const CK_MECHANISM_TYPE mech_type,
- IN const unsigned char * const source,
- IN const size_t source_size,
- OUT unsigned char * const target,
- IN OUT size_t * const target_size
+_pkcs11h_enum_splitCertificateIdList (
+ IN const pkcs11h_certificate_id_list_t cert_id_all,
+ OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,
+ OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list
) {
- CK_MECHANISM mech = {
- mech_type, NULL, 0
- };
- CK_ULONG size;
+ typedef struct info_s {
+ struct info_s *next;
+ pkcs11h_certificate_id_t e;
+ X509 *x509;
+ PKCS11H_BOOL fIsIssuer;
+ } *info_t;
+
+ pkcs11h_certificate_id_list_t cert_id_issuers_list = NULL;
+ pkcs11h_certificate_id_list_t cert_id_end_list = NULL;
+
+ info_t head = NULL;
+ info_t info = NULL;
+
CK_RV rv = CKR_OK;
- bool fLogonRetry = false;
- bool fOpSuccess = false;
- PKCS11ASSERT (pkcs11h_data!=NULL);
- PKCS11ASSERT (pkcs11h_data->fInitialized);
- PKCS11ASSERT (pkcs11h_certificate!=NULL);
- PKCS11ASSERT (source!=NULL);
- PKCS11ASSERT (target_size!=NULL);
+ /*PKCS11H_ASSERT (cert_id_all!=NULL); NOT NEEDED */
+ /*PKCS11H_ASSERT (p_cert_id_issuers_list!=NULL); NOT NEEDED*/
+ PKCS11H_ASSERT (p_cert_id_end_list!=NULL);
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_decrypt entry pkcs11h_certificate=%p, mech_type=%ld, source=%p, source_size=%u, target=%p, target_size=%p",
- (void *)pkcs11h_certificate,
- mech_type,
- source,
- source_size,
- target,
- (void *)target_size
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_splitCertificateIdList entry cert_id_all=%p, p_cert_id_issuers_list=%p, p_cert_id_end_list=%p",
+ (void *)cert_id_all,
+ (void *)p_cert_id_issuers_list,
+ (void *)p_cert_id_end_list
);
- if (rv != CKR_OK) {
- rv = _pkcs11h_validateSession (pkcs11h_certificate->session);
+ if (p_cert_id_issuers_list != NULL) {
+ *p_cert_id_issuers_list = NULL;
}
+ *p_cert_id_end_list = NULL;
- while (rv == CKR_OK && !fOpSuccess) {
+ OpenSSL_add_all_digests ();
- /*
- * Don't try invalid object
- */
- if (
- rv == CKR_OK &&
- pkcs11h_certificate->hKey == PKCS11H_INVALID_OBJECT_HANDLE
+ if (rv == CKR_OK) {
+ pkcs11h_certificate_id_list_t entry = NULL;
+
+ for (
+ entry = cert_id_all;
+ entry != NULL && rv == CKR_OK;
+ entry = entry->next
) {
- rv = CKR_OBJECT_HANDLE_INVALID;
- }
+ info_t new_info = NULL;
- if (rv == CKR_OK) {
- rv = pkcs11h_certificate->session->provider->f->C_DecryptInit (
- pkcs11h_certificate->session->hSession,
- &mech,
- pkcs11h_certificate->hKey
- );
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_malloc ((void *)&new_info, sizeof (struct info_s))) == CKR_OK &&
+ entry->certificate_id->certificate_blob != NULL
+ ) {
+ pkcs11_openssl_d2i_t d2i = (pkcs11_openssl_d2i_t)entry->certificate_id->certificate_blob;
+ new_info->next = head;
+ new_info->e = entry->certificate_id;
+ new_info->x509 = X509_new ();
+ if (
+ new_info->x509 != NULL &&
+ !d2i_X509 (
+ &new_info->x509,
+ &d2i,
+ entry->certificate_id->certificate_blob_size
+ )
+ ) {
+ X509_free (new_info->x509);
+ new_info->x509 = NULL;
+ }
+ head = new_info;
+ new_info = NULL;
+ }
}
- if (rv == CKR_OK) {
- size = *target_size;
- rv = pkcs11h_certificate->session->provider->f->C_Decrypt (
- pkcs11h_certificate->session->hSession,
- (CK_BYTE_PTR)source,
- source_size,
- (CK_BYTE_PTR)target,
- &size
- );
+ }
- *target_size = (int)size;
- }
+ if (rv == CKR_OK) {
+ for (
+ info = head;
+ info != NULL;
+ info = info->next
+ ) {
+ info_t info2 = NULL;
+ for (
+ info2 = head;
+ info2 != NULL && !info->fIsIssuer;
+ info2 = info2->next
+ ) {
+ EVP_PKEY *pub = NULL;
- if (rv == CKR_OK) {
- fOpSuccess = true;
+ pub = X509_get_pubkey (info->x509);
+
+ if (
+ info != info2 &&
+ info->x509 != NULL &&
+ info2->x509 != NULL &&
+/* Some people get this wrong !X509_NAME_cmp (
+ X509_get_subject_name (info->x509),
+ X509_get_issuer_name (info2->x509)
+ ) && */
+ X509_verify (info2->x509, pub) == 1
+ ) {
+ info->fIsIssuer = TRUE;
+ }
+
+ if (pub != NULL) {
+ EVP_PKEY_free (pub);
+ pub = NULL;
+ }
+ }
}
- else {
- if (!fLogonRetry) {
- PKCS11DLOG (
- PKCS11_LOG_DEBUG1,
- "PKCS#11: Private key operation failed rv=%ld-'%s'",
- rv,
- pkcs11h_getMessage (rv)
+ }
+
+ if (rv == CKR_OK) {
+ for (
+ info = head;
+ info != NULL && rv == CKR_OK;
+ info = info->next
+ ) {
+ pkcs11h_certificate_id_list_t new_entry = NULL;
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_malloc (
+ (void *)&new_entry,
+ sizeof (struct pkcs11h_certificate_id_list_s)
);
- fLogonRetry = true;
- rv = _pkcs11h_resetCertificateSession (pkcs11h_certificate);
}
+
+ if (
+ rv == CKR_OK &&
+ (rv = pkcs11h_duplicateCertificateId (
+ &new_entry->certificate_id,
+ info->e
+ )) == CKR_OK
+ ) {
+ /*
+ * Should not free base list
+ */
+ info->e = NULL;
+ }
+
+ if (rv == CKR_OK) {
+ if (info->fIsIssuer) {
+ new_entry->next = cert_id_issuers_list;
+ cert_id_issuers_list = new_entry;
+ new_entry = NULL;
+ }
+ else {
+ new_entry->next = cert_id_end_list;
+ cert_id_end_list = new_entry;
+ new_entry = NULL;
+ }
+ }
+
+ if (new_entry != NULL) {
+ if (new_entry->certificate_id != NULL) {
+ pkcs11h_freeCertificateId (new_entry->certificate_id);
+ }
+ _pkcs11h_free ((void *)&new_entry);
+ }
+ }
+ }
+
+ if (rv == CKR_OK) {
+ while (head != NULL) {
+ info_t entry = head;
+ head = head->next;
+
+ if (entry->x509 != NULL) {
+ X509_free (entry->x509);
+ entry->x509 = NULL;
+ }
+ _pkcs11h_free ((void *)&entry);
}
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_decrypt return rv=%ld-'%s'",
+ if (rv == CKR_OK && p_cert_id_issuers_list != NULL ) {
+ *p_cert_id_issuers_list = cert_id_issuers_list;
+ cert_id_issuers_list = NULL;
+ }
+
+ if (rv == CKR_OK) {
+ *p_cert_id_end_list = cert_id_end_list;
+ cert_id_end_list = NULL;
+ }
+
+ if (cert_id_issuers_list != NULL) {
+ pkcs11h_freeCertificateIdList (cert_id_issuers_list);
+ }
+
+ if (cert_id_end_list != NULL) {
+ pkcs11h_freeCertificateIdList (cert_id_end_list);
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_splitCertificateIdList return rv=%ld-'%s'",
rv,
pkcs11h_getMessage (rv)
);
@@ -2496,172 +7808,802 @@ pkcs11h_decrypt (
}
CK_RV
-pkcs11h_getCertificate (
- IN const pkcs11h_certificate_t pkcs11h_certificate,
- OUT unsigned char * const certificate,
- IN OUT size_t * const certificate_size
+pkcs11h_freeCertificateIdList (
+ IN const pkcs11h_certificate_id_list_t cert_id_list
+) {
+ pkcs11h_certificate_id_list_t _id = cert_id_list;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ /*PKCS11H_ASSERT (cert_id_list!=NULL); NOT NEEDED*/
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_freeCertificateIdList entry cert_id_list=%p",
+ (void *)cert_id_list
+ );
+
+ while (_id != NULL) {
+ pkcs11h_certificate_id_list_t x = _id;
+ _id = _id->next;
+ if (x->certificate_id != NULL) {
+ pkcs11h_freeCertificateId (x->certificate_id);
+ }
+ x->next = NULL;
+ _pkcs11h_free ((void *)&x);
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_freeCertificateIdList return"
+ );
+
+ return CKR_OK;
+}
+
+CK_RV
+pkcs11h_enum_getTokenCertificateIds (
+ IN const pkcs11h_token_id_t token_id,
+ IN const int method,
+ OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,
+ OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list
) {
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+ pkcs11h_session_t session = NULL;
CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ PKCS11H_ASSERT (token_id!=NULL);
+ /*PKCS11H_ASSERT (p_cert_id_issuers_list!=NULL); NOT NEEDED*/
+ PKCS11H_ASSERT (p_cert_id_end_list!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_enum_getTokenCertificateIds entry token_id=%p, method=%d, p_cert_id_issuers_list=%p, p_cert_id_end_list=%p",
+ (void *)token_id,
+ method,
+ (void *)p_cert_id_issuers_list,
+ (void *)p_cert_id_end_list
+ );
+
+ if (p_cert_id_issuers_list != NULL) {
+ *p_cert_id_issuers_list = NULL;
+ }
+ *p_cert_id_end_list = NULL;
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_mutexLock (&s_pkcs11h_data->mutexCache)) == CKR_OK
+ ) {
+ fMutexLocked = TRUE;
+ }
+#endif
+
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_getSessionByTokenId (
+ token_id,
+ &session
+ )) == CKR_OK
+ ) {
+ if (method == PKCS11H_ENUM_METHOD_RELOAD) {
+ pkcs11h_freeCertificateIdList (session->cached_certs);
+ session->cached_certs = NULL;
+ }
+
+ if (session->cached_certs == NULL) {
+ rv = _pkcs11h_enum_getSessionCertificates (session);
+ }
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_enum_splitCertificateIdList (
+ session->cached_certs,
+ p_cert_id_issuers_list,
+ p_cert_id_end_list
+ );
+ }
+
+ if (session != NULL) {
+ _pkcs11h_releaseSession (session);
+ }
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&s_pkcs11h_data->mutexCache);
+ fMutexLocked = FALSE;
+ }
+#endif
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_enum_getTokenCertificateIds return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
- PKCS11ASSERT (pkcs11h_data!=NULL);
- PKCS11ASSERT (pkcs11h_data->fInitialized);
- PKCS11ASSERT (certificate_size!=NULL);
+ return rv;
+}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_getCertificate entry pkcs11h_certificate=%p, certificate=%p, certificate_size=%p",
- (void *)pkcs11h_certificate,
- certificate,
- (void *)certificate_size
+CK_RV
+pkcs11h_enum_getCertificateIds (
+ IN const int method,
+ OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,
+ OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list
+) {
+#if defined(ENABLE_PKCS11H_THREADING)
+ PKCS11H_BOOL fMutexLocked = FALSE;
+#endif
+ pkcs11h_certificate_id_list_t cert_id_list = NULL;
+ pkcs11h_provider_t current_provider;
+ pkcs11h_session_t current_session;
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
+ PKCS11H_ASSERT (s_pkcs11h_data->fInitialized);
+ /*PKCS11H_ASSERT (p_cert_id_issuers_list!=NULL); NOT NEEDED*/
+ PKCS11H_ASSERT (p_cert_id_end_list!=NULL);
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_enum_getCertificateIds entry method=%d, p_cert_id_issuers_list=%p, p_cert_id_end_list=%p",
+ method,
+ (void *)p_cert_id_issuers_list,
+ (void *)p_cert_id_end_list
);
+ if (p_cert_id_issuers_list != NULL) {
+ *p_cert_id_issuers_list = NULL;
+ }
+ *p_cert_id_end_list = NULL;
+
+#if defined(ENABLE_PKCS11H_THREADING)
if (
rv == CKR_OK &&
- pkcs11h_certificate->certificate == NULL
+ (rv = _pkcs11h_mutexLock (&s_pkcs11h_data->mutexCache)) == CKR_OK
) {
- rv = CKR_FUNCTION_REJECTED;
+ fMutexLocked = TRUE;
+ }
+#endif
+
+ for (
+ current_session = s_pkcs11h_data->sessions;
+ current_session != NULL;
+ current_session = current_session->next
+ ) {
+ current_session->fTouch = FALSE;
+ if (method == PKCS11H_ENUM_METHOD_RELOAD) {
+ pkcs11h_freeCertificateIdList (current_session->cached_certs);
+ current_session->cached_certs = NULL;
+ }
+ }
+
+ for (
+ current_provider = s_pkcs11h_data->providers;
+ (
+ current_provider != NULL &&
+ rv == CKR_OK
+ );
+ current_provider = current_provider->next
+ ) {
+ CK_SLOT_ID_PTR slots = NULL;
+ CK_ULONG slotnum;
+ CK_SLOT_ID slot_index;
+
+ if (!current_provider->fEnabled) {
+ continue;
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_getSlotList (
+ current_provider,
+ CK_TRUE,
+ &slots,
+ &slotnum
+ );
+ }
+
+ for (
+ slot_index=0;
+ (
+ slot_index < slotnum &&
+ rv == CKR_OK
+ );
+ slot_index++
+ ) {
+ pkcs11h_session_t session = NULL;
+ pkcs11h_token_id_t token_id = NULL;
+ CK_TOKEN_INFO info;
+
+ if (rv == CKR_OK) {
+ rv = current_provider->f->C_GetTokenInfo (
+ slots[slot_index],
+ &info
+ );
+ }
+
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_getTokenId (
+ &info,
+ &token_id
+ )) == CKR_OK &&
+ (rv = _pkcs11h_getSessionByTokenId (
+ token_id,
+ &session
+ )) == CKR_OK
+ ) {
+ session->fTouch = TRUE;
+
+ if (session->cached_certs == NULL) {
+ rv = _pkcs11h_enum_getSessionCertificates (session);
+ }
+ }
+
+ if (rv != CKR_OK) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Cannot get token information for provider '%s' slot %ld rv=%ld-'%s'",
+ current_provider->manufacturerID,
+ slots[slot_index],
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ /*
+ * Ignore error
+ */
+ rv = CKR_OK;
+ }
+
+ if (session != NULL) {
+ _pkcs11h_releaseSession (session);
+ session = NULL;
+ }
+
+ if (token_id != NULL) {
+ pkcs11h_freeTokenId (token_id);
+ token_id = NULL;
+ }
+ }
+
+ if (rv != CKR_OK) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Cannot get slot list for provider '%s' rv=%ld-'%s'",
+ current_provider->manufacturerID,
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ /*
+ * Ignore error
+ */
+ rv = CKR_OK;
+ }
+
+ if (slots != NULL) {
+ _pkcs11h_free ((void *)&slots);
+ slots = NULL;
+ }
+ }
+
+ for (
+ current_session = s_pkcs11h_data->sessions;
+ (
+ current_session != NULL &&
+ rv == CKR_OK
+ );
+ current_session = current_session->next
+ ) {
+ if (
+ method == PKCS11H_ENUM_METHOD_CACHE ||
+ (
+ (
+ method == PKCS11H_ENUM_METHOD_RELOAD ||
+ method == PKCS11H_ENUM_METHOD_CACHE_EXIST
+ ) &&
+ current_session->fTouch
+ )
+ ) {
+ pkcs11h_certificate_id_list_t entry = NULL;
+
+ for (
+ entry = current_session->cached_certs;
+ (
+ entry != NULL &&
+ rv == CKR_OK
+ );
+ entry = entry->next
+ ) {
+ pkcs11h_certificate_id_list_t new_entry = NULL;
+
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_malloc (
+ (void *)&new_entry,
+ sizeof (struct pkcs11h_certificate_id_list_s)
+ )) == CKR_OK &&
+ (rv = pkcs11h_duplicateCertificateId (
+ &new_entry->certificate_id,
+ entry->certificate_id
+ )) == CKR_OK
+ ) {
+ new_entry->next = cert_id_list;
+ cert_id_list = new_entry;
+ new_entry = NULL;
+ }
+
+ if (new_entry != NULL) {
+ new_entry->next = NULL;
+ pkcs11h_freeCertificateIdList (new_entry);
+ new_entry = NULL;
+ }
+ }
+ }
}
if (rv == CKR_OK) {
- *certificate_size = pkcs11h_certificate->certificate_size;
+ rv = _pkcs11h_enum_splitCertificateIdList (
+ cert_id_list,
+ p_cert_id_issuers_list,
+ p_cert_id_end_list
+ );
}
- if (certificate != NULL) {
+ if (cert_id_list != NULL) {
+ pkcs11h_freeCertificateIdList (cert_id_list);
+ cert_id_list = NULL;
+ }
+
+
+#if defined(ENABLE_PKCS11H_THREADING)
+ if (fMutexLocked) {
+ _pkcs11h_mutexRelease (&s_pkcs11h_data->mutexCache);
+ fMutexLocked = FALSE;
+ }
+#endif
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_enum_getCertificateIds return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+#endif /* ENABLE_PKCS11H_CERTIFICATE */
+
+#endif /* ENABLE_PKCS11H_ENUM */
+
+#if defined(ENABLE_PKCS11H_SLOTEVENT)
+/*======================================================================*
+ * SLOTEVENT INTERFACE
+ *======================================================================*/
+
+static
+unsigned long
+_pkcs11h_slotevent_checksum (
+ IN const unsigned char * const p,
+ IN const size_t s
+) {
+ unsigned long r = 0;
+ size_t i;
+ for (i=0;i<s;i++) {
+ r += p[i];
+ }
+ return r;
+}
+
+static
+void *
+_pkcs11h_slotevent_provider (
+ IN void *p
+) {
+ pkcs11h_provider_t provider = (pkcs11h_provider_t)p;
+ CK_SLOT_ID slot;
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_slotevent_provider provider='%s' entry",
+ provider->manufacturerID
+ );
+
+ if (rv == CKR_OK && !provider->fEnabled) {
+ rv = CKR_OPERATION_NOT_INITIALIZED;
+ }
+
+ if (rv == CKR_OK) {
+
+ if (provider->nSlotEventPollInterval == 0) {
+ provider->nSlotEventPollInterval = PKCS11H_DEFAULT_SLOTEVENT_POLL;
+ }
+
+ /*
+ * If we cannot finalize, we cannot cause
+ * WaitForSlotEvent to terminate
+ */
+ if (!provider->fShouldFinalize) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Setup slotevent provider='%s' mode hardset to poll",
+ provider->manufacturerID
+ );
+ provider->nSlotEventMethod = PKCS11H_SLOTEVENT_METHOD_POLL;
+ }
+
if (
+ provider->nSlotEventMethod == PKCS11H_SLOTEVENT_METHOD_AUTO ||
+ provider->nSlotEventMethod == PKCS11H_SLOTEVENT_METHOD_TRIGGER
+ ) {
+ if (
+ provider->f->C_WaitForSlotEvent (
+ CKF_DONT_BLOCK,
+ &slot,
+ NULL_PTR
+ ) == CKR_FUNCTION_NOT_SUPPORTED
+ ) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Setup slotevent provider='%s' mode is poll",
+ provider->manufacturerID
+ );
+
+ provider->nSlotEventMethod = PKCS11H_SLOTEVENT_METHOD_POLL;
+ }
+ else {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Setup slotevent provider='%s' mode is trigger",
+ provider->manufacturerID
+ );
+
+ provider->nSlotEventMethod = PKCS11H_SLOTEVENT_METHOD_TRIGGER;
+ }
+ }
+ }
+
+ if (provider->nSlotEventMethod == PKCS11H_SLOTEVENT_METHOD_TRIGGER) {
+ while (
+ !s_pkcs11h_data->fSlotEventShouldTerminate &&
+ provider->fEnabled &&
rv == CKR_OK &&
- *certificate_size > pkcs11h_certificate->certificate_size
+ (rv = provider->f->C_WaitForSlotEvent (
+ 0,
+ &slot,
+ NULL_PTR
+ )) == CKR_OK
) {
- rv = CKR_BUFFER_TOO_SMALL;
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Slotevent provider='%s' event",
+ provider->manufacturerID
+ );
+
+ _pkcs11h_condSignal (&s_pkcs11h_data->condSlotEvent);
}
-
+ }
+ else {
+ unsigned long ulLastChecksum = 0;
+ PKCS11H_BOOL fFirstTime = TRUE;
+
+ while (
+ !s_pkcs11h_data->fSlotEventShouldTerminate &&
+ provider->fEnabled &&
+ rv == CKR_OK
+ ) {
+ unsigned long ulCurrentChecksum = 0;
+
+ CK_SLOT_ID_PTR slots = NULL;
+ CK_ULONG slotnum;
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Slotevent provider='%s' poll",
+ provider->manufacturerID
+ );
+
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_getSlotList (
+ provider,
+ TRUE,
+ &slots,
+ &slotnum
+ )) == CKR_OK
+ ) {
+ CK_ULONG i;
+
+ for (i=0;i<slotnum;i++) {
+ CK_TOKEN_INFO info;
+
+ if (provider->f->C_GetTokenInfo (slots[i], &info) == CKR_OK) {
+ ulCurrentChecksum += (
+ _pkcs11h_slotevent_checksum (
+ info.label,
+ sizeof (info.label)
+ ) +
+ _pkcs11h_slotevent_checksum (
+ info.manufacturerID,
+ sizeof (info.manufacturerID)
+ ) +
+ _pkcs11h_slotevent_checksum (
+ info.model,
+ sizeof (info.model)
+ ) +
+ _pkcs11h_slotevent_checksum (
+ info.serialNumber,
+ sizeof (info.serialNumber)
+ )
+ );
+ }
+ }
+ }
+
+ if (rv == CKR_OK) {
+ if (fFirstTime) {
+ fFirstTime = FALSE;
+ }
+ else {
+ if (ulLastChecksum != ulCurrentChecksum) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Slotevent provider='%s' event",
+ provider->manufacturerID
+ );
+
+ _pkcs11h_condSignal (&s_pkcs11h_data->condSlotEvent);
+ }
+ }
+ ulLastChecksum = ulCurrentChecksum;
+ }
+
+ if (slots != NULL) {
+ _pkcs11h_free ((void *)&slots);
+ }
+
+ if (!s_pkcs11h_data->fSlotEventShouldTerminate) {
+ _pkcs11h_sleep (provider->nSlotEventPollInterval);
+ }
+ }
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_slotevent_provider provider='%s' return",
+ provider->manufacturerID
+ );
+
+ return NULL;
+}
+
+static
+void *
+_pkcs11h_slotevent_manager (
+ IN void *p
+) {
+ PKCS11H_BOOL fFirst = TRUE;
+
+ (void)p;
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_slotevent_manager entry"
+ );
+
+ /*
+ * Trigger hook, so application may
+ * depend on initial slot change
+ */
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Calling slotevent hook"
+ );
+ s_pkcs11h_data->hooks.slotevent (s_pkcs11h_data->hooks.slotevent_data);
+
+ while (
+ fFirst || /* Must enter wait or mutex will never be free */
+ !s_pkcs11h_data->fSlotEventShouldTerminate
+ ) {
+ pkcs11h_provider_t current_provider;
+
+ fFirst = FALSE;
+
+ /*
+ * Start each provider thread
+ * if not already started.
+ * This is required in order to allow
+ * adding new providers.
+ */
+ for (
+ current_provider = s_pkcs11h_data->providers;
+ current_provider != NULL;
+ current_provider = current_provider->next
+ ) {
+ if (!current_provider->fEnabled) {
+ if (current_provider->threadSlotEvent == PKCS11H_THREAD_NULL) {
+ _pkcs11h_threadStart (
+ &current_provider->threadSlotEvent,
+ _pkcs11h_slotevent_provider,
+ current_provider
+ );
+ }
+ }
+ else {
+ if (current_provider->threadSlotEvent != PKCS11H_THREAD_NULL) {
+ _pkcs11h_threadJoin (&current_provider->threadSlotEvent);
+ }
+ }
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_slotevent_manager waiting for slotevent"
+ );
+ _pkcs11h_condWait (&s_pkcs11h_data->condSlotEvent, PKCS11H_COND_INFINITE);
+
+ if (s_pkcs11h_data->fSlotEventSkipEvent) {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Slotevent skipping event"
+ );
+ s_pkcs11h_data->fSlotEventSkipEvent = FALSE;
+ }
+ else {
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
+ "PKCS#11: Calling slotevent hook"
+ );
+ s_pkcs11h_data->hooks.slotevent (s_pkcs11h_data->hooks.slotevent_data);
+ }
+ }
+
+ {
+ pkcs11h_provider_t current_provider;
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_slotevent_manager joining threads"
+ );
+
+
+ for (
+ current_provider = s_pkcs11h_data->providers;
+ current_provider != NULL;
+ current_provider = current_provider->next
+ ) {
+ if (current_provider->threadSlotEvent != PKCS11H_THREAD_NULL) {
+ _pkcs11h_threadJoin (&current_provider->threadSlotEvent);
+ }
+ }
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_slotevent_manager return"
+ );
+
+ return NULL;
+}
+
+static
+CK_RV
+_pkcs11h_slotevent_init () {
+ CK_RV rv = CKR_OK;
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_slotevent_init entry"
+ );
+
+ if (!s_pkcs11h_data->fSlotEventInitialized) {
if (rv == CKR_OK) {
- memmove (certificate, pkcs11h_certificate->certificate, *certificate_size);
+ rv = _pkcs11h_condInit (&s_pkcs11h_data->condSlotEvent);
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_threadStart (
+ &s_pkcs11h_data->threadSlotEvent,
+ _pkcs11h_slotevent_manager,
+ NULL
+ );
+ }
+
+ if (rv == CKR_OK) {
+ s_pkcs11h_data->fSlotEventInitialized = TRUE;
}
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_getCertificate return rv=%ld-'%s'",
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_slotevent_init return rv=%ld-'%s'",
rv,
pkcs11h_getMessage (rv)
);
+ return rv;
+}
+
+static
+CK_RV
+_pkcs11h_slotevent_notify () {
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_slotevent_notify entry"
+ );
+
+ if (s_pkcs11h_data->fSlotEventInitialized) {
+ s_pkcs11h_data->fSlotEventSkipEvent = TRUE;
+ _pkcs11h_condSignal (&s_pkcs11h_data->condSlotEvent);
+ }
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_slotevent_notify return"
+ );
+
return CKR_OK;
}
-char *
-pkcs11h_getMessage (
- IN const int rv
-) {
- switch (rv) {
- case CKR_OK: return "CKR_OK";
- case CKR_CANCEL: return "CKR_CANCEL";
- case CKR_HOST_MEMORY: return "CKR_HOST_MEMORY";
- case CKR_SLOT_ID_INVALID: return "CKR_SLOT_ID_INVALID";
- case CKR_GENERAL_ERROR: return "CKR_GENERAL_ERROR";
- case CKR_FUNCTION_FAILED: return "CKR_FUNCTION_FAILED";
- case CKR_ARGUMENTS_BAD: return "CKR_ARGUMENTS_BAD";
- case CKR_NO_EVENT: return "CKR_NO_EVENT";
- case CKR_NEED_TO_CREATE_THREADS: return "CKR_NEED_TO_CREATE_THREADS";
- case CKR_CANT_LOCK: return "CKR_CANT_LOCK";
- case CKR_ATTRIBUTE_READ_ONLY: return "CKR_ATTRIBUTE_READ_ONLY";
- case CKR_ATTRIBUTE_SENSITIVE: return "CKR_ATTRIBUTE_SENSITIVE";
- case CKR_ATTRIBUTE_TYPE_INVALID: return "CKR_ATTRIBUTE_TYPE_INVALID";
- case CKR_ATTRIBUTE_VALUE_INVALID: return "CKR_ATTRIBUTE_VALUE_INVALID";
- case CKR_DATA_INVALID: return "CKR_DATA_INVALID";
- case CKR_DATA_LEN_RANGE: return "CKR_DATA_LEN_RANGE";
- case CKR_DEVICE_ERROR: return "CKR_DEVICE_ERROR";
- case CKR_DEVICE_MEMORY: return "CKR_DEVICE_MEMORY";
- case CKR_DEVICE_REMOVED: return "CKR_DEVICE_REMOVED";
- case CKR_ENCRYPTED_DATA_INVALID: return "CKR_ENCRYPTED_DATA_INVALID";
- case CKR_ENCRYPTED_DATA_LEN_RANGE: return "CKR_ENCRYPTED_DATA_LEN_RANGE";
- case CKR_FUNCTION_CANCELED: return "CKR_FUNCTION_CANCELED";
- case CKR_FUNCTION_NOT_PARALLEL: return "CKR_FUNCTION_NOT_PARALLEL";
- case CKR_FUNCTION_NOT_SUPPORTED: return "CKR_FUNCTION_NOT_SUPPORTED";
- case CKR_KEY_HANDLE_INVALID: return "CKR_KEY_HANDLE_INVALID";
- case CKR_KEY_SIZE_RANGE: return "CKR_KEY_SIZE_RANGE";
- case CKR_KEY_TYPE_INCONSISTENT: return "CKR_KEY_TYPE_INCONSISTENT";
- case CKR_KEY_NOT_NEEDED: return "CKR_KEY_NOT_NEEDED";
- case CKR_KEY_CHANGED: return "CKR_KEY_CHANGED";
- case CKR_KEY_NEEDED: return "CKR_KEY_NEEDED";
- case CKR_KEY_INDIGESTIBLE: return "CKR_KEY_INDIGESTIBLE";
- case CKR_KEY_FUNCTION_NOT_PERMITTED: return "CKR_KEY_FUNCTION_NOT_PERMITTED";
- case CKR_KEY_NOT_WRAPPABLE: return "CKR_KEY_NOT_WRAPPABLE";
- case CKR_KEY_UNEXTRACTABLE: return "CKR_KEY_UNEXTRACTABLE";
- case CKR_MECHANISM_INVALID: return "CKR_MECHANISM_INVALID";
- case CKR_MECHANISM_PARAM_INVALID: return "CKR_MECHANISM_PARAM_INVALID";
- case CKR_OBJECT_HANDLE_INVALID: return "CKR_OBJECT_HANDLE_INVALID";
- case CKR_OPERATION_ACTIVE: return "CKR_OPERATION_ACTIVE";
- case CKR_OPERATION_NOT_INITIALIZED: return "CKR_OPERATION_NOT_INITIALIZED";
- case CKR_PIN_INCORRECT: return "CKR_PIN_INCORRECT";
- case CKR_PIN_INVALID: return "CKR_PIN_INVALID";
- case CKR_PIN_LEN_RANGE: return "CKR_PIN_LEN_RANGE";
- case CKR_PIN_EXPIRED: return "CKR_PIN_EXPIRED";
- case CKR_PIN_LOCKED: return "CKR_PIN_LOCKED";
- case CKR_SESSION_CLOSED: return "CKR_SESSION_CLOSED";
- case CKR_SESSION_COUNT: return "CKR_SESSION_COUNT";
- case CKR_SESSION_HANDLE_INVALID: return "CKR_SESSION_HANDLE_INVALID";
- case CKR_SESSION_PARALLEL_NOT_SUPPORTED: return "CKR_SESSION_PARALLEL_NOT_SUPPORTED";
- case CKR_SESSION_READ_ONLY: return "CKR_SESSION_READ_ONLY";
- case CKR_SESSION_EXISTS: return "CKR_SESSION_EXISTS";
- case CKR_SESSION_READ_ONLY_EXISTS: return "CKR_SESSION_READ_ONLY_EXISTS";
- case CKR_SESSION_READ_WRITE_SO_EXISTS: return "CKR_SESSION_READ_WRITE_SO_EXISTS";
- case CKR_SIGNATURE_INVALID: return "CKR_SIGNATURE_INVALID";
- case CKR_SIGNATURE_LEN_RANGE: return "CKR_SIGNATURE_LEN_RANGE";
- case CKR_TEMPLATE_INCOMPLETE: return "CKR_TEMPLATE_INCOMPLETE";
- case CKR_TEMPLATE_INCONSISTENT: return "CKR_TEMPLATE_INCONSISTENT";
- case CKR_TOKEN_NOT_PRESENT: return "CKR_TOKEN_NOT_PRESENT";
- case CKR_TOKEN_NOT_RECOGNIZED: return "CKR_TOKEN_NOT_RECOGNIZED";
- case CKR_TOKEN_WRITE_PROTECTED: return "CKR_TOKEN_WRITE_PROTECTED";
- case CKR_UNWRAPPING_KEY_HANDLE_INVALID: return "CKR_UNWRAPPING_KEY_HANDLE_INVALID";
- case CKR_UNWRAPPING_KEY_SIZE_RANGE: return "CKR_UNWRAPPING_KEY_SIZE_RANGE";
- case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT: return "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT";
- case CKR_USER_ALREADY_LOGGED_IN: return "CKR_USER_ALREADY_LOGGED_IN";
- case CKR_USER_NOT_LOGGED_IN: return "CKR_USER_NOT_LOGGED_IN";
- case CKR_USER_PIN_NOT_INITIALIZED: return "CKR_USER_PIN_NOT_INITIALIZED";
- case CKR_USER_TYPE_INVALID: return "CKR_USER_TYPE_INVALID";
- case CKR_USER_ANOTHER_ALREADY_LOGGED_IN: return "CKR_USER_ANOTHER_ALREADY_LOGGED_IN";
- case CKR_USER_TOO_MANY_TYPES: return "CKR_USER_TOO_MANY_TYPES";
- case CKR_WRAPPED_KEY_INVALID: return "CKR_WRAPPED_KEY_INVALID";
- case CKR_WRAPPED_KEY_LEN_RANGE: return "CKR_WRAPPED_KEY_LEN_RANGE";
- case CKR_WRAPPING_KEY_HANDLE_INVALID: return "CKR_WRAPPING_KEY_HANDLE_INVALID";
- case CKR_WRAPPING_KEY_SIZE_RANGE: return "CKR_WRAPPING_KEY_SIZE_RANGE";
- case CKR_WRAPPING_KEY_TYPE_INCONSISTENT: return "CKR_WRAPPING_KEY_TYPE_INCONSISTENT";
- case CKR_RANDOM_SEED_NOT_SUPPORTED: return "CKR_RANDOM_SEED_NOT_SUPPORTED";
- case CKR_RANDOM_NO_RNG: return "CKR_RANDOM_NO_RNG";
- case CKR_DOMAIN_PARAMS_INVALID: return "CKR_DOMAIN_PARAMS_INVALID";
- case CKR_BUFFER_TOO_SMALL: return "CKR_BUFFER_TOO_SMALL";
- case CKR_SAVED_STATE_INVALID: return "CKR_SAVED_STATE_INVALID";
- case CKR_INFORMATION_SENSITIVE: return "CKR_INFORMATION_SENSITIVE";
- case CKR_STATE_UNSAVEABLE: return "CKR_STATE_UNSAVEABLE";
- case CKR_CRYPTOKI_NOT_INITIALIZED: return "CKR_CRYPTOKI_NOT_INITIALIZED";
- case CKR_CRYPTOKI_ALREADY_INITIALIZED: return "CKR_CRYPTOKI_ALREADY_INITIALIZED";
- case CKR_MUTEX_BAD: return "CKR_MUTEX_BAD";
- case CKR_MUTEX_NOT_LOCKED: return "CKR_MUTEX_NOT_LOCKED";
- case CKR_FUNCTION_REJECTED: return "CKR_FUNCTION_REJECTED";
- case CKR_VENDOR_DEFINED: return "CKR_VENDOR_DEFINED";
- default: return "Unknown PKCS#11 error";
+static
+CK_RV
+_pkcs11h_slotevent_terminate () {
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_slotevent_terminate entry"
+ );
+
+ if (s_pkcs11h_data->fSlotEventInitialized) {
+ s_pkcs11h_data->fSlotEventShouldTerminate = TRUE;
+
+ _pkcs11h_slotevent_notify ();
+
+ if (s_pkcs11h_data->threadSlotEvent != PKCS11H_THREAD_NULL) {
+ _pkcs11h_threadJoin (&s_pkcs11h_data->threadSlotEvent);
+ }
+
+ _pkcs11h_condFree (&s_pkcs11h_data->condSlotEvent);
+ s_pkcs11h_data->fSlotEventInitialized = FALSE;
}
+
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_slotevent_terminate return"
+ );
+
+ return CKR_OK;
}
-/*==========================================
- * openssl interface
- */
+#endif
+
+#if defined(ENABLE_PKCS11H_OPENSSL)
+/*======================================================================*
+ * OPENSSL INTERFACE
+ *======================================================================*/
static
pkcs11h_openssl_session_t
-_pkcs11h_openssl_get_pkcs11h_openssl_session (
+_pkcs11h_openssl_get_openssl_session (
IN OUT const RSA *rsa
) {
pkcs11h_openssl_session_t session;
- PKCS11ASSERT (rsa!=NULL);
+ PKCS11H_ASSERT (rsa!=NULL);
#if OPENSSL_VERSION_NUMBER < 0x00907000L
session = (pkcs11h_openssl_session_t)RSA_get_app_data ((RSA *)rsa);
#else
session = (pkcs11h_openssl_session_t)RSA_get_app_data (rsa);
#endif
- PKCS11ASSERT (session!=NULL);
+ PKCS11H_ASSERT (session!=NULL);
return session;
}
@@ -2671,12 +8613,10 @@ pkcs11h_certificate_t
_pkcs11h_openssl_get_pkcs11h_certificate (
IN OUT const RSA *rsa
) {
- pkcs11h_openssl_session_t session = _pkcs11h_openssl_get_pkcs11h_openssl_session (rsa);
+ pkcs11h_openssl_session_t session = _pkcs11h_openssl_get_openssl_session (rsa);
- PKCS11ASSERT (session!=NULL);
- PKCS11ASSERT (session->certificate!=NULL);
- PKCS11ASSERT (session->certificate->session!=NULL);
- PKCS11ASSERT (session->certificate->session->fValid);
+ PKCS11H_ASSERT (session!=NULL);
+ PKCS11H_ASSERT (session->certificate!=NULL);
return session->certificate;
}
@@ -2702,12 +8642,12 @@ _pkcs11h_openssl_dec (
IN int padding
) {
#endif
- PKCS11ASSERT (from!=NULL);
- PKCS11ASSERT (to!=NULL);
- PKCS11ASSERT (rsa!=NULL);
+ PKCS11H_ASSERT (from!=NULL);
+ PKCS11H_ASSERT (to!=NULL);
+ PKCS11H_ASSERT (rsa!=NULL);
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
"PKCS#11: _pkcs11h_openssl_dec entered - flen=%d, from=%p, to=%p, rsa=%p, padding=%d",
flen,
from,
@@ -2716,13 +8656,13 @@ _pkcs11h_openssl_dec (
padding
);
- PKCS11LOG (
- PKCS11_LOG_ERROR,
+ PKCS11H_LOG (
+ PKCS11H_LOG_ERROR,
"PKCS#11: Private key decryption is not supported"
);
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
"PKCS#11: _pkcs11h_openssl_dec return"
);
@@ -2752,7 +8692,7 @@ _pkcs11h_openssl_sign (
IN OUT const RSA *rsa
) {
#endif
- pkcs11h_certificate_t pkcs11h_certificate = _pkcs11h_openssl_get_pkcs11h_certificate (rsa);
+ pkcs11h_certificate_t certificate = _pkcs11h_openssl_get_pkcs11h_certificate (rsa);
CK_RV rv = CKR_OK;
int myrsa_size = 0;
@@ -2761,12 +8701,12 @@ _pkcs11h_openssl_sign (
unsigned char *enc = NULL;
int enc_len = 0;
- PKCS11ASSERT (m!=NULL);
- PKCS11ASSERT (sigret!=NULL);
- PKCS11ASSERT (siglen!=NULL);
+ PKCS11H_ASSERT (m!=NULL);
+ PKCS11H_ASSERT (sigret!=NULL);
+ PKCS11H_ASSERT (siglen!=NULL);
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
"PKCS#11: _pkcs11h_openssl_sign entered - type=%d, m=%p, m_len=%u, signret=%p, signlen=%p, rsa=%p",
type,
m,
@@ -2794,18 +8734,18 @@ _pkcs11h_openssl_sign (
if (
rv == CKR_OK &&
- (enc=enc_alloc=(unsigned char *)malloc ((unsigned int)myrsa_size+1)) == NULL
+ (rv = _pkcs11h_malloc ((void*)&enc, myrsa_size+1)) == CKR_OK
) {
- rv = CKR_HOST_MEMORY;
+ enc_alloc = enc;
}
if (rv == CKR_OK) {
- sig.algor= &algor;
+ sig.algor = &algor;
}
if (
rv == CKR_OK &&
- (sig.algor->algorithm=OBJ_nid2obj(type)) == NULL
+ (sig.algor->algorithm = OBJ_nid2obj (type)) == NULL
) {
rv = CKR_FUNCTION_FAILED;
}
@@ -2818,26 +8758,26 @@ _pkcs11h_openssl_sign (
}
if (rv == CKR_OK) {
- parameter.type=V_ASN1_NULL;
- parameter.value.ptr=NULL;
+ parameter.type = V_ASN1_NULL;
+ parameter.value.ptr = NULL;
- sig.algor->parameter= &parameter;
+ sig.algor->parameter = &parameter;
- sig.digest=&digest;
- sig.digest->data=(unsigned char *)m;
- sig.digest->length=m_len;
+ sig.digest = &digest;
+ sig.digest->data = (unsigned char *)m;
+ sig.digest->length = m_len;
}
if (
rv == CKR_OK &&
- (enc_len=i2d_X509_SIG(&sig,NULL)) < 0
+ (enc_len=i2d_X509_SIG (&sig, NULL)) < 0
) {
rv = CKR_FUNCTION_FAILED;
}
if (rv == CKR_OK) {
- unsigned char *p=enc;
- i2d_X509_SIG(&sig,&p);
+ unsigned char *p = enc;
+ i2d_X509_SIG (&sig, &p);
}
}
@@ -2848,65 +8788,34 @@ _pkcs11h_openssl_sign (
rv = CKR_KEY_SIZE_RANGE;
}
- /*
- * Get key attributes
- * so signature mode will
- * be available
- */
- if (rv == CKR_OK) {
- rv = _pkcs11h_getCertificateKeyAttributes (pkcs11h_certificate);
- }
-
if (rv == CKR_OK) {
- PKCS11DLOG (
- PKCS11_LOG_DEBUG1,
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG1,
"PKCS#11: Performing signature"
);
*siglen = myrsa_size;
- switch (pkcs11h_certificate->signmode) {
- case pkcs11h_signmode_sign:
- if (
- (rv = pkcs11h_sign (
- pkcs11h_certificate,
- CKM_RSA_PKCS,
- enc,
- enc_len,
- sigret,
- siglen
- )) != CKR_OK
- ) {
- PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot perform signature %ld:'%s'", rv, pkcs11h_getMessage (rv));
- }
- break;
- case pkcs11h_signmode_recover:
- if (
- (rv = pkcs11h_signRecover (
- pkcs11h_certificate,
- CKM_RSA_PKCS,
- enc,
- enc_len,
- sigret,
- siglen
- )) != CKR_OK
- ) {
- PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot perform signature-recover %ld:'%s'", rv, pkcs11h_getMessage (rv));
- }
- break;
- default:
- rv = CKR_FUNCTION_REJECTED;
- PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Invalid signature mode");
- break;
+ if (
+ (rv = pkcs11h_certificate_signAny (
+ certificate,
+ CKM_RSA_PKCS,
+ enc,
+ enc_len,
+ sigret,
+ siglen
+ )) != CKR_OK
+ ) {
+ PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot perform signature %ld:'%s'", rv, pkcs11h_getMessage (rv));
}
}
if (enc_alloc != NULL) {
- free (enc_alloc);
+ _pkcs11h_free ((void *)&enc_alloc);
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
"PKCS#11: _pkcs11h_openssl_sign - return rv=%ld-'%s'",
rv,
pkcs11h_getMessage (rv)
@@ -2920,18 +8829,18 @@ int
_pkcs11h_openssl_finish (
IN OUT RSA *rsa
) {
- pkcs11h_openssl_session_t pkcs11h_openssl_session = _pkcs11h_openssl_get_pkcs11h_openssl_session (rsa);
+ pkcs11h_openssl_session_t openssl_session = _pkcs11h_openssl_get_openssl_session (rsa);
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
"PKCS#11: _pkcs11h_openssl_finish - entered rsa=%p",
(void *)rsa
);
RSA_set_app_data (rsa, NULL);
- if (pkcs11h_openssl_session->orig_finish != NULL) {
- pkcs11h_openssl_session->orig_finish (rsa);
+ if (openssl_session->orig_finish != NULL) {
+ openssl_session->orig_finish (rsa);
#ifdef BROKEN_OPENSSL_ENGINE
{
@@ -2950,10 +8859,10 @@ _pkcs11h_openssl_finish (
#endif
}
- pkcs11h_openssl_freeSession (pkcs11h_openssl_session);
+ pkcs11h_openssl_freeSession (openssl_session);
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
"PKCS#11: _pkcs11h_openssl_finish - return"
);
@@ -2961,192 +8870,187 @@ _pkcs11h_openssl_finish (
}
pkcs11h_openssl_session_t
-pkcs11h_openssl_createSession () {
- pkcs11h_openssl_session_t pkcs11h_openssl_session = NULL;
- bool fOK = true;
+pkcs11h_openssl_createSession (
+ IN const pkcs11h_certificate_t certificate
+) {
+ pkcs11h_openssl_session_t openssl_session = NULL;
+ PKCS11H_BOOL fOK = TRUE;
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
"PKCS#11: pkcs11h_openssl_createSession - entry"
);
if (
fOK &&
- (pkcs11h_openssl_session = (pkcs11h_openssl_session_t)malloc (sizeof (struct pkcs11h_openssl_session_s))) == NULL
+ _pkcs11h_malloc (
+ (void*)&openssl_session,
+ sizeof (struct pkcs11h_openssl_session_s)) != CKR_OK
) {
- fOK = false;
- PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot allocate memory");
+ fOK = FALSE;
+ PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot allocate memory");
}
if (fOK) {
- memset (pkcs11h_openssl_session, 0, sizeof (struct pkcs11h_openssl_session_s));
- }
+ const RSA_METHOD *def = RSA_get_default_method();
- if (fOK) {
- pkcs11h_openssl_session->nReferenceCount = 1;
+ memmove (&openssl_session->smart_rsa, def, sizeof(RSA_METHOD));
+
+ openssl_session->orig_finish = def->finish;
+
+ openssl_session->smart_rsa.name = "pkcs11";
+ openssl_session->smart_rsa.rsa_priv_dec = _pkcs11h_openssl_dec;
+ openssl_session->smart_rsa.rsa_sign = _pkcs11h_openssl_sign;
+ openssl_session->smart_rsa.finish = _pkcs11h_openssl_finish;
+ openssl_session->smart_rsa.flags = RSA_METHOD_FLAG_NO_CHECK | RSA_FLAG_EXT_PKEY;
+ openssl_session->certificate = certificate;
+ openssl_session->nReferenceCount = 1;
}
if (!fOK) {
- free (pkcs11h_openssl_session);
- pkcs11h_openssl_session = NULL;
+ _pkcs11h_free ((void *)&openssl_session);
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_openssl_createSession - return pkcs11h_openssl_session=%p",
- (void *)pkcs11h_openssl_session
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_openssl_createSession - return openssl_session=%p",
+ (void *)openssl_session
);
- return pkcs11h_openssl_session;
+ return openssl_session;
}
void
pkcs11h_openssl_freeSession (
- IN const pkcs11h_openssl_session_t pkcs11h_openssl_session
+ IN const pkcs11h_openssl_session_t openssl_session
) {
- PKCS11ASSERT (pkcs11h_openssl_session!=NULL);
- PKCS11ASSERT (pkcs11h_openssl_session->nReferenceCount>0);
+ PKCS11H_ASSERT (openssl_session!=NULL);
+ PKCS11H_ASSERT (openssl_session->nReferenceCount>0);
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_openssl_freeSession - entry pkcs11h_openssl_session=%p, count=%d",
- (void *)pkcs11h_openssl_session,
- pkcs11h_openssl_session->nReferenceCount
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_openssl_freeSession - entry openssl_session=%p, count=%d",
+ (void *)openssl_session,
+ openssl_session->nReferenceCount
);
- pkcs11h_openssl_session->nReferenceCount--;
+ openssl_session->nReferenceCount--;
- if (pkcs11h_openssl_session->nReferenceCount == 0) {
- if (pkcs11h_openssl_session->x509) {
- X509_free (pkcs11h_openssl_session->x509);
- pkcs11h_openssl_session->x509 = NULL;
+ if (openssl_session->nReferenceCount == 0) {
+ if (openssl_session->x509 != NULL) {
+ X509_free (openssl_session->x509);
+ openssl_session->x509 = NULL;
}
- if (pkcs11h_openssl_session->certificate != NULL) {
- pkcs11h_freeCertificateSession (pkcs11h_openssl_session->certificate);
- pkcs11h_openssl_session->certificate = NULL;
+ if (openssl_session->certificate != NULL) {
+ pkcs11h_freeCertificate (openssl_session->certificate);
+ openssl_session->certificate = NULL;
}
- free (pkcs11h_openssl_session);
+ _pkcs11h_free ((void *)&openssl_session);
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
"PKCS#11: pkcs11h_openssl_freeSession - return"
);
}
RSA *
pkcs11h_openssl_getRSA (
- IN const pkcs11h_openssl_session_t pkcs11h_openssl_session
+ IN const pkcs11h_openssl_session_t openssl_session
) {
X509 *x509 = NULL;
RSA *rsa = NULL;
EVP_PKEY *pubkey = NULL;
CK_RV rv = CKR_OK;
- unsigned char certificate[10*1024];
- size_t certificate_size;
pkcs11_openssl_d2i_t d2i1 = NULL;
- bool fOK = true;
+ PKCS11H_BOOL fOK = TRUE;
- PKCS11ASSERT (pkcs11h_openssl_session!=NULL);
- PKCS11ASSERT (!pkcs11h_openssl_session->fInitialized);
+ PKCS11H_ASSERT (openssl_session!=NULL);
+ PKCS11H_ASSERT (!openssl_session->fInitialized);
+ PKCS11H_ASSERT (openssl_session!=NULL);
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_openssl_getRSA - entry pkcs11h_openssl_session=%p",
- (void *)pkcs11h_openssl_session
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_openssl_getRSA - entry openssl_session=%p",
+ (void *)openssl_session
);
if (
fOK &&
(x509 = X509_new ()) == NULL
) {
- fOK = false;
- PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Unable to allocate certificate object");
+ fOK = FALSE;
+ PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Unable to allocate certificate object");
}
- certificate_size = sizeof (certificate);
if (
fOK &&
- (rv = pkcs11h_getCertificate (
- pkcs11h_openssl_session->certificate,
- certificate,
- &certificate_size
- )) != CKR_OK
- ) {
- fOK = false;
- PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot read X.509 certificate from token %ld-'%s'", rv, pkcs11h_getMessage (rv));
+ (rv = _pkcs11h_ensureCertificateBlob (openssl_session->certificate)) != CKR_OK
+ ) {
+ fOK = FALSE;
+ PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot read X.509 certificate from token %ld-'%s'", rv, pkcs11h_getMessage (rv));
}
- d2i1 = (pkcs11_openssl_d2i_t)certificate;
+ d2i1 = (pkcs11_openssl_d2i_t)openssl_session->certificate->id->certificate_blob;
if (
fOK &&
- !d2i_X509 (&x509, &d2i1, certificate_size)
+ !d2i_X509 (&x509, &d2i1, openssl_session->certificate->id->certificate_blob_size)
) {
- fOK = false;
- PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Unable to parse X.509 certificate");
+ fOK = FALSE;
+ PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Unable to parse X.509 certificate");
}
if (
fOK &&
(pubkey = X509_get_pubkey (x509)) == NULL
) {
- fOK = false;
- PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot get public key");
+ fOK = FALSE;
+ PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot get public key");
}
if (
fOK &&
pubkey->type != EVP_PKEY_RSA
) {
- fOK = false;
- PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Invalid public key algorithm");
+ fOK = FALSE;
+ PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Invalid public key algorithm");
}
if (
fOK &&
(rsa = EVP_PKEY_get1_RSA (pubkey)) == NULL
) {
- fOK = false;
- PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot get RSA key");
+ fOK = FALSE;
+ PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot get RSA key");
}
- if (fOK) {
- const RSA_METHOD *def = RSA_get_default_method();
-
- memmove (&pkcs11h_openssl_session->smart_rsa, def, sizeof(RSA_METHOD));
-
- pkcs11h_openssl_session->orig_finish = def->finish;
-
- pkcs11h_openssl_session->smart_rsa.name = "pkcs11";
- pkcs11h_openssl_session->smart_rsa.rsa_priv_dec = _pkcs11h_openssl_dec;
- pkcs11h_openssl_session->smart_rsa.rsa_sign = _pkcs11h_openssl_sign;
- pkcs11h_openssl_session->smart_rsa.finish = _pkcs11h_openssl_finish;
- pkcs11h_openssl_session->smart_rsa.flags = RSA_METHOD_FLAG_NO_CHECK | RSA_FLAG_EXT_PKEY;
+ if (fOK) {
- RSA_set_method (rsa, &pkcs11h_openssl_session->smart_rsa);
- RSA_set_app_data (rsa, pkcs11h_openssl_session);
- pkcs11h_openssl_session->nReferenceCount++;
+ RSA_set_method (rsa, &openssl_session->smart_rsa);
+ RSA_set_app_data (rsa, openssl_session);
+ openssl_session->nReferenceCount++;
}
#ifdef BROKEN_OPENSSL_ENGINE
if (fOK) {
- if (!rsa->engine)
+ if (!rsa->engine) {
rsa->engine = ENGINE_get_default_RSA();
+ }
- ENGINE_set_RSA(ENGINE_get_default_RSA(), &pkcs11h_openssl_session->smart_rsa);
- PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: OpenSSL engine support is broken! Workaround enabled");
+ ENGINE_set_RSA(ENGINE_get_default_RSA(), &openssl_session->smart_rsa);
+ PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: OpenSSL engine support is broken! Workaround enabled");
}
#endif
if (fOK) {
/*
- So that it won't hold RSA
- */
- pkcs11h_openssl_session->x509 = X509_dup (x509);
+ * dup x509 so that it won't hold RSA
+ */
+ openssl_session->x509 = X509_dup (x509);
rsa->flags |= RSA_FLAG_SIGN_VER;
- pkcs11h_openssl_session->fInitialized = true;
+ openssl_session->fInitialized = TRUE;
}
else {
if (rsa != NULL) {
@@ -3169,8 +9073,8 @@ pkcs11h_openssl_getRSA (
x509 = NULL;
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
"PKCS#11: pkcs11h_openssl_getRSA - return rsa=%p",
(void *)rsa
);
@@ -3180,24 +9084,24 @@ pkcs11h_openssl_getRSA (
X509 *
pkcs11h_openssl_getX509 (
- IN const pkcs11h_openssl_session_t pkcs11h_openssl_session
+ IN const pkcs11h_openssl_session_t openssl_session
) {
X509 *x509 = NULL;
- PKCS11ASSERT (pkcs11h_openssl_session!=NULL);
+ PKCS11H_ASSERT (openssl_session!=NULL);
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: pkcs11h_openssl_getX509 - entry pkcs11h_openssl_session=%p",
- (void *)pkcs11h_openssl_session
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_openssl_getX509 - entry openssl_session=%p",
+ (void *)openssl_session
);
- if (pkcs11h_openssl_session->x509 != NULL) {
- x509 = X509_dup (pkcs11h_openssl_session->x509);
+ if (openssl_session->x509 != NULL) {
+ x509 = X509_dup (openssl_session->x509);
}
- PKCS11DLOG (
- PKCS11_LOG_DEBUG2,
+ PKCS11H_DEBUG (
+ PKCS11H_LOG_DEBUG2,
"PKCS#11: pkcs11h_openssl_getX509 - return x509=%p",
(void *)x509
);
@@ -3205,6 +9109,12 @@ pkcs11h_openssl_getX509 (
return x509;
}
+#endif /* ENABLE_PKCS11H_OPENSSL */
+
+#if defined(ENABLE_PKCS11H_STANDALONE)
+/*======================================================================*
+ * STANDALONE INTERFACE
+ *======================================================================*/
void
pkcs11h_standalone_dump_slots (
@@ -3216,7 +9126,9 @@ pkcs11h_standalone_dump_slots (
pkcs11h_provider_t pkcs11h_provider;
- PKCS11ASSERT (provider!=NULL);
+ PKCS11H_ASSERT (my_output!=NULL);
+ /*PKCS11H_ASSERT (pData) NOT NEEDED */
+ PKCS11H_ASSERT (provider!=NULL);
if (
rv == CKR_OK &&
@@ -3227,7 +9139,18 @@ pkcs11h_standalone_dump_slots (
if (
rv == CKR_OK &&
- (rv = pkcs11h_addProvider (provider, NULL)) != CKR_OK
+ (rv = pkcs11h_addProvider (
+ provider,
+ provider,
+ FALSE,
+ (
+ PKCS11H_SIGNMODE_MASK_SIGN |
+ PKCS11H_SIGNMODE_MASK_RECOVER
+ ),
+ PKCS11H_SLOTEVENT_METHOD_AUTO,
+ 0,
+ FALSE
+ )) != CKR_OK
) {
my_output (pData, "PKCS#11: Cannot initialize provider %ld-'%s'\n", rv, pkcs11h_getMessage (rv));
}
@@ -3236,7 +9159,7 @@ pkcs11h_standalone_dump_slots (
* our provider is head
*/
if (rv == CKR_OK) {
- pkcs11h_provider = pkcs11h_data->providers;
+ pkcs11h_provider = s_pkcs11h_data->providers;
if (pkcs11h_provider == NULL || !pkcs11h_provider->fEnabled) {
my_output (pData, "PKCS#11: Cannot get provider %ld-'%s'\n", rv, pkcs11h_getMessage (rv));
rv = CKR_GENERAL_ERROR;
@@ -3254,8 +9177,8 @@ pkcs11h_standalone_dump_slots (
char szManufacturerID[sizeof (info.manufacturerID)+1];
_pkcs11h_fixupFixedString (
- (char *)info.manufacturerID,
szManufacturerID,
+ (char *)info.manufacturerID,
sizeof (info.manufacturerID)
);
@@ -3277,17 +9200,17 @@ pkcs11h_standalone_dump_slots (
}
if (rv == CKR_OK) {
- CK_SLOT_ID slots[1024];
+ CK_SLOT_ID_PTR slots = NULL;
CK_ULONG slotnum;
- CK_SLOT_ID s;
+ CK_SLOT_ID slot_index;
- slotnum = sizeof (slots) / sizeof (CK_SLOT_ID);
if (
- (rv = pkcs11h_provider->f->C_GetSlotList (
- FALSE,
- slots,
+ _pkcs11h_getSlotList (
+ pkcs11h_provider,
+ CK_FALSE,
+ &slots,
&slotnum
- )) != CKR_OK
+ ) != CKR_OK
) {
my_output (pData, "PKCS#11: Cannot get slot list %ld-'%s'\n", rv, pkcs11h_getMessage (rv));
}
@@ -3301,48 +9224,93 @@ pkcs11h_standalone_dump_slots (
"\n"
"Slots: (id - name)\n"
),
- PKCS11_PRM_SLOT_TYPE,
- PKCS11_PRM_SLOT_ID
+ PKCS11H_PRM_SLOT_TYPE,
+ PKCS11H_PRM_SLOT_ID
);
- for (s=0;s<slotnum;s++) {
+ for (slot_index=0;slot_index < slotnum;slot_index++) {
CK_SLOT_INFO info;
if (
(rv = pkcs11h_provider->f->C_GetSlotInfo (
- slots[s],
+ slots[slot_index],
&info
)) == CKR_OK
) {
char szCurrentName[sizeof (info.slotDescription)+1];
_pkcs11h_fixupFixedString (
- (char *)info.slotDescription,
szCurrentName,
+ (char *)info.slotDescription,
sizeof (info.slotDescription)
);
- my_output (pData, "\t%lu - %s\n", slots[s], szCurrentName);
+ my_output (pData, "\t%lu - %s\n", slots[slot_index], szCurrentName);
}
}
}
+
+ if (slots != NULL) {
+ _pkcs11h_free ((void *)&slots);
+ }
}
pkcs11h_terminate ();
}
static
-bool
+PKCS11H_BOOL
_pkcs11h_standalone_dump_objects_pin_prompt (
IN const void *pData,
- IN const char * const szLabel,
+ IN const pkcs11h_token_id_t token,
OUT char * const szPIN,
IN const size_t nMaxPIN
) {
strncpy (szPIN, (char *)pData, nMaxPIN);
- return true;
+ return TRUE;
}
void
+_pkcs11h_standalone_dump_objects_hex (
+ IN const unsigned char * const p,
+ IN const size_t p_size,
+ OUT char * const sz,
+ IN const size_t max,
+ IN const char * const szLinePrefix
+) {
+ size_t j;
+
+ sz[0] = '\0';
+
+ for (j=0;j<p_size;j+=16) {
+ char szLine[3*16+1];
+ size_t k;
+
+ szLine[0] = '\0';
+ for (k=0;k<16 && j+k<p_size;k++) {
+ sprintf (szLine+strlen (szLine), "%02x ", p[j+k]);
+ }
+
+ strncat (
+ sz,
+ szLinePrefix,
+ max-1-strlen (sz)
+ );
+ strncat (
+ sz,
+ szLine,
+ max-1-strlen (sz)
+ );
+ strncat (
+ sz,
+ "\n",
+ max-1-strlen (sz)
+ );
+ }
+
+ sz[max-1] = '\0';
+}
+
+void
pkcs11h_standalone_dump_objects (
IN const pkcs11h_output_print_t my_output,
IN const void *pData,
@@ -3353,11 +9321,15 @@ pkcs11h_standalone_dump_objects (
CK_SLOT_ID s;
CK_RV rv = CKR_OK;
- pkcs11h_provider_t pkcs11h_provider;
+ pkcs11h_provider_t pkcs11h_provider = NULL;
+ pkcs11h_token_id_t token_id = NULL;
+ pkcs11h_session_t session = NULL;
- PKCS11ASSERT (provider!=NULL);
- PKCS11ASSERT (slot!=NULL);
- PKCS11ASSERT (pin!=NULL);
+ PKCS11H_ASSERT (my_output!=NULL);
+ /*PKCS11H_ASSERT (pData) NOT NEEDED */
+ PKCS11H_ASSERT (provider!=NULL);
+ PKCS11H_ASSERT (slot!=NULL);
+ PKCS11H_ASSERT (pin!=NULL);
s = atoi (slot);
@@ -3377,16 +9349,27 @@ pkcs11h_standalone_dump_objects (
if (
rv == CKR_OK &&
- (rv = pkcs11h_addProvider (provider, NULL)) != CKR_OK
+ (rv = pkcs11h_addProvider (
+ provider,
+ provider,
+ FALSE,
+ (
+ PKCS11H_SIGNMODE_MASK_SIGN |
+ PKCS11H_SIGNMODE_MASK_RECOVER
+ ),
+ PKCS11H_SLOTEVENT_METHOD_AUTO,
+ 0,
+ FALSE
+ )) != CKR_OK
) {
my_output (pData, "PKCS#11: Cannot initialize provider %ld-'%s'\n", rv, pkcs11h_getMessage (rv));
}
- /*
+ /*
* our provider is head
*/
if (rv == CKR_OK) {
- pkcs11h_provider = pkcs11h_data->providers;
+ pkcs11h_provider = s_pkcs11h_data->providers;
if (pkcs11h_provider == NULL || !pkcs11h_provider->fEnabled) {
my_output (pData, "PKCS#11: Cannot get provider %ld-'%s'\n", rv, pkcs11h_getMessage (rv));
rv = CKR_GENERAL_ERROR;
@@ -3403,6 +9386,7 @@ pkcs11h_standalone_dump_objects (
)) != CKR_OK
) {
my_output (pData, "PKCS#11: Cannot get token information for slot %ld %ld-'%s'\n", s, rv, pkcs11h_getMessage (rv));
+ /* Ignore this error */
rv = CKR_OK;
}
else {
@@ -3412,23 +9396,23 @@ pkcs11h_standalone_dump_objects (
char szSerialNumber[sizeof (info.serialNumber)+1];
_pkcs11h_fixupFixedString (
- (char *)info.label,
szLabel,
+ (char *)info.label,
sizeof (info.label)
);
_pkcs11h_fixupFixedString (
- (char *)info.manufacturerID,
szManufacturerID,
+ (char *)info.manufacturerID,
sizeof (info.manufacturerID)
);
_pkcs11h_fixupFixedString (
- (char *)info.model,
szModel,
+ (char *)info.model,
sizeof (info.model)
);
_pkcs11h_fixupFixedString (
- (char *)info.serialNumber,
szSerialNumber,
+ (char *)info.serialNumber,
sizeof (info.serialNumber)
);
@@ -3451,256 +9435,449 @@ pkcs11h_standalone_dump_objects (
szModel,
szSerialNumber,
(unsigned)info.flags,
- PKCS11_PRM_SLOT_TYPE,
- PKCS11_PRM_SLOT_ID,
+ PKCS11H_PRM_SLOT_TYPE,
+ PKCS11H_PRM_SLOT_ID,
szLabel
);
+
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_getTokenId (
+ &info,
+ &token_id
+ )) != CKR_OK
+ ) {
+ my_output (pData, "PKCS#11: Cannot get token id for slot %ld %ld-'%s'\n", s, rv, pkcs11h_getMessage (rv));
+ rv = CKR_OK;
+ }
}
}
- if (rv == CKR_OK) {
- CK_SESSION_HANDLE session;
-
+ if (token_id != NULL) {
if (
- (rv = pkcs11h_provider->f->C_OpenSession (
- s,
- CKF_SERIAL_SESSION,
- NULL_PTR,
- NULL_PTR,
+ (rv = _pkcs11h_getSessionByTokenId (
+ token_id,
&session
)) != CKR_OK
) {
- my_output (pData, "PKCS#11: Cannot open session to slot %ld %ld-'%s'\n", s, rv, pkcs11h_getMessage (rv));
+ my_output (pData, "PKCS#11: Cannot session for token '%s' %ld-'%s'\n", token_id->label, rv, pkcs11h_getMessage (rv));
rv = CKR_OK;
}
- else {
- CK_OBJECT_HANDLE objects[10];
- CK_ULONG objects_found;
+ }
+
+ if (session != NULL) {
+ CK_OBJECT_HANDLE *objects = NULL;
+ CK_ULONG objects_found = 0;
+ CK_ULONG i;
+
+ if (
+ (rv = _pkcs11h_login (
+ session,
+ FALSE,
+ TRUE,
+ PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT
+ )) != CKR_OK
+ ) {
+ my_output (pData, "PKCS#11: Cannot open session to token '%s' %ld-'%s'\n", session->token_id->label, rv, pkcs11h_getMessage (rv));
+ }
+ my_output (
+ pData,
+ (
+ "The following objects are available for use with this token.\n"
+ "Each object shown below may be used as a parameter to\n"
+ "%s and %s options.\n"
+ "\n"
+ ),
+ PKCS11H_PRM_OBJ_TYPE,
+ PKCS11H_PRM_OBJ_ID
+ );
+
+ if (
+ rv == CKR_OK &&
+ (rv = _pkcs11h_findObjects (
+ session,
+ NULL,
+ 0,
+ &objects,
+ &objects_found
+ )) != CKR_OK
+ ) {
+ my_output (pData, "PKCS#11: Cannot query objects for token '%s' %ld-'%s'\n", session->token_id->label, rv, pkcs11h_getMessage (rv));
+ }
+
+ for (i=0;rv == CKR_OK && i < objects_found;i++) {
+ CK_OBJECT_CLASS attrs_class = 0;
+ CK_ATTRIBUTE attrs[] = {
+ {CKA_CLASS, &attrs_class, sizeof (attrs_class)}
+ };
+
if (
- (rv = pkcs11h_provider->f->C_Login (
- session,
- CKU_USER,
- (CK_CHAR_PTR)pin,
- (CK_ULONG)strlen (pin)
- )) != CKR_OK &&
- rv != CKR_USER_ALREADY_LOGGED_IN
- ) {
- my_output (pData, "PKCS#11: Cannot login to token on slot %ld %ld-'%s'\n", s, rv, pkcs11h_getMessage (rv));
- }
-
- if (
- (rv = pkcs11h_provider->f->C_FindObjectsInit (
+ _pkcs11h_getObjectAttributes (
session,
- NULL,
- 0
- )) != CKR_OK
+ objects[i],
+ attrs,
+ sizeof (attrs) / sizeof (CK_ATTRIBUTE)
+ ) == CKR_OK
) {
- my_output (pData, "PKCS#11: Cannot query objects for token on slot %ld %ld-'%s'\n", s, rv, pkcs11h_getMessage (rv));
- }
-
- my_output (
- pData,
- (
- "The following objects are available for use with this token.\n"
- "Each object shown below may be used as a parameter to\n"
- "%s and %s options.\n"
- "\n"
- ),
- PKCS11_PRM_OBJ_TYPE,
- PKCS11_PRM_OBJ_ID
- );
-
- while (
- (rv = pkcs11h_provider->f->C_FindObjects (
- session,
- objects,
- sizeof (objects) / sizeof (CK_OBJECT_HANDLE),
- &objects_found
- )) == CKR_OK &&
- objects_found > 0
- ) {
- CK_ULONG i;
-
- for (i=0;i<objects_found;i++) {
- CK_OBJECT_CLASS attrs_class;
- unsigned char attrs_id[PKCS11H_MAX_ATTRIBUTE_SIZE];
- unsigned char attrs_label[PKCS11H_MAX_ATTRIBUTE_SIZE];
- CK_ATTRIBUTE attrs[] = {
- {CKA_CLASS, &attrs_class, sizeof (attrs_class)},
- {CKA_ID, attrs_id, sizeof (attrs_id)},
- {CKA_LABEL, attrs_label, sizeof (attrs_label)-1}
+ if (attrs_class == CKO_CERTIFICATE) {
+ CK_ATTRIBUTE attrs_cert[] = {
+ {CKA_ID, NULL, 0},
+ {CKA_LABEL, NULL, 0},
+ {CKA_VALUE, NULL, 0}
};
-
+ unsigned char *attrs_id = NULL;
+ int attrs_id_size = 0;
+ unsigned char *attrs_value = NULL;
+ int attrs_value_size = 0;
+ char *attrs_label = NULL;
+ char szHexId[1024];
+ char szSubject[1024];
+ char szSerial[1024];
+ char szNotBefore[1024];
+
+ szSubject[0] = '\0';
+ szSerial[0] = '\0';
+ szNotBefore[0] = '\0';
+
+
if (
- pkcs11h_provider->f->C_GetAttributeValue (
+ _pkcs11h_getObjectAttributes (
session,
objects[i],
- attrs,
- sizeof (attrs) / sizeof (CK_ATTRIBUTE)
+ attrs_cert,
+ sizeof (attrs_cert) / sizeof (CK_ATTRIBUTE)
+ ) == CKR_OK &&
+ _pkcs11h_malloc (
+ (void *)&attrs_label,
+ attrs_cert[1].ulValueLen+1
) == CKR_OK
) {
- int id_len = attrs[1].ulValueLen;
- int j;
-
- attrs_label[attrs[2].ulValueLen] = 0;
-
- my_output (
- pData,
- (
- "Object\n"
- "\tLabel:\t\t%s\n"
- "\tId:\n"
- ),
- attrs_label
+ attrs_id = (unsigned char *)attrs_cert[0].pValue;
+ attrs_id_size = attrs_cert[0].ulValueLen;
+ attrs_value = (unsigned char *)attrs_cert[2].pValue;
+ attrs_value_size = attrs_cert[2].ulValueLen;
+
+ memset (attrs_label, 0, attrs_cert[1].ulValueLen+1);
+ memmove (attrs_label, attrs_cert[1].pValue, attrs_cert[1].ulValueLen);
+ _pkcs11h_standalone_dump_objects_hex (
+ attrs_id,
+ attrs_id_size,
+ szHexId,
+ sizeof (szHexId),
+ "\t\t"
);
-
-
- for (j=0;j<id_len;j+=16) {
- char szLine[3*16+1];
- int k;
-
- szLine[0] = '\0';
- for (k=0;k<16 && j+k<id_len;k++) {
- sprintf (szLine+strlen (szLine), "%02x ", attrs_id[j+k]);
- }
-
- my_output (pData, "\t\t%s\n", szLine);
+ }
+
+ if (attrs_value != NULL) {
+ X509 *x509 = NULL;
+ BIO *bioSerial = NULL;
+
+ if ((x509 = X509_new ()) == NULL) {
+ my_output (pData, "Cannot create x509 context\n");
}
-
- if (attrs_class == CKO_CERTIFICATE) {
- unsigned char certificate[PKCS11H_MAX_ATTRIBUTE_SIZE];
- CK_ATTRIBUTE attrs_cert[] = {
- {CKA_VALUE, certificate, sizeof (certificate)}
- };
-
- my_output (pData, "\tType:\t\tCertificate\n");
-
- if (
- pkcs11h_provider->f->C_GetAttributeValue (
- session,
- objects[i],
- attrs_cert,
- sizeof (attrs_cert) / sizeof (CK_ATTRIBUTE)
- ) == CKR_OK
- ) {
- X509 *x509 = NULL;
- BIO *bioSerial = NULL;
-
- char szSubject[1024];
- char szSerial[1024];
- char szNotBefore[1024];
-
- szSubject[0] = '\0';
- szSerial[0] = '\0';
- szNotBefore[0] = '\0';
-
- if ((x509 = X509_new ()) == NULL) {
- my_output (pData, "Cannot create x509 context\n");
- }
- else {
- pkcs11_openssl_d2i_t d2i1 = (pkcs11_openssl_d2i_t)certificate;
- if (d2i_X509 (&x509, &d2i1, attrs_cert[0].ulValueLen)) {
-
- ASN1_TIME *notBefore = X509_get_notBefore (x509);
- if (notBefore != NULL && notBefore->length < (int) sizeof (szNotBefore) - 1) {
- memmove (szNotBefore, notBefore->data, notBefore->length);
- szNotBefore[notBefore->length] = '\0';
- }
-
- X509_NAME_oneline (
- X509_get_subject_name (x509),
- szSubject,
- sizeof (szSubject)
- );
- szSubject[sizeof (szSubject) - 1] = '\0';
- }
- }
-
- if ((bioSerial = BIO_new (BIO_s_mem ())) == NULL) {
- my_output (pData, "Cannot create BIO context\n");
- }
- else {
- int n;
-
- i2a_ASN1_INTEGER(bioSerial, X509_get_serialNumber (x509));
- n = BIO_read (bioSerial, szSerial, sizeof (szSerial)-1);
- if (n<0) {
- szSerial[0] = '\0';
- }
- else {
- szSerial[n] = '\0';
- }
- }
-
-
- if (x509 != NULL) {
- X509_free (x509);
- x509 = NULL;
- }
- if (bioSerial != NULL) {
- BIO_free_all (bioSerial);
- bioSerial = NULL;
+ else {
+ pkcs11_openssl_d2i_t d2i1 = (pkcs11_openssl_d2i_t)attrs_value;
+ if (d2i_X509 (&x509, &d2i1, attrs_value_size)) {
+
+ ASN1_TIME *notBefore = X509_get_notBefore (x509);
+ if (notBefore != NULL && notBefore->length < (int) sizeof (szNotBefore) - 1) {
+ memmove (szNotBefore, notBefore->data, notBefore->length);
+ szNotBefore[notBefore->length] = '\0';
}
-
- my_output (
- pData,
- (
- "\tsubject:\t%s\n"
- "\tserialNumber:\t%s\n"
- "\tnotBefore:\t%s\n"
- ),
+
+ X509_NAME_oneline (
+ X509_get_subject_name (x509),
szSubject,
- szSerial,
- szNotBefore
+ sizeof (szSubject)
);
+ szSubject[sizeof (szSubject) - 1] = '\0';
}
}
- else if (attrs_class == CKO_PRIVATE_KEY) {
- CK_BBOOL sign_recover;
- CK_BBOOL sign;
- CK_ATTRIBUTE attrs_key[] = {
- {CKA_SIGN, &sign_recover, sizeof (sign_recover)},
- {CKA_SIGN_RECOVER, &sign, sizeof (sign)}
- };
-
- my_output (pData, "\tType:\t\tPrivate Key\n");
-
- if (
- pkcs11h_provider->f->C_GetAttributeValue (
- session,
- objects[i],
- attrs_key,
- sizeof (attrs_key) / sizeof (CK_ATTRIBUTE)
- ) == CKR_OK
- ) {
- my_output (
- pData,
- (
- "\tSign:\t\t%s\n"
- "\tSign Recover:\t%s\n"
- ),
- sign ? "TRUE" : "FALSE",
- sign_recover ? "TRUE" : "FALSE"
- );
- }
+
+ if ((bioSerial = BIO_new (BIO_s_mem ())) == NULL) {
+ my_output (pData, "Cannot create BIO context\n");
}
else {
- my_output (pData, "\tType:\t\tUnsupported\n");
+ int n;
+
+ i2a_ASN1_INTEGER(bioSerial, X509_get_serialNumber (x509));
+ n = BIO_read (bioSerial, szSerial, sizeof (szSerial)-1);
+ if (n<0) {
+ szSerial[0] = '\0';
+ }
+ else {
+ szSerial[n] = '\0';
+ }
+ }
+
+ if (x509 != NULL) {
+ X509_free (x509);
+ x509 = NULL;
+ }
+ if (bioSerial != NULL) {
+ BIO_free_all (bioSerial);
+ bioSerial = NULL;
}
}
+
+ my_output (
+ pData,
+ (
+ "Object\n"
+ "\tType:\t\t\tCertificate\n"
+ "\tCKA_ID:\n"
+ "%s"
+ "\tCKA_LABEL:\t\t%s\n"
+ "\tsubject:\t\t%s\n"
+ "\tserialNumber:\t\t%s\n"
+ "\tnotBefore:\t\t%s\n"
+ ),
+ szHexId,
+ attrs_label,
+ szSubject,
+ szSerial,
+ szNotBefore
+ );
+
+ _pkcs11h_free ((void *)&attrs_label);
+
+ _pkcs11h_freeObjectAttributes (
+ attrs_cert,
+ sizeof (attrs_cert) / sizeof (CK_ATTRIBUTE)
+ );
+ }
+ else if (attrs_class == CKO_PRIVATE_KEY) {
+ CK_BBOOL sign_recover = CK_FALSE;
+ CK_BBOOL sign = CK_FALSE;
+ CK_ATTRIBUTE attrs_key[] = {
+ {CKA_SIGN, &sign_recover, sizeof (sign_recover)},
+ {CKA_SIGN_RECOVER, &sign, sizeof (sign)}
+ };
+ CK_ATTRIBUTE attrs_key_common[] = {
+ {CKA_ID, NULL, 0},
+ {CKA_LABEL, NULL, 0}
+ };
+ unsigned char *attrs_id = NULL;
+ int attrs_id_size = 0;
+ char *attrs_label = NULL;
+ char szHexId[1024];
+
+ pkcs11h_provider->f->C_GetAttributeValue (
+ session->hSession,
+ objects[i],
+ attrs_key,
+ sizeof (attrs_key) / sizeof (CK_ATTRIBUTE)
+ );
+
+ if (
+ _pkcs11h_getObjectAttributes (
+ session,
+ objects[i],
+ attrs_key_common,
+ sizeof (attrs_key_common) / sizeof (CK_ATTRIBUTE)
+ ) == CKR_OK &&
+ _pkcs11h_malloc (
+ (void *)&attrs_label,
+ attrs_key_common[1].ulValueLen+1
+ ) == CKR_OK
+ ) {
+ attrs_id = (unsigned char *)attrs_key_common[0].pValue;
+ attrs_id_size = attrs_key_common[0].ulValueLen;
+
+ memset (attrs_label, 0, attrs_key_common[1].ulValueLen+1);
+ memmove (attrs_label, attrs_key_common[1].pValue, attrs_key_common[1].ulValueLen);
+
+ _pkcs11h_standalone_dump_objects_hex (
+ attrs_id,
+ attrs_id_size,
+ szHexId,
+ sizeof (szHexId),
+ "\t\t"
+ );
+
+ }
+
+ my_output (
+ pData,
+ (
+ "Object\n"
+ "\tType:\t\t\tPrivate Key\n"
+ "\tCKA_ID:\n"
+ "%s"
+ "\tCKA_LABEL:\t\t%s\n"
+ "\tCKA_SIGN:\t\t%s\n"
+ "\tCKA_SIGN_RECOVER:\t%s\n"
+ ),
+ szHexId,
+ attrs_label,
+ sign ? "TRUE" : "FALSE",
+ sign_recover ? "TRUE" : "FALSE"
+ );
+
+ _pkcs11h_free ((void *)&attrs_label);
+
+ _pkcs11h_freeObjectAttributes (
+ attrs_key_common,
+ sizeof (attrs_key_common) / sizeof (CK_ATTRIBUTE)
+ );
+ }
+ else if (attrs_class == CKO_PUBLIC_KEY) {
+ CK_ATTRIBUTE attrs_key_common[] = {
+ {CKA_ID, NULL, 0},
+ {CKA_LABEL, NULL, 0}
+ };
+ unsigned char *attrs_id = NULL;
+ int attrs_id_size = 0;
+ char *attrs_label = NULL;
+ char szHexId[1024];
+
+ if (
+ _pkcs11h_getObjectAttributes (
+ session,
+ objects[i],
+ attrs_key_common,
+ sizeof (attrs_key_common) / sizeof (CK_ATTRIBUTE)
+ ) == CKR_OK &&
+ _pkcs11h_malloc (
+ (void *)&attrs_label,
+ attrs_key_common[1].ulValueLen+1
+ ) == CKR_OK
+ ) {
+ attrs_id = (unsigned char *)attrs_key_common[0].pValue;
+ attrs_id_size = attrs_key_common[0].ulValueLen;
+
+ memset (attrs_label, 0, attrs_key_common[1].ulValueLen+1);
+ memmove (attrs_label, attrs_key_common[1].pValue, attrs_key_common[1].ulValueLen);
+
+ _pkcs11h_standalone_dump_objects_hex (
+ attrs_id,
+ attrs_id_size,
+ szHexId,
+ sizeof (szHexId),
+ "\t\t"
+ );
+
+ }
+
+ my_output (
+ pData,
+ (
+ "Object\n"
+ "\tType:\t\t\tPublic Key\n"
+ "\tCKA_ID:\n"
+ "%s"
+ "\tCKA_LABEL:\t\t%s\n"
+ ),
+ szHexId,
+ attrs_label
+ );
+
+ _pkcs11h_free ((void *)&attrs_label);
+
+ _pkcs11h_freeObjectAttributes (
+ attrs_key_common,
+ sizeof (attrs_key_common) / sizeof (CK_ATTRIBUTE)
+ );
+ }
+ else if (attrs_class == CKO_DATA) {
+ CK_ATTRIBUTE attrs_key_common[] = {
+ {CKA_APPLICATION, NULL, 0},
+ {CKA_LABEL, NULL, 0}
+ };
+ char *attrs_application = NULL;
+ char *attrs_label = NULL;
+
+ if (
+ _pkcs11h_getObjectAttributes (
+ session,
+ objects[i],
+ attrs_key_common,
+ sizeof (attrs_key_common) / sizeof (CK_ATTRIBUTE)
+ ) == CKR_OK &&
+ _pkcs11h_malloc (
+ (void *)&attrs_application,
+ attrs_key_common[0].ulValueLen+1
+ ) == CKR_OK &&
+ _pkcs11h_malloc (
+ (void *)&attrs_label,
+ attrs_key_common[1].ulValueLen+1
+ ) == CKR_OK
+ ) {
+ memset (attrs_application, 0, attrs_key_common[0].ulValueLen+1);
+ memmove (attrs_application, attrs_key_common[0].pValue, attrs_key_common[0].ulValueLen);
+ memset (attrs_label, 0, attrs_key_common[1].ulValueLen+1);
+ memmove (attrs_label, attrs_key_common[1].pValue, attrs_key_common[1].ulValueLen);
+ }
+
+ my_output (
+ pData,
+ (
+ "Object\n"
+ "\tType:\t\t\tData\n"
+ "\tCKA_APPLICATION\t\t%s\n"
+ "\tCKA_LABEL:\t\t%s\n"
+ ),
+ attrs_application,
+ attrs_label
+ );
+
+ _pkcs11h_free ((void *)&attrs_application);
+ _pkcs11h_free ((void *)&attrs_label);
+
+ _pkcs11h_freeObjectAttributes (
+ attrs_key_common,
+ sizeof (attrs_key_common) / sizeof (CK_ATTRIBUTE)
+ );
+ }
+ else {
+ my_output (
+ pData,
+ (
+ "Object\n"
+ "\tType:\t\t\tUnsupported\n"
+ )
+ );
}
-
- pkcs11h_provider->f->C_FindObjectsFinal (session);
- pkcs11h_provider->f->C_Logout (session);
- pkcs11h_provider->f->C_CloseSession (session);
}
+
+ _pkcs11h_freeObjectAttributes (
+ attrs,
+ sizeof (attrs) / sizeof (CK_ATTRIBUTE)
+ );
+
+ /*
+ * Ignore any error and
+ * perform next iteration
+ */
+ rv = CKR_OK;
}
+
+ if (objects != NULL) {
+ _pkcs11h_free ((void *)&objects);
+ }
+
+ /*
+ * Ignore this error
+ */
+ rv = CKR_OK;
+ }
+
+ if (session != NULL) {
+ _pkcs11h_releaseSession (session);
+ session = NULL;
+ }
+
+ if (token_id != NULL) {
+ pkcs11h_freeTokenId (token_id);
+ token_id = NULL;
}
pkcs11h_terminate ();
}
+#endif /* ENABLE_PKCS11H_STANDALONE */
+
#ifdef BROKEN_OPENSSL_ENGINE
static void broken_openssl_init() __attribute__ ((constructor));
static void broken_openssl_init()
@@ -3713,4 +9890,5 @@ static void broken_openssl_init()
#else
static void dummy (void) {}
-#endif /* PKCS11_HELPER_ENABLE */
+#endif /* PKCS11H_HELPER_ENABLE */
+
diff --git a/pkcs11-helper.h b/pkcs11-helper.h
index df3db66..27289c4 100644
--- a/pkcs11-helper.h
+++ b/pkcs11-helper.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005 Alon Bar-Lev <alon.barlev@gmail.com>
+ * Copyright (c) 2005-2006 Alon Bar-Lev <alon.barlev@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifi-
@@ -34,225 +34,895 @@
*
*/
-#ifndef __PKCS11_HELPER_H
-#define __PKCS11_HELPER_H
+#ifndef __PKCS11H_HELPER_H
+#define __PKCS11H_HELPER_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
#include "pkcs11-helper-config.h"
-#define PKCS11H_MAX_ATTRIBUTE_SIZE (10*1024)
+#if defined(ENABLE_PKCS11H_SLOTEVENT) && !defined(ENABLE_PKCS11H_THREADING)
+#error PKCS#11: ENABLE_PKCS11H_SLOTEVENT requires ENABLE_PKCS11H_THREADING
+#endif
+#if defined(ENABLE_PKCS11H_OPENSSL) && !defined(ENABLE_PKCS11H_CERTIFICATE)
+#error PKCS#11: ENABLE_PKCS11H_OPENSSL requires ENABLE_PKCS11H_CERTIFICATE
+#endif
+
+#define PKCS11H_LOG_DEBUG2 5
+#define PKCS11H_LOG_DEBUG1 4
+#define PKCS11H_LOG_INFO 3
+#define PKCS11H_LOG_WARN 2
+#define PKCS11H_LOG_ERROR 1
+#define PKCS11H_LOG_QUITE 0
+
#define PKCS11H_PIN_CACHE_INFINITE -1
+#define PKCS11H_SIGNMODE_MASK_SIGN (1<<0)
+#define PKCS11H_SIGNMODE_MASK_RECOVER (1<<1)
+
+#define PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT (1<<0)
+#define PKCS11H_PROMPT_MAST_ALLOW_CARD_PROMPT (1<<1)
+
+#define PKCS11H_SLOTEVENT_METHOD_AUTO 0
+#define PKCS11H_SLOTEVENT_METHOD_TRIGGER 1
+#define PKCS11H_SLOTEVENT_METHOD_POLL 2
+
+#define PKCS11H_ENUM_METHOD_CACHE 0
+#define PKCS11H_ENUM_METHOD_CACHE_EXIST 1
+#define PKCS11H_ENUM_METHOD_RELOAD 2
+
typedef void (*pkcs11h_output_print_t)(
IN const void *pData,
IN const char * const szFormat,
IN ...
+)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+ ;
+
+struct pkcs11h_token_id_s;
+typedef struct pkcs11h_token_id_s *pkcs11h_token_id_t;
+
+#if defined(ENABLE_PKCS11H_CERTIFICATE)
+
+struct pkcs11h_certificate_id_s;
+struct pkcs11h_certificate_s;
+typedef struct pkcs11h_certificate_id_s *pkcs11h_certificate_id_t;
+typedef struct pkcs11h_certificate_s *pkcs11h_certificate_t;
+
+#endif /* ENABLE_PKCS11H_CERTIFICATE */
+
+#if defined(ENABLE_PKCS11H_ENUM)
+
+struct pkcs11h_token_id_list_s;
+typedef struct pkcs11h_token_id_list_s *pkcs11h_token_id_list_t;
+
+#if defined(ENABLE_PKCS11H_DATA)
+
+struct pkcs11h_data_id_list_s;
+typedef struct pkcs11h_data_id_list_s *pkcs11h_data_id_list_t;
+
+#endif /* ENABLE_PKCS11H_DATA */
+
+#if defined(ENABLE_PKCS11H_CERTIFICATE)
+
+struct pkcs11h_certificate_id_list_s;
+typedef struct pkcs11h_certificate_id_list_s *pkcs11h_certificate_id_list_t;
+
+#endif /* ENABLE_PKCS11H_CERTIFICATE */
+
+#endif /* ENABLE_PKCS11H_ENUM */
+
+typedef void (*pkcs11h_hook_log_t)(
+ IN const void *pData,
+ IN const unsigned flags,
+ IN const char * const szFormat,
+ IN va_list args
);
-typedef bool (*pkcs11h_hook_card_prompt_t)(
+typedef void (*pkcs11h_hook_slotevent_t)(
+ IN const void *pData
+);
+
+typedef PKCS11H_BOOL (*pkcs11h_hook_token_prompt_t)(
IN const void *pData,
- IN const char * const szLabel
+ IN const pkcs11h_token_id_t token
);
-typedef bool (*pkcs11h_hook_pin_prompt_t)(
+typedef PKCS11H_BOOL (*pkcs11h_hook_pin_prompt_t)(
IN const void *pData,
- IN const char * const szLabel,
+ IN const pkcs11h_token_id_t token,
OUT char * const szPIN,
IN const size_t nMaxPIN
);
+struct pkcs11h_token_id_s {
+ char label[1024];
+ char manufacturerID[sizeof (((CK_TOKEN_INFO *)NULL)->manufacturerID)+1];
+ char model[sizeof (((CK_TOKEN_INFO *)NULL)->model)+1];
+ char serialNumber[sizeof (((CK_TOKEN_INFO *)NULL)->serialNumber)+1];
+};
+
+#if defined(ENABLE_PKCS11H_CERTIFICATE)
+
+struct pkcs11h_certificate_id_s {
+ pkcs11h_token_id_t token_id;
-typedef struct pkcs11h_hooks_s {
- void *card_prompt_data;
- void *pin_prompt_data;
- pkcs11h_hook_card_prompt_t card_prompt;
- pkcs11h_hook_pin_prompt_t pin_prompt;
-} *pkcs11h_hooks_t;
+ char displayName[1024];
+ CK_BYTE_PTR attrCKA_ID;
+ size_t attrCKA_ID_size;
-typedef struct pkcs11h_provider_s {
- struct pkcs11h_provider_s *next;
+ unsigned char *certificate_blob;
+ size_t certificate_blob_size;
+};
- bool fEnabled;
- char *szName;
-
-#if defined(WIN32)
- HANDLE hLibrary;
-#else
- void *hLibrary;
#endif
- CK_FUNCTION_LIST_PTR f;
- bool fShouldFinalize;
- char *szSignMode;
-} *pkcs11h_provider_t;
+#if defined(ENABLE_PKCS11H_ENUM)
-typedef struct pkcs11h_session_s {
- struct pkcs11h_session_s *next;
+struct pkcs11h_token_id_list_s {
+ pkcs11h_token_id_list_t next;
+ pkcs11h_token_id_t token_id;
+};
- int nReferenceCount;
- bool fValid;
+#if defined(ENABLE_PKCS11H_DATA)
- pkcs11h_provider_t provider;
+struct pkcs11h_data_id_list_s {
+ pkcs11h_data_id_list_t next;
- bool fProtectedAuthentication;
+ char *application;
+ char *label;
+};
- char szLabel[sizeof (((CK_TOKEN_INFO *)NULL)->label)+1];
- CK_CHAR serialNumber[sizeof (((CK_TOKEN_INFO *)NULL)->serialNumber)];
+#endif /* ENABLE_PKCS11H_DATA */
- CK_SESSION_HANDLE hSession;
+#if defined(ENABLE_PKCS11H_CERTIFICATE)
- int nPINCachePeriod;
- time_t timePINExpire;
-} *pkcs11h_session_t;
+struct pkcs11h_certificate_id_list_s {
+ pkcs11h_certificate_id_list_t next;
+ pkcs11h_certificate_id_t certificate_id;
+};
-typedef struct pkcs11h_certificate_s {
+#endif /* ENABLE_PKCS11H_CERTIFICATE */
- pkcs11h_session_t session;
+#endif /* ENABLE_PKCS11H_CERTIFICATE */
- unsigned char *certificate;
- size_t certificate_size;
- unsigned char *certificate_id;
- size_t certificate_id_size;
+#if defined(ENABLE_PKCS11H_OPENSSL)
- enum {
- pkcs11h_signmode_none = 0,
- pkcs11h_signmode_sign,
- pkcs11h_signmode_recover
- } signmode;
+struct pkcs11h_openssl_session_s;
+typedef struct pkcs11h_openssl_session_s *pkcs11h_openssl_session_t;
- CK_OBJECT_HANDLE hKey;
+#endif /* ENABLE_PKCS11H_OPENSSL */
- bool fCertPrivate;
-} *pkcs11h_certificate_t;
+/*
+ * pkcs11h_getMessage - Get message by return value.
+ *
+ * Parameters:
+ * rv - Return value.
+ */
+char *
+pkcs11h_getMessage (
+ IN const int rv
+);
-typedef struct pkcs11h_data_s {
- bool fInitialized;
- int nPINCachePeriod;
+/*
+ * pkcs11h_initialize - Inititalize helper interface.
+ *
+ * Must be called once, from main thread.
+ * Defaults:
+ * Protected authentication enabled.
+ * PIN cached is infinite.
+ */
+CK_RV
+pkcs11h_initialize ();
- pkcs11h_provider_t providers;
- pkcs11h_session_t sessions;
- pkcs11h_hooks_t hooks;
+/*
+ * pkcs11h_terminate - Terminate helper interface.
+ *
+ * Must be called once, from main thread, after all
+ * related resources freed.
+ */
+CK_RV
+pkcs11h_terminate ();
- CK_SESSION_HANDLE session;
-} *pkcs11h_data_t;
+/*
+ * pkcs11h_setLogLevel - Set current log level of the helper.
+ *
+ * Parameters:
+ * flags - current log level.
+ *
+ * The log level can be set to maximum, but setting it to lower
+ * level will improve performance.
+ */
+void
+pkcs11h_setLogLevel (
+ IN const unsigned flags
+);
-typedef struct pkcs11h_openssl_session_s {
- int nReferenceCount;
- bool fInitialized;
- X509 *x509;
- RSA_METHOD smart_rsa;
- int (*orig_finish)(RSA *rsa);
- pkcs11h_certificate_t certificate;
-} *pkcs11h_openssl_session_t;
+/*
+ * pkcs11h_getLogLevel - Get current log level.
+ */
+unsigned
+pkcs11h_getLogLevel ();
+/*
+ * pkcs11h_setLogHook - Set a log callback.
+ *
+ * Parameters:
+ * hook - Callback.
+ * pData - Data to send to callback.
+ */
CK_RV
-pkcs11h_initialize ();
+pkcs11h_setLogHook (
+ IN const pkcs11h_hook_log_t hook,
+ IN void * const pData
+);
+/*
+ * pkcs11h_setSlotEventHook - Set a slot event callback.
+ *
+ * Parameters:
+ * hook - Callback.
+ * pData - Data to send to callback.
+ *
+ * Calling this function initialize slot event notifications, these
+ * notifications can be started, but never terminate due to PKCS#11 limitation.
+ *
+ * In order to use slot events you must have threading enabled.
+ */
CK_RV
-pkcs11h_terminate ();
+pkcs11h_setSlotEventHook (
+ IN const pkcs11h_hook_slotevent_t hook,
+ IN void * const pData
+);
+/*
+ * pkcs11h_setTokenPromptHook - Set a token prompt callback.
+ *
+ * Parameters:
+ * hook - Callback.
+ * pData - Data to send to callback.
+ */
CK_RV
-pkcs11h_setCardPromptHook (
- IN const pkcs11h_hook_card_prompt_t hook,
+pkcs11h_setTokenPromptHook (
+ IN const pkcs11h_hook_token_prompt_t hook,
IN void * const pData
);
+/*
+ * pkcs11h_setPINPromptHook - Set a pin prompt callback.
+ *
+ * Parameters:
+ * hook - Callback.
+ * pData - Data to send to callback.
+ */
CK_RV
pkcs11h_setPINPromptHook (
IN const pkcs11h_hook_pin_prompt_t hook,
IN void * const pData
);
+/*
+ * pkcs11h_setProtectedAuthentication - Set global protected authentication mode.
+ *
+ * Parameters:
+ * fProtectedAuthentication - Allow protected authentication if enabled by token.
+ */
+CK_RV
+pkcs11h_setProtectedAuthentication (
+ IN const PKCS11H_BOOL fProtectedAuthentication
+);
+
+/*
+ * pkcs11h_setPINCachePeriod - Set global PIN cache timeout.
+ *
+ * Parameters:
+ * nPINCachePeriod - Cache period in seconds, or PKCS11H_PIN_CACHE_INFINITE.
+ */
CK_RV
pkcs11h_setPINCachePeriod (
IN const int nPINCachePeriod
);
+/*
+ * pkcs11h_setMaxLoginRetries - Set global login retries attempts.
+ *
+ * Parameters:
+ * nMaxLoginRetries - Login retries handled by the helper.
+ */
+CK_RV
+pkcs11h_setMaxLoginRetries (
+ IN const int nMaxLoginRetries
+);
+
+/*
+ * pkcs11h_addProvider - Add a PKCS#11 provider.
+ *
+ * Parameters:
+ * szReferenceName - Reference name for this provider.
+ * szProvider - Provider library location.
+ * fProtectedAuthentication - Allow this provider to use protected authentication.
+ * maskSignMode - Provider signmode override.
+ * nSlotEventMethod - Provider slot event method.
+ * nSlotEventPollInterval - Slot event poll interval (If in polling mode).
+ * fCertIsPrivate - Provider's certificate access should be done after login.
+ *
+ * This function must be called from the main thread.
+ *
+ * The global fProtectedAuthentication must be enabled in order to allow provider specific.
+ * The maskSignMode can be 0 in order to automatically detect key sign mode.
+ */
CK_RV
pkcs11h_addProvider (
+ IN const char * const szReferenceName,
IN const char * const szProvider,
- IN const char * const szSignMode
+ IN const PKCS11H_BOOL fProtectedAuthentication,
+ IN const unsigned maskSignMode,
+ IN const int nSlotEventMethod,
+ IN const int nSlotEventPollInterval,
+ IN const PKCS11H_BOOL fCertIsPrivate
);
+/*
+ * pkcs11h_delProvider - Delete a PKCS#11 provider.
+ *
+ * Parameters:
+ * szReferenceName - Reference name for this provider.
+ *
+ * This function must be called from the main thread.
+ */
+CK_RV
+pkcs11h_removeProvider (
+ IN const char * const szReferenceName
+);
+
+/*
+ * pkcs11h_forkFixup - Handle special case of Unix fork()
+ *
+ * This function should be called after fork is called. This is required
+ * due to a limitation of the PKCS#11 standard.
+ *
+ * This function must be called from the main thread.
+ *
+ * The helper library handles fork automatically if ENABLE_PKCS11H_THREADING
+ * is set on configuration file, by use of pthread_atfork.
+ */
CK_RV
pkcs11h_forkFixup ();
+/*
+ * pkcs11h_plugAndPlay - Handle slot rescan.
+ *
+ * This function must be called from the main thread.
+ *
+ * PKCS#11 providers do not allow plug&play, plug&play can be established by
+ * finalizing all providers and initializing them again.
+ *
+ * The cost of this process is invalidating all sessions, and require user
+ * login at the next access.
+ */
CK_RV
-pkcs11h_createCertificateSession (
- IN const char * const szSlotType,
- IN const char * const szSlot,
- IN const char * const szIdType,
- IN const char * const szId,
- IN const bool fProtectedAuthentication,
- IN const bool fCertPrivate,
+pkcs11h_plugAndPlay ();
+
+/*
+ * pkcs11h_freeTokenId - Free token_id object.
+ */
+CK_RV
+pkcs11h_freeTokenId (
+ IN pkcs11h_token_id_t certificate_id
+);
+
+/*
+ * pkcs11h_duplicateTokenId - Duplicate token_id object.
+ */
+CK_RV
+pkcs11h_duplicateTokenId (
+ OUT pkcs11h_token_id_t * const to,
+ IN const pkcs11h_token_id_t from
+);
+
+/*
+ * pkcs11h_sameTokenId - Returns TRUE if same token id
+ */
+PKCS11H_BOOL
+pkcs11h_sameTokenId (
+ IN const pkcs11h_token_id_t a,
+ IN const pkcs11h_token_id_t b
+);
+
+#if defined(ENABLE_PKCS11H_TOKEN)
+
+/*
+ * pkcs11h_token_ensureAccess - Ensure token is accessible.
+ *
+ * Parameters:
+ * token_id - Token id object.
+ * maskPrompt - Allow prompt.
+ */
+CK_RV
+pkcs11h_token_ensureAccess (
+ IN const pkcs11h_token_id_t token_id,
+ IN const unsigned maskPrompt
+);
+
+#endif /* ENABLE_PKCS11H_TOKEN */
+
+#if defined(ENABLE_PKCS11H_DATA)
+
+CK_RV
+pkcs11h_data_get (
+ IN const pkcs11h_token_id_t token_id,
+ IN const PKCS11H_BOOL fPublic,
+ IN const char * const szApplication,
+ IN const char * const szLabel,
+ OUT char * const blob,
+ IN OUT size_t * const p_blob_size
+);
+
+CK_RV
+pkcs11h_data_put (
+ IN const pkcs11h_token_id_t token_id,
+ IN const PKCS11H_BOOL fPublic,
+ IN const char * const szApplication,
+ IN const char * const szLabel,
+ OUT char * const blob,
+ IN const size_t blob_size
+);
+
+CK_RV
+pkcs11h_data_del (
+ IN const pkcs11h_token_id_t token_id,
+ IN const PKCS11H_BOOL fPublic,
+ IN const char * const szApplication,
+ IN const char * const szLabel
+);
+
+#endif /* ENABLE_PKCS11H_DATA */
+
+#if defined(ENABLE_PKCS11H_CERTIFICATE)
+/*======================================================================*
+ * CERTIFICATE INTERFACE
+ *======================================================================*/
+
+/*
+ * pkcs11h_freeCertificateId - Free certificate_id object.
+ */
+CK_RV
+pkcs11h_freeCertificateId (
+ IN pkcs11h_certificate_id_t certificate_id
+);
+
+/*
+ * pkcs11h_duplicateCertificateId - Duplicate certificate_id object.
+ */
+CK_RV
+pkcs11h_duplicateCertificateId (
+ OUT pkcs11h_certificate_id_t * const to,
+ IN const pkcs11h_certificate_id_t from
+);
+
+/*
+ * pkcs11h_freeCertificate - Free certificate object.
+ */
+CK_RV
+pkcs11h_freeCertificate (
+ IN pkcs11h_certificate_t certificate
+);
+
+/*
+ * pkcs11h_certificate_create - Create a certificate object out of certificate_id.
+ *
+ * Parameters:
+ * certificate_id - Certificate id object to be based on.
+ * nPINCachePeriod - Session specific cache period.
+ * p_certificate - Receives certificate object.
+ *
+ * The certificate id object may not specify the full certificate.
+ * The certificate object must be freed by caller.
+ */
+CK_RV
+pkcs11h_certificate_create (
+ IN const pkcs11h_certificate_id_t certificate_id,
IN const int nPINCachePeriod,
- OUT pkcs11h_certificate_t * const pkcs11h_certificate
+ OUT pkcs11h_certificate_t * const p_certificate
+);
+
+/*
+ * pkcs11h_certificate_getCertificateId - Get certifiate id object out of a certifiate
+ *
+ * Parameters:
+ * certificate - Certificate object.
+ * p_certificate_id - Certificate id object pointer.
+ *
+ * The certificate id must be freed by caller.
+ */
+CK_RV
+pkcs11h_certificate_getCertificateId (
+ IN const pkcs11h_certificate_t certificate,
+ OUT pkcs11h_certificate_id_t * const p_certificate_id
+);
+
+/*
+ * pkcs11h_certificate_getCertificateBlob - Get the certificate blob out of the certificate object.
+ *
+ * ParametersL
+ * certificate - Certificate object.
+ * certificate_blob - Buffer.
+ * certificate_blob_size - Buffer size.
+ *
+ * Buffer may be NULL in order to get size.
+ */
+CK_RV
+pkcs11h_certificate_getCertificateBlob (
+ IN const pkcs11h_certificate_t certificate,
+ OUT unsigned char * const certificate_blob,
+ IN OUT size_t * const p_certificate_blob_size
);
+/*
+ * pkcs11h_certificate_ensureCertificateAccess - Ensure certificate is accessible.
+ *
+ * Parameters:
+ * certificate - Certificate object.
+ * maskPrompt - Allow prompt.
+ */
CK_RV
-pkcs11h_freeCertificateSession (
- IN const pkcs11h_certificate_t pkcs11h_certificate
+pkcs11h_certificate_ensureCertificateAccess (
+ IN const pkcs11h_certificate_t certificate,
+ IN const unsigned maskPrompt
);
+/*
+ * pkcs11h_certificate_ensureKeyAccess - Ensure key is accessible.
+ *
+ * Parameters:
+ * certificate - Certificate object.
+ * maskPrompt - Allow prompt.
+ */
CK_RV
-pkcs11h_sign (
- IN const pkcs11h_certificate_t pkcs11h_certificate,
+pkcs11h_certificate_ensureKeyAccess (
+ IN const pkcs11h_certificate_t certificate,
+ IN const unsigned maskPrompt
+);
+
+/*
+ * pkcs11h_certificate_sign - Sign data.
+ *
+ * Parameters:
+ * certificate - Certificate object.
+ * mech_type - PKCS#11 mechanism.
+ * source - Buffer to sign.
+ * source_size - Buffer size.
+ * target - Target buffer, can be NULL to get size.
+ * target_size - Target buffer size.
+ */
+CK_RV
+pkcs11h_certificate_sign (
+ IN const pkcs11h_certificate_t certificate,
IN const CK_MECHANISM_TYPE mech_type,
IN const unsigned char * const source,
IN const size_t source_size,
OUT unsigned char * const target,
- IN OUT size_t * const target_size
+ IN OUT size_t * const p_target_size
);
+/*
+ * pkcs11h_certificate_signRecover - Sign data.
+ *
+ * Parameters:
+ * certificate - Certificate object.
+ * mech_type - PKCS#11 mechanism.
+ * source - Buffer to sign.
+ * source_size - Buffer size.
+ * target - Target buffer, can be NULL to get size.
+ * target_size - Target buffer size.
+ */
CK_RV
-pkcs11h_signRecover (
- IN const pkcs11h_certificate_t pkcs11h_certificate,
+pkcs11h_certificate_signRecover (
+ IN const pkcs11h_certificate_t certificate,
IN const CK_MECHANISM_TYPE mech_type,
IN const unsigned char * const source,
IN const size_t source_size,
OUT unsigned char * const target,
- IN OUT size_t * const target_size
+ IN OUT size_t * const p_target_size
);
+/*
+ * pkcs11h_certificate_signAny - Sign data mechanism determined by key attributes.
+ *
+ * Parameters:
+ * certificate - Certificate object.
+ * mech_type - PKCS#11 mechanism.
+ * source - Buffer to sign.
+ * source_size - Buffer size.
+ * target - Target buffer, can be NULL to get size.
+ * target_size - Target buffer size.
+ */
CK_RV
-pkcs11h_decrypt (
- IN const pkcs11h_certificate_t pkcs11h_certificate,
+pkcs11h_certificate_signAny (
+ IN const pkcs11h_certificate_t certificate,
IN const CK_MECHANISM_TYPE mech_type,
IN const unsigned char * const source,
IN const size_t source_size,
OUT unsigned char * const target,
- IN OUT size_t * const target_size
+ IN OUT size_t * const p_target_size
);
+/*
+ * pkcs11h_certificate_decrypt - Decrypt data.
+ *
+ * Parameters:
+ * certificate - Certificate object.
+ * mech_type - PKCS#11 mechanism.
+ * source - Buffer to sign.
+ * source_size - Buffer size.
+ * target - Target buffer, can be NULL to get size.
+ * target_size - Target buffer size.
+ */
CK_RV
-pkcs11h_getCertificate (
- IN const pkcs11h_certificate_t pkcs11h_certificate,
- OUT unsigned char * const certificate,
- IN OUT size_t * const certificate_size
+pkcs11h_certificate_decrypt (
+ IN const pkcs11h_certificate_t certificate,
+ IN const CK_MECHANISM_TYPE mech_type,
+ IN const unsigned char * const source,
+ IN const size_t source_size,
+ OUT unsigned char * const target,
+ IN OUT size_t * const p_target_size
);
-char *
-pkcs11h_getMessage (
- IN const int rv
+#endif /* ENABLE_PKCS11H_CERTIFICATE */
+
+#if defined(ENABLE_PKCS11H_LOCATE)
+/*======================================================================*
+ * LOCATE INTERFACE
+ *======================================================================*/
+
+#if defined(ENABLE_PKCS11H_TOKEN) || defined(ENABLE_PKCS11H_CERTIFICATE)
+
+/*
+ * pkcs11h_locate_token - Locate token based on atributes.
+ *
+ * Parameters:
+ * szSlotType - How to locate slot.
+ * szSlot - Slot name.
+ * p_token_id - Token object.
+ *
+ * Slot:
+ * id - Slot number.
+ * name - Slot name.
+ * label - Available token label.
+ *
+ * Caller must free token id.
+ */
+CK_RV
+pkcs11h_locate_token (
+ IN const char * const szSlotType,
+ IN const char * const szSlot,
+ OUT pkcs11h_token_id_t * const p_token_id
);
+#endif /* ENABLE_PKCS11H_TOKEN || ENABLE_PKCS11H_CERTIFICATE */
+
+#if defined(ENABLE_PKCS11H_CERTIFICATE)
+
+/*
+ * pkcs11h_locate_certificate - Locate certificate based on atributes.
+ *
+ * Parameters:
+ * szSlotType - How to locate slot.
+ * szSlot - Slot name.
+ * szIdType - How to locate object.
+ * szId - Object name.
+ * p_certificate_id - Certificate object.
+ *
+ * Slot:
+ * Same as pkcs11h_locate_token.
+ *
+ * Object:
+ * id - Certificate CKA_ID (hex string) (Fastest).
+ * label - Certificate CKA_LABEL (string).
+ * subject - Certificate subject (OpenSSL DN).
+ *
+ * Caller must free certificate id.
+ */
+CK_RV
+pkcs11h_locate_certificate (
+ IN const char * const szSlotType,
+ IN const char * const szSlot,
+ IN const char * const szIdType,
+ IN const char * const szId,
+ OUT pkcs11h_certificate_id_t * const p_certificate_id
+);
+
+#endif /* ENABLE_PKCS11H_CERTIFICATE */
+
+#endif /* ENABLE_PKCS11H_LOCATE */
+
+#if defined(ENABLE_PKCS11H_ENUM)
+/*======================================================================*
+ * ENUM INTERFACE
+ *======================================================================*/
+
+#if defined(ENABLE_PKCS11H_TOKEN)
+
+/*
+ * pkcs11h_freeCertificateIdList - Free certificate_id list.
+ */
+CK_RV
+pkcs11h_freeTokenIdList (
+ IN const pkcs11h_token_id_list_t token_id_list
+);
+
+/*
+ * pkcs11h_enum_getTokenIds - Enumerate available tokens
+ *
+ * Parameters:
+ * p_token_id_list - A list of token ids.
+ *
+ * Caller must free the list.
+ */
+CK_RV
+pkcs11h_enum_getTokenIds (
+ IN const int method,
+ OUT pkcs11h_token_id_list_t * const p_token_id_list
+);
+
+#endif /* ENABLE_PKCS11H_TOKEN */
+
+#if defined(ENABLE_PKCS11H_DATA)
+
+CK_RV
+pkcs11h_freeDataIdList (
+ IN const pkcs11h_data_id_list_t data_id_list
+);
+
+CK_RV
+pkcs11h_enumDataObjects (
+ IN const pkcs11h_token_id_t token_id,
+ IN const PKCS11H_BOOL fPublic,
+ OUT pkcs11h_data_id_list_t * const p_data_id_list
+);
+
+#endif /* ENABLE_PKCS11H_DATA */
+
+#if defined(ENABLE_PKCS11H_CERTIFICATE)
+
+/*
+ * pkcs11h_freeCertificateIdList - Free certificate_id list.
+ */
+CK_RV
+pkcs11h_freeCertificateIdList (
+ IN const pkcs11h_certificate_id_list_t cert_id_list
+);
+
+/*
+ * pkcs11h_enum_getTokenCertificateIds - Enumerate available certificates on specific token
+ *
+ * Parameters:
+ * token_id - Token id to enum.
+ * method - How to fetch certificates.
+ * p_cert_id_issuers_list - Receives issues list, can be NULL.
+ * p_cert_id_end_list - Receives end certificates list.
+ *
+ * This function will likely take long time.
+ *
+ * Method can be one of the following:
+ * PKCS11H_ENUM_METHOD_CACHE
+ * Return available certificates, even if token was once detected and
+ * was removed.
+ * PKCS11H_ENUM_METHOD_CACHE_EXIST
+ * Return available certificates for available tokens only, don't
+ * read the contents of the token if already read, even if this token
+ * removed and inserted.
+ * PKCS11H_ENUM_METHOD_RELOAD
+ * Clear all caches and then enum.
+ *
+ * Caller must free the lists.
+ */
+CK_RV
+pkcs11h_enum_getTokenCertificateIds (
+ IN const pkcs11h_token_id_t token_id,
+ IN const int method,
+ OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,
+ OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list
+);
+
+/*
+ * pkcs11h_enum_getCertificateIds - Enumerate available certificates.
+ *
+ * Parameters:
+ * method - How to fetch certificates.
+ * p_cert_id_issuers_list - Receives issues list, can be NULL.
+ * p_cert_id_end_list - Receives end certificates list.
+ *
+ * This function will likely take long time.
+ *
+ * Method can be one of the following:
+ * PKCS11H_ENUM_METHOD_CACHE
+ * Return available certificates, even if token was once detected and
+ * was removed.
+ * PKCS11H_ENUM_METHOD_CACHE_EXIST
+ * Return available certificates for available tokens only, don't
+ * read the contents of the token if already read, even if this token
+ * removed and inserted.
+ * PKCS11H_ENUM_METHOD_RELOAD
+ * Clear all caches and then enum.
+ *
+ * Caller must free lists.
+ */
+CK_RV
+pkcs11h_enum_getCertificateIds (
+ IN const int method,
+ OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,
+ OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list
+);
+
+#endif /* ENABLE_PKCS11H_CERTIFICATE */
+
+#endif /* ENABLE_PKCS11H_ENUM */
+
+#if defined(ENABLE_PKCS11H_OPENSSL)
+/*======================================================================*
+ * OPENSSL INTERFACE
+ *======================================================================*/
+
+/*
+ * pkcs11h_openssl_createSession - Create OpenSSL session based on a certificate object.
+ *
+ * Parameters:
+ * certificate - Certificate object.
+ *
+ * The certificate object will be freed by the OpenSSL interface on session end.
+ */
pkcs11h_openssl_session_t
-pkcs11h_openssl_createSession ();
+pkcs11h_openssl_createSession (
+ IN const pkcs11h_certificate_t certificate
+);
+/*
+ * pkcs11h_openssl_freeSession - Free OpenSSL session.
+ *
+ * Parameters:
+ * openssl_session - Session to free.
+ *
+ * The openssl_session object has a reference count just like other OpenSSL objects.
+ */
void
pkcs11h_openssl_freeSession (
- IN const pkcs11h_openssl_session_t pkcs11h_openssl_session
+ IN const pkcs11h_openssl_session_t openssl_session
);
+/*
+ * pkcs11h_openssl_getRSA - Returns an RSA object out of the openssl_session object.
+ *
+ * Parameters:
+ * openssl_session - Session.
+ */
RSA *
pkcs11h_openssl_getRSA (
- IN const pkcs11h_openssl_session_t pkcs11h_openssl_session
+ IN const pkcs11h_openssl_session_t openssl_session
);
+/*
+ * pkcs11h_openssl_getX509 - Returns an X509 object out of the openssl_session object.
+ *
+ * Parameters:
+ * openssl_session - Session.
+ */
X509 *
pkcs11h_openssl_getX509 (
- IN const pkcs11h_openssl_session_t pkcs11h_openssl_session
+ IN const pkcs11h_openssl_session_t openssl_session
);
+#endif /* ENABLE_PKCS11H_OPENSSL */
+
+#if defined(ENABLE_PKCS11H_STANDALONE)
+/*======================================================================*
+ * STANDALONE INTERFACE
+ *======================================================================*/
+
void
pkcs11h_standalone_dump_slots (
IN const pkcs11h_output_print_t my_output,
@@ -269,4 +939,10 @@ pkcs11h_standalone_dump_objects (
IN const char * const pin
);
+#endif /* ENABLE_PKCS11H_STANDALONE */
+
+#ifdef __cplusplus
+}
#endif
+
+#endif /* __PKCS11H_HELPER_H */
diff --git a/pkcs11.c b/pkcs11.c
index a8875cf..3b136c5 100644
--- a/pkcs11.c
+++ b/pkcs11.c
@@ -44,6 +44,74 @@
#include "pkcs11.h"
static
+unsigned
+_pkcs11_msg_pkcs112openvpn (
+ IN const unsigned flags
+) {
+ unsigned openvpn_flags;
+
+ switch (flags) {
+ case PKCS11H_LOG_DEBUG2:
+ openvpn_flags = D_PKCS11_DEBUG;
+ break;
+ case PKCS11H_LOG_DEBUG1:
+ openvpn_flags = D_SHOW_PKCS11;
+ break;
+ case PKCS11H_LOG_INFO:
+ openvpn_flags = M_INFO;
+ break;
+ case PKCS11H_LOG_WARN:
+ openvpn_flags = M_WARN;
+ break;
+ case PKCS11H_LOG_ERROR:
+ openvpn_flags = M_FATAL;
+ break;
+ default:
+ openvpn_flags = M_FATAL;
+ break;
+ }
+
+#if defined(ENABLE_PKCS11_FORCE_DEBUG)
+ openvpn_flags=M_INFO;
+#endif
+
+ return openvpn_flags;
+}
+
+static
+unsigned
+_pkcs11_msg_openvpn2pkcs11 (
+ IN const unsigned flags
+) {
+ unsigned pkcs11_flags;
+
+ if ((flags & D_PKCS11_DEBUG) != 0) {
+ pkcs11_flags = PKCS11H_LOG_DEBUG2;
+ }
+ else if ((flags & D_SHOW_PKCS11) != 0) {
+ pkcs11_flags = PKCS11H_LOG_DEBUG1;
+ }
+ else if ((flags & M_INFO) != 0) {
+ pkcs11_flags = PKCS11H_LOG_INFO;
+ }
+ else if ((flags & M_WARN) != 0) {
+ pkcs11_flags = PKCS11H_LOG_WARN;
+ }
+ else if ((flags & M_FATAL) != 0) {
+ pkcs11_flags = PKCS11H_LOG_ERROR;
+ }
+ else {
+ pkcs11_flags = PKCS11H_LOG_ERROR;
+ }
+
+#if defined(ENABLE_PKCS11_FORCE_DEBUG)
+ pkcs11_flags = PKCS11H_LOG_DEBUG2;
+#endif
+
+ return pkcs11_flags;
+}
+
+static
void
_pkcs11_openvpn_print (
IN const void *pData,
@@ -62,20 +130,46 @@ _pkcs11_openvpn_print (
}
static
+void
+_pkcs11_openvpn_log (
+ IN const void *pData,
+ IN unsigned flags,
+ IN const char * const szFormat,
+ IN va_list args
+) {
+ char Buffer[10*1024];
+
+ vsnprintf (Buffer, sizeof (Buffer), szFormat, args);
+ Buffer[sizeof (Buffer)-1] = 0;
+
+ msg (_pkcs11_msg_pkcs112openvpn (flags), "%s", Buffer);
+}
+
+static
bool
-_pkcs11_openvpn_card_prompt (
+_pkcs11_openvpn_token_prompt (
IN const void *pData,
- IN const char * const szLabel
+ IN const pkcs11h_token_id_t token
) {
static struct user_pass token_resp;
- ASSERT (szLabel!=NULL);
+ ASSERT (token!=NULL);
CLEAR (token_resp);
token_resp.defined = false;
token_resp.nocache = true;
- openvpn_snprintf (token_resp.username, sizeof (token_resp.username), "Please insert %s token", szLabel);
- get_user_pass (&token_resp, NULL, "token-insertion-request", GET_USER_PASS_MANAGEMENT|GET_USER_PASS_NEED_OK);
+ openvpn_snprintf (
+ token_resp.username,
+ sizeof (token_resp.username),
+ "Please insert %s token",
+ token->label
+ );
+ get_user_pass (
+ &token_resp,
+ NULL,
+ "token-insertion-request",
+ GET_USER_PASS_MANAGEMENT|GET_USER_PASS_NEED_OK
+ );
return strcmp (token_resp.password, "ok") == 0;
}
@@ -84,16 +178,16 @@ static
bool
_pkcs11_openvpn_pin_prompt (
IN const void *pData,
- IN const char * const szLabel,
+ IN const pkcs11h_token_id_t token,
OUT char * const szPIN,
IN const size_t nMaxPIN
) {
static struct user_pass token_pass;
char szPrompt[1024];
- ASSERT (szLabel!=NULL);
+ ASSERT (token!=NULL);
- openvpn_snprintf (szPrompt, sizeof (szPrompt), "%s token", szLabel);
+ openvpn_snprintf (szPrompt, sizeof (szPrompt), "%s token", token->label);
token_pass.defined = false;
token_pass.nocache = true;
@@ -111,12 +205,13 @@ _pkcs11_openvpn_pin_prompt (
bool
pkcs11_initialize (
- const int nPINCachePeriod
+ IN const bool fProtectedAuthentication,
+ IN const int nPINCachePeriod
) {
CK_RV rv = CKR_OK;
- PKCS11LOG (
- PKCS11_LOG_DEBUG2,
+ dmsg (
+ D_PKCS11_DEBUG,
"PKCS#11: pkcs11_initialize - entered"
);
@@ -124,32 +219,50 @@ pkcs11_initialize (
rv == CKR_OK &&
(rv = pkcs11h_initialize ()) != CKR_OK
) {
- PKCS11LOG (PKCS11_LOG_ERROR, "PKCS#11: Cannot initialize %ld-'%s'", rv, pkcs11h_getMessage (rv));
+ msg (M_FATAL, "PKCS#11: Cannot initialize %ld-'%s'", rv, pkcs11h_getMessage (rv));
}
if (
rv == CKR_OK &&
- (rv = pkcs11h_setCardPromptHook (_pkcs11_openvpn_card_prompt, NULL)) != CKR_OK
+ (rv = pkcs11h_setLogHook (_pkcs11_openvpn_log, NULL)) != CKR_OK
) {
- PKCS11LOG (PKCS11_LOG_ERROR, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv));
+ msg (M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv));
+ }
+
+ if (rv == CKR_OK) {
+ pkcs11h_setLogLevel (_pkcs11_msg_openvpn2pkcs11 (get_debug_level ()));
+ }
+
+ if (
+ rv == CKR_OK &&
+ (rv = pkcs11h_setTokenPromptHook (_pkcs11_openvpn_token_prompt, NULL)) != CKR_OK
+ ) {
+ msg (M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv));
}
if (
rv == CKR_OK &&
(rv = pkcs11h_setPINPromptHook (_pkcs11_openvpn_pin_prompt, NULL)) != CKR_OK
) {
- PKCS11LOG (PKCS11_LOG_ERROR, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv));
+ msg (M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv));
+ }
+
+ if (
+ rv == CKR_OK &&
+ (rv = pkcs11h_setProtectedAuthentication (fProtectedAuthentication)) != CKR_OK
+ ) {
+ msg (M_FATAL, "PKCS#11: Cannot set protected authentication mode %ld-'%s'", rv, pkcs11h_getMessage (rv));
}
if (
rv == CKR_OK &&
(rv = pkcs11h_setPINCachePeriod (nPINCachePeriod)) != CKR_OK
) {
- PKCS11LOG (PKCS11_LOG_ERROR, "PKCS#11: Cannot set PIN cache period %ld-'%s'", rv, pkcs11h_getMessage (rv));
+ msg (M_FATAL, "PKCS#11: Cannot set PIN cache period %ld-'%s'", rv, pkcs11h_getMessage (rv));
}
- PKCS11LOG (
- PKCS11_LOG_DEBUG2,
+ dmsg (
+ D_PKCS11_DEBUG,
"PKCS#11: pkcs11_initialize - return %ld-'%s'",
rv,
pkcs11h_getMessage (rv)
@@ -160,15 +273,15 @@ pkcs11_initialize (
void
pkcs11_terminate () {
- PKCS11LOG (
- PKCS11_LOG_DEBUG2,
+ dmsg (
+ D_PKCS11_DEBUG,
"PKCS#11: pkcs11_terminate - entered"
);
pkcs11h_terminate ();
- PKCS11LOG (
- PKCS11_LOG_DEBUG2,
+ dmsg (
+ D_PKCS11_DEBUG,
"PKCS#11: pkcs11_terminate - return"
);
}
@@ -181,32 +294,69 @@ pkcs11_forkFixup () {
bool
pkcs11_addProvider (
IN const char * const provider,
- IN const char * const sign_mode
+ IN const bool fProtectedAuthentication,
+ IN const char * const sign_mode,
+ IN const bool fCertIsPrivate
) {
+ unsigned maskSignMode = 0;
+
CK_RV rv = CKR_OK;
- PKCS11LOG (
- PKCS11_LOG_DEBUG2,
+ ASSERT (provider!=NULL);
+ /*ASSERT (sign_mode!=NULL); NULL is default */
+
+ dmsg (
+ D_PKCS11_DEBUG,
"PKCS#11: pkcs11_addProvider - entered - provider='%s', sign_mode='%s'",
provider,
sign_mode == NULL ? "default" : sign_mode
);
- PKCS11LOG (
- PKCS11_LOG_INFO,
+ msg (
+ M_INFO,
"PKCS#11: Adding PKCS#11 provider '%s'",
provider
);
+ if (rv == CKR_OK) {
+ if (sign_mode == NULL || !strcmp (sign_mode, "auto")) {
+ maskSignMode = 0;
+ }
+ else if (!strcmp (sign_mode, "sign")) {
+ maskSignMode = PKCS11H_SIGNMODE_MASK_SIGN;
+ }
+ else if (!strcmp (sign_mode, "recover")) {
+ maskSignMode = PKCS11H_SIGNMODE_MASK_RECOVER;
+ }
+ else if (!strcmp (sign_mode, "any")) {
+ maskSignMode = (
+ PKCS11H_SIGNMODE_MASK_SIGN |
+ PKCS11H_SIGNMODE_MASK_RECOVER
+ );
+ }
+ else {
+ msg (M_FATAL, "PKCS#11: Invalid sign mode '%s'", sign_mode);
+ rv = CKR_ARGUMENTS_BAD;
+ }
+ }
+
if (
rv == CKR_OK &&
- (rv = pkcs11h_addProvider (provider, sign_mode)) != CKR_OK
+ (rv = pkcs11h_addProvider (
+ provider,
+ provider,
+ fProtectedAuthentication,
+ maskSignMode,
+ PKCS11H_SLOTEVENT_METHOD_AUTO,
+ 0,
+ fCertIsPrivate
+ )) != CKR_OK
) {
- PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot initialize provider '%s' %ld-'%s'", provider, rv, pkcs11h_getMessage (rv));
+ msg (M_WARN, "PKCS#11: Cannot initialize provider '%s' %ld-'%s'", provider, rv, pkcs11h_getMessage (rv));
}
- PKCS11LOG (
- PKCS11_LOG_DEBUG2,
+ dmsg (
+ D_PKCS11_DEBUG,
"PKCS#11: pkcs11_addProvider - return rv=%ld-'%s'",
rv,
pkcs11h_getMessage (rv)
@@ -221,73 +371,94 @@ SSL_CTX_use_pkcs11 (
IN const char * const pkcs11_slot_type,
IN const char * const pkcs11_slot,
IN const char * const pkcs11_id_type,
- IN const char * const pkcs11_id,
- IN const bool pkcs11_protected_authentication,
- IN const bool pkcs11_cert_private
+ IN const char * const pkcs11_id
) {
X509 *x509 = NULL;
RSA *rsa = NULL;
- pkcs11h_openssl_session_t pkcs11h_openssl_session = NULL;
+ pkcs11h_certificate_id_t certificate_id = NULL;
+ pkcs11h_certificate_t certificate = NULL;
+ pkcs11h_openssl_session_t openssl_session = NULL;
CK_RV rv = CKR_OK;
bool fOK = true;
- PKCS11LOG (
- PKCS11_LOG_DEBUG2,
- "PKCS#11: SSL_CTX_use_pkcs11 - entered - ssl_ctx=%p, pkcs11_slot_type='%s', pkcs11_slot='%s', pkcs11_id_type='%s', pkcs11_id='%s', pkcs11_protected_authentication=%d",
+ ASSERT (ssl_ctx!=NULL);
+ ASSERT (pkcs11_slot_type!=NULL);
+ ASSERT (pkcs11_slot!=NULL);
+ ASSERT (pkcs11_id_type!=NULL);
+ ASSERT (pkcs11_id!=NULL);
+
+ dmsg (
+ D_PKCS11_DEBUG,
+ "PKCS#11: SSL_CTX_use_pkcs11 - entered - ssl_ctx=%p, pkcs11_slot_type='%s', pkcs11_slot='%s', pkcs11_id_type='%s', pkcs11_id='%s'",
(void *)ssl_ctx,
pkcs11_slot_type,
pkcs11_slot,
pkcs11_id_type,
- pkcs11_id,
- pkcs11_protected_authentication ? 1 : 0
+ pkcs11_id
);
- PKCS11ASSERT (ssl_ctx!=NULL);
- PKCS11ASSERT (pkcs11_slot_type!=NULL);
- PKCS11ASSERT (pkcs11_slot!=NULL);
- PKCS11ASSERT (pkcs11_id_type!=NULL);
- PKCS11ASSERT (pkcs11_id!=NULL);
+ ASSERT (ssl_ctx!=NULL);
+ ASSERT (pkcs11_slot_type!=NULL);
+ ASSERT (pkcs11_slot!=NULL);
+ ASSERT (pkcs11_id_type!=NULL);
+ ASSERT (pkcs11_id!=NULL);
if (
fOK &&
- (pkcs11h_openssl_session = pkcs11h_openssl_createSession ()) == NULL
+ (rv = pkcs11h_locate_certificate (
+ pkcs11_slot_type,
+ pkcs11_slot,
+ pkcs11_id_type,
+ pkcs11_id,
+ &certificate_id
+ )) != CKR_OK
) {
fOK = false;
- PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot initialize openssh session");
+ msg (M_WARN, "PKCS#11: Cannot set parameters %ld-'%s'", rv, pkcs11h_getMessage (rv));
}
if (
fOK &&
- (rv = pkcs11h_createCertificateSession (
- pkcs11_slot_type,
- pkcs11_slot,
- pkcs11_id_type,
- pkcs11_id,
- pkcs11_protected_authentication,
- pkcs11_cert_private,
+ (rv = pkcs11h_certificate_create (
+ certificate_id,
PKCS11H_PIN_CACHE_INFINITE,
- &pkcs11h_openssl_session->certificate
+ &certificate
)) != CKR_OK
) {
fOK = false;
- PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot set parameters %ld-'%s'", rv, pkcs11h_getMessage (rv));
+ msg (M_WARN, "PKCS#11: Cannot get certificate %ld-'%s'", rv, pkcs11h_getMessage (rv));
}
if (
fOK &&
- (rsa = pkcs11h_openssl_getRSA (pkcs11h_openssl_session)) == NULL
+ (openssl_session = pkcs11h_openssl_createSession (certificate)) == NULL
) {
fOK = false;
- PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Unable get rsa object");
+ msg (M_WARN, "PKCS#11: Cannot initialize openssl session");
+ }
+
+ if (fOK) {
+ /*
+ * Will be released by openssl_session
+ */
+ certificate = NULL;
}
if (
fOK &&
- (x509 = pkcs11h_openssl_getX509 (pkcs11h_openssl_session)) == NULL
+ (rsa = pkcs11h_openssl_getRSA (openssl_session)) == NULL
) {
fOK = false;
- PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Unable get certificate object");
+ msg (M_WARN, "PKCS#11: Unable get rsa object");
+ }
+
+ if (
+ fOK &&
+ (x509 = pkcs11h_openssl_getX509 (openssl_session)) == NULL
+ ) {
+ fOK = false;
+ msg (M_WARN, "PKCS#11: Unable get certificate object");
}
if (
@@ -295,7 +466,7 @@ SSL_CTX_use_pkcs11 (
!SSL_CTX_use_RSAPrivateKey (ssl_ctx, rsa)
) {
fOK = false;
- PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot set private key for openssl");
+ msg (M_WARN, "PKCS#11: Cannot set private key for openssl");
}
if (
@@ -303,7 +474,7 @@ SSL_CTX_use_pkcs11 (
!SSL_CTX_use_certificate (ssl_ctx, x509)
) {
fOK = false;
- PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot set certificate for openssl");
+ msg (M_WARN, "PKCS#11: Cannot set certificate for openssl");
}
/*
@@ -320,14 +491,24 @@ SSL_CTX_use_pkcs11 (
RSA_free (rsa);
rsa = NULL;
}
+
+ if (certificate != NULL) {
+ pkcs11h_freeCertificate (certificate);
+ certificate = NULL;
+ }
+
+ if (certificate_id != NULL) {
+ pkcs11h_freeCertificateId (certificate_id);
+ certificate_id = NULL;
+ }
- if (pkcs11h_openssl_session != NULL) {
- pkcs11h_openssl_freeSession (pkcs11h_openssl_session);
- pkcs11h_openssl_session = NULL;
+ if (openssl_session != NULL) {
+ pkcs11h_openssl_freeSession (openssl_session);
+ openssl_session = NULL;
}
- PKCS11LOG (
- PKCS11_LOG_DEBUG2,
+ dmsg (
+ D_PKCS11_DEBUG,
"PKCS#11: SSL_CTX_use_pkcs11 - return fOK=%d, rv=%ld",
fOK ? 1 : 0,
rv
diff --git a/pkcs11.h b/pkcs11.h
index 652647f..0e69d11 100644
--- a/pkcs11.h
+++ b/pkcs11.h
@@ -31,6 +31,7 @@
bool
pkcs11_initialize (
+ const bool fProtectedAuthentication,
const int nPINCachePeriod
);
@@ -43,7 +44,9 @@ pkcs11_forkFixup ();
bool
pkcs11_addProvider (
const char * const provider,
- const char * const sign_mode
+ const bool fProtectedAuthentication,
+ const char * const sign_mode,
+ const bool fCertIsPrivate
);
int
@@ -52,9 +55,7 @@ SSL_CTX_use_pkcs11 (
const char * const pkcs11_slot_type,
const char * const pkcs11_slot,
const char * const pkcs11_id_type,
- const char * const pkcs11_id,
- const bool pkcs11_protected_authentication,
- const bool pkcs11_cert_private
+ const char * const pkcs11_id
);
void
@@ -71,4 +72,4 @@ show_pkcs11_objects (
#endif /* ENABLE_PKCS11 */
-#endif /* OPENVPN_PKCS11_H */
+#endif /* OPENVPN_PKCS11H_H */
diff --git a/ssl.c b/ssl.c
index 42fd904..2aa6e4a 100644
--- a/ssl.c
+++ b/ssl.c
@@ -1145,7 +1145,7 @@ init_ssl (const struct options *options)
if (options->pkcs11_providers[0])
{
/* Load Certificate and Private Key */
- if (!SSL_CTX_use_pkcs11 (ctx, options->pkcs11_slot_type, options->pkcs11_slot, options->pkcs11_id_type, options->pkcs11_id, options->pkcs11_protected_authentication, options->pkcs11_cert_private))
+ if (!SSL_CTX_use_pkcs11 (ctx, options->pkcs11_slot_type, options->pkcs11_slot, options->pkcs11_id_type, options->pkcs11_id))
msg (M_SSLERR, "Cannot load certificate \"%s:%s\" from slot \"%s:%s\" using PKCS#11 interface",
options->pkcs11_id_type, options->pkcs11_id, options->pkcs11_slot_type, options->pkcs11_slot);
}