blob: ab4a82ddfa6f2f92ccfde43af8b4b59f70016cf0 [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/*
Brian Murrayb0c3c432016-05-18 14:29:51 -070063 * Multiplication by u in the Galois field of GF(2^n)
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000064 *
Brian Murrayb0c3c432016-05-18 14:29:51 -070065 * As explained in the paper, this can computed:
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000066 * If MSB(p) = 0, then p = (p << 1)
Brian Murrayb0c3c432016-05-18 14:29:51 -070067 * If MSB(p) = 1, then p = (p << 1) ^ R_n
68 * with R_64 = 0x1B and R_128 = 0x87
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000069 *
70 * Input and output MUST not point to the same buffer
Brian Murrayb0c3c432016-05-18 14:29:51 -070071 * Block size must be 8 byes or 16 bytes.
Robert Cragie3d23b1d2015-12-15 07:38:11 +000072 */
Brian Murrayb0c3c432016-05-18 14:29:51 -070073static int cmac_multiply_by_u( unsigned char *output,
74 const unsigned char *input,
75 size_t blocksize)
Robert Cragie3d23b1d2015-12-15 07:38:11 +000076{
Robert Cragie3d23b1d2015-12-15 07:38:11 +000077
Brian Murrayb0c3c432016-05-18 14:29:51 -070078 const unsigned char R_128 = 0x87;
79 const unsigned char R_64 = 0x1B;
80 unsigned char R_n, mask;
81 unsigned char overflow = 0x00;
82 int i, starting_index;
83
84 starting_index = blocksize -1;
85
86 if(blocksize == 16){
87 R_n = R_128;
88 } else if(blocksize == 8) {
89 R_n = R_64;
90 } else {
91 return MBEDTLS_ERR_CMAC_BAD_INPUT;
92 }
93
94
95 for( i = starting_index; i >= 0; i-- )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000096 {
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000097 output[i] = input[i] << 1 | overflow;
98 overflow = input[i] >> 7;
Robert Cragie3d23b1d2015-12-15 07:38:11 +000099 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000100
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +0000101 /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
102 * using bit operations to avoid branches */
103 /* MSVC has a warning about unary minus on unsigned, but this is
104 * well-defined and precisely what we want to do here */
105#if defined(_MSC_VER)
106#pragma warning( push )
107#pragma warning( disable : 4146 )
108#endif
109 mask = - ( input[0] >> 7 );
110#if defined(_MSC_VER)
111#pragma warning( pop )
112#endif
113
Brian Murrayb0c3c432016-05-18 14:29:51 -0700114 output[starting_index] ^= R_n & mask;
115 return 0;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000116}
117
118/*
119 * Generate subkeys
120 */
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000121static int cmac_generate_subkeys( mbedtls_cmac_context *ctx )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000122{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700123 int ret, keybytes;
124 unsigned char *L;
125 size_t olen, block_size;
126
127 ret = 0;
128 block_size = ctx->cipher_ctx.cipher_info->block_size;
129
130 L = mbedtls_calloc(block_size, sizeof(unsigned char));
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000131
132 /* Calculate Ek(0) */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700133 memset( L, 0, block_size );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000134 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx,
Brian Murrayb0c3c432016-05-18 14:29:51 -0700135 L, block_size, L, &olen ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000136 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700137 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000138 }
139
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000140 /*
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000141 * Generate K1 and K2
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000142 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700143 if( ( ret = cmac_multiply_by_u( ctx->K1, L , block_size) ) != 0 )
144 goto exit;
145 if( ( cmac_multiply_by_u( ctx->K2, ctx->K1 , block_size) ) != 0 )
146 goto exit;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000147
Brian Murrayb0c3c432016-05-18 14:29:51 -0700148 exit:
149 mbedtls_zeroize( L, sizeof( L ) );
150 free(L);
151 return ret;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000152}
153
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000154/*
155 * Set key and prepare context for use
156 */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000157int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx,
158 mbedtls_cipher_id_t cipher,
159 const unsigned char *key,
160 unsigned int keybits )
161{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700162 int ret, blocksize;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000163 const mbedtls_cipher_info_t *cipher_info;
164
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000165 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
166 MBEDTLS_MODE_ECB );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000167 if( cipher_info == NULL )
168 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
169
Brian Murrayb0c3c432016-05-18 14:29:51 -0700170 ctx->K1 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) );
171 ctx->K2 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000172
173 mbedtls_cipher_free( &ctx->cipher_ctx );
174
175 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
176 return( ret );
177
178 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000179 MBEDTLS_ENCRYPT ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000180 {
181 return( ret );
182 }
183
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000184 return( cmac_generate_subkeys( ctx ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000185}
186
187/*
188 * Free context
189 */
190void mbedtls_cmac_free( mbedtls_cmac_context *ctx )
191{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700192 int block_size;
193 block_size = ctx->cipher_ctx.cipher_info->block_size;
194
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000195 mbedtls_cipher_free( &ctx->cipher_ctx );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700196
197 mbedtls_zeroize(ctx->K1, block_size * sizeof( unsigned char ) );
198 mbedtls_zeroize(ctx->K2, block_size * sizeof( unsigned char ) );
199 mbedtls_free( ctx->K1 );
200 mbedtls_free( ctx->K2 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000201}
202
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000203/*
204 * Create padded last block from (partial) last block.
205 *
206 * We can't use the padding option from the cipher layer, as it only works for
207 * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
208 */
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000209static void cmac_pad( unsigned char padded_block[16],
Brian Murrayb0c3c432016-05-18 14:29:51 -0700210 size_t padded_block_len,
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000211 const unsigned char *last_block,
Brian Murrayb0c3c432016-05-18 14:29:51 -0700212 size_t last_block_len )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000213{
214 size_t j;
215
Brian Murrayb0c3c432016-05-18 14:29:51 -0700216 for( j = 0; j < padded_block_len; j++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000217 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700218 if( j < last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000219 padded_block[j] = last_block[j];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700220 else if( j == last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000221 padded_block[j] = 0x80;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000222 else
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000223 padded_block[j] = 0x00;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000224 }
225}
226
227/*
Brian Murrayb0c3c432016-05-18 14:29:51 -0700228 * XOR Block
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000229 * Here, macro results in smaller compiled code than static inline function
230 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700231#define XOR_BLOCK( o, i1, i2 ) \
232 for( i = 0; i < block_size; i++ ) \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000233 ( o )[i] = ( i1 )[i] ^ ( i2 )[i];
234
235/*
236 * Update the CMAC state using an input block x
237 */
238#define UPDATE_CMAC( x ) \
239do { \
Brian Murrayb0c3c432016-05-18 14:29:51 -0700240 XOR_BLOCK( state, ( x ), state ); \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000241 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \
Brian Murrayb0c3c432016-05-18 14:29:51 -0700242 state, block_size, \
243 state, &olen ) ) != 0 ) \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000244 return( ret ); \
245} while( 0 )
246
247/*
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000248 * Generate tag on complete message
249 */
Manuel Pégourié-Gonnardab9c5fd2016-01-13 15:05:57 +0000250int mbedtls_cmac_generate( mbedtls_cmac_context *ctx,
251 const unsigned char *input, size_t in_len,
252 unsigned char *tag, size_t tag_len )
253
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000254{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700255
256 unsigned char *state;
257 unsigned char *M_last;
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000258 int n, i, j, ret, needs_padding;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700259 size_t olen, block_size;
260
261
262 ret = 0;
263 block_size = ctx->cipher_ctx.cipher_info->block_size;
264
265 state = mbedtls_calloc(block_size, sizeof(unsigned char) );
266 M_last = mbedtls_calloc(block_size, sizeof(unsigned char) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000267
268 /*
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000269 * Check in_len requirements: SP800-38B A
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000270 * 4 is a worst case bottom limit
271 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700272 if( tag_len < 4 || tag_len > block_size || tag_len % 2 != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000273 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
274
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000275 if( in_len == 0 )
276 needs_padding = 1;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000277 else
Brian Murrayb0c3c432016-05-18 14:29:51 -0700278 needs_padding = in_len % block_size != 0;
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000279
Brian Murrayb0c3c432016-05-18 14:29:51 -0700280 n = in_len / block_size + needs_padding;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000281
282 /* Calculate last block */
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000283 if( needs_padding )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000284 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700285 cmac_pad( M_last, block_size, input + block_size * ( n - 1 ), in_len % block_size );
286 XOR_BLOCK( M_last, M_last, ctx->K2 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000287 }
288 else
289 {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000290 /* Last block is complete block */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700291 XOR_BLOCK( M_last, input + block_size * ( n - 1 ), ctx->K1 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000292 }
293
Brian Murrayb0c3c432016-05-18 14:29:51 -0700294 memset( state, 0, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000295
296 for( j = 0; j < n - 1; j++ )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700297 UPDATE_CMAC( input + block_size * j );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000298
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000299 UPDATE_CMAC( M_last );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000300
Brian Murrayb0c3c432016-05-18 14:29:51 -0700301 memcpy( tag, state, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000302
Brian Murrayb0c3c432016-05-18 14:29:51 -0700303 exit:
304 free(state);
305 free(M_last);
306 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000307}
308
Brian Murrayb0c3c432016-05-18 14:29:51 -0700309#undef XOR_BLOCK
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000310#undef UPDATE_CMAC
311
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000312/*
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000313 * Verify tag on complete message
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000314 */
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000315int mbedtls_cmac_verify( mbedtls_cmac_context *ctx,
316 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000317 const unsigned char *tag, size_t tag_len )
318{
319 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700320 unsigned char *check_tag;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000321 unsigned char i;
322 int diff;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000323
Brian Murrayb0c3c432016-05-18 14:29:51 -0700324 check_tag = mbedtls_calloc(ctx->cipher_ctx.cipher_info->block_size,
325 sizeof(unsigned char) );
326
Manuel Pégourié-Gonnardab9c5fd2016-01-13 15:05:57 +0000327 if( ( ret = mbedtls_cmac_generate( ctx, input, in_len,
328 check_tag, tag_len ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000329 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700330 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000331 }
332
333 /* Check tag in "constant-time" */
334 for( diff = 0, i = 0; i < tag_len; i++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000335 diff |= tag[i] ^ check_tag[i];
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000336
337 if( diff != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700338 ret = MBEDTLS_ERR_CMAC_VERIFY_FAILED;
339 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000340
Brian Murrayb0c3c432016-05-18 14:29:51 -0700341 exit:
342 free(check_tag);
343 return ret;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000344}
345
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000346/*
347 * PRF based on CMAC with AES-128
Brian Murrayb0c3c432016-05-18 14:29:51 -0700348 * See RFC 4615
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000349 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700350int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000351 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000352 unsigned char *tag )
353{
354 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700355 mbedtls_cmac_context ctx;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000356 unsigned char zero_key[16];
357 unsigned char int_key[16];
358
Brian Murrayb0c3c432016-05-18 14:29:51 -0700359 mbedtls_cmac_init(&ctx);
360
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000361 if( key_length == 16 )
362 {
363 /* Use key as is */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000364 memcpy( int_key, key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000365 }
366 else
367 {
368 mbedtls_cmac_context zero_ctx;
369
370 /* Key is AES_CMAC(0, key) */
371 mbedtls_cmac_init( &zero_ctx );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000372 memset( zero_key, 0, 16 );
373 ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES,
374 zero_key, 8 * sizeof zero_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000375 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700376 goto exit;
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000377
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000378 ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000379 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700380 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000381 }
382
Brian Murrayb0c3c432016-05-18 14:29:51 -0700383 ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000384 int_key, 8 * sizeof int_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000385 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700386 goto exit;
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000387
388 mbedtls_zeroize( int_key, sizeof( int_key ) );
389
Brian Murrayb0c3c432016-05-18 14:29:51 -0700390 ret = mbedtls_cmac_generate( &ctx, input, in_len, tag, 16 );
391
392 exit:
393 mbedtls_cmac_free(&ctx);
394 return( ret );
395
396
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000397}
398
399#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
400/*
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000401 * Examples 1 to 4 from SP800-38B corrected Appendix D.1
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000402 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
403 */
404
Brian Murrayb0c3c432016-05-18 14:29:51 -0700405#define NB_CMAC_TESTS_AES_128 4
406#define NB_CMAC_TESTS_AES_192 4
407#define NB_CMAC_TESTS_AES_256 4
408#define NB_CMAC_TESTS_3DES 4
409
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000410#define NB_PRF_TESTS 3
411
Brian Murrayb0c3c432016-05-18 14:29:51 -0700412/* AES 128 Key */
413static const unsigned char aes_128_key[] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000414 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
415 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
416};
417
Brian Murrayb0c3c432016-05-18 14:29:51 -0700418/* AES 192 Key */
419static const unsigned char aes_192_key[] = {
420 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
421 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
422 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
423};
424
425/* AES 256 Key */
426static const unsigned char aes_256_key[] = {
427 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
428 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
429 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
430 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
431};
432
433/* 3DES 112 bit key */
434static const unsigned char des3_2key_key[] = {
435 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5,
436 0x8a, 0x3d, 0x10, 0xba, 0x80, 0x57, 0x0d, 0x38,
437 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5
438};
439
440/* 3DES 168 bit key */
441static const unsigned char des3_3key_key[] = {
442 0x8a, 0xa8, 0x3b, 0xf8, 0xcb, 0xda, 0x10, 0x62,
443 0x0b, 0xc1, 0xbf, 0x19, 0xfb, 0xb6, 0xcd, 0x58,
444 0xbc, 0x31, 0x3d, 0x4a, 0x37, 0x1c, 0xa8, 0xb5
445};
446
447
448
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000449/* Assume we don't need to test Ek0 as this is a function of the cipher */
450
451/* Subkey K1 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700452static const unsigned char aes_128_k1[] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000453 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
454 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
455};
456
457/* Subkey K2 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700458static const unsigned char aes_128_k2[] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000459 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
460 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
461};
462
Brian Murrayb0c3c432016-05-18 14:29:51 -0700463
464
465/* Subkey K1 */
466static const unsigned char aes_192_k1[] = {
467 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
468 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
469};
470
471/* Subkey K2 */
472static const unsigned char aes_192_k2[] = {
473 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
474 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
475};
476
477/* Subkey K1 */
478static const unsigned char aes_256_k1[] = {
479 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
480 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
481};
482
483/* Subkey K2 */
484static const unsigned char aes_256_k2[] = {
485 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
486 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
487};
488
489
490/* Subkey K1 */
491static const unsigned char des3_2key_k1[] = {
492 0x8e, 0xcf, 0x37, 0x3e, 0xd7, 0x1a, 0xfa, 0xef
493};
494
495/* Subkey K2 */
496static const unsigned char des3_2key_k2[] = {
497 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5
498};
499
500/* Subkey K1 */
501static const unsigned char des3_3key_k1[] = {
502 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f
503};
504
505/* Subkey K2 */
506static const unsigned char des3_3key_k2[] = {
507 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5
508};
509
510/* Assume we don't need to test Ek0 as this is a function of the cipher */
511
512
513
514/* All Messages are the same. The difference is the length */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000515static const unsigned char M[] = {
516 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
517 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
518 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
519 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
520 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
521 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
522 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
523 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
524};
525
Brian Murrayb0c3c432016-05-18 14:29:51 -0700526static const unsigned char T_128[NB_CMAC_TESTS_3DES][16] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000527 {
528 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
529 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
530 },
531 {
532 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
533 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
534 },
535 {
536 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
537 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
538 },
539 {
540 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
541 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
542 }
543};
544
545/* Sizes in bytes */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700546static const size_t Mlen[NB_CMAC_TESTS_AES_192] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000547 0,
548 16,
549 40,
550 64
551};
552
Brian Murrayb0c3c432016-05-18 14:29:51 -0700553static const size_t Mlen_3des[NB_CMAC_TESTS_AES_192] = {
554 0,
555 8,
556 20,
557 32
558};
559
560
561
562static const unsigned char T_256[NB_CMAC_TESTS_AES_192][16] = {
563 {
564 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
565 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
566 },
567 {
568 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
569 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
570 },
571 {
572 0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2,
573 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6
574 },
575 {
576 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
577 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
578 }
579};
580
581static const unsigned char T_192[NB_CMAC_TESTS_AES_192][16] = {
582 {
583 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
584 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
585 },
586 {
587 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
588 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
589 },
590 {
591 0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad,
592 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e
593 },
594 {
595 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
596 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
597 }
598};
599
600static const unsigned char T_3des_2key[NB_CMAC_TESTS_AES_192][16] = {
601 {
602 0xbd, 0x2e, 0xbf, 0x9a, 0x3b, 0xa0, 0x03, 0x61
603 },
604 {
605 0x4f, 0xf2, 0xab, 0x81, 0x3c, 0x53, 0xce, 0x83
606 },
607 {
608 0x62, 0xdd, 0x1b, 0x47, 0x19, 0x02, 0xbd, 0x4e
609 },
610 {
611 0x31, 0xb1, 0xe4, 0x31, 0xda, 0xbc, 0x4e, 0xb8
612 }
613};
614
615static const unsigned char T_3des_3key[NB_CMAC_TESTS_AES_192][16] = {
616 {
617 0xb7, 0xa6, 0x88, 0xe1, 0x22, 0xff, 0xaf, 0x95
618 },
619 {
620 0x8e, 0x8f, 0x29, 0x31, 0x36, 0x28, 0x37, 0x97
621 },
622 {
623 0x74, 0x3d, 0xdb, 0xe0, 0xce, 0x2d, 0xc2, 0xed
624 },
625 {
626 0x33, 0xe6, 0xb1, 0x09, 0x24, 0x00, 0xea, 0xe5
627 }
628};
629
630
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000631/* PRF K */
632static const unsigned char PRFK[] = {
633 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
634 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
635 0xed, 0xcb
636};
637
638/* Sizes in bytes */
639static const size_t PRFKlen[NB_PRF_TESTS] = {
640 18,
641 16,
642 10
643};
644
645/* PRF M */
646static const unsigned char PRFM[] = {
647 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
648 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000649 0x10, 0x11, 0x12, 0x13
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000650};
651
652static const unsigned char PRFT[NB_PRF_TESTS][16] = {
653 {
654 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
655 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
656 },
657 {
658 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
659 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
660 },
661 {
662 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
663 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
664 }
665};
666
667
668int mbedtls_cmac_self_test( int verbose )
669{
670 mbedtls_cmac_context ctx;
671 unsigned char tag[16];
672 int i;
673 int ret;
674
675 mbedtls_cmac_init( &ctx );
676
Brian Murrayb0c3c432016-05-18 14:29:51 -0700677 // AES 128 bit key
678 if( mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, aes_128_key, 8 * sizeof(aes_128_key) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000679 {
680 if( verbose != 0 )
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000681 mbedtls_printf( " CMAC: setup failed\n" );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000682
683 return( 1 );
684 }
685
Brian Murrayb0c3c432016-05-18 14:29:51 -0700686 if( ( memcmp( ctx.K1, aes_128_k1, 16 ) != 0 ) ||
687 ( memcmp( ctx.K2, aes_128_k2, 16 ) != 0 ) )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000688 {
689 if( verbose != 0 )
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000690 mbedtls_printf( " CMAC: subkey generation failed\n" );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000691
692 return( 1 );
693 }
694
Brian Murrayb0c3c432016-05-18 14:29:51 -0700695 for( i = 0; i < NB_CMAC_TESTS_AES_128; i++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000696 {
697 mbedtls_printf( " AES-128-CMAC #%u: ", i );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000698
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000699 ret = mbedtls_cmac_generate( &ctx, M, Mlen[i], tag, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000700 if( ret != 0 ||
Brian Murrayb0c3c432016-05-18 14:29:51 -0700701 memcmp( tag, T_128[i], 16 ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000702 {
703 if( verbose != 0 )
704 mbedtls_printf( "failed\n" );
705
706 return( 1 );
707 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000708
Brian Murrayb0c3c432016-05-18 14:29:51 -0700709 ret = mbedtls_cmac_verify( &ctx, M, Mlen[i], T_128[i], 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000710 if( ret != 0 )
711 {
712 if( verbose != 0 )
713 mbedtls_printf( "failed\n" );
714
715 return( 1 );
716 }
717
718 if( verbose != 0 )
719 mbedtls_printf( "passed\n" );
720 }
721
Brian Murrayb0c3c432016-05-18 14:29:51 -0700722 // AES 192 bit key
723 if( mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, aes_192_key, 8 * sizeof(aes_192_key) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000724 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700725 if( verbose != 0 )
726 mbedtls_printf( " CMAC: setup failed\n" );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000727
Brian Murrayb0c3c432016-05-18 14:29:51 -0700728 return( 1 );
729 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000730
Brian Murrayb0c3c432016-05-18 14:29:51 -0700731 if( ( memcmp( ctx.K1, aes_192_k1, 16 ) != 0 ) ||
732 ( memcmp( ctx.K2, aes_192_k2, 16 ) != 0 ) )
733 {
734 if( verbose != 0 )
735 mbedtls_printf( " CMAC: subkey generation failed\n" );
736
737 return( 1 );
738 }
739
740 for( i = 0; i < NB_CMAC_TESTS_AES_192; i++ )
741 {
742 mbedtls_printf( " AES-192-CMAC #%u: ", i );
743
744 ret = mbedtls_cmac_generate( &ctx, M, Mlen[i], tag, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000745 if( ret != 0 ||
Brian Murrayb0c3c432016-05-18 14:29:51 -0700746 memcmp( tag, T_192[i], 16 ) != 0 )
747 {
748 if( verbose != 0 )
749 mbedtls_printf( "failed\n" );
750
751 return( 1 );
752 }
753
754 ret = mbedtls_cmac_verify( &ctx, M, Mlen[i], T_192[i], 16 );
755 if( ret != 0 )
756 {
757 if( verbose != 0 )
758 mbedtls_printf( "failed\n" );
759
760 return( 1 );
761 }
762
763 if( verbose != 0 )
764 mbedtls_printf( "passed\n" );
765 }
766
767 // 3DES 2 key bit key
768 if( (ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_3DES, des3_2key_key, 8 * sizeof(des3_2key_key) )) != 0 )
769 {
770 if( verbose != 0 )
771 mbedtls_printf( " CMAC: setup failed %i\n", ret);
772
773 return( 1 );
774 }
775
776 if( ( memcmp( ctx.K1, des3_2key_k1, 8 ) != 0 ) ||
777 ( memcmp( ctx.K2, des3_2key_k2, 8 ) != 0 ) )
778 {
779 if( verbose != 0 )
780 mbedtls_printf( " CMAC: subkey generation failed\n" );
781
782 return( 1 );
783 }
784
785 for( i = 0; i < NB_CMAC_TESTS_3DES; i++ )
786 {
787 mbedtls_printf( " DES-112-CMAC #%u: ", i );
788
789 ret = mbedtls_cmac_generate( &ctx, M, Mlen_3des[i], tag, 8 );
790 if( ret != 0 ||
791 memcmp( tag, T_3des_2key[i], 8 ) != 0 )
792 {
793 if( verbose != 0 )
794 mbedtls_printf( "failed\n" );
795
796 return( 1 );
797 }
798
799 ret = mbedtls_cmac_verify( &ctx, M, Mlen_3des[i], T_3des_2key[i], 8 );
800 if( ret != 0 )
801 {
802 if( verbose != 0 )
803 mbedtls_printf( "failed\n" );
804
805 return( 1 );
806 }
807
808 if( verbose != 0 )
809 mbedtls_printf( "passed\n" );
810 }
811
812 // 3DES 3 key
813 if( (ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_3DES, des3_3key_key, 8 * sizeof(des3_3key_key) )) != 0 )
814 {
815 if( verbose != 0 )
816 mbedtls_printf( " CMAC: setup failed %i\n", ret);
817
818 return( 1 );
819 }
820
821 if( ( memcmp( ctx.K1, des3_3key_k1, 8 ) != 0 ) ||
822 ( memcmp( ctx.K2, des3_3key_k2, 8 ) != 0 ) )
823 {
824 if( verbose != 0 )
825 mbedtls_printf( " CMAC: subkey generation failed\n" );
826
827 return( 1 );
828 }
829
830 for( i = 0; i < NB_CMAC_TESTS_3DES; i++ )
831 {
832 mbedtls_printf( " DES-168-CMAC #%u: ", i );
833
834 ret = mbedtls_cmac_generate( &ctx, M, Mlen_3des[i], tag, 8 );
835 if( ret != 0 ||
836 memcmp( tag, T_3des_3key[i], 8 ) != 0 )
837 {
838 if( verbose != 0 )
839 mbedtls_printf( "failed\n" );
840
841 return( 1 );
842 }
843
844 ret = mbedtls_cmac_verify( &ctx, M, Mlen_3des[i], T_3des_3key[i], 8 );
845 if( ret != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000846 {
847 if( verbose != 0 )
848 mbedtls_printf( "failed\n" );
849
850 return( 1 );
851 }
852
853 if( verbose != 0 )
854 mbedtls_printf( "passed\n" );
855 }
856
857 mbedtls_cmac_free( &ctx );
858
Brian Murrayb0c3c432016-05-18 14:29:51 -0700859 for( i = 0; i < NB_PRF_TESTS; i++ )
860 {
861 mbedtls_printf( " AES-CMAC-128-PRF #%u: ", i );
862
863 mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, tag );
864
865 if( ret != 0 ||
866 memcmp( tag, PRFT[i], 16 ) != 0 )
867 {
868 if( verbose != 0 )
869 mbedtls_printf( "failed\n" );
870
871 return( 1 );
872 } else if( verbose != 0 )
873 {
874 mbedtls_printf( "passed\n" );
875 }
876 }
877
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000878 if( verbose != 0 )
879 mbedtls_printf( "\n" );
880
881 return( 0 );
882}
883
884#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
885
886#endif /* MBEDTLS_CMAC_C */