LCOV - code coverage report
Current view: top level - externals/tinycrypt/lib/source - ccm_mode.c (source / functions) Coverage Total Hit
Test: lcov.info Lines: 0.0 % 105 0
Test Date: 2026-03-12 12:01:18 Functions: 0.0 % 5 0
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0.0 % 76 0

             Branch data     Line data    Source code
       1                 :             : /* ccm_mode.c - TinyCrypt implementation of CCM mode */
       2                 :             : 
       3                 :             : /*
       4                 :             :  *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
       5                 :             :  *
       6                 :             :  *  Redistribution and use in source and binary forms, with or without
       7                 :             :  *  modification, are permitted provided that the following conditions are met:
       8                 :             :  *
       9                 :             :  *    - Redistributions of source code must retain the above copyright notice,
      10                 :             :  *     this list of conditions and the following disclaimer.
      11                 :             :  *
      12                 :             :  *    - Redistributions in binary form must reproduce the above copyright
      13                 :             :  *    notice, this list of conditions and the following disclaimer in the
      14                 :             :  *    documentation and/or other materials provided with the distribution.
      15                 :             :  *
      16                 :             :  *    - Neither the name of Intel Corporation nor the names of its contributors
      17                 :             :  *    may be used to endorse or promote products derived from this software
      18                 :             :  *    without specific prior written permission.
      19                 :             :  *
      20                 :             :  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      21                 :             :  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      22                 :             :  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      23                 :             :  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
      24                 :             :  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      25                 :             :  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      26                 :             :  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      27                 :             :  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      28                 :             :  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      29                 :             :  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      30                 :             :  *  POSSIBILITY OF SUCH DAMAGE.
      31                 :             :  */
      32                 :             : 
      33                 :             : #include <tinycrypt/ccm_mode.h>
      34                 :             : #include <tinycrypt/constants.h>
      35                 :             : #include <tinycrypt/utils.h>
      36                 :             : 
      37                 :             : #include <stdio.h>
      38                 :             : 
      39                 :           0 : int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce,
      40                 :             :                   unsigned int nlen, unsigned int mlen)
      41                 :             : {
      42                 :             : 
      43                 :             :         /* input sanity check: */
      44                 :           0 :         if (c == (TCCcmMode_t) 0 ||
      45   [ #  #  #  # ]:           0 :             sched == (TCAesKeySched_t) 0 ||
      46                 :             :             nonce == (uint8_t *) 0) {
      47                 :             :                 return TC_CRYPTO_FAIL;
      48         [ #  # ]:           0 :         } else if (nlen != 13) {
      49                 :             :                 return TC_CRYPTO_FAIL; /* The allowed nonce size is: 13. See documentation.*/
      50   [ #  #  #  # ]:           0 :         } else if ((mlen < 4) || (mlen > 16) || (mlen & 1)) {
      51                 :             :                 return TC_CRYPTO_FAIL; /* The allowed mac sizes are: 4, 6, 8, 10, 12, 14, 16.*/
      52                 :             :         }
      53                 :             : 
      54                 :           0 :         c->mlen = mlen;
      55                 :           0 :         c->sched = sched;
      56                 :           0 :         c->nonce = nonce;
      57                 :             : 
      58                 :           0 :         return TC_CRYPTO_SUCCESS;
      59                 :             : }
      60                 :             : 
      61                 :             : /**
      62                 :             :  * Variation of CBC-MAC mode used in CCM.
      63                 :             :  */
      64                 :           0 : static void ccm_cbc_mac(uint8_t *T, const uint8_t *data, unsigned int dlen,
      65                 :             :                         unsigned int flag, TCAesKeySched_t sched)
      66                 :             : {
      67                 :             : 
      68                 :           0 :         unsigned int i;
      69                 :             : 
      70         [ #  # ]:           0 :         if (flag > 0) {
      71                 :           0 :                 T[0] ^= (uint8_t)(dlen >> 8);
      72                 :           0 :                 T[1] ^= (uint8_t)(dlen);
      73                 :           0 :                 dlen += 2; i = 2;
      74                 :             :         } else {
      75                 :           0 :                 i = 0;
      76                 :             :         }
      77                 :             : 
      78         [ #  # ]:           0 :         while (i < dlen) {
      79                 :           0 :                 T[i++ % (Nb * Nk)] ^= *data++;
      80   [ #  #  #  # ]:           0 :                 if (((i % (Nb * Nk)) == 0) || dlen == i) {
      81                 :           0 :                         (void) tc_aes_encrypt(T, T, sched);
      82                 :             :                 }
      83                 :             :         }
      84                 :           0 : }
      85                 :             : 
      86                 :             : /**
      87                 :             :  * Variation of CTR mode used in CCM.
      88                 :             :  * The CTR mode used by CCM is slightly different than the conventional CTR
      89                 :             :  * mode (the counter is increased before encryption, instead of after
      90                 :             :  * encryption). Besides, it is assumed that the counter is stored in the last
      91                 :             :  * 2 bytes of the nonce.
      92                 :             :  */
      93                 :           0 : static int ccm_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
      94                 :             :                         unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched)
      95                 :             : {
      96                 :             : 
      97                 :           0 :         uint8_t buffer[TC_AES_BLOCK_SIZE];
      98                 :           0 :         uint8_t nonce[TC_AES_BLOCK_SIZE];
      99                 :           0 :         uint16_t block_num;
     100                 :           0 :         unsigned int i;
     101                 :             : 
     102                 :             :         /* input sanity check: */
     103                 :           0 :         if (out == (uint8_t *) 0 ||
     104         [ #  # ]:           0 :             in == (uint8_t *) 0 ||
     105                 :           0 :             ctr == (uint8_t *) 0 ||
     106         [ #  # ]:           0 :             sched == (TCAesKeySched_t) 0 ||
     107                 :           0 :             inlen == 0 ||
     108   [ #  #  #  # ]:           0 :             outlen == 0 ||
     109                 :             :             outlen != inlen) {
     110                 :             :                 return TC_CRYPTO_FAIL;
     111                 :             :         }
     112                 :             : 
     113                 :             :         /* copy the counter to the nonce */
     114                 :           0 :         (void) _copy(nonce, sizeof(nonce), ctr, sizeof(nonce));
     115                 :             : 
     116                 :             :         /* select the last 2 bytes of the nonce to be incremented */
     117                 :           0 :         block_num = (uint16_t) ((nonce[14] << 8)|(nonce[15]));
     118         [ #  # ]:           0 :         for (i = 0; i < inlen; ++i) {
     119         [ #  # ]:           0 :                 if ((i % (TC_AES_BLOCK_SIZE)) == 0) {
     120                 :           0 :                         block_num++;
     121                 :           0 :                         nonce[14] = (uint8_t)(block_num >> 8);
     122                 :           0 :                         nonce[15] = (uint8_t)(block_num);
     123         [ #  # ]:           0 :                         if (!tc_aes_encrypt(buffer, nonce, sched)) {
     124                 :             :                                 return TC_CRYPTO_FAIL;
     125                 :             :                         }
     126                 :             :                 }
     127                 :             :                 /* update the output */
     128                 :           0 :                 *out++ = buffer[i % (TC_AES_BLOCK_SIZE)] ^ *in++;
     129                 :             :         }
     130                 :             : 
     131                 :             :         /* update the counter */
     132                 :           0 :         ctr[14] = nonce[14]; ctr[15] = nonce[15];
     133                 :             : 
     134                 :           0 :         return TC_CRYPTO_SUCCESS;
     135                 :             : }
     136                 :             : 
     137                 :           0 : int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen,
     138                 :             :                                  const uint8_t *associated_data,
     139                 :             :                                  unsigned int alen, const uint8_t *payload,
     140                 :             :                                  unsigned int plen, TCCcmMode_t c)
     141                 :             : {
     142                 :             : 
     143                 :             :         /* input sanity check: */
     144                 :           0 :         if ((out == (uint8_t *) 0) ||
     145         [ #  # ]:           0 :                 (c == (TCCcmMode_t) 0) ||
     146         [ #  # ]:           0 :                 ((plen > 0) && (payload == (uint8_t *) 0)) ||
     147         [ #  # ]:           0 :                 ((alen > 0) && (associated_data == (uint8_t *) 0)) ||
     148                 :           0 :                 (alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */
     149         [ #  # ]:           0 :                 (plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */
     150         [ #  # ]:           0 :                 (olen < (plen + c->mlen))) {  /* invalid output buffer size */
     151                 :             :                 return TC_CRYPTO_FAIL;
     152                 :             :         }
     153                 :             : 
     154                 :           0 :         uint8_t b[Nb * Nk];
     155                 :           0 :         uint8_t tag[Nb * Nk];
     156                 :           0 :         unsigned int i;
     157                 :             : 
     158                 :             :         /* GENERATING THE AUTHENTICATION TAG: */
     159                 :             : 
     160                 :             :         /* formatting the sequence b for authentication: */
     161         [ #  # ]:           0 :         b[0] = ((alen > 0) ? 0x40:0) | (((c->mlen - 2) / 2 << 3)) | (1);
     162         [ #  # ]:           0 :         for (i = 1; i <= 13; ++i) {
     163                 :           0 :                 b[i] = c->nonce[i - 1];
     164                 :             :         }
     165                 :           0 :         b[14] = (uint8_t)(plen >> 8);
     166                 :           0 :         b[15] = (uint8_t)(plen);
     167                 :             : 
     168                 :             :         /* computing the authentication tag using cbc-mac: */
     169                 :           0 :         (void) tc_aes_encrypt(tag, b, c->sched);
     170         [ #  # ]:           0 :         if (alen > 0) {
     171                 :           0 :                 ccm_cbc_mac(tag, associated_data, alen, 1, c->sched);
     172                 :             :         }
     173         [ #  # ]:           0 :         if (plen > 0) {
     174                 :           0 :                 ccm_cbc_mac(tag, payload, plen, 0, c->sched);
     175                 :             :         }
     176                 :             : 
     177                 :             :         /* ENCRYPTION: */
     178                 :             : 
     179                 :             :         /* formatting the sequence b for encryption: */
     180                 :           0 :         b[0] = 1; /* q - 1 = 2 - 1 = 1 */
     181                 :           0 :         b[14] = b[15] = TC_ZERO_BYTE;
     182                 :             : 
     183                 :             :         /* encrypting payload using ctr mode: */
     184                 :           0 :         ccm_ctr_mode(out, plen, payload, plen, b, c->sched);
     185                 :             : 
     186                 :           0 :         b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter for ctr_mode (0):*/
     187                 :             : 
     188                 :             :         /* encrypting b and adding the tag to the output: */
     189                 :           0 :         (void) tc_aes_encrypt(b, b, c->sched);
     190                 :           0 :         out += plen;
     191         [ #  # ]:           0 :         for (i = 0; i < c->mlen; ++i) {
     192                 :           0 :                 *out++ = tag[i] ^ b[i];
     193                 :             :         }
     194                 :             : 
     195                 :             :         return TC_CRYPTO_SUCCESS;
     196                 :             : }
     197                 :             : 
     198                 :           0 : int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen,
     199                 :             :                                    const uint8_t *associated_data,
     200                 :             :                                    unsigned int alen, const uint8_t *payload,
     201                 :             :                                    unsigned int plen, TCCcmMode_t c)
     202                 :             : {
     203                 :             : 
     204                 :             :         /* input sanity check: */
     205                 :           0 :         if ((out == (uint8_t *) 0) ||
     206         [ #  # ]:           0 :             (c == (TCCcmMode_t) 0) ||
     207         [ #  # ]:           0 :             ((plen > 0) && (payload == (uint8_t *) 0)) ||
     208         [ #  # ]:           0 :             ((alen > 0) && (associated_data == (uint8_t *) 0)) ||
     209                 :           0 :             (alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */
     210         [ #  # ]:           0 :             (plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */
     211         [ #  # ]:           0 :             (olen < plen - c->mlen)) { /* invalid output buffer size */
     212                 :             :                 return TC_CRYPTO_FAIL;
     213                 :             :   }
     214                 :             : 
     215                 :           0 :         uint8_t b[Nb * Nk];
     216                 :           0 :         uint8_t tag[Nb * Nk];
     217                 :           0 :         unsigned int i;
     218                 :             : 
     219                 :             :         /* DECRYPTION: */
     220                 :             : 
     221                 :             :         /* formatting the sequence b for decryption: */
     222                 :           0 :         b[0] = 1; /* q - 1 = 2 - 1 = 1 */
     223         [ #  # ]:           0 :         for (i = 1; i < 14; ++i) {
     224                 :           0 :                 b[i] = c->nonce[i - 1];
     225                 :             :         }
     226                 :           0 :         b[14] = b[15] = TC_ZERO_BYTE; /* initial counter value is 0 */
     227                 :             : 
     228                 :             :         /* decrypting payload using ctr mode: */
     229                 :           0 :         ccm_ctr_mode(out, plen - c->mlen, payload, plen - c->mlen, b, c->sched);
     230                 :             : 
     231                 :           0 :         b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter value (0) */
     232                 :             : 
     233                 :             :         /* encrypting b and restoring the tag from input: */
     234                 :           0 :         (void) tc_aes_encrypt(b, b, c->sched);
     235         [ #  # ]:           0 :         for (i = 0; i < c->mlen; ++i) {
     236                 :           0 :                 tag[i] = *(payload + plen - c->mlen + i) ^ b[i];
     237                 :             :         }
     238                 :             : 
     239                 :             :         /* VERIFYING THE AUTHENTICATION TAG: */
     240                 :             : 
     241                 :             :         /* formatting the sequence b for authentication: */
     242         [ #  # ]:           0 :         b[0] = ((alen > 0) ? 0x40:0)|(((c->mlen - 2) / 2 << 3)) | (1);
     243         [ #  # ]:           0 :         for (i = 1; i < 14; ++i) {
     244                 :           0 :                 b[i] = c->nonce[i - 1];
     245                 :             :         }
     246                 :           0 :         b[14] = (uint8_t)((plen - c->mlen) >> 8);
     247                 :           0 :         b[15] = (uint8_t)(plen - c->mlen);
     248                 :             : 
     249                 :             :         /* computing the authentication tag using cbc-mac: */
     250                 :           0 :         (void) tc_aes_encrypt(b, b, c->sched);
     251         [ #  # ]:           0 :         if (alen > 0) {
     252                 :           0 :                 ccm_cbc_mac(b, associated_data, alen, 1, c->sched);
     253                 :             :         }
     254         [ #  # ]:           0 :         if (plen > 0) {
     255                 :           0 :                 ccm_cbc_mac(b, out, plen - c->mlen, 0, c->sched);
     256                 :             :         }
     257                 :             : 
     258                 :             :         /* comparing the received tag and the computed one: */
     259         [ #  # ]:           0 :         if (_compare(b, tag, c->mlen) == 0) {
     260                 :             :                 return TC_CRYPTO_SUCCESS;
     261                 :             :         } else {
     262                 :             :                 /* erase the decrypted buffer in case of mac validation failure: */
     263                 :           0 :                 _set(out, 0, plen - c->mlen);
     264                 :           0 :                 return TC_CRYPTO_FAIL;
     265                 :             :         }
     266                 :             : }
        

Generated by: LCOV version 2.0-1