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