LCOV - code coverage report
Current view: top level - externals/tinycrypt/lib/source - ccm_mode.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 105 0.0 %
Date: 2024-09-16 20:15:30 Functions: 0 5 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 76 0.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 1.14