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