mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

Committer:
ansond
Date:
Thu Jun 11 03:27:03 2015 +0000
Revision:
0:137634ff4186
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:137634ff4186 1 /*
ansond 0:137634ff4186 2 * NIST SP800-38C compliant CCM implementation
ansond 0:137634ff4186 3 *
ansond 0:137634ff4186 4 * Copyright (C) 2014, ARM Limited, All Rights Reserved
ansond 0:137634ff4186 5 *
ansond 0:137634ff4186 6 * This file is part of mbed TLS (https://tls.mbed.org)
ansond 0:137634ff4186 7 *
ansond 0:137634ff4186 8 * This program is free software; you can redistribute it and/or modify
ansond 0:137634ff4186 9 * it under the terms of the GNU General Public License as published by
ansond 0:137634ff4186 10 * the Free Software Foundation; either version 2 of the License, or
ansond 0:137634ff4186 11 * (at your option) any later version.
ansond 0:137634ff4186 12 *
ansond 0:137634ff4186 13 * This program is distributed in the hope that it will be useful,
ansond 0:137634ff4186 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ansond 0:137634ff4186 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ansond 0:137634ff4186 16 * GNU General Public License for more details.
ansond 0:137634ff4186 17 *
ansond 0:137634ff4186 18 * You should have received a copy of the GNU General Public License along
ansond 0:137634ff4186 19 * with this program; if not, write to the Free Software Foundation, Inc.,
ansond 0:137634ff4186 20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ansond 0:137634ff4186 21 */
ansond 0:137634ff4186 22
ansond 0:137634ff4186 23 /*
ansond 0:137634ff4186 24 * Definition of CCM:
ansond 0:137634ff4186 25 * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
ansond 0:137634ff4186 26 * RFC 3610 "Counter with CBC-MAC (CCM)"
ansond 0:137634ff4186 27 *
ansond 0:137634ff4186 28 * Related:
ansond 0:137634ff4186 29 * RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
ansond 0:137634ff4186 30 */
ansond 0:137634ff4186 31
ansond 0:137634ff4186 32 #if !defined(POLARSSL_CONFIG_FILE)
ansond 0:137634ff4186 33 #include "polarssl/config.h"
ansond 0:137634ff4186 34 #else
ansond 0:137634ff4186 35 #include POLARSSL_CONFIG_FILE
ansond 0:137634ff4186 36 #endif
ansond 0:137634ff4186 37
ansond 0:137634ff4186 38 #if defined(POLARSSL_CCM_C)
ansond 0:137634ff4186 39
ansond 0:137634ff4186 40 #include "polarssl/ccm.h"
ansond 0:137634ff4186 41
ansond 0:137634ff4186 42 #include <string.h>
ansond 0:137634ff4186 43
ansond 0:137634ff4186 44 #if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
ansond 0:137634ff4186 45 #if defined(POLARSSL_PLATFORM_C)
ansond 0:137634ff4186 46 #include "polarssl/platform.h"
ansond 0:137634ff4186 47 #else
ansond 0:137634ff4186 48 #include <stdio.h>
ansond 0:137634ff4186 49 #define polarssl_printf printf
ansond 0:137634ff4186 50 #endif /* POLARSSL_PLATFORM_C */
ansond 0:137634ff4186 51 #endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
ansond 0:137634ff4186 52
ansond 0:137634ff4186 53 /* Implementation that should never be optimized out by the compiler */
ansond 0:137634ff4186 54 static void polarssl_zeroize( void *v, size_t n ) {
ansond 0:137634ff4186 55 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
ansond 0:137634ff4186 56 }
ansond 0:137634ff4186 57
ansond 0:137634ff4186 58 #define CCM_ENCRYPT 0
ansond 0:137634ff4186 59 #define CCM_DECRYPT 1
ansond 0:137634ff4186 60
ansond 0:137634ff4186 61 /*
ansond 0:137634ff4186 62 * Initialize context
ansond 0:137634ff4186 63 */
ansond 0:137634ff4186 64 int ccm_init( ccm_context *ctx, cipher_id_t cipher,
ansond 0:137634ff4186 65 const unsigned char *key, unsigned int keysize )
ansond 0:137634ff4186 66 {
ansond 0:137634ff4186 67 int ret;
ansond 0:137634ff4186 68 const cipher_info_t *cipher_info;
ansond 0:137634ff4186 69
ansond 0:137634ff4186 70 memset( ctx, 0, sizeof( ccm_context ) );
ansond 0:137634ff4186 71
ansond 0:137634ff4186 72 cipher_init( &ctx->cipher_ctx );
ansond 0:137634ff4186 73
ansond 0:137634ff4186 74 cipher_info = cipher_info_from_values( cipher, keysize, POLARSSL_MODE_ECB );
ansond 0:137634ff4186 75 if( cipher_info == NULL )
ansond 0:137634ff4186 76 return( POLARSSL_ERR_CCM_BAD_INPUT );
ansond 0:137634ff4186 77
ansond 0:137634ff4186 78 if( cipher_info->block_size != 16 )
ansond 0:137634ff4186 79 return( POLARSSL_ERR_CCM_BAD_INPUT );
ansond 0:137634ff4186 80
ansond 0:137634ff4186 81 cipher_free( &ctx->cipher_ctx );
ansond 0:137634ff4186 82
ansond 0:137634ff4186 83 if( ( ret = cipher_init_ctx( &ctx->cipher_ctx, cipher_info ) ) != 0 )
ansond 0:137634ff4186 84 return( ret );
ansond 0:137634ff4186 85
ansond 0:137634ff4186 86 if( ( ret = cipher_setkey( &ctx->cipher_ctx, key, keysize,
ansond 0:137634ff4186 87 POLARSSL_ENCRYPT ) ) != 0 )
ansond 0:137634ff4186 88 {
ansond 0:137634ff4186 89 return( ret );
ansond 0:137634ff4186 90 }
ansond 0:137634ff4186 91
ansond 0:137634ff4186 92 return( 0 );
ansond 0:137634ff4186 93 }
ansond 0:137634ff4186 94
ansond 0:137634ff4186 95 /*
ansond 0:137634ff4186 96 * Free context
ansond 0:137634ff4186 97 */
ansond 0:137634ff4186 98 void ccm_free( ccm_context *ctx )
ansond 0:137634ff4186 99 {
ansond 0:137634ff4186 100 cipher_free( &ctx->cipher_ctx );
ansond 0:137634ff4186 101 polarssl_zeroize( ctx, sizeof( ccm_context ) );
ansond 0:137634ff4186 102 }
ansond 0:137634ff4186 103
ansond 0:137634ff4186 104 /*
ansond 0:137634ff4186 105 * Macros for common operations.
ansond 0:137634ff4186 106 * Results in smaller compiled code than static inline functions.
ansond 0:137634ff4186 107 */
ansond 0:137634ff4186 108
ansond 0:137634ff4186 109 /*
ansond 0:137634ff4186 110 * Update the CBC-MAC state in y using a block in b
ansond 0:137634ff4186 111 * (Always using b as the source helps the compiler optimise a bit better.)
ansond 0:137634ff4186 112 */
ansond 0:137634ff4186 113 #define UPDATE_CBC_MAC \
ansond 0:137634ff4186 114 for( i = 0; i < 16; i++ ) \
ansond 0:137634ff4186 115 y[i] ^= b[i]; \
ansond 0:137634ff4186 116 \
ansond 0:137634ff4186 117 if( ( ret = cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \
ansond 0:137634ff4186 118 return( ret );
ansond 0:137634ff4186 119
ansond 0:137634ff4186 120 /*
ansond 0:137634ff4186 121 * Encrypt or decrypt a partial block with CTR
ansond 0:137634ff4186 122 * Warning: using b for temporary storage! src and dst must not be b!
ansond 0:137634ff4186 123 * This avoids allocating one more 16 bytes buffer while allowing src == dst.
ansond 0:137634ff4186 124 */
ansond 0:137634ff4186 125 #define CTR_CRYPT( dst, src, len ) \
ansond 0:137634ff4186 126 if( ( ret = cipher_update( &ctx->cipher_ctx, ctr, 16, b, &olen ) ) != 0 ) \
ansond 0:137634ff4186 127 return( ret ); \
ansond 0:137634ff4186 128 \
ansond 0:137634ff4186 129 for( i = 0; i < len; i++ ) \
ansond 0:137634ff4186 130 dst[i] = src[i] ^ b[i];
ansond 0:137634ff4186 131
ansond 0:137634ff4186 132 /*
ansond 0:137634ff4186 133 * Authenticated encryption or decryption
ansond 0:137634ff4186 134 */
ansond 0:137634ff4186 135 static int ccm_auth_crypt( ccm_context *ctx, int mode, size_t length,
ansond 0:137634ff4186 136 const unsigned char *iv, size_t iv_len,
ansond 0:137634ff4186 137 const unsigned char *add, size_t add_len,
ansond 0:137634ff4186 138 const unsigned char *input, unsigned char *output,
ansond 0:137634ff4186 139 unsigned char *tag, size_t tag_len )
ansond 0:137634ff4186 140 {
ansond 0:137634ff4186 141 int ret;
ansond 0:137634ff4186 142 unsigned char i;
ansond 0:137634ff4186 143 unsigned char q = 16 - 1 - iv_len;
ansond 0:137634ff4186 144 size_t len_left, olen;
ansond 0:137634ff4186 145 unsigned char b[16];
ansond 0:137634ff4186 146 unsigned char y[16];
ansond 0:137634ff4186 147 unsigned char ctr[16];
ansond 0:137634ff4186 148 const unsigned char *src;
ansond 0:137634ff4186 149 unsigned char *dst;
ansond 0:137634ff4186 150
ansond 0:137634ff4186 151 /*
ansond 0:137634ff4186 152 * Check length requirements: SP800-38C A.1
ansond 0:137634ff4186 153 * Additional requirement: a < 2^16 - 2^8 to simplify the code.
ansond 0:137634ff4186 154 * 'length' checked later (when writing it to the first block)
ansond 0:137634ff4186 155 */
ansond 0:137634ff4186 156 if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
ansond 0:137634ff4186 157 return( POLARSSL_ERR_CCM_BAD_INPUT );
ansond 0:137634ff4186 158
ansond 0:137634ff4186 159 /* Also implies q is within bounds */
ansond 0:137634ff4186 160 if( iv_len < 7 || iv_len > 13 )
ansond 0:137634ff4186 161 return( POLARSSL_ERR_CCM_BAD_INPUT );
ansond 0:137634ff4186 162
ansond 0:137634ff4186 163 if( add_len > 0xFF00 )
ansond 0:137634ff4186 164 return( POLARSSL_ERR_CCM_BAD_INPUT );
ansond 0:137634ff4186 165
ansond 0:137634ff4186 166 /*
ansond 0:137634ff4186 167 * First block B_0:
ansond 0:137634ff4186 168 * 0 .. 0 flags
ansond 0:137634ff4186 169 * 1 .. iv_len nonce (aka iv)
ansond 0:137634ff4186 170 * iv_len+1 .. 15 length
ansond 0:137634ff4186 171 *
ansond 0:137634ff4186 172 * With flags as (bits):
ansond 0:137634ff4186 173 * 7 0
ansond 0:137634ff4186 174 * 6 add present?
ansond 0:137634ff4186 175 * 5 .. 3 (t - 2) / 2
ansond 0:137634ff4186 176 * 2 .. 0 q - 1
ansond 0:137634ff4186 177 */
ansond 0:137634ff4186 178 b[0] = 0;
ansond 0:137634ff4186 179 b[0] |= ( add_len > 0 ) << 6;
ansond 0:137634ff4186 180 b[0] |= ( ( tag_len - 2 ) / 2 ) << 3;
ansond 0:137634ff4186 181 b[0] |= q - 1;
ansond 0:137634ff4186 182
ansond 0:137634ff4186 183 memcpy( b + 1, iv, iv_len );
ansond 0:137634ff4186 184
ansond 0:137634ff4186 185 for( i = 0, len_left = length; i < q; i++, len_left >>= 8 )
ansond 0:137634ff4186 186 b[15-i] = (unsigned char)( len_left & 0xFF );
ansond 0:137634ff4186 187
ansond 0:137634ff4186 188 if( len_left > 0 )
ansond 0:137634ff4186 189 return( POLARSSL_ERR_CCM_BAD_INPUT );
ansond 0:137634ff4186 190
ansond 0:137634ff4186 191
ansond 0:137634ff4186 192 /* Start CBC-MAC with first block */
ansond 0:137634ff4186 193 memset( y, 0, 16 );
ansond 0:137634ff4186 194 UPDATE_CBC_MAC;
ansond 0:137634ff4186 195
ansond 0:137634ff4186 196 /*
ansond 0:137634ff4186 197 * If there is additional data, update CBC-MAC with
ansond 0:137634ff4186 198 * add_len, add, 0 (padding to a block boundary)
ansond 0:137634ff4186 199 */
ansond 0:137634ff4186 200 if( add_len > 0 )
ansond 0:137634ff4186 201 {
ansond 0:137634ff4186 202 size_t use_len;
ansond 0:137634ff4186 203 len_left = add_len;
ansond 0:137634ff4186 204 src = add;
ansond 0:137634ff4186 205
ansond 0:137634ff4186 206 memset( b, 0, 16 );
ansond 0:137634ff4186 207 b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF );
ansond 0:137634ff4186 208 b[1] = (unsigned char)( ( add_len ) & 0xFF );
ansond 0:137634ff4186 209
ansond 0:137634ff4186 210 use_len = len_left < 16 - 2 ? len_left : 16 - 2;
ansond 0:137634ff4186 211 memcpy( b + 2, src, use_len );
ansond 0:137634ff4186 212 len_left -= use_len;
ansond 0:137634ff4186 213 src += use_len;
ansond 0:137634ff4186 214
ansond 0:137634ff4186 215 UPDATE_CBC_MAC;
ansond 0:137634ff4186 216
ansond 0:137634ff4186 217 while( len_left > 0 )
ansond 0:137634ff4186 218 {
ansond 0:137634ff4186 219 use_len = len_left > 16 ? 16 : len_left;
ansond 0:137634ff4186 220
ansond 0:137634ff4186 221 memset( b, 0, 16 );
ansond 0:137634ff4186 222 memcpy( b, src, use_len );
ansond 0:137634ff4186 223 UPDATE_CBC_MAC;
ansond 0:137634ff4186 224
ansond 0:137634ff4186 225 len_left -= use_len;
ansond 0:137634ff4186 226 src += use_len;
ansond 0:137634ff4186 227 }
ansond 0:137634ff4186 228 }
ansond 0:137634ff4186 229
ansond 0:137634ff4186 230 /*
ansond 0:137634ff4186 231 * Prepare counter block for encryption:
ansond 0:137634ff4186 232 * 0 .. 0 flags
ansond 0:137634ff4186 233 * 1 .. iv_len nonce (aka iv)
ansond 0:137634ff4186 234 * iv_len+1 .. 15 counter (initially 1)
ansond 0:137634ff4186 235 *
ansond 0:137634ff4186 236 * With flags as (bits):
ansond 0:137634ff4186 237 * 7 .. 3 0
ansond 0:137634ff4186 238 * 2 .. 0 q - 1
ansond 0:137634ff4186 239 */
ansond 0:137634ff4186 240 ctr[0] = q - 1;
ansond 0:137634ff4186 241 memcpy( ctr + 1, iv, iv_len );
ansond 0:137634ff4186 242 memset( ctr + 1 + iv_len, 0, q );
ansond 0:137634ff4186 243 ctr[15] = 1;
ansond 0:137634ff4186 244
ansond 0:137634ff4186 245 /*
ansond 0:137634ff4186 246 * Authenticate and {en,de}crypt the message.
ansond 0:137634ff4186 247 *
ansond 0:137634ff4186 248 * The only difference between encryption and decryption is
ansond 0:137634ff4186 249 * the respective order of authentication and {en,de}cryption.
ansond 0:137634ff4186 250 */
ansond 0:137634ff4186 251 len_left = length;
ansond 0:137634ff4186 252 src = input;
ansond 0:137634ff4186 253 dst = output;
ansond 0:137634ff4186 254
ansond 0:137634ff4186 255 while( len_left > 0 )
ansond 0:137634ff4186 256 {
ansond 0:137634ff4186 257 unsigned char use_len = len_left > 16 ? 16 : len_left;
ansond 0:137634ff4186 258
ansond 0:137634ff4186 259 if( mode == CCM_ENCRYPT )
ansond 0:137634ff4186 260 {
ansond 0:137634ff4186 261 memset( b, 0, 16 );
ansond 0:137634ff4186 262 memcpy( b, src, use_len );
ansond 0:137634ff4186 263 UPDATE_CBC_MAC;
ansond 0:137634ff4186 264 }
ansond 0:137634ff4186 265
ansond 0:137634ff4186 266 CTR_CRYPT( dst, src, use_len );
ansond 0:137634ff4186 267
ansond 0:137634ff4186 268 if( mode == CCM_DECRYPT )
ansond 0:137634ff4186 269 {
ansond 0:137634ff4186 270 memset( b, 0, 16 );
ansond 0:137634ff4186 271 memcpy( b, dst, use_len );
ansond 0:137634ff4186 272 UPDATE_CBC_MAC;
ansond 0:137634ff4186 273 }
ansond 0:137634ff4186 274
ansond 0:137634ff4186 275 dst += use_len;
ansond 0:137634ff4186 276 src += use_len;
ansond 0:137634ff4186 277 len_left -= use_len;
ansond 0:137634ff4186 278
ansond 0:137634ff4186 279 /*
ansond 0:137634ff4186 280 * Increment counter.
ansond 0:137634ff4186 281 * No need to check for overflow thanks to the length check above.
ansond 0:137634ff4186 282 */
ansond 0:137634ff4186 283 for( i = 0; i < q; i++ )
ansond 0:137634ff4186 284 if( ++ctr[15-i] != 0 )
ansond 0:137634ff4186 285 break;
ansond 0:137634ff4186 286 }
ansond 0:137634ff4186 287
ansond 0:137634ff4186 288 /*
ansond 0:137634ff4186 289 * Authentication: reset counter and crypt/mask internal tag
ansond 0:137634ff4186 290 */
ansond 0:137634ff4186 291 for( i = 0; i < q; i++ )
ansond 0:137634ff4186 292 ctr[15-i] = 0;
ansond 0:137634ff4186 293
ansond 0:137634ff4186 294 CTR_CRYPT( y, y, 16 );
ansond 0:137634ff4186 295 memcpy( tag, y, tag_len );
ansond 0:137634ff4186 296
ansond 0:137634ff4186 297 return( 0 );
ansond 0:137634ff4186 298 }
ansond 0:137634ff4186 299
ansond 0:137634ff4186 300 /*
ansond 0:137634ff4186 301 * Authenticated encryption
ansond 0:137634ff4186 302 */
ansond 0:137634ff4186 303 int ccm_encrypt_and_tag( ccm_context *ctx, size_t length,
ansond 0:137634ff4186 304 const unsigned char *iv, size_t iv_len,
ansond 0:137634ff4186 305 const unsigned char *add, size_t add_len,
ansond 0:137634ff4186 306 const unsigned char *input, unsigned char *output,
ansond 0:137634ff4186 307 unsigned char *tag, size_t tag_len )
ansond 0:137634ff4186 308 {
ansond 0:137634ff4186 309 return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len,
ansond 0:137634ff4186 310 add, add_len, input, output, tag, tag_len ) );
ansond 0:137634ff4186 311 }
ansond 0:137634ff4186 312
ansond 0:137634ff4186 313 /*
ansond 0:137634ff4186 314 * Authenticated decryption
ansond 0:137634ff4186 315 */
ansond 0:137634ff4186 316 int ccm_auth_decrypt( ccm_context *ctx, size_t length,
ansond 0:137634ff4186 317 const unsigned char *iv, size_t iv_len,
ansond 0:137634ff4186 318 const unsigned char *add, size_t add_len,
ansond 0:137634ff4186 319 const unsigned char *input, unsigned char *output,
ansond 0:137634ff4186 320 const unsigned char *tag, size_t tag_len )
ansond 0:137634ff4186 321 {
ansond 0:137634ff4186 322 int ret;
ansond 0:137634ff4186 323 unsigned char check_tag[16];
ansond 0:137634ff4186 324 unsigned char i;
ansond 0:137634ff4186 325 int diff;
ansond 0:137634ff4186 326
ansond 0:137634ff4186 327 if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length,
ansond 0:137634ff4186 328 iv, iv_len, add, add_len,
ansond 0:137634ff4186 329 input, output, check_tag, tag_len ) ) != 0 )
ansond 0:137634ff4186 330 {
ansond 0:137634ff4186 331 return( ret );
ansond 0:137634ff4186 332 }
ansond 0:137634ff4186 333
ansond 0:137634ff4186 334 /* Check tag in "constant-time" */
ansond 0:137634ff4186 335 for( diff = 0, i = 0; i < tag_len; i++ )
ansond 0:137634ff4186 336 diff |= tag[i] ^ check_tag[i];
ansond 0:137634ff4186 337
ansond 0:137634ff4186 338 if( diff != 0 )
ansond 0:137634ff4186 339 {
ansond 0:137634ff4186 340 polarssl_zeroize( output, length );
ansond 0:137634ff4186 341 return( POLARSSL_ERR_CCM_AUTH_FAILED );
ansond 0:137634ff4186 342 }
ansond 0:137634ff4186 343
ansond 0:137634ff4186 344 return( 0 );
ansond 0:137634ff4186 345 }
ansond 0:137634ff4186 346
ansond 0:137634ff4186 347
ansond 0:137634ff4186 348 #if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
ansond 0:137634ff4186 349 /*
ansond 0:137634ff4186 350 * Examples 1 to 3 from SP800-38C Appendix C
ansond 0:137634ff4186 351 */
ansond 0:137634ff4186 352
ansond 0:137634ff4186 353 #define NB_TESTS 3
ansond 0:137634ff4186 354
ansond 0:137634ff4186 355 /*
ansond 0:137634ff4186 356 * The data is the same for all tests, only the used length changes
ansond 0:137634ff4186 357 */
ansond 0:137634ff4186 358 static const unsigned char key[] = {
ansond 0:137634ff4186 359 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
ansond 0:137634ff4186 360 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
ansond 0:137634ff4186 361 };
ansond 0:137634ff4186 362
ansond 0:137634ff4186 363 static const unsigned char iv[] = {
ansond 0:137634ff4186 364 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
ansond 0:137634ff4186 365 0x18, 0x19, 0x1a, 0x1b
ansond 0:137634ff4186 366 };
ansond 0:137634ff4186 367
ansond 0:137634ff4186 368 static const unsigned char ad[] = {
ansond 0:137634ff4186 369 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
ansond 0:137634ff4186 370 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
ansond 0:137634ff4186 371 0x10, 0x11, 0x12, 0x13
ansond 0:137634ff4186 372 };
ansond 0:137634ff4186 373
ansond 0:137634ff4186 374 static const unsigned char msg[] = {
ansond 0:137634ff4186 375 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
ansond 0:137634ff4186 376 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
ansond 0:137634ff4186 377 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
ansond 0:137634ff4186 378 };
ansond 0:137634ff4186 379
ansond 0:137634ff4186 380 static const size_t iv_len [NB_TESTS] = { 7, 8, 12 };
ansond 0:137634ff4186 381 static const size_t add_len[NB_TESTS] = { 8, 16, 20 };
ansond 0:137634ff4186 382 static const size_t msg_len[NB_TESTS] = { 4, 16, 24 };
ansond 0:137634ff4186 383 static const size_t tag_len[NB_TESTS] = { 4, 6, 8 };
ansond 0:137634ff4186 384
ansond 0:137634ff4186 385 static const unsigned char res[NB_TESTS][32] = {
ansond 0:137634ff4186 386 { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
ansond 0:137634ff4186 387 { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
ansond 0:137634ff4186 388 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
ansond 0:137634ff4186 389 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd },
ansond 0:137634ff4186 390 { 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a,
ansond 0:137634ff4186 391 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b,
ansond 0:137634ff4186 392 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5,
ansond 0:137634ff4186 393 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 }
ansond 0:137634ff4186 394 };
ansond 0:137634ff4186 395
ansond 0:137634ff4186 396 int ccm_self_test( int verbose )
ansond 0:137634ff4186 397 {
ansond 0:137634ff4186 398 ccm_context ctx;
ansond 0:137634ff4186 399 unsigned char out[32];
ansond 0:137634ff4186 400 size_t i;
ansond 0:137634ff4186 401 int ret;
ansond 0:137634ff4186 402
ansond 0:137634ff4186 403 if( ccm_init( &ctx, POLARSSL_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 )
ansond 0:137634ff4186 404 {
ansond 0:137634ff4186 405 if( verbose != 0 )
ansond 0:137634ff4186 406 polarssl_printf( " CCM: setup failed" );
ansond 0:137634ff4186 407
ansond 0:137634ff4186 408 return( 1 );
ansond 0:137634ff4186 409 }
ansond 0:137634ff4186 410
ansond 0:137634ff4186 411 for( i = 0; i < NB_TESTS; i++ )
ansond 0:137634ff4186 412 {
ansond 0:137634ff4186 413 if( verbose != 0 )
ansond 0:137634ff4186 414 polarssl_printf( " CCM-AES #%u: ", (unsigned int) i + 1 );
ansond 0:137634ff4186 415
ansond 0:137634ff4186 416 ret = ccm_encrypt_and_tag( &ctx, msg_len[i],
ansond 0:137634ff4186 417 iv, iv_len[i], ad, add_len[i],
ansond 0:137634ff4186 418 msg, out,
ansond 0:137634ff4186 419 out + msg_len[i], tag_len[i] );
ansond 0:137634ff4186 420
ansond 0:137634ff4186 421 if( ret != 0 ||
ansond 0:137634ff4186 422 memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 )
ansond 0:137634ff4186 423 {
ansond 0:137634ff4186 424 if( verbose != 0 )
ansond 0:137634ff4186 425 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 426
ansond 0:137634ff4186 427 return( 1 );
ansond 0:137634ff4186 428 }
ansond 0:137634ff4186 429
ansond 0:137634ff4186 430 ret = ccm_auth_decrypt( &ctx, msg_len[i],
ansond 0:137634ff4186 431 iv, iv_len[i], ad, add_len[i],
ansond 0:137634ff4186 432 res[i], out,
ansond 0:137634ff4186 433 res[i] + msg_len[i], tag_len[i] );
ansond 0:137634ff4186 434
ansond 0:137634ff4186 435 if( ret != 0 ||
ansond 0:137634ff4186 436 memcmp( out, msg, msg_len[i] ) != 0 )
ansond 0:137634ff4186 437 {
ansond 0:137634ff4186 438 if( verbose != 0 )
ansond 0:137634ff4186 439 polarssl_printf( "failed\n" );
ansond 0:137634ff4186 440
ansond 0:137634ff4186 441 return( 1 );
ansond 0:137634ff4186 442 }
ansond 0:137634ff4186 443
ansond 0:137634ff4186 444 if( verbose != 0 )
ansond 0:137634ff4186 445 polarssl_printf( "passed\n" );
ansond 0:137634ff4186 446 }
ansond 0:137634ff4186 447
ansond 0:137634ff4186 448 ccm_free( &ctx );
ansond 0:137634ff4186 449
ansond 0:137634ff4186 450 if( verbose != 0 )
ansond 0:137634ff4186 451 polarssl_printf( "\n" );
ansond 0:137634ff4186 452
ansond 0:137634ff4186 453 return( 0 );
ansond 0:137634ff4186 454 }
ansond 0:137634ff4186 455
ansond 0:137634ff4186 456 #endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
ansond 0:137634ff4186 457
ansond 0:137634ff4186 458 #endif /* POLARSSL_CCM_C */
ansond 0:137634ff4186 459