1339640Smm/*
2339640Smm   BLAKE2 reference source code package - reference C implementations
3339640Smm
4339640Smm   Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the
5339640Smm   terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
6339640Smm   your option.  The terms of these licenses can be found at:
7339640Smm
8339640Smm   - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
9339640Smm   - OpenSSL license   : https://www.openssl.org/source/license.html
10339640Smm   - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
11339640Smm
12339640Smm   More information about the BLAKE2 hash function can be found at
13339640Smm   https://blake2.net.
14339640Smm*/
15339640Smm
16339640Smm#include <stdint.h>
17339640Smm#include <string.h>
18339640Smm#include <stdio.h>
19339640Smm
20339640Smm#include "archive_blake2.h"
21339640Smm#include "archive_blake2_impl.h"
22339640Smm
23339640Smmstatic const uint32_t blake2s_IV[8] =
24339640Smm{
25339640Smm  0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
26339640Smm  0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
27339640Smm};
28339640Smm
29339640Smmstatic const uint8_t blake2s_sigma[10][16] =
30339640Smm{
31339640Smm  {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 } ,
32339640Smm  { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 } ,
33339640Smm  { 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4 } ,
34339640Smm  {  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8 } ,
35339640Smm  {  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13 } ,
36339640Smm  {  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9 } ,
37339640Smm  { 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11 } ,
38339640Smm  { 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10 } ,
39339640Smm  {  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5 } ,
40339640Smm  { 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13 , 0 } ,
41339640Smm};
42339640Smm
43339640Smmstatic void blake2s_set_lastnode( blake2s_state *S )
44339640Smm{
45339640Smm  S->f[1] = (uint32_t)-1;
46339640Smm}
47339640Smm
48339640Smm/* Some helper functions, not necessarily useful */
49339640Smmstatic int blake2s_is_lastblock( const blake2s_state *S )
50339640Smm{
51339640Smm  return S->f[0] != 0;
52339640Smm}
53339640Smm
54339640Smmstatic void blake2s_set_lastblock( blake2s_state *S )
55339640Smm{
56339640Smm  if( S->last_node ) blake2s_set_lastnode( S );
57339640Smm
58339640Smm  S->f[0] = (uint32_t)-1;
59339640Smm}
60339640Smm
61339640Smmstatic void blake2s_increment_counter( blake2s_state *S, const uint32_t inc )
62339640Smm{
63339640Smm  S->t[0] += inc;
64339640Smm  S->t[1] += ( S->t[0] < inc );
65339640Smm}
66339640Smm
67339640Smmstatic void blake2s_init0( blake2s_state *S )
68339640Smm{
69339640Smm  size_t i;
70339640Smm  memset( S, 0, sizeof( blake2s_state ) );
71339640Smm
72339640Smm  for( i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i];
73339640Smm}
74339640Smm
75339640Smm/* init2 xors IV with input parameter block */
76339640Smmint blake2s_init_param( blake2s_state *S, const blake2s_param *P )
77339640Smm{
78339640Smm  const unsigned char *p = ( const unsigned char * )( P );
79339640Smm  size_t i;
80339640Smm
81339640Smm  blake2s_init0( S );
82339640Smm
83339640Smm  /* IV XOR ParamBlock */
84339640Smm  for( i = 0; i < 8; ++i )
85339640Smm    S->h[i] ^= load32( &p[i * 4] );
86339640Smm
87339640Smm  S->outlen = P->digest_length;
88339640Smm  return 0;
89339640Smm}
90339640Smm
91339640Smm
92339640Smm/* Sequential blake2s initialization */
93339640Smmint blake2s_init( blake2s_state *S, size_t outlen )
94339640Smm{
95339640Smm  blake2s_param P[1];
96339640Smm
97339640Smm  /* Move interval verification here? */
98339640Smm  if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
99339640Smm
100339640Smm  P->digest_length = (uint8_t)outlen;
101339640Smm  P->key_length    = 0;
102339640Smm  P->fanout        = 1;
103339640Smm  P->depth         = 1;
104339640Smm  store32( &P->leaf_length, 0 );
105339640Smm  store32( &P->node_offset, 0 );
106339640Smm  store16( &P->xof_length, 0 );
107339640Smm  P->node_depth    = 0;
108339640Smm  P->inner_length  = 0;
109339640Smm  /* memset(P->reserved, 0, sizeof(P->reserved) ); */
110339640Smm  memset( P->salt,     0, sizeof( P->salt ) );
111339640Smm  memset( P->personal, 0, sizeof( P->personal ) );
112339640Smm  return blake2s_init_param( S, P );
113339640Smm}
114339640Smm
115339640Smmint blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen )
116339640Smm{
117339640Smm  blake2s_param P[1];
118339640Smm
119339640Smm  if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
120339640Smm
121339640Smm  if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
122339640Smm
123339640Smm  P->digest_length = (uint8_t)outlen;
124339640Smm  P->key_length    = (uint8_t)keylen;
125339640Smm  P->fanout        = 1;
126339640Smm  P->depth         = 1;
127339640Smm  store32( &P->leaf_length, 0 );
128339640Smm  store32( &P->node_offset, 0 );
129339640Smm  store16( &P->xof_length, 0 );
130339640Smm  P->node_depth    = 0;
131339640Smm  P->inner_length  = 0;
132339640Smm  /* memset(P->reserved, 0, sizeof(P->reserved) ); */
133339640Smm  memset( P->salt,     0, sizeof( P->salt ) );
134339640Smm  memset( P->personal, 0, sizeof( P->personal ) );
135339640Smm
136339640Smm  if( blake2s_init_param( S, P ) < 0 ) return -1;
137339640Smm
138339640Smm  {
139339640Smm    uint8_t block[BLAKE2S_BLOCKBYTES];
140339640Smm    memset( block, 0, BLAKE2S_BLOCKBYTES );
141339640Smm    memcpy( block, key, keylen );
142339640Smm    blake2s_update( S, block, BLAKE2S_BLOCKBYTES );
143339640Smm    secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
144339640Smm  }
145339640Smm  return 0;
146339640Smm}
147339640Smm
148339640Smm#define G(r,i,a,b,c,d)                      \
149339640Smm  do {                                      \
150339640Smm    a = a + b + m[blake2s_sigma[r][2*i+0]]; \
151339640Smm    d = rotr32(d ^ a, 16);                  \
152339640Smm    c = c + d;                              \
153339640Smm    b = rotr32(b ^ c, 12);                  \
154339640Smm    a = a + b + m[blake2s_sigma[r][2*i+1]]; \
155339640Smm    d = rotr32(d ^ a, 8);                   \
156339640Smm    c = c + d;                              \
157339640Smm    b = rotr32(b ^ c, 7);                   \
158339640Smm  } while(0)
159339640Smm
160339640Smm#define ROUND(r)                    \
161339640Smm  do {                              \
162339640Smm    G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
163339640Smm    G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
164339640Smm    G(r,2,v[ 2],v[ 6],v[10],v[14]); \
165339640Smm    G(r,3,v[ 3],v[ 7],v[11],v[15]); \
166339640Smm    G(r,4,v[ 0],v[ 5],v[10],v[15]); \
167339640Smm    G(r,5,v[ 1],v[ 6],v[11],v[12]); \
168339640Smm    G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
169339640Smm    G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
170339640Smm  } while(0)
171339640Smm
172339640Smmstatic void blake2s_compress( blake2s_state *S, const uint8_t in[BLAKE2S_BLOCKBYTES] )
173339640Smm{
174339640Smm  uint32_t m[16];
175339640Smm  uint32_t v[16];
176339640Smm  size_t i;
177339640Smm
178339640Smm  for( i = 0; i < 16; ++i ) {
179339640Smm    m[i] = load32( in + i * sizeof( m[i] ) );
180339640Smm  }
181339640Smm
182339640Smm  for( i = 0; i < 8; ++i ) {
183339640Smm    v[i] = S->h[i];
184339640Smm  }
185339640Smm
186339640Smm  v[ 8] = blake2s_IV[0];
187339640Smm  v[ 9] = blake2s_IV[1];
188339640Smm  v[10] = blake2s_IV[2];
189339640Smm  v[11] = blake2s_IV[3];
190339640Smm  v[12] = S->t[0] ^ blake2s_IV[4];
191339640Smm  v[13] = S->t[1] ^ blake2s_IV[5];
192339640Smm  v[14] = S->f[0] ^ blake2s_IV[6];
193339640Smm  v[15] = S->f[1] ^ blake2s_IV[7];
194339640Smm
195339640Smm  ROUND( 0 );
196339640Smm  ROUND( 1 );
197339640Smm  ROUND( 2 );
198339640Smm  ROUND( 3 );
199339640Smm  ROUND( 4 );
200339640Smm  ROUND( 5 );
201339640Smm  ROUND( 6 );
202339640Smm  ROUND( 7 );
203339640Smm  ROUND( 8 );
204339640Smm  ROUND( 9 );
205339640Smm
206339640Smm  for( i = 0; i < 8; ++i ) {
207339640Smm    S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
208339640Smm  }
209339640Smm}
210339640Smm
211339640Smm#undef G
212339640Smm#undef ROUND
213339640Smm
214339640Smmint blake2s_update( blake2s_state *S, const void *pin, size_t inlen )
215339640Smm{
216339640Smm  const unsigned char * in = (const unsigned char *)pin;
217339640Smm  if( inlen > 0 )
218339640Smm  {
219339640Smm    size_t left = S->buflen;
220339640Smm    size_t fill = BLAKE2S_BLOCKBYTES - left;
221339640Smm    if( inlen > fill )
222339640Smm    {
223339640Smm      S->buflen = 0;
224339640Smm      memcpy( S->buf + left, in, fill ); /* Fill buffer */
225339640Smm      blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
226339640Smm      blake2s_compress( S, S->buf ); /* Compress */
227339640Smm      in += fill; inlen -= fill;
228339640Smm      while(inlen > BLAKE2S_BLOCKBYTES) {
229339640Smm        blake2s_increment_counter(S, BLAKE2S_BLOCKBYTES);
230339640Smm        blake2s_compress( S, in );
231339640Smm        in += BLAKE2S_BLOCKBYTES;
232339640Smm        inlen -= BLAKE2S_BLOCKBYTES;
233339640Smm      }
234339640Smm    }
235339640Smm    memcpy( S->buf + S->buflen, in, inlen );
236339640Smm    S->buflen += inlen;
237339640Smm  }
238339640Smm  return 0;
239339640Smm}
240339640Smm
241339640Smmint blake2s_final( blake2s_state *S, void *out, size_t outlen )
242339640Smm{
243339640Smm  uint8_t buffer[BLAKE2S_OUTBYTES] = {0};
244339640Smm  size_t i;
245339640Smm
246339640Smm  if( out == NULL || outlen < S->outlen )
247339640Smm    return -1;
248339640Smm
249339640Smm  if( blake2s_is_lastblock( S ) )
250339640Smm    return -1;
251339640Smm
252339640Smm  blake2s_increment_counter( S, ( uint32_t )S->buflen );
253339640Smm  blake2s_set_lastblock( S );
254339640Smm  memset( S->buf + S->buflen, 0, BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */
255339640Smm  blake2s_compress( S, S->buf );
256339640Smm
257339640Smm  for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
258339640Smm    store32( buffer + sizeof( S->h[i] ) * i, S->h[i] );
259339640Smm
260339640Smm  memcpy( out, buffer, outlen );
261339640Smm  secure_zero_memory(buffer, sizeof(buffer));
262339640Smm  return 0;
263339640Smm}
264339640Smm
265339640Smmint blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
266339640Smm{
267339640Smm  blake2s_state S[1];
268339640Smm
269339640Smm  /* Verify parameters */
270339640Smm  if ( NULL == in && inlen > 0 ) return -1;
271339640Smm
272339640Smm  if ( NULL == out ) return -1;
273339640Smm
274339640Smm  if ( NULL == key && keylen > 0) return -1;
275339640Smm
276339640Smm  if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
277339640Smm
278339640Smm  if( keylen > BLAKE2S_KEYBYTES ) return -1;
279339640Smm
280339640Smm  if( keylen > 0 )
281339640Smm  {
282339640Smm    if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1;
283339640Smm  }
284339640Smm  else
285339640Smm  {
286339640Smm    if( blake2s_init( S, outlen ) < 0 ) return -1;
287339640Smm  }
288339640Smm
289339640Smm  blake2s_update( S, ( const uint8_t * )in, inlen );
290339640Smm  blake2s_final( S, out, outlen );
291339640Smm  return 0;
292339640Smm}
293339640Smm
294339640Smm#if defined(SUPERCOP)
295339640Smmint crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
296339640Smm{
297339640Smm  return blake2s( out, BLAKE2S_OUTBYTES, in, inlen, NULL, 0 );
298339640Smm}
299339640Smm#endif
300339640Smm
301339640Smm#if defined(BLAKE2S_SELFTEST)
302339640Smm#include <string.h>
303339640Smm#include "blake2-kat.h"
304339640Smmint main( void )
305339640Smm{
306339640Smm  uint8_t key[BLAKE2S_KEYBYTES];
307339640Smm  uint8_t buf[BLAKE2_KAT_LENGTH];
308339640Smm  size_t i, step;
309339640Smm
310339640Smm  for( i = 0; i < BLAKE2S_KEYBYTES; ++i )
311339640Smm    key[i] = ( uint8_t )i;
312339640Smm
313339640Smm  for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
314339640Smm    buf[i] = ( uint8_t )i;
315339640Smm
316339640Smm  /* Test simple API */
317339640Smm  for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
318339640Smm  {
319339640Smm    uint8_t hash[BLAKE2S_OUTBYTES];
320339640Smm    blake2s( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
321339640Smm
322339640Smm    if( 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) )
323339640Smm    {
324339640Smm      goto fail;
325339640Smm    }
326339640Smm  }
327339640Smm
328339640Smm  /* Test streaming API */
329339640Smm  for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
330339640Smm    for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
331339640Smm      uint8_t hash[BLAKE2S_OUTBYTES];
332339640Smm      blake2s_state S;
333339640Smm      uint8_t * p = buf;
334339640Smm      size_t mlen = i;
335339640Smm      int err = 0;
336339640Smm
337339640Smm      if( (err = blake2s_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
338339640Smm        goto fail;
339339640Smm      }
340339640Smm
341339640Smm      while (mlen >= step) {
342339640Smm        if ( (err = blake2s_update(&S, p, step)) < 0 ) {
343339640Smm          goto fail;
344339640Smm        }
345339640Smm        mlen -= step;
346339640Smm        p += step;
347339640Smm      }
348339640Smm      if ( (err = blake2s_update(&S, p, mlen)) < 0) {
349339640Smm        goto fail;
350339640Smm      }
351339640Smm      if ( (err = blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
352339640Smm        goto fail;
353339640Smm      }
354339640Smm
355339640Smm      if (0 != memcmp(hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES)) {
356339640Smm        goto fail;
357339640Smm      }
358339640Smm    }
359339640Smm  }
360339640Smm
361339640Smm  puts( "ok" );
362339640Smm  return 0;
363339640Smmfail:
364339640Smm  puts("error");
365339640Smm  return -1;
366339640Smm}
367339640Smm#endif
368