blob: 35c32f3a5c8791bf8c61a6414bbb136058f9469f [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
Robert Cragie3d23b1d2015-12-15 07:38:11 +000049/* Implementation that should never be optimized out by the compiler */
50static void mbedtls_zeroize( void *v, size_t n ) {
51 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
52}
53
54/*
55 * Initialize context
56 */
57void mbedtls_cmac_init( mbedtls_cmac_context *ctx )
58{
59 memset( ctx, 0, sizeof( mbedtls_cmac_context ) );
60}
61
62/*
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000063 * Multiply by u in GF(2^128)
64 *
65 * As explained in the paper, this can be achieved as
66 * If MSB(p) = 0, then p = (p << 1)
67 * If MSB(p) = 1, then p = (p << 1) ^ Rb
68 * with Rb = 0x87
69 *
70 * Input and output MUST not point to the same buffer
Robert Cragie3d23b1d2015-12-15 07:38:11 +000071 */
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000072static void multiply_by_u( unsigned char *output, const unsigned char *input )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000073{
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +000074 const unsigned char Rb = 0x87; /* block size 16 only */
75 unsigned char mask;
Robert Cragie3d23b1d2015-12-15 07:38:11 +000076 unsigned char overflow = 0;
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000077 int i;
Robert Cragie3d23b1d2015-12-15 07:38:11 +000078
79 for( i = 15; i >= 0; i-- )
80 {
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000081 output[i] = input[i] << 1 | overflow;
82 overflow = input[i] >> 7;
Robert Cragie3d23b1d2015-12-15 07:38:11 +000083 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +000084
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +000085 /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
86 * using bit operations to avoid branches */
87 /* MSVC has a warning about unary minus on unsigned, but this is
88 * well-defined and precisely what we want to do here */
89#if defined(_MSC_VER)
90#pragma warning( push )
91#pragma warning( disable : 4146 )
92#endif
93 mask = - ( input[0] >> 7 );
94#if defined(_MSC_VER)
95#pragma warning( pop )
96#endif
97
98 output[15] ^= Rb & mask;
Robert Cragie3d23b1d2015-12-15 07:38:11 +000099}
100
101/*
102 * Generate subkeys
103 */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000104static int generate_subkeys( mbedtls_cmac_context *ctx )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000105{
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000106 int ret;
107 unsigned char L[16];
108 size_t olen;
109
110 /* Calculate Ek(0) */
111 memset( L, 0, 16 );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000112 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx,
113 L, 16, L, &olen ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000114 {
115 return( ret );
116 }
117
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000118 /*
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000119 * Generate K1 and K2
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000120 */
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000121 multiply_by_u( ctx->K1, L );
122 multiply_by_u( ctx->K2, ctx->K1 );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000123
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000124 mbedtls_zeroize( L, sizeof( L ) );
125
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000126 return( 0 );
127}
128
129int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx,
130 mbedtls_cipher_id_t cipher,
131 const unsigned char *key,
132 unsigned int keybits )
133{
134 int ret;
135 const mbedtls_cipher_info_t *cipher_info;
136
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000137 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
138 MBEDTLS_MODE_ECB );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000139 if( cipher_info == NULL )
140 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
141
142 if( cipher_info->block_size != 16 )
143 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
144
145 mbedtls_cipher_free( &ctx->cipher_ctx );
146
147 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
148 return( ret );
149
150 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000151 MBEDTLS_ENCRYPT ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000152 {
153 return( ret );
154 }
155
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000156 return( generate_subkeys( ctx ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000157}
158
159/*
160 * Free context
161 */
162void mbedtls_cmac_free( mbedtls_cmac_context *ctx )
163{
164 mbedtls_cipher_free( &ctx->cipher_ctx );
165 mbedtls_zeroize( ctx, sizeof( mbedtls_cmac_context ) );
166}
167
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000168/*
169 * Create padded last block from (partial) last block.
170 *
171 * We can't use the padding option from the cipher layer, as it only works for
172 * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
173 */
174static void padding( unsigned char padded_block[16],
175 const unsigned char *last_block,
176 size_t length )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000177{
178 size_t j;
179
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000180 for( j = 0; j < 16; j++ )
181 {
182 if( j < length )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000183 padded_block[j] = last_block[j];
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000184 else if( j == length )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000185 padded_block[j] = 0x80;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000186 else
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000187 padded_block[j] = 0x00;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000188 }
189}
190
191/*
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000192 * XOR 128-bit
193 * Here, macro results in smaller compiled code than static inline function
194 */
195#define XOR_128( o, i1, i2 ) \
196 for( i = 0; i < 16; i++ ) \
197 ( o )[i] = ( i1 )[i] ^ ( i2 )[i];
198
199/*
200 * Update the CMAC state using an input block x
201 */
202#define UPDATE_CMAC( x ) \
203do { \
204 XOR_128( state, ( x ), state ); \
205 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \
206 state, 16, state, &olen ) ) != 0 ) \
207 return( ret ); \
208} while( 0 )
209
210/*
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000211 * Generate tag on complete message
212 */
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000213static int cmac_generate( mbedtls_cmac_context *ctx,
214 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000215 unsigned char *tag, size_t tag_len )
216{
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000217 unsigned char state[16];
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000218 unsigned char M_last[16];
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000219 int n, i, j, ret, needs_padding;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000220 size_t olen;
221
222 /*
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000223 * Check in_len requirements: SP800-38B A
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000224 * 4 is a worst case bottom limit
225 */
226 if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
227 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
228
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000229 if( in_len == 0 )
230 needs_padding = 1;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000231 else
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000232 needs_padding = in_len % 16 != 0;
233
234 n = in_len / 16 + needs_padding;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000235
236 /* Calculate last block */
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000237 if( needs_padding )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000238 {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000239 padding( M_last, input + 16 * ( n - 1 ), in_len % 16 );
240 XOR_128( M_last, M_last, ctx->K2 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000241 }
242 else
243 {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000244 /* Last block is complete block */
245 XOR_128( M_last, input + 16 * ( n - 1 ), ctx->K1 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000246 }
247
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000248 memset( state, 0, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000249
250 for( j = 0; j < n - 1; j++ )
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000251 UPDATE_CMAC( input + 16 * j );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000252
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000253 UPDATE_CMAC( M_last );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000254
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000255 memcpy( tag, state, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000256
257 return( 0 );
258}
259
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000260#undef XOR_128
261#undef UPDATE_CMAC
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 */