[Cryptech-Commits] [sw/pkcs11] 02/05: Compiles without SQLite3. Does not run (yet).

git at cryptech.is git at cryptech.is
Tue Nov 22 05:27:37 UTC 2016


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

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

commit e4aab24cfe9cfa59e872f246b208fd7692e582b8
Author: Rob Austein <sra at hactrn.net>
AuthorDate: Sun Nov 20 23:30:39 2016 -0500

    Compiles without SQLite3.  Does not run (yet).
---
 pkcs11.c | 1316 +++++++++++++++++++++++++++++++-------------------------------
 1 file changed, 667 insertions(+), 649 deletions(-)

diff --git a/pkcs11.c b/pkcs11.c
index fd8d156..96afb4b 100644
--- a/pkcs11.c
+++ b/pkcs11.c
@@ -155,8 +155,11 @@ typedef struct p11_session {
   CK_STATE state;                       /* State (CKS_*) of this session */
   CK_NOTIFY notify;                     /* Notification callback */
   CK_VOID_PTR application;              /* Application data */
-  hal_rpc_pkey_attribute *find_query;   /* FindObject*() query state */
-  int find_query_done;                  /* find_query has terminated */
+  hal_rpc_pkey_attribute_t *find_query; /* FindObject*() query state */
+  unsigned find_query_token : 1;        /* Find query for token objects in progress */
+  unsigned find_query_session : 1;      /* Find query for session objects in progress */
+  unsigned find_query_n : 30;           /* Number of entries in find_query */
+  hal_uuid_t find_query_previous_uuid;  /* Previous UUID for find queries */
   hal_digest_algorithm_t
     digest_algorithm,                   /* Hash algorithm for C_Digest*() */
     sign_digest_algorithm,              /* Hash algorithm for C_Sign*() */
@@ -222,11 +225,11 @@ static enum {
  * PKCS #11 sessions and object handles for this application.
  */
 
-static p11_session_t p11_sessions[P11_MAX_SESSION_HANDLES];
-static p11_object_t  p11_objects [P11_MAX_OBJECT_HANDLES];
+static p11_session_t p11_sessions     [P11_MAX_SESSION_HANDLES];
+static p11_object_t  p11_objects      [P11_MAX_OBJECT_HANDLES];
+static unsigned      p11_object_uuids [P11_MAX_OBJECT_HANDLES];
 
-static unsigned p11_sessions_in_use, p11_session_next;
-static unsigned p11_objects_in_use,  p11_object_next;
+static unsigned p11_sessions_in_use, p11_objects_in_use;
 
 /*
  * Mutex callbacks.
@@ -660,7 +663,7 @@ static inline CK_ULONG handle_compose(const handle_flavor_t flavor,
 {
   return (mask_dpb(HANDLE_MASK_FLAVOR, flavor) |
           mask_dpb(HANDLE_MASK_NONCE,  nonce)  |
-          mask_dbp(HANDLE_MASK_INDEX,  index));
+          mask_dpb(HANDLE_MASK_INDEX,  index));
 }
 
 static inline handle_flavor_t handle_flavor(const CK_ULONG handle)
@@ -670,7 +673,7 @@ static inline handle_flavor_t handle_flavor(const CK_ULONG handle)
 
 static inline unsigned handle_index(const CK_ULONG handle)
 {
-  return mask_ldb(HANDLE_INDEX, handle);
+  return mask_ldb(HANDLE_MASK_INDEX, handle);
 }
 
 // Backwards compatability, probably phase this out
@@ -679,79 +682,64 @@ static inline unsigned handle_index(const CK_ULONG handle)
 

 
 /*
- * Attribute methods.
+ * Descriptor methods.  Descriptors are generated at compile time by
+ * an auxiliary Python script, see attributes.* for details.
  */
 
 /*
- * Set an attribute for a given object.
- *
- * It would be trivial to generalize this to take a CK_ATTRIBUTE_PTR
- * template instead of a single attribute, at the cost of losing the
- * const specifiers (CK_ATTRIBUTE_PTR has an internal non-const void*).
+ * Return the descriptor associated with a particular object class and
+ * key type.
  */
 
-static int p11_attribute_set(const hal_pkey_handle_t pkey,
-                             const CK_ATTRIBUTE_TYPE type,
-                             const void * const value,
-                             const CK_ULONG length)
+static const p11_descriptor_t *p11_descriptor_from_key_type(const CK_OBJECT_CLASS object_class,
+                                                            const CK_KEY_TYPE key_type)
 {
-  const hal_rpc_pkey_attribute_t attribute = {.type = type, .length = length, .value = value};
-  return hal_check(hal_rpc_pkey_set_attributes(pkey, &attribute, 1));
+  int i;
+
+  for (i = 0; i < sizeof(p11_descriptor_keyclass_map)/sizeof(*p11_descriptor_keyclass_map); i++) {
+    const p11_descriptor_keyclass_map_t * const m = &p11_descriptor_keyclass_map[i];
+    if (m->object_class == object_class && m->key_type == key_type)
+      return m->descriptor;
+  }
+
+  return NULL;
 }
 
 /*
- * Get a single attribute from a given object.
- *
- * This could easily be generalized to take a CK_ATTRIBUTE_PTR, at the
- * cost of more complicated error semantics.
+ * Find the entry for a particular attribute in a descriptor.
  */
 
-static int p11_attribute_get(const hal_pkey_handle_t pkey,
-                             const CK_ATTRIBUTE_TYPE type,
-                             void *value,
-                             CK_ULONG *length,
-                             const CK_ULONG maxlength)
+static const p11_attribute_descriptor_t *p11_find_attribute_in_descriptor(const p11_descriptor_t *descriptor,
+                                                                          const CK_ATTRIBUTE_TYPE type)
 {
-  hal_rpc_pkey_attribute_t attribute = {.type = type};
-
-  if (!hal_check(hal_rpc_pkey_get_attributes(pkey, &attribute, 1, value, maxlength)))
-    return 0;
+  int i;
 
-  if (length != NULL)
-    *length = attribute.length;
+  if (descriptor != NULL && descriptor->attributes != NULL)
+    for (i = 0; i < descriptor->n_attributes; i++)
+      if (descriptor->attributes[i].type == type)
+        return &descriptor->attributes[i];
 
-  return 1;
+  return NULL;
 }
 
 /*
- * Wrappers to set and get CK_BBOOL and CK_ULONG values.
+ * Check whether an attribute is marked as sensitive.  If we don't
+ * recognize the attribute, report it as sensitive (safer than the
+ * alternative).
  */
 
-static int p11_attribute_set_bbool(const hal_pkey_handle_t pkey, const CK_ATTRIBUTE_TYPE type, const CK_BBOOL value)
-{
-  return p11_attribute_set(pkey, type, &value, sizeof(value));
-}
-
-#if 0
-
-static int p11_attribute_set_ulong(const hal_pkey_handle_t pkey, const CK_ATTRIBUTE_TYPE type, const CK_ULONG value)
+static int p11_attribute_is_sensitive(const p11_descriptor_t *descriptor,
+                                      const CK_ATTRIBUTE_TYPE type)
 {
-  return p11_attribute_set(pkey, type, &value, sizeof(value));
+  const p11_attribute_descriptor_t *a = p11_find_attribute_in_descriptor(descriptor, type);
+  return a == NULL || (a->flags & P11_DESCRIPTOR_SENSITIVE) != 0;
 }
 
-#endif
-
-static int p11_attribute_get_bbool(const hal_pkey_handle_t pkey, const CK_ATTRIBUTE_TYPE type, CK_BBOOL *value)
-{
-  CK_ULONG length;
-  return p11_attribute_get(pkey, type, value, &length, sizeof(*value)) && length == sizeof(*value);
-}
+

 
-static int p11_attribute_get_ulong(const hal_pkey_handle_t pkey, const CK_ATTRIBUTE_TYPE type, CK_ULONG *value)
-{
-  CK_ULONG length;
-  return p11_attribute_get(pkey, type, value, &length, sizeof(*value)) && length == sizeof(*value);
-}
+/*
+ * Attribute methods.
+ */
 
 /*
  * Find an attribute in a CK_ATTRIBUTE_PTR template.  Returns index
@@ -784,6 +772,104 @@ static void *p11_attribute_find_value_in_template(const CK_ATTRIBUTE_TYPE type,
 }
 
 /*
+ * Set attributes for a newly-created or newly-uploaded HSM key.
+ */
+
+static int p11_attributes_set(const hal_pkey_handle_t pkey,
+                              const CK_ATTRIBUTE_PTR template,
+                              const CK_ULONG template_length,
+                              const p11_descriptor_t * const descriptor,
+                              const hal_rpc_pkey_attribute_t *extra,
+                              const unsigned extra_length)
+{
+  assert(template != NULL && descriptor != NULL && (extra_length == 0 || extra != NULL));
+
+  /*
+   * Populate attributes, starting with the application's template,
+   * which we assume has already been blessed by the API function that
+   * called this method.
+   *
+   * If the attribute is flagged as sensitive in the descriptor, we
+   * don't store it as an attribute.  Generally, this only arises for
+   * private key components of objects created with C_CreateObject(),
+   * but in theory there are some corner cases in which a user could
+   * choose to mark a private key as extractable and not sensitive, so
+   * we might have to back-fill missing values in those cases if
+   * anyone ever thinks up a sane reason for supporting them.  For
+   * now, assume that private keys are bloody well supposed to be
+   * private.
+   */
+
+  hal_rpc_pkey_attribute_t attributes[template_length + descriptor->n_attributes + extra_length];
+  unsigned n = 0;
+
+  for (int i = 0; i < template_length; i++) {
+    const CK_ATTRIBUTE_TYPE type = template[i].type;
+    const void *             val = template[i].pValue;
+    const int                len = template[i].ulValueLen;
+
+    if (p11_attribute_is_sensitive(descriptor, type))
+      continue;
+
+    if (n >= sizeof(attributes) / sizeof(*attributes))
+      return 0;
+
+    attributes[n].type   = type;
+    attributes[n].value  = val;
+    attributes[n].length = len;
+    n++;
+  }
+
+  /*
+   * Next, add defaults from the descriptor.
+   */
+
+  for (int i = 0; i < descriptor->n_attributes; i++) {
+    const CK_ATTRIBUTE_TYPE type = descriptor->attributes[i].type;
+    const void *             val = descriptor->attributes[i].value;
+    const int                len = descriptor->attributes[i].length;
+    const unsigned         flags = descriptor->attributes[i].flags;
+
+    if (val == NULL && (flags & P11_DESCRIPTOR_DEFAULT_VALUE) != 0)
+      val = "";
+
+    if (val == NULL || p11_attribute_find_in_template(type, template, template_length) >= 0)
+      continue;
+
+    if (n >= sizeof(attributes) / sizeof(*attributes))
+      return 0;
+
+    attributes[n].type   = type;
+    attributes[n].value  = val;
+    attributes[n].length = len;
+    n++;
+  }
+
+  /*
+   * Finally, add any attributes provided by the calling function itself.
+   */
+
+  for (int i = 0; i < extra_length; i++) {
+    if (n >= sizeof(attributes) / sizeof(*attributes))
+      return 0;
+
+    attributes[n].type   = extra[i].type;
+    attributes[n].value  = extra[i].value;
+    attributes[n].length = extra[i].length;
+    n++;
+  }
+
+  /*
+   * Set all those attributes.
+   */
+
+  if (!hal_check(hal_rpc_pkey_set_attributes(pkey, attributes, n)))
+    return 0;
+
+  return 1;
+}
+
+/*
  * Map a keyusage-related attribute to a keyusage bit flag.
  *
  * Assumes that calling code has already checked whether this
@@ -832,65 +918,42 @@ static void p11_attribute_apply_keyusage(hal_key_flags_t *keyusage, const CK_ATT
 

 
 /*
- * Descriptor methods.  Descriptors are generated at compile time by
- * an auxiliary Python script, see attributes.* for details.
- */
-
-/*
- * Return the descriptor associated with a particular object class and
- * key type.
+ * Object methods.
  */
 
-static const p11_descriptor_t *p11_descriptor_from_key_type(const CK_OBJECT_CLASS object_class,
-                                                            const CK_KEY_TYPE key_type)
-{
-  int i;
-
-  for (i = 0; i < sizeof(p11_descriptor_keyclass_map)/sizeof(*p11_descriptor_keyclass_map); i++) {
-    const p11_descriptor_keyclass_map_t * const m = &p11_descriptor_keyclass_map[i];
-    if (m->object_class == object_class && m->key_type == key_type)
-      return m->descriptor;
-  }
-
-  return NULL;
-}
-
 /*
- * Find the entry for a particular attribute in a descriptor.
+ * Look up an object's UUID in the object index table, return
+ * indication of whether it's present or not and the position it
+ * should occupy within the index table in either case.
+ *
+ * NB: *where is a position in p11_object_uuids[], not p11_objects[].
  */
 
-static const p11_attribute_descriptor_t *p11_find_attribute_in_descriptor(const p11_descriptor_t *descriptor,
-                                                                          const CK_ATTRIBUTE_TYPE type)
+static int p11_object_uuid_bsearch(const hal_uuid_t * const uuid, int *where)
 {
-  int i;
+  assert(uuid != NULL && where != NULL);
 
-  if (descriptor != NULL && descriptor->attributes != NULL)
-    for (i = 0; i < descriptor->n_attributes; i++)
-      if (descriptor->attributes[i].type == type)
-        return &descriptor->attributes[i];
-
-  return NULL;
-}
+  int lo = -1;
+  int hi = p11_objects_in_use;
 
-/*
- * Check whether an attribute is marked as sensitive.  If we don't
- * recognize the attribute, report it as sensitive (safer than the
- * alternative).
- */
-
-static int p11_attribute_is_sensitive(const p11_descriptor_t *descriptor,
-                                      const CK_ATTRIBUTE_TYPE type)
-{
-  const p11_attribute_descriptor_t *a = p11_find_attribute_in_descriptor(descriptor, type);
-  return a == NULL || (a->flags & P11_DESCRIPTOR_SENSITIVE) != 0;
+  for (;;) {
+    int m = (lo + hi) / 2;
+    if (hi == 0 || m == lo) {
+      *where = hi;
+      return 0;
+    }
+    const int cmp = hal_uuid_cmp(uuid, &p11_objects[p11_object_uuids[m]].uuid);
+    if (cmp < 0)
+      hi = m;
+    else if (cmp > 0)
+      lo = m;
+    else {
+      *where = m;
+      return 1;
+    }
+  }
 }
 
-

-
-/*
- * Object methods.
- */
-
 /*
  * Allocate a new object.
  */
@@ -905,6 +968,17 @@ static CK_OBJECT_HANDLE p11_object_allocate(const handle_flavor_t flavor,
   if (flavor != handle_flavor_token_object && flavor != handle_flavor_session_object)
     return CK_INVALID_HANDLE;
 
+  int where;
+
+  if (p11_object_uuid_bsearch(uuid, &where)) {
+    assert(where >= 0 && where < p11_objects_in_use);
+    const CK_OBJECT_HANDLE handle = p11_objects[p11_object_uuids[where]].handle;
+    return handle_flavor(handle) == flavor ? handle : CK_INVALID_HANDLE;
+  }
+
+  if (p11_objects_in_use >= sizeof(p11_objects) / sizeof(*p11_objects))
+    return CK_INVALID_HANDLE;
+
   static unsigned next_index, nonce;
   const unsigned  last_index = next_index;
   p11_object_t *object = NULL;
@@ -919,13 +993,22 @@ static CK_OBJECT_HANDLE p11_object_allocate(const handle_flavor_t flavor,
     if (next_index == 0)
       ++nonce;
 
-    object = p11_objects[next_index];
+    object = &p11_objects[next_index];
 
-  } while (object.handle == CK_INVALID_HANDLE);
+  } while (object->handle != CK_INVALID_HANDLE);
 
-  object->handle = handle_compose(flavor, nonce, next_handle);
+  object->handle = handle_compose(flavor, nonce, next_index);
   object->uuid = *uuid;
   object->session = flavor == handle_flavor_session_object ? session->handle : CK_INVALID_HANDLE;
+
+  if (where < p11_objects_in_use)
+    memmove(&p11_object_uuids[where + 1], &p11_object_uuids[where],
+            (p11_objects_in_use - where) * sizeof(*p11_object_uuids));
+
+  p11_object_uuids[where] = next_index;
+
+  p11_objects_in_use++;
+
   return object->handle;
 }
 
@@ -938,16 +1021,44 @@ static void p11_object_free(p11_object_t *object)
   if (object == NULL)
     return;
 
-#warning Should we delete session objects here?
+  int where;
+
+  if (p11_objects_in_use > 0 &&
+      p11_object_uuid_bsearch(&object->uuid, &where) &&
+      --p11_objects_in_use > where)
+    memmove(&p11_object_uuids[where], &p11_object_uuids[where + 1],
+            (p11_objects_in_use - where) * sizeof(*p11_object_uuids));
 
   memset(object, 0, sizeof(*object));
 }
 
 /*
- * Find an object.
+ * Find an object given its UUID.
+ */
+
+static p11_object_t *p11_object_by_uuid(const hal_uuid_t * const uuid)
+{
+  int where;
+
+  if (uuid == NULL || !p11_object_uuid_bsearch(uuid, &where))
+    return NULL;
+
+  assert(where >= 0 && where < p11_objects_in_use);
+
+  p11_object_t *object = &p11_objects[p11_object_uuids[where]];
+
+  if (handle_flavor(object->handle) != handle_flavor_session_object &&
+      handle_flavor(object->handle) != handle_flavor_token_object)
+    return NULL;
+
+  return object;
+}
+
+/*
+ * Find an object given its handle.
  */
 
