Botan  2.11.0
Crypto and TLS for C++11
sha3.cpp
Go to the documentation of this file.
1 /*
2 * SHA-3
3 * (C) 2010,2016 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/sha3.h>
9 #include <botan/rotate.h>
10 #include <botan/exceptn.h>
11 #include <botan/cpuid.h>
12 
13 namespace Botan {
14 
15 namespace {
16 
17 inline void SHA3_round(uint64_t T[25], const uint64_t A[25], uint64_t RC)
18  {
19  const uint64_t C0 = A[0] ^ A[5] ^ A[10] ^ A[15] ^ A[20];
20  const uint64_t C1 = A[1] ^ A[6] ^ A[11] ^ A[16] ^ A[21];
21  const uint64_t C2 = A[2] ^ A[7] ^ A[12] ^ A[17] ^ A[22];
22  const uint64_t C3 = A[3] ^ A[8] ^ A[13] ^ A[18] ^ A[23];
23  const uint64_t C4 = A[4] ^ A[9] ^ A[14] ^ A[19] ^ A[24];
24 
25  const uint64_t D0 = rotl<1>(C0) ^ C3;
26  const uint64_t D1 = rotl<1>(C1) ^ C4;
27  const uint64_t D2 = rotl<1>(C2) ^ C0;
28  const uint64_t D3 = rotl<1>(C3) ^ C1;
29  const uint64_t D4 = rotl<1>(C4) ^ C2;
30 
31  const uint64_t B00 = A[ 0] ^ D1;
32  const uint64_t B01 = rotl<44>(A[ 6] ^ D2);
33  const uint64_t B02 = rotl<43>(A[12] ^ D3);
34  const uint64_t B03 = rotl<21>(A[18] ^ D4);
35  const uint64_t B04 = rotl<14>(A[24] ^ D0);
36  T[ 0] = B00 ^ (~B01 & B02) ^ RC;
37  T[ 1] = B01 ^ (~B02 & B03);
38  T[ 2] = B02 ^ (~B03 & B04);
39  T[ 3] = B03 ^ (~B04 & B00);
40  T[ 4] = B04 ^ (~B00 & B01);
41 
42  const uint64_t B05 = rotl<28>(A[ 3] ^ D4);
43  const uint64_t B06 = rotl<20>(A[ 9] ^ D0);
44  const uint64_t B07 = rotl< 3>(A[10] ^ D1);
45  const uint64_t B08 = rotl<45>(A[16] ^ D2);
46  const uint64_t B09 = rotl<61>(A[22] ^ D3);
47  T[ 5] = B05 ^ (~B06 & B07);
48  T[ 6] = B06 ^ (~B07 & B08);
49  T[ 7] = B07 ^ (~B08 & B09);
50  T[ 8] = B08 ^ (~B09 & B05);
51  T[ 9] = B09 ^ (~B05 & B06);
52 
53  const uint64_t B10 = rotl< 1>(A[ 1] ^ D2);
54  const uint64_t B11 = rotl< 6>(A[ 7] ^ D3);
55  const uint64_t B12 = rotl<25>(A[13] ^ D4);
56  const uint64_t B13 = rotl< 8>(A[19] ^ D0);
57  const uint64_t B14 = rotl<18>(A[20] ^ D1);
58  T[10] = B10 ^ (~B11 & B12);
59  T[11] = B11 ^ (~B12 & B13);
60  T[12] = B12 ^ (~B13 & B14);
61  T[13] = B13 ^ (~B14 & B10);
62  T[14] = B14 ^ (~B10 & B11);
63 
64  const uint64_t B15 = rotl<27>(A[ 4] ^ D0);
65  const uint64_t B16 = rotl<36>(A[ 5] ^ D1);
66  const uint64_t B17 = rotl<10>(A[11] ^ D2);
67  const uint64_t B18 = rotl<15>(A[17] ^ D3);
68  const uint64_t B19 = rotl<56>(A[23] ^ D4);
69  T[15] = B15 ^ (~B16 & B17);
70  T[16] = B16 ^ (~B17 & B18);
71  T[17] = B17 ^ (~B18 & B19);
72  T[18] = B18 ^ (~B19 & B15);
73  T[19] = B19 ^ (~B15 & B16);
74 
75  const uint64_t B20 = rotl<62>(A[ 2] ^ D3);
76  const uint64_t B21 = rotl<55>(A[ 8] ^ D4);
77  const uint64_t B22 = rotl<39>(A[14] ^ D0);
78  const uint64_t B23 = rotl<41>(A[15] ^ D1);
79  const uint64_t B24 = rotl< 2>(A[21] ^ D2);
80  T[20] = B20 ^ (~B21 & B22);
81  T[21] = B21 ^ (~B22 & B23);
82  T[22] = B22 ^ (~B23 & B24);
83  T[23] = B23 ^ (~B24 & B20);
84  T[24] = B24 ^ (~B20 & B21);
85  }
86 
87 }
88 
89 //static
90 void SHA_3::permute(uint64_t A[25])
91  {
92 #if defined(BOTAN_HAS_SHA3_BMI2)
93  if(CPUID::has_bmi2())
94  {
95  return permute_bmi2(A);
96  }
97 #endif
98 
99  static const uint64_t RC[24] = {
100  0x0000000000000001, 0x0000000000008082, 0x800000000000808A,
101  0x8000000080008000, 0x000000000000808B, 0x0000000080000001,
102  0x8000000080008081, 0x8000000000008009, 0x000000000000008A,
103  0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
104  0x000000008000808B, 0x800000000000008B, 0x8000000000008089,
105  0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
106  0x000000000000800A, 0x800000008000000A, 0x8000000080008081,
107  0x8000000000008080, 0x0000000080000001, 0x8000000080008008
108  };
109 
110  uint64_t T[25];
111 
112  for(size_t i = 0; i != 24; i += 2)
113  {
114  SHA3_round(T, A, RC[i+0]);
115  SHA3_round(A, T, RC[i+1]);
116  }
117  }
118 
119 //static
120 size_t SHA_3::absorb(size_t bitrate,
121  secure_vector<uint64_t>& S, size_t S_pos,
122  const uint8_t input[], size_t length)
123  {
124  while(length > 0)
125  {
126  size_t to_take = std::min(length, bitrate / 8 - S_pos);
127 
128  length -= to_take;
129 
130  while(to_take && S_pos % 8)
131  {
132  S[S_pos / 8] ^= static_cast<uint64_t>(input[0]) << (8 * (S_pos % 8));
133 
134  ++S_pos;
135  ++input;
136  --to_take;
137  }
138 
139  while(to_take && to_take % 8 == 0)
140  {
141  S[S_pos / 8] ^= load_le<uint64_t>(input, 0);
142  S_pos += 8;
143  input += 8;
144  to_take -= 8;
145  }
146 
147  while(to_take)
148  {
149  S[S_pos / 8] ^= static_cast<uint64_t>(input[0]) << (8 * (S_pos % 8));
150 
151  ++S_pos;
152  ++input;
153  --to_take;
154  }
155 
156  if(S_pos == bitrate / 8)
157  {
158  SHA_3::permute(S.data());
159  S_pos = 0;
160  }
161  }
162 
163  return S_pos;
164  }
165 
166 //static
167 void SHA_3::finish(size_t bitrate,
168  secure_vector<uint64_t>& S, size_t S_pos,
169  uint8_t init_pad, uint8_t fini_pad)
170  {
171  BOTAN_ARG_CHECK(bitrate % 64 == 0, "SHA-3 bitrate must be multiple of 64");
172 
173  S[S_pos / 8] ^= static_cast<uint64_t>(init_pad) << (8 * (S_pos % 8));
174  S[(bitrate / 64) - 1] ^= static_cast<uint64_t>(fini_pad) << 56;
175  SHA_3::permute(S.data());
176  }
177 
178 //static
179 void SHA_3::expand(size_t bitrate,
180  secure_vector<uint64_t>& S,
181  uint8_t output[], size_t output_length)
182  {
183  BOTAN_ARG_CHECK(bitrate % 64 == 0, "SHA-3 bitrate must be multiple of 64");
184 
185  const size_t byterate = bitrate / 8;
186 
187  while(output_length > 0)
188  {
189  const size_t copying = std::min(byterate, output_length);
190 
191  copy_out_vec_le(output, copying, S);
192 
193  output += copying;
194  output_length -= copying;
195 
196  if(output_length > 0)
197  {
198  SHA_3::permute(S.data());
199  }
200  }
201  }
202 
203 SHA_3::SHA_3(size_t output_bits) :
204  m_output_bits(output_bits),
205  m_bitrate(1600 - 2*output_bits),
206  m_S(25),
207  m_S_pos(0)
208  {
209  // We only support the parameters for SHA-3 in this constructor
210 
211  if(output_bits != 224 && output_bits != 256 &&
212  output_bits != 384 && output_bits != 512)
213  throw Invalid_Argument("SHA_3: Invalid output length " +
214  std::to_string(output_bits));
215  }
216 
217 std::string SHA_3::name() const
218  {
219  return "SHA-3(" + std::to_string(m_output_bits) + ")";
220  }
221 
222 std::string SHA_3::provider() const
223  {
224 #if defined(BOTAN_HAS_SHA3_BMI2)
225  if(CPUID::has_bmi2())
226  {
227  return "bmi2";
228  }
229 #endif
230 
231  return "base";
232  }
233 
234 std::unique_ptr<HashFunction> SHA_3::copy_state() const
235  {
236  return std::unique_ptr<HashFunction>(new SHA_3(*this));
237  }
238 
239 HashFunction* SHA_3::clone() const
240  {
241  return new SHA_3(m_output_bits);
242  }
243 
244 void SHA_3::clear()
245  {
246  zeroise(m_S);
247  m_S_pos = 0;
248  }
249 
250 void SHA_3::add_data(const uint8_t input[], size_t length)
251  {
252  m_S_pos = SHA_3::absorb(m_bitrate, m_S, m_S_pos, input, length);
253  }
254 
255 void SHA_3::final_result(uint8_t output[])
256  {
257  SHA_3::finish(m_bitrate, m_S, m_S_pos, 0x06, 0x80);
258 
259  /*
260  * We never have to run the permutation again because we only support
261  * limited output lengths
262  */
263  copy_out_vec_le(output, m_output_bits/8, m_S);
264 
265  clear();
266  }
267 
268 }
uint32_t uint8_t output[]
Definition: ffi.h:512
size_t * output_length
Definition: ffi.h:280
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
char * name
Definition: ffi.h:330
uint64_t load_le< uint64_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:235
Definition: alg_id.cpp:13
#define BOTAN_ARG_CHECK(expr, msg)
Definition: assert.h:37
size_t const uint8_t input[]
Definition: base32.h:30
void BlockCipher const uint8_t size_t uint8_t output[]
Definition: package.h:29
fe T
Definition: ge.cpp:37
void zeroise(std::vector< T, Alloc > &vec)
Definition: secmem.h:160
void copy_out_vec_le(uint8_t out[], size_t out_bytes, const std::vector< T, Alloc > &in)
Definition: loadstor.h:692