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

randombit / botan / 19671441278

25 Nov 2025 01:37PM UTC coverage: 90.358% (-0.3%) from 90.668%
19671441278

Pull #4540

github

web-flow
Merge 438f4f7dd into 222c91120
Pull Request #4540: PKCS #11 Version 3.2 Support

100942 of 111713 relevant lines covered (90.36%)

12822105.04 hits per line

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

95.83
/src/lib/hash/blake2s/blake2s.cpp
1
/*
2
 * BLAKE2s
3
 * (C) 2023, 2025       Richard Huveneers
4
 * (C) 2025             Kagan Can Sit
5
 * (C) 2025             René Meusel, Rohde & Schwarz Cybersecurity
6
 *
7
 * Based on the RFC7693 reference implementation
8
 *
9
 * Botan is released under the Simplified BSD License (see license.txt)
10
 */
11

12
#include <botan/internal/blake2s.h>
13

14
#include <botan/exceptn.h>
15
#include <botan/internal/fmt.h>
16
#include <botan/internal/loadstor.h>
17
#include <botan/internal/rotate.h>
18
#include <botan/internal/stl_util.h>
19

20
namespace Botan {
21

22
namespace {
23

24
// Initialization Vector.
25

26
constexpr std::array<uint32_t, 8> blake2s_iv{
27
   0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19};
28

29
// Mixing function G.
30

31
template <uint8_t a, uint8_t b, uint8_t c, uint8_t d>
32
   requires(a < 16 && b < 16 && c < 16 && d < 16)
33
constexpr void B2S_G(uint32_t x, uint32_t y, std::span<uint32_t, 16> v) {
407,120✔
34
   v[a] = v[a] + v[b] + x;
407,120✔
35
   v[d] = rotr<16>(v[d] ^ v[a]);
407,120✔
36
   v[c] = v[c] + v[d];
407,120✔
37
   v[b] = rotr<12>(v[b] ^ v[c]);
407,120✔
38
   v[a] = v[a] + v[b] + y;
407,120✔
39
   v[d] = rotr<8>(v[d] ^ v[a]);
407,120✔
40
   v[c] = v[c] + v[d];
407,120✔
41
   v[b] = rotr<7>(v[b] ^ v[c]);
407,120✔
42
}
407,120✔
43

44
}  // namespace
45

46
std::string BLAKE2s::name() const {
771✔
47
   return fmt("BLAKE2s({})", m_outlen << 3);
771✔
48
}
49

50
// BLAKE2s is specified as a message authentication code. For that, the
51
// key would need to be zero-padded and incorporated into the initial hash
52
// state. See RFC 7693 Section 3.3 and Appendix D.2 `blake2s_init()`.
53
void BLAKE2s::state_init(size_t outlen) {
3,069✔
54
   m_h = blake2s_iv;  // state, "param block"
3,069✔
55
   m_h[0] ^= 0x01010000 ^ outlen;
3,069✔
56

57
   m_bytes_processed = 0;
3,069✔
58
   m_outlen = outlen;
3,069✔
59
   m_buffer.clear();
×
60
}
×
61

62
// Compression function. "last" flag indicates last block.
63
void BLAKE2s::compress(bool last, std::span<const uint8_t> buf) {
5,089✔
64
   BOTAN_ASSERT_NOMSG(buf.size() == block_size);
5,089✔
65
   constexpr std::array<std::array<uint8_t, 16>, 10> sigma{{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
5,089✔
66
                                                            {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
67
                                                            {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
68
                                                            {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
69
                                                            {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
70
                                                            {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
71
                                                            {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
72
                                                            {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
73
                                                            {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
74
                                                            {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0}}};
75

76
   // init work variables
77
   std::array<uint32_t, 16> v = concat(m_h, blake2s_iv);
5,089✔
78

79
   v[12] ^= static_cast<uint32_t>(m_bytes_processed);
5,089✔
80
   v[13] ^= static_cast<uint32_t>(m_bytes_processed >> 32);
5,089✔
81
   if(last) {  // last block flag set ?
5,089✔
82
      v[14] = ~v[14];
2,041✔
83
   }
84

85
   const auto m = load_le<std::array<uint32_t, 16>>(buf);  // get little-endian words
5,089✔
86

87
   for(const auto& perm : sigma) {  // ten rounds
55,979✔
88
      B2S_G<0, 4, 8, 12>(m[perm[0]], m[perm[1]], v);
50,890✔
89
      B2S_G<1, 5, 9, 13>(m[perm[2]], m[perm[3]], v);
50,890✔
90
      B2S_G<2, 6, 10, 14>(m[perm[4]], m[perm[5]], v);
50,890✔
91
      B2S_G<3, 7, 11, 15>(m[perm[6]], m[perm[7]], v);
50,890✔
92
      B2S_G<0, 5, 10, 15>(m[perm[8]], m[perm[9]], v);
50,890✔
93
      B2S_G<1, 6, 11, 12>(m[perm[10]], m[perm[11]], v);
50,890✔
94
      B2S_G<2, 7, 8, 13>(m[perm[12]], m[perm[13]], v);
50,890✔
95
      B2S_G<3, 4, 9, 14>(m[perm[14]], m[perm[15]], v);
50,890✔
96
   }
97

98
   for(size_t i = 0; i < 8; ++i) {
45,801✔
99
      m_h[i] ^= v[i] ^ v[i + 8];
40,712✔
100
   }
101
}
5,089✔
102

103
/*
104
 * Clear memory of sensitive data
105
 */
106
void BLAKE2s::clear() {
2,298✔
107
   state_init(m_outlen);
2,298✔
108
}
2,298✔
109

110
void BLAKE2s::add_data(std::span<const uint8_t> input) {
4,684✔
111
   BufferSlicer in(input);
4,684✔
112

113
   while(!in.empty()) {
15,157✔
114
      if(const auto one_block = m_buffer.handle_unaligned_data(in)) {
5,789✔
115
         m_bytes_processed += block_size;
508✔
116
         compress(false, *one_block);
508✔
117
      }
118

119
      if(m_buffer.in_alignment()) {
5,789✔
120
         while(const auto aligned_block = m_buffer.next_aligned_block_to_process(in)) {
4,194✔
121
            m_bytes_processed += block_size;
2,540✔
122
            compress(false, *aligned_block);
2,540✔
123
         }
2,540✔
124
      }
125
   }
126
}
4,684✔
127

128
void BLAKE2s::final_result(std::span<uint8_t> out) {
2,041✔
129
   m_bytes_processed += m_buffer.elements_in_buffer();
2,041✔
130

131
   m_buffer.fill_up_with_zeros();
2,041✔
132
   compress(true, m_buffer.consume());
2,041✔
133

134
   // little endian convert and store
135
   copy_out_le(out.first(output_length()), m_h);
2,041✔
136

137
   clear();
2,041✔
138
}
2,041✔
139

140
std::unique_ptr<HashFunction> BLAKE2s::copy_state() const {
250✔
141
   return std::make_unique<BLAKE2s>(*this);
250✔
142
}
143

144
/*
145
 * BLAKE2s Constructor
146
 */
147
BLAKE2s::BLAKE2s(size_t output_bits) {
771✔
148
   if(output_bits == 0 || output_bits > 256 || output_bits % 8 != 0) {
771✔
149
      throw Invalid_Argument("Bad output bits size for BLAKE2s");
×
150
   }
151
   state_init(output_bits >> 3);
771✔
152
}
771✔
153

154
BLAKE2s::~BLAKE2s() {
2,042✔
155
   secure_scrub_memory(m_h);
1,021✔
156
}
2,042✔
157

158
}  // 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