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