summaryrefslogtreecommitdiff
path: root/chip/npcx
diff options
context:
space:
mode:
authorCHLin <CHLin56@nuvoton.com>2020-09-29 14:23:59 +0800
committerCommit Bot <commit-bot@chromium.org>2020-10-13 11:29:46 +0000
commit0f12014ad53ddfd0063a733a1357f81478136dc8 (patch)
treeb8a4e3b500ed7b9d28ae67588b8ceba42879503c /chip/npcx
parent44435d3b9c447ad25edaa8aece42f1cff0dd6df9 (diff)
downloadchrome-ec-0f12014ad53ddfd0063a733a1357f81478136dc8.tar.gz
npcx9: support SHA256 hardware accelerator
There is the hardware accelerator for SHA computation inside npcx9. This CL wraps the Nuvoton SHA library APIs (which are in the ROM) to Chromium EC's SHA256_* APIs to speed up the SHA256 computation. With the help of the hardware accelerator, the hash computation runs several times faster than the software method (see b:155771688 for more detailed evaluation data.) Also, we can gain ~840 bytes of code size. BRANCH=none BUG=b:165777478 BUG=b:155771688 TEST=pass "make buildall" TEST=flash the same RW image; #define/#undef CONFIG_SHA256_HW_ACCELERATE ; verify the RW hash value is the same in the console message. TEST=with the following test CL, move test patterns in test/sha256.c to board/npcx9_evb/test_sha256.c; pass all test patterns. Signed-off-by: CHLin <CHLin56@nuvoton.com> Change-Id: I45ca609889bd73573d67d15f3e561614201e60f6 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2455021 Tested-by: CH Lin <chlin56@nuvoton.com> Auto-Submit: CH Lin <chlin56@nuvoton.com> Reviewed-by: caveh jalali <caveh@chromium.org> Commit-Queue: caveh jalali <caveh@chromium.org>
Diffstat (limited to 'chip/npcx')
-rw-r--r--chip/npcx/build.mk2
-rw-r--r--chip/npcx/clock.c11
-rw-r--r--chip/npcx/sha256_chip.c141
-rw-r--r--chip/npcx/sha256_chip.h25
4 files changed, 178 insertions, 1 deletions
diff --git a/chip/npcx/build.mk b/chip/npcx/build.mk
index 4409c33c5d..a013ef5ef5 100644
--- a/chip/npcx/build.mk
+++ b/chip/npcx/build.mk
@@ -48,6 +48,8 @@ ifneq ($(CHIP_FAMILY),$(filter $(CHIP_FAMILY),npcx5 npcx7))
chip-y+=lct.o
endif
+chip-$(CONFIG_SHA256_HW_ACCELERATE)+=sha256_chip.o
+
# spi monitor program fw for openocd and UUT(UART Update Tool)
npcx-monitor-fw=chip/npcx/spiflashfw/npcx_monitor
npcx-monitor-fw-bin=${out}/$(npcx-monitor-fw).bin
diff --git a/chip/npcx/clock.c b/chip/npcx/clock.c
index 0f8f737401..ad611973be 100644
--- a/chip/npcx/clock.c
+++ b/chip/npcx/clock.c
@@ -166,11 +166,20 @@ void clock_turbo(void)
#elif NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX7
void clock_turbo(void)
{
- /*
+#if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9
+ /* For NPCX9:
+ * Increase CORE_CLK (CPU) as the same as OSC_CLK. Since
+ * CORE_CLK > 66MHz, we also need to set FIUDIV as 1 but
+ * can keep AHB6DIV to 0.
+ */
+ NPCX_HFCGP = 0x00;
+#else
+ /* For NPCX7:
* Increase CORE_CLK (CPU) as the same as OSC_CLK. Since
* CORE_CLK > 66MHz, we also need to set AHB6DIV and FIUDIV as 1.
*/
NPCX_HFCGP = 0x01;
+#endif
NPCX_HFCBCD = BIT(4);
}
diff --git a/chip/npcx/sha256_chip.c b/chip/npcx/sha256_chip.c
new file mode 100644
index 0000000000..6d2d938895
--- /dev/null
+++ b/chip/npcx/sha256_chip.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2020 The Chromium OS Authors. All rights reserved.
+ * 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 "common.h"
+#include "sha256.h"
+#include "util.h"
+
+enum ncl_status {
+ NCL_STATUS_OK,
+ NCL_STATUS_FAIL,
+ NCL_STATUS_INVALID_PARAM,
+ NCL_STATUS_PARAM_NOT_SUPPORTED,
+ NCL_STATUS_SYSTEM_BUSY,
+ NCL_STATUS_AUTHENTICATION_FAIL,
+ NCL_STATUS_NO_RESPONSE,
+ NCL_STATUS_HARDWARE_ERROR,
+};
+
+enum ncl_sha_type {
+ NCL_SHA_TYPE_2_256 = 0,
+ NCL_SHA_TYPE_2_384 = 1,
+ NCL_SHA_TYPE_2_512 = 2,
+ NCL_SHA_TYPE_NUM
+};
+
+/*
+ * The base address of the table that holds the function pointer for each
+ * SHA256 API in ROM.
+ */
+#define NCL_SHA_BASE_ADDR 0x00000100UL
+struct ncl_sha {
+ /* Get the SHA context size required by SHA APIs. */
+ uint32_t (*get_context_size)(void);
+ /* Initial SHA context. */
+ enum ncl_status (*init_context)(void *ctx);
+ /* Finalize SHA context. */
+ enum ncl_status (*finalize_context)(void *ctx);
+ /* Initiate the SHA hardware module and setups needed parameters. */
+ enum ncl_status (*init)(void *ctx);
+ /*
+ * Prepare the context buffer for a SHA calculation - by loading the
+ * initial SHA-256/384/512 parameters.
+ */
+ enum ncl_status (*start)(void *ctx, enum ncl_sha_type type);
+ /*
+ * Updates the SHA calculation with the additional data. When the
+ * function returns, the hardware and memory buffer shall be ready to
+ * accept new data * buffers for SHA calculation and changes to the data
+ * in data buffer should no longer effect the SHA calculation.
+ */
+ enum ncl_status (*update)(void *ctx, const uint8_t *data, uint32_t Len);
+ /* Return the SHA result (digest.) */
+ enum ncl_status (*finish)(void *ctx, uint8_t *hashDigest);
+ /* Perform a complete SHA calculation */
+ enum ncl_status (*calc)(void *ctx, enum ncl_sha_type type,
+ const uint8_t *data, uint32_t Len, uint8_t *hashDigest);
+ /* Power on/off the SHA module. */
+ enum ncl_status (*power)(void *ctx, uint8_t enable);
+ /* Reset the SHA hardware and terminate any in-progress operations. */
+ enum ncl_status (*reset)(void *ctx);
+};
+
+#define NCL_SHA ((const struct ncl_sha *)NCL_SHA_BASE_ADDR)
+
+void SHA256_init(struct sha256_ctx *ctx)
+{
+ NCL_SHA->init_context(ctx->handle);
+ NCL_SHA->power(ctx->handle, 1);
+ NCL_SHA->init(ctx->handle);
+ NCL_SHA->reset(ctx->handle);
+ NCL_SHA->start(ctx->handle, NCL_SHA_TYPE_2_256);
+}
+
+void SHA256_update(struct sha256_ctx *ctx, const uint8_t *data, uint32_t len)
+{
+ NCL_SHA->update(ctx->handle, data, len);
+}
+
+void SHA256_abort(struct sha256_ctx *ctx)
+{
+ NCL_SHA->reset(ctx->handle);
+ NCL_SHA->power(ctx->handle, 0);
+ NCL_SHA->finalize_context(ctx->handle);
+}
+
+uint8_t *SHA256_final(struct sha256_ctx *ctx)
+{
+ NCL_SHA->finish(ctx->handle, ctx->buf);
+ NCL_SHA->power(ctx->handle, 0);
+ NCL_SHA->finalize_context(ctx->handle);
+ 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;
+ uint8_t *tmp;
+ int i;
+
+ memset(key_pad, mask, SHA256_BLOCK_SIZE);
+ 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);
+ tmp = SHA256_final(&hmac_ctx);
+ memcpy(output, tmp, SHA256_DIGEST_SIZE);
+}
+/*
+ * Note: When the API is called, it will consume about half 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);
+
+ /*
+ * 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);
+}
diff --git a/chip/npcx/sha256_chip.h b/chip/npcx/sha256_chip.h
new file mode 100644
index 0000000000..3b9586d962
--- /dev/null
+++ b/chip/npcx/sha256_chip.h
@@ -0,0 +1,25 @@
+/* Copyright 2020 The Chromium OS Authors. All rights reserved.
+ * 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 "common.h"
+
+#define NPCX_SHA256_HANDLE_SIZE 212
+struct sha256_ctx {
+ /* the context handle required for SHA256 API */
+ uint8_t handle[NPCX_SHA256_HANDLE_SIZE];
+ /*
+ * 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];
+} __aligned(4);
+
+void SHA256_abort(struct sha256_ctx *ctx);
+
+#endif /* __CROS_EC_SHA256_CHIP_H */