-static p11_object_t *p11_object_find(const CK_OBJECT_HANDLE object_handle)
+static p11_object_t *p11_object_by_handle(const CK_OBJECT_HANDLE object_handle)
 {
   if (handle_flavor(object_handle) != handle_flavor_session_object &&
       handle_flavor(object_handle) != handle_flavor_token_object)
@@ -966,25 +1077,27 @@ static p11_object_t *p11_object_find(const CK_OBJECT_HANDLE object_handle)
   return object;
 }
 
+#if 0
+
 /*
  * Iterate over object handles.  Start with CK_INVALID_HANDLE,
  * returns CK_INVALID_HANDLE when done.
  */
 
-static CK_BJECT_HANDLE p11_object_handle_iterate(const CK_OBJECT_HANDLE object_handle)
+static CK_OBJECT_HANDLE p11_object_handle_iterate(const CK_OBJECT_HANDLE object_handle)
 {
   if (handle_flavor(object_handle) != handle_flavor_session_object &&
       handle_flavor(object_handle) != handle_flavor_token_object)
-    return CK_HANDLE_INVALID;
+    return CK_INVALID_HANDLE;
 
-  for (unsigned index = session_handle == CK_INVALID_HANDLE ? 0 : handle_index(session_handle) + 1;
+  for (unsigned index = object_handle == CK_INVALID_HANDLE ? 0 : handle_index(object_handle) + 1;
        index < sizeof(p11_sessions) / sizeof(*p11_sessions);
        index++)
     if (handle_flavor(p11_sessions[index].handle) == handle_flavor_session_object ||
         handle_flavor(p11_sessions[index].handle) == handle_flavor_token_object)
       return p11_sessions[index].handle;
 
-  return CK_HANDLE_INVALID;
+  return CK_INVALID_HANDLE;
 }
 
 /*
@@ -996,9 +1109,11 @@ static p11_object_t *p11_object_iterate(p11_object_t *object)
   if (object == NULL)
     return NULL;
 
-  return p11_object_find(p11_object_handle_iterate(object->handle));
+  return p11_object_by_handle(p11_object_handle_iterate(object->handle));
 }
 
+#endif
+
 /*
  * Translate CKA_TOKEN value to handle flavor.
  */
@@ -1008,6 +1123,12 @@ static inline handle_flavor_t p11_object_flavor_from_cka_token(const CK_BBOOL *b
   return (bbool != NULL && *bbool) ? handle_flavor_token_object : handle_flavor_session_object;
 }
 
+static inline hal_key_flags_t p11_object_hal_flags(const CK_OBJECT_HANDLE handle)
+{
+  return handle_flavor(handle) == handle_flavor_token_object ? HAL_KEY_FLAG_TOKEN : 0;
+}
+
+
 /*
  * Open the HSM pkey object (if any) corresponding to the PKCS #11 handle.
  */
@@ -1016,12 +1137,13 @@ static int p11_object_pkey_open(const p11_session_t *session,
                                 const CK_OBJECT_HANDLE object_handle,
                                 hal_pkey_handle_t *pkey)
 {
-  return (session != NULL && pkey != NULL &&
+  const p11_object_t *object = p11_object_by_handle(object_handle);
+
+  return (session != NULL && pkey != NULL && object != NULL &&
           hal_check(hal_rpc_pkey_open(p11_session_hal_client(session),
                                       p11_session_hal_session(session),
-                                      pkey,
-                                      p11_object_get_uuid(object_handle),
-                                      p11_object_get_hal_flags(object_handle))));
+                                      pkey, &object->uuid,
+                                      p11_object_hal_flags(object_handle))));
 }
 
 /*
@@ -1032,178 +1154,56 @@ typedef enum { p11_object_access_read, p11_object_access_write } p11_object_acce
 
 static CK_RV p11_object_check_rights(const p11_session_t *session,
                                      const CK_OBJECT_HANDLE object_handle,
-                                     const p11_object_access_t rights)
+                                     const p11_object_access_t rights,
+                                     const CK_BBOOL cka_private,
+                                     const CK_BBOOL cka_token)
 {
-  hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
-  CK_BBOOL cka_private;
-  CK_BBOOL cka_token;
   CK_RV rv;
 
   if (session == NULL)
     lose(CKR_SESSION_HANDLE_INVALID);
 
-  if (!p11_object_pkey_open(session, object_handle, &pkey))
-    lose(CKR_OBJECT_HANDLE_INVALID);
-
-  if (!p11_attribute_get_bbool(pkey, CKA_PRIVATE, &cka_private))
-    cka_private = CK_TRUE;
-
-  if (!p11_attribute_get_bbool(pkey, CKA_TOKEN, &cka_token))
-    cka_token = CK_FALSE;
-
   /*
    * Read-only sessions are, um, read-only.  Well, except, in PKCS #11,
-   * read-only only sort of means what you might expect.
-   */
-
-  if (rights == p11_object_access_write) {
-    switch (session->state) {
-    case CKS_RO_PUBLIC_SESSION:
-      if (cka_private)
-        lose(CKR_SESSION_READ_ONLY);
-      /* Fall through */
-    case CKS_RO_USER_FUNCTIONS:
-      if (cka_token)
-        lose(CKR_SESSION_READ_ONLY);
-      /* Fall through */
-    }
-  }
-
-  /*
-   * Private objects don't exist for sessions in the wrong state.
-   */
-
-  switch (session->state) {
-  case CKS_RO_PUBLIC_SESSION:
-  case CKS_RW_PUBLIC_SESSION:
-  case CKS_RW_SO_FUNCTIONS:
-    if (cka_private)
-      lose(CKR_OBJECT_HANDLE_INVALID);
-  }
-
-#warning Want session-object visibility sanity check here?
-  /*
-   * At this point the old code checked for objects which are not
-   * supposed to be visible to this session.  In theory, the keystore
-   * now handles that, but we might want a sanity check here too.
-   */
-
-  rv = CKR_OK;
-
- fail:
-  (void) hal_check(hal_rpc_pkey_close(pkey));
-  return rv;
-}
-
-/*
- * Given a pkey handle and UUID for a newly created HSM key, attach
- * attributes and create an object handle.
- */
-
-static CK_OBJECT_HANDLE p11_object_create(const p11_session_t *session,
-                                          const hal_pkey_handle_t pkey,
-                                          const hal_uuid_t *uuid,
-                                          const handle_flavor_t flavor,
-                                          const CK_ATTRIBUTE_PTR template,
-                                          const CK_ULONG template_length,
-                                          const p11_descriptor_t * const descriptor,
-                                          const hal_rpc_pkey_attribute_t *extra,
-                                          const unsigned extra_length)
-{
-  assert(session != NULL && template != NULL && descriptor != NULL && uuid != NULL &&
-         (extra_length == 0 || extra != NULL) &&
-         (flavor == handle_flavor_token_object || flavor == handle_flavor_session_object));
-
-  /*
-   * Populate attributes, starting with the application's template,
-   * which we assume has already been blessed by the API function that
-   * called this method.
-   *
-   * If the attribute is flagged as sensitive in the descriptor, we
-   * don't store it as an attribute.  Generally, this only arises for
-   * private key components of objects created with C_CreateObject(),
-   * but in theory there are some corner cases in which a user could
-   * choose to mark a private key as extractable and not sensitive, so
-   * we might have to back-fill missing values in those cases if
-   * anyone ever thinks up a sane reason for supporting them.  For
-   * now, assume that private keys are bloody well supposed to be
-   * private.
-   */
-
-  hal_rpc_pkey_attribute_t attributes[template_length + descriptor->n_attributes + extra_length];
-  unsigned n = 0;
-
-  for (int i = 0; i < template_length; i++) {
-    const CK_ATTRIBUTE_TYPE type = template[i].type;
-    const void *             val = template[i].pValue;
-    const int                len = template[i].ulValueLen;
-
-    if (p11_attribute_is_sensitive(descriptor, type))
-      continue;
-
-    if (n >= sizeof(attributes) / sizeof(*attributes))
-      lose(CKR_FUNCTION_FAILED);
-
-    attributes[n].type   = type;
-    attributes[n].value  = val;
-    attributes[n].length = len;
-    n++;
-  }
-
-  /*
-   * Next, add defaults from the descriptor.
-   */
-
-  for (int i = 0; i < descriptor->n_attributes; i++) {
-    const CK_ATTRIBUTE_TYPE type = descriptor->attributes[i].type;
-    const void *             val = descriptor->attributes[i].value;
-    const int                len = descriptor->attributes[i].length;
-    const unsigned         flags = descriptor->attributes[i].flags;
-
-    if (val == NULL && (flags & P11_DESCRIPTOR_DEFAULT_VALUE) != 0)
-      val = "";
-
-    if (val == NULL || p11_attribute_find_in_template(type, template, template_length) >= 0)
-      continue;
-
-    if (n >= sizeof(attributes) / sizeof(*attributes))
-      lose(CKR_FUNCTION_FAILED);
-
-    attributes[n].type   = type;
-    attributes[n].value  = val;
-    attributes[n].length = len;
-    n++;
-  }
-
-  /*
-   * Finally, add any attributes provided by the calling function itself.
+   * read-only only sort of means what you might expect.
    */
 
-  for (int i = 0; i < extra_length; i++) {
-    if (n >= sizeof(attributes) / sizeof(*attributes))
-      lose(CKR_FUNCTION_FAILED);
-
-    attributes[n].type   = extra[i].type;
-    attributes[n].value  = extra[i].value;
-    attributes[n].length = extra[i].length;
-    n++;
+  if (rights == p11_object_access_write) {
+    switch (session->state) {
+    case CKS_RO_PUBLIC_SESSION:
+      if (cka_private)
+        lose(CKR_SESSION_READ_ONLY);
+      /* Fall through */
+    case CKS_RO_USER_FUNCTIONS:
+      if (cka_token)
+        lose(CKR_SESSION_READ_ONLY);
+      /* Fall through */
+    }
   }
 
   /*
-   * Set all those attributes.
+   * Private objects don't exist for sessions in the wrong state.
    */
 
-  if (!hal_check(hal_rpc_pkey_set_attributes(pkey, attributes, n)))
-    lose(CKR_FUNCTION_FAILED);
+  switch (session->state) {
+  case CKS_RO_PUBLIC_SESSION:
+  case CKS_RW_PUBLIC_SESSION:
+  case CKS_RW_SO_FUNCTIONS:
+    if (cka_private)
+      lose(CKR_OBJECT_HANDLE_INVALID);
+  }
 
+#warning Want session-object visibility sanity check here?
   /*
-   * Create the object handle, then we're done.
+   * At this point the old code checked for objects which are not
+   * supposed to be visible to this session.  In theory, the keystore
+   * now handles that, but we might want a sanity check here too.
    */
 
-  return p11_object_allocate(flavor, uuid, session);
+  rv = CKR_OK;
 
  fail:
-  return CK_INVALID_HANDLE;
+  return rv;
 }
 
 /*
@@ -1218,13 +1218,14 @@ static int p11_object_create_rsa_public_key(const p11_session_t * const session,
                                             CK_OBJECT_HANDLE_PTR phObject,
                                             const hal_key_flags_t flags)
 {
-  const hal_rpc_pkey_attributes extra[] = {
-    {.type = CKA_LOCAL, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)}
+  const hal_rpc_pkey_attribute_t extra[] = {
+    {.type = CKA_LOCAL, .value = &const_CK_FALSE, .length = sizeof(const_CK_FALSE)}
   };
 
   hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
   uint8_t keybuf[hal_rsa_key_t_size];
   hal_rsa_key_t *key = NULL;
+  hal_uuid_t uuid;
 
   const uint8_t *cka_modulus = NULL;
   size_t cka_modulus_len = 0;
@@ -1246,7 +1247,6 @@ static int p11_object_create_rsa_public_key(const p11_session_t * const session,
 
   if (ok) {
     uint8_t der[hal_rsa_public_key_to_der_len(key)];
-    hal_uuid_t uuid;
     ok = (hal_check(hal_rsa_public_key_to_der(key, der, NULL, sizeof(der))) &&
           hal_check(hal_rpc_pkey_load(p11_session_hal_client(session),
                                       p11_session_hal_session(session),
@@ -1254,9 +1254,12 @@ static int p11_object_create_rsa_public_key(const p11_session_t * const session,
                                       &uuid, der, sizeof(der), flags)));
   }
 
+  if (ok)
+    ok = p11_attributes_set(pkey, template, template_len, descriptor,
+                            extra, sizeof(extra)/sizeof(*extra));
+
   if (ok) {
-    *phObject = p11_object_create(session, pkey, &uuid, flavor, template, template_len,
-                                  descriptor, extra, sizeof(extra)/sizeof(*extra));
+    *phObject = p11_object_allocate(flavor, &uuid, session);
     ok = *phObject != CK_INVALID_HANDLE;
   }
 
@@ -1276,14 +1279,15 @@ static int p11_object_create_ec_public_key(const p11_session_t * const session,
                                            CK_OBJECT_HANDLE_PTR phObject,
                                            const hal_key_flags_t flags)
 {
-  const hal_rpc_pkey_attributes extra[] = {
-    {.type = CKA_LOCAL, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)}
+  const hal_rpc_pkey_attribute_t extra[] = {
+    {.type = CKA_LOCAL, .value = &const_CK_FALSE, .length = sizeof(const_CK_FALSE)}
   };
 
   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;
+  hal_uuid_t uuid;
 
   const uint8_t *cka_ec_point  = NULL;  size_t cka_ec_point_len  = 0;
   const uint8_t *cka_ec_params = NULL;  size_t cka_ec_params_len = 0;
@@ -1305,7 +1309,6 @@ static int p11_object_create_ec_public_key(const p11_session_t * const session,
 
   if (ok) {
     uint8_t der[hal_ecdsa_public_key_to_der_len(key)];
-    hal_uuid_t uuid;
     ok = (hal_check(hal_ecdsa_public_key_to_der(key, der, NULL, sizeof(der))) &&
           hal_check(hal_rpc_pkey_load(p11_session_hal_client(session),
                                       p11_session_hal_session(session),
@@ -1313,9 +1316,12 @@ static int p11_object_create_ec_public_key(const p11_session_t * const session,
                                       &uuid, der, sizeof(der), flags)));
   }
 
+  if (ok)
+    ok = p11_attributes_set(pkey, template, template_len, descriptor,
+                            extra, sizeof(extra)/sizeof(*extra));
+
   if (ok) {
-    *phObject = p11_object_create(session, pkey, &uuid, flavor, template, template_len,
-                                  descriptor, extra, sizeof(extra)/sizeof(*extra));
+    *phObject = p11_object_allocate(flavor, &uuid, session);
     ok = *phObject != CK_INVALID_HANDLE;
   }
 
@@ -1335,10 +1341,10 @@ static int p11_object_create_rsa_private_key(const p11_session_t * const session
                                              CK_OBJECT_HANDLE_PTR phObject,
                                              const hal_key_flags_t flags)
 {
-  const hal_rpc_pkey_attributes extra[] = {
-    {.type = CKA_LOCAL,             .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)},
-    {.type = CKA_ALWAYS_SENSITIVE,  .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)},
-    {.type = CKA_NEVER_EXTRACTABLE, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)}
+  const hal_rpc_pkey_attribute_t extra[] = {
+    {.type = CKA_LOCAL,             .value = &const_CK_FALSE, .length = sizeof(const_CK_FALSE)},
+    {.type = CKA_ALWAYS_SENSITIVE,  .value = &const_CK_FALSE, .length = sizeof(const_CK_FALSE)},
+    {.type = CKA_NEVER_EXTRACTABLE, .value = &const_CK_FALSE, .length = sizeof(const_CK_FALSE)}
   };
 
   hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
@@ -1394,9 +1400,12 @@ static int p11_object_create_rsa_private_key(const p11_session_t * const session
 
   memset(keybuf, 0, sizeof(keybuf));
 
+  if (ok)
+    ok = p11_attributes_set(pkey, template, template_len, descriptor,
+                            extra, sizeof(extra)/sizeof(*extra));
+
   if (ok) {
-    *phObject = p11_object_create(session, pkey, &uuid, flavor, template, template_len,
-                                  descriptor, extra, sizeof(extra)/sizeof(*extra));
+    *phObject = p11_object_allocate(flavor, &uuid, session);
     ok = *phObject != CK_INVALID_HANDLE;
   }
 
@@ -1416,16 +1425,17 @@ static int p11_object_create_ec_private_key(const p11_session_t * const session,
                                             CK_OBJECT_HANDLE_PTR phObject,
                                             const hal_key_flags_t flags)
 {
-  const hal_rpc_pkey_attributes extra[] = {
-    {.type = CKA_LOCAL,             .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)},
-    {.type = CKA_ALWAYS_SENSITIVE,  .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)},
-    {.type = CKA_NEVER_EXTRACTABLE, .value = &const_CKA_FALSE, .length = sizeof(const_CKA_FALSE)}
+  const hal_rpc_pkey_attribute_t extra[] = {
+    {.type = CKA_LOCAL,             .value = &const_CK_FALSE, .length = sizeof(const_CK_FALSE)},
+    {.type = CKA_ALWAYS_SENSITIVE,  .value = &const_CK_FALSE, .length = sizeof(const_CK_FALSE)},
+    {.type = CKA_NEVER_EXTRACTABLE, .value = &const_CK_FALSE, .length = sizeof(const_CK_FALSE)}
   };
 
   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;
+  hal_uuid_t uuid;
 
   const uint8_t *cka_value     = NULL;  size_t cka_value_len     = 0;
   const uint8_t *cka_ec_point  = NULL;  size_t cka_ec_point_len  = 0;
@@ -1453,7 +1463,6 @@ static int p11_object_create_ec_private_key(const p11_session_t * const session,
 
   if (ok) {
     uint8_t der[hal_ecdsa_private_key_to_der_len(key)];
-    hal_uuid_t uuid;
     ok = (hal_check(hal_ecdsa_private_key_to_der(key, der, NULL, sizeof(der))) &&
           hal_check(hal_rpc_pkey_load(p11_session_hal_client(session),
                                       p11_session_hal_session(session),
@@ -1464,9 +1473,12 @@ static int p11_object_create_ec_private_key(const p11_session_t * const session,
 
   memset(keybuf, 0, sizeof(keybuf));
 
+  if (ok)
+    ok = p11_attributes_set(pkey, template, template_len, descriptor,
+                            extra, sizeof(extra)/sizeof(*extra));
+
   if (ok) {
-    *phObject = p11_object_create(session, pkey, &uuid, flavor, template, template_len,
-                                  descriptor, extra, sizeof(extra)/sizeof(*extra));
+    *phObject = p11_object_allocate(flavor, &uuid, session);
     ok = *phObject != CK_INVALID_HANDLE;
   }
 
@@ -1507,12 +1519,12 @@ static p11_session_t *p11_session_allocate(void)
     if (next_index == 0)
       ++nonce;
 
-    session = p11_sessions[next_index];
+    session = &p11_sessions[next_index];
 
-  } while (session.handle == CK_INVALID_HANDLE);
+  } while (session->handle != CK_INVALID_HANDLE);
 
   memset(session, 0, sizeof(*session));
-  session.handle = handle_compose(handle_flavor_session, nonce, next_handle);
+  session->handle = handle_compose(handle_flavor_session, nonce, next_index);
   p11_sessions_in_use++;
   return session;
 }
@@ -1576,7 +1588,7 @@ static p11_session_t *p11_session_find(const CK_SESSION_HANDLE session_handle)
 static CK_SESSION_HANDLE p11_session_handle_iterate(const CK_SESSION_HANDLE session_handle)
 {
   if (handle_flavor(session_handle) != handle_flavor_session)
-    return CK_HANDLE_INVALID;
+    return CK_INVALID_HANDLE;
 
   for (unsigned index = session_handle == CK_INVALID_HANDLE ? 0 : handle_index(session_handle) + 1;
        index < sizeof(p11_sessions) / sizeof(*p11_sessions);
@@ -1584,7 +1596,7 @@ static CK_SESSION_HANDLE p11_session_handle_iterate(const CK_SESSION_HANDLE sess
     if (handle_flavor(p11_sessions[index].handle) == handle_flavor_session)
       return p11_sessions[index].handle;
 
-  return CK_HANDLE_INVALID;
+  return CK_INVALID_HANDLE;
 }
 
 /*
@@ -1995,21 +2007,22 @@ static CK_RV generate_keypair_rsa_pkcs(p11_session_t *session,
       lose(CKR_FUNCTION_FAILED);
 
     const hal_rpc_pkey_attribute_t extra[] = {
-      {.type   = CKA_LOCAL,
-       .value  = &const_CK_TRUE,        .length = sizeof(const_CK_TRUE)},
-      {.type   = CKA_KEY_GEN_MECHANISM,
-       .value  = &mechanism->mechanism, .length = sizeof(mechanism->mechanism)},
-      {.type   = CKA_MODULUS,
-       value   = modulus,               .length = modulus_len}
+      {.type  = CKA_LOCAL,
+       .value = &const_CK_TRUE,         .length = sizeof(const_CK_TRUE)},
+      {.type  = CKA_KEY_GEN_MECHANISM,
+       .value = &pMechanism->mechanism, .length = sizeof(pMechanism->mechanism)},
+      {.type  = CKA_MODULUS,
+       .value  = modulus,               .length = modulus_len}
     };
 
-    *phPrivateKey = p11_object_create(session, private_pkey, &private_uuid, private_handle_flavor,
-                                      pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
-                                      private_descriptor, extra, sizeof(extra)/sizeof(*extra));
+    if (!p11_attributes_set(private_pkey, pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+                            private_descriptor, extra, sizeof(extra)/sizeof(*extra))            ||
+        !p11_attributes_set(public_pkey, pPublicKeyTemplate, ulPublicKeyAttributeCount,
+                            public_descriptor, extra, sizeof(extra)/sizeof(*extra)))
+      lose(CKR_FUNCTION_FAILED);
 
-    *phPublicKey = p11_object_create(session, public_handle_flavor,
-                                     pPublicKeyTemplate, ulPublicKeyAttributeCount,
-                                     public_descriptor, extra, sizeof(extra)/sizeof(*extra));
+    *phPrivateKey = p11_object_allocate(private_handle_flavor, &private_uuid, session);
+    *phPublicKey  = p11_object_allocate(public_handle_flavor,  &public_uuid,  session);
 
     if (*phPrivateKey == CK_INVALID_HANDLE || *phPublicKey == CK_INVALID_HANDLE)
       lose(CKR_FUNCTION_FAILED);
@@ -2094,23 +2107,24 @@ static CK_RV generate_keypair_ec(p11_session_t *session,
       lose(CKR_FUNCTION_FAILED);
 
     const hal_rpc_pkey_attribute_t extra[] = {
-      {.type   = CKA_LOCAL,
-       .value  = &const_CK_TRUE,        .length = sizeof(const_CK_TRUE)},
-      {.type   = CKA_KEY_GEN_MECHANISM,
-       .value  = &mechanism->mechanism, .length = sizeof(mechanism->mechanism)},
-      {.type   = CKA_EC_PARAMS,
-       value   = params,                .length = params_len},
-      {.type   = CKA_EC_POINT,
-       value   = point,                 .length = sizeof(point)}
+      {.type  = CKA_LOCAL,
+       .value = &const_CK_TRUE,         .length = sizeof(const_CK_TRUE)},
+      {.type  = CKA_KEY_GEN_MECHANISM,
+       .value = &pMechanism->mechanism, .length = sizeof(pMechanism->mechanism)},
+      {.type  = CKA_EC_PARAMS,
+       .value  = params,                .length = params_len},
+      {.type  = CKA_EC_POINT,
+       .value = point,                  .length = sizeof(point)}
     };
 
-    *phPrivateKey = p11_object_create(session, private_pkey, &private_uuid, private_handle_flavor,
-                                      pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
-                                      private_descriptor, extra, sizeof(extra)/sizeof(*extra) - 1);
+    if (!p11_attributes_set(private_pkey, pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
+                            private_descriptor, extra, sizeof(extra)/sizeof(*extra) - 1)         ||
+        !p11_attributes_set(public_pkey, pPublicKeyTemplate, ulPublicKeyAttributeCount,
+                            public_descriptor, extra, sizeof(extra)/sizeof(*extra)))
+      lose(CKR_FUNCTION_FAILED);
 
-    *phPublicKey = p11_object_create(session, public_handle_flavor,
-                                     pPublicKeyTemplate, ulPublicKeyAttributeCount,
-                                     public_descriptor, extra, sizeof(extra)/sizeof(*extra));
+    *phPrivateKey = p11_object_allocate(private_handle_flavor, &private_uuid, session);
+    *phPublicKey  = p11_object_allocate(public_handle_flavor,  &public_uuid,  session);
 
     if (*phPrivateKey == CK_INVALID_HANDLE || *phPublicKey == CK_INVALID_HANDLE)
       lose(CKR_FUNCTION_FAILED);
@@ -2318,36 +2332,37 @@ static void digest_cleanup(hal_hash_handle_t *handle)
 }
 
 /*
- * 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.
+ * Compute the length of a signature based on the key.
  */
 
-static int get_signature_len(const CK_OBJECT_HANDLE object_handle,
-                             const hal_pkey_handle_t pkey,
+static int get_signature_len(const hal_pkey_handle_t pkey,
                              size_t *signature_len)
 {
   assert(signature_len != NULL);
 
-  CK_KEY_TYPE cka_key_type;
+  hal_rpc_pkey_attribute_t attribute;
+  uint8_t attribute_buffer[sizeof(CK_KEY_TYPE)];
   hal_curve_name_t curve;
   CK_BYTE oid[20];
-  CK_ULONG len;
 
-  if (!p11_attribute_get_ulong(session, object_handle, CKA_KEY_TYPE, &cka_key_type))
+  attribute.type = CKA_KEY_TYPE;
+  if (!hal_check(hal_rpc_pkey_get_attributes(pkey, &attribute, 1,
+                                             attribute_buffer, sizeof(attribute_buffer))))
     return 0;
 
-  switch (cka_key_type) {
+  switch (*(CK_KEY_TYPE*)attribute.value) {
 
   case CKK_RSA:
-    if (!p11_attribute_get(session, object_handle, CKA_MODULUS, NULL, &len, 0))
+    attribute.type = CKA_MODULUS;
+    if (!hal_check(hal_rpc_pkey_get_attributes(pkey, &attribute, 1, NULL, 0)))
       return 0;
-    *signature_len = len;
+    *signature_len = attribute.length;
     return 1;
 
   case CKK_EC:
-    if (!p11_attribute_get(session, object_handle, CKA_EC_PARAMS, oid, &len, sizeof(oid)) ||
-        !ec_curve_oid_to_name(oid, len, &curve))
+    attribute.type = CKA_EC_PARAMS;
+    if (!hal_check(hal_rpc_pkey_get_attributes(pkey, &attribute, 1, oid, sizeof(oid))) ||
+        !ec_curve_oid_to_name(attribute.value, attribute.length, &curve))
       return 0;
     switch (curve) {
     case HAL_CURVE_P256: *signature_len = 64;  return 1;
@@ -2379,7 +2394,7 @@ static CK_RV sign_hal_rpc(p11_session_t *session,
   if (!p11_object_pkey_open(session, session->sign_key_handle, &pkey))
     lose(CKR_FUNCTION_FAILED);
 
-  if (!get_signature_len(session->sign_key_handle, pkey, &signature_len))
+  if (!get_signature_len(pkey, &signature_len))
     lose(CKR_FUNCTION_FAILED);
 
   rv = pSignature != NULL && signature_len > *pulSignatureLen ? CKR_BUFFER_TOO_SMALL : CKR_OK;
@@ -2560,7 +2575,7 @@ CK_RV C_Finalize(CK_VOID_PTR pReserved)
    * Destroy all current sessions.
    */
 
-  p11_session_delete_all();
+  p11_session_free_all();
 
   /*
    * At this point we're pretty well committed to shutting down, so
@@ -2795,12 +2810,17 @@ CK_RV C_CloseSession(CK_SESSION_HANDLE hSession)
 {
   ENTER_PUBLIC_FUNCTION(C_CloseSession);
 
-  CK_RV rv;
+  p11_session_t *session;
+  CK_RV rv = CKR_OK;
 
   mutex_lock_or_return_failure(p11_global_mutex);
 
-  rv = p11_session_delete(hSession);
+  if ((session = p11_session_find(hSession)) == NULL)
+    lose(CKR_SESSION_HANDLE_INVALID);
+
+  p11_session_free(session);
 
+ fail:
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
 }
 
@@ -2813,7 +2833,7 @@ CK_RV C_CloseAllSessions(CK_SLOT_ID slotID)
 
   mutex_lock_or_return_failure(p11_global_mutex);
 
-  p11_session_delete_all();
+  p11_session_free_all();
 
   return mutex_unlock(p11_global_mutex);
 }
@@ -2924,6 +2944,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 = NULL;
   CK_RV rv = CKR_OK;
 
   mutex_lock_or_return_failure(p11_global_mutex);
@@ -2934,7 +2955,7 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession)
    * anything special for "this" session.
    */
 
-  if (p11_session_find(hSession) == NULL)
+  if ((session = p11_session_find(hSession)) == NULL)
     lose(CKR_SESSION_HANDLE_INVALID);
 
   if (logged_in_as == not_logged_in)
@@ -2950,7 +2971,7 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession)
 
     const hal_session_handle_t session_handle_none = {HAL_HANDLE_NONE};
 
-    const hal_rpc_pkey_attribute attrs[] = {
+    const hal_rpc_pkey_attribute_t attrs[] = {
       {.type = CKA_PRIVATE, .value = &const_CK_TRUE, .length = sizeof(const_CK_TRUE)}
     };
 
@@ -2965,12 +2986,13 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession)
                                                  HAL_KEY_TYPE_NONE, HAL_CURVE_NONE,
                                                  0,
                                                  attrs, sizeof(attrs)/sizeof(*attrs),
-                                                 uuids, &n, sizeof(uuids)/sizeof(*uuuids),
-                                                 &uuids[sizeof(uuids)/sizeof(*uuuids) - 1]));
+                                                 uuids, &n, sizeof(uuids)/sizeof(*uuids),
+                                                 &uuids[sizeof(uuids)/sizeof(*uuids) - 1]));
       if (rv != CKR_OK)
         goto fail;
 
       for (int i = 0; i < n; i++) {
+        p11_object_free(p11_object_by_uuid(&uuids[i]));
         hal_pkey_handle_t pkey;
         rv = p11_whine_from_hal(hal_rpc_pkey_open(p11_session_hal_client(session),
                                                   session_handle_none, &pkey, &uuids[i], 0));
@@ -2982,17 +3004,7 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession)
         }
       }
 
