1 /*
2    BLAKE2 reference source code package - reference C implementations
3 
4    Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
5 
6    To the extent possible under law, the author(s) have dedicated all copyright
7    and related and neighboring rights to this software to the public domain
8    worldwide. This software is distributed without any warranty.
9 
10    You should have received a copy of the CC0 Public Domain Dedication along with
11    this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
12 */
13 /* blake2s.c
14  *
15  * Copyright (C) 2006-2021 wolfSSL Inc.
16  *
17  * This file is part of wolfSSL.
18  *
19  * wolfSSL is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 2 of the License, or
22  * (at your option) any later version.
23  *
24  * wolfSSL is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, write to the Free Software
31  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
32  */
33 
34 
35 
36 #ifdef HAVE_CONFIG_H
37     #include <config.h>
38 #endif
39 
40 #include <wolfssl/wolfcrypt/settings.h>
41 
42 #ifdef HAVE_BLAKE2S
43 
44 #include <wolfssl/wolfcrypt/blake2.h>
45 #include <wolfssl/wolfcrypt/blake2-impl.h>
46 #include <wolfssl/wolfcrypt/error-crypt.h>
47 
48 
49 static const word32 blake2s_IV[8] =
50 {
51   0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
52   0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
53 };
54 
55 static const byte blake2s_sigma[10][16] =
56 {
57   {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 } ,
58   { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 } ,
59   { 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4 } ,
60   {  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8 } ,
61   {  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13 } ,
62   {  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9 } ,
63   { 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11 } ,
64   { 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10 } ,
65   {  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5 } ,
66   { 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13 , 0 }
67 };
68 
69 
blake2s_set_lastnode(blake2s_state * S)70 static WC_INLINE int blake2s_set_lastnode( blake2s_state *S )
71 {
72   S->f[1] = ~0;
73   return 0;
74 }
75 
76 /* Some helper functions, not necessarily useful */
blake2s_set_lastblock(blake2s_state * S)77 static WC_INLINE int blake2s_set_lastblock( blake2s_state *S )
78 {
79   if( S->last_node ) blake2s_set_lastnode( S );
80 
81   S->f[0] = ~0;
82   return 0;
83 }
84 
blake2s_increment_counter(blake2s_state * S,const word32 inc)85 static WC_INLINE int blake2s_increment_counter( blake2s_state *S, const word32
86                                              inc )
87 {
88   S->t[0] += inc;
89   S->t[1] += ( S->t[0] < inc );
90   return 0;
91 }
92 
blake2s_init0(blake2s_state * S)93 static WC_INLINE int blake2s_init0( blake2s_state *S )
94 {
95   int i;
96   XMEMSET( S, 0, sizeof( blake2s_state ) );
97 
98   for( i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i];
99 
100   return 0;
101 }
102 
103 /* init xors IV with input parameter block */
blake2s_init_param(blake2s_state * S,const blake2s_param * P)104 int blake2s_init_param( blake2s_state *S, const blake2s_param *P )
105 {
106   word32 i;
107   byte *p ;
108   blake2s_init0( S );
109   p =  ( byte * )( P );
110 
111   /* IV XOR ParamBlock */
112   for( i = 0; i < 8; ++i )
113     S->h[i] ^= load32( p + sizeof( S->h[i] ) * i );
114 
115   return 0;
116 }
117 
118 
119 
blake2s_init(blake2s_state * S,const byte outlen)120 int blake2s_init( blake2s_state *S, const byte outlen )
121 {
122   blake2s_param P[1];
123 
124   if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return BAD_FUNC_ARG;
125 
126 #ifdef WOLFSSL_BLAKE2S_INIT_EACH_FIELD
127   P->digest_length = outlen;
128   P->key_length    = 0;
129   P->fanout        = 1;
130   P->depth         = 1;
131   store32( &P->leaf_length, 0 );
132   store32( &P->node_offset, 0 );
133   P->node_depth    = 0;
134   P->inner_length  = 0;
135   XMEMSET( P->reserved, 0, sizeof( P->reserved ) );
136   XMEMSET( P->salt,     0, sizeof( P->salt ) );
137   XMEMSET( P->personal, 0, sizeof( P->personal ) );
138 #else
139   XMEMSET( P, 0, sizeof( *P ) );
140   P->digest_length = outlen;
141   P->fanout        = 1;
142   P->depth         = 1;
143 #endif
144   return blake2s_init_param( S, P );
145 }
146 
147 
blake2s_init_key(blake2s_state * S,const byte outlen,const void * key,const byte keylen)148 int blake2s_init_key( blake2s_state *S, const byte outlen, const void *key,
149                       const byte keylen )
150 {
151   int ret = 0;
152   blake2s_param P[1];
153 
154   if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return BAD_FUNC_ARG;
155 
156   if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return BAD_FUNC_ARG;
157 
158 #ifdef WOLFSSL_BLAKE2S_INIT_EACH_FIELD
159   P->digest_length = outlen;
160   P->key_length    = keylen;
161   P->fanout        = 1;
162   P->depth         = 1;
163   store32( &P->leaf_length, 0 );
164   store64( &P->node_offset, 0 );
165   P->node_depth    = 0;
166   P->inner_length  = 0;
167   XMEMSET( P->reserved, 0, sizeof( P->reserved ) );
168   XMEMSET( P->salt,     0, sizeof( P->salt ) );
169   XMEMSET( P->personal, 0, sizeof( P->personal ) );
170 #else
171   XMEMSET( P, 0, sizeof( *P ) );
172   P->digest_length = outlen;
173   P->key_length    = keylen;
174   P->fanout        = 1;
175   P->depth         = 1;
176 #endif
177 
178   ret = blake2s_init_param( S, P );
179   if (ret < 0)
180       return ret;
181 
182   {
183 #ifdef WOLFSSL_SMALL_STACK
184     byte* block;
185 
186     block = (byte*)XMALLOC(BLAKE2S_BLOCKBYTES, NULL, DYNAMIC_TYPE_TMP_BUFFER);
187 
188     if ( block == NULL ) return MEMORY_E;
189 #else
190     byte block[BLAKE2S_BLOCKBYTES];
191 #endif
192 
193     XMEMSET( block, 0, BLAKE2S_BLOCKBYTES );
194     XMEMCPY( block, key, keylen );
195     ret = blake2s_update( S, block, BLAKE2S_BLOCKBYTES );
196     secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from */
197                                                      /* memory */
198 
199 #ifdef WOLFSSL_SMALL_STACK
200     XFREE(block, NULL, DYNAMIC_TYPE_TMP_BUFFER);
201 #endif
202   }
203   return ret;
204 }
205 
blake2s_compress(blake2s_state * S,const byte block[BLAKE2S_BLOCKBYTES],word32 * m,word32 * v)206 static WC_INLINE int blake2s_compress(
207     blake2s_state *S,
208     const byte block[BLAKE2S_BLOCKBYTES],
209     word32* m,
210     word32* v)
211 {
212   int i;
213 
214   for( i = 0; i < 16; ++i )
215     m[i] = load32( block + i * sizeof( m[i] ) );
216 
217   for( i = 0; i < 8; ++i )
218     v[i] = S->h[i];
219 
220   v[ 8] = blake2s_IV[0];
221   v[ 9] = blake2s_IV[1];
222   v[10] = blake2s_IV[2];
223   v[11] = blake2s_IV[3];
224   v[12] = S->t[0] ^ blake2s_IV[4];
225   v[13] = S->t[1] ^ blake2s_IV[5];
226   v[14] = S->f[0] ^ blake2s_IV[6];
227   v[15] = S->f[1] ^ blake2s_IV[7];
228 #define G(r,i,a,b,c,d) \
229   do { \
230     a = a + b + m[blake2s_sigma[r][2*i+0]]; \
231     d = rotr32(d ^ a, 16); \
232     c = c + d; \
233     b = rotr32(b ^ c, 12); \
234     a = a + b + m[blake2s_sigma[r][2*i+1]]; \
235     d = rotr32(d ^ a, 8); \
236     c = c + d; \
237     b = rotr32(b ^ c, 7); \
238   } while(0)
239 #define ROUND(r)  \
240   do { \
241     G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
242     G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
243     G(r,2,v[ 2],v[ 6],v[10],v[14]); \
244     G(r,3,v[ 3],v[ 7],v[11],v[15]); \
245     G(r,4,v[ 0],v[ 5],v[10],v[15]); \
246     G(r,5,v[ 1],v[ 6],v[11],v[12]); \
247     G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
248     G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
249   } while(0)
250   ROUND( 0 );
251   ROUND( 1 );
252   ROUND( 2 );
253   ROUND( 3 );
254   ROUND( 4 );
255   ROUND( 5 );
256   ROUND( 6 );
257   ROUND( 7 );
258   ROUND( 8 );
259   ROUND( 9 );
260 
261   for( i = 0; i < 8; ++i )
262     S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
263 
264 #undef G
265 #undef ROUND
266 
267   return 0;
268 }
269 
270 /* inlen now in bytes */
blake2s_update(blake2s_state * S,const byte * in,word32 inlen)271 int blake2s_update( blake2s_state *S, const byte *in, word32 inlen )
272 {
273   int ret = 0;
274 #ifdef WOLFSSL_SMALL_STACK
275   word32* m;
276   word32* v;
277 
278   m = (word32*)XMALLOC(sizeof(word32) * 32, NULL, DYNAMIC_TYPE_TMP_BUFFER);
279 
280   if ( m == NULL ) return MEMORY_E;
281 
282   v = &m[16];
283 #else
284   word32 m[16];
285   word32 v[16];
286 #endif
287 
288   while( inlen > 0 )
289   {
290     word32 left = S->buflen;
291     word32 fill = 2 * BLAKE2S_BLOCKBYTES - left;
292 
293     if( inlen > fill )
294     {
295       XMEMCPY( S->buf + left, in, (wolfssl_word)fill ); /* Fill buffer */
296       S->buflen += fill;
297       blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
298 
299       {
300           ret= blake2s_compress( S, S->buf, m, v );
301           if (ret < 0) break;
302       }
303 
304       XMEMCPY( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
305               /* Shift buffer left */
306       S->buflen -= BLAKE2S_BLOCKBYTES;
307       in += fill;
308       inlen -= fill;
309     }
310     else /* inlen <= fill */
311     {
312       XMEMCPY( S->buf + left, in, (wolfssl_word)inlen );
313       S->buflen += inlen; /* Be lazy, do not compress */
314       inlen = 0;
315     }
316   }
317 
318 #ifdef WOLFSSL_SMALL_STACK
319   XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER);
320 #endif
321 
322   return ret;
323 }
324 
325 /* Is this correct? */
blake2s_final(blake2s_state * S,byte * out,byte outlen)326 int blake2s_final( blake2s_state *S, byte *out, byte outlen )
327 {
328   int ret = 0;
329   int     i;
330   byte buffer[BLAKE2S_BLOCKBYTES];
331 #ifdef WOLFSSL_SMALL_STACK
332   word32* m;
333   word32* v;
334 
335   m = (word32*)XMALLOC(sizeof(word32) * 32, NULL, DYNAMIC_TYPE_TMP_BUFFER);
336 
337   if ( m == NULL ) return MEMORY_E;
338 
339   v = &m[16];
340 #else
341   word32 m[16];
342   word32 v[16];
343 #endif
344 
345   if( S->buflen > BLAKE2S_BLOCKBYTES )
346   {
347     blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
348 
349     {
350         ret = blake2s_compress( S, S->buf, m, v );
351         if (ret < 0) goto out;
352     }
353 
354     S->buflen -= BLAKE2S_BLOCKBYTES;
355     XMEMCPY( S->buf, S->buf + BLAKE2S_BLOCKBYTES, (wolfssl_word)S->buflen );
356   }
357 
358   blake2s_increment_counter( S, S->buflen );
359   blake2s_set_lastblock( S );
360   XMEMSET( S->buf + S->buflen, 0, (wolfssl_word)(2 * BLAKE2S_BLOCKBYTES - S->buflen) );
361          /* Padding */
362   {
363       ret = blake2s_compress( S, S->buf, m, v );
364       if (ret < 0) goto out;
365   }
366 
367   for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
368     store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );
369 
370   XMEMCPY( out, buffer, outlen );
371 
372  out:
373 
374 #ifdef WOLFSSL_SMALL_STACK
375   XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER);
376 #endif
377 
378   return ret;
379 }
380 
381 /* inlen, at least, should be word32. Others can be size_t. */
blake2s(byte * out,const void * in,const void * key,const byte outlen,const word32 inlen,byte keylen)382 int blake2s( byte *out, const void *in, const void *key, const byte outlen,
383              const word32 inlen, byte keylen )
384 {
385   blake2s_state S[1];
386 
387   /* Verify parameters */
388   if ( NULL == in ) return BAD_FUNC_ARG;
389 
390   if ( NULL == out ) return BAD_FUNC_ARG;
391 
392   if( NULL == key ) keylen = 0;
393 
394   if( keylen > 0 )
395   {
396       int ret = blake2s_init_key( S, outlen, key, keylen );
397       if (ret < 0) return ret;
398   }
399   else
400   {
401       int ret = blake2s_init( S, outlen );
402       if (ret < 0) return ret;
403   }
404 
405   {
406       int ret = blake2s_update( S, ( byte * )in, inlen );
407       if (ret < 0) return ret;
408   }
409 
410   return blake2s_final( S, out, outlen );
411 }
412 
413 #if defined(BLAKE2S_SELFTEST)
414 #include <string.h>
415 #include "blake2-kat.h"
main(int argc,char ** argv)416 int main( int argc, char **argv )
417 {
418   byte key[BLAKE2S_KEYBYTES];
419   byte buf[KAT_LENGTH];
420 
421   for( word32 i = 0; i < BLAKE2S_KEYBYTES; ++i )
422     key[i] = ( byte )i;
423 
424   for( word32 i = 0; i < KAT_LENGTH; ++i )
425     buf[i] = ( byte )i;
426 
427   for( word32 i = 0; i < KAT_LENGTH; ++i )
428   {
429     byte hash[BLAKE2S_OUTBYTES];
430     if ( blake2s( hash, buf, key, BLAKE2S_OUTBYTES, i, BLAKE2S_KEYBYTES ) < 0 )
431     {
432       puts( "error" );
433       return -1;
434     }
435 
436     if( 0 != XMEMCMP( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) )
437     {
438       puts( "error" );
439       return -1;
440     }
441   }
442 
443   puts( "ok" );
444   return 0;
445 }
446 #endif
447 
448 
449 /* wolfCrypt API */
450 
451 /* Init Blake2s digest, track size in case final doesn't want to "remember" */
wc_InitBlake2s(Blake2s * b2s,word32 digestSz)452 int wc_InitBlake2s(Blake2s* b2s, word32 digestSz)
453 {
454     if (b2s == NULL){
455         return BAD_FUNC_ARG;
456     }
457     b2s->digestSz = digestSz;
458 
459     return blake2s_init(b2s->S, (byte)digestSz);
460 }
461 
462 
463 /* Init Blake2s digest with key, track size in case final doesn't want to "remember" */
wc_InitBlake2s_WithKey(Blake2s * b2s,word32 digestSz,const byte * key,word32 keylen)464 int wc_InitBlake2s_WithKey(Blake2s* b2s, word32 digestSz, const byte *key, word32 keylen)
465 {
466     if (b2s == NULL){
467         return BAD_FUNC_ARG;
468     }
469     b2s->digestSz = digestSz;
470 
471     if (keylen >= 256)
472         return BAD_FUNC_ARG;
473 
474     if (key)
475         return blake2s_init_key(b2s->S, (byte)digestSz, key, (byte)keylen);
476     else
477         return blake2s_init(b2s->S, (byte)digestSz);
478 }
479 
480 
481 /* Blake2s Update */
wc_Blake2sUpdate(Blake2s * b2s,const byte * data,word32 sz)482 int wc_Blake2sUpdate(Blake2s* b2s, const byte* data, word32 sz)
483 {
484     return blake2s_update(b2s->S, data, sz);
485 }
486 
487 
488 /* Blake2s Final, if pass in zero size we use init digestSz */
wc_Blake2sFinal(Blake2s * b2s,byte * final,word32 requestSz)489 int wc_Blake2sFinal(Blake2s* b2s, byte* final, word32 requestSz)
490 {
491     word32 sz = requestSz ? requestSz : b2s->digestSz;
492 
493     return blake2s_final(b2s->S, final, (byte)sz);
494 }
495 
496 
497 /* end CTaoCrypt API */
498 
499 #endif  /* HAVE_BLAKE2S */
500 
501