blob: 7fc513a452969410182bece1c36ba01bae026485 [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 Butcher327398a2016-10-05 14:09:11 +010062#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || \
63 defined(MBEDTLS_DES_C) )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000064#include <stdio.h>
Brian Murray8b4111c2016-09-13 15:58:46 -070065#define mbedtls_printf printf
Simon Butcher69283e52016-10-06 12:49:58 +010066#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C || MBEDTLS_DES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +000067#endif /* MBEDTLS_PLATFORM_C */
Brian Murray8b4111c2016-09-13 15:58:46 -070068
Robert Cragie3d23b1d2015-12-15 07:38:11 +000069/* Implementation that should never be optimized out by the compiler */
70static void mbedtls_zeroize( void *v, size_t n ) {
Simon Butcher327398a2016-10-05 14:09:11 +010071 volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
Robert Cragie3d23b1d2015-12-15 07:38:11 +000072}
73
74/*
Brian Murrayb0c3c432016-05-18 14:29:51 -070075 * Multiplication by u in the Galois field of GF(2^n)
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000076 *
Brian Murray72b69e32016-09-13 14:21:01 -070077 * As explained in NIST SP 800-38B, this can be computed:
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000078 *
Simon Butcher327398a2016-10-05 14:09:11 +010079 * If MSB(p) = 0, then p = (p << 1)
80 * If MSB(p) = 1, then p = (p << 1) ^ R_n
81 * with R_64 = 0x1B and R_128 = 0x87
82 *
83 * Input and output MUST NOT point to the same buffer
Simon Butcher69283e52016-10-06 12:49:58 +010084 * Block size must be 8 byes or 16 bytes - the block sizes for DES and AES.
Robert Cragie3d23b1d2015-12-15 07:38:11 +000085 */
Brian Murrayb0c3c432016-05-18 14:29:51 -070086static int cmac_multiply_by_u( unsigned char *output,
87 const unsigned char *input,
Brian Murray53e23b62016-09-13 14:00:15 -070088 size_t blocksize )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000089{
Brian Murrayb0c3c432016-05-18 14:29:51 -070090 const unsigned char R_128 = 0x87;
91 const unsigned char R_64 = 0x1B;
92 unsigned char R_n, mask;
93 unsigned char overflow = 0x00;
Simon Butcher327398a2016-10-05 14:09:11 +010094 int i;
Brian Murrayb0c3c432016-05-18 14:29:51 -070095
Simon Butcher69283e52016-10-06 12:49:58 +010096 if( blocksize == MBEDTLS_AES_BLOCK_SIZE )
Brian Murray6a3c0d22016-05-20 18:25:43 -070097 {
Brian Murrayb0c3c432016-05-18 14:29:51 -070098 R_n = R_128;
Simon Butcher327398a2016-10-05 14:09:11 +010099 }
Simon Butcher69283e52016-10-06 12:49:58 +0100100 else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE )
Brian Murray6a3c0d22016-05-20 18:25:43 -0700101 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700102 R_n = R_64;
Simon Butcher327398a2016-10-05 14:09:11 +0100103 }
104 else
Brian Murray6a3c0d22016-05-20 18:25:43 -0700105 {
Simon Butcher327398a2016-10-05 14:09:11 +0100106 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700107 }
108
Simon Butcher327398a2016-10-05 14:09:11 +0100109 for( i = blocksize - 1; i >= 0; i-- )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000110 {
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000111 output[i] = input[i] << 1 | overflow;
112 overflow = input[i] >> 7;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000113 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000114
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +0000115 /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
116 * using bit operations to avoid branches */
Simon Butcher327398a2016-10-05 14:09:11 +0100117
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +0000118 /* MSVC has a warning about unary minus on unsigned, but this is
119 * well-defined and precisely what we want to do here */
120#if defined(_MSC_VER)
121#pragma warning( push )
122#pragma warning( disable : 4146 )
123#endif
124 mask = - ( input[0] >> 7 );
125#if defined(_MSC_VER)
126#pragma warning( pop )
127#endif
128
Simon Butcher327398a2016-10-05 14:09:11 +0100129 output[ blocksize - 1 ] ^= R_n & mask;
130
Brian Murrayb439d452016-05-19 16:02:42 -0700131 return( 0 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000132}
133
134/*
135 * Generate subkeys
Simon Butcher327398a2016-10-05 14:09:11 +0100136 *
137 * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000138 */
Simon Butcher327398a2016-10-05 14:09:11 +0100139static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx,
140 unsigned char* K1, unsigned char* K2 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000141{
Brian Murray57863ad2016-05-19 16:38:36 -0700142 int ret;
Simon Butcher69283e52016-10-06 12:49:58 +0100143 unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700144 size_t olen, block_size;
145
Simon Butcher327398a2016-10-05 14:09:11 +0100146 mbedtls_zeroize( L, sizeof( L ) );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700147
Simon Butcher327398a2016-10-05 14:09:11 +0100148 block_size = ctx->cipher_info->block_size;
149
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000150 /* Calculate Ek(0) */
Simon Butcher327398a2016-10-05 14:09:11 +0100151 if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700152 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000153
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000154 /*
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000155 * Generate K1 and K2
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000156 */
Simon Butcher327398a2016-10-05 14:09:11 +0100157 if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700158 goto exit;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000159
Simon Butcher327398a2016-10-05 14:09:11 +0100160 if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 )
161 goto exit;
162
163exit:
164 mbedtls_zeroize( L, sizeof( L ) );
165
166 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000167}
168
Simon Butcher69283e52016-10-06 12:49:58 +0100169static void cmac_xor_block( unsigned char *output, const unsigned char *input1,
170 const unsigned char *input2,
171 const size_t block_size )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000172{
Simon Butcher327398a2016-10-05 14:09:11 +0100173 size_t index;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000174
Simon Butcher327398a2016-10-05 14:09:11 +0100175 for( index = 0; index < block_size; index++ )
176 output[ index ] = input1[ index ] ^ input2[ index ];
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000177}
178
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000179/*
180 * Create padded last block from (partial) last block.
181 *
182 * We can't use the padding option from the cipher layer, as it only works for
183 * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
184 */
Simon Butcher69283e52016-10-06 12:49:58 +0100185static void cmac_pad( unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX],
Brian Murray53e23b62016-09-13 14:00:15 -0700186 size_t padded_block_len,
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000187 const unsigned char *last_block,
Brian Murrayb0c3c432016-05-18 14:29:51 -0700188 size_t last_block_len )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000189{
190 size_t j;
191
Brian Murrayb0c3c432016-05-18 14:29:51 -0700192 for( j = 0; j < padded_block_len; j++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000193 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700194 if( j < last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000195 padded_block[j] = last_block[j];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700196 else if( j == last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000197 padded_block[j] = 0x80;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000198 else
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000199 padded_block[j] = 0x00;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000200 }
201}
202
Simon Butcher327398a2016-10-05 14:09:11 +0100203int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx,
Simon Butcher94ffde72016-10-05 15:33:53 +0100204 const unsigned char *key, size_t keybits )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000205{
Simon Butcher327398a2016-10-05 14:09:11 +0100206 mbedtls_cipher_type_t type;
207 mbedtls_cmac_context_t *cmac_ctx;
Simon Butcher327398a2016-10-05 14:09:11 +0100208 int retval;
209
210 if( ctx == NULL || ctx->cipher_info == NULL || key == NULL )
211 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
212
Simon Butcher94ffde72016-10-05 15:33:53 +0100213 if( ( retval = mbedtls_cipher_setkey( ctx, key, keybits,
Simon Butcher327398a2016-10-05 14:09:11 +0100214 MBEDTLS_ENCRYPT ) ) != 0 )
215 return( retval );
216
Simon Butcher327398a2016-10-05 14:09:11 +0100217 type = ctx->cipher_info->type;
218
219 switch( type )
220 {
221 case MBEDTLS_CIPHER_AES_128_ECB:
222 case MBEDTLS_CIPHER_AES_192_ECB:
223 case MBEDTLS_CIPHER_AES_256_ECB:
224 case MBEDTLS_CIPHER_DES_EDE3_ECB:
225 break;
226 default:
227 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
228 }
229
230 /* Allocated and initialise in the cipher context memory for the CMAC
231 * context */
232 cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) );
233 if( cmac_ctx == NULL )
234 return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
235
236 ctx->cmac_ctx = cmac_ctx;
237
238 mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) );
239 cmac_ctx->padding_flag = 1;
240
241 return 0;
242}
243
244int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx,
245 const unsigned char *input, size_t ilen )
246{
247 mbedtls_cmac_context_t* cmac_ctx;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700248 unsigned char *state;
Simon Butcher327398a2016-10-05 14:09:11 +0100249 int n, j, ret = 0;
250 size_t olen, block_size;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700251
Simon Butcher327398a2016-10-05 14:09:11 +0100252 if( ctx == NULL || ctx->cipher_info == NULL || input == NULL ||
253 ctx->cmac_ctx == NULL )
254 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700255
Simon Butcher327398a2016-10-05 14:09:11 +0100256 cmac_ctx = ctx->cmac_ctx;
257 block_size = ctx->cipher_info->block_size;
258 state = ctx->cmac_ctx->state;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000259
Simon Butcher327398a2016-10-05 14:09:11 +0100260 /* Is their data still to process from the last call, that's equal to
261 * or greater than a block? */
262 if( cmac_ctx->unprocessed_len > 0 &&
263 ilen + cmac_ctx->unprocessed_len > block_size )
Brian Murray57863ad2016-05-19 16:38:36 -0700264 {
Simon Butcher327398a2016-10-05 14:09:11 +0100265 memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
266 input,
267 block_size - cmac_ctx->unprocessed_len );
268
269 cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size );
270
271 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
272 &olen ) ) != 0 )
273 {
274 goto exit;
275 }
276
277 ilen -= block_size;
278 input += cmac_ctx->unprocessed_len;
279
280 cmac_ctx->unprocessed_len = 0;
Brian Murray57863ad2016-05-19 16:38:36 -0700281 }
282
Simon Butcher327398a2016-10-05 14:09:11 +0100283 /* n is the number of blocks including any final partial block */
284 n = ( ilen + block_size - 1 ) / block_size;
285
286 /* Iterate across the input data in block sized chunks */
287 for( j = 0; j < n - 1; j++ )
Brian Murray57863ad2016-05-19 16:38:36 -0700288 {
Simon Butcher327398a2016-10-05 14:09:11 +0100289 cmac_xor_block( state, input, state, block_size );
290
291 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
292 &olen ) ) != 0 )
293 goto exit;
294
295 ilen -= block_size;
296 input += block_size;
297
298 cmac_ctx->padding_flag = 0;
Brian Murray57863ad2016-05-19 16:38:36 -0700299 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000300
Simon Butcher327398a2016-10-05 14:09:11 +0100301 /* If there is data left over that wasn't aligned to a block */
302 if( ilen > 0 )
303 {
304 memcpy( &cmac_ctx->unprocessed_block, input, ilen );
305 cmac_ctx->unprocessed_len = ilen;
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000306
Simon Butcher327398a2016-10-05 14:09:11 +0100307 if( ilen % block_size > 0 )
308 cmac_ctx->padding_flag = 1;
309 else
310 cmac_ctx->padding_flag = 0;
311 }
312
313exit:
314 return( ret );
315}
316
317int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx,
318 unsigned char *output )
319{
320 mbedtls_cmac_context_t* cmac_ctx;
Simon Butcher69283e52016-10-06 12:49:58 +0100321 unsigned char *state, *last_block;
322 unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
323 unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
324 unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX];
Simon Butcher327398a2016-10-05 14:09:11 +0100325 int ret;
326 size_t olen, block_size;
327
328 if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ||
329 output == NULL )
330 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
331
332 cmac_ctx = ctx->cmac_ctx;
333 block_size = ctx->cipher_info->block_size;
334 state = cmac_ctx->state;
335
Simon Butcher69283e52016-10-06 12:49:58 +0100336 mbedtls_zeroize( K1, sizeof( K1 ) );
337 mbedtls_zeroize( K2, sizeof( K2 ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100338 cmac_generate_subkeys( ctx, K1, K2 );
339
Simon Butcher69283e52016-10-06 12:49:58 +0100340 last_block = cmac_ctx->unprocessed_block;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000341
342 /* Calculate last block */
Simon Butcher327398a2016-10-05 14:09:11 +0100343 if( cmac_ctx->padding_flag )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000344 {
Simon Butcher327398a2016-10-05 14:09:11 +0100345 cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len );
346 cmac_xor_block( M_last, M_last, K2, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000347 }
348 else
349 {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000350 /* Last block is complete block */
Simon Butcher327398a2016-10-05 14:09:11 +0100351 cmac_xor_block( M_last, last_block, K1, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000352 }
353
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000354
Simon Butcher327398a2016-10-05 14:09:11 +0100355 cmac_xor_block( state, M_last, state, block_size );
356 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
357 &olen ) ) != 0 )
358 {
359 goto exit;
360 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000361
Simon Butcher327398a2016-10-05 14:09:11 +0100362 memcpy( output, state, block_size );
363
364exit:
365 /* Wipe the generated keys on the stack, and any other transients to avoid
366 * side channel leakage */
Simon Butcher69283e52016-10-06 12:49:58 +0100367 mbedtls_zeroize( K1, sizeof( K1 ) );
368 mbedtls_zeroize( K2, sizeof( K2 ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100369
Simon Butcher69283e52016-10-06 12:49:58 +0100370 cmac_ctx->padding_flag = 1;
Simon Butcher327398a2016-10-05 14:09:11 +0100371 cmac_ctx->unprocessed_len = 0;
372 mbedtls_zeroize( cmac_ctx->unprocessed_block,
Simon Butcher69283e52016-10-06 12:49:58 +0100373 sizeof( cmac_ctx->unprocessed_block ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100374
Simon Butcher69283e52016-10-06 12:49:58 +0100375 mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX );
Simon Butcher327398a2016-10-05 14:09:11 +0100376 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000377}
378
Simon Butcher327398a2016-10-05 14:09:11 +0100379int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000380{
Simon Butcher327398a2016-10-05 14:09:11 +0100381 mbedtls_cmac_context_t* cmac_ctx;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000382
Simon Butcher327398a2016-10-05 14:09:11 +0100383 if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL )
384 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700385
Simon Butcher327398a2016-10-05 14:09:11 +0100386 cmac_ctx = ctx->cmac_ctx;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000387
Simon Butcher327398a2016-10-05 14:09:11 +0100388 /* Reset the internal state */
389 cmac_ctx->unprocessed_len = 0;
390 mbedtls_zeroize( cmac_ctx->unprocessed_block,
391 sizeof( cmac_ctx->unprocessed_len ) );
Simon Butcher69283e52016-10-06 12:49:58 +0100392 mbedtls_zeroize( cmac_ctx->state, MBEDTLS_CIPHER_BLKSIZE_MAX );
Simon Butcher327398a2016-10-05 14:09:11 +0100393 cmac_ctx->padding_flag = 1;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000394
Simon Butcher327398a2016-10-05 14:09:11 +0100395 return( 0 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000396}
397
Simon Butcher327398a2016-10-05 14:09:11 +0100398int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info,
399 const unsigned char *key, size_t keylen,
400 const unsigned char *input, size_t ilen,
401 unsigned char *output )
402{
403 mbedtls_cipher_context_t ctx;
404 int ret;
405
406 if( cipher_info == NULL || key == NULL || input == NULL || output == NULL )
407 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
408
409 mbedtls_cipher_init( &ctx );
410
411 if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
412 goto exit;
413
414 ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen );
Simon Butcher327398a2016-10-05 14:09:11 +0100415 if( ret != 0 )
416 goto exit;
Simon Butcher327398a2016-10-05 14:09:11 +0100417
418 ret = mbedtls_cipher_cmac_update( &ctx, input, ilen );
419 if( ret != 0 )
420 goto exit;
421
Simon Butcher69283e52016-10-06 12:49:58 +0100422 ret = mbedtls_cipher_cmac_finish( &ctx, output );
Simon Butcher327398a2016-10-05 14:09:11 +0100423
424exit:
Simon Butcher69283e52016-10-06 12:49:58 +0100425 mbedtls_cipher_free( &ctx );
426
Simon Butcher327398a2016-10-05 14:09:11 +0100427 return( ret );
428}
Simon Butcher327398a2016-10-05 14:09:11 +0100429
Simon Butcher69283e52016-10-06 12:49:58 +0100430#if defined(MBEDTLS_AES_C)
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000431/*
Simon Butcher69283e52016-10-06 12:49:58 +0100432 * Implementation of AES-CMAC-PRF-128 defined in RFC 4615
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000433 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700434int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000435 const unsigned char *input, size_t in_len,
Simon Butcher327398a2016-10-05 14:09:11 +0100436 unsigned char *output )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000437{
438 int ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100439 const mbedtls_cipher_info_t *cipher_info;
Simon Butcher69283e52016-10-06 12:49:58 +0100440 unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE];
441 unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE];
442
443 if( key == NULL || input == NULL || output == NULL )
444 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000445
Simon Butcher327398a2016-10-05 14:09:11 +0100446 cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB );
447 if( cipher_info == NULL )
448 {
449 /* Failing at this point must be due to a build issue */
450 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
451 goto exit;
452 }
Brian Murrayb0c3c432016-05-18 14:29:51 -0700453
Simon Butcher69283e52016-10-06 12:49:58 +0100454 if( key_length == MBEDTLS_AES_BLOCK_SIZE )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000455 {
456 /* Use key as is */
Simon Butcher69283e52016-10-06 12:49:58 +0100457 memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000458 }
459 else
460 {
Simon Butcher69283e52016-10-06 12:49:58 +0100461 memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE );
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000462
Simon Butcher327398a2016-10-05 14:09:11 +0100463 ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key,
464 key_length, int_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000465 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700466 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000467 }
468
Simon Butcher327398a2016-10-05 14:09:11 +0100469 ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len,
470 output );
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000471
Simon Butcher327398a2016-10-05 14:09:11 +0100472exit:
473 mbedtls_zeroize( int_key, sizeof( int_key ) );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700474
Simon Butcher327398a2016-10-05 14:09:11 +0100475 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000476}
Brian Murrayb439d452016-05-19 16:02:42 -0700477#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000478
Simon Butcher69283e52016-10-06 12:49:58 +0100479#if defined(MBEDTLS_SELF_TEST)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000480/*
Brian Murray0f6af732016-05-19 15:59:23 -0700481 * CMAC test data from SP800-38B Appendix D.1 (corrected)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000482 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
Brian Murray0f6af732016-05-19 15:59:23 -0700483 *
484 * AES-CMAC-PRF-128 test data from RFC 4615
485 * https://tools.ietf.org/html/rfc4615#page-4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000486 */
487
Brian Murray0f6af732016-05-19 15:59:23 -0700488#define NB_CMAC_TESTS_PER_KEY 4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000489#define NB_PRF_TESTS 3
Simon Butcher327398a2016-10-05 14:09:11 +0100490
Brian Murray0f6af732016-05-19 15:59:23 -0700491#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
492/* All CMAC test inputs are truncated from the same 64 byte buffer. */
493static const unsigned char test_message[] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000494 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
495 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
496 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
497 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
498 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
499 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
500 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
501 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
502};
Simon Butcher69283e52016-10-06 12:49:58 +0100503#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */
Brian Murray0cf14c12016-05-23 12:49:50 -0700504
Simon Butcher69283e52016-10-06 12:49:58 +0100505#if defined(MBEDTLS_AES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700506/* Truncation point of message for AES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700507static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700508 0,
509 16,
510 40,
511 64
512};
513
514/* AES 128 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700515static const unsigned char aes_128_key[16] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700516 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
517 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
518};
Simon Butcher69283e52016-10-06 12:49:58 +0100519static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700520 {
521 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
522 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
523 },
524 {
525 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
526 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
527 }
528};
Simon Butcher69283e52016-10-06 12:49:58 +0100529static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000530 {
531 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
532 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
533 },
534 {
535 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
536 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
537 },
538 {
539 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
540 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
541 },
542 {
543 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
544 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
545 }
546};
547
Brian Murray0f6af732016-05-19 15:59:23 -0700548/* AES 192 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700549static const unsigned char aes_192_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700550 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
551 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
552 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000553};
Simon Butcher69283e52016-10-06 12:49:58 +0100554static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700555 {
Brian Murray0f6af732016-05-19 15:59:23 -0700556 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
557 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
Brian Murrayb0c3c432016-05-18 14:29:51 -0700558 },
559 {
Brian Murray0f6af732016-05-19 15:59:23 -0700560 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
561 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
Brian Murrayb0c3c432016-05-18 14:29:51 -0700562 }
563};
Simon Butcher69283e52016-10-06 12:49:58 +0100564static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700565 {
566 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
567 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
568 },
569 {
570 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
571 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
572 },
573 {
574 0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad,
575 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e
576 },
577 {
578 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
579 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
580 }
581};
582
Brian Murray0f6af732016-05-19 15:59:23 -0700583/* AES 256 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700584static const unsigned char aes_256_key[32] = {
Brian Murray87e40402016-05-19 19:05:57 -0700585 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
586 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
587 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
588 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
Brian Murray0f6af732016-05-19 15:59:23 -0700589};
Simon Butcher69283e52016-10-06 12:49:58 +0100590static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700591 {
592 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
593 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
594 },
595 {
596 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
597 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
598 }
599};
Simon Butcher69283e52016-10-06 12:49:58 +0100600static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700601 {
602 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
603 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
604 },
605 {
606 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
607 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
608 },
609 {
610 0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2,
611 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6
612 },
613 {
614 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
615 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
616 }
617};
618#endif /* MBEDTLS_AES_C */
619
Simon Butcher69283e52016-10-06 12:49:58 +0100620#if defined(MBEDTLS_DES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700621/* Truncation point of message for 3DES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700622static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700623 0,
624 8,
625 20,
626 32
627};
628
629/* 3DES 2 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700630static const unsigned char des3_2key_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700631 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5,
632 0x8a, 0x3d, 0x10, 0xba, 0x80, 0x57, 0x0d, 0x38,
633 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5
Brian Murray0f6af732016-05-19 15:59:23 -0700634};
635static const unsigned char des3_2key_subkeys[2][8] = {
636 {
637 0x8e, 0xcf, 0x37, 0x3e, 0xd7, 0x1a, 0xfa, 0xef
638 },
639 {
640 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5
641 }
642};
Simon Butcher69283e52016-10-06 12:49:58 +0100643static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700644 {
645 0xbd, 0x2e, 0xbf, 0x9a, 0x3b, 0xa0, 0x03, 0x61
646 },
647 {
648 0x4f, 0xf2, 0xab, 0x81, 0x3c, 0x53, 0xce, 0x83
649 },
650 {
651 0x62, 0xdd, 0x1b, 0x47, 0x19, 0x02, 0xbd, 0x4e
652 },
653 {
654 0x31, 0xb1, 0xe4, 0x31, 0xda, 0xbc, 0x4e, 0xb8
655 }
656};
657
Brian Murray0f6af732016-05-19 15:59:23 -0700658/* 3DES 3 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700659static const unsigned char des3_3key_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700660 0x8a, 0xa8, 0x3b, 0xf8, 0xcb, 0xda, 0x10, 0x62,
661 0x0b, 0xc1, 0xbf, 0x19, 0xfb, 0xb6, 0xcd, 0x58,
662 0xbc, 0x31, 0x3d, 0x4a, 0x37, 0x1c, 0xa8, 0xb5
Brian Murray0f6af732016-05-19 15:59:23 -0700663};
664static const unsigned char des3_3key_subkeys[2][8] = {
665 {
666 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f
667 },
668 {
669 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5
670 }
671};
Simon Butcher69283e52016-10-06 12:49:58 +0100672static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700673 {
674 0xb7, 0xa6, 0x88, 0xe1, 0x22, 0xff, 0xaf, 0x95
675 },
676 {
677 0x8e, 0x8f, 0x29, 0x31, 0x36, 0x28, 0x37, 0x97
678 },
679 {
680 0x74, 0x3d, 0xdb, 0xe0, 0xce, 0x2d, 0xc2, 0xed
681 },
682 {
683 0x33, 0xe6, 0xb1, 0x09, 0x24, 0x00, 0xea, 0xe5
684 }
685};
686
Brian Murray0f6af732016-05-19 15:59:23 -0700687#endif /* MBEDTLS_DES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700688
Simon Butcher69283e52016-10-06 12:49:58 +0100689#if defined(MBEDTLS_AES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700690/* AES AES-CMAC-PRF-128 Test Data */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000691static const unsigned char PRFK[] = {
692 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
693 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
694 0xed, 0xcb
695};
696
697/* Sizes in bytes */
698static const size_t PRFKlen[NB_PRF_TESTS] = {
699 18,
700 16,
701 10
702};
703
704/* PRF M */
705static const unsigned char PRFM[] = {
706 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
707 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000708 0x10, 0x11, 0x12, 0x13
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000709};
710
711static const unsigned char PRFT[NB_PRF_TESTS][16] = {
712 {
713 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
714 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
715 },
716 {
717 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
718 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
719 },
720 {
721 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
722 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
723 }
724};
Brian Murray0f6af732016-05-19 15:59:23 -0700725#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000726
Simon Butcher327398a2016-10-05 14:09:11 +0100727static int cmac_test_subkeys( int verbose,
728 const char* testname,
729 const unsigned char* key,
730 int keybits,
731 const unsigned char* subkeys,
732 mbedtls_cipher_type_t cipher_type,
733 int block_size,
734 int num_tests )
735{
736 int i, ret;
737 mbedtls_cipher_context_t ctx;
738 const mbedtls_cipher_info_t *cipher_info;
Simon Butcher69283e52016-10-06 12:49:58 +0100739 unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
740 unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
Simon Butcher327398a2016-10-05 14:09:11 +0100741
742 cipher_info = mbedtls_cipher_info_from_type( cipher_type );
743 if( cipher_info == NULL )
744 {
745 /* Failing at this point must be due to a build issue */
Simon Butcher69283e52016-10-06 12:49:58 +0100746 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
Simon Butcher327398a2016-10-05 14:09:11 +0100747 }
748
Simon Butcher69283e52016-10-06 12:49:58 +0100749 mbedtls_cipher_init( &ctx );
750
Simon Butcher327398a2016-10-05 14:09:11 +0100751 for( i = 0; i < num_tests; i++ )
752 {
753 if( verbose != 0 )
Simon Butcher69283e52016-10-06 12:49:58 +0100754 mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 );
Simon Butcher327398a2016-10-05 14:09:11 +0100755
756 if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
757 {
758 if( verbose != 0 )
759 mbedtls_printf( "test execution failed\n" );
760
761 goto exit;
762 }
763
764 if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits,
765 MBEDTLS_ENCRYPT ) ) != 0 )
766 {
767 if( verbose != 0 )
768 mbedtls_printf( "test execution failed\n" );
769
770 goto exit;
771 }
772
773 ret = cmac_generate_subkeys( &ctx, K1, K2 );
774 if( ret != 0 )
775 {
776 if( verbose != 0 )
777 mbedtls_printf( "failed\n" );
778 goto exit;
779 }
780
781 if( ( ret = memcmp( K1, subkeys, block_size ) != 0 ) ||
782 ( ret = memcmp( K2, &subkeys[block_size], block_size ) != 0 ) )
783 {
784 if( verbose != 0 )
785 mbedtls_printf( "failed\n" );
786 goto exit;
787 }
788
789 if( verbose != 0 )
790 mbedtls_printf( "passed\n" );
791 }
792
793exit:
Simon Butcher69283e52016-10-06 12:49:58 +0100794 mbedtls_cipher_free( &ctx );
795
Simon Butcher327398a2016-10-05 14:09:11 +0100796 return( ret );
797}
798
Simon Butcher69283e52016-10-06 12:49:58 +0100799static int cmac_test_wth_cipher( int verbose,
800 const char* testname,
801 const unsigned char* key,
802 int keybits,
803 const unsigned char* messages,
804 const unsigned int message_lengths[4],
805 const unsigned char* expected_result,
806 mbedtls_cipher_type_t cipher_type,
807 int block_size,
808 int num_tests )
Brian Murray00dc5f02016-05-19 14:23:50 -0700809{
Simon Butcher327398a2016-10-05 14:09:11 +0100810 const mbedtls_cipher_info_t *cipher_info;
Brian Murray00dc5f02016-05-19 14:23:50 -0700811 int i, ret;
Simon Butcher69283e52016-10-06 12:49:58 +0100812 unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX];
Brian Murray57863ad2016-05-19 16:38:36 -0700813
Simon Butcher327398a2016-10-05 14:09:11 +0100814 cipher_info = mbedtls_cipher_info_from_type( cipher_type );
815 if( cipher_info == NULL )
Brian Murray00dc5f02016-05-19 14:23:50 -0700816 {
Simon Butcher327398a2016-10-05 14:09:11 +0100817 /* Failing at this point must be due to a build issue */
818 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
Brian Murray00dc5f02016-05-19 14:23:50 -0700819 goto exit;
820 }
821
822 for( i = 0; i < num_tests; i++ )
823 {
824 if( verbose != 0 )
825 mbedtls_printf( " %s CMAC #%u: ", testname, i +1 );
826
Simon Butcher327398a2016-10-05 14:09:11 +0100827 if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages,
828 message_lengths[i], output ) ) != 0 )
Brian Murray00dc5f02016-05-19 14:23:50 -0700829 {
830 if( verbose != 0 )
831 mbedtls_printf( "failed\n" );
832 goto exit;
833 }
Brian Murray9ce2e092016-05-24 22:46:43 -0700834
Simon Butcher327398a2016-10-05 14:09:11 +0100835 if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 )
Brian Murray00dc5f02016-05-19 14:23:50 -0700836 {
837 if( verbose != 0 )
838 mbedtls_printf( "failed\n" );
839 goto exit;
840 }
841
Brian Murray9ce2e092016-05-24 22:46:43 -0700842 if( verbose != 0 )
843 mbedtls_printf( "passed\n" );
Brian Murray00dc5f02016-05-19 14:23:50 -0700844 }
Simon Butcher327398a2016-10-05 14:09:11 +0100845
Simon Butcher69283e52016-10-06 12:49:58 +0100846exit:
Simon Butcher327398a2016-10-05 14:09:11 +0100847 return( ret );
Brian Murray00dc5f02016-05-19 14:23:50 -0700848}
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000849
Simon Butcher69283e52016-10-06 12:49:58 +0100850#if defined(MBEDTLS_AES_C)
851static int test_aes128_cmac_prf( int verbose )
Brian Murray6a3c0d22016-05-20 18:25:43 -0700852{
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000853 int i;
854 int ret;
Simon Butcher69283e52016-10-06 12:49:58 +0100855 unsigned char output[MBEDTLS_AES_BLOCK_SIZE];
Simon Butcher327398a2016-10-05 14:09:11 +0100856
Brian Murrayb0c3c432016-05-18 14:29:51 -0700857 for( i = 0; i < NB_PRF_TESTS; i++ )
858 {
Brian Murray0f6af732016-05-19 15:59:23 -0700859 mbedtls_printf( " AES CMAC 128 PRF #%u: ", i );
Simon Butcher327398a2016-10-05 14:09:11 +0100860 ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700861 if( ret != 0 ||
Simon Butcher69283e52016-10-06 12:49:58 +0100862 memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700863 {
Simon Butcher327398a2016-10-05 14:09:11 +0100864
Brian Murrayb0c3c432016-05-18 14:29:51 -0700865 if( verbose != 0 )
866 mbedtls_printf( "failed\n" );
867
Brian Murray0f6af732016-05-19 15:59:23 -0700868 return( ret );
Simon Butcher69283e52016-10-06 12:49:58 +0100869 }
870 else if( verbose != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700871 {
872 mbedtls_printf( "passed\n" );
873 }
874 }
Brian Murray0f6af732016-05-19 15:59:23 -0700875 return( ret );
876}
877#endif /* MBEDTLS_AES_C */
878
879int mbedtls_cmac_self_test( int verbose )
880{
881 int ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100882
Simon Butcher69283e52016-10-06 12:49:58 +0100883#if defined(MBEDTLS_AES_C)
Simon Butcher327398a2016-10-05 14:09:11 +0100884 /* AES-128 */
885 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100886 "AES 128",
887 aes_128_key,
888 128,
889 (const unsigned char*)aes_128_subkeys,
890 MBEDTLS_CIPHER_AES_128_ECB,
891 MBEDTLS_AES_BLOCK_SIZE,
892 NB_CMAC_TESTS_PER_KEY ) != 0 ) )
Simon Butcher327398a2016-10-05 14:09:11 +0100893 {
894 return( ret );
895 }
896
Brian Murrayae1cb122016-05-23 15:01:59 -0700897 if( ( ret = cmac_test_wth_cipher( verbose,
898 "AES 128",
899 aes_128_key,
900 128,
901 test_message,
902 aes_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100903 (const unsigned char*)aes_128_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100904 MBEDTLS_CIPHER_AES_128_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100905 MBEDTLS_AES_BLOCK_SIZE,
906 NB_CMAC_TESTS_PER_KEY ) != 0 ) )
Simon Butcher327398a2016-10-05 14:09:11 +0100907 {
908 return( ret );
909 }
910
911 /* AES-192 */
912 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100913 "AES 192",
914 aes_192_key,
915 192,
916 (const unsigned char*)aes_192_subkeys,
917 MBEDTLS_CIPHER_AES_192_ECB,
918 MBEDTLS_AES_BLOCK_SIZE,
919 NB_CMAC_TESTS_PER_KEY ) != 0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700920 {
921 return( ret );
922 }
Brian Murray0f6af732016-05-19 15:59:23 -0700923
Brian Murrayae1cb122016-05-23 15:01:59 -0700924 if( ( ret = cmac_test_wth_cipher( verbose,
925 "AES 192",
926 aes_192_key,
927 192,
928 test_message,
929 aes_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100930 (const unsigned char*)aes_192_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100931 MBEDTLS_CIPHER_AES_192_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100932 MBEDTLS_AES_BLOCK_SIZE,
933 NB_CMAC_TESTS_PER_KEY ) != 0 ) )
Simon Butcher327398a2016-10-05 14:09:11 +0100934 {
Simon Butcher327398a2016-10-05 14:09:11 +0100935 return( ret );
936 }
937
938 /* AES-256 */
939 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100940 "AES 256",
941 aes_256_key,
942 256,
943 (const unsigned char*)aes_256_subkeys,
944 MBEDTLS_CIPHER_AES_256_ECB,
945 MBEDTLS_AES_BLOCK_SIZE,
946 NB_CMAC_TESTS_PER_KEY ) != 0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700947 {
948 return( ret );
949 }
Brian Murray0f6af732016-05-19 15:59:23 -0700950
Simon Butcher69283e52016-10-06 12:49:58 +0100951 if( ( ret = cmac_test_wth_cipher ( verbose,
Brian Murrayae1cb122016-05-23 15:01:59 -0700952 "AES 256",
953 aes_256_key,
954 256,
955 test_message,
956 aes_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100957 (const unsigned char*)aes_256_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100958 MBEDTLS_CIPHER_AES_256_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100959 MBEDTLS_AES_BLOCK_SIZE,
960 NB_CMAC_TESTS_PER_KEY ) != 0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700961 {
962 return( ret );
963 }
Brian Murray0f6af732016-05-19 15:59:23 -0700964#endif /* MBEDTLS_AES_C */
965
Simon Butcher69283e52016-10-06 12:49:58 +0100966#if defined(MBEDTLS_DES_C)
Simon Butcher327398a2016-10-05 14:09:11 +0100967 /* 3DES 2 key */
968 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100969 "3DES 2 key",
970 des3_2key_key,
971 192,
972 (const unsigned char*)des3_2key_subkeys,
973 MBEDTLS_CIPHER_DES_EDE3_ECB,
974 MBEDTLS_DES3_BLOCK_SIZE,
975 NB_CMAC_TESTS_PER_KEY ) != 0 ) )
Simon Butcher327398a2016-10-05 14:09:11 +0100976 {
977 return( ret );
978 }
979
Brian Murrayae1cb122016-05-23 15:01:59 -0700980 if( ( ret = cmac_test_wth_cipher( verbose,
981 "3DES 2 key",
982 des3_2key_key,
983 192,
984 test_message,
985 des3_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100986 (const unsigned char*)des3_2key_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100987 MBEDTLS_CIPHER_DES_EDE3_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100988 MBEDTLS_DES3_BLOCK_SIZE,
989 NB_CMAC_TESTS_PER_KEY ) != 0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700990 {
991 return( ret );
992 }
Brian Murray0f6af732016-05-19 15:59:23 -0700993
Simon Butcher327398a2016-10-05 14:09:11 +0100994 /* 3DES 3 key */
995 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100996 "3DES 3 key",
997 des3_3key_key,
998 192,
999 (const unsigned char*)des3_3key_subkeys,
1000 MBEDTLS_CIPHER_DES_EDE3_ECB,
1001 MBEDTLS_DES3_BLOCK_SIZE,
1002 NB_CMAC_TESTS_PER_KEY ) != 0 ) )
Simon Butcher327398a2016-10-05 14:09:11 +01001003 {
1004 return( ret );
1005 }
1006
Brian Murrayae1cb122016-05-23 15:01:59 -07001007 if( ( ret = cmac_test_wth_cipher( verbose,
1008 "3DES 3 key",
1009 des3_3key_key,
1010 192,
1011 test_message,
1012 des3_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +01001013 (const unsigned char*)des3_3key_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +01001014 MBEDTLS_CIPHER_DES_EDE3_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +01001015 MBEDTLS_DES3_BLOCK_SIZE,
1016 NB_CMAC_TESTS_PER_KEY ) != 0 ) )
Brian Murray9044b022016-05-19 16:36:56 -07001017 {
1018 return( ret );
1019 }
Brian Murray0f6af732016-05-19 15:59:23 -07001020#endif /* MBEDTLS_DES_C */
1021
Simon Butcher69283e52016-10-06 12:49:58 +01001022#if defined(MBEDTLS_AES_C)
Brian Murray9044b022016-05-19 16:36:56 -07001023 if( ( ret = test_aes128_cmac_prf( verbose ) != 0 ) )
1024 return( ret );
Brian Murray0f6af732016-05-19 15:59:23 -07001025#endif /* MBEDTLS_AES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -07001026
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001027 if( verbose != 0 )
1028 mbedtls_printf( "\n" );
Brian Murray0f6af732016-05-19 15:59:23 -07001029
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001030 return( 0 );
1031}
1032
Brian Murray0f6af732016-05-19 15:59:23 -07001033#endif /* MBEDTLS_SELF_TEST */
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001034
1035#endif /* MBEDTLS_CMAC_C */