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