aboutsummaryrefslogtreecommitdiff
path: root/ks.c
diff options
context:
space:
mode:
Diffstat (limited to 'ks.c')
-rw-r--r--ks.c411
1 files changed, 0 insertions, 411 deletions
diff --git a/ks.c b/ks.c
deleted file mode 100644
index 48d4751..0000000
--- a/ks.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * ks.c
- * ----
- * Keystore API. This is internal within libhal.
- *
- * Authors: Rob Austein
- * Copyright (c) 2015, 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 <string.h>
-#include <assert.h>
-
-#include "hal.h"
-#include "hal_internal.h"
-#include "last_gasp_pin_internal.h"
-
-#define KEK_LENGTH (bitsToBytes(256))
-
-/*
- * In "remote" and "mixed" RPC modes we're a software only RPC client
- * without (direct) access to secure hardware, thus there is no real
- * point in encrypting keys. As precautions, we (a) warn about this
- * when configured in one of these modes, and (b) refuse to store any
- * sort of private keys.
- */
-
-#define USE_KEK (RPC_CLIENT != RPC_CLIENT_REMOTE && RPC_CLIENT != RPC_CLIENT_MIXED)
-
-#if !USE_KEK
-#warning ks.c compiled without KEK support and will only accept public keys -- this is normal for the host-side build of libhsm
-#endif
-
-static inline int acceptable_key_type(const hal_key_type_t type)
-{
- switch (type) {
-#if USE_KEK
- case HAL_KEY_TYPE_RSA_PRIVATE:
- case HAL_KEY_TYPE_EC_PRIVATE:
-#endif
- case HAL_KEY_TYPE_RSA_PUBLIC:
- case HAL_KEY_TYPE_EC_PUBLIC:
- return 1;
- default:
- return 0;
- }
-}
-
-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)
-{
- if (name == NULL || der == NULL || der_len == 0 || !acceptable_key_type(type))
- return HAL_ERROR_BAD_ARGUMENTS;
-
- if (name_len > HAL_RPC_PKEY_NAME_MAX)
- return HAL_ERROR_KEY_NAME_TOO_LONG;
-
- const hal_ks_keydb_t * const db = hal_ks_get_keydb();
- hal_error_t err;
- int hint_;
-
- if (db == NULL)
- return HAL_ERROR_KEYSTORE_ACCESS;
-
- if (hint == NULL)
- hint = &hint_;
-
- *hint = -1;
-
- for (int i = 0; i < sizeof(db->keys)/sizeof(*db->keys); i++) {
- if (!db->keys[i].in_use && *hint < 0)
- *hint = i;
- if (db->keys[i].in_use &&
- db->keys[i].type == type &&
- db->keys[i].name_len == name_len && memcmp(db->keys[i].name, name, name_len) == 0)
- return HAL_ERROR_KEY_NAME_IN_USE;
- }
-
- if (*hint < 0)
- return HAL_ERROR_NO_KEY_SLOTS_AVAILABLE;
-
- hal_ks_key_t k;
- memset(&k, 0, sizeof(k));
- k.der_len = sizeof(k.der);
-
-#if USE_KEK
-
- 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;
-
-#else /* USE_KEK */
-
- if (der_len > k.der_len)
- return HAL_ERROR_RESULT_TOO_LONG;
-
- k.der_len = der_len;
- memcpy(k.der, der, der_len);
-
-#endif /* USE_KEK */
-
- assert(name_len <= sizeof(k.name));
- memcpy(k.name, name, name_len);
- k.name_len = name_len;
- k.type = type;
- k.curve = curve;
- k.flags = flags;
-
- if ((err = hal_ks_set_keydb(&k, *hint, 0)) != HAL_OK)
- return err;
-
- return HAL_OK;
-}
-
-static int find(const hal_ks_keydb_t * const db,
- const hal_key_type_t type,
- const uint8_t * const name, const size_t name_len,
- int *hint)
-{
- assert(db != NULL && name != NULL && acceptable_key_type(type));
-
- if (hint != NULL && *hint >= 0 && *hint < sizeof(db->keys)/sizeof(*db->keys) &&
- db->keys[*hint].in_use &&
- db->keys[*hint].type == type &&
- db->keys[*hint].name_len == name_len && memcmp(db->keys[*hint].name, name, name_len) == 0)
- return 1;
-
- for (int i = 0; i < sizeof(db->keys)/sizeof(*db->keys); i++) {
- if (!db->keys[i].in_use ||
- (hint != NULL && i == *hint) ||
- db->keys[i].type != type ||
- db->keys[i].name_len != name_len || memcmp(db->keys[i].name, name, name_len) != 0)
- continue;
- if (hint != NULL)
- *hint = i;
- return 1;
- }
-
- return 0;
-}
-
-hal_error_t hal_ks_exists(const hal_key_type_t type,
- const uint8_t * const name, const size_t name_len,
- int *hint)
-{
- if (name == NULL || !acceptable_key_type(type))
- return HAL_ERROR_BAD_ARGUMENTS;
-
- const hal_ks_keydb_t * const db = hal_ks_get_keydb();
-
- if (db == NULL)
- return HAL_ERROR_KEYSTORE_ACCESS;
-
- if (find(db, type, name, name_len, hint))
- return HAL_OK;
- else
- return HAL_ERROR_KEY_NOT_FOUND;
-}
-
-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)
-{
- if (name == NULL || !acceptable_key_type(type))
- return HAL_ERROR_BAD_ARGUMENTS;
-
- const hal_ks_keydb_t * const db = hal_ks_get_keydb();
- int hint_ = -1;
-
- if (db == NULL)
- return HAL_ERROR_KEYSTORE_ACCESS;
-
- if (hint == NULL)
- hint = &hint_;
-
- if (!find(db, type, name, name_len, hint))
- return HAL_ERROR_KEY_NOT_FOUND;
-
- const hal_ks_key_t * const k = &db->keys[*hint];
-
- if (curve != NULL)
- *curve = k->curve;
-
- if (flags != NULL)
- *flags = k->flags;
-
- if (der == NULL && der_len != NULL)
- *der_len = k->der_len;
-
- if (der != NULL) {
-
-#if USE_KEK
-
- 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;
-
-#else /* USE_KEK */
-
- if (k->der_len > der_max)
- return HAL_ERROR_RESULT_TOO_LONG;
-
- if (der_len != NULL)
- *der_len = k->der_len;
-
- memcpy(der, k->der, k->der_len);
-
-#endif /* USE_KEK */
- }
-
- return HAL_OK;
-}
-
-hal_error_t hal_ks_delete(const hal_key_type_t type,
- const uint8_t * const name, const size_t name_len,
- int *hint)
-{
- if (name == NULL || !acceptable_key_type(type))
- return HAL_ERROR_BAD_ARGUMENTS;
-
- const hal_ks_keydb_t * const db = hal_ks_get_keydb();
- int hint_ = -1;
-
- if (db == NULL)
- return HAL_ERROR_KEYSTORE_ACCESS;
-
- if (hint == NULL)
- hint = &hint_;
-
- if (!find(db, type, name, name_len, hint))
- return HAL_ERROR_KEY_NOT_FOUND;
-
- return hal_ks_del_keydb(*hint);
-}
-
-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)
-{
- if (old_name == NULL || new_name == NULL || !acceptable_key_type(type))
- return HAL_ERROR_BAD_ARGUMENTS;
-
- if (new_name_len > HAL_RPC_PKEY_NAME_MAX)
- return HAL_ERROR_KEY_NAME_TOO_LONG;
-
- const hal_ks_keydb_t * const db = hal_ks_get_keydb();
- int hint_ = -1;
-
- if (db == NULL)
- return HAL_ERROR_KEYSTORE_ACCESS;
-
- if (find(db, type, new_name, new_name_len, NULL))
- return HAL_ERROR_KEY_NAME_IN_USE;
-
- if (hint == NULL)
- hint = &hint_;
-
- if (!find(db, type, old_name, old_name_len, hint))
- return HAL_ERROR_KEY_NOT_FOUND;
-
- hal_ks_key_t k = db->keys[*hint];
-
- assert(new_name_len <= sizeof(k.name));
- memcpy(k.name, new_name, new_name_len);
- k.name_len = new_name_len;
-
- return hal_ks_set_keydb(&k, *hint, 1);
-}
-
-hal_error_t hal_ks_list(hal_pkey_info_t *result,
- unsigned *result_len,
- const unsigned result_max)
-{
- if (result == NULL || result_len == NULL)
- return HAL_ERROR_BAD_ARGUMENTS;
-
- const hal_ks_keydb_t * const db = hal_ks_get_keydb();
-
- if (db == NULL)
- return HAL_ERROR_KEYSTORE_ACCESS;
-
- *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_len = db->keys[i].name_len;
- memcpy(result[*result_len].name, db->keys[i].name, db->keys[i].name_len);
- ++ *result_len;
- }
-
- return HAL_OK;
-}
-
-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;
-
- const hal_ks_keydb_t * const db = hal_ks_get_keydb();
-
- if (db == NULL)
- return HAL_ERROR_KEYSTORE_ACCESS;
-
- 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;
- }
-
-#warning Need better "Have we been initialized yet?" test
- /*
- * 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.
- *
- * We probably need some more general "have we been initialized?"
- * state somewhere, and might want to refuse to do things like
- * storing keys until we've been initialized and the appropriate
- * PINs have been set.
- *
- * Just to make things more fun, some drivers return all zeros for
- * "this has never been set", some return all ones to indicate the
- * same thing. REALLY need a flag somewhere.
- */
-
- 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 HAL_OK;
-}
-
-/*
- * Local variables:
- * indent-tabs-mode: nil
- * End:
- */