Files
zephyr/drivers/crypto/crypto_stm32_hash.c
Etienne Carriere b0ccb2295f drivers: stm32: use STM32_CLOCK_INFO_BY_NAME() and friends
Use STM32_CLOCK_INFO(), STM32_DT_INST_CLOCK_INFO(),
STM32_CLOCK_INFO_BY_NAME() and STM32_DT_INST_CLOCK_INFO_BY_NAME()
helper macros in STM32 drivers.

Using these macros ensure the clock division factor is properly
populated according to DT information. Prior these changes some
drivers only got the bus and bits position information and missed
the clock division information which is fine only when this division
factor information is 0.

Signed-off-by: Etienne Carriere <etienne.carriere@st.com>
2025-11-14 15:26:17 +02:00

188 lines
4.8 KiB
C

/*
* 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 -ENOTSUP;
}
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 -ENOTSUP;
}
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 = STM32_DT_INST_CLOCK_INFO(0),
};
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);