From dda779dfb7dc661d2c2d1e289a6919987ab9d914 Mon Sep 17 00:00:00 2001 From: Jun Lin Date: Thu, 8 Dec 2022 11:20:45 +0800 Subject: 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 Change-Id: I3979c088933d2caa09576f4aacc14d2ffb6f73f6 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4116105 Reviewed-by: Fabio Baltieri Tested-by: CH Lin Commit-Queue: CH Lin Code-Coverage: Zoss --- include/sha256.h | 8 ++ zephyr/Kconfig | 13 ++++ zephyr/include/cros/nuvoton/npcx9.dtsi | 4 + zephyr/shim/include/sha256_hw.h | 23 ++++++ zephyr/shim/src/CMakeLists.txt | 2 + zephyr/shim/src/sha256_hw.c | 138 +++++++++++++++++++++++++++++++++ 6 files changed, 188 insertions(+) create mode 100644 zephyr/shim/include/sha256_hw.h create mode 100644 zephyr/shim/src/sha256_hw.c 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 / { + 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 + +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 +#include +#include +#include +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); -- cgit v1.2.1