Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Merge branch 'blake2-digests'
Vsevolod Stakhov committed 11 years ago
commit 58d49cefe148e5a5a733961dba0d328bb69f0474
parent d5f66a7
10 files changed +688 -1
modified configure.ac
@@ -429,6 +429,7 @@ AC_SUBST([REPOS_LDADD_STATIC])
AC_CONFIG_FILES(Makefile \
		src/Makefile \
		external/Makefile \
+
		external/blake2/Makefile \
		scripts/Makefile \
		docs/Makefile \
		tests/Makefile \
modified external/Makefile.am
@@ -281,3 +281,5 @@ libelf/native-elf-format.h:
	$(srcdir)/libelf/native-elf-format > libelf/native-elf-format.h

endif
+

+
SUBDIRS=	blake2

\ No newline at end of file
added external/blake2/Makefile.am
@@ -0,0 +1,11 @@
+
noinst_HEADERS=	blake2.h \
+
				blake2-impl.h
+

+
noinst_LTLIBRARIES=	libblake2.la libblake2_static.la
+

+
blake2_common_cflags=	-I$(top_srcdir)/compat -O3
+
libblake2_la_SOURCES=	blake2b-ref.c
+
libblake2_la_CFLAGS=	$(blake2_common_cflags) -shared
+
libblake2_static_la_SOURCES=	$(libblake2_la_SOURCES)
+
libblake2_static_la_CFLAGS=	$(blake2_common_cflags) -static
+
libblake2_static_la_LDFLAGS=	-all-static

\ No newline at end of file
added external/blake2/blake2-impl.h
@@ -0,0 +1,151 @@
+
/*
+
   BLAKE2 reference source code package - reference C implementations
+

+
   Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
+

+
   To the extent possible under law, the author(s) have dedicated all copyright
+
   and related and neighboring rights to this software to the public domain
+
   worldwide. This software is distributed without any warranty.
+

+
   You should have received a copy of the CC0 Public Domain Dedication along with
+
   this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
+
*/
+
#pragma once
+
#ifndef __BLAKE2_IMPL_H__
+
#define __BLAKE2_IMPL_H__
+

+
#include <pkg_config.h>
+
#include <stdint.h>
+

+
#ifdef HAVE_SYS_ENDIAN_H
+
#include <sys/endian.h>
+
#elif HAVE_ENDIAN_H
+
#include <endian.h>
+
#elif HAVE_MACHINE_ENDIAN_H
+
#include <machine/endian.h>
+
#endif
+

+
#ifdef __BYTE_ORDER
+
# if __BYTE_ORDER == __LITTLE_ENDIAN
+
#  define NATIVE_LITTLE_ENDIAN
+
# endif
+
#endif
+

+
static inline uint32_t load32( const void *src )
+
{
+
#if defined(NATIVE_LITTLE_ENDIAN)
+
  uint32_t w;
+
  memcpy(&w, src, sizeof w);
+
  return w;
+
#else
+
  const uint8_t *p = ( const uint8_t * )src;
+
  uint32_t w = *p++;
+
  w |= ( uint32_t )( *p++ ) <<  8;
+
  w |= ( uint32_t )( *p++ ) << 16;
+
  w |= ( uint32_t )( *p++ ) << 24;
+
  return w;
+
#endif
+
}
+

+
static inline uint64_t load64( const void *src )
+
{
+
#if defined(NATIVE_LITTLE_ENDIAN)
+
  uint64_t w;
+
  memcpy(&w, src, sizeof w);
+
  return w;
+
#else
+
  const uint8_t *p = ( const uint8_t * )src;
+
  uint64_t w = *p++;
+
  w |= ( uint64_t )( *p++ ) <<  8;
+
  w |= ( uint64_t )( *p++ ) << 16;
+
  w |= ( uint64_t )( *p++ ) << 24;
+
  w |= ( uint64_t )( *p++ ) << 32;
+
  w |= ( uint64_t )( *p++ ) << 40;
+
  w |= ( uint64_t )( *p++ ) << 48;
+
  w |= ( uint64_t )( *p++ ) << 56;
+
  return w;
+
#endif
+
}
+

+
static inline void store32( void *dst, uint32_t w )
+
{
+
#if defined(NATIVE_LITTLE_ENDIAN)
+
  memcpy(dst, &w, sizeof w);
+
#else
+
  uint8_t *p = ( uint8_t * )dst;
+
  *p++ = ( uint8_t )w; w >>= 8;
+
  *p++ = ( uint8_t )w; w >>= 8;
+
  *p++ = ( uint8_t )w; w >>= 8;
+
  *p++ = ( uint8_t )w;
+
#endif
+
}
+

+
static inline void store64( void *dst, uint64_t w )
+
{
+
#if defined(NATIVE_LITTLE_ENDIAN)
+
  memcpy(dst, &w, sizeof w);
+
#else
+
  uint8_t *p = ( uint8_t * )dst;
+
  *p++ = ( uint8_t )w; w >>= 8;
+
  *p++ = ( uint8_t )w; w >>= 8;
+
  *p++ = ( uint8_t )w; w >>= 8;
+
  *p++ = ( uint8_t )w; w >>= 8;
+
  *p++ = ( uint8_t )w; w >>= 8;
+
  *p++ = ( uint8_t )w; w >>= 8;
+
  *p++ = ( uint8_t )w; w >>= 8;
+
  *p++ = ( uint8_t )w;
+
#endif
+
}
+

+
static inline uint64_t load48( const void *src )
+
{
+
  const uint8_t *p = ( const uint8_t * )src;
+
  uint64_t w = *p++;
+
  w |= ( uint64_t )( *p++ ) <<  8;
+
  w |= ( uint64_t )( *p++ ) << 16;
+
  w |= ( uint64_t )( *p++ ) << 24;
+
  w |= ( uint64_t )( *p++ ) << 32;
+
  w |= ( uint64_t )( *p++ ) << 40;
+
  return w;
+
}
+

+
static inline void store48( void *dst, uint64_t w )
+
{
+
  uint8_t *p = ( uint8_t * )dst;
+
  *p++ = ( uint8_t )w; w >>= 8;
+
  *p++ = ( uint8_t )w; w >>= 8;
+
  *p++ = ( uint8_t )w; w >>= 8;
+
  *p++ = ( uint8_t )w; w >>= 8;
+
  *p++ = ( uint8_t )w; w >>= 8;
+
  *p++ = ( uint8_t )w;
+
}
+

+
static inline uint32_t rotl32( const uint32_t w, const unsigned c )
+
{
+
  return ( w << c ) | ( w >> ( 32 - c ) );
+
}
+

+
static inline uint64_t rotl64( const uint64_t w, const unsigned c )
+
{
+
  return ( w << c ) | ( w >> ( 64 - c ) );
+
}
+

+
static inline uint32_t rotr32( const uint32_t w, const unsigned c )
+
{
+
  return ( w >> c ) | ( w << ( 32 - c ) );
+
}
+

+
static inline uint64_t rotr64( const uint64_t w, const unsigned c )
+
{
+
  return ( w >> c ) | ( w << ( 64 - c ) );
+
}
+

+
/* prevents compiler optimizing out memset() */
+
static inline void secure_zero_memory( void *v, size_t n )
+
{
+
  volatile uint8_t *p = ( volatile uint8_t * )v;
+
  while( n-- ) *p++ = 0;
+
}
+

+
#endif
+

added external/blake2/blake2.h
@@ -0,0 +1,89 @@
+
/*
+
   BLAKE2 reference source code package - reference C implementations
+

+
   Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
+

+
   To the extent possible under law, the author(s) have dedicated all copyright
+
   and related and neighboring rights to this software to the public domain
+
   worldwide. This software is distributed without any warranty.
+

+
   You should have received a copy of the CC0 Public Domain Dedication along with
+
   this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
+
*/
+
#pragma once
+
#ifndef __BLAKE2_H__
+
#define __BLAKE2_H__
+

+
#include <stddef.h>
+
#include <stdint.h>
+

+
#ifndef BLAKE_ALIGN
+
# if defined(_MSC_VER)
+
#  define BLAKE_ALIGN(x) __declspec(align(x))
+
# else
+
#  define BLAKE_ALIGN(x) __attribute__((aligned(x)))
+
# endif
+
#endif
+

+
#if defined(__cplusplus)
+
extern "C" {
+
#endif
+

+

+
  enum blake2b_constant
+
  {
+
    BLAKE2B_BLOCKBYTES = 128,
+
    BLAKE2B_OUTBYTES   = 64,
+
    BLAKE2B_KEYBYTES   = 64,
+
    BLAKE2B_SALTBYTES  = 16,
+
    BLAKE2B_PERSONALBYTES = 16
+
  };
+

+
#pragma pack(push, 1)
+

+
  typedef struct __blake2b_param
+
  {
+
    uint8_t  digest_length; // 1
+
    uint8_t  key_length;    // 2
+
    uint8_t  fanout;        // 3
+
    uint8_t  depth;         // 4
+
    uint32_t leaf_length;   // 8
+
    uint64_t node_offset;   // 16
+
    uint8_t  node_depth;    // 17
+
    uint8_t  inner_length;  // 18
+
    uint8_t  reserved[14];  // 32
+
    uint8_t  salt[BLAKE2B_SALTBYTES]; // 48
+
    uint8_t  personal[BLAKE2B_PERSONALBYTES];  // 64
+
  } blake2b_param;
+

+
  BLAKE_ALIGN( 64 ) typedef struct __blake2b_state
+
  {
+
    uint64_t h[8];
+
    uint64_t t[2];
+
    uint64_t f[2];
+
    uint8_t  buf[2 * BLAKE2B_BLOCKBYTES];
+
    size_t   buflen;
+
    uint8_t  last_node;
+
  } blake2b_state;
+

+
#pragma pack(pop)
+

+
  int blake2b_init( blake2b_state *S, const uint8_t outlen );
+
  int blake2b_init_key( blake2b_state *S, const uint8_t outlen, const void *key, const uint8_t keylen );
+
  int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
+
  int blake2b_update( blake2b_state *S, const uint8_t *in, uint64_t inlen );
+
  int blake2b_final( blake2b_state *S, uint8_t *out, uint8_t outlen );
+

+
  int blake2b( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen );
+

+
  static inline int blake2( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen )
+
  {
+
    return blake2b( out, in, key, outlen, inlen, keylen );
+
  }
+

+
#if defined(__cplusplus)
+
}
+
#endif
+

+
#endif
+

added external/blake2/blake2b-ref.c
@@ -0,0 +1,394 @@
+
/*
+
   BLAKE2 reference source code package - reference C implementations
+

+
   Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
+

+
   To the extent possible under law, the author(s) have dedicated all copyright
+
   and related and neighboring rights to this software to the public domain
+
   worldwide. This software is distributed without any warranty.
+

+
   You should have received a copy of the CC0 Public Domain Dedication along with
+
   this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
+
*/
+

+
#include <stdint.h>
+
#include <string.h>
+
#include <stdio.h>
+

+
#include "blake2.h"
+
#include "blake2-impl.h"
+

+
static const uint64_t blake2b_IV[8] =
+
{
+
  0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
+
  0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
+
  0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+
  0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
+
};
+

+
static const uint8_t blake2b_sigma[12][16] =
+
{
+
  {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 } ,
+
  { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 } ,
+
  { 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4 } ,
+
  {  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8 } ,
+
  {  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13 } ,
+
  {  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9 } ,
+
  { 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11 } ,
+
  { 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10 } ,
+
  {  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5 } ,
+
  { 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13 , 0 } ,
+
  {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 } ,
+
  { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 }
+
};
+

+

+
static inline int blake2b_set_lastnode( blake2b_state *S )
+
{
+
  S->f[1] = ~0ULL;
+
  return 0;
+
}
+

+
static inline int blake2b_clear_lastnode( blake2b_state *S )
+
{
+
  S->f[1] = 0ULL;
+
  return 0;
+
}
+

+
/* Some helper functions, not necessarily useful */
+
static inline int blake2b_set_lastblock( blake2b_state *S )
+
{
+
  if( S->last_node ) blake2b_set_lastnode( S );
+

+
  S->f[0] = ~0ULL;
+
  return 0;
+
}
+

+
static inline int blake2b_clear_lastblock( blake2b_state *S )
+
{
+
  if( S->last_node ) blake2b_clear_lastnode( S );
+

+
  S->f[0] = 0ULL;
+
  return 0;
+
}
+

+
static inline int blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
+
{
+
  S->t[0] += inc;
+
  S->t[1] += ( S->t[0] < inc );
+
  return 0;
+
}
+

+

+

+
// Parameter-related functions
+
static inline int blake2b_param_set_digest_length( blake2b_param *P, const uint8_t digest_length )
+
{
+
  P->digest_length = digest_length;
+
  return 0;
+
}
+

+
static inline int blake2b_param_set_fanout( blake2b_param *P, const uint8_t fanout )
+
{
+
  P->fanout = fanout;
+
  return 0;
+
}
+

+
static inline int blake2b_param_set_max_depth( blake2b_param *P, const uint8_t depth )
+
{
+
  P->depth = depth;
+
  return 0;
+
}
+

+
static inline int blake2b_param_set_leaf_length( blake2b_param *P, const uint32_t leaf_length )
+
{
+
  store32( &P->leaf_length, leaf_length );
+
  return 0;
+
}
+

+
static inline int blake2b_param_set_node_offset( blake2b_param *P, const uint64_t node_offset )
+
{
+
  store64( &P->node_offset, node_offset );
+
  return 0;
+
}
+

+
static inline int blake2b_param_set_node_depth( blake2b_param *P, const uint8_t node_depth )
+
{
+
  P->node_depth = node_depth;
+
  return 0;
+
}
+

+
static inline int blake2b_param_set_inner_length( blake2b_param *P, const uint8_t inner_length )
+
{
+
  P->inner_length = inner_length;
+
  return 0;
+
}
+

+
static inline int blake2b_param_set_salt( blake2b_param *P, const uint8_t salt[BLAKE2B_SALTBYTES] )
+
{
+
  memcpy( P->salt, salt, BLAKE2B_SALTBYTES );
+
  return 0;
+
}
+

+
static inline int blake2b_param_set_personal( blake2b_param *P, const uint8_t personal[BLAKE2B_PERSONALBYTES] )
+
{
+
  memcpy( P->personal, personal, BLAKE2B_PERSONALBYTES );
+
  return 0;
+
}
+

+
static inline int blake2b_init0( blake2b_state *S )
+
{
+
  memset( S, 0, sizeof( blake2b_state ) );
+

+
  for( int i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];
+

+
  return 0;
+
}
+

+
/* init xors IV with input parameter block */
+
int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
+
{
+
  blake2b_init0( S );
+
  const uint8_t *p = ( const uint8_t * )( P );
+

+
  /* IV XOR ParamBlock */
+
  for( size_t i = 0; i < 8; ++i )
+
    S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );
+

+
  return 0;
+
}
+

+

+

+
int blake2b_init( blake2b_state *S, const uint8_t outlen )
+
{
+
  blake2b_param P[1];
+

+
  if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
+

+
  P->digest_length = outlen;
+
  P->key_length    = 0;
+
  P->fanout        = 1;
+
  P->depth         = 1;
+
  store32( &P->leaf_length, 0 );
+
  store64( &P->node_offset, 0 );
+
  P->node_depth    = 0;
+
  P->inner_length  = 0;
+
  memset( P->reserved, 0, sizeof( P->reserved ) );
+
  memset( P->salt,     0, sizeof( P->salt ) );
+
  memset( P->personal, 0, sizeof( P->personal ) );
+
  return blake2b_init_param( S, P );
+
}
+

+

+
int blake2b_init_key( blake2b_state *S, const uint8_t outlen, const void *key, const uint8_t keylen )
+
{
+
  blake2b_param P[1];
+

+
  if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
+

+
  if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
+

+
  P->digest_length = outlen;
+
  P->key_length    = keylen;
+
  P->fanout        = 1;
+
  P->depth         = 1;
+
  store32( &P->leaf_length, 0 );
+
  store64( &P->node_offset, 0 );
+
  P->node_depth    = 0;
+
  P->inner_length  = 0;
+
  memset( P->reserved, 0, sizeof( P->reserved ) );
+
  memset( P->salt,     0, sizeof( P->salt ) );
+
  memset( P->personal, 0, sizeof( P->personal ) );
+

+
  if( blake2b_init_param( S, P ) < 0 ) return -1;
+

+
  {
+
    uint8_t block[BLAKE2B_BLOCKBYTES];
+
    memset( block, 0, BLAKE2B_BLOCKBYTES );
+
    memcpy( block, key, keylen );
+
    blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
+
    secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
+
  }
+
  return 0;
+
}
+

+
static int blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
+
{
+
  uint64_t m[16];
+
  uint64_t v[16];
+
  int i;
+

+
  for( i = 0; i < 16; ++i )
+
    m[i] = load64( block + i * sizeof( m[i] ) );
+

+
  for( i = 0; i < 8; ++i )
+
    v[i] = S->h[i];
+

+
  v[ 8] = blake2b_IV[0];
+
  v[ 9] = blake2b_IV[1];
+
  v[10] = blake2b_IV[2];
+
  v[11] = blake2b_IV[3];
+
  v[12] = S->t[0] ^ blake2b_IV[4];
+
  v[13] = S->t[1] ^ blake2b_IV[5];
+
  v[14] = S->f[0] ^ blake2b_IV[6];
+
  v[15] = S->f[1] ^ blake2b_IV[7];
+
#define G(r,i,a,b,c,d) \
+
  do { \
+
    a = a + b + m[blake2b_sigma[r][2*i+0]]; \
+
    d = rotr64(d ^ a, 32); \
+
    c = c + d; \
+
    b = rotr64(b ^ c, 24); \
+
    a = a + b + m[blake2b_sigma[r][2*i+1]]; \
+
    d = rotr64(d ^ a, 16); \
+
    c = c + d; \
+
    b = rotr64(b ^ c, 63); \
+
  } while(0)
+
#define ROUND(r)  \
+
  do { \
+
    G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
+
    G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
+
    G(r,2,v[ 2],v[ 6],v[10],v[14]); \
+
    G(r,3,v[ 3],v[ 7],v[11],v[15]); \
+
    G(r,4,v[ 0],v[ 5],v[10],v[15]); \
+
    G(r,5,v[ 1],v[ 6],v[11],v[12]); \
+
    G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
+
    G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
+
  } while(0)
+
  ROUND( 0 );
+
  ROUND( 1 );
+
  ROUND( 2 );
+
  ROUND( 3 );
+
  ROUND( 4 );
+
  ROUND( 5 );
+
  ROUND( 6 );
+
  ROUND( 7 );
+
  ROUND( 8 );
+
  ROUND( 9 );
+
  ROUND( 10 );
+
  ROUND( 11 );
+

+
  for( i = 0; i < 8; ++i )
+
    S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
+

+
#undef G
+
#undef ROUND
+
  return 0;
+
}
+

+
/* inlen now in bytes */
+
int blake2b_update( blake2b_state *S, const uint8_t *in, uint64_t inlen )
+
{
+
  while( inlen > 0 )
+
  {
+
    size_t left = S->buflen;
+
    size_t fill = 2 * BLAKE2B_BLOCKBYTES - left;
+

+
    if( inlen > fill )
+
    {
+
      memcpy( S->buf + left, in, fill ); // Fill buffer
+
      S->buflen += fill;
+
      blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
+
      blake2b_compress( S, S->buf ); // Compress
+
      memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); // Shift buffer left
+
      S->buflen -= BLAKE2B_BLOCKBYTES;
+
      in += fill;
+
      inlen -= fill;
+
    }
+
    else // inlen <= fill
+
    {
+
      memcpy( S->buf + left, in, inlen );
+
      S->buflen += inlen; // Be lazy, do not compress
+
      in += inlen;
+
      inlen -= inlen;
+
    }
+
  }
+

+
  return 0;
+
}
+

+
/* Is this correct? */
+
int blake2b_final( blake2b_state *S, uint8_t *out, uint8_t outlen )
+
{
+
  uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
+

+
  if( outlen > BLAKE2B_OUTBYTES )
+
    return -1;
+

+
  if( S->buflen > BLAKE2B_BLOCKBYTES )
+
  {
+
    blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
+
    blake2b_compress( S, S->buf );
+
    S->buflen -= BLAKE2B_BLOCKBYTES;
+
    memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, S->buflen );
+
  }
+

+
  blake2b_increment_counter( S, S->buflen );
+
  blake2b_set_lastblock( S );
+
  memset( S->buf + S->buflen, 0, 2 * BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */
+
  blake2b_compress( S, S->buf );
+

+
  for( int i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
+
    store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );
+

+
  memcpy( out, buffer, outlen );
+
  return 0;
+
}
+

+
/* inlen, at least, should be uint64_t. Others can be size_t. */
+
int blake2b( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen )
+
{
+
  blake2b_state S[1];
+

+
  /* Verify parameters */
+
  if ( NULL == in ) return -1;
+

+
  if ( NULL == out ) return -1;
+

+
  if( NULL == key ) keylen = 0;
+

+
  if( keylen > 0 )
+
  {
+
    if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
+
  }
+
  else
+
  {
+
    if( blake2b_init( S, outlen ) < 0 ) return -1;
+
  }
+

+
  blake2b_update( S, ( const uint8_t * )in, inlen );
+
  blake2b_final( S, out, outlen );
+
  return 0;
+
}
+

+
#if defined(BLAKE2B_SELFTEST)
+
#include <string.h>
+
#include "blake2-kat.h"
+
int main( int argc, char **argv )
+
{
+
  uint8_t key[BLAKE2B_KEYBYTES];
+
  uint8_t buf[KAT_LENGTH];
+

+
  for( size_t i = 0; i < BLAKE2B_KEYBYTES; ++i )
+
    key[i] = ( uint8_t )i;
+

+
  for( size_t i = 0; i < KAT_LENGTH; ++i )
+
    buf[i] = ( uint8_t )i;
+

+
  for( size_t i = 0; i < KAT_LENGTH; ++i )
+
  {
+
    uint8_t hash[BLAKE2B_OUTBYTES];
+
    blake2b( hash, buf, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES );
+

+
    if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )
+
    {
+
      puts( "error" );
+
      return -1;
+
    }
+
  }
+

+
  puts( "ok" );
+
  return 0;
+
}
+
#endif
+

modified libpkg/Makefile.am
@@ -11,6 +11,7 @@ pkg_common_cflags= -I$(top_srcdir)/libpkg -I$(top_builddir)/libpkg \
			-I$(top_srcdir)/external/uthash \
			-I$(top_srcdir)/external/sqlite \
			-I$(top_srcdir)/external/include \
+
			-I$(top_srcdir)/external/blake2 \
			-DPREFIX=\"$(prefix)\" \
			-Wno-pointer-sign

@@ -78,6 +79,7 @@ libpkg_la_LIBADD= $(top_builddir)/compat/libbsd_compat.la \
			$(top_builddir)/external/libsbuf.la \
			$(top_builddir)/external/libpicosat.la \
			$(top_builddir)/external/libfetch.la \
+
			$(top_builddir)/external/blake2/libblake2.la \
			@REPOS_LDADD@ \
			@LIBEXECINFO_LIB@ \
			@LDNS_LIBS@ \
@@ -122,6 +124,7 @@ libpkg_static_la_LIBADD= $(top_builddir)/external/libucl_static.la \
			$(top_builddir)/external/libpicosat_static.la \
			$(top_builddir)/external/libsbuf_static.la \
			$(top_builddir)/external/libfetch_static.la \
+
			$(top_builddir)/external/blake2/libblake2_static.la \
			@REPOS_LDADD_STATIC@

EXTRA_libpkg_static_la_DEPENDENCIES=	@REPOS_LDADD_STATIC@ libpkg.ver
modified libpkg/pkg_checksum.c
@@ -27,6 +27,7 @@
#include "pkg.h"
#include "private/pkg.h"
#include "private/event.h"
+
#include "blake2.h"

struct pkg_checksum_entry {
	const char *field;
@@ -44,6 +45,8 @@ typedef void (*pkg_checksum_encode_func)(unsigned char *in, size_t inlen,

static void pkg_checksum_hash_sha256(struct pkg_checksum_entry *entries,
				unsigned char **out, size_t *outlen);
+
static void pkg_checksum_hash_blake2(struct pkg_checksum_entry *entries,
+
				unsigned char **out, size_t *outlen);
static void pkg_checksum_encode_base32(unsigned char *in, size_t inlen,
				char *out, size_t outlen);
static void pkg_checksum_encode_hex(unsigned char *in, size_t inlen,
@@ -67,6 +70,12 @@ static const struct _pkg_cksum_type {
		pkg_checksum_hash_sha256,
		pkg_checksum_encode_hex
	},
+
	[PKG_HASH_TYPE_BLAKE2_BASE32] = {
+
		"blake2_base32",
+
		PKG_CHECKSUM_BLAKE2_LEN,
+
		pkg_checksum_hash_blake2,
+
		pkg_checksum_encode_hex
+
	},
	[PKG_HASH_TYPE_UNKNOWN] = {
		NULL,
		-1,
@@ -266,6 +275,30 @@ pkg_checksum_hash_sha256(struct pkg_checksum_entry *entries,
	}
}

+
static void
+
pkg_checksum_hash_blake2(struct pkg_checksum_entry *entries,
+
		unsigned char **out, size_t *outlen)
+
{
+
	blake2b_state st;
+

+
	blake2b_init (&st, BLAKE2B_OUTBYTES);
+

+
	while(entries) {
+
		blake2b_update (&st, entries->field, strlen(entries->field));
+
		blake2b_update (&st, entries->value, strlen(entries->value));
+
		entries = entries->next;
+
	}
+
	*out = malloc(BLAKE2B_OUTBYTES);
+
	if (*out != NULL) {
+
		blake2b_final (&st, *out, BLAKE2B_OUTBYTES);
+
		*outlen = BLAKE2B_OUTBYTES;
+
	}
+
	else {
+
		pkg_emit_errno("malloc", "pkg_checksum_hash_blake2");
+
		*outlen = 0;
+
	}
+
}
+

/*
 * We use here z-base32 encoding described here:
 * http://philzimmermann.com/docs/human-oriented-base-32-encoding.txt
modified libpkg/pkg_repo_meta.c
@@ -98,7 +98,7 @@ pkg_repo_meta_open_schema_v1()
			"maintainer = {type = string};\n"
			"source = {type = string};\n"
			"packing_format = {enum = [txz, tbz, tgz]};\n"
-
			"digest_format = {enum = [sha256_base32, sha256_hex]};\n"
+
			"digest_format = {enum = [sha256_base32, sha256_hex, blake2_base32]};\n"
			"digests = {type = string};\n"
			"manifests = {type = string};\n"
			"conflicts = {type = string};\n"
modified libpkg/private/pkg.h
@@ -271,6 +271,7 @@ struct pkg_repo_meta_key {
typedef enum pkg_checksum_type_e {
	PKG_HASH_TYPE_SHA256_BASE32 = 0,
	PKG_HASH_TYPE_SHA256_HEX,
+
	PKG_HASH_TYPE_BLAKE2_BASE32,
	PKG_HASH_TYPE_UNKNOWN
} pkg_checksum_type_t;

@@ -503,6 +504,7 @@ bool pkg_repo_meta_is_special_file(const char *file, struct pkg_repo_meta *meta)
typedef enum {
	HASH_UNKNOWN,
	HASH_SHA256,
+
	HASH_BLAKE2
} hash_t;

struct fingerprint {
@@ -608,6 +610,7 @@ pkg_object* pkg_emit_object(struct pkg *pkg, short flags);

/* Hash is in format <version>:<typeid>:<hexhash> */
#define PKG_CHECKSUM_SHA256_LEN (SHA256_DIGEST_LENGTH * 2 + sizeof("100") * 2 + 2)
+
#define PKG_CHECKSUM_BLAKE2_LEN (BLAKE2B_OUTBYTES * 8 / 5 + sizeof("100") * 2 + 2)
#define PKG_CHECKSUM_CUR_VERSION 2

int pkg_checksum_generate(struct pkg *pkg, char *dest, size_t destlen,