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