Skip to content

Commit 6f8efb2

Browse files
committed
drivers: crypto: Add initial support for rpi_pico sha256 accelerator
Add basic support for RaspberryPi Pico's SHA256 hardware accelerator. Signed-off-by: TOKITA Hiroshi <[email protected]>
1 parent a486f51 commit 6f8efb2

File tree

6 files changed

+251
-19
lines changed

6 files changed

+251
-19
lines changed

drivers/crypto/CMakeLists.txt

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
# SPDX-License-Identifier: Apache-2.0
22

33
zephyr_library()
4-
zephyr_library_sources_ifdef(CONFIG_CRYPTO_TINYCRYPT_SHIM crypto_tc_shim.c)
5-
zephyr_library_sources_ifdef(CONFIG_CRYPTO_ATAES132A crypto_ataes132a.c)
6-
zephyr_library_sources_ifdef(CONFIG_CRYPTO_MBEDTLS_SHIM crypto_mtls_shim.c)
7-
zephyr_library_sources_ifdef(CONFIG_CRYPTO_STM32 crypto_stm32.c)
8-
zephyr_library_sources_ifdef(CONFIG_CRYPTO_SMARTBOND crypto_smartbond.c)
9-
zephyr_library_sources_ifdef(CONFIG_CRYPTO_NRF_ECB crypto_nrf_ecb.c)
10-
zephyr_library_sources_ifdef(CONFIG_CRYPTO_INTEL_SHA crypto_intel_sha.c)
11-
zephyr_library_sources_ifdef(CONFIG_CRYPTO_NPCX_SHA crypto_npcx_sha.c)
12-
zephyr_library_sources_ifdef(CONFIG_CRYPTO_MCHP_XEC_SYMCR crypto_mchp_xec_symcr.c)
13-
zephyr_library_sources_ifdef(CONFIG_CRYPTO_IT8XXX2_SHA crypto_it8xxx2_sha.c)
14-
zephyr_library_sources_ifdef(CONFIG_CRYPTO_IT8XXX2_SHA_V2 crypto_it8xxx2_sha_v2.c)
15-
zephyr_library_sources_ifdef(CONFIG_CRYPTO_MCUX_DCP crypto_mcux_dcp.c)
16-
zephyr_library_sources_ifdef(CONFIG_CRYPTO_SI32 crypto_si32.c)
17-
zephyr_library_sources_ifdef(CONFIG_CRYPTO_CC23X0 crypto_cc23x0.c)
4+
5+
# zephyr-keep-sorted-start
6+
zephyr_library_sources_ifdef(CONFIG_CRYPTO_ATAES132A crypto_ataes132a.c)
7+
zephyr_library_sources_ifdef(CONFIG_CRYPTO_CC23X0 crypto_cc23x0.c)
8+
zephyr_library_sources_ifdef(CONFIG_CRYPTO_INTEL_SHA crypto_intel_sha.c)
9+
zephyr_library_sources_ifdef(CONFIG_CRYPTO_IT8XXX2_SHA crypto_it8xxx2_sha.c)
10+
zephyr_library_sources_ifdef(CONFIG_CRYPTO_IT8XXX2_SHA_V2 crypto_it8xxx2_sha_v2.c)
11+
zephyr_library_sources_ifdef(CONFIG_CRYPTO_MBEDTLS_SHIM crypto_mtls_shim.c)
12+
zephyr_library_sources_ifdef(CONFIG_CRYPTO_MCHP_XEC_SYMCR crypto_mchp_xec_symcr.c)
13+
zephyr_library_sources_ifdef(CONFIG_CRYPTO_MCUX_DCP crypto_mcux_dcp.c)
14+
zephyr_library_sources_ifdef(CONFIG_CRYPTO_NPCX_SHA crypto_npcx_sha.c)
15+
zephyr_library_sources_ifdef(CONFIG_CRYPTO_NRF_ECB crypto_nrf_ecb.c)
16+
zephyr_library_sources_ifdef(CONFIG_CRYPTO_RPI_PICO_SHA256 crypto_rpi_pico_sha256.c)
17+
zephyr_library_sources_ifdef(CONFIG_CRYPTO_SI32 crypto_si32.c)
18+
zephyr_library_sources_ifdef(CONFIG_CRYPTO_SMARTBOND crypto_smartbond.c)
19+
zephyr_library_sources_ifdef(CONFIG_CRYPTO_STM32 crypto_stm32.c)
20+
zephyr_library_sources_ifdef(CONFIG_CRYPTO_TINYCRYPT_SHIM crypto_tc_shim.c)
21+
# zephyr-keep-sorted-stop
22+
1823
zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS)

drivers/crypto/Kconfig

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,19 @@ config CRYPTO_MBEDTLS_SHIM_MAX_SESSION
7474
This can be used to tweak the amount of sessions the driver
7575
can handle in parallel.
7676

