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 
253 void KeccakCore::keccakp()
254 {
255  static const uint8_t addMod5Table[9] PROGMEM = {
256  0, 1, 2, 3, 4, 0, 1, 2, 3
257  };
258  #define addMod5(x, y) (pgm_read_byte(&(addMod5Table[(x) + (y)])))
259  uint64_t D;
260  uint8_t index, index2;
261  for (uint8_t round = 0; round < 24; ++round) {
262  // Step mapping theta. The specification mentions two temporary
263  // arrays of size 5 called C and D. To save a bit of memory,
264  // we use the first row of B to store C and compute D on the fly.
265  for (index = 0; index < 5; ++index) {
266  state.B[0][index] = state.A[0][index] ^ state.A[1][index] ^
267  state.A[2][index] ^ state.A[3][index] ^
268  state.A[4][index];
269  }
270  for (index = 0; index < 5; ++index) {
271  D = state.B[0][addMod5(index, 4)] ^
272  leftRotate1_64(state.B[0][addMod5(index, 1)]);
273  for (index2 = 0; index2 < 5; ++index2)
274  state.A[index2][index] ^= D;
275  }
276 
277  // Step mapping rho and pi combined into a single step.
278  // Rotate all lanes by a specific offset and rearrange.
279  state.B[0][0] = state.A[0][0];
280  state.B[1][0] = leftRotate28_64(state.A[0][3]);
281  state.B[2][0] = leftRotate1_64 (state.A[0][1]);
282  state.B[3][0] = leftRotate27_64(state.A[0][4]);
283  state.B[4][0] = leftRotate62_64(state.A[0][2]);
284  state.B[0][1] = leftRotate44_64(state.A[1][1]);
285  state.B[1][1] = leftRotate20_64(state.A[1][4]);
286  state.B[2][1] = leftRotate6_64 (state.A[1][2]);
287  state.B[3][1] = leftRotate36_64(state.A[1][0]);
288  state.B[4][1] = leftRotate55_64(state.A[1][3]);
289  state.B[0][2] = leftRotate43_64(state.A[2][2]);
290  state.B[1][2] = leftRotate3_64 (state.A[2][0]);
291  state.B[2][2] = leftRotate25_64(state.A[2][3]);
292  state.B[3][2] = leftRotate10_64(state.A[2][1]);
293  state.B[4][2] = leftRotate39_64(state.A[2][4]);
294  state.B[0][3] = leftRotate21_64(state.A[3][3]);
295  state.B[1][3] = leftRotate45_64(state.A[3][1]);
296  state.B[2][3] = leftRotate8_64 (state.A[3][4]);
297  state.B[3][3] = leftRotate15_64(state.A[3][2]);
298  state.B[4][3] = leftRotate41_64(state.A[3][0]);
299  state.B[0][4] = leftRotate14_64(state.A[4][4]);
300  state.B[1][4] = leftRotate61_64(state.A[4][2]);
301  state.B[2][4] = leftRotate18_64(state.A[4][0]);
302  state.B[3][4] = leftRotate56_64(state.A[4][3]);
303  state.B[4][4] = leftRotate2_64 (state.A[4][1]);
304 
305  // Step mapping chi. Combine each lane with two other lanes in its row.
306  for (index = 0; index < 5; ++index) {
307  for (index2 = 0; index2 < 5; ++index2) {
308  state.A[index2][index] =
309  state.B[index2][index] ^
310  ((~state.B[index2][addMod5(index, 1)]) &
311  state.B[index2][addMod5(index, 2)]);
312  }
313  }
314 
315  // Step mapping iota. XOR A[0][0] with the round constant.
316  static uint64_t const RC[24] PROGMEM = {
317  0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808AULL,
318  0x8000000080008000ULL, 0x000000000000808BULL, 0x0000000080000001ULL,
319  0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008AULL,
320  0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000AULL,
321  0x000000008000808BULL, 0x800000000000008BULL, 0x8000000000008089ULL,
322  0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL,
323  0x000000000000800AULL, 0x800000008000000AULL, 0x8000000080008081ULL,
324  0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL
325  };
326  state.A[0][0] ^= pgm_read_qword(RC + round);
327  }
328 }
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