aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hal_internal.h9
-rw-r--r--ks.c12
-rw-r--r--ks.h4
-rw-r--r--ks_token.c9
-rw-r--r--ks_volatile.c31
-rw-r--r--rpc_misc.c92
-rw-r--r--rpc_pkey.c26
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).
diff --git a/ks.c b/ks.c
index e966b94..92dc303 100644
--- a/ks.c
+++ b/ks.c
@@ -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.
*/
diff --git a/ks.h b/ks.h
index 240d3e6..1c09b53 100644
--- a/ks.h
+++ b/ks.h
@@ -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)
diff --git a/ks_token.c b/ks_token.c
index e69eb02..e29a90d 100644
--- a/ks_token.c
+++ b/ks_token.c
@@ -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 };
diff --git a/rpc_misc.c b/rpc_misc.c
index 3f466bb..6e64af2 100644
--- a/rpc_misc.c
+++ b/rpc_misc.c
@@ -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)
diff --git a/rpc_pkey.c b/rpc_pkey.c
index ff61580..3d4a379 100644
--- a/rpc_pkey.c
+++ b/rpc_pkey.c
@@ -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