blob: f755d409f09db1c8c41ac6f127be185d6018514f [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
Simon Butcher69283e52016-10-06 12:49:58 +010065#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C || MBEDTLS_DES_C */
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
Simon Butcher69283e52016-10-06 12:49:58 +010083 * Block size must be 8 byes 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 Butcher327398a2016-10-05 14:09:11 +0100108 for( i = 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 Butcher94ffde72016-10-05 15:33:53 +0100212 if( ( retval = mbedtls_cipher_setkey( ctx, key, 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 ) );
238 cmac_ctx->padding_flag = 1;
239
240 return 0;
241}
242
243int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx,
244 const unsigned char *input, size_t ilen )
245{
246 mbedtls_cmac_context_t* cmac_ctx;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700247 unsigned char *state;
Andres AGa592dcc2016-10-06 15:23:39 +0100248 int n, j, ret = 0;
Simon Butcher327398a2016-10-05 14:09:11 +0100249 size_t olen, block_size;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700250
Simon Butcher327398a2016-10-05 14:09:11 +0100251 if( ctx == NULL || ctx->cipher_info == NULL || input == NULL ||
252 ctx->cmac_ctx == NULL )
253 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700254
Simon Butcher327398a2016-10-05 14:09:11 +0100255 cmac_ctx = ctx->cmac_ctx;
256 block_size = ctx->cipher_info->block_size;
257 state = ctx->cmac_ctx->state;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000258
Simon Butcher327398a2016-10-05 14:09:11 +0100259 /* Is their data still to process from the last call, that's equal to
260 * or greater than a block? */
261 if( cmac_ctx->unprocessed_len > 0 &&
Andres AGa592dcc2016-10-06 15:23:39 +0100262 ilen > block_size - cmac_ctx->unprocessed_len )
Brian Murray57863ad2016-05-19 16:38:36 -0700263 {
Simon Butcher327398a2016-10-05 14:09:11 +0100264 memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
265 input,
266 block_size - cmac_ctx->unprocessed_len );
267
268 cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size );
269
270 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
271 &olen ) ) != 0 )
272 {
273 goto exit;
274 }
275
276 ilen -= block_size;
277 input += cmac_ctx->unprocessed_len;
278
279 cmac_ctx->unprocessed_len = 0;
Brian Murray57863ad2016-05-19 16:38:36 -0700280 }
281
Simon Butcher327398a2016-10-05 14:09:11 +0100282 /* n is the number of blocks including any final partial block */
283 n = ( ilen + block_size - 1 ) / block_size;
284
285 /* Iterate across the input data in block sized chunks */
286 for( j = 0; j < n - 1; j++ )
Brian Murray57863ad2016-05-19 16:38:36 -0700287 {
Simon Butcher327398a2016-10-05 14:09:11 +0100288 cmac_xor_block( state, input, state, block_size );
289
290 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
291 &olen ) ) != 0 )
292 goto exit;
293
294 ilen -= block_size;
295 input += block_size;
296
297 cmac_ctx->padding_flag = 0;
Brian Murray57863ad2016-05-19 16:38:36 -0700298 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000299
Simon Butcher327398a2016-10-05 14:09:11 +0100300 /* If there is data left over that wasn't aligned to a block */
301 if( ilen > 0 )
302 {
303 memcpy( &cmac_ctx->unprocessed_block, input, ilen );
304 cmac_ctx->unprocessed_len = ilen;
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000305
Simon Butcher327398a2016-10-05 14:09:11 +0100306 if( ilen % block_size > 0 )
307 cmac_ctx->padding_flag = 1;
308 else
309 cmac_ctx->padding_flag = 0;
310 }
311
312exit:
313 return( ret );
314}
315
316int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx,
317 unsigned char *output )
318{
319 mbedtls_cmac_context_t* cmac_ctx;
Simon Butcher69283e52016-10-06 12:49:58 +0100320 unsigned char *state, *last_block;
321 unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
322 unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
323 unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX];
Simon Butcher327398a2016-10-05 14:09:11 +0100324 int ret;
325 size_t olen, block_size;
326
327 if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ||
328 output == NULL )
329 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
330
331 cmac_ctx = ctx->cmac_ctx;
332 block_size = ctx->cipher_info->block_size;
333 state = cmac_ctx->state;
334
Simon Butcher69283e52016-10-06 12:49:58 +0100335 mbedtls_zeroize( K1, sizeof( K1 ) );
336 mbedtls_zeroize( K2, sizeof( K2 ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100337 cmac_generate_subkeys( ctx, K1, K2 );
338
Simon Butcher69283e52016-10-06 12:49:58 +0100339 last_block = cmac_ctx->unprocessed_block;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000340
341 /* Calculate last block */
Simon Butcher327398a2016-10-05 14:09:11 +0100342 if( cmac_ctx->padding_flag )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000343 {
Simon Butcher327398a2016-10-05 14:09:11 +0100344 cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len );
345 cmac_xor_block( M_last, M_last, K2, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000346 }
347 else
348 {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000349 /* Last block is complete block */
Simon Butcher327398a2016-10-05 14:09:11 +0100350 cmac_xor_block( M_last, last_block, K1, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000351 }
352
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000353
Simon Butcher327398a2016-10-05 14:09:11 +0100354 cmac_xor_block( state, M_last, state, block_size );
355 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
356 &olen ) ) != 0 )
357 {
358 goto exit;
359 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000360
Simon Butcher327398a2016-10-05 14:09:11 +0100361 memcpy( output, state, block_size );
362
363exit:
364 /* Wipe the generated keys on the stack, and any other transients to avoid
365 * side channel leakage */
Simon Butcher69283e52016-10-06 12:49:58 +0100366 mbedtls_zeroize( K1, sizeof( K1 ) );
367 mbedtls_zeroize( K2, sizeof( K2 ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100368
Simon Butcher69283e52016-10-06 12:49:58 +0100369 cmac_ctx->padding_flag = 1;
Simon Butcher327398a2016-10-05 14:09:11 +0100370 cmac_ctx->unprocessed_len = 0;
371 mbedtls_zeroize( cmac_ctx->unprocessed_block,
Simon Butcher69283e52016-10-06 12:49:58 +0100372 sizeof( cmac_ctx->unprocessed_block ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100373
Simon Butcher69283e52016-10-06 12:49:58 +0100374 mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX );
Simon Butcher327398a2016-10-05 14:09:11 +0100375 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000376}
377
Simon Butcher327398a2016-10-05 14:09:11 +0100378int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000379{
Simon Butcher327398a2016-10-05 14:09:11 +0100380 mbedtls_cmac_context_t* cmac_ctx;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000381
Simon Butcher327398a2016-10-05 14:09:11 +0100382 if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL )
383 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700384
Simon Butcher327398a2016-10-05 14:09:11 +0100385 cmac_ctx = ctx->cmac_ctx;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000386
Simon Butcher327398a2016-10-05 14:09:11 +0100387 /* Reset the internal state */
388 cmac_ctx->unprocessed_len = 0;
389 mbedtls_zeroize( cmac_ctx->unprocessed_block,
Andres AGa592dcc2016-10-06 15:23:39 +0100390 sizeof( cmac_ctx->unprocessed_block ) );
Simon Butcherd241f1c2016-10-06 10:39:49 +0100391 mbedtls_zeroize( cmac_ctx->state,
392 sizeof( cmac_ctx->state ) );
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
Simon Butcher420be4e2016-10-07 12:55:43 +0100781 if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 ||
782 ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100783 {
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 )
Andres AGa592dcc2016-10-06 15:23:39 +0100825 mbedtls_printf( " %s CMAC #%u: ", testname, i + 1 );
Brian Murray00dc5f02016-05-19 14:23:50 -0700826
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,
Simon Butcher420be4e2016-10-07 12:55:43 +0100892 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,
Simon Butcher420be4e2016-10-07 12:55:43 +0100906 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,
Simon Butcher420be4e2016-10-07 12:55:43 +0100919 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,
Simon Butcher420be4e2016-10-07 12:55:43 +0100933 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,
Simon Butcher420be4e2016-10-07 12:55:43 +0100946 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,
Simon Butcher420be4e2016-10-07 12:55:43 +0100960 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,
Simon Butcher420be4e2016-10-07 12:55:43 +0100975 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,
Simon Butcher420be4e2016-10-07 12:55:43 +0100989 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,
Simon Butcher420be4e2016-10-07 12:55:43 +01001002 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,
Simon Butcher420be4e2016-10-07 12:55:43 +01001016 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)
Simon Butcher420be4e2016-10-07 12:55:43 +01001023 if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -07001024 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 */