blob: 8ea0685b7a6a5ae987f1a106b82ee4afa4c01578 [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 ) );
238 cmac_ctx->padding_flag = 1;
239
240 return 0;
241}
242
243int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx,
244 const unsigned char *input, size_t ilen )
245{
246 mbedtls_cmac_context_t* cmac_ctx;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700247 unsigned char *state;
Andres AGa592dcc2016-10-06 15:23:39 +0100248 int n, j, ret = 0;
Simon Butcher327398a2016-10-05 14:09:11 +0100249 size_t olen, block_size;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700250
Simon Butcher327398a2016-10-05 14:09:11 +0100251 if( ctx == NULL || ctx->cipher_info == NULL || input == NULL ||
252 ctx->cmac_ctx == NULL )
253 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700254
Simon Butcher327398a2016-10-05 14:09:11 +0100255 cmac_ctx = ctx->cmac_ctx;
256 block_size = ctx->cipher_info->block_size;
257 state = ctx->cmac_ctx->state;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000258
Simon Butcher6b0774a2016-10-10 21:37:42 +0100259 /* Is there data still to process from the last call, that's greater in
260 * size than a block? */
Simon Butcher327398a2016-10-05 14:09:11 +0100261 if( cmac_ctx->unprocessed_len > 0 &&
Andres AGa592dcc2016-10-06 15:23:39 +0100262 ilen > block_size - cmac_ctx->unprocessed_len )
Brian Murray57863ad2016-05-19 16:38:36 -0700263 {
Simon Butcher327398a2016-10-05 14:09:11 +0100264 memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
265 input,
266 block_size - cmac_ctx->unprocessed_len );
267
268 cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size );
269
270 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
271 &olen ) ) != 0 )
272 {
273 goto exit;
274 }
275
Simon Butcher6b0774a2016-10-10 21:37:42 +0100276 input += block_size - cmac_ctx->unprocessed_len;
277 ilen -= block_size - cmac_ctx->unprocessed_len;
Simon Butcher327398a2016-10-05 14:09:11 +0100278 cmac_ctx->unprocessed_len = 0;
Brian Murray57863ad2016-05-19 16:38:36 -0700279 }
280
Simon Butcher327398a2016-10-05 14:09:11 +0100281 /* n is the number of blocks including any final partial block */
282 n = ( ilen + block_size - 1 ) / block_size;
283
284 /* Iterate across the input data in block sized chunks */
285 for( j = 0; j < n - 1; j++ )
Brian Murray57863ad2016-05-19 16:38:36 -0700286 {
Simon Butcher327398a2016-10-05 14:09:11 +0100287 cmac_xor_block( state, input, state, block_size );
288
289 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
290 &olen ) ) != 0 )
291 goto exit;
292
293 ilen -= block_size;
294 input += block_size;
295
296 cmac_ctx->padding_flag = 0;
Brian Murray57863ad2016-05-19 16:38:36 -0700297 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000298
Simon Butcher327398a2016-10-05 14:09:11 +0100299 /* If there is data left over that wasn't aligned to a block */
300 if( ilen > 0 )
301 {
Simon Butcher6b0774a2016-10-10 21:37:42 +0100302 memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len],
303 input,
304 ilen );
305 cmac_ctx->unprocessed_len += ilen;
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000306
Simon Butcher327398a2016-10-05 14:09:11 +0100307 if( ilen % block_size > 0 )
308 cmac_ctx->padding_flag = 1;
309 else
310 cmac_ctx->padding_flag = 0;
311 }
312
313exit:
314 return( ret );
315}
316
317int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx,
318 unsigned char *output )
319{
320 mbedtls_cmac_context_t* cmac_ctx;
Simon Butcher69283e52016-10-06 12:49:58 +0100321 unsigned char *state, *last_block;
322 unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
323 unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
324 unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX];
Simon Butcher327398a2016-10-05 14:09:11 +0100325 int ret;
326 size_t olen, block_size;
327
328 if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ||
329 output == NULL )
330 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
331
332 cmac_ctx = ctx->cmac_ctx;
333 block_size = ctx->cipher_info->block_size;
334 state = cmac_ctx->state;
335
Simon Butcher69283e52016-10-06 12:49:58 +0100336 mbedtls_zeroize( K1, sizeof( K1 ) );
337 mbedtls_zeroize( K2, sizeof( K2 ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100338 cmac_generate_subkeys( ctx, K1, K2 );
339
Simon Butcher69283e52016-10-06 12:49:58 +0100340 last_block = cmac_ctx->unprocessed_block;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000341
342 /* Calculate last block */
Simon Butcher6b0774a2016-10-10 21:37:42 +0100343 if( cmac_ctx->padding_flag && cmac_ctx->unprocessed_len < block_size )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000344 {
Simon Butcher327398a2016-10-05 14:09:11 +0100345 cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len );
346 cmac_xor_block( M_last, M_last, K2, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000347 }
348 else
349 {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000350 /* Last block is complete block */
Simon Butcher327398a2016-10-05 14:09:11 +0100351 cmac_xor_block( M_last, last_block, K1, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000352 }
353
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000354
Simon Butcher327398a2016-10-05 14:09:11 +0100355 cmac_xor_block( state, M_last, state, block_size );
356 if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state,
357 &olen ) ) != 0 )
358 {
359 goto exit;
360 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000361
Simon Butcher327398a2016-10-05 14:09:11 +0100362 memcpy( output, state, block_size );
363
364exit:
365 /* Wipe the generated keys on the stack, and any other transients to avoid
366 * side channel leakage */
Simon Butcher69283e52016-10-06 12:49:58 +0100367 mbedtls_zeroize( K1, sizeof( K1 ) );
368 mbedtls_zeroize( K2, sizeof( K2 ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100369
Simon Butcher69283e52016-10-06 12:49:58 +0100370 cmac_ctx->padding_flag = 1;
Simon Butcher327398a2016-10-05 14:09:11 +0100371 cmac_ctx->unprocessed_len = 0;
372 mbedtls_zeroize( cmac_ctx->unprocessed_block,
Simon Butcher69283e52016-10-06 12:49:58 +0100373 sizeof( cmac_ctx->unprocessed_block ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100374
Simon Butcher69283e52016-10-06 12:49:58 +0100375 mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX );
Simon Butcher327398a2016-10-05 14:09:11 +0100376 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000377}
378
Simon Butcher327398a2016-10-05 14:09:11 +0100379int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000380{
Simon Butcher327398a2016-10-05 14:09:11 +0100381 mbedtls_cmac_context_t* cmac_ctx;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000382
Simon Butcher327398a2016-10-05 14:09:11 +0100383 if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL )
384 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700385
Simon Butcher327398a2016-10-05 14:09:11 +0100386 cmac_ctx = ctx->cmac_ctx;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000387
Simon Butcher327398a2016-10-05 14:09:11 +0100388 /* Reset the internal state */
389 cmac_ctx->unprocessed_len = 0;
390 mbedtls_zeroize( cmac_ctx->unprocessed_block,
Andres AGa592dcc2016-10-06 15:23:39 +0100391 sizeof( cmac_ctx->unprocessed_block ) );
Simon Butcherd241f1c2016-10-06 10:39:49 +0100392 mbedtls_zeroize( cmac_ctx->state,
393 sizeof( cmac_ctx->state ) );
Simon Butcher327398a2016-10-05 14:09:11 +0100394 cmac_ctx->padding_flag = 1;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000395
Simon Butcher327398a2016-10-05 14:09:11 +0100396 return( 0 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000397}
398
Simon Butcher327398a2016-10-05 14:09:11 +0100399int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info,
400 const unsigned char *key, size_t keylen,
401 const unsigned char *input, size_t ilen,
402 unsigned char *output )
403{
404 mbedtls_cipher_context_t ctx;
405 int ret;
406
407 if( cipher_info == NULL || key == NULL || input == NULL || output == NULL )
408 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
409
410 mbedtls_cipher_init( &ctx );
411
412 if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
413 goto exit;
414
415 ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen );
Simon Butcher327398a2016-10-05 14:09:11 +0100416 if( ret != 0 )
417 goto exit;
Simon Butcher327398a2016-10-05 14:09:11 +0100418
419 ret = mbedtls_cipher_cmac_update( &ctx, input, ilen );
420 if( ret != 0 )
421 goto exit;
422
Simon Butcher69283e52016-10-06 12:49:58 +0100423 ret = mbedtls_cipher_cmac_finish( &ctx, output );
Simon Butcher327398a2016-10-05 14:09:11 +0100424
425exit:
Simon Butcher69283e52016-10-06 12:49:58 +0100426 mbedtls_cipher_free( &ctx );
427
Simon Butcher327398a2016-10-05 14:09:11 +0100428 return( ret );
429}
Simon Butcher327398a2016-10-05 14:09:11 +0100430
Simon Butcher69283e52016-10-06 12:49:58 +0100431#if defined(MBEDTLS_AES_C)
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000432/*
Simon Butcher69283e52016-10-06 12:49:58 +0100433 * Implementation of AES-CMAC-PRF-128 defined in RFC 4615
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000434 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700435int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000436 const unsigned char *input, size_t in_len,
Simon Butcher327398a2016-10-05 14:09:11 +0100437 unsigned char *output )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000438{
439 int ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100440 const mbedtls_cipher_info_t *cipher_info;
Simon Butcher69283e52016-10-06 12:49:58 +0100441 unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE];
442 unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE];
443
444 if( key == NULL || input == NULL || output == NULL )
445 return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000446
Simon Butcher327398a2016-10-05 14:09:11 +0100447 cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB );
448 if( cipher_info == NULL )
449 {
450 /* Failing at this point must be due to a build issue */
451 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
452 goto exit;
453 }
Brian Murrayb0c3c432016-05-18 14:29:51 -0700454
Simon Butcher69283e52016-10-06 12:49:58 +0100455 if( key_length == MBEDTLS_AES_BLOCK_SIZE )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000456 {
457 /* Use key as is */
Simon Butcher69283e52016-10-06 12:49:58 +0100458 memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000459 }
460 else
461 {
Simon Butcher69283e52016-10-06 12:49:58 +0100462 memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE );
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000463
Simon Butcher327398a2016-10-05 14:09:11 +0100464 ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key,
465 key_length, int_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000466 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700467 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000468 }
469
Simon Butcher327398a2016-10-05 14:09:11 +0100470 ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len,
471 output );
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000472
Simon Butcher327398a2016-10-05 14:09:11 +0100473exit:
474 mbedtls_zeroize( int_key, sizeof( int_key ) );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700475
Simon Butcher327398a2016-10-05 14:09:11 +0100476 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000477}
Brian Murrayb439d452016-05-19 16:02:42 -0700478#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000479
Simon Butcher69283e52016-10-06 12:49:58 +0100480#if defined(MBEDTLS_SELF_TEST)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000481/*
Brian Murray0f6af732016-05-19 15:59:23 -0700482 * CMAC test data from SP800-38B Appendix D.1 (corrected)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000483 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
Brian Murray0f6af732016-05-19 15:59:23 -0700484 *
485 * AES-CMAC-PRF-128 test data from RFC 4615
486 * https://tools.ietf.org/html/rfc4615#page-4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000487 */
488
Brian Murray0f6af732016-05-19 15:59:23 -0700489#define NB_CMAC_TESTS_PER_KEY 4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000490#define NB_PRF_TESTS 3
Simon Butcher327398a2016-10-05 14:09:11 +0100491
Brian Murray0f6af732016-05-19 15:59:23 -0700492#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
493/* All CMAC test inputs are truncated from the same 64 byte buffer. */
494static const unsigned char test_message[] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000495 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
496 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
497 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
498 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
499 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
500 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
501 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
502 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
503};
Simon Butcher69283e52016-10-06 12:49:58 +0100504#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */
Brian Murray0cf14c12016-05-23 12:49:50 -0700505
Simon Butcher69283e52016-10-06 12:49:58 +0100506#if defined(MBEDTLS_AES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700507/* Truncation point of message for AES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700508static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700509 0,
510 16,
511 40,
512 64
513};
514
515/* AES 128 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700516static const unsigned char aes_128_key[16] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700517 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
518 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
519};
Simon Butcher69283e52016-10-06 12:49:58 +0100520static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700521 {
522 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
523 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
524 },
525 {
526 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
527 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
528 }
529};
Simon Butcher69283e52016-10-06 12:49:58 +0100530static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000531 {
532 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
533 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
534 },
535 {
536 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
537 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
538 },
539 {
540 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
541 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
542 },
543 {
544 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
545 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
546 }
547};
548
Brian Murray0f6af732016-05-19 15:59:23 -0700549/* AES 192 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700550static const unsigned char aes_192_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700551 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
552 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
553 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000554};
Simon Butcher69283e52016-10-06 12:49:58 +0100555static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700556 {
Brian Murray0f6af732016-05-19 15:59:23 -0700557 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
558 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
Brian Murrayb0c3c432016-05-18 14:29:51 -0700559 },
560 {
Brian Murray0f6af732016-05-19 15:59:23 -0700561 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
562 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
Brian Murrayb0c3c432016-05-18 14:29:51 -0700563 }
564};
Simon Butcher69283e52016-10-06 12:49:58 +0100565static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700566 {
567 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
568 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
569 },
570 {
571 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
572 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
573 },
574 {
575 0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad,
576 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e
577 },
578 {
579 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
580 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
581 }
582};
583
Brian Murray0f6af732016-05-19 15:59:23 -0700584/* AES 256 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700585static const unsigned char aes_256_key[32] = {
Brian Murray87e40402016-05-19 19:05:57 -0700586 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
587 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
588 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
589 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
Brian Murray0f6af732016-05-19 15:59:23 -0700590};
Simon Butcher69283e52016-10-06 12:49:58 +0100591static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700592 {
593 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
594 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
595 },
596 {
597 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
598 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
599 }
600};
Simon Butcher69283e52016-10-06 12:49:58 +0100601static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700602 {
603 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
604 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
605 },
606 {
607 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
608 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
609 },
610 {
611 0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2,
612 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6
613 },
614 {
615 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
616 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
617 }
618};
619#endif /* MBEDTLS_AES_C */
620
Simon Butcher69283e52016-10-06 12:49:58 +0100621#if defined(MBEDTLS_DES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700622/* Truncation point of message for 3DES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700623static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700624 0,
625 8,
626 20,
627 32
628};
629
630/* 3DES 2 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700631static const unsigned char des3_2key_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700632 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5,
633 0x8a, 0x3d, 0x10, 0xba, 0x80, 0x57, 0x0d, 0x38,
634 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5
Brian Murray0f6af732016-05-19 15:59:23 -0700635};
636static const unsigned char des3_2key_subkeys[2][8] = {
637 {
638 0x8e, 0xcf, 0x37, 0x3e, 0xd7, 0x1a, 0xfa, 0xef
639 },
640 {
641 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5
642 }
643};
Simon Butcher69283e52016-10-06 12:49:58 +0100644static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700645 {
646 0xbd, 0x2e, 0xbf, 0x9a, 0x3b, 0xa0, 0x03, 0x61
647 },
648 {
649 0x4f, 0xf2, 0xab, 0x81, 0x3c, 0x53, 0xce, 0x83
650 },
651 {
652 0x62, 0xdd, 0x1b, 0x47, 0x19, 0x02, 0xbd, 0x4e
653 },
654 {
655 0x31, 0xb1, 0xe4, 0x31, 0xda, 0xbc, 0x4e, 0xb8
656 }
657};
658
Brian Murray0f6af732016-05-19 15:59:23 -0700659/* 3DES 3 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700660static const unsigned char des3_3key_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700661 0x8a, 0xa8, 0x3b, 0xf8, 0xcb, 0xda, 0x10, 0x62,
662 0x0b, 0xc1, 0xbf, 0x19, 0xfb, 0xb6, 0xcd, 0x58,
663 0xbc, 0x31, 0x3d, 0x4a, 0x37, 0x1c, 0xa8, 0xb5
Brian Murray0f6af732016-05-19 15:59:23 -0700664};
665static const unsigned char des3_3key_subkeys[2][8] = {
666 {
667 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f
668 },
669 {
670 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5
671 }
672};
Simon Butcher69283e52016-10-06 12:49:58 +0100673static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700674 {
675 0xb7, 0xa6, 0x88, 0xe1, 0x22, 0xff, 0xaf, 0x95
676 },
677 {
678 0x8e, 0x8f, 0x29, 0x31, 0x36, 0x28, 0x37, 0x97
679 },
680 {
681 0x74, 0x3d, 0xdb, 0xe0, 0xce, 0x2d, 0xc2, 0xed
682 },
683 {
684 0x33, 0xe6, 0xb1, 0x09, 0x24, 0x00, 0xea, 0xe5
685 }
686};
687
Brian Murray0f6af732016-05-19 15:59:23 -0700688#endif /* MBEDTLS_DES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700689
Simon Butcher69283e52016-10-06 12:49:58 +0100690#if defined(MBEDTLS_AES_C)
Brian Murray0f6af732016-05-19 15:59:23 -0700691/* AES AES-CMAC-PRF-128 Test Data */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000692static const unsigned char PRFK[] = {
693 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
694 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
695 0xed, 0xcb
696};
697
698/* Sizes in bytes */
699static const size_t PRFKlen[NB_PRF_TESTS] = {
700 18,
701 16,
702 10
703};
704
705/* PRF M */
706static const unsigned char PRFM[] = {
707 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
708 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000709 0x10, 0x11, 0x12, 0x13
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000710};
711
712static const unsigned char PRFT[NB_PRF_TESTS][16] = {
713 {
714 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
715 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
716 },
717 {
718 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
719 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
720 },
721 {
722 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
723 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
724 }
725};
Brian Murray0f6af732016-05-19 15:59:23 -0700726#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000727
Simon Butcher327398a2016-10-05 14:09:11 +0100728static int cmac_test_subkeys( int verbose,
729 const char* testname,
730 const unsigned char* key,
731 int keybits,
732 const unsigned char* subkeys,
733 mbedtls_cipher_type_t cipher_type,
734 int block_size,
735 int num_tests )
736{
737 int i, ret;
738 mbedtls_cipher_context_t ctx;
739 const mbedtls_cipher_info_t *cipher_info;
Simon Butcher69283e52016-10-06 12:49:58 +0100740 unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
741 unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
Simon Butcher327398a2016-10-05 14:09:11 +0100742
743 cipher_info = mbedtls_cipher_info_from_type( cipher_type );
744 if( cipher_info == NULL )
745 {
746 /* Failing at this point must be due to a build issue */
Simon Butcher69283e52016-10-06 12:49:58 +0100747 return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
Simon Butcher327398a2016-10-05 14:09:11 +0100748 }
749
Simon Butcher69283e52016-10-06 12:49:58 +0100750 mbedtls_cipher_init( &ctx );
751
Simon Butcher327398a2016-10-05 14:09:11 +0100752 for( i = 0; i < num_tests; i++ )
753 {
754 if( verbose != 0 )
Simon Butcher69283e52016-10-06 12:49:58 +0100755 mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 );
Simon Butcher327398a2016-10-05 14:09:11 +0100756
757 if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 )
758 {
759 if( verbose != 0 )
760 mbedtls_printf( "test execution failed\n" );
761
762 goto exit;
763 }
764
765 if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits,
766 MBEDTLS_ENCRYPT ) ) != 0 )
767 {
768 if( verbose != 0 )
769 mbedtls_printf( "test execution failed\n" );
770
771 goto exit;
772 }
773
774 ret = cmac_generate_subkeys( &ctx, K1, K2 );
775 if( ret != 0 )
776 {
777 if( verbose != 0 )
778 mbedtls_printf( "failed\n" );
779 goto exit;
780 }
781
Simon Butcher420be4e2016-10-07 12:55:43 +0100782 if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 ||
783 ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100784 {
785 if( verbose != 0 )
786 mbedtls_printf( "failed\n" );
787 goto exit;
788 }
789
790 if( verbose != 0 )
791 mbedtls_printf( "passed\n" );
792 }
793
794exit:
Simon Butcher69283e52016-10-06 12:49:58 +0100795 mbedtls_cipher_free( &ctx );
796
Simon Butcher327398a2016-10-05 14:09:11 +0100797 return( ret );
798}
799
Simon Butcher69283e52016-10-06 12:49:58 +0100800static int cmac_test_wth_cipher( int verbose,
801 const char* testname,
802 const unsigned char* key,
803 int keybits,
804 const unsigned char* messages,
805 const unsigned int message_lengths[4],
806 const unsigned char* expected_result,
807 mbedtls_cipher_type_t cipher_type,
808 int block_size,
809 int num_tests )
Brian Murray00dc5f02016-05-19 14:23:50 -0700810{
Simon Butcher327398a2016-10-05 14:09:11 +0100811 const mbedtls_cipher_info_t *cipher_info;
Brian Murray00dc5f02016-05-19 14:23:50 -0700812 int i, ret;
Simon Butcher69283e52016-10-06 12:49:58 +0100813 unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX];
Brian Murray57863ad2016-05-19 16:38:36 -0700814
Simon Butcher327398a2016-10-05 14:09:11 +0100815 cipher_info = mbedtls_cipher_info_from_type( cipher_type );
816 if( cipher_info == NULL )
Brian Murray00dc5f02016-05-19 14:23:50 -0700817 {
Simon Butcher327398a2016-10-05 14:09:11 +0100818 /* Failing at this point must be due to a build issue */
819 ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
Brian Murray00dc5f02016-05-19 14:23:50 -0700820 goto exit;
821 }
822
823 for( i = 0; i < num_tests; i++ )
824 {
825 if( verbose != 0 )
Andres AGa592dcc2016-10-06 15:23:39 +0100826 mbedtls_printf( " %s CMAC #%u: ", testname, i + 1 );
Brian Murray00dc5f02016-05-19 14:23:50 -0700827
Simon Butcher327398a2016-10-05 14:09:11 +0100828 if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages,
829 message_lengths[i], output ) ) != 0 )
Brian Murray00dc5f02016-05-19 14:23:50 -0700830 {
831 if( verbose != 0 )
832 mbedtls_printf( "failed\n" );
833 goto exit;
834 }
Brian Murray9ce2e092016-05-24 22:46:43 -0700835
Simon Butcher327398a2016-10-05 14:09:11 +0100836 if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 )
Brian Murray00dc5f02016-05-19 14:23:50 -0700837 {
838 if( verbose != 0 )
839 mbedtls_printf( "failed\n" );
840 goto exit;
841 }
842
Brian Murray9ce2e092016-05-24 22:46:43 -0700843 if( verbose != 0 )
844 mbedtls_printf( "passed\n" );
Brian Murray00dc5f02016-05-19 14:23:50 -0700845 }
Simon Butcher327398a2016-10-05 14:09:11 +0100846
Simon Butcher69283e52016-10-06 12:49:58 +0100847exit:
Simon Butcher327398a2016-10-05 14:09:11 +0100848 return( ret );
Brian Murray00dc5f02016-05-19 14:23:50 -0700849}
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000850
Simon Butcher69283e52016-10-06 12:49:58 +0100851#if defined(MBEDTLS_AES_C)
852static int test_aes128_cmac_prf( int verbose )
Brian Murray6a3c0d22016-05-20 18:25:43 -0700853{
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000854 int i;
855 int ret;
Simon Butcher69283e52016-10-06 12:49:58 +0100856 unsigned char output[MBEDTLS_AES_BLOCK_SIZE];
Simon Butcher327398a2016-10-05 14:09:11 +0100857
Brian Murrayb0c3c432016-05-18 14:29:51 -0700858 for( i = 0; i < NB_PRF_TESTS; i++ )
859 {
Brian Murray0f6af732016-05-19 15:59:23 -0700860 mbedtls_printf( " AES CMAC 128 PRF #%u: ", i );
Simon Butcher327398a2016-10-05 14:09:11 +0100861 ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700862 if( ret != 0 ||
Simon Butcher69283e52016-10-06 12:49:58 +0100863 memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700864 {
Simon Butcher327398a2016-10-05 14:09:11 +0100865
Brian Murrayb0c3c432016-05-18 14:29:51 -0700866 if( verbose != 0 )
867 mbedtls_printf( "failed\n" );
868
Brian Murray0f6af732016-05-19 15:59:23 -0700869 return( ret );
Simon Butcher69283e52016-10-06 12:49:58 +0100870 }
871 else if( verbose != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700872 {
873 mbedtls_printf( "passed\n" );
874 }
875 }
Brian Murray0f6af732016-05-19 15:59:23 -0700876 return( ret );
877}
878#endif /* MBEDTLS_AES_C */
879
880int mbedtls_cmac_self_test( int verbose )
881{
882 int ret;
Simon Butcher327398a2016-10-05 14:09:11 +0100883
Simon Butcher69283e52016-10-06 12:49:58 +0100884#if defined(MBEDTLS_AES_C)
Simon Butcher327398a2016-10-05 14:09:11 +0100885 /* AES-128 */
886 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100887 "AES 128",
888 aes_128_key,
889 128,
890 (const unsigned char*)aes_128_subkeys,
891 MBEDTLS_CIPHER_AES_128_ECB,
892 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100893 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100894 {
895 return( ret );
896 }
897
Brian Murrayae1cb122016-05-23 15:01:59 -0700898 if( ( ret = cmac_test_wth_cipher( verbose,
899 "AES 128",
900 aes_128_key,
901 128,
902 test_message,
903 aes_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100904 (const unsigned char*)aes_128_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100905 MBEDTLS_CIPHER_AES_128_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100906 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100907 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100908 {
909 return( ret );
910 }
911
912 /* AES-192 */
913 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100914 "AES 192",
915 aes_192_key,
916 192,
917 (const unsigned char*)aes_192_subkeys,
918 MBEDTLS_CIPHER_AES_192_ECB,
919 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100920 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -0700921 {
922 return( ret );
923 }
Brian Murray0f6af732016-05-19 15:59:23 -0700924
Brian Murrayae1cb122016-05-23 15:01:59 -0700925 if( ( ret = cmac_test_wth_cipher( verbose,
926 "AES 192",
927 aes_192_key,
928 192,
929 test_message,
930 aes_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100931 (const unsigned char*)aes_192_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100932 MBEDTLS_CIPHER_AES_192_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100933 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100934 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100935 {
Simon Butcher327398a2016-10-05 14:09:11 +0100936 return( ret );
937 }
938
939 /* AES-256 */
940 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100941 "AES 256",
942 aes_256_key,
943 256,
944 (const unsigned char*)aes_256_subkeys,
945 MBEDTLS_CIPHER_AES_256_ECB,
946 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100947 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -0700948 {
949 return( ret );
950 }
Brian Murray0f6af732016-05-19 15:59:23 -0700951
Simon Butcher69283e52016-10-06 12:49:58 +0100952 if( ( ret = cmac_test_wth_cipher ( verbose,
Brian Murrayae1cb122016-05-23 15:01:59 -0700953 "AES 256",
954 aes_256_key,
955 256,
956 test_message,
957 aes_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100958 (const unsigned char*)aes_256_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100959 MBEDTLS_CIPHER_AES_256_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100960 MBEDTLS_AES_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100961 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -0700962 {
963 return( ret );
964 }
Brian Murray0f6af732016-05-19 15:59:23 -0700965#endif /* MBEDTLS_AES_C */
966
Simon Butcher69283e52016-10-06 12:49:58 +0100967#if defined(MBEDTLS_DES_C)
Simon Butcher327398a2016-10-05 14:09:11 +0100968 /* 3DES 2 key */
969 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100970 "3DES 2 key",
971 des3_2key_key,
972 192,
973 (const unsigned char*)des3_2key_subkeys,
974 MBEDTLS_CIPHER_DES_EDE3_ECB,
975 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100976 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +0100977 {
978 return( ret );
979 }
980
Brian Murrayae1cb122016-05-23 15:01:59 -0700981 if( ( ret = cmac_test_wth_cipher( verbose,
982 "3DES 2 key",
983 des3_2key_key,
984 192,
985 test_message,
986 des3_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +0100987 (const unsigned char*)des3_2key_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +0100988 MBEDTLS_CIPHER_DES_EDE3_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +0100989 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +0100990 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -0700991 {
992 return( ret );
993 }
Brian Murray0f6af732016-05-19 15:59:23 -0700994
Simon Butcher327398a2016-10-05 14:09:11 +0100995 /* 3DES 3 key */
996 if( ( ret = cmac_test_subkeys( verbose,
Simon Butcher69283e52016-10-06 12:49:58 +0100997 "3DES 3 key",
998 des3_3key_key,
999 192,
1000 (const unsigned char*)des3_3key_subkeys,
1001 MBEDTLS_CIPHER_DES_EDE3_ECB,
1002 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +01001003 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Simon Butcher327398a2016-10-05 14:09:11 +01001004 {
1005 return( ret );
1006 }
1007
Brian Murrayae1cb122016-05-23 15:01:59 -07001008 if( ( ret = cmac_test_wth_cipher( verbose,
1009 "3DES 3 key",
1010 des3_3key_key,
1011 192,
1012 test_message,
1013 des3_message_lengths,
Simon Butcher69283e52016-10-06 12:49:58 +01001014 (const unsigned char*)des3_3key_expected_result,
Simon Butcher327398a2016-10-05 14:09:11 +01001015 MBEDTLS_CIPHER_DES_EDE3_ECB,
Simon Butcher69283e52016-10-06 12:49:58 +01001016 MBEDTLS_DES3_BLOCK_SIZE,
Simon Butcher420be4e2016-10-07 12:55:43 +01001017 NB_CMAC_TESTS_PER_KEY ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -07001018 {
1019 return( ret );
1020 }
Brian Murray0f6af732016-05-19 15:59:23 -07001021#endif /* MBEDTLS_DES_C */
1022
Simon Butcher69283e52016-10-06 12:49:58 +01001023#if defined(MBEDTLS_AES_C)
Simon Butcher420be4e2016-10-07 12:55:43 +01001024 if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 )
Brian Murray9044b022016-05-19 16:36:56 -07001025 return( ret );
Brian Murray0f6af732016-05-19 15:59:23 -07001026#endif /* MBEDTLS_AES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -07001027
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001028 if( verbose != 0 )
1029 mbedtls_printf( "\n" );
Brian Murray0f6af732016-05-19 15:59:23 -07001030
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001031 return( 0 );
1032}
1033
Brian Murray0f6af732016-05-19 15:59:23 -07001034#endif /* MBEDTLS_SELF_TEST */
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001035
1036#endif /* MBEDTLS_CMAC_C */