blob: 5a6206ea9d08ac230da565a3a9c3ac36809b9385 [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 *
Brian Murray53e23b62016-09-13 14:00:15 -07004 * \brief NIST SP800-38B compliant CMAC implementation
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 Butcher327398a2016-10-05 14:09:11 +010062#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || \
63 defined(MBEDTLS_DES_C) )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000064#include <stdio.h>
Brian Murray8b4111c2016-09-13 15:58:46 -070065#define mbedtls_printf printf
Simon Butcher327398a2016-10-05 14:09:11 +010066#endif /* defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) ||
67 * defined(MBEDTLS_DES_C) )*/
Robert Cragie3d23b1d2015-12-15 07:38:11 +000068#endif /* MBEDTLS_PLATFORM_C */
Brian Murray8b4111c2016-09-13 15:58:46 -070069
Robert Cragie3d23b1d2015-12-15 07:38:11 +000070/* Implementation that should never be optimized out by the compiler */
71static void mbedtls_zeroize( void *v, size_t n ) {
Simon Butcher327398a2016-10-05 14:09:11 +010072 volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
Robert Cragie3d23b1d2015-12-15 07:38:11 +000073}
74
75/*
Brian Murrayb0c3c432016-05-18 14:29:51 -070076 * Multiplication by u in the Galois field of GF(2^n)
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000077 *
Brian Murray72b69e32016-09-13 14:21:01 -070078 * As explained in NIST SP 800-38B, this can be computed:
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000079 *
Simon Butcher327398a2016-10-05 14:09:11 +010080 * If MSB(p) = 0, then p = (p << 1)
81 * If MSB(p) = 1, then p = (p << 1) ^ R_n
82 * with R_64 = 0x1B and R_128 = 0x87
83 *
84 * Input and output MUST NOT point to the same buffer
Brian Murrayb0c3c432016-05-18 14:29:51 -070085 * Block size must be 8 byes or 16 bytes.
Robert Cragie3d23b1d2015-12-15 07:38:11 +000086 */
Brian Murrayb0c3c432016-05-18 14:29:51 -070087static int cmac_multiply_by_u( unsigned char *output,
88 const unsigned char *input,
Brian Murray53e23b62016-09-13 14:00:15 -070089 size_t blocksize )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000090{
Brian Murrayb0c3c432016-05-18 14:29:51 -070091 const unsigned char R_128 = 0x87;
92 const unsigned char R_64 = 0x1B;
93 unsigned char R_n, mask;
94 unsigned char overflow = 0x00;
Simon Butcher327398a2016-10-05 14:09:11 +010095 int i;
Brian Murrayb0c3c432016-05-18 14:29:51 -070096
Brian Murray6a3c0d22016-05-20 18:25:43 -070097 if( blocksize == 16 )
98 {
Brian Murrayb0c3c432016-05-18 14:29:51 -070099 R_n = R_128;
Simon Butcher327398a2016-10-05 14:09:11 +0100100 }
101 else if( blocksize == 8 )
Brian Murray6a3c0d22016-05-20 18:25:43 -0700102 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700103 R_n = R_64;
Simon Butcher327398a2016-10-05 14:09:11 +0100104 }
105 else
Brian Murray6a3c0d22016-05-20 18:25:43 -0700106 {
Simon Butcher327398a2016-10-05 14:09:11 +0100107 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700108 }
109
Simon Butcher327398a2016-10-05 14:09:11 +0100110 for( i = blocksize - 1; i >= 0; i-- )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000111 {
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000112 output[i] = input[i] << 1 | overflow;
113 overflow = input[i] >> 7;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000114 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000115
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +0000116 /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
117 * using bit operations to avoid branches */
Simon Butcher327398a2016-10-05 14:09:11 +0100118
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +0000119 /* MSVC has a warning about unary minus on unsigned, but this is
120 * well-defined and precisely what we want to do here */
121#if defined(_MSC_VER)
122#pragma warning( push )
123#pragma warning( disable : 4146 )
124#endif
125 mask = - ( input[0] >> 7 );
126#if defined(_MSC_VER)
127#pragma warning( pop )
128#endif
129
Simon Butcher327398a2016-10-05 14:09:11 +0100130 output[ blocksize - 1 ] ^= R_n & mask;
131
Brian Murrayb439d452016-05-19 16:02:42 -0700132 return( 0 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000133}
134
135/*
136 * Generate subkeys
Simon Butcher327398a2016-10-05 14:09:11 +0100137 *
138 * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000139 */
Simon Butcher327398a2016-10-05 14:09:11 +0100140static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx,
141 unsigned char* K1, unsigned char* K2 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000142{
Brian Murray57863ad2016-05-19 16:38:36 -0700143 int ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100144 unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700145 size_t olen, block_size;
146
Simon Butcher327398a2016-10-05 14:09:11 +0100147 mbedtls_zeroize( L, sizeof( L ) );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700148
Simon Butcher327398a2016-10-05 14:09:11 +0100149 block_size = ctx->cipher_info->block_size;
150
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000151 /* Calculate Ek(0) */
Simon Butcher327398a2016-10-05 14:09:11 +0100152 if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700153 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000154
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000155 /*
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000156 * Generate K1 and K2
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000157 */
Simon Butcher327398a2016-10-05 14:09:11 +0100158 if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700159 goto exit;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000160
Simon Butcher327398a2016-10-05 14:09:11 +0100161 if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 )
162 goto exit;
163
164exit:
165 mbedtls_zeroize( L, sizeof( L ) );
166
167 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000168}
169
Simon Butcher327398a2016-10-05 14:09:11 +0100170static void cmac_xor_block(unsigned char *output, const unsigned char *input1,
171 const unsigned char *input2, const size_t block_size )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000172{
Simon Butcher327398a2016-10-05 14:09:11 +0100173 size_t index;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000174
Simon Butcher327398a2016-10-05 14:09:11 +0100175 for( index = 0; index < block_size; index++ )
176 output[ index ] = input1[ index ] ^ input2[ index ];
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000177}
178
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000179/*
180 * Create padded last block from (partial) last block.
181 *
182 * We can't use the padding option from the cipher layer, as it only works for
183 * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
184 */
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000185static void cmac_pad( unsigned char padded_block[16],
Brian Murray53e23b62016-09-13 14:00:15 -0700186 size_t padded_block_len,
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000187 const unsigned char *last_block,
Brian Murrayb0c3c432016-05-18 14:29:51 -0700188 size_t last_block_len )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000189{
190 size_t j;
191
Brian Murrayb0c3c432016-05-18 14:29:51 -0700192 for( j = 0; j < padded_block_len; j++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000193 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700194 if( j < last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000195 padded_block[j] = last_block[j];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700196 else if( j == last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000197 padded_block[j] = 0x80;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000198 else
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000199 padded_block[j] = 0x00;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000200 }
201}
202
Simon Butcher327398a2016-10-05 14:09:11 +0100203int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx,
Simon Butcher94ffde72016-10-05 15:33:53 +0100204 const unsigned char *key, size_t keybits )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000205{
Simon Butcher327398a2016-10-05 14:09:11 +0100206 mbedtls_cipher_type_t type;
207 mbedtls_cmac_context_t *cmac_ctx;
208 unsigned int block_size;
209 int retval;
210
211 if( ctx == NULL || ctx->cipher_info == NULL || key == NULL )
212 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
213
Simon Butcher94ffde72016-10-05 15:33:53 +0100214 if( ( retval = mbedtls_cipher_setkey( ctx, key, keybits,
Simon Butcher327398a2016-10-05 14:09:11 +0100215 MBEDTLS_ENCRYPT ) ) != 0 )
216 return( retval );
217
218 block_size = ctx->cipher_info->block_size;
219 type = ctx->cipher_info->type;
220
221 switch( type )
222 {
223 case MBEDTLS_CIPHER_AES_128_ECB:
224 case MBEDTLS_CIPHER_AES_192_ECB:
225 case MBEDTLS_CIPHER_AES_256_ECB:
226 case MBEDTLS_CIPHER_DES_EDE3_ECB:
227 break;
228 default:
229 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
230 }
231
232 /* Allocated and initialise in the cipher context memory for the CMAC
233 * context */
234 cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) );
235 if( cmac_ctx == NULL )
236 return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
237
238 ctx->cmac_ctx = cmac_ctx;
239
240 mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) );
241 cmac_ctx->padding_flag = 1;
242
243 return 0;
244}
245
246int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx,
247 const unsigned char *input, size_t ilen )
248{
249 mbedtls_cmac_context_t* cmac_ctx;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700250 unsigned char *state;
Simon Butcher327398a2016-10-05 14:09:11 +0100251 int n, j, ret = 0;
252 size_t olen, block_size;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700253
Simon Butcher327398a2016-10-05 14:09:11 +0100254 if( ctx == NULL || ctx->cipher_info == NULL || input == NULL ||
255 ctx->cmac_ctx == NULL )
256 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700257
Simon Butcher327398a2016-10-05 14:09:11 +0100258 cmac_ctx = ctx->cmac_ctx;
259 block_size = ctx->cipher_info->block_size;
260 state = ctx->cmac_ctx->state;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000261
Simon Butcher327398a2016-10-05 14:09:11 +0100262 /* Is their data still to process from the last call, that's equal to
263 * or greater than a block? */
264 if( cmac_ctx->unprocessed_len > 0 &&
265 ilen + cmac_ctx->unprocessed_len > block_size )
Brian Murray57863ad2016-05-19 16:38:36 -0700266 {
Simon Butcher327398a2016-10-05 14:09:11 +0100267 memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
268 input,
269 block_size - cmac_ctx->unprocessed_len );
270
271 cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size );
272
273 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
274 &olen ) ) != 0 )
275 {
276 goto exit;
277 }
278
279 ilen -= block_size;
280 input += cmac_ctx->unprocessed_len;
281
282 cmac_ctx->unprocessed_len = 0;
Brian Murray57863ad2016-05-19 16:38:36 -0700283 }
284
Simon Butcher327398a2016-10-05 14:09:11 +0100285 /* n is the number of blocks including any final partial block */
286 n = ( ilen + block_size - 1 ) / block_size;
287
288 /* Iterate across the input data in block sized chunks */
289 for( j = 0; j < n - 1; j++ )
Brian Murray57863ad2016-05-19 16:38:36 -0700290 {
Simon Butcher327398a2016-10-05 14:09:11 +0100291 //char *ptr = input + block_size * j ;
292 cmac_xor_block( state, input, state, block_size );
293
294 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
295 &olen ) ) != 0 )
296 goto exit;
297
298 ilen -= block_size;
299 input += block_size;
300
301 cmac_ctx->padding_flag = 0;
Brian Murray57863ad2016-05-19 16:38:36 -0700302 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000303
Simon Butcher327398a2016-10-05 14:09:11 +0100304 /* If there is data left over that wasn't aligned to a block */
305 if( ilen > 0 )
306 {
307 memcpy( &cmac_ctx->unprocessed_block, input, ilen );
308 cmac_ctx->unprocessed_len = ilen;
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000309
Simon Butcher327398a2016-10-05 14:09:11 +0100310 if( ilen % block_size > 0 )
311 cmac_ctx->padding_flag = 1;
312 else
313 cmac_ctx->padding_flag = 0;
314 }
315
316exit:
317 return( ret );
318}
319
320int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx,
321 unsigned char *output )
322{
323 mbedtls_cmac_context_t* cmac_ctx;
324 unsigned char *state;
325 unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE];
326 unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE];
327 unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE];
328 int ret;
329 size_t olen, block_size;
330
331 if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ||
332 output == NULL )
333 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
334
335 cmac_ctx = ctx->cmac_ctx;
336 block_size = ctx->cipher_info->block_size;
337 state = cmac_ctx->state;
338
339 mbedtls_zeroize( K1, sizeof(K1) );
340 mbedtls_zeroize( K2, sizeof(K2) );
341 cmac_generate_subkeys( ctx, K1, K2 );
342
343// mbedtls_zeroize( M_last, sizeof(M_last) );
344// if( cmac_ctx->unprocessed_len > 0 )
345// needs_padding = 1;
346
347 unsigned char *last_block = cmac_ctx->unprocessed_block;
348 //unsigned char *M_last = cmac_ctx->unprocessed_block;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000349
350 /* Calculate last block */
Simon Butcher327398a2016-10-05 14:09:11 +0100351 if( cmac_ctx->padding_flag )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000352 {
Simon Butcher327398a2016-10-05 14:09:11 +0100353 cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len );
354 cmac_xor_block( M_last, M_last, K2, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000355 }
356 else
357 {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000358 /* Last block is complete block */
Simon Butcher327398a2016-10-05 14:09:11 +0100359 cmac_xor_block( M_last, last_block, K1, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000360 }
361
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000362
Simon Butcher327398a2016-10-05 14:09:11 +0100363 cmac_xor_block( state, M_last, state, block_size );
364 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
365 &olen ) ) != 0 )
366 {
367 goto exit;
368 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000369
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000370
Simon Butcher327398a2016-10-05 14:09:11 +0100371
372 memcpy( output, state, block_size );
373
374exit:
375 /* Wipe the generated keys on the stack, and any other transients to avoid
376 * side channel leakage */
377 mbedtls_zeroize( K1, sizeof(K1) );
378 mbedtls_zeroize( K2, sizeof(K2) );
379
380 cmac_ctx->unprocessed_len = 0;
381 mbedtls_zeroize( cmac_ctx->unprocessed_block,
382 sizeof( cmac_ctx->unprocessed_len ) );
383
384 mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE );
385 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000386}
387
Simon Butcher327398a2016-10-05 14:09:11 +0100388int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000389{
Simon Butcher327398a2016-10-05 14:09:11 +0100390 mbedtls_cmac_context_t* cmac_ctx;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000391
Simon Butcher327398a2016-10-05 14:09:11 +0100392 if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL )
393 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700394
Simon Butcher327398a2016-10-05 14:09:11 +0100395 cmac_ctx = ctx->cmac_ctx;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000396
Simon Butcher327398a2016-10-05 14:09:11 +0100397 /* Reset the internal state */
398 cmac_ctx->unprocessed_len = 0;
399 mbedtls_zeroize( cmac_ctx->unprocessed_block,
400 sizeof( cmac_ctx->unprocessed_len ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000401
Simon Butcher327398a2016-10-05 14:09:11 +0100402 cmac_ctx->padding_flag = 1;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000403
Simon Butcher327398a2016-10-05 14:09:11 +0100404 return( 0 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000405}
406
Simon Butcher327398a2016-10-05 14:09:11 +0100407int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info,
408 const unsigned char *key, size_t keylen,
409 const unsigned char *input, size_t ilen,
410 unsigned char *output )
411{
412 mbedtls_cipher_context_t ctx;
413 int ret;
414
415 if( cipher_info == NULL || key == NULL || input == NULL || output == NULL )
416 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
417
418 mbedtls_cipher_init( &ctx );
419
420 if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
421 goto exit;
422
423 ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen );
424
425 if( ret != 0 )
426 goto exit;
427 // Are we leaking here? Should we reset or free?
428
429 ret = mbedtls_cipher_cmac_update( &ctx, input, ilen );
430 if( ret != 0 )
431 goto exit;
432
433 mbedtls_cipher_cmac_finish( &ctx, output );
434 if( ret != 0 )
435 goto exit;
436
437exit:
438 return( ret );
439}
Brian Murrayb439d452016-05-19 16:02:42 -0700440#ifdef MBEDTLS_AES_C
Simon Butcher327398a2016-10-05 14:09:11 +0100441
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000442/*
Simon Butcher327398a2016-10-05 14:09:11 +0100443// TODO - clean up comments
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000444 * PRF based on CMAC with AES-128
Brian Murrayb0c3c432016-05-18 14:29:51 -0700445 * See RFC 4615
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000446 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700447int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000448 const unsigned char *input, size_t in_len,
Simon Butcher327398a2016-10-05 14:09:11 +0100449 unsigned char *output )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000450{
451 int ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100452 const mbedtls_cipher_info_t *cipher_info;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000453 unsigned char zero_key[16];
454 unsigned char int_key[16];
455
Simon Butcher327398a2016-10-05 14:09:11 +0100456 cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB );
457 if( cipher_info == NULL )
458 {
459 /* Failing at this point must be due to a build issue */
460 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
461 goto exit;
462 }
Brian Murrayb0c3c432016-05-18 14:29:51 -0700463
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000464 if( key_length == 16 )
465 {
466 /* Use key as is */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000467 memcpy( int_key, key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000468 }
469 else
470 {
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000471 memset( zero_key, 0, 16 );
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000472
Simon Butcher327398a2016-10-05 14:09:11 +0100473 ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key,
474 key_length, int_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000475 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700476 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000477 }
478
Simon Butcher327398a2016-10-05 14:09:11 +0100479 ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len,
480 output );
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000481
Simon Butcher327398a2016-10-05 14:09:11 +0100482exit:
483 mbedtls_zeroize( int_key, sizeof( int_key ) );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700484
Simon Butcher327398a2016-10-05 14:09:11 +0100485 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000486}
Brian Murrayb439d452016-05-19 16:02:42 -0700487#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000488
Brian Murray0f6af732016-05-19 15:59:23 -0700489#ifdef MBEDTLS_SELF_TEST
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000490/*
Brian Murray0f6af732016-05-19 15:59:23 -0700491 * CMAC test data from SP800-38B Appendix D.1 (corrected)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000492 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
Brian Murray0f6af732016-05-19 15:59:23 -0700493 *
494 * AES-CMAC-PRF-128 test data from RFC 4615
495 * https://tools.ietf.org/html/rfc4615#page-4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000496 */
497
Brian Murray0f6af732016-05-19 15:59:23 -0700498#define NB_CMAC_TESTS_PER_KEY 4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000499#define NB_PRF_TESTS 3
Simon Butcher327398a2016-10-05 14:09:11 +0100500
501// TODO - should use a value somewhere else
Brian Murray0f6af732016-05-19 15:59:23 -0700502#define AES_BLOCK_SIZE 16
503#define DES3_BLOCK_SIZE 8
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000504
Brian Murray0f6af732016-05-19 15:59:23 -0700505#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
506/* All CMAC test inputs are truncated from the same 64 byte buffer. */
507static const unsigned char test_message[] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000508 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
509 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
510 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
511 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
512 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
513 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
514 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
515 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
516};
Brian Murray0cf14c12016-05-23 12:49:50 -0700517
518
Brian Murray0f6af732016-05-19 15:59:23 -0700519#endif /* defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000520
Brian Murray0f6af732016-05-19 15:59:23 -0700521#ifdef MBEDTLS_AES_C
522/* Truncation point of message for AES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700523static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700524 0,
525 16,
526 40,
527 64
528};
529
530/* AES 128 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700531static const unsigned char aes_128_key[16] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700532 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
533 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
534};
535static const unsigned char aes_128_subkeys[2][AES_BLOCK_SIZE] = {
536 {
537 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
538 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
539 },
540 {
541 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
542 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
543 }
544};
545static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000546 {
547 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
548 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
549 },
550 {
551 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
552 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
553 },
554 {
555 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
556 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
557 },
558 {
559 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
560 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
561 }
562};
563
Brian Murray0f6af732016-05-19 15:59:23 -0700564/* AES 192 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700565static const unsigned char aes_192_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700566 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
567 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
568 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000569};
Brian Murray0f6af732016-05-19 15:59:23 -0700570static const unsigned char aes_192_subkeys[2][AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700571 {
Brian Murray0f6af732016-05-19 15:59:23 -0700572 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
573 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
Brian Murrayb0c3c432016-05-18 14:29:51 -0700574 },
575 {
Brian Murray0f6af732016-05-19 15:59:23 -0700576 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
577 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
Brian Murrayb0c3c432016-05-18 14:29:51 -0700578 }
579};
Brian Murray0f6af732016-05-19 15:59:23 -0700580static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700581 {
582 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
583 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
584 },
585 {
586 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
587 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
588 },
589 {
590 0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad,
591 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e
592 },
593 {
594 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
595 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
596 }
597};
598
Brian Murray0f6af732016-05-19 15:59:23 -0700599/* AES 256 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700600static const unsigned char aes_256_key[32] = {
Brian Murray87e40402016-05-19 19:05:57 -0700601 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
602 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
603 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
604 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
Brian Murray0f6af732016-05-19 15:59:23 -0700605};
606static const unsigned char aes_256_subkeys[2][AES_BLOCK_SIZE] = {
607 {
608 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
609 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
610 },
611 {
612 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
613 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
614 }
615};
616static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
617 {
618 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
619 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
620 },
621 {
622 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
623 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
624 },
625 {
626 0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2,
627 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6
628 },
629 {
630 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
631 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
632 }
633};
634#endif /* MBEDTLS_AES_C */
635
636#ifdef MBEDTLS_DES_C
637/* Truncation point of message for 3DES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700638static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700639 0,
640 8,
641 20,
642 32
643};
644
645/* 3DES 2 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700646static const unsigned char des3_2key_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700647 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5,
648 0x8a, 0x3d, 0x10, 0xba, 0x80, 0x57, 0x0d, 0x38,
649 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5
Brian Murray0f6af732016-05-19 15:59:23 -0700650};
651static const unsigned char des3_2key_subkeys[2][8] = {
652 {
653 0x8e, 0xcf, 0x37, 0x3e, 0xd7, 0x1a, 0xfa, 0xef
654 },
655 {
656 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5
657 }
658};
Brian Murray57863ad2016-05-19 16:38:36 -0700659static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700660 {
661 0xbd, 0x2e, 0xbf, 0x9a, 0x3b, 0xa0, 0x03, 0x61
662 },
663 {
664 0x4f, 0xf2, 0xab, 0x81, 0x3c, 0x53, 0xce, 0x83
665 },
666 {
667 0x62, 0xdd, 0x1b, 0x47, 0x19, 0x02, 0xbd, 0x4e
668 },
669 {
670 0x31, 0xb1, 0xe4, 0x31, 0xda, 0xbc, 0x4e, 0xb8
671 }
672};
673
Brian Murray0f6af732016-05-19 15:59:23 -0700674/* 3DES 3 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700675static const unsigned char des3_3key_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700676 0x8a, 0xa8, 0x3b, 0xf8, 0xcb, 0xda, 0x10, 0x62,
677 0x0b, 0xc1, 0xbf, 0x19, 0xfb, 0xb6, 0xcd, 0x58,
678 0xbc, 0x31, 0x3d, 0x4a, 0x37, 0x1c, 0xa8, 0xb5
Brian Murray0f6af732016-05-19 15:59:23 -0700679};
680static const unsigned char des3_3key_subkeys[2][8] = {
681 {
682 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f
683 },
684 {
685 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5
686 }
687};
Brian Murray57863ad2016-05-19 16:38:36 -0700688static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700689 {
690 0xb7, 0xa6, 0x88, 0xe1, 0x22, 0xff, 0xaf, 0x95
691 },
692 {
693 0x8e, 0x8f, 0x29, 0x31, 0x36, 0x28, 0x37, 0x97
694 },
695 {
696 0x74, 0x3d, 0xdb, 0xe0, 0xce, 0x2d, 0xc2, 0xed
697 },
698 {
699 0x33, 0xe6, 0xb1, 0x09, 0x24, 0x00, 0xea, 0xe5
700 }
701};
702
Brian Murray0f6af732016-05-19 15:59:23 -0700703#endif /* MBEDTLS_DES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700704
Brian Murray0f6af732016-05-19 15:59:23 -0700705#ifdef MBEDTLS_AES_C
706/* AES AES-CMAC-PRF-128 Test Data */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000707static const unsigned char PRFK[] = {
708 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
709 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
710 0xed, 0xcb
711};
712
713/* Sizes in bytes */
714static const size_t PRFKlen[NB_PRF_TESTS] = {
715 18,
716 16,
717 10
718};
719
720/* PRF M */
721static const unsigned char PRFM[] = {
722 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
723 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000724 0x10, 0x11, 0x12, 0x13
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000725};
726
727static const unsigned char PRFT[NB_PRF_TESTS][16] = {
728 {
729 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
730 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
731 },
732 {
733 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
734 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
735 },
736 {
737 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
738 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
739 }
740};
Brian Murray0f6af732016-05-19 15:59:23 -0700741#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000742
Simon Butcher327398a2016-10-05 14:09:11 +0100743static int cmac_test_subkeys( int verbose,
744 const char* testname,
745 const unsigned char* key,
746 int keybits,
747 const unsigned char* subkeys,
748 mbedtls_cipher_type_t cipher_type,
749 int block_size,
750 int num_tests )
751{
752 int i, ret;
753 mbedtls_cipher_context_t ctx;
754 const mbedtls_cipher_info_t *cipher_info;
755 unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE];
756 unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX_SIZE];
757
758 cipher_info = mbedtls_cipher_info_from_type( cipher_type );
759 if( cipher_info == NULL )
760 {
761 /* Failing at this point must be due to a build issue */
762 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
763 goto exit;
764 }
765
766 for( i = 0; i < num_tests; i++ )
767 {
768 if( verbose != 0 )
769 mbedtls_printf( " %s CMAC subkey #%u: ", testname, i +1 );
770
771 mbedtls_cipher_init( &ctx );
772
773 if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
774 {
775 if( verbose != 0 )
776 mbedtls_printf( "test execution failed\n" );
777
778 goto exit;
779 }
780
781 if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits,
782 MBEDTLS_ENCRYPT ) ) != 0 )
783 {
784 if( verbose != 0 )
785 mbedtls_printf( "test execution failed\n" );
786
787 goto exit;
788 }
789
790 ret = cmac_generate_subkeys( &ctx, K1, K2 );
791 if( ret != 0 )
792 {
793 if( verbose != 0 )
794 mbedtls_printf( "failed\n" );
795 goto exit;
796 }
797
798 if( ( ret = memcmp( K1, subkeys, block_size ) != 0 ) ||
799 ( ret = memcmp( K2, &subkeys[block_size], block_size ) != 0 ) )
800 {
801 if( verbose != 0 )
802 mbedtls_printf( "failed\n" );
803 goto exit;
804 }
805
806 if( verbose != 0 )
807 mbedtls_printf( "passed\n" );
808 }
809
810exit:
811 return( ret );
812}
813
Brian Murrayae1cb122016-05-23 15:01:59 -0700814static inline int cmac_test_wth_cipher( int verbose,
815 const char* testname,
816 const unsigned char* key,
817 int keybits,
818 const unsigned char* messages,
819 const unsigned int message_lengths[4],
Brian Murrayae1cb122016-05-23 15:01:59 -0700820 const unsigned char* expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100821 mbedtls_cipher_type_t cipher_type,
822 int block_size,
823 int num_tests )
Brian Murray00dc5f02016-05-19 14:23:50 -0700824{
Simon Butcher327398a2016-10-05 14:09:11 +0100825 const mbedtls_cipher_info_t *cipher_info;
Brian Murray00dc5f02016-05-19 14:23:50 -0700826 int i, ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100827 unsigned char* output;
Brian Murray00dc5f02016-05-19 14:23:50 -0700828
Simon Butcher327398a2016-10-05 14:09:11 +0100829 output = mbedtls_calloc( block_size, sizeof( unsigned char ) );
830 if( output == NULL )
Brian Murray6a3c0d22016-05-20 18:25:43 -0700831 {
Simon Butcher327398a2016-10-05 14:09:11 +0100832 ret = MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
Brian Murray57863ad2016-05-19 16:38:36 -0700833 goto exit;
834 }
835
Simon Butcher327398a2016-10-05 14:09:11 +0100836 cipher_info = mbedtls_cipher_info_from_type( cipher_type );
837 if( cipher_info == NULL )
Brian Murray00dc5f02016-05-19 14:23:50 -0700838 {
Simon Butcher327398a2016-10-05 14:09:11 +0100839 /* Failing at this point must be due to a build issue */
840 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
Brian Murray00dc5f02016-05-19 14:23:50 -0700841 goto exit;
842 }
843
844 for( i = 0; i < num_tests; i++ )
845 {
846 if( verbose != 0 )
847 mbedtls_printf( " %s CMAC #%u: ", testname, i +1 );
848
Simon Butcher327398a2016-10-05 14:09:11 +0100849 if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages,
850 message_lengths[i], output ) ) != 0 )
Brian Murray00dc5f02016-05-19 14:23:50 -0700851 {
852 if( verbose != 0 )
853 mbedtls_printf( "failed\n" );
854 goto exit;
855 }
Brian Murray9ce2e092016-05-24 22:46:43 -0700856
Simon Butcher327398a2016-10-05 14:09:11 +0100857 if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 )
Brian Murray00dc5f02016-05-19 14:23:50 -0700858 {
859 if( verbose != 0 )
860 mbedtls_printf( "failed\n" );
861 goto exit;
862 }
863
Brian Murray9ce2e092016-05-24 22:46:43 -0700864 if( verbose != 0 )
865 mbedtls_printf( "passed\n" );
Brian Murray00dc5f02016-05-19 14:23:50 -0700866 }
Simon Butcher327398a2016-10-05 14:09:11 +0100867exit:
868 mbedtls_free( output );
869
870 return( ret );
Brian Murray00dc5f02016-05-19 14:23:50 -0700871}
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000872
Brian Murray0f6af732016-05-19 15:59:23 -0700873#ifdef MBEDTLS_AES_C
Brian Murrayae1cb122016-05-23 15:01:59 -0700874static inline int test_aes128_cmac_prf( int verbose )
Brian Murray6a3c0d22016-05-20 18:25:43 -0700875{
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000876 int i;
877 int ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100878 unsigned char output[16];
879
Brian Murrayb0c3c432016-05-18 14:29:51 -0700880 for( i = 0; i < NB_PRF_TESTS; i++ )
881 {
Brian Murray0f6af732016-05-19 15:59:23 -0700882 mbedtls_printf( " AES CMAC 128 PRF #%u: ", i );
Simon Butcher327398a2016-10-05 14:09:11 +0100883 ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700884 if( ret != 0 ||
Simon Butcher327398a2016-10-05 14:09:11 +0100885 memcmp( output, PRFT[i], 16 ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700886 {
Simon Butcher327398a2016-10-05 14:09:11 +0100887
Brian Murrayb0c3c432016-05-18 14:29:51 -0700888 if( verbose != 0 )
889 mbedtls_printf( "failed\n" );
890
Brian Murray0f6af732016-05-19 15:59:23 -0700891 return( ret );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700892 } else if( verbose != 0 )
893 {
894 mbedtls_printf( "passed\n" );
895 }
896 }
Brian Murray0f6af732016-05-19 15:59:23 -0700897 return( ret );
898}
899#endif /* MBEDTLS_AES_C */
900
901int mbedtls_cmac_self_test( int verbose )
902{
903 int ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100904
Brian Murray0f6af732016-05-19 15:59:23 -0700905#ifdef MBEDTLS_AES_C
Simon Butcher327398a2016-10-05 14:09:11 +0100906
907 /* AES-128 */
908 if( ( ret = cmac_test_subkeys( verbose,
909 "AES 128",
910 aes_128_key,
911 128,
912 (const unsigned char*) aes_128_subkeys,
913 MBEDTLS_CIPHER_AES_128_ECB,
914 AES_BLOCK_SIZE,
915 NB_CMAC_TESTS_PER_KEY ) !=0 ) )
916 {
917 return( ret );
918 }
919
Brian Murrayae1cb122016-05-23 15:01:59 -0700920 if( ( ret = cmac_test_wth_cipher( verbose,
921 "AES 128",
922 aes_128_key,
923 128,
924 test_message,
925 aes_message_lengths,
Brian Murrayae1cb122016-05-23 15:01:59 -0700926 (const unsigned char*) aes_128_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100927 MBEDTLS_CIPHER_AES_128_ECB,
928 AES_BLOCK_SIZE,
929 NB_CMAC_TESTS_PER_KEY ) !=0 ) )
930 {
931 return( ret );
932 }
933
934 /* AES-192 */
935 if( ( ret = cmac_test_subkeys( verbose,
936 "AES 192",
937 aes_192_key,
938 192,
939 (const unsigned char*) aes_192_subkeys,
940 MBEDTLS_CIPHER_AES_192_ECB,
941 AES_BLOCK_SIZE,
942 NB_CMAC_TESTS_PER_KEY ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700943 {
944 return( ret );
945 }
Brian Murray0f6af732016-05-19 15:59:23 -0700946
Brian Murrayae1cb122016-05-23 15:01:59 -0700947 if( ( ret = cmac_test_wth_cipher( verbose,
948 "AES 192",
949 aes_192_key,
950 192,
951 test_message,
952 aes_message_lengths,
Brian Murrayae1cb122016-05-23 15:01:59 -0700953 (const unsigned char*) aes_192_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100954 MBEDTLS_CIPHER_AES_192_ECB,
955 AES_BLOCK_SIZE,
956 NB_CMAC_TESTS_PER_KEY ) !=0 ) )
957 {
958mbedtls_printf("ret = %x\n", ret);
959 return( ret );
960 }
961
962 /* AES-256 */
963 if( ( ret = cmac_test_subkeys( verbose,
964 "AES 256",
965 aes_256_key,
966 256,
967 (const unsigned char*) aes_256_subkeys,
968 MBEDTLS_CIPHER_AES_256_ECB,
969 AES_BLOCK_SIZE,
970 NB_CMAC_TESTS_PER_KEY ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700971 {
972 return( ret );
973 }
Brian Murray0f6af732016-05-19 15:59:23 -0700974
Simon Butcher327398a2016-10-05 14:09:11 +0100975 if( ( ret = cmac_test_wth_cipher ( verbose,
Brian Murrayae1cb122016-05-23 15:01:59 -0700976 "AES 256",
977 aes_256_key,
978 256,
979 test_message,
980 aes_message_lengths,
Brian Murrayae1cb122016-05-23 15:01:59 -0700981 (const unsigned char*) aes_256_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100982 MBEDTLS_CIPHER_AES_256_ECB,
983 AES_BLOCK_SIZE,
984 NB_CMAC_TESTS_PER_KEY ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700985 {
986 return( ret );
987 }
Brian Murray0f6af732016-05-19 15:59:23 -0700988#endif /* MBEDTLS_AES_C */
989
990#ifdef MBEDTLS_DES_C
Simon Butcher327398a2016-10-05 14:09:11 +0100991 /* 3DES 2 key */
992 if( ( ret = cmac_test_subkeys( verbose,
993 "3DES 2 key",
994 des3_2key_key,
995 192,
996 (const unsigned char*) des3_2key_subkeys,
997 MBEDTLS_CIPHER_DES_EDE3_ECB,
998 DES3_BLOCK_SIZE,
999 NB_CMAC_TESTS_PER_KEY ) !=0 ) )
1000 {
1001 return( ret );
1002 }
1003
1004
1005
Brian Murrayae1cb122016-05-23 15:01:59 -07001006 if( ( ret = cmac_test_wth_cipher( verbose,
1007 "3DES 2 key",
1008 des3_2key_key,
1009 192,
1010 test_message,
1011 des3_message_lengths,
Brian Murrayae1cb122016-05-23 15:01:59 -07001012 (const unsigned char*) des3_2key_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +01001013 MBEDTLS_CIPHER_DES_EDE3_ECB,
1014 DES3_BLOCK_SIZE,
1015 NB_CMAC_TESTS_PER_KEY ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -07001016 {
1017 return( ret );
1018 }
Brian Murray0f6af732016-05-19 15:59:23 -07001019
Simon Butcher327398a2016-10-05 14:09:11 +01001020 /* 3DES 3 key */
1021 if( ( ret = cmac_test_subkeys( verbose,
1022 "3DES 3 key",
1023 des3_3key_key,
1024 192,
1025 (const unsigned char*) des3_3key_subkeys,
1026 MBEDTLS_CIPHER_DES_EDE3_ECB,
1027 DES3_BLOCK_SIZE,
1028 NB_CMAC_TESTS_PER_KEY ) !=0 ) )
1029 {
1030 return( ret );
1031 }
1032
1033
Brian Murrayae1cb122016-05-23 15:01:59 -07001034 if( ( ret = cmac_test_wth_cipher( verbose,
1035 "3DES 3 key",
1036 des3_3key_key,
1037 192,
1038 test_message,
1039 des3_message_lengths,
Brian Murrayae1cb122016-05-23 15:01:59 -07001040 (const unsigned char*) des3_3key_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +01001041 MBEDTLS_CIPHER_DES_EDE3_ECB,
1042 DES3_BLOCK_SIZE,
1043 NB_CMAC_TESTS_PER_KEY ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -07001044 {
1045 return( ret );
1046 }
Brian Murray0f6af732016-05-19 15:59:23 -07001047#endif /* MBEDTLS_DES_C */
1048
1049#ifdef MBEDTLS_AES_C
Brian Murray9044b022016-05-19 16:36:56 -07001050 if( ( ret = test_aes128_cmac_prf( verbose ) != 0 ) )
1051 return( ret );
Brian Murray0f6af732016-05-19 15:59:23 -07001052#endif /* MBEDTLS_AES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -07001053
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001054 if( verbose != 0 )
1055 mbedtls_printf( "\n" );
Brian Murray0f6af732016-05-19 15:59:23 -07001056
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001057 return( 0 );
1058}
1059
Brian Murray0f6af732016-05-19 15:59:23 -07001060#endif /* MBEDTLS_SELF_TEST */
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001061
1062#endif /* MBEDTLS_CMAC_C */