Botan 3.13.0
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/exceptn.h>
11#include <botan/internal/buffer_slicer.h>
12#include <botan/internal/fmt.h>
13#include <botan/internal/loadstor.h>
14#include <botan/internal/rotate.h>
15
16namespace Botan {
17
18namespace {
19
20void SipRounds(uint64_t M, secure_vector<uint64_t>& V, size_t r) {
21 uint64_t V0 = V[0];
22 uint64_t V1 = V[1];
23 uint64_t V2 = V[2];
24 uint64_t V3 = V[3];
25
26 V3 ^= M;
27 for(size_t i = 0; i != r; ++i) {
28 V0 += V1;
29 V2 += V3;
30 V1 = rotl<13>(V1);
31 V3 = rotl<16>(V3);
32 V1 ^= V0;
33 V3 ^= V2;
34 V0 = rotl<32>(V0);
35
36 V2 += V1;
37 V0 += V3;
38 V1 = rotl<17>(V1);
39 V3 = rotl<21>(V3);
40 V1 ^= V2;
41 V3 ^= V0;
42 V2 = rotl<32>(V2);
43 }
44 V0 ^= M;
45
46 V[0] = V0;
47 V[1] = V1;
48 V[2] = V2;
49 V[3] = V3;
50}
51
52} // namespace
53
54SipHash::SipHash(size_t c, size_t d) : m_C(c), m_D(d) {
55 BOTAN_ARG_CHECK(m_C > 0 && m_C <= 64, "SipHash C parameter out of range");
56 BOTAN_ARG_CHECK(m_D > 0 && m_D <= 64, "SipHash D parameter out of range");
57}
58
59void SipHash::add_data(std::span<const uint8_t> input) {
61
62 // SipHash counts the message length mod 256
63 m_words += static_cast<uint8_t>(input.size());
64
65 BufferSlicer in(input);
66
67 if(m_mbuf_pos > 0) {
68 while(!in.empty() && m_mbuf_pos != 8) {
69 m_mbuf = (m_mbuf >> 8) | (static_cast<uint64_t>(in.take_byte()) << 56);
70 ++m_mbuf_pos;
71 }
72
73 if(m_mbuf_pos == 8) {
74 SipRounds(m_mbuf, m_V, m_C);
75 m_mbuf_pos = 0;
76 m_mbuf = 0;
77 }
78 }
79
80 while(in.remaining() >= 8) {
81 SipRounds(load_le<uint64_t>(in.take(8).data(), 0), m_V, m_C);
82 }
83
84 while(!in.empty()) {
85 m_mbuf = (m_mbuf >> 8) | (static_cast<uint64_t>(in.take_byte()) << 56);
86 m_mbuf_pos++;
87 }
88}
89
90void SipHash::final_result(std::span<uint8_t> mac) {
92
93 if(m_mbuf_pos == 0) {
94 m_mbuf = (static_cast<uint64_t>(m_words) << 56);
95 } else if(m_mbuf_pos < 8) {
96 m_mbuf = (m_mbuf >> (64 - m_mbuf_pos * 8)) | (static_cast<uint64_t>(m_words) << 56);
97 }
98
99 SipRounds(m_mbuf, m_V, m_C);
100
101 m_V[2] ^= 0xFF;
102 SipRounds(0, m_V, m_D);
103
104 const uint64_t X = m_V[0] ^ m_V[1] ^ m_V[2] ^ m_V[3];
105
106 store_le(X, mac.data());
107
108 reset_msg();
109}
110
111void SipHash::start_msg(std::span<const uint8_t> nonce) {
112 if(!nonce.empty()) {
113 throw Invalid_IV_Length(name(), nonce.size());
114 }
116
117 reset_msg();
118}
119
120void SipHash::reset_msg() {
121 m_V.resize(4);
122 m_V[0] = m_K[0] ^ 0x736F6D6570736575;
123 m_V[1] = m_K[1] ^ 0x646F72616E646F6D;
124 m_V[2] = m_K[0] ^ 0x6C7967656E657261;
125 m_V[3] = m_K[1] ^ 0x7465646279746573;
126 m_mbuf = 0;
127 m_mbuf_pos = 0;
128 m_words = 0;
129}
130
132 return !m_V.empty();
133}
134
135void SipHash::key_schedule(std::span<const uint8_t> key) {
136 const uint64_t K0 = load_le<uint64_t>(key.data(), 0);
137 const uint64_t K1 = load_le<uint64_t>(key.data(), 1);
138
139 m_K.resize(2);
140 m_K[0] = K0;
141 m_K[1] = K1;
142
143 m_V.resize(4);
144 reset_msg();
145}
146
148 zap(m_K);
149 zap(m_V);
150 m_mbuf = 0;
151 m_mbuf_pos = 0;
152 m_words = 0;
153}
154
155std::string SipHash::name() const {
156 return fmt("SipHash({},{})", m_C, m_D);
157}
158
159std::unique_ptr<MessageAuthenticationCode> SipHash::new_object() const {
160 return std::make_unique<SipHash>(m_C, m_D);
161}
162
163} // namespace Botan
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33
void clear() override
Definition siphash.cpp:147
std::string name() const override
Definition siphash.cpp:155
SipHash(size_t c, size_t d)
Definition siphash.cpp:54
bool has_keying_material() const override
Definition siphash.cpp:131
std::unique_ptr< MessageAuthenticationCode > new_object() const override
Definition siphash.cpp:159
void assert_key_material_set() const
Definition sym_algo.h:180
void zap(std::vector< T, Alloc > &vec)
Definition secmem.h:261
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
constexpr auto store_le(ParamTs &&... params)
Definition loadstor.h:736
BOTAN_FORCE_INLINE constexpr T rotl(T input)
Definition rotate.h:23
constexpr auto load_le(ParamTs &&... params)
Definition loadstor.h:495
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:128