Botan  2.1.0
Crypto and TLS for C++11
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/siphash.h>
9 
10 namespace Botan {
11 
12 namespace {
13 
14 void SipRounds(uint64_t M, secure_vector<uint64_t>& V, size_t r)
15  {
16  uint64_t V0 = V[0], V1 = V[1], V2 = V[2], V3 = V[3];
17 
18  V3 ^= M;
19  for(size_t i = 0; i != r; ++i)
20  {
21  V0 += V1; V2 += V3;
22  V1 = rotate_left(V1, 13);
23  V3 = rotate_left(V3, 16);
24  V1 ^= V0; V3 ^= V2;
25  V0 = rotate_left(V0, 32);
26 
27  V2 += V1; V0 += V3;
28  V1 = rotate_left(V1, 17);
29  V3 = rotate_left(V3, 21);
30  V1 ^= V2; V3 ^= V0;
31  V2 = rotate_left(V2, 32);
32  }
33  V0 ^= M;
34 
35  V[0] = V0; V[1] = V1; V[2] = V2; V[3] = V3;
36  }
37 
38 }
39 
40 void SipHash::add_data(const uint8_t input[], size_t length)
41  {
42  m_words += length;
43 
44  if(m_mbuf_pos)
45  {
46  while(length && m_mbuf_pos != 8)
47  {
48  m_mbuf = (m_mbuf >> 8) | (static_cast<uint64_t>(input[0]) << 56);
49  ++m_mbuf_pos;
50  ++input;
51  length--;
52  }
53 
54  if(m_mbuf_pos == 8)
55  {
56  SipRounds(m_mbuf, m_V, m_C);
57  m_mbuf_pos = 0;
58  m_mbuf = 0;
59  }
60  }
61 
62  while(length >= 8)
63  {
64  SipRounds(load_le<uint64_t>(input, 0), m_V, m_C);
65  input += 8;
66  length -= 8;
67  }
68 
69  for(size_t i = 0; i != length; ++i)
70  {
71  m_mbuf = (m_mbuf >> 8) | (static_cast<uint64_t>(input[i]) << 56);
72  m_mbuf_pos++;
73  }
74  }
75 
76 void SipHash::final_result(uint8_t mac[])
77  {
78  m_mbuf = (m_mbuf >> (64-m_mbuf_pos*8)) | (static_cast<uint64_t>(m_words) << 56);
79  SipRounds(m_mbuf, m_V, m_C);
80 
81  m_V[2] ^= 0xFF;
82  SipRounds(0, m_V, m_D);
83 
84  const uint64_t X = m_V[0] ^ m_V[1] ^ m_V[2] ^ m_V[3];
85 
86  store_le(X, mac);
87 
88  clear();
89  }
90 
91 void SipHash::key_schedule(const uint8_t key[], size_t)
92  {
93  const uint64_t K0 = load_le<uint64_t>(key, 0);
94  const uint64_t K1 = load_le<uint64_t>(key, 1);
95 
96  m_V.resize(4);
97  m_V[0] = K0 ^ 0x736F6D6570736575;
98  m_V[1] = K1 ^ 0x646F72616E646F6D;
99  m_V[2] = K0 ^ 0x6C7967656E657261;
100  m_V[3] = K1 ^ 0x7465646279746573;
101  }
102 
104  {
105  m_V.clear();
106  m_mbuf = 0;
107  m_mbuf_pos = 0;
108  m_words = 0;
109  }
110 
111 std::string SipHash::name() const
112  {
113  return "SipHash(" + std::to_string(m_C) + "," + std::to_string(m_D) + ")";
114  }
115 
117  {
118  return new SipHash(m_C, m_D);
119  }
120 
121 }
T rotate_left(T input, size_t rot)
Definition: rotate.h:21
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:47
std::string name() const override
Definition: siphash.cpp:111
SipHash(size_t c=2, size_t d=4)
Definition: siphash.h:18
MessageAuthenticationCode * clone() const override
Definition: siphash.cpp:116
uint64_t load_le< uint64_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:243
void clear() override
Definition: siphash.cpp:103
Definition: alg_id.cpp:13
void store_le(uint16_t in, uint8_t out[2])
Definition: loadstor.h:457