/ external / blake2 / blake2s-ref.c
blake2s-ref.c
  1  /*
  2     BLAKE2 reference source code package - reference C implementations
  3    
  4     Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the
  5     terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
  6     your option.  The terms of these licenses can be found at:
  7    
  8     - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
  9     - OpenSSL license   : https://www.openssl.org/source/license.html
 10     - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
 11    
 12     More information about the BLAKE2 hash function can be found at
 13     https://blake2.net.
 14  */
 15  
 16  #include <stdint.h>
 17  #include <string.h>
 18  #include <stdio.h>
 19  
 20  #include "blake2.h"
 21  #include "blake2-impl.h"
 22  
 23  static const uint32_t blake2s_IV[8] =
 24  {
 25    0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
 26    0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
 27  };
 28  
 29  static const uint8_t blake2s_sigma[10][16] =
 30  {
 31    {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 } ,
 32    { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 } ,
 33    { 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4 } ,
 34    {  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8 } ,
 35    {  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13 } ,
 36    {  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9 } ,
 37    { 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11 } ,
 38    { 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10 } ,
 39    {  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5 } ,
 40    { 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13 , 0 } ,
 41  };
 42  
 43  static void blake2s_set_lastnode( blake2s_state *S )
 44  {
 45    S->f[1] = (uint32_t)-1;
 46  }
 47  
 48  /* Some helper functions, not necessarily useful */
 49  static int blake2s_is_lastblock( const blake2s_state *S )
 50  {
 51    return S->f[0] != 0;
 52  }
 53  
 54  static void blake2s_set_lastblock( blake2s_state *S )
 55  {
 56    if( S->last_node ) blake2s_set_lastnode( S );
 57  
 58    S->f[0] = (uint32_t)-1;
 59  }
 60  
 61  static void blake2s_increment_counter( blake2s_state *S, const uint32_t inc )
 62  {
 63    S->t[0] += inc;
 64    S->t[1] += ( S->t[0] < inc );
 65  }
 66  
 67  static void blake2s_init0( blake2s_state *S )
 68  {
 69    size_t i;
 70    memset( S, 0, sizeof( blake2s_state ) );
 71  
 72    for( i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i];
 73  }
 74  
 75  /* init2 xors IV with input parameter block */
 76  int blake2s_init_param( blake2s_state *S, const blake2s_param *P )
 77  {
 78    const unsigned char *p = ( const unsigned char * )( P );
 79    size_t i;
 80  
 81    blake2s_init0( S );
 82  
 83    /* IV XOR ParamBlock */
 84    for( i = 0; i < 8; ++i )
 85      S->h[i] ^= load32( &p[i * 4] );
 86  
 87    S->outlen = P->digest_length;
 88    return 0;
 89  }
 90  
 91  
 92  /* Sequential blake2s initialization */
 93  int blake2s_init( blake2s_state *S, size_t outlen )
 94  {
 95    blake2s_param P[1];
 96  
 97    /* Move interval verification here? */
 98    if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
 99  
100    P->digest_length = (uint8_t)outlen;
101    P->key_length    = 0;
102    P->fanout        = 1;
103    P->depth         = 1;
104    store32( &P->leaf_length, 0 );
105    store32( &P->node_offset, 0 );
106    store16( &P->xof_length, 0 );
107    P->node_depth    = 0;
108    P->inner_length  = 0;
109    /* memset(P->reserved, 0, sizeof(P->reserved) ); */
110    memset( P->salt,     0, sizeof( P->salt ) );
111    memset( P->personal, 0, sizeof( P->personal ) );
112    return blake2s_init_param( S, P );
113  }
114  
115  int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen )
116  {
117    blake2s_param P[1];
118  
119    if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
120  
121    if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
122  
123    P->digest_length = (uint8_t)outlen;
124    P->key_length    = (uint8_t)keylen;
125    P->fanout        = 1;
126    P->depth         = 1;
127    store32( &P->leaf_length, 0 );
128    store32( &P->node_offset, 0 );
129    store16( &P->xof_length, 0 );
130    P->node_depth    = 0;
131    P->inner_length  = 0;
132    /* memset(P->reserved, 0, sizeof(P->reserved) ); */
133    memset( P->salt,     0, sizeof( P->salt ) );
134    memset( P->personal, 0, sizeof( P->personal ) );
135  
136    if( blake2s_init_param( S, P ) < 0 ) return -1;
137  
138    {
139      uint8_t block[BLAKE2S_BLOCKBYTES];
140      memset( block, 0, BLAKE2S_BLOCKBYTES );
141      memcpy( block, key, keylen );
142      blake2s_update( S, block, BLAKE2S_BLOCKBYTES );
143      secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
144    }
145    return 0;
146  }
147  
148  #define G(r,i,a,b,c,d)                      \
149    do {                                      \
150      a = a + b + m[blake2s_sigma[r][2*i+0]]; \
151      d = rotr32(d ^ a, 16);                  \
152      c = c + d;                              \
153      b = rotr32(b ^ c, 12);                  \
154      a = a + b + m[blake2s_sigma[r][2*i+1]]; \
155      d = rotr32(d ^ a, 8);                   \
156      c = c + d;                              \
157      b = rotr32(b ^ c, 7);                   \
158    } while(0)
159  
160  #define ROUND(r)                    \
161    do {                              \
162      G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
163      G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
164      G(r,2,v[ 2],v[ 6],v[10],v[14]); \
165      G(r,3,v[ 3],v[ 7],v[11],v[15]); \
166      G(r,4,v[ 0],v[ 5],v[10],v[15]); \
167      G(r,5,v[ 1],v[ 6],v[11],v[12]); \
168      G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
169      G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
170    } while(0)
171  
172  static void blake2s_compress( blake2s_state *S, const uint8_t in[BLAKE2S_BLOCKBYTES] )
173  {
174    uint32_t m[16];
175    uint32_t v[16];
176    size_t i;
177  
178    for( i = 0; i < 16; ++i ) {
179      m[i] = load32( in + i * sizeof( m[i] ) );
180    }
181  
182    for( i = 0; i < 8; ++i ) {
183      v[i] = S->h[i];
184    }
185  
186    v[ 8] = blake2s_IV[0];
187    v[ 9] = blake2s_IV[1];
188    v[10] = blake2s_IV[2];
189    v[11] = blake2s_IV[3];
190    v[12] = S->t[0] ^ blake2s_IV[4];
191    v[13] = S->t[1] ^ blake2s_IV[5];
192    v[14] = S->f[0] ^ blake2s_IV[6];
193    v[15] = S->f[1] ^ blake2s_IV[7];
194  
195    ROUND( 0 );
196    ROUND( 1 );
197    ROUND( 2 );
198    ROUND( 3 );
199    ROUND( 4 );
200    ROUND( 5 );
201    ROUND( 6 );
202    ROUND( 7 );
203    ROUND( 8 );
204    ROUND( 9 );
205  
206    for( i = 0; i < 8; ++i ) {
207      S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
208    }
209  }
210  
211  #undef G
212  #undef ROUND
213  
214  int blake2s_update( blake2s_state *S, const void *pin, size_t inlen )
215  {
216    const unsigned char * in = (const unsigned char *)pin;
217    if( inlen > 0 )
218    {
219      size_t left = S->buflen;
220      size_t fill = BLAKE2S_BLOCKBYTES - left;
221      if( inlen > fill )
222      {
223        S->buflen = 0;
224        memcpy( S->buf + left, in, fill ); /* Fill buffer */
225        blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
226        blake2s_compress( S, S->buf ); /* Compress */
227        in += fill; inlen -= fill;
228        while(inlen > BLAKE2S_BLOCKBYTES) {
229          blake2s_increment_counter(S, BLAKE2S_BLOCKBYTES);
230          blake2s_compress( S, in );
231          in += BLAKE2S_BLOCKBYTES;
232          inlen -= BLAKE2S_BLOCKBYTES;
233        }
234      }
235      memcpy( S->buf + S->buflen, in, inlen );
236      S->buflen += inlen;
237    }
238    return 0;
239  }
240  
241  int blake2s_final( blake2s_state *S, void *out, size_t outlen )
242  {
243    uint8_t buffer[BLAKE2S_OUTBYTES] = {0};
244    size_t i;
245  
246    if( out == NULL || outlen < S->outlen )
247      return -1;
248  
249    if( blake2s_is_lastblock( S ) )
250      return -1;
251  
252    blake2s_increment_counter( S, ( uint32_t )S->buflen );
253    blake2s_set_lastblock( S );
254    memset( S->buf + S->buflen, 0, BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */
255    blake2s_compress( S, S->buf );
256  
257    for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
258      store32( buffer + sizeof( S->h[i] ) * i, S->h[i] );
259  
260    memcpy( out, buffer, outlen );
261    secure_zero_memory(buffer, sizeof(buffer));
262    return 0;
263  }
264  
265  int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
266  {
267    blake2s_state S[1];
268  
269    /* Verify parameters */
270    if ( NULL == in && inlen > 0 ) return -1;
271  
272    if ( NULL == out ) return -1;
273  
274    if ( NULL == key && keylen > 0) return -1;
275  
276    if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
277  
278    if( keylen > BLAKE2S_KEYBYTES ) return -1;
279  
280    if( keylen > 0 )
281    {
282      if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1;
283    }
284    else
285    {
286      if( blake2s_init( S, outlen ) < 0 ) return -1;
287    }
288  
289    blake2s_update( S, ( const uint8_t * )in, inlen );
290    blake2s_final( S, out, outlen );
291    return 0;
292  }
293  
294  #if defined(SUPERCOP)
295  int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
296  {
297    return blake2s( out, BLAKE2S_OUTBYTES in, inlen, NULL, 0 );
298  }
299  #endif
300  
301  #if defined(BLAKE2S_SELFTEST)
302  #include <string.h>
303  #include "blake2-kat.h"
304  int main( void )
305  {
306    uint8_t key[BLAKE2S_KEYBYTES];
307    uint8_t buf[BLAKE2_KAT_LENGTH];
308    size_t i, step;
309  
310    for( i = 0; i < BLAKE2S_KEYBYTES; ++i )
311      key[i] = ( uint8_t )i;
312  
313    for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
314      buf[i] = ( uint8_t )i;
315  
316    /* Test simple API */
317    for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
318    {
319      uint8_t hash[BLAKE2S_OUTBYTES];
320      blake2s( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
321  
322      if( 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) )
323      {
324        goto fail;
325      }
326    }
327  
328    /* Test streaming API */
329    for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
330      for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
331        uint8_t hash[BLAKE2S_OUTBYTES];
332        blake2s_state S;
333        uint8_t * p = buf;
334        size_t mlen = i;
335        int err = 0;
336  
337        if( (err = blake2s_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
338          goto fail;
339        }
340  
341        while (mlen >= step) {
342          if ( (err = blake2s_update(&S, p, step)) < 0 ) {
343            goto fail;
344          }
345          mlen -= step;
346          p += step;
347        }
348        if ( (err = blake2s_update(&S, p, mlen)) < 0) {
349          goto fail;
350        }
351        if ( (err = blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
352          goto fail;
353        }
354  
355        if (0 != memcmp(hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES)) {
356          goto fail;
357        }
358      }
359    }
360  
361    puts( "ok" );
362    return 0;
363  fail:
364    puts("error");
365    return -1;
366  }
367  #endif
368  
369