Blame cbits/blake2/sse/blake2sp.c

Packit 141393
/*
Packit 141393
   BLAKE2 reference source code package - optimized C implementations
Packit 141393
Packit 141393
   Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the
Packit 141393
   terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
Packit 141393
   your option.  The terms of these licenses can be found at:
Packit 141393
Packit 141393
   - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
Packit 141393
   - OpenSSL license   : https://www.openssl.org/source/license.html
Packit 141393
   - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
Packit 141393
Packit 141393
   More information about the BLAKE2 hash function can be found at
Packit 141393
   https://blake2.net.
Packit 141393
*/
Packit 141393
Packit 141393
#include <stdlib.h>
Packit 141393
#include <string.h>
Packit 141393
#include <stdio.h>
Packit 141393
Packit 141393
#if defined(_OPENMP)
Packit 141393
#include <omp.h>
Packit 141393
#endif
Packit 141393
Packit 141393
#include "blake2.h"
Packit 141393
#include "blake2-impl.h"
Packit 141393
Packit 141393
#define PARALLELISM_DEGREE 8
Packit 141393
Packit 141393
/*
Packit 141393
  blake2sp_init_param defaults to setting the expecting output length
Packit 141393
  from the digest_length parameter block field.
Packit 141393
Packit 141393
  In some cases, however, we do not want this, as the output length
Packit 141393
  of these instances is given by inner_length instead.
Packit 141393
*/
Packit 141393
static int blake2sp_init_leaf_param( blake2s_state *S, const blake2s_param *P )
Packit 141393
{
Packit 141393
  int err = blake2s_init_param(S, P);
Packit 141393
  S->outlen = P->inner_length;
Packit 141393
  return err;
Packit 141393
}
Packit 141393
Packit 141393
static int blake2sp_init_leaf( blake2s_state *S, size_t outlen, size_t keylen, uint64_t offset )
Packit 141393
{
Packit 141393
  blake2s_param P[1];
Packit 141393
  P->digest_length = (uint8_t)outlen;
Packit 141393
  P->key_length = (uint8_t)keylen;
Packit 141393
  P->fanout = PARALLELISM_DEGREE;
Packit 141393
  P->depth = 2;
Packit 141393
  P->leaf_length = 0;
Packit 141393
  P->node_offset = offset;
Packit 141393
  P->xof_length = 0;
Packit 141393
  P->node_depth = 0;
Packit 141393
  P->inner_length = BLAKE2S_OUTBYTES;
Packit 141393
  memset( P->salt, 0, sizeof( P->salt ) );
Packit 141393
  memset( P->personal, 0, sizeof( P->personal ) );
Packit 141393
  return blake2sp_init_leaf_param( S, P );
Packit 141393
}
Packit 141393
Packit 141393
static int blake2sp_init_root( blake2s_state *S, size_t outlen, size_t keylen )
Packit 141393
{
Packit 141393
  blake2s_param P[1];
Packit 141393
  P->digest_length = (uint8_t)outlen;
Packit 141393
  P->key_length = (uint8_t)keylen;
Packit 141393
  P->fanout = PARALLELISM_DEGREE;
Packit 141393
  P->depth = 2;
Packit 141393
  P->leaf_length = 0;
Packit 141393
  P->node_offset = 0;
Packit 141393
  P->xof_length = 0;
Packit 141393
  P->node_depth = 1;
Packit 141393
  P->inner_length = BLAKE2S_OUTBYTES;
Packit 141393
  memset( P->salt, 0, sizeof( P->salt ) );
Packit 141393
  memset( P->personal, 0, sizeof( P->personal ) );
Packit 141393
  return blake2s_init_param( S, P );
Packit 141393
}
Packit 141393
Packit 141393
Packit 141393
int blake2sp_init( blake2sp_state *S, size_t outlen )
Packit 141393
{
Packit 141393
  size_t i;
Packit 141393
Packit 141393
  if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
Packit 141393
Packit 141393
  memset( S->buf, 0, sizeof( S->buf ) );
Packit 141393
  S->buflen = 0;
Packit 141393
  S->outlen = outlen;
Packit 141393
Packit 141393
  if( blake2sp_init_root( S->R, outlen, 0 ) < 0 )
Packit 141393
    return -1;
Packit 141393
Packit 141393
  for( i = 0; i < PARALLELISM_DEGREE; ++i )
Packit 141393
    if( blake2sp_init_leaf( S->S[i], outlen, 0, i ) < 0 ) return -1;
Packit 141393
Packit 141393
  S->R->last_node = 1;
Packit 141393
  S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
Packit 141393
  return 0;
Packit 141393
}
Packit 141393
Packit 141393
int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen )
Packit 141393
{
Packit 141393
  size_t i;
Packit 141393
Packit 141393
  if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
Packit 141393
Packit 141393
  if( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
Packit 141393
Packit 141393
  memset( S->buf, 0, sizeof( S->buf ) );
Packit 141393
  S->buflen = 0;
Packit 141393
  S->outlen = outlen;
Packit 141393
Packit 141393
  if( blake2sp_init_root( S->R, outlen, keylen ) < 0 )
Packit 141393
    return -1;
Packit 141393
Packit 141393
  for( i = 0; i < PARALLELISM_DEGREE; ++i )
Packit 141393
    if( blake2sp_init_leaf( S->S[i], outlen, keylen, i ) < 0 ) return -1;
Packit 141393
Packit 141393
  S->R->last_node = 1;
Packit 141393
  S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
Packit 141393
  {
Packit 141393
    uint8_t block[BLAKE2S_BLOCKBYTES];
Packit 141393
    memset( block, 0, BLAKE2S_BLOCKBYTES );
Packit 141393
    memcpy( block, key, keylen );
Packit 141393
Packit 141393
    for( i = 0; i < PARALLELISM_DEGREE; ++i )
Packit 141393
      blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES );
Packit 141393
Packit 141393
    secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
Packit 141393
  }
Packit 141393
  return 0;
Packit 141393
}
Packit 141393
Packit 141393
Packit 141393
int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
Packit 141393
{
Packit 141393
  const unsigned char * in = (const unsigned char *)pin;
Packit 141393
  size_t left = S->buflen;
Packit 141393
  size_t fill = sizeof( S->buf ) - left;
Packit 141393
  size_t i;
Packit 141393
Packit 141393
  if( left && inlen >= fill )
Packit 141393
  {
Packit 141393
    memcpy( S->buf + left, in, fill );
Packit 141393
Packit 141393
    for( i = 0; i < PARALLELISM_DEGREE; ++i )
Packit 141393
      blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
Packit 141393
Packit 141393
    in += fill;
Packit 141393
    inlen -= fill;
Packit 141393
    left = 0;
Packit 141393
  }
Packit 141393
Packit 141393
#if defined(_OPENMP)
Packit 141393
  #pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE)
Packit 141393
#else
Packit 141393
Packit 141393
  for( i = 0; i < PARALLELISM_DEGREE; ++i )
Packit 141393
#endif
Packit 141393
  {
Packit 141393
#if defined(_OPENMP)
Packit 141393
    size_t      i = omp_get_thread_num();
Packit 141393
#endif
Packit 141393
    size_t inlen__ = inlen;
Packit 141393
    const unsigned char *in__ = ( const unsigned char * )in;
Packit 141393
    in__ += i * BLAKE2S_BLOCKBYTES;
Packit 141393
Packit 141393
    while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
Packit 141393
    {
Packit 141393
      blake2s_update( S->S[i], in__, BLAKE2S_BLOCKBYTES );
Packit 141393
      in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
Packit 141393
      inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
Packit 141393
    }
Packit 141393
  }
Packit 141393
Packit 141393
  in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
Packit 141393
  inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
Packit 141393
Packit 141393
  if( inlen > 0 )
Packit 141393
    memcpy( S->buf + left, in, inlen );
Packit 141393
Packit 141393
  S->buflen = left + inlen;
Packit 141393
  return 0;
Packit 141393
}
Packit 141393
Packit 141393
Packit 141393
int blake2sp_final( blake2sp_state *S, void *out, size_t outlen )
Packit 141393
{
Packit 141393
  uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
Packit 141393
  size_t i;
Packit 141393
Packit 141393
  if(out == NULL || outlen < S->outlen) {
Packit 141393
    return -1;
Packit 141393
  }
Packit 141393
Packit 141393
  for( i = 0; i < PARALLELISM_DEGREE; ++i )
Packit 141393
  {
Packit 141393
    if( S->buflen > i * BLAKE2S_BLOCKBYTES )
Packit 141393
    {
Packit 141393
      size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES;
Packit 141393
Packit 141393
      if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
Packit 141393
Packit 141393
      blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
Packit 141393
    }
Packit 141393
Packit 141393
    blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES );
Packit 141393
  }
