Botan 3.6.1
Crypto and TLS for C&
siphash.cpp
Go to the documentation of this file.
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
15namespace Botan {
16
17namespace {
18
19void SipRounds(uint64_t M, secure_vector<uint64_t>& V, size_t r) {
20 uint64_t V0 = V[0], V1 = V[1], V2 = V[2], V3 = V[3];
21
22 V3 ^= M;
23 for(size_t i = 0; i != r; ++i) {
24 V0 += V1;
25 V2 += V3;
26 V1 = rotl<13>(V1);
27 V3 = rotl<16>(V3);
28 V1 ^= V0;
29 V3 ^= V2;
30 V0 = rotl<32>(V0);
31
32 V2 += V1;
33 V0 += V3;
34 V1 = rotl<17>(V1);
35 V3 = rotl<21>(V3);
36 V1 ^= V2;
37 V3 ^= V0;
38 V2 = rotl<32>(V2);
39 }
40 V0 ^= M;
41
42 V[0] = V0;
43 V[1] = V1;
44 V[2] = V2;
45 V[3] = V3;
46}
47
48} // namespace
49
50void SipHash::add_data(std::span<const uint8_t> input) {
52
53 // SipHash counts the message length mod 256
54 m_words += static_cast<uint8_t>(input.size());
55
56 BufferSlicer in(input);
57
58 if(m_mbuf_pos) {
59 while(!in.empty() && m_mbuf_pos != 8) {
60 m_mbuf = (m_mbuf >> 8) | (static_cast<uint64_t>(in.take_byte()) << 56);
61 ++m_mbuf_pos;
62 }
63
64 if(m_mbuf_pos == 8) {
65 SipRounds(m_mbuf, m_V, m_C);
66 m_mbuf_pos = 0;
67 m_mbuf = 0;
68 }
69 }
70
71 while(in.remaining() >= 8) {
72 SipRounds(load_le<uint64_t>(in.take(8).data(), 0), m_V, m_C);
73 }
74
75 while(!in.empty()) {
76 m_mbuf = (m_mbuf >> 8) | (static_cast<uint64_t>(in.take_byte()) << 56);
77 m_mbuf_pos++;
78 }
79}
80
81void SipHash::final_result(std::span<uint8_t> mac) {
83
84 if(m_mbuf_pos == 0) {
85 m_mbuf = (static_cast<uint64_t>(m_words) << 56);
86 } else if(m_mbuf_pos < 8) {
87 m_mbuf = (m_mbuf >> (64 - m_mbuf_pos * 8)) | (static_cast<uint64_t>(m_words) << 56);
88 }
89
90 SipRounds(m_mbuf, m_V, m_C);
91
92 m_V[2] ^= 0xFF;
93 SipRounds(0, m_V, m_D);
94
95 const uint64_t X = m_V[0] ^ m_V[1] ^ m_V[2] ^ m_V[3];
96
97 store_le(X, mac.data());
98
99 m_V[0] = m_K[0] ^ 0x736F6D6570736575;
100 m_V[1] = m_K[1] ^ 0x646F72616E646F6D;
101 m_V[2] = m_K[0] ^ 0x6C7967656E657261;
102 m_V[3] = m_K[1] ^ 0x7465646279746573;
103 m_mbuf = 0;
104 m_mbuf_pos = 0;
105 m_words = 0;
106}
107
109 return !m_V.empty();
110}
111
112void SipHash::key_schedule(std::span<const uint8_t> key) {
113 const uint64_t K0 = load_le<uint64_t>(key.data(), 0);
114 const uint64_t K1 = load_le<uint64_t>(key.data(), 1);
115
116 m_K.resize(2);
117 m_K[0] = K0;
118 m_K[1] = K1;
119
120 m_V.resize(4);
121 m_V[0] = m_K[0] ^ 0x736F6D6570736575;
122 m_V[1] = m_K[1] ^ 0x646F72616E646F6D;
123 m_V[2] = m_K[0] ^ 0x6C7967656E657261;
124 m_V[3] = m_K[1] ^ 0x7465646279746573;
125}
126
128 zap(m_K);
129 zap(m_V);
130 m_mbuf = 0;
131 m_mbuf_pos = 0;
132 m_words = 0;
133}
134
135std::string SipHash::name() const {
136 return fmt("SipHash({},{})", m_C, m_D);
137}
138
139std::unique_ptr<MessageAuthenticationCode> SipHash::new_object() const {
140 return std::make_unique<SipHash>(m_C, m_D);
141}
142
143} // namespace Botan
void clear() override
Definition siphash.cpp:127
std::string name() const override
Definition siphash.cpp:135
bool has_keying_material() const override
Definition siphash.cpp:108
std::unique_ptr< MessageAuthenticationCode > new_object() const override
Definition siphash.cpp:139
void assert_key_material_set() const
Definition sym_algo.h:139
FE_25519 X
Definition ge.cpp:25
void zap(std::vector< T, Alloc > &vec)
Definition secmem.h:117
constexpr T rotl(T input)
Definition rotate.h:21
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
constexpr auto store_le(ParamTs &&... params)
Definition loadstor.h:764
constexpr auto load_le(ParamTs &&... params)
Definition loadstor.h:521
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61