Skip to content

Commit 95934d2

Browse files
bayrem-gharsellaouijhedberg
authored andcommitted
drivers: crypto: Add STM32 HASH hardware driver
Add STM32 HASH driver with SHA-224/256 support for STM32U5 Signed-off-by: Bayrem Gharsellaoui <[email protected]>
1 parent 3eb4d79 commit 95934d2

File tree

5 files changed

+267
-0
lines changed

5 files changed

+267
-0
lines changed

drivers/crypto/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ zephyr_library()
44
zephyr_library_sources_ifdef(CONFIG_CRYPTO_ATAES132A crypto_ataes132a.c)
55
zephyr_library_sources_ifdef(CONFIG_CRYPTO_MBEDTLS_SHIM crypto_mtls_shim.c)
66
zephyr_library_sources_ifdef(CONFIG_CRYPTO_STM32 crypto_stm32.c)
7+
zephyr_library_sources_ifdef(CONFIG_CRYPTO_STM32_HASH crypto_stm32_hash.c)
78
zephyr_library_sources_ifdef(CONFIG_CRYPTO_SMARTBOND crypto_smartbond.c)
89
zephyr_library_sources_ifdef(CONFIG_CRYPTO_NRF_ECB crypto_nrf_ecb.c)
910
zephyr_library_sources_ifdef(CONFIG_CRYPTO_INTEL_SHA crypto_intel_sha.c)

drivers/crypto/Kconfig.stm32

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,21 @@ config CRYPTO_STM32_MAX_SESSION
1919
help
2020
This can be used to tweak the amount of sessions the driver
2121
can handle in parallel.
22+
23+
config CRYPTO_STM32_HASH
24+
bool "STM32 Hash Accelerator driver"
25+
default y
26+
depends on DT_HAS_ST_STM32_HASH_ENABLED
27+
select USE_STM32_HAL_HASH
28+
select USE_STM32_HAL_HASH_EX
29+
help
30+
Enable support for the STM32 HASH hardware accelerator (SHA224/SHA256),
31+
using the STM32 HAL HASH driver.
32+
33+
config CRYPTO_STM32_HASH_MAX_SESSIONS
34+
int "Maximum of sessions STM32 hash driver can handle"
35+
default 2
36+
depends on CRYPTO_STM32_HASH
37+
help
38+
This can be used to tweak the amount of sessions the driver
39+
can handle in parallel.

