blob: 4c25a67d03e89f666a253958197e596a0af49a4e [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
Brian Murray00dc5f02016-05-19 14:23:50 -070062
Robert Cragie3d23b1d2015-12-15 07:38:11 +000063/*
Brian Murrayb0c3c432016-05-18 14:29:51 -070064 * Multiplication by u in the Galois field of GF(2^n)
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000065 *
Brian Murrayb0c3c432016-05-18 14:29:51 -070066 * As explained in the paper, this can computed:
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000067 * If MSB(p) = 0, then p = (p << 1)
Brian Murrayb0c3c432016-05-18 14:29:51 -070068 * If MSB(p) = 1, then p = (p << 1) ^ R_n
69 * with R_64 = 0x1B and R_128 = 0x87
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000070 *
71 * Input and output MUST not point to the same buffer
Brian Murrayb0c3c432016-05-18 14:29:51 -070072 * Block size must be 8 byes or 16 bytes.
Robert Cragie3d23b1d2015-12-15 07:38:11 +000073 */
Brian Murrayb0c3c432016-05-18 14:29:51 -070074static int cmac_multiply_by_u( unsigned char *output,
75 const unsigned char *input,
Brian Murrayb439d452016-05-19 16:02:42 -070076 size_t blocksize )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000077{
Robert Cragie3d23b1d2015-12-15 07:38:11 +000078
Brian Murrayb0c3c432016-05-18 14:29:51 -070079 const unsigned char R_128 = 0x87;
80 const unsigned char R_64 = 0x1B;
81 unsigned char R_n, mask;
82 unsigned char overflow = 0x00;
83 int i, starting_index;
84
85 starting_index = blocksize -1;
86
Brian Murrayb439d452016-05-19 16:02:42 -070087 if( blocksize == 16 ){
Brian Murrayb0c3c432016-05-18 14:29:51 -070088 R_n = R_128;
Brian Murrayb439d452016-05-19 16:02:42 -070089 } else if( blocksize == 8 ) {
Brian Murrayb0c3c432016-05-18 14:29:51 -070090 R_n = R_64;
91 } else {
Brian Murrayb439d452016-05-19 16:02:42 -070092 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
Brian Murrayb0c3c432016-05-18 14:29:51 -070093 }
94
95
96 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
128 ret = 0;
129 block_size = ctx->cipher_ctx.cipher_info->block_size;
130
Brian Murrayb439d452016-05-19 16:02:42 -0700131 L = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Brian Murray57863ad2016-05-19 16:38:36 -0700132 if( L == NULL)
133 {
134 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
135 goto exit;
136 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000137 /* Calculate Ek(0) */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700138 memset( L, 0, block_size );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000139 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx,
Brian Murrayb0c3c432016-05-18 14:29:51 -0700140 L, block_size, L, &olen ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000141 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700142 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000143 }
144
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000145 /*
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000146 * Generate K1 and K2
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000147 */
Brian Murrayb439d452016-05-19 16:02:42 -0700148 if( ( ret = cmac_multiply_by_u( ctx->K1, L , block_size ) ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700149 goto exit;
Brian Murrayb439d452016-05-19 16:02:42 -0700150 if( ( cmac_multiply_by_u( ctx->K2, ctx->K1 , block_size ) ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700151 goto exit;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000152
Brian Murrayb0c3c432016-05-18 14:29:51 -0700153 exit:
Brian Murray57863ad2016-05-19 16:38:36 -0700154 if( L != NULL )
155 mbedtls_zeroize( L, sizeof( L ) );
Brian Murrayb439d452016-05-19 16:02:42 -0700156 free( L );
157 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000158}
159
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000160/*
161 * Set key and prepare context for use
162 */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000163int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx,
164 mbedtls_cipher_id_t cipher,
165 const unsigned char *key,
166 unsigned int keybits )
167{
Brian Murray57863ad2016-05-19 16:38:36 -0700168 int ret;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000169 const mbedtls_cipher_info_t *cipher_info;
170
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000171 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
172 MBEDTLS_MODE_ECB );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000173 if( cipher_info == NULL )
174 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
175
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000176 mbedtls_cipher_free( &ctx->cipher_ctx );
177
178 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
179 return( ret );
180
181 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000182 MBEDTLS_ENCRYPT ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000183 {
184 return( ret );
185 }
186
Brian Murray2cfa5072016-05-23 20:17:04 -0700187 ctx->K1 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) );
188 ctx->K2 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) );
189
190 if( ctx->K1 == NULL || ctx->K2 == NULL )
191 {
192 mbedtls_free(ctx->K1);
193 mbedtls_free(ctx->K2);
194 return( MBEDTLS_ERR_CMAC_ALLOC_FAILED );
195 }
196
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000197 return( cmac_generate_subkeys( ctx ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000198}
199
200/*
201 * Free context
202 */
203void mbedtls_cmac_free( mbedtls_cmac_context *ctx )
204{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700205 int block_size;
206 block_size = ctx->cipher_ctx.cipher_info->block_size;
207
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000208 mbedtls_cipher_free( &ctx->cipher_ctx );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700209
Brian Murrayb439d452016-05-19 16:02:42 -0700210 mbedtls_zeroize( ctx->K1, block_size * sizeof( unsigned char ) );
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/*
249 * Update the CMAC state using an input block x
250 */
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 )
268
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000269{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700270
271 unsigned char *state;
272 unsigned char *M_last;
Brian Murray57863ad2016-05-19 16:38:36 -0700273 int n, j, ret, needs_padding;
274 size_t olen, block_size, i;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700275
276
277 ret = 0;
278 block_size = ctx->cipher_ctx.cipher_info->block_size;
279
Brian Murrayb439d452016-05-19 16:02:42 -0700280 state = mbedtls_calloc( block_size, sizeof( unsigned char ) );
281 M_last = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000282
Brian Murray57863ad2016-05-19 16:38:36 -0700283 if( state == NULL || M_last == NULL )
284 {
285 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
286 goto exit;
287 }
288
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000289 /*
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000290 * Check in_len requirements: SP800-38B A
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000291 * 4 is a worst case bottom limit
292 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700293 if( tag_len < 4 || tag_len > block_size || tag_len % 2 != 0 )
Brian Murray57863ad2016-05-19 16:38:36 -0700294 {
295 ret = MBEDTLS_ERR_CMAC_BAD_INPUT;
296 goto exit;
297 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000298
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000299 if( in_len == 0 )
300 needs_padding = 1;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000301 else
Brian Murrayb0c3c432016-05-18 14:29:51 -0700302 needs_padding = in_len % block_size != 0;
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000303
Brian Murrayb0c3c432016-05-18 14:29:51 -0700304 n = in_len / block_size + needs_padding;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000305
306 /* Calculate last block */
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000307 if( needs_padding )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000308 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700309 cmac_pad( M_last, block_size, input + block_size * ( n - 1 ), in_len % block_size );
310 XOR_BLOCK( M_last, M_last, ctx->K2 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000311 }
312 else
313 {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000314 /* Last block is complete block */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700315 XOR_BLOCK( M_last, input + block_size * ( n - 1 ), ctx->K1 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000316 }
317
Brian Murrayb0c3c432016-05-18 14:29:51 -0700318 memset( state, 0, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000319
320 for( j = 0; j < n - 1; j++ )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700321 UPDATE_CMAC( input + block_size * j );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000322
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000323 UPDATE_CMAC( M_last );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000324
Brian Murray00dc5f02016-05-19 14:23:50 -0700325 memcpy( tag, state, tag_len );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000326
Brian Murrayb0c3c432016-05-18 14:29:51 -0700327 exit:
Brian Murrayb439d452016-05-19 16:02:42 -0700328 free( state );
329 free( M_last );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700330 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000331}
332
Brian Murrayb0c3c432016-05-18 14:29:51 -0700333#undef XOR_BLOCK
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000334#undef UPDATE_CMAC
335
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000336/*
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000337 * Verify tag on complete message
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000338 */
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000339int mbedtls_cmac_verify( mbedtls_cmac_context *ctx,
340 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000341 const unsigned char *tag, size_t tag_len )
342{
343 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700344 unsigned char *check_tag;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000345 unsigned char i;
346 int diff;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000347
Brian Murrayb439d452016-05-19 16:02:42 -0700348 check_tag = mbedtls_calloc( ctx->cipher_ctx.cipher_info->block_size,
349 sizeof( unsigned char ) );
Brian Murray57863ad2016-05-19 16:38:36 -0700350 if(check_tag == NULL)
351 {
352 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
353 goto exit;
354 }
Brian Murrayb0c3c432016-05-18 14:29:51 -0700355
Manuel Pégourié-Gonnardab9c5fd2016-01-13 15:05:57 +0000356 if( ( ret = mbedtls_cmac_generate( ctx, input, in_len,
357 check_tag, tag_len ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000358 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700359 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000360 }
361
362 /* Check tag in "constant-time" */
363 for( diff = 0, i = 0; i < tag_len; i++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000364 diff |= tag[i] ^ check_tag[i];
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000365
366 if( diff != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700367 ret = MBEDTLS_ERR_CMAC_VERIFY_FAILED;
368 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000369
Brian Murrayb0c3c432016-05-18 14:29:51 -0700370 exit:
Brian Murrayb439d452016-05-19 16:02:42 -0700371 free( check_tag );
372 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000373}
374
Brian Murrayb439d452016-05-19 16:02:42 -0700375#ifdef MBEDTLS_AES_C
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000376/*
377 * PRF based on CMAC with AES-128
Brian Murrayb0c3c432016-05-18 14:29:51 -0700378 * See RFC 4615
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000379 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700380int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000381 const unsigned char *input, size_t in_len,
Brian Murrayb439d452016-05-19 16:02:42 -0700382 unsigned char tag[16] )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000383{
384 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700385 mbedtls_cmac_context ctx;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000386 unsigned char zero_key[16];
387 unsigned char int_key[16];
388
Brian Murrayb439d452016-05-19 16:02:42 -0700389 mbedtls_cmac_init(&ctx );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700390
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000391 if( key_length == 16 )
392 {
393 /* Use key as is */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000394 memcpy( int_key, key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000395 }
396 else
397 {
398 mbedtls_cmac_context zero_ctx;
399
Brian Murrayb439d452016-05-19 16:02:42 -0700400 /* Key is AES_CMAC( 0, key ) */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000401 mbedtls_cmac_init( &zero_ctx );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000402 memset( zero_key, 0, 16 );
403 ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES,
404 zero_key, 8 * sizeof zero_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000405 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700406 goto exit;
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000407
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000408 ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000409 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700410 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000411 }
412
Brian Murrayb0c3c432016-05-18 14:29:51 -0700413 ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000414 int_key, 8 * sizeof int_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000415 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700416 goto exit;
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000417
418 mbedtls_zeroize( int_key, sizeof( int_key ) );
419
Brian Murrayb0c3c432016-05-18 14:29:51 -0700420 ret = mbedtls_cmac_generate( &ctx, input, in_len, tag, 16 );
421
422 exit:
Brian Murrayb439d452016-05-19 16:02:42 -0700423 mbedtls_cmac_free( &ctx );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700424 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000425}
Brian Murrayb439d452016-05-19 16:02:42 -0700426#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000427
Brian Murray0f6af732016-05-19 15:59:23 -0700428#ifdef MBEDTLS_SELF_TEST
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000429/*
Brian Murray0f6af732016-05-19 15:59:23 -0700430 * CMAC test data from SP800-38B Appendix D.1 (corrected)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000431 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
Brian Murray0f6af732016-05-19 15:59:23 -0700432 *
433 * AES-CMAC-PRF-128 test data from RFC 4615
434 * https://tools.ietf.org/html/rfc4615#page-4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000435 */
436
Brian Murray0f6af732016-05-19 15:59:23 -0700437#define NB_CMAC_TESTS_PER_KEY 4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000438#define NB_PRF_TESTS 3
Brian Murray0f6af732016-05-19 15:59:23 -0700439#define AES_BLOCK_SIZE 16
440#define DES3_BLOCK_SIZE 8
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000441
Brian Murray0f6af732016-05-19 15:59:23 -0700442#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
443/* All CMAC test inputs are truncated from the same 64 byte buffer. */
444static const unsigned char test_message[] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000445 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
446 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
447 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
448 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
449 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
450 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
451 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
452 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
453};
Brian Murray0f6af732016-05-19 15:59:23 -0700454#endif /* defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000455
Brian Murray0f6af732016-05-19 15:59:23 -0700456#ifdef MBEDTLS_AES_C
457/* Truncation point of message for AES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700458static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700459 0,
460 16,
461 40,
462 64
463};
464
465/* AES 128 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700466static const unsigned char aes_128_key[16] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700467 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
468 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
469};
470static const unsigned char aes_128_subkeys[2][AES_BLOCK_SIZE] = {
471 {
472 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
473 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
474 },
475 {
476 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
477 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
478 }
479};
480static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000481 {
482 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
483 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
484 },
485 {
486 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
487 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
488 },
489 {
490 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
491 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
492 },
493 {
494 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
495 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
496 }
497};
498
Brian Murray0f6af732016-05-19 15:59:23 -0700499/* AES 192 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700500static const unsigned char aes_192_key[24] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700501 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
502 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
503 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000504};
Brian Murray0f6af732016-05-19 15:59:23 -0700505static const unsigned char aes_192_subkeys[2][AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700506 {
Brian Murray0f6af732016-05-19 15:59:23 -0700507 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
508 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
Brian Murrayb0c3c432016-05-18 14:29:51 -0700509 },
510 {
Brian Murray0f6af732016-05-19 15:59:23 -0700511 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
512 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
Brian Murrayb0c3c432016-05-18 14:29:51 -0700513 }
514};
Brian Murray0f6af732016-05-19 15:59:23 -0700515static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700516 {
517 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
518 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
519 },
520 {
521 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
522 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
523 },
524 {
525 0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad,
526 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e
527 },
528 {
529 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
530 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
531 }
532};
533
Brian Murray0f6af732016-05-19 15:59:23 -0700534/* AES 256 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700535static const unsigned char aes_256_key[32] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700536 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
537 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
538 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
539 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
540};
541static const unsigned char aes_256_subkeys[2][AES_BLOCK_SIZE] = {
542 {
543 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
544 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
545 },
546 {
547 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
548 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
549 }
550};
551static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
552 {
553 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
554 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
555 },
556 {
557 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
558 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
559 },
560 {
561 0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2,
562 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6
563 },
564 {
565 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
566 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
567 }
568};
569#endif /* MBEDTLS_AES_C */
570
571#ifdef MBEDTLS_DES_C
572/* Truncation point of message for 3DES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700573static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700574 0,
575 8,
576 20,
577 32
578};
579
580/* 3DES 2 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700581static const unsigned char des3_2key_key[24] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700582 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5,
583 0x8a, 0x3d, 0x10, 0xba, 0x80, 0x57, 0x0d, 0x38,
584 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5
585};
586static const unsigned char des3_2key_subkeys[2][8] = {
587 {
588 0x8e, 0xcf, 0x37, 0x3e, 0xd7, 0x1a, 0xfa, 0xef
589 },
590 {
591 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5
592 }
593};
Brian Murray57863ad2016-05-19 16:38:36 -0700594static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700595 {
596 0xbd, 0x2e, 0xbf, 0x9a, 0x3b, 0xa0, 0x03, 0x61
597 },
598 {
599 0x4f, 0xf2, 0xab, 0x81, 0x3c, 0x53, 0xce, 0x83
600 },
601 {
602 0x62, 0xdd, 0x1b, 0x47, 0x19, 0x02, 0xbd, 0x4e
603 },
604 {
605 0x31, 0xb1, 0xe4, 0x31, 0xda, 0xbc, 0x4e, 0xb8
606 }
607};
608
Brian Murray0f6af732016-05-19 15:59:23 -0700609/* 3DES 3 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700610static const unsigned char des3_3key_key[24] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700611 0x8a, 0xa8, 0x3b, 0xf8, 0xcb, 0xda, 0x10, 0x62,
612 0x0b, 0xc1, 0xbf, 0x19, 0xfb, 0xb6, 0xcd, 0x58,
613 0xbc, 0x31, 0x3d, 0x4a, 0x37, 0x1c, 0xa8, 0xb5
614};
615static const unsigned char des3_3key_subkeys[2][8] = {
616 {
617 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f
618 },
619 {
620 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5
621 }
622};
Brian Murray57863ad2016-05-19 16:38:36 -0700623static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700624 {
625 0xb7, 0xa6, 0x88, 0xe1, 0x22, 0xff, 0xaf, 0x95
626 },
627 {
628 0x8e, 0x8f, 0x29, 0x31, 0x36, 0x28, 0x37, 0x97
629 },
630 {
631 0x74, 0x3d, 0xdb, 0xe0, 0xce, 0x2d, 0xc2, 0xed
632 },
633 {
634 0x33, 0xe6, 0xb1, 0x09, 0x24, 0x00, 0xea, 0xe5
635 }
636};
637
Brian Murray0f6af732016-05-19 15:59:23 -0700638#endif /* MBEDTLS_DES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700639
Brian Murray0f6af732016-05-19 15:59:23 -0700640#ifdef MBEDTLS_AES_C
641/* AES AES-CMAC-PRF-128 Test Data */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000642static const unsigned char PRFK[] = {
643 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
644 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
645 0xed, 0xcb
646};
647
648/* Sizes in bytes */
649static const size_t PRFKlen[NB_PRF_TESTS] = {
650 18,
651 16,
652 10
653};
654
655/* PRF M */
656static const unsigned char PRFM[] = {
657 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
658 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000659 0x10, 0x11, 0x12, 0x13
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000660};
661
662static const unsigned char PRFT[NB_PRF_TESTS][16] = {
663 {
664 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
665 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
666 },
667 {
668 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
669 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
670 },
671 {
672 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
673 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
674 }
675};
Brian Murray0f6af732016-05-19 15:59:23 -0700676#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000677
Brian Murrayb439d452016-05-19 16:02:42 -0700678int test_cmac_with_cipher( int verbose,
Brian Murray57863ad2016-05-19 16:38:36 -0700679 char* testname,
Brian Murray00dc5f02016-05-19 14:23:50 -0700680 const unsigned char* key,
681 int keybits,
682 const unsigned char* messages,
Brian Murray57863ad2016-05-19 16:38:36 -0700683 const unsigned int message_lengths[4],
Brian Murray00dc5f02016-05-19 14:23:50 -0700684 const unsigned char* subkeys,
685 const unsigned char* expected_result,
686 mbedtls_cipher_id_t cipher_id,
Brian Murrayb439d452016-05-19 16:02:42 -0700687 int block_size )
Brian Murray00dc5f02016-05-19 14:23:50 -0700688{
689 const int num_tests = 4;
690 mbedtls_cmac_context ctx;
691 int i, ret;
692 unsigned char* tag;
693
694 tag = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Brian Murray57863ad2016-05-19 16:38:36 -0700695 if( tag == NULL ){
696 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
697 goto exit;
698 }
699
Brian Murray00dc5f02016-05-19 14:23:50 -0700700 mbedtls_cmac_init( &ctx );
701
702 if( ( ret = mbedtls_cmac_setkey( &ctx, cipher_id, key, keybits ) ) != 0 )
703 {
704 if( verbose != 0 )
705 mbedtls_printf( " CMAC: setup failed\n" );
706 goto exit;
707 }
708
709 if( ( ret = memcmp( ctx.K1, subkeys, block_size ) != 0 ) ||
710 ( ret = memcmp( ctx.K2, &subkeys[block_size], block_size ) != 0 ) )
711 {
712 if( verbose != 0 )
713 mbedtls_printf( " CMAC: subkey generation failed\n" );
714 goto exit;
715 }
716
717 for( i = 0; i < num_tests; i++ )
718 {
719 if( verbose != 0 )
720 mbedtls_printf( " %s CMAC #%u: ", testname, i +1 );
721
722 if( ( ret = mbedtls_cmac_generate( &ctx, messages, message_lengths[i], tag, block_size ) ) != 0 )
723 {
724 if( verbose != 0 )
725 mbedtls_printf( "failed\n" );
726 goto exit;
727 }
728 if( ( ret = memcmp( tag, &expected_result[i * block_size], block_size ) ) != 0 )
729 {
730 if( verbose != 0 )
731 mbedtls_printf( "failed\n" );
732 goto exit;
733 }
734
735 if( ( ret = mbedtls_cmac_verify( &ctx, messages, message_lengths[i], &expected_result[i * block_size], block_size ) != 0 ) )
736 {
737 if( verbose != 0 )
738 mbedtls_printf( "failed\n" );
739 goto exit;
740 }
741 mbedtls_printf( "passed\n" );
742 }
743 exit:
744 free( tag );
745 mbedtls_cmac_free( &ctx );
746 return( ret );
747}
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000748
Brian Murray0f6af732016-05-19 15:59:23 -0700749#ifdef MBEDTLS_AES_C
Brian Murray57863ad2016-05-19 16:38:36 -0700750int test_aes128_cmac_prf( int verbose ) {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000751 int i;
752 int ret;
Brian Murray0f6af732016-05-19 15:59:23 -0700753 unsigned char tag[16];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700754 for( i = 0; i < NB_PRF_TESTS; i++ )
755 {
Brian Murray0f6af732016-05-19 15:59:23 -0700756 mbedtls_printf( " AES CMAC 128 PRF #%u: ", i );
757 ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, tag );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700758 if( ret != 0 ||
759 memcmp( tag, PRFT[i], 16 ) != 0 )
760 {
761 if( verbose != 0 )
762 mbedtls_printf( "failed\n" );
763
Brian Murray0f6af732016-05-19 15:59:23 -0700764 return( ret );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700765 } else if( verbose != 0 )
766 {
767 mbedtls_printf( "passed\n" );
768 }
769 }
Brian Murray0f6af732016-05-19 15:59:23 -0700770 return( ret );
771}
772#endif /* MBEDTLS_AES_C */
773
774int mbedtls_cmac_self_test( int verbose )
775{
776 int ret;
777
778#ifdef MBEDTLS_AES_C
Brian Murray9044b022016-05-19 16:36:56 -0700779 if( ( ret = test_cmac_with_cipher( verbose,
780 "AES 128",
781 aes_128_key,
782 128,
783 test_message,
784 aes_message_lengths,
Brian Murray57863ad2016-05-19 16:38:36 -0700785 (const unsigned char*) aes_128_subkeys,
786 (const unsigned char*) aes_128_expected_result,
Brian Murray9044b022016-05-19 16:36:56 -0700787 MBEDTLS_CIPHER_ID_AES,
788 AES_BLOCK_SIZE ) !=0 ) )
789 {
790 return( ret );
791 }
Brian Murray0f6af732016-05-19 15:59:23 -0700792
Brian Murray9044b022016-05-19 16:36:56 -0700793 if( ( ret = test_cmac_with_cipher( verbose,
Brian Murray57863ad2016-05-19 16:38:36 -0700794 "AES 192",
795 aes_192_key,
796 192,
797 test_message,
798 aes_message_lengths,
799 (const unsigned char*) aes_192_subkeys,
800 (const unsigned char*) aes_192_expected_result,
801 MBEDTLS_CIPHER_ID_AES,
802 AES_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700803 {
804 return( ret );
805 }
Brian Murray0f6af732016-05-19 15:59:23 -0700806
Brian Murray9044b022016-05-19 16:36:56 -0700807 if( ( ret = test_cmac_with_cipher ( verbose,
Brian Murray57863ad2016-05-19 16:38:36 -0700808 "AES 256",
809 aes_256_key,
810 256,
811 test_message,
812 aes_message_lengths,
813 (const unsigned char*) aes_256_subkeys,
814 (const unsigned char*) aes_256_expected_result,
815 MBEDTLS_CIPHER_ID_AES,
816 AES_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700817 {
818 return( ret );
819 }
Brian Murray0f6af732016-05-19 15:59:23 -0700820#endif /* MBEDTLS_AES_C */
821
822#ifdef MBEDTLS_DES_C
Brian Murray9044b022016-05-19 16:36:56 -0700823 if( ( ret = test_cmac_with_cipher( verbose,
Brian Murray57863ad2016-05-19 16:38:36 -0700824 "3DES 2 key",
825 des3_2key_key,
826 192,
827 test_message,
828 des3_message_lengths,
829 (const unsigned char*) des3_2key_subkeys,
830 (const unsigned char*) des3_2key_expected_result,
831 MBEDTLS_CIPHER_ID_3DES,
832 DES3_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700833 {
834 return( ret );
835 }
Brian Murray0f6af732016-05-19 15:59:23 -0700836
Brian Murray9044b022016-05-19 16:36:56 -0700837 if( ( ret = test_cmac_with_cipher( verbose,
Brian Murray57863ad2016-05-19 16:38:36 -0700838 "3DES 3 key",
839 des3_3key_key,
840 192,
841 test_message,
842 des3_message_lengths,
843 (const unsigned char*) des3_3key_subkeys,
844 (const unsigned char*) des3_3key_expected_result,
845 MBEDTLS_CIPHER_ID_3DES,
846 DES3_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700847 {
848 return( ret );
849 }
Brian Murray0f6af732016-05-19 15:59:23 -0700850#endif /* MBEDTLS_DES_C */
851
852#ifdef MBEDTLS_AES_C
Brian Murray9044b022016-05-19 16:36:56 -0700853 if( ( ret = test_aes128_cmac_prf( verbose ) != 0 ) )
854 return( ret );
855
Brian Murray0f6af732016-05-19 15:59:23 -0700856#endif /* MBEDTLS_AES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700857
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000858 if( verbose != 0 )
859 mbedtls_printf( "\n" );
Brian Murray0f6af732016-05-19 15:59:23 -0700860
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000861 return( 0 );
862}
863
Brian Murray0f6af732016-05-19 15:59:23 -0700864#endif /* MBEDTLS_SELF_TEST */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000865
866#endif /* MBEDTLS_CMAC_C */