From 6c8a60b104141ee4f5779a10956c62b0441a262b Mon Sep 17 00:00:00 2001 From: Bayrem Gharsellaoui Date: Tue, 5 Aug 2025 15:35:01 +0100 Subject: [PATCH 1/3] drivers: crypto: Add STM32 HASH hardware driver Add STM32 HASH driver with SHA-224/256 support for STM32U5 Signed-off-by: Bayrem Gharsellaoui --- drivers/crypto/CMakeLists.txt | 1 + drivers/crypto/Kconfig.stm32 | 18 +++ drivers/crypto/crypto_stm32_hash.c | 186 ++++++++++++++++++++++++ drivers/crypto/crypto_stm32_hash_priv.h | 40 +++++ dts/bindings/crypto/st,stm32-hash.yaml | 22 +++ 5 files changed, 267 insertions(+) create mode 100644 drivers/crypto/crypto_stm32_hash.c create mode 100644 drivers/crypto/crypto_stm32_hash_priv.h create mode 100644 dts/bindings/crypto/st,stm32-hash.yaml diff --git a/drivers/crypto/CMakeLists.txt b/drivers/crypto/CMakeLists.txt index 448febf70672f..f325c7f34a9aa 100644 --- a/drivers/crypto/CMakeLists.txt +++ b/drivers/crypto/CMakeLists.txt @@ -4,6 +4,7 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_CRYPTO_ATAES132A crypto_ataes132a.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_MBEDTLS_SHIM crypto_mtls_shim.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_STM32 crypto_stm32.c) +zephyr_library_sources_ifdef(CONFIG_CRYPTO_STM32_HASH crypto_stm32_hash.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_SMARTBOND crypto_smartbond.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_NRF_ECB crypto_nrf_ecb.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_INTEL_SHA crypto_intel_sha.c) diff --git a/drivers/crypto/Kconfig.stm32 b/drivers/crypto/Kconfig.stm32 index 424e5b81fe03c..513347a011a88 100644 --- a/drivers/crypto/Kconfig.stm32 +++ b/drivers/crypto/Kconfig.stm32 @@ -19,3 +19,21 @@ config CRYPTO_STM32_MAX_SESSION help This can be used to tweak the amount of sessions the driver can handle in parallel. + +config CRYPTO_STM32_HASH + bool "STM32 Hash Accelerator driver" + default y + depends on DT_HAS_ST_STM32_HASH_ENABLED + select USE_STM32_HAL_HASH + select USE_STM32_HAL_HASH_EX + help + Enable support for the STM32 HASH hardware accelerator (SHA224/SHA256), + using the STM32 HAL HASH driver. + +config CRYPTO_STM32_HASH_MAX_SESSIONS + int "Maximum of sessions STM32 hash driver can handle" + default 2 + depends on CRYPTO_STM32_HASH + help + This can be used to tweak the amount of sessions the driver + can handle in parallel. diff --git a/drivers/crypto/crypto_stm32_hash.c b/drivers/crypto/crypto_stm32_hash.c new file mode 100644 index 0000000000000..b563ed899cef8 --- /dev/null +++ b/drivers/crypto/crypto_stm32_hash.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2025 Bayrem Gharsellaoui + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "crypto_stm32_hash_priv.h" + +#define LOG_LEVEL CONFIG_CRYPTO_LOG_LEVEL +#include +LOG_MODULE_REGISTER(crypto_stm32_hash); + +#define DT_DRV_COMPAT st_stm32_hash + +static struct crypto_stm32_hash_session stm32_hash_sessions[CONFIG_CRYPTO_STM32_HASH_MAX_SESSIONS]; + +static int crypto_stm32_hash_get_unused_session_index(const struct device *dev) +{ + struct crypto_stm32_hash_data *data = CRYPTO_STM32_HASH_DATA(dev); + + k_sem_take(&data->session_sem, K_FOREVER); + + for (int i = 0; i < CONFIG_CRYPTO_STM32_HASH_MAX_SESSIONS; i++) { + if (!stm32_hash_sessions[i].in_use) { + stm32_hash_sessions[i].in_use = true; + k_sem_give(&data->session_sem); + return i; + } + } + + k_sem_give(&data->session_sem); + return -1; +} + +static int stm32_hash_handler(struct hash_ctx *ctx, struct hash_pkt *pkt, bool finish) +{ + const struct device *dev = ctx->device; + struct crypto_stm32_hash_data *data = CRYPTO_STM32_HASH_DATA(dev); + struct crypto_stm32_hash_session *session = CRYPTO_STM32_HASH_SESSN(ctx); + HAL_StatusTypeDef status; + + if (!pkt || !pkt->in_buf || !pkt->out_buf) { + LOG_ERR("Invalid packet buffers"); + return -EINVAL; + } + + if (!finish) { + LOG_ERR("Multipart hashing not supported yet"); + return -ENOTSUP; + } + + k_sem_take(&data->device_sem, K_FOREVER); + + switch (session->algo) { + case CRYPTO_HASH_ALGO_SHA224: + status = HAL_HASHEx_SHA224_Start(&data->hhash, pkt->in_buf, pkt->in_len, + pkt->out_buf, HAL_MAX_DELAY); + break; + case CRYPTO_HASH_ALGO_SHA256: + status = HAL_HASHEx_SHA256_Start(&data->hhash, pkt->in_buf, pkt->in_len, + pkt->out_buf, HAL_MAX_DELAY); + break; + default: + k_sem_give(&data->device_sem); + LOG_ERR("Unsupported algorithm in handler: %d", session->algo); + return -EINVAL; + } + + k_sem_give(&data->device_sem); + + if (status != HAL_OK) { + LOG_ERR("HAL HASH computation failed (status=%d)", status); + return -EIO; + } + + LOG_DBG("Hash computation successful"); + return 0; +} + +static int stm32_hash_begin_session(const struct device *dev, struct hash_ctx *ctx, + enum hash_algo algo) +{ + int ctx_idx; + struct crypto_stm32_hash_session *session; + + switch (algo) { + case CRYPTO_HASH_ALGO_SHA224: + case CRYPTO_HASH_ALGO_SHA256: + break; + default: + LOG_ERR("Unsupported hash algorithm: %d", algo); + return -EINVAL; + } + + ctx_idx = crypto_stm32_hash_get_unused_session_index(dev); + if (ctx_idx < 0) { + LOG_ERR("No free session for now"); + return -ENOSPC; + } + + session = &stm32_hash_sessions[ctx_idx]; + memset(&session->config, 0, sizeof(session->config)); + memset(session->digest, 0, sizeof(session->digest)); + session->in_use = true; + session->algo = algo; + + ctx->drv_sessn_state = session; + ctx->hash_hndlr = stm32_hash_handler; + ctx->started = false; + + LOG_DBG("begin_session (algo=%d)", algo); + return 0; +} + +static int stm32_hash_free_session(const struct device *dev, struct hash_ctx *ctx) +{ + struct crypto_stm32_hash_session *session = CRYPTO_STM32_HASH_SESSN(ctx); + + if (!session) { + LOG_ERR("Tried to free a NULL session"); + return -EINVAL; + } + + memset(session, 0, sizeof(*session)); + + LOG_DBG("Session freed"); + return 0; +} + +static int stm32_hash_query_caps(const struct device *dev) +{ + return (CAP_SYNC_OPS | CAP_SEPARATE_IO_BUFS); +} + +static int crypto_stm32_hash_init(const struct device *dev) +{ + const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); + const struct crypto_stm32_hash_config *cfg = CRYPTO_STM32_HASH_CFG(dev); + struct crypto_stm32_hash_data *data = CRYPTO_STM32_HASH_DATA(dev); + + if (!device_is_ready(clk)) { + LOG_ERR("Clock control device not ready"); + return -ENODEV; + } + + if (clock_control_on(clk, (clock_control_subsys_t)&cfg->pclken) != 0) { + LOG_ERR("Clock op failed\n"); + return -EIO; + } + + k_sem_init(&data->device_sem, 1, 1); + k_sem_init(&data->session_sem, 1, 1); + + data->hhash.Init.DataType = HASH_DATATYPE_8B; + if (HAL_HASH_Init(&data->hhash) != HAL_OK) { + LOG_ERR("Peripheral init error"); + return -EIO; + } + + return 0; +} + +static DEVICE_API(crypto, stm32_hash_funcs) = { + .hash_begin_session = stm32_hash_begin_session, + .hash_free_session = stm32_hash_free_session, + .query_hw_caps = stm32_hash_query_caps, +}; + +static struct crypto_stm32_hash_data crypto_stm32_hash_dev_data = {0}; + +static const struct crypto_stm32_hash_config crypto_stm32_hash_dev_config = { + .reset = RESET_DT_SPEC_INST_GET(0), + .pclken = {.enr = DT_INST_CLOCKS_CELL(0, bits), .bus = DT_INST_CLOCKS_CELL(0, bus)}}; + +DEVICE_DT_INST_DEFINE(0, crypto_stm32_hash_init, NULL, &crypto_stm32_hash_dev_data, + &crypto_stm32_hash_dev_config, POST_KERNEL, CONFIG_CRYPTO_INIT_PRIORITY, + &stm32_hash_funcs); diff --git a/drivers/crypto/crypto_stm32_hash_priv.h b/drivers/crypto/crypto_stm32_hash_priv.h new file mode 100644 index 0000000000000..74f1a9b316645 --- /dev/null +++ b/drivers/crypto/crypto_stm32_hash_priv.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025 Bayrem Gharsellaoui + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_CRYPTO_CRYPTO_STM32_HASH_PRIV_H_ +#define ZEPHYR_DRIVERS_CRYPTO_CRYPTO_STM32_HASH_PRIV_H_ + +#define hash_config_t HASH_InitTypeDef + +/* Max digest length: SHA256 = 32 bytes */ +#define STM32_HASH_MAX_DIGEST_SIZE (32) + +struct crypto_stm32_hash_config { + const struct reset_dt_spec reset; + struct stm32_pclken pclken; +}; + +struct crypto_stm32_hash_data { + HASH_HandleTypeDef hhash; + struct k_sem device_sem; + struct k_sem session_sem; +}; + +struct crypto_stm32_hash_session { + hash_config_t config; + uint8_t digest[STM32_HASH_MAX_DIGEST_SIZE]; + bool in_use; + enum hash_algo algo; +}; + +#define CRYPTO_STM32_HASH_CFG(dev) ((const struct crypto_stm32_hash_config *const)(dev)->config) + +#define CRYPTO_STM32_HASH_DATA(dev) ((struct crypto_stm32_hash_data *const)(dev)->data) + +#define CRYPTO_STM32_HASH_SESSN(ctx) \ + ((struct crypto_stm32_hash_session *const)(ctx)->drv_sessn_state) + +#endif /* ZEPHYR_DRIVERS_CRYPTO_CRYPTO_STM32_HASH_PRIV_H_ */ diff --git a/dts/bindings/crypto/st,stm32-hash.yaml b/dts/bindings/crypto/st,stm32-hash.yaml new file mode 100644 index 0000000000000..a71bd95b6e095 --- /dev/null +++ b/dts/bindings/crypto/st,stm32-hash.yaml @@ -0,0 +1,22 @@ +# Copyright (c) 2025 Bayrem Gharsellaoui +# SPDX-License-Identifier: Apache-2.0 + +title: STM32 HASH Processor + +description: | + STM32 hardware hash accelerator supporting SHA-224 and SHA-256 + hashing algorithms. + +compatible: "st,stm32-hash" + +include: [base.yaml, reset-device.yaml] + +properties: + reg: + required: true + + clocks: + required: true + + resets: + required: true From cb93af6eb5e9ea9abd23f21808e897800734e83b Mon Sep 17 00:00:00 2001 From: Bayrem Gharsellaoui Date: Tue, 5 Aug 2025 15:37:30 +0100 Subject: [PATCH 2/3] boards: stm32: Enable HASH peripheral for nucleo_u575zi_q Add device tree support for STM32 HASH peripheral on the nucleo_u575zi_q Signed-off-by: Bayrem Gharsellaoui --- boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi | 4 ++++ dts/arm/st/u5/stm32u575.dtsi | 1 + dts/arm/st/u5/stm32u5_crypt.dtsi | 8 ++++++++ 3 files changed, 13 insertions(+) diff --git a/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi b/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi index d9579a8a0c4a8..9b6cbd766d0b6 100644 --- a/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi +++ b/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi @@ -176,6 +176,10 @@ status = "okay"; }; +&hash { + status = "okay"; +}; + zephyr_udc0: &usbotg_fs { pinctrl-0 = <&usb_otg_fs_dm_pa11 &usb_otg_fs_dp_pa12>; pinctrl-names = "default"; diff --git a/dts/arm/st/u5/stm32u575.dtsi b/dts/arm/st/u5/stm32u575.dtsi index 1db3c8325e10b..c83b3fc7fc6ec 100644 --- a/dts/arm/st/u5/stm32u575.dtsi +++ b/dts/arm/st/u5/stm32u575.dtsi @@ -7,6 +7,7 @@ #include #include +#include / { sram0: memory@20000000 { diff --git a/dts/arm/st/u5/stm32u5_crypt.dtsi b/dts/arm/st/u5/stm32u5_crypt.dtsi index 6b36a01f9f100..77d03149116dd 100644 --- a/dts/arm/st/u5/stm32u5_crypt.dtsi +++ b/dts/arm/st/u5/stm32u5_crypt.dtsi @@ -14,5 +14,13 @@ interrupts = <93 0>; status = "disabled"; }; + + hash: hash@420c0400 { + compatible = "st,stm32-hash"; + reg = <0x420c0400 0x400>; + clocks = <&rcc STM32_CLOCK(AHB2, 17)>; + resets = <&rctl STM32_RESET(AHB2L, 17)>; + status = "disabled"; + }; }; }; From 0b9cd052a84c36ca1fa7177787b4e47da24d219f Mon Sep 17 00:00:00 2001 From: Bayrem Gharsellaoui Date: Tue, 5 Aug 2025 15:38:07 +0100 Subject: [PATCH 3/3] tests: crypto: Add nucleo_u575zi_q support to crypto_hash test Enable crypto.hash test on nucleo_u575zi_q board Signed-off-by: Bayrem Gharsellaoui --- tests/crypto/crypto_hash/src/main.c | 2 ++ tests/crypto/crypto_hash/testcase.yaml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/crypto/crypto_hash/src/main.c b/tests/crypto/crypto_hash/src/main.c index ea1229dda6df5..3df053996fd75 100644 --- a/tests/crypto/crypto_hash/src/main.c +++ b/tests/crypto/crypto_hash/src/main.c @@ -13,6 +13,8 @@ #define CRYPTO_DRV_NAME CONFIG_CRYPTO_MBEDTLS_SHIM_DRV_NAME #elif DT_HAS_COMPAT_STATUS_OKAY(renesas_smartbond_crypto) #define CRYPTO_DEV_COMPAT renesas_smartbond_crypto +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_hash) +#define CRYPTO_DEV_COMPAT st_stm32_hash #else #error "You need to enable one crypto device" #endif diff --git a/tests/crypto/crypto_hash/testcase.yaml b/tests/crypto/crypto_hash/testcase.yaml index 46436f7cd9b5c..52989e174e670 100644 --- a/tests/crypto/crypto_hash/testcase.yaml +++ b/tests/crypto/crypto_hash/testcase.yaml @@ -2,7 +2,9 @@ tests: crypto.hash: platform_allow: - native_sim + - nucleo_u575zi_q integration_platforms: - native_sim + - nucleo_u575zi_q extra_args: EXTRA_CONF_FILE=prj_mtls_shim.conf tags: crypto