1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2017, 2020 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_aes.h"
10 #include "string.h"
11
12 /*******************************************************************************
13 * Definitions
14 *******************************************************************************/
15
16 /* Component ID definition, used by tools. */
17 #ifndef FSL_COMPONENT_ID
18 #define FSL_COMPONENT_ID "platform.drivers.aes"
19 #endif
20
21 /*!< Use standard C library memcpy */
22 #define aes_memcpy memcpy
23
24 /*! @brief Definitions used for writing to the AES module CFG register. */
25 typedef enum _aes_configuration
26 {
27 kAES_CfgEncryptEcb = 0x001u, /*!< OUTTEXT_SEL, HOLD_SEL and INBLK_SEL = Encrypt Ecb */
28 kAES_CfgDecryptEcb = 0x001u, /*!< OUTTEXT_SEL, HOLD_SEL and INBLK_SEL = Decrypt Ecb */
29 kAES_CfgEncryptCbc = 0x023u, /*!< OUTTEXT_SEL, HOLD_SEL and INBLK_SEL = Encrypt Cbc */
30 kAES_CfgDecryptCbc = 0x211u, /*!< OUTTEXT_SEL, HOLD_SEL and INBLK_SEL = Decrypt Cbc */
31 kAES_CfgEncryptCfb = 0x132u, /*!< OUTTEXT_SEL, HOLD_SEL and INBLK_SEL = Encrypt Cfb */
32 kAES_CfgDecryptCfb = 0x112u, /*!< OUTTEXT_SEL, HOLD_SEL and INBLK_SEL = Decrypt Cfb */
33 kAES_CfgCryptOfb = 0x122u, /*!< OUTTEXT_SEL, HOLD_SEL and INBLK_SEL = Ofb */
34 kAES_CfgCryptCtr = 0x102u, /*!< OUTTEXT_SEL, HOLD_SEL and INBLK_SEL = Ctr */
35 kAES_CfgCryptGcmTag = 0x102u, /*!< OUTTEXT_SEL, HOLD_SEL and INBLK_SEL = Gcm */
36 kAES_CfgSwap = 0x51u, /*!< INTEXT swap bytes, OUTTEXT swap bytes, PROC_EN = Encrypt/Decrypt */
37 kAES_CfgIntextSwap = 0x11u, /*!< INTEXT swap bytes, PROC_EN = Encrypt/Decrypt */
38 kAES_CfgSwapIntextHashIn = 0x12u, /*!< Swap INTEXT only, Hash INTEXT */
39 kAES_CfgSwapIntextHashOut = 0x16u, /*!< Swap INTEXT only, Hash OUTTEXT */
40 kAES_CfgSwapEnDecHashIn = 0x53u, /*!< Swap INTEXT and OUTTEXT, Encrypt/Decrypt and Hash, Hash INTEXT */
41 kAES_CfgSwapEnDecHashOut = 0x57u, /*!< Swap INTEXT and OUTTEXT, Encrypt/Decrypt and Hash, Hash OUTTEXT */
42 kAES_CfgSwapIntextEnDecHashIn = 0x13u, /*!< Swap INTEXT, Encrypt/Decrypt and Hash, Hash INTEXT */
43 } aes_configuration_t;
44
45 /*! @brief Actual operation with AES. */
46 typedef enum _aes_encryption_decryption_mode
47 {
48 kAES_ModeEncrypt = 0U, /*!< Encryption */
49 kAES_ModeDecrypt = 1U, /*!< Decryption */
50 } aes_encryption_decryption_mode_t;
51
52 /*******************************************************************************
53 * Prototypes
54 ******************************************************************************/
55
56 static void aes_gcm_dec32(uint8_t *input);
57
58 /*******************************************************************************
59 * Code
60 ******************************************************************************/
61
62 /*!
63 * @brief Reads an unaligned word.
64 *
65 * This function creates a 32-bit word from an input array of four bytes.
66 *
67 * @param src Input array of four bytes. The array can start at any address in memory.
68 * @return 32-bit unsigned int created from the input byte array.
69 */
aes_get_word_from_unaligned(const uint8_t * srcAddr)70 static inline uint32_t aes_get_word_from_unaligned(const uint8_t *srcAddr)
71 {
72 #if (!(defined(__CORTEX_M)) || (defined(__CORTEX_M) && (__CORTEX_M == 0)))
73 register const uint8_t *src = srcAddr;
74 /* Cortex M0 does not support misaligned loads */
75 if ((uint32_t)src & 0x3u)
76 {
77 union _align_bytes_t
78 {
79 uint32_t word;
80 uint8_t byte[sizeof(uint32_t)];
81 } my_bytes;
82
83 my_bytes.byte[0] = *src;
84 my_bytes.byte[1] = *(src + 1);
85 my_bytes.byte[2] = *(src + 2);
86 my_bytes.byte[3] = *(src + 3);
87 return my_bytes.word;
88 }
89 else
90 {
91 /* addr aligned to 0-modulo-4 so it is safe to type cast */
92 return *((const uint32_t *)src);
93 }
94 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
95 /* -O3 optimization in Keil uses LDM instruction here (LDM r4!, {r0})
96 * which is wrong, because srcAddr might be unaligned.
97 * LDM on unaligned address causes hard-fault. so use memcpy() */
98 uint32_t ret;
99 memcpy(&ret, srcAddr, sizeof(uint32_t));
100 return ret;
101 #else
102 return *((const uint32_t *)(uint32_t)srcAddr);
103 #endif
104 }
105
106 /*!
107 * @brief Converts a 32-bit word into a byte array.
108 *
109 * This function creates an output array of four bytes from an input 32-bit word.
110 *
111 * @param srcWord Input 32-bit unsigned integer.
112 * @param[out] dst Output array of four bytes. The array can start at any address in memory.
113 */
aes_set_unaligned_from_word(uint32_t srcWord,uint8_t * dstAddr)114 static inline void aes_set_unaligned_from_word(uint32_t srcWord, uint8_t *dstAddr)
115 {
116 #if (!(defined(__CORTEX_M)) || (defined(__CORTEX_M) && (__CORTEX_M == 0)))
117 register uint8_t *dst = dstAddr;
118 /* Cortex M0 does not support misaligned stores */
119 if ((uint32_t)dst & 0x3u)
120 {
121 *dst++ = (srcWord & 0x000000FFU);
122 *dst++ = (srcWord & 0x0000FF00U) >> 8;
123 *dst++ = (srcWord & 0x00FF0000U) >> 16;
124 *dst++ = (srcWord & 0xFF000000U) >> 24;
125 }
126 else
127 {
128 *((uint32_t *)dstAddr) = srcWord; /* addr aligned to 0-modulo-4 so it is safe to type cast */
129 }
130 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
131 uint32_t ret;
132 ret = srcWord;
133 memcpy(dstAddr, &ret, sizeof(uint32_t));
134 return;
135 #else
136 *((uint32_t *)(uint32_t)dstAddr) = srcWord;
137 #endif
138 }
139
140 /*!
141 * @brief Swap bytes withing 32-bit word.
142 *
143 * This function changes endianess of a 32-bit word.
144 *
145 * @param in 32-bit unsigned integer
146 * @return 32-bit unsigned integer with different endianess (big endian to little endian and vice versa).
147 */
swap_bytes(uint32_t in)148 static uint32_t swap_bytes(uint32_t in)
149 {
150 return (((in & 0x000000ffu) << 24) | ((in & 0x0000ff00u) << 8) | ((in & 0x00ff0000u) >> 8) |
151 ((in & 0xff000000u) >> 24));
152 }
153
154 /*!
155 * @brief Loads key into key registers.
156 *
157 * This function loads the key into the AES key registers.
158 *
159 * @param base AES peripheral base address.
160 * @param key Input key in big endian format.
161 * @param keySize Size of the input key in bytes. Must be 16, 24 or 32.
162 * @return Status of the load key operation.
163 */
aes_load_key(AES_Type * base,const uint8_t * key,size_t keySize)164 static status_t aes_load_key(AES_Type *base, const uint8_t *key, size_t keySize)
165 {
166 uint32_t aesCfgKeyCfg;
167 uint32_t aesCfg;
168 int index;
169 int keyWords;
170
171 switch (keySize)
172 {
173 case 16u:
174 aesCfgKeyCfg = 0u;
175 keyWords = 4;
176 break;
177
178 case 24u:
179 aesCfgKeyCfg = 1u;
180 keyWords = 6;
181 break;
182
183 case 32u:
184 aesCfgKeyCfg = 2u;
185 keyWords = 8;
186 break;
187
188 default:
189 keyWords = 0;
190 break;
191 }
192
193 if (0 == keyWords)
194 {
195 /* invalidate a possibly valid key. user attempted to set a key but gives incorrect size. */
196 base->CMD = AES_CMD_WIPE(1);
197 /* wait for Idle */
198 while (0U == (base->STAT & AES_STAT_IDLE_MASK))
199 {
200 }
201 base->CMD = AES_CMD_WIPE(0u);
202 return kStatus_InvalidArgument;
203 }
204
205 aesCfg = base->CFG;
206 aesCfg &= ~AES_CFG_KEY_CFG_MASK;
207 aesCfg |= AES_CFG_KEY_CFG(aesCfgKeyCfg);
208 base->CFG = aesCfg;
209
210 for (index = 0; index < keyWords; index++)
211 {
212 base->KEY[index] = swap_bytes(aes_get_word_from_unaligned(key));
213 key += sizeof(uint32_t);
214 }
215
216 return kStatus_Success;
217 }
218
219 /*!
220 * @brief AES process one 16-byte block.
221 *
222 * This function pushes 16 bytes of data to INTEXT and pops 16 bytes of data from OUTTEXT.
223 *
224 * @param base AES peripheral base address.
225 * @param[out] output 16-byte block read from the OUTTEXT registers.
226 * @param input 16-byte block written to the INTEXT registers.
227 */
aes_one_block(AES_Type * base,uint8_t * output,const uint8_t * input)228 static void aes_one_block(AES_Type *base, uint8_t *output, const uint8_t *input)
229 {
230 int index;
231 uint32_t aesStat;
232
233 /* If defined FLS_FEATURE_AES_IRQ_DISABLE, disable IRQs during computing AES block, */
234 /* please note that this can affect IRQs latency */
235 #if defined(FLS_FEATURE_AES_IRQ_DISABLE) && (FLS_FEATURE_AES_IRQ_DISABLE > 0)
236 uint32_t currPriMask;
237 /* disable global interrupt */
238 currPriMask = DisableGlobalIRQ();
239 #endif /* FLS_FEATURE_AES_IRQ_DISABLE */
240
241 /* If the IN_READY bit in STAT register is 1, write the input text in the INTEXT [3:0]
242 registers. */
243 aesStat = base->STAT;
244
245 /* Wait until input text can be written. */
246 while (0U == (aesStat & AES_STAT_IN_READY_MASK))
247 {
248 aesStat = base->STAT;
249 }
250
251 /* Write input data into INTEXT regs */
252 for (index = 0; index < 4; index++)
253 {
254 base->INTEXT[index] = aes_get_word_from_unaligned(input);
255 input += sizeof(uint32_t);
256 }
257
258 /* Wait until output text is ready to be read */
259 while (0U == (aesStat & AES_STAT_OUT_READY_MASK))
260 {
261 aesStat = base->STAT;
262 }
263
264 /* Read output data from OUTTEXT regs */
265 for (index = 0; index < 4; index++)
266 {
267 aes_set_unaligned_from_word(base->OUTTEXT[index], output);
268 output += sizeof(uint32_t);
269 }
270
271 #if defined(FLS_FEATURE_AES_IRQ_DISABLE) && (FLS_FEATURE_AES_IRQ_DISABLE > 0)
272 /* global interrupt enable */
273 EnableGlobalIRQ(currPriMask);
274 #endif /* FLS_FEATURE_AES_IRQ_DISABLE */
275 }
276
277 /*!
278 * @brief AES switch to forward mode.
279 *
280 * This function sets the AES to forward mode if it is in reverse mode.
281 *
282 * @param base AES peripheral base address.
283 */
aes_set_forward(AES_Type * base)284 static void aes_set_forward(AES_Type *base)
285 {
286 if (AES_STAT_REVERSE_MASK == (base->STAT & AES_STAT_REVERSE_MASK))
287 {
288 /* currently in reverse, switch to forward */
289 base->CMD = AES_CMD_SWITCH_MODE(1u);
290
291 /* wait for Idle */
292 while (0U == (base->STAT & AES_STAT_IDLE_MASK))
293 {
294 }
295
296 base->CMD = AES_CMD_SWITCH_MODE(0u);
297 }
298 }
299
300 /*!
301 * @brief AES switch to reverse mode.
302 *
303 * This function sets the AES to reverse mode if it is in forward mode.
304 *
305 * @param base AES peripheral base address.
306 */
aes_set_reverse(AES_Type * base)307 static void aes_set_reverse(AES_Type *base)
308 {
309 if (0U == (base->STAT & AES_STAT_REVERSE_MASK))
310 {
311 /* currently in forward, switch to reverse */
312 base->CMD = AES_CMD_SWITCH_MODE(1u);
313
314 /* wait for Idle */
315 while (0U == (base->STAT & AES_STAT_IDLE_MASK))
316 {
317 }
318
319 base->CMD = AES_CMD_SWITCH_MODE(0u);
320 }
321 }
322
323 /*!
324 * @brief AES write HOLDING registers.
325 *
326 * This function writes input 16-byte data to AES HOLDING registers.
327 *
328 * @param base AES peripheral base address.
329 * @param input 16-byte input data.
330 */
aes_set_holding(AES_Type * base,const uint8_t * input)331 static void aes_set_holding(AES_Type *base, const uint8_t *input)
332 {
333 int index;
334
335 for (index = 0; index < 4; index++)
336 {
337 base->HOLDING[index] = swap_bytes(aes_get_word_from_unaligned(input));
338 input += sizeof(uint32_t);
339 }
340 }
341
342 /*!
343 * @brief AES check KEY_VALID.
344 *
345 * This function check the KEY_VALID bit in AES status register.
346 *
347 * @param base AES peripheral base address.
348 * @return kStatus_Success if the key is valid.
349 * @return kStatus_InvalidArgument if the key is invalid.
350 */
aes_check_key_valid(AES_Type * base)351 static status_t aes_check_key_valid(AES_Type *base)
352 {
353 status_t status;
354
355 /* Check the key is valid */
356 status =
357 (AES_STAT_KEY_VALID_MASK == (base->STAT & AES_STAT_KEY_VALID_MASK)) ? kStatus_Success : kStatus_InvalidArgument;
358
359 return status;
360 }
361
362 /*!
363 * brief Sets AES key.
364 *
365 * Sets AES key.
366 *
367 * param base AES peripheral base address
368 * param key Input key to use for encryption or decryption
369 * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
370 * return Status from Set Key operation
371 */
AES_SetKey(AES_Type * base,const uint8_t * key,size_t keySize)372 status_t AES_SetKey(AES_Type *base, const uint8_t *key, size_t keySize)
373 {
374 return aes_load_key(base, key, keySize);
375 }
376
377 /*!
378 * brief Encrypts AES using the ECB block mode.
379 *
380 * Encrypts AES using the ECB block mode.
381 *
382 * param base AES peripheral base address
383 * param plaintext Input plain text to encrypt
384 * param[out] ciphertext Output cipher text
385 * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
386 * return Status from encrypt operation
387 */
AES_EncryptEcb(AES_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,size_t size)388 status_t AES_EncryptEcb(AES_Type *base, const uint8_t *plaintext, uint8_t *ciphertext, size_t size)
389 {
390 status_t status;
391
392 /* ECB mode, size must be 16-byte multiple */
393 if (0U != (size % 16u))
394 {
395 return kStatus_InvalidArgument;
396 }
397
398 /*5. Select the required crypto operation (encryption/decryption/hash) and AES mode in the CFG register.*/
399 *(volatile uint8_t *)((uint32_t)base) = (uint8_t)kAES_CfgSwap;
400 *(volatile uint16_t *)(((uint32_t)base + 2u)) = (uint16_t)kAES_CfgEncryptEcb;
401
402 status = aes_check_key_valid(base);
403 if (status != kStatus_Success)
404 {
405 return status;
406 }
407
408 /* make sure AES is set to forward mode */
409 aes_set_forward(base);
410
411 while (size != 0U)
412 {
413 aes_one_block(base, ciphertext, plaintext);
414 ciphertext += 16;
415 plaintext += 16;
416 size -= 16u;
417 }
418
419 return status;
420 }
421
422 /*!
423 * brief Decrypts AES using the ECB block mode.
424 *
425 * Decrypts AES using the ECB block mode.
426 *
427 * param base AES peripheral base address
428 * param ciphertext Input ciphertext to decrypt
429 * param[out] plaintext Output plain text
430 * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
431 * return Status from decrypt operation
432 */
AES_DecryptEcb(AES_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,size_t size)433 status_t AES_DecryptEcb(AES_Type *base, const uint8_t *ciphertext, uint8_t *plaintext, size_t size)
434 {
435 status_t status;
436
437 /* ECB mode, size must be 16-byte multiple */
438 if (0U != (size % 16u))
439 {
440 return kStatus_InvalidArgument;
441 }
442
443 status = aes_check_key_valid(base);
444 if (status != kStatus_Success)
445 {
446 return status;
447 }
448
449 /*5. Select the required crypto operation (encryption/decryption/hash) and AES mode in the CFG register.*/
450 *(volatile uint8_t *)((uint32_t)base) = (uint8_t)kAES_CfgSwap;
451 *(volatile uint16_t *)(((uint32_t)base + 2u)) = (uint16_t)kAES_CfgDecryptEcb;
452
453 /* make sure AES is set to reverse mode */
454 aes_set_reverse(base);
455
456 while (size != 0U)
457 {
458 aes_one_block(base, plaintext, ciphertext);
459 ciphertext += 16;
460 plaintext += 16;
461 size -= 16u;
462 }
463
464 return status;
465 }
466
467 /*!
468 * @brief Main function for CBC, CFB and OFB modes.
469 *
470 * @param base AES peripheral base address
471 * @param input Input plaintext for encryption, input ciphertext for decryption.
472 * @param[out] output Output ciphertext for encryption, output plaintext for decryption.
473 * @param size Size of input and output data in bytes. For CBC and CFB it must be multiple of 16-bytes.
474 * @param iv Input initial vector to combine with the first input block.
475 * @return Status from the operation.
476 */
aes_block_mode(AES_Type * base,const uint8_t * input,uint8_t * output,size_t size,const uint8_t iv[AES_IV_SIZE],aes_configuration_t configuration)477 static status_t aes_block_mode(AES_Type *base,
478 const uint8_t *input,
479 uint8_t *output,
480 size_t size,
481 const uint8_t iv[AES_IV_SIZE],
482 aes_configuration_t configuration)
483 {
484 status_t status;
485
486 /* CBC and CFB128 mode, size must be 16-byte multiple */
487 switch (configuration)
488 {
489 case kAES_CfgEncryptCfb:
490 case kAES_CfgDecryptCfb:
491 case kAES_CfgEncryptCbc:
492 case kAES_CfgDecryptCbc:
493 if (0U != (size % 16u))
494 {
495 status = kStatus_InvalidArgument;
496 }
497 else
498 {
499 status = kStatus_Success;
500 }
501 break;
502
503 case kAES_CfgCryptOfb:
504 status = kStatus_Success;
505 break;
506
507 default:
508 status = kStatus_InvalidArgument;
509 break;
510 }
511 if (status != kStatus_Success)
512 {
513 return status;
514 }
515
516 /* Check the key is valid */
517 status = aes_check_key_valid(base);
518 if (status != kStatus_Success)
519 {
520 return status;
521 }
522
523 /*5. Select the required crypto operation (encryption/decryption/hash) and AES mode in the CFG register.*/
524 *(volatile uint8_t *)((uint32_t)base) = (uint8_t)kAES_CfgSwap;
525 *(volatile uint16_t *)(((uint32_t)base + 2u)) = (uint16_t)configuration;
526
527 /* CBC decrypt use reverse AES cipher. */
528 switch (configuration)
529 {
530 case kAES_CfgDecryptCbc:
531 aes_set_reverse(base);
532 break;
533
534 default:
535 aes_set_forward(base);
536 break;
537 }
538
539 /* For CBC, CFB and OFB modes write the Initialization Vector (IV) in the HOLDING
540 [3:0] registers. For CTR mode write the initial counter value in the HOLDING [3:0]
541 registers. */
542 aes_set_holding(base, iv);
543
544 while (size >= 16u)
545 {
546 aes_one_block(base, output, input);
547 size -= 16u;
548 output += 16;
549 input += 16;
550 }
551
552 /* OFB can have non-block multiple size. CBC and CFB128 have size zero at this moment. */
553 if (0U != (size % 16u))
554 {
555 uint8_t blkTemp[16] = {0};
556
557 (void)aes_memcpy(blkTemp, input, size);
558 aes_one_block(base, blkTemp, blkTemp);
559 (void)aes_memcpy(output, blkTemp, size);
560 }
561
562 return status;
563 }
564
565 /*!
566 * brief Encrypts AES using CBC block mode.
567 *
568 * param base AES peripheral base address
569 * param plaintext Input plain text to encrypt
570 * param[out] ciphertext Output cipher text
571 * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
572 * param iv Input initial vector to combine with the first input block.
573 * return Status from encrypt operation
574 */
AES_EncryptCbc(AES_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,size_t size,const uint8_t iv[AES_IV_SIZE])575 status_t AES_EncryptCbc(
576 AES_Type *base, const uint8_t *plaintext, uint8_t *ciphertext, size_t size, const uint8_t iv[AES_IV_SIZE])
577 {
578 return aes_block_mode(base, plaintext, ciphertext, size, iv, kAES_CfgEncryptCbc);
579 }
580
581 /*!
582 * brief Decrypts AES using CBC block mode.
583 *
584 * param base AES peripheral base address
585 * param ciphertext Input cipher text to decrypt
586 * param[out] plaintext Output plain text
587 * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
588 * param iv Input initial vector to combine with the first input block.
589 * return Status from decrypt operation
590 */
AES_DecryptCbc(AES_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,size_t size,const uint8_t iv[AES_IV_SIZE])591 status_t AES_DecryptCbc(
592 AES_Type *base, const uint8_t *ciphertext, uint8_t *plaintext, size_t size, const uint8_t iv[AES_IV_SIZE])
593 {
594 return aes_block_mode(base, ciphertext, plaintext, size, iv, kAES_CfgDecryptCbc);
595 }
596
597 /*!
598 * brief Encrypts AES using CFB block mode.
599 *
600 * param base AES peripheral base address
601 * param plaintext Input plain text to encrypt
602 * param[out] ciphertext Output cipher text
603 * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
604 * param iv Input Initial vector to be used as the first input block.
605 * return Status from encrypt operation
606 */
AES_EncryptCfb(AES_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,size_t size,const uint8_t iv[AES_IV_SIZE])607 status_t AES_EncryptCfb(
608 AES_Type *base, const uint8_t *plaintext, uint8_t *ciphertext, size_t size, const uint8_t iv[AES_IV_SIZE])
609 {
610 return aes_block_mode(base, plaintext, ciphertext, size, iv, kAES_CfgEncryptCfb);
611 }
612
613 /*!
614 * brief Decrypts AES using CFB block mode.
615 *
616 * param base AES peripheral base address
617 * param ciphertext Input cipher text to decrypt
618 * param[out] plaintext Output plain text
619 * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
620 * param iv Input Initial vector to be used as the first input block.
621 * return Status from decrypt operation
622 */
AES_DecryptCfb(AES_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,size_t size,const uint8_t iv[AES_IV_SIZE])623 status_t AES_DecryptCfb(
624 AES_Type *base, const uint8_t *ciphertext, uint8_t *plaintext, size_t size, const uint8_t iv[AES_IV_SIZE])
625 {
626 return aes_block_mode(base, ciphertext, plaintext, size, iv, kAES_CfgDecryptCfb);
627 }
628
629 /*!
630 * brief Encrypts AES using OFB block mode.
631 *
632 * param base AES peripheral base address
633 * param plaintext Input plain text to encrypt
634 * param[out] ciphertext Output cipher text
635 * param size Size of input and output data in bytes.
636 * param iv Input Initial vector to be used as the first input block.
637 * return Status from encrypt operation
638 */
AES_EncryptOfb(AES_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,size_t size,const uint8_t iv[AES_IV_SIZE])639 status_t AES_EncryptOfb(
640 AES_Type *base, const uint8_t *plaintext, uint8_t *ciphertext, size_t size, const uint8_t iv[AES_IV_SIZE])
641 {
642 return aes_block_mode(base, plaintext, ciphertext, size, iv, kAES_CfgCryptOfb);
643 }
644
645 /*!
646 * brief Decrypts AES using OFB block mode.
647 *
648 * param base AES peripheral base address
649 * param ciphertext Input cipher text to decrypt
650 * param[out] plaintext Output plain text
651 * param size Size of input and output data in bytes.
652 * param iv Input Initial vector to be used as the first input block.
653 * return Status from decrypt operation
654 */
AES_DecryptOfb(AES_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,size_t size,const uint8_t iv[AES_IV_SIZE])655 status_t AES_DecryptOfb(
656 AES_Type *base, const uint8_t *ciphertext, uint8_t *plaintext, size_t size, const uint8_t iv[AES_IV_SIZE])
657 {
658 return aes_block_mode(base, ciphertext, plaintext, size, iv, kAES_CfgCryptOfb);
659 }
660
661 /*!
662 * brief Encrypts or decrypts AES using CTR block mode.
663 *
664 * Encrypts or decrypts AES using CTR block mode.
665 * AES CTR mode uses only forward AES cipher and same algorithm for encryption and decryption.
666 * The only difference between encryption and decryption is that, for encryption, the input argument
667 * is plain text and the output argument is cipher text. For decryption, the input argument is cipher text
668 * and the output argument is plain text.
669 *
670 * param base AES peripheral base address
671 * param input Input data for CTR block mode
672 * param[out] output Output data for CTR block mode
673 * param size Size of input and output data in bytes
674 * param[in,out] counter Input counter (updates on return)
675 * param[out] counterlast Output cipher of last counter, for chained CTR calls. NULL can be passed if chained calls are
676 * not used.
677 * param[out] szLeft Output number of bytes in left unused in counterlast block. NULL can be passed if chained calls
678 * are not used.
679 * return Status from crypt operation
680 */
AES_CryptCtr(AES_Type * base,const uint8_t * input,uint8_t * output,size_t size,uint8_t counter[AES_BLOCK_SIZE],uint8_t counterlast[AES_BLOCK_SIZE],size_t * szLeft)681 status_t AES_CryptCtr(AES_Type *base,
682 const uint8_t *input,
683 uint8_t *output,
684 size_t size,
685 uint8_t counter[AES_BLOCK_SIZE],
686 uint8_t counterlast[AES_BLOCK_SIZE],
687 size_t *szLeft)
688 {
689 status_t status;
690 uint32_t lastSize;
691 uint8_t lastBlock[AES_BLOCK_SIZE] = {0};
692 uint8_t *lastEncryptedCounter;
693
694 /* Check the key is valid */
695 status = aes_check_key_valid(base);
696 if (status != kStatus_Success)
697 {
698 return status;
699 }
700
701 /*5. Select the required crypto operation (encryption/decryption/hash) and AES mode in the CFG register.*/
702 *(volatile uint8_t *)((uint32_t)base) = (uint8_t)kAES_CfgSwap;
703 *(volatile uint16_t *)(((uint32_t)base + 2u)) = (uint16_t)kAES_CfgCryptCtr;
704 aes_set_forward(base);
705
706 /* For CBC, CFB and OFB modes write the Initialization Vector (IV) in the HOLDING
707 [3:0] registers. For CTR mode write the initial counter value in the HOLDING [3:0]
708 registers. */
709 aes_set_holding(base, counter);
710
711 /* set counter increment by one */
712 base->CTR_INCR = 0x1U;
713
714 /* Split the size into full 16-byte chunks and last incomplete block */
715 lastSize = 0U;
716 if (size <= 16U)
717 {
718 lastSize = size;
719 size = 0U;
720 }
721 else
722 {
723 /* Process all 16-byte data chunks. */
724 lastSize = size % 16U;
725 if (lastSize == 0U)
726 {
727 lastSize = 16U;
728 size -= 16U;
729 }
730 else
731 {
732 size -= lastSize; /* size will be rounded down to 16 byte boundary. remaining bytes in lastSize */
733 }
734 }
735
736 /* full 16-byte blocks */
737 while (size != 0U)
738 {
739 aes_one_block(base, output, input);
740 size -= 16u;
741 input += 16;
742 output += 16;
743 }
744
745 /* last block */
746 if (counterlast != NULL)
747 {
748 lastEncryptedCounter = counterlast;
749 }
750 else
751 {
752 lastEncryptedCounter = lastBlock;
753 }
754 aes_one_block(base, lastEncryptedCounter, lastBlock); /* lastBlock is all zeroes, so I get directly ECB of the last
755 counter, as the XOR with zeroes doesn't change */
756
757 /* remain output = input XOR counterlast */
758 for (uint32_t i = 0; i < lastSize; i++)
759 {
760 output[i] = input[i] ^ lastEncryptedCounter[i];
761 }
762
763 /* read counter value after last encryption */
764 aes_set_unaligned_from_word(swap_bytes(base->HOLDING[3]), &counter[12]);
765 aes_gcm_dec32(&counter[0]); /* TODO HW problem? (first time it increments HOLDING3 twice) */
766
767 if (szLeft != NULL)
768 {
769 *szLeft = 16U - lastSize;
770 }
771
772 return status;
773 }
774
775 /*!
776 * @brief AES write input to INTEXT registers.
777 *
778 * This function writes input 16-byte data to AES INTEXT registers
779 * and wait for the engine Idle.
780 *
781 * @param base AES peripheral base address.
782 * @param input 16-byte input data.
783 */
aes_gcm_one_block_input_only(AES_Type * base,const uint8_t * input)784 static void aes_gcm_one_block_input_only(AES_Type *base, const uint8_t *input)
785 {
786 int index;
787 uint32_t aesStat;
788
789 /* If the IN_READY bit in STAT register is 1, write the input text in the INTEXT [3:0]
790 registers. */
791 index = 0;
792 while (index < 4)
793 {
794 aesStat = base->STAT;
795
796 if (0U != (aesStat & AES_STAT_IN_READY_MASK))
797 {
798 base->INTEXT[index] = aes_get_word_from_unaligned(input);
799 input += sizeof(uint32_t);
800 index++;
801 }
802 }
803
804 while (0U == (base->STAT & AES_STAT_IDLE_MASK))
805 {
806 }
807 }
808
809 /*!
810 * @brief AES execute command.
811 *
812 * This function issues command to AES CMD register.
813 *
814 * @param base AES peripheral base address.
815 * @param cmdMask Bit mask for the command to be issued.
816 */
aes_command(AES_Type * base,uint32_t cmdMask)817 static void aes_command(AES_Type *base, uint32_t cmdMask)
818 {
819 base->CMD = cmdMask;
820 /* wait for Idle */
821 while (0U == (base->STAT & AES_STAT_IDLE_MASK))
822 {
823 }
824 base->CMD = 0;
825 }
826
827 /*!
828 * @brief AES read GCM_TAG.
829 *
830 * This function reads data from GCM_TAG registers.
831 *
832 * @param base AES peripheral base address.
833 * @param output 16 byte memory to write the GCM_TAG to.
834 */
aes_gcm_get_tag(AES_Type * base,uint8_t * output)835 static void aes_gcm_get_tag(AES_Type *base, uint8_t *output)
836 {
837 int index;
838
839 for (index = 0; index < 4; index++)
840 {
841 aes_set_unaligned_from_word(swap_bytes(base->GCM_TAG[index]), output);
842 output += sizeof(uint32_t);
843 }
844 }
845
846 /*!
847 * @brief AES GCM check validity of input arguments.
848 *
849 * This function checks the validity of input arguments.
850 *
851 * @param base AES peripheral base address.
852 * @param src Source address (plaintext or ciphertext).
853 * @param iv Initialization vector address.
854 * @param aad Additional authenticated data address.
855 * @param dst Destination address (plaintext or ciphertext).
856 * @param inputSize Size of input (same size as output) data in bytes.
857 * @param ivSize Size of Initialization vector in bytes.
858 * @param aadSize Size of additional data in bytes.
859 * @param tagSize Size of the GCM tag in bytes.
860 */
aes_gcm_check_input_args(AES_Type * base,const uint8_t * src,const uint8_t * iv,const uint8_t * aad,uint8_t * dst,size_t inputSize,size_t ivSize,size_t aadSize,size_t tagSize)861 static status_t aes_gcm_check_input_args(AES_Type *base,
862 const uint8_t *src,
863 const uint8_t *iv,
864 const uint8_t *aad,
865 uint8_t *dst,
866 size_t inputSize,
867 size_t ivSize,
868 size_t aadSize,
869 size_t tagSize)
870 {
871 if (base == NULL)
872 {
873 return kStatus_InvalidArgument;
874 }
875
876 /* tag can be NULL to skip tag processing */
877 if (((ivSize != 0U) && (NULL == iv)) || ((aadSize != 0U) && (NULL == aad)) ||
878 ((inputSize != 0U) && ((NULL == src) || (NULL == dst))))
879 {
880 return kStatus_InvalidArgument;
881 }
882
883 /* octet length of tag (tagSize) must be element of 4,8,12,13,14,15,16 */
884 if (((tagSize > 16u) || (tagSize < 12u)) && (tagSize != 4u) && (tagSize != 8u))
885 {
886 return kStatus_InvalidArgument;
887 }
888
889 /* no IV AAD DATA makes no sense */
890 if (0U == (inputSize + ivSize + aadSize))
891 {
892 return kStatus_InvalidArgument;
893 }
894
895 /* check length of input strings. This is more strict than the GCM specificaiton due to 32-bit architecture.
896 * The API interface would work on 64-bit architecture as well, but as it has not been tested, let it limit to
897 * 32-bits.
898 */
899 if (!((ivSize >= 1u) && (sizeof(size_t) <= 4u)))
900 {
901 return kStatus_InvalidArgument;
902 }
903
904 return kStatus_Success;
905 }
906
907 /*!
908 * @brief Increment a 16 byte integer.
909 *
910 * This function increments by one a 16 byte integer.
911 *
912 * @param input Pointer to a 16 byte integer to be incremented by one.
913 */
aes_gcm_incr32(uint8_t * input)914 static void aes_gcm_incr32(uint8_t *input)
915 {
916 int i = 15;
917 while (input[i] == (uint8_t)0xFFu)
918 {
919 input[i] = (uint8_t)0x00u;
920 i--;
921 if (i < 0)
922 {
923 return;
924 }
925 }
926
927 if (i >= 0)
928 {
929 input[i] += (uint8_t)1u;
930 }
931 }
932
933 /*!
934 * @brief Decrement a 16 byte integer.
935 *
936 * This function decrements by one a 16 byte integer.
937 *
938 * @param input Pointer to a 16 byte integer to be decremented by one.
939 */
aes_gcm_dec32(uint8_t * input)940 static void aes_gcm_dec32(uint8_t *input)
941 {
942 int i = 15;
943 while (input[i] == (uint8_t)0x00u)
944 {
945 input[i] = (uint8_t)0xFFu;
946 i--;
947 if (i < 0)
948 {
949 return;
950 }
951 }
952
953 if (i >= 0)
954 {
955 input[i] -= (uint8_t)1u;
956 }
957 }
958
959 /*!
960 * @brief AES read GF128_Z registers.
961 *
962 * This function reads AES module GF128_Z registers.
963 *
964 * @param base AES peripheral base address.
965 * @param input Pointer to a 16 byte integer to write the GF128_Z value to.
966 */
aes_get_gf128(AES_Type * base,uint8_t * output)967 static void aes_get_gf128(AES_Type *base, uint8_t *output)
968 {
969 int i;
970 for (i = 0; i < 4; i++)
971 {
972 aes_set_unaligned_from_word(swap_bytes(base->GF128_Z[i]), output);
973 output += sizeof(uint32_t);
974 }
975 }
976
977 /*!
978 * @brief GCM process.
979 *
980 * This function is the main function for AES GCM encryption/decryption and tag generation/comparison.
981 *
982 * @param base AES peripheral base address.
983 * @param encryptMode Whether the actual operation is an encryption or a decryption.
984 * @param src Input plaintext for encryption or ciphertext for decryption.
985 * @param inputSize Size of input and output in bytes.
986 * @param iv Input initial vector.
987 * @param ivSize Size of initial vector in bytes.
988 * @param aad Additional authenticated data.
989 * @param aadSize Size of additional authenticated data in bytes.
990 * @param dst Output ciphertext for encryption or plaintext for decryption.
991 * @param tag For encryption, GCM tag output. For decryption, GCM tag input for comparison.
992 * @param tagSize Size of the GCM tag in bytes.
993 */
aes_gcm_process(AES_Type * base,aes_encryption_decryption_mode_t encryptMode,const uint8_t * src,size_t inputSize,const uint8_t * iv,size_t ivSize,const uint8_t * aad,size_t aadSize,uint8_t * dst,uint8_t * tag,size_t tagSize)994 static status_t aes_gcm_process(AES_Type *base,
995 aes_encryption_decryption_mode_t encryptMode,
996 const uint8_t *src,
997 size_t inputSize,
998 const uint8_t *iv,
999 size_t ivSize,
1000 const uint8_t *aad,
1001 size_t aadSize,
1002 uint8_t *dst,
1003 uint8_t *tag,
1004 size_t tagSize)
1005 {
1006 status_t status;
1007 uint8_t blkZero[16] = {0};
1008 uint8_t blkJ0[16] = {0};
1009 uint8_t blkTag[16] = {0};
1010 uint32_t saveSize;
1011 uint32_t saveAadSize;
1012 uint32_t saveIvSize;
1013 uint8_t lastBlock[AES_BLOCK_SIZE] = {0};
1014
1015 status = aes_gcm_check_input_args(base, src, iv, aad, dst, inputSize, ivSize, aadSize, tagSize);
1016 if (status != kStatus_Success)
1017 {
1018 return status;
1019 }
1020
1021 status = aes_check_key_valid(base);
1022 if (status != kStatus_Success)
1023 {
1024 return status;
1025 }
1026
1027 saveSize = inputSize;
1028 saveAadSize = aadSize;
1029 saveIvSize = ivSize;
1030
1031 /* 1. Let H = CIPHK(0_128). */
1032 *(volatile uint8_t *)((uint32_t)base) = (uint8_t)
1033 kAES_CfgIntextSwap; /* do not swap OUTTEXT, as OUTTEXT is copied for further use into GF128_Y register */
1034 *(volatile uint16_t *)(((uint32_t)base + 2u)) = (uint16_t)kAES_CfgEncryptEcb;
1035
1036 /* make sure AES is set to forward mode */
1037 aes_set_forward(base);
1038
1039 /* move 128-bit zeroes to INTEXT */
1040 aes_gcm_one_block_input_only(base, blkZero);
1041
1042 /* set COPY_TO_Y command */
1043 aes_command(base, AES_CMD_COPY_TO_Y(1));
1044
1045 if (ivSize != 12u)
1046 {
1047 /* if ivSize is not 12 bytes, we have to compute GF128 hash to get the initial counter J0 */
1048 uint8_t ivBlkZero[16] = {0};
1049
1050 *(volatile uint8_t *)((uint32_t)base) = (uint8_t)kAES_CfgSwapIntextHashIn;
1051 while (ivSize >= 16u)
1052 {
1053 aes_gcm_one_block_input_only(base, iv);
1054 iv += 16;
1055 ivSize -= 16u;
1056 }
1057 if (ivSize != 0U)
1058 {
1059 (void)aes_memcpy(ivBlkZero, iv, ivSize);
1060 aes_gcm_one_block_input_only(base, ivBlkZero);
1061 }
1062
1063 (void)aes_memcpy(ivBlkZero, blkZero, 16);
1064 aes_set_unaligned_from_word(swap_bytes(8U * saveIvSize), &ivBlkZero[12]);
1065 aes_gcm_one_block_input_only(base, ivBlkZero);
1066
1067 aes_get_gf128(base, blkJ0);
1068 aes_gcm_incr32(blkJ0);
1069
1070 /* put back the hash sub-key. this will abort running GF128, because we have to start new GF128 again for AAD
1071 * and C */
1072 *(volatile uint8_t *)((uint32_t)base) = (uint8_t)
1073 kAES_CfgIntextSwap; /* do not swap OUTTEXT, as OUTTEXT is copied for further use into GF128_Y register */
1074 *(volatile uint16_t *)(((uint32_t)base + 2u)) = (uint16_t)kAES_CfgEncryptEcb;
1075 aes_gcm_one_block_input_only(base, blkZero);
1076 aes_command(base, AES_CMD_COPY_TO_Y(1));
1077 }
1078 else
1079 {
1080 (void)aes_memcpy(blkJ0, iv, 12);
1081 blkJ0[15] = 0x02U; /* add one to Counter for the first encryption with plaintext - see GCM specification */
1082 }
1083
1084 /* process all AAD as GF128 of INTEXT, pad to full 16-bytes block with zeroes */
1085 if (aadSize != 0U)
1086 {
1087 *(volatile uint8_t *)((uint32_t)base) = (uint8_t)kAES_CfgSwapIntextHashIn;
1088 while (aadSize >= 16u)
1089 {
1090 aes_gcm_one_block_input_only(base, aad);
1091 aad += 16;
1092 aadSize -= 16u;
1093 }
1094 if (aadSize != 0U)
1095 {
1096 uint8_t aadBlkZero[16] = {0};
1097 (void)aes_memcpy(aadBlkZero, aad, aadSize);
1098 aes_gcm_one_block_input_only(base, aadBlkZero);
1099 }
1100 }
1101
1102 /* switch to EnryptDecryptHash, Hash of OUTTEXT, EncryptDecrypt in GCM mode */
1103 /* Process all plaintext, pad to full 16-bytes block with zeroes */
1104 if (encryptMode == kAES_ModeEncrypt)
1105 {
1106 *(volatile uint8_t *)((uint32_t)base) =
1107 (uint8_t)kAES_CfgSwapEnDecHashOut; /* Encrypt operation adds output to hash */
1108 }
1109 else
1110 {
1111 *(volatile uint8_t *)((uint32_t)base) =
1112 (uint8_t)kAES_CfgSwapEnDecHashIn; /* Decrypt operation adds input to hash */
1113 }
1114
1115 *(volatile uint16_t *)(((uint32_t)base + 2u)) = (uint16_t) /*kAES_CfgCryptGcmTag*/ kAES_CfgCryptCtr;
1116
1117 aes_set_holding(base, blkJ0);
1118
1119 /* set counter increment by one */
1120 base->CTR_INCR = 0x1U;
1121
1122 if (inputSize != 0U)
1123 {
1124 /* full 16-byte blocks */
1125 while (inputSize >= 16u)
1126 {
1127 aes_one_block(base, dst, src);
1128 inputSize -= 16u;
1129 src += 16;
1130 dst += 16;
1131 }
1132 /* last incomplete block. output shall be padded. */
1133 if (inputSize != 0U)
1134 {
1135 if (encryptMode == kAES_ModeEncrypt)
1136 {
1137 uint8_t outputBlkZero[16] = {0};
1138
1139 /* I need to pad ciphertext, so I turn off the hash, and after I have ciphertext, I pad it with zeroes
1140 * and hash manually */
1141 *(volatile uint8_t *)((uint32_t)base) = (uint8_t)kAES_CfgSwap;
1142 (void)aes_memcpy(lastBlock, src, inputSize);
1143 aes_one_block(base, lastBlock, lastBlock);
1144 (void)aes_memcpy(dst, lastBlock, inputSize);
1145 /* pad the last output block with zeroes and add it to GF128 hash */
1146 (void)aes_memcpy(outputBlkZero, lastBlock, inputSize);
1147 *(volatile uint8_t *)((uint32_t)base) = (uint8_t)kAES_CfgSwapIntextHashIn;
1148 aes_gcm_one_block_input_only(base, outputBlkZero);
1149 }
1150 else
1151 {
1152 (void)aes_memcpy(lastBlock, src, inputSize);
1153 aes_one_block(base, lastBlock, lastBlock);
1154 (void)aes_memcpy(dst, lastBlock, inputSize);
1155 }
1156 }
1157 }
1158
1159 /* Process AAD len plus Ciphertext len */
1160 *(volatile uint8_t *)((uint32_t)base) = (uint8_t)kAES_CfgIntextSwap;
1161 *(volatile uint16_t *)(((uint32_t)base + 2u)) = (uint16_t)kAES_CfgEncryptEcb;
1162 aes_gcm_dec32(blkJ0);
1163 aes_gcm_one_block_input_only(base, blkJ0);
1164 *(volatile uint8_t *)((uint32_t)base) = (uint8_t)kAES_CfgSwapIntextHashIn;
1165 if (saveSize != 0U)
1166 {
1167 aes_set_unaligned_from_word(swap_bytes(saveSize * 8u), &blkZero[12]);
1168 }
1169 if (saveAadSize != 0U)
1170 {
1171 aes_set_unaligned_from_word(swap_bytes(saveAadSize * 8u), &blkZero[4]);
1172 }
1173 aes_gcm_one_block_input_only(base, blkZero); /* len(A) || len(C) */
1174 aes_gcm_get_tag(base, blkTag);
1175
1176 if ((tag != NULL) && (tagSize != 0U))
1177 {
1178 if (encryptMode == kAES_ModeEncrypt)
1179 {
1180 (void)aes_memcpy(tag, blkTag, tagSize);
1181 }
1182 else
1183 {
1184 size_t i = 0;
1185 uint32_t equal = 0;
1186 uint32_t chXor;
1187
1188 while (i < tagSize)
1189 {
1190 chXor = ((uint32_t)tag[i] ^ (uint32_t)blkTag[i]);
1191 equal |= chXor;
1192 i++;
1193 }
1194
1195 if (equal != 0U)
1196 {
1197 status = kStatus_Fail;
1198 }
1199 }
1200 }
1201
1202 return status;
1203 }
1204
1205 /*!
1206 * brief Encrypts AES and tags using GCM block mode.
1207 *
1208 * Encrypts AES and optionally tags using GCM block mode. If plaintext is NULL, only the GHASH is calculated and output
1209 * in the 'tag' field.
1210 *
1211 * param base AES peripheral base address
1212 * param plaintext Input plain text to encrypt
1213 * param[out] ciphertext Output cipher text.
1214 * param size Size of input and output data in bytes
1215 * param iv Input initial vector
1216 * param ivSize Size of the IV
1217 * param aad Input additional authentication data
1218 * param aadSize Input size in bytes of AAD
1219 * param[out] tag Output hash tag. Set to NULL to skip tag processing.
1220 * param tagSize Input size of the tag to generate, in bytes. Must be 4,8,12,13,14,15 or 16.
1221 * return Status from encrypt operation
1222 */
AES_EncryptTagGcm(AES_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,size_t size,const uint8_t * iv,size_t ivSize,const uint8_t * aad,size_t aadSize,uint8_t * tag,size_t tagSize)1223 status_t AES_EncryptTagGcm(AES_Type *base,
1224 const uint8_t *plaintext,
1225 uint8_t *ciphertext,
1226 size_t size,
1227 const uint8_t *iv,
1228 size_t ivSize,
1229 const uint8_t *aad,
1230 size_t aadSize,
1231 uint8_t *tag,
1232 size_t tagSize)
1233 {
1234 status_t status;
1235 status =
1236 aes_gcm_process(base, kAES_ModeEncrypt, plaintext, size, iv, ivSize, aad, aadSize, ciphertext, tag, tagSize);
1237 return status;
1238 }
1239
1240 /*!
1241 * brief Decrypts AES and authenticates using GCM block mode.
1242 *
1243 * Decrypts AES and optionally authenticates using GCM block mode. If ciphertext is NULL, only the GHASH is calculated
1244 * and compared with the received GHASH in 'tag' field.
1245 *
1246 * param base AES peripheral base address
1247 * param ciphertext Input cipher text to decrypt
1248 * param[out] plaintext Output plain text.
1249 * param size Size of input and output data in bytes
1250 * param iv Input initial vector
1251 * param ivSize Size of the IV
1252 * param aad Input additional authentication data
1253 * param aadSize Input size in bytes of AAD
1254 * param tag Input hash tag to compare. Set to NULL to skip tag processing.
1255 * param tagSize Input size of the tag, in bytes. Must be 4, 8, 12, 13, 14, 15, or 16.
1256 * return Status from decrypt operation
1257 */
AES_DecryptTagGcm(AES_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,size_t size,const uint8_t * iv,size_t ivSize,const uint8_t * aad,size_t aadSize,const uint8_t * tag,size_t tagSize)1258 status_t AES_DecryptTagGcm(AES_Type *base,
1259 const uint8_t *ciphertext,
1260 uint8_t *plaintext,
1261 size_t size,
1262 const uint8_t *iv,
1263 size_t ivSize,
1264 const uint8_t *aad,
1265 size_t aadSize,
1266 const uint8_t *tag,
1267 size_t tagSize)
1268 {
1269 uint8_t temp_tag[16] = {0}; /* max. octet length of MAC (tag) is 16 */
1270 uint8_t *tag_ptr;
1271 status_t status;
1272
1273 tag_ptr = NULL;
1274 if (tag != NULL)
1275 {
1276 (void)aes_memcpy(temp_tag, tag, tagSize);
1277 tag_ptr = &temp_tag[0];
1278 }
1279
1280 status = aes_gcm_process(base, kAES_ModeDecrypt, ciphertext, size, iv, ivSize, aad, aadSize, plaintext, tag_ptr,
1281 tagSize);
1282 return status;
1283 }
1284