Arduino Cryptography Library
 All Classes Files Functions Variables Enumerations Enumerator Pages
BLAKE2b.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 "BLAKE2b.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 
76 {
77  reset();
78 }
79 
85 {
86  clean(state);
87 }
88 
89 size_t BLAKE2b::hashSize() const
90 {
91  return 64;
92 }
93 
94 size_t BLAKE2b::blockSize() const
95 {
96  return 128;
97 }
98 
99 // Initialization vectors for BLAKE2b.
100 #define BLAKE2b_IV0 0x6a09e667f3bcc908ULL
101 #define BLAKE2b_IV1 0xbb67ae8584caa73bULL
102 #define BLAKE2b_IV2 0x3c6ef372fe94f82bULL
103 #define BLAKE2b_IV3 0xa54ff53a5f1d36f1ULL
104 #define BLAKE2b_IV4 0x510e527fade682d1ULL
105 #define BLAKE2b_IV5 0x9b05688c2b3e6c1fULL
106 #define BLAKE2b_IV6 0x1f83d9abfb41bd6bULL
107 #define BLAKE2b_IV7 0x5be0cd19137e2179ULL
108 
110 {
111  state.h[0] = BLAKE2b_IV0 ^ 0x01010040; // Default output length of 64.
112  state.h[1] = BLAKE2b_IV1;
113  state.h[2] = BLAKE2b_IV2;
114  state.h[3] = BLAKE2b_IV3;
115  state.h[4] = BLAKE2b_IV4;
116  state.h[5] = BLAKE2b_IV5;
117  state.h[6] = BLAKE2b_IV6;
118  state.h[7] = BLAKE2b_IV7;
119  state.chunkSize = 0;
120  state.lengthLow = 0;
121  state.lengthHigh = 0;
122 }
123 
131 void BLAKE2b::reset(uint8_t outputLength)
132 {
133  if (outputLength < 1)
134  outputLength = 1;
135  else if (outputLength > 64)
136  outputLength = 64;
137  state.h[0] = BLAKE2b_IV0 ^ 0x01010000 ^ outputLength;
138  state.h[1] = BLAKE2b_IV1;
139  state.h[2] = BLAKE2b_IV2;
140  state.h[3] = BLAKE2b_IV3;
141  state.h[4] = BLAKE2b_IV4;
142  state.h[5] = BLAKE2b_IV5;
143  state.h[6] = BLAKE2b_IV6;
144  state.h[7] = BLAKE2b_IV7;
145  state.chunkSize = 0;
146  state.lengthLow = 0;
147  state.lengthHigh = 0;
148 }
149 
162 void BLAKE2b::reset(const void *key, size_t keyLen, uint8_t outputLength)
163 {
164  if (keyLen > 64)
165  keyLen = 64;
166  if (outputLength < 1)
167  outputLength = 1;
168  else if (outputLength > 64)
169  outputLength = 64;
170  state.h[0] = BLAKE2b_IV0 ^ 0x01010000 ^ (keyLen << 8) ^ outputLength;
171  state.h[1] = BLAKE2b_IV1;
172  state.h[2] = BLAKE2b_IV2;
173  state.h[3] = BLAKE2b_IV3;
174  state.h[4] = BLAKE2b_IV4;
175  state.h[5] = BLAKE2b_IV5;
176  state.h[6] = BLAKE2b_IV6;
177  state.h[7] = BLAKE2b_IV7;
178  if (keyLen > 0) {
179  // Set the first block to the key and pad with zeroes.
180  memcpy(state.m, key, keyLen);
181  memset(((uint8_t *)state.m) + keyLen, 0, 128 - keyLen);
182  state.chunkSize = 128;
183  state.lengthLow = 128;
184  } else {
185  // No key. The first data block is the first hashed block.
186  state.chunkSize = 0;
187  state.lengthLow = 0;
188  }
189  state.lengthHigh = 0;
190 }
191 
192 void BLAKE2b::update(const void *data, size_t len)
193 {
194  // Break the input up into 1024-bit chunks and process each in turn.
195  const uint8_t *d = (const uint8_t *)data;
196  while (len > 0) {
197  if (state.chunkSize == 128) {
198  // Previous chunk was full and we know that it wasn't the
199  // last chunk, so we can process it now with f0 set to zero.
200  processChunk(0);
201  state.chunkSize = 0;
202  }
203  uint8_t size = 128 - state.chunkSize;
204  if (size > len)
205  size = len;
206  memcpy(((uint8_t *)state.m) + state.chunkSize, d, size);
207  state.chunkSize += size;
208  uint64_t temp = state.lengthLow;
209  state.lengthLow += size;
210  if (state.lengthLow < temp)
211  ++state.lengthHigh;
212  len -= size;
213  d += size;
214  }
215 }
216 
217 void BLAKE2b::finalize(void *hash, size_t len)
218 {
219  // Pad the last chunk and hash it with f0 set to all-ones.
220  memset(((uint8_t *)state.m) + state.chunkSize, 0, 128 - state.chunkSize);
221  processChunk(0xFFFFFFFFFFFFFFFFULL);
222 
223  // Convert the hash into little-endian in the message buffer.
224  for (uint8_t posn = 0; posn < 8; ++posn)
225  state.m[posn] = htole64(state.h[posn]);
226 
227  // Copy the hash to the caller's return buffer.
228  if (len > 64)
229  len = 64;
230  memcpy(hash, state.m, len);
231 }
232 
234 {
235  clean(state);
236  reset();
237 }
238 
239 void BLAKE2b::resetHMAC(const void *key, size_t keyLen)
240 {
241  formatHMACKey(state.m, key, keyLen, 0x36);
242  state.lengthLow += 128;
243  processChunk(0);
244 }
245 
246 void BLAKE2b::finalizeHMAC(const void *key, size_t keyLen, void *hash, size_t hashLen)
247 {
248  uint8_t temp[64];
249  finalize(temp, sizeof(temp));
250  formatHMACKey(state.m, key, keyLen, 0x5C);
251  state.lengthLow += 128;
252  processChunk(0);
253  update(temp, sizeof(temp));
254  finalize(hash, hashLen);
255  clean(temp);
256 }
257 
258 // Permutation on the message input state for BLAKE2b.
259 static const uint8_t sigma[12][16] PROGMEM = {
260  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
261  {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
262  {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
263  { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
264  { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
265  { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
266  {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
267  {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
268  { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
269  {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0},
270  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
271  {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
272 };
273 
274 // Perform a BLAKE2b quarter round operation.
275 #define quarterRound(a, b, c, d, i) \
276  do { \
277  uint64_t _b = (b); \
278  uint64_t _a = (a) + _b + state.m[pgm_read_byte(&(sigma[index][2 * (i)]))]; \
279  uint64_t _d = rightRotate32_64((d) ^ _a); \
280  uint64_t _c = (c) + _d; \
281  _b = rightRotate24_64(_b ^ _c); \
282  _a += _b + state.m[pgm_read_byte(&(sigma[index][2 * (i) + 1]))]; \
283  (d) = _d = rightRotate16_64(_d ^ _a); \
284  _c += _d; \
285  (a) = _a; \
286  (b) = rightRotate63_64(_b ^ _c); \
287  (c) = _c; \
288  } while (0)
289 
290 void BLAKE2b::processChunk(uint64_t f0)
291 {
292  uint8_t index;
293  uint64_t v[16];
294 
295  // Byte-swap the message buffer into little-endian if necessary.
296 #if !defined(CRYPTO_LITTLE_ENDIAN)
297  for (index = 0; index < 16; ++index)
298  state.m[index] = le64toh(state.m[index]);
299 #endif
300 
301  // Format the block to be hashed.
302  memcpy(v, state.h, sizeof(state.h));
303  v[8] = BLAKE2b_IV0;
304  v[9] = BLAKE2b_IV1;
305  v[10] = BLAKE2b_IV2;
306  v[11] = BLAKE2b_IV3;
307  v[12] = BLAKE2b_IV4 ^ state.lengthLow;
308  v[13] = BLAKE2b_IV5 ^ state.lengthHigh;
309  v[14] = BLAKE2b_IV6 ^ f0;
310  v[15] = BLAKE2b_IV7;
311 
312  // Perform the 12 BLAKE2b rounds.
313  for (index = 0; index < 12; ++index) {
314  // Column round.
315  quarterRound(v[0], v[4], v[8], v[12], 0);
316  quarterRound(v[1], v[5], v[9], v[13], 1);
317  quarterRound(v[2], v[6], v[10], v[14], 2);
318  quarterRound(v[3], v[7], v[11], v[15], 3);
319 
320  // Diagonal round.
321  quarterRound(v[0], v[5], v[10], v[15], 4);
322  quarterRound(v[1], v[6], v[11], v[12], 5);
323  quarterRound(v[2], v[7], v[8], v[13], 6);
324  quarterRound(v[3], v[4], v[9], v[14], 7);
325  }
326 
327  // Combine the new and old hash values.
328  for (index = 0; index < 8; ++index)
329  state.h[index] ^= (v[index] ^ v[index + 8]);
330 }
void finalize(void *hash, size_t len)
Finalizes the hashing process and returns the hash.
Definition: BLAKE2b.cpp:217
void reset()
Resets the hash ready for a new hashing process.
Definition: BLAKE2b.cpp:109
void clear()
Clears the hash state, removing all sensitive data, and then resets the hash ready for a new hashing ...
Definition: BLAKE2b.cpp:233
BLAKE2b()
Constructs a BLAKE2b hash object.
Definition: BLAKE2b.cpp:75
size_t blockSize() const
Size of the internal block used by the hash algorithm.
Definition: BLAKE2b.cpp:94
size_t hashSize() const
Size of the hash result from finalize().
Definition: BLAKE2b.cpp:89
virtual ~BLAKE2b()
Destroys this BLAKE2b hash object after clearing sensitive information.
Definition: BLAKE2b.cpp:84
void update(const void *data, size_t len)
Updates the hash with more data.
Definition: BLAKE2b.cpp:192
void resetHMAC(const void *key, size_t keyLen)
Resets the hash ready for a new HMAC hashing process.
Definition: BLAKE2b.cpp:239
void formatHMACKey(void *block, const void *key, size_t len, uint8_t pad)
Formats a HMAC key into a block.
Definition: Hash.cpp:162
void finalizeHMAC(const void *key, size_t keyLen, void *hash, size_t hashLen)
Finalizes the HMAC hashing process and returns the hash.
Definition: BLAKE2b.cpp:246