-      if (n > 0) {
-        for (CK_OBJECT_HANDLE handle = p11_object_handle_iterate(CK_INVALID_HANDLE);
-             handle != CK_INVALID_HANDLE; handle = p11_object_handle_iterate(handle)) {
-          p11_object_t *object = p11_object_find(handle);
-          assert(object != NULL);
-          if (bsearch(&object->uuid, uuids, n, sizeof(*uuids), hal_uuid_cmp) != NULL)
-            p11_object_free(object);
-        }
-      }
-
-    } while (n == sizeof(uuids)/sizeof(*uuuids));
+    } while (n == sizeof(uuids)/sizeof(*uuids));
 
     memset(uuids, 0, sizeof(uuids));
     do {
@@ -3002,22 +3014,15 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession)
                                                  HAL_KEY_TYPE_NONE, HAL_CURVE_NONE,
                                                  HAL_KEY_FLAG_TOKEN,
                                                  attrs, sizeof(attrs)/sizeof(*attrs),
-                                                 uuids, &n, sizeof(uuids)/sizeof(*uuuids),
-                                                 &uuids[sizeof(uuids)/sizeof(*uuuids) - 1]));
+                                                 uuids, &n, sizeof(uuids)/sizeof(*uuids),
+                                                 &uuids[sizeof(uuids)/sizeof(*uuids) - 1]));
       if (rv != CKR_OK)
         goto fail;
 
