ArduinoLibs
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
KeccakCore.cpp
1 /*
2  * Copyright (C) 2015 Southern Storm Software, Pty Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "KeccakCore.h"
24 #include "Crypto.h"
25 #include "utility/EndianUtil.h"
26 #include "utility/RotateUtil.h"
27 #include "utility/ProgMemUtil.h"
28 #include <string.h>
29 
50  : _blockSize(8)
51 {
52  memset(state.A, 0, sizeof(state.A));
53  state.inputSize = 0;
54  state.outputSize = 0;
55 }
56 
62 {
63  clean(state);
64 }
65 
71 size_t KeccakCore::capacity() const
72 {
73  return 1600 - ((size_t)_blockSize) * 8;
74 }
75 
89 void KeccakCore::setCapacity(size_t capacity)
90 {
91  _blockSize = (1600 - capacity) / 8;
92  reset();
93 }
94 
110 {
111  memset(state.A, 0, sizeof(state.A));
112  state.inputSize = 0;
113  state.outputSize = 0;
114 }
115 
128 void KeccakCore::update(const void *data, size_t size)
129 {
130  // Stop generating output while we incorporate the new data.
131  state.outputSize = 0;
132 
133  // Break the input up into chunks and process each in turn.
134  const uint8_t *d = (const uint8_t *)data;
135 #if !defined(CRYPTO_LITTLE_ENDIAN)
136  uint64_t *Awords = &(state.A[0][0]);
137  uint8_t index, index2;
138 #endif
139  while (size > 0) {
140  uint8_t len = _blockSize - state.inputSize;
141  if (len > size)
142  len = size;
143 #if defined(CRYPTO_LITTLE_ENDIAN)
144  uint8_t *Abytes = ((uint8_t *)state.A) + state.inputSize;
145  for (uint8_t posn = 0; posn < len; ++posn)
146  Abytes[posn] ^= d[posn];
147 #else
148  index2 = state.inputSize;
149  for (index = 0; index < len; ++index) {
150  Awords[index2 / 8] ^= (((uint64_t)d[index]) << ((index2 % 8) * 8));
151  ++index2;
152  }
153 #endif
154  state.inputSize += len;
155  size -= len;
156  d += len;
157  if (state.inputSize == _blockSize) {
158  keccakp();
159  state.inputSize = 0;
160  }
161  }
162 }
163 
174 void KeccakCore::pad(uint8_t tag)
175 {
176  // Padding for SHA3-NNN variants according to FIPS 202 appends "01",
177  // then another "1", then many zero bits, followed by a final "1".
178  // SHAKE appends "1111" first instead of "01". Note that SHA-3 numbers
179  // bits from the least significant, so appending "01" is equivalent
180  // to 0x02 for byte-aligned data, not 0x40.
181  uint8_t size = state.inputSize;
182  uint64_t *Awords = &(state.A[0][0]);
183  Awords[size / 8] ^= (((uint64_t)tag) << ((size % 8) * 8));
184  Awords[(_blockSize - 1) / 8] ^= 0x8000000000000000ULL;
185  keccakp();
186  state.inputSize = 0;
187  state.outputSize = 0;
188 }
189 
201 void KeccakCore::extract(void *data, size_t size)
202 {
203 #if !defined(CRYPTO_LITTLE_ENDIAN)
204  uint8_t index, index2;
205  const uint64_t *Awords = &(state.A[0][0]);
206 #endif
207 
208  // Stop accepting input while we are generating output.
209  state.inputSize = 0;
210 
211  // Copy the output data into the caller's return buffer.
212  uint8_t *d = (uint8_t *)data;
213  uint8_t tempSize;
214  while (size > 0) {
215  // Generate another output block if the current one has been exhausted.
216  if (state.outputSize >= _blockSize) {
217  keccakp();
218  state.outputSize = 0;
219  }
220 
221  // How many bytes can we copy this time around?
222  tempSize = _blockSize - state.outputSize;
223  if (tempSize > size)
224  tempSize = size;
225 
226  // Copy the partial output data into the caller's return buffer.
227 #if defined(CRYPTO_LITTLE_ENDIAN)
228  memcpy(d, ((uint8_t *)(state.A)) + state.outputSize, tempSize);
229 #else
230  index2 = state.outputSize;
231  for (index = 0; index < tempSize; ++index) {
232  d[index] = (uint8_t)(Awords[index2 / 8] >> ((index2 % 8) * 8));
233  ++index2;
234  }
235 #endif
236  state.outputSize += tempSize;
237  size -= tempSize;
238  d += tempSize;
239  }
240 }
241 
246 {
247  clean(state);
248 }
249 
263 void KeccakCore::setHMACKey(const void *key, size_t len, uint8_t pad, size_t hashSize)
264 {
265  uint8_t *b = (uint8_t *)state.B;
266  size_t size = blockSize();
267  reset();
268  if (len <= size) {
269  memcpy(b, key, len);
270  } else {
271  update(key, len);
272  this->pad(0x06);
273  extract(b, hashSize);
274  len = hashSize;
275  reset();
276  }
277  memset(b + len, pad, size - len);
278  while (len > 0) {
279  *b++ ^= pad;
280  --len;
281  }
282  update(state.B, size);
283 }
284 
288 void KeccakCore::keccakp()
289 {
290  static const uint8_t addMod5Table[9] PROGMEM = {
291  0, 1, 2, 3, 4, 0, 1, 2, 3
292  };
293  #define addMod5(x, y) (pgm_read_byte(&(addMod5Table[(x) + (y)])))
294  uint64_t D;
295  uint8_t index, index2;
296  for (uint8_t round = 0; round < 24; ++round) {
297  // Step mapping theta. The specification mentions two temporary
298  // arrays of size 5 called C and D. To save a bit of memory,
299  // we use the first row of B to store C and compute D on the fly.
300  for (index = 0; index < 5; ++index) {
301  state.B[0][index] = state.A[0][index] ^ state.A[1][index] ^
302  state.A[2][index] ^ state.A[3][index] ^
303  state.A[4][index];
304  }
305  for (index = 0; index < 5; ++index) {
306  D = state.B[0][addMod5(index, 4)] ^
307  leftRotate1_64(state.B[0][addMod5(index, 1)]);
308  for (index2 = 0; index2 < 5; ++index2)
309  state.A[index2][index] ^= D;
310  }
311 
312  // Step mapping rho and pi combined into a single step.
313  // Rotate all lanes by a specific offset and rearrange.
314  state.B[0][0] = state.A[0][0];
315  state.B[1][0] = leftRotate28_64(state.A[0][3]);
316  state.B[2][0] = leftRotate1_64 (state.A[0][1]);
317  state.B[3][0] = leftRotate27_64(state.A[0][4]);
318  state.B[4][0] = leftRotate62_64(state.A[0][2]);
319  state.B[0][1] = leftRotate44_64(state.A[1][1]);
320  state.B[1][1] = leftRotate20_64(state.A[1][4]);
321  state.B[2][1] = leftRotate6_64 (state.A[1][2]);
322  state.B[3][1] = leftRotate36_64(state.A[1][0]);
323  state.B[4][1] = leftRotate55_64(state.A[1][3]);
324  state.B[0][2] = leftRotate43_64(state.A[2][2]);
325  state.B[1][2] = leftRotate3_64 (state.A[2][0]);
326  state.B[2][2] = leftRotate25_64(state.A[2][3]);
327  state.B[3][2] = leftRotate10_64(state.A[2][1]);
328  state.B[4][2] = leftRotate39_64(state.A[2][4]);
329  state.B[0][3] = leftRotate21_64(state.A[3][3]);
330  state.B[1][3] = leftRotate45_64(state.A[3][1]);
331  state.B[2][3] = leftRotate8_64 (state.A[3][4]);
332  state.B[3][3] = leftRotate15_64(state.A[3][2]);
333  state.B[4][3] = leftRotate41_64(state.A[3][0]);
334  state.B[0][4] = leftRotate14_64(state.A[4][4]);
335  state.B[1][4] = leftRotate61_64(state.A[4][2]);
336  state.B[2][4] = leftRotate18_64(state.A[4][0]);
337  state.B[3][4] = leftRotate56_64(state.A[4][3]);
338  state.B[4][4] = leftRotate2_64 (state.A[4][1]);
339 
340  // Step mapping chi. Combine each lane with two other lanes in its row.
341  for (index = 0; index < 5; ++index) {
342  for (index2 = 0; index2 < 5; ++index2) {
343  state.A[index2][index] =
344  state.B[index2][index] ^
345  ((~state.B[index2][addMod5(index, 1)]) &
346  state.B[index2][addMod5(index, 2)]);
347  }
348  }
349 
350  // Step mapping iota. XOR A[0][0] with the round constant.
351  static uint64_t const RC[24] PROGMEM = {
352  0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808AULL,
353  0x8000000080008000ULL, 0x000000000000808BULL, 0x0000000080000001ULL,
354  0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008AULL,
355  0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000AULL,
356  0x000000008000808BULL, 0x800000000000008BULL, 0x8000000000008089ULL,
357  0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL,
358  0x000000000000800AULL, 0x800000008000000AULL, 0x8000000080008081ULL,
359  0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL
360  };
361  state.A[0][0] ^= pgm_read_qword(RC + round);
362  }
363 }
size_t blockSize() const
Returns the input block size for the sponge function in bytes.
Definition: KeccakCore.h:38
void setHMACKey(const void *key, size_t len, uint8_t pad, size_t hashSize)
Sets a HMAC key for a Keccak-based hash algorithm.
Definition: KeccakCore.cpp:263
void setCapacity(size_t capacity)
Sets the capacity of the Keccak sponge function in bits.
Definition: KeccakCore.cpp:89
~KeccakCore()
Destroys this Keccak sponge function after clearing all sensitive information.
Definition: KeccakCore.cpp:61
void extract(void *data, size_t size)
Extracts data from the Keccak sponge function.
Definition: KeccakCore.cpp:201
void pad(uint8_t tag)
Pads the last block of input data to blockSize().
Definition: KeccakCore.cpp:174
size_t capacity() const
Returns the capacity of the sponge function in bits.
Definition: KeccakCore.cpp:71
KeccakCore()
Constructs a new Keccak sponge function.
Definition: KeccakCore.cpp:49
void update(const void *data, size_t size)
Updates the Keccak sponge function with more input data.
Definition: KeccakCore.cpp:128
void clear()
Clears all sensitive data from this object.
Definition: KeccakCore.cpp:245
void reset()
Resets the Keccak sponge function ready for a new session.
Definition: KeccakCore.cpp:109