Coverage Report

Created: 2022-11-24 06:56

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