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