1 /**
2 * \file
3 *
4 * \brief AES Advanced Encryption Standard(Sync) functionality declaration.
5 *
6 * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Subject to your compliance with these terms, you may use Microchip
13 * software and any derivatives exclusively with Microchip products.
14 * It is your responsibility to comply with third party license terms applicable
15 * to your use of third party software (including open source software) that
16 * may accompany Microchip software.
17 *
18 * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
19 * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
20 * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
21 * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
22 * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
23 * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
24 * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
25 * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
26 * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
27 * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
28 * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
29 *
30 * \asf_license_stop
31 *
32 */
33
34 #include <hal_aes_sync.h>
35
36 #define DRIVER_VERSION 0x00000001u
37
38 static inline void aes_sync_cfb_crypt_first_unaligned_data(const enum aes_action enc, const uint8_t **input,
39 uint8_t **output, uint32_t *length, uint8_t *iv,
40 uint32_t *iv_ofst, uint32_t block_bytes);
41
42 static inline void aes_sync_cfb_crypt_last_unaligned_data(struct aes_sync_descriptor *descr, const enum aes_action enc,
43 const uint8_t *input, uint8_t *output, uint32_t length,
44 uint8_t *iv, uint32_t *iv_ofst);
45 /**
46 * \brief Initialize AES.
47 */
aes_sync_init(struct aes_sync_descriptor * descr,void * const hw)48 int32_t aes_sync_init(struct aes_sync_descriptor *descr, void *const hw)
49 {
50 ASSERT(descr && hw);
51
52 return _aes_sync_init(&descr->dev, hw);
53 }
54
55 /**
56 * \brief Deinitialize AES.
57 */
aes_sync_deinit(struct aes_sync_descriptor * descr)58 int32_t aes_sync_deinit(struct aes_sync_descriptor *descr)
59 {
60 ASSERT(descr);
61
62 return _aes_sync_deinit(&descr->dev);
63 }
64
65 /**
66 * \brief Enable AES
67 */
aes_sync_enable(struct aes_sync_descriptor * descr)68 int32_t aes_sync_enable(struct aes_sync_descriptor *descr)
69 {
70 ASSERT(descr);
71
72 return _aes_sync_enable(&descr->dev);
73 }
74
75 /**
76 * \brief Disable AES
77 */
aes_sync_disable(struct aes_sync_descriptor * descr)78 int32_t aes_sync_disable(struct aes_sync_descriptor *descr)
79 {
80 ASSERT(descr);
81
82 return _aes_sync_disable(&descr->dev);
83 }
84
85 /**
86 * \brief Set AES Key (encryption)
87 */
aes_sync_set_encrypt_key(struct aes_sync_descriptor * descr,const uint8_t * key,const enum aes_keysize size)88 int32_t aes_sync_set_encrypt_key(struct aes_sync_descriptor *descr, const uint8_t *key, const enum aes_keysize size)
89 {
90 ASSERT(descr && key);
91 return _aes_sync_set_key(&descr->dev, key, size);
92 }
93
94 /**
95 * \brief Set AES Key (decryption)
96 */
aes_sync_set_decrypt_key(struct aes_sync_descriptor * descr,const uint8_t * key,const enum aes_keysize size)97 int32_t aes_sync_set_decrypt_key(struct aes_sync_descriptor *descr, const uint8_t *key, const enum aes_keysize size)
98 {
99 ASSERT(descr && key);
100 return _aes_sync_set_key(&descr->dev, key, size);
101 }
102
103 /**
104 * \brief AES-ECB block encryption/decryption
105 */
aes_sync_ecb_crypt(struct aes_sync_descriptor * descr,const enum aes_action enc,const uint8_t * input,uint8_t * output)106 int32_t aes_sync_ecb_crypt(struct aes_sync_descriptor *descr, const enum aes_action enc, const uint8_t *input,
107 uint8_t *output)
108 {
109 ASSERT(descr && input && output);
110 return _aes_sync_ecb_crypt(&descr->dev, enc, input, output);
111 }
112
113 /**
114 * \brief AES-CBC block encryption/decryption
115 */
aes_sync_cbc_crypt(struct aes_sync_descriptor * descr,const enum aes_action enc,const uint8_t * input,uint8_t * output,uint32_t length,uint8_t iv[16])116 int32_t aes_sync_cbc_crypt(struct aes_sync_descriptor *descr, const enum aes_action enc, const uint8_t *input,
117 uint8_t *output, uint32_t length, uint8_t iv[16])
118 {
119 ASSERT(descr && input && output && length && iv);
120 return _aes_sync_cbc_crypt(&descr->dev, enc, input, output, length, iv);
121 }
122
123 /**
124 * \brief AES-CFB encryption/decryption first block unaligned data
125 */
aes_sync_cfb_crypt_first_unaligned_data(const enum aes_action enc,const uint8_t ** input,uint8_t ** output,uint32_t * length,uint8_t * iv,uint32_t * iv_ofst,uint32_t block_bytes)126 static inline void aes_sync_cfb_crypt_first_unaligned_data(const enum aes_action enc, const uint8_t **input,
127 uint8_t **output, uint32_t *length, uint8_t *iv,
128 uint32_t *iv_ofst, uint32_t block_bytes)
129 {
130 if (*iv_ofst) {
131 while (((*iv_ofst) < block_bytes) && *length) {
132 **output = (**input) ^ iv[*iv_ofst];
133 /* Update IV for next crypt */
134 iv[*iv_ofst] = (enc == AES_ENCRYPT) ? (**output) : (**input);
135 (*input)++;
136 (*output)++;
137 (*iv_ofst)++;
138 (*length)--;
139 }
140 *iv_ofst &= (block_bytes - 1);
141 }
142 }
143
144 /**
145 * \brief AES-CFB encryption/decryption last block unaligned data
146 */
aes_sync_cfb_crypt_last_unaligned_data(struct aes_sync_descriptor * descr,const enum aes_action enc,const uint8_t * input,uint8_t * output,uint32_t length,uint8_t * iv,uint32_t * iv_ofst)147 static inline void aes_sync_cfb_crypt_last_unaligned_data(struct aes_sync_descriptor *descr, const enum aes_action enc,
148 const uint8_t *input, uint8_t *output, uint32_t length,
149 uint8_t *iv, uint32_t *iv_ofst)
150 {
151 if (length) {
152 _aes_sync_ecb_crypt(&descr->dev, AES_ENCRYPT, iv, iv);
153 while ((*iv_ofst) < length) {
154 *output = (*input) ^ iv[*iv_ofst];
155 /* Update IV for next crypt */
156 iv[*iv_ofst] = (enc == AES_ENCRYPT) ? (*output) : (*input);
157 input++;
158 output++;
159 (*iv_ofst)++;
160 }
161 }
162 }
163
164 /**
165 * \brief AES-CFB128 block encryption/decryption
166 */
aes_sync_cfb128_crypt(struct aes_sync_descriptor * descr,const enum aes_action enc,const uint8_t * input,uint8_t * output,uint32_t length,uint8_t * iv,uint32_t * iv_ofst)167 int32_t aes_sync_cfb128_crypt(struct aes_sync_descriptor *descr, const enum aes_action enc, const uint8_t *input,
168 uint8_t *output, uint32_t length, uint8_t *iv, uint32_t *iv_ofst)
169 {
170 ASSERT(descr && input && output && length && iv && iv_ofst && *iv_ofst < 16);
171
172 aes_sync_cfb_crypt_first_unaligned_data(enc, &input, &output, &length, iv, iv_ofst, 16);
173 /* if left length more than 1 block, then use cfb128 encrypt */
174 if (length >> 4) {
175 _aes_sync_cfb128_crypt(&descr->dev, enc, input, output, (length & ~0xF), iv);
176 input += (length & ~0xF);
177 output += (length & ~0xF);
178 length = length & 0xF;
179 }
180 aes_sync_cfb_crypt_last_unaligned_data(descr, enc, input, output, length, iv, iv_ofst);
181
182 return ERR_NONE;
183 }
184
185 /**
186 * \brief AES-CFB64 block encryption/decryption
187 */
aes_sync_cfb64_crypt(struct aes_sync_descriptor * descr,const enum aes_action enc,const uint8_t * input,uint8_t * output,uint32_t length,uint8_t * iv,uint32_t * iv_ofst)188 int32_t aes_sync_cfb64_crypt(struct aes_sync_descriptor *descr, const enum aes_action enc, const uint8_t *input,
189 uint8_t *output, uint32_t length, uint8_t *iv, uint32_t *iv_ofst)
190 {
191 ASSERT(descr && input && output && length && iv && iv_ofst && *iv_ofst < 8);
192
193 aes_sync_cfb_crypt_first_unaligned_data(enc, &input, &output, &length, iv, iv_ofst, 8);
194 /* if left length more than 1 block, then use cfb64 encrypt */
195 if (length >> 3) {
196 _aes_sync_cfb64_crypt(&descr->dev, enc, input, output, (length & ~0x7), iv);
197 input += (length & ~0x7);
198 output += (length & ~0x7);
199 length = length & 0x7;
200 }
201 aes_sync_cfb_crypt_last_unaligned_data(descr, enc, input, output, length, iv, iv_ofst);
202
203 return ERR_NONE;
204 }
205
206 /**
207 * \brief AES-CFB32 block encryption/decryption
208 *
209 * \param[in] desc AES descriptor
210 * \param[in] enc AES_SYNC_ENCRYPT or AES_SYNC_DECRYPT
211 * \param[in] input buffer holding the input data
212 * \param[out] output buffer holding the output data
213 * \param[out] length byte length of the input data
214 * \param[in, out] iv initialization Vector (updated after use)
215 * \param[in, out] iv_ofst offset in IV (updated after use)
216 *
217 * \return ERR_NONE if successful
218 */
aes_sync_cfb32_crypt(struct aes_sync_descriptor * descr,const enum aes_action enc,const uint8_t * input,uint8_t * output,uint32_t length,uint8_t * iv,uint32_t * iv_ofst)219 int32_t aes_sync_cfb32_crypt(struct aes_sync_descriptor *descr, const enum aes_action enc, const uint8_t *input,
220 uint8_t *output, uint32_t length, uint8_t *iv, uint32_t *iv_ofst)
221 {
222 ASSERT(descr && input && output && length && iv && iv_ofst && *iv_ofst < 4);
223
224 aes_sync_cfb_crypt_first_unaligned_data(enc, &input, &output, &length, iv, iv_ofst, 4);
225 /* if left length more than 1 block, then use cfb32 encrypt */
226 if (length >> 2) {
227 _aes_sync_cfb32_crypt(&descr->dev, enc, input, output, (length & ~0x3), iv);
228 input += (length & ~0x3);
229 output += (length & ~0x3);
230 length = length & 0x3;
231 }
232 aes_sync_cfb_crypt_last_unaligned_data(descr, enc, input, output, length, iv, iv_ofst);
233
234 return ERR_NONE;
235 }
236
237 /**
238 * \brief AES-CFB16 block encryption/decryption
239 */
aes_sync_cfb16_crypt(struct aes_sync_descriptor * descr,const enum aes_action enc,const uint8_t * input,uint8_t * output,uint32_t length,uint8_t * iv,uint32_t * iv_ofst)240 int32_t aes_sync_cfb16_crypt(struct aes_sync_descriptor *descr, const enum aes_action enc, const uint8_t *input,
241 uint8_t *output, uint32_t length, uint8_t *iv, uint32_t *iv_ofst)
242 {
243 ASSERT(descr && input && output && length && iv && iv_ofst && *iv_ofst < 2);
244
245 aes_sync_cfb_crypt_first_unaligned_data(enc, &input, &output, &length, iv, iv_ofst, 2);
246
247 /* if left length more than 1 block, then use cfb16 encrypt */
248 if (length >> 1) {
249 _aes_sync_cfb16_crypt(&descr->dev, enc, input, output, (length & ~0x1), iv);
250 input += (length & ~0x1);
251 output += (length & ~0x1);
252 length = length & 0x1;
253 }
254 aes_sync_cfb_crypt_last_unaligned_data(descr, enc, input, output, length, iv, iv_ofst);
255
256 return ERR_NONE;
257 }
258
259 /**
260 * \brief AES-CFB8 block encryption/decryption
261 */
aes_sync_cfb8_crypt(struct aes_sync_descriptor * descr,const enum aes_action enc,const uint8_t * input,uint8_t * output,uint32_t length,uint8_t * iv)262 int32_t aes_sync_cfb8_crypt(struct aes_sync_descriptor *descr, const enum aes_action enc, const uint8_t *input,
263 uint8_t *output, uint32_t length, uint8_t *iv)
264 {
265 ASSERT(descr && input && output && length && iv);
266 return _aes_sync_cfb8_crypt(&descr->dev, enc, input, output, length, iv);
267 }
268
269 /**
270 * \brief AES-OFB block encryption/decryption
271 */
aes_sync_ofb_crypt(struct aes_sync_descriptor * descr,const uint8_t * input,uint8_t * output,uint32_t length,uint8_t * iv,uint32_t * iv_ofst)272 int32_t aes_sync_ofb_crypt(struct aes_sync_descriptor *descr, const uint8_t *input, uint8_t *output, uint32_t length,
273 uint8_t *iv, uint32_t *iv_ofst)
274 {
275 ASSERT(descr && input && output && length && iv && iv_ofst && *iv_ofst < 16);
276
277 /* Encrypt first unaligned block data */
278 if (*iv_ofst) {
279 while ((*iv_ofst) < 16 && length) {
280 *output = (uint8_t)((*input) ^ iv[*iv_ofst]);
281 input++;
282 output++;
283 (*iv_ofst)++;
284 length--;
285 }
286 *iv_ofst &= 0xF;
287 }
288
289 /* if left length more than 1 block, then use cfb128 encrypt */
290 if (length >> 4) {
291 _aes_sync_ofb_crypt(&descr->dev, input, output, (length & ~0xF), iv);
292 input += (length & ~0xF);
293 output += (length & ~0xF);
294 length = length & 0xF;
295 *iv_ofst = 0;
296 }
297 /* Encrypt last unaligned data and update iv */
298 if (length) {
299 _aes_sync_ecb_crypt(&descr->dev, AES_ENCRYPT, iv, iv);
300 while ((*iv_ofst) < length) {
301 *output = (*input) ^ iv[*iv_ofst];
302 input++;
303 output++;
304 (*iv_ofst)++;
305 }
306 }
307 return ERR_NONE;
308 }
309
310 /**
311 * \brief AES-CTR block encryption/decryption
312 */
aes_sync_ctr_crypt(struct aes_sync_descriptor * descr,const uint8_t * input,uint8_t * output,uint32_t length,uint8_t buffer[16],uint8_t nc[16],uint32_t * nc_ofst)313 int32_t aes_sync_ctr_crypt(struct aes_sync_descriptor *descr, const uint8_t *input, uint8_t *output, uint32_t length,
314 uint8_t buffer[16], uint8_t nc[16], uint32_t *nc_ofst)
315 {
316 int32_t i;
317 ASSERT(descr && input && output && length && nc && nc_ofst && *nc_ofst < 16);
318
319 /* Encrypt first unaligned block data */
320 if (*nc_ofst) {
321 while ((*nc_ofst) < 16 && length) {
322 *output++ = (*input) ^ buffer[*nc_ofst];
323 input++;
324 (*nc_ofst)++;
325 length--;
326 }
327 *nc_ofst &= 0xF;
328 }
329 /* if left length more than 1 block, then use ctr encrypt */
330 if (length >> 4) {
331 _aes_sync_ctr_crypt(&descr->dev, input, output, (length & ~0xF), nc);
332 input += (length & ~0xF);
333 output += (length & ~0xF);
334 length = length & 0xF;
335 }
336 /* Encrypt last unaligned data and update buffer */
337 if (length) {
338 _aes_sync_ecb_crypt(&descr->dev, AES_ENCRYPT, nc, buffer);
339 for (i = 16; i > 0; i--) {
340 if (++nc[i - 1] != 0)
341 break;
342 }
343 while (*nc_ofst < length) {
344 *output++ = (*input) ^ buffer[*nc_ofst];
345 input++;
346 (*nc_ofst)++;
347 }
348 }
349
350 return ERR_NONE;
351 }
352
353 /**
354 * \brief AES-GCM block encryption/decryption
355 */
aes_sync_gcm_crypt_and_tag(struct aes_sync_descriptor * const descr,const enum aes_action enc,const uint8_t * input,uint8_t * output,uint32_t length,const uint8_t * iv,uint32_t iv_len,const uint8_t * aad,uint32_t aad_len,uint8_t * tag,uint32_t tag_len)356 int32_t aes_sync_gcm_crypt_and_tag(struct aes_sync_descriptor *const descr, const enum aes_action enc,
357 const uint8_t *input, uint8_t *output, uint32_t length, const uint8_t *iv,
358 uint32_t iv_len, const uint8_t *aad, uint32_t aad_len, uint8_t *tag,
359 uint32_t tag_len)
360 {
361 ASSERT(descr && iv && iv_len);
362 ASSERT((input && output && length) || (!length));
363 ASSERT(((aad && aad_len) || !aad_len));
364 ASSERT((tag && tag_len && (tag_len <= 16)) || !tag_len);
365 return _aes_sync_gcm_crypt_and_tag(&descr->dev, enc, input, output, length, iv, iv_len, aad, aad_len, tag, tag_len);
366 }
367
368 /**
369 * \brief AES-GCM block encryption
370 */
aes_sync_gcm_auth_decrypt(struct aes_sync_descriptor * const descr,const uint8_t * input,uint8_t * output,uint32_t length,const uint8_t * iv,uint32_t iv_len,const uint8_t * aad,uint32_t aad_len,const uint8_t * tag,uint32_t tag_len)371 int32_t aes_sync_gcm_auth_decrypt(struct aes_sync_descriptor *const descr, const uint8_t *input, uint8_t *output,
372 uint32_t length, const uint8_t *iv, uint32_t iv_len, const uint8_t *aad,
373 uint32_t aad_len, const uint8_t *tag, uint32_t tag_len)
374 {
375 uint8_t vtag[16];
376 uint32_t index;
377 int32_t result;
378
379 ASSERT(descr && iv && iv_len);
380 ASSERT((input && output && length) || (!length));
381 ASSERT(((aad && aad_len) || !aad_len));
382 ASSERT((tag && tag_len && (tag_len <= 16)) || !tag_len);
383
384 result = _aes_sync_gcm_crypt_and_tag(
385 &descr->dev, AES_DECRYPT, input, output, length, iv, iv_len, aad, aad_len, vtag, tag_len);
386 if (result != ERR_NONE) {
387 return result;
388 }
389 for (index = 0; index < tag_len; index++) {
390 if (vtag[index] != tag[index]) {
391 return ERR_INVALID_DATA;
392 }
393 }
394 return ERR_NONE;
395 }
396
397 /**
398 * \brief AES-GCM block start
399 */
aes_sync_gcm_start(struct aes_sync_descriptor * const descr,const enum aes_action enc,const uint8_t * iv,uint32_t iv_len,const uint8_t * aad,uint32_t aad_len)400 int32_t aes_sync_gcm_start(struct aes_sync_descriptor *const descr, const enum aes_action enc, const uint8_t *iv,
401 uint32_t iv_len, const uint8_t *aad, uint32_t aad_len)
402 {
403 ASSERT(descr && iv && iv_len);
404 ASSERT((aad && aad_len) || !aad_len);
405 return _aes_sync_gcm_start(&descr->dev, enc, iv, iv_len, aad, aad_len);
406 }
407
408 /**
409 * \brief AES-GCM block update
410 */
aes_sync_gcm_update(struct aes_sync_descriptor * const descr,const uint8_t * input,uint8_t * output,uint32_t length)411 int32_t aes_sync_gcm_update(struct aes_sync_descriptor *const descr, const uint8_t *input, uint8_t *output,
412 uint32_t length)
413 {
414 ASSERT(descr);
415 ASSERT((input && output && length) || (!length));
416 return _aes_sync_gcm_update(&descr->dev, input, output, length);
417 }
418
419 /**
420 * \brief AES-GCM block finish
421 */
aes_sync_gcm_finish(struct aes_sync_descriptor * const descr,uint8_t * tag,uint32_t tag_len)422 int32_t aes_sync_gcm_finish(struct aes_sync_descriptor *const descr, uint8_t *tag, uint32_t tag_len)
423 {
424 ASSERT(descr && ((tag && tag_len && (tag_len <= 16)) || !tag_len));
425 return _aes_sync_gcm_finish(&descr->dev, tag, tag_len);
426 }
427
428 /**
429 * \brief AES-CCM block encryption/decryption
430 */
aes_sync_ccm_crypt_and_tag(struct aes_sync_descriptor * const descr,const enum aes_action enc,const uint8_t * input,uint8_t * output,uint32_t length,const uint8_t * iv,uint32_t iv_len,const uint8_t * aad,uint32_t aad_len,uint8_t * tag,uint32_t tag_len)431 int32_t aes_sync_ccm_crypt_and_tag(struct aes_sync_descriptor *const descr, const enum aes_action enc,
432 const uint8_t *input, uint8_t *output, uint32_t length, const uint8_t *iv,
433 uint32_t iv_len, const uint8_t *aad, uint32_t aad_len, uint8_t *tag,
434 uint32_t tag_len)
435 {
436 ASSERT(descr && input && output && length && iv);
437 ASSERT((aad && aad_len) || !aad_len);
438 /* Length requirements follow the SP800-38C A.1 */
439 ASSERT(tag && (tag_len >= 4) && (tag_len <= 16) && !(tag_len % 2));
440 ASSERT((iv_len >= 7) && (iv_len <= 13));
441
442 return _aes_sync_ccm_crypt_and_tag(&descr->dev, enc, input, output, length, iv, iv_len, aad, aad_len, tag, tag_len);
443 }
444
445 /**
446 * \brief AES-CCM block authenticated decryption
447 */
aes_sync_ccm_auth_decrypt(struct aes_sync_descriptor * const descr,const uint8_t * input,uint8_t * output,uint32_t length,const uint8_t * iv,uint32_t iv_len,const uint8_t * aad,uint32_t aad_len,const uint8_t * tag,uint32_t tag_len)448 int32_t aes_sync_ccm_auth_decrypt(struct aes_sync_descriptor *const descr, const uint8_t *input, uint8_t *output,
449 uint32_t length, const uint8_t *iv, uint32_t iv_len, const uint8_t *aad,
450 uint32_t aad_len, const uint8_t *tag, uint32_t tag_len)
451 {
452 uint8_t vtag[16];
453 uint32_t index;
454 int32_t result;
455
456 ASSERT(descr && input && output && length && iv);
457 ASSERT((aad && aad_len) || !aad_len);
458 /* Length requirements follow the SP800-38C A.1 */
459 ASSERT(tag && (tag_len >= 4) && (tag_len <= 16) && !(tag_len % 2));
460 ASSERT((iv_len >= 7) && (iv_len <= 13));
461
462 result = _aes_sync_ccm_crypt_and_tag(
463 &descr->dev, AES_DECRYPT, input, output, length, iv, iv_len, aad, aad_len, vtag, tag_len);
464 if (result != ERR_NONE) {
465 return result;
466 }
467 for (index = 0; index < tag_len; index++) {
468 if (vtag[index] != tag[index]) {
469 return ERR_INVALID_DATA;
470 }
471 }
472 return ERR_NONE;
473 }
474
475 /**
476 * \brief Retrieve the current driver version
477 */
aes_sync_get_version(void)478 uint32_t aes_sync_get_version(void)
479 {
480 return DRIVER_VERSION;
481 }
482