LCOV - code coverage report
Current view: top level - libs/sha512/tests/src - test_libsha512_0004.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 78 78
Test Date: 2026-07-12 01:01:34 Functions: 100.0 % 10 10
Branches: 75.0 % 4 3

             Branch data     Line data    Source code
       1                 :             : #include "test_libsha512_utils.h"
       2                 :             : 
       3                 :             : /**
       4                 :             :  * @brief Fill a test message with deterministic bytes
       5                 :             :  * @details The exact text is not important for this test. A stable byte pattern
       6                 :             :  * makes every boundary case reproducible while still exercising ordinary binary
       7                 :             :  * input rather than a special empty buffer
       8                 :             :  *
       9                 :             :  * @param message Descriptor that receives the generated bytes
      10                 :             :  * @param message_size Number of bytes to generate
      11                 :             :  * @return SUCCESS when the message descriptor is ready to hash
      12                 :             :  */
      13                 :           6 : static Return prepare_boundary_message(
      14                 :             :         memory *message,
      15                 :             :         size_t message_size)
      16                 :             : {
      17                 :             :         /* Status returned by this function through provide()
      18                 :             :            Default value assumes successful completion */
      19                 :           6 :         Return status = SUCCESS;
      20                 :             : 
      21                 :           6 :         unsigned char *message_data = NULL;
      22                 :             : 
      23                 :             :         /* Require a real descriptor and a non-empty size before writing the pattern */
      24                 :           6 :         ASSERT(message != NULL);
      25                 :           6 :         ASSERT(message_size > 0U);
      26                 :           6 :         ASSERT(SUCCESS == m_resize(message,message_size,ZERO_NEW_MEMORY));
      27                 :             : 
      28                 :             :         /* Ask libmem for writable bytes only after the descriptor has the requested
      29                 :             :            length */
      30                 :           6 :         IF(message != NULL)
      31                 :             :         {
      32                 :           6 :                 message_data = m_data(unsigned char,message);
      33                 :             :         }
      34                 :             : 
      35                 :           6 :         ASSERT(message_data != NULL);
      36                 :             : 
      37                 :             :         /* Fill with a predictable alphabet pattern. It is simple to inspect, but it
      38                 :             :            still exercises binary hashing rather than relying on string helpers */
      39   [ +  -  +  + ]:         726 :         for(size_t byte_index = 0U; SUCCESS == status && byte_index < message_size; byte_index++)
      40                 :             :         {
      41                 :         720 :                 message_data[byte_index] = (unsigned char)('A' + (byte_index % 26U));
      42                 :             :         }
      43                 :             : 
      44                 :           6 :         provide(status);
      45                 :             : }
      46                 :             : 
      47                 :             : /**
      48                 :             :  * @brief Prepare a two-piece chunk plan for one boundary message
      49                 :             :  * @details The first chunk leaves one byte for the second update call. For a
      50                 :             :  * 128-byte message this specifically exercises the path where buffered input
      51                 :             :  * completes a full SHA-512 block
      52                 :             :  *
      53                 :             :  * @param chunks Descriptor that receives two size_t chunk lengths
      54                 :             :  * @param message_size Total message size that the chunks must cover
      55                 :             :  * @return SUCCESS when the chunk descriptor contains a complete plan
      56                 :             :  */
      57                 :           6 : static Return prepare_boundary_chunks(
      58                 :             :         memory *chunks,
      59                 :             :         size_t message_size)
      60                 :             : {
      61                 :             :         /* Status returned by this function through provide()
      62                 :             :            Default value assumes successful completion */
      63                 :           6 :         Return status = SUCCESS;
      64                 :             : 
      65                 :           6 :         size_t *chunk_data = NULL;
      66                 :             : 
      67                 :             :         /* The boundary comparison needs exactly two chunks: almost the whole message
      68                 :             :            first, then one final byte */
      69                 :           6 :         ASSERT(chunks != NULL);
      70                 :           6 :         ASSERT(message_size > 0U);
      71                 :           6 :         ASSERT(SUCCESS == m_resize(chunks,2U,ZERO_NEW_MEMORY));
      72                 :             : 
      73                 :             :         /* Retrieve writable chunk storage after libmem has allocated two entries */
      74                 :           6 :         IF(chunks != NULL)
      75                 :             :         {
      76                 :           6 :                 chunk_data = m_data(size_t,chunks);
      77                 :             :         }
      78                 :             : 
      79                 :           6 :         ASSERT(chunk_data != NULL);
      80                 :             : 
      81                 :             :         /* The final one-byte update is the important part of this scenario because
      82                 :             :            it can complete a buffered SHA-512 block */
      83                 :           6 :         IF(chunk_data != NULL)
      84                 :             :         {
      85                 :           6 :                 chunk_data[0] = message_size - 1U;
      86                 :           6 :                 chunk_data[1] = 1U;
      87                 :             :         }
      88                 :             : 
      89                 :           6 :         provide(status);
      90                 :             : }
      91                 :             : 
      92                 :             : /**
      93                 :             :  * @brief Compare one-shot and chunked hashing at one SHA-512 boundary
      94                 :             :  * @details A size close to the 128-byte block or 112-byte padding threshold can
      95                 :             :  * use different internal paths. The public digest must stay the same no matter
      96                 :             :  * which path is used
      97                 :             :  *
      98                 :             :  * @param message_size Boundary size to exercise
      99                 :             :  * @return SUCCESS when both hashing styles produce one digest
     100                 :             :  */
     101                 :           6 : static Return check_sha512_boundary_size(size_t message_size)
     102                 :             : {
     103                 :             :         /* Status returned by this function through provide()
     104                 :             :            Default value assumes successful completion */
     105                 :           6 :         Return status = SUCCESS;
     106                 :             : 
     107                 :             :         /* Keep all temporary buffers in libmem descriptors so setup, hashing, and
     108                 :             :            cleanup follow the same rules as the rest of the test environment */
     109                 :           6 :         m_create(unsigned char,message);
     110                 :           6 :         m_create(size_t,chunks);
     111                 :           6 :         m_create(unsigned char,one_shot_digest);
     112                 :           6 :         m_create(unsigned char,chunked_digest);
     113                 :           6 :         m_create(unsigned char,monocypher_digest);
     114                 :             : 
     115                 :             :         /* Build one deterministic boundary-sized message and a chunk plan that
     116                 :             :            finishes it with a one-byte update */
     117                 :           6 :         ASSERT(SUCCESS == prepare_boundary_message(message,message_size));
     118                 :           6 :         ASSERT(SUCCESS == prepare_boundary_chunks(chunks,message_size));
     119                 :             : 
     120                 :             :         /* Hash the exact same bytes through both libsha512 paths and the Monocypher
     121                 :             :            reference. Boundary behavior is correct only if every digest matches */
     122                 :           6 :         ASSERT(SUCCESS == calculate_sha512_digest(
     123                 :             :                 m_data_ro(unsigned char,message),
     124                 :             :                 message->length,
     125                 :             :                 one_shot_digest));
     126                 :           6 :         ASSERT(SUCCESS == calculate_sha512_digest_monocypher(
     127                 :             :                 m_data_ro(unsigned char,message),
     128                 :             :                 message->length,
     129                 :             :                 monocypher_digest));
     130                 :           6 :         ASSERT(SUCCESS == calculate_sha512_digest_in_chunks(
     131                 :             :                 m_data_ro(unsigned char,message),
     132                 :             :                 message->length,
     133                 :             :                 chunks,
     134                 :             :                 chunked_digest));
     135                 :           6 :         ASSERT(SUCCESS == assert_sha512_digest_matches(one_shot_digest,monocypher_digest));
     136                 :           6 :         ASSERT(SUCCESS == assert_sha512_digest_matches(chunked_digest,monocypher_digest));
     137                 :             : 
     138                 :             :         /* Free descriptors with call() so a failed boundary check does not leak the
     139                 :             :            buffers allocated for that size */
     140                 :           6 :         call(m_del(message));
     141                 :           6 :         call(m_del(chunks));
     142                 :           6 :         call(m_del(one_shot_digest));
     143                 :           6 :         call(m_del(chunked_digest));
     144                 :           6 :         call(m_del(monocypher_digest));
     145                 :             : 
     146                 :           6 :         provide(status);
     147                 :             : }
     148                 :             : 
     149                 :             : /**
     150                 :             :  * @brief Check the byte just before the SHA-512 padding threshold
     151                 :             :  * @details A 111-byte message leaves exactly enough room for padding and the
     152                 :             :  * length field in one final block, so one-shot and chunked hashing must agree
     153                 :             :  *
     154                 :             :  * @return SUCCESS when the 111-byte digest is stable across input styles
     155                 :             :  */
     156                 :           1 : static Return test_libsha512_0004_1(void)
     157                 :             : {
     158                 :           1 :         INITTEST;
     159                 :             : 
     160                 :             :         /* Exercise the byte immediately before the 112-byte padding boundary */
     161                 :           1 :         run(check_sha512_boundary_size(111U));
     162                 :             : 
     163                 :           1 :         RETURN_STATUS;
     164                 :             : }
     165                 :             : 
     166                 :             : /**
     167                 :             :  * @brief Check the SHA-512 padding threshold itself
     168                 :             :  * @details A 112-byte message reaches the point where final padding must spill
     169                 :             :  * into an additional block, which is a classic edge for SHA-512 implementations
     170                 :             :  *
     171                 :             :  * @return SUCCESS when the 112-byte digest is stable across input styles
     172                 :             :  */
     173                 :           1 : static Return test_libsha512_0004_2(void)
     174                 :             : {
     175                 :           1 :         INITTEST;
     176                 :             : 
     177                 :             :         /* Exercise the exact boundary where SHA-512 final padding changes shape */
     178                 :           1 :         run(check_sha512_boundary_size(112U));
     179                 :             : 
     180                 :           1 :         RETURN_STATUS;
     181                 :             : }
     182                 :             : 
     183                 :             : /**
     184                 :             :  * @brief Check the byte just after the SHA-512 padding threshold
     185                 :             :  * @details A 113-byte message confirms that the post-threshold finalization
     186                 :             :  * path still produces the same digest for one-shot and chunked callers
     187                 :             :  *
     188                 :             :  * @return SUCCESS when the 113-byte digest is stable across input styles
     189                 :             :  */
     190                 :           1 : static Return test_libsha512_0004_3(void)
     191                 :             : {
     192                 :           1 :         INITTEST;
     193                 :             : 
     194                 :             :         /* Exercise the first byte after the 112-byte padding boundary */
     195                 :           1 :         run(check_sha512_boundary_size(113U));
     196                 :             : 
     197                 :           1 :         RETURN_STATUS;
     198                 :             : }
     199                 :             : 
     200                 :             : /**
     201                 :             :  * @brief Check the byte just before a full SHA-512 block
     202                 :             :  * @details A 127-byte message leaves one byte to complete the 128-byte block
     203                 :             :  * size, making it a useful streaming boundary for chunked updates
     204                 :             :  *
     205                 :             :  * @return SUCCESS when the 127-byte digest is stable across input styles
     206                 :             :  */
     207                 :           1 : static Return test_libsha512_0004_4(void)
     208                 :             : {
     209                 :           1 :         INITTEST;
     210                 :             : 
     211                 :             :         /* Exercise the byte immediately before a full SHA-512 block */
     212                 :           1 :         run(check_sha512_boundary_size(127U));
     213                 :             : 
     214                 :           1 :         RETURN_STATUS;
     215                 :             : }
     216                 :             : 
     217                 :             : /**
     218                 :             :  * @brief Check an exact full SHA-512 block
     219                 :             :  * @details A 128-byte message verifies the path where update processing can
     220                 :             :  * compress a full block before final padding is added
     221                 :             :  *
     222                 :             :  * @return SUCCESS when the 128-byte digest is stable across input styles
     223                 :             :  */
     224                 :           1 : static Return test_libsha512_0004_5(void)
     225                 :             : {
     226                 :           1 :         INITTEST;
     227                 :             : 
     228                 :             :         /* Exercise the exact 128-byte SHA-512 block size */
     229                 :           1 :         run(check_sha512_boundary_size(128U));
     230                 :             : 
     231                 :           1 :         RETURN_STATUS;
     232                 :             : }
     233                 :             : 
     234                 :             : /**
     235                 :             :  * @brief Check the byte just after a full SHA-512 block
     236                 :             :  * @details A 129-byte message proves that hashing remains stable immediately
     237                 :             :  * after a block is compressed and new buffered input begins
     238                 :             :  *
     239                 :             :  * @return SUCCESS when the 129-byte digest is stable across input styles
     240                 :             :  */
     241                 :           1 : static Return test_libsha512_0004_6(void)
     242                 :             : {
     243                 :           1 :         INITTEST;
     244                 :             : 
     245                 :             :         /* Exercise the first byte after a full SHA-512 block */
     246                 :           1 :         run(check_sha512_boundary_size(129U));
     247                 :             : 
     248                 :           1 :         RETURN_STATUS;
     249                 :             : }
     250                 :             : 
     251                 :             : /**
     252                 :             :  * @brief Check SHA-512 behavior around block and padding boundaries
     253                 :             :  * @details The selected sizes sit on both sides of important internal limits:
     254                 :             :  * 112 bytes for final padding and 128 bytes for a full SHA-512 block
     255                 :             :  *
     256                 :             :  * @return SUCCESS when all boundary sizes produce stable digests
     257                 :             :  */
     258                 :           1 : Return test_libsha512_0004(void)
     259                 :             : {
     260                 :           1 :         INITTEST;
     261                 :             : 
     262                 :             :         /* Exercise each boundary independently so a failure points to the exact
     263                 :             :            message size that broke the one-shot versus chunked guarantee */
     264                 :           1 :         TEST(test_libsha512_0004_1,"111-byte input stays stable just before SHA-512 padding spillover");
     265                 :           1 :         TEST(test_libsha512_0004_2,"112-byte input stays stable at SHA-512 padding spillover");
     266                 :           1 :         TEST(test_libsha512_0004_3,"113-byte input stays stable just after SHA-512 padding spillover");
     267                 :           1 :         TEST(test_libsha512_0004_4,"127-byte input stays stable just before a full SHA-512 block");
     268                 :           1 :         TEST(test_libsha512_0004_5,"128-byte input stays stable at a full SHA-512 block");
     269                 :           1 :         TEST(test_libsha512_0004_6,"129-byte input stays stable just after a full SHA-512 block");
     270                 :             : 
     271                 :           1 :         RETURN_STATUS;
     272                 :             : }
        

Generated by: LCOV version 2.0-1