1 /*!
2 \file gd32l23x_cau_tdes.c
3 \brief CAU TDES 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
37 #define TDESBSY_TIMEOUT ((uint32_t)0x00010000U)
38
39 /* TDES calculate process */
40 static ErrStatus cau_tdes_calculate(uint8_t *input, uint32_t in_length, uint8_t *output);
41
42 /*!
43 \brief encrypt and decrypt using TDES in ECB mode
44 \param[in] cau_parameter: pointer to the input structure
45 alg_dir: algorithm dirctory
46 CAU_ENCRYPT, CAU_DECRYPT
47 key: key, 24 bytes
48 input: input data
49 in_length: input data length in bytes, must be a multiple of 8 bytes
50 \param[out] output: pointer to the output structure
51 \retval ErrStatus: SUCCESS or ERROR
52 */
cau_tdes_ecb(cau_parameter_struct * cau_parameter,uint8_t * output)53 ErrStatus cau_tdes_ecb(cau_parameter_struct *cau_parameter, uint8_t *output)
54 {
55 ErrStatus ret = ERROR;
56 cau_key_parameter_struct key_initpara;
57 uint32_t keyaddr = (uint32_t)(cau_parameter->key);
58 uint32_t inputaddr = (uint32_t)(cau_parameter->input);
59 uint32_t outputaddr = (uint32_t)output;
60
61 /* key structure initialization */
62 cau_key_struct_para_init(&key_initpara);
63 /* initialize the CAU peripheral */
64 cau_init(cau_parameter->alg_dir, CAU_MODE_TDES_ECB, CAU_SWAPPING_8BIT);
65
66 /* key initialization */
67 key_initpara.key_1_high = __REV(*(uint32_t *)(keyaddr));
68 keyaddr += 4U;
69 key_initpara.key_1_low = __REV(*(uint32_t *)(keyaddr));
70 keyaddr += 4U;
71 key_initpara.key_2_high = __REV(*(uint32_t *)(keyaddr));
72 keyaddr += 4U;
73 key_initpara.key_2_low = __REV(*(uint32_t *)(keyaddr));
74 keyaddr += 4U;
75 key_initpara.key_3_high = __REV(*(uint32_t *)(keyaddr));
76 keyaddr += 4U;
77 key_initpara.key_3_low = __REV(*(uint32_t *)(keyaddr));
78 cau_key_init(&key_initpara);
79
80 /* flush the IN and OUT FIFOs */
81 cau_fifo_flush();
82
83 /* enable the CAU peripheral */
84 cau_enable();
85 /* TDES calculate process */
86 ret = cau_tdes_calculate((uint8_t *)inputaddr, cau_parameter->in_length, (uint8_t *)outputaddr);
87 /* disable the CAU peripheral */
88 cau_disable();
89
90 return ret;
91 }
92
93 /*!
94 \brief encrypt and decrypt using TDES in CBC mode
95 \param[in] cau_parameter: pointer to the input structure
96 alg_dir: algorithm dirctory
97 CAU_ENCRYPT, CAU_DECRYPT
98 key: key, 24 bytes
99 iv: initialization vector, 8 bytes
100 input: input data
101 in_length: input data length in bytes, must be a multiple of 8 bytes
102 \param[out] output: pointer to the output structure
103 \retval ErrStatus: SUCCESS or ERROR
104 */
cau_tdes_cbc(cau_parameter_struct * cau_parameter,uint8_t * output)105 ErrStatus cau_tdes_cbc(cau_parameter_struct *cau_parameter, uint8_t *output)
106 {
107 ErrStatus ret = ERROR;
108 cau_key_parameter_struct key_initpara;
109 cau_iv_parameter_struct iv_initpara;
110 uint32_t keyaddr = (uint32_t)(cau_parameter->key);
111 uint32_t inputaddr = (uint32_t)(cau_parameter->input);
112 uint32_t outputaddr = (uint32_t)output;
113 uint32_t ivaddr = (uint32_t)(cau_parameter->iv);
114
115 /* key structure initialization */
116 cau_key_struct_para_init(&key_initpara);
117 /* initialize the CAU peripheral */
118 cau_init(cau_parameter->alg_dir, CAU_MODE_TDES_CBC, CAU_SWAPPING_8BIT);
119
120 /* key initialization */
121 key_initpara.key_1_high = __REV(*(uint32_t *)(keyaddr));
122 keyaddr += 4U;
123 key_initpara.key_1_low = __REV(*(uint32_t *)(keyaddr));
124 keyaddr += 4U;
125 key_initpara.key_2_high = __REV(*(uint32_t *)(keyaddr));
126 keyaddr += 4U;
127 key_initpara.key_2_low = __REV(*(uint32_t *)(keyaddr));
128 keyaddr += 4U;
129 key_initpara.key_3_high = __REV(*(uint32_t *)(keyaddr));
130 keyaddr += 4U;
131 key_initpara.key_3_low = __REV(*(uint32_t *)(keyaddr));
132 cau_key_init(&key_initpara);
133
134 /* vectors initialization */
135 iv_initpara.iv_0_high = __REV(*(uint32_t *)(ivaddr));
136 ivaddr += 4U;
137 iv_initpara.iv_0_low = __REV(*(uint32_t *)(ivaddr));
138 cau_iv_init(&iv_initpara);
139
140 /* flush the IN and OUT FIFOs */
141 cau_fifo_flush();
142 /* enable the CAU peripheral */
143 cau_enable();
144 /* TDES calculate process */
145 ret = cau_tdes_calculate((uint8_t *)inputaddr, cau_parameter->in_length, (uint8_t *)outputaddr);
146 /* disable the CAU peripheral */
147 cau_disable();
148
149 return ret;
150 }
151
152 /*!
153 \brief TDES calculate process
154 \param[in] input: pointer to the input buffer
155 \param[in] in_length: length of the input buffer in bytes, must be a multiple of 8 bytes
156 \param[out] output: pointer to the returned buffer
157 \retval ErrStatus: SUCCESS or ERROR
158 */
cau_tdes_calculate(uint8_t * input,uint32_t in_length,uint8_t * output)159 static ErrStatus cau_tdes_calculate(uint8_t *input, uint32_t in_length, uint8_t *output)
160 {
161 uint32_t inputaddr = (uint32_t)input;
162 uint32_t outputaddr = (uint32_t)output;
163 uint32_t i = 0U;
164 __IO uint32_t counter = 0U;
165 uint32_t busystatus = 0U;
166
167 /* the clock is not enabled or there is no embeded CAU peripheral */
168 if(DISABLE == cau_enable_state_get()) {
169 return ERROR;
170 }
171
172 for(i = 0U; i < in_length; i += 8U) {
173 /* write data to the IN FIFO */
174 cau_data_write(*(uint32_t *)(inputaddr));
175 inputaddr += 4U;
176 cau_data_write(*(uint32_t *)(inputaddr));
177 inputaddr += 4U;
178
179 /* wait until the complete message has been processed */
180 counter = 0U;
181 do {
182 busystatus = cau_flag_get(CAU_FLAG_BUSY);
183 counter++;
184 } while((TDESBSY_TIMEOUT != counter) && (RESET != busystatus));
185
186 if(RESET != busystatus) {
187 return ERROR;
188 } else {
189 /* read the output block from the output FIFO */
190 *(uint32_t *)(outputaddr) = cau_data_read();
191 outputaddr += 4U;
192 *(uint32_t *)(outputaddr) = cau_data_read();
193 outputaddr += 4U;
194 }
195 }
196
197 return SUCCESS;
198 }
199