blob: 2bbb31dc577c727cfce034dd9cc56d4bde1cd137 [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
Nicolas Toromanoffdb13fac2020-09-30 17:36:45 +0200257static int stm32_pka_parse_fdt(void)
258{
259 int node;
260 struct dt_node_info info;
261 void *fdt;
262
263 if (fdt_get_address(&fdt) == 0) {
264 return -FDT_ERR_NOTFOUND;
265 }
266
267 node = dt_get_node(&info, -1, DT_PKA_COMPAT);
268 if (node < 0) {
269 ERROR("No PKA entry in DT\n");
270 return -FDT_ERR_NOTFOUND;
271 }
272
273 if (info.status == DT_DISABLED) {
274 return -FDT_ERR_NOTFOUND;
275 }
276
277 if ((info.base == 0) || (info.clock < 0) || (info.reset < 0)) {
278 return -FDT_ERR_BADVALUE;
279 }
280
281 pka_pdata.base = (uintptr_t)info.base;
282 pka_pdata.clock_id = (unsigned long)info.clock;
283 pka_pdata.reset_id = (unsigned int)info.reset;
284
285 return 0;
286}
287
288static int pka_wait_bit(uintptr_t base, uint32_t bit)
289{
290 uint64_t timeout = timeout_init_us(PKA_TIMEOUT_US);
291
292 while ((mmio_read_32(base + _PKA_SR) & bit) != bit) {
293 if (timeout_elapsed(timeout)) {
294 WARN("timeout waiting %x\n", bit);
295 return -ETIMEDOUT;
296 }
297 }
298
299 return 0;
300
301}
302
303static void pka_disable(uintptr_t base)
304{
305 mmio_clrbits_32(base + _PKA_CR, _PKA_CR_EN);
306}
307
308static int pka_enable(uintptr_t base, uint32_t mode)
309{
310 /* Set mode and disable interrupts */
311 mmio_clrsetbits_32(base + _PKA_CR, _PKA_IT_MASK | _PKA_CR_MODE_MASK,
312 _PKA_CR_MODE_MASK & (mode << _PKA_CR_MODE_SHIFT));
313
314 mmio_setbits_32(base + _PKA_CR, _PKA_CR_EN);
315
316 return pka_wait_bit(base, _PKA_SR_INITOK);
317}
318
319/*
320 * Data are already loaded in PKA internal RAM
321 * MODE is set
322 * We start process, and wait for its end.
323 */
324static int stm32_pka_process(uintptr_t base)
325{
326 mmio_setbits_32(base + _PKA_CR, _PKA_CR_START);
327
328 return pka_wait_bit(base, _PKA_IT_PROCEND);
329}
330
331/**
332 * @brief Write ECC operand to PKA RAM.
333 * @note PKA expect to write u64 word, each u64 are: the least significant bit is
334 * bit 0; the most significant bit is bit 63.
335 * We write eo_nbw (ECC operand Size) u64, value that depends of the chosen
336 * prime modulus length in bits.
337 * First less signicant u64 is written to low address
338 * Most significant u64 to higher address.
339 * And at last address we write a u64(0x0)
340 * @note This function doesn't only manage endianness (as bswap64 do), but also
341 * complete most significant incomplete u64 with 0 (if data is not a u64
342 * multiple), and fill u64 last address with 0.
343 * @param addr: PKA_RAM address to write the buffer 'data'
344 * @param data: is a BYTE list with most significant bytes first
345 * @param data_size: nb of byte in data
346 * @param eo_nbw: is ECC Operand size in 64bits word (including the extra 0)
347 * (note it depends of the prime modulus length, not the data size)
348 * @retval 0 if OK.
349 * -EINVAL if data_size and eo_nbw are inconsistent, ie data doesn't
350 * fit in defined eo_nbw, or eo_nbw bigger than hardware limit.
351 */
352static int write_eo_data(uintptr_t addr, uint8_t *data, unsigned int data_size,
353 unsigned int eo_nbw)
354{
355 uint32_t word_index;
356 int data_index;
357
358 if ((eo_nbw < OP_NBW_FROM_SIZE(data_size)) || (eo_nbw > MAX_EO_NBW)) {
359 return -EINVAL;
360 }
361
362 /* Fill value */
363 data_index = (int)data_size - 1;
364 for (word_index = 0U; word_index < eo_nbw; word_index++) {
365 uint64_t tmp = 0ULL;
366 unsigned int i = 0U; /* index in the tmp U64 word */
367
368 /* Stop if end of tmp or end of data */
369 while ((i < sizeof(tmp)) && (data_index >= 0)) {
370 tmp |= (uint64_t)(data[data_index]) << (UINT8_LEN * i);
371 i++; /* Move byte index in current (u64)tmp */
372 data_index--; /* Move to just next most significat byte */
373 }
374
375 mmio_write_64(addr + word_index * sizeof(tmp), tmp);
376 }
377
378 return 0;
379}
380
381static unsigned int get_ecc_op_nbword(enum stm32_pka_ecdsa_curve_id cid)
382{
383 if (cid >= ARRAY_SIZE(curve_def)) {
384 ERROR("CID %u is out of boundaries\n", cid);
385 panic();
386 }
387
388 return OP_NBW_FROM_LEN(curve_def[cid].n_len);
389}
390
391static int stm32_pka_ecdsa_verif_configure_curve(uintptr_t base, enum stm32_pka_ecdsa_curve_id cid)
392{
393 int ret;
394 unsigned int eo_nbw = get_ecc_op_nbword(cid);
395
396 mmio_write_64(base + _PKA_RAM_N_LEN, curve_def[cid].n_len);
397 mmio_write_64(base + _PKA_RAM_P_LEN, curve_def[cid].p_len);
398 mmio_write_64(base + _PKA_RAM_A_SIGN, curve_def[cid].a_sign);
399
400 ret = write_eo_data(base + _PKA_RAM_A, curve_def[cid].a, curve_def[cid].a_size, eo_nbw);
401 if (ret < 0) {
402 return ret;
403 }
404
405 ret = write_eo_data(base + _PKA_RAM_PRIME_N,
406 curve_def[cid].n, div_round_up(curve_def[cid].n_len, UINT8_LEN),
407 eo_nbw);
408 if (ret < 0) {
409 return ret;
410 }
411
412 ret = write_eo_data(base + _PKA_RAM_P, curve_def[cid].p,
413 div_round_up(curve_def[cid].p_len, UINT8_LEN), eo_nbw);
414 if (ret < 0) {
415 return ret;
416 }
417
418 ret = write_eo_data(base + _PKA_RAM_XG, curve_def[cid].xg, curve_def[cid].xg_size, eo_nbw);
419 if (ret < 0) {
420 return ret;
421 }
422
423 ret = write_eo_data(base + _PKA_RAM_YG, curve_def[cid].yg, curve_def[cid].yg_size, eo_nbw);
424 if (ret < 0) {
425 return ret;
426 }
427
428 return 0;
429}
430
431static int stm32_pka_ecdsa_verif_check_return(uintptr_t base)
432{
433 uint64_t value;
434 uint32_t sr;
435
436 sr = mmio_read_32(base + _PKA_SR);
437 if ((sr & (_PKA_IT_OPERR | _PKA_IT_ADDRERR | _PKA_IT_RAMERR)) != 0) {
438 WARN("Detected error(s): %s%s%s\n",
439 (sr & _PKA_IT_OPERR) ? "Operation " : "",
440 (sr & _PKA_IT_ADDRERR) ? "Address " : "",
441 (sr & _PKA_IT_RAMERR) ? "RAM" : "");
442 return -EINVAL;
443 }
444
445 value = mmio_read_64(base + _PKA_RAM_ECDSA_VERIFY);
446 if (value == _PKA_RAM_ECDSA_VERIFY_VALID) {
447 return 0;
448 }
449
450 if (value == _PKA_RAM_ECDSA_VERIFY_INVALID) {
451 return -EAUTH;
452 }
453
454 return -EINVAL;
455}
456
457/**
458 * @brief Check if BigInt stored in data is 0
459 *
460 * @param data: a BYTE array with most significant bytes first
461 * @param size: data size
462 *
463 * @retval: true: if data represents a 0 value (ie all bytes == 0)
464 * false: if data represents a non-zero value.
465 */
466static bool is_zero(uint8_t *data, unsigned int size)
467{
468 unsigned int i;
469
470 for (i = 0U; i < size; i++) {
471 if (data[i] != 0U) {
472 return false;
473 }
474 }
475
476 return true;
477}
478
479/**
480 * @brief Compare two BigInt:
481 * @param xdata_a: a BYTE array with most significant bytes first
482 * @param size_a: nb of Byte of 'a'
483 * @param data_b: a BYTE array with most significant bytes first
484 * @param size_b: nb of Byte of 'b'
485 *
486 * @retval: true if data_a < data_b
487 * false if data_a >= data_b
488 */
489static bool is_smaller(uint8_t *data_a, unsigned int size_a,
490 uint8_t *data_b, unsigned int size_b)
491{
492 unsigned int i;
493
494 i = MAX(size_a, size_b) + 1U;
495 do {
496 uint8_t a, b;
497
498 i--;
499 if (size_a < i) {
500 a = 0U;
501 } else {
502 a = data_a[size_a - i];
503 }
504
505 if (size_b < i) {
506 b = 0U;
507 } else {
508 b = data_b[size_b - i];
509 }
510
511 if (a < b) {
512 return true;
513 }
514
515 if (a > b) {
516 return false;
517 }
518 } while (i != 0U);
519
520 return false;
521}
522
523static int stm32_pka_ecdsa_check_param(void *sig_r_ptr, unsigned int sig_r_size,
524 void *sig_s_ptr, unsigned int sig_s_size,
525 void *pk_x_ptr, unsigned int pk_x_size,
526 void *pk_y_ptr, unsigned int pk_y_size,
527 enum stm32_pka_ecdsa_curve_id cid)
528{
529 /* Public Key check */
530 /* Check Xq < p */
531 if (!is_smaller(pk_x_ptr, pk_x_size,
532 curve_def[cid].p, div_round_up(curve_def[cid].p_len, UINT8_LEN))) {
533 WARN("%s Xq < p inval\n", __func__);
534 return -EINVAL;
535 }
536
537 /* Check Yq < p */
538 if (!is_smaller(pk_y_ptr, pk_y_size,
539 curve_def[cid].p, div_round_up(curve_def[cid].p_len, UINT8_LEN))) {
540 WARN("%s Yq < p inval\n", __func__);
541 return -EINVAL;
542 }
543
544 /* Signature check */
545 /* Check 0 < r < n */
546 if (!is_smaller(sig_r_ptr, sig_r_size,
547 curve_def[cid].n, div_round_up(curve_def[cid].n_len, UINT8_LEN)) &&
548 !is_zero(sig_r_ptr, sig_r_size)) {
549 WARN("%s 0< r < n inval\n", __func__);
550 return -EINVAL;
551 }
552
553 /* Check 0 < s < n */
554 if (!is_smaller(sig_s_ptr, sig_s_size,
555 curve_def[cid].n, div_round_up(curve_def[cid].n_len, UINT8_LEN)) &&
556 !is_zero(sig_s_ptr, sig_s_size)) {
557 WARN("%s 0< s < n inval\n", __func__);
558 return -EINVAL;
559 }
560
561 return 0;
562}
563
564/*
565 * @brief Initialize the PKA driver.
566 * @param None.
567 * @retval 0 if OK, negative value else.
568 */
569int stm32_pka_init(void)
570{
571 int err;
572#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
573 uint32_t ver;
574 uint32_t id;
575#endif
576
577 err = stm32_pka_parse_fdt();
578 if (err != 0) {
Yann Gautier55f3eb42022-12-13 10:51:56 +0100579 return err;
Nicolas Toromanoffdb13fac2020-09-30 17:36:45 +0200580 }
581
582 clk_enable(pka_pdata.clock_id);
583
584 if (stm32mp_reset_assert((unsigned long)pka_pdata.reset_id, TIMEOUT_US_1MS) != 0) {
585 panic();
586 }
587
588 udelay(PKA_RESET_DELAY);
589 if (stm32mp_reset_deassert((unsigned long)pka_pdata.reset_id, TIMEOUT_US_1MS) != 0) {
590 panic();
591 }
592
593#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
594 id = mmio_read_32(pka_pdata.base + _PKA_IPIDR);
595 ver = mmio_read_32(pka_pdata.base + _PKA_VERR);
596
597 VERBOSE("STM32 PKA[%x] V%u.%u\n", id,
598 (ver & _PKA_VERR_MAJREV_MASK) >> _PKA_VERR_MAJREV_SHIFT,
599 (ver & _PKA_VERR_MINREV_MASK) >> _PKA_VERR_MINREV_SHIFT);
600#endif
601 return 0;
602}
603
604int stm32_pka_ecdsa_verif(void *hash, unsigned int hash_size,
605 void *sig_r_ptr, unsigned int sig_r_size,
606 void *sig_s_ptr, unsigned int sig_s_size,
607 void *pk_x_ptr, unsigned int pk_x_size,
608 void *pk_y_ptr, unsigned int pk_y_size,
609 enum stm32_pka_ecdsa_curve_id cid)
610{
611 int ret;
612 uintptr_t base = pka_pdata.base;
613 unsigned int eo_nbw = get_ecc_op_nbword(cid);
614
615 if ((hash == NULL) || (sig_r_ptr == NULL) || (sig_s_ptr == NULL) ||
616 (pk_x_ptr == NULL) || (pk_y_ptr == NULL)) {
617 INFO("%s invalid input param\n", __func__);
618 return -EINVAL;
619 }
620
621 ret = stm32_pka_ecdsa_check_param(sig_r_ptr, sig_r_size,
622 sig_s_ptr, sig_s_size,
623 pk_x_ptr, pk_x_size,
624 pk_y_ptr, pk_y_size,
625 cid);
626 if (ret < 0) {
627 INFO("%s check param error %d\n", __func__, ret);
628 goto out;
629 }
630
631 if ((mmio_read_32(base + _PKA_SR) & _PKA_SR_BUSY) == _PKA_SR_BUSY) {
632 INFO("%s busy\n", __func__);
633 ret = -EBUSY;
634 goto out;
635 }
636
637 /* Fill PKA RAM */
638 /* With curve id values */
639 ret = stm32_pka_ecdsa_verif_configure_curve(base, cid);
640 if (ret < 0) {
641 goto out;
642 }
643
644 /* With pubkey */
645 ret = write_eo_data(base + _PKA_RAM_XQ, pk_x_ptr, pk_x_size, eo_nbw);
646 if (ret < 0) {
647 goto out;
648 }
649
650 ret = write_eo_data(base + _PKA_RAM_YQ, pk_y_ptr, pk_y_size, eo_nbw);
651 if (ret < 0) {
652 goto out;
653 }
654
655 /* With hash */
656 ret = write_eo_data(base + _PKA_RAM_HASH_Z, hash, hash_size, eo_nbw);
657 if (ret < 0) {
658 goto out;
659 }
660
661 /* With signature */
662 ret = write_eo_data(base + _PKA_RAM_SIGN_R, sig_r_ptr, sig_r_size, eo_nbw);
663 if (ret < 0) {
664 goto out;
665 }
666
667 ret = write_eo_data(base + _PKA_RAM_SIGN_S, sig_s_ptr, sig_s_size, eo_nbw);
668 if (ret < 0) {
669 goto out;
670 }
671
672 /* Set mode to ecdsa signature verification */
673 ret = pka_enable(base, _PKA_CR_MODE_ECDSA_VERIF);
674 if (ret < 0) {
675 WARN("%s set mode pka error %d\n", __func__, ret);
676 goto out;
677 }
678
679 /* Start processing and wait end */
680 ret = stm32_pka_process(base);
681 if (ret < 0) {
682 WARN("%s process error %d\n", __func__, ret);
683 goto out;
684 }
685
686 /* Check return status */
687 ret = stm32_pka_ecdsa_verif_check_return(base);
688
689 /* Unset end proc */
690 mmio_setbits_32(base + _PKA_CLRFR, _PKA_IT_PROCEND);
691
692out:
693 /* Disable PKA (will stop all pending proccess and reset RAM) */
694 pka_disable(base);
695
696 return ret;
697}