[Cryptech-Commits] [sw/libhal] 01/02: Clean out huge swacks of RPC API we don't need anymore.

git at cryptech.is git at cryptech.is
Sat Nov 12 04:36:44 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 2ff032823f6acf0cc409c0e541041ebe1f0dbc75
Author: Rob Austein <sra at hactrn.net>
AuthorDate: Thu Nov 10 21:44:22 2016 -0500

    Clean out huge swacks of RPC API we don't need anymore.
    
    pkey attribute API is now just set_attributes() and get_attributes().
---
 hal.h                 |  18 ---
 hal_internal.h        | 110 +----------------
 ks_flash.c            | 332 +-------------------------------------------------
 ks_index.c            |   5 +-
 ks_volatile.c         | 182 ++-------------------------
 libhal.py             |  33 -----
 rpc_api.c             |  36 ------
 rpc_client.c          | 113 +----------------
 rpc_pkey.c            | 101 +--------------
 rpc_server.c          | 105 ----------------
 tests/test-rpc_pkey.c |  26 ++--
 unit-tests.py         | 171 +++++++-------------------
 12 files changed, 86 insertions(+), 1146 deletions(-)

diff --git a/hal.h b/hal.h
index 59018ea..a90c608 100644
--- a/hal.h
+++ b/hal.h
@@ -792,20 +792,6 @@ extern hal_error_t hal_rpc_pkey_match(const hal_client_handle_t client,
                                       const unsigned result_max,
                                       const hal_uuid_t * const previous_uuid);
 
-extern hal_error_t hal_rpc_pkey_set_attribute(const hal_pkey_handle_t pkey,
-                                              const uint32_t type,
-                                              const uint8_t * const value,
-                                              const size_t value_len);
-
-extern hal_error_t hal_rpc_pkey_get_attribute(const hal_pkey_handle_t pkey,
-                                              const uint32_t type,
-                                              uint8_t *value,
-                                              size_t *value_len,
-                                              const size_t value_max);
-
-extern hal_error_t hal_rpc_pkey_delete_attribute(const hal_pkey_handle_t pkey,
-                                                 const uint32_t type);
-
 extern hal_error_t hal_rpc_pkey_set_attributes(const hal_pkey_handle_t pkey,
                                                const hal_rpc_pkey_attribute_t *const attributes,
                                                const unsigned attributes_len);
@@ -816,10 +802,6 @@ extern hal_error_t hal_rpc_pkey_get_attributes(const hal_pkey_handle_t pkey,
                                                uint8_t *attributes_buffer,
                                                const size_t attributes_buffer_len);
 
-extern hal_error_t hal_rpc_pkey_delete_attributes(const hal_pkey_handle_t pkey,
-                                                  const uint32_t * const types,
-                                                  const unsigned types_len);
-
 extern hal_error_t hal_rpc_client_init(void);
 
 extern hal_error_t hal_rpc_client_close(void);
diff --git a/hal_internal.h b/hal_internal.h
index 554ca62..dc00568 100644
--- a/hal_internal.h
+++ b/hal_internal.h
@@ -257,21 +257,6 @@ typedef struct {
                        const unsigned result_max,
                        const hal_uuid_t * const previous_uuid);
 
-  hal_error_t (*set_attribute)(const hal_pkey_handle_t pkey,
-                               const uint32_t type,
-                               const uint8_t * const value,
-                               const size_t value_len);
-
-  hal_error_t (*get_attribute)(const hal_pkey_handle_t pkey,
-                               const uint32_t type,
-                               uint8_t *value,
-                               size_t *value_len,
-                               const size_t value_max);
-
-  hal_error_t (*delete_attribute)(const hal_pkey_handle_t pkey,
-                                  const uint32_t type);
-
-
   hal_error_t (*set_attributes)(const hal_pkey_handle_t pkey,
                                 const hal_rpc_pkey_attribute_t *attributes,
                                 const unsigned attributes_len);
@@ -282,10 +267,6 @@ typedef struct {
                                 uint8_t *attributes_buffer,
                                 const size_t attributes_buffer_len);
 
-  hal_error_t (*delete_attributes)(const hal_pkey_handle_t pkey,
-                                   const uint32_t *types,
-                                   const unsigned types_len);
-
 } hal_rpc_pkey_dispatch_t;
 
 
@@ -519,23 +500,6 @@ struct hal_ks_driver {
                        const unsigned result_max,
                        const hal_uuid_t * const previous_uuid);
 
-  hal_error_t (*set_attribute)(hal_ks_t *ks,
-                               hal_pkey_slot_t *slot,
-                               const uint32_t type,
-                               const uint8_t * const value,
-                               const size_t value_len);
-
-  hal_error_t (*get_attribute)(hal_ks_t *ks,
-                               hal_pkey_slot_t *slot,
-                               const uint32_t type,
-                               uint8_t *value,
-                               size_t *value_len,
-                               const size_t value_max);
-
-  hal_error_t (*delete_attribute)(hal_ks_t *ks,
-                                  hal_pkey_slot_t *slot,
-                                  const uint32_t type);
-
   hal_error_t (*set_attributes)(hal_ks_t *ks,
                                 hal_pkey_slot_t *slot,
                                 const hal_rpc_pkey_attribute_t *attributes,
@@ -548,11 +512,6 @@ struct hal_ks_driver {
                                 uint8_t *attributes_buffer,
                                 const size_t attributes_buffer_len);
 
-  hal_error_t (*delete_attributes)(hal_ks_t *ks,
-                                   hal_pkey_slot_t *slot,
-                                   const uint32_t *types,
-                                   const unsigned types_len);
-
 };
 
 
@@ -695,50 +654,6 @@ static inline hal_error_t hal_ks_match(hal_ks_t *ks,
                            result, result_len, result_max, previous_uuid);
 }
 
-static inline  hal_error_t hal_ks_set_attribute(hal_ks_t *ks,
-                                                hal_pkey_slot_t *slot,
-                                                const uint32_t type,
-                                                const uint8_t * const value,
-                                                const size_t value_len)
-{
-  if (ks == NULL || ks->driver == NULL || slot == NULL)
-    return HAL_ERROR_BAD_ARGUMENTS;
-
-  if (ks->driver->set_attribute == NULL)
-    return HAL_ERROR_NOT_IMPLEMENTED;
-
-  return ks->driver->set_attribute(ks, slot, type, value, value_len);
-}
-
-static inline hal_error_t hal_ks_get_attribute(hal_ks_t *ks,
-                                               hal_pkey_slot_t *slot,
-                                               const uint32_t type,
-                                               uint8_t *value,
-                                               size_t *value_len,
-                                               const size_t value_max)
-{
-  if (ks == NULL || ks->driver == NULL || slot == NULL)
-    return HAL_ERROR_BAD_ARGUMENTS;
-
-  if (ks->driver->get_attribute == NULL)
-    return HAL_ERROR_NOT_IMPLEMENTED;
-
-  return ks->driver->get_attribute(ks, slot, type, value, value_len, value_max);
-}
-
-static inline hal_error_t hal_ks_delete_attribute(hal_ks_t *ks,
-                                                  hal_pkey_slot_t *slot,
-                                                  const uint32_t type)
-{
-  if (ks == NULL || ks->driver == NULL || slot == NULL)
-    return HAL_ERROR_BAD_ARGUMENTS;
-
-  if (ks->driver->delete_attribute == NULL)
-    return HAL_ERROR_NOT_IMPLEMENTED;
-
-  return ks->driver->delete_attribute(ks, slot, type);
-}
-
 static inline  hal_error_t hal_ks_set_attributes(hal_ks_t *ks,
                                                  hal_pkey_slot_t *slot,
                                                  const hal_rpc_pkey_attribute_t *attributes,
@@ -777,21 +692,6 @@ static inline hal_error_t hal_ks_get_attributes(hal_ks_t *ks,
                                     attributes_buffer, attributes_buffer_len);
 }
 
