Path: blob/master/Utilities/cmlibarchive/libarchive/archive_blake2s_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 <stdint.h>18#include <string.h>19#include <stdio.h>2021#include "archive_blake2.h"22#include "archive_blake2_impl.h"2324static const uint32_t blake2s_IV[8] =25{260x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,270x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL28};2930static const uint8_t blake2s_sigma[10][16] =31{32{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,33{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,34{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,35{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,36{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,37{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,38{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,39{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,40{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,41{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,42};4344static void blake2s_set_lastnode( blake2s_state *S )45{46S->f[1] = (uint32_t)-1;47}4849/* Some helper functions, not necessarily useful */50static int blake2s_is_lastblock( const blake2s_state *S )51{52return S->f[0] != 0;53}5455static void blake2s_set_lastblock( blake2s_state *S )56{57if( S->last_node ) blake2s_set_lastnode( S );5859S->f[0] = (uint32_t)-1;60}6162static void blake2s_increment_counter( blake2s_state *S, const uint32_t inc )63{64S->t[0] += inc;65S->t[1] += ( S->t[0] < inc );66}6768static void blake2s_init0( blake2s_state *S )69{70size_t i;71memset( S, 0, sizeof( blake2s_state ) );7273for( i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i];74}7576/* init2 xors IV with input parameter block */77int blake2s_init_param( blake2s_state *S, const blake2s_param *P )78{79const unsigned char *p = ( const unsigned char * )( P );80size_t i;8182blake2s_init0( S );8384/* IV XOR ParamBlock */85for( i = 0; i < 8; ++i )86S->h[i] ^= load32( &p[i * 4] );8788S->outlen = P->digest_length;89return 0;90}919293/* Sequential blake2s initialization */94int blake2s_init( blake2s_state *S, size_t outlen )95{96blake2s_param P[1];9798/* Move interval verification here? */99if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;100101P->digest_length = (uint8_t)outlen;102P->key_length = 0;103P->fanout = 1;104P->depth = 1;105store32( &P->leaf_length, 0 );106store32( &P->node_offset, 0 );107store16( &P->xof_length, 0 );108P->node_depth = 0;109P->inner_length = 0;110/* memset(P->reserved, 0, sizeof(P->reserved) ); */111memset( P->salt, 0, sizeof( P->salt ) );112memset( P->personal, 0, sizeof( P->personal ) );113return blake2s_init_param( S, P );114}115116int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen )117{118blake2s_param P[1];119120if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;121122if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;123124P->digest_length = (uint8_t)outlen;125P->key_length = (uint8_t)keylen;126P->fanout = 1;127P->depth = 1;128store32( &P->leaf_length, 0 );129store32( &P->node_offset, 0 );130store16( &P->xof_length, 0 );131P->node_depth = 0;132P->inner_length = 0;133/* memset(P->reserved, 0, sizeof(P->reserved) ); */134memset( P->salt, 0, sizeof( P->salt ) );135memset( P->personal, 0, sizeof( P->personal ) );136137if( blake2s_init_param( S, P ) < 0 ) return -1;138139{140uint8_t block[BLAKE2S_BLOCKBYTES];141memset( block, 0, BLAKE2S_BLOCKBYTES );142memcpy( block, key, keylen );143blake2s_update( S, block, BLAKE2S_BLOCKBYTES );144secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */145}146return 0;147}148149#define G(r,i,a,b,c,d) \150do { \151a = a + b + m[blake2s_sigma[r][2*i+0]]; \152d = rotr32(d ^ a, 16); \153c = c + d; \154b = rotr32(b ^ c, 12); \155a = a + b + m[blake2s_sigma[r][2*i+1]]; \156d = rotr32(d ^ a, 8); \157c = c + d; \158b = rotr32(b ^ c, 7); \159} while(0)160161#define ROUND(r) \162do { \163G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \164G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \165G(r,2,v[ 2],v[ 6],v[10],v[14]); \166G(r,3,v[ 3],v[ 7],v[11],v[15]); \167G(r,4,v[ 0],v[ 5],v[10],v[15]); \168G(r,5,v[ 1],v[ 6],v[11],v[12]); \169G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \170G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \171} while(0)172173static void blake2s_compress( blake2s_state *S, const uint8_t in[BLAKE2S_BLOCKBYTES] )174{175uint32_t m[16];176uint32_t v[16];177size_t i;178179for( i = 0; i < 16; ++i ) {180m[i] = load32( in + i * sizeof( m[i] ) );181}182183for( i = 0; i < 8; ++i ) {184v[i] = S->h[i];185}186187v[ 8] = blake2s_IV[0];188v[ 9] = blake2s_IV[1];189v[10] = blake2s_IV[2];190v[11] = blake2s_IV[3];191v[12] = S->t[0] ^ blake2s_IV[4];192v[13] = S->t[1] ^ blake2s_IV[5];193v[14] = S->f[0] ^ blake2s_IV[6];194v[15] = S->f[1] ^ blake2s_IV[7];195196ROUND( 0 );197ROUND( 1 );198ROUND( 2 );199ROUND( 3 );200ROUND( 4 );201ROUND( 5 );202ROUND( 6 );203ROUND( 7 );204ROUND( 8 );205ROUND( 9 );206207for( i = 0; i < 8; ++i ) {208S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];209}210}211212#undef G213#undef ROUND214215int blake2s_update( blake2s_state *S, const void *pin, size_t inlen )216{217const unsigned char * in = (const unsigned char *)pin;218if( inlen > 0 )219{220size_t left = S->buflen;221size_t fill = BLAKE2S_BLOCKBYTES - left;222if( inlen > fill )223{224S->buflen = 0;225memcpy( S->buf + left, in, fill ); /* Fill buffer */226blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );227blake2s_compress( S, S->buf ); /* Compress */228in += fill; inlen -= fill;229while(inlen > BLAKE2S_BLOCKBYTES) {230blake2s_increment_counter(S, BLAKE2S_BLOCKBYTES);231blake2s_compress( S, in );232in += BLAKE2S_BLOCKBYTES;233inlen -= BLAKE2S_BLOCKBYTES;234}235}236memcpy( S->buf + S->buflen, in, inlen );237S->buflen += inlen;238}239return 0;240}241242int blake2s_final( blake2s_state *S, void *out, size_t outlen )243{244uint8_t buffer[BLAKE2S_OUTBYTES] = {0};245size_t i;246247if( out == NULL || outlen < S->outlen )248return -1;249250if( blake2s_is_lastblock( S ) )251return -1;252253blake2s_increment_counter( S, ( uint32_t )S->buflen );254blake2s_set_lastblock( S );255memset( S->buf + S->buflen, 0, BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */256blake2s_compress( S, S->buf );257258for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */259store32( buffer + sizeof( S->h[i] ) * i, S->h[i] );260261memcpy( out, buffer, outlen );262secure_zero_memory(buffer, sizeof(buffer));263return 0;264}265266int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )267{268blake2s_state S[1];269270/* Verify parameters */271if ( NULL == in && inlen > 0 ) return -1;272273if ( NULL == out ) return -1;274275if ( NULL == key && keylen > 0) return -1;276277if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;278279if( keylen > BLAKE2S_KEYBYTES ) return -1;280281if( keylen > 0 )282{283if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1;284}285else286{287if( blake2s_init( S, outlen ) < 0 ) return -1;288}289290blake2s_update( S, ( const uint8_t * )in, inlen );291blake2s_final( S, out, outlen );292return 0;293}294295#if defined(SUPERCOP)296int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )297{298return blake2s( out, BLAKE2S_OUTBYTES, in, inlen, NULL, 0 );299}300#endif301302#if defined(BLAKE2S_SELFTEST)303#include <string.h>304#include "blake2-kat.h"305int main( void )306{307uint8_t key[BLAKE2S_KEYBYTES];308uint8_t buf[BLAKE2_KAT_LENGTH];309size_t i, step;310311for( i = 0; i < BLAKE2S_KEYBYTES; ++i )312key[i] = ( uint8_t )i;313314for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )315buf[i] = ( uint8_t )i;316317/* Test simple API */318for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )319{320uint8_t hash[BLAKE2S_OUTBYTES];321blake2s( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );322323if( 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) )324{325goto fail;326}327}328329/* Test streaming API */330for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {331for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {332uint8_t hash[BLAKE2S_OUTBYTES];333blake2s_state S;334uint8_t * p = buf;335size_t mlen = i;336int err = 0;337338if( (err = blake2s_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {339goto fail;340}341342while (mlen >= step) {343if ( (err = blake2s_update(&S, p, step)) < 0 ) {344goto fail;345}346mlen -= step;347p += step;348}349if ( (err = blake2s_update(&S, p, mlen)) < 0) {350goto fail;351}352if ( (err = blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {353goto fail;354}355356if (0 != memcmp(hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES)) {357goto fail;358}359}360}361362puts( "ok" );363return 0;364fail:365puts("error");366return -1;367}368#endif369370371