Coverage Report

Created: 2019-12-03 15:21

/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/siphash.h>
9
#include <botan/loadstor.h>
10
#include <botan/rotate.h>
11
12
namespace Botan {
13
14
namespace {
15
16
void SipRounds(uint64_t M, secure_vector<uint64_t>& V, size_t r)
17
0
   {
18
0
   uint64_t V0 = V[0], V1 = V[1], V2 = V[2], V3 = V[3];
19
0
20
0
   V3 ^= M;
21
0
   for(size_t i = 0; i != r; ++i)
22
0
      {
23
0
      V0 += V1; V2 += V3;
24
0
      V1 = rotl<13>(V1);
25
0
      V3 = rotl<16>(V3);
26
0
      V1 ^= V0; V3 ^= V2;
27
0
      V0 = rotl<32>(V0);
28
0
29
0
      V2 += V1; V0 += V3;
30
0
      V1 = rotl<17>(V1);
31
0
      V3 = rotl<21>(V3);
32
0
      V1 ^= V2; V3 ^= V0;
33
0
      V2 = rotl<32>(V2);
34
0
      }
35
0
   V0 ^= M;
36
0
37
0
   V[0] = V0; V[1] = V1; V[2] = V2; V[3] = V3;
38
0
   }
39
40
}
41
42
void SipHash::add_data(const uint8_t input[], size_t length)
43
0
   {
44
0
   verify_key_set(m_V.empty() == false);
45
0
46
0
   // SipHash counts the message length mod 256
47
0
   m_words += static_cast<uint8_t>(length);
48
0
49
0
   if(m_mbuf_pos)
50
0
      {
51
0
      while(length && m_mbuf_pos != 8)
52
0
         {
53
0
         m_mbuf = (m_mbuf >> 8) | (static_cast<uint64_t>(input[0]) << 56);
54
0
         ++m_mbuf_pos;
55
0
         ++input;
56
0
         length--;
57
0
         }
58
0
59
0
      if(m_mbuf_pos == 8)
60
0
         {
61
0
         SipRounds(m_mbuf, m_V, m_C);
62
0
         m_mbuf_pos = 0;
63
0
         m_mbuf = 0;
64
0
         }
65
0
      }
66
0
67
0
   while(length >= 8)
68
0
      {
69
0
      SipRounds(load_le<uint64_t>(input, 0), m_V, m_C);
70
0
      input += 8;
71
0
      length -= 8;
72
0
      }
73
0
74
0
   for(size_t i = 0; i != length; ++i)
75
0
      {
76
0
      m_mbuf = (m_mbuf >> 8) | (static_cast<uint64_t>(input[i]) << 56);
77
0
      m_mbuf_pos++;
78
0
      }
79
0
   }
80
81
void SipHash::final_result(uint8_t mac[])
82
0
   {
83
0
   verify_key_set(m_V.empty() == false);
84
0
85
0
   if(m_mbuf_pos == 0)
86
0
      {
87
0
      m_mbuf = (static_cast<uint64_t>(m_words) << 56);
88
0
      }
89
0
   else if(m_mbuf_pos < 8)
90
0
      {
91
0
      m_mbuf = (m_mbuf >> (64-m_mbuf_pos*8)) | (static_cast<uint64_t>(m_words) << 56);
92
0
      }
93
0
94
0
   SipRounds(m_mbuf, m_V, m_C);
95
0
96
0
   m_V[2] ^= 0xFF;
97
0
   SipRounds(0, m_V, m_D);
98
0
99
0
   const uint64_t X = m_V[0] ^ m_V[1] ^ m_V[2] ^ m_V[3];
100
0
101
0
   store_le(X, mac);
102
0
103
0
   clear();
104
0
   }
105
106
void SipHash::key_schedule(const uint8_t key[], size_t)
107
0
   {
108
0
   const uint64_t K0 = load_le<uint64_t>(key, 0);
109
0
   const uint64_t K1 = load_le<uint64_t>(key, 1);
110
0
111
0
   m_V.resize(4);
112
0
   m_V[0] = K0 ^ 0x736F6D6570736575;
113
0
   m_V[1] = K1 ^ 0x646F72616E646F6D;
114
0
   m_V[2] = K0 ^ 0x6C7967656E657261;
115
0
   m_V[3] = K1 ^ 0x7465646279746573;
116
0
   }
117
118
void SipHash::clear()
119
0
   {
120
0
   zap(m_V);
121
0
   m_mbuf = 0;
122
0
   m_mbuf_pos = 0;
123
0
   m_words = 0;
124
0
   }
125
126
std::string SipHash::name() const
127
0
   {
128
0
   return "SipHash(" + std::to_string(m_C) + "," + std::to_string(m_D) + ")";
129
0
   }
130
131
MessageAuthenticationCode* SipHash::clone() const
132
0
   {
133
0
   return new SipHash(m_C, m_D);
134
0
   }
135
136
}