• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 21712952425

05 Feb 2026 01:16PM UTC coverage: 90.076% (+0.005%) from 90.071%
21712952425

Pull #5287

github

web-flow
Merge 1b320c06e into 8c9623340
Pull Request #5287: Split out BufferSlicer and BufferStuffer to their own headers

102242 of 113507 relevant lines covered (90.08%)

11534589.25 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.07
/src/lib/hash/blake2/blake2b.cpp
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

11
#include <botan/exceptn.h>
12
#include <botan/mem_ops.h>
13
#include <botan/internal/fmt.h>
14
#include <botan/internal/loadstor.h>
15
#include <botan/internal/rotate.h>
16
#include <array>
17

18
namespace Botan {
19

20
namespace {
21

22
constexpr std::array<uint64_t, 8> blake2b_IV{0x6a09e667f3bcc908,
23
                                             0xbb67ae8584caa73b,
24
                                             0x3c6ef372fe94f82b,
25
                                             0xa54ff53a5f1d36f1,
26
                                             0x510e527fade682d1,
27
                                             0x9b05688c2b3e6c1f,
28
                                             0x1f83d9abfb41bd6b,
29
                                             0x5be0cd19137e2179};
30

31
}  // namespace
32

33
BLAKE2b::BLAKE2b(size_t output_bits) : m_output_bits(output_bits), m_H(blake2b_IV.size()), m_T(), m_F(), m_key_size(0) {
18,660✔
34
   if(output_bits == 0 || output_bits > 512 || output_bits % 8 != 0) {
6,220✔
35
      throw Invalid_Argument("Bad output bits size for BLAKE2b");
1✔
36
   }
37

38
   state_init();
6,219✔
39
}
6,221✔
40

41
void BLAKE2b::state_init() {
227,750✔
42
   copy_mem(m_H.data(), blake2b_IV.data(), blake2b_IV.size());
227,750✔
43
   m_H[0] ^= (0x01010000 | (static_cast<uint8_t>(m_key_size) << 8) | static_cast<uint8_t>(output_length()));
227,750✔
44
   m_T[0] = m_T[1] = 0;
227,750✔
45
   m_F = 0;
227,750✔
46

47
   m_buffer.clear();
227,750✔
48
   if(m_key_size > 0) {
227,750✔
49
      m_buffer.append(m_padded_key_buffer);
4,597✔
50
   }
51
}
227,750✔
52

53
namespace {
54

55
BOTAN_FORCE_INLINE void G(uint64_t& a, uint64_t& b, uint64_t& c, uint64_t& d, uint64_t M0, uint64_t M1) {
234,547✔
56
   a = a + b + M0;
234,547✔
57
   d = rotr<32>(d ^ a);
234,547✔
58
   c = c + d;
234,547✔
59
   b = rotr<24>(b ^ c);
234,547✔
60
   a = a + b + M1;
234,547✔
61
   d = rotr<16>(d ^ a);
234,547✔
62
   c = c + d;
234,547✔
63
   b = rotr<63>(b ^ c);
234,547✔
64
}
65

66
template <size_t i0,
67
          size_t i1,
68
          size_t i2,
69
          size_t i3,
70
          size_t i4,
71
          size_t i5,
72
          size_t i6,
73
          size_t i7,
74
          size_t i8,
75
          size_t i9,
76
          size_t iA,
77
          size_t iB,
78
          size_t iC,
79
          size_t iD,
80
          size_t iE,
81
          size_t iF>
82
BOTAN_FORCE_INLINE void ROUND(uint64_t* v, const uint64_t* M) {
234,547✔
83
   G(v[0], v[4], v[8], v[12], M[i0], M[i1]);
234,547✔
84
   G(v[1], v[5], v[9], v[13], M[i2], M[i3]);
234,547✔
85
   G(v[2], v[6], v[10], v[14], M[i4], M[i5]);
234,547✔
86
   G(v[3], v[7], v[11], v[15], M[i6], M[i7]);
234,547✔
87
   G(v[0], v[5], v[10], v[15], M[i8], M[i9]);
234,547✔
88
   G(v[1], v[6], v[11], v[12], M[iA], M[iB]);
234,547✔
89
   G(v[2], v[7], v[8], v[13], M[iC], M[iD]);
234,547✔
90
   G(v[3], v[4], v[9], v[14], M[iE], M[iF]);
234,547✔
91
}
92

93
}  // namespace
94

95
void BLAKE2b::compress(const uint8_t* input, size_t blocks, uint64_t increment) {
234,323✔
96
   for(size_t b = 0; b != blocks; ++b) {
468,870✔
97
      m_T[0] += increment;
234,547✔
98
      if(m_T[0] < increment) {
234,547✔
99
         m_T[1]++;
×
100
      }
101

102
      uint64_t M[16];
234,547✔
103
      uint64_t v[16];
234,547✔
104
      load_le(M, input, 16);
234,547✔
105

106
      input += BLAKE2B_BLOCKBYTES;
234,547✔
107

108
      for(size_t i = 0; i < 8; i++) {
2,110,923✔
109
         v[i] = m_H[i];
1,876,376✔
110
      }
111
      for(size_t i = 0; i != 8; ++i) {
2,110,923✔
112
         v[i + 8] = blake2b_IV[i];
1,876,376✔
113
      }
114

115
      v[12] ^= m_T[0];
234,547✔
116
      v[13] ^= m_T[1];
234,547✔
117
      v[14] ^= m_F;
234,547✔
118

119
      ROUND<0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15>(v, M);
234,547✔
120
      ROUND<14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3>(v, M);
234,547✔
121
      ROUND<11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4>(v, M);
234,547✔
122
      ROUND<7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8>(v, M);
234,547✔
123
      ROUND<9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13>(v, M);
234,547✔
124
      ROUND<2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9>(v, M);
234,547✔
125
      ROUND<12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11>(v, M);
234,547✔
126
      ROUND<13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10>(v, M);
234,547✔
127
      ROUND<6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5>(v, M);
234,547✔
128
      ROUND<10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0>(v, M);
234,547✔
129
      ROUND<0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15>(v, M);
234,547✔
130
      ROUND<14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3>(v, M);
234,547✔
131

132
      for(size_t i = 0; i < 8; i++) {
2,110,923✔
133
         m_H[i] ^= v[i] ^ v[i + 8];
1,876,376✔
134
      }
135
   }
136
}
234,323✔
137

138
void BLAKE2b::add_data(std::span<const uint8_t> input) {
403,400✔
139
   BufferSlicer in(input);
403,400✔
140

141
   while(!in.empty()) {
1,221,930✔
142
      if(const auto one_block = m_buffer.handle_unaligned_data(in)) {
415,130✔
143
         compress(one_block->data(), 1, BLAKE2B_BLOCKBYTES);
12,920✔
144
      }
145

146
      if(m_buffer.in_alignment()) {
415,130✔
147
         const auto [aligned_data, full_blocks] = m_buffer.aligned_data_to_process(in);
15,304✔
148
         if(full_blocks > 0) {
15,304✔
149
            compress(aligned_data.data(), full_blocks, BLAKE2B_BLOCKBYTES);
3,351✔
150
         }
151
      }
152
   }
153
}
403,400✔
154

155
void BLAKE2b::final_result(std::span<uint8_t> output) {
218,052✔
156
   const auto pos = m_buffer.elements_in_buffer();
218,052✔
157
   m_buffer.fill_up_with_zeros();
218,052✔
158

159
   m_F = 0xFFFFFFFFFFFFFFFF;
218,052✔
160
   compress(m_buffer.consume().data(), 1, pos);
218,052✔
161
   copy_out_le(output.first(output_length()), m_H);
218,052✔
162
   state_init();
218,052✔
163
}
218,052✔
164

165
Key_Length_Specification BLAKE2b::key_spec() const {
4,324✔
166
   return Key_Length_Specification(1, 64);
4,324✔
167
}
168

169
std::string BLAKE2b::name() const {
3,951✔
170
   return fmt("BLAKE2b({})", m_output_bits);
3,951✔
171
}
172

173
std::unique_ptr<HashFunction> BLAKE2b::new_object() const {
771✔
174
   return std::make_unique<BLAKE2b>(m_output_bits);
771✔
175
}
176

177
std::unique_ptr<HashFunction> BLAKE2b::copy_state() const {
753✔
178
   return std::make_unique<BLAKE2b>(*this);
753✔
179
}
180

181
bool BLAKE2b::has_keying_material() const {
8,102✔
182
   return m_key_size > 0;
8,102✔
183
}
184

185
void BLAKE2b::key_schedule(std::span<const uint8_t> key) {
2,162✔
186
   BOTAN_ASSERT_NOMSG(key.size() <= m_buffer.size());
2,162✔
187

188
   m_key_size = key.size();
2,162✔
189
   m_padded_key_buffer.resize(m_buffer.size());
2,162✔
190

191
   if(m_padded_key_buffer.size() > m_key_size) {
2,162✔
192
      const size_t padding = m_padded_key_buffer.size() - m_key_size;
2,162✔
193
      clear_mem(m_padded_key_buffer.data() + m_key_size, padding);
2,162✔
194
   }
195

196
   copy_mem(m_padded_key_buffer.data(), key.data(), key.size());
2,162✔
197
   state_init();
2,162✔
198
}
2,162✔
199

200
void BLAKE2b::clear() {
1,317✔
201
   zeroise(m_H);
1,317✔
202
   m_buffer.clear();
1,317✔
203
   zeroise(m_padded_key_buffer);
1,317✔
204
   m_key_size = 0;
1,317✔
205
   state_init();
1,317✔
206
}
1,317✔
207

208
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc