[Cryptech-Commits] [sw/pkcs11] 01/04: First pass on converting from direct libhal calls to libhal RPC calls.

git at cryptech.is git at cryptech.is
Fri May 13 01:48:44 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 fcacebf82d87c9dedf45aa130d383102aafc3e16
Author: Rob Austein <sra at hactrn.net>
AuthorDate: Thu May 12 09:54:08 2016 -0400

    First pass on converting from direct libhal calls to libhal RPC calls.
    
    This version isn't really expected to work properly, but it's far
    enough along to be worth archiving before starting runtime testing.
---
 pkcs11.c   | 1106 ++++++++++++++++++++----------------------------------------
 schema.sql |   59 +---
 2 files changed, 373 insertions(+), 792 deletions(-)

diff --git a/pkcs11.c b/pkcs11.c
index 433e7ab..b1aac5f 100644
--- a/pkcs11.c
+++ b/pkcs11.c
@@ -6,7 +6,7 @@
  * libhal library connecting to the Cryptech FPGA cores.
  *
  * Author: Rob Austein
- * Copyright (c) 2015, NORDUnet A/S
+ * Copyright (c) 2015-2016, NORDUnet A/S
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -153,17 +153,17 @@ typedef struct p11_session {
   CK_VOID_PTR application;              /* Application data */
   sqlite3_stmt *find_query;             /* FindObject*() query state */
   int find_query_done;                  /* find_query has terminated */
-  const hal_hash_descriptor_t
-    *digest_descriptor,                 /* Hash for C_Digest*() */
-    *sign_digest_descriptor,            /* Hash for C_Sign*() */
-    *verify_digest_descriptor;          /* Hash for C_Verify*() */
+  hal_digest_algorithm_t
+    digest_algorithm,                   /* Hash algorithm for C_Digest*() */
+    sign_digest_algorithm,              /* Hash algorithm for C_Sign*() */
+    verify_digest_algorithm;            /* Hash algorithm for C_Verify*() */
   CK_OBJECT_HANDLE
-    sign_key_handle,                    /* Key  for C_Sign*() */
-    verify_key_handle;                  /* Key  for C_Verify() */
-  hal_hash_state_t
-    *digest_state,                      /* Hash state for C_Digest*() */
-    *sign_digest_state,                 /* Hash state for C_Sign*() */
-    *verify_digest_state;               /* Hash state for C_Verify*() */
+    sign_key_handle,                    /* Private key for C_Sign*() */
+    verify_key_handle;                  /* Public  key for C_Verify() */
+  hal_hash_handle_t
+    digest_handle,                      /* Hash state for C_Digest*() */
+    sign_digest_handle,                 /* Hash state for C_Sign*() */
+    verify_digest_handle;               /* Hash state for C_Verify*() */
 } p11_session_t;
 
 /*
@@ -505,6 +505,28 @@ static int ec_curve_oid_to_name(const uint8_t * const oid, const size_t oid_len,
   return 1;
 }
 
+/*
+ * Extract libhal-compatible client and session identifiers from a session.
+ *
+ * libhal's session identifiers are deliberately chosen to be in the same
+ * numeric range as PKCS #11's, so we can just use them directly.
+ *
+ * libhal's client identifiers are multiplexing extension handled elsewhere,
+ * for our purposes using constant client identifier of zero will do.
+ */
+
+static inline hal_client_handle_t p11_session_hal_client(const p11_session_t * const session)
+{
+  hal_client_handle_t handle = {0};
+  return handle;
+}
+
+static inline hal_session_handle_t p11_session_hal_session(const p11_session_t * const session)
+{
+  hal_session_handle_t handle = {session->handle};
+  return handle;
+}
+
 

 
 /*
@@ -1173,302 +1195,99 @@ static CK_OBJECT_HANDLE p11_object_create(const p11_session_t *session,
 }
 
 /*
- * Store a private key.
- *
- * Write the key as DER, encrypt that using AES key wrap, and store
- * the result as an SQL blob.
- *
- * We jump through a few minor hoops to let us do all the encoding and
- * wrapping in place in a single buffer.
+ * Construct libhal type code for a key object.
  */
 
-static int p11_object_set_generic_private_key(const CK_OBJECT_HANDLE object_handle,
-                                              const void * const key,
-                                              const size_t key_der_len,
-                                              hal_error_t (*to_der)(const void * const, uint8_t *, size_t *, const size_t))
+static int p11_object_pkey_type(const CK_OBJECT_HANDLE object_handle,
+                                hal_key_type_t *pkey_type)
 {
-  static const char select_kek[] =
-    " SELECT kek FROM global";
-
-  static const char update_format[] =
-    " UPDATE %s_object SET private_key = ?1"
-    " WHERE %s_object_id = (SELECT %s_object_id FROM object WHERE object_handle = ?2)";
+  static const char update_pkey_type[] =
+    " UPDATE object SET hal_pkey_type = ?2 WHERE object_handle = ?1";
 
-  uint8_t wrapbuf[hal_aes_keywrap_ciphertext_length(key_der_len)];
-  const char *flavor = is_token_handle(object_handle) ? "token" : "session";
-  size_t der_len, wrapbuf_len = sizeof(wrapbuf);
-  sqlite3_stmt *q = NULL;
-  int ok = 0;
+  assert(pkey_type != NULL);
 
-  assert(to_der);
-
-  if (!sql_check_ok(sql_prepare(&q, select_kek))                                ||
-      !sql_check_row(sqlite3_step(q))                                           ||
-      sqlite3_column_type(q, 0) == SQLITE_NULL                                  ||
-      !hal_check(to_der(key, wrapbuf + 8, &der_len, sizeof(wrapbuf) - 8))       ||
-      !hal_check(hal_aes_keywrap(NULL,
-                                 sqlite3_column_blob(q, 0),
-                                 sqlite3_column_bytes(q, 0),
-                                 wrapbuf+8, der_len, wrapbuf, &wrapbuf_len))	||
-      !sql_check_ok(sql_finalize_and_clear(&q))                                 ||
-      !sql_check_ok(sql_prepare(&q, update_format, flavor, flavor, flavor))     ||
-      !sql_check_ok(sqlite3_bind_blob( q, 1, wrapbuf, wrapbuf_len, NULL))       ||
-      !sql_check_ok(sqlite3_bind_int64(q, 2, object_handle))                    ||
-      !sql_check_done(sqlite3_step(q)))
-    goto fail;
-
-  ok = 1;
+  CK_OBJECT_CLASS cka_class;
+  CK_KEY_TYPE cka_key_type;
 
- fail:
-  memset(wrapbuf, 0, sizeof(wrapbuf));
-  sqlite3_finalize(q);
-  return ok;
-}
+  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;
 
-/*
- * Store an RSA private key.
- *
- * Use p11_object_set_generic_private_key() to wrap the PKCS #1.5
- * RSAPrivateKey encoding of the private key.
- */
+  else if (cka_class == CKO_PRIVATE_KEY && cka_key_type == CKK_EC)
+    *pkey_type = HAL_KEY_TYPE_EC_PRIVATE;
 
-static hal_error_t p11_object_encode_rsa_key(const void * const key,
-                                             uint8_t * der,
-                                             size_t *der_len,
-                                             const size_t der_max)
-{
-  return hal_rsa_private_key_to_der(key, der, der_len, der_max);
-}
+  else if (cka_class == CKO_PUBLIC_KEY && cka_key_type == CKK_RSA)
+    *pkey_type = HAL_KEY_TYPE_RSA_PUBLIC;
 
-static int p11_object_set_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
-                                          const hal_rsa_key_t * const key)
-{
-  return p11_object_set_generic_private_key(object_handle,
-                                            key,
-                                            hal_rsa_private_key_to_der_len(key),
-                                            p11_object_encode_rsa_key);
-}
+  else if (cka_class == CKO_PUBLIC_KEY && cka_key_type == CKK_EC)
+    *pkey_type = HAL_KEY_TYPE_EC_PUBLIC;
 
-/*
- * Store an EC private key.
- *
- * Use p11_object_set_generic_private_key() to wrap the RFC 5915
- * ECPrivateKey encoding of the private key.
- */
+  else
+    *pkey_type = HAL_KEY_TYPE_NONE;
 
-static hal_error_t p11_object_encode_ec_key(const void * const key,
-                                            uint8_t * der,
-                                            size_t *der_len,
-                                            const size_t der_max)
-{
-  return hal_ecdsa_private_key_to_der(key, der, der_len, der_max);
-}
+  sqlite3_stmt *q = NULL;
 
-static int p11_object_set_ec_private_key(const CK_OBJECT_HANDLE object_handle,
-                                         const hal_ecdsa_key_t * const key)
-{
-  return p11_object_set_generic_private_key(object_handle,
-                                            key,
-                                            hal_ecdsa_private_key_to_der_len(key),
-                                            p11_object_encode_ec_key);
+  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)));
 }
 
 /*
- * Fetch a private key.
- *
- * Retrieve SQL blob from the object, unwrap that to get the DER
- * encoding, load the key from that.
- *
- * If the key isn't set, we return success with null key.
+ * Fetch the libhal pkey handle for a key object.
  */
 
-static int p11_object_get_generic_private_key(const CK_OBJECT_HANDLE object_handle,
-                                              void **key,
-                                              uint8_t *keybuf, const size_t keybuf_len,
-                                              hal_error_t (*from_der)(void **, void *,
-                                                                      const size_t, const uint8_t * const, const size_t))
+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 kek, private_key FROM global, %s_object NATURAL JOIN object WHERE object_handle = ?1";
+    " 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";
+
+  hal_key_type_t pkey_type;
   sqlite3_stmt *q = NULL;
   int ok;
 
