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 <stdlib.h> 17339640Smm#include <string.h> 18339640Smm#include <stdio.h> 19339640Smm 20339640Smm#if defined(_OPENMP) 21339640Smm#include <omp.h> 22339640Smm#endif 23339640Smm 24339640Smm#include "archive_blake2.h" 25339640Smm#include "archive_blake2_impl.h" 26339640Smm 27339640Smm#define PARALLELISM_DEGREE 8 28339640Smm 29339640Smm/* 30339640Smm blake2sp_init_param defaults to setting the expecting output length 31339640Smm from the digest_length parameter block field. 32339640Smm 33339640Smm In some cases, however, we do not want this, as the output length 34339640Smm of these instances is given by inner_length instead. 35339640Smm*/ 36339640Smmstatic int blake2sp_init_leaf_param( blake2s_state *S, const blake2s_param *P ) 37339640Smm{ 38339640Smm int err = blake2s_init_param(S, P); 39339640Smm S->outlen = P->inner_length; 40339640Smm return err; 41339640Smm} 42339640Smm 43339640Smmstatic int blake2sp_init_leaf( blake2s_state *S, size_t outlen, size_t keylen, uint32_t offset ) 44339640Smm{ 45339640Smm blake2s_param P[1]; 46339640Smm P->digest_length = (uint8_t)outlen; 47339640Smm P->key_length = (uint8_t)keylen; 48339640Smm P->fanout = PARALLELISM_DEGREE; 49339640Smm P->depth = 2; 50339640Smm store32( &P->leaf_length, 0 ); 51339640Smm store32( &P->node_offset, offset ); 52339640Smm store16( &P->xof_length, 0 ); 53339640Smm P->node_depth = 0; 54339640Smm P->inner_length = BLAKE2S_OUTBYTES; 55339640Smm memset( P->salt, 0, sizeof( P->salt ) ); 56339640Smm memset( P->personal, 0, sizeof( P->personal ) ); 57339640Smm return blake2sp_init_leaf_param( S, P ); 58339640Smm} 59339640Smm 60339640Smmstatic int blake2sp_init_root( blake2s_state *S, size_t outlen, size_t keylen ) 61339640Smm{ 62339640Smm blake2s_param P[1]; 63339640Smm P->digest_length = (uint8_t)outlen; 64339640Smm P->key_length = (uint8_t)keylen; 65339640Smm P->fanout = PARALLELISM_DEGREE; 66339640Smm P->depth = 2; 67339640Smm store32( &P->leaf_length, 0 ); 68339640Smm store32( &P->node_offset, 0 ); 69339640Smm store16( &P->xof_length, 0 ); 70339640Smm P->node_depth = 1; 71339640Smm P->inner_length = BLAKE2S_OUTBYTES; 72339640Smm memset( P->salt, 0, sizeof( P->salt ) ); 73339640Smm memset( P->personal, 0, sizeof( P->personal ) ); 74339640Smm return blake2s_init_param( S, P ); 75339640Smm} 76339640Smm 77339640Smm 78339640Smmint blake2sp_init( blake2sp_state *S, size_t outlen ) 79339640Smm{ 80339640Smm size_t i; 81339640Smm 82339640Smm if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1; 83339640Smm 84339640Smm memset( S->buf, 0, sizeof( S->buf ) ); 85339640Smm S->buflen = 0; 86339640Smm S->outlen = outlen; 87339640Smm 88339640Smm if( blake2sp_init_root( S->R, outlen, 0 ) < 0 ) 89339640Smm return -1; 90339640Smm 91339640Smm for( i = 0; i < PARALLELISM_DEGREE; ++i ) 92346105Smm if( blake2sp_init_leaf( S->S[i], outlen, 0, (uint32_t)i ) < 0 ) return -1; 93339640Smm 94339640Smm S->R->last_node = 1; 95339640Smm S->S[PARALLELISM_DEGREE - 1]->last_node = 1; 96339640Smm return 0; 97339640Smm} 98339640Smm 99339640Smmint blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen ) 100339640Smm{ 101339640Smm size_t i; 102339640Smm 103339640Smm if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1; 104339640Smm 105339640Smm if( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1; 106339640Smm 107339640Smm memset( S->buf, 0, sizeof( S->buf ) ); 108339640Smm S->buflen = 0; 109339640Smm S->outlen = outlen; 110339640Smm 111339640Smm if( blake2sp_init_root( S->R, outlen, keylen ) < 0 ) 112339640Smm return -1; 113339640Smm 114339640Smm for( i = 0; i < PARALLELISM_DEGREE; ++i ) 115346105Smm if( blake2sp_init_leaf( S->S[i], outlen, keylen, (uint32_t)i ) < 0 ) return -1; 116339640Smm 117339640Smm S->R->last_node = 1; 118339640Smm S->S[PARALLELISM_DEGREE - 1]->last_node = 1; 119339640Smm { 120339640Smm uint8_t block[BLAKE2S_BLOCKBYTES]; 121339640Smm memset( block, 0, BLAKE2S_BLOCKBYTES ); 122339640Smm memcpy( block, key, keylen ); 123339640Smm 124339640Smm for( i = 0; i < PARALLELISM_DEGREE; ++i ) 125339640Smm blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES ); 126339640Smm 127339640Smm secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */ 128339640Smm } 129339640Smm return 0; 130339640Smm} 131339640Smm 132339640Smm 133339640Smmint blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen ) 134339640Smm{ 135339640Smm const unsigned char * in = (const unsigned char *)pin; 136339640Smm size_t left = S->buflen; 137339640Smm size_t fill = sizeof( S->buf ) - left; 138339640Smm size_t i; 139339640Smm 140339640Smm if( left && inlen >= fill ) 141339640Smm { 142339640Smm memcpy( S->buf + left, in, fill ); 143339640Smm 144339640Smm for( i = 0; i < PARALLELISM_DEGREE; ++i ) 145339640Smm blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); 146339640Smm 147339640Smm in += fill; 148339640Smm inlen -= fill; 149339640Smm left = 0; 150339640Smm } 151339640Smm 152339640Smm#if defined(_OPENMP) 153339640Smm #pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE) 154339640Smm#else 155339640Smm for( i = 0; i < PARALLELISM_DEGREE; ++i ) 156339640Smm#endif 157339640Smm { 158339640Smm#if defined(_OPENMP) 159339640Smm size_t i = omp_get_thread_num(); 160339640Smm#endif 161339640Smm size_t inlen__ = inlen; 162339640Smm const unsigned char *in__ = ( const unsigned char * )in; 163339640Smm in__ += i * BLAKE2S_BLOCKBYTES; 164339640Smm 165339640Smm while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES ) 166339640Smm { 167339640Smm blake2s_update( S->S[i], in__, BLAKE2S_BLOCKBYTES ); 168339640Smm in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; 169339640Smm inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; 170339640Smm } 171339640Smm } 172339640Smm 173339640Smm in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES ); 174339640Smm inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; 175339640Smm 176339640Smm if( inlen > 0 ) 177339640Smm memcpy( S->buf + left, in, inlen ); 178339640Smm 179339640Smm S->buflen = left + inlen; 180339640Smm return 0; 181339640Smm} 182339640Smm 183339640Smm 184339640Smmint blake2sp_final( blake2sp_state *S, void *out, size_t outlen ) 185339640Smm{ 186339640Smm uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES]; 187339640Smm size_t i; 188339640Smm 189339640Smm if(out == NULL || outlen < S->outlen) { 190339640Smm return -1; 191339640Smm } 192339640Smm 193339640Smm for( i = 0; i < PARALLELISM_DEGREE; ++i ) 194339640Smm { 195339640Smm if( S->buflen > i * BLAKE2S_BLOCKBYTES ) 196339640Smm { 197339640Smm size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES; 198339640Smm 199339640Smm if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES; 200339640Smm 201339640Smm blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left ); 202339640Smm } 203339640Smm 204339640Smm blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES ); 205339640Smm } 206339640Smm 207339640Smm for( i = 0; i < PARALLELISM_DEGREE; ++i ) 208339640Smm blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES ); 209339640Smm 210339640Smm return blake2s_final( S->R, out, S->outlen ); 211339640Smm} 212339640Smm 213339640Smm 214339640Smmint blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) 215339640Smm{ 216339640Smm uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES]; 217339640Smm blake2s_state S[PARALLELISM_DEGREE][1]; 218339640Smm blake2s_state FS[1]; 219339640Smm size_t i; 220339640Smm 221339640Smm /* Verify parameters */ 222339640Smm if ( NULL == in && inlen > 0 ) return -1; 223339640Smm 224339640Smm if ( NULL == out ) return -1; 225339640Smm 226339640Smm if ( NULL == key && keylen > 0) return -1; 227339640Smm 228339640Smm if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1; 229339640Smm 230339640Smm if( keylen > BLAKE2S_KEYBYTES ) return -1; 231339640Smm 232339640Smm for( i = 0; i < PARALLELISM_DEGREE; ++i ) 233346105Smm if( blake2sp_init_leaf( S[i], outlen, keylen, (uint32_t)i ) < 0 ) return -1; 234339640Smm 235339640Smm S[PARALLELISM_DEGREE - 1]->last_node = 1; /* mark last node */ 236339640Smm 237339640Smm if( keylen > 0 ) 238339640Smm { 239339640Smm uint8_t block[BLAKE2S_BLOCKBYTES]; 240339640Smm memset( block, 0, BLAKE2S_BLOCKBYTES ); 241339640Smm memcpy( block, key, keylen ); 242339640Smm 243339640Smm for( i = 0; i < PARALLELISM_DEGREE; ++i ) 244339640Smm blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES ); 245339640Smm 246339640Smm secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */ 247339640Smm } 248339640Smm 249339640Smm#if defined(_OPENMP) 250339640Smm #pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE) 251339640Smm#else 252339640Smm 253339640Smm for( i = 0; i < PARALLELISM_DEGREE; ++i ) 254339640Smm#endif 255339640Smm { 256339640Smm#if defined(_OPENMP) 257339640Smm size_t i = omp_get_thread_num(); 258339640Smm#endif 259339640Smm size_t inlen__ = inlen; 260339640Smm const unsigned char *in__ = ( const unsigned char * )in; 261339640Smm in__ += i * BLAKE2S_BLOCKBYTES; 262339640Smm 263339640Smm while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES ) 264339640Smm { 265339640Smm blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES ); 266339640Smm in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; 267339640Smm inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES; 268339640Smm } 269339640Smm 270339640Smm if( inlen__ > i * BLAKE2S_BLOCKBYTES ) 271339640Smm { 272339640Smm const size_t left = inlen__ - i * BLAKE2S_BLOCKBYTES; 273339640Smm const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES; 274339640Smm blake2s_update( S[i], in__, len ); 275339640Smm } 276339640Smm 277339640Smm blake2s_final( S[i], hash[i], BLAKE2S_OUTBYTES ); 278339640Smm } 279339640Smm 280339640Smm if( blake2sp_init_root( FS, outlen, keylen ) < 0 ) 281339640Smm return -1; 282339640Smm 283339640Smm FS->last_node = 1; 284339640Smm 285339640Smm for( i = 0; i < PARALLELISM_DEGREE; ++i ) 286339640Smm blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES ); 287339640Smm 288339640Smm return blake2s_final( FS, out, outlen ); 289339640Smm} 290339640Smm 291339640Smm 292339640Smm 293339640Smm#if defined(BLAKE2SP_SELFTEST) 294339640Smm#include <string.h> 295339640Smm#include "blake2-kat.h" 296339640Smmint main( void ) 297339640Smm{ 298339640Smm uint8_t key[BLAKE2S_KEYBYTES]; 299339640Smm uint8_t buf[BLAKE2_KAT_LENGTH]; 300339640Smm size_t i, step; 301339640Smm 302339640Smm for( i = 0; i < BLAKE2S_KEYBYTES; ++i ) 303339640Smm key[i] = ( uint8_t )i; 304339640Smm 305339640Smm for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) 306339640Smm buf[i] = ( uint8_t )i; 307339640Smm 308339640Smm /* Test simple API */ 309339640Smm for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) 310339640Smm { 311339640Smm uint8_t hash[BLAKE2S_OUTBYTES]; 312339640Smm blake2sp( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES ); 313339640Smm 314339640Smm if( 0 != memcmp( hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES ) ) 315339640Smm { 316339640Smm goto fail; 317339640Smm } 318339640Smm } 319339640Smm 320339640Smm /* Test streaming API */ 321339640Smm for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) { 322339640Smm for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) { 323339640Smm uint8_t hash[BLAKE2S_OUTBYTES]; 324339640Smm blake2sp_state S; 325339640Smm uint8_t * p = buf; 326339640Smm size_t mlen = i; 327339640Smm int err = 0; 328339640Smm 329339640Smm if( (err = blake2sp_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) { 330339640Smm goto fail; 331339640Smm } 332339640Smm 333339640Smm while (mlen >= step) { 334339640Smm if ( (err = blake2sp_update(&S, p, step)) < 0 ) { 335339640Smm goto fail; 336339640Smm } 337339640Smm mlen -= step; 338339640Smm p += step; 339339640Smm } 340339640Smm if ( (err = blake2sp_update(&S, p, mlen)) < 0) { 341339640Smm goto fail; 342339640Smm } 343339640Smm if ( (err = blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) { 344339640Smm goto fail; 345339640Smm } 346339640Smm 347339640Smm if (0 != memcmp(hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES)) { 348339640Smm goto fail; 349339640Smm } 350339640Smm } 351339640Smm } 352339640Smm 353339640Smm puts( "ok" ); 354339640Smm return 0; 355339640Smmfail: 356339640Smm puts("error"); 357339640Smm return -1; 358339640Smm} 359339640Smm#endif 360