-static inline hal_error_t hal_ks_delete_attributes(hal_ks_t *ks,
-                                                   hal_pkey_slot_t *slot,
-                                                   const uint32_t *types,
-                                                   const unsigned types_len)
-{
-  if (ks == NULL || ks->driver == NULL || slot == NULL ||
-      types == NULL || types_len == 0)
-    return HAL_ERROR_BAD_ARGUMENTS;
-
-  if (ks->driver->delete_attributes == NULL)
-    return HAL_ERROR_NOT_IMPLEMENTED;
-
-  return ks->driver->delete_attributes(ks, slot, types, types_len);
-}
-
 /*
  * Keystore index.  This is intended to be usable by both memory-based
  * (in-memory, mmap(), ...) keystores and keystores based on raw flash.
@@ -872,7 +772,8 @@ extern hal_error_t hal_ks_index_find_range(hal_ks_index_t *ksi,
                                            const unsigned max_blocks,
                                            unsigned *n_blocks,
                                            unsigned *blocknos,
-                                           int *hint);
+                                           int *hint,
+                                           const int strict);
 
 /*
  * Add a key block, return its block number.
@@ -972,7 +873,7 @@ extern hal_error_t hal_rpc_server_transport_close(void);
  */
 
 typedef enum {
-    RPC_FUNC_GET_VERSION = 0,
+    RPC_FUNC_GET_VERSION,
     RPC_FUNC_GET_RANDOM,
     RPC_FUNC_SET_PIN,
     RPC_FUNC_LOGIN,
@@ -998,15 +899,10 @@ typedef enum {
     RPC_FUNC_PKEY_SIGN,
     RPC_FUNC_PKEY_VERIFY,
     RPC_FUNC_PKEY_LIST,
-    RPC_FUNC_PKEY_RENAME,
     RPC_FUNC_PKEY_MATCH,
-    RPC_FUNC_PKEY_SET_ATTRIBUTE,
-    RPC_FUNC_PKEY_GET_ATTRIBUTE,
-    RPC_FUNC_PKEY_DELETE_ATTRIBUTE,
     RPC_FUNC_PKEY_GET_KEY_CURVE,
     RPC_FUNC_PKEY_SET_ATTRIBUTES,
     RPC_FUNC_PKEY_GET_ATTRIBUTES,
-    RPC_FUNC_PKEY_DELETE_ATTRIBUTES,
 } rpc_func_num_t;
 
 #define RPC_VERSION 0x01010000          /* 1.1.0.0 */
diff --git a/ks_flash.c b/ks_flash.c
index 0d8542e..957ded3 100644
--- a/ks_flash.c
+++ b/ks_flash.c
@@ -753,7 +753,7 @@ static hal_error_t ks_init(const hal_ks_driver_t * const driver)
     unsigned n_blocks;
     int where = -1;
 
-    if ((err = hal_ks_index_find_range(&db.ksi, &name, 0, &n_blocks, NULL, &where)) != HAL_OK)
+    if ((err = hal_ks_index_find_range(&db.ksi, &name, 0, &n_blocks, NULL, &where, 0)) != HAL_OK)
       return err;
 
     while (where > 0 && !hal_uuid_cmp(&name, &db.ksi.names[db.ksi.index[where - 1]].name)) {
@@ -1250,300 +1250,6 @@ static hal_error_t ks_match(hal_ks_t *ks,
   return HAL_OK;
 }
 
-static  hal_error_t ks_set_attribute(hal_ks_t *ks,
-                                     hal_pkey_slot_t *slot,
-                                     const uint32_t type,
-                                     const uint8_t * const value,
-                                     const size_t value_len)
-{
-  if (ks != &db.ks || slot == NULL)
-    return HAL_ERROR_BAD_ARGUMENTS;
-
-  /*
-   * Try to add new attribute as a single-block update.
-   */
-
-  flash_block_t *block;
-  unsigned chunk = 0;
-  hal_error_t err;
-
-  do {
-    int hint = slot->hint + chunk;
-    unsigned b;
-
-    if ((err = hal_ks_index_find(&db.ksi, &slot->name, chunk, &b, &hint)) != HAL_OK ||
-        (err = block_read_cached(b, &block))                              != HAL_OK)
-      return err;
-
-    if (block->header.this_chunk != chunk)
-      return HAL_ERROR_IMPOSSIBLE;
-
-    if (chunk == 0)
-      slot->hint = hint;
-
-    uint8_t *bytes = NULL;
-    size_t bytes_len = 0;
-    unsigned *attrs_len;
-
-    if ((err = locate_attributes(block, chunk, &bytes, &bytes_len, &attrs_len)) != HAL_OK)
-      return err;
-
-    cache_mark_used(block, b);
-
-    hal_rpc_pkey_attribute_t attrs[*attrs_len + 1];
-    const unsigned old_attrs_len = *attrs_len;
-    size_t total;
-
-    if ((err = hal_ks_attribute_scan(bytes, bytes_len, attrs, *attrs_len, &total)) != HAL_OK)
-      return err;
-
-    err = hal_ks_attribute_insert(bytes, bytes_len, attrs, attrs_len, &total, type, value, value_len);
-
-    if (*attrs_len != old_attrs_len && err != HAL_OK)
-      cache_release(block);
-
-    if (err == HAL_ERROR_RESULT_TOO_LONG)
-      continue;
-
-    if (err != HAL_OK)
-      return err;
-
-    return block_update(b, block, &slot->name, chunk, &hint);
-
-  } while (++chunk < block->header.total_chunks);
-
-  /*
-   * If we get here, we have to add a new block, which requires
-   * rewriting all the others to bump the total_blocks count.  We need
-   * to keep track of all the old chunks so we can zero them at the
-   * end, and because we can't zero them until we've written out the
-   * new chunks, we need enough free blocks for the entire new object.
-   */
-
-  const unsigned total_chunks = block->header.total_chunks;
-  unsigned b, blocks[total_chunks];
-
-  if (db.ksi.used + total_chunks + 1 > db.ksi.size)
-    return HAL_ERROR_NO_KEY_INDEX_SLOTS;
-
-  /*
-   * Phase 1: Deprecate all the old chunks, remember where the were.
-   */
-
-  for (chunk = 0; chunk < total_chunks; chunk++) {
-    int hint = slot->hint + chunk;
-    if ((err = hal_ks_index_find(&db.ksi, &slot->name, chunk, &blocks[chunk], &hint)) != HAL_OK ||
-        (err = block_deprecate(blocks[chunk]))                                        != HAL_OK)
-      return err;
-  }
-
-  /*
-   * Phase 2: Rewrite all the existing chunks with the new total_chunks value.
-   */
-
-  for (chunk = 0; chunk < total_chunks; chunk++) {
-    int hint = slot->hint + chunk;
-    if ((err = block_read_cached(blocks[chunk], &block)) != HAL_OK)
-      return err;
-    if (block->header.this_chunk != chunk)
-      return HAL_ERROR_IMPOSSIBLE;
-    block->header.block_status = BLOCK_STATUS_LIVE;
-    block->header.total_chunks = total_chunks + 1;
-
-    uint8_t *bytes = NULL;
-    size_t bytes_len = 0;
-    unsigned *attrs_len;
-    size_t total;
-
-    if ((err = locate_attributes(block, chunk, &bytes, &bytes_len, &attrs_len)) != HAL_OK)
-      return err;
-
-    if (*attrs_len > 0) {
-      hal_rpc_pkey_attribute_t attrs[*attrs_len];
-      if ((err = hal_ks_attribute_scan(bytes, bytes_len, attrs, *attrs_len, &total)) != HAL_OK ||
-          (err = hal_ks_attribute_delete(bytes, bytes_len, attrs, attrs_len, &total, type)) != HAL_OK)
-        return err;
-    }
-
-    unsigned b;
-
-    if ((err = hal_ks_index_replace(&db.ksi, &slot->name, chunk, &b, &hint))    != HAL_OK ||
-        (err = block_write(b, block))                                           != HAL_OK)
-      return err;
-  }
-
-  /*
-   * Phase 3: Write the new chunk.
-   */
-
-  {
-    block = cache_pick_lru();
-
-    memset(block, 0xFF, sizeof(*block));
-
-    block->header.block_type   = BLOCK_TYPE_ATTR;
-    block->header.block_status = BLOCK_STATUS_LIVE;
-    block->header.total_chunks = total_chunks + 1;
-    block->header.this_chunk   = total_chunks;
-    block->attr.name = slot->name;
-    block->attr.attributes_len = 0;
-
-    hal_rpc_pkey_attribute_t attrs[1];
-    size_t total = 0;
-
-    if ((err = hal_ks_attribute_insert(block->attr.attributes,
-                                       SIZEOF_FLASH_ATTRIBUTE_BLOCK_ATTRIBUTES,
-                                       attrs, &block->attr.attributes_len, &total,
-                                       type, value, value_len))                         != HAL_OK ||
-        (err = hal_ks_index_add(&db.ksi, &slot->name, total_chunks, &b, NULL))          != HAL_OK ||
-        (err = block_write(b, block))                                                   != HAL_OK)
-      return err;
-
-    cache_mark_used(block, b);
-  }
-
-  /*
-   * Phase 4: Zero the old chunks we deprecated in phase 1.
-   */
-
-  for (chunk = 0; chunk < total_chunks; chunk++)
-    if ((err = block_zero(blocks[chunk])) != HAL_OK)
-      return err;
-
-  return HAL_OK;
-}
-
-static  hal_error_t ks_get_attribute(hal_ks_t *ks,
-                                     hal_pkey_slot_t *slot,
-                                     const uint32_t type,
-                                     uint8_t *value,
-                                     size_t *value_len,
-                                     const size_t value_max)
-{
-  if (ks != &db.ks || slot == NULL)
-    return HAL_ERROR_BAD_ARGUMENTS;
-
-  flash_block_t *block;
-  hal_error_t err;
-  unsigned b;
-
-  hal_rpc_pkey_attribute_t a = {0, 0, NULL};
-  unsigned chunk = 0;
-
-  do {
-    int hint = slot->hint + chunk;
-
-    if ((err = hal_ks_index_find(&db.ksi, &slot->name, chunk, &b, &hint)) != HAL_OK ||
-        (err = block_read_cached(b, &block))                              != HAL_OK)
-      return err;
-
-    if (block->header.this_chunk != chunk)
-      return HAL_ERROR_IMPOSSIBLE;
-
-    if (chunk == 0)
-      slot->hint = hint;
-
-    cache_mark_used(block, b);
-
-    uint8_t *bytes = NULL;
-    size_t bytes_len = 0;
-    unsigned *attrs_len;
-
-    if ((err = locate_attributes(block, chunk, &bytes, &bytes_len, &attrs_len)) != HAL_OK)
-      return err;
-
-    if (*attrs_len == 0)
-      continue;
-
-    hal_rpc_pkey_attribute_t attrs[*attrs_len];
-
-    if ((err = hal_ks_attribute_scan(bytes, bytes_len, attrs, *attrs_len, NULL)) != HAL_OK)
-      return err;
-
-    for (int i = 0; a.value == NULL && i < *attrs_len; ++i)
-      if (attrs[i].type == type)
-        a = attrs[i];
-
-  } while (a.value == NULL && ++chunk < block->header.total_chunks);
-
-  if (a.value == NULL)
-    return HAL_ERROR_ATTRIBUTE_NOT_FOUND;
-
-  if (a.length > value_max && value != NULL)
-    return HAL_ERROR_RESULT_TOO_LONG;
-
-  if (value != NULL)
-    memcpy(value, a.value, a.length);
-
-  if (value_len != NULL)
-    *value_len = a.length;
-
-  return HAL_OK;
-}
-
-static hal_error_t ks_delete_attribute(hal_ks_t *ks,
-                                       hal_pkey_slot_t *slot,
-                                       const uint32_t type)
-{
-  /*
-   * For extra credit, we could handle attribute compaction here, but
-   * in practice we expect attribute deletion without deleting the
-   * entire object to be a rare enough event that it may not be worth
-   * it.  Certainly it's not a high priority, so later, if ever.
-   */
-
-  if (ks != &db.ks || slot == NULL)
-    return HAL_ERROR_BAD_ARGUMENTS;
-
-  flash_block_t *block;
-  unsigned chunk = 0;
-
-  do {
-    int hint = slot->hint + chunk;
-    hal_error_t err;
-    unsigned b;
-
-    if ((err = hal_ks_index_find(&db.ksi, &slot->name, chunk, &b, &hint)) != HAL_OK ||
-        (err = block_read_cached(b, &block))                              != HAL_OK)
-      return err;
-
-    if (block->header.this_chunk != chunk)
-      return HAL_ERROR_IMPOSSIBLE;
-
-    if (chunk == 0)
-      slot->hint = hint;
-
-    uint8_t *bytes = NULL;
-    size_t bytes_len = 0;
-    unsigned *attrs_len;
-
-    if ((err = locate_attributes(block, chunk, &bytes, &bytes_len, &attrs_len)) != HAL_OK)
-      return err;
-
-    cache_mark_used(block, b);
-
-    if (*attrs_len == 0)
-      continue;
-
-    hal_rpc_pkey_attribute_t attrs[*attrs_len];
-    const unsigned old_attrs_len = *attrs_len;
-    size_t total;
-
-    if ((err = hal_ks_attribute_scan(  bytes, bytes_len, attrs, *attrs_len, &total))       != HAL_OK ||
-        (err = hal_ks_attribute_delete(bytes, bytes_len, attrs,  attrs_len, &total, type)) != HAL_OK)
-      return err;
-
-    if (*attrs_len == old_attrs_len)
-      continue;
-
-    if ((err = block_update(b, block, &slot->name, chunk, &hint)) != HAL_OK)
-      return err;
-
-  } while (++chunk < block->header.total_chunks);
-
-  return HAL_OK;
-}
-
 static  hal_error_t ks_set_attributes(hal_ks_t *ks,
                                       hal_pkey_slot_t *slot,
                                       const hal_rpc_pkey_attribute_t *attributes,
@@ -1853,12 +1559,13 @@ static  hal_error_t ks_set_attributes(hal_ks_t *ks,
 
       switch (err) {
       case HAL_OK:
-        if (++updated_attributes_i >= updated_attributes_len)
+        if (++updated_attributes_i < updated_attributes_len)
           continue;
         break;
       case HAL_ERROR_RESULT_TOO_LONG:
-        if (new_chunk == 0 || new_attrs_len > 0)
-          break;
+        if (new_chunk > 0 && new_attrs_len == 0)
+          return err;
+        break;
       default:
         return err;
       }
@@ -1973,29 +1680,6 @@ static  hal_error_t ks_get_attributes(hal_ks_t *ks,
   return HAL_OK;
 }
 
-static hal_error_t ks_delete_attributes(hal_ks_t *ks,
-                                        hal_pkey_slot_t *slot,
-                                        const uint32_t *types,
-                                        const unsigned types_len)
-{
-  // Most likely we will remove this function from the API entirely,
-  // but for now implement it in terms of ks_set_attributes() to keep
-  // all the horrid update logic in one place.
-
-  if (ks != &db.ks || slot == NULL || types == NULL || types_len == 0)
-    return HAL_ERROR_BAD_ARGUMENTS;
-
-  hal_rpc_pkey_attribute_t attributes[types_len];
-
-  for (int i = 0; i < types_len; i++) {
-    attributes[i].type   = types[i];
-    attributes[i].length = 0;
-    attributes[i].value  = NULL;
-  }
-
-  return ks_set_attributes(ks, slot, attributes, types_len);
-}
-
 const hal_ks_driver_t hal_ks_token_driver[1] = {{
   ks_init,
   ks_shutdown,
@@ -2006,12 +1690,8 @@ const hal_ks_driver_t hal_ks_token_driver[1] = {{
   ks_delete,
   ks_list,
   ks_match,
-  ks_set_attribute,
-  ks_get_attribute,
-  ks_delete_attribute,
   ks_set_attributes,
-  ks_get_attributes,
-  ks_delete_attributes
+  ks_get_attributes
 }};
 
 /*
diff --git a/ks_index.c b/ks_index.c
index fe4d1b8..0c12fcc 100644
--- a/ks_index.c
+++ b/ks_index.c
@@ -230,7 +230,8 @@ hal_error_t hal_ks_index_find_range(hal_ks_index_t *ksi,
                                     const unsigned max_blocks,
                                     unsigned *n_blocks,
                                     unsigned *blocknos,
-                                    int *hint)
+                                    int *hint,
+                                    const int strict)
 {
   if (ksi == NULL || ksi->index == NULL || ksi->names == NULL ||
       ksi->size == 0 || ksi->used > ksi->size || name == NULL)
@@ -246,7 +247,7 @@ hal_error_t hal_ks_index_find_range(hal_ks_index_t *ksi,
   int n = 0;
 
   for (int i = where; i < ksi->used && !hal_uuid_cmp(name, &ksi->names[ksi->index[i]].name); i++) {
-    if (n != ksi->names[ksi->index[i]].chunk)
+    if (strict && n != ksi->names[ksi->index[i]].chunk)
       return HAL_ERROR_IMPOSSIBLE;
     if (blocknos != NULL && n < max_blocks)
       blocknos[n] = ksi->index[i];
diff --git a/ks_volatile.c b/ks_volatile.c
index b69c3c0..8767458 100644
--- a/ks_volatile.c
+++ b/ks_volatile.c
@@ -470,131 +470,6 @@ static hal_error_t ks_match(hal_ks_t *ks,
   return HAL_OK;
 }
 
-static hal_error_t ks_set_attribute(hal_ks_t *ks,
-                                    hal_pkey_slot_t *slot,
-                                    const uint32_t type,
-                                    const uint8_t * const value,
-                                    const size_t value_len)
-{
-  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 (!key_visible_to_session(ksv, slot->client_handle, slot->session_handle, k))
-    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,
-                                    hal_pkey_slot_t *slot,
-                                    const uint32_t type,
-                                    uint8_t *value,
-                                    size_t *value_len,
-                                    const size_t value_max)
-{
-  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 (!key_visible_to_session(ksv, slot->client_handle, slot->session_handle, k))
-    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)
-{
-  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 (!key_visible_to_session(ksv, slot->client_handle, slot->session_handle, k))
-    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);
-}
-
 static hal_error_t ks_set_attributes(hal_ks_t *ks,
                                      hal_pkey_slot_t *slot,
                                      const hal_rpc_pkey_attribute_t *attributes,
@@ -626,10 +501,16 @@ static hal_error_t ks_set_attributes(hal_ks_t *ks,
   if ((err = hal_ks_attribute_scan(bytes, bytes_len, attrs, k->attributes_len, &total_len)) != HAL_OK)
     return err;
 
-  for (const hal_rpc_pkey_attribute_t *a = attributes; a < attributes + attributes_len; a++)
-    if ((err =  hal_ks_attribute_insert(bytes, bytes_len, attrs, &k->attributes_len, &total_len,
-                                        a->type, a->value, a->length)) != HAL_OK)
+  for (const hal_rpc_pkey_attribute_t *a = attributes; a < attributes + attributes_len; a++) {
+    if (a->length > 0 && a->value != NULL)
+      err =  hal_ks_attribute_insert(bytes, bytes_len, attrs, &k->attributes_len, &total_len,
+                                     a->type, a->value, a->length);
+    else
+      err =  hal_ks_attribute_delete(bytes, bytes_len, attrs, &k->attributes_len, &total_len,
+                                     a->type);
+    if (err != HAL_OK)
       return err;
+  }
 
   return HAL_OK;
 }
@@ -690,45 +571,6 @@ static hal_error_t ks_get_attributes(hal_ks_t *ks,
   return HAL_OK;
 }
 
-static hal_error_t ks_delete_attributes(hal_ks_t *ks,
-                                        hal_pkey_slot_t *slot,
-                                        const uint32_t *types,
-                                        const unsigned types_len)
-{
-  if (ks == NULL || slot == NULL || types == NULL || types_len == 0)
-    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 (!key_visible_to_session(ksv, slot->client_handle, slot->session_handle, k))
-    return HAL_ERROR_KEY_NOT_FOUND;
-
-  hal_rpc_pkey_attribute_t attrs[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;
-
-  if ((err = hal_ks_attribute_scan(bytes, bytes_len, attrs, k->attributes_len, &total_len)) != HAL_OK)
-    return err;
-
-  for (int i = 0; i < types_len; i++)
-    if ((err = hal_ks_attribute_delete(bytes, bytes_len, attrs, &k->attributes_len,
-                                       &total_len, types[i])) != HAL_OK)
-      return err;
-
-  return HAL_OK;
-}
-
 const hal_ks_driver_t hal_ks_volatile_driver[1] = {{
   ks_volatile_init,
   ks_volatile_shutdown,
@@ -739,12 +581,8 @@ const hal_ks_driver_t hal_ks_volatile_driver[1] = {{
   ks_delete,
   ks_list,
   ks_match,
-  ks_set_attribute,
-  ks_get_attribute,
-  ks_delete_attribute,
   ks_set_attributes,
-  ks_get_attributes,
-  ks_delete_attributes
+  ks_get_attributes
 }};
 
 #endif /* STATIC_KS_VOLATILE_SLOTS > 0 */
diff --git a/libhal.py b/libhal.py
index b243a26..6662700 100644
--- a/libhal.py
+++ b/libhal.py
@@ -179,15 +179,10 @@ RPCFunc.define('''
     RPC_FUNC_PKEY_SIGN,
     RPC_FUNC_PKEY_VERIFY,
     RPC_FUNC_PKEY_LIST,
-    RPC_FUNC_PKEY_RENAME,
     RPC_FUNC_PKEY_MATCH,
-    RPC_FUNC_PKEY_SET_ATTRIBUTE,
-    RPC_FUNC_PKEY_GET_ATTRIBUTE,
-    RPC_FUNC_PKEY_DELETE_ATTRIBUTE,
     RPC_FUNC_PKEY_GET_KEY_CURVE,
     RPC_FUNC_PKEY_SET_ATTRIBUTES,
     RPC_FUNC_PKEY_GET_ATTRIBUTES,
-    RPC_FUNC_PKEY_DELETE_ATTRIBUTES,
 ''')
 
 class HALDigestAlgorithm(Enum): pass
@@ -385,24 +380,12 @@ class PKey(Handle):
     def verify(self, hash = 0, data = "", signature = None):
         self.hsm.pkey_verify(self, hash = hash, data = data, signature = signature)
 
-    def set_attribute(self, attr_type, attr_value = None):
-        self.hsm.pkey_set_attribute(self, attr_type, attr_value)
-
-    def get_attribute(self, attr_type):
-        return self.hsm.pkey_get_attribute(self, attr_type)
-
-    def delete_attribute(self, attr_type):
-        self.hsm.pkey_delete_attribute(self, attr_type)
-
     def set_attributes(self, attributes):
         self.hsm.pkey_set_attributes(self, attributes)
 
     def get_attributes(self, attributes, attributes_buffer_len = 2048):
         return self.hsm.pkey_get_attributes(self, attributes, attributes_buffer_len)
 
-    def delete_attributes(self, attributes):
-        self.hsm.pkey_delete_attributes(self, attributes)
-
 
 class HSM(object):
 
@@ -668,18 +651,6 @@ class HSM(object):
                     u = UUID(bytes = r.unpack_bytes())
                     yield u
 
-    def pkey_set_attribute(self, pkey, attr_type, attr_value = None):
-        with self.rpc(RPC_FUNC_PKEY_SET_ATTRIBUTE, pkey, attr_type, attr_value):
-            return
-
-    def pkey_get_attribute(self, pkey, attr_type, value_max = 1024):
-        with self.rpc(RPC_FUNC_PKEY_GET_ATTRIBUTE, pkey, attr_type, value_max) as r:
-            return r.unpack_bytes()
-
-    def pkey_delete_attribute(self, pkey, attr_type):
-        with self.rpc(RPC_FUNC_PKEY_DELETE_ATTRIBUTE, pkey, attr_type):
-            return
-
     def pkey_set_attributes(self, pkey, attributes):
         with self.rpc(RPC_FUNC_PKEY_SET_ATTRIBUTES, pkey, attributes):
             return
@@ -691,7 +662,3 @@ class HSM(object):
             if n != len(attributes):
                 raise HAL_ERROR_RPC_PROTOCOL_ERROR
             return dict((r.unpack_uint(), r.unpack_bytes()) for i in xrange(n))
-
-    def pkey_delete_attributes(self, pkey, attributes):
-        with self.rpc(RPC_FUNC_PKEY_DELETE_ATTRIBUTES, pkey, attributes):
-            return
diff --git a/rpc_api.c b/rpc_api.c
index 772d522..d908e8f 100644
--- a/rpc_api.c
+++ b/rpc_api.c
@@ -372,33 +372,6 @@ hal_error_t hal_rpc_pkey_match(const hal_client_handle_t client,
                                       result, result_len, result_max, previous_uuid);
 }
 
-hal_error_t hal_rpc_pkey_set_attribute(const hal_pkey_handle_t pkey,
-                                       const uint32_t type,
-                                       const uint8_t * const value,
-                                       const size_t value_len)
-{
-  if (value == NULL)
-    return HAL_ERROR_BAD_ARGUMENTS;
-  return hal_rpc_pkey_dispatch->set_attribute(pkey, type, value, value_len);
-}
-
-hal_error_t hal_rpc_pkey_get_attribute(const hal_pkey_handle_t pkey,
-                                       const uint32_t type,
-                                       uint8_t *value,
-                                       size_t *value_len,
-                                       const size_t value_max)
-{
-  if (value == NULL || value_len == NULL)
-    return HAL_ERROR_BAD_ARGUMENTS;
-  return hal_rpc_pkey_dispatch->get_attribute(pkey, type, value, value_len, value_max);
-}
-
-hal_error_t hal_rpc_pkey_delete_attribute(const hal_pkey_handle_t pkey,
-                                          const uint32_t type)
-{
-  return hal_rpc_pkey_dispatch->delete_attribute(pkey, type);
-}
-
 hal_error_t hal_rpc_pkey_set_attributes(const hal_pkey_handle_t pkey,
                                         const hal_rpc_pkey_attribute_t *attributes,
                                         const unsigned attributes_len)
@@ -420,15 +393,6 @@ hal_error_t hal_rpc_pkey_get_attributes(const hal_pkey_handle_t pkey,
                                                attributes_buffer, attributes_buffer_len);
 }
 
-hal_error_t hal_rpc_pkey_delete_attributes(const hal_pkey_handle_t pkey,
-                                           const uint32_t * const types,
-                                           const unsigned types_len)
-{
-  if (types == NULL || types_len == 0)
-    return HAL_ERROR_BAD_ARGUMENTS;
-  return hal_rpc_pkey_dispatch->delete_attributes(pkey, types, types_len);
-}
-
 /*
  * Local variables:
  * indent-tabs-mode: nil
diff --git a/rpc_client.c b/rpc_client.c
index 76c4f0f..c428cc6 100644
--- a/rpc_client.c
+++ b/rpc_client.c
@@ -883,82 +883,6 @@ static hal_error_t pkey_remote_match(const hal_client_handle_t client,
   return rpc_ret;
 }
 
-static hal_error_t pkey_remote_set_attribute(const hal_pkey_handle_t pkey,
-                                             const uint32_t type,
-                                             const uint8_t * const value,
-                                             const size_t value_len)
-{
-  uint8_t outbuf[nargs(5) + pad(value_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf);
-  uint8_t inbuf[nargs(3)];
-  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_SET_ATTRIBUTE));
-  check(hal_xdr_encode_int(&optr, olimit, dummy_client.handle));
-  check(hal_xdr_encode_int(&optr, olimit, pkey.handle));
-  check(hal_xdr_encode_int(&optr, olimit, type));
-  check(hal_xdr_encode_buffer(&optr, olimit, value, value_len));
-  check(hal_rpc_send(outbuf, optr - outbuf));
-
-  check(read_matching_packet(RPC_FUNC_PKEY_SET_ATTRIBUTE, inbuf, sizeof(inbuf), &iptr, &ilimit));
-
-  check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret));
-  return rpc_ret;
-}
-
-static hal_error_t pkey_remote_get_attribute(const hal_pkey_handle_t pkey,
-                                             const uint32_t type,
-                                             uint8_t *value,
-                                             size_t *value_len,
-                                             const size_t value_max)
-{
-  uint8_t outbuf[nargs(5)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf);
-  uint8_t inbuf[nargs(4) + pad(value_max)];
-  const uint8_t *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf);
-  uint32_t vlen32 = value_max;
-  hal_client_handle_t dummy_client = {0};
-  hal_error_t rpc_ret;
-
-  check(hal_xdr_encode_int(&optr, olimit, RPC_FUNC_PKEY_GET_ATTRIBUTE));
-  check(hal_xdr_encode_int(&optr, olimit, dummy_client.handle));
-  check(hal_xdr_encode_int(&optr, olimit, pkey.handle));
-  check(hal_xdr_encode_int(&optr, olimit, type));
-  check(hal_xdr_encode_int(&optr, olimit, vlen32));
-  check(hal_rpc_send(outbuf, optr - outbuf));
-
-  check(read_matching_packet(RPC_FUNC_PKEY_GET_ATTRIBUTE, inbuf, sizeof(inbuf), &iptr, &ilimit));
-
-  check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret));
-  if (rpc_ret == HAL_OK) {
-    check(hal_xdr_decode_buffer(&iptr, ilimit, value, &vlen32));
-    *value_len = (size_t) vlen32;
-  }
-
-  return rpc_ret;
-}
-
-static hal_error_t pkey_remote_delete_attribute(const hal_pkey_handle_t pkey,
-                                                const uint32_t type)
-{
-  uint8_t outbuf[nargs(4)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf);
-  uint8_t inbuf[nargs(3)];
-  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_DELETE_ATTRIBUTE));
-  check(hal_xdr_encode_int(&optr, olimit, dummy_client.handle));
-  check(hal_xdr_encode_int(&optr, olimit, pkey.handle));
-  check(hal_xdr_encode_int(&optr, olimit, type));
-  check(hal_rpc_send(outbuf, optr - outbuf));
-
-  check(read_matching_packet(RPC_FUNC_PKEY_DELETE_ATTRIBUTE, inbuf, sizeof(inbuf), &iptr, &ilimit));
-
-  check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret));
-  return rpc_ret;
-}
-
 static hal_error_t pkey_remote_set_attributes(const hal_pkey_handle_t pkey,
                                              const hal_rpc_pkey_attribute_t *attributes,
                                              const unsigned attributes_len)
@@ -1034,31 +958,6 @@ static hal_error_t pkey_remote_get_attributes(const hal_pkey_handle_t pkey,
   return rpc_ret;
 }
 
-static hal_error_t pkey_remote_delete_attributes(const hal_pkey_handle_t pkey,
-                                                 const uint32_t *types,
-                                                 const unsigned types_len)
-{
-  uint8_t outbuf[nargs(4 + types_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf);
-  uint8_t inbuf[nargs(3)];
-  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_DELETE_ATTRIBUTES));
-  check(hal_xdr_encode_int(&optr, olimit, dummy_client.handle));
-  check(hal_xdr_encode_int(&optr, olimit, pkey.handle));
-  check(hal_xdr_encode_int(&optr, olimit, types_len));
-  for (int i = 0; i < types_len; i++) {
-    check(hal_xdr_encode_int(&optr, olimit, types[i]));
-  }
-  check(hal_rpc_send(outbuf, optr - outbuf));
-
-  check(read_matching_packet(RPC_FUNC_PKEY_DELETE_ATTRIBUTES, inbuf, sizeof(inbuf), &iptr, &ilimit));
-
-  check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret));
-  return rpc_ret;
-}
-
 #if RPC_CLIENT == RPC_CLIENT_MIXED
 
 /*
@@ -1187,12 +1086,8 @@ const hal_rpc_pkey_dispatch_t hal_rpc_remote_pkey_dispatch = {
   pkey_remote_verify,
   pkey_remote_list,
   pkey_remote_match,
-  pkey_remote_set_attribute,
-  pkey_remote_get_attribute,
-  pkey_remote_delete_attribute,
   pkey_remote_set_attributes,
-  pkey_remote_get_attributes,
-  pkey_remote_delete_attributes
+  pkey_remote_get_attributes
 };
 
 #if RPC_CLIENT == RPC_CLIENT_MIXED
@@ -1212,12 +1107,8 @@ const hal_rpc_pkey_dispatch_t hal_rpc_mixed_pkey_dispatch = {
   pkey_mixed_verify,
   pkey_remote_list,
   pkey_remote_match,
-  pkey_remote_set_attribute,
-  pkey_remote_get_attribute,
-  pkey_remote_delete_attribute,
   pkey_remote_set_attributes,
-  pkey_remote_get_attributes,
-  pkey_remote_delete_attributes
+  pkey_remote_get_attributes
 };
 #endif /* RPC_CLIENT == RPC_CLIENT_MIXED */
 
diff --git a/rpc_pkey.c b/rpc_pkey.c
index 50403d7..0310647 100644
--- a/rpc_pkey.c
+++ b/rpc_pkey.c
@@ -977,77 +977,6 @@ static hal_error_t pkey_local_match(const hal_client_handle_t client,
   return err;
 }
 
-static hal_error_t pkey_local_set_attribute(const hal_pkey_handle_t pkey,
-                                            const uint32_t type,
-                                            const uint8_t * const value,
-                                            const size_t value_len)
-{
-  hal_pkey_slot_t *slot = find_handle(pkey);
-
-  if (slot == NULL)
-    return HAL_ERROR_KEY_NOT_FOUND;
-
-  hal_ks_t *ks = NULL;
-  hal_error_t err;
-
-  if ((err = check_writable(slot->client_handle, slot->flags)) != HAL_OK)
-    return err;
-
-  if ((err = ks_open_from_flags(&ks, slot->flags)) == HAL_OK &&
-      (err = hal_ks_set_attribute(ks, slot, type, value, value_len)) == HAL_OK)
-    err = hal_ks_close(ks);
-  else if (ks != NULL)
-    (void) hal_ks_close(ks);
-
-  return err;
-}
-
-static hal_error_t pkey_local_get_attribute(const hal_pkey_handle_t pkey,
-                                            const uint32_t type,
-                                            uint8_t *value,
-                                            size_t *value_len,
-                                            const size_t value_max)
-{
-  hal_pkey_slot_t *slot = find_handle(pkey);
-
-  if (slot == NULL)
-    return HAL_ERROR_KEY_NOT_FOUND;
-
-  hal_ks_t *ks = NULL;
-  hal_error_t err;
-
-  if ((err = ks_open_from_flags(&ks, slot->flags)) == HAL_OK &&
-      (err = hal_ks_get_attribute(ks, slot, type, value, value_len, value_max)) == HAL_OK)
-    err = hal_ks_close(ks);
-  else if (ks != NULL)
-    (void) hal_ks_close(ks);
-
-  return err;
-}
-
-static hal_error_t pkey_local_delete_attribute(const hal_pkey_handle_t pkey,
-                                               const uint32_t type)
-{
-  hal_pkey_slot_t *slot = find_handle(pkey);
-
-  if (slot == NULL)
-    return HAL_ERROR_KEY_NOT_FOUND;
-
-  hal_ks_t *ks = NULL;
-  hal_error_t err;
-
-  if ((err = check_writable(slot->client_handle, slot->flags)) != HAL_OK)
-    return err;
-
-  if ((err = ks_open_from_flags(&ks, slot->flags)) == HAL_OK &&
-      (err = hal_ks_delete_attribute(ks, slot, type)) == HAL_OK)
-    err = hal_ks_close(ks);
-  else if (ks != NULL)
-    (void) hal_ks_close(ks);
-
-  return err;
-}
-
 static hal_error_t pkey_local_set_attributes(const hal_pkey_handle_t pkey,
                                              const hal_rpc_pkey_attribute_t *attributes,
                                              const unsigned attributes_len)
@@ -1096,30 +1025,6 @@ static hal_error_t pkey_local_get_attributes(const hal_pkey_handle_t pkey,
   return err;
 }
 
-static hal_error_t pkey_local_delete_attributes(const hal_pkey_handle_t pkey,
-                                                const uint32_t * const types,
-                                                const unsigned types_len)
-{
-  hal_pkey_slot_t *slot = find_handle(pkey);
-
-  if (slot == NULL)
-    return HAL_ERROR_KEY_NOT_FOUND;
-
-  hal_ks_t *ks = NULL;
-  hal_error_t err;
-
-  if ((err = check_writable(slot->client_handle, slot->flags)) != HAL_OK)
-    return err;
-
-  if ((err = ks_open_from_flags(&ks, slot->flags)) == HAL_OK &&
-      (err = hal_ks_delete_attributes(ks, slot, types, types_len)) == HAL_OK)
-    err = hal_ks_close(ks);
-  else if (ks != NULL)
-    (void) hal_ks_close(ks);
-
-  return err;
-}
-
 const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch = {
   pkey_local_load,
   pkey_local_find,
@@ -1136,12 +1041,8 @@ const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch = {
   pkey_local_verify,
   pkey_local_list,
   pkey_local_match,
-  pkey_local_set_attribute,
-  pkey_local_get_attribute,
-  pkey_local_delete_attribute,
   pkey_local_set_attributes,
-  pkey_local_get_attributes,
-  pkey_local_delete_attributes
+  pkey_local_get_attributes
 };
 
 /*
diff --git a/rpc_server.c b/rpc_server.c
index 201d028..4f06e00 100644
--- a/rpc_server.c
+++ b/rpc_server.c
@@ -743,76 +743,6 @@ static hal_error_t pkey_match(const uint8_t **iptr, const uint8_t * const ilimit
     return ret;
 }
 
-static hal_error_t pkey_set_attribute(const uint8_t **iptr, const uint8_t * const ilimit,
-                                      uint8_t **optr, const uint8_t * const olimit)
-{
-    hal_client_handle_t client;
-    hal_pkey_handle_t pkey;
-    uint32_t type;
-    const uint8_t *value;
-    uint32_t value_len;
-    hal_error_t ret;
-
-    check(hal_xdr_decode_int(iptr, ilimit, &client.handle));
-    check(hal_xdr_decode_int(iptr, ilimit, &pkey.handle));
-    check(hal_xdr_decode_int(iptr, ilimit, &type));
-    check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &value, &value_len));
-
-    ret = hal_rpc_pkey_set_attribute(pkey, type, value, value_len);
-
-    return ret;
-}
-
-static hal_error_t pkey_get_attribute(const uint8_t **iptr, const uint8_t * const ilimit,
-                                      uint8_t **optr, const uint8_t * const olimit)
-{
-    hal_client_handle_t client;
-    hal_pkey_handle_t pkey;
-    uint32_t type;
-    size_t value_len;
-    uint32_t value_max;
-    uint8_t *optr_orig = *optr;
-    hal_error_t ret;
-
-    check(hal_xdr_decode_int(iptr, ilimit, &client.handle));
-    check(hal_xdr_decode_int(iptr, ilimit, &pkey.handle));
-    check(hal_xdr_decode_int(iptr, ilimit, &type));
-    check(hal_xdr_decode_int(iptr, ilimit, &value_max));
-    if (value_max > olimit - *optr - 4)
-        return HAL_ERROR_RPC_PACKET_OVERFLOW;
-
-    *optr += 4;
-    ret = hal_rpc_pkey_get_attribute(pkey, type, *optr, &value_len, value_max);
-
-    if (ret == HAL_OK) {
-        *optr = optr_orig;
-        check(hal_xdr_encode_int(optr, olimit, value_len));
-        *optr += pad(value_len);
-    }
-    else {
-        *optr = optr_orig;
-    }
-
-    return ret;
-}
-
-static hal_error_t pkey_delete_attribute(const uint8_t **iptr, const uint8_t * const ilimit,
-                                         uint8_t **optr, const uint8_t * const olimit)
-{
-    hal_client_handle_t client;
-    hal_pkey_handle_t pkey;
-    uint32_t type;
-    hal_error_t ret;
-
-    check(hal_xdr_decode_int(iptr, ilimit, &client.handle));
-    check(hal_xdr_decode_int(iptr, ilimit, &pkey.handle));
-    check(hal_xdr_decode_int(iptr, ilimit, &type));
-
-    ret = hal_rpc_pkey_delete_attribute(pkey, type);
-
-    return ret;
-}
-
 static hal_error_t pkey_set_attributes(const uint8_t **iptr, const uint8_t * const ilimit,
                                        uint8_t **optr, const uint8_t * const olimit)
 {
@@ -886,29 +816,6 @@ static hal_error_t pkey_get_attributes(const uint8_t **iptr, const uint8_t * con
     return ret;
 }
 
-static hal_error_t pkey_delete_attributes(const uint8_t **iptr, const uint8_t * const ilimit,
-                                          uint8_t **optr, const uint8_t * const olimit)
-{
-    hal_client_handle_t client;
-    hal_pkey_handle_t pkey;
-    uint32_t types_len;
-    hal_error_t ret;
-
-    check(hal_xdr_decode_int(iptr, ilimit, &client.handle));
-    check(hal_xdr_decode_int(iptr, ilimit, &pkey.handle));
-    check(hal_xdr_decode_int(iptr, ilimit, &types_len));
-
-    uint32_t types[types_len > 0 ? types_len : 1];
-
-    for (int i = 0; i < types_len; i++) {
-        check(hal_xdr_decode_int(iptr, ilimit, &types[i]));
-    }
-
-    ret = hal_rpc_pkey_delete_attributes(pkey, types, types_len);
-
-    return ret;
-}
-
 
 hal_error_t hal_rpc_server_dispatch(const uint8_t * const ibuf, const size_t ilen,
                                     uint8_t * const obuf, size_t * const olen)
@@ -1012,24 +919,12 @@ hal_error_t hal_rpc_server_dispatch(const uint8_t * const ibuf, const size_t ile
     case RPC_FUNC_PKEY_MATCH:
         handler = pkey_match;
         break;
-    case RPC_FUNC_PKEY_SET_ATTRIBUTE:
-        handler = pkey_set_attribute;
-        break;
-    case RPC_FUNC_PKEY_GET_ATTRIBUTE:
-        handler = pkey_get_attribute;
-        break;
-    case RPC_FUNC_PKEY_DELETE_ATTRIBUTE:
-        handler = pkey_delete_attribute;
-        break;
     case RPC_FUNC_PKEY_SET_ATTRIBUTES:
         handler = pkey_set_attributes;
         break;
     case RPC_FUNC_PKEY_GET_ATTRIBUTES:
         handler = pkey_get_attributes;
         break;
-    case RPC_FUNC_PKEY_DELETE_ATTRIBUTES:
-        handler = pkey_delete_attributes;
-        break;
     }
 
     if (handler)
diff --git a/tests/test-rpc_pkey.c b/tests/test-rpc_pkey.c
index 789422e..6f2485b 100644
--- a/tests/test-rpc_pkey.c
+++ b/tests/test-rpc_pkey.c
@@ -64,30 +64,33 @@ static int test_attributes(const hal_pkey_handle_t pkey,
   static const char format[] = "Test attribute %lu";
 
   hal_error_t err;
-  size_t n;
 
   for (const size_t *size = sizes; *size; size++) {
     uint8_t buf_1[*size], buf_2[*size];
     memset(buf_1, 0x55, sizeof(buf_1));
     snprintf((char *) buf_1, sizeof(buf_1), format, (unsigned long) *size);
+    hal_rpc_pkey_attribute_t attr_1[1] = {{ *size, sizeof(buf_1), buf_1 }};
+    hal_rpc_pkey_attribute_t attr_2[1] = {{ *size, 0, NULL }};
+    hal_rpc_pkey_attribute_t attr_3[1] = {{ *size, 0, NULL }};
 
-    if ((err = hal_rpc_pkey_set_attribute(pkey, *size, buf_1, sizeof(buf_1))) != HAL_OK)
+    if ((err = hal_rpc_pkey_set_attributes(pkey, attr_1, sizeof(attr_1)/sizeof(*attr_1))) != HAL_OK)
       lose("Could not set attribute %lu: %s\n",
            (unsigned long) *size, hal_error_string(err));
 
-    if ((err = hal_rpc_pkey_get_attribute(pkey, *size, buf_2, &n, sizeof(buf_2))) != HAL_OK)
+    if ((err = hal_rpc_pkey_get_attributes(pkey, attr_2, sizeof(attr_2)/sizeof(*attr_2),
+                                           buf_2, sizeof(buf_2))) != HAL_OK)
       lose("Could not get attribute %lu: %s\n",
            (unsigned long) *size, hal_error_string(err));
 
-    if (n != *size)
+    if (attr_2[0].length != *size)
       lose("Unexpected size returned for attribute %lu: %lu\n",
-           (unsigned long) *size, (unsigned long) n);
+           (unsigned long) *size, (unsigned long) attr_2[0].length);
 
-    if ((err = hal_rpc_pkey_delete_attribute(pkey, *size)) != HAL_OK)
+    if ((err = hal_rpc_pkey_set_attributes(pkey, attr_3, sizeof(attr_3)/sizeof(*attr_3))) != HAL_OK)
       lose("Could not delete attribute %lu: %s\n",
            (unsigned long) *size, hal_error_string(err));
 
-    if ((err = hal_rpc_pkey_set_attribute(pkey, *size, buf_1, sizeof(buf_1))) != HAL_OK)
+    if ((err = hal_rpc_pkey_set_attributes(pkey, attr_1, sizeof(attr_1)/sizeof(*attr_1))) != HAL_OK)
       lose("Could not (re)set attribute %lu: %s\n",
            (unsigned long) *size, hal_error_string(err));
   }
@@ -99,7 +102,8 @@ static int test_attributes(const hal_pkey_handle_t pkey,
     unsigned result_len;
 
     if ((err = hal_rpc_pkey_match(client, session, HAL_KEY_TYPE_NONE, HAL_CURVE_NONE, flags, NULL, 0,
-                                  result, &result_len, sizeof(result)/sizeof(*result), &previous_uuid)) != HAL_OK)
+                                  result, &result_len, sizeof(result)/sizeof(*result),
+                                  &previous_uuid)) != HAL_OK)
       lose("Unrestricted match() failed: %s\n", hal_error_string(err));
 
     if (result_len == 0)
@@ -113,8 +117,10 @@ static int test_attributes(const hal_pkey_handle_t pkey,
 
       if ((err = hal_rpc_pkey_match(client, session, HAL_KEY_TYPE_NONE, HAL_CURVE_NONE, flags,
                                     attribute, sizeof(attribute)/sizeof(*attribute),
-                                    result, &result_len, sizeof(result)/sizeof(*result), &previous_uuid)) != HAL_OK)
-        lose("Restricted match() for attribute %lu failed: %s\n", (unsigned long) *size, hal_error_string(err));
+                                    result, &result_len, sizeof(result)/sizeof(*result),
+                                    &previous_uuid)) != HAL_OK)
+        lose("Restricted match() for attribute %lu failed: %s\n",
+             (unsigned long) *size, hal_error_string(err));
 
       if (result_len == 0)
         lose("Restricted match for attribute %lu found no results\n", (unsigned long) *size);
diff --git a/unit-tests.py b/unit-tests.py
index 3d79da9..43d8944 100644
--- a/unit-tests.py
+++ b/unit-tests.py
@@ -138,13 +138,11 @@ class TestBasic(TestCase):
     """
 
     def test_get_version(self):
-        "Test whether get_version() works"
         version = hsm.get_version()
         # Might want to inspect the result here
         self.assertIsInstance(version, int)
 
     def test_get_random(self):
-        "Test whether get_random() works"
         length = 32
         random = hsm.get_random(length)
         self.assertIsInstance(random, str)
@@ -165,7 +163,6 @@ class TestPIN(TestCase):
         hsm.logout()
 
     def test_is_logged_in(self):
-        "Test whether is_logged_in() returns correct exception when not logged in"
         for user in pin_map:
             self.assertRaises(HAL_ERROR_FORBIDDEN, hsm.is_logged_in, user)
 
@@ -260,33 +257,26 @@ class TestPKeyGen(TestCaseLoggedIn):
         self.sign_verify(hashalg, k1, k2)
 
     def test_gen_sign_verify_ecdsa_p256_sha256(self):
-        "Generate/sign/verify with ECDSA-P256-SHA-256"
         self.gen_sign_verify_ecdsa(HAL_DIGEST_ALGORITHM_SHA256, HAL_CURVE_P256)
 
     def test_gen_sign_verify_ecdsa_p384_sha384(self):
-        "Generate/sign/verify with ECDSA-P384-SHA-384"
         self.gen_sign_verify_ecdsa(HAL_DIGEST_ALGORITHM_SHA384, HAL_CURVE_P384)
 
     def test_gen_sign_verify_ecdsa_p521_sha512(self):
-        "Generate/sign/verify with ECDSA-P521-SHA-512"
         self.gen_sign_verify_ecdsa(HAL_DIGEST_ALGORITHM_SHA512, HAL_CURVE_P521)
 
     def test_gen_sign_verify_rsa_1024_p256_sha256(self):
-        "Generate/sign/verify with RSA-1024-SHA-256"
         self.gen_sign_verify_rsa(HAL_DIGEST_ALGORITHM_SHA256, 1024)
 
     @unittest.skipUnless(args.all_tests, "Slow")
     def test_gen_sign_verify_rsa_2048_sha384(self):
-        "Generate/sign/verify with RSA-2048-SHA-384"
         self.gen_sign_verify_rsa(HAL_DIGEST_ALGORITHM_SHA384, 2048)
 
     @unittest.skipUnless(args.all_tests, "Hideously slow")
     def test_gen_sign_verify_rsa_4096_sha512(self):
-        "Generate/sign/verify with RSA-4096-SHA-512"
         self.gen_sign_verify_rsa(HAL_DIGEST_ALGORITHM_SHA512, 4096)
 
     def test_gen_unsupported_length(self):
-        "Key length not multiple of 32 bits"
         with self.assertRaises(HAL_ERROR_BAD_ARGUMENTS):
             hsm.pkey_generate_rsa(1028).delete()
 
@@ -515,8 +505,7 @@ class TestPKeyList(TestCaseLoggedIn):
             with hsm.pkey_load(obj.keytype, obj.curve, obj.der, flags) as k:
                 self.addCleanup(lambda uuid: hsm.pkey_find(uuid, flags = flags).delete(), k.uuid)
                 uuids.add(k.uuid)
-                for i, a in enumerate((str(obj.keytype), str(obj.fn2))):
-                    k.set_attribute(i, a)
+                k.set_attributes(dict((i, a) for i, a in enumerate((str(obj.keytype), str(obj.fn2)))))
         return uuids
 
     def ks_list(self, flags):
@@ -554,13 +543,13 @@ class TestPKeyList(TestCaseLoggedIn):
         for keytype in set(HALKeyType.index.itervalues()) - {HAL_KEY_TYPE_NONE}:
             for n, k in self.match(flags = flags, uuids = uuids, type = keytype):
                 self.assertEqual(k.key_type, keytype)
-                self.assertEqual(k.get_attribute(0), str(keytype))
+                self.assertEqual(k.get_attributes({0}).pop(0), str(keytype))
             self.assertEqual(n, sum(1 for t1, t2 in tags if t1 == keytype))
 
         for curve in set(HALCurve.index.itervalues()) - {HAL_CURVE_NONE}:
             for n, k in self.match(flags = flags, uuids = uuids, curve = curve):
                 self.assertEqual(k.key_curve, curve)
-                self.assertEqual(k.get_attribute(1), str(curve))
+                self.assertEqual(k.get_attributes({1}).pop(1), str(curve))
                 self.assertIn(k.key_type, (HAL_KEY_TYPE_EC_PUBLIC,
                                            HAL_KEY_TYPE_EC_PRIVATE))
             self.assertEqual(n, sum(1 for t1, t2 in tags if t2 == curve))
@@ -568,15 +557,17 @@ class TestPKeyList(TestCaseLoggedIn):
         for keylen in set(kl for kt, kl in tags if not isinstance(kl, Enum)):
             for n, k in self.match(flags = flags, uuids = uuids,
                                    attributes = {1 : str(keylen)}):
-                self.assertEqual(keylen, int(k.get_attribute(1)))
+                self.assertEqual(keylen, int(k.get_attributes({1}).pop(1)))
                 self.assertIn(k.key_type, (HAL_KEY_TYPE_RSA_PUBLIC,
                                            HAL_KEY_TYPE_RSA_PRIVATE))
-            self.assertEqual(n, sum(1 for t1, t2 in tags if not isinstance(t2, Enum) and  t2 == keylen))
+            self.assertEqual(n, sum(1 for t1, t2 in tags
+                                    if not isinstance(t2, Enum) and  t2 == keylen))
 
         for n, k in self.match(flags = flags, uuids = uuids,
                                type = HAL_KEY_TYPE_RSA_PUBLIC, attributes = {1 : "2048"}):
             self.assertEqual(k.key_type, HAL_KEY_TYPE_RSA_PUBLIC)
-        self.assertEqual(n, sum(1 for t1, t2 in tags if t1 == HAL_KEY_TYPE_RSA_PUBLIC and t2 == 2048))
+        self.assertEqual(n, sum(1 for t1, t2 in tags
+                                if t1 == HAL_KEY_TYPE_RSA_PUBLIC and t2 == 2048))
 
     def test_ks_match_token(self):
         self.ks_match(HAL_KEY_FLAG_TOKEN)
@@ -597,12 +588,12 @@ class TestPKeyAttribute(TestCaseLoggedIn):
                 with hsm.pkey_load(obj.keytype, obj.curve, obj.der, flags) as k:
                     pinwheel()
                     self.addCleanup(lambda uuid: hsm.pkey_find(uuid, flags = flags).delete(), k.uuid)
-                    for j in xrange(n_attrs):
-                        k.set_attribute(j, "Attribute {}{}".format(j, "*" * n_fill))
-                        pinwheel()
+                    k.set_attributes(dict((j, "Attribute {}{}".format(j, "*" * n_fill))
+                                          for j in xrange(n_attrs)))
+                    pinwheel()
 
     def test_attribute_bloat_volatile_many(self):
-        self.load_and_fill(0, n_attrs = 192)
+        self.load_and_fill(0, n_attrs = 128) # 192
 
     def test_attribute_bloat_volatile_big(self):
         self.load_and_fill(0, n_attrs = 6, n_fill = 512)
@@ -611,7 +602,7 @@ class TestPKeyAttribute(TestCaseLoggedIn):
         self.load_and_fill(HAL_KEY_FLAG_TOKEN, n_attrs = 128)
 
     def test_attribute_bloat_token_big(self):
-        self.load_and_fill(HAL_KEY_FLAG_TOKEN, n_attrs = 16, n_fill = 1024)
+        self.load_and_fill(HAL_KEY_FLAG_TOKEN, n_attrs = 4, n_fill = 512) # [16, 1024]
 
 
 class TestPKeyAttributeWriteSpeedToken(TestCaseLoggedIn):
@@ -625,33 +616,18 @@ class TestPKeyAttributeWriteSpeedToken(TestCaseLoggedIn):
         self.addCleanup(self.k.delete)
         super(TestPKeyAttributeWriteSpeedToken, self).setUp()
 
-    def set_attributes_single(self, n_attrs):
-        pinwheel = Pinwheel()
-        for i in xrange(n_attrs):
-            pinwheel()
-            self.k.set_attribute(i, "Attribute {}".format(i))
-
-    def set_attributes_bulk(self, n_attrs):
+    def set_attributes(self, n_attrs):
         self.k.set_attributes(dict((i, "Attribute {}".format(i))
                                    for i in xrange(n_attrs)))
 
-    def test_set_1_attribute_single(self):
-        self.set_attributes_single(1)
-
-    def test_set_6_attributes_single(self):
-        self.set_attributes_single(6)
+    def test_set_1_attribute(self):
+        self.set_attributes(1)
 
-    def test_set_12_attributes_single(self):
-        self.set_attributes_single(12)
+    def test_set_6_attributes(self):
+        self.set_attributes(6)
 
-    def test_set_1_attribute_bulk(self):
-        self.set_attributes_bulk(1)
-
-    def test_set_6_attributes_bulk(self):
-        self.set_attributes_bulk(6)
-
-    def test_set_12_attributes_bulk(self):
-        self.set_attributes_bulk(12)
+    def test_set_12_attributes(self):
+        self.set_attributes(12)
 
 class TestPKeyAttributeWriteSpeedVolatile(TestCaseLoggedIn):
     """
@@ -664,33 +640,18 @@ class TestPKeyAttributeWriteSpeedVolatile(TestCaseLoggedIn):
         self.addCleanup(self.k.delete)
         super(TestPKeyAttributeWriteSpeedVolatile, self).setUp()
 
-    def set_attributes_single(self, n_attrs):
-        pinwheel = Pinwheel()
-        for i in xrange(n_attrs):
-            pinwheel()
-            self.k.set_attribute(i, "Attribute {}".format(i))
-
-    def set_attributes_bulk(self, n_attrs):
+    def set_attributes(self, n_attrs):
         self.k.set_attributes(dict((i, "Attribute {}".format(i))
                                    for i in xrange(n_attrs)))
 
-    def test_set_1_attribute_single(self):
-        self.set_attributes_single(1)
-
-    def test_set_6_attributes_single(self):
-        self.set_attributes_single(6)
-
-    def test_set_12_attributes_single(self):
-        self.set_attributes_single(12)
+    def test_set_1_attribute(self):
+        self.set_attributes(1)
 
-    def test_set_1_attribute_bulk(self):
-        self.set_attributes_bulk(1)
+    def test_set_6_attributes(self):
+        self.set_attributes(6)
 
-    def test_set_6_attributes_bulk(self):
-        self.set_attributes_bulk(6)
-
-    def test_set_12_attributes_bulk(self):
-        self.set_attributes_bulk(12)
+    def test_set_12_attributes(self):
+        self.set_attributes(12)
 
 class TestPKeyAttributeReadSpeedToken(TestCaseLoggedIn):
     """
@@ -701,12 +662,8 @@ class TestPKeyAttributeReadSpeedToken(TestCaseLoggedIn):
         der = PreloadedKey.db[HAL_KEY_TYPE_EC_PRIVATE, HAL_CURVE_P256].der
         self.k = hsm.pkey_load(HAL_KEY_TYPE_EC_PRIVATE, HAL_CURVE_P256, der, HAL_KEY_FLAG_TOKEN)
         self.addCleanup(self.k.delete)
-        if False:
-            for i in xrange(12):
-                self.k.set_attribute(i, "Attribute {}".format(i))
-        else:
-            self.k.set_attributes(dict((i, "Attribute {}".format(i))
-                                       for i in xrange(12)))
+        self.k.set_attributes(dict((i, "Attribute {}".format(i))
+                                   for i in xrange(12)))
         super(TestPKeyAttributeReadSpeedToken, self).setUp()
 
     def verify_attributes(self, n_attrs, attributes):
@@ -714,35 +671,18 @@ class TestPKeyAttributeReadSpeedToken(TestCaseLoggedIn):
                         for i in xrange(n_attrs))
         self.assertEqual(attributes, expected)
 
-    def get_attributes_single(self, n_attrs):
-        pinwheel = Pinwheel()
-        attributes = {}
-        for i in xrange(n_attrs):
-            pinwheel()
-            attributes[i] = self.k.get_attribute(i)
-        self.verify_attributes(n_attrs, attributes)
-
-    def get_attributes_bulk(self, n_attrs):
+    def get_attributes(self, n_attrs):
         attributes = self.k.get_attributes(range(n_attrs))
         self.verify_attributes(n_attrs, attributes)
 
-    def test_get_1_attribute_single(self):
-        self.get_attributes_single(1)
-
-    def test_get_6_attributes_single(self):
-        self.get_attributes_single(6)
+    def test_get_1_attribute(self):
+        self.get_attributes(1)
 
-    def test_get_12_attributes_single(self):
-        self.get_attributes_single(12)
+    def test_get_6_attributes(self):
+        self.get_attributes(6)
 
-    def test_get_1_attribute_bulk(self):
-        self.get_attributes_bulk(1)
-
-    def test_get_6_attributes_bulk(self):
-        self.get_attributes_bulk(6)
-
-    def test_get_12_attributes_bulk(self):
-        self.get_attributes_bulk(12)
+    def test_get_12_attributes(self):
+        self.get_attributes(12)
 
 class TestPKeyAttributeReadSpeedVolatile(TestCaseLoggedIn):
     """
@@ -753,12 +693,8 @@ class TestPKeyAttributeReadSpeedVolatile(TestCaseLoggedIn):
         der = PreloadedKey.db[HAL_KEY_TYPE_EC_PRIVATE, HAL_CURVE_P256].der
         self.k = hsm.pkey_load(HAL_KEY_TYPE_EC_PRIVATE, HAL_CURVE_P256, der, 0)
         self.addCleanup(self.k.delete)
-        if False:
-            for i in xrange(12):
-                self.k.set_attribute(i, "Attribute {}".format(i))
-        else:
-            self.k.set_attributes(dict((i, "Attribute {}".format(i))
-                                       for i in xrange(12)))
+        self.k.set_attributes(dict((i, "Attribute {}".format(i))
+                                   for i in xrange(12)))
         super(TestPKeyAttributeReadSpeedVolatile, self).setUp()
 
     def verify_attributes(self, n_attrs, attributes):
@@ -766,35 +702,18 @@ class TestPKeyAttributeReadSpeedVolatile(TestCaseLoggedIn):
                         for i in xrange(n_attrs))
         self.assertEqual(attributes, expected)
 
-    def get_attributes_single(self, n_attrs):
-        pinwheel = Pinwheel()
-        attributes = {}
-        for i in xrange(n_attrs):
-            pinwheel()
-            attributes[i] = self.k.get_attribute(i)
-        self.verify_attributes(n_attrs, attributes)
-
-    def get_attributes_bulk(self, n_attrs):
+    def get_attributes(self, n_attrs):
         attributes = self.k.get_attributes(range(n_attrs))
         self.verify_attributes(n_attrs, attributes)
 
-    def test_get_1_attribute_single(self):
-        self.get_attributes_single(1)
-
-    def test_get_6_attributes_single(self):
-        self.get_attributes_single(6)
-
-    def test_get_12_attributes_single(self):
-        self.get_attributes_single(12)
-
-    def test_get_1_attribute_bulk(self):
-        self.get_attributes_bulk(1)
+    def test_get_1_attribute(self):
+        self.get_attributes(1)
 
-    def test_get_6_attributes_bulk(self):
-        self.get_attributes_bulk(6)
+    def test_get_6_attributes(self):
+        self.get_attributes(6)
 
-    def test_get_12_attributes_bulk(self):
-        self.get_attributes_bulk(12)
+    def test_get_12_attributes(self):
+        self.get_attributes(12)
 
 
 @unittest.skipUnless(ecdsa_loaded, "Requires Python ECDSA package")



More information about the Commits mailing list