blob: ee2fe056ce6c4bf9cd4e7c483c9c5f681b96852c [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
740 for( i = 0; i < num_tests; i++ )
741 {
742 if( verbose != 0 )
Simon Butcher69283e52016-10-06 12:49:58 +0100743 mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 );
Simon Butcher327398a2016-10-05 14:09:11 +0100744
Janos Follathd4443582016-10-12 10:00:42 +0100745 mbedtls_cipher_init( &ctx );
746
Simon Butcher327398a2016-10-05 14:09:11 +0100747 if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
748 {
749 if( verbose != 0 )
750 mbedtls_printf( "test execution failed\n" );
751
Janos Follathd4443582016-10-12 10:00:42 +0100752 goto cleanup;
Simon Butcher327398a2016-10-05 14:09:11 +0100753 }
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
Janos Follathd4443582016-10-12 10:00:42 +0100761 goto cleanup;
Simon Butcher327398a2016-10-05 14:09:11 +0100762 }
763
764 ret = cmac_generate_subkeys( &ctx, K1, K2 );
765 if( ret != 0 )
766 {
767 if( verbose != 0 )
768 mbedtls_printf( "failed\n" );
Janos Follathd4443582016-10-12 10:00:42 +0100769
770 goto cleanup;
Simon Butcher327398a2016-10-05 14:09:11 +0100771 }
772
Simon Butcher420be4e2016-10-07 12:55:43 +0100773 if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 ||
774 ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100775 {
776 if( verbose != 0 )
777 mbedtls_printf( "failed\n" );
Janos Follathd4443582016-10-12 10:00:42 +0100778
779 goto cleanup;
Simon Butcher327398a2016-10-05 14:09:11 +0100780 }
781
782 if( verbose != 0 )
783 mbedtls_printf( "passed\n" );
Janos Follathd4443582016-10-12 10:00:42 +0100784
785 mbedtls_cipher_free( &ctx );
Simon Butcher327398a2016-10-05 14:09:11 +0100786 }
787
Janos Follathd4443582016-10-12 10:00:42 +0100788 goto exit;
789
790cleanup:
Simon Butcher69283e52016-10-06 12:49:58 +0100791 mbedtls_cipher_free( &ctx );
792
Janos Follathd4443582016-10-12 10:00:42 +0100793exit:
Simon Butcher327398a2016-10-05 14:09:11 +0100794 return( ret );
795}
796
Simon Butcher69283e52016-10-06 12:49:58 +0100797static int cmac_test_wth_cipher( int verbose,
798 const char* testname,
799 const unsigned char* key,
800 int keybits,
801 const unsigned char* messages,
802 const unsigned int message_lengths[4],
803 const unsigned char* expected_result,
804 mbedtls_cipher_type_t cipher_type,
805 int block_size,
806 int num_tests )
Brian Murray00dc5f02016-05-19 14:23:50 -0700807{
Simon Butcher327398a2016-10-05 14:09:11 +0100808 const mbedtls_cipher_info_t *cipher_info;
Brian Murray00dc5f02016-05-19 14:23:50 -0700809 int i, ret;
Simon Butcher69283e52016-10-06 12:49:58 +0100810 unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX];
Brian Murray57863ad2016-05-19 16:38:36 -0700811
Simon Butcher327398a2016-10-05 14:09:11 +0100812 cipher_info = mbedtls_cipher_info_from_type( cipher_type );
813 if( cipher_info == NULL )
Brian Murray00dc5f02016-05-19 14:23:50 -0700814 {
Simon Butcher327398a2016-10-05 14:09:11 +0100815 /* Failing at this point must be due to a build issue */
816 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
Brian Murray00dc5f02016-05-19 14:23:50 -0700817 goto exit;
818 }
819
820 for( i = 0; i < num_tests; i++ )
821 {
822 if( verbose != 0 )
Andres AGa592dcc2016-10-06 15:23:39 +0100823 mbedtls_printf( " %s CMAC #%u: ", testname, i + 1 );
Brian Murray00dc5f02016-05-19 14:23:50 -0700824
Simon Butcher327398a2016-10-05 14:09:11 +0100825 if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages,
826 message_lengths[i], output ) ) != 0 )
Brian Murray00dc5f02016-05-19 14:23:50 -0700827 {
828 if( verbose != 0 )
829 mbedtls_printf( "failed\n" );
830 goto exit;
831 }
Brian Murray9ce2e092016-05-24 22:46:43 -0700832
Simon Butcher327398a2016-10-05 14:09:11 +0100833 if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 )
Brian Murray00dc5f02016-05-19 14:23:50 -0700834 {
835 if( verbose != 0 )
836 mbedtls_printf( "failed\n" );
837 goto exit;
838 }
839
Brian Murray9ce2e092016-05-24 22:46:43 -0700840 if( verbose != 0 )
841 mbedtls_printf( "passed\n" );
Brian Murray00dc5f02016-05-19 14:23:50 -0700842 }
Simon Butcher327398a2016-10-05 14:09:11 +0100843
Simon Butcher69283e52016-10-06 12:49:58 +0100844exit:
Simon Butcher327398a2016-10-05 14:09:11 +0100845 return( ret );
Brian Murray00dc5f02016-05-19 14:23:50 -0700846}
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000847
Simon Butcher69283e52016-10-06 12:49:58 +0100848#if defined(MBEDTLS_AES_C)
849static int test_aes128_cmac_prf( int verbose )
Brian Murray6a3c0d22016-05-20 18:25:43 -0700850{
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000851 int i;
852 int ret;
Simon Butcher69283e52016-10-06 12:49:58 +0100853 unsigned char output[MBEDTLS_AES_BLOCK_SIZE];
Simon Butcher327398a2016-10-05 14:09:11 +0100854
Brian Murrayb0c3c432016-05-18 14:29:51 -0700855 for( i = 0; i < NB_PRF_TESTS; i++ )
856 {
Brian Murray0f6af732016-05-19 15:59:23 -0700857 mbedtls_printf( " AES CMAC 128 PRF #%u: ", i );
Simon Butcher327398a2016-10-05 14:09:11 +0100858 ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700859 if( ret != 0 ||
Simon Butcher69283e52016-10-06 12:49:58 +0100860 memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700861 {
Simon Butcher327398a2016-10-05 14:09:11 +0100862
Brian Murrayb0c3c432016-05-18 14:29:51 -0700863 if( verbose != 0 )
864 mbedtls_printf( "failed\n" );
865
Brian Murray0f6af732016-05-19 15:59:23 -0700866 return( ret );
Simon Butcher69283e52016-10-06 12:49:58 +0100867 }
868 else if( verbose != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700869 {
870 mbedtls_printf( "passed\n" );
871 }
872 }
Brian Murray0f6af732016-05-19 15:59:23 -0700873 return( ret );
874}
875#endif /* MBEDTLS_AES_C */
876
877int mbedtls_cmac_self_test( int verbose )
878{
879 int ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100880
Simon Butcher69283e52016-10-06 12:49:58 +0100881#if defined(MBEDTLS_AES_C)
Simon Butcher327398a2016-10-05 14:09:11 +0100882 /* AES-128 */
883 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100884 "AES 128",
885 aes_128_key,
886 128,
887 (const unsigned char*)aes_128_subkeys,
888 MBEDTLS_CIPHER_AES_128_ECB,
889 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100890 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100891 {
892 return( ret );
893 }
894
Brian Murrayae1cb122016-05-23 15:01:59 -0700895 if( ( ret = cmac_test_wth_cipher( verbose,
896 "AES 128",
897 aes_128_key,
898 128,
899 test_message,
900 aes_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100901 (const unsigned char*)aes_128_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100902 MBEDTLS_CIPHER_AES_128_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100903 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100904 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100905 {
906 return( ret );
907 }
908
909 /* AES-192 */
910 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100911 "AES 192",
912 aes_192_key,
913 192,
914 (const unsigned char*)aes_192_subkeys,
915 MBEDTLS_CIPHER_AES_192_ECB,
916 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100917 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -0700918 {
919 return( ret );
920 }
Brian Murray0f6af732016-05-19 15:59:23 -0700921
Brian Murrayae1cb122016-05-23 15:01:59 -0700922 if( ( ret = cmac_test_wth_cipher( verbose,
923 "AES 192",
924 aes_192_key,
925 192,
926 test_message,
927 aes_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100928 (const unsigned char*)aes_192_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100929 MBEDTLS_CIPHER_AES_192_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100930 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 {
Simon Butcher327398a2016-10-05 14:09:11 +0100933 return( ret );
934 }
935
936 /* AES-256 */
937 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100938 "AES 256",
939 aes_256_key,
940 256,
941 (const unsigned char*)aes_256_subkeys,
942 MBEDTLS_CIPHER_AES_256_ECB,
943 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100944 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -0700945 {
946 return( ret );
947 }
Brian Murray0f6af732016-05-19 15:59:23 -0700948
Simon Butcher69283e52016-10-06 12:49:58 +0100949 if( ( ret = cmac_test_wth_cipher ( verbose,
Brian Murrayae1cb122016-05-23 15:01:59 -0700950 "AES 256",
951 aes_256_key,
952 256,
953 test_message,
954 aes_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100955 (const unsigned char*)aes_256_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100956 MBEDTLS_CIPHER_AES_256_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100957 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#endif /* MBEDTLS_AES_C */
963
Simon Butcher69283e52016-10-06 12:49:58 +0100964#if defined(MBEDTLS_DES_C)
Simon Butcher327398a2016-10-05 14:09:11 +0100965 /* 3DES 2 key */
966 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100967 "3DES 2 key",
968 des3_2key_key,
969 192,
970 (const unsigned char*)des3_2key_subkeys,
971 MBEDTLS_CIPHER_DES_EDE3_ECB,
972 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100973 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100974 {
975 return( ret );
976 }
977
Brian Murrayae1cb122016-05-23 15:01:59 -0700978 if( ( ret = cmac_test_wth_cipher( verbose,
979 "3DES 2 key",
980 des3_2key_key,
981 192,
982 test_message,
983 des3_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100984 (const unsigned char*)des3_2key_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100985 MBEDTLS_CIPHER_DES_EDE3_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100986 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100987 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -0700988 {
989 return( ret );
990 }
Brian Murray0f6af732016-05-19 15:59:23 -0700991
Simon Butcher327398a2016-10-05 14:09:11 +0100992 /* 3DES 3 key */
993 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100994 "3DES 3 key",
995 des3_3key_key,
996 192,
997 (const unsigned char*)des3_3key_subkeys,
998 MBEDTLS_CIPHER_DES_EDE3_ECB,
999 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +01001000 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +01001001 {
1002 return( ret );
1003 }
1004
Brian Murrayae1cb122016-05-23 15:01:59 -07001005 if( ( ret = cmac_test_wth_cipher( verbose,
1006 "3DES 3 key",
1007 des3_3key_key,
1008 192,
1009 test_message,
1010 des3_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +01001011 (const unsigned char*)des3_3key_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +01001012 MBEDTLS_CIPHER_DES_EDE3_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +01001013 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +01001014 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -07001015 {
1016 return( ret );
1017 }
Brian Murray0f6af732016-05-19 15:59:23 -07001018#endif /* MBEDTLS_DES_C */
1019
Simon Butcher69283e52016-10-06 12:49:58 +01001020#if defined(MBEDTLS_AES_C)
Simon Butcher420be4e2016-10-07 12:55:43 +01001021 if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -07001022 return( ret );
Brian Murray0f6af732016-05-19 15:59:23 -07001023#endif /* MBEDTLS_AES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -07001024
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001025 if( verbose != 0 )
1026 mbedtls_printf( "\n" );
Brian Murray0f6af732016-05-19 15:59:23 -07001027
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001028 return( 0 );
1029}
1030
Brian Murray0f6af732016-05-19 15:59:23 -07001031#endif /* MBEDTLS_SELF_TEST */
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001032
1033#endif /* MBEDTLS_CMAC_C */