diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | hal.h | 27 | ||||
-rw-r--r-- | hal_internal.h | 266 | ||||
-rw-r--r-- | ks_flash.c | 653 | ||||
-rw-r--r-- | ks_volatile.c | 269 | ||||
-rw-r--r-- | rpc_api.c | 39 | ||||
-rw-r--r-- | rpc_client.c | 116 | ||||
-rw-r--r-- | rpc_pkey.c | 289 | ||||
-rw-r--r-- | rpc_server.c | 107 | ||||
-rw-r--r-- | uuid.c | 75 |
10 files changed, 1241 insertions, 603 deletions
@@ -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 @@ -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 <string.h> + #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 @@ -256,14 +255,27 @@ extern hal_error_t hal_rpc_pkey_pkcs1_construct_digestinfo(const hal_hash_handle 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); @@ -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 <string.h> +#include <assert.h> #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 @@ -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, @@ -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. */ /* @@ -223,6 +198,27 @@ static hal_error_t pkcs1_5_pad(const uint8_t * const data, const size_t data_len } /* + * 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)); @@ -429,30 +457,6 @@ static hal_error_t pkey_local_delete(const hal_pkey_handle_t pkey) } /* - * 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; @@ -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 <assert.h> + +#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: + */ |