blob: 75de8cb5b9169be674ed4f60b8f5dd1c5177d7bf [file] [log] [blame]
Manuel Pégourié-Gonnarda6916fa2014-05-02 15:17:29 +02001/*
2 * NIST SP800-38C compliant CCM implementation
3 *
Manuel Pégourié-Gonnarda658a402015-01-23 09:45:19 +00004 * Copyright (C) 2014, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnarda6916fa2014-05-02 15:17:29 +02005 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +00006 * This file is part of mbed TLS (https://tls.mbed.org)
Manuel Pégourié-Gonnarda6916fa2014-05-02 15:17:29 +02007 *
Manuel Pégourié-Gonnarda6916fa2014-05-02 15:17:29 +02008 * 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.
12 *
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.
17 *
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.
21 */
22
23/*
24 * Definition of CCM:
25 * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
26 * RFC 3610 "Counter with CBC-MAC (CCM)"
27 *
28 * Related:
29 * RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
30 */
31
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000033#include "mbedtls/config.h"
Manuel Pégourié-Gonnarda6916fa2014-05-02 15:17:29 +020034#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnarda6916fa2014-05-02 15:17:29 +020036#endif
37
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_CCM_C)
Manuel Pégourié-Gonnarda6916fa2014-05-02 15:17:29 +020039
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000040#include "mbedtls/ccm.h"
Manuel Pégourié-Gonnarda6916fa2014-05-02 15:17:29 +020041
Rich Evans00ab4702015-02-06 13:43:58 +000042#include <string.h>
43
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
45#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/platform.h"
Rich Evans00ab4702015-02-06 13:43:58 +000047#else
48#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#define mbedtls_printf printf
50#endif /* MBEDTLS_PLATFORM_C */
51#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Rich Evans00ab4702015-02-06 13:43:58 +000052
Paul Bakker34617722014-06-13 17:20:13 +020053/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020055 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
56}
57
Manuel Pégourié-Gonnard00232332014-05-06 15:56:07 +020058#define CCM_ENCRYPT 0
59#define CCM_DECRYPT 1
60
Manuel Pégourié-Gonnard9fe0d132014-05-06 12:12:45 +020061/*
62 * Initialize context
63 */
Manuel Pégourié-Gonnard6963ff02015-04-28 18:02:54 +020064void mbedtls_ccm_init( mbedtls_ccm_context *ctx )
65{
66 memset( ctx, 0, sizeof( mbedtls_ccm_context ) );
67}
68
69int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
70 mbedtls_cipher_id_t cipher,
71 const unsigned char *key,
72 unsigned int keysize )
Manuel Pégourié-Gonnard9fe0d132014-05-06 12:12:45 +020073{
74 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020075 const mbedtls_cipher_info_t *cipher_info;
Manuel Pégourié-Gonnard9fe0d132014-05-06 12:12:45 +020076
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020077 cipher_info = mbedtls_cipher_info_from_values( cipher, keysize, MBEDTLS_MODE_ECB );
Manuel Pégourié-Gonnard9fe0d132014-05-06 12:12:45 +020078 if( cipher_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020079 return( MBEDTLS_ERR_CCM_BAD_INPUT );
Manuel Pégourié-Gonnard9fe0d132014-05-06 12:12:45 +020080
81 if( cipher_info->block_size != 16 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082 return( MBEDTLS_ERR_CCM_BAD_INPUT );
Manuel Pégourié-Gonnard9fe0d132014-05-06 12:12:45 +020083
Manuel Pégourié-Gonnard8473f872015-05-14 13:51:45 +020084 if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
Manuel Pégourié-Gonnard9fe0d132014-05-06 12:12:45 +020085 return( ret );
86
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020087 if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keysize,
88 MBEDTLS_ENCRYPT ) ) != 0 )
Manuel Pégourié-Gonnard9fe0d132014-05-06 12:12:45 +020089 {
90 return( ret );
91 }
92
93 return( 0 );
94}
95
96/*
97 * Free context
98 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020099void mbedtls_ccm_free( mbedtls_ccm_context *ctx )
Manuel Pégourié-Gonnard9fe0d132014-05-06 12:12:45 +0200100{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101 mbedtls_cipher_free( &ctx->cipher_ctx );
102 mbedtls_zeroize( ctx, sizeof( mbedtls_ccm_context ) );
Manuel Pégourié-Gonnard9fe0d132014-05-06 12:12:45 +0200103}
104
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200105/*
106 * Macros for common operations.
107 * Results in smaller compiled code than static inline functions.
108 */
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200109
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200110/*
111 * Update the CBC-MAC state in y using a block in b
112 * (Always using b as the source helps the compiler optimise a bit better.)
113 */
114#define UPDATE_CBC_MAC \
115 for( i = 0; i < 16; i++ ) \
116 y[i] ^= b[i]; \
117 \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200118 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200119 return( ret );
120
121/*
122 * Encrypt or decrypt a partial block with CTR
123 * Warning: using b for temporary storage! src and dst must not be b!
Manuel Pégourié-Gonnard0f6b66d2014-05-07 14:43:46 +0200124 * This avoids allocating one more 16 bytes buffer while allowing src == dst.
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200125 */
126#define CTR_CRYPT( dst, src, len ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127 if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctr, 16, b, &olen ) ) != 0 ) \
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200128 return( ret ); \
129 \
130 for( i = 0; i < len; i++ ) \
131 dst[i] = src[i] ^ b[i];
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200132
133/*
Manuel Pégourié-Gonnard00232332014-05-06 15:56:07 +0200134 * Authenticated encryption or decryption
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200135 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length,
Manuel Pégourié-Gonnard00232332014-05-06 15:56:07 +0200137 const unsigned char *iv, size_t iv_len,
138 const unsigned char *add, size_t add_len,
139 const unsigned char *input, unsigned char *output,
140 unsigned char *tag, size_t tag_len )
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200141{
142 int ret;
143 unsigned char i;
144 unsigned char q = 16 - 1 - iv_len;
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200145 size_t len_left, olen;
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200146 unsigned char b[16];
147 unsigned char y[16];
148 unsigned char ctr[16];
149 const unsigned char *src;
150 unsigned char *dst;
151
152 /*
153 * Check length requirements: SP800-38C A.1
154 * Additional requirement: a < 2^16 - 2^8 to simplify the code.
155 * 'length' checked later (when writing it to the first block)
156 */
157 if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 return( MBEDTLS_ERR_CCM_BAD_INPUT );
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200159
160 /* Also implies q is within bounds */
161 if( iv_len < 7 || iv_len > 13 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162 return( MBEDTLS_ERR_CCM_BAD_INPUT );
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200163
164 if( add_len > 0xFF00 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200165 return( MBEDTLS_ERR_CCM_BAD_INPUT );
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200166
167 /*
168 * First block B_0:
169 * 0 .. 0 flags
170 * 1 .. iv_len nonce (aka iv)
171 * iv_len+1 .. 15 length
172 *
173 * With flags as (bits):
174 * 7 0
175 * 6 add present?
176 * 5 .. 3 (t - 2) / 2
177 * 2 .. 0 q - 1
178 */
179 b[0] = 0;
180 b[0] |= ( add_len > 0 ) << 6;
181 b[0] |= ( ( tag_len - 2 ) / 2 ) << 3;
182 b[0] |= q - 1;
183
184 memcpy( b + 1, iv, iv_len );
185
186 for( i = 0, len_left = length; i < q; i++, len_left >>= 8 )
187 b[15-i] = (unsigned char)( len_left & 0xFF );
188
189 if( len_left > 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 return( MBEDTLS_ERR_CCM_BAD_INPUT );
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200191
192
193 /* Start CBC-MAC with first block */
194 memset( y, 0, 16 );
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200195 UPDATE_CBC_MAC;
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200196
197 /*
198 * If there is additional data, update CBC-MAC with
199 * add_len, add, 0 (padding to a block boundary)
200 */
201 if( add_len > 0 )
202 {
203 size_t use_len;
204 len_left = add_len;
205 src = add;
206
207 memset( b, 0, 16 );
208 b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF );
209 b[1] = (unsigned char)( ( add_len ) & 0xFF );
210
211 use_len = len_left < 16 - 2 ? len_left : 16 - 2;
212 memcpy( b + 2, src, use_len );
213 len_left -= use_len;
214 src += use_len;
215
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200216 UPDATE_CBC_MAC;
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200217
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200218 while( len_left > 0 )
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200219 {
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200220 use_len = len_left > 16 ? 16 : len_left;
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200221
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200222 memset( b, 0, 16 );
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200223 memcpy( b, src, use_len );
224 UPDATE_CBC_MAC;
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200225
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200226 len_left -= use_len;
227 src += use_len;
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200228 }
229 }
230
231 /*
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200232 * Prepare counter block for encryption:
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200233 * 0 .. 0 flags
234 * 1 .. iv_len nonce (aka iv)
235 * iv_len+1 .. 15 counter (initially 1)
236 *
237 * With flags as (bits):
238 * 7 .. 3 0
239 * 2 .. 0 q - 1
240 */
241 ctr[0] = q - 1;
242 memcpy( ctr + 1, iv, iv_len );
243 memset( ctr + 1 + iv_len, 0, q );
244 ctr[15] = 1;
245
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200246 /*
247 * Authenticate and {en,de}crypt the message.
248 *
249 * The only difference between encryption and decryption is
250 * the respective order of authentication and {en,de}cryption.
251 */
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200252 len_left = length;
253 src = input;
254 dst = output;
255
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200256 while( len_left > 0 )
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200257 {
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200258 unsigned char use_len = len_left > 16 ? 16 : len_left;
259
Manuel Pégourié-Gonnardce77d552014-05-06 18:06:52 +0200260 if( mode == CCM_ENCRYPT )
261 {
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200262 memset( b, 0, 16 );
263 memcpy( b, src, use_len );
264 UPDATE_CBC_MAC;
Manuel Pégourié-Gonnardce77d552014-05-06 18:06:52 +0200265 }
266
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200267 CTR_CRYPT( dst, src, use_len );
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200268
Manuel Pégourié-Gonnardce77d552014-05-06 18:06:52 +0200269 if( mode == CCM_DECRYPT )
270 {
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200271 memset( b, 0, 16 );
272 memcpy( b, dst, use_len );
273 UPDATE_CBC_MAC;
Manuel Pégourié-Gonnardce77d552014-05-06 18:06:52 +0200274 }
275
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200276 dst += use_len;
277 src += use_len;
278 len_left -= use_len;
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200279
Manuel Pégourié-Gonnardce77d552014-05-06 18:06:52 +0200280 /*
281 * Increment counter.
282 * No need to check for overflow thanks to the length check above.
283 */
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200284 for( i = 0; i < q; i++ )
285 if( ++ctr[15-i] != 0 )
286 break;
287 }
288
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200289 /*
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200290 * Authentication: reset counter and crypt/mask internal tag
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200291 */
292 for( i = 0; i < q; i++ )
293 ctr[15-i] = 0;
294
Manuel Pégourié-Gonnardaed60652014-05-07 13:14:42 +0200295 CTR_CRYPT( y, y, 16 );
296 memcpy( tag, y, tag_len );
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200297
298 return( 0 );
299}
300
Manuel Pégourié-Gonnard00232332014-05-06 15:56:07 +0200301/*
302 * Authenticated encryption
303 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200304int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
Manuel Pégourié-Gonnard00232332014-05-06 15:56:07 +0200305 const unsigned char *iv, size_t iv_len,
306 const unsigned char *add, size_t add_len,
307 const unsigned char *input, unsigned char *output,
308 unsigned char *tag, size_t tag_len )
309{
310 return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len,
311 add, add_len, input, output, tag, tag_len ) );
312}
313
314/*
315 * Authenticated decryption
316 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200317int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
Manuel Pégourié-Gonnard00232332014-05-06 15:56:07 +0200318 const unsigned char *iv, size_t iv_len,
319 const unsigned char *add, size_t add_len,
320 const unsigned char *input, unsigned char *output,
321 const unsigned char *tag, size_t tag_len )
322{
323 int ret;
324 unsigned char check_tag[16];
325 unsigned char i;
326 int diff;
327
328 if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length,
329 iv, iv_len, add, add_len,
330 input, output, check_tag, tag_len ) ) != 0 )
331 {
332 return( ret );
333 }
334
335 /* Check tag in "constant-time" */
336 for( diff = 0, i = 0; i < tag_len; i++ )
337 diff |= tag[i] ^ check_tag[i];
338
339 if( diff != 0 )
340 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341 mbedtls_zeroize( output, length );
342 return( MBEDTLS_ERR_CCM_AUTH_FAILED );
Manuel Pégourié-Gonnard00232332014-05-06 15:56:07 +0200343 }
344
345 return( 0 );
346}
347
Manuel Pégourié-Gonnarda6916fa2014-05-02 15:17:29 +0200348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200349#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200350/*
351 * Examples 1 to 3 from SP800-38C Appendix C
352 */
353
354#define NB_TESTS 3
355
356/*
357 * The data is the same for all tests, only the used length changes
358 */
359static const unsigned char key[] = {
360 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
361 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
362};
363
364static const unsigned char iv[] = {
365 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
366 0x18, 0x19, 0x1a, 0x1b
367};
368
369static const unsigned char ad[] = {
370 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
371 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
372 0x10, 0x11, 0x12, 0x13
373};
374
375static const unsigned char msg[] = {
376 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
377 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
378 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
379};
380
381static const size_t iv_len [NB_TESTS] = { 7, 8, 12 };
382static const size_t add_len[NB_TESTS] = { 8, 16, 20 };
383static const size_t msg_len[NB_TESTS] = { 4, 16, 24 };
384static const size_t tag_len[NB_TESTS] = { 4, 6, 8 };
385
386static const unsigned char res[NB_TESTS][32] = {
387 { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
388 { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
389 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
390 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd },
391 { 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a,
392 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b,
393 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5,
394 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 }
395};
396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397int mbedtls_ccm_self_test( int verbose )
Manuel Pégourié-Gonnarda6916fa2014-05-02 15:17:29 +0200398{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399 mbedtls_ccm_context ctx;
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200400 unsigned char out[32];
401 size_t i;
402 int ret;
403
Manuel Pégourié-Gonnard6963ff02015-04-28 18:02:54 +0200404 mbedtls_ccm_init( &ctx );
405
406 if( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 )
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200407 {
408 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409 mbedtls_printf( " CCM: setup failed" );
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200410
411 return( 1 );
412 }
413
414 for( i = 0; i < NB_TESTS; i++ )
415 {
416 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200417 mbedtls_printf( " CCM-AES #%u: ", (unsigned int) i + 1 );
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200418
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419 ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i],
Manuel Pégourié-Gonnardce77d552014-05-06 18:06:52 +0200420 iv, iv_len[i], ad, add_len[i],
421 msg, out,
422 out + msg_len[i], tag_len[i] );
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200423
424 if( ret != 0 ||
425 memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 )
426 {
427 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 mbedtls_printf( "failed\n" );
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200429
430 return( 1 );
431 }
432
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200433 ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i],
Manuel Pégourié-Gonnardce77d552014-05-06 18:06:52 +0200434 iv, iv_len[i], ad, add_len[i],
435 res[i], out,
436 res[i] + msg_len[i], tag_len[i] );
437
438 if( ret != 0 ||
439 memcmp( out, msg, msg_len[i] ) != 0 )
440 {
441 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442 mbedtls_printf( "failed\n" );
Manuel Pégourié-Gonnardce77d552014-05-06 18:06:52 +0200443
444 return( 1 );
445 }
446
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200447 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200448 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard637eb3d2014-05-06 12:13:09 +0200449 }
450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200451 mbedtls_ccm_free( &ctx );
Manuel Pégourié-Gonnarda6916fa2014-05-02 15:17:29 +0200452
453 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnarda6916fa2014-05-02 15:17:29 +0200455
456 return( 0 );
457}
458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
Manuel Pégourié-Gonnarda6916fa2014-05-02 15:17:29 +0200460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200461#endif /* MBEDTLS_CCM_C */