blob: fa32212eba3c0ffbce898470b78a67de056fae9e [file] [log] [blame]
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001/*
2 * NIST SP800-38B compliant CMAC implementation
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21
22/*
23 * Definition of CMAC:
24 * http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
25 * RFC 4493 "The AES-CMAC Algorithm"
26 */
27
28#if !defined(MBEDTLS_CONFIG_FILE)
29#include "mbedtls/config.h"
30#else
31#include MBEDTLS_CONFIG_FILE
32#endif
33
34#if defined(MBEDTLS_CMAC_C)
35
36#include "mbedtls/cmac.h"
37
38#include <string.h>
39
40#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
41#if defined(MBEDTLS_PLATFORM_C)
42#include "mbedtls/platform.h"
43#else
44#include <stdio.h>
45#define mbedtls_printf printf
46#endif /* MBEDTLS_PLATFORM_C */
47#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
48
49/*
50 * Macros for common operations.
51 * Results in smaller compiled code than static inline functions.
52 */
53
54/*
55 * XOR 128-bit
56 */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +000057#define XOR_128( i1, i2, o ) \
Robert Cragie3d23b1d2015-12-15 07:38:11 +000058 for( i = 0; i < 16; i++ ) \
59 ( o )[i] = ( i1 )[i] ^ ( i2 )[i];
60
61/*
62 * Update the CMAC state in Mn using an input block x
63 * TODO: Compiler optimisation
64 */
65#define UPDATE_CMAC( x ) \
66 XOR_128( Mn, ( x ), Mn ); \
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +000067 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \
68 Mn, 16, Mn, &olen ) ) != 0 ) \
Robert Cragie3d23b1d2015-12-15 07:38:11 +000069 return( ret );
70
71/* Implementation that should never be optimized out by the compiler */
72static void mbedtls_zeroize( void *v, size_t n ) {
73 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
74}
75
76/*
77 * Initialize context
78 */
79void mbedtls_cmac_init( mbedtls_cmac_context *ctx )
80{
81 memset( ctx, 0, sizeof( mbedtls_cmac_context ) );
82}
83
84/*
85 * Leftshift a 16-byte block by 1 bit
86 * \note output can be same as input
87 */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +000088static void leftshift_onebit( unsigned char *input, unsigned char *output )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000089{
90 int i;
91 unsigned char temp;
92 unsigned char overflow = 0;
93
94 for( i = 15; i >= 0; i-- )
95 {
96 temp = input[i];
97 output[i] = temp << 1;
98 output[i] |= overflow;
99 overflow = temp >> 7;
100 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000101
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000102 return;
103}
104
105/*
106 * Generate subkeys
107 */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000108static int generate_subkeys( mbedtls_cmac_context *ctx )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000109{
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000110 static const unsigned char Rb[2] = { 0x00, 0x87 }; /* block size 16 only */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000111 int ret;
112 unsigned char L[16];
113 size_t olen;
114
115 /* Calculate Ek(0) */
116 memset( L, 0, 16 );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000117 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx,
118 L, 16, L, &olen ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000119 {
120 return( ret );
121 }
122
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000123 /*
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000124 * Generate K1
125 * If MSB(L) = 0, then K1 = (L << 1)
126 * If MSB(L) = 1, then K1 = (L << 1) ^ Rb
127 */
128 leftshift_onebit( L, ctx->K1 );
129 ctx->K1[15] ^= Rb[L[0] >> 7]; /* "Constant-time" operation */
130
131 /*
132 * Generate K2
133 * If MSB(K1) == 0, then K2 = (K1 << 1)
134 * If MSB(K1) == 1, then K2 = (K1 << 1) ^ Rb
135 */
136 leftshift_onebit( ctx->K1, ctx->K2 );
137 ctx->K2[15] ^= Rb[ctx->K1[0] >> 7]; /* "Constant-time" operation */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000138
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000139 return( 0 );
140}
141
142int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx,
143 mbedtls_cipher_id_t cipher,
144 const unsigned char *key,
145 unsigned int keybits )
146{
147 int ret;
148 const mbedtls_cipher_info_t *cipher_info;
149
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000150 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
151 MBEDTLS_MODE_ECB );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000152 if( cipher_info == NULL )
153 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
154
155 if( cipher_info->block_size != 16 )
156 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
157
158 mbedtls_cipher_free( &ctx->cipher_ctx );
159
160 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
161 return( ret );
162
163 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000164 MBEDTLS_ENCRYPT ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000165 {
166 return( ret );
167 }
168
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000169 return( generate_subkeys( ctx ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000170}
171
172/*
173 * Free context
174 */
175void mbedtls_cmac_free( mbedtls_cmac_context *ctx )
176{
177 mbedtls_cipher_free( &ctx->cipher_ctx );
178 mbedtls_zeroize( ctx, sizeof( mbedtls_cmac_context ) );
179}
180
181/* TODO: Use cipher padding function? */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000182static void padding( const unsigned char *lastb,
183 unsigned char *pad,
184 const size_t length )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000185{
186 size_t j;
187
188 /* original last block */
189 for( j = 0; j < 16; j++ )
190 {
191 if( j < length )
192 {
193 pad[j] = lastb[j];
194 }
195 else if( j == length )
196 {
197 pad[j] = 0x80;
198 }
199 else
200 {
201 pad[j] = 0x00;
202 }
203 }
204}
205
206/*
207 * Generate tag on complete message
208 */
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000209static int cmac_generate( mbedtls_cmac_context *ctx,
210 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000211 unsigned char *tag, size_t tag_len )
212{
213 unsigned char Mn[16];
214 unsigned char M_last[16];
215 unsigned char padded[16];
216 int n, i, j, ret, flag;
217 size_t olen;
218
219 /*
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000220 * Check in_len requirements: SP800-38B A
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000221 * 4 is a worst case bottom limit
222 */
223 if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
224 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
225
226 /* TODO: Use cipher padding function? */
227 // mbedtls_cipher_set_padding_mode( ctx->cipher, MBEDTLS_PADDING_ONE_AND_ZEROS );
228
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000229 n = ( in_len + 15 ) / 16; /* n is number of rounds */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000230
231 if( n == 0 )
232 {
233 n = 1;
234 flag = 0;
235 }
236 else
237 {
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000238 flag = ( ( in_len % 16 ) == 0);
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000239 }
240
241 /* Calculate last block */
242 if( flag )
243 {
244 /* Last block is complete block */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000245 XOR_128( &input[16 * ( n - 1 )], ctx->K1, M_last );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000246 }
247 else
248 {
249 /* TODO: Use cipher padding function? */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000250 padding( &input[16 * ( n - 1 )], padded, in_len % 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000251 XOR_128( padded, ctx->K2, M_last );
252 }
253
254 memset( Mn, 0, 16 );
255
256 for( j = 0; j < n - 1; j++ )
257 {
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000258 UPDATE_CMAC( &input[16 * j] );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000259 }
260
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000261 UPDATE_CMAC( M_last );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000262
263 memcpy( tag, Mn, 16 );
264
265 return( 0 );
266}
267
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000268int mbedtls_cmac_generate( mbedtls_cmac_context *ctx,
269 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000270 unsigned char *tag, size_t tag_len )
271{
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000272 return( cmac_generate( ctx, input, in_len, tag, tag_len ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000273}
274
275/*
276 * Authenticated decryption
277 */
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000278int mbedtls_cmac_verify( mbedtls_cmac_context *ctx,
279 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000280 const unsigned char *tag, size_t tag_len )
281{
282 int ret;
283 unsigned char check_tag[16];
284 unsigned char i;
285 int diff;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000286
287 if( ( ret = cmac_generate( ctx, input, in_len, check_tag, tag_len ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000288 {
289 return ret;
290 }
291
292 /* Check tag in "constant-time" */
293 for( diff = 0, i = 0; i < tag_len; i++ )
294 {
295 diff |= tag[i] ^ check_tag[i];
296 }
297
298 if( diff != 0 )
299 {
300 return( MBEDTLS_ERR_CMAC_VERIFY_FAILED );
301 }
302
303 return( 0 );
304}
305
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000306int mbedtls_aes_cmac_prf_128( mbedtls_cmac_context *ctx,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000307 const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000308 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000309 unsigned char *tag )
310{
311 int ret;
312 unsigned char zero_key[16];
313 unsigned char int_key[16];
314
315 if( key_length == 16 )
316 {
317 /* Use key as is */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000318 memcpy( int_key, key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000319 }
320 else
321 {
322 mbedtls_cmac_context zero_ctx;
323
324 /* Key is AES_CMAC(0, key) */
325 mbedtls_cmac_init( &zero_ctx );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000326 memset( zero_key, 0, 16 );
327 ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES,
328 zero_key, 8 * sizeof zero_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000329 if( ret != 0 )
330 {
331 return( ret );
332 }
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000333 ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000334 if( ret != 0 )
335 {
336 return( ret );
337 }
338 }
339
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000340 ret = mbedtls_cmac_setkey( ctx, MBEDTLS_CIPHER_ID_AES,
341 int_key, 8 * sizeof int_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000342 if( ret != 0 )
343 {
344 return( ret );
345 }
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000346 return( mbedtls_cmac_generate( ctx, input, in_len, tag, 16 ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000347}
348
349#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
350/*
351 * Examples 1 to 4 from SP800-3B corrected Appendix D.1
352 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
353 */
354
355#define NB_CMAC_TESTS 4
356#define NB_PRF_TESTS 3
357
358/* Key */
359static const unsigned char key[] = {
360 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
361 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
362};
363
364/* Assume we don't need to test Ek0 as this is a function of the cipher */
365
366/* Subkey K1 */
367static const unsigned char K1[] = {
368 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
369 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
370};
371
372/* Subkey K2 */
373static const unsigned char K2[] = {
374 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
375 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
376};
377
378/* All Messages */
379static const unsigned char M[] = {
380 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
381 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
382 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
383 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
384 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
385 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
386 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
387 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
388};
389
390static const unsigned char T[NB_CMAC_TESTS][16] = {
391 {
392 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
393 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
394 },
395 {
396 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
397 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
398 },
399 {
400 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
401 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
402 },
403 {
404 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
405 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
406 }
407};
408
409/* Sizes in bytes */
410static const size_t Mlen[NB_CMAC_TESTS] = {
411 0,
412 16,
413 40,
414 64
415};
416
417/* PRF K */
418static const unsigned char PRFK[] = {
419 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
420 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
421 0xed, 0xcb
422};
423
424/* Sizes in bytes */
425static const size_t PRFKlen[NB_PRF_TESTS] = {
426 18,
427 16,
428 10
429};
430
431/* PRF M */
432static const unsigned char PRFM[] = {
433 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
434 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000435 0x10, 0x11, 0x12, 0x13
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000436};
437
438static const unsigned char PRFT[NB_PRF_TESTS][16] = {
439 {
440 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
441 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
442 },
443 {
444 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
445 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
446 },
447 {
448 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
449 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
450 }
451};
452
453
454int mbedtls_cmac_self_test( int verbose )
455{
456 mbedtls_cmac_context ctx;
457 unsigned char tag[16];
458 int i;
459 int ret;
460
461 mbedtls_cmac_init( &ctx );
462
463 if( mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 )
464 {
465 if( verbose != 0 )
466 mbedtls_printf( " CMAC: setup failed" );
467
468 return( 1 );
469 }
470
471 if( ( memcmp( ctx.K1, K1, 16 ) != 0 ) ||
472 ( memcmp( ctx.K2, K2, 16 ) != 0 ) )
473 {
474 if( verbose != 0 )
475 mbedtls_printf( " CMAC: subkey generation failed" );
476
477 return( 1 );
478 }
479
480 for( i = 0; i < NB_CMAC_TESTS; i++ )
481 {
482 mbedtls_printf( " AES-128-CMAC #%u: ", i );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000483
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000484 ret = mbedtls_cmac_generate( &ctx, M, Mlen[i], tag, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000485 if( ret != 0 ||
486 memcmp( tag, T[i], 16 ) != 0 )
487 {
488 if( verbose != 0 )
489 mbedtls_printf( "failed\n" );
490
491 return( 1 );
492 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000493
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000494 ret = mbedtls_cmac_verify( &ctx, M, Mlen[i], T[i], 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000495 if( ret != 0 )
496 {
497 if( verbose != 0 )
498 mbedtls_printf( "failed\n" );
499
500 return( 1 );
501 }
502
503 if( verbose != 0 )
504 mbedtls_printf( "passed\n" );
505 }
506
507 for( i = 0; i < NB_PRF_TESTS; i++ )
508 {
509 mbedtls_printf( " AES-CMAC-128-PRF #%u: ", i );
510
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000511 mbedtls_aes_cmac_prf_128( &ctx, PRFK, PRFKlen[i], PRFM, 20, tag );
512
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000513 if( ret != 0 ||
514 memcmp( tag, PRFT[i], 16 ) != 0 )
515 {
516 if( verbose != 0 )
517 mbedtls_printf( "failed\n" );
518
519 return( 1 );
520 }
521
522 if( verbose != 0 )
523 mbedtls_printf( "passed\n" );
524 }
525
526 mbedtls_cmac_free( &ctx );
527
528 if( verbose != 0 )
529 mbedtls_printf( "\n" );
530
531 return( 0 );
532}
533
534#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
535
536#endif /* MBEDTLS_CMAC_C */