blob: 035ad071d4d0aa9f5d3b0935acd1abbc6e246846 [file] [log] [blame]
Andres Amaya Garciaaf610a02016-12-14 10:13:43 +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
Janos Follathcd13bd22016-12-13 11:51:04 +000029 * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf
Simon Butcher327398a2016-10-05 14:09:11 +010030 *
31 * - RFC 4493 - The AES-CMAC Algorithm
32 * https://tools.ietf.org/html/rfc4493
33 *
34 * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message
35 * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128)
36 * Algorithm for the Internet Key Exchange Protocol (IKE)
37 * https://tools.ietf.org/html/rfc4615
38 *
39 * Additional test vectors: ISO/IEC 9797-1
40 *
Robert Cragie3d23b1d2015-12-15 07:38:11 +000041 */
42
43#if !defined(MBEDTLS_CONFIG_FILE)
44#include "mbedtls/config.h"
45#else
46#include MBEDTLS_CONFIG_FILE
47#endif
48
49#if defined(MBEDTLS_CMAC_C)
50
51#include "mbedtls/cmac.h"
52
53#include <string.h>
54
Brian Murray8b4111c2016-09-13 15:58:46 -070055
Robert Cragie3d23b1d2015-12-15 07:38:11 +000056#if defined(MBEDTLS_PLATFORM_C)
57#include "mbedtls/platform.h"
58#else
Brian Murray8b4111c2016-09-13 15:58:46 -070059#include <stdlib.h>
60#define mbedtls_calloc calloc
61#define mbedtls_free free
Simon Butcherd241f1c2016-10-06 10:39:49 +010062#if defined(MBEDTLS_SELF_TEST)
Robert Cragie3d23b1d2015-12-15 07:38:11 +000063#include <stdio.h>
Brian Murray8b4111c2016-09-13 15:58:46 -070064#define mbedtls_printf printf
Brian J Murray2adecba2016-11-06 04:45:15 -080065#endif /* MBEDTLS_SELF_TEST */
Robert Cragie3d23b1d2015-12-15 07:38:11 +000066#endif /* MBEDTLS_PLATFORM_C */
Brian Murray8b4111c2016-09-13 15:58:46 -070067
Robert Cragie3d23b1d2015-12-15 07:38:11 +000068/* Implementation that should never be optimized out by the compiler */
69static void mbedtls_zeroize( void *v, size_t n ) {
Simon Butcher327398a2016-10-05 14:09:11 +010070 volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
Robert Cragie3d23b1d2015-12-15 07:38:11 +000071}
72
73/*
Brian Murrayb0c3c432016-05-18 14:29:51 -070074 * Multiplication by u in the Galois field of GF(2^n)
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000075 *
Brian Murray72b69e32016-09-13 14:21:01 -070076 * As explained in NIST SP 800-38B, this can be computed:
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000077 *
Simon Butcher327398a2016-10-05 14:09:11 +010078 * If MSB(p) = 0, then p = (p << 1)
79 * If MSB(p) = 1, then p = (p << 1) ^ R_n
80 * with R_64 = 0x1B and R_128 = 0x87
81 *
82 * Input and output MUST NOT point to the same buffer
Brian J Murray2adecba2016-11-06 04:45:15 -080083 * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES.
Robert Cragie3d23b1d2015-12-15 07:38:11 +000084 */
Brian Murrayb0c3c432016-05-18 14:29:51 -070085static int cmac_multiply_by_u( unsigned char *output,
86 const unsigned char *input,
Brian Murray53e23b62016-09-13 14:00:15 -070087 size_t blocksize )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000088{
Brian Murrayb0c3c432016-05-18 14:29:51 -070089 const unsigned char R_128 = 0x87;
90 const unsigned char R_64 = 0x1B;
91 unsigned char R_n, mask;
92 unsigned char overflow = 0x00;
Simon Butcher327398a2016-10-05 14:09:11 +010093 int i;
Brian Murrayb0c3c432016-05-18 14:29:51 -070094
Simon Butcher69283e52016-10-06 12:49:58 +010095 if( blocksize == MBEDTLS_AES_BLOCK_SIZE )
Brian Murray6a3c0d22016-05-20 18:25:43 -070096 {
Brian Murrayb0c3c432016-05-18 14:29:51 -070097 R_n = R_128;
Simon Butcher327398a2016-10-05 14:09:11 +010098 }
Simon Butcher69283e52016-10-06 12:49:58 +010099 else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE )
Brian Murray6a3c0d22016-05-20 18:25:43 -0700100 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700101 R_n = R_64;
Simon Butcher327398a2016-10-05 14:09:11 +0100102 }
103 else
Brian Murray6a3c0d22016-05-20 18:25:43 -0700104 {
Simon Butcher327398a2016-10-05 14:09:11 +0100105 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700106 }
107
Simon B3249cb72016-11-03 01:11:37 +0000108 for( i = (int)blocksize - 1; i >= 0; i-- )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000109 {
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000110 output[i] = input[i] << 1 | overflow;
111 overflow = input[i] >> 7;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000112 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000113
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +0000114 /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
115 * using bit operations to avoid branches */
Simon Butcher327398a2016-10-05 14:09:11 +0100116
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +0000117 /* MSVC has a warning about unary minus on unsigned, but this is
118 * well-defined and precisely what we want to do here */
119#if defined(_MSC_VER)
120#pragma warning( push )
121#pragma warning( disable : 4146 )
122#endif
123 mask = - ( input[0] >> 7 );
124#if defined(_MSC_VER)
125#pragma warning( pop )
126#endif
127
Simon Butcher327398a2016-10-05 14:09:11 +0100128 output[ blocksize - 1 ] ^= R_n & mask;
129
Brian Murrayb439d452016-05-19 16:02:42 -0700130 return( 0 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000131}
132
133/*
134 * Generate subkeys
Simon Butcher327398a2016-10-05 14:09:11 +0100135 *
136 * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000137 */
Simon Butcher327398a2016-10-05 14:09:11 +0100138static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx,
139 unsigned char* K1, unsigned char* K2 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000140{
Brian Murray57863ad2016-05-19 16:38:36 -0700141 int ret;
Simon Butcher69283e52016-10-06 12:49:58 +0100142 unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700143 size_t olen, block_size;
144
Simon Butcher327398a2016-10-05 14:09:11 +0100145 mbedtls_zeroize( L, sizeof( L ) );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700146
Simon Butcher327398a2016-10-05 14:09:11 +0100147 block_size = ctx->cipher_info->block_size;
148
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000149 /* Calculate Ek(0) */
Simon Butcher327398a2016-10-05 14:09:11 +0100150 if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700151 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000152
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000153 /*
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000154 * Generate K1 and K2
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000155 */
Simon Butcher327398a2016-10-05 14:09:11 +0100156 if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700157 goto exit;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000158
Simon Butcher327398a2016-10-05 14:09:11 +0100159 if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 )
160 goto exit;
161
162exit:
163 mbedtls_zeroize( L, sizeof( L ) );
164
165 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000166}
167
Simon Butcher69283e52016-10-06 12:49:58 +0100168static void cmac_xor_block( unsigned char *output, const unsigned char *input1,
169 const unsigned char *input2,
170 const size_t block_size )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000171{
Simon Butcher327398a2016-10-05 14:09:11 +0100172 size_t index;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000173
Simon Butcher327398a2016-10-05 14:09:11 +0100174 for( index = 0; index < block_size; index++ )
175 output[ index ] = input1[ index ] ^ input2[ index ];
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000176}
177
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000178/*
179 * Create padded last block from (partial) last block.
180 *
181 * We can't use the padding option from the cipher layer, as it only works for
182 * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
183 */
Simon Butcher69283e52016-10-06 12:49:58 +0100184static void cmac_pad( unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX],
Brian Murray53e23b62016-09-13 14:00:15 -0700185 size_t padded_block_len,
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000186 const unsigned char *last_block,
Brian Murrayb0c3c432016-05-18 14:29:51 -0700187 size_t last_block_len )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000188{
189 size_t j;
190
Brian Murrayb0c3c432016-05-18 14:29:51 -0700191 for( j = 0; j < padded_block_len; j++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000192 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700193 if( j < last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000194 padded_block[j] = last_block[j];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700195 else if( j == last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000196 padded_block[j] = 0x80;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000197 else
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000198 padded_block[j] = 0x00;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000199 }
200}
201
Simon Butcher327398a2016-10-05 14:09:11 +0100202int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx,
Simon Butcher94ffde72016-10-05 15:33:53 +0100203 const unsigned char *key, size_t keybits )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000204{
Simon Butcher327398a2016-10-05 14:09:11 +0100205 mbedtls_cipher_type_t type;
206 mbedtls_cmac_context_t *cmac_ctx;
Simon Butcher327398a2016-10-05 14:09:11 +0100207 int retval;
208
209 if( ctx == NULL || ctx->cipher_info == NULL || key == NULL )
210 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
211
Simon B3249cb72016-11-03 01:11:37 +0000212 if( ( retval = mbedtls_cipher_setkey( ctx, key, (int)keybits,
Simon Butcher327398a2016-10-05 14:09:11 +0100213 MBEDTLS_ENCRYPT ) ) != 0 )
214 return( retval );
215
Simon Butcher327398a2016-10-05 14:09:11 +0100216 type = ctx->cipher_info->type;
217
218 switch( type )
219 {
220 case MBEDTLS_CIPHER_AES_128_ECB:
221 case MBEDTLS_CIPHER_AES_192_ECB:
222 case MBEDTLS_CIPHER_AES_256_ECB:
223 case MBEDTLS_CIPHER_DES_EDE3_ECB:
224 break;
225 default:
226 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
227 }
228
229 /* Allocated and initialise in the cipher context memory for the CMAC
230 * context */
231 cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) );
232 if( cmac_ctx == NULL )
233 return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
234
235 ctx->cmac_ctx = cmac_ctx;
236
237 mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100238
239 return 0;
240}
241
242int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx,
243 const unsigned char *input, size_t ilen )
244{
245 mbedtls_cmac_context_t* cmac_ctx;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700246 unsigned char *state;
Simon B3249cb72016-11-03 01:11:37 +0000247 int ret = 0;
248 size_t n, j, olen, block_size;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700249
Simon Butcher327398a2016-10-05 14:09:11 +0100250 if( ctx == NULL || ctx->cipher_info == NULL || input == NULL ||
251 ctx->cmac_ctx == NULL )
252 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700253
Simon Butcher327398a2016-10-05 14:09:11 +0100254 cmac_ctx = ctx->cmac_ctx;
255 block_size = ctx->cipher_info->block_size;
256 state = ctx->cmac_ctx->state;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000257
Simon Butcher6b0774a2016-10-10 21:37:42 +0100258 /* Is there data still to process from the last call, that's greater in
259 * size than a block? */
Simon Butcher327398a2016-10-05 14:09:11 +0100260 if( cmac_ctx->unprocessed_len > 0 &&
Andres AGa592dcc2016-10-06 15:23:39 +0100261 ilen > block_size - cmac_ctx->unprocessed_len )
Brian Murray57863ad2016-05-19 16:38:36 -0700262 {
Simon Butcher327398a2016-10-05 14:09:11 +0100263 memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
264 input,
265 block_size - cmac_ctx->unprocessed_len );
266
267 cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size );
268
269 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
270 &olen ) ) != 0 )
271 {
272 goto exit;
273 }
274
Simon Butcher6b0774a2016-10-10 21:37:42 +0100275 input += block_size - cmac_ctx->unprocessed_len;
276 ilen -= block_size - cmac_ctx->unprocessed_len;
Simon Butcher327398a2016-10-05 14:09:11 +0100277 cmac_ctx->unprocessed_len = 0;
Brian Murray57863ad2016-05-19 16:38:36 -0700278 }
279
Simon Butcher327398a2016-10-05 14:09:11 +0100280 /* n is the number of blocks including any final partial block */
281 n = ( ilen + block_size - 1 ) / block_size;
282
Simon B3249cb72016-11-03 01:11:37 +0000283 /* Iterate across the input data in block sized chunks, excluding any
284 * final partial or complete block */
285 for( j = 1; j < n; j++ )
Brian Murray57863ad2016-05-19 16:38:36 -0700286 {
Simon Butcher327398a2016-10-05 14:09:11 +0100287 cmac_xor_block( state, input, state, block_size );
288
289 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
290 &olen ) ) != 0 )
291 goto exit;
292
293 ilen -= block_size;
294 input += block_size;
Brian Murray57863ad2016-05-19 16:38:36 -0700295 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000296
Simon Butcher327398a2016-10-05 14:09:11 +0100297 /* If there is data left over that wasn't aligned to a block */
298 if( ilen > 0 )
299 {
Simon Butcher6b0774a2016-10-10 21:37:42 +0100300 memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
301 input,
302 ilen );
303 cmac_ctx->unprocessed_len += ilen;
Simon Butcher327398a2016-10-05 14:09:11 +0100304 }
305
306exit:
307 return( ret );
308}
309
310int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx,
311 unsigned char *output )
312{
313 mbedtls_cmac_context_t* cmac_ctx;
Simon Butcher69283e52016-10-06 12:49:58 +0100314 unsigned char *state, *last_block;
315 unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
316 unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
317 unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX];
Simon Butcher327398a2016-10-05 14:09:11 +0100318 int ret;
319 size_t olen, block_size;
320
321 if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ||
322 output == NULL )
323 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
324
325 cmac_ctx = ctx->cmac_ctx;
326 block_size = ctx->cipher_info->block_size;
327 state = cmac_ctx->state;
328
Simon Butcher69283e52016-10-06 12:49:58 +0100329 mbedtls_zeroize( K1, sizeof( K1 ) );
330 mbedtls_zeroize( K2, sizeof( K2 ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100331 cmac_generate_subkeys( ctx, K1, K2 );
332
Simon Butcher69283e52016-10-06 12:49:58 +0100333 last_block = cmac_ctx->unprocessed_block;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000334
335 /* Calculate last block */
Janos Follathe3d882a2016-10-11 10:49:26 +0100336 if( cmac_ctx->unprocessed_len < block_size )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000337 {
Simon Butcher327398a2016-10-05 14:09:11 +0100338 cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len );
339 cmac_xor_block( M_last, M_last, K2, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000340 }
341 else
342 {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000343 /* Last block is complete block */
Simon Butcher327398a2016-10-05 14:09:11 +0100344 cmac_xor_block( M_last, last_block, K1, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000345 }
346
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000347
Simon Butcher327398a2016-10-05 14:09:11 +0100348 cmac_xor_block( state, M_last, state, block_size );
349 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
350 &olen ) ) != 0 )
351 {
352 goto exit;
353 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000354
Simon Butcher327398a2016-10-05 14:09:11 +0100355 memcpy( output, state, block_size );
356
357exit:
358 /* Wipe the generated keys on the stack, and any other transients to avoid
359 * side channel leakage */
Simon Butcher69283e52016-10-06 12:49:58 +0100360 mbedtls_zeroize( K1, sizeof( K1 ) );
361 mbedtls_zeroize( K2, sizeof( K2 ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100362
363 cmac_ctx->unprocessed_len = 0;
364 mbedtls_zeroize( cmac_ctx->unprocessed_block,
Simon Butcher69283e52016-10-06 12:49:58 +0100365 sizeof( cmac_ctx->unprocessed_block ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100366
Simon Butcher69283e52016-10-06 12:49:58 +0100367 mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX );
Simon Butcher327398a2016-10-05 14:09:11 +0100368 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000369}
370
Simon Butcher327398a2016-10-05 14:09:11 +0100371int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000372{
Simon Butcher327398a2016-10-05 14:09:11 +0100373 mbedtls_cmac_context_t* cmac_ctx;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000374
Simon Butcher327398a2016-10-05 14:09:11 +0100375 if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL )
376 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700377
Simon Butcher327398a2016-10-05 14:09:11 +0100378 cmac_ctx = ctx->cmac_ctx;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000379
Simon Butcher327398a2016-10-05 14:09:11 +0100380 /* Reset the internal state */
381 cmac_ctx->unprocessed_len = 0;
382 mbedtls_zeroize( cmac_ctx->unprocessed_block,
Andres AGa592dcc2016-10-06 15:23:39 +0100383 sizeof( cmac_ctx->unprocessed_block ) );
Simon Butcherd241f1c2016-10-06 10:39:49 +0100384 mbedtls_zeroize( cmac_ctx->state,
385 sizeof( cmac_ctx->state ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000386
Simon Butcher327398a2016-10-05 14:09:11 +0100387 return( 0 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000388}
389
Simon Butcher327398a2016-10-05 14:09:11 +0100390int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info,
391 const unsigned char *key, size_t keylen,
392 const unsigned char *input, size_t ilen,
393 unsigned char *output )
394{
395 mbedtls_cipher_context_t ctx;
396 int ret;
397
398 if( cipher_info == NULL || key == NULL || input == NULL || output == NULL )
399 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
400
401 mbedtls_cipher_init( &ctx );
402
403 if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
404 goto exit;
405
406 ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen );
Simon Butcher327398a2016-10-05 14:09:11 +0100407 if( ret != 0 )
408 goto exit;
Simon Butcher327398a2016-10-05 14:09:11 +0100409
410 ret = mbedtls_cipher_cmac_update( &ctx, input, ilen );
411 if( ret != 0 )
412 goto exit;
413
Simon Butcher69283e52016-10-06 12:49:58 +0100414 ret = mbedtls_cipher_cmac_finish( &ctx, output );
Simon Butcher327398a2016-10-05 14:09:11 +0100415
416exit:
Simon Butcher69283e52016-10-06 12:49:58 +0100417 mbedtls_cipher_free( &ctx );
418
Simon Butcher327398a2016-10-05 14:09:11 +0100419 return( ret );
420}
Simon Butcher327398a2016-10-05 14:09:11 +0100421
Simon Butcher69283e52016-10-06 12:49:58 +0100422#if defined(MBEDTLS_AES_C)
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000423/*
Simon Butcher69283e52016-10-06 12:49:58 +0100424 * Implementation of AES-CMAC-PRF-128 defined in RFC 4615
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000425 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700426int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000427 const unsigned char *input, size_t in_len,
Simon Butcher327398a2016-10-05 14:09:11 +0100428 unsigned char *output )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000429{
430 int ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100431 const mbedtls_cipher_info_t *cipher_info;
Simon Butcher69283e52016-10-06 12:49:58 +0100432 unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE];
433 unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE];
434
435 if( key == NULL || input == NULL || output == NULL )
436 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000437
Simon Butcher327398a2016-10-05 14:09:11 +0100438 cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB );
439 if( cipher_info == NULL )
440 {
441 /* Failing at this point must be due to a build issue */
442 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
443 goto exit;
444 }
Brian Murrayb0c3c432016-05-18 14:29:51 -0700445
Simon Butcher69283e52016-10-06 12:49:58 +0100446 if( key_length == MBEDTLS_AES_BLOCK_SIZE )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000447 {
448 /* Use key as is */
Simon Butcher69283e52016-10-06 12:49:58 +0100449 memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000450 }
451 else
452 {
Simon Butcher69283e52016-10-06 12:49:58 +0100453 memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE );
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000454
Simon Butcher327398a2016-10-05 14:09:11 +0100455 ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key,
456 key_length, int_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000457 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700458 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000459 }
460
Simon Butcher327398a2016-10-05 14:09:11 +0100461 ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len,
462 output );
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000463
Simon Butcher327398a2016-10-05 14:09:11 +0100464exit:
465 mbedtls_zeroize( int_key, sizeof( int_key ) );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700466
Simon Butcher327398a2016-10-05 14:09:11 +0100467 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000468}
Brian Murrayb439d452016-05-19 16:02:42 -0700469#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000470
Simon Butcher69283e52016-10-06 12:49:58 +0100471#if defined(MBEDTLS_SELF_TEST)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000472/*
Janos Follathcd13bd22016-12-13 11:51:04 +0000473 * CMAC test data for SP800-38B
474 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf
475 * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf
Brian Murray0f6af732016-05-19 15:59:23 -0700476 *
477 * AES-CMAC-PRF-128 test data from RFC 4615
478 * https://tools.ietf.org/html/rfc4615#page-4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000479 */
480
Brian Murray0f6af732016-05-19 15:59:23 -0700481#define NB_CMAC_TESTS_PER_KEY 4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000482#define NB_PRF_TESTS 3
Simon Butcher327398a2016-10-05 14:09:11 +0100483
Brian Murray0f6af732016-05-19 15:59:23 -0700484#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
485/* All CMAC test inputs are truncated from the same 64 byte buffer. */
486static const unsigned char test_message[] = {
Janos Follathcd13bd22016-12-13 11:51:04 +0000487 /* PT */
488 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
489 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
490 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
491 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
492 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
493 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
494 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
495 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000496};
Simon Butcher69283e52016-10-06 12:49:58 +0100497#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */
Brian Murray0cf14c12016-05-23 12:49:50 -0700498
Simon Butcher69283e52016-10-06 12:49:58 +0100499#if defined(MBEDTLS_AES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700500/* Truncation point of message for AES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700501static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Janos Follathcd13bd22016-12-13 11:51:04 +0000502 /* Mlen */
Brian Murray0f6af732016-05-19 15:59:23 -0700503 0,
504 16,
Janos Follathcd13bd22016-12-13 11:51:04 +0000505 20,
Brian Murray0f6af732016-05-19 15:59:23 -0700506 64
507};
508
Janos Follathcd13bd22016-12-13 11:51:04 +0000509/* CMAC-AES128 Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700510static const unsigned char aes_128_key[16] = {
Janos Follathcd13bd22016-12-13 11:51:04 +0000511 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
512 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
Brian Murray0f6af732016-05-19 15:59:23 -0700513};
Simon Butcher69283e52016-10-06 12:49:58 +0100514static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700515 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000516 /* K1 */
517 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
518 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
Brian Murray0f6af732016-05-19 15:59:23 -0700519 },
520 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000521 /* K2 */
522 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
523 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
Brian Murray0f6af732016-05-19 15:59:23 -0700524 }
525};
Simon Butcher69283e52016-10-06 12:49:58 +0100526static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000527 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000528 /* Example #1 */
529 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
530 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000531 },
532 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000533 /* Example #2 */
534 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
535 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000536 },
537 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000538 /* Example #3 */
539 0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8,
540 0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000541 },
542 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000543 /* Example #4 */
544 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
545 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000546 }
547};
548
Janos Follathcd13bd22016-12-13 11:51:04 +0000549/* CMAC-AES192 Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700550static const unsigned char aes_192_key[24] = {
Janos Follathcd13bd22016-12-13 11:51:04 +0000551 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
552 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
553 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000554};
Simon Butcher69283e52016-10-06 12:49:58 +0100555static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700556 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000557 /* K1 */
558 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
559 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
Brian Murrayb0c3c432016-05-18 14:29:51 -0700560 },
561 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000562 /* K2 */
563 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
564 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
Brian Murrayb0c3c432016-05-18 14:29:51 -0700565 }
566};
Simon Butcher69283e52016-10-06 12:49:58 +0100567static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700568 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000569 /* Example #1 */
570 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
571 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
Brian Murrayb0c3c432016-05-18 14:29:51 -0700572 },
573 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000574 /* Example #2 */
575 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
576 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
Brian Murrayb0c3c432016-05-18 14:29:51 -0700577 },
578 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000579 /* Example #3 */
580 0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04,
581 0x44, 0xa9, 0xfa, 0x7e, 0xc7, 0x40, 0xec, 0xf8
Brian Murrayb0c3c432016-05-18 14:29:51 -0700582 },
583 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000584 /* Example #4 */
585 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
586 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
Brian Murrayb0c3c432016-05-18 14:29:51 -0700587 }
588};
589
Janos Follathcd13bd22016-12-13 11:51:04 +0000590/* CMAC-AES256 Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700591static const unsigned char aes_256_key[32] = {
Janos Follathcd13bd22016-12-13 11:51:04 +0000592 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
593 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
594 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
595 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
Brian Murray0f6af732016-05-19 15:59:23 -0700596};
Simon Butcher69283e52016-10-06 12:49:58 +0100597static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700598 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000599 /* K1 */
600 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
601 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
Brian Murray0f6af732016-05-19 15:59:23 -0700602 },
603 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000604 /* K2 */
605 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
606 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
Brian Murray0f6af732016-05-19 15:59:23 -0700607 }
608};
Simon Butcher69283e52016-10-06 12:49:58 +0100609static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700610 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000611 /* Example #1 */
612 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
613 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
Brian Murray0f6af732016-05-19 15:59:23 -0700614 },
615 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000616 /* Example #2 */
617 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
618 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
Brian Murray0f6af732016-05-19 15:59:23 -0700619 },
620 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000621 /* Example #3 */
622 0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a,
623 0x02, 0x3c, 0x1f, 0xe0, 0x3b, 0xad, 0x6d, 0x93
Brian Murray0f6af732016-05-19 15:59:23 -0700624 },
625 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000626 /* Example #4 */
627 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
628 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
Brian Murray0f6af732016-05-19 15:59:23 -0700629 }
630};
631#endif /* MBEDTLS_AES_C */
632
Simon Butcher69283e52016-10-06 12:49:58 +0100633#if defined(MBEDTLS_DES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700634/* Truncation point of message for 3DES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700635static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700636 0,
Janos Follathcd13bd22016-12-13 11:51:04 +0000637 16,
Brian Murray0f6af732016-05-19 15:59:23 -0700638 20,
639 32
640};
641
Janos Follathcd13bd22016-12-13 11:51:04 +0000642/* CMAC-TDES (Generation) - 2 Key Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700643static const unsigned char des3_2key_key[24] = {
Janos Follathcd13bd22016-12-13 11:51:04 +0000644 /* Key1 */
645 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
646 /* Key2 */
647 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01,
648 /* Key3 */
649 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
Brian Murray0f6af732016-05-19 15:59:23 -0700650};
651static const unsigned char des3_2key_subkeys[2][8] = {
652 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000653 /* K1 */
654 0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9
Brian Murray0f6af732016-05-19 15:59:23 -0700655 },
656 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000657 /* K2 */
658 0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2
Brian Murray0f6af732016-05-19 15:59:23 -0700659 }
660};
Simon Butcher69283e52016-10-06 12:49:58 +0100661static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700662 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000663 /* Sample #1 */
664 0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60
Brian Murrayb0c3c432016-05-18 14:29:51 -0700665 },
666 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000667 /* Sample #2 */
668 0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b
Brian Murrayb0c3c432016-05-18 14:29:51 -0700669 },
670 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000671 /* Sample #3 */
672 0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69
Brian Murrayb0c3c432016-05-18 14:29:51 -0700673 },
674 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000675 /* Sample #4 */
676 0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb
Brian Murrayb0c3c432016-05-18 14:29:51 -0700677 }
678};
679
Janos Follathcd13bd22016-12-13 11:51:04 +0000680/* CMAC-TDES (Generation) - 3 Key Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700681static const unsigned char des3_3key_key[24] = {
Janos Follathcd13bd22016-12-13 11:51:04 +0000682 /* Key1 */
683 0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef,
684 /* Key2 */
685 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01,
686 /* Key3 */
687 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23
Brian Murray0f6af732016-05-19 15:59:23 -0700688};
689static const unsigned char des3_3key_subkeys[2][8] = {
690 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000691 /* K1 */
692 0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0
Brian Murray0f6af732016-05-19 15:59:23 -0700693 },
694 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000695 /* K2 */
696 0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b
Brian Murray0f6af732016-05-19 15:59:23 -0700697 }
698};
Simon Butcher69283e52016-10-06 12:49:58 +0100699static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700700 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000701 /* Sample #1 */
702 0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50
Brian Murrayb0c3c432016-05-18 14:29:51 -0700703 },
704 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000705 /* Sample #2 */
706 0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09
Brian Murrayb0c3c432016-05-18 14:29:51 -0700707 },
708 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000709 /* Sample #3 */
710 0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2
Brian Murrayb0c3c432016-05-18 14:29:51 -0700711 },
712 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000713 /* Sample #4 */
714 0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5
Brian Murrayb0c3c432016-05-18 14:29:51 -0700715 }
716};
717
Brian Murray0f6af732016-05-19 15:59:23 -0700718#endif /* MBEDTLS_DES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700719
Simon Butcher69283e52016-10-06 12:49:58 +0100720#if defined(MBEDTLS_AES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700721/* AES AES-CMAC-PRF-128 Test Data */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000722static const unsigned char PRFK[] = {
Janos Follathcd13bd22016-12-13 11:51:04 +0000723 /* Key */
724 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
725 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000726 0xed, 0xcb
727};
728
729/* Sizes in bytes */
730static const size_t PRFKlen[NB_PRF_TESTS] = {
731 18,
732 16,
733 10
734};
735
Janos Follathcd13bd22016-12-13 11:51:04 +0000736/* Message */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000737static const unsigned char PRFM[] = {
Janos Follathcd13bd22016-12-13 11:51:04 +0000738 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
739 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000740 0x10, 0x11, 0x12, 0x13
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000741};
742
743static const unsigned char PRFT[NB_PRF_TESTS][16] = {
744 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000745 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
746 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000747 },
748 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000749 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
750 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000751 },
752 {
Janos Follathcd13bd22016-12-13 11:51:04 +0000753 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
754 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000755 }
756};
Brian Murray0f6af732016-05-19 15:59:23 -0700757#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000758
Simon Butcher327398a2016-10-05 14:09:11 +0100759static int cmac_test_subkeys( int verbose,
760 const char* testname,
761 const unsigned char* key,
762 int keybits,
763 const unsigned char* subkeys,
764 mbedtls_cipher_type_t cipher_type,
765 int block_size,
766 int num_tests )
767{
768 int i, ret;
769 mbedtls_cipher_context_t ctx;
770 const mbedtls_cipher_info_t *cipher_info;
Simon Butcher69283e52016-10-06 12:49:58 +0100771 unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
772 unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
Simon Butcher327398a2016-10-05 14:09:11 +0100773
774 cipher_info = mbedtls_cipher_info_from_type( cipher_type );
775 if( cipher_info == NULL )
776 {
777 /* Failing at this point must be due to a build issue */
Simon Butcher69283e52016-10-06 12:49:58 +0100778 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
Simon Butcher327398a2016-10-05 14:09:11 +0100779 }
780
781 for( i = 0; i < num_tests; i++ )
782 {
783 if( verbose != 0 )
Simon Butcher69283e52016-10-06 12:49:58 +0100784 mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 );
Simon Butcher327398a2016-10-05 14:09:11 +0100785
Janos Follathd4443582016-10-12 10:00:42 +0100786 mbedtls_cipher_init( &ctx );
787
Simon Butcher327398a2016-10-05 14:09:11 +0100788 if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
789 {
790 if( verbose != 0 )
791 mbedtls_printf( "test execution failed\n" );
792
Janos Follathd4443582016-10-12 10:00:42 +0100793 goto cleanup;
Simon Butcher327398a2016-10-05 14:09:11 +0100794 }
795
796 if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits,
797 MBEDTLS_ENCRYPT ) ) != 0 )
798 {
799 if( verbose != 0 )
800 mbedtls_printf( "test execution failed\n" );
801
Janos Follathd4443582016-10-12 10:00:42 +0100802 goto cleanup;
Simon Butcher327398a2016-10-05 14:09:11 +0100803 }
804
805 ret = cmac_generate_subkeys( &ctx, K1, K2 );
806 if( ret != 0 )
807 {
808 if( verbose != 0 )
809 mbedtls_printf( "failed\n" );
Janos Follathd4443582016-10-12 10:00:42 +0100810
811 goto cleanup;
Simon Butcher327398a2016-10-05 14:09:11 +0100812 }
813
Simon Butcher420be4e2016-10-07 12:55:43 +0100814 if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 ||
815 ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100816 {
817 if( verbose != 0 )
818 mbedtls_printf( "failed\n" );
Janos Follathd4443582016-10-12 10:00:42 +0100819
820 goto cleanup;
Simon Butcher327398a2016-10-05 14:09:11 +0100821 }
822
823 if( verbose != 0 )
824 mbedtls_printf( "passed\n" );
Janos Follathd4443582016-10-12 10:00:42 +0100825
826 mbedtls_cipher_free( &ctx );
Simon Butcher327398a2016-10-05 14:09:11 +0100827 }
828
Janos Follathd4443582016-10-12 10:00:42 +0100829 goto exit;
830
831cleanup:
Simon Butcher69283e52016-10-06 12:49:58 +0100832 mbedtls_cipher_free( &ctx );
833
Janos Follathd4443582016-10-12 10:00:42 +0100834exit:
Simon Butcher327398a2016-10-05 14:09:11 +0100835 return( ret );
836}
837
Simon Butcher69283e52016-10-06 12:49:58 +0100838static int cmac_test_wth_cipher( int verbose,
839 const char* testname,
840 const unsigned char* key,
841 int keybits,
842 const unsigned char* messages,
843 const unsigned int message_lengths[4],
844 const unsigned char* expected_result,
845 mbedtls_cipher_type_t cipher_type,
846 int block_size,
847 int num_tests )
Brian Murray00dc5f02016-05-19 14:23:50 -0700848{
Simon Butcher327398a2016-10-05 14:09:11 +0100849 const mbedtls_cipher_info_t *cipher_info;
Brian Murray00dc5f02016-05-19 14:23:50 -0700850 int i, ret;
Simon Butcher69283e52016-10-06 12:49:58 +0100851 unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX];
Brian Murray57863ad2016-05-19 16:38:36 -0700852
Simon Butcher327398a2016-10-05 14:09:11 +0100853 cipher_info = mbedtls_cipher_info_from_type( cipher_type );
854 if( cipher_info == NULL )
Brian Murray00dc5f02016-05-19 14:23:50 -0700855 {
Simon Butcher327398a2016-10-05 14:09:11 +0100856 /* Failing at this point must be due to a build issue */
857 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
Brian Murray00dc5f02016-05-19 14:23:50 -0700858 goto exit;
859 }
860
861 for( i = 0; i < num_tests; i++ )
862 {
863 if( verbose != 0 )
Andres AGa592dcc2016-10-06 15:23:39 +0100864 mbedtls_printf( " %s CMAC #%u: ", testname, i + 1 );
Brian Murray00dc5f02016-05-19 14:23:50 -0700865
Simon Butcher327398a2016-10-05 14:09:11 +0100866 if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages,
867 message_lengths[i], output ) ) != 0 )
Brian Murray00dc5f02016-05-19 14:23:50 -0700868 {
869 if( verbose != 0 )
870 mbedtls_printf( "failed\n" );
871 goto exit;
872 }
Brian Murray9ce2e092016-05-24 22:46:43 -0700873
Simon Butcher327398a2016-10-05 14:09:11 +0100874 if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 )
Brian Murray00dc5f02016-05-19 14:23:50 -0700875 {
876 if( verbose != 0 )
877 mbedtls_printf( "failed\n" );
878 goto exit;
879 }
880
Brian Murray9ce2e092016-05-24 22:46:43 -0700881 if( verbose != 0 )
882 mbedtls_printf( "passed\n" );
Brian Murray00dc5f02016-05-19 14:23:50 -0700883 }
Simon Butcher327398a2016-10-05 14:09:11 +0100884
Simon Butcher69283e52016-10-06 12:49:58 +0100885exit:
Simon Butcher327398a2016-10-05 14:09:11 +0100886 return( ret );
Brian Murray00dc5f02016-05-19 14:23:50 -0700887}
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000888
Simon Butcher69283e52016-10-06 12:49:58 +0100889#if defined(MBEDTLS_AES_C)
890static int test_aes128_cmac_prf( int verbose )
Brian Murray6a3c0d22016-05-20 18:25:43 -0700891{
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000892 int i;
893 int ret;
Simon Butcher69283e52016-10-06 12:49:58 +0100894 unsigned char output[MBEDTLS_AES_BLOCK_SIZE];
Simon Butcher327398a2016-10-05 14:09:11 +0100895
Brian Murrayb0c3c432016-05-18 14:29:51 -0700896 for( i = 0; i < NB_PRF_TESTS; i++ )
897 {
Brian Murray0f6af732016-05-19 15:59:23 -0700898 mbedtls_printf( " AES CMAC 128 PRF #%u: ", i );
Simon Butcher327398a2016-10-05 14:09:11 +0100899 ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700900 if( ret != 0 ||
Simon Butcher69283e52016-10-06 12:49:58 +0100901 memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700902 {
Simon Butcher327398a2016-10-05 14:09:11 +0100903
Brian Murrayb0c3c432016-05-18 14:29:51 -0700904 if( verbose != 0 )
905 mbedtls_printf( "failed\n" );
906
Brian Murray0f6af732016-05-19 15:59:23 -0700907 return( ret );
Simon Butcher69283e52016-10-06 12:49:58 +0100908 }
909 else if( verbose != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700910 {
911 mbedtls_printf( "passed\n" );
912 }
913 }
Brian Murray0f6af732016-05-19 15:59:23 -0700914 return( ret );
915}
916#endif /* MBEDTLS_AES_C */
917
918int mbedtls_cmac_self_test( int verbose )
919{
920 int ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100921
Simon Butcher69283e52016-10-06 12:49:58 +0100922#if defined(MBEDTLS_AES_C)
Simon Butcher327398a2016-10-05 14:09:11 +0100923 /* AES-128 */
924 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100925 "AES 128",
926 aes_128_key,
927 128,
928 (const unsigned char*)aes_128_subkeys,
929 MBEDTLS_CIPHER_AES_128_ECB,
930 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100931 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100932 {
933 return( ret );
934 }
935
Brian Murrayae1cb122016-05-23 15:01:59 -0700936 if( ( ret = cmac_test_wth_cipher( verbose,
937 "AES 128",
938 aes_128_key,
939 128,
940 test_message,
941 aes_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100942 (const unsigned char*)aes_128_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100943 MBEDTLS_CIPHER_AES_128_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100944 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100945 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100946 {
947 return( ret );
948 }
949
950 /* AES-192 */
951 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100952 "AES 192",
953 aes_192_key,
954 192,
955 (const unsigned char*)aes_192_subkeys,
956 MBEDTLS_CIPHER_AES_192_ECB,
957 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100958 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -0700959 {
960 return( ret );
961 }
Brian Murray0f6af732016-05-19 15:59:23 -0700962
Brian Murrayae1cb122016-05-23 15:01:59 -0700963 if( ( ret = cmac_test_wth_cipher( verbose,
964 "AES 192",
965 aes_192_key,
966 192,
967 test_message,
968 aes_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100969 (const unsigned char*)aes_192_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100970 MBEDTLS_CIPHER_AES_192_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100971 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100972 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100973 {
Simon Butcher327398a2016-10-05 14:09:11 +0100974 return( ret );
975 }
976
977 /* AES-256 */
978 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100979 "AES 256",
980 aes_256_key,
981 256,
982 (const unsigned char*)aes_256_subkeys,
983 MBEDTLS_CIPHER_AES_256_ECB,
984 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100985 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -0700986 {
987 return( ret );
988 }
Brian Murray0f6af732016-05-19 15:59:23 -0700989
Simon Butcher69283e52016-10-06 12:49:58 +0100990 if( ( ret = cmac_test_wth_cipher ( verbose,
Brian Murrayae1cb122016-05-23 15:01:59 -0700991 "AES 256",
992 aes_256_key,
993 256,
994 test_message,
995 aes_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100996 (const unsigned char*)aes_256_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100997 MBEDTLS_CIPHER_AES_256_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100998 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100999 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -07001000 {
1001 return( ret );
1002 }
Brian Murray0f6af732016-05-19 15:59:23 -07001003#endif /* MBEDTLS_AES_C */
1004
Simon Butcher69283e52016-10-06 12:49:58 +01001005#if defined(MBEDTLS_DES_C)
Simon Butcher327398a2016-10-05 14:09:11 +01001006 /* 3DES 2 key */
1007 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +01001008 "3DES 2 key",
1009 des3_2key_key,
1010 192,
1011 (const unsigned char*)des3_2key_subkeys,
1012 MBEDTLS_CIPHER_DES_EDE3_ECB,
1013 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +01001014 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +01001015 {
1016 return( ret );
1017 }
1018
Brian Murrayae1cb122016-05-23 15:01:59 -07001019 if( ( ret = cmac_test_wth_cipher( verbose,
1020 "3DES 2 key",
1021 des3_2key_key,
1022 192,
1023 test_message,
1024 des3_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +01001025 (const unsigned char*)des3_2key_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +01001026 MBEDTLS_CIPHER_DES_EDE3_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +01001027 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +01001028 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -07001029 {
1030 return( ret );
1031 }
Brian Murray0f6af732016-05-19 15:59:23 -07001032
Simon Butcher327398a2016-10-05 14:09:11 +01001033 /* 3DES 3 key */
1034 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +01001035 "3DES 3 key",
1036 des3_3key_key,
1037 192,
1038 (const unsigned char*)des3_3key_subkeys,
1039 MBEDTLS_CIPHER_DES_EDE3_ECB,
1040 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +01001041 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +01001042 {
1043 return( ret );
1044 }
1045
Brian Murrayae1cb122016-05-23 15:01:59 -07001046 if( ( ret = cmac_test_wth_cipher( verbose,
1047 "3DES 3 key",
1048 des3_3key_key,
1049 192,
1050 test_message,
1051 des3_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +01001052 (const unsigned char*)des3_3key_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +01001053 MBEDTLS_CIPHER_DES_EDE3_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +01001054 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +01001055 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -07001056 {
1057 return( ret );
1058 }
Brian Murray0f6af732016-05-19 15:59:23 -07001059#endif /* MBEDTLS_DES_C */
1060
Simon Butcher69283e52016-10-06 12:49:58 +01001061#if defined(MBEDTLS_AES_C)
Simon Butcher420be4e2016-10-07 12:55:43 +01001062 if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -07001063 return( ret );
Brian Murray0f6af732016-05-19 15:59:23 -07001064#endif /* MBEDTLS_AES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -07001065
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001066 if( verbose != 0 )
1067 mbedtls_printf( "\n" );
Brian Murray0f6af732016-05-19 15:59:23 -07001068
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001069 return( 0 );
1070}
1071
Brian Murray0f6af732016-05-19 15:59:23 -07001072#endif /* MBEDTLS_SELF_TEST */
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001073
1074#endif /* MBEDTLS_CMAC_C */