From 7c61f43d516dff9f1047d1c08a9bb778cb8edc68 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Wed, 24 May 2017 21:44:56 -0400 Subject: Checkpoint, not expected to work yet, includes a lot of notes. --- ks.c | 1131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1131 insertions(+) create mode 100644 ks.c (limited to 'ks.c') diff --git a/ks.c b/ks.c new file mode 100644 index 0000000..c107eb6 --- /dev/null +++ b/ks.c @@ -0,0 +1,1131 @@ +/* + * ks.c + * ---- + * Keystore, generic parts anyway. This is internal within libhal. + * + * Copyright (c) 2015-2017, 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 +#include + +#include "hal.h" +#include "hal_internal.h" +#include "ks.h" + +/* + * Find a block in the index, return true (found) or false (not found). + * "where" indicates the name's position, or the position of the first free block. + * + * NB: This does NOT return a block number, it returns an index into + * ks->index[]. + */ + +static int ks_find(const hal_ks_t * const ks, + const hal_uuid_t * const uuid, + const int * const hint, + int *where) +{ + if (ks == NULL || ks->index == NULL || ks->names == NULL || uuid == NULL || where == NULL) + return 0; + + if (hint != NULL && *hint >= 0 && *hint < ks->used && + hal_uuid_cmp(uuid, &ks->names[ks->index[*hint]]) == 0) { + *where = *hint; + return 1; + } + + int lo = -1; + int hi = ks->used; + + for (;;) { + int m = (lo + hi) / 2; + if (hi == 0 || m == lo) { + *where = hi; + return 0; + } + const int cmp = hal_uuid_cmp(uuid, &ks->names[ks->index[m]]); + if (cmp < 0) + hi = m; + else if (cmp > 0) + lo = m; + else { + *where = m; + return 1; + } + } +} + +/* + * Heapsort the index. We only need to do this on setup, for other + * operations we're just inserting or deleting a single entry in an + * already-ordered array, which is just a search problem. If we were + * really crunched for space, we could use an insertion sort here, but + * heapsort is easy and works well with data already in place. + */ + +static inline void ks_heapsift(hal_ks_t *ks, int parent, const int end) +{ + if (ks == NULL || ks->index == NULL || ks->names == NULL || parent < 0 || end < parent) + return; + for (;;) { + const int left_child = parent * 2 + 1; + const int right_child = parent * 2 + 2; + int biggest = parent; + if (left_child <= end && hal_uuid_cmp(&ks->names[ks->index[biggest]], + &ks->names[ks->index[left_child]]) < 0) + biggest = left_child; + if (right_child <= end && hal_uuid_cmp(&ks->names[ks->index[biggest]], + &ks->names[ks->index[right_child]]) < 0) + biggest = right_child; + if (biggest == parent) + return; + const uint16_t tmp = ks->index[biggest]; + ks->index[biggest] = ks->index[parent]; + ks->index[parent] = tmp; + parent = biggest; + } +} + +static inline void ks_heapsort(hal_ks_t *ks) +{ + if (ks == NULL || ks->index == NULL || ks->names == NULL) + return; + if (ks->used < 2) + return; + for (int i = (ks->used - 2) / 2; i >= 0; i--) + ks_heapsift(ks, i, ks->used - 1); + for (int i = ks->used - 1; i > 0; i--) { + const uint16_t tmp = ks->index[i]; + ks->index[i] = ks->index[0]; + ks->index[0] = tmp; + ks_heapsift(ks, 0, i - 1); + } +} + +/* + * Perform a consistency check on the index. + */ + +#define fsck(_ks) \ + do { hal_error_t _err = hal_ks_index_fsck(_ks); if (_err != HAL_OK) return _err; } while (0) + + +hal_error_t hal_ks_index_fsck(hal_ks_t *ks) +{ + if (ks == NULL || ks->index == NULL || ks->names == NULL || + ks->size == 0 || ks->used > ks->size) + return HAL_ERROR_BAD_ARGUMENTS; + + for (int i = 1; i < ks->used; i++) + if (hal_uuid_cmp(&ks->names[ks->index[i - 1]], &ks->names[ks->index[i]]) >= 0) + return HAL_ERROR_KS_INDEX_UUID_MISORDERED; + + return HAL_OK; +} + +/* + * Find a single block by name. + */ + +hal_error_t hal_ks_index_find(hal_ks_t *ks, + const hal_uuid_t * const name, + unsigned *blockno, + int *hint) +{ + if (ks == NULL || ks->index == NULL || ks->names == NULL || + ks->size == 0 || ks->used > ks->size || name == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + int where; + + fsck(ks); + + int ok = ks_find(ks, name, hint, &where); + + if (blockno != NULL) + *blockno = ks->index[where]; + + if (hint != NULL) + *hint = where; + + return ok ? HAL_OK : HAL_ERROR_KEY_NOT_FOUND; +} + +/* + * Add a single block to the index. + */ + +hal_error_t hal_ks_index_add(hal_ks_t *ks, + const hal_uuid_t * const name, + unsigned *blockno, + int *hint) +{ + if (ks == NULL || ks->index == NULL || ks->names == NULL || + ks->size == 0 || ks->used > ks->size || name == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + if (ks->used == ks->size) + return HAL_ERROR_NO_KEY_INDEX_SLOTS; + + int where; + + fsck(ks); + + if (ks_find(ks, name, hint, &where)) + return HAL_ERROR_KEY_NAME_IN_USE; + + /* + * Grab first block on free list, which makes room to slide the + * index up by one slot so we can insert the new block number. + */ + + const size_t len = (ks->used - where) * sizeof(*ks->index); + const uint16_t b = ks->index[ks->used++]; + memmove(&ks->index[where + 1], &ks->index[where], len); + ks->index[where] = b; + ks->names[b] = *name; + + if (blockno != NULL) + *blockno = b; + + if (hint != NULL) + *hint = where; + + fsck(ks); + + return HAL_OK; +} + +/* + * Delete a single block from the index. + */ + +hal_error_t hal_ks_index_delete(hal_ks_t *ks, + const hal_uuid_t * const name, + unsigned *blockno, + int *hint) +{ + if (ks == NULL || ks->index == NULL || ks->names == NULL || + ks->size == 0 || ks->used > ks->size || name == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + int where; + + fsck(ks); + + if (ks->used == 0 || !ks_find(ks, name, hint, &where)) + return HAL_ERROR_KEY_NOT_FOUND; + + /* + * Free the block and stuff it at the end of the free list. + */ + + const size_t len = (ks->size - where - 1) * sizeof(*ks->index); + const uint16_t b = ks->index[where]; + memmove(&ks->index[where], &ks->index[where + 1], len); + ks->index[ks->size - 1] = b; + ks->used--; + memset(&ks->names[b], 0, sizeof(ks->names[b])); + + if (blockno != NULL) + *blockno = b; + + if (hint != NULL) + *hint = where; + + fsck(ks); + + return HAL_OK; +} + +/* + * Replace a single block in the index. + */ + +hal_error_t hal_ks_index_replace(hal_ks_t *ks, + const hal_uuid_t * const name, + unsigned *blockno, + int *hint) +{ + if (ks == NULL || ks->index == NULL || ks->names == NULL || + ks->size == 0 || ks->used > ks->size || name == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + if (ks->used == ks->size) + return HAL_ERROR_NO_KEY_INDEX_SLOTS; + + int where; + + fsck(ks); + + if (ks->used == 0 || !ks_find(ks, name, hint, &where)) + return HAL_ERROR_KEY_NOT_FOUND; + + /* + * Grab first block from free list, slide free list down, put old + * block at end of free list and replace old block with new block. + */ + + const size_t len = (ks->size - ks->used - 1) * sizeof(*ks->index); + const uint16_t b1 = ks->index[where]; + const uint16_t b2 = ks->index[ks->used]; + memmove(&ks->index[ks->used], &ks->index[ks->used + 1], len); + ks->index[ks->size - 1] = b1; + ks->index[where] = b2; + ks->names[b2] = *name; + memset(&ks->names[b1], 0, sizeof(ks->names[b1])); + + if (blockno != NULL) + *blockno = b2; + + if (hint != NULL) + *hint = where; + + fsck(ks); + + return HAL_OK; +} + +/* + * Pick unused or least-recently-used slot in our in-memory cache. + * + * Updating lru values is caller's problem: if caller is using a cache + * slot as a temporary buffer and there's no point in caching the + * result, leave the lru values alone and the right thing will happen. + */ + +static inline ks_block_t *cache_pick_lru(hal_ks_t *ks) +{ + uint32_t best_delta = 0; + int best_index = 0; + + for (int i = 0; i < ks->cache_size; i++) { + + if (ks->cache[i].blockno == ~0) + return &ks->cache[i].block; + + const unsigned delta = ks->cache_lru - ks->cache[i].lru; + if (delta > best_delta) { + best_delta = delta; + best_index = i; + } + + } + + ks->cache[best_index].blockno = ~0; + return &ks->cache[best_index].block; +} + +/* + * Find a block in our in-memory cache; return block or NULL if not present. + */ + +static inline ks_block_t *cache_find_block(const hal_ks_t * const ks, const unsigned blockno) +{ + for (int i = 0; i < ks->cache_size; i++) + if (ks->cache[i].blockno == blockno) + return &ks->cache[i].block; + return NULL; +} + +/* + * Mark a block in our in-memory cache as being in current use. + */ + +static inline void cache_mark_used(hal_ks_t *ks, const ks_block_t * const block, const unsigned blockno) +{ + for (int i = 0; i < ks->cache_size; i++) { + if (&ks->cache[i].block == block) { + ks->cache[i].blockno = blockno; + ks->cache[i].lru = ++ks->cache_lru; + return; + } + } +} + +/* + * Release a block from the in-memory cache. + */ + +static inline void cache_release(hal_ks_t *ks, const ks_block_t * const block) +{ + if (block != NULL) + cache_mark_used(block, ~0); +} + +/* + * Generate CRC-32 for a block. + * + * This function needs to understand the structure of + * ks_block_header_t, so that it can skip over fields that + * shouldn't be included in the CRC. + */ + +static hal_crc32_t calculate_block_crc(const ks_block_t * const block) +{ + hal_crc32_t crc = hal_crc32_init(); + + if (block != NULL) { + + crc = hal_crc32_update(crc, &block->header.block_type, + sizeof(block->header.block_type)); + + crc = hal_crc32_update(crc, + block->bytes + sizeof(ks_block_header_t), + sizeof(*block) - sizeof(ks_block_header_t)); + } + + return hal_crc32_finalize(crc); +} + +/* + * Read a block using the cache. Marking the block as used is left + * for the caller, so we can avoid blowing out the cache when we + * perform a ks_match() operation. + */ + +static hal_error_t block_read_cached(hal_ks_t *ks, const unsigned blockno, ks_block_t **block) +{ + if (block == NULL) + return HAL_ERROR_IMPOSSIBLE; + + if ((*block = cache_find_block(ks, blockno)) != NULL) + return HAL_OK; + + if ((*block = cache_pick_lru(ks)) == NULL) + return HAL_ERROR_IMPOSSIBLE; + + return block_read(ks, blockno, *block); +} + +/* + * Update one block, including zombie jamboree. + */ + +static hal_error_t block_update(hal_ks_t *ks, + const unsigned b1, + ks_block_t *block, + const hal_uuid_t * const uuid, + int *hint) +{ + if (block == NULL) + return HAL_ERROR_IMPOSSIBLE; + + if (ks->used == ks->size) + return HAL_ERROR_NO_KEY_INDEX_SLOTS; + + cache_release(block); + + hal_error_t err; + unsigned b2; + + if ((err = block_deprecate(ks, b1)) != HAL_OK || + (err = hal_ks_index_replace(ks, uuid, &b2, hint)) != HAL_OK || + (err = block_write(ks, b2, block)) != HAL_OK || + (err = block_zero(ks, b1)) != HAL_OK) + return err; + + cache_mark_used(ks, block, b2); + + /* + * Erase the first block in the free list. In case of restart, this + * puts the block back at the head of the free list. + */ + + return block_erase_maybe(ks, ks->index[ks->used]); +} + +/* + * Initialize keystore. This includes various tricky bits, some of + * which attempt to preserve the free list ordering across reboots, to + * improve our simplistic attempt at wear leveling, others attempt to + * recover from unclean shutdown. + */ + +static inline void *gnaw(uint8_t **mem, size_t *len, const size_t size) +{ + if (mem == NULL || *mem == NULL || len == NULL || size > *len) + return NULL; + void *ret = *mem; + *mem += size; + *len -= size; + return ret; +} + +#warning Call ks_alloc_common() and ks_init_common() while holding hal_ks_lock(); ! + +hal_error_t ks_alloc_common(hal_ks_t *ks, const unsigned ks_blocks, const unsigned cache_blocks) +{ + /* + * We allocate a single big chunk of memory rather than three + * smaller chunks to make it atomic. We need all three, so this way + * either all succeed or all fail. + */ + + size_t len = (sizeof(*ks->index) * ks_blocks + + sizeof(*ks->names) * ks_blocks + + sizeof(*ks->cache) * cache_blocks); + + uint8_t *mem = hal_allocate_static_memory(len); + + if (mem == NULL) + return HAL_ERROR_ALLOCATION_FAILURE; + + memset(ks, 0, sizeof(*ks)); + memset(mem, 0, len); + + ks->index = gnaw(&mem, &len, sizeof(*ks->index) * ks_blocks); + ks->names = gnaw(&mem, &len, sizeof(*ks->names) * ks_blocks); + ks->cache = gnaw(&mem, &len, sizeof(*ks->cache) * cache_blocks); + + ks->size = ks_blocks; + ks->cache_size = cache_blocks; + + return HAL_OK; +} + +hal_error_t ks_init_common(hal_ks_t *ks, const hal_ks_driver_t * const driver) +{ + if (ks->index == NULL || ks->names == NULL || ks->cache == NULL) + return HAL_ERROR_IMPOSSIBLE; + + ks->used = 0; + + for (int i = 0; i < ks->cache_size; i++) + ks->cache[i].blockno = ~0; + + /* + * Scan existing content of keystore to figure out what we've got. + * This gets a bit involved due to the need to recover from things + * like power failures at inconvenient times. + */ + + ks_block_type_t block_types[ks->size]; + ks_block_status_t block_status[ks->size]; + ks_block_t *block = cache_pick_lru(ks); + int first_erased = -1; + hal_error_t err; + uint16_t n = 0; + + if (block == NULL) + return HAL_ERROR_IMPOSSIBLE; + + for (int i = 0; i < ks->size; i++) { + + /* + * Read one block. If the CRC is bad or the block type is + * unknown, it's old data we don't understand, something we were + * writing when we crashed, or bad flash; in any of these cases, + * we want the block to end up near the end of the free list. + */ + + err = block_read(ks, i, block); + + if (err == HAL_ERROR_KEYSTORE_BAD_CRC || err == HAL_ERROR_KEYSTORE_BAD_BLOCK_TYPE) + block_types[i] = BLOCK_TYPE_UNKNOWN; + + else if (err == HAL_OK) + block_types[i] = block_get_type(block); + + else + return err; + + switch (block_types[i]) { + case BLOCK_TYPE_KEY: + case BLOCK_TYPE_PIN: + block_status[i] = block_get_status(block); + break; + default: + block_status[i] = BLOCK_STATUS_UNKNOWN; + } + + /* + * First erased block we see is head of the free list. + */ + + if (block_types[i] == BLOCK_TYPE_ERASED && first_erased < 0) + first_erased = i; + + /* + * If it's a valid data block, include it in the index. We remove + * tombstones (if any) below, for now it's easiest to include them + * in the index, so we can look them up by name if we must. + */ + + const hal_uuid_t *uuid = NULL; + + switch (block_types[i]) { + case BLOCK_TYPE_KEY: uuid = &block->key.name; break; + case BLOCK_TYPE_PIN: uuid = &pin_uuid; break; + default: /* Keep GCC happy */ break; + } + + if (uuid != NULL) { + ks->names[i] = *uuid; + ks->index[n++] = i; + } + } + + ks->used = n; + + if (ks->used > ks->size) + return HAL_ERROR_IMPOSSIBLE; + + /* + * At this point we've built the (unsorted) index from all the valid + * blocks. Now we need to insert free and unrecognized blocks into + * the free list in our preferred order. It's possible that there's + * a better way to do this than linear scan, but this is just + * integer comparisons in a fairly small data set, so it's probably + * not worth trying to optimize. + */ + + if (n < ks->size) + for (int i = 0; i < ks->size; i++) + if (block_types[i] == BLOCK_TYPE_ERASED) + ks->index[n++] = i; + + if (n < ks->size) + for (int i = first_erased; i < ks->size; i++) + if (block_types[i] == BLOCK_TYPE_ZEROED) + ks->index[n++] = i; + + if (n < ks->size) + for (int i = 0; i < first_erased; i++) + if (block_types[i] == BLOCK_TYPE_ZEROED) + ks->index[n++] = i; + + if (n < ks->size) + for (int i = 0; i < ks->size; i++) + if (block_types[i] == BLOCK_TYPE_UNKNOWN) + ks->index[n++] = i; + + if (ks->used > ks->size) + return HAL_ERROR_IMPOSSIBLE; + + /* + * Sort the index, then deal with tombstones. Tombstones are blocks + * left behind when something bad (like a power failure) happened + * while we updating. There can be at most one tombstone and one + * live block for a given UUID. If we find no live block, we need + * to restore it from the tombstone, after which we need to zero the + * tombstone in either case. The sequence of operations while + * updating is designed so that, barring a bug or a hardware + * failure, we should never lose data. + */ + + ks_heapsort(ks); + + for (unsigned b_tomb = 0; b_tomb < ks->size; b_tomb++) { + + if (block_status[b_tomb] != BLOCK_STATUS_TOMBSTONE) + continue; + + hal_uuid_t name = ks->names[b_tomb]; + + int where = -1; + + if ((err = hal_ks_index_find(ks, &name, NULL, &where)) != HAL_OK) + return err; + + if (b_tomb != ks->index[where]) { + if (ks->used > where + 1 && b_tomb == ks->index[where + 1]) + where = where + 1; + else if (0 <= where - 1 && b_tomb == ks->index[where - 1]) + where = where - 1; + else + return HAL_ERROR_IMPOSSIBLE; + } + + const int matches_next = where + 1 < ks->used && !hal_uuid_cmp(&name, &ks->names[ks->index[where + 1]]); + const int matches_prev = where - 1 >= 0 && !hal_uuid_cmp(&name, &ks->names[ks->index[where - 1]]); + + if ((matches_prev && matches_next) || + (matches_prev && block_status[ks->index[b_tomb - 1]] != BLOCK_STATUS_LIVE) || + (matches_next && block_status[ks->index[b_tomb + 1]] != BLOCK_STATUS_LIVE)) + return HAL_ERROR_IMPOSSIBLE; + + if (matches_prev || matches_next) { + memmove(&ks->index[where], &ks->index[where + 1], (ks->size - where - 1) * sizeof(*ks->index)); + ks->index[ks->size - 1] = b_tomb; + } + + else { + unsigned b_live; + if ((err = block_read(ks, b_tomb, block)) != HAL_OK) + return err; + block->header.block_status = BLOCK_STATUS_LIVE; + if ((err = hal_ks_index_replace(ks, &name, &b_live, &where)) != HAL_OK || + (err = block_write(ks, b_live, block)) != HAL_OK) + return err; + block_status[b_live] = BLOCK_STATUS_LIVE; + } + + if ((err = block_zero(ks, b_tomb)) != HAL_OK) + return err; + block_types[ b_tomb] = BLOCK_TYPE_ZEROED; + block_status[b_tomb] = BLOCK_STATUS_UNKNOWN; + } + + /* + * Erase first block on free list if it's not already erased. + */ + + if (ks->used < ks->size && + (err = block_erase_maybe(ks, ks->index[ks->used])) != HAL_OK) + return err; + + /* + * And we're finally done. + */ + + ks->driver = driver; + + return HAL_OK; +} + +static inline int acceptable_key_type(const hal_key_type_t type) +{ + switch (type) { + case HAL_KEY_TYPE_RSA_PRIVATE: + case HAL_KEY_TYPE_EC_PRIVATE: + case HAL_KEY_TYPE_RSA_PUBLIC: + case HAL_KEY_TYPE_EC_PUBLIC: + return 1; + default: + return 0; + } +} + +hal_error_t ks_store(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_error_t err = HAL_OK; + ks_block_t *block; + flash_key_block_t *k; + uint8_t kek[KEK_LENGTH]; + size_t kek_len; + unsigned b; + + hal_ks_lock(); + + if ((block = cache_pick_lru(ks)) == NULL) { + err = HAL_ERROR_IMPOSSIBLE; + goto done; + } + + k = &block->key; + + if ((err = hal_ks_index_add(ks, &slot->name, &b, &slot->hint)) != HAL_OK) + goto done; + + cache_mark_used(ks, block, b); + + memset(block, 0xFF, sizeof(*block)); + + block->header.block_type = BLOCK_TYPE_KEY; + block->header.block_status = BLOCK_STATUS_LIVE; + + k->name = slot->name; + k->type = slot->type; + k->curve = slot->curve; + k->flags = slot->flags; + k->der_len = SIZEOF_FLASH_KEY_BLOCK_DER; + k->attributes_len = 0; + + if (ks->used < ks->size) + err = 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)); + + if (err == HAL_OK) + err = block_write(ks, b, block); + + if (err == HAL_OK) + goto done; + + memset(block, 0, sizeof(*block)); + cache_release(ks, block); + (void) hal_ks_index_delete(ks, &slot->name, NULL, &slot->hint); + + done: + hal_ks_unlock(); + return err; +} + +static hal_error_t ks_fetch(hal_ks_t *ks, + hal_pkey_slot_t *slot, + uint8_t *der, size_t *der_len, const size_t der_max) +{ + if (ks == NULL || slot == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + hal_error_t err = HAL_OK; + ks_block_t *block; + unsigned b; + + hal_ks_lock(); + + if ((err = hal_ks_index_find(ks, &slot->name, &b, &slot->hint)) != HAL_OK || + (err = block_read_cached(ks, b, &block)) != HAL_OK) + goto done; + + if (block_get_type(block) != BLOCK_TYPE_KEY) { + err = HAL_ERROR_KEYSTORE_WRONG_BLOCK_TYPE; /* HAL_ERROR_KEY_NOT_FOUND */ + goto done; + } + + cache_mark_used(ks, block, b); + + flash_key_block_t *k = &block->key; + + slot->type = k->type; + slot->curve = k->curve; + slot->flags = k->flags; + + if (der == NULL && der_len != NULL) + *der_len = k->der_len; + + if (der != NULL) { + + 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_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); + + memset(kek, 0, sizeof(kek)); + } + + done: + hal_ks_unlock(); + return err; +} + +static hal_error_t ks_delete(hal_ks_t *ks, + hal_pkey_slot_t *slot) +{ + if (ks == NULL || slot == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + hal_error_t err = HAL_OK; + unsigned b; + + hal_ks_lock(); + + if ((err = hal_ks_index_delete(ks, &slot->name, &b, &slot->hint)) != HAL_OK) + goto done; + + cache_release(ks, cache_find_block(ks, b)); + + if ((err = block_zero(ks, b)) != HAL_OK) + goto done; + + err = block_erase_maybe(ks, ks->index[ks->used]); + + done: + hal_ks_unlock(); + return err; +} + +static inline hal_error_t locate_attributes(ks_block_t *block, + uint8_t **bytes, size_t *bytes_len, + unsigned **attrs_len) +{ + if (block == NULL || bytes == NULL || bytes_len == NULL || attrs_len == NULL) + return HAL_ERROR_IMPOSSIBLE; + + + if (block_get_type(block) != BLOCK_TYPE_KEY) + return HAL_ERROR_KEYSTORE_WRONG_BLOCK_TYPE; + *attrs_len = &block->key.attributes_len; + *bytes = block->key.der + block->key.der_len; + *bytes_len = SIZEOF_FLASH_KEY_BLOCK_DER - block->key.der_len; + + return HAL_OK; +} + +static hal_error_t ks_match(hal_ks_t *ks, + const hal_client_handle_t client, + const hal_session_handle_t session, + const hal_key_type_t type, + const hal_curve_name_t curve, + const hal_key_flags_t mask, + const hal_key_flags_t flags, + const hal_pkey_attribute_t *attributes, + const unsigned attributes_len, + hal_uuid_t *result, + unsigned *result_len, + const unsigned result_max, + const hal_uuid_t * const previous_uuid) +{ + if (ks == NULL || (attributes == NULL && attributes_len > 0) || + result == NULL || result_len == NULL || previous_uuid == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + hal_error_t err = HAL_OK; + ks_block_t *block; + int i = -1; + + hal_ks_lock(); + + *result_len = 0; + + err = hal_ks_index_find(ks, previous_uuid, NULL, &i); + + if (err == HAL_ERROR_KEY_NOT_FOUND) + i--; + else if (err != HAL_OK) + goto done; + + while (*result_len < result_max && ++i < ks->used) { + + unsigned b = ks->index[i]; + + if ((err = block_read_cached(ks, b, &block)) != HAL_OK) + goto done; + + if ((type != HAL_KEY_TYPE_NONE && type != block->key.type) || + (curve != HAL_CURVE_NONE && curve != block->key.curve) || + ((flags ^ block->key.flags) & mask) != 0) + continue; + + if (attributes_len > 0) { + uint8_t need_attr[attributes_len]; + uint8_t *bytes = NULL; + size_t bytes_len = 0; + unsigned *attrs_len; + int possible = 1; + + memset(need_attr, 1, sizeof(need_attr)); + + if ((err = locate_attributes(block, &bytes, &bytes_len, &attrs_len)) != HAL_OK) + goto done; + + if (*attrs_len > 0) { + hal_pkey_attribute_t attrs[*attrs_len]; + + if ((err = hal_ks_attribute_scan(bytes, bytes_len, attrs, *attrs_len, NULL)) != HAL_OK) + goto done; + + for (int j = 0; possible && j < attributes_len; j++) { + + if (!need_attr[j]) + continue; + + for (hal_pkey_attribute_t *a = attrs; a < attrs + *attrs_len; a++) { + if (a->type != attributes[j].type) + continue; + need_attr[j] = 0; + possible = (a->length == attributes[j].length && + !memcmp(a->value, attributes[j].value, a->length)); + break; + } + } + } + + if (!possible || memchr(need_attr, 1, sizeof(need_attr)) != NULL) + continue; + } + + result[*result_len] = ks->names[b]; + ++*result_len; + } + + err = HAL_OK; + + done: + hal_ks_unlock(); + return err; +} + +static hal_error_t ks_set_attributes(hal_ks_t *ks, + hal_pkey_slot_t *slot, + const hal_pkey_attribute_t *attributes, + const unsigned attributes_len) +{ + if (ks == NULL || slot == NULL || attributes == NULL || attributes_len == 0) + return HAL_ERROR_BAD_ARGUMENTS; + + hal_error_t err = HAL_OK; + ks_block_t *block; + unsigned b; + + hal_ks_lock(); + + { + if ((err = hal_ks_index_find(ks, &slot->name, &b, &slot->hint)) != HAL_OK || + (err = block_read_cached(ks, b, &block)) != HAL_OK) + goto done; + + cache_mark_used(ks, block, b); + + uint8_t *bytes = NULL; + size_t bytes_len = 0; + unsigned *attrs_len; + + if ((err = locate_attributes(block, &bytes, &bytes_len, &attrs_len)) != HAL_OK) + goto done; + + hal_pkey_attribute_t attrs[*attrs_len + attributes_len]; + size_t total; + + if ((err = hal_ks_attribute_scan(bytes, bytes_len, attrs, *attrs_len, &total)) != HAL_OK) + goto done; + + for (int i = 0; err == HAL_OK && i < attributes_len; i++) + if (attributes[i].length == HAL_PKEY_ATTRIBUTE_NIL) + err = hal_ks_attribute_delete(bytes, bytes_len, attrs, attrs_len, &total, + attributes[i].type); + else + err = hal_ks_attribute_insert(bytes, bytes_len, attrs, attrs_len, &total, + attributes[i].type, + attributes[i].value, + attributes[i].length); + + if (err == HAL_OK) + err = block_update(ks, b, block, &slot->name, &slot->hint); + else + cache_release(ks, block); + } + + done: + hal_ks_unlock(); + return err; +} + +static hal_error_t ks_get_attributes(hal_ks_t *ks, + hal_pkey_slot_t *slot, + hal_pkey_attribute_t *attributes, + const unsigned attributes_len, + uint8_t *attributes_buffer, + const size_t attributes_buffer_len) +{ + if (ks == NULL || slot == NULL || attributes == NULL || attributes_len == 0 || + attributes_buffer == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + for (int i = 0; i < attributes_len; i++) { + attributes[i].length = 0; + attributes[i].value = NULL; + } + + uint8_t *abuf = attributes_buffer; + ks_block_t *block = NULL; + hal_error_t err = HAL_OK; + unsigned found = 0; + unsigned b; + + hal_ks_lock(); + + { + if ((err = hal_ks_index_find(ks, &slot->name, &b, &slot->hint)) != HAL_OK || + (err = block_read_cached(ks, b, &block)) != HAL_OK) + goto done; + + cache_mark_used(ks, block, b); + + uint8_t *bytes = NULL; + size_t bytes_len = 0; + unsigned *attrs_len; + + if ((err = locate_attributes(block, &bytes, &bytes_len, &attrs_len)) != HAL_OK) + goto done; + + if (*attrs_len == 0) { + err = HAL_ERROR_ATTRIBUTE_NOT_FOUND; + goto done; + } + + hal_pkey_attribute_t attrs[*attrs_len]; + + if ((err = hal_ks_attribute_scan(bytes, bytes_len, attrs, *attrs_len, NULL)) != HAL_OK) + goto done; + + for (int i = 0; i < attributes_len; i++) { + + if (attributes[i].length > 0) + continue; + + int j = 0; + while (j < *attrs_len && attrs[j].type != attributes[i].type) + j++; + if (j >= *attrs_len) + continue; + found++; + + attributes[i].length = attrs[j].length; + + if (attributes_buffer_len == 0) + continue; + + if (attrs[j].length > attributes_buffer + attributes_buffer_len - abuf) { + err = HAL_ERROR_RESULT_TOO_LONG; + goto done; + } + + memcpy(abuf, attrs[j].value, attrs[j].length); + attributes[i].value = abuf; + abuf += attrs[j].length; + } + + }; + + if (found < attributes_len && attributes_buffer_len > 0) + err = HAL_ERROR_ATTRIBUTE_NOT_FOUND; + else + err = HAL_OK; + + done: + hal_ks_unlock(); + return err; +} + +/* + * Local variables: + * indent-tabs-mode: nil + * End: + */ -- cgit v1.2.3 From c1b19879e13e5717867c73b3273b0fbdeea88c01 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Wed, 24 May 2017 22:36:55 -0400 Subject: Type name cleanup, key visibility. --- ks.c | 181 ++++++++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 119 insertions(+), 62 deletions(-) (limited to 'ks.c') diff --git a/ks.c b/ks.c index c107eb6..89babc2 100644 --- a/ks.c +++ b/ks.c @@ -321,7 +321,7 @@ hal_error_t hal_ks_index_replace(hal_ks_t *ks, * result, leave the lru values alone and the right thing will happen. */ -static inline ks_block_t *cache_pick_lru(hal_ks_t *ks) +static inline hal_ks_block_t *cache_pick_lru(hal_ks_t *ks) { uint32_t best_delta = 0; int best_index = 0; @@ -347,7 +347,7 @@ static inline ks_block_t *cache_pick_lru(hal_ks_t *ks) * Find a block in our in-memory cache; return block or NULL if not present. */ -static inline ks_block_t *cache_find_block(const hal_ks_t * const ks, const unsigned blockno) +static inline hal_ks_block_t *cache_find_block(const hal_ks_t * const ks, const unsigned blockno) { for (int i = 0; i < ks->cache_size; i++) if (ks->cache[i].blockno == blockno) @@ -359,7 +359,7 @@ static inline ks_block_t *cache_find_block(const hal_ks_t * const ks, const unsi * Mark a block in our in-memory cache as being in current use. */ -static inline void cache_mark_used(hal_ks_t *ks, const ks_block_t * const block, const unsigned blockno) +static inline void cache_mark_used(hal_ks_t *ks, const hal_ks_block_t * const block, const unsigned blockno) { for (int i = 0; i < ks->cache_size; i++) { if (&ks->cache[i].block == block) { @@ -374,7 +374,7 @@ static inline void cache_mark_used(hal_ks_t *ks, const ks_block_t * const block, * Release a block from the in-memory cache. */ -static inline void cache_release(hal_ks_t *ks, const ks_block_t * const block) +static inline void cache_release(hal_ks_t *ks, const hal_ks_block_t * const block) { if (block != NULL) cache_mark_used(block, ~0); @@ -383,12 +383,12 @@ static inline void cache_release(hal_ks_t *ks, const ks_block_t * const block) /* * Generate CRC-32 for a block. * - * This function needs to understand the structure of - * ks_block_header_t, so that it can skip over fields that + * This function needs to understand the structure of the + * hal_ks_block_header_t, so that it can skip over fields that * shouldn't be included in the CRC. */ -static hal_crc32_t calculate_block_crc(const ks_block_t * const block) +static hal_crc32_t calculate_block_crc(const hal_ks_block_t * const block) { hal_crc32_t crc = hal_crc32_init(); @@ -398,8 +398,8 @@ static hal_crc32_t calculate_block_crc(const ks_block_t * const block) sizeof(block->header.block_type)); crc = hal_crc32_update(crc, - block->bytes + sizeof(ks_block_header_t), - sizeof(*block) - sizeof(ks_block_header_t)); + block->bytes + sizeof(hal_ks_block_header_t), + sizeof(*block) - sizeof(hal_ks_block_header_t)); } return hal_crc32_finalize(crc); @@ -408,10 +408,10 @@ static hal_crc32_t calculate_block_crc(const ks_block_t * const block) /* * Read a block using the cache. Marking the block as used is left * for the caller, so we can avoid blowing out the cache when we - * perform a ks_match() operation. + * perform a hal_ks_match() operation. */ -static hal_error_t block_read_cached(hal_ks_t *ks, const unsigned blockno, ks_block_t **block) +static hal_error_t block_read_cached(hal_ks_t *ks, const unsigned blockno, hal_ks_block_t **block) { if (block == NULL) return HAL_ERROR_IMPOSSIBLE; @@ -431,7 +431,7 @@ static hal_error_t block_read_cached(hal_ks_t *ks, const unsigned blockno, ks_bl static hal_error_t block_update(hal_ks_t *ks, const unsigned b1, - ks_block_t *block, + hal_ks_block_t *block, const hal_uuid_t * const uuid, int *hint) { @@ -479,9 +479,9 @@ static inline void *gnaw(uint8_t **mem, size_t *len, const size_t size) return ret; } -#warning Call ks_alloc_common() and ks_init_common() while holding hal_ks_lock(); ! +#warning Call hal_ks_alloc_common() and hal_ks_init_common() while holding hal_ks_lock(); ! -hal_error_t ks_alloc_common(hal_ks_t *ks, const unsigned ks_blocks, const unsigned cache_blocks) +hal_error_t hal_ks_alloc_common(hal_ks_t *ks, const unsigned ks_blocks, const unsigned cache_blocks) { /* * We allocate a single big chunk of memory rather than three @@ -511,7 +511,7 @@ hal_error_t ks_alloc_common(hal_ks_t *ks, const unsigned ks_blocks, const unsign return HAL_OK; } -hal_error_t ks_init_common(hal_ks_t *ks, const hal_ks_driver_t * const driver) +hal_error_t hal_ks_init_common(hal_ks_t *ks, const hal_ks_driver_t * const driver) { if (ks->index == NULL || ks->names == NULL || ks->cache == NULL) return HAL_ERROR_IMPOSSIBLE; @@ -527,9 +527,9 @@ hal_error_t ks_init_common(hal_ks_t *ks, const hal_ks_driver_t * const driver) * like power failures at inconvenient times. */ - ks_block_type_t block_types[ks->size]; - ks_block_status_t block_status[ks->size]; - ks_block_t *block = cache_pick_lru(ks); + hal_ks_block_type_t block_types[ks->size]; + hal_ks_block_status_t block_status[ks->size]; + hal_ks_block_t *block = cache_pick_lru(ks); int first_erased = -1; hal_error_t err; uint16_t n = 0; @@ -711,6 +711,10 @@ hal_error_t ks_init_common(hal_ks_t *ks, const hal_ks_driver_t * const driver) return HAL_OK; } +/* + * Test whether we like a particular key type. + */ + static inline int acceptable_key_type(const hal_key_type_t type) { switch (type) { @@ -724,15 +728,56 @@ static inline int acceptable_key_type(const hal_key_type_t type) } } -hal_error_t ks_store(hal_ks_t *ks, - hal_pkey_slot_t *slot, - const uint8_t * const der, const size_t der_len) +/* + * Test whether the current session can see a particular key. One + * might expect this to be based on whether the session matches, and + * indeed it would be in a sane world, but in the world of PKCS #11, + * keys belong to sessions, are visible to other sessions, and may + * even be modifiable by other sessions, but softly and silently + * vanish away when the original creating session is destroyed. + * + * In our terms, this means that visibility of session objects is + * determined only by the client handle, so taking the session handle + * as an argument here isn't really necessary, but we've flipflopped + * on that enough times that at least for now I'd prefer to leave the + * session handle here and not have to revise all the RPC calls again. + * Remove it at some later date and redo the RPC calls if we manage to + * avoid revising this yet again. + */ + +static inline hal_error_t key_visible(const hal_ks_t * const ks, + const hal_client_handle_t client, + const hal_session_handle_t session, + const unsigned blockno) +{ + if (ks == NULL) + return HAL_ERROR_IMPOSSIBLE; + + if (!ks->per_session) + return HAL_OK; + + hal_error_t err; + + if ((err = hal_ks_test_owner(ks, client, session)) != HAL_OK) + return err; + + err = hal_rpc_is_logged_in(client, HAL_USER_WHEEL); + + if (err == HAL_ERROR_FORBIDDEN) + err = HAL_ERROR_KEY_NOT_FOUND; + + return err; +} + +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) { if (ks == NULL || slot == NULL || der == NULL || der_len == 0 || !acceptable_key_type(slot->type)) return HAL_ERROR_BAD_ARGUMENTS; hal_error_t err = HAL_OK; - ks_block_t *block; + hal_ks_block_t *block; flash_key_block_t *k; uint8_t kek[KEK_LENGTH]; size_t kek_len; @@ -778,6 +823,9 @@ hal_error_t ks_store(hal_ks_t *ks, if (err == HAL_OK) err = block_write(ks, b, block); + if (err == HAL_OK) + err = hal_ks_set_owner(ks, b, slot->client_handle, slot->session_handle); + if (err == HAL_OK) goto done; @@ -790,21 +838,22 @@ hal_error_t ks_store(hal_ks_t *ks, return err; } -static hal_error_t ks_fetch(hal_ks_t *ks, - hal_pkey_slot_t *slot, - uint8_t *der, size_t *der_len, const size_t der_max) +hal_error_t hal_ks_fetch(hal_ks_t *ks, + hal_pkey_slot_t *slot, + uint8_t *der, size_t *der_len, const size_t der_max) { if (ks == NULL || slot == NULL) return HAL_ERROR_BAD_ARGUMENTS; hal_error_t err = HAL_OK; - ks_block_t *block; + hal_ks_block_t *block; unsigned b; hal_ks_lock(); - if ((err = hal_ks_index_find(ks, &slot->name, &b, &slot->hint)) != HAL_OK || - (err = block_read_cached(ks, b, &block)) != HAL_OK) + if ((err = hal_ks_index_find(ks, &slot->name, &b, &slot->hint)) != HAL_OK || + (err = key_visible(ks, slot->client_handle, slot->session_handle, b)) != HAL_OK || + (err = block_read_cached(ks, b, &block)) != HAL_OK) goto done; if (block_get_type(block) != BLOCK_TYPE_KEY) { @@ -845,8 +894,8 @@ static hal_error_t ks_fetch(hal_ks_t *ks, return err; } -static hal_error_t ks_delete(hal_ks_t *ks, - hal_pkey_slot_t *slot) +hal_error_t hal_ks_delete(hal_ks_t *ks, + hal_pkey_slot_t *slot) { if (ks == NULL || slot == NULL) return HAL_ERROR_BAD_ARGUMENTS; @@ -856,7 +905,8 @@ static hal_error_t ks_delete(hal_ks_t *ks, hal_ks_lock(); - if ((err = hal_ks_index_delete(ks, &slot->name, &b, &slot->hint)) != HAL_OK) + if ((err = hal_ks_index_delete(ks, &slot->name, &b, &slot->hint)) != HAL_OK || + (err = key_visible(ks, slot->client_handle, slot->session_handle, b)) != HAL_OK) goto done; cache_release(ks, cache_find_block(ks, b)); @@ -871,7 +921,7 @@ static hal_error_t ks_delete(hal_ks_t *ks, return err; } -static inline hal_error_t locate_attributes(ks_block_t *block, +static inline hal_error_t locate_attributes(hal_ks_block_t *block, uint8_t **bytes, size_t *bytes_len, unsigned **attrs_len) { @@ -888,26 +938,26 @@ static inline hal_error_t locate_attributes(ks_block_t *block, return HAL_OK; } -static hal_error_t ks_match(hal_ks_t *ks, - const hal_client_handle_t client, - const hal_session_handle_t session, - const hal_key_type_t type, - const hal_curve_name_t curve, - const hal_key_flags_t mask, - const hal_key_flags_t flags, - const hal_pkey_attribute_t *attributes, - const unsigned attributes_len, - hal_uuid_t *result, - unsigned *result_len, - const unsigned result_max, - const hal_uuid_t * const previous_uuid) +hal_error_t hal_ks_match(hal_ks_t *ks, + const hal_client_handle_t client, + const hal_session_handle_t session, + const hal_key_type_t type, + const hal_curve_name_t curve, + const hal_key_flags_t mask, + const hal_key_flags_t flags, + const hal_pkey_attribute_t *attributes, + const unsigned attributes_len, + hal_uuid_t *result, + unsigned *result_len, + const unsigned result_max, + const hal_uuid_t * const previous_uuid) { if (ks == NULL || (attributes == NULL && attributes_len > 0) || result == NULL || result_len == NULL || previous_uuid == NULL) return HAL_ERROR_BAD_ARGUMENTS; hal_error_t err = HAL_OK; - ks_block_t *block; + hal_ks_block_t *block; int i = -1; hal_ks_lock(); @@ -928,6 +978,11 @@ static hal_error_t ks_match(hal_ks_t *ks, if ((err = block_read_cached(ks, b, &block)) != HAL_OK) goto done; + if ((err = key_visible(ks, client, session, b)) == HAL_ERROR_KEY_NOT_FOUND) + continue; + else if (err != HAL_OK) + goto done; + if ((type != HAL_KEY_TYPE_NONE && type != block->key.type) || (curve != HAL_CURVE_NONE && curve != block->key.curve) || ((flags ^ block->key.flags) & mask) != 0) @@ -982,23 +1037,24 @@ static hal_error_t ks_match(hal_ks_t *ks, return err; } -static hal_error_t ks_set_attributes(hal_ks_t *ks, - hal_pkey_slot_t *slot, - const hal_pkey_attribute_t *attributes, - const unsigned attributes_len) +hal_error_t hal_ks_set_attributes(hal_ks_t *ks, + hal_pkey_slot_t *slot, + const hal_pkey_attribute_t *attributes, + const unsigned attributes_len) { if (ks == NULL || slot == NULL || attributes == NULL || attributes_len == 0) return HAL_ERROR_BAD_ARGUMENTS; hal_error_t err = HAL_OK; - ks_block_t *block; + hal_ks_block_t *block; unsigned b; hal_ks_lock(); { - if ((err = hal_ks_index_find(ks, &slot->name, &b, &slot->hint)) != HAL_OK || - (err = block_read_cached(ks, b, &block)) != HAL_OK) + if ((err = hal_ks_index_find(ks, &slot->name, &b, &slot->hint)) != HAL_OK || + (err = key_visibile(ks, slot->client_handle, slot->session_handle, b)) != HAL_OK || + (err = block_read_cached(ks, b, &block)) != HAL_OK) goto done; cache_mark_used(ks, block, b); @@ -1037,12 +1093,12 @@ static hal_error_t ks_set_attributes(hal_ks_t *ks, return err; } -static hal_error_t ks_get_attributes(hal_ks_t *ks, - hal_pkey_slot_t *slot, - hal_pkey_attribute_t *attributes, - const unsigned attributes_len, - uint8_t *attributes_buffer, - const size_t attributes_buffer_len) +hal_error_t hal_ks_get_attributes(hal_ks_t *ks, + hal_pkey_slot_t *slot, + hal_pkey_attribute_t *attributes, + const unsigned attributes_len, + uint8_t *attributes_buffer, + const size_t attributes_buffer_len) { if (ks == NULL || slot == NULL || attributes == NULL || attributes_len == 0 || attributes_buffer == NULL) @@ -1054,7 +1110,7 @@ static hal_error_t ks_get_attributes(hal_ks_t *ks, } uint8_t *abuf = attributes_buffer; - ks_block_t *block = NULL; + hal_ks_block_t *block = NULL; hal_error_t err = HAL_OK; unsigned found = 0; unsigned b; @@ -1062,8 +1118,9 @@ static hal_error_t ks_get_attributes(hal_ks_t *ks, hal_ks_lock(); { - if ((err = hal_ks_index_find(ks, &slot->name, &b, &slot->hint)) != HAL_OK || - (err = block_read_cached(ks, b, &block)) != HAL_OK) + if ((err = hal_ks_index_find(ks, &slot->name, &b, &slot->hint)) != HAL_OK || + (err = key_visibile(ks, slot->client_handle, slot->session_handle, b)) != HAL_OK || + (err = block_read_cached(ks, b, &block)) != HAL_OK) goto done; cache_mark_used(ks, block, b); -- cgit v1.2.3 From b9565626187cca926c21120786ec575c59f06a05 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Thu, 25 May 2017 01:05:10 -0400 Subject: Fix up ks driver calls and inline wrappers. --- ks.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'ks.c') diff --git a/ks.c b/ks.c index 89babc2..a93cbe1 100644 --- a/ks.c +++ b/ks.c @@ -422,7 +422,7 @@ static hal_error_t block_read_cached(hal_ks_t *ks, const unsigned blockno, hal_k if ((*block = cache_pick_lru(ks)) == NULL) return HAL_ERROR_IMPOSSIBLE; - return block_read(ks, blockno, *block); + return hal_ks_block_read(ks, blockno, *block); } /* @@ -446,10 +446,10 @@ static hal_error_t block_update(hal_ks_t *ks, hal_error_t err; unsigned b2; - if ((err = block_deprecate(ks, b1)) != HAL_OK || + if ((err = hal_ks_block_deprecate(ks, b1)) != HAL_OK || (err = hal_ks_index_replace(ks, uuid, &b2, hint)) != HAL_OK || - (err = block_write(ks, b2, block)) != HAL_OK || - (err = block_zero(ks, b1)) != HAL_OK) + (err = hal_ks_block_write(ks, b2, block)) != HAL_OK || + (err = hal_ks_block_zero(ks, b1)) != HAL_OK) return err; cache_mark_used(ks, block, b2); @@ -459,7 +459,7 @@ static hal_error_t block_update(hal_ks_t *ks, * puts the block back at the head of the free list. */ - return block_erase_maybe(ks, ks->index[ks->used]); + return hal_ks_block_erase_maybe(ks, ks->index[ks->used]); } /* @@ -546,7 +546,7 @@ hal_error_t hal_ks_init_common(hal_ks_t *ks, const hal_ks_driver_t * const drive * we want the block to end up near the end of the free list. */ - err = block_read(ks, i, block); + err = hal_ks_block_read(ks, i, block); if (err == HAL_ERROR_KEYSTORE_BAD_CRC || err == HAL_ERROR_KEYSTORE_BAD_BLOCK_TYPE) block_types[i] = BLOCK_TYPE_UNKNOWN; @@ -679,16 +679,16 @@ hal_error_t hal_ks_init_common(hal_ks_t *ks, const hal_ks_driver_t * const drive else { unsigned b_live; - if ((err = block_read(ks, b_tomb, block)) != HAL_OK) + if ((err = hal_ks_block_read(ks, b_tomb, block)) != HAL_OK) return err; block->header.block_status = BLOCK_STATUS_LIVE; if ((err = hal_ks_index_replace(ks, &name, &b_live, &where)) != HAL_OK || - (err = block_write(ks, b_live, block)) != HAL_OK) + (err = hal_ks_block_write(ks, b_live, block)) != HAL_OK) return err; block_status[b_live] = BLOCK_STATUS_LIVE; } - if ((err = block_zero(ks, b_tomb)) != HAL_OK) + if ((err = hal_ks_block_zero(ks, b_tomb)) != HAL_OK) return err; block_types[ b_tomb] = BLOCK_TYPE_ZEROED; block_status[b_tomb] = BLOCK_STATUS_UNKNOWN; @@ -699,7 +699,7 @@ hal_error_t hal_ks_init_common(hal_ks_t *ks, const hal_ks_driver_t * const drive */ if (ks->used < ks->size && - (err = block_erase_maybe(ks, ks->index[ks->used])) != HAL_OK) + (err = hal_ks_block_erase_maybe(ks, ks->index[ks->used])) != HAL_OK) return err; /* @@ -758,7 +758,7 @@ static inline hal_error_t key_visible(const hal_ks_t * const ks, hal_error_t err; - if ((err = hal_ks_test_owner(ks, client, session)) != HAL_OK) + if ((err = hal_ks_block_test_owner(ks, client, session)) != HAL_OK) return err; err = hal_rpc_is_logged_in(client, HAL_USER_WHEEL); @@ -810,7 +810,7 @@ hal_error_t hal_ks_store(hal_ks_t *ks, k->attributes_len = 0; if (ks->used < ks->size) - err = block_erase_maybe(ks, ks->index[ks->used]); + 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)); @@ -821,10 +821,10 @@ hal_error_t hal_ks_store(hal_ks_t *ks, memset(kek, 0, sizeof(kek)); if (err == HAL_OK) - err = block_write(ks, b, block); + err = hal_ks_block_write(ks, b, block); if (err == HAL_OK) - err = hal_ks_set_owner(ks, b, slot->client_handle, slot->session_handle); + err = hal_ks_block_set_owner(ks, b, slot->client_handle, slot->session_handle); if (err == HAL_OK) goto done; @@ -853,7 +853,7 @@ 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 = key_visible(ks, slot->client_handle, slot->session_handle, b)) != HAL_OK || - (err = block_read_cached(ks, b, &block)) != HAL_OK) + (err = hal_ks_block_read_cached(ks, b, &block)) != HAL_OK) goto done; if (block_get_type(block) != BLOCK_TYPE_KEY) { @@ -911,10 +911,10 @@ hal_error_t hal_ks_delete(hal_ks_t *ks, cache_release(ks, cache_find_block(ks, b)); - if ((err = block_zero(ks, b)) != HAL_OK) + if ((err = hal_ks_block_zero(ks, b)) != HAL_OK) goto done; - err = block_erase_maybe(ks, ks->index[ks->used]); + err = hal_ks_block_erase_maybe(ks, ks->index[ks->used]); done: hal_ks_unlock(); @@ -975,7 +975,7 @@ hal_error_t hal_ks_match(hal_ks_t *ks, unsigned b = ks->index[i]; - if ((err = block_read_cached(ks, b, &block)) != HAL_OK) + if ((err = hal_ks_block_read_cached(ks, b, &block)) != HAL_OK) goto done; if ((err = key_visible(ks, client, session, b)) == HAL_ERROR_KEY_NOT_FOUND) @@ -1054,7 +1054,7 @@ hal_error_t hal_ks_set_attributes(hal_ks_t *ks, { if ((err = hal_ks_index_find(ks, &slot->name, &b, &slot->hint)) != HAL_OK || (err = key_visibile(ks, slot->client_handle, slot->session_handle, b)) != HAL_OK || - (err = block_read_cached(ks, b, &block)) != HAL_OK) + (err = hal_ks_block_read_cached(ks, b, &block)) != HAL_OK) goto done; cache_mark_used(ks, block, b); @@ -1120,7 +1120,7 @@ hal_error_t hal_ks_get_attributes(hal_ks_t *ks, { if ((err = hal_ks_index_find(ks, &slot->name, &b, &slot->hint)) != HAL_OK || (err = key_visibile(ks, slot->client_handle, slot->session_handle, b)) != HAL_OK || - (err = block_read_cached(ks, b, &block)) != HAL_OK) + (err = hal_ks_block_read_cached(ks, b, &block)) != HAL_OK) goto done; cache_mark_used(ks, block, b); -- cgit v1.2.3 From 5eccb3e6d7c27149a0092de48eb21baa495879cb Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Thu, 25 May 2017 11:18:39 -0400 Subject: Checkpoint while refactoring. Almost certainly will not compile. --- ks.c | 275 ++----------------------------------------------------------------- 1 file changed, 8 insertions(+), 267 deletions(-) (limited to 'ks.c') diff --git a/ks.c b/ks.c index a93cbe1..f0c71cc 100644 --- a/ks.c +++ b/ks.c @@ -40,277 +40,17 @@ #include "ks.h" /* - * Find a block in the index, return true (found) or false (not found). - * "where" indicates the name's position, or the position of the first free block. - * - * NB: This does NOT return a block number, it returns an index into - * ks->index[]. - */ - -static int ks_find(const hal_ks_t * const ks, - const hal_uuid_t * const uuid, - const int * const hint, - int *where) -{ - if (ks == NULL || ks->index == NULL || ks->names == NULL || uuid == NULL || where == NULL) - return 0; - - if (hint != NULL && *hint >= 0 && *hint < ks->used && - hal_uuid_cmp(uuid, &ks->names[ks->index[*hint]]) == 0) { - *where = *hint; - return 1; - } - - int lo = -1; - int hi = ks->used; - - for (;;) { - int m = (lo + hi) / 2; - if (hi == 0 || m == lo) { - *where = hi; - return 0; - } - const int cmp = hal_uuid_cmp(uuid, &ks->names[ks->index[m]]); - if (cmp < 0) - hi = m; - else if (cmp > 0) - lo = m; - else { - *where = m; - return 1; - } - } -} - -/* - * Heapsort the index. We only need to do this on setup, for other - * operations we're just inserting or deleting a single entry in an - * already-ordered array, which is just a search problem. If we were - * really crunched for space, we could use an insertion sort here, but - * heapsort is easy and works well with data already in place. - */ - -static inline void ks_heapsift(hal_ks_t *ks, int parent, const int end) -{ - if (ks == NULL || ks->index == NULL || ks->names == NULL || parent < 0 || end < parent) - return; - for (;;) { - const int left_child = parent * 2 + 1; - const int right_child = parent * 2 + 2; - int biggest = parent; - if (left_child <= end && hal_uuid_cmp(&ks->names[ks->index[biggest]], - &ks->names[ks->index[left_child]]) < 0) - biggest = left_child; - if (right_child <= end && hal_uuid_cmp(&ks->names[ks->index[biggest]], - &ks->names[ks->index[right_child]]) < 0) - biggest = right_child; - if (biggest == parent) - return; - const uint16_t tmp = ks->index[biggest]; - ks->index[biggest] = ks->index[parent]; - ks->index[parent] = tmp; - parent = biggest; - } -} - -static inline void ks_heapsort(hal_ks_t *ks) -{ - if (ks == NULL || ks->index == NULL || ks->names == NULL) - return; - if (ks->used < 2) - return; - for (int i = (ks->used - 2) / 2; i >= 0; i--) - ks_heapsift(ks, i, ks->used - 1); - for (int i = ks->used - 1; i > 0; i--) { - const uint16_t tmp = ks->index[i]; - ks->index[i] = ks->index[0]; - ks->index[0] = tmp; - ks_heapsift(ks, 0, i - 1); - } -} - -/* - * Perform a consistency check on the index. + * Type safe casts. */ -#define fsck(_ks) \ - do { hal_error_t _err = hal_ks_index_fsck(_ks); if (_err != HAL_OK) return _err; } while (0) - - -hal_error_t hal_ks_index_fsck(hal_ks_t *ks) +static inline ks_block_type_t block_get_type(const ks_block_t * const block) { - if (ks == NULL || ks->index == NULL || ks->names == NULL || - ks->size == 0 || ks->used > ks->size) - return HAL_ERROR_BAD_ARGUMENTS; - - for (int i = 1; i < ks->used; i++) - if (hal_uuid_cmp(&ks->names[ks->index[i - 1]], &ks->names[ks->index[i]]) >= 0) - return HAL_ERROR_KS_INDEX_UUID_MISORDERED; - - return HAL_OK; + return block == NULL ? HAL_KS_BLOCK_TYPE_UNKNOWN : (ks_block_type_t) block->header.block_type; } -/* - * Find a single block by name. - */ - -hal_error_t hal_ks_index_find(hal_ks_t *ks, - const hal_uuid_t * const name, - unsigned *blockno, - int *hint) +static inline ks_block_status_t block_get_status(const ks_block_t * const block) { - if (ks == NULL || ks->index == NULL || ks->names == NULL || - ks->size == 0 || ks->used > ks->size || name == NULL) - return HAL_ERROR_BAD_ARGUMENTS; - - int where; - - fsck(ks); - - int ok = ks_find(ks, name, hint, &where); - - if (blockno != NULL) - *blockno = ks->index[where]; - - if (hint != NULL) - *hint = where; - - return ok ? HAL_OK : HAL_ERROR_KEY_NOT_FOUND; -} - -/* - * Add a single block to the index. - */ - -hal_error_t hal_ks_index_add(hal_ks_t *ks, - const hal_uuid_t * const name, - unsigned *blockno, - int *hint) -{ - if (ks == NULL || ks->index == NULL || ks->names == NULL || - ks->size == 0 || ks->used > ks->size || name == NULL) - return HAL_ERROR_BAD_ARGUMENTS; - - if (ks->used == ks->size) - return HAL_ERROR_NO_KEY_INDEX_SLOTS; - - int where; - - fsck(ks); - - if (ks_find(ks, name, hint, &where)) - return HAL_ERROR_KEY_NAME_IN_USE; - - /* - * Grab first block on free list, which makes room to slide the - * index up by one slot so we can insert the new block number. - */ - - const size_t len = (ks->used - where) * sizeof(*ks->index); - const uint16_t b = ks->index[ks->used++]; - memmove(&ks->index[where + 1], &ks->index[where], len); - ks->index[where] = b; - ks->names[b] = *name; - - if (blockno != NULL) - *blockno = b; - - if (hint != NULL) - *hint = where; - - fsck(ks); - - return HAL_OK; -} - -/* - * Delete a single block from the index. - */ - -hal_error_t hal_ks_index_delete(hal_ks_t *ks, - const hal_uuid_t * const name, - unsigned *blockno, - int *hint) -{ - if (ks == NULL || ks->index == NULL || ks->names == NULL || - ks->size == 0 || ks->used > ks->size || name == NULL) - return HAL_ERROR_BAD_ARGUMENTS; - - int where; - - fsck(ks); - - if (ks->used == 0 || !ks_find(ks, name, hint, &where)) - return HAL_ERROR_KEY_NOT_FOUND; - - /* - * Free the block and stuff it at the end of the free list. - */ - - const size_t len = (ks->size - where - 1) * sizeof(*ks->index); - const uint16_t b = ks->index[where]; - memmove(&ks->index[where], &ks->index[where + 1], len); - ks->index[ks->size - 1] = b; - ks->used--; - memset(&ks->names[b], 0, sizeof(ks->names[b])); - - if (blockno != NULL) - *blockno = b; - - if (hint != NULL) - *hint = where; - - fsck(ks); - - return HAL_OK; -} - -/* - * Replace a single block in the index. - */ - -hal_error_t hal_ks_index_replace(hal_ks_t *ks, - const hal_uuid_t * const name, - unsigned *blockno, - int *hint) -{ - if (ks == NULL || ks->index == NULL || ks->names == NULL || - ks->size == 0 || ks->used > ks->size || name == NULL) - return HAL_ERROR_BAD_ARGUMENTS; - - if (ks->used == ks->size) - return HAL_ERROR_NO_KEY_INDEX_SLOTS; - - int where; - - fsck(ks); - - if (ks->used == 0 || !ks_find(ks, name, hint, &where)) - return HAL_ERROR_KEY_NOT_FOUND; - - /* - * Grab first block from free list, slide free list down, put old - * block at end of free list and replace old block with new block. - */ - - const size_t len = (ks->size - ks->used - 1) * sizeof(*ks->index); - const uint16_t b1 = ks->index[where]; - const uint16_t b2 = ks->index[ks->used]; - memmove(&ks->index[ks->used], &ks->index[ks->used + 1], len); - ks->index[ks->size - 1] = b1; - ks->index[where] = b2; - ks->names[b2] = *name; - memset(&ks->names[b1], 0, sizeof(ks->names[b1])); - - if (blockno != NULL) - *blockno = b2; - - if (hint != NULL) - *hint = where; - - fsck(ks); - - return HAL_OK; + return block == NULL ? HAL_KS_BLOCK_STATUS_UNKNOWN : (ks_block_status_t) block->header.block_status; } /* @@ -641,7 +381,8 @@ hal_error_t hal_ks_init_common(hal_ks_t *ks, const hal_ks_driver_t * const drive * failure, we should never lose data. */ - ks_heapsort(ks); + if ((err = hal_ks_index_heapsort(ks)) != HAL_OK) + return err; for (unsigned b_tomb = 0; b_tomb < ks->size; b_tomb++) { @@ -666,7 +407,7 @@ hal_error_t hal_ks_init_common(hal_ks_t *ks, const hal_ks_driver_t * const drive const int matches_next = where + 1 < ks->used && !hal_uuid_cmp(&name, &ks->names[ks->index[where + 1]]); const int matches_prev = where - 1 >= 0 && !hal_uuid_cmp(&name, &ks->names[ks->index[where - 1]]); - + if ((matches_prev && matches_next) || (matches_prev && block_status[ks->index[b_tomb - 1]] != BLOCK_STATUS_LIVE) || (matches_next && block_status[ks->index[b_tomb + 1]] != BLOCK_STATUS_LIVE)) -- cgit v1.2.3 From f59533ee9807832ea5ca7dd5492592c8991a9f34 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Sun, 28 May 2017 12:11:31 -0400 Subject: Further keystore cleanup and consolidation. Still not yet expected to compile, much less run, but getting closer. --- ks.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'ks.c') diff --git a/ks.c b/ks.c index f0c71cc..3d1ae61 100644 --- a/ks.c +++ b/ks.c @@ -221,24 +221,31 @@ static inline void *gnaw(uint8_t **mem, size_t *len, const size_t size) #warning Call hal_ks_alloc_common() and hal_ks_init_common() while holding hal_ks_lock(); ! -hal_error_t hal_ks_alloc_common(hal_ks_t *ks, const unsigned ks_blocks, const unsigned cache_blocks) +hal_error_t hal_ks_alloc_common(hal_ks_t *ks, + const unsigned ks_blocks, + const unsigned cache_blocks, + void **extra, + const size_t extra_len) { /* - * We allocate a single big chunk of memory rather than three - * smaller chunks to make it atomic. We need all three, so this way - * either all succeed or all fail. + * We allocate a single big chunk of memory to make it atomic. We + * need all three of our blocks, so this way either all succeed or + * all fail; we allow our caller to piggyback its own memory needs + * (if any) on ours for the same reason. */ size_t len = (sizeof(*ks->index) * ks_blocks + sizeof(*ks->names) * ks_blocks + - sizeof(*ks->cache) * cache_blocks); + sizeof(*ks->cache) * cache_blocks + + extra_len); uint8_t *mem = hal_allocate_static_memory(len); if (mem == NULL) return HAL_ERROR_ALLOCATION_FAILURE; - memset(ks, 0, sizeof(*ks)); + memset(((uint8_t *) ks) + sizeof(hal_ks_driver_t), 0, + sizeof(hal_ks_t) - sizeof(hal_ks_driver_t)); memset(mem, 0, len); ks->index = gnaw(&mem, &len, sizeof(*ks->index) * ks_blocks); @@ -248,10 +255,13 @@ hal_error_t hal_ks_alloc_common(hal_ks_t *ks, const unsigned ks_blocks, const un ks->size = ks_blocks; ks->cache_size = cache_blocks; + if (extra != NULL) + *extra = mem; + return HAL_OK; } -hal_error_t hal_ks_init_common(hal_ks_t *ks, const hal_ks_driver_t * const driver) +hal_error_t hal_ks_init_common(hal_ks_t *ks) { if (ks->index == NULL || ks->names == NULL || ks->cache == NULL) return HAL_ERROR_IMPOSSIBLE; @@ -447,8 +457,6 @@ hal_error_t hal_ks_init_common(hal_ks_t *ks, const hal_ks_driver_t * const drive * And we're finally done. */ - ks->driver = driver; - return HAL_OK; } -- cgit v1.2.3 From 2caa6c72640877abc5f3572c4d926a23ff672ab1 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Sun, 28 May 2017 16:11:25 -0400 Subject: Almost compiles. Need to refactor init sequence slightly (again), this time to humor the bootloader, which has its own special read-only view of the PIN block in the token keystore. --- ks.c | 141 +++++++++++++++++++++++++++++++++---------------------------------- 1 file changed, 70 insertions(+), 71 deletions(-) (limited to 'ks.c') diff --git a/ks.c b/ks.c index 3d1ae61..a0a4de7 100644 --- a/ks.c +++ b/ks.c @@ -40,18 +40,11 @@ #include "ks.h" /* - * Type safe casts. + * PIN block gets the all-zeros UUID, which will never be returned by + * the UUID generation code (by definition -- it's not a version 4 UUID). */ -static inline ks_block_type_t block_get_type(const ks_block_t * const block) -{ - return block == NULL ? HAL_KS_BLOCK_TYPE_UNKNOWN : (ks_block_type_t) block->header.block_type; -} - -static inline ks_block_status_t block_get_status(const ks_block_t * const block) -{ - return block == NULL ? HAL_KS_BLOCK_STATUS_UNKNOWN : (ks_block_status_t) block->header.block_status; -} +const hal_uuid_t hal_ks_pin_uuid = {{0}}; /* * Pick unused or least-recently-used slot in our in-memory cache. @@ -61,7 +54,7 @@ static inline ks_block_status_t block_get_status(const ks_block_t * const block) * result, leave the lru values alone and the right thing will happen. */ -static inline hal_ks_block_t *cache_pick_lru(hal_ks_t *ks) +hal_ks_block_t *hal_ks_cache_pick_lru(hal_ks_t *ks) { uint32_t best_delta = 0; int best_index = 0; @@ -87,7 +80,7 @@ static inline hal_ks_block_t *cache_pick_lru(hal_ks_t *ks) * Find a block in our in-memory cache; return block or NULL if not present. */ -static inline hal_ks_block_t *cache_find_block(const hal_ks_t * const ks, const unsigned blockno) +hal_ks_block_t *hal_ks_cache_find_block(const hal_ks_t * const ks, const unsigned blockno) { for (int i = 0; i < ks->cache_size; i++) if (ks->cache[i].blockno == blockno) @@ -99,7 +92,7 @@ static inline hal_ks_block_t *cache_find_block(const hal_ks_t * const ks, const * Mark a block in our in-memory cache as being in current use. */ -static inline void cache_mark_used(hal_ks_t *ks, const hal_ks_block_t * const block, const unsigned blockno) +void hal_ks_cache_mark_used(hal_ks_t *ks, const hal_ks_block_t * const block, const unsigned blockno) { for (int i = 0; i < ks->cache_size; i++) { if (&ks->cache[i].block == block) { @@ -114,10 +107,10 @@ static inline void cache_mark_used(hal_ks_t *ks, const hal_ks_block_t * const bl * Release a block from the in-memory cache. */ -static inline void cache_release(hal_ks_t *ks, const hal_ks_block_t * const block) +void hal_ks_cache_release(hal_ks_t *ks, const hal_ks_block_t * const block) { if (block != NULL) - cache_mark_used(block, ~0); + hal_ks_cache_mark_used(ks, block, ~0); } /* @@ -128,7 +121,7 @@ static inline void cache_release(hal_ks_t *ks, const hal_ks_block_t * const bloc * shouldn't be included in the CRC. */ -static hal_crc32_t calculate_block_crc(const hal_ks_block_t * const block) +hal_crc32_t hal_ks_block_calculate_crc(const hal_ks_block_t * const block) { hal_crc32_t crc = hal_crc32_init(); @@ -151,15 +144,15 @@ static hal_crc32_t calculate_block_crc(const hal_ks_block_t * const block) * perform a hal_ks_match() operation. */ -static hal_error_t block_read_cached(hal_ks_t *ks, const unsigned blockno, hal_ks_block_t **block) +hal_error_t hal_ks_block_read_cached(hal_ks_t *ks, const unsigned blockno, hal_ks_block_t **block) { if (block == NULL) return HAL_ERROR_IMPOSSIBLE; - if ((*block = cache_find_block(ks, blockno)) != NULL) + if ((*block = hal_ks_cache_find_block(ks, blockno)) != NULL) return HAL_OK; - if ((*block = cache_pick_lru(ks)) == NULL) + if ((*block = hal_ks_cache_pick_lru(ks)) == NULL) return HAL_ERROR_IMPOSSIBLE; return hal_ks_block_read(ks, blockno, *block); @@ -169,11 +162,11 @@ static hal_error_t block_read_cached(hal_ks_t *ks, const unsigned blockno, hal_k * Update one block, including zombie jamboree. */ -static hal_error_t block_update(hal_ks_t *ks, - const unsigned b1, - hal_ks_block_t *block, - const hal_uuid_t * const uuid, - int *hint) +hal_error_t hal_ks_block_update(hal_ks_t *ks, + const unsigned b1, + hal_ks_block_t *block, + const hal_uuid_t * const uuid, + int *hint) { if (block == NULL) return HAL_ERROR_IMPOSSIBLE; @@ -181,7 +174,7 @@ static hal_error_t block_update(hal_ks_t *ks, if (ks->used == ks->size) return HAL_ERROR_NO_KEY_INDEX_SLOTS; - cache_release(block); + hal_ks_cache_release(ks, block); hal_error_t err; unsigned b2; @@ -192,7 +185,7 @@ static hal_error_t block_update(hal_ks_t *ks, (err = hal_ks_block_zero(ks, b1)) != HAL_OK) return err; - cache_mark_used(ks, block, b2); + hal_ks_cache_mark_used(ks, block, b2); /* * Erase the first block in the free list. In case of restart, this @@ -209,6 +202,14 @@ static hal_error_t block_update(hal_ks_t *ks, * recover from unclean shutdown. */ +hal_error_t hal_ks_init(hal_ks_t *ks, const int alloc) +{ + return + ks == NULL || ks->driver == NULL ? HAL_ERROR_BAD_ARGUMENTS : + ks->driver->init == NULL ? HAL_ERROR_NOT_IMPLEMENTED : + ks->driver->init(ks, alloc); +} + static inline void *gnaw(uint8_t **mem, size_t *len, const size_t size) { if (mem == NULL || *mem == NULL || len == NULL || size > *len) @@ -219,8 +220,6 @@ static inline void *gnaw(uint8_t **mem, size_t *len, const size_t size) return ret; } -#warning Call hal_ks_alloc_common() and hal_ks_init_common() while holding hal_ks_lock(); ! - hal_error_t hal_ks_alloc_common(hal_ks_t *ks, const unsigned ks_blocks, const unsigned cache_blocks, @@ -279,7 +278,7 @@ hal_error_t hal_ks_init_common(hal_ks_t *ks) hal_ks_block_type_t block_types[ks->size]; hal_ks_block_status_t block_status[ks->size]; - hal_ks_block_t *block = cache_pick_lru(ks); + hal_ks_block_t *block = hal_ks_cache_pick_lru(ks); int first_erased = -1; hal_error_t err; uint16_t n = 0; @@ -299,28 +298,28 @@ hal_error_t hal_ks_init_common(hal_ks_t *ks) err = hal_ks_block_read(ks, i, block); if (err == HAL_ERROR_KEYSTORE_BAD_CRC || err == HAL_ERROR_KEYSTORE_BAD_BLOCK_TYPE) - block_types[i] = BLOCK_TYPE_UNKNOWN; + block_types[i] = HAL_KS_BLOCK_TYPE_UNKNOWN; else if (err == HAL_OK) - block_types[i] = block_get_type(block); + block_types[i] = hal_ks_block_get_type(block); else return err; switch (block_types[i]) { - case BLOCK_TYPE_KEY: - case BLOCK_TYPE_PIN: - block_status[i] = block_get_status(block); + case HAL_KS_BLOCK_TYPE_KEY: + case HAL_KS_BLOCK_TYPE_PIN: + block_status[i] = hal_ks_block_get_status(block); break; default: - block_status[i] = BLOCK_STATUS_UNKNOWN; + block_status[i] = HAL_KS_BLOCK_STATUS_UNKNOWN; } /* * First erased block we see is head of the free list. */ - if (block_types[i] == BLOCK_TYPE_ERASED && first_erased < 0) + if (block_types[i] == HAL_KS_BLOCK_TYPE_ERASED && first_erased < 0) first_erased = i; /* @@ -332,8 +331,8 @@ hal_error_t hal_ks_init_common(hal_ks_t *ks) const hal_uuid_t *uuid = NULL; switch (block_types[i]) { - case BLOCK_TYPE_KEY: uuid = &block->key.name; break; - case BLOCK_TYPE_PIN: uuid = &pin_uuid; break; + case HAL_KS_BLOCK_TYPE_KEY: uuid = &block->key.name; break; + case HAL_KS_BLOCK_TYPE_PIN: uuid = &hal_ks_pin_uuid; break; default: /* Keep GCC happy */ break; } @@ -359,22 +358,22 @@ hal_error_t hal_ks_init_common(hal_ks_t *ks) if (n < ks->size) for (int i = 0; i < ks->size; i++) - if (block_types[i] == BLOCK_TYPE_ERASED) + if (block_types[i] == HAL_KS_BLOCK_TYPE_ERASED) ks->index[n++] = i; if (n < ks->size) for (int i = first_erased; i < ks->size; i++) - if (block_types[i] == BLOCK_TYPE_ZEROED) + if (block_types[i] == HAL_KS_BLOCK_TYPE_ZEROED) ks->index[n++] = i; if (n < ks->size) for (int i = 0; i < first_erased; i++) - if (block_types[i] == BLOCK_TYPE_ZEROED) + if (block_types[i] == HAL_KS_BLOCK_TYPE_ZEROED) ks->index[n++] = i; if (n < ks->size) for (int i = 0; i < ks->size; i++) - if (block_types[i] == BLOCK_TYPE_UNKNOWN) + if (block_types[i] == HAL_KS_BLOCK_TYPE_UNKNOWN) ks->index[n++] = i; if (ks->used > ks->size) @@ -396,7 +395,7 @@ hal_error_t hal_ks_init_common(hal_ks_t *ks) for (unsigned b_tomb = 0; b_tomb < ks->size; b_tomb++) { - if (block_status[b_tomb] != BLOCK_STATUS_TOMBSTONE) + if (block_status[b_tomb] != HAL_KS_BLOCK_STATUS_TOMBSTONE) continue; hal_uuid_t name = ks->names[b_tomb]; @@ -419,8 +418,8 @@ hal_error_t hal_ks_init_common(hal_ks_t *ks) const int matches_prev = where - 1 >= 0 && !hal_uuid_cmp(&name, &ks->names[ks->index[where - 1]]); if ((matches_prev && matches_next) || - (matches_prev && block_status[ks->index[b_tomb - 1]] != BLOCK_STATUS_LIVE) || - (matches_next && block_status[ks->index[b_tomb + 1]] != BLOCK_STATUS_LIVE)) + (matches_prev && block_status[ks->index[b_tomb - 1]] != HAL_KS_BLOCK_STATUS_LIVE) || + (matches_next && block_status[ks->index[b_tomb + 1]] != HAL_KS_BLOCK_STATUS_LIVE)) return HAL_ERROR_IMPOSSIBLE; if (matches_prev || matches_next) { @@ -432,17 +431,17 @@ hal_error_t hal_ks_init_common(hal_ks_t *ks) unsigned b_live; if ((err = hal_ks_block_read(ks, b_tomb, block)) != HAL_OK) return err; - block->header.block_status = BLOCK_STATUS_LIVE; + block->header.block_status = HAL_KS_BLOCK_STATUS_LIVE; if ((err = hal_ks_index_replace(ks, &name, &b_live, &where)) != HAL_OK || (err = hal_ks_block_write(ks, b_live, block)) != HAL_OK) return err; - block_status[b_live] = BLOCK_STATUS_LIVE; + block_status[b_live] = HAL_KS_BLOCK_STATUS_LIVE; } if ((err = hal_ks_block_zero(ks, b_tomb)) != HAL_OK) return err; - block_types[ b_tomb] = BLOCK_TYPE_ZEROED; - block_status[b_tomb] = BLOCK_STATUS_UNKNOWN; + block_types[ b_tomb] = HAL_KS_BLOCK_TYPE_ZEROED; + block_status[b_tomb] = HAL_KS_BLOCK_STATUS_UNKNOWN; } /* @@ -494,7 +493,7 @@ static inline int acceptable_key_type(const hal_key_type_t type) * avoid revising this yet again. */ -static inline hal_error_t key_visible(const hal_ks_t * const ks, +static inline hal_error_t key_visible(hal_ks_t * const ks, const hal_client_handle_t client, const hal_session_handle_t session, const unsigned blockno) @@ -507,7 +506,7 @@ static inline hal_error_t key_visible(const hal_ks_t * const ks, hal_error_t err; - if ((err = hal_ks_block_test_owner(ks, client, session)) != HAL_OK) + if ((err = hal_ks_block_test_owner(ks, blockno, client, session)) != HAL_OK) return err; err = hal_rpc_is_logged_in(client, HAL_USER_WHEEL); @@ -527,14 +526,14 @@ hal_error_t hal_ks_store(hal_ks_t *ks, hal_error_t err = HAL_OK; hal_ks_block_t *block; - flash_key_block_t *k; + hal_ks_key_block_t *k; uint8_t kek[KEK_LENGTH]; size_t kek_len; unsigned b; hal_ks_lock(); - if ((block = cache_pick_lru(ks)) == NULL) { + if ((block = hal_ks_cache_pick_lru(ks)) == NULL) { err = HAL_ERROR_IMPOSSIBLE; goto done; } @@ -544,18 +543,18 @@ hal_error_t hal_ks_store(hal_ks_t *ks, if ((err = hal_ks_index_add(ks, &slot->name, &b, &slot->hint)) != HAL_OK) goto done; - cache_mark_used(ks, block, b); + hal_ks_cache_mark_used(ks, block, b); memset(block, 0xFF, sizeof(*block)); - block->header.block_type = BLOCK_TYPE_KEY; - block->header.block_status = BLOCK_STATUS_LIVE; + 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_FLASH_KEY_BLOCK_DER; + k->der_len = SIZEOF_KS_KEY_BLOCK_DER; k->attributes_len = 0; if (ks->used < ks->size) @@ -579,7 +578,7 @@ hal_error_t hal_ks_store(hal_ks_t *ks, goto done; memset(block, 0, sizeof(*block)); - cache_release(ks, block); + hal_ks_cache_release(ks, block); (void) hal_ks_index_delete(ks, &slot->name, NULL, &slot->hint); done: @@ -605,14 +604,14 @@ hal_error_t hal_ks_fetch(hal_ks_t *ks, (err = hal_ks_block_read_cached(ks, b, &block)) != HAL_OK) goto done; - if (block_get_type(block) != BLOCK_TYPE_KEY) { + 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; } - cache_mark_used(ks, block, b); + hal_ks_cache_mark_used(ks, block, b); - flash_key_block_t *k = &block->key; + hal_ks_key_block_t *k = &block->key; slot->type = k->type; slot->curve = k->curve; @@ -658,7 +657,7 @@ hal_error_t hal_ks_delete(hal_ks_t *ks, (err = key_visible(ks, slot->client_handle, slot->session_handle, b)) != HAL_OK) goto done; - cache_release(ks, cache_find_block(ks, b)); + hal_ks_cache_release(ks, hal_ks_cache_find_block(ks, b)); if ((err = hal_ks_block_zero(ks, b)) != HAL_OK) goto done; @@ -678,11 +677,11 @@ static inline hal_error_t locate_attributes(hal_ks_block_t *block, return HAL_ERROR_IMPOSSIBLE; - if (block_get_type(block) != BLOCK_TYPE_KEY) + if (hal_ks_block_get_type(block) != HAL_KS_BLOCK_TYPE_KEY) return HAL_ERROR_KEYSTORE_WRONG_BLOCK_TYPE; *attrs_len = &block->key.attributes_len; *bytes = block->key.der + block->key.der_len; - *bytes_len = SIZEOF_FLASH_KEY_BLOCK_DER - block->key.der_len; + *bytes_len = SIZEOF_KS_KEY_BLOCK_DER - block->key.der_len; return HAL_OK; } @@ -802,11 +801,11 @@ hal_error_t hal_ks_set_attributes(hal_ks_t *ks, { if ((err = hal_ks_index_find(ks, &slot->name, &b, &slot->hint)) != HAL_OK || - (err = key_visibile(ks, slot->client_handle, slot->session_handle, b)) != HAL_OK || + (err = key_visible(ks, slot->client_handle, slot->session_handle, b)) != HAL_OK || (err = hal_ks_block_read_cached(ks, b, &block)) != HAL_OK) goto done; - cache_mark_used(ks, block, b); + hal_ks_cache_mark_used(ks, block, b); uint8_t *bytes = NULL; size_t bytes_len = 0; @@ -832,9 +831,9 @@ hal_error_t hal_ks_set_attributes(hal_ks_t *ks, attributes[i].length); if (err == HAL_OK) - err = block_update(ks, b, block, &slot->name, &slot->hint); + err = hal_ks_block_update(ks, b, block, &slot->name, &slot->hint); else - cache_release(ks, block); + hal_ks_cache_release(ks, block); } done: @@ -868,11 +867,11 @@ hal_error_t hal_ks_get_attributes(hal_ks_t *ks, { if ((err = hal_ks_index_find(ks, &slot->name, &b, &slot->hint)) != HAL_OK || - (err = key_visibile(ks, slot->client_handle, slot->session_handle, b)) != HAL_OK || - (err = hal_ks_block_read_cached(ks, b, &block)) != HAL_OK) + (err = key_visible(ks, slot->client_handle, slot->session_handle, b)) != HAL_OK || + (err = hal_ks_block_read_cached(ks, b, &block)) != HAL_OK) goto done; - cache_mark_used(ks, block, b); + hal_ks_cache_mark_used(ks, block, b); uint8_t *bytes = NULL; size_t bytes_len = 0; -- cgit v1.2.3 From 5cee716555db92942c5b11c824839bb00aaf35b9 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Mon, 29 May 2017 00:44:18 -0400 Subject: Debug per-session keys. --- ks.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'ks.c') diff --git a/ks.c b/ks.c index a0a4de7..2d1d8c4 100644 --- a/ks.c +++ b/ks.c @@ -182,6 +182,7 @@ hal_error_t hal_ks_block_update(hal_ks_t *ks, if ((err = hal_ks_block_deprecate(ks, b1)) != HAL_OK || (err = hal_ks_index_replace(ks, uuid, &b2, hint)) != HAL_OK || (err = hal_ks_block_write(ks, b2, block)) != HAL_OK || + (err = hal_ks_block_copy_owner(ks, b1, b2)) != HAL_OK || (err = hal_ks_block_zero(ks, b1)) != HAL_OK) return err; @@ -243,8 +244,8 @@ hal_error_t hal_ks_alloc_common(hal_ks_t *ks, if (mem == NULL) return HAL_ERROR_ALLOCATION_FAILURE; - memset(((uint8_t *) ks) + sizeof(hal_ks_driver_t), 0, - sizeof(hal_ks_t) - sizeof(hal_ks_driver_t)); + memset(((uint8_t *) ks) + sizeof(ks->driver), 0, + sizeof(hal_ks_t) - sizeof(ks->driver)); memset(mem, 0, len); ks->index = gnaw(&mem, &len, sizeof(*ks->index) * ks_blocks); @@ -498,23 +499,21 @@ static inline hal_error_t key_visible(hal_ks_t * const ks, const hal_session_handle_t session, const unsigned blockno) { + hal_error_t err; + if (ks == NULL) return HAL_ERROR_IMPOSSIBLE; if (!ks->per_session) return HAL_OK; - hal_error_t err; - - if ((err = hal_ks_block_test_owner(ks, blockno, client, session)) != HAL_OK) + if ((err = hal_ks_block_test_owner(ks, blockno, client, session)) != HAL_ERROR_KEY_NOT_FOUND) return err; - err = hal_rpc_is_logged_in(client, HAL_USER_WHEEL); - - if (err == HAL_ERROR_FORBIDDEN) - err = HAL_ERROR_KEY_NOT_FOUND; + if ((err = hal_rpc_is_logged_in(client, HAL_USER_WHEEL)) != HAL_ERROR_FORBIDDEN) + return err; - return err; + return HAL_ERROR_KEY_NOT_FOUND; } hal_error_t hal_ks_store(hal_ks_t *ks, -- cgit v1.2.3 From d2633bb4155c6798949e92d8113bc036b942a018 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Mon, 29 May 2017 12:44:12 -0400 Subject: Indentation. --- ks.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'ks.c') diff --git a/ks.c b/ks.c index 2d1d8c4..2b33771 100644 --- a/ks.c +++ b/ks.c @@ -163,10 +163,10 @@ hal_error_t hal_ks_block_read_cached(hal_ks_t *ks, const unsigned blockno, hal_k */ hal_error_t hal_ks_block_update(hal_ks_t *ks, - const unsigned b1, - hal_ks_block_t *block, - const hal_uuid_t * const uuid, - int *hint) + const unsigned b1, + hal_ks_block_t *block, + const hal_uuid_t * const uuid, + int *hint) { if (block == NULL) return HAL_ERROR_IMPOSSIBLE; -- cgit v1.2.3 From 776c4e8cfed92bc2d894f002cb7d222abc65bb50 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Mon, 29 May 2017 13:16:14 -0400 Subject: Simplify per-session keys. Cosmetic cleanup of pkey_slot along the way. --- ks.c | 68 +++++++++++++++----------------------------------------------------- 1 file changed, 15 insertions(+), 53 deletions(-) (limited to 'ks.c') diff --git a/ks.c b/ks.c index 2b33771..e966b94 100644 --- a/ks.c +++ b/ks.c @@ -477,45 +477,6 @@ static inline int acceptable_key_type(const hal_key_type_t type) } } -/* - * Test whether the current session can see a particular key. One - * might expect this to be based on whether the session matches, and - * indeed it would be in a sane world, but in the world of PKCS #11, - * keys belong to sessions, are visible to other sessions, and may - * even be modifiable by other sessions, but softly and silently - * vanish away when the original creating session is destroyed. - * - * In our terms, this means that visibility of session objects is - * determined only by the client handle, so taking the session handle - * as an argument here isn't really necessary, but we've flipflopped - * on that enough times that at least for now I'd prefer to leave the - * session handle here and not have to revise all the RPC calls again. - * Remove it at some later date and redo the RPC calls if we manage to - * avoid revising this yet again. - */ - -static inline hal_error_t key_visible(hal_ks_t * const ks, - const hal_client_handle_t client, - const hal_session_handle_t session, - const unsigned blockno) -{ - hal_error_t err; - - if (ks == NULL) - return HAL_ERROR_IMPOSSIBLE; - - if (!ks->per_session) - return HAL_OK; - - if ((err = hal_ks_block_test_owner(ks, blockno, client, session)) != HAL_ERROR_KEY_NOT_FOUND) - return err; - - if ((err = hal_rpc_is_logged_in(client, HAL_USER_WHEEL)) != HAL_ERROR_FORBIDDEN) - return err; - - return HAL_ERROR_KEY_NOT_FOUND; -} - 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) @@ -571,7 +532,7 @@ hal_error_t hal_ks_store(hal_ks_t *ks, err = hal_ks_block_write(ks, b, block); if (err == HAL_OK) - err = hal_ks_block_set_owner(ks, b, slot->client_handle, slot->session_handle); + err = hal_ks_block_set_owner(ks, b, slot->client, slot->session); if (err == HAL_OK) goto done; @@ -598,9 +559,9 @@ hal_error_t hal_ks_fetch(hal_ks_t *ks, hal_ks_lock(); - if ((err = hal_ks_index_find(ks, &slot->name, &b, &slot->hint)) != HAL_OK || - (err = key_visible(ks, slot->client_handle, slot->session_handle, b)) != HAL_OK || - (err = hal_ks_block_read_cached(ks, b, &block)) != HAL_OK) + 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; if (hal_ks_block_get_type(block) != HAL_KS_BLOCK_TYPE_KEY) { @@ -652,8 +613,8 @@ hal_error_t hal_ks_delete(hal_ks_t *ks, hal_ks_lock(); - if ((err = hal_ks_index_delete(ks, &slot->name, &b, &slot->hint)) != HAL_OK || - (err = key_visible(ks, slot->client_handle, slot->session_handle, b)) != HAL_OK) + if ((err = hal_ks_index_delete(ks, &slot->name, &b, &slot->hint)) != HAL_OK || + (err = hal_ks_block_test_owner(ks, b, slot->client, slot->session)) != HAL_OK) goto done; hal_ks_cache_release(ks, hal_ks_cache_find_block(ks, b)); @@ -725,9 +686,10 @@ hal_error_t hal_ks_match(hal_ks_t *ks, if ((err = hal_ks_block_read_cached(ks, b, &block)) != HAL_OK) goto done; - if ((err = key_visible(ks, client, session, b)) == HAL_ERROR_KEY_NOT_FOUND) + if ((err = hal_ks_block_test_owner(ks, b, client, session)) == HAL_ERROR_KEY_NOT_FOUND) continue; - else if (err != HAL_OK) + + if (err != HAL_OK) goto done; if ((type != HAL_KEY_TYPE_NONE && type != block->key.type) || @@ -799,9 +761,9 @@ hal_error_t hal_ks_set_attributes(hal_ks_t *ks, hal_ks_lock(); { - if ((err = hal_ks_index_find(ks, &slot->name, &b, &slot->hint)) != HAL_OK || - (err = key_visible(ks, slot->client_handle, slot->session_handle, b)) != HAL_OK || - (err = hal_ks_block_read_cached(ks, b, &block)) != HAL_OK) + 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); @@ -865,9 +827,9 @@ hal_error_t hal_ks_get_attributes(hal_ks_t *ks, hal_ks_lock(); { - if ((err = hal_ks_index_find(ks, &slot->name, &b, &slot->hint)) != HAL_OK || - (err = key_visible(ks, slot->client_handle, slot->session_handle, b)) != HAL_OK || - (err = hal_ks_block_read_cached(ks, b, &block)) != HAL_OK) + 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); -- cgit v1.2.3 From 6b881dfa81a0d51d4897c62de5abdb94c1aba0b7 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Tue, 30 May 2017 19:52:32 -0400 Subject: Hold keystore lock before calling keystore driver methods. Most keystore methods already followed this rule, but hal_ks_*_init() and hal_ks_*_logout() were confused, in different ways. --- ks.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) (limited to 'ks.c') diff --git a/ks.c b/ks.c index 92dc303..665a2fd 100644 --- a/ks.c +++ b/ks.c @@ -205,10 +205,19 @@ hal_error_t hal_ks_block_update(hal_ks_t *ks, hal_error_t hal_ks_init(hal_ks_t *ks, const int alloc) { - return - ks == NULL || ks->driver == NULL ? HAL_ERROR_BAD_ARGUMENTS : - ks->driver->init == NULL ? HAL_ERROR_NOT_IMPLEMENTED : - ks->driver->init(ks, alloc); + if (ks == NULL || ks->driver == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + if (ks->driver->init == NULL) + return HAL_ERROR_NOT_IMPLEMENTED; + + hal_ks_lock(); + + const hal_error_t err = ks->driver->init(ks, alloc); + + hal_ks_unlock(); + + return err; } static inline void *gnaw(uint8_t **mem, size_t *len, const size_t size) @@ -466,10 +475,19 @@ hal_error_t hal_ks_init_common(hal_ks_t *ks) 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); + if (ks == NULL || ks->driver == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + if (ks->driver->logout == NULL) + return HAL_ERROR_NOT_IMPLEMENTED; + + hal_ks_lock(); + + const hal_error_t err = ks->driver->logout(ks, client); + + hal_ks_unlock(); + + return err; } /* -- cgit v1.2.3 From a83d9dfba5f882ca75eaab9a166e6ad9794f2f90 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Sun, 4 Jun 2017 12:21:45 -0400 Subject: Tweak CRC input to be backwards compatabile with ksng. Except for torture tests, we never really used the hideously complex multi-block capabilities of the ksng version of the flash keystore, among other reasons because the only keys large enough to trigger the multi-block code were slow enough to constitute torture on their own. So we can preserve backwards compatabliity simply by including the former *chunk fields (renamed legacy* here) in the CRC and checking for the expected single-block key values. We probably want to include everything in the CRC in any case except when there's an explicit reason omit something, so, this is cheap, just a bit obscure. At some point in the future we can phase out support for the backwards compatible values, but there's no particular hurry about it unless we want to reuse those fields for some other purpose. --- ks.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'ks.c') diff --git a/ks.c b/ks.c index 665a2fd..a4e7498 100644 --- a/ks.c +++ b/ks.c @@ -130,6 +130,12 @@ hal_crc32_t hal_ks_block_calculate_crc(const hal_ks_block_t * const block) crc = hal_crc32_update(crc, &block->header.block_type, sizeof(block->header.block_type)); + crc = hal_crc32_update(crc, &block->header.legacy_1, + sizeof(block->header.legacy_1)); + + crc = hal_crc32_update(crc, &block->header.legacy_2, + sizeof(block->header.legacy_2)); + crc = hal_crc32_update(crc, block->bytes + sizeof(hal_ks_block_header_t), sizeof(*block) - sizeof(hal_ks_block_header_t)); @@ -310,11 +316,16 @@ hal_error_t hal_ks_init_common(hal_ks_t *ks) if (err == HAL_ERROR_KEYSTORE_BAD_CRC || err == HAL_ERROR_KEYSTORE_BAD_BLOCK_TYPE) block_types[i] = HAL_KS_BLOCK_TYPE_UNKNOWN; - else if (err == HAL_OK) - block_types[i] = hal_ks_block_get_type(block); + else if (err != HAL_OK) + return err; + + else if ((block->header.legacy_1 != 0xFF || block->header.legacy_2 != 0xFF) && + (block->header.legacy_1 != 0x01 || block->header.legacy_2 != 0x00)) + block_types[i] = HAL_KS_BLOCK_TYPE_UNKNOWN; else - return err; + block_types[i] = hal_ks_block_get_type(block); + switch (block_types[i]) { case HAL_KS_BLOCK_TYPE_KEY: -- cgit v1.2.3