mbed os with nrf51 internal bandgap enabled to read battery level

Dependents:   BLE_file_test BLE_Blink ExternalEncoder

Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

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