aboutsummaryrefslogtreecommitdiff
path: root/pkcs11.c
diff options
context:
space:
mode:
Diffstat (limited to 'pkcs11.c')
-rw-r--r--pkcs11.c1935
1 files changed, 802 insertions, 1133 deletions
diff --git a/pkcs11.c b/pkcs11.c
index 6c52383..fd8d156 100644
--- a/pkcs11.c
+++ b/pkcs11.c
@@ -42,8 +42,6 @@
#include <stdarg.h>
#include <assert.h>
-#include <sqlite3.h>
-
#include <hal.h>
/*
@@ -74,6 +72,21 @@
#define P11_ONE_AND_ONLY_SLOT 0
/*
+ * How many sessions and object handles to allow. We could do this
+ * with dynamic memory, but static arrays are simpler and faster. We
+ * don't expect all that many sessions, and slots in the object table
+ * are cheap.
+ */
+
+#ifndef P11_MAX_SESSION_HANDLES
+#define P11_MAX_SESSION_HANDLES (64)
+#endif
+
+#ifndef P11_MAX_OBJECT_HANDLES
+#define P11_MAX_OBJECT_HANDLES (4096)
+#endif
+
+/*
* Version numbers. Placeholders for now.
*
* Software version number is just the version of this PKCS #11
@@ -130,29 +143,19 @@
/*
- * PKCS #11 session.
- */
-
-/*
- * At present we have no concept of encryption or signature algorithms
- * in libhal, as we only support RSA and AES. For PKCS #11 purposes
- * we can figure out what kind of key we're looking at from attributes
- * like CKA_KEY_TYPE, so it's just something we look up given the key
- * object handle.
- *
- * General idea is that we have separate descriptors/handles/state for
- * each operation that we're allowed to do in parallel, so sign,
- * verify, digest, encrypt, decrypt, wrapkey, and unwrapkey all need
- * separate slots in the session structure. Add these as we go.
+ * PKCS #11 sessions. General idea is that we have separate
+ * descriptors/handles/state for each operation that we're allowed to
+ * do in parallel, so sign, verify, digest, encrypt, decrypt, wrapkey,
+ * and unwrapkey all need separate slots in the session structure.
+ * Add these as we go.
*/
typedef struct p11_session {
CK_SESSION_HANDLE handle; /* Session handle */
- struct p11_session *link; /* Next session in list */
CK_STATE state; /* State (CKS_*) of this session */
CK_NOTIFY notify; /* Notification callback */
CK_VOID_PTR application; /* Application data */
- sqlite3_stmt *find_query; /* FindObject*() query state */
+ hal_rpc_pkey_attribute *find_query; /* FindObject*() query state */
int find_query_done; /* find_query has terminated */
hal_digest_algorithm_t
digest_algorithm, /* Hash algorithm for C_Digest*() */
@@ -168,34 +171,40 @@ typedef struct p11_session {
} p11_session_t;
/*
+ * PKCS #11 objects. These are pretty simple, as they're really just
+ * mappings from PKCS #11's naming scheme to libhal UUIDs, with a little
+ * extra fun for PKCS #11 "session" objects.
+ */
+
+typedef struct p11_object {
+ CK_OBJECT_HANDLE handle; /* Object handle */
+ CK_SESSION_HANDLE session; /* Associated session (if any) */
+ hal_uuid_t uuid; /* libhal key UUID */
+} p11_object_t;
+
+/*
* PKCS #11 handle management. PKCS #11 has two kinds of handles:
* session handles and object handles. We subdivide object handles
- * into token object handles (handles for objects that live on the
- * token) and session object handles (handles for objects that live
- * only as long as the session does), and we steal a bit of the object
- * handle as a flag to distinguish between our two kinds of object
- * handles, considerably simplifing the objected-related SQL code.
+ * into token object handles (handles for objects which live on the
+ * token, ie, in non-volatile storage) and session object handles
+ * (handles for objects which live only as long as the session does),
+ * and we steal two bits of the handle as as flags to distinguish
+ * between these three kinds handles. We sub-divide the rest of a
+ * handle into a nonce (well, a lame one -- for now this is just a
+ * counter, if this becomes an issue we could do better) and an array
+ * index into the relevant table.
*/
typedef enum {
- handle_flavor_session,
- handle_flavor_token_object,
- handle_flavor_session_object
+ handle_flavor_none = 0, /* Matches CK_INVALID_HANDLE */
+ handle_flavor_session = 1,
+ handle_flavor_token_object = 2,
+ handle_flavor_session_object = 3
} handle_flavor_t;
-#define FLAG_HANDLE_TOKEN 0x80000000
-
-#define is_token_handle(_handle_) (((_handle_) & FLAG_HANDLE_TOKEN) != 0)
-
-/*
- * Digest algorithm to use when computing a key hashes. This doesn't
- * need to be particularly secure, we're just using it to generate
- * reasonably unique identifier strings from public keys. We use
- * SHA-1 for this because that's what most X.509 implementations use
- * for this purpose.
- */
-
-#define P11_KEY_HASH_ALGORITHM HAL_DIGEST_ALGORITHM_SHA1
+#define HANDLE_MASK_FLAVOR (0xc0000000)
+#define HANDLE_MASK_NONCE (0x3fff0000)
+#define HANDLE_MASK_INDEX (0x0000ffff)
@@ -210,19 +219,14 @@ static enum {
} logged_in_as = not_logged_in;
/*
- * PKCS #11 sessions for this application.
+ * PKCS #11 sessions and object handles for this application.
*/
-static p11_session_t *p11_sessions;
+static p11_session_t p11_sessions[P11_MAX_SESSION_HANDLES];
+static p11_object_t p11_objects [P11_MAX_OBJECT_HANDLES];
-/*
- * Next PKCS #11 handle to allocate. We use a single handle space for
- * both session and object handles, and we just keep incrementing
- * until it wraps, to reduce the amount of time we have to spend
- * on SQL probes to avoid handle conflicts.
- */
-
-static CK_ULONG next_handle;
+static unsigned p11_sessions_in_use, p11_session_next;
+static unsigned p11_objects_in_use, p11_object_next;
/*
* Mutex callbacks.
@@ -410,202 +414,6 @@ static CK_RV _p11_error_from_hal(const hal_error_t err, const char * const file,
/*
- * SQL utilities.
- */
-
-/*
- * Debugging control.
- */
-
-#ifndef DEBUG_SQL
-#define DEBUG_SQL 1
-#endif
-
-/*
- * Default filename for SQL database lives. Can be overriden at
- * runtime by setting PKCS11_DATABASE environment variable.
- */
-
-#ifndef SQL_DATABASE
-#define SQL_DATABASE ".cryptech-pkcs11.db"
-#endif
-
-/*
- * SQL database.
- */
-
-static sqlite3 *sqldb = NULL;
-
-/*
- * Error checking for SQLite calls.
- */
-
-#if DEBUG_SQL
-
-#define sql_whine(_expr_) \
- (fprintf(stderr, "\n%s:%u: %s returned %s\n", \
- __FILE__, __LINE__, #_expr_, sqlite3_errmsg(sqldb)), \
- sql_breakpoint())
-
-#else /* DEBUG_SQL */
-
-#define sql_whine(_expr_) \
- ((void) 0)
-
-#endif /* DEBUG_SQL */
-
-#define sql_check(_good_, _expr_) \
- ((_expr_) == (_good_) ? 1 : (sql_whine(_expr_), 0))
-
-#define sql_check_ok(_expr_) sql_check(SQLITE_OK, _expr_)
-#define sql_check_row(_expr_) sql_check(SQLITE_ROW, _expr_)
-#define sql_check_done(_expr_) sql_check(SQLITE_DONE, _expr_)
-#define sql_whine_step() sql_whine(sqlite3_step())
-
-/*
- * Hook on which to hang a debugger breakpoint on SQL errors.
- */
-
-#if DEBUG_SQL
-static void sql_breakpoint(void)
-{
- fprintf(stderr, "\n[sql_breakpoint]\n");
-}
-#endif
-
-/*
- * Execute SQL code that doesn't require a prepared query.
- */
-
-static int sql_exec(const char *cmd)
-{
- char *msg = NULL;
-
- if (sql_check_ok(sqlite3_exec(sqldb, cmd, NULL, NULL, &msg)))
- return 1;
-
-#if DEBUG_SQL
- if (msg != NULL)
- fprintf(stderr, "\n[%s]\n", msg);
-#endif
-
- return 0;
-}
-
-/*
- * Initialize SQL. This includes loading our schema, portions of
- * which live in the temp (memory) database thus always need to be
- * created on startup.
- */
-
-static int sql_init(void)
-{
- static const char schema[] =
-#include "schema.h"
- ;
-
- assert(sqldb == NULL);
-
- const char * const env = getenv("CRYPTECH_PKCS11_DATABASE");
- const char * const home = getenv("HOME");
- const char * const base = SQL_DATABASE;
- int ok;
-
- if (env != NULL) {
- ok = sql_check_ok(sqlite3_open(env, &sqldb));
- }
-
- else if (home == NULL) {
- ok = sql_check_ok(sqlite3_open(base, &sqldb));
- }
-
- else {
- char fn[strlen(home) + strlen(base) + 2];
- snprintf(fn, sizeof(fn), "%s/%s", home, base);
- ok = sql_check_ok(sqlite3_open(fn, &sqldb));
- }
-
- return ok && sql_exec(schema);
-}
-
-/*
- * Shut down SQL.
- *
- * Yes, this can return failure, although it's not clear what we're
- * meant to do about that if the application is going to shut down
- * regardless of what we do. I guess we could loop retrying a few
- * times for errors like SQLITE_BUSY, but that's about it.
- */
-
-static int sql_fini(void)
-{
- if (!sql_check_ok(sqlite3_close(sqldb)))
- return 0;
-
- sqldb = NULL;
- return 1;
-}
-
-/*
- * GCC attribute declaration to help catch format string errors,
- * ignored by other compilers.
- */
-
-#ifdef __GNUC__
-static int sql_prepare(sqlite3_stmt **q,
- const char *format, ...)
- __attribute__ ((format (printf, 2, 3)));
-#endif
-
-/*
- * Prepare an SQLite3 query, using vsnprintf() to format the query.
- *
- * WARNING WARNING WARNING WARNING
- *
- * Do not use this formatting mechanism for anything involving
- * user-supplied data. It's only intended to handle things like
- * selecting between two parallel table structures or queries using
- * manifest constants that are only available in C header files.
- */
-
-static int sql_prepare(sqlite3_stmt **q, const char *format, ...)
-{
- char buffer[2048];
- va_list ap;
- size_t n;
-
- va_start(ap, format);
- n = vsnprintf(buffer, sizeof(buffer), format, ap);
- va_end(ap);
-
- if (n >= sizeof(buffer))
- return SQLITE_TOOBIG;
-
- return sqlite3_prepare_v2(sqldb, buffer, -1, q, NULL);
-}
-
-/*
- * This idiom occurs frequently, bundle it so we have the option of
- * doing it along with the normal conditional control flow that SQL
- * queries seem to follow.
- */
-
-static int sql_finalize_and_clear(sqlite3_stmt **q)
-{
- assert(q != NULL);
-
- int err = sqlite3_finalize(*q);
-
- if (err != SQLITE_OK)
- return err;
-
- *q = NULL;
- return SQLITE_OK;
-}
-
-
-
-/*
* Thread mutex utilities. We need to handle three separate cases:
*
* 1) User doesn't care about mutexes;
@@ -778,6 +586,20 @@ static CK_RV posix_mutex_unlock(CK_VOID_PTR pMutex)
/*
+ * Bit mask twiddling utilities.
+ */
+
+static inline CK_ULONG mask_ldb(const CK_ULONG mask, const CK_ULONG value)
+{
+ return (value & mask) / (mask & ~(mask - 1));
+}
+
+static inline CK_ULONG mask_dpb(const CK_ULONG mask, const CK_ULONG value)
+{
+ return (value * (mask & ~(mask - 1))) & mask;
+}
+
+/*
* Translate between libhal EC curve names and OIDs.
*/
#warning Perhaps this should be a utility routine in libhal instead of here
@@ -828,82 +650,32 @@ static inline hal_session_handle_t p11_session_hal_session(const p11_session_t *
return handle;
}
-
-
/*
- * Find an unused handle.
- *
- * Note that zero is an excluded value (CK_INVALID_HANDLE), hence the
- * slightly odd arithmetic.
- *
- * For object handles, we steal the high-order bit to flag whether the
- * handle represents a session object or token object.
+ * Handle utilities.
*/
-static CK_ULONG p11_allocate_unused_handle(const handle_flavor_t flavor)
+static inline CK_ULONG handle_compose(const handle_flavor_t flavor,
+ const unsigned nonce,
+ const unsigned index)
{
- static const char select_format[] =
- " SELECT %s_id FROM %s WHERE %s_handle = ?";
-
- const char *table = flavor == handle_flavor_session ? "session" : "object";
- sqlite3_stmt *q = NULL;
- CK_ULONG handle;
- int ret;
-
- if (!sql_check_ok(sql_prepare(&q, select_format, table, table, table)))
- goto fail;
-
- for (;;) {
-
- handle = ++next_handle;
- next_handle %= 0xFFFFFFFF;
-
- switch (flavor) {
- case handle_flavor_session:
- break;
- case handle_flavor_token_object:
- handle |= FLAG_HANDLE_TOKEN;
- break;
- case handle_flavor_session_object:
- handle &= ~FLAG_HANDLE_TOKEN;
- break;
- }
-
- assert(handle != CK_INVALID_HANDLE);
-
- if (!sql_check_ok(sqlite3_reset(q)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 1, handle)))
- goto fail;
-
- if ((ret = sqlite3_step(q)) == SQLITE_ROW)
- continue;
-
- if (ret == SQLITE_DONE)
- break;
-
- sql_whine_step();
- goto fail;
-
- }
-
- sqlite3_finalize(q);
- return handle;
-
- fail:
- sqlite3_finalize(q);
- return CK_INVALID_HANDLE;
+ return (mask_dpb(HANDLE_MASK_FLAVOR, flavor) |
+ mask_dpb(HANDLE_MASK_NONCE, nonce) |
+ mask_dbp(HANDLE_MASK_INDEX, index));
}
-/*
- * Translate CKA_TOKEN value to handle flavor.
- */
+static inline handle_flavor_t handle_flavor(const CK_ULONG handle)
+{
+ return (handle_flavor_t) mask_ldb(HANDLE_MASK_FLAVOR, handle);
+}
-static handle_flavor_t p11_handle_flavor_from_cka_token(const CK_BBOOL *bbool)
+static inline unsigned handle_index(const CK_ULONG handle)
{
- assert(bbool != NULL);
- return *bbool ? handle_flavor_token_object : handle_flavor_session_object;
+ return mask_ldb(HANDLE_INDEX, handle);
}
+// Backwards compatability, probably phase this out
+#define is_token_handle(_handle_) (handle_flavor(_handle_) == handle_flavor_token_object)
+
/*
@@ -918,32 +690,13 @@ static handle_flavor_t p11_handle_flavor_from_cka_token(const CK_BBOOL *bbool)
* const specifiers (CK_ATTRIBUTE_PTR has an internal non-const void*).
*/
-static int p11_attribute_set(const CK_OBJECT_HANDLE object_handle,
+static int p11_attribute_set(const hal_pkey_handle_t pkey,
const CK_ATTRIBUTE_TYPE type,
const void * const value,
const CK_ULONG length)
{
- static const char insert_format[] =
- " INSERT OR REPLACE INTO %s_attribute (%s_object_id, type, value)"
- " VALUES ((SELECT %s_object_id FROM object WHERE object_handle = ?1), ?2, ?3)";
-
- const char *flavor = is_token_handle(object_handle) ? "token" : "session";
-
- sqlite3_stmt *q = NULL;
- int ok = 0;
-
- if (!sql_check_ok(sql_prepare(&q, insert_format, flavor, flavor, flavor)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 2, type)) ||
- !sql_check_ok(sqlite3_bind_blob( q, 3, value, length, NULL)) ||
- !sql_check_done(sqlite3_step(q)))
- goto fail;
-
- ok = 1;
-
- fail:
- sqlite3_finalize(q);
- return ok;
+ const hal_rpc_pkey_attribute_t attribute = {.type = type, .length = length, .value = value};
+ return hal_check(hal_rpc_pkey_set_attributes(pkey, &attribute, 1));
}
/*
@@ -953,83 +706,51 @@ static int p11_attribute_set(const CK_OBJECT_HANDLE object_handle,
* cost of more complicated error semantics.
*/
-static int p11_attribute_get(const CK_OBJECT_HANDLE object_handle,
+static int p11_attribute_get(const hal_pkey_handle_t pkey,
const CK_ATTRIBUTE_TYPE type,
void *value,
CK_ULONG *length,
const CK_ULONG maxlength)
{
- static const char select_format[] =
- " SELECT value FROM %s_attribute NATURAL JOIN object"
- " WHERE object_handle = ?1 AND type = ?2";
-
- const char *flavor = is_token_handle(object_handle) ? "token" : "session";
-
- sqlite3_stmt *q = NULL;
- int ret, ok = 0;
- CK_ULONG len;
+ hal_rpc_pkey_attribute_t attribute = {.type = type};
- if (!sql_check_ok(sql_prepare(&q, select_format, flavor)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 2, type)))
- goto fail;
-
- ret = sqlite3_step(q);
-
- if (ret == SQLITE_DONE)
- goto fail;
-
- if (ret != SQLITE_ROW) {
- sql_whine_step();
- goto fail;
- }
-
- len = sqlite3_column_bytes(q, 0);
+ if (!hal_check(hal_rpc_pkey_get_attributes(pkey, &attribute, 1, value, maxlength)))
+ return 0;
if (length != NULL)
- *length = len;
+ *length = attribute.length;
- if (value != NULL && maxlength < len)
- goto fail;
-
- if (value != NULL)
- memcpy(value, sqlite3_column_blob(q, 0), len);
-
- ok = 1;
-
- fail:
- sqlite3_finalize(q);
- return ok;
+ return 1;
}
/*
* Wrappers to set and get CK_BBOOL and CK_ULONG values.
*/
-static int p11_attribute_set_bbool(const CK_OBJECT_HANDLE object_handle, const CK_ATTRIBUTE_TYPE type, const CK_BBOOL value)
+static int p11_attribute_set_bbool(const hal_pkey_handle_t pkey, const CK_ATTRIBUTE_TYPE type, const CK_BBOOL value)
{
- return p11_attribute_set(object_handle, type, &value, sizeof(value));
+ return p11_attribute_set(pkey, type, &value, sizeof(value));
}
#if 0
-static int p11_attribute_set_ulong(const CK_OBJECT_HANDLE object_handle, const CK_ATTRIBUTE_TYPE type, const CK_ULONG value)
+static int p11_attribute_set_ulong(const hal_pkey_handle_t pkey, const CK_ATTRIBUTE_TYPE type, const CK_ULONG value)
{
- return p11_attribute_set(object_handle, type, &value, sizeof(value));
+ return p11_attribute_set(pkey, type, &value, sizeof(value));
}
#endif
-static int p11_attribute_get_bbool(const CK_OBJECT_HANDLE object_handle, const CK_ATTRIBUTE_TYPE type, CK_BBOOL *value)
+static int p11_attribute_get_bbool(const hal_pkey_handle_t pkey, const CK_ATTRIBUTE_TYPE type, CK_BBOOL *value)
{
CK_ULONG length;
- return p11_attribute_get(object_handle, type, value, &length, sizeof(*value)) && length == sizeof(*value);
+ return p11_attribute_get(pkey, type, value, &length, sizeof(*value)) && length == sizeof(*value);
}
-static int p11_attribute_get_ulong(const CK_OBJECT_HANDLE object_handle, const CK_ATTRIBUTE_TYPE type, CK_ULONG *value)
+static int p11_attribute_get_ulong(const hal_pkey_handle_t pkey, const CK_ATTRIBUTE_TYPE type, CK_ULONG *value)
{
CK_ULONG length;
- return p11_attribute_get(object_handle, type, value, &length, sizeof(*value)) && length == sizeof(*value);
+ return p11_attribute_get(pkey, type, value, &length, sizeof(*value)) && length == sizeof(*value);
}
/*
@@ -1171,6 +892,139 @@ static int p11_attribute_is_sensitive(const p11_descriptor_t *descriptor,
*/
/*
+ * Allocate a new object.
+ */
+
+static CK_OBJECT_HANDLE p11_object_allocate(const handle_flavor_t flavor,
+ const hal_uuid_t *uuid,
+ const p11_session_t *session)
+{
+ if (uuid == NULL)
+ return CK_INVALID_HANDLE;
+
+ if (flavor != handle_flavor_token_object && flavor != handle_flavor_session_object)
+ return CK_INVALID_HANDLE;
+
+ static unsigned next_index, nonce;
+ const unsigned last_index = next_index;
+ p11_object_t *object = NULL;
+
+ do {
+
+ next_index = (next_index + 1) % (sizeof(p11_objects) / sizeof(*p11_objects));
+
+ if (next_index == last_index)
+ return CK_INVALID_HANDLE;
+
+ if (next_index == 0)
+ ++nonce;
+
+ object = p11_objects[next_index];
+
+ } while (object.handle == CK_INVALID_HANDLE);
+
+ object->handle = handle_compose(flavor, nonce, next_handle);
+ object->uuid = *uuid;
+ object->session = flavor == handle_flavor_session_object ? session->handle : CK_INVALID_HANDLE;
+ return object->handle;
+}
+
+/*
+ * Free an object.
+ */
+
+static void p11_object_free(p11_object_t *object)
+{
+ if (object == NULL)
+ return;
+
+#warning Should we delete session objects here?
+
+ memset(object, 0, sizeof(*object));
+}
+
+/*
+ * Find an object.
+ */
+
+static p11_object_t *p11_object_find(const CK_OBJECT_HANDLE object_handle)
+{
+ if (handle_flavor(object_handle) != handle_flavor_session_object &&
+ handle_flavor(object_handle) != handle_flavor_token_object)
+ return NULL;
+
+ const unsigned index = handle_index(object_handle);
+
+ if (index >= sizeof(p11_objects) / sizeof(*p11_objects))
+ return NULL;
+
+ p11_object_t *object = &p11_objects[index];
+
+ if (object->handle != object_handle)
+ return NULL;
+
+ return object;
+}
+
+/*
+ * Iterate over object handles. Start with CK_INVALID_HANDLE,
+ * returns CK_INVALID_HANDLE when done.
+ */
+
+static CK_BJECT_HANDLE p11_object_handle_iterate(const CK_OBJECT_HANDLE object_handle)
+{
+ if (handle_flavor(object_handle) != handle_flavor_session_object &&
+ handle_flavor(object_handle) != handle_flavor_token_object)
+ return CK_HANDLE_INVALID;
+
+ for (unsigned index = session_handle == CK_INVALID_HANDLE ? 0 : handle_index(session_handle) + 1;
+ index < sizeof(p11_sessions) / sizeof(*p11_sessions);
+ index++)
+ if (handle_flavor(p11_sessions[index].handle) == handle_flavor_session_object ||
+ handle_flavor(p11_sessions[index].handle) == handle_flavor_token_object)
+ return p11_sessions[index].handle;
+
+ return CK_HANDLE_INVALID;
+}
+
+/*
+ * Syntactic sugar to iterate over objects instead of object handles.
+ */
+
+static p11_object_t *p11_object_iterate(p11_object_t *object)
+{
+ if (object == NULL)
+ return NULL;
+
+ return p11_object_find(p11_object_handle_iterate(object->handle));
+}
+
+/*
+ * Translate CKA_TOKEN value to handle flavor.
+ */
+
+static inline handle_flavor_t p11_object_flavor_from_cka_token(const CK_BBOOL *bbool)
+{
+ return (bbool != NULL && *bbool) ? handle_flavor_token_object : handle_flavor_session_object;
+}
+
+/*
+ * Open the HSM pkey object (if any) corresponding to the PKCS #11 handle.
+ */
+
+static int p11_object_pkey_open(const p11_session_t *session,
+ const CK_OBJECT_HANDLE object_handle,
+ hal_pkey_handle_t *pkey)
+{
+ return (session != NULL && pkey != NULL &&
+ hal_check(hal_rpc_pkey_open(p11_session_hal_client(session),
+ p11_session_hal_session(session),
+ pkey,
+ p11_object_get_uuid(object_handle),
+ p11_object_get_hal_flags(object_handle))));
+}
+
+/*
* Check access rights for an object.
*/
@@ -1180,13 +1034,7 @@ static CK_RV p11_object_check_rights(const p11_session_t *session,
const CK_OBJECT_HANDLE object_handle,
const p11_object_access_t rights)
{
- static const char object_exists_query[] =
- " SELECT count(*) FROM object WHERE object_handle = ?1";
-
- static const char session_object_query[] =
- " SELECT session_handle FROM session NATURAL JOIN object WHERE object_handle = ?1";
-
- sqlite3_stmt *q = NULL;
+ hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
CK_BBOOL cka_private;
CK_BBOOL cka_token;
CK_RV rv;
@@ -1194,10 +1042,13 @@ static CK_RV p11_object_check_rights(const p11_session_t *session,
if (session == NULL)
lose(CKR_SESSION_HANDLE_INVALID);
- if (!p11_attribute_get_bbool(object_handle, CKA_PRIVATE, &cka_private))
+ if (!p11_object_pkey_open(session, object_handle, &pkey))
+ lose(CKR_OBJECT_HANDLE_INVALID);
+
+ if (!p11_attribute_get_bbool(pkey, CKA_PRIVATE, &cka_private))
cka_private = CK_TRUE;
- if (!p11_attribute_get_bbool(object_handle, CKA_TOKEN, &cka_token))
+ if (!p11_attribute_get_bbool(pkey, CKA_TOKEN, &cka_token))
cka_token = CK_FALSE;
/*
@@ -1230,186 +1081,59 @@ static CK_RV p11_object_check_rights(const p11_session_t *session,
lose(CKR_OBJECT_HANDLE_INVALID);
}
+#warning Want session-object visibility sanity check here?
/*
- * Does the object even exist?
- */
-
- if (!sql_check_ok(sql_prepare(&q, object_exists_query)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) ||
- !sql_check_row(sqlite3_step(q)) ||
- !sqlite3_column_int(q, 0))
- lose(CKR_OBJECT_HANDLE_INVALID);
-
- /*
- * Session objects are only visible to the session which created them.
- */
-
- if (!is_token_handle(object_handle) &&
- (!sql_check_ok(sql_finalize_and_clear(&q)) ||
- !sql_check_ok(sql_prepare(&q, session_object_query)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) ||
- !sql_check_row(sqlite3_step(q)) ||
- sqlite3_column_int64(q, 0) != session->handle))
- lose(CKR_OBJECT_HANDLE_INVALID);
-
- /*
- * Ran out of reasons to reject, guess we should allow it.
+ * At this point the old code checked for objects which are not
+ * supposed to be visible to this session. In theory, the keystore
+ * now handles that, but we might want a sanity check here too.
*/
rv = CKR_OK;
fail:
- sqlite3_finalize(q);
+ (void) hal_check(hal_rpc_pkey_close(pkey));
return rv;
}
/*
- * Delete all private objects, probably because user logged out.
- *
- * In the case of token objects, the object itself remains in the
- * token, we're just deleting our handle for the object.
- *
- * In the case of session objects, the object itself goes away.
- */
-
-static int p11_object_delete_all_private(void)
-{
- static const char delete_format[] =
- " WITH"
- " s AS (SELECT session_object_id FROM session_attribute WHERE type = %u AND value <> X'00'),"
- " t AS (SELECT token_object_id FROM token_attribute WHERE type = %u AND value <> X'00')"
- " DELETE FROM object WHERE token_object_id IN t OR session_object_id IN s";
-
- sqlite3_stmt *q = NULL;
- int ok = 0;
-
- if (!sql_check_ok(sql_prepare(&q, delete_format, CKA_PRIVATE, CKA_PRIVATE)) ||
- !sql_check_done(sqlite3_step(q)))
- goto fail;
-
- ok = 1;
-
- fail:
- sqlite3_finalize(q);
- return ok;
-}
-
-/*
- * Create a new object.
- *
- * This is a bit nasty due to the SQL foreign key constraints and the
- * different handling required for session and token objects.
+ * Given a pkey handle and UUID for a newly created HSM key, attach
+ * attributes and create an object handle.
*/
static CK_OBJECT_HANDLE p11_object_create(const p11_session_t *session,
+ const hal_pkey_handle_t pkey,
+ const hal_uuid_t *uuid,
const handle_flavor_t flavor,
const CK_ATTRIBUTE_PTR template,
const CK_ULONG template_length,
const p11_descriptor_t * const descriptor,
- const CK_MECHANISM_PTR mechanism)
+ const hal_rpc_pkey_attribute_t *extra,
+ const unsigned extra_length)
{
- static const char insert_object[] =
- " INSERT INTO object (object_handle)"
- " VALUES (?)";
-
- static const char insert_token_object[] =
- " INSERT INTO token_object DEFAULT VALUES";
-
- static const char insert_session_object[] =
- " INSERT INTO session_object (object_id) VALUES (?)";
-
- static const char update_object_session_object[] =
- " UPDATE object SET"
- " session_id = (SELECT session_id FROM session WHERE session_handle = ?1),"
- " session_object_id = ?2"
- " WHERE object_id = ?3";
-
- static const char update_object_token_object[] =
- " UPDATE object SET token_object_id = ?1 WHERE object_id = ?2";
-
- static const char insert_token_attribute[] =
- " INSERT OR REPLACE INTO token_attribute (token_object_id, type, value)"
- " VALUES (?1, ?2, ?3)";
-
- static const char insert_session_attribute[] =
- " INSERT OR REPLACE INTO session_attribute (session_object_id, type, value)"
- " VALUES (?1, ?2, ?3)";
-
- CK_OBJECT_HANDLE object_handle = p11_allocate_unused_handle(flavor);;
- sqlite3_int64 object_id, session_object_id, token_object_id;
- sqlite3_stmt *q = NULL;
- int i, ok = 0;
-
- assert(session != NULL && template != NULL && descriptor != NULL &&
- (flavor == handle_flavor_token_object ||
- flavor == handle_flavor_session_object));
-
- if (!sql_check_ok(sql_prepare(&q, insert_object)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) ||
- !sql_check_done(sqlite3_step(q)))
- goto fail;
-
- object_id = sqlite3_last_insert_rowid(sqldb);
-
- if (!sql_check_ok(sql_finalize_and_clear(&q)))
- goto fail;
-
- switch (flavor) {
-
- case handle_flavor_token_object:
- if (!sql_check_ok(sql_prepare(&q, insert_token_object)) ||
- !sql_check_done(sqlite3_step(q)))
- goto fail;
- token_object_id = sqlite3_last_insert_rowid(sqldb);
- if (!sql_check_ok(sql_finalize_and_clear(&q)) ||
- !sql_check_ok(sql_prepare(&q, update_object_token_object)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 1, token_object_id)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 2, object_id)) ||
- !sql_check_done(sqlite3_step(q)) ||
- !sql_check_ok(sql_finalize_and_clear(&q)) ||
- !sql_check_ok(sql_prepare(&q, insert_token_attribute)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 1, token_object_id)))
- goto fail;
- break;
-
- case handle_flavor_session_object:
- if (!sql_check_ok(sql_prepare(&q, insert_session_object)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 1, object_id)) ||
- !sql_check_done(sqlite3_step(q)))
- goto fail;
- session_object_id = sqlite3_last_insert_rowid(sqldb);
- if (!sql_check_ok(sql_finalize_and_clear(&q)) ||
- !sql_check_ok(sql_prepare(&q, update_object_session_object)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 1, session->handle)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 2, session_object_id)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 3, object_id)) ||
- !sql_check_done(sqlite3_step(q)) ||
- !sql_check_ok(sql_finalize_and_clear(&q)) ||
- !sql_check_ok(sql_prepare(&q, insert_session_attribute)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 1, session_object_id)))
- goto fail;
- break;
-
- default: /* Suppress GCC warning */
- goto fail;
- }
+ assert(session != NULL && template != NULL && descriptor != NULL && uuid != NULL &&
+ (extra_length == 0 || extra != NULL) &&
+ (flavor == handle_flavor_token_object || flavor == handle_flavor_session_object));
/*
- * Now populate attributes, starting with the application's
- * template, which we assume has already been blessed by the API
- * function that called this method.
+ * Populate attributes, starting with the application's template,
+ * which we assume has already been blessed by the API function that
+ * called this method.
*
* If the attribute is flagged as sensitive in the descriptor, we
- * don't store it in SQL. Generally, this only arises for private
- * key components of objects created with C_CreateObject(), but in
- * theory there are some corner cases in which a user could choose
- * to mark a private key as extractable and not sensitive, so we
- * might have to back-fill missing values in those cases if anyone
- * ever thinks up a sane reason for supporting them. For now, assume
- * that private keys are bloody well supposed to be private.
+ * don't store it as an attribute. Generally, this only arises for
+ * private key components of objects created with C_CreateObject(),
+ * but in theory there are some corner cases in which a user could
+ * choose to mark a private key as extractable and not sensitive, so
+ * we might have to back-fill missing values in those cases if
+ * anyone ever thinks up a sane reason for supporting them. For
+ * now, assume that private keys are bloody well supposed to be
+ * private.
*/
- for (i = 0; i < template_length; i++) {
+ hal_rpc_pkey_attribute_t attributes[template_length + descriptor->n_attributes + extra_length];
+ unsigned n = 0;
+
+ for (int i = 0; i < template_length; i++) {
const CK_ATTRIBUTE_TYPE type = template[i].type;
const void * val = template[i].pValue;
const int len = template[i].ulValueLen;
@@ -1417,18 +1141,20 @@ static CK_OBJECT_HANDLE p11_object_create(const p11_session_t *session,
if (p11_attribute_is_sensitive(descriptor, type))
continue;
- if (!sql_check_ok(sqlite3_reset(q)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 2, type)) ||
- !sql_check_ok(sqlite3_bind_blob( q, 3, val, len, NULL)) ||
- !sql_check_done(sqlite3_step(q)))
- goto fail;
+ if (n >= sizeof(attributes) / sizeof(*attributes))
+ lose(CKR_FUNCTION_FAILED);
+
+ attributes[n].type = type;
+ attributes[n].value = val;
+ attributes[n].length = len;
+ n++;
}
/*
* Next, add defaults from the descriptor.
*/
- for (i = 0; i < descriptor->n_attributes; i++) {
+ for (int i = 0; i < descriptor->n_attributes; i++) {
const CK_ATTRIBUTE_TYPE type = descriptor->attributes[i].type;
const void * val = descriptor->attributes[i].value;
const int len = descriptor->attributes[i].length;
@@ -1440,107 +1166,98 @@ static CK_OBJECT_HANDLE p11_object_create(const p11_session_t *session,
if (val == NULL || p11_attribute_find_in_template(type, template, template_length) >= 0)
continue;
- if (!sql_check_ok(sqlite3_reset(q)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 2, type)) ||
- !sql_check_ok(sqlite3_bind_blob( q, 3, val, len, NULL)) ||
- !sql_check_done(sqlite3_step(q)))
- goto fail;
+ if (n >= sizeof(attributes) / sizeof(*attributes))
+ lose(CKR_FUNCTION_FAILED);
+
+ attributes[n].type = type;
+ attributes[n].value = val;
+ attributes[n].length = len;
+ n++;
}
/*
- * Finally, add generation mechanism attributes as needed.
+ * Finally, add any attributes provided by the calling function itself.
*/
- if (mechanism != NULL &&
- (!sql_check_ok(sqlite3_reset(q)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 2, CKA_LOCAL)) ||
- !sql_check_ok(sqlite3_bind_blob( q, 3, &const_CK_TRUE, sizeof(const_CK_TRUE), NULL)) ||
- !sql_check_done(sqlite3_step(q)) ||
- !sql_check_ok(sqlite3_reset(q)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 2, CKA_KEY_GEN_MECHANISM)) ||
- !sql_check_ok(sqlite3_bind_blob( q, 3, &mechanism->mechanism, sizeof(mechanism->mechanism), NULL)) ||
- !sql_check_done(sqlite3_step(q))))
- goto fail;
+ for (int i = 0; i < extra_length; i++) {
+ if (n >= sizeof(attributes) / sizeof(*attributes))
+ lose(CKR_FUNCTION_FAILED);
+
+ attributes[n].type = extra[i].type;
+ attributes[n].value = extra[i].value;
+ attributes[n].length = extra[i].length;
+ n++;
+ }
/*
- * If we made it past all that, we're happy.
+ * Set all those attributes.
*/
- ok = 1;
-
- fail:
- sqlite3_finalize(q);
- return ok ? object_handle : CK_INVALID_HANDLE;
-}
-
-/*
- * Bind PKCS #11 objects to keystore objects, via the key's pkey type
- * and UUID.
- */
-
-static int p11_object_bind_pkey(const p11_session_t * const session,
- const CK_OBJECT_HANDLE object_handle,
- const hal_uuid_t * const pkey_uuid)
-{
- assert(session != NULL && pkey_uuid != NULL);
-
- static const char update_format[] =
- " UPDATE %s_object SET hal_pkey_uuid = ?1"
- " WHERE %s_object_id = (SELECT %s_object_id FROM object WHERE object_handle = ?2)";
+ if (!hal_check(hal_rpc_pkey_set_attributes(pkey, attributes, n)))
+ lose(CKR_FUNCTION_FAILED);
- const char *flavor = is_token_handle(object_handle) ? "token" : "session";
- sqlite3_stmt *q = NULL;
+ /*
+ * Create the object handle, then we're done.
+ */
- int ok = (sql_check_ok(sql_prepare(&q, update_format, flavor, flavor, flavor)) &&
- sql_check_ok(sqlite3_bind_blob( q, 1, pkey_uuid, sizeof(*pkey_uuid), NULL)) &&
- sql_check_ok(sqlite3_bind_int64(q, 2, object_handle)) &&
- sql_check_done(sqlite3_step(q)));
+ return p11_object_allocate(flavor, uuid, session);
- sqlite3_finalize(q);
- return ok;
+ fail:
+ return CK_INVALID_HANDLE;
}
/*
* Create pkeys to go with PKCS #11 key objects loaded by C_CreateObject().
*/
-static inline int p11_object_create_rsa_public_key(const p11_session_t * const session,
- const CK_OBJECT_HANDLE object_handle,
- const hal_key_flags_t flags)
+static int p11_object_create_rsa_public_key(const p11_session_t * const session,
+ const handle_flavor_t flavor,
+ const CK_ATTRIBUTE_PTR template,
+ const CK_ULONG template_len,
+ const p11_descriptor_t * const descriptor,
+ CK_OBJECT_HANDLE_PTR phObject,
+ const hal_key_flags_t flags)
{
- static const char select_format[] =
- " WITH a (type, value) "
- " AS (SELECT type, value FROM %s_attribute NATURAL JOIN object WHERE object_handle = ?1)"
- " SELECT a1.value, a2.value FROM a AS a1, a AS a2 WHERE a1.type = %u AND a2.type = %u";
-
- const char *flavor = is_token_handle(object_handle) ? "token" : "session";
+ const hal_rpc_pkey_attributes extra[] = {
+ {.type = CKA_LOCAL, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)}
+ };
hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
uint8_t keybuf[hal_rsa_key_t_size];
hal_rsa_key_t *key = NULL;
- sqlite3_stmt *q = NULL;
- int ok
- = (sql_check_ok(sql_prepare(&q, select_format, flavor, CKA_MODULUS, CKA_PUBLIC_EXPONENT)) &&
- sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) &&
- sql_check_row(sqlite3_step(q)) &&
- sqlite3_column_type(q, 0) == SQLITE_BLOB &&
- sqlite3_column_type(q, 1) == SQLITE_BLOB &&
- hal_check(hal_rsa_key_load_public(&key, keybuf, sizeof(keybuf),
- sqlite3_column_blob( q, 0),
- sqlite3_column_bytes(q, 0),
- sqlite3_column_blob( q, 1),
- sqlite3_column_bytes(q, 1))));
+ const uint8_t *cka_modulus = NULL;
+ size_t cka_modulus_len = 0;
+ const uint8_t *cka_public_exponent = const_0x010001;
+ size_t cka_public_exponent_len = sizeof(const_0x010001);
+
+ for (int i = 0; i < template_len; i++) {
+ const void * const val = template[i].pValue;
+ const size_t len = template[i].ulValueLen;
+ switch (template[i].type) {
+ case CKA_MODULUS: cka_modulus = val; cka_modulus_len = len; break;
+ case CKA_PUBLIC_EXPONENT: cka_public_exponent = val; cka_public_exponent_len = len; break;
+ }
+ }
+
+ int ok = hal_check(hal_rsa_key_load_public(&key, keybuf, sizeof(keybuf),
+ cka_modulus, cka_modulus_len,
+ cka_public_exponent, cka_public_exponent_len));
if (ok) {
uint8_t der[hal_rsa_public_key_to_der_len(key)];
hal_uuid_t uuid;
- ok = (hal_check(hal_rsa_public_key_to_der(key, der, NULL, sizeof(der))) &&
+ ok = (hal_check(hal_rsa_public_key_to_der(key, der, NULL, sizeof(der))) &&
hal_check(hal_rpc_pkey_load(p11_session_hal_client(session),
p11_session_hal_session(session),
&pkey, HAL_KEY_TYPE_RSA_PUBLIC, HAL_CURVE_NONE,
- &uuid, der, sizeof(der), flags)) &&
- p11_object_bind_pkey(session, object_handle, &uuid));
+ &uuid, der, sizeof(der), flags)));
+ }
+
+ if (ok) {
+ *phObject = p11_object_create(session, pkey, &uuid, flavor, template, template_len,
+ descriptor, extra, sizeof(extra)/sizeof(*extra));
+ ok = *phObject != CK_INVALID_HANDLE;
}
if (!ok && pkey.handle != HAL_HANDLE_NONE)
@@ -1548,48 +1265,58 @@ static inline int p11_object_create_rsa_public_key(const p11_session_t * const s
else
(void) hal_rpc_pkey_close(pkey);
- sqlite3_finalize(q);
return ok;
}
-static inline int p11_object_create_ec_public_key(const p11_session_t * const session,
- const CK_OBJECT_HANDLE object_handle,
- const hal_key_flags_t flags)
+static int p11_object_create_ec_public_key(const p11_session_t * const session,
+ const handle_flavor_t flavor,
+ const CK_ATTRIBUTE_PTR template,
+ const CK_ULONG template_len,
+ const p11_descriptor_t * const descriptor,
+ CK_OBJECT_HANDLE_PTR phObject,
+ const hal_key_flags_t flags)
{
- static const char select_format[] =
- " WITH a (type, value) "
- " AS (SELECT type, value FROM %s_attribute NATURAL JOIN object WHERE object_handle = ?1)"
- " SELECT a1.value, a2.value FROM a AS a1, a AS a2 WHERE a1.type = %u AND a2.type = %u";
-
- const char *flavor = is_token_handle(object_handle) ? "token" : "session";
+ const hal_rpc_pkey_attributes extra[] = {
+ {.type = CKA_LOCAL, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)}
+ };
hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
uint8_t keybuf[hal_ecdsa_key_t_size];
hal_ecdsa_key_t *key = NULL;
hal_curve_name_t curve;
- sqlite3_stmt *q = NULL;
+
+ const uint8_t *cka_ec_point = NULL; size_t cka_ec_point_len = 0;
+ const uint8_t *cka_ec_params = NULL; size_t cka_ec_params_len = 0;
+
+ for (int i = 0; i < template_len; i++) {
+ const void * const val = template[i].pValue;
+ const size_t len = template[i].ulValueLen;
+ switch (template[i].type) {
+ case CKA_EC_POINT: cka_ec_point = val; cka_ec_point_len = len; break;
+ case CKA_EC_PARAMS: cka_ec_params = val; cka_ec_params_len = len; break;
+ }
+ }
int ok
- = (sql_check_ok(sql_prepare(&q, select_format, flavor, CKA_EC_PARAMS, CKA_EC_POINT)) &&
- sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) &&
- sql_check_row(sqlite3_step(q)) &&
- sqlite3_column_type(q, 0) == SQLITE_BLOB &&
- sqlite3_column_type(q, 1) == SQLITE_BLOB &&
- ec_curve_oid_to_name(sqlite3_column_blob( q, 0), sqlite3_column_bytes(q, 0), &curve) &&
+ = (ec_curve_oid_to_name(cka_ec_params, cka_ec_params_len, &curve) &&
hal_check(hal_ecdsa_key_from_ecpoint(&key, keybuf, sizeof(keybuf),
- sqlite3_column_blob( q, 1),
- sqlite3_column_bytes(q, 1),
+ cka_ec_point, cka_ec_point_len,
curve)));
if (ok) {
uint8_t der[hal_ecdsa_public_key_to_der_len(key)];
hal_uuid_t uuid;
- ok = (hal_check(hal_ecdsa_public_key_to_der(key, der, NULL, sizeof(der))) &&
+ ok = (hal_check(hal_ecdsa_public_key_to_der(key, der, NULL, sizeof(der))) &&
hal_check(hal_rpc_pkey_load(p11_session_hal_client(session),
p11_session_hal_session(session),
&pkey, HAL_KEY_TYPE_EC_PUBLIC, curve,
- &uuid, der, sizeof(der), flags)) &&
- p11_object_bind_pkey(session, object_handle, &uuid));
+ &uuid, der, sizeof(der), flags)));
+ }
+
+ if (ok) {
+ *phObject = p11_object_create(session, pkey, &uuid, flavor, template, template_len,
+ descriptor, extra, sizeof(extra)/sizeof(*extra));
+ ok = *phObject != CK_INVALID_HANDLE;
}
if (!ok && pkey.handle != HAL_HANDLE_NONE)
@@ -1597,193 +1324,157 @@ static inline int p11_object_create_ec_public_key(const p11_session_t * const se
else
(void) hal_rpc_pkey_close(pkey);
- sqlite3_finalize(q);
return ok;
}
-static inline int p11_object_create_rsa_private_key(const p11_session_t * const session,
- const CK_OBJECT_HANDLE object_handle,
- const hal_key_flags_t flags,
- const CK_ATTRIBUTE_PTR template,
- const CK_ULONG template_len)
+static int p11_object_create_rsa_private_key(const p11_session_t * const session,
+ const handle_flavor_t flavor,
+ const CK_ATTRIBUTE_PTR template,
+ const CK_ULONG template_len,
+ const p11_descriptor_t * const descriptor,
+ CK_OBJECT_HANDLE_PTR phObject,
+ const hal_key_flags_t flags)
{
- static const char select_format[] =
- " WITH a (type, value) "
- " AS (SELECT type, value FROM %s_attribute NATURAL JOIN object WHERE object_handle = ?1)"
- " SELECT a1.value, a2.value FROM a AS a1, a AS a2 WHERE a1.type = %u AND a2.type = %u";
-
- const char *flavor = is_token_handle(object_handle) ? "token" : "session";
+ const hal_rpc_pkey_attributes extra[] = {
+ {.type = CKA_LOCAL, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)},
+ {.type = CKA_ALWAYS_SENSITIVE, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)},
+ {.type = CKA_NEVER_EXTRACTABLE, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)}
+ };
hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
uint8_t keybuf[hal_rsa_key_t_size];
hal_rsa_key_t *key = NULL;
- sqlite3_stmt *q = NULL;
+ hal_uuid_t uuid;
+ const uint8_t *cka_modulus = NULL; size_t cka_modulus_len = 0;
const uint8_t *cka_private_exponent = NULL; size_t cka_private_exponent_len = 0;
- const uint8_t *cka_prime_1 = NULL; size_t cka_prime_1_len = 0;
- const uint8_t *cka_prime_2 = NULL; size_t cka_prime_2_len = 0;
- const uint8_t *cka_exponent_1 = NULL; size_t cka_exponent_1_len = 0;
- const uint8_t *cka_exponent_2 = NULL; size_t cka_exponent_2_len = 0;
- const uint8_t *cka_coefficient = NULL; size_t cka_coefficient_len = 0;
+ const uint8_t *cka_prime_1 = NULL; size_t cka_prime_1_len = 0;
+ const uint8_t *cka_prime_2 = NULL; size_t cka_prime_2_len = 0;
+ const uint8_t *cka_exponent_1 = NULL; size_t cka_exponent_1_len = 0;
+ const uint8_t *cka_exponent_2 = NULL; size_t cka_exponent_2_len = 0;
+ const uint8_t *cka_coefficient = NULL; size_t cka_coefficient_len = 0;
+
+ const uint8_t *cka_public_exponent = const_0x010001;
+ size_t cka_public_exponent_len = sizeof(const_0x010001);
for (int i = 0; i < template_len; i++) {
+ const void * const val = template[i].pValue;
+ const size_t len = template[i].ulValueLen;
switch (template[i].type) {
- case CKA_PRIVATE_EXPONENT:
- cka_private_exponent = template[i].pValue; cka_private_exponent_len = template[i].ulValueLen;
- break;
- case CKA_PRIME_1:
- cka_prime_1 = template[i].pValue; cka_prime_1_len = template[i].ulValueLen;
- break;
- case CKA_PRIME_2:
- cka_prime_2 = template[i].pValue; cka_prime_2_len = template[i].ulValueLen;
- break;
- case CKA_EXPONENT_1:
- cka_exponent_1 = template[i].pValue; cka_exponent_1_len = template[i].ulValueLen;
- break;
- case CKA_EXPONENT_2:
- cka_exponent_2 = template[i].pValue; cka_exponent_2_len = template[i].ulValueLen;
- break;
- case CKA_COEFFICIENT:
- cka_coefficient = template[i].pValue; cka_coefficient_len = template[i].ulValueLen;
- break;
+ case CKA_MODULUS: cka_modulus = val; cka_modulus_len = len; break;
+ case CKA_PUBLIC_EXPONENT: cka_public_exponent = val; cka_public_exponent_len = len; break;
+ case CKA_PRIVATE_EXPONENT: cka_private_exponent = val; cka_private_exponent_len = len; break;
+ case CKA_PRIME_1: cka_prime_1 = val; cka_prime_1_len = len; break;
+ case CKA_PRIME_2: cka_prime_2 = val; cka_prime_2_len = len; break;
+ case CKA_EXPONENT_1: cka_exponent_1 = val; cka_exponent_1_len = len; break;
+ case CKA_EXPONENT_2: cka_exponent_2 = val; cka_exponent_2_len = len; break;
+ case CKA_COEFFICIENT: cka_coefficient = val; cka_coefficient_len = len; break;
}
}
- int ok
- = (sql_check_ok(sql_prepare(&q, select_format, flavor, CKA_MODULUS, CKA_PUBLIC_EXPONENT)) &&
- sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) &&
- sql_check_row(sqlite3_step(q)) &&
- sqlite3_column_type(q, 0) == SQLITE_BLOB &&
- sqlite3_column_type(q, 1) == SQLITE_BLOB &&
- hal_check(hal_rsa_key_load_private(&key, keybuf, sizeof(keybuf),
- sqlite3_column_blob( q, 0), sqlite3_column_bytes(q, 0),
- sqlite3_column_blob( q, 1), sqlite3_column_bytes(q, 1),
- cka_private_exponent, cka_private_exponent_len,
- cka_prime_1, cka_prime_1_len,
- cka_prime_2, cka_prime_2_len,
- cka_coefficient, cka_coefficient_len,
- cka_exponent_1, cka_exponent_1_len,
- cka_exponent_2, cka_exponent_2_len)));
-
+ int ok = hal_check(hal_rsa_key_load_private(&key, keybuf, sizeof(keybuf),
+ cka_modulus, cka_modulus_len,
+ cka_public_exponent, cka_public_exponent_len,
+ cka_private_exponent, cka_private_exponent_len,
+ cka_prime_1, cka_prime_1_len,
+ cka_prime_2, cka_prime_2_len,
+ cka_coefficient, cka_coefficient_len,
+ cka_exponent_1, cka_exponent_1_len,
+ cka_exponent_2, cka_exponent_2_len));
if (ok) {
uint8_t der[hal_rsa_private_key_to_der_len(key)];
- hal_uuid_t uuid;
- ok = (hal_check(hal_rsa_private_key_to_der(key, der, NULL, sizeof(der))) &&
+ ok = (hal_check(hal_rsa_private_key_to_der(key, der, NULL, sizeof(der))) &&
hal_check(hal_rpc_pkey_load(p11_session_hal_client(session),
p11_session_hal_session(session),
- &pkey, HAL_KEY_TYPE_RSA_PRIVATE, HAL_CURVE_NONE,
- &uuid, der, sizeof(der), flags)) &&
- p11_object_bind_pkey(session, object_handle, &uuid));
+ &pkey, HAL_KEY_TYPE_RSA_PRIVATE,
+ HAL_CURVE_NONE, &uuid,
+ der, sizeof(der), flags)));
memset(der, 0, sizeof(der));
}
memset(keybuf, 0, sizeof(keybuf));
+ if (ok) {
+ *phObject = p11_object_create(session, pkey, &uuid, flavor, template, template_len,
+ descriptor, extra, sizeof(extra)/sizeof(*extra));
+ ok = *phObject != CK_INVALID_HANDLE;
+ }
+
if (!ok && pkey.handle != HAL_HANDLE_NONE)
(void) hal_rpc_pkey_delete(pkey);
else
(void) hal_rpc_pkey_close(pkey);
- sqlite3_finalize(q);
return ok;
}
-static inline int p11_object_create_ec_private_key(const p11_session_t * const session,
- const CK_OBJECT_HANDLE object_handle,
- const hal_key_flags_t flags,
- const CK_ATTRIBUTE_PTR template,
- const CK_ULONG template_len)
+static int p11_object_create_ec_private_key(const p11_session_t * const session,
+ const handle_flavor_t flavor,
+ const CK_ATTRIBUTE_PTR template,
+ const CK_ULONG template_len,
+ const p11_descriptor_t * const descriptor,
+ CK_OBJECT_HANDLE_PTR phObject,
+ const hal_key_flags_t flags)
{
- static const char select_format[] =
- " WITH a (type, value) "
- " AS (SELECT type, value FROM %s_attribute NATURAL JOIN object WHERE object_handle = ?1)"
- " SELECT a1.value, a2.value FROM a AS a1, a AS a2 WHERE a1.type = %u AND a2.type = %u";
-
- const char *flavor = is_token_handle(object_handle) ? "token" : "session";
+ const hal_rpc_pkey_attributes extra[] = {
+ {.type = CKA_LOCAL, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)},
+ {.type = CKA_ALWAYS_SENSITIVE, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)},
+ {.type = CKA_NEVER_EXTRACTABLE, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)}
+ };
hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
uint8_t keybuf[hal_ecdsa_key_t_size];
hal_ecdsa_key_t *key = NULL;
hal_curve_name_t curve;
- sqlite3_stmt *q = NULL;
- const uint8_t *ecpoint = NULL;
- size_t ecpoint_len = 0;
- const uint8_t *cka_value = NULL; size_t cka_value_len = 0;
+ const uint8_t *cka_value = NULL; size_t cka_value_len = 0;
+ const uint8_t *cka_ec_point = NULL; size_t cka_ec_point_len = 0;
+ const uint8_t *cka_ec_params = NULL; size_t cka_ec_params_len = 0;
- for (int i = 0; i < template_len; i++)
- if (template[i].type == CKA_VALUE)
- cka_value = template[i].pValue, cka_value_len = template[i].ulValueLen;
+ for (int i = 0; i < template_len; i++) {
+ const void * const val = template[i].pValue;
+ const size_t len = template[i].ulValueLen;
+ switch (template[i].type) {
+ case CKA_VALUE: cka_value = val; cka_value_len = len; break;
+ case CKA_EC_POINT: cka_ec_point = val; cka_ec_point_len = len; break;
+ case CKA_EC_PARAMS: cka_ec_params = val; cka_ec_params_len = len; break;
+ }
+ }
int ok
- = (sql_check_ok(sql_prepare(&q, select_format, flavor, CKA_EC_PARAMS, CKA_EC_POINT)) &&
- sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) &&
- sql_check_row(sqlite3_step(q)) &&
- sqlite3_column_type(q, 0) == SQLITE_BLOB &&
- sqlite3_column_type(q, 1) == SQLITE_BLOB &&
- ec_curve_oid_to_name(sqlite3_column_blob( q, 0), sqlite3_column_bytes(q, 0), &curve) &&
- ((ecpoint_len = sqlite3_column_bytes(q, 1)) & 1) != 0 &&
- *(ecpoint = sqlite3_column_blob( q, 1)) == 0x04 &&
+ = (ec_curve_oid_to_name(cka_ec_params, cka_ec_params_len, &curve) &&
hal_check(hal_ecdsa_key_load_private(&key, keybuf, sizeof(keybuf), curve,
- ecpoint + 1 + 0 * ecpoint_len / 2, ecpoint_len / 2,
- ecpoint + 1 + 0 * ecpoint_len / 2, ecpoint_len / 2,
- cka_value, cka_value_len)));
+ cka_ec_point + 1 + 0 * cka_ec_point_len / 2,
+ cka_ec_point_len / 2,
+ cka_ec_point + 1 + 1 * cka_ec_point_len / 2,
+ cka_ec_point_len / 2,
+ cka_value,
+ cka_value_len)));
if (ok) {
uint8_t der[hal_ecdsa_private_key_to_der_len(key)];
hal_uuid_t uuid;
- ok = (hal_check(hal_ecdsa_private_key_to_der(key, der, NULL, sizeof(der))) &&
+ ok = (hal_check(hal_ecdsa_private_key_to_der(key, der, NULL, sizeof(der))) &&
hal_check(hal_rpc_pkey_load(p11_session_hal_client(session),
p11_session_hal_session(session),
&pkey, HAL_KEY_TYPE_EC_PRIVATE, curve,
- &uuid, der, sizeof(der), flags)) &&
- p11_object_bind_pkey(session, object_handle, &uuid));
+ &uuid, der, sizeof(der), flags)));
memset(der, 0, sizeof(der));
}
memset(keybuf, 0, sizeof(keybuf));
+ if (ok) {
+ *phObject = p11_object_create(session, pkey, &uuid, flavor, template, template_len,
+ descriptor, extra, sizeof(extra)/sizeof(*extra));
+ ok = *phObject != CK_INVALID_HANDLE;
+ }
+
if (!ok && pkey.handle != HAL_HANDLE_NONE)
(void) hal_rpc_pkey_delete(pkey);
else
(void) hal_rpc_pkey_close(pkey);
- sqlite3_finalize(q);
- return ok;
-}
-
-/*
- * Given a PKCS #11 object, obtain a libhal pkey handle.
- */
-
-static int p11_object_get_pkey_handle(const p11_session_t * const session,
- const CK_OBJECT_HANDLE object_handle,
- hal_pkey_handle_t *pkey_handle)
-{
- static const char select_format[] =
- " SELECT hal_pkey_uuid FROM %s_object NATURAL JOIN object WHERE object_handle = ?1";
-
- hal_key_flags_t flags = is_token_handle(object_handle) ? HAL_KEY_FLAG_TOKEN : 0;
- const char *flavor = is_token_handle(object_handle) ? "token" : "session";
- sqlite3_stmt *q = NULL;
- int ok = 0;
-
- assert(pkey_handle != NULL);
-
- if (!sql_check_ok(sql_prepare(&q, select_format, flavor)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) ||
- !sql_check_row(sqlite3_step(q)) ||
- sqlite3_column_type(q, 0) != SQLITE_BLOB ||
- sqlite3_column_bytes(q, 0) != sizeof(hal_uuid_t))
- goto fail;
-
- const hal_uuid_t * const pkey_uuid = sqlite3_column_blob(q, 0);
-
- ok = hal_check(hal_rpc_pkey_open(p11_session_hal_client(session), p11_session_hal_session(session),
- pkey_handle, pkey_uuid, flags));
-
- fail:
- sqlite3_finalize(q);
return ok;
}
@@ -1797,12 +1488,32 @@ static int p11_object_get_pkey_handle(const p11_session_t * const session,
* Create a new session.
*/
-static p11_session_t *p11_session_new(void)
+static p11_session_t *p11_session_allocate(void)
{
- p11_session_t *session = malloc(sizeof(*session));
- if (session == NULL)
+ static unsigned next_index, nonce;
+ const unsigned last_index = next_index;
+ p11_session_t *session = NULL;
+
+ if (p11_sessions_in_use >= sizeof(p11_sessions) / sizeof(*p11_sessions))
return NULL;
+
+ do {
+
+ next_index = (next_index + 1) % (sizeof(p11_sessions) / sizeof(*p11_sessions));
+
+ if (next_index == last_index)
+ return NULL;
+
+ if (next_index == 0)
+ ++nonce;
+
+ session = p11_sessions[next_index];
+
+ } while (session.handle == CK_INVALID_HANDLE);
+
memset(session, 0, sizeof(*session));
+ session.handle = handle_compose(handle_flavor_session, nonce, next_handle);
+ p11_sessions_in_use++;
return session;
}
@@ -1815,137 +1526,89 @@ static void p11_session_free(p11_session_t *session)
if (session == NULL)
return;
- sql_finalize_and_clear(&session->find_query);
+ assert(p11_sessions_in_use > 0);
+
+ if (session->find_query)
+ free(session->find_query);
+
(void) hal_rpc_hash_finalize(session->digest_handle, NULL, 0);
(void) hal_rpc_hash_finalize(session->sign_digest_handle, NULL, 0);
(void) hal_rpc_hash_finalize(session->verify_digest_handle, NULL, 0);
- free(session);
+
+ memset(session, 0, sizeof(*session));
+
+ if (--p11_sessions_in_use == 0)
+ logged_in_as = not_logged_in;
}
/*
- * Assign a handle to a session and add the session to SQL.
+ * Find a session.
*/
-static int p11_session_add(p11_session_t *session)
+static p11_session_t *p11_session_find(const CK_SESSION_HANDLE session_handle)
{
- static const char insert_session[] =
- " INSERT INTO session (session_handle) VALUES (?)";
-
- sqlite3_stmt *q = NULL;
- int ok = 0;
+ if (handle_flavor(session_handle) != handle_flavor_session)
+ return NULL;
- assert(session != NULL);
+ const unsigned index = handle_index(session_handle);
- session->handle = p11_allocate_unused_handle(handle_flavor_session);
+ if (index >= sizeof(p11_sessions) / sizeof(*p11_sessions))
+ return NULL;
- if (!sql_check_ok(sql_prepare(&q, insert_session)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 1, session->handle)) ||
- !sql_check_done(sqlite3_step(q)))
- goto fail;
+ p11_session_t *session = &p11_sessions[index];
- session->link = p11_sessions;
- p11_sessions = session;
- ok = 1;
+ if (session->handle != session_handle)
+ return NULL;
- fail:
- sqlite3_finalize(q);
- return ok;
+ return session;
}
/*
- * Find a session.
+ * Iterate over session handles. Start with CK_INVALID_HANDLE,
+ * returns CK_INVALID_HANDLE when done.
*
- * Since we don't expect the total number of sessions to be all that
- * high, we use a linked list with a move-to-the-front search. Some
- * of the other session methods assume this behavior, so be careful if
- * you decide to change it.
+ * This does not verify the provided session handle, because we want
+ * to be able to modify the sessions this finds, including deleting
+ * them (which invalidates the session handle). Don't trust the
+ * returned handle until it has been blessed by p11_session_find().
*/
-static p11_session_t *p11_session_find(const CK_SESSION_HANDLE session_handle)
+static CK_SESSION_HANDLE p11_session_handle_iterate(const CK_SESSION_HANDLE session_handle)
{
- p11_session_t **link, *session;
-
- for (link = &p11_sessions;
- (session = *link) != NULL && session->handle != session_handle;
- link = &session->link)
- ;
+ if (handle_flavor(session_handle) != handle_flavor_session)
+ return CK_HANDLE_INVALID;
- if (session != NULL && link != &p11_sessions) {
- *link = session->link;
- session->link = p11_sessions;
- p11_sessions = session;
- }
+ for (unsigned index = session_handle == CK_INVALID_HANDLE ? 0 : handle_index(session_handle) + 1;
+ index < sizeof(p11_sessions) / sizeof(*p11_sessions);
+ index++)
+ if (handle_flavor(p11_sessions[index].handle) == handle_flavor_session)
+ return p11_sessions[index].handle;
- return session;
+ return CK_HANDLE_INVALID;
}
/*
- * Delete a session: remove it from SQL and free the session data
- * structure.
- *
- * This method assumes the move-to-the-front behavior of
- * p11_session_find().
+ * Same thing, but return session objects instead of session handles.
+ * This is just syntactic sugar around a common idiom.
*/
-static CK_RV p11_session_delete(const CK_SESSION_HANDLE session_handle)
+static p11_session_t *p11_session_iterate(p11_session_t *session)
{
- static const char delete_session[] =
- " DELETE FROM session WHERE session_handle = ?";
-
- p11_session_t *session = p11_session_find(session_handle);
- sqlite3_stmt *q = NULL;
- CK_RV rv = CKR_OK;
-
if (session == NULL)
- return CKR_SESSION_HANDLE_INVALID;
-
- if (!sql_check_ok(sql_prepare(&q, delete_session)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 1, session_handle)) ||
- !sql_check_done(sqlite3_step(q)))
- lose(CKR_FUNCTION_FAILED);
-
- /* Check that move-to-the-front behaved as expected */
- assert(p11_sessions == session);
-
- p11_sessions = session->link;
- p11_session_free(session);
-
- /* Deleting last session also logs us out */
- if (p11_sessions == NULL)
- logged_in_as = not_logged_in;
+ return NULL;
- fail:
- sqlite3_finalize(q);
- return rv;
+ return p11_session_find(p11_session_handle_iterate(session->handle));
}
/*
- * Delete all sessions.
+ * Delete all sessions. Have to use p11_session_handle_iterate() here.
*/
-#warning Should this also clear the object table?
-
-static CK_RV p11_session_delete_all(void)
+static void p11_session_free_all(void)
{
- static const char delete_all_sessions[] =
- " DELETE FROM session";
-
- p11_session_t *session;
- CK_RV rv = CKR_OK;
-
- if (!sql_exec(delete_all_sessions))
- lose(CKR_FUNCTION_FAILED);
-
- while (p11_sessions != NULL) {
- session = p11_sessions;
- p11_sessions = session->link;
- p11_session_free(session);
- }
-
- logged_in_as = not_logged_in;
-
- fail:
- return rv;
+ for (CK_SESSION_HANDLE handle = p11_session_handle_iterate(CK_INVALID_HANDLE);
+ handle != CK_INVALID_HANDLE; handle = p11_session_handle_iterate(handle))
+ p11_session_free(p11_session_find(handle));
}
/*
@@ -1956,24 +1619,25 @@ static CK_RV p11_session_delete_all(void)
static int p11_session_consistent_login(void)
{
- p11_session_t *session;
-
switch (logged_in_as) {
case not_logged_in:
- for (session = p11_sessions; session != NULL; session = session->link)
+ for (p11_session_t *session = p11_session_iterate(NULL);
+ session != NULL; session = p11_session_iterate(session))
if (session->state != CKS_RO_PUBLIC_SESSION && session->state != CKS_RW_PUBLIC_SESSION)
return 0;
return 1;
case logged_in_as_user:
- for (session = p11_sessions; session != NULL; session = session->link)
+ for (p11_session_t *session = p11_session_iterate(NULL);
+ session != NULL; session = p11_session_iterate(session))
if (session->state != CKS_RO_USER_FUNCTIONS && session->state != CKS_RW_USER_FUNCTIONS)
return 0;
return 1;
case logged_in_as_so:
- for (session = p11_sessions; session != NULL; session = session->link)
+ for (p11_session_t *session = p11_session_iterate(NULL);
+ session != NULL; session = p11_session_iterate(session))
if (session->state != CKS_RW_SO_FUNCTIONS)
return 0;
return 1;
@@ -2255,27 +1919,33 @@ static CK_RV p11_check_keypair_attributes(const p11_session_t *session,
*/
static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session,
+ const handle_flavor_t public_handle_flavor,
const CK_ATTRIBUTE_PTR pPublicKeyTemplate,
const CK_ULONG ulPublicKeyAttributeCount,
- const CK_OBJECT_HANDLE public_handle,
+ const p11_descriptor_t *public_descriptor,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
const hal_key_flags_t public_flags,
+ const handle_flavor_t private_handle_flavor,
const CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
const CK_ULONG ulPrivateKeyAttributeCount,
- const CK_OBJECT_HANDLE private_handle,
- const hal_key_flags_t private_flags)
+ const p11_descriptor_t *private_descriptor,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ const hal_key_flags_t private_flags,
+ const CK_MECHANISM_PTR pMechanism)
{
- const int same_keystore = is_token_handle(public_handle) == is_token_handle(private_handle);
+ hal_pkey_handle_t public_pkey = {HAL_HANDLE_NONE}, private_pkey = {HAL_HANDLE_NONE};
const uint8_t *public_exponent = const_0x010001;
size_t public_exponent_len = sizeof(const_0x010001);
- hal_pkey_handle_t pkey1 = {HAL_HANDLE_NONE}, pkey2 = {HAL_HANDLE_NONE};
+ hal_uuid_t public_uuid, private_uuid;
CK_ULONG keysize = 0;
- hal_uuid_t uuid;
CK_RV rv;
- int i;
- assert(session != NULL && pPublicKeyTemplate != NULL && pPrivateKeyTemplate != NULL);
+ assert(pPublicKeyTemplate != NULL && pPrivateKeyTemplate != NULL &&
+ public_descriptor != NULL && private_descriptor != NULL &&
+ phPublicKey != NULL && phPrivateKey != NULL &&
+ session != NULL && pMechanism != NULL);
- for (i = 0; i < ulPublicKeyAttributeCount; i++) {
+ for (int i = 0; i < ulPublicKeyAttributeCount; i++) {
const CK_ATTRIBUTE_TYPE type = pPublicKeyTemplate[i].type;
const void * const val = pPublicKeyTemplate[i].pValue;
const size_t len = pPublicKeyTemplate[i].ulValueLen;
@@ -2298,47 +1968,58 @@ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session,
if (keysize == 0)
return CKR_TEMPLATE_INCOMPLETE;
- if (!hal_check(hal_rpc_pkey_generate_rsa(p11_session_hal_client(session),
- p11_session_hal_session(session),
- &pkey1, &uuid, keysize,
- public_exponent, public_exponent_len,
- private_flags)) ||
- !p11_object_bind_pkey(session, private_handle, &uuid))
- lose(CKR_FUNCTION_FAILED);
-
{
- uint8_t der[hal_rpc_pkey_get_public_key_len(pkey1)], keybuf[hal_rsa_key_t_size];
+ if (!hal_check(hal_rpc_pkey_generate_rsa(p11_session_hal_client(session),
+ p11_session_hal_session(session),
+ &private_pkey, &private_uuid, keysize,
+ public_exponent, public_exponent_len,
+ private_flags)))
+ lose(CKR_FUNCTION_FAILED);
+
+ uint8_t der[hal_rpc_pkey_get_public_key_len(private_pkey)], keybuf[hal_rsa_key_t_size];
size_t der_len, modulus_len;
hal_rsa_key_t *key = NULL;
- if (!hal_check(hal_rpc_pkey_get_public_key(pkey1, der, &der_len, sizeof(der))) ||
+ if (!hal_check(hal_rpc_pkey_get_public_key(private_pkey, der, &der_len, sizeof(der))) ||
!hal_check(hal_rsa_public_key_from_der(&key, keybuf, sizeof(keybuf), der, der_len)) ||
+ !hal_check(hal_rpc_pkey_load(p11_session_hal_client(session),
+ p11_session_hal_session(session),
+ &public_pkey, HAL_KEY_TYPE_RSA_PUBLIC, HAL_CURVE_NONE,
+ &public_uuid, der, der_len, public_flags)) ||
!hal_check(hal_rsa_key_get_modulus(key, NULL, &modulus_len, 0)))
lose(CKR_FUNCTION_FAILED);
uint8_t modulus[modulus_len];
- if (!hal_check(hal_rsa_key_get_modulus(key, modulus, NULL, sizeof(modulus))) ||
- !p11_attribute_set(public_handle, CKA_MODULUS, modulus, modulus_len) ||
- !p11_attribute_set(private_handle, CKA_MODULUS, modulus, modulus_len))
+ if (!hal_check(hal_rsa_key_get_modulus(key, modulus, NULL, sizeof(modulus))))
lose(CKR_FUNCTION_FAILED);
- if (!same_keystore &&
- !hal_check(hal_rpc_pkey_load(p11_session_hal_client(session),
- p11_session_hal_session(session),
- &pkey2, HAL_KEY_TYPE_RSA_PUBLIC, HAL_CURVE_NONE,
- &uuid, der, der_len, public_flags)))
+ const hal_rpc_pkey_attribute_t extra[] = {
+ {.type = CKA_LOCAL,
+ .value = &const_CK_TRUE, .length = sizeof(const_CK_TRUE)},
+ {.type = CKA_KEY_GEN_MECHANISM,
+ .value = &mechanism->mechanism, .length = sizeof(mechanism->mechanism)},
+ {.type = CKA_MODULUS,
+ value = modulus, .length = modulus_len}
+ };
+
+ *phPrivateKey = p11_object_create(session, private_pkey, &private_uuid, private_handle_flavor,
+ pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+ private_descriptor, extra, sizeof(extra)/sizeof(*extra));
+
+ *phPublicKey = p11_object_create(session, public_handle_flavor,
+ pPublicKeyTemplate, ulPublicKeyAttributeCount,
+ public_descriptor, extra, sizeof(extra)/sizeof(*extra));
+
+ if (*phPrivateKey == CK_INVALID_HANDLE || *phPublicKey == CK_INVALID_HANDLE)
lose(CKR_FUNCTION_FAILED);
}
- if (!p11_object_bind_pkey(session, public_handle, &uuid))
- lose(CKR_FUNCTION_FAILED);
-
rv = CKR_OK;
fail:
- hal_rpc_pkey_close(pkey1);
- hal_rpc_pkey_close(pkey2);
+ hal_rpc_pkey_close(private_pkey);
+ hal_rpc_pkey_close(public_pkey);
return rv;
}
@@ -2347,27 +2028,30 @@ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session,
*/
static CK_RV generate_keypair_ec(p11_session_t *session,
+ const handle_flavor_t public_handle_flavor,
const CK_ATTRIBUTE_PTR pPublicKeyTemplate,
const CK_ULONG ulPublicKeyAttributeCount,
- const CK_OBJECT_HANDLE public_handle,
+ const p11_descriptor_t *public_descriptor,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
const hal_key_flags_t public_flags,
+ const handle_flavor_t private_handle_flavor,
const CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
const CK_ULONG ulPrivateKeyAttributeCount,
- const CK_OBJECT_HANDLE private_handle,
- const hal_key_flags_t private_flags)
+ const p11_descriptor_t *private_descriptor,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ const hal_key_flags_t private_flags,
+ const CK_MECHANISM_PTR pMechanism)
{
- const int same_keystore = is_token_handle(public_handle) == is_token_handle(private_handle);
- hal_pkey_handle_t pkey1 = {HAL_HANDLE_NONE}, pkey2 = {HAL_HANDLE_NONE};
+ hal_pkey_handle_t public_pkey = {HAL_HANDLE_NONE}, private_pkey = {HAL_HANDLE_NONE};
const CK_BYTE *params = NULL;
hal_curve_name_t curve;
size_t params_len;
- hal_uuid_t uuid;
+ hal_uuid_t public_uuid, private_uuid;
CK_RV rv;
- int i;
assert(session != NULL && pPublicKeyTemplate != NULL && pPrivateKeyTemplate != NULL);
- for (i = 0; i < ulPublicKeyAttributeCount; i++) {
+ for (int i = 0; i < ulPublicKeyAttributeCount; i++) {
const CK_ATTRIBUTE_TYPE type = pPublicKeyTemplate[i].type;
const void * const val = pPublicKeyTemplate[i].pValue;
const size_t len = pPublicKeyTemplate[i].ulValueLen;
@@ -2384,45 +2068,59 @@ static CK_RV generate_keypair_ec(p11_session_t *session,
if (!ec_curve_oid_to_name(params, params_len, &curve))
return CKR_TEMPLATE_INCOMPLETE;
- if (!hal_check(hal_rpc_pkey_generate_ec(p11_session_hal_client(session),
- p11_session_hal_session(session),
- &pkey1, &uuid, curve, private_flags)) ||
- !p11_object_bind_pkey(session, private_handle, &uuid) ||
- !p11_attribute_set(public_handle, CKA_EC_PARAMS, params, params_len) ||
- !p11_attribute_set(private_handle, CKA_EC_PARAMS, params, params_len))
- lose(CKR_FUNCTION_FAILED);
-
{
- uint8_t der[hal_rpc_pkey_get_public_key_len(pkey1)], keybuf[hal_ecdsa_key_t_size];
+
+ if (!hal_check(hal_rpc_pkey_generate_ec(p11_session_hal_client(session),
+ p11_session_hal_session(session),
+ &private_pkey, &private_uuid,
+ curve, private_flags)))
+ lose(CKR_FUNCTION_FAILED);
+
+ uint8_t der[hal_rpc_pkey_get_public_key_len(private_pkey)], keybuf[hal_ecdsa_key_t_size];
hal_ecdsa_key_t *key = NULL;
size_t der_len;
- if (!hal_check(hal_rpc_pkey_get_public_key(pkey1, der, &der_len, sizeof(der))) ||
- !hal_check(hal_ecdsa_public_key_from_der(&key, keybuf, sizeof(keybuf), der, der_len)))
+ if (!hal_check(hal_rpc_pkey_get_public_key(private_pkey, der, &der_len, sizeof(der))) ||
+ !hal_check(hal_ecdsa_public_key_from_der(&key, keybuf, sizeof(keybuf), der, der_len)) ||
+ !hal_check(hal_rpc_pkey_load(p11_session_hal_client(session),
+ p11_session_hal_session(session),
+ &public_pkey, HAL_KEY_TYPE_EC_PUBLIC, curve,
+ &public_uuid, der, der_len, public_flags)))
lose(CKR_FUNCTION_FAILED);
uint8_t point[hal_ecdsa_key_to_ecpoint_len(key)];
- if (!hal_check(hal_ecdsa_key_to_ecpoint(key, point, NULL, sizeof(point))) ||
- !p11_attribute_set(public_handle, CKA_EC_POINT, point, sizeof(point)))
+ if (!hal_check(hal_ecdsa_key_to_ecpoint(key, point, NULL, sizeof(point))))
lose(CKR_FUNCTION_FAILED);
- if (!same_keystore &&
- !hal_check(hal_rpc_pkey_load(p11_session_hal_client(session),
- p11_session_hal_session(session),
- &pkey2, HAL_KEY_TYPE_EC_PUBLIC, curve,
- &uuid, der, der_len, public_flags)))
+ const hal_rpc_pkey_attribute_t extra[] = {
+ {.type = CKA_LOCAL,
+ .value = &const_CK_TRUE, .length = sizeof(const_CK_TRUE)},
+ {.type = CKA_KEY_GEN_MECHANISM,
+ .value = &mechanism->mechanism, .length = sizeof(mechanism->mechanism)},
+ {.type = CKA_EC_PARAMS,
+ value = params, .length = params_len},
+ {.type = CKA_EC_POINT,
+ value = point, .length = sizeof(point)}
+ };
+
+ *phPrivateKey = p11_object_create(session, private_pkey, &private_uuid, private_handle_flavor,
+ pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+ private_descriptor, extra, sizeof(extra)/sizeof(*extra) - 1);
+
+ *phPublicKey = p11_object_create(session, public_handle_flavor,
+ pPublicKeyTemplate, ulPublicKeyAttributeCount,
+ public_descriptor, extra, sizeof(extra)/sizeof(*extra));
+
+ if (*phPrivateKey == CK_INVALID_HANDLE || *phPublicKey == CK_INVALID_HANDLE)
lose(CKR_FUNCTION_FAILED);
}
- if (!p11_object_bind_pkey(session, public_handle, &uuid))
- lose(CKR_FUNCTION_FAILED);
-
rv = CKR_OK;
fail:
- hal_rpc_pkey_close(pkey1);
- hal_rpc_pkey_close(pkey2);
+ hal_rpc_pkey_close(private_pkey);
+ hal_rpc_pkey_close(public_pkey);
return rv;
}
@@ -2434,16 +2132,19 @@ static CK_RV generate_keypair_ec(p11_session_t *session,
static CK_RV generate_keypair(p11_session_t *session,
const CK_MECHANISM_PTR pMechanism,
CK_RV (*mechanism_handler)(p11_session_t *session,
-
+ const handle_flavor_t public_handle_flavor,
const CK_ATTRIBUTE_PTR pPublicKeyTemplate,
const CK_ULONG ulPublicKeyAttributeCount,
- const CK_OBJECT_HANDLE public_handle,
+ const p11_descriptor_t *public_descriptor,
+ CK_OBJECT_HANDLE_PTR phPublicKey,
const hal_key_flags_t public_flags,
-
+ const handle_flavor_t private_handle_flavor,
const CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
const CK_ULONG ulPrivateKeyAttributeCount,
- const CK_OBJECT_HANDLE private_handle,
- const hal_key_flags_t private_flags),
+ const p11_descriptor_t *private_descriptor,
+ CK_OBJECT_HANDLE_PTR phPrivateKey,
+ const hal_key_flags_t private_flags,
+ const CK_MECHANISM_PTR pMechanism),
const CK_ATTRIBUTE_PTR pPublicKeyTemplate,
const CK_ULONG ulPublicKeyAttributeCount,
const p11_descriptor_t * const public_descriptor,
@@ -2453,19 +2154,17 @@ static CK_RV generate_keypair(p11_session_t *session,
const p11_descriptor_t * const private_descriptor,
CK_OBJECT_HANDLE_PTR phPrivateKey)
{
- CK_OBJECT_HANDLE public_handle = CK_INVALID_HANDLE;
- CK_OBJECT_HANDLE private_handle = CK_INVALID_HANDLE;
- handle_flavor_t public_handle_flavor = handle_flavor_session_object;
+ handle_flavor_t public_handle_flavor = handle_flavor_session_object;
handle_flavor_t private_handle_flavor = handle_flavor_session_object;
- hal_key_flags_t public_flags = 0;
+ hal_key_flags_t public_flags = 0;
hal_key_flags_t private_flags = 0;
- int in_transaction = 0;
CK_RV rv;
- int i;
rv = p11_check_keypair_attributes(session,
- pPublicKeyTemplate, ulPublicKeyAttributeCount, public_descriptor, &public_flags,
- pPrivateKeyTemplate, ulPrivateKeyAttributeCount, private_descriptor, &private_flags);
+ pPublicKeyTemplate, ulPublicKeyAttributeCount,
+ public_descriptor, &public_flags,
+ pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+ private_descriptor, &private_flags);
if (rv != CKR_OK)
return rv;
@@ -2473,52 +2172,26 @@ static CK_RV generate_keypair(p11_session_t *session,
pPublicKeyTemplate != NULL && phPublicKey != NULL &&
pPrivateKeyTemplate != NULL && phPrivateKey != NULL);
- for (i = 0; i < ulPublicKeyAttributeCount; i++)
+ for (int i = 0; i < ulPublicKeyAttributeCount; i++)
if (pPublicKeyTemplate[i].type == CKA_TOKEN)
- public_handle_flavor = p11_handle_flavor_from_cka_token(pPublicKeyTemplate[i].pValue);
+ public_handle_flavor = p11_object_flavor_from_cka_token(pPublicKeyTemplate[i].pValue);
- for (i = 0; i < ulPrivateKeyAttributeCount; i++)
+ for (int i = 0; i < ulPrivateKeyAttributeCount; i++)
if (pPrivateKeyTemplate[i].type == CKA_TOKEN)
- private_handle_flavor = p11_handle_flavor_from_cka_token(pPrivateKeyTemplate[i].pValue);
+ private_handle_flavor = p11_object_flavor_from_cka_token(pPrivateKeyTemplate[i].pValue);
if (public_handle_flavor == handle_flavor_token_object)
- public_flags |= HAL_KEY_FLAG_TOKEN;
+ public_flags |= HAL_KEY_FLAG_TOKEN;
if (private_handle_flavor == handle_flavor_token_object)
private_flags |= HAL_KEY_FLAG_TOKEN;
- if (!sql_exec("BEGIN"))
- lose(CKR_FUNCTION_FAILED);
-
- in_transaction = 1;
-
- if ((public_handle = p11_object_create(session, public_handle_flavor,
- pPublicKeyTemplate, ulPublicKeyAttributeCount,
- public_descriptor, pMechanism)) == CK_INVALID_HANDLE)
- lose(CKR_FUNCTION_FAILED);
-
- if ((private_handle = p11_object_create(session, private_handle_flavor,
- pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
- private_descriptor, pMechanism)) == CK_INVALID_HANDLE)
- lose(CKR_FUNCTION_FAILED);
-
- rv = mechanism_handler(session,
- pPublicKeyTemplate, ulPublicKeyAttributeCount, public_handle, public_flags,
- pPrivateKeyTemplate, ulPrivateKeyAttributeCount, private_handle, private_flags);
- if (rv != CKR_OK)
- goto fail;
-
- if (!sql_exec("COMMIT"))
- lose(CKR_FUNCTION_FAILED);
-
- *phPublicKey = public_handle;
- *phPrivateKey = private_handle;
- return CKR_OK;
-
- fail:
- if (in_transaction && !sql_exec("ROLLBACK"))
- rv = CKR_GENERAL_ERROR;
- return rv;
+ return mechanism_handler(session,
+ public_handle_flavor, pPublicKeyTemplate, ulPublicKeyAttributeCount,
+ public_descriptor, phPublicKey, public_flags,
+ private_handle_flavor, pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+ private_descriptor, phPrivateKey, private_flags,
+ pMechanism);
}
/*
@@ -2661,19 +2334,19 @@ static int get_signature_len(const CK_OBJECT_HANDLE object_handle,
CK_BYTE oid[20];
CK_ULONG len;
- if (!p11_attribute_get_ulong(object_handle, CKA_KEY_TYPE, &cka_key_type))
+ if (!p11_attribute_get_ulong(session, object_handle, CKA_KEY_TYPE, &cka_key_type))
return 0;
switch (cka_key_type) {
case CKK_RSA:
- if (!p11_attribute_get(object_handle, CKA_MODULUS, NULL, &len, 0))
+ if (!p11_attribute_get(session, object_handle, CKA_MODULUS, NULL, &len, 0))
return 0;
*signature_len = len;
return 1;
case CKK_EC:
- if (!p11_attribute_get(object_handle, CKA_EC_PARAMS, oid, &len, sizeof(oid)) ||
+ if (!p11_attribute_get(session, object_handle, CKA_EC_PARAMS, oid, &len, sizeof(oid)) ||
!ec_curve_oid_to_name(oid, len, &curve))
return 0;
switch (curve) {
@@ -2703,7 +2376,7 @@ static CK_RV sign_hal_rpc(p11_session_t *session,
assert(session != NULL && pulSignatureLen != NULL);
- if (!p11_object_get_pkey_handle(session, session->sign_key_handle, &pkey))
+ if (!p11_object_pkey_open(session, session->sign_key_handle, &pkey))
lose(CKR_FUNCTION_FAILED);
if (!get_signature_len(session->sign_key_handle, pkey, &signature_len))
@@ -2738,7 +2411,7 @@ static CK_RV verify_hal_rpc(p11_session_t *session,
assert(session != NULL);
- if (!p11_object_get_pkey_handle(session, session->verify_key_handle, &pkey))
+ if (!p11_object_pkey_open(session, session->verify_key_handle, &pkey))
lose(CKR_FUNCTION_FAILED);
rv = p11_whine_from_hal(hal_rpc_pkey_verify(pkey, session->verify_digest_handle, pData, ulDataLen,
@@ -2763,8 +2436,6 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs)
ENTER_PUBLIC_FUNCTION(C_Initialize);
CK_C_INITIALIZE_ARGS_PTR a = pInitArgs;
- int initialized_sql = 0;
- int initialized_rpc = 0;
CK_RV rv;
/*
@@ -2864,18 +2535,6 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs)
if (!hal_check(hal_rpc_client_init()))
lose(CKR_GENERAL_ERROR);
- initialized_rpc = 1;
-
- /*
- * Initialize SQLite3, opening the database(s) and loading the
- * schema and views.
- */
-
- if (!sql_init())
- lose(CKR_GENERAL_ERROR);
-
- initialized_sql = 1;
-
#if USE_POSIX
initialized_pid = getpid();
#endif
@@ -2883,13 +2542,6 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs)
return CKR_OK;
fail:
-
- if (initialized_sql)
- sql_fini();
-
- if (initialized_rpc)
- hal_rpc_client_close();
-
return rv;
}
@@ -2911,14 +2563,7 @@ CK_RV C_Finalize(CK_VOID_PTR pReserved)
p11_session_delete_all();
/*
- * Shut down SQLite3.
- */
-
- if (!sql_fini())
- lose(CKR_GENERAL_ERROR);
-
- /*
- * By this point we're pretty well committed to shutting down, so
+ * At this point we're pretty well committed to shutting down, so
* there's not much to be done if any of the rest of this fails.
*/
@@ -2933,10 +2578,6 @@ CK_RV C_Finalize(CK_VOID_PTR pReserved)
#endif
return rv;
-
- fail:
- (void) mutex_unlock(p11_global_mutex);
- return rv;
}
CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
@@ -3113,7 +2754,7 @@ CK_RV C_OpenSession(CK_SLOT_ID slotID,
if (parallel_session)
lose(CKR_SESSION_PARALLEL_NOT_SUPPORTED);
- if ((session = p11_session_new()) == NULL)
+ if ((session = p11_session_allocate()) == NULL)
lose(CKR_HOST_MEMORY);
switch (logged_in_as) {
@@ -3136,9 +2777,6 @@ CK_RV C_OpenSession(CK_SLOT_ID slotID,
session->notify = Notify;
session->application = pApplication;
- if (!p11_session_add(session))
- lose(CKR_FUNCTION_FAILED);
-
assert(p11_session_consistent_login());
if ((rv = mutex_unlock(p11_global_mutex)) != CKR_OK)
@@ -3188,7 +2826,6 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession,
ENTER_PUBLIC_FUNCTION(C_Login);
const hal_client_handle_t client = {HAL_HANDLE_NONE};
- p11_session_t *session;
hal_user_t user = HAL_USER_NONE;
CK_RV rv = CKR_OK;
@@ -3232,7 +2869,8 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession,
case logged_in_as_so: lose(CKR_USER_ALREADY_LOGGED_IN);
case logged_in_as_user: lose(CKR_USER_ANOTHER_ALREADY_LOGGED_IN);
}
- for (session = p11_sessions; session != NULL; session = session->link)
+ for (p11_session_t *session = p11_session_iterate(NULL);
+ session != NULL; session = p11_session_iterate(session))
if (session->state == CKS_RO_PUBLIC_SESSION)
lose(CKR_SESSION_READ_ONLY_EXISTS);
user = HAL_USER_SO;
@@ -3259,7 +2897,8 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession,
logged_in_as = userType == CKU_SO ? logged_in_as_so : logged_in_as_user;
- for (session = p11_sessions; session != NULL; session = session->link) {
+ for (p11_session_t *session = p11_session_iterate(NULL);
+ session != NULL; session = p11_session_iterate(session)) {
switch (session->state) {
case CKS_RO_PUBLIC_SESSION:
@@ -3285,7 +2924,6 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession)
ENTER_PUBLIC_FUNCTION(C_Logout);
const hal_client_handle_t client = {HAL_HANDLE_NONE};
- p11_session_t *session;
CK_RV rv = CKR_OK;
mutex_lock_or_return_failure(p11_global_mutex);
@@ -3303,36 +2941,108 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession)
lose(CKR_USER_NOT_LOGGED_IN);
/*
- * Update global login state, then delete any private objects and
- * whack every existing session into the right state.
+ * Delete any private objects and whack every existing session into
+ * the right state.
*/
- assert(p11_session_consistent_login());
-
- if ((rv = p11_whine_from_hal(hal_rpc_logout(client))) != CKR_OK)
- goto fail;
-
- logged_in_as = not_logged_in;
-
- p11_object_delete_all_private();
-
- for (session = p11_sessions; session != NULL; session = session->link) {
- switch (session->state) {
+ {
+ assert(p11_session_consistent_login());
+
+ const hal_session_handle_t session_handle_none = {HAL_HANDLE_NONE};
+
+ const hal_rpc_pkey_attribute attrs[] = {
+ {.type = CKA_PRIVATE, .value = &const_CK_TRUE, .length = sizeof(const_CK_TRUE)}
+ };
+
+ hal_uuid_t uuids[64];
+ unsigned n;
+
+ memset(uuids, 0, sizeof(uuids));
+ do {
+
+ rv = p11_whine_from_hal(hal_rpc_pkey_match(p11_session_hal_client(session),
+ session_handle_none,
+ HAL_KEY_TYPE_NONE, HAL_CURVE_NONE,
+ 0,
+ attrs, sizeof(attrs)/sizeof(*attrs),
+ uuids, &n, sizeof(uuids)/sizeof(*uuuids),
+ &uuids[sizeof(uuids)/sizeof(*uuuids) - 1]));
+ if (rv != CKR_OK)
+ goto fail;
+
+ for (int i = 0; i < n; i++) {
+ hal_pkey_handle_t pkey;
+ rv = p11_whine_from_hal(hal_rpc_pkey_open(p11_session_hal_client(session),
+ session_handle_none, &pkey, &uuids[i], 0));
+ if (rv != CKR_OK)
+ goto fail;
+ if ((rv = p11_whine_from_hal(hal_rpc_pkey_delete(pkey))) != CKR_OK) {
+ (void) hal_rpc_pkey_close(pkey);
+ goto fail;
+ }
+ }
+
+ if (n > 0) {
+ for (CK_OBJECT_HANDLE handle = p11_object_handle_iterate(CK_INVALID_HANDLE);
+ handle != CK_INVALID_HANDLE; handle = p11_object_handle_iterate(handle)) {
+ p11_object_t *object = p11_object_find(handle);
+ assert(object != NULL);
+ if (bsearch(&object->uuid, uuids, n, sizeof(*uuids), hal_uuid_cmp) != NULL)
+ p11_object_free(object);
+ }
+ }
+
+ } while (n == sizeof(uuids)/sizeof(*uuuids));
+
+ memset(uuids, 0, sizeof(uuids));
+ do {
+
+ rv = p11_whine_from_hal(hal_rpc_pkey_match(p11_session_hal_client(session),
+ session_handle_none,
+ HAL_KEY_TYPE_NONE, HAL_CURVE_NONE,
+ HAL_KEY_FLAG_TOKEN,
+ attrs, sizeof(attrs)/sizeof(*attrs),
+ uuids, &n, sizeof(uuids)/sizeof(*uuuids),
+ &uuids[sizeof(uuids)/sizeof(*uuuids) - 1]));
+ if (rv != CKR_OK)
+ goto fail;
+
+ if (n > 0) {
+ for (CK_OBJECT_HANDLE handle = p11_object_handle_iterate(CK_INVALID_HANDLE);
+ handle != CK_INVALID_HANDLE; handle = p11_object_handle_iterate(handle)) {
+ p11_object_t *object = p11_object_find(handle);
+ assert(object != NULL);
+ if (bsearch(&object->uuid, uuids, n, sizeof(*uuids), hal_uuid_cmp) != NULL)
+ p11_object_free(object);
+ }
+ }
+
+ } while (n == sizeof(uuids)/sizeof(*uuuids));
+
+ for (p11_session_t *session = p11_session_iterate(NULL);
+ session != NULL; session = p11_session_iterate(session)) {
+ switch (session->state) {
+
+ case CKS_RO_USER_FUNCTIONS:
+ session->state = CKS_RO_PUBLIC_SESSION;
+ continue;
+
+ case CKS_RW_USER_FUNCTIONS:
+ case CKS_RW_SO_FUNCTIONS:
+ session->state = CKS_RW_PUBLIC_SESSION;
+ continue;
+
+ }
+ }
- case CKS_RO_USER_FUNCTIONS:
- session->state = CKS_RO_PUBLIC_SESSION;
- continue;
+ if ((rv = p11_whine_from_hal(hal_rpc_logout(client))) != CKR_OK)
+ goto fail;
- case CKS_RW_USER_FUNCTIONS:
- case CKS_RW_SO_FUNCTIONS:
- session->state = CKS_RW_PUBLIC_SESSION;
- continue;
+ logged_in_as = not_logged_in;
- }
+ assert(p11_session_consistent_login());
}
- assert(p11_session_consistent_login());
-
fail:
mutex_unlock_return_with_rv(rv, p11_global_mutex);
}
@@ -3345,7 +3055,6 @@ CK_RV C_CreateObject(CK_SESSION_HANDLE hSession,
ENTER_PUBLIC_FUNCTION(C_CreateObject);
CK_OBJECT_HANDLE handle = CK_INVALID_HANDLE;
- int in_transaction = 0;
p11_session_t *session;
CK_RV rv;
@@ -3385,8 +3094,7 @@ CK_RV C_CreateObject(CK_SESSION_HANDLE hSession,
if ((rv = p11_check_create_attributes(session, pTemplate, ulCount, descriptor)) != CKR_OK)
goto fail;
- const handle_flavor_t flavor
- = cka_token == NULL ? handle_flavor_session_object : p11_handle_flavor_from_cka_token(cka_token);
+ const handle_flavor_t flavor = p11_object_flavor_from_cka_token(cka_token);
switch (session->state) {
case CKS_RO_PUBLIC_SESSION:
@@ -3395,56 +3103,40 @@ CK_RV C_CreateObject(CK_SESSION_HANDLE hSession,
lose(CKR_SESSION_READ_ONLY);
}
- if (!sql_exec("BEGIN"))
- lose(CKR_FUNCTION_FAILED);
-
- in_transaction = 1;
-
- if ((handle = p11_object_create(session, flavor, pTemplate, ulCount, descriptor, NULL)) == CK_INVALID_HANDLE)
- lose(CKR_FUNCTION_FAILED);
-
- if (!p11_attribute_set_bbool(handle, CKA_LOCAL, CK_FALSE))
- lose(CKR_FUNCTION_FAILED);
-
- switch (*cka_class) {
- case CKO_PRIVATE_KEY:
- case CKO_SECRET_KEY:
- if (!p11_attribute_set_bbool(handle, CKA_ALWAYS_SENSITIVE, CK_FALSE) ||
- !p11_attribute_set_bbool(handle, CKA_NEVER_EXTRACTABLE, CK_FALSE))
- lose(CKR_FUNCTION_FAILED);
- }
-
hal_key_flags_t flags = flavor == handle_flavor_token_object ? HAL_KEY_FLAG_TOKEN : 0;
for (int i = 0; i < ulCount; i++)
p11_attribute_apply_keyusage(&flags, pTemplate[i].type, pTemplate[i].pValue);
- if (*cka_class == CKO_PUBLIC_KEY && *cka_key_type == CKK_RSA &&
- !p11_object_create_rsa_public_key(session, handle, flags))
- lose(CKR_FUNCTION_FAILED);
+ int (*handler)(const p11_session_t *session,
+ const handle_flavor_t flavor,
+ const CK_ATTRIBUTE_PTR pTemplate,
+ const CK_ULONG ulCount,
+ const p11_descriptor_t * const descriptor,
+ CK_OBJECT_HANDLE_PTR phObject,
+ const hal_key_flags_t flags) = NULL;
- if (*cka_class == CKO_PUBLIC_KEY && *cka_key_type == CKK_EC &&
- !p11_object_create_ec_public_key(session, handle, flags))
- lose(CKR_FUNCTION_FAILED);
+ if (*cka_class == CKO_PUBLIC_KEY && *cka_key_type == CKK_RSA)
+ handler = p11_object_create_rsa_public_key;
- if (*cka_class == CKO_PRIVATE_KEY && *cka_key_type == CKK_RSA &&
- !p11_object_create_rsa_private_key(session, handle, flags, pTemplate, ulCount))
- lose(CKR_FUNCTION_FAILED);
+ if (*cka_class == CKO_PUBLIC_KEY && *cka_key_type == CKK_EC)
+ handler = p11_object_create_ec_public_key;
- if (*cka_class == CKO_PRIVATE_KEY && *cka_key_type == CKK_EC &&
- !p11_object_create_ec_private_key(session, handle, flags, pTemplate, ulCount))
- lose(CKR_FUNCTION_FAILED);
+ if (*cka_class == CKO_PRIVATE_KEY && *cka_key_type == CKK_RSA)
+ handler = p11_object_create_rsa_private_key;
+
+ if (*cka_class == CKO_PRIVATE_KEY && *cka_key_type == CKK_EC)
+ handler = p11_object_create_ec_private_key;
- if (!sql_exec("COMMIT"))
+ if (handler == NULL)
lose(CKR_FUNCTION_FAILED);
- *phObject = handle;
+ if (!handler(session, flavor, pTemplate, ulCount, descriptor, phObject, flags))
+ lose(CKR_FUNCTION_FAILED);
return mutex_unlock(p11_global_mutex);
fail:
- if (in_transaction && !sql_exec("ROLLBACK"))
- rv = CKR_GENERAL_ERROR;
mutex_unlock_return_with_rv(rv, p11_global_mutex);
}
@@ -3453,17 +3145,8 @@ CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession,
{
ENTER_PUBLIC_FUNCTION(C_DestroyObject);
- static const char delete_object[] =
- " DELETE FROM object WHERE object_handle = ?";
-
- static const char delete_token_object[] =
- " DELETE FROM token_object"
- " WHERE token_object_id = (SELECT token_object_id FROM object WHERE object_handle = ?)";
-
-
hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
p11_session_t *session;
- sqlite3_stmt *q = NULL;
CK_RV rv = CKR_OK;
mutex_lock_or_return_failure(p11_global_mutex);
@@ -3473,23 +3156,17 @@ CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession,
if ((rv = p11_object_check_rights(session, hObject, p11_object_access_write)) != CKR_OK)
goto fail;
- if (p11_object_get_pkey_handle(session, hObject, &pkey) && !hal_check(hal_rpc_pkey_delete(pkey)))
+ if (!p11_object_pkey_open(session, hObject, &pkey))
lose(CKR_FUNCTION_FAILED);
- if (is_token_handle(hObject) &&
- (!sql_check_ok(sql_prepare(&q, delete_token_object)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 1, hObject)) ||
- !sql_check_done(sqlite3_step(q)) ||
- !sql_check_ok(sql_finalize_and_clear(&q))))
+ if (!hal_check(hal_rpc_pkey_delete(pkey))) {
+ (void) hal_rpc_pkey_close(pkey);
lose(CKR_FUNCTION_FAILED);
+ }
- if (!sql_check_ok(sql_prepare(&q, delete_object)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 1, hObject)) ||
- !sql_check_done(sqlite3_step(q)))
- lose(CKR_FUNCTION_FAILED);
+ p11_object_free(p11_object_find(hObject));
fail:
- sqlite3_finalize(q);
mutex_unlock_return_with_rv(rv, p11_global_mutex);
}
@@ -3500,21 +3177,13 @@ CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession,
{
ENTER_PUBLIC_FUNCTION(C_GetAttributeValue);
- static const char select_format[] =
- " SELECT value FROM %s_attribute NATURAL JOIN object"
- " WHERE object_handle = ?1 AND type = ?2";
-
- const char *flavor = is_token_handle(hObject) ? "token" : "session";
-
p11_session_t *session;
const p11_descriptor_t *descriptor = NULL;
CK_BBOOL cka_sensitive, cka_extractable;
CK_OBJECT_CLASS cka_class;
CK_KEY_TYPE cka_key_type;
int sensitive_object = 0;
- sqlite3_stmt *q = NULL;
CK_RV rv;
- int ret, i;
mutex_lock_or_return_failure(p11_global_mutex);
@@ -3526,15 +3195,15 @@ CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession,
if ((rv = p11_object_check_rights(session, hObject, p11_object_access_read)) != CKR_OK)
goto fail;
- if (!p11_attribute_get_ulong(hObject, CKA_CLASS, &cka_class))
+ if (!p11_attribute_get_ulong(session, hObject, CKA_CLASS, &cka_class))
lose(CKR_OBJECT_HANDLE_INVALID);
switch (cka_class) {
case CKO_PRIVATE_KEY:
case CKO_SECRET_KEY:
- if (!p11_attribute_get_bbool(hObject, CKA_EXTRACTABLE, &cka_extractable) ||
- !p11_attribute_get_bbool(hObject, CKA_SENSITIVE, &cka_sensitive))
+ if (!p11_attribute_get_bbool(session, hObject, CKA_EXTRACTABLE, &cka_extractable) ||
+ !p11_attribute_get_bbool(session, hObject, CKA_SENSITIVE, &cka_sensitive))
lose(CKR_OBJECT_HANDLE_INVALID);
sensitive_object = cka_sensitive || !cka_extractable;
@@ -3542,7 +3211,7 @@ CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession,
/* Fall through */
case CKO_PUBLIC_KEY:
- if (!p11_attribute_get_ulong(hObject, CKA_KEY_TYPE, &cka_key_type))
+ if (!p11_attribute_get_ulong(session, hObject, CKA_KEY_TYPE, &cka_key_type))
lose(CKR_OBJECT_HANDLE_INVALID);
descriptor = p11_descriptor_from_key_type(cka_class, cka_key_type);
}
@@ -3553,7 +3222,7 @@ CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession,
rv = CKR_OK;
- for (i = 0; i < ulCount; i++) {
+ for (int i = 0; i < ulCount; i++) {
if (sensitive_object && p11_attribute_is_sensitive(descriptor, pTemplate[i].type)) {
pTemplate[i].ulValueLen = -1;
@@ -4013,9 +3682,9 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession,
if ((rv = p11_object_check_rights(session, hKey, p11_object_access_read)) != CKR_OK)
goto fail;
- if (!p11_attribute_get_ulong(hKey, CKA_CLASS, &key_class) ||
- !p11_attribute_get_ulong(hKey, CKA_KEY_TYPE, &key_type) ||
- !p11_attribute_get_bbool(hKey, CKA_SIGN, &key_sign) ||
+ if (!p11_attribute_get_ulong(session, hKey, CKA_CLASS, &key_class) ||
+ !p11_attribute_get_ulong(session, hKey, CKA_KEY_TYPE, &key_type) ||
+ !p11_attribute_get_bbool(session, hKey, CKA_SIGN, &key_sign) ||
key_class != CKO_PRIVATE_KEY)
lose(CKR_KEY_HANDLE_INVALID);
@@ -4110,7 +3779,7 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession,
if (session->sign_digest_handle.handle != HAL_HANDLE_NONE)
lose(CKR_OPERATION_ACTIVE);
- if (!p11_attribute_get_ulong(session->sign_key_handle, CKA_KEY_TYPE, &key_type))
+ if (!p11_attribute_get_ulong(session, session->sign_key_handle, CKA_KEY_TYPE, &key_type))
lose(CKR_FUNCTION_FAILED);
if (session->sign_digest_algorithm != HAL_DIGEST_ALGORITHM_NONE && pSignature != NULL) {
@@ -4202,7 +3871,7 @@ CK_RV C_SignFinal(CK_SESSION_HANDLE hSession,
if (session->sign_key_handle == CK_INVALID_HANDLE || session->sign_digest_handle.handle == HAL_HANDLE_NONE)
lose(CKR_OPERATION_NOT_INITIALIZED);
- if (!p11_attribute_get_ulong(session->sign_key_handle, CKA_KEY_TYPE, &key_type))
+ if (!p11_attribute_get_ulong(session, session->sign_key_handle, CKA_KEY_TYPE, &key_type))
lose(CKR_FUNCTION_FAILED);
switch (key_type) {
@@ -4252,9 +3921,9 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession,
if ((rv = p11_object_check_rights(session, hKey, p11_object_access_read)) != CKR_OK)
goto fail;
- if (!p11_attribute_get_ulong(hKey, CKA_CLASS, &key_class) ||
- !p11_attribute_get_ulong(hKey, CKA_KEY_TYPE, &key_type) ||
- !p11_attribute_get_bbool(hKey, CKA_VERIFY, &key_verify) ||
+ if (!p11_attribute_get_ulong(session, hKey, CKA_CLASS, &key_class) ||
+ !p11_attribute_get_ulong(session, hKey, CKA_KEY_TYPE, &key_type) ||
+ !p11_attribute_get_bbool(session, hKey, CKA_VERIFY, &key_verify) ||
key_class != CKO_PUBLIC_KEY)
lose(CKR_KEY_HANDLE_INVALID);
@@ -4354,7 +4023,7 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession,
ulDataLen = 0;
}
- if (!p11_attribute_get_ulong(session->verify_key_handle, CKA_KEY_TYPE, &key_type))
+ if (!p11_attribute_get_ulong(session, session->verify_key_handle, CKA_KEY_TYPE, &key_type))
lose(CKR_FUNCTION_FAILED);
switch (key_type) {
@@ -4439,7 +4108,7 @@ CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession,
if (session->verify_key_handle == CK_INVALID_HANDLE || session->verify_digest_handle.handle == HAL_HANDLE_NONE)
lose(CKR_OPERATION_NOT_INITIALIZED);
- if (!p11_attribute_get_ulong(session->verify_key_handle, CKA_KEY_TYPE, &key_type))
+ if (!p11_attribute_get_ulong(session, session->verify_key_handle, CKA_KEY_TYPE, &key_type))
lose(CKR_FUNCTION_FAILED);
switch (key_type) {