1*0e33efe4SConrad Meyer /*
2*0e33efe4SConrad Meyer BLAKE2 reference source code package - reference C implementations
3*0e33efe4SConrad Meyer
4*0e33efe4SConrad Meyer Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
5*0e33efe4SConrad Meyer
6*0e33efe4SConrad Meyer To the extent possible under law, the author(s) have dedicated all copyright
7*0e33efe4SConrad Meyer and related and neighboring rights to this software to the public domain
8*0e33efe4SConrad Meyer worldwide. This software is distributed without any warranty.
9*0e33efe4SConrad Meyer
10*0e33efe4SConrad Meyer You should have received a copy of the CC0 Public Domain Dedication along with
11*0e33efe4SConrad Meyer this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
12*0e33efe4SConrad Meyer */
13*0e33efe4SConrad Meyer
14*0e33efe4SConrad Meyer #include <stdint.h>
15*0e33efe4SConrad Meyer #include <string.h>
16*0e33efe4SConrad Meyer #include <stdio.h>
17*0e33efe4SConrad Meyer
18*0e33efe4SConrad Meyer #include "blake2.h"
19*0e33efe4SConrad Meyer #include "blake2-impl.h"
20*0e33efe4SConrad Meyer
21*0e33efe4SConrad Meyer static const uint64_t blake2b_IV[8] =
22*0e33efe4SConrad Meyer {
23*0e33efe4SConrad Meyer 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
24*0e33efe4SConrad Meyer 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
25*0e33efe4SConrad Meyer 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
26*0e33efe4SConrad Meyer 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
27*0e33efe4SConrad Meyer };
28*0e33efe4SConrad Meyer
29*0e33efe4SConrad Meyer static const uint8_t blake2b_sigma[12][16] =
30*0e33efe4SConrad Meyer {
31*0e33efe4SConrad Meyer { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
32*0e33efe4SConrad Meyer { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
33*0e33efe4SConrad Meyer { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
34*0e33efe4SConrad Meyer { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
35*0e33efe4SConrad Meyer { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
36*0e33efe4SConrad Meyer { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
37*0e33efe4SConrad Meyer { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
38*0e33efe4SConrad Meyer { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
39*0e33efe4SConrad Meyer { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
40*0e33efe4SConrad Meyer { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
41*0e33efe4SConrad Meyer { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
42*0e33efe4SConrad Meyer { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
43*0e33efe4SConrad Meyer };
44*0e33efe4SConrad Meyer
45*0e33efe4SConrad Meyer
blake2b_set_lastnode(blake2b_state * S)46*0e33efe4SConrad Meyer static inline int blake2b_set_lastnode( blake2b_state *S )
47*0e33efe4SConrad Meyer {
48*0e33efe4SConrad Meyer S->f[1] = ~0ULL;
49*0e33efe4SConrad Meyer return 0;
50*0e33efe4SConrad Meyer }
51*0e33efe4SConrad Meyer
blake2b_clear_lastnode(blake2b_state * S)52*0e33efe4SConrad Meyer static inline int blake2b_clear_lastnode( blake2b_state *S )
53*0e33efe4SConrad Meyer {
54*0e33efe4SConrad Meyer S->f[1] = 0ULL;
55*0e33efe4SConrad Meyer return 0;
56*0e33efe4SConrad Meyer }
57*0e33efe4SConrad Meyer
58*0e33efe4SConrad Meyer /* Some helper functions, not necessarily useful */
blake2b_set_lastblock(blake2b_state * S)59*0e33efe4SConrad Meyer static inline int blake2b_set_lastblock( blake2b_state *S )
60*0e33efe4SConrad Meyer {
61*0e33efe4SConrad Meyer if( S->last_node ) blake2b_set_lastnode( S );
62*0e33efe4SConrad Meyer
63*0e33efe4SConrad Meyer S->f[0] = ~0ULL;
64*0e33efe4SConrad Meyer return 0;
65*0e33efe4SConrad Meyer }
66*0e33efe4SConrad Meyer
blake2b_clear_lastblock(blake2b_state * S)67*0e33efe4SConrad Meyer static inline int blake2b_clear_lastblock( blake2b_state *S )
68*0e33efe4SConrad Meyer {
69*0e33efe4SConrad Meyer if( S->last_node ) blake2b_clear_lastnode( S );
70*0e33efe4SConrad Meyer
71*0e33efe4SConrad Meyer S->f[0] = 0ULL;
72*0e33efe4SConrad Meyer return 0;
73*0e33efe4SConrad Meyer }
74*0e33efe4SConrad Meyer
blake2b_increment_counter(blake2b_state * S,const uint64_t inc)75*0e33efe4SConrad Meyer static inline int blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
76*0e33efe4SConrad Meyer {
77*0e33efe4SConrad Meyer S->t[0] += inc;
78*0e33efe4SConrad Meyer S->t[1] += ( S->t[0] < inc );
79*0e33efe4SConrad Meyer return 0;
80*0e33efe4SConrad Meyer }
81*0e33efe4SConrad Meyer
82*0e33efe4SConrad Meyer
83*0e33efe4SConrad Meyer
84*0e33efe4SConrad Meyer // Parameter-related functions
blake2b_param_set_digest_length(blake2b_param * P,const uint8_t digest_length)85*0e33efe4SConrad Meyer static inline int blake2b_param_set_digest_length( blake2b_param *P, const uint8_t digest_length )
86*0e33efe4SConrad Meyer {
87*0e33efe4SConrad Meyer P->digest_length = digest_length;
88*0e33efe4SConrad Meyer return 0;
89*0e33efe4SConrad Meyer }
90*0e33efe4SConrad Meyer
blake2b_param_set_fanout(blake2b_param * P,const uint8_t fanout)91*0e33efe4SConrad Meyer static inline int blake2b_param_set_fanout( blake2b_param *P, const uint8_t fanout )
92*0e33efe4SConrad Meyer {
93*0e33efe4SConrad Meyer P->fanout = fanout;
94*0e33efe4SConrad Meyer return 0;
95*0e33efe4SConrad Meyer }
96*0e33efe4SConrad Meyer
blake2b_param_set_max_depth(blake2b_param * P,const uint8_t depth)97*0e33efe4SConrad Meyer static inline int blake2b_param_set_max_depth( blake2b_param *P, const uint8_t depth )
98*0e33efe4SConrad Meyer {
99*0e33efe4SConrad Meyer P->depth = depth;
100*0e33efe4SConrad Meyer return 0;
101*0e33efe4SConrad Meyer }
102*0e33efe4SConrad Meyer
blake2b_param_set_leaf_length(blake2b_param * P,const uint32_t leaf_length)103*0e33efe4SConrad Meyer static inline int blake2b_param_set_leaf_length( blake2b_param *P, const uint32_t leaf_length )
104*0e33efe4SConrad Meyer {
105*0e33efe4SConrad Meyer store32( &P->leaf_length, leaf_length );
106*0e33efe4SConrad Meyer return 0;
107*0e33efe4SConrad Meyer }
108*0e33efe4SConrad Meyer
blake2b_param_set_node_offset(blake2b_param * P,const uint64_t node_offset)109*0e33efe4SConrad Meyer static inline int blake2b_param_set_node_offset( blake2b_param *P, const uint64_t node_offset )
110*0e33efe4SConrad Meyer {
111*0e33efe4SConrad Meyer store64( &P->node_offset, node_offset );
112*0e33efe4SConrad Meyer return 0;
113*0e33efe4SConrad Meyer }
114*0e33efe4SConrad Meyer
blake2b_param_set_node_depth(blake2b_param * P,const uint8_t node_depth)115*0e33efe4SConrad Meyer static inline int blake2b_param_set_node_depth( blake2b_param *P, const uint8_t node_depth )
116*0e33efe4SConrad Meyer {
117*0e33efe4SConrad Meyer P->node_depth = node_depth;
118*0e33efe4SConrad Meyer return 0;
119*0e33efe4SConrad Meyer }
120*0e33efe4SConrad Meyer
blake2b_param_set_inner_length(blake2b_param * P,const uint8_t inner_length)121*0e33efe4SConrad Meyer static inline int blake2b_param_set_inner_length( blake2b_param *P, const uint8_t inner_length )
122*0e33efe4SConrad Meyer {
123*0e33efe4SConrad Meyer P->inner_length = inner_length;
124*0e33efe4SConrad Meyer return 0;
125*0e33efe4SConrad Meyer }
126*0e33efe4SConrad Meyer
blake2b_param_set_salt(blake2b_param * P,const uint8_t salt[BLAKE2B_SALTBYTES])127*0e33efe4SConrad Meyer static inline int blake2b_param_set_salt( blake2b_param *P, const uint8_t salt[BLAKE2B_SALTBYTES] )
128*0e33efe4SConrad Meyer {
129*0e33efe4SConrad Meyer memcpy( P->salt, salt, BLAKE2B_SALTBYTES );
130*0e33efe4SConrad Meyer return 0;
131*0e33efe4SConrad Meyer }
132*0e33efe4SConrad Meyer
blake2b_param_set_personal(blake2b_param * P,const uint8_t personal[BLAKE2B_PERSONALBYTES])133*0e33efe4SConrad Meyer static inline int blake2b_param_set_personal( blake2b_param *P, const uint8_t personal[BLAKE2B_PERSONALBYTES] )
134*0e33efe4SConrad Meyer {
135*0e33efe4SConrad Meyer memcpy( P->personal, personal, BLAKE2B_PERSONALBYTES );
136*0e33efe4SConrad Meyer return 0;
137*0e33efe4SConrad Meyer }
138*0e33efe4SConrad Meyer
blake2b_init0(blake2b_state * S)139*0e33efe4SConrad Meyer static inline int blake2b_init0( blake2b_state *S )
140*0e33efe4SConrad Meyer {
141*0e33efe4SConrad Meyer memset( S, 0, sizeof( blake2b_state ) );
142*0e33efe4SConrad Meyer
143*0e33efe4SConrad Meyer for( int i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];
144*0e33efe4SConrad Meyer
145*0e33efe4SConrad Meyer return 0;
146*0e33efe4SConrad Meyer }
147*0e33efe4SConrad Meyer
148*0e33efe4SConrad Meyer #define blake2b_init BLAKE2_IMPL_NAME(blake2b_init)
149*0e33efe4SConrad Meyer #define blake2b_init_param BLAKE2_IMPL_NAME(blake2b_init_param)
150*0e33efe4SConrad Meyer #define blake2b_init_key BLAKE2_IMPL_NAME(blake2b_init_key)
151*0e33efe4SConrad Meyer #define blake2b_update BLAKE2_IMPL_NAME(blake2b_update)
152*0e33efe4SConrad Meyer #define blake2b_final BLAKE2_IMPL_NAME(blake2b_final)
153*0e33efe4SConrad Meyer #define blake2b BLAKE2_IMPL_NAME(blake2b)
154*0e33efe4SConrad Meyer
155*0e33efe4SConrad Meyer #if defined(__cplusplus)
156*0e33efe4SConrad Meyer extern "C" {
157*0e33efe4SConrad Meyer #endif
158*0e33efe4SConrad Meyer int blake2b_init( blake2b_state *S, size_t outlen );
159*0e33efe4SConrad Meyer int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
160*0e33efe4SConrad Meyer int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );
161*0e33efe4SConrad Meyer int blake2b_update( blake2b_state *S, const uint8_t *in, size_t inlen );
162*0e33efe4SConrad Meyer int blake2b_final( blake2b_state *S, uint8_t *out, size_t outlen );
163*0e33efe4SConrad Meyer int blake2b( uint8_t *out, const void *in, const void *key, size_t outlen, size_t inlen, size_t keylen );
164*0e33efe4SConrad Meyer #if defined(__cplusplus)
165*0e33efe4SConrad Meyer }
166*0e33efe4SConrad Meyer #endif
167*0e33efe4SConrad Meyer
168*0e33efe4SConrad Meyer /* init xors IV with input parameter block */
blake2b_init_param(blake2b_state * S,const blake2b_param * P)169*0e33efe4SConrad Meyer int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
170*0e33efe4SConrad Meyer {
171*0e33efe4SConrad Meyer blake2b_init0( S );
172*0e33efe4SConrad Meyer uint8_t *p = ( uint8_t * )( P );
173*0e33efe4SConrad Meyer
174*0e33efe4SConrad Meyer /* IV XOR ParamBlock */
175*0e33efe4SConrad Meyer for( size_t i = 0; i < 8; ++i )
176*0e33efe4SConrad Meyer S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );
177*0e33efe4SConrad Meyer
178*0e33efe4SConrad Meyer S->outlen = P->digest_length;
179*0e33efe4SConrad Meyer return 0;
180*0e33efe4SConrad Meyer }
181*0e33efe4SConrad Meyer
182*0e33efe4SConrad Meyer
183*0e33efe4SConrad Meyer
blake2b_init(blake2b_state * S,size_t outlen)184*0e33efe4SConrad Meyer int blake2b_init( blake2b_state *S, size_t outlen )
185*0e33efe4SConrad Meyer {
186*0e33efe4SConrad Meyer blake2b_param P[1];
187*0e33efe4SConrad Meyer
188*0e33efe4SConrad Meyer if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
189*0e33efe4SConrad Meyer
190*0e33efe4SConrad Meyer P->digest_length = ( uint8_t ) outlen;
191*0e33efe4SConrad Meyer P->key_length = 0;
192*0e33efe4SConrad Meyer P->fanout = 1;
193*0e33efe4SConrad Meyer P->depth = 1;
194*0e33efe4SConrad Meyer store32( &P->leaf_length, 0 );
195*0e33efe4SConrad Meyer store64( &P->node_offset, 0 );
196*0e33efe4SConrad Meyer P->node_depth = 0;
197*0e33efe4SConrad Meyer P->inner_length = 0;
198*0e33efe4SConrad Meyer memset( P->reserved, 0, sizeof( P->reserved ) );
199*0e33efe4SConrad Meyer memset( P->salt, 0, sizeof( P->salt ) );
200*0e33efe4SConrad Meyer memset( P->personal, 0, sizeof( P->personal ) );
201*0e33efe4SConrad Meyer return blake2b_init_param( S, P );
202*0e33efe4SConrad Meyer }
203*0e33efe4SConrad Meyer
204*0e33efe4SConrad Meyer
blake2b_init_key(blake2b_state * S,size_t outlen,const void * key,size_t keylen)205*0e33efe4SConrad Meyer int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen )
206*0e33efe4SConrad Meyer {
207*0e33efe4SConrad Meyer blake2b_param P[1];
208*0e33efe4SConrad Meyer
209*0e33efe4SConrad Meyer if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
210*0e33efe4SConrad Meyer
211*0e33efe4SConrad Meyer if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
212*0e33efe4SConrad Meyer
213*0e33efe4SConrad Meyer P->digest_length = ( uint8_t ) outlen;
214*0e33efe4SConrad Meyer P->key_length = ( uint8_t ) keylen;
215*0e33efe4SConrad Meyer P->fanout = 1;
216*0e33efe4SConrad Meyer P->depth = 1;
217*0e33efe4SConrad Meyer store32( &P->leaf_length, 0 );
218*0e33efe4SConrad Meyer store64( &P->node_offset, 0 );
219*0e33efe4SConrad Meyer P->node_depth = 0;
220*0e33efe4SConrad Meyer P->inner_length = 0;
221*0e33efe4SConrad Meyer memset( P->reserved, 0, sizeof( P->reserved ) );
222*0e33efe4SConrad Meyer memset( P->salt, 0, sizeof( P->salt ) );
223*0e33efe4SConrad Meyer memset( P->personal, 0, sizeof( P->personal ) );
224*0e33efe4SConrad Meyer
225*0e33efe4SConrad Meyer if( blake2b_init_param( S, P ) < 0 ) return -1;
226*0e33efe4SConrad Meyer
227*0e33efe4SConrad Meyer {
228*0e33efe4SConrad Meyer uint8_t block[BLAKE2B_BLOCKBYTES];
229*0e33efe4SConrad Meyer memset( block, 0, BLAKE2B_BLOCKBYTES );
230*0e33efe4SConrad Meyer memcpy( block, key, keylen );
231*0e33efe4SConrad Meyer blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
232*0e33efe4SConrad Meyer secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
233*0e33efe4SConrad Meyer }
234*0e33efe4SConrad Meyer return 0;
235*0e33efe4SConrad Meyer }
236*0e33efe4SConrad Meyer
blake2b_compress(blake2b_state * S,const uint8_t block[BLAKE2B_BLOCKBYTES])237*0e33efe4SConrad Meyer static int blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
238*0e33efe4SConrad Meyer {
239*0e33efe4SConrad Meyer uint64_t m[16];
240*0e33efe4SConrad Meyer uint64_t v[16];
241*0e33efe4SConrad Meyer size_t i;
242*0e33efe4SConrad Meyer
243*0e33efe4SConrad Meyer for( i = 0; i < 16; ++i )
244*0e33efe4SConrad Meyer m[i] = load64( block + i * sizeof( m[i] ) );
245*0e33efe4SConrad Meyer
246*0e33efe4SConrad Meyer for( i = 0; i < 8; ++i )
247*0e33efe4SConrad Meyer v[i] = S->h[i];
248*0e33efe4SConrad Meyer
249*0e33efe4SConrad Meyer v[ 8] = blake2b_IV[0];
250*0e33efe4SConrad Meyer v[ 9] = blake2b_IV[1];
251*0e33efe4SConrad Meyer v[10] = blake2b_IV[2];
252*0e33efe4SConrad Meyer v[11] = blake2b_IV[3];
253*0e33efe4SConrad Meyer v[12] = S->t[0] ^ blake2b_IV[4];
254*0e33efe4SConrad Meyer v[13] = S->t[1] ^ blake2b_IV[5];
255*0e33efe4SConrad Meyer v[14] = S->f[0] ^ blake2b_IV[6];
256*0e33efe4SConrad Meyer v[15] = S->f[1] ^ blake2b_IV[7];
257*0e33efe4SConrad Meyer #define G(r,i,a,b,c,d) \
258*0e33efe4SConrad Meyer do { \
259*0e33efe4SConrad Meyer a = a + b + m[blake2b_sigma[r][2*i+0]]; \
260*0e33efe4SConrad Meyer d = rotr64(d ^ a, 32); \
261*0e33efe4SConrad Meyer c = c + d; \
262*0e33efe4SConrad Meyer b = rotr64(b ^ c, 24); \
263*0e33efe4SConrad Meyer a = a + b + m[blake2b_sigma[r][2*i+1]]; \
264*0e33efe4SConrad Meyer d = rotr64(d ^ a, 16); \
265*0e33efe4SConrad Meyer c = c + d; \
266*0e33efe4SConrad Meyer b = rotr64(b ^ c, 63); \
267*0e33efe4SConrad Meyer } while(0)
268*0e33efe4SConrad Meyer #define ROUND(r) \
269*0e33efe4SConrad Meyer do { \
270*0e33efe4SConrad Meyer G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
271*0e33efe4SConrad Meyer G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
272*0e33efe4SConrad Meyer G(r,2,v[ 2],v[ 6],v[10],v[14]); \
273*0e33efe4SConrad Meyer G(r,3,v[ 3],v[ 7],v[11],v[15]); \
274*0e33efe4SConrad Meyer G(r,4,v[ 0],v[ 5],v[10],v[15]); \
275*0e33efe4SConrad Meyer G(r,5,v[ 1],v[ 6],v[11],v[12]); \
276*0e33efe4SConrad Meyer G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
277*0e33efe4SConrad Meyer G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
278*0e33efe4SConrad Meyer } while(0)
279*0e33efe4SConrad Meyer ROUND( 0 );
280*0e33efe4SConrad Meyer ROUND( 1 );
281*0e33efe4SConrad Meyer ROUND( 2 );
282*0e33efe4SConrad Meyer ROUND( 3 );
283*0e33efe4SConrad Meyer ROUND( 4 );
284*0e33efe4SConrad Meyer ROUND( 5 );
285*0e33efe4SConrad Meyer ROUND( 6 );
286*0e33efe4SConrad Meyer ROUND( 7 );
287*0e33efe4SConrad Meyer ROUND( 8 );
288*0e33efe4SConrad Meyer ROUND( 9 );
289*0e33efe4SConrad Meyer ROUND( 10 );
290*0e33efe4SConrad Meyer ROUND( 11 );
291*0e33efe4SConrad Meyer
292*0e33efe4SConrad Meyer for( i = 0; i < 8; ++i )
293*0e33efe4SConrad Meyer S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
294*0e33efe4SConrad Meyer
295*0e33efe4SConrad Meyer #undef G
296*0e33efe4SConrad Meyer #undef ROUND
297*0e33efe4SConrad Meyer return 0;
298*0e33efe4SConrad Meyer }
299*0e33efe4SConrad Meyer
300*0e33efe4SConrad Meyer
blake2b_update(blake2b_state * S,const uint8_t * in,size_t inlen)301*0e33efe4SConrad Meyer int blake2b_update( blake2b_state *S, const uint8_t *in, size_t inlen )
302*0e33efe4SConrad Meyer {
303*0e33efe4SConrad Meyer while( inlen > 0 )
304*0e33efe4SConrad Meyer {
305*0e33efe4SConrad Meyer uint32_t left = S->buflen;
306*0e33efe4SConrad Meyer uint32_t fill = 2 * BLAKE2B_BLOCKBYTES - left;
307*0e33efe4SConrad Meyer
308*0e33efe4SConrad Meyer if( inlen > fill )
309*0e33efe4SConrad Meyer {
310*0e33efe4SConrad Meyer memcpy( S->buf + left, in, fill ); // Fill buffer
311*0e33efe4SConrad Meyer S->buflen += fill;
312*0e33efe4SConrad Meyer blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
313*0e33efe4SConrad Meyer blake2b_compress( S, S->buf ); // Compress
314*0e33efe4SConrad Meyer memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); // Shift buffer left
315*0e33efe4SConrad Meyer S->buflen -= BLAKE2B_BLOCKBYTES;
316*0e33efe4SConrad Meyer in += fill;
317*0e33efe4SConrad Meyer inlen -= fill;
318*0e33efe4SConrad Meyer }
319*0e33efe4SConrad Meyer else // inlen <= fill
320*0e33efe4SConrad Meyer {
321*0e33efe4SConrad Meyer memcpy( S->buf + left, in, inlen );
322*0e33efe4SConrad Meyer S->buflen += ( uint32_t ) inlen; // Be lazy, do not compress
323*0e33efe4SConrad Meyer in += inlen;
324*0e33efe4SConrad Meyer inlen -= inlen;
325*0e33efe4SConrad Meyer }
326*0e33efe4SConrad Meyer }
327*0e33efe4SConrad Meyer
328*0e33efe4SConrad Meyer return 0;
329*0e33efe4SConrad Meyer }
330*0e33efe4SConrad Meyer
blake2b_final(blake2b_state * S,uint8_t * out,size_t outlen)331*0e33efe4SConrad Meyer int blake2b_final( blake2b_state *S, uint8_t *out, size_t outlen )
332*0e33efe4SConrad Meyer {
333*0e33efe4SConrad Meyer uint8_t buffer[BLAKE2B_OUTBYTES];
334*0e33efe4SConrad Meyer size_t i;
335*0e33efe4SConrad Meyer
336*0e33efe4SConrad Meyer if(S->outlen != outlen) return -1;
337*0e33efe4SConrad Meyer
338*0e33efe4SConrad Meyer if( S->buflen > BLAKE2B_BLOCKBYTES )
339*0e33efe4SConrad Meyer {
340*0e33efe4SConrad Meyer blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
341*0e33efe4SConrad Meyer blake2b_compress( S, S->buf );
342*0e33efe4SConrad Meyer S->buflen -= BLAKE2B_BLOCKBYTES;
343*0e33efe4SConrad Meyer memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, S->buflen );
344*0e33efe4SConrad Meyer }
345*0e33efe4SConrad Meyer
346*0e33efe4SConrad Meyer blake2b_increment_counter( S, S->buflen );
347*0e33efe4SConrad Meyer blake2b_set_lastblock( S );
348*0e33efe4SConrad Meyer memset( S->buf + S->buflen, 0, 2 * BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */
349*0e33efe4SConrad Meyer blake2b_compress( S, S->buf );
350*0e33efe4SConrad Meyer
351*0e33efe4SConrad Meyer for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
352*0e33efe4SConrad Meyer store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );
353*0e33efe4SConrad Meyer
354*0e33efe4SConrad Meyer memcpy( out, buffer, outlen );
355*0e33efe4SConrad Meyer return 0;
356*0e33efe4SConrad Meyer }
357*0e33efe4SConrad Meyer
blake2b(uint8_t * out,const void * in,const void * key,size_t outlen,size_t inlen,size_t keylen)358*0e33efe4SConrad Meyer int blake2b( uint8_t *out, const void *in, const void *key, size_t outlen, size_t inlen, size_t keylen )
359*0e33efe4SConrad Meyer {
360*0e33efe4SConrad Meyer blake2b_state S[1];
361*0e33efe4SConrad Meyer
362*0e33efe4SConrad Meyer /* Verify parameters */
363*0e33efe4SConrad Meyer if ( NULL == in && inlen > 0 ) return -1;
364*0e33efe4SConrad Meyer
365*0e33efe4SConrad Meyer if ( NULL == out ) return -1;
366*0e33efe4SConrad Meyer
367*0e33efe4SConrad Meyer if( NULL == key && keylen > 0 ) return -1;
368*0e33efe4SConrad Meyer
369*0e33efe4SConrad Meyer if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
370*0e33efe4SConrad Meyer
371*0e33efe4SConrad Meyer if( keylen > BLAKE2B_KEYBYTES ) return -1;
372*0e33efe4SConrad Meyer
373*0e33efe4SConrad Meyer if( keylen > 0 )
374*0e33efe4SConrad Meyer {
375*0e33efe4SConrad Meyer if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
376*0e33efe4SConrad Meyer }
377*0e33efe4SConrad Meyer else
378*0e33efe4SConrad Meyer {
379*0e33efe4SConrad Meyer if( blake2b_init( S, outlen ) < 0 ) return -1;
380*0e33efe4SConrad Meyer }
381*0e33efe4SConrad Meyer
382*0e33efe4SConrad Meyer if( blake2b_update( S, ( uint8_t * )in, inlen ) < 0 ) return -1;
383*0e33efe4SConrad Meyer return blake2b_final( S, out, outlen );
384*0e33efe4SConrad Meyer }
385*0e33efe4SConrad Meyer
386*0e33efe4SConrad Meyer
387