blob: 23b8044ffe34068eeea18646b9d685f080fc7bcd [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é-Gonnard7b555f22016-01-13 15:09:09 +000072static void cmac_multiply_by_u( unsigned char *output,
73 const unsigned char *input )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000074{
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +000075 const unsigned char Rb = 0x87; /* block size 16 only */
76 unsigned char mask;
Robert Cragie3d23b1d2015-12-15 07:38:11 +000077 unsigned char overflow = 0;
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000078 int i;
Robert Cragie3d23b1d2015-12-15 07:38:11 +000079
80 for( i = 15; i >= 0; i-- )
81 {
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000082 output[i] = input[i] << 1 | overflow;
83 overflow = input[i] >> 7;
Robert Cragie3d23b1d2015-12-15 07:38:11 +000084 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +000085
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +000086 /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
87 * using bit operations to avoid branches */
88 /* MSVC has a warning about unary minus on unsigned, but this is
89 * well-defined and precisely what we want to do here */
90#if defined(_MSC_VER)
91#pragma warning( push )
92#pragma warning( disable : 4146 )
93#endif
94 mask = - ( input[0] >> 7 );
95#if defined(_MSC_VER)
96#pragma warning( pop )
97#endif
98
99 output[15] ^= Rb & mask;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000100}
101
102/*
103 * Generate subkeys
104 */
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000105static int cmac_generate_subkeys( mbedtls_cmac_context *ctx )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000106{
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000107 int ret;
108 unsigned char L[16];
109 size_t olen;
110
111 /* Calculate Ek(0) */
112 memset( L, 0, 16 );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000113 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx,
114 L, 16, L, &olen ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000115 {
116 return( ret );
117 }
118
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000119 /*
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000120 * Generate K1 and K2
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000121 */
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000122 cmac_multiply_by_u( ctx->K1, L );
123 cmac_multiply_by_u( ctx->K2, ctx->K1 );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000124
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000125 mbedtls_zeroize( L, sizeof( L ) );
126
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000127 return( 0 );
128}
129
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000130/*
131 * Set key and prepare context for use
132 */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000133int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx,
134 mbedtls_cipher_id_t cipher,
135 const unsigned char *key,
136 unsigned int keybits )
137{
138 int ret;
139 const mbedtls_cipher_info_t *cipher_info;
140
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000141 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
142 MBEDTLS_MODE_ECB );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000143 if( cipher_info == NULL )
144 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
145
146 if( cipher_info->block_size != 16 )
147 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
148
149 mbedtls_cipher_free( &ctx->cipher_ctx );
150
151 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
152 return( ret );
153
154 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000155 MBEDTLS_ENCRYPT ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000156 {
157 return( ret );
158 }
159
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000160 return( cmac_generate_subkeys( ctx ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000161}
162
163/*
164 * Free context
165 */
166void mbedtls_cmac_free( mbedtls_cmac_context *ctx )
167{
168 mbedtls_cipher_free( &ctx->cipher_ctx );
169 mbedtls_zeroize( ctx, sizeof( mbedtls_cmac_context ) );
170}
171
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000172/*
173 * Create padded last block from (partial) last block.
174 *
175 * We can't use the padding option from the cipher layer, as it only works for
176 * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
177 */
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000178static void cmac_pad( unsigned char padded_block[16],
179 const unsigned char *last_block,
180 size_t length )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000181{
182 size_t j;
183
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000184 for( j = 0; j < 16; j++ )
185 {
186 if( j < length )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000187 padded_block[j] = last_block[j];
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000188 else if( j == length )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000189 padded_block[j] = 0x80;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000190 else
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000191 padded_block[j] = 0x00;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000192 }
193}
194
195/*
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000196 * XOR 128-bit
197 * Here, macro results in smaller compiled code than static inline function
198 */
199#define XOR_128( o, i1, i2 ) \
200 for( i = 0; i < 16; i++ ) \
201 ( o )[i] = ( i1 )[i] ^ ( i2 )[i];
202
203/*
204 * Update the CMAC state using an input block x
205 */
206#define UPDATE_CMAC( x ) \
207do { \
208 XOR_128( state, ( x ), state ); \
209 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \
210 state, 16, state, &olen ) ) != 0 ) \
211 return( ret ); \
212} while( 0 )
213
214/*
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000215 * Generate tag on complete message
216 */
Manuel Pégourié-Gonnardab9c5fd2016-01-13 15:05:57 +0000217int mbedtls_cmac_generate( mbedtls_cmac_context *ctx,
218 const unsigned char *input, size_t in_len,
219 unsigned char *tag, size_t tag_len )
220
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000221{
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000222 unsigned char state[16];
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000223 unsigned char M_last[16];
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000224 int n, i, j, ret, needs_padding;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000225 size_t olen;
226
227 /*
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000228 * Check in_len requirements: SP800-38B A
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000229 * 4 is a worst case bottom limit
230 */
231 if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
232 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
233
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000234 if( in_len == 0 )
235 needs_padding = 1;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000236 else
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000237 needs_padding = in_len % 16 != 0;
238
239 n = in_len / 16 + needs_padding;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000240
241 /* Calculate last block */
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000242 if( needs_padding )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000243 {
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000244 cmac_pad( M_last, input + 16 * ( n - 1 ), in_len % 16 );
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000245 XOR_128( M_last, M_last, ctx->K2 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000246 }
247 else
248 {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000249 /* Last block is complete block */
250 XOR_128( M_last, input + 16 * ( n - 1 ), ctx->K1 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000251 }
252
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000253 memset( state, 0, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000254
255 for( j = 0; j < n - 1; j++ )
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000256 UPDATE_CMAC( input + 16 * j );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000257
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000258 UPDATE_CMAC( M_last );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000259
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000260 memcpy( tag, state, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000261
262 return( 0 );
263}
264
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000265#undef XOR_128
266#undef UPDATE_CMAC
267
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000268/*
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000269 * Verify tag on complete message
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000270 */
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
Manuel Pégourié-Gonnardab9c5fd2016-01-13 15:05:57 +0000280 if( ( ret = mbedtls_cmac_generate( ctx, input, in_len,
281 check_tag, tag_len ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000282 {
283 return ret;
284 }
285
286 /* Check tag in "constant-time" */
287 for( diff = 0, i = 0; i < tag_len; i++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000288 diff |= tag[i] ^ check_tag[i];
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000289
290 if( diff != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000291 return( MBEDTLS_ERR_CMAC_VERIFY_FAILED );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000292
293 return( 0 );
294}
295
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000296/*
297 * PRF based on CMAC with AES-128
298 * TODO: add reference to the standard
299 * TODO: do we need to take a cmac_context as an argument here?
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 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000325 return( ret );
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000326
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000327 ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000328 if( ret != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000329 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000330 }
331
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000332 ret = mbedtls_cmac_setkey( ctx, MBEDTLS_CIPHER_ID_AES,
333 int_key, 8 * sizeof int_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000334 if( ret != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000335 return( ret );
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000336
337 mbedtls_zeroize( int_key, sizeof( int_key ) );
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/*
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000344 * Examples 1 to 4 from SP800-38B corrected Appendix D.1
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000345 * 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 )
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000459 mbedtls_printf( " CMAC: setup failed\n" );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000460
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 )
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000468 mbedtls_printf( " CMAC: subkey generation failed\n" );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000469
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 */