aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2016-05-14 14:04:09 -0400
committerRob Austein <sra@hactrn.net>2016-05-14 14:04:09 -0400
commit7ce10ab8b2351157445a281695dddae0a91f7580 (patch)
tree182bc89f1004e57ddf6fdf4fdaeeff743a65e466
parentb99b156905409cc44844b234fe73b4f4a4bd1b90 (diff)
Add (back) ability to construct public keys from stored attributes.
-rw-r--r--pkcs11.c143
1 files changed, 128 insertions, 15 deletions
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);