From c2b116a5e46ed89bf1426def0c447d2e46cc9474 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Thu, 1 Sep 2016 15:37:07 -0400 Subject: Revised keystore API, part one. Not usable yet. Changes to implement a revised keystore API. This code probably won't even compile properly yet, and almost certainly will not run, but most of the expected changes are complete at this point. Main points: * Key names are now UUIDs, and are generated by the HSM, not the client. * Keystore API no longer assumes that key database is resident in memory (original API was written on the assumption that the keystore flash would be mapped into the HSM CPU's address space, but apparently the board and flash drivers don't really support that). A few other changes have probably crept in, but the bulk of this changeset is just following through implications of the above, some of which percolate all the way back to the public RPC API. --- Makefile | 3 +- hal.h | 27 +-- hal_internal.h | 266 +++++++++++++++-------- ks_flash.c | 653 ++++++++++++++++++++++++++++++++++++++++----------------- ks_volatile.c | 269 +++++++++++++++++++----- rpc_api.c | 39 +--- rpc_client.c | 116 +++++----- rpc_pkey.c | 289 ++++++++++++++----------- rpc_server.c | 107 ++++++---- uuid.c | 75 +++++++ 10 files changed, 1241 insertions(+), 603 deletions(-) create mode 100644 uuid.c diff --git a/Makefile b/Makefile index 190466b..b9d1558 100644 --- a/Makefile +++ b/Makefile @@ -75,6 +75,7 @@ endif OBJ += errorstrings.o hash.o asn1.o ecdsa.o rsa.o ${KS_OBJ} xdr.o slip.o OBJ += rpc_api.o rpc_hash.o rpc_misc.o rpc_pkey.o rpc_client.o rpc_server.o +OBJ += uuid.o # Object files to build when we're on a platform with direct access # to our hardware (Verilog) cores. @@ -113,7 +114,7 @@ endif # Default at the moment is mmap, since that should work on the Novena # and we haven't yet written the flash code for the bridge board. -KS_OBJ = ks.o +#KS_OBJ = ks.o ifeq "${KS}" "mmap" KS_OBJ += ks_mmap.o diff --git a/hal.h b/hal.h index 9d5a32b..f6573a4 100644 --- a/hal.h +++ b/hal.h @@ -143,6 +143,7 @@ DEFINE_HAL_ERROR(HAL_ERROR_MASTERKEY_NOT_SET, "Master key (Key Encryption Key) not set") \ DEFINE_HAL_ERROR(HAL_ERROR_MASTERKEY_FAIL, "Master key generic failure") \ DEFINE_HAL_ERROR(HAL_ERROR_MASTERKEY_BAD_LENGTH, "Master key of unacceptable length") \ + DEFINE_HAL_ERROR(HAL_ERROR_KS_DRIVER_NOT_FOUND, "Keystore driver not found") \ END_OF_HAL_ERROR_LIST /* Marker to forestall silly line continuation errors */ @@ -675,7 +676,7 @@ extern hal_error_t hal_rpc_hash_finalize(const hal_hash_handle_t hash, * a session handle and which ones don't...). */ -#define HAL_RPC_PKEY_NAME_MAX 128 +typedef struct { uint8_t uuid[16]; } hal_uuid_t; typedef struct { uint32_t handle; } hal_pkey_handle_t; @@ -684,14 +685,14 @@ typedef uint32_t hal_key_flags_t; #define HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE (1 << 0) #define HAL_KEY_FLAG_USAGE_KEYENCIPHERMENT (1 << 1) #define HAL_KEY_FLAG_USAGE_DATAENCIPHERMENT (1 << 2) -#define HAL_KEY_FLAG_PROXIMATE (1 << 3) +#define HAL_KEY_FLAG_TOKEN (1 << 3) extern hal_error_t hal_rpc_pkey_load(const hal_client_handle_t client, const hal_session_handle_t session, hal_pkey_handle_t *pkey, const hal_key_type_t type, const hal_curve_name_t curve, - const uint8_t * const name, const size_t name_len, + hal_uuid_t *name, const uint8_t * const der, const size_t der_len, const hal_key_flags_t flags); @@ -699,13 +700,13 @@ extern hal_error_t hal_rpc_pkey_find(const hal_client_handle_t client, const hal_session_handle_t session, hal_pkey_handle_t *pkey, const hal_key_type_t type, - const uint8_t * const name, const size_t name_len, + const hal_uuid_t * const name, const hal_key_flags_t flags); extern hal_error_t hal_rpc_pkey_generate_rsa(const hal_client_handle_t client, const hal_session_handle_t session, hal_pkey_handle_t *pkey, - const uint8_t * const name, const size_t name_len, + hal_uuid_t *name, const unsigned key_length, const uint8_t * const public_exponent, const size_t public_exponent_len, const hal_key_flags_t flags); @@ -713,7 +714,7 @@ extern hal_error_t hal_rpc_pkey_generate_rsa(const hal_client_handle_t client, extern hal_error_t hal_rpc_pkey_generate_ec(const hal_client_handle_t client, const hal_session_handle_t session, hal_pkey_handle_t *pkey, - const uint8_t * const name, const size_t name_len, + hal_uuid_t *name, const hal_curve_name_t curve, const hal_key_flags_t flags); @@ -721,9 +722,6 @@ extern hal_error_t hal_rpc_pkey_close(const hal_pkey_handle_t pkey); extern hal_error_t hal_rpc_pkey_delete(const hal_pkey_handle_t pkey); -extern hal_error_t hal_rpc_pkey_rename(const hal_pkey_handle_t pkey, - const uint8_t * const name, const size_t name_len); - extern hal_error_t hal_rpc_pkey_get_key_type(const hal_pkey_handle_t pkey, hal_key_type_t *type); @@ -751,8 +749,7 @@ typedef struct { hal_key_type_t type; hal_curve_name_t curve; hal_key_flags_t flags; - char name[HAL_RPC_PKEY_NAME_MAX]; - size_t name_len; + hal_uuid_t name; /* ... */ } hal_pkey_info_t; @@ -762,10 +759,16 @@ extern hal_error_t hal_rpc_pkey_list(hal_pkey_info_t *result, hal_key_flags_t flags); extern hal_error_t hal_rpc_client_init(void); + extern hal_error_t hal_rpc_client_close(void); + extern hal_error_t hal_rpc_server_init(void); + extern hal_error_t hal_rpc_server_close(void); -extern hal_error_t hal_rpc_server_dispatch(const uint8_t * const ibuf, const size_t ilen, uint8_t * const obuf, size_t * const olen); + +extern hal_error_t hal_rpc_server_dispatch(const uint8_t * const ibuf, const size_t ilen, + uint8_t * const obuf, size_t * const olen); + extern void hal_rpc_server_main(void); #endif /* _HAL_H_ */ diff --git a/hal_internal.h b/hal_internal.h index 5e08c4e..ff7381f 100644 --- a/hal_internal.h +++ b/hal_internal.h @@ -36,6 +36,8 @@ #ifndef _HAL_INTERNAL_H_ #define _HAL_INTERNAL_H_ +#include + #include "hal.h" #include "verilog_constants.h" @@ -169,7 +171,7 @@ typedef struct { hal_pkey_handle_t *pkey, const hal_key_type_t type, const hal_curve_name_t curve, - const uint8_t * const name, const size_t name_len, + hal_uuid_t *name, const uint8_t * const der, const size_t der_len, const hal_key_flags_t flags); @@ -177,13 +179,13 @@ typedef struct { const hal_session_handle_t session, hal_pkey_handle_t *pkey, const hal_key_type_t type, - const uint8_t * const name, const size_t name_len, + const hal_uuid_t * const name, const hal_key_flags_t flags); hal_error_t (*generate_rsa)(const hal_client_handle_t client, const hal_session_handle_t session, hal_pkey_handle_t *pkey, - const uint8_t * const name, const size_t name_len, + hal_uuid_t *name, const unsigned key_length, const uint8_t * const public_exponent, const size_t public_exponent_len, const hal_key_flags_t flags); @@ -191,7 +193,7 @@ typedef struct { hal_error_t (*generate_ec)(const hal_client_handle_t client, const hal_session_handle_t session, hal_pkey_handle_t *pkey, - const uint8_t * const name, const size_t name_len, + hal_uuid_t *name, const hal_curve_name_t curve, const hal_key_flags_t flags); @@ -199,9 +201,6 @@ typedef struct { hal_error_t (*delete)(const hal_pkey_handle_t pkey); - hal_error_t (*rename)(const hal_pkey_handle_t pkey, - const uint8_t * const name, const size_t name_len); - hal_error_t (*get_key_type)(const hal_pkey_handle_t pkey, hal_key_type_t *key_type); @@ -241,7 +240,7 @@ extern const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch, hal_rpc_remote * See code in rpc_pkey.c for how this flag fits into the pkey handle. */ -#define HAL_PKEY_HANDLE_PROXIMATE_FLAG (1 << 31) +#define HAL_PKEY_HANDLE_TOKEN_FLAG (1 << 31) /* * Mostly used by the local_pkey code, but the mixed_pkey code needs @@ -255,15 +254,28 @@ extern hal_error_t hal_rpc_pkey_pkcs1_construct_digestinfo(const hal_hash_handle uint8_t *digest_info, size_t *digest_info_len, const size_t digest_info_max); +/* + * UUID stuff. All UUIDs we use (or are likely to use) are type 4 "random" UUIDs + */ + +static inline int hal_uuid_cmp(const hal_uuid_t * const a, const hal_uuid_t * const b) +{ + return memcmp(a, b, sizeof(hal_uuid_t)); +} + +extern hal_error_t hal_uuid_gen(hal_uuid_t *uuid); + /* * Keystore API. - * - * The original design for this subsystem used two separate tables, - * one for RSA keys, one for EC keys, because the RSA keys are so much - * larger than the EC keys. This led to unnecessarily complex and - * duplicated code, so for now we treat all keys the same, and waste - * the unneeded space in the case of EC keys. - * + */ + +/* + * The first chunk of this is stuff that's really internal to the + * keystore implementation(s), and perhaps should move to a separate + * ks_internal.h. + */ + +/* * Sizes for ASN.1-encoded keys, this may not be exact due to ASN.1 * INTEGER encoding rules but should be good enough for buffer sizing: * @@ -278,29 +290,26 @@ extern hal_error_t hal_rpc_pkey_pkcs1_construct_digestinfo(const hal_hash_handle * wrapped form (see hal_aes_keywrap_cyphertext_length()). * * We also need to store PINs somewhere, so they go into the keystore - * data structure even though they're not keys. Like keys, they're - * stored in a relatively safe form (PBKDF2), so while we would prefer - * to keep them private, they don't require tamper-protected RAM. + * even though they're not keys. Like keys, they're stored in a + * relatively safe form (PBKDF2), so while we would prefer to keep + * them private, they don't require tamper-protected RAM. */ #define HAL_KS_WRAPPED_KEYSIZE ((4655 + 15) & ~7) -#ifndef HAL_STATIC_PKEY_STATE_BLOCKS -#define HAL_STATIC_PKEY_STATE_BLOCKS 0 -#endif - -/* This struct is ordered such that all metadata appears before the +/* + * This struct is ordered such that all metadata appears before the * big buffers, in order for all metadata to be loaded with a single * page read from e.g. the ks_flash module. */ + typedef struct { hal_key_type_t type; hal_curve_name_t curve; hal_key_flags_t flags; uint8_t in_use; - size_t name_len; size_t der_len; - uint8_t name[HAL_RPC_PKEY_NAME_MAX]; + hal_uuid_t name; uint8_t der[HAL_KS_WRAPPED_KEYSIZE]; } hal_ks_key_t; @@ -314,37 +323,6 @@ typedef struct { uint8_t salt[HAL_PIN_SALT_LENGTH]; } hal_ks_pin_t; -typedef struct { - -#if HAL_STATIC_PKEY_STATE_BLOCKS > 0 - hal_ks_key_t keys[HAL_STATIC_PKEY_STATE_BLOCKS]; -#else - #warning No keys in keydb -#endif - - hal_ks_pin_t wheel_pin; - hal_ks_pin_t so_pin; - hal_ks_pin_t user_pin; - -} hal_ks_keydb_t; - -extern hal_error_t hal_set_pin_default_iterations(const hal_client_handle_t client, - const uint32_t iterations); - -/* - * Internal functions within the keystore implementation. Think of - * these as concrete methods for the keystore API subclassed onto - * various storage technologies. - */ - -extern const hal_ks_keydb_t *hal_ks_get_keydb(void); - -extern hal_error_t hal_ks_set_keydb(const hal_ks_key_t * const key, - const int loc, - const int updating); - -extern hal_error_t hal_ks_del_keydb(const int loc); - extern hal_error_t hal_ks_get_kek(uint8_t *kek, size_t *kek_len, const size_t kek_max); @@ -359,38 +337,154 @@ extern hal_error_t hal_ks_get_kek(uint8_t *kek, * Unclear whether these should also call the ASN.1 encode/decode * functions. For the moment, the answer is no, but we may need to * revisit this as the underlying Verilog API evolves. + * + * hal_pkey_slot_t is defined here too, so that keystore drivers can + * piggyback on the pkey database for storage related to keys on which + * the user currently has an active pkey handle. Nothing outside the + * pkey and keystore code should touch this. */ -extern hal_error_t hal_ks_store(const hal_key_type_t type, - const hal_curve_name_t curve, - const hal_key_flags_t flags, - const uint8_t * const name, const size_t name_len, - const uint8_t * const der, const size_t der_len, - int *hint); - -extern hal_error_t hal_ks_exists(const hal_key_type_t type, - const uint8_t * const name, const size_t name_len, - int *hint); - -extern hal_error_t hal_ks_fetch(const hal_key_type_t type, - const uint8_t * const name, const size_t name_len, - hal_curve_name_t *curve, - hal_key_flags_t *flags, - uint8_t *der, size_t *der_len, const size_t der_max, - int *hint); - -extern hal_error_t hal_ks_delete(const hal_key_type_t type, - const uint8_t * const name, const size_t name_len, - int *hint); - -extern hal_error_t hal_ks_rename(const hal_key_type_t type, - const uint8_t * const old_name, const size_t old_name_len, - const uint8_t * const new_name, const size_t new_name_len, - int *hint); - -extern hal_error_t hal_ks_list(hal_pkey_info_t *result, - unsigned *result_len, - const unsigned result_max); +typedef struct { + hal_client_handle_t client_handle; + hal_session_handle_t session_handle; + hal_pkey_handle_t pkey_handle; + hal_key_type_t type; + 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. + */ + + /* + * This might be where we'd stash a (hal_core_t *) pointing to a + * core which has already been loaded with the key, if we were + * trying to be clever about using multiple signing cores. Moot + * point (ie, no way we could possibly test such a thing) as long as + * the FPGA is too small to hold more than one modexp core and ECDSA + * is entirely software, so skip it for now, but the implied + * semantics are interesting: a pkey handle starts to resemble an + * initialized signing core, and once all the cores are in use, one + * can't load another key without closing an existing pkey handle. + */ +} hal_pkey_slot_t; + +typedef struct hal_ks_driver hal_ks_driver_t; + +typedef struct hal_ks hal_ks_t; + +struct hal_ks_driver { + + hal_error_t (*open)(const hal_ks_driver_t * const driver, + hal_ks_t **ks); + + hal_error_t (*close)(hal_ks_t *ks); + + hal_error_t (*store)(hal_ks_t *ks, + const hal_pkey_slot_t * const slot, + const uint8_t * const der, const size_t der_len); + + hal_error_t (*fetch)(hal_ks_t *ks, + hal_pkey_slot_t *slot, + 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_error_t (*list)(hal_ks_t *ks, + hal_pkey_info_t *result, + unsigned *result_len, + const unsigned result_max); +}; + + +struct hal_ks { + const hal_ks_driver_t *driver; + /* + * Any other common portions of hal_ks_t go here. + */ + + /* + * Driver-specific stuff is handled by a form of subclassing: + * driver module embeds this structure at the head of whatever + * else it needs, and performs casts as needed. + */ +}; + +extern const hal_ks_driver_t hal_ks_volatile_driver[1]; + +static inline hal_error_t hal_ks_open(const hal_ks_driver_t * const driver, + hal_ks_t **ks) +{ + if (driver == NULL || driver->open == NULL || ks == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + return driver->open(driver, ks); +} + +static inline hal_error_t hal_ks_close(hal_ks_t *ks) +{ + if (ks == NULL || ks->driver == NULL || ks->driver->close == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + return ks->driver->close(ks); +} + +static inline hal_error_t hal_ks_store(hal_ks_t *ks, + hal_pkey_slot_t *slot, + const uint8_t * const der, const size_t der_len) +{ + if (ks == NULL || ks->driver == NULL || ks->driver->store == NULL || slot == NULL || der == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + return ks->driver->store(ks, slot, der, der_len); +} + +static inline hal_error_t hal_ks_fetch(hal_ks_t *ks, + hal_pkey_slot_t *slot, + uint8_t *der, size_t *der_len, const size_t der_max) +{ + if (ks == NULL || ks->driver == NULL || ks->driver->fetch == NULL || slot == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + return ks->driver->fetch(ks, slot, der, der_len, der_max); +} + +static inline hal_error_t hal_ks_delete(hal_ks_t *ks, + hal_pkey_slot_t *slot) +{ + if (ks == NULL || ks->driver == NULL || ks->driver->delete == NULL || slot == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + return ks->driver->delete(ks, slot); +} + +static inline hal_error_t hal_ks_list(hal_ks_t *ks, + hal_pkey_info_t *result, + unsigned *result_len, + const unsigned result_max) +{ + if (ks == NULL || ks->driver == NULL || ks->driver->list == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + return ks->driver->list(ks, result, result_len, result_max); +} + +/* + * This stuff might want renaming, eg, to hal_pin_*(). + */ + +extern hal_error_t hal_set_pin_default_iterations(const hal_client_handle_t client, + const uint32_t iterations); extern hal_error_t hal_ks_get_pin(const hal_user_t user, const hal_ks_pin_t **pin); diff --git a/ks_flash.c b/ks_flash.c index 9ba342a..c51ece9 100644 --- a/ks_flash.c +++ b/ks_flash.c @@ -49,234 +49,511 @@ #define PAGE_SIZE_MASK (KEYSTORE_PAGE_SIZE - 1) /* - * Use a one-element array here so that references can be pointer-based - * as in the other implementations, to ease re-merge at some later date. + * Temporary hack: In-memory copy of entire (tiny) keystore database. + * This is backwards compatability to let us debug without changing + * too many moving parts at the same time, but will need to be + * replaced by something that can handle a much larger number of keys, + * which is one of the main points of the new keystore API. */ -static hal_ks_keydb_t db[1]; +typedef struct { + hal_ks_t ks; /* Must be first (C "subclassing") */ + + hal_ks_pin_t wheel_pin; + hal_ks_pin_t so_pin; + hal_ks_pin_t user_pin; + +#if HAL_STATIC_PKEY_STATE_BLOCKS > 0 + hal_ks_key_t keys[HAL_STATIC_PKEY_STATE_BLOCKS]; +#else +#warning No keys in keydb +#endif + +} db_t; + +static db_t db; #define FLASH_SECTOR_1_OFFSET (0 * KEYSTORE_SECTOR_SIZE) #define FLASH_SECTOR_2_OFFSET (1 * KEYSTORE_SECTOR_SIZE) -uint32_t _active_sector_offset() +static inline uint32_t _active_sector_offset() { - /* XXX Load status bytes from both sectors and decide which is current. */ - #warning Have not implemented two flash sectors yet - return FLASH_SECTOR_1_OFFSET; + /* XXX Load status bytes from both sectors and decide which is current. */ +#warning Have not implemented two flash sectors yet + return FLASH_SECTOR_1_OFFSET; } -uint32_t _get_key_offset(uint32_t num) +static inline uint32_t _get_key_offset(uint32_t num) { - /* Reserve first two pages for flash sector state, PINs and future additions. - * The three PINs alone currently occupy 3 * (64 + 16 + 4) bytes (252). - */ - uint32_t offset = KEYSTORE_PAGE_SIZE * 2; - uint32_t key_size = sizeof(*db->keys); - uint32_t bytes_per_key = KEYSTORE_PAGE_SIZE * ((key_size / KEYSTORE_PAGE_SIZE) + 1); - offset += num * bytes_per_key; - return offset; + /* + * Reserve first two pages for flash sector state, PINs and future additions. + * The three PINs alone currently occupy 3 * (64 + 16 + 4) bytes (252). + */ + uint32_t offset = KEYSTORE_PAGE_SIZE * 2; + uint32_t key_size = sizeof(*db.keys); + uint32_t bytes_per_key = KEYSTORE_PAGE_SIZE * ((key_size / KEYSTORE_PAGE_SIZE) + 1); + offset += num * bytes_per_key; + return offset; } -const hal_ks_keydb_t *hal_ks_get_keydb(void) +static hal_error_t ks_init(void) { - uint32_t offset, i, idx = 0, active_sector_offset; - hal_ks_key_t *key; - uint8_t page_buf[KEYSTORE_PAGE_SIZE]; - - memset(db, 0, sizeof(*db)); - - if (keystore_check_id() != 1) return NULL; - - active_sector_offset = _active_sector_offset(); - - /* The PINs are in the second page of the sector. */ - offset = active_sector_offset + KEYSTORE_PAGE_SIZE; - if (keystore_read_data(offset, page_buf, sizeof(page_buf)) != 1) return NULL; - offset = 0; - memcpy(&db->wheel_pin, page_buf + offset, sizeof(db->wheel_pin)); - offset += sizeof(db->wheel_pin); - memcpy(&db->so_pin, page_buf + offset, sizeof(db->so_pin)); - offset += sizeof(db->so_pin); - memcpy(&db->user_pin, page_buf + offset, sizeof(db->user_pin)); - - for (i = 0; i < sizeof(db->keys) / sizeof(*db->keys); i++) { - offset = _get_key_offset(i); - if (offset > KEYSTORE_SECTOR_SIZE) { - idx++; - continue; - } - - offset += active_sector_offset; - - if (keystore_read_data(offset, page_buf, sizeof(page_buf)) != 1) return NULL; - - key = (hal_ks_key_t *) page_buf; - if (key->in_use == 0xff) { - /* unprogrammed data */ - idx++; - continue; - } - - if (key->in_use == 1) { - uint8_t *dst = (uint8_t *) &db->keys[idx]; - uint32_t to_read = sizeof(*db->keys); - - /* We already have the first page in page_buf. Put it into place. */ - memcpy(dst, page_buf, sizeof(page_buf)); - to_read -= sizeof(page_buf); - dst += sizeof(page_buf); - - /* Read as many more full pages as possible */ - if (keystore_read_data (offset + KEYSTORE_PAGE_SIZE, dst, to_read & ~PAGE_SIZE_MASK) != 1) return NULL; - dst += to_read & ~PAGE_SIZE_MASK; - to_read &= PAGE_SIZE_MASK; - - if (to_read) { - /* Partial last page. We can only read full pages so load it into page_buf. */ - if (keystore_read_data(offset + sizeof(*db->keys) - to_read, page_buf, sizeof(page_buf)) != 1) return NULL; - memcpy(dst, page_buf, to_read); - } - } - idx++; + if (db.ks.driver == hal_ks_flash_driver) + return LIBHAL_OK; + + if (db.ks.driver != NULL) + return HAL_ERROR_IMPOSSIBLE; + + uint8_t page_buf[KEYSTORE_PAGE_SIZE]; + uint32_t idx = 0; /* Current index into db.keys[] */ + + memset(db, 0, sizeof(*db)); + + if (keystore_check_id() != 1) + return HAL_ERROR_KEYSTORE_ACCESS; + + uint32_t active_sector_offset = _active_sector_offset(); + + /* + * The PINs are in the second page of the sector. + * Caching all of these these makes some sense in any case. + */ + + uint32_t offset = active_sector_offset + KEYSTORE_PAGE_SIZE; + if (keystore_read_data(offset, page_buf, sizeof(page_buf)) != 1) + return HAL_ERROR_KEYSTORE_ACCESS; + + offset = 0; + memcpy(&db.wheel_pin, page_buf + offset, sizeof(db.wheel_pin)); + + offset += sizeof(db.wheel_pin); + memcpy(&db.so_pin, page_buf + offset, sizeof(db.so_pin)); + + offset += sizeof(db.so_pin); + memcpy(&db.user_pin, page_buf + offset, sizeof(db.user_pin)); + + /* + * Now read out all the keys. This is a temporary hack, in the long + * run we want to pull these as they're needed, although depending + * on how we organize the flash we might still need an initial scan + * on startup to build some kind of in-memory index. + */ + + for (int i = 0; i < sizeof(db.keys) / sizeof(*db.keys); i++) { + + if ((offset = _get_key_offset(i)) > KEYSTORE_SECTOR_SIZE) { + idx++; + continue; } - return db; -} + offset += active_sector_offset; -hal_error_t _write_data_to_flash(const uint32_t offset, const uint8_t *data, const size_t len) -{ - uint8_t page_buf[KEYSTORE_PAGE_SIZE]; - uint32_t to_write = len; + if (keystore_read_data(offset, page_buf, sizeof(page_buf)) != 1) + return HAL_ERROR_KEYSTORE_ACCESS; - if (keystore_write_data(offset, data, to_write & ~PAGE_SIZE_MASK) != 1) { - return HAL_ERROR_KEYSTORE_ACCESS; + const hal_ks_key_t *key = (const hal_ks_key_t *) page_buf; + + if (key->in_use == 0xff) { + /* unprogrammed data */ + idx++; + continue; } - to_write &= PAGE_SIZE_MASK; - if (to_write) { - /* Use page_buf to write the remaining bytes, since we must write a full page each time. */ - memset(page_buf, 0xff, sizeof(page_buf)); - memcpy(page_buf, data + len - to_write, to_write); - if (keystore_write_data((offset + len) & ~PAGE_SIZE_MASK, page_buf, sizeof(page_buf)) != 1) { - return HAL_ERROR_KEYSTORE_ACCESS; - } + + if (key->in_use == 1) { + uint8_t *dst = (uint8_t *) &db.keys[idx]; + uint32_t to_read = sizeof(*db.keys); + + /* We already have the first page in page_buf. Put it into place. */ + memcpy(dst, page_buf, sizeof(page_buf)); + to_read -= sizeof(page_buf); + dst += sizeof(page_buf); + + /* Read as many more full pages as possible */ + if (keystore_read_data (offset + KEYSTORE_PAGE_SIZE, dst, to_read & ~PAGE_SIZE_MASK) != 1) + return HAL_ERROR_KEYSTORE_ACCESS; + dst += to_read & ~PAGE_SIZE_MASK; + to_read &= PAGE_SIZE_MASK; + + if (to_read) { + /* Partial last page. We can only read full pages so load it into page_buf. */ + if (keystore_read_data(offset + sizeof(*db.keys) - to_read, page_buf, sizeof(page_buf)) != 1) + return HAL_ERROR_KEYSTORE_ACCESS; + memcpy(dst, page_buf, to_read); + } } + idx++; + } - return LIBHAL_OK; + db.ks.driver = hal_ks_flash_driver; + + return LIBHAL_OK; +} + +static hal_error_t _write_data_to_flash(const uint32_t offset, const uint8_t *data, const size_t len) +{ + uint8_t page_buf[KEYSTORE_PAGE_SIZE]; + uint32_t to_write = len; + + if (keystore_write_data(offset, data, to_write & ~PAGE_SIZE_MASK) != 1) + return HAL_ERROR_KEYSTORE_ACCESS; + + to_write &= PAGE_SIZE_MASK; + if (to_write) { + /* + * Use page_buf to write the remaining bytes, since we must write a full page each time. + */ + memset(page_buf, 0xff, sizeof(page_buf)); + memcpy(page_buf, data + len - to_write, to_write); + if (keystore_write_data((offset + len) & ~PAGE_SIZE_MASK, page_buf, sizeof(page_buf)) != 1) + return HAL_ERROR_KEYSTORE_ACCESS; + } + + return LIBLIBHAL_OK; } /* * Write the full DB to flash, PINs and all. */ -hal_error_t _write_db_to_flash(const uint32_t sector_offset) + +static hal_error_t _write_db_to_flash(const uint32_t sector_offset) { - hal_error_t status; - uint8_t page_buf[KEYSTORE_PAGE_SIZE]; - uint32_t i, offset; + hal_error_t status; + uint8_t page_buf[KEYSTORE_PAGE_SIZE]; + uint32_t i, offset; - if (sizeof(db->wheel_pin) + sizeof(db->so_pin) + sizeof(db->user_pin) > sizeof(page_buf)) { - return HAL_ERROR_BAD_ARGUMENTS; - } + if (sizeof(db.wheel_pin) + sizeof(db.so_pin) + sizeof(db.user_pin) > sizeof(page_buf)) + return HAL_ERROR_BAD_ARGUMENTS; - /* Put the three PINs into page_buf */ - offset = 0; - memcpy(page_buf + offset, &db->wheel_pin, sizeof(db->wheel_pin)); - offset += sizeof(db->wheel_pin); - memcpy(page_buf + offset, &db->so_pin, sizeof(db->so_pin)); - offset += sizeof(db->so_pin); - memcpy(page_buf + offset, &db->user_pin, sizeof(db->user_pin)); - - /* Write PINs into the second of the two reserved pages at the start of the sector. */ - offset = sector_offset + KEYSTORE_PAGE_SIZE; - if ((status = _write_data_to_flash(offset, page_buf, sizeof(page_buf))) != LIBHAL_OK) { - return status; - } + /* Put the three PINs into page_buf */ + offset = 0; + memcpy(page_buf + offset, &db.wheel_pin, sizeof(db.wheel_pin)); + offset += sizeof(db.wheel_pin); + memcpy(page_buf + offset, &db.so_pin, sizeof(db.so_pin)); + offset += sizeof(db.so_pin); + memcpy(page_buf + offset, &db.user_pin, sizeof(db.user_pin)); + + /* Write PINs into the second of the two reserved pages at the start of the sector. */ + offset = sector_offset + KEYSTORE_PAGE_SIZE; + if ((status = _write_data_to_flash(offset, page_buf, sizeof(page_buf))) != LIBHAL_OK) + return status; + + for (i = 0; i < sizeof(db.keys) / sizeof(*db.keys); i++) { + offset = _get_key_offset(i); + if (offset > KEYSTORE_SECTOR_SIZE) + return HAL_ERROR_BAD_ARGUMENTS; - for (i = 0; i < sizeof(db->keys) / sizeof(*db->keys); i++) { - offset = _get_key_offset(i); - if (offset > KEYSTORE_SECTOR_SIZE) { - return HAL_ERROR_BAD_ARGUMENTS; - } + offset += sector_offset; - offset += sector_offset; + if ((status =_write_data_to_flash(offset, (uint8_t *) &db.keys[i], sizeof(*db.keys))) != LIBHAL_OK) + return status; + } - if ((status =_write_data_to_flash(offset, (uint8_t *) &db->keys[i], sizeof(*db->keys))) != LIBHAL_OK) { - return status; - } - } + return LIBHAL_OK; +} - return LIBHAL_OK; +static hal_error_t ks_open(const hal_ks_driver_t * const driver, + hal_ks_t **ks) +{ + hal_error_t err; + + if (driver != hal_ks_flash_driver || ks == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + if ((err = ks_init()) != LIBHAL_OK) + return err; + + *ks = &db.ks; + return LIBHAL_OK; } -hal_error_t hal_ks_set_keydb(const hal_ks_key_t * const key, - const int loc, - const int updating) +static hal_error_t ks_close(hal_ks_t *ks) { - hal_error_t status; - uint32_t offset, active_sector_offset; - hal_ks_key_t *tmp_key; - uint8_t page_buf[KEYSTORE_PAGE_SIZE]; + if (ks != NULL && ks != &db.ks) + return HAL_ERROR_BAD_ARGUMENTS; - if (key == NULL || loc < 0 || loc >= sizeof(db->keys)/sizeof(*db->keys) || (!key->in_use != !updating)) - return HAL_ERROR_BAD_ARGUMENTS; + return LIBHAL_OK; +} - offset = _get_key_offset(loc); - if (offset > KEYSTORE_SECTOR_SIZE) return HAL_ERROR_BAD_ARGUMENTS; +static inline int acceptable_key_type(const hal_key_type_t type) +{ + switch (type) { + case HAL_KEY_TYPE_RSA_PRIVATE: + case HAL_KEY_TYPE_EC_PRIVATE: + case HAL_KEY_TYPE_RSA_PUBLIC: + case HAL_KEY_TYPE_EC_PUBLIC: + return 1; + default: + return 0; + } +} - active_sector_offset = _active_sector_offset(); +static inline hal_ks_key_t *find(const hal_key_type_t type, + const hal_uuid_t * const name) +{ + assert(name != NULL && acceptable_key_type(type)); - offset += active_sector_offset; + for (int i = 0; i < sizeof(db.keys)/sizeof(*db.keys); i++) + if (db.keys[i].in_use && db.keys[i].type == type && hal_uuid_cmp(&db.keys[i].name, name) == 0) + return &db.keys[i]; - if (keystore_check_id() != 1) return HAL_ERROR_KEYSTORE_ACCESS; + return NULL; +} - /* Check if there is a key occupying this slot in the flash already. - * Don't trust the in-memory representation since it would mean data - * corruption in flash if it had been altered. - */ - if (keystore_read_data(offset, page_buf, sizeof(page_buf)) != 1) { - return HAL_ERROR_KEYSTORE_ACCESS; - } - tmp_key = (hal_ks_key_t *) page_buf; - - db->keys[loc] = *key; - db->keys[loc].in_use = 1; - - if (tmp_key->in_use == 0xff) { - /* Key slot was unused in flash. Write the new key there. */ - if ((status = _write_data_to_flash(offset, (uint8_t *) key, sizeof(*db->keys))) != LIBHAL_OK) { - return status; - } - } else { - /* TODO: Erase and write the database to the inactive sector, and then toggle active sector. */ - if (keystore_erase_sectors(active_sector_offset / KEYSTORE_SECTOR_SIZE, - active_sector_offset / KEYSTORE_SECTOR_SIZE) != 1) { - return HAL_ERROR_KEYSTORE_ACCESS; - } - if ((status =_write_db_to_flash(active_sector_offset)) != LIBHAL_OK) { - return status; - } - } +static hal_error_t ks_fetch(hal_ks_t *ks, + hal_pkey_slot_t *slot, + uint8_t *der, size_t *der_len, const size_t der_max) +{ + if (ks != &db.ks || slot == NULL || !acceptable_key_type(slot->type)) + return HAL_ERROR_BAD_ARGUMENTS; - return LIBHAL_OK; + const hal_ks_key_t * const k = find(slot->type, &slot->name); + + if (k == NULL) + return HAL_ERROR_KEY_NOT_FOUND; + + slot->curve = k->curve; + slot->flags = k->flags; + + if (der == NULL && der_len != NULL) + *der_len = k->der_len; + + if (der != NULL) { + + uint8_t kek[KEK_LENGTH]; + size_t kek_len, der_len_; + hal_error_t err; + + if (der_len == NULL) + der_len = &der_len_; + + *der_len = der_max; + + if ((err = hal_ks_get_kek(kek, &kek_len, sizeof(kek))) == LIBHAL_OK) + err = hal_aes_keyunwrap(NULL, kek, kek_len, k->der, k->der_len, der, der_len); + + memset(kek, 0, sizeof(kek)); + + if (err != LIBHAL_OK) + return err; + } + + return LIBHAL_OK; +} + +static hal_error_t ks_list(hal_ks_t *ks, + hal_pkey_info_t *result, + unsigned *result_len, + const unsigned result_max) +{ + if (ks != &db.ks || result == NULL || result_len == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + *result_len = 0; + + for (int i = 0; i < sizeof(db.keys)/sizeof(*db.keys); i++) { + + if (!db.keys[i].in_use) + continue; + + if (*result_len == result_max) + return HAL_ERROR_RESULT_TOO_LONG; + + result[*result_len].type = db.keys[i].type; + result[*result_len].curve = db.keys[i].curve; + result[*result_len].flags = db.keys[i].flags; + result[*result_len].name = db.keys[i].name; + ++ *result_len; + } + + return LIBHAL_OK; } -hal_error_t hal_ks_del_keydb(const int loc) +/* + * This function in particular really needs to be rewritten to take + * advantage of the new keystore API. + */ + +static hal_error_t ks_store(hal_ks_t *ks, + const hal_pkey_slot_t * const slot, + const uint8_t * const der, const size_t der_len) { - uint32_t offset; + if (ks != &db.ks || slot == NULL || der == NULL || der_len == 0 || !acceptable_key_type(slot->type)) + return HAL_ERROR_BAD_ARGUMENTS; + + if (find(slot->type, &slot->name) != NULL) + return HAL_ERROR_KEY_NAME_IN_USE; + + int loc = -1; + + for (int i = 0; i < sizeof(db.keys)/sizeof(*db.keys); i++) + if (!db.keys[i].in_use && loc < 0) + loc = i; + + if (loc < 0) + return HAL_ERROR_NO_KEY_SLOTS_AVAILABLE; + + hal_ks_key_t k; + memset(&k, 0, sizeof(k)); + k.der_len = sizeof(k.der); + + uint8_t kek[KEK_LENGTH]; + size_t kek_len; + + hal_error_t err; + + if ((err = hal_ks_get_kek(kek, &kek_len, sizeof(kek))) == LIBHAL_OK) + err = hal_aes_keywrap(NULL, kek, kek_len, der, der_len, k.der, &k.der_len); - if (loc < 0 || loc >= sizeof(db->keys)/sizeof(*db->keys)) + memset(kek, 0, sizeof(kek)); + + if (err != LIBHAL_OK) + return err; + + k.name = slot->name; + k.type = slot->type; + k.curve = slot->curve; + k.flags = slot->flags; + + uint8_t page_buf[KEYSTORE_PAGE_SIZE]; + + uint32_t offset = _get_key_offset(loc); + + if (offset > KEYSTORE_SECTOR_SIZE) return HAL_ERROR_BAD_ARGUMENTS; - offset = _get_key_offset(loc); - if (offset > KEYSTORE_SECTOR_SIZE) { - return HAL_ERROR_BAD_ARGUMENTS; + uint32_t active_sector_offset = _active_sector_offset(); + + offset += active_sector_offset; + + if (keystore_check_id() != 1) + return HAL_ERROR_KEYSTORE_ACCESS; + + /* + * Check if there is a key occupying this slot in the flash already. + * This includes the case where we've zeroed a former key without + * erasing the flash sector, so we have to check the flash itself, + * we can't just look at the in-memory representation. + */ + + if (keystore_read_data(offset, page_buf, sizeof(page_buf)) != 1) + return HAL_ERROR_KEYSTORE_ACCESS; + + const int unused_since_erasure = ((hal_ks_key_t *) page_buf)->in_use == 0xFF; + + db.keys[loc] = k; + db.keys[loc].in_use = 1; + + if (unused_since_erasure) { + + /* + * Key slot was unused in flash, so we can just write the new key there. + */ + + if ((err = _write_data_to_flash(offset, (uint8_t *) &k, sizeof(k))) != LIBHAL_OK) + return err; + + } else { + + /* + * Key slot in flash has been used. We should be more clever than + * this, but for now we just rewrite the whole freaking keystore. + */ + + /* TODO: Erase and write the database to the inactive sector, and then toggle active sector. */ + + if (keystore_erase_sectors(active_sector_offset / KEYSTORE_SECTOR_SIZE, + active_sector_offset / KEYSTORE_SECTOR_SIZE) != 1) + return HAL_ERROR_KEYSTORE_ACCESS; + + if ((err =_write_db_to_flash(active_sector_offset)) != LIBHAL_OK) + return err; } + return LIBHAL_OK; +} + +static hal_error_t ks_delete(hal_ks_t *ks, + const hal_pkey_slot_t * const slot) +{ + if (ks != &db.ks || slot == NULL || !acceptable_key_type(slot->type)) + return HAL_ERROR_BAD_ARGUMENTS; + + hal_ks_key_t *k = find(slot->type, &slot->name); + + if (k == NULL) + return HAL_ERROR_KEY_NOT_FOUND; + + const int loc = k - db.keys + uint32_t offset = _get_key_offset(loc); + + if (loc < 0 || offset > KEYSTORE_SECTOR_SIZE) + return HAL_ERROR_IMPOSSIBLE; + offset += _active_sector_offset(); - memset(&db->keys[loc], 0, sizeof(*db->keys)); + memset(k, 0, sizeof(*k)); + + /* + * Setting bits to 0 never requires erasing flash. Just write it. + */ - /* Setting bits to 0 never requires erasing flash. Just write it. */ - return _write_data_to_flash(offset, (uint8_t *) &db->keys[loc], sizeof(*db->keys)); + return _write_data_to_flash(offset, (uint8_t *) k, sizeof(*k)); +} + +const hal_ks_driver_t hal_ks_flash_driver[1] = {{ + ks_flash_open, + ks_flash_close, + ks_store, + ks_fetch, + ks_delete, + ks_list +}}; + +/* + * The remaining functions aren't really part of the keystore API per se, + * but they all involve non-key data which we keep in the keystore + * because it's the flash we've got. + */ + +hal_error_t hal_ks_get_pin(const hal_user_t user, + const hal_ks_pin_t **pin) +{ + if (pin == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + hal_error_t err; + + if ((err = ks_init()) != LIBHAL_OK) + return err; + + switch (user) { + case HAL_USER_WHEEL: *pin = &db.wheel_pin; break; + case HAL_USER_SO: *pin = &db.so_pin; break; + case HAL_USER_NORMAL: *pin = &db.user_pin; break; + default: return HAL_ERROR_BAD_ARGUMENTS; + } + + /* + * If we were looking for the WHEEL PIN and it appears to be + * completely unset, return the compiled-in last-gasp PIN. This is + * a terrible answer, but we need some kind of bootstrapping + * mechanism. Feel free to suggest something better. + */ + + uint8_t u00 = 0x00, uFF = 0xFF; + for (int i = 0; i < sizeof((*pin)->pin); i++) { + u00 |= (*pin)->pin[i]; + uFF &= (*pin)->pin[i]; + } + for (int i = 0; i < sizeof((*pin)->salt); i++) { + u00 |= (*pin)->salt[i]; + uFF &= (*pin)->salt[i]; + } + if (user == HAL_USER_WHEEL && ((u00 == 0x00 && (*pin)->iterations == 0x00000000) || + (uFF == 0xFF && (*pin)->iterations == 0xFFFFFFFF))) + *pin = &hal_last_gasp_pin; + + return LIBHAL_OK; } hal_error_t hal_ks_set_pin(const hal_user_t user, @@ -290,9 +567,9 @@ hal_error_t hal_ks_set_pin(const hal_user_t user, hal_ks_pin_t *p = NULL; switch (user) { - case HAL_USER_WHEEL: p = &db->wheel_pin; break; - case HAL_USER_SO: p = &db->so_pin; break; - case HAL_USER_NORMAL: p = &db->user_pin; break; + case HAL_USER_WHEEL: p = &db.wheel_pin; break; + case HAL_USER_SO: p = &db.so_pin; break; + case HAL_USER_NORMAL: p = &db.user_pin; break; default: return HAL_ERROR_BAD_ARGUMENTS; } @@ -306,9 +583,9 @@ hal_error_t hal_ks_set_pin(const hal_user_t user, /* TODO: Erase and write the database to the inactive sector, and then toggle active sector. */ if (keystore_erase_sectors(active_sector_offset / KEYSTORE_SECTOR_SIZE, - active_sector_offset / KEYSTORE_SECTOR_SIZE) != 1) { - return HAL_ERROR_KEYSTORE_ACCESS; - } + active_sector_offset / KEYSTORE_SECTOR_SIZE) != 1) + return HAL_ERROR_KEYSTORE_ACCESS; + return _write_db_to_flash(active_sector_offset); } @@ -325,16 +602,19 @@ hal_error_t hal_ks_get_kek(uint8_t *kek, bitsToBytes(256)); hal_error_t err = masterkey_volatile_read(kek, len); + if (err == LIBHAL_OK) { - *kek_len = len; - return LIBHAL_OK; + *kek_len = len; + return LIBHAL_OK; } + if (masterkey_flash_read(kek, len) == LIBHAL_OK) { - *kek_len = len; - return LIBHAL_OK; + *kek_len = len; + return LIBHAL_OK; } - /* Both keystores returned an error, probably HAL_ERROR_MASTERKEY_NOT_SET. + /* + * Both keystores returned an error, probably HAL_ERROR_MASTERKEY_NOT_SET. * I could try to be clever and compare the errors, but really the volatile * keystore is the important one (you shouldn't store the master key in * flash), so return that error. @@ -343,7 +623,6 @@ hal_error_t hal_ks_get_kek(uint8_t *kek, } - /* * Local variables: * indent-tabs-mode: nil diff --git a/ks_volatile.c b/ks_volatile.c index 00f656a..147e6c9 100644 --- a/ks_volatile.c +++ b/ks_volatile.c @@ -7,7 +7,7 @@ * to survive library exit, eg, for storing PKCS #11 session keys. * * Authors: Rob Austein - * Copyright (c) 2015, NORDUnet A/S All rights reserved. + * Copyright (c) 2015-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 @@ -37,106 +37,267 @@ */ #include +#include #include "hal.h" #include "hal_internal.h" -/* - * Splitting the different keystore backends out into separate files - * seemed like a good idea at the time, but the code is getting - * somewhat repetitive. Might want to re-merge and conditionalize in - * some other way. Deferred until we sort out ks_flash.c. - */ +#define KEK_LENGTH (bitsToBytes(256)) + +#ifndef HAL_STATIC_PKEY_STATE_BLOCKS +#define HAL_STATIC_PKEY_STATE_BLOCKS 0 +#endif /* - * Use a one-element array here so that references can be pointer-based - * as in the other implementations, to ease re-merge at some later date. + * Keystore database itself. For the moment, we stick to the old + * model where the entire database is wrapped in a C structure. We + * may want to change this, but if so, we'll need a replacement for + * the length check. If we do decide to replace it, we may want to + * keep the C structure but replace the fixed size array with a C99 + * "flexible array", ie, + * + * hal_ks_key_t keys[]; + * + * which is like the old GCC zero-length array hack, and can only + * go at the end of the structure. */ -static hal_ks_keydb_t db[1]; +typedef struct { + + hal_ks_pin_t wheel_pin; + hal_ks_pin_t so_pin; + hal_ks_pin_t user_pin; + +#if HAL_STATIC_PKEY_STATE_BLOCKS > 0 + hal_ks_key_t keys[HAL_STATIC_PKEY_STATE_BLOCKS]; +#else +#warning No keys in keydb +#endif + +} db_t; /* - * There's no good place to store the master key (KEK) in this volatile memory implementation. - * We might be able to add a bit of protection doing things like using locked physical memory, - * as gpg does, or obfuscating the KEK a bit to make it harder to pull out of a crash dump, - * but, really, there's not a lot we can do against a determined opponant in this case. - * - * For now, we just go through the motions. + * "Subclass" (well, what one can do in C) of hal_ks_t. This is + * separate from db_t primarily to simplify things like rewriting the + * old ks_mmap driver to piggy-back on the ks_volatile driver: we + * wouldn't want the hal_ks_t into the mmap()ed file. */ -static uint8_t kekbuf[bitsToBytes(256)]; +typedef struct { + hal_ks_t ks; /* Must be first */ + db_t *db; /* Which memory-based keystore database */ +} ks_t; -const hal_ks_keydb_t *hal_ks_get_keydb(void) +static db_t volatile_db; + +static ks_t volatile_ks = { { hal_ks_volatile_driver }, &volatile_db }; + +static inline ks_t *ks_to_ksv(hal_ks_t *ks) { - return db; + return (ks_t *) ks; } -hal_error_t hal_ks_set_keydb(const hal_ks_key_t * const key, - const int loc, - const int updating) +static hal_error_t ks_volatile_open(const hal_ks_driver_t * const driver, + hal_ks_t **ks) { - if (key == NULL || loc < 0 || loc >= sizeof(db->keys)/sizeof(*db->keys) || (!key->in_use != !updating)) - return HAL_ERROR_BAD_ARGUMENTS; + assert(driver != NULL && ks != NULL); + *ks = &volatile_ks.ks; + return HAL_OK; +} - db->keys[loc] = *key; - db->keys[loc].in_use = 1; +static hal_error_t ks_volatile_close(hal_ks_t *ks) +{ return HAL_OK; } -hal_error_t hal_ks_del_keydb(const int loc) +static inline int acceptable_key_type(const hal_key_type_t type) +{ + switch (type) { + case HAL_KEY_TYPE_RSA_PRIVATE: + case HAL_KEY_TYPE_EC_PRIVATE: + case HAL_KEY_TYPE_RSA_PUBLIC: + case HAL_KEY_TYPE_EC_PUBLIC: + return 1; + default: + return 0; + } +} + +static hal_error_t ks_store(hal_ks_t *ks, + const hal_pkey_slot_t * const slot, + const uint8_t * const der, const size_t der_len) { - if (loc < 0 || loc >= sizeof(db->keys)/sizeof(*db->keys)) + if (ks == NULL || slot == NULL || der == NULL || der_len == 0 || !acceptable_key_type(slot->type)) return HAL_ERROR_BAD_ARGUMENTS; - memset(&db->keys[loc], 0, sizeof(db->keys[loc])); + ks_t *ksv = ks_to_ksv(ks); + hal_error_t err; + + if (ksv->db == NULL) + return HAL_ERROR_KEYSTORE_ACCESS; + + int loc = -1; + + for (int i = 0; i < sizeof(ksv->db->keys)/sizeof(*ksv->db->keys); i++) { + if (!ksv->db->keys[i].in_use && loc < 0) + loc = i; + if (ksv->db->keys[i].in_use && + ksv->db->keys[i].type == slot->type && + hal_uuid_cmp(&ksv->db->keys[i].name, &slot->name) == 0) + return HAL_ERROR_KEY_NAME_IN_USE; + } + + if (loc < 0) + return HAL_ERROR_NO_KEY_SLOTS_AVAILABLE; + + hal_ks_key_t k; + memset(&k, 0, sizeof(k)); + k.der_len = sizeof(k.der); + + uint8_t kek[KEK_LENGTH]; + size_t kek_len; + + if ((err = hal_ks_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); + + memset(kek, 0, sizeof(kek)); + + if (err != HAL_OK) + return err; + + k.name = slot->name; + k.type = slot->type; + k.curve = slot->curve; + k.flags = slot->flags; + + ksv->db->keys[loc] = k; + ksv->db->keys[loc].in_use = 1; + return HAL_OK; } -hal_error_t hal_ks_set_pin(const hal_user_t user, - const hal_ks_pin_t * const pin) +static hal_ks_key_t *find(ks_t *ksv, + const hal_key_type_t type, + const hal_uuid_t * const name) { - if (pin == NULL) + assert(ksv != NULL && name != NULL && acceptable_key_type(type)); + + for (int i = 0; i < sizeof(ksv->db->keys)/sizeof(*ksv->db->keys); i++) + if (ksv->db->keys[i].in_use && ksv->db->keys[i].type == type && hal_uuid_cmp(&ksv->db->keys[i].name, name) == 0) + return &ksv->db->keys[i]; + + return NULL; +} + +static hal_error_t ks_fetch(hal_ks_t *ks, + hal_pkey_slot_t *slot, + uint8_t *der, size_t *der_len, const size_t der_max) +{ + if (ks == NULL || slot == NULL || !acceptable_key_type(slot->type)) return HAL_ERROR_BAD_ARGUMENTS; - hal_ks_pin_t *p = NULL; + ks_t *ksv = ks_to_ksv(ks); + + if (ksv->db == NULL) + return HAL_ERROR_KEYSTORE_ACCESS; + + const hal_ks_key_t * const k = find(ksv, slot->type, &slot->name); + + if (k == NULL) + return HAL_ERROR_KEY_NOT_FOUND; + + slot->curve = k->curve; + slot->flags = k->flags; - switch (user) { - case HAL_USER_WHEEL: p = &db->wheel_pin; break; - case HAL_USER_SO: p = &db->so_pin; break; - case HAL_USER_NORMAL: p = &db->user_pin; break; - default: return HAL_ERROR_BAD_ARGUMENTS; + if (der == NULL && der_len != NULL) + *der_len = k->der_len; + + if (der != NULL) { + + uint8_t kek[KEK_LENGTH]; + size_t kek_len, der_len_; + hal_error_t err; + + if (der_len == NULL) + der_len = &der_len_; + + *der_len = der_max; + + if ((err = hal_ks_get_kek(kek, &kek_len, sizeof(kek))) == HAL_OK) + err = hal_aes_keyunwrap(NULL, kek, kek_len, k->der, k->der_len, der, der_len); + + memset(kek, 0, sizeof(kek)); + + if (err != HAL_OK) + return err; } - *p = *pin; return HAL_OK; } -hal_error_t hal_ks_get_kek(uint8_t *kek, - size_t *kek_len, - const size_t kek_max) +static hal_error_t ks_delete(hal_ks_t *ks, + const hal_pkey_slot_t * const slot) { - if (kek == NULL || kek_len == NULL || kek_max < bitsToBytes(128)) + if (ks == NULL || slot == NULL || !acceptable_key_type(slot->type)) return HAL_ERROR_BAD_ARGUMENTS; - hal_error_t err; + ks_t *ksv = ks_to_ksv(ks); - const size_t len = ((kek_max < bitsToBytes(192)) ? bitsToBytes(128) : - (kek_max < bitsToBytes(256)) ? bitsToBytes(192) : - bitsToBytes(256)); + if (ksv->db == NULL) + return HAL_ERROR_KEYSTORE_ACCESS; - uint8_t t = 0; + hal_ks_key_t *k = find(ksv, slot->type, &slot->name); - for (int i = 0; i < sizeof(kekbuf); i++) - t |= kekbuf[i]; + if (k == NULL) + return HAL_ERROR_KEY_NOT_FOUND; - if (t == 0 && (err = hal_rpc_get_random(kekbuf, sizeof(kekbuf))) != HAL_OK) - return err; + memset(k, 0, sizeof(*k)); + + return HAL_OK; +} + +static hal_error_t ks_list(hal_ks_t *ks, + hal_pkey_info_t *result, + unsigned *result_len, + const unsigned result_max) +{ + if (ks == NULL || result == NULL || result_len == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + ks_t *ksv = ks_to_ksv(ks); + + if (ksv->db == NULL) + return HAL_ERROR_KEYSTORE_ACCESS; + + *result_len = 0; + + for (int i = 0; i < sizeof(ksv->db->keys)/sizeof(*ksv->db->keys); i++) { + + if (!ksv->db->keys[i].in_use) + continue; + + if (*result_len == result_max) + return HAL_ERROR_RESULT_TOO_LONG; + + result[*result_len].type = ksv->db->keys[i].type; + result[*result_len].curve = ksv->db->keys[i].curve; + result[*result_len].flags = ksv->db->keys[i].flags; + result[*result_len].name = ksv->db->keys[i].name; + ++ *result_len; + } - memcpy(kek, kekbuf, len); - *kek_len = len; return HAL_OK; } +const hal_ks_driver_t hal_ks_volatile_driver[1] = {{ + ks_volatile_open, + ks_volatile_close, + ks_store, + ks_fetch, + ks_delete, + ks_list +}}; + /* * Local variables: * indent-tabs-mode: nil diff --git a/rpc_api.c b/rpc_api.c index a19bdb4..2fe7e63 100644 --- a/rpc_api.c +++ b/rpc_api.c @@ -75,7 +75,7 @@ static inline int check_pkey_flags(const hal_key_flags_t flags) return (flags &~ (HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE | HAL_KEY_FLAG_USAGE_KEYENCIPHERMENT | HAL_KEY_FLAG_USAGE_DATAENCIPHERMENT | - HAL_KEY_FLAG_PROXIMATE)) == 0; + HAL_KEY_FLAG_TOKEN)) == 0; } static inline int check_pkey_type_curve_flags(const hal_key_type_t type, @@ -218,36 +218,31 @@ hal_error_t hal_rpc_pkey_load(const hal_client_handle_t client, hal_pkey_handle_t *pkey, const hal_key_type_t type, const hal_curve_name_t curve, - const uint8_t * const name, const size_t name_len, + hal_uuid_t *name, const uint8_t * const der, const size_t der_len, const hal_key_flags_t flags) { - if (pkey == NULL || name == NULL || der == NULL || der_len == 0 || - !check_pkey_type_curve_flags(type, curve, flags)) + if (pkey == NULL || name == NULL || der == NULL || der_len == 0 || !check_pkey_type_curve_flags(type, curve, flags)) return HAL_ERROR_BAD_ARGUMENTS; - if (name_len > HAL_RPC_PKEY_NAME_MAX) - return HAL_ERROR_KEY_NAME_TOO_LONG; - return hal_rpc_pkey_dispatch->load(client, session, pkey, type, curve, name, name_len, der, der_len, flags); + return hal_rpc_pkey_dispatch->load(client, session, pkey, type, curve, name, der, der_len, flags); } hal_error_t hal_rpc_pkey_find(const hal_client_handle_t client, const hal_session_handle_t session, hal_pkey_handle_t *pkey, const hal_key_type_t type, - const uint8_t * const name, const size_t name_len, + const hal_uuid_t * const name, const hal_key_flags_t flags) { if (pkey == NULL || name == NULL || !check_pkey_type(type)) return HAL_ERROR_BAD_ARGUMENTS; - if (name_len > HAL_RPC_PKEY_NAME_MAX) - return HAL_ERROR_KEY_NAME_TOO_LONG; - return hal_rpc_pkey_dispatch->find(client, session, pkey, type, name, name_len, flags); + return hal_rpc_pkey_dispatch->find(client, session, pkey, type, name, flags); } hal_error_t hal_rpc_pkey_generate_rsa(const hal_client_handle_t client, const hal_session_handle_t session, hal_pkey_handle_t *pkey, - const uint8_t * const name, const size_t name_len, + hal_uuid_t *name, const unsigned key_len, const uint8_t * const exp, const size_t exp_len, const hal_key_flags_t flags) @@ -255,24 +250,20 @@ hal_error_t hal_rpc_pkey_generate_rsa(const hal_client_handle_t client, if (pkey == NULL || name == NULL || key_len == 0 || (key_len & 7) != 0 || exp == NULL || exp_len == 0 || !check_pkey_flags(flags)) return HAL_ERROR_BAD_ARGUMENTS; - if (name_len > HAL_RPC_PKEY_NAME_MAX) - return HAL_ERROR_KEY_NAME_TOO_LONG; - return hal_rpc_pkey_dispatch->generate_rsa(client, session, pkey, name, name_len, key_len, exp, exp_len, flags); + return hal_rpc_pkey_dispatch->generate_rsa(client, session, pkey, name, key_len, exp, exp_len, flags); } hal_error_t hal_rpc_pkey_generate_ec(const hal_client_handle_t client, const hal_session_handle_t session, hal_pkey_handle_t *pkey, - const uint8_t * const name, const size_t name_len, + hal_uuid_t *name, const hal_curve_name_t curve, const hal_key_flags_t flags) { if (pkey == NULL || name == NULL || !check_pkey_type_curve_flags(HAL_KEY_TYPE_EC_PRIVATE, curve, flags)) return HAL_ERROR_BAD_ARGUMENTS; - if (name_len > HAL_RPC_PKEY_NAME_MAX) - return HAL_ERROR_KEY_NAME_TOO_LONG; - return hal_rpc_pkey_dispatch->generate_ec(client, session, pkey, name, name_len, curve, flags); + return hal_rpc_pkey_dispatch->generate_ec(client, session, pkey, name, curve, flags); } hal_error_t hal_rpc_pkey_close(const hal_pkey_handle_t pkey) @@ -285,16 +276,6 @@ hal_error_t hal_rpc_pkey_delete(const hal_pkey_handle_t pkey) return hal_rpc_pkey_dispatch->delete(pkey); } -hal_error_t hal_rpc_pkey_rename(const hal_pkey_handle_t pkey, - const uint8_t * const name, const size_t name_len) -{ - if (name == NULL) - return HAL_ERROR_BAD_ARGUMENTS; - if (name_len > HAL_RPC_PKEY_NAME_MAX) - return HAL_ERROR_KEY_NAME_TOO_LONG; - return hal_rpc_pkey_dispatch->rename(pkey, name, name_len); -} - hal_error_t hal_rpc_pkey_get_key_type(const hal_pkey_handle_t pkey, hal_key_type_t *type) { diff --git a/rpc_client.c b/rpc_client.c index a952a6e..98d6abe 100644 --- a/rpc_client.c +++ b/rpc_client.c @@ -411,13 +411,14 @@ static hal_error_t pkey_remote_load(const hal_client_handle_t client, hal_pkey_handle_t *pkey, const hal_key_type_t type, const hal_curve_name_t curve, - const uint8_t * const name, const size_t name_len, + hal_uuid_t *name, const uint8_t * const der, const size_t der_len, const hal_key_flags_t flags) { - uint8_t outbuf[nargs(8) + pad(name_len) + pad(der_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); - uint8_t inbuf[nargs(4)]; + uint8_t outbuf[nargs(7) + pad(der_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[nargs(5) + pad(sizeof(name->uuid))]; const uint8_t *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + uint32_t name_len = sizeof(name->uuid); hal_error_t rpc_ret; check(hal_xdr_encode_int(&optr, olimit, RPC_FUNC_PKEY_LOAD)); @@ -425,7 +426,6 @@ static hal_error_t pkey_remote_load(const hal_client_handle_t client, 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)); - check(hal_xdr_encode_buffer(&optr, olimit, name, name_len)); check(hal_xdr_encode_buffer(&optr, olimit, der, der_len)); check(hal_xdr_encode_int(&optr, olimit, flags)); check(hal_rpc_send(outbuf, optr - outbuf)); @@ -433,8 +433,13 @@ static hal_error_t pkey_remote_load(const hal_client_handle_t client, check(read_matching_packet(RPC_FUNC_PKEY_LOAD, inbuf, sizeof(inbuf), &iptr, &ilimit)); check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret)); - if (rpc_ret == HAL_OK) + + if (rpc_ret == HAL_OK) { check(hal_xdr_decode_int(&iptr, ilimit, &pkey->handle)); + check(hal_xdr_decode_buffer(&iptr, ilimit, name->uuid, &name_len)); + if (name_len != sizeof(name->uuid)) + return HAL_ERROR_KEY_NAME_TOO_LONG; + } return rpc_ret; } @@ -443,10 +448,10 @@ static hal_error_t pkey_remote_find(const hal_client_handle_t client, const hal_session_handle_t session, hal_pkey_handle_t *pkey, const hal_key_type_t type, - const uint8_t * const name, const size_t name_len, + const hal_uuid_t * const name, const hal_key_flags_t flags) { - uint8_t outbuf[nargs(6) + pad(name_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t outbuf[nargs(6) + pad(sizeof(name->uuid))], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); uint8_t inbuf[nargs(4)]; const uint8_t *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); hal_error_t rpc_ret; @@ -455,13 +460,14 @@ static hal_error_t pkey_remote_find(const hal_client_handle_t client, 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_buffer(&optr, olimit, name, name_len)); + check(hal_xdr_encode_buffer(&optr, olimit, name->uuid, sizeof(name->uuid))); check(hal_xdr_encode_int(&optr, olimit, flags)); check(hal_rpc_send(outbuf, optr - outbuf)); check(read_matching_packet(RPC_FUNC_PKEY_FIND, inbuf, sizeof(inbuf), &iptr, &ilimit)); check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret)); + if (rpc_ret == HAL_OK) check(hal_xdr_decode_int(&iptr, ilimit, &pkey->handle)); @@ -471,20 +477,20 @@ static hal_error_t pkey_remote_find(const hal_client_handle_t client, static hal_error_t pkey_remote_generate_rsa(const hal_client_handle_t client, const hal_session_handle_t session, hal_pkey_handle_t *pkey, - const uint8_t * const name, const size_t name_len, + hal_uuid_t *name, const unsigned key_len, const uint8_t * const exp, const size_t exp_len, const hal_key_flags_t flags) { - uint8_t outbuf[nargs(7) + pad(name_len) + pad(exp_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); - uint8_t inbuf[nargs(4)]; + uint8_t outbuf[nargs(6) + pad(exp_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[nargs(5) + pad(sizeof(name->uuid))]; const uint8_t *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + uint32_t name_len = sizeof(name->uuid); hal_error_t rpc_ret; check(hal_xdr_encode_int(&optr, olimit, RPC_FUNC_PKEY_GENERATE_RSA)); check(hal_xdr_encode_int(&optr, olimit, client.handle)); check(hal_xdr_encode_int(&optr, olimit, session.handle)); - check(hal_xdr_encode_buffer(&optr, olimit, name, name_len)); check(hal_xdr_encode_int(&optr, olimit, key_len)); check(hal_xdr_encode_buffer(&optr, olimit, exp, exp_len)); check(hal_xdr_encode_int(&optr, olimit, flags)); @@ -493,8 +499,13 @@ static hal_error_t pkey_remote_generate_rsa(const hal_client_handle_t client, check(read_matching_packet(RPC_FUNC_PKEY_GENERATE_RSA, inbuf, sizeof(inbuf), &iptr, &ilimit)); check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret)); - if (rpc_ret == HAL_OK) + + if (rpc_ret == HAL_OK) { check(hal_xdr_decode_int(&iptr, ilimit, &pkey->handle)); + check(hal_xdr_decode_buffer(&iptr, ilimit, name->uuid, &name_len)); + if (name_len != sizeof(name->uuid)) + return HAL_ERROR_KEY_NAME_TOO_LONG; + } return rpc_ret; } @@ -502,19 +513,19 @@ static hal_error_t pkey_remote_generate_rsa(const hal_client_handle_t client, static hal_error_t pkey_remote_generate_ec(const hal_client_handle_t client, const hal_session_handle_t session, hal_pkey_handle_t *pkey, - const uint8_t * const name, const size_t name_len, + hal_uuid_t *name, const hal_curve_name_t curve, const hal_key_flags_t flags) { - uint8_t outbuf[nargs(6) + pad(name_len)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); - uint8_t inbuf[nargs(4)]; + uint8_t outbuf[nargs(5)], *optr = outbuf, *olimit = outbuf + sizeof(outbuf); + uint8_t inbuf[nargs(5) + pad(sizeof(name->uuid))]; const uint8_t *iptr = inbuf, *ilimit = inbuf + sizeof(inbuf); + uint32_t name_len = sizeof(name->uuid); hal_error_t rpc_ret; check(hal_xdr_encode_int(&optr, olimit, RPC_FUNC_PKEY_GENERATE_EC)); check(hal_xdr_encode_int(&optr, olimit, client.handle)); check(hal_xdr_encode_int(&optr, olimit, session.handle)); - check(hal_xdr_encode_buffer(&optr, olimit, name, name_len)); check(hal_xdr_encode_int(&optr, olimit, curve)); check(hal_xdr_encode_int(&optr, olimit, flags)); check(hal_rpc_send(outbuf, optr - outbuf)); @@ -522,8 +533,13 @@ static hal_error_t pkey_remote_generate_ec(const hal_client_handle_t client, check(read_matching_packet(RPC_FUNC_PKEY_GENERATE_EC, inbuf, sizeof(inbuf), &iptr, &ilimit)); check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret)); - if (rpc_ret == HAL_OK) + + if (rpc_ret == HAL_OK) { check(hal_xdr_decode_int(&iptr, ilimit, &pkey->handle)); + check(hal_xdr_decode_buffer(&iptr, ilimit, name->uuid, &name_len)); + if (name_len != sizeof(name->uuid)) + return HAL_ERROR_KEY_NAME_TOO_LONG; + } return rpc_ret; } @@ -566,28 +582,6 @@ static hal_error_t pkey_remote_delete(const hal_pkey_handle_t pkey) return rpc_ret; } -static hal_error_t pkey_remote_rename(const hal_pkey_handle_t pkey, - const uint8_t * const name, const size_t name_len) -{ - uint8_t outbuf[nargs(4) + pad(name_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_RENAME)); - check(hal_xdr_encode_int(&optr, olimit, dummy_client.handle)); - check(hal_xdr_encode_int(&optr, olimit, pkey.handle)); - check(hal_xdr_encode_buffer(&optr, olimit, name, name_len)); - check(hal_rpc_send(outbuf, optr - outbuf)); - - check(read_matching_packet(RPC_FUNC_PKEY_RENAME, inbuf, sizeof(inbuf), &iptr, &ilimit)); - - check(hal_xdr_decode_int(&iptr, ilimit, &rpc_ret)); - return rpc_ret; -} - - static hal_error_t pkey_remote_get_key_type(const hal_pkey_handle_t pkey, hal_key_type_t *type) { @@ -750,12 +744,17 @@ static hal_error_t pkey_remote_verify(const hal_session_handle_t session, 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 i32; + uint32_t u32; + + check(hal_xdr_decode_int(iptr, ilimit, &u32)); info->type = u32; + check(hal_xdr_decode_int(iptr, ilimit, &u32)); info->curve = u32; + check(hal_xdr_decode_int(iptr, ilimit, &u32)); info->flags = u32; + + u32 = sizeof(info->name.uuid); + check(hal_xdr_decode_buffer(iptr, ilimit, info->name.uuid, &u32)); + if (u32 != sizeof(info->name.uuid)) + return HAL_ERROR_KEY_NAME_TOO_LONG; - check(hal_xdr_decode_int(iptr, ilimit, &i32)); info->type = i32; - check(hal_xdr_decode_int(iptr, ilimit, &i32)); info->curve = i32; - check(hal_xdr_decode_int(iptr, ilimit, &i32)); info->flags = i32; - check(hal_xdr_decode_buffer(iptr, ilimit, (uint8_t *)&info->name[0], &i32)); info->name_len = i32; return HAL_OK; } @@ -907,46 +906,43 @@ static hal_error_t pkey_mixed_load(const hal_client_handle_t client, hal_pkey_handle_t *pkey, const hal_key_type_t type, const hal_curve_name_t curve, - const uint8_t * const name, const size_t name_len, + hal_uuid_t *name, const uint8_t * const der, const size_t der_len, const hal_key_flags_t flags) { - return mixed_flags_dispatch(flags)->load(client, session, pkey, type, curve, - name, name_len, der, der_len, flags); + return mixed_flags_dispatch(flags)->load(client, session, pkey, type, curve, name, der, der_len, flags); } static hal_error_t pkey_mixed_find(const hal_client_handle_t client, const hal_session_handle_t session, hal_pkey_handle_t *pkey, const hal_key_type_t type, - const uint8_t * const name, const size_t name_len, + const hal_uuid_t * const name, const hal_key_flags_t flags) { - return mixed_flags_dispatch(flags)->find(client, session, pkey, type, - name, name_len, flags); + return mixed_flags_dispatch(flags)->find(client, session, pkey, type, name, flags); } static hal_error_t pkey_mixed_generate_rsa(const hal_client_handle_t client, const hal_session_handle_t session, hal_pkey_handle_t *pkey, - const uint8_t * const name, const size_t name_len, + hal_uuid_t *name, const unsigned key_length, const uint8_t * const public_exponent, const size_t public_exponent_len, const hal_key_flags_t flags) { - return mixed_flags_dispatch(flags)->generate_rsa(client, session, pkey, - name, name_len, key_length, + return mixed_flags_dispatch(flags)->generate_rsa(client, session, pkey, name, key_length, public_exponent, public_exponent_len, flags); } static hal_error_t pkey_mixed_generate_ec(const hal_client_handle_t client, const hal_session_handle_t session, hal_pkey_handle_t *pkey, - const uint8_t * const name, const size_t name_len, + hal_uuid_t *name, const hal_curve_name_t curve, const hal_key_flags_t flags) { - return mixed_flags_dispatch(flags)->generate_ec(client, session, pkey, name, name_len, curve, flags); + return mixed_flags_dispatch(flags)->generate_ec(client, session, pkey, name, curve, flags); } static hal_error_t pkey_mixed_close(const hal_pkey_handle_t pkey) @@ -959,12 +955,6 @@ static hal_error_t pkey_mixed_delete(const hal_pkey_handle_t pkey) return mixed_handle_dispatch(pkey)->delete(pkey); } -static hal_error_t pkey_mixed_rename(const hal_pkey_handle_t pkey, - const uint8_t * const name, const size_t name_len) -{ - return mixed_handle_dispatch(pkey)->rename(pkey, name, name_len); -} - static hal_error_t pkey_mixed_get_key_type(const hal_pkey_handle_t pkey, hal_key_type_t *key_type) { @@ -1027,7 +1017,6 @@ const hal_rpc_pkey_dispatch_t hal_rpc_remote_pkey_dispatch = { pkey_remote_generate_ec, pkey_remote_close, pkey_remote_delete, - pkey_remote_rename, pkey_remote_get_key_type, pkey_remote_get_key_flags, pkey_remote_get_public_key_len, @@ -1045,7 +1034,6 @@ const hal_rpc_pkey_dispatch_t hal_rpc_mixed_pkey_dispatch = { pkey_mixed_generate_ec, pkey_mixed_close, pkey_mixed_delete, - pkey_mixed_rename, pkey_mixed_get_key_type, pkey_mixed_get_key_flags, pkey_mixed_get_public_key_len, diff --git a/rpc_pkey.c b/rpc_pkey.c index d6efbe7..6de3a9b 100644 --- a/rpc_pkey.c +++ b/rpc_pkey.c @@ -39,35 +39,12 @@ #include "hal.h" #include "hal_internal.h" -typedef struct { - hal_client_handle_t client_handle; - hal_session_handle_t session_handle; - hal_pkey_handle_t pkey_handle; - hal_key_type_t type; - hal_curve_name_t curve; - hal_key_flags_t flags; - uint8_t name[HAL_RPC_PKEY_NAME_MAX]; - size_t name_len; - int ks_hint; - /* - * This might be where we'd stash a (hal_core_t *) pointing to a - * core which has already been loaded with the key, if we were - * trying to be clever about using multiple signing cores. Moot - * point (ie, no way we could possibly test such a thing) as long as - * the FPGA is too small to hold more than one modexp core and ECDSA - * is entirely software, so skip it for now, but the implied - * semantics are interesting: a pkey handle starts to resemble an - * initialized signing core, and once all the cores are in use, one - * can't load another key without closing an existing pkey handle. - */ -} pkey_slot_t; - #ifndef HAL_STATIC_PKEY_STATE_BLOCKS #define HAL_STATIC_PKEY_STATE_BLOCKS 0 #endif #if HAL_STATIC_PKEY_STATE_BLOCKS > 0 -static pkey_slot_t pkey_handle[HAL_STATIC_PKEY_STATE_BLOCKS]; +static hal_pkey_slot_t pkey_handle[HAL_STATIC_PKEY_STATE_BLOCKS]; #endif /* @@ -82,23 +59,23 @@ static pkey_slot_t pkey_handle[HAL_STATIC_PKEY_STATE_BLOCKS]; * handlers to route calls to the appropriate destination. */ -static inline pkey_slot_t *alloc_slot(const hal_key_flags_t flags) +static inline hal_pkey_slot_t *alloc_slot(const hal_key_flags_t flags) { #if HAL_STATIC_PKEY_STATE_BLOCKS > 0 static uint16_t next_glop = 0; uint32_t glop = ++next_glop << 16; next_glop %= 0x7FFF; - assert((glop & HAL_PKEY_HANDLE_PROXIMATE_FLAG) == 0); + assert((glop & HAL_PKEY_HANDLE_TOKEN_FLAG) == 0); - if ((flags & HAL_KEY_FLAG_PROXIMATE) != 0) - glop |= HAL_PKEY_HANDLE_PROXIMATE_FLAG; + if ((flags & HAL_KEY_FLAG_TOKEN) != 0) + glop |= HAL_PKEY_HANDLE_TOKEN_FLAG; for (int i = 0; i < sizeof(pkey_handle)/sizeof(*pkey_handle); i++) { if (pkey_handle[i].type != HAL_KEY_TYPE_NONE) continue; + memset(&pkey_handle[i], 0, sizeof(pkey_handle[i])); pkey_handle[i].pkey_handle.handle = i | glop; - pkey_handle[i].ks_hint = -1; return &pkey_handle[i]; } #endif @@ -111,7 +88,7 @@ static inline pkey_slot_t *alloc_slot(const hal_key_flags_t flags) * the right glop. Returns slot pointer on success, NULL otherwise. */ -static inline pkey_slot_t *find_handle(const hal_pkey_handle_t handle) +static inline hal_pkey_slot_t *find_handle(const hal_pkey_handle_t handle) { #if HAL_STATIC_PKEY_STATE_BLOCKS > 0 const int i = (int) (handle.handle & 0xFFFF); @@ -129,12 +106,10 @@ static inline pkey_slot_t *find_handle(const hal_pkey_handle_t handle) * Need to check detailed PKCS #11 rules, but, from memory, we may be supposed to allow * access to non-token objects even when not logged in. Maybe. Rules are complex. * - * I think the libhal translation of this resolves around what we've - * been calling the PROXIMATE flags (which probably ought to be - * renamed to *_NONTOKEN_*, slightly less confusing name). For token - * objects, we insist on being logged in properly; for non-token - * objects, we do whatever silly thing PKCS #11 wants us to do, - * probably defaulting to requiring login if PKCS #11 gives us a choice. + * I think the libhal translation of this resolves around HAL_KEY_FLAG_TOKEN. + * For token objects, we insist on being logged in properly; for non-token + * objects, we do whatever silly thing PKCS #11 wants us to do, probably + * defaulting to requiring login if PKCS #11 gives us a choice. */ /* @@ -222,6 +197,27 @@ static hal_error_t pkcs1_5_pad(const uint8_t * const data, const size_t data_len return HAL_OK; } +/* + * Given key flags, open appropriate keystore driver. + */ + +static inline hal_error_t ks_open_from_flags(hal_ks_t **ks, const hal_key_flags_t flags) +{ + if ((flags & HAL_KEY_FLAG_TOKEN) == 0) + return hal_ks_open(hal_ks_volatile_driver, ks); + +#if 0 + + return hal_ks_open(hal_ks_token_driver, ks); + +#else +#warning This needs to open hal_ks_token_driver here, once we get around to writing that driver + + return HAL_ERROR_KS_DRIVER_NOT_FOUND; + +#endif +} + /* * Receive key from application, store it with supplied name, return a key handle. */ @@ -231,30 +227,39 @@ static hal_error_t pkey_local_load(const hal_client_handle_t client, hal_pkey_handle_t *pkey, const hal_key_type_t type, const hal_curve_name_t curve, - const uint8_t * const name, const size_t name_len, + hal_uuid_t *name, const uint8_t * const der, const size_t der_len, const hal_key_flags_t flags) { - pkey_slot_t *slot; - hal_error_t err; + assert(pkey != NULL && name != NULL); - assert(sizeof(slot->name) >= name_len && pkey != NULL); + hal_pkey_slot_t *slot; + hal_ks_t *ks = NULL; + hal_error_t err; if ((slot = alloc_slot(flags)) == NULL) return HAL_ERROR_NO_KEY_SLOTS_AVAILABLE; - if ((err = hal_ks_store(type, curve, flags, name, name_len, der, der_len, &slot->ks_hint)) != HAL_OK) + if ((err = hal_uuid_gen(&slot->name)) != HAL_OK) return err; - memcpy(slot->name, name, name_len); slot->client_handle = client; slot->session_handle = session; slot->type = type; slot->curve = curve; slot->flags = flags; - slot->name_len = name_len; + + if ((err = ks_open_from_flags(&ks, flags)) == HAL_OK && + (err = hal_ks_store(ks, slot, der, der_len)) == HAL_OK) + err = hal_ks_close(ks); + else if (ks != NULL) + (void) hal_ks_close(ks); + + if (err != HAL_OK) + return err; *pkey = slot->pkey_handle; + *name = slot->name; return HAL_OK; } @@ -266,25 +271,31 @@ static hal_error_t pkey_local_find(const hal_client_handle_t client, const hal_session_handle_t session, hal_pkey_handle_t *pkey, const hal_key_type_t type, - const uint8_t * const name, const size_t name_len, + const hal_uuid_t * const name, const hal_key_flags_t flags) { - pkey_slot_t *slot; - hal_error_t err; + assert(pkey != NULL && name != NULL); - assert(sizeof(slot->name) >= name_len && pkey != NULL); + hal_pkey_slot_t *slot; + hal_ks_t *ks = NULL; + hal_error_t err; if ((slot = alloc_slot(flags)) == NULL) return HAL_ERROR_NO_KEY_SLOTS_AVAILABLE; - if ((err = hal_ks_fetch(type, name, name_len, &slot->curve, &slot->flags, NULL, NULL, 0, &slot->ks_hint)) != HAL_OK) - return err; - - memcpy(slot->name, name, name_len); + slot->name = *name; slot->client_handle = client; slot->session_handle = session; slot->type = type; - slot->name_len = name_len; + + if ((err = ks_open_from_flags(&ks, flags)) == HAL_OK && + (err = hal_ks_fetch(ks, slot, NULL, NULL, 0)) == HAL_OK) + err = hal_ks_close(ks); + else if (ks != NULL) + (void) hal_ks_close(ks); + + if (err != HAL_OK) + return err; *pkey = slot->pkey_handle; return HAL_OK; @@ -297,21 +308,30 @@ static hal_error_t pkey_local_find(const hal_client_handle_t client, static hal_error_t pkey_local_generate_rsa(const hal_client_handle_t client, const hal_session_handle_t session, hal_pkey_handle_t *pkey, - const uint8_t * const name, const size_t name_len, + hal_uuid_t *name, const unsigned key_length, const uint8_t * const public_exponent, const size_t public_exponent_len, const hal_key_flags_t flags) { - pkey_slot_t *slot; - hal_error_t err; + assert(pkey != NULL && name != NULL && (key_length & 7) == 0); - assert(sizeof(slot->name) >= name_len && pkey != NULL && (key_length & 7) == 0); + uint8_t keybuf[hal_rsa_key_t_size]; + hal_rsa_key_t *key = NULL; + hal_pkey_slot_t *slot; + hal_ks_t *ks = NULL; + hal_error_t err; if ((slot = alloc_slot(flags)) == NULL) return HAL_ERROR_NO_KEY_SLOTS_AVAILABLE; - uint8_t keybuf[hal_rsa_key_t_size]; - hal_rsa_key_t *key = NULL; + if ((err = hal_uuid_gen(&slot->name)) != HAL_OK) + return err; + + slot->client_handle = client; + slot->session_handle = session; + slot->type = HAL_KEY_TYPE_RSA_PRIVATE; + slot->curve = HAL_CURVE_NONE; + slot->flags = flags; if ((err = hal_rsa_key_gen(NULL, &key, keybuf, sizeof(keybuf), key_length / 8, public_exponent, public_exponent_len)) != HAL_OK) @@ -320,9 +340,12 @@ static hal_error_t pkey_local_generate_rsa(const hal_client_handle_t client, uint8_t der[hal_rsa_private_key_to_der_len(key)]; size_t der_len; - if ((err = hal_rsa_private_key_to_der(key, der, &der_len, sizeof(der))) == HAL_OK) - err = hal_ks_store(HAL_KEY_TYPE_RSA_PRIVATE, HAL_CURVE_NONE, flags, - name, name_len, der, der_len, &slot->ks_hint); + if ((err = hal_rsa_private_key_to_der(key, der, &der_len, sizeof(der))) == HAL_OK && + (err = ks_open_from_flags(&ks, flags)) == HAL_OK && + (err = hal_ks_store(ks, slot, der, der_len)) == HAL_OK) + err = hal_ks_close(ks); + else if (ks != NULL) + (void) hal_ks_close(ks); memset(keybuf, 0, sizeof(keybuf)); memset(der, 0, sizeof(der)); @@ -330,15 +353,8 @@ static hal_error_t pkey_local_generate_rsa(const hal_client_handle_t client, if (err != HAL_OK) return err; - memcpy(slot->name, name, name_len); - slot->client_handle = client; - slot->session_handle = session; - slot->type = HAL_KEY_TYPE_RSA_PRIVATE; - slot->curve = HAL_CURVE_NONE; - slot->flags = flags; - slot->name_len = name_len; - *pkey = slot->pkey_handle; + *name = slot->name; return HAL_OK; } @@ -350,20 +366,29 @@ static hal_error_t pkey_local_generate_rsa(const hal_client_handle_t client, static hal_error_t pkey_local_generate_ec(const hal_client_handle_t client, const hal_session_handle_t session, hal_pkey_handle_t *pkey, - const uint8_t * const name, const size_t name_len, + hal_uuid_t *name, const hal_curve_name_t curve, const hal_key_flags_t flags) { - pkey_slot_t *slot; - hal_error_t err; + assert(pkey != NULL && name != NULL); - assert(sizeof(slot->name) >= name_len && pkey != NULL); + uint8_t keybuf[hal_ecdsa_key_t_size]; + hal_ecdsa_key_t *key = NULL; + hal_pkey_slot_t *slot; + hal_ks_t *ks = NULL; + hal_error_t err; if ((slot = alloc_slot(flags)) == NULL) return HAL_ERROR_NO_KEY_SLOTS_AVAILABLE; - uint8_t keybuf[hal_ecdsa_key_t_size]; - hal_ecdsa_key_t *key = NULL; + if ((err = hal_uuid_gen(&slot->name)) != HAL_OK) + return err; + + slot->client_handle = client; + slot->session_handle = session; + slot->type = HAL_KEY_TYPE_EC_PRIVATE; + slot->curve = curve; + slot->flags = flags; if ((err = hal_ecdsa_key_gen(NULL, &key, keybuf, sizeof(keybuf), curve)) != HAL_OK) return err; @@ -371,9 +396,12 @@ static hal_error_t pkey_local_generate_ec(const hal_client_handle_t client, uint8_t der[hal_ecdsa_private_key_to_der_len(key)]; size_t der_len; - if ((err = hal_ecdsa_private_key_to_der(key, der, &der_len, sizeof(der))) == HAL_OK) - err = hal_ks_store(HAL_KEY_TYPE_EC_PRIVATE, curve, flags, - name, name_len, der, der_len, &slot->ks_hint); + if ((err = hal_ecdsa_private_key_to_der(key, der, &der_len, sizeof(der))) == HAL_OK && + (err = ks_open_from_flags(&ks, flags)) == HAL_OK && + (err = hal_ks_store(ks, slot, der, der_len)) == HAL_OK) + err = hal_ks_close(ks); + else if (ks != NULL) + (void) hal_ks_close(ks); memset(keybuf, 0, sizeof(keybuf)); memset(der, 0, sizeof(der)); @@ -381,15 +409,8 @@ static hal_error_t pkey_local_generate_ec(const hal_client_handle_t client, if (err != HAL_OK) return err; - memcpy(slot->name, name, name_len); - slot->client_handle = client; - slot->session_handle = session; - slot->type = HAL_KEY_TYPE_EC_PRIVATE; - slot->curve = curve; - slot->flags = flags; - slot->name_len = name_len; - *pkey = slot->pkey_handle; + *name = slot->name; return HAL_OK; } @@ -399,7 +420,7 @@ static hal_error_t pkey_local_generate_ec(const hal_client_handle_t client, static hal_error_t pkey_local_close(const hal_pkey_handle_t pkey) { - pkey_slot_t *slot; + hal_pkey_slot_t *slot; if ((slot = find_handle(pkey)) == NULL) return HAL_ERROR_KEY_NOT_FOUND; @@ -415,12 +436,19 @@ static hal_error_t pkey_local_close(const hal_pkey_handle_t pkey) static hal_error_t pkey_local_delete(const hal_pkey_handle_t pkey) { - pkey_slot_t *slot = find_handle(pkey); + hal_pkey_slot_t *slot = find_handle(pkey); if (slot == NULL) return HAL_ERROR_KEY_NOT_FOUND; - hal_error_t err = hal_ks_delete(slot->type, slot->name, slot->name_len, &slot->ks_hint); + hal_ks_t *ks = NULL; + hal_error_t err; + + if ((err = ks_open_from_flags(&ks, slot->flags)) == HAL_OK && + (err = hal_ks_delete(ks, slot)) == HAL_OK) + err = hal_ks_close(ks); + else if (ks != NULL) + (void) hal_ks_close(ks); if (err == HAL_OK || err == HAL_ERROR_KEY_NOT_FOUND) memset(slot, 0, sizeof(*slot)); @@ -428,30 +456,6 @@ static hal_error_t pkey_local_delete(const hal_pkey_handle_t pkey) return err; } -/* - * Rename a key in the key store, given its key handle and a new name. - */ - -static hal_error_t pkey_local_rename(const hal_pkey_handle_t pkey, - const uint8_t * const name, const size_t name_len) -{ - pkey_slot_t *slot = find_handle(pkey); - - if (slot == NULL) - return HAL_ERROR_KEY_NOT_FOUND; - - hal_error_t err = hal_ks_rename(slot->type, slot->name, slot->name_len, name, name_len, &slot->ks_hint); - - if (err == HAL_OK) { - assert(name_len <= sizeof(slot->name)); - memcpy(slot->name, name, name_len); - memset(slot->name + name_len, 0, sizeof(slot->name) - name_len); - slot->name_len = name_len; - } - - return err; -} - /* * Get type of key associated with handle. */ @@ -462,7 +466,7 @@ static hal_error_t pkey_local_get_key_type(const hal_pkey_handle_t pkey, if (type == NULL) return HAL_ERROR_BAD_ARGUMENTS; - pkey_slot_t *slot = find_handle(pkey); + hal_pkey_slot_t *slot = find_handle(pkey); if (slot == NULL) return HAL_ERROR_KEY_NOT_FOUND; @@ -482,7 +486,7 @@ static hal_error_t pkey_local_get_key_flags(const hal_pkey_handle_t pkey, if (flags == NULL) return HAL_ERROR_BAD_ARGUMENTS; - pkey_slot_t *slot = find_handle(pkey); + hal_pkey_slot_t *slot = find_handle(pkey); if (slot == NULL) return HAL_ERROR_KEY_NOT_FOUND; @@ -498,7 +502,7 @@ static hal_error_t pkey_local_get_key_flags(const hal_pkey_handle_t pkey, static size_t pkey_local_get_public_key_len(const hal_pkey_handle_t pkey) { - pkey_slot_t *slot = find_handle(pkey); + hal_pkey_slot_t *slot = find_handle(pkey); if (slot == NULL) return 0; @@ -510,9 +514,16 @@ static size_t pkey_local_get_public_key_len(const hal_pkey_handle_t pkey) hal_ecdsa_key_t *ecdsa_key = NULL; uint8_t der[HAL_KS_WRAPPED_KEYSIZE]; size_t der_len; + hal_ks_t *ks = NULL; + hal_error_t err; - if (hal_ks_fetch(slot->type, slot->name, slot->name_len, NULL, NULL, - der, &der_len, sizeof(der), &slot->ks_hint) == HAL_OK) { + if ((err = ks_open_from_flags(&ks, slot->flags)) == HAL_OK && + (err = hal_ks_fetch(ks, slot, der, &der_len, sizeof(der))) == HAL_OK) + err = hal_ks_close(ks); + else if (ks != NULL) + (void) hal_ks_close(ks); + + if (err == HAL_OK) { switch (slot->type) { case HAL_KEY_TYPE_RSA_PUBLIC: @@ -548,7 +559,7 @@ static size_t pkey_local_get_public_key_len(const hal_pkey_handle_t pkey) static hal_error_t pkey_local_get_public_key(const hal_pkey_handle_t pkey, uint8_t *der, size_t *der_len, const size_t der_max) { - pkey_slot_t *slot = find_handle(pkey); + hal_pkey_slot_t *slot = find_handle(pkey); if (slot == NULL) return HAL_ERROR_KEY_NOT_FOUND; @@ -558,10 +569,16 @@ static hal_error_t pkey_local_get_public_key(const hal_pkey_handle_t pkey, hal_ecdsa_key_t *ecdsa_key = NULL; uint8_t buf[HAL_KS_WRAPPED_KEYSIZE]; size_t buf_len; + hal_ks_t *ks = NULL; hal_error_t err; - if ((err = hal_ks_fetch(slot->type, slot->name, slot->name_len, NULL, NULL, - buf, &buf_len, sizeof(buf), &slot->ks_hint)) == HAL_OK) { + if ((err = ks_open_from_flags(&ks, slot->flags)) == HAL_OK && + (err = hal_ks_fetch(ks, slot, buf, &buf_len, sizeof(buf))) == HAL_OK) + err = hal_ks_close(ks); + else if (ks != NULL) + (void) hal_ks_close(ks); + + if (err == HAL_OK) { switch (slot->type) { case HAL_KEY_TYPE_RSA_PUBLIC: @@ -678,7 +695,7 @@ static hal_error_t pkey_local_sign(const hal_session_handle_t session, const uint8_t * const input, const size_t input_len, uint8_t * signature, size_t *signature_len, const size_t signature_max) { - pkey_slot_t *slot = find_handle(pkey); + hal_pkey_slot_t *slot = find_handle(pkey); if (slot == NULL) return HAL_ERROR_KEY_NOT_FOUND; @@ -703,9 +720,14 @@ static hal_error_t pkey_local_sign(const hal_session_handle_t session, uint8_t keybuf[hal_rsa_key_t_size > hal_ecdsa_key_t_size ? hal_rsa_key_t_size : hal_ecdsa_key_t_size]; uint8_t der[HAL_KS_WRAPPED_KEYSIZE]; size_t der_len; + hal_ks_t *ks = NULL; hal_error_t err; - err = hal_ks_fetch(slot->type, slot->name, slot->name_len, NULL, NULL, der, &der_len, sizeof(der), &slot->ks_hint); + if ((err = ks_open_from_flags(&ks, slot->flags)) == HAL_OK && + (err = hal_ks_fetch(ks, slot, der, &der_len, sizeof(der))) == HAL_OK) + err = hal_ks_close(ks); + else if (ks != NULL) + (void) hal_ks_close(ks); if (err == HAL_OK) err = signer(keybuf, sizeof(keybuf), der, der_len, hash, input, input_len, signature, signature_len, signature_max); @@ -820,7 +842,7 @@ static hal_error_t pkey_local_verify(const hal_session_handle_t session, const uint8_t * const input, const size_t input_len, const uint8_t * const signature, const size_t signature_len) { - pkey_slot_t *slot = find_handle(pkey); + hal_pkey_slot_t *slot = find_handle(pkey); if (slot == NULL) return HAL_ERROR_KEY_NOT_FOUND; @@ -847,9 +869,14 @@ static hal_error_t pkey_local_verify(const hal_session_handle_t session, uint8_t keybuf[hal_rsa_key_t_size > hal_ecdsa_key_t_size ? hal_rsa_key_t_size : hal_ecdsa_key_t_size]; uint8_t der[HAL_KS_WRAPPED_KEYSIZE]; size_t der_len; + hal_ks_t *ks = NULL; hal_error_t err; - err = hal_ks_fetch(slot->type, slot->name, slot->name_len, NULL, NULL, der, &der_len, sizeof(der), &slot->ks_hint); + if ((err = ks_open_from_flags(&ks, slot->flags)) == HAL_OK && + (err = hal_ks_fetch(ks, slot, der, &der_len, sizeof(der))) == HAL_OK) + err = hal_ks_close(ks); + else if (ks != NULL) + (void) hal_ks_close(ks); if (err == HAL_OK) err = verifier(keybuf, sizeof(keybuf), slot->type, der, der_len, hash, input, input_len, signature, signature_len); @@ -870,7 +897,16 @@ static hal_error_t pkey_local_list(hal_pkey_info_t *result, const unsigned result_max, hal_key_flags_t flags) { - return hal_ks_list(result, result_len, result_max); + hal_ks_t *ks = NULL; + hal_error_t err; + + if ((err = ks_open_from_flags(&ks, flags)) == HAL_OK && + (err = hal_ks_list(ks, result, result_len, result_max)) == 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 = { @@ -880,7 +916,6 @@ const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch = { pkey_local_generate_ec, pkey_local_close, pkey_local_delete, - pkey_local_rename, pkey_local_get_key_type, pkey_local_get_key_flags, pkey_local_get_public_key_len, diff --git a/rpc_server.c b/rpc_server.c index a0de42d..9694ab8 100644 --- a/rpc_server.c +++ b/rpc_server.c @@ -55,6 +55,7 @@ static hal_error_t get_version(const uint8_t **iptr, const uint8_t * const ilimi /* call the local function */ ret = hal_rpc_local_misc_dispatch.get_version(&version); + if (ret == HAL_OK) check(hal_xdr_encode_int(optr, olimit, version)); @@ -102,6 +103,7 @@ static hal_error_t set_pin(const uint8_t **iptr, const uint8_t * const ilimit, /* call the local function */ ret = hal_rpc_local_misc_dispatch.set_pin(client, user, (const char * const)pin, pin_len); + return ret; } @@ -120,6 +122,7 @@ static hal_error_t login(const uint8_t **iptr, const uint8_t * const ilimit, /* call the local function */ ret = hal_rpc_local_misc_dispatch.login(client, user, (const char * const)pin, pin_len); + return ret; } @@ -133,6 +136,7 @@ static hal_error_t logout(const uint8_t **iptr, const uint8_t * const ilimit, /* call the local function */ ret = hal_rpc_local_misc_dispatch.logout(client); + return ret; } @@ -146,6 +150,7 @@ static hal_error_t logout_all(const uint8_t **iptr, const uint8_t * const ilimit /* call the local function */ ret = hal_rpc_local_misc_dispatch.logout_all(); + return ret; } @@ -161,6 +166,7 @@ static hal_error_t is_logged_in(const uint8_t **iptr, const uint8_t * const ilim /* call the local function */ ret = hal_rpc_local_misc_dispatch.is_logged_in(client, user); + return ret; } @@ -177,8 +183,10 @@ static hal_error_t hash_get_digest_len(const uint8_t **iptr, const uint8_t * con /* call the local function */ ret = hal_rpc_local_hash_dispatch.get_digest_length(alg, &length); + if (ret == HAL_OK) check(hal_xdr_encode_int(optr, olimit, length)); + return ret; } @@ -228,8 +236,10 @@ static hal_error_t hash_get_algorithm(const uint8_t **iptr, const uint8_t * cons /* call the local function */ ret = hal_rpc_local_hash_dispatch.get_algorithm(hash, &alg); + if (ret == HAL_OK) check(hal_xdr_encode_int(optr, olimit, alg)); + return ret; } @@ -251,8 +261,10 @@ static hal_error_t hash_initialize(const uint8_t **iptr, const uint8_t * const i /* call the local function */ ret = hal_rpc_local_hash_dispatch.initialize(client, session, &hash, (hal_digest_algorithm_t)alg, key, (size_t)key_len); + if (ret == HAL_OK) check(hal_xdr_encode_int(optr, olimit, hash.handle)); + return ret; } @@ -271,6 +283,7 @@ static hal_error_t hash_update(const uint8_t **iptr, const uint8_t * const ilimi /* call the local function */ ret = hal_rpc_local_hash_dispatch.update(hash, data, (size_t)length); + return ret; } @@ -309,8 +322,9 @@ static hal_error_t pkey_load(const uint8_t **iptr, const uint8_t * const ilimit, hal_pkey_handle_t pkey; uint32_t type; uint32_t curve; - const uint8_t *name, *der; - uint32_t name_len, der_len; + hal_uuid_t name; + const uint8_t *der; + uint32_t der_len; hal_key_flags_t flags; hal_error_t ret; @@ -318,14 +332,19 @@ static hal_error_t pkey_load(const uint8_t **iptr, const uint8_t * const ilimit, check(hal_xdr_decode_int(iptr, ilimit, &session.handle)); check(hal_xdr_decode_int(iptr, ilimit, &type)); check(hal_xdr_decode_int(iptr, ilimit, &curve)); - check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &name, &name_len)); check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &der, &der_len)); check(hal_xdr_decode_int(iptr, ilimit, &flags)); /* call the local function */ - ret = hal_rpc_local_pkey_dispatch.load(client, session, &pkey, type, curve, name, name_len, der, der_len, flags); - if (ret == HAL_OK) - check(hal_xdr_encode_int(optr, olimit, pkey.handle)); + ret = hal_rpc_local_pkey_dispatch.load(client, session, &pkey, type, curve, &name, der, der_len, flags); + + if (ret == HAL_OK) { + uint8_t *optr_orig = *optr; + if ((ret = hal_xdr_encode_int(optr, olimit, pkey.handle)) != HAL_OK || + (ret = hal_xdr_encode_buffer(optr, olimit, name.uuid, sizeof(name.uuid))) != HAL_OK) + *optr = optr_orig; + } + return ret; } @@ -336,7 +355,7 @@ static hal_error_t pkey_find(const uint8_t **iptr, const uint8_t * const ilimit, hal_session_handle_t session; hal_pkey_handle_t pkey; uint32_t type; - const uint8_t *name; + const uint8_t *name_ptr; uint32_t name_len; hal_key_flags_t flags; hal_error_t ret; @@ -344,13 +363,18 @@ static hal_error_t pkey_find(const uint8_t **iptr, const uint8_t * const ilimit, check(hal_xdr_decode_int(iptr, ilimit, &client.handle)); check(hal_xdr_decode_int(iptr, ilimit, &session.handle)); check(hal_xdr_decode_int(iptr, ilimit, &type)); - check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &name, &name_len)); + check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &name_ptr, &name_len)); check(hal_xdr_decode_int(iptr, ilimit, &flags)); + if (name_len != sizeof(hal_uuid_t)) + return HAL_ERROR_KEY_NAME_TOO_LONG; + /* call the local function */ - ret = hal_rpc_local_pkey_dispatch.find(client, session, &pkey, type, name, name_len, flags); + ret = hal_rpc_local_pkey_dispatch.find(client, session, &pkey, type, (const hal_uuid_t *) name_ptr, flags); + if (ret == HAL_OK) check(hal_xdr_encode_int(optr, olimit, pkey.handle)); + return ret; } @@ -360,8 +384,7 @@ static hal_error_t pkey_generate_rsa(const uint8_t **iptr, const uint8_t * const hal_client_handle_t client; hal_session_handle_t session; hal_pkey_handle_t pkey; - const uint8_t *name; - uint32_t name_len; + hal_uuid_t name; uint32_t key_len; const uint8_t *exp; uint32_t exp_len; @@ -370,15 +393,20 @@ static hal_error_t pkey_generate_rsa(const uint8_t **iptr, const uint8_t * const check(hal_xdr_decode_int(iptr, ilimit, &client.handle)); check(hal_xdr_decode_int(iptr, ilimit, &session.handle)); - check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &name, &name_len)); check(hal_xdr_decode_int(iptr, ilimit, &key_len)); check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &exp, &exp_len)); check(hal_xdr_decode_int(iptr, ilimit, &flags)); /* call the local function */ - ret = hal_rpc_local_pkey_dispatch.generate_rsa(client, session, &pkey, name, name_len, key_len, exp, exp_len, flags); - if (ret == HAL_OK) - check(hal_xdr_encode_int(optr, olimit, pkey.handle)); + ret = hal_rpc_local_pkey_dispatch.generate_rsa(client, session, &pkey, &name, key_len, exp, exp_len, flags); + + if (ret == HAL_OK) { + uint8_t *optr_orig = *optr; + if ((ret = hal_xdr_encode_int(optr, olimit, pkey.handle)) != HAL_OK || + (ret = hal_xdr_encode_buffer(optr, olimit, name.uuid, sizeof(name.uuid))) != HAL_OK) + *optr = optr_orig; + } + return ret; } @@ -388,22 +416,26 @@ static hal_error_t pkey_generate_ec(const uint8_t **iptr, const uint8_t * const hal_client_handle_t client; hal_session_handle_t session; hal_pkey_handle_t pkey; - const uint8_t *name; - uint32_t name_len; + hal_uuid_t name; uint32_t curve; 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, &session.handle)); - check(hal_xdr_decode_buffer_in_place(iptr, ilimit, &name, &name_len)); check(hal_xdr_decode_int(iptr, ilimit, &curve)); check(hal_xdr_decode_int(iptr, ilimit, &flags)); /* call the local function */ - ret = hal_rpc_local_pkey_dispatch.generate_ec(client, session, &pkey, name, name_len, curve, flags); - if (ret == HAL_OK) - check(hal_xdr_encode_int(optr, olimit, pkey.handle)); + ret = hal_rpc_local_pkey_dispatch.generate_ec(client, session, &pkey, &name, curve, flags); + + if (ret == HAL_OK) { + uint8_t *optr_orig = *optr; + if ((ret = hal_xdr_encode_int(optr, olimit, pkey.handle)) != HAL_OK || + (ret = hal_xdr_encode_buffer(optr, olimit, name.uuid, sizeof(name.uuid))) != HAL_OK) + *optr = optr_orig; + } + return ret; } @@ -419,6 +451,7 @@ static hal_error_t pkey_close(const uint8_t **iptr, const uint8_t * const ilimit /* call the local function */ ret = hal_rpc_local_pkey_dispatch.close(pkey); + return ret; } @@ -434,24 +467,7 @@ static hal_error_t pkey_delete(const uint8_t **iptr, const uint8_t * const ilimi /* call the local function */ ret = hal_rpc_local_pkey_dispatch.delete(pkey); - return ret; -} - -static hal_error_t pkey_rename(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_pkey_handle_t pkey; - const uint8_t *name; - uint32_t name_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_buffer_in_place(iptr, ilimit, &name, &name_len)); - - /* call the local function */ - ret = hal_rpc_local_pkey_dispatch.rename(pkey, name, name_len); return ret; } @@ -468,8 +484,10 @@ static hal_error_t pkey_get_key_type(const uint8_t **iptr, const uint8_t * const /* call the local function */ ret = hal_rpc_local_pkey_dispatch.get_key_type(pkey, &type); + if (ret == HAL_OK) check(hal_xdr_encode_int(optr, olimit, type)); + return ret; } @@ -486,8 +504,10 @@ static hal_error_t pkey_get_key_flags(const uint8_t **iptr, const uint8_t * cons /* call the local function */ ret = hal_rpc_local_pkey_dispatch.get_key_flags(pkey, &flags); + if (ret == HAL_OK) check(hal_xdr_encode_int(optr, olimit, flags)); + return ret; } @@ -503,7 +523,9 @@ static hal_error_t pkey_get_public_key_len(const uint8_t **iptr, const uint8_t * /* call the local function */ len = hal_rpc_local_pkey_dispatch.get_public_key_len(pkey); + check(hal_xdr_encode_int(optr, olimit, len)); + return HAL_OK; } @@ -598,6 +620,7 @@ static hal_error_t pkey_remote_verify(const uint8_t **iptr, const uint8_t * cons /* call the local function */ ret = hal_rpc_local_pkey_dispatch.verify(session, pkey, hash, input, input_len, sig, sig_len); + return ret; } @@ -609,12 +632,11 @@ static hal_error_t hal_xdr_encode_pkey_info(uint8_t **optr, const uint8_t * cons if ((ret = hal_xdr_encode_int(optr, olimit, info->type)) != HAL_OK || (ret = hal_xdr_encode_int(optr, olimit, info->curve)) != HAL_OK || (ret = hal_xdr_encode_int(optr, olimit, info->flags)) != HAL_OK || - (ret = hal_xdr_encode_buffer(optr, olimit, (uint8_t *)&info->name[0], info->name_len)) != HAL_OK) + (ret = hal_xdr_encode_buffer(optr, olimit, info->name.uuid, sizeof(info->name.uuid))) != HAL_OK) *optr = optr_orig; return ret; } - static hal_error_t pkey_list(const uint8_t **iptr, const uint8_t * const ilimit, uint8_t **optr, const uint8_t * const olimit) { @@ -633,6 +655,7 @@ static hal_error_t pkey_list(const uint8_t **iptr, const uint8_t * const ilimit, /* call the local function */ 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)); @@ -643,6 +666,7 @@ static hal_error_t pkey_list(const uint8_t **iptr, const uint8_t * const ilimit, } } } + return ret; } @@ -739,9 +763,6 @@ hal_error_t hal_rpc_server_dispatch(const uint8_t * const ibuf, const size_t ile case RPC_FUNC_PKEY_LIST: ret = pkey_list(&iptr, ilimit, &optr, olimit); break; - case RPC_FUNC_PKEY_RENAME: - ret = pkey_rename(&iptr, ilimit, &optr, olimit); - break; default: ret = HAL_ERROR_RPC_BAD_FUNCTION; break; diff --git a/uuid.c b/uuid.c new file mode 100644 index 0000000..04410c0 --- /dev/null +++ b/uuid.c @@ -0,0 +1,75 @@ +/* + * uuid.c + * ------ + * UUID support for keystore database. + * + * 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 "hal.h" +#include "hal_internal.h" + +hal_error_t hal_uuid_gen(hal_uuid_t *uuid) +{ + hal_error_t err; + + if (uuid == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + /* + * Generate a version 4 UUID as specified in RFC 4122. + * This is basically a 122-bit random number. + */ + + if ((err = hal_rpc_get_random(uuid->uuid, sizeof(uuid->uuid))) != HAL_OK) + return err; + + /* + * Set high order bits of clock_seq_hi_and_reserved and + * time_hi_and_version fields to magic values as specified by RFC + * 4122 section 4.4. + * + * Not recommended reading if you've eaten recently. + */ + + uuid->uuid[6] &= 0x0f; + uuid->uuid[6] |= 0x40; + uuid->uuid[8] &= 0x3f; + uuid->uuid[8] |= 0x80; + + return HAL_OK; +} + +/* + * Local variables: + * indent-tabs-mode: nil + * End: + */ -- cgit v1.2.3