blob: 8f6574a203a63303a482575bc4b8b343e8bef3ae [file] [log] [blame]
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001/*
2 * NIST SP800-38B compliant CMAC implementation
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21
22/*
23 * Definition of CMAC:
24 * http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
25 * RFC 4493 "The AES-CMAC Algorithm"
26 */
27
28#if !defined(MBEDTLS_CONFIG_FILE)
29#include "mbedtls/config.h"
30#else
31#include MBEDTLS_CONFIG_FILE
32#endif
33
34#if defined(MBEDTLS_CMAC_C)
35
36#include "mbedtls/cmac.h"
37
38#include <string.h>
39
40#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
41#if defined(MBEDTLS_PLATFORM_C)
42#include "mbedtls/platform.h"
43#else
44#include <stdio.h>
45#define mbedtls_printf printf
46#endif /* MBEDTLS_PLATFORM_C */
47#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
48
49/*
50 * Macros for common operations.
51 * Results in smaller compiled code than static inline functions.
52 */
53
54/*
55 * XOR 128-bit
56 */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +000057#define XOR_128( i1, i2, o ) \
Robert Cragie3d23b1d2015-12-15 07:38:11 +000058 for( i = 0; i < 16; i++ ) \
59 ( o )[i] = ( i1 )[i] ^ ( i2 )[i];
60
61/*
62 * Update the CMAC state in Mn using an input block x
63 * TODO: Compiler optimisation
64 */
65#define UPDATE_CMAC( x ) \
66 XOR_128( Mn, ( x ), Mn ); \
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +000067 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \
68 Mn, 16, Mn, &olen ) ) != 0 ) \
Robert Cragie3d23b1d2015-12-15 07:38:11 +000069 return( ret );
70
71/* Implementation that should never be optimized out by the compiler */
72static void mbedtls_zeroize( void *v, size_t n ) {
73 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
74}
75
76/*
77 * Initialize context
78 */
79void mbedtls_cmac_init( mbedtls_cmac_context *ctx )
80{
81 memset( ctx, 0, sizeof( mbedtls_cmac_context ) );
82}
83
84/*
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000085 * Multiply by u in GF(2^128)
86 *
87 * As explained in the paper, this can be achieved as
88 * If MSB(p) = 0, then p = (p << 1)
89 * If MSB(p) = 1, then p = (p << 1) ^ Rb
90 * with Rb = 0x87
91 *
92 * Input and output MUST not point to the same buffer
Robert Cragie3d23b1d2015-12-15 07:38:11 +000093 */
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000094static void multiply_by_u( unsigned char *output, const unsigned char *input )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000095{
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000096 static const unsigned char Rb[2] = { 0x00, 0x87 }; /* block size 16 only */
Robert Cragie3d23b1d2015-12-15 07:38:11 +000097 unsigned char overflow = 0;
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000098 int i;
Robert Cragie3d23b1d2015-12-15 07:38:11 +000099
100 for( i = 15; i >= 0; i-- )
101 {
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000102 output[i] = input[i] << 1 | overflow;
103 overflow = input[i] >> 7;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000104 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000105
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000106 output[15] ^= Rb[input[0] >> 7]; /* "Constant-time" operation */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000107}
108
109/*
110 * Generate subkeys
111 */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000112static int generate_subkeys( mbedtls_cmac_context *ctx )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000113{
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000114 int ret;
115 unsigned char L[16];
116 size_t olen;
117
118 /* Calculate Ek(0) */
119 memset( L, 0, 16 );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000120 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx,
121 L, 16, L, &olen ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000122 {
123 return( ret );
124 }
125
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000126 /*
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000127 * Generate K1 and K2
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000128 */
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000129 multiply_by_u( ctx->K1, L );
130 multiply_by_u( ctx->K2, ctx->K1 );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000131
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000132 return( 0 );
133}
134
135int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx,
136 mbedtls_cipher_id_t cipher,
137 const unsigned char *key,
138 unsigned int keybits )
139{
140 int ret;
141 const mbedtls_cipher_info_t *cipher_info;
142
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000143 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
144 MBEDTLS_MODE_ECB );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000145 if( cipher_info == NULL )
146 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
147
148 if( cipher_info->block_size != 16 )
149 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
150
151 mbedtls_cipher_free( &ctx->cipher_ctx );
152
153 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
154 return( ret );
155
156 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000157 MBEDTLS_ENCRYPT ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000158 {
159 return( ret );
160 }
161
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000162 return( generate_subkeys( ctx ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000163}
164
165/*
166 * Free context
167 */
168void mbedtls_cmac_free( mbedtls_cmac_context *ctx )
169{
170 mbedtls_cipher_free( &ctx->cipher_ctx );
171 mbedtls_zeroize( ctx, sizeof( mbedtls_cmac_context ) );
172}
173
174/* TODO: Use cipher padding function? */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000175static void padding( const unsigned char *lastb,
176 unsigned char *pad,
177 const size_t length )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000178{
179 size_t j;
180
181 /* original last block */
182 for( j = 0; j < 16; j++ )
183 {
184 if( j < length )
185 {
186 pad[j] = lastb[j];
187 }
188 else if( j == length )
189 {
190 pad[j] = 0x80;
191 }
192 else
193 {
194 pad[j] = 0x00;
195 }
196 }
197}
198
199/*
200 * Generate tag on complete message
201 */
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000202static int cmac_generate( mbedtls_cmac_context *ctx,
203 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000204 unsigned char *tag, size_t tag_len )
205{
206 unsigned char Mn[16];
207 unsigned char M_last[16];
208 unsigned char padded[16];
209 int n, i, j, ret, flag;
210 size_t olen;
211
212 /*
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000213 * Check in_len requirements: SP800-38B A
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000214 * 4 is a worst case bottom limit
215 */
216 if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
217 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
218
219 /* TODO: Use cipher padding function? */
220 // mbedtls_cipher_set_padding_mode( ctx->cipher, MBEDTLS_PADDING_ONE_AND_ZEROS );
221
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000222 n = ( in_len + 15 ) / 16; /* n is number of rounds */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000223
224 if( n == 0 )
225 {
226 n = 1;
227 flag = 0;
228 }
229 else
230 {
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000231 flag = ( ( in_len % 16 ) == 0);
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000232 }
233
234 /* Calculate last block */
235 if( flag )
236 {
237 /* Last block is complete block */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000238 XOR_128( &input[16 * ( n - 1 )], ctx->K1, M_last );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000239 }
240 else
241 {
242 /* TODO: Use cipher padding function? */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000243 padding( &input[16 * ( n - 1 )], padded, in_len % 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000244 XOR_128( padded, ctx->K2, M_last );
245 }
246
247 memset( Mn, 0, 16 );
248
249 for( j = 0; j < n - 1; j++ )
250 {
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000251 UPDATE_CMAC( &input[16 * j] );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000252 }
253
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000254 UPDATE_CMAC( M_last );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000255
256 memcpy( tag, Mn, 16 );
257
258 return( 0 );
259}
260
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000261int mbedtls_cmac_generate( mbedtls_cmac_context *ctx,
262 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000263 unsigned char *tag, size_t tag_len )
264{
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000265 return( cmac_generate( ctx, input, in_len, tag, tag_len ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000266}
267
268/*
269 * Authenticated decryption
270 */
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000271int mbedtls_cmac_verify( mbedtls_cmac_context *ctx,
272 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000273 const unsigned char *tag, size_t tag_len )
274{
275 int ret;
276 unsigned char check_tag[16];
277 unsigned char i;
278 int diff;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000279
280 if( ( ret = cmac_generate( ctx, input, in_len, check_tag, tag_len ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000281 {
282 return ret;
283 }
284
285 /* Check tag in "constant-time" */
286 for( diff = 0, i = 0; i < tag_len; i++ )
287 {
288 diff |= tag[i] ^ check_tag[i];
289 }
290
291 if( diff != 0 )
292 {
293 return( MBEDTLS_ERR_CMAC_VERIFY_FAILED );
294 }
295
296 return( 0 );
297}
298
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000299int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000300 const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000301 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000302 unsigned char *tag )
303{
304 int ret;
305 unsigned char zero_key[16];
306 unsigned char int_key[16];
307
308 if( key_length == 16 )
309 {
310 /* Use key as is */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000311 memcpy( int_key, key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000312 }
313 else
314 {
315 mbedtls_cmac_context zero_ctx;
316
317 /* Key is AES_CMAC(0, key) */
318 mbedtls_cmac_init( &zero_ctx );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000319 memset( zero_key, 0, 16 );
320 ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES,
321 zero_key, 8 * sizeof zero_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000322 if( ret != 0 )
323 {
324 return( ret );
325 }
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000326 ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000327 if( ret != 0 )
328 {
329 return( ret );
330 }
331 }
332
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000333 ret = mbedtls_cmac_setkey( ctx, MBEDTLS_CIPHER_ID_AES,
334 int_key, 8 * sizeof int_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000335 if( ret != 0 )
336 {
337 return( ret );
338 }
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000339 return( mbedtls_cmac_generate( ctx, input, in_len, tag, 16 ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000340}
341
342#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
343/*
344 * Examples 1 to 4 from SP800-3B corrected Appendix D.1
345 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
346 */
347
348#define NB_CMAC_TESTS 4
349#define NB_PRF_TESTS 3
350
351/* Key */
352static const unsigned char key[] = {
353 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
354 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
355};
356
357/* Assume we don't need to test Ek0 as this is a function of the cipher */
358
359/* Subkey K1 */
360static const unsigned char K1[] = {
361 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
362 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
363};
364
365/* Subkey K2 */
366static const unsigned char K2[] = {
367 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
368 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
369};
370
371/* All Messages */
372static const unsigned char M[] = {
373 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
374 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
375 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
376 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
377 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
378 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
379 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
380 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
381};
382
383static const unsigned char T[NB_CMAC_TESTS][16] = {
384 {
385 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
386 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
387 },
388 {
389 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
390 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
391 },
392 {
393 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
394 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
395 },
396 {
397 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
398 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
399 }
400};
401
402/* Sizes in bytes */
403static const size_t Mlen[NB_CMAC_TESTS] = {
404 0,
405 16,
406 40,
407 64
408};
409
410/* PRF K */
411static const unsigned char PRFK[] = {
412 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
413 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
414 0xed, 0xcb
415};
416
417/* Sizes in bytes */
418static const size_t PRFKlen[NB_PRF_TESTS] = {
419 18,
420 16,
421 10
422};
423
424/* PRF M */
425static const unsigned char PRFM[] = {
426 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
427 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000428 0x10, 0x11, 0x12, 0x13
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000429};
430
431static const unsigned char PRFT[NB_PRF_TESTS][16] = {
432 {
433 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
434 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
435 },
436 {
437 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
438 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
439 },
440 {
441 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
442 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
443 }
444};
445
446
447int mbedtls_cmac_self_test( int verbose )
448{
449 mbedtls_cmac_context ctx;
450 unsigned char tag[16];
451 int i;
452 int ret;
453
454 mbedtls_cmac_init( &ctx );
455
456 if( mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 )
457 {
458 if( verbose != 0 )
459 mbedtls_printf( " CMAC: setup failed" );
460
461 return( 1 );
462 }
463
464 if( ( memcmp( ctx.K1, K1, 16 ) != 0 ) ||
465 ( memcmp( ctx.K2, K2, 16 ) != 0 ) )
466 {
467 if( verbose != 0 )
468 mbedtls_printf( " CMAC: subkey generation failed" );
469
470 return( 1 );
471 }
472
473 for( i = 0; i < NB_CMAC_TESTS; i++ )
474 {
475 mbedtls_printf( " AES-128-CMAC #%u: ", i );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000476
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000477 ret = mbedtls_cmac_generate( &ctx, M, Mlen[i], tag, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000478 if( ret != 0 ||
479 memcmp( tag, T[i], 16 ) != 0 )
480 {
481 if( verbose != 0 )
482 mbedtls_printf( "failed\n" );
483
484 return( 1 );
485 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000486
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000487 ret = mbedtls_cmac_verify( &ctx, M, Mlen[i], T[i], 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000488 if( ret != 0 )
489 {
490 if( verbose != 0 )
491 mbedtls_printf( "failed\n" );
492
493 return( 1 );
494 }
495
496 if( verbose != 0 )
497 mbedtls_printf( "passed\n" );
498 }
499
500 for( i = 0; i < NB_PRF_TESTS; i++ )
501 {
502 mbedtls_printf( " AES-CMAC-128-PRF #%u: ", i );
503
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000504 mbedtls_aes_cmac_prf_128( &ctx, PRFK, PRFKlen[i], PRFM, 20, tag );
505
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000506 if( ret != 0 ||
507 memcmp( tag, PRFT[i], 16 ) != 0 )
508 {
509 if( verbose != 0 )
510 mbedtls_printf( "failed\n" );
511
512 return( 1 );
513 }
514
515 if( verbose != 0 )
516 mbedtls_printf( "passed\n" );
517 }
518
519 mbedtls_cmac_free( &ctx );
520
521 if( verbose != 0 )
522 mbedtls_printf( "\n" );
523
524 return( 0 );
525}
526
527#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
528
529#endif /* MBEDTLS_CMAC_C */