INSTINCT Code Coverage Report


Directory: src/
File: util/Random/SHA256.cpp
Date: 2025-02-07 16:54:41
Exec Total Coverage
Lines: 82 94 87.2%
Functions: 12 13 92.3%
Branches: 21 36 58.3%

Line Branch Exec Source
1 /*
2 MIT License
3
4 Copyright (c) 2021 Jérémy LAMBERT (SystemGlitch)
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 */
24
25 // NOLINTBEGIN
26
27 #include "SHA256.hpp"
28
29 #include <cstring>
30 #include <iomanip>
31 #include <sstream>
32
33 #if defined(__clang__)
34 #pragma GCC diagnostic push
35 #pragma GCC diagnostic ignored "-Wsign-conversion"
36 #endif
37
38 namespace NAV
39 {
40 constexpr std::array<uint32_t, 64> SHA256::K;
41
42 84 SHA256::SHA256() : m_blocklen(0), m_bitlen(0) // NOLINT
43 {
44 84 m_state[0] = 0x6a09e667;
45 84 m_state[1] = 0xbb67ae85;
46 84 m_state[2] = 0x3c6ef372;
47 84 m_state[3] = 0xa54ff53a;
48 84 m_state[4] = 0x510e527f;
49 84 m_state[5] = 0x9b05688c;
50 84 m_state[6] = 0x1f83d9ab;
51 84 m_state[7] = 0x5be0cd19;
52 84 }
53
54 84 void SHA256::update(const uint8_t* data, size_t length)
55 {
56
2/2
✓ Branch 0 taken 1586 times.
✓ Branch 1 taken 84 times.
1670 for (size_t i = 0; i < length; i++)
57 {
58 1586 m_data[m_blocklen++] = data[i]; // NOLINT
59
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1586 times.
1586 if (m_blocklen == 64)
60 {
61 transform();
62
63 // End of the block
64 m_bitlen += 512;
65 m_blocklen = 0;
66 }
67 }
68 84 }
69
70 84 void SHA256::update(const std::string& data)
71 {
72 84 update(reinterpret_cast<const uint8_t*>(data.c_str()), data.size()); // NOLINT
73 84 }
74
75 84 uint8_t* SHA256::digest()
76 {
77 84 uint8_t* hash = new uint8_t[32]; // NOLINT
78
79 84 pad();
80 84 revert(hash);
81
82 84 return hash;
83 }
84
85 48384 uint32_t SHA256::rotr(uint32_t x, uint32_t n)
86 {
87 48384 return (x >> n) | (x << (32 - n));
88 }
89
90 5376 uint32_t SHA256::choose(uint32_t e, uint32_t f, uint32_t g)
91 {
92 5376 return (e & f) ^ (~e & g);
93 }
94
95 5376 uint32_t SHA256::majority(uint32_t a, uint32_t b, uint32_t c)
96 {
97 5376 return (a & (b | c)) | (b & c);
98 }
99
100 4032 uint32_t SHA256::sig0(uint32_t x)
101 {
102 4032 return SHA256::rotr(x, 7) ^ SHA256::rotr(x, 18) ^ (x >> 3); // NOLINT
103 }
104
105 4032 uint32_t SHA256::sig1(uint32_t x)
106 {
107 4032 return SHA256::rotr(x, 17) ^ SHA256::rotr(x, 19) ^ (x >> 10); // NOLINT
108 }
109
110 84 void SHA256::transform()
111 {
112 uint32_t maj, xorA, ch, xorE, sum, newA, newE, m[64]; // NOLINT
113 uint32_t state[8]; // NOLINT
114
115
2/2
✓ Branch 0 taken 1344 times.
✓ Branch 1 taken 84 times.
1428 for (uint8_t i = 0, j = 0; i < 16; i++, j += 4)
116 { // Split data in 32 bit blocks for the 16 first words
117 1344 m[i] = (m_data[j] << 24) | (m_data[j + 1] << 16) | (m_data[j + 2] << 8) | (m_data[j + 3]); // NOLINT
118 }
119
120
2/2
✓ Branch 0 taken 4032 times.
✓ Branch 1 taken 84 times.
4116 for (uint8_t k = 16; k < 64; k++)
121 { // Remaining 48 blocks
122 4032 m[k] = SHA256::sig1(m[k - 2]) + m[k - 7] + SHA256::sig0(m[k - 15]) + m[k - 16]; // NOLINT
123 }
124
125
2/2
✓ Branch 0 taken 672 times.
✓ Branch 1 taken 84 times.
756 for (uint8_t i = 0; i < 8; i++)
126 {
127 672 state[i] = m_state[i]; // NOLINT
128 }
129
130
2/2
✓ Branch 0 taken 5376 times.
✓ Branch 1 taken 84 times.
5460 for (uint8_t i = 0; i < 64; i++)
131 {
132 5376 maj = SHA256::majority(state[0], state[1], state[2]);
133 5376 xorA = SHA256::rotr(state[0], 2) ^ SHA256::rotr(state[0], 13) ^ SHA256::rotr(state[0], 22);
134
135 5376 ch = choose(state[4], state[5], state[6]);
136
137 5376 xorE = SHA256::rotr(state[4], 6) ^ SHA256::rotr(state[4], 11) ^ SHA256::rotr(state[4], 25);
138
139 5376 sum = m[i] + K[i] + state[7] + ch + xorE; // NOLINT
140 5376 newA = xorA + maj + sum;
141 5376 newE = state[3] + sum;
142
143 5376 state[7] = state[6];
144 5376 state[6] = state[5];
145 5376 state[5] = state[4];
146 5376 state[4] = newE;
147 5376 state[3] = state[2];
148 5376 state[2] = state[1];
149 5376 state[1] = state[0];
150 5376 state[0] = newA;
151 }
152
153
2/2
✓ Branch 0 taken 672 times.
✓ Branch 1 taken 84 times.
756 for (uint8_t i = 0; i < 8; i++)
154 {
155 672 m_state[i] += state[i]; // NOLINT
156 }
157 84 }
158
159 84 void SHA256::pad()
160 {
161 84 uint64_t i = m_blocklen;
162
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
84 uint8_t end = m_blocklen < 56 ? 56 : 64;
163
164 84 m_data[i++] = 0x80; // Append a bit 1 // NOLINT
165
2/2
✓ Branch 0 taken 3034 times.
✓ Branch 1 taken 84 times.
3118 while (i < end)
166 {
167 3034 m_data[i++] = 0x00; // Pad with zeros // NOLINT
168 }
169
170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 if (m_blocklen >= 56)
171 {
172 transform();
173 memset(m_data, 0, 56); // NOLINT
174 }
175
176 // Append to the padding the total message's length in bits and transform.
177 84 m_bitlen += m_blocklen * 8; // NOLINT
178 84 m_data[63] = static_cast<uint8_t>(m_bitlen);
179 84 m_data[62] = static_cast<uint8_t>(m_bitlen >> 8); // NOLINT
180 84 m_data[61] = static_cast<uint8_t>(m_bitlen >> 16); // NOLINT
181 84 m_data[60] = static_cast<uint8_t>(m_bitlen >> 24); // NOLINT
182 84 m_data[59] = static_cast<uint8_t>(m_bitlen >> 32); // NOLINT
183 84 m_data[58] = static_cast<uint8_t>(m_bitlen >> 40); // NOLINT
184 84 m_data[57] = static_cast<uint8_t>(m_bitlen >> 48); // NOLINT
185 84 m_data[56] = static_cast<uint8_t>(m_bitlen >> 56); // NOLINT
186 84 transform();
187 84 }
188
189 84 void SHA256::revert(uint8_t* hash)
190 {
191 // SHA uses big endian byte ordering
192 // Revert all bytes
193
2/2
✓ Branch 0 taken 336 times.
✓ Branch 1 taken 84 times.
420 for (uint8_t i = 0; i < 4; i++)
194 {
195
2/2
✓ Branch 0 taken 2688 times.
✓ Branch 1 taken 336 times.
3024 for (uint8_t j = 0; j < 8; j++)
196 {
197 2688 hash[i + (j * 4)] = (m_state[j] >> (24 - i * 8)) & 0x000000ff; // NOLINT
198 }
199 }
200 84 }
201
202 std::string SHA256::toString(const uint8_t* digest)
203 {
204 std::stringstream s;
205 s << std::setfill('0') << std::hex;
206
207 for (uint8_t i = 0; i < 32; i++)
208 {
209 s << std::setw(2) << static_cast<unsigned int>(digest[i]); // NOLINT
210 }
211
212 return s.str();
213 }
214
215 } // namespace NAV
216
217 #if defined(__clang__)
218 #pragma GCC diagnostic pop
219 #endif
220 // NOLINTEND
221