xref: /rk3399_ARM-atf/drivers/st/crypto/stm32_hash.c (revision c1ad67a174528f2295fac0f4c728a4d4398aa15c)
1 /*
2  * Copyright (c) 2019-2025, STMicroelectronics - All Rights Reserved
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <errno.h>
9 #include <stdint.h>
10 
11 #include <arch_helpers.h>
12 #include <common/debug.h>
13 #include <common/sha_common_macros.h>
14 #include <drivers/clk.h>
15 #include <drivers/delay_timer.h>
16 #include <drivers/st/stm32_hash.h>
17 #include <drivers/st/stm32mp_reset.h>
18 #include <lib/mmio.h>
19 #include <lib/utils.h>
20 #include <libfdt.h>
21 #include <plat/common/platform.h>
22 
23 #include <platform_def.h>
24 
25 #if STM32_HASH_VER == 2
26 #define DT_HASH_COMPAT			"st,stm32f756-hash"
27 #endif
28 #if STM32_HASH_VER == 4
29 #define DT_HASH_COMPAT			"st,stm32mp13-hash"
30 #endif
31 
32 #define HASH_CR				0x00U
33 #define HASH_DIN			0x04U
34 #define HASH_STR			0x08U
35 #define HASH_SR				0x24U
36 #define HASH_HREG(x)			(0x310U + ((x) * 0x04U))
37 
38 /* Control Register */
39 #define HASH_CR_INIT			BIT(2)
40 #define HASH_CR_DATATYPE_SHIFT		U(4)
41 #if STM32_HASH_VER == 2
42 #define HASH_CR_ALGO_SHA1		0x0U
43 #define HASH_CR_ALGO_MD5		BIT(7)
44 #define HASH_CR_ALGO_SHA224		BIT(18)
45 #define HASH_CR_ALGO_SHA256		(BIT(18) | BIT(7))
46 #endif
47 #if STM32_HASH_VER == 4
48 #define HASH_CR_ALGO_SHIFT		U(17)
49 #define HASH_CR_ALGO_SHA1		((uint32_t)(0x0U) << HASH_CR_ALGO_SHIFT)
50 #define HASH_CR_ALGO_SHA224		((uint32_t)(0x2U) << HASH_CR_ALGO_SHIFT)
51 #define HASH_CR_ALGO_SHA256		((uint32_t)(0x3U) << HASH_CR_ALGO_SHIFT)
52 #define HASH_CR_ALGO_SHA384		((uint32_t)(0xCU) << HASH_CR_ALGO_SHIFT)
53 #define HASH_CR_ALGO_SHA512_224		((uint32_t)(0xDU) << HASH_CR_ALGO_SHIFT)
54 #define HASH_CR_ALGO_SHA512_256		((uint32_t)(0xEU) << HASH_CR_ALGO_SHIFT)
55 #define HASH_CR_ALGO_SHA512		((uint32_t)(0xFU) << HASH_CR_ALGO_SHIFT)
56 #endif
57 
58 /* Status Flags */
59 #define HASH_SR_DCIS			BIT(1)
60 #define HASH_SR_BUSY			BIT(3)
61 
62 /* STR Register */
63 #define HASH_STR_NBLW_MASK		GENMASK(4, 0)
64 #define HASH_STR_DCAL			BIT(8)
65 
66 #define RESET_TIMEOUT_US_1MS		1000U
67 #define HASH_TIMEOUT_US			10000U
68 
69 enum stm32_hash_data_format {
70 	HASH_DATA_32_BITS,
71 	HASH_DATA_16_BITS,
72 	HASH_DATA_8_BITS,
73 	HASH_DATA_1_BIT
74 };
75 
76 struct stm32_hash_instance {
77 	uintptr_t base;
78 	unsigned int clock;
79 	size_t digest_size;
80 };
81 
82 struct stm32_hash_remain {
83 	uint32_t buffer;
84 	size_t length;
85 };
86 
87 /* Expect a single HASH peripheral */
88 static struct stm32_hash_instance stm32_hash;
89 static struct stm32_hash_remain stm32_remain;
90 
hash_base(void)91 static uintptr_t hash_base(void)
92 {
93 	return stm32_hash.base;
94 }
95 
hash_wait_busy(void)96 static int hash_wait_busy(void)
97 {
98 	uint64_t timeout = timeout_init_us(HASH_TIMEOUT_US);
99 
100 	while ((mmio_read_32(hash_base() + HASH_SR) & HASH_SR_BUSY) != 0U) {
101 		if (timeout_elapsed(timeout)) {
102 			ERROR("%s: busy timeout\n", __func__);
103 			return -ETIMEDOUT;
104 		}
105 	}
106 
107 	return 0;
108 }
109 
hash_wait_computation(void)110 static int hash_wait_computation(void)
111 {
112 	uint64_t timeout = timeout_init_us(HASH_TIMEOUT_US);
113 
114 	while ((mmio_read_32(hash_base() + HASH_SR) & HASH_SR_DCIS) == 0U) {
115 		if (timeout_elapsed(timeout)) {
116 			ERROR("%s: busy timeout\n", __func__);
117 			return -ETIMEDOUT;
118 		}
119 	}
120 
121 	return 0;
122 }
123 
hash_write_data(uint32_t data)124 static int hash_write_data(uint32_t data)
125 {
126 	int ret;
127 
128 	ret = hash_wait_busy();
129 	if (ret != 0) {
130 		return ret;
131 	}
132 
133 	mmio_write_32(hash_base() + HASH_DIN, data);
134 
135 	return 0;
136 }
137 
hash_hw_init(enum stm32_hash_algo_mode mode)138 static void hash_hw_init(enum stm32_hash_algo_mode mode)
139 {
140 	uint32_t reg;
141 
142 	reg = HASH_CR_INIT | ((uint32_t)HASH_DATA_8_BITS << HASH_CR_DATATYPE_SHIFT);
143 
144 	switch (mode) {
145 #if STM32_HASH_VER == 2
146 	case HASH_MD5SUM:
147 		reg |= HASH_CR_ALGO_MD5;
148 		stm32_hash.digest_size = MD5_DIGEST_SIZE;
149 		break;
150 #endif
151 	case HASH_SHA1:
152 		reg |= HASH_CR_ALGO_SHA1;
153 		stm32_hash.digest_size = SHA1_DIGEST_SIZE;
154 		break;
155 	case HASH_SHA224:
156 		reg |= HASH_CR_ALGO_SHA224;
157 		stm32_hash.digest_size = SHA224_DIGEST_SIZE;
158 		break;
159 #if STM32_HASH_VER == 4
160 	case HASH_SHA384:
161 		reg |= HASH_CR_ALGO_SHA384;
162 		stm32_hash.digest_size = SHA384_DIGEST_SIZE;
163 		break;
164 	case HASH_SHA512:
165 		reg |= HASH_CR_ALGO_SHA512;
166 		stm32_hash.digest_size = SHA512_DIGEST_SIZE;
167 		break;
168 #endif
169 	/* Default selected algo is SHA256 */
170 	case HASH_SHA256:
171 	default:
172 		reg |= HASH_CR_ALGO_SHA256;
173 		stm32_hash.digest_size = SHA256_DIGEST_SIZE;
174 		break;
175 	}
176 
177 	mmio_write_32(hash_base() + HASH_CR, reg);
178 }
179 
hash_get_digest(uint8_t * digest)180 static int hash_get_digest(uint8_t *digest)
181 {
182 	int ret;
183 	uint32_t i;
184 	uint32_t dsg;
185 
186 	ret = hash_wait_computation();
187 	if (ret != 0) {
188 		return ret;
189 	}
190 
191 	for (i = 0U; i < (stm32_hash.digest_size / sizeof(uint32_t)); i++) {
192 		dsg = __builtin_bswap32(mmio_read_32(hash_base() +
193 						     HASH_HREG(i)));
194 		(void)(memcpy(&digest[i * sizeof(uint32_t)], (uint8_t *)&dsg, sizeof(uint32_t)));
195 	}
196 
197 	/*
198 	 * Clean hardware context as HASH could be used later
199 	 * by non-secure software
200 	 */
201 	hash_hw_init(HASH_SHA256);
202 
203 	return 0;
204 }
205 
stm32_hash_update(const uint8_t * buffer,size_t length)206 int stm32_hash_update(const uint8_t *buffer, size_t length)
207 {
208 	size_t remain_length = length;
209 	uint8_t *remain_buf = (uint8_t *)&stm32_remain.buffer;
210 	const uint8_t *buf = buffer;
211 	int ret = 0;
212 
213 	if ((length == 0U) || (buffer == NULL)) {
214 		return 0;
215 	}
216 
217 	ret = clk_enable(stm32_hash.clock);
218 	if (ret != 0) {
219 		return ret;
220 	}
221 
222 	if (stm32_remain.length != 0U) {
223 		uint32_t copysize;
224 
225 		copysize = MIN((sizeof(uint32_t) - stm32_remain.length),
226 			       length);
227 		(void)(memcpy(&remain_buf[stm32_remain.length], buf, copysize));
228 		remain_length -= copysize;
229 		buf = &buf[copysize];
230 		if (stm32_remain.length == sizeof(uint32_t)) {
231 			ret = hash_write_data(stm32_remain.buffer);
232 			if (ret != 0) {
233 				goto exit;
234 			}
235 
236 			zeromem(&stm32_remain, sizeof(stm32_remain));
237 		}
238 	}
239 
240 	while (remain_length / sizeof(uint32_t) != 0U) {
241 		uint32_t tmp_buf;
242 
243 		(void)(memcpy((void *)&tmp_buf, buf, sizeof(uint32_t)));
244 		ret = hash_write_data(tmp_buf);
245 		if (ret != 0) {
246 			goto exit;
247 		}
248 
249 		buf = &buf[sizeof(uint32_t)];
250 		remain_length -= sizeof(uint32_t);
251 	}
252 
253 	if (remain_length != 0U) {
254 		assert(stm32_remain.length == 0U);
255 
256 		(void)(memcpy((uint8_t *)&stm32_remain.buffer, buf, remain_length));
257 		stm32_remain.length = remain_length;
258 	}
259 
260 exit:
261 	clk_disable(stm32_hash.clock);
262 
263 	return ret;
264 }
265 
stm32_hash_final(uint8_t * digest)266 int stm32_hash_final(uint8_t *digest)
267 {
268 	int ret;
269 
270 	ret = clk_enable(stm32_hash.clock);
271 	if (ret != 0) {
272 		return ret;
273 	}
274 
275 	if (stm32_remain.length != 0U) {
276 		ret = hash_write_data(stm32_remain.buffer);
277 		if (ret != 0) {
278 			clk_disable(stm32_hash.clock);
279 			return ret;
280 		}
281 
282 		mmio_clrsetbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK,
283 				   8U * stm32_remain.length);
284 		zeromem(&stm32_remain, sizeof(stm32_remain));
285 	} else {
286 		mmio_clrbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK);
287 	}
288 
289 	mmio_setbits_32(hash_base() + HASH_STR, HASH_STR_DCAL);
290 
291 	ret = hash_get_digest(digest);
292 
293 	clk_disable(stm32_hash.clock);
294 
295 	return ret;
296 }
297 
stm32_hash_final_update(const uint8_t * buffer,uint32_t length,uint8_t * digest)298 int stm32_hash_final_update(const uint8_t *buffer, uint32_t length,
299 			    uint8_t *digest)
300 {
301 	int ret;
302 
303 	ret = stm32_hash_update(buffer, length);
304 	if (ret != 0) {
305 		return ret;
306 	}
307 
308 	return stm32_hash_final(digest);
309 }
310 
stm32_hash_init(enum stm32_hash_algo_mode mode)311 void stm32_hash_init(enum stm32_hash_algo_mode mode)
312 {
313 	if (clk_enable(stm32_hash.clock) != 0) {
314 		ERROR("%s: fail to enable clock\n", __func__);
315 		panic();
316 	}
317 
318 	hash_hw_init(mode);
319 
320 	clk_disable(stm32_hash.clock);
321 
322 	zeromem(&stm32_remain, sizeof(stm32_remain));
323 }
324 
stm32_hash_register(void)325 int stm32_hash_register(void)
326 {
327 	struct dt_node_info hash_info;
328 	int node;
329 	int ret;
330 
331 	for (node = dt_get_node(&hash_info, -1, DT_HASH_COMPAT);
332 	     node != -FDT_ERR_NOTFOUND;
333 	     node = dt_get_node(&hash_info, node, DT_HASH_COMPAT)) {
334 		if (hash_info.status != DT_DISABLED) {
335 			break;
336 		}
337 	}
338 
339 	if (node == -FDT_ERR_NOTFOUND) {
340 		return -ENODEV;
341 	}
342 
343 	if (hash_info.clock < 0) {
344 		return -EINVAL;
345 	}
346 
347 	stm32_hash.base = hash_info.base;
348 	stm32_hash.clock = hash_info.clock;
349 
350 	ret = clk_enable(stm32_hash.clock);
351 	if (ret != 0) {
352 		return ret;
353 	}
354 
355 	if (hash_info.reset >= 0) {
356 		uint32_t id = (uint32_t)hash_info.reset;
357 
358 		if (stm32mp_reset_assert(id, RESET_TIMEOUT_US_1MS) != 0) {
359 			panic();
360 		}
361 		udelay(20);
362 		if (stm32mp_reset_deassert(id, RESET_TIMEOUT_US_1MS) != 0) {
363 			panic();
364 		}
365 	}
366 
367 	clk_disable(stm32_hash.clock);
368 
369 	return 0;
370 }
371