blob: 87846a617df32ae4d34fdf7e35ad70c509205af6 [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
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000132 mbedtls_zeroize( L, sizeof( L ) );
133
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000134 return( 0 );
135}
136
137int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx,
138 mbedtls_cipher_id_t cipher,
139 const unsigned char *key,
140 unsigned int keybits )
141{
142 int ret;
143 const mbedtls_cipher_info_t *cipher_info;
144
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000145 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
146 MBEDTLS_MODE_ECB );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000147 if( cipher_info == NULL )
148 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
149
150 if( cipher_info->block_size != 16 )
151 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
152
153 mbedtls_cipher_free( &ctx->cipher_ctx );
154
155 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
156 return( ret );
157
158 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000159 MBEDTLS_ENCRYPT ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000160 {
161 return( ret );
162 }
163
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000164 return( generate_subkeys( ctx ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000165}
166
167/*
168 * Free context
169 */
170void mbedtls_cmac_free( mbedtls_cmac_context *ctx )
171{
172 mbedtls_cipher_free( &ctx->cipher_ctx );
173 mbedtls_zeroize( ctx, sizeof( mbedtls_cmac_context ) );
174}
175
176/* TODO: Use cipher padding function? */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000177static void padding( const unsigned char *lastb,
178 unsigned char *pad,
179 const size_t length )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000180{
181 size_t j;
182
183 /* original last block */
184 for( j = 0; j < 16; j++ )
185 {
186 if( j < length )
187 {
188 pad[j] = lastb[j];
189 }
190 else if( j == length )
191 {
192 pad[j] = 0x80;
193 }
194 else
195 {
196 pad[j] = 0x00;
197 }
198 }
199}
200
201/*
202 * Generate tag on complete message
203 */
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000204static int cmac_generate( mbedtls_cmac_context *ctx,
205 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000206 unsigned char *tag, size_t tag_len )
207{
208 unsigned char Mn[16];
209 unsigned char M_last[16];
210 unsigned char padded[16];
211 int n, i, j, ret, flag;
212 size_t olen;
213
214 /*
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000215 * Check in_len requirements: SP800-38B A
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000216 * 4 is a worst case bottom limit
217 */
218 if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
219 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
220
221 /* TODO: Use cipher padding function? */
222 // mbedtls_cipher_set_padding_mode( ctx->cipher, MBEDTLS_PADDING_ONE_AND_ZEROS );
223
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000224 n = ( in_len + 15 ) / 16; /* n is number of rounds */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000225
226 if( n == 0 )
227 {
228 n = 1;
229 flag = 0;
230 }
231 else
232 {
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000233 flag = ( ( in_len % 16 ) == 0);
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000234 }
235
236 /* Calculate last block */
237 if( flag )
238 {
239 /* Last block is complete block */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000240 XOR_128( &input[16 * ( n - 1 )], ctx->K1, M_last );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000241 }
242 else
243 {
244 /* TODO: Use cipher padding function? */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000245 padding( &input[16 * ( n - 1 )], padded, in_len % 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000246 XOR_128( padded, ctx->K2, M_last );
247 }
248
249 memset( Mn, 0, 16 );
250
251 for( j = 0; j < n - 1; j++ )
252 {
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000253 UPDATE_CMAC( &input[16 * j] );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000254 }
255
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000256 UPDATE_CMAC( M_last );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000257
258 memcpy( tag, Mn, 16 );
259
260 return( 0 );
261}
262
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000263int mbedtls_cmac_generate( mbedtls_cmac_context *ctx,
264 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000265 unsigned char *tag, size_t tag_len )
266{
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000267 return( cmac_generate( ctx, input, in_len, tag, tag_len ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000268}
269
270/*
271 * Authenticated decryption
272 */
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000273int mbedtls_cmac_verify( mbedtls_cmac_context *ctx,
274 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000275 const unsigned char *tag, size_t tag_len )
276{
277 int ret;
278 unsigned char check_tag[16];
279 unsigned char i;
280 int diff;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000281
282 if( ( ret = cmac_generate( ctx, input, in_len, check_tag, tag_len ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000283 {
284 return ret;
285 }
286
287 /* Check tag in "constant-time" */
288 for( diff = 0, i = 0; i < tag_len; i++ )
289 {
290 diff |= tag[i] ^ check_tag[i];
291 }
292
293 if( diff != 0 )
294 {
295 return( MBEDTLS_ERR_CMAC_VERIFY_FAILED );
296 }
297
298 return( 0 );
299}
300
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000301int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000302 const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000303 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000304 unsigned char *tag )
305{
306 int ret;
307 unsigned char zero_key[16];
308 unsigned char int_key[16];
309
310 if( key_length == 16 )
311 {
312 /* Use key as is */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000313 memcpy( int_key, key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000314 }
315 else
316 {
317 mbedtls_cmac_context zero_ctx;
318
319 /* Key is AES_CMAC(0, key) */
320 mbedtls_cmac_init( &zero_ctx );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000321 memset( zero_key, 0, 16 );
322 ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES,
323 zero_key, 8 * sizeof zero_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000324 if( ret != 0 )
325 {
326 return( ret );
327 }
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000328 ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000329 if( ret != 0 )
330 {
331 return( ret );
332 }
333 }
334
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000335 ret = mbedtls_cmac_setkey( ctx, MBEDTLS_CIPHER_ID_AES,
336 int_key, 8 * sizeof int_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000337 if( ret != 0 )
338 {
339 return( ret );
340 }
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000341
342 mbedtls_zeroize( int_key, sizeof( int_key ) );
343
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000344 return( mbedtls_cmac_generate( ctx, input, in_len, tag, 16 ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000345}
346
347#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
348/*
349 * Examples 1 to 4 from SP800-3B corrected Appendix D.1
350 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
351 */
352
353#define NB_CMAC_TESTS 4
354#define NB_PRF_TESTS 3
355
356/* Key */
357static const unsigned char key[] = {
358 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
359 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
360};
361
362/* Assume we don't need to test Ek0 as this is a function of the cipher */
363
364/* Subkey K1 */
365static const unsigned char K1[] = {
366 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
367 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
368};
369
370/* Subkey K2 */
371static const unsigned char K2[] = {
372 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
373 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
374};
375
376/* All Messages */
377static const unsigned char M[] = {
378 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
379 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
380 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
381 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
382 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
383 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
384 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
385 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
386};
387
388static const unsigned char T[NB_CMAC_TESTS][16] = {
389 {
390 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
391 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
392 },
393 {
394 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
395 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
396 },
397 {
398 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
399 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
400 },
401 {
402 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
403 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
404 }
405};
406
407/* Sizes in bytes */
408static const size_t Mlen[NB_CMAC_TESTS] = {
409 0,
410 16,
411 40,
412 64
413};
414
415/* PRF K */
416static const unsigned char PRFK[] = {
417 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
418 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
419 0xed, 0xcb
420};
421
422/* Sizes in bytes */
423static const size_t PRFKlen[NB_PRF_TESTS] = {
424 18,
425 16,
426 10
427};
428
429/* PRF M */
430static const unsigned char PRFM[] = {
431 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
432 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000433 0x10, 0x11, 0x12, 0x13
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000434};
435
436static const unsigned char PRFT[NB_PRF_TESTS][16] = {
437 {
438 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
439 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
440 },
441 {
442 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
443 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
444 },
445 {
446 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
447 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
448 }
449};
450
451
452int mbedtls_cmac_self_test( int verbose )
453{
454 mbedtls_cmac_context ctx;
455 unsigned char tag[16];
456 int i;
457 int ret;
458
459 mbedtls_cmac_init( &ctx );
460
461 if( mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 )
462 {
463 if( verbose != 0 )
464 mbedtls_printf( " CMAC: setup failed" );
465
466 return( 1 );
467 }
468
469 if( ( memcmp( ctx.K1, K1, 16 ) != 0 ) ||
470 ( memcmp( ctx.K2, K2, 16 ) != 0 ) )
471 {
472 if( verbose != 0 )
473 mbedtls_printf( " CMAC: subkey generation failed" );
474
475 return( 1 );
476 }
477
478 for( i = 0; i < NB_CMAC_TESTS; i++ )
479 {
480 mbedtls_printf( " AES-128-CMAC #%u: ", i );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000481
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000482 ret = mbedtls_cmac_generate( &ctx, M, Mlen[i], tag, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000483 if( ret != 0 ||
484 memcmp( tag, T[i], 16 ) != 0 )
485 {
486 if( verbose != 0 )
487 mbedtls_printf( "failed\n" );
488
489 return( 1 );
490 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000491
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000492 ret = mbedtls_cmac_verify( &ctx, M, Mlen[i], T[i], 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000493 if( ret != 0 )
494 {
495 if( verbose != 0 )
496 mbedtls_printf( "failed\n" );
497
498 return( 1 );
499 }
500
501 if( verbose != 0 )
502 mbedtls_printf( "passed\n" );
503 }
504
505 for( i = 0; i < NB_PRF_TESTS; i++ )
506 {
507 mbedtls_printf( " AES-CMAC-128-PRF #%u: ", i );
508
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000509 mbedtls_aes_cmac_prf_128( &ctx, PRFK, PRFKlen[i], PRFM, 20, tag );
510
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000511 if( ret != 0 ||
512 memcmp( tag, PRFT[i], 16 ) != 0 )
513 {
514 if( verbose != 0 )
515 mbedtls_printf( "failed\n" );
516
517 return( 1 );
518 }
519
520 if( verbose != 0 )
521 mbedtls_printf( "passed\n" );
522 }
523
524 mbedtls_cmac_free( &ctx );
525
526 if( verbose != 0 )
527 mbedtls_printf( "\n" );
528
529 return( 0 );
530}
531
532#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
533
534#endif /* MBEDTLS_CMAC_C */