aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2016-05-18 15:37:51 -0400
committerRob Austein <sra@hactrn.net>2016-05-18 15:37:51 -0400
commitd77efd2f3abd3b7381351c388adae9fabba41361 (patch)
tree8ad09e85ed90bc0409f20edf9fd543ca5212a6f5
parent00b2adefccab211bb853c79ac84315dbd40ee05d (diff)
Refactor object creation code.
-rw-r--r--pkcs11.c252
1 files changed, 105 insertions, 147 deletions
diff --git a/pkcs11.c b/pkcs11.c
index 4fde44f..667c3da 100644
--- a/pkcs11.c
+++ b/pkcs11.c
@@ -1416,64 +1416,29 @@ static CK_OBJECT_HANDLE p11_object_create(const p11_session_t *session,
}
/*
- * Construct and store libhal type code for a key object.
- */
-
-static int p11_object_pkey_type(const CK_OBJECT_HANDLE object_handle,
- hal_key_type_t *pkey_type)
-{
- static const char update_pkey_type[] =
- " UPDATE object SET hal_pkey_type = ?2 WHERE object_handle = ?1";
-
- assert(pkey_type != NULL);
-
- CK_OBJECT_CLASS cka_class;
- CK_KEY_TYPE cka_key_type;
-
- if (!p11_attribute_get_ulong(object_handle, CKA_CLASS, &cka_class) ||
- !p11_attribute_get_ulong(object_handle, CKA_KEY_TYPE, &cka_key_type))
- return 0;
-
- else if (cka_class == CKO_PRIVATE_KEY && cka_key_type == CKK_RSA)
- *pkey_type = HAL_KEY_TYPE_RSA_PRIVATE;
-
- else if (cka_class == CKO_PRIVATE_KEY && cka_key_type == CKK_EC)
- *pkey_type = HAL_KEY_TYPE_EC_PRIVATE;
-
- else if (cka_class == CKO_PUBLIC_KEY && cka_key_type == CKK_RSA)
- *pkey_type = HAL_KEY_TYPE_RSA_PUBLIC;
-
- else if (cka_class == CKO_PUBLIC_KEY && cka_key_type == CKK_EC)
- *pkey_type = HAL_KEY_TYPE_EC_PUBLIC;
-
- else
- *pkey_type = HAL_KEY_TYPE_NONE;
-
- sqlite3_stmt *q = NULL;
-
- 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.
+ * Bind PKCS #11 objects to keystore objects.
+ *
+ * This requires storing the pkey type (supplied) and the SKI
+ * (calcualted from supplied public key DER) of the key. We return
+ * the calculated SKI so that the caller can use it as the pkey name.
+ *
+ * We don't work with pkey handles here because that would create a
+ * chicken-and-egg problem, given that the values calculated and
+ * stored by this function are what we use to look up a pkey given
+ * a PKCS #11 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)
+static int p11_object_bind_pkey(const p11_session_t * const session,
+ const hal_key_type_t pkey_type,
+ 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";
+ " UPDATE object SET hal_pkey_type = ?1, hal_pkey_ski = ?2 WHERE object_handle = ?3 OR object_handle = ?4";
hal_hash_handle_t hash = {HAL_HANDLE_NONE};
@@ -1491,33 +1456,24 @@ static int p11_object_pkey_ski(const p11_session_t * const session,
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)) &&
+ ok = (sql_check_ok(sql_prepare(&q, update_pkey_ski)) &&
+ sql_check_ok(sqlite3_bind_int64(q, 1, pkey_type)) &&
+ sql_check_ok(sqlite3_bind_blob( q, 2, ski, ski_len, NULL)) &&
+ sql_check_ok(sqlite3_bind_int64(q, 3, object_handle_1)) &&
+ sql_check_ok(sqlite3_bind_int64(q, 4, object_handle_2)) &&
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;
}
/*
- * Fetch the libhal pkey handle for a key object.
+ * Create pkeys to go with PKCS #11 public key objects loaded by C_CreateObject().
*/
-#warning Should do something about key usage flags in p11_object_get_*_public_key()
-
-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 hal_key_flags_t flags)
+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 const char select_format[] =
" WITH a (type, value) "
@@ -1526,20 +1482,19 @@ static inline int p11_object_get_rsa_public_key(const p11_session_t * const sess
const char *flavor = is_token_handle(object_handle) ? "token" : "session";
+ 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;
size_t ski_len = 0;
int ok
- = (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_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),
@@ -1548,24 +1503,24 @@ static inline int p11_object_get_rsa_public_key(const p11_session_t * const sess
if (ok) {
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)) &&
+ ok = (hal_check(hal_rsa_public_key_to_der(key, der, NULL, sizeof(der))) &&
+ p11_object_bind_pkey(session, HAL_KEY_TYPE_RSA_PUBLIC,
+ 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, ski, sizeof(ski),
- der, sizeof(der), flags)));
+ &pkey, HAL_KEY_TYPE_RSA_PUBLIC, HAL_CURVE_NONE,
+ ski, sizeof(ski), der, sizeof(der), flags)));
}
+ (void) hal_rpc_pkey_close(pkey);
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 hal_key_flags_t flags)
+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 const char select_format[] =
" WITH a (type, value) "
@@ -1574,6 +1529,7 @@ static inline int p11_object_get_ec_public_key(const p11_session_t * const sessi
const char *flavor = is_token_handle(object_handle) ? "token" : "session";
+ 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;
@@ -1581,17 +1537,13 @@ static inline int p11_object_get_ec_public_key(const p11_session_t * const sessi
size_t ski_len = 0;
int ok
- = (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) &&
+ = (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) &&
hal_check(hal_ecdsa_key_from_ecpoint(&key, keybuf, sizeof(keybuf),
sqlite3_column_blob( q, 1),
sqlite3_column_bytes(q, 1),
@@ -1599,20 +1551,25 @@ static inline int p11_object_get_ec_public_key(const p11_session_t * const sessi
if (ok) {
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)) &&
+ ok = (hal_check(hal_ecdsa_public_key_to_der(key, der, NULL, sizeof(der))) &&
+ p11_object_bind_pkey(session, HAL_KEY_TYPE_EC_PUBLIC,
+ 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, ski, sizeof(ski),
- der, sizeof(der), flags)));
+ &pkey, HAL_KEY_TYPE_EC_PUBLIC, curve,
+ ski, sizeof(ski), der, sizeof(der), flags)));
}
+ (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)
@@ -1621,49 +1578,24 @@ static int p11_object_get_pkey_handle(const p11_session_t * const session,
" 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;
sqlite3_stmt *q = NULL;
- hal_error_t err;
int ok = 0;
assert(pkey_handle != NULL);
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;
-
- const int column_0_type = sqlite3_column_type(q, 0);
- const int column_1_type = sqlite3_column_type(q, 1);
-
- if (column_0_type == SQLITE_INTEGER)
- pkey_type = (hal_key_type_t) sqlite3_column_int64(q, 0);
-
- else if (column_0_type != SQLITE_NULL || !p11_object_pkey_type(object_handle, &pkey_type))
- goto fail;
-
- if (column_1_type == SQLITE_BLOB)
- err = hal_whine_allow(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),
- HAL_ERROR_KEY_NOT_FOUND);
-
- else if (column_1_type == SQLITE_NULL)
- err = hal_whine(HAL_ERROR_KEY_NOT_FOUND);
-
- else
+ !sql_check_row(sqlite3_step(q)) ||
+ sqlite3_column_type(q, 0) != SQLITE_INTEGER ||
+ sqlite3_column_type(q, 1) != SQLITE_BLOB)
goto fail;
- if (err == HAL_OK)
- ok = 1;
-
- else if (err == HAL_ERROR_KEY_NOT_FOUND && pkey_type == HAL_KEY_TYPE_RSA_PUBLIC)
- ok = p11_object_get_rsa_public_key(session, object_handle, pkey_handle, flags);
+ const hal_key_type_t pkey_type = sqlite3_column_int64(q, 0);
+ const uint8_t * const ski = sqlite3_column_blob( q, 1);
+ const size_t ski_len = sqlite3_column_bytes(q, 1);
- else if (err == HAL_ERROR_KEY_NOT_FOUND && pkey_type == HAL_KEY_TYPE_EC_PUBLIC)
- ok = p11_object_get_ec_public_key(session, object_handle, pkey_handle, flags);
-
- else
- ok = 0;
+ ok = hal_check(hal_rpc_pkey_find(p11_session_hal_client(session), p11_session_hal_session(session),
+ pkey_handle, pkey_type, ski, ski_len, flags));
fail:
sqlite3_finalize(q);
@@ -2167,8 +2099,8 @@ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session,
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)) ||
+ !p11_object_bind_pkey(session, HAL_KEY_TYPE_RSA_PRIVATE, 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)))
@@ -2247,8 +2179,8 @@ static CK_RV generate_keypair_ec(p11_session_t *session,
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)) ||
+ !p11_object_bind_pkey(session, HAL_KEY_TYPE_EC_PRIVATE, 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);
@@ -3201,19 +3133,34 @@ 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);
+
switch (session->state) {
case CKS_RO_PUBLIC_SESSION:
case CKS_RO_USER_FUNCTIONS:
- if (cka_token != NULL && *cka_token)
+ if (flavor == handle_flavor_token_object)
lose(CKR_SESSION_READ_ONLY);
}
+ /*
+ * The above checks notwithstanding, we don't (yet) know how to
+ * create anything but CKO_PUBLIC_KEY objects here.
+ *
+ * The main problem issue is that we need to be very sure that
+ * sensitive attributes don't get put in publicly-readable storage,
+ * which will require filtering creation of sensitive attributes in
+ * p11_object_create().
+ *
+ * Which we need to do anyway, eventually, but let's get handling of
+ * keys we generate ourselves working properly (again) first.
+ */
+ if (*cka_class != CKO_PUBLIC_KEY)
+ lose(CKR_TEMPLATE_INCONSISTENT);
+
if (!sql_exec("BEGIN"))
lose(CKR_FUNCTION_FAILED);
- const handle_flavor_t flavor
- = cka_token == NULL ? handle_flavor_session_object : p11_handle_flavor_from_cka_token(cka_token);
-
if ((handle = p11_object_create(session, flavor, pTemplate, ulCount, descriptor, NULL)) == CK_INVALID_HANDLE)
lose(CKR_FUNCTION_FAILED);
@@ -3228,7 +3175,18 @@ CK_RV C_CreateObject(CK_SESSION_HANDLE hSession,
lose(CKR_FUNCTION_FAILED);
}
-#warning Somewhere around here we need to create a libhal key object from supplied components
+ hal_key_flags_t flags = flavor == handle_flavor_session_object ? HAL_KEY_FLAG_PROXIMATE : 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))
+ goto fail;
+
+ if (*cka_class == CKO_PUBLIC_KEY && *cka_key_type == CKK_EC &&
+ !p11_object_create_ec_public_key(session, handle, flags))
+ goto fail;
if (!sql_exec("COMMIT"))
lose(CKR_FUNCTION_FAILED);