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