2 * NIST SP800-38C compliant CCM implementation
4 * Copyright (C) 2014, ARM Limited, All Rights Reserved
6 * This file is part of mbed TLS (https://polarssl.org)
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
26 * RFC 3610 "Counter with CBC-MAC (CCM)"
29 * RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
32 #if !defined(POLARSSL_CONFIG_FILE)
33 #include "polarssl/config.h"
35 #include POLARSSL_CONFIG_FILE
38 #if defined(POLARSSL_CCM_C)
40 #include "polarssl/ccm.h"
42 /* Implementation that should never be optimized out by the compiler */
43 static void polarssl_zeroize( void *v
, size_t n
) {
44 volatile unsigned char *p
= v
; while( n
-- ) *p
++ = 0;
53 int ccm_init( ccm_context
*ctx
, cipher_id_t cipher
,
54 const unsigned char *key
, unsigned int keysize
)
57 const cipher_info_t
*cipher_info
;
59 memset( ctx
, 0, sizeof( ccm_context
) );
61 cipher_init( &ctx
->cipher_ctx
);
63 cipher_info
= cipher_info_from_values( cipher
, keysize
, POLARSSL_MODE_ECB
);
64 if( cipher_info
== NULL
)
65 return( POLARSSL_ERR_CCM_BAD_INPUT
);
67 if( cipher_info
->block_size
!= 16 )
68 return( POLARSSL_ERR_CCM_BAD_INPUT
);
70 if( ( ret
= cipher_init_ctx( &ctx
->cipher_ctx
, cipher_info
) ) != 0 )
73 if( ( ret
= cipher_setkey( &ctx
->cipher_ctx
, key
, keysize
,
74 POLARSSL_ENCRYPT
) ) != 0 )
85 void ccm_free( ccm_context
*ctx
)
87 cipher_free( &ctx
->cipher_ctx
);
88 polarssl_zeroize( ctx
, sizeof( ccm_context
) );
92 * Macros for common operations.
93 * Results in smaller compiled code than static inline functions.
97 * Update the CBC-MAC state in y using a block in b
98 * (Always using b as the source helps the compiler optimise a bit better.)
100 #define UPDATE_CBC_MAC \
101 for( i = 0; i < 16; i++ ) \
104 if( ( ret = cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \
108 * Encrypt or decrypt a partial block with CTR
109 * Warning: using b for temporary storage! src and dst must not be b!
110 * This avoids allocating one more 16 bytes buffer while allowing src == dst.
112 #define CTR_CRYPT( dst, src, len ) \
113 if( ( ret = cipher_update( &ctx->cipher_ctx, ctr, 16, b, &olen ) ) != 0 ) \
116 for( i = 0; i < len; i++ ) \
117 dst[i] = src[i] ^ b[i];
120 * Authenticated encryption or decryption
122 static int ccm_auth_crypt( ccm_context
*ctx
, int mode
, size_t length
,
123 const unsigned char *iv
, size_t iv_len
,
124 const unsigned char *add
, size_t add_len
,
125 const unsigned char *input
, unsigned char *output
,
126 unsigned char *tag
, size_t tag_len
)
130 unsigned char q
= 16 - 1 - iv_len
;
131 size_t len_left
, olen
;
134 unsigned char ctr
[16];
135 const unsigned char *src
;
139 * Check length requirements: SP800-38C A.1
140 * Additional requirement: a < 2^16 - 2^8 to simplify the code.
141 * 'length' checked later (when writing it to the first block)
143 if( tag_len
< 4 || tag_len
> 16 || tag_len
% 2 != 0 )
144 return( POLARSSL_ERR_CCM_BAD_INPUT
);
146 /* Also implies q is within bounds */
147 if( iv_len
< 7 || iv_len
> 13 )
148 return( POLARSSL_ERR_CCM_BAD_INPUT
);
150 if( add_len
> 0xFF00 )
151 return( POLARSSL_ERR_CCM_BAD_INPUT
);
156 * 1 .. iv_len nonce (aka iv)
157 * iv_len+1 .. 15 length
159 * With flags as (bits):
166 b
[0] |= ( add_len
> 0 ) << 6;
167 b
[0] |= ( ( tag_len
- 2 ) / 2 ) << 3;
170 memcpy( b
+ 1, iv
, iv_len
);
172 for( i
= 0, len_left
= length
; i
< q
; i
++, len_left
>>= 8 )
173 b
[15-i
] = (unsigned char)( len_left
& 0xFF );
176 return( POLARSSL_ERR_CCM_BAD_INPUT
);
179 /* Start CBC-MAC with first block */
184 * If there is additional data, update CBC-MAC with
185 * add_len, add, 0 (padding to a block boundary)
194 b
[0] = (unsigned char)( ( add_len
>> 8 ) & 0xFF );
195 b
[1] = (unsigned char)( ( add_len
) & 0xFF );
197 use_len
= len_left
< 16 - 2 ? len_left
: 16 - 2;
198 memcpy( b
+ 2, src
, use_len
);
204 while( len_left
> 0 )
206 use_len
= len_left
> 16 ? 16 : len_left
;
209 memcpy( b
, src
, use_len
);
218 * Prepare counter block for encryption:
220 * 1 .. iv_len nonce (aka iv)
221 * iv_len+1 .. 15 counter (initially 1)
223 * With flags as (bits):
228 memcpy( ctr
+ 1, iv
, iv_len
);
229 memset( ctr
+ 1 + iv_len
, 0, q
);
233 * Authenticate and {en,de}crypt the message.
235 * The only difference between encryption and decryption is
236 * the respective order of authentication and {en,de}cryption.
242 while( len_left
> 0 )
244 unsigned char use_len
= len_left
> 16 ? 16 : len_left
;
246 if( mode
== CCM_ENCRYPT
)
249 memcpy( b
, src
, use_len
);
253 CTR_CRYPT( dst
, src
, use_len
);
255 if( mode
== CCM_DECRYPT
)
258 memcpy( b
, dst
, use_len
);
268 * No need to check for overflow thanks to the length check above.
270 for( i
= 0; i
< q
; i
++ )
271 if( ++ctr
[15-i
] != 0 )
276 * Authentication: reset counter and crypt/mask internal tag
278 for( i
= 0; i
< q
; i
++ )
281 CTR_CRYPT( y
, y
, 16 );
282 memcpy( tag
, y
, tag_len
);
288 * Authenticated encryption
290 int ccm_encrypt_and_tag( ccm_context
*ctx
, size_t length
,
291 const unsigned char *iv
, size_t iv_len
,
292 const unsigned char *add
, size_t add_len
,
293 const unsigned char *input
, unsigned char *output
,
294 unsigned char *tag
, size_t tag_len
)
296 return( ccm_auth_crypt( ctx
, CCM_ENCRYPT
, length
, iv
, iv_len
,
297 add
, add_len
, input
, output
, tag
, tag_len
) );
301 * Authenticated decryption
303 int ccm_auth_decrypt( ccm_context
*ctx
, size_t length
,
304 const unsigned char *iv
, size_t iv_len
,
305 const unsigned char *add
, size_t add_len
,
306 const unsigned char *input
, unsigned char *output
,
307 const unsigned char *tag
, size_t tag_len
)
310 unsigned char check_tag
[16];
314 if( ( ret
= ccm_auth_crypt( ctx
, CCM_DECRYPT
, length
,
315 iv
, iv_len
, add
, add_len
,
316 input
, output
, check_tag
, tag_len
) ) != 0 )
321 /* Check tag in "constant-time" */
322 for( diff
= 0, i
= 0; i
< tag_len
; i
++ )
323 diff
|= tag
[i
] ^ check_tag
[i
];
327 polarssl_zeroize( output
, length
);
328 return( POLARSSL_ERR_CCM_AUTH_FAILED
);
335 #if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_AES_C)
337 #if defined(POLARSSL_PLATFORM_C)
338 #include "polarssl/platform.h"
341 #define polarssl_printf printf
345 * Examples 1 to 3 from SP800-38C Appendix C
351 * The data is the same for all tests, only the used length changes
353 static const unsigned char key
[] = {
354 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
355 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
358 static const unsigned char iv
[] = {
359 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
360 0x18, 0x19, 0x1a, 0x1b
363 static const unsigned char ad
[] = {
364 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
365 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
366 0x10, 0x11, 0x12, 0x13
369 static const unsigned char msg
[] = {
370 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
371 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
372 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
375 static const size_t iv_len
[NB_TESTS
] = { 7, 8, 12 };
376 static const size_t add_len
[NB_TESTS
] = { 8, 16, 20 };
377 static const size_t msg_len
[NB_TESTS
] = { 4, 16, 24 };
378 static const size_t tag_len
[NB_TESTS
] = { 4, 6, 8 };
380 static const unsigned char res
[NB_TESTS
][32] = {
381 { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
382 { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
383 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
384 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd },
385 { 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a,
386 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b,
387 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5,
388 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 }
391 int ccm_self_test( int verbose
)
394 unsigned char out
[32];
398 if( ccm_init( &ctx
, POLARSSL_CIPHER_ID_AES
, key
, 8 * sizeof key
) != 0 )
401 polarssl_printf( " CCM: setup failed" );
406 for( i
= 0; i
< NB_TESTS
; i
++ )
409 polarssl_printf( " CCM-AES #%u: ", (unsigned int) i
+ 1 );
411 ret
= ccm_encrypt_and_tag( &ctx
, msg_len
[i
],
412 iv
, iv_len
[i
], ad
, add_len
[i
],
414 out
+ msg_len
[i
], tag_len
[i
] );
417 memcmp( out
, res
[i
], msg_len
[i
] + tag_len
[i
] ) != 0 )
420 polarssl_printf( "failed\n" );
425 ret
= ccm_auth_decrypt( &ctx
, msg_len
[i
],
426 iv
, iv_len
[i
], ad
, add_len
[i
],
428 res
[i
] + msg_len
[i
], tag_len
[i
] );
431 memcmp( out
, msg
, msg_len
[i
] ) != 0 )
434 polarssl_printf( "failed\n" );
440 polarssl_printf( "passed\n" );
446 polarssl_printf( "\n" );
451 #endif /* POLARSSL_SELF_TEST && POLARSSL_AES_C */
453 #endif /* POLARSSL_CCM_C */