-  assert(key != NULL && keybuf != NULL);
+  assert(pkey_handle != NULL);
 
-  /*
-   * Pull everything we need from the database.
-   */
+  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 (!sql_check_ok(sql_prepare(&q, select_format, flavor))     ||
-      !sql_check_ok(sqlite3_bind_int64(q, 1, object_handle))    ||
-      !sql_check_row(sqlite3_step(q))                           ||
-      sqlite3_column_type(q, 0) == SQLITE_NULL) {
-    ok = 0;
-  }
+  if (!ok)
+    goto fail;
 
-  else if (sqlite3_column_type(q, 1) == SQLITE_NULL) {
-    *key = NULL;
-    ok = 1;
-  }
+  switch (sqlite3_column_type(q, 1)) {
 
-  else {
-    const uint8_t * const kek  = sqlite3_column_blob(q, 0);
-    const uint8_t * const pkey = sqlite3_column_blob(q, 1);
-    const size_t kek_len  = sqlite3_column_bytes(q, 0);
-    const size_t pkey_len = sqlite3_column_bytes(q, 1);
-    size_t  wrapbuf_len = pkey_len;
-    uint8_t wrapbuf[pkey_len];
+  case SQLITE_INTEGER:
+    pkey_type = (hal_key_type_t) sqlite3_column_int64(q, 1);
+    break;
 
-    ok = (hal_check(hal_aes_keyunwrap(NULL, kek, kek_len, pkey, pkey_len, wrapbuf, &wrapbuf_len)) &&
-          hal_check(from_der(key, keybuf, keybuf_len, wrapbuf, wrapbuf_len)));
+  case SQLITE_NULL:
+    ok = p11_object_pkey_type(object_handle, &pkey_type);
+    if (!ok)
+      goto fail;
+    break;
 
-    memset(wrapbuf, 0, sizeof(wrapbuf));
+  default:
+    ok = 0;
+    goto fail;
   }
 
-  if (!ok || *key == NULL)
-    memset(keybuf, 0, keybuf_len);
-
-  sqlite3_finalize(q);
-  return ok;
-}
-
-/*
- * Fetch an RSA private key.
- *
- * Use p11_object_get_generic_private_key() to unwrap the DER encoding
- * of a PKCS #1.5 RSAPrivateKey object.
- */
-
-static hal_error_t p11_object_decode_rsa_key(void **key_,
-                                             void *keybuf, const size_t keybuf_len,
-                                             const uint8_t * const der, const size_t der_len)
-{
-  assert(key_ != NULL);
-  hal_rsa_key_t *key = NULL;
-  hal_error_t err = hal_rsa_private_key_from_der(&key, keybuf, keybuf_len, der, der_len);
-  *key_ = key;
-  return err;
-}
-
-static int p11_object_get_rsa_private_key(const CK_OBJECT_HANDLE object_handle,
-                                          hal_rsa_key_t **key,
-                                          uint8_t *keybuf, const size_t keybuf_len)
-{
-  assert(key != NULL);
-  void *key_ = NULL;
-  int ok = p11_object_get_generic_private_key(object_handle, &key_, keybuf, keybuf_len, p11_object_decode_rsa_key);
-  *key = key_;
-  return ok;
-}
-
-/*
- * Fetch an EC private key.
- *
- * Use p11_object_get_generic_private_key() to unwrap the DER encoding
- * of an RFC 5915 ECPrivateKey object.
- */
-
-static hal_error_t p11_object_decode_ec_key(void **key_,
-                                             void *keybuf, const size_t keybuf_len,
-                                             const uint8_t * const der, const size_t der_len)
-{
-  assert(key_ != NULL);
-  hal_ecdsa_key_t *key = NULL;
-  hal_error_t err = hal_ecdsa_private_key_from_der(&key, keybuf, keybuf_len, der, der_len);
-  *key_ = key;
-  return err;
-}
-
-static int p11_object_get_ec_private_key(const CK_OBJECT_HANDLE object_handle,
-                                          hal_ecdsa_key_t **key,
-                                          uint8_t *keybuf, const size_t keybuf_len)
-{
-  assert(key != NULL);
-  void *key_ = NULL;
-  int ok = p11_object_get_generic_private_key(object_handle, &key_, keybuf, keybuf_len, p11_object_decode_ec_key);
-  *key = key_;
-  return ok;
-}
-
-#warning Revisit return semantics of p11_object_get_*_private_key() and p11_object_*_rsa_public_key()
-
-/*
- * Fetch an RSA public key.
- *
- * Public keys aren't stored separately the way that private keys are,
- * so we're looking for the public components so we can load them into
- * a key object.
- */
-
-static int p11_object_get_rsa_public_key(const CK_OBJECT_HANDLE object_handle,
-                                         hal_rsa_key_t **key,
-                                         uint8_t *keybuf, const size_t keybuf_len)
-{
-  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";
-
-  const char *flavor = is_token_handle(object_handle) ? "token" : "session";
-  sqlite3_stmt *q = NULL;
-
-  assert(key != NULL && keybuf != NULL);
-
-  const 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, keybuf_len,
-                                                    sqlite3_column_blob( q, 0),
-                                                    sqlite3_column_bytes(q, 0),
-                                                    sqlite3_column_blob( q, 1),
-                                                    sqlite3_column_bytes(q, 1))));
-
-  sqlite3_finalize(q);
-  return ok;
-}
-
-/*
- * Fetch an EC public key.
- *
- * Public keys aren't stored separately the way that private keys are,
- * so we're looking for the public components so we can load them into
- * a key object.
- */
-
-static int p11_object_get_ec_public_key(const CK_OBJECT_HANDLE object_handle,
-                                        hal_ecdsa_key_t **key,
-                                        uint8_t *keybuf, const size_t keybuf_len)
-{
-  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";
-
-  const char *flavor = is_token_handle(object_handle) ? "token" : "session";
-  sqlite3_stmt *q = NULL;
-  hal_curve_name_t curve;
-
-  assert(key != NULL && keybuf != NULL);
-
-  const 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, keybuf_len,
-                                                       sqlite3_column_blob( q, 1),
-                                                       sqlite3_column_bytes(q, 1),
-                                                       curve)));
+  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)));
 
+ fail:
   sqlite3_finalize(q);
   return ok;
 }
@@ -1502,9 +1321,9 @@ static void p11_session_free(p11_session_t *session)
     return;
 
   sql_finalize_and_clear(&session->find_query);
-  hal_hash_cleanup(&session->digest_state);
-  hal_hash_cleanup(&session->sign_digest_state);
-  hal_hash_cleanup(&session->verify_digest_state);
+  (void) hal_rpc_hash_finalize(session->digest_handle, NULL, 0);
+  (void) hal_rpc_hash_finalize(session->sign_digest_handle, NULL, 0);
+  (void) hal_rpc_hash_finalize(session->verify_digest_handle, NULL, 0);
   free(session);
 }
 
@@ -1917,14 +1736,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 CK_OBJECT_HANDLE public_handle)
+                                       const CK_OBJECT_HANDLE public_handle,
+                                       const uint8_t * const id, const size_t id_len)
 {
   const uint8_t *public_exponent = const_0x010001;
   size_t public_exponent_len = sizeof(const_0x010001);
-  uint8_t keybuf[hal_rsa_key_t_size];
-  hal_rsa_key_t *key = NULL;
+  hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
   CK_ULONG keysize = 0;
-  size_t modulus_len;
   CK_RV rv;
   int i;
 
@@ -1950,26 +1768,31 @@ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session,
     }
   }
 
-  if (keysize == 0)
+  if (keysize == 0 || id == NULL)
     return CKR_TEMPLATE_INCOMPLETE;
 
-  memset(keybuf, 0, sizeof(keybuf));
+#warning Should do something here with pkey flags
 
-  if (!hal_check(hal_rsa_key_gen(NULL, &key, keybuf, sizeof(keybuf), keysize / 8,
-                                 public_exponent, public_exponent_len)))
+  if (!hal_check(hal_rpc_pkey_generate_rsa(p11_session_hal_client(session),
+                                           p11_session_hal_session(session),
+                                           &pkey, id, id_len, keysize / 8,
+                                           public_exponent, public_exponent_len, 0)))
     lose(CKR_FUNCTION_FAILED);
 
-  if (!p11_object_set_rsa_private_key(private_handle, key))
-    lose(CKR_FUNCTION_FAILED);
+  {
+    uint8_t der[hal_rpc_pkey_get_public_key_len(pkey)], keybuf[hal_rsa_key_t_size];
+    size_t der_len, modulus_len;
+    hal_rsa_key_t *key = NULL;
 
-  if (!hal_check(hal_rsa_key_get_modulus(key, NULL, &modulus_len, 0)))
-    lose(CKR_FUNCTION_FAILED);
+    if (!hal_check(hal_rpc_pkey_get_public_key(pkey, der, &der_len, sizeof(der)))               ||
+        !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);
 
-  {
     uint8_t modulus[modulus_len];
 
-    if (!hal_check(hal_rsa_key_get_modulus(key, modulus, &modulus_len, sizeof(modulus))) ||
-        !p11_attribute_set(public_handle,  CKA_MODULUS, modulus, modulus_len)            ||
+    if (!hal_check(hal_rsa_key_get_modulus(key, modulus, NULL, sizeof(modulus)))        ||
+        !p11_attribute_set(public_handle,  CKA_MODULUS, modulus, modulus_len)           ||
         !p11_attribute_set(private_handle, CKA_MODULUS, modulus, modulus_len))
       lose(CKR_FUNCTION_FAILED);
   }
@@ -1977,7 +1800,7 @@ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session,
   rv = CKR_OK;
 
  fail:
-  hal_rsa_key_clear(key);
+  hal_rpc_pkey_close(pkey);
   return rv;
 }
 
@@ -1986,15 +1809,15 @@ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session,
  */
 
 static CK_RV generate_keypair_ec(p11_session_t *session,
-                                       const CK_ATTRIBUTE_PTR pPublicKeyTemplate,
-                                       const CK_ULONG ulPublicKeyAttributeCount,
-                                       const CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
-                                       const CK_ULONG ulPrivateKeyAttributeCount,
-                                       const CK_OBJECT_HANDLE private_handle,
-                                       const CK_OBJECT_HANDLE public_handle)
+                                 const CK_ATTRIBUTE_PTR pPublicKeyTemplate,
+                                 const CK_ULONG ulPublicKeyAttributeCount,
+                                 const CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
+                                 const CK_ULONG ulPrivateKeyAttributeCount,
+                                 const CK_OBJECT_HANDLE private_handle,
+                                 const CK_OBJECT_HANDLE public_handle,
+                                 const uint8_t * const id, const size_t id_len)
 {
-  uint8_t keybuf[hal_ecdsa_key_t_size];
-  hal_ecdsa_key_t *key = NULL;
+  hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
   const CK_BYTE *params = NULL;
   hal_curve_name_t curve;
   size_t params_len;
@@ -2017,18 +1840,25 @@ static CK_RV generate_keypair_ec(p11_session_t *session,
     }
   }
 
