1 /*!
2     \file    gd32l23x_cau_aes.c
3     \brief   CAU AES driver
4 
5     \version 2021-08-04, V1.0.0, firmware for GD32L23x
6     \version 2021-08-12, V1.0.1, firmware for GD32L23x
7 */
8 
9 /*
10     Copyright (c) 2021, GigaDevice Semiconductor Inc.
11 
12     Redistribution and use in source and binary forms, with or without modification,
13 are permitted provided that the following conditions are met:
14 
15     1. Redistributions of source code must retain the above copyright notice, this
16        list of conditions and the following disclaimer.
17     2. Redistributions in binary form must reproduce the above copyright notice,
18        this list of conditions and the following disclaimer in the documentation
19        and/or other materials provided with the distribution.
20     3. Neither the name of the copyright holder nor the names of its contributors
21        may be used to endorse or promote products derived from this software without
22        specific prior written permission.
23 
24     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
33 OF SUCH DAMAGE.
34 */
35 
36 #include "gd32l23x_cau.h"
37 #include <string.h>
38 
39 #define AESBSY_TIMEOUT    ((uint32_t)0x00010000U)
40 #define BLOCK_B0_MASK     ((uint8_t)0x07U)
41 #define BLOCK_DATA_SIZE   16U
42 #define MAX_CCM_IV_SIZE   15U
43 
44 /* configure AES key structure parameter */
45 static void cau_aes_key_config(uint8_t *key, uint32_t keysize, cau_key_parameter_struct *cau_key_initpara);
46 /* fill data into data input register */
47 static ErrStatus cau_fill_data(uint8_t *input, uint32_t in_length);
48 /* AES calculate process */
49 static ErrStatus cau_aes_calculate(uint8_t *input, uint32_t in_length, uint8_t *output);
50 
51 /*!
52     \brief      encrypt and decrypt using AES in ECB mode
53     \param[in]  cau_parameter: pointer to the input structure
54                   alg_dir: algorithm dirctory
55                     CAU_ENCRYPT, CAU_DECRYPT
56                   key: key
57                   key_size: key size in bits, must be either 128, 192 or 256
58                   input: input data
59                   in_length: input data length in bytes, must be a multiple of 16 bytes
60     \param[out] output: pointer to the returned buffer
61     \retval     ErrStatus: SUCCESS or ERROR
62 */
cau_aes_ecb(cau_parameter_struct * cau_parameter,uint8_t * output)63 ErrStatus cau_aes_ecb(cau_parameter_struct *cau_parameter, uint8_t *output)
64 {
65     ErrStatus ret = ERROR;
66     cau_key_parameter_struct key_initpara;
67     __IO uint32_t counter = 0U;
68     uint32_t busystatus = 0U;
69 
70     /* key structure initialization */
71     cau_key_struct_para_init(&key_initpara);
72     /* AES key structure parameter config */
73     cau_aes_key_config(cau_parameter->key, cau_parameter->key_size, &key_initpara);
74     /* key initialization */
75     cau_key_init(&key_initpara);
76 
77     /* AES decryption */
78     if(CAU_DECRYPT == cau_parameter->alg_dir) {
79         /* flush the IN and OUT FIFOs */
80         cau_fifo_flush();
81         /* initialize the CAU peripheral */
82         cau_init(CAU_DECRYPT, CAU_MODE_AES_KEY, CAU_SWAPPING_32BIT);
83 
84         /* enable the CAU peripheral */
85         cau_enable();
86 
87         /* wait until the busy flag is RESET */
88         do {
89             busystatus = cau_flag_get(CAU_FLAG_BUSY);
90             counter++;
91         } while((AESBSY_TIMEOUT != counter) && (RESET != busystatus));
92 
93         if(RESET != busystatus) {
94             return ERROR;
95         }
96     }
97 
98     /* initialize the CAU peripheral */
99     cau_init(cau_parameter->alg_dir, CAU_MODE_AES_ECB, CAU_SWAPPING_8BIT);
100 
101     /* flush the IN and OUT FIFOs */
102     cau_fifo_flush();
103 
104     /* enable the CAU peripheral */
105     cau_enable();
106     /* AES calculate process */
107     ret = cau_aes_calculate(cau_parameter->input, cau_parameter->in_length, output);
108     /* disable the CAU peripheral */
109     cau_disable();
110 
111     return ret;
112 }
113 
114 /*!
115     \brief      encrypt and decrypt using AES in CBC mode
116     \param[in]  cau_parameter: pointer to the input structure
117                   alg_dir: algorithm dirctory
118                     CAU_ENCRYPT, CAU_DECRYPT
119                   key: key
120                   key_size: key size in bits, must be either 128, 192 or 256
121                   iv: initialization vector, 16 bytes
122                   input: input data
123                   in_length: input data length in bytes, must be a multiple of 16 bytes
124     \param[out] output: pointer to the returned buffer
125     \retval     ErrStatus: SUCCESS or ERROR
126 */
cau_aes_cbc(cau_parameter_struct * cau_parameter,uint8_t * output)127 ErrStatus cau_aes_cbc(cau_parameter_struct *cau_parameter, uint8_t *output)
128 {
129     ErrStatus ret = ERROR;
130     cau_key_parameter_struct key_initpara;
131     cau_iv_parameter_struct iv_initpara;
132     __IO uint32_t counter = 0U;
133     uint32_t busystatus = 0U;
134 
135     uint32_t ivaddr = (uint32_t)cau_parameter->iv;
136 
137     /* key structure initialization */
138     cau_key_struct_para_init(&key_initpara);
139     /* AES key structure parameter config */
140     cau_aes_key_config(cau_parameter->key, cau_parameter->key_size, &key_initpara);
141     /* key initialization */
142     cau_key_init(&key_initpara);
143 
144     /* AES decryption */
145     if(CAU_DECRYPT == cau_parameter->alg_dir) {
146         /* flush the IN and OUT FIFOs */
147         cau_fifo_flush();
148         /* initialize the CAU peripheral */
149         cau_init(CAU_DECRYPT, CAU_MODE_AES_KEY, CAU_SWAPPING_32BIT);
150 
151         /* enable the CAU peripheral */
152         cau_enable();
153 
154         /* wait until the busy flag is RESET */
155         do {
156             busystatus = cau_flag_get(CAU_FLAG_BUSY);
157             counter++;
158         } while((AESBSY_TIMEOUT != counter) && (RESET != busystatus));
159 
160         if(RESET != busystatus) {
161             return ERROR;
162         }
163     }
164 
165     /* initialize the CAU peripheral */
166     cau_init(cau_parameter->alg_dir, CAU_MODE_AES_CBC, CAU_SWAPPING_8BIT);
167 
168     /* vectors initialization */
169     iv_initpara.iv_0_high = __REV(*(uint32_t *)(ivaddr));
170     ivaddr += 4U;
171     iv_initpara.iv_0_low = __REV(*(uint32_t *)(ivaddr));
172     ivaddr += 4U;
173     iv_initpara.iv_1_high = __REV(*(uint32_t *)(ivaddr));
174     ivaddr += 4U;
175     iv_initpara.iv_1_low = __REV(*(uint32_t *)(ivaddr));
176     cau_iv_init(&iv_initpara);
177 
178     /* flush the IN and OUT FIFOs */
179     cau_fifo_flush();
180 
181     /* enable the CAU peripheral */
182     cau_enable();
183     /* AES calculate process */
184     ret = cau_aes_calculate(cau_parameter->input, cau_parameter->in_length, output);
185     /* disable the CAU peripheral */
186     cau_disable();
187 
188     return ret;
189 }
190 
191 /*!
192     \brief      encrypt and decrypt using AES in CTR mode
193     \param[in]  cau_parameter: pointer to the input structure
194                   alg_dir: algorithm dirctory
195                     CAU_ENCRYPT, CAU_DECRYPT
196                   key: key
197                   key_size: key size in bits, must be either 128, 192 or 256
198                   iv: initialization vector, 16 bytes
199                   input: input data
200                   in_length: input data length in bytes, must be a multiple of 16 bytes
201     \param[out] output: pointer to the returned buffer
202     \retval     ErrStatus: SUCCESS or ERROR
203 */
cau_aes_ctr(cau_parameter_struct * cau_parameter,uint8_t * output)204 ErrStatus cau_aes_ctr(cau_parameter_struct *cau_parameter, uint8_t *output)
205 {
206     ErrStatus ret = ERROR;
207     cau_key_parameter_struct key_initpara;
208     cau_iv_parameter_struct iv_initpara;
209     uint32_t ivaddr = (uint32_t)cau_parameter->iv;
210 
211     /* key structure initialization */
212     cau_key_struct_para_init(&key_initpara);
213     /* initialize the CAU peripheral */
214     cau_init(cau_parameter->alg_dir, CAU_MODE_AES_CTR, CAU_SWAPPING_8BIT);
215 
216     /* AES key structure parameter config */
217     cau_aes_key_config(cau_parameter->key, cau_parameter->key_size, &key_initpara);
218     /* key initialization */
219     cau_key_init(&key_initpara);
220 
221     /* vectors initialization */
222     iv_initpara.iv_0_high = __REV(*(uint32_t *)(ivaddr));
223     ivaddr += 4U;
224     iv_initpara.iv_0_low = __REV(*(uint32_t *)(ivaddr));
225     ivaddr += 4U;
226     iv_initpara.iv_1_high = __REV(*(uint32_t *)(ivaddr));
227     ivaddr += 4U;
228     iv_initpara.iv_1_low = __REV(*(uint32_t *)(ivaddr));
229     cau_iv_init(&iv_initpara);
230 
231     /* flush the IN and OUT FIFOs */
232     cau_fifo_flush();
233 
234     /* enable the CAU peripheral */
235     cau_enable();
236     /* AES calculate process */
237     ret = cau_aes_calculate(cau_parameter->input, cau_parameter->in_length, output);
238     /* disable the CAU peripheral */
239     cau_disable();
240 
241     return ret;
242 }
243 
244 /*!
245     \brief      encrypt and decrypt using AES in CFB mode
246     \param[in]  cau_parameter: pointer to the input structure
247                   alg_dir: algorithm dirctory
248                     CAU_ENCRYPT, CAU_DECRYPT
249                   key: key
250                   key_size: key size in bits, must be either 128, 192 or 256
251                   iv: initialization vector, 16 bytes
252                   input: input data
253                   in_length: input data length in bytes, must be a multiple of 16 bytes
254     \param[out] output: pointer to the returned buffer
255     \retval     ErrStatus: SUCCESS or ERROR
256 */
cau_aes_cfb(cau_parameter_struct * cau_parameter,uint8_t * output)257 ErrStatus cau_aes_cfb(cau_parameter_struct *cau_parameter, uint8_t *output)
258 {
259     ErrStatus ret = ERROR;
260     cau_key_parameter_struct key_initpara;
261     cau_iv_parameter_struct iv_initpara;
262     uint32_t ivaddr = (uint32_t)cau_parameter->iv;
263 
264     /* key structure initialization */
265     cau_key_struct_para_init(&key_initpara);
266     /* initialize the CAU peripheral */
267     cau_init(cau_parameter->alg_dir, CAU_MODE_AES_CFB, CAU_SWAPPING_8BIT);
268 
269     /* AES key structure parameter config */
270     cau_aes_key_config(cau_parameter->key, cau_parameter->key_size, &key_initpara);
271     /* key initialization */
272     cau_key_init(&key_initpara);
273 
274     /* vectors initialization */
275     iv_initpara.iv_0_high = __REV(*(uint32_t *)(ivaddr));
276     ivaddr += 4U;
277     iv_initpara.iv_0_low = __REV(*(uint32_t *)(ivaddr));
278     ivaddr += 4U;
279     iv_initpara.iv_1_high = __REV(*(uint32_t *)(ivaddr));
280     ivaddr += 4U;
281     iv_initpara.iv_1_low = __REV(*(uint32_t *)(ivaddr));
282     cau_iv_init(&iv_initpara);
283 
284     /* flush the IN and OUT FIFOs */
285     cau_fifo_flush();
286     /* enable the CAU peripheral */
287     cau_enable();
288     /* AES calculate process */
289     ret = cau_aes_calculate(cau_parameter->input, cau_parameter->in_length, output);
290     /* disable the CAU peripheral */
291     cau_disable();
292 
293     return ret;
294 }
295 
296 /*!
297     \brief      encrypt and decrypt using AES in OFB mode
298     \param[in]  cau_parameter: pointer to the input structure
299                   alg_dir: algorithm dirctory
300                     CAU_ENCRYPT, CAU_DECRYPT
301                   key: key
302                   key_size: key size in bits, must be either 128, 192 or 256
303                   iv: initialization vector, 16 bytes
304                   input: input data
305                   in_length: input data length in bytes, must be a multiple of 16 bytes
306     \param[out] output: pointer to the returned buffer
307     \retval     ErrStatus: SUCCESS or ERROR
308 */
cau_aes_ofb(cau_parameter_struct * cau_parameter,uint8_t * output)309 ErrStatus cau_aes_ofb(cau_parameter_struct *cau_parameter, uint8_t *output)
310 {
311     ErrStatus ret = ERROR;
312     cau_key_parameter_struct key_initpara;
313     cau_iv_parameter_struct iv_initpara;
314     uint32_t ivaddr = (uint32_t)cau_parameter->iv;
315 
316     /* key structure initialization */
317     cau_key_struct_para_init(&key_initpara);
318     /* initialize the CAU peripheral */
319     cau_init(cau_parameter->alg_dir, CAU_MODE_AES_OFB, CAU_SWAPPING_8BIT);
320 
321     /* AES key structure parameter config */
322     cau_aes_key_config(cau_parameter->key, cau_parameter->key_size, &key_initpara);
323     /* key initialization */
324     cau_key_init(&key_initpara);
325 
326     /* vectors initialization */
327     iv_initpara.iv_0_high = __REV(*(uint32_t *)(ivaddr));
328     ivaddr += 4U;
329     iv_initpara.iv_0_low = __REV(*(uint32_t *)(ivaddr));
330     ivaddr += 4U;
331     iv_initpara.iv_1_high = __REV(*(uint32_t *)(ivaddr));
332     ivaddr += 4U;
333     iv_initpara.iv_1_low = __REV(*(uint32_t *)(ivaddr));
334     cau_iv_init(&iv_initpara);
335 
336     /* flush the IN and OUT FIFOs */
337     cau_fifo_flush();
338     /* enable the CAU peripheral */
339     cau_enable();
340     /* AES calculate process */
341     ret = cau_aes_calculate(cau_parameter->input, cau_parameter->in_length, output);
342     /* disable the CAU peripheral */
343     cau_disable();
344 
345     return ret;
346 }
347 
348 /*!
349     \brief      encrypt and decrypt using AES in GCM mode
350     \param[in]  cau_parameter: pointer to the input structure
351                   alg_dir: algorithm dirctory
352                     CAU_ENCRYPT, CAU_DECRYPT
353                   key: key
354                   key_size: key size in bits, must be either 128, 192 or 256
355                   iv: initialization vector, 16 bytes
356                   input: input data
357                   in_length: input data length in bytes, must be a multiple of 16 bytes
358                   aad: additional authentication data
359                   aad_size: aad size in bytes, must be a multiple of 16 bytes
360     \param[out] output: pointer to the returned output data buffer
361     \param[out] tag: pointer to the returned tag buffer
362     \retval     ErrStatus: SUCCESS or ERROR
363 */
cau_aes_gcm(cau_parameter_struct * cau_parameter,uint8_t * output,uint8_t * tag)364 ErrStatus cau_aes_gcm(cau_parameter_struct *cau_parameter, uint8_t *output, uint8_t *tag)
365 {
366     ErrStatus ret = SUCCESS;
367     cau_key_parameter_struct key_initpara;
368     cau_iv_parameter_struct iv_initpara;
369     uint64_t aadlength = (uint64_t)cau_parameter->aad_size * 8U;
370     uint64_t inputlength = (uint64_t)cau_parameter->in_length * 8U;
371     uint32_t ivaddr = (uint32_t)cau_parameter->iv;
372     uint32_t tagaddr = (uint32_t)tag;
373 
374     /* key structure initialization */
375     cau_key_struct_para_init(&key_initpara);
376     /* initialize the CAU peripheral */
377     cau_init(cau_parameter->alg_dir, CAU_MODE_AES_GCM, CAU_SWAPPING_8BIT);
378 
379     /* AES key structure parameter config */
380     cau_aes_key_config(cau_parameter->key, cau_parameter->key_size, &key_initpara);
381     /* key initialization */
382     cau_key_init(&key_initpara);
383 
384     /* vectors initialization */
385     iv_initpara.iv_0_high = __REV(*(uint32_t *)(ivaddr));
386     ivaddr += 4U;
387     iv_initpara.iv_0_low = __REV(*(uint32_t *)(ivaddr));
388     ivaddr += 4U;
389     iv_initpara.iv_1_high = __REV(*(uint32_t *)(ivaddr));
390     ivaddr += 4U;
391     iv_initpara.iv_1_low = __REV(*(uint32_t *)(ivaddr));
392     cau_iv_init(&iv_initpara);
393 
394     /* prepare phase */
395     /* select prepare phase */
396     cau_phase_config(CAU_PREPARE_PHASE);
397     /* enable the CAU peripheral */
398     cau_enable();
399     /* wait for CAUEN bit to be 0 */
400     while(ENABLE == cau_enable_state_get()) {
401     }
402 
403     /* aad phase */
404     if((uint32_t)0U != cau_parameter->aad_size) {
405         /* select aad phase */
406         cau_phase_config(CAU_AAD_PHASE);
407         /* flush the IN and OUT FIFOs */
408         cau_fifo_flush();
409         /* enable the CAU peripheral */
410         cau_enable();
411 
412         ret = cau_fill_data(cau_parameter->aad, cau_parameter->aad_size);
413 
414         if(ERROR == ret) {
415             return ret;
416         }
417     }
418 
419     /* encrypt or dcrypt phase */
420     if((uint32_t)0U != cau_parameter->in_length) {
421         /* select encrypt or dcrypt phase */
422         cau_phase_config(CAU_ENCRYPT_DECRYPT_PHASE);
423         /* flush the IN and OUT FIFOs */
424         cau_fifo_flush();
425         /* enable the CAU peripheral */
426         cau_enable();
427 
428         /* AES calculate process */
429         ret = cau_aes_calculate(cau_parameter->input, cau_parameter->in_length, output);
430 
431         if(ERROR == ret) {
432             return ret;
433         }
434     }
435 
436     /* tag phase */
437     /* select tag phase */
438     cau_phase_config(CAU_TAG_PHASE);
439     /* flush the IN and OUT FIFOs */
440     cau_fifo_flush();
441     /* enable the CAU peripheral */
442     cau_enable();
443 
444     if(DISABLE == cau_enable_state_get()) {
445         return ERROR;
446     }
447 
448     cau_data_write(__REV((uint32_t)(aadlength >> 32U)));
449     cau_data_write(__REV((uint32_t)aadlength));
450     cau_data_write(__REV((uint32_t)(inputlength >> 32U)));
451     cau_data_write(__REV((uint32_t)inputlength));
452 
453     /* wait until the ONE flag is set */
454     while(RESET == cau_flag_get(CAU_FLAG_OUTFIFO_NO_EMPTY)) {
455     }
456 
457     /* read the tag in the OUT FIFO */
458     *(uint32_t *)(tagaddr) = cau_data_read();
459     tagaddr += 4U;
460     *(uint32_t *)(tagaddr) = cau_data_read();
461     tagaddr += 4U;
462     *(uint32_t *)(tagaddr) = cau_data_read();
463     tagaddr += 4U;
464     *(uint32_t *)(tagaddr) = cau_data_read();
465     tagaddr += 4U;
466 
467     /* disable the CAU peripheral */
468     cau_disable();
469 
470     return ret;
471 }
472 
473 /*!
474     \brief      encrypt and decrypt using AES in CCM mode
475     \param[in]  cau_parameter: pointer to the input structure
476                   alg_dir: algorithm dirctory
477                     CAU_ENCRYPT, CAU_DECRYPT
478                   key: key
479                   key_size: key size in bytes
480                   iv: initialization vector
481                   iv_size: iv size in bytes
482                   input: input data
483                   in_length: input data length in bytes
484                   aad: additional authentication data
485                   aad_size: aad size
486     \param[in]  mac_size: mac size (in bytes)
487     \param[out] output: pointer to the returned output data buffer
488     \param[out] tag: pointer to the returned tag buffer
489     \param[out] aad_buf: pointer to the user buffer used when formatting aad block
490     \retval     ErrStatus: SUCCESS or ERROR
491 */
cau_aes_ccm(cau_parameter_struct * cau_parameter,uint8_t * output,uint8_t tag[],uint32_t tag_size,uint8_t aad_buf[])492 ErrStatus cau_aes_ccm(cau_parameter_struct *cau_parameter, uint8_t *output, uint8_t tag[], uint32_t tag_size, uint8_t aad_buf[])
493 {
494     cau_key_parameter_struct key_initpara;
495     cau_iv_parameter_struct iv_initpara;
496     ErrStatus ret = ERROR;
497     uint32_t inputaddr  = (uint32_t)cau_parameter->input;
498     uint32_t inputsize = cau_parameter->in_length;
499     uint32_t aadaddr = (uint32_t)cau_parameter->aad;
500     uint32_t aadsize = cau_parameter->aad_size;
501     uint32_t aad_block_size = 0U;
502     uint32_t ivaddr = (uint32_t)cau_parameter->iv;
503     uint32_t ivsize = cau_parameter->iv_size;
504     uint32_t outputaddr = (uint32_t)output;
505     uint32_t i = 0U, plen = 0U;
506     uint32_t head_index = 0U;
507     uint8_t blockb0[16U] = {0U};
508     uint8_t counter[16U] = {0U};
509     uint32_t ctraddr = (uint32_t)counter;
510     uint32_t b0addr = (uint32_t)blockb0;
511     uint32_t temp_tag[4U];
512 
513     /* formatting the aad block */
514     if((uint32_t)0U != aadsize) {
515         /* check that the aad length is lower than 2^16 - 2^8 = 65536 - 256 = 65280 */
516         if(aadsize < 65280U) {
517             aad_buf[head_index++] = (uint8_t)((aadsize >> 8U) & 0xFFU);
518             aad_buf[head_index++] = (uint8_t)((aadsize) & 0xFFU);
519             aad_block_size = aadsize + 2U;
520         } else {
521             /* aad is encoded as 0xFF || 0xFE || [aadsize]32, i.e., six octets */
522             aad_buf[head_index++] = 0xFFU;
523             aad_buf[head_index++] = 0xFEU;
524             aad_buf[head_index++] = (uint8_t)((aadsize & 0xFF000000U) >> 24U);
525             aad_buf[head_index++] = (uint8_t)((aadsize & 0x00FF0000U) >> 16U);
526             aad_buf[head_index++] = (uint8_t)((aadsize & 0x0000FF00U) >> 8U);
527             aad_buf[head_index++] = (uint8_t)(aadsize & 0x000000FFU);
528             aad_block_size = aadsize + 6U;
529         }
530         /* copy the aad buffer in internal buffer "HBuffer" */
531         for(i = 0U; i < aadsize; i++) {
532             aad_buf[head_index++] = *(uint8_t *)((uint32_t)(aadaddr + i));
533         }
534         /* check if the aad block size is modulo 16 */
535         if(0U != (aad_block_size % 16U)) {
536             /* Padd the aad buffer with 0s till the HBuffer length is modulo 16 */
537             for(i = aad_block_size; i <= ((aad_block_size / 16U) + 1U) * 16U; i++) {
538                 aad_buf[i] = 0U;
539             }
540             /* set the aad size to modulo 16 */
541             aad_block_size = ((aad_block_size / 16U) + 1U) * 16U;
542         }
543         /* set the pointer aadaddr to HBuffer */
544         aadaddr = (uint32_t)aad_buf;
545     }
546 
547     /* formatting the block B0 */
548     if(0U != aadsize) {
549         blockb0[0] = 0x40U;
550     }
551     /* flags byte */
552     blockb0[0] |= (0U | (((((uint8_t) tag_size - 2U) / 2U) & 0x07U) << 3U) | (((uint8_t)(15U - ivsize) - 1U) & 0x07U));
553 
554     if(ivsize > MAX_CCM_IV_SIZE) {
555         return ERROR;
556     }
557 
558     for(i = 0U; i < ivsize; i++) {
559         blockb0[i + 1U] = *(uint8_t *)((uint32_t)(ivaddr + i));
560     }
561 
562     /* the byte length for payload length expressing, which plus the ivsize must equal to 15 bytes */
563     plen = 15U - ivsize;
564     /* if the byte length for payload length expressing is more than 4 bytes */
565     if(plen > 4U) {
566         /* pad the blockb0 after vectors, and before the last 4 bytes */
567         for(; i < 11U; i++) {
568             blockb0[i + 1U] = 0U;
569         }
570         blockb0[12U] = (uint8_t)((inputsize >> 24U) & 0xFFU);
571         blockb0[13U] = (uint8_t)((inputsize >> 16U) & 0xFFU);
572         blockb0[14U] = (uint8_t)((inputsize >> 8U) & 0xFFU);
573         blockb0[15U] = (uint8_t)(inputsize & 0xFFU);
574     } else {
575         /* the payload length is expressed in plen bytes */
576         for(; i < 15U; i++) {
577             blockb0[i + 1U] = (uint8_t)((inputsize >> ((plen - 1U) * 8U)) & 0xFFU);
578             plen--;
579         }
580     }
581 
582     /* formatting the initial counter */
583     /* byte 0: bits 0-2 contain the same encoding of q as in B0 */
584     counter[0] = blockb0[0] & BLOCK_B0_MASK;
585     for(i = 1U; i < ivsize + 1U; i++) {
586         counter[i] = blockb0[i];
587     }
588     /* set the LSB to 1 */
589     counter[15] |= 0x01U;
590 
591     /* init phase */
592     /* flush the IN and OUT FIFOs */
593     cau_fifo_flush();
594     /* clear CAUEN bit to ensure CAU is disable */
595     cau_disable();
596 
597     /* key structure initialization */
598     cau_key_struct_para_init(&key_initpara);
599     /* initialize the CAU peripheral */
600     cau_init(cau_parameter->alg_dir, CAU_MODE_AES_CCM, CAU_SWAPPING_8BIT);
601     /* select init phase */
602     cau_phase_config(CAU_PREPARE_PHASE);
603 
604     /* AES key structure parameter config */
605     cau_aes_key_config(cau_parameter->key, cau_parameter->key_size, &key_initpara);
606     /* key initialization */
607     cau_key_init(&key_initpara);
608 
609     /* vectors initialization */
610     iv_initpara.iv_0_high = __REV(*(uint32_t *)(ctraddr));
611     ctraddr += 4U;
612     iv_initpara.iv_0_low = __REV(*(uint32_t *)(ctraddr));
613     ctraddr += 4U;
614     iv_initpara.iv_1_high = __REV(*(uint32_t *)(ctraddr));
615     ctraddr += 4U;
616     iv_initpara.iv_1_low = __REV(*(uint32_t *)(ctraddr));
617     cau_iv_init(&iv_initpara);
618 
619     /* enable the CAU peripheral */
620     cau_enable();
621 
622     /* write block B0 in the In FIFO */
623     cau_data_write(*(uint32_t *)(b0addr));
624     b0addr += 4U;
625     cau_data_write(*(uint32_t *)(b0addr));
626     b0addr += 4U;
627     cau_data_write(*(uint32_t *)(b0addr));
628     b0addr += 4U;
629     cau_data_write(*(uint32_t *)(b0addr));
630 
631     /* wait for CAUEN bit to be 0 */
632     while(ENABLE == cau_enable_state_get()) {
633     }
634 
635     /* aad phase */
636     if((uint32_t)0U != aadsize) {
637         /* select aad phase */
638         cau_phase_config(CAU_AAD_PHASE);
639         /* enable the CAU peripheral */
640         cau_enable();
641 
642         ret = cau_fill_data((uint8_t *)aadaddr, aad_block_size);
643 
644         if(ERROR == ret) {
645             return ret;
646         }
647     }
648 
649     /* encrypt or dcrypt phase */
650     inputsize = cau_parameter->in_length;
651 
652     if((uint32_t)0U != inputsize) {
653         /* select encrypt or dcrypt phase */
654         cau_phase_config(CAU_ENCRYPT_DECRYPT_PHASE);
655         /* enable the CAU peripheral */
656         cau_enable();
657 
658         /* AES calculate process */
659         ret = cau_aes_calculate((uint8_t *)inputaddr, inputsize, (uint8_t *)outputaddr);
660 
661         if(ERROR == ret) {
662             return ret;
663         }
664     }
665 
666     /* tag phase */
667     /* select final phase */
668     cau_phase_config(CAU_TAG_PHASE);
669     /* enable the CAU peripheral */
670     cau_enable();
671 
672     if(DISABLE == cau_enable_state_get()) {
673         return ERROR;
674     }
675 
676     ctraddr = (uint32_t)counter;
677 
678     cau_data_write(*(uint32_t *)(ctraddr));
679     ctraddr += 4U;
680     cau_data_write(*(uint32_t *)(ctraddr));
681     ctraddr += 4U;
682     cau_data_write(*(uint32_t *)(ctraddr));
683     ctraddr += 4U;
684     /* reset bit 0 (after 8-bit swap) is equivalent to reset bit 24 (before 8-bit swap) */
685     cau_data_write(*(uint32_t *)(ctraddr) & 0xFEFFFFFFU);
686 
687     /* wait until the ONE flag is set */
688     while(RESET == cau_flag_get(CAU_FLAG_OUTFIFO_NO_EMPTY)) {
689     }
690 
691     /* read the tag in the OUT FIFO */
692     temp_tag[0] = cau_data_read();
693     temp_tag[1] = cau_data_read();
694     temp_tag[2] = cau_data_read();
695     temp_tag[3] = cau_data_read();
696 
697     /* disable the CAU peripheral */
698     cau_disable();
699 
700     /* Copy temporary authentication TAG in user TAG buffer */
701     for(i = 0U; i < tag_size; i++) {
702         tag[i] = (uint8_t)(temp_tag[i / 4U] >> (8U * (i % 4U)));
703     }
704 
705     return ret;
706 }
707 /*!
708     \brief      AES key structure parameter config
709     \param[in]  key: key used for AES algorithm
710     \param[in]  keysize: length of the key in bits, must be either 128, 192 or 256
711     \param[out] cau_key_initpara: key init parameter struct
712                   key_0_high: key 0 high
713                   key_0_low:  key 0 low
714                   key_1_high: key 1 high
715                   key_1_low:  key 1 low
716                   key_2_high: key 2 high
717                   key_2_low:  key 2 low
718                   key_3_high: key 3 high
719                   key_3_low:  key 3 low
720     \retval     none
721 */
cau_aes_key_config(uint8_t * key,uint32_t keysize,cau_key_parameter_struct * cau_key_initpara)722 static void cau_aes_key_config(uint8_t *key, uint32_t keysize, cau_key_parameter_struct *cau_key_initpara)
723 {
724     uint32_t keyaddr = (uint32_t)key;
725 
726     switch(keysize) {
727     case 128:
728         cau_aes_keysize_config(CAU_KEYSIZE_128BIT);
729         cau_key_initpara->key_2_high = __REV(*(uint32_t *)(keyaddr));
730         keyaddr += 4U;
731         cau_key_initpara->key_2_low  = __REV(*(uint32_t *)(keyaddr));
732         keyaddr += 4U;
733         cau_key_initpara->key_3_high = __REV(*(uint32_t *)(keyaddr));
734         keyaddr += 4U;
735         cau_key_initpara->key_3_low  = __REV(*(uint32_t *)(keyaddr));
736         break;
737     case 192:
738         cau_aes_keysize_config(CAU_KEYSIZE_192BIT);
739         cau_key_initpara->key_1_high = __REV(*(uint32_t *)(keyaddr));
740         keyaddr += 4U;
741         cau_key_initpara->key_1_low  = __REV(*(uint32_t *)(keyaddr));
742         keyaddr += 4U;
743         cau_key_initpara->key_2_high = __REV(*(uint32_t *)(keyaddr));
744         keyaddr += 4U;
745         cau_key_initpara->key_2_low  = __REV(*(uint32_t *)(keyaddr));
746         keyaddr += 4U;
747         cau_key_initpara->key_3_high = __REV(*(uint32_t *)(keyaddr));
748         keyaddr += 4U;
749         cau_key_initpara->key_3_low  = __REV(*(uint32_t *)(keyaddr));
750         break;
751     case 256:
752         cau_aes_keysize_config(CAU_KEYSIZE_256BIT);
753         cau_key_initpara->key_0_high = __REV(*(uint32_t *)(keyaddr));
754         keyaddr += 4U;
755         cau_key_initpara->key_0_low  = __REV(*(uint32_t *)(keyaddr));
756         keyaddr += 4U;
757         cau_key_initpara->key_1_high = __REV(*(uint32_t *)(keyaddr));
758         keyaddr += 4U;
759         cau_key_initpara->key_1_low  = __REV(*(uint32_t *)(keyaddr));
760         keyaddr += 4U;
761         cau_key_initpara->key_2_high = __REV(*(uint32_t *)(keyaddr));
762         keyaddr += 4U;
763         cau_key_initpara->key_2_low  = __REV(*(uint32_t *)(keyaddr));
764         keyaddr += 4U;
765         cau_key_initpara->key_3_high = __REV(*(uint32_t *)(keyaddr));
766         keyaddr += 4U;
767         cau_key_initpara->key_3_low  = __REV(*(uint32_t *)(keyaddr));
768         break;
769     default:
770         break;
771     }
772 }
773 
774 /*!
775     \brief      fill data into data input register
776     \param[in]  input: pointer to the input buffer
777     \param[in]  in_length: length of the input buffer in bytes, must be a multiple of 16 bytes
778     \retval     ErrStatus: SUCCESS or ERROR
779 */
cau_fill_data(uint8_t * input,uint32_t in_length)780 static ErrStatus cau_fill_data(uint8_t *input, uint32_t in_length)
781 {
782     uint32_t inputaddr  = (uint32_t)input;
783     uint32_t i = 0U;
784     __IO uint32_t counter = 0U;
785     uint32_t busystatus = 0U;
786 
787     if(DISABLE == cau_enable_state_get()) {
788         return ERROR;
789     }
790 
791     for(i = 0U; i < in_length; i += BLOCK_DATA_SIZE) {
792         /* wait until the IEM flag is set */
793         while(RESET == cau_flag_get(CAU_FLAG_INFIFO_EMPTY)) {
794         }
795 
796         if(i + BLOCK_DATA_SIZE > in_length) {
797             /* the last block data number is less than 128bit */
798             uint32_t block_data_temp[4] = {0U};
799 
800             /* fill the remaining bits with zero */
801             memcpy(block_data_temp, (uint32_t *)inputaddr, in_length - i);
802             inputaddr = (uint32_t)block_data_temp;
803 
804             /* if GCM encryption or CCM decryption, then configurate NBPILB bits in CTL register */
805             if((CAU_CTL & CAU_CTL_GCM_CCMPH) == CAU_ENCRYPT_DECRYPT_PHASE) {
806                 if((CAU_CTL & (CAU_CTL_ALGM | CAU_CTL_CAUDIR)) == (CAU_MODE_AES_GCM | CAU_ENCRYPT)) {
807                     CAU_CTL |= CAU_PADDING_BYTES(i + BLOCK_DATA_SIZE - in_length);
808                 } else if((CAU_CTL & (CAU_CTL_ALGM | CAU_CTL_CAUDIR)) == (CAU_MODE_AES_CCM | CAU_DECRYPT)) {
809                     CAU_CTL |= CAU_PADDING_BYTES(i + BLOCK_DATA_SIZE - in_length);
810                 } else {
811                 }
812             }
813         }
814 
815         /* write data to the IN FIFO */
816         cau_data_write(*(uint32_t *)(inputaddr));
817         inputaddr += 4U;
818         cau_data_write(*(uint32_t *)(inputaddr));
819         inputaddr += 4U;
820         cau_data_write(*(uint32_t *)(inputaddr));
821         inputaddr += 4U;
822         cau_data_write(*(uint32_t *)(inputaddr));
823         inputaddr += 4U;
824     }
825     /* wait until the complete message has been processed */
826     counter = 0U;
827     do {
828         busystatus = cau_flag_get(CAU_FLAG_BUSY);
829         counter++;
830     } while((AESBSY_TIMEOUT != counter) && (RESET != busystatus));
831 
832     if(RESET != busystatus) {
833         return ERROR;
834     }
835 
836     return SUCCESS;
837 }
838 
839 /*!
840     \brief      AES calculate process
841     \param[in]  input: pointer to the input buffer
842     \param[in]  in_length: length of the input buffer in bytes, must be a multiple of 16 bytes
843     \param[out]  output: pointer to the returned buffer
844     \retval     ErrStatus: SUCCESS or ERROR
845 */
cau_aes_calculate(uint8_t * input,uint32_t in_length,uint8_t * output)846 static ErrStatus cau_aes_calculate(uint8_t *input, uint32_t in_length, uint8_t *output)
847 {
848     uint32_t inputaddr  = (uint32_t)input;
849     uint32_t outputaddr = (uint32_t)output;
850     uint32_t i = 0U;
851     __IO uint32_t counter = 0U;
852     uint32_t busystatus = 0U;
853 
854     /* the clock is not enabled or there is no embeded CAU peripheral */
855     if(DISABLE == cau_enable_state_get()) {
856         return ERROR;
857     }
858 
859     for(i = 0U; i < in_length; i += BLOCK_DATA_SIZE) {
860         /* wait until the IEM flag is set */
861         while(RESET == cau_flag_get(CAU_FLAG_INFIFO_EMPTY)) {
862         }
863 
864         /* check if the last input data block */
865         if(i + BLOCK_DATA_SIZE > in_length) {
866             /* the last block data number is less than 128bit */
867             uint32_t block_data_temp[4] = {0};
868 
869             /* fill the remaining bits with zero */
870             memcpy(block_data_temp, (uint32_t *)inputaddr, in_length - i);
871             inputaddr = (uint32_t)block_data_temp;
872 
873             /* if GCM encryption or CCM decryption, then configurate NBPILB bits in CTL register */
874             if((CAU_CTL & (CAU_CTL_ALGM | CAU_CTL_CAUDIR)) == (CAU_MODE_AES_GCM | CAU_ENCRYPT)) {
875                 CAU_CTL |= CAU_PADDING_BYTES(i + BLOCK_DATA_SIZE - in_length);
876             } else if((CAU_CTL & (CAU_CTL_ALGM | CAU_CTL_CAUDIR)) == (CAU_MODE_AES_CCM | CAU_DECRYPT)) {
877                 CAU_CTL |= CAU_PADDING_BYTES(i + BLOCK_DATA_SIZE - in_length);
878             } else {
879             }
880         }
881 
882         /* write data to the IN FIFO */
883         cau_data_write(*(uint32_t *)(inputaddr));
884         inputaddr += 4U;
885         cau_data_write(*(uint32_t *)(inputaddr));
886         inputaddr += 4U;
887         cau_data_write(*(uint32_t *)(inputaddr));
888         inputaddr += 4U;
889         cau_data_write(*(uint32_t *)(inputaddr));
890         inputaddr += 4U;
891 
892         /* wait until the complete message has been processed */
893         counter = 0U;
894         do {
895             busystatus = cau_flag_get(CAU_FLAG_BUSY);
896             counter++;
897         } while((AESBSY_TIMEOUT != counter) && (RESET != busystatus));
898 
899         if(RESET != busystatus) {
900             return ERROR;
901         } else {
902             /* read the output block from the output FIFO */
903             *(uint32_t *)(outputaddr) = cau_data_read();
904             outputaddr += 4U;
905             *(uint32_t *)(outputaddr) = cau_data_read();
906             outputaddr += 4U;
907             *(uint32_t *)(outputaddr) = cau_data_read();
908             outputaddr += 4U;
909             *(uint32_t *)(outputaddr) = cau_data_read();
910             outputaddr += 4U;
911         }
912     }
913 
914     return SUCCESS;
915 }
916