blob: d32d1c7e710d95d13956328226ee84a0c2e630e8 [file] [log] [blame]
Robert Cragie3d23b1d2015-12-15 07:38:11 +00001/*
2 * NIST SP800-38B compliant CMAC implementation
3 *
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21
22/*
23 * Definition of CMAC:
24 * http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
25 * RFC 4493 "The AES-CMAC Algorithm"
26 */
27
28#if !defined(MBEDTLS_CONFIG_FILE)
29#include "mbedtls/config.h"
30#else
31#include MBEDTLS_CONFIG_FILE
32#endif
33
34#if defined(MBEDTLS_CMAC_C)
35
36#include "mbedtls/cmac.h"
37
38#include <string.h>
39
40#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
41#if defined(MBEDTLS_PLATFORM_C)
42#include "mbedtls/platform.h"
43#else
44#include <stdio.h>
45#define mbedtls_printf printf
46#endif /* MBEDTLS_PLATFORM_C */
47#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
48
Robert Cragie3d23b1d2015-12-15 07:38:11 +000049/* Implementation that should never be optimized out by the compiler */
50static void mbedtls_zeroize( void *v, size_t n ) {
51 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
52}
53
54/*
55 * Initialize context
56 */
57void mbedtls_cmac_init( mbedtls_cmac_context *ctx )
58{
59 memset( ctx, 0, sizeof( mbedtls_cmac_context ) );
60}
61
62/*
Brian Murrayb0c3c432016-05-18 14:29:51 -070063 * Multiplication by u in the Galois field of GF(2^n)
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000064 *
Brian Murray87e40402016-05-19 19:05:57 -070065 * As explained in the paper, this can be computed:
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000066 * If MSB(p) = 0, then p = (p << 1)
Brian Murrayb0c3c432016-05-18 14:29:51 -070067 * If MSB(p) = 1, then p = (p << 1) ^ R_n
68 * with R_64 = 0x1B and R_128 = 0x87
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000069 *
70 * Input and output MUST not point to the same buffer
Brian Murrayb0c3c432016-05-18 14:29:51 -070071 * Block size must be 8 byes or 16 bytes.
Robert Cragie3d23b1d2015-12-15 07:38:11 +000072 */
Brian Murrayb0c3c432016-05-18 14:29:51 -070073static int cmac_multiply_by_u( unsigned char *output,
74 const unsigned char *input,
Brian Murrayb439d452016-05-19 16:02:42 -070075 size_t blocksize )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000076{
Brian Murrayb0c3c432016-05-18 14:29:51 -070077 const unsigned char R_128 = 0x87;
78 const unsigned char R_64 = 0x1B;
79 unsigned char R_n, mask;
80 unsigned char overflow = 0x00;
81 int i, starting_index;
82
83 starting_index = blocksize -1;
84
Brian Murrayb439d452016-05-19 16:02:42 -070085 if( blocksize == 16 ){
Brian Murrayb0c3c432016-05-18 14:29:51 -070086 R_n = R_128;
Brian Murrayb439d452016-05-19 16:02:42 -070087 } else if( blocksize == 8 ) {
Brian Murrayb0c3c432016-05-18 14:29:51 -070088 R_n = R_64;
89 } else {
Brian Murrayb439d452016-05-19 16:02:42 -070090 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
Brian Murrayb0c3c432016-05-18 14:29:51 -070091 }
92
Brian Murrayb0c3c432016-05-18 14:29:51 -070093 for( i = starting_index; i >= 0; i-- )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000094 {
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000095 output[i] = input[i] << 1 | overflow;
96 overflow = input[i] >> 7;
Robert Cragie3d23b1d2015-12-15 07:38:11 +000097 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +000098
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +000099 /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
100 * using bit operations to avoid branches */
101 /* MSVC has a warning about unary minus on unsigned, but this is
102 * well-defined and precisely what we want to do here */
103#if defined(_MSC_VER)
104#pragma warning( push )
105#pragma warning( disable : 4146 )
106#endif
107 mask = - ( input[0] >> 7 );
108#if defined(_MSC_VER)
109#pragma warning( pop )
110#endif
111
Brian Murrayb0c3c432016-05-18 14:29:51 -0700112 output[starting_index] ^= R_n & mask;
Brian Murrayb439d452016-05-19 16:02:42 -0700113 return( 0 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000114}
115
116/*
117 * Generate subkeys
118 */
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000119static int cmac_generate_subkeys( mbedtls_cmac_context *ctx )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000120{
Brian Murray57863ad2016-05-19 16:38:36 -0700121 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700122 unsigned char *L;
123 size_t olen, block_size;
124
125 ret = 0;
126 block_size = ctx->cipher_ctx.cipher_info->block_size;
127
Brian Murrayb439d452016-05-19 16:02:42 -0700128 L = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Brian Murray4b64ab62016-05-20 06:33:01 -0700129 if( L == NULL )
Brian Murray57863ad2016-05-19 16:38:36 -0700130 {
131 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
132 goto exit;
133 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000134 /* Calculate Ek(0) */
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:
Brian Murray57863ad2016-05-19 16:38:36 -0700150 if( L != NULL )
151 mbedtls_zeroize( L, sizeof( L ) );
Brian Murray4b64ab62016-05-20 06:33:01 -0700152 mbedtls_free( L );
Brian Murrayb439d452016-05-19 16:02:42 -0700153 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000154}
155
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000156/*
157 * Set key and prepare context for use
158 */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000159int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx,
160 mbedtls_cipher_id_t cipher,
161 const unsigned char *key,
162 unsigned int keybits )
163{
Brian Murray57863ad2016-05-19 16:38:36 -0700164 int ret;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000165 const mbedtls_cipher_info_t *cipher_info;
166
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000167 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
168 MBEDTLS_MODE_ECB );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000169 if( cipher_info == NULL )
170 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
171
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000172 mbedtls_cipher_free( &ctx->cipher_ctx );
173
174 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
175 return( ret );
176
177 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000178 MBEDTLS_ENCRYPT ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000179 {
180 return( ret );
181 }
182
Brian Murray2cfa5072016-05-23 20:17:04 -0700183 ctx->K1 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) );
184 ctx->K2 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) );
185
186 if( ctx->K1 == NULL || ctx->K2 == NULL )
187 {
188 mbedtls_free(ctx->K1);
189 mbedtls_free(ctx->K2);
190 return( MBEDTLS_ERR_CMAC_ALLOC_FAILED );
191 }
192
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000193 return( cmac_generate_subkeys( ctx ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000194}
195
196/*
197 * Free context
198 */
199void mbedtls_cmac_free( mbedtls_cmac_context *ctx )
200{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700201 int block_size;
202 block_size = ctx->cipher_ctx.cipher_info->block_size;
203
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000204 mbedtls_cipher_free( &ctx->cipher_ctx );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700205
Brian Murrayb439d452016-05-19 16:02:42 -0700206 mbedtls_zeroize( ctx->K1, block_size * sizeof( unsigned char ) );
207 mbedtls_zeroize( ctx->K2, block_size * sizeof( unsigned char ) );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700208 mbedtls_free( ctx->K1 );
209 mbedtls_free( ctx->K2 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000210}
211
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000212/*
213 * Create padded last block from (partial) last block.
214 *
215 * We can't use the padding option from the cipher layer, as it only works for
216 * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
217 */
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000218static void cmac_pad( unsigned char padded_block[16],
Brian Murrayb0c3c432016-05-18 14:29:51 -0700219 size_t padded_block_len,
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000220 const unsigned char *last_block,
Brian Murrayb0c3c432016-05-18 14:29:51 -0700221 size_t last_block_len )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000222{
223 size_t j;
224
Brian Murrayb0c3c432016-05-18 14:29:51 -0700225 for( j = 0; j < padded_block_len; j++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000226 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700227 if( j < last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000228 padded_block[j] = last_block[j];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700229 else if( j == last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000230 padded_block[j] = 0x80;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000231 else
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000232 padded_block[j] = 0x00;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000233 }
234}
235
236/*
Brian Murrayb0c3c432016-05-18 14:29:51 -0700237 * XOR Block
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000238 * Here, macro results in smaller compiled code than static inline function
239 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700240#define XOR_BLOCK( o, i1, i2 ) \
241 for( i = 0; i < block_size; i++ ) \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000242 ( o )[i] = ( i1 )[i] ^ ( i2 )[i];
243
244/*
Brian Murray87e40402016-05-19 19:05:57 -0700245 * Update the CMAC state using an input block
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000246 */
247#define UPDATE_CMAC( x ) \
248do { \
Brian Murrayb0c3c432016-05-18 14:29:51 -0700249 XOR_BLOCK( state, ( x ), state ); \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000250 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \
Brian Murrayb0c3c432016-05-18 14:29:51 -0700251 state, block_size, \
252 state, &olen ) ) != 0 ) \
Brian Murray57863ad2016-05-19 16:38:36 -0700253 { \
254 goto exit; \
255 } \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000256} while( 0 )
257
258/*
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000259 * Generate tag on complete message
260 */
Manuel Pégourié-Gonnardab9c5fd2016-01-13 15:05:57 +0000261int mbedtls_cmac_generate( mbedtls_cmac_context *ctx,
262 const unsigned char *input, size_t in_len,
263 unsigned char *tag, size_t tag_len )
264
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000265{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700266 unsigned char *state;
267 unsigned char *M_last;
Brian Murray57863ad2016-05-19 16:38:36 -0700268 int n, j, ret, needs_padding;
269 size_t olen, block_size, i;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700270
Brian Murrayb0c3c432016-05-18 14:29:51 -0700271 ret = 0;
272 block_size = ctx->cipher_ctx.cipher_info->block_size;
273
Brian Murrayb439d452016-05-19 16:02:42 -0700274 state = mbedtls_calloc( block_size, sizeof( unsigned char ) );
275 M_last = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000276
Brian Murray57863ad2016-05-19 16:38:36 -0700277 if( state == NULL || M_last == NULL )
278 {
279 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
280 goto exit;
281 }
282
Brian Murray87e40402016-05-19 19:05:57 -0700283 if( tag_len < 2 || tag_len > block_size || tag_len % 2 != 0 )
Brian Murray57863ad2016-05-19 16:38:36 -0700284 {
285 ret = MBEDTLS_ERR_CMAC_BAD_INPUT;
286 goto exit;
287 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000288
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000289 if( in_len == 0 )
290 needs_padding = 1;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000291 else
Brian Murrayb0c3c432016-05-18 14:29:51 -0700292 needs_padding = in_len % block_size != 0;
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000293
Brian Murrayb0c3c432016-05-18 14:29:51 -0700294 n = in_len / block_size + needs_padding;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000295
296 /* Calculate last block */
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000297 if( needs_padding )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000298 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700299 cmac_pad( M_last, block_size, input + block_size * ( n - 1 ), in_len % block_size );
300 XOR_BLOCK( M_last, M_last, ctx->K2 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000301 }
302 else
303 {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000304 /* Last block is complete block */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700305 XOR_BLOCK( M_last, input + block_size * ( n - 1 ), ctx->K1 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000306 }
307
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000308 for( j = 0; j < n - 1; j++ )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700309 UPDATE_CMAC( input + block_size * j );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000310
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000311 UPDATE_CMAC( M_last );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000312
Brian Murray00dc5f02016-05-19 14:23:50 -0700313 memcpy( tag, state, tag_len );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000314
Brian Murrayb0c3c432016-05-18 14:29:51 -0700315 exit:
Brian Murray4b64ab62016-05-20 06:33:01 -0700316 mbedtls_free( state );
317 mbedtls_free( M_last );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700318 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000319}
320
Brian Murrayb0c3c432016-05-18 14:29:51 -0700321#undef XOR_BLOCK
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000322#undef UPDATE_CMAC
323
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000324/*
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000325 * Verify tag on complete message
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000326 */
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000327int mbedtls_cmac_verify( mbedtls_cmac_context *ctx,
328 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000329 const unsigned char *tag, size_t tag_len )
330{
331 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700332 unsigned char *check_tag;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000333 unsigned char i;
334 int diff;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000335
Brian Murrayb439d452016-05-19 16:02:42 -0700336 check_tag = mbedtls_calloc( ctx->cipher_ctx.cipher_info->block_size,
337 sizeof( unsigned char ) );
Brian Murray4b64ab62016-05-20 06:33:01 -0700338 if( check_tag == NULL )
Brian Murray57863ad2016-05-19 16:38:36 -0700339 {
340 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
341 goto exit;
342 }
Brian Murrayb0c3c432016-05-18 14:29:51 -0700343
Manuel Pégourié-Gonnardab9c5fd2016-01-13 15:05:57 +0000344 if( ( ret = mbedtls_cmac_generate( ctx, input, in_len,
345 check_tag, tag_len ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000346 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700347 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000348 }
349
350 /* Check tag in "constant-time" */
351 for( diff = 0, i = 0; i < tag_len; i++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000352 diff |= tag[i] ^ check_tag[i];
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000353
354 if( diff != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700355 ret = MBEDTLS_ERR_CMAC_VERIFY_FAILED;
356 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000357
Brian Murrayb0c3c432016-05-18 14:29:51 -0700358 exit:
Brian Murray4b64ab62016-05-20 06:33:01 -0700359 mbedtls_free( check_tag );
Brian Murrayb439d452016-05-19 16:02:42 -0700360 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000361}
362
Brian Murrayb439d452016-05-19 16:02:42 -0700363#ifdef MBEDTLS_AES_C
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000364/*
365 * PRF based on CMAC with AES-128
Brian Murrayb0c3c432016-05-18 14:29:51 -0700366 * See RFC 4615
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000367 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700368int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000369 const unsigned char *input, size_t in_len,
Brian Murrayb439d452016-05-19 16:02:42 -0700370 unsigned char tag[16] )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000371{
372 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700373 mbedtls_cmac_context ctx;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000374 unsigned char zero_key[16];
375 unsigned char int_key[16];
376
Brian Murrayb439d452016-05-19 16:02:42 -0700377 mbedtls_cmac_init(&ctx );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700378
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000379 if( key_length == 16 )
380 {
381 /* Use key as is */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000382 memcpy( int_key, key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000383 }
384 else
385 {
386 mbedtls_cmac_context zero_ctx;
387
Brian Murrayb439d452016-05-19 16:02:42 -0700388 /* Key is AES_CMAC( 0, key ) */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000389 mbedtls_cmac_init( &zero_ctx );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000390 memset( zero_key, 0, 16 );
391 ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES,
392 zero_key, 8 * sizeof zero_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000393 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700394 goto exit;
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000395
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000396 ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000397 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700398 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000399 }
400
Brian Murrayb0c3c432016-05-18 14:29:51 -0700401 ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000402 int_key, 8 * sizeof int_key );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000403 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700404 goto exit;
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000405
406 mbedtls_zeroize( int_key, sizeof( int_key ) );
407
Brian Murrayb0c3c432016-05-18 14:29:51 -0700408 ret = mbedtls_cmac_generate( &ctx, input, in_len, tag, 16 );
409
410 exit:
Brian Murrayb439d452016-05-19 16:02:42 -0700411 mbedtls_cmac_free( &ctx );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700412 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000413}
Brian Murrayb439d452016-05-19 16:02:42 -0700414#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000415
Brian Murray0f6af732016-05-19 15:59:23 -0700416#ifdef MBEDTLS_SELF_TEST
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000417/*
Brian Murray0f6af732016-05-19 15:59:23 -0700418 * CMAC test data from SP800-38B Appendix D.1 (corrected)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000419 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
Brian Murray0f6af732016-05-19 15:59:23 -0700420 *
421 * AES-CMAC-PRF-128 test data from RFC 4615
422 * https://tools.ietf.org/html/rfc4615#page-4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000423 */
424
Brian Murray0f6af732016-05-19 15:59:23 -0700425#define NB_CMAC_TESTS_PER_KEY 4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000426#define NB_PRF_TESTS 3
Brian Murray0f6af732016-05-19 15:59:23 -0700427#define AES_BLOCK_SIZE 16
428#define DES3_BLOCK_SIZE 8
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000429
Brian Murray0f6af732016-05-19 15:59:23 -0700430#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
431/* All CMAC test inputs are truncated from the same 64 byte buffer. */
432static const unsigned char test_message[] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000433 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
434 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
435 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
436 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
437 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
438 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
439 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
440 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
441};
Brian Murray0f6af732016-05-19 15:59:23 -0700442#endif /* defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000443
Brian Murray0f6af732016-05-19 15:59:23 -0700444#ifdef MBEDTLS_AES_C
445/* Truncation point of message for AES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700446static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700447 0,
448 16,
449 40,
450 64
451};
452
453/* AES 128 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700454static const unsigned char aes_128_key[16] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700455 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
456 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
457};
458static const unsigned char aes_128_subkeys[2][AES_BLOCK_SIZE] = {
459 {
460 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
461 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
462 },
463 {
464 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
465 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
466 }
467};
468static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000469 {
470 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
471 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
472 },
473 {
474 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
475 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
476 },
477 {
478 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
479 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
480 },
481 {
482 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
483 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
484 }
485};
486
Brian Murray0f6af732016-05-19 15:59:23 -0700487/* AES 192 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700488static const unsigned char aes_192_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700489 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
490 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
491 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000492};
Brian Murray0f6af732016-05-19 15:59:23 -0700493static const unsigned char aes_192_subkeys[2][AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700494 {
Brian Murray0f6af732016-05-19 15:59:23 -0700495 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
496 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
Brian Murrayb0c3c432016-05-18 14:29:51 -0700497 },
498 {
Brian Murray0f6af732016-05-19 15:59:23 -0700499 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
500 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
Brian Murrayb0c3c432016-05-18 14:29:51 -0700501 }
502};
Brian Murray0f6af732016-05-19 15:59:23 -0700503static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700504 {
505 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
506 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
507 },
508 {
509 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
510 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
511 },
512 {
513 0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad,
514 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e
515 },
516 {
517 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
518 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
519 }
520};
521
Brian Murray0f6af732016-05-19 15:59:23 -0700522/* AES 256 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700523static const unsigned char aes_256_key[32] = {
Brian Murray87e40402016-05-19 19:05:57 -0700524 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
525 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
526 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
527 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
Brian Murray0f6af732016-05-19 15:59:23 -0700528};
529static const unsigned char aes_256_subkeys[2][AES_BLOCK_SIZE] = {
530 {
531 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
532 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
533 },
534 {
535 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
536 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
537 }
538};
539static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
540 {
541 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
542 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
543 },
544 {
545 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
546 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
547 },
548 {
549 0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2,
550 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6
551 },
552 {
553 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
554 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
555 }
556};
557#endif /* MBEDTLS_AES_C */
558
559#ifdef MBEDTLS_DES_C
560/* Truncation point of message for 3DES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700561static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700562 0,
563 8,
564 20,
565 32
566};
567
568/* 3DES 2 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700569static const unsigned char des3_2key_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700570 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5,
571 0x8a, 0x3d, 0x10, 0xba, 0x80, 0x57, 0x0d, 0x38,
572 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5
Brian Murray0f6af732016-05-19 15:59:23 -0700573};
574static const unsigned char des3_2key_subkeys[2][8] = {
575 {
576 0x8e, 0xcf, 0x37, 0x3e, 0xd7, 0x1a, 0xfa, 0xef
577 },
578 {
579 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5
580 }
581};
Brian Murray57863ad2016-05-19 16:38:36 -0700582static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700583 {
584 0xbd, 0x2e, 0xbf, 0x9a, 0x3b, 0xa0, 0x03, 0x61
585 },
586 {
587 0x4f, 0xf2, 0xab, 0x81, 0x3c, 0x53, 0xce, 0x83
588 },
589 {
590 0x62, 0xdd, 0x1b, 0x47, 0x19, 0x02, 0xbd, 0x4e
591 },
592 {
593 0x31, 0xb1, 0xe4, 0x31, 0xda, 0xbc, 0x4e, 0xb8
594 }
595};
596
Brian Murray0f6af732016-05-19 15:59:23 -0700597/* 3DES 3 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700598static const unsigned char des3_3key_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700599 0x8a, 0xa8, 0x3b, 0xf8, 0xcb, 0xda, 0x10, 0x62,
600 0x0b, 0xc1, 0xbf, 0x19, 0xfb, 0xb6, 0xcd, 0x58,
601 0xbc, 0x31, 0x3d, 0x4a, 0x37, 0x1c, 0xa8, 0xb5
Brian Murray0f6af732016-05-19 15:59:23 -0700602};
603static const unsigned char des3_3key_subkeys[2][8] = {
604 {
605 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f
606 },
607 {
608 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5
609 }
610};
Brian Murray57863ad2016-05-19 16:38:36 -0700611static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700612 {
613 0xb7, 0xa6, 0x88, 0xe1, 0x22, 0xff, 0xaf, 0x95
614 },
615 {
616 0x8e, 0x8f, 0x29, 0x31, 0x36, 0x28, 0x37, 0x97
617 },
618 {
619 0x74, 0x3d, 0xdb, 0xe0, 0xce, 0x2d, 0xc2, 0xed
620 },
621 {
622 0x33, 0xe6, 0xb1, 0x09, 0x24, 0x00, 0xea, 0xe5
623 }
624};
625
Brian Murray0f6af732016-05-19 15:59:23 -0700626#endif /* MBEDTLS_DES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700627
Brian Murray0f6af732016-05-19 15:59:23 -0700628#ifdef MBEDTLS_AES_C
629/* AES AES-CMAC-PRF-128 Test Data */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000630static const unsigned char PRFK[] = {
631 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
632 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
633 0xed, 0xcb
634};
635
636/* Sizes in bytes */
637static const size_t PRFKlen[NB_PRF_TESTS] = {
638 18,
639 16,
640 10
641};
642
643/* PRF M */
644static const unsigned char PRFM[] = {
645 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
646 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000647 0x10, 0x11, 0x12, 0x13
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000648};
649
650static const unsigned char PRFT[NB_PRF_TESTS][16] = {
651 {
652 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
653 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
654 },
655 {
656 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
657 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
658 },
659 {
660 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
661 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
662 }
663};
Brian Murray0f6af732016-05-19 15:59:23 -0700664#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000665
Brian Murrayb439d452016-05-19 16:02:42 -0700666int test_cmac_with_cipher( int verbose,
Brian Murray87e40402016-05-19 19:05:57 -0700667 char* testname,
668 const unsigned char* key,
669 int keybits,
670 const unsigned char* messages,
671 const unsigned int message_lengths[4],
672 const unsigned char* subkeys,
673 const unsigned char* expected_result,
674 mbedtls_cipher_id_t cipher_id,
675 int block_size )
Brian Murray00dc5f02016-05-19 14:23:50 -0700676{
Brian Murray87e40402016-05-19 19:05:57 -0700677 const int num_tests = 4;
678 mbedtls_cmac_context ctx;
Brian Murray00dc5f02016-05-19 14:23:50 -0700679 int i, ret;
680 unsigned char* tag;
681
682 tag = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Brian Murray57863ad2016-05-19 16:38:36 -0700683 if( tag == NULL ){
684 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
685 goto exit;
686 }
687
Brian Murray00dc5f02016-05-19 14:23:50 -0700688 mbedtls_cmac_init( &ctx );
689
690 if( ( ret = mbedtls_cmac_setkey( &ctx, cipher_id, key, keybits ) ) != 0 )
691 {
692 if( verbose != 0 )
693 mbedtls_printf( " CMAC: setup failed\n" );
694 goto exit;
695 }
696
697 if( ( ret = memcmp( ctx.K1, subkeys, block_size ) != 0 ) ||
698 ( ret = memcmp( ctx.K2, &subkeys[block_size], block_size ) != 0 ) )
699 {
700 if( verbose != 0 )
701 mbedtls_printf( " CMAC: subkey generation failed\n" );
702 goto exit;
703 }
704
705 for( i = 0; i < num_tests; i++ )
706 {
707 if( verbose != 0 )
708 mbedtls_printf( " %s CMAC #%u: ", testname, i +1 );
709
710 if( ( ret = mbedtls_cmac_generate( &ctx, messages, message_lengths[i], tag, block_size ) ) != 0 )
711 {
712 if( verbose != 0 )
713 mbedtls_printf( "failed\n" );
714 goto exit;
715 }
716 if( ( ret = memcmp( tag, &expected_result[i * block_size], block_size ) ) != 0 )
717 {
718 if( verbose != 0 )
719 mbedtls_printf( "failed\n" );
720 goto exit;
721 }
722
723 if( ( ret = mbedtls_cmac_verify( &ctx, messages, message_lengths[i], &expected_result[i * block_size], block_size ) != 0 ) )
724 {
Brian Murray4b64ab62016-05-20 06:33:01 -0700725 if( verbose != 0 )
726 mbedtls_printf( "failed\n" );
727 goto exit;
Brian Murray00dc5f02016-05-19 14:23:50 -0700728 }
729 mbedtls_printf( "passed\n" );
730 }
731 exit:
Brian Murray4b64ab62016-05-20 06:33:01 -0700732 mbedtls_free( tag );
Brian Murray00dc5f02016-05-19 14:23:50 -0700733 mbedtls_cmac_free( &ctx );
734 return( ret );
735}
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000736
Brian Murray0f6af732016-05-19 15:59:23 -0700737#ifdef MBEDTLS_AES_C
Brian Murray57863ad2016-05-19 16:38:36 -0700738int test_aes128_cmac_prf( int verbose ) {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000739 int i;
740 int ret;
Brian Murray0f6af732016-05-19 15:59:23 -0700741 unsigned char tag[16];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700742 for( i = 0; i < NB_PRF_TESTS; i++ )
743 {
Brian Murray0f6af732016-05-19 15:59:23 -0700744 mbedtls_printf( " AES CMAC 128 PRF #%u: ", i );
745 ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, tag );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700746 if( ret != 0 ||
747 memcmp( tag, PRFT[i], 16 ) != 0 )
748 {
749 if( verbose != 0 )
750 mbedtls_printf( "failed\n" );
751
Brian Murray0f6af732016-05-19 15:59:23 -0700752 return( ret );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700753 } else if( verbose != 0 )
754 {
755 mbedtls_printf( "passed\n" );
756 }
757 }
Brian Murray0f6af732016-05-19 15:59:23 -0700758 return( ret );
759}
760#endif /* MBEDTLS_AES_C */
761
762int mbedtls_cmac_self_test( int verbose )
763{
764 int ret;
765
766#ifdef MBEDTLS_AES_C
Brian Murray9044b022016-05-19 16:36:56 -0700767 if( ( ret = test_cmac_with_cipher( verbose,
768 "AES 128",
769 aes_128_key,
770 128,
771 test_message,
772 aes_message_lengths,
Brian Murray57863ad2016-05-19 16:38:36 -0700773 (const unsigned char*) aes_128_subkeys,
774 (const unsigned char*) aes_128_expected_result,
Brian Murray9044b022016-05-19 16:36:56 -0700775 MBEDTLS_CIPHER_ID_AES,
776 AES_BLOCK_SIZE ) !=0 ) )
777 {
778 return( ret );
779 }
Brian Murray0f6af732016-05-19 15:59:23 -0700780
Brian Murray9044b022016-05-19 16:36:56 -0700781 if( ( ret = test_cmac_with_cipher( verbose,
Brian Murray57863ad2016-05-19 16:38:36 -0700782 "AES 192",
783 aes_192_key,
784 192,
785 test_message,
786 aes_message_lengths,
787 (const unsigned char*) aes_192_subkeys,
788 (const unsigned char*) aes_192_expected_result,
789 MBEDTLS_CIPHER_ID_AES,
790 AES_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700791 {
792 return( ret );
793 }
Brian Murray0f6af732016-05-19 15:59:23 -0700794
Brian Murray9044b022016-05-19 16:36:56 -0700795 if( ( ret = test_cmac_with_cipher ( verbose,
Brian Murray57863ad2016-05-19 16:38:36 -0700796 "AES 256",
797 aes_256_key,
798 256,
799 test_message,
800 aes_message_lengths,
801 (const unsigned char*) aes_256_subkeys,
802 (const unsigned char*) aes_256_expected_result,
803 MBEDTLS_CIPHER_ID_AES,
804 AES_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700805 {
806 return( ret );
807 }
Brian Murray0f6af732016-05-19 15:59:23 -0700808#endif /* MBEDTLS_AES_C */
809
810#ifdef MBEDTLS_DES_C
Brian Murray9044b022016-05-19 16:36:56 -0700811 if( ( ret = test_cmac_with_cipher( verbose,
Brian Murray57863ad2016-05-19 16:38:36 -0700812 "3DES 2 key",
813 des3_2key_key,
814 192,
815 test_message,
816 des3_message_lengths,
817 (const unsigned char*) des3_2key_subkeys,
818 (const unsigned char*) des3_2key_expected_result,
819 MBEDTLS_CIPHER_ID_3DES,
820 DES3_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700821 {
822 return( ret );
823 }
Brian Murray0f6af732016-05-19 15:59:23 -0700824
Brian Murray9044b022016-05-19 16:36:56 -0700825 if( ( ret = test_cmac_with_cipher( verbose,
Brian Murray57863ad2016-05-19 16:38:36 -0700826 "3DES 3 key",
827 des3_3key_key,
828 192,
829 test_message,
830 des3_message_lengths,
831 (const unsigned char*) des3_3key_subkeys,
832 (const unsigned char*) des3_3key_expected_result,
833 MBEDTLS_CIPHER_ID_3DES,
834 DES3_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700835 {
836 return( ret );
837 }
Brian Murray0f6af732016-05-19 15:59:23 -0700838#endif /* MBEDTLS_DES_C */
839
840#ifdef MBEDTLS_AES_C
Brian Murray9044b022016-05-19 16:36:56 -0700841 if( ( ret = test_aes128_cmac_prf( verbose ) != 0 ) )
842 return( ret );
843
Brian Murray0f6af732016-05-19 15:59:23 -0700844#endif /* MBEDTLS_AES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700845
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000846 if( verbose != 0 )
847 mbedtls_printf( "\n" );
Brian Murray0f6af732016-05-19 15:59:23 -0700848
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000849 return( 0 );
850}
851
Brian Murray0f6af732016-05-19 15:59:23 -0700852#endif /* MBEDTLS_SELF_TEST */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000853
854#endif /* MBEDTLS_CMAC_C */