/src/botan/src/lib/hash/blake2/blake2b.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * BLAKE2b |
3 | | * (C) 2016 cynecx |
4 | | * (C) 2017 Jack Lloyd |
5 | | * |
6 | | * Botan is released under the Simplified BSD License (see license.txt) |
7 | | */ |
8 | | |
9 | | #include <botan/internal/blake2b.h> |
10 | | #include <botan/exceptn.h> |
11 | | #include <botan/mem_ops.h> |
12 | | #include <botan/internal/loadstor.h> |
13 | | #include <botan/internal/rotate.h> |
14 | | #include <algorithm> |
15 | | |
16 | | namespace Botan { |
17 | | |
18 | | namespace { |
19 | | |
20 | | enum blake2b_constant { |
21 | | BLAKE2B_BLOCKBYTES = 128, |
22 | | BLAKE2B_IVU64COUNT = 8 |
23 | | }; |
24 | | |
25 | | const uint64_t blake2b_IV[BLAKE2B_IVU64COUNT] = { |
26 | | 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, |
27 | | 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, |
28 | | 0x510e527fade682d1, 0x9b05688c2b3e6c1f, |
29 | | 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179 |
30 | | }; |
31 | | |
32 | | } |
33 | | |
34 | | BLAKE2b::BLAKE2b(size_t output_bits) : |
35 | | m_output_bits(output_bits), |
36 | | m_buffer(BLAKE2B_BLOCKBYTES), |
37 | | m_bufpos(0), |
38 | | m_H(BLAKE2B_IVU64COUNT), |
39 | | m_key_size(0) |
40 | 0 | { |
41 | 0 | if(output_bits == 0 || output_bits > 512 || output_bits % 8 != 0) |
42 | 0 | { |
43 | 0 | throw Invalid_Argument("Bad output bits size for BLAKE2b"); |
44 | 0 | } |
45 | | |
46 | 0 | state_init(); |
47 | 0 | } |
48 | | |
49 | | void BLAKE2b::state_init() |
50 | 0 | { |
51 | 0 | copy_mem(m_H.data(), blake2b_IV, BLAKE2B_IVU64COUNT); |
52 | 0 | m_H[0] ^= (0x01010000 | (static_cast<uint8_t>(m_key_size) << 8) | static_cast<uint8_t>(output_length())); |
53 | 0 | m_T[0] = m_T[1] = 0; |
54 | 0 | m_F[0] = m_F[1] = 0; |
55 | |
|
56 | 0 | if(m_key_size == 0) |
57 | 0 | { |
58 | 0 | m_bufpos = 0; |
59 | 0 | } |
60 | 0 | else |
61 | 0 | { |
62 | 0 | BOTAN_ASSERT_NOMSG(m_padded_key_buffer.size() == m_buffer.size()); |
63 | 0 | copy_mem(m_buffer.data(), m_padded_key_buffer.data(), m_padded_key_buffer.size()); |
64 | 0 | m_bufpos = m_padded_key_buffer.size(); |
65 | 0 | } |
66 | 0 | } |
67 | | |
68 | | namespace { |
69 | | |
70 | | BOTAN_FORCE_INLINE void G(uint64_t& a, uint64_t& b, uint64_t& c, uint64_t& d, |
71 | | uint64_t M0, uint64_t M1) |
72 | 0 | { |
73 | 0 | a = a + b + M0; |
74 | 0 | d = rotr<32>(d ^ a); |
75 | 0 | c = c + d; |
76 | 0 | b = rotr<24>(b ^ c); |
77 | 0 | a = a + b + M1; |
78 | 0 | d = rotr<16>(d ^ a); |
79 | 0 | c = c + d; |
80 | 0 | b = rotr<63>(b ^ c); |
81 | 0 | } |
82 | | |
83 | | template<size_t i0, size_t i1, size_t i2, size_t i3, size_t i4, size_t i5, size_t i6, size_t i7, |
84 | | size_t i8, size_t i9, size_t iA, size_t iB, size_t iC, size_t iD, size_t iE, size_t iF> |
85 | | BOTAN_FORCE_INLINE void ROUND(uint64_t* v, const uint64_t* M) |
86 | 0 | { |
87 | 0 | G(v[ 0], v[ 4], v[ 8], v[12], M[i0], M[i1]); |
88 | 0 | G(v[ 1], v[ 5], v[ 9], v[13], M[i2], M[i3]); |
89 | 0 | G(v[ 2], v[ 6], v[10], v[14], M[i4], M[i5]); |
90 | 0 | G(v[ 3], v[ 7], v[11], v[15], M[i6], M[i7]); |
91 | 0 | G(v[ 0], v[ 5], v[10], v[15], M[i8], M[i9]); |
92 | 0 | G(v[ 1], v[ 6], v[11], v[12], M[iA], M[iB]); |
93 | 0 | G(v[ 2], v[ 7], v[ 8], v[13], M[iC], M[iD]); |
94 | 0 | G(v[ 3], v[ 4], v[ 9], v[14], M[iE], M[iF]); |
95 | 0 | } Unexecuted instantiation: blake2b.cpp:void Botan::(anonymous namespace)::ROUND<0ul, 1ul, 2ul, 3ul, 4ul, 5ul, 6ul, 7ul, 8ul, 9ul, 10ul, 11ul, 12ul, 13ul, 14ul, 15ul>(unsigned long*, unsigned long const*) Unexecuted instantiation: blake2b.cpp:void Botan::(anonymous namespace)::ROUND<14ul, 10ul, 4ul, 8ul, 9ul, 15ul, 13ul, 6ul, 1ul, 12ul, 0ul, 2ul, 11ul, 7ul, 5ul, 3ul>(unsigned long*, unsigned long const*) Unexecuted instantiation: blake2b.cpp:void Botan::(anonymous namespace)::ROUND<11ul, 8ul, 12ul, 0ul, 5ul, 2ul, 15ul, 13ul, 10ul, 14ul, 3ul, 6ul, 7ul, 1ul, 9ul, 4ul>(unsigned long*, unsigned long const*) Unexecuted instantiation: blake2b.cpp:void Botan::(anonymous namespace)::ROUND<7ul, 9ul, 3ul, 1ul, 13ul, 12ul, 11ul, 14ul, 2ul, 6ul, 5ul, 10ul, 4ul, 0ul, 15ul, 8ul>(unsigned long*, unsigned long const*) Unexecuted instantiation: blake2b.cpp:void Botan::(anonymous namespace)::ROUND<9ul, 0ul, 5ul, 7ul, 2ul, 4ul, 10ul, 15ul, 14ul, 1ul, 11ul, 12ul, 6ul, 8ul, 3ul, 13ul>(unsigned long*, unsigned long const*) Unexecuted instantiation: blake2b.cpp:void Botan::(anonymous namespace)::ROUND<2ul, 12ul, 6ul, 10ul, 0ul, 11ul, 8ul, 3ul, 4ul, 13ul, 7ul, 5ul, 15ul, 14ul, 1ul, 9ul>(unsigned long*, unsigned long const*) Unexecuted instantiation: blake2b.cpp:void Botan::(anonymous namespace)::ROUND<12ul, 5ul, 1ul, 15ul, 14ul, 13ul, 4ul, 10ul, 0ul, 7ul, 6ul, 3ul, 9ul, 2ul, 8ul, 11ul>(unsigned long*, unsigned long const*) Unexecuted instantiation: blake2b.cpp:void Botan::(anonymous namespace)::ROUND<13ul, 11ul, 7ul, 14ul, 12ul, 1ul, 3ul, 9ul, 5ul, 0ul, 15ul, 4ul, 8ul, 6ul, 2ul, 10ul>(unsigned long*, unsigned long const*) Unexecuted instantiation: blake2b.cpp:void Botan::(anonymous namespace)::ROUND<6ul, 15ul, 14ul, 9ul, 11ul, 3ul, 0ul, 8ul, 12ul, 2ul, 13ul, 7ul, 1ul, 4ul, 10ul, 5ul>(unsigned long*, unsigned long const*) Unexecuted instantiation: blake2b.cpp:void Botan::(anonymous namespace)::ROUND<10ul, 2ul, 8ul, 4ul, 7ul, 6ul, 1ul, 5ul, 15ul, 11ul, 9ul, 14ul, 3ul, 12ul, 13ul, 0ul>(unsigned long*, unsigned long const*) |
96 | | |
97 | | |
98 | | } |
99 | | |
100 | | void BLAKE2b::compress(const uint8_t* input, size_t blocks, uint64_t increment) |
101 | 0 | { |
102 | 0 | for(size_t b = 0; b != blocks; ++b) |
103 | 0 | { |
104 | 0 | m_T[0] += increment; |
105 | 0 | if(m_T[0] < increment) |
106 | 0 | { |
107 | 0 | m_T[1]++; |
108 | 0 | } |
109 | |
|
110 | 0 | uint64_t M[16]; |
111 | 0 | uint64_t v[16]; |
112 | 0 | load_le(M, input, 16); |
113 | |
|
114 | 0 | input += BLAKE2B_BLOCKBYTES; |
115 | |
|
116 | 0 | for(size_t i = 0; i < 8; i++) |
117 | 0 | v[i] = m_H[i]; |
118 | 0 | for(size_t i = 0; i != 8; ++i) |
119 | 0 | v[i + 8] = blake2b_IV[i]; |
120 | |
|
121 | 0 | v[12] ^= m_T[0]; |
122 | 0 | v[13] ^= m_T[1]; |
123 | 0 | v[14] ^= m_F[0]; |
124 | 0 | v[15] ^= m_F[1]; |
125 | |
|
126 | 0 | ROUND< 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15>(v, M); |
127 | 0 | ROUND<14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3>(v, M); |
128 | 0 | ROUND<11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4>(v, M); |
129 | 0 | ROUND< 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8>(v, M); |
130 | 0 | ROUND< 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13>(v, M); |
131 | 0 | ROUND< 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9>(v, M); |
132 | 0 | ROUND<12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11>(v, M); |
133 | 0 | ROUND<13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10>(v, M); |
134 | 0 | ROUND< 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5>(v, M); |
135 | 0 | ROUND<10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0>(v, M); |
136 | 0 | ROUND< 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15>(v, M); |
137 | 0 | ROUND<14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3>(v, M); |
138 | |
|
139 | 0 | for(size_t i = 0; i < 8; i++) |
140 | 0 | { |
141 | 0 | m_H[i] ^= v[i] ^ v[i + 8]; |
142 | 0 | } |
143 | 0 | } |
144 | 0 | } |
145 | | |
146 | | void BLAKE2b::add_data(const uint8_t input[], size_t length) |
147 | 0 | { |
148 | 0 | if(length == 0) |
149 | 0 | return; |
150 | | |
151 | 0 | if(m_bufpos > 0) |
152 | 0 | { |
153 | 0 | if(m_bufpos < BLAKE2B_BLOCKBYTES) |
154 | 0 | { |
155 | 0 | const size_t take = std::min(BLAKE2B_BLOCKBYTES - m_bufpos, length); |
156 | 0 | copy_mem(&m_buffer[m_bufpos], input, take); |
157 | 0 | m_bufpos += take; |
158 | 0 | length -= take; |
159 | 0 | input += take; |
160 | 0 | } |
161 | |
|
162 | 0 | if(m_bufpos == m_buffer.size() && length > 0) |
163 | 0 | { |
164 | 0 | compress(m_buffer.data(), 1, BLAKE2B_BLOCKBYTES); |
165 | 0 | m_bufpos = 0; |
166 | 0 | } |
167 | 0 | } |
168 | |
|
169 | 0 | if(length > BLAKE2B_BLOCKBYTES) |
170 | 0 | { |
171 | 0 | const size_t full_blocks = ((length-1) / BLAKE2B_BLOCKBYTES); |
172 | 0 | compress(input, full_blocks, BLAKE2B_BLOCKBYTES); |
173 | |
|
174 | 0 | input += full_blocks * BLAKE2B_BLOCKBYTES; |
175 | 0 | length -= full_blocks * BLAKE2B_BLOCKBYTES; |
176 | 0 | } |
177 | |
|
178 | 0 | if(length > 0) |
179 | 0 | { |
180 | 0 | copy_mem(&m_buffer[m_bufpos], input, length); |
181 | 0 | m_bufpos += length; |
182 | 0 | } |
183 | 0 | } |
184 | | |
185 | | void BLAKE2b::final_result(uint8_t output[]) |
186 | 0 | { |
187 | 0 | if(m_bufpos != BLAKE2B_BLOCKBYTES) |
188 | 0 | clear_mem(&m_buffer[m_bufpos], BLAKE2B_BLOCKBYTES - m_bufpos); |
189 | 0 | m_F[0] = 0xFFFFFFFFFFFFFFFF; |
190 | 0 | compress(m_buffer.data(), 1, m_bufpos); |
191 | 0 | copy_out_vec_le(output, output_length(), m_H); |
192 | 0 | state_init(); |
193 | 0 | } |
194 | | |
195 | | Key_Length_Specification BLAKE2b::key_spec() const |
196 | 0 | { |
197 | 0 | return Key_Length_Specification(0, 64); |
198 | 0 | } |
199 | | |
200 | | std::string BLAKE2b::name() const |
201 | 0 | { |
202 | 0 | return "BLAKE2b(" + std::to_string(m_output_bits) + ")"; |
203 | 0 | } |
204 | | |
205 | | std::unique_ptr<HashFunction> BLAKE2b::new_object() const |
206 | 0 | { |
207 | 0 | return std::make_unique<BLAKE2b>(m_output_bits); |
208 | 0 | } |
209 | | |
210 | | std::unique_ptr<HashFunction> BLAKE2b::copy_state() const |
211 | 0 | { |
212 | 0 | return std::make_unique<BLAKE2b>(*this); |
213 | 0 | } |
214 | | |
215 | | void BLAKE2b::key_schedule(const uint8_t key[], size_t length) |
216 | 0 | { |
217 | 0 | BOTAN_ASSERT_NOMSG(length <= m_buffer.size()); |
218 | |
|
219 | 0 | m_key_size = length; |
220 | 0 | m_padded_key_buffer.resize(m_buffer.size()); |
221 | |
|
222 | 0 | if(m_padded_key_buffer.size() > length) |
223 | 0 | { |
224 | 0 | size_t padding = m_padded_key_buffer.size() - length; |
225 | 0 | clear_mem(m_padded_key_buffer.data() + length, padding); |
226 | 0 | } |
227 | |
|
228 | 0 | copy_mem(m_padded_key_buffer.data(), key, length); |
229 | 0 | state_init(); |
230 | 0 | } |
231 | | |
232 | | void BLAKE2b::clear() |
233 | 0 | { |
234 | 0 | zeroise(m_H); |
235 | 0 | zeroise(m_buffer); |
236 | 0 | zeroise(m_padded_key_buffer); |
237 | 0 | m_bufpos = 0; |
238 | 0 | m_key_size = 0; |
239 | 0 | state_init(); |
240 | 0 | } |
241 | | |
242 | | } |