]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/WolfSSL/ctaocrypt/src/blake2b.c
Rename the CyaSSL directory to WolfSSL
[freertos] / FreeRTOS-Plus / Source / WolfSSL / ctaocrypt / src / blake2b.c
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 /* blake2b.c
14  *
15  * Copyright (C) 2006-2014 wolfSSL Inc.
16  *
17  * This file is part of CyaSSL.
18  *
19  * CyaSSL 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  * CyaSSL 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-1301, USA
32  */
33
34
35 #ifdef HAVE_CONFIG_H
36     #include <config.h>
37 #endif
38
39 #include <cyassl/ctaocrypt/settings.h>
40
41 #ifdef HAVE_BLAKE2
42
43 #include <cyassl/ctaocrypt/blake2.h>
44 #include <cyassl/ctaocrypt/blake2-impl.h>
45
46
47 static const word64 blake2b_IV[8] =
48 {
49   0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
50   0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
51   0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
52   0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
53 };
54
55 static const byte blake2b_sigma[12][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   {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 } ,
68   { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 }
69 };
70
71
72 static INLINE int blake2b_set_lastnode( blake2b_state *S )
73 {
74   S->f[1] = ~0ULL;
75   return 0;
76 }
77
78 /* Some helper functions, not necessarily useful */
79 static INLINE int blake2b_set_lastblock( blake2b_state *S )
80 {
81   if( S->last_node ) blake2b_set_lastnode( S );
82
83   S->f[0] = ~0ULL;
84   return 0;
85 }
86
87 static INLINE int blake2b_increment_counter( blake2b_state *S, const word64
88                                              inc )
89 {
90   S->t[0] += inc;
91   S->t[1] += ( S->t[0] < inc );
92   return 0;
93 }
94
95 static INLINE int blake2b_init0( blake2b_state *S )
96 {
97   int i;
98   XMEMSET( S, 0, sizeof( blake2b_state ) );
99
100   for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];
101
102   return 0;
103 }
104
105 /* init xors IV with input parameter block */
106 int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
107 {
108   word32 i;
109   blake2b_init0( S );
110   byte *p = ( byte * )( P );
111
112   /* IV XOR ParamBlock */
113   for( i = 0; i < 8; ++i )
114     S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );
115
116   return 0;
117 }
118
119
120
121 int blake2b_init( blake2b_state *S, const byte outlen )
122 {
123   blake2b_param P[1];
124
125   if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
126
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   store64( &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   return blake2b_init_param( S, P );
139 }
140
141
142 int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key,
143                       const byte keylen )
144 {
145   blake2b_param P[1];
146
147   if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
148
149   if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
150
151   P->digest_length = outlen;
152   P->key_length    = keylen;
153   P->fanout        = 1;
154   P->depth         = 1;
155   store32( &P->leaf_length, 0 );
156   store64( &P->node_offset, 0 );
157   P->node_depth    = 0;
158   P->inner_length  = 0;
159   XMEMSET( P->reserved, 0, sizeof( P->reserved ) );
160   XMEMSET( P->salt,     0, sizeof( P->salt ) );
161   XMEMSET( P->personal, 0, sizeof( P->personal ) );
162
163   if( blake2b_init_param( S, P ) < 0 ) return -1;
164
165   {
166 #ifdef CYASSL_SMALL_STACK
167     byte* block;
168
169     block = (byte*)XMALLOC(BLAKE2B_BLOCKBYTES, NULL, DYNAMIC_TYPE_TMP_BUFFER);
170
171     if ( block == NULL ) return -1;
172 #else
173     byte block[BLAKE2B_BLOCKBYTES];
174 #endif
175
176     XMEMSET( block, 0, BLAKE2B_BLOCKBYTES );
177     XMEMCPY( block, key, keylen );
178     blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
179     secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from */
180                                                      /* memory */
181
182 #ifdef CYASSL_SMALL_STACK
183     XFREE(block, NULL, DYNAMIC_TYPE_TMP_BUFFER);
184 #endif
185   }
186   return 0;
187 }
188
189 static int blake2b_compress( blake2b_state *S,
190                              const byte block[BLAKE2B_BLOCKBYTES] )
191 {
192   int i;
193
194 #ifdef CYASSL_SMALL_STACK
195   word64* m;
196   word64* v;
197
198   m = (word64*)XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
199
200   if ( m == NULL ) return -1;
201
202   v = (word64*)XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER);
203
204   if ( v == NULL )
205   {
206     XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER);
207     return -1;
208   }
209 #else
210   word64 m[16];
211   word64 v[16];
212 #endif
213
214   for( i = 0; i < 16; ++i )
215     m[i] = load64( block + i * sizeof( m[i] ) );
216
217   for( i = 0; i < 8; ++i )
218     v[i] = S->h[i];
219
220   v[ 8] = blake2b_IV[0];
221   v[ 9] = blake2b_IV[1];
222   v[10] = blake2b_IV[2];
223   v[11] = blake2b_IV[3];
224   v[12] = S->t[0] ^ blake2b_IV[4];
225   v[13] = S->t[1] ^ blake2b_IV[5];
226   v[14] = S->f[0] ^ blake2b_IV[6];
227   v[15] = S->f[1] ^ blake2b_IV[7];
228 #define G(r,i,a,b,c,d) \
229   do { \
230     a = a + b + m[blake2b_sigma[r][2*i+0]]; \
231     d = rotr64(d ^ a, 32); \
232     c = c + d; \
233     b = rotr64(b ^ c, 24); \
234     a = a + b + m[blake2b_sigma[r][2*i+1]]; \
235     d = rotr64(d ^ a, 16); \
236     c = c + d; \
237     b = rotr64(b ^ c, 63); \
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   ROUND( 10 );
261   ROUND( 11 );
262
263   for( i = 0; i < 8; ++i )
264     S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
265
266 #undef G
267 #undef ROUND
268
269 #ifdef CYASSL_SMALL_STACK
270   XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER);
271   XFREE(v, NULL, DYNAMIC_TYPE_TMP_BUFFER);
272 #endif
273
274   return 0;
275 }
276
277 /* inlen now in bytes */
278 int blake2b_update( blake2b_state *S, const byte *in, word64 inlen )
279 {
280   while( inlen > 0 )
281   {
282     word64 left = S->buflen;
283     word64 fill = 2 * BLAKE2B_BLOCKBYTES - left;
284
285     if( inlen > fill )
286     {
287       XMEMCPY( S->buf + left, in, (word)fill ); /* Fill buffer */
288       S->buflen += fill;
289       blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
290
291       if ( blake2b_compress( S, S->buf ) < 0 ) return -1; /* Compress */
292
293       XMEMCPY( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES );
294               /* Shift buffer left */
295       S->buflen -= BLAKE2B_BLOCKBYTES;
296       in += fill;
297       inlen -= fill;
298     }
299     else /* inlen <= fill */
300     {
301       XMEMCPY( S->buf + left, in, (word)inlen );
302       S->buflen += inlen; /* Be lazy, do not compress */
303       in += inlen;
304       inlen -= inlen;
305     }
306   }
307
308   return 0;
309 }
310
311 /* Is this correct? */
312 int blake2b_final( blake2b_state *S, byte *out, byte outlen )
313 {
314   byte buffer[BLAKE2B_OUTBYTES];
315   int     i;
316
317   if( S->buflen > BLAKE2B_BLOCKBYTES )
318   {
319     blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
320
321     if ( blake2b_compress( S, S->buf ) < 0 ) return -1;
322
323     S->buflen -= BLAKE2B_BLOCKBYTES;
324     XMEMCPY( S->buf, S->buf + BLAKE2B_BLOCKBYTES, (word)S->buflen );
325   }
326
327   blake2b_increment_counter( S, S->buflen );
328   blake2b_set_lastblock( S );
329   XMEMSET( S->buf + S->buflen, 0, (word)(2 * BLAKE2B_BLOCKBYTES - S->buflen) );
330          /* Padding */
331   if ( blake2b_compress( S, S->buf ) < 0 ) return -1;
332
333   for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
334     store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );
335
336   XMEMCPY( out, buffer, outlen );
337   return 0;
338 }
339
340 /* inlen, at least, should be word64. Others can be size_t. */
341 int blake2b( byte *out, const void *in, const void *key, const byte outlen,
342              const word64 inlen, byte keylen )
343 {
344   blake2b_state S[1];
345
346   /* Verify parameters */
347   if ( NULL == in ) return -1;
348
349   if ( NULL == out ) return -1;
350
351   if( NULL == key ) keylen = 0;
352
353   if( keylen > 0 )
354   {
355     if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
356   }
357   else
358   {
359     if( blake2b_init( S, outlen ) < 0 ) return -1;
360   }
361
362   if ( blake2b_update( S, ( byte * )in, inlen ) < 0) return -1;
363
364   return blake2b_final( S, out, outlen );
365 }
366
367 #if defined(BLAKE2B_SELFTEST)
368 #include <string.h>
369 #include "blake2-kat.h"
370 int main( int argc, char **argv )
371 {
372   byte key[BLAKE2B_KEYBYTES];
373   byte buf[KAT_LENGTH];
374
375   for( word32 i = 0; i < BLAKE2B_KEYBYTES; ++i )
376     key[i] = ( byte )i;
377
378   for( word32 i = 0; i < KAT_LENGTH; ++i )
379     buf[i] = ( byte )i;
380
381   for( word32 i = 0; i < KAT_LENGTH; ++i )
382   {
383     byte hash[BLAKE2B_OUTBYTES];
384     if ( blake2b( hash, buf, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES ) < 0 )
385     {
386       puts( "error" );
387       return -1;
388     }
389
390     if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )
391     {
392       puts( "error" );
393       return -1;
394     }
395   }
396
397   puts( "ok" );
398   return 0;
399 }
400 #endif
401
402
403 /* CTaoCrypt API */
404
405 /* Init Blake2b digest, track size incase final doesn't want to "remember" */
406 int InitBlake2b(Blake2b* b2b, word32 digestSz)
407 {
408     b2b->digestSz = digestSz;
409
410     return blake2b_init(b2b->S, (byte)digestSz);
411 }
412
413
414 /* Blake2b Update */
415 int Blake2bUpdate(Blake2b* b2b, const byte* data, word32 sz)
416 {
417     return blake2b_update(b2b->S, data, sz);
418 }
419
420
421 /* Blake2b Final, if pass in zero size we use init digestSz */
422 int Blake2bFinal(Blake2b* b2b, byte* final, word32 requestSz)
423 {
424     word32 sz = requestSz ? requestSz : b2b->digestSz;
425
426     return blake2b_final(b2b->S, final, (byte)sz);
427 }
428
429
430 /* end CTaoCrypt API */
431
432 #endif  /* HAVE_BLAKE2 */
433