From db32574d6c85bb48a2f01d80eec6e241152704ff Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Fri, 7 Oct 2016 17:32:14 -0400 Subject: Checkpoint along the way to adding keystore attribute support. This is mostly to archive a commit where PKCS #11 "make test" still works after converting the ks_volatile code to use SDRAM allocated at startup instead of (large) static variables. The attribute code itself is incomplete at this point. --- Makefile | 2 +- hal.h | 33 ++++++++++ hal_internal.h | 173 ++++++++++++++++++++++++++++++++++++++++++++++++ ks_attribute.c | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ks_flash.c | 56 ++++++++++++++-- ks_volatile.c | 136 ++++++++++++++++++++++++++++++-------- rpc_api.c | 50 ++++++++++++++ rpc_client.c | 152 ++++++++++++++++++++++++++++++++++++++++-- rpc_pkey.c | 94 +++++++++++++++++++++++++- rpc_server.c | 153 +++++++++++++++++++++++++++++++++++++++--- 10 files changed, 1003 insertions(+), 51 deletions(-) create mode 100644 ks_attribute.c diff --git a/Makefile b/Makefile index b4c6086..afde6c4 100644 --- a/Makefile +++ b/Makefile @@ -118,7 +118,7 @@ endif # # The mmap keystore hasn't been rewritten for the new API yet. -KS_OBJ = ks_index.o ks_volatile.o +KS_OBJ = ks_index.o ks_attribute.o ks_volatile.o ifeq "${KS}" "mmap" KS_OBJ += ks_mmap.o diff --git a/hal.h b/hal.h index e94f3b8..5b4de69 100644 --- a/hal.h +++ b/hal.h @@ -147,6 +147,7 @@ DEFINE_HAL_ERROR(HAL_ERROR_KEYSTORE_BAD_CRC, "Bad CRC in keystore") \ 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") \ END_OF_HAL_ERROR_LIST /* Marker to forestall silly line continuation errors */ @@ -735,6 +736,8 @@ extern size_t hal_rpc_pkey_get_public_key_len(const hal_pkey_handle_t pkey); extern hal_error_t hal_rpc_pkey_get_public_key(const hal_pkey_handle_t pkey, uint8_t *der, size_t *der_len, const size_t der_max); +#warning Um, why do hal_rpc_pkey_sign() and hal_rpc_pkey_verify() take session arguments? + extern hal_error_t hal_rpc_pkey_sign(const hal_session_handle_t session, const hal_pkey_handle_t pkey, const hal_hash_handle_t hash, @@ -760,6 +763,36 @@ extern hal_error_t hal_rpc_pkey_list(hal_pkey_info_t *result, const unsigned result_max, hal_key_flags_t flags); +typedef struct { + uint32_t type; + size_t length; + const uint8_t *value; +} hal_rpc_pkey_attribute_t; + +extern hal_error_t hal_rpc_pkey_match(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 unsigned attributes_len, + hal_uuid_t *result, + unsigned *result_len, + const unsigned result_max, + hal_uuid_t *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_client_init(void); extern hal_error_t hal_rpc_client_close(void); diff --git a/hal_internal.h b/hal_internal.h index 11f9898..0d40922 100644 --- a/hal_internal.h +++ b/hal_internal.h @@ -242,6 +242,30 @@ typedef struct { const unsigned result_max, hal_key_flags_t flags); + hal_error_t (*match)(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 unsigned attributes_len, + hal_uuid_t *result, + unsigned *result_len, + const unsigned result_max, + hal_uuid_t *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_rpc_pkey_dispatch_t; @@ -470,6 +494,35 @@ struct hal_ks_driver { hal_pkey_info_t *result, unsigned *result_len, const unsigned result_max); + + hal_error_t (*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 unsigned attributes_len, + hal_uuid_t *result, + unsigned *result_len, + const unsigned result_max, + hal_uuid_t *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); + }; @@ -563,6 +616,59 @@ static inline hal_error_t hal_ks_list(hal_ks_t *ks, return ks->driver->list(ks, result, result_len, result_max); } +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 unsigned attributes_len, + hal_uuid_t *result, + unsigned *result_len, + const unsigned result_max, + hal_uuid_t *previous_uuid) +{ + if (ks == NULL || ks->driver == NULL || ks->driver->match == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + return ks->driver->match(ks, type, curve, flags, attributes, attributes_len, + 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 || ks->driver->set_attribute == NULL || slot == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + 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 || ks->driver->get_attribute == NULL || slot == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + 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 || ks->driver->delete_attribute == NULL || slot == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + return ks->driver->delete_attribute(ks, slot, type); +} + /* * Keystore index. This is intended to be usable by both memory-based * (in-memory, mmap(), ...) keystores and keystores based on raw flash. @@ -675,6 +781,69 @@ extern hal_error_t hal_ks_index_replace(hal_ks_index_t *ksi, unsigned *blockno, int *hint); +/* + * 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, + const size_t bytes_len, + hal_rpc_pkey_attribute_t *attributes, + const unsigned attributes_len, + size_t *total_len); + +extern hal_error_t hal_ks_attribute_delete(uint8_t *bytes, + const size_t bytes_len, + hal_rpc_pkey_attribute_t *attributes, + unsigned *attributes_len, + size_t *total_len, + const uint32_t type); + +extern hal_error_t hal_ks_attribute_insert(uint8_t *bytes, const size_t bytes_len, + hal_rpc_pkey_attribute_t *attributes, + unsigned *attributes_len, + size_t *total_len, + const uint32_t type, + const uint8_t * const value, + const size_t value_len); + /* * RPC lowest-level send and receive routines. These are blocking, and * transport-specific (sockets, USB). @@ -725,6 +894,10 @@ typedef enum { 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_num_t; #define RPC_VERSION 0x01010000 /* 1.1.0.0 */ diff --git a/ks_attribute.c b/ks_attribute.c new file mode 100644 index 0000000..248f98d --- /dev/null +++ b/ks_attribute.c @@ -0,0 +1,205 @@ +/* + * ks_attribute.c + * -------------- + * Keystore attribute API. This is internal within libhal. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "hal.h" +#include "hal_internal.h" + +/* + * Read and write attribute headers (type and length). We could do + * this with a structure type and casts, but that has portability + * issues, and doing it this way just isn't expensive enough to worry about. + */ + +#define HEADER_LEN (4 + 2) + +static inline hal_error_t read_header(const uint8_t * const bytes, const size_t bytes_len, + uint32_t *attribute_type, size_t *attribute_len) +{ + if (bytes == NULL || bytes_len < HEADER_LEN || attribute_type == NULL || attribute_len == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + *attribute_type = ((bytes[0] << 24) | + (bytes[1] << 16) | + (bytes[2] << 8) | + (bytes[3] << 0)); + *attribute_len = ((bytes[4] << 8) | + (bytes[5] << 0)); + + return HAL_OK; +} + +static inline hal_error_t write_header(uint8_t *bytes, const size_t bytes_len, + const uint32_t attribute_type, const size_t attribute_len) +{ + if (bytes == NULL || bytes_len < HEADER_LEN) + return HAL_ERROR_BAD_ARGUMENTS; + + bytes[0] = (attribute_type >> 24) & 0xFF; + bytes[1] = (attribute_type >> 16) & 0xFF; + bytes[2] = (attribute_type >> 8) & 0xFF; + bytes[3] = (attribute_type >> 0) & 0xFF; + bytes[4] = (attribute_len >> 8) & 0xFF; + bytes[5] = (attribute_len >> 0) & 0xFF; + + return HAL_OK; +} + +hal_error_t hal_ks_attribute_scan(const uint8_t * const bytes, const size_t bytes_len, + hal_rpc_pkey_attribute_t *attributes, const unsigned attributes_len, + size_t *total_len) +{ + if (bytes == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + const uint8_t *b = bytes; + const uint8_t * const end = bytes + bytes_len; + + for (int i = 0; i < attributes_len; i++) { + uint32_t type; + size_t length; + hal_error_t err = read_header(b, end - b, &type, &length); + if (err != HAL_OK) + return err; + b += HEADER_LEN; + if (attributes != NULL) { + attributes[i].type = type; + attributes[i].length = length; + attributes[i].value = b; + } + b += length; + if (b > end) + return HAL_ERROR_BAD_ATTRIBUTE_LENGTH; + } + + if (total_len != NULL) + *total_len = b - bytes; + + return HAL_OK; +} + +/* + * Given scan(), delete() and insert() should be relatively simple. + * + * delete() does a scan to find the attribute it wants to delete, and, + * if found, uses memmove() to copy the rest down. + * + * insert() does a delete to get rid of old value, if any, then does + * another scan, checks length what we want to insert against + * total_len returned by the scan, and either appends the new + * attribute or returns error code saying it couldn't. + */ + +hal_error_t hal_ks_attribute_delete(uint8_t *bytes, const size_t bytes_len, + hal_rpc_pkey_attribute_t *attributes, unsigned *attributes_len, + size_t *total_len, + const uint32_t type) +{ + if (bytes == NULL || attributes == NULL || attributes_len == NULL || total_len == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + int i = 0; + + while (i < *attributes_len && attributes[i].type != type) + i++; + + if (i == *attributes_len) + return HAL_OK; + + const size_t delete_length = HEADER_LEN + attributes[i].length; + const size_t delete_offset = attributes[i].value - HEADER_LEN - bytes; + + if (delete_offset + delete_length > *total_len) + return HAL_ERROR_IMPOSSIBLE; + + memmove(bytes + delete_offset, + bytes + delete_offset + delete_length, + *total_len - delete_length - delete_offset); + + *total_len -= delete_length; + + memmove(&attributes[i], &attributes[i + 1], *attributes_len - i - 1); + + --*attributes_len; + + return HAL_OK; +} + +hal_error_t hal_ks_attribute_insert(uint8_t *bytes, const size_t bytes_len, + hal_rpc_pkey_attribute_t *attributes, unsigned *attributes_len, + size_t *total_len, + const uint32_t type, + const uint8_t * const value, const size_t value_len) + +{ + if (bytes == NULL || attributes == NULL || attributes_len == NULL || + total_len == NULL || value == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + hal_error_t err + = hal_ks_attribute_delete(bytes, bytes_len, attributes, attributes_len, total_len, type); + + if (err != HAL_OK) + return err; + + if (*total_len + HEADER_LEN + value_len > bytes_len) + return HAL_ERROR_RESULT_TOO_LONG; + + uint8_t *b = bytes + *total_len; + + if ((err = write_header(b, bytes_len - *total_len, type, value_len)) != HAL_OK) + return err; + + b += HEADER_LEN; + + memcpy(b, value, value_len); + + *total_len += HEADER_LEN + value_len; + + attributes[*attributes_len].type = type; + attributes[*attributes_len].length = value_len; + attributes[*attributes_len].value = b; + + ++*attributes_len; + + return HAL_OK; +} + +/* + * Local variables: + * indent-tabs-mode: nil + * End: + */ diff --git a/ks_flash.c b/ks_flash.c index 475dcde..5b3f718 100644 --- a/ks_flash.c +++ b/ks_flash.c @@ -174,10 +174,9 @@ typedef struct { const static hal_uuid_t pin_uuid = {{0}}; /* - * The in-memory database almost certainly should be a pointer to - * allocated SDRAM rather than compile-time data space. Well, - * the arrays should be, anyway, it might be reasonable to keep - * the top level structure here. Worry about that later. + * The in-memory database structure itself is small, but the arrays it + * points to are large enough that they come from SDRAM allocated at + * startup. */ static db_t db; @@ -201,7 +200,7 @@ static inline flash_block_status_t block_get_status(const flash_block_t * const /* * Pick unused or least-recently-used slot in our in-memory cache. * - * Updating lru values is caller's problem: if caller is using cache + * Updating lru values is caller's problem: if caller is using a cache * slot as a temporary buffer and there's no point in caching the * result, leave the lru values alone and the right thing will happen. */ @@ -432,7 +431,6 @@ static hal_error_t block_erase(const unsigned blockno) /* * Erase a flash block if it hasn't already been erased. - * We have to disable fast read for this to work properly. * May not be necessary, trying to avoid unnecessary wear. * * Unclear whether there's any sane reason why this needs to be @@ -1033,6 +1031,46 @@ static hal_error_t ks_list(hal_ks_t *ks, return HAL_OK; } +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 unsigned attributes_len, + hal_uuid_t *result, + unsigned *result_len, + const unsigned result_max, + hal_uuid_t *previous_uuid) +{ +#warning NIY +} + +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) +{ +#warning NIY +} + +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) +{ +#warning NIY +} + +static hal_error_t ks_delete_attribute(hal_ks_t *ks, + hal_pkey_slot_t *slot, + const uint32_t type) +{ +#warning NIY +} + const hal_ks_driver_t hal_ks_token_driver[1] = {{ ks_init, ks_shutdown, @@ -1041,7 +1079,11 @@ const hal_ks_driver_t hal_ks_token_driver[1] = {{ ks_store, ks_fetch, ks_delete, - ks_list + ks_list, + ks_match, + ks_set_attribute, + ks_get_attribute, + ks_delete_attribute }}; /* diff --git a/ks_volatile.c b/ks_volatile.c index 29793a4..daaef41 100644 --- a/ks_volatile.c +++ b/ks_volatile.c @@ -48,12 +48,10 @@ #define HAL_STATIC_PKEY_STATE_BLOCKS 0 #endif -#ifndef HAL_STATIC_KS_VOLATILE_SLOTS -#define HAL_STATIC_KS_VOLATILE_SLOTS HAL_STATIC_PKEY_STATE_BLOCKS +#ifndef HAL_KS_VOLATILE_SLOTS +#define HAL_KS_VOLATILE_SLOTS HAL_STATIC_PKEY_STATE_BLOCKS #endif -#if HAL_STATIC_KS_VOLATILE_SLOTS > 0 - /* * In-memory keystore database. This should also be usable for * mmap(), if and when we get around to rewriting that driver (and in @@ -70,9 +68,7 @@ typedef struct { typedef struct { hal_ks_index_t ksi; - uint16_t _index[HAL_STATIC_KS_VOLATILE_SLOTS]; - hal_ks_name_t _names[HAL_STATIC_KS_VOLATILE_SLOTS]; - ks_key_t keys[HAL_STATIC_KS_VOLATILE_SLOTS]; + ks_key_t *keys; } db_t; /* @@ -87,7 +83,14 @@ typedef struct { db_t *db; /* Which memory-based keystore database */ } ks_t; -static db_t volatile_db; +/* + * If we also supported mmap, there would be a separate definition for + * HAL_KS_MMAP_SLOTS above, and the bulk of the code would be under a + * conditional testing whether either HAL_KS_*_SLOTS were nonzero. + */ + +#if HAL_KS_VOLATILE_SLOTS > 0 + static ks_t volatile_ks; static inline ks_t *ks_to_ksv(hal_ks_t *ks) @@ -95,9 +98,39 @@ static inline ks_t *ks_to_ksv(hal_ks_t *ks) return (ks_t *) ks; } -static hal_error_t ks_init(db_t *db) +static inline void *gnaw(uint8_t **mem, size_t *len, const size_t size) +{ + if (mem == NULL || *mem == NULL || len == NULL || size > *len) + return NULL; + void *ret = *mem; + *mem += size; + *len -= size; + return ret; +} + +static hal_error_t ks_init(const hal_ks_driver_t * const driver, + ks_t *ksv, + uint8_t *mem, + size_t len) { - assert(db != NULL); + if (ksv == NULL || mem == NULL) + return HAL_ERROR_IMPOSSIBLE; + + memset(ksv, 0, sizeof(*ksv)); + memset(mem, 0, len); + + if ((ksv->db = gnaw(&mem, &len, sizeof(*ksv->db))) == NULL || + (ksv->db->ksi.index = gnaw(&mem, &len, + sizeof(*ksv->db->ksi.index) * HAL_KS_VOLATILE_SLOTS)) == NULL || + (ksv->db->ksi.names = gnaw(&mem, &len, + sizeof(*ksv->db->ksi.names) * HAL_KS_VOLATILE_SLOTS)) == NULL || + (ksv->db->keys = gnaw(&mem, &len, + sizeof(*ksv->db->keys) * HAL_KS_VOLATILE_SLOTS)) == NULL) + return HAL_ERROR_IMPOSSIBLE; + + ksv->ks.driver = driver; + ksv->db->ksi.size = HAL_KS_VOLATILE_SLOTS; + ksv->db->ksi.used = 0; /* * Set up keystore with empty index and full free list. @@ -105,34 +138,31 @@ static hal_error_t ks_init(db_t *db) * just populate the free list in block numerical order. */ - db->ksi.size = HAL_STATIC_KS_VOLATILE_SLOTS; - db->ksi.used = 0; - db->ksi.index = db->_index; - db->ksi.names = db->_names; - - for (int i = 0; i < HAL_STATIC_KS_VOLATILE_SLOTS; i++) - db->_index[i] = i; + for (int i = 0; i < HAL_KS_VOLATILE_SLOTS; i++) + ksv->db->ksi.index[i] = i; - const hal_error_t err = hal_ks_index_setup(&db->ksi); - - if (err != HAL_OK) - db->ksi.size = 0; /* Mark uninitialized if setup failed */ - - return err; + return hal_ks_index_setup(&ksv->db->ksi); } static hal_error_t ks_volatile_init(const hal_ks_driver_t * const driver) { - volatile_ks.ks.driver = driver; - volatile_ks.db = &volatile_db; - return ks_init(volatile_ks.db); + const size_t len = (sizeof(*volatile_ks.db) + + sizeof(*volatile_ks.db->ksi.index) * HAL_KS_VOLATILE_SLOTS + + sizeof(*volatile_ks.db->ksi.names) * HAL_KS_VOLATILE_SLOTS + + sizeof(*volatile_ks.db->keys) * HAL_KS_VOLATILE_SLOTS); + + uint8_t *mem = hal_allocate_static_memory(len); + + if (mem == NULL) + return HAL_ERROR_ALLOCATION_FAILURE; + + return ks_init(driver, &volatile_ks, mem, len); } static hal_error_t ks_volatile_shutdown(const hal_ks_driver_t * const driver) { if (volatile_ks.ks.driver != driver) return HAL_ERROR_KEYSTORE_ACCESS; - memset(&volatile_ks, 0, sizeof(volatile_ks)); return HAL_OK; } @@ -303,6 +333,50 @@ static hal_error_t ks_list(hal_ks_t *ks, return HAL_OK; } +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 unsigned attributes_len, + hal_uuid_t *result, + unsigned *result_len, + const unsigned result_max, + hal_uuid_t *previous_uuid) +{ +#warning NIY + return HAL_ERROR_IMPOSSIBLE; +} + +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) +{ +#warning NIY + return HAL_ERROR_IMPOSSIBLE; +} + +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) +{ +#warning NIY + return HAL_ERROR_IMPOSSIBLE; +} + +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; +} + const hal_ks_driver_t hal_ks_volatile_driver[1] = {{ ks_volatile_init, ks_volatile_shutdown, @@ -311,10 +385,14 @@ const hal_ks_driver_t hal_ks_volatile_driver[1] = {{ ks_store, ks_fetch, ks_delete, - ks_list + ks_list, + ks_match, + ks_set_attribute, + ks_get_attribute, + ks_delete_attribute }}; -#endif /* HAL_STATIC_KS_VOLATILE_SLOTS > 0 */ +#endif /* HAL_KS_VOLATILE_SLOTS > 0 */ /* * Local variables: diff --git a/rpc_api.c b/rpc_api.c index a8dc89d..022dc62 100644 --- a/rpc_api.c +++ b/rpc_api.c @@ -338,6 +338,56 @@ hal_error_t hal_rpc_pkey_list(hal_pkey_info_t *result, return hal_rpc_pkey_dispatch->list(result, result_len, result_max, flags); } +hal_error_t hal_rpc_pkey_match(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 unsigned attributes_len, + hal_uuid_t *result, + unsigned *result_len, + const unsigned result_max, + hal_uuid_t *previous_uuid) +{ + if ((attributes == NULL && attributes_len > 0) || previous_uuid == NULL || + result == NULL || result_len == NULL || result_max == 0) + return HAL_ERROR_BAD_ARGUMENTS; + + if (attributes != NULL) + for (int i = 0; i < attributes_len; i++) + if (attributes[i].value == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + return hal_rpc_pkey_dispatch->match(type, curve, flags, attributes, attributes_len, + 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); +} + /* * Local variables: * indent-tabs-mode: nil diff --git a/rpc_client.c b/rpc_client.c index b4184d4..a56052d 100644 --- a/rpc_client.c +++ b/rpc_client.c @@ -740,7 +740,8 @@ static hal_error_t pkey_remote_verify(const hal_session_handle_t session, return rpc_ret; } -static hal_error_t hal_xdr_decode_pkey_info(const uint8_t **iptr, const uint8_t * const ilimit, hal_pkey_info_t *info) +static hal_error_t hal_xdr_decode_pkey_info(const uint8_t **iptr, const uint8_t * const ilimit, + hal_pkey_info_t *info) { uint32_t u32; @@ -778,10 +779,9 @@ static hal_error_t pkey_remote_list(hal_pkey_info_t *result, check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret)); if (rpc_ret == HAL_OK) { - int i; check(hal_xdr_decode_int(&iptr, ilimit, &len)); *result_len = len; - for (i = 0; i < len; ++i) { + for (int i = 0; i < len; ++i) { if ((ret = hal_xdr_decode_pkey_info(&iptr, ilimit, &result[i])) != HAL_OK) { *result_len = 0; return ret; @@ -791,6 +791,140 @@ static hal_error_t pkey_remote_list(hal_pkey_info_t *result, return rpc_ret; } +static hal_error_t pkey_remote_match(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 unsigned attributes_len, + hal_uuid_t *result, + unsigned *result_len, + const unsigned result_max, + hal_uuid_t *previous_uuid) +{ + size_t attributes_buffer_len = 0; + if (attributes != NULL) + for (int i = 0; i < attributes_len; i++) + attributes_buffer_len += attributes[i].length; + + uint8_t outbuf[nargs(8 + attributes_len * 2) + pad(attributes_buffer_len) + pad(sizeof(hal_uuid_t))]; + 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, type)); + check(hal_xdr_encode_int(&optr, olimit, curve)); + check(hal_xdr_encode_int(&optr, olimit, flags)); + check(hal_xdr_encode_int(&optr, olimit, attributes_len)); + if (attributes != NULL) { + 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_xdr_encode_int(&optr, olimit, result_max)); + check(hal_xdr_encode_buffer(&optr, olimit, previous_uuid->uuid, sizeof(previous_uuid->uuid))); + check(hal_rpc_send(outbuf, optr - outbuf)); + + check(read_matching_packet(RPC_FUNC_PKEY_MATCH, inbuf, sizeof(inbuf), &iptr, &ilimit)); + + check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) { + uint32_t array_len, uuid_len; + *result_len = 0; + check(hal_xdr_decode_int(&iptr, ilimit, &array_len)); + for (int i = 0; i < array_len; ++i) { + 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; + } + check(hal_xdr_decode_buffer(&iptr, ilimit, previous_uuid->uuid, &uuid_len)); + if (uuid_len != sizeof(previous_uuid->uuid)) + return HAL_ERROR_KEY_NAME_TOO_LONG; + *result_len = array_len; + } + 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; +} + #if RPC_CLIENT == RPC_CLIENT_MIXED /* @@ -918,7 +1052,11 @@ const hal_rpc_pkey_dispatch_t hal_rpc_remote_pkey_dispatch = { pkey_remote_get_public_key, pkey_remote_sign, pkey_remote_verify, - pkey_remote_list + pkey_remote_list, + pkey_remote_match, + pkey_remote_set_attribute, + pkey_remote_get_attribute, + pkey_remote_delete_attribute }; #if RPC_CLIENT == RPC_CLIENT_MIXED @@ -935,7 +1073,11 @@ const hal_rpc_pkey_dispatch_t hal_rpc_mixed_pkey_dispatch = { pkey_remote_get_public_key, pkey_mixed_sign, pkey_mixed_verify, - pkey_remote_list + pkey_remote_list, + pkey_remote_match, + pkey_remote_set_attribute, + pkey_remote_get_attribute, + pkey_remote_delete_attribute }; #endif /* RPC_CLIENT == RPC_CLIENT_MIXED */ diff --git a/rpc_pkey.c b/rpc_pkey.c index cf0975b..207d980 100644 --- a/rpc_pkey.c +++ b/rpc_pkey.c @@ -867,6 +867,94 @@ static hal_error_t pkey_local_list(hal_pkey_info_t *result, return err; } +static hal_error_t pkey_local_match(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 unsigned attributes_len, + hal_uuid_t *result, + unsigned *result_len, + const unsigned result_max, + hal_uuid_t *previous_uuid) +{ + hal_ks_t *ks = NULL; + hal_error_t err; + + if ((err = ks_open_from_flags(&ks, flags)) == HAL_OK && + (err = hal_ks_match(ks, type, curve, flags, attributes, attributes_len, + result, result_len, result_max, previous_uuid)) == 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_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 = 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 = 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; +} + const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch = { pkey_local_load, pkey_local_find, @@ -880,7 +968,11 @@ const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch = { pkey_local_get_public_key, pkey_local_sign, pkey_local_verify, - pkey_local_list + pkey_local_list, + pkey_local_match, + pkey_local_set_attribute, + pkey_local_get_attribute, + pkey_local_delete_attribute }; /* diff --git a/rpc_server.c b/rpc_server.c index 22e354a..5f3502f 100644 --- a/rpc_server.c +++ b/rpc_server.c @@ -560,8 +560,8 @@ static hal_error_t pkey_get_public_key(const uint8_t **iptr, const uint8_t * con return ret; } -static hal_error_t pkey_remote_sign(const uint8_t **iptr, const uint8_t * const ilimit, - uint8_t **optr, const uint8_t * const olimit) +static hal_error_t pkey_sign(const uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) { hal_client_handle_t client __attribute__((unused)); hal_session_handle_t session; @@ -596,8 +596,8 @@ static hal_error_t pkey_remote_sign(const uint8_t **iptr, const uint8_t * const return ret; } -static hal_error_t pkey_remote_verify(const uint8_t **iptr, const uint8_t * const ilimit, - uint8_t **optr, const uint8_t * const olimit) +static hal_error_t pkey_verify(const uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) { hal_client_handle_t client __attribute__((unused)); hal_session_handle_t session; @@ -655,9 +655,8 @@ static hal_error_t pkey_list(const uint8_t **iptr, const uint8_t * const ilimit, ret = hal_rpc_local_pkey_dispatch.list(result, &result_len, result_max, flags); if (ret == HAL_OK) { - int i; check(hal_xdr_encode_int(optr, olimit, result_len)); - for (i = 0; i < result_len; ++i) { + for (int i = 0; i < result_len; ++i) { if ((ret = hal_xdr_encode_pkey_info(optr, olimit, &result[i])) != HAL_OK) { *optr = optr_orig; break; @@ -668,6 +667,132 @@ static hal_error_t pkey_list(const uint8_t **iptr, const uint8_t * const ilimit, return ret; } +#warning Which RPC pkey functions take session looks kind of messed up +// list() and match() probably should take session, sign() and verify() probably should not + +static hal_error_t pkey_match(const uint8_t **iptr, const uint8_t * const ilimit, + uint8_t **optr, const uint8_t * const olimit) +{ + hal_client_handle_t client; + uint32_t type, curve, attributes_len, result_max, previous_uuid_len; + const uint8_t *previous_uuid_ptr; + hal_key_flags_t flags; + hal_error_t ret; + + check(hal_xdr_decode_int(iptr, ilimit, &client.handle)); + check(hal_xdr_decode_int(iptr, ilimit, &type)); + check(hal_xdr_decode_int(iptr, ilimit, &curve)); + check(hal_xdr_decode_int(iptr, ilimit, &flags)); + 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; + } + + check(hal_xdr_decode_int(iptr, ilimit, &result_max)); + check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &previous_uuid_ptr, &previous_uuid_len)); + + if (previous_uuid_len != sizeof(hal_uuid_t)) + return HAL_ERROR_KEY_NAME_TOO_LONG; + + hal_uuid_t result[result_max]; + unsigned result_len; + + ret = hal_rpc_local_pkey_dispatch.match(type, curve, flags, attributes, attributes_len, + result, &result_len, result_max, + (hal_uuid_t *) previous_uuid_ptr); + + if (ret == HAL_OK) { + uint8_t *optr_orig = *optr; + check(hal_xdr_encode_int(optr, olimit, result_len)); + for (int i = 0; i < result_len; ++i) { + if ((ret = hal_xdr_encode_buffer(optr, olimit, result[i].uuid, + sizeof(result[i].uuid))) != HAL_OK) { + *optr = optr_orig; + break; + } + } + } + + 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_local_pkey_dispatch.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_local_pkey_dispatch.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_local_pkey_dispatch.delete_attribute(pkey, type); + + 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) { @@ -753,14 +878,26 @@ hal_error_t hal_rpc_server_dispatch(const uint8_t * const ibuf, const size_t ile ret = pkey_get_public_key(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_PKEY_SIGN: - ret = pkey_remote_sign(&iptr, ilimit, &optr, olimit); + ret = pkey_sign(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_PKEY_VERIFY: - ret = pkey_remote_verify(&iptr, ilimit, &optr, olimit); + ret = pkey_verify(&iptr, ilimit, &optr, olimit); break; case RPC_FUNC_PKEY_LIST: ret = pkey_list(&iptr, ilimit, &optr, olimit); break; + case RPC_FUNC_PKEY_MATCH: + ret = pkey_match(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_PKEY_SET_ATTRIBUTE: + ret = pkey_set_attribute(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_PKEY_GET_ATTRIBUTE: + ret = pkey_get_attribute(&iptr, ilimit, &optr, olimit); + break; + case RPC_FUNC_PKEY_DELETE_ATTRIBUTE: + ret = pkey_delete_attribute(&iptr, ilimit, &optr, olimit); + break; default: ret = HAL_ERROR_RPC_BAD_FUNCTION; break; -- cgit v1.2.3