1*0e33efe4SConrad Meyer /*
2*0e33efe4SConrad Meyer BLAKE2 reference source code package - optimized 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 <stdlib.h>
15*0e33efe4SConrad Meyer #include <string.h>
16*0e33efe4SConrad Meyer #include <stdio.h>
17*0e33efe4SConrad Meyer
18*0e33efe4SConrad Meyer #if defined(_OPENMP)
19*0e33efe4SConrad Meyer #include <omp.h>
20*0e33efe4SConrad Meyer #endif
21*0e33efe4SConrad Meyer
22*0e33efe4SConrad Meyer #include "blake2.h"
23*0e33efe4SConrad Meyer #include "blake2-impl.h"
24*0e33efe4SConrad Meyer
25*0e33efe4SConrad Meyer #define PARALLELISM_DEGREE 8
26*0e33efe4SConrad Meyer
blake2sp_init_leaf(blake2s_state * S,uint8_t outlen,uint8_t keylen,uint64_t offset)27*0e33efe4SConrad Meyer static int blake2sp_init_leaf( blake2s_state *S, uint8_t outlen, uint8_t keylen, uint64_t offset )
28*0e33efe4SConrad Meyer {
29*0e33efe4SConrad Meyer blake2s_param P[1];
30*0e33efe4SConrad Meyer P->digest_length = outlen;
31*0e33efe4SConrad Meyer P->key_length = keylen;
32*0e33efe4SConrad Meyer P->fanout = PARALLELISM_DEGREE;
33*0e33efe4SConrad Meyer P->depth = 2;
34*0e33efe4SConrad Meyer P->leaf_length = 0;
35*0e33efe4SConrad Meyer store48( P->node_offset, offset );
36*0e33efe4SConrad Meyer P->node_depth = 0;
37*0e33efe4SConrad Meyer P->inner_length = BLAKE2S_OUTBYTES;
38*0e33efe4SConrad Meyer memset( P->salt, 0, sizeof( P->salt ) );
39*0e33efe4SConrad Meyer memset( P->personal, 0, sizeof( P->personal ) );
40*0e33efe4SConrad Meyer blake2s_init_param( S, P );
41*0e33efe4SConrad Meyer S->outlen = P->inner_length;
42*0e33efe4SConrad Meyer return 0;
43*0e33efe4SConrad Meyer }
44*0e33efe4SConrad Meyer
blake2sp_init_root(blake2s_state * S,uint8_t outlen,uint8_t keylen)45*0e33efe4SConrad Meyer static int blake2sp_init_root( blake2s_state *S, uint8_t outlen, uint8_t keylen )
46*0e33efe4SConrad Meyer {
47*0e33efe4SConrad Meyer blake2s_param P[1];
48*0e33efe4SConrad Meyer P->digest_length = outlen;
49*0e33efe4SConrad Meyer P->key_length = keylen;
50*0e33efe4SConrad Meyer P->fanout = PARALLELISM_DEGREE;
51*0e33efe4SConrad Meyer P->depth = 2;
52*0e33efe4SConrad Meyer P->leaf_length = 0;
53*0e33efe4SConrad Meyer store48( P->node_offset, 0ULL );
54*0e33efe4SConrad Meyer P->node_depth = 1;
55*0e33efe4SConrad Meyer P->inner_length = BLAKE2S_OUTBYTES;
56*0e33efe4SConrad Meyer memset( P->salt, 0, sizeof( P->salt ) );
57*0e33efe4SConrad Meyer memset( P->personal, 0, sizeof( P->personal ) );
58*0e33efe4SConrad Meyer blake2s_init_param( S, P );
59*0e33efe4SConrad Meyer S->outlen = P->digest_length;
60*0e33efe4SConrad Meyer return 0;
61*0e33efe4SConrad Meyer }
62*0e33efe4SConrad Meyer
63*0e33efe4SConrad Meyer
blake2sp_init(blake2sp_state * S,size_t outlen)64*0e33efe4SConrad Meyer int blake2sp_init( blake2sp_state *S, size_t outlen )
65*0e33efe4SConrad Meyer {
66*0e33efe4SConrad Meyer if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
67*0e33efe4SConrad Meyer
68*0e33efe4SConrad Meyer memset( S->buf, 0, sizeof( S->buf ) );
69*0e33efe4SConrad Meyer S->buflen = 0;
70*0e33efe4SConrad Meyer
71*0e33efe4SConrad Meyer if( blake2sp_init_root( S->R, ( uint8_t ) outlen, 0 ) < 0 )
72*0e33efe4SConrad Meyer return -1;
73*0e33efe4SConrad Meyer
74*0e33efe4SConrad Meyer for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
75*0e33efe4SConrad Meyer if( blake2sp_init_leaf( S->S[i], ( uint8_t ) outlen, 0, i ) < 0 ) return -1;
76*0e33efe4SConrad Meyer
77*0e33efe4SConrad Meyer S->R->last_node = 1;
78*0e33efe4SConrad Meyer S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
79*0e33efe4SConrad Meyer S->outlen = ( uint8_t ) outlen;
80*0e33efe4SConrad Meyer return 0;
81*0e33efe4SConrad Meyer }
82*0e33efe4SConrad Meyer
blake2sp_init_key(blake2sp_state * S,size_t outlen,const void * key,size_t keylen)83*0e33efe4SConrad Meyer int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen )
84*0e33efe4SConrad Meyer {
85*0e33efe4SConrad Meyer if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
86*0e33efe4SConrad Meyer
87*0e33efe4SConrad Meyer if( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
88*0e33efe4SConrad Meyer
89*0e33efe4SConrad Meyer memset( S->buf, 0, sizeof( S->buf ) );
90*0e33efe4SConrad Meyer S->buflen = 0;
91*0e33efe4SConrad Meyer
92*0e33efe4SConrad Meyer if( blake2sp_init_root( S->R, ( uint8_t ) outlen, ( uint8_t ) keylen ) < 0 )
93*0e33efe4SConrad Meyer return -1;
94*0e33efe4SConrad Meyer
95*0e33efe4SConrad Meyer for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
96*0e33efe4SConrad Meyer if( blake2sp_init_leaf( S->S[i], ( uint8_t ) outlen, ( uint8_t ) keylen, i ) < 0 )
97*0e33efe4SConrad Meyer return -1;
98*0e33efe4SConrad Meyer
99*0e33efe4SConrad Meyer S->R->last_node = 1;
100*0e33efe4SConrad Meyer S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
101*0e33efe4SConrad Meyer S->outlen = ( uint8_t ) outlen;
102*0e33efe4SConrad Meyer {
103*0e33efe4SConrad Meyer uint8_t block[BLAKE2S_BLOCKBYTES];
104*0e33efe4SConrad Meyer memset( block, 0, BLAKE2S_BLOCKBYTES );
105*0e33efe4SConrad Meyer memcpy( block, key, keylen );
106*0e33efe4SConrad Meyer
107*0e33efe4SConrad Meyer for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
108*0e33efe4SConrad Meyer blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES );
109*0e33efe4SConrad Meyer
110*0e33efe4SConrad Meyer secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
111*0e33efe4SConrad Meyer }
112*0e33efe4SConrad Meyer return 0;
113*0e33efe4SConrad Meyer }
114*0e33efe4SConrad Meyer
115*0e33efe4SConrad Meyer
blake2sp_update(blake2sp_state * S,const uint8_t * in,size_t inlen)116*0e33efe4SConrad Meyer int blake2sp_update( blake2sp_state *S, const uint8_t *in, size_t inlen )
117*0e33efe4SConrad Meyer {
118*0e33efe4SConrad Meyer size_t left = S->buflen;
119*0e33efe4SConrad Meyer size_t fill = sizeof( S->buf ) - left;
120*0e33efe4SConrad Meyer
121*0e33efe4SConrad Meyer if( left && inlen >= fill )
122*0e33efe4SConrad Meyer {
123*0e33efe4SConrad Meyer memcpy( S->buf + left, in, fill );
124*0e33efe4SConrad Meyer
125*0e33efe4SConrad Meyer for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
126*0e33efe4SConrad Meyer blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
127*0e33efe4SConrad Meyer
128*0e33efe4SConrad Meyer in += fill;
129*0e33efe4SConrad Meyer inlen -= fill;
130*0e33efe4SConrad Meyer left = 0;
131*0e33efe4SConrad Meyer }
132*0e33efe4SConrad Meyer
133*0e33efe4SConrad Meyer #if defined(_OPENMP)
134*0e33efe4SConrad Meyer omp_set_num_threads(PARALLELISM_DEGREE);
135*0e33efe4SConrad Meyer #pragma omp parallel shared(S)
136*0e33efe4SConrad Meyer #else
137*0e33efe4SConrad Meyer for( size_t id__ = 0; id__ < PARALLELISM_DEGREE; ++id__ )
138*0e33efe4SConrad Meyer #endif
139*0e33efe4SConrad Meyer {
140*0e33efe4SConrad Meyer #if defined(_OPENMP)
141*0e33efe4SConrad Meyer size_t id__ = ( size_t ) omp_get_thread_num();
142*0e33efe4SConrad Meyer #endif
143*0e33efe4SConrad Meyer size_t inlen__ = inlen;
144*0e33efe4SConrad Meyer const uint8_t *in__ = ( const uint8_t * )in;
145*0e33efe4SConrad Meyer in__ += id__ * BLAKE2S_BLOCKBYTES;
146*0e33efe4SConrad Meyer
147*0e33efe4SConrad Meyer while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
148*0e33efe4SConrad Meyer {
149*0e33efe4SConrad Meyer blake2s_update( S->S[id__], in__, BLAKE2S_BLOCKBYTES );
150*0e33efe4SConrad Meyer in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
151*0e33efe4SConrad Meyer inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
152*0e33efe4SConrad Meyer }
153*0e33efe4SConrad Meyer }
154*0e33efe4SConrad Meyer
155*0e33efe4SConrad Meyer in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
156*0e33efe4SConrad Meyer inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
157*0e33efe4SConrad Meyer
158*0e33efe4SConrad Meyer if( inlen > 0 )
159*0e33efe4SConrad Meyer memcpy( S->buf + left, in, inlen );
160*0e33efe4SConrad Meyer
161*0e33efe4SConrad Meyer S->buflen = ( uint32_t ) left + ( uint32_t ) inlen;
162*0e33efe4SConrad Meyer return 0;
163*0e33efe4SConrad Meyer }
164*0e33efe4SConrad Meyer
165*0e33efe4SConrad Meyer
blake2sp_final(blake2sp_state * S,uint8_t * out,size_t outlen)166*0e33efe4SConrad Meyer int blake2sp_final( blake2sp_state *S, uint8_t *out, size_t outlen )
167*0e33efe4SConrad Meyer {
168*0e33efe4SConrad Meyer uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
169*0e33efe4SConrad Meyer
170*0e33efe4SConrad Meyer if(S->outlen != outlen) return -1;
171*0e33efe4SConrad Meyer
172*0e33efe4SConrad Meyer for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
173*0e33efe4SConrad Meyer {
174*0e33efe4SConrad Meyer if( S->buflen > i * BLAKE2S_BLOCKBYTES )
175*0e33efe4SConrad Meyer {
176*0e33efe4SConrad Meyer size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES;
177*0e33efe4SConrad Meyer
178*0e33efe4SConrad Meyer if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
179*0e33efe4SConrad Meyer
180*0e33efe4SConrad Meyer blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
181*0e33efe4SConrad Meyer }
182*0e33efe4SConrad Meyer
183*0e33efe4SConrad Meyer blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES );
184*0e33efe4SConrad Meyer }
185*0e33efe4SConrad Meyer
186*0e33efe4SConrad Meyer for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
187*0e33efe4SConrad Meyer blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES );
188*0e33efe4SConrad Meyer
189*0e33efe4SConrad Meyer blake2s_final( S->R, out, outlen );
190*0e33efe4SConrad Meyer return 0;
191*0e33efe4SConrad Meyer }
192*0e33efe4SConrad Meyer
193*0e33efe4SConrad Meyer
blake2sp(uint8_t * out,const void * in,const void * key,size_t outlen,size_t inlen,size_t keylen)194*0e33efe4SConrad Meyer int blake2sp( uint8_t *out, const void *in, const void *key, size_t outlen, size_t inlen, size_t keylen )
195*0e33efe4SConrad Meyer {
196*0e33efe4SConrad Meyer uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
197*0e33efe4SConrad Meyer blake2s_state S[PARALLELISM_DEGREE][1];
198*0e33efe4SConrad Meyer blake2s_state FS[1];
199*0e33efe4SConrad Meyer
200*0e33efe4SConrad Meyer /* Verify parameters */
201*0e33efe4SConrad Meyer if ( NULL == in && inlen > 0 ) return -1;
202*0e33efe4SConrad Meyer
203*0e33efe4SConrad Meyer if ( NULL == out ) return -1;
204*0e33efe4SConrad Meyer
205*0e33efe4SConrad Meyer if ( NULL == key && keylen > 0 ) return -1;
206*0e33efe4SConrad Meyer
207*0e33efe4SConrad Meyer if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
208*0e33efe4SConrad Meyer
209*0e33efe4SConrad Meyer if( keylen > BLAKE2S_KEYBYTES ) return -1;
210*0e33efe4SConrad Meyer
211*0e33efe4SConrad Meyer for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
212*0e33efe4SConrad Meyer if( blake2sp_init_leaf( S[i], ( uint8_t ) outlen, ( uint8_t ) keylen, i ) < 0 )
213*0e33efe4SConrad Meyer return -1;
214*0e33efe4SConrad Meyer
215*0e33efe4SConrad Meyer S[PARALLELISM_DEGREE - 1]->last_node = 1; // mark last node
216*0e33efe4SConrad Meyer
217*0e33efe4SConrad Meyer if( keylen > 0 )
218*0e33efe4SConrad Meyer {
219*0e33efe4SConrad Meyer uint8_t block[BLAKE2S_BLOCKBYTES];
220*0e33efe4SConrad Meyer memset( block, 0, BLAKE2S_BLOCKBYTES );
221*0e33efe4SConrad Meyer memcpy( block, key, keylen );
222*0e33efe4SConrad Meyer
223*0e33efe4SConrad Meyer for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
224*0e33efe4SConrad Meyer blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES );
225*0e33efe4SConrad Meyer
226*0e33efe4SConrad Meyer secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
227*0e33efe4SConrad Meyer }
228*0e33efe4SConrad Meyer
229*0e33efe4SConrad Meyer #if defined(_OPENMP)
230*0e33efe4SConrad Meyer omp_set_num_threads(PARALLELISM_DEGREE);
231*0e33efe4SConrad Meyer #pragma omp parallel shared(S,hash)
232*0e33efe4SConrad Meyer #else
233*0e33efe4SConrad Meyer
234*0e33efe4SConrad Meyer for( size_t id__ = 0; id__ < PARALLELISM_DEGREE; ++id__ )
235*0e33efe4SConrad Meyer #endif
236*0e33efe4SConrad Meyer {
237*0e33efe4SConrad Meyer #if defined(_OPENMP)
238*0e33efe4SConrad Meyer size_t id__ = ( size_t ) omp_get_thread_num();
239*0e33efe4SConrad Meyer #endif
240*0e33efe4SConrad Meyer size_t inlen__ = inlen;
241*0e33efe4SConrad Meyer const uint8_t *in__ = ( const uint8_t * )in;
242*0e33efe4SConrad Meyer in__ += id__ * BLAKE2S_BLOCKBYTES;
243*0e33efe4SConrad Meyer
244*0e33efe4SConrad Meyer while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
245*0e33efe4SConrad Meyer {
246*0e33efe4SConrad Meyer blake2s_update( S[id__], in__, BLAKE2S_BLOCKBYTES );
247*0e33efe4SConrad Meyer in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
248*0e33efe4SConrad Meyer inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
249*0e33efe4SConrad Meyer }
250*0e33efe4SConrad Meyer
251*0e33efe4SConrad Meyer if( inlen__ > id__ * BLAKE2S_BLOCKBYTES )
252*0e33efe4SConrad Meyer {
253*0e33efe4SConrad Meyer const size_t left = inlen__ - id__ * BLAKE2S_BLOCKBYTES;
254*0e33efe4SConrad Meyer const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES;
255*0e33efe4SConrad Meyer blake2s_update( S[id__], in__, len );
256*0e33efe4SConrad Meyer }
257*0e33efe4SConrad Meyer
258*0e33efe4SConrad Meyer blake2s_final( S[id__], hash[id__], BLAKE2S_OUTBYTES );
259*0e33efe4SConrad Meyer }
260*0e33efe4SConrad Meyer
261*0e33efe4SConrad Meyer if( blake2sp_init_root( FS, ( uint8_t ) outlen, ( uint8_t ) keylen ) < 0 )
262*0e33efe4SConrad Meyer return -1;
263*0e33efe4SConrad Meyer
264*0e33efe4SConrad Meyer FS->last_node = 1;
265*0e33efe4SConrad Meyer
266*0e33efe4SConrad Meyer for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
267*0e33efe4SConrad Meyer blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES );
268*0e33efe4SConrad Meyer
269*0e33efe4SConrad Meyer return blake2s_final( FS, out, outlen );
270*0e33efe4SConrad Meyer }
271*0e33efe4SConrad Meyer
272*0e33efe4SConrad Meyer
273*0e33efe4SConrad Meyer
274*0e33efe4SConrad Meyer
275