blob: 547ff89beca3507b2de2b5489979cb7e2ec4eeb8 [file] [log] [blame]
Nicolas Toromanoffda968b12020-09-18 09:19:11 +02001/*
Maxime Méré9b41e192024-06-28 14:03:32 +02002 * Copyright (c) 2022-2025, STMicroelectronics - All Rights Reserved
Nicolas Toromanoffda968b12020-09-18 09:19:11 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6#include <assert.h>
7#include <endian.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_saes.h>
14#include <drivers/st/stm32mp_reset.h>
15#include <lib/mmio.h>
16#include <lib/utils_def.h>
17#include <libfdt.h>
18
19#include <platform_def.h>
20
21#define UINT8_BIT 8U
22#define AES_BLOCK_SIZE_BIT 128U
23#define AES_BLOCK_SIZE (AES_BLOCK_SIZE_BIT / UINT8_BIT)
24
25#define AES_KEYSIZE_128 16U
26#define AES_KEYSIZE_256 32U
27#define AES_IVSIZE 16U
28
29/* SAES control register */
30#define _SAES_CR 0x0U
31/* SAES status register */
32#define _SAES_SR 0x04U
33/* SAES data input register */
34#define _SAES_DINR 0x08U
35/* SAES data output register */
36#define _SAES_DOUTR 0x0CU
37/* SAES key registers [0-3] */
38#define _SAES_KEYR0 0x10U
39#define _SAES_KEYR1 0x14U
40#define _SAES_KEYR2 0x18U
41#define _SAES_KEYR3 0x1CU
42/* SAES initialization vector registers [0-3] */
43#define _SAES_IVR0 0x20U
44#define _SAES_IVR1 0x24U
45#define _SAES_IVR2 0x28U
46#define _SAES_IVR3 0x2CU
47/* SAES key registers [4-7] */
48#define _SAES_KEYR4 0x30U
49#define _SAES_KEYR5 0x34U
50#define _SAES_KEYR6 0x38U
51#define _SAES_KEYR7 0x3CU
52/* SAES suspend registers [0-7] */
53#define _SAES_SUSPR0 0x40U
54#define _SAES_SUSPR1 0x44U
55#define _SAES_SUSPR2 0x48U
56#define _SAES_SUSPR3 0x4CU
57#define _SAES_SUSPR4 0x50U
58#define _SAES_SUSPR5 0x54U
59#define _SAES_SUSPR6 0x58U
60#define _SAES_SUSPR7 0x5CU
61/* SAES Interrupt Enable Register */
62#define _SAES_IER 0x300U
63/* SAES Interrupt Status Register */
64#define _SAES_ISR 0x304U
65/* SAES Interrupt Clear Register */
66#define _SAES_ICR 0x308U
67
68/* SAES control register fields */
69#define _SAES_CR_RESET_VALUE 0x0U
70#define _SAES_CR_IPRST BIT(31)
71#define _SAES_CR_KEYSEL_MASK GENMASK(30, 28)
72#define _SAES_CR_KEYSEL_SHIFT 28U
73#define _SAES_CR_KEYSEL_SOFT 0x0U
74#define _SAES_CR_KEYSEL_DHUK 0x1U
75#define _SAES_CR_KEYSEL_BHK 0x2U
76#define _SAES_CR_KEYSEL_BHU_XOR_BH_K 0x4U
77#define _SAES_CR_KEYSEL_TEST 0x7U
78#define _SAES_CR_KSHAREID_MASK GENMASK(27, 26)
79#define _SAES_CR_KSHAREID_SHIFT 26U
80#define _SAES_CR_KSHAREID_CRYP 0x0U
81#define _SAES_CR_KEYMOD_MASK GENMASK(25, 24)
82#define _SAES_CR_KEYMOD_SHIFT 24U
83#define _SAES_CR_KEYMOD_NORMAL 0x0U
84#define _SAES_CR_KEYMOD_WRAPPED 0x1U
85#define _SAES_CR_KEYMOD_SHARED 0x2U
86#define _SAES_CR_NPBLB_MASK GENMASK(23, 20)
87#define _SAES_CR_NPBLB_SHIFT 20U
88#define _SAES_CR_KEYPROT BIT(19)
89#define _SAES_CR_KEYSIZE BIT(18)
90#define _SAES_CR_GCMPH_MASK GENMASK(14, 13)
91#define _SAES_CR_GCMPH_SHIFT 13U
92#define _SAES_CR_GCMPH_INIT 0U
93#define _SAES_CR_GCMPH_HEADER 1U
94#define _SAES_CR_GCMPH_PAYLOAD 2U
95#define _SAES_CR_GCMPH_FINAL 3U
96#define _SAES_CR_DMAOUTEN BIT(12)
97#define _SAES_CR_DMAINEN BIT(11)
98#define _SAES_CR_CHMOD_MASK (BIT(16) | GENMASK(6, 5))
99#define _SAES_CR_CHMOD_SHIFT 5U
100#define _SAES_CR_CHMOD_ECB 0x0U
101#define _SAES_CR_CHMOD_CBC 0x1U
102#define _SAES_CR_CHMOD_CTR 0x2U
103#define _SAES_CR_CHMOD_GCM 0x3U
104#define _SAES_CR_CHMOD_GMAC 0x3U
105#define _SAES_CR_CHMOD_CCM 0x800U
106#define _SAES_CR_MODE_MASK GENMASK(4, 3)
107#define _SAES_CR_MODE_SHIFT 3U
108#define _SAES_CR_MODE_ENC 0U
109#define _SAES_CR_MODE_KEYPREP 1U
110#define _SAES_CR_MODE_DEC 2U
111#define _SAES_CR_DATATYPE_MASK GENMASK(2, 1)
112#define _SAES_CR_DATATYPE_SHIFT 1U
113#define _SAES_CR_DATATYPE_NONE 0U
114#define _SAES_CR_DATATYPE_HALF_WORD 1U
115#define _SAES_CR_DATATYPE_BYTE 2U
116#define _SAES_CR_DATATYPE_BIT 3U
117#define _SAES_CR_EN BIT(0)
118
119/* SAES status register fields */
120#define _SAES_SR_KEYVALID BIT(7)
121#define _SAES_SR_BUSY BIT(3)
122#define _SAES_SR_WRERR BIT(2)
123#define _SAES_SR_RDERR BIT(1)
124#define _SAES_SR_CCF BIT(0)
125
126/* SAES interrupt registers fields */
127#define _SAES_I_RNG_ERR BIT(3)
128#define _SAES_I_KEY_ERR BIT(2)
129#define _SAES_I_RW_ERR BIT(1)
130#define _SAES_I_CC BIT(0)
131
132#define SAES_TIMEOUT_US 100000U
133#define TIMEOUT_US_1MS 1000U
134#define SAES_RESET_DELAY 20U
135
136#define IS_CHAINING_MODE(mod, cr) \
137 (((cr) & _SAES_CR_CHMOD_MASK) == (_SAES_CR_CHMOD_##mod << _SAES_CR_CHMOD_SHIFT))
138
139#define SET_CHAINING_MODE(mod, cr) \
140 mmio_clrsetbits_32((cr), _SAES_CR_CHMOD_MASK, _SAES_CR_CHMOD_##mod << _SAES_CR_CHMOD_SHIFT)
141
Nicolas Toromanoffda968b12020-09-18 09:19:11 +0200142static struct stm32_saes_platdata saes_pdata;
143
Nicolas Toromanoffda968b12020-09-18 09:19:11 +0200144static int stm32_saes_parse_fdt(struct stm32_saes_platdata *pdata)
145{
146 int node;
147 struct dt_node_info info;
148 void *fdt;
149
150 if (fdt_get_address(&fdt) == 0) {
151 return -FDT_ERR_NOTFOUND;
152 }
153
154 node = dt_get_node(&info, -1, DT_SAES_COMPAT);
155 if (node < 0) {
156 ERROR("No SAES entry in DT\n");
157 return -FDT_ERR_NOTFOUND;
158 }
159
160 if (info.status == DT_DISABLED) {
161 return -FDT_ERR_NOTFOUND;
162 }
163
164 if ((info.base == 0U) || (info.clock < 0) || (info.reset < 0)) {
165 return -FDT_ERR_BADVALUE;
166 }
167
168 pdata->base = (uintptr_t)info.base;
169 pdata->clock_id = (unsigned long)info.clock;
170 pdata->reset_id = (unsigned int)info.reset;
171
172 return 0;
173}
174
175static bool does_chaining_mode_need_iv(uint32_t cr)
176{
177 return !(IS_CHAINING_MODE(ECB, cr));
178}
179
180static bool is_encrypt(uint32_t cr)
181{
182 return (cr & _SAES_CR_MODE_MASK) == (_SAES_CR_MODE_ENC << _SAES_CR_MODE_SHIFT);
183}
184
185static bool is_decrypt(uint32_t cr)
186{
187 return (cr & _SAES_CR_MODE_MASK) == (_SAES_CR_MODE_DEC << _SAES_CR_MODE_SHIFT);
188}
189
190static int wait_computation_completed(uintptr_t base)
191{
192 uint64_t timeout = timeout_init_us(SAES_TIMEOUT_US);
193
194 while ((mmio_read_32(base + _SAES_SR) & _SAES_SR_CCF) != _SAES_SR_CCF) {
195 if (timeout_elapsed(timeout)) {
196 WARN("%s: timeout\n", __func__);
197 return -ETIMEDOUT;
198 }
199 }
200
201 return 0;
202}
203
204static void clear_computation_completed(uintptr_t base)
205{
206 mmio_setbits_32(base + _SAES_ICR, _SAES_I_CC);
207}
208
209static int saes_start(struct stm32_saes_context *ctx)
210{
211 uint64_t timeout;
212
213 /* Reset IP */
Maxime Méré9b41e192024-06-28 14:03:32 +0200214 if ((mmio_read_32(ctx->base + _SAES_SR) & _SAES_SR_BUSY) != _SAES_SR_BUSY) {
215 mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
216 udelay(SAES_RESET_DELAY);
217 mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
218 }
Nicolas Toromanoffda968b12020-09-18 09:19:11 +0200219
220 timeout = timeout_init_us(SAES_TIMEOUT_US);
221 while ((mmio_read_32(ctx->base + _SAES_SR) & _SAES_SR_BUSY) == _SAES_SR_BUSY) {
222 if (timeout_elapsed(timeout)) {
223 WARN("%s: timeout\n", __func__);
224 return -ETIMEDOUT;
225 }
226 }
227
228 return 0;
229}
230
231static void saes_end(struct stm32_saes_context *ctx, int prev_error)
232{
233 if (prev_error != 0) {
234 /* Reset IP */
235 mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
236 udelay(SAES_RESET_DELAY);
237 mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
238 }
239
240 /* Disable the SAES peripheral */
241 mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
242}
243
244static void saes_write_iv(struct stm32_saes_context *ctx)
245{
246 /* If chaining mode need to restore IV */
247 if (does_chaining_mode_need_iv(ctx->cr)) {
248 uint8_t i;
249
250 /* Restore the _SAES_IVRx */
251 for (i = 0U; i < AES_IVSIZE / sizeof(uint32_t); i++) {
252 mmio_write_32(ctx->base + _SAES_IVR0 + i * sizeof(uint32_t), ctx->iv[i]);
253 }
254 }
255
256}
257
258static void saes_write_key(struct stm32_saes_context *ctx)
259{
260 /* Restore the _SAES_KEYRx if SOFTWARE key */
261 if ((ctx->cr & _SAES_CR_KEYSEL_MASK) == (_SAES_CR_KEYSEL_SOFT << _SAES_CR_KEYSEL_SHIFT)) {
262 uint8_t i;
263
264 for (i = 0U; i < AES_KEYSIZE_128 / sizeof(uint32_t); i++) {
265 mmio_write_32(ctx->base + _SAES_KEYR0 + i * sizeof(uint32_t), ctx->key[i]);
266 }
267
268 if ((ctx->cr & _SAES_CR_KEYSIZE) == _SAES_CR_KEYSIZE) {
269 for (i = 0U; i < (AES_KEYSIZE_256 / 2U) / sizeof(uint32_t); i++) {
270 mmio_write_32(ctx->base + _SAES_KEYR4 + i * sizeof(uint32_t),
271 ctx->key[i + 4U]);
272 }
273 }
274 }
275}
276
277static int saes_prepare_key(struct stm32_saes_context *ctx)
278{
279 /* Disable the SAES peripheral */
280 mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
281
282 /* Set key size */
283 if ((ctx->cr & _SAES_CR_KEYSIZE) != 0U) {
284 mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_KEYSIZE);
285 } else {
286 mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_KEYSIZE);
287 }
288
289 saes_write_key(ctx);
290
291 /* For ECB/CBC decryption, key preparation mode must be selected to populate the key */
292 if ((IS_CHAINING_MODE(ECB, ctx->cr) || IS_CHAINING_MODE(CBC, ctx->cr)) &&
293 is_decrypt(ctx->cr)) {
294 int ret;
295
296 /* Select Mode 2 */
297 mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_MODE_MASK,
298 _SAES_CR_MODE_KEYPREP << _SAES_CR_MODE_SHIFT);
299
300 /* Enable SAES */
301 mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
302
303 /* Wait Computation completed */
304 ret = wait_computation_completed(ctx->base);
305 if (ret != 0) {
306 return ret;
307 }
308
309 clear_computation_completed(ctx->base);
310
311 /* Set Mode 3 */
312 mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_MODE_MASK,
313 _SAES_CR_MODE_DEC << _SAES_CR_MODE_SHIFT);
314 }
315
316 return 0;
317}
318
319static int save_context(struct stm32_saes_context *ctx)
320{
321 if ((mmio_read_32(ctx->base + _SAES_SR) & _SAES_SR_CCF) != 0U) {
322 /* Device should not be in a processing phase */
323 return -EINVAL;
324 }
325
326 /* Save CR */
327 ctx->cr = mmio_read_32(ctx->base + _SAES_CR);
328
329 /* If chaining mode need to save current IV */
330 if (does_chaining_mode_need_iv(ctx->cr)) {
331 uint8_t i;
332
333 /* Save IV */
334 for (i = 0U; i < AES_IVSIZE / sizeof(uint32_t); i++) {
335 ctx->iv[i] = mmio_read_32(ctx->base + _SAES_IVR0 + i * sizeof(uint32_t));
336 }
337 }
338
339 /* Disable the SAES peripheral */
340 mmio_clrbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
341
342 return 0;
343}
344
345/* To resume the processing of a message */
346static int restore_context(struct stm32_saes_context *ctx)
347{
348 int ret;
349
350 /* IP should be disabled */
351 if ((mmio_read_32(ctx->base + _SAES_CR) & _SAES_CR_EN) != 0U) {
352 VERBOSE("%s: Device is still enabled\n", __func__);
353 return -EINVAL;
354 }
355
356 /* Reset internal state */
357 mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_IPRST);
358
359 /* Restore the _SAES_CR */
360 mmio_write_32(ctx->base + _SAES_CR, ctx->cr);
361
362 /* Preparation decrypt key */
363 ret = saes_prepare_key(ctx);
364 if (ret != 0) {
365 return ret;
366 }
367
368 saes_write_iv(ctx);
369
370 /* Enable the SAES peripheral */
371 mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
372
373 return 0;
374}
375
376/**
377 * @brief Initialize SAES driver.
378 * @param None.
379 * @retval 0 if OK; negative value else.
380 */
381int stm32_saes_driver_init(void)
382{
383 int err;
384
385 err = stm32_saes_parse_fdt(&saes_pdata);
386 if (err != 0) {
Yann Gautier55f3eb42022-12-13 10:51:56 +0100387 return err;
Nicolas Toromanoffda968b12020-09-18 09:19:11 +0200388 }
389
390 clk_enable(saes_pdata.clock_id);
391 if (stm32mp_reset_assert(saes_pdata.reset_id, TIMEOUT_US_1MS) != 0) {
392 panic();
393 }
394
395 udelay(SAES_RESET_DELAY);
396 if (stm32mp_reset_deassert(saes_pdata.reset_id, TIMEOUT_US_1MS) != 0) {
397 panic();
398 }
399
400 return 0;
401}
402
403/**
404 * @brief Start a AES computation.
405 * @param ctx: SAES process context
406 * @param is_dec: true if decryption, false if encryption
407 * @param ch_mode: define the chaining mode
408 * @param key_select: define where the key comes from.
409 * @param key: pointer to key (if key_select is KEY_SOFT, else unused)
410 * @param key_size: key size
411 * @param iv: pointer to initialization vectore (unsed if ch_mode is ECB)
412 * @param iv_size: iv size
413 * @note this function doesn't access to hardware but store in ctx the values
414 *
415 * @retval 0 if OK; negative value else.
416 */
417int stm32_saes_init(struct stm32_saes_context *ctx, bool is_dec,
418 enum stm32_saes_chaining_mode ch_mode, enum stm32_saes_key_selection key_select,
419 const void *key, size_t key_size, const void *iv, size_t iv_size)
420{
421 unsigned int i;
422 const uint32_t *iv_u32;
423 const uint32_t *key_u32;
424
425 ctx->assoc_len = 0U;
426 ctx->load_len = 0U;
427
428 ctx->base = saes_pdata.base;
429 ctx->cr = _SAES_CR_RESET_VALUE;
430
431 /* We want buffer to be u32 aligned */
432 assert((uintptr_t)key % __alignof__(uint32_t) == 0);
433 assert((uintptr_t)iv % __alignof__(uint32_t) == 0);
434
435 iv_u32 = iv;
436 key_u32 = key;
437
438 if (is_dec) {
439 /* Save Mode 3 = decrypt */
440 mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_MODE_MASK,
441 _SAES_CR_MODE_DEC << _SAES_CR_MODE_SHIFT);
442 } else {
443 /* Save Mode 1 = crypt */
444 mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_MODE_MASK,
445 _SAES_CR_MODE_ENC << _SAES_CR_MODE_SHIFT);
446 }
447
448 /* Save chaining mode */
449 switch (ch_mode) {
450 case STM32_SAES_MODE_ECB:
451 SET_CHAINING_MODE(ECB, (uintptr_t)&(ctx->cr));
452 break;
453 case STM32_SAES_MODE_CBC:
454 SET_CHAINING_MODE(CBC, (uintptr_t)&(ctx->cr));
455 break;
456 case STM32_SAES_MODE_CTR:
457 SET_CHAINING_MODE(CTR, (uintptr_t)&(ctx->cr));
458 break;
459 case STM32_SAES_MODE_GCM:
460 SET_CHAINING_MODE(GCM, (uintptr_t)&(ctx->cr));
461 break;
462 case STM32_SAES_MODE_CCM:
463 SET_CHAINING_MODE(CCM, (uintptr_t)&(ctx->cr));
464 break;
465 default:
466 return -EINVAL;
467 }
468
469 /* We will use HW Byte swap (_SAES_CR_DATATYPE_BYTE) for data.
470 * so we won't need to
471 * htobe32(data) before write to DINR
472 * nor
473 * be32toh after reading from DOUTR
474 *
475 * But note that wrap key only accept _SAES_CR_DATATYPE_NONE
476 */
477 mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_DATATYPE_MASK,
478 _SAES_CR_DATATYPE_BYTE << _SAES_CR_DATATYPE_SHIFT);
479
480 /* Configure keysize */
481 switch (key_size) {
482 case AES_KEYSIZE_128:
483 mmio_clrbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSIZE);
484 break;
485 case AES_KEYSIZE_256:
486 mmio_setbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSIZE);
487 break;
488 default:
489 return -EINVAL;
490 }
491
492 /* Configure key */
493 switch (key_select) {
494 case STM32_SAES_KEY_SOFT:
495 mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
496 _SAES_CR_KEYSEL_SOFT << _SAES_CR_KEYSEL_SHIFT);
497 /* Save key */
498 switch (key_size) {
499 case AES_KEYSIZE_128:
500 /* First 16 bytes == 4 u32 */
501 for (i = 0U; i < AES_KEYSIZE_128 / sizeof(uint32_t); i++) {
502 mmio_write_32((uintptr_t)(ctx->key + i), htobe32(key_u32[3 - i]));
503 /* /!\ we save the key in HW byte order
504 * and word order : key[i] is for _SAES_KEYRi
505 */
506 }
507 break;
508 case AES_KEYSIZE_256:
509 for (i = 0U; i < AES_KEYSIZE_256 / sizeof(uint32_t); i++) {
510 mmio_write_32((uintptr_t)(ctx->key + i), htobe32(key_u32[7 - i]));
511 /* /!\ we save the key in HW byte order
512 * and word order : key[i] is for _SAES_KEYRi
513 */
514 }
515 break;
516 default:
517 return -EINVAL;
518 }
519
520 break;
521 case STM32_SAES_KEY_DHU:
522 mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
523 _SAES_CR_KEYSEL_DHUK << _SAES_CR_KEYSEL_SHIFT);
524 break;
525 case STM32_SAES_KEY_BH:
526 mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
527 _SAES_CR_KEYSEL_BHK << _SAES_CR_KEYSEL_SHIFT);
528 break;
529 case STM32_SAES_KEY_BHU_XOR_BH:
530 mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
531 _SAES_CR_KEYSEL_BHU_XOR_BH_K << _SAES_CR_KEYSEL_SHIFT);
532 break;
533 case STM32_SAES_KEY_WRAPPED:
534 mmio_clrsetbits_32((uintptr_t)&(ctx->cr), _SAES_CR_KEYSEL_MASK,
535 _SAES_CR_KEYSEL_SOFT << _SAES_CR_KEYSEL_SHIFT);
536 break;
537
538 default:
539 return -EINVAL;
540 }
541
542 /* Save IV */
543 if (ch_mode != STM32_SAES_MODE_ECB) {
544 if ((iv == NULL) || (iv_size != AES_IVSIZE)) {
545 return -EINVAL;
546 }
547
548 for (i = 0U; i < AES_IVSIZE / sizeof(uint32_t); i++) {
549 mmio_write_32((uintptr_t)(ctx->iv + i), htobe32(iv_u32[3 - i]));
550 /* /!\ We save the iv in HW byte order */
551 }
552 }
553
554 return saes_start(ctx);
555}
556
557/**
558 * @brief Update (or start) a AES authentificate process of associated data (CCM or GCM).
559 * @param ctx: SAES process context
560 * @param last_block: true if last assoc data block
561 * @param data: pointer to associated data
562 * @param data_size: data size
563 *
564 * @retval 0 if OK; negative value else.
565 */
566int stm32_saes_update_assodata(struct stm32_saes_context *ctx, bool last_block,
567 uint8_t *data, size_t data_size)
568{
569 int ret;
570 uint32_t *data_u32;
571 unsigned int i = 0U;
572
573 /* We want buffers to be u32 aligned */
574 assert((uintptr_t)data % __alignof__(uint32_t) == 0);
575 data_u32 = (uint32_t *)data;
576
577 /* Init phase */
578 ret = restore_context(ctx);
579 if (ret != 0) {
580 goto out;
581 }
582
583 ret = wait_computation_completed(ctx->base);
584 if (ret != 0) {
585 return ret;
586 }
587
588 clear_computation_completed(ctx->base);
589
590 if ((data == NULL) || (data_size == 0U)) {
591 /* No associated data */
592 /* ret already = 0 */
593 goto out;
594 }
595
596 /* There is an header/associated data phase */
597 mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK,
598 _SAES_CR_GCMPH_HEADER << _SAES_CR_GCMPH_SHIFT);
599
600 /* Enable the SAES peripheral */
601 mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
602
603 while (i < round_down(data_size, AES_BLOCK_SIZE)) {
604 unsigned int w; /* Word index */
605
606 w = i / sizeof(uint32_t);
607 /* No need to htobe() as we configure the HW to swap bytes */
608 mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 0U]);
609 mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 1U]);
610 mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 2U]);
611 mmio_write_32(ctx->base + _SAES_DINR, data_u32[w + 3U]);
612
613 ret = wait_computation_completed(ctx->base);
614 if (ret != 0) {
615 goto out;
616 }
617
618 clear_computation_completed(ctx->base);
619
620 /* Process next block */
621 i += AES_BLOCK_SIZE;
622 ctx->assoc_len += AES_BLOCK_SIZE_BIT;
623 }
624
625 /* Manage last block if not a block size multiple */
626 if ((last_block) && (i < data_size)) {
627 /* We don't manage unaligned last block yet */
628 ret = -ENODEV;
629 goto out;
630 }
631
632out:
633 if (ret != 0) {
634 saes_end(ctx, ret);
635 }
636
637 return ret;
638}
639
640/**
641 * @brief Update (or start) a AES authenticate and de/encrypt with payload data (CCM or GCM).
642 * @param ctx: SAES process context
643 * @param last_block: true if last payload data block
644 * @param data_in: pointer to payload
645 * @param data_out: pointer where to save de/encrypted payload
646 * @param data_size: payload size
647 *
648 * @retval 0 if OK; negative value else.
649 */
650int stm32_saes_update_load(struct stm32_saes_context *ctx, bool last_block,
651 uint8_t *data_in, uint8_t *data_out, size_t data_size)
652{
653 int ret = 0;
654 uint32_t *data_in_u32;
655 uint32_t *data_out_u32;
656 unsigned int i = 0U;
657 uint32_t prev_cr;
658
659 /* We want buffers to be u32 aligned */
660 assert((uintptr_t)data_in % __alignof__(uint32_t) == 0);
661 assert((uintptr_t)data_out % __alignof__(uint32_t) == 0);
662 data_in_u32 = (uint32_t *)data_in;
663 data_out_u32 = (uint32_t *)data_out;
664
665 prev_cr = mmio_read_32(ctx->base + _SAES_CR);
666
667 if ((data_in == NULL) || (data_size == 0U)) {
668 /* there is no data */
669 goto out;
670 }
671
672 /* There is a load phase */
673 mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK,
674 _SAES_CR_GCMPH_PAYLOAD << _SAES_CR_GCMPH_SHIFT);
675
676 if ((prev_cr & _SAES_CR_GCMPH_MASK) ==
677 (_SAES_CR_GCMPH_INIT << _SAES_CR_GCMPH_SHIFT)) {
678 /* Still in initialization phase, no header
679 * We need to enable the SAES peripheral
680 */
681 mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
682 }
683
684 while (i < round_down(data_size, AES_BLOCK_SIZE)) {
685 unsigned int w; /* Word index */
686
687 w = i / sizeof(uint32_t);
688 /* No need to htobe() as we configure the HW to swap bytes */
689 mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 0U]);
690 mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 1U]);
691 mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 2U]);
692 mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 3U]);
693
694 ret = wait_computation_completed(ctx->base);
695 if (ret != 0) {
696 goto out;
697 }
698
699 /* No need to htobe() as we configure the HW to swap bytes */
700 data_out_u32[w + 0U] = mmio_read_32(ctx->base + _SAES_DOUTR);
701 data_out_u32[w + 1U] = mmio_read_32(ctx->base + _SAES_DOUTR);
702 data_out_u32[w + 2U] = mmio_read_32(ctx->base + _SAES_DOUTR);
703 data_out_u32[w + 3U] = mmio_read_32(ctx->base + _SAES_DOUTR);
704
705 clear_computation_completed(ctx->base);
706
707 /* Process next block */
708 i += AES_BLOCK_SIZE;
709 ctx->load_len += AES_BLOCK_SIZE_BIT;
710 }
711 /* Manage last block if not a block size multiple */
712 if ((last_block) && (i < data_size)) {
713 uint32_t block_in[AES_BLOCK_SIZE / sizeof(uint32_t)] = {0};
714 uint32_t block_out[AES_BLOCK_SIZE / sizeof(uint32_t)] = {0};
715
716 memcpy(block_in, data_in + i, data_size - i);
717
718 /* No need to htobe() as we configure the HW to swap bytes */
719 mmio_write_32(ctx->base + _SAES_DINR, block_in[0U]);
720 mmio_write_32(ctx->base + _SAES_DINR, block_in[1U]);
721 mmio_write_32(ctx->base + _SAES_DINR, block_in[2U]);
722 mmio_write_32(ctx->base + _SAES_DINR, block_in[3U]);
723
724 ret = wait_computation_completed(ctx->base);
725 if (ret != 0) {
726 VERBOSE("%s %d\n", __func__, __LINE__);
727 goto out;
728 }
729
730 /* No need to htobe() as we configure the HW to swap bytes */
731 block_out[0U] = mmio_read_32(ctx->base + _SAES_DOUTR);
732 block_out[1U] = mmio_read_32(ctx->base + _SAES_DOUTR);
733 block_out[2U] = mmio_read_32(ctx->base + _SAES_DOUTR);
734 block_out[3U] = mmio_read_32(ctx->base + _SAES_DOUTR);
735
736 clear_computation_completed(ctx->base);
737
738 memcpy(data_out + i, block_out, data_size - i);
739
740 ctx->load_len += (data_size - i) * UINT8_BIT;
741 }
742
743out:
744 if (ret != 0) {
745 saes_end(ctx, ret);
746 }
747
748 return ret;
749}
750
751/**
752 * @brief Get authentication tag for AES authenticated algorithms (CCM or GCM).
753 * @param ctx: SAES process context
754 * @param tag: pointer where to save the tag
755 * @param data_size: tag size
756 *
757 * @retval 0 if OK; negative value else.
758 */
759int stm32_saes_final(struct stm32_saes_context *ctx, uint8_t *tag,
760 size_t tag_size)
761{
762 int ret;
763 uint32_t tag_u32[4];
764 uint32_t prev_cr;
765
766 prev_cr = mmio_read_32(ctx->base + _SAES_CR);
767
768 mmio_clrsetbits_32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK,
769 _SAES_CR_GCMPH_FINAL << _SAES_CR_GCMPH_SHIFT);
770
771 if ((prev_cr & _SAES_CR_GCMPH_MASK) == (_SAES_CR_GCMPH_INIT << _SAES_CR_GCMPH_SHIFT)) {
772 /* Still in initialization phase, no header
773 * We need to enable the SAES peripheral
774 */
775 mmio_setbits_32(ctx->base + _SAES_CR, _SAES_CR_EN);
776 }
777
778 /* No need to htobe() as we configure the HW to swap bytes */
779 mmio_write_32(ctx->base + _SAES_DINR, 0);
780 mmio_write_32(ctx->base + _SAES_DINR, ctx->assoc_len);
781 mmio_write_32(ctx->base + _SAES_DINR, 0);
782 mmio_write_32(ctx->base + _SAES_DINR, ctx->load_len);
783
784 ret = wait_computation_completed(ctx->base);
785 if (ret != 0) {
786 goto out;
787 }
788
789 /* No need to htobe() as we configure the HW to swap bytes */
790 tag_u32[0] = mmio_read_32(ctx->base + _SAES_DOUTR);
791 tag_u32[1] = mmio_read_32(ctx->base + _SAES_DOUTR);
792 tag_u32[2] = mmio_read_32(ctx->base + _SAES_DOUTR);
793 tag_u32[3] = mmio_read_32(ctx->base + _SAES_DOUTR);
794
795 clear_computation_completed(ctx->base);
796
797 memcpy(tag, tag_u32, MIN(sizeof(tag_u32), tag_size));
798
799out:
800 saes_end(ctx, ret);
801
802 return ret;
803}
804
805/**
806 * @brief Update (or start) a AES de/encrypt process (ECB, CBC or CTR).
807 * @param ctx: SAES process context
808 * @param last_block: true if last payload data block
809 * @param data_in: pointer to payload
810 * @param data_out: pointer where to save de/encrypted payload
811 * @param data_size: payload size
812 *
813 * @retval 0 if OK; negative value else.
814 */
815int stm32_saes_update(struct stm32_saes_context *ctx, bool last_block,
816 uint8_t *data_in, uint8_t *data_out, size_t data_size)
817{
818 int ret;
819 uint32_t *data_in_u32;
820 uint32_t *data_out_u32;
821 unsigned int i = 0U;
822
823 /* We want buffers to be u32 aligned */
824 assert((uintptr_t)data_in % __alignof__(uint32_t) == 0);
825 assert((uintptr_t)data_out % __alignof__(uint32_t) == 0);
826 data_in_u32 = (uint32_t *)data_in;
827 data_out_u32 = (uint32_t *)data_out;
828
829 if ((!last_block) &&
830 (round_down(data_size, AES_BLOCK_SIZE) != data_size)) {
831 ERROR("%s: non last block must be multiple of 128 bits\n",
832 __func__);
833 ret = -EINVAL;
834 goto out;
835 }
836
837 /* In CBC encryption we need to manage specifically last 2 128bits
838 * blocks if total size in not a block size aligned
839 * work TODO. Currently return ENODEV.
840 * Morevoer as we need to know last 2 block, if unaligned and
841 * call with less than two block, return -EINVAL.
842 */
843 if (last_block && IS_CHAINING_MODE(CBC, ctx->cr) && is_encrypt(ctx->cr) &&
844 (round_down(data_size, AES_BLOCK_SIZE) != data_size)) {
845 if (data_size < AES_BLOCK_SIZE * 2U) {
846 ERROR("if CBC, last part size should be at least 2 * AES_BLOCK_SIZE\n");
847 ret = -EINVAL;
848 goto out;
849 }
850 /* Moreover the CBC specific padding for encrypt is not yet implemented */
851 ret = -ENODEV;
852 goto out;
853 }
854
855 ret = restore_context(ctx);
856 if (ret != 0) {
857 goto out;
858 }
859
860 while (i < round_down(data_size, AES_BLOCK_SIZE)) {
861 unsigned int w; /* Word index */
862
863 w = i / sizeof(uint32_t);
864 /* No need to htobe() as we configure the HW to swap bytes */
865 mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 0U]);
866 mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 1U]);
867 mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 2U]);
868 mmio_write_32(ctx->base + _SAES_DINR, data_in_u32[w + 3U]);
869
870 ret = wait_computation_completed(ctx->base);
871 if (ret != 0) {
872 goto out;
873 }
874
875 /* No need to htobe() as we configure the HW to swap bytes */
876 data_out_u32[w + 0U] = mmio_read_32(ctx->base + _SAES_DOUTR);
877 data_out_u32[w + 1U] = mmio_read_32(ctx->base + _SAES_DOUTR);
878 data_out_u32[w + 2U] = mmio_read_32(ctx->base + _SAES_DOUTR);
879 data_out_u32[w + 3U] = mmio_read_32(ctx->base + _SAES_DOUTR);
880
881 clear_computation_completed(ctx->base);
882
883 /* Process next block */
884 i += AES_BLOCK_SIZE;
885 }
886 /* Manage last block if not a block size multiple */
887
888 if ((last_block) && (i < data_size)) {
889 /* In and out buffer have same size so should be AES_BLOCK_SIZE multiple */
890 ret = -ENODEV;
891 goto out;
892 }
893
894 if (!last_block) {
895 ret = save_context(ctx);
896 }
897
898out:
899 /* If last block or error, end of SAES process */
900 if (last_block || (ret != 0)) {
901 saes_end(ctx, ret);
902 }
903
904 return ret;
905}