Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@
status = "okay";
};

&hash {
status = "okay";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we enable this by default? Might be a thing to keep off by default to avoid inflating build sizes. Might be okay though, let maintainers say is it or not

Copy link
Contributor Author

@bayrem-gharsellaoui bayrem-gharsellaoui Aug 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I inspired from the STM32 aes / cryp driver which is enabled by default on the boards

};

zephyr_udc0: &usbotg_fs {
pinctrl-0 = <&usb_otg_fs_dm_pa11 &usb_otg_fs_dp_pa12>;
pinctrl-names = "default";
Expand Down
1 change: 1 addition & 0 deletions drivers/crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
18 changes: 18 additions & 0 deletions drivers/crypto/Kconfig.stm32
Original file line number Diff line number Diff line change
Expand Up @@ -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.
186 changes: 186 additions & 0 deletions drivers/crypto/crypto_stm32_hash.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
/*
* Copyright (c) 2025 Bayrem Gharsellaoui
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/init.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/crypto/crypto.h>
#include <zephyr/drivers/clock_control/stm32_clock_control.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/reset.h>
#include <soc.h>

#include "crypto_stm32_hash_priv.h"

#define LOG_LEVEL CONFIG_CRYPTO_LOG_LEVEL
#include <zephyr/logging/log.h>
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));
Comment on lines +111 to +112
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry if I'm not understanding, but I could not find where these two are used in the driver. Could you please elaborate where those are used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, those fields aren’t actively used in the current implementation. I initially added them to align with how the STM32 HAL handles staged digests and configuration (especially for future support of multipart operations).

I can to remove them for now if that’s preferred.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not one who sets preferences here. Let's wait for maintainers' reviews

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);
40 changes: 40 additions & 0 deletions drivers/crypto/crypto_stm32_hash_priv.h
Original file line number Diff line number Diff line change
@@ -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)
Comment on lines +33 to +38
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the parentheses useful here?

Suggested change
#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)
#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)

Copy link
Contributor Author

@bayrem-gharsellaoui bayrem-gharsellaoui Aug 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I just followed the below implementation as reference.
https://github.com/zephyrproject-rtos/zephyr/blob/main/drivers/crypto/crypto_stm32_priv.h#L38


#endif /* ZEPHYR_DRIVERS_CRYPTO_CRYPTO_STM32_HASH_PRIV_H_ */
1 change: 1 addition & 0 deletions dts/arm/st/u5/stm32u575.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <st/u5/stm32u5_usbotg_fs.dtsi>
#include <zephyr/dt-bindings/memory-controller/stm32-fmc-nor-psram.h>
#include <st/u5/stm32u5_crypt.dtsi>

/ {
sram0: memory@20000000 {
Expand Down
8 changes: 8 additions & 0 deletions dts/arm/st/u5/stm32u5_crypt.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -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";
};
};
};
22 changes: 22 additions & 0 deletions dts/bindings/crypto/st,stm32-hash.yaml
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions tests/crypto/crypto_hash/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions tests/crypto/crypto_hash/testcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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