blob: 62f2a6abb4559377331b7261506b0b7dff4e5c3d [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 ) );
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;
Andres AGa592dcc2016-10-06 15:23:39 +0100247 int n, j, ret = 0;
Simon Butcher327398a2016-10-05 14:09:11 +0100248 size_t 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
283 /* Iterate across the input data in block sized chunks */
284 for( j = 0; j < n - 1; j++ )
Brian Murray57863ad2016-05-19 16:38:36 -0700285 {
Simon Butcher327398a2016-10-05 14:09:11 +0100286 cmac_xor_block( state, input, state, block_size );
287
288 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
289 &olen ) ) != 0 )
290 goto exit;
291
292 ilen -= block_size;
293 input += block_size;
Brian Murray57863ad2016-05-19 16:38:36 -0700294 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000295
Simon Butcher327398a2016-10-05 14:09:11 +0100296 /* If there is data left over that wasn't aligned to a block */
297 if( ilen > 0 )
298 {
Simon Butcher6b0774a2016-10-10 21:37:42 +0100299 memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
300 input,
301 ilen );
302 cmac_ctx->unprocessed_len += ilen;
Simon Butcher327398a2016-10-05 14:09:11 +0100303 }
304
305exit:
306 return( ret );
307}
308
309int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx,
310 unsigned char *output )
311{
312 mbedtls_cmac_context_t* cmac_ctx;
Simon Butcher69283e52016-10-06 12:49:58 +0100313 unsigned char *state, *last_block;
314 unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
315 unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
316 unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX];
Simon Butcher327398a2016-10-05 14:09:11 +0100317 int ret;
318 size_t olen, block_size;
319
320 if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ||
321 output == NULL )
322 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
323
324 cmac_ctx = ctx->cmac_ctx;
325 block_size = ctx->cipher_info->block_size;
326 state = cmac_ctx->state;
327
Simon Butcher69283e52016-10-06 12:49:58 +0100328 mbedtls_zeroize( K1, sizeof( K1 ) );
329 mbedtls_zeroize( K2, sizeof( K2 ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100330 cmac_generate_subkeys( ctx, K1, K2 );
331
Simon Butcher69283e52016-10-06 12:49:58 +0100332 last_block = cmac_ctx->unprocessed_block;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000333
334 /* Calculate last block */
Janos Follathe3d882a2016-10-11 10:49:26 +0100335 if( cmac_ctx->unprocessed_len < block_size )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000336 {
Simon Butcher327398a2016-10-05 14:09:11 +0100337 cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len );
338 cmac_xor_block( M_last, M_last, K2, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000339 }
340 else
341 {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000342 /* Last block is complete block */
Simon Butcher327398a2016-10-05 14:09:11 +0100343 cmac_xor_block( M_last, last_block, K1, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000344 }
345
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000346
Simon Butcher327398a2016-10-05 14:09:11 +0100347 cmac_xor_block( state, M_last, state, block_size );
348 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
349 &olen ) ) != 0 )
350 {
351 goto exit;
352 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000353
Simon Butcher327398a2016-10-05 14:09:11 +0100354 memcpy( output, state, block_size );
355
356exit:
357 /* Wipe the generated keys on the stack, and any other transients to avoid
358 * side channel leakage */
Simon Butcher69283e52016-10-06 12:49:58 +0100359 mbedtls_zeroize( K1, sizeof( K1 ) );
360 mbedtls_zeroize( K2, sizeof( K2 ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100361
362 cmac_ctx->unprocessed_len = 0;
363 mbedtls_zeroize( cmac_ctx->unprocessed_block,
Simon Butcher69283e52016-10-06 12:49:58 +0100364 sizeof( cmac_ctx->unprocessed_block ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100365
Simon Butcher69283e52016-10-06 12:49:58 +0100366 mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX );
Simon Butcher327398a2016-10-05 14:09:11 +0100367 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000368}
369
Simon Butcher327398a2016-10-05 14:09:11 +0100370int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000371{
Simon Butcher327398a2016-10-05 14:09:11 +0100372 mbedtls_cmac_context_t* cmac_ctx;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000373
Simon Butcher327398a2016-10-05 14:09:11 +0100374 if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL )
375 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700376
Simon Butcher327398a2016-10-05 14:09:11 +0100377 cmac_ctx = ctx->cmac_ctx;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000378
Simon Butcher327398a2016-10-05 14:09:11 +0100379 /* Reset the internal state */
380 cmac_ctx->unprocessed_len = 0;
381 mbedtls_zeroize( cmac_ctx->unprocessed_block,
Andres AGa592dcc2016-10-06 15:23:39 +0100382 sizeof( cmac_ctx->unprocessed_block ) );
Simon Butcherd241f1c2016-10-06 10:39:49 +0100383 mbedtls_zeroize( cmac_ctx->state,
384 sizeof( cmac_ctx->state ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000385
Simon Butcher327398a2016-10-05 14:09:11 +0100386 return( 0 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000387}
388
Simon Butcher327398a2016-10-05 14:09:11 +0100389int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info,
390 const unsigned char *key, size_t keylen,
391 const unsigned char *input, size_t ilen,
392 unsigned char *output )
393{
394 mbedtls_cipher_context_t ctx;
395 int ret;
396
397 if( cipher_info == NULL || key == NULL || input == NULL || output == NULL )
398 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
399
400 mbedtls_cipher_init( &ctx );
401
402 if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
403 goto exit;
404
405 ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen );
Simon Butcher327398a2016-10-05 14:09:11 +0100406 if( ret != 0 )
407 goto exit;
Simon Butcher327398a2016-10-05 14:09:11 +0100408
409 ret = mbedtls_cipher_cmac_update( &ctx, input, ilen );
410 if( ret != 0 )
411 goto exit;
412
Simon Butcher69283e52016-10-06 12:49:58 +0100413 ret = mbedtls_cipher_cmac_finish( &ctx, output );
Simon Butcher327398a2016-10-05 14:09:11 +0100414
415exit:
Simon Butcher69283e52016-10-06 12:49:58 +0100416 mbedtls_cipher_free( &ctx );
417
Simon Butcher327398a2016-10-05 14:09:11 +0100418 return( ret );
419}
Simon Butcher327398a2016-10-05 14:09:11 +0100420
Simon Butcher69283e52016-10-06 12:49:58 +0100421#if defined(MBEDTLS_AES_C)
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000422/*
Simon Butcher69283e52016-10-06 12:49:58 +0100423 * Implementation of AES-CMAC-PRF-128 defined in RFC 4615
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000424 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700425int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000426 const unsigned char *input, size_t in_len,
Simon Butcher327398a2016-10-05 14:09:11 +0100427 unsigned char *output )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000428{
429 int ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100430 const mbedtls_cipher_info_t *cipher_info;
Simon Butcher69283e52016-10-06 12:49:58 +0100431 unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE];
432 unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE];
433
434 if( key == NULL || input == NULL || output == NULL )
435 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000436
Simon Butcher327398a2016-10-05 14:09:11 +0100437 cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB );
438 if( cipher_info == NULL )
439 {
440 /* Failing at this point must be due to a build issue */
441 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
442 goto exit;
443 }
Brian Murrayb0c3c432016-05-18 14:29:51 -0700444
Simon Butcher69283e52016-10-06 12:49:58 +0100445 if( key_length == MBEDTLS_AES_BLOCK_SIZE )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000446 {
447 /* Use key as is */
Simon Butcher69283e52016-10-06 12:49:58 +0100448 memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000449 }
450 else
451 {
Simon Butcher69283e52016-10-06 12:49:58 +0100452 memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE );
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000453
Simon Butcher327398a2016-10-05 14:09:11 +0100454 ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key,
455 key_length, int_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000456 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700457 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000458 }
459
Simon Butcher327398a2016-10-05 14:09:11 +0100460 ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len,
461 output );
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000462
Simon Butcher327398a2016-10-05 14:09:11 +0100463exit:
464 mbedtls_zeroize( int_key, sizeof( int_key ) );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700465
Simon Butcher327398a2016-10-05 14:09:11 +0100466 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000467}
Brian Murrayb439d452016-05-19 16:02:42 -0700468#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000469
Simon Butcher69283e52016-10-06 12:49:58 +0100470#if defined(MBEDTLS_SELF_TEST)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000471/*
Brian Murray0f6af732016-05-19 15:59:23 -0700472 * CMAC test data from SP800-38B Appendix D.1 (corrected)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000473 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
Brian Murray0f6af732016-05-19 15:59:23 -0700474 *
475 * AES-CMAC-PRF-128 test data from RFC 4615
476 * https://tools.ietf.org/html/rfc4615#page-4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000477 */
478
Brian Murray0f6af732016-05-19 15:59:23 -0700479#define NB_CMAC_TESTS_PER_KEY 4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000480#define NB_PRF_TESTS 3
Simon Butcher327398a2016-10-05 14:09:11 +0100481
Brian Murray0f6af732016-05-19 15:59:23 -0700482#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
483/* All CMAC test inputs are truncated from the same 64 byte buffer. */
484static const unsigned char test_message[] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000485 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
486 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
487 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
488 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
489 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
490 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
491 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
492 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
493};
Simon Butcher69283e52016-10-06 12:49:58 +0100494#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */
Brian Murray0cf14c12016-05-23 12:49:50 -0700495
Simon Butcher69283e52016-10-06 12:49:58 +0100496#if defined(MBEDTLS_AES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700497/* Truncation point of message for AES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700498static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700499 0,
500 16,
501 40,
502 64
503};
504
505/* AES 128 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700506static const unsigned char aes_128_key[16] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700507 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
508 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
509};
Simon Butcher69283e52016-10-06 12:49:58 +0100510static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700511 {
512 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
513 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
514 },
515 {
516 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
517 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
518 }
519};
Simon Butcher69283e52016-10-06 12:49:58 +0100520static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000521 {
522 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
523 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
524 },
525 {
526 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
527 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
528 },
529 {
530 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
531 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
532 },
533 {
534 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
535 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
536 }
537};
538
Brian Murray0f6af732016-05-19 15:59:23 -0700539/* AES 192 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700540static const unsigned char aes_192_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700541 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
542 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
543 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000544};
Simon Butcher69283e52016-10-06 12:49:58 +0100545static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700546 {
Brian Murray0f6af732016-05-19 15:59:23 -0700547 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
548 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
Brian Murrayb0c3c432016-05-18 14:29:51 -0700549 },
550 {
Brian Murray0f6af732016-05-19 15:59:23 -0700551 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
552 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
Brian Murrayb0c3c432016-05-18 14:29:51 -0700553 }
554};
Simon Butcher69283e52016-10-06 12:49:58 +0100555static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700556 {
557 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
558 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
559 },
560 {
561 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
562 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
563 },
564 {
565 0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad,
566 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e
567 },
568 {
569 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
570 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
571 }
572};
573
Brian Murray0f6af732016-05-19 15:59:23 -0700574/* AES 256 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700575static const unsigned char aes_256_key[32] = {
Brian Murray87e40402016-05-19 19:05:57 -0700576 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
577 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
578 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
579 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
Brian Murray0f6af732016-05-19 15:59:23 -0700580};
Simon Butcher69283e52016-10-06 12:49:58 +0100581static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700582 {
583 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
584 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
585 },
586 {
587 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
588 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
589 }
590};
Simon Butcher69283e52016-10-06 12:49:58 +0100591static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700592 {
593 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
594 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
595 },
596 {
597 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
598 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
599 },
600 {
601 0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2,
602 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6
603 },
604 {
605 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
606 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
607 }
608};
609#endif /* MBEDTLS_AES_C */
610
Simon Butcher69283e52016-10-06 12:49:58 +0100611#if defined(MBEDTLS_DES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700612/* Truncation point of message for 3DES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700613static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700614 0,
615 8,
616 20,
617 32
618};
619
620/* 3DES 2 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700621static const unsigned char des3_2key_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700622 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5,
623 0x8a, 0x3d, 0x10, 0xba, 0x80, 0x57, 0x0d, 0x38,
624 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5
Brian Murray0f6af732016-05-19 15:59:23 -0700625};
626static const unsigned char des3_2key_subkeys[2][8] = {
627 {
628 0x8e, 0xcf, 0x37, 0x3e, 0xd7, 0x1a, 0xfa, 0xef
629 },
630 {
631 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5
632 }
633};
Simon Butcher69283e52016-10-06 12:49:58 +0100634static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700635 {
636 0xbd, 0x2e, 0xbf, 0x9a, 0x3b, 0xa0, 0x03, 0x61
637 },
638 {
639 0x4f, 0xf2, 0xab, 0x81, 0x3c, 0x53, 0xce, 0x83
640 },
641 {
642 0x62, 0xdd, 0x1b, 0x47, 0x19, 0x02, 0xbd, 0x4e
643 },
644 {
645 0x31, 0xb1, 0xe4, 0x31, 0xda, 0xbc, 0x4e, 0xb8
646 }
647};
648
Brian Murray0f6af732016-05-19 15:59:23 -0700649/* 3DES 3 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700650static const unsigned char des3_3key_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700651 0x8a, 0xa8, 0x3b, 0xf8, 0xcb, 0xda, 0x10, 0x62,
652 0x0b, 0xc1, 0xbf, 0x19, 0xfb, 0xb6, 0xcd, 0x58,
653 0xbc, 0x31, 0x3d, 0x4a, 0x37, 0x1c, 0xa8, 0xb5
Brian Murray0f6af732016-05-19 15:59:23 -0700654};
655static const unsigned char des3_3key_subkeys[2][8] = {
656 {
657 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f
658 },
659 {
660 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5
661 }
662};
Simon Butcher69283e52016-10-06 12:49:58 +0100663static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700664 {
665 0xb7, 0xa6, 0x88, 0xe1, 0x22, 0xff, 0xaf, 0x95
666 },
667 {
668 0x8e, 0x8f, 0x29, 0x31, 0x36, 0x28, 0x37, 0x97
669 },
670 {
671 0x74, 0x3d, 0xdb, 0xe0, 0xce, 0x2d, 0xc2, 0xed
672 },
673 {
674 0x33, 0xe6, 0xb1, 0x09, 0x24, 0x00, 0xea, 0xe5
675 }
676};
677
Brian Murray0f6af732016-05-19 15:59:23 -0700678#endif /* MBEDTLS_DES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700679
Simon Butcher69283e52016-10-06 12:49:58 +0100680#if defined(MBEDTLS_AES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700681/* AES AES-CMAC-PRF-128 Test Data */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000682static const unsigned char PRFK[] = {
683 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
684 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
685 0xed, 0xcb
686};
687
688/* Sizes in bytes */
689static const size_t PRFKlen[NB_PRF_TESTS] = {
690 18,
691 16,
692 10
693};
694
695/* PRF M */
696static const unsigned char PRFM[] = {
697 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
698 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000699 0x10, 0x11, 0x12, 0x13
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000700};
701
702static const unsigned char PRFT[NB_PRF_TESTS][16] = {
703 {
704 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
705 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
706 },
707 {
708 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
709 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
710 },
711 {
712 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
713 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
714 }
715};
Brian Murray0f6af732016-05-19 15:59:23 -0700716#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000717
Simon Butcher327398a2016-10-05 14:09:11 +0100718static int cmac_test_subkeys( int verbose,
719 const char* testname,
720 const unsigned char* key,
721 int keybits,
722 const unsigned char* subkeys,
723 mbedtls_cipher_type_t cipher_type,
724 int block_size,
725 int num_tests )
726{
727 int i, ret;
728 mbedtls_cipher_context_t ctx;
729 const mbedtls_cipher_info_t *cipher_info;
Simon Butcher69283e52016-10-06 12:49:58 +0100730 unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
731 unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
Simon Butcher327398a2016-10-05 14:09:11 +0100732
733 cipher_info = mbedtls_cipher_info_from_type( cipher_type );
734 if( cipher_info == NULL )
735 {
736 /* Failing at this point must be due to a build issue */
Simon Butcher69283e52016-10-06 12:49:58 +0100737 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
Simon Butcher327398a2016-10-05 14:09:11 +0100738 }
739
Simon Butcher69283e52016-10-06 12:49:58 +0100740 mbedtls_cipher_init( &ctx );
741
Simon Butcher327398a2016-10-05 14:09:11 +0100742 for( i = 0; i < num_tests; i++ )
743 {
744 if( verbose != 0 )
Simon Butcher69283e52016-10-06 12:49:58 +0100745 mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 );
Simon Butcher327398a2016-10-05 14:09:11 +0100746
747 if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
748 {
749 if( verbose != 0 )
750 mbedtls_printf( "test execution failed\n" );
751
752 goto exit;
753 }
754
755 if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits,
756 MBEDTLS_ENCRYPT ) ) != 0 )
757 {
758 if( verbose != 0 )
759 mbedtls_printf( "test execution failed\n" );
760
761 goto exit;
762 }
763
764 ret = cmac_generate_subkeys( &ctx, K1, K2 );
765 if( ret != 0 )
766 {
767 if( verbose != 0 )
768 mbedtls_printf( "failed\n" );
769 goto exit;
770 }
771
Simon Butcher420be4e2016-10-07 12:55:43 +0100772 if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 ||
773 ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100774 {
775 if( verbose != 0 )
776 mbedtls_printf( "failed\n" );
777 goto exit;
778 }
779
780 if( verbose != 0 )
781 mbedtls_printf( "passed\n" );
782 }
783
784exit:
Simon Butcher69283e52016-10-06 12:49:58 +0100785 mbedtls_cipher_free( &ctx );
786
Simon Butcher327398a2016-10-05 14:09:11 +0100787 return( ret );
788}
789
Simon Butcher69283e52016-10-06 12:49:58 +0100790static int cmac_test_wth_cipher( int verbose,
791 const char* testname,
792 const unsigned char* key,
793 int keybits,
794 const unsigned char* messages,
795 const unsigned int message_lengths[4],
796 const unsigned char* expected_result,
797 mbedtls_cipher_type_t cipher_type,
798 int block_size,
799 int num_tests )
Brian Murray00dc5f02016-05-19 14:23:50 -0700800{
Simon Butcher327398a2016-10-05 14:09:11 +0100801 const mbedtls_cipher_info_t *cipher_info;
Brian Murray00dc5f02016-05-19 14:23:50 -0700802 int i, ret;
Simon Butcher69283e52016-10-06 12:49:58 +0100803 unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX];
Brian Murray57863ad2016-05-19 16:38:36 -0700804
Simon Butcher327398a2016-10-05 14:09:11 +0100805 cipher_info = mbedtls_cipher_info_from_type( cipher_type );
806 if( cipher_info == NULL )
Brian Murray00dc5f02016-05-19 14:23:50 -0700807 {
Simon Butcher327398a2016-10-05 14:09:11 +0100808 /* Failing at this point must be due to a build issue */
809 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
Brian Murray00dc5f02016-05-19 14:23:50 -0700810 goto exit;
811 }
812
813 for( i = 0; i < num_tests; i++ )
814 {
815 if( verbose != 0 )
Andres AGa592dcc2016-10-06 15:23:39 +0100816 mbedtls_printf( " %s CMAC #%u: ", testname, i + 1 );
Brian Murray00dc5f02016-05-19 14:23:50 -0700817
Simon Butcher327398a2016-10-05 14:09:11 +0100818 if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages,
819 message_lengths[i], output ) ) != 0 )
Brian Murray00dc5f02016-05-19 14:23:50 -0700820 {
821 if( verbose != 0 )
822 mbedtls_printf( "failed\n" );
823 goto exit;
824 }
Brian Murray9ce2e092016-05-24 22:46:43 -0700825
Simon Butcher327398a2016-10-05 14:09:11 +0100826 if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 )
Brian Murray00dc5f02016-05-19 14:23:50 -0700827 {
828 if( verbose != 0 )
829 mbedtls_printf( "failed\n" );
830 goto exit;
831 }
832
Brian Murray9ce2e092016-05-24 22:46:43 -0700833 if( verbose != 0 )
834 mbedtls_printf( "passed\n" );
Brian Murray00dc5f02016-05-19 14:23:50 -0700835 }
Simon Butcher327398a2016-10-05 14:09:11 +0100836
Simon Butcher69283e52016-10-06 12:49:58 +0100837exit:
Simon Butcher327398a2016-10-05 14:09:11 +0100838 return( ret );
Brian Murray00dc5f02016-05-19 14:23:50 -0700839}
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000840
Simon Butcher69283e52016-10-06 12:49:58 +0100841#if defined(MBEDTLS_AES_C)
842static int test_aes128_cmac_prf( int verbose )
Brian Murray6a3c0d22016-05-20 18:25:43 -0700843{
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000844 int i;
845 int ret;
Simon Butcher69283e52016-10-06 12:49:58 +0100846 unsigned char output[MBEDTLS_AES_BLOCK_SIZE];
Simon Butcher327398a2016-10-05 14:09:11 +0100847
Brian Murrayb0c3c432016-05-18 14:29:51 -0700848 for( i = 0; i < NB_PRF_TESTS; i++ )
849 {
Brian Murray0f6af732016-05-19 15:59:23 -0700850 mbedtls_printf( " AES CMAC 128 PRF #%u: ", i );
Simon Butcher327398a2016-10-05 14:09:11 +0100851 ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700852 if( ret != 0 ||
Simon Butcher69283e52016-10-06 12:49:58 +0100853 memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700854 {
Simon Butcher327398a2016-10-05 14:09:11 +0100855
Brian Murrayb0c3c432016-05-18 14:29:51 -0700856 if( verbose != 0 )
857 mbedtls_printf( "failed\n" );
858
Brian Murray0f6af732016-05-19 15:59:23 -0700859 return( ret );
Simon Butcher69283e52016-10-06 12:49:58 +0100860 }
861 else if( verbose != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700862 {
863 mbedtls_printf( "passed\n" );
864 }
865 }
Brian Murray0f6af732016-05-19 15:59:23 -0700866 return( ret );
867}
868#endif /* MBEDTLS_AES_C */
869
870int mbedtls_cmac_self_test( int verbose )
871{
872 int ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100873
Simon Butcher69283e52016-10-06 12:49:58 +0100874#if defined(MBEDTLS_AES_C)
Simon Butcher327398a2016-10-05 14:09:11 +0100875 /* AES-128 */
876 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100877 "AES 128",
878 aes_128_key,
879 128,
880 (const unsigned char*)aes_128_subkeys,
881 MBEDTLS_CIPHER_AES_128_ECB,
882 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100883 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100884 {
885 return( ret );
886 }
887
Brian Murrayae1cb122016-05-23 15:01:59 -0700888 if( ( ret = cmac_test_wth_cipher( verbose,
889 "AES 128",
890 aes_128_key,
891 128,
892 test_message,
893 aes_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100894 (const unsigned char*)aes_128_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100895 MBEDTLS_CIPHER_AES_128_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100896 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100897 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100898 {
899 return( ret );
900 }
901
902 /* AES-192 */
903 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100904 "AES 192",
905 aes_192_key,
906 192,
907 (const unsigned char*)aes_192_subkeys,
908 MBEDTLS_CIPHER_AES_192_ECB,
909 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100910 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -0700911 {
912 return( ret );
913 }
Brian Murray0f6af732016-05-19 15:59:23 -0700914
Brian Murrayae1cb122016-05-23 15:01:59 -0700915 if( ( ret = cmac_test_wth_cipher( verbose,
916 "AES 192",
917 aes_192_key,
918 192,
919 test_message,
920 aes_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100921 (const unsigned char*)aes_192_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100922 MBEDTLS_CIPHER_AES_192_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100923 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100924 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100925 {
Simon Butcher327398a2016-10-05 14:09:11 +0100926 return( ret );
927 }
928
929 /* AES-256 */
930 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100931 "AES 256",
932 aes_256_key,
933 256,
934 (const unsigned char*)aes_256_subkeys,
935 MBEDTLS_CIPHER_AES_256_ECB,
936 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100937 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -0700938 {
939 return( ret );
940 }
Brian Murray0f6af732016-05-19 15:59:23 -0700941
Simon Butcher69283e52016-10-06 12:49:58 +0100942 if( ( ret = cmac_test_wth_cipher ( verbose,
Brian Murrayae1cb122016-05-23 15:01:59 -0700943 "AES 256",
944 aes_256_key,
945 256,
946 test_message,
947 aes_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100948 (const unsigned char*)aes_256_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100949 MBEDTLS_CIPHER_AES_256_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100950 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100951 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -0700952 {
953 return( ret );
954 }
Brian Murray0f6af732016-05-19 15:59:23 -0700955#endif /* MBEDTLS_AES_C */
956
Simon Butcher69283e52016-10-06 12:49:58 +0100957#if defined(MBEDTLS_DES_C)
Simon Butcher327398a2016-10-05 14:09:11 +0100958 /* 3DES 2 key */
959 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100960 "3DES 2 key",
961 des3_2key_key,
962 192,
963 (const unsigned char*)des3_2key_subkeys,
964 MBEDTLS_CIPHER_DES_EDE3_ECB,
965 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100966 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100967 {
968 return( ret );
969 }
970
Brian Murrayae1cb122016-05-23 15:01:59 -0700971 if( ( ret = cmac_test_wth_cipher( verbose,
972 "3DES 2 key",
973 des3_2key_key,
974 192,
975 test_message,
976 des3_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100977 (const unsigned char*)des3_2key_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100978 MBEDTLS_CIPHER_DES_EDE3_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100979 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100980 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -0700981 {
982 return( ret );
983 }
Brian Murray0f6af732016-05-19 15:59:23 -0700984
Simon Butcher327398a2016-10-05 14:09:11 +0100985 /* 3DES 3 key */
986 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100987 "3DES 3 key",
988 des3_3key_key,
989 192,
990 (const unsigned char*)des3_3key_subkeys,
991 MBEDTLS_CIPHER_DES_EDE3_ECB,
992 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100993 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100994 {
995 return( ret );
996 }
997
Brian Murrayae1cb122016-05-23 15:01:59 -0700998 if( ( ret = cmac_test_wth_cipher( verbose,
999 "3DES 3 key",
1000 des3_3key_key,
1001 192,
1002 test_message,
1003 des3_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +01001004 (const unsigned char*)des3_3key_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +01001005 MBEDTLS_CIPHER_DES_EDE3_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +01001006 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +01001007 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -07001008 {
1009 return( ret );
1010 }
Brian Murray0f6af732016-05-19 15:59:23 -07001011#endif /* MBEDTLS_DES_C */
1012
Simon Butcher69283e52016-10-06 12:49:58 +01001013#if defined(MBEDTLS_AES_C)
Simon Butcher420be4e2016-10-07 12:55:43 +01001014 if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -07001015 return( ret );
Brian Murray0f6af732016-05-19 15:59:23 -07001016#endif /* MBEDTLS_AES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -07001017
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001018 if( verbose != 0 )
1019 mbedtls_printf( "\n" );
Brian Murray0f6af732016-05-19 15:59:23 -07001020
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001021 return( 0 );
1022}
1023
Brian Murray0f6af732016-05-19 15:59:23 -07001024#endif /* MBEDTLS_SELF_TEST */
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001025
1026#endif /* MBEDTLS_CMAC_C */