summaryrefslogtreecommitdiff
path: root/common/vboot_hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/vboot_hash.c')
-rw-r--r--common/vboot_hash.c89
1 files changed, 69 insertions, 20 deletions
diff --git a/common/vboot_hash.c b/common/vboot_hash.c
index 0642e09e3c..0387040670 100644
--- a/common/vboot_hash.c
+++ b/common/vboot_hash.c
@@ -13,6 +13,7 @@
#include "host_command.h"
#include "sha256.h"
#include "shared_mem.h"
+#include "stdbool.h"
#include "system.h"
#include "task.h"
#include "timer.h"
@@ -44,6 +45,8 @@ static uint32_t curr_pos;
static const uint8_t *hash; /* Hash, or NULL if not valid */
static int want_abort;
static int in_progress;
+#define VBOOT_HASH_DEFERRED true
+#define VBOOT_HASH_BLOCKING false
static struct sha256_ctx ctx;
@@ -109,6 +112,35 @@ static int read_and_hash_chunk(int offset, int size)
#define SHA256_PRINT_SIZE 4
#endif
+static void hash_next_chunk(size_t size)
+{
+#ifdef CONFIG_MAPPED_STORAGE
+ flash_lock_mapped_storage(1);
+ SHA256_update(&ctx, (const uint8_t *)(CONFIG_MAPPED_STORAGE_BASE +
+ data_offset + curr_pos), size);
+ flash_lock_mapped_storage(0);
+#else
+ if (read_and_hash_chunk(data_offset + curr_pos, size) != EC_SUCCESS)
+ return;
+#endif
+}
+
+static void vboot_hash_all_chunks(void)
+{
+ do {
+ size_t size = MIN(CHUNK_SIZE, data_size - curr_pos);
+ hash_next_chunk(size);
+ curr_pos += size;
+ } while (curr_pos < data_size);
+
+ hash = SHA256_final(&ctx);
+ CPRINTS("hash done %ph", HEX_BUF(hash, SHA256_PRINT_SIZE));
+ in_progress = 0;
+ clock_enable_module(MODULE_FAST_CPU, 0);
+
+ return;
+}
+
/**
* Do next chunk of hashing work, if any.
*/
@@ -126,16 +158,7 @@ static void vboot_hash_next_chunk(void)
/* Compute the next chunk of hash */
size = MIN(CHUNK_SIZE, data_size - curr_pos);
-
-#ifdef CONFIG_MAPPED_STORAGE
- flash_lock_mapped_storage(1);
- SHA256_update(&ctx, (const uint8_t *)(CONFIG_MAPPED_STORAGE_BASE +
- data_offset + curr_pos), size);
- flash_lock_mapped_storage(0);
-#else
- if (read_and_hash_chunk(data_offset + curr_pos, size) != EC_SUCCESS)
- return;
-#endif
+ hash_next_chunk(size);
curr_pos += size;
if (curr_pos >= data_size) {
@@ -159,13 +182,23 @@ static void vboot_hash_next_chunk(void)
}
/**
- * Start computing a hash of <size> bytes of data at flash offset <offset>.
*
* If nonce_size is non-zero, prefixes the <nonce> onto the data to be hashed.
* Returns non-zero if error.
*/
+/**
+ * Start computing a hash of <size> bytes of data at flash offset <offset>.
+ *
+ * @param offset start address of data on flash to compute hash for.
+ * @param size size of data to compute hash for.
+ * @param nonce nonce to differentiate hash.
+ * @param nonce_size size of nonce.
+ * @param deferred True to hash progressively through deferred calls.
+ * False to hash with a blocking single call.
+ * @return ec_error_list.
+ */
static int vboot_hash_start(uint32_t offset, uint32_t size,
- const uint8_t *nonce, int nonce_size)
+ const uint8_t *nonce, int nonce_size, bool deferred)
{
/* Fail if hash computation is already in progress */
if (in_progress)
@@ -195,7 +228,10 @@ static int vboot_hash_start(uint32_t offset, uint32_t size,
if (nonce_size)
SHA256_update(&ctx, nonce, nonce_size);
- hook_call_deferred(&vboot_hash_next_chunk_data, 0);
+ if (deferred)
+ hook_call_deferred(&vboot_hash_next_chunk_data, 0);
+ else
+ vboot_hash_all_chunks();
return EC_SUCCESS;
}
@@ -232,7 +268,9 @@ int vboot_hash_invalidate(int offset, int size)
*/
static uint32_t get_rw_size(void)
{
-#ifdef CONFIG_VBOOT_EFS
+#ifdef CONFIG_VBOOT_EFS /* Only needed for EFS, which signs and verifies
+ * entire RW, thus not needed for EFS2, which
+ * verifies only the used image size. */
return CONFIG_RW_SIZE;
#else
return system_get_image_used(SYSTEM_IMAGE_RW);
@@ -270,11 +308,19 @@ static void vboot_hash_init(void)
{
/* Start computing the hash of RW firmware */
vboot_hash_start(flash_get_rw_offset(system_get_active_copy()),
- get_rw_size(), NULL, 0);
+ get_rw_size(), NULL, 0, VBOOT_HASH_DEFERRED);
}
}
DECLARE_HOOK(HOOK_INIT, vboot_hash_init, HOOK_PRIO_INIT_VBOOT_HASH);
+int vboot_get_rw_hash(const uint8_t **dst)
+{
+ int rv = vboot_hash_start(flash_get_rw_offset(system_get_active_copy()),
+ get_rw_size(), NULL, 0, VBOOT_HASH_BLOCKING);
+ *dst = hash;
+ return rv;
+}
+
#ifdef CONFIG_SAVE_VBOOT_HASH
static int vboot_hash_preserve_state(void)
@@ -345,13 +391,14 @@ static int command_hash(int argc, char **argv)
} else if (!strcasecmp(argv[1], "rw")) {
return vboot_hash_start(
get_offset(EC_VBOOT_HASH_OFFSET_ACTIVE),
- get_rw_size(), NULL, 0);
+ get_rw_size(),
+ NULL, 0, VBOOT_HASH_DEFERRED);
} else if (!strcasecmp(argv[1], "ro")) {
return vboot_hash_start(
CONFIG_EC_PROTECTED_STORAGE_OFF +
CONFIG_RO_STORAGE_OFF,
system_get_image_used(SYSTEM_IMAGE_RO),
- NULL, 0);
+ NULL, 0, VBOOT_HASH_DEFERRED);
}
return EC_ERROR_PARAM2;
}
@@ -373,9 +420,10 @@ static int command_hash(int argc, char **argv)
return vboot_hash_start(offset, size,
(const uint8_t *)&nonce,
- sizeof(nonce));
+ sizeof(nonce), VBOOT_HASH_DEFERRED);
} else
- return vboot_hash_start(offset, size, NULL, 0);
+ return vboot_hash_start(offset, size,
+ NULL, 0, VBOOT_HASH_DEFERRED);
}
DECLARE_CONSOLE_COMMAND(hash, command_hash,
"[abort | ro | rw] | [<offset> <size> [<nonce>]]",
@@ -428,7 +476,8 @@ static int host_start_hash(const struct ec_params_vboot_hash *p)
(offset == EC_VBOOT_HASH_OFFSET_UPDATE))
size = get_rw_size();
offset = get_offset(offset);
- rv = vboot_hash_start(offset, size, p->nonce_data, p->nonce_size);
+ rv = vboot_hash_start(offset, size, p->nonce_data, p->nonce_size,
+ VBOOT_HASH_DEFERRED);
if (rv == EC_SUCCESS)
return EC_RES_SUCCESS;