Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-17 08:46:46

0001 #ifndef BOOST_HASH2_BLAKE2_HPP_INCLUDED
0002 #define BOOST_HASH2_BLAKE2_HPP_INCLUDED
0003 
0004 // Copyright 2025 Christian Mazakas.
0005 // Distributed under the Boost Software License, Version 1.0.
0006 // https://www.boost.org/LICENSE_1_0.txt
0007 //
0008 
0009 #include <boost/hash2/digest.hpp>
0010 #include <boost/hash2/hmac.hpp>
0011 
0012 #include <boost/hash2/detail/is_constant_evaluated.hpp>
0013 #include <boost/hash2/detail/memcpy.hpp>
0014 #include <boost/hash2/detail/memset.hpp>
0015 #include <boost/hash2/detail/read.hpp>
0016 #include <boost/hash2/detail/rot.hpp>
0017 #include <boost/hash2/detail/write.hpp>
0018 
0019 #include <boost/assert.hpp>
0020 #include <boost/config.hpp>
0021 #include <boost/config/workaround.hpp>
0022 
0023 #include <cstdint>
0024 
0025 #if !defined(BOOST_HASH2_BLAKE2_CONSTEXPR)
0026 
0027 #if BOOST_WORKAROUND(BOOST_GCC, >= 50000 && BOOST_GCC < 60000)
0028 #define BOOST_HASH2_BLAKE2_CONSTEXPR
0029 #else
0030 #define BOOST_HASH2_BLAKE2_CONSTEXPR BOOST_CXX14_CONSTEXPR
0031 #endif
0032 
0033 #endif
0034 
0035 namespace boost
0036 {
0037 namespace hash2
0038 {
0039 namespace detail
0040 {
0041 
0042 template<class = void>
0043 struct blake2b_constants
0044 {
0045     constexpr static const std::uint64_t iv[ 8 ] =
0046     {
0047         0x6a09e667f3bcc908, 0xbb67ae8584caa73b,
0048         0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
0049         0x510e527fade682d1, 0x9b05688c2b3e6c1f,
0050         0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
0051     };
0052 };
0053 
0054 template<class = void>
0055 struct blake2s_constants
0056 {
0057     constexpr static const std::uint32_t iv[ 8 ] =
0058     {
0059         0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0060         0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
0061     };
0062 };
0063 
0064 // copy-paste from Boost.Unordered's prime_fmod approach
0065 #if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
0066 
0067 // https://en.cppreference.com/w/cpp/language/static#Constant_static_members
0068 // If a const non-inline (since C++17) static data member or a constexpr
0069 // static data member (since C++11)(until C++17) is odr-used, a definition
0070 // at namespace scope is still required, but it cannot have an
0071 // initializer.
0072 template<class T>
0073 constexpr std::uint64_t blake2b_constants<T>::iv[ 8 ];
0074 
0075 template<class T>
0076 constexpr std::uint32_t blake2s_constants<T>::iv[ 8 ];
0077 
0078 #endif
0079 
0080 } // namespace detail
0081 
0082 class blake2b_512
0083 {
0084 private:
0085 
0086     unsigned char b_[ 128 ] = {};
0087     std::uint64_t h_[ 8 ] = {};
0088     std::uint64_t t_[ 2 ] = {};
0089     std::size_t m_ = 0;
0090 
0091     BOOST_HASH2_BLAKE2_CONSTEXPR void init( std::uint64_t keylen = 0 )
0092     {
0093         for( int i = 0; i < 8; ++i )
0094         {
0095             h_[ i ] = detail::blake2b_constants<>::iv[ i ];
0096         }
0097 
0098         std::uint64_t const outlen = 64;
0099         h_[ 0 ] ^= 0x01010000 ^ ( keylen << 8 ) ^ outlen;
0100     }
0101 
0102     BOOST_HASH2_BLAKE2_CONSTEXPR BOOST_FORCEINLINE static void G( std::uint64_t v[ 16 ], int a, int b, int c, int d, std::uint64_t x, std::uint64_t y )
0103     {
0104         v[ a ] = v[ a ] + v[ b ] + x;
0105         v[ d ] = detail::rotr( v[ d ] ^ v[ a ], 32 );
0106         v[ c ] = v[ c ] + v[ d ];
0107         v[ b ] = detail::rotr( v[ b ] ^ v[ c ], 24 );
0108         v[ a ] = v[ a ] + v[ b ] + y;
0109         v[ d ] = detail::rotr( v[ d ] ^ v[ a ], 16 );
0110         v[ c ] = v[ c ] + v[ d ];
0111         v[ b ] = detail::rotr( v[ b ] ^ v[ c ], 63 );
0112     }
0113 
0114     BOOST_HASH2_BLAKE2_CONSTEXPR void transform( unsigned char const block[ 128 ], bool is_final = false )
0115     {
0116         auto iv = detail::blake2b_constants<>::iv;
0117 
0118         std::uint64_t v[ 16 ] = {};
0119         std::uint64_t m[ 16 ] = {};
0120 
0121         v[ 0 ] = h_[ 0 ];
0122         v[ 1 ] = h_[ 1 ];
0123         v[ 2 ] = h_[ 2 ];
0124         v[ 3 ] = h_[ 3 ];
0125         v[ 4 ] = h_[ 4 ];
0126         v[ 5 ] = h_[ 5 ];
0127         v[ 6 ] = h_[ 6 ];
0128         v[ 7 ] = h_[ 7 ];
0129 
0130         v[  8 ] = iv[ 0 ];
0131         v[  9 ] = iv[ 1 ];
0132         v[ 10 ] = iv[ 2 ];
0133         v[ 11 ] = iv[ 3 ];
0134         v[ 12 ] = iv[ 4 ];
0135         v[ 13 ] = iv[ 5 ];
0136         v[ 14 ] = iv[ 6 ];
0137         v[ 15 ] = iv[ 7 ];
0138 
0139         v[ 12 ] ^= t_[ 0 ];
0140         v[ 13 ] ^= t_[ 1 ];
0141 
0142         if( is_final )
0143         {
0144             v[ 14 ] = ~v[ 14 ];
0145         }
0146 
0147         for( int i = 0; i < 16; ++i )
0148         {
0149             m[ i ] = detail::read64le( block + 8 * i );
0150         }
0151 
0152         // round 0
0153         G( v, 0, 4,  8, 12, m[  0 ], m[  1 ] );
0154         G( v, 1, 5,  9, 13, m[  2 ], m[  3 ] );
0155         G( v, 2, 6, 10, 14, m[  4 ], m[  5 ] );
0156         G( v, 3, 7, 11, 15, m[  6 ], m[  7 ] );
0157         G( v, 0, 5, 10, 15, m[  8 ], m[  9 ] );
0158         G( v, 1, 6, 11, 12, m[ 10 ], m[ 11 ] );
0159         G( v, 2, 7,  8, 13, m[ 12 ], m[ 13 ] );
0160         G( v, 3, 4,  9, 14, m[ 14 ], m[ 15 ] );
0161 
0162         // round 1
0163         G( v, 0, 4,  8, 12, m[ 14 ], m[ 10 ] );
0164         G( v, 1, 5,  9, 13, m[  4 ], m[  8 ] );
0165         G( v, 2, 6, 10, 14, m[  9 ], m[ 15 ] );
0166         G( v, 3, 7, 11, 15, m[ 13 ], m[  6 ] );
0167         G( v, 0, 5, 10, 15, m[  1 ], m[ 12 ] );
0168         G( v, 1, 6, 11, 12, m[  0 ], m[  2 ] );
0169         G( v, 2, 7,  8, 13, m[ 11 ], m[  7 ] );
0170         G( v, 3, 4,  9, 14, m[  5 ], m[  3 ] );
0171 
0172         // round 2
0173         G( v, 0, 4,  8, 12, m[ 11 ], m[  8 ] );
0174         G( v, 1, 5,  9, 13, m[ 12 ], m[  0 ] );
0175         G( v, 2, 6, 10, 14, m[  5 ], m[  2 ] );
0176         G( v, 3, 7, 11, 15, m[ 15 ], m[ 13 ] );
0177         G( v, 0, 5, 10, 15, m[ 10 ], m[ 14 ] );
0178         G( v, 1, 6, 11, 12, m[  3 ], m[  6 ] );
0179         G( v, 2, 7,  8, 13, m[  7 ], m[  1 ] );
0180         G( v, 3, 4,  9, 14, m[  9 ], m[  4 ] );
0181 
0182         // round 3
0183         G( v, 0, 4,  8, 12, m[  7 ], m[  9 ] );
0184         G( v, 1, 5,  9, 13, m[  3 ], m[  1 ] );
0185         G( v, 2, 6, 10, 14, m[ 13 ], m[ 12 ] );
0186         G( v, 3, 7, 11, 15, m[ 11 ], m[ 14 ] );
0187         G( v, 0, 5, 10, 15, m[  2 ], m[  6 ] );
0188         G( v, 1, 6, 11, 12, m[  5 ], m[ 10 ] );
0189         G( v, 2, 7,  8, 13, m[  4 ], m[  0 ] );
0190         G( v, 3, 4,  9, 14, m[ 15 ], m[  8 ] );
0191 
0192         // round 4
0193         G( v, 0, 4,  8, 12, m[  9 ], m[  0 ] );
0194         G( v, 1, 5,  9, 13, m[  5 ], m[  7 ] );
0195         G( v, 2, 6, 10, 14, m[  2 ], m[  4 ] );
0196         G( v, 3, 7, 11, 15, m[ 10 ], m[ 15 ] );
0197         G( v, 0, 5, 10, 15, m[ 14 ], m[  1 ] );
0198         G( v, 1, 6, 11, 12, m[ 11 ], m[ 12 ] );
0199         G( v, 2, 7,  8, 13, m[  6 ], m[  8 ] );
0200         G( v, 3, 4,  9, 14, m[  3 ], m[ 13 ] );
0201 
0202         // round 5
0203         G( v, 0, 4,  8, 12,  m[  2 ], m[ 12 ] );
0204         G( v, 1, 5,  9, 13,  m[  6 ], m[ 10 ] );
0205         G( v, 2, 6, 10, 14,  m[  0 ], m[ 11 ] );
0206         G( v, 3, 7, 11, 15,  m[  8 ], m[  3 ] );
0207         G( v, 0, 5, 10, 15,  m[  4 ], m[ 13 ] );
0208         G( v, 1, 6, 11, 12,  m[  7 ], m[  5 ] );
0209         G( v, 2, 7,  8, 13,  m[ 15 ], m[ 14 ] );
0210         G( v, 3, 4,  9, 14,  m[  1 ], m[  9 ] );
0211 
0212         // round 6
0213         G( v, 0, 4,  8, 12, m[ 12 ], m[  5 ] );
0214         G( v, 1, 5,  9, 13, m[  1 ], m[ 15 ] );
0215         G( v, 2, 6, 10, 14, m[ 14 ], m[ 13 ] );
0216         G( v, 3, 7, 11, 15, m[  4 ], m[ 10 ] );
0217         G( v, 0, 5, 10, 15, m[  0 ], m[  7 ] );
0218         G( v, 1, 6, 11, 12, m[  6 ], m[  3 ] );
0219         G( v, 2, 7,  8, 13, m[  9 ], m[  2 ] );
0220         G( v, 3, 4,  9, 14, m[  8 ], m[ 11 ] );
0221 
0222         // round 7
0223         G( v, 0, 4,  8, 12, m[ 13 ], m[ 11 ] );
0224         G( v, 1, 5,  9, 13, m[  7 ], m[ 14 ] );
0225         G( v, 2, 6, 10, 14, m[ 12 ], m[  1 ] );
0226         G( v, 3, 7, 11, 15, m[  3 ], m[  9 ] );
0227         G( v, 0, 5, 10, 15, m[  5 ], m[  0 ] );
0228         G( v, 1, 6, 11, 12, m[ 15 ], m[  4 ] );
0229         G( v, 2, 7,  8, 13, m[  8 ], m[  6 ] );
0230         G( v, 3, 4,  9, 14, m[  2 ], m[ 10 ] );
0231 
0232         // round 8
0233         G( v, 0, 4,  8, 12, m[  6 ], m[ 15 ] );
0234         G( v, 1, 5,  9, 13, m[ 14 ], m[  9 ] );
0235         G( v, 2, 6, 10, 14, m[ 11 ], m[  3 ] );
0236         G( v, 3, 7, 11, 15, m[  0 ], m[  8 ] );
0237         G( v, 0, 5, 10, 15, m[ 12 ], m[  2 ] );
0238         G( v, 1, 6, 11, 12, m[ 13 ], m[  7 ] );
0239         G( v, 2, 7,  8, 13, m[  1 ], m[  4 ] );
0240         G( v, 3, 4,  9, 14, m[ 10 ], m[  5 ] );
0241 
0242         // round 9
0243         G( v, 0, 4,  8, 12, m[ 10 ], m[  2 ] );
0244         G( v, 1, 5,  9, 13, m[  8 ], m[  4 ] );
0245         G( v, 2, 6, 10, 14, m[  7 ], m[  6 ] );
0246         G( v, 3, 7, 11, 15, m[  1 ], m[  5 ] );
0247         G( v, 0, 5, 10, 15, m[ 15 ], m[ 11 ] );
0248         G( v, 1, 6, 11, 12, m[  9 ], m[ 14 ] );
0249         G( v, 2, 7,  8, 13, m[  3 ], m[ 12 ] );
0250         G( v, 3, 4,  9, 14, m[ 13 ], m[  0 ] );
0251 
0252         // round 10
0253         G( v, 0, 4,  8, 12, m[  0 ], m[  1 ] );
0254         G( v, 1, 5,  9, 13, m[  2 ], m[  3 ] );
0255         G( v, 2, 6, 10, 14, m[  4 ], m[  5 ] );
0256         G( v, 3, 7, 11, 15, m[  6 ], m[  7 ] );
0257         G( v, 0, 5, 10, 15, m[  8 ], m[  9 ] );
0258         G( v, 1, 6, 11, 12, m[ 10 ], m[ 11 ] );
0259         G( v, 2, 7,  8, 13, m[ 12 ], m[ 13 ] );
0260         G( v, 3, 4,  9, 14, m[ 14 ], m[ 15 ] );
0261 
0262         // round 11
0263         G( v, 0, 4,  8, 12, m[ 14 ], m[ 10 ] );
0264         G( v, 1, 5,  9, 13, m[  4 ], m[  8 ] );
0265         G( v, 2, 6, 10, 14, m[  9 ], m[ 15 ] );
0266         G( v, 3, 7, 11, 15, m[ 13 ], m[  6 ] );
0267         G( v, 0, 5, 10, 15, m[  1 ], m[ 12 ] );
0268         G( v, 1, 6, 11, 12, m[  0 ], m[  2 ] );
0269         G( v, 2, 7,  8, 13, m[ 11 ], m[  7 ] );
0270         G( v, 3, 4,  9, 14, m[  5 ], m[  3 ] );
0271 
0272         h_[ 0 ] ^= v[ 0 ] ^ v[ 0 + 8 ];
0273         h_[ 1 ] ^= v[ 1 ] ^ v[ 1 + 8 ];
0274         h_[ 2 ] ^= v[ 2 ] ^ v[ 2 + 8 ];
0275         h_[ 3 ] ^= v[ 3 ] ^ v[ 3 + 8 ];
0276         h_[ 4 ] ^= v[ 4 ] ^ v[ 4 + 8 ];
0277         h_[ 5 ] ^= v[ 5 ] ^ v[ 5 + 8 ];
0278         h_[ 6 ] ^= v[ 6 ] ^ v[ 6 + 8 ];
0279         h_[ 7 ] ^= v[ 7 ] ^ v[ 7 + 8 ];
0280     }
0281 
0282     BOOST_HASH2_BLAKE2_CONSTEXPR BOOST_FORCEINLINE void incr_len( std::size_t n )
0283     {
0284         t_[ 0 ] += n;
0285         t_[ 1 ] += ( t_[ 0 ] < n ); // overflowed
0286     }
0287 
0288 public:
0289 
0290     using result_type = digest<64>;
0291 
0292     static constexpr std::size_t block_size = 128;
0293 
0294     BOOST_HASH2_BLAKE2_CONSTEXPR blake2b_512()
0295     {
0296         init();
0297     }
0298 
0299     BOOST_HASH2_BLAKE2_CONSTEXPR explicit blake2b_512( std::uint64_t seed )
0300     {
0301         if( seed == 0 )
0302         {
0303             init();
0304             return;
0305         }
0306 
0307         unsigned char tmp[ 8 ] = {};
0308         detail::write64le( tmp, seed );
0309 
0310         init( 8 );
0311         update( tmp, 8 );
0312         m_ = block_size;
0313     }
0314 
0315     blake2b_512( void const* p, std::size_t n ) : blake2b_512( static_cast<unsigned char const*>( p ), n )
0316     {
0317     }
0318 
0319     BOOST_HASH2_BLAKE2_CONSTEXPR blake2b_512( unsigned char const* p, std::size_t n )
0320     {
0321         if( n == 0 )
0322         {
0323             init();
0324             return;
0325         }
0326 
0327         auto k = n;
0328         if( k > block_size / 2 )
0329         {
0330             k = block_size / 2;
0331         }
0332 
0333         init( k );
0334         update( p, k );
0335         m_ = block_size;
0336         p += k;
0337         n -= k;
0338 
0339         if( n != 0 )
0340         {
0341             update( p, n );
0342             result();
0343         }
0344     }
0345 
0346     void update( void const* pv, std::size_t n )
0347     {
0348         unsigned char const* p = reinterpret_cast<unsigned char const*>( pv );
0349         update( p, n );
0350     }
0351 
0352     BOOST_HASH2_BLAKE2_CONSTEXPR void update( unsigned char const* p, std::size_t n )
0353     {
0354         if( n > 0 )
0355         {
0356             std::size_t k = block_size - m_;
0357             if( n > k )
0358             {
0359                 detail::memcpy( b_ + m_, p, k );
0360                 incr_len( block_size );
0361                 transform( b_ );
0362                 detail::memset( b_ , 0, block_size );
0363                 p += k;
0364                 n -= k;
0365                 m_ = 0;
0366 
0367                 while( n > block_size )
0368                 {
0369                     incr_len( block_size );
0370                     transform( p );
0371                     p += block_size;
0372                     n -= block_size;
0373                 }
0374             }
0375 
0376             detail::memcpy( b_ + m_, p, n );
0377             m_ += n;
0378         }
0379     }
0380 
0381     BOOST_HASH2_BLAKE2_CONSTEXPR result_type result()
0382     {
0383         result_type digest;
0384 
0385         incr_len( m_ );
0386         for( auto i = m_; i < block_size; ++i )
0387         {
0388             b_[ i ] = 0;
0389         }
0390 
0391         transform( b_, true );
0392         detail::memset( b_ , 0,  block_size );
0393         m_ = 0;
0394 
0395         for( int i = 0; i < 8; ++i )
0396         {
0397             detail::write64le( digest.data() + i * 8, h_[ i ] );
0398         }
0399         return digest;
0400     }
0401 };
0402 
0403 class blake2s_256
0404 {
0405 private:
0406 
0407     unsigned char b_[ 64 ] = {};
0408     std::uint32_t h_[ 8 ] = {};
0409     std::uint32_t t_[ 2 ] = {};
0410     std::size_t m_ = 0;
0411 
0412     BOOST_HASH2_BLAKE2_CONSTEXPR void init( std::uint32_t keylen = 0 )
0413     {
0414         for( int i = 0; i < 8; ++i )
0415         {
0416             h_[ i ] = detail::blake2s_constants<>::iv[ i ];
0417         }
0418 
0419         std::uint32_t const outlen = 32;
0420         h_[ 0 ] ^= 0x01010000 ^ ( keylen << 8 ) ^ outlen;
0421     }
0422 
0423     BOOST_HASH2_BLAKE2_CONSTEXPR BOOST_FORCEINLINE static void G( std::uint32_t v[ 16 ], int a, int b, int c, int d, std::uint32_t x, std::uint32_t y )
0424     {
0425         v[ a ] = v[ a ] + v[ b ] + x;
0426         v[ d ] = detail::rotr( v[ d ] ^ v[ a ], 16 );
0427         v[ c ] = v[ c ] + v[ d ];
0428         v[ b ] = detail::rotr( v[ b ] ^ v[ c ], 12 );
0429         v[ a ] = v[ a ] + v[ b ] + y;
0430         v[ d ] = detail::rotr( v[ d ] ^ v[ a ], 8 );
0431         v[ c ] = v[ c ] + v[ d ];
0432         v[ b ] = detail::rotr( v[ b ] ^ v[ c ], 7 );
0433     }
0434 
0435     BOOST_HASH2_BLAKE2_CONSTEXPR void transform( unsigned char const block[ 64 ], bool is_final = false )
0436     {
0437         auto iv = detail::blake2s_constants<>::iv;
0438 
0439         std::uint32_t v[ 16 ] = {};
0440         std::uint32_t m[ 16 ] = {};
0441 
0442         v[ 0 ] = h_[ 0 ];
0443         v[ 1 ] = h_[ 1 ];
0444         v[ 2 ] = h_[ 2 ];
0445         v[ 3 ] = h_[ 3 ];
0446         v[ 4 ] = h_[ 4 ];
0447         v[ 5 ] = h_[ 5 ];
0448         v[ 6 ] = h_[ 6 ];
0449         v[ 7 ] = h_[ 7 ];
0450 
0451         v[  8 ] = iv[ 0 ];
0452         v[  9 ] = iv[ 1 ];
0453         v[ 10 ] = iv[ 2 ];
0454         v[ 11 ] = iv[ 3 ];
0455         v[ 12 ] = iv[ 4 ];
0456         v[ 13 ] = iv[ 5 ];
0457         v[ 14 ] = iv[ 6 ];
0458         v[ 15 ] = iv[ 7 ];
0459 
0460         v[ 12 ] ^= t_[ 0 ];
0461         v[ 13 ] ^= t_[ 1 ];
0462 
0463         if( is_final )
0464         {
0465             v[ 14 ] = ~v[ 14 ];
0466         }
0467 
0468         for( int i = 0; i < 16; ++i )
0469         {
0470             m[ i ] = detail::read32le( block + 4 * i );
0471         }
0472 
0473         // round 0
0474         G( v, 0, 4,  8, 12, m[  0 ], m[  1 ] );
0475         G( v, 1, 5,  9, 13, m[  2 ], m[  3 ] );
0476         G( v, 2, 6, 10, 14, m[  4 ], m[  5 ] );
0477         G( v, 3, 7, 11, 15, m[  6 ], m[  7 ] );
0478         G( v, 0, 5, 10, 15, m[  8 ], m[  9 ] );
0479         G( v, 1, 6, 11, 12, m[ 10 ], m[ 11 ] );
0480         G( v, 2, 7,  8, 13, m[ 12 ], m[ 13 ] );
0481         G( v, 3, 4,  9, 14, m[ 14 ], m[ 15 ] );
0482 
0483         // round 1
0484         G( v, 0, 4,  8, 12, m[ 14 ], m[ 10 ] );
0485         G( v, 1, 5,  9, 13, m[  4 ], m[  8 ] );
0486         G( v, 2, 6, 10, 14, m[  9 ], m[ 15 ] );
0487         G( v, 3, 7, 11, 15, m[ 13 ], m[  6 ] );
0488         G( v, 0, 5, 10, 15, m[  1 ], m[ 12 ] );
0489         G( v, 1, 6, 11, 12, m[  0 ], m[  2 ] );
0490         G( v, 2, 7,  8, 13, m[ 11 ], m[  7 ] );
0491         G( v, 3, 4,  9, 14, m[  5 ], m[  3 ] );
0492 
0493         // round 2
0494         G( v, 0, 4,  8, 12, m[ 11 ], m[  8 ] );
0495         G( v, 1, 5,  9, 13, m[ 12 ], m[  0 ] );
0496         G( v, 2, 6, 10, 14, m[  5 ], m[  2 ] );
0497         G( v, 3, 7, 11, 15, m[ 15 ], m[ 13 ] );
0498         G( v, 0, 5, 10, 15, m[ 10 ], m[ 14 ] );
0499         G( v, 1, 6, 11, 12, m[  3 ], m[  6 ] );
0500         G( v, 2, 7,  8, 13, m[  7 ], m[  1 ] );
0501         G( v, 3, 4,  9, 14, m[  9 ], m[  4 ] );
0502 
0503         // round 3
0504         G( v, 0, 4,  8, 12, m[  7 ], m[  9 ] );
0505         G( v, 1, 5,  9, 13, m[  3 ], m[  1 ] );
0506         G( v, 2, 6, 10, 14, m[ 13 ], m[ 12 ] );
0507         G( v, 3, 7, 11, 15, m[ 11 ], m[ 14 ] );
0508         G( v, 0, 5, 10, 15, m[  2 ], m[  6 ] );
0509         G( v, 1, 6, 11, 12, m[  5 ], m[ 10 ] );
0510         G( v, 2, 7,  8, 13, m[  4 ], m[  0 ] );
0511         G( v, 3, 4,  9, 14, m[ 15 ], m[  8 ] );
0512 
0513         // round 4
0514         G( v, 0, 4,  8, 12, m[  9 ], m[  0 ] );
0515         G( v, 1, 5,  9, 13, m[  5 ], m[  7 ] );
0516         G( v, 2, 6, 10, 14, m[  2 ], m[  4 ] );
0517         G( v, 3, 7, 11, 15, m[ 10 ], m[ 15 ] );
0518         G( v, 0, 5, 10, 15, m[ 14 ], m[  1 ] );
0519         G( v, 1, 6, 11, 12, m[ 11 ], m[ 12 ] );
0520         G( v, 2, 7,  8, 13, m[  6 ], m[  8 ] );
0521         G( v, 3, 4,  9, 14, m[  3 ], m[ 13 ] );
0522 
0523         // round 5
0524         G( v, 0, 4,  8, 12, m[  2 ], m[ 12 ] );
0525         G( v, 1, 5,  9, 13, m[  6 ], m[ 10 ] );
0526         G( v, 2, 6, 10, 14, m[  0 ], m[ 11 ] );
0527         G( v, 3, 7, 11, 15, m[  8 ], m[  3 ] );
0528         G( v, 0, 5, 10, 15, m[  4 ], m[ 13 ] );
0529         G( v, 1, 6, 11, 12, m[  7 ], m[  5 ] );
0530         G( v, 2, 7,  8, 13, m[ 15 ], m[ 14 ] );
0531         G( v, 3, 4,  9, 14, m[  1 ], m[  9 ] );
0532 
0533         // round 6
0534         G( v, 0, 4,  8, 12, m[ 12 ], m[  5 ] );
0535         G( v, 1, 5,  9, 13, m[  1 ], m[ 15 ] );
0536         G( v, 2, 6, 10, 14, m[ 14 ], m[ 13 ] );
0537         G( v, 3, 7, 11, 15, m[  4 ], m[ 10 ] );
0538         G( v, 0, 5, 10, 15, m[  0 ], m[  7 ] );
0539         G( v, 1, 6, 11, 12, m[  6 ], m[  3 ] );
0540         G( v, 2, 7,  8, 13, m[  9 ], m[  2 ] );
0541         G( v, 3, 4,  9, 14, m[  8 ], m[ 11 ] );
0542 
0543         // round 7
0544         G( v, 0, 4,  8, 12, m[ 13 ], m[ 11 ] );
0545         G( v, 1, 5,  9, 13, m[  7 ], m[ 14 ] );
0546         G( v, 2, 6, 10, 14, m[ 12 ], m[  1 ] );
0547         G( v, 3, 7, 11, 15, m[  3 ], m[  9 ] );
0548         G( v, 0, 5, 10, 15, m[  5 ], m[  0 ] );
0549         G( v, 1, 6, 11, 12, m[ 15 ], m[  4 ] );
0550         G( v, 2, 7,  8, 13, m[  8 ], m[  6 ] );
0551         G( v, 3, 4,  9, 14, m[  2 ], m[ 10 ] );
0552 
0553         // round 8
0554         G( v, 0, 4,  8, 12, m[  6 ], m[ 15 ] );
0555         G( v, 1, 5,  9, 13, m[ 14 ], m[  9 ] );
0556         G( v, 2, 6, 10, 14, m[ 11 ], m[  3 ] );
0557         G( v, 3, 7, 11, 15, m[  0 ], m[  8 ] );
0558         G( v, 0, 5, 10, 15, m[ 12 ], m[  2 ] );
0559         G( v, 1, 6, 11, 12, m[ 13 ], m[  7 ] );
0560         G( v, 2, 7,  8, 13, m[  1 ], m[  4 ] );
0561         G( v, 3, 4,  9, 14, m[ 10 ], m[  5 ] );
0562 
0563         // round 9
0564         G( v, 0, 4,  8, 12, m[ 10 ], m[  2 ] );
0565         G( v, 1, 5,  9, 13, m[  8 ], m[  4 ] );
0566         G( v, 2, 6, 10, 14, m[  7 ], m[  6 ] );
0567         G( v, 3, 7, 11, 15, m[  1 ], m[  5 ] );
0568         G( v, 0, 5, 10, 15, m[ 15 ], m[ 11 ] );
0569         G( v, 1, 6, 11, 12, m[  9 ], m[ 14 ] );
0570         G( v, 2, 7,  8, 13, m[  3 ], m[ 12 ] );
0571         G( v, 3, 4,  9, 14, m[ 13 ], m[  0 ] );
0572 
0573         h_[ 0 ] ^= v[ 0 ] ^ v[ 0 + 8 ];
0574         h_[ 1 ] ^= v[ 1 ] ^ v[ 1 + 8 ];
0575         h_[ 2 ] ^= v[ 2 ] ^ v[ 2 + 8 ];
0576         h_[ 3 ] ^= v[ 3 ] ^ v[ 3 + 8 ];
0577         h_[ 4 ] ^= v[ 4 ] ^ v[ 4 + 8 ];
0578         h_[ 5 ] ^= v[ 5 ] ^ v[ 5 + 8 ];
0579         h_[ 6 ] ^= v[ 6 ] ^ v[ 6 + 8 ];
0580         h_[ 7 ] ^= v[ 7 ] ^ v[ 7 + 8 ];
0581     }
0582 
0583     BOOST_HASH2_BLAKE2_CONSTEXPR void incr_len( std::size_t n )
0584     {
0585         auto m = static_cast<std::uint32_t>( n );
0586         t_[ 0 ] += m;
0587         t_[ 1 ] += ( t_[ 0 ] < m ); // overflowed
0588     }
0589 
0590 public:
0591 
0592     using result_type = digest<32>;
0593 
0594     static constexpr std::size_t block_size = 64;
0595 
0596     BOOST_HASH2_BLAKE2_CONSTEXPR blake2s_256()
0597     {
0598         init();
0599     }
0600 
0601     BOOST_HASH2_BLAKE2_CONSTEXPR explicit blake2s_256( std::uint64_t seed )
0602     {
0603         if( seed == 0 )
0604         {
0605             init();
0606             return;
0607         }
0608 
0609         unsigned char tmp[ 8 ] = {};
0610         detail::write64le( tmp, seed );
0611 
0612         init( 8 );
0613         update( tmp, 8 );
0614         m_ = block_size;
0615     }
0616 
0617     blake2s_256( void const* p, std::size_t n ) : blake2s_256( static_cast<unsigned char const*>( p ), n )
0618     {
0619     }
0620 
0621     BOOST_HASH2_BLAKE2_CONSTEXPR blake2s_256( unsigned char const* p, std::size_t n )
0622     {
0623         if( n == 0 )
0624         {
0625             init();
0626             return;
0627         }
0628 
0629         auto k = n;
0630         if( k > block_size / 2 )
0631         {
0632             k = block_size / 2;
0633         }
0634 
0635         init( static_cast<std::uint32_t>( k ) );
0636         update( p, k );
0637         m_ = block_size;
0638 
0639         p += k;
0640         n -= k;
0641 
0642         if( n != 0 )
0643         {
0644             update( p, n );
0645             result();
0646         }
0647     }
0648 
0649     void update( void const* pv, std::size_t n )
0650     {
0651         unsigned char const* p = reinterpret_cast<unsigned char const*>( pv );
0652         update( p, n );
0653     }
0654 
0655     BOOST_HASH2_BLAKE2_CONSTEXPR void update( unsigned char const* p, std::size_t n )
0656     {
0657         if( n > 0 )
0658         {
0659             std::size_t k = block_size - m_;
0660             if( n > k )
0661             {
0662                 detail::memcpy( b_ + m_, p, k );
0663                 incr_len( block_size );
0664                 transform( b_ );
0665                 detail::memset( b_ , 0,  block_size );
0666                 p += k;
0667                 n -= k;
0668                 m_ = 0;
0669 
0670                 while( n > block_size )
0671                 {
0672                     incr_len( block_size );
0673                     transform( p );
0674                     p += block_size;
0675                     n -= block_size;
0676                 }
0677             }
0678 
0679             detail::memcpy( b_ + m_, p, n );
0680             m_ += n;
0681         }
0682     }
0683 
0684     BOOST_HASH2_BLAKE2_CONSTEXPR result_type result()
0685     {
0686         result_type digest;
0687 
0688         incr_len( m_ );
0689         for( auto i = m_; i < block_size; ++i )
0690         {
0691             b_[ i ] = 0;
0692         }
0693 
0694         transform( b_, true );
0695         detail::memset( b_ , 0,  block_size );
0696         m_ = 0;
0697         for( int i = 0; i < 8; ++i )
0698         {
0699             detail::write32le( digest.data() + i * 4, h_[ i ] );
0700         }
0701         return digest;
0702     }
0703 };
0704 
0705 using hmac_blake2b_512 = hmac<blake2b_512>;
0706 using hmac_blake2s_256 = hmac<blake2s_256>;
0707 
0708 } // namespace hash2
0709 } // namespace boost
0710 
0711 #endif // BOOST_HASH2_BLAKE2_HPP_INCLUDED