aboutsummaryrefslogtreecommitdiff
path: root/ks.c
diff options
context:
space:
mode:
Diffstat (limited to 'ks.c')
-rw-r--r--ks.c123
1 files changed, 100 insertions, 23 deletions
diff --git a/ks.c b/ks.c
index a4e7498..2401a34 100644
--- a/ks.c
+++ b/ks.c
@@ -518,6 +518,46 @@ static inline int acceptable_key_type(const hal_key_type_t type)
}
}
+/*
+ * Internal bits of constructing a new key block.
+ */
+
+static hal_error_t construct_key_block(hal_ks_block_t *block,
+ hal_pkey_slot_t *slot,
+ const uint8_t * const der, const size_t der_len)
+{
+ if (block == NULL || slot == NULL || der == NULL || der_len == 0)
+ return HAL_ERROR_IMPOSSIBLE;
+
+ hal_ks_key_block_t *k = &block->key;
+ hal_error_t err = HAL_OK;
+ uint8_t kek[KEK_LENGTH];
+ size_t kek_len;
+
+ memset(block, 0xFF, sizeof(*block));
+
+ block->header.block_type = HAL_KS_BLOCK_TYPE_KEY;
+ block->header.block_status = HAL_KS_BLOCK_STATUS_LIVE;
+
+ k->name = slot->name;
+ k->type = slot->type;
+ k->curve = slot->curve;
+ k->flags = slot->flags;
+ k->der_len = SIZEOF_KS_KEY_BLOCK_DER;
+ k->attributes_len = 0;
+
+ if ((err = hal_mkm_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));
+
+ return err;
+}
+
+/*
+ * Store a key block.
+ */
+
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)
@@ -527,9 +567,6 @@ hal_error_t hal_ks_store(hal_ks_t *ks,
hal_error_t err = HAL_OK;
hal_ks_block_t *block;
- hal_ks_key_block_t *k;
- uint8_t kek[KEK_LENGTH];
- size_t kek_len;
unsigned b;
hal_ks_lock();
@@ -539,35 +576,16 @@ hal_error_t hal_ks_store(hal_ks_t *ks,
goto done;
}
- k = &block->key;
-
if ((err = hal_ks_index_add(ks, &slot->name, &b, &slot->hint)) != HAL_OK)
goto done;
hal_ks_cache_mark_used(ks, block, b);
- memset(block, 0xFF, sizeof(*block));
-
- block->header.block_type = HAL_KS_BLOCK_TYPE_KEY;
- block->header.block_status = HAL_KS_BLOCK_STATUS_LIVE;
-
- k->name = slot->name;
- k->type = slot->type;
- k->curve = slot->curve;
- k->flags = slot->flags;
- k->der_len = SIZEOF_KS_KEY_BLOCK_DER;
- k->attributes_len = 0;
-
if (ks->used < ks->size)
err = hal_ks_block_erase_maybe(ks, ks->index[ks->used]);
if (err == HAL_OK)
- err = hal_mkm_get_kek(kek, &kek_len, sizeof(kek));
-
- if (err == HAL_OK)
- err = hal_aes_keywrap(NULL, kek, kek_len, der, der_len, k->der, &k->der_len);
-
- memset(kek, 0, sizeof(kek));
+ err = construct_key_block(block, slot, der, der_len);
if (err == HAL_OK)
err = hal_ks_block_write(ks, b, block);
@@ -931,6 +949,65 @@ hal_error_t hal_ks_get_attributes(hal_ks_t *ks,
return err;
}
+hal_error_t hal_ks_rewrite_der(hal_ks_t *ks,
+ hal_pkey_slot_t *slot,
+ const uint8_t * const der, const size_t der_len)
+{
+ if (ks == NULL || slot == NULL || der == NULL || der_len == 0 || !acceptable_key_type(slot->type))
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ hal_ks_block_t *block = NULL;
+ hal_error_t err = HAL_OK;
+ unsigned b;
+
+ hal_ks_lock();
+
+ {
+ if ((err = hal_ks_index_find(ks, &slot->name, &b, &slot->hint)) != HAL_OK ||
+ (err = hal_ks_block_test_owner(ks, b, slot->client, slot->session)) != HAL_OK ||
+ (err = hal_ks_block_read_cached(ks, b, &block)) != HAL_OK)
+ goto done;
+
+ hal_ks_cache_mark_used(ks, block, b);
+
+ size_t bytes_len = 0, attributes_len = 0;
+ unsigned *count = NULL;
+ uint8_t *bytes = NULL;
+
+ if ((err = locate_attributes(block, &bytes, &bytes_len, &count)) != HAL_OK ||
+ (err = hal_ks_attribute_scan(bytes, bytes_len, NULL, *count, &attributes_len)) != HAL_OK)
+ goto done;
+
+ if (der_len + attributes_len > SIZEOF_KS_KEY_BLOCK_DER) {
+ err = HAL_ERROR_RESULT_TOO_LONG;
+ goto done;
+ }
+
+ uint8_t attributes[attributes_len > 0 ? attributes_len : 1];
+ hal_ks_key_block_t *k = &block->key;
+ unsigned attributes_count = *count;
+
+ memcpy(attributes, bytes, attributes_len);
+
+ if ((err = construct_key_block(block, slot, der, der_len)) != HAL_OK)
+ goto done;
+
+ if (k->der_len + attributes_len > SIZEOF_KS_KEY_BLOCK_DER) {
+ err = HAL_ERROR_IMPOSSIBLE;
+ goto done;
+ }
+
+ memcpy(k->der + k->der_len, attributes, attributes_len);
+ k->attributes_len = attributes_count;
+
+ err = hal_ks_block_update(ks, b, block, &slot->name, &slot->hint);
+ }
+
+ done:
+ hal_ks_unlock();
+ return err;
+}
+
/*
* Local variables:
* indent-tabs-mode: nil