17db96d56Sopenharmony_ci/* 27db96d56Sopenharmony_ci BLAKE2 reference source code package - optimized C implementations 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_ci Written in 2012 by Samuel Neves <sneves@dei.uc.pt> 57db96d56Sopenharmony_ci 67db96d56Sopenharmony_ci To the extent possible under law, the author(s) have dedicated all copyright 77db96d56Sopenharmony_ci and related and neighboring rights to this software to the public domain 87db96d56Sopenharmony_ci worldwide. This software is distributed without any warranty. 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ci You should have received a copy of the CC0 Public Domain Dedication along with 117db96d56Sopenharmony_ci this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>. 127db96d56Sopenharmony_ci*/ 137db96d56Sopenharmony_ci 147db96d56Sopenharmony_ci#include <stdint.h> 157db96d56Sopenharmony_ci#include <string.h> 167db96d56Sopenharmony_ci#include <stdio.h> 177db96d56Sopenharmony_ci 187db96d56Sopenharmony_ci#include "blake2.h" 197db96d56Sopenharmony_ci#include "blake2-impl.h" 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci#include "blake2-config.h" 227db96d56Sopenharmony_ci 237db96d56Sopenharmony_ci#if defined(_MSC_VER) 247db96d56Sopenharmony_ci#include <intrin.h> 257db96d56Sopenharmony_ci#endif 267db96d56Sopenharmony_ci 277db96d56Sopenharmony_ci#if defined(HAVE_SSE2) 287db96d56Sopenharmony_ci#include <emmintrin.h> 297db96d56Sopenharmony_ci// MSVC only defines _mm_set_epi64x for x86_64... 307db96d56Sopenharmony_ci#if defined(_MSC_VER) && !defined(_M_X64) 317db96d56Sopenharmony_cistatic inline __m128i _mm_set_epi64x( const uint64_t u1, const uint64_t u0 ) 327db96d56Sopenharmony_ci{ 337db96d56Sopenharmony_ci return _mm_set_epi32( u1 >> 32, u1, u0 >> 32, u0 ); 347db96d56Sopenharmony_ci} 357db96d56Sopenharmony_ci#endif 367db96d56Sopenharmony_ci#endif 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_ci#if defined(HAVE_SSSE3) 407db96d56Sopenharmony_ci#include <tmmintrin.h> 417db96d56Sopenharmony_ci#endif 427db96d56Sopenharmony_ci#if defined(HAVE_SSE4_1) 437db96d56Sopenharmony_ci#include <smmintrin.h> 447db96d56Sopenharmony_ci#endif 457db96d56Sopenharmony_ci#if defined(HAVE_AVX) 467db96d56Sopenharmony_ci#include <immintrin.h> 477db96d56Sopenharmony_ci#endif 487db96d56Sopenharmony_ci#if defined(HAVE_XOP) && !defined(_MSC_VER) 497db96d56Sopenharmony_ci#include <x86intrin.h> 507db96d56Sopenharmony_ci#endif 517db96d56Sopenharmony_ci 527db96d56Sopenharmony_ci#include "blake2s-round.h" 537db96d56Sopenharmony_ci 547db96d56Sopenharmony_cistatic const uint32_t blake2s_IV[8] = 557db96d56Sopenharmony_ci{ 567db96d56Sopenharmony_ci 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, 577db96d56Sopenharmony_ci 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL 587db96d56Sopenharmony_ci}; 597db96d56Sopenharmony_ci 607db96d56Sopenharmony_cistatic const uint8_t blake2s_sigma[10][16] = 617db96d56Sopenharmony_ci{ 627db96d56Sopenharmony_ci { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 637db96d56Sopenharmony_ci { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , 647db96d56Sopenharmony_ci { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , 657db96d56Sopenharmony_ci { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , 667db96d56Sopenharmony_ci { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , 677db96d56Sopenharmony_ci { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , 687db96d56Sopenharmony_ci { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , 697db96d56Sopenharmony_ci { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , 707db96d56Sopenharmony_ci { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , 717db96d56Sopenharmony_ci { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , 727db96d56Sopenharmony_ci}; 737db96d56Sopenharmony_ci 747db96d56Sopenharmony_ci 757db96d56Sopenharmony_ci/* Some helper functions, not necessarily useful */ 767db96d56Sopenharmony_cistatic inline int blake2s_set_lastnode( blake2s_state *S ) 777db96d56Sopenharmony_ci{ 787db96d56Sopenharmony_ci S->f[1] = ~0U; 797db96d56Sopenharmony_ci return 0; 807db96d56Sopenharmony_ci} 817db96d56Sopenharmony_ci 827db96d56Sopenharmony_cistatic inline int blake2s_clear_lastnode( blake2s_state *S ) 837db96d56Sopenharmony_ci{ 847db96d56Sopenharmony_ci S->f[1] = 0U; 857db96d56Sopenharmony_ci return 0; 867db96d56Sopenharmony_ci} 877db96d56Sopenharmony_ci 887db96d56Sopenharmony_cistatic inline int blake2s_set_lastblock( blake2s_state *S ) 897db96d56Sopenharmony_ci{ 907db96d56Sopenharmony_ci if( S->last_node ) blake2s_set_lastnode( S ); 917db96d56Sopenharmony_ci 927db96d56Sopenharmony_ci S->f[0] = ~0U; 937db96d56Sopenharmony_ci return 0; 947db96d56Sopenharmony_ci} 957db96d56Sopenharmony_ci 967db96d56Sopenharmony_cistatic inline int blake2s_clear_lastblock( blake2s_state *S ) 977db96d56Sopenharmony_ci{ 987db96d56Sopenharmony_ci if( S->last_node ) blake2s_clear_lastnode( S ); 997db96d56Sopenharmony_ci 1007db96d56Sopenharmony_ci S->f[0] = 0U; 1017db96d56Sopenharmony_ci return 0; 1027db96d56Sopenharmony_ci} 1037db96d56Sopenharmony_ci 1047db96d56Sopenharmony_cistatic inline int blake2s_increment_counter( blake2s_state *S, const uint32_t inc ) 1057db96d56Sopenharmony_ci{ 1067db96d56Sopenharmony_ci uint64_t t = ( ( uint64_t )S->t[1] << 32 ) | S->t[0]; 1077db96d56Sopenharmony_ci t += inc; 1087db96d56Sopenharmony_ci S->t[0] = ( uint32_t )( t >> 0 ); 1097db96d56Sopenharmony_ci S->t[1] = ( uint32_t )( t >> 32 ); 1107db96d56Sopenharmony_ci return 0; 1117db96d56Sopenharmony_ci} 1127db96d56Sopenharmony_ci 1137db96d56Sopenharmony_ci 1147db96d56Sopenharmony_ci// Parameter-related functions 1157db96d56Sopenharmony_cistatic inline int blake2s_param_set_digest_length( blake2s_param *P, const uint8_t digest_length ) 1167db96d56Sopenharmony_ci{ 1177db96d56Sopenharmony_ci P->digest_length = digest_length; 1187db96d56Sopenharmony_ci return 0; 1197db96d56Sopenharmony_ci} 1207db96d56Sopenharmony_ci 1217db96d56Sopenharmony_cistatic inline int blake2s_param_set_fanout( blake2s_param *P, const uint8_t fanout ) 1227db96d56Sopenharmony_ci{ 1237db96d56Sopenharmony_ci P->fanout = fanout; 1247db96d56Sopenharmony_ci return 0; 1257db96d56Sopenharmony_ci} 1267db96d56Sopenharmony_ci 1277db96d56Sopenharmony_cistatic inline int blake2s_param_set_max_depth( blake2s_param *P, const uint8_t depth ) 1287db96d56Sopenharmony_ci{ 1297db96d56Sopenharmony_ci P->depth = depth; 1307db96d56Sopenharmony_ci return 0; 1317db96d56Sopenharmony_ci} 1327db96d56Sopenharmony_ci 1337db96d56Sopenharmony_cistatic inline int blake2s_param_set_leaf_length( blake2s_param *P, const uint32_t leaf_length ) 1347db96d56Sopenharmony_ci{ 1357db96d56Sopenharmony_ci P->leaf_length = leaf_length; 1367db96d56Sopenharmony_ci return 0; 1377db96d56Sopenharmony_ci} 1387db96d56Sopenharmony_ci 1397db96d56Sopenharmony_cistatic inline int blake2s_param_set_node_offset( blake2s_param *P, const uint64_t node_offset ) 1407db96d56Sopenharmony_ci{ 1417db96d56Sopenharmony_ci store48( P->node_offset, node_offset ); 1427db96d56Sopenharmony_ci return 0; 1437db96d56Sopenharmony_ci} 1447db96d56Sopenharmony_ci 1457db96d56Sopenharmony_cistatic inline int blake2s_param_set_node_depth( blake2s_param *P, const uint8_t node_depth ) 1467db96d56Sopenharmony_ci{ 1477db96d56Sopenharmony_ci P->node_depth = node_depth; 1487db96d56Sopenharmony_ci return 0; 1497db96d56Sopenharmony_ci} 1507db96d56Sopenharmony_ci 1517db96d56Sopenharmony_cistatic inline int blake2s_param_set_inner_length( blake2s_param *P, const uint8_t inner_length ) 1527db96d56Sopenharmony_ci{ 1537db96d56Sopenharmony_ci P->inner_length = inner_length; 1547db96d56Sopenharmony_ci return 0; 1557db96d56Sopenharmony_ci} 1567db96d56Sopenharmony_ci 1577db96d56Sopenharmony_cistatic inline int blake2s_param_set_salt( blake2s_param *P, const uint8_t salt[BLAKE2S_SALTBYTES] ) 1587db96d56Sopenharmony_ci{ 1597db96d56Sopenharmony_ci memcpy( P->salt, salt, BLAKE2S_SALTBYTES ); 1607db96d56Sopenharmony_ci return 0; 1617db96d56Sopenharmony_ci} 1627db96d56Sopenharmony_ci 1637db96d56Sopenharmony_cistatic inline int blake2s_param_set_personal( blake2s_param *P, const uint8_t personal[BLAKE2S_PERSONALBYTES] ) 1647db96d56Sopenharmony_ci{ 1657db96d56Sopenharmony_ci memcpy( P->personal, personal, BLAKE2S_PERSONALBYTES ); 1667db96d56Sopenharmony_ci return 0; 1677db96d56Sopenharmony_ci} 1687db96d56Sopenharmony_ci 1697db96d56Sopenharmony_cistatic inline int blake2s_init0( blake2s_state *S ) 1707db96d56Sopenharmony_ci{ 1717db96d56Sopenharmony_ci memset( S, 0, sizeof( blake2s_state ) ); 1727db96d56Sopenharmony_ci 1737db96d56Sopenharmony_ci for( int i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i]; 1747db96d56Sopenharmony_ci 1757db96d56Sopenharmony_ci return 0; 1767db96d56Sopenharmony_ci} 1777db96d56Sopenharmony_ci 1787db96d56Sopenharmony_ci#if defined(__cplusplus) 1797db96d56Sopenharmony_ciextern "C" { 1807db96d56Sopenharmony_ci#endif 1817db96d56Sopenharmony_ci int blake2s_init( blake2s_state *S, size_t outlen ); 1827db96d56Sopenharmony_ci int blake2s_init_param( blake2s_state *S, const blake2s_param *P ); 1837db96d56Sopenharmony_ci int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen ); 1847db96d56Sopenharmony_ci int blake2s_update( blake2s_state *S, const uint8_t *in, size_t inlen ); 1857db96d56Sopenharmony_ci int blake2s_final( blake2s_state *S, uint8_t *out, size_t outlen ); 1867db96d56Sopenharmony_ci int blake2s( uint8_t *out, const void *in, const void *key, size_t outlen, size_t inlen, size_t keylen ); 1877db96d56Sopenharmony_ci#if defined(__cplusplus) 1887db96d56Sopenharmony_ci} 1897db96d56Sopenharmony_ci#endif 1907db96d56Sopenharmony_ci 1917db96d56Sopenharmony_ci 1927db96d56Sopenharmony_ci/* init2 xors IV with input parameter block */ 1937db96d56Sopenharmony_ciint blake2s_init_param( blake2s_state *S, const blake2s_param *P ) 1947db96d56Sopenharmony_ci{ 1957db96d56Sopenharmony_ci uint8_t *p, *h, *v; 1967db96d56Sopenharmony_ci //blake2s_init0( S ); 1977db96d56Sopenharmony_ci v = ( uint8_t * )( blake2s_IV ); 1987db96d56Sopenharmony_ci h = ( uint8_t * )( S->h ); 1997db96d56Sopenharmony_ci p = ( uint8_t * )( P ); 2007db96d56Sopenharmony_ci /* IV XOR ParamBlock */ 2017db96d56Sopenharmony_ci memset( S, 0, sizeof( blake2s_state ) ); 2027db96d56Sopenharmony_ci 2037db96d56Sopenharmony_ci for( int i = 0; i < BLAKE2S_OUTBYTES; ++i ) h[i] = v[i] ^ p[i]; 2047db96d56Sopenharmony_ci 2057db96d56Sopenharmony_ci S->outlen = P->digest_length; 2067db96d56Sopenharmony_ci return 0; 2077db96d56Sopenharmony_ci} 2087db96d56Sopenharmony_ci 2097db96d56Sopenharmony_ci 2107db96d56Sopenharmony_ci/* Some sort of default parameter block initialization, for sequential blake2s */ 2117db96d56Sopenharmony_ciint blake2s_init( blake2s_state *S, size_t outlen ) 2127db96d56Sopenharmony_ci{ 2137db96d56Sopenharmony_ci if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; 2147db96d56Sopenharmony_ci 2157db96d56Sopenharmony_ci const blake2s_param P = 2167db96d56Sopenharmony_ci { 2177db96d56Sopenharmony_ci outlen, 2187db96d56Sopenharmony_ci 0, 2197db96d56Sopenharmony_ci 1, 2207db96d56Sopenharmony_ci 1, 2217db96d56Sopenharmony_ci 0, 2227db96d56Sopenharmony_ci {0}, 2237db96d56Sopenharmony_ci 0, 2247db96d56Sopenharmony_ci 0, 2257db96d56Sopenharmony_ci {0}, 2267db96d56Sopenharmony_ci {0} 2277db96d56Sopenharmony_ci }; 2287db96d56Sopenharmony_ci return blake2s_init_param( S, &P ); 2297db96d56Sopenharmony_ci} 2307db96d56Sopenharmony_ci 2317db96d56Sopenharmony_ci 2327db96d56Sopenharmony_ciint blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen ) 2337db96d56Sopenharmony_ci{ 2347db96d56Sopenharmony_ci if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; 2357db96d56Sopenharmony_ci 2367db96d56Sopenharmony_ci if ( ( !key ) || ( !keylen ) || keylen > BLAKE2S_KEYBYTES ) return -1; 2377db96d56Sopenharmony_ci 2387db96d56Sopenharmony_ci const blake2s_param P = 2397db96d56Sopenharmony_ci { 2407db96d56Sopenharmony_ci outlen, 2417db96d56Sopenharmony_ci keylen, 2427db96d56Sopenharmony_ci 1, 2437db96d56Sopenharmony_ci 1, 2447db96d56Sopenharmony_ci 0, 2457db96d56Sopenharmony_ci {0}, 2467db96d56Sopenharmony_ci 0, 2477db96d56Sopenharmony_ci 0, 2487db96d56Sopenharmony_ci {0}, 2497db96d56Sopenharmony_ci {0} 2507db96d56Sopenharmony_ci }; 2517db96d56Sopenharmony_ci 2527db96d56Sopenharmony_ci if( blake2s_init_param( S, &P ) < 0 ) 2537db96d56Sopenharmony_ci return -1; 2547db96d56Sopenharmony_ci 2557db96d56Sopenharmony_ci { 2567db96d56Sopenharmony_ci uint8_t block[BLAKE2S_BLOCKBYTES]; 2577db96d56Sopenharmony_ci memset( block, 0, BLAKE2S_BLOCKBYTES ); 2587db96d56Sopenharmony_ci memcpy( block, key, keylen ); 2597db96d56Sopenharmony_ci blake2s_update( S, block, BLAKE2S_BLOCKBYTES ); 2607db96d56Sopenharmony_ci secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */ 2617db96d56Sopenharmony_ci } 2627db96d56Sopenharmony_ci return 0; 2637db96d56Sopenharmony_ci} 2647db96d56Sopenharmony_ci 2657db96d56Sopenharmony_ci 2667db96d56Sopenharmony_cistatic inline int blake2s_compress( blake2s_state *S, const uint8_t block[BLAKE2S_BLOCKBYTES] ) 2677db96d56Sopenharmony_ci{ 2687db96d56Sopenharmony_ci __m128i row1, row2, row3, row4; 2697db96d56Sopenharmony_ci __m128i buf1, buf2, buf3, buf4; 2707db96d56Sopenharmony_ci#if defined(HAVE_SSE4_1) 2717db96d56Sopenharmony_ci __m128i t0, t1; 2727db96d56Sopenharmony_ci#if !defined(HAVE_XOP) 2737db96d56Sopenharmony_ci __m128i t2; 2747db96d56Sopenharmony_ci#endif 2757db96d56Sopenharmony_ci#endif 2767db96d56Sopenharmony_ci __m128i ff0, ff1; 2777db96d56Sopenharmony_ci#if defined(HAVE_SSSE3) && !defined(HAVE_XOP) 2787db96d56Sopenharmony_ci const __m128i r8 = _mm_set_epi8( 12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1 ); 2797db96d56Sopenharmony_ci const __m128i r16 = _mm_set_epi8( 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2 ); 2807db96d56Sopenharmony_ci#endif 2817db96d56Sopenharmony_ci#if defined(HAVE_SSE4_1) 2827db96d56Sopenharmony_ci const __m128i m0 = LOADU( block + 00 ); 2837db96d56Sopenharmony_ci const __m128i m1 = LOADU( block + 16 ); 2847db96d56Sopenharmony_ci const __m128i m2 = LOADU( block + 32 ); 2857db96d56Sopenharmony_ci const __m128i m3 = LOADU( block + 48 ); 2867db96d56Sopenharmony_ci#else 2877db96d56Sopenharmony_ci const uint32_t m0 = ( ( uint32_t * )block )[ 0]; 2887db96d56Sopenharmony_ci const uint32_t m1 = ( ( uint32_t * )block )[ 1]; 2897db96d56Sopenharmony_ci const uint32_t m2 = ( ( uint32_t * )block )[ 2]; 2907db96d56Sopenharmony_ci const uint32_t m3 = ( ( uint32_t * )block )[ 3]; 2917db96d56Sopenharmony_ci const uint32_t m4 = ( ( uint32_t * )block )[ 4]; 2927db96d56Sopenharmony_ci const uint32_t m5 = ( ( uint32_t * )block )[ 5]; 2937db96d56Sopenharmony_ci const uint32_t m6 = ( ( uint32_t * )block )[ 6]; 2947db96d56Sopenharmony_ci const uint32_t m7 = ( ( uint32_t * )block )[ 7]; 2957db96d56Sopenharmony_ci const uint32_t m8 = ( ( uint32_t * )block )[ 8]; 2967db96d56Sopenharmony_ci const uint32_t m9 = ( ( uint32_t * )block )[ 9]; 2977db96d56Sopenharmony_ci const uint32_t m10 = ( ( uint32_t * )block )[10]; 2987db96d56Sopenharmony_ci const uint32_t m11 = ( ( uint32_t * )block )[11]; 2997db96d56Sopenharmony_ci const uint32_t m12 = ( ( uint32_t * )block )[12]; 3007db96d56Sopenharmony_ci const uint32_t m13 = ( ( uint32_t * )block )[13]; 3017db96d56Sopenharmony_ci const uint32_t m14 = ( ( uint32_t * )block )[14]; 3027db96d56Sopenharmony_ci const uint32_t m15 = ( ( uint32_t * )block )[15]; 3037db96d56Sopenharmony_ci#endif 3047db96d56Sopenharmony_ci row1 = ff0 = LOADU( &S->h[0] ); 3057db96d56Sopenharmony_ci row2 = ff1 = LOADU( &S->h[4] ); 3067db96d56Sopenharmony_ci row3 = _mm_setr_epi32( 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A ); 3077db96d56Sopenharmony_ci row4 = _mm_xor_si128( _mm_setr_epi32( 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 ), LOADU( &S->t[0] ) ); 3087db96d56Sopenharmony_ci ROUND( 0 ); 3097db96d56Sopenharmony_ci ROUND( 1 ); 3107db96d56Sopenharmony_ci ROUND( 2 ); 3117db96d56Sopenharmony_ci ROUND( 3 ); 3127db96d56Sopenharmony_ci ROUND( 4 ); 3137db96d56Sopenharmony_ci ROUND( 5 ); 3147db96d56Sopenharmony_ci ROUND( 6 ); 3157db96d56Sopenharmony_ci ROUND( 7 ); 3167db96d56Sopenharmony_ci ROUND( 8 ); 3177db96d56Sopenharmony_ci ROUND( 9 ); 3187db96d56Sopenharmony_ci STOREU( &S->h[0], _mm_xor_si128( ff0, _mm_xor_si128( row1, row3 ) ) ); 3197db96d56Sopenharmony_ci STOREU( &S->h[4], _mm_xor_si128( ff1, _mm_xor_si128( row2, row4 ) ) ); 3207db96d56Sopenharmony_ci return 0; 3217db96d56Sopenharmony_ci} 3227db96d56Sopenharmony_ci 3237db96d56Sopenharmony_ci 3247db96d56Sopenharmony_ciint blake2s_update( blake2s_state *S, const uint8_t *in, size_t inlen ) 3257db96d56Sopenharmony_ci{ 3267db96d56Sopenharmony_ci while( inlen > 0 ) 3277db96d56Sopenharmony_ci { 3287db96d56Sopenharmony_ci size_t left = S->buflen; 3297db96d56Sopenharmony_ci size_t fill = 2 * BLAKE2S_BLOCKBYTES - left; 3307db96d56Sopenharmony_ci 3317db96d56Sopenharmony_ci if( inlen > fill ) 3327db96d56Sopenharmony_ci { 3337db96d56Sopenharmony_ci memcpy( S->buf + left, in, fill ); // Fill buffer 3347db96d56Sopenharmony_ci S->buflen += fill; 3357db96d56Sopenharmony_ci blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); 3367db96d56Sopenharmony_ci blake2s_compress( S, S->buf ); // Compress 3377db96d56Sopenharmony_ci memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); // Shift buffer left 3387db96d56Sopenharmony_ci S->buflen -= BLAKE2S_BLOCKBYTES; 3397db96d56Sopenharmony_ci in += fill; 3407db96d56Sopenharmony_ci inlen -= fill; 3417db96d56Sopenharmony_ci } 3427db96d56Sopenharmony_ci else /* inlen <= fill */ 3437db96d56Sopenharmony_ci { 3447db96d56Sopenharmony_ci memcpy( S->buf + left, in, inlen ); 3457db96d56Sopenharmony_ci S->buflen += inlen; // Be lazy, do not compress 3467db96d56Sopenharmony_ci in += inlen; 3477db96d56Sopenharmony_ci inlen -= inlen; 3487db96d56Sopenharmony_ci } 3497db96d56Sopenharmony_ci } 3507db96d56Sopenharmony_ci 3517db96d56Sopenharmony_ci return 0; 3527db96d56Sopenharmony_ci} 3537db96d56Sopenharmony_ci 3547db96d56Sopenharmony_ci 3557db96d56Sopenharmony_ciint blake2s_final( blake2s_state *S, uint8_t *out, size_t outlen ) 3567db96d56Sopenharmony_ci{ 3577db96d56Sopenharmony_ci uint8_t buffer[BLAKE2S_OUTBYTES]; 3587db96d56Sopenharmony_ci 3597db96d56Sopenharmony_ci if(outlen != S->outlen ) return -1; 3607db96d56Sopenharmony_ci 3617db96d56Sopenharmony_ci if( S->buflen > BLAKE2S_BLOCKBYTES ) 3627db96d56Sopenharmony_ci { 3637db96d56Sopenharmony_ci blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); 3647db96d56Sopenharmony_ci blake2s_compress( S, S->buf ); 3657db96d56Sopenharmony_ci S->buflen -= BLAKE2S_BLOCKBYTES; 3667db96d56Sopenharmony_ci memmove( S->buf, S->buf + BLAKE2S_BLOCKBYTES, S->buflen ); 3677db96d56Sopenharmony_ci } 3687db96d56Sopenharmony_ci 3697db96d56Sopenharmony_ci blake2s_increment_counter( S, ( uint32_t )S->buflen ); 3707db96d56Sopenharmony_ci blake2s_set_lastblock( S ); 3717db96d56Sopenharmony_ci memset( S->buf + S->buflen, 0, 2 * BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */ 3727db96d56Sopenharmony_ci blake2s_compress( S, S->buf ); 3737db96d56Sopenharmony_ci 3747db96d56Sopenharmony_ci for( int i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ 3757db96d56Sopenharmony_ci store32( buffer + sizeof( S->h[i] ) * i, S->h[i] ); 3767db96d56Sopenharmony_ci 3777db96d56Sopenharmony_ci memcpy( out, buffer, outlen ); 3787db96d56Sopenharmony_ci return 0; 3797db96d56Sopenharmony_ci} 3807db96d56Sopenharmony_ci 3817db96d56Sopenharmony_ciint blake2s( uint8_t *out, const void *in, const void *key, size_t outlen, size_t inlen, size_t keylen ) 3827db96d56Sopenharmony_ci{ 3837db96d56Sopenharmony_ci blake2s_state S[1]; 3847db96d56Sopenharmony_ci 3857db96d56Sopenharmony_ci /* Verify parameters */ 3867db96d56Sopenharmony_ci if ( NULL == in && inlen > 0 ) return -1; 3877db96d56Sopenharmony_ci 3887db96d56Sopenharmony_ci if ( NULL == out ) return -1; 3897db96d56Sopenharmony_ci 3907db96d56Sopenharmony_ci if ( NULL == key && keylen > 0) return -1; 3917db96d56Sopenharmony_ci 3927db96d56Sopenharmony_ci if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1; 3937db96d56Sopenharmony_ci 3947db96d56Sopenharmony_ci if( keylen > BLAKE2S_KEYBYTES ) return -1; 3957db96d56Sopenharmony_ci 3967db96d56Sopenharmony_ci if( keylen > 0 ) 3977db96d56Sopenharmony_ci { 3987db96d56Sopenharmony_ci if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1; 3997db96d56Sopenharmony_ci } 4007db96d56Sopenharmony_ci else 4017db96d56Sopenharmony_ci { 4027db96d56Sopenharmony_ci if( blake2s_init( S, outlen ) < 0 ) return -1; 4037db96d56Sopenharmony_ci } 4047db96d56Sopenharmony_ci 4057db96d56Sopenharmony_ci if( blake2s_update( S, ( uint8_t * )in, inlen ) < 0) return -1; 4067db96d56Sopenharmony_ci return blake2s_final( S, out, outlen ); 4077db96d56Sopenharmony_ci} 4087db96d56Sopenharmony_ci 4097db96d56Sopenharmony_ci#if defined(SUPERCOP) 4107db96d56Sopenharmony_ciint crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen ) 4117db96d56Sopenharmony_ci{ 4127db96d56Sopenharmony_ci return blake2s( out, in, NULL, BLAKE2S_OUTBYTES, (size_t)inlen, 0 ); 4137db96d56Sopenharmony_ci} 4147db96d56Sopenharmony_ci#endif 4157db96d56Sopenharmony_ci 416