From 7ce10ab8b2351157445a281695dddae0a91f7580 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Sat, 14 May 2016 14:04:09 -0400 Subject: Add (back) ability to construct public keys from stored attributes. --- pkcs11.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 128 insertions(+), 15 deletions(-) (limited to 'pkcs11.c') diff --git a/pkcs11.c b/pkcs11.c index 5d30d34..6ed7bc3 100644 --- a/pkcs11.c +++ b/pkcs11.c @@ -1394,6 +1394,95 @@ static int p11_object_pkey_type(const CK_OBJECT_HANDLE object_handle, * Fetch the libhal pkey handle for a key object. */ +static inline int p11_object_get_rsa_public_key(const p11_session_t * const session, + const CK_OBJECT_HANDLE object_handle, + hal_pkey_handle_t *pkey_handle, + const char *flavor, + const uint8_t * const name, const size_t name_len, + 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"; + + 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)))); + + if (ok) { + uint8_t der[hal_rsa_public_key_to_der_len(key)]; + 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_handle, HAL_KEY_TYPE_RSA_PUBLIC, + HAL_CURVE_NONE, name, name_len, + der, sizeof(der), flags))); + } + + sqlite3_finalize(q); + return ok; +} + +static inline int p11_object_get_ec_public_key(const p11_session_t * const session, + const CK_OBJECT_HANDLE object_handle, + hal_pkey_handle_t *pkey_handle, + const char *flavor, + const uint8_t * const name, const size_t name_len, + 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"; + + uint8_t keybuf[hal_ecdsa_key_t_size]; + hal_ecdsa_key_t *key = NULL; + hal_curve_name_t curve; + sqlite3_stmt *q = NULL; + + 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) && + hal_check(hal_ecdsa_key_from_ecpoint(&key, keybuf, sizeof(keybuf), + sqlite3_column_blob( q, 1), + sqlite3_column_bytes(q, 1), + curve))); + + if (ok) { + uint8_t der[hal_ecdsa_public_key_to_der_len(key)]; + 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_handle, HAL_KEY_TYPE_EC_PUBLIC, + curve, name, name_len, + der, sizeof(der), flags))); + } + + sqlite3_finalize(q); + return ok; +} + 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) @@ -1404,17 +1493,17 @@ static int p11_object_get_pkey_handle(const p11_session_t * const session, const char *flavor = is_token_handle(object_handle) ? "token" : "session"; + hal_key_flags_t flags = is_token_handle(object_handle) ? 0 : HAL_KEY_FLAG_PROXIMATE; hal_key_type_t pkey_type; sqlite3_stmt *q = NULL; - int ok; + hal_error_t err; + int ok = 0; assert(pkey_handle != NULL); - ok = (sql_check_ok(sql_prepare(&q, select_format, flavor, CKA_ID)) && - sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) && - sql_check_row(sqlite3_step(q))); - - if (!ok) + if (!sql_check_ok(sql_prepare(&q, select_format, flavor, CKA_ID)) || + !sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) || + !sql_check_row(sqlite3_step(q))) goto fail; switch (sqlite3_column_type(q, 1)) { @@ -1424,22 +1513,46 @@ static int p11_object_get_pkey_handle(const p11_session_t * const session, break; case SQLITE_NULL: - ok = p11_object_pkey_type(object_handle, &pkey_type); - if (!ok) + if (!p11_object_pkey_type(object_handle, &pkey_type)) goto fail; break; default: - ok = 0; goto fail; } - ok = hal_check(hal_rpc_pkey_find(p11_session_hal_client(session), - p11_session_hal_session(session), - pkey_handle, pkey_type, - sqlite3_column_blob(q, 0), - sqlite3_column_bytes(q, 0), - 0)); + err = hal_rpc_pkey_find(p11_session_hal_client(session), + p11_session_hal_session(session), + pkey_handle, pkey_type, + sqlite3_column_blob(q, 0), + sqlite3_column_bytes(q, 0), + flags); + + if (err == HAL_ERROR_KEY_NOT_FOUND) { + switch (pkey_type) { + + case HAL_KEY_TYPE_RSA_PUBLIC: + if (!p11_object_get_rsa_public_key(session, object_handle, pkey_handle, flavor, + sqlite3_column_blob(q, 0), sqlite3_column_bytes(q, 0), flags)) + goto fail; + break; + + case HAL_KEY_TYPE_EC_PUBLIC: + if (!p11_object_get_ec_public_key(session, object_handle, pkey_handle, flavor, + sqlite3_column_blob(q, 0), sqlite3_column_bytes(q, 0), flags)) + goto fail; + break; + + default: + (void) hal_check(err); + goto fail; + } + } + + else if (!hal_check(err)) + goto fail; + + ok = 1; fail: sqlite3_finalize(q); -- cgit v1.2.3