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