[Cryptech-Commits] [sw/libhal] 05/08: Per-session objects in ks_volatile; more untested ks_attribute code.

git at cryptech.is git at cryptech.is
Sun Oct 16 20:23:45 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/libhal.

commit 015eefa32f54f84c56bb7c6d36c0edcc104a69e8
Author: Rob Austein <sra at hactrn.net>
AuthorDate: Sun Oct 9 23:02:03 2016 -0400

    Per-session objects in ks_volatile; more untested ks_attribute code.
    
    Mostly this is another checkpoint (still passes PKCS #11 "make test").
    
    ks_volatile.c now contains support for per-session object visibility;
    this may need more work to support things like a CLI view of all
    objects regardless of session.  Adding this required minor changes to
    the keystore and pkey APIs, mostly because sessions are per-client.
    
    ks_volatile.c also contains an untested first cut at attribute
    support.  Attribute support in ks_flash.c still under construction.
---
 hal.h          |   7 +-
 hal_internal.h |  31 ++++----
 ks_flash.c     |  69 +++++++++++++----
 ks_volatile.c  | 233 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 rpc_api.c      |  11 ++-
 rpc_client.c   |  12 +--
 rpc_pkey.c     |  13 ++--
 rpc_server.c   |   4 +-
 8 files changed, 311 insertions(+), 69 deletions(-)

diff --git a/hal.h b/hal.h
index 997db7c..6bb2f67 100644
--- a/hal.h
+++ b/hal.h
@@ -148,6 +148,7 @@
   DEFINE_HAL_ERROR(HAL_ERROR_KEYSTORE_BAD_BLOCK_TYPE,   "Unsupported keystore block type")              \
   DEFINE_HAL_ERROR(HAL_ERROR_KEYSTORE_LOST_DATA,        "Keystore appears to have lost data")           \
   DEFINE_HAL_ERROR(HAL_ERROR_BAD_ATTRIBUTE_LENGTH,      "Bad attribute length")                         \
+  DEFINE_HAL_ERROR(HAL_ERROR_ATTRIBUTE_NOT_FOUND,       "Attribute not found")                          \
   END_OF_HAL_ERROR_LIST
 
 /* Marker to forestall silly line continuation errors */
@@ -754,7 +755,8 @@ typedef struct {
   /* ... */
 } hal_pkey_info_t;
 
-extern hal_error_t hal_rpc_pkey_list(const hal_session_handle_t session,
+extern hal_error_t hal_rpc_pkey_list(const hal_client_handle_t client,
+                                     const hal_session_handle_t session,
                                      hal_pkey_info_t *result,
                                      unsigned *result_len,
                                      const unsigned result_max,
@@ -766,7 +768,8 @@ typedef struct {
   const uint8_t *value;
 } hal_rpc_pkey_attribute_t;
 
-extern hal_error_t hal_rpc_pkey_match(const hal_session_handle_t session,
+extern hal_error_t hal_rpc_pkey_match(const hal_client_handle_t client,
+                                      const hal_session_handle_t session,
                                       const hal_key_type_t type,
                                       const hal_curve_name_t curve,
                                       const hal_key_flags_t flags,
diff --git a/hal_internal.h b/hal_internal.h
index fe1cb1f..61d8489 100644
--- a/hal_internal.h
+++ b/hal_internal.h
@@ -235,13 +235,15 @@ typedef struct {
                          const uint8_t * const input, const size_t input_len,
                          const uint8_t * const signature, const size_t signature_len);
 
-  hal_error_t  (*list)(const hal_session_handle_t session,
+  hal_error_t  (*list)(const hal_client_handle_t client,
+                       const hal_session_handle_t session,
                        hal_pkey_info_t *result,
                        unsigned *result_len,
                        const unsigned result_max,
                        hal_key_flags_t flags);
 
-  hal_error_t (*match)(const hal_session_handle_t session,
+  hal_error_t (*match)(const hal_client_handle_t client,
+                       const hal_session_handle_t session,
                        const hal_key_type_t type,
                        const hal_curve_name_t curve,
                        const hal_key_flags_t flags,
@@ -438,18 +440,7 @@ typedef struct {
   hal_curve_name_t curve;
   hal_key_flags_t flags;
   hal_uuid_t name;
-
-  /*
-   * We used to stash a "hint" value here for the keystore driver to
-   * speed things up when we had multiple operations on the same key.
-   * Removed as premature optimization during keystore rewrite, but we
-   * may want to put something like this back once the new API has
-   * stablized.  If so, form would probably be a union containing
-   * keystore-driver-specific data, which everything else (including
-   * the pkey code) should treat as opaque: making it really opaque
-   * would complicate memory allocation and isn't worth it for an
-   * internal API.
-   */
+  int hint;
 
   /*
    * This might be where we'd stash a (hal_core_t *) pointing to a
@@ -480,7 +471,7 @@ struct hal_ks_driver {
   hal_error_t (*close)(hal_ks_t *ks);
 
   hal_error_t (*store)(hal_ks_t *ks,
-                       const hal_pkey_slot_t * const slot,
+                       hal_pkey_slot_t *slot,
 		       const uint8_t * const der,  const size_t der_len);
 
   hal_error_t (*fetch)(hal_ks_t *ks,
@@ -488,15 +479,17 @@ struct hal_ks_driver {
 		       uint8_t *der, size_t *der_len, const size_t der_max);
 
   hal_error_t (*delete)(hal_ks_t *ks,
-                        const hal_pkey_slot_t * const slot);
+                        hal_pkey_slot_t *slot);
 
   hal_error_t (*list)(hal_ks_t *ks,
+                      const hal_client_handle_t client,
                       const hal_session_handle_t session,
 		      hal_pkey_info_t *result,
 		      unsigned *result_len,
 		      const unsigned result_max);
 
   hal_error_t (*match)(hal_ks_t *ks,
+                       const hal_client_handle_t client,
                        const hal_session_handle_t session,
                        const hal_key_type_t type,
                        const hal_curve_name_t curve,
@@ -608,6 +601,7 @@ static inline hal_error_t hal_ks_delete(hal_ks_t *ks,
 }
 
 static inline hal_error_t hal_ks_list(hal_ks_t *ks,
+                                      const hal_client_handle_t client,
                                       const hal_session_handle_t session,
                                       hal_pkey_info_t *result,
                                       unsigned *result_len,
@@ -616,10 +610,11 @@ static inline hal_error_t hal_ks_list(hal_ks_t *ks,
   if (ks == NULL || ks->driver == NULL || ks->driver->list == NULL)
     return HAL_ERROR_BAD_ARGUMENTS;
 
-  return ks->driver->list(ks, session, result, result_len, result_max);
+  return ks->driver->list(ks, client, session, result, result_len, result_max);
 }
 
 static inline hal_error_t hal_ks_match(hal_ks_t *ks,
+                                       const hal_client_handle_t client,
                                        const hal_session_handle_t session,
                                        const hal_key_type_t type,
                                        const hal_curve_name_t curve,
@@ -634,7 +629,7 @@ static inline hal_error_t hal_ks_match(hal_ks_t *ks,
   if (ks == NULL || ks->driver == NULL || ks->driver->match == NULL)
     return HAL_ERROR_BAD_ARGUMENTS;
 
-  return ks->driver->match(ks, session, type, curve, flags, attributes, attributes_len,
+  return ks->driver->match(ks, client, session, type, curve, flags, attributes, attributes_len,
                            result, result_len, result_max, previous_uuid);
 }
 
diff --git a/ks_flash.c b/ks_flash.c
index b14fc6a..300c7c4 100644
--- a/ks_flash.c
+++ b/ks_flash.c
@@ -61,6 +61,7 @@ typedef enum {
   BLOCK_TYPE_ERASED  = 0xFF, /* Pristine erased block (candidate for reuse) */
   BLOCK_TYPE_ZEROED  = 0x00, /* Zeroed block (recently used) */
   BLOCK_TYPE_KEY     = 0x55, /* Block contains key material */
+  BLOCK_TYPE_ATTR    = 0x66, /* Block contains key attributes (overflow from key block) */
   BLOCK_TYPE_PIN     = 0xAA, /* Block contains PINs */
   BLOCK_TYPE_UNKNOWN = -1,   /* Internal code for "I have no clue what this is" */
 } flash_block_type_t;
@@ -89,9 +90,7 @@ typedef struct {
 } flash_block_header_t;
 
 /*
- * We probably want some kind of TLV format for optional attributes
- * in key objects, and might want to put the DER key itself there to
- * save space.
+ * Key block.  Tail end of "der" field (after der_len) used for attributes.
  */
 
 typedef struct {
@@ -101,9 +100,27 @@ typedef struct {
   hal_curve_name_t      curve;
   hal_key_flags_t       flags;
   size_t                der_len;
-  uint8_t               der[HAL_KS_WRAPPED_KEYSIZE];
+  unsigned              attributes_len;
+  uint8_t               der[];  /* Must be last field -- C99 "flexible array member" */
 } flash_key_block_t;
 
+#define SIZEOF_FLASH_KEY_BLOCK_DER \
+  (KEYSTORE_SUBSECTOR_SIZE - offsetof(flash_key_block_t, der))
+
+/*
+ * Key attribute overflow block (attributes which don't fit in der field of key block).
+ */
+
+typedef struct {
+  flash_block_header_t  header;
+  hal_uuid_t            name;
+  unsigned              attributes_len;
+  uint8_t               attributes[]; /* Must be last field -- C99 "flexible array member" */
+} flash_attributes_block_t;
+
+#define SIZEOF_FLASH_ATTRIBUTE_BLOCK_ATTRIBUTES \
+  (KEYSTORE_SUBSECTOR_SIZE - offsetof(flash_attributes_block_t, attributes))
+
 /*
  * PIN block.  Also includes space for backing up the KEK when
  * HAL_MKM_FLASH_BACKUP_KLUDGE is enabled.
@@ -127,10 +144,11 @@ typedef struct {
  */
 
 typedef union {
-  uint8_t               bytes[KEYSTORE_SUBSECTOR_SIZE];
-  flash_block_header_t  header;
-  flash_key_block_t     key;
-  flash_pin_block_t     pin;
+  uint8_t                       bytes[KEYSTORE_SUBSECTOR_SIZE];
+  flash_block_header_t          header;
+  flash_key_block_t             key;
+  flash_attributes_block_t      attr;
+  flash_pin_block_t             pin;
 } flash_block_t;
 
 /*
@@ -326,6 +344,7 @@ static hal_error_t block_read(const unsigned blockno, flash_block_t *block)
     return HAL_OK;
   case BLOCK_TYPE_KEY:
   case BLOCK_TYPE_PIN:
+  case BLOCK_TYPE_ATTR:
     break;
   default:
     return HAL_ERROR_KEYSTORE_BAD_BLOCK_TYPE;
@@ -474,6 +493,7 @@ static hal_error_t block_write(const unsigned blockno, flash_block_t *block)
   switch (block_get_type(block)) {
   case BLOCK_TYPE_KEY:
   case BLOCK_TYPE_PIN:
+  case BLOCK_TYPE_ATTR:
     block->header.crc = calculate_block_crc(block);
     break;
   default:
@@ -562,10 +582,15 @@ static hal_error_t ks_init(const hal_ks_driver_t * const driver)
     else
       return err;
 
-    if (block_types[i] == BLOCK_TYPE_KEY || block_types[i] == BLOCK_TYPE_PIN)
+    switch (block_types[i]) {
+    case BLOCK_TYPE_KEY:
+    case BLOCK_TYPE_PIN:
+    case BLOCK_TYPE_ATTR:
       block_status[i] = block_get_status(block);
-    else
+      break;
+    default:
       block_status[i] = BLOCK_STATUS_UNKNOWN;
+    }
 
     /*
      * First erased block we see is head of the free list.
@@ -580,12 +605,20 @@ static hal_error_t ks_init(const hal_ks_driver_t * const driver)
      * in the index, so we can look them up by name if we must.
      */
 
-    if (block_types[i] == BLOCK_TYPE_KEY || block_types[i] == BLOCK_TYPE_PIN) {
-      db.ksi.names[i].name = block_types[i] == BLOCK_TYPE_KEY ? block->key.name : pin_uuid;
+    const hal_uuid_t *uuid = NULL;
+
+    switch (block_types[i]) {
+    case BLOCK_TYPE_KEY:        uuid = &block->key.name;        break;
+    case BLOCK_TYPE_ATTR:       uuid = &block->attr.name;       break;
+    case BLOCK_TYPE_PIN:        uuid = &pin_uuid;               break;
+    default:                    /* Keep GCC happy */            break;
+    }
+
+    if (uuid != NULL) {
+      db.ksi.names[i].name = *uuid;
       db.ksi.names[i].chunk = block->header.this_chunk;
       db.ksi.index[n++] = i;
     }
-
   }
 
   db.ksi.used = n;
@@ -873,7 +906,7 @@ static inline int acceptable_key_type(const hal_key_type_t type)
 }
 
 static hal_error_t ks_store(hal_ks_t *ks,
-                            const hal_pkey_slot_t * const slot,
+                            hal_pkey_slot_t *slot,
                             const uint8_t * const der, const size_t der_len)
 {
   if (ks != &db.ks || slot == NULL || der == NULL || der_len == 0 || !acceptable_key_type(slot->type))
@@ -905,7 +938,7 @@ static hal_error_t ks_store(hal_ks_t *ks,
   k->type    = slot->type;
   k->curve   = slot->curve;
   k->flags   = slot->flags;
-  k->der_len = sizeof(k->der);
+  k->der_len = SIZEOF_FLASH_KEY_BLOCK_DER;
 
   if ((err = hal_mkm_get_kek(kek, &kek_len, sizeof(kek))) == HAL_OK)
     err = hal_aes_keywrap(NULL, kek, kek_len, der, der_len, k->der, &k->der_len);
@@ -975,7 +1008,7 @@ static hal_error_t ks_fetch(hal_ks_t *ks,
 }
 
 static hal_error_t ks_delete(hal_ks_t *ks,
-                             const hal_pkey_slot_t * const slot)
+                             hal_pkey_slot_t *slot)
 {
   if (ks != &db.ks || slot == NULL)
     return HAL_ERROR_BAD_ARGUMENTS;
@@ -996,6 +1029,8 @@ static hal_error_t ks_delete(hal_ks_t *ks,
 }
 
 static hal_error_t ks_list(hal_ks_t *ks,
+                           const hal_client_handle_t client,
+                           const hal_session_handle_t session,
                            hal_pkey_info_t *result,
                            unsigned *result_len,
                            const unsigned result_max)
@@ -1032,6 +1067,8 @@ static hal_error_t ks_list(hal_ks_t *ks,
 }
 
 static hal_error_t ks_match(hal_ks_t *ks,
+                            const hal_client_handle_t client,
+                            const hal_session_handle_t session,
                             const hal_key_type_t type,
                             const hal_curve_name_t curve,
                             const hal_key_flags_t flags,
diff --git a/ks_volatile.c b/ks_volatile.c
index daaef41..35f1e38 100644
--- a/ks_volatile.c
+++ b/ks_volatile.c
@@ -52,6 +52,10 @@
 #define HAL_KS_VOLATILE_SLOTS HAL_STATIC_PKEY_STATE_BLOCKS
 #endif
 
+#ifndef HAL_KS_VOLATILE_ATTRIBUTE_SPACE
+#define HAL_KS_VOLATILE_ATTRIBUTE_SPACE 4096
+#endif
+
 /*
  * In-memory keystore database.  This should also be usable for
  * mmap(), if and when we get around to rewriting that driver (and in
@@ -62,8 +66,11 @@ typedef struct {
   hal_key_type_t        type;
   hal_curve_name_t      curve;
   hal_key_flags_t       flags;
+  hal_client_handle_t   client;
+  hal_session_handle_t  session;
   size_t                der_len;
-  uint8_t               der[HAL_KS_WRAPPED_KEYSIZE];
+  unsigned              attributes_len;
+  uint8_t               der[HAL_KS_WRAPPED_KEYSIZE + HAL_KS_VOLATILE_ATTRIBUTE_SPACE];
 } ks_key_t;
 
 typedef struct {
@@ -81,6 +88,7 @@ typedef struct {
 typedef struct {
   hal_ks_t ks;              /* Must be first */
   db_t *db;                 /* Which memory-based keystore database */
+  int per_session;          /* Whether objects are per-session */
 } ks_t;
 
 /*
@@ -109,6 +117,7 @@ static inline void *gnaw(uint8_t **mem, size_t *len, const size_t size)
 }
 
 static hal_error_t ks_init(const hal_ks_driver_t * const driver,
+                           const int per_session,
                            ks_t *ksv,
                            uint8_t *mem,
                            size_t len)
@@ -129,6 +138,7 @@ static hal_error_t ks_init(const hal_ks_driver_t * const driver,
     return HAL_ERROR_IMPOSSIBLE;
 
   ksv->ks.driver     = driver;
+  ksv->per_session   = per_session;
   ksv->db->ksi.size  = HAL_KS_VOLATILE_SLOTS;
   ksv->db->ksi.used  = 0;
 
@@ -156,7 +166,7 @@ static hal_error_t ks_volatile_init(const hal_ks_driver_t * const driver)
   if (mem == NULL)
     return HAL_ERROR_ALLOCATION_FAILURE;
 
-  return ks_init(driver, &volatile_ks, mem, len);
+  return ks_init(driver, 1, &volatile_ks, mem, len);
 }
 
 static hal_error_t ks_volatile_shutdown(const hal_ks_driver_t * const driver)
@@ -193,7 +203,7 @@ static inline int acceptable_key_type(const hal_key_type_t type)
 }
 
 static hal_error_t ks_store(hal_ks_t *ks,
-                            const hal_pkey_slot_t * const slot,
+                            hal_pkey_slot_t *slot,
                             const uint8_t * const der, const size_t der_len)
 {
   if (ks == NULL || slot == NULL || der == NULL || der_len == 0 || !acceptable_key_type(slot->type))
@@ -206,7 +216,7 @@ static hal_error_t ks_store(hal_ks_t *ks,
   if (ksv->db == NULL)
     return HAL_ERROR_KEYSTORE_ACCESS;
 
-  if ((err = hal_ks_index_add(&ksv->db->ksi, &slot->name, 0, &b, NULL)) != HAL_OK)
+  if ((err = hal_ks_index_add(&ksv->db->ksi, &slot->name, 0, &b, &slot->hint)) != HAL_OK)
     return err;
 
   uint8_t kek[KEK_LENGTH];
@@ -219,6 +229,11 @@ static hal_error_t ks_store(hal_ks_t *ks,
   k.curve   = slot->curve;
   k.flags   = slot->flags;
 
+  if (ksv->per_session) {
+    k.client  = slot->client_handle;
+    k.session = slot->session_handle;
+  }
+
   if ((err = hal_mkm_get_kek(kek, &kek_len, sizeof(kek))) == HAL_OK)
     err = hal_aes_keywrap(NULL, kek, kek_len, der, der_len, k.der, &k.der_len);
 
@@ -227,7 +242,7 @@ static hal_error_t ks_store(hal_ks_t *ks,
   if (err == HAL_OK)
     ksv->db->keys[b] = k;
   else
-    (void) hal_ks_index_delete(&ksv->db->ksi, &slot->name, 0, NULL, NULL);
+    (void) hal_ks_index_delete(&ksv->db->ksi, &slot->name, 0, NULL, &slot->hint);
 
   return err;
 }
@@ -246,11 +261,15 @@ static hal_error_t ks_fetch(hal_ks_t *ks,
   if (ksv->db == NULL)
     return HAL_ERROR_KEYSTORE_ACCESS;
 
-  if ((err = hal_ks_index_find(&ksv->db->ksi, &slot->name, 0, &b, NULL)) != HAL_OK)
+  if ((err = hal_ks_index_find(&ksv->db->ksi, &slot->name, 0, &b, &slot->hint)) != HAL_OK)
     return err;
 
   const ks_key_t * const k = &ksv->db->keys[b];
 
+  if (ksv->per_session && (k->client.handle  != slot->client_handle.handle ||
+                           k->session.handle != slot->session_handle.handle))
+    return HAL_ERROR_KEY_NOT_FOUND;
+
   slot->type  = k->type;
   slot->curve = k->curve;
   slot->flags = k->flags;
@@ -282,7 +301,7 @@ static hal_error_t ks_fetch(hal_ks_t *ks,
 }
 
 static hal_error_t ks_delete(hal_ks_t *ks,
-                             const hal_pkey_slot_t * const slot)
+                             hal_pkey_slot_t *slot)
 {
   if (ks == NULL || slot == NULL)
     return HAL_ERROR_BAD_ARGUMENTS;
@@ -294,7 +313,14 @@ static hal_error_t ks_delete(hal_ks_t *ks,
   if (ksv->db == NULL)
     return HAL_ERROR_KEYSTORE_ACCESS;
 
-  if ((err = hal_ks_index_delete(&ksv->db->ksi, &slot->name, 0, &b, NULL)) != HAL_OK)
+  if ((err = hal_ks_index_find(&ksv->db->ksi, &slot->name, 0, &b, &slot->hint)) != HAL_OK)
+    return err;
+
+  if (ksv->per_session && (ksv->db->keys[b].client.handle  != slot->client_handle.handle ||
+                           ksv->db->keys[b].session.handle != slot->session_handle.handle))
+    return HAL_ERROR_KEY_NOT_FOUND;
+
+  if ((err = hal_ks_index_delete(&ksv->db->ksi, &slot->name, 0, &b, &slot->hint)) != HAL_OK)
     return err;
 
   memset(&ksv->db->keys[b], 0, sizeof(ksv->db->keys[b]));
@@ -303,6 +329,8 @@ static hal_error_t ks_delete(hal_ks_t *ks,
 }
 
 static hal_error_t ks_list(hal_ks_t *ks,
+                           hal_client_handle_t client,
+                           hal_session_handle_t session,
                            hal_pkey_info_t *result,
                            unsigned *result_len,
                            const unsigned result_max)
@@ -322,6 +350,9 @@ static hal_error_t ks_list(hal_ks_t *ks,
     unsigned b = ksv->db->ksi.index[i];
     if (ksv->db->ksi.names[b].chunk > 0)
       continue;
+    if (ksv->per_session && (ksv->db->keys[b].client.handle  != client.handle ||
+                             ksv->db->keys[b].session.handle != session.handle))
+      continue;
     result[i].name  = ksv->db->ksi.names[b].name;
     result[i].type  = ksv->db->keys[b].type;
     result[i].curve = ksv->db->keys[b].curve;
@@ -334,6 +365,8 @@ static hal_error_t ks_list(hal_ks_t *ks,
 }
 
 static hal_error_t ks_match(hal_ks_t *ks,
+                            hal_client_handle_t client,
+                            hal_session_handle_t session,
                             const hal_key_type_t type,
                             const hal_curve_name_t curve,
                             const hal_key_flags_t flags,
@@ -344,8 +377,77 @@ static hal_error_t ks_match(hal_ks_t *ks,
                             const unsigned result_max,
                             hal_uuid_t *previous_uuid)
 {
-#warning NIY
-  return HAL_ERROR_IMPOSSIBLE;
+  if (ks == NULL || attributes == NULL ||
+      result == NULL || result_len == NULL || previous_uuid == NULL)
+    return HAL_ERROR_BAD_ARGUMENTS;
+
+  ks_t *ksv = ks_to_ksv(ks);
+
+  if (ksv->db == NULL)
+    return HAL_ERROR_KEYSTORE_ACCESS;
+
+  hal_error_t err;
+  int i = -1;
+
+  *result_len = 0;
+
+  if ((err = hal_ks_index_find(&ksv->db->ksi, previous_uuid, 0, NULL, &i)) != HAL_OK)
+    return err;
+
+  while (*result_len < result_max) {
+
+    if (++i >= ksv->db->ksi.used)
+      return HAL_OK;
+
+    unsigned b = ksv->db->ksi.index[i];
+
+    if (ksv->db->ksi.names[b].chunk > 0)
+      continue;
+
+    if (type != HAL_KEY_TYPE_NONE && type != ksv->db->keys[b].type)
+      continue;
+
+    if (curve != HAL_CURVE_NONE && curve != ksv->db->keys[b].curve)
+      continue;
+
+    if (ksv->per_session && (ksv->db->keys[b].client.handle  != client.handle ||
+                             ksv->db->keys[b].session.handle != session.handle))
+      continue;
+
+    if (attributes_len > 0) {
+      const ks_key_t * const k = &ksv->db->keys[b];
+      int ok = 1;
+
+      if (k->attributes_len == 0)
+        continue;
+
+      hal_rpc_pkey_attribute_t key_attrs[k->attributes_len];
+
+      if ((err = hal_ks_attribute_scan(k->der + k->der_len, sizeof(k->der) - k->der_len,
+                                       key_attrs, k->attributes_len, NULL)) != HAL_OK)
+        return err;
+
+      for (hal_rpc_pkey_attribute_t *required = attributes;
+           ok && required < attributes + attributes_len; required++) {
+
+        hal_rpc_pkey_attribute_t *present = key_attrs;
+        while (ok && present->type != required->type)
+          ok = ++present < key_attrs + k->attributes_len;
+
+        if (ok)
+          ok = (present->length == required->length &&
+                !memcmp(present->value, required->value, present->length));
+      }
+
+      if (!ok)
+        continue;
+    }
+
+    result[*result_len] = ksv->db->ksi.names[b].name;
+    ++*result_len;
+  }
+
+  return HAL_ERROR_RESULT_TOO_LONG;
 }
 
 static  hal_error_t ks_set_attribute(hal_ks_t *ks,
@@ -354,8 +456,37 @@ static  hal_error_t ks_set_attribute(hal_ks_t *ks,
                                      const uint8_t * const value,
                                      const size_t value_len)
 {
-#warning NIY
-  return HAL_ERROR_IMPOSSIBLE;
+  if (ks == NULL || slot == NULL)
+    return HAL_ERROR_BAD_ARGUMENTS;
+
+  ks_t *ksv = ks_to_ksv(ks);
+  hal_error_t err;
+  unsigned b;
+
+  if (ksv->db == NULL)
+    return HAL_ERROR_KEYSTORE_ACCESS;
+
+  if ((err = hal_ks_index_find(&ksv->db->ksi, &slot->name, 0, &b, &slot->hint)) != HAL_OK)
+    return err;
+
+  ks_key_t * const k = &ksv->db->keys[b];
+
+  if (ksv->per_session && (k->client.handle  != slot->client_handle.handle ||
+                           k->session.handle != slot->session_handle.handle))
+    return HAL_ERROR_KEY_NOT_FOUND;
+
+  hal_rpc_pkey_attribute_t attributes[k->attributes_len + 1];
+  uint8_t *bytes = k->der + k->der_len;
+  size_t bytes_len = sizeof(k->der) - k->der_len;
+  size_t total_len;
+
+  err = hal_ks_attribute_scan(bytes, bytes_len, attributes, k->attributes_len, &total_len);
+
+  if (err != HAL_OK)
+    return err;
+
+  return hal_ks_attribute_insert(bytes, bytes_len, attributes, &k->attributes_len, &total_len,
+                                 type, value, value_len);
 }
 
 static  hal_error_t ks_get_attribute(hal_ks_t *ks,
@@ -365,16 +496,86 @@ static  hal_error_t ks_get_attribute(hal_ks_t *ks,
                                      size_t *value_len,
                                      const size_t value_max)
 {
-#warning NIY
-  return HAL_ERROR_IMPOSSIBLE;
+  if (ks == NULL || slot == NULL)
+    return HAL_ERROR_BAD_ARGUMENTS;
+
+  ks_t *ksv = ks_to_ksv(ks);
+  hal_error_t err;
+  unsigned b;
+
+  if (ksv->db == NULL)
+    return HAL_ERROR_KEYSTORE_ACCESS;
+
+  if ((err = hal_ks_index_find(&ksv->db->ksi, &slot->name, 0, &b, &slot->hint)) != HAL_OK)
+    return err;
+
+  const ks_key_t * const k = &ksv->db->keys[b];
+
+  if (ksv->per_session && (k->client.handle  != slot->client_handle.handle ||
+                           k->session.handle != slot->session_handle.handle))
+    return HAL_ERROR_KEY_NOT_FOUND;
+
+  if (k->attributes_len == 0)
+    return HAL_ERROR_ATTRIBUTE_NOT_FOUND;
+
+  hal_rpc_pkey_attribute_t attributes[k->attributes_len];
+
+  if ((err = hal_ks_attribute_scan(k->der + k->der_len, sizeof(k->der) - k->der_len,
+                                   attributes, k->attributes_len, NULL)) != HAL_OK)
+    return err;
+
+  int i = 0;
+
+  while (attributes[i].type != type)
+    if (++i >= k->attributes_len)
+      return HAL_ERROR_ATTRIBUTE_NOT_FOUND;
+
+  if (attributes[i].length > value_max && value != NULL)
+    return HAL_ERROR_RESULT_TOO_LONG;
+
+  if (value != NULL)
+    memcpy(value, attributes[i].value, attributes[i].length);
+
+  if (value_len != NULL)
+    *value_len = attributes[i].length;
+
+  return HAL_OK;
 }
 
 static hal_error_t ks_delete_attribute(hal_ks_t *ks,
                                        hal_pkey_slot_t *slot,
                                        const uint32_t type)
 {
-#warning NIY
-  return HAL_ERROR_IMPOSSIBLE;
+  if (ks == NULL || slot == NULL)
+    return HAL_ERROR_BAD_ARGUMENTS;
+
+  ks_t *ksv = ks_to_ksv(ks);
+  hal_error_t err;
+  unsigned b;
+
+  if (ksv->db == NULL)
+    return HAL_ERROR_KEYSTORE_ACCESS;
+
+  if ((err = hal_ks_index_find(&ksv->db->ksi, &slot->name, 0, &b, &slot->hint)) != HAL_OK)
+    return err;
+
+  ks_key_t * const k = &ksv->db->keys[b];
+
+  if (ksv->per_session && (k->client.handle  != slot->client_handle.handle ||
+                           k->session.handle != slot->session_handle.handle))
+    return HAL_ERROR_KEY_NOT_FOUND;
+
+  hal_rpc_pkey_attribute_t attributes[k->attributes_len + 1];
+  uint8_t *bytes = k->der + k->der_len;
+  size_t bytes_len = sizeof(k->der) - k->der_len;
+  size_t total_len;
+
+  err = hal_ks_attribute_scan(bytes, bytes_len, attributes, k->attributes_len, &total_len);
+
+  if (err != HAL_OK)
+    return err;
+
+  return hal_ks_attribute_delete(bytes, bytes_len, attributes, &k->attributes_len, &total_len, type);
 }
 
 const hal_ks_driver_t hal_ks_volatile_driver[1] = {{
diff --git a/rpc_api.c b/rpc_api.c
index f7b04cc..3ff814a 100644
--- a/rpc_api.c
+++ b/rpc_api.c
@@ -326,7 +326,8 @@ hal_error_t hal_rpc_pkey_verify(const hal_pkey_handle_t pkey,
   return hal_rpc_pkey_dispatch->verify(pkey, hash, input, input_len, signature, signature_len);
 }
 
-hal_error_t hal_rpc_pkey_list(const hal_session_handle_t session,
+hal_error_t hal_rpc_pkey_list(const hal_client_handle_t client,
+                              const hal_session_handle_t session,
                               hal_pkey_info_t *result,
                               unsigned *result_len,
                               const unsigned result_max,
@@ -334,10 +335,11 @@ hal_error_t hal_rpc_pkey_list(const hal_session_handle_t session,
 {
   if (result == NULL || result_len == NULL || result_max == 0)
     return HAL_ERROR_BAD_ARGUMENTS;
-  return hal_rpc_pkey_dispatch->list(session, result, result_len, result_max, flags);
+  return hal_rpc_pkey_dispatch->list(client, session, result, result_len, result_max, flags);
 }
 
-hal_error_t hal_rpc_pkey_match(const hal_session_handle_t session,
+hal_error_t hal_rpc_pkey_match(const hal_client_handle_t client,
+                               const hal_session_handle_t session,
                                const hal_key_type_t type,
                                const hal_curve_name_t curve,
                                const hal_key_flags_t flags,
@@ -357,7 +359,8 @@ hal_error_t hal_rpc_pkey_match(const hal_session_handle_t session,
       if (attributes[i].value == NULL)
         return HAL_ERROR_BAD_ARGUMENTS;
 
-  return hal_rpc_pkey_dispatch->match(session, type, curve, flags, attributes, attributes_len,
+  return hal_rpc_pkey_dispatch->match(client, session, type, curve, flags,
+                                      attributes, attributes_len,
                                       result, result_len, result_max, previous_uuid);
 }
 
diff --git a/rpc_client.c b/rpc_client.c
index 78e2f16..6eaa465 100644
--- a/rpc_client.c
+++ b/rpc_client.c
@@ -753,7 +753,8 @@ static hal_error_t hal_xdr_decode_pkey_info(const uint8_t **iptr, const uint8_t
   return HAL_OK;
 }
 
-static hal_error_t pkey_remote_list(const hal_session_handle_t session,
+static hal_error_t pkey_remote_list(const hal_client_handle_t client,
+                                    const hal_session_handle_t session,
                                     hal_pkey_info_t *result,
                                     unsigned *result_len,
                                     const unsigned result_max,
@@ -763,11 +764,10 @@ static hal_error_t pkey_remote_list(const hal_session_handle_t session,
   uint8_t inbuf[nargs(4) + pad(result_max * sizeof(hal_pkey_info_t))];
   const uint8_t *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf);
   uint32_t len;
-  hal_client_handle_t dummy_client = {0};
   hal_error_t ret, rpc_ret;
 
   check(hal_xdr_encode_int(&optr, olimit, RPC_FUNC_PKEY_LIST));
-  check(hal_xdr_encode_int(&optr, olimit, dummy_client.handle));
+  check(hal_xdr_encode_int(&optr, olimit, client.handle));
   check(hal_xdr_encode_int(&optr, olimit, session.handle));
   check(hal_xdr_encode_int(&optr, olimit, result_max));
   check(hal_xdr_encode_int(&optr, olimit, flags));
@@ -789,7 +789,8 @@ static hal_error_t pkey_remote_list(const hal_session_handle_t session,
   return rpc_ret;
 }
 
-static hal_error_t pkey_remote_match(const hal_session_handle_t session,
+static hal_error_t pkey_remote_match(const hal_client_handle_t client,
+                                     const hal_session_handle_t session,
                                      const hal_key_type_t type,
                                      const hal_curve_name_t curve,
                                      const hal_key_flags_t flags,
@@ -809,11 +810,10 @@ static hal_error_t pkey_remote_match(const hal_session_handle_t session,
   uint8_t *optr = outbuf, *olimit = outbuf + sizeof(outbuf);
   uint8_t inbuf[nargs(5) + pad(result_max * sizeof(hal_uuid_t)) + pad(sizeof(hal_uuid_t))];
   const uint8_t *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf);
-  hal_client_handle_t dummy_client = {0};
   hal_error_t rpc_ret;
 
   check(hal_xdr_encode_int(&optr, olimit, RPC_FUNC_PKEY_MATCH));
-  check(hal_xdr_encode_int(&optr, olimit, dummy_client.handle));
+  check(hal_xdr_encode_int(&optr, olimit, client.handle));
   check(hal_xdr_encode_int(&optr, olimit, session.handle));
   check(hal_xdr_encode_int(&optr, olimit, type));
   check(hal_xdr_encode_int(&optr, olimit, curve));
diff --git a/rpc_pkey.c b/rpc_pkey.c
index 22ad197..0a53221 100644
--- a/rpc_pkey.c
+++ b/rpc_pkey.c
@@ -55,7 +55,7 @@ static hal_pkey_slot_t pkey_handle[HAL_STATIC_PKEY_STATE_BLOCKS];
  * soon, to help identify use-after-free bugs in calling code.
  *
  * The high order bit of the pkey handle is left free for
- * HAL_PKEY_HANDLE_PROXIMATE_FLAG, which is used by the mixed-mode
+ * HAL_PKEY_HANDLE_TOKEN_FLAG, which is used by the mixed-mode
  * handlers to route calls to the appropriate destination.
  */
 
@@ -76,6 +76,7 @@ static inline hal_pkey_slot_t *alloc_slot(const hal_key_flags_t flags)
       continue;
     memset(&pkey_handle[i], 0, sizeof(pkey_handle[i]));
     pkey_handle[i].pkey_handle.handle = i | glop;
+    pkey_handle[i].hint = -1;
     return &pkey_handle[i];
   }
 #endif
@@ -848,7 +849,8 @@ static hal_error_t pkey_local_verify(const hal_pkey_handle_t pkey,
  * List keys in the key store.
  */
 
-static hal_error_t pkey_local_list(const hal_session_handle_t session,
+static hal_error_t pkey_local_list(const hal_client_handle_t client,
+                                   const hal_session_handle_t session,
                                    hal_pkey_info_t *result,
                                    unsigned *result_len,
                                    const unsigned result_max,
@@ -858,7 +860,7 @@ static hal_error_t pkey_local_list(const hal_session_handle_t session,
   hal_error_t err;
 
   if ((err = ks_open_from_flags(&ks, flags)) == HAL_OK &&
-      (err = hal_ks_list(ks, session, result, result_len, result_max)) == HAL_OK)
+      (err = hal_ks_list(ks, client, session, result, result_len, result_max)) == HAL_OK)
     err = hal_ks_close(ks);
   else if (ks != NULL)
     (void) hal_ks_close(ks);
@@ -866,7 +868,8 @@ static hal_error_t pkey_local_list(const hal_session_handle_t session,
   return err;
 }
 
-static hal_error_t pkey_local_match(const hal_session_handle_t session,
+static hal_error_t pkey_local_match(const hal_client_handle_t client,
+                                    const hal_session_handle_t session,
                                     const hal_key_type_t type,
                                     const hal_curve_name_t curve,
                                     const hal_key_flags_t flags,
@@ -881,7 +884,7 @@ static hal_error_t pkey_local_match(const hal_session_handle_t session,
   hal_error_t err;
 
   if ((err = ks_open_from_flags(&ks, flags)) == HAL_OK &&
-      (err = hal_ks_match(ks, session, type, curve, flags, attributes, attributes_len,
+      (err = hal_ks_match(ks, client, session, type, curve, flags, attributes, attributes_len,
                           result, result_len, result_max, previous_uuid)) == HAL_OK)
     err = hal_ks_close(ks);
   else if (ks != NULL)
diff --git a/rpc_server.c b/rpc_server.c
index e4fde9f..d9e640a 100644
--- a/rpc_server.c
+++ b/rpc_server.c
@@ -650,7 +650,7 @@ static hal_error_t pkey_list(const uint8_t **iptr, const uint8_t * const ilimit,
     unsigned result_len;
 
     /* call the local function */
-    ret = hal_rpc_local_pkey_dispatch.list(session, result, &result_len, result_max, flags);
+    ret = hal_rpc_local_pkey_dispatch.list(client, session, result, &result_len, result_max, flags);
 
     if (ret == HAL_OK) {
         check(hal_xdr_encode_int(optr, olimit, result_len));
@@ -701,7 +701,7 @@ static hal_error_t pkey_match(const uint8_t **iptr, const uint8_t * const ilimit
     hal_uuid_t result[result_max];
     unsigned result_len;
 
-    ret = hal_rpc_local_pkey_dispatch.match(session, type, curve, flags,
+    ret = hal_rpc_local_pkey_dispatch.match(client, session, type, curve, flags,
                                             attributes, attributes_len,
                                             result, &result_len, result_max,
                                             (hal_uuid_t *) previous_uuid_ptr);



More information about the Commits mailing list