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