blob: d5198341861bccc3161470ef440c47166ce6bb27 [file] [log] [blame]
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001/*
2 * NIST SP800-38B compliant CMAC implementation
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21
22/*
23 * Definition of CMAC:
24 * http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
25 * RFC 4493 "The AES-CMAC Algorithm"
26 */
27
28#if !defined(MBEDTLS_CONFIG_FILE)
29#include "mbedtls/config.h"
30#else
31#include MBEDTLS_CONFIG_FILE
32#endif
33
34#if defined(MBEDTLS_CMAC_C)
35
36#include "mbedtls/cmac.h"
37
38#include <string.h>
39
40#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
41#if defined(MBEDTLS_PLATFORM_C)
42#include "mbedtls/platform.h"
43#else
44#include <stdio.h>
45#define mbedtls_printf printf
46#endif /* MBEDTLS_PLATFORM_C */
47#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
48
Robert Cragie3d23b1d2015-12-15 07:38:11 +000049/* Implementation that should never be optimized out by the compiler */
50static void mbedtls_zeroize( void *v, size_t n ) {
51 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
52}
53
54/*
55 * Initialize context
56 */
57void mbedtls_cmac_init( mbedtls_cmac_context *ctx )
58{
59 memset( ctx, 0, sizeof( mbedtls_cmac_context ) );
60}
61
62/*
Brian Murrayb0c3c432016-05-18 14:29:51 -070063 * Multiplication by u in the Galois field of GF(2^n)
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000064 *
Brian Murray87e40402016-05-19 19:05:57 -070065 * As explained in the paper, this can be computed:
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000066 * If MSB(p) = 0, then p = (p << 1)
Brian Murrayb0c3c432016-05-18 14:29:51 -070067 * If MSB(p) = 1, then p = (p << 1) ^ R_n
68 * with R_64 = 0x1B and R_128 = 0x87
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000069 *
70 * Input and output MUST not point to the same buffer
Brian Murrayb0c3c432016-05-18 14:29:51 -070071 * Block size must be 8 byes or 16 bytes.
Robert Cragie3d23b1d2015-12-15 07:38:11 +000072 */
Brian Murrayb0c3c432016-05-18 14:29:51 -070073static int cmac_multiply_by_u( unsigned char *output,
74 const unsigned char *input,
Brian Murrayb439d452016-05-19 16:02:42 -070075 size_t blocksize )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000076{
Brian Murrayb0c3c432016-05-18 14:29:51 -070077 const unsigned char R_128 = 0x87;
78 const unsigned char R_64 = 0x1B;
79 unsigned char R_n, mask;
80 unsigned char overflow = 0x00;
81 int i, starting_index;
82
83 starting_index = blocksize -1;
84
Brian Murray6a3c0d22016-05-20 18:25:43 -070085 if( blocksize == 16 )
86 {
Brian Murrayb0c3c432016-05-18 14:29:51 -070087 R_n = R_128;
Brian Murray6a3c0d22016-05-20 18:25:43 -070088 } else if( blocksize == 8 )
89 {
Brian Murrayb0c3c432016-05-18 14:29:51 -070090 R_n = R_64;
Brian Murray6a3c0d22016-05-20 18:25:43 -070091 } else
92 {
Brian Murrayb439d452016-05-19 16:02:42 -070093 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
Brian Murrayb0c3c432016-05-18 14:29:51 -070094 }
95
Brian Murrayb0c3c432016-05-18 14:29:51 -070096 for( i = starting_index; i >= 0; i-- )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000097 {
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000098 output[i] = input[i] << 1 | overflow;
99 overflow = input[i] >> 7;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000100 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000101
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +0000102 /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
103 * using bit operations to avoid branches */
104 /* MSVC has a warning about unary minus on unsigned, but this is
105 * well-defined and precisely what we want to do here */
106#if defined(_MSC_VER)
107#pragma warning( push )
108#pragma warning( disable : 4146 )
109#endif
110 mask = - ( input[0] >> 7 );
111#if defined(_MSC_VER)
112#pragma warning( pop )
113#endif
114
Brian Murrayb0c3c432016-05-18 14:29:51 -0700115 output[starting_index] ^= R_n & mask;
Brian Murrayb439d452016-05-19 16:02:42 -0700116 return( 0 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000117}
118
119/*
120 * Generate subkeys
121 */
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000122static int cmac_generate_subkeys( mbedtls_cmac_context *ctx )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000123{
Brian Murray57863ad2016-05-19 16:38:36 -0700124 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700125 unsigned char *L;
126 size_t olen, block_size;
127
Brian Murrayb0c3c432016-05-18 14:29:51 -0700128 block_size = ctx->cipher_ctx.cipher_info->block_size;
129
Brian Murrayb439d452016-05-19 16:02:42 -0700130 L = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Brian Murray4b64ab62016-05-20 06:33:01 -0700131 if( L == NULL )
Brian Murray57863ad2016-05-19 16:38:36 -0700132 {
133 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
134 goto exit;
135 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000136 /* Calculate Ek(0) */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000137 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx,
Brian Murrayb0c3c432016-05-18 14:29:51 -0700138 L, block_size, L, &olen ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000139 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700140 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000141 }
142
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000143 /*
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000144 * Generate K1 and K2
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000145 */
Brian Murrayb439d452016-05-19 16:02:42 -0700146 if( ( ret = cmac_multiply_by_u( ctx->K1, L , block_size ) ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700147 goto exit;
Brian Murray6a3c0d22016-05-20 18:25:43 -0700148 if( ( ret = cmac_multiply_by_u( ctx->K2, ctx->K1 , block_size ) ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700149 goto exit;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000150
Brian Murrayb0c3c432016-05-18 14:29:51 -0700151 exit:
Brian Murray57863ad2016-05-19 16:38:36 -0700152 if( L != NULL )
153 mbedtls_zeroize( L, sizeof( L ) );
Brian Murray4b64ab62016-05-20 06:33:01 -0700154 mbedtls_free( L );
Brian Murrayb439d452016-05-19 16:02:42 -0700155 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000156}
157
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000158/*
159 * Set key and prepare context for use
160 */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000161int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx,
162 mbedtls_cipher_id_t cipher,
163 const unsigned char *key,
164 unsigned int keybits )
165{
Brian Murray57863ad2016-05-19 16:38:36 -0700166 int ret;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000167 const mbedtls_cipher_info_t *cipher_info;
168
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000169 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
170 MBEDTLS_MODE_ECB );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000171 if( cipher_info == NULL )
172 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
173
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000174 mbedtls_cipher_free( &ctx->cipher_ctx );
175
176 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
177 return( ret );
178
179 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000180 MBEDTLS_ENCRYPT ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000181 {
182 return( ret );
183 }
184
Brian Murray2cfa5072016-05-23 20:17:04 -0700185 ctx->K1 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) );
186 ctx->K2 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) );
187
188 if( ctx->K1 == NULL || ctx->K2 == NULL )
189 {
190 mbedtls_free(ctx->K1);
191 mbedtls_free(ctx->K2);
192 return( MBEDTLS_ERR_CMAC_ALLOC_FAILED );
193 }
194
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000195 return( cmac_generate_subkeys( ctx ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000196}
197
198/*
199 * Free context
200 */
201void mbedtls_cmac_free( mbedtls_cmac_context *ctx )
202{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700203 int block_size;
204 block_size = ctx->cipher_ctx.cipher_info->block_size;
205
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000206 mbedtls_cipher_free( &ctx->cipher_ctx );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700207
Brian Murray6a3c0d22016-05-20 18:25:43 -0700208 if( ctx->K1 != NULL )
209 mbedtls_zeroize( ctx->K1, block_size * sizeof( unsigned char ) );
210 if( ctx->K2 != NULL )
211 mbedtls_zeroize( ctx->K2, block_size * sizeof( unsigned char ) );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700212 mbedtls_free( ctx->K1 );
213 mbedtls_free( ctx->K2 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000214}
215
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000216/*
217 * Create padded last block from (partial) last block.
218 *
219 * We can't use the padding option from the cipher layer, as it only works for
220 * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
221 */
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000222static void cmac_pad( unsigned char padded_block[16],
Brian Murrayb0c3c432016-05-18 14:29:51 -0700223 size_t padded_block_len,
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000224 const unsigned char *last_block,
Brian Murrayb0c3c432016-05-18 14:29:51 -0700225 size_t last_block_len )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000226{
227 size_t j;
228
Brian Murrayb0c3c432016-05-18 14:29:51 -0700229 for( j = 0; j < padded_block_len; j++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000230 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700231 if( j < last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000232 padded_block[j] = last_block[j];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700233 else if( j == last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000234 padded_block[j] = 0x80;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000235 else
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000236 padded_block[j] = 0x00;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000237 }
238}
239
240/*
Brian Murrayb0c3c432016-05-18 14:29:51 -0700241 * XOR Block
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000242 * Here, macro results in smaller compiled code than static inline function
243 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700244#define XOR_BLOCK( o, i1, i2 ) \
245 for( i = 0; i < block_size; i++ ) \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000246 ( o )[i] = ( i1 )[i] ^ ( i2 )[i];
247
248/*
Brian Murray87e40402016-05-19 19:05:57 -0700249 * Update the CMAC state using an input block
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000250 */
251#define UPDATE_CMAC( x ) \
252do { \
Brian Murrayb0c3c432016-05-18 14:29:51 -0700253 XOR_BLOCK( state, ( x ), state ); \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000254 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \
Brian Murrayb0c3c432016-05-18 14:29:51 -0700255 state, block_size, \
256 state, &olen ) ) != 0 ) \
Brian Murray57863ad2016-05-19 16:38:36 -0700257 { \
258 goto exit; \
259 } \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000260} while( 0 )
261
262/*
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000263 * Generate tag on complete message
264 */
Manuel Pégourié-Gonnardab9c5fd2016-01-13 15:05:57 +0000265int mbedtls_cmac_generate( mbedtls_cmac_context *ctx,
266 const unsigned char *input, size_t in_len,
267 unsigned char *tag, size_t tag_len )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000268{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700269 unsigned char *state;
270 unsigned char *M_last;
Brian Murray57863ad2016-05-19 16:38:36 -0700271 int n, j, ret, needs_padding;
272 size_t olen, block_size, i;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700273
Brian Murrayb0c3c432016-05-18 14:29:51 -0700274 ret = 0;
275 block_size = ctx->cipher_ctx.cipher_info->block_size;
276
Brian Murrayb439d452016-05-19 16:02:42 -0700277 state = mbedtls_calloc( block_size, sizeof( unsigned char ) );
278 M_last = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000279
Brian Murray57863ad2016-05-19 16:38:36 -0700280 if( state == NULL || M_last == NULL )
281 {
282 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
283 goto exit;
284 }
285
Brian Murray87e40402016-05-19 19:05:57 -0700286 if( tag_len < 2 || tag_len > block_size || tag_len % 2 != 0 )
Brian Murray57863ad2016-05-19 16:38:36 -0700287 {
288 ret = MBEDTLS_ERR_CMAC_BAD_INPUT;
289 goto exit;
290 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000291
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000292 if( in_len == 0 )
293 needs_padding = 1;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000294 else
Brian Murrayb0c3c432016-05-18 14:29:51 -0700295 needs_padding = in_len % block_size != 0;
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000296
Brian Murrayb0c3c432016-05-18 14:29:51 -0700297 n = in_len / block_size + needs_padding;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000298
299 /* Calculate last block */
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000300 if( needs_padding )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000301 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700302 cmac_pad( M_last, block_size, input + block_size * ( n - 1 ), in_len % block_size );
303 XOR_BLOCK( M_last, M_last, ctx->K2 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000304 }
305 else
306 {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000307 /* Last block is complete block */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700308 XOR_BLOCK( M_last, input + block_size * ( n - 1 ), ctx->K1 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000309 }
310
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000311 for( j = 0; j < n - 1; j++ )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700312 UPDATE_CMAC( input + block_size * j );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000313
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000314 UPDATE_CMAC( M_last );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000315
Brian Murray00dc5f02016-05-19 14:23:50 -0700316 memcpy( tag, state, tag_len );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000317
Brian Murrayb0c3c432016-05-18 14:29:51 -0700318 exit:
Brian Murray4b64ab62016-05-20 06:33:01 -0700319 mbedtls_free( state );
320 mbedtls_free( M_last );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700321 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000322}
323
Brian Murrayb0c3c432016-05-18 14:29:51 -0700324#undef XOR_BLOCK
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000325#undef UPDATE_CMAC
326
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000327/*
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000328 * Verify tag on complete message
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000329 */
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000330int mbedtls_cmac_verify( mbedtls_cmac_context *ctx,
331 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000332 const unsigned char *tag, size_t tag_len )
333{
334 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700335 unsigned char *check_tag;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000336 unsigned char i;
337 int diff;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000338
Brian Murrayb439d452016-05-19 16:02:42 -0700339 check_tag = mbedtls_calloc( ctx->cipher_ctx.cipher_info->block_size,
340 sizeof( unsigned char ) );
Brian Murray4b64ab62016-05-20 06:33:01 -0700341 if( check_tag == NULL )
Brian Murray57863ad2016-05-19 16:38:36 -0700342 {
343 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
344 goto exit;
345 }
Brian Murrayb0c3c432016-05-18 14:29:51 -0700346
Manuel Pégourié-Gonnardab9c5fd2016-01-13 15:05:57 +0000347 if( ( ret = mbedtls_cmac_generate( ctx, input, in_len,
348 check_tag, tag_len ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000349 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700350 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000351 }
352
353 /* Check tag in "constant-time" */
354 for( diff = 0, i = 0; i < tag_len; i++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000355 diff |= tag[i] ^ check_tag[i];
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000356
357 if( diff != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700358 ret = MBEDTLS_ERR_CMAC_VERIFY_FAILED;
359 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000360
Brian Murrayb0c3c432016-05-18 14:29:51 -0700361 exit:
Brian Murray4b64ab62016-05-20 06:33:01 -0700362 mbedtls_free( check_tag );
Brian Murrayb439d452016-05-19 16:02:42 -0700363 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000364}
365
Brian Murrayb439d452016-05-19 16:02:42 -0700366#ifdef MBEDTLS_AES_C
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000367/*
368 * PRF based on CMAC with AES-128
Brian Murrayb0c3c432016-05-18 14:29:51 -0700369 * See RFC 4615
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000370 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700371int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000372 const unsigned char *input, size_t in_len,
Brian Murrayb439d452016-05-19 16:02:42 -0700373 unsigned char tag[16] )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000374{
375 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700376 mbedtls_cmac_context ctx;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000377 unsigned char zero_key[16];
378 unsigned char int_key[16];
379
Brian Murrayb439d452016-05-19 16:02:42 -0700380 mbedtls_cmac_init(&ctx );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700381
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000382 if( key_length == 16 )
383 {
384 /* Use key as is */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000385 memcpy( int_key, key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000386 }
387 else
388 {
389 mbedtls_cmac_context zero_ctx;
390
Brian Murrayb439d452016-05-19 16:02:42 -0700391 /* Key is AES_CMAC( 0, key ) */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000392 mbedtls_cmac_init( &zero_ctx );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000393 memset( zero_key, 0, 16 );
394 ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES,
Brian Murray6a3c0d22016-05-20 18:25:43 -0700395 zero_key, 8 * sizeof( zero_key ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000396 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700397 goto exit;
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000398
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000399 ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000400 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700401 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000402 }
403
Brian Murrayb0c3c432016-05-18 14:29:51 -0700404 ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
Brian Murray6a3c0d22016-05-20 18:25:43 -0700405 int_key, 8 * sizeof( int_key ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000406 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700407 goto exit;
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000408
Brian Murrayb0c3c432016-05-18 14:29:51 -0700409 ret = mbedtls_cmac_generate( &ctx, input, in_len, tag, 16 );
410
411 exit:
Brian Murray6a3c0d22016-05-20 18:25:43 -0700412 mbedtls_zeroize( int_key, sizeof( int_key ) );
413 mbedtls_cmac_free( &ctx );
414 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000415}
Brian Murrayb439d452016-05-19 16:02:42 -0700416#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000417
Brian Murray0f6af732016-05-19 15:59:23 -0700418#ifdef MBEDTLS_SELF_TEST
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000419/*
Brian Murray0f6af732016-05-19 15:59:23 -0700420 * CMAC test data from SP800-38B Appendix D.1 (corrected)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000421 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
Brian Murray0f6af732016-05-19 15:59:23 -0700422 *
423 * AES-CMAC-PRF-128 test data from RFC 4615
424 * https://tools.ietf.org/html/rfc4615#page-4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000425 */
426
Brian Murray0f6af732016-05-19 15:59:23 -0700427#define NB_CMAC_TESTS_PER_KEY 4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000428#define NB_PRF_TESTS 3
Brian Murray0f6af732016-05-19 15:59:23 -0700429#define AES_BLOCK_SIZE 16
430#define DES3_BLOCK_SIZE 8
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000431
Brian Murray0f6af732016-05-19 15:59:23 -0700432#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
433/* All CMAC test inputs are truncated from the same 64 byte buffer. */
434static const unsigned char test_message[] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000435 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
436 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
437 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
438 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
439 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
440 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
441 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
442 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
443};
Brian Murray0cf14c12016-05-23 12:49:50 -0700444
445
Brian Murray0f6af732016-05-19 15:59:23 -0700446#endif /* defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000447
Brian Murray0f6af732016-05-19 15:59:23 -0700448#ifdef MBEDTLS_AES_C
449/* Truncation point of message for AES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700450static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700451 0,
452 16,
453 40,
454 64
455};
456
457/* AES 128 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700458static const unsigned char aes_128_key[16] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700459 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
460 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
461};
462static const unsigned char aes_128_subkeys[2][AES_BLOCK_SIZE] = {
463 {
464 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
465 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
466 },
467 {
468 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
469 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
470 }
471};
472static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000473 {
474 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
475 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
476 },
477 {
478 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
479 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
480 },
481 {
482 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
483 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
484 },
485 {
486 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
487 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
488 }
489};
490
Brian Murray0f6af732016-05-19 15:59:23 -0700491/* AES 192 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700492static const unsigned char aes_192_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700493 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
494 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
495 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000496};
Brian Murray0f6af732016-05-19 15:59:23 -0700497static const unsigned char aes_192_subkeys[2][AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700498 {
Brian Murray0f6af732016-05-19 15:59:23 -0700499 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
500 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
Brian Murrayb0c3c432016-05-18 14:29:51 -0700501 },
502 {
Brian Murray0f6af732016-05-19 15:59:23 -0700503 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
504 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
Brian Murrayb0c3c432016-05-18 14:29:51 -0700505 }
506};
Brian Murray0f6af732016-05-19 15:59:23 -0700507static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700508 {
509 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
510 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
511 },
512 {
513 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
514 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
515 },
516 {
517 0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad,
518 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e
519 },
520 {
521 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
522 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
523 }
524};
525
Brian Murray0f6af732016-05-19 15:59:23 -0700526/* AES 256 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700527static const unsigned char aes_256_key[32] = {
Brian Murray87e40402016-05-19 19:05:57 -0700528 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
529 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
530 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
531 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
Brian Murray0f6af732016-05-19 15:59:23 -0700532};
533static const unsigned char aes_256_subkeys[2][AES_BLOCK_SIZE] = {
534 {
535 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
536 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
537 },
538 {
539 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
540 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
541 }
542};
543static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
544 {
545 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
546 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
547 },
548 {
549 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
550 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
551 },
552 {
553 0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2,
554 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6
555 },
556 {
557 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
558 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
559 }
560};
561#endif /* MBEDTLS_AES_C */
562
563#ifdef MBEDTLS_DES_C
564/* Truncation point of message for 3DES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700565static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700566 0,
567 8,
568 20,
569 32
570};
571
572/* 3DES 2 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700573static const unsigned char des3_2key_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700574 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5,
575 0x8a, 0x3d, 0x10, 0xba, 0x80, 0x57, 0x0d, 0x38,
576 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5
Brian Murray0f6af732016-05-19 15:59:23 -0700577};
578static const unsigned char des3_2key_subkeys[2][8] = {
579 {
580 0x8e, 0xcf, 0x37, 0x3e, 0xd7, 0x1a, 0xfa, 0xef
581 },
582 {
583 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5
584 }
585};
Brian Murray57863ad2016-05-19 16:38:36 -0700586static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700587 {
588 0xbd, 0x2e, 0xbf, 0x9a, 0x3b, 0xa0, 0x03, 0x61
589 },
590 {
591 0x4f, 0xf2, 0xab, 0x81, 0x3c, 0x53, 0xce, 0x83
592 },
593 {
594 0x62, 0xdd, 0x1b, 0x47, 0x19, 0x02, 0xbd, 0x4e
595 },
596 {
597 0x31, 0xb1, 0xe4, 0x31, 0xda, 0xbc, 0x4e, 0xb8
598 }
599};
600
Brian Murray0f6af732016-05-19 15:59:23 -0700601/* 3DES 3 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700602static const unsigned char des3_3key_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700603 0x8a, 0xa8, 0x3b, 0xf8, 0xcb, 0xda, 0x10, 0x62,
604 0x0b, 0xc1, 0xbf, 0x19, 0xfb, 0xb6, 0xcd, 0x58,
605 0xbc, 0x31, 0x3d, 0x4a, 0x37, 0x1c, 0xa8, 0xb5
Brian Murray0f6af732016-05-19 15:59:23 -0700606};
607static const unsigned char des3_3key_subkeys[2][8] = {
608 {
609 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f
610 },
611 {
612 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5
613 }
614};
Brian Murray57863ad2016-05-19 16:38:36 -0700615static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700616 {
617 0xb7, 0xa6, 0x88, 0xe1, 0x22, 0xff, 0xaf, 0x95
618 },
619 {
620 0x8e, 0x8f, 0x29, 0x31, 0x36, 0x28, 0x37, 0x97
621 },
622 {
623 0x74, 0x3d, 0xdb, 0xe0, 0xce, 0x2d, 0xc2, 0xed
624 },
625 {
626 0x33, 0xe6, 0xb1, 0x09, 0x24, 0x00, 0xea, 0xe5
627 }
628};
629
Brian Murray0f6af732016-05-19 15:59:23 -0700630#endif /* MBEDTLS_DES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700631
Brian Murray0f6af732016-05-19 15:59:23 -0700632#ifdef MBEDTLS_AES_C
633/* AES AES-CMAC-PRF-128 Test Data */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000634static const unsigned char PRFK[] = {
635 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
636 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
637 0xed, 0xcb
638};
639
640/* Sizes in bytes */
641static const size_t PRFKlen[NB_PRF_TESTS] = {
642 18,
643 16,
644 10
645};
646
647/* PRF M */
648static const unsigned char PRFM[] = {
649 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
650 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000651 0x10, 0x11, 0x12, 0x13
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000652};
653
654static const unsigned char PRFT[NB_PRF_TESTS][16] = {
655 {
656 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
657 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
658 },
659 {
660 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
661 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
662 },
663 {
664 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
665 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
666 }
667};
Brian Murray0f6af732016-05-19 15:59:23 -0700668#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000669
Brian Murrayae1cb122016-05-23 15:01:59 -0700670static inline int cmac_test_wth_cipher( int verbose,
671 const char* testname,
672 const unsigned char* key,
673 int keybits,
674 const unsigned char* messages,
675 const unsigned int message_lengths[4],
676 const unsigned char* subkeys,
677 const unsigned char* expected_result,
678 mbedtls_cipher_id_t cipher_id,
679 int block_size )
Brian Murray00dc5f02016-05-19 14:23:50 -0700680{
Brian Murray87e40402016-05-19 19:05:57 -0700681 const int num_tests = 4;
682 mbedtls_cmac_context ctx;
Brian Murray00dc5f02016-05-19 14:23:50 -0700683 int i, ret;
684 unsigned char* tag;
685
686 tag = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Brian Murray6a3c0d22016-05-20 18:25:43 -0700687 if( tag == NULL )
688 {
Brian Murray57863ad2016-05-19 16:38:36 -0700689 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
690 goto exit;
691 }
692
Brian Murray00dc5f02016-05-19 14:23:50 -0700693 mbedtls_cmac_init( &ctx );
694
695 if( ( ret = mbedtls_cmac_setkey( &ctx, cipher_id, key, keybits ) ) != 0 )
696 {
697 if( verbose != 0 )
698 mbedtls_printf( " CMAC: setup failed\n" );
699 goto exit;
700 }
701
702 if( ( ret = memcmp( ctx.K1, subkeys, block_size ) != 0 ) ||
703 ( ret = memcmp( ctx.K2, &subkeys[block_size], block_size ) != 0 ) )
704 {
705 if( verbose != 0 )
706 mbedtls_printf( " CMAC: subkey generation failed\n" );
707 goto exit;
708 }
709
710 for( i = 0; i < num_tests; i++ )
711 {
712 if( verbose != 0 )
713 mbedtls_printf( " %s CMAC #%u: ", testname, i +1 );
714
715 if( ( ret = mbedtls_cmac_generate( &ctx, messages, message_lengths[i], tag, block_size ) ) != 0 )
716 {
717 if( verbose != 0 )
718 mbedtls_printf( "failed\n" );
719 goto exit;
720 }
721 if( ( ret = memcmp( tag, &expected_result[i * block_size], block_size ) ) != 0 )
722 {
723 if( verbose != 0 )
724 mbedtls_printf( "failed\n" );
725 goto exit;
726 }
727
728 if( ( ret = mbedtls_cmac_verify( &ctx, messages, message_lengths[i], &expected_result[i * block_size], block_size ) != 0 ) )
729 {
Brian Murray4b64ab62016-05-20 06:33:01 -0700730 if( verbose != 0 )
731 mbedtls_printf( "failed\n" );
732 goto exit;
Brian Murray00dc5f02016-05-19 14:23:50 -0700733 }
734 mbedtls_printf( "passed\n" );
735 }
736 exit:
Brian Murray4b64ab62016-05-20 06:33:01 -0700737 mbedtls_free( tag );
Brian Murray00dc5f02016-05-19 14:23:50 -0700738 mbedtls_cmac_free( &ctx );
739 return( ret );
740}
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000741
Brian Murray0f6af732016-05-19 15:59:23 -0700742#ifdef MBEDTLS_AES_C
Brian Murrayae1cb122016-05-23 15:01:59 -0700743static inline int test_aes128_cmac_prf( int verbose )
Brian Murray6a3c0d22016-05-20 18:25:43 -0700744{
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000745 int i;
746 int ret;
Brian Murray0f6af732016-05-19 15:59:23 -0700747 unsigned char tag[16];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700748 for( i = 0; i < NB_PRF_TESTS; i++ )
749 {
Brian Murray0f6af732016-05-19 15:59:23 -0700750 mbedtls_printf( " AES CMAC 128 PRF #%u: ", i );
751 ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, tag );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700752 if( ret != 0 ||
753 memcmp( tag, PRFT[i], 16 ) != 0 )
754 {
755 if( verbose != 0 )
756 mbedtls_printf( "failed\n" );
757
Brian Murray0f6af732016-05-19 15:59:23 -0700758 return( ret );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700759 } else if( verbose != 0 )
760 {
761 mbedtls_printf( "passed\n" );
762 }
763 }
Brian Murray0f6af732016-05-19 15:59:23 -0700764 return( ret );
765}
766#endif /* MBEDTLS_AES_C */
767
768int mbedtls_cmac_self_test( int verbose )
769{
770 int ret;
771
772#ifdef MBEDTLS_AES_C
Brian Murrayae1cb122016-05-23 15:01:59 -0700773 if( ( ret = cmac_test_wth_cipher( verbose,
774 "AES 128",
775 aes_128_key,
776 128,
777 test_message,
778 aes_message_lengths,
779 (const unsigned char*) aes_128_subkeys,
780 (const unsigned char*) aes_128_expected_result,
781 MBEDTLS_CIPHER_ID_AES,
782 AES_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700783 {
784 return( ret );
785 }
Brian Murray0f6af732016-05-19 15:59:23 -0700786
Brian Murrayae1cb122016-05-23 15:01:59 -0700787 if( ( ret = cmac_test_wth_cipher( verbose,
788 "AES 192",
789 aes_192_key,
790 192,
791 test_message,
792 aes_message_lengths,
793 (const unsigned char*) aes_192_subkeys,
794 (const unsigned char*) aes_192_expected_result,
795 MBEDTLS_CIPHER_ID_AES,
796 AES_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700797 {
798 return( ret );
799 }
Brian Murray0f6af732016-05-19 15:59:23 -0700800
Brian Murrayae1cb122016-05-23 15:01:59 -0700801 if( ( ret = cmac_test_wth_cipher ( verbose,
802 "AES 256",
803 aes_256_key,
804 256,
805 test_message,
806 aes_message_lengths,
807 (const unsigned char*) aes_256_subkeys,
808 (const unsigned char*) aes_256_expected_result,
809 MBEDTLS_CIPHER_ID_AES,
810 AES_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700811 {
812 return( ret );
813 }
Brian Murray0f6af732016-05-19 15:59:23 -0700814#endif /* MBEDTLS_AES_C */
815
816#ifdef MBEDTLS_DES_C
Brian Murrayae1cb122016-05-23 15:01:59 -0700817 if( ( ret = cmac_test_wth_cipher( verbose,
818 "3DES 2 key",
819 des3_2key_key,
820 192,
821 test_message,
822 des3_message_lengths,
823 (const unsigned char*) des3_2key_subkeys,
824 (const unsigned char*) des3_2key_expected_result,
825 MBEDTLS_CIPHER_ID_3DES,
826 DES3_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700827 {
828 return( ret );
829 }
Brian Murray0f6af732016-05-19 15:59:23 -0700830
Brian Murrayae1cb122016-05-23 15:01:59 -0700831 if( ( ret = cmac_test_wth_cipher( verbose,
832 "3DES 3 key",
833 des3_3key_key,
834 192,
835 test_message,
836 des3_message_lengths,
837 (const unsigned char*) des3_3key_subkeys,
838 (const unsigned char*) des3_3key_expected_result,
839 MBEDTLS_CIPHER_ID_3DES,
840 DES3_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700841 {
842 return( ret );
843 }
Brian Murray0f6af732016-05-19 15:59:23 -0700844#endif /* MBEDTLS_DES_C */
845
846#ifdef MBEDTLS_AES_C
Brian Murray9044b022016-05-19 16:36:56 -0700847 if( ( ret = test_aes128_cmac_prf( verbose ) != 0 ) )
848 return( ret );
Brian Murray0f6af732016-05-19 15:59:23 -0700849#endif /* MBEDTLS_AES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700850
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000851 if( verbose != 0 )
852 mbedtls_printf( "\n" );
Brian Murray0f6af732016-05-19 15:59:23 -0700853
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000854 return( 0 );
855}
856
Brian Murray0f6af732016-05-19 15:59:23 -0700857#endif /* MBEDTLS_SELF_TEST */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000858
859#endif /* MBEDTLS_CMAC_C */