blob: 0fa5b58f50cfa880cf2e804a07cd3bd0affacfca [file] [log] [blame]
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001/*
Brian Murray53e23b62016-09-13 14:00:15 -07002 * \file cmac.c
Simon Butcher327398a2016-10-05 14:09:11 +01003 *
Simon Butcher69283e52016-10-06 12:49:58 +01004 * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES
Robert Cragie3d23b1d2015-12-15 07:38:11 +00005 *
Brian Murray53e23b62016-09-13 14:00:15 -07006 * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
Robert Cragie3d23b1d2015-12-15 07:38:11 +00007 * SPDX-License-Identifier: Apache-2.0
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License"); you may
10 * not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 * This file is part of mbed TLS (https://tls.mbed.org)
22 */
23
24/*
Brian Murray53e23b62016-09-13 14:00:15 -070025 * References:
Simon Butcher327398a2016-10-05 14:09:11 +010026 *
27 * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The
28 * CMAC Mode for Authentication
29 * http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38b.pdf
30 *
31 * - RFC 4493 - The AES-CMAC Algorithm
32 * https://tools.ietf.org/html/rfc4493
33 *
34 * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message
35 * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128)
36 * Algorithm for the Internet Key Exchange Protocol (IKE)
37 * https://tools.ietf.org/html/rfc4615
38 *
39 * Additional test vectors: ISO/IEC 9797-1
40 *
Robert Cragie3d23b1d2015-12-15 07:38:11 +000041 */
42
43#if !defined(MBEDTLS_CONFIG_FILE)
44#include "mbedtls/config.h"
45#else
46#include MBEDTLS_CONFIG_FILE
47#endif
48
49#if defined(MBEDTLS_CMAC_C)
50
51#include "mbedtls/cmac.h"
52
53#include <string.h>
54
Brian Murray8b4111c2016-09-13 15:58:46 -070055
Robert Cragie3d23b1d2015-12-15 07:38:11 +000056#if defined(MBEDTLS_PLATFORM_C)
57#include "mbedtls/platform.h"
58#else
Brian Murray8b4111c2016-09-13 15:58:46 -070059#include <stdlib.h>
60#define mbedtls_calloc calloc
61#define mbedtls_free free
Simon Butcherd241f1c2016-10-06 10:39:49 +010062#if defined(MBEDTLS_SELF_TEST)
Robert Cragie3d23b1d2015-12-15 07:38:11 +000063#include <stdio.h>
Brian Murray8b4111c2016-09-13 15:58:46 -070064#define mbedtls_printf printf
Brian J Murray2adecba2016-11-06 04:45:15 -080065#endif /* MBEDTLS_SELF_TEST */
Robert Cragie3d23b1d2015-12-15 07:38:11 +000066#endif /* MBEDTLS_PLATFORM_C */
Brian Murray8b4111c2016-09-13 15:58:46 -070067
Robert Cragie3d23b1d2015-12-15 07:38:11 +000068/* Implementation that should never be optimized out by the compiler */
69static void mbedtls_zeroize( void *v, size_t n ) {
Simon Butcher327398a2016-10-05 14:09:11 +010070 volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
Robert Cragie3d23b1d2015-12-15 07:38:11 +000071}
72
73/*
Brian Murrayb0c3c432016-05-18 14:29:51 -070074 * Multiplication by u in the Galois field of GF(2^n)
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000075 *
Brian Murray72b69e32016-09-13 14:21:01 -070076 * As explained in NIST SP 800-38B, this can be computed:
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000077 *
Simon Butcher327398a2016-10-05 14:09:11 +010078 * If MSB(p) = 0, then p = (p << 1)
79 * If MSB(p) = 1, then p = (p << 1) ^ R_n
80 * with R_64 = 0x1B and R_128 = 0x87
81 *
82 * Input and output MUST NOT point to the same buffer
Brian J Murray2adecba2016-11-06 04:45:15 -080083 * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES.
Robert Cragie3d23b1d2015-12-15 07:38:11 +000084 */
Brian Murrayb0c3c432016-05-18 14:29:51 -070085static int cmac_multiply_by_u( unsigned char *output,
86 const unsigned char *input,
Brian Murray53e23b62016-09-13 14:00:15 -070087 size_t blocksize )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000088{
Brian Murrayb0c3c432016-05-18 14:29:51 -070089 const unsigned char R_128 = 0x87;
90 const unsigned char R_64 = 0x1B;
91 unsigned char R_n, mask;
92 unsigned char overflow = 0x00;
Simon Butcher327398a2016-10-05 14:09:11 +010093 int i;
Brian Murrayb0c3c432016-05-18 14:29:51 -070094
Simon Butcher69283e52016-10-06 12:49:58 +010095 if( blocksize == MBEDTLS_AES_BLOCK_SIZE )
Brian Murray6a3c0d22016-05-20 18:25:43 -070096 {
Brian Murrayb0c3c432016-05-18 14:29:51 -070097 R_n = R_128;
Simon Butcher327398a2016-10-05 14:09:11 +010098 }
Simon Butcher69283e52016-10-06 12:49:58 +010099 else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE )
Brian Murray6a3c0d22016-05-20 18:25:43 -0700100 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700101 R_n = R_64;
Simon Butcher327398a2016-10-05 14:09:11 +0100102 }
103 else
Brian Murray6a3c0d22016-05-20 18:25:43 -0700104 {
Simon Butcher327398a2016-10-05 14:09:11 +0100105 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700106 }
107
Simon B3249cb72016-11-03 01:11:37 +0000108 for( i = (int)blocksize - 1; i >= 0; i-- )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000109 {
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000110 output[i] = input[i] << 1 | overflow;
111 overflow = input[i] >> 7;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000112 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000113
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +0000114 /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
115 * using bit operations to avoid branches */
Simon Butcher327398a2016-10-05 14:09:11 +0100116
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +0000117 /* MSVC has a warning about unary minus on unsigned, but this is
118 * well-defined and precisely what we want to do here */
119#if defined(_MSC_VER)
120#pragma warning( push )
121#pragma warning( disable : 4146 )
122#endif
123 mask = - ( input[0] >> 7 );
124#if defined(_MSC_VER)
125#pragma warning( pop )
126#endif
127
Simon Butcher327398a2016-10-05 14:09:11 +0100128 output[ blocksize - 1 ] ^= R_n & mask;
129
Brian Murrayb439d452016-05-19 16:02:42 -0700130 return( 0 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000131}
132
133/*
134 * Generate subkeys
Simon Butcher327398a2016-10-05 14:09:11 +0100135 *
136 * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000137 */
Simon Butcher327398a2016-10-05 14:09:11 +0100138static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx,
139 unsigned char* K1, unsigned char* K2 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000140{
Brian Murray57863ad2016-05-19 16:38:36 -0700141 int ret;
Simon Butcher69283e52016-10-06 12:49:58 +0100142 unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700143 size_t olen, block_size;
144
Simon Butcher327398a2016-10-05 14:09:11 +0100145 mbedtls_zeroize( L, sizeof( L ) );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700146
Simon Butcher327398a2016-10-05 14:09:11 +0100147 block_size = ctx->cipher_info->block_size;
148
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000149 /* Calculate Ek(0) */
Simon Butcher327398a2016-10-05 14:09:11 +0100150 if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700151 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000152
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000153 /*
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000154 * Generate K1 and K2
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000155 */
Simon Butcher327398a2016-10-05 14:09:11 +0100156 if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700157 goto exit;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000158
Simon Butcher327398a2016-10-05 14:09:11 +0100159 if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 )
160 goto exit;
161
162exit:
163 mbedtls_zeroize( L, sizeof( L ) );
164
165 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000166}
167
Simon Butcher69283e52016-10-06 12:49:58 +0100168static void cmac_xor_block( unsigned char *output, const unsigned char *input1,
169 const unsigned char *input2,
170 const size_t block_size )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000171{
Simon Butcher327398a2016-10-05 14:09:11 +0100172 size_t index;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000173
Simon Butcher327398a2016-10-05 14:09:11 +0100174 for( index = 0; index < block_size; index++ )
175 output[ index ] = input1[ index ] ^ input2[ index ];
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000176}
177
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000178/*
179 * Create padded last block from (partial) last block.
180 *
181 * We can't use the padding option from the cipher layer, as it only works for
182 * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
183 */
Simon Butcher69283e52016-10-06 12:49:58 +0100184static void cmac_pad( unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX],
Brian Murray53e23b62016-09-13 14:00:15 -0700185 size_t padded_block_len,
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000186 const unsigned char *last_block,
Brian Murrayb0c3c432016-05-18 14:29:51 -0700187 size_t last_block_len )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000188{
189 size_t j;
190
Brian Murrayb0c3c432016-05-18 14:29:51 -0700191 for( j = 0; j < padded_block_len; j++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000192 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700193 if( j < last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000194 padded_block[j] = last_block[j];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700195 else if( j == last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000196 padded_block[j] = 0x80;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000197 else
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000198 padded_block[j] = 0x00;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000199 }
200}
201
Simon Butcher327398a2016-10-05 14:09:11 +0100202int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx,
Simon Butcher94ffde72016-10-05 15:33:53 +0100203 const unsigned char *key, size_t keybits )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000204{
Simon Butcher327398a2016-10-05 14:09:11 +0100205 mbedtls_cipher_type_t type;
206 mbedtls_cmac_context_t *cmac_ctx;
Simon Butcher327398a2016-10-05 14:09:11 +0100207 int retval;
208
209 if( ctx == NULL || ctx->cipher_info == NULL || key == NULL )
210 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
211
Simon B3249cb72016-11-03 01:11:37 +0000212 if( ( retval = mbedtls_cipher_setkey( ctx, key, (int)keybits,
Simon Butcher327398a2016-10-05 14:09:11 +0100213 MBEDTLS_ENCRYPT ) ) != 0 )
214 return( retval );
215
Simon Butcher327398a2016-10-05 14:09:11 +0100216 type = ctx->cipher_info->type;
217
218 switch( type )
219 {
220 case MBEDTLS_CIPHER_AES_128_ECB:
221 case MBEDTLS_CIPHER_AES_192_ECB:
222 case MBEDTLS_CIPHER_AES_256_ECB:
223 case MBEDTLS_CIPHER_DES_EDE3_ECB:
224 break;
225 default:
226 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
227 }
228
229 /* Allocated and initialise in the cipher context memory for the CMAC
230 * context */
231 cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) );
232 if( cmac_ctx == NULL )
233 return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
234
235 ctx->cmac_ctx = cmac_ctx;
236
237 mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100238
239 return 0;
240}
241
242int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx,
243 const unsigned char *input, size_t ilen )
244{
245 mbedtls_cmac_context_t* cmac_ctx;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700246 unsigned char *state;
Simon B3249cb72016-11-03 01:11:37 +0000247 int ret = 0;
248 size_t n, j, olen, block_size;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700249
Simon Butcher327398a2016-10-05 14:09:11 +0100250 if( ctx == NULL || ctx->cipher_info == NULL || input == NULL ||
251 ctx->cmac_ctx == NULL )
252 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700253
Simon Butcher327398a2016-10-05 14:09:11 +0100254 cmac_ctx = ctx->cmac_ctx;
255 block_size = ctx->cipher_info->block_size;
256 state = ctx->cmac_ctx->state;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000257
Simon Butcher6b0774a2016-10-10 21:37:42 +0100258 /* Is there data still to process from the last call, that's greater in
259 * size than a block? */
Simon Butcher327398a2016-10-05 14:09:11 +0100260 if( cmac_ctx->unprocessed_len > 0 &&
Andres AGa592dcc2016-10-06 15:23:39 +0100261 ilen > block_size - cmac_ctx->unprocessed_len )
Brian Murray57863ad2016-05-19 16:38:36 -0700262 {
Simon Butcher327398a2016-10-05 14:09:11 +0100263 memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
264 input,
265 block_size - cmac_ctx->unprocessed_len );
266
267 cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size );
268
269 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
270 &olen ) ) != 0 )
271 {
272 goto exit;
273 }
274
Simon Butcher6b0774a2016-10-10 21:37:42 +0100275 input += block_size - cmac_ctx->unprocessed_len;
276 ilen -= block_size - cmac_ctx->unprocessed_len;
Simon Butcher327398a2016-10-05 14:09:11 +0100277 cmac_ctx->unprocessed_len = 0;
Brian Murray57863ad2016-05-19 16:38:36 -0700278 }
279
Simon Butcher327398a2016-10-05 14:09:11 +0100280 /* n is the number of blocks including any final partial block */
281 n = ( ilen + block_size - 1 ) / block_size;
282
Simon B3249cb72016-11-03 01:11:37 +0000283 /* Iterate across the input data in block sized chunks, excluding any
284 * final partial or complete block */
285 for( j = 1; j < n; j++ )
Brian Murray57863ad2016-05-19 16:38:36 -0700286 {
Simon Butcher327398a2016-10-05 14:09:11 +0100287 cmac_xor_block( state, input, state, block_size );
288
289 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
290 &olen ) ) != 0 )
291 goto exit;
292
293 ilen -= block_size;
294 input += block_size;
Brian Murray57863ad2016-05-19 16:38:36 -0700295 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000296
Simon Butcher327398a2016-10-05 14:09:11 +0100297 /* If there is data left over that wasn't aligned to a block */
298 if( ilen > 0 )
299 {
Simon Butcher6b0774a2016-10-10 21:37:42 +0100300 memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
301 input,
302 ilen );
303 cmac_ctx->unprocessed_len += ilen;
Simon Butcher327398a2016-10-05 14:09:11 +0100304 }
305
306exit:
307 return( ret );
308}
309
310int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx,
311 unsigned char *output )
312{
313 mbedtls_cmac_context_t* cmac_ctx;
Simon Butcher69283e52016-10-06 12:49:58 +0100314 unsigned char *state, *last_block;
315 unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
316 unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
317 unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX];
Simon Butcher327398a2016-10-05 14:09:11 +0100318 int ret;
319 size_t olen, block_size;
320
321 if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ||
322 output == NULL )
323 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
324
325 cmac_ctx = ctx->cmac_ctx;
326 block_size = ctx->cipher_info->block_size;
327 state = cmac_ctx->state;
328
Simon Butcher69283e52016-10-06 12:49:58 +0100329 mbedtls_zeroize( K1, sizeof( K1 ) );
330 mbedtls_zeroize( K2, sizeof( K2 ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100331 cmac_generate_subkeys( ctx, K1, K2 );
332
Simon Butcher69283e52016-10-06 12:49:58 +0100333 last_block = cmac_ctx->unprocessed_block;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000334
335 /* Calculate last block */
Janos Follathe3d882a2016-10-11 10:49:26 +0100336 if( cmac_ctx->unprocessed_len < block_size )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000337 {
Simon Butcher327398a2016-10-05 14:09:11 +0100338 cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len );
339 cmac_xor_block( M_last, M_last, K2, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000340 }
341 else
342 {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000343 /* Last block is complete block */
Simon Butcher327398a2016-10-05 14:09:11 +0100344 cmac_xor_block( M_last, last_block, K1, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000345 }
346
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000347
Simon Butcher327398a2016-10-05 14:09:11 +0100348 cmac_xor_block( state, M_last, state, block_size );
349 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
350 &olen ) ) != 0 )
351 {
352 goto exit;
353 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000354
Simon Butcher327398a2016-10-05 14:09:11 +0100355 memcpy( output, state, block_size );
356
357exit:
358 /* Wipe the generated keys on the stack, and any other transients to avoid
359 * side channel leakage */
Simon Butcher69283e52016-10-06 12:49:58 +0100360 mbedtls_zeroize( K1, sizeof( K1 ) );
361 mbedtls_zeroize( K2, sizeof( K2 ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100362
363 cmac_ctx->unprocessed_len = 0;
364 mbedtls_zeroize( cmac_ctx->unprocessed_block,
Simon Butcher69283e52016-10-06 12:49:58 +0100365 sizeof( cmac_ctx->unprocessed_block ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100366
Simon Butcher69283e52016-10-06 12:49:58 +0100367 mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX );
Simon Butcher327398a2016-10-05 14:09:11 +0100368 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000369}
370
Simon Butcher327398a2016-10-05 14:09:11 +0100371int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000372{
Simon Butcher327398a2016-10-05 14:09:11 +0100373 mbedtls_cmac_context_t* cmac_ctx;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000374
Simon Butcher327398a2016-10-05 14:09:11 +0100375 if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL )
376 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700377
Simon Butcher327398a2016-10-05 14:09:11 +0100378 cmac_ctx = ctx->cmac_ctx;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000379
Simon Butcher327398a2016-10-05 14:09:11 +0100380 /* Reset the internal state */
381 cmac_ctx->unprocessed_len = 0;
382 mbedtls_zeroize( cmac_ctx->unprocessed_block,
Andres AGa592dcc2016-10-06 15:23:39 +0100383 sizeof( cmac_ctx->unprocessed_block ) );
Simon Butcherd241f1c2016-10-06 10:39:49 +0100384 mbedtls_zeroize( cmac_ctx->state,
385 sizeof( cmac_ctx->state ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000386
Simon Butcher327398a2016-10-05 14:09:11 +0100387 return( 0 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000388}
389
Simon Butcher327398a2016-10-05 14:09:11 +0100390int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info,
391 const unsigned char *key, size_t keylen,
392 const unsigned char *input, size_t ilen,
393 unsigned char *output )
394{
395 mbedtls_cipher_context_t ctx;
396 int ret;
397
398 if( cipher_info == NULL || key == NULL || input == NULL || output == NULL )
399 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
400
401 mbedtls_cipher_init( &ctx );
402
403 if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
404 goto exit;
405
406 ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen );
Simon Butcher327398a2016-10-05 14:09:11 +0100407 if( ret != 0 )
408 goto exit;
Simon Butcher327398a2016-10-05 14:09:11 +0100409
410 ret = mbedtls_cipher_cmac_update( &ctx, input, ilen );
411 if( ret != 0 )
412 goto exit;
413
Simon Butcher69283e52016-10-06 12:49:58 +0100414 ret = mbedtls_cipher_cmac_finish( &ctx, output );
Simon Butcher327398a2016-10-05 14:09:11 +0100415
416exit:
Simon Butcher69283e52016-10-06 12:49:58 +0100417 mbedtls_cipher_free( &ctx );
418
Simon Butcher327398a2016-10-05 14:09:11 +0100419 return( ret );
420}
Simon Butcher327398a2016-10-05 14:09:11 +0100421
Simon Butcher69283e52016-10-06 12:49:58 +0100422#if defined(MBEDTLS_AES_C)
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000423/*
Simon Butcher69283e52016-10-06 12:49:58 +0100424 * Implementation of AES-CMAC-PRF-128 defined in RFC 4615
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000425 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700426int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000427 const unsigned char *input, size_t in_len,
Simon Butcher327398a2016-10-05 14:09:11 +0100428 unsigned char *output )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000429{
430 int ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100431 const mbedtls_cipher_info_t *cipher_info;
Simon Butcher69283e52016-10-06 12:49:58 +0100432 unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE];
433 unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE];
434
435 if( key == NULL || input == NULL || output == NULL )
436 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000437
Simon Butcher327398a2016-10-05 14:09:11 +0100438 cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB );
439 if( cipher_info == NULL )
440 {
441 /* Failing at this point must be due to a build issue */
442 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
443 goto exit;
444 }
Brian Murrayb0c3c432016-05-18 14:29:51 -0700445
Simon Butcher69283e52016-10-06 12:49:58 +0100446 if( key_length == MBEDTLS_AES_BLOCK_SIZE )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000447 {
448 /* Use key as is */
Simon Butcher69283e52016-10-06 12:49:58 +0100449 memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000450 }
451 else
452 {
Simon Butcher69283e52016-10-06 12:49:58 +0100453 memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE );
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000454
Simon Butcher327398a2016-10-05 14:09:11 +0100455 ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key,
456 key_length, int_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000457 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700458 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000459 }
460
Simon Butcher327398a2016-10-05 14:09:11 +0100461 ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len,
462 output );
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000463
Simon Butcher327398a2016-10-05 14:09:11 +0100464exit:
465 mbedtls_zeroize( int_key, sizeof( int_key ) );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700466
Simon Butcher327398a2016-10-05 14:09:11 +0100467 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000468}
Brian Murrayb439d452016-05-19 16:02:42 -0700469#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000470
Simon Butcher69283e52016-10-06 12:49:58 +0100471#if defined(MBEDTLS_SELF_TEST)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000472/*
Brian Murray0f6af732016-05-19 15:59:23 -0700473 * CMAC test data from SP800-38B Appendix D.1 (corrected)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000474 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
Brian Murray0f6af732016-05-19 15:59:23 -0700475 *
476 * AES-CMAC-PRF-128 test data from RFC 4615
477 * https://tools.ietf.org/html/rfc4615#page-4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000478 */
479
Brian Murray0f6af732016-05-19 15:59:23 -0700480#define NB_CMAC_TESTS_PER_KEY 4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000481#define NB_PRF_TESTS 3
Simon Butcher327398a2016-10-05 14:09:11 +0100482
Brian Murray0f6af732016-05-19 15:59:23 -0700483#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
484/* All CMAC test inputs are truncated from the same 64 byte buffer. */
485static const unsigned char test_message[] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000486 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
487 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
488 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
489 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
490 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
491 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
492 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
493 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
494};
Simon Butcher69283e52016-10-06 12:49:58 +0100495#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */
Brian Murray0cf14c12016-05-23 12:49:50 -0700496
Simon Butcher69283e52016-10-06 12:49:58 +0100497#if defined(MBEDTLS_AES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700498/* Truncation point of message for AES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700499static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700500 0,
501 16,
502 40,
503 64
504};
505
506/* AES 128 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700507static const unsigned char aes_128_key[16] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700508 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
509 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
510};
Simon Butcher69283e52016-10-06 12:49:58 +0100511static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700512 {
513 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
514 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
515 },
516 {
517 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
518 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
519 }
520};
Simon Butcher69283e52016-10-06 12:49:58 +0100521static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000522 {
523 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
524 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
525 },
526 {
527 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
528 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
529 },
530 {
531 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
532 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
533 },
534 {
535 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
536 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
537 }
538};
539
Brian Murray0f6af732016-05-19 15:59:23 -0700540/* AES 192 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700541static const unsigned char aes_192_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700542 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
543 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
544 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000545};
Simon Butcher69283e52016-10-06 12:49:58 +0100546static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700547 {
Brian Murray0f6af732016-05-19 15:59:23 -0700548 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
549 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
Brian Murrayb0c3c432016-05-18 14:29:51 -0700550 },
551 {
Brian Murray0f6af732016-05-19 15:59:23 -0700552 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
553 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
Brian Murrayb0c3c432016-05-18 14:29:51 -0700554 }
555};
Simon Butcher69283e52016-10-06 12:49:58 +0100556static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700557 {
558 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
559 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
560 },
561 {
562 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
563 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
564 },
565 {
566 0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad,
567 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e
568 },
569 {
570 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
571 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
572 }
573};
574
Brian Murray0f6af732016-05-19 15:59:23 -0700575/* AES 256 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700576static const unsigned char aes_256_key[32] = {
Brian Murray87e40402016-05-19 19:05:57 -0700577 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
578 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
579 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
580 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
Brian Murray0f6af732016-05-19 15:59:23 -0700581};
Simon Butcher69283e52016-10-06 12:49:58 +0100582static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700583 {
584 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
585 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
586 },
587 {
588 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
589 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
590 }
591};
Simon Butcher69283e52016-10-06 12:49:58 +0100592static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700593 {
594 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
595 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
596 },
597 {
598 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
599 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
600 },
601 {
602 0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2,
603 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6
604 },
605 {
606 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
607 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
608 }
609};
610#endif /* MBEDTLS_AES_C */
611
Simon Butcher69283e52016-10-06 12:49:58 +0100612#if defined(MBEDTLS_DES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700613/* Truncation point of message for 3DES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700614static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700615 0,
616 8,
617 20,
618 32
619};
620
621/* 3DES 2 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700622static const unsigned char des3_2key_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700623 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5,
624 0x8a, 0x3d, 0x10, 0xba, 0x80, 0x57, 0x0d, 0x38,
625 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5
Brian Murray0f6af732016-05-19 15:59:23 -0700626};
627static const unsigned char des3_2key_subkeys[2][8] = {
628 {
629 0x8e, 0xcf, 0x37, 0x3e, 0xd7, 0x1a, 0xfa, 0xef
630 },
631 {
632 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5
633 }
634};
Simon Butcher69283e52016-10-06 12:49:58 +0100635static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700636 {
637 0xbd, 0x2e, 0xbf, 0x9a, 0x3b, 0xa0, 0x03, 0x61
638 },
639 {
640 0x4f, 0xf2, 0xab, 0x81, 0x3c, 0x53, 0xce, 0x83
641 },
642 {
643 0x62, 0xdd, 0x1b, 0x47, 0x19, 0x02, 0xbd, 0x4e
644 },
645 {
646 0x31, 0xb1, 0xe4, 0x31, 0xda, 0xbc, 0x4e, 0xb8
647 }
648};
649
Brian Murray0f6af732016-05-19 15:59:23 -0700650/* 3DES 3 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700651static const unsigned char des3_3key_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700652 0x8a, 0xa8, 0x3b, 0xf8, 0xcb, 0xda, 0x10, 0x62,
653 0x0b, 0xc1, 0xbf, 0x19, 0xfb, 0xb6, 0xcd, 0x58,
654 0xbc, 0x31, 0x3d, 0x4a, 0x37, 0x1c, 0xa8, 0xb5
Brian Murray0f6af732016-05-19 15:59:23 -0700655};
656static const unsigned char des3_3key_subkeys[2][8] = {
657 {
658 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f
659 },
660 {
661 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5
662 }
663};
Simon Butcher69283e52016-10-06 12:49:58 +0100664static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700665 {
666 0xb7, 0xa6, 0x88, 0xe1, 0x22, 0xff, 0xaf, 0x95
667 },
668 {
669 0x8e, 0x8f, 0x29, 0x31, 0x36, 0x28, 0x37, 0x97
670 },
671 {
672 0x74, 0x3d, 0xdb, 0xe0, 0xce, 0x2d, 0xc2, 0xed
673 },
674 {
675 0x33, 0xe6, 0xb1, 0x09, 0x24, 0x00, 0xea, 0xe5
676 }
677};
678
Brian Murray0f6af732016-05-19 15:59:23 -0700679#endif /* MBEDTLS_DES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700680
Simon Butcher69283e52016-10-06 12:49:58 +0100681#if defined(MBEDTLS_AES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700682/* AES AES-CMAC-PRF-128 Test Data */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000683static const unsigned char PRFK[] = {
684 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
685 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
686 0xed, 0xcb
687};
688
689/* Sizes in bytes */
690static const size_t PRFKlen[NB_PRF_TESTS] = {
691 18,
692 16,
693 10
694};
695
696/* PRF M */
697static const unsigned char PRFM[] = {
698 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
699 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000700 0x10, 0x11, 0x12, 0x13
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000701};
702
703static const unsigned char PRFT[NB_PRF_TESTS][16] = {
704 {
705 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
706 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
707 },
708 {
709 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
710 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
711 },
712 {
713 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
714 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
715 }
716};
Brian Murray0f6af732016-05-19 15:59:23 -0700717#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000718
Simon Butcher327398a2016-10-05 14:09:11 +0100719static int cmac_test_subkeys( int verbose,
720 const char* testname,
721 const unsigned char* key,
722 int keybits,
723 const unsigned char* subkeys,
724 mbedtls_cipher_type_t cipher_type,
725 int block_size,
726 int num_tests )
727{
728 int i, ret;
729 mbedtls_cipher_context_t ctx;
730 const mbedtls_cipher_info_t *cipher_info;
Simon Butcher69283e52016-10-06 12:49:58 +0100731 unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
732 unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
Simon Butcher327398a2016-10-05 14:09:11 +0100733
734 cipher_info = mbedtls_cipher_info_from_type( cipher_type );
735 if( cipher_info == NULL )
736 {
737 /* Failing at this point must be due to a build issue */
Simon Butcher69283e52016-10-06 12:49:58 +0100738 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
Simon Butcher327398a2016-10-05 14:09:11 +0100739 }
740
741 for( i = 0; i < num_tests; i++ )
742 {
743 if( verbose != 0 )
Simon Butcher69283e52016-10-06 12:49:58 +0100744 mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 );
Simon Butcher327398a2016-10-05 14:09:11 +0100745
Janos Follathd4443582016-10-12 10:00:42 +0100746 mbedtls_cipher_init( &ctx );
747
Simon Butcher327398a2016-10-05 14:09:11 +0100748 if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
749 {
750 if( verbose != 0 )
751 mbedtls_printf( "test execution failed\n" );
752
Janos Follathd4443582016-10-12 10:00:42 +0100753 goto cleanup;
Simon Butcher327398a2016-10-05 14:09:11 +0100754 }
755
756 if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits,
757 MBEDTLS_ENCRYPT ) ) != 0 )
758 {
759 if( verbose != 0 )
760 mbedtls_printf( "test execution failed\n" );
761
Janos Follathd4443582016-10-12 10:00:42 +0100762 goto cleanup;
Simon Butcher327398a2016-10-05 14:09:11 +0100763 }
764
765 ret = cmac_generate_subkeys( &ctx, K1, K2 );
766 if( ret != 0 )
767 {
768 if( verbose != 0 )
769 mbedtls_printf( "failed\n" );
Janos Follathd4443582016-10-12 10:00:42 +0100770
771 goto cleanup;
Simon Butcher327398a2016-10-05 14:09:11 +0100772 }
773
Simon Butcher420be4e2016-10-07 12:55:43 +0100774 if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 ||
775 ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100776 {
777 if( verbose != 0 )
778 mbedtls_printf( "failed\n" );
Janos Follathd4443582016-10-12 10:00:42 +0100779
780 goto cleanup;
Simon Butcher327398a2016-10-05 14:09:11 +0100781 }
782
783 if( verbose != 0 )
784 mbedtls_printf( "passed\n" );
Janos Follathd4443582016-10-12 10:00:42 +0100785
786 mbedtls_cipher_free( &ctx );
Simon Butcher327398a2016-10-05 14:09:11 +0100787 }
788
Janos Follathd4443582016-10-12 10:00:42 +0100789 goto exit;
790
791cleanup:
Simon Butcher69283e52016-10-06 12:49:58 +0100792 mbedtls_cipher_free( &ctx );
793
Janos Follathd4443582016-10-12 10:00:42 +0100794exit:
Simon Butcher327398a2016-10-05 14:09:11 +0100795 return( ret );
796}
797
Simon Butcher69283e52016-10-06 12:49:58 +0100798static int cmac_test_wth_cipher( int verbose,
799 const char* testname,
800 const unsigned char* key,
801 int keybits,
802 const unsigned char* messages,
803 const unsigned int message_lengths[4],
804 const unsigned char* expected_result,
805 mbedtls_cipher_type_t cipher_type,
806 int block_size,
807 int num_tests )
Brian Murray00dc5f02016-05-19 14:23:50 -0700808{
Simon Butcher327398a2016-10-05 14:09:11 +0100809 const mbedtls_cipher_info_t *cipher_info;
Brian Murray00dc5f02016-05-19 14:23:50 -0700810 int i, ret;
Simon Butcher69283e52016-10-06 12:49:58 +0100811 unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX];
Brian Murray57863ad2016-05-19 16:38:36 -0700812
Simon Butcher327398a2016-10-05 14:09:11 +0100813 cipher_info = mbedtls_cipher_info_from_type( cipher_type );
814 if( cipher_info == NULL )
Brian Murray00dc5f02016-05-19 14:23:50 -0700815 {
Simon Butcher327398a2016-10-05 14:09:11 +0100816 /* Failing at this point must be due to a build issue */
817 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
Brian Murray00dc5f02016-05-19 14:23:50 -0700818 goto exit;
819 }
820
821 for( i = 0; i < num_tests; i++ )
822 {
823 if( verbose != 0 )
Andres AGa592dcc2016-10-06 15:23:39 +0100824 mbedtls_printf( " %s CMAC #%u: ", testname, i + 1 );
Brian Murray00dc5f02016-05-19 14:23:50 -0700825
Simon Butcher327398a2016-10-05 14:09:11 +0100826 if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages,
827 message_lengths[i], output ) ) != 0 )
Brian Murray00dc5f02016-05-19 14:23:50 -0700828 {
829 if( verbose != 0 )
830 mbedtls_printf( "failed\n" );
831 goto exit;
832 }
Brian Murray9ce2e092016-05-24 22:46:43 -0700833
Simon Butcher327398a2016-10-05 14:09:11 +0100834 if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 )
Brian Murray00dc5f02016-05-19 14:23:50 -0700835 {
836 if( verbose != 0 )
837 mbedtls_printf( "failed\n" );
838 goto exit;
839 }
840
Brian Murray9ce2e092016-05-24 22:46:43 -0700841 if( verbose != 0 )
842 mbedtls_printf( "passed\n" );
Brian Murray00dc5f02016-05-19 14:23:50 -0700843 }
Simon Butcher327398a2016-10-05 14:09:11 +0100844
Simon Butcher69283e52016-10-06 12:49:58 +0100845exit:
Simon Butcher327398a2016-10-05 14:09:11 +0100846 return( ret );
Brian Murray00dc5f02016-05-19 14:23:50 -0700847}
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000848
Simon Butcher69283e52016-10-06 12:49:58 +0100849#if defined(MBEDTLS_AES_C)
850static int test_aes128_cmac_prf( int verbose )
Brian Murray6a3c0d22016-05-20 18:25:43 -0700851{
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000852 int i;
853 int ret;
Simon Butcher69283e52016-10-06 12:49:58 +0100854 unsigned char output[MBEDTLS_AES_BLOCK_SIZE];
Simon Butcher327398a2016-10-05 14:09:11 +0100855
Brian Murrayb0c3c432016-05-18 14:29:51 -0700856 for( i = 0; i < NB_PRF_TESTS; i++ )
857 {
Brian Murray0f6af732016-05-19 15:59:23 -0700858 mbedtls_printf( " AES CMAC 128 PRF #%u: ", i );
Simon Butcher327398a2016-10-05 14:09:11 +0100859 ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700860 if( ret != 0 ||
Simon Butcher69283e52016-10-06 12:49:58 +0100861 memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700862 {
Simon Butcher327398a2016-10-05 14:09:11 +0100863
Brian Murrayb0c3c432016-05-18 14:29:51 -0700864 if( verbose != 0 )
865 mbedtls_printf( "failed\n" );
866
Brian Murray0f6af732016-05-19 15:59:23 -0700867 return( ret );
Simon Butcher69283e52016-10-06 12:49:58 +0100868 }
869 else if( verbose != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700870 {
871 mbedtls_printf( "passed\n" );
872 }
873 }
Brian Murray0f6af732016-05-19 15:59:23 -0700874 return( ret );
875}
876#endif /* MBEDTLS_AES_C */
877
878int mbedtls_cmac_self_test( int verbose )
879{
880 int ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100881
Simon Butcher69283e52016-10-06 12:49:58 +0100882#if defined(MBEDTLS_AES_C)
Simon Butcher327398a2016-10-05 14:09:11 +0100883 /* AES-128 */
884 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100885 "AES 128",
886 aes_128_key,
887 128,
888 (const unsigned char*)aes_128_subkeys,
889 MBEDTLS_CIPHER_AES_128_ECB,
890 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100891 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100892 {
893 return( ret );
894 }
895
Brian Murrayae1cb122016-05-23 15:01:59 -0700896 if( ( ret = cmac_test_wth_cipher( verbose,
897 "AES 128",
898 aes_128_key,
899 128,
900 test_message,
901 aes_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100902 (const unsigned char*)aes_128_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100903 MBEDTLS_CIPHER_AES_128_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100904 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100905 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100906 {
907 return( ret );
908 }
909
910 /* AES-192 */
911 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100912 "AES 192",
913 aes_192_key,
914 192,
915 (const unsigned char*)aes_192_subkeys,
916 MBEDTLS_CIPHER_AES_192_ECB,
917 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100918 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -0700919 {
920 return( ret );
921 }
Brian Murray0f6af732016-05-19 15:59:23 -0700922
Brian Murrayae1cb122016-05-23 15:01:59 -0700923 if( ( ret = cmac_test_wth_cipher( verbose,
924 "AES 192",
925 aes_192_key,
926 192,
927 test_message,
928 aes_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100929 (const unsigned char*)aes_192_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100930 MBEDTLS_CIPHER_AES_192_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100931 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100932 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100933 {
Simon Butcher327398a2016-10-05 14:09:11 +0100934 return( ret );
935 }
936
937 /* AES-256 */
938 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100939 "AES 256",
940 aes_256_key,
941 256,
942 (const unsigned char*)aes_256_subkeys,
943 MBEDTLS_CIPHER_AES_256_ECB,
944 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100945 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -0700946 {
947 return( ret );
948 }
Brian Murray0f6af732016-05-19 15:59:23 -0700949
Simon Butcher69283e52016-10-06 12:49:58 +0100950 if( ( ret = cmac_test_wth_cipher ( verbose,
Brian Murrayae1cb122016-05-23 15:01:59 -0700951 "AES 256",
952 aes_256_key,
953 256,
954 test_message,
955 aes_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100956 (const unsigned char*)aes_256_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100957 MBEDTLS_CIPHER_AES_256_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100958 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100959 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -0700960 {
961 return( ret );
962 }
Brian Murray0f6af732016-05-19 15:59:23 -0700963#endif /* MBEDTLS_AES_C */
964
Simon Butcher69283e52016-10-06 12:49:58 +0100965#if defined(MBEDTLS_DES_C)
Simon Butcher327398a2016-10-05 14:09:11 +0100966 /* 3DES 2 key */
967 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100968 "3DES 2 key",
969 des3_2key_key,
970 192,
971 (const unsigned char*)des3_2key_subkeys,
972 MBEDTLS_CIPHER_DES_EDE3_ECB,
973 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100974 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100975 {
976 return( ret );
977 }
978
Brian Murrayae1cb122016-05-23 15:01:59 -0700979 if( ( ret = cmac_test_wth_cipher( verbose,
980 "3DES 2 key",
981 des3_2key_key,
982 192,
983 test_message,
984 des3_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100985 (const unsigned char*)des3_2key_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100986 MBEDTLS_CIPHER_DES_EDE3_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100987 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100988 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -0700989 {
990 return( ret );
991 }
Brian Murray0f6af732016-05-19 15:59:23 -0700992
Simon Butcher327398a2016-10-05 14:09:11 +0100993 /* 3DES 3 key */
994 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100995 "3DES 3 key",
996 des3_3key_key,
997 192,
998 (const unsigned char*)des3_3key_subkeys,
999 MBEDTLS_CIPHER_DES_EDE3_ECB,
1000 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +01001001 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +01001002 {
1003 return( ret );
1004 }
1005
Brian Murrayae1cb122016-05-23 15:01:59 -07001006 if( ( ret = cmac_test_wth_cipher( verbose,
1007 "3DES 3 key",
1008 des3_3key_key,
1009 192,
1010 test_message,
1011 des3_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +01001012 (const unsigned char*)des3_3key_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +01001013 MBEDTLS_CIPHER_DES_EDE3_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +01001014 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +01001015 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -07001016 {
1017 return( ret );
1018 }
Brian Murray0f6af732016-05-19 15:59:23 -07001019#endif /* MBEDTLS_DES_C */
1020
Simon Butcher69283e52016-10-06 12:49:58 +01001021#if defined(MBEDTLS_AES_C)
Simon Butcher420be4e2016-10-07 12:55:43 +01001022 if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -07001023 return( ret );
Brian Murray0f6af732016-05-19 15:59:23 -07001024#endif /* MBEDTLS_AES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -07001025
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001026 if( verbose != 0 )
1027 mbedtls_printf( "\n" );
Brian Murray0f6af732016-05-19 15:59:23 -07001028
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001029 return( 0 );
1030}
1031
Brian Murray0f6af732016-05-19 15:59:23 -07001032#endif /* MBEDTLS_SELF_TEST */
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001033
1034#endif /* MBEDTLS_CMAC_C */