drivers/crypto/crypto_stm32_hash.c

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
/*
2+
* Copyright (c) 2025 Bayrem Gharsellaoui
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/init.h>
8+
#include <zephyr/kernel.h>
9+
#include <zephyr/device.h>
10+
#include <zephyr/crypto/crypto.h>
11+
#include <zephyr/drivers/clock_control/stm32_clock_control.h>
12+
#include <zephyr/drivers/clock_control.h>
13+
#include <zephyr/drivers/reset.h>
14+
#include <soc.h>
15+
16+
#include "crypto_stm32_hash_priv.h"
17+
18+
#define LOG_LEVEL CONFIG_CRYPTO_LOG_LEVEL
19+
#include <zephyr/logging/log.h>
20+
LOG_MODULE_REGISTER(crypto_stm32_hash);
21+
22+
#define DT_DRV_COMPAT st_stm32_hash
23+
24+
static struct crypto_stm32_hash_session stm32_hash_sessions[CONFIG_CRYPTO_STM32_HASH_MAX_SESSIONS];
25+
26+
static int crypto_stm32_hash_get_unused_session_index(const struct device *dev)
27+
{
28+
struct crypto_stm32_hash_data *data = CRYPTO_STM32_HASH_DATA(dev);
29+
30+
k_sem_take(&data->session_sem, K_FOREVER);
31+
32+
for (int i = 0; i < CONFIG_CRYPTO_STM32_HASH_MAX_SESSIONS; i++) {
33+
if (!stm32_hash_sessions[i].in_use) {
34+
stm32_hash_sessions[i].in_use = true;
35+
k_sem_give(&data->session_sem);
36+
return i;
37+
}
38+
}
39+
40+
k_sem_give(&data->session_sem);
41+
return -1;
42+
}
43+
44+
static int stm32_hash_handler(struct hash_ctx *ctx, struct hash_pkt *pkt, bool finish)
45+
{
46+
const struct device *dev = ctx->device;
47+
struct crypto_stm32_hash_data *data = CRYPTO_STM32_HASH_DATA(dev);
48+
struct crypto_stm32_hash_session *session = CRYPTO_STM32_HASH_SESSN(ctx);
49+
HAL_StatusTypeDef status;
50+
51+
if (!pkt || !pkt->in_buf || !pkt->out_buf) {
52+
LOG_ERR("Invalid packet buffers");
53+
return -EINVAL;
54+
}
55+
56+
if (!finish) {
57+
LOG_ERR("Multipart hashing not supported yet");
58+
return -ENOTSUP;
59+
}
60+
61+
k_sem_take(&data->device_sem, K_FOREVER);
62+
63+
switch (session->algo) {
64+
case CRYPTO_HASH_ALGO_SHA224:
65+
status = HAL_HASHEx_SHA224_Start(&data->hhash, pkt->in_buf, pkt->in_len,
66+
pkt->out_buf, HAL_MAX_DELAY);
67+
break;
68+
case CRYPTO_HASH_ALGO_SHA256:
69+
status = HAL_HASHEx_SHA256_Start(&data->hhash, pkt->in_buf, pkt->in_len,
70+
pkt->out_buf, HAL_MAX_DELAY);
71+
break;
72+
default:
73+
k_sem_give(&data->device_sem);
74+
LOG_ERR("Unsupported algorithm in handler: %d", session->algo);
75+
return -EINVAL;
76+
}
77+
78+
k_sem_give(&data->device_sem);
79+
80+
if (status != HAL_OK) {
81+
LOG_ERR("HAL HASH computation failed (status=%d)", status);
82+
return -EIO;
83+
}
84+
85+
LOG_DBG("Hash computation successful");
86+
return 0;
87+
}
88+
89+
static int stm32_hash_begin_session(const struct device *dev, struct hash_ctx *ctx,
90+
enum hash_algo algo)
91+
{
92+
int ctx_idx;
93+
struct crypto_stm32_hash_session *session;
94+
95+
switch (algo) {
96+
case CRYPTO_HASH_ALGO_SHA224:
97+
case CRYPTO_HASH_ALGO_SHA256:
98+
break;
99+
default:
100+
LOG_ERR("Unsupported hash algorithm: %d", algo);
101+
return -EINVAL;
102+
}
103+
104+
ctx_idx = crypto_stm32_hash_get_unused_session_index(dev);
105+
if (ctx_idx < 0) {
106+
LOG_ERR("No free session for now");
107+
return -ENOSPC;
108+
}
109+
110+
session = &stm32_hash_sessions[ctx_idx];
111+
memset(&session->config, 0, sizeof(session->config));
112+
memset(session->digest, 0, sizeof(session->digest));
113+
session->in_use = true;
114+
session->algo = algo;
115+
116+
ctx->drv_sessn_state = session;
117+
ctx->hash_hndlr = stm32_hash_handler;
118+
ctx->started = false;
119+
120+
LOG_DBG("begin_session (algo=%d)", algo);
121+
return 0;
122+
}
123+
124+
static int stm32_hash_free_session(const struct device *dev, struct hash_ctx *ctx)
125+
{
126+
struct crypto_stm32_hash_session *session = CRYPTO_STM32_HASH_SESSN(ctx);
127+
128+
if (!session) {
129+
LOG_ERR("Tried to free a NULL session");
130+
return -EINVAL;
131+
}
132+
133+
memset(session, 0, sizeof(*session));
134+
135+
LOG_DBG("Session freed");
136+
return 0;
137+
}
138+
139+
static int stm32_hash_query_caps(const struct device *dev)
140+
{
141+
return (CAP_SYNC_OPS | CAP_SEPARATE_IO_BUFS);
142+
}
143+
144+
static int crypto_stm32_hash_init(const struct device *dev)
145+
{
146+
const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
147+
const struct crypto_stm32_hash_config *cfg = CRYPTO_STM32_HASH_CFG(dev);
148+
struct crypto_stm32_hash_data *data = CRYPTO_STM32_HASH_DATA(dev);
149+
150+
if (!device_is_ready(clk)) {
151+
LOG_ERR("Clock control device not ready");
152+
return -ENODEV;
153+
}
154+
155+
if (clock_control_on(clk, (clock_control_subsys_t)&cfg->pclken) != 0) {
156+
LOG_ERR("Clock op failed\n");
157+
return -EIO;
158+
}
159+
160+
k_sem_init(&data->device_sem, 1, 1);
161+
k_sem_init(&data->session_sem, 1, 1);
162+
163+
data->hhash.Init.DataType = HASH_DATATYPE_8B;
164+
if (HAL_HASH_Init(&data->hhash) != HAL_OK) {
165+
LOG_ERR("Peripheral init error");
166+
return -EIO;
167+
}
168+
169+
return 0;
170+
}
171+
172+
static DEVICE_API(crypto, stm32_hash_funcs) = {
173+
.hash_begin_session = stm32_hash_begin_session,
174+
.hash_free_session = stm32_hash_free_session,
175+
.query_hw_caps = stm32_hash_query_caps,
176+
};
177+
178+
static struct crypto_stm32_hash_data crypto_stm32_hash_dev_data = {0};
179+
180+
static const struct crypto_stm32_hash_config crypto_stm32_hash_dev_config = {
181+
.reset = RESET_DT_SPEC_INST_GET(0),
182+
.pclken = {.enr = DT_INST_CLOCKS_CELL(0, bits), .bus = DT_INST_CLOCKS_CELL(0, bus)}};
183+
184+
DEVICE_DT_INST_DEFINE(0, crypto_stm32_hash_init, NULL, &crypto_stm32_hash_dev_data,
185+
&crypto_stm32_hash_dev_config, POST_KERNEL, CONFIG_CRYPTO_INIT_PRIORITY,
186+
&stm32_hash_funcs);
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (c) 2025 Bayrem Gharsellaoui
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef ZEPHYR_DRIVERS_CRYPTO_CRYPTO_STM32_HASH_PRIV_H_
8+
#define ZEPHYR_DRIVERS_CRYPTO_CRYPTO_STM32_HASH_PRIV_H_
9+
10+
#define hash_config_t HASH_InitTypeDef
11+
12+
/* Max digest length: SHA256 = 32 bytes */
13+
#define STM32_HASH_MAX_DIGEST_SIZE (32)
14+
15+
struct crypto_stm32_hash_config {
16+
const struct reset_dt_spec reset;
17+
struct stm32_pclken pclken;
18+
};
19+
20+
struct crypto_stm32_hash_data {
21+
HASH_HandleTypeDef hhash;
22+
struct k_sem device_sem;
23+
struct k_sem session_sem;
24+
};
25+
26+
struct crypto_stm32_hash_session {
27+
hash_config_t config;
28+
uint8_t digest[STM32_HASH_MAX_DIGEST_SIZE];
29+
bool in_use;
30+
enum hash_algo algo;
31+
};
32+
33+
#define CRYPTO_STM32_HASH_CFG(dev) ((const struct crypto_stm32_hash_config *const)(dev)->config)
34+
35+
#define CRYPTO_STM32_HASH_DATA(dev) ((struct crypto_stm32_hash_data *const)(dev)->data)
36+
37+
#define CRYPTO_STM32_HASH_SESSN(ctx) \
38+
((struct crypto_stm32_hash_session *const)(ctx)->drv_sessn_state)
39+
40+
#endif /* ZEPHYR_DRIVERS_CRYPTO_CRYPTO_STM32_HASH_PRIV_H_ */
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright (c) 2025 Bayrem Gharsellaoui
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
title: STM32 HASH Processor
5+
6+
description: |
7+
STM32 hardware hash accelerator supporting SHA-224 and SHA-256
8+
hashing algorithms.
9+
10+
compatible: "st,stm32-hash"
11+
12+
include: [base.yaml, reset-device.yaml]
13+
14+
properties:
15+
reg:
16+
required: true
17+
18+
clocks:
19+
required: true
20+
21+
resets:
22+
required: true

0 commit comments

Comments
 (0)