-  if (!ec_curve_oid_to_name(params, params_len, &curve))
+  if (!ec_curve_oid_to_name(params, params_len, &curve) || id == NULL)
     return CKR_TEMPLATE_INCOMPLETE;
 
-  memset(keybuf, 0, sizeof(keybuf));
-
-  if (!hal_check(hal_ecdsa_key_gen(NULL, &key, keybuf, sizeof(keybuf), curve))  ||
-      !p11_object_set_ec_private_key(private_handle, key)                       ||
+  if (!hal_check(hal_rpc_pkey_generate_ec(p11_session_hal_client(session),
+                                          p11_session_hal_session(session),
+                                          &pkey, id, id_len, curve, 0))         ||
       !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];
+    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)))               ||
+        !hal_check(hal_ecdsa_public_key_from_der(&key, keybuf, sizeof(keybuf), der, der_len)))
+      lose(CKR_FUNCTION_FAILED);
+
     uint8_t point[hal_ecdsa_key_to_ecpoint_len(key)];
 
     if (!hal_check(hal_ecdsa_key_to_ecpoint(key, point, NULL, sizeof(point)))   ||
@@ -2039,7 +1869,7 @@ static CK_RV generate_keypair_ec(p11_session_t *session,
   rv = CKR_OK;
 
  fail:
-  hal_ecdsa_key_clear(key);
+  hal_rpc_pkey_close(pkey);
   return rv;
 }
 
@@ -2062,7 +1892,8 @@ 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 CK_OBJECT_HANDLE public_handle),
+                                                         const CK_OBJECT_HANDLE public_handle,
+                                                         const uint8_t * const id, const size_t id_len),
                               const p11_descriptor_t * const public_descriptor,
                               const p11_descriptor_t * const private_descriptor)
 {
@@ -2104,11 +1935,29 @@ static CK_RV generate_keypair(p11_session_t *session,
                                           private_descriptor, pMechanism)) == CK_INVALID_HANDLE)
     lose(CKR_FUNCTION_FAILED);
 
-  if ((rv = mechanism_handler(session,
-                              pPublicKeyTemplate, ulPublicKeyAttributeCount,
-                              pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
-                              private_handle, public_handle)) != CKR_OK)
-    goto fail;
+  {
+    size_t public_id_len = 0, private_id_len = 0;
+
+    if (!p11_attribute_get(public_handle,  CKA_ID, NULL, &public_id_len, 0) ||
+        !p11_attribute_get(private_handle, CKA_ID, NULL, &public_id_len, 0))
+      lose(CKR_TEMPLATE_INCOMPLETE);
+
+    uint8_t public_id[public_id_len], private_id[private_id_len];
+
+    if (!p11_attribute_get(public_handle,  CKA_ID, public_id,  NULL, public_id_len) ||
+        !p11_attribute_get(private_handle, CKA_ID, private_id, NULL, public_id_len))
+      lose(CKR_TEMPLATE_INCOMPLETE);
+
+    if (public_id_len != private_id_len || memcmp(public_id, private_id, public_id_len) != 0)
+      lose(CKR_TEMPLATE_INCONSISTENT);
+
+    if ((rv = mechanism_handler(session,
+                                pPublicKeyTemplate, ulPublicKeyAttributeCount,
+                                pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+                                private_handle, public_handle,
+                                public_id, public_id_len)) != CKR_OK)
+      goto fail;
+  }
 
   if (!sql_exec("COMMIT"))
     lose(CKR_FUNCTION_FAILED);
