blake2s.c
Go to the documentation of this file.
1 /**
2  * @file blake2s.c
3  * @brief BLAKE2 cryptographic hash and MAC (BLAKE2s variant)
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneCrypto Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @section Description
26  *
27  * BLAKE2s is cryptographic hash function optimized for 8- to 32-bit platforms
28  * that produces digests of any size between 1 and 32 bytes. Refer to RFC 7693
29  * for more details
30  *
31  * @author Oryx Embedded SARL (www.oryx-embedded.com)
32  * @version 1.9.0
33  **/
34 
35 //Switch to the appropriate trace level
36 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
37 
38 //Dependencies
39 #include "core/crypto.h"
40 #include "hash/blake2s.h"
41 
42 //Check crypto library configuration
43 #if (BLAKE2S_SUPPORT == ENABLED)
44 
45 //Mixing function G (borrowed from ChaCha quarter-round function)
46 #define G(a, b, c, d, x, y) \
47 { \
48  a += b + x; \
49  d ^= a; \
50  d = ROR32(d, 16); \
51  c += d; \
52  b ^= c; \
53  b = ROR32(b, 12); \
54  a += b + y; \
55  d ^= a; \
56  d = ROR32(d, 8); \
57  c += d; \
58  b ^= c; \
59  b = ROR32(b, 7); \
60 }
61 
62 //Message schedule SIGMA
63 static const uint8_t sigma[10][16] =
64 {
65  {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
66  {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
67  {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
68  {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
69  {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
70  {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
71  {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
72  {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
73  {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
74  {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0}
75 };
76 
77 //Initialization vector
78 static const uint32_t iv[8] =
79 {
80  0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
81  0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
82 };
83 
84 
85 /**
86  * @brief Digest a message using BLAKE2s
87  * @param[in] key Pointer to the key
88  * @param[in] keyLen Length of the key
89  * @param[in] data Pointer to the message being hashed
90  * @param[in] dataLen Length of the message
91  * @param[out] digest Pointer to the calculated digest
92  * @param[in] digestLen Expected length of the digest
93  * @return Error code
94  **/
95 
96 error_t blake2sCompute(const void *key, size_t keyLen, const void *data,
97  size_t dataLen, uint8_t *digest, size_t digestLen)
98 {
99  error_t error;
100  Blake2sContext *context;
101 
102  //Allocate a memory buffer to hold the BLAKE2s context
103  context = cryptoAllocMem(sizeof(Blake2sContext));
104 
105  //Successful memory allocation?
106  if(context != NULL)
107  {
108  //Initialize the hashing context
109  error = blake2sInit(context, key, keyLen, digestLen);
110 
111  //Check status code
112  if(!error)
113  {
114  //Digest the message
115  blake2sUpdate(context, data, dataLen);
116  //Finalize the BLAKE2s message digest
117  blake2sFinal(context, digest);
118  }
119 
120  //Free previously allocated memory
121  cryptoFreeMem(context);
122  }
123  else
124  {
125  //Failed to allocate memory
126  error = ERROR_OUT_OF_MEMORY;
127  }
128 
129  //Return status code
130  return error;
131 }
132 
133 
134 /**
135  * @brief Initialize BLAKE2s message digest context
136  * @param[in] context Pointer to the BLAKE2s context to initialize
137  * @param[in] key Pointer to the key
138  * @param[in] keyLen Length of the key
139  * @param[in] digestLen Expected length of the digest
140  * @return Error code
141  **/
142 
143 error_t blake2sInit(Blake2sContext *context, const void *key,
144  size_t keyLen, size_t digestLen)
145 {
146  size_t i;
147 
148  //Check the length of the key
149  if(keyLen > 32)
151 
152  //Check the length of the hash
153  if(digestLen < 1 || digestLen > 32)
155 
156  //Initialize state vector
157  for(i = 0; i < 8; i++)
158  {
159  context->h[i] = iv[i];
160  }
161 
162  //The first byte of the parameter block is the hash size in bytes
163  context->h[0] ^= digestLen;
164  //The second byte of the parameter block is the key size in bytes
165  context->h[0] ^= keyLen << 8;
166  //Bytes 2 and 3 are set as 01
167  context->h[0] ^= 0x01010000;
168 
169  //Number of bytes in the buffer
170  context->size = 0;
171 
172  //Total number of bytes
173  context->totalSize[0] = 0;
174  context->totalSize[1] = 0;
175 
176  //Size of the digest
177  context->digestSize = digestLen;
178 
179  //Clear input buffer
180  cryptoMemset(context->buffer, 0, 64);
181 
182  //Any secret key?
183  if(keyLen > 0)
184  {
185  //Copy the secret key
186  cryptoMemcpy(context->buffer, key, keyLen);
187  //The secret key is padded with zero bytes
188  context->size = 64;
189  }
190 
191  //Successful initialization
192  return NO_ERROR;
193 }
194 
195 
196 /**
197  * @brief Update the BLAKE2s context with a portion of the message being hashed
198  * @param[in] context Pointer to the BLAKE2s context
199  * @param[in] data Pointer to the buffer being hashed
200  * @param[in] length Length of the buffer
201  **/
202 
203 void blake2sUpdate(Blake2sContext *context, const void *data, size_t length)
204 {
205  size_t n;
206 
207  //Process the incoming data
208  while(length > 0)
209  {
210  //Each message block consists of 16 words
211  if(context->size == 64)
212  {
213  //Compress the 16-word block
214  blake2sProcessBlock(context, FALSE);
215  //Empty the buffer
216  context->size = 0;
217  }
218 
219  //The buffer can hold at most 64 bytes
220  n = MIN(length, 64 - context->size);
221 
222  //Copy the data to the buffer
223  cryptoMemcpy(context->buffer + context->size, data, n);
224  //Update the length of the buffer
225  context->size += n;
226 
227  //Advance the data pointer
228  data = (uint8_t *) data + n;
229  //Remaining bytes to process
230  length -= n;
231  }
232 }
233 
234 
235 /**
236  * @brief Finish the BLAKE2s message digest
237  * @param[in] context Pointer to the BLAKE2s context
238  * @param[out] digest Calculated digest (optional parameter)
239  **/
240 
241 void blake2sFinal(Blake2sContext *context, uint8_t *digest)
242 {
243  size_t i;
244 
245  //The last block is padded with zeros to full block size, if required
246  for(i = context->size; i < 64; i++)
247  {
248  context->buffer[i] = 0;
249  }
250 
251  //Compress the last block
252  blake2sProcessBlock(context, TRUE);
253 
254  //Convert from host byte order to big-endian byte order
255  for(i = 0; i < 8; i++)
256  {
257  context->h[i] = htole32(context->h[i]);
258  }
259 
260  //Copy the resulting digest
261  if(digest != NULL)
262  {
263  cryptoMemcpy(digest, context->digest, context->digestSize);
264  }
265 }
266 
267 
268 /**
269  * @brief Compression function F
270  * @param[in] context Pointer to the BLAKE2s context
271  * @param[in] last Flag indicating the last block
272  **/
273 
275 {
276  uint_t i;
277  uint32_t *m;
278  uint32_t v[16];
279 
280  //Initialize the working vector
281  for(i = 0; i < 8; i++)
282  {
283  //First half from state
284  v[i] = context->h[i];
285  //Second half from IV
286  v[i + 8] = iv[i];
287  }
288 
289  //Increment offset counter
290  context->totalSize[0] += context->size;
291 
292  //Propagate the carry if necessary
293  if(context->totalSize[0] < context->size)
294  {
295  context->totalSize[1]++;
296  }
297 
298  //Low word of the offset
299  v[12] ^= context->totalSize[0];
300  //High word of the offset
301  v[13] ^= context->totalSize[1];
302 
303  //Last block flag?
304  if(last)
305  {
306  //Invert all bits
307  v[14] = ~v[14];
308  }
309 
310  //Point to the message block vector
311  m = context->m;
312 
313  //Convert from little-endian byte order to host byte order
314  for(i = 0; i < 16; i++)
315  {
316  m[i] = letoh32(m[i]);
317  }
318 
319  //Cryptographic mixing
320  for(i = 0; i < 10; i++)
321  {
322  //The column rounds apply the quarter-round function to the four
323  //columns, from left to right
324  G(v[0], v[4], v[8], v[12], m[sigma[i][0]], m[sigma[i][1]]);
325  G(v[1], v[5], v[9], v[13], m[sigma[i][2]], m[sigma[i][3]]);
326  G(v[2], v[6], v[10], v[14], m[sigma[i][4]], m[sigma[i][5]]);
327  G(v[3], v[7], v[11], v[15], m[sigma[i][6]], m[sigma[i][7]]);
328 
329  //The diagonal rounds apply the quarter-round function to the top-left,
330  //bottom-right diagonal, followed by the pattern shifted one place to
331  //the right, for three more quarter-rounds
332  G(v[0], v[5], v[10], v[15], m[sigma[i][8]], m[sigma[i][9]]);
333  G(v[1], v[6], v[11], v[12], m[sigma[i][10]], m[sigma[i][11]]);
334  G(v[2], v[7], v[8], v[13], m[sigma[i][12]], m[sigma[i][13]]);
335  G(v[3], v[4], v[9], v[14], m[sigma[i][14]], m[sigma[i][15]]);
336  }
337 
338  //XOR the two halves
339  for(i = 0; i < 8; i++)
340  {
341  context->h[i] ^= v[i] ^ v[i + 8];
342  }
343 }
344 
345 #endif
#define cryptoMemcpy(dest, src, length)
Definition: crypto.h:590
uint8_t buffer[64]
Definition: blake2s.h:58
#define cryptoFreeMem(p)
Definition: crypto.h:578
#define cryptoAllocMem(size)
Definition: crypto.h:573
General definitions for cryptographic algorithms.
Invalid parameter.
Definition: error.h:45
uint32_t h[8]
Definition: blake2s.h:52
uint8_t m
Definition: ndp.h:299
size_t digestSize
Definition: blake2s.h:62
#define TRUE
Definition: os_port.h:48
void blake2sUpdate(Blake2sContext *context, const void *data, size_t length)
Update the BLAKE2s context with a portion of the message being hashed.
Definition: blake2s.c:203
#define G(a, b, c, d, x, y)
Definition: blake2s.c:46
#define htole32(value)
Definition: cpu_endian.h:404
uint16_t last
Definition: ipv4_frag.h:94
size_t size
Definition: blake2s.h:60
uint32_t m[16]
Definition: blake2s.h:57
#define MIN(a, b)
Definition: os_port.h:60
error_t blake2sInit(Blake2sContext *context, const void *key, size_t keyLen, size_t digestLen)
Initialize BLAKE2s message digest context.
Definition: blake2s.c:143
Success.
Definition: error.h:42
error_t
Error codes.
Definition: error.h:40
error_t blake2sCompute(const void *key, size_t keyLen, const void *data, size_t dataLen, uint8_t *digest, size_t digestLen)
Digest a message using BLAKE2s.
Definition: blake2s.c:96
unsigned int uint_t
Definition: compiler_port.h:43
BLAKE2s algorithm context.
Definition: blake2s.h:48
uint8_t data[]
Definition: dtls_misc.h:167
uint8_t digest[32]
Definition: blake2s.h:53
#define letoh32(value)
Definition: cpu_endian.h:412
BLAKE2 cryptographic hash and MAC (BLAKE2s variant)
#define cryptoMemset(p, value, length)
Definition: crypto.h:584
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
void blake2sFinal(Blake2sContext *context, uint8_t *digest)
Finish the BLAKE2s message digest.
Definition: blake2s.c:241
void blake2sProcessBlock(Blake2sContext *context, bool_t last)
Compression function F.
Definition: blake2s.c:274
#define FALSE
Definition: os_port.h:44
int bool_t
Definition: compiler_port.h:47
uint32_t totalSize[2]
Definition: blake2s.h:61