librsync  2.0.1
blake2b-ref.c
1 /*
2  BLAKE2 reference source code package - reference C implementations
3 
4  Written in 2012 by Samuel Neves <[email protected]>
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 
14 /* This code, but not the algorithm, has been slightly modified for use in
15  * librsync.
16  */
17 
18 #include "config.h"
19 #include <stdint.h>
20 #include <string.h>
21 #include <stdio.h>
22 
23 #include "blake2.h"
24 #include "blake2-impl.h"
25 
26 static const uint64_t blake2b_IV[8] =
27 {
28  0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
29  0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
30  0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
31  0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
32 };
33 
34 static const uint8_t blake2b_sigma[12][16] =
35 {
36  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
37  { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
38  { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
39  { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
40  { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
41  { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
42  { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
43  { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
44  { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
45  { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
46  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
47  { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
48 };
49 
50 
51 static inline int blake2b_set_lastnode( blake2b_state *S )
52 {
53  S->f[1] = ~0ULL;
54  return 0;
55 }
56 
57 static inline int blake2b_clear_lastnode( blake2b_state *S )
58 {
59  S->f[1] = 0ULL;
60  return 0;
61 }
62 
63 /* Some helper functions, not necessarily useful */
64 static inline int blake2b_set_lastblock( blake2b_state *S )
65 {
66  if( S->last_node ) blake2b_set_lastnode( S );
67 
68  S->f[0] = ~0ULL;
69  return 0;
70 }
71 
72 static inline int blake2b_clear_lastblock( blake2b_state *S )
73 {
74  if( S->last_node ) blake2b_clear_lastnode( S );
75 
76  S->f[0] = 0ULL;
77  return 0;
78 }
79 
80 static inline int blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
81 {
82  S->t[0] += inc;
83  S->t[1] += ( S->t[0] < inc );
84  return 0;
85 }
86 
87 
88 
89 // Parameter-related functions
90 static inline int blake2b_param_set_digest_length( blake2b_param *P, const uint8_t digest_length )
91 {
92  P->digest_length = digest_length;
93  return 0;
94 }
95 
96 static inline int blake2b_param_set_fanout( blake2b_param *P, const uint8_t fanout )
97 {
98  P->fanout = fanout;
99  return 0;
100 }
101 
102 static inline int blake2b_param_set_max_depth( blake2b_param *P, const uint8_t depth )
103 {
104  P->depth = depth;
105  return 0;
106 }
107 
108 static inline int blake2b_param_set_leaf_length( blake2b_param *P, const uint32_t leaf_length )
109 {
110  store32( &P->leaf_length, leaf_length );
111  return 0;
112 }
113 
114 static inline int blake2b_param_set_node_offset( blake2b_param *P, const uint64_t node_offset )
115 {
116  store64( &P->node_offset, node_offset );
117  return 0;
118 }
119 
120 static inline int blake2b_param_set_node_depth( blake2b_param *P, const uint8_t node_depth )
121 {
122  P->node_depth = node_depth;
123  return 0;
124 }
125 
126 static inline int blake2b_param_set_inner_length( blake2b_param *P, const uint8_t inner_length )
127 {
128  P->inner_length = inner_length;
129  return 0;
130 }
131 
132 static inline int blake2b_param_set_salt( blake2b_param *P, const uint8_t salt[BLAKE2B_SALTBYTES] )
133 {
134  memcpy( P->salt, salt, BLAKE2B_SALTBYTES );
135  return 0;
136 }
137 
138 static inline int blake2b_param_set_personal( blake2b_param *P, const uint8_t personal[BLAKE2B_PERSONALBYTES] )
139 {
140  memcpy( P->personal, personal, BLAKE2B_PERSONALBYTES );
141  return 0;
142 }
143 
144 static inline int blake2b_init0( blake2b_state *S )
145 {
146  int i;
147  memset( S, 0, sizeof( blake2b_state ) );
148 
149  for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];
150 
151  return 0;
152 }
153 
154 /* init xors IV with input parameter block */
155 int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
156 {
157  const uint8_t *p = ( const uint8_t * )( P );
158  size_t i;
159 
160  blake2b_init0( S );
161  /* IV XOR ParamBlock */
162  for( i = 0; i < 8; ++i )
163  S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );
164 
165  return 0;
166 }
167 
168 
169 
170 int blake2b_init( blake2b_state *S, const uint8_t outlen )
171 {
172  blake2b_param P[1];
173 
174  if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
175 
176  P->digest_length = outlen;
177  P->key_length = 0;
178  P->fanout = 1;
179  P->depth = 1;
180  store32( &P->leaf_length, 0 );
181  store64( &P->node_offset, 0 );
182  P->node_depth = 0;
183  P->inner_length = 0;
184  memset( P->reserved, 0, sizeof( P->reserved ) );
185  memset( P->salt, 0, sizeof( P->salt ) );
186  memset( P->personal, 0, sizeof( P->personal ) );
187  return blake2b_init_param( S, P );
188 }
189 
190 
191 int blake2b_init_key( blake2b_state *S, const uint8_t outlen, const void *key, const uint8_t keylen )
192 {
193  blake2b_param P[1];
194 
195  if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
196 
197  if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
198 
199  P->digest_length = outlen;
200  P->key_length = keylen;
201  P->fanout = 1;
202  P->depth = 1;
203  store32( &P->leaf_length, 0 );
204  store64( &P->node_offset, 0 );
205  P->node_depth = 0;
206  P->inner_length = 0;
207  memset( P->reserved, 0, sizeof( P->reserved ) );
208  memset( P->salt, 0, sizeof( P->salt ) );
209  memset( P->personal, 0, sizeof( P->personal ) );
210 
211  if( blake2b_init_param( S, P ) < 0 ) return -1;
212 
213  {
214  uint8_t block[BLAKE2B_BLOCKBYTES];
215  memset( block, 0, BLAKE2B_BLOCKBYTES );
216  memcpy( block, key, keylen );
217  blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
218  secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
219  }
220  return 0;
221 }
222 
223 static int blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
224 {
225  uint64_t m[16];
226  uint64_t v[16];
227  int i;
228 
229  for( i = 0; i < 16; ++i )
230  m[i] = load64( block + i * sizeof( m[i] ) );
231 
232  for( i = 0; i < 8; ++i )
233  v[i] = S->h[i];
234 
235  v[ 8] = blake2b_IV[0];
236  v[ 9] = blake2b_IV[1];
237  v[10] = blake2b_IV[2];
238  v[11] = blake2b_IV[3];
239  v[12] = S->t[0] ^ blake2b_IV[4];
240  v[13] = S->t[1] ^ blake2b_IV[5];
241  v[14] = S->f[0] ^ blake2b_IV[6];
242  v[15] = S->f[1] ^ blake2b_IV[7];
243 #define G(r,i,a,b,c,d) \
244  do { \
245  a = a + b + m[blake2b_sigma[r][2*i+0]]; \
246  d = rotr64(d ^ a, 32); \
247  c = c + d; \
248  b = rotr64(b ^ c, 24); \
249  a = a + b + m[blake2b_sigma[r][2*i+1]]; \
250  d = rotr64(d ^ a, 16); \
251  c = c + d; \
252  b = rotr64(b ^ c, 63); \
253  } while(0)
254 #define ROUND(r) \
255  do { \
256  G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
257  G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
258  G(r,2,v[ 2],v[ 6],v[10],v[14]); \
259  G(r,3,v[ 3],v[ 7],v[11],v[15]); \
260  G(r,4,v[ 0],v[ 5],v[10],v[15]); \
261  G(r,5,v[ 1],v[ 6],v[11],v[12]); \
262  G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
263  G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
264  } while(0)
265  ROUND( 0 );
266  ROUND( 1 );
267  ROUND( 2 );
268  ROUND( 3 );
269  ROUND( 4 );
270  ROUND( 5 );
271  ROUND( 6 );
272  ROUND( 7 );
273  ROUND( 8 );
274  ROUND( 9 );
275  ROUND( 10 );
276  ROUND( 11 );
277 
278  for( i = 0; i < 8; ++i )
279  S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
280 
281 #undef G
282 #undef ROUND
283  return 0;
284 }
285 
286 /* inlen now in bytes */
287 int blake2b_update( blake2b_state *S, const uint8_t *in, uint64_t inlen )
288 {
289  while( inlen > 0 )
290  {
291  size_t left = S->buflen;
292  size_t fill = 2 * BLAKE2B_BLOCKBYTES - left;
293 
294  if( inlen > fill )
295  {
296  memcpy( S->buf + left, in, fill ); // Fill buffer
297  S->buflen += fill;
298  blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
299  blake2b_compress( S, S->buf ); // Compress
300  memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); // Shift buffer left
301  S->buflen -= BLAKE2B_BLOCKBYTES;
302  in += fill;
303  inlen -= fill;
304  }
305  else // inlen <= fill
306  {
307  memcpy( S->buf + left, in, inlen );
308  S->buflen += inlen; // Be lazy, do not compress
309  in += inlen;
310  inlen -= inlen;
311  }
312  }
313 
314  return 0;
315 }
316 
317 /* Is this correct? */
318 int blake2b_final( blake2b_state *S, uint8_t *out, uint8_t outlen )
319 {
320  uint8_t buffer[BLAKE2B_OUTBYTES];
321  int i;
322 
323  if( S->buflen > BLAKE2B_BLOCKBYTES )
324  {
325  blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
326  blake2b_compress( S, S->buf );
327  S->buflen -= BLAKE2B_BLOCKBYTES;
328  memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, S->buflen );
329  }
330 
331  blake2b_increment_counter( S, S->buflen );
332  blake2b_set_lastblock( S );
333  memset( S->buf + S->buflen, 0, 2 * BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */
334  blake2b_compress( S, S->buf );
335 
336  for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
337  store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );
338 
339  memcpy( out, buffer, outlen );
340  return 0;
341 }
342 
343 /* inlen, at least, should be uint64_t. Others can be size_t. */
344 int blake2b( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen )
345 {
346  blake2b_state S[1];
347 
348  /* Verify parameters */
349  if ( NULL == in ) return -1;
350 
351  if ( NULL == out ) return -1;
352 
353  if( NULL == key ) keylen = 0;
354 
355  if( keylen > 0 )
356  {
357  if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
358  }
359  else
360  {
361  if( blake2b_init( S, outlen ) < 0 ) return -1;
362  }
363 
364  blake2b_update( S, ( const uint8_t * )in, inlen );
365  blake2b_final( S, out, outlen );
366  return 0;
367 }
368 
369 #if defined(BLAKE2B_SELFTEST)
370 #include <string.h>
371 #include "blake2-kat.h"
372 int main( int argc, char **argv )
373 {
374  uint8_t key[BLAKE2B_KEYBYTES];
375  uint8_t buf[KAT_LENGTH];
376 
377  for( size_t i = 0; i < BLAKE2B_KEYBYTES; ++i )
378  key[i] = ( uint8_t )i;
379 
380  for( size_t i = 0; i < KAT_LENGTH; ++i )
381  buf[i] = ( uint8_t )i;
382 
383  for( size_t i = 0; i < KAT_LENGTH; ++i )
384  {
385  uint8_t hash[BLAKE2B_OUTBYTES];
386  blake2b( hash, buf, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES );
387 
388  if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )
389  {
390  puts( "error" );
391  return -1;
392  }
393  }
394 
395  puts( "ok" );
396  return 0;
397 }
398 #endif
399