summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2019-05-15 08:56:47 -0700
committerchrome-bot <chrome-bot@chromium.org>2019-05-24 15:09:48 -0700
commit58e31f4788e369028f960e2fd39b435f1a1c4687 (patch)
treea08c25ed3316f1c590ba1f73ea189224c85c844f
parent60021c7225b3d247113b4c60e056d0cc01ad50ad (diff)
downloadchrome-ec-58e31f4788e369028f960e2fd39b435f1a1c4687.tar.gz
nvmem: make page header checksums different between prod and dev
When moving an H1 between prod and dev Cr50 images, it is important to quickly determine that the NVMEM contents are not retrievable. The first object verified by the initialization routine is the page header, but since SHA value is used for integrity verification, it does not change despite the fact that the mode (and encryption keys as a result) changed. Using encrypted header value for integrity verification guarantees that when transition between prod and dev modes happen the initialization function discovers it right away and reinitializes NVMEM instead of trying to interpret corrupted objects. The host/dcrypto stub used for unit tests and fuzzing needs to be modified to ensure that page headers read from uninitialized flash do not look valid (where encrypted value of 0xffffffff is 0xffffffff). BRANCH=cr50, cr50-mp BUG=b:129710256 TEST=make buildall -j successd, as well as migration of a Chrome OS device from legacy to new nvmem layout. Change-Id: I613513cc67b14f553d2760919d6058f8dbed6e41 Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1615423 Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org> Reviewed-by: Andrey Pronin <apronin@chromium.org>
-rw-r--r--chip/host/dcrypto/app_cipher.c15
-rw-r--r--common/new_nvmem.c34
-rw-r--r--test/build.mk2
3 files changed, 35 insertions, 16 deletions
diff --git a/chip/host/dcrypto/app_cipher.c b/chip/host/dcrypto/app_cipher.c
index 69d54a41b1..ab52484753 100644
--- a/chip/host/dcrypto/app_cipher.c
+++ b/chip/host/dcrypto/app_cipher.c
@@ -26,8 +26,19 @@ void app_compute_hash(uint8_t *p_buf, size_t num_bytes,
int app_cipher(const void *salt_p, void *out_p, const void *in_p, size_t size)
{
- /* See README.md for while this is a passthrough. */
- memcpy(out_p, in_p, size);
+ /* See README.md for why this is not a real encryption.. */
+ size_t i;
+ const uint8_t *src;
+ const uint8_t *salt;
+ uint8_t *dst;
+
+ src = in_p;
+ salt = salt_p;
+ dst = out_p;
+
+ for (i = 0; i < size; i++)
+ dst[i] = src[i] ^ salt[i & 7];
+
return 1;
}
diff --git a/common/new_nvmem.c b/common/new_nvmem.c
index 4975d4fbe6..d193273ac2 100644
--- a/common/new_nvmem.c
+++ b/common/new_nvmem.c
@@ -19,6 +19,7 @@
#include "nvmem_vars.h"
#include "shared_mem.h"
#include "system.h"
+#include "system_chip.h"
#include "task.h"
#include "timer.h"
@@ -463,15 +464,27 @@ static STATE_CLEAR_DATA *get_scd(void)
ri.offset);
}
-/* Veirify page header hash. */
-static int page_header_is_valid(struct nn_page_header *ph)
+/*
+ * Make sure page header hash is different between prod and other types of
+ * images.
+ */
+static uint32_t calculate_page_header_hash(struct nn_page_header *ph)
{
- uint32_t ph_hash;
+ uint32_t hash;
+ static const uint32_t salt[] = {1, 2, 3, 4};
+
+ BUILD_ASSERT(sizeof(hash) ==
+ offsetof(struct nn_page_header, page_hash));
- app_compute_hash_wrapper(ph, offsetof(struct nn_page_header, page_hash),
- &ph_hash, sizeof(ph_hash));
+ app_cipher(salt, &hash, ph, sizeof(hash));
- return ph_hash == ph->page_hash;
+ return hash;
+}
+
+/* Veirify page header hash. */
+static int page_header_is_valid(struct nn_page_header *ph)
+{
+ return calculate_page_header_hash(ph) == ph->page_hash;
}
/* Convert flash page number in 0..255 range into actual flash address. */
@@ -631,10 +644,7 @@ static enum ec_error_list set_first_page_header(void)
struct nn_page_header *fph; /* Address in flash. */
ph.data_offset = sizeof(ph);
- app_compute_hash_wrapper(&ph,
- offsetof(struct nn_page_header, page_hash),
- &ph.page_hash, sizeof(ph.page_hash));
-
+ ph.page_hash = calculate_page_header_hash(&ph);
fph = flash_index_to_ph(page_list[0]);
rv = write_to_flash(fph, &ph, sizeof(ph));
@@ -956,9 +966,7 @@ static void start_new_flash_page(size_t data_size)
ph.data_offset = sizeof(ph) + data_size;
ph.page_number = master_at.mt.ph->page_number + 1;
- app_compute_hash_wrapper(&ph,
- offsetof(struct nn_page_header, page_hash),
- &ph.page_hash, sizeof(ph.page_hash));
+ ph.page_hash = calculate_page_header_hash(&ph);
master_at.list_index++;
if (master_at.list_index == ARRAY_SIZE(page_list))
report_no_payload_failure(NVMEMF_PAGE_LIST_OVERFLOW);
diff --git a/test/build.mk b/test/build.mk
index b668d1d06d..93ae9d405a 100644
--- a/test/build.mk
+++ b/test/build.mk
@@ -152,7 +152,7 @@ fp-y=fp.o
x25519-y=x25519.o
TPM2_ROOT := $(CROS_WORKON_SRCROOT)/src/third_party/tpm2
-$(out)/RO/common/new_nvmem.o: CFLAGS += -I$(TPM2_ROOT)
+$(out)/RO/common/new_nvmem.o: CFLAGS += -I$(TPM2_ROOT) -I chip/g
$(out)/RO/test/nvmem.o: CFLAGS += -I$(TPM2_ROOT)
$(out)/RO/test/nvmem_tpm2_mock.o: CFLAGS += -I$(TPM2_ROOT)