URI: 
       tblake2bp-ref.c - dedup - data deduplication program
  HTML git clone git://bitreich.org/dedup/ git://hg6vgqziawt5s4dj.onion/dedup/
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR README
   DIR LICENSE
       ---
       tblake2bp-ref.c (9429B)
       ---
            1 /*
            2    BLAKE2 reference source code package - reference C implementations
            3 
            4    Copyright 2012, Samuel Neves <sneves@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 <stdio.h>
           17 #include <stdlib.h>
           18 #include <string.h>
           19 #include <stdint.h>
           20 
           21 #if defined(_OPENMP)
           22 #include <omp.h>
           23 #endif
           24 
           25 #include "blake2.h"
           26 #include "blake2-impl.h"
           27 
           28 #define PARALLELISM_DEGREE 4
           29 
           30 /*
           31   blake2b_init_param defaults to setting the expecting output length
           32   from the digest_length parameter block field.
           33 
           34   In some cases, however, we do not want this, as the output length
           35   of these instances is given by inner_length instead.
           36 */
           37 static int blake2bp_init_leaf_param( blake2b_state *S, const blake2b_param *P )
           38 {
           39   int err = blake2b_init_param(S, P);
           40   S->outlen = P->inner_length;
           41   return err;
           42 }
           43 
           44 static int blake2bp_init_leaf( blake2b_state *S, size_t outlen, size_t keylen, uint64_t offset )
           45 {
           46   blake2b_param P[1];
           47   P->digest_length = (uint8_t)outlen;
           48   P->key_length = (uint8_t)keylen;
           49   P->fanout = PARALLELISM_DEGREE;
           50   P->depth = 2;
           51   store32( &P->leaf_length, 0 );
           52   store32( &P->node_offset, offset );
           53   store32( &P->xof_length, 0 );
           54   P->node_depth = 0;
           55   P->inner_length = BLAKE2B_OUTBYTES;
           56   memset( P->reserved, 0, sizeof( P->reserved ) );
           57   memset( P->salt, 0, sizeof( P->salt ) );
           58   memset( P->personal, 0, sizeof( P->personal ) );
           59   return blake2bp_init_leaf_param( S, P );
           60 }
           61 
           62 static int blake2bp_init_root( blake2b_state *S, size_t outlen, size_t keylen )
           63 {
           64   blake2b_param P[1];
           65   P->digest_length = (uint8_t)outlen;
           66   P->key_length = (uint8_t)keylen;
           67   P->fanout = PARALLELISM_DEGREE;
           68   P->depth = 2;
           69   store32( &P->leaf_length, 0 );
           70   store32( &P->node_offset, 0 );
           71   store32( &P->xof_length, 0 );
           72   P->node_depth = 1;
           73   P->inner_length = BLAKE2B_OUTBYTES;
           74   memset( P->reserved, 0, sizeof( P->reserved ) );
           75   memset( P->salt, 0, sizeof( P->salt ) );
           76   memset( P->personal, 0, sizeof( P->personal ) );
           77   return blake2b_init_param( S, P );
           78 }
           79 
           80 
           81 int blake2bp_init( blake2bp_state *S, size_t outlen )
           82 {
           83   size_t i;
           84 
           85   if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
           86 
           87   memset( S->buf, 0, sizeof( S->buf ) );
           88   S->buflen = 0;
           89   S->outlen = outlen;
           90 
           91   if( blake2bp_init_root( S->R, outlen, 0 ) < 0 )
           92     return -1;
           93 
           94   for( i = 0; i < PARALLELISM_DEGREE; ++i )
           95     if( blake2bp_init_leaf( S->S[i], outlen, 0, i ) < 0 ) return -1;
           96 
           97   S->R->last_node = 1;
           98   S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
           99   return 0;
          100 }
          101 
          102 int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen )
          103 {
          104   size_t i;
          105 
          106   if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
          107 
          108   if( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
          109 
          110   memset( S->buf, 0, sizeof( S->buf ) );
          111   S->buflen = 0;
          112   S->outlen = outlen;
          113 
          114   if( blake2bp_init_root( S->R, outlen, keylen ) < 0 )
          115     return -1;
          116 
          117   for( i = 0; i < PARALLELISM_DEGREE; ++i )
          118     if( blake2bp_init_leaf( S->S[i], outlen, keylen, i ) < 0 ) return -1;
          119 
          120   S->R->last_node = 1;
          121   S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
          122   {
          123     uint8_t block[BLAKE2B_BLOCKBYTES];
          124     memset( block, 0, BLAKE2B_BLOCKBYTES );
          125     memcpy( block, key, keylen );
          126 
          127     for( i = 0; i < PARALLELISM_DEGREE; ++i )
          128       blake2b_update( S->S[i], block, BLAKE2B_BLOCKBYTES );
          129 
          130     secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
          131   }
          132   return 0;
          133 }
          134 
          135 
          136 int blake2bp_update( blake2bp_state *S, const void *pin, size_t inlen )
          137 {
          138   const unsigned char * in = (const unsigned char *)pin;
          139   size_t left = S->buflen;
          140   size_t fill = sizeof( S->buf ) - left;
          141   size_t i;
          142 
          143   if( left && inlen >= fill )
          144   {
          145     memcpy( S->buf + left, in, fill );
          146 
          147     for( i = 0; i < PARALLELISM_DEGREE; ++i )
          148       blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES );
          149 
          150     in += fill;
          151     inlen -= fill;
          152     left = 0;
          153   }
          154 
          155 #if defined(_OPENMP)
          156   #pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE)
          157 #else
          158 
          159   for( i = 0; i < PARALLELISM_DEGREE; ++i )
          160 #endif
          161   {
          162 #if defined(_OPENMP)
          163     size_t      i = omp_get_thread_num();
          164 #endif
          165     size_t inlen__ = inlen;
          166     const unsigned char *in__ = ( const unsigned char * )in;
          167     in__ += i * BLAKE2B_BLOCKBYTES;
          168 
          169     while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES )
          170     {
          171       blake2b_update( S->S[i], in__, BLAKE2B_BLOCKBYTES );
          172       in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
          173       inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
          174     }
          175   }
          176 
          177   in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES );
          178   inlen %= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
          179 
          180   if( inlen > 0 )
          181     memcpy( S->buf + left, in, inlen );
          182 
          183   S->buflen = left + inlen;
          184   return 0;
          185 }
          186 
          187 int blake2bp_final( blake2bp_state *S, void *out, size_t outlen )
          188 {
          189   uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES];
          190   size_t i;
          191 
          192   if(out == NULL || outlen < S->outlen) {
          193     return -1;
          194   }
          195 
          196   for( i = 0; i < PARALLELISM_DEGREE; ++i )
          197   {
          198     if( S->buflen > i * BLAKE2B_BLOCKBYTES )
          199     {
          200       size_t left = S->buflen - i * BLAKE2B_BLOCKBYTES;
          201 
          202       if( left > BLAKE2B_BLOCKBYTES ) left = BLAKE2B_BLOCKBYTES;
          203 
          204       blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, left );
          205     }
          206 
          207     blake2b_final( S->S[i], hash[i], BLAKE2B_OUTBYTES );
          208   }
          209 
          210   for( i = 0; i < PARALLELISM_DEGREE; ++i )
          211     blake2b_update( S->R, hash[i], BLAKE2B_OUTBYTES );
          212 
          213   return blake2b_final( S->R, out, S->outlen );
          214 }
          215 
          216 int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
          217 {
          218   uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES];
          219   blake2b_state S[PARALLELISM_DEGREE][1];
          220   blake2b_state FS[1];
          221   size_t i;
          222 
          223   /* Verify parameters */
          224   if ( NULL == in && inlen > 0 ) return -1;
          225 
          226   if ( NULL == out ) return -1;
          227 
          228   if( NULL == key && keylen > 0 ) return -1;
          229 
          230   if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
          231 
          232   if( keylen > BLAKE2B_KEYBYTES ) return -1;
          233 
          234   for( i = 0; i < PARALLELISM_DEGREE; ++i )
          235     if( blake2bp_init_leaf( S[i], outlen, keylen, i ) < 0 ) return -1;
          236 
          237   S[PARALLELISM_DEGREE - 1]->last_node = 1; /* mark last node */
          238 
          239   if( keylen > 0 )
          240   {
          241     uint8_t block[BLAKE2B_BLOCKBYTES];
          242     memset( block, 0, BLAKE2B_BLOCKBYTES );
          243     memcpy( block, key, keylen );
          244 
          245     for( i = 0; i < PARALLELISM_DEGREE; ++i )
          246       blake2b_update( S[i], block, BLAKE2B_BLOCKBYTES );
          247 
          248     secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
          249   }
          250 
          251 #if defined(_OPENMP)
          252   #pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE)
          253 #else
          254 
          255   for( i = 0; i < PARALLELISM_DEGREE; ++i )
          256 #endif
          257   {
          258 #if defined(_OPENMP)
          259     size_t      i = omp_get_thread_num();
          260 #endif
          261     size_t inlen__ = inlen;
          262     const unsigned char *in__ = ( const unsigned char * )in;
          263     in__ += i * BLAKE2B_BLOCKBYTES;
          264 
          265     while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES )
          266     {
          267       blake2b_update( S[i], in__, BLAKE2B_BLOCKBYTES );
          268       in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
          269       inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
          270     }
          271 
          272     if( inlen__ > i * BLAKE2B_BLOCKBYTES )
          273     {
          274       const size_t left = inlen__ - i * BLAKE2B_BLOCKBYTES;
          275       const size_t len = left <= BLAKE2B_BLOCKBYTES ? left : BLAKE2B_BLOCKBYTES;
          276       blake2b_update( S[i], in__, len );
          277     }
          278 
          279     blake2b_final( S[i], hash[i], BLAKE2B_OUTBYTES );
          280   }
          281 
          282   if( blake2bp_init_root( FS, outlen, keylen ) < 0 )
          283     return -1;
          284 
          285   FS->last_node = 1; /* Mark as last node */
          286 
          287   for( i = 0; i < PARALLELISM_DEGREE; ++i )
          288     blake2b_update( FS, hash[i], BLAKE2B_OUTBYTES );
          289 
          290   return blake2b_final( FS, out, outlen );;
          291 }
          292 
          293 #if defined(BLAKE2BP_SELFTEST)
          294 #include <string.h>
          295 #include "blake2-kat.h"
          296 int main( void )
          297 {
          298   uint8_t key[BLAKE2B_KEYBYTES];
          299   uint8_t buf[BLAKE2_KAT_LENGTH];
          300   size_t i, step;
          301 
          302   for( i = 0; i < BLAKE2B_KEYBYTES; ++i )
          303     key[i] = ( uint8_t )i;
          304 
          305   for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
          306     buf[i] = ( uint8_t )i;
          307 
          308   /* Test simple API */
          309   for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
          310   {
          311     uint8_t hash[BLAKE2B_OUTBYTES];
          312     blake2bp( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );
          313 
          314     if( 0 != memcmp( hash, blake2bp_keyed_kat[i], BLAKE2B_OUTBYTES ) )
          315     {
          316       goto fail;
          317     }
          318   }
          319 
          320   /* Test streaming API */
          321   for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {
          322     for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
          323       uint8_t hash[BLAKE2B_OUTBYTES];
          324       blake2bp_state S;
          325       uint8_t * p = buf;
          326       size_t mlen = i;
          327       int err = 0;
          328 
          329       if( (err = blake2bp_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
          330         goto fail;
          331       }
          332 
          333       while (mlen >= step) {
          334         if ( (err = blake2bp_update(&S, p, step)) < 0 ) {
          335           goto fail;
          336         }
          337         mlen -= step;
          338         p += step;
          339       }
          340       if ( (err = blake2bp_update(&S, p, mlen)) < 0) {
          341         goto fail;
          342       }
          343       if ( (err = blake2bp_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
          344         goto fail;
          345       }
          346 
          347       if (0 != memcmp(hash, blake2bp_keyed_kat[i], BLAKE2B_OUTBYTES)) {
          348         goto fail;
          349       }
          350     }
          351   }
          352 
          353   puts( "ok" );
          354   return 0;
          355 fail:
          356   puts("error");
          357   return -1;
          358 }
          359 #endif