blob: 62f2a6abb4559377331b7261506b0b7dff4e5c3d [file] [log] [blame]
Robert Cragie9bf1e5d2015-12-15 07:38:11 +00001/*
Brian Murray3d644312016-09-13 14:00:15 -07002 * \file cmac.c
Simon Butcher0c790732016-10-05 14:09:11 +01003 *
Simon Butcherf394e092016-10-06 12:49:58 +01004 * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES
Robert Cragie9bf1e5d2015-12-15 07:38:11 +00005 *
Brian Murray3d644312016-09-13 14:00:15 -07006 * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
Robert Cragie9bf1e5d2015-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 Murray3d644312016-09-13 14:00:15 -070025 * References:
Simon Butcher0c790732016-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 Cragie9bf1e5d2015-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 Murray7b07e0e2016-09-13 15:58:46 -070055
Robert Cragie9bf1e5d2015-12-15 07:38:11 +000056#if defined(MBEDTLS_PLATFORM_C)
57#include "mbedtls/platform.h"
58#else
Brian Murray7b07e0e2016-09-13 15:58:46 -070059#include <stdlib.h>
60#define mbedtls_calloc calloc
61#define mbedtls_free free
Simon Butcher21279322016-10-06 10:39:49 +010062#if defined(MBEDTLS_SELF_TEST)
Robert Cragie9bf1e5d2015-12-15 07:38:11 +000063#include <stdio.h>
Brian Murray7b07e0e2016-09-13 15:58:46 -070064#define mbedtls_printf printf
Simon Butcherf394e092016-10-06 12:49:58 +010065#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C || MBEDTLS_DES_C */
Robert Cragie9bf1e5d2015-12-15 07:38:11 +000066#endif /* MBEDTLS_PLATFORM_C */
Brian Murray7b07e0e2016-09-13 15:58:46 -070067
Robert Cragie9bf1e5d2015-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 Butcher0c790732016-10-05 14:09:11 +010070 volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +000071}
72
73/*
Brian Murray7c6476c2016-05-18 14:29:51 -070074 * Multiplication by u in the Galois field of GF(2^n)
Manuel Pégourié-Gonnard756bcf72016-01-13 11:28:16 +000075 *
Brian Murray51686182016-09-13 14:21:01 -070076 * As explained in NIST SP 800-38B, this can be computed:
Manuel Pégourié-Gonnard756bcf72016-01-13 11:28:16 +000077 *
Simon Butcher0c790732016-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 Butcherf394e092016-10-06 12:49:58 +010083 * Block size must be 8 byes or 16 bytes - the block sizes for DES and AES.
Robert Cragie9bf1e5d2015-12-15 07:38:11 +000084 */
Brian Murray7c6476c2016-05-18 14:29:51 -070085static int cmac_multiply_by_u( unsigned char *output,
86 const unsigned char *input,
Brian Murray3d644312016-09-13 14:00:15 -070087 size_t blocksize )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +000088{
Brian Murray7c6476c2016-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 Butcher0c790732016-10-05 14:09:11 +010093 int i;
Brian Murray7c6476c2016-05-18 14:29:51 -070094
Simon Butcherf394e092016-10-06 12:49:58 +010095 if( blocksize == MBEDTLS_AES_BLOCK_SIZE )
Brian Murray4e067032016-05-20 18:25:43 -070096 {
Brian Murray7c6476c2016-05-18 14:29:51 -070097 R_n = R_128;
Simon Butcher0c790732016-10-05 14:09:11 +010098 }
Simon Butcherf394e092016-10-06 12:49:58 +010099 else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE )
Brian Murray4e067032016-05-20 18:25:43 -0700100 {
Brian Murray7c6476c2016-05-18 14:29:51 -0700101 R_n = R_64;
Simon Butcher0c790732016-10-05 14:09:11 +0100102 }
103 else
Brian Murray4e067032016-05-20 18:25:43 -0700104 {
Simon Butcher0c790732016-10-05 14:09:11 +0100105 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Brian Murray7c6476c2016-05-18 14:29:51 -0700106 }
107
Simon Butcher0c790732016-10-05 14:09:11 +0100108 for( i = blocksize - 1; i >= 0; i-- )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000109 {
Manuel Pégourié-Gonnard756bcf72016-01-13 11:28:16 +0000110 output[i] = input[i] << 1 | overflow;
111 overflow = input[i] >> 7;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000112 }
Manuel Pégourié-Gonnarda4dfa052016-01-13 11:00:47 +0000113
Manuel Pégourié-Gonnard89b8d832016-01-13 13:05:03 +0000114 /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
115 * using bit operations to avoid branches */
Simon Butcher0c790732016-10-05 14:09:11 +0100116
Manuel Pégourié-Gonnard89b8d832016-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 Butcher0c790732016-10-05 14:09:11 +0100128 output[ blocksize - 1 ] ^= R_n & mask;
129
Brian Murrayafdb60f2016-05-19 16:02:42 -0700130 return( 0 );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000131}
132
133/*
134 * Generate subkeys
Simon Butcher0c790732016-10-05 14:09:11 +0100135 *
136 * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000137 */
Simon Butcher0c790732016-10-05 14:09:11 +0100138static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx,
139 unsigned char* K1, unsigned char* K2 )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000140{
Brian Murray86ff9862016-05-19 16:38:36 -0700141 int ret;
Simon Butcherf394e092016-10-06 12:49:58 +0100142 unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX];
Brian Murray7c6476c2016-05-18 14:29:51 -0700143 size_t olen, block_size;
144
Simon Butcher0c790732016-10-05 14:09:11 +0100145 mbedtls_zeroize( L, sizeof( L ) );
Brian Murray7c6476c2016-05-18 14:29:51 -0700146
Simon Butcher0c790732016-10-05 14:09:11 +0100147 block_size = ctx->cipher_info->block_size;
148
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000149 /* Calculate Ek(0) */
Simon Butcher0c790732016-10-05 14:09:11 +0100150 if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 )
Brian Murray7c6476c2016-05-18 14:29:51 -0700151 goto exit;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000152
Manuel Pégourié-Gonnarda4dfa052016-01-13 11:00:47 +0000153 /*
Manuel Pégourié-Gonnard756bcf72016-01-13 11:28:16 +0000154 * Generate K1 and K2
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000155 */
Simon Butcher0c790732016-10-05 14:09:11 +0100156 if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 )
Brian Murray7c6476c2016-05-18 14:29:51 -0700157 goto exit;
Manuel Pégourié-Gonnarda4dfa052016-01-13 11:00:47 +0000158
Simon Butcher0c790732016-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 Cragie9bf1e5d2015-12-15 07:38:11 +0000166}
167
Simon Butcherf394e092016-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 Cragie9bf1e5d2015-12-15 07:38:11 +0000171{
Simon Butcher0c790732016-10-05 14:09:11 +0100172 size_t index;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000173
Simon Butcher0c790732016-10-05 14:09:11 +0100174 for( index = 0; index < block_size; index++ )
175 output[ index ] = input1[ index ] ^ input2[ index ];
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000176}
177
Manuel Pégourié-Gonnardda8724f2016-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 Butcherf394e092016-10-06 12:49:58 +0100184static void cmac_pad( unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX],
Brian Murray3d644312016-09-13 14:00:15 -0700185 size_t padded_block_len,
Manuel Pégourié-Gonnard2b0e21f2016-01-13 15:09:09 +0000186 const unsigned char *last_block,
Brian Murray7c6476c2016-05-18 14:29:51 -0700187 size_t last_block_len )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000188{
189 size_t j;
190
Brian Murray7c6476c2016-05-18 14:29:51 -0700191 for( j = 0; j < padded_block_len; j++ )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000192 {
Brian Murray7c6476c2016-05-18 14:29:51 -0700193 if( j < last_block_len )
Manuel Pégourié-Gonnardda8724f2016-01-13 13:14:04 +0000194 padded_block[j] = last_block[j];
Brian Murray7c6476c2016-05-18 14:29:51 -0700195 else if( j == last_block_len )
Manuel Pégourié-Gonnardda8724f2016-01-13 13:14:04 +0000196 padded_block[j] = 0x80;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000197 else
Manuel Pégourié-Gonnardda8724f2016-01-13 13:14:04 +0000198 padded_block[j] = 0x00;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000199 }
200}
201
Simon Butcher0c790732016-10-05 14:09:11 +0100202int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx,
Simon Butcher5805fbe2016-10-05 15:33:53 +0100203 const unsigned char *key, size_t keybits )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000204{
Simon Butcher0c790732016-10-05 14:09:11 +0100205 mbedtls_cipher_type_t type;
206 mbedtls_cmac_context_t *cmac_ctx;
Simon Butcher0c790732016-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 Butcher5805fbe2016-10-05 15:33:53 +0100212 if( ( retval = mbedtls_cipher_setkey( ctx, key, keybits,
Simon Butcher0c790732016-10-05 14:09:11 +0100213 MBEDTLS_ENCRYPT ) ) != 0 )
214 return( retval );
215
Simon Butcher0c790732016-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 Butcher0c790732016-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 Murray7c6476c2016-05-18 14:29:51 -0700246 unsigned char *state;
Andres AG8254b6c2016-10-06 15:23:39 +0100247 int n, j, ret = 0;
Simon Butcher0c790732016-10-05 14:09:11 +0100248 size_t olen, block_size;
Brian Murray7c6476c2016-05-18 14:29:51 -0700249
Simon Butcher0c790732016-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 Murray7c6476c2016-05-18 14:29:51 -0700253
Simon Butcher0c790732016-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 Cragie9bf1e5d2015-12-15 07:38:11 +0000257
Simon Butcherc61351d2016-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 Butcher0c790732016-10-05 14:09:11 +0100260 if( cmac_ctx->unprocessed_len > 0 &&
Andres AG8254b6c2016-10-06 15:23:39 +0100261 ilen > block_size - cmac_ctx->unprocessed_len )
Brian Murray86ff9862016-05-19 16:38:36 -0700262 {
Simon Butcher0c790732016-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 Butcherc61351d2016-10-10 21:37:42 +0100275 input += block_size - cmac_ctx->unprocessed_len;
276 ilen -= block_size - cmac_ctx->unprocessed_len;
Simon Butcher0c790732016-10-05 14:09:11 +0100277 cmac_ctx->unprocessed_len = 0;
Brian Murray86ff9862016-05-19 16:38:36 -0700278 }
279
Simon Butcher0c790732016-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 Murray86ff9862016-05-19 16:38:36 -0700285 {
Simon Butcher0c790732016-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 Murray86ff9862016-05-19 16:38:36 -0700294 }
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000295
Simon Butcher0c790732016-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 Butcherc61351d2016-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 Butcher0c790732016-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 Butcherf394e092016-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 Butcher0c790732016-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 Butcherf394e092016-10-06 12:49:58 +0100328 mbedtls_zeroize( K1, sizeof( K1 ) );
329 mbedtls_zeroize( K2, sizeof( K2 ) );
Simon Butcher0c790732016-10-05 14:09:11 +0100330 cmac_generate_subkeys( ctx, K1, K2 );
331
Simon Butcherf394e092016-10-06 12:49:58 +0100332 last_block = cmac_ctx->unprocessed_block;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000333
334 /* Calculate last block */
Janos Follath2b3b7402016-10-11 10:49:26 +0100335 if( cmac_ctx->unprocessed_len < block_size )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000336 {
Simon Butcher0c790732016-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 Cragie9bf1e5d2015-12-15 07:38:11 +0000339 }
340 else
341 {
Manuel Pégourié-Gonnard59ae4ba2016-01-13 14:27:55 +0000342 /* Last block is complete block */
Simon Butcher0c790732016-10-05 14:09:11 +0100343 cmac_xor_block( M_last, last_block, K1, block_size );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000344 }
345
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000346
Simon Butcher0c790732016-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 Cragie9bf1e5d2015-12-15 07:38:11 +0000353
Simon Butcher0c790732016-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 Butcherf394e092016-10-06 12:49:58 +0100359 mbedtls_zeroize( K1, sizeof( K1 ) );
360 mbedtls_zeroize( K2, sizeof( K2 ) );
Simon Butcher0c790732016-10-05 14:09:11 +0100361
362 cmac_ctx->unprocessed_len = 0;
363 mbedtls_zeroize( cmac_ctx->unprocessed_block,
Simon Butcherf394e092016-10-06 12:49:58 +0100364 sizeof( cmac_ctx->unprocessed_block ) );
Simon Butcher0c790732016-10-05 14:09:11 +0100365
Simon Butcherf394e092016-10-06 12:49:58 +0100366 mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX );
Simon Butcher0c790732016-10-05 14:09:11 +0100367 return( ret );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000368}
369
Simon Butcher0c790732016-10-05 14:09:11 +0100370int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000371{
Simon Butcher0c790732016-10-05 14:09:11 +0100372 mbedtls_cmac_context_t* cmac_ctx;
Manuel Pégourié-Gonnarda4dfa052016-01-13 11:00:47 +0000373
Simon Butcher0c790732016-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 Murray7c6476c2016-05-18 14:29:51 -0700376
Simon Butcher0c790732016-10-05 14:09:11 +0100377 cmac_ctx = ctx->cmac_ctx;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000378
Simon Butcher0c790732016-10-05 14:09:11 +0100379 /* Reset the internal state */
380 cmac_ctx->unprocessed_len = 0;
381 mbedtls_zeroize( cmac_ctx->unprocessed_block,
Andres AG8254b6c2016-10-06 15:23:39 +0100382 sizeof( cmac_ctx->unprocessed_block ) );
Simon Butcher21279322016-10-06 10:39:49 +0100383 mbedtls_zeroize( cmac_ctx->state,
384 sizeof( cmac_ctx->state ) );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000385
Simon Butcher0c790732016-10-05 14:09:11 +0100386 return( 0 );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000387}
388
Simon Butcher0c790732016-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 Butcher0c790732016-10-05 14:09:11 +0100406 if( ret != 0 )
407 goto exit;
Simon Butcher0c790732016-10-05 14:09:11 +0100408
409 ret = mbedtls_cipher_cmac_update( &ctx, input, ilen );
410 if( ret != 0 )
411 goto exit;
412
Simon Butcherf394e092016-10-06 12:49:58 +0100413 ret = mbedtls_cipher_cmac_finish( &ctx, output );
Simon Butcher0c790732016-10-05 14:09:11 +0100414
415exit:
Simon Butcherf394e092016-10-06 12:49:58 +0100416 mbedtls_cipher_free( &ctx );
417
Simon Butcher0c790732016-10-05 14:09:11 +0100418 return( ret );
419}
Simon Butcher0c790732016-10-05 14:09:11 +0100420
Simon Butcherf394e092016-10-06 12:49:58 +0100421#if defined(MBEDTLS_AES_C)
Manuel Pégourié-Gonnard2b0e21f2016-01-13 15:09:09 +0000422/*
Simon Butcherf394e092016-10-06 12:49:58 +0100423 * Implementation of AES-CMAC-PRF-128 defined in RFC 4615
Manuel Pégourié-Gonnard2b0e21f2016-01-13 15:09:09 +0000424 */
Brian Murray7c6476c2016-05-18 14:29:51 -0700425int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard9c83eeb2016-01-13 10:48:02 +0000426 const unsigned char *input, size_t in_len,
Simon Butcher0c790732016-10-05 14:09:11 +0100427 unsigned char *output )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000428{
429 int ret;
Simon Butcher0c790732016-10-05 14:09:11 +0100430 const mbedtls_cipher_info_t *cipher_info;
Simon Butcherf394e092016-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 Cragie9bf1e5d2015-12-15 07:38:11 +0000436
Simon Butcher0c790732016-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 Murray7c6476c2016-05-18 14:29:51 -0700444
Simon Butcherf394e092016-10-06 12:49:58 +0100445 if( key_length == MBEDTLS_AES_BLOCK_SIZE )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000446 {
447 /* Use key as is */
Simon Butcherf394e092016-10-06 12:49:58 +0100448 memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000449 }
450 else
451 {
Simon Butcherf394e092016-10-06 12:49:58 +0100452 memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE );
Manuel Pégourié-Gonnard2b0e21f2016-01-13 15:09:09 +0000453
Simon Butcher0c790732016-10-05 14:09:11 +0100454 ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key,
455 key_length, int_key );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000456 if( ret != 0 )
Brian Murray7c6476c2016-05-18 14:29:51 -0700457 goto exit;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000458 }
459
Simon Butcher0c790732016-10-05 14:09:11 +0100460 ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len,
461 output );
Manuel Pégourié-Gonnard28ea7912016-01-13 11:30:00 +0000462
Simon Butcher0c790732016-10-05 14:09:11 +0100463exit:
464 mbedtls_zeroize( int_key, sizeof( int_key ) );
Brian Murray7c6476c2016-05-18 14:29:51 -0700465
Simon Butcher0c790732016-10-05 14:09:11 +0100466 return( ret );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000467}
Brian Murrayafdb60f2016-05-19 16:02:42 -0700468#endif /* MBEDTLS_AES_C */
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000469
Simon Butcherf394e092016-10-06 12:49:58 +0100470#if defined(MBEDTLS_SELF_TEST)
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000471/*
Brian Murrayd666eb52016-05-19 15:59:23 -0700472 * CMAC test data from SP800-38B Appendix D.1 (corrected)
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000473 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
Brian Murrayd666eb52016-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 Cragie9bf1e5d2015-12-15 07:38:11 +0000477 */
478
Brian Murrayd666eb52016-05-19 15:59:23 -0700479#define NB_CMAC_TESTS_PER_KEY 4
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000480#define NB_PRF_TESTS 3
Simon Butcher0c790732016-10-05 14:09:11 +0100481
Brian Murrayd666eb52016-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 Cragie9bf1e5d2015-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 Butcherf394e092016-10-06 12:49:58 +0100494#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */
Brian Murrayfe9ff012016-05-23 12:49:50 -0700495
Simon Butcherf394e092016-10-06 12:49:58 +0100496#if defined(MBEDTLS_AES_C)
Brian Murrayd666eb52016-05-19 15:59:23 -0700497/* Truncation point of message for AES CMAC tests */
Brian Murray86ff9862016-05-19 16:38:36 -0700498static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murrayd666eb52016-05-19 15:59:23 -0700499 0,
500 16,
501 40,
502 64
503};
504
505/* AES 128 CMAC Test Data */
Brian Murray86ff9862016-05-19 16:38:36 -0700506static const unsigned char aes_128_key[16] = {
Brian Murrayd666eb52016-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 Butcherf394e092016-10-06 12:49:58 +0100510static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murrayd666eb52016-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 Butcherf394e092016-10-06 12:49:58 +0100520static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
Robert Cragie9bf1e5d2015-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 Murrayd666eb52016-05-19 15:59:23 -0700539/* AES 192 CMAC Test Data */
Brian Murray86ff9862016-05-19 16:38:36 -0700540static const unsigned char aes_192_key[24] = {
Brian Murray6eae89b2016-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 Cragie9bf1e5d2015-12-15 07:38:11 +0000544};
Simon Butcherf394e092016-10-06 12:49:58 +0100545static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murray7c6476c2016-05-18 14:29:51 -0700546 {
Brian Murrayd666eb52016-05-19 15:59:23 -0700547 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
548 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
Brian Murray7c6476c2016-05-18 14:29:51 -0700549 },
550 {
Brian Murrayd666eb52016-05-19 15:59:23 -0700551 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
552 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
Brian Murray7c6476c2016-05-18 14:29:51 -0700553 }
554};
Simon Butcherf394e092016-10-06 12:49:58 +0100555static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murray7c6476c2016-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 Murrayd666eb52016-05-19 15:59:23 -0700574/* AES 256 CMAC Test Data */
Brian Murray86ff9862016-05-19 16:38:36 -0700575static const unsigned char aes_256_key[32] = {
Brian Murray6eae89b2016-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 Murrayd666eb52016-05-19 15:59:23 -0700580};
Simon Butcherf394e092016-10-06 12:49:58 +0100581static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murrayd666eb52016-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 Butcherf394e092016-10-06 12:49:58 +0100591static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murrayd666eb52016-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 Butcherf394e092016-10-06 12:49:58 +0100611#if defined(MBEDTLS_DES_C)
Brian Murrayd666eb52016-05-19 15:59:23 -0700612/* Truncation point of message for 3DES CMAC tests */
Brian Murray86ff9862016-05-19 16:38:36 -0700613static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murrayd666eb52016-05-19 15:59:23 -0700614 0,
615 8,
616 20,
617 32
618};
619
620/* 3DES 2 Key CMAC Test Data */
Brian Murray86ff9862016-05-19 16:38:36 -0700621static const unsigned char des3_2key_key[24] = {
Brian Murray6eae89b2016-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 Murrayd666eb52016-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 Butcherf394e092016-10-06 12:49:58 +0100634static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = {
Brian Murray7c6476c2016-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 Murrayd666eb52016-05-19 15:59:23 -0700649/* 3DES 3 Key CMAC Test Data */
Brian Murray86ff9862016-05-19 16:38:36 -0700650static const unsigned char des3_3key_key[24] = {
Brian Murray6eae89b2016-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 Murrayd666eb52016-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 Butcherf394e092016-10-06 12:49:58 +0100663static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = {
Brian Murray7c6476c2016-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 Murrayd666eb52016-05-19 15:59:23 -0700678#endif /* MBEDTLS_DES_C */
Brian Murray7c6476c2016-05-18 14:29:51 -0700679
Simon Butcherf394e092016-10-06 12:49:58 +0100680#if defined(MBEDTLS_AES_C)
Brian Murrayd666eb52016-05-19 15:59:23 -0700681/* AES AES-CMAC-PRF-128 Test Data */
Robert Cragie9bf1e5d2015-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é-Gonnarda4dfa052016-01-13 11:00:47 +0000699 0x10, 0x11, 0x12, 0x13
Robert Cragie9bf1e5d2015-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 Murrayd666eb52016-05-19 15:59:23 -0700716#endif /* MBEDTLS_AES_C */
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000717
Simon Butcher0c790732016-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 Butcherf394e092016-10-06 12:49:58 +0100730 unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
731 unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
Simon Butcher0c790732016-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 Butcherf394e092016-10-06 12:49:58 +0100737 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
Simon Butcher0c790732016-10-05 14:09:11 +0100738 }
739
Simon Butcherf394e092016-10-06 12:49:58 +0100740 mbedtls_cipher_init( &ctx );
741
Simon Butcher0c790732016-10-05 14:09:11 +0100742 for( i = 0; i < num_tests; i++ )
743 {
744 if( verbose != 0 )
Simon Butcherf394e092016-10-06 12:49:58 +0100745 mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 );
Simon Butcher0c790732016-10-05 14:09:11 +0100746
747 if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
748 {
749 if( verbose != 0 )
750 mbedtls_printf( "test execution failed\n" );
751
752 goto exit;
753 }
754
755 if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits,
756 MBEDTLS_ENCRYPT ) ) != 0 )
757 {
758 if( verbose != 0 )
759 mbedtls_printf( "test execution failed\n" );
760
761 goto exit;
762 }
763
764 ret = cmac_generate_subkeys( &ctx, K1, K2 );
765 if( ret != 0 )
766 {
767 if( verbose != 0 )
768 mbedtls_printf( "failed\n" );
769 goto exit;
770 }
771
Simon Butcherad882672016-10-07 12:55:43 +0100772 if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 ||
773 ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 )
Simon Butcher0c790732016-10-05 14:09:11 +0100774 {
775 if( verbose != 0 )
776 mbedtls_printf( "failed\n" );
777 goto exit;
778 }
779
780 if( verbose != 0 )
781 mbedtls_printf( "passed\n" );
782 }
783
784exit:
Simon Butcherf394e092016-10-06 12:49:58 +0100785 mbedtls_cipher_free( &ctx );
786
Simon Butcher0c790732016-10-05 14:09:11 +0100787 return( ret );
788}
789
Simon Butcherf394e092016-10-06 12:49:58 +0100790static int cmac_test_wth_cipher( int verbose,
791 const char* testname,
792 const unsigned char* key,
793 int keybits,
794 const unsigned char* messages,
795 const unsigned int message_lengths[4],
796 const unsigned char* expected_result,
797 mbedtls_cipher_type_t cipher_type,
798 int block_size,
799 int num_tests )
Brian Murray3c0412a2016-05-19 14:23:50 -0700800{
Simon Butcher0c790732016-10-05 14:09:11 +0100801 const mbedtls_cipher_info_t *cipher_info;
Brian Murray3c0412a2016-05-19 14:23:50 -0700802 int i, ret;
Simon Butcherf394e092016-10-06 12:49:58 +0100803 unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX];
Brian Murray86ff9862016-05-19 16:38:36 -0700804
Simon Butcher0c790732016-10-05 14:09:11 +0100805 cipher_info = mbedtls_cipher_info_from_type( cipher_type );
806 if( cipher_info == NULL )
Brian Murray3c0412a2016-05-19 14:23:50 -0700807 {
Simon Butcher0c790732016-10-05 14:09:11 +0100808 /* Failing at this point must be due to a build issue */
809 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
Brian Murray3c0412a2016-05-19 14:23:50 -0700810 goto exit;
811 }
812
813 for( i = 0; i < num_tests; i++ )
814 {
815 if( verbose != 0 )
Andres AG8254b6c2016-10-06 15:23:39 +0100816 mbedtls_printf( " %s CMAC #%u: ", testname, i + 1 );
Brian Murray3c0412a2016-05-19 14:23:50 -0700817
Simon Butcher0c790732016-10-05 14:09:11 +0100818 if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages,
819 message_lengths[i], output ) ) != 0 )
Brian Murray3c0412a2016-05-19 14:23:50 -0700820 {
821 if( verbose != 0 )
822 mbedtls_printf( "failed\n" );
823 goto exit;
824 }
Brian Murray0b21cdf2016-05-24 22:46:43 -0700825
Simon Butcher0c790732016-10-05 14:09:11 +0100826 if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 )
Brian Murray3c0412a2016-05-19 14:23:50 -0700827 {
828 if( verbose != 0 )
829 mbedtls_printf( "failed\n" );
830 goto exit;
831 }
832
Brian Murray0b21cdf2016-05-24 22:46:43 -0700833 if( verbose != 0 )
834 mbedtls_printf( "passed\n" );
Brian Murray3c0412a2016-05-19 14:23:50 -0700835 }
Simon Butcher0c790732016-10-05 14:09:11 +0100836
Simon Butcherf394e092016-10-06 12:49:58 +0100837exit:
Simon Butcher0c790732016-10-05 14:09:11 +0100838 return( ret );
Brian Murray3c0412a2016-05-19 14:23:50 -0700839}
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000840
Simon Butcherf394e092016-10-06 12:49:58 +0100841#if defined(MBEDTLS_AES_C)
842static int test_aes128_cmac_prf( int verbose )
Brian Murray4e067032016-05-20 18:25:43 -0700843{
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000844 int i;
845 int ret;
Simon Butcherf394e092016-10-06 12:49:58 +0100846 unsigned char output[MBEDTLS_AES_BLOCK_SIZE];
Simon Butcher0c790732016-10-05 14:09:11 +0100847
Brian Murray7c6476c2016-05-18 14:29:51 -0700848 for( i = 0; i < NB_PRF_TESTS; i++ )
849 {
Brian Murrayd666eb52016-05-19 15:59:23 -0700850 mbedtls_printf( " AES CMAC 128 PRF #%u: ", i );
Simon Butcher0c790732016-10-05 14:09:11 +0100851 ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output );
Brian Murray7c6476c2016-05-18 14:29:51 -0700852 if( ret != 0 ||
Simon Butcherf394e092016-10-06 12:49:58 +0100853 memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 )
Brian Murray7c6476c2016-05-18 14:29:51 -0700854 {
Simon Butcher0c790732016-10-05 14:09:11 +0100855
Brian Murray7c6476c2016-05-18 14:29:51 -0700856 if( verbose != 0 )
857 mbedtls_printf( "failed\n" );
858
Brian Murrayd666eb52016-05-19 15:59:23 -0700859 return( ret );
Simon Butcherf394e092016-10-06 12:49:58 +0100860 }
861 else if( verbose != 0 )
Brian Murray7c6476c2016-05-18 14:29:51 -0700862 {
863 mbedtls_printf( "passed\n" );
864 }
865 }
Brian Murrayd666eb52016-05-19 15:59:23 -0700866 return( ret );
867}
868#endif /* MBEDTLS_AES_C */
869
870int mbedtls_cmac_self_test( int verbose )
871{
872 int ret;
Simon Butcher0c790732016-10-05 14:09:11 +0100873
Simon Butcherf394e092016-10-06 12:49:58 +0100874#if defined(MBEDTLS_AES_C)
Simon Butcher0c790732016-10-05 14:09:11 +0100875 /* AES-128 */
876 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcherf394e092016-10-06 12:49:58 +0100877 "AES 128",
878 aes_128_key,
879 128,
880 (const unsigned char*)aes_128_subkeys,
881 MBEDTLS_CIPHER_AES_128_ECB,
882 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcherad882672016-10-07 12:55:43 +0100883 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher0c790732016-10-05 14:09:11 +0100884 {
885 return( ret );
886 }
887
Brian Murraybbed6602016-05-23 15:01:59 -0700888 if( ( ret = cmac_test_wth_cipher( verbose,
889 "AES 128",
890 aes_128_key,
891 128,
892 test_message,
893 aes_message_lengths,
Simon Butcherf394e092016-10-06 12:49:58 +0100894 (const unsigned char*)aes_128_expected_result,
Simon Butcher0c790732016-10-05 14:09:11 +0100895 MBEDTLS_CIPHER_AES_128_ECB,
Simon Butcherf394e092016-10-06 12:49:58 +0100896 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcherad882672016-10-07 12:55:43 +0100897 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher0c790732016-10-05 14:09:11 +0100898 {
899 return( ret );
900 }
901
902 /* AES-192 */
903 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcherf394e092016-10-06 12:49:58 +0100904 "AES 192",
905 aes_192_key,
906 192,
907 (const unsigned char*)aes_192_subkeys,
908 MBEDTLS_CIPHER_AES_192_ECB,
909 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcherad882672016-10-07 12:55:43 +0100910 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray3d3c9b82016-05-19 16:36:56 -0700911 {
912 return( ret );
913 }
Brian Murrayd666eb52016-05-19 15:59:23 -0700914
Brian Murraybbed6602016-05-23 15:01:59 -0700915 if( ( ret = cmac_test_wth_cipher( verbose,
916 "AES 192",
917 aes_192_key,
918 192,
919 test_message,
920 aes_message_lengths,
Simon Butcherf394e092016-10-06 12:49:58 +0100921 (const unsigned char*)aes_192_expected_result,
Simon Butcher0c790732016-10-05 14:09:11 +0100922 MBEDTLS_CIPHER_AES_192_ECB,
Simon Butcherf394e092016-10-06 12:49:58 +0100923 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcherad882672016-10-07 12:55:43 +0100924 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher0c790732016-10-05 14:09:11 +0100925 {
Simon Butcher0c790732016-10-05 14:09:11 +0100926 return( ret );
927 }
928
929 /* AES-256 */
930 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcherf394e092016-10-06 12:49:58 +0100931 "AES 256",
932 aes_256_key,
933 256,
934 (const unsigned char*)aes_256_subkeys,
935 MBEDTLS_CIPHER_AES_256_ECB,
936 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcherad882672016-10-07 12:55:43 +0100937 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray3d3c9b82016-05-19 16:36:56 -0700938 {
939 return( ret );
940 }
Brian Murrayd666eb52016-05-19 15:59:23 -0700941
Simon Butcherf394e092016-10-06 12:49:58 +0100942 if( ( ret = cmac_test_wth_cipher ( verbose,
Brian Murraybbed6602016-05-23 15:01:59 -0700943 "AES 256",
944 aes_256_key,
945 256,
946 test_message,
947 aes_message_lengths,
Simon Butcherf394e092016-10-06 12:49:58 +0100948 (const unsigned char*)aes_256_expected_result,
Simon Butcher0c790732016-10-05 14:09:11 +0100949 MBEDTLS_CIPHER_AES_256_ECB,
Simon Butcherf394e092016-10-06 12:49:58 +0100950 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcherad882672016-10-07 12:55:43 +0100951 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray3d3c9b82016-05-19 16:36:56 -0700952 {
953 return( ret );
954 }
Brian Murrayd666eb52016-05-19 15:59:23 -0700955#endif /* MBEDTLS_AES_C */
956
Simon Butcherf394e092016-10-06 12:49:58 +0100957#if defined(MBEDTLS_DES_C)
Simon Butcher0c790732016-10-05 14:09:11 +0100958 /* 3DES 2 key */
959 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcherf394e092016-10-06 12:49:58 +0100960 "3DES 2 key",
961 des3_2key_key,
962 192,
963 (const unsigned char*)des3_2key_subkeys,
964 MBEDTLS_CIPHER_DES_EDE3_ECB,
965 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcherad882672016-10-07 12:55:43 +0100966 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher0c790732016-10-05 14:09:11 +0100967 {
968 return( ret );
969 }
970
Brian Murraybbed6602016-05-23 15:01:59 -0700971 if( ( ret = cmac_test_wth_cipher( verbose,
972 "3DES 2 key",
973 des3_2key_key,
974 192,
975 test_message,
976 des3_message_lengths,
Simon Butcherf394e092016-10-06 12:49:58 +0100977 (const unsigned char*)des3_2key_expected_result,
Simon Butcher0c790732016-10-05 14:09:11 +0100978 MBEDTLS_CIPHER_DES_EDE3_ECB,
Simon Butcherf394e092016-10-06 12:49:58 +0100979 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcherad882672016-10-07 12:55:43 +0100980 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray3d3c9b82016-05-19 16:36:56 -0700981 {
982 return( ret );
983 }
Brian Murrayd666eb52016-05-19 15:59:23 -0700984
Simon Butcher0c790732016-10-05 14:09:11 +0100985 /* 3DES 3 key */
986 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcherf394e092016-10-06 12:49:58 +0100987 "3DES 3 key",
988 des3_3key_key,
989 192,
990 (const unsigned char*)des3_3key_subkeys,
991 MBEDTLS_CIPHER_DES_EDE3_ECB,
992 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcherad882672016-10-07 12:55:43 +0100993 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher0c790732016-10-05 14:09:11 +0100994 {
995 return( ret );
996 }
997
Brian Murraybbed6602016-05-23 15:01:59 -0700998 if( ( ret = cmac_test_wth_cipher( verbose,
999 "3DES 3 key",
1000 des3_3key_key,
1001 192,
1002 test_message,
1003 des3_message_lengths,
Simon Butcherf394e092016-10-06 12:49:58 +01001004 (const unsigned char*)des3_3key_expected_result,
Simon Butcher0c790732016-10-05 14:09:11 +01001005 MBEDTLS_CIPHER_DES_EDE3_ECB,
Simon Butcherf394e092016-10-06 12:49:58 +01001006 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcherad882672016-10-07 12:55:43 +01001007 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray3d3c9b82016-05-19 16:36:56 -07001008 {
1009 return( ret );
1010 }
Brian Murrayd666eb52016-05-19 15:59:23 -07001011#endif /* MBEDTLS_DES_C */
1012
Simon Butcherf394e092016-10-06 12:49:58 +01001013#if defined(MBEDTLS_AES_C)
Simon Butcherad882672016-10-07 12:55:43 +01001014 if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 )
Brian Murray3d3c9b82016-05-19 16:36:56 -07001015 return( ret );
Brian Murrayd666eb52016-05-19 15:59:23 -07001016#endif /* MBEDTLS_AES_C */
Brian Murray7c6476c2016-05-18 14:29:51 -07001017
Robert Cragie9bf1e5d2015-12-15 07:38:11 +00001018 if( verbose != 0 )
1019 mbedtls_printf( "\n" );
Brian Murrayd666eb52016-05-19 15:59:23 -07001020
Robert Cragie9bf1e5d2015-12-15 07:38:11 +00001021 return( 0 );
1022}
1023
Brian Murrayd666eb52016-05-19 15:59:23 -07001024#endif /* MBEDTLS_SELF_TEST */
Robert Cragie9bf1e5d2015-12-15 07:38:11 +00001025
1026#endif /* MBEDTLS_CMAC_C */