diff options
Diffstat (limited to 'pkcs11.c')
-rw-r--r-- | pkcs11.c | 1935 |
1 files changed, 802 insertions, 1133 deletions
@@ -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) { |