2 * NIST SP800-38C compliant CCM implementation
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 * This file is part of mbed TLS (https://tls.mbed.org)
24 * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
25 * RFC 3610 "Counter with CBC-MAC (CCM)"
28 * RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
31 #if !defined(MBEDTLS_CONFIG_FILE)
32 #include "mbedtls/config.h"
34 #include MBEDTLS_CONFIG_FILE
37 #if defined(MBEDTLS_CCM_C)
39 #include "mbedtls/ccm.h"
40 #include "mbedtls/platform_util.h"
44 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
45 #if defined(MBEDTLS_PLATFORM_C)
46 #include "mbedtls/platform.h"
49 #define mbedtls_printf printf
50 #endif /* MBEDTLS_PLATFORM_C */
51 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
53 #if !defined(MBEDTLS_CCM_ALT)
55 #define CCM_VALIDATE_RET( cond ) \
56 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CCM_BAD_INPUT )
57 #define CCM_VALIDATE( cond ) \
58 MBEDTLS_INTERNAL_VALIDATE( cond )
66 void mbedtls_ccm_init( mbedtls_ccm_context *ctx )
68 CCM_VALIDATE( ctx != NULL );
69 memset( ctx, 0, sizeof( mbedtls_ccm_context ) );
72 int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
73 mbedtls_cipher_id_t cipher,
74 const unsigned char *key,
75 unsigned int keybits )
78 const mbedtls_cipher_info_t *cipher_info;
80 CCM_VALIDATE_RET( ctx != NULL );
81 CCM_VALIDATE_RET( key != NULL );
83 cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB );
84 if( cipher_info == NULL )
85 return( MBEDTLS_ERR_CCM_BAD_INPUT );
87 if( cipher_info->block_size != 16 )
88 return( MBEDTLS_ERR_CCM_BAD_INPUT );
90 mbedtls_cipher_free( &ctx->cipher_ctx );
92 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
95 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
96 MBEDTLS_ENCRYPT ) ) != 0 )
107 void mbedtls_ccm_free( mbedtls_ccm_context *ctx )
111 mbedtls_cipher_free( &ctx->cipher_ctx );
112 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ccm_context ) );
116 * Macros for common operations.
117 * Results in smaller compiled code than static inline functions.
121 * Update the CBC-MAC state in y using a block in b
122 * (Always using b as the source helps the compiler optimise a bit better.)
124 #define UPDATE_CBC_MAC \
125 for( i = 0; i < 16; i++ ) \
128 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \
132 * Encrypt or decrypt a partial block with CTR
133 * Warning: using b for temporary storage! src and dst must not be b!
134 * This avoids allocating one more 16 bytes buffer while allowing src == dst.
136 #define CTR_CRYPT( dst, src, len ) \
139 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctr, \
140 16, b, &olen ) ) != 0 ) \
145 for( i = 0; i < (len); i++ ) \
146 (dst)[i] = (src)[i] ^ b[i]; \
150 * Authenticated encryption or decryption
152 static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length,
153 const unsigned char *iv, size_t iv_len,
154 const unsigned char *add, size_t add_len,
155 const unsigned char *input, unsigned char *output,
156 unsigned char *tag, size_t tag_len )
161 size_t len_left, olen;
164 unsigned char ctr[16];
165 const unsigned char *src;
169 * Check length requirements: SP800-38C A.1
170 * Additional requirement: a < 2^16 - 2^8 to simplify the code.
171 * 'length' checked later (when writing it to the first block)
173 * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4).
175 if( tag_len == 2 || tag_len > 16 || tag_len % 2 != 0 )
176 return( MBEDTLS_ERR_CCM_BAD_INPUT );
178 /* Also implies q is within bounds */
179 if( iv_len < 7 || iv_len > 13 )
180 return( MBEDTLS_ERR_CCM_BAD_INPUT );
182 if( add_len > 0xFF00 )
183 return( MBEDTLS_ERR_CCM_BAD_INPUT );
185 q = 16 - 1 - (unsigned char) iv_len;
190 * 1 .. iv_len nonce (aka iv)
191 * iv_len+1 .. 15 length
193 * With flags as (bits):
200 b[0] |= ( add_len > 0 ) << 6;
201 b[0] |= ( ( tag_len - 2 ) / 2 ) << 3;
204 memcpy( b + 1, iv, iv_len );
206 for( i = 0, len_left = length; i < q; i++, len_left >>= 8 )
207 b[15-i] = (unsigned char)( len_left & 0xFF );
210 return( MBEDTLS_ERR_CCM_BAD_INPUT );
213 /* Start CBC-MAC with first block */
218 * If there is additional data, update CBC-MAC with
219 * add_len, add, 0 (padding to a block boundary)
228 b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF );
229 b[1] = (unsigned char)( ( add_len ) & 0xFF );
231 use_len = len_left < 16 - 2 ? len_left : 16 - 2;
232 memcpy( b + 2, src, use_len );
238 while( len_left > 0 )
240 use_len = len_left > 16 ? 16 : len_left;
243 memcpy( b, src, use_len );
252 * Prepare counter block for encryption:
254 * 1 .. iv_len nonce (aka iv)
255 * iv_len+1 .. 15 counter (initially 1)
257 * With flags as (bits):
262 memcpy( ctr + 1, iv, iv_len );
263 memset( ctr + 1 + iv_len, 0, q );
267 * Authenticate and {en,de}crypt the message.
269 * The only difference between encryption and decryption is
270 * the respective order of authentication and {en,de}cryption.
276 while( len_left > 0 )
278 size_t use_len = len_left > 16 ? 16 : len_left;
280 if( mode == CCM_ENCRYPT )
283 memcpy( b, src, use_len );
287 CTR_CRYPT( dst, src, use_len );
289 if( mode == CCM_DECRYPT )
292 memcpy( b, dst, use_len );
302 * No need to check for overflow thanks to the length check above.
304 for( i = 0; i < q; i++ )
305 if( ++ctr[15-i] != 0 )
310 * Authentication: reset counter and crypt/mask internal tag
312 for( i = 0; i < q; i++ )
315 CTR_CRYPT( y, y, 16 );
316 memcpy( tag, y, tag_len );
322 * Authenticated encryption
324 int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
325 const unsigned char *iv, size_t iv_len,
326 const unsigned char *add, size_t add_len,
327 const unsigned char *input, unsigned char *output,
328 unsigned char *tag, size_t tag_len )
330 CCM_VALIDATE_RET( ctx != NULL );
331 CCM_VALIDATE_RET( iv != NULL );
332 CCM_VALIDATE_RET( add_len == 0 || add != NULL );
333 CCM_VALIDATE_RET( length == 0 || input != NULL );
334 CCM_VALIDATE_RET( length == 0 || output != NULL );
335 CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
336 return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len,
337 add, add_len, input, output, tag, tag_len ) );
340 int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
341 const unsigned char *iv, size_t iv_len,
342 const unsigned char *add, size_t add_len,
343 const unsigned char *input, unsigned char *output,
344 unsigned char *tag, size_t tag_len )
346 CCM_VALIDATE_RET( ctx != NULL );
347 CCM_VALIDATE_RET( iv != NULL );
348 CCM_VALIDATE_RET( add_len == 0 || add != NULL );
349 CCM_VALIDATE_RET( length == 0 || input != NULL );
350 CCM_VALIDATE_RET( length == 0 || output != NULL );
351 CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
353 return( MBEDTLS_ERR_CCM_BAD_INPUT );
355 return( mbedtls_ccm_star_encrypt_and_tag( ctx, length, iv, iv_len, add,
356 add_len, input, output, tag, tag_len ) );
360 * Authenticated decryption
362 int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
363 const unsigned char *iv, size_t iv_len,
364 const unsigned char *add, size_t add_len,
365 const unsigned char *input, unsigned char *output,
366 const unsigned char *tag, size_t tag_len )
369 unsigned char check_tag[16];
373 CCM_VALIDATE_RET( ctx != NULL );
374 CCM_VALIDATE_RET( iv != NULL );
375 CCM_VALIDATE_RET( add_len == 0 || add != NULL );
376 CCM_VALIDATE_RET( length == 0 || input != NULL );
377 CCM_VALIDATE_RET( length == 0 || output != NULL );
378 CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
380 if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length,
381 iv, iv_len, add, add_len,
382 input, output, check_tag, tag_len ) ) != 0 )
387 /* Check tag in "constant-time" */
388 for( diff = 0, i = 0; i < tag_len; i++ )
389 diff |= tag[i] ^ check_tag[i];
393 mbedtls_platform_zeroize( output, length );
394 return( MBEDTLS_ERR_CCM_AUTH_FAILED );
400 int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
401 const unsigned char *iv, size_t iv_len,
402 const unsigned char *add, size_t add_len,
403 const unsigned char *input, unsigned char *output,
404 const unsigned char *tag, size_t tag_len )
406 CCM_VALIDATE_RET( ctx != NULL );
407 CCM_VALIDATE_RET( iv != NULL );
408 CCM_VALIDATE_RET( add_len == 0 || add != NULL );
409 CCM_VALIDATE_RET( length == 0 || input != NULL );
410 CCM_VALIDATE_RET( length == 0 || output != NULL );
411 CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
414 return( MBEDTLS_ERR_CCM_BAD_INPUT );
416 return( mbedtls_ccm_star_auth_decrypt( ctx, length, iv, iv_len, add,
417 add_len, input, output, tag, tag_len ) );
419 #endif /* !MBEDTLS_CCM_ALT */
421 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
423 * Examples 1 to 3 from SP800-38C Appendix C
427 #define CCM_SELFTEST_PT_MAX_LEN 24
428 #define CCM_SELFTEST_CT_MAX_LEN 32
430 * The data is the same for all tests, only the used length changes
432 static const unsigned char key[] = {
433 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
434 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
437 static const unsigned char iv[] = {
438 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
439 0x18, 0x19, 0x1a, 0x1b
442 static const unsigned char ad[] = {
443 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
444 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
445 0x10, 0x11, 0x12, 0x13
448 static const unsigned char msg[CCM_SELFTEST_PT_MAX_LEN] = {
449 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
450 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
451 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
454 static const size_t iv_len [NB_TESTS] = { 7, 8, 12 };
455 static const size_t add_len[NB_TESTS] = { 8, 16, 20 };
456 static const size_t msg_len[NB_TESTS] = { 4, 16, 24 };
457 static const size_t tag_len[NB_TESTS] = { 4, 6, 8 };
459 static const unsigned char res[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = {
460 { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
461 { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
462 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
463 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd },
464 { 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a,
465 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b,
466 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5,
467 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 }
470 int mbedtls_ccm_self_test( int verbose )
472 mbedtls_ccm_context ctx;
474 * Some hardware accelerators require the input and output buffers
475 * would be in RAM, because the flash is not accessible.
476 * Use buffers on the stack to hold the test vectors data.
478 unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN];
479 unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN];
483 mbedtls_ccm_init( &ctx );
485 if( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 )
488 mbedtls_printf( " CCM: setup failed" );
493 for( i = 0; i < NB_TESTS; i++ )
496 mbedtls_printf( " CCM-AES #%u: ", (unsigned int) i + 1 );
498 memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN );
499 memset( ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN );
500 memcpy( plaintext, msg, msg_len[i] );
502 ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i],
503 iv, iv_len[i], ad, add_len[i],
504 plaintext, ciphertext,
505 ciphertext + msg_len[i], tag_len[i] );
508 memcmp( ciphertext, res[i], msg_len[i] + tag_len[i] ) != 0 )
511 mbedtls_printf( "failed\n" );
515 memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN );
517 ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i],
518 iv, iv_len[i], ad, add_len[i],
519 ciphertext, plaintext,
520 ciphertext + msg_len[i], tag_len[i] );
523 memcmp( plaintext, msg, msg_len[i] ) != 0 )
526 mbedtls_printf( "failed\n" );
532 mbedtls_printf( "passed\n" );
535 mbedtls_ccm_free( &ctx );
538 mbedtls_printf( "\n" );
543 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
545 #endif /* MBEDTLS_CCM_C */