Coverage Report

Created: 2024-02-25 06:16

/src/botan/src/lib/mac/siphash/siphash.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* SipHash
3
* (C) 2014,2015 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/internal/siphash.h>
9
10
#include <botan/internal/fmt.h>
11
#include <botan/internal/loadstor.h>
12
#include <botan/internal/rotate.h>
13
#include <botan/internal/stl_util.h>
14
15
namespace Botan {
16
17
namespace {
18
19
1.32k
void SipRounds(uint64_t M, secure_vector<uint64_t>& V, size_t r) {
20
1.32k
   uint64_t V0 = V[0], V1 = V[1], V2 = V[2], V3 = V[3];
21
22
1.32k
   V3 ^= M;
23
4.31k
   for(size_t i = 0; i != r; ++i) {
24
2.98k
      V0 += V1;
25
2.98k
      V2 += V3;
26
2.98k
      V1 = rotl<13>(V1);
27
2.98k
      V3 = rotl<16>(V3);
28
2.98k
      V1 ^= V0;
29
2.98k
      V3 ^= V2;
30
2.98k
      V0 = rotl<32>(V0);
31
32
2.98k
      V2 += V1;
33
2.98k
      V0 += V3;
34
2.98k
      V1 = rotl<17>(V1);
35
2.98k
      V3 = rotl<21>(V3);
36
2.98k
      V1 ^= V2;
37
2.98k
      V3 ^= V0;
38
2.98k
      V2 = rotl<32>(V2);
39
2.98k
   }
40
1.32k
   V0 ^= M;
41
42
1.32k
   V[0] = V0;
43
1.32k
   V[1] = V1;
44
1.32k
   V[2] = V2;
45
1.32k
   V[3] = V3;
46
1.32k
}
47
48
}  // namespace
49
50
5.11k
void SipHash::add_data(std::span<const uint8_t> input) {
51
5.11k
   assert_key_material_set();
52
53
   // SipHash counts the message length mod 256
54
5.11k
   m_words += static_cast<uint8_t>(input.size());
55
56
5.11k
   BufferSlicer in(input);
57
58
5.11k
   if(m_mbuf_pos) {
59
3.68k
      while(!in.empty() && m_mbuf_pos != 8) {
60
1.63k
         m_mbuf = (m_mbuf >> 8) | (static_cast<uint64_t>(in.take_byte()) << 56);
61
1.63k
         ++m_mbuf_pos;
62
1.63k
      }
63
64
2.04k
      if(m_mbuf_pos == 8) {
65
374
         SipRounds(m_mbuf, m_V, m_C);
66
374
         m_mbuf_pos = 0;
67
374
         m_mbuf = 0;
68
374
      }
69
2.04k
   }
70
71
5.73k
   while(in.remaining() >= 8) {
72
627
      SipRounds(load_le<uint64_t>(in.take(8).data(), 0), m_V, m_C);
73
627
   }
74
75
6.63k
   while(!in.empty()) {
76
1.51k
      m_mbuf = (m_mbuf >> 8) | (static_cast<uint64_t>(in.take_byte()) << 56);
77
1.51k
      m_mbuf_pos++;
78
1.51k
   }
79
5.11k
}
80
81
164
void SipHash::final_result(std::span<uint8_t> mac) {
82
164
   assert_key_material_set();
83
84
164
   if(m_mbuf_pos == 0) {
85
59
      m_mbuf = (static_cast<uint64_t>(m_words) << 56);
86
105
   } else if(m_mbuf_pos < 8) {
87
105
      m_mbuf = (m_mbuf >> (64 - m_mbuf_pos * 8)) | (static_cast<uint64_t>(m_words) << 56);
88
105
   }
89
90
164
   SipRounds(m_mbuf, m_V, m_C);
91
92
164
   m_V[2] ^= 0xFF;
93
164
   SipRounds(0, m_V, m_D);
94
95
164
   const uint64_t X = m_V[0] ^ m_V[1] ^ m_V[2] ^ m_V[3];
96
97
164
   store_le(X, mac.data());
98
99
164
   m_V[0] = m_K[0] ^ 0x736F6D6570736575;
100
164
   m_V[1] = m_K[1] ^ 0x646F72616E646F6D;
101
164
   m_V[2] = m_K[0] ^ 0x6C7967656E657261;
102
164
   m_V[3] = m_K[1] ^ 0x7465646279746573;
103
164
   m_mbuf = 0;
104
164
   m_mbuf_pos = 0;
105
164
   m_words = 0;
106
164
}
107
108
5.27k
bool SipHash::has_keying_material() const {
109
5.27k
   return !m_V.empty();
110
5.27k
}
111
112
164
void SipHash::key_schedule(std::span<const uint8_t> key) {
113
164
   const uint64_t K0 = load_le<uint64_t>(key.data(), 0);
114
164
   const uint64_t K1 = load_le<uint64_t>(key.data(), 1);
115
116
164
   m_K.resize(2);
117
164
   m_K[0] = K0;
118
164
   m_K[1] = K1;
119
120
164
   m_V.resize(4);
121
164
   m_V[0] = m_K[0] ^ 0x736F6D6570736575;
122
164
   m_V[1] = m_K[1] ^ 0x646F72616E646F6D;
123
164
   m_V[2] = m_K[0] ^ 0x6C7967656E657261;
124
164
   m_V[3] = m_K[1] ^ 0x7465646279746573;
125
164
}
126
127
0
void SipHash::clear() {
128
0
   zap(m_K);
129
0
   zap(m_V);
130
0
   m_mbuf = 0;
131
0
   m_mbuf_pos = 0;
132
0
   m_words = 0;
133
0
}
134
135
34
std::string SipHash::name() const {
136
34
   return fmt("SipHash({},{})", m_C, m_D);
137
34
}
138
139
0
std::unique_ptr<MessageAuthenticationCode> SipHash::new_object() const {
140
0
   return std::make_unique<SipHash>(m_C, m_D);
141
0
}
142
143
}  // namespace Botan