Packit 141393
Packit 141393
  for( i = 0; i < PARALLELISM_DEGREE; ++i )
Packit 141393
    blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES );
Packit 141393
Packit 141393
  return blake2s_final( S->R, out, S->outlen );
Packit 141393
}
Packit 141393
Packit 141393
Packit 141393
int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
Packit 141393
{
Packit 141393
  uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
Packit 141393
  blake2s_state S[PARALLELISM_DEGREE][1];
Packit 141393
  blake2s_state FS[1];
Packit 141393
  size_t i;
Packit 141393
Packit 141393
  /* Verify parameters */
Packit 141393
  if ( NULL == in && inlen > 0 ) return -1;
Packit 141393
Packit 141393
  if ( NULL == out ) return -1;
Packit 141393
Packit 141393
  if ( NULL == key && keylen > 0) return -1;
Packit 141393
Packit 141393
  if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
Packit 141393
Packit 141393
  if( keylen > BLAKE2S_KEYBYTES ) return -1;
Packit 141393
Packit 141393
  for( i = 0; i < PARALLELISM_DEGREE; ++i )
Packit 141393
    if( blake2sp_init_leaf( S[i], outlen, keylen, i ) < 0 ) return -1;
Packit 141393
Packit 141393
  S[PARALLELISM_DEGREE - 1]->last_node = 1; /* mark last node */
Packit 141393
Packit 141393
  if( keylen > 0 )
Packit 141393
  {
Packit 141393
    uint8_t block[BLAKE2S_BLOCKBYTES];
Packit 141393
    memset( block, 0, BLAKE2S_BLOCKBYTES );
Packit 141393
    memcpy( block, key, keylen );
Packit 141393
Packit 141393
    for( i = 0; i < PARALLELISM_DEGREE; ++i )
Packit 141393
      blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES );
Packit 141393
Packit 141393
    secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
Packit 141393
  }
