1 /**
2 *
3 * \file
4 *
5 * \brief SAM Advanced Encryption Standard driver.
6 *
7 * This file defines a useful set of functions for the AES on SAM devices.
8 *
9 * Copyright (c) 2014-2016 Atmel Corporation. All rights reserved.
10 *
11 * \asf_license_start
12 *
13 * \page License
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions are met:
17 *
18 * 1. Redistributions of source code must retain the above copyright notice,
19 * this list of conditions and the following disclaimer.
20 *
21 * 2. Redistributions in binary form must reproduce the above copyright notice,
22 * this list of conditions and the following disclaimer in the documentation
23 * and/or other materials provided with the distribution.
24 *
25 * 3. The name of Atmel may not be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * 4. This software may only be redistributed and used in connection with an
29 * Atmel microcontroller product.
30 *
31 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
32 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
33 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
34 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
35 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
40 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGE.
42 *
43 * \asf_license_stop
44 *
45 */
46 /*
47 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
48 */
49
50 #include <aes.h>
51 #include <system.h>
52
53 /**
54 * \brief Initializes an AES configuration structure to defaults.
55 *
56 * Initializes the specified AES configuration structure to a set of
57 * known default values.
58 *
59 * \note This function should be called to initialize <b>all</b> new instances of
60 * AES configuration structures before they are further modified by the user
61 * application.
62 *
63 * The default configuration is as follows:
64 * - Data encryption
65 * - 128-bit AES key size
66 * - 128-bit cipher feedback size
67 * - Manual start mode
68 * - Electronic Codebook (ECB) mode
69 * - All countermeasures are enabled
70 * - XRO key is disabled
71 * - Key generation is disabled
72 * - Last output data mode is disabled
73 *
74 * \param[out] config Pointer to an AES configuration structure
75 */
aes_get_config_defaults(struct aes_config * const config)76 void aes_get_config_defaults(
77 struct aes_config *const config)
78 {
79
80 /* Sanity check arguments */
81 Assert(config);
82 config->encrypt_mode = AES_ENCRYPTION;
83 config->key_size = AES_KEY_SIZE_128;
84 config->start_mode = AES_MANUAL_START;
85 config->opmode= AES_ECB_MODE;
86 config->cfb_size = AES_CFB_SIZE_128;
87 config->ctype = AES_COUNTERMEASURE_TYPE_ALL;
88 config->enable_xor_key = false;
89 config->enable_key_gen = false;
90 config->lod = false;
91 }
92
93 /**
94 * \brief Initialize the AES module.
95 *
96 * \param[out] module Pointer to the software instance struct
97 * \param[in] hw Module hardware register base address pointer
98 * \param[in] config Pointer to an AES configuration structure
99 */
aes_init(struct aes_module * const module,Aes * const hw,struct aes_config * const config)100 void aes_init(
101 struct aes_module *const module,
102 Aes *const hw,
103 struct aes_config *const config)
104 {
105 /* Sanity check arguments */
106 Assert(hw);
107 Assert(config);
108 Assert(module);
109
110 /* Enable clock for AES */
111 system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, MCLK_APBCMASK_AES);
112
113 /* Perform a software reset */
114 hw->CTRLA.reg = AES_CTRLA_SWRST;
115
116 /* Initialize the AES with new configurations */
117 aes_set_config(module,hw, config);
118 }
119
120 /**
121 * \brief Enable the AES module.
122 *
123 * \param[in,out] module Pointer to the software instance struct
124 */
aes_enable(struct aes_module * const module)125 void aes_enable(struct aes_module *const module)
126 {
127 Assert(module);
128 Assert(module->hw);
129 module->hw->CTRLA.reg |= AES_CTRLA_ENABLE;
130
131 }
132
133 /**
134 * \brief Disable the AES module.
135 * \param[in] module Pointer to the software instance struct
136 */
aes_disable(struct aes_module * const module)137 void aes_disable(struct aes_module *const module)
138 {
139 Assert(module);
140 Assert(module->hw);
141
142 /* Disbale interrupt */
143 module->hw->INTENCLR.reg = AES_INTENCLR_MASK;
144 /* Clear interrupt flag */
145 module->hw->INTFLAG.reg = AES_INTFLAG_MASK;
146
147 module->hw->CTRLA.reg &= (~AES_CTRLA_ENABLE);
148 }
149
150 /**
151 * \brief Configure the AES module.
152 *
153 * \param[out] module Pointer to the software instance struct
154 * \param[in] hw Module hardware register base address pointer
155 * \param[in] config Pointer to an AES configuration structure
156 */
aes_set_config(struct aes_module * const module,Aes * const hw,struct aes_config * const config)157 void aes_set_config(
158 struct aes_module *const module,
159 Aes *const hw,
160 struct aes_config *const config)
161 {
162 uint32_t ul_mode = 0;
163
164 /* Validate arguments. */
165 Assert(hw);
166 Assert(config);
167 Assert(module);
168
169 module->opmode = config->opmode;
170 module->hw = hw;
171 module->key_size = config->key_size;
172 module->cfb_size = config->cfb_size;
173
174 ul_mode |= (config->encrypt_mode << AES_CTRLA_CIPHER_Pos)
175 | (config->start_mode << AES_CTRLA_STARTMODE_Pos)
176 | (config->key_size << AES_CTRLA_KEYSIZE_Pos)
177 | (config->opmode << AES_CTRLA_AESMODE_Pos)
178 | (config->cfb_size << AES_CTRLA_CFBS_Pos)
179 | (AES_CTRLA_CTYPE(config->ctype))
180 | (config->enable_xor_key << AES_CTRLA_XORKEY_Pos)
181 | (config->enable_key_gen << AES_CTRLA_KEYGEN_Pos)
182 | (config->lod << AES_CTRLA_LOD_Pos);
183 if (hw->CTRLA.reg & AES_CTRLA_ENABLE) {
184 aes_disable(module);
185 hw->CTRLA.reg = ul_mode;
186 aes_enable(module);
187 } else {
188 hw->CTRLA.reg = ul_mode;
189 }
190 }
191
192 /**
193 * \brief Write the 128/192/256-bit cryptographic key.
194 *
195 * \param[in] module Pointer to the software instance struct
196 * \param[in] key Pointer to 4/6/8 contiguous 32-bit words
197 *
198 * \note The key size depends on the current AES configuration.
199 */
aes_write_key(struct aes_module * const module,const uint32_t * key)200 void aes_write_key(
201 struct aes_module *const module,
202 const uint32_t *key)
203 {
204 uint32_t i, key_length = 0;
205
206 /* Validate arguments. */
207 Assert(module);
208 Assert(module->hw);
209 Assert(key);
210
211 switch (module->key_size) {
212 case AES_KEY_SIZE_128:
213 key_length = 4;
214 break;
215
216 case AES_KEY_SIZE_192:
217 key_length = 6;
218 break;
219
220 case AES_KEY_SIZE_256:
221 key_length = 8;
222 break;
223
224 default:
225 break;
226 }
227
228 for (i = 0; i < key_length; i++) {
229 module->hw->KEYWORD[i].reg = *key;
230 key++;
231 }
232 }
233
234 /**
235 * \brief Write the initialization vector (for the CBC, CFB, OFB, CTR, and GCM
236 * cipher modes).
237 *
238 * \param[in] module Pointer to the software instance struct
239 * \param[in] vector Pointer to four contiguous 32-bit words
240 */
aes_write_init_vector(struct aes_module * const module,const uint32_t * vector)241 void aes_write_init_vector(
242 struct aes_module *const module,
243 const uint32_t *vector)
244 {
245 uint32_t i;
246
247 /* Validate arguments. */
248 Assert(module);
249 Assert(module->hw);
250 Assert(module->opmode != AES_ECB_MODE);
251
252 for (i = 0; i < 4; i++) {
253 module->hw->INTVECTV[i].reg = *vector;
254 vector++;
255 }
256 }
257
258 /**
259 * \brief Write the input data (four consecutive 32-bit words).
260 *
261 * \param[in] module Pointer to the software instance struct
262 * \param[in] input_data_buffer Pointer to an input data buffer
263 */
aes_write_input_data(struct aes_module * const module,const uint32_t * input_data_buffer)264 void aes_write_input_data(
265 struct aes_module *const module,
266 const uint32_t *input_data_buffer)
267 {
268 uint32_t i;
269
270 /* Validate arguments. */
271 Assert(module);
272 Assert(module->hw);;
273 Assert(input_data_buffer);
274
275 module->hw->DATABUFPTR.reg = 0;
276 if (module->opmode == AES_CFB_MODE
277 && module->cfb_size == AES_CFB_SIZE_64){
278 for (i = 0; i < 2; i++) {
279 module->hw->INDATA.reg = *input_data_buffer;
280 input_data_buffer++;
281 }
282 } else if (module->opmode == AES_CFB_MODE
283 && (module->cfb_size == AES_CFB_SIZE_32 || module->cfb_size == AES_CFB_SIZE_16)){
284 module->hw->INDATA.reg = *input_data_buffer;
285 } else {
286 for (i = 0; i < 4; i++) {
287 module->hw->INDATA.reg = *input_data_buffer;
288 input_data_buffer++;
289 }
290 }
291 }
292
293 /**
294 * \brief Read the output data.
295 *
296 * \note The data buffer that holds the processed data must be large enough to hold
297 * four consecutive 32-bit words.
298 *
299 * \param[in] module Pointer to the software instance struct
300 * \param[in] output_data_buffer Pointer to an output buffer
301 */
aes_read_output_data(struct aes_module * const module,uint32_t * output_data_buffer)302 void aes_read_output_data(
303 struct aes_module *const module,
304 uint32_t *output_data_buffer)
305 {
306 uint32_t i;
307
308 /* Validate arguments. */
309 Assert(module);
310 Assert(module->hw);
311 Assert(output_data_buffer);
312
313 module->hw->DATABUFPTR.reg = 0;
314 if (module->opmode == AES_CFB_MODE
315 && module->cfb_size == AES_CFB_SIZE_64){
316 for (i = 0; i < 2; i++) {
317 *output_data_buffer = module->hw->INDATA.reg;
318 output_data_buffer++;
319 }
320 } else if (module->opmode == AES_CFB_MODE
321 && (module->cfb_size == AES_CFB_SIZE_32 || module->cfb_size == AES_CFB_SIZE_16)){
322 *output_data_buffer = module->hw->INDATA.reg;
323 } else {
324 for (i = 0; i < 4; i++) {
325 *output_data_buffer = module->hw->INDATA.reg;
326 output_data_buffer++;
327 }
328 }
329 }
330