blob: e57e024bb0c05e11de87dbbe43a9ff46624f97d8 [file] [log] [blame]
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001/*
Brian Murray53e23b62016-09-13 14:00:15 -07002 * \file cmac.c
3 * \brief NIST SP800-38B compliant CMAC implementation
Robert Cragie3d23b1d2015-12-15 07:38:11 +00004 *
Brian Murray53e23b62016-09-13 14:00:15 -07005 * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
Robert Cragie3d23b1d2015-12-15 07:38:11 +00006 * SPDX-License-Identifier: Apache-2.0
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License"); you may
9 * not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 * This file is part of mbed TLS (https://tls.mbed.org)
21 */
22
23/*
Brian Murray53e23b62016-09-13 14:00:15 -070024 * References:
25 * - CMAC: NIST SP 800-38B
26 * - CMAC PRF: RFC 4493
27 * - Additional test vectors: ISO/IEC 9797-1
Robert Cragie3d23b1d2015-12-15 07:38:11 +000028 */
29
30#if !defined(MBEDTLS_CONFIG_FILE)
31#include "mbedtls/config.h"
32#else
33#include MBEDTLS_CONFIG_FILE
34#endif
35
36#if defined(MBEDTLS_CMAC_C)
37
38#include "mbedtls/cmac.h"
39
40#include <string.h>
41
42#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
43#if defined(MBEDTLS_PLATFORM_C)
44#include "mbedtls/platform.h"
45#else
46#include <stdio.h>
47#define mbedtls_printf printf
48#endif /* MBEDTLS_PLATFORM_C */
49#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
50
Robert Cragie3d23b1d2015-12-15 07:38:11 +000051/* Implementation that should never be optimized out by the compiler */
52static void mbedtls_zeroize( void *v, size_t n ) {
53 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
54}
55
56/*
57 * Initialize context
58 */
59void mbedtls_cmac_init( mbedtls_cmac_context *ctx )
60{
61 memset( ctx, 0, sizeof( mbedtls_cmac_context ) );
62}
63
64/*
Brian Murrayb0c3c432016-05-18 14:29:51 -070065 * Multiplication by u in the Galois field of GF(2^n)
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000066 *
Brian Murray87e40402016-05-19 19:05:57 -070067 * As explained in the paper, this can be computed:
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000068 * If MSB(p) = 0, then p = (p << 1)
Brian Murrayb0c3c432016-05-18 14:29:51 -070069 * If MSB(p) = 1, then p = (p << 1) ^ R_n
70 * with R_64 = 0x1B and R_128 = 0x87
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000071 *
72 * Input and output MUST not point to the same buffer
Brian Murrayb0c3c432016-05-18 14:29:51 -070073 * Block size must be 8 byes or 16 bytes.
Robert Cragie3d23b1d2015-12-15 07:38:11 +000074 */
Brian Murrayb0c3c432016-05-18 14:29:51 -070075static int cmac_multiply_by_u( unsigned char *output,
76 const unsigned char *input,
Brian Murray53e23b62016-09-13 14:00:15 -070077 size_t blocksize )
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 Murray6a3c0d22016-05-20 18:25:43 -070087 if( blocksize == 16 )
88 {
Brian Murrayb0c3c432016-05-18 14:29:51 -070089 R_n = R_128;
Brian Murray6a3c0d22016-05-20 18:25:43 -070090 } else if( blocksize == 8 )
91 {
Brian Murrayb0c3c432016-05-18 14:29:51 -070092 R_n = R_64;
Brian Murray6a3c0d22016-05-20 18:25:43 -070093 } else
94 {
Brian Murrayb439d452016-05-19 16:02:42 -070095 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
Brian Murrayb0c3c432016-05-18 14:29:51 -070096 }
97
Brian Murrayb0c3c432016-05-18 14:29:51 -070098 for( i = starting_index; i >= 0; i-- )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000099 {
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000100 output[i] = input[i] << 1 | overflow;
101 overflow = input[i] >> 7;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000102 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000103
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +0000104 /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
105 * using bit operations to avoid branches */
106 /* MSVC has a warning about unary minus on unsigned, but this is
107 * well-defined and precisely what we want to do here */
108#if defined(_MSC_VER)
109#pragma warning( push )
110#pragma warning( disable : 4146 )
111#endif
112 mask = - ( input[0] >> 7 );
113#if defined(_MSC_VER)
114#pragma warning( pop )
115#endif
116
Brian Murrayb0c3c432016-05-18 14:29:51 -0700117 output[starting_index] ^= R_n & mask;
Brian Murrayb439d452016-05-19 16:02:42 -0700118 return( 0 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000119}
120
121/*
122 * Generate subkeys
123 */
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000124static int cmac_generate_subkeys( mbedtls_cmac_context *ctx )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000125{
Brian Murray57863ad2016-05-19 16:38:36 -0700126 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700127 unsigned char *L;
128 size_t olen, block_size;
129
Brian Murrayb0c3c432016-05-18 14:29:51 -0700130 block_size = ctx->cipher_ctx.cipher_info->block_size;
131
Brian Murrayb439d452016-05-19 16:02:42 -0700132 L = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Brian Murray4b64ab62016-05-20 06:33:01 -0700133 if( L == NULL )
Brian Murray57863ad2016-05-19 16:38:36 -0700134 {
135 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
136 goto exit;
137 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000138 /* Calculate Ek(0) */
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 Murray6a3c0d22016-05-20 18:25:43 -0700150 if( ( ret = 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 Murray53e23b62016-09-13 14:00:15 -0700156 mbedtls_free( L );
Brian Murrayb439d452016-05-19 16:02:42 -0700157 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 Murray53e23b62016-09-13 14:00:15 -0700205 int block_size;
206 block_size = ctx->cipher_ctx.cipher_info->block_size;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000207 mbedtls_cipher_free( &ctx->cipher_ctx );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700208
Brian Murray6a3c0d22016-05-20 18:25:43 -0700209 if( ctx->K1 != NULL )
210 mbedtls_zeroize( ctx->K1, block_size * sizeof( unsigned char ) );
211 if( ctx->K2 != NULL )
212 mbedtls_zeroize( ctx->K2, block_size * sizeof( unsigned char ) );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700213 mbedtls_free( ctx->K1 );
214 mbedtls_free( ctx->K2 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000215}
216
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000217/*
218 * Create padded last block from (partial) last block.
219 *
220 * We can't use the padding option from the cipher layer, as it only works for
221 * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
222 */
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000223static void cmac_pad( unsigned char padded_block[16],
Brian Murray53e23b62016-09-13 14:00:15 -0700224 size_t padded_block_len,
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000225 const unsigned char *last_block,
Brian Murrayb0c3c432016-05-18 14:29:51 -0700226 size_t last_block_len )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000227{
228 size_t j;
229
Brian Murrayb0c3c432016-05-18 14:29:51 -0700230 for( j = 0; j < padded_block_len; j++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000231 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700232 if( j < last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000233 padded_block[j] = last_block[j];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700234 else if( j == last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000235 padded_block[j] = 0x80;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000236 else
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000237 padded_block[j] = 0x00;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000238 }
239}
240
241/*
Brian Murrayb0c3c432016-05-18 14:29:51 -0700242 * XOR Block
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000243 * Here, macro results in smaller compiled code than static inline function
244 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700245#define XOR_BLOCK( o, i1, i2 ) \
246 for( i = 0; i < block_size; i++ ) \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000247 ( o )[i] = ( i1 )[i] ^ ( i2 )[i];
248
249/*
Brian Murray87e40402016-05-19 19:05:57 -0700250 * Update the CMAC state using an input block
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000251 */
252#define UPDATE_CMAC( x ) \
253do { \
Brian Murrayb0c3c432016-05-18 14:29:51 -0700254 XOR_BLOCK( state, ( x ), state ); \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000255 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \
Brian Murrayb0c3c432016-05-18 14:29:51 -0700256 state, block_size, \
257 state, &olen ) ) != 0 ) \
Brian Murray57863ad2016-05-19 16:38:36 -0700258 { \
259 goto exit; \
260 } \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000261} while( 0 )
262
263/*
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000264 * Generate tag on complete message
265 */
Manuel Pégourié-Gonnardab9c5fd2016-01-13 15:05:57 +0000266int mbedtls_cmac_generate( mbedtls_cmac_context *ctx,
267 const unsigned char *input, size_t in_len,
268 unsigned char *tag, size_t tag_len )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000269{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700270 unsigned char *state;
271 unsigned char *M_last;
Brian Murray57863ad2016-05-19 16:38:36 -0700272 int n, j, ret, needs_padding;
273 size_t olen, block_size, i;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700274
Brian Murrayb0c3c432016-05-18 14:29:51 -0700275 ret = 0;
276 block_size = ctx->cipher_ctx.cipher_info->block_size;
277
Brian Murrayb439d452016-05-19 16:02:42 -0700278 state = mbedtls_calloc( block_size, sizeof( unsigned char ) );
279 M_last = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000280
Brian Murray57863ad2016-05-19 16:38:36 -0700281 if( state == NULL || M_last == NULL )
282 {
283 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
284 goto exit;
285 }
286
Brian Murray87e40402016-05-19 19:05:57 -0700287 if( tag_len < 2 || tag_len > block_size || tag_len % 2 != 0 )
Brian Murray57863ad2016-05-19 16:38:36 -0700288 {
289 ret = MBEDTLS_ERR_CMAC_BAD_INPUT;
290 goto exit;
291 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000292
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000293 if( in_len == 0 )
294 needs_padding = 1;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000295 else
Brian Murrayb0c3c432016-05-18 14:29:51 -0700296 needs_padding = in_len % block_size != 0;
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000297
Brian Murrayb0c3c432016-05-18 14:29:51 -0700298 n = in_len / block_size + needs_padding;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000299
300 /* Calculate last block */
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000301 if( needs_padding )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000302 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700303 cmac_pad( M_last, block_size, input + block_size * ( n - 1 ), in_len % block_size );
304 XOR_BLOCK( M_last, M_last, ctx->K2 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000305 }
306 else
307 {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000308 /* Last block is complete block */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700309 XOR_BLOCK( M_last, input + block_size * ( n - 1 ), ctx->K1 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000310 }
311
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000312 for( j = 0; j < n - 1; j++ )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700313 UPDATE_CMAC( input + block_size * j );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000314
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000315 UPDATE_CMAC( M_last );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000316
Brian Murray00dc5f02016-05-19 14:23:50 -0700317 memcpy( tag, state, tag_len );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000318
Brian Murrayb0c3c432016-05-18 14:29:51 -0700319 exit:
Brian Murray4b64ab62016-05-20 06:33:01 -0700320 mbedtls_free( state );
321 mbedtls_free( M_last );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700322 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000323}
324
Brian Murrayb0c3c432016-05-18 14:29:51 -0700325#undef XOR_BLOCK
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000326#undef UPDATE_CMAC
327
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000328/*
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000329 * Verify tag on complete message
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000330 */
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000331int mbedtls_cmac_verify( mbedtls_cmac_context *ctx,
332 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000333 const unsigned char *tag, size_t tag_len )
334{
335 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700336 unsigned char *check_tag;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000337 unsigned char i;
338 int diff;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000339
Brian Murrayb439d452016-05-19 16:02:42 -0700340 check_tag = mbedtls_calloc( ctx->cipher_ctx.cipher_info->block_size,
341 sizeof( unsigned char ) );
Brian Murray4b64ab62016-05-20 06:33:01 -0700342 if( check_tag == NULL )
Brian Murray57863ad2016-05-19 16:38:36 -0700343 {
344 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
345 goto exit;
346 }
Brian Murrayb0c3c432016-05-18 14:29:51 -0700347
Manuel Pégourié-Gonnardab9c5fd2016-01-13 15:05:57 +0000348 if( ( ret = mbedtls_cmac_generate( ctx, input, in_len,
349 check_tag, tag_len ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000350 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700351 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000352 }
353
354 /* Check tag in "constant-time" */
355 for( diff = 0, i = 0; i < tag_len; i++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000356 diff |= tag[i] ^ check_tag[i];
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000357
358 if( diff != 0 )
Brian Murray9ce2e092016-05-24 22:46:43 -0700359 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700360 ret = MBEDTLS_ERR_CMAC_VERIFY_FAILED;
361 goto exit;
Brian Murray9ce2e092016-05-24 22:46:43 -0700362 }
363 else
364 {
365 ret = 0;
366 goto exit;
367 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000368
Brian Murrayb0c3c432016-05-18 14:29:51 -0700369 exit:
Brian Murray4b64ab62016-05-20 06:33:01 -0700370 mbedtls_free( check_tag );
Brian Murrayb439d452016-05-19 16:02:42 -0700371 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000372}
373
Brian Murrayb439d452016-05-19 16:02:42 -0700374#ifdef MBEDTLS_AES_C
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000375/*
376 * PRF based on CMAC with AES-128
Brian Murrayb0c3c432016-05-18 14:29:51 -0700377 * See RFC 4615
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000378 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700379int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000380 const unsigned char *input, size_t in_len,
Brian Murrayb439d452016-05-19 16:02:42 -0700381 unsigned char tag[16] )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000382{
383 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700384 mbedtls_cmac_context ctx;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000385 unsigned char zero_key[16];
386 unsigned char int_key[16];
387
Brian Murrayb439d452016-05-19 16:02:42 -0700388 mbedtls_cmac_init(&ctx );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700389
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000390 if( key_length == 16 )
391 {
392 /* Use key as is */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000393 memcpy( int_key, key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000394 }
395 else
396 {
397 mbedtls_cmac_context zero_ctx;
398
Brian Murrayb439d452016-05-19 16:02:42 -0700399 /* Key is AES_CMAC( 0, key ) */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000400 mbedtls_cmac_init( &zero_ctx );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000401 memset( zero_key, 0, 16 );
402 ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES,
Brian Murray6a3c0d22016-05-20 18:25:43 -0700403 zero_key, 8 * sizeof( zero_key ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000404 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700405 goto exit;
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000406
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000407 ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000408 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700409 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000410 }
411
Brian Murrayb0c3c432016-05-18 14:29:51 -0700412 ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
Brian Murray6a3c0d22016-05-20 18:25:43 -0700413 int_key, 8 * sizeof( int_key ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000414 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700415 goto exit;
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000416
Brian Murrayb0c3c432016-05-18 14:29:51 -0700417 ret = mbedtls_cmac_generate( &ctx, input, in_len, tag, 16 );
418
419 exit:
Brian Murray6a3c0d22016-05-20 18:25:43 -0700420 mbedtls_zeroize( int_key, sizeof( int_key ) );
421 mbedtls_cmac_free( &ctx );
Brian Murray53e23b62016-09-13 14:00:15 -0700422 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000423}
Brian Murrayb439d452016-05-19 16:02:42 -0700424#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000425
Brian Murray0f6af732016-05-19 15:59:23 -0700426#ifdef MBEDTLS_SELF_TEST
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000427/*
Brian Murray0f6af732016-05-19 15:59:23 -0700428 * CMAC test data from SP800-38B Appendix D.1 (corrected)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000429 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
Brian Murray0f6af732016-05-19 15:59:23 -0700430 *
431 * AES-CMAC-PRF-128 test data from RFC 4615
432 * https://tools.ietf.org/html/rfc4615#page-4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000433 */
434
Brian Murray0f6af732016-05-19 15:59:23 -0700435#define NB_CMAC_TESTS_PER_KEY 4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000436#define NB_PRF_TESTS 3
Brian Murray0f6af732016-05-19 15:59:23 -0700437#define AES_BLOCK_SIZE 16
438#define DES3_BLOCK_SIZE 8
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000439
Brian Murray0f6af732016-05-19 15:59:23 -0700440#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
441/* All CMAC test inputs are truncated from the same 64 byte buffer. */
442static const unsigned char test_message[] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000443 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
444 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
445 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
446 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
447 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
448 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
449 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
450 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
451};
Brian Murray0cf14c12016-05-23 12:49:50 -0700452
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 Murray87e40402016-05-19 19:05:57 -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 Murray87e40402016-05-19 19:05:57 -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
Brian Murray0f6af732016-05-19 15:59:23 -0700540};
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 Murray87e40402016-05-19 19:05:57 -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
Brian Murray0f6af732016-05-19 15:59:23 -0700585};
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 Murray87e40402016-05-19 19:05:57 -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
Brian Murray0f6af732016-05-19 15:59:23 -0700614};
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 Murrayae1cb122016-05-23 15:01:59 -0700678static inline int cmac_test_wth_cipher( int verbose,
679 const char* testname,
680 const unsigned char* key,
681 int keybits,
682 const unsigned char* messages,
683 const unsigned int message_lengths[4],
684 const unsigned char* subkeys,
685 const unsigned char* expected_result,
686 mbedtls_cipher_id_t cipher_id,
687 int block_size )
Brian Murray00dc5f02016-05-19 14:23:50 -0700688{
Brian Murray87e40402016-05-19 19:05:57 -0700689 const int num_tests = 4;
690 mbedtls_cmac_context ctx;
Brian Murray00dc5f02016-05-19 14:23:50 -0700691 int i, ret;
692 unsigned char* tag;
693
694 tag = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Brian Murray6a3c0d22016-05-20 18:25:43 -0700695 if( tag == NULL )
696 {
Brian Murray57863ad2016-05-19 16:38:36 -0700697 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
698 goto exit;
699 }
700
Brian Murray00dc5f02016-05-19 14:23:50 -0700701 mbedtls_cmac_init( &ctx );
702
703 if( ( ret = mbedtls_cmac_setkey( &ctx, cipher_id, key, keybits ) ) != 0 )
704 {
705 if( verbose != 0 )
706 mbedtls_printf( " CMAC: setup failed\n" );
707 goto exit;
708 }
709
710 if( ( ret = memcmp( ctx.K1, subkeys, block_size ) != 0 ) ||
711 ( ret = memcmp( ctx.K2, &subkeys[block_size], block_size ) != 0 ) )
712 {
713 if( verbose != 0 )
714 mbedtls_printf( " CMAC: subkey generation failed\n" );
715 goto exit;
716 }
717
718 for( i = 0; i < num_tests; i++ )
719 {
720 if( verbose != 0 )
721 mbedtls_printf( " %s CMAC #%u: ", testname, i +1 );
722
723 if( ( ret = mbedtls_cmac_generate( &ctx, messages, message_lengths[i], tag, block_size ) ) != 0 )
724 {
725 if( verbose != 0 )
726 mbedtls_printf( "failed\n" );
727 goto exit;
728 }
Brian Murray9ce2e092016-05-24 22:46:43 -0700729
Brian Murray00dc5f02016-05-19 14:23:50 -0700730 if( ( ret = memcmp( tag, &expected_result[i * block_size], block_size ) ) != 0 )
731 {
732 if( verbose != 0 )
733 mbedtls_printf( "failed\n" );
734 goto exit;
735 }
736
737 if( ( ret = mbedtls_cmac_verify( &ctx, messages, message_lengths[i], &expected_result[i * block_size], block_size ) != 0 ) )
738 {
Brian Murray4b64ab62016-05-20 06:33:01 -0700739 if( verbose != 0 )
740 mbedtls_printf( "failed\n" );
741 goto exit;
Brian Murray00dc5f02016-05-19 14:23:50 -0700742 }
Brian Murray9ce2e092016-05-24 22:46:43 -0700743
744 if( verbose != 0 )
745 mbedtls_printf( "passed\n" );
Brian Murray00dc5f02016-05-19 14:23:50 -0700746 }
747 exit:
Brian Murray4b64ab62016-05-20 06:33:01 -0700748 mbedtls_free( tag );
Brian Murray00dc5f02016-05-19 14:23:50 -0700749 mbedtls_cmac_free( &ctx );
750 return( ret );
751}
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000752
Brian Murray0f6af732016-05-19 15:59:23 -0700753#ifdef MBEDTLS_AES_C
Brian Murrayae1cb122016-05-23 15:01:59 -0700754static inline int test_aes128_cmac_prf( int verbose )
Brian Murray6a3c0d22016-05-20 18:25:43 -0700755{
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000756 int i;
757 int ret;
Brian Murray0f6af732016-05-19 15:59:23 -0700758 unsigned char tag[16];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700759 for( i = 0; i < NB_PRF_TESTS; i++ )
760 {
Brian Murray0f6af732016-05-19 15:59:23 -0700761 mbedtls_printf( " AES CMAC 128 PRF #%u: ", i );
762 ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, tag );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700763 if( ret != 0 ||
764 memcmp( tag, PRFT[i], 16 ) != 0 )
765 {
766 if( verbose != 0 )
767 mbedtls_printf( "failed\n" );
768
Brian Murray0f6af732016-05-19 15:59:23 -0700769 return( ret );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700770 } else if( verbose != 0 )
771 {
772 mbedtls_printf( "passed\n" );
773 }
774 }
Brian Murray0f6af732016-05-19 15:59:23 -0700775 return( ret );
776}
777#endif /* MBEDTLS_AES_C */
778
779int mbedtls_cmac_self_test( int verbose )
780{
781 int ret;
782
783#ifdef MBEDTLS_AES_C
Brian Murrayae1cb122016-05-23 15:01:59 -0700784 if( ( ret = cmac_test_wth_cipher( verbose,
785 "AES 128",
786 aes_128_key,
787 128,
788 test_message,
789 aes_message_lengths,
790 (const unsigned char*) aes_128_subkeys,
791 (const unsigned char*) aes_128_expected_result,
792 MBEDTLS_CIPHER_ID_AES,
793 AES_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700794 {
795 return( ret );
796 }
Brian Murray0f6af732016-05-19 15:59:23 -0700797
Brian Murrayae1cb122016-05-23 15:01:59 -0700798 if( ( ret = cmac_test_wth_cipher( verbose,
799 "AES 192",
800 aes_192_key,
801 192,
802 test_message,
803 aes_message_lengths,
804 (const unsigned char*) aes_192_subkeys,
805 (const unsigned char*) aes_192_expected_result,
806 MBEDTLS_CIPHER_ID_AES,
807 AES_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700808 {
809 return( ret );
810 }
Brian Murray0f6af732016-05-19 15:59:23 -0700811
Brian Murrayae1cb122016-05-23 15:01:59 -0700812 if( ( ret = cmac_test_wth_cipher ( verbose,
813 "AES 256",
814 aes_256_key,
815 256,
816 test_message,
817 aes_message_lengths,
818 (const unsigned char*) aes_256_subkeys,
819 (const unsigned char*) aes_256_expected_result,
820 MBEDTLS_CIPHER_ID_AES,
821 AES_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700822 {
823 return( ret );
824 }
Brian Murray0f6af732016-05-19 15:59:23 -0700825#endif /* MBEDTLS_AES_C */
826
827#ifdef MBEDTLS_DES_C
Brian Murrayae1cb122016-05-23 15:01:59 -0700828 if( ( ret = cmac_test_wth_cipher( verbose,
829 "3DES 2 key",
830 des3_2key_key,
831 192,
832 test_message,
833 des3_message_lengths,
834 (const unsigned char*) des3_2key_subkeys,
835 (const unsigned char*) des3_2key_expected_result,
836 MBEDTLS_CIPHER_ID_3DES,
837 DES3_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700838 {
839 return( ret );
840 }
Brian Murray0f6af732016-05-19 15:59:23 -0700841
Brian Murrayae1cb122016-05-23 15:01:59 -0700842 if( ( ret = cmac_test_wth_cipher( verbose,
843 "3DES 3 key",
844 des3_3key_key,
845 192,
846 test_message,
847 des3_message_lengths,
848 (const unsigned char*) des3_3key_subkeys,
849 (const unsigned char*) des3_3key_expected_result,
850 MBEDTLS_CIPHER_ID_3DES,
851 DES3_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700852 {
853 return( ret );
854 }
Brian Murray0f6af732016-05-19 15:59:23 -0700855#endif /* MBEDTLS_DES_C */
856
857#ifdef MBEDTLS_AES_C
Brian Murray9044b022016-05-19 16:36:56 -0700858 if( ( ret = test_aes128_cmac_prf( verbose ) != 0 ) )
859 return( ret );
Brian Murray0f6af732016-05-19 15:59:23 -0700860#endif /* MBEDTLS_AES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700861
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000862 if( verbose != 0 )
863 mbedtls_printf( "\n" );
Brian Murray0f6af732016-05-19 15:59:23 -0700864
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000865 return( 0 );
866}
867
Brian Murray0f6af732016-05-19 15:59:23 -0700868#endif /* MBEDTLS_SELF_TEST */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000869
870#endif /* MBEDTLS_CMAC_C */