Packit 141393
Packit 141393
#if defined(_OPENMP)
Packit 141393
  #pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE)
Packit 141393
#else
Packit 141393
Packit 141393
  for( i = 0; i < PARALLELISM_DEGREE; ++i )
Packit 141393
#endif
Packit 141393
  {
Packit 141393
#if defined(_OPENMP)
Packit 141393
    size_t      i = omp_get_thread_num();
Packit 141393
#endif
Packit 141393
    size_t inlen__ = inlen;
Packit 141393
    const unsigned char *in__ = ( const unsigned char * )in;
Packit 141393
    in__ += i * BLAKE2S_BLOCKBYTES;
Packit 141393
Packit 141393
    while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
Packit 141393
    {
Packit 141393
      blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES );
Packit 141393
      in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
Packit 141393
      inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
Packit 141393
    }
Packit 141393
Packit 141393
    if( inlen__ > i * BLAKE2S_BLOCKBYTES )
Packit 141393
    {
Packit 141393
      const size_t left = inlen__ - i * BLAKE2S_BLOCKBYTES;
Packit 141393
      const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES;
Packit 141393
      blake2s_update( S[i], in__, len );
Packit 141393
    }
Packit 141393
Packit 141393
    blake2s_final( S[i], hash[i], BLAKE2S_OUTBYTES );
Packit 141393
  }
Packit 141393
Packit 141393
  if( blake2sp_init_root( FS, outlen, keylen ) < 0 )
Packit 141393
    return -1;
Packit 141393
Packit 141393
  FS->last_node = 1;
Packit 141393
Packit 141393
  for( i = 0; i < PARALLELISM_DEGREE; ++i )
Packit 141393
    blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES );
Packit 141393
Packit 141393
  return blake2s_final( FS, out, outlen );
Packit 141393
}
Packit 141393
Packit 141393
#if defined(BLAKE2SP_SELFTEST)
Packit 141393
#include <string.h>
Packit 141393
#include "blake2-kat.h"
Packit 141393
int main( void )
Packit 141393
{
Packit 141393
  uint8_t key[BLAKE2S_KEYBYTES];
Packit 141393
  uint8_t buf[BLAKE2_KAT_LENGTH];
Packit 141393
  size_t i, step;
Packit 141393
Packit 141393
  for( i = 0; i < BLAKE2S_KEYBYTES; ++i )
Packit 141393
    key[i] = ( uint8_t )i;
Packit 141393
Packit 141393
  for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
Packit 141393
    buf[i] = ( uint8_t )i;
Packit 141393
Packit 141393
  /* Test simple API */
Packit 141393
  for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
Packit 141393
  {
Packit 141393
    uint8_t hash[BLAKE2S_OUTBYTES];
Packit 141393
    blake2sp( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
Packit 141393
Packit 141393
    if( 0 != memcmp( hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES ) )
Packit 141393
    {
Packit 141393
      goto fail;
Packit 141393
    }
Packit 141393
  }
Packit 141393
Packit 141393
  /* Test streaming API */
Packit 141393
  for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
Packit 141393
    for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
Packit 141393
      uint8_t hash[BLAKE2S_OUTBYTES];
Packit 141393
      blake2sp_state S;
Packit 141393
      uint8_t * p = buf;
Packit 141393
      size_t mlen = i;
Packit 141393
      int err = 0;
Packit 141393
Packit 141393
      if( (err = blake2sp_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
Packit 141393
        goto fail;
Packit 141393
      }
Packit 141393
Packit 141393
      while (mlen >= step) {
Packit 141393
        if ( (err = blake2sp_update(&S, p, step)) < 0 ) {
Packit 141393
          goto fail;
Packit 141393
        }
Packit 141393
        mlen -= step;
Packit 141393
        p += step;
Packit 141393
      }
Packit 141393
      if ( (err = blake2sp_update(&S, p, mlen)) < 0) {
Packit 141393
        goto fail;
Packit 141393
      }
Packit 141393
      if ( (err = blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
Packit 141393
        goto fail;
Packit 141393
      }
Packit 141393
Packit 141393
      if (0 != memcmp(hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES)) {
Packit 141393
        goto fail;
Packit 141393
      }
Packit 141393
    }
Packit 141393
  }
Packit 141393
Packit 141393
  puts( "ok" );
Packit 141393
  return 0;
Packit 141393
fail:
Packit 141393
  puts("error");
Packit 141393
  return -1;
Packit 141393
}
Packit 141393
#endif