blake2 (empty) → 0.1.0
raw patch · 29 files changed
+3926/−0 lines, 29 filesdep +QuickCheckdep +basedep +base16-bytestringsetup-changed
Dependencies added: QuickCheck, base, base16-bytestring, blake2, bytestring, criterion, hlint, tasty, tasty-quickcheck
Files
- .travis.yml +84/−0
- LICENSE +24/−0
- README.md +6/−0
- Setup.hs +2/−0
- benchmarks/bench.hs +40/−0
- blake2.cabal +129/−0
- cbits/blake2b.c +439/−0
- cbits/blake2bp.c +298/−0
- cbits/blake2s.c +422/−0
- cbits/blake2sp.c +293/−0
- changelog.md +3/−0
- include/blake2-config.h +72/−0
- include/blake2-impl.h +136/−0
- include/blake2.h +150/−0
- include/blake2b-load-sse2.h +68/−0
- include/blake2b-load-sse41.h +402/−0
- include/blake2b-round.h +157/−0
- include/blake2s-load-sse2.h +59/−0
- include/blake2s-load-sse41.h +229/−0
- include/blake2s-load-xop.h +189/−0
- include/blake2s-round.h +88/−0
- src/Crypto/Hash/BLAKE2/BLAKE2b.hsc +95/−0
- src/Crypto/Hash/BLAKE2/BLAKE2bp.hsc +95/−0
- src/Crypto/Hash/BLAKE2/BLAKE2s.hsc +95/−0
- src/Crypto/Hash/BLAKE2/BLAKE2sp.hsc +95/−0
- src/Crypto/Hash/BLAKE2/Internal.hs +130/−0
- tests/Imports.hs +7/−0
- tests/hlint.hs +16/−0
- tests/properties.hs +103/−0
+ .travis.yml view
@@ -0,0 +1,84 @@+# This file has been generated -- see https://github.com/hvr/multi-ghc-travis+language: c+sudo: false++cache:+ directories:+ - $HOME/.cabsnap+ - $HOME/.cabal/packages++before_cache:+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.tar++matrix:+ include:+ - env: CABALVER=1.22 GHCVER=7.10.1+ compiler: ": #GHC 7.10.1"+ addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.1,alex-3.1.4,happy-1.19.5], sources: [hvr-ghc]}}+ - env: CABALVER=1.22 GHCVER=7.10.2+ compiler: ": #GHC 7.10.2"+ addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.2,alex-3.1.4,happy-1.19.5], sources: [hvr-ghc]}}+ - env: CABALVER=1.22 GHCVER=head+ compiler: ": #GHC head"+ addons: {apt: {packages: [cabal-install-1.22,ghc-head,alex-3.1.4,happy-1.19.5], sources: [hvr-ghc]}}++ allow_failures:+ - env: CABALVER=1.22 GHCVER=head++before_install:+ - unset CC+ - export HAPPYVER=1.19.5+ - export ALEXVER=3.1.4+ - export PATH=~/.cabal/bin:/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:/opt/happy/$HAPPYVER/bin:/opt/alex/$ALEXVER/bin:$PATH++install:+ - cabal --version+ - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"+ - if [ -f $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz ];+ then+ zcat $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz >+ $HOME/.cabal/packages/hackage.haskell.org/00-index.tar;+ fi+ - travis_retry cabal update+ - "sed -i 's/^jobs:.*$/jobs: 2/' $HOME/.cabal/config"+ - cabal install --only-dependencies --enable-tests --dry -v blake2.cabal > installplan.txt+ - sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt++ # check whether current requested install-plan matches cached package-db snapshot+ - if diff -u installplan.txt $HOME/.cabsnap/installplan.txt;+ then+ echo "cabal build-cache HIT";+ rm -rfv .ghc;+ cp -a $HOME/.cabsnap/ghc $HOME/.ghc;+ cp -a $HOME/.cabsnap/lib $HOME/.cabsnap/share $HOME/.cabsnap/bin $HOME/.cabal/;+ else+ echo "cabal build-cache MISS";+ rm -rf $HOME/.cabsnap;+ mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin;+ cabal install --only-dependencies --enable-tests blake2.cabal;+ if [ "$GHCVER" = "7.10.1" ]; then cabal install Cabal-1.22.4.0; fi;+ fi++ # snapshot package-db on cache miss+ - if [ ! -d $HOME/.cabsnap ];+ then+ echo "snapshotting package-db to build-cache";+ mkdir $HOME/.cabsnap;+ cp -a $HOME/.ghc $HOME/.cabsnap/ghc;+ cp -a $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin installplan.txt $HOME/.cabsnap/;+ fi++ - cabal install++script:+ - cabal configure --enable-tests -v2 # -v2 provides useful information for debugging+ - cabal build # this builds all libraries and executables (including tests)+ - cabal test+ - cabal sdist # tests that a source-distribution can be generated++ # Check that the resulting source distribution can be built & installed.+ # If there are no other `.tar.gz` files in `dist`, this can be even simpler:+ # `cabal install --force-reinstalls dist/*-*.tar.gz`+ - SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz &&+ (cd dist && cabal install --enable-tests --run-tests --force-reinstalls "$SRC_TGZ")
+ LICENSE view
@@ -0,0 +1,24 @@+This is free and unencumbered software released into the public domain.++Anyone is free to copy, modify, publish, use, compile, sell, or+distribute this software, either in source code form or as a compiled+binary, for any purpose, commercial or non-commercial, and by any+means.++In jurisdictions that recognize copyright laws, the author or authors+of this software dedicate any and all copyright interest in the+software to the public domain. We make this dedication for the benefit+of the public at large and to the detriment of our heirs and+successors. We intend this dedication to be an overt act of+relinquishment in perpetuity of all present and future rights to this+software under copyright law.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR+OTHER DEALINGS IN THE SOFTWARE.++For more information, please refer to <http://unlicense.org>
+ README.md view
@@ -0,0 +1,6 @@+# blake2++[](https://travis-ci.org/centromere/blake2)+[](http://www.haskell.org)++This library provides the [BLAKE2](https://blake2.net/) hash algorithms.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ benchmarks/bench.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE OverloadedStrings #-}+module Main where++import Criterion.Main+import Data.ByteString (ByteString)+import qualified Data.ByteString as B (replicate)++import qualified Crypto.Hash.BLAKE2.BLAKE2b as B2b+import qualified Crypto.Hash.BLAKE2.BLAKE2bp as B2bp+import qualified Crypto.Hash.BLAKE2.BLAKE2s as B2s+import qualified Crypto.Hash.BLAKE2.BLAKE2sp as B2sp++kb :: ByteString+kb = B.replicate 1024 3++mb :: ByteString+mb = B.replicate (1024^2) 3++gb :: ByteString+gb = B.replicate (1024^3) 3++main :: IO ()+main = defaultMain+ [ bgroup "blake2s" [ bench "1 kb" $ nf (B2s.hash 32 "") kb+ , bench "1 mb" $ nf (B2s.hash 32 "") mb+ , bench "1 gb" $ nf (B2s.hash 32 "") gb+ ]+ , bgroup "blake2sp" [ bench "1 kb" $ nf (B2sp.hash 32 "") kb+ , bench "1 mb" $ nf (B2sp.hash 32 "") mb+ , bench "1 gb" $ nf (B2sp.hash 32 "") gb+ ]+ , bgroup "blake2b" [ bench "1 kb" $ nf (B2b.hash 64 "") kb+ , bench "1 mb" $ nf (B2b.hash 64 "") mb+ , bench "1 gb" $ nf (B2b.hash 64 "") gb+ ]+ , bgroup "blake2bp" [ bench "1 kb" $ nf (B2bp.hash 64 "") kb+ , bench "1 mb" $ nf (B2bp.hash 64 "") mb+ , bench "1 gb" $ nf (B2bp.hash 64 "") gb+ ]+ ]
+ blake2.cabal view
@@ -0,0 +1,129 @@+name: blake2+version: 0.1.0+synopsis: A library providing BLAKE2+license: PublicDomain+license-file: LICENSE+author: John Galt+maintainer: jgalt@centromere.net+homepage: https://github.com/centromere/blake2+bug-reports: https://github.com/centromere/blake2/issues+category: Cryptography+build-type: Simple+cabal-version: >=1.10+tested-with: GHC == 7.10.1, GHC == 7.10.2+description:+ This library provides the <https://blake2.net/ BLAKE2> hash algorithms.++extra-source-files:+ .travis.yml+ README.md+ changelog.md+ LICENSE+ cbits/blake2s.c+ cbits/blake2bp.c+ cbits/blake2sp.c+ cbits/blake2b.c+ include/blake2.h+ include/blake2s-round.h+ include/blake2b-round.h+ include/blake2b-load-sse41.h+ include/blake2s-load-sse2.h+ include/blake2b-load-sse2.h+ include/blake2s-load-sse41.h+ include/blake2-impl.h+ include/blake2-config.h+ include/blake2s-load-xop.h++source-repository head+ type: git+ location: https://github.com/centromere/blake2.git++--------------------------------------------------------------------------------+-- FLAGS++flag hlint++flag doctest++flag llvm+ default: False+ manual: True++--------------------------------------------------------------------------------+-- LIBRARY++library+ build-depends:+ base >=4.8 && <5,+ bytestring+ hs-source-dirs: src+ default-language: Haskell2010+ exposed-modules:+ Crypto.Hash.BLAKE2.BLAKE2b+ Crypto.Hash.BLAKE2.BLAKE2bp+ Crypto.Hash.BLAKE2.BLAKE2s+ Crypto.Hash.BLAKE2.BLAKE2sp+ Crypto.Hash.BLAKE2.Internal+ ghc-options: -rtsopts -with-rtsopts=-N -Wall -fwarn-tabs+ cc-options: -std=c99+ include-dirs: include+ c-sources:+ cbits/blake2b.c+ cbits/blake2bp.c+ cbits/blake2s.c+ cbits/blake2sp.c++ if flag(llvm)+ ghc-options: -fllvm++--------------------------------------------------------------------------------+-- TESTS++test-suite properties+ type: exitcode-stdio-1.0+ main-is: properties.hs+ ghc-options: -Wall -fwarn-tabs+ hs-source-dirs: tests+ default-language: Haskell2010++ build-depends:+ base >=4.8 && <5,+ base16-bytestring,+ bytestring,+ blake2,+ QuickCheck,+ tasty,+ tasty-quickcheck++ other-modules:+ Imports++test-suite hlint+ type: exitcode-stdio-1.0+ main-is: hlint.hs+ ghc-options: -Wall -fwarn-tabs+ hs-source-dirs: tests+ default-language: Haskell2010++ if !flag(hlint)+ buildable: False+ else+ build-depends:+ base >=4.8 && <5,+ hlint++--------------------------------------------------------------------------------+-- BENCHMARKS++benchmark bench+ type: exitcode-stdio-1.0+ main-is: bench.hs+ ghc-options: -Wall -fwarn-tabs+ hs-source-dirs: benchmarks+ default-language: Haskell2010++ build-depends:+ base >=4.8 && <5,+ blake2,+ bytestring,+ criterion
+ cbits/blake2b.c view
@@ -0,0 +1,439 @@+/*+ BLAKE2 reference source code package - optimized 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"++#include "blake2-config.h"++#ifdef _MSC_VER+#include <intrin.h> /* for _mm_set_epi64x */+#endif+#include <emmintrin.h>+#if defined(HAVE_SSSE3)+#include <tmmintrin.h>+#endif+#if defined(HAVE_SSE41)+#include <smmintrin.h>+#endif+#if defined(HAVE_AVX)+#include <immintrin.h>+#endif+#if defined(HAVE_XOP)+#include <x86intrin.h>+#endif++#include "blake2b-round.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 }+};+++/* Some helper functions, not necessarily useful */+static inline int blake2b_set_lastnode( blake2b_state *S )+{+ S->f[1] = -1;+ return 0;+}++static inline int blake2b_clear_lastnode( blake2b_state *S )+{+ S->f[1] = 0;+ return 0;+}++static inline int blake2b_set_lastblock( blake2b_state *S )+{+ if( S->last_node ) blake2b_set_lastnode( S );++ S->f[0] = -1;+ return 0;+}++static inline int blake2b_clear_lastblock( blake2b_state *S )+{+ if( S->last_node ) blake2b_clear_lastnode( S );++ S->f[0] = 0;+ return 0;+}+++static inline int blake2b_increment_counter( blake2b_state *S, const uint64_t inc )+{+#if __x86_64__+ // ADD/ADC chain+ __uint128_t t = ( ( __uint128_t )S->t[1] << 64 ) | S->t[0];+ t += inc;+ S->t[0] = ( uint64_t )( t >> 0 );+ S->t[1] = ( uint64_t )( t >> 64 );+#else+ S->t[0] += inc;+ S->t[1] += ( S->t[0] < inc );+#endif+ 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 )+{+ P->leaf_length = leaf_length;+ return 0;+}++static inline int blake2b_param_set_node_offset( blake2b_param *P, const uint64_t node_offset )+{+ 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 * v = ( const uint8_t * )( blake2b_IV );+ const uint8_t * p = ( const uint8_t * )( P );+ uint8_t * h = ( uint8_t * )( S->h );+ /* IV XOR ParamBlock */+ memset( S, 0, sizeof( blake2b_state ) );++ for( int i = 0; i < BLAKE2B_OUTBYTES; ++i ) h[i] = v[i] ^ p[i];++ return 0;+}+++/* Some sort of default parameter block initialization, for sequential blake2b */+int blake2b_init( blake2b_state *S, const uint8_t outlen )+{+ if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;++ const blake2b_param P =+ {+ outlen,+ 0,+ 1,+ 1,+ 0,+ 0,+ 0,+ 0,+ {0},+ {0},+ {0}+ };+ return blake2b_init_param( S, &P );+}++int blake2b_init_key( blake2b_state *S, const uint8_t outlen, const void *key, const uint8_t keylen )+{+ if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;++ if ( ( !keylen ) || keylen > BLAKE2B_KEYBYTES ) return -1;++ const blake2b_param P =+ {+ outlen,+ keylen,+ 1,+ 1,+ 0,+ 0,+ 0,+ 0,+ {0},+ {0},+ {0}+ };++ if( blake2b_init_param( S, &P ) < 0 )+ return 0;++ {+ 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 inline int blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )+{+ __m128i row1l, row1h;+ __m128i row2l, row2h;+ __m128i row3l, row3h;+ __m128i row4l, row4h;+ __m128i b0, b1;+ __m128i t0, t1;+#if defined(HAVE_SSSE3) && !defined(HAVE_XOP)+ const __m128i r16 = _mm_setr_epi8( 2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9 );+ const __m128i r24 = _mm_setr_epi8( 3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10 );+#endif+#if defined(HAVE_SSE41)+ const __m128i m0 = LOADU( block + 00 );+ const __m128i m1 = LOADU( block + 16 );+ const __m128i m2 = LOADU( block + 32 );+ const __m128i m3 = LOADU( block + 48 );+ const __m128i m4 = LOADU( block + 64 );+ const __m128i m5 = LOADU( block + 80 );+ const __m128i m6 = LOADU( block + 96 );+ const __m128i m7 = LOADU( block + 112 );+#else+ const uint64_t m0 = ( ( uint64_t * )block )[ 0];+ const uint64_t m1 = ( ( uint64_t * )block )[ 1];+ const uint64_t m2 = ( ( uint64_t * )block )[ 2];+ const uint64_t m3 = ( ( uint64_t * )block )[ 3];+ const uint64_t m4 = ( ( uint64_t * )block )[ 4];+ const uint64_t m5 = ( ( uint64_t * )block )[ 5];+ const uint64_t m6 = ( ( uint64_t * )block )[ 6];+ const uint64_t m7 = ( ( uint64_t * )block )[ 7];+ const uint64_t m8 = ( ( uint64_t * )block )[ 8];+ const uint64_t m9 = ( ( uint64_t * )block )[ 9];+ const uint64_t m10 = ( ( uint64_t * )block )[10];+ const uint64_t m11 = ( ( uint64_t * )block )[11];+ const uint64_t m12 = ( ( uint64_t * )block )[12];+ const uint64_t m13 = ( ( uint64_t * )block )[13];+ const uint64_t m14 = ( ( uint64_t * )block )[14];+ const uint64_t m15 = ( ( uint64_t * )block )[15];+#endif+ row1l = LOADU( &S->h[0] );+ row1h = LOADU( &S->h[2] );+ row2l = LOADU( &S->h[4] );+ row2h = LOADU( &S->h[6] );+ row3l = LOADU( &blake2b_IV[0] );+ row3h = LOADU( &blake2b_IV[2] );+ row4l = _mm_xor_si128( LOADU( &blake2b_IV[4] ), LOADU( &S->t[0] ) );+ row4h = _mm_xor_si128( LOADU( &blake2b_IV[6] ), LOADU( &S->f[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 );+ row1l = _mm_xor_si128( row3l, row1l );+ row1h = _mm_xor_si128( row3h, row1h );+ STOREU( &S->h[0], _mm_xor_si128( LOADU( &S->h[0] ), row1l ) );+ STOREU( &S->h[2], _mm_xor_si128( LOADU( &S->h[2] ), row1h ) );+ row2l = _mm_xor_si128( row4l, row2l );+ row2h = _mm_xor_si128( row4h, row2h );+ STOREU( &S->h[4], _mm_xor_si128( LOADU( &S->h[4] ), row2l ) );+ STOREU( &S->h[6], _mm_xor_si128( LOADU( &S->h[6] ), row2h ) );+ return 0;+}+++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;+}+++int blake2b_final( blake2b_state *S, uint8_t *out, uint8_t outlen )+{+ 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 );+ memcpy( out, &S->h[0], outlen );+ return 0;+}+++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 && inlen > 0 ) return -1;++ if ( NULL == out ) return -1;++ if( NULL == key && keylen > 0 ) return -1;++ if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;++ if( keylen > BLAKE2B_KEYBYTES ) return -1;++ if( keylen )+ {+ 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(SUPERCOP)+int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )+{+ return blake2b( out, in, NULL, BLAKE2B_OUTBYTES, inlen, 0 );+}+#endif++#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+
+ cbits/blake2bp.c view
@@ -0,0 +1,298 @@+/*+ BLAKE2 reference source code package - optimized 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 <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <stdint.h>++#if defined(_OPENMP)+#include <omp.h>+#endif++#include "blake2.h"+#include "blake2-impl.h"++#define PARALLELISM_DEGREE 4++static inline int blake2bp_init_leaf( blake2b_state *S, uint8_t outlen, uint8_t keylen, uint64_t offset )+{+ blake2b_param P[1];+ P->digest_length = outlen;+ P->key_length = keylen;+ P->fanout = PARALLELISM_DEGREE;+ P->depth = 2;+ P->leaf_length = 0;+ P->node_offset = offset;+ P->node_depth = 0;+ P->inner_length = BLAKE2B_OUTBYTES;+ 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 );+}++static inline int blake2bp_init_root( blake2b_state *S, uint8_t outlen, uint8_t keylen )+{+ blake2b_param P[1];+ P->digest_length = outlen;+ P->key_length = keylen;+ P->fanout = PARALLELISM_DEGREE;+ P->depth = 2;+ P->leaf_length = 0;+ P->node_offset = 0;+ P->node_depth = 1;+ P->inner_length = BLAKE2B_OUTBYTES;+ 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 blake2bp_init( blake2bp_state *S, const uint8_t outlen )+{+ if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;++ memset( S->buf, 0, sizeof( S->buf ) );+ S->buflen = 0;++ if( blake2bp_init_root( S->R, outlen, 0 ) < 0 )+ return -1;++ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )+ if( blake2bp_init_leaf( S->S[i], outlen, 0, i ) < 0 ) return -1;++ S->R->last_node = 1;+ S->S[PARALLELISM_DEGREE - 1]->last_node = 1;+ return 0;+}++int blake2bp_init_key( blake2bp_state *S, const uint8_t outlen, const void *key, const uint8_t keylen )+{+ if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;++ if( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;++ memset( S->buf, 0, sizeof( S->buf ) );+ S->buflen = 0;++ if( blake2bp_init_root( S->R, outlen, keylen ) < 0 )+ return -1;++ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )+ if( blake2bp_init_leaf( S->S[i], outlen, keylen, i ) < 0 ) return -1;++ S->R->last_node = 1;+ S->S[PARALLELISM_DEGREE - 1]->last_node = 1;+ {+ uint8_t block[BLAKE2B_BLOCKBYTES];+ memset( block, 0, BLAKE2B_BLOCKBYTES );+ memcpy( block, key, keylen );++ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )+ blake2b_update( S->S[i], block, BLAKE2B_BLOCKBYTES );++ secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */+ }+ return 0;+}+++int blake2bp_update( blake2bp_state *S, const uint8_t *in, uint64_t inlen )+{+ size_t left = S->buflen;+ size_t fill = sizeof( S->buf ) - left;++ if( left && inlen >= fill )+ {+ memcpy( S->buf + left, in, fill );++ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )+ blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES );++ in += fill;+ inlen -= fill;+ left = 0;+ }++#if defined(_OPENMP)+ #pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE)+#else++ for( size_t id__ = 0; id__ < PARALLELISM_DEGREE; ++id__ )+#endif+ {+#if defined(_OPENMP)+ size_t id__ = omp_get_thread_num();+#endif+ uint64_t inlen__ = inlen;+ const uint8_t *in__ = ( const uint8_t * )in;+ in__ += id__ * BLAKE2B_BLOCKBYTES;++ while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES )+ {+ blake2b_update( S->S[id__], in__, BLAKE2B_BLOCKBYTES );+ in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;+ inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;+ }+ }++ in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES );+ inlen %= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;++ if( inlen > 0 )+ memcpy( S->buf + left, in, inlen );++ S->buflen = left + inlen;+ return 0;+}++++int blake2bp_final( blake2bp_state *S, uint8_t *out, const uint8_t outlen )+{+ uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES];++ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )+ {+ if( S->buflen > i * BLAKE2B_BLOCKBYTES )+ {+ size_t left = S->buflen - i * BLAKE2B_BLOCKBYTES;++ if( left > BLAKE2B_BLOCKBYTES ) left = BLAKE2B_BLOCKBYTES;++ blake2b_update( S->S[i], S->buf + i * BLAKE2B_BLOCKBYTES, left );+ }++ blake2b_final( S->S[i], hash[i], BLAKE2B_OUTBYTES );+ }++ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )+ blake2b_update( S->R, hash[i], BLAKE2B_OUTBYTES );++ return blake2b_final( S->R, out, outlen );+}++int blake2bp( uint8_t *out, const void *in, const void *key, uint8_t outlen, uint64_t inlen, uint8_t keylen )+{+ uint8_t hash[PARALLELISM_DEGREE][BLAKE2B_OUTBYTES];+ blake2b_state S[PARALLELISM_DEGREE][1];+ blake2b_state FS[1];++ /* Verify parameters */+ if ( NULL == in && inlen > 0 ) return -1;++ if ( NULL == out ) return -1;++ if( NULL == key && keylen > 0 ) return -1;++ if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;++ if( keylen > BLAKE2B_KEYBYTES ) return -1;++ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )+ if( blake2bp_init_leaf( S[i], outlen, keylen, i ) < 0 ) return -1;++ S[PARALLELISM_DEGREE - 1]->last_node = 1; // mark last node++ if( keylen > 0 )+ {+ uint8_t block[BLAKE2B_BLOCKBYTES];+ memset( block, 0, BLAKE2B_BLOCKBYTES );+ memcpy( block, key, keylen );++ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )+ blake2b_update( S[i], block, BLAKE2B_BLOCKBYTES );++ secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */+ }++#if defined(_OPENMP)+ #pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE)+#else++ for( size_t id__ = 0; id__ < PARALLELISM_DEGREE; ++id__ )+#endif+ {+#if defined(_OPENMP)+ size_t id__ = omp_get_thread_num();+#endif+ uint64_t inlen__ = inlen;+ const uint8_t *in__ = ( const uint8_t * )in;+ in__ += id__ * BLAKE2B_BLOCKBYTES;++ while( inlen__ >= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES )+ {+ blake2b_update( S[id__], in__, BLAKE2B_BLOCKBYTES );+ in__ += PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;+ inlen__ -= PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;+ }++ if( inlen__ > id__ * BLAKE2B_BLOCKBYTES )+ {+ const size_t left = inlen__ - id__ * BLAKE2B_BLOCKBYTES;+ const size_t len = left <= BLAKE2B_BLOCKBYTES ? left : BLAKE2B_BLOCKBYTES;+ blake2b_update( S[id__], in__, len );+ }++ blake2b_final( S[id__], hash[id__], BLAKE2B_OUTBYTES );+ }++ if( blake2bp_init_root( FS, outlen, keylen ) < 0 )+ return -1;++ FS->last_node = 1; // Mark as last node++ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )+ blake2b_update( FS, hash[i], BLAKE2B_OUTBYTES );++ return blake2b_final( FS, out, outlen );+}+++#if defined(BLAKE2BP_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];+ //blake2bp( hash, buf, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES );+ blake2bp_state S[1];+ blake2bp_init_key( S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES );+ blake2bp_update( S, buf, i );+ blake2bp_final( S, hash, BLAKE2B_OUTBYTES );++ if( 0 != memcmp( hash, blake2bp_keyed_kat[i], BLAKE2B_OUTBYTES ) )+ {+ puts( "error" );+ return -1;+ }+ }++ puts( "ok" );+ return 0;+}+#endif+
+ cbits/blake2s.c view
@@ -0,0 +1,422 @@+/*+ BLAKE2 reference source code package - optimized 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"++#include "blake2-config.h"+++#include <emmintrin.h>+#if defined(HAVE_SSSE3)+#include <tmmintrin.h>+#endif+#if defined(HAVE_SSE41)+#include <smmintrin.h>+#endif+#if defined(HAVE_AVX)+#include <immintrin.h>+#endif+#if defined(HAVE_XOP)+#include <x86intrin.h>+#endif++#include "blake2s-round.h"++static const uint32_t blake2s_IV[8] =+{+ 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,+ 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL+};++static const uint8_t blake2s_sigma[10][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 } ,+};+++/* Some helper functions, not necessarily useful */+static inline int blake2s_set_lastnode( blake2s_state *S )+{+ S->f[1] = -1;+ return 0;+}++static inline int blake2s_clear_lastnode( blake2s_state *S )+{+ S->f[1] = 0;+ return 0;+}++static inline int blake2s_set_lastblock( blake2s_state *S )+{+ if( S->last_node ) blake2s_set_lastnode( S );++ S->f[0] = -1;+ return 0;+}++static inline int blake2s_clear_lastblock( blake2s_state *S )+{+ if( S->last_node ) blake2s_clear_lastnode( S );++ S->f[0] = 0;+ return 0;+}++static inline int blake2s_increment_counter( blake2s_state *S, const uint32_t inc )+{+ uint64_t t = ( ( uint64_t )S->t[1] << 32 ) | S->t[0];+ t += inc;+ S->t[0] = ( uint32_t )( t >> 0 );+ S->t[1] = ( uint32_t )( t >> 32 );+ return 0;+}+++// Parameter-related functions+static inline int blake2s_param_set_digest_length( blake2s_param *P, const uint8_t digest_length )+{+ P->digest_length = digest_length;+ return 0;+}++static inline int blake2s_param_set_fanout( blake2s_param *P, const uint8_t fanout )+{+ P->fanout = fanout;+ return 0;+}++static inline int blake2s_param_set_max_depth( blake2s_param *P, const uint8_t depth )+{+ P->depth = depth;+ return 0;+}++static inline int blake2s_param_set_leaf_length( blake2s_param *P, const uint32_t leaf_length )+{+ P->leaf_length = leaf_length;+ return 0;+}++static inline int blake2s_param_set_node_offset( blake2s_param *P, const uint64_t node_offset )+{+ store48( P->node_offset, node_offset );+ return 0;+}++static inline int blake2s_param_set_node_depth( blake2s_param *P, const uint8_t node_depth )+{+ P->node_depth = node_depth;+ return 0;+}++static inline int blake2s_param_set_inner_length( blake2s_param *P, const uint8_t inner_length )+{+ P->inner_length = inner_length;+ return 0;+}++static inline int blake2s_param_set_salt( blake2s_param *P, const uint8_t salt[BLAKE2S_SALTBYTES] )+{+ memcpy( P->salt, salt, BLAKE2S_SALTBYTES );+ return 0;+}++static inline int blake2s_param_set_personal( blake2s_param *P, const uint8_t personal[BLAKE2S_PERSONALBYTES] )+{+ memcpy( P->personal, personal, BLAKE2S_PERSONALBYTES );+ return 0;+}++static inline int blake2s_init0( blake2s_state *S )+{+ memset( S, 0, sizeof( blake2s_state ) );++ for( int i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i];++ return 0;+}++/* init2 xors IV with input parameter block */+int blake2s_init_param( blake2s_state *S, const blake2s_param *P )+{+ //blake2s_init0( S );+ const uint8_t * v = ( const uint8_t * )( blake2s_IV );+ const uint8_t * p = ( const uint8_t * )( P );+ uint8_t * h = ( uint8_t * )( S->h );+ /* IV XOR ParamBlock */+ memset( S, 0, sizeof( blake2s_state ) );++ for( int i = 0; i < BLAKE2S_OUTBYTES; ++i ) h[i] = v[i] ^ p[i];++ return 0;+}+++/* Some sort of default parameter block initialization, for sequential blake2s */+int blake2s_init( blake2s_state *S, const uint8_t outlen )+{+ /* Move interval verification here? */+ if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;++ const blake2s_param P =+ {+ outlen,+ 0,+ 1,+ 1,+ 0,+ {0},+ 0,+ 0,+ {0},+ {0}+ };+ return blake2s_init_param( S, &P );+}+++int blake2s_init_key( blake2s_state *S, const uint8_t outlen, const void *key, const uint8_t keylen )+{+ /* Move interval verification here? */+ if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;++ if ( ( !key ) || ( !keylen ) || keylen > BLAKE2S_KEYBYTES ) return -1;++ const blake2s_param P =+ {+ outlen,+ keylen,+ 1,+ 1,+ 0,+ {0},+ 0,+ 0,+ {0},+ {0}+ };++ if( blake2s_init_param( S, &P ) < 0 )+ return -1;++ {+ uint8_t block[BLAKE2S_BLOCKBYTES];+ memset( block, 0, BLAKE2S_BLOCKBYTES );+ memcpy( block, key, keylen );+ blake2s_update( S, block, BLAKE2S_BLOCKBYTES );+ secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */+ }+ return 0;+}+++static inline int blake2s_compress( blake2s_state *S, const uint8_t block[BLAKE2S_BLOCKBYTES] )+{+ __m128i row1, row2, row3, row4;+ __m128i buf1, buf2, buf3, buf4;+#if defined(HAVE_SSE41)+ __m128i t0, t1;+#if !defined(HAVE_XOP)+ __m128i t2;+#endif+#endif+ __m128i ff0, ff1;+#if defined(HAVE_SSSE3) && !defined(HAVE_XOP)+ const __m128i r8 = _mm_set_epi8( 12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1 );+ const __m128i r16 = _mm_set_epi8( 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2 );+#endif+#if defined(HAVE_SSE41)+ const __m128i m0 = LOADU( block + 00 );+ const __m128i m1 = LOADU( block + 16 );+ const __m128i m2 = LOADU( block + 32 );+ const __m128i m3 = LOADU( block + 48 );+#else+ const uint32_t m0 = ( ( uint32_t * )block )[ 0];+ const uint32_t m1 = ( ( uint32_t * )block )[ 1];+ const uint32_t m2 = ( ( uint32_t * )block )[ 2];+ const uint32_t m3 = ( ( uint32_t * )block )[ 3];+ const uint32_t m4 = ( ( uint32_t * )block )[ 4];+ const uint32_t m5 = ( ( uint32_t * )block )[ 5];+ const uint32_t m6 = ( ( uint32_t * )block )[ 6];+ const uint32_t m7 = ( ( uint32_t * )block )[ 7];+ const uint32_t m8 = ( ( uint32_t * )block )[ 8];+ const uint32_t m9 = ( ( uint32_t * )block )[ 9];+ const uint32_t m10 = ( ( uint32_t * )block )[10];+ const uint32_t m11 = ( ( uint32_t * )block )[11];+ const uint32_t m12 = ( ( uint32_t * )block )[12];+ const uint32_t m13 = ( ( uint32_t * )block )[13];+ const uint32_t m14 = ( ( uint32_t * )block )[14];+ const uint32_t m15 = ( ( uint32_t * )block )[15];+#endif+ row1 = ff0 = LOADU( &S->h[0] );+ row2 = ff1 = LOADU( &S->h[4] );+ row3 = _mm_setr_epi32( 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A );+ row4 = _mm_xor_si128( _mm_setr_epi32( 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 ), LOADU( &S->t[0] ) );+ ROUND( 0 );+ ROUND( 1 );+ ROUND( 2 );+ ROUND( 3 );+ ROUND( 4 );+ ROUND( 5 );+ ROUND( 6 );+ ROUND( 7 );+ ROUND( 8 );+ ROUND( 9 );+ STOREU( &S->h[0], _mm_xor_si128( ff0, _mm_xor_si128( row1, row3 ) ) );+ STOREU( &S->h[4], _mm_xor_si128( ff1, _mm_xor_si128( row2, row4 ) ) );+ return 0;+}++/* inlen now in bytes */+int blake2s_update( blake2s_state *S, const uint8_t *in, uint64_t inlen )+{+ while( inlen > 0 )+ {+ size_t left = S->buflen;+ size_t fill = 2 * BLAKE2S_BLOCKBYTES - left;++ if( inlen > fill )+ {+ memcpy( S->buf + left, in, fill ); // Fill buffer+ S->buflen += fill;+ blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );+ blake2s_compress( S, S->buf ); // Compress+ memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); // Shift buffer left+ S->buflen -= BLAKE2S_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 blake2s_final( blake2s_state *S, uint8_t *out, uint8_t outlen )+{+ uint8_t buffer[BLAKE2S_OUTBYTES] = {0};++ if( outlen > BLAKE2S_OUTBYTES )+ return -1;++ if( S->buflen > BLAKE2S_BLOCKBYTES )+ {+ blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );+ blake2s_compress( S, S->buf );+ S->buflen -= BLAKE2S_BLOCKBYTES;+ memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, S->buflen );+ }++ blake2s_increment_counter( S, ( uint32_t )S->buflen );+ blake2s_set_lastblock( S );+ memset( S->buf + S->buflen, 0, 2 * BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */+ blake2s_compress( S, S->buf );++ for( int i = 0; i < 8; ++i ) /* Output full hash to temp buffer */+ store32( 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 blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen )+{+ blake2s_state S[1];++ /* Verify parameters */+ if ( NULL == in && inlen > 0 ) return -1;++ if ( NULL == out ) return -1;++ if ( NULL == key && keylen > 0) return -1;++ if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;++ if( keylen > BLAKE2S_KEYBYTES ) return -1;++ if( keylen > 0 )+ {+ if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1;+ }+ else+ {+ if( blake2s_init( S, outlen ) < 0 ) return -1;+ }++ blake2s_update( S, ( const uint8_t * )in, inlen );+ blake2s_final( S, out, outlen );+ return 0;+}++#if defined(SUPERCOP)+int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )+{+ return blake2s( out, in, NULL, BLAKE2S_OUTBYTES, inlen, 0 );+}+#endif++#if defined(BLAKE2S_SELFTEST)+#include <string.h>+#include "blake2-kat.h"+int main( int argc, char **argv )+{+ uint8_t key[BLAKE2S_KEYBYTES];+ uint8_t buf[KAT_LENGTH];++ for( size_t i = 0; i < BLAKE2S_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[BLAKE2S_OUTBYTES];++ if( blake2s( hash, buf, key, BLAKE2S_OUTBYTES, i, BLAKE2S_KEYBYTES ) < 0 ||+ 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) )+ {+ puts( "error" );+ return -1;+ }+ }++ puts( "ok" );+ return 0;+}+#endif++
+ cbits/blake2sp.c view
@@ -0,0 +1,293 @@+/*+ BLAKE2 reference source code package - optimized 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 <stdlib.h>+#include <string.h>+#include <stdio.h>++#if defined(_OPENMP)+#include <omp.h>+#endif++#include "blake2.h"+#include "blake2-impl.h"++#define PARALLELISM_DEGREE 8++static inline int blake2sp_init_leaf( blake2s_state *S, uint8_t outlen, uint8_t keylen, uint64_t offset )+{+ blake2s_param P[1];+ P->digest_length = outlen;+ P->key_length = keylen;+ P->fanout = PARALLELISM_DEGREE;+ P->depth = 2;+ P->leaf_length = 0;+ store48( P->node_offset, offset );+ P->node_depth = 0;+ P->inner_length = BLAKE2S_OUTBYTES;+ memset( P->salt, 0, sizeof( P->salt ) );+ memset( P->personal, 0, sizeof( P->personal ) );+ return blake2s_init_param( S, P );+}++static inline int blake2sp_init_root( blake2s_state *S, uint8_t outlen, uint8_t keylen )+{+ blake2s_param P[1];+ P->digest_length = outlen;+ P->key_length = keylen;+ P->fanout = PARALLELISM_DEGREE;+ P->depth = 2;+ P->leaf_length = 0;+ store48( P->node_offset, 0ULL );+ P->node_depth = 1;+ P->inner_length = BLAKE2S_OUTBYTES;+ memset( P->salt, 0, sizeof( P->salt ) );+ memset( P->personal, 0, sizeof( P->personal ) );+ return blake2s_init_param( S, P );+}+++int blake2sp_init( blake2sp_state *S, const uint8_t outlen )+{+ if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;++ memset( S->buf, 0, sizeof( S->buf ) );+ S->buflen = 0;++ if( blake2sp_init_root( S->R, outlen, 0 ) < 0 )+ return -1;++ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )+ if( blake2sp_init_leaf( S->S[i], outlen, 0, i ) < 0 ) return -1;++ S->R->last_node = 1;+ S->S[PARALLELISM_DEGREE - 1]->last_node = 1;+ return 0;+}++int blake2sp_init_key( blake2sp_state *S, const uint8_t outlen, const void *key, const uint8_t keylen )+{+ if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;++ if( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;++ memset( S->buf, 0, sizeof( S->buf ) );+ S->buflen = 0;++ if( blake2sp_init_root( S->R, outlen, keylen ) < 0 )+ return -1;++ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )+ if( blake2sp_init_leaf( S->S[i], outlen, keylen, i ) < 0 ) return -1;++ S->R->last_node = 1;+ S->S[PARALLELISM_DEGREE - 1]->last_node = 1;+ {+ uint8_t block[BLAKE2S_BLOCKBYTES];+ memset( block, 0, BLAKE2S_BLOCKBYTES );+ memcpy( block, key, keylen );++ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )+ blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES );++ secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */+ }+ return 0;+}+++int blake2sp_update( blake2sp_state *S, const uint8_t *in, uint64_t inlen )+{+ size_t left = S->buflen;+ size_t fill = sizeof( S->buf ) - left;++ if( left && inlen >= fill )+ {+ memcpy( S->buf + left, in, fill );++ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )+ blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );++ in += fill;+ inlen -= fill;+ left = 0;+ }++#if defined(_OPENMP)+ #pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE)+#else++ for( size_t id__ = 0; id__ < PARALLELISM_DEGREE; ++id__ )+#endif+ {+#if defined(_OPENMP)+ size_t id__ = omp_get_thread_num();+#endif+ uint64_t inlen__ = inlen;+ const uint8_t *in__ = ( const uint8_t * )in;+ in__ += id__ * BLAKE2S_BLOCKBYTES;++ while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )+ {+ blake2s_update( S->S[id__], in__, BLAKE2S_BLOCKBYTES );+ in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;+ inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;+ }+ }++ in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );+ inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;++ if( inlen > 0 )+ memcpy( S->buf + left, in, inlen );++ S->buflen = left + inlen;+ return 0;+}+++int blake2sp_final( blake2sp_state *S, uint8_t *out, const uint8_t outlen )+{+ uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];++ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )+ {+ if( S->buflen > i * BLAKE2S_BLOCKBYTES )+ {+ size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES;++ if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;++ blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );+ }++ blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES );+ }++ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )+ blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES );++ return blake2s_final( S->R, out, outlen );+}+++int blake2sp( uint8_t *out, const void *in, const void *key, uint8_t outlen, uint64_t inlen, uint8_t keylen )+{+ uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];+ blake2s_state S[PARALLELISM_DEGREE][1];+ blake2s_state FS[1];++ /* Verify parameters */+ if ( NULL == in && inlen > 0 ) return -1;++ if ( NULL == out ) return -1;++ if ( NULL == key && keylen > 0) return -1;++ if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;++ if( keylen > BLAKE2S_KEYBYTES ) return -1;++ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )+ if( blake2sp_init_leaf( S[i], outlen, keylen, i ) < 0 ) return -1;++ S[PARALLELISM_DEGREE - 1]->last_node = 1; // mark last node++ if( keylen > 0 )+ {+ uint8_t block[BLAKE2S_BLOCKBYTES];+ memset( block, 0, BLAKE2S_BLOCKBYTES );+ memcpy( block, key, keylen );++ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )+ blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES );++ secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */+ }++#if defined(_OPENMP)+ #pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE)+#else++ for( size_t id__ = 0; id__ < PARALLELISM_DEGREE; ++id__ )+#endif+ {+#if defined(_OPENMP)+ size_t id__ = omp_get_thread_num();+#endif+ uint64_t inlen__ = inlen;+ const uint8_t *in__ = ( const uint8_t * )in;+ in__ += id__ * BLAKE2S_BLOCKBYTES;++ while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )+ {+ blake2s_update( S[id__], in__, BLAKE2S_BLOCKBYTES );+ in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;+ inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;+ }++ if( inlen__ > id__ * BLAKE2S_BLOCKBYTES )+ {+ const size_t left = inlen__ - id__ * BLAKE2S_BLOCKBYTES;+ const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES;+ blake2s_update( S[id__], in__, len );+ }++ blake2s_final( S[id__], hash[id__], BLAKE2S_OUTBYTES );+ }++ if( blake2sp_init_root( FS, outlen, keylen ) < 0 )+ return -1;++ FS->last_node = 1;++ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )+ blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES );++ return blake2s_final( FS, out, outlen );+}++#if defined(BLAKE2SP_SELFTEST)+#include <string.h>+#include "blake2-kat.h"+int main( int argc, char **argv )+{+ uint8_t key[BLAKE2S_KEYBYTES];+ uint8_t buf[KAT_LENGTH];++ for( size_t i = 0; i < BLAKE2S_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[BLAKE2S_OUTBYTES];+ blake2sp( hash, buf, key, BLAKE2S_OUTBYTES, i, BLAKE2S_KEYBYTES );++ if( 0 != memcmp( hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES ) )+ {+ puts( "error" );+ return -1;+ }+ }++ puts( "ok" );+ return 0;+}+#endif++++
+ changelog.md view
@@ -0,0 +1,3 @@+# 0.1.0++* First version.
+ include/blake2-config.h view
@@ -0,0 +1,72 @@+/*+ BLAKE2 reference source code package - optimized 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_CONFIG_H__+#define __BLAKE2_CONFIG_H__++// These don't work everywhere+#if defined(__SSE2__)+#define HAVE_SSE2+#endif++#if defined(__SSSE3__)+#define HAVE_SSSE3+#endif++#if defined(__SSE4_1__)+#define HAVE_SSE41+#endif++#if defined(__AVX__)+#define HAVE_AVX+#endif++#if defined(__XOP__)+#define HAVE_XOP+#endif+++#ifdef HAVE_AVX2+#ifndef HAVE_AVX+#define HAVE_AVX+#endif+#endif++#ifdef HAVE_XOP+#ifndef HAVE_AVX+#define HAVE_AVX+#endif+#endif++#ifdef HAVE_AVX+#ifndef HAVE_SSE41+#define HAVE_SSE41+#endif+#endif++#ifdef HAVE_SSE41+#ifndef HAVE_SSSE3+#define HAVE_SSSE3+#endif+#endif++#ifdef HAVE_SSSE3+#define HAVE_SSE2+#endif++#if !defined(HAVE_SSE2)+#error "This code requires at least SSE2."+#endif++#endif+
+ include/blake2-impl.h view
@@ -0,0 +1,136 @@+/*+ BLAKE2 reference source code package - optimized 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 <stdint.h>++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+
+ include/blake2.h view
@@ -0,0 +1,150 @@+/*+ BLAKE2 reference source code package - optimized 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>++#if defined(__cplusplus)+extern "C" {+#endif++ enum blake2s_constant+ {+ BLAKE2S_BLOCKBYTES = 64,+ BLAKE2S_OUTBYTES = 32,+ BLAKE2S_KEYBYTES = 32,+ BLAKE2S_SALTBYTES = 8,+ BLAKE2S_PERSONALBYTES = 8+ };++ enum blake2b_constant+ {+ BLAKE2B_BLOCKBYTES = 128,+ BLAKE2B_OUTBYTES = 64,+ BLAKE2B_KEYBYTES = 64,+ BLAKE2B_SALTBYTES = 16,+ BLAKE2B_PERSONALBYTES = 16+ };++#pragma pack(push, 1)+ typedef struct __blake2s_param+ {+ uint8_t digest_length; // 1+ uint8_t key_length; // 2+ uint8_t fanout; // 3+ uint8_t depth; // 4+ uint32_t leaf_length; // 8+ uint8_t node_offset[6];// 14+ uint8_t node_depth; // 15+ uint8_t inner_length; // 16+ // uint8_t reserved[0];+ uint8_t salt[BLAKE2S_SALTBYTES]; // 24+ uint8_t personal[BLAKE2S_PERSONALBYTES]; // 32+ } blake2s_param;++ typedef struct __blake2s_state+ {+ uint32_t h[8];+ uint32_t t[2];+ uint32_t f[2];+ uint8_t buf[2 * BLAKE2S_BLOCKBYTES];+ size_t buflen;+ uint8_t last_node;+ } blake2s_state;++ 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;++ 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;++ typedef struct __blake2sp_state+ {+ blake2s_state S[8][1];+ blake2s_state R[1];+ uint8_t buf[8 * BLAKE2S_BLOCKBYTES];+ size_t buflen;+ } blake2sp_state;++ typedef struct __blake2bp_state+ {+ blake2b_state S[4][1];+ blake2b_state R[1];+ uint8_t buf[4 * BLAKE2B_BLOCKBYTES];+ size_t buflen;+ } blake2bp_state;+#pragma pack(pop)++ // Streaming API+ int blake2s_init( blake2s_state *S, const uint8_t outlen );+ int blake2s_init_key( blake2s_state *S, const uint8_t outlen, const void *key, const uint8_t keylen );+ int blake2s_init_param( blake2s_state *S, const blake2s_param *P );+ int blake2s_update( blake2s_state *S, const uint8_t *in, uint64_t inlen );+ int blake2s_final( blake2s_state *S, uint8_t *out, uint8_t outlen );++ 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 blake2sp_init( blake2sp_state *S, const uint8_t outlen );+ int blake2sp_init_key( blake2sp_state *S, const uint8_t outlen, const void *key, const uint8_t keylen );+ int blake2sp_update( blake2sp_state *S, const uint8_t *in, uint64_t inlen );+ int blake2sp_final( blake2sp_state *S, uint8_t *out, uint8_t outlen );++ int blake2bp_init( blake2bp_state *S, const uint8_t outlen );+ int blake2bp_init_key( blake2bp_state *S, const uint8_t outlen, const void *key, const uint8_t keylen );+ int blake2bp_update( blake2bp_state *S, const uint8_t *in, uint64_t inlen );+ int blake2bp_final( blake2bp_state *S, uint8_t *out, uint8_t outlen );++ // Simple API+ int blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen );+ int blake2b( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen );++ int blake2sp( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen );+ int blake2bp( 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+
+ include/blake2b-load-sse2.h view
@@ -0,0 +1,68 @@+/*+ BLAKE2 reference source code package - optimized 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 __BLAKE2B_LOAD_SSE2_H__+#define __BLAKE2B_LOAD_SSE2_H__++#define LOAD_MSG_0_1(b0, b1) b0 = _mm_set_epi64x(m2, m0); b1 = _mm_set_epi64x(m6, m4)+#define LOAD_MSG_0_2(b0, b1) b0 = _mm_set_epi64x(m3, m1); b1 = _mm_set_epi64x(m7, m5)+#define LOAD_MSG_0_3(b0, b1) b0 = _mm_set_epi64x(m10, m8); b1 = _mm_set_epi64x(m14, m12)+#define LOAD_MSG_0_4(b0, b1) b0 = _mm_set_epi64x(m11, m9); b1 = _mm_set_epi64x(m15, m13)+#define LOAD_MSG_1_1(b0, b1) b0 = _mm_set_epi64x(m4, m14); b1 = _mm_set_epi64x(m13, m9)+#define LOAD_MSG_1_2(b0, b1) b0 = _mm_set_epi64x(m8, m10); b1 = _mm_set_epi64x(m6, m15)+#define LOAD_MSG_1_3(b0, b1) b0 = _mm_set_epi64x(m0, m1); b1 = _mm_set_epi64x(m5, m11)+#define LOAD_MSG_1_4(b0, b1) b0 = _mm_set_epi64x(m2, m12); b1 = _mm_set_epi64x(m3, m7)+#define LOAD_MSG_2_1(b0, b1) b0 = _mm_set_epi64x(m12, m11); b1 = _mm_set_epi64x(m15, m5)+#define LOAD_MSG_2_2(b0, b1) b0 = _mm_set_epi64x(m0, m8); b1 = _mm_set_epi64x(m13, m2)+#define LOAD_MSG_2_3(b0, b1) b0 = _mm_set_epi64x(m3, m10); b1 = _mm_set_epi64x(m9, m7)+#define LOAD_MSG_2_4(b0, b1) b0 = _mm_set_epi64x(m6, m14); b1 = _mm_set_epi64x(m4, m1)+#define LOAD_MSG_3_1(b0, b1) b0 = _mm_set_epi64x(m3, m7); b1 = _mm_set_epi64x(m11, m13)+#define LOAD_MSG_3_2(b0, b1) b0 = _mm_set_epi64x(m1, m9); b1 = _mm_set_epi64x(m14, m12)+#define LOAD_MSG_3_3(b0, b1) b0 = _mm_set_epi64x(m5, m2); b1 = _mm_set_epi64x(m15, m4)+#define LOAD_MSG_3_4(b0, b1) b0 = _mm_set_epi64x(m10, m6); b1 = _mm_set_epi64x(m8, m0)+#define LOAD_MSG_4_1(b0, b1) b0 = _mm_set_epi64x(m5, m9); b1 = _mm_set_epi64x(m10, m2)+#define LOAD_MSG_4_2(b0, b1) b0 = _mm_set_epi64x(m7, m0); b1 = _mm_set_epi64x(m15, m4)+#define LOAD_MSG_4_3(b0, b1) b0 = _mm_set_epi64x(m11, m14); b1 = _mm_set_epi64x(m3, m6)+#define LOAD_MSG_4_4(b0, b1) b0 = _mm_set_epi64x(m12, m1); b1 = _mm_set_epi64x(m13, m8)+#define LOAD_MSG_5_1(b0, b1) b0 = _mm_set_epi64x(m6, m2); b1 = _mm_set_epi64x(m8, m0)+#define LOAD_MSG_5_2(b0, b1) b0 = _mm_set_epi64x(m10, m12); b1 = _mm_set_epi64x(m3, m11)+#define LOAD_MSG_5_3(b0, b1) b0 = _mm_set_epi64x(m7, m4); b1 = _mm_set_epi64x(m1, m15)+#define LOAD_MSG_5_4(b0, b1) b0 = _mm_set_epi64x(m5, m13); b1 = _mm_set_epi64x(m9, m14)+#define LOAD_MSG_6_1(b0, b1) b0 = _mm_set_epi64x(m1, m12); b1 = _mm_set_epi64x(m4, m14)+#define LOAD_MSG_6_2(b0, b1) b0 = _mm_set_epi64x(m15, m5); b1 = _mm_set_epi64x(m10, m13)+#define LOAD_MSG_6_3(b0, b1) b0 = _mm_set_epi64x(m6, m0); b1 = _mm_set_epi64x(m8, m9)+#define LOAD_MSG_6_4(b0, b1) b0 = _mm_set_epi64x(m3, m7); b1 = _mm_set_epi64x(m11, m2)+#define LOAD_MSG_7_1(b0, b1) b0 = _mm_set_epi64x(m7, m13); b1 = _mm_set_epi64x(m3, m12)+#define LOAD_MSG_7_2(b0, b1) b0 = _mm_set_epi64x(m14, m11); b1 = _mm_set_epi64x(m9, m1)+#define LOAD_MSG_7_3(b0, b1) b0 = _mm_set_epi64x(m15, m5); b1 = _mm_set_epi64x(m2, m8)+#define LOAD_MSG_7_4(b0, b1) b0 = _mm_set_epi64x(m4, m0); b1 = _mm_set_epi64x(m10, m6)+#define LOAD_MSG_8_1(b0, b1) b0 = _mm_set_epi64x(m14, m6); b1 = _mm_set_epi64x(m0, m11)+#define LOAD_MSG_8_2(b0, b1) b0 = _mm_set_epi64x(m9, m15); b1 = _mm_set_epi64x(m8, m3)+#define LOAD_MSG_8_3(b0, b1) b0 = _mm_set_epi64x(m13, m12); b1 = _mm_set_epi64x(m10, m1)+#define LOAD_MSG_8_4(b0, b1) b0 = _mm_set_epi64x(m7, m2); b1 = _mm_set_epi64x(m5, m4)+#define LOAD_MSG_9_1(b0, b1) b0 = _mm_set_epi64x(m8, m10); b1 = _mm_set_epi64x(m1, m7)+#define LOAD_MSG_9_2(b0, b1) b0 = _mm_set_epi64x(m4, m2); b1 = _mm_set_epi64x(m5, m6)+#define LOAD_MSG_9_3(b0, b1) b0 = _mm_set_epi64x(m9, m15); b1 = _mm_set_epi64x(m13, m3)+#define LOAD_MSG_9_4(b0, b1) b0 = _mm_set_epi64x(m14, m11); b1 = _mm_set_epi64x(m0, m12)+#define LOAD_MSG_10_1(b0, b1) b0 = _mm_set_epi64x(m2, m0); b1 = _mm_set_epi64x(m6, m4)+#define LOAD_MSG_10_2(b0, b1) b0 = _mm_set_epi64x(m3, m1); b1 = _mm_set_epi64x(m7, m5)+#define LOAD_MSG_10_3(b0, b1) b0 = _mm_set_epi64x(m10, m8); b1 = _mm_set_epi64x(m14, m12)+#define LOAD_MSG_10_4(b0, b1) b0 = _mm_set_epi64x(m11, m9); b1 = _mm_set_epi64x(m15, m13)+#define LOAD_MSG_11_1(b0, b1) b0 = _mm_set_epi64x(m4, m14); b1 = _mm_set_epi64x(m13, m9)+#define LOAD_MSG_11_2(b0, b1) b0 = _mm_set_epi64x(m8, m10); b1 = _mm_set_epi64x(m6, m15)+#define LOAD_MSG_11_3(b0, b1) b0 = _mm_set_epi64x(m0, m1); b1 = _mm_set_epi64x(m5, m11)+#define LOAD_MSG_11_4(b0, b1) b0 = _mm_set_epi64x(m2, m12); b1 = _mm_set_epi64x(m3, m7)+++#endif+
+ include/blake2b-load-sse41.h view
@@ -0,0 +1,402 @@+/*+ BLAKE2 reference source code package - optimized 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 __BLAKE2B_LOAD_SSE41_H__+#define __BLAKE2B_LOAD_SSE41_H__++#define LOAD_MSG_0_1(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m0, m1); \+b1 = _mm_unpacklo_epi64(m2, m3); \+} while(0)+++#define LOAD_MSG_0_2(b0, b1) \+do \+{ \+b0 = _mm_unpackhi_epi64(m0, m1); \+b1 = _mm_unpackhi_epi64(m2, m3); \+} while(0)+++#define LOAD_MSG_0_3(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m4, m5); \+b1 = _mm_unpacklo_epi64(m6, m7); \+} while(0)+++#define LOAD_MSG_0_4(b0, b1) \+do \+{ \+b0 = _mm_unpackhi_epi64(m4, m5); \+b1 = _mm_unpackhi_epi64(m6, m7); \+} while(0)+++#define LOAD_MSG_1_1(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m7, m2); \+b1 = _mm_unpackhi_epi64(m4, m6); \+} while(0)+++#define LOAD_MSG_1_2(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m5, m4); \+b1 = _mm_alignr_epi8(m3, m7, 8); \+} while(0)+++#define LOAD_MSG_1_3(b0, b1) \+do \+{ \+b0 = _mm_shuffle_epi32(m0, _MM_SHUFFLE(1,0,3,2)); \+b1 = _mm_unpackhi_epi64(m5, m2); \+} while(0)+++#define LOAD_MSG_1_4(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m6, m1); \+b1 = _mm_unpackhi_epi64(m3, m1); \+} while(0)+++#define LOAD_MSG_2_1(b0, b1) \+do \+{ \+b0 = _mm_alignr_epi8(m6, m5, 8); \+b1 = _mm_unpackhi_epi64(m2, m7); \+} while(0)+++#define LOAD_MSG_2_2(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m4, m0); \+b1 = _mm_blend_epi16(m1, m6, 0xF0); \+} while(0)+++#define LOAD_MSG_2_3(b0, b1) \+do \+{ \+b0 = _mm_blend_epi16(m5, m1, 0xF0); \+b1 = _mm_unpackhi_epi64(m3, m4); \+} while(0)+++#define LOAD_MSG_2_4(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m7, m3); \+b1 = _mm_alignr_epi8(m2, m0, 8); \+} while(0)+++#define LOAD_MSG_3_1(b0, b1) \+do \+{ \+b0 = _mm_unpackhi_epi64(m3, m1); \+b1 = _mm_unpackhi_epi64(m6, m5); \+} while(0)+++#define LOAD_MSG_3_2(b0, b1) \+do \+{ \+b0 = _mm_unpackhi_epi64(m4, m0); \+b1 = _mm_unpacklo_epi64(m6, m7); \+} while(0)+++#define LOAD_MSG_3_3(b0, b1) \+do \+{ \+b0 = _mm_blend_epi16(m1, m2, 0xF0); \+b1 = _mm_blend_epi16(m2, m7, 0xF0); \+} while(0)+++#define LOAD_MSG_3_4(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m3, m5); \+b1 = _mm_unpacklo_epi64(m0, m4); \+} while(0)+++#define LOAD_MSG_4_1(b0, b1) \+do \+{ \+b0 = _mm_unpackhi_epi64(m4, m2); \+b1 = _mm_unpacklo_epi64(m1, m5); \+} while(0)+++#define LOAD_MSG_4_2(b0, b1) \+do \+{ \+b0 = _mm_blend_epi16(m0, m3, 0xF0); \+b1 = _mm_blend_epi16(m2, m7, 0xF0); \+} while(0)+++#define LOAD_MSG_4_3(b0, b1) \+do \+{ \+b0 = _mm_blend_epi16(m7, m5, 0xF0); \+b1 = _mm_blend_epi16(m3, m1, 0xF0); \+} while(0)+++#define LOAD_MSG_4_4(b0, b1) \+do \+{ \+b0 = _mm_alignr_epi8(m6, m0, 8); \+b1 = _mm_blend_epi16(m4, m6, 0xF0); \+} while(0)+++#define LOAD_MSG_5_1(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m1, m3); \+b1 = _mm_unpacklo_epi64(m0, m4); \+} while(0)+++#define LOAD_MSG_5_2(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m6, m5); \+b1 = _mm_unpackhi_epi64(m5, m1); \+} while(0)+++#define LOAD_MSG_5_3(b0, b1) \+do \+{ \+b0 = _mm_blend_epi16(m2, m3, 0xF0); \+b1 = _mm_unpackhi_epi64(m7, m0); \+} while(0)+++#define LOAD_MSG_5_4(b0, b1) \+do \+{ \+b0 = _mm_unpackhi_epi64(m6, m2); \+b1 = _mm_blend_epi16(m7, m4, 0xF0); \+} while(0)+++#define LOAD_MSG_6_1(b0, b1) \+do \+{ \+b0 = _mm_blend_epi16(m6, m0, 0xF0); \+b1 = _mm_unpacklo_epi64(m7, m2); \+} while(0)+++#define LOAD_MSG_6_2(b0, b1) \+do \+{ \+b0 = _mm_unpackhi_epi64(m2, m7); \+b1 = _mm_alignr_epi8(m5, m6, 8); \+} while(0)+++#define LOAD_MSG_6_3(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m0, m3); \+b1 = _mm_shuffle_epi32(m4, _MM_SHUFFLE(1,0,3,2)); \+} while(0)+++#define LOAD_MSG_6_4(b0, b1) \+do \+{ \+b0 = _mm_unpackhi_epi64(m3, m1); \+b1 = _mm_blend_epi16(m1, m5, 0xF0); \+} while(0)+++#define LOAD_MSG_7_1(b0, b1) \+do \+{ \+b0 = _mm_unpackhi_epi64(m6, m3); \+b1 = _mm_blend_epi16(m6, m1, 0xF0); \+} while(0)+++#define LOAD_MSG_7_2(b0, b1) \+do \+{ \+b0 = _mm_alignr_epi8(m7, m5, 8); \+b1 = _mm_unpackhi_epi64(m0, m4); \+} while(0)+++#define LOAD_MSG_7_3(b0, b1) \+do \+{ \+b0 = _mm_unpackhi_epi64(m2, m7); \+b1 = _mm_unpacklo_epi64(m4, m1); \+} while(0)+++#define LOAD_MSG_7_4(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m0, m2); \+b1 = _mm_unpacklo_epi64(m3, m5); \+} while(0)+++#define LOAD_MSG_8_1(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m3, m7); \+b1 = _mm_alignr_epi8(m0, m5, 8); \+} while(0)+++#define LOAD_MSG_8_2(b0, b1) \+do \+{ \+b0 = _mm_unpackhi_epi64(m7, m4); \+b1 = _mm_alignr_epi8(m4, m1, 8); \+} while(0)+++#define LOAD_MSG_8_3(b0, b1) \+do \+{ \+b0 = m6; \+b1 = _mm_alignr_epi8(m5, m0, 8); \+} while(0)+++#define LOAD_MSG_8_4(b0, b1) \+do \+{ \+b0 = _mm_blend_epi16(m1, m3, 0xF0); \+b1 = m2; \+} while(0)+++#define LOAD_MSG_9_1(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m5, m4); \+b1 = _mm_unpackhi_epi64(m3, m0); \+} while(0)+++#define LOAD_MSG_9_2(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m1, m2); \+b1 = _mm_blend_epi16(m3, m2, 0xF0); \+} while(0)+++#define LOAD_MSG_9_3(b0, b1) \+do \+{ \+b0 = _mm_unpackhi_epi64(m7, m4); \+b1 = _mm_unpackhi_epi64(m1, m6); \+} while(0)+++#define LOAD_MSG_9_4(b0, b1) \+do \+{ \+b0 = _mm_alignr_epi8(m7, m5, 8); \+b1 = _mm_unpacklo_epi64(m6, m0); \+} while(0)+++#define LOAD_MSG_10_1(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m0, m1); \+b1 = _mm_unpacklo_epi64(m2, m3); \+} while(0)+++#define LOAD_MSG_10_2(b0, b1) \+do \+{ \+b0 = _mm_unpackhi_epi64(m0, m1); \+b1 = _mm_unpackhi_epi64(m2, m3); \+} while(0)+++#define LOAD_MSG_10_3(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m4, m5); \+b1 = _mm_unpacklo_epi64(m6, m7); \+} while(0)+++#define LOAD_MSG_10_4(b0, b1) \+do \+{ \+b0 = _mm_unpackhi_epi64(m4, m5); \+b1 = _mm_unpackhi_epi64(m6, m7); \+} while(0)+++#define LOAD_MSG_11_1(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m7, m2); \+b1 = _mm_unpackhi_epi64(m4, m6); \+} while(0)+++#define LOAD_MSG_11_2(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m5, m4); \+b1 = _mm_alignr_epi8(m3, m7, 8); \+} while(0)+++#define LOAD_MSG_11_3(b0, b1) \+do \+{ \+b0 = _mm_shuffle_epi32(m0, _MM_SHUFFLE(1,0,3,2)); \+b1 = _mm_unpackhi_epi64(m5, m2); \+} while(0)+++#define LOAD_MSG_11_4(b0, b1) \+do \+{ \+b0 = _mm_unpacklo_epi64(m6, m1); \+b1 = _mm_unpackhi_epi64(m3, m1); \+} while(0)+++#endif+
+ include/blake2b-round.h view
@@ -0,0 +1,157 @@+/*+ BLAKE2 reference source code package - optimized 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 __BLAKE2B_ROUND_H__+#define __BLAKE2B_ROUND_H__++#define LOADU(p) _mm_loadu_si128( (const __m128i *)(p) )+#define STOREU(p,r) _mm_storeu_si128((__m128i *)(p), r)++#define TOF(reg) _mm_castsi128_ps((reg))+#define TOI(reg) _mm_castps_si128((reg))++#define LIKELY(x) __builtin_expect((x),1)+++/* Microarchitecture-specific macros */+#ifndef HAVE_XOP+#ifdef HAVE_SSSE3+#define _mm_roti_epi64(x, c) \+ (-(c) == 32) ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2,3,0,1)) \+ : (-(c) == 24) ? _mm_shuffle_epi8((x), r24) \+ : (-(c) == 16) ? _mm_shuffle_epi8((x), r16) \+ : (-(c) == 63) ? _mm_xor_si128(_mm_srli_epi64((x), -(c)), _mm_add_epi64((x), (x))) \+ : _mm_xor_si128(_mm_srli_epi64((x), -(c)), _mm_slli_epi64((x), 64-(-(c))))+#else+#define _mm_roti_epi64(r, c) _mm_xor_si128(_mm_srli_epi64( (r), -(c) ),_mm_slli_epi64( (r), 64-(-(c)) ))+#endif+#else+/* ... */+#endif++++#define G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \+ row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \+ row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \+ \+ row4l = _mm_xor_si128(row4l, row1l); \+ row4h = _mm_xor_si128(row4h, row1h); \+ \+ row4l = _mm_roti_epi64(row4l, -32); \+ row4h = _mm_roti_epi64(row4h, -32); \+ \+ row3l = _mm_add_epi64(row3l, row4l); \+ row3h = _mm_add_epi64(row3h, row4h); \+ \+ row2l = _mm_xor_si128(row2l, row3l); \+ row2h = _mm_xor_si128(row2h, row3h); \+ \+ row2l = _mm_roti_epi64(row2l, -24); \+ row2h = _mm_roti_epi64(row2h, -24); \+ +#define G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \+ row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \+ row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \+ \+ row4l = _mm_xor_si128(row4l, row1l); \+ row4h = _mm_xor_si128(row4h, row1h); \+ \+ row4l = _mm_roti_epi64(row4l, -16); \+ row4h = _mm_roti_epi64(row4h, -16); \+ \+ row3l = _mm_add_epi64(row3l, row4l); \+ row3h = _mm_add_epi64(row3h, row4h); \+ \+ row2l = _mm_xor_si128(row2l, row3l); \+ row2h = _mm_xor_si128(row2h, row3h); \+ \+ row2l = _mm_roti_epi64(row2l, -63); \+ row2h = _mm_roti_epi64(row2h, -63); \+ +#if defined(HAVE_SSSE3)+#define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \+ t0 = _mm_alignr_epi8(row2h, row2l, 8); \+ t1 = _mm_alignr_epi8(row2l, row2h, 8); \+ row2l = t0; \+ row2h = t1; \+ \+ t0 = row3l; \+ row3l = row3h; \+ row3h = t0; \+ \+ t0 = _mm_alignr_epi8(row4h, row4l, 8); \+ t1 = _mm_alignr_epi8(row4l, row4h, 8); \+ row4l = t1; \+ row4h = t0;++#define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \+ t0 = _mm_alignr_epi8(row2l, row2h, 8); \+ t1 = _mm_alignr_epi8(row2h, row2l, 8); \+ row2l = t0; \+ row2h = t1; \+ \+ t0 = row3l; \+ row3l = row3h; \+ row3h = t0; \+ \+ t0 = _mm_alignr_epi8(row4l, row4h, 8); \+ t1 = _mm_alignr_epi8(row4h, row4l, 8); \+ row4l = t1; \+ row4h = t0;+#else++#define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \+ t0 = row4l;\+ t1 = row2l;\+ row4l = row3l;\+ row3l = row3h;\+ row3h = row4l;\+ row4l = _mm_unpackhi_epi64(row4h, _mm_unpacklo_epi64(t0, t0)); \+ row4h = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(row4h, row4h)); \+ row2l = _mm_unpackhi_epi64(row2l, _mm_unpacklo_epi64(row2h, row2h)); \+ row2h = _mm_unpackhi_epi64(row2h, _mm_unpacklo_epi64(t1, t1))++#define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \+ t0 = row3l;\+ row3l = row3h;\+ row3h = t0;\+ t0 = row2l;\+ t1 = row4l;\+ row2l = _mm_unpackhi_epi64(row2h, _mm_unpacklo_epi64(row2l, row2l)); \+ row2h = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(row2h, row2h)); \+ row4l = _mm_unpackhi_epi64(row4l, _mm_unpacklo_epi64(row4h, row4h)); \+ row4h = _mm_unpackhi_epi64(row4h, _mm_unpacklo_epi64(t1, t1))++#endif++#if defined(HAVE_SSE41)+#include "blake2b-load-sse41.h"+#else+#include "blake2b-load-sse2.h"+#endif++#define ROUND(r) \+ LOAD_MSG_ ##r ##_1(b0, b1); \+ G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \+ LOAD_MSG_ ##r ##_2(b0, b1); \+ G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \+ DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \+ LOAD_MSG_ ##r ##_3(b0, b1); \+ G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \+ LOAD_MSG_ ##r ##_4(b0, b1); \+ G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \+ UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h);++#endif+
+ include/blake2s-load-sse2.h view
@@ -0,0 +1,59 @@+/*+ BLAKE2 reference source code package - optimized 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 __BLAKE2S_LOAD_SSE2_H__+#define __BLAKE2S_LOAD_SSE2_H__++#define LOAD_MSG_0_1(buf) buf = _mm_set_epi32(m6,m4,m2,m0)+#define LOAD_MSG_0_2(buf) buf = _mm_set_epi32(m7,m5,m3,m1)+#define LOAD_MSG_0_3(buf) buf = _mm_set_epi32(m14,m12,m10,m8)+#define LOAD_MSG_0_4(buf) buf = _mm_set_epi32(m15,m13,m11,m9)+#define LOAD_MSG_1_1(buf) buf = _mm_set_epi32(m13,m9,m4,m14)+#define LOAD_MSG_1_2(buf) buf = _mm_set_epi32(m6,m15,m8,m10)+#define LOAD_MSG_1_3(buf) buf = _mm_set_epi32(m5,m11,m0,m1)+#define LOAD_MSG_1_4(buf) buf = _mm_set_epi32(m3,m7,m2,m12)+#define LOAD_MSG_2_1(buf) buf = _mm_set_epi32(m15,m5,m12,m11)+#define LOAD_MSG_2_2(buf) buf = _mm_set_epi32(m13,m2,m0,m8)+#define LOAD_MSG_2_3(buf) buf = _mm_set_epi32(m9,m7,m3,m10)+#define LOAD_MSG_2_4(buf) buf = _mm_set_epi32(m4,m1,m6,m14)+#define LOAD_MSG_3_1(buf) buf = _mm_set_epi32(m11,m13,m3,m7)+#define LOAD_MSG_3_2(buf) buf = _mm_set_epi32(m14,m12,m1,m9)+#define LOAD_MSG_3_3(buf) buf = _mm_set_epi32(m15,m4,m5,m2)+#define LOAD_MSG_3_4(buf) buf = _mm_set_epi32(m8,m0,m10,m6)+#define LOAD_MSG_4_1(buf) buf = _mm_set_epi32(m10,m2,m5,m9)+#define LOAD_MSG_4_2(buf) buf = _mm_set_epi32(m15,m4,m7,m0)+#define LOAD_MSG_4_3(buf) buf = _mm_set_epi32(m3,m6,m11,m14)+#define LOAD_MSG_4_4(buf) buf = _mm_set_epi32(m13,m8,m12,m1)+#define LOAD_MSG_5_1(buf) buf = _mm_set_epi32(m8,m0,m6,m2)+#define LOAD_MSG_5_2(buf) buf = _mm_set_epi32(m3,m11,m10,m12)+#define LOAD_MSG_5_3(buf) buf = _mm_set_epi32(m1,m15,m7,m4)+#define LOAD_MSG_5_4(buf) buf = _mm_set_epi32(m9,m14,m5,m13)+#define LOAD_MSG_6_1(buf) buf = _mm_set_epi32(m4,m14,m1,m12)+#define LOAD_MSG_6_2(buf) buf = _mm_set_epi32(m10,m13,m15,m5)+#define LOAD_MSG_6_3(buf) buf = _mm_set_epi32(m8,m9,m6,m0)+#define LOAD_MSG_6_4(buf) buf = _mm_set_epi32(m11,m2,m3,m7)+#define LOAD_MSG_7_1(buf) buf = _mm_set_epi32(m3,m12,m7,m13)+#define LOAD_MSG_7_2(buf) buf = _mm_set_epi32(m9,m1,m14,m11)+#define LOAD_MSG_7_3(buf) buf = _mm_set_epi32(m2,m8,m15,m5)+#define LOAD_MSG_7_4(buf) buf = _mm_set_epi32(m10,m6,m4,m0)+#define LOAD_MSG_8_1(buf) buf = _mm_set_epi32(m0,m11,m14,m6)+#define LOAD_MSG_8_2(buf) buf = _mm_set_epi32(m8,m3,m9,m15)+#define LOAD_MSG_8_3(buf) buf = _mm_set_epi32(m10,m1,m13,m12)+#define LOAD_MSG_8_4(buf) buf = _mm_set_epi32(m5,m4,m7,m2)+#define LOAD_MSG_9_1(buf) buf = _mm_set_epi32(m1,m7,m8,m10)+#define LOAD_MSG_9_2(buf) buf = _mm_set_epi32(m5,m6,m4,m2)+#define LOAD_MSG_9_3(buf) buf = _mm_set_epi32(m13,m3,m9,m15)+#define LOAD_MSG_9_4(buf) buf = _mm_set_epi32(m0,m12,m14,m11)+++#endif
+ include/blake2s-load-sse41.h view
@@ -0,0 +1,229 @@+/*+ BLAKE2 reference source code package - optimized 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 __BLAKE2S_LOAD_SSE41_H__+#define __BLAKE2S_LOAD_SSE41_H__++#define LOAD_MSG_0_1(buf) \+buf = TOI(_mm_shuffle_ps(TOF(m0), TOF(m1), _MM_SHUFFLE(2,0,2,0)));++#define LOAD_MSG_0_2(buf) \+buf = TOI(_mm_shuffle_ps(TOF(m0), TOF(m1), _MM_SHUFFLE(3,1,3,1)));++#define LOAD_MSG_0_3(buf) \+buf = TOI(_mm_shuffle_ps(TOF(m2), TOF(m3), _MM_SHUFFLE(2,0,2,0)));++#define LOAD_MSG_0_4(buf) \+buf = TOI(_mm_shuffle_ps(TOF(m2), TOF(m3), _MM_SHUFFLE(3,1,3,1)));++#define LOAD_MSG_1_1(buf) \+t0 = _mm_blend_epi16(m1, m2, 0x0C); \+t1 = _mm_slli_si128(m3, 4); \+t2 = _mm_blend_epi16(t0, t1, 0xF0); \+buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,1,0,3));++#define LOAD_MSG_1_2(buf) \+t0 = _mm_shuffle_epi32(m2,_MM_SHUFFLE(0,0,2,0)); \+t1 = _mm_blend_epi16(m1,m3,0xC0); \+t2 = _mm_blend_epi16(t0, t1, 0xF0); \+buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,3,0,1));++#define LOAD_MSG_1_3(buf) \+t0 = _mm_slli_si128(m1, 4); \+t1 = _mm_blend_epi16(m2, t0, 0x30); \+t2 = _mm_blend_epi16(m0, t1, 0xF0); \+buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,3,0,1));++#define LOAD_MSG_1_4(buf) \+t0 = _mm_unpackhi_epi32(m0,m1); \+t1 = _mm_slli_si128(m3, 4); \+t2 = _mm_blend_epi16(t0, t1, 0x0C); \+buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,3,0,1));++#define LOAD_MSG_2_1(buf) \+t0 = _mm_unpackhi_epi32(m2,m3); \+t1 = _mm_blend_epi16(m3,m1,0x0C); \+t2 = _mm_blend_epi16(t0, t1, 0x0F); \+buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(3,1,0,2));++#define LOAD_MSG_2_2(buf) \+t0 = _mm_unpacklo_epi32(m2,m0); \+t1 = _mm_blend_epi16(t0, m0, 0xF0); \+t2 = _mm_slli_si128(m3, 8); \+buf = _mm_blend_epi16(t1, t2, 0xC0);++#define LOAD_MSG_2_3(buf) \+t0 = _mm_blend_epi16(m0, m2, 0x3C); \+t1 = _mm_srli_si128(m1, 12); \+t2 = _mm_blend_epi16(t0,t1,0x03); \+buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(1,0,3,2));++#define LOAD_MSG_2_4(buf) \+t0 = _mm_slli_si128(m3, 4); \+t1 = _mm_blend_epi16(m0, m1, 0x33); \+t2 = _mm_blend_epi16(t1, t0, 0xC0); \+buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(0,1,2,3));++#define LOAD_MSG_3_1(buf) \+t0 = _mm_unpackhi_epi32(m0,m1); \+t1 = _mm_unpackhi_epi32(t0, m2); \+t2 = _mm_blend_epi16(t1, m3, 0x0C); \+buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(3,1,0,2));++#define LOAD_MSG_3_2(buf) \+t0 = _mm_slli_si128(m2, 8); \+t1 = _mm_blend_epi16(m3,m0,0x0C); \+t2 = _mm_blend_epi16(t1, t0, 0xC0); \+buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,0,1,3));++#define LOAD_MSG_3_3(buf) \+t0 = _mm_blend_epi16(m0,m1,0x0F); \+t1 = _mm_blend_epi16(t0, m3, 0xC0); \+buf = _mm_shuffle_epi32(t1, _MM_SHUFFLE(3,0,1,2));++#define LOAD_MSG_3_4(buf) \+t0 = _mm_unpacklo_epi32(m0,m2); \+t1 = _mm_unpackhi_epi32(m1,m2); \+buf = _mm_unpacklo_epi64(t1,t0);++#define LOAD_MSG_4_1(buf) \+t0 = _mm_unpacklo_epi64(m1,m2); \+t1 = _mm_unpackhi_epi64(m0,m2); \+t2 = _mm_blend_epi16(t0,t1,0x33); \+buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,0,1,3));++#define LOAD_MSG_4_2(buf) \+t0 = _mm_unpackhi_epi64(m1,m3); \+t1 = _mm_unpacklo_epi64(m0,m1); \+buf = _mm_blend_epi16(t0,t1,0x33);++#define LOAD_MSG_4_3(buf) \+t0 = _mm_unpackhi_epi64(m3,m1); \+t1 = _mm_unpackhi_epi64(m2,m0); \+buf = _mm_blend_epi16(t1,t0,0x33);++#define LOAD_MSG_4_4(buf) \+t0 = _mm_blend_epi16(m0,m2,0x03); \+t1 = _mm_slli_si128(t0, 8); \+t2 = _mm_blend_epi16(t1,m3,0x0F); \+buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(1,2,0,3));++#define LOAD_MSG_5_1(buf) \+t0 = _mm_unpackhi_epi32(m0,m1); \+t1 = _mm_unpacklo_epi32(m0,m2); \+buf = _mm_unpacklo_epi64(t0,t1);++#define LOAD_MSG_5_2(buf) \+t0 = _mm_srli_si128(m2, 4); \+t1 = _mm_blend_epi16(m0,m3,0x03); \+buf = _mm_blend_epi16(t1,t0,0x3C);++#define LOAD_MSG_5_3(buf) \+t0 = _mm_blend_epi16(m1,m0,0x0C); \+t1 = _mm_srli_si128(m3, 4); \+t2 = _mm_blend_epi16(t0,t1,0x30); \+buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(1,2,3,0));++#define LOAD_MSG_5_4(buf) \+t0 = _mm_unpacklo_epi64(m1,m2); \+t1= _mm_shuffle_epi32(m3, _MM_SHUFFLE(0,2,0,1)); \+buf = _mm_blend_epi16(t0,t1,0x33);++#define LOAD_MSG_6_1(buf) \+t0 = _mm_slli_si128(m1, 12); \+t1 = _mm_blend_epi16(m0,m3,0x33); \+buf = _mm_blend_epi16(t1,t0,0xC0);++#define LOAD_MSG_6_2(buf) \+t0 = _mm_blend_epi16(m3,m2,0x30); \+t1 = _mm_srli_si128(m1, 4); \+t2 = _mm_blend_epi16(t0,t1,0x03); \+buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,1,3,0));++#define LOAD_MSG_6_3(buf) \+t0 = _mm_unpacklo_epi64(m0,m2); \+t1 = _mm_srli_si128(m1, 4); \+buf = _mm_shuffle_epi32(_mm_blend_epi16(t0,t1,0x0C), _MM_SHUFFLE(2,3,1,0));++#define LOAD_MSG_6_4(buf) \+t0 = _mm_unpackhi_epi32(m1,m2); \+t1 = _mm_unpackhi_epi64(m0,t0); \+buf = _mm_shuffle_epi32(t1, _MM_SHUFFLE(3,0,1,2));++#define LOAD_MSG_7_1(buf) \+t0 = _mm_unpackhi_epi32(m0,m1); \+t1 = _mm_blend_epi16(t0,m3,0x0F); \+buf = _mm_shuffle_epi32(t1,_MM_SHUFFLE(2,0,3,1));++#define LOAD_MSG_7_2(buf) \+t0 = _mm_blend_epi16(m2,m3,0x30); \+t1 = _mm_srli_si128(m0,4); \+t2 = _mm_blend_epi16(t0,t1,0x03); \+buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(1,0,2,3));++#define LOAD_MSG_7_3(buf) \+t0 = _mm_unpackhi_epi64(m0,m3); \+t1 = _mm_unpacklo_epi64(m1,m2); \+t2 = _mm_blend_epi16(t0,t1,0x3C); \+buf = _mm_shuffle_epi32(t2,_MM_SHUFFLE(0,2,3,1));++#define LOAD_MSG_7_4(buf) \+t0 = _mm_unpacklo_epi32(m0,m1); \+t1 = _mm_unpackhi_epi32(m1,m2); \+buf = _mm_unpacklo_epi64(t0,t1);++#define LOAD_MSG_8_1(buf) \+t0 = _mm_unpackhi_epi32(m1,m3); \+t1 = _mm_unpacklo_epi64(t0,m0); \+t2 = _mm_blend_epi16(t1,m2,0xC0); \+buf = _mm_shufflehi_epi16(t2,_MM_SHUFFLE(1,0,3,2));++#define LOAD_MSG_8_2(buf) \+t0 = _mm_unpackhi_epi32(m0,m3); \+t1 = _mm_blend_epi16(m2,t0,0xF0); \+buf = _mm_shuffle_epi32(t1,_MM_SHUFFLE(0,2,1,3));++#define LOAD_MSG_8_3(buf) \+t0 = _mm_blend_epi16(m2,m0,0x0C); \+t1 = _mm_slli_si128(t0,4); \+buf = _mm_blend_epi16(t1,m3,0x0F);++#define LOAD_MSG_8_4(buf) \+t0 = _mm_blend_epi16(m1,m0,0x30); \+buf = _mm_shuffle_epi32(t0,_MM_SHUFFLE(1,0,3,2));++#define LOAD_MSG_9_1(buf) \+t0 = _mm_blend_epi16(m0,m2,0x03); \+t1 = _mm_blend_epi16(m1,m2,0x30); \+t2 = _mm_blend_epi16(t1,t0,0x0F); \+buf = _mm_shuffle_epi32(t2,_MM_SHUFFLE(1,3,0,2));++#define LOAD_MSG_9_2(buf) \+t0 = _mm_slli_si128(m0,4); \+t1 = _mm_blend_epi16(m1,t0,0xC0); \+buf = _mm_shuffle_epi32(t1,_MM_SHUFFLE(1,2,0,3));++#define LOAD_MSG_9_3(buf) \+t0 = _mm_unpackhi_epi32(m0,m3); \+t1 = _mm_unpacklo_epi32(m2,m3); \+t2 = _mm_unpackhi_epi64(t0,t1); \+buf = _mm_shuffle_epi32(t2,_MM_SHUFFLE(3,0,2,1));++#define LOAD_MSG_9_4(buf) \+t0 = _mm_blend_epi16(m3,m2,0xC0); \+t1 = _mm_unpacklo_epi32(m0,m3); \+t2 = _mm_blend_epi16(t0,t1,0x0F); \+buf = _mm_shuffle_epi32(t2,_MM_SHUFFLE(0,1,2,3));++#endif+
+ include/blake2s-load-xop.h view
@@ -0,0 +1,189 @@+/*+ BLAKE2 reference source code package - optimized 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 __BLAKE2S_LOAD_XOP_H__+#define __BLAKE2S_LOAD_XOP_H__++#define TOB(x) ((x)*4*0x01010101 + 0x03020100) // ..or not TOB++/* Basic VPPERM emulation, for testing purposes */+/*static __m128i _mm_perm_epi8(const __m128i src1, const __m128i src2, const __m128i sel)+{+ const __m128i sixteen = _mm_set1_epi8(16);+ const __m128i t0 = _mm_shuffle_epi8(src1, sel);+ const __m128i s1 = _mm_shuffle_epi8(src2, _mm_sub_epi8(sel, sixteen));+ const __m128i mask = _mm_or_si128(_mm_cmpeq_epi8(sel, sixteen),+ _mm_cmpgt_epi8(sel, sixteen)); // (>=16) = 0xff : 00+ return _mm_blendv_epi8(t0, s1, mask);+}*/++#define LOAD_MSG_0_1(buf) \+buf = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(6),TOB(4),TOB(2),TOB(0)) );++#define LOAD_MSG_0_2(buf) \+buf = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(7),TOB(5),TOB(3),TOB(1)) );++#define LOAD_MSG_0_3(buf) \+buf = _mm_perm_epi8(m2, m3, _mm_set_epi32(TOB(6),TOB(4),TOB(2),TOB(0)) );++#define LOAD_MSG_0_4(buf) \+buf = _mm_perm_epi8(m2, m3, _mm_set_epi32(TOB(7),TOB(5),TOB(3),TOB(1)) );++#define LOAD_MSG_1_1(buf) \+t0 = _mm_perm_epi8(m1, m2, _mm_set_epi32(TOB(0),TOB(5),TOB(0),TOB(0)) ); \+buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(5),TOB(2),TOB(1),TOB(6)) );++#define LOAD_MSG_1_2(buf) \+t1 = _mm_perm_epi8(m1, m2, _mm_set_epi32(TOB(2),TOB(0),TOB(4),TOB(6)) ); \+buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(7),TOB(1),TOB(0)) );++#define LOAD_MSG_1_3(buf) \+t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(5),TOB(0),TOB(0),TOB(1)) ); \+buf = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(3),TOB(7),TOB(1),TOB(0)) );++#define LOAD_MSG_1_4(buf) \+t1 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(3),TOB(7),TOB(2),TOB(0)) ); \+buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(1),TOB(4)) );++#define LOAD_MSG_2_1(buf) \+t0 = _mm_perm_epi8(m1, m2, _mm_set_epi32(TOB(0),TOB(1),TOB(0),TOB(7)) ); \+buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(7),TOB(2),TOB(4),TOB(0)) );++#define LOAD_MSG_2_2(buf) \+t1 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(0),TOB(2),TOB(0),TOB(4)) ); \+buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(5),TOB(2),TOB(1),TOB(0)) );++#define LOAD_MSG_2_3(buf) \+t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(7),TOB(3),TOB(0)) ); \+buf = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(5),TOB(2),TOB(1),TOB(6)) );++#define LOAD_MSG_2_4(buf) \+t1 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(4),TOB(1),TOB(6),TOB(0)) ); \+buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(1),TOB(6)) );++#define LOAD_MSG_3_1(buf) \+t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(0),TOB(3),TOB(7)) ); \+t0 = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(7),TOB(2),TOB(1),TOB(0)) ); \+buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(3),TOB(5),TOB(1),TOB(0)) );++#define LOAD_MSG_3_2(buf) \+t1 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(0),TOB(0),TOB(1),TOB(5)) ); \+buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(6),TOB(4),TOB(1),TOB(0)) );++#define LOAD_MSG_3_3(buf) \+t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(4),TOB(5),TOB(2)) ); \+buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(7),TOB(2),TOB(1),TOB(0)) );++#define LOAD_MSG_3_4(buf) \+t1 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(0),TOB(0),TOB(6)) ); \+buf = _mm_perm_epi8(t1, m2, _mm_set_epi32(TOB(4),TOB(2),TOB(6),TOB(0)) );++#define LOAD_MSG_4_1(buf) \+t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(2),TOB(5),TOB(0)) ); \+buf = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(6),TOB(2),TOB(1),TOB(5)) );++#define LOAD_MSG_4_2(buf) \+t1 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(4),TOB(7),TOB(0)) ); \+buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(7),TOB(2),TOB(1),TOB(0)) );++#define LOAD_MSG_4_3(buf) \+t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(3),TOB(6),TOB(0),TOB(0)) ); \+t0 = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(3),TOB(2),TOB(7),TOB(0)) ); \+buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(1),TOB(6)) );++#define LOAD_MSG_4_4(buf) \+t1 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(0),TOB(4),TOB(0),TOB(1)) ); \+buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(5),TOB(2),TOB(4),TOB(0)) );++#define LOAD_MSG_5_1(buf) \+t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(0),TOB(6),TOB(2)) ); \+buf = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(4),TOB(2),TOB(1),TOB(0)) );++#define LOAD_MSG_5_2(buf) \+t1 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(3),TOB(7),TOB(6),TOB(0)) ); \+buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(1),TOB(4)) );++#define LOAD_MSG_5_3(buf) \+t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(1),TOB(0),TOB(7),TOB(4)) ); \+buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(3),TOB(7),TOB(1),TOB(0)) );++#define LOAD_MSG_5_4(buf) \+t1 = _mm_perm_epi8(m1, m2, _mm_set_epi32(TOB(5),TOB(0),TOB(1),TOB(0)) ); \+buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(6),TOB(1),TOB(5)) );++#define LOAD_MSG_6_1(buf) \+t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(4),TOB(0),TOB(1),TOB(0)) ); \+buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(3),TOB(6),TOB(1),TOB(4)) );++#define LOAD_MSG_6_2(buf) \+t1 = _mm_perm_epi8(m1, m2, _mm_set_epi32(TOB(6),TOB(0),TOB(0),TOB(1)) ); \+buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(5),TOB(7),TOB(0)) );++#define LOAD_MSG_6_3(buf) \+t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(0),TOB(6),TOB(0)) ); \+buf = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(4),TOB(5),TOB(1),TOB(0)) );++#define LOAD_MSG_6_4(buf) \+t1 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(2),TOB(3),TOB(7)) ); \+buf = _mm_perm_epi8(t1, m2, _mm_set_epi32(TOB(7),TOB(2),TOB(1),TOB(0)) );++#define LOAD_MSG_7_1(buf) \+t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(3),TOB(0),TOB(7),TOB(0)) ); \+buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(3),TOB(4),TOB(1),TOB(5)) );++#define LOAD_MSG_7_2(buf) \+t1 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(5),TOB(1),TOB(0),TOB(7)) ); \+buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(6),TOB(0)) );++#define LOAD_MSG_7_3(buf) \+t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(2),TOB(0),TOB(0),TOB(5)) ); \+t0 = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(3),TOB(4),TOB(1),TOB(0)) ); \+buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(7),TOB(0)) );++#define LOAD_MSG_7_4(buf) \+t1 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(6),TOB(4),TOB(0)) ); \+buf = _mm_perm_epi8(t1, m2, _mm_set_epi32(TOB(6),TOB(2),TOB(1),TOB(0)) );++#define LOAD_MSG_8_1(buf) \+t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(0),TOB(0),TOB(6)) ); \+t0 = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(3),TOB(7),TOB(1),TOB(0)) ); \+buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(6),TOB(0)) );++#define LOAD_MSG_8_2(buf) \+t1 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(4),TOB(3),TOB(5),TOB(0)) ); \+buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(1),TOB(7)) );++#define LOAD_MSG_8_3(buf) \+t0 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(6),TOB(1),TOB(0),TOB(0)) ); \+buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(5),TOB(4)) ); \+ +#define LOAD_MSG_8_4(buf) \+buf = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(5),TOB(4),TOB(7),TOB(2)) );++#define LOAD_MSG_9_1(buf) \+t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(1),TOB(7),TOB(0),TOB(0)) ); \+buf = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(3),TOB(2),TOB(4),TOB(6)) );++#define LOAD_MSG_9_2(buf) \+buf = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(5),TOB(6),TOB(4),TOB(2)) );++#define LOAD_MSG_9_3(buf) \+t0 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(0),TOB(3),TOB(5),TOB(0)) ); \+buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(5),TOB(2),TOB(1),TOB(7)) );++#define LOAD_MSG_9_4(buf) \+t1 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(0),TOB(0),TOB(0),TOB(7)) ); \+buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(4),TOB(6),TOB(0)) );++#endif+
+ include/blake2s-round.h view
@@ -0,0 +1,88 @@+/*+ BLAKE2 reference source code package - optimized 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 __BLAKE2S_ROUND_H__+#define __BLAKE2S_ROUND_H__++#define LOADU(p) _mm_loadu_si128( (const __m128i *)(p) )+#define STOREU(p,r) _mm_storeu_si128((__m128i *)(p), r)++#define TOF(reg) _mm_castsi128_ps((reg))+#define TOI(reg) _mm_castps_si128((reg))++#define LIKELY(x) __builtin_expect((x),1)+++/* Microarchitecture-specific macros */+#ifndef HAVE_XOP+#ifdef HAVE_SSSE3+#define _mm_roti_epi32(r, c) ( \+ (8==-(c)) ? _mm_shuffle_epi8(r,r8) \+ : (16==-(c)) ? _mm_shuffle_epi8(r,r16) \+ : _mm_xor_si128(_mm_srli_epi32( (r), -(c) ),_mm_slli_epi32( (r), 32-(-(c)) )) )+#else+#define _mm_roti_epi32(r, c) _mm_xor_si128(_mm_srli_epi32( (r), -(c) ),_mm_slli_epi32( (r), 32-(-(c)) ))+#endif+#else+/* ... */+#endif+++#define G1(row1,row2,row3,row4,buf) \+ row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \+ row4 = _mm_xor_si128( row4, row1 ); \+ row4 = _mm_roti_epi32(row4, -16); \+ row3 = _mm_add_epi32( row3, row4 ); \+ row2 = _mm_xor_si128( row2, row3 ); \+ row2 = _mm_roti_epi32(row2, -12);++#define G2(row1,row2,row3,row4,buf) \+ row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \+ row4 = _mm_xor_si128( row4, row1 ); \+ row4 = _mm_roti_epi32(row4, -8); \+ row3 = _mm_add_epi32( row3, row4 ); \+ row2 = _mm_xor_si128( row2, row3 ); \+ row2 = _mm_roti_epi32(row2, -7);++#define DIAGONALIZE(row1,row2,row3,row4) \+ row4 = _mm_shuffle_epi32( row4, _MM_SHUFFLE(2,1,0,3) ); \+ row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(1,0,3,2) ); \+ row2 = _mm_shuffle_epi32( row2, _MM_SHUFFLE(0,3,2,1) );++#define UNDIAGONALIZE(row1,row2,row3,row4) \+ row4 = _mm_shuffle_epi32( row4, _MM_SHUFFLE(0,3,2,1) ); \+ row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(1,0,3,2) ); \+ row2 = _mm_shuffle_epi32( row2, _MM_SHUFFLE(2,1,0,3) );++#if defined(HAVE_XOP)+#include "blake2s-load-xop.h"+#elif defined(HAVE_SSE41)+#include "blake2s-load-sse41.h"+#else+#include "blake2s-load-sse2.h"+#endif++#define ROUND(r) \+ LOAD_MSG_ ##r ##_1(buf1); \+ G1(row1,row2,row3,row4,buf1); \+ LOAD_MSG_ ##r ##_2(buf2); \+ G2(row1,row2,row3,row4,buf2); \+ DIAGONALIZE(row1,row2,row3,row4); \+ LOAD_MSG_ ##r ##_3(buf3); \+ G1(row1,row2,row3,row4,buf3); \+ LOAD_MSG_ ##r ##_4(buf4); \+ G2(row1,row2,row3,row4,buf4); \+ UNDIAGONALIZE(row1,row2,row3,row4); \+ +#endif+
+ src/Crypto/Hash/BLAKE2/BLAKE2b.hsc view
@@ -0,0 +1,95 @@+----------------------------------------------------------------+-- |+-- Module : Crypto.Hash.BLAKE2.BLAKE2b+-- Maintainer : John Galt <jgalt@centromere.net>+-- Stability : experimental+-- Portability : POSIX++module Crypto.Hash.BLAKE2.BLAKE2b+ ( -- * Types+ BLAKE2bState,+ -- * Functions+ initialize,+ initialize',+ update,+ finalize,+ hash+ ) where++import Data.ByteString (ByteString)+import Foreign.C.Types (CInt(..))+import Foreign.ForeignPtr (ForeignPtr)+import Foreign.Storable (Storable(..))++import Crypto.Hash.BLAKE2.Internal++#include "blake2.h"++data BLAKE2bStruct++instance Storable BLAKE2bStruct where+ sizeOf _ = #{size blake2b_state}+ alignment _ = #{alignment blake2b_state}+ peek = error "peek not implemented"+ poke = error "poke not implemented"++#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)++-- | The hash state.+type BLAKE2bState = ForeignPtr BLAKE2bStruct++-- | Create a new hashing state.+initialize :: Int+ -- ^ Output length+ -> BLAKE2bState+initialize = initializer c_blake2b_init+{-# INLINE initialize #-}++-- | Create a new keyed hashing state.+initialize' :: Int+ -- ^ Output length+ -> ByteString+ -- ^ Key+ -> BLAKE2bState+initialize' = initializer' c_blake2b_init_key+{-# INLINE initialize' #-}++-- | Add data to the hashing state.+update :: ByteString+ -- ^ Data to hash+ -> BLAKE2bState+ -- ^ Hashing state+ -> BLAKE2bState+update = updater c_blake2b_update+{-# INLINE update #-}++-- | Finalize the hashing state.+finalize :: Int+ -- ^ Output length+ -> BLAKE2bState+ -- ^ Hashing state+ -> ByteString+finalize = finalizer c_blake2b_final+{-# INLINE finalize #-}++-- | Perform hashing all in one step.+hash :: Int+ -- ^ Output length+ -> ByteString+ -- ^ Key+ -> ByteString+ -- ^ Data to hash+ -> ByteString+hash = hasher c_blake2b+{-# INLINE hash #-}++foreign import ccall unsafe "blake2.h blake2b"+ c_blake2b :: HashFunc+foreign import ccall unsafe "blake2.h blake2b_init"+ c_blake2b_init :: InitFunc BLAKE2bStruct+foreign import ccall unsafe "blake2.h blake2b_init_key"+ c_blake2b_init_key :: InitKeyFunc BLAKE2bStruct+foreign import ccall unsafe "blake2.h blake2b_update"+ c_blake2b_update :: UpdateFunc BLAKE2bStruct+foreign import ccall unsafe "blake2.h blake2b_final"+ c_blake2b_final :: FinalFunc BLAKE2bStruct
+ src/Crypto/Hash/BLAKE2/BLAKE2bp.hsc view
@@ -0,0 +1,95 @@+----------------------------------------------------------------+-- |+-- Module : Crypto.Hash.BLAKE2.BLAKE2bp+-- Maintainer : John Galt <jgalt@centromere.net>+-- Stability : experimental+-- Portability : POSIX++module Crypto.Hash.BLAKE2.BLAKE2bp+ ( -- * Types+ BLAKE2bpState,+ -- * Functions+ initialize,+ initialize',+ update,+ finalize,+ hash+ ) where++import Data.ByteString (ByteString)+import Foreign.C.Types (CInt(..))+import Foreign.ForeignPtr (ForeignPtr)+import Foreign.Storable (Storable(..))++import Crypto.Hash.BLAKE2.Internal++#include "blake2.h"++data BLAKE2bpStruct++instance Storable BLAKE2bpStruct where+ sizeOf _ = #{size blake2bp_state}+ alignment _ = #{alignment blake2bp_state}+ peek = error "peek not implemented"+ poke = error "poke not implemented"++#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)++-- | The hash state.+type BLAKE2bpState = ForeignPtr BLAKE2bpStruct++-- | Create a new hashing state.+initialize :: Int+ -- ^ Output length+ -> BLAKE2bpState+initialize = initializer c_blake2bp_init+{-# INLINE initialize #-}++-- | Create a new keyed hashing state.+initialize' :: Int+ -- ^ Output length+ -> ByteString+ -- ^ Key+ -> BLAKE2bpState+initialize' = initializer' c_blake2bp_init_key+{-# INLINE initialize' #-}++-- | Add data to the hashing state.+update :: ByteString+ -- ^ Data to hash+ -> BLAKE2bpState+ -- ^ Hashing state+ -> BLAKE2bpState+update = updater c_blake2bp_update+{-# INLINE update #-}++-- | Finalize the hashing state.+finalize :: Int+ -- ^ Output length+ -> BLAKE2bpState+ -- ^ Hashing state+ -> ByteString+finalize = finalizer c_blake2bp_final+{-# INLINE finalize #-}++-- | Perform hashing all in one step.+hash :: Int+ -- ^ Output length+ -> ByteString+ -- ^ Key+ -> ByteString+ -- ^ Data to hash+ -> ByteString+hash = hasher c_blake2bp+{-# INLINE hash #-}++foreign import ccall unsafe "blake2.h blake2bp"+ c_blake2bp :: HashFunc+foreign import ccall unsafe "blake2.h blake2bp_init"+ c_blake2bp_init :: InitFunc BLAKE2bpStruct+foreign import ccall unsafe "blake2.h blake2bp_init_key"+ c_blake2bp_init_key :: InitKeyFunc BLAKE2bpStruct+foreign import ccall unsafe "blake2.h blake2bp_update"+ c_blake2bp_update :: UpdateFunc BLAKE2bpStruct+foreign import ccall unsafe "blake2.h blake2bp_final"+ c_blake2bp_final :: FinalFunc BLAKE2bpStruct
+ src/Crypto/Hash/BLAKE2/BLAKE2s.hsc view
@@ -0,0 +1,95 @@+----------------------------------------------------------------+-- |+-- Module : Crypto.Hash.BLAKE2.BLAKE2s+-- Maintainer : John Galt <jgalt@centromere.net>+-- Stability : experimental+-- Portability : POSIX++module Crypto.Hash.BLAKE2.BLAKE2s+ ( -- * Types+ BLAKE2sState,+ -- * Functions+ initialize,+ initialize',+ update,+ finalize,+ hash+ ) where++import Data.ByteString (ByteString)+import Foreign.C.Types (CInt(..))+import Foreign.ForeignPtr (ForeignPtr)+import Foreign.Storable (Storable(..))++import Crypto.Hash.BLAKE2.Internal++#include "blake2.h"++data BLAKE2sStruct++instance Storable BLAKE2sStruct where+ sizeOf _ = #{size blake2s_state}+ alignment _ = #{alignment blake2s_state}+ peek = error "peek not implemented"+ poke = error "poke not implemented"++#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)++-- | The hash state.+type BLAKE2sState = ForeignPtr BLAKE2sStruct++-- | Create a new hashing state.+initialize :: Int+ -- ^ Output length+ -> BLAKE2sState+initialize = initializer c_blake2s_init+{-# INLINE initialize #-}++-- | Create a new keyed hashing state.+initialize' :: Int+ -- ^ Output length+ -> ByteString+ -- ^ Key+ -> BLAKE2sState+initialize' = initializer' c_blake2s_init_key+{-# INLINE initialize' #-}++-- | Add data to the hashing state.+update :: ByteString+ -- ^ Data to hash+ -> BLAKE2sState+ -- ^ Hashing state+ -> BLAKE2sState+update = updater c_blake2s_update+{-# INLINE update #-}++-- | Finalize the hashing state.+finalize :: Int+ -- ^ Output length+ -> BLAKE2sState+ -- ^ Hashing state+ -> ByteString+finalize = finalizer c_blake2s_final+{-# INLINE finalize #-}++-- | Perform hashing all in one step.+hash :: Int+ -- ^ Output length+ -> ByteString+ -- ^ Key+ -> ByteString+ -- ^ Data to hash+ -> ByteString+hash = hasher c_blake2s+{-# INLINE hash #-}++foreign import ccall unsafe "blake2.h blake2s"+ c_blake2s :: HashFunc+foreign import ccall unsafe "blake2.h blake2s_init"+ c_blake2s_init :: InitFunc BLAKE2sStruct+foreign import ccall unsafe "blake2.h blake2s_init_key"+ c_blake2s_init_key :: InitKeyFunc BLAKE2sStruct+foreign import ccall unsafe "blake2.h blake2s_update"+ c_blake2s_update :: UpdateFunc BLAKE2sStruct+foreign import ccall unsafe "blake2.h blake2s_final"+ c_blake2s_final :: FinalFunc BLAKE2sStruct
+ src/Crypto/Hash/BLAKE2/BLAKE2sp.hsc view
@@ -0,0 +1,95 @@+----------------------------------------------------------------+-- |+-- Module : Crypto.Hash.BLAKE2.BLAKE2sp+-- Maintainer : John Galt <jgalt@centromere.net>+-- Stability : experimental+-- Portability : POSIX++module Crypto.Hash.BLAKE2.BLAKE2sp+ ( -- * Types+ BLAKE2spState,+ -- * Functions+ initialize,+ initialize',+ update,+ finalize,+ hash+ ) where++import Data.ByteString (ByteString)+import Foreign.C.Types (CInt(..))+import Foreign.ForeignPtr (ForeignPtr)+import Foreign.Storable (Storable(..))++import Crypto.Hash.BLAKE2.Internal++#include "blake2.h"++data BLAKE2spStruct++instance Storable BLAKE2spStruct where+ sizeOf _ = #{size blake2sp_state}+ alignment _ = #{alignment blake2sp_state}+ peek = error "peek not implemented"+ poke = error "poke not implemented"++#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)++-- | The hash state.+type BLAKE2spState = ForeignPtr BLAKE2spStruct++-- | Create a new hashing state.+initialize :: Int+ -- ^ Output length+ -> BLAKE2spState+initialize = initializer c_blake2sp_init+{-# INLINE initialize #-}++-- | Create a new keyed hashing state.+initialize' :: Int+ -- ^ Output length+ -> ByteString+ -- ^ Key+ -> BLAKE2spState+initialize' = initializer' c_blake2sp_init_key+{-# INLINE initialize' #-}++-- | Add data to the hashing state.+update :: ByteString+ -- ^ Data to hash+ -> BLAKE2spState+ -- ^ Hashing state+ -> BLAKE2spState+update = updater c_blake2sp_update+{-# INLINE update #-}++-- | Finalize the hashing state.+finalize :: Int+ -- ^ Output length+ -> BLAKE2spState+ -- ^ Hashing state+ -> ByteString+finalize = finalizer c_blake2sp_final+{-# INLINE finalize #-}++-- | Perform hashing all in one step.+hash :: Int+ -- ^ Output length+ -> ByteString+ -- ^ Key+ -> ByteString+ -- ^ Data to hash+ -> ByteString+hash = hasher c_blake2sp+{-# INLINE hash #-}++foreign import ccall unsafe "blake2.h blake2sp"+ c_blake2sp :: HashFunc+foreign import ccall unsafe "blake2.h blake2sp_init"+ c_blake2sp_init :: InitFunc BLAKE2spStruct+foreign import ccall unsafe "blake2.h blake2sp_init_key"+ c_blake2sp_init_key :: InitKeyFunc BLAKE2spStruct+foreign import ccall unsafe "blake2.h blake2sp_update"+ c_blake2sp_update :: UpdateFunc BLAKE2spStruct+foreign import ccall unsafe "blake2.h blake2sp_final"+ c_blake2sp_final :: FinalFunc BLAKE2spStruct
+ src/Crypto/Hash/BLAKE2/Internal.hs view
@@ -0,0 +1,130 @@+----------------------------------------------------------------+-- |+-- Module : Crypto.Hash.BLAKE2.Internal+-- Maintainer : John Galt <jgalt@centromere.net>+-- Stability : experimental+-- Portability : POSIX++module Crypto.Hash.BLAKE2.Internal+ ( -- * Types+ InitFunc,+ InitKeyFunc,+ UpdateFunc,+ FinalFunc,+ HashFunc,+ -- * Functions+ initializer,+ initializer',+ updater,+ finalizer,+ hasher+ ) where++import Control.Monad (void)+import Data.ByteString (ByteString)+import Data.ByteString.Internal (create, toForeignPtr)+import Data.ByteString.Unsafe (unsafeUseAsCStringLen)+import Data.Word (Word8, Word64)+import Foreign.C.Types (CInt(..), CChar)+import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtr, withForeignPtr)+import Foreign.Marshal.Array (copyArray)+import Foreign.Ptr (Ptr)+import Foreign.Storable (Storable(..))+import System.IO.Unsafe (unsafePerformIO)++-- int blake2X_init( blake2s_state *S, const uint8_t outlen );+type InitFunc a = Ptr a -> Int -> IO CInt++-- int blake2X_init_key( blake2s_state *S, const uint8_t outlen, const void+-- *key, const uint8_t keylen );+type InitKeyFunc a = Ptr a -> Word8 -> Ptr CChar -> Word8 -> IO CInt++-- int blake2X_update( blake2s_state *S, const uint8_t *in,+-- uint64_t inlen );+type UpdateFunc a = Ptr a -> Ptr Word8 -> Word64 -> IO CInt++-- int blake2X_final( blake2s_state *S, uint8_t *out, uint8_t outlen );+type FinalFunc a = Ptr a -> Ptr Word8 -> Word8 -> IO CInt++-- int blake2X( uint8_t *out, const void *in, const void *key, const+-- uint8_t outlen, const uint64_t inlen, uint8_t keylen );+type HashFunc = Ptr Word8+ -> Ptr CChar+ -> Ptr CChar+ -> Word8+ -> Word64+ -> Word8+ -> IO CInt++initializer :: Storable a+ => InitFunc a+ -> Int+ -> ForeignPtr a+initializer f outlen = unsafePerformIO $ do+ fptr <- mallocForeignPtr+ withForeignPtr fptr $ \ptr -> do+ ret <- f ptr outlen+ if ret == 0+ then return fptr+ else error "initialization failure"++initializer' :: Storable a+ => InitKeyFunc a+ -> Int+ -> ByteString+ -> ForeignPtr a+initializer' f outlen key = unsafePerformIO $ do+ fptr <- mallocForeignPtr+ withForeignPtr fptr $ \ptr ->+ unsafeUseAsCStringLen key $ \(kptr, klen) -> do+ let klen' = fromIntegral klen+ outlen' = fromIntegral outlen+ ret <- f ptr outlen' kptr klen'+ if ret == 0+ then return fptr+ else error "initialization failure"++updater :: Storable a+ => UpdateFunc a+ -> ByteString+ -> ForeignPtr a+ -> ForeignPtr a+updater f d state = unsafePerformIO $ do+ newState <- mallocForeignPtr+ withForeignPtr newState $ \nsptr -> do+ let (dfp, _, dlen) = toForeignPtr d+ dlen' = fromIntegral dlen+ withForeignPtr dfp $ \dptr ->+ withForeignPtr state $ \sptr -> do+ copyArray nsptr sptr 1+ void $ f nsptr dptr dlen'+ return newState++finalizer :: Storable a+ => FinalFunc a+ -> Int+ -> ForeignPtr a+ -> ByteString+finalizer f outlen state = unsafePerformIO $ do+ newState <- mallocForeignPtr+ withForeignPtr newState $ \nsptr ->+ create outlen $ \optr ->+ withForeignPtr state $ \sptr -> do+ let outlen' = fromIntegral outlen+ copyArray nsptr sptr 1+ void $ f nsptr optr outlen'++hasher :: HashFunc+ -> Int+ -> ByteString+ -> ByteString+ -> ByteString+hasher h outlen key input =+ unsafePerformIO . create outlen $ \out ->+ unsafeUseAsCStringLen key $ \(kstr, klen) ->+ unsafeUseAsCStringLen input $ \(istr, ilen) ->+ let outlen' = fromIntegral outlen+ ilen' = fromIntegral ilen+ klen' = fromIntegral klen+ in void $ h out istr kstr outlen' ilen' klen'+{-# INLINE hasher #-}
+ tests/Imports.hs view
@@ -0,0 +1,7 @@+module Imports+ (+ module X+ ) where++import Test.Tasty as X+import Test.Tasty.QuickCheck as X
+ tests/hlint.hs view
@@ -0,0 +1,16 @@+module Main where++import Control.Monad+import Language.Haskell.HLint+import System.Environment+import System.Exit++main :: IO ()+main = do+ args <- getArgs+ hints <- hlint $ [ "src"+ , "benchmarks"+ , "tests"+ , "--cpp-define=HLINT"+ ] `mappend` args+ unless (null hints) exitFailure
+ tests/properties.hs view
@@ -0,0 +1,103 @@+{-# LANGUAGE OverloadedStrings #-}+module Main where++import Data.ByteString (ByteString)+import qualified Data.ByteString.Base16 as Hex+import Prelude hiding (compare)++import qualified Crypto.Hash.BLAKE2.BLAKE2b as B2b+import qualified Crypto.Hash.BLAKE2.BLAKE2bp as B2bp+import qualified Crypto.Hash.BLAKE2.BLAKE2s as B2s+import qualified Crypto.Hash.BLAKE2.BLAKE2sp as B2sp++import Imports++key32 :: ByteString+key32 = fst . Hex.decode $ "000102030405060708090a0b0c0d0e0f\+ \101112131415161718191a1b1c1d1e1f"++key64 :: ByteString+key64 = fst . Hex.decode $ "000102030405060708090a0b0c0d0e0f\+ \101112131415161718191a1b1c1d1e1f\+ \202122232425262728292a2b2c2d2e2f\+ \303132333435363738393a3b3c3d3e3f"++compare :: (ByteString -> ByteString)+ -> ByteString+ -> ByteString+ -> Property+compare f input expectation = property $ result === expectation+ where+ result = Hex.encode . f . fst . Hex.decode $ input++test0s :: Property+test0s = compare (B2s.hash 32 key32) "" "48a8997da407876b3d79c0d92325ad3b89cbb754d86ab71aee047ad345fd2c49"++test1s :: Property+test1s = compare (B2s.hash 32 key32) "00" "40d15fee7c328830166ac3f918650f807e7e01e177258cdc0a39b11f598066f1"++test2s :: Property+test2s = compare (B2s.hash 32 key32) "0001" "6bb71300644cd3991b26ccd4d274acd1adeab8b1d7914546c1198bbe9fc9d803"++test3s :: Property+test3s = compare (B2s.hash 32 key32) "000102" "1d220dbe2ee134661fdf6d9e74b41704710556f2f6e5a091b227697445dbea6b"++test0sp :: Property+test0sp = compare (B2sp.hash 32 key32) "" "715cb13895aeb678f6124160bff21465b30f4f6874193fc851b4621043f09cc6"++test1sp :: Property+test1sp = compare (B2sp.hash 32 key32) "00" "40578ffa52bf51ae1866f4284d3a157fc1bcd36ac13cbdcb0377e4d0cd0b6603"++test2sp :: Property+test2sp = compare (B2sp.hash 32 key32) "0001" "67e3097545bad7e852d74d4eb548eca7c219c202a7d088db0efeac0eac304249"++test3sp :: Property+test3sp = compare (B2sp.hash 32 key32) "000102" "8dbcc0589a3d17296a7a58e2f1eff0e2aa4210b58d1f88b86d7ba5f29dd3b583"++test0b :: Property+test0b = compare (B2b.hash 64 key64) "" "10ebb67700b1868efb4417987acf4690ae9d972fb7a590c2f02871799aaa4786b5e996e8f0f4eb981fc214b005f42d2ff4233499391653df7aefcbc13fc51568"++test1b :: Property+test1b = compare (B2b.hash 64 key64) "00" "961f6dd1e4dd30f63901690c512e78e4b45e4742ed197c3c5e45c549fd25f2e4187b0bc9fe30492b16b0d0bc4ef9b0f34c7003fac09a5ef1532e69430234cebd"++test2b :: Property+test2b = compare (B2b.hash 64 key64) "0001" "da2cfbe2d8409a0f38026113884f84b50156371ae304c4430173d08a99d9fb1b983164a3770706d537f49e0c916d9f32b95cc37a95b99d857436f0232c88a965"++test3b :: Property+test3b = compare (B2b.hash 64 key64) "000102" "33d0825dddf7ada99b0e7e307104ad07ca9cfd9692214f1561356315e784f3e5a17e364ae9dbb14cb2036df932b77f4b292761365fb328de7afdc6d8998f5fc1"++test0bp :: Property+test0bp = compare (B2bp.hash 64 key64) "" "9d9461073e4eb640a255357b839f394b838c6ff57c9b686a3f76107c1066728f3c9956bd785cbc3bf79dc2ab578c5a0c063b9d9c405848de1dbe821cd05c940a"++test1bp :: Property+test1bp = compare (B2bp.hash 64 key64) "00" "ff8e90a37b94623932c59f7559f26035029c376732cb14d41602001cbb73adb79293a2dbda5f60703025144d158e2735529596251c73c0345ca6fccb1fb1e97e"++test2bp :: Property+test2bp = compare (B2bp.hash 64 key64) "0001" "d6220ca195a0f356a4795e071cee1f5412ecd95d8a5e01d7c2b86750ca53d7f64c29cbb3d289c6f4ecc6c01e3ca9338971170388e3e40228479006d1bbebad51"++test3bp :: Property+test3bp = compare (B2bp.hash 64 key64) "000102" "30302c3fc999065d10dc982c8feef41bbb6642718f624af6e3eabea083e7fe785340db4b0897efff39cee1dc1eb737cd1eea0fe75384984e7d8f446faa683b80"++main :: IO ()+main = defaultMain $ testGroup "blake2"+ [ testGroup "blake2s" [ testProperty "0" test0s+ , testProperty "1" test1s+ , testProperty "2" test2s+ , testProperty "3" test3s+ ]+ , testGroup "blake2sp" [ testProperty "0" test0sp+ , testProperty "1" test1sp+ , testProperty "2" test2sp+ , testProperty "3" test3sp+ ]+ , testGroup "blake2b" [ testProperty "0" test0b+ , testProperty "1" test1b+ , testProperty "2" test2b+ , testProperty "3" test3b+ ]+ , testGroup "blake2bp" [ testProperty "0" test0bp+ , testProperty "1" test1bp+ , testProperty "2" test2bp+ , testProperty "3" test3bp+ ]+ ]