blob: d8c809b416b931851bd52ca939705da634878ea2 [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 Murray9ce2e092016-05-24 22:46:43 -0700358 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700359 ret = MBEDTLS_ERR_CMAC_VERIFY_FAILED;
360 goto exit;
Brian Murray9ce2e092016-05-24 22:46:43 -0700361 }
362 else
363 {
364 ret = 0;
365 goto exit;
366 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000367
Brian Murrayb0c3c432016-05-18 14:29:51 -0700368 exit:
Brian Murray4b64ab62016-05-20 06:33:01 -0700369 mbedtls_free( check_tag );
Brian Murrayb439d452016-05-19 16:02:42 -0700370 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000371}
372
Brian Murrayb439d452016-05-19 16:02:42 -0700373#ifdef MBEDTLS_AES_C
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000374/*
375 * PRF based on CMAC with AES-128
Brian Murrayb0c3c432016-05-18 14:29:51 -0700376 * See RFC 4615
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000377 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700378int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000379 const unsigned char *input, size_t in_len,
Brian Murrayb439d452016-05-19 16:02:42 -0700380 unsigned char tag[16] )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000381{
382 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700383 mbedtls_cmac_context ctx;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000384 unsigned char zero_key[16];
385 unsigned char int_key[16];
386
Brian Murrayb439d452016-05-19 16:02:42 -0700387 mbedtls_cmac_init(&ctx );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700388
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000389 if( key_length == 16 )
390 {
391 /* Use key as is */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000392 memcpy( int_key, key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000393 }
394 else
395 {
396 mbedtls_cmac_context zero_ctx;
397
Brian Murrayb439d452016-05-19 16:02:42 -0700398 /* Key is AES_CMAC( 0, key ) */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000399 mbedtls_cmac_init( &zero_ctx );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000400 memset( zero_key, 0, 16 );
401 ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES,
Brian Murray6a3c0d22016-05-20 18:25:43 -0700402 zero_key, 8 * sizeof( zero_key ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000403 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700404 goto exit;
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000405
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000406 ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000407 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700408 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000409 }
410
Brian Murrayb0c3c432016-05-18 14:29:51 -0700411 ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
Brian Murray6a3c0d22016-05-20 18:25:43 -0700412 int_key, 8 * sizeof( int_key ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000413 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700414 goto exit;
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000415
Brian Murrayb0c3c432016-05-18 14:29:51 -0700416 ret = mbedtls_cmac_generate( &ctx, input, in_len, tag, 16 );
417
418 exit:
Brian Murray6a3c0d22016-05-20 18:25:43 -0700419 mbedtls_zeroize( int_key, sizeof( int_key ) );
420 mbedtls_cmac_free( &ctx );
421 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000422}
Brian Murrayb439d452016-05-19 16:02:42 -0700423#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000424
Brian Murray0f6af732016-05-19 15:59:23 -0700425#ifdef MBEDTLS_SELF_TEST
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000426/*
Brian Murray0f6af732016-05-19 15:59:23 -0700427 * CMAC test data from SP800-38B Appendix D.1 (corrected)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000428 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
Brian Murray0f6af732016-05-19 15:59:23 -0700429 *
430 * AES-CMAC-PRF-128 test data from RFC 4615
431 * https://tools.ietf.org/html/rfc4615#page-4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000432 */
433
Brian Murray0f6af732016-05-19 15:59:23 -0700434#define NB_CMAC_TESTS_PER_KEY 4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000435#define NB_PRF_TESTS 3
Brian Murray0f6af732016-05-19 15:59:23 -0700436#define AES_BLOCK_SIZE 16
437#define DES3_BLOCK_SIZE 8
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000438
Brian Murray0f6af732016-05-19 15:59:23 -0700439#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
440/* All CMAC test inputs are truncated from the same 64 byte buffer. */
441static const unsigned char test_message[] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000442 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
443 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
444 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
445 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
446 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
447 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
448 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
449 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
450};
Brian Murray0cf14c12016-05-23 12:49:50 -0700451
452
Brian Murray0f6af732016-05-19 15:59:23 -0700453#endif /* defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000454
Brian Murray0f6af732016-05-19 15:59:23 -0700455#ifdef MBEDTLS_AES_C
456/* Truncation point of message for AES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700457static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700458 0,
459 16,
460 40,
461 64
462};
463
464/* AES 128 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700465static const unsigned char aes_128_key[16] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700466 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
467 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
468};
469static const unsigned char aes_128_subkeys[2][AES_BLOCK_SIZE] = {
470 {
471 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
472 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
473 },
474 {
475 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
476 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
477 }
478};
479static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000480 {
481 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
482 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
483 },
484 {
485 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
486 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
487 },
488 {
489 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
490 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
491 },
492 {
493 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
494 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
495 }
496};
497
Brian Murray0f6af732016-05-19 15:59:23 -0700498/* AES 192 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700499static const unsigned char aes_192_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700500 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
501 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
502 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000503};
Brian Murray0f6af732016-05-19 15:59:23 -0700504static const unsigned char aes_192_subkeys[2][AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700505 {
Brian Murray0f6af732016-05-19 15:59:23 -0700506 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
507 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
Brian Murrayb0c3c432016-05-18 14:29:51 -0700508 },
509 {
Brian Murray0f6af732016-05-19 15:59:23 -0700510 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
511 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
Brian Murrayb0c3c432016-05-18 14:29:51 -0700512 }
513};
Brian Murray0f6af732016-05-19 15:59:23 -0700514static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700515 {
516 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
517 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
518 },
519 {
520 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
521 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
522 },
523 {
524 0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad,
525 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e
526 },
527 {
528 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
529 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
530 }
531};
532
Brian Murray0f6af732016-05-19 15:59:23 -0700533/* AES 256 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700534static const unsigned char aes_256_key[32] = {
Brian Murray87e40402016-05-19 19:05:57 -0700535 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
536 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
537 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
538 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
Brian Murray0f6af732016-05-19 15:59:23 -0700539};
540static const unsigned char aes_256_subkeys[2][AES_BLOCK_SIZE] = {
541 {
542 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
543 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
544 },
545 {
546 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
547 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
548 }
549};
550static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
551 {
552 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
553 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
554 },
555 {
556 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
557 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
558 },
559 {
560 0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2,
561 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6
562 },
563 {
564 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
565 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
566 }
567};
568#endif /* MBEDTLS_AES_C */
569
570#ifdef MBEDTLS_DES_C
571/* Truncation point of message for 3DES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700572static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700573 0,
574 8,
575 20,
576 32
577};
578
579/* 3DES 2 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700580static const unsigned char des3_2key_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700581 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5,
582 0x8a, 0x3d, 0x10, 0xba, 0x80, 0x57, 0x0d, 0x38,
583 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5
Brian Murray0f6af732016-05-19 15:59:23 -0700584};
585static const unsigned char des3_2key_subkeys[2][8] = {
586 {
587 0x8e, 0xcf, 0x37, 0x3e, 0xd7, 0x1a, 0xfa, 0xef
588 },
589 {
590 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5
591 }
592};
Brian Murray57863ad2016-05-19 16:38:36 -0700593static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700594 {
595 0xbd, 0x2e, 0xbf, 0x9a, 0x3b, 0xa0, 0x03, 0x61
596 },
597 {
598 0x4f, 0xf2, 0xab, 0x81, 0x3c, 0x53, 0xce, 0x83
599 },
600 {
601 0x62, 0xdd, 0x1b, 0x47, 0x19, 0x02, 0xbd, 0x4e
602 },
603 {
604 0x31, 0xb1, 0xe4, 0x31, 0xda, 0xbc, 0x4e, 0xb8
605 }
606};
607
Brian Murray0f6af732016-05-19 15:59:23 -0700608/* 3DES 3 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700609static const unsigned char des3_3key_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700610 0x8a, 0xa8, 0x3b, 0xf8, 0xcb, 0xda, 0x10, 0x62,
611 0x0b, 0xc1, 0xbf, 0x19, 0xfb, 0xb6, 0xcd, 0x58,
612 0xbc, 0x31, 0x3d, 0x4a, 0x37, 0x1c, 0xa8, 0xb5
Brian Murray0f6af732016-05-19 15:59:23 -0700613};
614static const unsigned char des3_3key_subkeys[2][8] = {
615 {
616 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f
617 },
618 {
619 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5
620 }
621};
Brian Murray57863ad2016-05-19 16:38:36 -0700622static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700623 {
624 0xb7, 0xa6, 0x88, 0xe1, 0x22, 0xff, 0xaf, 0x95
625 },
626 {
627 0x8e, 0x8f, 0x29, 0x31, 0x36, 0x28, 0x37, 0x97
628 },
629 {
630 0x74, 0x3d, 0xdb, 0xe0, 0xce, 0x2d, 0xc2, 0xed
631 },
632 {
633 0x33, 0xe6, 0xb1, 0x09, 0x24, 0x00, 0xea, 0xe5
634 }
635};
636
Brian Murray0f6af732016-05-19 15:59:23 -0700637#endif /* MBEDTLS_DES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700638
Brian Murray0f6af732016-05-19 15:59:23 -0700639#ifdef MBEDTLS_AES_C
640/* AES AES-CMAC-PRF-128 Test Data */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000641static const unsigned char PRFK[] = {
642 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
643 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
644 0xed, 0xcb
645};
646
647/* Sizes in bytes */
648static const size_t PRFKlen[NB_PRF_TESTS] = {
649 18,
650 16,
651 10
652};
653
654/* PRF M */
655static const unsigned char PRFM[] = {
656 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
657 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000658 0x10, 0x11, 0x12, 0x13
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000659};
660
661static const unsigned char PRFT[NB_PRF_TESTS][16] = {
662 {
663 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
664 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
665 },
666 {
667 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
668 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
669 },
670 {
671 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
672 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
673 }
674};
Brian Murray0f6af732016-05-19 15:59:23 -0700675#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000676
Brian Murrayae1cb122016-05-23 15:01:59 -0700677static inline int cmac_test_wth_cipher( int verbose,
678 const char* testname,
679 const unsigned char* key,
680 int keybits,
681 const unsigned char* messages,
682 const unsigned int message_lengths[4],
683 const unsigned char* subkeys,
684 const unsigned char* expected_result,
685 mbedtls_cipher_id_t cipher_id,
686 int block_size )
Brian Murray00dc5f02016-05-19 14:23:50 -0700687{
Brian Murray87e40402016-05-19 19:05:57 -0700688 const int num_tests = 4;
689 mbedtls_cmac_context ctx;
Brian Murray00dc5f02016-05-19 14:23:50 -0700690 int i, ret;
691 unsigned char* tag;
692
693 tag = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Brian Murray6a3c0d22016-05-20 18:25:43 -0700694 if( tag == NULL )
695 {
Brian Murray57863ad2016-05-19 16:38:36 -0700696 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 }
Brian Murray9ce2e092016-05-24 22:46:43 -0700728
Brian Murray00dc5f02016-05-19 14:23:50 -0700729 if( ( ret = memcmp( tag, &expected_result[i * block_size], block_size ) ) != 0 )
730 {
731 if( verbose != 0 )
732 mbedtls_printf( "failed\n" );
733 goto exit;
734 }
735
736 if( ( ret = mbedtls_cmac_verify( &ctx, messages, message_lengths[i], &expected_result[i * block_size], block_size ) != 0 ) )
737 {
Brian Murray4b64ab62016-05-20 06:33:01 -0700738 if( verbose != 0 )
739 mbedtls_printf( "failed\n" );
740 goto exit;
Brian Murray00dc5f02016-05-19 14:23:50 -0700741 }
Brian Murray9ce2e092016-05-24 22:46:43 -0700742
743 if( verbose != 0 )
744 mbedtls_printf( "passed\n" );
Brian Murray00dc5f02016-05-19 14:23:50 -0700745 }
746 exit:
Brian Murray4b64ab62016-05-20 06:33:01 -0700747 mbedtls_free( tag );
Brian Murray00dc5f02016-05-19 14:23:50 -0700748 mbedtls_cmac_free( &ctx );
749 return( ret );
750}
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000751
Brian Murray0f6af732016-05-19 15:59:23 -0700752#ifdef MBEDTLS_AES_C
Brian Murrayae1cb122016-05-23 15:01:59 -0700753static inline int test_aes128_cmac_prf( int verbose )
Brian Murray6a3c0d22016-05-20 18:25:43 -0700754{
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000755 int i;
756 int ret;
Brian Murray0f6af732016-05-19 15:59:23 -0700757 unsigned char tag[16];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700758 for( i = 0; i < NB_PRF_TESTS; i++ )
759 {
Brian Murray0f6af732016-05-19 15:59:23 -0700760 mbedtls_printf( " AES CMAC 128 PRF #%u: ", i );
761 ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, tag );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700762 if( ret != 0 ||
763 memcmp( tag, PRFT[i], 16 ) != 0 )
764 {
765 if( verbose != 0 )
766 mbedtls_printf( "failed\n" );
767
Brian Murray0f6af732016-05-19 15:59:23 -0700768 return( ret );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700769 } else if( verbose != 0 )
770 {
771 mbedtls_printf( "passed\n" );
772 }
773 }
Brian Murray0f6af732016-05-19 15:59:23 -0700774 return( ret );
775}
776#endif /* MBEDTLS_AES_C */
777
778int mbedtls_cmac_self_test( int verbose )
779{
780 int ret;
781
782#ifdef MBEDTLS_AES_C
Brian Murrayae1cb122016-05-23 15:01:59 -0700783 if( ( ret = cmac_test_wth_cipher( verbose,
784 "AES 128",
785 aes_128_key,
786 128,
787 test_message,
788 aes_message_lengths,
789 (const unsigned char*) aes_128_subkeys,
790 (const unsigned char*) aes_128_expected_result,
791 MBEDTLS_CIPHER_ID_AES,
792 AES_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700793 {
794 return( ret );
795 }
Brian Murray0f6af732016-05-19 15:59:23 -0700796
Brian Murrayae1cb122016-05-23 15:01:59 -0700797 if( ( ret = cmac_test_wth_cipher( verbose,
798 "AES 192",
799 aes_192_key,
800 192,
801 test_message,
802 aes_message_lengths,
803 (const unsigned char*) aes_192_subkeys,
804 (const unsigned char*) aes_192_expected_result,
805 MBEDTLS_CIPHER_ID_AES,
806 AES_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700807 {
808 return( ret );
809 }
Brian Murray0f6af732016-05-19 15:59:23 -0700810
Brian Murrayae1cb122016-05-23 15:01:59 -0700811 if( ( ret = cmac_test_wth_cipher ( verbose,
812 "AES 256",
813 aes_256_key,
814 256,
815 test_message,
816 aes_message_lengths,
817 (const unsigned char*) aes_256_subkeys,
818 (const unsigned char*) aes_256_expected_result,
819 MBEDTLS_CIPHER_ID_AES,
820 AES_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700821 {
822 return( ret );
823 }
Brian Murray0f6af732016-05-19 15:59:23 -0700824#endif /* MBEDTLS_AES_C */
825
826#ifdef MBEDTLS_DES_C
Brian Murrayae1cb122016-05-23 15:01:59 -0700827 if( ( ret = cmac_test_wth_cipher( verbose,
828 "3DES 2 key",
829 des3_2key_key,
830 192,
831 test_message,
832 des3_message_lengths,
833 (const unsigned char*) des3_2key_subkeys,
834 (const unsigned char*) des3_2key_expected_result,
835 MBEDTLS_CIPHER_ID_3DES,
836 DES3_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700837 {
838 return( ret );
839 }
Brian Murray0f6af732016-05-19 15:59:23 -0700840
Brian Murrayae1cb122016-05-23 15:01:59 -0700841 if( ( ret = cmac_test_wth_cipher( verbose,
842 "3DES 3 key",
843 des3_3key_key,
844 192,
845 test_message,
846 des3_message_lengths,
847 (const unsigned char*) des3_3key_subkeys,
848 (const unsigned char*) des3_3key_expected_result,
849 MBEDTLS_CIPHER_ID_3DES,
850 DES3_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700851 {
852 return( ret );
853 }
Brian Murray0f6af732016-05-19 15:59:23 -0700854#endif /* MBEDTLS_DES_C */
855
856#ifdef MBEDTLS_AES_C
Brian Murray9044b022016-05-19 16:36:56 -0700857 if( ( ret = test_aes128_cmac_prf( verbose ) != 0 ) )
858 return( ret );
Brian Murray0f6af732016-05-19 15:59:23 -0700859#endif /* MBEDTLS_AES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700860
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000861 if( verbose != 0 )
862 mbedtls_printf( "\n" );
Brian Murray0f6af732016-05-19 15:59:23 -0700863
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000864 return( 0 );
865}
866
Brian Murray0f6af732016-05-19 15:59:23 -0700867#endif /* MBEDTLS_SELF_TEST */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000868
869#endif /* MBEDTLS_CMAC_C */