@@ -2192,14 +2041,17 @@ static CK_RV p11_check_create_attributes(const p11_session_t *session,
  * Add data to a digest.
  */
 
-static CK_RV digest_update(const hal_hash_descriptor_t * const descriptor,
-                           hal_hash_state_t **state,
+static CK_RV digest_update(const p11_session_t * const session,
+                           const hal_digest_algorithm_t algorithm,
+                           hal_hash_handle_t *handle,
                            const uint8_t * const data, const size_t data_len)
 {
-  assert(descriptor != NULL && state != NULL && data != NULL);
+  assert(algorithm != hal_digest_algorithm_none && handle != NULL && data != NULL);
 
-  if (*state == NULL) {
-    switch (hal_hash_initialize(NULL, descriptor, state, NULL, 0)) {
+  if (handle->handle == HAL_HANDLE_NONE) {
+    switch (hal_rpc_hash_initialize(p11_session_hal_client(session),
+                                    p11_session_hal_session(session),
+                                    handle, algorithm, NULL, 0)) {
     case HAL_OK:
       break;
     case HAL_ERROR_ALLOCATION_FAILURE:
@@ -2209,130 +2061,88 @@ static CK_RV digest_update(const hal_hash_descriptor_t * const descriptor,
     }
   }
 
-  if (!hal_check(hal_hash_update(*state, data, data_len)))
+  if (!hal_check(hal_rpc_hash_update(*handle, data, data_len)))
     return CKR_FUNCTION_FAILED;
 
   return CKR_OK;
 }
 
 /*
- * Construct a PKCS #1 DigestInfo object.  This requires some (very
- * basic) ASN.1 encoding, which we perform inline.
+ * Finish using a digest context, if we haven't already.
  */
 
-static int pkcs1_construct_digestinfo(const hal_hash_descriptor_t * const desc,
-                                      hal_hash_state_t *state,
-                                      uint8_t *digest_info, const size_t digest_info_len)
+static void digest_cleanup(hal_hash_handle_t *handle)
 {
-  assert(desc != NULL && state != NULL && digest_info != NULL);
-
-  /*
-   * Make sure size of output buffer is right.  Caller is responsible
-   * for supplying the right length, the check here is just paranoia.
-   *
-   * This encoder will fail if the DigestInfo object is more than
-   * 129 octets long.  Rewrite if and when we need to support
-   * digests or OIDs long enough for that to be an issue.
-   */
-
-  assert(digest_info_len == desc->digest_length + desc->digest_algorithm_id_length + 4);
-  assert(digest_info_len < 130);
-
-  uint8_t *d = digest_info;
-
-  *d++ = 0x30;                /* SEQUENCE */
-  *d++ = (uint8_t) (digest_info_len - 2);
-
-  memcpy(d, desc->digest_algorithm_id, desc->digest_algorithm_id_length);
-  d += desc->digest_algorithm_id_length;
-
-  *d++ = 0x04;                /* OCTET STRING */
-  *d++ = (uint8_t) desc->digest_length;
-
-  assert(digest_info + digest_info_len == d + desc->digest_length);
-
-  return hal_check(hal_hash_finalize(state, d, desc->digest_length));
+  assert(handle != NULL);
+  if (handle->handle == HAL_HANDLE_NONE)
+    return;
+  (void) hal_rpc_hash_finalize(*handle, NULL, 0);
+  handle->handle = HAL_HANDLE_NONE;
 }
 
 /*
- * Pad an octet string with PKCS #1.5 padding for use with RSA.
- *
- * For the moment, this only handles type 01 encryption blocks, thus
- * is only suitable for use with signature and verification.  If and
- * when we add support for encryption and decryption, this function
- * should be extended to take an argument specifying the block type
- * and include support for generating type 02 encryption blocks.
- * Other than the block type code, the only difference is the padding
- * value: for type 01 it's constant (0xFF), for type 02 it should be
- * non-zero random bytes from the CSPRNG.
+ * Compute the length of a signature based on the key.  We could get
+ * this via the RPC API, but its probably faster to look in the local
+ * attribute database.  Rewrite this later if this proves incorrect.
  */
 
-static int pkcs1_5_pad(const uint8_t * const data, const size_t data_len,
-                       uint8_t *block, const size_t block_len)
+static int get_signature_len(const CK_OBJECT_HANDLE object_handle,
+                             const hal_pkey_handle_t pkey,
+                             size_t *signature_len)
 {
-  assert(data != NULL && block != NULL);
+  assert(signature_len != NULL);
 
-  /*
-   * Congregation will now please turn to RFC 2313 8.1 as we
-   * construct a PKCS #1.5 type 01 encryption block.
-   */
+  CK_KEY_TYPE cka_key_type;
+  hal_curve_name_t curve;
+  CK_BYTE oid[20];
+  CK_ULONG len;
 
-  if (data_len > block_len - 11)
+  if (!p11_attribute_get_ulong(object_handle, CKA_KEY_TYPE, &cka_key_type))
     return 0;
 
-  block[0] = 0x00;
-  block[1] = 0x01;
+  switch (cka_key_type) {
 
-  /* This is where we'd use non-zero random bytes if constructing a type 02 block. */
-  memset(block + 2, 0xFF, block_len - 3 - data_len);
-
-  block[block_len - data_len - 1] = 0x00;
-  memcpy(block + block_len - data_len, data, data_len);
+  case CKK_RSA:
+    if (!p11_attribute_get(object_handle, CKA_MODULUS, NULL, &len, 0))
+      return 0;
+    *signature_len = len;
+    return 1;
 
-#if DEBUG_PKCS11 > 1
-  fprintf(stderr, "[PKCS #1.5 block_len %lu data_len %lu block ",
-          (unsigned long) block_len, (unsigned long) data_len);
-  for (int i = 0; i < block_len; i++)
-    fprintf(stderr, "%s%02x", i == 0 ? "" : ":", block[i]);
-  fprintf(stderr, "]\n");
-#endif
+  case CKK_EC:
+    if (!p11_attribute_get(object_handle, CKA_EC_PARAMS, oid, &len, sizeof(oid)) ||
+        !ec_curve_oid_to_name(oid, len, &curve))
+      return 0;
+    switch (curve) {
+    case HAL_CURVE_P256: *signature_len = 64;  return 1;
+    case HAL_CURVE_P384: *signature_len = 96;  return 1;
+    case HAL_CURVE_P521: *signature_len = 132; return 1;
+    default:                                   return 0;
+   }
+  }
 
-  return 1;
+  return 0;
 }
 
 /*
- * Generate an RSA PKCS #1.5 signature.
- *
- * As explained in RFC 3447, the RSASP1 (signature generation)
- * operation is the same mathematical operation as the RSADP
- * (decryption) operation (both use the private key as exponent).
+ * Generate a signature using the libhal RPC API.
  */
 
-static CK_RV sign_rsa_pkcs(p11_session_t *session,
-                           CK_BYTE_PTR pData,
-                           CK_ULONG ulDataLen,
-                           CK_BYTE_PTR pSignature,
-                           CK_ULONG_PTR pulSignatureLen)
+static CK_RV sign_hal_rpc(p11_session_t *session,
+                          CK_BYTE_PTR pData,
+                          CK_ULONG ulDataLen,
+                          CK_BYTE_PTR pSignature,
+                          CK_ULONG_PTR pulSignatureLen)
 {
-  uint8_t keybuf[hal_rsa_key_t_size];
-  hal_rsa_key_t *key = NULL;
+  hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
   size_t signature_len;
   CK_RV rv;
 
   assert(session != NULL && pulSignatureLen != NULL);
 
-  const hal_hash_descriptor_t * const descriptor = session->sign_digest_descriptor;
-  uint8_t digest_info[descriptor == NULL ? 1 : descriptor->digest_length + 4 + descriptor->digest_algorithm_id_length];
-
-  if (!p11_object_get_rsa_private_key(session->sign_key_handle,
-                                      &key, keybuf, sizeof(keybuf)))
+  if (!p11_object_get_pkey_handle(session, session->sign_key_handle, &pkey))
     lose(CKR_FUNCTION_FAILED);
 
-  /*
-   * Retrieve signature length, which is just the the modulus length.
-   */
-
-  if (!hal_check(hal_rsa_key_get_modulus(key, NULL, &signature_len, 0)))
+  if (!get_signature_len(session->sign_key_handle, pkey, &signature_len))
     lose(CKR_FUNCTION_FAILED);
 
   rv = signature_len > *pulSignatureLen ? CKR_BUFFER_TOO_SMALL : CKR_OK;
@@ -2342,205 +2152,53 @@ static CK_RV sign_rsa_pkcs(p11_session_t *session,
   if (pSignature != NULL && rv == CKR_BUFFER_TOO_SMALL)
     lose(CKR_BUFFER_TOO_SMALL);
 
-  if (pSignature != NULL && descriptor != NULL) {
-
-    if (!pkcs1_construct_digestinfo(descriptor, session->sign_digest_state, digest_info, sizeof(digest_info)))
-      lose(CKR_FUNCTION_FAILED);
-
-    pData = digest_info;
-    ulDataLen = sizeof(digest_info);
-  }
-
-  if (pSignature != NULL) {
-
-    if (!pkcs1_5_pad(pData, ulDataLen, pSignature, signature_len))
-      lose(CKR_DATA_LEN_RANGE);
-
-    if (!hal_check(hal_rsa_decrypt(NULL, key, pSignature, signature_len, pSignature, signature_len)))
-      lose(CKR_FUNCTION_FAILED);
-  }
+#warning Should pay more attention to translating error codes here
+  if (pSignature != NULL &&
+      !hal_check(hal_rpc_pkey_sign(p11_session_hal_session(session), pkey, session->sign_digest_handle,
+                                   pData, ulDataLen, pSignature, pulSignatureLen, signature_len)))
+    lose(CKR_FUNCTION_FAILED);
 
   rv = CKR_OK;                  /* Fall through */
 
  fail:
-  hal_rsa_key_clear(key);
+  hal_rpc_pkey_close(pkey);
   return rv;
 }
 
 /*
- * Verify a PKCS #1.5 padded RSA signature.
- *
- * We don't bother decoding the ASN.1, we just generate the type 01
- * encryption block we expect and compare it with what we got.
- *
- * Using constant-time comparision code for this is probably
- * unnecessary, but it's also harmless.
+ * Verify a signature using the libhal RPC API.
  */
 
-static CK_RV verify_rsa_pkcs(p11_session_t *session,
-                             CK_BYTE_PTR pData,
-                             CK_ULONG ulDataLen,
-                             CK_BYTE_PTR pSignature,
-                             CK_ULONG ulSignatureLen)
+static CK_RV verify_hal_rpc(p11_session_t *session,
+                            CK_BYTE_PTR pData,
+                            CK_ULONG ulDataLen,
+                            CK_BYTE_PTR pSignature,
+                            CK_ULONG ulSignatureLen)
 {
-  uint8_t keybuf[hal_rsa_key_t_size];
-  hal_rsa_key_t *key = NULL;
+  hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
   CK_RV rv;
 
   assert(session != NULL);
 
-  const hal_hash_descriptor_t * const descriptor = session->verify_digest_descriptor;
-  uint8_t digest_info[descriptor == NULL ? 1 : descriptor->digest_length + 4 + descriptor->digest_algorithm_id_length];
-  uint8_t expected[ulSignatureLen], received[ulSignatureLen];
-  unsigned diff = 0;
-
-  if (!p11_object_get_rsa_public_key(session->verify_key_handle,
-                                     &key, keybuf, sizeof(keybuf)))
+  if (!p11_object_get_pkey_handle(session, session->verify_key_handle, &pkey))
     lose(CKR_FUNCTION_FAILED);
 
-  if (session->verify_digest_descriptor != NULL) {
-
-    if (!pkcs1_construct_digestinfo(session->verify_digest_descriptor,
-                                    session->verify_digest_state,
-                                    digest_info, sizeof(digest_info)))
-      lose(CKR_FUNCTION_FAILED);
-
-    pData = digest_info;
-    ulDataLen = sizeof(digest_info);
-
-  }
-
-  if (!pkcs1_5_pad(pData, ulDataLen, expected, sizeof(expected)))
-    lose(CKR_DATA_LEN_RANGE);
+#warning Should pay more attention to translating error codes here
 
-  if (!hal_check(hal_rsa_encrypt(NULL, key, pSignature, ulSignatureLen, received, sizeof(received))))
+  if (!hal_check(hal_rpc_pkey_verify(p11_session_hal_session(session), pkey, session->verify_digest_handle,
+                                     pData, ulDataLen, pSignature, ulSignatureLen)))
     lose(CKR_FUNCTION_FAILED);
-
-  for (int i = 0; i < ulSignatureLen; i++)
-    diff |= expected[i] ^ received[i];
-
-  if (diff != 0)
-    lose(CKR_SIGNATURE_INVALID);
+ /* lose(CKR_SIGNATURE_INVALID); */
 
   rv = CKR_OK;                  /* Fall through */
 
  fail:
-  hal_rsa_key_clear(key);
+  hal_rpc_pkey_close(pkey);
   return rv;
 }
 
 #warning May need to do something about truncating oversized hashes for ECDSA, see PKCS11 spec
 
-/*
- * Generate an ECDSA signature.
- */
-
-static CK_RV sign_ecdsa(p11_session_t *session,
-                        CK_BYTE_PTR pData,
-                        CK_ULONG ulDataLen,
-                        CK_BYTE_PTR pSignature,
-                        CK_ULONG_PTR pulSignatureLen)
-{
-  uint8_t keybuf[hal_ecdsa_key_t_size];
-  hal_ecdsa_key_t *key = NULL;
-  hal_curve_name_t curve;
-  size_t signature_len;
-  CK_RV rv;
-
-  assert(session != NULL && pulSignatureLen != NULL);
-
-  const hal_hash_descriptor_t * const descriptor = session->sign_digest_descriptor;
-  uint8_t digest[descriptor == NULL ? 1 : descriptor->digest_length];
-
-  if (!p11_object_get_ec_private_key(session->sign_key_handle, &key, keybuf, sizeof(keybuf)))
-    lose(CKR_FUNCTION_FAILED);
-
-  /*
-   * Signature length is determined by curve parameters.
-   */
-
-  if (!hal_check(hal_ecdsa_key_get_curve(key, &curve)))
-    lose(CKR_FUNCTION_FAILED);
-
-  switch (curve) {
-  case HAL_CURVE_P256: signature_len = 256; break;
-  case HAL_CURVE_P384: signature_len = 384; break;
-  case HAL_CURVE_P521: signature_len = 521; break;
-  default: lose(CKR_FUNCTION_FAILED);
-  }
-
-  signature_len = ((signature_len + 7) / 8) * 2;
-
-  rv = signature_len > *pulSignatureLen ? CKR_BUFFER_TOO_SMALL : CKR_OK;
-
-  *pulSignatureLen = signature_len;
-
-  if (pSignature != NULL && rv == CKR_BUFFER_TOO_SMALL)
-    lose(CKR_BUFFER_TOO_SMALL);
-
-  if (pSignature != NULL && descriptor != NULL) {
-
-    if (!hal_check(hal_hash_finalize(session->sign_digest_state, digest, sizeof(digest))))
-      lose(CKR_FUNCTION_FAILED);
-
-    pData = digest;
-    ulDataLen = sizeof(digest);
-  }
-
-  if (pSignature != NULL && !hal_check(hal_ecdsa_sign(NULL, key, pData, ulDataLen,
-                                                      pSignature, &signature_len, *pulSignatureLen)))
-    lose(CKR_FUNCTION_FAILED);
-
-  assert(signature_len == *pulSignatureLen);
-
-  rv = CKR_OK;                  /* Fall through */
-
- fail:
-  hal_ecdsa_key_clear(key);
-  return rv;
-}
-
-/*
- * Verify an ECDSA signature.
- */
-
-static CK_RV verify_ecdsa(p11_session_t *session,
-                          CK_BYTE_PTR pData,
-                          CK_ULONG ulDataLen,
-                          CK_BYTE_PTR pSignature,
-                          CK_ULONG ulSignatureLen)
-{
-  uint8_t keybuf[hal_ecdsa_key_t_size];
-  hal_ecdsa_key_t *key = NULL;
-  CK_RV rv;
-
-  assert(session != NULL && pSignature != NULL);
-
-  const hal_hash_descriptor_t * const descriptor = session->verify_digest_descriptor;
-  uint8_t digest[descriptor == NULL ? 1 : descriptor->digest_length];
-
-  if (!p11_object_get_ec_public_key(session->verify_key_handle, &key, keybuf, sizeof(keybuf)))
-    lose(CKR_FUNCTION_FAILED);
-
-  if (session->verify_digest_descriptor != NULL) {
-
-    if (!hal_check(hal_hash_finalize(session->verify_digest_state, digest, sizeof(digest))))
-      lose(CKR_FUNCTION_FAILED);
-
-    pData = digest;
-    ulDataLen = sizeof(digest);
-  }
-
-  if (!hal_check(hal_ecdsa_verify(NULL, key, pData, ulDataLen, pSignature, ulSignatureLen)))
-    lose(CKR_SIGNATURE_INVALID);
-
-  rv = CKR_OK;                  /* Fall through */
-
- fail:
-  hal_ecdsa_key_clear(key);
-  return rv;
-}
-
 

 
 /*
@@ -2958,13 +2616,11 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession,
 {
   ENTER_PUBLIC_FUNCTION(C_Login);
 
-  static const char pin_query_format[] =
-    " SELECT pbkdf2_iterations, %s_pin, %s_pin_salt FROM global";
-
+  const hal_client_handle_t client = {HAL_HANDLE_NONE};
   p11_session_t *session;
-  sqlite3_stmt *q = NULL;
-  const char *pin_type;
+  hal_user_t user = HAL_USER_NONE;
   CK_RV rv = CKR_OK;
+  hal_error_t err;
 
   mutex_lock_or_return_failure(p11_global_mutex);
 
@@ -2998,13 +2654,13 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession,
 
   switch (userType) {
   case CKU_USER:
-    pin_type = "user";
+    user = HAL_USER_NORMAL;
     break;
   case CKU_SO:
     for (session = p11_sessions; session != NULL; session = session->link)
       if (session->state == CKS_RO_PUBLIC_SESSION)
         lose(CKR_SESSION_READ_ONLY_EXISTS);
-    pin_type = "so";
+    user = HAL_USER_SO;
     break;
   case CKU_CONTEXT_SPECIFIC:
     lose(CKR_OPERATION_NOT_INITIALIZED);
@@ -3013,53 +2669,15 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession,
   }
 
   /*
-   * Look up the PIN and make sure it's set.
-   *
-   * Not obvious what error we should return if SO PIN isn't set, for
-   * now consider this state "locked" (because it hasn't been set yet).
-   */
-
-  if (!sql_check_ok(sql_prepare(&q, pin_query_format, pin_type, pin_type)) ||
-      !sql_check_row(sqlite3_step(q)))
-    lose(CKR_FUNCTION_FAILED);
-
-  if (sqlite3_column_type(q, 1) == SQLITE_NULL ||
-      sqlite3_column_type(q, 2) == SQLITE_NULL) {
-    switch (userType) {
-    case CKU_USER:
-      lose(CKR_USER_PIN_NOT_INITIALIZED);
-    case CKU_SO:
-      lose(CKR_PIN_LOCKED);
-    default:
-      lose(CKR_USER_TYPE_INVALID);
-    }
-  }
-
-  /*
-   * Run PBKDF2 over the supplied PIN and compare results.
-   *
-   * Probably not really necessary to use constant-time string
-   * comparison, but it's harmless and cheap, so we might as well.
+   * Try to log in the HSM.
    */
 
-  {
-    const unsigned iterations = sqlite3_column_int(q, 0);
-    const uint8_t * const pin  = sqlite3_column_blob(q, 1);
-    const uint8_t * const salt = sqlite3_column_blob(q, 2);
-    const size_t pin_len  = sqlite3_column_bytes(q, 1);
-    const size_t salt_len = sqlite3_column_bytes(q, 2);
-    uint8_t pinbuf[pin_len];
-    unsigned diff = 0;
-
-    if (!hal_check(hal_pbkdf2(NULL, hal_hash_sha256, pPin, ulPinLen, salt, salt_len,
-                              pinbuf, sizeof(pinbuf), iterations)))
-      lose(CKR_FUNCTION_FAILED);
-
-    for (int i = 0; i < pin_len; i++)
-      diff |= pin[i] ^ pinbuf[i];
-
-    if (diff != 0)
+#warning Might need better error code translation here
+  if (!hal_check((err = hal_rpc_login(client, user, (char *) pPin, ulPinLen)))) {
+    if (err == HAL_ERROR_PIN_INCORRECT)
       lose(CKR_PIN_INCORRECT);
+    else
+      lose(CKR_FUNCTION_FAILED);
   }
 
   /*
@@ -3089,7 +2707,6 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession,
   assert(p11_session_consistent_login());
 
  fail:
-  sqlite3_finalize(q);
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
 }
 
@@ -3097,6 +2714,7 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession)
 {
   ENTER_PUBLIC_FUNCTION(C_Logout);
 
+  const hal_client_handle_t client = {HAL_HANDLE_NONE};
   p11_session_t *session;
   CK_RV rv = CKR_OK;
 
@@ -3121,6 +2739,10 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession)
 
   assert(p11_session_consistent_login());
 
+#warning Might want better error translation here
+  if (!hal_check(hal_rpc_logout(client)))
+    lose(CKR_FUNCTION_FAILED);
+
   logged_in_as = not_logged_in;
 
   p11_object_delete_all_private();
@@ -3153,6 +2775,7 @@ CK_RV C_CreateObject(CK_SESSION_HANDLE hSession,
 {
   ENTER_PUBLIC_FUNCTION(C_CreateObject);
 
+  CK_OBJECT_HANDLE handle = CK_INVALID_HANDLE;
   p11_session_t *session;
   CK_RV rv;
 
@@ -3205,7 +2828,8 @@ CK_RV C_CreateObject(CK_SESSION_HANDLE hSession,
   const handle_flavor_t flavor
     = cka_token == NULL ? handle_flavor_session_object : p11_handle_flavor_from_cka_token(cka_token);
 
-  CK_OBJECT_HANDLE handle = p11_object_create(session, flavor, pTemplate, ulCount, descriptor, NULL);
+  if ((handle = p11_object_create(session, flavor, pTemplate, ulCount, descriptor, NULL)) == CK_INVALID_HANDLE)
+    lose(CKR_FUNCTION_FAILED);
 
   if (!p11_attribute_set_bbool(handle, CKA_LOCAL, CK_FALSE))
     lose(CKR_FUNCTION_FAILED);
@@ -3218,6 +2842,8 @@ 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
+
   if (!sql_exec("COMMIT"))
     lose(CKR_FUNCTION_FAILED);
 
@@ -3244,6 +2870,7 @@ CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession,
     " WHERE token_object_id = (SELECT token_object_id FROM object WHERE object_handle = ?)";
 
 
+  hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
   p11_session_t *session;
   sqlite3_stmt *q = NULL;
   CK_RV rv = CKR_OK;
@@ -3255,6 +2882,9 @@ CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession,
   if ((rv = p11_object_check_rights(session, hObject, p11_object_access_write)) != CKR_OK)
     goto fail;
 
+  if (p11_object_get_pkey_handle(session, hObject, &pkey) && !hal_check(hal_rpc_pkey_delete(pkey)))
+    lose(CKR_FUNCTION_FAILED);
+
   if (is_token_handle(hObject)                                  &&
       (!sql_check_ok(sql_prepare(&q, delete_token_object))      ||
        !sql_check_ok(sqlite3_bind_int64(q, 1, hObject))         ||
@@ -3604,6 +3234,7 @@ CK_RV C_DigestInit(CK_SESSION_HANDLE hSession,
 {
   ENTER_PUBLIC_FUNCTION(C_DigestInit);
 
+  hal_digest_algorithm_t algorithm;
   p11_session_t *session;
   CK_RV rv = CKR_OK;
 
@@ -3615,22 +3246,18 @@ CK_RV C_DigestInit(CK_SESSION_HANDLE hSession,
   if (pMechanism == NULL)
     lose(CKR_ARGUMENTS_BAD);
 
-  if (session->digest_descriptor != NULL)
+  if (session->digest_algorithm != hal_digest_algorithm_none)
     lose(CKR_OPERATION_ACTIVE);
 
   switch (pMechanism->mechanism) {
-  case CKM_SHA_1:       session->digest_descriptor = hal_hash_sha1;   break;
-  case CKM_SHA256:      session->digest_descriptor = hal_hash_sha256; break;
-  case CKM_SHA384:      session->digest_descriptor = hal_hash_sha384; break;
-  case CKM_SHA512:      session->digest_descriptor = hal_hash_sha512; break;
+  case CKM_SHA_1:       algorithm = hal_digest_algorithm_sha1;   break;
+  case CKM_SHA256:      algorithm = hal_digest_algorithm_sha256; break;
+  case CKM_SHA384:      algorithm = hal_digest_algorithm_sha384; break;
+  case CKM_SHA512:      algorithm = hal_digest_algorithm_sha512; break;
   default:              lose(CKR_MECHANISM_INVALID);
   }
 
-  if (hal_core_find(session->digest_descriptor->core_name, NULL) == NULL) {
-    session->digest_descriptor = NULL;
-    lose(CKR_MECHANISM_INVALID);
-  }
-
+  session->digest_algorithm = algorithm;
   return mutex_unlock(p11_global_mutex);
 
  fail:
@@ -3646,6 +3273,7 @@ CK_RV C_Digest(CK_SESSION_HANDLE hSession,
   ENTER_PUBLIC_FUNCTION(C_Digest);
 
   p11_session_t *session;
+  size_t digest_len;
   CK_RV rv = CKR_OK;
 
   mutex_lock_or_return_failure(p11_global_mutex);
@@ -3656,15 +3284,18 @@ CK_RV C_Digest(CK_SESSION_HANDLE hSession,
   if (pData == NULL || pulDigestLen == NULL)
     lose(CKR_ARGUMENTS_BAD);
 
-  if (session->digest_descriptor == NULL)
+  if (session->digest_algorithm == hal_digest_algorithm_none)
     lose(CKR_OPERATION_NOT_INITIALIZED);
 
-  if (session->digest_state != NULL)
+  if (session->digest_handle.handle != HAL_HANDLE_NONE)
     lose(CKR_OPERATION_ACTIVE);
 
-  rv = *pulDigestLen < session->digest_descriptor->digest_length ? CKR_BUFFER_TOO_SMALL : CKR_OK;
+  if (!hal_check(hal_rpc_hash_get_digest_length(session->digest_algorithm, &digest_len)))
+    lose(CKR_FUNCTION_FAILED);
 
-  *pulDigestLen = session->digest_descriptor->digest_length;
+  rv = *pulDigestLen < digest_len ? CKR_BUFFER_TOO_SMALL : CKR_OK;
+
+  *pulDigestLen = digest_len;
 
   if (pDigest == NULL)
     return mutex_unlock(p11_global_mutex);
@@ -3672,19 +3303,19 @@ CK_RV C_Digest(CK_SESSION_HANDLE hSession,
   if (rv == CKR_BUFFER_TOO_SMALL)
     lose(CKR_BUFFER_TOO_SMALL);
 
-  if ((rv = digest_update(session->digest_descriptor, &session->digest_state,
-                          pData, ulDataLen)) != CKR_OK)
+  if ((rv = digest_update(session, session->digest_algorithm,
+                          &session->digest_handle, pData, ulDataLen)) != CKR_OK)
     goto fail;
 
-  if (!hal_check(hal_hash_finalize(session->digest_state, pDigest, *pulDigestLen)))
+  if (!hal_check(hal_rpc_hash_finalize(session->digest_handle, pDigest, *pulDigestLen)))
     lose(CKR_FUNCTION_FAILED);
 
   rv = CKR_OK;                  /* Fall through */
 
  fail:
   if (session != NULL) {
-    hal_hash_cleanup(&session->digest_state);
-    session->digest_descriptor = NULL;
+    digest_cleanup(&session->digest_handle);
+    session->digest_algorithm = hal_digest_algorithm_none;
   }
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
 }
@@ -3706,23 +3337,19 @@ CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession,
   if (pPart == NULL)
     lose(CKR_ARGUMENTS_BAD);
 
-  if (session->digest_descriptor == NULL)
+  if (session->digest_algorithm == hal_digest_algorithm_none)
     lose(CKR_OPERATION_NOT_INITIALIZED);
 
-  if (!session->digest_descriptor->can_restore_state)
-    lose(CKR_FUNCTION_FAILED);
-
-  if ((rv = digest_update(session->digest_descriptor,
-                          &session->digest_state,
-                          pPart, ulPartLen)) != CKR_OK)
+  if ((rv = digest_update(session, session->digest_algorithm,
+                          &session->digest_handle, pPart, ulPartLen)) != CKR_OK)
     goto fail;
 
   return mutex_unlock(p11_global_mutex);
 
  fail:
   if (session != NULL) {
-    hal_hash_cleanup(&session->digest_state);
-    session->digest_descriptor = NULL;
+    digest_cleanup(&session->digest_handle);
+    session->digest_algorithm = hal_digest_algorithm_none;
   }
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
 }
@@ -3734,6 +3361,7 @@ CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession,
   ENTER_PUBLIC_FUNCTION(C_DigestFinal);
 
   p11_session_t *session;
+  size_t digest_len;
   CK_RV rv = CKR_OK;
 
   mutex_lock_or_return_failure(p11_global_mutex);
@@ -3744,12 +3372,15 @@ CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession,
   if (pulDigestLen == NULL)
     lose(CKR_ARGUMENTS_BAD);
 
-  if (session->digest_descriptor == NULL || session->digest_state == NULL)
+  if (session->digest_algorithm == hal_digest_algorithm_none || session->digest_handle.handle == HAL_HANDLE_NONE)
     lose(CKR_OPERATION_NOT_INITIALIZED);
 
-  rv = *pulDigestLen < session->digest_descriptor->digest_length ? CKR_BUFFER_TOO_SMALL : CKR_OK;
+  if (!hal_check(hal_rpc_hash_get_digest_length(session->digest_algorithm, &digest_len)))
+    lose(CKR_FUNCTION_FAILED);
+
+  rv = *pulDigestLen < digest_len ? CKR_BUFFER_TOO_SMALL : CKR_OK;
 
-  *pulDigestLen = session->digest_descriptor->digest_length;
+  *pulDigestLen = digest_len;
 
   if (pDigest == NULL)
     return mutex_unlock(p11_global_mutex);
@@ -3757,15 +3388,15 @@ CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession,
   if (rv == CKR_BUFFER_TOO_SMALL)
     lose(CKR_BUFFER_TOO_SMALL);
 
-  if (!hal_check(hal_hash_finalize(session->digest_state, pDigest, *pulDigestLen)))
+  if (!hal_check(hal_rpc_hash_finalize(session->digest_handle, pDigest, *pulDigestLen)))
     lose(CKR_FUNCTION_FAILED);
 
   rv = CKR_OK;                  /* Fall through */
 
  fail:
   if (session != NULL) {
-    hal_hash_cleanup(&session->digest_state);
-    session->digest_descriptor = NULL;
+    digest_cleanup(&session->digest_handle);
+    session->digest_algorithm = hal_digest_algorithm_none;
   }
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
 }
@@ -3790,7 +3421,7 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession,
   if (pMechanism == NULL)
     lose(CKR_ARGUMENTS_BAD);
 
-  if (session->sign_key_handle != CK_INVALID_HANDLE || session->sign_digest_descriptor != NULL)
+  if (session->sign_key_handle != CK_INVALID_HANDLE || session->sign_digest_algorithm != hal_digest_algorithm_none)
     lose(CKR_OPERATION_ACTIVE);
 
   if ((rv = p11_object_check_rights(session, hKey, p11_object_access_read)) != CKR_OK)
@@ -3830,22 +3461,22 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession,
   switch (pMechanism->mechanism) {
   case CKM_RSA_PKCS:
   case CKM_ECDSA:
-    session->sign_digest_descriptor = NULL;
+    session->sign_digest_algorithm = hal_digest_algorithm_none;
     break;
   case CKM_SHA1_RSA_PKCS:
-    session->sign_digest_descriptor = hal_hash_sha1;
+    session->sign_digest_algorithm = hal_digest_algorithm_sha1;
     break;
   case CKM_SHA256_RSA_PKCS:
   case CKM_ECDSA_SHA256:
-    session->sign_digest_descriptor = hal_hash_sha256;
+    session->sign_digest_algorithm = hal_digest_algorithm_sha256;
     break;
   case CKM_SHA384_RSA_PKCS:     
   case CKM_ECDSA_SHA384:
-    session->sign_digest_descriptor = hal_hash_sha384;
+    session->sign_digest_algorithm = hal_digest_algorithm_sha384;
     break;
   case CKM_SHA512_RSA_PKCS:     
   case CKM_ECDSA_SHA512:
-    session->sign_digest_descriptor = hal_hash_sha512;
+    session->sign_digest_algorithm = hal_digest_algorithm_sha512;
     break;
   default:
     return CKR_MECHANISM_INVALID;
@@ -3856,7 +3487,7 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession,
  fail:
   if (session != NULL) {
     session->sign_key_handle = CK_INVALID_HANDLE;
-    session->sign_digest_descriptor = NULL;
+    session->sign_digest_algorithm = hal_digest_algorithm_none;
   }
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
 }
@@ -3884,25 +3515,25 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession,
   if (session->sign_key_handle == CK_INVALID_HANDLE)
     lose(CKR_OPERATION_NOT_INITIALIZED);
 
-  if (session->sign_digest_state != NULL)
+  if (session->sign_digest_handle.handle != HAL_HANDLE_NONE)
     lose(CKR_OPERATION_ACTIVE);
 
-  if (session->sign_digest_descriptor != NULL && pSignature != NULL &&
-      (rv = digest_update(session->sign_digest_descriptor,
-                          &session->sign_digest_state, pData, ulDataLen)) != CKR_OK)
-    goto fail;
-
   if (!p11_attribute_get_ulong(session->sign_key_handle, CKA_KEY_TYPE, &key_type))
     lose(CKR_FUNCTION_FAILED);
 
+  if (session->sign_digest_algorithm != hal_digest_algorithm_none && pSignature != NULL) {
+    if ((rv = digest_update(session, session->sign_digest_algorithm,
+                            &session->sign_digest_handle, pData, ulDataLen)) != CKR_OK)
+      goto fail;
+    pData = NULL;
+    ulDataLen = 0;
+  }
+
   switch (key_type) {
 
   case CKK_RSA:
-    rv = sign_rsa_pkcs(session, pData, ulDataLen, pSignature, pulSignatureLen);
-    break;
-
   case CKK_EC:
-    rv = sign_ecdsa(session, pData, ulDataLen, pSignature, pulSignatureLen);
+    rv = sign_hal_rpc(session, pData, ulDataLen, pSignature, pulSignatureLen);
     break;
 
   default:
@@ -3912,8 +3543,8 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession,
  fail:
   if (session != NULL && pSignature != NULL) {
     session->sign_key_handle = CK_INVALID_HANDLE;
-    session->sign_digest_descriptor = NULL;
-    hal_hash_cleanup(&session->sign_digest_state);
+    session->sign_digest_algorithm = hal_digest_algorithm_none;
+    digest_cleanup(&session->sign_digest_handle);
   }
 
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
@@ -3939,12 +3570,11 @@ CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession,
   if (session->sign_key_handle == CK_INVALID_HANDLE)
     lose(CKR_OPERATION_NOT_INITIALIZED);
 
-  if (session->sign_digest_descriptor == NULL || !session->sign_digest_descriptor->can_restore_state)
+  if (session->sign_digest_algorithm == hal_digest_algorithm_none)
     lose(CKR_FUNCTION_FAILED);
 
-  if ((rv = digest_update(session->sign_digest_descriptor,
-                          &session->sign_digest_state,
-                          pPart, ulPartLen)) != CKR_OK)
+  if ((rv = digest_update(session, session->sign_digest_algorithm,
+                          &session->sign_digest_handle, pPart, ulPartLen)) != CKR_OK)
     goto fail;
 
   return mutex_unlock(p11_global_mutex);
@@ -3952,8 +3582,8 @@ CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession,
  fail:
   if (session != NULL) {
     session->sign_key_handle = CK_INVALID_HANDLE;
-    session->sign_digest_descriptor = NULL;
-    hal_hash_cleanup(&session->sign_digest_state);
+    session->sign_digest_algorithm = hal_digest_algorithm_none;
+    digest_cleanup(&session->sign_digest_handle);
   }
 
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
@@ -3977,7 +3607,7 @@ CK_RV C_SignFinal(CK_SESSION_HANDLE hSession,
   if (pulSignatureLen == NULL)
     lose(CKR_ARGUMENTS_BAD);
 
-  if (session->sign_key_handle == CK_INVALID_HANDLE || session->sign_digest_state == NULL)
+  if (session->sign_key_handle == CK_INVALID_HANDLE || session->sign_digest_handle.handle == HAL_HANDLE_NONE)
     lose(CKR_OPERATION_NOT_INITIALIZED);
 
   if (!p11_attribute_get_ulong(session->sign_key_handle, CKA_KEY_TYPE, &key_type))
@@ -3986,11 +3616,8 @@ CK_RV C_SignFinal(CK_SESSION_HANDLE hSession,
   switch (key_type) {
 
   case CKK_RSA:
-    rv = sign_rsa_pkcs(session, NULL, 0, pSignature, pulSignatureLen);
-    break;
-
   case CKK_EC:
-    rv = sign_ecdsa(session, NULL, 0, pSignature, pulSignatureLen);
+    rv = sign_hal_rpc(session, NULL, 0, pSignature, pulSignatureLen);
     break;
 
   default:
@@ -4000,8 +3627,8 @@ CK_RV C_SignFinal(CK_SESSION_HANDLE hSession,
  fail:
   if (session != NULL && pSignature != NULL) {
     session->sign_key_handle = CK_INVALID_HANDLE;
-    session->sign_digest_descriptor = NULL;
-    hal_hash_cleanup(&session->sign_digest_state);
+    session->sign_digest_algorithm = hal_digest_algorithm_none;
+    digest_cleanup(&session->sign_digest_handle);
   }
 
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
@@ -4027,7 +3654,7 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession,
   if (pMechanism == NULL)
     lose(CKR_ARGUMENTS_BAD);
 
-  if (session->verify_key_handle != CK_INVALID_HANDLE || session->verify_digest_descriptor != NULL)
+  if (session->verify_key_handle != CK_INVALID_HANDLE || session->verify_digest_algorithm != hal_digest_algorithm_none)
     lose(CKR_OPERATION_ACTIVE);
 
   if ((rv = p11_object_check_rights(session, hKey, p11_object_access_read)) != CKR_OK)
@@ -4067,22 +3694,22 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession,
   switch (pMechanism->mechanism) {
   case CKM_RSA_PKCS:
   case CKM_ECDSA:
-    session->verify_digest_descriptor = NULL;
+    session->verify_digest_algorithm = hal_digest_algorithm_none;
     break;
   case CKM_SHA1_RSA_PKCS:
-    session->verify_digest_descriptor = hal_hash_sha1;
+    session->verify_digest_algorithm = hal_digest_algorithm_sha1;
     break;
   case CKM_SHA256_RSA_PKCS:
   case CKM_ECDSA_SHA256:
-    session->verify_digest_descriptor = hal_hash_sha256;
+    session->verify_digest_algorithm = hal_digest_algorithm_sha256;
     break;
   case CKM_SHA384_RSA_PKCS:
   case CKM_ECDSA_SHA384:
-    session->verify_digest_descriptor = hal_hash_sha384;
+    session->verify_digest_algorithm = hal_digest_algorithm_sha384;
     break;
   case CKM_SHA512_RSA_PKCS:
   case CKM_ECDSA_SHA512:
-    session->verify_digest_descriptor = hal_hash_sha512;
+    session->verify_digest_algorithm = hal_digest_algorithm_sha512;
     break;
   default:
     return CKR_MECHANISM_INVALID;
@@ -4093,7 +3720,7 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession,
  fail:
   if (session != NULL) {
     session->verify_key_handle = CK_INVALID_HANDLE;
-    session->verify_digest_descriptor = NULL;
+    session->verify_digest_algorithm = hal_digest_algorithm_none;
   }
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
 }
@@ -4121,10 +3748,13 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession,
   if (session->verify_key_handle == CK_INVALID_HANDLE)
     lose(CKR_OPERATION_NOT_INITIALIZED);
 
-  if (session->verify_digest_descriptor != NULL &&
-      (rv = digest_update(session->verify_digest_descriptor,
-                          &session->verify_digest_state, pData, ulDataLen)) != CKR_OK)
-    goto fail;
+  if (session->verify_digest_algorithm != hal_digest_algorithm_none) {
+    if ((rv = digest_update(session, session->verify_digest_algorithm,
+                            &session->verify_digest_handle, pData, ulDataLen)) != CKR_OK)
+      goto fail;
+    pData = NULL;
+    ulDataLen = 0;
+  }
 
   if (!p11_attribute_get_ulong(session->verify_key_handle, CKA_KEY_TYPE, &key_type))
     lose(CKR_FUNCTION_FAILED);
@@ -4132,11 +3762,8 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession,
   switch (key_type) {
 
   case CKK_RSA:
-    rv = verify_rsa_pkcs(session, pData, ulDataLen, pSignature, ulSignatureLen);
-    break;
-
   case CKK_EC:
-    rv = verify_ecdsa(session, pData, ulDataLen, pSignature, ulSignatureLen);
+    rv = verify_hal_rpc(session, pData, ulDataLen, pSignature, ulSignatureLen);
     break;
 
   default:
@@ -4147,8 +3774,8 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession,
 
   if (session != NULL) {
     session->verify_key_handle = CK_INVALID_HANDLE;
-    session->verify_digest_descriptor = NULL;
-    hal_hash_cleanup(&session->verify_digest_state);
+    session->verify_digest_algorithm = hal_digest_algorithm_none;
+    digest_cleanup(&session->verify_digest_handle);
   }
 
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
@@ -4174,12 +3801,11 @@ CK_RV C_VerifyUpdate(CK_SESSION_HANDLE hSession,
   if (session->verify_key_handle == CK_INVALID_HANDLE)
     lose(CKR_OPERATION_NOT_INITIALIZED);
 
-  if (session->verify_digest_descriptor == NULL || !session->verify_digest_descriptor->can_restore_state)
+  if (session->verify_digest_algorithm == hal_digest_algorithm_none)
     lose(CKR_FUNCTION_FAILED);
 
-  if ((rv = digest_update(session->verify_digest_descriptor,
-                          &session->verify_digest_state,
-                          pPart, ulPartLen)) != CKR_OK)
+  if ((rv = digest_update(session, session->verify_digest_algorithm,
+                          &session->verify_digest_handle, pPart, ulPartLen)) != CKR_OK)
     goto fail;
 
   return mutex_unlock(p11_global_mutex);
@@ -4187,8 +3813,8 @@ CK_RV C_VerifyUpdate(CK_SESSION_HANDLE hSession,
  fail:
   if (session != NULL) {
     session->verify_key_handle = CK_INVALID_HANDLE;
-    session->verify_digest_descriptor = NULL;
-    hal_hash_cleanup(&session->verify_digest_state);
+    session->verify_digest_algorithm = hal_digest_algorithm_none;
+    digest_cleanup(&session->verify_digest_handle);
   }
 
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
@@ -4212,7 +3838,7 @@ CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession,
   if (pSignature == NULL)
     lose(CKR_ARGUMENTS_BAD);
 
-  if (session->verify_key_handle == CK_INVALID_HANDLE || session->verify_digest_state == NULL)
+  if (session->verify_key_handle == CK_INVALID_HANDLE || session->verify_digest_handle.handle == HAL_HANDLE_NONE)
     lose(CKR_OPERATION_NOT_INITIALIZED);
 
   if (!p11_attribute_get_ulong(session->verify_key_handle, CKA_KEY_TYPE, &key_type))
@@ -4221,11 +3847,8 @@ CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession,
   switch (key_type) {
 
   case CKK_RSA:
-    rv = verify_rsa_pkcs(session, NULL, 0, pSignature, ulSignatureLen);
-    break;
-
   case CKK_EC:
-    rv = verify_ecdsa(session, NULL, 0, pSignature, ulSignatureLen);
+    rv = verify_hal_rpc(session, NULL, 0, pSignature, ulSignatureLen);
     break;
 
   default:
@@ -4236,8 +3859,8 @@ CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession,
 
   if (session != NULL) {
     session->verify_key_handle = CK_INVALID_HANDLE;
-    session->verify_digest_descriptor = NULL;
-    hal_hash_cleanup(&session->verify_digest_state);
+    session->verify_digest_algorithm = hal_digest_algorithm_none;
+    digest_cleanup(&session->verify_digest_handle);
   }
 
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
@@ -4321,7 +3944,7 @@ CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession,
   if (RandomData == NULL)
     lose(CKR_ARGUMENTS_BAD);
 
-  if (!hal_check(hal_get_random(NULL, RandomData, ulRandomLen)))
+  if (!hal_check(hal_rpc_get_random(RandomData, ulRandomLen)))
     lose(CKR_FUNCTION_FAILED);
 
  fail:
@@ -4361,44 +3984,55 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
   if (slotID != P11_ONE_AND_ONLY_SLOT)
     return CKR_SLOT_ID_INVALID;
 
+#if 0
+  /*
+   * Perhaps revisit this after adding an RPC call to let us check
+   * which cores are available.  For now, given that we now have
+   * software core support for these hash algorithms, this test isn't
+   * particularly useful.
+   */
+
+  hal_digest_algorithm_t algorithm = hal_digest_algorithm_none;
+  CK_RV rv = CKR_OK;
+
   switch (type) {
 
   case CKM_SHA_1:
   case CKM_SHA1_RSA_PKCS:
   case CKM_SHA_1_HMAC:
   case CKM_ECDSA_SHA1:
-    if (hal_core_find(hal_hash_sha1->core_name, NULL) == NULL)
-      return CKR_MECHANISM_INVALID;
+    algorithm = hal_digest_algorithm_sha1;
     break;
 
   case CKM_SHA256:
   case CKM_SHA256_RSA_PKCS:
   case CKM_SHA256_HMAC:
   case CKM_ECDSA_SHA256:
-    if (hal_core_find(hal_hash_sha256->core_name, NULL) == NULL)
-      return CKR_MECHANISM_INVALID;
+    algorithm = hal_digest_algorithm_sha256;
     break;
 
   case CKM_SHA384:
   case CKM_SHA384_RSA_PKCS:
   case CKM_SHA384_HMAC:
   case CKM_ECDSA_SHA384:
-    if (hal_core_find(hal_hash_sha384->core_name, NULL) == NULL)
-      return CKR_MECHANISM_INVALID;
+    algorithm = hal_digest_algorithm_sha384;
     break;
 
   case CKM_SHA512:
   case CKM_SHA512_RSA_PKCS:
   case CKM_SHA512_HMAC:
   case CKM_ECDSA_SHA512:
-    if (hal_core_find(hal_hash_sha512->core_name, NULL) == NULL)
-      return CKR_MECHANISM_INVALID;
+    algorithm = hal_digest_algorithm_sha512;
     break;
 
   default:
     break;
   }
 
+  if (algorithm != hal_digest_algorithm_none && (rv = digest_available(algorithm)) != CKR_OK)
+    return rv;
+#endif
+
   switch (type) {
 
   case CKM_RSA_PKCS_KEY_PAIR_GEN:
diff --git a/schema.sql b/schema.sql
index ab09529..8a81505 100644
--- a/schema.sql
+++ b/schema.sql
@@ -1,7 +1,7 @@
 -- SQLite3 schema for Cryptech PKCS #11 implementation.
 --
 -- Author: Rob Austein
--- Copyright (c) 2015, NORDUnet A/S
+-- Copyright (c) 2015-2016, NORDUnet A/S
 -- All rights reserved.
 --
 -- Redistribution and use in source and binary forms, with or without
@@ -53,58 +53,6 @@
 
 PRAGMA foreign_keys = ON;
 
--- Values we have to store somewhere and for which we have no better
--- place.  This is a table with exactly one row (enforced by the CHECK
--- clause on the primary index).  All columns must either allow NULL
--- or provide default values.
-
-CREATE TABLE IF NOT EXISTS global (
-       global_id                INTEGER PRIMARY KEY NOT NULL DEFAULT 1 CHECK (global_id = 1),
-
-       -- Key-encryption-key (KEK)
-       --
-       -- The KEK **really** should be somewhere else, like in RAM
-       -- protected by tamper detection circuitry, but we don't have
-       -- that yet.  Not obvious that a separate file would be more
-       -- secure, so keep it here until we do have a better place.
-
-       kek                      BLOB CHECK (kek IS NULL OR (typeof(kek) = "blob" AND length(kek) IN (16, 32))),
-
-       -- PBKDF2-based PIN storage and check values.
-       --
-       -- "so_pin" and "user_pin" are PBKDF2 output, so only
-       -- moderately sensitive.
-       --
-       -- Not obvious that PKCS #11 ever really allows "so_pin" to be
-       -- unset, so it may want a NOT NULL constraint, but in that
-       -- case we'll need to provide a default value, which doesn't
-       -- seem like much of an improvement.  "so_pin" probably
-       -- requires out-of-band initialization.  "user-pin" is allowed
-       -- to be unset, there's an error code specifically for that
-       -- situation.
-       --
-       -- Numeric minima for PBKDF2 iterations, length of PIN, and
-       -- length of PBKDF2 salt are somewhat arbitrary, and will
-       -- probably change over time (which is why they are minima).
-       -- Initial testing was with 100000, which takes about 8 seconds
-       -- on a Novena with the current SHA256 and PBKDF2
-       -- implementation, which seems a bit slow, so backed that down
-       -- a bit.  Feel free to suggest better minima.
-
-       pbkdf2_iterations        INTEGER NOT NULL DEFAULT 20000,
-       so_pin                   BLOB,
-       user_pin                 BLOB,
-       so_pin_salt,             BLOB,
-       user_pin_salt            BLOB,
-       CHECK ((pbkdf2_iterations >= 10000)                                                                AND
-              (so_pin        IS NULL OR (typeof(so_pin)        = "blob" AND length(so_pin)        >= 32)) AND
-              (user_pin      IS NULL OR (typeof(user_pin)      = "blob" AND length(user_pin)      >= 32)) AND
-              (so_pin_salt   IS NULL OR (typeof(so_pin_salt)   = "blob" AND length(so_pin_salt)   >= 16)) AND
-              (user_pin_salt IS NULL OR (typeof(user_pin_salt) = "blob" AND length(user_pin_salt) >= 16)))
-);
-
-INSERT OR IGNORE INTO global DEFAULT VALUES;
-
 CREATE TEMPORARY TABLE IF NOT EXISTS session (
         session_id              INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
         session_handle          INTEGER NOT NULL UNIQUE
@@ -115,6 +63,7 @@ CREATE TEMPORARY TABLE IF NOT EXISTS object (
         object_id               INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
         object_handle           INTEGER NOT NULL UNIQUE
                                 CHECK (object_handle > 0 AND object_handle <= 0xFFFFFFFF),
+        hal_pkey_type           INTEGER,
         session_id              INTEGER REFERENCES session
                                 ON DELETE CASCADE ON UPDATE CASCADE
                                 DEFERRABLE INITIALLY DEFERRED,
@@ -129,7 +78,6 @@ CREATE TEMPORARY TABLE IF NOT EXISTS object (
 
 CREATE TEMPORARY TABLE IF NOT EXISTS session_object (
         session_object_id       INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
-        private_key             BLOB UNIQUE,
         object_id               INTEGER NOT NULL UNIQUE
                                 REFERENCES object
                                 ON DELETE CASCADE ON UPDATE CASCADE
@@ -145,8 +93,7 @@ CREATE TEMPORARY TABLE IF NOT EXISTS session_attribute (
 );
 
 CREATE TABLE IF NOT EXISTS token_object (
-        token_object_id         INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
-        private_key             BLOB UNIQUE
+        token_object_id         INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL
 );
 
 CREATE TABLE IF NOT EXISTS token_attribute (



More information about the Commits mailing list