summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>2005-10-20 05:58:08 +0000
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>2005-10-20 05:58:08 +0000
commit984cf0036c882c4fada83448aaa37bbd5ebb8130 (patch)
treed8a8d9f93c48326f2bb2295d95e19a4c830b3d62
parentf78687162b7593ba0ab4edba19cce370ad917e0a (diff)
downloadopenvpn-984cf0036c882c4fada83448aaa37bbd5ebb8130.tar.gz
openvpn-984cf0036c882c4fada83448aaa37bbd5ebb8130.tar.xz
openvpn-984cf0036c882c4fada83448aaa37bbd5ebb8130.zip
Merged with Alon's r688.
git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@689 e7ae566f-a301-0410-adde-c780ea21d3b5
-rw-r--r--Makefile.am2
-rw-r--r--error.c15
-rw-r--r--error.h1
-rw-r--r--init.c10
-rwxr-xr-xmakefile.w324
-rw-r--r--makefile.w32-vc4
-rw-r--r--manage.c50
-rw-r--r--manage.h3
-rw-r--r--misc.c41
-rw-r--r--misc.h10
-rw-r--r--options.c4
-rw-r--r--pkcs11-helper-config.h84
-rw-r--r--pkcs11-helper.c3239
-rw-r--r--pkcs11-helper.h252
-rw-r--r--pkcs11.c2829
-rw-r--r--pkcs11.h12
-rw-r--r--proxy.c1
-rw-r--r--ssl.c4
18 files changed, 3795 insertions, 2770 deletions
diff --git a/Makefile.am b/Makefile.am
index 6519f2a..424b167 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -67,7 +67,7 @@ openvpn_SOURCES = \
multi.c multi.h \
ntlm.c ntlm.h \
occ.c occ.h occ-inline.h \
- pkcs11.c pkcs11.h cryptoki.h \
+ pkcs11.c pkcs11.h pkcs11-helper.c pkcs11-helper.h pkcs11-helper-config.h cryptoki.h \
openvpn.c openvpn.h \
openvpn-plugin.h \
options.c options.h \
diff --git a/error.c b/error.c
index 01a6207..f01dd8f 100644
--- a/error.c
+++ b/error.c
@@ -300,26 +300,29 @@ void x_msg (const unsigned int flags, const char *format, ...)
if ((flags & M_NOPREFIX) || suppress_timestamps)
{
- fprintf (fp, "%s%s%s\n",
+ fprintf (fp, "%s%s%s%s",
prefix,
prefix_sep,
- m1);
+ m1,
+ (flags&M_NOLF) ? "" : "\n");
}
else
{
#ifdef USE_PTHREAD
- fprintf (fp, "%s [%d] %s%s%s\n",
+ fprintf (fp, "%s [%d] %s%s%s%s",
time_string (0, 0, show_usec, &gc),
(int) openvpn_thread_self (),
prefix,
prefix_sep,
- m1);
+ m1,
+ (flags&M_NOLF) ? "" : "\n");
#else
- fprintf (fp, "%s %s%s%s\n",
+ fprintf (fp, "%s %s%s%s%s",
time_string (0, 0, show_usec, &gc),
prefix,
prefix_sep,
- m1);
+ m1,
+ (flags&M_NOLF) ? "" : "\n");
#endif
}
fflush(fp);
diff --git a/error.h b/error.h
index 8bcc909..5d2501b 100644
--- a/error.h
+++ b/error.h
@@ -97,6 +97,7 @@ extern int x_msg_line_num;
#define M_USAGE_SMALL (1<<13) /* fatal options error, call usage_small */
#define M_MSG_VIRT_OUT (1<<14) /* output message through msg_status_output callback */
#define M_OPTERR (1<<15) /* print "Options error:" prefix */
+#define M_NOLF (1<<16) /* don't print new line */
/* flag combinations which are frequently used */
#define M_ERR (M_FATAL | M_ERRNO)
diff --git a/init.c b/init.c
index c2fb6cf..97d0660 100644
--- a/init.c
+++ b/init.c
@@ -116,12 +116,12 @@ context_init_1 (struct context *c)
#if defined(ENABLE_PKCS11)
{
int i;
- init_pkcs11 (c->options.pkcs11_pin_cache_period);
+ pkcs11_initialize (c->options.pkcs11_pin_cache_period);
for (i=0;i<MAX_PARMS && c->options.pkcs11_providers[i] != NULL;i++)
- add_pkcs11 (c->options.pkcs11_providers[i], c->options.pkcs11_sign_mode[i]);
+ pkcs11_addProvider (c->options.pkcs11_providers[i], c->options.pkcs11_sign_mode[i]);
}
#endif
-
+
#if P2MP
/* Auth user/pass input */
if (c->options.auth_user_pass_file)
@@ -236,7 +236,7 @@ uninit_static (void)
#endif
#ifdef ENABLE_PKCS11
- free_pkcs11 ();
+ pkcs11_terminate ();
#endif
#if defined(MEASURE_TLS_HANDSHAKE_STATS) && defined(USE_CRYPTO) && defined(USE_SSL)
@@ -376,7 +376,7 @@ possibly_become_daemon (const struct options *options, const bool first_time)
set_std_files_to_null (true);
#if defined(ENABLE_PKCS11)
- fork_fix_pkcs11 ();
+ pkcs11_forkFixup ();
#endif
ret = true;
diff --git a/makefile.w32 b/makefile.w32
index 0a1517c..48cc3f1 100755
--- a/makefile.w32
+++ b/makefile.w32
@@ -96,7 +96,7 @@ HEADERS = \
ntlm.h \
occ-inline.h \
occ.h \
- pkcs11.h \
+ pkcs11.h pkcs11-helper.h cryptoki.h \
openvpn.h \
openvpn-plugin.h \
options.h \
@@ -151,7 +151,7 @@ OBJS = base64.o \
multi.o \
ntlm.o \
occ.o \
- pkcs11.o \
+ pkcs11.o pkcs11-helper.o \
openvpn.o \
options.o \
otime.o \
diff --git a/makefile.w32-vc b/makefile.w32-vc
index bcd0c62..49c1031 100644
--- a/makefile.w32-vc
+++ b/makefile.w32-vc
@@ -81,7 +81,7 @@ HEADERS = \
ntlm.h \
occ-inline.h \
occ.h \
- pkcs11.h \
+ pkcs11.h pkcs11-helper.h cryptoki.h \
openvpn.h \
openvpn-plugin.h \
options.h \
@@ -136,7 +136,7 @@ OBJS = base64.obj \
multi.obj \
ntlm.obj \
occ.obj \
- pkcs11.obj \
+ pkcs11.obj pkcs11-helper.obj \
openvpn.obj \
options.obj \
otime.obj \
diff --git a/manage.c b/manage.c
index 7be67fd..d17d9ce 100644
--- a/manage.c
+++ b/manage.c
@@ -39,6 +39,7 @@
#include "event.h"
#include "otime.h"
#include "integer.h"
+#include "misc.h"
#include "manage.h"
#include "memdbg.h"
@@ -74,6 +75,7 @@ man_help ()
msg (M_CLIENT, " + show last N lines or 'all' for entire history.");
msg (M_CLIENT, "mute [n] : Set log mute level to n, or show level if n is absent.");
msg (M_CLIENT, "net : (Windows only) Show network info and routing table.");
+ msg (M_CLIENT, "ok type : Enter confirmation for NEED-OK request.");
msg (M_CLIENT, "password type p : Enter password p for a queried OpenVPN password.");
msg (M_CLIENT, "signal s : Send signal s to daemon,");
msg (M_CLIENT, " s = SIGHUP|SIGTERM|SIGUSR1|SIGUSR2.");
@@ -467,6 +469,10 @@ man_up_finalize (struct management *man)
if (strlen (man->connection.up_query.password))
man->connection.up_query.defined = true;
break;
+ case UP_QUERY_NEED_OK:
+ if (strlen (man->connection.up_query.password))
+ man->connection.up_query.defined = true;
+ break;
default:
ASSERT (0);
}
@@ -521,6 +527,13 @@ man_query_password (struct management *man, const char *type, const char *string
}
static void
+man_query_need_ok (struct management *man, const char *type)
+{
+ const bool needed = ((man->connection.up_query_mode == UP_QUERY_NEED_OK) && man->connection.up_query_type);
+ man_query_user_pass (man, type, "ok", needed, "ok-confirmation", man->connection.up_query.password, USER_PASS_LEN);
+}
+
+static void
man_net (struct management *man)
{
if (man->persist.callback.show_net)
@@ -708,6 +721,11 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch
if (man_need (man, p, 2, 0))
man_query_password (man, p[1], p[2]);
}
+ else if (streq (p[0], "ok"))
+ {
+ if (man_need (man, p, 1, 0))
+ man_query_need_ok (man, p[1]);
+ }
else if (streq (p[0], "net"))
{
man_net (man);
@@ -1130,7 +1148,7 @@ man_settings_init (struct man_settings *ms,
* Get username/password
*/
if (pass_file)
- get_user_pass (&ms->up, pass_file, true, "Management", 0);
+ get_user_pass (&ms->up, pass_file, "Management", GET_USER_PASS_PASSWORD_ONLY);
/*
* Should OpenVPN query the management layer for
@@ -1728,7 +1746,7 @@ bool
management_query_user_pass (struct management *man,
struct user_pass *up,
const char *type,
- const bool password_only)
+ const unsigned int flags)
{
struct gc_arena gc = gc_new ();
bool ret = false;
@@ -1738,6 +1756,9 @@ management_query_user_pass (struct management *man,
volatile int signal_received = 0;
const bool standalone_disabled_save = man->persist.standalone_disabled;
struct buffer alert_msg = alloc_buf_gc (128, &gc);
+ const char *alert_type = NULL;
+ const char *prefix = NULL;
+ unsigned int up_query_mode = 0;
ret = true;
man->persist.standalone_disabled = false; /* This is so M_CLIENT messages will be correctly passed through msg() */
@@ -1745,9 +1766,28 @@ management_query_user_pass (struct management *man,
CLEAR (man->connection.up_query);
- buf_printf (&alert_msg, ">PASSWORD:Need '%s' %s",
+ if (flags & GET_USER_PASS_NEED_OK)
+ {
+ up_query_mode = UP_QUERY_NEED_OK;
+ prefix= "NEED-OK";
+ alert_type = "confirmation";
+ }
+ else if (flags & GET_USER_PASS_PASSWORD_ONLY)
+ {
+ up_query_mode = UP_QUERY_PASS;
+ prefix = "PASSWORD";
+ alert_type = "password";
+ }
+ else
+ {
+ up_query_mode = UP_QUERY_USER_PASS;
+ prefix = "PASSWORD";
+ alert_type = "username/password";
+ }
+ buf_printf (&alert_msg, ">%s:Need '%s' %s",
+ prefix,
type,
- password_only ? "password" : "username/password");
+ alert_type);
man_wait_for_client_connection (man, &signal_received, 0, MWCC_PASSWORD_WAIT);
if (signal_received)
@@ -1759,7 +1799,7 @@ management_query_user_pass (struct management *man,
msg (M_CLIENT, "%s", man->persist.special_state_msg);
/* tell command line parser which info we need */
- man->connection.up_query_mode = password_only ? UP_QUERY_PASS : UP_QUERY_USER_PASS;
+ man->connection.up_query_mode = up_query_mode;
man->connection.up_query_type = type;
/* run command processing event loop until we get our username/password */
diff --git a/manage.h b/manage.h
index 5d059fa..310f460 100644
--- a/manage.h
+++ b/manage.h
@@ -203,6 +203,7 @@ struct man_settings {
#define UP_QUERY_DISABLED 0
#define UP_QUERY_USER_PASS 1
#define UP_QUERY_PASS 2
+#define UP_QUERY_NEED_OK 3
/* states */
#define MS_INITIAL 0 /* all sockets are closed */
@@ -282,7 +283,7 @@ void management_set_callback (struct management *man,
void management_clear_callback (struct management *man);
-bool management_query_user_pass (struct management *man, struct user_pass *up, const char *type, const bool password_only);
+bool management_query_user_pass (struct management *man, struct user_pass *up, const char *type, const unsigned int flags);
bool management_would_hold (struct management *man);
bool management_hold (struct management *man);
diff --git a/misc.c b/misc.c
index f4e7079..4a79ee5 100644
--- a/misc.c
+++ b/misc.c
@@ -1155,7 +1155,6 @@ get_console_input (const char *prompt, const bool echo, char *input, const int c
void
get_user_pass (struct user_pass *up,
const char *auth_file,
- const bool password_only,
const char *prefix,
const unsigned int flags)
{
@@ -1173,32 +1172,44 @@ get_user_pass (struct user_pass *up,
&& ((auth_file && streq (auth_file, "management")) || (from_stdin && (flags & GET_USER_PASS_MANAGEMENT)))
&& management_query_user_pass_enabled (management))
{
- if (!management_query_user_pass (management, up, prefix, password_only))
- msg (M_FATAL, "ERROR: could not read %s username/password from management interface", prefix);
+ if (!management_query_user_pass (management, up, prefix, flags))
+ msg (M_FATAL, "ERROR: could not read %s username/password/ok from management interface", prefix);
}
else
#endif
/*
* Get username/password from standard input?
*/
- if (from_stdin)
+ if (from_stdin || (flags & GET_USER_PASS_NEED_OK))
{
struct buffer user_prompt = alloc_buf_gc (128, &gc);
struct buffer pass_prompt = alloc_buf_gc (128, &gc);
- buf_printf (&user_prompt, "Enter %s Username:", prefix);
- buf_printf (&pass_prompt, "Enter %s Password:", prefix);
-
- if (!password_only)
+ if (flags & GET_USER_PASS_NEED_OK)
{
- if (!get_console_input (BSTR (&user_prompt), true, up->username, USER_PASS_LEN))
- msg (M_FATAL, "ERROR: could not read %s username from stdin", prefix);
- if (strlen (up->username) == 0)
- msg (M_FATAL, "ERROR: %s username is empty", prefix);
+ buf_printf (&pass_prompt, "NEED-OK:%s:", prefix);
+ }
+ else
+ {
+ buf_printf (&user_prompt, "Enter %s Username:", prefix);
+ buf_printf (&pass_prompt, "Enter %s Password:", prefix);
+
+ if (!(flags & GET_USER_PASS_PASSWORD_ONLY))
+ {
+ if (!get_console_input (BSTR (&user_prompt), true, up->username, USER_PASS_LEN))
+ msg (M_FATAL, "ERROR: could not read %s username from stdin", prefix);
+ if (strlen (up->username) == 0)
+ msg (M_FATAL, "ERROR: %s username is empty", prefix);
+ }
}
if (!get_console_input (BSTR (&pass_prompt), false, up->password, USER_PASS_LEN))
- msg (M_FATAL, "ERROR: could not not read %s password from stdin", prefix);
+ msg (M_FATAL, "ERROR: could not not read %s %s from stdin",
+ prefix,
+ (flags & GET_USER_PASS_NEED_OK) ? "ok-confirmation" : "password");
+
+ if (flags & GET_USER_PASS_NEED_OK)
+ strcpy (up->password, "ok");
}
else
{
@@ -1222,7 +1233,7 @@ get_user_pass (struct user_pass *up,
if (!fp)
msg (M_ERR, "Error opening '%s' auth file: %s", prefix, auth_file);
- if (password_only)
+ if (flags & GET_USER_PASS_PASSWORD_ONLY)
{
if (fgets (up->password, USER_PASS_LEN, fp) == NULL)
msg (M_FATAL, "Error reading password from %s authfile: %s",
@@ -1243,7 +1254,7 @@ get_user_pass (struct user_pass *up,
chomp (up->username);
chomp (up->password);
- if (!password_only && strlen (up->username) == 0)
+ if (!(flags & GET_USER_PASS_PASSWORD_ONLY) && strlen (up->username) == 0)
msg (M_FATAL, "ERROR: username from %s authfile '%s' is empty", prefix, auth_file);
}
diff --git a/misc.h b/misc.h
index ac8cd42..aec12c6 100644
--- a/misc.h
+++ b/misc.h
@@ -229,12 +229,16 @@ struct user_pass
bool get_console_input (const char *prompt, const bool echo, char *input, const int capacity);
-#define GET_USER_PASS_MANAGEMENT (1<<0)
-#define GET_USER_PASS_SENSITIVE (1<<1)
+/*
+ * Flags for get_user_pass and management_query_user_pass
+ */
+#define GET_USER_PASS_MANAGEMENT (1<<0)
+#define GET_USER_PASS_SENSITIVE (1<<1)
+#define GET_USER_PASS_PASSWORD_ONLY (1<<2)
+#define GET_USER_PASS_NEED_OK (1<<3)
void get_user_pass (struct user_pass *up,
const char *auth_file,
- const bool password_only,
const char *prefix,
const unsigned int flags);
diff --git a/options.c b/options.c
index 0a4a113..05a2d0f 100644
--- a/options.c
+++ b/options.c
@@ -4896,7 +4896,7 @@ add_option (struct options *options,
{
char *module = p[i++];
VERIFY_PERMISSION (OPT_P_GENERAL);
- show_pkcs11_slots (M_INFO|M_NOPREFIX, M_WARN|M_NOPREFIX, module);
+ show_pkcs11_slots (module);
openvpn_exit (OPENVPN_EXIT_STATUS_GOOD); /* exit point */
}
else if (streq (p[0], "show-pkcs11-objects") && p[1] && p[2])
@@ -4916,7 +4916,7 @@ add_option (struct options *options,
gc_free (&gc);
- show_pkcs11_objects (M_INFO|M_NOPREFIX, M_WARN|M_NOPREFIX, provider, slot, pin);
+ show_pkcs11_objects (provider, slot, pin);
openvpn_exit (OPENVPN_EXIT_STATUS_GOOD); /* exit point */
}
else if (streq (p[0], "pkcs11-providers") && p[1])
diff --git a/pkcs11-helper-config.h b/pkcs11-helper-config.h
new file mode 100644
index 0000000..b75e1e3
--- /dev/null
+++ b/pkcs11-helper-config.h
@@ -0,0 +1,84 @@
+/*
+* OpenVPN -- An application to securely tunnel IP networks
+* over a single TCP/UDP port, with support for SSL/TLS-based
+* session authentication and key exchange,
+* packet encryption, packet authentication, and
+* packet compression.
+*
+* Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@openvpn.net>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2
+* as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program (see the file COPYING included with this
+* distribution); if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef __PKCS11_HELPER_CONFIG_H
+#define __PKCS11_HELPER_CONFIG_H
+
+#if!defined(PKCS11H_NO_NEED_INCLUDE_CONFIG)
+
+#if defined(WIN32)
+#include "config-win32.h"
+#else
+#include "config.h"
+#endif
+
+#include "syshead.h"
+
+#endif /* PKCS11H_NO_NEED_INCLUDE_CONFIG */
+
+#ifdef ENABLE_PKCS11
+#define PKCS11H_ENABLE_HELPER
+#endif
+
+#ifdef PKCS11H_ENABLE_HELPER
+
+#if defined(WIN32)
+#include "cryptoki-win32.h"
+#else
+#include "cryptoki.h"
+#endif
+
+#include "error.h"
+#include "misc.h"
+#include "ssl.h"
+
+#define PKCS11ASSERT ASSERT
+#define PKCS11LOG msg
+#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
+
+#if !defined(false)
+#define false 0
+#endif
+#if !defined(true)
+#define true (!false)
+#endif
+
+#if !defined(IN)
+#define IN
+#endif
+#if !defined(OUT)
+#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"
+
+#endif /* PKCS11H_ENABLE_HELPER */
+#endif /* __PKCS11_HELPER_CONFIG_H */
diff --git a/pkcs11-helper.c b/pkcs11-helper.c
new file mode 100644
index 0000000..32c986d
--- /dev/null
+++ b/pkcs11-helper.c
@@ -0,0 +1,3239 @@
+/*
+ * Copyright (c) 2005 Alon Bar-Lev <alon.barlev@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modifi-
+ * cation, are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright no-
+ * tice, this list of conditions and the following disclaimer in the do-
+ * cumentation and/or other materials provided with the distribution.
+ *
+ * o The names of the contributors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LI-
+ * ABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUEN-
+ * TIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEV-
+ * ER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABI-
+ * LITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * The routines in this file deal with providing private key cryptography
+ * using RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki).
+ *
+ */
+
+#include "pkcs11-helper-config.h"
+
+#if defined(PKCS11H_ENABLE_HELPER)
+
+#if defined(WIN32)
+#include "cryptoki-win32.h"
+#else
+#include "cryptoki.h"
+#endif
+
+#include "pkcs11-helper.h"
+
+/*===========================================
+ * Constants
+ */
+
+#if OPENSSL_VERSION_NUMBER < 0x00907000L && defined(CRYPTO_LOCK_ENGINE)
+# define RSA_get_default_method RSA_get_default_openssl_method
+#else
+# ifdef HAVE_ENGINE_GET_DEFAULT_RSA
+# include <openssl/engine.h>
+# if OPENSSL_VERSION_NUMBER < 0x0090704fL
+# define BROKEN_OPENSSL_ENGINE
+# endif
+# endif
+#endif
+
+
+/*===========================================
+ * Low level prototypes
+ */
+
+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 */
+);
+static
+void
+_hexToBinary (
+ IN const char * const szSource,
+ OUT unsigned char * const target,
+ IN OUT size_t * const target_size
+);
+static
+CK_RV
+_pkcs11h_getSlotById (
+ IN const pkcs11h_session_t pkcs11h_session,
+ IN const char * const szSlot
+);
+static
+CK_RV
+_pkcs11h_getSlotByName (
+ IN const pkcs11h_session_t pkcs11h_session,
+ IN const char * const szName
+);
+static
+CK_RV
+_pkcs11h_getSlotByLabel (
+ IN const pkcs11h_session_t pkcs11h_session,
+ IN const char * const szLabel
+);
+static
+CK_RV
+_pkcs11h_getObjectById (
+ IN const pkcs11h_session_t pkcs11h_session,
+ IN const CK_OBJECT_CLASS class,
+ IN const unsigned char * const id,
+ IN const size_t id_size,
+ OUT CK_OBJECT_HANDLE * const handle
+);
+static
+CK_RV
+_pkcs11h_setSessionTokenInfo (
+ IN const pkcs11h_session_t pkcs11h_session
+);
+static
+CK_RV
+_pkcs11h_resetSlot (
+ IN const pkcs11h_session_t pkcs11h_session
+);
+static
+CK_RV
+_pkcs11h_loadCertificate (
+ IN const pkcs11h_session_t pkcs11h_session,
+ IN const char * const szIdType,
+ IN const char * const szId
+);
+static
+CK_RV
+_pkcs11h_loadKeyProperties (
+ IN const pkcs11h_session_t pkcs11h_session
+);
+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
+);
+static
+CK_RV
+_pkcs11h_validateSession (
+ IN const pkcs11h_session_t pkcs11h_session
+);
+static
+CK_RV
+_pkcs11h_login (
+ IN const pkcs11h_session_t pkcs11h_session
+);
+static
+CK_RV
+_pkcs11h_logout (
+ IN const pkcs11h_session_t pkcs11h_session
+);
+static
+int
+_pkcs11h_openssl_sign (
+ IN int type,
+ IN const unsigned char *m,
+ IN unsigned int m_len,
+ OUT unsigned char *sigret,
+ OUT unsigned int *siglen,
+ IN OUT const RSA *rsa
+);
+
+/*==========================================
+ * openssl interface
+ */
+
+static
+int
+_pkcs11h_openssl_finish (
+ IN OUT RSA *rsa
+);
+static
+int
+_pkcs11h_openssl_priv_dec (
+ IN int flen,
+ IN const unsigned char *from,
+ OUT unsigned char *to,
+ IN OUT RSA *rsa,
+ IN int padding
+);
+static
+int
+_pkcs11h_openssl_priv_enc (
+ IN int flen,
+ IN const unsigned char *from,
+ OUT unsigned char *to,
+ IN OUT RSA *rsa,
+ IN int padding
+);
+static
+pkcs11h_openssl_session_t
+_pkcs11h_openssl_get_pkcs11h_openssl_session (
+ IN OUT const RSA *rsa
+);
+static
+pkcs11h_session_t
+_pkcs11h_openssl_get_pkcs11h_session (
+ IN OUT const RSA *rsa
+);
+
+/*==========================================
+ * Static data
+ */
+
+pkcs11h_data_t pkcs11h_data = NULL;
+
+/*==========================================
+ * Internal utility functions
+ */
+
+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 */
+) {
+ char *p;
+
+ PKCS11ASSERT (szSource!=NULL);
+ PKCS11ASSERT (szTarget!=NULL);
+
+ p = szTarget+nLength;
+ memmove (szTarget, szSource, nLength);
+ *p = '\0';
+ p--;
+ while (p >= szTarget && *p == ' ') {
+ *p = '\0';
+ p--;
+ }
+}
+
+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;
+
+ PKCS11ASSERT (szSource!=NULL);
+ PKCS11ASSERT (target!=NULL);
+ PKCS11ASSERT (target_size!=NULL);
+
+ target_max_size = *target_size;
+ p = szSource;
+ *target_size = 0;
+
+ while (*p != '\0' && *target_size < target_max_size) {
+ if (isxdigit (*p)) {
+ buf[i%2] = *p;
+
+ if ((i%2) == 1) {
+ unsigned v;
+ sscanf (buf, "%x", &v);
+ target[*target_size] = v & 0xff;
+ (*target_size)++;
+ }
+
+ i++;
+ }
+ p++;
+ }
+}
+
+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
+) {
+ /*
+ * 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 *x509Current = NULL, *x509New = NULL;
+ char szNotBeforeCurrent[1024], szNotBeforeNew[1024];
+ bool fBetter = false;
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _isBetterCertificate entry pCurrent=%p, nCurrentSize=%u, pNew=%p, nNewSize=%u",
+ pCurrent,
+ nCurrentSize,
+ pNew,
+ nNewSize
+ );
+
+ /*
+ * First certificae
+ * always select
+ */
+ if (nCurrentSize == 0) {
+ fBetter = true;
+ }
+ else {
+ PKCS11ASSERT (pCurrent!=NULL);
+ PKCS11ASSERT (pNew!=NULL);
+
+ szNotBeforeCurrent[0] = '\0';
+ szNotBeforeNew[0] = '\0';
+
+ x509Current = X509_new ();
+ x509New = X509_new ();
+
+ if (x509Current != NULL && x509New != NULL) {
+ const unsigned char *p1, *p2;
+
+ p1 = pCurrent;
+ p2 = pNew;
+ if (
+ d2i_X509 (&x509Current, (unsigned char **)&p1, nCurrentSize) &&
+ d2i_X509 (&x509New, (unsigned char **)&p2, nNewSize)
+ ) {
+ ASN1_TIME *notBeforeCurrent = X509_get_notBefore (x509Current);
+ ASN1_TIME *notBeforeNew = X509_get_notBefore (x509New);
+
+ if (
+ notBeforeCurrent != NULL &&
+ notBeforeNew != NULL &&
+ notBeforeCurrent->length < (int) sizeof (szNotBeforeCurrent) - 1 &&
+ notBeforeNew->length < (int) sizeof (szNotBeforeNew) - 1
+ ) {
+ memmove (szNotBeforeCurrent, notBeforeCurrent->data, notBeforeCurrent->length);
+ szNotBeforeCurrent[notBeforeCurrent->length] = '\0';
+ memmove (szNotBeforeNew, notBeforeNew->data, notBeforeNew->length);
+ szNotBeforeNew[notBeforeNew->length] = '\0';
+ }
+ }
+ }
+
+ if (x509Current != NULL) {
+ X509_free (x509Current);
+ x509Current = NULL;
+ }
+ if (x509New != NULL) {
+ X509_free (x509New);
+ x509New = NULL;
+ }
+
+ fBetter = strcmp (szNotBeforeCurrent, szNotBeforeNew) < 0;
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _isBetterCertificate return fBetter=%d",
+ fBetter ? 1 : 0
+ );
+
+ return fBetter;
+}
+
+/*========================================
+ * Low level PKCS#11 functions
+ */
+
+static
+CK_RV
+_pkcs11h_getSlotById (
+ IN const pkcs11h_session_t pkcs11h_session,
+ IN const char * const szSlot
+) {
+ pkcs11h_provider_t provider;
+ CK_RV rv = CKR_OK;
+ int provider_number;
+ int slot_number;
+ int i;
+
+ PKCS11ASSERT (pkcs11h_session!=NULL);
+ PKCS11ASSERT (szSlot!=NULL);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_getSlotById entry pkcs11h_session=%p, szSlot=%s",
+ (void *)pkcs11h_session,
+ szSlot
+ );
+
+ if (rv == CKR_OK) {
+ if (strchr (szSlot, ':') == NULL) {
+ provider_number = 0;
+ slot_number = atoi (szSlot);
+ }
+ else {
+ sscanf (szSlot, "%d:%d", &provider_number, &slot_number);
+ }
+ }
+
+ if (rv == CKR_OK) {
+ for (
+ i=0, provider=pkcs11h_data->providers;
+ (
+ i < provider_number &&
+ provider != NULL &&
+ rv == CKR_OK
+ );
+ i++, provider = provider->next
+ );
+
+ if (
+ provider == NULL ||
+ (
+ provider != NULL &&
+ !provider->fEnabled
+ )
+ ) {
+ rv = CKR_SLOT_ID_INVALID;
+ }
+ }
+
+ if (rv == CKR_OK) {
+ pkcs11h_session->provider = provider;
+ pkcs11h_session->slot = slot_number;
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG1,
+ "PKCS#11: slot selected %s-%ld",
+ pkcs11h_session->provider->szName,
+ pkcs11h_session->slot
+ );
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_getSlotById return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+static
+CK_RV
+_pkcs11h_getSlotByName (
+ IN const pkcs11h_session_t pkcs11h_session,
+ IN const char * const szName
+) {
+ CK_RV rv = CKR_OK;
+
+ pkcs11h_provider_t provider;
+ bool fFound = false;
+
+ PKCS11ASSERT (pkcs11h_session!=NULL);
+ PKCS11ASSERT (szName!=NULL);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_getSlotByName entry pkcs11h_session=%p, szName=%s",
+ (void *)pkcs11h_session,
+ szName
+ );
+
+ for (
+ provider = pkcs11h_data->providers;
+ (
+ provider != NULL &&
+ !fFound
+ );
+ provider = provider->next
+ ) {
+ CK_SLOT_ID slots[1024];
+ CK_ULONG slotnum;
+
+ if (!provider->fEnabled) {
+ continue;
+ }
+
+ slotnum = sizeof (slots) / sizeof (CK_SLOT_ID);
+ if (
+ (rv = provider->f->C_GetSlotList (
+ TRUE,
+ slots,
+ &slotnum
+ )) == CKR_OK
+ ) {
+ CK_SLOT_ID s;
+
+ for (s=0;!fFound && s<slotnum;s++) {
+ CK_SLOT_INFO info;
+
+ if (
+ (rv = 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 (!strcmp (szCurrentName, szName)) {
+ fFound = true;
+ pkcs11h_session->provider = provider;
+ pkcs11h_session->slot = slots[s];
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG1,
+ "PKCS#11: slot selected %s-%ld",
+ pkcs11h_session->provider->szName,
+ pkcs11h_session->slot
+ );
+ }
+ }
+ }
+ }
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_getSlotByName return fFound=%d-'%s'",
+ fFound ? 1 : 0,
+ pkcs11h_getMessage (rv)
+ );
+
+ return fFound ? CKR_OK : CKR_SLOT_ID_INVALID;
+}
+
+static
+CK_RV
+_pkcs11h_getSlotByLabel (
+ IN const pkcs11h_session_t pkcs11h_session,
+ IN const char * const szLabel
+) {
+ CK_RV rv;
+
+ pkcs11h_provider_t provider;
+ bool fFound = false;
+
+ PKCS11ASSERT (pkcs11h_session!=NULL);
+ PKCS11ASSERT (szLabel!=NULL);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "_PKCS#11: pkcs11h_getSlotByLabel entry pkcs11h_session=%p, szName=%s",
+ (void *)pkcs11h_session,
+ szLabel
+ );
+
+ for (
+ provider = pkcs11h_data->providers;
+ (
+ provider != NULL &&
+ !fFound
+ );
+ provider = provider->next
+ ) {
+ CK_SLOT_ID slots[1024];
+ CK_ULONG slotnum;
+
+ if (!provider->fEnabled) {
+ continue;
+ }
+
+ slotnum = sizeof (slots) / sizeof (CK_SLOT_ID);
+ if (
+ (rv = provider->f->C_GetSlotList (
+ TRUE,
+ slots,
+ &slotnum
+ )) == CKR_OK
+ ) {
+ CK_SLOT_ID s;
+
+ for (s=0;!fFound && s<slotnum;s++) {
+ CK_TOKEN_INFO info;
+
+ if (
+ (rv = 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 (!strcmp (szCurrentLabel, szLabel)) {
+ fFound = true;
+ pkcs11h_session->provider = provider;
+ pkcs11h_session->slot = slots[s];
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG1,
+ "PKCS#11: slot selected %s-%ld",
+ pkcs11h_session->provider->szName,
+ pkcs11h_session->slot
+ );
+ }
+ }
+ }
+ }
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_getSlotByLabel return fFound=%d",
+ fFound ? 1 : 0
+ );
+
+ return fFound ? CKR_OK : CKR_SLOT_ID_INVALID;
+}
+
+static
+CK_RV
+_pkcs11h_setSessionTokenInfo (
+ IN const pkcs11h_session_t pkcs11h_session
+) {
+ CK_TOKEN_INFO info;
+ CK_RV rv;
+
+ PKCS11ASSERT (pkcs11h_session!=NULL);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_setSessionTokenInfo entry pkcs11h_session=%p",
+ (void *)pkcs11h_session
+ );
+
+ if (
+ (rv = pkcs11h_session->provider->f->C_GetTokenInfo (
+ pkcs11h_session->slot,
+ &info
+ )) == CKR_OK
+ ) {
+ _pkcs11h_fixupFixedString (
+ (char *)info.label,
+ pkcs11h_session->szLabel,
+ sizeof (info.label)
+ );
+
+ memmove (
+ pkcs11h_session->serialNumber,
+ info.serialNumber,
+ sizeof (pkcs11h_session->serialNumber)
+ );
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_setSessionTokenInfo return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+static
+CK_RV
+_pkcs11h_resetSlot (
+ IN const pkcs11h_session_t pkcs11h_session
+) {
+ CK_SLOT_ID slots[1024];
+ CK_ULONG slotnum;
+ CK_RV rv;
+ bool fFound = false;
+ bool fCancel = false;
+
+ PKCS11ASSERT (pkcs11h_session!=NULL);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_resetSlot entry pkcs11h_session=%p",
+ (void *)pkcs11h_session
+ );
+
+ do {
+ slotnum = sizeof (slots) / sizeof (CK_SLOT_ID);
+ if (
+ (rv = pkcs11h_session->provider->f->C_GetSlotList (
+ TRUE,
+ slots,
+ &slotnum
+ )) == CKR_OK
+ ) {
+ CK_SLOT_ID s;
+
+ for (s=0;!fFound && s<slotnum;s++) {
+ CK_TOKEN_INFO info;
+
+ if (
+ (rv = pkcs11h_session->provider->f->C_GetTokenInfo (
+ slots[s],
+ &info
+ )) == CKR_OK
+ ) {
+ if (
+ !memcmp (
+ pkcs11h_session->serialNumber,
+ info.serialNumber,
+ sizeof (pkcs11h_session->serialNumber)
+ )
+ ) {
+ pkcs11h_session->slot = slots[s];
+ fFound = true;
+ }
+ }
+ }
+ }
+
+ if (!fFound) {
+ fCancel = !pkcs11h_data->hooks->card_prompt (
+ pkcs11h_data->hooks->card_prompt_data,
+ pkcs11h_session->szLabel
+ );
+ }
+ } while (!fFound && !fCancel);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_resetSlot return fFound=%d",
+ fFound ? 1 : 0
+ );
+
+ return fFound ? CKR_OK : CKR_SLOT_ID_INVALID;
+}
+
+static
+CK_RV
+_pkcs11h_getObjectById (
+ IN const pkcs11h_session_t pkcs11h_session,
+ IN const CK_OBJECT_CLASS class,
+ IN const unsigned char * const id,
+ IN const size_t id_size,
+ OUT CK_OBJECT_HANDLE * const handle
+) {
+ CK_ULONG count;
+ CK_RV rv = CKR_OK;
+
+ CK_ATTRIBUTE filter[] = {
+ {CKA_CLASS, (void *)&class, sizeof (class)},
+ {CKA_ID, (void *)id, id_size}
+ };
+
+ PKCS11ASSERT (pkcs11h_session!=NULL);
+ PKCS11ASSERT (id!=NULL);
+ PKCS11ASSERT (handle!=NULL);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_getObjectById entry pkcs11h_session=%p, class=%ld, id=%p, id_size=%u, handle=%p",
+ (void *)pkcs11h_session,
+ class,
+ id,
+ id_size,
+ (void *)handle
+ );
+
+ if (rv == CKR_OK) {
+ rv = pkcs11h_session->provider->f->C_FindObjectsInit (
+ pkcs11h_session->session,
+ filter,
+ sizeof (filter) / sizeof (CK_ATTRIBUTE)
+ );
+ }
+
+ if (rv == CKR_OK) {
+ rv = pkcs11h_session->provider->f->C_FindObjects (
+ pkcs11h_session->session,
+ handle,
+ 1,
+ &count
+ );
+ }
+
+ if (
+ rv == CKR_OK &&
+ count == 0
+ ) {
+ rv = CKR_FUNCTION_REJECTED;
+ }
+
+ pkcs11h_session->provider->f->C_FindObjectsFinal (
+ pkcs11h_session->session
+ );
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_getObjectById return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+static
+CK_RV
+_pkcs11h_loadCertificate (
+ IN const pkcs11h_session_t pkcs11h_session,
+ IN const char * const szIdType,
+ IN const char * const szId
+) {
+ CK_OBJECT_HANDLE objects[10];
+ CK_ULONG objects_found;
+ 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;
+
+ 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}
+ };
+
+ PKCS11ASSERT (pkcs11h_session!=NULL);
+ PKCS11ASSERT (szIdType!=NULL);
+ PKCS11ASSERT (szId!=NULL);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_loadCertificate entry pkcs11h_session=%p, szIdType=%s, szId=%s",
+ (void *)pkcs11h_session,
+ szIdType,
+ szId
+ );
+
+ 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
+ );
+ }
+ else if (!strcmp (szIdType, "id")) {
+ size_t s = sizeof (cert_filter_by);
+
+ cert_filter[1].type = CKA_ID;
+ _hexToBinary (
+ szId,
+ cert_filter_by,
+ &s
+ );
+ cert_filter[1].ulValueLen = s;
+ }
+ else if (!strcmp (szIdType, "subject")) {
+ memmove (&cert_filter[1], &cert_filter[0], sizeof (CK_ATTRIBUTE));
+ }
+ else {
+ rv = CKR_ARGUMENTS_BAD;
+ }
+ }
+
+ if (rv == CKR_OK) {
+ rv = pkcs11h_session->provider->f->C_FindObjectsInit (
+ pkcs11h_session->session,
+ cert_filter,
+ sizeof (cert_filter) / sizeof (CK_ATTRIBUTE)
+ );
+ }
+
+ if (rv == CKR_OK) {
+ while (
+ (rv = pkcs11h_session->provider->f->C_FindObjects (
+ pkcs11h_session->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++) {
+ 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_session->provider->f->C_GetAttributeValue (
+ pkcs11h_session->session,
+ objects[i],
+ attrs,
+ sizeof (attrs) / sizeof (CK_ATTRIBUTE)
+ ) == CKR_OK
+ ) {
+ bool fSelected = false;
+
+ if (!strcmp (szIdType, "subject")) {
+ X509 *x509 = NULL;
+ char szSubject[1024];
+ unsigned char *p;
+
+ x509 = X509_new ();
+
+ p = attrs_value;
+ if (d2i_X509 (&x509, &p, 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 (!strcmp (szId, szSubject)) {
+ fSelected = true;
+ }
+ }
+ else {
+ fSelected = true;
+ }
+
+ 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
+ );
+ }
+ }
+ }
+ }
+
+ pkcs11h_session->provider->f->C_FindObjectsFinal (
+ pkcs11h_session->session
+ );
+ rv = CKR_OK;
+ }
+
+ if (
+ rv == CKR_OK &&
+ selected_certificate_size == 0
+ ) {
+ rv = CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+
+ if (
+ rv == CKR_OK &&
+ (pkcs11h_session->certificate = (unsigned char *)malloc (selected_certificate_size)) == NULL
+ ) {
+ rv = CKR_HOST_MEMORY;
+ }
+
+ if (rv == CKR_OK) {
+ pkcs11h_session->certificate_size = selected_certificate_size;
+ memmove (
+ pkcs11h_session->certificate,
+ selected_certificate,
+ selected_certificate_size
+ );
+ }
+
+ if (
+ rv == CKR_OK &&
+ (pkcs11h_session->certificate_id = (unsigned char *)malloc (selected_id_size)) == NULL
+ ) {
+ rv = CKR_HOST_MEMORY;
+ }
+
+ if (rv == CKR_OK) {
+ pkcs11h_session->certificate_id_size = selected_id_size;
+ memmove (
+ pkcs11h_session->certificate_id,
+ selected_id,
+ selected_id_size
+ );
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_loadCertificate return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+static
+CK_RV
+_pkcs11h_loadKeyProperties (
+ IN const pkcs11h_session_t pkcs11h_session
+) {
+ CK_OBJECT_HANDLE key;
+ 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)}
+ };
+
+ PKCS11ASSERT (pkcs11h_session!=NULL);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_loadKeyProperties entry pkcs11h_session=%p",
+ (void *)pkcs11h_session
+ );
+
+ if (!strcmp (pkcs11h_session->provider->szSignMode, "recover")) {
+ pkcs11h_session->fKeySignRecover = true;
+ }
+ else if (!strcmp (pkcs11h_session->provider->szSignMode, "sign")) {
+ pkcs11h_session->fKeySignRecover = false;
+ }
+ else {
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_getObjectById (
+ pkcs11h_session,
+ CKO_PRIVATE_KEY,
+ pkcs11h_session->certificate_id,
+ pkcs11h_session->certificate_id_size,
+ &key
+ );
+ }
+
+ if (rv == CKR_OK) {
+ rv = pkcs11h_session->provider->f->C_GetAttributeValue (
+ pkcs11h_session->session,
+ key,
+ key_attrs,
+ sizeof (key_attrs) / sizeof (CK_ATTRIBUTE)
+ );
+ }
+
+ if (rv == CKR_OK) {
+ if (key_attrs_sign_recover != CK_FALSE) {
+ pkcs11h_session->fKeySignRecover = true;
+ }
+ else if (key_attrs_sign != CK_FALSE) {
+ pkcs11h_session->fKeySignRecover = false;
+ }
+ else {
+ rv = CKR_KEY_TYPE_INCONSISTENT;
+ }
+ }
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_loadKeyProperties return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+static
+CK_RV
+_pkcs11h_validateSession (
+ IN const pkcs11h_session_t pkcs11h_session
+) {
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_validateSession entry pkcs11h_session=%p",
+ (void *)pkcs11h_session
+ );
+
+ if (
+ pkcs11h_session->timePINExpire != (time_t)0 &&
+ pkcs11h_session->timePINExpire < time (NULL)
+ ) {
+ _pkcs11h_logout (pkcs11h_session);
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_validateSession return"
+ );
+
+ return CKR_OK;
+}
+
+static
+CK_RV
+_pkcs11h_login (
+ IN const pkcs11h_session_t pkcs11h_session
+) {
+ CK_RV rv = CKR_OK;
+
+
+ PKCS11ASSERT (pkcs11h_session!=NULL);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_login entry pkcs11h_session=%p",
+ (void *)pkcs11h_session
+ );
+
+ _pkcs11h_logout (pkcs11h_session);
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_resetSlot (pkcs11h_session);
+ }
+
+ if (rv == CKR_OK) {
+ rv = pkcs11h_session->provider->f->C_OpenSession (
+ pkcs11h_session->slot,
+ CKF_SERIAL_SESSION,
+ NULL_PTR,
+ NULL_PTR,
+ &pkcs11h_session->session
+ );
+ }
+
+ if (rv == CKR_OK) {
+ int nRetryCount = 0;
+ do {
+ CK_UTF8CHAR_PTR utfPIN = NULL;
+ CK_ULONG lPINLength = 0;
+ char szPIN[1024];
+
+ /*
+ * Assume OK for next iteration
+ */
+ rv = CKR_OK;
+
+ if (
+ rv == CKR_OK &&
+ !pkcs11h_session->fProtectedAuthentication
+ ) {
+ if (
+ !pkcs11h_data->hooks->pin_prompt (
+ pkcs11h_data->hooks->pin_prompt_data,
+ pkcs11h_session->szLabel,
+ szPIN,
+ sizeof (szPIN)
+ )
+ ) {
+ rv = CKR_FUNCTION_FAILED;
+ }
+ else {
+ utfPIN = (CK_UTF8CHAR_PTR)szPIN;
+ lPINLength = strlen (szPIN);
+ }
+ }
+
+ if (pkcs11h_data->nPINCachePeriod == -1) {
+ pkcs11h_session->timePINExpire = 0;
+ }
+ else {
+ pkcs11h_session->timePINExpire = (
+ time (NULL) +
+ (time_t)pkcs11h_data->nPINCachePeriod
+ );
+ }
+ if (
+ rv == CKR_OK &&
+ (rv = pkcs11h_session->provider->f->C_Login (
+ pkcs11h_session->session,
+ CKU_USER,
+ utfPIN,
+ lPINLength
+ )) != CKR_OK
+ ) {
+ if (rv == CKR_USER_ALREADY_LOGGED_IN) {
+ rv = CKR_OK;
+ }
+ }
+
+ /*
+ * Clean PIN buffer
+ */
+ memset (szPIN, 0, sizeof (szPIN));
+ } while (
+ ++nRetryCount < 3 &&
+ (
+ rv == CKR_PIN_INCORRECT ||
+ rv == CKR_PIN_INVALID
+ )
+ );
+ }
+
+ if (
+ rv == CKR_OK &&
+ pkcs11h_session->certificate_id != NULL
+ ) {
+ rv = _pkcs11h_getObjectById (
+ pkcs11h_session,
+ CKO_PRIVATE_KEY,
+ pkcs11h_session->certificate_id,
+ pkcs11h_session->certificate_id_size,
+ &pkcs11h_session->key
+ );
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_login return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+static
+CK_RV
+_pkcs11h_logout (
+ IN const pkcs11h_session_t pkcs11h_session
+) {
+ PKCS11ASSERT (pkcs11h_session!=NULL);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_logout entry pkcs11h_session=%p",
+ (void *)pkcs11h_session
+ );
+
+ if (pkcs11h_session->session != (CK_SESSION_HANDLE)-1) {
+ pkcs11h_session->provider->f->C_Logout (pkcs11h_session->session);
+ pkcs11h_session->provider->f->C_CloseSession (pkcs11h_session->session);
+ pkcs11h_session->key = (CK_OBJECT_HANDLE)-1;
+ pkcs11h_session->session = (CK_SESSION_HANDLE)-1;
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_logout return"
+ );
+
+ return CKR_OK;
+}
+
+
+/*=======================================
+ * Simplified PKCS#11 functions
+ */
+
+static
+bool
+_pkcs11h_hooks_card_prompt_default (
+ IN const void * pData,
+ IN const char * const szLabel
+) {
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_hooks_card_prompt_default pData=%p, szLabel=%s",
+ pData,
+ szLabel
+ );
+
+ return false;
+}
+
+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
+) {
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_hooks_pin_prompt_default pData=%p, szLabel=%s",
+ pData,
+ szLabel
+ );
+
+ return false;
+}
+
+CK_RV
+pkcs11h_initialize () {
+
+ CK_RV rv = CKR_OK;
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_initialize entry"
+ );
+
+ pkcs11h_terminate ();
+
+ if (
+ rv == CKR_OK &&
+ (pkcs11h_data = (pkcs11h_data_t)malloc (sizeof (struct pkcs11h_data_s))) == NULL
+ ) {
+ rv = CKR_HOST_MEMORY;
+ }
+
+ if (rv == CKR_OK) {
+ memset (pkcs11h_data, 0, sizeof (struct pkcs11h_data_s));
+ }
+
+ if (
+ rv == CKR_OK &&
+ (pkcs11h_data->hooks = (pkcs11h_hooks_t)malloc (sizeof (struct pkcs11h_hooks_s))) == NULL
+ ) {
+ rv = CKR_HOST_MEMORY;
+ }
+
+ if (rv == CKR_OK) {
+ memset (pkcs11h_data->hooks, 0, sizeof (struct pkcs11h_hooks_s));
+
+ pkcs11h_data->fInitialized = true;
+ pkcs11h_data->nPINCachePeriod = -1;
+
+ pkcs11h_setCardPromptHook (_pkcs11h_hooks_card_prompt_default, NULL);
+ pkcs11h_setPINPromptHook (_pkcs11h_hooks_pin_prompt_default, NULL);
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_initialize return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+CK_RV
+pkcs11h_terminate () {
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_terminate entry"
+ );
+
+ if (pkcs11h_data != NULL) {
+ pkcs11h_provider_t last = NULL;
+
+ for (
+ ;
+ pkcs11h_data->providers != NULL;
+ pkcs11h_data->providers = pkcs11h_data->providers->next
+ ) {
+ if (last != NULL) {
+ free (last);
+ }
+ last = pkcs11h_data->providers;
+
+ if (pkcs11h_data->providers->szSignMode != NULL) {
+ free (pkcs11h_data->providers->szSignMode);
+ pkcs11h_data->providers->szSignMode = NULL;
+ }
+
+ if (pkcs11h_data->providers->fShouldFinalize) {
+ pkcs11h_data->providers->f->C_Finalize (NULL);
+ pkcs11h_data->providers->fShouldFinalize = false;
+ }
+
+ if (pkcs11h_data->providers->f != NULL) {
+ pkcs11h_data->providers->f = NULL;
+ }
+
+ if (pkcs11h_data->providers->hLibrary != NULL) {
+#if defined(WIN32)
+ FreeLibrary (pkcs11h_data->providers->hLibrary);
+#else
+ dlclose (pkcs11h_data->providers->hLibrary);
+#endif
+ pkcs11h_data->providers->hLibrary = NULL;
+ }
+ }
+
+ if (last != NULL) {
+ free (last);
+ }
+
+ if (pkcs11h_data->hooks != NULL) {
+ free (pkcs11h_data->hooks);
+ pkcs11h_data->hooks = NULL;
+ }
+
+ free (pkcs11h_data);
+ pkcs11h_data = NULL;
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_terminate return"
+ );
+
+ return CKR_OK;
+}
+
+CK_RV
+pkcs11h_setPINPromptHook (
+ IN const pkcs11h_hook_pin_prompt_t hook,
+ IN void * const pData
+) {
+ PKCS11ASSERT (pkcs11h_data!=NULL);
+ PKCS11ASSERT (pkcs11h_data->fInitialized);
+
+ pkcs11h_data->hooks->pin_prompt = hook;
+ pkcs11h_data->hooks->pin_prompt_data = pData;
+
+ return CKR_OK;
+}
+
+CK_RV
+pkcs11h_setCardPromptHook (
+ IN const pkcs11h_hook_card_prompt_t hook,
+ IN void * const pData
+) {
+ PKCS11ASSERT (pkcs11h_data!=NULL);
+ PKCS11ASSERT (pkcs11h_data->fInitialized);
+
+ pkcs11h_data->hooks->card_prompt = hook;
+ pkcs11h_data->hooks->card_prompt_data = pData;
+
+ return CKR_OK;
+}
+
+CK_RV
+pkcs11h_setPINCachePeriod (
+ IN const int nPINCachePeriod
+) {
+ PKCS11ASSERT (pkcs11h_data!=NULL);
+ PKCS11ASSERT (pkcs11h_data->fInitialized);
+
+ pkcs11h_data->nPINCachePeriod = nPINCachePeriod;
+
+ return CKR_OK;
+}
+
+CK_RV
+pkcs11h_addProvider (
+ IN const char * const szProvider,
+ IN const char * const szSignMode
+) {
+ pkcs11h_provider_t provider = NULL;
+ CK_C_GetFunctionList gfl = NULL;
+ CK_RV rv = CKR_OK;
+
+ PKCS11ASSERT (pkcs11h_data!=NULL);
+ PKCS11ASSERT (pkcs11h_data->fInitialized);
+ PKCS11ASSERT (szProvider!=NULL);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_addProvider entry pid=%d, szProvider=%s, szSignMode=%s",
+#if defined(WIN32)
+ 0,
+#else
+ getpid (),
+#endif
+ szProvider,
+ szSignMode
+ );
+
+ if (
+ rv == CKR_OK &&
+ (provider = (pkcs11h_provider_t)malloc (sizeof (struct pkcs11h_provider_s))) == NULL
+ ) {
+ rv = CKR_HOST_MEMORY;
+ }
+
+ if (rv == CKR_OK) {
+ memset (provider, 0, sizeof (struct pkcs11h_provider_s));
+ provider->szName = strdup (szProvider);
+
+ if (szSignMode == NULL) {
+ provider->szSignMode = strdup ("auto");
+ }
+ else {
+ provider->szSignMode = strdup (szSignMode);
+ }
+ if (provider->szSignMode == NULL) {
+ rv = CKR_HOST_MEMORY;
+ }
+ }
+
+ 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 (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) {
+ rv = gfl (&provider->f);
+ }
+
+ 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) {
+ provider->fEnabled = true;
+ }
+
+ if (provider != NULL) {
+ if (pkcs11h_data->providers == NULL) {
+ pkcs11h_data->providers = provider;
+ }
+ else {
+ pkcs11h_provider_t last = NULL;
+
+ for (
+ last = pkcs11h_data->providers;
+ last->next != NULL;
+ last = last->next
+ );
+ last->next = provider;
+ }
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_addProvider return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+CK_RV
+pkcs11h_forkFixup () {
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_forkFixup entry pid=%d",
+#if defined(WIN32)
+ 0
+#else
+ getpid ()
+#endif
+ );
+
+ if (pkcs11h_data != NULL && pkcs11h_data->fInitialized) {
+
+ pkcs11h_provider_t current;
+
+ for (
+ current = pkcs11h_data->providers;
+ current != NULL;
+ current = current->next
+ ) {
+ if (current->fEnabled) {
+ current->f->C_Initialize (NULL);
+ }
+ }
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_forkFixup return"
+ );
+
+ return CKR_OK;
+}
+
+CK_RV
+pkcs11h_createSession (
+ IN const char * const szSlotType,
+ IN const char * const szSlot,
+ IN const char * const szIdType,
+ IN const char * const szId,
+ IN const bool fProtectedAuthentication,
+ OUT pkcs11h_session_t * const p_pkcs11h_session
+) {
+ pkcs11h_session_t pkcs11h_session;
+ CK_RV rv = CKR_OK;
+
+ PKCS11ASSERT (pkcs11h_data!=NULL);
+ PKCS11ASSERT (pkcs11h_data->fInitialized);
+ PKCS11ASSERT (szSlotType!=NULL);
+ PKCS11ASSERT (szSlot!=NULL);
+ PKCS11ASSERT (szIdType!=NULL);
+ PKCS11ASSERT (szId!=NULL);
+ PKCS11ASSERT (p_pkcs11h_session!=NULL);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_createSession entry szSlotType=%s, szSlot=%s, szIdType=%s, szId=%s, fProtectedAuthentication=%d, p_pkcs11h_session=%p",
+ szSlotType,
+ szSlot,
+ szIdType,
+ szId,
+ fProtectedAuthentication ? 1 : 0,
+ (void *)p_pkcs11h_session
+ );
+
+ if (
+ rv == CKR_OK &&
+ (pkcs11h_session = (pkcs11h_session_t)malloc (sizeof (struct pkcs11h_session_s))) == NULL
+ ) {
+ rv = CKR_HOST_MEMORY;
+ }
+
+ if (rv == CKR_OK) {
+ *p_pkcs11h_session = pkcs11h_session;
+ memset (pkcs11h_session, 0, sizeof (struct pkcs11h_session_s));
+ }
+
+ if (rv == CKR_OK) {
+ pkcs11h_session->key = (CK_OBJECT_HANDLE)-1;
+ pkcs11h_session->session = (CK_SESSION_HANDLE)-1;
+ pkcs11h_session->fProtectedAuthentication = fProtectedAuthentication;
+ }
+
+ if (rv == CKR_OK) {
+ bool fCancel = false;
+
+ do {
+ if (!strcmp (szSlotType, "id")) {
+ rv = _pkcs11h_getSlotById (pkcs11h_session, szSlot);
+ }
+ else if (!strcmp (szSlotType, "name")) {
+ rv = _pkcs11h_getSlotByName (pkcs11h_session, szSlot);
+ }
+ else if (!strcmp (szSlotType, "label")) {
+ rv = _pkcs11h_getSlotByLabel (pkcs11h_session, szSlot);
+ }
+ else {
+ rv = CKR_ARGUMENTS_BAD;
+ }
+
+ if (rv == CKR_SLOT_ID_INVALID) {
+ char szLabel[1024];
+ strcpy (szLabel, "SLOT(");
+ strncat (szLabel, szSlotType, sizeof (szLabel)-1);
+ strncat (szLabel, "=", sizeof (szLabel)-1);
+ strncat (szLabel, szSlot, sizeof (szLabel)-1);
+ strncat (szLabel, ")", sizeof (szLabel)-1);
+ szLabel[sizeof (szLabel)-1] = 0;
+ fCancel = !pkcs11h_data->hooks->card_prompt (
+ pkcs11h_data->hooks->card_prompt_data,
+ szLabel
+ );
+ }
+ } while (rv == CKR_SLOT_ID_INVALID && !fCancel);
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_setSessionTokenInfo (pkcs11h_session);
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_login (
+ pkcs11h_session
+ );
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_loadCertificate (
+ pkcs11h_session,
+ szIdType,
+ szId
+ );
+ }
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_loadKeyProperties (
+ pkcs11h_session
+ );
+ }
+
+ /*
+ * Complete missing login process
+ */
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_getObjectById (
+ pkcs11h_session,
+ CKO_PRIVATE_KEY,
+ pkcs11h_session->certificate_id,
+ pkcs11h_session->certificate_id_size,
+ &pkcs11h_session->key
+ );
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_createSession return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+CK_RV
+pkcs11h_freeSession (
+ IN const pkcs11h_session_t pkcs11h_session
+) {
+ PKCS11ASSERT (pkcs11h_data!=NULL);
+ PKCS11ASSERT (pkcs11h_data->fInitialized);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_freeSession entry pkcs11h_session=%p",
+ (void *)pkcs11h_session
+ );
+
+ if (pkcs11h_session != NULL) {
+ _pkcs11h_logout (pkcs11h_session);
+
+ if (pkcs11h_session->certificate != NULL) {
+ free (pkcs11h_session->certificate);
+ }
+ if (pkcs11h_session->certificate_id != NULL) {
+ free (pkcs11h_session->certificate_id);
+ }
+
+ free (pkcs11h_session);
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_freeSession return"
+ );
+
+ return CKR_OK;
+}
+
+CK_RV
+pkcs11h_sign (
+ IN const pkcs11h_session_t pkcs11h_session,
+ 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
+) {
+ CK_MECHANISM mech = {
+ mech_type, NULL, 0
+ };
+
+ CK_RV rv = CKR_OK;
+ bool fLogonRetry = false;
+ bool fOpSuccess = false;
+
+ PKCS11ASSERT (pkcs11h_data!=NULL);
+ PKCS11ASSERT (pkcs11h_data->fInitialized);
+ PKCS11ASSERT (pkcs11h_session!=NULL);
+ PKCS11ASSERT (source!=NULL);
+ PKCS11ASSERT (target_size!=NULL);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_sign entry pkcs11h_session=%p, mech_type=%ld, source=%p, source_size=%u, target=%p, target_size=%p",
+ (void *)pkcs11h_session,
+ mech_type,
+ source,
+ source_size,
+ target,
+ (void *)target_size
+ );
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_validateSession (pkcs11h_session);
+ }
+
+ while (rv == CKR_OK && !fOpSuccess) {
+ rv = pkcs11h_session->provider->f->C_SignInit (
+ pkcs11h_session->session,
+ &mech,
+ pkcs11h_session->key
+ );
+
+ if (rv == CKR_OK) {
+ fOpSuccess = true;
+ }
+ else {
+ if (!fLogonRetry) {
+ fLogonRetry = true;
+ rv = _pkcs11h_login (pkcs11h_session);
+ }
+ }
+ }
+
+ if (rv == CKR_OK) {
+ CK_ULONG size = *target_size;
+ rv = pkcs11h_session->provider->f->C_Sign (
+ pkcs11h_session->session,
+ (CK_BYTE_PTR)source,
+ source_size,
+ (CK_BYTE_PTR)target,
+ &size
+ );
+
+ *target_size = (int)size;
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_sign return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+CK_RV
+pkcs11h_signRecover (
+ IN const pkcs11h_session_t pkcs11h_session,
+ 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
+) {
+ CK_MECHANISM mech = {
+ mech_type, NULL, 0
+ };
+ CK_RV rv = CKR_OK;
+ bool fLogonRetry = false;
+ bool fOpSuccess = false;
+
+ PKCS11ASSERT (pkcs11h_data!=NULL);
+ PKCS11ASSERT (pkcs11h_data->fInitialized);
+ PKCS11ASSERT (pkcs11h_session!=NULL);
+ PKCS11ASSERT (source!=NULL);
+ PKCS11ASSERT (target_size!=NULL);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_signRecover entry pkcs11h_session=%p, mech_type=%ld, source=%p, source_size=%u, target=%p, target_size=%p",
+ (void *)pkcs11h_session,
+ mech_type,
+ source,
+ source_size,
+ target,
+ (void *)target_size
+ );
+
+ if (rv == CKR_OK) {
+ rv = _pkcs11h_validateSession (pkcs11h_session);
+ }
+
+ while (rv == CKR_OK && !fOpSuccess) {
+ rv = pkcs11h_session->provider->f->C_SignRecoverInit (
+ pkcs11h_session->session,
+ &mech,
+ pkcs11h_session->key
+ );
+
+ if (rv == CKR_OK) {
+ fOpSuccess = true;
+ }
+ else {
+ if (!fLogonRetry) {
+ fLogonRetry = true;
+ rv = _pkcs11h_login (pkcs11h_session);
+ }
+ }
+ }
+
+ if (rv == CKR_OK) {
+ CK_ULONG size = *target_size;
+ rv = pkcs11h_session->provider->f->C_SignRecover (
+ pkcs11h_session->session,
+ (CK_BYTE_PTR)source,
+ source_size,
+ (CK_BYTE_PTR)target,
+ &size
+ );
+
+ *target_size = (int)size;
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_signRecover return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+CK_RV
+pkcs11h_decrypt (
+ IN const pkcs11h_session_t pkcs11h_session,
+ 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
+) {
+ CK_MECHANISM mech = {
+ mech_type, NULL, 0
+ };
+ CK_ULONG size;
+ CK_RV rv = CKR_OK;
+ bool fLogonRetry = false;
+ bool fOpSuccess = false;
+
+ PKCS11ASSERT (pkcs11h_data!=NULL);
+ PKCS11ASSERT (pkcs11h_data->fInitialized);
+ PKCS11ASSERT (pkcs11h_session!=NULL);
+ PKCS11ASSERT (source!=NULL);
+ PKCS11ASSERT (target_size!=NULL);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_decrypt entry pkcs11h_session=%p, mech_type=%ld, source=%p, source_size=%u, target=%p, target_size=%p",
+ (void *)pkcs11h_session,
+ mech_type,
+ source,
+ source_size,
+ target,
+ (void *)target_size
+ );
+
+ if (rv != CKR_OK) {
+ rv = _pkcs11h_validateSession (pkcs11h_session);
+ }
+
+ while (rv == CKR_OK && !fOpSuccess) {
+ rv = pkcs11h_session->provider->f->C_DecryptInit (
+ pkcs11h_session->session,
+ &mech,
+ pkcs11h_session->key
+ );
+
+ if (rv == CKR_OK) {
+ fOpSuccess = true;
+ }
+ else {
+ if (!fLogonRetry) {
+ fLogonRetry = true;
+ rv = _pkcs11h_login (pkcs11h_session);
+ }
+ }
+ }
+
+ if (rv == CKR_OK) {
+ size = *target_size;
+ rv = pkcs11h_session->provider->f->C_Decrypt (
+ pkcs11h_session->session,
+ (CK_BYTE_PTR)source,
+ source_size,
+ (CK_BYTE_PTR)target,
+ &size
+ );
+
+ *target_size = (int)size;
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_decrypt return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv;
+}
+
+CK_RV
+pkcs11h_getCertificate (
+ IN const pkcs11h_session_t pkcs11h_session,
+ OUT unsigned char * const certificate,
+ IN OUT size_t * const certificate_size
+) {
+ CK_RV rv = CKR_OK;
+
+ PKCS11ASSERT (pkcs11h_data!=NULL);
+ PKCS11ASSERT (pkcs11h_data->fInitialized);
+ PKCS11ASSERT (certificate_size!=NULL);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_getCertificate entry pkcs11h_session=%p, certificate=%p, certificate_size=%p",
+ (void *)pkcs11h_session,
+ certificate,
+ (void *)certificate_size
+ );
+
+ *certificate_size = pkcs11h_session->certificate_size;
+
+ if (certificate != NULL) {
+ if (
+ rv == CKR_OK &&
+ *certificate_size > pkcs11h_session->certificate_size
+ ) {
+ rv = CKR_BUFFER_TOO_SMALL;
+ }
+
+ if (rv == CKR_OK) {
+ memmove (certificate, pkcs11h_session->certificate, *certificate_size);
+ }
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_getCertificate return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ 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";
+ }
+}
+
+/*==========================================
+ * openssl interface
+ */
+
+static
+pkcs11h_openssl_session_t
+_pkcs11h_openssl_get_pkcs11h_openssl_session (
+ IN OUT const RSA *rsa
+) {
+ pkcs11h_openssl_session_t session;
+
+ PKCS11ASSERT (rsa!=NULL);
+ session = (pkcs11h_openssl_session_t)RSA_get_app_data (rsa);
+ PKCS11ASSERT (session!=NULL);
+
+ return session;
+}
+
+static
+pkcs11h_session_t
+_pkcs11h_openssl_get_pkcs11h_session (
+ IN OUT const RSA *rsa
+) {
+ pkcs11h_openssl_session_t session;
+
+ PKCS11ASSERT (rsa!=NULL);
+ session = (pkcs11h_openssl_session_t)RSA_get_app_data (rsa);
+ PKCS11ASSERT (session!=NULL);
+ PKCS11ASSERT (session->pkcs11h_session!=NULL);
+
+ return session->pkcs11h_session;
+}
+
+static
+int
+_pkcs11h_openssl_priv_enc (
+ IN int flen,
+ IN const unsigned char *from,
+ OUT unsigned char *to,
+ IN OUT RSA *rsa,
+ IN int padding
+) {
+ PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Private key encryption not supported");
+ return -1;
+}
+
+static
+int
+_pkcs11h_openssl_priv_dec (
+ IN int flen,
+ IN const unsigned char *from,
+ OUT unsigned char *to,
+ IN OUT RSA *rsa,
+ IN int padding
+) {
+ pkcs11h_session_t pkcs11h_session = _pkcs11h_openssl_get_pkcs11h_session (rsa);
+ CK_RV rv = CKR_OK;
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_openssl_priv_dec entered - flen=%d, from=%p, to=%p, rsa=%p, padding=%d",
+ flen,
+ from,
+ to,
+ (void *)rsa,
+ padding
+ );
+
+ PKCS11ASSERT (from!=NULL);
+ PKCS11ASSERT (to!=NULL);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG1,
+ "PKCS#11: Performing decryption using private key"
+ );
+
+ if (padding != RSA_PKCS1_PADDING) {
+ rv = CKR_ARGUMENTS_BAD;
+ }
+
+ if (
+ rv == CKR_OK &&
+ (rv = pkcs11h_decrypt (
+ pkcs11h_session,
+ CKM_RSA_PKCS,
+ from,
+ flen,
+ to,
+ (size_t *)&flen
+ )) != CKR_OK
+ ) {
+ PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot decrypt using private key %ld:'%s'", rv, pkcs11h_getMessage (rv));
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_openssl_priv_dec - return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ return rv == CKR_OK ? 1 : -1;
+}
+
+static
+int
+_pkcs11h_openssl_sign (
+ IN int type,
+ IN const unsigned char *m,
+ IN unsigned int m_len,
+ OUT unsigned char *sigret,
+ OUT unsigned int *siglen,
+ IN OUT const RSA *rsa
+) {
+ pkcs11h_openssl_session_t pkcs11h_openssl_session = _pkcs11h_openssl_get_pkcs11h_openssl_session (rsa);
+ pkcs11h_session_t pkcs11h_session = _pkcs11h_openssl_get_pkcs11h_session (rsa);
+ CK_RV rv = CKR_OK;
+
+ int myrsa_size = 0;
+
+ unsigned char *enc_alloc = NULL;
+ unsigned char *enc;
+ int enc_len = 0;
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_openssl_sign entered - type=%d, m=%p, m_len=%u, signret=%p, signlen=%p, rsa=%p",
+ type,
+ m,
+ m_len,
+ sigret,
+ (void *)siglen,
+ (void *)rsa
+ );
+
+ PKCS11ASSERT (m!=NULL);
+ PKCS11ASSERT (sigret!=NULL);
+ PKCS11ASSERT (siglen!=NULL);
+
+ if (rv == CKR_OK) {
+ myrsa_size=RSA_size(rsa);
+ }
+
+ if (pkcs11h_openssl_session->fShouldPadSign) {
+ X509_SIG sig;
+ ASN1_TYPE parameter;
+ X509_ALGOR algor;
+ ASN1_OCTET_STRING digest;
+
+ if (
+ rv == CKR_OK &&
+ (enc=enc_alloc=(unsigned char *)malloc ((unsigned int)myrsa_size+1)) == NULL
+ ) {
+ rv = CKR_HOST_MEMORY;
+ }
+
+ if (rv == CKR_OK) {
+ sig.algor= &algor;
+ }
+
+ if (
+ rv == CKR_OK &&
+ (sig.algor->algorithm=OBJ_nid2obj(type)) == NULL
+ ) {
+ rv = CKR_FUNCTION_FAILED;
+ }
+
+ if (
+ rv == CKR_OK &&
+ sig.algor->algorithm->length == 0
+ ) {
+ rv = CKR_KEY_SIZE_RANGE;
+ }
+
+ if (rv == CKR_OK) {
+ parameter.type=V_ASN1_NULL;
+ parameter.value.ptr=NULL;
+
+ sig.algor->parameter= &parameter;
+
+ 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
+ ) {
+ rv = CKR_FUNCTION_FAILED;
+ }
+
+ if (
+ rv == CKR_OK &&
+ enc_len > (myrsa_size-RSA_PKCS1_PADDING_SIZE)
+ ) {
+ rv = CKR_KEY_SIZE_RANGE;
+ }
+
+ if (rv == CKR_OK) {
+ unsigned char *p=enc;
+ i2d_X509_SIG(&sig,&p);
+ }
+ }
+ else {
+ if (rv == CKR_OK) {
+ enc = (unsigned char *)m;
+ enc_len = m_len;
+ }
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG1,
+ "PKCS#11: Performing signature"
+ );
+
+ *siglen = myrsa_size;
+
+ if (pkcs11h_session->fKeySignRecover) {
+ if (
+ (rv = pkcs11h_signRecover (
+ pkcs11h_session,
+ 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));
+ }
+ }
+ else {
+ if (
+ (rv = pkcs11h_sign (
+ pkcs11h_session,
+ 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));
+ }
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_openssl_sign - return rv=%ld-'%s'",
+ rv,
+ pkcs11h_getMessage (rv)
+ );
+
+ if (enc_alloc != NULL) {
+ free (enc_alloc);
+ }
+
+ return rv == CKR_OK ? 1 : -1;
+}
+
+static
+int
+_pkcs11h_openssl_finish (
+ IN OUT RSA *rsa
+) {
+ pkcs11h_openssl_session_t pkcs11h_openssl_session = _pkcs11h_openssl_get_pkcs11h_openssl_session (rsa);
+
+ PKCS11LOG (
+ PKCS11_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);
+
+#ifdef BROKEN_OPENSSL_ENGINE
+ {
+ /* We get called TWICE here, once for
+ * releasing the key and also for
+ * releasing the engine.
+ * To prevent endless recursion, FIRST
+ * clear rsa->engine, THEN call engine->finish
+ */
+ ENGINE *e = rsa->engine;
+ rsa->engine = NULL;
+ if (e) {
+ ENGINE_finish(e);
+ }
+ }
+#endif
+ }
+
+ pkcs11h_openssl_freeSession (pkcs11h_openssl_session);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: _pkcs11h_openssl_finish - return"
+ );
+
+ return 1;
+}
+
+pkcs11h_openssl_session_t
+pkcs11h_openssl_createSession (
+ IN const bool fShouldPadSign
+) {
+ pkcs11h_openssl_session_t pkcs11h_openssl_session = NULL;
+ bool fOK = true;
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_openssl_createSession - entry fShouldPadSign=%d",
+ fShouldPadSign ? 1 : 0
+ );
+
+ if (
+ fOK &&
+ (pkcs11h_openssl_session = (pkcs11h_openssl_session_t)malloc (sizeof (struct pkcs11h_openssl_session_s))) == NULL
+ ) {
+ fOK = false;
+ PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot allocate memory");
+ }
+
+ if (fOK) {
+ memset (pkcs11h_openssl_session, 0, sizeof (struct pkcs11h_openssl_session_s));
+ }
+
+ if (fOK) {
+ pkcs11h_openssl_session->fShouldPadSign = fShouldPadSign;
+ pkcs11h_openssl_session->nReferenceCount = 1;
+ }
+
+ if (!fOK) {
+ free (pkcs11h_openssl_session);
+ pkcs11h_openssl_session = NULL;
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_openssl_createSession - return pkcs11h_openssl_session=%p",
+ (void *)pkcs11h_openssl_session
+ );
+
+ return pkcs11h_openssl_session;
+}
+
+void
+pkcs11h_openssl_freeSession (
+ IN const pkcs11h_openssl_session_t pkcs11h_openssl_session
+) {
+ PKCS11ASSERT (pkcs11h_openssl_session!=NULL);
+ PKCS11ASSERT (pkcs11h_openssl_session->nReferenceCount>0);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_openssl_freeSession - entry pkcs11h_openssl_session=%p, count=%d",
+ (void *)pkcs11h_openssl_session,
+ pkcs11h_openssl_session->nReferenceCount
+ );
+
+ pkcs11h_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 (pkcs11h_openssl_session->pkcs11h_session != NULL) {
+ pkcs11h_freeSession (pkcs11h_openssl_session->pkcs11h_session);
+ pkcs11h_openssl_session->pkcs11h_session = NULL;
+ }
+
+ free (pkcs11h_openssl_session);
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_openssl_freeSession - return"
+ );
+}
+
+RSA *
+pkcs11h_openssl_getRSA (
+ IN const pkcs11h_openssl_session_t pkcs11h_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;
+ unsigned char *p;
+ bool fOK = true;
+
+ PKCS11ASSERT (pkcs11h_openssl_session!=NULL);
+ PKCS11ASSERT (!pkcs11h_openssl_session->fInitialized);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_openssl_getRSA - entry pkcs11h_openssl_session=%p",
+ (void *)pkcs11h_openssl_session
+ );
+
+ if (
+ fOK &&
+ (x509 = X509_new ()) == NULL
+ ) {
+ fOK = false;
+ PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Unable to allocate certificate object");
+ }
+
+ certificate_size = sizeof (certificate);
+ if (
+ fOK &&
+ (rv = pkcs11h_getCertificate (
+ pkcs11h_openssl_session->pkcs11h_session,
+ 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));
+ }
+
+ p = certificate;
+ if (
+ fOK &&
+ !d2i_X509 (&x509, &p, certificate_size)
+ ) {
+ fOK = false;
+ PKCS11LOG (PKCS11_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");
+ }
+
+ if (
+ fOK &&
+ pubkey->type != EVP_PKEY_RSA
+ ) {
+ fOK = false;
+ PKCS11LOG (PKCS11_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");
+ }
+
+ 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_enc = _pkcs11h_openssl_priv_enc;
+ pkcs11h_openssl_session->smart_rsa.rsa_priv_dec = _pkcs11h_openssl_priv_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;
+
+ RSA_set_method (rsa, &pkcs11h_openssl_session->smart_rsa);
+ RSA_set_app_data (rsa, pkcs11h_openssl_session);
+ pkcs11h_openssl_session->nReferenceCount++;
+ }
+
+#ifdef BROKEN_OPENSSL_ENGINE
+ if (fOK) {
+ 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");
+ }
+#endif
+
+ if (fOK) {
+ /*
+ So that it won't hold RSA
+ */
+ pkcs11h_openssl_session->x509 = X509_dup (x509);
+ rsa->flags |= RSA_FLAG_SIGN_VER;
+ pkcs11h_openssl_session->fInitialized = true;
+ }
+ else {
+ if (rsa != NULL) {
+ RSA_free (rsa);
+ rsa = NULL;
+ }
+ }
+
+ /*
+ * openssl objects have reference
+ * count, so release them
+ */
+ if (pubkey != NULL) {
+ EVP_PKEY_free (pubkey);
+ pubkey = NULL;
+ }
+
+ if (x509 != NULL) {
+ X509_free (x509);
+ x509 = NULL;
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_openssl_getRSA - return rsa=%p",
+ (void *)rsa
+ );
+
+ return rsa;
+}
+
+X509 *
+pkcs11h_openssl_getX509 (
+ IN const pkcs11h_openssl_session_t pkcs11h_openssl_session
+) {
+ X509 *x509 = NULL;
+
+ PKCS11ASSERT (pkcs11h_openssl_session!=NULL);
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_openssl_getX509 - entry pkcs11h_openssl_session=%p",
+ (void *)pkcs11h_openssl_session
+ );
+
+ if (pkcs11h_openssl_session->x509 != NULL) {
+ x509 = X509_dup (pkcs11h_openssl_session->x509);
+ }
+
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11h_openssl_getX509 - return x509=%p",
+ (void *)x509
+ );
+
+ return x509;
+}
+
+
+void
+pkcs11h_standalone_dump_slots (
+ IN const pkcs11h_output_print_t my_output,
+ IN const void *pData,
+ IN const char * const provider
+) {
+ CK_RV rv = CKR_OK;
+
+ pkcs11h_provider_t pkcs11h_provider;
+
+ PKCS11ASSERT (provider!=NULL);
+
+ if (
+ rv == CKR_OK &&
+ (rv = pkcs11h_initialize ()) != CKR_OK
+ ) {
+ my_output (pData, "PKCS#11: Cannot initialize interface %ld-'%s'\n", rv, pkcs11h_getMessage (rv));
+ }
+
+ if (
+ rv == CKR_OK &&
+ (rv = pkcs11h_addProvider (provider, NULL)) != 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;
+ 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;
+ }
+ }
+
+ if (rv == CKR_OK) {
+ CK_INFO info;
+
+ if ((rv = pkcs11h_provider->f->C_GetInfo (&info)) != CKR_OK) {
+ my_output (pData, "PKCS#11: Cannot get PKCS#11 provider information %ld-'%s'\n", rv, pkcs11h_getMessage (rv));
+ rv = CKR_OK;
+ }
+ else {
+ char szManufacturerID[sizeof (info.manufacturerID)+1];
+
+ _pkcs11h_fixupFixedString (
+ (char *)info.manufacturerID,
+ szManufacturerID,
+ sizeof (info.manufacturerID)
+ );
+
+ my_output (
+ pData,
+ (
+ "Provider Information:\n"
+ "\tcryptokiVersion:\t%u.%u\n"
+ "\tmanufacturerID:\t\t%s\n"
+ "\tflags:\t\t\t%d\n"
+ "\n"
+ ),
+ info.cryptokiVersion.major,
+ info.cryptokiVersion.minor,
+ szManufacturerID,
+ (unsigned)info.flags
+ );
+ }
+ }
+
+ if (rv == CKR_OK) {
+ CK_SLOT_ID slots[1024];
+ CK_ULONG slotnum;
+ CK_SLOT_ID s;
+
+ slotnum = sizeof (slots) / sizeof (CK_SLOT_ID);
+ if (
+ (rv = pkcs11h_provider->f->C_GetSlotList (
+ FALSE,
+ slots,
+ &slotnum
+ )) != CKR_OK
+ ) {
+ my_output (pData, "PKCS#11: Cannot get slot list %ld-'%s'\n", rv, pkcs11h_getMessage (rv));
+ }
+ else {
+ my_output (
+ pData,
+ (
+ "The following slots are available for use with this provider.\n"
+ "Each slot shown below may be used as a parameter to a\n"
+ "%s and %s options.\n"
+ "\n"
+ "Slots: (id - name)\n"
+ ),
+ PKCS11_PRM_SLOT_TYPE,
+ PKCS11_PRM_SLOT_ID
+ );
+ for (s=0;s<slotnum;s++) {
+ CK_SLOT_INFO info;
+
+ if (
+ (rv = pkcs11h_provider->f->C_GetSlotInfo (
+ slots[s],
+ &info
+ )) == CKR_OK
+ ) {
+ char szCurrentName[sizeof (info.slotDescription)+1];
+
+ _pkcs11h_fixupFixedString (
+ (char *)info.slotDescription,
+ szCurrentName,
+ sizeof (info.slotDescription)
+ );
+
+ my_output (pData, "\t%lu - %s\n", slots[s], szCurrentName);
+ }
+ }
+ }
+ }
+
+ pkcs11h_terminate ();
+}
+
+static
+bool
+_pkcs11h_standalone_dump_objects_pin_prompt (
+ IN const void *pData,
+ IN const char * const szLabel,
+ OUT char * const szPIN,
+ IN const size_t nMaxPIN
+) {
+ strncpy (szPIN, (char *)pData, nMaxPIN);
+ return true;
+}
+
+void
+pkcs11h_standalone_dump_objects (
+ IN const pkcs11h_output_print_t my_output,
+ IN const void *pData,
+ IN const char * const provider,
+ IN const char * const slot,
+ IN const char * const pin
+) {
+ CK_SLOT_ID s;
+ CK_RV rv = CKR_OK;
+
+ pkcs11h_provider_t pkcs11h_provider;
+
+ PKCS11ASSERT (provider!=NULL);
+ PKCS11ASSERT (slot!=NULL);
+ PKCS11ASSERT (pin!=NULL);
+
+ s = atoi (slot);
+
+ if (
+ rv == CKR_OK &&
+ (rv = pkcs11h_initialize ()) != CKR_OK
+ ) {
+ my_output (pData, "PKCS#11: Cannot initialize interface %ld-'%s'\n", rv, pkcs11h_getMessage (rv));
+ }
+
+ if (
+ rv == CKR_OK &&
+ (rv = pkcs11h_setPINPromptHook (_pkcs11h_standalone_dump_objects_pin_prompt, (void *)pin)) != CKR_OK
+ ) {
+ my_output (pData, "PKCS#11: Cannot set hooks %ld-'%s'\n", rv, pkcs11h_getMessage (rv));
+ }
+
+ if (
+ rv == CKR_OK &&
+ (rv = pkcs11h_addProvider (provider, NULL)) != 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;
+ 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;
+ }
+ }
+
+ if (rv == CKR_OK) {
+ CK_TOKEN_INFO info;
+
+ if (
+ (rv = pkcs11h_provider->f->C_GetTokenInfo (
+ s,
+ &info
+ )) != CKR_OK
+ ) {
+ my_output (pData, "PKCS#11: Cannot get token information for slot %ld %ld-'%s'\n", s, rv, pkcs11h_getMessage (rv));
+ rv = CKR_OK;
+ }
+ else {
+ char szLabel[sizeof (info.label)+1];
+ char szManufacturerID[sizeof (info.manufacturerID)+1];
+ char szModel[sizeof (info.model)+1];
+ char szSerialNumber[sizeof (info.serialNumber)+1];
+
+ _pkcs11h_fixupFixedString (
+ (char *)info.label,
+ szLabel,
+ sizeof (info.label)
+ );
+ _pkcs11h_fixupFixedString (
+ (char *)info.manufacturerID,
+ szManufacturerID,
+ sizeof (info.manufacturerID)
+ );
+ _pkcs11h_fixupFixedString (
+ (char *)info.model,
+ szModel,
+ sizeof (info.model)
+ );
+ _pkcs11h_fixupFixedString (
+ (char *)info.serialNumber,
+ szSerialNumber,
+ sizeof (info.serialNumber)
+ );
+
+ my_output (
+ pData,
+ (
+ "Token Information:\n"
+ "\tlabel:\t\t%s\n"
+ "\tmanufacturerID:\t%s\n"
+ "\tmodel:\t\t%s\n"
+ "\tserialNumber:\t%s\n"
+ "\tflags:\t\t%08x\n"
+ "\n"
+ "You can access this token using\n"
+ "%s \"label\" %s \"%s\" options.\n"
+ "\n"
+ ),
+ szLabel,
+ szManufacturerID,
+ szModel,
+ szSerialNumber,
+ (unsigned)info.flags,
+ PKCS11_PRM_SLOT_TYPE,
+ PKCS11_PRM_SLOT_ID,
+ szLabel
+ );
+ }
+ }
+
+ if (rv == CKR_OK) {
+ CK_SESSION_HANDLE session;
+
+ if (
+ (rv = pkcs11h_provider->f->C_OpenSession (
+ s,
+ CKF_SERIAL_SESSION,
+ NULL_PTR,
+ NULL_PTR,
+ &session
+ )) != CKR_OK
+ ) {
+ my_output (pData, "PKCS#11: Cannot open session to slot %ld %ld-'%s'\n", s, rv, pkcs11h_getMessage (rv));
+ rv = CKR_OK;
+ }
+ else {
+ CK_OBJECT_HANDLE objects[10];
+ CK_ULONG objects_found;
+
+ 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 (
+ session,
+ NULL,
+ 0
+ )) != 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 (
+ pkcs11h_provider->f->C_GetAttributeValue (
+ session,
+ objects[i],
+ attrs,
+ sizeof (attrs) / sizeof (CK_ATTRIBUTE)
+ ) == 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
+ );
+
+
+ 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_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 {
+ unsigned char *p;
+
+ p = certificate;
+ if (d2i_X509 (&x509, &p, 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;
+ }
+
+ my_output (
+ pData,
+ (
+ "\tsubject:\t%s\n"
+ "\tserialNumber:\t%s\n"
+ "\tnotBefore:\t%s\n"
+ ),
+ szSubject,
+ szSerial,
+ szNotBefore
+ );
+ }
+ }
+ 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"
+ );
+ }
+ }
+ else {
+ my_output (pData, "\tType:\t\tUnsupported\n");
+ }
+ }
+ }
+
+ pkcs11h_provider->f->C_FindObjectsFinal (session);
+ pkcs11h_provider->f->C_Logout (session);
+ pkcs11h_provider->f->C_CloseSession (session);
+ }
+ }
+ }
+
+ pkcs11h_terminate ();
+}
+
+#ifdef BROKEN_OPENSSL_ENGINE
+static void broken_openssl_init() __attribute__ ((constructor));
+static void broken_openssl_init()
+{
+ SSL_library_init();
+ ENGINE_load_openssl();
+ ENGINE_register_all_RSA();
+}
+#endif
+
+#else
+static void dummy (void) {}
+#endif /* PKCS11_HELPER_ENABLE */
diff --git a/pkcs11-helper.h b/pkcs11-helper.h
new file mode 100644
index 0000000..10a3a6f
--- /dev/null
+++ b/pkcs11-helper.h
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2005 Alon Bar-Lev <alon.barlev@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modifi-
+ * cation, are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright no-
+ * tice, this list of conditions and the following disclaimer in the do-
+ * cumentation and/or other materials provided with the distribution.
+ *
+ * o The names of the contributors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LI-
+ * ABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUEN-
+ * TIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEV-
+ * ER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABI-
+ * LITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * The routines in this file deal with providing private key cryptography
+ * using RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki).
+ *
+ */
+
+#ifndef __PKCS11_HELPER_H
+#define __PKCS11_HELPER_H
+
+#include "pkcs11-helper-config.h"
+
+#define PKCS11H_MAX_ATTRIBUTE_SIZE (10*1024)
+
+typedef void (*pkcs11h_output_print_t)(
+ IN const void *pData,
+ IN const char * const szFormat,
+ IN ...
+);
+
+typedef bool (*pkcs11h_hook_card_prompt_t)(
+ IN const void *pData,
+ IN const char * const szLabel
+);
+
+typedef bool (*pkcs11h_hook_pin_prompt_t)(
+ IN const void *pData,
+ IN const char * const szLabel,
+ OUT char * const szPIN,
+ IN const size_t nMaxPIN
+);
+
+
+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;
+
+typedef struct pkcs11h_provider_s {
+ struct pkcs11h_provider_s *next;
+
+ 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;
+
+typedef struct pkcs11h_session_s {
+
+ pkcs11h_provider_t provider;
+
+ bool fProtectedAuthentication;
+
+ char szLabel[sizeof (((CK_TOKEN_INFO *)NULL)->label)+1];
+ CK_CHAR serialNumber[sizeof (((CK_TOKEN_INFO *)NULL)->serialNumber)];
+
+ unsigned char *certificate;
+ size_t certificate_size;
+ unsigned char *certificate_id;
+ size_t certificate_id_size;
+
+ CK_SLOT_ID slot;
+ bool fKeySignRecover;
+
+ CK_SESSION_HANDLE session;
+ CK_OBJECT_HANDLE key;
+
+ time_t timePINExpire;
+} *pkcs11h_session_t;
+
+typedef struct pkcs11h_data_s {
+ bool fInitialized;
+ int nPINCachePeriod;
+ pkcs11h_provider_t providers;
+ pkcs11h_hooks_t hooks;
+} *pkcs11h_data_t;
+
+typedef struct pkcs11h_openssl_session_s {
+ int nReferenceCount;
+ bool fInitialized;
+ bool fShouldPadSign;
+ X509 *x509;
+ RSA_METHOD smart_rsa;
+ int (*orig_finish)(RSA *rsa);
+ pkcs11h_session_t pkcs11h_session;
+} *pkcs11h_openssl_session_t;
+
+CK_RV
+pkcs11h_initialize ();
+
+CK_RV
+pkcs11h_terminate ();
+
+CK_RV
+pkcs11h_setCardPromptHook (
+ IN const pkcs11h_hook_card_prompt_t hook,
+ IN void * const pData
+);
+
+CK_RV
+pkcs11h_setPINPromptHook (
+ IN const pkcs11h_hook_pin_prompt_t hook,
+ IN void * const pData
+);
+
+CK_RV
+pkcs11h_setPINCachePeriod (
+ IN const int nPINCachePeriod
+);
+
+CK_RV
+pkcs11h_addProvider (
+ IN const char * const szProvider,
+ IN const char * const szSignMode
+);
+
+CK_RV
+pkcs11h_forkFixup ();
+
+CK_RV
+pkcs11h_createSession (
+ IN const char * const szSlotType,
+ IN const char * const szSlot,
+ IN const char * const szIdType,
+ IN const char * const szId,
+ IN const bool fProtectedAuthentication,
+ OUT pkcs11h_session_t * const pkcs11h_session
+);
+
+CK_RV
+pkcs11h_freeSession (
+ IN const pkcs11h_session_t pkcs11h_session
+);
+
+CK_RV
+pkcs11h_sign (
+ IN const pkcs11h_session_t pkcs11h_session,
+ 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
+);
+
+CK_RV
+pkcs11h_signRecover (
+ IN const pkcs11h_session_t pkcs11h_session,
+ 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
+);
+
+CK_RV
+pkcs11h_decrypt (
+ IN const pkcs11h_session_t pkcs11h_session,
+ 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
+);
+
+CK_RV
+pkcs11h_getCertificate (
+ IN const pkcs11h_session_t pkcs11h_session,
+ OUT unsigned char * const certificate,
+ IN OUT size_t * const certificate_size
+);
+
+char *
+pkcs11h_getMessage (
+ IN const int rv
+);
+
+pkcs11h_openssl_session_t
+pkcs11h_openssl_createSession (
+ IN const bool fShouldPadSign
+);
+
+void
+pkcs11h_openssl_freeSession (
+ IN const pkcs11h_openssl_session_t pkcs11h_openssl_session
+);
+
+RSA *
+pkcs11h_openssl_getRSA (
+ IN const pkcs11h_openssl_session_t pkcs11h_openssl_session
+);
+
+X509 *
+pkcs11h_openssl_getX509 (
+ IN const pkcs11h_openssl_session_t pkcs11h_openssl_session
+);
+
+void
+pkcs11h_standalone_dump_slots (
+ IN const pkcs11h_output_print_t my_output,
+ IN const void *pData,
+ IN const char * const provider
+);
+
+void
+pkcs11h_standalone_dump_objects (
+ IN const pkcs11h_output_print_t my_output,
+ IN const void *pData,
+ IN const char * const provider,
+ IN const char * const slot,
+ IN const char * const pin
+);
+
+#endif
diff --git a/pkcs11.c b/pkcs11.c
index 8dd9dfe..84d663b 100644
--- a/pkcs11.c
+++ b/pkcs11.c
@@ -38,2143 +38,34 @@
#if defined(ENABLE_PKCS11)
-#include "error.h"
-#include "misc.h"
-#include "ssl.h"
-
-#if !defined(IN)
-#define IN
-#endif
-#if !defined(OUT)
-#define OUT
-#endif
-
-#if defined(WIN32)
-#include "cryptoki-win32.h"
-#else
-#include "cryptoki.h"
-#endif
+#define PKCS11H_NO_NEED_INCLUDE_CONFIG
+#include "pkcs11-helper.h"
#include "pkcs11.h"
-/*===========================================
- * MACROS
- */
-
#define snprintf openvpn_snprintf
-/*===========================================
- * Constants
- */
-
-#if OPENSSL_VERSION_NUMBER < 0x00907000L && defined(CRYPTO_LOCK_ENGINE)
-# define RSA_get_default_method RSA_get_default_openssl_method
-#else
-# ifdef HAVE_ENGINE_GET_DEFAULT_RSA
-# include <openssl/engine.h>
-# if OPENSSL_VERSION_NUMBER < 0x0090704fL
-# define BROKEN_OPENSSL_ENGINE
-# endif
-# endif
-#endif
-
-#define PKCS11_MAX_ATTRIBUTE_SIZE (10*1024)
-
-/*===========================================
- * Types
- */
-
-typedef bool (*pkcs11_hook_card_prompt_t)(
- IN const void *pData,
- IN const char * const szLabel
-);
-
-typedef bool (*pkcs11_hook_pin_prompt_t)(
- IN const void *pData,
- IN const char * const szLabel,
- OUT char * const szPIN,
- IN const size_t nMaxPIN
-);
-
-typedef struct pkcs11_hooks_s {
- void *card_prompt_data;
- void *pin_prompt_data;
- pkcs11_hook_card_prompt_t card_prompt;
- pkcs11_hook_pin_prompt_t pin_prompt;
-} *pkcs11_hooks_t;
-
-typedef struct pkcs11_provider_s {
- struct pkcs11_provider_s *next;
-
- bool fEnabled;
-
-#if defined(WIN32)
- HANDLE hLibrary;
-#else
- void *hLibrary;
-#endif
- CK_FUNCTION_LIST_PTR f;
- bool fShouldFinalize;
- char *szSignMode;
-
-} *pkcs11_provider_t;
-
-typedef struct pkcs11_session_s {
-
- pkcs11_provider_t provider;
-
- bool fProtectedAuthentication;
-
- char szLabel[sizeof (((CK_TOKEN_INFO *)NULL)->label)+1];
- CK_CHAR serialNumber[sizeof (((CK_TOKEN_INFO *)NULL)->serialNumber)];
-
- unsigned char *certificate;
- size_t certificate_size;
- unsigned char *certificate_id;
- size_t certificate_id_size;
-
- CK_SLOT_ID slot;
- bool fKeySignRecover;
-
- CK_SESSION_HANDLE session;
- CK_OBJECT_HANDLE key;
-
- time_t timePINExpire;
-} *pkcs11_session_t;
-
-typedef struct pkcs11_data_s {
- bool fInitialized;
- int nPINCachePeriod;
- pkcs11_provider_t providers;
- pkcs11_hooks_t hooks;
-} *pkcs11_data_t;
-
-/*===========================================
- * Low level prototypes
- */
-
-static
-void
-_fixupFixedString (
- IN const char * const szSource,
- OUT char * const szTarget, /* MUST BE >= nLength+1 */
- 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
-);
-static
-CK_RV
-_pkcs11_getSlotById (
- IN const pkcs11_session_t pkcs11_session,
- IN const char * const szSlot
-);
-static
-CK_RV
-_pkcs11_getSlotByName (
- IN const pkcs11_session_t pkcs11_session,
- IN const char * const szName
-);
-static
-CK_RV
-_pkcs11_getSlotByLabel (
- IN const pkcs11_session_t pkcs11_session,
- IN const char * const szLabel
-);
-static
-CK_RV
-_pkcs11_getObjectById (
- IN const pkcs11_session_t pkcs11_session,
- IN const CK_OBJECT_CLASS class,
- IN const unsigned char * const id,
- IN const size_t id_size,
- OUT CK_OBJECT_HANDLE * const handle
-);
-static
-CK_RV
-_pkcs11_setSessionTokenInfo (
- IN const pkcs11_session_t pkcs11_session
-);
-static
-CK_RV
-_pkcs11_resetSlot (
- IN const pkcs11_session_t pkcs11_session
-);
-static
-CK_RV
-_pkcs11_loadCertificate (
- IN const pkcs11_session_t pkcs11_session,
- IN const char * const szIdType,
- IN const char * const szId
-);
-static
-CK_RV
-_pkcs11_loadKeyProperties (
- IN const pkcs11_session_t pkcs11_session
-);
-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
-);
-static
-CK_RV
-_pkcs11_validateSession (
- IN const pkcs11_session_t pkcs11_session
-);
-static
-CK_RV
-_pkcs11_login (
- IN const pkcs11_session_t pkcs11_session
-);
-static
-CK_RV
-_pkcs11_logout (
- IN const pkcs11_session_t pkcs11_session
-);
-
-/*=========================================
- * Simplified functions prototypes
- */
-static
-bool
-_pkcs11_hooks_card_prompt_default (
- IN const void *pData,
- IN const char * const szLabel
-);
-static
-bool
-_pkcs11_hooks_pin_prompt_default (
+_pkcs11_openvpn_print (
IN const void *pData,
- IN const char * const szLabel,
- OUT char * const szPIN,
- IN const size_t nMaxPIN
-);
-static
-CK_RV
-pkcs11_initialize ();
-static
-CK_RV
-pkcs11_terminate ();
-static
-CK_RV
-pkcs11_setCardPromptHook (
- IN const pkcs11_hook_card_prompt_t hook,
- IN void * const pData
-);
-static
-CK_RV
-pkcs11_setPINPromptHook (
- IN const pkcs11_hook_pin_prompt_t hook,
- IN void * const pData
-);
-static
-CK_RV
-pkcs11_setPINCachePeriod (
- IN const int nPINCachePeriod
-);
-static
-CK_RV
-pkcs11_addProvider (
- IN const char * const szProvider,
- IN const char * const szSignMode
-);
-static
-CK_RV
-pkcs11_forkFixup ();
-static
-CK_RV
-pkcs11_createSession (
- IN const char * const szSlotType,
- IN const char * const szSlot,
- IN const char * const szIdType,
- IN const char * const szId,
- IN const bool fProtectedAuthentication,
- OUT pkcs11_session_t * const pkcs11_session
-);
-static
-CK_RV
-pkcs11_freeSession (
- IN const pkcs11_session_t pkcs11_session
-);
-static
-CK_RV
-pkcs11_sign (
- IN const pkcs11_session_t pkcs11_session,
- 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
-);
-static
-CK_RV
-pkcs11_signRecover (
- IN const pkcs11_session_t pkcs11_session,
- 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
-);
-static
-CK_RV
-pkcs11_decrypt (
- IN const pkcs11_session_t pkcs11_session,
- 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
-);
-static
-CK_RV
-pkcs11_getCertificate (
- IN const pkcs11_session_t pkcs11_session,
- OUT unsigned char * const certificate,
- IN OUT size_t * const certificate_size
-);
-static
-char *
-pkcs11_getMessage (
- IN const int rv
-);
-
-/*==========================================
- * Static data
- */
-
-static pkcs11_data_t pkcs11_data = NULL;
-
-/*==========================================
- * Internal utility functions
- */
-
-static
-void
-_fixupFixedString (
- IN const char * const szSource,
- OUT char * const szTarget, /* MUST BE >= nLength+1 */
- IN const size_t nLength /* FIXED STRING LENGTH */
-) {
- char *p;
-
- ASSERT (szSource!=NULL);
- ASSERT (szTarget!=NULL);
-
- p = szTarget+nLength;
- memmove (szTarget, szSource, nLength);
- *p = '\0';
- p--;
- while (p >= szTarget && *p == ' ') {
- *p = '\0';
- p--;
- }
-}
-
-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;
-
- ASSERT (szSource!=NULL);
- ASSERT (target!=NULL);
- ASSERT (target_size!=NULL);
-
- target_max_size = *target_size;
- p = szSource;
- *target_size = 0;
-
- while (*p != '\0' && *target_size < target_max_size) {
- if (isxdigit (*p)) {
- buf[i%2] = *p;
-
- if ((i%2) == 1) {
- unsigned v;
- sscanf (buf, "%x", &v);
- target[*target_size] = v & 0xff;
- (*target_size)++;
- }
-
- i++;
- }
- p++;
- }
-}
-
-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
-) {
- /*
- * 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 *x509Current = NULL, *x509New = NULL;
- char szNotBeforeCurrent[1024], szNotBeforeNew[1024];
-
- /*
- * First certificae
- * always select
- */
- if (nCurrentSize == 0) {
- return true;
- }
-
- szNotBeforeCurrent[0] = '\0';
- szNotBeforeNew[0] = '\0';
-
- x509Current = X509_new ();
- x509New = X509_new ();
-
- if (x509Current != NULL && x509New != NULL) {
- const unsigned char *p1, *p2;
-
- p1 = pCurrent;
- p2 = pNew;
- if (
- d2i_X509 (&x509Current, (unsigned char **)&p1, nCurrentSize) &&
- d2i_X509 (&x509New, (unsigned char **)&p2, nNewSize)
- ) {
- ASN1_TIME *notBeforeCurrent = X509_get_notBefore (x509Current);
- ASN1_TIME *notBeforeNew = X509_get_notBefore (x509New);
-
- if (
- notBeforeCurrent != NULL &&
- notBeforeNew != NULL &&
- notBeforeCurrent->length < (int) sizeof (szNotBeforeCurrent) - 1 &&
- notBeforeNew->length < (int) sizeof (szNotBeforeNew) - 1
- ) {
- memmove (szNotBeforeCurrent, notBeforeCurrent->data, notBeforeCurrent->length);
- szNotBeforeCurrent[notBeforeCurrent->length] = '\0';
- memmove (szNotBeforeNew, notBeforeNew->data, notBeforeNew->length);
- szNotBeforeNew[notBeforeNew->length] = '\0';
- }
- }
- }
-
- if (x509Current != NULL) {
- X509_free (x509Current);
- x509Current = NULL;
- }
- if (x509New != NULL) {
- X509_free (x509New);
- x509New = NULL;
- }
-
- return strcmp (szNotBeforeCurrent, szNotBeforeNew) < 0;
-}
-
-/*========================================
- * Low level PKCS#11 functions
- */
-
-static
-CK_RV
-_pkcs11_getSlotById (
- IN const pkcs11_session_t pkcs11_session,
- IN const char * const szSlot
-) {
- pkcs11_provider_t provider;
- int provider_number;
- int slot_number;
- int i;
-
- ASSERT (pkcs11_session!=NULL);
- ASSERT (szSlot!=NULL);
-
- if (strchr (szSlot, ':') == NULL) {
- provider_number = 0;
- slot_number = atoi (szSlot);
- }
- else {
- sscanf (szSlot, "%d:%d", &provider_number, &slot_number);
- }
-
- for (
- i=0, provider=pkcs11_data->providers;
- i < provider_number && provider != NULL;
- i++, provider = provider->next
- );
-
- if (
- provider == NULL ||
- (
- provider != NULL &&
- !provider->fEnabled
- )
- ) {
- return CKR_SLOT_ID_INVALID;
- }
-
- pkcs11_session->provider = provider;
- pkcs11_session->slot = slot_number;
- return CKR_OK;
-}
-
-static
-CK_RV
-_pkcs11_getSlotByName (
- IN const pkcs11_session_t pkcs11_session,
- IN const char * const szName
-) {
- CK_RV rv;
-
- pkcs11_provider_t provider;
- bool fFound = false;
-
- ASSERT (pkcs11_session!=NULL);
- ASSERT (szName!=NULL);
-
- for (
- provider = pkcs11_data->providers;
- (
- provider != NULL &&
- !fFound
- );
- provider = provider->next
- ) {
- CK_SLOT_ID slots[1024];
- CK_ULONG slotnum;
-
- if (!provider->fEnabled) {
- continue;
- }
-
- slotnum = sizeof (slots) / sizeof (CK_SLOT_ID);
- if (
- (rv = provider->f->C_GetSlotList (
- TRUE,
- slots,
- &slotnum
- )) == CKR_OK
- ) {
- CK_SLOT_ID s;
-
- for (s=0;!fFound && s<slotnum;s++) {
- CK_SLOT_INFO info;
-
- if (
- (rv = provider->f->C_GetSlotInfo (
- slots[s],
- &info
- )) == CKR_OK
- ) {
- char szCurrentName[sizeof (info.slotDescription)+1];
-
- _fixupFixedString (
- (char *)info.slotDescription,
- szCurrentName,
- sizeof (info.slotDescription)
- );
-
- if (!strcmp (szCurrentName, szName)) {
- fFound = true;
- pkcs11_session->provider = provider;
- pkcs11_session->slot = slots[s];
- }
- }
- }
- }
- }
-
- return fFound ? CKR_OK : CKR_SLOT_ID_INVALID;
-}
-
-static
-CK_RV
-_pkcs11_getSlotByLabel (
- IN const pkcs11_session_t pkcs11_session,
- IN const char * const szLabel
-) {
- CK_RV rv;
-
- pkcs11_provider_t provider;
- bool fFound = false;
-
- ASSERT (pkcs11_session!=NULL);
- ASSERT (szLabel!=NULL);
-
- for (
- provider = pkcs11_data->providers;
- (
- provider != NULL &&
- !fFound
- );
- provider = provider->next
- ) {
- CK_SLOT_ID slots[1024];
- CK_ULONG slotnum;
-
- if (!provider->fEnabled) {
- continue;
- }
-
- slotnum = sizeof (slots) / sizeof (CK_SLOT_ID);
- if (
- (rv = provider->f->C_GetSlotList (
- TRUE,
- slots,
- &slotnum
- )) == CKR_OK
- ) {
- CK_SLOT_ID s;
-
- for (s=0;!fFound && s<slotnum;s++) {
- CK_TOKEN_INFO info;
-
- if (
- (rv = provider->f->C_GetTokenInfo (
- slots[s],
- &info
- )) == CKR_OK
- ) {
- char szCurrentLabel[sizeof (info.label)+1];
-
- _fixupFixedString (
- (char *)info.label,
- szCurrentLabel,
- sizeof (info.label)
- );
-
- if (!strcmp (szCurrentLabel, szLabel)) {
- fFound = true;
- pkcs11_session->provider = provider;
- pkcs11_session->slot = slots[s];
- }
- }
- }
- }
- }
-
- return fFound ? CKR_OK : CKR_SLOT_ID_INVALID;
-}
-
-static
-CK_RV
-_pkcs11_setSessionTokenInfo (
- IN const pkcs11_session_t pkcs11_session
-) {
- CK_TOKEN_INFO info;
- CK_RV rv;
-
- ASSERT (pkcs11_session!=NULL);
-
- if (
- (rv = pkcs11_session->provider->f->C_GetTokenInfo (
- pkcs11_session->slot,
- &info
- )) == CKR_OK
- ) {
- _fixupFixedString (
- (char *)info.label,
- pkcs11_session->szLabel,
- sizeof (info.label)
- );
-
- memmove (
- pkcs11_session->serialNumber,
- info.serialNumber,
- sizeof (pkcs11_session->serialNumber)
- );
- }
-
- return rv;
-}
-
-static
-CK_RV
-_pkcs11_resetSlot (
- IN const pkcs11_session_t pkcs11_session
-) {
- CK_SLOT_ID slots[1024];
- CK_ULONG slotnum;
- CK_RV rv;
- bool fFound = false;
- bool fCancel = false;
-
- ASSERT (pkcs11_session!=NULL);
-
- do {
- slotnum = sizeof (slots) / sizeof (CK_SLOT_ID);
- if (
- (rv = pkcs11_session->provider->f->C_GetSlotList (
- TRUE,
- slots,
- &slotnum
- )) == CKR_OK
- ) {
- CK_SLOT_ID s;
-
- for (s=0;!fFound && s<slotnum;s++) {
- CK_TOKEN_INFO info;
-
- if (
- (rv = pkcs11_session->provider->f->C_GetTokenInfo (
- slots[s],
- &info
- )) == CKR_OK
- ) {
- if (
- !memcmp (
- pkcs11_session->serialNumber,
- info.serialNumber,
- sizeof (pkcs11_session->serialNumber)
- )
- ) {
- pkcs11_session->slot = slots[s];
- fFound = true;
- }
- }
- }
- }
-
- if (!fFound) {
- fCancel = !pkcs11_data->hooks->card_prompt (
- pkcs11_data->hooks->card_prompt_data,
- pkcs11_session->szLabel
- );
- }
- } while (!fFound && !fCancel);
-
- return fFound ? CKR_OK : CKR_SLOT_ID_INVALID;
-}
-
-static
-CK_RV
-_pkcs11_getObjectById (
- IN const pkcs11_session_t pkcs11_session,
- IN const CK_OBJECT_CLASS class,
- IN const unsigned char * const id,
- IN const size_t id_size,
- OUT CK_OBJECT_HANDLE * const handle
-) {
- CK_ULONG count;
- CK_RV rv = CKR_OK;
-
- CK_ATTRIBUTE filter[] = {
- {CKA_CLASS, (void *)&class, sizeof (class)},
- {CKA_ID, (void *)id, id_size}
- };
-
- ASSERT (pkcs11_session!=NULL);
- ASSERT (id!=NULL);
- ASSERT (handle!=NULL);
-
- if (rv == CKR_OK) {
- rv = pkcs11_session->provider->f->C_FindObjectsInit (
- pkcs11_session->session,
- filter,
- sizeof (filter) / sizeof (CK_ATTRIBUTE)
- );
- }
-
- if (rv == CKR_OK) {
- rv = pkcs11_session->provider->f->C_FindObjects (
- pkcs11_session->session,
- handle,
- 1,
- &count
- );
- }
-
- if (
- rv == CKR_OK &&
- count == 0
- ) {
- rv = CKR_FUNCTION_REJECTED;
- }
-
- pkcs11_session->provider->f->C_FindObjectsFinal (
- pkcs11_session->session
- );
-
- return rv;
-}
-
-static
-CK_RV
-_pkcs11_loadCertificate (
- IN const pkcs11_session_t pkcs11_session,
- IN const char * const szIdType,
- IN const char * const szId
-) {
- CK_OBJECT_HANDLE objects[10];
- CK_ULONG objects_found;
- CK_RV rv;
-
- unsigned char selected_id[PKCS11_MAX_ATTRIBUTE_SIZE];
- int selected_id_size = 0;
- unsigned char selected_certificate[PKCS11_MAX_ATTRIBUTE_SIZE];
- int selected_certificate_size = 0;
-
- CK_OBJECT_CLASS cert_filter_class = CKO_CERTIFICATE;
- unsigned char cert_filter_by[PKCS11_MAX_ATTRIBUTE_SIZE];
- CK_ATTRIBUTE cert_filter[] = {
- {CKA_CLASS, &cert_filter_class, sizeof (cert_filter_class)},
- {0, cert_filter_by, 0}
- };
-
- ASSERT (pkcs11_session!=NULL);
- ASSERT (szIdType!=NULL);
- ASSERT (szId!=NULL);
-
- 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
- );
- }
- else if (!strcmp (szIdType, "id")) {
- size_t s = sizeof (cert_filter_by);
-
- cert_filter[1].type = CKA_ID;
- _hexToBinary (
- szId,
- cert_filter_by,
- &s
- );
- cert_filter[1].ulValueLen = s;
- }
- else if (!strcmp (szIdType, "subject")) {
- memmove (&cert_filter[1], &cert_filter[0], sizeof (CK_ATTRIBUTE));
- }
- else {
- return CKR_ARGUMENTS_BAD;
- }
-
- if (
- (rv = pkcs11_session->provider->f->C_FindObjectsInit (
- pkcs11_session->session,
- cert_filter,
- sizeof (cert_filter) / sizeof (CK_ATTRIBUTE)
- )) != CKR_OK
- ) {
- return rv;
- }
-
- while (
- (rv = pkcs11_session->provider->f->C_FindObjects (
- pkcs11_session->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++) {
- unsigned char attrs_id[PKCS11_MAX_ATTRIBUTE_SIZE];
- unsigned char attrs_value[PKCS11_MAX_ATTRIBUTE_SIZE];
- CK_ATTRIBUTE attrs[] = {
- {CKA_ID, attrs_id, sizeof (attrs_id)},
- {CKA_VALUE, attrs_value, sizeof (attrs_value)}
- };
-
- if (
- pkcs11_session->provider->f->C_GetAttributeValue (
- pkcs11_session->session,
- objects[i],
- attrs,
- sizeof (attrs) / sizeof (CK_ATTRIBUTE)
- ) == CKR_OK
- ) {
- bool fSelected = false;
-
- if (!strcmp (szIdType, "subject")) {
- X509 *x509 = NULL;
- char szSubject[1024];
- unsigned char *p;
-
- x509 = X509_new ();
-
- p = attrs_value;
- if (d2i_X509 (&x509, &p, 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 (!strcmp (szId, szSubject)) {
- fSelected = true;
- }
- }
- else {
- fSelected = true;
- }
-
- 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
- );
- }
- }
- }
- }
-
- pkcs11_session->provider->f->C_FindObjectsFinal (
- pkcs11_session->session
- );
-
- if (selected_certificate_size == 0) {
- return CKR_ATTRIBUTE_VALUE_INVALID;
- }
-
- if ((pkcs11_session->certificate = (unsigned char *)malloc (selected_certificate_size)) == NULL) {
- return CKR_HOST_MEMORY;
- }
- pkcs11_session->certificate_size = selected_certificate_size;
- memmove (
- pkcs11_session->certificate,
- selected_certificate,
- selected_certificate_size
- );
- if ((pkcs11_session->certificate_id = (unsigned char *)malloc (selected_id_size)) == NULL) {
- return CKR_HOST_MEMORY;
- }
- pkcs11_session->certificate_id_size = selected_id_size;
- memmove (
- pkcs11_session->certificate_id,
- selected_id,
- selected_id_size
- );
-
- return CKR_OK;
-}
-
-static
-CK_RV
-_pkcs11_loadKeyProperties (
- IN const pkcs11_session_t pkcs11_session
-) {
- CK_OBJECT_HANDLE key;
- CK_RV rv;
-
- 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)}
- };
-
- ASSERT (pkcs11_session!=NULL);
-
- if (!strcmp (pkcs11_session->provider->szSignMode, "recover")) {
- pkcs11_session->fKeySignRecover = true;
- }
- else if (!strcmp (pkcs11_session->provider->szSignMode, "sign")) {
- pkcs11_session->fKeySignRecover = false;
- }
- else {
- if (
- (rv = _pkcs11_getObjectById (
- pkcs11_session,
- CKO_PRIVATE_KEY,
- pkcs11_session->certificate_id,
- pkcs11_session->certificate_id_size,
- &key
- )) != CKR_OK
- ) {
- return rv;
- }
-
- if (
- pkcs11_session->provider->f->C_GetAttributeValue (
- pkcs11_session->session,
- key,
- key_attrs,
- sizeof (key_attrs) / sizeof (CK_ATTRIBUTE)
- ) == CKR_OK
- ) {
- if (key_attrs_sign_recover != CK_FALSE) {
- pkcs11_session->fKeySignRecover = true;
- }
- else if (key_attrs_sign != CK_FALSE) {
- pkcs11_session->fKeySignRecover = false;
- }
- else {
- return CKR_KEY_TYPE_INCONSISTENT;
- }
- }
-
- }
-
- return CKR_OK;
-}
-
-static
-CK_RV
-_pkcs11_validateSession (
- IN const pkcs11_session_t pkcs11_session
-) {
- if (
- pkcs11_session->timePINExpire != (time_t)0 &&
- pkcs11_session->timePINExpire < time (NULL)
- ) {
- _pkcs11_logout (pkcs11_session);
- }
- return CKR_OK;
-}
-
-static
-CK_RV
-_pkcs11_login (
- IN const pkcs11_session_t pkcs11_session
-) {
- CK_RV rv = CKR_OK;
-
-
- ASSERT (pkcs11_session!=NULL);
-
- _pkcs11_logout (pkcs11_session);
-
- if (rv == CKR_OK) {
- rv = _pkcs11_resetSlot (pkcs11_session);
- }
-
- if (rv == CKR_OK) {
- rv = pkcs11_session->provider->f->C_OpenSession (
- pkcs11_session->slot,
- CKF_SERIAL_SESSION,
- NULL_PTR,
- NULL_PTR,
- &pkcs11_session->session
- );
- }
-
- if (rv == CKR_OK) {
- int nRetryCount = 0;
- do {
- CK_UTF8CHAR_PTR utfPIN = NULL;
- CK_ULONG lPINLength = 0;
- char szPIN[1024];
-
- /*
- * Assume OK for next iteration
- */
- rv = CKR_OK;
-
- if (
- rv == CKR_OK &&
- !pkcs11_session->fProtectedAuthentication
- ) {
- if (
- !pkcs11_data->hooks->pin_prompt (
- pkcs11_data->hooks->pin_prompt_data,
- pkcs11_session->szLabel,
- szPIN,
- sizeof (szPIN)
- )
- ) {
- rv = CKR_FUNCTION_FAILED;
- }
- else {
- utfPIN = (CK_UTF8CHAR_PTR)szPIN;
- lPINLength = strlen (szPIN);
- }
- }
-
- if (pkcs11_data->nPINCachePeriod == -1) {
- pkcs11_session->timePINExpire = 0;
- }
- else {
- pkcs11_session->timePINExpire = (
- time (NULL) +
- (time_t)pkcs11_data->nPINCachePeriod
- );
- }
- if (
- rv == CKR_OK &&
- (rv = pkcs11_session->provider->f->C_Login (
- pkcs11_session->session,
- CKU_USER,
- utfPIN,
- lPINLength
- )) != CKR_OK
- ) {
- if (rv == CKR_USER_ALREADY_LOGGED_IN) {
- rv = CKR_OK;
- }
- }
-
- /*
- * Clean PIN buffer
- */
- memset (szPIN, 0, sizeof (szPIN));
- } while (
- ++nRetryCount < 3 &&
- (
- rv == CKR_PIN_INCORRECT ||
- rv == CKR_PIN_INVALID
- )
- );
- }
-
- if (
- rv == CKR_OK &&
- pkcs11_session->certificate_id != NULL
- ) {
- rv = _pkcs11_getObjectById (
- pkcs11_session,
- CKO_PRIVATE_KEY,
- pkcs11_session->certificate_id,
- pkcs11_session->certificate_id_size,
- &pkcs11_session->key
- );
- }
-
- return rv;
-}
-
-static
-CK_RV
-_pkcs11_logout (
- IN const pkcs11_session_t pkcs11_session
-) {
- ASSERT (pkcs11_session!=NULL);
-
- if (pkcs11_session->session != (CK_SESSION_HANDLE)-1) {
- pkcs11_session->provider->f->C_Logout (pkcs11_session->session);
- pkcs11_session->provider->f->C_CloseSession (pkcs11_session->session);
- pkcs11_session->key = (CK_OBJECT_HANDLE)-1;
- pkcs11_session->session = (CK_SESSION_HANDLE)-1;
- }
-
- return CKR_OK;
-}
-
-
-/*=======================================
- * Simplified PKCS#11 functions
- */
-
-static
-bool
-_pkcs11_hooks_card_prompt_default (
- IN const void * pData,
- IN const char * const szLabel
-) {
- return false;
-}
-
-static
-bool
-_pkcs11_hooks_pin_prompt_default (
- IN const void * pData,
- IN const char * const szLabel,
- OUT char * const szPIN,
- IN const size_t nMaxPIN
-) {
- return false;
-}
-
-static
-CK_RV
-pkcs11_initialize () {
-
- pkcs11_terminate ();
-
- pkcs11_data = (pkcs11_data_t)malloc (sizeof (struct pkcs11_data_s));
- if (pkcs11_data == NULL) {
- return CKR_HOST_MEMORY;
- }
-
- memset (pkcs11_data, 0, sizeof (struct pkcs11_data_s));
-
- pkcs11_data->nPINCachePeriod = -1;
-
- pkcs11_data->hooks = (pkcs11_hooks_t)malloc (sizeof (struct pkcs11_hooks_s));
- if (pkcs11_data->hooks == NULL) {
- return CKR_HOST_MEMORY;
- }
-
- memset (pkcs11_data->hooks, 0, sizeof (struct pkcs11_hooks_s));
-
- pkcs11_data->fInitialized = true;
-
- pkcs11_setCardPromptHook (_pkcs11_hooks_card_prompt_default, NULL);
- pkcs11_setPINPromptHook (_pkcs11_hooks_pin_prompt_default, NULL);
-
- return CKR_OK;
-}
-
-static
-CK_RV
-pkcs11_terminate () {
-
- if (pkcs11_data != NULL) {
- pkcs11_provider_t last = NULL;
-
- for (
- ;
- pkcs11_data->providers != NULL;
- pkcs11_data->providers = pkcs11_data->providers->next
- ) {
- if (last != NULL) {
- free (last);
- }
- last = pkcs11_data->providers;
-
- if (pkcs11_data->providers->szSignMode != NULL) {
- free (pkcs11_data->providers->szSignMode);
- pkcs11_data->providers->szSignMode = NULL;
- }
-
- if (pkcs11_data->providers->fShouldFinalize) {
- pkcs11_data->providers->f->C_Finalize (NULL);
- pkcs11_data->providers->fShouldFinalize = false;
- }
-
- if (pkcs11_data->providers->f != NULL) {
- pkcs11_data->providers->f = NULL;
- }
-
- if (pkcs11_data->providers->hLibrary != NULL) {
-#if defined(WIN32)
- FreeLibrary (pkcs11_data->providers->hLibrary);
-#else
- dlclose (pkcs11_data->providers->hLibrary);
-#endif
- pkcs11_data->providers->hLibrary = NULL;
- }
- }
-
- if (last != NULL) {
- free (last);
- }
-
- if (pkcs11_data->hooks != NULL) {
- free (pkcs11_data->hooks);
- pkcs11_data->hooks = NULL;
- }
-
- free (pkcs11_data);
- pkcs11_data = NULL;
- }
-
- return CKR_OK;
-}
-
-static
-CK_RV
-pkcs11_setPINPromptHook (
- IN const pkcs11_hook_pin_prompt_t hook,
- IN void * const pData
-) {
- ASSERT (pkcs11_data!=NULL);
- ASSERT (pkcs11_data->fInitialized);
-
- pkcs11_data->hooks->pin_prompt = hook;
- pkcs11_data->hooks->pin_prompt_data = pData;
-
- return CKR_OK;
-}
-
-static
-CK_RV
-pkcs11_setCardPromptHook (
- IN const pkcs11_hook_card_prompt_t hook,
- IN void * const pData
-) {
- ASSERT (pkcs11_data!=NULL);
- ASSERT (pkcs11_data->fInitialized);
-
- pkcs11_data->hooks->card_prompt = hook;
- pkcs11_data->hooks->card_prompt_data = pData;
-
- return CKR_OK;
-}
-
-static
-CK_RV
-pkcs11_setPINCachePeriod (
- IN const int nPINCachePeriod
-) {
- ASSERT (pkcs11_data!=NULL);
- ASSERT (pkcs11_data->fInitialized);
-
- pkcs11_data->nPINCachePeriod = nPINCachePeriod;
-
- return CKR_OK;
-}
-
-static
-CK_RV
-pkcs11_addProvider (
- IN const char * const szProvider,
- IN const char * const szSignMode
-) {
- pkcs11_provider_t provider = NULL;
- CK_C_GetFunctionList gfl = NULL;
- CK_RV rv = CKR_OK;
-
- ASSERT (pkcs11_data!=NULL);
- ASSERT (pkcs11_data->fInitialized);
- ASSERT (szProvider!=NULL);
-
- if (
- rv == CKR_OK &&
- (provider = (pkcs11_provider_t)malloc (sizeof (struct pkcs11_provider_s))) == NULL
- ) {
- rv = CKR_HOST_MEMORY;
- }
-
- if (rv == CKR_OK) {
- memset (provider, 0, sizeof (struct pkcs11_provider_s));
- if (szSignMode == NULL) {
- provider->szSignMode = strdup ("auto");
- }
- else {
- provider->szSignMode = strdup (szSignMode);
- }
- if (provider->szSignMode == NULL) {
- rv = CKR_HOST_MEMORY;
- }
- }
-
- 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 (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) {
- rv = gfl (&provider->f);
- }
-
- 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) {
- provider->fEnabled = true;
- }
-
- if (provider != NULL) {
- if (pkcs11_data->providers == NULL) {
- pkcs11_data->providers = provider;
- }
- else {
- pkcs11_provider_t last = NULL;
-
- for (
- last = pkcs11_data->providers;
- last->next != NULL;
- last = last->next
- );
- last->next = provider;
- }
- }
-
- return rv;
-}
-
-static
-CK_RV
-pkcs11_forkFixup () {
-
- if (pkcs11_data != NULL && pkcs11_data->fInitialized) {
-
- pkcs11_provider_t current;
-
- for (
- current = pkcs11_data->providers;
- current != NULL;
- current = current->next
- ) {
- if (current->fEnabled) {
- current->f->C_Initialize (NULL);
- }
- }
- }
-
- return CKR_OK;
-}
-
-static
-CK_RV
-pkcs11_createSession (
- IN const char * const szSlotType,
- IN const char * const szSlot,
- IN const char * const szIdType,
- IN const char * const szId,
- IN const bool fProtectedAuthentication,
- OUT pkcs11_session_t * const p_pkcs11_session
+ IN const char * const szFormat,
+ IN ...
) {
- pkcs11_session_t pkcs11_session;
- CK_RV rv = CKR_OK;
-
- ASSERT (pkcs11_data!=NULL);
- ASSERT (pkcs11_data->fInitialized);
- ASSERT (szSlotType!=NULL);
- ASSERT (szSlot!=NULL);
- ASSERT (szIdType!=NULL);
- ASSERT (szId!=NULL);
- ASSERT (p_pkcs11_session!=NULL);
-
- if (
- rv == CKR_OK &&
- (pkcs11_session = (pkcs11_session_t)malloc (sizeof (struct pkcs11_session_s))) == NULL
- ) {
- rv = CKR_HOST_MEMORY;
- }
-
- if (rv == CKR_OK) {
- *p_pkcs11_session = pkcs11_session;
- memset (pkcs11_session, 0, sizeof (struct pkcs11_session_s));
- }
-
- if (rv == CKR_OK) {
- pkcs11_session->key = (CK_OBJECT_HANDLE)-1;
- pkcs11_session->session = (CK_SESSION_HANDLE)-1;
- pkcs11_session->fProtectedAuthentication = fProtectedAuthentication;
- }
-
- if (rv == CKR_OK) {
- bool fCancel = false;
-
- do {
- if (!strcmp (szSlotType, "id")) {
- rv = _pkcs11_getSlotById (pkcs11_session, szSlot);
- }
- else if (!strcmp (szSlotType, "name")) {
- rv = _pkcs11_getSlotByName (pkcs11_session, szSlot);
- }
- else if (!strcmp (szSlotType, "label")) {
- rv = _pkcs11_getSlotByLabel (pkcs11_session, szSlot);
- }
- else {
- rv = CKR_ARGUMENTS_BAD;
- }
-
- if (rv == CKR_SLOT_ID_INVALID) {
- char szLabel[1024];
- snprintf (szLabel, sizeof (szLabel), "SLOT(%s=%s)", szSlotType, szSlot);
- fCancel = !pkcs11_data->hooks->card_prompt (
- pkcs11_data->hooks->card_prompt_data,
- szLabel
- );
- }
- } while (rv == CKR_SLOT_ID_INVALID && !fCancel);
- }
-
- if (rv == CKR_OK) {
- rv = _pkcs11_setSessionTokenInfo (pkcs11_session);
- }
-
- if (rv == CKR_OK) {
- rv = _pkcs11_login (
- pkcs11_session
- );
- }
-
- if (rv == CKR_OK) {
- rv = _pkcs11_loadCertificate (
- pkcs11_session,
- szIdType,
- szId
- );
- }
-
- if (rv == CKR_OK) {
- rv = _pkcs11_loadKeyProperties (
- pkcs11_session
- );
- }
-
- /*
- * Complete missing login process
- */
- if (rv == CKR_OK) {
- rv = _pkcs11_getObjectById (
- pkcs11_session,
- CKO_PRIVATE_KEY,
- pkcs11_session->certificate_id,
- pkcs11_session->certificate_id_size,
- &pkcs11_session->key
- );
- }
-
- return rv;
-}
-
-CK_RV
-pkcs11_freeSession (
- IN const pkcs11_session_t pkcs11_session
-) {
- ASSERT (pkcs11_data!=NULL);
- ASSERT (pkcs11_data->fInitialized);
-
- if (pkcs11_session != NULL) {
- _pkcs11_logout (pkcs11_session);
-
- if (pkcs11_session->certificate != NULL) {
- free (pkcs11_session->certificate);
- }
- if (pkcs11_session->certificate_id != NULL) {
- free (pkcs11_session->certificate_id);
- }
-
- free (pkcs11_session);
- }
-
- return CKR_OK;
-}
-
-static
-CK_RV
-pkcs11_sign (
- IN const pkcs11_session_t pkcs11_session,
- 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
-) {
- CK_MECHANISM mech = {
- mech_type, NULL, 0
- };
- CK_RV rv = CKR_OK;
- bool fLogonRetry = false;
- bool fOpSuccess = false;
-
- ASSERT (pkcs11_data!=NULL);
- ASSERT (pkcs11_data->fInitialized);
- ASSERT (pkcs11_session!=NULL);
- ASSERT (source!=NULL);
- ASSERT (target_size!=NULL);
-
- rv = _pkcs11_validateSession (pkcs11_session);
-
- while (rv == CKR_OK && !fOpSuccess) {
- rv = pkcs11_session->provider->f->C_SignInit (
- pkcs11_session->session,
- &mech,
- pkcs11_session->key
- );
-
- if (rv == CKR_OK) {
- fOpSuccess = true;
- }
- else {
- if (!fLogonRetry) {
- fLogonRetry = true;
- rv = _pkcs11_login (pkcs11_session);
- }
- }
- }
-
- if (rv == CKR_OK) {
- CK_ULONG size = *target_size;
- rv = pkcs11_session->provider->f->C_Sign (
- pkcs11_session->session,
- (CK_BYTE_PTR)source,
- source_size,
- (CK_BYTE_PTR)target,
- &size
- );
-
- *target_size = (int)size;
- }
-
- return rv;
-}
-
-static
-CK_RV
-pkcs11_signRecover (
- IN const pkcs11_session_t pkcs11_session,
- 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
-) {
- CK_MECHANISM mech = {
- mech_type, NULL, 0
- };
- CK_RV rv = CKR_OK;
- bool fLogonRetry = false;
- bool fOpSuccess = false;
-
- ASSERT (pkcs11_data!=NULL);
- ASSERT (pkcs11_data->fInitialized);
- ASSERT (pkcs11_session!=NULL);
- ASSERT (source!=NULL);
- ASSERT (target_size!=NULL);
-
- rv = _pkcs11_validateSession (pkcs11_session);
-
- while (rv == CKR_OK && !fOpSuccess) {
- rv = pkcs11_session->provider->f->C_SignRecoverInit (
- pkcs11_session->session,
- &mech,
- pkcs11_session->key
- );
-
- if (rv == CKR_OK) {
- fOpSuccess = true;
- }
- else {
- if (!fLogonRetry) {
- fLogonRetry = true;
- rv = _pkcs11_login (pkcs11_session);
- }
- }
- }
-
- if (rv == CKR_OK) {
- CK_ULONG size = *target_size;
- rv = pkcs11_session->provider->f->C_SignRecover (
- pkcs11_session->session,
- (CK_BYTE_PTR)source,
- source_size,
- (CK_BYTE_PTR)target,
- &size
- );
-
- *target_size = (int)size;
- }
-
- return rv;
-}
-
-static
-CK_RV
-pkcs11_decrypt (
- IN const pkcs11_session_t pkcs11_session,
- 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
-) {
- CK_MECHANISM mech = {
- mech_type, NULL, 0
- };
- CK_ULONG size;
- CK_RV rv = CKR_OK;
- bool fLogonRetry = false;
- bool fOpSuccess = false;
-
- ASSERT (pkcs11_data!=NULL);
- ASSERT (pkcs11_data->fInitialized);
- ASSERT (pkcs11_session!=NULL);
- ASSERT (source!=NULL);
- ASSERT (target_size!=NULL);
-
- rv = _pkcs11_validateSession (pkcs11_session);
-
- while (rv == CKR_OK && !fOpSuccess) {
- rv = pkcs11_session->provider->f->C_DecryptInit (
- pkcs11_session->session,
- &mech,
- pkcs11_session->key
- );
-
- if (rv == CKR_OK) {
- fOpSuccess = true;
- }
- else {
- if (!fLogonRetry) {
- fLogonRetry = true;
- rv = _pkcs11_login (pkcs11_session);
- }
- }
- }
-
- if (rv == CKR_OK) {
- size = *target_size;
- rv = pkcs11_session->provider->f->C_Decrypt (
- pkcs11_session->session,
- (CK_BYTE_PTR)source,
- source_size,
- (CK_BYTE_PTR)target,
- &size
- );
-
- *target_size = (int)size;
- }
-
- return rv;
-}
-
-static
-CK_RV
-pkcs11_getCertificate (
- IN const pkcs11_session_t pkcs11_session,
- OUT unsigned char * const certificate,
- IN OUT size_t * const certificate_size
-) {
- ASSERT (pkcs11_data!=NULL);
- ASSERT (pkcs11_data->fInitialized);
- ASSERT (certificate_size!=NULL);
-
- *certificate_size = pkcs11_session->certificate_size;
-
- if (certificate == NULL) {
- return CKR_OK;
- }
-
- if (*certificate_size > pkcs11_session->certificate_size) {
- return CKR_BUFFER_TOO_SMALL;
- }
-
- memmove (certificate, pkcs11_session->certificate, *certificate_size);
-
- return CKR_OK;
-}
-
-static
-char *
-pkcs11_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";
- }
-}
-
-/*==========================================
- * openssl interface
- */
-
-typedef struct openssl_session_s {
- RSA_METHOD smart_rsa;
- int (*orig_finish)(RSA *rsa);
- pkcs11_session_t pkcs11_session;
-} *openssl_session_t;
-
-static
-pkcs11_session_t
-_openssl_get_pkcs11_session (const RSA *rsa) {
- openssl_session_t session;
-
- ASSERT (rsa!=NULL);
- session = (openssl_session_t)RSA_get_app_data (rsa);
- ASSERT (session!=NULL);
- ASSERT (session->pkcs11_session!=NULL);
-
- return session->pkcs11_session;
-}
-
-static
-int
-openssl_pkcs11_priv_enc (
- int flen,
- const unsigned char *from,
- unsigned char *to,
- RSA *rsa,
- int padding
-) {
- msg(M_WARN, "PKCS#11: Private key encryption not supported");
- return -1;
-}
-
-static
-int
-openssl_pkcs11_priv_dec (
- int flen, const unsigned char *from,
- unsigned char *to,
- RSA *rsa,
- int padding
-) {
- pkcs11_session_t pkcs11_session = _openssl_get_pkcs11_session (rsa);
- CK_RV rv = CKR_OK;
-
- msg (
- D_PKCS11_DEBUG,
- "PKCS#11: openssl_pkcs11_priv_dec entered - flen=%d, from=%p, to=%p, rsa=%p, padding=%d",
- flen,
- from,
- to,
- (void *)rsa,
- padding
- );
-
- ASSERT (from!=NULL);
- ASSERT (to!=NULL);
-
- msg (
- D_SHOW_PKCS11,
- "PKCS#11: Performing decryption using private key"
- );
-
- if (padding != RSA_PKCS1_PADDING) {
- rv = CKR_ARGUMENTS_BAD;
- }
-
- if (
- rv == CKR_OK &&
- (rv = pkcs11_decrypt (
- pkcs11_session,
- CKM_RSA_PKCS,
- from,
- flen,
- to,
- (size_t *)&flen
- )) != CKR_OK
- ) {
- msg (M_WARN, "PKCS#11: Cannot decrypt using private key %ld:'%s'", rv, pkcs11_getMessage (rv));
- }
-
- msg (
- D_PKCS11_DEBUG,
- "PKCS#11: openssl_pkcs11_priv_dec - return rv=%ld",
- rv
- );
-
- return rv == CKR_OK ? 1 : -1;
-}
-
-static
-int
-openssl_pkcs11_sign (
- int type,
- const unsigned char *m,
- unsigned int m_len,
- unsigned char *sigret,
- unsigned int *siglen,
- const RSA *rsa
-) {
- pkcs11_session_t pkcs11_session = _openssl_get_pkcs11_session (rsa);
- CK_RV rv = CKR_OK;
-
- msg (
- D_PKCS11_DEBUG,
- "PKCS#11: openssl_pkcs11_priv_sign entered - type=%d, m=%p, m_len=%u, signret=%p, signlen=%p, rsa=%p",
- type,
- m,
- m_len,
- sigret,
- (void *)siglen,
- (void *)rsa
- );
-
- ASSERT (m!=NULL);
- ASSERT (siglen!=NULL);
-
- msg (
- D_SHOW_PKCS11,
- "PKCS#11: Performing signature"
- );
-
- *siglen = RSA_size(rsa);
-
- if (pkcs11_session->fKeySignRecover) {
- if (
- (rv = pkcs11_signRecover (
- pkcs11_session,
- CKM_RSA_PKCS,
- m,
- m_len,
- sigret,
- siglen
- )) != CKR_OK
- ) {
- msg (M_WARN, "PKCS#11: Cannot perform signature-recover %ld:'%s'", rv, pkcs11_getMessage (rv));
- }
- }
- else {
- if (
- (rv = pkcs11_sign (
- pkcs11_session,
- CKM_RSA_PKCS,
- m,
- m_len,
- sigret,
- siglen
- )) != CKR_OK
- ) {
- msg (M_WARN, "PKCS#11: Cannot perform signature %ld:'%s'", rv, pkcs11_getMessage (rv));
- }
- }
-
- msg (
- D_PKCS11_DEBUG,
- "PKCS#11: openssl_pkcs11_priv_sign - return rv=%ld",
- rv
- );
-
- return rv == CKR_OK ? 1 : -1;
-}
-
-static
-int
-openssl_pkcs11_finish(RSA *rsa) {
- pkcs11_session_t pkcs11_session = _openssl_get_pkcs11_session (rsa);
- openssl_session_t openssl_session;
-
- msg (
- D_PKCS11_DEBUG,
- "PKCS#11: openssl_pkcs11_finish - entered rsa=%p",
- (void *)rsa
- );
-
- openssl_session = (openssl_session_t)RSA_get_app_data (rsa);
-
- RSA_set_app_data (rsa, NULL);
- pkcs11_freeSession (pkcs11_session);
-
- if (openssl_session->orig_finish != NULL) {
- openssl_session->orig_finish (rsa);
-
-#ifdef BROKEN_OPENSSL_ENGINE
- {
- /* We get called TWICE here, once for
- * releasing the key and also for
- * releasing the engine.
- * To prevent endless recursion, FIRST
- * clear rsa->engine, THEN call engine->finish
- */
- ENGINE *e = rsa->engine;
- rsa->engine = NULL;
- if (e) {
- ENGINE_finish(e);
- }
- }
-#endif
- }
-
- free (openssl_session);
-
- msg (
- D_PKCS11_DEBUG,
- "PKCS#11: openssl_pkcs11_finish - return"
- );
+ char Buffer[10*1024];
+ va_list args;
- return 1;
-}
-
-void
-openssl_pkcs11_set_rsa(const openssl_session_t openssl_session, RSA *rsa)
-{
- const RSA_METHOD *def = RSA_get_default_method();
-
- ASSERT (openssl_session!=NULL);
- ASSERT (rsa!=NULL);
-
- 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_enc = openssl_pkcs11_priv_enc;
- openssl_session->smart_rsa.rsa_priv_dec = openssl_pkcs11_priv_dec;
- openssl_session->smart_rsa.rsa_sign = openssl_pkcs11_sign;
- openssl_session->smart_rsa.finish = openssl_pkcs11_finish;
- openssl_session->smart_rsa.flags = RSA_METHOD_FLAG_NO_CHECK | RSA_FLAG_EXT_PKEY;
-
- RSA_set_method (rsa, &openssl_session->smart_rsa);
- RSA_set_app_data (rsa, openssl_session);
+ va_start (args, szFormat);
+ vsnprintf (Buffer, sizeof (Buffer), szFormat, args);
+ va_end (args);
+ Buffer[sizeof (Buffer)-1] = 0;
-#ifdef BROKEN_OPENSSL_ENGINE
- if (fOK) {
- if (!rsa->engine)
- rsa->engine = ENGINE_get_default_RSA();
-
- ENGINE_set_RSA(ENGINE_get_default_RSA(), openssl_session->smart_rsa);
- msg(M_WARN, "PKCS#11: OpenSSL engine support is broken! Workaround enabled");
- }
-#endif
-}
-
-
-#ifdef BROKEN_OPENSSL_ENGINE
-static void broken_openssl_init() __attribute__ ((constructor));
-static void broken_openssl_init()
-{
- SSL_library_init();
- ENGINE_load_openssl();
- ENGINE_register_all_RSA();
+ msg (M_INFO|M_NOPREFIX|M_NOLF, "%s", Buffer);
}
-#endif
-
-/*==========================================
- * openvpn interface
- */
static
bool
-_openvpn_pkcs11_card_prompt (
+_pkcs11_openvpn_card_prompt (
IN const void *pData,
IN const char * const szLabel
) {
@@ -2184,11 +75,11 @@ _openvpn_pkcs11_card_prompt (
ASSERT (szLabel!=NULL);
- openvpn_snprintf (szPrompt, sizeof (szPrompt), "INSERT");
+ openvpn_snprintf (szPrompt, sizeof (szPrompt), "Please insert %s token", szLabel);
token_pass.defined = false;
token_pass.nocache = true;
- get_user_pass (&token_pass, NULL, true, szPrompt, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE);
+ get_user_pass (&token_pass, NULL, szPrompt, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_NEED_OK);
strncpynt (szTemp, token_pass.password, sizeof (szTemp));
purge_user_pass (&token_pass, true);
@@ -2202,7 +93,7 @@ _openvpn_pkcs11_card_prompt (
static
bool
-_openvpn_pkcs11_pin_prompt (
+_pkcs11_openvpn_pin_prompt (
IN const void *pData,
IN const char * const szLabel,
OUT char * const szPIN,
@@ -2217,7 +108,7 @@ _openvpn_pkcs11_pin_prompt (
token_pass.defined = false;
token_pass.nocache = true;
- get_user_pass (&token_pass, NULL, true, szPrompt, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE);
+ get_user_pass (&token_pass, NULL, szPrompt, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_PASSWORD_ONLY);
strncpynt (szPIN, token_pass.password, nMaxPIN);
purge_user_pass (&token_pass, true);
@@ -2230,213 +121,166 @@ _openvpn_pkcs11_pin_prompt (
}
void
-init_pkcs11 (
+pkcs11_initialize (
const int nPINCachePeriod
) {
CK_RV rv;
- msg (
- D_PKCS11_DEBUG,
- "PKCS#11: init_pkcs11 - entered"
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11_initialize - entered"
);
- if ((rv = pkcs11_initialize ()) != CKR_OK) {
- msg (M_FATAL, "PKCS#11: Cannot initialize %ld-'%s'", rv, pkcs11_getMessage (rv));
+ if ((rv = pkcs11h_initialize ()) != CKR_OK) {
+ PKCS11LOG (PKCS11_LOG_ERROR, "PKCS#11: Cannot initialize %ld-'%s'", rv, pkcs11h_getMessage (rv));
}
-/*Until REQUEST/REPLY interface.
- if ((rv = pkcs11_setCardPromptHook (_openvpn_pkcs11_card_prompt, NULL)) != CKR_OK) {
- msg (M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11_getMessage (rv));
+
+ if ((rv = pkcs11h_setCardPromptHook (_pkcs11_openvpn_card_prompt, NULL)) != CKR_OK) {
+ PKCS11LOG (PKCS11_LOG_ERROR, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv));
}
-*/
- if ((rv = pkcs11_setPINPromptHook (_openvpn_pkcs11_pin_prompt, NULL)) != CKR_OK) {
- msg (M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11_getMessage (rv));
+
+ if ((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));
}
- if ((rv = pkcs11_setPINCachePeriod (nPINCachePeriod)) != CKR_OK) {
- msg (M_FATAL, "PKCS#11: Cannot set PIN cache period %ld-'%s'", rv, pkcs11_getMessage (rv));
+ if ((rv = pkcs11h_setPINCachePeriod (nPINCachePeriod)) != CKR_OK) {
+ PKCS11LOG (PKCS11_LOG_ERROR, "PKCS#11: Cannot set PIN cache period %ld-'%s'", rv, pkcs11h_getMessage (rv));
}
- msg (
- D_PKCS11_DEBUG,
- "PKCS#11: init_pkcs11 - return"
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11_initialize - return"
);
}
void
-free_pkcs11 () {
- msg (
- D_PKCS11_DEBUG,
- "PKCS#11: free_pkcs11 - entered"
+pkcs11_terminate () {
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11_terminate - entered"
);
- pkcs11_terminate ();
+ pkcs11h_terminate ();
- msg (
- D_PKCS11_DEBUG,
- "PKCS#11: free_pkcs11 - return"
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11_terminate - return"
);
}
void
-fork_fix_pkcs11 () {
- pkcs11_forkFixup ();
+pkcs11_forkFixup () {
+ pkcs11h_forkFixup ();
}
void
-add_pkcs11 (
+pkcs11_addProvider (
IN const char * const provider,
IN const char * const sign_mode
) {
CK_RV rv;
- msg (
- D_PKCS11_DEBUG,
- "PKCS#11: add_pkcs11 - entered - provider='%s', sign_mode='%s'",
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11_addProvider - entered - provider='%s', sign_mode='%s'",
provider,
sign_mode == NULL ? "default" : sign_mode
);
- msg (
- M_INFO,
+ PKCS11LOG (
+ PKCS11_LOG_INFO,
"PKCS#11: Adding PKCS#11 provider '%s'",
provider
);
- if ((rv = pkcs11_addProvider (provider, sign_mode)) != CKR_OK) {
- msg (M_WARN, "PKCS#11: Cannot initialize provider '%s' %ld-'%s'", provider, rv, pkcs11_getMessage (rv));
+ if ((rv = pkcs11h_addProvider (provider, sign_mode)) != CKR_OK) {
+ PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot initialize provider '%s' %ld-'%s'", provider, rv, pkcs11h_getMessage (rv));
}
- msg (
- D_PKCS11_DEBUG,
- "PKCS#11: add_pkcs11 - return"
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: pkcs11_addProvider - return"
);
}
int
SSL_CTX_use_pkcs11 (
IN OUT SSL_CTX * const ssl_ctx,
- 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 char * const pkcs11h_slot_type,
+ IN const char * const pkcs11h_slot,
+ IN const char * const pkcs11h_id_type,
+ IN const char * const pkcs11h_id,
+ IN const bool pkcs11h_protected_authentication
) {
X509 *x509 = NULL;
RSA *rsa = NULL;
- EVP_PKEY *pubkey = NULL;
- openssl_session_t openssl_session = NULL;
- bool fShouldFreeOpenSSLSession = true;
+ pkcs11h_openssl_session_t pkcs11h_openssl_session = NULL;
CK_RV rv = CKR_OK;
- unsigned char certificate[10*1024];
- size_t certificate_size;
- unsigned char *p;
bool fOK = true;
- msg (
- 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', pkcs11_protected_authentication=%d",
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
+ "PKCS#11: SSL_CTX_use_pkcs11 - entered - ssl_ctx=%p, pkcs11h_slot_type='%s', pkcs11h_slot='%s', pkcs11h_id_type='%s', pkcs11h_id='%s', pkcs11h_protected_authentication=%d",
(void *)ssl_ctx,
- pkcs11_slot_type,
- pkcs11_slot,
- pkcs11_id_type,
- pkcs11_id,
- pkcs11_protected_authentication ? 1 : 0
+ pkcs11h_slot_type,
+ pkcs11h_slot,
+ pkcs11h_id_type,
+ pkcs11h_id,
+ pkcs11h_protected_authentication ? 1 : 0
);
- ASSERT (ssl_ctx!=NULL);
- ASSERT (pkcs11_slot_type!=NULL);
- ASSERT (pkcs11_slot!=NULL);
- ASSERT (pkcs11_id_type!=NULL);
- ASSERT (pkcs11_id!=NULL);
+ PKCS11ASSERT (ssl_ctx!=NULL);
+ PKCS11ASSERT (pkcs11h_slot_type!=NULL);
+ PKCS11ASSERT (pkcs11h_slot!=NULL);
+ PKCS11ASSERT (pkcs11h_id_type!=NULL);
+ PKCS11ASSERT (pkcs11h_id!=NULL);
if (
fOK &&
- (openssl_session = (openssl_session_t)malloc (sizeof (struct openssl_session_s))) == NULL
+ (pkcs11h_openssl_session = pkcs11h_openssl_createSession (false)) == NULL
) {
fOK = false;
- msg (M_WARN, "PKCS#11: Cannot allocate memory");
+ PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot initialize openssh session");
}
- if (fOK) {
- memset (openssl_session, 0, sizeof (struct openssl_session_s));
- }
-
if (
fOK &&
- (rv = pkcs11_createSession (
- pkcs11_slot_type,
- pkcs11_slot,
- pkcs11_id_type,
- pkcs11_id,
- pkcs11_protected_authentication,
- &openssl_session->pkcs11_session
+ (rv = pkcs11h_createSession (
+ pkcs11h_slot_type,
+ pkcs11h_slot,
+ pkcs11h_id_type,
+ pkcs11h_id,
+ pkcs11h_protected_authentication,
+ &pkcs11h_openssl_session->pkcs11h_session
)) != CKR_OK
) {
fOK = false;
- msg (M_WARN, "PKCS#11: Cannot set parameters %ld-'%s'", rv, pkcs11_getMessage (rv));
+ PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot set parameters %ld-'%s'", rv, pkcs11h_getMessage (rv));
}
if (
fOK &&
- (x509 = X509_new ()) == NULL
+ (rsa = pkcs11h_openssl_getRSA (pkcs11h_openssl_session)) == NULL
) {
fOK = false;
- msg (M_WARN, "PKCS#11: Unable to allocate certificate object");
+ PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Unable get rsa object");
}
- certificate_size = sizeof (certificate);
if (
fOK &&
- (rv = pkcs11_getCertificate (
- openssl_session->pkcs11_session,
- certificate,
- &certificate_size
- )) != CKR_OK
- ) {
- fOK = false;
- msg (M_WARN, "PKCS#11: Cannot read X.509 certificate from token %ld-'%s'", rv, pkcs11_getMessage (rv));
- }
-
- p = certificate;
- if (
- fOK &&
- !d2i_X509 (&x509, &p, certificate_size)
- ) {
- fOK = false;
- msg (M_WARN, "PKCS#11: Unable to parse X.509 certificate");
- }
-
- if (
- fOK &&
- (pubkey = X509_get_pubkey (x509)) == NULL
- ) {
- fOK = false;
- msg (M_WARN, "PKCS#11: Cannot get public key");
- }
-
- if (
- fOK &&
- pubkey->type != EVP_PKEY_RSA
+ (x509 = pkcs11h_openssl_getX509 (pkcs11h_openssl_session)) == NULL
) {
fOK = false;
- msg (M_WARN, "PKCS#11: Invalid public key algorithm");
+ PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Unable get certificate object");
}
if (
fOK &&
- (rsa = EVP_PKEY_get1_RSA (pubkey)) == NULL
+ !SSL_CTX_use_RSAPrivateKey (ssl_ctx, rsa)
) {
fOK = false;
- msg (M_WARN, "PKCS#11: Cannot get RSA key");
- }
-
- if (fOK) {
- openssl_pkcs11_set_rsa (openssl_session, rsa);
- rsa->flags |= RSA_FLAG_SIGN_VER;
-
- /* it will be freed when rsa usage count will be zero */
- fShouldFreeOpenSSLSession = false;
+ PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot set private key for openssl");
}
if (
@@ -2444,25 +288,13 @@ SSL_CTX_use_pkcs11 (
!SSL_CTX_use_certificate (ssl_ctx, x509)
) {
fOK = false;
- msg (M_WARN, "PKCS#11: Cannot set certificate for openssl");
- }
-
- if (
- fOK &&
- !SSL_CTX_use_RSAPrivateKey (ssl_ctx, rsa)
- ) {
- fOK = false;
- msg (M_WARN, "PKCS#11: Cannot set private key for openssl");
+ PKCS11LOG (PKCS11_LOG_WARN, "PKCS#11: Cannot set certificate for openssl");
}
/*
* openssl objects have reference
* count, so release them
*/
- if (pubkey != NULL) {
- EVP_PKEY_free (pubkey);
- pubkey = NULL;
- }
if (x509 != NULL) {
X509_free (x509);
@@ -2473,19 +305,14 @@ SSL_CTX_use_pkcs11 (
RSA_free (rsa);
rsa = NULL;
}
-
- if (fShouldFreeOpenSSLSession) {
- if (openssl_session != NULL) {
- if (openssl_session->pkcs11_session != NULL) {
- pkcs11_freeSession (openssl_session->pkcs11_session);
- }
- free (openssl_session);
- openssl_session = NULL;
- }
+
+ if (pkcs11h_openssl_session != NULL) {
+ pkcs11h_openssl_freeSession (pkcs11h_openssl_session);
+ pkcs11h_openssl_session = NULL;
}
- msg (
- D_PKCS11_DEBUG,
+ PKCS11LOG (
+ PKCS11_LOG_DEBUG2,
"PKCS#11: SSL_CTX_use_pkcs11 - return fOK=%d, rv=%ld",
fOK ? 1 : 0,
rv
@@ -2496,460 +323,28 @@ SSL_CTX_use_pkcs11 (
void
show_pkcs11_slots (
- IN const int msglev,
- IN const int warnlev,
- IN const char * const provider
+ const char * const provider
) {
- CK_INFO info;
- CK_SLOT_ID slots[1024];
- CK_ULONG slotnum;
- CK_SLOT_ID s;
- CK_RV rv;
-
- pkcs11_provider_t pkcs11_provider;
-
- ASSERT (provider!=NULL);
-
- if (
- (rv = pkcs11_initialize ()) != CKR_OK
- ) {
- msg (M_FATAL, "PKCS#11: Cannot initialize interface %ld-'%s'", rv, pkcs11_getMessage (rv));
- }
-
- if (
- (rv = pkcs11_addProvider (provider, NULL)) != CKR_OK
- ) {
- msg (M_FATAL, "PKCS#11: Cannot initialize provider %ld-'%s'", rv, pkcs11_getMessage (rv));
- }
-
- /*
- * our provider is head
- */
- pkcs11_provider = pkcs11_data->providers;
- if (pkcs11_provider == NULL || !pkcs11_provider->fEnabled) {
- msg (M_FATAL, "PKCS#11: Cannot get provider %ld-'%s'", rv, pkcs11_getMessage (rv));
- }
-
- if (
- (rv = pkcs11_provider->f->C_GetInfo (&info)) != CKR_OK
- ) {
- msg (warnlev, "PKCS#11: Cannot get PKCS#11 provider information %ld-'%s'", rv, pkcs11_getMessage (rv));
- }
- else {
- char szManufacturerID[sizeof (info.manufacturerID)+1];
-
- _fixupFixedString (
- (char *)info.manufacturerID,
- szManufacturerID,
- sizeof (info.manufacturerID)
- );
-
- msg (
- msglev,
- (
- "Provider Information:\n"
- "\tcryptokiVersion: %u.%u\n"
- "\tmanufacturerID: %s\n"
- "\tflags: %d\n"
- ),
- info.cryptokiVersion.major,
- info.cryptokiVersion.minor,
- szManufacturerID,
- (unsigned)info.flags
- );
- }
-
- slotnum = sizeof (slots) / sizeof (CK_SLOT_ID);
- if (
- (rv = pkcs11_provider->f->C_GetSlotList (
- FALSE,
- slots,
- &slotnum
- )) != CKR_OK
- ) {
- msg (warnlev, "PKCS#11: Cannot get slot list %ld-'%s'", rv, pkcs11_getMessage (rv));
- }
- else {
- msg (
- msglev,
- (
- "The following slots are available for use with this provider.\n"
- "Each slot shown below may be used as a parameter to a\n"
- "--pkcs11-slot-type and --pkcs11-slot options.\n"
- "\n"
- "Slots: (id - name)"
- )
- );
- for (s=0;s<slotnum;s++) {
- CK_SLOT_INFO info;
-
- if (
- (rv = pkcs11_provider->f->C_GetSlotInfo (
- slots[s],
- &info
- )) == CKR_OK
- ) {
- char szCurrentName[sizeof (info.slotDescription)+1];
-
- _fixupFixedString (
- (char *)info.slotDescription,
- szCurrentName,
- sizeof (info.slotDescription)
- );
-
- msg (msglev, "\t%lu - %s", slots[s], szCurrentName);
- }
- }
- }
-
- pkcs11_terminate ();
-}
-
-static
-bool
-_show_pkcs11_objects_pin_prompt (
- IN const void *pData,
- IN const char * const szLabel,
- OUT char * const szPIN,
- IN const size_t nMaxPIN
-) {
- strncpy (szPIN, (char *)pData, nMaxPIN);
- return true;
+ pkcs11h_standalone_dump_slots (
+ _pkcs11_openvpn_print,
+ NULL,
+ provider
+ );
}
void
show_pkcs11_objects (
- IN const int msglev,
- IN const int warnlev,
- IN const char * const provider,
- IN const char * const slot,
- IN const char * const pin
+ const char * const provider,
+ const char * const slot,
+ const char * const pin
) {
- CK_OBJECT_HANDLE objects[10];
- CK_SESSION_HANDLE session;
- CK_ULONG objects_found;
- CK_TOKEN_INFO info;
- CK_SLOT_ID s;
- CK_RV rv;
-
- pkcs11_provider_t pkcs11_provider;
-
- ASSERT (provider!=NULL);
- ASSERT (slot!=NULL);
- ASSERT (pin!=NULL);
-
- s = atoi (slot);
-
- if (
- (rv = pkcs11_initialize ()) != CKR_OK
- ) {
- msg (M_FATAL, "PKCS#11: Cannot initialize interface %ld-'%s'", rv, pkcs11_getMessage (rv));
- }
-
- if (
- (rv = pkcs11_setPINPromptHook (_show_pkcs11_objects_pin_prompt, (void *)pin)) != CKR_OK
- ) {
- msg (M_FATAL, "PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11_getMessage (rv));
- }
-
- if (
- (rv = pkcs11_addProvider (provider, NULL)) != CKR_OK
- ) {
- msg (M_FATAL, "PKCS#11: Cannot initialize provider %ld-'%s'", rv, pkcs11_getMessage (rv));
- }
-
- /*
- * our provider is head
- */
- pkcs11_provider = pkcs11_data->providers;
- if (pkcs11_provider == NULL || !pkcs11_provider->fEnabled) {
- msg (M_FATAL, "PKCS#11: Cannot get provider %ld-'%s'", rv, pkcs11_getMessage (rv));
- }
-
- if (
- (rv = pkcs11_provider->f->C_GetTokenInfo (
- s,
- &info
- )) != CKR_OK
- ) {
- msg (warnlev, "PKCS#11: Cannot get token information for slot %ld %ld-'%s'", s, rv, pkcs11_getMessage (rv));
- }
- else {
- char szLabel[sizeof (info.label)+1];
- char szManufacturerID[sizeof (info.manufacturerID)+1];
- char szModel[sizeof (info.model)+1];
- char szSerialNumber[sizeof (info.serialNumber)+1];
-
- _fixupFixedString (
- (char *)info.label,
- szLabel,
- sizeof (info.label)
- );
- _fixupFixedString (
- (char *)info.manufacturerID,
- szManufacturerID,
- sizeof (info.manufacturerID)
- );
- _fixupFixedString (
- (char *)info.model,
- szModel,
- sizeof (info.model)
- );
- _fixupFixedString (
- (char *)info.serialNumber,
- szSerialNumber,
- sizeof (info.serialNumber)
- );
-
- msg (
- msglev,
- (
- "Token Information:\n"
- "\tlabel:\t\t%s\n"
- "\tmanufacturerID:\t%s\n"
- "\tmodel:\t\t%s\n"
- "\tserialNumber:\t%s\n"
- "\tflags:\t\t%08x\n"
- "\n"
- "You can access this token using\n"
- "--pkcs11-slot-type \"label\" --pkcs11-slot \"%s\" options.\n"
- ),
- szLabel,
- szManufacturerID,
- szModel,
- szSerialNumber,
- (unsigned)info.flags,
- szLabel
- );
- }
-
- if (
- (rv = pkcs11_provider->f->C_OpenSession (
- s,
- CKF_SERIAL_SESSION,
- NULL_PTR,
- NULL_PTR,
- &session
- )) != CKR_OK
- ) {
- msg (M_FATAL, "PKCS#11: Cannot open session to slot %ld %ld-'%s'", s, rv, pkcs11_getMessage (rv));
- }
-
- if (
- (rv = pkcs11_provider->f->C_Login (
- session,
- CKU_USER,
- (CK_CHAR_PTR)pin,
- (CK_ULONG)strlen (pin)
- )) != CKR_OK &&
- rv != CKR_USER_ALREADY_LOGGED_IN
- ) {
- msg (M_FATAL, "PKCS#11: Cannot login to token on slot %ld %ld-'%s'", s, rv, pkcs11_getMessage (rv));
- }
-
- if (
- (rv = pkcs11_provider->f->C_FindObjectsInit (
- session,
- NULL,
- 0
- )) != CKR_OK
- ) {
- msg (M_FATAL, "PKCS#11: Cannot query objects for token on slot %ld %ld-'%s'", s, rv, pkcs11_getMessage (rv));
- }
-
- msg (
- msglev,
- "The following objects are available for use with this token.\n"
- "Each object shown below may be used as a parameter to\n"
- "--pkcs11-id-type and --pkcs11-id options.\n"
+ pkcs11h_standalone_dump_objects (
+ _pkcs11_openvpn_print,
+ NULL,
+ provider,
+ slot,
+ pin
);
-
- while (
- (rv = pkcs11_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[PKCS11_MAX_ATTRIBUTE_SIZE];
- unsigned char attrs_label[PKCS11_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 (
- pkcs11_provider->f->C_GetAttributeValue (
- session,
- objects[i],
- attrs,
- sizeof (attrs) / sizeof (CK_ATTRIBUTE)
- ) == CKR_OK
- ) {
- int id_len = attrs[1].ulValueLen;
- int j;
-
- attrs_label[attrs[2].ulValueLen] = 0;
-
- msg (
- msglev,
- (
- "Object\n"
- "\tLabel:\t\t%s\n"
- "\tId:"
- ),
- attrs_label
- );
-
-
- 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]);
- }
-
- msg (msglev, "\t\t%s", szLine);
- }
-
- if (attrs_class == CKO_CERTIFICATE) {
- unsigned char certificate[PKCS11_MAX_ATTRIBUTE_SIZE];
- CK_ATTRIBUTE attrs_cert[] = {
- {CKA_VALUE, certificate, sizeof (certificate)}
- };
-
- msg (msglev, "\tType:\t\tCertificate");
-
- if (
- pkcs11_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) {
- msg (warnlev, "Cannot create x509 context");
- }
- else {
- unsigned char *p;
-
- p = certificate;
- if (d2i_X509 (&x509, &p, 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) {
- msg (warnlev, "Cannot create BIO context");
- }
- 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;
- }
-
- msg (
- msglev,
- (
- "\tsubject:\t%s\n"
- "\tserialNumber:\t%s\n"
- "\tnotBefore:\t%s"
- ),
- szSubject,
- szSerial,
- szNotBefore
- );
- }
- }
- 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)}
- };
-
- msg (msglev, "\tType:\t\tPrivate Key");
-
- if (
- pkcs11_provider->f->C_GetAttributeValue (
- session,
- objects[i],
- attrs_key,
- sizeof (attrs_key) / sizeof (CK_ATTRIBUTE)
- ) == CKR_OK
- ) {
- msg (
- msglev,
- (
- "\tSign:\t\t%s\n"
- "\tSign Recover:\t%s"
- ),
- sign ? "TRUE" : "FALSE",
- sign_recover ? "TRUE" : "FALSE"
- );
- }
- }
- else {
- msg (msglev, "\tType:\t\tUnsupported");
- }
- }
- }
- }
- pkcs11_provider->f->C_FindObjectsFinal (session);
- pkcs11_provider->f->C_Logout (session);
- pkcs11_provider->f->C_CloseSession (session);
- pkcs11_terminate ();
}
#else
diff --git a/pkcs11.h b/pkcs11.h
index a6f0f89..4e4a95b 100644
--- a/pkcs11.h
+++ b/pkcs11.h
@@ -30,18 +30,18 @@
#include <openssl/ssl.h>
void
-init_pkcs11 (
+pkcs11_initialize (
const int nPINCachePeriod
);
void
-free_pkcs11 ();
+pkcs11_terminate ();
void
-fork_fix_pkcs11 ();
+pkcs11_forkFixup ();
void
-add_pkcs11 (
+pkcs11_addProvider (
const char * const provider,
const char * const sign_mode
);
@@ -58,15 +58,11 @@ SSL_CTX_use_pkcs11 (
void
show_pkcs11_slots (
- const int msglev,
- const int warnlev,
const char * const provider
);
void
show_pkcs11_objects (
- const int msglev,
- const int warnlev,
const char * const provider,
const char * const slot,
const char * const pin
diff --git a/proxy.c b/proxy.c
index 5c8521a..0911733 100644
--- a/proxy.c
+++ b/proxy.c
@@ -280,7 +280,6 @@ new_http_proxy (const struct http_proxy_options *o,
{
get_user_pass (&static_proxy_user_pass,
o->auth_file,
- false,
"HTTP Proxy",
GET_USER_PASS_MANAGEMENT);
p->up = static_proxy_user_pass;
diff --git a/ssl.c b/ssl.c
index dc2381e..8a7f0a3 100644
--- a/ssl.c
+++ b/ssl.c
@@ -266,7 +266,7 @@ void
pem_password_setup (const char *auth_file)
{
if (!strlen (passbuf.password))
- get_user_pass (&passbuf, auth_file, true, UP_TYPE_PRIVATE_KEY, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE);
+ get_user_pass (&passbuf, auth_file, UP_TYPE_PRIVATE_KEY, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE|GET_USER_PASS_PASSWORD_ONLY);
}
int
@@ -296,7 +296,7 @@ auth_user_pass_setup (const char *auth_file)
{
auth_user_pass_enabled = true;
if (!auth_user_pass.defined)
- get_user_pass (&auth_user_pass, auth_file, false, UP_TYPE_AUTH, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE);
+ get_user_pass (&auth_user_pass, auth_file, UP_TYPE_AUTH, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE);
}
/*