summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJun Lin <CHLin56@nuvoton.com>2022-12-08 11:20:45 +0800
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-12-29 03:00:46 +0000
commitdda779dfb7dc661d2c2d1e289a6919987ab9d914 (patch)
tree6af2e89b88f3faa3432089b1ee405ccefb46f174
parent488f8b888a58d4892664109224f5e8231b547623 (diff)
downloadchrome-ec-dda779dfb7dc661d2c2d1e289a6919987ab9d914.tar.gz
zephyr: shim: shim SHA256 API to adapot HW accelerator driver
Wrap Zephyr crypto_sha* driver APIs to meet the interface of Cros-EC SHA256 APIs. This CL has dependency on PR: https://github.com/zephyrproject-rtos/zephyr/pull/53031 BRANCH=none BUG=b:155771688 TEST=keep the same RW image; flash different RO images with/without hardware accelerator; verify the RW hash value is the same in the console message. TEST=in the test CL; move test patterns in test/sha256.c to zephyr/program/npcx_evb/npcx9/src/test_sha256.c; pass all test patterns. Signed-off-by: Jun Lin <CHLin56@nuvoton.com> Change-Id: I3979c088933d2caa09576f4aacc14d2ffb6f73f6 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4116105 Reviewed-by: Fabio Baltieri <fabiobaltieri@google.com> Tested-by: CH Lin <chlin56@nuvoton.com> Commit-Queue: CH Lin <chlin56@nuvoton.com> Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com>
-rw-r--r--include/sha256.h8
-rw-r--r--zephyr/Kconfig13
-rw-r--r--zephyr/include/cros/nuvoton/npcx9.dtsi4
-rw-r--r--zephyr/shim/include/sha256_hw.h23
-rw-r--r--zephyr/shim/src/CMakeLists.txt2
-rw-r--r--zephyr/shim/src/sha256_hw.c138
6 files changed, 188 insertions, 0 deletions
diff --git a/include/sha256.h b/include/sha256.h
index d1193c2661..00cdb73446 100644
--- a/include/sha256.h
+++ b/include/sha256.h
@@ -13,6 +13,13 @@
#define SHA256_DIGEST_SIZE 32
#define SHA256_BLOCK_SIZE 64
+#ifdef CONFIG_PLATFORM_EC_SHA256_HW_ZEPHYR
+/*
+ * The chip's header file must implement the SHA256 context structure and
+ * specific functions for its hardware accelerator module.
+ */
+#include "sha256_hw.h"
+#else
#ifdef CONFIG_SHA256_HW_ACCELERATE
/*
* The chip's header file must implement the SHA256 context structure and
@@ -29,6 +36,7 @@ struct sha256_ctx {
uint8_t buf[SHA256_DIGEST_SIZE]; /* Used to store the final digest. */
};
#endif
+#endif
void SHA256_init(struct sha256_ctx *ctx);
void SHA256_update(struct sha256_ctx *ctx, const uint8_t *data, uint32_t len);
diff --git a/zephyr/Kconfig b/zephyr/Kconfig
index 0a227659d9..c5a7e7fa38 100644
--- a/zephyr/Kconfig
+++ b/zephyr/Kconfig
@@ -578,8 +578,21 @@ config PLATFORM_EC_RTC
to the outside world and can often obtain the current time when
desired.
+# Workaround for not being able to have commas in macro arguments
+DT_CHOSEN_CROS_EC_SHA := cros-ec,sha
+
+config PLATFORM_EC_SHA256_HW_ZEPHYR
+ bool
+ default "$(dt_chosen_enabled,$(DT_CHOSEN_CROS_EC_SHA))"
+ select CRYPTO
+ help
+ Use the Zephyr crypto_sha driver to compute SHA256 hashing.
+ Enabling this config implies PLATFORM_EC_SHA256_HW_ACCELERATE is
+ selected.
+
choice PLATFORM_EC_SHA256_MODE
prompt "Select method to use for computing SHA256 hashes"
+ default PLATFORM_EC_SHA256_HW_ACCELERATE if $(dt_chosen_enabled,$(DT_CHOSEN_CROS_EC_SHA))
help
The verified boot mechanism requests the hash of the entire read-write
portion of the EC image. This is typically done using a hashing block
diff --git a/zephyr/include/cros/nuvoton/npcx9.dtsi b/zephyr/include/cros/nuvoton/npcx9.dtsi
index 864ce20269..3889437342 100644
--- a/zephyr/include/cros/nuvoton/npcx9.dtsi
+++ b/zephyr/include/cros/nuvoton/npcx9.dtsi
@@ -9,6 +9,10 @@
#include <cros/nuvoton/npcx.dtsi>
/ {
+ chosen {
+ cros-ec,sha = &sha0;
+ };
+
soc {
};
diff --git a/zephyr/shim/include/sha256_hw.h b/zephyr/shim/include/sha256_hw.h
new file mode 100644
index 0000000000..5891c6a818
--- /dev/null
+++ b/zephyr/shim/include/sha256_hw.h
@@ -0,0 +1,23 @@
+/* Copyright 2020 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __CROS_EC_SHA256_CHIP_H
+#define __CROS_EC_SHA256_CHIP_H
+
+#include <zephyr/crypto/crypto.h>
+
+struct sha256_ctx {
+ /*
+ * This is used to buffer:
+ * 1. the result (digest) of the SHA256 computation.
+ * 2. the 1st block input data (the key padding) for hmac_SHA256_step.
+ */
+ uint8_t buf[SHA256_BLOCK_SIZE];
+ struct hash_ctx hash_sha256;
+} __aligned(4);
+
+void SHA256_abort(struct sha256_ctx *ctx);
+
+#endif /* __CROS_EC_SHA256_CHIP_H */
diff --git a/zephyr/shim/src/CMakeLists.txt b/zephyr/shim/src/CMakeLists.txt
index d2a35dda49..f7bdb8fe85 100644
--- a/zephyr/shim/src/CMakeLists.txt
+++ b/zephyr/shim/src/CMakeLists.txt
@@ -82,3 +82,5 @@ zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_USBC_RETIMER_INTEL_BB
zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_USBC_RETIMER_INTEL_HB
bb_retimer_usb_mux.c)
zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_SYSTEM_SAFE_MODE system_safe_mode.c)
+zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_SHA256_HW_ZEPHYR
+ sha256_hw.c)
diff --git a/zephyr/shim/src/sha256_hw.c b/zephyr/shim/src/sha256_hw.c
new file mode 100644
index 0000000000..017b2ea857
--- /dev/null
+++ b/zephyr/shim/src/sha256_hw.c
@@ -0,0 +1,138 @@
+/* Copyright 2022 The ChromiumOS Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* SHA256 module for Chrome EC */
+
+#include "sha256.h"
+
+#include <zephyr/crypto/crypto.h>
+#include <zephyr/device.h>
+#include <zephyr/kernel.h>
+#include <zephyr/logging/log.h>
+LOG_MODULE_REGISTER(sha256_hw_shim, CONFIG_CRYPTO_LOG_LEVEL);
+
+static const struct device *sha256_hw_dev =
+ DEVICE_DT_GET(DT_CHOSEN(cros_ec_sha));
+
+void SHA256_init(struct sha256_ctx *ctx)
+{
+ int ret;
+ struct hash_ctx *hash_ctx = &ctx->hash_sha256;
+
+ hash_ctx->flags = CAP_SYNC_OPS | CAP_SEPARATE_IO_BUFS;
+ ret = hash_begin_session(sha256_hw_dev, hash_ctx,
+ CRYPTO_HASH_ALGO_SHA256);
+ if (ret != 0) {
+ LOG_ERR("SHA256 Init Fail");
+ }
+}
+
+void SHA256_update(struct sha256_ctx *ctx, const uint8_t *data, uint32_t len)
+{
+ int ret;
+ struct hash_pkt pkt = {
+ .in_buf = (uint8_t *)data,
+ .in_len = len,
+ .out_buf = ctx->buf,
+ };
+ struct hash_ctx *hash_ctx = &ctx->hash_sha256;
+
+ ret = hash_update(hash_ctx, &pkt);
+
+ if (ret != 0) {
+ LOG_ERR("SHA256 Update Fail");
+ }
+}
+
+void SHA256_abort(struct sha256_ctx *ctx)
+{
+ struct hash_ctx *hash_ctx = &ctx->hash_sha256;
+
+ hash_free_session(sha256_hw_dev, hash_ctx);
+}
+
+uint8_t *SHA256_final(struct sha256_ctx *ctx)
+{
+ int ret;
+ struct hash_pkt pkt = {
+ .in_buf = NULL,
+ .in_len = 0,
+ .out_buf = ctx->buf,
+ };
+ struct hash_ctx *hash_ctx = &ctx->hash_sha256;
+
+ /*
+ * Call hash_compute function with zero input data to finish SHA256
+ * computation and get the digest.
+ */
+ ret = hash_compute(hash_ctx, &pkt);
+
+ if (ret != 0) {
+ LOG_ERR("SHA256 Final Fail");
+ }
+
+ hash_free_session(sha256_hw_dev, hash_ctx);
+ return ctx->buf;
+}
+
+static void hmac_SHA256_step(uint8_t *output, uint8_t mask, const uint8_t *key,
+ const int key_len, const uint8_t *data,
+ const int data_len)
+{
+ struct sha256_ctx hmac_ctx;
+ uint8_t *key_pad = hmac_ctx.buf;
+ int i;
+
+ memset(hmac_ctx.buf, mask, sizeof(hmac_ctx.buf));
+ for (i = 0; i < key_len; i++)
+ key_pad[i] ^= key[i];
+
+ SHA256_init(&hmac_ctx);
+ SHA256_update(&hmac_ctx, key_pad, SHA256_BLOCK_SIZE);
+ SHA256_update(&hmac_ctx, data, data_len);
+ SHA256_final(&hmac_ctx);
+ __ASSERT(sizeof(hmac_ctx.buf) <= SHA256_BLOCK_SIZE,
+ "hmac buf size > SHA256 block size");
+ memcpy(output, hmac_ctx.buf, SHA256_DIGEST_SIZE);
+}
+
+/*
+ * Note: When the API is called, it will consume sizeof(struct sha256_ctx) of
+ * TASK_STACK_SIZE because a variable of structure sha256_ctx is declared
+ * in the function hmac_SHA256_step.
+ */
+void hmac_SHA256(uint8_t *output, const uint8_t *key, const int key_len,
+ const uint8_t *message, const int message_len)
+{
+ /* This code does not support key_len > block_size. */
+ __ASSERT(key_len <= SHA256_BLOCK_SIZE,
+ "Key length > SHA256 block size");
+
+ /*
+ * i_key_pad = key (zero-padded) ^ 0x36
+ * output = hash(i_key_pad || message)
+ * (Use output as temporary buffer)
+ */
+ hmac_SHA256_step(output, 0x36, key, key_len, message, message_len);
+
+ /*
+ * o_key_pad = key (zero-padded) ^ 0x5c
+ * output = hash(o_key_pad || output)
+ */
+ hmac_SHA256_step(output, 0x5c, key, key_len, output,
+ SHA256_DIGEST_SIZE);
+}
+
+static int zephyr_shim_init_sha256(const struct device *unused)
+{
+ ARG_UNUSED(unused);
+
+ if (!device_is_ready(sha256_hw_dev)) {
+ k_oops();
+ }
+
+ return 0;
+}
+SYS_INIT(zephyr_shim_init_sha256, APPLICATION, 0);