diff options
-rw-r--r-- | hal_internal.h | 9 | ||||
-rw-r--r-- | ks.c | 12 | ||||
-rw-r--r-- | ks.h | 4 | ||||
-rw-r--r-- | ks_token.c | 9 | ||||
-rw-r--r-- | ks_volatile.c | 31 | ||||
-rw-r--r-- | rpc_misc.c | 92 | ||||
-rw-r--r-- | rpc_pkey.c | 26 |
7 files changed, 153 insertions, 30 deletions
diff --git a/hal_internal.h b/hal_internal.h index add7890..2486fd2 100644 --- a/hal_internal.h +++ b/hal_internal.h @@ -432,6 +432,12 @@ extern hal_error_t hal_mkm_flash_erase(const size_t len); #endif /* + * Clean up pkey stuff that's tied to a particular client on logout. + */ + +extern hal_error_t hal_pkey_logout(const hal_client_handle_t client); + +/* * Keystore API for use by the pkey implementation. * * In an attempt to emulate what current theory says will eventually @@ -522,6 +528,9 @@ extern hal_error_t hal_ks_get_attributes(hal_ks_t *ks, uint8_t *attributes_buffer, const size_t attributes_buffer_len); +extern hal_error_t hal_ks_logout(hal_ks_t *ks, + const hal_client_handle_t client); + /* * RPC lowest-level send and receive routines. These are blocking, and * transport-specific (sockets, USB). @@ -461,6 +461,18 @@ hal_error_t hal_ks_init_common(hal_ks_t *ks) } /* + * Log a client out of a keystore. + */ + +hal_error_t hal_ks_logout(hal_ks_t *ks, const hal_client_handle_t client) +{ + return + ks == NULL || ks->driver == NULL ? HAL_ERROR_BAD_ARGUMENTS : + ks->driver->logout == NULL ? HAL_ERROR_NOT_IMPLEMENTED : + ks->driver->logout(ks, client); +} + +/* * Test whether we like a particular key type. */ @@ -223,12 +223,14 @@ struct hal_ks_driver { hal_error_t (*test_owner) (hal_ks_t *ks, const unsigned blockno, const hal_client_handle_t client, const hal_session_handle_t session); hal_error_t (*copy_owner) (hal_ks_t *ks, const unsigned source, const unsigned target); + hal_error_t (*logout) (hal_ks_t *ks, const hal_client_handle_t client); }; /* * Wrappers around keystore driver methods. * - * hal_ks_init() is missing here because we expose it to the rest of libhal. + * hal_ks_init() and hal_ks_logout() are missing here because we + * expose them to the rest of libhal. */ static inline hal_error_t hal_ks_block_read(hal_ks_t *ks, const unsigned blockno, hal_ks_block_t *block) @@ -289,6 +289,12 @@ static hal_error_t ks_token_copy_owner(hal_ks_t *ks, return HAL_OK; } +static hal_error_t ks_token_logout(hal_ks_t *ks, + hal_client_handle_t client) +{ + return HAL_OK; +} + /* * Forward reference. */ @@ -394,7 +400,8 @@ static const hal_ks_driver_t ks_token_driver = { .erase_maybe = ks_token_erase_maybe, .set_owner = ks_token_set_owner, .test_owner = ks_token_test_owner, - .copy_owner = ks_token_copy_owner + .copy_owner = ks_token_copy_owner, + .logout = ks_token_logout }; static ks_token_db_t _db = { .ks.driver = &ks_token_driver }; diff --git a/ks_volatile.c b/ks_volatile.c index 02054ff..57806e8 100644 --- a/ks_volatile.c +++ b/ks_volatile.c @@ -218,6 +218,34 @@ static hal_error_t ks_volatile_copy_owner(hal_ks_t *ks, } /* + * Zero any blocks owned by a client that we're logging out. + */ + +static hal_error_t ks_volatile_logout(hal_ks_t *ks, + hal_client_handle_t client) +{ + if (ks != hal_ks_volatile || client.handle == HAL_HANDLE_NONE) + return HAL_ERROR_IMPOSSIBLE; + + for (int i = 0; i < ks->used; i++) { + unsigned b = ks->index[i]; + hal_error_t err; + int hint = i; + + if (db->keys[b].client.handle != client.handle) + continue; + + if ((err = hal_ks_index_delete(ks, &ks->names[b], 0, NULL, &hint)) != HAL_OK || + (err = hal_ks_block_zero(ks, b)) != HAL_OK) + return err; + + i--; + } + + return HAL_OK; +} + +/* * Initialize keystore. */ @@ -272,7 +300,8 @@ static const hal_ks_driver_t ks_volatile_driver = { .erase_maybe = ks_volatile_erase, /* sic */ .set_owner = ks_volatile_set_owner, .test_owner = ks_volatile_test_owner, - .copy_owner = ks_volatile_copy_owner + .copy_owner = ks_volatile_copy_owner, + .logout = ks_volatile_logout }; static ks_volatile_db_t _db = { .ks.driver = &ks_volatile_driver }; @@ -33,8 +33,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <assert.h> - #include "hal.h" #include "hal_internal.h" @@ -46,7 +44,8 @@ static hal_error_t get_version(uint32_t *version) static hal_error_t get_random(void *buffer, const size_t length) { - assert(buffer != NULL && length > 0); + if (buffer == NULL || length == 0) + return HAL_ERROR_IMPOSSIBLE; return hal_get_random(NULL, buffer, length); } @@ -96,7 +95,7 @@ static uint32_t hal_pin_default_iterations = HAL_PIN_DEFAULT_ITERATIONS; #endif #ifndef HAL_STATIC_CLIENT_STATE_BLOCKS -#define HAL_STATIC_CLIENT_STATE_BLOCKS 10 +#define HAL_STATIC_CLIENT_STATE_BLOCKS 10 #endif #if HAL_STATIC_CLIENT_STATE_BLOCKS > 0 @@ -109,19 +108,51 @@ static client_slot_t client_handle[HAL_STATIC_CLIENT_STATE_BLOCKS]; * them. HAL_USER_NONE indicates an empty slot in the table. */ -static inline client_slot_t *alloc_slot(void) +static inline hal_error_t alloc_slot(const hal_client_handle_t client, + const hal_user_t user) { client_slot_t *slot = NULL; hal_critical_section_start(); #if HAL_STATIC_CLIENT_STATE_BLOCKS > 0 + + for (int i = 0; slot == NULL && i < sizeof(client_handle)/sizeof(*client_handle); i++) + if (client_handle[i].logged_in != HAL_USER_NONE && + client_handle[i].handle.handle == client.handle) + slot = &client_handle[i]; + for (int i = 0; slot == NULL && i < sizeof(client_handle)/sizeof(*client_handle); i++) if (client_handle[i].logged_in == HAL_USER_NONE) slot = &client_handle[i]; + #endif + if (slot != NULL) { + slot->handle = client; + slot->logged_in = user; + } + hal_critical_section_end(); - return slot; + return slot == NULL ? HAL_ERROR_NO_CLIENT_SLOTS_AVAILABLE : HAL_OK; +} + +static inline hal_error_t clear_slot(client_slot_t *slot) +{ + if (slot == NULL) + return HAL_OK; + + hal_error_t err; + + if ((err = hal_pkey_logout(slot->handle)) != HAL_OK) + return err; + + hal_critical_section_start(); + + memset(slot, 0, sizeof(*slot)); + + hal_critical_section_end(); + + return HAL_OK; } static inline client_slot_t *find_handle(const hal_client_handle_t handle) @@ -143,8 +174,8 @@ static hal_error_t login(const hal_client_handle_t client, const hal_user_t user, const char * const pin, const size_t pin_len) { - assert(pin != NULL && pin_len != 0); - assert(user == HAL_USER_NORMAL || user == HAL_USER_SO || user == HAL_USER_WHEEL); + if (pin == NULL || pin_len == 0 || (user != HAL_USER_NORMAL && user != HAL_USER_SO && user != HAL_USER_WHEEL)) + return HAL_ERROR_IMPOSSIBLE; const hal_ks_pin_t *p; hal_error_t err; @@ -168,21 +199,14 @@ static hal_error_t login(const hal_client_handle_t client, return HAL_ERROR_PIN_INCORRECT; } - client_slot_t *slot = find_handle(client); - - if (slot == NULL && (slot = alloc_slot()) == NULL) - return HAL_ERROR_NO_CLIENT_SLOTS_AVAILABLE; - - slot->handle = client; - slot->logged_in = user; - - return HAL_OK; + return alloc_slot(client, user); } static hal_error_t is_logged_in(const hal_client_handle_t client, const hal_user_t user) { - assert(user == HAL_USER_NORMAL || user == HAL_USER_SO || user == HAL_USER_WHEEL); + if (user != HAL_USER_NORMAL && user != HAL_USER_SO && user != HAL_USER_WHEEL) + return HAL_ERROR_IMPOSSIBLE; client_slot_t *slot = find_handle(client); @@ -194,19 +218,32 @@ static hal_error_t is_logged_in(const hal_client_handle_t client, static hal_error_t logout(const hal_client_handle_t client) { - client_slot_t *slot = find_handle(client); - - if (slot != NULL) - slot->logged_in = HAL_USER_NONE; - - return HAL_OK; + return clear_slot(find_handle(client)); } static hal_error_t logout_all(void) { #if HAL_STATIC_CLIENT_STATE_BLOCKS > 0 - for (int i = 0; i < sizeof(client_handle)/sizeof(*client_handle); i++) - client_handle[i].logged_in = HAL_USER_NONE; + + client_slot_t *slot; + hal_error_t err; + int i = 0; + + do { + + hal_critical_section_start(); + + for (slot = NULL; slot == NULL && i < sizeof(client_handle)/sizeof(*client_handle); i++) + if (client_handle[i].logged_in != HAL_USER_NONE) + slot = &client_handle[i]; + + hal_critical_section_end(); + + if ((err = clear_slot(slot)) != HAL_OK) + return err; + + } while (slot != NULL); + #endif return HAL_OK; @@ -216,7 +253,8 @@ static hal_error_t set_pin(const hal_client_handle_t client, const hal_user_t user, const char * const newpin, const size_t newpin_len) { - assert(newpin != NULL && newpin_len >= hal_rpc_min_pin_length && newpin_len <= hal_rpc_max_pin_length); + if (newpin == NULL || newpin_len < hal_rpc_min_pin_length || newpin_len > hal_rpc_max_pin_length) + return HAL_ERROR_IMPOSSIBLE; if ((user != HAL_USER_NORMAL || is_logged_in(client, HAL_USER_SO) != HAL_OK) && is_logged_in(client, HAL_USER_WHEEL) != HAL_OK) @@ -129,6 +129,32 @@ static inline hal_pkey_slot_t *find_handle(const hal_pkey_handle_t handle) } /* + * Clean up key state associated with a client when logging out. + */ + +hal_error_t hal_pkey_logout(const hal_client_handle_t client) +{ + if (client.handle == HAL_HANDLE_NONE) + return HAL_OK; + + hal_error_t err; + + if ((err = hal_ks_logout(hal_ks_volatile, client)) != HAL_OK || + (err = hal_ks_logout(hal_ks_token, client)) != HAL_OK) + return err; + + hal_critical_section_start(); + + for (int i = 0; i < sizeof(pkey_slot)/sizeof(*pkey_slot); i++) + if (pkey_slot[i].pkey.handle == client.handle) + memset(&pkey_slot[i], 0, sizeof(pkey_slot[i])); + + hal_critical_section_end(); + + return HAL_OK; +} + +/* * Access rules are a bit complicated, mostly due to PKCS #11. * * The simple, obvious rule would be that one must be logged in as |