diff options
-rw-r--r-- | chip/npcx/build.mk | 2 | ||||
-rw-r--r-- | chip/npcx/clock.c | 11 | ||||
-rw-r--r-- | chip/npcx/sha256_chip.c | 141 | ||||
-rw-r--r-- | chip/npcx/sha256_chip.h | 25 | ||||
-rw-r--r-- | common/build.mk | 17 | ||||
-rw-r--r-- | common/vboot_hash.c | 3 | ||||
-rw-r--r-- | include/config.h | 3 | ||||
-rw-r--r-- | include/sha256.h | 8 |
8 files changed, 207 insertions, 3 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 */ diff --git a/common/build.mk b/common/build.mk index ebaa3cc582..e0350eefb3 100644 --- a/common/build.mk +++ b/common/build.mk @@ -124,7 +124,13 @@ common-$(CONFIG_ONLINE_CALIB)+=stillness_detector.o kasa.o math_util.o \ mat44.o vec3.o newton_fit.o accel_cal.o online_calibration.o \ mkbp_event.o mag_cal.o math_util.o mat33.o gyro_cal.o gyro_still_det.o common-$(CONFIG_SHA1)+= sha1.o -common-$(CONFIG_SHA256)+=sha256.o +ifeq ($(CONFIG_SHA256),y) +# use the standard software SHA256 lib if the chip cannot support SHA256 +# hardware accelerator. +ifeq ($(CONFIG_SHA256_HW_ACCELERATE),) +common-y+=sha256.o +endif +endif common-$(CONFIG_SOFTWARE_CLZ)+=clz.o common-$(CONFIG_SOFTWARE_CTZ)+=ctz.o common-$(CONFIG_CMD_SPI_XFER)+=spi_commands.o @@ -160,7 +166,14 @@ common-$(CONFIG_USB_UPDATE)+=usb_update.o update_fw.o common-$(CONFIG_USBC_PPC)+=usbc_ppc.o common-$(CONFIG_VBOOT_EFS)+=vboot/vboot.o common-$(CONFIG_VBOOT_EFS2)+=vboot/efs2.o -common-$(CONFIG_VBOOT_HASH)+=sha256.o vboot_hash.o +ifeq ($(CONFIG_VBOOT_HASH),y) +common-y+=vboot_hash.o +# use the standard software SHA256 lib if the chip cannot support SHA256 +# hardware accelerator. +ifeq ($(CONFIG_SHA256_HW_ACCELERATE),) +common-y+=sha256.o +endif +endif common-$(CONFIG_VOLUME_BUTTONS)+=button.o common-$(CONFIG_VSTORE)+=vstore.o common-$(CONFIG_WEBUSB_URL)+=webusb_desc.o diff --git a/common/vboot_hash.c b/common/vboot_hash.c index a08c707630..e3bdf9e6fd 100644 --- a/common/vboot_hash.c +++ b/common/vboot_hash.c @@ -67,6 +67,9 @@ void vboot_hash_abort(void) want_abort = 0; data_size = 0; hash = NULL; +#ifdef CONFIG_SHA256_HW_ACCELERATE + SHA256_abort(&ctx); +#endif } } diff --git a/include/config.h b/include/config.h index 1921828c70..612afacad7 100644 --- a/include/config.h +++ b/include/config.h @@ -3334,6 +3334,9 @@ /* Support computing of other hash sizes (without the VBOOT code) */ #undef CONFIG_SHA256 +/* Compute SHA256 by using chip's hardware accelerator */ +#undef CONFIG_SHA256_HW_ACCELERATE + /* Unroll some loops in SHA256_transform for better performance. */ #undef CONFIG_SHA256_UNROLLED diff --git a/include/sha256.h b/include/sha256.h index 6671c0ae3a..130a666788 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_SHA256_HW_ACCELERATE +/* + * The chip's header file must implement the SHA256 context structure and + * specific functions for its hardware accelerator module. + */ +#include "sha256_chip.h" +#else /* SHA256 context */ struct sha256_ctx { uint32_t h[8]; @@ -21,6 +28,7 @@ struct sha256_ctx { uint8_t block[2 * SHA256_BLOCK_SIZE]; uint8_t buf[SHA256_DIGEST_SIZE]; /* Used to store the final digest. */ }; +#endif void SHA256_init(struct sha256_ctx *ctx); void SHA256_update(struct sha256_ctx *ctx, const uint8_t *data, uint32_t len); |