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 : : }
|