aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2016-05-15 23:01:45 -0400
committerRob Austein <sra@hactrn.net>2016-05-15 23:01:45 -0400
commit4be4d40a2af0aecd4b3fe41e33500cfc35442da2 (patch)
tree1a915da05e01cb92bf28d7444ae0ce0c1461df48
parentf0e3e1feff3a3504d4b3d6f48f6d44a0a27ecba0 (diff)
Use key hashes instead of CKA_ID to name objects in libhal keystore.
-rw-r--r--pkcs11.c231
-rw-r--r--schema.sql1
2 files changed, 150 insertions, 82 deletions
diff --git a/pkcs11.c b/pkcs11.c
index b5878e5..e08b9ca 100644
--- a/pkcs11.c
+++ b/pkcs11.c
@@ -188,6 +188,16 @@ typedef enum {
#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
+
/*
@@ -1345,7 +1355,7 @@ static CK_OBJECT_HANDLE p11_object_create(const p11_session_t *session,
}
/*
- * Construct libhal type code for a key object.
+ * Construct and store libhal type code for a key object.
*/
static int p11_object_pkey_type(const CK_OBJECT_HANDLE object_handle,
@@ -1380,11 +1390,61 @@ static int p11_object_pkey_type(const CK_OBJECT_HANDLE object_handle,
sqlite3_stmt *q = NULL;
- return (sql_check_ok(sql_prepare(&q, update_pkey_type)) &&
- sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) &&
- sql_check_ok(sqlite3_bind_int64(q, 2, *pkey_type)) &&
- sql_check_done(sqlite3_step(q)) &&
- sql_check_ok(sqlite3_finalize(q)));
+ int ok = (sql_check_ok(sql_prepare(&q, update_pkey_type)) &&
+ sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) &&
+ sql_check_ok(sqlite3_bind_int64(q, 2, *pkey_type)) &&
+ sql_check_done(sqlite3_step(q)));
+
+ sqlite3_finalize(q);
+ return ok;
+}
+
+/*
+ * Construct and store SKI (key hash) for a key object.
+ */
+
+static int p11_object_pkey_ski(const p11_session_t * const session,
+ const CK_OBJECT_HANDLE object_handle_1,
+ const CK_OBJECT_HANDLE object_handle_2,
+ const uint8_t * const der, const size_t der_len,
+ uint8_t *ski, const size_t ski_len)
+{
+ assert(session != NULL && der != NULL && ski != NULL);
+
+ static const char update_pkey_ski[] =
+ " UPDATE object SET hal_pkey_ski = ?2 WHERE object_handle = ?1";
+
+ hal_hash_handle_t hash = {HAL_HANDLE_NONE};
+
+ int ok = hal_check(hal_rpc_hash_initialize(p11_session_hal_client(session),
+ p11_session_hal_session(session),
+ &hash, P11_KEY_HASH_ALGORITHM, NULL, 0));
+ if (ok)
+ ok = hal_check(hal_rpc_hash_update(hash, der, der_len));
+
+ if (hash.handle != HAL_HANDLE_NONE)
+ ok = hal_check(hal_rpc_hash_finalize(hash, ski, ski_len)) && ok;
+
+ if (!ok)
+ return 0;
+
+ sqlite3_stmt *q = NULL;
+
+ ok = (sql_check_ok(sql_prepare(&q, update_pkey_ski)) &&
+ sql_check_ok(sqlite3_bind_int64(q, 1,
+ object_handle_1)) &&
+ sql_check_ok(sqlite3_bind_blob( q, 2,
+ ski, ski_len, NULL)) &&
+ sql_check_done(sqlite3_step(q)));
+
+ if (ok && object_handle_2 != CK_INVALID_HANDLE)
+ ok = (sql_check_ok(sqlite3_reset(q)) &&
+ sql_check_ok(sqlite3_bind_int64(q, 1,
+ object_handle_2)) &&
+ sql_check_done(sqlite3_step(q)));
+
+ sqlite3_finalize(q);
+ return ok;
}
/*
@@ -1396,8 +1456,6 @@ static int p11_object_pkey_type(const CK_OBJECT_HANDLE object_handle,
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[] =
@@ -1405,17 +1463,22 @@ static inline int p11_object_get_rsa_public_key(const p11_session_t * const sess
" 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";
+
uint8_t keybuf[hal_rsa_key_t_size];
hal_rsa_key_t *key = NULL;
sqlite3_stmt *q = NULL;
+ size_t ski_len = 0;
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_rpc_hash_get_digest_length(P11_KEY_HASH_ALGORITHM,
+ &ski_len)) &&
+ 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),
@@ -1423,12 +1486,14 @@ static inline int p11_object_get_rsa_public_key(const p11_session_t * const sess
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))) &&
+ uint8_t der[hal_rsa_public_key_to_der_len(key)], ski[ski_len];
+ ok = (hal_check(hal_rsa_public_key_to_der(key, der, NULL, sizeof(der))) &&
+ p11_object_pkey_ski(session, object_handle, CK_INVALID_HANDLE,
+ der, sizeof(der), ski, sizeof(ski)) &&
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,
+ HAL_CURVE_NONE, ski, sizeof(ski),
der, sizeof(der), flags)));
}
@@ -1439,8 +1504,6 @@ static inline int p11_object_get_rsa_public_key(const p11_session_t * const sess
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[] =
@@ -1448,33 +1511,40 @@ static inline int p11_object_get_ec_public_key(const p11_session_t * const sessi
" 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";
+
uint8_t keybuf[hal_ecdsa_key_t_size];
hal_ecdsa_key_t *key = NULL;
hal_curve_name_t curve;
sqlite3_stmt *q = NULL;
+ size_t ski_len = 0;
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 &&
+ = (hal_check(hal_rpc_hash_get_digest_length(P11_KEY_HASH_ALGORITHM,
+ &ski_len)) &&
+ 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) &&
+ &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))) &&
+ uint8_t der[hal_ecdsa_public_key_to_der_len(key)], ski[ski_len];
+ ok = (hal_check(hal_ecdsa_public_key_to_der(key, der, NULL, sizeof(der))) &&
+ p11_object_pkey_ski(session, object_handle, CK_INVALID_HANDLE,
+ der, sizeof(der), ski, sizeof(ski)) &&
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,
+ curve, ski, sizeof(ski),
der, sizeof(der), flags)));
}
@@ -1486,11 +1556,8 @@ 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 value, hal_pkey_type FROM %s_attribute NATURAL JOIN object"
- " WHERE object_handle = ?1 AND type = %u";
-
- const char *flavor = is_token_handle(object_handle) ? "token" : "session";
+ static const char select_query[] =
+ " SELECT hal_pkey_type, hal_pkey_ski FROM object WHERE object_handle = ?1";
hal_key_flags_t flags = is_token_handle(object_handle) ? 0 : HAL_KEY_FLAG_PROXIMATE;
hal_key_type_t pkey_type;
@@ -1500,15 +1567,15 @@ static int p11_object_get_pkey_handle(const p11_session_t * const session,
assert(pkey_handle != NULL);
- if (!sql_check_ok(sql_prepare(&q, select_format, flavor, CKA_ID)) ||
- !sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) ||
+ if (!sql_check_ok(sql_prepare(&q, select_query)) ||
+ !sql_check_ok(sqlite3_bind_int64(q, 1, object_handle)) ||
!sql_check_row(sqlite3_step(q)))
goto fail;
- switch (sqlite3_column_type(q, 1)) {
+ switch (sqlite3_column_type(q, 0)) {
case SQLITE_INTEGER:
- pkey_type = (hal_key_type_t) sqlite3_column_int64(q, 1);
+ pkey_type = (hal_key_type_t) sqlite3_column_int64(q, 0);
break;
case SQLITE_NULL:
@@ -1520,25 +1587,31 @@ static int p11_object_get_pkey_handle(const p11_session_t * const session,
goto fail;
}
- 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);
+ switch (sqlite3_column_type(q, 1)) {
+
+ case SQLITE_BLOB:
+ err = hal_rpc_pkey_find(p11_session_hal_client(session), p11_session_hal_session(session), pkey_handle,
+ pkey_type, sqlite3_column_blob(q, 1), sqlite3_column_bytes(q, 1), flags);
+ break;
+
+ case SQLITE_NULL:
+ err = HAL_ERROR_KEY_NOT_FOUND;
+ break;
+
+ default:
+ goto fail;
+ }
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))
+ if (!p11_object_get_rsa_public_key(session, object_handle, pkey_handle, 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))
+ if (!p11_object_get_ec_public_key(session, object_handle, pkey_handle, flags))
goto fail;
break;
@@ -1897,9 +1970,6 @@ static CK_RV p11_template_check_2(const p11_session_t *session,
* possible through the object descriptor.
*
* Key usage handling here is based on RFC 5280 4.2.1.3.
- *
- * PKCS #11 suggests but does not require CKA_ID values for public and
- * private key to match.
*/
static CK_RV p11_check_keypair_attributes(const p11_session_t *session,
@@ -2007,13 +2077,13 @@ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session,
const CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
const CK_ULONG ulPrivateKeyAttributeCount,
const CK_OBJECT_HANDLE private_handle,
- const hal_key_flags_t private_flags,
- const uint8_t * const id, const size_t id_len)
+ const hal_key_flags_t private_flags)
{
const uint8_t *public_exponent = const_0x010001;
size_t public_exponent_len = sizeof(const_0x010001);
hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
CK_ULONG keysize = 0;
+ size_t ski_len = 0;
CK_RV rv;
int i;
@@ -2039,22 +2109,28 @@ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session,
}
}
- if (keysize == 0 || id == NULL)
+ if (keysize == 0)
return CKR_TEMPLATE_INCOMPLETE;
+ if (!hal_check(hal_rpc_hash_get_digest_length(P11_KEY_HASH_ALGORITHM, &ski_len)))
+ lose(CKR_FUNCTION_FAILED);
+
if (!hal_check(hal_rpc_pkey_generate_rsa(p11_session_hal_client(session),
p11_session_hal_session(session),
- &pkey, id, id_len, keysize,
+ &pkey, (const uint8_t *) "", 0, keysize,
public_exponent, public_exponent_len,
private_flags)))
lose(CKR_FUNCTION_FAILED);
{
- uint8_t der[hal_rpc_pkey_get_public_key_len(pkey)], keybuf[hal_rsa_key_t_size];
+ uint8_t der[hal_rpc_pkey_get_public_key_len(pkey)], keybuf[hal_rsa_key_t_size], ski[ski_len];
size_t der_len, modulus_len;
hal_rsa_key_t *key = NULL;
if (!hal_check(hal_rpc_pkey_get_public_key(pkey, der, &der_len, sizeof(der))) ||
+ !p11_object_pkey_ski(session, private_handle, public_handle,
+ der, sizeof(der), ski, sizeof(ski)) ||
+ !hal_check(hal_rpc_pkey_rename(pkey, ski, sizeof(ski))) ||
!hal_check(hal_rsa_public_key_from_der(&key, keybuf, sizeof(keybuf), der, der_len)) ||
!hal_check(hal_rsa_key_get_modulus(key, NULL, &modulus_len, 0)))
lose(CKR_FUNCTION_FAILED);
@@ -2086,13 +2162,13 @@ static CK_RV generate_keypair_ec(p11_session_t *session,
const CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
const CK_ULONG ulPrivateKeyAttributeCount,
const CK_OBJECT_HANDLE private_handle,
- const hal_key_flags_t private_flags,
- const uint8_t * const id, const size_t id_len)
+ const hal_key_flags_t private_flags)
{
hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
const CK_BYTE *params = NULL;
hal_curve_name_t curve;
size_t params_len;
+ size_t ski_len = 0;
CK_RV rv;
int i;
@@ -2112,23 +2188,29 @@ static CK_RV generate_keypair_ec(p11_session_t *session,
}
}
- if (!ec_curve_oid_to_name(params, params_len, &curve) || id == NULL)
+ if (!ec_curve_oid_to_name(params, params_len, &curve))
return CKR_TEMPLATE_INCOMPLETE;
+ if (!hal_check(hal_rpc_hash_get_digest_length(P11_KEY_HASH_ALGORITHM, &ski_len)))
+ lose(CKR_FUNCTION_FAILED);
+
if (!hal_check(hal_rpc_pkey_generate_ec(p11_session_hal_client(session),
p11_session_hal_session(session),
- &pkey, id, id_len, curve,
+ &pkey, (const uint8_t *) "", 0, curve,
private_flags)) ||
!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(pkey)], keybuf[hal_ecdsa_key_t_size];
+ uint8_t der[hal_rpc_pkey_get_public_key_len(pkey)], keybuf[hal_ecdsa_key_t_size], ski[ski_len];
hal_ecdsa_key_t *key = NULL;
size_t der_len;
if (!hal_check(hal_rpc_pkey_get_public_key(pkey, der, &der_len, sizeof(der))) ||
+ !p11_object_pkey_ski(session, private_handle, public_handle,
+ der, sizeof(der), ski, sizeof(ski)) ||
+ !hal_check(hal_rpc_pkey_rename(pkey, ski, sizeof(ski))) ||
!hal_check(hal_ecdsa_public_key_from_der(&key, keybuf, sizeof(keybuf), der, der_len)))
lose(CKR_FUNCTION_FAILED);
@@ -2167,8 +2249,7 @@ static CK_RV generate_keypair(p11_session_t *session,
const CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
const CK_ULONG ulPrivateKeyAttributeCount,
const CK_OBJECT_HANDLE private_handle,
- const hal_key_flags_t private_flags,
- const uint8_t * const id, const size_t id_len),
+ const hal_key_flags_t private_flags),
const p11_descriptor_t * const public_descriptor,
const p11_descriptor_t * const private_descriptor)
{
@@ -2218,25 +2299,11 @@ static CK_RV generate_keypair(p11_session_t *session,
private_descriptor, pMechanism)) == CK_INVALID_HANDLE)
lose(CKR_FUNCTION_FAILED);
- {
- CK_ULONG id_len = 0;
-
- if (!p11_attribute_get(private_handle, CKA_ID, NULL, &id_len, 0) &&
- !p11_attribute_get(public_handle, CKA_ID, NULL, &id_len, 0))
- lose(CKR_TEMPLATE_INCOMPLETE);
-
- uint8_t id[id_len];
-
- if (!p11_attribute_get(private_handle, CKA_ID, id, NULL, (size_t) id_len) &&
- !p11_attribute_get(public_handle, CKA_ID, id, NULL, (size_t) id_len))
- lose(CKR_TEMPLATE_INCOMPLETE);
-
- if ((rv = mechanism_handler(session,
- pPublicKeyTemplate, ulPublicKeyAttributeCount, public_handle, public_flags,
- pPrivateKeyTemplate, ulPrivateKeyAttributeCount, private_handle, private_flags,
- id, id_len)) != CKR_OK)
- goto fail;
- }
+ 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);
diff --git a/schema.sql b/schema.sql
index 8a81505..bc984ab 100644
--- a/schema.sql
+++ b/schema.sql
@@ -64,6 +64,7 @@ CREATE TEMPORARY TABLE IF NOT EXISTS object (
object_handle INTEGER NOT NULL UNIQUE
CHECK (object_handle > 0 AND object_handle <= 0xFFFFFFFF),
hal_pkey_type INTEGER,
+ hal_pkey_ski BLOB,
session_id INTEGER REFERENCES session
ON DELETE CASCADE ON UPDATE CASCADE
DEFERRABLE INITIALLY DEFERRED,