1 /*!
2     \file    gd32l23x_cau.c
3     \brief   CAU driver
4 
5     \version 2021-08-04, V1.0.0, firmware for GD32L23x
6 */
7 
8 /*
9     Copyright (c) 2021, GigaDevice Semiconductor Inc.
10 
11     Redistribution and use in source and binary forms, with or without modification,
12 are permitted provided that the following conditions are met:
13 
14     1. Redistributions of source code must retain the above copyright notice, this
15        list of conditions and the following disclaimer.
16     2. Redistributions in binary form must reproduce the above copyright notice,
17        this list of conditions and the following disclaimer in the documentation
18        and/or other materials provided with the distribution.
19     3. Neither the name of the copyright holder nor the names of its contributors
20        may be used to endorse or promote products derived from this software without
21        specific prior written permission.
22 
23     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32 OF SUCH DAMAGE.
33 */
34 
35 #include "gd32l23x_cau.h"
36 #include "gd32l23x_rcu.h"
37 
38 #define FLAG_MASK            ((uint32_t)0x00000020U)
39 #define STAT0_AESDES_MASK    ((uint32_t)0x00000015U)
40 #define STAT0_TDES_MASK      ((uint32_t)0x00000014U)
41 
42 /*!
43     \brief      reset the CAU peripheral
44     \param[in]  none
45     \param[out] none
46     \retval     none
47 */
cau_deinit(void)48 void cau_deinit(void)
49 {
50     /* enable CAU reset state */
51     rcu_periph_reset_enable(RCU_CAURST);
52     /* release CAU from reset state */
53     rcu_periph_reset_disable(RCU_CAURST);
54     /* enable PMU clock */
55     rcu_periph_clock_enable(RCU_PMU);
56     /* wakeup CAU power domain */
57     PMU_CTL1 |= PMU_CORE1_WAKE;
58     /* check CAU power domain is active */
59     while(0U == (PMU_STAT & PMU_STAT_CORE1PS_ACTIVE)) {
60     }
61 }
62 
63 /*!
64     \brief      initialize the CAU encrypt and decrypt parameter struct with the default values
65     \param[in]  none
66     \param[out] cau_parameter:
67                   alg_dir: algorithm dirctory
68                     CAU_ENCRYPT, CAU_DECRYPT
69                   key: key
70                   key_size: key size in bytes
71                   iv: initialization vector
72                   iv_size: iv size in bytes
73                   input: input data
74                   in_length: input data length in bytes
75                   aad: additional authentication data
76                   aad_size: header size
77     \retval     none
78 */
cau_struct_para_init(cau_parameter_struct * cau_parameter)79 void cau_struct_para_init(cau_parameter_struct *cau_parameter)
80 {
81     /* set the CAU encrypt and decrypt parameters struct with the default values */
82     cau_parameter->alg_dir     = CAU_ENCRYPT;
83     cau_parameter->key         = 0U;
84     cau_parameter->key_size    = 0U;
85     cau_parameter->iv          = 0U;
86     cau_parameter->iv_size     = 0U;
87     cau_parameter->input       = 0U;
88     cau_parameter->in_length   = 0U;
89     cau_parameter->aad         = 0U;
90     cau_parameter->aad_size    = 0U;
91 }
92 
93 /*!
94     \brief      initialize the key parameter structure with the default values
95     \param[in]  none
96     \param[out] key_initpara:
97                   key_0_high: key 0 high
98                   key_0_low:  key 0 low
99                   key_1_high: key 1 high
100                   key_1_low:  key 1 low
101                   key_2_high: key 2 high
102                   key_2_low:  key 2 low
103                   key_3_high: key 3 high
104                   key_3_low:  key 3 low
105     \retval     none
106 */
cau_key_struct_para_init(cau_key_parameter_struct * key_initpara)107 void cau_key_struct_para_init(cau_key_parameter_struct *key_initpara)
108 {
109     /* set the key parameters struct with the default values */
110     key_initpara->key_0_high   = 0U;
111     key_initpara->key_0_low    = 0U;
112     key_initpara->key_1_high   = 0U;
113     key_initpara->key_1_low    = 0U;
114     key_initpara->key_2_high   = 0U;
115     key_initpara->key_2_low    = 0U;
116     key_initpara->key_3_high   = 0U;
117     key_initpara->key_3_low    = 0U;
118 }
119 
120 /*!
121     \brief      initialize the vectors parameter struct with the default values
122     \param[in]  none
123     \param[out] iv_initpara:
124                   iv_0_high: init vector 0 high
125                   iv_0_low:  init vector 0 low
126                   iv_1_high: init vector 1 high
127                   iv_1_low:  init vector 1 low
128     \retval     none
129 */
cau_iv_struct_para_init(cau_iv_parameter_struct * iv_initpara)130 void cau_iv_struct_para_init(cau_iv_parameter_struct *iv_initpara)
131 {
132     /* set the vectors parameters struct with the default values */
133     iv_initpara->iv_0_high   = 0U;
134     iv_initpara->iv_0_low    = 0U;
135     iv_initpara->iv_1_high   = 0U;
136     iv_initpara->iv_1_low    = 0U;
137 }
138 
139 /*!
140     \brief      initialize the context parameter struct with the default values
141     \param[in]  none
142     \param[out] cau_context:
143                   ctl_config: current configuration
144                   iv_0_high: init vector 0 high
145                   iv_0_low:  init vector 0 low
146                   iv_1_high: init vector 1 high
147                   iv_1_low:  init vector 1 low
148                   key_0_high: key 0 high
149                   key_0_low:  key 0 low
150                   key_1_high: key 1 high
151                   key_1_low:  key 1 low
152                   key_2_high: key 2 high
153                   key_2_low:  key 2 low
154                   key_3_high: key 3 high
155                   key_3_low:  key 3 low
156                   gcmccmctxs[8]: GCM or CCM mode context switch
157                   gcmctxs[8]: GCM mode context switch
158     \retval     none
159 */
cau_context_struct_para_init(cau_context_parameter_struct * cau_context)160 void cau_context_struct_para_init(cau_context_parameter_struct *cau_context)
161 {
162     cau_context->ctl_config = 0U;
163 
164     /* set the vectors parameters with the default values */
165     cau_context->iv_0_high  = 0U;
166     cau_context->iv_0_low   = 0U;
167     cau_context->iv_1_high  = 0U;
168     cau_context->iv_1_low   = 0U;
169 
170     /* set the key parameters with the default values */
171     cau_context->key_0_high = 0U;
172     cau_context->key_0_low  = 0U;
173     cau_context->key_1_high = 0U;
174     cau_context->key_1_low  = 0U;
175     cau_context->key_2_high = 0U;
176     cau_context->key_2_low  = 0U;
177     cau_context->key_3_high = 0U;
178     cau_context->key_3_low  = 0U;
179 
180     /* set the context switch with the default values */
181     cau_context->gcmccmctxs[0] = 0U;
182     cau_context->gcmccmctxs[1] = 0U;
183     cau_context->gcmccmctxs[2] = 0U;
184     cau_context->gcmccmctxs[3] = 0U;
185     cau_context->gcmccmctxs[4] = 0U;
186     cau_context->gcmccmctxs[5] = 0U;
187     cau_context->gcmccmctxs[6] = 0U;
188     cau_context->gcmccmctxs[7] = 0U;
189 
190     cau_context->gcmctxs[0] = 0U;
191     cau_context->gcmctxs[1] = 0U;
192     cau_context->gcmctxs[2] = 0U;
193     cau_context->gcmctxs[3] = 0U;
194     cau_context->gcmctxs[4] = 0U;
195     cau_context->gcmctxs[5] = 0U;
196     cau_context->gcmctxs[6] = 0U;
197     cau_context->gcmctxs[7] = 0U;
198 }
199 
200 /*!
201     \brief      enable the CAU peripheral
202     \param[in]  none
203     \param[out] none
204     \retval     none
205 */
cau_enable(void)206 void cau_enable(void)
207 {
208     /* enable the CAU processor */
209     CAU_CTL |= CAU_CTL_CAUEN;
210 }
211 
212 /*!
213     \brief      disable the CAU peripheral
214     \param[in]  none
215     \param[out] none
216     \retval     none
217 */
cau_disable(void)218 void cau_disable(void)
219 {
220     /* disable the CAU processor */
221     CAU_CTL &= ~CAU_CTL_CAUEN;
222 }
223 
224 /*!
225     \brief      enable the CAU DMA interface
226     \param[in]  dma_req: specify the CAU DMA transfer request to be enabled
227                 one or more parameters can be selected which are shown as below:
228       \arg        CAU_DMA_INFIFO: DMA for incoming(Rx) data transfer
229       \arg        CAU_DMA_OUTFIFO: DMA for outgoing(Tx) data transfer
230     \param[out] none
231     \retval     none
232 */
cau_dma_enable(uint32_t dma_req)233 void cau_dma_enable(uint32_t dma_req)
234 {
235     /* enable the selected CAU DMA request */
236     CAU_DMAEN |= dma_req;
237 }
238 
239 /*!
240     \brief      disable the CAU DMA interface
241     \param[in]  dma_req: specify the CAU DMA transfer request to be disabled
242                 one or more parameters can be selected which are shown as below:
243       \arg        CAU_DMA_INFIFO: DMA for incoming(Rx) data transfer
244       \arg        CAU_DMA_OUTFIFO: DMA for outgoing(Tx) data transfer
245     \param[out] none
246     \retval     none
247 */
cau_dma_disable(uint32_t dma_req)248 void cau_dma_disable(uint32_t dma_req)
249 {
250     /* disable the selected CAU DMA request */
251     CAU_DMAEN &= ~(dma_req);
252 }
253 
254 /*!
255     \brief      initialize the CAU peripheral
256     \param[in]  alg_dir: algorithm direction
257                 only one parameter can be selected which is shown as below:
258       \arg        CAU_ENCRYPT: encrypt
259       \arg        CAU_DECRYPT: decrypt
260     \param[in]  algo_mode: algorithm mode selection
261                 only one parameter can be selected which is shown as below:
262       \arg        CAU_MODE_TDES_ECB: TDES-ECB (3DES Electronic codebook)
263       \arg        CAU_MODE_TDES_CBC: TDES-CBC (3DES Cipher block chaining)
264       \arg        CAU_MODE_DES_ECB: DES-ECB (simple DES Electronic codebook)
265       \arg        CAU_MODE_DES_CBC: DES-CBC (simple DES Cipher block chaining)
266       \arg        CAU_MODE_AES_ECB: AES-ECB (AES Electronic codebook)
267       \arg        CAU_MODE_AES_CBC: AES-CBC (AES Cipher block chaining)
268       \arg        CAU_MODE_AES_CTR: AES-CTR (AES counter mode)
269       \arg        CAU_MODE_AES_KEY: AES decryption key preparation mode
270       \arg        CAU_MODE_AES_GCM: AES-GCM (AES Galois/counter mode)
271       \arg        CAU_MODE_AES_CCM: AES-CCM (AES combined cipher machine mode)
272       \arg        CAU_MODE_AES_CFB: AES-CFB (cipher feedback mode)
273       \arg        CAU_MODE_AES_OFB: AES-OFB (output feedback mode)
274     \param[in]  swapping: data swapping selection
275                 only one parameter can be selected which is shown as below:
276       \arg        CAU_SWAPPING_32BIT: no swapping
277       \arg        CAU_SWAPPING_16BIT: half-word swapping
278       \arg        CAU_SWAPPING_8BIT: bytes swapping
279       \arg        CAU_SWAPPING_1BIT: bit swapping
280     \param[out] none
281     \retval     none
282 */
cau_init(uint32_t alg_dir,uint32_t algo_mode,uint32_t swapping)283 void cau_init(uint32_t alg_dir, uint32_t algo_mode, uint32_t swapping)
284 {
285     /* select algorithm mode */
286     CAU_CTL &= ~CAU_CTL_ALGM;
287     CAU_CTL |= algo_mode;
288 
289     /* select data swapping */
290     CAU_CTL &= ~CAU_CTL_DATAM;
291     CAU_CTL |= swapping;
292 
293     /* select algorithm direction */
294     CAU_CTL &= ~CAU_CTL_CAUDIR;
295     CAU_CTL |= alg_dir;
296 }
297 
298 /*!
299     \brief      configure key size if use AES algorithm
300     \param[in]  key_size: key length selection when aes mode
301                 only one parameter can be selected which is shown as below:
302       \arg        CAU_KEYSIZE_128BIT: 128 bit key length
303       \arg        CAU_KEYSIZE_192BIT: 192 bit key length
304       \arg        CAU_KEYSIZE_256BIT: 256 bit key length
305     \param[out] none
306     \retval     none
307 */
cau_aes_keysize_config(uint32_t key_size)308 void cau_aes_keysize_config(uint32_t key_size)
309 {
310     CAU_CTL &= ~CAU_CTL_KEYM;
311     CAU_CTL |= key_size;
312 }
313 
314 /*!
315     \brief      initialize the key parameters
316     \param[in]  key_initpara: key init parameter struct
317                   key_0_high: key 0 high
318                   key_0_low:  key 0 low
319                   key_1_high: key 1 high
320                   key_1_low:  key 1 low
321                   key_2_high: key 2 high
322                   key_2_low:  key 2 low
323                   key_3_high: key 3 high
324                   key_3_low:  key 3 low
325     \param[out] none
326     \retval     none
327 */
cau_key_init(cau_key_parameter_struct * key_initpara)328 void cau_key_init(cau_key_parameter_struct *key_initpara)
329 {
330     CAU_KEY0H = key_initpara->key_0_high;
331     CAU_KEY0L = key_initpara->key_0_low;
332     CAU_KEY1H = key_initpara->key_1_high;
333     CAU_KEY1L = key_initpara->key_1_low;
334     CAU_KEY2H = key_initpara->key_2_high;
335     CAU_KEY2L = key_initpara->key_2_low;
336     CAU_KEY3H = key_initpara->key_3_high;
337     CAU_KEY3L = key_initpara->key_3_low;
338 }
339 
340 /*!
341     \brief      initialize the vectors parameters
342     \param[in]  iv_initpara: vectors init parameter struct
343                   iv_0_high: init vector 0 high
344                   iv_0_low:  init vector 0 low
345                   iv_1_high: init vector 1 high
346                   iv_1_low:  init vector 1 low
347     \param[out] none
348     \retval     none
349 */
cau_iv_init(cau_iv_parameter_struct * iv_initpara)350 void cau_iv_init(cau_iv_parameter_struct *iv_initpara)
351 {
352     CAU_IV0H = iv_initpara->iv_0_high;
353     CAU_IV0L = iv_initpara->iv_0_low;
354     CAU_IV1H = iv_initpara->iv_1_high;
355     CAU_IV1L = iv_initpara->iv_1_low;
356 }
357 
358 /*!
359     \brief      configure phase
360     \param[in]  phase: gcm or ccm phase
361                 only one parameter can be selected which is shown as below:
362       \arg        CAU_PREPARE_PHASE: prepare phase
363       \arg        CAU_AAD_PHASE: AAD phase
364       \arg        CAU_ENCRYPT_DECRYPT_PHASE: encryption/decryption phase
365       \arg        CAU_TAG_PHASE: tag phase
366     \param[out] none
367     \retval     none
368 */
cau_phase_config(uint32_t phase)369 void cau_phase_config(uint32_t phase)
370 {
371     uint32_t temp;
372     /* Get the CTL register */
373     temp = CAU_CTL;
374     /* Reset the phase configuration bits */
375     temp &= ~CAU_CTL_GCM_CCMPH;
376     /* Set the selected phase */
377     temp |= phase;
378     /* Set the CTL register */
379     CAU_CTL = temp;
380 }
381 
382 /*!
383     \brief      flush the IN and OUT FIFOs
384     \param[in]  none
385     \param[out] none
386     \retval     none
387 */
cau_fifo_flush(void)388 void cau_fifo_flush(void)
389 {
390     /* reset the read and write pointers of the FIFOs */
391     CAU_CTL |= CAU_CTL_FFLUSH;
392 }
393 
394 /*!
395     \brief      return whether CAU peripheral is enabled or disabled
396     \param[in]  none
397     \param[out] none
398     \retval     ControlStatus: ENABLE or DISABLE
399 */
cau_enable_state_get(void)400 ControlStatus cau_enable_state_get(void)
401 {
402     ControlStatus ret = DISABLE;
403     if(RESET != (CAU_CTL & CAU_CTL_CAUEN)) {
404         ret = ENABLE;
405     }
406     return ret;
407 }
408 
409 /*!
410     \brief      write data to the IN FIFO
411     \param[in]  data: data to write (0 - 0xFFFFFFFF)
412     \param[out] none
413     \retval     none
414 */
cau_data_write(uint32_t data)415 void cau_data_write(uint32_t data)
416 {
417     CAU_DI = data;
418 }
419 
420 /*!
421     \brief      return the last data entered into the output FIFO
422     \param[in]  none
423     \param[out] none
424     \retval     last data entered into the output FIFO
425 */
cau_data_read(void)426 uint32_t cau_data_read(void)
427 {
428     return CAU_DO;
429 }
430 
431 /*!
432     \brief      save context before context switching
433     \param[in]  key_initpara: key init parameter struct
434                   key_0_high: key 0 high
435                   key_0_low:  key 0 low
436                   key_1_high: key 1 high
437                   key_1_low:  key 1 low
438                   key_2_high: key 2 high
439                   key_2_low:  key 2 low
440                   key_3_high: key 3 high
441                   key_3_low:  key 3 low
442     \param[out] cau_context:
443                   ctl_config: current configuration
444                   iv_0_high: init vector 0 high
445                   iv_0_low:  init vector 0 low
446                   iv_1_high: init vector 1 high
447                   iv_1_low:  init vector 1 low
448                   key_0_high: key 0 high
449                   key_0_low:  key 0 low
450                   key_1_high: key 1 high
451                   key_1_low:  key 1 low
452                   key_2_high: key 2 high
453                   key_2_low:  key 2 low
454                   key_3_high: key 3 high
455                   key_3_low:  key 3 low
456                   gcmccmctxs[8]: GCM or CCM mode context switch
457                   gcmctxs[8]: GCM mode context switch
458     \retval     none
459 */
cau_context_save(cau_context_parameter_struct * cau_context,cau_key_parameter_struct * key_initpara)460 void cau_context_save(cau_context_parameter_struct *cau_context, cau_key_parameter_struct *key_initpara)
461 {
462     uint32_t checkmask = 0U;
463     uint32_t checkbits = 0U;
464     uint32_t algm_reg = 0U;
465 
466     /* stop DMA transfers on the IN FIFO by clearing the DMAIEN bit in the CAU_DMAEN */
467     CAU_DMAEN &= ~CAU_DMA_INFIFO;
468 
469     algm_reg = CAU_CTL & CAU_CTL_ALGM;
470     /* AES or DES */
471     if((uint32_t)0 != (algm_reg & (~CAU_MODE_TDES_CBC))) {
472         /* wait until both the IN and OUT FIFOs are empty (IEM=1 and ONE=0 in the CAU_STAT0 register) and BUSY=0 */
473         checkbits = CAU_STAT0_IEM;
474         checkmask = STAT0_AESDES_MASK;
475         /* TDES */
476     } else {
477         /* wait until OUT FIFO is empty (ONE=0 in the CAU_STAT0 register) and BUSY=0 */
478         checkbits = 0U;
479         checkmask = STAT0_TDES_MASK;
480     }
481 
482     while((CAU_STAT0 & checkmask) != checkbits) {
483     }
484 
485     /* stop DMA transfers on the OUT FIFO by clear CAU_DMAEN_DMAOEN=0 */
486     CAU_DMAEN &= ~CAU_DMAEN_DMAOEN;
487     /* disable CAU */
488     CAU_CTL &= ~CAU_CTL_CAUEN;
489 
490     /* save the current configuration (bit 19, bit[17:16] and bit[9:2] in the CAU_CTL register) */
491     cau_context->ctl_config  = CAU_CTL & (CAU_CTL_GCM_CCMPH |
492                                           CAU_CTL_KEYM  |
493                                           CAU_CTL_DATAM |
494                                           CAU_CTL_ALGM  |
495                                           CAU_CTL_CAUDIR |
496                                           CAU_CTL_NBPILB);
497 
498     /* save the key value */
499     cau_context->key_0_high = key_initpara->key_0_high;
500     cau_context->key_0_low  = key_initpara->key_0_low;
501     cau_context->key_1_high = key_initpara->key_1_high;
502     cau_context->key_1_low  = key_initpara->key_1_low;
503     cau_context->key_2_high = key_initpara->key_2_high;
504     cau_context->key_2_low  = key_initpara->key_2_low;
505     cau_context->key_3_high = key_initpara->key_3_high;
506     cau_context->key_3_low  = key_initpara->key_3_low;
507 
508     if((CAU_MODE_TDES_ECB != algm_reg) && (CAU_MODE_DES_ECB != algm_reg) && (CAU_MODE_AES_ECB != algm_reg)) {
509         /* if not in ECB mode, save the initialization vectors */
510         cau_context->iv_0_high = CAU_IV0H;
511         cau_context->iv_0_low = CAU_IV0L;
512         cau_context->iv_1_high = CAU_IV1H;
513         cau_context->iv_1_low = CAU_IV1L;
514     }
515 
516     /* if in GCM/CCM mode, save the context switch registers */
517     if((CAU_MODE_AES_GCM == algm_reg) || (CAU_MODE_AES_CCM == algm_reg)) {
518         cau_context->gcmccmctxs[0U] = CAU_GCMCCMCTXSx(0U);
519         cau_context->gcmccmctxs[1U] = CAU_GCMCCMCTXSx(1U);
520         cau_context->gcmccmctxs[2U] = CAU_GCMCCMCTXSx(2U);
521         cau_context->gcmccmctxs[3U] = CAU_GCMCCMCTXSx(3U);
522         cau_context->gcmccmctxs[4U] = CAU_GCMCCMCTXSx(4U);
523         cau_context->gcmccmctxs[5U] = CAU_GCMCCMCTXSx(5U);
524         cau_context->gcmccmctxs[6U] = CAU_GCMCCMCTXSx(6U);
525         cau_context->gcmccmctxs[7U] = CAU_GCMCCMCTXSx(7U);
526     }
527 
528     /* if in GCM mode, save the context switch registers */
529     if(CAU_MODE_AES_GCM == algm_reg) {
530         cau_context->gcmctxs[0U] = CAU_GCMCTXSx(0U);
531         cau_context->gcmctxs[1U] = CAU_GCMCTXSx(1U);
532         cau_context->gcmctxs[2U] = CAU_GCMCTXSx(2U);
533         cau_context->gcmctxs[3U] = CAU_GCMCTXSx(3U);
534         cau_context->gcmctxs[4U] = CAU_GCMCTXSx(4U);
535         cau_context->gcmctxs[5U] = CAU_GCMCTXSx(5U);
536         cau_context->gcmctxs[6U] = CAU_GCMCTXSx(6U);
537         cau_context->gcmctxs[7U] = CAU_GCMCTXSx(7U);
538     }
539 }
540 
541 /*!
542     \brief      restore context after context switching
543     \param[in]  cau_context:
544                   ctl_config: current configuration
545                   iv_0_high: init vector 0 high
546                   iv_0_low:  init vector 0 low
547                   iv_1_high: init vector 1 high
548                   iv_1_low:  init vector 1 low
549                   key_0_high: key 0 high
550                   key_0_low:  key 0 low
551                   key_1_high: key 1 high
552                   key_1_low:  key 1 low
553                   key_2_high: key 2 high
554                   key_2_low:  key 2 low
555                   key_3_high: key 3 high
556                   key_3_low:  key 3 low
557                   gcmccmctxs[8]: GCM or CCM mode context switch
558                   gcmctxs[8]: GCM mode context switch
559     \param[out] none
560     \retval     none
561 */
cau_context_restore(cau_context_parameter_struct * cau_context)562 void cau_context_restore(cau_context_parameter_struct *cau_context)
563 {
564     uint32_t algm_reg, aes_decrypt;
565 
566     /* configure the processor with the saved configuration */
567     CAU_CTL = cau_context->ctl_config;
568 
569     algm_reg = CAU_CTL & CAU_CTL_ALGM;
570 
571     /* restore the key value */
572     CAU_KEY0H = cau_context->key_0_high;
573     CAU_KEY0L = cau_context->key_0_low;
574     CAU_KEY1H = cau_context->key_1_high;
575     CAU_KEY1L = cau_context->key_1_low;
576     CAU_KEY2H = cau_context->key_2_high;
577     CAU_KEY2L = cau_context->key_2_low;
578     CAU_KEY3H = cau_context->key_3_high;
579     CAU_KEY3L = cau_context->key_3_low;
580 
581     if((CAU_MODE_TDES_ECB != algm_reg) && (CAU_MODE_DES_ECB != algm_reg) && (CAU_MODE_AES_ECB != algm_reg)) {
582         /* restore the initialization vectors */
583         CAU_IV0H = cau_context->iv_0_high;
584         CAU_IV0L = cau_context->iv_0_low;
585         CAU_IV1H = cau_context->iv_1_high;
586         CAU_IV1L = cau_context->iv_1_low;
587     }
588 
589     /* if in GCM/CCM mode, restore the context switch registers */
590     if((CAU_MODE_AES_GCM == algm_reg) || (CAU_MODE_AES_CCM == algm_reg)) {
591         CAU_GCMCCMCTXSx(0U) = cau_context->gcmccmctxs[0U];
592         CAU_GCMCCMCTXSx(1U) = cau_context->gcmccmctxs[1U];
593         CAU_GCMCCMCTXSx(2U) = cau_context->gcmccmctxs[2U];
594         CAU_GCMCCMCTXSx(3U) = cau_context->gcmccmctxs[3U];
595         CAU_GCMCCMCTXSx(4U) = cau_context->gcmccmctxs[4U];
596         CAU_GCMCCMCTXSx(5U) = cau_context->gcmccmctxs[5U];
597         CAU_GCMCCMCTXSx(6U) = cau_context->gcmccmctxs[6U];
598         CAU_GCMCCMCTXSx(7U) = cau_context->gcmccmctxs[7U];
599     }
600 
601     /* if in GCM mode, restore the context switch registers */
602     if(CAU_MODE_AES_GCM == algm_reg) {
603         CAU_GCMCTXSx(0U) = cau_context->gcmctxs[0U];
604         CAU_GCMCTXSx(1U) = cau_context->gcmctxs[1U];
605         CAU_GCMCTXSx(2U) = cau_context->gcmctxs[2U];
606         CAU_GCMCTXSx(3U) = cau_context->gcmctxs[3U];
607         CAU_GCMCTXSx(4U) = cau_context->gcmctxs[4U];
608         CAU_GCMCTXSx(5U) = cau_context->gcmctxs[5U];
609         CAU_GCMCTXSx(6U) = cau_context->gcmctxs[6U];
610         CAU_GCMCTXSx(7U) = cau_context->gcmctxs[7U];
611     }
612 
613     /* if it is AES ECB/CBC decryption, then first prepare key */
614     aes_decrypt = CAU_CTL & (CAU_CTL_ALGM | CAU_CTL_CAUDIR);
615     if(((CAU_MODE_AES_ECB | CAU_DECRYPT) == aes_decrypt) || ((CAU_MODE_AES_CBC | CAU_DECRYPT) == aes_decrypt)) {
616         uint32_t alg_dir, algo_mode, swapping;
617 
618         /* flush IN/OUT FIFOs */
619         cau_fifo_flush();
620         /* parameters for key preparation for AES decryption */
621         alg_dir = CAU_DECRYPT;
622         algo_mode = CAU_MODE_AES_KEY;
623         swapping = CAU_SWAPPING_32BIT;
624         cau_init(alg_dir, algo_mode, swapping);
625 
626         /* enable CAU */
627         cau_enable();
628 
629         /* wait until BUSY=0 */
630         while((uint32_t)0U != cau_flag_get(CAU_FLAG_BUSY)) {
631         }
632 
633         /* parameters for decryption */
634         CAU_CTL = cau_context->ctl_config;
635     }
636 
637     /* enable CAU */
638     cau_enable();
639 }
640 
641 /*!
642     \brief      enable the CAU interrupts
643     \param[in]  interrupt: specify the CAU interrupt source to be enabled
644                 one or more parameters can be selected which are shown as below:
645       \arg        CAU_INT_INFIFO: input FIFO interrupt
646       \arg        CAU_INT_OUTFIFO: output FIFO interrupt
647     \param[out] none
648     \retval     none
649 */
cau_interrupt_enable(uint32_t interrupt)650 void cau_interrupt_enable(uint32_t interrupt)
651 {
652     /* enable the selected CAU interrupt */
653     CAU_INTEN |= interrupt;
654 }
655 
656 /*!
657     \brief      disable the CAU interrupts
658     \param[in]  interrupt: specify the CAU interrupt source to be disabled
659                 one or more parameters can be selected which are shown as below:
660       \arg        CAU_INT_INFIFO: input FIFO interrupt
661       \arg        CAU_INT_OUTFIFO: output FIFO interrupt
662     \param[out] none
663     \retval     none
664 */
cau_interrupt_disable(uint32_t interrupt)665 void cau_interrupt_disable(uint32_t interrupt)
666 {
667     /* disable the selected CAU interrupt */
668     CAU_INTEN &= ~(interrupt);
669 }
670 
671 /*!
672     \brief      get the interrupt flag
673     \param[in]  interrupt: CAU interrupt flag
674                 only one parameter can be selected which is shown as below:
675       \arg        CAU_INT_FLAG_INFIFO: input FIFO interrupt
676       \arg        CAU_INT_FLAG_OUTFIFO: output FIFO interrupt
677     \param[out] none
678     \retval     FlagStatus: SET or RESET
679 */
cau_interrupt_flag_get(uint32_t interrupt)680 FlagStatus cau_interrupt_flag_get(uint32_t interrupt)
681 {
682     FlagStatus flag = RESET;
683 
684     /* check the status of the specified CAU interrupt */
685     if(RESET != (CAU_INTF & interrupt)) {
686         flag = SET;
687     }
688 
689     return flag;
690 }
691 
692 /*!
693     \brief      get the CAU flag status
694     \param[in]  flag: CAU flag status
695                 only one parameter can be selected which is shown as below:
696       \arg        CAU_FLAG_INFIFO_EMPTY: input FIFO empty
697       \arg        CAU_FLAG_INFIFO_NO_FULL: input FIFO is not full
698       \arg        CAU_FLAG_OUTFIFO_NO_EMPTY: output FIFO not empty
699       \arg        CAU_FLAG_OUTFIFO_FULL: output FIFO is full
700       \arg        CAU_FLAG_BUSY: the CAU core is busy
701       \arg        CAU_FLAG_INFIFO: input FIFO flag status
702       \arg        CAU_FLAG_OUTFIFO: output FIFO flag status
703     \param[out] none
704     \retval     FlagStatus: SET or RESET
705 */
cau_flag_get(uint32_t flag)706 FlagStatus cau_flag_get(uint32_t flag)
707 {
708     uint32_t reg = 0U;
709     FlagStatus ret_flag = RESET;
710 
711     /* check if the flag is in CAU_STAT1 register */
712     if(RESET != (flag & FLAG_MASK)) {
713         reg = CAU_STAT1;
714     } else {
715         /* the flag is in CAU_STAT0 register */
716         reg = CAU_STAT0;
717     }
718 
719     /* check the status of the specified CAU flag */
720     if(RESET != (reg & flag)) {
721         ret_flag = SET;
722     }
723 
724     return ret_flag;
725 }
726