blob: 8348939f11f422a93f6afadd510dd094d7bc96fd [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
Brian Murray00dc5f02016-05-19 14:23:50 -070062
Robert Cragie3d23b1d2015-12-15 07:38:11 +000063/*
Brian Murrayb0c3c432016-05-18 14:29:51 -070064 * Multiplication by u in the Galois field of GF(2^n)
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000065 *
Brian Murrayb0c3c432016-05-18 14:29:51 -070066 * As explained in the paper, this can computed:
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000067 * If MSB(p) = 0, then p = (p << 1)
Brian Murrayb0c3c432016-05-18 14:29:51 -070068 * If MSB(p) = 1, then p = (p << 1) ^ R_n
69 * with R_64 = 0x1B and R_128 = 0x87
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000070 *
71 * Input and output MUST not point to the same buffer
Brian Murrayb0c3c432016-05-18 14:29:51 -070072 * Block size must be 8 byes or 16 bytes.
Robert Cragie3d23b1d2015-12-15 07:38:11 +000073 */
Brian Murrayb0c3c432016-05-18 14:29:51 -070074static int cmac_multiply_by_u( unsigned char *output,
75 const unsigned char *input,
76 size_t blocksize)
Robert Cragie3d23b1d2015-12-15 07:38:11 +000077{
Robert Cragie3d23b1d2015-12-15 07:38:11 +000078
Brian Murrayb0c3c432016-05-18 14:29:51 -070079 const unsigned char R_128 = 0x87;
80 const unsigned char R_64 = 0x1B;
81 unsigned char R_n, mask;
82 unsigned char overflow = 0x00;
83 int i, starting_index;
84
85 starting_index = blocksize -1;
86
87 if(blocksize == 16){
88 R_n = R_128;
89 } else if(blocksize == 8) {
90 R_n = R_64;
91 } else {
92 return MBEDTLS_ERR_CMAC_BAD_INPUT;
93 }
94
95
96 for( i = starting_index; i >= 0; i-- )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000097 {
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000098 output[i] = input[i] << 1 | overflow;
99 overflow = input[i] >> 7;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000100 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000101
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +0000102 /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
103 * using bit operations to avoid branches */
104 /* MSVC has a warning about unary minus on unsigned, but this is
105 * well-defined and precisely what we want to do here */
106#if defined(_MSC_VER)
107#pragma warning( push )
108#pragma warning( disable : 4146 )
109#endif
110 mask = - ( input[0] >> 7 );
111#if defined(_MSC_VER)
112#pragma warning( pop )
113#endif
114
Brian Murrayb0c3c432016-05-18 14:29:51 -0700115 output[starting_index] ^= R_n & mask;
116 return 0;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000117}
118
119/*
120 * Generate subkeys
121 */
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000122static int cmac_generate_subkeys( mbedtls_cmac_context *ctx )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000123{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700124 int ret, keybytes;
125 unsigned char *L;
126 size_t olen, block_size;
127
128 ret = 0;
129 block_size = ctx->cipher_ctx.cipher_info->block_size;
130
131 L = mbedtls_calloc(block_size, sizeof(unsigned char));
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000132
133 /* Calculate Ek(0) */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700134 memset( L, 0, block_size );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000135 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx,
Brian Murrayb0c3c432016-05-18 14:29:51 -0700136 L, block_size, L, &olen ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000137 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700138 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000139 }
140
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000141 /*
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000142 * Generate K1 and K2
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000143 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700144 if( ( ret = cmac_multiply_by_u( ctx->K1, L , block_size) ) != 0 )
145 goto exit;
146 if( ( cmac_multiply_by_u( ctx->K2, ctx->K1 , block_size) ) != 0 )
147 goto exit;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000148
Brian Murrayb0c3c432016-05-18 14:29:51 -0700149 exit:
150 mbedtls_zeroize( L, sizeof( L ) );
151 free(L);
152 return ret;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000153}
154
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000155/*
156 * Set key and prepare context for use
157 */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000158int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx,
159 mbedtls_cipher_id_t cipher,
160 const unsigned char *key,
161 unsigned int keybits )
162{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700163 int ret, blocksize;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000164 const mbedtls_cipher_info_t *cipher_info;
165
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000166 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
167 MBEDTLS_MODE_ECB );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000168 if( cipher_info == NULL )
169 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
170
Brian Murrayb0c3c432016-05-18 14:29:51 -0700171 ctx->K1 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) );
172 ctx->K2 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000173
174 mbedtls_cipher_free( &ctx->cipher_ctx );
175
176 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
177 return( ret );
178
179 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000180 MBEDTLS_ENCRYPT ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000181 {
182 return( ret );
183 }
184
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000185 return( cmac_generate_subkeys( ctx ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000186}
187
188/*
189 * Free context
190 */
191void mbedtls_cmac_free( mbedtls_cmac_context *ctx )
192{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700193 int block_size;
194 block_size = ctx->cipher_ctx.cipher_info->block_size;
195
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000196 mbedtls_cipher_free( &ctx->cipher_ctx );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700197
198 mbedtls_zeroize(ctx->K1, block_size * sizeof( unsigned char ) );
199 mbedtls_zeroize(ctx->K2, block_size * sizeof( unsigned char ) );
200 mbedtls_free( ctx->K1 );
201 mbedtls_free( ctx->K2 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000202}
203
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000204/*
205 * Create padded last block from (partial) last block.
206 *
207 * We can't use the padding option from the cipher layer, as it only works for
208 * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
209 */
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000210static void cmac_pad( unsigned char padded_block[16],
Brian Murrayb0c3c432016-05-18 14:29:51 -0700211 size_t padded_block_len,
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000212 const unsigned char *last_block,
Brian Murrayb0c3c432016-05-18 14:29:51 -0700213 size_t last_block_len )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000214{
215 size_t j;
216
Brian Murrayb0c3c432016-05-18 14:29:51 -0700217 for( j = 0; j < padded_block_len; j++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000218 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700219 if( j < last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000220 padded_block[j] = last_block[j];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700221 else if( j == last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000222 padded_block[j] = 0x80;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000223 else
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000224 padded_block[j] = 0x00;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000225 }
226}
227
228/*
Brian Murrayb0c3c432016-05-18 14:29:51 -0700229 * XOR Block
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000230 * Here, macro results in smaller compiled code than static inline function
231 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700232#define XOR_BLOCK( o, i1, i2 ) \
233 for( i = 0; i < block_size; i++ ) \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000234 ( o )[i] = ( i1 )[i] ^ ( i2 )[i];
235
236/*
237 * Update the CMAC state using an input block x
238 */
239#define UPDATE_CMAC( x ) \
240do { \
Brian Murrayb0c3c432016-05-18 14:29:51 -0700241 XOR_BLOCK( state, ( x ), state ); \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000242 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \
Brian Murrayb0c3c432016-05-18 14:29:51 -0700243 state, block_size, \
244 state, &olen ) ) != 0 ) \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000245 return( ret ); \
246} while( 0 )
247
248/*
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000249 * Generate tag on complete message
250 */
Manuel Pégourié-Gonnardab9c5fd2016-01-13 15:05:57 +0000251int mbedtls_cmac_generate( mbedtls_cmac_context *ctx,
252 const unsigned char *input, size_t in_len,
253 unsigned char *tag, size_t tag_len )
254
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000255{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700256
257 unsigned char *state;
258 unsigned char *M_last;
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000259 int n, i, j, ret, needs_padding;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700260 size_t olen, block_size;
261
262
263 ret = 0;
264 block_size = ctx->cipher_ctx.cipher_info->block_size;
265
266 state = mbedtls_calloc(block_size, sizeof(unsigned char) );
267 M_last = mbedtls_calloc(block_size, sizeof(unsigned char) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000268
269 /*
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000270 * Check in_len requirements: SP800-38B A
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000271 * 4 is a worst case bottom limit
272 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700273 if( tag_len < 4 || tag_len > block_size || tag_len % 2 != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000274 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
275
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000276 if( in_len == 0 )
277 needs_padding = 1;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000278 else
Brian Murrayb0c3c432016-05-18 14:29:51 -0700279 needs_padding = in_len % block_size != 0;
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000280
Brian Murrayb0c3c432016-05-18 14:29:51 -0700281 n = in_len / block_size + needs_padding;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000282
283 /* Calculate last block */
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000284 if( needs_padding )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000285 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700286 cmac_pad( M_last, block_size, input + block_size * ( n - 1 ), in_len % block_size );
287 XOR_BLOCK( M_last, M_last, ctx->K2 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000288 }
289 else
290 {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000291 /* Last block is complete block */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700292 XOR_BLOCK( M_last, input + block_size * ( n - 1 ), ctx->K1 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000293 }
294
Brian Murrayb0c3c432016-05-18 14:29:51 -0700295 memset( state, 0, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000296
297 for( j = 0; j < n - 1; j++ )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700298 UPDATE_CMAC( input + block_size * j );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000299
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000300 UPDATE_CMAC( M_last );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000301
Brian Murray00dc5f02016-05-19 14:23:50 -0700302 memcpy( tag, state, tag_len );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000303
Brian Murrayb0c3c432016-05-18 14:29:51 -0700304 exit:
305 free(state);
306 free(M_last);
307 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000308}
309
Brian Murrayb0c3c432016-05-18 14:29:51 -0700310#undef XOR_BLOCK
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000311#undef UPDATE_CMAC
312
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000313/*
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000314 * Verify tag on complete message
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000315 */
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000316int mbedtls_cmac_verify( mbedtls_cmac_context *ctx,
317 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000318 const unsigned char *tag, size_t tag_len )
319{
320 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700321 unsigned char *check_tag;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000322 unsigned char i;
323 int diff;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000324
Brian Murrayb0c3c432016-05-18 14:29:51 -0700325 check_tag = mbedtls_calloc(ctx->cipher_ctx.cipher_info->block_size,
326 sizeof(unsigned char) );
327
Manuel Pégourié-Gonnardab9c5fd2016-01-13 15:05:57 +0000328 if( ( ret = mbedtls_cmac_generate( ctx, input, in_len,
329 check_tag, tag_len ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000330 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700331 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000332 }
333
334 /* Check tag in "constant-time" */
335 for( diff = 0, i = 0; i < tag_len; i++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000336 diff |= tag[i] ^ check_tag[i];
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000337
338 if( diff != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700339 ret = MBEDTLS_ERR_CMAC_VERIFY_FAILED;
340 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000341
Brian Murrayb0c3c432016-05-18 14:29:51 -0700342 exit:
343 free(check_tag);
344 return ret;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000345}
346
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000347/*
348 * PRF based on CMAC with AES-128
Brian Murrayb0c3c432016-05-18 14:29:51 -0700349 * See RFC 4615
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000350 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700351int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000352 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000353 unsigned char *tag )
354{
355 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700356 mbedtls_cmac_context ctx;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000357 unsigned char zero_key[16];
358 unsigned char int_key[16];
359
Brian Murrayb0c3c432016-05-18 14:29:51 -0700360 mbedtls_cmac_init(&ctx);
361
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000362 if( key_length == 16 )
363 {
364 /* Use key as is */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000365 memcpy( int_key, key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000366 }
367 else
368 {
369 mbedtls_cmac_context zero_ctx;
370
371 /* Key is AES_CMAC(0, key) */
372 mbedtls_cmac_init( &zero_ctx );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000373 memset( zero_key, 0, 16 );
374 ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES,
375 zero_key, 8 * sizeof zero_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000376 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700377 goto exit;
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000378
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000379 ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000380 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700381 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000382 }
383
Brian Murrayb0c3c432016-05-18 14:29:51 -0700384 ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000385 int_key, 8 * sizeof int_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000386 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700387 goto exit;
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000388
389 mbedtls_zeroize( int_key, sizeof( int_key ) );
390
Brian Murrayb0c3c432016-05-18 14:29:51 -0700391 ret = mbedtls_cmac_generate( &ctx, input, in_len, tag, 16 );
392
393 exit:
394 mbedtls_cmac_free(&ctx);
395 return( ret );
396
397
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000398}
399
400#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
401/*
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000402 * Examples 1 to 4 from SP800-38B corrected Appendix D.1
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000403 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
404 */
405
Brian Murrayb0c3c432016-05-18 14:29:51 -0700406#define NB_CMAC_TESTS_AES_128 4
407#define NB_CMAC_TESTS_AES_192 4
408#define NB_CMAC_TESTS_AES_256 4
409#define NB_CMAC_TESTS_3DES 4
410
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000411#define NB_PRF_TESTS 3
412
Brian Murrayb0c3c432016-05-18 14:29:51 -0700413/* AES 128 Key */
414static const unsigned char aes_128_key[] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000415 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
416 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
417};
418
Brian Murrayb0c3c432016-05-18 14:29:51 -0700419/* AES 192 Key */
420static const unsigned char aes_192_key[] = {
421 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
422 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
423 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
424};
425
426/* AES 256 Key */
427static const unsigned char aes_256_key[] = {
428 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
429 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
430 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
431 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
432};
433
434/* 3DES 112 bit key */
435static const unsigned char des3_2key_key[] = {
436 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5,
437 0x8a, 0x3d, 0x10, 0xba, 0x80, 0x57, 0x0d, 0x38,
438 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5
439};
440
441/* 3DES 168 bit key */
442static const unsigned char des3_3key_key[] = {
443 0x8a, 0xa8, 0x3b, 0xf8, 0xcb, 0xda, 0x10, 0x62,
444 0x0b, 0xc1, 0xbf, 0x19, 0xfb, 0xb6, 0xcd, 0x58,
445 0xbc, 0x31, 0x3d, 0x4a, 0x37, 0x1c, 0xa8, 0xb5
446};
447
Brian Murray00dc5f02016-05-19 14:23:50 -0700448static const unsigned char aes_128_subkeys[2][16] = {
449 {
450 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
451 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
452 },
453 {
454 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
455 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
456 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000457};
458
Brian Murray00dc5f02016-05-19 14:23:50 -0700459static const unsigned char aes_192_subkeys[2][16] = {
460 {
461 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
462 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
463 },
464 {
465 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
466 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
467 }
468};
469
470static const unsigned char aes_256_subkeys[2][16] = {
471 {
472 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
473 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
474 },
475 {
476 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
477 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
478 }
479};
480
481static const unsigned char des3_2key_subkeys[2][8] = {
482 {
483 0x8e, 0xcf, 0x37, 0x3e, 0xd7, 0x1a, 0xfa, 0xef
484 },
485 {
486 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5
487 }
488};
489
490static const unsigned char des3_3key_subkeys[2][8] = {
491 {
492 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f
493 },
494 {
495 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5
496 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000497};
498
Brian Murrayb0c3c432016-05-18 14:29:51 -0700499
Brian Murray00dc5f02016-05-19 14:23:50 -0700500/* All Messages are truncated from the same 64 byte buffer. */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000501static const unsigned char M[] = {
502 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
503 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
504 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
505 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
506 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
507 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
508 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
509 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
510};
511
Brian Murrayb0c3c432016-05-18 14:29:51 -0700512static const unsigned char T_128[NB_CMAC_TESTS_3DES][16] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000513 {
514 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
515 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
516 },
517 {
518 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
519 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
520 },
521 {
522 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
523 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
524 },
525 {
526 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
527 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
528 }
529};
530
531/* Sizes in bytes */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700532static const size_t Mlen[NB_CMAC_TESTS_AES_192] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000533 0,
534 16,
535 40,
536 64
537};
538
Brian Murrayb0c3c432016-05-18 14:29:51 -0700539static const size_t Mlen_3des[NB_CMAC_TESTS_AES_192] = {
540 0,
541 8,
542 20,
543 32
544};
545
546
547
548static const unsigned char T_256[NB_CMAC_TESTS_AES_192][16] = {
549 {
550 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
551 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
552 },
553 {
554 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
555 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
556 },
557 {
558 0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2,
559 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6
560 },
561 {
562 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
563 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
564 }
565};
566
567static const unsigned char T_192[NB_CMAC_TESTS_AES_192][16] = {
568 {
569 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
570 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
571 },
572 {
573 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
574 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
575 },
576 {
577 0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad,
578 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e
579 },
580 {
581 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
582 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
583 }
584};
585
Brian Murray00dc5f02016-05-19 14:23:50 -0700586static const unsigned char T_3des_2key[4][8] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700587 {
588 0xbd, 0x2e, 0xbf, 0x9a, 0x3b, 0xa0, 0x03, 0x61
589 },
590 {
591 0x4f, 0xf2, 0xab, 0x81, 0x3c, 0x53, 0xce, 0x83
592 },
593 {
594 0x62, 0xdd, 0x1b, 0x47, 0x19, 0x02, 0xbd, 0x4e
595 },
596 {
597 0x31, 0xb1, 0xe4, 0x31, 0xda, 0xbc, 0x4e, 0xb8
598 }
599};
600
Brian Murray00dc5f02016-05-19 14:23:50 -0700601static const unsigned char T_3des_3key[4][8] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700602 {
603 0xb7, 0xa6, 0x88, 0xe1, 0x22, 0xff, 0xaf, 0x95
604 },
605 {
606 0x8e, 0x8f, 0x29, 0x31, 0x36, 0x28, 0x37, 0x97
607 },
608 {
609 0x74, 0x3d, 0xdb, 0xe0, 0xce, 0x2d, 0xc2, 0xed
610 },
611 {
612 0x33, 0xe6, 0xb1, 0x09, 0x24, 0x00, 0xea, 0xe5
613 }
614};
615
616
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000617/* PRF K */
618static const unsigned char PRFK[] = {
619 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
620 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
621 0xed, 0xcb
622};
623
624/* Sizes in bytes */
625static const size_t PRFKlen[NB_PRF_TESTS] = {
626 18,
627 16,
628 10
629};
630
631/* PRF M */
632static const unsigned char PRFM[] = {
633 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
634 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000635 0x10, 0x11, 0x12, 0x13
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000636};
637
638static const unsigned char PRFT[NB_PRF_TESTS][16] = {
639 {
640 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
641 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
642 },
643 {
644 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
645 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
646 },
647 {
648 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
649 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
650 }
651};
652
Brian Murray00dc5f02016-05-19 14:23:50 -0700653int test_cmac_with_cipher(int verbose,
654 const unsigned char* testname,
655 const unsigned char* key,
656 int keybits,
657 const unsigned char* messages,
658 size_t message_lengths[4],
659 const unsigned char* subkeys,
660 const unsigned char* expected_result,
661 mbedtls_cipher_id_t cipher_id,
662 int block_size)
663{
664 const int num_tests = 4;
665 mbedtls_cmac_context ctx;
666 int i, ret;
667 unsigned char* tag;
668
669 tag = mbedtls_calloc( block_size, sizeof( unsigned char ) );
670 mbedtls_cmac_init( &ctx );
671
672 if( ( ret = mbedtls_cmac_setkey( &ctx, cipher_id, key, keybits ) ) != 0 )
673 {
674 if( verbose != 0 )
675 mbedtls_printf( " CMAC: setup failed\n" );
676 goto exit;
677 }
678
679 if( ( ret = memcmp( ctx.K1, subkeys, block_size ) != 0 ) ||
680 ( ret = memcmp( ctx.K2, &subkeys[block_size], block_size ) != 0 ) )
681 {
682 if( verbose != 0 )
683 mbedtls_printf( " CMAC: subkey generation failed\n" );
684 goto exit;
685 }
686
687 for( i = 0; i < num_tests; i++ )
688 {
689 if( verbose != 0 )
690 mbedtls_printf( " %s CMAC #%u: ", testname, i +1 );
691
692 if( ( ret = mbedtls_cmac_generate( &ctx, messages, message_lengths[i], tag, block_size ) ) != 0 )
693 {
694 if( verbose != 0 )
695 mbedtls_printf( "failed\n" );
696 goto exit;
697 }
698 if( ( ret = memcmp( tag, &expected_result[i * block_size], block_size ) ) != 0 )
699 {
700 if( verbose != 0 )
701 mbedtls_printf( "failed\n" );
702 goto exit;
703 }
704
705 if( ( ret = mbedtls_cmac_verify( &ctx, messages, message_lengths[i], &expected_result[i * block_size], block_size ) != 0 ) )
706 {
707 if( verbose != 0 )
708 mbedtls_printf( "failed\n" );
709 goto exit;
710 }
711 mbedtls_printf( "passed\n" );
712 }
713 exit:
714 free( tag );
715 mbedtls_cmac_free( &ctx );
716 return( ret );
717}
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000718
719int mbedtls_cmac_self_test( int verbose )
720{
721 mbedtls_cmac_context ctx;
722 unsigned char tag[16];
723 int i;
724 int ret;
725
Brian Murray00dc5f02016-05-19 14:23:50 -0700726 test_cmac_with_cipher(verbose,
727 "AES 128",
728 aes_128_key,
729 128,
730 M,
731 Mlen,
732 aes_128_subkeys,
733 T_128,
734 MBEDTLS_CIPHER_ID_AES,
735 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000736
Brian Murray00dc5f02016-05-19 14:23:50 -0700737 test_cmac_with_cipher(verbose,
738 "AES 192",
739 aes_192_key,
740 192,
741 M,
742 Mlen,
743 aes_192_subkeys,
744 T_192,
745 MBEDTLS_CIPHER_ID_AES,
746 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000747
Brian Murray00dc5f02016-05-19 14:23:50 -0700748 test_cmac_with_cipher(verbose,
749 "AES 256",
750 aes_256_key,
751 256,
752 M,
753 Mlen,
754 aes_256_subkeys,
755 T_256,
756 MBEDTLS_CIPHER_ID_AES,
757 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000758
Brian Murray00dc5f02016-05-19 14:23:50 -0700759 test_cmac_with_cipher(verbose,
760 "3DES 2 key",
761 des3_2key_key,
762 192,
763 M,
764 Mlen_3des,
765 des3_2key_subkeys,
766 T_3des_2key,
767 MBEDTLS_CIPHER_ID_3DES,
768 8 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000769
Brian Murray00dc5f02016-05-19 14:23:50 -0700770 test_cmac_with_cipher(verbose,
771 "3DES 3 key",
772 des3_3key_key,
773 192,
774 M,
775 Mlen_3des,
776 des3_3key_subkeys,
777 T_3des_3key,
778 MBEDTLS_CIPHER_ID_3DES,
779 8 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000780
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000781
Brian Murrayb0c3c432016-05-18 14:29:51 -0700782 for( i = 0; i < NB_PRF_TESTS; i++ )
783 {
784 mbedtls_printf( " AES-CMAC-128-PRF #%u: ", i );
785
786 mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, tag );
787
788 if( ret != 0 ||
789 memcmp( tag, PRFT[i], 16 ) != 0 )
790 {
791 if( verbose != 0 )
792 mbedtls_printf( "failed\n" );
793
794 return( 1 );
795 } else if( verbose != 0 )
796 {
797 mbedtls_printf( "passed\n" );
798 }
799 }
800
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000801 if( verbose != 0 )
802 mbedtls_printf( "\n" );
Brian Murray00dc5f02016-05-19 14:23:50 -0700803*/
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000804 return( 0 );
805}
806
807#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
808
809#endif /* MBEDTLS_CMAC_C */