[Cryptech-Commits] [sw/pkcs11] 04/05: Refactor object creation code.

git at cryptech.is git at cryptech.is
Thu May 19 03:17:49 UTC 2016


This is an automated email from the git hooks/post-receive script.

sra at hactrn.net pushed a commit to branch rpc
in repository sw/pkcs11.

commit d77efd2f3abd3b7381351c388adae9fabba41361
Author: Rob Austein <sra at hactrn.net>
AuthorDate: Wed May 18 15:37:51 2016 -0400

    Refactor object creation code.
---
 pkcs11.c | 252 ++++++++++++++++++++++++++-------------------------------------
 1 file 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);



More information about the Commits mailing list