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