LCOV - code coverage report
Current view: top level - externals/mbedtls/library - ccm.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 168 195 86.2 %
Date: 2024-09-16 20:15:30 Functions: 16 18 88.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 82 136 60.3 %

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

Generated by: LCOV version 1.14