blob: f86e4c5aaa202ffc97f99deba291f6589b826d0b [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
Brian Murray8b4111c2016-09-13 15:58:46 -070042
Robert Cragie3d23b1d2015-12-15 07:38:11 +000043#if defined(MBEDTLS_PLATFORM_C)
44#include "mbedtls/platform.h"
45#else
Brian Murray8b4111c2016-09-13 15:58:46 -070046#include <stdlib.h>
47#define mbedtls_calloc calloc
48#define mbedtls_free free
49#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000050#include <stdio.h>
Brian Murray8b4111c2016-09-13 15:58:46 -070051#define mbedtls_printf printf
52#endif /* defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) )*/
Robert Cragie3d23b1d2015-12-15 07:38:11 +000053#endif /* MBEDTLS_PLATFORM_C */
Brian Murray8b4111c2016-09-13 15:58:46 -070054
Robert Cragie3d23b1d2015-12-15 07:38:11 +000055
Robert Cragie3d23b1d2015-12-15 07:38:11 +000056/* Implementation that should never be optimized out by the compiler */
57static void mbedtls_zeroize( void *v, size_t n ) {
58 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
59}
60
61/*
62 * Initialize context
63 */
64void mbedtls_cmac_init( mbedtls_cmac_context *ctx )
65{
66 memset( ctx, 0, sizeof( mbedtls_cmac_context ) );
67}
68
69/*
Brian Murrayb0c3c432016-05-18 14:29:51 -070070 * Multiplication by u in the Galois field of GF(2^n)
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000071 *
Brian Murray72b69e32016-09-13 14:21:01 -070072 * As explained in NIST SP 800-38B, this can be computed:
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000073 * If MSB(p) = 0, then p = (p << 1)
Brian Murrayb0c3c432016-05-18 14:29:51 -070074 * If MSB(p) = 1, then p = (p << 1) ^ R_n
75 * with R_64 = 0x1B and R_128 = 0x87
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +000076 *
77 * Input and output MUST not point to the same buffer
Brian Murrayb0c3c432016-05-18 14:29:51 -070078 * Block size must be 8 byes or 16 bytes.
Robert Cragie3d23b1d2015-12-15 07:38:11 +000079 */
Brian Murrayb0c3c432016-05-18 14:29:51 -070080static int cmac_multiply_by_u( unsigned char *output,
81 const unsigned char *input,
Brian Murray53e23b62016-09-13 14:00:15 -070082 size_t blocksize )
Robert Cragie3d23b1d2015-12-15 07:38:11 +000083{
Brian Murrayb0c3c432016-05-18 14:29:51 -070084 const unsigned char R_128 = 0x87;
85 const unsigned char R_64 = 0x1B;
86 unsigned char R_n, mask;
87 unsigned char overflow = 0x00;
88 int i, starting_index;
89
90 starting_index = blocksize -1;
91
Brian Murray6a3c0d22016-05-20 18:25:43 -070092 if( blocksize == 16 )
93 {
Brian Murrayb0c3c432016-05-18 14:29:51 -070094 R_n = R_128;
Brian Murray6a3c0d22016-05-20 18:25:43 -070095 } else if( blocksize == 8 )
96 {
Brian Murrayb0c3c432016-05-18 14:29:51 -070097 R_n = R_64;
Brian Murray6a3c0d22016-05-20 18:25:43 -070098 } else
99 {
Brian Murrayb439d452016-05-19 16:02:42 -0700100 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700101 }
102
Brian Murrayb0c3c432016-05-18 14:29:51 -0700103 for( i = starting_index; i >= 0; i-- )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000104 {
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000105 output[i] = input[i] << 1 | overflow;
106 overflow = input[i] >> 7;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000107 }
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000108
Manuel Pégourié-Gonnard475f06f2016-01-13 13:05:03 +0000109 /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
110 * using bit operations to avoid branches */
111 /* MSVC has a warning about unary minus on unsigned, but this is
112 * well-defined and precisely what we want to do here */
113#if defined(_MSC_VER)
114#pragma warning( push )
115#pragma warning( disable : 4146 )
116#endif
117 mask = - ( input[0] >> 7 );
118#if defined(_MSC_VER)
119#pragma warning( pop )
120#endif
121
Brian Murrayb0c3c432016-05-18 14:29:51 -0700122 output[starting_index] ^= R_n & mask;
Brian Murrayb439d452016-05-19 16:02:42 -0700123 return( 0 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000124}
125
126/*
127 * Generate subkeys
128 */
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000129static int cmac_generate_subkeys( mbedtls_cmac_context *ctx )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000130{
Brian Murray57863ad2016-05-19 16:38:36 -0700131 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700132 unsigned char *L;
133 size_t olen, block_size;
134
Brian Murrayb0c3c432016-05-18 14:29:51 -0700135 block_size = ctx->cipher_ctx.cipher_info->block_size;
136
Brian Murrayb439d452016-05-19 16:02:42 -0700137 L = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Brian Murray4b64ab62016-05-20 06:33:01 -0700138 if( L == NULL )
Brian Murray57863ad2016-05-19 16:38:36 -0700139 {
140 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
141 goto exit;
142 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000143 /* Calculate Ek(0) */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000144 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx,
Brian Murrayb0c3c432016-05-18 14:29:51 -0700145 L, block_size, L, &olen ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000146 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700147 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000148 }
149
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000150 /*
Manuel Pégourié-Gonnarda610b4c2016-01-13 11:28:16 +0000151 * Generate K1 and K2
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000152 */
Brian Murrayb439d452016-05-19 16:02:42 -0700153 if( ( ret = cmac_multiply_by_u( ctx->K1, L , block_size ) ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700154 goto exit;
Brian Murray6a3c0d22016-05-20 18:25:43 -0700155 if( ( ret = cmac_multiply_by_u( ctx->K2, ctx->K1 , block_size ) ) != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700156 goto exit;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000157
Brian Murrayb0c3c432016-05-18 14:29:51 -0700158 exit:
Brian Murray57863ad2016-05-19 16:38:36 -0700159 if( L != NULL )
160 mbedtls_zeroize( L, sizeof( L ) );
Brian Murray53e23b62016-09-13 14:00:15 -0700161 mbedtls_free( L );
Brian Murrayb439d452016-05-19 16:02:42 -0700162 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000163}
164
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000165/*
166 * Set key and prepare context for use
167 */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000168int mbedtls_cmac_setkey( mbedtls_cmac_context *ctx,
169 mbedtls_cipher_id_t cipher,
170 const unsigned char *key,
171 unsigned int keybits )
172{
Brian Murray57863ad2016-05-19 16:38:36 -0700173 int ret;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000174 const mbedtls_cipher_info_t *cipher_info;
175
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000176 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
177 MBEDTLS_MODE_ECB );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000178 if( cipher_info == NULL )
179 return( MBEDTLS_ERR_CMAC_BAD_INPUT );
180
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000181 mbedtls_cipher_free( &ctx->cipher_ctx );
182
183 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
184 return( ret );
185
186 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000187 MBEDTLS_ENCRYPT ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000188 {
189 return( ret );
190 }
191
Brian Murray2cfa5072016-05-23 20:17:04 -0700192 ctx->K1 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) );
193 ctx->K2 = mbedtls_calloc( cipher_info->block_size, sizeof( unsigned char ) );
194
195 if( ctx->K1 == NULL || ctx->K2 == NULL )
196 {
197 mbedtls_free(ctx->K1);
198 mbedtls_free(ctx->K2);
199 return( MBEDTLS_ERR_CMAC_ALLOC_FAILED );
200 }
201
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000202 return( cmac_generate_subkeys( ctx ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000203}
204
205/*
206 * Free context
207 */
208void mbedtls_cmac_free( mbedtls_cmac_context *ctx )
209{
Brian Murray53e23b62016-09-13 14:00:15 -0700210 int block_size;
211 block_size = ctx->cipher_ctx.cipher_info->block_size;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000212 mbedtls_cipher_free( &ctx->cipher_ctx );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700213
Brian Murray6a3c0d22016-05-20 18:25:43 -0700214 if( ctx->K1 != NULL )
215 mbedtls_zeroize( ctx->K1, block_size * sizeof( unsigned char ) );
216 if( ctx->K2 != NULL )
217 mbedtls_zeroize( ctx->K2, block_size * sizeof( unsigned char ) );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700218 mbedtls_free( ctx->K1 );
219 mbedtls_free( ctx->K2 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000220}
221
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000222/*
223 * Create padded last block from (partial) last block.
224 *
225 * We can't use the padding option from the cipher layer, as it only works for
226 * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
227 */
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000228static void cmac_pad( unsigned char padded_block[16],
Brian Murray53e23b62016-09-13 14:00:15 -0700229 size_t padded_block_len,
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000230 const unsigned char *last_block,
Brian Murrayb0c3c432016-05-18 14:29:51 -0700231 size_t last_block_len )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000232{
233 size_t j;
234
Brian Murrayb0c3c432016-05-18 14:29:51 -0700235 for( j = 0; j < padded_block_len; j++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000236 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700237 if( j < last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000238 padded_block[j] = last_block[j];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700239 else if( j == last_block_len )
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000240 padded_block[j] = 0x80;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000241 else
Manuel Pégourié-Gonnardd2c3d3e2016-01-13 13:14:04 +0000242 padded_block[j] = 0x00;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000243 }
244}
245
246/*
Brian Murrayb0c3c432016-05-18 14:29:51 -0700247 * XOR Block
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000248 * Here, macro results in smaller compiled code than static inline function
249 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700250#define XOR_BLOCK( o, i1, i2 ) \
251 for( i = 0; i < block_size; i++ ) \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000252 ( o )[i] = ( i1 )[i] ^ ( i2 )[i];
253
254/*
Brian Murray87e40402016-05-19 19:05:57 -0700255 * Update the CMAC state using an input block
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000256 */
257#define UPDATE_CMAC( x ) \
258do { \
Brian Murrayb0c3c432016-05-18 14:29:51 -0700259 XOR_BLOCK( state, ( x ), state ); \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000260 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, \
Brian Murrayb0c3c432016-05-18 14:29:51 -0700261 state, block_size, \
262 state, &olen ) ) != 0 ) \
Brian Murray57863ad2016-05-19 16:38:36 -0700263 { \
264 goto exit; \
265 } \
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000266} while( 0 )
267
268/*
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000269 * Generate tag on complete message
270 */
Manuel Pégourié-Gonnardab9c5fd2016-01-13 15:05:57 +0000271int mbedtls_cmac_generate( mbedtls_cmac_context *ctx,
272 const unsigned char *input, size_t in_len,
273 unsigned char *tag, size_t tag_len )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000274{
Brian Murrayb0c3c432016-05-18 14:29:51 -0700275 unsigned char *state;
276 unsigned char *M_last;
Brian Murray57863ad2016-05-19 16:38:36 -0700277 int n, j, ret, needs_padding;
278 size_t olen, block_size, i;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700279
Brian Murrayb0c3c432016-05-18 14:29:51 -0700280 ret = 0;
281 block_size = ctx->cipher_ctx.cipher_info->block_size;
282
Brian Murrayb439d452016-05-19 16:02:42 -0700283 state = mbedtls_calloc( block_size, sizeof( unsigned char ) );
284 M_last = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000285
Brian Murray57863ad2016-05-19 16:38:36 -0700286 if( state == NULL || M_last == NULL )
287 {
288 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
289 goto exit;
290 }
291
Brian Murray87e40402016-05-19 19:05:57 -0700292 if( tag_len < 2 || tag_len > block_size || tag_len % 2 != 0 )
Brian Murray57863ad2016-05-19 16:38:36 -0700293 {
294 ret = MBEDTLS_ERR_CMAC_BAD_INPUT;
295 goto exit;
296 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000297
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000298 if( in_len == 0 )
299 needs_padding = 1;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000300 else
Brian Murrayb0c3c432016-05-18 14:29:51 -0700301 needs_padding = in_len % block_size != 0;
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000302
Brian Murrayb0c3c432016-05-18 14:29:51 -0700303 n = in_len / block_size + needs_padding;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000304
305 /* Calculate last block */
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000306 if( needs_padding )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000307 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700308 cmac_pad( M_last, block_size, input + block_size * ( n - 1 ), in_len % block_size );
309 XOR_BLOCK( M_last, M_last, ctx->K2 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000310 }
311 else
312 {
Manuel Pégourié-Gonnard2c063062016-01-13 14:27:55 +0000313 /* Last block is complete block */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700314 XOR_BLOCK( M_last, input + block_size * ( n - 1 ), ctx->K1 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000315 }
316
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000317 for( j = 0; j < n - 1; j++ )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700318 UPDATE_CMAC( input + block_size * j );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000319
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000320 UPDATE_CMAC( M_last );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000321
Brian Murray00dc5f02016-05-19 14:23:50 -0700322 memcpy( tag, state, tag_len );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000323
Brian Murrayb0c3c432016-05-18 14:29:51 -0700324 exit:
Brian Murray4b64ab62016-05-20 06:33:01 -0700325 mbedtls_free( state );
326 mbedtls_free( M_last );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700327 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000328}
329
Brian Murrayb0c3c432016-05-18 14:29:51 -0700330#undef XOR_BLOCK
Manuel Pégourié-Gonnardd18c7072016-01-13 15:03:05 +0000331#undef UPDATE_CMAC
332
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000333/*
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000334 * Verify tag on complete message
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000335 */
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000336int mbedtls_cmac_verify( mbedtls_cmac_context *ctx,
337 const unsigned char *input, size_t in_len,
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000338 const unsigned char *tag, size_t tag_len )
339{
340 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700341 unsigned char *check_tag;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000342 unsigned char i;
343 int diff;
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000344
Brian Murrayb439d452016-05-19 16:02:42 -0700345 check_tag = mbedtls_calloc( ctx->cipher_ctx.cipher_info->block_size,
346 sizeof( unsigned char ) );
Brian Murray4b64ab62016-05-20 06:33:01 -0700347 if( check_tag == NULL )
Brian Murray57863ad2016-05-19 16:38:36 -0700348 {
349 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
350 goto exit;
351 }
Brian Murrayb0c3c432016-05-18 14:29:51 -0700352
Manuel Pégourié-Gonnardab9c5fd2016-01-13 15:05:57 +0000353 if( ( ret = mbedtls_cmac_generate( ctx, input, in_len,
354 check_tag, tag_len ) ) != 0 )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000355 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700356 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000357 }
358
359 /* Check tag in "constant-time" */
360 for( diff = 0, i = 0; i < tag_len; i++ )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000361 diff |= tag[i] ^ check_tag[i];
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000362
363 if( diff != 0 )
Brian Murray9ce2e092016-05-24 22:46:43 -0700364 {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700365 ret = MBEDTLS_ERR_CMAC_VERIFY_FAILED;
366 goto exit;
Brian Murray9ce2e092016-05-24 22:46:43 -0700367 }
368 else
369 {
370 ret = 0;
371 goto exit;
372 }
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000373
Brian Murrayb0c3c432016-05-18 14:29:51 -0700374 exit:
Brian Murray4b64ab62016-05-20 06:33:01 -0700375 mbedtls_free( check_tag );
Brian Murrayb439d452016-05-19 16:02:42 -0700376 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000377}
378
Brian Murrayb439d452016-05-19 16:02:42 -0700379#ifdef MBEDTLS_AES_C
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000380/*
381 * PRF based on CMAC with AES-128
Brian Murrayb0c3c432016-05-18 14:29:51 -0700382 * See RFC 4615
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000383 */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700384int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000385 const unsigned char *input, size_t in_len,
Brian Murrayb439d452016-05-19 16:02:42 -0700386 unsigned char tag[16] )
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000387{
388 int ret;
Brian Murrayb0c3c432016-05-18 14:29:51 -0700389 mbedtls_cmac_context ctx;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000390 unsigned char zero_key[16];
391 unsigned char int_key[16];
392
Brian Murrayb439d452016-05-19 16:02:42 -0700393 mbedtls_cmac_init(&ctx );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700394
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000395 if( key_length == 16 )
396 {
397 /* Use key as is */
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000398 memcpy( int_key, key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000399 }
400 else
401 {
402 mbedtls_cmac_context zero_ctx;
403
Brian Murrayb439d452016-05-19 16:02:42 -0700404 /* Key is AES_CMAC( 0, key ) */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000405 mbedtls_cmac_init( &zero_ctx );
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000406 memset( zero_key, 0, 16 );
407 ret = mbedtls_cmac_setkey( &zero_ctx, MBEDTLS_CIPHER_ID_AES,
Brian Murray6a3c0d22016-05-20 18:25:43 -0700408 zero_key, 8 * sizeof( zero_key ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000409 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700410 goto exit;
Manuel Pégourié-Gonnard7b555f22016-01-13 15:09:09 +0000411
Manuel Pégourié-Gonnard690083c2016-01-13 10:48:02 +0000412 ret = mbedtls_cmac_generate( &zero_ctx, key, key_length, int_key, 16 );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000413 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700414 goto exit;
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000415 }
416
Brian Murrayb0c3c432016-05-18 14:29:51 -0700417 ret = mbedtls_cmac_setkey( &ctx, MBEDTLS_CIPHER_ID_AES,
Brian Murray6a3c0d22016-05-20 18:25:43 -0700418 int_key, 8 * sizeof( int_key ) );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000419 if( ret != 0 )
Brian Murrayb0c3c432016-05-18 14:29:51 -0700420 goto exit;
Manuel Pégourié-Gonnardd6cf7542016-01-13 11:30:00 +0000421
Brian Murrayb0c3c432016-05-18 14:29:51 -0700422 ret = mbedtls_cmac_generate( &ctx, input, in_len, tag, 16 );
423
424 exit:
Brian Murray6a3c0d22016-05-20 18:25:43 -0700425 mbedtls_zeroize( int_key, sizeof( int_key ) );
426 mbedtls_cmac_free( &ctx );
Brian Murray53e23b62016-09-13 14:00:15 -0700427 return( ret );
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000428}
Brian Murrayb439d452016-05-19 16:02:42 -0700429#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000430
Brian Murray0f6af732016-05-19 15:59:23 -0700431#ifdef MBEDTLS_SELF_TEST
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000432/*
Brian Murray0f6af732016-05-19 15:59:23 -0700433 * CMAC test data from SP800-38B Appendix D.1 (corrected)
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000434 * http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
Brian Murray0f6af732016-05-19 15:59:23 -0700435 *
436 * AES-CMAC-PRF-128 test data from RFC 4615
437 * https://tools.ietf.org/html/rfc4615#page-4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000438 */
439
Brian Murray0f6af732016-05-19 15:59:23 -0700440#define NB_CMAC_TESTS_PER_KEY 4
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000441#define NB_PRF_TESTS 3
Brian Murray0f6af732016-05-19 15:59:23 -0700442#define AES_BLOCK_SIZE 16
443#define DES3_BLOCK_SIZE 8
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000444
Brian Murray0f6af732016-05-19 15:59:23 -0700445#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)
446/* All CMAC test inputs are truncated from the same 64 byte buffer. */
447static const unsigned char test_message[] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000448 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
449 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
450 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
451 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
452 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
453 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
454 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
455 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
456};
Brian Murray0cf14c12016-05-23 12:49:50 -0700457
458
Brian Murray0f6af732016-05-19 15:59:23 -0700459#endif /* defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000460
Brian Murray0f6af732016-05-19 15:59:23 -0700461#ifdef MBEDTLS_AES_C
462/* Truncation point of message for AES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700463static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700464 0,
465 16,
466 40,
467 64
468};
469
470/* AES 128 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700471static const unsigned char aes_128_key[16] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700472 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
473 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
474};
475static const unsigned char aes_128_subkeys[2][AES_BLOCK_SIZE] = {
476 {
477 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66,
478 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde
479 },
480 {
481 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc,
482 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b
483 }
484};
485static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000486 {
487 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
488 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
489 },
490 {
491 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
492 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
493 },
494 {
495 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
496 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27
497 },
498 {
499 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
500 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
501 }
502};
503
Brian Murray0f6af732016-05-19 15:59:23 -0700504/* AES 192 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700505static const unsigned char aes_192_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700506 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
507 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
508 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000509};
Brian Murray0f6af732016-05-19 15:59:23 -0700510static const unsigned char aes_192_subkeys[2][AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700511 {
Brian Murray0f6af732016-05-19 15:59:23 -0700512 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27,
513 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96
Brian Murrayb0c3c432016-05-18 14:29:51 -0700514 },
515 {
Brian Murray0f6af732016-05-19 15:59:23 -0700516 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e,
517 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c
Brian Murrayb0c3c432016-05-18 14:29:51 -0700518 }
519};
Brian Murray0f6af732016-05-19 15:59:23 -0700520static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700521 {
522 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5,
523 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67
524 },
525 {
526 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90,
527 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84
528 },
529 {
530 0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad,
531 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e
532 },
533 {
534 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79,
535 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11
536 }
537};
538
Brian Murray0f6af732016-05-19 15:59:23 -0700539/* AES 256 CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700540static const unsigned char aes_256_key[32] = {
Brian Murray87e40402016-05-19 19:05:57 -0700541 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
542 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
543 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
544 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
Brian Murray0f6af732016-05-19 15:59:23 -0700545};
546static const unsigned char aes_256_subkeys[2][AES_BLOCK_SIZE] = {
547 {
548 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac,
549 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f
550 },
551 {
552 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58,
553 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9
554 }
555};
556static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][AES_BLOCK_SIZE] = {
557 {
558 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e,
559 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83
560 },
561 {
562 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82,
563 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c
564 },
565 {
566 0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2,
567 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6
568 },
569 {
570 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5,
571 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10
572 }
573};
574#endif /* MBEDTLS_AES_C */
575
576#ifdef MBEDTLS_DES_C
577/* Truncation point of message for 3DES CMAC tests */
Brian Murray57863ad2016-05-19 16:38:36 -0700578static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = {
Brian Murray0f6af732016-05-19 15:59:23 -0700579 0,
580 8,
581 20,
582 32
583};
584
585/* 3DES 2 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700586static const unsigned char des3_2key_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700587 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5,
588 0x8a, 0x3d, 0x10, 0xba, 0x80, 0x57, 0x0d, 0x38,
589 0x4c, 0xf1, 0x51, 0x34, 0xa2, 0x85, 0x0d, 0xd5
Brian Murray0f6af732016-05-19 15:59:23 -0700590};
591static const unsigned char des3_2key_subkeys[2][8] = {
592 {
593 0x8e, 0xcf, 0x37, 0x3e, 0xd7, 0x1a, 0xfa, 0xef
594 },
595 {
596 0x1d, 0x9e, 0x6e, 0x7d, 0xae, 0x35, 0xf5, 0xc5
597 }
598};
Brian Murray57863ad2016-05-19 16:38:36 -0700599static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700600 {
601 0xbd, 0x2e, 0xbf, 0x9a, 0x3b, 0xa0, 0x03, 0x61
602 },
603 {
604 0x4f, 0xf2, 0xab, 0x81, 0x3c, 0x53, 0xce, 0x83
605 },
606 {
607 0x62, 0xdd, 0x1b, 0x47, 0x19, 0x02, 0xbd, 0x4e
608 },
609 {
610 0x31, 0xb1, 0xe4, 0x31, 0xda, 0xbc, 0x4e, 0xb8
611 }
612};
613
Brian Murray0f6af732016-05-19 15:59:23 -0700614/* 3DES 3 Key CMAC Test Data */
Brian Murray57863ad2016-05-19 16:38:36 -0700615static const unsigned char des3_3key_key[24] = {
Brian Murray87e40402016-05-19 19:05:57 -0700616 0x8a, 0xa8, 0x3b, 0xf8, 0xcb, 0xda, 0x10, 0x62,
617 0x0b, 0xc1, 0xbf, 0x19, 0xfb, 0xb6, 0xcd, 0x58,
618 0xbc, 0x31, 0x3d, 0x4a, 0x37, 0x1c, 0xa8, 0xb5
Brian Murray0f6af732016-05-19 15:59:23 -0700619};
620static const unsigned char des3_3key_subkeys[2][8] = {
621 {
622 0x91, 0x98, 0xe9, 0xd3, 0x14, 0xe6, 0x53, 0x5f
623 },
624 {
625 0x23, 0x31, 0xd3, 0xa6, 0x29, 0xcc, 0xa6, 0xa5
626 }
627};
Brian Murray57863ad2016-05-19 16:38:36 -0700628static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][DES3_BLOCK_SIZE] = {
Brian Murrayb0c3c432016-05-18 14:29:51 -0700629 {
630 0xb7, 0xa6, 0x88, 0xe1, 0x22, 0xff, 0xaf, 0x95
631 },
632 {
633 0x8e, 0x8f, 0x29, 0x31, 0x36, 0x28, 0x37, 0x97
634 },
635 {
636 0x74, 0x3d, 0xdb, 0xe0, 0xce, 0x2d, 0xc2, 0xed
637 },
638 {
639 0x33, 0xe6, 0xb1, 0x09, 0x24, 0x00, 0xea, 0xe5
640 }
641};
642
Brian Murray0f6af732016-05-19 15:59:23 -0700643#endif /* MBEDTLS_DES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700644
Brian Murray0f6af732016-05-19 15:59:23 -0700645#ifdef MBEDTLS_AES_C
646/* AES AES-CMAC-PRF-128 Test Data */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000647static const unsigned char PRFK[] = {
648 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
649 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
650 0xed, 0xcb
651};
652
653/* Sizes in bytes */
654static const size_t PRFKlen[NB_PRF_TESTS] = {
655 18,
656 16,
657 10
658};
659
660/* PRF M */
661static const unsigned char PRFM[] = {
662 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
663 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
Manuel Pégourié-Gonnard3da54022016-01-13 11:00:47 +0000664 0x10, 0x11, 0x12, 0x13
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000665};
666
667static const unsigned char PRFT[NB_PRF_TESTS][16] = {
668 {
669 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b,
670 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a
671 },
672 {
673 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52,
674 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d
675 },
676 {
677 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee,
678 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d
679 }
680};
Brian Murray0f6af732016-05-19 15:59:23 -0700681#endif /* MBEDTLS_AES_C */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000682
Brian Murrayae1cb122016-05-23 15:01:59 -0700683static inline int cmac_test_wth_cipher( int verbose,
684 const char* testname,
685 const unsigned char* key,
686 int keybits,
687 const unsigned char* messages,
688 const unsigned int message_lengths[4],
689 const unsigned char* subkeys,
690 const unsigned char* expected_result,
691 mbedtls_cipher_id_t cipher_id,
692 int block_size )
Brian Murray00dc5f02016-05-19 14:23:50 -0700693{
Brian Murray87e40402016-05-19 19:05:57 -0700694 const int num_tests = 4;
695 mbedtls_cmac_context ctx;
Brian Murray00dc5f02016-05-19 14:23:50 -0700696 int i, ret;
697 unsigned char* tag;
698
699 tag = mbedtls_calloc( block_size, sizeof( unsigned char ) );
Brian Murray6a3c0d22016-05-20 18:25:43 -0700700 if( tag == NULL )
701 {
Brian Murray57863ad2016-05-19 16:38:36 -0700702 ret = MBEDTLS_ERR_CMAC_ALLOC_FAILED;
703 goto exit;
704 }
705
Brian Murray00dc5f02016-05-19 14:23:50 -0700706 mbedtls_cmac_init( &ctx );
707
708 if( ( ret = mbedtls_cmac_setkey( &ctx, cipher_id, key, keybits ) ) != 0 )
709 {
710 if( verbose != 0 )
711 mbedtls_printf( " CMAC: setup failed\n" );
712 goto exit;
713 }
714
715 if( ( ret = memcmp( ctx.K1, subkeys, block_size ) != 0 ) ||
716 ( ret = memcmp( ctx.K2, &subkeys[block_size], block_size ) != 0 ) )
717 {
718 if( verbose != 0 )
719 mbedtls_printf( " CMAC: subkey generation failed\n" );
720 goto exit;
721 }
722
723 for( i = 0; i < num_tests; i++ )
724 {
725 if( verbose != 0 )
726 mbedtls_printf( " %s CMAC #%u: ", testname, i +1 );
727
728 if( ( ret = mbedtls_cmac_generate( &ctx, messages, message_lengths[i], tag, block_size ) ) != 0 )
729 {
730 if( verbose != 0 )
731 mbedtls_printf( "failed\n" );
732 goto exit;
733 }
Brian Murray9ce2e092016-05-24 22:46:43 -0700734
Brian Murray00dc5f02016-05-19 14:23:50 -0700735 if( ( ret = memcmp( tag, &expected_result[i * block_size], block_size ) ) != 0 )
736 {
737 if( verbose != 0 )
738 mbedtls_printf( "failed\n" );
739 goto exit;
740 }
741
742 if( ( ret = mbedtls_cmac_verify( &ctx, messages, message_lengths[i], &expected_result[i * block_size], block_size ) != 0 ) )
743 {
Brian Murray4b64ab62016-05-20 06:33:01 -0700744 if( verbose != 0 )
745 mbedtls_printf( "failed\n" );
746 goto exit;
Brian Murray00dc5f02016-05-19 14:23:50 -0700747 }
Brian Murray9ce2e092016-05-24 22:46:43 -0700748
749 if( verbose != 0 )
750 mbedtls_printf( "passed\n" );
Brian Murray00dc5f02016-05-19 14:23:50 -0700751 }
752 exit:
Brian Murray4b64ab62016-05-20 06:33:01 -0700753 mbedtls_free( tag );
Brian Murray00dc5f02016-05-19 14:23:50 -0700754 mbedtls_cmac_free( &ctx );
755 return( ret );
756}
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000757
Brian Murray0f6af732016-05-19 15:59:23 -0700758#ifdef MBEDTLS_AES_C
Brian Murrayae1cb122016-05-23 15:01:59 -0700759static inline int test_aes128_cmac_prf( int verbose )
Brian Murray6a3c0d22016-05-20 18:25:43 -0700760{
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000761 int i;
762 int ret;
Brian Murray0f6af732016-05-19 15:59:23 -0700763 unsigned char tag[16];
Brian Murrayb0c3c432016-05-18 14:29:51 -0700764 for( i = 0; i < NB_PRF_TESTS; i++ )
765 {
Brian Murray0f6af732016-05-19 15:59:23 -0700766 mbedtls_printf( " AES CMAC 128 PRF #%u: ", i );
767 ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, tag );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700768 if( ret != 0 ||
769 memcmp( tag, PRFT[i], 16 ) != 0 )
770 {
771 if( verbose != 0 )
772 mbedtls_printf( "failed\n" );
773
Brian Murray0f6af732016-05-19 15:59:23 -0700774 return( ret );
Brian Murrayb0c3c432016-05-18 14:29:51 -0700775 } else if( verbose != 0 )
776 {
777 mbedtls_printf( "passed\n" );
778 }
779 }
Brian Murray0f6af732016-05-19 15:59:23 -0700780 return( ret );
781}
782#endif /* MBEDTLS_AES_C */
783
784int mbedtls_cmac_self_test( int verbose )
785{
786 int ret;
787
788#ifdef MBEDTLS_AES_C
Brian Murrayae1cb122016-05-23 15:01:59 -0700789 if( ( ret = cmac_test_wth_cipher( verbose,
790 "AES 128",
791 aes_128_key,
792 128,
793 test_message,
794 aes_message_lengths,
795 (const unsigned char*) aes_128_subkeys,
796 (const unsigned char*) aes_128_expected_result,
797 MBEDTLS_CIPHER_ID_AES,
798 AES_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700799 {
800 return( ret );
801 }
Brian Murray0f6af732016-05-19 15:59:23 -0700802
Brian Murrayae1cb122016-05-23 15:01:59 -0700803 if( ( ret = cmac_test_wth_cipher( verbose,
804 "AES 192",
805 aes_192_key,
806 192,
807 test_message,
808 aes_message_lengths,
809 (const unsigned char*) aes_192_subkeys,
810 (const unsigned char*) aes_192_expected_result,
811 MBEDTLS_CIPHER_ID_AES,
812 AES_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700813 {
814 return( ret );
815 }
Brian Murray0f6af732016-05-19 15:59:23 -0700816
Brian Murrayae1cb122016-05-23 15:01:59 -0700817 if( ( ret = cmac_test_wth_cipher ( verbose,
818 "AES 256",
819 aes_256_key,
820 256,
821 test_message,
822 aes_message_lengths,
823 (const unsigned char*) aes_256_subkeys,
824 (const unsigned char*) aes_256_expected_result,
825 MBEDTLS_CIPHER_ID_AES,
826 AES_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700827 {
828 return( ret );
829 }
Brian Murray0f6af732016-05-19 15:59:23 -0700830#endif /* MBEDTLS_AES_C */
831
832#ifdef MBEDTLS_DES_C
Brian Murrayae1cb122016-05-23 15:01:59 -0700833 if( ( ret = cmac_test_wth_cipher( verbose,
834 "3DES 2 key",
835 des3_2key_key,
836 192,
837 test_message,
838 des3_message_lengths,
839 (const unsigned char*) des3_2key_subkeys,
840 (const unsigned char*) des3_2key_expected_result,
841 MBEDTLS_CIPHER_ID_3DES,
842 DES3_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700843 {
844 return( ret );
845 }
Brian Murray0f6af732016-05-19 15:59:23 -0700846
Brian Murrayae1cb122016-05-23 15:01:59 -0700847 if( ( ret = cmac_test_wth_cipher( verbose,
848 "3DES 3 key",
849 des3_3key_key,
850 192,
851 test_message,
852 des3_message_lengths,
853 (const unsigned char*) des3_3key_subkeys,
854 (const unsigned char*) des3_3key_expected_result,
855 MBEDTLS_CIPHER_ID_3DES,
856 DES3_BLOCK_SIZE ) !=0 ) )
Brian Murray9044b022016-05-19 16:36:56 -0700857 {
858 return( ret );
859 }
Brian Murray0f6af732016-05-19 15:59:23 -0700860#endif /* MBEDTLS_DES_C */
861
862#ifdef MBEDTLS_AES_C
Brian Murray9044b022016-05-19 16:36:56 -0700863 if( ( ret = test_aes128_cmac_prf( verbose ) != 0 ) )
864 return( ret );
Brian Murray0f6af732016-05-19 15:59:23 -0700865#endif /* MBEDTLS_AES_C */
Brian Murrayb0c3c432016-05-18 14:29:51 -0700866
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000867 if( verbose != 0 )
868 mbedtls_printf( "\n" );
Brian Murray0f6af732016-05-19 15:59:23 -0700869
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000870 return( 0 );
871}
872
Brian Murray0f6af732016-05-19 15:59:23 -0700873#endif /* MBEDTLS_SELF_TEST */
Robert Cragie3d23b1d2015-12-15 07:38:11 +0000874
875#endif /* MBEDTLS_CMAC_C */