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

             Branch data     Line data    Source code
       1                 :             : #include "test_libsha512_utils.h"
       2                 :             : 
       3                 :             : /**
       4                 :             :  * @brief Check that callers can hash a message in several updates
       5                 :             :  * @details Real callers often read data in pieces from files or streams. This
       6                 :             :  * test proves that feeding the same message in chunks produces the same digest
       7                 :             :  * as hashing the whole message in one call
       8                 :             :  *
       9                 :             :  * @return SUCCESS when whole-message and chunked hashing produce one digest
      10                 :             :  */
      11                 :           1 : Return test_libsha512_0002(void)
      12                 :             : {
      13                 :           1 :         INITTEST;
      14                 :             : 
      15                 :             :         /* Pick a familiar 43-byte pangram so the test data is easy to recognize */
      16                 :             :         static const char message_text[] = "The quick brown fox jumps over the lazy dog";
      17                 :             : 
      18                 :             :         /* Several deliberately different chunk plans for the same 43-byte message.
      19                 :             :            Each plan sums to 43, so applying any of them through sha512_update must
      20                 :             :            reproduce the one-shot reference digest. Together they cover obvious
      21                 :             :            pathological shapes: a single big update, an irregular Fibonacci-like
      22                 :             :            split, a heavy-front/tiny-tail split, and one update per byte */
      23                 :             :         static const size_t plan_singleton[] = {43U};
      24                 :             :         static const size_t plan_fibonacci[] = {1U,2U,3U,5U,8U,13U,11U};
      25                 :             :         static const size_t plan_skewed[] = {40U,2U,1U};
      26                 :             :         static const size_t plan_byte_at_a_time[] = {
      27                 :             :                 1U,1U,1U,1U,1U,1U,1U,1U,1U,1U,
      28                 :             :                 1U,1U,1U,1U,1U,1U,1U,1U,1U,1U,
      29                 :             :                 1U,1U,1U,1U,1U,1U,1U,1U,1U,1U,
      30                 :             :                 1U,1U,1U,1U,1U,1U,1U,1U,1U,1U,
      31                 :             :                 1U,1U,1U
      32                 :             :         };
      33                 :             : 
      34                 :             :         const struct {
      35                 :             :                 const size_t *sizes;
      36                 :             :                 size_t count;
      37                 :           1 :         } chunk_plans[] = {
      38                 :             :                 {plan_singleton,      sizeof(plan_singleton)      / sizeof(plan_singleton[0])     },
      39                 :             :                 {plan_fibonacci,      sizeof(plan_fibonacci)      / sizeof(plan_fibonacci[0])     },
      40                 :             :                 {plan_skewed,         sizeof(plan_skewed)         / sizeof(plan_skewed[0])        },
      41                 :             :                 {plan_byte_at_a_time, sizeof(plan_byte_at_a_time) / sizeof(plan_byte_at_a_time[0])}
      42                 :             :         };
      43                 :             : 
      44                 :           1 :         size_t message_length = 0U;
      45                 :             : 
      46                 :             :         /* Allocate all test data through libmem, matching the style used by the
      47                 :             :            other library test suites */
      48                 :           1 :         m_create(char,message,MEMORY_STRING);
      49                 :           1 :         m_create(size_t,chunks);
      50                 :           1 :         m_create(unsigned char,one_shot_digest);
      51                 :           1 :         m_create(unsigned char,chunked_digest);
      52                 :           1 :         m_create(unsigned char,monocypher_digest);
      53                 :             : 
      54                 :             :         /* Prepare the message, resolve its libmem-tracked length through the public
      55                 :             :            helper, and compute the libsha512 one-shot digest checked below */
      56                 :           1 :         ASSERT(SUCCESS == m_copy_fixed_string(message,sizeof(message_text),message_text));
      57                 :           1 :         ASSERT(SUCCESS == m_string_length(message,&message_length));
      58                 :           1 :         ASSERT(SUCCESS == calculate_sha512_digest(
      59                 :             :                 (const unsigned char *)m_text(message),
      60                 :             :                 message_length,
      61                 :             :                 one_shot_digest));
      62                 :           1 :         ASSERT(SUCCESS == calculate_sha512_digest_monocypher(
      63                 :             :                 (const unsigned char *)m_text(message),
      64                 :             :                 message_length,
      65                 :             :                 monocypher_digest));
      66                 :           1 :         ASSERT(SUCCESS == assert_sha512_digest_matches(one_shot_digest,monocypher_digest));
      67                 :             : 
      68                 :             :         /* Replay the message through every chunk plan. m_copy_buffer rewrites the
      69                 :             :            chunks descriptor from scratch on each iteration, so plans are isolated
      70                 :             :            from one another. Every chunked digest is checked against Monocypher, not
      71                 :             :            only against libsha512's one-shot path */
      72   [ +  -  +  + ]:           5 :         for(size_t plan_index = 0U; SUCCESS == status && plan_index < sizeof(chunk_plans) / sizeof(chunk_plans[0]); plan_index++)
      73                 :             :         {
      74                 :           4 :                 ASSERT(SUCCESS == m_copy_buffer(
      75                 :             :                         chunks,
      76                 :             :                         chunk_plans[plan_index].count * sizeof(size_t),
      77                 :             :                         chunk_plans[plan_index].sizes));
      78                 :           4 :                 ASSERT(SUCCESS == calculate_sha512_digest_in_chunks(
      79                 :             :                         (const unsigned char *)m_text(message),
      80                 :             :                         message_length,
      81                 :             :                         chunks,
      82                 :             :                         chunked_digest));
      83                 :           4 :                 ASSERT(SUCCESS == assert_sha512_digest_matches(chunked_digest,monocypher_digest));
      84                 :             :         }
      85                 :             : 
      86                 :             :         /* Release every descriptor through call() so cleanup still runs after an
      87                 :             :            earlier assertion marks the test as failed */
      88                 :           1 :         call(m_del(message));
      89                 :           1 :         call(m_del(chunks));
      90                 :           1 :         call(m_del(one_shot_digest));
      91                 :           1 :         call(m_del(chunked_digest));
      92                 :           1 :         call(m_del(monocypher_digest));
      93                 :             : 
      94                 :           1 :         RETURN_STATUS;
      95                 :             : }
        

Generated by: LCOV version 2.0-1