-      if (n > 0) {
-        for (CK_OBJECT_HANDLE handle = p11_object_handle_iterate(CK_INVALID_HANDLE);
-             handle != CK_INVALID_HANDLE; handle = p11_object_handle_iterate(handle)) {
-          p11_object_t *object = p11_object_find(handle);
-          assert(object != NULL);
-          if (bsearch(&object->uuid, uuids, n, sizeof(*uuids), hal_uuid_cmp) != NULL)
-            p11_object_free(object);
-        }
-      }
+      for (int i = 0; i < n; i++)
+        p11_object_free(p11_object_by_uuid(&uuids[i]));
 
-    } while (n == sizeof(uuids)/sizeof(*uuuids));
+    } while (n == sizeof(uuids)/sizeof(*uuids));
 
     for (p11_session_t *session = p11_session_iterate(NULL);
          session != NULL; session = p11_session_iterate(session)) {
@@ -3054,7 +3059,6 @@ 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;
 
@@ -3145,7 +3149,14 @@ CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession,
 {
   ENTER_PUBLIC_FUNCTION(C_DestroyObject);
 
+  uint8_t attributes_buffer[2 * sizeof(CK_BBOOL)];
   hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
+  hal_rpc_pkey_attribute_t attributes[] = {
+    [0].type = CKA_PRIVATE,
+    [1].type = CKA_TOKEN
+  };
+  CK_BBOOL cka_private;
+  CK_BBOOL cka_token;
   p11_session_t *session;
   CK_RV rv = CKR_OK;
 
@@ -3153,20 +3164,29 @@ CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession,
 
   session = p11_session_find(hSession);
 
-  if ((rv = p11_object_check_rights(session, hObject, p11_object_access_write)) != CKR_OK)
-    goto fail;
-
   if (!p11_object_pkey_open(session, hObject, &pkey))
     lose(CKR_FUNCTION_FAILED);
 
-  if (!hal_check(hal_rpc_pkey_delete(pkey))) {
-    (void) hal_rpc_pkey_close(pkey);
+  if (!hal_check(hal_rpc_pkey_get_attributes(pkey, attributes, sizeof(attributes)/sizeof(*attributes),
+                                             attributes_buffer, sizeof(attributes_buffer))))
+    lose(CKR_KEY_HANDLE_INVALID);
+
+  cka_private  = *(CK_BBOOL*) attributes[0].value;
+  cka_token    = *(CK_BBOOL*) attributes[1].value;
+
+  rv = p11_object_check_rights(session, hObject, p11_object_access_write, cka_private, cka_token);
+
+  if (rv != CKR_OK)
+    goto fail;
+
+  if (!hal_check(hal_rpc_pkey_delete(pkey)))
     lose(CKR_FUNCTION_FAILED);
-  }
 
-  p11_object_free(p11_object_find(hObject));
+  p11_object_free(p11_object_by_handle(hObject));
 
  fail:
+  if (pkey.handle != HAL_HANDLE_NONE)
+    (void) hal_rpc_pkey_close(pkey);
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
 }
 
@@ -3177,12 +3197,14 @@ CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession,
 {
   ENTER_PUBLIC_FUNCTION(C_GetAttributeValue);
 
-  p11_session_t *session;
+  hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
   const p11_descriptor_t *descriptor = NULL;
-  CK_BBOOL cka_sensitive, cka_extractable;
+  CK_BBOOL cka_extractable, cka_sensitive;
   CK_OBJECT_CLASS cka_class;
-  CK_KEY_TYPE cka_key_type;
+  CK_BBOOL cka_private;
+  CK_BBOOL cka_token;
   int sensitive_object = 0;
+  p11_session_t *session;
   CK_RV rv;
 
   mutex_lock_or_return_failure(p11_global_mutex);
@@ -3192,70 +3214,122 @@ CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession,
 
   session = p11_session_find(hSession);
 
-  if ((rv = p11_object_check_rights(session, hObject, p11_object_access_read)) != CKR_OK)
-    goto fail;
-
-  if (!p11_attribute_get_ulong(session, hObject, CKA_CLASS, &cka_class))
+  if (!p11_object_pkey_open(session, hObject, &pkey))
     lose(CKR_OBJECT_HANDLE_INVALID);
 
-  switch (cka_class) {
+  {
+    hal_rpc_pkey_attribute_t attributes[] = {
+      [0].type = CKA_CLASS,
+      [1].type = CKA_PRIVATE,
+      [2].type = CKA_TOKEN
+    };
+    uint8_t attributes_buffer[sizeof(CK_OBJECT_CLASS) + 2 * sizeof(CK_BBOOL)];
 
-  case CKO_PRIVATE_KEY:
-  case CKO_SECRET_KEY:
-    if (!p11_attribute_get_bbool(session, hObject, CKA_EXTRACTABLE, &cka_extractable) ||
-        !p11_attribute_get_bbool(session, hObject, CKA_SENSITIVE,   &cka_sensitive))
+    if (!hal_check(hal_rpc_pkey_get_attributes(pkey,
+                                               attributes, sizeof(attributes)/sizeof(*attributes),
+                                               attributes_buffer, sizeof(attributes_buffer))))
       lose(CKR_OBJECT_HANDLE_INVALID);
 
-    sensitive_object = cka_sensitive || !cka_extractable;
+    cka_class    = *(CK_OBJECT_CLASS*) attributes[0].value;
+    cka_private  = *(CK_BBOOL*)        attributes[1].value;
+    cka_token    = *(CK_BBOOL*)        attributes[2].value;
 
-    /* Fall through */
+    rv = p11_object_check_rights(session, hObject, p11_object_access_read, cka_private, cka_token);
 
-  case CKO_PUBLIC_KEY:
-    if (!p11_attribute_get_ulong(session, hObject, CKA_KEY_TYPE, &cka_key_type))
+    if (rv != CKR_OK)
+      goto fail;
+  }
+
+  if (cka_class == CKO_PRIVATE_KEY || cka_class == CKO_SECRET_KEY) {
+    hal_rpc_pkey_attribute_t attributes[] = {
+      [0].type = CKA_EXTRACTABLE,
+      [1].type = CKA_SENSITIVE
+    };
+    uint8_t attributes_buffer[sizeof(CK_OBJECT_CLASS) + sizeof(CK_KEY_TYPE)];
+
+    if (!hal_check(hal_rpc_pkey_get_attributes(pkey,
+                                               attributes, sizeof(attributes)/sizeof(*attributes),
+                                               attributes_buffer, sizeof(attributes_buffer))))
       lose(CKR_OBJECT_HANDLE_INVALID);
-    descriptor = p11_descriptor_from_key_type(cka_class, cka_key_type);
+
+    cka_extractable = *(CK_BBOOL*) attributes[0].value;
+    cka_sensitive   = *(CK_BBOOL*) attributes[1].value;
+
+    sensitive_object = cka_sensitive || !cka_extractable;
   }
 
-  if (!sql_check_ok(sql_prepare(&q, select_format, flavor)) ||
-      !sql_check_ok(sqlite3_bind_int64(q, 1, hObject)))
-    lose(CKR_FUNCTION_FAILED);
+  {
+    hal_rpc_pkey_attribute_t attributes[ulCount];
 
-  rv = CKR_OK;
+    memset(attributes, 0, sizeof(attributes));
 
-  for (int i = 0; i < ulCount; i++) {
+    for (int i = 0; i < ulCount; i++)
+      attributes[i].type = pTemplate[i].type;
 
-    if (sensitive_object && p11_attribute_is_sensitive(descriptor, pTemplate[i].type)) {
-      pTemplate[i].ulValueLen = -1;
-      rv = CKR_ATTRIBUTE_SENSITIVE;
-    }
+    if (!hal_check(hal_rpc_pkey_get_attributes(pkey,
+                                               attributes, sizeof(attributes)/sizeof(*attributes),
+                                               NULL, 0)))
+      lose(CKR_OBJECT_HANDLE_INVALID);
 
-    else if (!sql_check_ok(sqlite3_reset(q)) ||
-             !sql_check_ok(sqlite3_bind_int64(q, 2, pTemplate[i].type)) ||
-             (ret = sqlite3_step(q)) != SQLITE_ROW) {
-      if (ret != SQLITE_DONE)
-        sql_whine_step();
-      pTemplate[i].ulValueLen = -1;
-      rv = CKR_ATTRIBUTE_TYPE_INVALID;
-    }
+    rv = CKR_OK;
 
-    else if (pTemplate[i].pValue == NULL) {
-      pTemplate[i].ulValueLen = sqlite3_column_bytes(q, 0);
-    }
+    size_t attributes_buffer_len = 0;
 
-    else if (pTemplate[i].ulValueLen >= sqlite3_column_bytes(q, 0)) {
-      pTemplate[i].ulValueLen = sqlite3_column_bytes(q, 0);
-      memcpy(pTemplate[i].pValue, sqlite3_column_blob(q, 0), pTemplate[i].ulValueLen);
+    for (int i = 0; i < ulCount; i++) {
+      if (sensitive_object && p11_attribute_is_sensitive(descriptor, pTemplate[i].type)) {
+        pTemplate[i].ulValueLen = -1;
+        rv = CKR_ATTRIBUTE_SENSITIVE;
+        continue;
+      }
+      if (attributes[i].length == 0) {
+        pTemplate[i].ulValueLen = -1;
+        rv = CKR_ATTRIBUTE_TYPE_INVALID;
+        continue;
+      }
+      if (pTemplate[i].pValue == NULL) {
+        pTemplate[i].ulValueLen = attributes[i].length;
+        continue;
+      }
+      if (pTemplate[i].ulValueLen < attributes[i].length) {
+        pTemplate[i].ulValueLen = -1;
+        rv = CKR_BUFFER_TOO_SMALL;
+        continue;
+      }
+      attributes_buffer_len += attributes[i].length;
     }
 
-    else {
-      pTemplate[i].ulValueLen = -1;
-      rv = CKR_BUFFER_TOO_SMALL;
-    }
+    if (attributes_buffer_len == 0)
+      goto fail;
+
+    uint8_t attributes_buffer[attributes_buffer_len];
+    unsigned n = 0;
+
+    for (int i = 0; i < ulCount; i++)
+      if (pTemplate[i].pValue != NULL && pTemplate[i].ulValueLen != -1)
+        attributes[n++].type = pTemplate[i].type;
+
+    if (!hal_check(hal_rpc_pkey_get_attributes(pkey, attributes, n,
+                                               attributes_buffer, sizeof(attributes_buffer))))
+      lose(CKR_OBJECT_HANDLE_INVALID);
 
+    for (int i = 0; i < n; i++) {
+      int j = p11_attribute_find_in_template(attributes[i].type, pTemplate, ulCount);
+
+      if (j < 0 || pTemplate[j].ulValueLen == -1 || pTemplate[j].ulValueLen < attributes[i].length)
+        lose(CKR_FUNCTION_FAILED);
+
+      memcpy(pTemplate[j].pValue, attributes[i].value, attributes[i].length);
+      pTemplate[j].ulValueLen = attributes[i].length;
+    }
   }
 
  fail:
-  sqlite3_finalize(q);
+  if (pkey.handle != HAL_HANDLE_NONE) {
+    if (rv == CKR_OK)
+      rv = p11_whine_from_hal(hal_rpc_pkey_close(pkey));
+    else
+      (void) hal_rpc_pkey_close(pkey);
+  }
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
 }
 
@@ -3265,139 +3339,76 @@ CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession,
 {
   ENTER_PUBLIC_FUNCTION(C_FindObjectsInit);
 
-  static const char select_missing[] =
-    " WITH"
-    "   known AS (SELECT token_object_id FROM object WHERE token_object_id IS NOT NULL)"
-    " SELECT token_object_id FROM token_object WHERE token_object_id NOT IN known";
-
-  static const char insert_missing[] =
-    " INSERT INTO object (object_handle, token_object_id) VALUES (?1, ?2)";
-
-  static const char create_format[] =
-    " CREATE TEMPORARY TABLE findobjects_%lu AS"
-    " SELECT object_id FROM object NATURAL LEFT JOIN session"
-    " WHERE session_handle IS NULL OR session_handle = ?1";
-
-  static const char drop_format[] =
-    " DROP TABLE IF EXISTS findobjects_%lu";
-
-  static const char delete_format[] =
-    " WITH"
-    "   matches AS (SELECT object_id"
-    "                 FROM object NATURAL JOIN session_attribute"
-    "                 WHERE type = ?1 AND value = ?2"
-    "               UNION"
-    "               SELECT object_id"
-    "                 FROM object NATURAL JOIN token_attribute"
-    "                 WHERE type = ?1 AND value = ?2)"
-    " DELETE FROM findobjects_%lu WHERE object_id NOT IN matches";
-
-  static const char select_format[] =
-    " SELECT object_handle FROM findobjects_%lu NATURAL JOIN object ORDER BY object_id";
-
+  const size_t attributes_len = sizeof(hal_rpc_pkey_attribute_t) * (ulCount + 1);
+  size_t len = attributes_len;
+  CK_BBOOL *cka_private = NULL;
+  CK_BBOOL *cka_token = NULL;
   p11_session_t *session;
-  sqlite3_stmt *q1 = NULL, *q2 = NULL;
   CK_RV rv = CKR_OK;
-  int i, ret;
+  uint8_t *mem;
 
   mutex_lock_or_return_failure(p11_global_mutex);
 
   if ((session = p11_session_find(hSession)) == NULL)
     lose(CKR_SESSION_HANDLE_INVALID);
 
-  if (ulCount > 0  && pTemplate == NULL)
+  if (ulCount > 0 && pTemplate == NULL)
     lose(CKR_ARGUMENTS_BAD);
 
   if (session->find_query != NULL)
     lose(CKR_OPERATION_ACTIVE);
 
-  /*
-   * Assign handles to any token objects that don't have them yet.
-   */
+  assert(!session->find_query_token && !session->find_query_session);
 
-  if (!sql_check_ok(sql_prepare(&q1, select_missing))   ||
-      !sql_check_ok(sql_prepare(&q2, insert_missing)))
-    lose(CKR_FUNCTION_FAILED);
+  for (int i = 0; i < ulCount; i++) {
+    if (pTemplate[i].pValue == NULL || pTemplate[i].ulValueLen == 0)
+      lose(CKR_ARGUMENTS_BAD);
+    len += pTemplate[i].ulValueLen;
+  }
 
-  while ((ret = sqlite3_step(q1)) == SQLITE_ROW) {
-    sqlite3_int64 token_object_id = sqlite3_column_int64(q1, 0);
-    CK_OBJECT_HANDLE object_handle = p11_allocate_unused_handle(handle_flavor_token_object);
+  if ((mem = malloc(len)) == NULL)
+    lose(CKR_HOST_MEMORY);
 
-    if (!sql_check_ok(sqlite3_reset(q2))                                ||
-        !sql_check_ok(sqlite3_bind_int64(q2, 1, object_handle))         ||
-        !sql_check_ok(sqlite3_bind_int64(q2, 2, token_object_id))       ||
-        !sql_check_done(sqlite3_step(q2)))
-      lose(CKR_FUNCTION_FAILED);
-  }
+  session->find_query = (hal_rpc_pkey_attribute_t *) mem;
+  mem += attributes_len;
 
-  if (ret != SQLITE_DONE) {
-    sql_whine_step();
-    lose(CKR_FUNCTION_FAILED);
+  for (int i = 0; i < ulCount; i++) {
+    len = pTemplate[i].ulValueLen;
+    session->find_query[i].type   = pTemplate[i].type;
+    session->find_query[i].value  = mem;
+    session->find_query[i].length = len;
+    memcpy(mem, pTemplate[i].pValue, len);
+    mem += len;
   }
 
-  /*
-   * Create a temporary table to hold this session's FindObjects
-   * state.  Populate this with every object this session knows about,
-   * then prune based on login status and whatever filter attributes
-   * the caller supplied.
-   */
+  cka_private = p11_attribute_find_value_in_template(CKA_PRIVATE, pTemplate, ulCount);
+  cka_token   = p11_attribute_find_value_in_template(CKA_TOKEN,   pTemplate, ulCount);
 
-  if (!sql_check_ok(sql_finalize_and_clear(&q1))                ||
-      !sql_check_ok(sql_finalize_and_clear(&q2))                ||
-      !sql_check_ok(sql_prepare(&q1, drop_format, hSession))    ||
-      !sql_check_done(sqlite3_step(q1))                         ||
-      !sql_check_ok(sql_prepare(&q2, create_format, hSession))  ||
-      !sql_check_ok(sqlite3_bind_int64(q2, 1, hSession))        ||
-      !sql_check_done(sqlite3_step(q2))                         ||
-      !sql_check_ok(sql_finalize_and_clear(&q1))                ||
-      !sql_check_ok(sql_finalize_and_clear(&q2))                ||
-      !sql_check_ok(sql_prepare(&q1, delete_format, hSession)))
-    lose(CKR_FUNCTION_FAILED);
+  session->find_query_n       = ulCount;
+  session->find_query_token   = cka_token == NULL ||  *cka_token;
+  session->find_query_session = cka_token == NULL || !*cka_token;
+  memset(&session->find_query_previous_uuid, 0, sizeof(session->find_query_previous_uuid));
 
   /*
-   * If we're not logged in as the regular user, run an extra filter
-   * cycle to remove all private objects before we get to the
-   * caller-supplied template.
+   * Quietly enforce object privacy even if template tries to bypass,
+   * per PCKS #11 specification.
    */
 
-  if (logged_in_as != logged_in_as_user) {
-    if (!sql_check_ok(sqlite3_bind_int64(q1, 1, CKA_PRIVATE))   ||
-        !sql_check_ok(sqlite3_bind_blob( q1, 2,
-                                         &const_CK_FALSE,
-                                         sizeof(const_CK_FALSE),
-                                         NULL))                 ||
-        !sql_check_done(sqlite3_step(q1)))
-      lose(CKR_FUNCTION_FAILED);
+  if (logged_in_as != logged_in_as_user && cka_private == NULL) {
+    session->find_query[ulCount].type   = CKA_PRIVATE;
+    session->find_query[ulCount].value  = &const_CK_FALSE;
+    session->find_query[ulCount].length = sizeof(const_CK_FALSE);
+    session->find_query_n++;
   }
 
-  /*
-   * Filter through the caller-supplied template.
-   *
-   * NB: This doesn't support some of the more obscure searches, such
-   * as searches for sessions or hardware features.  Too much rope
-   * already, worry about those if we ever really need them.
-   */
-
-  for (i = 0; i < ulCount; i++)
-    if (!sql_check_ok(sqlite3_reset(q1))                                ||
-        !sql_check_ok(sqlite3_bind_int64(q1, 1, pTemplate[i].type))     ||
-        !sql_check_ok(sqlite3_bind_blob( q1, 2, pTemplate[i].pValue,
-                                        pTemplate[i].ulValueLen, NULL)) ||
-        !sql_check_done(sqlite3_step(q1)))
-      lose(CKR_FUNCTION_FAILED);
-
-  /*
-   * Stash a prepared query in the session object which will return
-   * whatever object handles survived all that filtering.
-   */
-
-  if (!sql_check_ok(sql_prepare(&session->find_query, select_format, hSession)))
-    lose(CKR_FUNCTION_FAILED);
-  session->find_query_done = 0;
+  if (logged_in_as != logged_in_as_user && cka_private != NULL && *cka_private) {
+    int i = p11_attribute_find_in_template(CKA_PRIVATE, pTemplate, ulCount);
+    assert(i >= 0 && i < ulCount);
+    session->find_query[i].value  = &const_CK_FALSE;
+    session->find_query[i].length = sizeof(const_CK_FALSE);
+  }
 
  fail:
-  sqlite3_finalize(q1);
-  sqlite3_finalize(q2);
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
 }
 
@@ -3408,8 +3419,8 @@ CK_RV C_FindObjects(CK_SESSION_HANDLE hSession,
 {
   ENTER_PUBLIC_FUNCTION(C_FindObjects);
 
+  hal_uuid_t previous_uuid = {{0}};
   p11_session_t *session;
-  int i, ret = SQLITE_OK;
   CK_RV rv = CKR_OK;
 
   mutex_lock_or_return_failure(p11_global_mutex);
@@ -3423,35 +3434,55 @@ CK_RV C_FindObjects(CK_SESSION_HANDLE hSession,
   if (phObject == NULL || pulObjectCount == NULL)
     lose(CKR_ARGUMENTS_BAD);
 
-  /*
-   * C_FindObjectsInit() did all the heavy lifting, we just have to
-   * return the resulting handles.
-   */
+  *pulObjectCount = 0;
 
-  i = 0;
+  while (*pulObjectCount < ulMaxObjectCount &&
+         (session->find_query_token || session->find_query_session)) {
+    hal_uuid_t uuids[ulMaxObjectCount - *pulObjectCount];
+    handle_flavor_t flavor;
+    hal_key_flags_t flags;
+    unsigned n;
 
-  if (!session->find_query_done)
-    while (i < ulMaxObjectCount && (ret = sqlite3_step(session->find_query)) == SQLITE_ROW)
-      phObject[i++] = (CK_OBJECT_HANDLE) sqlite3_column_int64(session->find_query, 0);
+    if (session->find_query_token) {
+      flavor = handle_flavor_token_object;
+      flags  = HAL_KEY_FLAG_TOKEN;
+    }
+    else {
+      flavor = handle_flavor_session_object;
+      flags  = 0;
+    }
 
-  switch (ret) {
+    rv = p11_whine_from_hal(hal_rpc_pkey_match(p11_session_hal_client(session),
+                                               p11_session_hal_session(session),
+                                               HAL_KEY_TYPE_NONE, HAL_CURVE_NONE, flags,
+                                               session->find_query, session->find_query_n,
+                                               uuids, &n, sizeof(uuids)/sizeof(*uuids),
+                                               &previous_uuid));
+      if (rv != CKR_OK)
+        goto fail;
 
-  case SQLITE_DONE:
-    session->find_query_done = 1;
-    break;
+      for (int i = 0; i < n; i++) {
+        phObject[*pulObjectCount] = p11_object_allocate(flavor, &uuids[i], session);
+        if (phObject[*pulObjectCount] == CK_INVALID_HANDLE)
+          lose(CKR_FUNCTION_FAILED);
+        ++*pulObjectCount;
+      }
 
-  case SQLITE_OK:
-  case SQLITE_ROW:
-    break;
+      if (n == sizeof(uuids)/sizeof(*uuids)) {
+        memcpy(&session->find_query_previous_uuid, &uuids[n - 1],
+               sizeof(session->find_query_previous_uuid));
+      }
 
-  default:
-    sql_whine_step();
-    lose(CKR_FUNCTION_FAILED);
+      else {
+        memset(&session->find_query_previous_uuid, 0, sizeof(session->find_query_previous_uuid));
 
+        if (session->find_query_token)
+          session->find_query_token = 0;
+        else
+          session->find_query_session = 0;
+      }
   }
 
-  *pulObjectCount = i;
-
  fail:
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
 }
@@ -3460,11 +3491,7 @@ CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
 {
   ENTER_PUBLIC_FUNCTION(C_FindObjectsFinal);
 
-  static const char drop_format[] =
-    " DROP TABLE IF EXISTS findobjects_%lu";
-
   p11_session_t *session;
-  sqlite3_stmt *q = NULL;
   CK_RV rv = CKR_OK;
 
   mutex_lock_or_return_failure(p11_global_mutex);
@@ -3475,17 +3502,15 @@ CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
   if (session->find_query == NULL)
     lose(CKR_OPERATION_NOT_INITIALIZED);
 
-  /*
-   * Clean up result query and temporary table.
-   */
+  free(session->find_query);
 
-  if (!sql_check_ok(sql_finalize_and_clear(&session->find_query))       ||
-      !sql_check_ok(sql_prepare(&q, drop_format, hSession))             ||
-      !sql_check_done(sqlite3_step(q)))
-    lose(CKR_FUNCTION_FAILED);
+  session->find_query = NULL;
+  session->find_query_n = 0;
+  session->find_query_token = 0;
+  session->find_query_session = 0;
+  memset(&session->find_query_previous_uuid, 0, sizeof(session->find_query_previous_uuid));
 
  fail:
-  sqlite3_finalize(q);
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
 }
 
@@ -3662,10 +3687,19 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession,
 {
   ENTER_PUBLIC_FUNCTION(C_SignInit);
 
+  uint8_t attributes_buffer[sizeof(CK_OBJECT_CLASS) + sizeof(CK_KEY_TYPE) + 3 * sizeof(CK_BBOOL)];
+  hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
+  hal_rpc_pkey_attribute_t attributes[] = {
+    [0].type = CKA_KEY_TYPE,
+    [1].type = CKA_SIGN,
+    [2].type = CKA_PRIVATE,
+    [3].type = CKA_TOKEN
+  };
+  CK_KEY_TYPE cka_key_type;
+  CK_BBOOL cka_sign;
+  CK_BBOOL cka_private;
+  CK_BBOOL cka_token;
   p11_session_t *session;
-  CK_OBJECT_CLASS key_class;
-  CK_KEY_TYPE key_type;
-  CK_BBOOL key_sign;
   CK_RV rv = CKR_OK;
 
   mutex_lock_or_return_failure(p11_global_mutex);
@@ -3676,19 +3710,28 @@ 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_algorithm != HAL_DIGEST_ALGORITHM_NONE)
+  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)
-    goto fail;
+  if (!p11_object_pkey_open(session, hKey, &pkey))
+    lose(CKR_KEY_HANDLE_INVALID);
 
-  if (!p11_attribute_get_ulong(session, hKey, CKA_CLASS,    &key_class)  ||
-      !p11_attribute_get_ulong(session, hKey, CKA_KEY_TYPE, &key_type)   ||
-      !p11_attribute_get_bbool(session, hKey, CKA_SIGN,     &key_sign)   ||
-      key_class != CKO_PRIVATE_KEY)
+  if (!hal_check(hal_rpc_pkey_get_attributes(pkey, attributes, sizeof(attributes)/sizeof(*attributes),
+                                             attributes_buffer, sizeof(attributes_buffer))))
     lose(CKR_KEY_HANDLE_INVALID);
 
-  if (!key_sign)
+  cka_key_type = *(CK_KEY_TYPE*) attributes[0].value;
+  cka_sign     = *(CK_BBOOL*)    attributes[1].value;
+  cka_private  = *(CK_BBOOL*)    attributes[2].value;
+  cka_token    = *(CK_BBOOL*)    attributes[3].value;
+
+  rv = p11_object_check_rights(session, hKey, p11_object_access_read, cka_private, cka_token);
+
+  if (rv != CKR_OK)
+    goto fail;
+
+  if (!cka_sign)
     lose(CKR_KEY_FUNCTION_NOT_PERMITTED);
 
   switch (pMechanism->mechanism) {
@@ -3698,7 +3741,7 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession,
   case CKM_SHA256_RSA_PKCS:
   case CKM_SHA384_RSA_PKCS:
   case CKM_SHA512_RSA_PKCS:
-    if (key_type != CKK_RSA)
+    if (cka_key_type != CKK_RSA)
       lose(CKR_KEY_TYPE_INCONSISTENT);
     break;
   case CKM_ECDSA:
@@ -3706,7 +3749,7 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession,
   case CKM_ECDSA_SHA256:
   case CKM_ECDSA_SHA384:
   case CKM_ECDSA_SHA512:
-    if (key_type != CKK_EC)
+    if (cka_key_type != CKK_EC)
       lose(CKR_KEY_TYPE_INCONSISTENT);
     break;
   default:
@@ -3743,10 +3786,12 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession,
     return CKR_MECHANISM_INVALID;
   }
 
-  return mutex_unlock(p11_global_mutex);
+  rv = CKR_OK;
 
  fail:
-  if (session != NULL) {
+  if (pkey.handle != HAL_HANDLE_NONE)
+    (void) hal_rpc_pkey_close(pkey);
+  if (rv != CKR_OK && session != NULL) {
     session->sign_key_handle = CK_INVALID_HANDLE;
     session->sign_digest_algorithm = HAL_DIGEST_ALGORITHM_NONE;
   }
@@ -3762,7 +3807,6 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession,
   ENTER_PUBLIC_FUNCTION(C_Sign);
 
   p11_session_t *session;
-  CK_KEY_TYPE key_type;
   CK_RV rv;
 
   mutex_lock_or_return_failure(p11_global_mutex);
@@ -3779,9 +3823,6 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession,
   if (session->sign_digest_handle.handle != HAL_HANDLE_NONE)
     lose(CKR_OPERATION_ACTIVE);
 
-  if (!p11_attribute_get_ulong(session, 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)
@@ -3790,16 +3831,8 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession,
     ulDataLen = 0;
   }
 
-  switch (key_type) {
-
-  case CKK_RSA:
-  case CKK_EC:
-    rv = sign_hal_rpc(session, pData, ulDataLen, pSignature, pulSignatureLen);
-    break;
+  rv = sign_hal_rpc(session, pData, ulDataLen, pSignature, pulSignatureLen);
 
-  default:
-    lose(CKR_FUNCTION_FAILED);
-  }
                                 /* Fall through */
  fail:
   if (session != NULL && pSignature != NULL && rv != CKR_BUFFER_TOO_SMALL) {
@@ -3857,7 +3890,6 @@ CK_RV C_SignFinal(CK_SESSION_HANDLE hSession,
   ENTER_PUBLIC_FUNCTION(C_SignFinal);
 
   p11_session_t *session;
-  CK_KEY_TYPE key_type;
   CK_RV rv;
 
   mutex_lock_or_return_failure(p11_global_mutex);
@@ -3868,22 +3900,12 @@ 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_handle.handle == HAL_HANDLE_NONE)
+  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, session->sign_key_handle, CKA_KEY_TYPE, &key_type))
-    lose(CKR_FUNCTION_FAILED);
-
-  switch (key_type) {
-
-  case CKK_RSA:
-  case CKK_EC:
-    rv = sign_hal_rpc(session, NULL, 0, pSignature, pulSignatureLen);
-    break;
+  rv = sign_hal_rpc(session, NULL, 0, pSignature, pulSignatureLen);
 
-  default:
-    lose(CKR_FUNCTION_FAILED);
-  }
                                 /* Fall through */
  fail:
   if (session != NULL && pSignature != NULL && rv != CKR_BUFFER_TOO_SMALL) {
@@ -3901,10 +3923,20 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession,
 {
   ENTER_PUBLIC_FUNCTION(C_VerifyInit);
 
+  uint8_t attributes_buffer[sizeof(CK_OBJECT_CLASS) + sizeof(CK_KEY_TYPE) + 3 * sizeof(CK_BBOOL)];
+  hal_pkey_handle_t pkey = {HAL_HANDLE_NONE};
+  hal_rpc_pkey_attribute_t attributes[] = {
+    [0].type = CKA_KEY_TYPE,
+    [1].type = CKA_VERIFY,
+    [2].type = CKA_PRIVATE,
+    [3].type = CKA_TOKEN
+  };
+  CK_KEY_TYPE cka_key_type;
+  CK_BBOOL cka_verify;
+  CK_BBOOL cka_private;
+  CK_BBOOL cka_token;
+
   p11_session_t *session;
-  CK_OBJECT_CLASS key_class;
-  CK_KEY_TYPE key_type;
-  CK_BBOOL key_verify;
   CK_RV rv = CKR_OK;
 
   mutex_lock_or_return_failure(p11_global_mutex);
@@ -3915,19 +3947,28 @@ 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_algorithm != HAL_DIGEST_ALGORITHM_NONE)
+  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)
-    goto fail;
+  if (!p11_object_pkey_open(session, hKey, &pkey))
+    lose(CKR_KEY_HANDLE_INVALID);
 
-  if (!p11_attribute_get_ulong(session, hKey, CKA_CLASS,    &key_class)  ||
-      !p11_attribute_get_ulong(session, hKey, CKA_KEY_TYPE, &key_type)   ||
-      !p11_attribute_get_bbool(session, hKey, CKA_VERIFY,   &key_verify) ||
-      key_class != CKO_PUBLIC_KEY)
+  if (!hal_check(hal_rpc_pkey_get_attributes(pkey, attributes, sizeof(attributes)/sizeof(*attributes),
+                                             attributes_buffer, sizeof(attributes_buffer))))
     lose(CKR_KEY_HANDLE_INVALID);
 
-  if (!key_verify)
+  cka_key_type = *(CK_KEY_TYPE*) attributes[0].value;
+  cka_verify   = *(CK_BBOOL*)    attributes[1].value;
+  cka_private  = *(CK_BBOOL*)    attributes[2].value;
+  cka_token    = *(CK_BBOOL*)    attributes[3].value;
+
+  rv = p11_object_check_rights(session, hKey, p11_object_access_read, cka_private, cka_token);
+
+  if (rv != CKR_OK)
+    goto fail;
+
+  if (!cka_verify)
     lose(CKR_KEY_FUNCTION_NOT_PERMITTED);
 
   switch (pMechanism->mechanism) {
@@ -3937,7 +3978,7 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession,
   case CKM_SHA256_RSA_PKCS:
   case CKM_SHA384_RSA_PKCS:
   case CKM_SHA512_RSA_PKCS:
-    if (key_type != CKK_RSA)
+    if (cka_key_type != CKK_RSA)
       lose(CKR_KEY_TYPE_INCONSISTENT);
     break;
   case CKM_ECDSA:
@@ -3945,7 +3986,7 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession,
   case CKM_ECDSA_SHA256:
   case CKM_ECDSA_SHA384:
   case CKM_ECDSA_SHA512:
-    if (key_type != CKK_EC)
+    if (cka_key_type != CKK_EC)
       lose(CKR_KEY_TYPE_INCONSISTENT);
     break;
   default:
@@ -3982,10 +4023,12 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession,
     return CKR_MECHANISM_INVALID;
   }
 
-  return mutex_unlock(p11_global_mutex);
+  rv = CKR_OK;
 
  fail:
-  if (session != NULL) {
+  if (pkey.handle != HAL_HANDLE_NONE)
+    (void) hal_rpc_pkey_close(pkey);
+  if (rv != CKR_OK && session != NULL) {
     session->verify_key_handle = CK_INVALID_HANDLE;
     session->verify_digest_algorithm = HAL_DIGEST_ALGORITHM_NONE;
   }
@@ -4001,7 +4044,6 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession,
   ENTER_PUBLIC_FUNCTION(C_Verify);
 
   p11_session_t *session;
-  CK_KEY_TYPE key_type;
   CK_RV rv;
 
   mutex_lock_or_return_failure(p11_global_mutex);
@@ -4023,19 +4065,7 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession,
     ulDataLen = 0;
   }
 
-  if (!p11_attribute_get_ulong(session, session->verify_key_handle, CKA_KEY_TYPE, &key_type))
-    lose(CKR_FUNCTION_FAILED);
-
-  switch (key_type) {
-
-  case CKK_RSA:
-  case CKK_EC:
-    rv = verify_hal_rpc(session, pData, ulDataLen, pSignature, ulSignatureLen);
-    break;
-
-  default:
-    lose(CKR_FUNCTION_FAILED);
-  }
+  rv = verify_hal_rpc(session, pData, ulDataLen, pSignature, ulSignatureLen);
 
  fail:                          /* Fall through */
 
@@ -4094,7 +4124,6 @@ CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession,
   ENTER_PUBLIC_FUNCTION(C_VerifyFinal);
 
   p11_session_t *session;
-  CK_KEY_TYPE key_type;
   CK_RV rv;
 
   mutex_lock_or_return_failure(p11_global_mutex);
@@ -4105,22 +4134,11 @@ 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_handle.handle == HAL_HANDLE_NONE)
+  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, session->verify_key_handle, CKA_KEY_TYPE, &key_type))
-    lose(CKR_FUNCTION_FAILED);
-
-  switch (key_type) {
-
-  case CKK_RSA:
-  case CKK_EC:
-    rv = verify_hal_rpc(session, NULL, 0, pSignature, ulSignatureLen);
-    break;
-
-  default:
-    lose(CKR_FUNCTION_FAILED);
-  }
+  rv = verify_hal_rpc(session, NULL, 0, pSignature, ulSignatureLen);
 
  fail:                          /* Fall through */
 



More information about the Commits mailing list