"Das U-Boot" Source Tree

lib: add BLAKE2 hash support

The code is cross-ported from BLAKE2 reference implementation
(https://github.com/BLAKE2/BLAKE2).

With minimal change to remove unused macros/features.

Currently there is only one user inside U-boot (btrfs), and since it
only utilize BLAKE2B, all other favors are all removed.

Signed-off-by: Qu Wenruo <wqu@suse.com>
[trini: Rename ROUND to R to avoid clash with <linux/bitops.h>
Signed-off-by: Tom Rini <trini@konsulko.com>

authored by

Qu Wenruo and committed by
Tom Rini
7c3fd5c2 ae435aef

+577
+94
include/u-boot/blake2.h
··· 1 + /* SPDX-License-Identifier: CC0-1.0 */ 2 + /* 3 + BLAKE2 reference source code package - reference C implementations 4 + 5 + Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the 6 + terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 7 + your option. The terms of these licenses can be found at: 8 + 9 + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 10 + - OpenSSL license : https://www.openssl.org/source/license.html 11 + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 12 + 13 + More information about the BLAKE2 hash function can be found at 14 + https://blake2.net. 15 + */ 16 + 17 + /* 18 + * Cross-ported from BLAKE2 (https://github.com/BLAKE2/BLAKE2). 19 + * Modifications includes: 20 + * 21 + * - Remove unsupported compilers like MSC/CPP 22 + * - Remove blake2s/blake2sp/blake2bp 23 + * This blake2 implementation is mostly for btrfs, which only utilizes 24 + * blake2b. 25 + */ 26 + #ifndef BLAKE2_H 27 + #define BLAKE2_H 28 + 29 + #include <stddef.h> 30 + #include <stdint.h> 31 + 32 + #if defined(_MSC_VER) 33 + #define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop)) 34 + #else 35 + #define BLAKE2_PACKED(x) x __attribute__((packed)) 36 + #endif 37 + 38 + enum blake2b_constant 39 + { 40 + BLAKE2B_BLOCKBYTES = 128, 41 + BLAKE2B_OUTBYTES = 64, 42 + BLAKE2B_KEYBYTES = 64, 43 + BLAKE2B_SALTBYTES = 16, 44 + BLAKE2B_PERSONALBYTES = 16 45 + }; 46 + 47 + typedef struct blake2b_state__ 48 + { 49 + uint64_t h[8]; 50 + uint64_t t[2]; 51 + uint64_t f[2]; 52 + uint8_t buf[BLAKE2B_BLOCKBYTES]; 53 + size_t buflen; 54 + size_t outlen; 55 + uint8_t last_node; 56 + } blake2b_state; 57 + 58 + BLAKE2_PACKED(struct blake2b_param__ 59 + { 60 + uint8_t digest_length; /* 1 */ 61 + uint8_t key_length; /* 2 */ 62 + uint8_t fanout; /* 3 */ 63 + uint8_t depth; /* 4 */ 64 + uint32_t leaf_length; /* 8 */ 65 + uint32_t node_offset; /* 12 */ 66 + uint32_t xof_length; /* 16 */ 67 + uint8_t node_depth; /* 17 */ 68 + uint8_t inner_length; /* 18 */ 69 + uint8_t reserved[14]; /* 32 */ 70 + uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ 71 + uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ 72 + }); 73 + 74 + typedef struct blake2b_param__ blake2b_param; 75 + 76 + /* Padded structs result in a compile-time error */ 77 + enum { 78 + BLAKE2_DUMMY_2 = 1/(int)(sizeof(blake2b_param) == BLAKE2B_OUTBYTES) 79 + }; 80 + 81 + /* Streaming API */ 82 + int blake2b_init( blake2b_state *S, size_t outlen ); 83 + int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen ); 84 + int blake2b_init_param( blake2b_state *S, const blake2b_param *P ); 85 + int blake2b_update( blake2b_state *S, const void *in, size_t inlen ); 86 + int blake2b_final( blake2b_state *S, void *out, size_t outlen ); 87 + 88 + /* Simple API */ 89 + int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); 90 + 91 + /* This is simply an alias for blake2b */ 92 + int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); 93 + 94 + #endif
+8
lib/Kconfig
··· 367 367 368 368 menu "Hashing Support" 369 369 370 + config BLAKE2 371 + bool "Enable BLAKE2 support" 372 + help 373 + This option enables support of hashing using BLAKE2B algorithm. 374 + The hash is calculated in software. 375 + The BLAKE2 algorithm produces a hash value (digest) between 1 and 376 + 64 bytes. 377 + 370 378 config SHA1 371 379 bool "Enable SHA1 support" 372 380 help
+1
lib/Makefile
··· 63 63 obj-$(CONFIG_ECDSA) += ecdsa/ 64 64 obj-$(CONFIG_$(SPL_)RSA) += rsa/ 65 65 obj-$(CONFIG_HASH) += hash-checksum.o 66 + obj-$(CONFIG_BLAKE2) += blake2/blake2b.o 66 67 obj-$(CONFIG_SHA1) += sha1.o 67 68 obj-$(CONFIG_SHA256) += sha256.o 68 69 obj-$(CONFIG_SHA512) += sha512.o
+163
lib/blake2/blake2-impl.h
··· 1 + /* SPDX-License-Identifier: CC0-1.0 */ 2 + /* 3 + BLAKE2 reference source code package - reference C implementations 4 + 5 + Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the 6 + terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 7 + your option. The terms of these licenses can be found at: 8 + 9 + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 10 + - OpenSSL license : https://www.openssl.org/source/license.html 11 + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 12 + 13 + More information about the BLAKE2 hash function can be found at 14 + https://blake2.net. 15 + */ 16 + 17 + /* 18 + * Cross-ported from BLAKE2 (https://github.com/BLAKE2/BLAKE2). 19 + * Modifications includes: 20 + * 21 + * - Remove unsupported compilers like MSC/CPP 22 + * - Use u-boot library functions/macros 23 + */ 24 + #ifndef BLAKE2_IMPL_H 25 + #define BLAKE2_IMPL_H 26 + 27 + #include <stdint.h> 28 + #include <string.h> 29 + 30 + #define BLAKE2_INLINE inline 31 + 32 + #ifdef __LITTLE_ENDIAN 33 + # define NATIVE_LITTLE_ENDIAN 34 + #endif 35 + 36 + static BLAKE2_INLINE uint32_t load32( const void *src ) 37 + { 38 + #if defined(NATIVE_LITTLE_ENDIAN) 39 + uint32_t w; 40 + memcpy(&w, src, sizeof w); 41 + return w; 42 + #else 43 + const uint8_t *p = ( const uint8_t * )src; 44 + return (( uint32_t )( p[0] ) << 0) | 45 + (( uint32_t )( p[1] ) << 8) | 46 + (( uint32_t )( p[2] ) << 16) | 47 + (( uint32_t )( p[3] ) << 24) ; 48 + #endif 49 + } 50 + 51 + static BLAKE2_INLINE uint64_t load64( const void *src ) 52 + { 53 + #if defined(NATIVE_LITTLE_ENDIAN) 54 + uint64_t w; 55 + memcpy(&w, src, sizeof w); 56 + return w; 57 + #else 58 + const uint8_t *p = ( const uint8_t * )src; 59 + return (( uint64_t )( p[0] ) << 0) | 60 + (( uint64_t )( p[1] ) << 8) | 61 + (( uint64_t )( p[2] ) << 16) | 62 + (( uint64_t )( p[3] ) << 24) | 63 + (( uint64_t )( p[4] ) << 32) | 64 + (( uint64_t )( p[5] ) << 40) | 65 + (( uint64_t )( p[6] ) << 48) | 66 + (( uint64_t )( p[7] ) << 56) ; 67 + #endif 68 + } 69 + 70 + static BLAKE2_INLINE uint16_t load16( const void *src ) 71 + { 72 + #if defined(NATIVE_LITTLE_ENDIAN) 73 + uint16_t w; 74 + memcpy(&w, src, sizeof w); 75 + return w; 76 + #else 77 + const uint8_t *p = ( const uint8_t * )src; 78 + return ( uint16_t )((( uint32_t )( p[0] ) << 0) | 79 + (( uint32_t )( p[1] ) << 8)); 80 + #endif 81 + } 82 + 83 + static BLAKE2_INLINE void store16( void *dst, uint16_t w ) 84 + { 85 + #if defined(NATIVE_LITTLE_ENDIAN) 86 + memcpy(dst, &w, sizeof w); 87 + #else 88 + uint8_t *p = ( uint8_t * )dst; 89 + *p++ = ( uint8_t )w; w >>= 8; 90 + *p++ = ( uint8_t )w; 91 + #endif 92 + } 93 + 94 + static BLAKE2_INLINE void store32( void *dst, uint32_t w ) 95 + { 96 + #if defined(NATIVE_LITTLE_ENDIAN) 97 + memcpy(dst, &w, sizeof w); 98 + #else 99 + uint8_t *p = ( uint8_t * )dst; 100 + p[0] = (uint8_t)(w >> 0); 101 + p[1] = (uint8_t)(w >> 8); 102 + p[2] = (uint8_t)(w >> 16); 103 + p[3] = (uint8_t)(w >> 24); 104 + #endif 105 + } 106 + 107 + static BLAKE2_INLINE void store64( void *dst, uint64_t w ) 108 + { 109 + #if defined(NATIVE_LITTLE_ENDIAN) 110 + memcpy(dst, &w, sizeof w); 111 + #else 112 + uint8_t *p = ( uint8_t * )dst; 113 + p[0] = (uint8_t)(w >> 0); 114 + p[1] = (uint8_t)(w >> 8); 115 + p[2] = (uint8_t)(w >> 16); 116 + p[3] = (uint8_t)(w >> 24); 117 + p[4] = (uint8_t)(w >> 32); 118 + p[5] = (uint8_t)(w >> 40); 119 + p[6] = (uint8_t)(w >> 48); 120 + p[7] = (uint8_t)(w >> 56); 121 + #endif 122 + } 123 + 124 + static BLAKE2_INLINE uint64_t load48( const void *src ) 125 + { 126 + const uint8_t *p = ( const uint8_t * )src; 127 + return (( uint64_t )( p[0] ) << 0) | 128 + (( uint64_t )( p[1] ) << 8) | 129 + (( uint64_t )( p[2] ) << 16) | 130 + (( uint64_t )( p[3] ) << 24) | 131 + (( uint64_t )( p[4] ) << 32) | 132 + (( uint64_t )( p[5] ) << 40) ; 133 + } 134 + 135 + static BLAKE2_INLINE void store48( void *dst, uint64_t w ) 136 + { 137 + uint8_t *p = ( uint8_t * )dst; 138 + p[0] = (uint8_t)(w >> 0); 139 + p[1] = (uint8_t)(w >> 8); 140 + p[2] = (uint8_t)(w >> 16); 141 + p[3] = (uint8_t)(w >> 24); 142 + p[4] = (uint8_t)(w >> 32); 143 + p[5] = (uint8_t)(w >> 40); 144 + } 145 + 146 + static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c ) 147 + { 148 + return ( w >> c ) | ( w << ( 32 - c ) ); 149 + } 150 + 151 + static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c ) 152 + { 153 + return ( w >> c ) | ( w << ( 64 - c ) ); 154 + } 155 + 156 + /* prevents compiler optimizing out memset() */ 157 + static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) 158 + { 159 + static void *(*const volatile memset_v)(void *, int, size_t) = &memset; 160 + memset_v(v, 0, n); 161 + } 162 + 163 + #endif
+311
lib/blake2/blake2b.c
··· 1 + /* SPDX-License-Identifier: CC0-1.0 */ 2 + /* 3 + BLAKE2 reference source code package - reference C implementations 4 + 5 + Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the 6 + terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 7 + your option. The terms of these licenses can be found at: 8 + 9 + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 10 + - OpenSSL license : https://www.openssl.org/source/license.html 11 + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 12 + 13 + More information about the BLAKE2 hash function can be found at 14 + https://blake2.net. 15 + */ 16 + 17 + /* 18 + * Cross-ported from BLAKE2 (https://github.com/BLAKE2/BLAKE2). 19 + * Modifications includes: 20 + * 21 + * - Remove unused features like selftest 22 + * - Use u-boot library functions/macros 23 + */ 24 + #include <stdint.h> 25 + #include <string.h> 26 + #include <stdio.h> 27 + #include <u-boot/blake2.h> 28 + #include "blake2-impl.h" 29 + 30 + static const uint64_t blake2b_IV[8] = 31 + { 32 + 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 33 + 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, 34 + 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, 35 + 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL 36 + }; 37 + 38 + static const uint8_t blake2b_sigma[12][16] = 39 + { 40 + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 41 + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , 42 + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , 43 + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , 44 + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , 45 + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , 46 + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , 47 + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , 48 + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , 49 + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , 50 + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 51 + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } 52 + }; 53 + 54 + 55 + static void blake2b_set_lastnode( blake2b_state *S ) 56 + { 57 + S->f[1] = (uint64_t)-1; 58 + } 59 + 60 + /* Some helper functions, not necessarily useful */ 61 + static int blake2b_is_lastblock( const blake2b_state *S ) 62 + { 63 + return S->f[0] != 0; 64 + } 65 + 66 + static void blake2b_set_lastblock( blake2b_state *S ) 67 + { 68 + if( S->last_node ) blake2b_set_lastnode( S ); 69 + 70 + S->f[0] = (uint64_t)-1; 71 + } 72 + 73 + static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc ) 74 + { 75 + S->t[0] += inc; 76 + S->t[1] += ( S->t[0] < inc ); 77 + } 78 + 79 + static void blake2b_init0( blake2b_state *S ) 80 + { 81 + size_t i; 82 + memset( S, 0, sizeof( blake2b_state ) ); 83 + 84 + for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i]; 85 + } 86 + 87 + /* init xors IV with input parameter block */ 88 + int blake2b_init_param( blake2b_state *S, const blake2b_param *P ) 89 + { 90 + const uint8_t *p = ( const uint8_t * )( P ); 91 + size_t i; 92 + 93 + blake2b_init0( S ); 94 + 95 + /* IV XOR ParamBlock */ 96 + for( i = 0; i < 8; ++i ) 97 + S->h[i] ^= load64( p + sizeof( S->h[i] ) * i ); 98 + 99 + S->outlen = P->digest_length; 100 + return 0; 101 + } 102 + 103 + 104 + 105 + int blake2b_init( blake2b_state *S, size_t outlen ) 106 + { 107 + blake2b_param P[1]; 108 + 109 + if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; 110 + 111 + P->digest_length = (uint8_t)outlen; 112 + P->key_length = 0; 113 + P->fanout = 1; 114 + P->depth = 1; 115 + store32( &P->leaf_length, 0 ); 116 + store32( &P->node_offset, 0 ); 117 + store32( &P->xof_length, 0 ); 118 + P->node_depth = 0; 119 + P->inner_length = 0; 120 + memset( P->reserved, 0, sizeof( P->reserved ) ); 121 + memset( P->salt, 0, sizeof( P->salt ) ); 122 + memset( P->personal, 0, sizeof( P->personal ) ); 123 + return blake2b_init_param( S, P ); 124 + } 125 + 126 + 127 + int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen ) 128 + { 129 + blake2b_param P[1]; 130 + 131 + if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; 132 + 133 + if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1; 134 + 135 + P->digest_length = (uint8_t)outlen; 136 + P->key_length = (uint8_t)keylen; 137 + P->fanout = 1; 138 + P->depth = 1; 139 + store32( &P->leaf_length, 0 ); 140 + store32( &P->node_offset, 0 ); 141 + store32( &P->xof_length, 0 ); 142 + P->node_depth = 0; 143 + P->inner_length = 0; 144 + memset( P->reserved, 0, sizeof( P->reserved ) ); 145 + memset( P->salt, 0, sizeof( P->salt ) ); 146 + memset( P->personal, 0, sizeof( P->personal ) ); 147 + 148 + if( blake2b_init_param( S, P ) < 0 ) return -1; 149 + 150 + { 151 + uint8_t block[BLAKE2B_BLOCKBYTES]; 152 + memset( block, 0, BLAKE2B_BLOCKBYTES ); 153 + memcpy( block, key, keylen ); 154 + blake2b_update( S, block, BLAKE2B_BLOCKBYTES ); 155 + secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */ 156 + } 157 + return 0; 158 + } 159 + 160 + #define G(r,i,a,b,c,d) \ 161 + do { \ 162 + a = a + b + m[blake2b_sigma[r][2*i+0]]; \ 163 + d = rotr64(d ^ a, 32); \ 164 + c = c + d; \ 165 + b = rotr64(b ^ c, 24); \ 166 + a = a + b + m[blake2b_sigma[r][2*i+1]]; \ 167 + d = rotr64(d ^ a, 16); \ 168 + c = c + d; \ 169 + b = rotr64(b ^ c, 63); \ 170 + } while(0) 171 + 172 + #define R(r) \ 173 + do { \ 174 + G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ 175 + G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ 176 + G(r,2,v[ 2],v[ 6],v[10],v[14]); \ 177 + G(r,3,v[ 3],v[ 7],v[11],v[15]); \ 178 + G(r,4,v[ 0],v[ 5],v[10],v[15]); \ 179 + G(r,5,v[ 1],v[ 6],v[11],v[12]); \ 180 + G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ 181 + G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ 182 + } while(0) 183 + 184 + static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] ) 185 + { 186 + uint64_t m[16]; 187 + uint64_t v[16]; 188 + size_t i; 189 + 190 + for( i = 0; i < 16; ++i ) { 191 + m[i] = load64( block + i * sizeof( m[i] ) ); 192 + } 193 + 194 + for( i = 0; i < 8; ++i ) { 195 + v[i] = S->h[i]; 196 + } 197 + 198 + v[ 8] = blake2b_IV[0]; 199 + v[ 9] = blake2b_IV[1]; 200 + v[10] = blake2b_IV[2]; 201 + v[11] = blake2b_IV[3]; 202 + v[12] = blake2b_IV[4] ^ S->t[0]; 203 + v[13] = blake2b_IV[5] ^ S->t[1]; 204 + v[14] = blake2b_IV[6] ^ S->f[0]; 205 + v[15] = blake2b_IV[7] ^ S->f[1]; 206 + 207 + R( 0 ); 208 + R( 1 ); 209 + R( 2 ); 210 + R( 3 ); 211 + R( 4 ); 212 + R( 5 ); 213 + R( 6 ); 214 + R( 7 ); 215 + R( 8 ); 216 + R( 9 ); 217 + R( 10 ); 218 + R( 11 ); 219 + 220 + for( i = 0; i < 8; ++i ) { 221 + S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; 222 + } 223 + } 224 + 225 + #undef G 226 + #undef R 227 + 228 + int blake2b_update( blake2b_state *S, const void *pin, size_t inlen ) 229 + { 230 + const unsigned char * in = (const unsigned char *)pin; 231 + if( inlen > 0 ) 232 + { 233 + size_t left = S->buflen; 234 + size_t fill = BLAKE2B_BLOCKBYTES - left; 235 + if( inlen > fill ) 236 + { 237 + S->buflen = 0; 238 + memcpy( S->buf + left, in, fill ); /* Fill buffer */ 239 + blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); 240 + blake2b_compress( S, S->buf ); /* Compress */ 241 + in += fill; inlen -= fill; 242 + while(inlen > BLAKE2B_BLOCKBYTES) { 243 + blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); 244 + blake2b_compress( S, in ); 245 + in += BLAKE2B_BLOCKBYTES; 246 + inlen -= BLAKE2B_BLOCKBYTES; 247 + } 248 + } 249 + memcpy( S->buf + S->buflen, in, inlen ); 250 + S->buflen += inlen; 251 + } 252 + return 0; 253 + } 254 + 255 + int blake2b_final( blake2b_state *S, void *out, size_t outlen ) 256 + { 257 + uint8_t buffer[BLAKE2B_OUTBYTES] = {0}; 258 + size_t i; 259 + 260 + if( out == NULL || outlen < S->outlen ) 261 + return -1; 262 + 263 + if( blake2b_is_lastblock( S ) ) 264 + return -1; 265 + 266 + blake2b_increment_counter( S, S->buflen ); 267 + blake2b_set_lastblock( S ); 268 + memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */ 269 + blake2b_compress( S, S->buf ); 270 + 271 + for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ 272 + store64( buffer + sizeof( S->h[i] ) * i, S->h[i] ); 273 + 274 + memcpy( out, buffer, S->outlen ); 275 + secure_zero_memory(buffer, sizeof(buffer)); 276 + return 0; 277 + } 278 + 279 + /* inlen, at least, should be uint64_t. Others can be size_t. */ 280 + int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) 281 + { 282 + blake2b_state S[1]; 283 + 284 + /* Verify parameters */ 285 + if ( NULL == in && inlen > 0 ) return -1; 286 + 287 + if ( NULL == out ) return -1; 288 + 289 + if( NULL == key && keylen > 0 ) return -1; 290 + 291 + if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1; 292 + 293 + if( keylen > BLAKE2B_KEYBYTES ) return -1; 294 + 295 + if( keylen > 0 ) 296 + { 297 + if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1; 298 + } 299 + else 300 + { 301 + if( blake2b_init( S, outlen ) < 0 ) return -1; 302 + } 303 + 304 + blake2b_update( S, ( const uint8_t * )in, inlen ); 305 + blake2b_final( S, out, outlen ); 306 + return 0; 307 + } 308 + 309 + int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) { 310 + return blake2b(out, outlen, in, inlen, key, keylen); 311 + }