LCOV - code coverage report
Current view: top level - externals/mbedtls/library - ccm.c (source / functions) Coverage Total Hit
Test: lcov.info Lines: 86.5 % 192 166
Test Date: 2026-03-12 12:01:18 Functions: 88.9 % 18 16
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 58.1 % 124 72

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

Generated by: LCOV version 2.0-1