aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hal.h17
-rw-r--r--hal_internal.h137
-rw-r--r--ks_flash.c2
-rw-r--r--ks_volatile.c165
-rw-r--r--libhal.py33
-rw-r--r--rpc_api.c32
-rw-r--r--rpc_client.c115
-rw-r--r--rpc_pkey.c79
-rw-r--r--rpc_server.c108
-rw-r--r--unit-tests.py116
10 files changed, 698 insertions, 106 deletions
diff --git a/hal.h b/hal.h
index 9ac17dc..74e0a51 100644
--- a/hal.h
+++ b/hal.h
@@ -155,6 +155,7 @@
DEFINE_HAL_ERROR(HAL_ERROR_KSI_INDEX_CHUNK_MISSING, "Key index chunk missing") \
DEFINE_HAL_ERROR(HAL_ERROR_KSI_INDEX_CHUNK_OVERLAPS, "Key index chunk overlaps") \
DEFINE_HAL_ERROR(HAL_ERROR_KEYSTORE_WRONG_BLOCK_TYPE, "Wrong block type in keystore") \
+ DEFINE_HAL_ERROR(HAL_ERROR_RPC_PROTOCOL_ERROR, "RPC protocol error") \
END_OF_HAL_ERROR_LIST
/* Marker to forestall silly line continuation errors */
@@ -783,7 +784,7 @@ extern hal_error_t hal_rpc_pkey_match(const hal_client_handle_t client,
const hal_key_type_t type,
const hal_curve_name_t curve,
const hal_key_flags_t flags,
- hal_rpc_pkey_attribute_t *attributes,
+ const hal_rpc_pkey_attribute_t *attributes,
const unsigned attributes_len,
hal_uuid_t *result,
unsigned *result_len,
@@ -804,6 +805,20 @@ extern hal_error_t hal_rpc_pkey_get_attribute(const hal_pkey_handle_t pkey,
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);
+
+extern hal_error_t hal_rpc_pkey_get_attributes(const hal_pkey_handle_t pkey,
+ hal_rpc_pkey_attribute_t *attributes,
+ const unsigned attributes_len,
+ 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 5faba54..6b82b9c 100644
--- a/hal_internal.h
+++ b/hal_internal.h
@@ -250,7 +250,7 @@ typedef struct {
const hal_key_type_t type,
const hal_curve_name_t curve,
const hal_key_flags_t flags,
- hal_rpc_pkey_attribute_t *attributes,
+ const hal_rpc_pkey_attribute_t *attributes,
const unsigned attributes_len,
hal_uuid_t *result,
unsigned *result_len,
@@ -271,6 +271,21 @@ typedef struct {
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);
+
+ hal_error_t (*get_attributes)(const hal_pkey_handle_t pkey,
+ hal_rpc_pkey_attribute_t *attributes,
+ const unsigned attributes_len,
+ 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;
@@ -497,7 +512,7 @@ struct hal_ks_driver {
const hal_key_type_t type,
const hal_curve_name_t curve,
const hal_key_flags_t flags,
- hal_rpc_pkey_attribute_t *attributes,
+ const hal_rpc_pkey_attribute_t *attributes,
const unsigned attributes_len,
hal_uuid_t *result,
unsigned *result_len,
@@ -521,6 +536,23 @@ struct hal_ks_driver {
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,
+ const unsigned attributes_len);
+
+ hal_error_t (*get_attributes)(hal_ks_t *ks,
+ hal_pkey_slot_t *slot,
+ hal_rpc_pkey_attribute_t *attributes,
+ const unsigned attributes_len,
+ 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);
+
};
@@ -622,7 +654,7 @@ static inline hal_error_t hal_ks_match(hal_ks_t *ks,
const hal_key_type_t type,
const hal_curve_name_t curve,
const hal_key_flags_t flags,
- hal_rpc_pkey_attribute_t *attributes,
+ const hal_rpc_pkey_attribute_t *attributes,
const unsigned attributes_len,
hal_uuid_t *result,
unsigned *result_len,
@@ -649,11 +681,11 @@ static inline hal_error_t hal_ks_set_attribute(hal_ks_t *ks,
}
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)
+ 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 || ks->driver->get_attribute == NULL || slot == NULL)
return HAL_ERROR_BAD_ARGUMENTS;
@@ -662,8 +694,8 @@ static inline hal_error_t hal_ks_get_attribute(hal_ks_t *ks,
}
static inline hal_error_t hal_ks_delete_attribute(hal_ks_t *ks,
- hal_pkey_slot_t *slot,
- const uint32_t type)
+ hal_pkey_slot_t *slot,
+ const uint32_t type)
{
if (ks == NULL || ks->driver == NULL || ks->driver->delete_attribute == NULL || slot == NULL)
return HAL_ERROR_BAD_ARGUMENTS;
@@ -671,6 +703,50 @@ static inline hal_error_t hal_ks_delete_attribute(hal_ks_t *ks,
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,
+ const unsigned attributes_len)
+{
+ if (ks == NULL || ks->driver == NULL || ks->driver->set_attributes == NULL || slot == NULL ||
+ attributes == NULL || attributes_len == 0)
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ for (int i = 0; i < attributes_len; i++)
+ if (attributes[i].length == 0 || attributes[i].value == NULL)
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ return ks->driver->set_attributes(ks, slot, attributes, attributes_len);
+}
+
+static inline hal_error_t hal_ks_get_attributes(hal_ks_t *ks,
+ hal_pkey_slot_t *slot,
+ hal_rpc_pkey_attribute_t *attributes,
+ const unsigned attributes_len,
+ uint8_t *attributes_buffer,
+ const size_t attributes_buffer_len)
+{
+ if (ks == NULL || ks->driver == NULL || ks->driver->get_attributes == NULL || slot == NULL ||
+ attributes == NULL || attributes_len == 0 ||
+ attributes_buffer == NULL || attributes_buffer_len == 0)
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ return ks->driver->get_attributes(ks, slot, attributes, attributes_len,
+ 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 || ks->driver->delete_attributes == NULL || slot == NULL ||
+ types == NULL || types_len == 0)
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ 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.
@@ -803,44 +879,6 @@ extern hal_error_t hal_ks_index_fsck(hal_ks_index_t *ksi);
/*
* Keystore attribute utilities, for use by keystore drivers.
- *
- * Basic model here is probably to replace the "der" block in a key
- * object with a byte array. We could use padding to get alignment,
- * but it's probably easier just to do this DNS style, pulling a
- * 16-bit length and 32-bit attribute type out of the byte array
- * directly. Well, maybe. I guess if we cast the uint8_t* to a
- * structure pointer we could use the structure to pull out the header
- * fields, but that has portability issues, particulary if the
- * compiler gets tetchy about type punning.
- *
- * Unclear whether we should treat the key DER specially. Might just
- * give it an attribute code of 0xFFFFFFFF and treat it same as
- * everything else, just always first for convenience. This assumes
- * that PKCS #11 will never use 0xFFFFFFFF, which is a bit risky, but
- * maybe the code just treats it a little bit specially and knows to
- * skip over the key DER when looking for attributes, etc.
- *
- * We probably don't want to let attributes span block boundaries. We
- * probably do want to attempt to fit a new attribute into the first
- * available space which can hold it. In theory, taken together, this
- * means we will only have to update multiple blocks when required to
- * add a new block (in which case the max_blocks count changes). Most
- * of this only applies to flash, for volatile we can use as much
- * memory as we like, although even there we might want smaller chunks
- * to avoid wasting huge tracts of space that don't end up being used.
- * But maybe that's just a configuration thing for the volatile
- * keystore(s).
- *
- * If we have to rewrite a block at all we might as well compact it,
- * so fragmentation in that sense is a non-issue. Might need to
- * collapse blocks when deletion has freed up enough space, but that
- * might be something we handle directly in ks_flash rather than in
- * the ks_attribute code.
- *
- * We need some way of figuring out how many attributes there are.
- * Options are a marker (like the IPv4 END-OF-OPTIONS option) or a
- * count in the header. Count is simpler and lets us pre-allocate
- * arrays so probably go with that.
*/
extern hal_error_t hal_ks_attribute_scan(const uint8_t * const bytes,
@@ -919,6 +957,9 @@ typedef enum {
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 7a11f0f..c96efd5 100644
--- a/ks_flash.c
+++ b/ks_flash.c
@@ -1156,7 +1156,7 @@ static hal_error_t ks_match(hal_ks_t *ks,
const hal_key_type_t type,
const hal_curve_name_t curve,
const hal_key_flags_t flags,
- hal_rpc_pkey_attribute_t *attributes,
+ const hal_rpc_pkey_attribute_t *attributes,
const unsigned attributes_len,
hal_uuid_t *result,
unsigned *result_len,
diff --git a/ks_volatile.c b/ks_volatile.c
index c8a424c..b69c3c0 100644
--- a/ks_volatile.c
+++ b/ks_volatile.c
@@ -390,7 +390,7 @@ static hal_error_t ks_match(hal_ks_t *ks,
const hal_key_type_t type,
const hal_curve_name_t curve,
const hal_key_flags_t flags,
- hal_rpc_pkey_attribute_t *attributes,
+ const hal_rpc_pkey_attribute_t *attributes,
const unsigned attributes_len,
hal_uuid_t *result,
unsigned *result_len,
@@ -447,7 +447,7 @@ static hal_error_t ks_match(hal_ks_t *ks,
key_attrs, k->attributes_len, NULL)) != HAL_OK)
return err;
- for (hal_rpc_pkey_attribute_t *required = attributes;
+ for (const hal_rpc_pkey_attribute_t *required = attributes;
ok && required < attributes + attributes_len; required++) {
hal_rpc_pkey_attribute_t *present = key_attrs;
@@ -470,11 +470,11 @@ 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)
+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;
@@ -508,12 +508,12 @@ static hal_error_t ks_set_attribute(hal_ks_t *ks,
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)
+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;
@@ -595,6 +595,140 @@ static hal_error_t ks_delete_attribute(hal_ks_t *ks,
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,
+ const unsigned attributes_len)
+{
+ if (ks == NULL || slot == NULL || attributes == NULL || attributes_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 + attributes_len];
+ 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 (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)
+ return err;
+
+ return HAL_OK;
+}
+
+static hal_error_t ks_get_attributes(hal_ks_t *ks,
+ hal_pkey_slot_t *slot,
+ hal_rpc_pkey_attribute_t *attributes,
+ const unsigned attributes_len,
+ uint8_t *attributes_buffer,
+ const size_t attributes_buffer_len)
+{
+ if (ks == NULL || slot == NULL || attributes == NULL || attributes_len == 0 ||
+ attributes_buffer == NULL || attributes_buffer_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;
+
+ 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 attrs[k->attributes_len];
+
+ if ((err = hal_ks_attribute_scan(k->der + k->der_len, sizeof(k->der) - k->der_len,
+ attrs, k->attributes_len, NULL)) != HAL_OK)
+ return err;
+
+ uint8_t *abuf = attributes_buffer;
+
+ for (int i = 0; i < attributes_len; i++) {
+
+ int j = 0;
+ while (attrs[j].type != attributes[i].type)
+ if (++j >= k->attributes_len)
+ return HAL_ERROR_ATTRIBUTE_NOT_FOUND;
+
+ if (attrs[j].length > attributes_buffer + attributes_buffer_len - abuf)
+ return HAL_ERROR_RESULT_TOO_LONG;
+
+ memcpy(abuf, attrs[j].value, attrs[j].length);
+ attributes[i].value = abuf;
+ attributes[i].length = attrs[j].length;
+ abuf += attrs[j].length;
+ }
+
+ 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,
@@ -607,7 +741,10 @@ const hal_ks_driver_t hal_ks_volatile_driver[1] = {{
ks_match,
ks_set_attribute,
ks_get_attribute,
- ks_delete_attribute
+ ks_delete_attribute,
+ ks_set_attributes,
+ ks_get_attributes,
+ ks_delete_attributes
}};
#endif /* STATIC_KS_VOLATILE_SLOTS > 0 */
diff --git a/libhal.py b/libhal.py
index 06445f0..4023edc 100644
--- a/libhal.py
+++ b/libhal.py
@@ -112,6 +112,7 @@ HALError.define(HAL_ERROR_KSI_INDEX_CHUNK_ORPHANED = "Key index chunk orphaned"
HALError.define(HAL_ERROR_KSI_INDEX_CHUNK_MISSING = "Key index chunk missing")
HALError.define(HAL_ERROR_KSI_INDEX_CHUNK_OVERLAPS = "Key index chunk overlaps")
HALError.define(HAL_ERROR_KEYSTORE_WRONG_BLOCK_TYPE = "Wrong block type in keystore")
+HALError.define(HAL_ERROR_RPC_PROTOCOL_ERROR = "RPC protocol error")
class Enum(int):
@@ -183,6 +184,9 @@ RPCFunc.define('''
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
@@ -389,6 +393,15 @@ class PKey(Handle):
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):
@@ -642,7 +655,7 @@ class HSM(object):
key_name = UUID(bytes = r.unpack_bytes())
yield key_type, key_curve, key_flags, key_name
- def pkey_match(self, type = 0, curve = 0, flags = 0, attributes = (),
+ def pkey_match(self, type = 0, curve = 0, flags = 0, attributes = {},
length = 64, client = 0, session = 0):
u = UUID(int = 0)
n = length
@@ -655,8 +668,6 @@ class HSM(object):
yield u
def pkey_set_attribute(self, pkey, attr_type, attr_value = None):
- if attr_value is None and isinstance(attr_type, Attribute):
- attr_type, attr_value = attr_type.type, attr_type.attr_value
with self.rpc(RPC_FUNC_PKEY_SET_ATTRIBUTE, pkey, attr_type, attr_value):
return
@@ -667,3 +678,19 @@ class HSM(object):
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
+
+ def pkey_get_attributes(self, pkey, attributes, attributes_buffer_len = 2048):
+ attributes = tuple(attributes)
+ with self.rpc(RPC_FUNC_PKEY_GET_ATTRIBUTES, pkey, attributes, attributes_buffer_len) as r:
+ n = r.unpack_uint()
+ 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 d337eeb..772d522 100644
--- a/rpc_api.c
+++ b/rpc_api.c
@@ -351,7 +351,7 @@ hal_error_t hal_rpc_pkey_match(const hal_client_handle_t client,
const hal_key_type_t type,
const hal_curve_name_t curve,
const hal_key_flags_t flags,
- hal_rpc_pkey_attribute_t *attributes,
+ const hal_rpc_pkey_attribute_t *attributes,
const unsigned attributes_len,
hal_uuid_t *result,
unsigned *result_len,
@@ -399,6 +399,36 @@ hal_error_t hal_rpc_pkey_delete_attribute(const hal_pkey_handle_t pkey,
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)
+{
+ if (attributes == NULL || attributes_len == 0)
+ return HAL_ERROR_BAD_ARGUMENTS;
+ return hal_rpc_pkey_dispatch->set_attributes(pkey, attributes, attributes_len);
+}
+
+hal_error_t hal_rpc_pkey_get_attributes(const hal_pkey_handle_t pkey,
+ hal_rpc_pkey_attribute_t *attributes,
+ const unsigned attributes_len,
+ uint8_t *attributes_buffer,
+ const size_t attributes_buffer_len)
+{
+ if (attributes == NULL || attributes_len == 0)
+ return HAL_ERROR_BAD_ARGUMENTS;
+ return hal_rpc_pkey_dispatch->get_attributes(pkey, attributes, attributes_len,
+ 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 0bd3ed5..76c4f0f 100644
--- a/rpc_client.c
+++ b/rpc_client.c
@@ -830,7 +830,7 @@ static hal_error_t pkey_remote_match(const hal_client_handle_t client,
const hal_key_type_t type,
const hal_curve_name_t curve,
const hal_key_flags_t flags,
- hal_rpc_pkey_attribute_t *attributes,
+ const hal_rpc_pkey_attribute_t *attributes,
const unsigned attributes_len,
hal_uuid_t *result,
unsigned *result_len,
@@ -869,10 +869,11 @@ static hal_error_t pkey_remote_match(const hal_client_handle_t client,
check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret));
if (rpc_ret == HAL_OK) {
- uint32_t array_len, uuid_len;
+ uint32_t array_len;
*result_len = 0;
check(hal_xdr_decode_int(&iptr, ilimit, &array_len));
for (int i = 0; i < array_len; ++i) {
+ uint32_t uuid_len = sizeof(result[i].uuid);
check(hal_xdr_decode_buffer(&iptr, ilimit, result[i].uuid, &uuid_len));
if (uuid_len != sizeof(result[i].uuid))
return HAL_ERROR_KEY_NAME_TOO_LONG;
@@ -958,6 +959,106 @@ static hal_error_t pkey_remote_delete_attribute(const hal_pkey_handle_t pkey,
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)
+{
+ size_t outbuf_len = nargs(4 + 2 * attributes_len);
+ for (int i = 0; i < attributes_len; i++)
+ outbuf_len += pad(attributes[i].length);
+
+ uint8_t outbuf[outbuf_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_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, attributes_len));
+ for (int i = 0; i < attributes_len; i++) {
+ check(hal_xdr_encode_int(&optr, olimit, attributes[i].type));
+ check(hal_xdr_encode_buffer(&optr, olimit, attributes[i].value, attributes[i].length));
+ }
+ check(hal_rpc_send(outbuf, optr - outbuf));
+
+ check(read_matching_packet(RPC_FUNC_PKEY_SET_ATTRIBUTES, inbuf, sizeof(inbuf), &iptr, &ilimit));
+
+ check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret));
+ return rpc_ret;
+}
+
+static hal_error_t pkey_remote_get_attributes(const hal_pkey_handle_t pkey,
+ hal_rpc_pkey_attribute_t *attributes,
+ const unsigned attributes_len,
+ uint8_t *attributes_buffer,
+ const size_t attributes_buffer_len)
+{
+ /* inbuf[] here includes one extra word per attribute for padding */
+ uint8_t outbuf[nargs(5 + attributes_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf);
+ uint8_t inbuf[nargs(3 + 3 * attributes_len) + attributes_buffer_len];
+ 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_GET_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, attributes_len));
+ for (int i = 0; i < attributes_len; i++)
+ check(hal_xdr_encode_int(&optr, olimit, attributes[i].type));
+ check(hal_xdr_encode_int(&optr, olimit, attributes_buffer_len));
+ check(hal_rpc_send(outbuf, optr - outbuf));
+
+ check(read_matching_packet(RPC_FUNC_PKEY_GET_ATTRIBUTES, inbuf, sizeof(inbuf), &iptr, &ilimit));
+
+ check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret));
+ if (rpc_ret == HAL_OK) {
+ uint8_t *abuf = attributes_buffer;
+ uint32_t u32;
+ check(hal_xdr_decode_int(&iptr, ilimit, &u32));
+ if (u32 != attributes_len)
+ return HAL_ERROR_RPC_PROTOCOL_ERROR;
+ for (int i = 0; i < attributes_len; i++) {
+ check(hal_xdr_decode_int(&iptr, ilimit, &u32));
+ if (u32 != attributes[i].type)
+ return HAL_ERROR_RPC_PROTOCOL_ERROR;
+ u32 = attributes_buffer + attributes_buffer_len - abuf;
+ check(hal_xdr_decode_buffer(&iptr, ilimit, abuf, &u32));
+ attributes[i].value = abuf;
+ attributes[i].length = u32;
+ abuf += u32;
+ }
+ }
+ 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
/*
@@ -1088,7 +1189,10 @@ const hal_rpc_pkey_dispatch_t hal_rpc_remote_pkey_dispatch = {
pkey_remote_match,
pkey_remote_set_attribute,
pkey_remote_get_attribute,
- pkey_remote_delete_attribute
+ pkey_remote_delete_attribute,
+ pkey_remote_set_attributes,
+ pkey_remote_get_attributes,
+ pkey_remote_delete_attributes
};
#if RPC_CLIENT == RPC_CLIENT_MIXED
@@ -1110,7 +1214,10 @@ const hal_rpc_pkey_dispatch_t hal_rpc_mixed_pkey_dispatch = {
pkey_remote_match,
pkey_remote_set_attribute,
pkey_remote_get_attribute,
- pkey_remote_delete_attribute
+ pkey_remote_delete_attribute,
+ pkey_remote_set_attributes,
+ pkey_remote_get_attributes,
+ pkey_remote_delete_attributes
};
#endif /* RPC_CLIENT == RPC_CLIENT_MIXED */
diff --git a/rpc_pkey.c b/rpc_pkey.c
index 88b6248..50403d7 100644
--- a/rpc_pkey.c
+++ b/rpc_pkey.c
@@ -954,7 +954,7 @@ static hal_error_t pkey_local_match(const hal_client_handle_t client,
const hal_key_type_t type,
const hal_curve_name_t curve,
const hal_key_flags_t flags,
- hal_rpc_pkey_attribute_t *attributes,
+ const hal_rpc_pkey_attribute_t *attributes,
const unsigned attributes_len,
hal_uuid_t *result,
unsigned *result_len,
@@ -1048,6 +1048,78 @@ static hal_error_t pkey_local_delete_attribute(const hal_pkey_handle_t pkey,
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)
+{
+ 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_attributes(ks, slot, attributes, attributes_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_attributes(const hal_pkey_handle_t pkey,
+ hal_rpc_pkey_attribute_t *attributes,
+ const unsigned attributes_len,
+ uint8_t *attributes_buffer,
+ const size_t attributes_buffer_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 = ks_open_from_flags(&ks, slot->flags)) == HAL_OK &&
+ (err = hal_ks_get_attributes(ks, slot, attributes, attributes_len,
+ attributes_buffer, attributes_buffer_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_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,
@@ -1066,7 +1138,10 @@ const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch = {
pkey_local_match,
pkey_local_set_attribute,
pkey_local_get_attribute,
- pkey_local_delete_attribute
+ pkey_local_delete_attribute,
+ pkey_local_set_attributes,
+ pkey_local_get_attributes,
+ pkey_local_delete_attributes
};
/*
diff --git a/rpc_server.c b/rpc_server.c
index a19a44b..201d028 100644
--- a/rpc_server.c
+++ b/rpc_server.c
@@ -44,6 +44,8 @@
#define pad(n) (((n) + 3) & ~3)
+#define nargs(n) ((n) * 4)
+
static hal_error_t get_version(const uint8_t **iptr, const uint8_t * const ilimit,
uint8_t **optr, const uint8_t * const olimit)
{
@@ -811,6 +813,103 @@ static hal_error_t pkey_delete_attribute(const uint8_t **iptr, const uint8_t * c
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)
+{
+ hal_client_handle_t client;
+ hal_pkey_handle_t pkey;
+ uint32_t attributes_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, &attributes_len));
+
+ hal_rpc_pkey_attribute_t attributes[attributes_len > 0 ? attributes_len : 1];
+
+ for (int i = 0; i < attributes_len; i++) {
+ hal_rpc_pkey_attribute_t *a = &attributes[i];
+ uint32_t value_len;
+ check(hal_xdr_decode_int(iptr, ilimit, &a->type));
+ check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &a->value, &value_len));
+ a->length = value_len;
+ }
+
+ ret = hal_rpc_pkey_set_attributes(pkey, attributes, attributes_len);
+
+ return ret;
+}
+
+static hal_error_t pkey_get_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 attributes_len, u32;
+ 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, &attributes_len));
+
+ hal_rpc_pkey_attribute_t attributes[attributes_len > 0 ? attributes_len : 1];
+
+ for (int i = 0; i < attributes_len; i++)
+ check(hal_xdr_decode_int(iptr, ilimit, &attributes[i].type));
+
+ check(hal_xdr_decode_int(iptr, ilimit, &u32));
+
+ const size_t attributes_buffer_len = u32;
+
+ if (nargs(1 + 2 * attributes_len) + attributes_buffer_len > olimit - *optr)
+ return HAL_ERROR_RPC_PACKET_OVERFLOW;
+
+ uint8_t attributes_buffer[attributes_buffer_len > 0 ? attributes_buffer_len : 1];
+
+ ret = hal_rpc_pkey_get_attributes(pkey, attributes, attributes_len,
+ attributes_buffer, attributes_buffer_len);
+
+ if (ret == HAL_OK) {
+ ret = hal_xdr_encode_int(optr, olimit, attributes_len);
+ for (int i = 0; ret == HAL_OK && i < attributes_len; i++) {
+ ret = hal_xdr_encode_int(optr, olimit, attributes[i].type);
+ if (ret != HAL_OK)
+ break;
+ ret = hal_xdr_encode_buffer(optr, olimit, attributes[i].value, attributes[i].length);
+ }
+ }
+
+ if (ret != HAL_OK)
+ *optr = optr_orig;
+
+ 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)
{
@@ -922,6 +1021,15 @@ hal_error_t hal_rpc_server_dispatch(const uint8_t * const ibuf, const size_t ile
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/unit-tests.py b/unit-tests.py
index ca18e3a..43b56ba 100644
--- a/unit-tests.py
+++ b/unit-tests.py
@@ -625,20 +625,33 @@ class TestPKeyAttributeWriteSpeedToken(TestCaseLoggedIn):
self.addCleanup(self.k.delete)
super(TestPKeyAttributeWriteSpeedToken, self).setUp()
- def set_attributes(self, n_attrs):
+ 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 test_set_1_attribute(self):
- self.set_attributes(1)
+ def set_attributes_bulk(self, n_attrs):
+ self.k.set_attributes(dict((i, "Attribute {}".format(i))
+ for i in xrange(n_attrs)))
- def test_set_6_attributes(self):
- self.set_attributes(6)
+ def test_set_1_attribute_single(self):
+ self.set_attributes_single(1)
- def test_set_12_attributes(self):
- self.set_attributes(12)
+ 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_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)
class TestPKeyAttributeWriteSpeedVolatile(TestCaseLoggedIn):
"""
@@ -651,19 +664,33 @@ class TestPKeyAttributeWriteSpeedVolatile(TestCaseLoggedIn):
self.addCleanup(self.k.delete)
super(TestPKeyAttributeWriteSpeedVolatile, self).setUp()
- def set_attributes(self, n_attrs):
+ 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 test_set_1_attribute(self):
- self.set_attributes(1)
+ def set_attributes_bulk(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_6_attributes(self):
- self.set_attributes(6)
+ def test_set_1_attribute_bulk(self):
+ self.set_attributes_bulk(1)
- def test_set_12_attributes(self):
- self.set_attributes(12)
+ def test_set_6_attributes_bulk(self):
+ self.set_attributes_bulk(6)
+ def test_set_12_attributes_bulk(self):
+ self.set_attributes_bulk(12)
class TestPKeyAttributeReadSpeedToken(TestCaseLoggedIn):
"""
@@ -674,23 +701,36 @@ 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)
- self.k.set_attribute(0, "Attribute 0")
+ for i in xrange(12):
+ self.k.set_attribute(i, "Attribute {}".format(i))
super(TestPKeyAttributeReadSpeedToken, self).setUp()
- def get_attributes(self, n_attrs):
+ def get_attributes_single(self, n_attrs):
pinwheel = Pinwheel()
for i in xrange(n_attrs):
pinwheel()
- self.k.get_attribute(0)
+ self.k.get_attribute(i)
+
+ def get_attributes_bulk(self, n_attrs):
+ self.k.get_attributes(range(n_attrs))
+
+ 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(self):
- self.get_attributes(1)
+ def test_get_1_attribute_bulk(self):
+ self.get_attributes_bulk(1)
- def test_get_6_attributes(self):
- self.get_attributes(6)
+ def test_get_6_attributes_bulk(self):
+ self.get_attributes_bulk(6)
- def test_get_12_attributes(self):
- self.get_attributes(12)
+ def test_get_12_attributes_bulk(self):
+ self.get_attributes_bulk(12)
class TestPKeyAttributeReadSpeedVolatile(TestCaseLoggedIn):
"""
@@ -701,24 +741,36 @@ 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)
- self.k.set_attribute(0, "Attribute 0")
+ for i in xrange(12):
+ self.k.set_attribute(i, "Attribute {}".format(i))
super(TestPKeyAttributeReadSpeedVolatile, self).setUp()
- def get_attributes(self, n_attrs):
+ def get_attributes_single(self, n_attrs):
pinwheel = Pinwheel()
for i in xrange(n_attrs):
pinwheel()
- self.k.get_attribute(0)
+ self.k.get_attribute(i)
+
+ def get_attributes_bulk(self, n_attrs):
+ self.k.get_attributes(range(n_attrs))
+
+ 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_12_attributes(self):
- self.get_attributes(12)
+ def test_get_6_attributes_bulk(self):
+ self.get_attributes_bulk(6)
+ def test_get_12_attributes_bulk(self):
+ self.get_attributes_bulk(12)
@unittest.skipUnless(ecdsa_loaded, "Requires Python ECDSA package")