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