blob: 3d223194be4ff1b878ea2b09b6cff0408c6e8e5a [file] [log] [blame]
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001/*
2 * NIST SP800-38B compliant CMAC implementation
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21
22/*
23 * Definition of CMAC:
24 * http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
25 * RFC 4493 "The AES-CMAC Algorithm"
26 */
27
28#if !defined(MBEDTLS_CONFIG_FILE)
29#include "mbedtls/config.h"
30#else
31#include MBEDTLS_CONFIG_FILE
32#endif
33
34#if defined(MBEDTLS_CMAC_C)
35
36#include "mbedtls/cmac.h"
37
38#include <string.h>
39
40#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
41#if defined(MBEDTLS_PLATFORM_C)
42#include "mbedtls/platform.h"
43#else
44#include <stdio.h>
45#define mbedtls_printf printf
46#endif /* MBEDTLS_PLATFORM_C */
47#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
48
Robert Cragie3d23b1d2015-12-15 07:38:11 +000049/* Implementation that should never be optimized out by the compiler */
50static void mbedtls_zeroize( void *v, size_t n ) {
51 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
52}
53
54/*
55 * Initialize context
56 */
57void mbedtls_cmac_init( mbedtls_cmac_context *ctx )
58{
59 memset( ctx, 0, sizeof( mbedtls_cmac_context ) );
60}
61
Brian Murray00dc5f02016-05-19 14:23:50 -070062
Robert Cragie3d23b1d2015-12-15 07:38:11 +000063/*
Brian Murrayb0c3c432016-05-18 14:29:51 -070064 * Multiplication by u in the Galois field of GF(2^n)
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000065 *
Brian Murrayb0c3c432016-05-18 14:29:51 -070066 * As explained in the paper, this can computed:
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000067 * If MSB(p) = 0, then p = (p << 1)
Brian Murrayb0c3c432016-05-18 14:29:51 -070068 * If MSB(p) = 1, then p = (p << 1) ^ R_n
69 * with R_64 = 0x1B and R_128 = 0x87
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000070 *
71 * Input and output MUST not point to the same buffer
Brian Murrayb0c3c432016-05-18 14:29:51 -070072 * Block size must be 8 byes or 16 bytes.
Robert Cragie3d23b1d2015-12-15 07:38:11 +000073 */
Brian Murrayb0c3c432016-05-18 14:29:51 -070074static int cmac_multiply_by_u( unsigned char *output,
75 const unsigned char *input,
Brian Murrayb439d452016-05-19 16:02:42 -070076 size_t blocksize )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000077{
Robert Cragie3d23b1d2015-12-15 07:38:11 +000078
Brian Murrayb0c3c432016-05-18 14:29:51 -070079 const unsigned char R_128 = 0x87;
80 const unsigned char R_64 = 0x1B;
81 unsigned char R_n, mask;
82 unsigned char overflow = 0x00;
83 int i, starting_index;
84
85 starting_index = blocksize -1;
86
Brian Murrayb439d452016-05-19 16:02:42 -070087 if( blocksize == 16 ){
Brian Murrayb0c3c432016-05-18 14:29:51 -070088 R_n = R_128;
Brian Murrayb439d452016-05-19 16:02:42 -070089 } else if( blocksize == 8 ) {
Brian Murrayb0c3c432016-05-18 14:29:51 -070090 R_n = R_64;
91 } else {
Brian Murrayb439d452016-05-19 16:02:42 -070092 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
Brian Murrayb0c3c432016-05-18 14:29:51 -070093 }
94
95
96 for( i = starting_index; i >= 0; i-- )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000097 {
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000098 output[i] = input[i] << 1 | overflow;
99 overflow = input[i] >> 7;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000100 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000101
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +0000102 /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
103 * using bit operations to avoid branches */
104 /* MSVC has a warning about unary minus on unsigned, but this is
105 * well-defined and precisely what we want to do here */
106#if defined(_MSC_VER)
107#pragma warning( push )
108#pragma warning( disable : 4146 )
109#endif
110 mask = - ( input[0] >> 7 );
111#if defined(_MSC_VER)
112#pragma warning( pop )
113#endif
114
Brian Murrayb0c3c432016-05-18 14:29:51 -0700115 output[starting_index] ^= R_n & mask;
Brian Murrayb439d452016-05-19 16:02:42 -0700116 return( 0 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000117}
118
119/*
120 * Generate subkeys
121 */
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000122static int cmac_generate_subkeys( mbedtls_cmac_context *ctx )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000123{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700124 int ret, keybytes;
125 unsigned char *L;
126 size_t olen, block_size;
127
128 ret = 0;
129 block_size = ctx->cipher_ctx.cipher_info->block_size;
130
Brian Murrayb439d452016-05-19 16:02:42 -0700131 L = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000132
133 /* Calculate Ek(0) */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700134 memset( L, 0, block_size );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000135 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx,
Brian Murrayb0c3c432016-05-18 14:29:51 -0700136 L, block_size, L, &olen ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000137 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700138 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000139 }
140
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000141 /*
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000142 * Generate K1 and K2
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000143 */
Brian Murrayb439d452016-05-19 16:02:42 -0700144 if( ( ret = cmac_multiply_by_u( ctx->K1, L , block_size ) ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700145 goto exit;
Brian Murrayb439d452016-05-19 16:02:42 -0700146 if( ( cmac_multiply_by_u( ctx->K2, ctx->K1 , block_size ) ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700147 goto exit;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000148
Brian Murrayb0c3c432016-05-18 14:29:51 -0700149 exit:
150 mbedtls_zeroize( L, sizeof( L ) );
Brian Murrayb439d452016-05-19 16:02:42 -0700151 free( L );
152 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000153}
154
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000155/*
156 * Set key and prepare context for use
157 */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000158int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx,
159 mbedtls_cipher_id_t cipher,
160 const unsigned char *key,
161 unsigned int keybits )
162{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700163 int ret, blocksize;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000164 const mbedtls_cipher_info_t *cipher_info;
165
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000166 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
167 MBEDTLS_MODE_ECB );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000168 if( cipher_info == NULL )
169 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
170
Brian Murrayb0c3c432016-05-18 14:29:51 -0700171 ctx->K1 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) );
172 ctx->K2 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000173
174 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
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000185 return( cmac_generate_subkeys( ctx ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000186}
187
188/*
189 * Free context
190 */
191void mbedtls_cmac_free( mbedtls_cmac_context *ctx )
192{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700193 int block_size;
194 block_size = ctx->cipher_ctx.cipher_info->block_size;
195
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000196 mbedtls_cipher_free( &ctx->cipher_ctx );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700197
Brian Murrayb439d452016-05-19 16:02:42 -0700198 mbedtls_zeroize( ctx->K1, block_size * sizeof( unsigned char ) );
199 mbedtls_zeroize( ctx->K2, block_size * sizeof( unsigned char ) );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700200 mbedtls_free( ctx->K1 );
201 mbedtls_free( ctx->K2 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000202}
203
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000204/*
205 * Create padded last block from (partial) last block.
206 *
207 * We can't use the padding option from the cipher layer, as it only works for
208 * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
209 */
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000210static void cmac_pad( unsigned char padded_block[16],
Brian Murrayb0c3c432016-05-18 14:29:51 -0700211 size_t padded_block_len,
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000212 const unsigned char *last_block,
Brian Murrayb0c3c432016-05-18 14:29:51 -0700213 size_t last_block_len )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000214{
215 size_t j;
216
Brian Murrayb0c3c432016-05-18 14:29:51 -0700217 for( j = 0; j < padded_block_len; j++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000218 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700219 if( j < last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000220 padded_block[j] = last_block[j];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700221 else if( j == last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000222 padded_block[j] = 0x80;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000223 else
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000224 padded_block[j] = 0x00;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000225 }
226}
227
228/*
Brian Murrayb0c3c432016-05-18 14:29:51 -0700229 * XOR Block
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000230 * Here, macro results in smaller compiled code than static inline function
231 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700232#define XOR_BLOCK( o, i1, i2 ) \
233 for( i = 0; i < block_size; i++ ) \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000234 ( o )[i] = ( i1 )[i] ^ ( i2 )[i];
235
236/*
237 * Update the CMAC state using an input block x
238 */
239#define UPDATE_CMAC( x ) \
240do { \
Brian Murrayb0c3c432016-05-18 14:29:51 -0700241 XOR_BLOCK( state, ( x ), state ); \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000242 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \
Brian Murrayb0c3c432016-05-18 14:29:51 -0700243 state, block_size, \
244 state, &olen ) ) != 0 ) \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000245 return( ret ); \
246} while( 0 )
247
248/*
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000249 * Generate tag on complete message
250 */
Manuel Pégourié-Gonnardab9c5fd2016-01-13 15:05:57 +0000251int mbedtls_cmac_generate( mbedtls_cmac_context *ctx,
252 const unsigned char *input, size_t in_len,
253 unsigned char *tag, size_t tag_len )
254
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000255{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700256
257 unsigned char *state;
258 unsigned char *M_last;
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000259 int n, i, j, ret, needs_padding;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700260 size_t olen, block_size;
261
262
263 ret = 0;
264 block_size = ctx->cipher_ctx.cipher_info->block_size;
265
Brian Murrayb439d452016-05-19 16:02:42 -0700266 state = mbedtls_calloc( block_size, sizeof( unsigned char ) );
267 M_last = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000268
269 /*
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000270 * Check in_len requirements: SP800-38B A
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000271 * 4 is a worst case bottom limit
272 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700273 if( tag_len < 4 || tag_len > block_size || tag_len % 2 != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000274 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
275
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000276 if( in_len == 0 )
277 needs_padding = 1;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000278 else
Brian Murrayb0c3c432016-05-18 14:29:51 -0700279 needs_padding = in_len % block_size != 0;
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000280
Brian Murrayb0c3c432016-05-18 14:29:51 -0700281 n = in_len / block_size + needs_padding;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000282
283 /* Calculate last block */
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000284 if( needs_padding )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000285 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700286 cmac_pad( M_last, block_size, input + block_size * ( n - 1 ), in_len % block_size );
287 XOR_BLOCK( M_last, M_last, ctx->K2 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000288 }
289 else
290 {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000291 /* Last block is complete block */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700292 XOR_BLOCK( M_last, input + block_size * ( n - 1 ), ctx->K1 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000293 }
294
Brian Murrayb0c3c432016-05-18 14:29:51 -0700295 memset( state, 0, block_size );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000296
297 for( j = 0; j < n - 1; j++ )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700298 UPDATE_CMAC( input + block_size * j );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000299
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000300 UPDATE_CMAC( M_last );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000301
Brian Murray00dc5f02016-05-19 14:23:50 -0700302 memcpy( tag, state, tag_len );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000303
Brian Murrayb0c3c432016-05-18 14:29:51 -0700304 exit:
Brian Murrayb439d452016-05-19 16:02:42 -0700305 free( state );
306 free( M_last );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700307 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000308}
309
Brian Murrayb0c3c432016-05-18 14:29:51 -0700310#undef XOR_BLOCK
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000311#undef UPDATE_CMAC
312
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000313/*
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000314 * Verify tag on complete message
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000315 */
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000316int mbedtls_cmac_verify( mbedtls_cmac_context *ctx,
317 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000318 const unsigned char *tag, size_t tag_len )
319{
320 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700321 unsigned char *check_tag;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000322 unsigned char i;
323 int diff;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000324
Brian Murrayb439d452016-05-19 16:02:42 -0700325 check_tag = mbedtls_calloc( ctx->cipher_ctx.cipher_info->block_size,
326 sizeof( unsigned char ) );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700327
Manuel Pégourié-Gonnardab9c5fd2016-01-13 15:05:57 +0000328 if( ( ret = mbedtls_cmac_generate( ctx, input, in_len,
329 check_tag, tag_len ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000330 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700331 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000332 }
333
334 /* Check tag in "constant-time" */
335 for( diff = 0, i = 0; i < tag_len; i++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000336 diff |= tag[i] ^ check_tag[i];
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000337
338 if( diff != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700339 ret = MBEDTLS_ERR_CMAC_VERIFY_FAILED;
340 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000341
Brian Murrayb0c3c432016-05-18 14:29:51 -0700342 exit:
Brian Murrayb439d452016-05-19 16:02:42 -0700343 free( check_tag );
344 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000345}
346
Brian Murrayb439d452016-05-19 16:02:42 -0700347#ifdef MBEDTLS_AES_C
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000348/*
349 * PRF based on CMAC with AES-128
Brian Murrayb0c3c432016-05-18 14:29:51 -0700350 * See RFC 4615
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000351 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700352int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000353 const unsigned char *input, size_t in_len,
Brian Murrayb439d452016-05-19 16:02:42 -0700354 unsigned char tag[16] )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000355{
356 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700357 mbedtls_cmac_context ctx;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000358 unsigned char zero_key[16];
359 unsigned char int_key[16];
360
Brian Murrayb439d452016-05-19 16:02:42 -0700361 mbedtls_cmac_init(&ctx );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700362
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000363 if( key_length == 16 )
364 {
365 /* Use key as is */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000366 memcpy( int_key, key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000367 }
368 else
369 {
370 mbedtls_cmac_context zero_ctx;
371
Brian Murrayb439d452016-05-19 16:02:42 -0700372 /* Key is AES_CMAC( 0, key ) */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000373 mbedtls_cmac_init( &zero_ctx );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000374 memset( zero_key, 0, 16 );
375 ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES,
376 zero_key, 8 * sizeof zero_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000377 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700378 goto exit;
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000379
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000380 ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000381 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700382 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000383 }
384
Brian Murrayb0c3c432016-05-18 14:29:51 -0700385 ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000386 int_key, 8 * sizeof int_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000387 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700388 goto exit;
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000389
390 mbedtls_zeroize( int_key, sizeof( int_key ) );
391
Brian Murrayb0c3c432016-05-18 14:29:51 -0700392 ret = mbedtls_cmac_generate( &ctx, input, in_len, tag, 16 );
393
394 exit:
Brian Murrayb439d452016-05-19 16:02:42 -0700395 mbedtls_cmac_free( &ctx );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700396 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000397}
Brian Murrayb439d452016-05-19 16:02:42 -0700398#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000399
Brian Murray0f6af732016-05-19 15:59:23 -0700400#ifdef MBEDTLS_SELF_TEST
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000401/*
Brian Murray0f6af732016-05-19 15:59:23 -0700402 * CMAC test data from SP800-38B Appendix D.1 (corrected)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000403 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
Brian Murray0f6af732016-05-19 15:59:23 -0700404 *
405 * AES-CMAC-PRF-128 test data from RFC 4615
406 * https://tools.ietf.org/html/rfc4615#page-4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000407 */
408
Brian Murray0f6af732016-05-19 15:59:23 -0700409#define NB_CMAC_TESTS_PER_KEY 4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000410#define NB_PRF_TESTS 3
Brian Murray0f6af732016-05-19 15:59:23 -0700411#define AES_BLOCK_SIZE 16
412#define DES3_BLOCK_SIZE 8
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000413
Brian Murray0f6af732016-05-19 15:59:23 -0700414#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
415/* All CMAC test inputs are truncated from the same 64 byte buffer. */
416static const unsigned char test_message[] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000417 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
418 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
419 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
420 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
421 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
422 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
423 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
424 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
425};
Brian Murray0f6af732016-05-19 15:59:23 -0700426#endif /* defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000427
Brian Murray0f6af732016-05-19 15:59:23 -0700428#ifdef MBEDTLS_AES_C
429/* Truncation point of message for AES CMAC tests */
430static const size_t aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
431 0,
432 16,
433 40,
434 64
435};
436
437/* AES 128 CMAC Test Data */
438static const unsigned char aes_128_key[] = {
439 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
440 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
441};
442static const unsigned char aes_128_subkeys[2][AES_BLOCK_SIZE] = {
443 {
444 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
445 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
446 },
447 {
448 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
449 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
450 }
451};
452static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000453 {
454 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
455 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
456 },
457 {
458 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
459 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
460 },
461 {
462 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
463 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
464 },
465 {
466 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
467 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
468 }
469};
470
Brian Murray0f6af732016-05-19 15:59:23 -0700471/* AES 192 CMAC Test Data */
472static const unsigned char aes_192_key[] = {
473 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
474 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
475 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000476};
Brian Murray0f6af732016-05-19 15:59:23 -0700477static const unsigned char aes_192_subkeys[2][AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700478 {
Brian Murray0f6af732016-05-19 15:59:23 -0700479 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
480 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
Brian Murrayb0c3c432016-05-18 14:29:51 -0700481 },
482 {
Brian Murray0f6af732016-05-19 15:59:23 -0700483 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
484 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
Brian Murrayb0c3c432016-05-18 14:29:51 -0700485 }
486};
Brian Murray0f6af732016-05-19 15:59:23 -0700487static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700488 {
489 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
490 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
491 },
492 {
493 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
494 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
495 },
496 {
497 0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad,
498 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e
499 },
500 {
501 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
502 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
503 }
504};
505
Brian Murray0f6af732016-05-19 15:59:23 -0700506/* AES 256 CMAC Test Data */
507static const unsigned char aes_256_key[] = {
508 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
509 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
510 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
511 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
512};
513static const unsigned char aes_256_subkeys[2][AES_BLOCK_SIZE] = {
514 {
515 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
516 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
517 },
518 {
519 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
520 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
521 }
522};
523static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
524 {
525 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
526 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
527 },
528 {
529 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
530 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
531 },
532 {
533 0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2,
534 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6
535 },
536 {
537 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
538 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
539 }
540};
541#endif /* MBEDTLS_AES_C */
542
543#ifdef MBEDTLS_DES_C
544/* Truncation point of message for 3DES CMAC tests */
545static const size_t des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
546 0,
547 8,
548 20,
549 32
550};
551
552/* 3DES 2 Key CMAC Test Data */
553static const unsigned char des3_2key_key[] = {
554 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5,
555 0x8a, 0x3d, 0x10, 0xba, 0x80, 0x57, 0x0d, 0x38,
556 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5
557};
558static const unsigned char des3_2key_subkeys[2][8] = {
559 {
560 0x8e, 0xcf, 0x37, 0x3e, 0xd7, 0x1a, 0xfa, 0xef
561 },
562 {
563 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5
564 }
565};
566static const unsigned char T_3des_2key[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700567 {
568 0xbd, 0x2e, 0xbf, 0x9a, 0x3b, 0xa0, 0x03, 0x61
569 },
570 {
571 0x4f, 0xf2, 0xab, 0x81, 0x3c, 0x53, 0xce, 0x83
572 },
573 {
574 0x62, 0xdd, 0x1b, 0x47, 0x19, 0x02, 0xbd, 0x4e
575 },
576 {
577 0x31, 0xb1, 0xe4, 0x31, 0xda, 0xbc, 0x4e, 0xb8
578 }
579};
580
Brian Murray0f6af732016-05-19 15:59:23 -0700581/* 3DES 3 Key CMAC Test Data */
582static const unsigned char des3_3key_key[] = {
583 0x8a, 0xa8, 0x3b, 0xf8, 0xcb, 0xda, 0x10, 0x62,
584 0x0b, 0xc1, 0xbf, 0x19, 0xfb, 0xb6, 0xcd, 0x58,
585 0xbc, 0x31, 0x3d, 0x4a, 0x37, 0x1c, 0xa8, 0xb5
586};
587static const unsigned char des3_3key_subkeys[2][8] = {
588 {
589 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f
590 },
591 {
592 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5
593 }
594};
595static const unsigned char T_3des_3key[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700596 {
597 0xb7, 0xa6, 0x88, 0xe1, 0x22, 0xff, 0xaf, 0x95
598 },
599 {
600 0x8e, 0x8f, 0x29, 0x31, 0x36, 0x28, 0x37, 0x97
601 },
602 {
603 0x74, 0x3d, 0xdb, 0xe0, 0xce, 0x2d, 0xc2, 0xed
604 },
605 {
606 0x33, 0xe6, 0xb1, 0x09, 0x24, 0x00, 0xea, 0xe5
607 }
608};
609
Brian Murray0f6af732016-05-19 15:59:23 -0700610#endif /* MBEDTLS_DES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700611
Brian Murray0f6af732016-05-19 15:59:23 -0700612#ifdef MBEDTLS_AES_C
613/* AES AES-CMAC-PRF-128 Test Data */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000614static const unsigned char PRFK[] = {
615 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
616 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
617 0xed, 0xcb
618};
619
620/* Sizes in bytes */
621static const size_t PRFKlen[NB_PRF_TESTS] = {
622 18,
623 16,
624 10
625};
626
627/* PRF M */
628static const unsigned char PRFM[] = {
629 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
630 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000631 0x10, 0x11, 0x12, 0x13
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000632};
633
634static const unsigned char PRFT[NB_PRF_TESTS][16] = {
635 {
636 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
637 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
638 },
639 {
640 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
641 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
642 },
643 {
644 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
645 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
646 }
647};
Brian Murray0f6af732016-05-19 15:59:23 -0700648#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000649
Brian Murrayb439d452016-05-19 16:02:42 -0700650int test_cmac_with_cipher( int verbose,
Brian Murray00dc5f02016-05-19 14:23:50 -0700651 const unsigned char* testname,
652 const unsigned char* key,
653 int keybits,
654 const unsigned char* messages,
655 size_t message_lengths[4],
656 const unsigned char* subkeys,
657 const unsigned char* expected_result,
658 mbedtls_cipher_id_t cipher_id,
Brian Murrayb439d452016-05-19 16:02:42 -0700659 int block_size )
Brian Murray00dc5f02016-05-19 14:23:50 -0700660{
661 const int num_tests = 4;
662 mbedtls_cmac_context ctx;
663 int i, ret;
664 unsigned char* tag;
665
666 tag = mbedtls_calloc( block_size, sizeof( unsigned char ) );
667 mbedtls_cmac_init( &ctx );
668
669 if( ( ret = mbedtls_cmac_setkey( &ctx, cipher_id, key, keybits ) ) != 0 )
670 {
671 if( verbose != 0 )
672 mbedtls_printf( " CMAC: setup failed\n" );
673 goto exit;
674 }
675
676 if( ( ret = memcmp( ctx.K1, subkeys, block_size ) != 0 ) ||
677 ( ret = memcmp( ctx.K2, &subkeys[block_size], block_size ) != 0 ) )
678 {
679 if( verbose != 0 )
680 mbedtls_printf( " CMAC: subkey generation failed\n" );
681 goto exit;
682 }
683
684 for( i = 0; i < num_tests; i++ )
685 {
686 if( verbose != 0 )
687 mbedtls_printf( " %s CMAC #%u: ", testname, i +1 );
688
689 if( ( ret = mbedtls_cmac_generate( &ctx, messages, message_lengths[i], tag, block_size ) ) != 0 )
690 {
691 if( verbose != 0 )
692 mbedtls_printf( "failed\n" );
693 goto exit;
694 }
695 if( ( ret = memcmp( tag, &expected_result[i * block_size], block_size ) ) != 0 )
696 {
697 if( verbose != 0 )
698 mbedtls_printf( "failed\n" );
699 goto exit;
700 }
701
702 if( ( ret = mbedtls_cmac_verify( &ctx, messages, message_lengths[i], &expected_result[i * block_size], block_size ) != 0 ) )
703 {
704 if( verbose != 0 )
705 mbedtls_printf( "failed\n" );
706 goto exit;
707 }
708 mbedtls_printf( "passed\n" );
709 }
710 exit:
711 free( tag );
712 mbedtls_cmac_free( &ctx );
713 return( ret );
714}
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000715
Brian Murray0f6af732016-05-19 15:59:23 -0700716#ifdef MBEDTLS_AES_C
717int test_aes128_cmac_prf( verbose ) {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000718 int i;
719 int ret;
Brian Murray0f6af732016-05-19 15:59:23 -0700720 unsigned char tag[16];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700721 for( i = 0; i < NB_PRF_TESTS; i++ )
722 {
Brian Murray0f6af732016-05-19 15:59:23 -0700723 mbedtls_printf( " AES CMAC 128 PRF #%u: ", i );
724 ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, tag );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700725 if( ret != 0 ||
726 memcmp( tag, PRFT[i], 16 ) != 0 )
727 {
728 if( verbose != 0 )
729 mbedtls_printf( "failed\n" );
730
Brian Murray0f6af732016-05-19 15:59:23 -0700731 return( ret );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700732 } else if( verbose != 0 )
733 {
734 mbedtls_printf( "passed\n" );
735 }
736 }
Brian Murray0f6af732016-05-19 15:59:23 -0700737 return( ret );
738}
739#endif /* MBEDTLS_AES_C */
740
741int mbedtls_cmac_self_test( int verbose )
742{
743 int ret;
744
745#ifdef MBEDTLS_AES_C
Brian Murrayb439d452016-05-19 16:02:42 -0700746 test_cmac_with_cipher( verbose,
Brian Murray0f6af732016-05-19 15:59:23 -0700747 "AES 128",
748 aes_128_key,
749 128,
750 test_message,
751 aes_message_lengths,
752 aes_128_subkeys,
753 aes_128_expected_result,
754 MBEDTLS_CIPHER_ID_AES,
755 AES_BLOCK_SIZE );
756
Brian Murrayb439d452016-05-19 16:02:42 -0700757 test_cmac_with_cipher( verbose,
Brian Murray0f6af732016-05-19 15:59:23 -0700758 "AES 192",
759 aes_192_key,
760 192,
761 test_message,
762 aes_message_lengths,
763 aes_192_subkeys,
764 aes_192_expected_result,
765 MBEDTLS_CIPHER_ID_AES,
766 AES_BLOCK_SIZE );
767
Brian Murrayb439d452016-05-19 16:02:42 -0700768 test_cmac_with_cipher ( verbose,
Brian Murray0f6af732016-05-19 15:59:23 -0700769 "AES 256",
770 aes_256_key,
771 256,
772 test_message,
773 aes_message_lengths,
774 aes_256_subkeys,
775 aes_256_expected_result,
776 MBEDTLS_CIPHER_ID_AES,
777 AES_BLOCK_SIZE );
778#endif /* MBEDTLS_AES_C */
779
780#ifdef MBEDTLS_DES_C
Brian Murrayb439d452016-05-19 16:02:42 -0700781 test_cmac_with_cipher( verbose,
Brian Murray0f6af732016-05-19 15:59:23 -0700782 "3DES 2 key",
783 des3_2key_key,
784 192,
785 test_message,
786 des3_message_lengths,
787 des3_2key_subkeys,
788 T_3des_2key,
789 MBEDTLS_CIPHER_ID_3DES,
790 DES3_BLOCK_SIZE );
791
Brian Murrayb439d452016-05-19 16:02:42 -0700792 test_cmac_with_cipher( verbose,
Brian Murray0f6af732016-05-19 15:59:23 -0700793 "3DES 3 key",
794 des3_3key_key,
795 192,
796 test_message,
797 des3_message_lengths,
798 des3_3key_subkeys,
799 T_3des_3key,
800 MBEDTLS_CIPHER_ID_3DES,
801 DES3_BLOCK_SIZE );
802#endif /* MBEDTLS_DES_C */
803
804#ifdef MBEDTLS_AES_C
805 test_aes128_cmac_prf( verbose );
806#endif /* MBEDTLS_AES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700807
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000808 if( verbose != 0 )
809 mbedtls_printf( "\n" );
Brian Murray0f6af732016-05-19 15:59:23 -0700810
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000811 return( 0 );
812}
813
Brian Murray0f6af732016-05-19 15:59:23 -0700814#endif /* MBEDTLS_SELF_TEST */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000815
816#endif /* MBEDTLS_CMAC_C */