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