1*817466cbSJens Wiklander /** 2*817466cbSJens Wiklander * \file cmac.c 3*817466cbSJens Wiklander * 4*817466cbSJens Wiklander * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES 5*817466cbSJens Wiklander * 6*817466cbSJens Wiklander * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved 7*817466cbSJens Wiklander * SPDX-License-Identifier: Apache-2.0 8*817466cbSJens Wiklander * 9*817466cbSJens Wiklander * Licensed under the Apache License, Version 2.0 (the "License"); you may 10*817466cbSJens Wiklander * not use this file except in compliance with the License. 11*817466cbSJens Wiklander * You may obtain a copy of the License at 12*817466cbSJens Wiklander * 13*817466cbSJens Wiklander * http://www.apache.org/licenses/LICENSE-2.0 14*817466cbSJens Wiklander * 15*817466cbSJens Wiklander * Unless required by applicable law or agreed to in writing, software 16*817466cbSJens Wiklander * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 17*817466cbSJens Wiklander * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18*817466cbSJens Wiklander * See the License for the specific language governing permissions and 19*817466cbSJens Wiklander * limitations under the License. 20*817466cbSJens Wiklander * 21*817466cbSJens Wiklander * This file is part of mbed TLS (https://tls.mbed.org) 22*817466cbSJens Wiklander */ 23*817466cbSJens Wiklander 24*817466cbSJens Wiklander /* 25*817466cbSJens Wiklander * References: 26*817466cbSJens Wiklander * 27*817466cbSJens Wiklander * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The 28*817466cbSJens Wiklander * CMAC Mode for Authentication 29*817466cbSJens Wiklander * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf 30*817466cbSJens Wiklander * 31*817466cbSJens Wiklander * - RFC 4493 - The AES-CMAC Algorithm 32*817466cbSJens Wiklander * https://tools.ietf.org/html/rfc4493 33*817466cbSJens Wiklander * 34*817466cbSJens Wiklander * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message 35*817466cbSJens Wiklander * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128) 36*817466cbSJens Wiklander * Algorithm for the Internet Key Exchange Protocol (IKE) 37*817466cbSJens Wiklander * https://tools.ietf.org/html/rfc4615 38*817466cbSJens Wiklander * 39*817466cbSJens Wiklander * Additional test vectors: ISO/IEC 9797-1 40*817466cbSJens Wiklander * 41*817466cbSJens Wiklander */ 42*817466cbSJens Wiklander 43*817466cbSJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE) 44*817466cbSJens Wiklander #include "mbedtls/config.h" 45*817466cbSJens Wiklander #else 46*817466cbSJens Wiklander #include MBEDTLS_CONFIG_FILE 47*817466cbSJens Wiklander #endif 48*817466cbSJens Wiklander 49*817466cbSJens Wiklander #if defined(MBEDTLS_CMAC_C) 50*817466cbSJens Wiklander 51*817466cbSJens Wiklander #include "mbedtls/cmac.h" 52*817466cbSJens Wiklander 53*817466cbSJens Wiklander #include <string.h> 54*817466cbSJens Wiklander 55*817466cbSJens Wiklander 56*817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C) 57*817466cbSJens Wiklander #include "mbedtls/platform.h" 58*817466cbSJens Wiklander #else 59*817466cbSJens Wiklander #include <stdlib.h> 60*817466cbSJens Wiklander #define mbedtls_calloc calloc 61*817466cbSJens Wiklander #define mbedtls_free free 62*817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) 63*817466cbSJens Wiklander #include <stdio.h> 64*817466cbSJens Wiklander #define mbedtls_printf printf 65*817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */ 66*817466cbSJens Wiklander #endif /* MBEDTLS_PLATFORM_C */ 67*817466cbSJens Wiklander 68*817466cbSJens Wiklander /* Implementation that should never be optimized out by the compiler */ 69*817466cbSJens Wiklander static void mbedtls_zeroize( void *v, size_t n ) { 70*817466cbSJens Wiklander volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; 71*817466cbSJens Wiklander } 72*817466cbSJens Wiklander 73*817466cbSJens Wiklander /* 74*817466cbSJens Wiklander * Multiplication by u in the Galois field of GF(2^n) 75*817466cbSJens Wiklander * 76*817466cbSJens Wiklander * As explained in NIST SP 800-38B, this can be computed: 77*817466cbSJens Wiklander * 78*817466cbSJens Wiklander * If MSB(p) = 0, then p = (p << 1) 79*817466cbSJens Wiklander * If MSB(p) = 1, then p = (p << 1) ^ R_n 80*817466cbSJens Wiklander * with R_64 = 0x1B and R_128 = 0x87 81*817466cbSJens Wiklander * 82*817466cbSJens Wiklander * Input and output MUST NOT point to the same buffer 83*817466cbSJens Wiklander * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES. 84*817466cbSJens Wiklander */ 85*817466cbSJens Wiklander static int cmac_multiply_by_u( unsigned char *output, 86*817466cbSJens Wiklander const unsigned char *input, 87*817466cbSJens Wiklander size_t blocksize ) 88*817466cbSJens Wiklander { 89*817466cbSJens Wiklander const unsigned char R_128 = 0x87; 90*817466cbSJens Wiklander const unsigned char R_64 = 0x1B; 91*817466cbSJens Wiklander unsigned char R_n, mask; 92*817466cbSJens Wiklander unsigned char overflow = 0x00; 93*817466cbSJens Wiklander int i; 94*817466cbSJens Wiklander 95*817466cbSJens Wiklander if( blocksize == MBEDTLS_AES_BLOCK_SIZE ) 96*817466cbSJens Wiklander { 97*817466cbSJens Wiklander R_n = R_128; 98*817466cbSJens Wiklander } 99*817466cbSJens Wiklander else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE ) 100*817466cbSJens Wiklander { 101*817466cbSJens Wiklander R_n = R_64; 102*817466cbSJens Wiklander } 103*817466cbSJens Wiklander else 104*817466cbSJens Wiklander { 105*817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 106*817466cbSJens Wiklander } 107*817466cbSJens Wiklander 108*817466cbSJens Wiklander for( i = (int)blocksize - 1; i >= 0; i-- ) 109*817466cbSJens Wiklander { 110*817466cbSJens Wiklander output[i] = input[i] << 1 | overflow; 111*817466cbSJens Wiklander overflow = input[i] >> 7; 112*817466cbSJens Wiklander } 113*817466cbSJens Wiklander 114*817466cbSJens Wiklander /* mask = ( input[0] >> 7 ) ? 0xff : 0x00 115*817466cbSJens Wiklander * using bit operations to avoid branches */ 116*817466cbSJens Wiklander 117*817466cbSJens Wiklander /* MSVC has a warning about unary minus on unsigned, but this is 118*817466cbSJens Wiklander * well-defined and precisely what we want to do here */ 119*817466cbSJens Wiklander #if defined(_MSC_VER) 120*817466cbSJens Wiklander #pragma warning( push ) 121*817466cbSJens Wiklander #pragma warning( disable : 4146 ) 122*817466cbSJens Wiklander #endif 123*817466cbSJens Wiklander mask = - ( input[0] >> 7 ); 124*817466cbSJens Wiklander #if defined(_MSC_VER) 125*817466cbSJens Wiklander #pragma warning( pop ) 126*817466cbSJens Wiklander #endif 127*817466cbSJens Wiklander 128*817466cbSJens Wiklander output[ blocksize - 1 ] ^= R_n & mask; 129*817466cbSJens Wiklander 130*817466cbSJens Wiklander return( 0 ); 131*817466cbSJens Wiklander } 132*817466cbSJens Wiklander 133*817466cbSJens Wiklander /* 134*817466cbSJens Wiklander * Generate subkeys 135*817466cbSJens Wiklander * 136*817466cbSJens Wiklander * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm 137*817466cbSJens Wiklander */ 138*817466cbSJens Wiklander static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx, 139*817466cbSJens Wiklander unsigned char* K1, unsigned char* K2 ) 140*817466cbSJens Wiklander { 141*817466cbSJens Wiklander int ret; 142*817466cbSJens Wiklander unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX]; 143*817466cbSJens Wiklander size_t olen, block_size; 144*817466cbSJens Wiklander 145*817466cbSJens Wiklander mbedtls_zeroize( L, sizeof( L ) ); 146*817466cbSJens Wiklander 147*817466cbSJens Wiklander block_size = ctx->cipher_info->block_size; 148*817466cbSJens Wiklander 149*817466cbSJens Wiklander /* Calculate Ek(0) */ 150*817466cbSJens Wiklander if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 ) 151*817466cbSJens Wiklander goto exit; 152*817466cbSJens Wiklander 153*817466cbSJens Wiklander /* 154*817466cbSJens Wiklander * Generate K1 and K2 155*817466cbSJens Wiklander */ 156*817466cbSJens Wiklander if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 ) 157*817466cbSJens Wiklander goto exit; 158*817466cbSJens Wiklander 159*817466cbSJens Wiklander if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 ) 160*817466cbSJens Wiklander goto exit; 161*817466cbSJens Wiklander 162*817466cbSJens Wiklander exit: 163*817466cbSJens Wiklander mbedtls_zeroize( L, sizeof( L ) ); 164*817466cbSJens Wiklander 165*817466cbSJens Wiklander return( ret ); 166*817466cbSJens Wiklander } 167*817466cbSJens Wiklander 168*817466cbSJens Wiklander static void cmac_xor_block( unsigned char *output, const unsigned char *input1, 169*817466cbSJens Wiklander const unsigned char *input2, 170*817466cbSJens Wiklander const size_t block_size ) 171*817466cbSJens Wiklander { 172*817466cbSJens Wiklander size_t idx; 173*817466cbSJens Wiklander 174*817466cbSJens Wiklander for( idx = 0; idx < block_size; idx++ ) 175*817466cbSJens Wiklander output[ idx ] = input1[ idx ] ^ input2[ idx ]; 176*817466cbSJens Wiklander } 177*817466cbSJens Wiklander 178*817466cbSJens Wiklander /* 179*817466cbSJens Wiklander * Create padded last block from (partial) last block. 180*817466cbSJens Wiklander * 181*817466cbSJens Wiklander * We can't use the padding option from the cipher layer, as it only works for 182*817466cbSJens Wiklander * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition. 183*817466cbSJens Wiklander */ 184*817466cbSJens Wiklander static void cmac_pad( unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX], 185*817466cbSJens Wiklander size_t padded_block_len, 186*817466cbSJens Wiklander const unsigned char *last_block, 187*817466cbSJens Wiklander size_t last_block_len ) 188*817466cbSJens Wiklander { 189*817466cbSJens Wiklander size_t j; 190*817466cbSJens Wiklander 191*817466cbSJens Wiklander for( j = 0; j < padded_block_len; j++ ) 192*817466cbSJens Wiklander { 193*817466cbSJens Wiklander if( j < last_block_len ) 194*817466cbSJens Wiklander padded_block[j] = last_block[j]; 195*817466cbSJens Wiklander else if( j == last_block_len ) 196*817466cbSJens Wiklander padded_block[j] = 0x80; 197*817466cbSJens Wiklander else 198*817466cbSJens Wiklander padded_block[j] = 0x00; 199*817466cbSJens Wiklander } 200*817466cbSJens Wiklander } 201*817466cbSJens Wiklander 202*817466cbSJens Wiklander int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, 203*817466cbSJens Wiklander const unsigned char *key, size_t keybits ) 204*817466cbSJens Wiklander { 205*817466cbSJens Wiklander mbedtls_cipher_type_t type; 206*817466cbSJens Wiklander mbedtls_cmac_context_t *cmac_ctx; 207*817466cbSJens Wiklander int retval; 208*817466cbSJens Wiklander 209*817466cbSJens Wiklander if( ctx == NULL || ctx->cipher_info == NULL || key == NULL ) 210*817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 211*817466cbSJens Wiklander 212*817466cbSJens Wiklander if( ( retval = mbedtls_cipher_setkey( ctx, key, (int)keybits, 213*817466cbSJens Wiklander MBEDTLS_ENCRYPT ) ) != 0 ) 214*817466cbSJens Wiklander return( retval ); 215*817466cbSJens Wiklander 216*817466cbSJens Wiklander type = ctx->cipher_info->type; 217*817466cbSJens Wiklander 218*817466cbSJens Wiklander switch( type ) 219*817466cbSJens Wiklander { 220*817466cbSJens Wiklander case MBEDTLS_CIPHER_AES_128_ECB: 221*817466cbSJens Wiklander case MBEDTLS_CIPHER_AES_192_ECB: 222*817466cbSJens Wiklander case MBEDTLS_CIPHER_AES_256_ECB: 223*817466cbSJens Wiklander case MBEDTLS_CIPHER_DES_EDE3_ECB: 224*817466cbSJens Wiklander break; 225*817466cbSJens Wiklander default: 226*817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 227*817466cbSJens Wiklander } 228*817466cbSJens Wiklander 229*817466cbSJens Wiklander /* Allocated and initialise in the cipher context memory for the CMAC 230*817466cbSJens Wiklander * context */ 231*817466cbSJens Wiklander cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) ); 232*817466cbSJens Wiklander if( cmac_ctx == NULL ) 233*817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); 234*817466cbSJens Wiklander 235*817466cbSJens Wiklander ctx->cmac_ctx = cmac_ctx; 236*817466cbSJens Wiklander 237*817466cbSJens Wiklander mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); 238*817466cbSJens Wiklander 239*817466cbSJens Wiklander return 0; 240*817466cbSJens Wiklander } 241*817466cbSJens Wiklander 242*817466cbSJens Wiklander int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, 243*817466cbSJens Wiklander const unsigned char *input, size_t ilen ) 244*817466cbSJens Wiklander { 245*817466cbSJens Wiklander mbedtls_cmac_context_t* cmac_ctx; 246*817466cbSJens Wiklander unsigned char *state; 247*817466cbSJens Wiklander int ret = 0; 248*817466cbSJens Wiklander size_t n, j, olen, block_size; 249*817466cbSJens Wiklander 250*817466cbSJens Wiklander if( ctx == NULL || ctx->cipher_info == NULL || input == NULL || 251*817466cbSJens Wiklander ctx->cmac_ctx == NULL ) 252*817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 253*817466cbSJens Wiklander 254*817466cbSJens Wiklander cmac_ctx = ctx->cmac_ctx; 255*817466cbSJens Wiklander block_size = ctx->cipher_info->block_size; 256*817466cbSJens Wiklander state = ctx->cmac_ctx->state; 257*817466cbSJens Wiklander 258*817466cbSJens Wiklander /* Is there data still to process from the last call, that's greater in 259*817466cbSJens Wiklander * size than a block? */ 260*817466cbSJens Wiklander if( cmac_ctx->unprocessed_len > 0 && 261*817466cbSJens Wiklander ilen > block_size - cmac_ctx->unprocessed_len ) 262*817466cbSJens Wiklander { 263*817466cbSJens Wiklander memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], 264*817466cbSJens Wiklander input, 265*817466cbSJens Wiklander block_size - cmac_ctx->unprocessed_len ); 266*817466cbSJens Wiklander 267*817466cbSJens Wiklander cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size ); 268*817466cbSJens Wiklander 269*817466cbSJens Wiklander if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, 270*817466cbSJens Wiklander &olen ) ) != 0 ) 271*817466cbSJens Wiklander { 272*817466cbSJens Wiklander goto exit; 273*817466cbSJens Wiklander } 274*817466cbSJens Wiklander 275*817466cbSJens Wiklander input += block_size - cmac_ctx->unprocessed_len; 276*817466cbSJens Wiklander ilen -= block_size - cmac_ctx->unprocessed_len; 277*817466cbSJens Wiklander cmac_ctx->unprocessed_len = 0; 278*817466cbSJens Wiklander } 279*817466cbSJens Wiklander 280*817466cbSJens Wiklander /* n is the number of blocks including any final partial block */ 281*817466cbSJens Wiklander n = ( ilen + block_size - 1 ) / block_size; 282*817466cbSJens Wiklander 283*817466cbSJens Wiklander /* Iterate across the input data in block sized chunks, excluding any 284*817466cbSJens Wiklander * final partial or complete block */ 285*817466cbSJens Wiklander for( j = 1; j < n; j++ ) 286*817466cbSJens Wiklander { 287*817466cbSJens Wiklander cmac_xor_block( state, input, state, block_size ); 288*817466cbSJens Wiklander 289*817466cbSJens Wiklander if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, 290*817466cbSJens Wiklander &olen ) ) != 0 ) 291*817466cbSJens Wiklander goto exit; 292*817466cbSJens Wiklander 293*817466cbSJens Wiklander ilen -= block_size; 294*817466cbSJens Wiklander input += block_size; 295*817466cbSJens Wiklander } 296*817466cbSJens Wiklander 297*817466cbSJens Wiklander /* If there is data left over that wasn't aligned to a block */ 298*817466cbSJens Wiklander if( ilen > 0 ) 299*817466cbSJens Wiklander { 300*817466cbSJens Wiklander memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], 301*817466cbSJens Wiklander input, 302*817466cbSJens Wiklander ilen ); 303*817466cbSJens Wiklander cmac_ctx->unprocessed_len += ilen; 304*817466cbSJens Wiklander } 305*817466cbSJens Wiklander 306*817466cbSJens Wiklander exit: 307*817466cbSJens Wiklander return( ret ); 308*817466cbSJens Wiklander } 309*817466cbSJens Wiklander 310*817466cbSJens Wiklander int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, 311*817466cbSJens Wiklander unsigned char *output ) 312*817466cbSJens Wiklander { 313*817466cbSJens Wiklander mbedtls_cmac_context_t* cmac_ctx; 314*817466cbSJens Wiklander unsigned char *state, *last_block; 315*817466cbSJens Wiklander unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; 316*817466cbSJens Wiklander unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; 317*817466cbSJens Wiklander unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX]; 318*817466cbSJens Wiklander int ret; 319*817466cbSJens Wiklander size_t olen, block_size; 320*817466cbSJens Wiklander 321*817466cbSJens Wiklander if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL || 322*817466cbSJens Wiklander output == NULL ) 323*817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 324*817466cbSJens Wiklander 325*817466cbSJens Wiklander cmac_ctx = ctx->cmac_ctx; 326*817466cbSJens Wiklander block_size = ctx->cipher_info->block_size; 327*817466cbSJens Wiklander state = cmac_ctx->state; 328*817466cbSJens Wiklander 329*817466cbSJens Wiklander mbedtls_zeroize( K1, sizeof( K1 ) ); 330*817466cbSJens Wiklander mbedtls_zeroize( K2, sizeof( K2 ) ); 331*817466cbSJens Wiklander cmac_generate_subkeys( ctx, K1, K2 ); 332*817466cbSJens Wiklander 333*817466cbSJens Wiklander last_block = cmac_ctx->unprocessed_block; 334*817466cbSJens Wiklander 335*817466cbSJens Wiklander /* Calculate last block */ 336*817466cbSJens Wiklander if( cmac_ctx->unprocessed_len < block_size ) 337*817466cbSJens Wiklander { 338*817466cbSJens Wiklander cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len ); 339*817466cbSJens Wiklander cmac_xor_block( M_last, M_last, K2, block_size ); 340*817466cbSJens Wiklander } 341*817466cbSJens Wiklander else 342*817466cbSJens Wiklander { 343*817466cbSJens Wiklander /* Last block is complete block */ 344*817466cbSJens Wiklander cmac_xor_block( M_last, last_block, K1, block_size ); 345*817466cbSJens Wiklander } 346*817466cbSJens Wiklander 347*817466cbSJens Wiklander 348*817466cbSJens Wiklander cmac_xor_block( state, M_last, state, block_size ); 349*817466cbSJens Wiklander if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, 350*817466cbSJens Wiklander &olen ) ) != 0 ) 351*817466cbSJens Wiklander { 352*817466cbSJens Wiklander goto exit; 353*817466cbSJens Wiklander } 354*817466cbSJens Wiklander 355*817466cbSJens Wiklander memcpy( output, state, block_size ); 356*817466cbSJens Wiklander 357*817466cbSJens Wiklander exit: 358*817466cbSJens Wiklander /* Wipe the generated keys on the stack, and any other transients to avoid 359*817466cbSJens Wiklander * side channel leakage */ 360*817466cbSJens Wiklander mbedtls_zeroize( K1, sizeof( K1 ) ); 361*817466cbSJens Wiklander mbedtls_zeroize( K2, sizeof( K2 ) ); 362*817466cbSJens Wiklander 363*817466cbSJens Wiklander cmac_ctx->unprocessed_len = 0; 364*817466cbSJens Wiklander mbedtls_zeroize( cmac_ctx->unprocessed_block, 365*817466cbSJens Wiklander sizeof( cmac_ctx->unprocessed_block ) ); 366*817466cbSJens Wiklander 367*817466cbSJens Wiklander mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX ); 368*817466cbSJens Wiklander return( ret ); 369*817466cbSJens Wiklander } 370*817466cbSJens Wiklander 371*817466cbSJens Wiklander int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) 372*817466cbSJens Wiklander { 373*817466cbSJens Wiklander mbedtls_cmac_context_t* cmac_ctx; 374*817466cbSJens Wiklander 375*817466cbSJens Wiklander if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ) 376*817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 377*817466cbSJens Wiklander 378*817466cbSJens Wiklander cmac_ctx = ctx->cmac_ctx; 379*817466cbSJens Wiklander 380*817466cbSJens Wiklander /* Reset the internal state */ 381*817466cbSJens Wiklander cmac_ctx->unprocessed_len = 0; 382*817466cbSJens Wiklander mbedtls_zeroize( cmac_ctx->unprocessed_block, 383*817466cbSJens Wiklander sizeof( cmac_ctx->unprocessed_block ) ); 384*817466cbSJens Wiklander mbedtls_zeroize( cmac_ctx->state, 385*817466cbSJens Wiklander sizeof( cmac_ctx->state ) ); 386*817466cbSJens Wiklander 387*817466cbSJens Wiklander return( 0 ); 388*817466cbSJens Wiklander } 389*817466cbSJens Wiklander 390*817466cbSJens Wiklander int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, 391*817466cbSJens Wiklander const unsigned char *key, size_t keylen, 392*817466cbSJens Wiklander const unsigned char *input, size_t ilen, 393*817466cbSJens Wiklander unsigned char *output ) 394*817466cbSJens Wiklander { 395*817466cbSJens Wiklander mbedtls_cipher_context_t ctx; 396*817466cbSJens Wiklander int ret; 397*817466cbSJens Wiklander 398*817466cbSJens Wiklander if( cipher_info == NULL || key == NULL || input == NULL || output == NULL ) 399*817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 400*817466cbSJens Wiklander 401*817466cbSJens Wiklander mbedtls_cipher_init( &ctx ); 402*817466cbSJens Wiklander 403*817466cbSJens Wiklander if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) 404*817466cbSJens Wiklander goto exit; 405*817466cbSJens Wiklander 406*817466cbSJens Wiklander ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen ); 407*817466cbSJens Wiklander if( ret != 0 ) 408*817466cbSJens Wiklander goto exit; 409*817466cbSJens Wiklander 410*817466cbSJens Wiklander ret = mbedtls_cipher_cmac_update( &ctx, input, ilen ); 411*817466cbSJens Wiklander if( ret != 0 ) 412*817466cbSJens Wiklander goto exit; 413*817466cbSJens Wiklander 414*817466cbSJens Wiklander ret = mbedtls_cipher_cmac_finish( &ctx, output ); 415*817466cbSJens Wiklander 416*817466cbSJens Wiklander exit: 417*817466cbSJens Wiklander mbedtls_cipher_free( &ctx ); 418*817466cbSJens Wiklander 419*817466cbSJens Wiklander return( ret ); 420*817466cbSJens Wiklander } 421*817466cbSJens Wiklander 422*817466cbSJens Wiklander #if defined(MBEDTLS_AES_C) 423*817466cbSJens Wiklander /* 424*817466cbSJens Wiklander * Implementation of AES-CMAC-PRF-128 defined in RFC 4615 425*817466cbSJens Wiklander */ 426*817466cbSJens Wiklander int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, 427*817466cbSJens Wiklander const unsigned char *input, size_t in_len, 428*817466cbSJens Wiklander unsigned char *output ) 429*817466cbSJens Wiklander { 430*817466cbSJens Wiklander int ret; 431*817466cbSJens Wiklander const mbedtls_cipher_info_t *cipher_info; 432*817466cbSJens Wiklander unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE]; 433*817466cbSJens Wiklander unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE]; 434*817466cbSJens Wiklander 435*817466cbSJens Wiklander if( key == NULL || input == NULL || output == NULL ) 436*817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); 437*817466cbSJens Wiklander 438*817466cbSJens Wiklander cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB ); 439*817466cbSJens Wiklander if( cipher_info == NULL ) 440*817466cbSJens Wiklander { 441*817466cbSJens Wiklander /* Failing at this point must be due to a build issue */ 442*817466cbSJens Wiklander ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 443*817466cbSJens Wiklander goto exit; 444*817466cbSJens Wiklander } 445*817466cbSJens Wiklander 446*817466cbSJens Wiklander if( key_length == MBEDTLS_AES_BLOCK_SIZE ) 447*817466cbSJens Wiklander { 448*817466cbSJens Wiklander /* Use key as is */ 449*817466cbSJens Wiklander memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE ); 450*817466cbSJens Wiklander } 451*817466cbSJens Wiklander else 452*817466cbSJens Wiklander { 453*817466cbSJens Wiklander memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE ); 454*817466cbSJens Wiklander 455*817466cbSJens Wiklander ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key, 456*817466cbSJens Wiklander key_length, int_key ); 457*817466cbSJens Wiklander if( ret != 0 ) 458*817466cbSJens Wiklander goto exit; 459*817466cbSJens Wiklander } 460*817466cbSJens Wiklander 461*817466cbSJens Wiklander ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len, 462*817466cbSJens Wiklander output ); 463*817466cbSJens Wiklander 464*817466cbSJens Wiklander exit: 465*817466cbSJens Wiklander mbedtls_zeroize( int_key, sizeof( int_key ) ); 466*817466cbSJens Wiklander 467*817466cbSJens Wiklander return( ret ); 468*817466cbSJens Wiklander } 469*817466cbSJens Wiklander #endif /* MBEDTLS_AES_C */ 470*817466cbSJens Wiklander 471*817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) 472*817466cbSJens Wiklander /* 473*817466cbSJens Wiklander * CMAC test data for SP800-38B 474*817466cbSJens Wiklander * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf 475*817466cbSJens Wiklander * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf 476*817466cbSJens Wiklander * 477*817466cbSJens Wiklander * AES-CMAC-PRF-128 test data from RFC 4615 478*817466cbSJens Wiklander * https://tools.ietf.org/html/rfc4615#page-4 479*817466cbSJens Wiklander */ 480*817466cbSJens Wiklander 481*817466cbSJens Wiklander #define NB_CMAC_TESTS_PER_KEY 4 482*817466cbSJens Wiklander #define NB_PRF_TESTS 3 483*817466cbSJens Wiklander 484*817466cbSJens Wiklander #if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) 485*817466cbSJens Wiklander /* All CMAC test inputs are truncated from the same 64 byte buffer. */ 486*817466cbSJens Wiklander static const unsigned char test_message[] = { 487*817466cbSJens Wiklander /* PT */ 488*817466cbSJens Wiklander 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 489*817466cbSJens Wiklander 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 490*817466cbSJens Wiklander 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 491*817466cbSJens Wiklander 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 492*817466cbSJens Wiklander 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 493*817466cbSJens Wiklander 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, 494*817466cbSJens Wiklander 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 495*817466cbSJens Wiklander 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 496*817466cbSJens Wiklander }; 497*817466cbSJens Wiklander #endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */ 498*817466cbSJens Wiklander 499*817466cbSJens Wiklander #if defined(MBEDTLS_AES_C) 500*817466cbSJens Wiklander /* Truncation point of message for AES CMAC tests */ 501*817466cbSJens Wiklander static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = { 502*817466cbSJens Wiklander /* Mlen */ 503*817466cbSJens Wiklander 0, 504*817466cbSJens Wiklander 16, 505*817466cbSJens Wiklander 20, 506*817466cbSJens Wiklander 64 507*817466cbSJens Wiklander }; 508*817466cbSJens Wiklander 509*817466cbSJens Wiklander /* CMAC-AES128 Test Data */ 510*817466cbSJens Wiklander static const unsigned char aes_128_key[16] = { 511*817466cbSJens Wiklander 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 512*817466cbSJens Wiklander 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c 513*817466cbSJens Wiklander }; 514*817466cbSJens Wiklander static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { 515*817466cbSJens Wiklander { 516*817466cbSJens Wiklander /* K1 */ 517*817466cbSJens Wiklander 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, 518*817466cbSJens Wiklander 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde 519*817466cbSJens Wiklander }, 520*817466cbSJens Wiklander { 521*817466cbSJens Wiklander /* K2 */ 522*817466cbSJens Wiklander 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, 523*817466cbSJens Wiklander 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b 524*817466cbSJens Wiklander } 525*817466cbSJens Wiklander }; 526*817466cbSJens Wiklander static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { 527*817466cbSJens Wiklander { 528*817466cbSJens Wiklander /* Example #1 */ 529*817466cbSJens Wiklander 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, 530*817466cbSJens Wiklander 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 531*817466cbSJens Wiklander }, 532*817466cbSJens Wiklander { 533*817466cbSJens Wiklander /* Example #2 */ 534*817466cbSJens Wiklander 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, 535*817466cbSJens Wiklander 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c 536*817466cbSJens Wiklander }, 537*817466cbSJens Wiklander { 538*817466cbSJens Wiklander /* Example #3 */ 539*817466cbSJens Wiklander 0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8, 540*817466cbSJens Wiklander 0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde 541*817466cbSJens Wiklander }, 542*817466cbSJens Wiklander { 543*817466cbSJens Wiklander /* Example #4 */ 544*817466cbSJens Wiklander 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, 545*817466cbSJens Wiklander 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe 546*817466cbSJens Wiklander } 547*817466cbSJens Wiklander }; 548*817466cbSJens Wiklander 549*817466cbSJens Wiklander /* CMAC-AES192 Test Data */ 550*817466cbSJens Wiklander static const unsigned char aes_192_key[24] = { 551*817466cbSJens Wiklander 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 552*817466cbSJens Wiklander 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, 553*817466cbSJens Wiklander 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b 554*817466cbSJens Wiklander }; 555*817466cbSJens Wiklander static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { 556*817466cbSJens Wiklander { 557*817466cbSJens Wiklander /* K1 */ 558*817466cbSJens Wiklander 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27, 559*817466cbSJens Wiklander 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96 560*817466cbSJens Wiklander }, 561*817466cbSJens Wiklander { 562*817466cbSJens Wiklander /* K2 */ 563*817466cbSJens Wiklander 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e, 564*817466cbSJens Wiklander 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c 565*817466cbSJens Wiklander } 566*817466cbSJens Wiklander }; 567*817466cbSJens Wiklander static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { 568*817466cbSJens Wiklander { 569*817466cbSJens Wiklander /* Example #1 */ 570*817466cbSJens Wiklander 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, 571*817466cbSJens Wiklander 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67 572*817466cbSJens Wiklander }, 573*817466cbSJens Wiklander { 574*817466cbSJens Wiklander /* Example #2 */ 575*817466cbSJens Wiklander 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, 576*817466cbSJens Wiklander 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84 577*817466cbSJens Wiklander }, 578*817466cbSJens Wiklander { 579*817466cbSJens Wiklander /* Example #3 */ 580*817466cbSJens Wiklander 0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04, 581*817466cbSJens Wiklander 0x44, 0xa9, 0xfa, 0x7e, 0xc7, 0x40, 0xec, 0xf8 582*817466cbSJens Wiklander }, 583*817466cbSJens Wiklander { 584*817466cbSJens Wiklander /* Example #4 */ 585*817466cbSJens Wiklander 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, 586*817466cbSJens Wiklander 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11 587*817466cbSJens Wiklander } 588*817466cbSJens Wiklander }; 589*817466cbSJens Wiklander 590*817466cbSJens Wiklander /* CMAC-AES256 Test Data */ 591*817466cbSJens Wiklander static const unsigned char aes_256_key[32] = { 592*817466cbSJens Wiklander 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 593*817466cbSJens Wiklander 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, 594*817466cbSJens Wiklander 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 595*817466cbSJens Wiklander 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 596*817466cbSJens Wiklander }; 597*817466cbSJens Wiklander static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { 598*817466cbSJens Wiklander { 599*817466cbSJens Wiklander /* K1 */ 600*817466cbSJens Wiklander 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac, 601*817466cbSJens Wiklander 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f 602*817466cbSJens Wiklander }, 603*817466cbSJens Wiklander { 604*817466cbSJens Wiklander /* K2 */ 605*817466cbSJens Wiklander 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58, 606*817466cbSJens Wiklander 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9 607*817466cbSJens Wiklander } 608*817466cbSJens Wiklander }; 609*817466cbSJens Wiklander static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { 610*817466cbSJens Wiklander { 611*817466cbSJens Wiklander /* Example #1 */ 612*817466cbSJens Wiklander 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, 613*817466cbSJens Wiklander 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83 614*817466cbSJens Wiklander }, 615*817466cbSJens Wiklander { 616*817466cbSJens Wiklander /* Example #2 */ 617*817466cbSJens Wiklander 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, 618*817466cbSJens Wiklander 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c 619*817466cbSJens Wiklander }, 620*817466cbSJens Wiklander { 621*817466cbSJens Wiklander /* Example #3 */ 622*817466cbSJens Wiklander 0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a, 623*817466cbSJens Wiklander 0x02, 0x3c, 0x1f, 0xe0, 0x3b, 0xad, 0x6d, 0x93 624*817466cbSJens Wiklander }, 625*817466cbSJens Wiklander { 626*817466cbSJens Wiklander /* Example #4 */ 627*817466cbSJens Wiklander 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, 628*817466cbSJens Wiklander 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10 629*817466cbSJens Wiklander } 630*817466cbSJens Wiklander }; 631*817466cbSJens Wiklander #endif /* MBEDTLS_AES_C */ 632*817466cbSJens Wiklander 633*817466cbSJens Wiklander #if defined(MBEDTLS_DES_C) 634*817466cbSJens Wiklander /* Truncation point of message for 3DES CMAC tests */ 635*817466cbSJens Wiklander static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { 636*817466cbSJens Wiklander 0, 637*817466cbSJens Wiklander 16, 638*817466cbSJens Wiklander 20, 639*817466cbSJens Wiklander 32 640*817466cbSJens Wiklander }; 641*817466cbSJens Wiklander 642*817466cbSJens Wiklander /* CMAC-TDES (Generation) - 2 Key Test Data */ 643*817466cbSJens Wiklander static const unsigned char des3_2key_key[24] = { 644*817466cbSJens Wiklander /* Key1 */ 645*817466cbSJens Wiklander 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 646*817466cbSJens Wiklander /* Key2 */ 647*817466cbSJens Wiklander 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01, 648*817466cbSJens Wiklander /* Key3 */ 649*817466cbSJens Wiklander 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef 650*817466cbSJens Wiklander }; 651*817466cbSJens Wiklander static const unsigned char des3_2key_subkeys[2][8] = { 652*817466cbSJens Wiklander { 653*817466cbSJens Wiklander /* K1 */ 654*817466cbSJens Wiklander 0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9 655*817466cbSJens Wiklander }, 656*817466cbSJens Wiklander { 657*817466cbSJens Wiklander /* K2 */ 658*817466cbSJens Wiklander 0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2 659*817466cbSJens Wiklander } 660*817466cbSJens Wiklander }; 661*817466cbSJens Wiklander static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { 662*817466cbSJens Wiklander { 663*817466cbSJens Wiklander /* Sample #1 */ 664*817466cbSJens Wiklander 0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60 665*817466cbSJens Wiklander }, 666*817466cbSJens Wiklander { 667*817466cbSJens Wiklander /* Sample #2 */ 668*817466cbSJens Wiklander 0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b 669*817466cbSJens Wiklander }, 670*817466cbSJens Wiklander { 671*817466cbSJens Wiklander /* Sample #3 */ 672*817466cbSJens Wiklander 0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69 673*817466cbSJens Wiklander }, 674*817466cbSJens Wiklander { 675*817466cbSJens Wiklander /* Sample #4 */ 676*817466cbSJens Wiklander 0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb 677*817466cbSJens Wiklander } 678*817466cbSJens Wiklander }; 679*817466cbSJens Wiklander 680*817466cbSJens Wiklander /* CMAC-TDES (Generation) - 3 Key Test Data */ 681*817466cbSJens Wiklander static const unsigned char des3_3key_key[24] = { 682*817466cbSJens Wiklander /* Key1 */ 683*817466cbSJens Wiklander 0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef, 684*817466cbSJens Wiklander /* Key2 */ 685*817466cbSJens Wiklander 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 686*817466cbSJens Wiklander /* Key3 */ 687*817466cbSJens Wiklander 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23 688*817466cbSJens Wiklander }; 689*817466cbSJens Wiklander static const unsigned char des3_3key_subkeys[2][8] = { 690*817466cbSJens Wiklander { 691*817466cbSJens Wiklander /* K1 */ 692*817466cbSJens Wiklander 0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0 693*817466cbSJens Wiklander }, 694*817466cbSJens Wiklander { 695*817466cbSJens Wiklander /* K2 */ 696*817466cbSJens Wiklander 0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b 697*817466cbSJens Wiklander } 698*817466cbSJens Wiklander }; 699*817466cbSJens Wiklander static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { 700*817466cbSJens Wiklander { 701*817466cbSJens Wiklander /* Sample #1 */ 702*817466cbSJens Wiklander 0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50 703*817466cbSJens Wiklander }, 704*817466cbSJens Wiklander { 705*817466cbSJens Wiklander /* Sample #2 */ 706*817466cbSJens Wiklander 0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09 707*817466cbSJens Wiklander }, 708*817466cbSJens Wiklander { 709*817466cbSJens Wiklander /* Sample #3 */ 710*817466cbSJens Wiklander 0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2 711*817466cbSJens Wiklander }, 712*817466cbSJens Wiklander { 713*817466cbSJens Wiklander /* Sample #4 */ 714*817466cbSJens Wiklander 0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5 715*817466cbSJens Wiklander } 716*817466cbSJens Wiklander }; 717*817466cbSJens Wiklander 718*817466cbSJens Wiklander #endif /* MBEDTLS_DES_C */ 719*817466cbSJens Wiklander 720*817466cbSJens Wiklander #if defined(MBEDTLS_AES_C) 721*817466cbSJens Wiklander /* AES AES-CMAC-PRF-128 Test Data */ 722*817466cbSJens Wiklander static const unsigned char PRFK[] = { 723*817466cbSJens Wiklander /* Key */ 724*817466cbSJens Wiklander 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 725*817466cbSJens Wiklander 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 726*817466cbSJens Wiklander 0xed, 0xcb 727*817466cbSJens Wiklander }; 728*817466cbSJens Wiklander 729*817466cbSJens Wiklander /* Sizes in bytes */ 730*817466cbSJens Wiklander static const size_t PRFKlen[NB_PRF_TESTS] = { 731*817466cbSJens Wiklander 18, 732*817466cbSJens Wiklander 16, 733*817466cbSJens Wiklander 10 734*817466cbSJens Wiklander }; 735*817466cbSJens Wiklander 736*817466cbSJens Wiklander /* Message */ 737*817466cbSJens Wiklander static const unsigned char PRFM[] = { 738*817466cbSJens Wiklander 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 739*817466cbSJens Wiklander 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 740*817466cbSJens Wiklander 0x10, 0x11, 0x12, 0x13 741*817466cbSJens Wiklander }; 742*817466cbSJens Wiklander 743*817466cbSJens Wiklander static const unsigned char PRFT[NB_PRF_TESTS][16] = { 744*817466cbSJens Wiklander { 745*817466cbSJens Wiklander 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b, 746*817466cbSJens Wiklander 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a 747*817466cbSJens Wiklander }, 748*817466cbSJens Wiklander { 749*817466cbSJens Wiklander 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52, 750*817466cbSJens Wiklander 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d 751*817466cbSJens Wiklander }, 752*817466cbSJens Wiklander { 753*817466cbSJens Wiklander 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee, 754*817466cbSJens Wiklander 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d 755*817466cbSJens Wiklander } 756*817466cbSJens Wiklander }; 757*817466cbSJens Wiklander #endif /* MBEDTLS_AES_C */ 758*817466cbSJens Wiklander 759*817466cbSJens Wiklander static int cmac_test_subkeys( int verbose, 760*817466cbSJens Wiklander const char* testname, 761*817466cbSJens Wiklander const unsigned char* key, 762*817466cbSJens Wiklander int keybits, 763*817466cbSJens Wiklander const unsigned char* subkeys, 764*817466cbSJens Wiklander mbedtls_cipher_type_t cipher_type, 765*817466cbSJens Wiklander int block_size, 766*817466cbSJens Wiklander int num_tests ) 767*817466cbSJens Wiklander { 768*817466cbSJens Wiklander int i, ret; 769*817466cbSJens Wiklander mbedtls_cipher_context_t ctx; 770*817466cbSJens Wiklander const mbedtls_cipher_info_t *cipher_info; 771*817466cbSJens Wiklander unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; 772*817466cbSJens Wiklander unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; 773*817466cbSJens Wiklander 774*817466cbSJens Wiklander cipher_info = mbedtls_cipher_info_from_type( cipher_type ); 775*817466cbSJens Wiklander if( cipher_info == NULL ) 776*817466cbSJens Wiklander { 777*817466cbSJens Wiklander /* Failing at this point must be due to a build issue */ 778*817466cbSJens Wiklander return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); 779*817466cbSJens Wiklander } 780*817466cbSJens Wiklander 781*817466cbSJens Wiklander for( i = 0; i < num_tests; i++ ) 782*817466cbSJens Wiklander { 783*817466cbSJens Wiklander if( verbose != 0 ) 784*817466cbSJens Wiklander mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 ); 785*817466cbSJens Wiklander 786*817466cbSJens Wiklander mbedtls_cipher_init( &ctx ); 787*817466cbSJens Wiklander 788*817466cbSJens Wiklander if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) 789*817466cbSJens Wiklander { 790*817466cbSJens Wiklander if( verbose != 0 ) 791*817466cbSJens Wiklander mbedtls_printf( "test execution failed\n" ); 792*817466cbSJens Wiklander 793*817466cbSJens Wiklander goto cleanup; 794*817466cbSJens Wiklander } 795*817466cbSJens Wiklander 796*817466cbSJens Wiklander if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits, 797*817466cbSJens Wiklander MBEDTLS_ENCRYPT ) ) != 0 ) 798*817466cbSJens Wiklander { 799*817466cbSJens Wiklander if( verbose != 0 ) 800*817466cbSJens Wiklander mbedtls_printf( "test execution failed\n" ); 801*817466cbSJens Wiklander 802*817466cbSJens Wiklander goto cleanup; 803*817466cbSJens Wiklander } 804*817466cbSJens Wiklander 805*817466cbSJens Wiklander ret = cmac_generate_subkeys( &ctx, K1, K2 ); 806*817466cbSJens Wiklander if( ret != 0 ) 807*817466cbSJens Wiklander { 808*817466cbSJens Wiklander if( verbose != 0 ) 809*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 810*817466cbSJens Wiklander 811*817466cbSJens Wiklander goto cleanup; 812*817466cbSJens Wiklander } 813*817466cbSJens Wiklander 814*817466cbSJens Wiklander if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 || 815*817466cbSJens Wiklander ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 ) 816*817466cbSJens Wiklander { 817*817466cbSJens Wiklander if( verbose != 0 ) 818*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 819*817466cbSJens Wiklander 820*817466cbSJens Wiklander goto cleanup; 821*817466cbSJens Wiklander } 822*817466cbSJens Wiklander 823*817466cbSJens Wiklander if( verbose != 0 ) 824*817466cbSJens Wiklander mbedtls_printf( "passed\n" ); 825*817466cbSJens Wiklander 826*817466cbSJens Wiklander mbedtls_cipher_free( &ctx ); 827*817466cbSJens Wiklander } 828*817466cbSJens Wiklander 829*817466cbSJens Wiklander goto exit; 830*817466cbSJens Wiklander 831*817466cbSJens Wiklander cleanup: 832*817466cbSJens Wiklander mbedtls_cipher_free( &ctx ); 833*817466cbSJens Wiklander 834*817466cbSJens Wiklander exit: 835*817466cbSJens Wiklander return( ret ); 836*817466cbSJens Wiklander } 837*817466cbSJens Wiklander 838*817466cbSJens Wiklander static int cmac_test_wth_cipher( int verbose, 839*817466cbSJens Wiklander const char* testname, 840*817466cbSJens Wiklander const unsigned char* key, 841*817466cbSJens Wiklander int keybits, 842*817466cbSJens Wiklander const unsigned char* messages, 843*817466cbSJens Wiklander const unsigned int message_lengths[4], 844*817466cbSJens Wiklander const unsigned char* expected_result, 845*817466cbSJens Wiklander mbedtls_cipher_type_t cipher_type, 846*817466cbSJens Wiklander int block_size, 847*817466cbSJens Wiklander int num_tests ) 848*817466cbSJens Wiklander { 849*817466cbSJens Wiklander const mbedtls_cipher_info_t *cipher_info; 850*817466cbSJens Wiklander int i, ret; 851*817466cbSJens Wiklander unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX]; 852*817466cbSJens Wiklander 853*817466cbSJens Wiklander cipher_info = mbedtls_cipher_info_from_type( cipher_type ); 854*817466cbSJens Wiklander if( cipher_info == NULL ) 855*817466cbSJens Wiklander { 856*817466cbSJens Wiklander /* Failing at this point must be due to a build issue */ 857*817466cbSJens Wiklander ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; 858*817466cbSJens Wiklander goto exit; 859*817466cbSJens Wiklander } 860*817466cbSJens Wiklander 861*817466cbSJens Wiklander for( i = 0; i < num_tests; i++ ) 862*817466cbSJens Wiklander { 863*817466cbSJens Wiklander if( verbose != 0 ) 864*817466cbSJens Wiklander mbedtls_printf( " %s CMAC #%u: ", testname, i + 1 ); 865*817466cbSJens Wiklander 866*817466cbSJens Wiklander if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages, 867*817466cbSJens Wiklander message_lengths[i], output ) ) != 0 ) 868*817466cbSJens Wiklander { 869*817466cbSJens Wiklander if( verbose != 0 ) 870*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 871*817466cbSJens Wiklander goto exit; 872*817466cbSJens Wiklander } 873*817466cbSJens Wiklander 874*817466cbSJens Wiklander if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 ) 875*817466cbSJens Wiklander { 876*817466cbSJens Wiklander if( verbose != 0 ) 877*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 878*817466cbSJens Wiklander goto exit; 879*817466cbSJens Wiklander } 880*817466cbSJens Wiklander 881*817466cbSJens Wiklander if( verbose != 0 ) 882*817466cbSJens Wiklander mbedtls_printf( "passed\n" ); 883*817466cbSJens Wiklander } 884*817466cbSJens Wiklander 885*817466cbSJens Wiklander exit: 886*817466cbSJens Wiklander return( ret ); 887*817466cbSJens Wiklander } 888*817466cbSJens Wiklander 889*817466cbSJens Wiklander #if defined(MBEDTLS_AES_C) 890*817466cbSJens Wiklander static int test_aes128_cmac_prf( int verbose ) 891*817466cbSJens Wiklander { 892*817466cbSJens Wiklander int i; 893*817466cbSJens Wiklander int ret; 894*817466cbSJens Wiklander unsigned char output[MBEDTLS_AES_BLOCK_SIZE]; 895*817466cbSJens Wiklander 896*817466cbSJens Wiklander for( i = 0; i < NB_PRF_TESTS; i++ ) 897*817466cbSJens Wiklander { 898*817466cbSJens Wiklander mbedtls_printf( " AES CMAC 128 PRF #%u: ", i ); 899*817466cbSJens Wiklander ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output ); 900*817466cbSJens Wiklander if( ret != 0 || 901*817466cbSJens Wiklander memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 ) 902*817466cbSJens Wiklander { 903*817466cbSJens Wiklander 904*817466cbSJens Wiklander if( verbose != 0 ) 905*817466cbSJens Wiklander mbedtls_printf( "failed\n" ); 906*817466cbSJens Wiklander 907*817466cbSJens Wiklander return( ret ); 908*817466cbSJens Wiklander } 909*817466cbSJens Wiklander else if( verbose != 0 ) 910*817466cbSJens Wiklander { 911*817466cbSJens Wiklander mbedtls_printf( "passed\n" ); 912*817466cbSJens Wiklander } 913*817466cbSJens Wiklander } 914*817466cbSJens Wiklander return( ret ); 915*817466cbSJens Wiklander } 916*817466cbSJens Wiklander #endif /* MBEDTLS_AES_C */ 917*817466cbSJens Wiklander 918*817466cbSJens Wiklander int mbedtls_cmac_self_test( int verbose ) 919*817466cbSJens Wiklander { 920*817466cbSJens Wiklander int ret; 921*817466cbSJens Wiklander 922*817466cbSJens Wiklander #if defined(MBEDTLS_AES_C) 923*817466cbSJens Wiklander /* AES-128 */ 924*817466cbSJens Wiklander if( ( ret = cmac_test_subkeys( verbose, 925*817466cbSJens Wiklander "AES 128", 926*817466cbSJens Wiklander aes_128_key, 927*817466cbSJens Wiklander 128, 928*817466cbSJens Wiklander (const unsigned char*)aes_128_subkeys, 929*817466cbSJens Wiklander MBEDTLS_CIPHER_AES_128_ECB, 930*817466cbSJens Wiklander MBEDTLS_AES_BLOCK_SIZE, 931*817466cbSJens Wiklander NB_CMAC_TESTS_PER_KEY ) ) != 0 ) 932*817466cbSJens Wiklander { 933*817466cbSJens Wiklander return( ret ); 934*817466cbSJens Wiklander } 935*817466cbSJens Wiklander 936*817466cbSJens Wiklander if( ( ret = cmac_test_wth_cipher( verbose, 937*817466cbSJens Wiklander "AES 128", 938*817466cbSJens Wiklander aes_128_key, 939*817466cbSJens Wiklander 128, 940*817466cbSJens Wiklander test_message, 941*817466cbSJens Wiklander aes_message_lengths, 942*817466cbSJens Wiklander (const unsigned char*)aes_128_expected_result, 943*817466cbSJens Wiklander MBEDTLS_CIPHER_AES_128_ECB, 944*817466cbSJens Wiklander MBEDTLS_AES_BLOCK_SIZE, 945*817466cbSJens Wiklander NB_CMAC_TESTS_PER_KEY ) ) != 0 ) 946*817466cbSJens Wiklander { 947*817466cbSJens Wiklander return( ret ); 948*817466cbSJens Wiklander } 949*817466cbSJens Wiklander 950*817466cbSJens Wiklander /* AES-192 */ 951*817466cbSJens Wiklander if( ( ret = cmac_test_subkeys( verbose, 952*817466cbSJens Wiklander "AES 192", 953*817466cbSJens Wiklander aes_192_key, 954*817466cbSJens Wiklander 192, 955*817466cbSJens Wiklander (const unsigned char*)aes_192_subkeys, 956*817466cbSJens Wiklander MBEDTLS_CIPHER_AES_192_ECB, 957*817466cbSJens Wiklander MBEDTLS_AES_BLOCK_SIZE, 958*817466cbSJens Wiklander NB_CMAC_TESTS_PER_KEY ) ) != 0 ) 959*817466cbSJens Wiklander { 960*817466cbSJens Wiklander return( ret ); 961*817466cbSJens Wiklander } 962*817466cbSJens Wiklander 963*817466cbSJens Wiklander if( ( ret = cmac_test_wth_cipher( verbose, 964*817466cbSJens Wiklander "AES 192", 965*817466cbSJens Wiklander aes_192_key, 966*817466cbSJens Wiklander 192, 967*817466cbSJens Wiklander test_message, 968*817466cbSJens Wiklander aes_message_lengths, 969*817466cbSJens Wiklander (const unsigned char*)aes_192_expected_result, 970*817466cbSJens Wiklander MBEDTLS_CIPHER_AES_192_ECB, 971*817466cbSJens Wiklander MBEDTLS_AES_BLOCK_SIZE, 972*817466cbSJens Wiklander NB_CMAC_TESTS_PER_KEY ) ) != 0 ) 973*817466cbSJens Wiklander { 974*817466cbSJens Wiklander return( ret ); 975*817466cbSJens Wiklander } 976*817466cbSJens Wiklander 977*817466cbSJens Wiklander /* AES-256 */ 978*817466cbSJens Wiklander if( ( ret = cmac_test_subkeys( verbose, 979*817466cbSJens Wiklander "AES 256", 980*817466cbSJens Wiklander aes_256_key, 981*817466cbSJens Wiklander 256, 982*817466cbSJens Wiklander (const unsigned char*)aes_256_subkeys, 983*817466cbSJens Wiklander MBEDTLS_CIPHER_AES_256_ECB, 984*817466cbSJens Wiklander MBEDTLS_AES_BLOCK_SIZE, 985*817466cbSJens Wiklander NB_CMAC_TESTS_PER_KEY ) ) != 0 ) 986*817466cbSJens Wiklander { 987*817466cbSJens Wiklander return( ret ); 988*817466cbSJens Wiklander } 989*817466cbSJens Wiklander 990*817466cbSJens Wiklander if( ( ret = cmac_test_wth_cipher ( verbose, 991*817466cbSJens Wiklander "AES 256", 992*817466cbSJens Wiklander aes_256_key, 993*817466cbSJens Wiklander 256, 994*817466cbSJens Wiklander test_message, 995*817466cbSJens Wiklander aes_message_lengths, 996*817466cbSJens Wiklander (const unsigned char*)aes_256_expected_result, 997*817466cbSJens Wiklander MBEDTLS_CIPHER_AES_256_ECB, 998*817466cbSJens Wiklander MBEDTLS_AES_BLOCK_SIZE, 999*817466cbSJens Wiklander NB_CMAC_TESTS_PER_KEY ) ) != 0 ) 1000*817466cbSJens Wiklander { 1001*817466cbSJens Wiklander return( ret ); 1002*817466cbSJens Wiklander } 1003*817466cbSJens Wiklander #endif /* MBEDTLS_AES_C */ 1004*817466cbSJens Wiklander 1005*817466cbSJens Wiklander #if defined(MBEDTLS_DES_C) 1006*817466cbSJens Wiklander /* 3DES 2 key */ 1007*817466cbSJens Wiklander if( ( ret = cmac_test_subkeys( verbose, 1008*817466cbSJens Wiklander "3DES 2 key", 1009*817466cbSJens Wiklander des3_2key_key, 1010*817466cbSJens Wiklander 192, 1011*817466cbSJens Wiklander (const unsigned char*)des3_2key_subkeys, 1012*817466cbSJens Wiklander MBEDTLS_CIPHER_DES_EDE3_ECB, 1013*817466cbSJens Wiklander MBEDTLS_DES3_BLOCK_SIZE, 1014*817466cbSJens Wiklander NB_CMAC_TESTS_PER_KEY ) ) != 0 ) 1015*817466cbSJens Wiklander { 1016*817466cbSJens Wiklander return( ret ); 1017*817466cbSJens Wiklander } 1018*817466cbSJens Wiklander 1019*817466cbSJens Wiklander if( ( ret = cmac_test_wth_cipher( verbose, 1020*817466cbSJens Wiklander "3DES 2 key", 1021*817466cbSJens Wiklander des3_2key_key, 1022*817466cbSJens Wiklander 192, 1023*817466cbSJens Wiklander test_message, 1024*817466cbSJens Wiklander des3_message_lengths, 1025*817466cbSJens Wiklander (const unsigned char*)des3_2key_expected_result, 1026*817466cbSJens Wiklander MBEDTLS_CIPHER_DES_EDE3_ECB, 1027*817466cbSJens Wiklander MBEDTLS_DES3_BLOCK_SIZE, 1028*817466cbSJens Wiklander NB_CMAC_TESTS_PER_KEY ) ) != 0 ) 1029*817466cbSJens Wiklander { 1030*817466cbSJens Wiklander return( ret ); 1031*817466cbSJens Wiklander } 1032*817466cbSJens Wiklander 1033*817466cbSJens Wiklander /* 3DES 3 key */ 1034*817466cbSJens Wiklander if( ( ret = cmac_test_subkeys( verbose, 1035*817466cbSJens Wiklander "3DES 3 key", 1036*817466cbSJens Wiklander des3_3key_key, 1037*817466cbSJens Wiklander 192, 1038*817466cbSJens Wiklander (const unsigned char*)des3_3key_subkeys, 1039*817466cbSJens Wiklander MBEDTLS_CIPHER_DES_EDE3_ECB, 1040*817466cbSJens Wiklander MBEDTLS_DES3_BLOCK_SIZE, 1041*817466cbSJens Wiklander NB_CMAC_TESTS_PER_KEY ) ) != 0 ) 1042*817466cbSJens Wiklander { 1043*817466cbSJens Wiklander return( ret ); 1044*817466cbSJens Wiklander } 1045*817466cbSJens Wiklander 1046*817466cbSJens Wiklander if( ( ret = cmac_test_wth_cipher( verbose, 1047*817466cbSJens Wiklander "3DES 3 key", 1048*817466cbSJens Wiklander des3_3key_key, 1049*817466cbSJens Wiklander 192, 1050*817466cbSJens Wiklander test_message, 1051*817466cbSJens Wiklander des3_message_lengths, 1052*817466cbSJens Wiklander (const unsigned char*)des3_3key_expected_result, 1053*817466cbSJens Wiklander MBEDTLS_CIPHER_DES_EDE3_ECB, 1054*817466cbSJens Wiklander MBEDTLS_DES3_BLOCK_SIZE, 1055*817466cbSJens Wiklander NB_CMAC_TESTS_PER_KEY ) ) != 0 ) 1056*817466cbSJens Wiklander { 1057*817466cbSJens Wiklander return( ret ); 1058*817466cbSJens Wiklander } 1059*817466cbSJens Wiklander #endif /* MBEDTLS_DES_C */ 1060*817466cbSJens Wiklander 1061*817466cbSJens Wiklander #if defined(MBEDTLS_AES_C) 1062*817466cbSJens Wiklander if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 ) 1063*817466cbSJens Wiklander return( ret ); 1064*817466cbSJens Wiklander #endif /* MBEDTLS_AES_C */ 1065*817466cbSJens Wiklander 1066*817466cbSJens Wiklander if( verbose != 0 ) 1067*817466cbSJens Wiklander mbedtls_printf( "\n" ); 1068*817466cbSJens Wiklander 1069*817466cbSJens Wiklander return( 0 ); 1070*817466cbSJens Wiklander } 1071*817466cbSJens Wiklander 1072*817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */ 1073*817466cbSJens Wiklander 1074*817466cbSJens Wiklander #endif /* MBEDTLS_CMAC_C */ 1075