blob: d8c809b416b931851bd52ca939705da634878ea2 [file] [log] [blame]
Robert Cragie9bf1e5d2015-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 Cragie9bf1e5d2015-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 Murray7c6476c2016-05-18 14:29:51 -070063 * Multiplication by u in the Galois field of GF(2^n)
Manuel Pégourié-Gonnard756bcf72016-01-13 11:28:16 +000064 *
Brian Murray6eae89b2016-05-19 19:05:57 -070065 * As explained in the paper, this can be computed:
Manuel Pégourié-Gonnard756bcf72016-01-13 11:28:16 +000066 * If MSB(p) = 0, then p = (p << 1)
Brian Murray7c6476c2016-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é-Gonnard756bcf72016-01-13 11:28:16 +000069 *
70 * Input and output MUST not point to the same buffer
Brian Murray7c6476c2016-05-18 14:29:51 -070071 * Block size must be 8 byes or 16 bytes.
Robert Cragie9bf1e5d2015-12-15 07:38:11 +000072 */
Brian Murray7c6476c2016-05-18 14:29:51 -070073static int cmac_multiply_by_u( unsigned char *output,
74 const unsigned char *input,
Brian Murrayafdb60f2016-05-19 16:02:42 -070075 size_t blocksize )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +000076{
Brian Murray7c6476c2016-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 Murray4e067032016-05-20 18:25:43 -070085 if( blocksize == 16 )
86 {
Brian Murray7c6476c2016-05-18 14:29:51 -070087 R_n = R_128;
Brian Murray4e067032016-05-20 18:25:43 -070088 } else if( blocksize == 8 )
89 {
Brian Murray7c6476c2016-05-18 14:29:51 -070090 R_n = R_64;
Brian Murray4e067032016-05-20 18:25:43 -070091 } else
92 {
Brian Murrayafdb60f2016-05-19 16:02:42 -070093 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
Brian Murray7c6476c2016-05-18 14:29:51 -070094 }
95
Brian Murray7c6476c2016-05-18 14:29:51 -070096 for( i = starting_index; i >= 0; i-- )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +000097 {
Manuel Pégourié-Gonnard756bcf72016-01-13 11:28:16 +000098 output[i] = input[i] << 1 | overflow;
99 overflow = input[i] >> 7;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000100 }
Manuel Pégourié-Gonnarda4dfa052016-01-13 11:00:47 +0000101
Manuel Pégourié-Gonnard89b8d832016-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 Murray7c6476c2016-05-18 14:29:51 -0700115 output[starting_index] ^= R_n & mask;
Brian Murrayafdb60f2016-05-19 16:02:42 -0700116 return( 0 );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000117}
118
119/*
120 * Generate subkeys
121 */
Manuel Pégourié-Gonnard2b0e21f2016-01-13 15:09:09 +0000122static int cmac_generate_subkeys( mbedtls_cmac_context *ctx )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000123{
Brian Murray86ff9862016-05-19 16:38:36 -0700124 int ret;
Brian Murray7c6476c2016-05-18 14:29:51 -0700125 unsigned char *L;
126 size_t olen, block_size;
127
Brian Murray7c6476c2016-05-18 14:29:51 -0700128 block_size = ctx->cipher_ctx.cipher_info->block_size;
129
Brian Murrayafdb60f2016-05-19 16:02:42 -0700130 L = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Brian Murraycdd1f6d2016-05-20 06:33:01 -0700131 if( L == NULL )
Brian Murray86ff9862016-05-19 16:38:36 -0700132 {
133 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
134 goto exit;
135 }
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000136 /* Calculate Ek(0) */
Manuel Pégourié-Gonnarda4dfa052016-01-13 11:00:47 +0000137 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx,
Brian Murray7c6476c2016-05-18 14:29:51 -0700138 L, block_size, L, &olen ) ) != 0 )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000139 {
Brian Murray7c6476c2016-05-18 14:29:51 -0700140 goto exit;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000141 }
142
Manuel Pégourié-Gonnarda4dfa052016-01-13 11:00:47 +0000143 /*
Manuel Pégourié-Gonnard756bcf72016-01-13 11:28:16 +0000144 * Generate K1 and K2
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000145 */
Brian Murrayafdb60f2016-05-19 16:02:42 -0700146 if( ( ret = cmac_multiply_by_u( ctx->K1, L , block_size ) ) != 0 )
Brian Murray7c6476c2016-05-18 14:29:51 -0700147 goto exit;
Brian Murray4e067032016-05-20 18:25:43 -0700148 if( ( ret = cmac_multiply_by_u( ctx->K2, ctx->K1 , block_size ) ) != 0 )
Brian Murray7c6476c2016-05-18 14:29:51 -0700149 goto exit;
Manuel Pégourié-Gonnarda4dfa052016-01-13 11:00:47 +0000150
Brian Murray7c6476c2016-05-18 14:29:51 -0700151 exit:
Brian Murray86ff9862016-05-19 16:38:36 -0700152 if( L != NULL )
153 mbedtls_zeroize( L, sizeof( L ) );
Brian Murraycdd1f6d2016-05-20 06:33:01 -0700154 mbedtls_free( L );
Brian Murrayafdb60f2016-05-19 16:02:42 -0700155 return( ret );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000156}
157
Manuel Pégourié-Gonnard2b0e21f2016-01-13 15:09:09 +0000158/*
159 * Set key and prepare context for use
160 */
Robert Cragie9bf1e5d2015-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 Murray86ff9862016-05-19 16:38:36 -0700166 int ret;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000167 const mbedtls_cipher_info_t *cipher_info;
168
Manuel Pégourié-Gonnarda4dfa052016-01-13 11:00:47 +0000169 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
170 MBEDTLS_MODE_ECB );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000171 if( cipher_info == NULL )
172 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
173
Robert Cragie9bf1e5d2015-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é-Gonnarda4dfa052016-01-13 11:00:47 +0000180 MBEDTLS_ENCRYPT ) ) != 0 )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000181 {
182 return( ret );
183 }
184
Brian Murraydb5c70e2016-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é-Gonnard2b0e21f2016-01-13 15:09:09 +0000195 return( cmac_generate_subkeys( ctx ) );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000196}
197
198/*
199 * Free context
200 */
201void mbedtls_cmac_free( mbedtls_cmac_context *ctx )
202{
Brian Murray7c6476c2016-05-18 14:29:51 -0700203 int block_size;
204 block_size = ctx->cipher_ctx.cipher_info->block_size;
205
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000206 mbedtls_cipher_free( &ctx->cipher_ctx );
Brian Murray7c6476c2016-05-18 14:29:51 -0700207
Brian Murray4e067032016-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 Murray7c6476c2016-05-18 14:29:51 -0700212 mbedtls_free( ctx->K1 );
213 mbedtls_free( ctx->K2 );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000214}
215
Manuel Pégourié-Gonnardda8724f2016-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é-Gonnard2b0e21f2016-01-13 15:09:09 +0000222static void cmac_pad( unsigned char padded_block[16],
Brian Murray7c6476c2016-05-18 14:29:51 -0700223 size_t padded_block_len,
Manuel Pégourié-Gonnard2b0e21f2016-01-13 15:09:09 +0000224 const unsigned char *last_block,
Brian Murray7c6476c2016-05-18 14:29:51 -0700225 size_t last_block_len )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000226{
227 size_t j;
228
Brian Murray7c6476c2016-05-18 14:29:51 -0700229 for( j = 0; j < padded_block_len; j++ )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000230 {
Brian Murray7c6476c2016-05-18 14:29:51 -0700231 if( j < last_block_len )
Manuel Pégourié-Gonnardda8724f2016-01-13 13:14:04 +0000232 padded_block[j] = last_block[j];
Brian Murray7c6476c2016-05-18 14:29:51 -0700233 else if( j == last_block_len )
Manuel Pégourié-Gonnardda8724f2016-01-13 13:14:04 +0000234 padded_block[j] = 0x80;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000235 else
Manuel Pégourié-Gonnardda8724f2016-01-13 13:14:04 +0000236 padded_block[j] = 0x00;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000237 }
238}
239
240/*
Brian Murray7c6476c2016-05-18 14:29:51 -0700241 * XOR Block
Manuel Pégourié-Gonnard5f8639f2016-01-13 15:03:05 +0000242 * Here, macro results in smaller compiled code than static inline function
243 */
Brian Murray7c6476c2016-05-18 14:29:51 -0700244#define XOR_BLOCK( o, i1, i2 ) \
245 for( i = 0; i < block_size; i++ ) \
Manuel Pégourié-Gonnard5f8639f2016-01-13 15:03:05 +0000246 ( o )[i] = ( i1 )[i] ^ ( i2 )[i];
247
248/*
Brian Murray6eae89b2016-05-19 19:05:57 -0700249 * Update the CMAC state using an input block
Manuel Pégourié-Gonnard5f8639f2016-01-13 15:03:05 +0000250 */
251#define UPDATE_CMAC( x ) \
252do { \
Brian Murray7c6476c2016-05-18 14:29:51 -0700253 XOR_BLOCK( state, ( x ), state ); \
Manuel Pégourié-Gonnard5f8639f2016-01-13 15:03:05 +0000254 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \
Brian Murray7c6476c2016-05-18 14:29:51 -0700255 state, block_size, \
256 state, &olen ) ) != 0 ) \
Brian Murray86ff9862016-05-19 16:38:36 -0700257 { \
258 goto exit; \
259 } \
Manuel Pégourié-Gonnard5f8639f2016-01-13 15:03:05 +0000260} while( 0 )
261
262/*
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000263 * Generate tag on complete message
264 */
Manuel Pégourié-Gonnarda878d3b2016-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 Cragie9bf1e5d2015-12-15 07:38:11 +0000268{
Brian Murray7c6476c2016-05-18 14:29:51 -0700269 unsigned char *state;
270 unsigned char *M_last;
Brian Murray86ff9862016-05-19 16:38:36 -0700271 int n, j, ret, needs_padding;
272 size_t olen, block_size, i;
Brian Murray7c6476c2016-05-18 14:29:51 -0700273
Brian Murray7c6476c2016-05-18 14:29:51 -0700274 ret = 0;
275 block_size = ctx->cipher_ctx.cipher_info->block_size;
276
Brian Murrayafdb60f2016-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 Cragie9bf1e5d2015-12-15 07:38:11 +0000279
Brian Murray86ff9862016-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 Murray6eae89b2016-05-19 19:05:57 -0700286 if( tag_len < 2 || tag_len > block_size || tag_len % 2 != 0 )
Brian Murray86ff9862016-05-19 16:38:36 -0700287 {
288 ret = MBEDTLS_ERR_CMAC_BAD_INPUT;
289 goto exit;
290 }
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000291
Manuel Pégourié-Gonnard59ae4ba2016-01-13 14:27:55 +0000292 if( in_len == 0 )
293 needs_padding = 1;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000294 else
Brian Murray7c6476c2016-05-18 14:29:51 -0700295 needs_padding = in_len % block_size != 0;
Manuel Pégourié-Gonnard59ae4ba2016-01-13 14:27:55 +0000296
Brian Murray7c6476c2016-05-18 14:29:51 -0700297 n = in_len / block_size + needs_padding;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000298
299 /* Calculate last block */
Manuel Pégourié-Gonnard59ae4ba2016-01-13 14:27:55 +0000300 if( needs_padding )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000301 {
Brian Murray7c6476c2016-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 Cragie9bf1e5d2015-12-15 07:38:11 +0000304 }
305 else
306 {
Manuel Pégourié-Gonnard59ae4ba2016-01-13 14:27:55 +0000307 /* Last block is complete block */
Brian Murray7c6476c2016-05-18 14:29:51 -0700308 XOR_BLOCK( M_last, input + block_size * ( n - 1 ), ctx->K1 );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000309 }
310
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000311 for( j = 0; j < n - 1; j++ )
Brian Murray7c6476c2016-05-18 14:29:51 -0700312 UPDATE_CMAC( input + block_size * j );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000313
Manuel Pégourié-Gonnarda4dfa052016-01-13 11:00:47 +0000314 UPDATE_CMAC( M_last );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000315
Brian Murray3c0412a2016-05-19 14:23:50 -0700316 memcpy( tag, state, tag_len );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000317
Brian Murray7c6476c2016-05-18 14:29:51 -0700318 exit:
Brian Murraycdd1f6d2016-05-20 06:33:01 -0700319 mbedtls_free( state );
320 mbedtls_free( M_last );
Brian Murray7c6476c2016-05-18 14:29:51 -0700321 return( ret );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000322}
323
Brian Murray7c6476c2016-05-18 14:29:51 -0700324#undef XOR_BLOCK
Manuel Pégourié-Gonnard5f8639f2016-01-13 15:03:05 +0000325#undef UPDATE_CMAC
326
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000327/*
Manuel Pégourié-Gonnard2b0e21f2016-01-13 15:09:09 +0000328 * Verify tag on complete message
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000329 */
Manuel Pégourié-Gonnard9c83eeb2016-01-13 10:48:02 +0000330int mbedtls_cmac_verify( mbedtls_cmac_context *ctx,
331 const unsigned char *input, size_t in_len,
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000332 const unsigned char *tag, size_t tag_len )
333{
334 int ret;
Brian Murray7c6476c2016-05-18 14:29:51 -0700335 unsigned char *check_tag;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000336 unsigned char i;
337 int diff;
Manuel Pégourié-Gonnarda4dfa052016-01-13 11:00:47 +0000338
Brian Murrayafdb60f2016-05-19 16:02:42 -0700339 check_tag = mbedtls_calloc( ctx->cipher_ctx.cipher_info->block_size,
340 sizeof( unsigned char ) );
Brian Murraycdd1f6d2016-05-20 06:33:01 -0700341 if( check_tag == NULL )
Brian Murray86ff9862016-05-19 16:38:36 -0700342 {
343 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
344 goto exit;
345 }
Brian Murray7c6476c2016-05-18 14:29:51 -0700346
Manuel Pégourié-Gonnarda878d3b2016-01-13 15:05:57 +0000347 if( ( ret = mbedtls_cmac_generate( ctx, input, in_len,
348 check_tag, tag_len ) ) != 0 )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000349 {
Brian Murray7c6476c2016-05-18 14:29:51 -0700350 goto exit;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000351 }
352
353 /* Check tag in "constant-time" */
354 for( diff = 0, i = 0; i < tag_len; i++ )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000355 diff |= tag[i] ^ check_tag[i];
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000356
357 if( diff != 0 )
Brian Murray0b21cdf2016-05-24 22:46:43 -0700358 {
Brian Murray7c6476c2016-05-18 14:29:51 -0700359 ret = MBEDTLS_ERR_CMAC_VERIFY_FAILED;
360 goto exit;
Brian Murray0b21cdf2016-05-24 22:46:43 -0700361 }
362 else
363 {
364 ret = 0;
365 goto exit;
366 }
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000367
Brian Murray7c6476c2016-05-18 14:29:51 -0700368 exit:
Brian Murraycdd1f6d2016-05-20 06:33:01 -0700369 mbedtls_free( check_tag );
Brian Murrayafdb60f2016-05-19 16:02:42 -0700370 return( ret );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000371}
372
Brian Murrayafdb60f2016-05-19 16:02:42 -0700373#ifdef MBEDTLS_AES_C
Manuel Pégourié-Gonnard2b0e21f2016-01-13 15:09:09 +0000374/*
375 * PRF based on CMAC with AES-128
Brian Murray7c6476c2016-05-18 14:29:51 -0700376 * See RFC 4615
Manuel Pégourié-Gonnard2b0e21f2016-01-13 15:09:09 +0000377 */
Brian Murray7c6476c2016-05-18 14:29:51 -0700378int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard9c83eeb2016-01-13 10:48:02 +0000379 const unsigned char *input, size_t in_len,
Brian Murrayafdb60f2016-05-19 16:02:42 -0700380 unsigned char tag[16] )
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000381{
382 int ret;
Brian Murray7c6476c2016-05-18 14:29:51 -0700383 mbedtls_cmac_context ctx;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000384 unsigned char zero_key[16];
385 unsigned char int_key[16];
386
Brian Murrayafdb60f2016-05-19 16:02:42 -0700387 mbedtls_cmac_init(&ctx );
Brian Murray7c6476c2016-05-18 14:29:51 -0700388
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000389 if( key_length == 16 )
390 {
391 /* Use key as is */
Manuel Pégourié-Gonnarda4dfa052016-01-13 11:00:47 +0000392 memcpy( int_key, key, 16 );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000393 }
394 else
395 {
396 mbedtls_cmac_context zero_ctx;
397
Brian Murrayafdb60f2016-05-19 16:02:42 -0700398 /* Key is AES_CMAC( 0, key ) */
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000399 mbedtls_cmac_init( &zero_ctx );
Manuel Pégourié-Gonnarda4dfa052016-01-13 11:00:47 +0000400 memset( zero_key, 0, 16 );
401 ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES,
Brian Murray4e067032016-05-20 18:25:43 -0700402 zero_key, 8 * sizeof( zero_key ) );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000403 if( ret != 0 )
Brian Murray7c6476c2016-05-18 14:29:51 -0700404 goto exit;
Manuel Pégourié-Gonnard2b0e21f2016-01-13 15:09:09 +0000405
Manuel Pégourié-Gonnard9c83eeb2016-01-13 10:48:02 +0000406 ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000407 if( ret != 0 )
Brian Murray7c6476c2016-05-18 14:29:51 -0700408 goto exit;
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000409 }
410
Brian Murray7c6476c2016-05-18 14:29:51 -0700411 ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
Brian Murray4e067032016-05-20 18:25:43 -0700412 int_key, 8 * sizeof( int_key ) );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000413 if( ret != 0 )
Brian Murray7c6476c2016-05-18 14:29:51 -0700414 goto exit;
Manuel Pégourié-Gonnard28ea7912016-01-13 11:30:00 +0000415
Brian Murray7c6476c2016-05-18 14:29:51 -0700416 ret = mbedtls_cmac_generate( &ctx, input, in_len, tag, 16 );
417
418 exit:
Brian Murray4e067032016-05-20 18:25:43 -0700419 mbedtls_zeroize( int_key, sizeof( int_key ) );
420 mbedtls_cmac_free( &ctx );
421 return( ret );
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000422}
Brian Murrayafdb60f2016-05-19 16:02:42 -0700423#endif /* MBEDTLS_AES_C */
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000424
Brian Murrayd666eb52016-05-19 15:59:23 -0700425#ifdef MBEDTLS_SELF_TEST
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000426/*
Brian Murrayd666eb52016-05-19 15:59:23 -0700427 * CMAC test data from SP800-38B Appendix D.1 (corrected)
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000428 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
Brian Murrayd666eb52016-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 Cragie9bf1e5d2015-12-15 07:38:11 +0000432 */
433
Brian Murrayd666eb52016-05-19 15:59:23 -0700434#define NB_CMAC_TESTS_PER_KEY 4
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000435#define NB_PRF_TESTS 3
Brian Murrayd666eb52016-05-19 15:59:23 -0700436#define AES_BLOCK_SIZE 16
437#define DES3_BLOCK_SIZE 8
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000438
Brian Murrayd666eb52016-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 Cragie9bf1e5d2015-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 Murrayfe9ff012016-05-23 12:49:50 -0700451
452
Brian Murrayd666eb52016-05-19 15:59:23 -0700453#endif /* defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) */
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000454
Brian Murrayd666eb52016-05-19 15:59:23 -0700455#ifdef MBEDTLS_AES_C
456/* Truncation point of message for AES CMAC tests */
Brian Murray86ff9862016-05-19 16:38:36 -0700457static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murrayd666eb52016-05-19 15:59:23 -0700458 0,
459 16,
460 40,
461 64
462};
463
464/* AES 128 CMAC Test Data */
Brian Murray86ff9862016-05-19 16:38:36 -0700465static const unsigned char aes_128_key[16] = {
Brian Murrayd666eb52016-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 Cragie9bf1e5d2015-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 Murrayd666eb52016-05-19 15:59:23 -0700498/* AES 192 CMAC Test Data */
Brian Murray86ff9862016-05-19 16:38:36 -0700499static const unsigned char aes_192_key[24] = {
Brian Murray6eae89b2016-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 Cragie9bf1e5d2015-12-15 07:38:11 +0000503};
Brian Murrayd666eb52016-05-19 15:59:23 -0700504static const unsigned char aes_192_subkeys[2][AES_BLOCK_SIZE] = {
Brian Murray7c6476c2016-05-18 14:29:51 -0700505 {
Brian Murrayd666eb52016-05-19 15:59:23 -0700506 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
507 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
Brian Murray7c6476c2016-05-18 14:29:51 -0700508 },
509 {
Brian Murrayd666eb52016-05-19 15:59:23 -0700510 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
511 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
Brian Murray7c6476c2016-05-18 14:29:51 -0700512 }
513};
Brian Murrayd666eb52016-05-19 15:59:23 -0700514static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
Brian Murray7c6476c2016-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 Murrayd666eb52016-05-19 15:59:23 -0700533/* AES 256 CMAC Test Data */
Brian Murray86ff9862016-05-19 16:38:36 -0700534static const unsigned char aes_256_key[32] = {
Brian Murray6eae89b2016-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 Murrayd666eb52016-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 Murray86ff9862016-05-19 16:38:36 -0700572static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murrayd666eb52016-05-19 15:59:23 -0700573 0,
574 8,
575 20,
576 32
577};
578
579/* 3DES 2 Key CMAC Test Data */
Brian Murray86ff9862016-05-19 16:38:36 -0700580static const unsigned char des3_2key_key[24] = {
Brian Murray6eae89b2016-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 Murrayd666eb52016-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 Murray86ff9862016-05-19 16:38:36 -0700593static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = {
Brian Murray7c6476c2016-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 Murrayd666eb52016-05-19 15:59:23 -0700608/* 3DES 3 Key CMAC Test Data */
Brian Murray86ff9862016-05-19 16:38:36 -0700609static const unsigned char des3_3key_key[24] = {
Brian Murray6eae89b2016-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 Murrayd666eb52016-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 Murray86ff9862016-05-19 16:38:36 -0700622static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = {
Brian Murray7c6476c2016-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 Murrayd666eb52016-05-19 15:59:23 -0700637#endif /* MBEDTLS_DES_C */
Brian Murray7c6476c2016-05-18 14:29:51 -0700638
Brian Murrayd666eb52016-05-19 15:59:23 -0700639#ifdef MBEDTLS_AES_C
640/* AES AES-CMAC-PRF-128 Test Data */
Robert Cragie9bf1e5d2015-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é-Gonnarda4dfa052016-01-13 11:00:47 +0000658 0x10, 0x11, 0x12, 0x13
Robert Cragie9bf1e5d2015-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 Murrayd666eb52016-05-19 15:59:23 -0700675#endif /* MBEDTLS_AES_C */
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000676
Brian Murraybbed6602016-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 Murray3c0412a2016-05-19 14:23:50 -0700687{
Brian Murray6eae89b2016-05-19 19:05:57 -0700688 const int num_tests = 4;
689 mbedtls_cmac_context ctx;
Brian Murray3c0412a2016-05-19 14:23:50 -0700690 int i, ret;
691 unsigned char* tag;
692
693 tag = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Brian Murray4e067032016-05-20 18:25:43 -0700694 if( tag == NULL )
695 {
Brian Murray86ff9862016-05-19 16:38:36 -0700696 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
697 goto exit;
698 }
699
Brian Murray3c0412a2016-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 Murray0b21cdf2016-05-24 22:46:43 -0700728
Brian Murray3c0412a2016-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 Murraycdd1f6d2016-05-20 06:33:01 -0700738 if( verbose != 0 )
739 mbedtls_printf( "failed\n" );
740 goto exit;
Brian Murray3c0412a2016-05-19 14:23:50 -0700741 }
Brian Murray0b21cdf2016-05-24 22:46:43 -0700742
743 if( verbose != 0 )
744 mbedtls_printf( "passed\n" );
Brian Murray3c0412a2016-05-19 14:23:50 -0700745 }
746 exit:
Brian Murraycdd1f6d2016-05-20 06:33:01 -0700747 mbedtls_free( tag );
Brian Murray3c0412a2016-05-19 14:23:50 -0700748 mbedtls_cmac_free( &ctx );
749 return( ret );
750}
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000751
Brian Murrayd666eb52016-05-19 15:59:23 -0700752#ifdef MBEDTLS_AES_C
Brian Murraybbed6602016-05-23 15:01:59 -0700753static inline int test_aes128_cmac_prf( int verbose )
Brian Murray4e067032016-05-20 18:25:43 -0700754{
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000755 int i;
756 int ret;
Brian Murrayd666eb52016-05-19 15:59:23 -0700757 unsigned char tag[16];
Brian Murray7c6476c2016-05-18 14:29:51 -0700758 for( i = 0; i < NB_PRF_TESTS; i++ )
759 {
Brian Murrayd666eb52016-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 Murray7c6476c2016-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 Murrayd666eb52016-05-19 15:59:23 -0700768 return( ret );
Brian Murray7c6476c2016-05-18 14:29:51 -0700769 } else if( verbose != 0 )
770 {
771 mbedtls_printf( "passed\n" );
772 }
773 }
Brian Murrayd666eb52016-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 Murraybbed6602016-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 Murray3d3c9b82016-05-19 16:36:56 -0700793 {
794 return( ret );
795 }
Brian Murrayd666eb52016-05-19 15:59:23 -0700796
Brian Murraybbed6602016-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 Murray3d3c9b82016-05-19 16:36:56 -0700807 {
808 return( ret );
809 }
Brian Murrayd666eb52016-05-19 15:59:23 -0700810
Brian Murraybbed6602016-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 Murray3d3c9b82016-05-19 16:36:56 -0700821 {
822 return( ret );
823 }
Brian Murrayd666eb52016-05-19 15:59:23 -0700824#endif /* MBEDTLS_AES_C */
825
826#ifdef MBEDTLS_DES_C
Brian Murraybbed6602016-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 Murray3d3c9b82016-05-19 16:36:56 -0700837 {
838 return( ret );
839 }
Brian Murrayd666eb52016-05-19 15:59:23 -0700840
Brian Murraybbed6602016-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 Murray3d3c9b82016-05-19 16:36:56 -0700851 {
852 return( ret );
853 }
Brian Murrayd666eb52016-05-19 15:59:23 -0700854#endif /* MBEDTLS_DES_C */
855
856#ifdef MBEDTLS_AES_C
Brian Murray3d3c9b82016-05-19 16:36:56 -0700857 if( ( ret = test_aes128_cmac_prf( verbose ) != 0 ) )
858 return( ret );
Brian Murrayd666eb52016-05-19 15:59:23 -0700859#endif /* MBEDTLS_AES_C */
Brian Murray7c6476c2016-05-18 14:29:51 -0700860
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000861 if( verbose != 0 )
862 mbedtls_printf( "\n" );
Brian Murrayd666eb52016-05-19 15:59:23 -0700863
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000864 return( 0 );
865}
866
Brian Murrayd666eb52016-05-19 15:59:23 -0700867#endif /* MBEDTLS_SELF_TEST */
Robert Cragie9bf1e5d2015-12-15 07:38:11 +0000868
869#endif /* MBEDTLS_CMAC_C */