Path: blob/master/Utilities/cmlibarchive/libarchive/archive_blake2sp_ref.c
3153 views
/*1BLAKE2 reference source code package - reference C implementations23Copyright 2012, Samuel Neves <[email protected]>. You may use this under the4terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at5your option. The terms of these licenses can be found at:67- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.08- OpenSSL license : https://www.openssl.org/source/license.html9- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.01011More information about the BLAKE2 hash function can be found at12https://blake2.net.13*/1415#include "archive_platform.h"1617#include <stdlib.h>18#include <string.h>19#include <stdio.h>2021#if defined(_OPENMP)22#include <omp.h>23#endif2425#include "archive_blake2.h"26#include "archive_blake2_impl.h"2728#define PARALLELISM_DEGREE 82930/* Remove system-defined preprocessor defintions that conflict with us. */31#undef FS3233/*34blake2sp_init_param defaults to setting the expecting output length35from the digest_length parameter block field.3637In some cases, however, we do not want this, as the output length38of these instances is given by inner_length instead.39*/40static int blake2sp_init_leaf_param( blake2s_state *S, const blake2s_param *P )41{42int err = blake2s_init_param(S, P);43S->outlen = P->inner_length;44return err;45}4647static int blake2sp_init_leaf( blake2s_state *S, size_t outlen, size_t keylen, uint32_t offset )48{49blake2s_param P[1];50P->digest_length = (uint8_t)outlen;51P->key_length = (uint8_t)keylen;52P->fanout = PARALLELISM_DEGREE;53P->depth = 2;54store32( &P->leaf_length, 0 );55store32( &P->node_offset, offset );56store16( &P->xof_length, 0 );57P->node_depth = 0;58P->inner_length = BLAKE2S_OUTBYTES;59memset( P->salt, 0, sizeof( P->salt ) );60memset( P->personal, 0, sizeof( P->personal ) );61return blake2sp_init_leaf_param( S, P );62}6364static int blake2sp_init_root( blake2s_state *S, size_t outlen, size_t keylen )65{66blake2s_param P[1];67P->digest_length = (uint8_t)outlen;68P->key_length = (uint8_t)keylen;69P->fanout = PARALLELISM_DEGREE;70P->depth = 2;71store32( &P->leaf_length, 0 );72store32( &P->node_offset, 0 );73store16( &P->xof_length, 0 );74P->node_depth = 1;75P->inner_length = BLAKE2S_OUTBYTES;76memset( P->salt, 0, sizeof( P->salt ) );77memset( P->personal, 0, sizeof( P->personal ) );78return blake2s_init_param( S, P );79}808182int blake2sp_init( blake2sp_state *S, size_t outlen )83{84size_t i;8586if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;8788memset( S->buf, 0, sizeof( S->buf ) );89S->buflen = 0;90S->outlen = outlen;9192if( blake2sp_init_root( S->R, outlen, 0 ) < 0 )93return -1;9495for( i = 0; i < PARALLELISM_DEGREE; ++i )96if( blake2sp_init_leaf( S->S[i], outlen, 0, (uint32_t)i ) < 0 ) return -1;9798S->R->last_node = 1;99S->S[PARALLELISM_DEGREE - 1]->last_node = 1;100return 0;101}102103int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen )104{105size_t i;106107if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;108109if( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;110111memset( S->buf, 0, sizeof( S->buf ) );112S->buflen = 0;113S->outlen = outlen;114115if( blake2sp_init_root( S->R, outlen, keylen ) < 0 )116return -1;117118for( i = 0; i < PARALLELISM_DEGREE; ++i )119if( blake2sp_init_leaf( S->S[i], outlen, keylen, (uint32_t)i ) < 0 ) return -1;120121S->R->last_node = 1;122S->S[PARALLELISM_DEGREE - 1]->last_node = 1;123{124uint8_t block[BLAKE2S_BLOCKBYTES];125memset( block, 0, BLAKE2S_BLOCKBYTES );126memcpy( block, key, keylen );127128for( i = 0; i < PARALLELISM_DEGREE; ++i )129blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES );130131secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */132}133return 0;134}135136137int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )138{139const unsigned char * in = (const unsigned char *)pin;140size_t left = S->buflen;141size_t fill = sizeof( S->buf ) - left;142size_t i;143144if( left && inlen >= fill )145{146memcpy( S->buf + left, in, fill );147148for( i = 0; i < PARALLELISM_DEGREE; ++i )149blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );150151in += fill;152inlen -= fill;153left = 0;154}155156#if defined(_OPENMP)157#pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE)158#else159for( i = 0; i < PARALLELISM_DEGREE; ++i )160#endif161{162#if defined(_OPENMP)163size_t i = omp_get_thread_num();164#endif165size_t inlen__ = inlen;166const unsigned char *in__ = ( const unsigned char * )in;167in__ += i * BLAKE2S_BLOCKBYTES;168169while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )170{171blake2s_update( S->S[i], in__, BLAKE2S_BLOCKBYTES );172in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;173inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;174}175}176177in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );178inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;179180if( inlen > 0 )181memcpy( S->buf + left, in, inlen );182183S->buflen = left + inlen;184return 0;185}186187188int blake2sp_final( blake2sp_state *S, void *out, size_t outlen )189{190uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];191size_t i;192193if(out == NULL || outlen < S->outlen) {194return -1;195}196197for( i = 0; i < PARALLELISM_DEGREE; ++i )198{199if( S->buflen > i * BLAKE2S_BLOCKBYTES )200{201size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES;202203if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;204205blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );206}207208blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES );209}210211for( i = 0; i < PARALLELISM_DEGREE; ++i )212blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES );213214return blake2s_final( S->R, out, S->outlen );215}216217218int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )219{220uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];221blake2s_state S[PARALLELISM_DEGREE][1];222blake2s_state FS[1];223size_t i;224225/* Verify parameters */226if ( NULL == in && inlen > 0 ) return -1;227228if ( NULL == out ) return -1;229230if ( NULL == key && keylen > 0) return -1;231232if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;233234if( keylen > BLAKE2S_KEYBYTES ) return -1;235236for( i = 0; i < PARALLELISM_DEGREE; ++i )237if( blake2sp_init_leaf( S[i], outlen, keylen, (uint32_t)i ) < 0 ) return -1;238239S[PARALLELISM_DEGREE - 1]->last_node = 1; /* mark last node */240241if( keylen > 0 )242{243uint8_t block[BLAKE2S_BLOCKBYTES];244memset( block, 0, BLAKE2S_BLOCKBYTES );245memcpy( block, key, keylen );246247for( i = 0; i < PARALLELISM_DEGREE; ++i )248blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES );249250secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */251}252253#if defined(_OPENMP)254#pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE)255#else256257for( i = 0; i < PARALLELISM_DEGREE; ++i )258#endif259{260#if defined(_OPENMP)261size_t i = omp_get_thread_num();262#endif263size_t inlen__ = inlen;264const unsigned char *in__ = ( const unsigned char * )in;265in__ += i * BLAKE2S_BLOCKBYTES;266267while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )268{269blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES );270in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;271inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;272}273274if( inlen__ > i * BLAKE2S_BLOCKBYTES )275{276const size_t left = inlen__ - i * BLAKE2S_BLOCKBYTES;277const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES;278blake2s_update( S[i], in__, len );279}280281blake2s_final( S[i], hash[i], BLAKE2S_OUTBYTES );282}283284if( blake2sp_init_root( FS, outlen, keylen ) < 0 )285return -1;286287FS->last_node = 1;288289for( i = 0; i < PARALLELISM_DEGREE; ++i )290blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES );291292return blake2s_final( FS, out, outlen );293}294295296297#if defined(BLAKE2SP_SELFTEST)298#include <string.h>299#include "blake2-kat.h"300int main( void )301{302uint8_t key[BLAKE2S_KEYBYTES];303uint8_t buf[BLAKE2_KAT_LENGTH];304size_t i, step;305306for( i = 0; i < BLAKE2S_KEYBYTES; ++i )307key[i] = ( uint8_t )i;308309for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )310buf[i] = ( uint8_t )i;311312/* Test simple API */313for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )314{315uint8_t hash[BLAKE2S_OUTBYTES];316blake2sp( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );317318if( 0 != memcmp( hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES ) )319{320goto fail;321}322}323324/* Test streaming API */325for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {326for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {327uint8_t hash[BLAKE2S_OUTBYTES];328blake2sp_state S;329uint8_t * p = buf;330size_t mlen = i;331int err = 0;332333if( (err = blake2sp_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {334goto fail;335}336337while (mlen >= step) {338if ( (err = blake2sp_update(&S, p, step)) < 0 ) {339goto fail;340}341mlen -= step;342p += step;343}344if ( (err = blake2sp_update(&S, p, mlen)) < 0) {345goto fail;346}347if ( (err = blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {348goto fail;349}350351if (0 != memcmp(hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES)) {352goto fail;353}354}355}356357puts( "ok" );358return 0;359fail:360puts("error");361return -1;362}363#endif364365366