xref: /rk3399_ARM-atf/drivers/st/crypto/stm32_pka.c (revision 379d77b3705b0f3a88332663bba956289cad5797)
1b0fbc02aSNicolas Toromanoff /*
26a187a00SLionel Debieve  * Copyright (c) 2022-2023, STMicroelectronics - All Rights Reserved
3b0fbc02aSNicolas Toromanoff  *
4b0fbc02aSNicolas Toromanoff  * SPDX-License-Identifier: BSD-3-Clause
5b0fbc02aSNicolas Toromanoff  */
6b0fbc02aSNicolas Toromanoff 
7b0fbc02aSNicolas Toromanoff #include <assert.h>
8b0fbc02aSNicolas Toromanoff #include <errno.h>
9b0fbc02aSNicolas Toromanoff #include <stdint.h>
10b0fbc02aSNicolas Toromanoff 
11b0fbc02aSNicolas Toromanoff #include <drivers/clk.h>
12b0fbc02aSNicolas Toromanoff #include <drivers/delay_timer.h>
13b0fbc02aSNicolas Toromanoff #include <drivers/st/stm32_pka.h>
14b0fbc02aSNicolas Toromanoff #include <drivers/st/stm32mp_reset.h>
15b0fbc02aSNicolas Toromanoff #include <lib/mmio.h>
16b0fbc02aSNicolas Toromanoff #include <lib/utils.h>
17b0fbc02aSNicolas Toromanoff #include <libfdt.h>
18b0fbc02aSNicolas Toromanoff #include <plat/common/platform.h>
19b0fbc02aSNicolas Toromanoff 
20b0fbc02aSNicolas Toromanoff #include <platform_def.h>
21b0fbc02aSNicolas Toromanoff 
226a187a00SLionel Debieve #if !PKA_USE_NIST_P256 && !PKA_USE_BRAINPOOL_P256R1 && !PKA_USE_BRAINPOOL_P256T1 && \
236a187a00SLionel Debieve 	!PKA_USE_NIST_P521
246a187a00SLionel Debieve #error "At least one ECDSA curve needs to be selected"
256a187a00SLionel Debieve #endif
266a187a00SLionel Debieve 
27b0fbc02aSNicolas Toromanoff /*
28b0fbc02aSNicolas Toromanoff  * For our comprehension in this file
29b0fbc02aSNicolas Toromanoff  *  _len are in BITs
30b0fbc02aSNicolas Toromanoff  *  _size are in BYTEs
31b0fbc02aSNicolas Toromanoff  *  _nbw are in number of PKA_word (PKA_word = u64)
32b0fbc02aSNicolas Toromanoff  */
33b0fbc02aSNicolas Toromanoff 
34b0fbc02aSNicolas Toromanoff #define UINT8_LEN			8U
35b0fbc02aSNicolas Toromanoff #define UINT64_LEN			(UINT8_LEN * sizeof(uint64_t))
36007433d8SBoyan Karatotev #define PKA_WORD_SIZE			(sizeof(uint64_t))
37b0fbc02aSNicolas Toromanoff #define OP_NBW_FROM_LEN(len)		(DIV_ROUND_UP_2EVAL((len), UINT64_LEN) + 1)
38b0fbc02aSNicolas Toromanoff #define OP_NBW_FROM_SIZE(s)		OP_NBW_FROM_LEN((s) * UINT8_LEN)
39007433d8SBoyan Karatotev #define OP_SIZE_FROM_SIZE(s)		(OP_NBW_FROM_SIZE(s) * PKA_WORD_SIZE)
40b0fbc02aSNicolas Toromanoff 
41b0fbc02aSNicolas Toromanoff #define DT_PKA_COMPAT			"st,stm32-pka64"
42b0fbc02aSNicolas Toromanoff 
43b0fbc02aSNicolas Toromanoff #define MAX_ECC_SIZE_LEN		640U
44b0fbc02aSNicolas Toromanoff #define MAX_EO_NBW			OP_NBW_FROM_LEN(MAX_ECC_SIZE_LEN)
45b0fbc02aSNicolas Toromanoff 
46b0fbc02aSNicolas Toromanoff /* PKA registers */
47b0fbc02aSNicolas Toromanoff /* PKA control register */
48b0fbc02aSNicolas Toromanoff #define _PKA_CR				0x0U
49b0fbc02aSNicolas Toromanoff /* PKA status register */
50b0fbc02aSNicolas Toromanoff #define _PKA_SR				0x4U
51b0fbc02aSNicolas Toromanoff /* PKA clear flag register */
52b0fbc02aSNicolas Toromanoff #define _PKA_CLRFR			0x8U
53b0fbc02aSNicolas Toromanoff /* PKA version register */
54b0fbc02aSNicolas Toromanoff #define _PKA_VERR			0x1FF4U
55b0fbc02aSNicolas Toromanoff /* PKA identification register */
56b0fbc02aSNicolas Toromanoff #define _PKA_IPIDR			0x1FF8U
57b0fbc02aSNicolas Toromanoff 
58b0fbc02aSNicolas Toromanoff /* PKA control register fields */
59*379d77b3SYann Gautier #define _PKA_CR_MODE_MASK		GENMASK_32(13, 8)
60b0fbc02aSNicolas Toromanoff #define _PKA_CR_MODE_SHIFT		8U
61b0fbc02aSNicolas Toromanoff #define _PKA_CR_MODE_ADD		0x9U
62b0fbc02aSNicolas Toromanoff #define _PKA_CR_MODE_ECDSA_VERIF	0x26U
63b0fbc02aSNicolas Toromanoff #define _PKA_CR_START			BIT(1)
64b0fbc02aSNicolas Toromanoff #define _PKA_CR_EN			BIT(0)
65b0fbc02aSNicolas Toromanoff 
66b0fbc02aSNicolas Toromanoff /* PKA status register fields */
67b0fbc02aSNicolas Toromanoff #define _PKA_SR_BUSY			BIT(16)
68b0fbc02aSNicolas Toromanoff #define _PKA_SR_LMF			BIT(1)
69b0fbc02aSNicolas Toromanoff #define _PKA_SR_INITOK			BIT(0)
70b0fbc02aSNicolas Toromanoff 
71b0fbc02aSNicolas Toromanoff /* PKA it flag fields (used in CR, SR and CLRFR) */
72*379d77b3SYann Gautier #define _PKA_IT_MASK			(GENMASK_32(21, 19) | BIT(17))
73b0fbc02aSNicolas Toromanoff #define _PKA_IT_SHIFT			17U
74b0fbc02aSNicolas Toromanoff #define _PKA_IT_OPERR			BIT(21)
75b0fbc02aSNicolas Toromanoff #define _PKA_IT_ADDRERR			BIT(20)
76b0fbc02aSNicolas Toromanoff #define _PKA_IT_RAMERR			BIT(19)
77b0fbc02aSNicolas Toromanoff #define _PKA_IT_PROCEND			BIT(17)
78b0fbc02aSNicolas Toromanoff 
79b0fbc02aSNicolas Toromanoff /* PKA version register fields */
80*379d77b3SYann Gautier #define _PKA_VERR_MAJREV_MASK		GENMASK_32(7, 4)
81b0fbc02aSNicolas Toromanoff #define _PKA_VERR_MAJREV_SHIFT		4U
82*379d77b3SYann Gautier #define _PKA_VERR_MINREV_MASK		GENMASK_32(3, 0)
83b0fbc02aSNicolas Toromanoff #define _PKA_VERR_MINREV_SHIFT		0U
84b0fbc02aSNicolas Toromanoff 
85b0fbc02aSNicolas Toromanoff /* RAM magic offset */
86b0fbc02aSNicolas Toromanoff #define _PKA_RAM_START			0x400U
87b0fbc02aSNicolas Toromanoff #define _PKA_RAM_SIZE			5336U
88b0fbc02aSNicolas Toromanoff 
89b0fbc02aSNicolas Toromanoff /* ECDSA verification */
90b0fbc02aSNicolas Toromanoff #define _PKA_RAM_N_LEN			0x408U /* 64 */
91b0fbc02aSNicolas Toromanoff #define _PKA_RAM_P_LEN			0x4C8U /* 64 */
92b0fbc02aSNicolas Toromanoff #define _PKA_RAM_A_SIGN			0x468U /* 64 */
93b0fbc02aSNicolas Toromanoff #define _PKA_RAM_A			0x470U /* EOS */
94b0fbc02aSNicolas Toromanoff #define _PKA_RAM_P			0x4D0U /* EOS */
95b0fbc02aSNicolas Toromanoff #define _PKA_RAM_XG			0x678U /* EOS */
96b0fbc02aSNicolas Toromanoff #define _PKA_RAM_YG			0x6D0U /* EOS */
97b0fbc02aSNicolas Toromanoff #define _PKA_RAM_XQ			0x12F8U /* EOS */
98b0fbc02aSNicolas Toromanoff #define _PKA_RAM_YQ			0x1350U /* EOS */
99b0fbc02aSNicolas Toromanoff #define _PKA_RAM_SIGN_R			0x10E0U /* EOS */
100b0fbc02aSNicolas Toromanoff #define _PKA_RAM_SIGN_S			0xC68U /* EOS */
101b0fbc02aSNicolas Toromanoff #define _PKA_RAM_HASH_Z			0x13A8U /* EOS */
102b0fbc02aSNicolas Toromanoff #define _PKA_RAM_PRIME_N		0x1088U /* EOS */
103b0fbc02aSNicolas Toromanoff #define _PKA_RAM_ECDSA_VERIFY		0x5D0U /* 64 */
104b0fbc02aSNicolas Toromanoff #define _PKA_RAM_ECDSA_VERIFY_VALID	0xD60DULL
105b0fbc02aSNicolas Toromanoff #define _PKA_RAM_ECDSA_VERIFY_INVALID	0xA3B7ULL
106b0fbc02aSNicolas Toromanoff 
107b0fbc02aSNicolas Toromanoff #define PKA_TIMEOUT_US			1000000U
108b0fbc02aSNicolas Toromanoff #define TIMEOUT_US_1MS			1000U
109b0fbc02aSNicolas Toromanoff #define PKA_RESET_DELAY			20U
110b0fbc02aSNicolas Toromanoff 
111b0fbc02aSNicolas Toromanoff struct curve_parameters {
112b0fbc02aSNicolas Toromanoff 	uint32_t a_sign;  /* 0 positive, 1 negative */
113b0fbc02aSNicolas Toromanoff 	uint8_t *a;    /* Curve coefficient |a| */
114b0fbc02aSNicolas Toromanoff 	size_t a_size;
115b0fbc02aSNicolas Toromanoff 	uint8_t *p;    /* Curve modulus value */
116b0fbc02aSNicolas Toromanoff 	uint32_t p_len;
117b0fbc02aSNicolas Toromanoff 	uint8_t *xg;   /* Curve base point G coordinate x */
118b0fbc02aSNicolas Toromanoff 	size_t xg_size;
119b0fbc02aSNicolas Toromanoff 	uint8_t *yg;   /* Curve base point G coordinate y */
120b0fbc02aSNicolas Toromanoff 	size_t yg_size;
121b0fbc02aSNicolas Toromanoff 	uint8_t *n;    /* Curve prime order n */
122b0fbc02aSNicolas Toromanoff 	uint32_t n_len;
123b0fbc02aSNicolas Toromanoff };
124b0fbc02aSNicolas Toromanoff 
125b0fbc02aSNicolas Toromanoff static const struct curve_parameters curve_def[] = {
126b0fbc02aSNicolas Toromanoff #if PKA_USE_NIST_P256
127b0fbc02aSNicolas Toromanoff 	[PKA_NIST_P256] = {
128b0fbc02aSNicolas Toromanoff 		.p_len = 256U,
129b0fbc02aSNicolas Toromanoff 		.n_len = 256U,
130b0fbc02aSNicolas Toromanoff 		.p  = (uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
131b0fbc02aSNicolas Toromanoff 				  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132b0fbc02aSNicolas Toromanoff 				  0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
133b0fbc02aSNicolas Toromanoff 				  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
134b0fbc02aSNicolas Toromanoff 		.n  = (uint8_t[]){0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
135b0fbc02aSNicolas Toromanoff 				  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
136b0fbc02aSNicolas Toromanoff 				  0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
137b0fbc02aSNicolas Toromanoff 				  0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51},
138b0fbc02aSNicolas Toromanoff 		.a_sign = 1U,
139b0fbc02aSNicolas Toromanoff 		.a = (uint8_t[]){0x03},
140b0fbc02aSNicolas Toromanoff 		.a_size = 1U,
141b0fbc02aSNicolas Toromanoff 		.xg = (uint8_t[]){0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47,
142b0fbc02aSNicolas Toromanoff 				  0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2,
143b0fbc02aSNicolas Toromanoff 				  0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
144b0fbc02aSNicolas Toromanoff 				  0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96},
145b0fbc02aSNicolas Toromanoff 		.xg_size = 32U,
146b0fbc02aSNicolas Toromanoff 		.yg = (uint8_t[]){0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B,
147b0fbc02aSNicolas Toromanoff 				  0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16,
148b0fbc02aSNicolas Toromanoff 				  0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
149b0fbc02aSNicolas Toromanoff 				  0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5},
150b0fbc02aSNicolas Toromanoff 		.yg_size = 32U,
151b0fbc02aSNicolas Toromanoff 	},
152b0fbc02aSNicolas Toromanoff #endif
153b0fbc02aSNicolas Toromanoff #if PKA_USE_BRAINPOOL_P256R1
154b0fbc02aSNicolas Toromanoff 	[PKA_BRAINPOOL_P256R1] = {
155b0fbc02aSNicolas Toromanoff 		.p_len = 256,
156b0fbc02aSNicolas Toromanoff 		.n_len = 256,
157b0fbc02aSNicolas Toromanoff 		.p  = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC,
158b0fbc02aSNicolas Toromanoff 				  0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72,
159b0fbc02aSNicolas Toromanoff 				  0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28,
160b0fbc02aSNicolas Toromanoff 				  0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x77},
161b0fbc02aSNicolas Toromanoff 		.n  = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC,
162b0fbc02aSNicolas Toromanoff 				  0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x71,
163b0fbc02aSNicolas Toromanoff 				  0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7,
164b0fbc02aSNicolas Toromanoff 				  0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7},
165b0fbc02aSNicolas Toromanoff 		.a  = (uint8_t[]){0x7D, 0x5A, 0x09, 0x75, 0xFC, 0x2C, 0x30, 0x57,
166b0fbc02aSNicolas Toromanoff 				  0xEE, 0xF6, 0x75, 0x30, 0x41, 0x7A, 0xFF, 0xE7,
167b0fbc02aSNicolas Toromanoff 				  0xFB, 0x80, 0x55, 0xC1, 0x26, 0xDC, 0x5C, 0x6C,
168b0fbc02aSNicolas Toromanoff 				  0xE9, 0x4A, 0x4B, 0x44, 0xF3, 0x30, 0xB5, 0xD9},
169b0fbc02aSNicolas Toromanoff 		.a_size = 32U,
170b0fbc02aSNicolas Toromanoff 		.xg = (uint8_t[]){0x8B, 0xD2, 0xAE, 0xB9, 0xCB, 0x7E, 0x57, 0xCB,
171b0fbc02aSNicolas Toromanoff 				  0x2C, 0x4B, 0x48, 0x2F, 0xFC, 0x81, 0xB7, 0xAF,
172b0fbc02aSNicolas Toromanoff 				  0xB9, 0xDE, 0x27, 0xE1, 0xE3, 0xBD, 0x23, 0xC2,
173b0fbc02aSNicolas Toromanoff 				  0x3A, 0x44, 0x53, 0xBD, 0x9A, 0xCE, 0x32, 0x62},
174b0fbc02aSNicolas Toromanoff 		.xg_size = 32U,
175b0fbc02aSNicolas Toromanoff 		.yg = (uint8_t[]){0x54, 0x7E, 0xF8, 0x35, 0xC3, 0xDA, 0xC4, 0xFD,
176b0fbc02aSNicolas Toromanoff 				  0x97, 0xF8, 0x46, 0x1A, 0x14, 0x61, 0x1D, 0xC9,
177b0fbc02aSNicolas Toromanoff 				  0xC2, 0x77, 0x45, 0x13, 0x2D, 0xED, 0x8E, 0x54,
178b0fbc02aSNicolas Toromanoff 				  0x5C, 0x1D, 0x54, 0xC7, 0x2F, 0x04, 0x69, 0x97},
179b0fbc02aSNicolas Toromanoff 		.yg_size = 32U,
180b0fbc02aSNicolas Toromanoff 	},
181b0fbc02aSNicolas Toromanoff #endif
182b0fbc02aSNicolas Toromanoff #if PKA_USE_BRAINPOOL_P256T1
183b0fbc02aSNicolas Toromanoff 	[PKA_BRAINPOOL_P256T1] = {
184b0fbc02aSNicolas Toromanoff 		.p_len = 256,
185b0fbc02aSNicolas Toromanoff 		.n_len = 256,
186b0fbc02aSNicolas Toromanoff 		.p  = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC,
187b0fbc02aSNicolas Toromanoff 				  0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72,
188b0fbc02aSNicolas Toromanoff 				  0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28,
189b0fbc02aSNicolas Toromanoff 				  0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x77},
190b0fbc02aSNicolas Toromanoff 		.n  = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC,
191b0fbc02aSNicolas Toromanoff 				  0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x71,
192b0fbc02aSNicolas Toromanoff 				  0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7,
193b0fbc02aSNicolas Toromanoff 				  0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7},
194b0fbc02aSNicolas Toromanoff 		.a  = (uint8_t[]){0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC,
195b0fbc02aSNicolas Toromanoff 				  0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72,
196b0fbc02aSNicolas Toromanoff 				  0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28,
197b0fbc02aSNicolas Toromanoff 				  0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x74},
198b0fbc02aSNicolas Toromanoff 		.a_size = 32U,
199b0fbc02aSNicolas Toromanoff 		.xg = (uint8_t[]){0xA3, 0xE8, 0xEB, 0x3C, 0xC1, 0xCF, 0xE7, 0xB7,
200b0fbc02aSNicolas Toromanoff 				  0x73, 0x22, 0x13, 0xB2, 0x3A, 0x65, 0x61, 0x49,
201b0fbc02aSNicolas Toromanoff 				  0xAF, 0xA1, 0x42, 0xC4, 0x7A, 0xAF, 0xBC, 0x2B,
202b0fbc02aSNicolas Toromanoff 				  0x79, 0xA1, 0x91, 0x56, 0x2E, 0x13, 0x05, 0xF4},
203b0fbc02aSNicolas Toromanoff 		.xg_size = 32U,
204b0fbc02aSNicolas Toromanoff 		.yg = (uint8_t[]){0x2D, 0x99, 0x6C, 0x82, 0x34, 0x39, 0xC5, 0x6D,
205b0fbc02aSNicolas Toromanoff 				  0x7F, 0x7B, 0x22, 0xE1, 0x46, 0x44, 0x41, 0x7E,
206b0fbc02aSNicolas Toromanoff 				  0x69, 0xBC, 0xB6, 0xDE, 0x39, 0xD0, 0x27, 0x00,
207b0fbc02aSNicolas Toromanoff 				  0x1D, 0xAB, 0xE8, 0xF3, 0x5B, 0x25, 0xC9, 0xBE},
208b0fbc02aSNicolas Toromanoff 		.yg_size = 32U,
209b0fbc02aSNicolas Toromanoff 	},
210b0fbc02aSNicolas Toromanoff #endif
211b0fbc02aSNicolas Toromanoff #if PKA_USE_NIST_P521
212b0fbc02aSNicolas Toromanoff 	[PKA_NIST_P521] = {
213b0fbc02aSNicolas Toromanoff 		.p_len = 521,
214b0fbc02aSNicolas Toromanoff 		.n_len = 521,
215b0fbc02aSNicolas Toromanoff 		.p  = (uint8_t[]){                                    0x01, 0xff,
216b0fbc02aSNicolas Toromanoff 				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
217b0fbc02aSNicolas Toromanoff 				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
218b0fbc02aSNicolas Toromanoff 				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
219b0fbc02aSNicolas Toromanoff 				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
220b0fbc02aSNicolas Toromanoff 				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
221b0fbc02aSNicolas Toromanoff 				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
222b0fbc02aSNicolas Toromanoff 				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
223b0fbc02aSNicolas Toromanoff 				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
224b0fbc02aSNicolas Toromanoff 		.n  = (uint8_t[]){                                    0x01, 0xff,
225b0fbc02aSNicolas Toromanoff 				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
226b0fbc02aSNicolas Toromanoff 				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
227b0fbc02aSNicolas Toromanoff 				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
228b0fbc02aSNicolas Toromanoff 				  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa,
229b0fbc02aSNicolas Toromanoff 				  0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b,
230b0fbc02aSNicolas Toromanoff 				  0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0,
231b0fbc02aSNicolas Toromanoff 				  0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae,
232b0fbc02aSNicolas Toromanoff 				  0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09},
233b0fbc02aSNicolas Toromanoff 		.a_sign = 1,
234b0fbc02aSNicolas Toromanoff 		.a  = (uint8_t[]){0x03},
235b0fbc02aSNicolas Toromanoff 		.a_size = 1U,
236b0fbc02aSNicolas Toromanoff 		.xg = (uint8_t[]){                                          0xc6,
237b0fbc02aSNicolas Toromanoff 				  0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd,
238b0fbc02aSNicolas Toromanoff 				  0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42,
239b0fbc02aSNicolas Toromanoff 				  0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f, 0xb5, 0x21,
240b0fbc02aSNicolas Toromanoff 				  0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, 0x3d, 0xba,
241b0fbc02aSNicolas Toromanoff 				  0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28,
242b0fbc02aSNicolas Toromanoff 				  0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff, 0xa8, 0xde,
243b0fbc02aSNicolas Toromanoff 				  0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b,
244b0fbc02aSNicolas Toromanoff 				  0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66},
245b0fbc02aSNicolas Toromanoff 		.xg_size = 65U,
246b0fbc02aSNicolas Toromanoff 		.yg = (uint8_t[]){                                    0x01, 0x18,
247b0fbc02aSNicolas Toromanoff 				  0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04,
248b0fbc02aSNicolas Toromanoff 				  0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9,
249b0fbc02aSNicolas Toromanoff 				  0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, 0x44, 0x68,
250b0fbc02aSNicolas Toromanoff 				  0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c,
251b0fbc02aSNicolas Toromanoff 				  0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40,
252b0fbc02aSNicolas Toromanoff 				  0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, 0x07, 0x61,
253b0fbc02aSNicolas Toromanoff 				  0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40,
254b0fbc02aSNicolas Toromanoff 				  0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50},
255b0fbc02aSNicolas Toromanoff 		.yg_size = 66U,
256b0fbc02aSNicolas Toromanoff 	},
257b0fbc02aSNicolas Toromanoff #endif
258b0fbc02aSNicolas Toromanoff };
259b0fbc02aSNicolas Toromanoff 
260b0fbc02aSNicolas Toromanoff static struct stm32_pka_platdata pka_pdata;
261b0fbc02aSNicolas Toromanoff 
262b0fbc02aSNicolas Toromanoff static int stm32_pka_parse_fdt(void)
263b0fbc02aSNicolas Toromanoff {
264b0fbc02aSNicolas Toromanoff 	int node;
265b0fbc02aSNicolas Toromanoff 	struct dt_node_info info;
266b0fbc02aSNicolas Toromanoff 	void *fdt;
267b0fbc02aSNicolas Toromanoff 
268b0fbc02aSNicolas Toromanoff 	if (fdt_get_address(&fdt) == 0) {
269b0fbc02aSNicolas Toromanoff 		return -FDT_ERR_NOTFOUND;
270b0fbc02aSNicolas Toromanoff 	}
271b0fbc02aSNicolas Toromanoff 
272b0fbc02aSNicolas Toromanoff 	node = dt_get_node(&info, -1, DT_PKA_COMPAT);
273b0fbc02aSNicolas Toromanoff 	if (node < 0) {
274b0fbc02aSNicolas Toromanoff 		ERROR("No PKA entry in DT\n");
275b0fbc02aSNicolas Toromanoff 		return -FDT_ERR_NOTFOUND;
276b0fbc02aSNicolas Toromanoff 	}
277b0fbc02aSNicolas Toromanoff 
278b0fbc02aSNicolas Toromanoff 	if (info.status == DT_DISABLED) {
279b0fbc02aSNicolas Toromanoff 		return -FDT_ERR_NOTFOUND;
280b0fbc02aSNicolas Toromanoff 	}
281b0fbc02aSNicolas Toromanoff 
282b0fbc02aSNicolas Toromanoff 	if ((info.base == 0) || (info.clock < 0) || (info.reset < 0)) {
283b0fbc02aSNicolas Toromanoff 		return -FDT_ERR_BADVALUE;
284b0fbc02aSNicolas Toromanoff 	}
285b0fbc02aSNicolas Toromanoff 
286b0fbc02aSNicolas Toromanoff 	pka_pdata.base = (uintptr_t)info.base;
287b0fbc02aSNicolas Toromanoff 	pka_pdata.clock_id = (unsigned long)info.clock;
288b0fbc02aSNicolas Toromanoff 	pka_pdata.reset_id = (unsigned int)info.reset;
289b0fbc02aSNicolas Toromanoff 
290b0fbc02aSNicolas Toromanoff 	return 0;
291b0fbc02aSNicolas Toromanoff }
292b0fbc02aSNicolas Toromanoff 
293b0fbc02aSNicolas Toromanoff static int pka_wait_bit(uintptr_t base, uint32_t bit)
294b0fbc02aSNicolas Toromanoff {
295b0fbc02aSNicolas Toromanoff 	uint64_t timeout = timeout_init_us(PKA_TIMEOUT_US);
296b0fbc02aSNicolas Toromanoff 
297b0fbc02aSNicolas Toromanoff 	while ((mmio_read_32(base + _PKA_SR) & bit) != bit) {
298b0fbc02aSNicolas Toromanoff 		if (timeout_elapsed(timeout)) {
299b0fbc02aSNicolas Toromanoff 			WARN("timeout waiting %x\n", bit);
300b0fbc02aSNicolas Toromanoff 			return -ETIMEDOUT;
301b0fbc02aSNicolas Toromanoff 		}
302b0fbc02aSNicolas Toromanoff 	}
303b0fbc02aSNicolas Toromanoff 
304b0fbc02aSNicolas Toromanoff 	return 0;
305b0fbc02aSNicolas Toromanoff 
306b0fbc02aSNicolas Toromanoff }
307b0fbc02aSNicolas Toromanoff 
308b0fbc02aSNicolas Toromanoff static void pka_disable(uintptr_t base)
309b0fbc02aSNicolas Toromanoff {
310b0fbc02aSNicolas Toromanoff 	mmio_clrbits_32(base + _PKA_CR, _PKA_CR_EN);
311b0fbc02aSNicolas Toromanoff }
312b0fbc02aSNicolas Toromanoff 
313b0fbc02aSNicolas Toromanoff static int pka_enable(uintptr_t base, uint32_t mode)
314b0fbc02aSNicolas Toromanoff {
315b0fbc02aSNicolas Toromanoff 	/* Set mode and disable interrupts */
316b0fbc02aSNicolas Toromanoff 	mmio_clrsetbits_32(base + _PKA_CR, _PKA_IT_MASK | _PKA_CR_MODE_MASK,
317b0fbc02aSNicolas Toromanoff 			   _PKA_CR_MODE_MASK & (mode << _PKA_CR_MODE_SHIFT));
318b0fbc02aSNicolas Toromanoff 
319b0fbc02aSNicolas Toromanoff 	mmio_setbits_32(base + _PKA_CR, _PKA_CR_EN);
320b0fbc02aSNicolas Toromanoff 
321b0fbc02aSNicolas Toromanoff 	return pka_wait_bit(base, _PKA_SR_INITOK);
322b0fbc02aSNicolas Toromanoff }
323b0fbc02aSNicolas Toromanoff 
324b0fbc02aSNicolas Toromanoff /*
325b0fbc02aSNicolas Toromanoff  * Data are already loaded in PKA internal RAM
326b0fbc02aSNicolas Toromanoff  * MODE is set
327b0fbc02aSNicolas Toromanoff  * We start process, and wait for its end.
328b0fbc02aSNicolas Toromanoff  */
329b0fbc02aSNicolas Toromanoff static int stm32_pka_process(uintptr_t base)
330b0fbc02aSNicolas Toromanoff {
331b0fbc02aSNicolas Toromanoff 	mmio_setbits_32(base + _PKA_CR, _PKA_CR_START);
332b0fbc02aSNicolas Toromanoff 
333b0fbc02aSNicolas Toromanoff 	return pka_wait_bit(base, _PKA_IT_PROCEND);
334b0fbc02aSNicolas Toromanoff }
335b0fbc02aSNicolas Toromanoff 
336b0fbc02aSNicolas Toromanoff /**
337b0fbc02aSNicolas Toromanoff  * @brief Write ECC operand to PKA RAM.
338b0fbc02aSNicolas Toromanoff  * @note  PKA expect to write u64 word, each u64 are: the least significant bit is
339b0fbc02aSNicolas Toromanoff  *        bit 0; the most significant bit is bit 63.
340b0fbc02aSNicolas Toromanoff  *        We write eo_nbw (ECC operand Size) u64, value that depends of the chosen
341b0fbc02aSNicolas Toromanoff  *        prime modulus length in bits.
342b0fbc02aSNicolas Toromanoff  *        First less signicant u64 is written to low address
343b0fbc02aSNicolas Toromanoff  *        Most significant u64 to higher address.
344b0fbc02aSNicolas Toromanoff  *        And at last address we write a u64(0x0)
345b0fbc02aSNicolas Toromanoff  * @note  This function doesn't only manage endianness (as bswap64 do), but also
346b0fbc02aSNicolas Toromanoff  *        complete most significant incomplete u64 with 0 (if data is not a u64
347b0fbc02aSNicolas Toromanoff  *        multiple), and fill u64 last address with 0.
348b0fbc02aSNicolas Toromanoff  * @param addr: PKA_RAM address to write the buffer 'data'
349b0fbc02aSNicolas Toromanoff  * @param data: is a BYTE list with most significant bytes first
350b0fbc02aSNicolas Toromanoff  * @param data_size: nb of byte in data
351b0fbc02aSNicolas Toromanoff  * @param eo_nbw: is ECC Operand size in 64bits word (including the extra 0)
352b0fbc02aSNicolas Toromanoff  *                (note it depends of the prime modulus length, not the data size)
353b0fbc02aSNicolas Toromanoff  * @retval 0 if OK.
354b0fbc02aSNicolas Toromanoff  *         -EINVAL if data_size and eo_nbw are inconsistent, ie data doesn't
355b0fbc02aSNicolas Toromanoff  *         fit in defined eo_nbw, or eo_nbw bigger than hardware limit.
356b0fbc02aSNicolas Toromanoff  */
357b0fbc02aSNicolas Toromanoff static int write_eo_data(uintptr_t addr, uint8_t *data, unsigned int data_size,
358b0fbc02aSNicolas Toromanoff 			 unsigned int eo_nbw)
359b0fbc02aSNicolas Toromanoff {
360b0fbc02aSNicolas Toromanoff 	uint32_t word_index;
361b0fbc02aSNicolas Toromanoff 	int data_index;
362b0fbc02aSNicolas Toromanoff 
363b0fbc02aSNicolas Toromanoff 	if ((eo_nbw < OP_NBW_FROM_SIZE(data_size)) || (eo_nbw > MAX_EO_NBW)) {
364b0fbc02aSNicolas Toromanoff 		return -EINVAL;
365b0fbc02aSNicolas Toromanoff 	}
366b0fbc02aSNicolas Toromanoff 
367b0fbc02aSNicolas Toromanoff 	/* Fill value */
368b0fbc02aSNicolas Toromanoff 	data_index = (int)data_size - 1;
369b0fbc02aSNicolas Toromanoff 	for (word_index = 0U; word_index < eo_nbw; word_index++) {
370b0fbc02aSNicolas Toromanoff 		uint64_t tmp = 0ULL;
371b0fbc02aSNicolas Toromanoff 		unsigned int i = 0U;  /* index in the tmp U64 word */
372b0fbc02aSNicolas Toromanoff 
373b0fbc02aSNicolas Toromanoff 		/* Stop if end of tmp or end of data */
374b0fbc02aSNicolas Toromanoff 		while ((i < sizeof(tmp)) && (data_index >= 0)) {
375b0fbc02aSNicolas Toromanoff 			tmp |= (uint64_t)(data[data_index]) << (UINT8_LEN * i);
376b0fbc02aSNicolas Toromanoff 			i++; /* Move byte index in current (u64)tmp */
377b0fbc02aSNicolas Toromanoff 			data_index--; /* Move to just next most significat byte */
378b0fbc02aSNicolas Toromanoff 		}
379b0fbc02aSNicolas Toromanoff 
380b0fbc02aSNicolas Toromanoff 		mmio_write_64(addr + word_index * sizeof(tmp), tmp);
381b0fbc02aSNicolas Toromanoff 	}
382b0fbc02aSNicolas Toromanoff 
383b0fbc02aSNicolas Toromanoff 	return 0;
384b0fbc02aSNicolas Toromanoff }
385b0fbc02aSNicolas Toromanoff 
386b0fbc02aSNicolas Toromanoff static unsigned int get_ecc_op_nbword(enum stm32_pka_ecdsa_curve_id cid)
387b0fbc02aSNicolas Toromanoff {
388b0fbc02aSNicolas Toromanoff 	if (cid >= ARRAY_SIZE(curve_def)) {
389b0fbc02aSNicolas Toromanoff 		ERROR("CID %u is out of boundaries\n", cid);
390b0fbc02aSNicolas Toromanoff 		panic();
391b0fbc02aSNicolas Toromanoff 	}
392b0fbc02aSNicolas Toromanoff 
393b0fbc02aSNicolas Toromanoff 	return OP_NBW_FROM_LEN(curve_def[cid].n_len);
394b0fbc02aSNicolas Toromanoff }
395b0fbc02aSNicolas Toromanoff 
396b0fbc02aSNicolas Toromanoff static int stm32_pka_ecdsa_verif_configure_curve(uintptr_t base, enum stm32_pka_ecdsa_curve_id cid)
397b0fbc02aSNicolas Toromanoff {
398b0fbc02aSNicolas Toromanoff 	int ret;
399b0fbc02aSNicolas Toromanoff 	unsigned int eo_nbw = get_ecc_op_nbword(cid);
400b0fbc02aSNicolas Toromanoff 
401b0fbc02aSNicolas Toromanoff 	mmio_write_64(base + _PKA_RAM_N_LEN, curve_def[cid].n_len);
402b0fbc02aSNicolas Toromanoff 	mmio_write_64(base + _PKA_RAM_P_LEN, curve_def[cid].p_len);
403b0fbc02aSNicolas Toromanoff 	mmio_write_64(base + _PKA_RAM_A_SIGN, curve_def[cid].a_sign);
404b0fbc02aSNicolas Toromanoff 
405b0fbc02aSNicolas Toromanoff 	ret = write_eo_data(base + _PKA_RAM_A, curve_def[cid].a, curve_def[cid].a_size, eo_nbw);
406b0fbc02aSNicolas Toromanoff 	if (ret < 0) {
407b0fbc02aSNicolas Toromanoff 		return ret;
408b0fbc02aSNicolas Toromanoff 	}
409b0fbc02aSNicolas Toromanoff 
410b0fbc02aSNicolas Toromanoff 	ret = write_eo_data(base + _PKA_RAM_PRIME_N,
411b0fbc02aSNicolas Toromanoff 			    curve_def[cid].n, div_round_up(curve_def[cid].n_len, UINT8_LEN),
412b0fbc02aSNicolas Toromanoff 			    eo_nbw);
413b0fbc02aSNicolas Toromanoff 	if (ret < 0) {
414b0fbc02aSNicolas Toromanoff 		return ret;
415b0fbc02aSNicolas Toromanoff 	}
416b0fbc02aSNicolas Toromanoff 
417b0fbc02aSNicolas Toromanoff 	ret = write_eo_data(base + _PKA_RAM_P, curve_def[cid].p,
418b0fbc02aSNicolas Toromanoff 			    div_round_up(curve_def[cid].p_len, UINT8_LEN), eo_nbw);
419b0fbc02aSNicolas Toromanoff 	if (ret < 0) {
420b0fbc02aSNicolas Toromanoff 		return ret;
421b0fbc02aSNicolas Toromanoff 	}
422b0fbc02aSNicolas Toromanoff 
423b0fbc02aSNicolas Toromanoff 	ret = write_eo_data(base + _PKA_RAM_XG, curve_def[cid].xg, curve_def[cid].xg_size, eo_nbw);
424b0fbc02aSNicolas Toromanoff 	if (ret < 0) {
425b0fbc02aSNicolas Toromanoff 		return ret;
426b0fbc02aSNicolas Toromanoff 	}
427b0fbc02aSNicolas Toromanoff 
428b0fbc02aSNicolas Toromanoff 	ret = write_eo_data(base + _PKA_RAM_YG, curve_def[cid].yg, curve_def[cid].yg_size, eo_nbw);
429b0fbc02aSNicolas Toromanoff 	if (ret < 0) {
430b0fbc02aSNicolas Toromanoff 		return ret;
431b0fbc02aSNicolas Toromanoff 	}
432b0fbc02aSNicolas Toromanoff 
433b0fbc02aSNicolas Toromanoff 	return 0;
434b0fbc02aSNicolas Toromanoff }
435b0fbc02aSNicolas Toromanoff 
436b0fbc02aSNicolas Toromanoff static int stm32_pka_ecdsa_verif_check_return(uintptr_t base)
437b0fbc02aSNicolas Toromanoff {
438b0fbc02aSNicolas Toromanoff 	uint64_t value;
439b0fbc02aSNicolas Toromanoff 	uint32_t sr;
440b0fbc02aSNicolas Toromanoff 
441b0fbc02aSNicolas Toromanoff 	sr = mmio_read_32(base + _PKA_SR);
442b0fbc02aSNicolas Toromanoff 	if ((sr & (_PKA_IT_OPERR | _PKA_IT_ADDRERR | _PKA_IT_RAMERR)) != 0) {
443b0fbc02aSNicolas Toromanoff 		WARN("Detected error(s): %s%s%s\n",
444b0fbc02aSNicolas Toromanoff 		     (sr & _PKA_IT_OPERR) ? "Operation " : "",
445b0fbc02aSNicolas Toromanoff 		     (sr & _PKA_IT_ADDRERR) ? "Address " : "",
446b0fbc02aSNicolas Toromanoff 		     (sr & _PKA_IT_RAMERR) ? "RAM" : "");
447b0fbc02aSNicolas Toromanoff 		return -EINVAL;
448b0fbc02aSNicolas Toromanoff 	}
449b0fbc02aSNicolas Toromanoff 
450b0fbc02aSNicolas Toromanoff 	value = mmio_read_64(base + _PKA_RAM_ECDSA_VERIFY);
451b0fbc02aSNicolas Toromanoff 	if (value == _PKA_RAM_ECDSA_VERIFY_VALID) {
452b0fbc02aSNicolas Toromanoff 		return 0;
453b0fbc02aSNicolas Toromanoff 	}
454b0fbc02aSNicolas Toromanoff 
455b0fbc02aSNicolas Toromanoff 	if (value == _PKA_RAM_ECDSA_VERIFY_INVALID) {
456b0fbc02aSNicolas Toromanoff 		return -EAUTH;
457b0fbc02aSNicolas Toromanoff 	}
458b0fbc02aSNicolas Toromanoff 
459b0fbc02aSNicolas Toromanoff 	return -EINVAL;
460b0fbc02aSNicolas Toromanoff }
461b0fbc02aSNicolas Toromanoff 
462b0fbc02aSNicolas Toromanoff /**
463b0fbc02aSNicolas Toromanoff  * @brief Check if BigInt stored in data is 0
464b0fbc02aSNicolas Toromanoff  *
465b0fbc02aSNicolas Toromanoff  * @param data: a BYTE array with most significant bytes first
466b0fbc02aSNicolas Toromanoff  * @param size: data size
467b0fbc02aSNicolas Toromanoff  *
468b0fbc02aSNicolas Toromanoff  * @retval: true: if data represents a 0 value (ie all bytes == 0)
469b0fbc02aSNicolas Toromanoff  *          false: if data represents a non-zero value.
470b0fbc02aSNicolas Toromanoff  */
471b0fbc02aSNicolas Toromanoff static bool is_zero(uint8_t *data, unsigned int size)
472b0fbc02aSNicolas Toromanoff {
473b0fbc02aSNicolas Toromanoff 	unsigned int i;
474b0fbc02aSNicolas Toromanoff 
475b0fbc02aSNicolas Toromanoff 	for (i = 0U; i < size; i++) {
476b0fbc02aSNicolas Toromanoff 		if (data[i] != 0U) {
477b0fbc02aSNicolas Toromanoff 			return false;
478b0fbc02aSNicolas Toromanoff 		}
479b0fbc02aSNicolas Toromanoff 	}
480b0fbc02aSNicolas Toromanoff 
481b0fbc02aSNicolas Toromanoff 	return true;
482b0fbc02aSNicolas Toromanoff }
483b0fbc02aSNicolas Toromanoff 
484b0fbc02aSNicolas Toromanoff /**
485b0fbc02aSNicolas Toromanoff  * @brief Compare two BigInt:
486b0fbc02aSNicolas Toromanoff  * @param xdata_a: a BYTE array with most significant bytes first
487b0fbc02aSNicolas Toromanoff  * @param size_a: nb of Byte of 'a'
488b0fbc02aSNicolas Toromanoff  * @param data_b: a BYTE array with most significant bytes first
489b0fbc02aSNicolas Toromanoff  * @param size_b: nb of Byte of 'b'
490b0fbc02aSNicolas Toromanoff  *
491b0fbc02aSNicolas Toromanoff  * @retval: true if data_a < data_b
492b0fbc02aSNicolas Toromanoff  *          false if data_a >= data_b
493b0fbc02aSNicolas Toromanoff  */
494b0fbc02aSNicolas Toromanoff static bool is_smaller(uint8_t *data_a, unsigned int size_a,
495b0fbc02aSNicolas Toromanoff 		       uint8_t *data_b, unsigned int size_b)
496b0fbc02aSNicolas Toromanoff {
497b0fbc02aSNicolas Toromanoff 	unsigned int i;
498b0fbc02aSNicolas Toromanoff 
499b0fbc02aSNicolas Toromanoff 	i = MAX(size_a, size_b) + 1U;
500b0fbc02aSNicolas Toromanoff 	do {
501b0fbc02aSNicolas Toromanoff 		uint8_t a, b;
502b0fbc02aSNicolas Toromanoff 
503b0fbc02aSNicolas Toromanoff 		i--;
504b0fbc02aSNicolas Toromanoff 		if (size_a < i) {
505b0fbc02aSNicolas Toromanoff 			a = 0U;
506b0fbc02aSNicolas Toromanoff 		} else {
507b0fbc02aSNicolas Toromanoff 			a = data_a[size_a - i];
508b0fbc02aSNicolas Toromanoff 		}
509b0fbc02aSNicolas Toromanoff 
510b0fbc02aSNicolas Toromanoff 		if (size_b < i) {
511b0fbc02aSNicolas Toromanoff 			b = 0U;
512b0fbc02aSNicolas Toromanoff 		} else {
513b0fbc02aSNicolas Toromanoff 			b = data_b[size_b - i];
514b0fbc02aSNicolas Toromanoff 		}
515b0fbc02aSNicolas Toromanoff 
516b0fbc02aSNicolas Toromanoff 		if (a < b) {
517b0fbc02aSNicolas Toromanoff 			return true;
518b0fbc02aSNicolas Toromanoff 		}
519b0fbc02aSNicolas Toromanoff 
520b0fbc02aSNicolas Toromanoff 		if (a > b) {
521b0fbc02aSNicolas Toromanoff 			return false;
522b0fbc02aSNicolas Toromanoff 		}
523b0fbc02aSNicolas Toromanoff 	} while (i != 0U);
524b0fbc02aSNicolas Toromanoff 
525b0fbc02aSNicolas Toromanoff 	return false;
526b0fbc02aSNicolas Toromanoff }
527b0fbc02aSNicolas Toromanoff 
528b0fbc02aSNicolas Toromanoff static int stm32_pka_ecdsa_check_param(void *sig_r_ptr, unsigned int sig_r_size,
529b0fbc02aSNicolas Toromanoff 				       void *sig_s_ptr, unsigned int sig_s_size,
530b0fbc02aSNicolas Toromanoff 				       void *pk_x_ptr, unsigned int pk_x_size,
531b0fbc02aSNicolas Toromanoff 				       void *pk_y_ptr, unsigned int pk_y_size,
532b0fbc02aSNicolas Toromanoff 				       enum stm32_pka_ecdsa_curve_id cid)
533b0fbc02aSNicolas Toromanoff {
534b0fbc02aSNicolas Toromanoff 	/* Public Key check */
535b0fbc02aSNicolas Toromanoff 	/* Check Xq < p */
536b0fbc02aSNicolas Toromanoff 	if (!is_smaller(pk_x_ptr, pk_x_size,
537b0fbc02aSNicolas Toromanoff 			curve_def[cid].p, div_round_up(curve_def[cid].p_len, UINT8_LEN))) {
538b0fbc02aSNicolas Toromanoff 		WARN("%s Xq < p inval\n", __func__);
539b0fbc02aSNicolas Toromanoff 		return -EINVAL;
540b0fbc02aSNicolas Toromanoff 	}
541b0fbc02aSNicolas Toromanoff 
542b0fbc02aSNicolas Toromanoff 	/* Check Yq < p */
543b0fbc02aSNicolas Toromanoff 	if (!is_smaller(pk_y_ptr, pk_y_size,
544b0fbc02aSNicolas Toromanoff 			curve_def[cid].p, div_round_up(curve_def[cid].p_len, UINT8_LEN))) {
545b0fbc02aSNicolas Toromanoff 		WARN("%s Yq < p inval\n", __func__);
546b0fbc02aSNicolas Toromanoff 		return -EINVAL;
547b0fbc02aSNicolas Toromanoff 	}
548b0fbc02aSNicolas Toromanoff 
549b0fbc02aSNicolas Toromanoff 	/* Signature check */
550b0fbc02aSNicolas Toromanoff 	/* Check 0 < r < n */
551b0fbc02aSNicolas Toromanoff 	if (!is_smaller(sig_r_ptr, sig_r_size,
552b0fbc02aSNicolas Toromanoff 			curve_def[cid].n, div_round_up(curve_def[cid].n_len, UINT8_LEN)) &&
553b0fbc02aSNicolas Toromanoff 	    !is_zero(sig_r_ptr, sig_r_size)) {
554b0fbc02aSNicolas Toromanoff 		WARN("%s 0< r < n inval\n", __func__);
555b0fbc02aSNicolas Toromanoff 		return -EINVAL;
556b0fbc02aSNicolas Toromanoff 	}
557b0fbc02aSNicolas Toromanoff 
558b0fbc02aSNicolas Toromanoff 	/* Check 0 < s < n */
559b0fbc02aSNicolas Toromanoff 	if (!is_smaller(sig_s_ptr, sig_s_size,
560b0fbc02aSNicolas Toromanoff 			curve_def[cid].n, div_round_up(curve_def[cid].n_len, UINT8_LEN)) &&
561b0fbc02aSNicolas Toromanoff 	    !is_zero(sig_s_ptr, sig_s_size)) {
562b0fbc02aSNicolas Toromanoff 		WARN("%s 0< s < n inval\n", __func__);
563b0fbc02aSNicolas Toromanoff 		return -EINVAL;
564b0fbc02aSNicolas Toromanoff 	}
565b0fbc02aSNicolas Toromanoff 
566b0fbc02aSNicolas Toromanoff 	return 0;
567b0fbc02aSNicolas Toromanoff }
568b0fbc02aSNicolas Toromanoff 
569b0fbc02aSNicolas Toromanoff /*
570b0fbc02aSNicolas Toromanoff  * @brief  Initialize the PKA driver.
571b0fbc02aSNicolas Toromanoff  * @param  None.
572b0fbc02aSNicolas Toromanoff  * @retval 0 if OK, negative value else.
573b0fbc02aSNicolas Toromanoff  */
574b0fbc02aSNicolas Toromanoff int stm32_pka_init(void)
575b0fbc02aSNicolas Toromanoff {
576b0fbc02aSNicolas Toromanoff 	int err;
577b0fbc02aSNicolas Toromanoff #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
578b0fbc02aSNicolas Toromanoff 	uint32_t ver;
579b0fbc02aSNicolas Toromanoff 	uint32_t id;
580b0fbc02aSNicolas Toromanoff #endif
581b0fbc02aSNicolas Toromanoff 
582b0fbc02aSNicolas Toromanoff 	err = stm32_pka_parse_fdt();
583b0fbc02aSNicolas Toromanoff 	if (err != 0) {
584b0fbc02aSNicolas Toromanoff 		return err;
585b0fbc02aSNicolas Toromanoff 	}
586b0fbc02aSNicolas Toromanoff 
587b0fbc02aSNicolas Toromanoff 	clk_enable(pka_pdata.clock_id);
588b0fbc02aSNicolas Toromanoff 
589b0fbc02aSNicolas Toromanoff 	if (stm32mp_reset_assert((unsigned long)pka_pdata.reset_id, TIMEOUT_US_1MS) != 0) {
590b0fbc02aSNicolas Toromanoff 		panic();
591b0fbc02aSNicolas Toromanoff 	}
592b0fbc02aSNicolas Toromanoff 
593b0fbc02aSNicolas Toromanoff 	udelay(PKA_RESET_DELAY);
594b0fbc02aSNicolas Toromanoff 	if (stm32mp_reset_deassert((unsigned long)pka_pdata.reset_id, TIMEOUT_US_1MS) != 0) {
595b0fbc02aSNicolas Toromanoff 		panic();
596b0fbc02aSNicolas Toromanoff 	}
597b0fbc02aSNicolas Toromanoff 
598b0fbc02aSNicolas Toromanoff #if LOG_LEVEL >= LOG_LEVEL_VERBOSE
599b0fbc02aSNicolas Toromanoff 	id = mmio_read_32(pka_pdata.base + _PKA_IPIDR);
600b0fbc02aSNicolas Toromanoff 	ver = mmio_read_32(pka_pdata.base + _PKA_VERR);
601b0fbc02aSNicolas Toromanoff 
602b0fbc02aSNicolas Toromanoff 	VERBOSE("STM32 PKA[%x] V%u.%u\n", id,
603b0fbc02aSNicolas Toromanoff 		(ver & _PKA_VERR_MAJREV_MASK) >> _PKA_VERR_MAJREV_SHIFT,
604b0fbc02aSNicolas Toromanoff 		(ver & _PKA_VERR_MINREV_MASK) >> _PKA_VERR_MINREV_SHIFT);
605b0fbc02aSNicolas Toromanoff #endif
606b0fbc02aSNicolas Toromanoff 	return 0;
607b0fbc02aSNicolas Toromanoff }
608b0fbc02aSNicolas Toromanoff 
609b0fbc02aSNicolas Toromanoff int stm32_pka_ecdsa_verif(void *hash, unsigned int hash_size,
610b0fbc02aSNicolas Toromanoff 			  void *sig_r_ptr, unsigned int sig_r_size,
611b0fbc02aSNicolas Toromanoff 			  void *sig_s_ptr, unsigned int sig_s_size,
612b0fbc02aSNicolas Toromanoff 			  void *pk_x_ptr, unsigned int pk_x_size,
613b0fbc02aSNicolas Toromanoff 			  void *pk_y_ptr, unsigned int pk_y_size,
614b0fbc02aSNicolas Toromanoff 			  enum stm32_pka_ecdsa_curve_id cid)
615b0fbc02aSNicolas Toromanoff {
616b0fbc02aSNicolas Toromanoff 	int ret;
617b0fbc02aSNicolas Toromanoff 	uintptr_t base = pka_pdata.base;
618b0fbc02aSNicolas Toromanoff 	unsigned int eo_nbw = get_ecc_op_nbword(cid);
619b0fbc02aSNicolas Toromanoff 
620b0fbc02aSNicolas Toromanoff 	if ((hash == NULL) || (sig_r_ptr == NULL) || (sig_s_ptr == NULL) ||
621b0fbc02aSNicolas Toromanoff 	    (pk_x_ptr == NULL) || (pk_y_ptr == NULL)) {
622b0fbc02aSNicolas Toromanoff 		INFO("%s invalid input param\n", __func__);
623b0fbc02aSNicolas Toromanoff 		return -EINVAL;
624b0fbc02aSNicolas Toromanoff 	}
625b0fbc02aSNicolas Toromanoff 
626b0fbc02aSNicolas Toromanoff 	ret = stm32_pka_ecdsa_check_param(sig_r_ptr, sig_r_size,
627b0fbc02aSNicolas Toromanoff 					  sig_s_ptr, sig_s_size,
628b0fbc02aSNicolas Toromanoff 					  pk_x_ptr, pk_x_size,
629b0fbc02aSNicolas Toromanoff 					  pk_y_ptr, pk_y_size,
630b0fbc02aSNicolas Toromanoff 					  cid);
631b0fbc02aSNicolas Toromanoff 	if (ret < 0) {
632b0fbc02aSNicolas Toromanoff 		INFO("%s check param error %d\n", __func__, ret);
633b0fbc02aSNicolas Toromanoff 		goto out;
634b0fbc02aSNicolas Toromanoff 	}
635b0fbc02aSNicolas Toromanoff 
636b0fbc02aSNicolas Toromanoff 	if ((mmio_read_32(base + _PKA_SR) & _PKA_SR_BUSY) == _PKA_SR_BUSY) {
637b0fbc02aSNicolas Toromanoff 		INFO("%s busy\n", __func__);
638b0fbc02aSNicolas Toromanoff 		ret = -EBUSY;
639b0fbc02aSNicolas Toromanoff 		goto out;
640b0fbc02aSNicolas Toromanoff 	}
641b0fbc02aSNicolas Toromanoff 
642b0fbc02aSNicolas Toromanoff 	/* Fill PKA RAM */
643b0fbc02aSNicolas Toromanoff 	/* With curve id values */
644b0fbc02aSNicolas Toromanoff 	ret = stm32_pka_ecdsa_verif_configure_curve(base, cid);
645b0fbc02aSNicolas Toromanoff 	if (ret < 0) {
646b0fbc02aSNicolas Toromanoff 		goto out;
647b0fbc02aSNicolas Toromanoff 	}
648b0fbc02aSNicolas Toromanoff 
649b0fbc02aSNicolas Toromanoff 	/* With pubkey */
650b0fbc02aSNicolas Toromanoff 	ret = write_eo_data(base + _PKA_RAM_XQ, pk_x_ptr, pk_x_size, eo_nbw);
651b0fbc02aSNicolas Toromanoff 	if (ret < 0) {
652b0fbc02aSNicolas Toromanoff 		goto out;
653b0fbc02aSNicolas Toromanoff 	}
654b0fbc02aSNicolas Toromanoff 
655b0fbc02aSNicolas Toromanoff 	ret = write_eo_data(base + _PKA_RAM_YQ, pk_y_ptr, pk_y_size, eo_nbw);
656b0fbc02aSNicolas Toromanoff 	if (ret < 0) {
657b0fbc02aSNicolas Toromanoff 		goto out;
658b0fbc02aSNicolas Toromanoff 	}
659b0fbc02aSNicolas Toromanoff 
660b0fbc02aSNicolas Toromanoff 	/* With hash */
661b0fbc02aSNicolas Toromanoff 	ret = write_eo_data(base + _PKA_RAM_HASH_Z, hash, hash_size, eo_nbw);
662b0fbc02aSNicolas Toromanoff 	if (ret < 0) {
663b0fbc02aSNicolas Toromanoff 		goto out;
664b0fbc02aSNicolas Toromanoff 	}
665b0fbc02aSNicolas Toromanoff 
666b0fbc02aSNicolas Toromanoff 	/* With signature */
667b0fbc02aSNicolas Toromanoff 	ret = write_eo_data(base + _PKA_RAM_SIGN_R, sig_r_ptr, sig_r_size, eo_nbw);
668b0fbc02aSNicolas Toromanoff 	if (ret < 0) {
669b0fbc02aSNicolas Toromanoff 		goto out;
670b0fbc02aSNicolas Toromanoff 	}
671b0fbc02aSNicolas Toromanoff 
672b0fbc02aSNicolas Toromanoff 	ret = write_eo_data(base + _PKA_RAM_SIGN_S, sig_s_ptr, sig_s_size, eo_nbw);
673b0fbc02aSNicolas Toromanoff 	if (ret < 0) {
674b0fbc02aSNicolas Toromanoff 		goto out;
675b0fbc02aSNicolas Toromanoff 	}
676b0fbc02aSNicolas Toromanoff 
677b0fbc02aSNicolas Toromanoff 	/* Set mode to ecdsa signature verification */
678b0fbc02aSNicolas Toromanoff 	ret = pka_enable(base, _PKA_CR_MODE_ECDSA_VERIF);
679b0fbc02aSNicolas Toromanoff 	if (ret < 0) {
680b0fbc02aSNicolas Toromanoff 		WARN("%s set mode pka error %d\n", __func__, ret);
681b0fbc02aSNicolas Toromanoff 		goto out;
682b0fbc02aSNicolas Toromanoff 	}
683b0fbc02aSNicolas Toromanoff 
684b0fbc02aSNicolas Toromanoff 	/* Start processing and wait end */
685b0fbc02aSNicolas Toromanoff 	ret = stm32_pka_process(base);
686b0fbc02aSNicolas Toromanoff 	if (ret < 0) {
687b0fbc02aSNicolas Toromanoff 		WARN("%s process error %d\n", __func__, ret);
688b0fbc02aSNicolas Toromanoff 		goto out;
689b0fbc02aSNicolas Toromanoff 	}
690b0fbc02aSNicolas Toromanoff 
691b0fbc02aSNicolas Toromanoff 	/* Check return status */
692b0fbc02aSNicolas Toromanoff 	ret = stm32_pka_ecdsa_verif_check_return(base);
693b0fbc02aSNicolas Toromanoff 
694b0fbc02aSNicolas Toromanoff 	/* Unset end proc */
695b0fbc02aSNicolas Toromanoff 	mmio_setbits_32(base + _PKA_CLRFR, _PKA_IT_PROCEND);
696b0fbc02aSNicolas Toromanoff 
697b0fbc02aSNicolas Toromanoff out:
6981b491eeaSElyes Haouas 	/* Disable PKA (will stop all pending process and reset RAM) */
699b0fbc02aSNicolas Toromanoff 	pka_disable(base);
700b0fbc02aSNicolas Toromanoff 
701b0fbc02aSNicolas Toromanoff 	return ret;
702b0fbc02aSNicolas Toromanoff }
703