1085658deSDaniel Fojt /*
2085658deSDaniel Fojt BLAKE2 reference source code package - reference C implementations
3085658deSDaniel Fojt
4085658deSDaniel Fojt Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
5085658deSDaniel Fojt terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
6085658deSDaniel Fojt your option. The terms of these licenses can be found at:
7085658deSDaniel Fojt
8085658deSDaniel Fojt - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
9085658deSDaniel Fojt - OpenSSL license : https://www.openssl.org/source/license.html
10085658deSDaniel Fojt - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
11085658deSDaniel Fojt
12085658deSDaniel Fojt More information about the BLAKE2 hash function can be found at
13085658deSDaniel Fojt https://blake2.net.
14085658deSDaniel Fojt */
15085658deSDaniel Fojt
16*50f8aa9cSAntonio Huete Jimenez #include "archive_platform.h"
17*50f8aa9cSAntonio Huete Jimenez
18085658deSDaniel Fojt #include <stdlib.h>
19085658deSDaniel Fojt #include <string.h>
20085658deSDaniel Fojt #include <stdio.h>
21085658deSDaniel Fojt
22085658deSDaniel Fojt #if defined(_OPENMP)
23085658deSDaniel Fojt #include <omp.h>
24085658deSDaniel Fojt #endif
25085658deSDaniel Fojt
26085658deSDaniel Fojt #include "archive_blake2.h"
27085658deSDaniel Fojt #include "archive_blake2_impl.h"
28085658deSDaniel Fojt
29085658deSDaniel Fojt #define PARALLELISM_DEGREE 8
30085658deSDaniel Fojt
31085658deSDaniel Fojt /*
32085658deSDaniel Fojt blake2sp_init_param defaults to setting the expecting output length
33085658deSDaniel Fojt from the digest_length parameter block field.
34085658deSDaniel Fojt
35085658deSDaniel Fojt In some cases, however, we do not want this, as the output length
36085658deSDaniel Fojt of these instances is given by inner_length instead.
37085658deSDaniel Fojt */
blake2sp_init_leaf_param(blake2s_state * S,const blake2s_param * P)38085658deSDaniel Fojt static int blake2sp_init_leaf_param( blake2s_state *S, const blake2s_param *P )
39085658deSDaniel Fojt {
40085658deSDaniel Fojt int err = blake2s_init_param(S, P);
41085658deSDaniel Fojt S->outlen = P->inner_length;
42085658deSDaniel Fojt return err;
43085658deSDaniel Fojt }
44085658deSDaniel Fojt
blake2sp_init_leaf(blake2s_state * S,size_t outlen,size_t keylen,uint32_t offset)45085658deSDaniel Fojt static int blake2sp_init_leaf( blake2s_state *S, size_t outlen, size_t keylen, uint32_t offset )
46085658deSDaniel Fojt {
47085658deSDaniel Fojt blake2s_param P[1];
48085658deSDaniel Fojt P->digest_length = (uint8_t)outlen;
49085658deSDaniel Fojt P->key_length = (uint8_t)keylen;
50085658deSDaniel Fojt P->fanout = PARALLELISM_DEGREE;
51085658deSDaniel Fojt P->depth = 2;
52085658deSDaniel Fojt store32( &P->leaf_length, 0 );
53085658deSDaniel Fojt store32( &P->node_offset, offset );
54085658deSDaniel Fojt store16( &P->xof_length, 0 );
55085658deSDaniel Fojt P->node_depth = 0;
56085658deSDaniel Fojt P->inner_length = BLAKE2S_OUTBYTES;
57085658deSDaniel Fojt memset( P->salt, 0, sizeof( P->salt ) );
58085658deSDaniel Fojt memset( P->personal, 0, sizeof( P->personal ) );
59085658deSDaniel Fojt return blake2sp_init_leaf_param( S, P );
60085658deSDaniel Fojt }
61085658deSDaniel Fojt
blake2sp_init_root(blake2s_state * S,size_t outlen,size_t keylen)62085658deSDaniel Fojt static int blake2sp_init_root( blake2s_state *S, size_t outlen, size_t keylen )
63085658deSDaniel Fojt {
64085658deSDaniel Fojt blake2s_param P[1];
65085658deSDaniel Fojt P->digest_length = (uint8_t)outlen;
66085658deSDaniel Fojt P->key_length = (uint8_t)keylen;
67085658deSDaniel Fojt P->fanout = PARALLELISM_DEGREE;
68085658deSDaniel Fojt P->depth = 2;
69085658deSDaniel Fojt store32( &P->leaf_length, 0 );
70085658deSDaniel Fojt store32( &P->node_offset, 0 );
71085658deSDaniel Fojt store16( &P->xof_length, 0 );
72085658deSDaniel Fojt P->node_depth = 1;
73085658deSDaniel Fojt P->inner_length = BLAKE2S_OUTBYTES;
74085658deSDaniel Fojt memset( P->salt, 0, sizeof( P->salt ) );
75085658deSDaniel Fojt memset( P->personal, 0, sizeof( P->personal ) );
76085658deSDaniel Fojt return blake2s_init_param( S, P );
77085658deSDaniel Fojt }
78085658deSDaniel Fojt
79085658deSDaniel Fojt
blake2sp_init(blake2sp_state * S,size_t outlen)80085658deSDaniel Fojt int blake2sp_init( blake2sp_state *S, size_t outlen )
81085658deSDaniel Fojt {
82085658deSDaniel Fojt size_t i;
83085658deSDaniel Fojt
84085658deSDaniel Fojt if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
85085658deSDaniel Fojt
86085658deSDaniel Fojt memset( S->buf, 0, sizeof( S->buf ) );
87085658deSDaniel Fojt S->buflen = 0;
88085658deSDaniel Fojt S->outlen = outlen;
89085658deSDaniel Fojt
90085658deSDaniel Fojt if( blake2sp_init_root( S->R, outlen, 0 ) < 0 )
91085658deSDaniel Fojt return -1;
92085658deSDaniel Fojt
93085658deSDaniel Fojt for( i = 0; i < PARALLELISM_DEGREE; ++i )
94085658deSDaniel Fojt if( blake2sp_init_leaf( S->S[i], outlen, 0, (uint32_t)i ) < 0 ) return -1;
95085658deSDaniel Fojt
96085658deSDaniel Fojt S->R->last_node = 1;
97085658deSDaniel Fojt S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
98085658deSDaniel Fojt return 0;
99085658deSDaniel Fojt }
100085658deSDaniel Fojt
blake2sp_init_key(blake2sp_state * S,size_t outlen,const void * key,size_t keylen)101085658deSDaniel Fojt int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen )
102085658deSDaniel Fojt {
103085658deSDaniel Fojt size_t i;
104085658deSDaniel Fojt
105085658deSDaniel Fojt if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
106085658deSDaniel Fojt
107085658deSDaniel Fojt if( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
108085658deSDaniel Fojt
109085658deSDaniel Fojt memset( S->buf, 0, sizeof( S->buf ) );
110085658deSDaniel Fojt S->buflen = 0;
111085658deSDaniel Fojt S->outlen = outlen;
112085658deSDaniel Fojt
113085658deSDaniel Fojt if( blake2sp_init_root( S->R, outlen, keylen ) < 0 )
114085658deSDaniel Fojt return -1;
115085658deSDaniel Fojt
116085658deSDaniel Fojt for( i = 0; i < PARALLELISM_DEGREE; ++i )
117085658deSDaniel Fojt if( blake2sp_init_leaf( S->S[i], outlen, keylen, (uint32_t)i ) < 0 ) return -1;
118085658deSDaniel Fojt
119085658deSDaniel Fojt S->R->last_node = 1;
120085658deSDaniel Fojt S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
121085658deSDaniel Fojt {
122085658deSDaniel Fojt uint8_t block[BLAKE2S_BLOCKBYTES];
123085658deSDaniel Fojt memset( block, 0, BLAKE2S_BLOCKBYTES );
124085658deSDaniel Fojt memcpy( block, key, keylen );
125085658deSDaniel Fojt
126085658deSDaniel Fojt for( i = 0; i < PARALLELISM_DEGREE; ++i )
127085658deSDaniel Fojt blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES );
128085658deSDaniel Fojt
129085658deSDaniel Fojt secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
130085658deSDaniel Fojt }
131085658deSDaniel Fojt return 0;
132085658deSDaniel Fojt }
133085658deSDaniel Fojt
134085658deSDaniel Fojt
blake2sp_update(blake2sp_state * S,const void * pin,size_t inlen)135085658deSDaniel Fojt int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
136085658deSDaniel Fojt {
137085658deSDaniel Fojt const unsigned char * in = (const unsigned char *)pin;
138085658deSDaniel Fojt size_t left = S->buflen;
139085658deSDaniel Fojt size_t fill = sizeof( S->buf ) - left;
140085658deSDaniel Fojt size_t i;
141085658deSDaniel Fojt
142085658deSDaniel Fojt if( left && inlen >= fill )
143085658deSDaniel Fojt {
144085658deSDaniel Fojt memcpy( S->buf + left, in, fill );
145085658deSDaniel Fojt
146085658deSDaniel Fojt for( i = 0; i < PARALLELISM_DEGREE; ++i )
147085658deSDaniel Fojt blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
148085658deSDaniel Fojt
149085658deSDaniel Fojt in += fill;
150085658deSDaniel Fojt inlen -= fill;
151085658deSDaniel Fojt left = 0;
152085658deSDaniel Fojt }
153085658deSDaniel Fojt
154085658deSDaniel Fojt #if defined(_OPENMP)
155085658deSDaniel Fojt #pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE)
156085658deSDaniel Fojt #else
157085658deSDaniel Fojt for( i = 0; i < PARALLELISM_DEGREE; ++i )
158085658deSDaniel Fojt #endif
159085658deSDaniel Fojt {
160085658deSDaniel Fojt #if defined(_OPENMP)
161085658deSDaniel Fojt size_t i = omp_get_thread_num();
162085658deSDaniel Fojt #endif
163085658deSDaniel Fojt size_t inlen__ = inlen;
164085658deSDaniel Fojt const unsigned char *in__ = ( const unsigned char * )in;
165085658deSDaniel Fojt in__ += i * BLAKE2S_BLOCKBYTES;
166085658deSDaniel Fojt
167085658deSDaniel Fojt while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
168085658deSDaniel Fojt {
169085658deSDaniel Fojt blake2s_update( S->S[i], in__, BLAKE2S_BLOCKBYTES );
170085658deSDaniel Fojt in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
171085658deSDaniel Fojt inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
172085658deSDaniel Fojt }
173085658deSDaniel Fojt }
174085658deSDaniel Fojt
175085658deSDaniel Fojt in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
176085658deSDaniel Fojt inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
177085658deSDaniel Fojt
178085658deSDaniel Fojt if( inlen > 0 )
179085658deSDaniel Fojt memcpy( S->buf + left, in, inlen );
180085658deSDaniel Fojt
181085658deSDaniel Fojt S->buflen = left + inlen;
182085658deSDaniel Fojt return 0;
183085658deSDaniel Fojt }
184085658deSDaniel Fojt
185085658deSDaniel Fojt
blake2sp_final(blake2sp_state * S,void * out,size_t outlen)186085658deSDaniel Fojt int blake2sp_final( blake2sp_state *S, void *out, size_t outlen )
187085658deSDaniel Fojt {
188085658deSDaniel Fojt uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
189085658deSDaniel Fojt size_t i;
190085658deSDaniel Fojt
191085658deSDaniel Fojt if(out == NULL || outlen < S->outlen) {
192085658deSDaniel Fojt return -1;
193085658deSDaniel Fojt }
194085658deSDaniel Fojt
195085658deSDaniel Fojt for( i = 0; i < PARALLELISM_DEGREE; ++i )
196085658deSDaniel Fojt {
197085658deSDaniel Fojt if( S->buflen > i * BLAKE2S_BLOCKBYTES )
198085658deSDaniel Fojt {
199085658deSDaniel Fojt size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES;
200085658deSDaniel Fojt
201085658deSDaniel Fojt if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
202085658deSDaniel Fojt
203085658deSDaniel Fojt blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
204085658deSDaniel Fojt }
205085658deSDaniel Fojt
206085658deSDaniel Fojt blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES );
207085658deSDaniel Fojt }
208085658deSDaniel Fojt
209085658deSDaniel Fojt for( i = 0; i < PARALLELISM_DEGREE; ++i )
210085658deSDaniel Fojt blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES );
211085658deSDaniel Fojt
212085658deSDaniel Fojt return blake2s_final( S->R, out, S->outlen );
213085658deSDaniel Fojt }
214085658deSDaniel Fojt
215085658deSDaniel Fojt
blake2sp(void * out,size_t outlen,const void * in,size_t inlen,const void * key,size_t keylen)216085658deSDaniel Fojt int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
217085658deSDaniel Fojt {
218085658deSDaniel Fojt uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
219085658deSDaniel Fojt blake2s_state S[PARALLELISM_DEGREE][1];
220085658deSDaniel Fojt blake2s_state FS[1];
221085658deSDaniel Fojt size_t i;
222085658deSDaniel Fojt
223085658deSDaniel Fojt /* Verify parameters */
224085658deSDaniel Fojt if ( NULL == in && inlen > 0 ) return -1;
225085658deSDaniel Fojt
226085658deSDaniel Fojt if ( NULL == out ) return -1;
227085658deSDaniel Fojt
228085658deSDaniel Fojt if ( NULL == key && keylen > 0) return -1;
229085658deSDaniel Fojt
230085658deSDaniel Fojt if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
231085658deSDaniel Fojt
232085658deSDaniel Fojt if( keylen > BLAKE2S_KEYBYTES ) return -1;
233085658deSDaniel Fojt
234085658deSDaniel Fojt for( i = 0; i < PARALLELISM_DEGREE; ++i )
235085658deSDaniel Fojt if( blake2sp_init_leaf( S[i], outlen, keylen, (uint32_t)i ) < 0 ) return -1;
236085658deSDaniel Fojt
237085658deSDaniel Fojt S[PARALLELISM_DEGREE - 1]->last_node = 1; /* mark last node */
238085658deSDaniel Fojt
239085658deSDaniel Fojt if( keylen > 0 )
240085658deSDaniel Fojt {
241085658deSDaniel Fojt uint8_t block[BLAKE2S_BLOCKBYTES];
242085658deSDaniel Fojt memset( block, 0, BLAKE2S_BLOCKBYTES );
243085658deSDaniel Fojt memcpy( block, key, keylen );
244085658deSDaniel Fojt
245085658deSDaniel Fojt for( i = 0; i < PARALLELISM_DEGREE; ++i )
246085658deSDaniel Fojt blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES );
247085658deSDaniel Fojt
248085658deSDaniel Fojt secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
249085658deSDaniel Fojt }
250085658deSDaniel Fojt
251085658deSDaniel Fojt #if defined(_OPENMP)
252085658deSDaniel Fojt #pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE)
253085658deSDaniel Fojt #else
254085658deSDaniel Fojt
255085658deSDaniel Fojt for( i = 0; i < PARALLELISM_DEGREE; ++i )
256085658deSDaniel Fojt #endif
257085658deSDaniel Fojt {
258085658deSDaniel Fojt #if defined(_OPENMP)
259085658deSDaniel Fojt size_t i = omp_get_thread_num();
260085658deSDaniel Fojt #endif
261085658deSDaniel Fojt size_t inlen__ = inlen;
262085658deSDaniel Fojt const unsigned char *in__ = ( const unsigned char * )in;
263085658deSDaniel Fojt in__ += i * BLAKE2S_BLOCKBYTES;
264085658deSDaniel Fojt
265085658deSDaniel Fojt while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
266085658deSDaniel Fojt {
267085658deSDaniel Fojt blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES );
268085658deSDaniel Fojt in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
269085658deSDaniel Fojt inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
270085658deSDaniel Fojt }
271085658deSDaniel Fojt
272085658deSDaniel Fojt if( inlen__ > i * BLAKE2S_BLOCKBYTES )
273085658deSDaniel Fojt {
274085658deSDaniel Fojt const size_t left = inlen__ - i * BLAKE2S_BLOCKBYTES;
275085658deSDaniel Fojt const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES;
276085658deSDaniel Fojt blake2s_update( S[i], in__, len );
277085658deSDaniel Fojt }
278085658deSDaniel Fojt
279085658deSDaniel Fojt blake2s_final( S[i], hash[i], BLAKE2S_OUTBYTES );
280085658deSDaniel Fojt }
281085658deSDaniel Fojt
282085658deSDaniel Fojt if( blake2sp_init_root( FS, outlen, keylen ) < 0 )
283085658deSDaniel Fojt return -1;
284085658deSDaniel Fojt
285085658deSDaniel Fojt FS->last_node = 1;
286085658deSDaniel Fojt
287085658deSDaniel Fojt for( i = 0; i < PARALLELISM_DEGREE; ++i )
288085658deSDaniel Fojt blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES );
289085658deSDaniel Fojt
290085658deSDaniel Fojt return blake2s_final( FS, out, outlen );
291085658deSDaniel Fojt }
292085658deSDaniel Fojt
293085658deSDaniel Fojt
294085658deSDaniel Fojt
295085658deSDaniel Fojt #if defined(BLAKE2SP_SELFTEST)
296085658deSDaniel Fojt #include <string.h>
297085658deSDaniel Fojt #include "blake2-kat.h"
main(void)298085658deSDaniel Fojt int main( void )
299085658deSDaniel Fojt {
300085658deSDaniel Fojt uint8_t key[BLAKE2S_KEYBYTES];
301085658deSDaniel Fojt uint8_t buf[BLAKE2_KAT_LENGTH];
302085658deSDaniel Fojt size_t i, step;
303085658deSDaniel Fojt
304085658deSDaniel Fojt for( i = 0; i < BLAKE2S_KEYBYTES; ++i )
305085658deSDaniel Fojt key[i] = ( uint8_t )i;
306085658deSDaniel Fojt
307085658deSDaniel Fojt for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
308085658deSDaniel Fojt buf[i] = ( uint8_t )i;
309085658deSDaniel Fojt
310085658deSDaniel Fojt /* Test simple API */
311085658deSDaniel Fojt for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
312085658deSDaniel Fojt {
313085658deSDaniel Fojt uint8_t hash[BLAKE2S_OUTBYTES];
314085658deSDaniel Fojt blake2sp( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
315085658deSDaniel Fojt
316085658deSDaniel Fojt if( 0 != memcmp( hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES ) )
317085658deSDaniel Fojt {
318085658deSDaniel Fojt goto fail;
319085658deSDaniel Fojt }
320085658deSDaniel Fojt }
321085658deSDaniel Fojt
322085658deSDaniel Fojt /* Test streaming API */
323085658deSDaniel Fojt for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
324085658deSDaniel Fojt for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
325085658deSDaniel Fojt uint8_t hash[BLAKE2S_OUTBYTES];
326085658deSDaniel Fojt blake2sp_state S;
327085658deSDaniel Fojt uint8_t * p = buf;
328085658deSDaniel Fojt size_t mlen = i;
329085658deSDaniel Fojt int err = 0;
330085658deSDaniel Fojt
331085658deSDaniel Fojt if( (err = blake2sp_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
332085658deSDaniel Fojt goto fail;
333085658deSDaniel Fojt }
334085658deSDaniel Fojt
335085658deSDaniel Fojt while (mlen >= step) {
336085658deSDaniel Fojt if ( (err = blake2sp_update(&S, p, step)) < 0 ) {
337085658deSDaniel Fojt goto fail;
338085658deSDaniel Fojt }
339085658deSDaniel Fojt mlen -= step;
340085658deSDaniel Fojt p += step;
341085658deSDaniel Fojt }
342085658deSDaniel Fojt if ( (err = blake2sp_update(&S, p, mlen)) < 0) {
343085658deSDaniel Fojt goto fail;
344085658deSDaniel Fojt }
345085658deSDaniel Fojt if ( (err = blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
346085658deSDaniel Fojt goto fail;
347085658deSDaniel Fojt }
348085658deSDaniel Fojt
349085658deSDaniel Fojt if (0 != memcmp(hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES)) {
350085658deSDaniel Fojt goto fail;
351085658deSDaniel Fojt }
352085658deSDaniel Fojt }
353085658deSDaniel Fojt }
354085658deSDaniel Fojt
355085658deSDaniel Fojt puts( "ok" );
356085658deSDaniel Fojt return 0;
357085658deSDaniel Fojt fail:
358085658deSDaniel Fojt puts("error");
359085658deSDaniel Fojt return -1;
360085658deSDaniel Fojt }
361085658deSDaniel Fojt #endif
362