LCOV - code coverage report
Current view: top level - externals/tinycrypt/lib/source - ctr_prng.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 90 0.0 %
Date: 2024-09-16 20:15:30 Functions: 0 6 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 40 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* ctr_prng.c - TinyCrypt implementation of CTR-PRNG */
       2                 :            : 
       3                 :            : /*
       4                 :            :  * Copyright (c) 2016, Chris Morrison
       5                 :            :  * All rights reserved.
       6                 :            :  *
       7                 :            :  * Redistribution and use in source and binary forms, with or without
       8                 :            :  * modification, are permitted provided that the following conditions are met:
       9                 :            :  *
      10                 :            :  * * Redistributions of source code must retain the above copyright notice, this
      11                 :            :  *   list of conditions and the following disclaimer.
      12                 :            :  *
      13                 :            :  * * Redistributions in binary form must reproduce the above copyright notice,
      14                 :            :  *   this list of conditions and the following disclaimer in the documentation
      15                 :            :  *   and/or other materials provided with the distribution.
      16                 :            :  *
      17                 :            :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      18                 :            :  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      19                 :            :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      20                 :            :  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
      21                 :            :  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      22                 :            :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      23                 :            :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      24                 :            :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      25                 :            :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      26                 :            :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      27                 :            :  * POSSIBILITY OF SUCH DAMAGE.
      28                 :            :  */
      29                 :            : 
      30                 :            : #include <tinycrypt/ctr_prng.h>
      31                 :            : #include <tinycrypt/utils.h>
      32                 :            : #include <tinycrypt/constants.h>
      33                 :            : #include <string.h>
      34                 :            : 
      35                 :            : /*
      36                 :            :  * This PRNG is based on the CTR_DRBG described in Recommendation for Random
      37                 :            :  * Number Generation Using Deterministic Random Bit Generators,
      38                 :            :  * NIST SP 800-90A Rev. 1.
      39                 :            :  *
      40                 :            :  * Annotations to particular steps (e.g. 10.2.1.2 Step 1) refer to the steps
      41                 :            :  * described in that document.
      42                 :            :  *
      43                 :            :  */
      44                 :            : 
      45                 :            : /**
      46                 :            :  *  @brief Array incrementer
      47                 :            :  *  Treats the supplied array as one contiguous number (MSB in arr[0]), and
      48                 :            :  *  increments it by one
      49                 :            :  *  @return none
      50                 :            :  *  @param arr IN/OUT -- array to be incremented
      51                 :            :  *  @param len IN -- size of arr in bytes
      52                 :            :  */
      53                 :          0 : static void arrInc(uint8_t arr[], unsigned int len)
      54                 :            : {
      55                 :          0 :         unsigned int i;
      56         [ #  # ]:          0 :         if (0 != arr) {
      57         [ #  # ]:          0 :                 for (i = len; i > 0U; i--) {
      58         [ #  # ]:          0 :                         if (++arr[i-1] != 0U) {
      59                 :            :                                 break;
      60                 :            :                         }
      61                 :            :                 }
      62                 :            :         }
      63                 :          0 : }
      64                 :            : 
      65                 :            : /**
      66                 :            :  *  @brief CTR PRNG update
      67                 :            :  *  Updates the internal state of supplied the CTR PRNG context
      68                 :            :  *  increments it by one
      69                 :            :  *  @return none
      70                 :            :  *  @note Assumes: providedData is (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes long
      71                 :            :  *  @param ctx IN/OUT -- CTR PRNG state
      72                 :            :  *  @param providedData IN -- data used when updating the internal state
      73                 :            :  */
      74                 :          0 : static void tc_ctr_prng_update(TCCtrPrng_t * const ctx, uint8_t const * const providedData)
      75                 :            : {
      76         [ #  # ]:          0 :         if (0 != ctx) {
      77                 :            :                 /* 10.2.1.2 step 1 */
      78                 :            :                 uint8_t temp[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
      79                 :            :                 unsigned int len = 0U;
      80                 :            : 
      81                 :            :                 /* 10.2.1.2 step 2 */
      82         [ #  # ]:          0 :                 while (len < sizeof temp) {
      83                 :          0 :                         unsigned int blocklen = sizeof(temp) - len;
      84                 :          0 :                         uint8_t output_block[TC_AES_BLOCK_SIZE];
      85                 :            : 
      86                 :            :                         /* 10.2.1.2 step 2.1 */
      87                 :          0 :                         arrInc(ctx->V, sizeof ctx->V);
      88                 :            : 
      89                 :            :                         /* 10.2.1.2 step 2.2 */
      90                 :          0 :                         if (blocklen > TC_AES_BLOCK_SIZE) {
      91                 :            :                                 blocklen = TC_AES_BLOCK_SIZE;
      92                 :            :                         }
      93                 :          0 :                         (void)tc_aes_encrypt(output_block, ctx->V, &ctx->key);
      94                 :            : 
      95                 :            :                         /* 10.2.1.2 step 2.3/step 3 */
      96                 :          0 :                         memcpy(&(temp[len]), output_block, blocklen);
      97                 :            : 
      98                 :          0 :                         len += blocklen;
      99                 :            :                 }
     100                 :            : 
     101                 :            :                 /* 10.2.1.2 step 4 */
     102         [ #  # ]:          0 :                 if (0 != providedData) {
     103                 :            :                         unsigned int i;
     104         [ #  # ]:          0 :                         for (i = 0U; i < sizeof temp; i++) {
     105                 :          0 :                                 temp[i] ^= providedData[i];
     106                 :            :                         }
     107                 :            :                 }
     108                 :            : 
     109                 :            :                 /* 10.2.1.2 step 5 */
     110                 :          0 :                 (void)tc_aes128_set_encrypt_key(&ctx->key, temp);
     111                 :            :     
     112                 :            :                 /* 10.2.1.2 step 6 */
     113                 :          0 :                 memcpy(ctx->V, &(temp[TC_AES_KEY_SIZE]), TC_AES_BLOCK_SIZE);
     114                 :            :         }
     115                 :          0 : }
     116                 :            : 
     117                 :          0 : int tc_ctr_prng_init(TCCtrPrng_t * const ctx, 
     118                 :            :                      uint8_t const * const entropy,
     119                 :            :                      unsigned int entropyLen, 
     120                 :            :                      uint8_t const * const personalization,
     121                 :            :                      unsigned int pLen)
     122                 :            : {
     123                 :          0 :         int result = TC_CRYPTO_FAIL;    
     124                 :          0 :         unsigned int i;
     125                 :          0 :         uint8_t personalization_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
     126                 :          0 :         uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
     127                 :          0 :         uint8_t zeroArr[TC_AES_BLOCK_SIZE] = {0U};
     128                 :            :   
     129         [ #  # ]:          0 :         if (0 != personalization) {
     130                 :            :                 /* 10.2.1.3.1 step 1 */
     131                 :          0 :                 unsigned int len = pLen;
     132                 :          0 :                 if (len > sizeof personalization_buf) {
     133                 :            :                         len = sizeof personalization_buf;
     134                 :            :                 }
     135                 :            : 
     136                 :            :                 /* 10.2.1.3.1 step 2 */
     137                 :          0 :                 memcpy(personalization_buf, personalization, len);
     138                 :            :         }
     139                 :            : 
     140   [ #  #  #  # ]:          0 :         if ((0 != ctx) && (0 != entropy) && (entropyLen >= sizeof seed_material)) {
     141                 :            :                 /* 10.2.1.3.1 step 3 */
     142                 :          0 :                 memcpy(seed_material, entropy, sizeof seed_material);
     143         [ #  # ]:          0 :                 for (i = 0U; i < sizeof seed_material; i++) {
     144                 :          0 :                         seed_material[i] ^= personalization_buf[i];
     145                 :            :                 }
     146                 :            : 
     147                 :            :                 /* 10.2.1.3.1 step 4 */
     148                 :          0 :                 (void)tc_aes128_set_encrypt_key(&ctx->key, zeroArr);
     149                 :            : 
     150                 :            :                 /* 10.2.1.3.1 step 5 */
     151                 :          0 :                 memset(ctx->V,   0x00, sizeof ctx->V);
     152                 :            :     
     153                 :            :                 /* 10.2.1.3.1 step 6 */    
     154                 :          0 :                 tc_ctr_prng_update(ctx, seed_material);
     155                 :            : 
     156                 :            :                 /* 10.2.1.3.1 step 7 */
     157                 :          0 :                 ctx->reseedCount = 1U;
     158                 :            : 
     159                 :          0 :                 result = TC_CRYPTO_SUCCESS;
     160                 :            :         }
     161                 :          0 :         return result;
     162                 :            : }
     163                 :            : 
     164                 :          0 : int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx, 
     165                 :            :                         uint8_t const * const entropy,
     166                 :            :                         unsigned int entropyLen,
     167                 :            :                         uint8_t const * const additional_input,
     168                 :            :                         unsigned int additionallen)
     169                 :            : {
     170                 :          0 :         unsigned int i;
     171                 :          0 :         int result = TC_CRYPTO_FAIL;
     172                 :          0 :         uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
     173                 :          0 :         uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
     174                 :            : 
     175         [ #  # ]:          0 :         if (0 != additional_input) {
     176                 :            :                 /* 10.2.1.4.1 step 1 */
     177                 :          0 :                 unsigned int len = additionallen;
     178                 :          0 :                 if (len > sizeof additional_input_buf) {
     179                 :            :                         len = sizeof additional_input_buf;
     180                 :            :                 }
     181                 :            : 
     182                 :            :                 /* 10.2.1.4.1 step 2 */
     183                 :          0 :                 memcpy(additional_input_buf, additional_input, len);
     184                 :            :         }
     185                 :            :         
     186                 :          0 :         unsigned int seedlen = (unsigned int)TC_AES_KEY_SIZE + (unsigned int)TC_AES_BLOCK_SIZE;
     187         [ #  # ]:          0 :         if ((0 != ctx) && (entropyLen >= seedlen)) {
     188                 :            :                 /* 10.2.1.4.1 step 3 */
     189                 :          0 :                 memcpy(seed_material, entropy, sizeof seed_material);
     190         [ #  # ]:          0 :                 for (i = 0U; i < sizeof seed_material; i++) {
     191                 :          0 :                         seed_material[i] ^= additional_input_buf[i];
     192                 :            :                 }
     193                 :            : 
     194                 :            :                 /* 10.2.1.4.1 step 4 */
     195                 :          0 :                 tc_ctr_prng_update(ctx, seed_material);
     196                 :            : 
     197                 :            :                 /* 10.2.1.4.1 step 5 */
     198                 :          0 :                 ctx->reseedCount = 1U;
     199                 :            : 
     200                 :          0 :                 result = TC_CRYPTO_SUCCESS;
     201                 :            :         }
     202                 :          0 :         return result;
     203                 :            : }
     204                 :            : 
     205                 :          0 : int tc_ctr_prng_generate(TCCtrPrng_t * const ctx,
     206                 :            :                         uint8_t const * const additional_input,
     207                 :            :                         unsigned int additionallen,
     208                 :            :                         uint8_t * const out,
     209                 :            :                         unsigned int outlen)
     210                 :            : {
     211                 :            :         /* 2^48 - see section 10.2.1 */
     212                 :          0 :         static const uint64_t MAX_REQS_BEFORE_RESEED = 0x1000000000000ULL; 
     213                 :            : 
     214                 :            :         /* 2^19 bits - see section 10.2.1 */ 
     215                 :          0 :         static const unsigned int MAX_BYTES_PER_REQ = 65536U; 
     216                 :            : 
     217                 :          0 :         unsigned int result = TC_CRYPTO_FAIL;
     218                 :            : 
     219   [ #  #  #  # ]:          0 :         if ((0 != ctx) && (0 != out) && (outlen < MAX_BYTES_PER_REQ)) {
     220                 :            :                 /* 10.2.1.5.1 step 1 */
     221         [ #  # ]:          0 :                 if (ctx->reseedCount > MAX_REQS_BEFORE_RESEED) {
     222                 :            :                         result = TC_CTR_PRNG_RESEED_REQ;
     223                 :            :                 } else {
     224                 :          0 :                         uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
     225         [ #  # ]:          0 :                         if (0 != additional_input) {
     226                 :            :                                 /* 10.2.1.5.1 step 2  */
     227                 :          0 :                                 unsigned int len = additionallen;
     228                 :          0 :                                 if (len > sizeof additional_input_buf) {
     229                 :            :                                         len = sizeof additional_input_buf;
     230                 :            :                                 }
     231                 :          0 :                                 memcpy(additional_input_buf, additional_input, len);
     232                 :          0 :                                 tc_ctr_prng_update(ctx, additional_input_buf);
     233                 :            :                         }
     234                 :            :       
     235                 :            :                         /* 10.2.1.5.1 step 3 - implicit */
     236                 :            : 
     237                 :            :                         /* 10.2.1.5.1 step 4 */
     238                 :            :                         unsigned int len = 0U;      
     239         [ #  # ]:          0 :                         while (len < outlen) {
     240                 :          0 :                                 unsigned int blocklen = outlen - len;
     241                 :          0 :                                 uint8_t output_block[TC_AES_BLOCK_SIZE];
     242                 :            : 
     243                 :            :                                 /* 10.2.1.5.1 step 4.1 */
     244                 :          0 :                                 arrInc(ctx->V, sizeof ctx->V);
     245                 :            : 
     246                 :            :                                 /* 10.2.1.5.1 step 4.2 */
     247                 :          0 :                                 (void)tc_aes_encrypt(output_block, ctx->V, &ctx->key);
     248                 :            :       
     249                 :            :                                 /* 10.2.1.5.1 step 4.3/step 5 */
     250                 :          0 :                                 if (blocklen > TC_AES_BLOCK_SIZE) {
     251                 :            :                                         blocklen = TC_AES_BLOCK_SIZE;
     252                 :            :                                 }
     253                 :          0 :                                 memcpy(&(out[len]), output_block, blocklen);
     254                 :            : 
     255                 :          0 :                                 len += blocklen;
     256                 :            :                         }
     257                 :            :       
     258                 :            :                         /* 10.2.1.5.1 step 6 */
     259                 :          0 :                         tc_ctr_prng_update(ctx, additional_input_buf);
     260                 :            : 
     261                 :            :                         /* 10.2.1.5.1 step 7 */
     262                 :          0 :                         ctx->reseedCount++;
     263                 :            : 
     264                 :            :                         /* 10.2.1.5.1 step 8 */
     265                 :          0 :                         result = TC_CRYPTO_SUCCESS;
     266                 :            :                 }
     267                 :            :         }
     268                 :            : 
     269                 :          0 :         return result;
     270                 :            : }
     271                 :            : 
     272                 :          0 : void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx)
     273                 :            : {
     274         [ #  # ]:          0 :         if (0 != ctx) {
     275                 :          0 :                 memset(ctx->key.words, 0x00, sizeof ctx->key.words);
     276                 :          0 :                 memset(ctx->V,         0x00, sizeof ctx->V);
     277                 :          0 :                 ctx->reseedCount = 0U;
     278                 :            :         }
     279                 :          0 : }
     280                 :            : 
     281                 :            : 
     282                 :            : 
     283                 :            : 

Generated by: LCOV version 1.14