1 /*
2 * NIST SP800-38C compliant CCM implementation
3 *
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 */
7
8 /*
9 * Definition of CCM:
10 * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
11 * RFC 3610 "Counter with CBC-MAC (CCM)"
12 *
13 * Related:
14 * RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
15 */
16
17 #include "common.h"
18
19 #if defined(MBEDTLS_CCM_C)
20
21 #include "mbedtls/ccm.h"
22 #include "mbedtls/platform_util.h"
23 #include "mbedtls/error.h"
24 #include "mbedtls/constant_time.h"
25
26 #include <string.h>
27
28 #if defined(MBEDTLS_PLATFORM_C)
29 #include "mbedtls/platform.h"
30 #else
31 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
32 #include <stdio.h>
33 #define mbedtls_printf printf
34 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
35 #endif /* MBEDTLS_PLATFORM_C */
36
37 #if !defined(MBEDTLS_CCM_ALT)
38
39
40 /*
41 * Initialize context
42 */
mbedtls_ccm_init(mbedtls_ccm_context * ctx)43 void mbedtls_ccm_init(mbedtls_ccm_context *ctx)
44 {
45 memset(ctx, 0, sizeof(mbedtls_ccm_context));
46 }
47
mbedtls_ccm_setkey(mbedtls_ccm_context * ctx,mbedtls_cipher_id_t cipher,const unsigned char * key,unsigned int keybits)48 int mbedtls_ccm_setkey(mbedtls_ccm_context *ctx,
49 mbedtls_cipher_id_t cipher,
50 const unsigned char *key,
51 unsigned int keybits)
52 {
53 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
54 const mbedtls_cipher_info_t *cipher_info;
55
56 cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
57 MBEDTLS_MODE_ECB);
58 if (cipher_info == NULL) {
59 return MBEDTLS_ERR_CCM_BAD_INPUT;
60 }
61
62 if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
63 return MBEDTLS_ERR_CCM_BAD_INPUT;
64 }
65
66 mbedtls_cipher_free(&ctx->cipher_ctx);
67
68 if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
69 return ret;
70 }
71
72 if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
73 MBEDTLS_ENCRYPT)) != 0) {
74 return ret;
75 }
76
77 return 0;
78 }
79
80 /*
81 * Free context
82 */
mbedtls_ccm_free(mbedtls_ccm_context * ctx)83 void mbedtls_ccm_free(mbedtls_ccm_context *ctx)
84 {
85 if (ctx == NULL) {
86 return;
87 }
88 mbedtls_cipher_free(&ctx->cipher_ctx);
89 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ccm_context));
90 }
91
92 #define CCM_STATE__CLEAR 0
93 #define CCM_STATE__STARTED (1 << 0)
94 #define CCM_STATE__LENGTHS_SET (1 << 1)
95 #define CCM_STATE__AUTH_DATA_STARTED (1 << 2)
96 #define CCM_STATE__AUTH_DATA_FINISHED (1 << 3)
97 #define CCM_STATE__ERROR (1 << 4)
98
99 /*
100 * Encrypt or decrypt a partial block with CTR
101 */
mbedtls_ccm_crypt(mbedtls_ccm_context * ctx,size_t offset,size_t use_len,const unsigned char * input,unsigned char * output)102 static int mbedtls_ccm_crypt(mbedtls_ccm_context *ctx,
103 size_t offset, size_t use_len,
104 const unsigned char *input,
105 unsigned char *output)
106 {
107 size_t olen = 0;
108 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
109 unsigned char tmp_buf[16] = { 0 };
110
111 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->ctr, 16, tmp_buf,
112 &olen)) != 0) {
113 ctx->state |= CCM_STATE__ERROR;
114 mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf));
115 return ret;
116 }
117
118 mbedtls_xor(output, input, tmp_buf + offset, use_len);
119
120 mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf));
121 return ret;
122 }
123
mbedtls_ccm_clear_state(mbedtls_ccm_context * ctx)124 static void mbedtls_ccm_clear_state(mbedtls_ccm_context *ctx)
125 {
126 ctx->state = CCM_STATE__CLEAR;
127 memset(ctx->y, 0, 16);
128 memset(ctx->ctr, 0, 16);
129 }
130
ccm_calculate_first_block_if_ready(mbedtls_ccm_context * ctx)131 static int ccm_calculate_first_block_if_ready(mbedtls_ccm_context *ctx)
132 {
133 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
134 unsigned char i;
135 size_t len_left, olen;
136
137 /* length calculation can be done only after both
138 * mbedtls_ccm_starts() and mbedtls_ccm_set_lengths() have been executed
139 */
140 if (!(ctx->state & CCM_STATE__STARTED) || !(ctx->state & CCM_STATE__LENGTHS_SET)) {
141 return 0;
142 }
143
144 /* CCM expects non-empty tag.
145 * CCM* allows empty tag. For CCM* without tag, ignore plaintext length.
146 */
147 if (ctx->tag_len == 0) {
148 if (ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT || ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) {
149 ctx->plaintext_len = 0;
150 } else {
151 return MBEDTLS_ERR_CCM_BAD_INPUT;
152 }
153 }
154
155 /*
156 * First block:
157 * 0 .. 0 flags
158 * 1 .. iv_len nonce (aka iv) - set by: mbedtls_ccm_starts()
159 * iv_len+1 .. 15 length
160 *
161 * With flags as (bits):
162 * 7 0
163 * 6 add present?
164 * 5 .. 3 (t - 2) / 2
165 * 2 .. 0 q - 1
166 */
167 ctx->y[0] |= (ctx->add_len > 0) << 6;
168 ctx->y[0] |= ((ctx->tag_len - 2) / 2) << 3;
169 ctx->y[0] |= ctx->q - 1;
170
171 for (i = 0, len_left = ctx->plaintext_len; i < ctx->q; i++, len_left >>= 8) {
172 ctx->y[15-i] = MBEDTLS_BYTE_0(len_left);
173 }
174
175 if (len_left > 0) {
176 ctx->state |= CCM_STATE__ERROR;
177 return MBEDTLS_ERR_CCM_BAD_INPUT;
178 }
179
180 /* Start CBC-MAC with first block*/
181 if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen)) != 0) {
182 ctx->state |= CCM_STATE__ERROR;
183 return ret;
184 }
185
186 return 0;
187 }
188
mbedtls_ccm_starts(mbedtls_ccm_context * ctx,int mode,const unsigned char * iv,size_t iv_len)189 int mbedtls_ccm_starts(mbedtls_ccm_context *ctx,
190 int mode,
191 const unsigned char *iv,
192 size_t iv_len)
193 {
194 /* Also implies q is within bounds */
195 if (iv_len < 7 || iv_len > 13) {
196 return MBEDTLS_ERR_CCM_BAD_INPUT;
197 }
198
199 ctx->mode = mode;
200 ctx->q = 16 - 1 - (unsigned char) iv_len;
201
202 /*
203 * Prepare counter block for encryption:
204 * 0 .. 0 flags
205 * 1 .. iv_len nonce (aka iv)
206 * iv_len+1 .. 15 counter (initially 1)
207 *
208 * With flags as (bits):
209 * 7 .. 3 0
210 * 2 .. 0 q - 1
211 */
212 memset(ctx->ctr, 0, 16);
213 ctx->ctr[0] = ctx->q - 1;
214 memcpy(ctx->ctr + 1, iv, iv_len);
215 memset(ctx->ctr + 1 + iv_len, 0, ctx->q);
216 ctx->ctr[15] = 1;
217
218 /*
219 * See ccm_calculate_first_block_if_ready() for block layout description
220 */
221 memcpy(ctx->y + 1, iv, iv_len);
222
223 ctx->state |= CCM_STATE__STARTED;
224 return ccm_calculate_first_block_if_ready(ctx);
225 }
226
mbedtls_ccm_set_lengths(mbedtls_ccm_context * ctx,size_t total_ad_len,size_t plaintext_len,size_t tag_len)227 int mbedtls_ccm_set_lengths(mbedtls_ccm_context *ctx,
228 size_t total_ad_len,
229 size_t plaintext_len,
230 size_t tag_len)
231 {
232 /*
233 * Check length requirements: SP800-38C A.1
234 * Additional requirement: a < 2^16 - 2^8 to simplify the code.
235 * 'length' checked later (when writing it to the first block)
236 *
237 * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4).
238 */
239 if (tag_len == 2 || tag_len > 16 || tag_len % 2 != 0) {
240 return MBEDTLS_ERR_CCM_BAD_INPUT;
241 }
242
243 if (total_ad_len >= 0xFF00) {
244 return MBEDTLS_ERR_CCM_BAD_INPUT;
245 }
246
247 ctx->plaintext_len = plaintext_len;
248 ctx->add_len = total_ad_len;
249 ctx->tag_len = tag_len;
250 ctx->processed = 0;
251
252 ctx->state |= CCM_STATE__LENGTHS_SET;
253 return ccm_calculate_first_block_if_ready(ctx);
254 }
255
mbedtls_ccm_update_ad(mbedtls_ccm_context * ctx,const unsigned char * add,size_t add_len)256 int mbedtls_ccm_update_ad(mbedtls_ccm_context *ctx,
257 const unsigned char *add,
258 size_t add_len)
259 {
260 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
261 size_t olen, use_len, offset;
262
263 if (ctx->state & CCM_STATE__ERROR) {
264 return MBEDTLS_ERR_CCM_BAD_INPUT;
265 }
266
267 if (add_len > 0) {
268 if (ctx->state & CCM_STATE__AUTH_DATA_FINISHED) {
269 return MBEDTLS_ERR_CCM_BAD_INPUT;
270 }
271
272 if (!(ctx->state & CCM_STATE__AUTH_DATA_STARTED)) {
273 if (add_len > ctx->add_len) {
274 return MBEDTLS_ERR_CCM_BAD_INPUT;
275 }
276
277 ctx->y[0] ^= (unsigned char) ((ctx->add_len >> 8) & 0xFF);
278 ctx->y[1] ^= (unsigned char) ((ctx->add_len) & 0xFF);
279
280 ctx->state |= CCM_STATE__AUTH_DATA_STARTED;
281 } else if (ctx->processed + add_len > ctx->add_len) {
282 return MBEDTLS_ERR_CCM_BAD_INPUT;
283 }
284
285 while (add_len > 0) {
286 offset = (ctx->processed + 2) % 16; /* account for y[0] and y[1]
287 * holding total auth data length */
288 use_len = 16 - offset;
289
290 if (use_len > add_len) {
291 use_len = add_len;
292 }
293
294 mbedtls_xor(ctx->y + offset, ctx->y + offset, add, use_len);
295
296 ctx->processed += use_len;
297 add_len -= use_len;
298 add += use_len;
299
300 if (use_len + offset == 16 || ctx->processed == ctx->add_len) {
301 if ((ret =
302 mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen)) != 0) {
303 ctx->state |= CCM_STATE__ERROR;
304 return ret;
305 }
306 }
307 }
308
309 if (ctx->processed == ctx->add_len) {
310 ctx->state |= CCM_STATE__AUTH_DATA_FINISHED;
311 ctx->processed = 0; // prepare for mbedtls_ccm_update()
312 }
313 }
314
315 return 0;
316 }
317
mbedtls_ccm_update(mbedtls_ccm_context * ctx,const unsigned char * input,size_t input_len,unsigned char * output,size_t output_size,size_t * output_len)318 int mbedtls_ccm_update(mbedtls_ccm_context *ctx,
319 const unsigned char *input, size_t input_len,
320 unsigned char *output, size_t output_size,
321 size_t *output_len)
322 {
323 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
324 unsigned char i;
325 size_t use_len, offset, olen;
326
327 unsigned char local_output[16];
328
329 if (ctx->state & CCM_STATE__ERROR) {
330 return MBEDTLS_ERR_CCM_BAD_INPUT;
331 }
332
333 /* Check against plaintext length only if performing operation with
334 * authentication
335 */
336 if (ctx->tag_len != 0 && ctx->processed + input_len > ctx->plaintext_len) {
337 return MBEDTLS_ERR_CCM_BAD_INPUT;
338 }
339
340 if (output_size < input_len) {
341 return MBEDTLS_ERR_CCM_BAD_INPUT;
342 }
343 *output_len = input_len;
344
345 ret = 0;
346
347 while (input_len > 0) {
348 offset = ctx->processed % 16;
349
350 use_len = 16 - offset;
351
352 if (use_len > input_len) {
353 use_len = input_len;
354 }
355
356 ctx->processed += use_len;
357
358 if (ctx->mode == MBEDTLS_CCM_ENCRYPT || \
359 ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT) {
360 mbedtls_xor(ctx->y + offset, ctx->y + offset, input, use_len);
361
362 if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) {
363 if ((ret =
364 mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen)) != 0) {
365 ctx->state |= CCM_STATE__ERROR;
366 goto exit;
367 }
368 }
369
370 ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, output);
371 if (ret != 0) {
372 goto exit;
373 }
374 }
375
376 if (ctx->mode == MBEDTLS_CCM_DECRYPT || \
377 ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) {
378 /* Since output may be in shared memory, we cannot be sure that
379 * it will contain what we wrote to it. Therefore, we should avoid using
380 * it as input to any operations.
381 * Write decrypted data to local_output to avoid using output variable as
382 * input in the XOR operation for Y.
383 */
384 ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, local_output);
385 if (ret != 0) {
386 goto exit;
387 }
388
389 mbedtls_xor(ctx->y + offset, ctx->y + offset, local_output, use_len);
390
391 memcpy(output, local_output, use_len);
392
393 if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) {
394 if ((ret =
395 mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen)) != 0) {
396 ctx->state |= CCM_STATE__ERROR;
397 goto exit;
398 }
399 }
400 }
401
402 if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) {
403 for (i = 0; i < ctx->q; i++) {
404 if (++(ctx->ctr)[15-i] != 0) {
405 break;
406 }
407 }
408 }
409
410 input_len -= use_len;
411 input += use_len;
412 output += use_len;
413 }
414
415 exit:
416 mbedtls_platform_zeroize(local_output, 16);
417
418 return ret;
419 }
420
mbedtls_ccm_finish(mbedtls_ccm_context * ctx,unsigned char * tag,size_t tag_len)421 int mbedtls_ccm_finish(mbedtls_ccm_context *ctx,
422 unsigned char *tag, size_t tag_len)
423 {
424 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
425 unsigned char i;
426
427 if (ctx->state & CCM_STATE__ERROR) {
428 return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
429 }
430
431 if (ctx->add_len > 0 && !(ctx->state & CCM_STATE__AUTH_DATA_FINISHED)) {
432 return MBEDTLS_ERR_CCM_BAD_INPUT;
433 }
434
435 if (ctx->plaintext_len > 0 && ctx->processed != ctx->plaintext_len) {
436 return MBEDTLS_ERR_CCM_BAD_INPUT;
437 }
438
439 /*
440 * Authentication: reset counter and crypt/mask internal tag
441 */
442 for (i = 0; i < ctx->q; i++) {
443 ctx->ctr[15-i] = 0;
444 }
445
446 ret = mbedtls_ccm_crypt(ctx, 0, 16, ctx->y, ctx->y);
447 if (ret != 0) {
448 return ret;
449 }
450 if (tag != NULL) {
451 memcpy(tag, ctx->y, tag_len);
452 }
453 mbedtls_ccm_clear_state(ctx);
454
455 return 0;
456 }
457
458 /*
459 * Authenticated encryption or decryption
460 */
ccm_auth_crypt(mbedtls_ccm_context * ctx,int mode,size_t length,const unsigned char * iv,size_t iv_len,const unsigned char * add,size_t add_len,const unsigned char * input,unsigned char * output,unsigned char * tag,size_t tag_len)461 static int ccm_auth_crypt(mbedtls_ccm_context *ctx, int mode, size_t length,
462 const unsigned char *iv, size_t iv_len,
463 const unsigned char *add, size_t add_len,
464 const unsigned char *input, unsigned char *output,
465 unsigned char *tag, size_t tag_len)
466 {
467 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
468 size_t olen;
469
470 if ((ret = mbedtls_ccm_starts(ctx, mode, iv, iv_len)) != 0) {
471 return ret;
472 }
473
474 if ((ret = mbedtls_ccm_set_lengths(ctx, add_len, length, tag_len)) != 0) {
475 return ret;
476 }
477
478 if ((ret = mbedtls_ccm_update_ad(ctx, add, add_len)) != 0) {
479 return ret;
480 }
481
482 if ((ret = mbedtls_ccm_update(ctx, input, length,
483 output, length, &olen)) != 0) {
484 return ret;
485 }
486
487 if ((ret = mbedtls_ccm_finish(ctx, tag, tag_len)) != 0) {
488 return ret;
489 }
490
491 return 0;
492 }
493
494 /*
495 * Authenticated encryption
496 */
mbedtls_ccm_star_encrypt_and_tag(mbedtls_ccm_context * ctx,size_t length,const unsigned char * iv,size_t iv_len,const unsigned char * add,size_t add_len,const unsigned char * input,unsigned char * output,unsigned char * tag,size_t tag_len)497 int mbedtls_ccm_star_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length,
498 const unsigned char *iv, size_t iv_len,
499 const unsigned char *add, size_t add_len,
500 const unsigned char *input, unsigned char *output,
501 unsigned char *tag, size_t tag_len)
502 {
503 return ccm_auth_crypt(ctx, MBEDTLS_CCM_STAR_ENCRYPT, length, iv, iv_len,
504 add, add_len, input, output, tag, tag_len);
505 }
506
mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context * ctx,size_t length,const unsigned char * iv,size_t iv_len,const unsigned char * add,size_t add_len,const unsigned char * input,unsigned char * output,unsigned char * tag,size_t tag_len)507 int mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length,
508 const unsigned char *iv, size_t iv_len,
509 const unsigned char *add, size_t add_len,
510 const unsigned char *input, unsigned char *output,
511 unsigned char *tag, size_t tag_len)
512 {
513 return ccm_auth_crypt(ctx, MBEDTLS_CCM_ENCRYPT, length, iv, iv_len,
514 add, add_len, input, output, tag, tag_len);
515 }
516
517 /*
518 * Authenticated decryption
519 */
mbedtls_ccm_compare_tags(const unsigned char * tag1,const unsigned char * tag2,size_t tag_len)520 static int mbedtls_ccm_compare_tags(const unsigned char *tag1,
521 const unsigned char *tag2,
522 size_t tag_len)
523 {
524 /* Check tag in "constant-time" */
525 int diff = mbedtls_ct_memcmp(tag1, tag2, tag_len);
526
527 if (diff != 0) {
528 return MBEDTLS_ERR_CCM_AUTH_FAILED;
529 }
530
531 return 0;
532 }
533
ccm_auth_decrypt(mbedtls_ccm_context * ctx,int mode,size_t length,const unsigned char * iv,size_t iv_len,const unsigned char * add,size_t add_len,const unsigned char * input,unsigned char * output,const unsigned char * tag,size_t tag_len)534 static int ccm_auth_decrypt(mbedtls_ccm_context *ctx, int mode, size_t length,
535 const unsigned char *iv, size_t iv_len,
536 const unsigned char *add, size_t add_len,
537 const unsigned char *input, unsigned char *output,
538 const unsigned char *tag, size_t tag_len)
539 {
540 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
541 unsigned char check_tag[16];
542
543 if ((ret = ccm_auth_crypt(ctx, mode, length,
544 iv, iv_len, add, add_len,
545 input, output, check_tag, tag_len)) != 0) {
546 return ret;
547 }
548
549 if ((ret = mbedtls_ccm_compare_tags(tag, check_tag, tag_len)) != 0) {
550 mbedtls_platform_zeroize(output, length);
551 return ret;
552 }
553
554 return 0;
555 }
556
mbedtls_ccm_star_auth_decrypt(mbedtls_ccm_context * ctx,size_t length,const unsigned char * iv,size_t iv_len,const unsigned char * add,size_t add_len,const unsigned char * input,unsigned char * output,const unsigned char * tag,size_t tag_len)557 int mbedtls_ccm_star_auth_decrypt(mbedtls_ccm_context *ctx, size_t length,
558 const unsigned char *iv, size_t iv_len,
559 const unsigned char *add, size_t add_len,
560 const unsigned char *input, unsigned char *output,
561 const unsigned char *tag, size_t tag_len)
562 {
563 return ccm_auth_decrypt(ctx, MBEDTLS_CCM_STAR_DECRYPT, length,
564 iv, iv_len, add, add_len,
565 input, output, tag, tag_len);
566 }
567
mbedtls_ccm_auth_decrypt(mbedtls_ccm_context * ctx,size_t length,const unsigned char * iv,size_t iv_len,const unsigned char * add,size_t add_len,const unsigned char * input,unsigned char * output,const unsigned char * tag,size_t tag_len)568 int mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx, size_t length,
569 const unsigned char *iv, size_t iv_len,
570 const unsigned char *add, size_t add_len,
571 const unsigned char *input, unsigned char *output,
572 const unsigned char *tag, size_t tag_len)
573 {
574 return ccm_auth_decrypt(ctx, MBEDTLS_CCM_DECRYPT, length,
575 iv, iv_len, add, add_len,
576 input, output, tag, tag_len);
577 }
578 #endif /* !MBEDTLS_CCM_ALT */
579
580 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
581 /*
582 * Examples 1 to 3 from SP800-38C Appendix C
583 */
584
585 #define NB_TESTS 3
586 #define CCM_SELFTEST_PT_MAX_LEN 24
587 #define CCM_SELFTEST_CT_MAX_LEN 32
588 /*
589 * The data is the same for all tests, only the used length changes
590 */
591 static const unsigned char key_test_data[] = {
592 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
593 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
594 };
595
596 static const unsigned char iv_test_data[] = {
597 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
598 0x18, 0x19, 0x1a, 0x1b
599 };
600
601 static const unsigned char ad_test_data[] = {
602 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
603 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
604 0x10, 0x11, 0x12, 0x13
605 };
606
607 static const unsigned char msg_test_data[CCM_SELFTEST_PT_MAX_LEN] = {
608 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
609 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
610 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
611 };
612
613 static const size_t iv_len_test_data[NB_TESTS] = { 7, 8, 12 };
614 static const size_t add_len_test_data[NB_TESTS] = { 8, 16, 20 };
615 static const size_t msg_len_test_data[NB_TESTS] = { 4, 16, 24 };
616 static const size_t tag_len_test_data[NB_TESTS] = { 4, 6, 8 };
617
618 static const unsigned char res_test_data[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = {
619 { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
620 { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
621 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
622 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd },
623 { 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a,
624 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b,
625 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5,
626 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 }
627 };
628
mbedtls_ccm_self_test(int verbose)629 int mbedtls_ccm_self_test(int verbose)
630 {
631 mbedtls_ccm_context ctx;
632 /*
633 * Some hardware accelerators require the input and output buffers
634 * would be in RAM, because the flash is not accessible.
635 * Use buffers on the stack to hold the test vectors data.
636 */
637 unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN];
638 unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN];
639 size_t i;
640 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
641
642 mbedtls_ccm_init(&ctx);
643
644 if (mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key_test_data,
645 8 * sizeof(key_test_data)) != 0) {
646 if (verbose != 0) {
647 mbedtls_printf(" CCM: setup failed");
648 }
649
650 return 1;
651 }
652
653 for (i = 0; i < NB_TESTS; i++) {
654 if (verbose != 0) {
655 mbedtls_printf(" CCM-AES #%u: ", (unsigned int) i + 1);
656 }
657
658 memset(plaintext, 0, CCM_SELFTEST_PT_MAX_LEN);
659 memset(ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN);
660 memcpy(plaintext, msg_test_data, msg_len_test_data[i]);
661
662 ret = mbedtls_ccm_encrypt_and_tag(&ctx, msg_len_test_data[i],
663 iv_test_data, iv_len_test_data[i],
664 ad_test_data, add_len_test_data[i],
665 plaintext, ciphertext,
666 ciphertext + msg_len_test_data[i],
667 tag_len_test_data[i]);
668
669 if (ret != 0 ||
670 memcmp(ciphertext, res_test_data[i],
671 msg_len_test_data[i] + tag_len_test_data[i]) != 0) {
672 if (verbose != 0) {
673 mbedtls_printf("failed\n");
674 }
675
676 return 1;
677 }
678 memset(plaintext, 0, CCM_SELFTEST_PT_MAX_LEN);
679
680 ret = mbedtls_ccm_auth_decrypt(&ctx, msg_len_test_data[i],
681 iv_test_data, iv_len_test_data[i],
682 ad_test_data, add_len_test_data[i],
683 ciphertext, plaintext,
684 ciphertext + msg_len_test_data[i],
685 tag_len_test_data[i]);
686
687 if (ret != 0 ||
688 memcmp(plaintext, msg_test_data, msg_len_test_data[i]) != 0) {
689 if (verbose != 0) {
690 mbedtls_printf("failed\n");
691 }
692
693 return 1;
694 }
695
696 if (verbose != 0) {
697 mbedtls_printf("passed\n");
698 }
699 }
700
701 mbedtls_ccm_free(&ctx);
702
703 if (verbose != 0) {
704 mbedtls_printf("\n");
705 }
706
707 return 0;
708 }
709
710 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
711
712 #endif /* MBEDTLS_CCM_C */
713