aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2018-05-19 22:18:56 -0400
committerRob Austein <sra@hactrn.net>2018-05-19 22:24:31 -0400
commita5b4842f95ea501dacb1ed828c924f372d3f1262 (patch)
tree91fe51cfe75b908b8392d54a1074f38af976ad5f
parent0d17fd984e6ed486d6cd622edee226e263aab510 (diff)
Release keystore lock before unwrapping key.
hal_ks_fetch() was written as lock-at-the-top, unlock-at-the-bottom to keep it as simple as possible, but this turns out to have bad performance implications when unwrapping the key is slow. So now we grab the wrapped key, release the lock, then unwrap, which should be safe enough given that hal_ks_fetch() is read-only. This lets us make better use of multiple AES cores to unwrap in parallel when we have multiple active clients.
-rw-r--r--ks.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/ks.c b/ks.c
index 1598679..f4015e0 100644
--- a/ks.c
+++ b/ks.c
@@ -623,16 +623,17 @@ hal_error_t hal_ks_fetch(hal_ks_t *ks,
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;
+ goto unlock;
if (hal_ks_block_get_type(block) != HAL_KS_BLOCK_TYPE_KEY) {
err = HAL_ERROR_KEYSTORE_WRONG_BLOCK_TYPE; /* HAL_ERROR_KEY_NOT_FOUND */
- goto done;
+ goto unlock;
}
hal_ks_cache_mark_used(ks, block, b);
hal_ks_key_block_t *k = &block->key;
+ const size_t k_der_len = k->der_len;
slot->type = k->type;
slot->curve = k->curve;
@@ -641,6 +642,15 @@ hal_error_t hal_ks_fetch(hal_ks_t *ks,
if (der == NULL && der_len != NULL)
*der_len = k->der_len;
+ if (der != NULL && k_der_len <= der_max)
+ memcpy(der, k->der, k_der_len);
+
+ unlock:
+ hal_ks_unlock();
+
+ if (err != HAL_OK)
+ return err;
+
if (der != NULL) {
uint8_t kek[KEK_LENGTH];
@@ -653,13 +663,11 @@ hal_error_t hal_ks_fetch(hal_ks_t *ks,
*der_len = der_max;
if ((err = hal_mkm_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);
+ err = hal_aes_keyunwrap(NULL, kek, kek_len, der, k_der_len, der, der_len);
memset(kek, 0, sizeof(kek));
}
- done:
- hal_ks_unlock();
return err;
}