Pinned to some recent date

Committer:
Simon Cooksey
Date:
Thu Nov 17 16:43:53 2016 +0000
Revision:
0:fb7af294d5d9
Initial commit

Who changed what in which revision?

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