77+
# zephyr-keep-sorted-start
7778
source "drivers/crypto/Kconfig.ataes132a"
78-
source "drivers/crypto/Kconfig.stm32"
79-
source "drivers/crypto/Kconfig.nrf_ecb"
79+
source "drivers/crypto/Kconfig.cc23x0"
8080
source "drivers/crypto/Kconfig.intel"
81-
source "drivers/crypto/Kconfig.npcx"
82-
source "drivers/crypto/Kconfig.xec"
8381
source "drivers/crypto/Kconfig.it8xxx2"
8482
source "drivers/crypto/Kconfig.mcux_dcp"
83+
source "drivers/crypto/Kconfig.npcx"
84+
source "drivers/crypto/Kconfig.nrf_ecb"
85+
source "drivers/crypto/Kconfig.rpi_pico"
8586
source "drivers/crypto/Kconfig.si32"
8687
source "drivers/crypto/Kconfig.smartbond"
87-
source "drivers/crypto/Kconfig.cc23x0"
88+
source "drivers/crypto/Kconfig.stm32"
89+
source "drivers/crypto/Kconfig.xec"
90+
# zephyr-keep-sorted-stop
8891

8992
endif # CRYPTO

drivers/crypto/Kconfig.rpi_pico

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright (c) 2025 TOKITA Hiroshi
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config CRYPTO_RPI_PICO_SHA256
5+
bool "RasberryPi Pico SHA256 Accelerator driver"
6+
default y
7+
depends on DT_HAS_RASPBERRYPI_PICO_SHA256_ENABLED
8+
help
9+
RaspberryPi Pico SHA256 accelarator driver.
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
/*
2+
* Copyright (c) 2025 TOKITA Hiroshi
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT raspberrypi_pico_sha256
8+
9+
#include <zephyr/crypto/crypto.h>
10+
#include <zephyr/sys/byteorder.h>
11+
12+
#include <hardware/sha256.h>
13+
#include <pico/bootrom/lock.h>
14+
15+
#include <zephyr/logging/log.h>
16+
LOG_MODULE_REGISTER(sha_rpi_pico_sha256, CONFIG_CRYPTO_LOG_LEVEL);
17+
18+
/*
19+
* This is based on the pico_sha256 implementation in the Pico-SDK.
20+
*/
21+
22+
/* We add one 0x80 byte, then 8 bytes for the size */
23+
#define SHA256_PADDING_DATA_BYTES 9
24+
#define SHA256_BLOCK_SIZE_BYTES 64
25+
26+
struct rpi_pico_sha256_data {
27+
bool locked;
28+
uint8_t cache_used;
29+
union {
30+
uint32_t word;
31+
uint8_t bytes[4];
32+
} cache;
33+
size_t total_data_size;
34+
};
35+
36+
static void write_to_hardware(struct rpi_pico_sha256_data *state, const uint8_t *data,
37+
size_t data_size_bytes)
38+
{
39+
if (!state->cache_used && !(((uintptr_t)data) & 3u)) {
40+
/* aligned writes */
41+
while (data_size_bytes >= 4) {
42+
/* write a whole word */
43+
sha256_wait_ready_blocking();
44+
sha256_put_word(*(const uint32_t *)data);
45+
data += 4;
46+
data_size_bytes -= 4;
47+
}
48+
}
49+
50+
while (data_size_bytes--) {
51+
state->cache.bytes[state->cache_used++] = *data++;
52+
if (state->cache_used == 4) {
53+
state->cache_used = 0;
54+
sha256_wait_ready_blocking();
55+
sha256_put_word(state->cache.word);
56+
}
57+
}
58+
}
59+
60+
static inline size_t bytes_to_write(struct rpi_pico_sha256_data *state, size_t data_size_bytes)
61+
{
62+
return ROUND_UP(state->total_data_size, SHA256_BLOCK_SIZE_BYTES) - state->total_data_size;
63+
}
64+
65+
static void update_internal(struct rpi_pico_sha256_data *state, const uint8_t *data,
66+
size_t data_size_bytes)
67+
{
68+
/* must finish off the last 64 byte block first or else sha256_err_not_ready will be true */
69+
const size_t bytes_left = MIN(bytes_to_write(state, data_size_bytes), data_size_bytes);
70+
71+
if (bytes_left > 0) {
72+
write_to_hardware(state, data, bytes_left);
73+
state->total_data_size += bytes_left;
74+
data_size_bytes -= bytes_left;
75+
data += bytes_left;
76+
}
77+
78+
/* Write the rest of the data */
79+
if (data_size_bytes > 0) {
80+
write_to_hardware(state, data, data_size_bytes);
81+
state->total_data_size += data_size_bytes;
82+
}
83+
}
84+
85+
static void add_zero_bytes(struct rpi_pico_sha256_data *state, size_t data_size_bytes)
86+
{
87+
const uint8_t zero[] = {0, 0, 0, 0};
88+
89+
while ((int32_t)data_size_bytes > 0) {
90+
update_internal(state, zero, MIN(4, data_size_bytes));
91+
data_size_bytes -= 4;
92+
}
93+
}
94+
95+
static void write_padding(struct rpi_pico_sha256_data *state)
96+
{
97+
/* Has to be a multiple of 64 bytes */
98+
99+
uint64_t size = ROUND_UP(state->total_data_size + SHA256_PADDING_DATA_BYTES,
100+
SHA256_BLOCK_SIZE_BYTES);
101+
const size_t user_data_size = state->total_data_size;
102+
const size_t padding_size_bytes = size - state->total_data_size;
103+
const uint8_t one_bit = 0x80;
104+
105+
/* append a single '1' bit */
106+
update_internal(state, &one_bit, 1);
107+
108+
/* Zero unused padding */
109+
add_zero_bytes(state, padding_size_bytes - SHA256_PADDING_DATA_BYTES);
110+
111+
/* Add size in bits, big endian */
112+
size = BSWAP_64((uint64_t)(user_data_size * 8));
113+
update_internal(state, (uint8_t *)&size, sizeof(uint64_t)); /* last write */
114+
}
115+
116+
static int rpi_pico_sha256_hash_handler(struct hash_ctx *ctx, struct hash_pkt *pkt, bool finish)
117+
{
118+
struct rpi_pico_sha256_data *data = ctx->device->data;
119+
120+
assert(data->locked);
121+
122+
data->cache_used = 0;
123+
data->cache.word = 0;
124+
data->total_data_size = 0;
125+
126+
sha256_err_not_ready_clear();
127+
sha256_set_bswap(true);
128+
sha256_start();
129+
130+
update_internal(data, pkt->in_buf, pkt->in_len);
131+
132+
if (!finish) {
133+
return 0;
134+
}
135+
136+
write_padding(data);
137+
sha256_wait_valid_blocking();
138+
139+
for (uint i = 0; i < 8; i++) {
140+
((uint32_t *)pkt->out_buf)[i] = BSWAP_32((uint32_t)sha256_hw->sum[i]);
141+
}
142+
143+
return 0;
144+
}
145+
146+
static int rpi_pico_sha256_query_hw_caps(const struct device *dev)
147+
{
148+
return (CAP_SEPARATE_IO_BUFS | CAP_SYNC_OPS);
149+
}
150+
151+
static int rpi_pico_sha256_hash_begin_session(const struct device *dev, struct hash_ctx *ctx,
152+
enum hash_algo algo)
153+
{
154+
struct rpi_pico_sha256_data *data = dev->data;
155+
156+
assert(!data->locked);
157+
158+
if (algo != CRYPTO_HASH_ALGO_SHA256) {
159+
LOG_ERR("Unsupported algo");
160+
return -EINVAL;
161+
}
162+
163+
if (ctx->flags & ~(rpi_pico_sha256_query_hw_caps(dev))) {
164+
LOG_ERR("Unsupported flag");
165+
return -EINVAL;
166+
}
167+
168+
if (!bootrom_try_acquire_lock(BOOTROM_LOCK_SHA_256)) {
169+
return -EBUSY;
170+
}
171+
172+
data->locked = true;
173+
ctx->hash_hndlr = rpi_pico_sha256_hash_handler;
174+
175+
return 0;
176+
}
177+
178+
static int rpi_pico_sha256_hash_session_free(const struct device *dev, struct hash_ctx *ctx)
179+
{
180+
struct rpi_pico_sha256_data *data = dev->data;
181+
182+
assert(data->locked);
183+
184+
bootrom_release_lock(BOOTROM_LOCK_SHA_256);
185+
data->locked = false;
186+
187+
return 0;
188+
}
189+
190+
static DEVICE_API(crypto, rpi_pico_sha256_crypto_api) = {
191+
.query_hw_caps = rpi_pico_sha256_query_hw_caps,
192+
.hash_begin_session = rpi_pico_sha256_hash_begin_session,
193+
.hash_free_session = rpi_pico_sha256_hash_session_free,
194+
};
195+
196+
#define RPI_PICO_SHA256_INIT(idx) \
197+
static struct rpi_pico_sha256_data rpi_pico_sha256_##idx##_data; \
198+
DEVICE_DT_INST_DEFINE(idx, NULL, NULL, &rpi_pico_sha256_##idx##_data, NULL, POST_KERNEL, \
199+
CONFIG_CRYPTO_INIT_PRIORITY, &rpi_pico_sha256_crypto_api);
200+
201+
DT_INST_FOREACH_STATUS_OKAY(RPI_PICO_SHA256_INIT)

dts/arm/raspberrypi/rpi_pico/rp2350.dtsi

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,12 @@
375375
status = "disabled";
376376
};
377377

378+
sha256: sha256@400f8000 {
379+
compatible = "raspberrypi,pico-sha256";
380+
reg = <0x400f8000 0x200>;
381+
status = "disabled";
382+
};
383+
378384
dma: dma@50000000 {
379385
compatible = "raspberrypi,pico-dma";
380386
reg = <0x50000000 DT_SIZE_K(64)>;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Copyright (c) 2025 TOKITA Hiroshi
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: RaspberryPi Pico SHA256 accelerator
5+
6+
compatible: "raspberrypi,pico-sha256"
7+
8+
include: base.yaml

0 commit comments

Comments
 (0)