2 BLAKE2 reference source code package - optimized C implementations
4 Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
6 To the extent possible under law, the author(s) have dedicated all copyright
7 and related and neighboring rights to this software to the public domain
8 worldwide. This software is distributed without any warranty.
10 You should have received a copy of the CC0 Public Domain Dedication along with
11 this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
23 #include "blake2-impl.h"
25 #define PARALLELISM_DEGREE 8
27 static int blake2sp_init_leaf( blake2s_state *S, uint8_t outlen, uint8_t keylen, uint64_t offset )
30 P->digest_length = outlen;
31 P->key_length = keylen;
32 P->fanout = PARALLELISM_DEGREE;
35 store48( P->node_offset, offset );
37 P->inner_length = BLAKE2S_OUTBYTES;
38 memset( P->salt, 0, sizeof( P->salt ) );
39 memset( P->personal, 0, sizeof( P->personal ) );
40 blake2s_init_param( S, P );
41 S->outlen = P->inner_length;
45 static int blake2sp_init_root( blake2s_state *S, uint8_t outlen, uint8_t keylen )
48 P->digest_length = outlen;
49 P->key_length = keylen;
50 P->fanout = PARALLELISM_DEGREE;
53 store48( P->node_offset, 0ULL );
55 P->inner_length = BLAKE2S_OUTBYTES;
56 memset( P->salt, 0, sizeof( P->salt ) );
57 memset( P->personal, 0, sizeof( P->personal ) );
58 blake2s_init_param( S, P );
59 S->outlen = P->digest_length;
64 int blake2sp_init( blake2sp_state *S, size_t outlen )
66 if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
68 memset( S->buf, 0, sizeof( S->buf ) );
71 if( blake2sp_init_root( S->R, ( uint8_t ) outlen, 0 ) < 0 )
74 for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
75 if( blake2sp_init_leaf( S->S[i], ( uint8_t ) outlen, 0, i ) < 0 ) return -1;
78 S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
79 S->outlen = ( uint8_t ) outlen;
83 int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen )
85 if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
87 if( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
89 memset( S->buf, 0, sizeof( S->buf ) );
92 if( blake2sp_init_root( S->R, ( uint8_t ) outlen, ( uint8_t ) keylen ) < 0 )
95 for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
96 if( blake2sp_init_leaf( S->S[i], ( uint8_t ) outlen, ( uint8_t ) keylen, i ) < 0 )
100 S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
101 S->outlen = ( uint8_t ) outlen;
103 uint8_t block[BLAKE2S_BLOCKBYTES];
104 memset( block, 0, BLAKE2S_BLOCKBYTES );
105 memcpy( block, key, keylen );
107 for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
108 blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES );
110 secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
116 int blake2sp_update( blake2sp_state *S, const uint8_t *in, size_t inlen )
118 size_t left = S->buflen;
119 size_t fill = sizeof( S->buf ) - left;
121 if( left && inlen >= fill )
123 memcpy( S->buf + left, in, fill );
125 for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
126 blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
134 omp_set_num_threads(PARALLELISM_DEGREE);
135 #pragma omp parallel shared(S)
137 for( size_t id__ = 0; id__ < PARALLELISM_DEGREE; ++id__ )
141 size_t id__ = ( size_t ) omp_get_thread_num();
143 size_t inlen__ = inlen;
144 const uint8_t *in__ = ( const uint8_t * )in;
145 in__ += id__ * BLAKE2S_BLOCKBYTES;
147 while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
149 blake2s_update( S->S[id__], in__, BLAKE2S_BLOCKBYTES );
150 in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
151 inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
155 in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
156 inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
159 memcpy( S->buf + left, in, inlen );
161 S->buflen = ( uint32_t ) left + ( uint32_t ) inlen;
166 int blake2sp_final( blake2sp_state *S, uint8_t *out, size_t outlen )
168 uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
170 if(S->outlen != outlen) return -1;
172 for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
174 if( S->buflen > i * BLAKE2S_BLOCKBYTES )
176 size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES;
178 if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
180 blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
183 blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES );
186 for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
187 blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES );
189 blake2s_final( S->R, out, outlen );
194 int blake2sp( uint8_t *out, const void *in, const void *key, size_t outlen, size_t inlen, size_t keylen )
196 uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
197 blake2s_state S[PARALLELISM_DEGREE][1];
200 /* Verify parameters */
201 if ( NULL == in && inlen > 0 ) return -1;
203 if ( NULL == out ) return -1;
205 if ( NULL == key && keylen > 0 ) return -1;
207 if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
209 if( keylen > BLAKE2S_KEYBYTES ) return -1;
211 for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
212 if( blake2sp_init_leaf( S[i], ( uint8_t ) outlen, ( uint8_t ) keylen, i ) < 0 )
215 S[PARALLELISM_DEGREE - 1]->last_node = 1; // mark last node
219 uint8_t block[BLAKE2S_BLOCKBYTES];
220 memset( block, 0, BLAKE2S_BLOCKBYTES );
221 memcpy( block, key, keylen );
223 for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
224 blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES );
226 secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
230 omp_set_num_threads(PARALLELISM_DEGREE);
231 #pragma omp parallel shared(S,hash)
234 for( size_t id__ = 0; id__ < PARALLELISM_DEGREE; ++id__ )
238 size_t id__ = ( size_t ) omp_get_thread_num();
240 size_t inlen__ = inlen;
241 const uint8_t *in__ = ( const uint8_t * )in;
242 in__ += id__ * BLAKE2S_BLOCKBYTES;
244 while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
246 blake2s_update( S[id__], in__, BLAKE2S_BLOCKBYTES );
247 in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
248 inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
251 if( inlen__ > id__ * BLAKE2S_BLOCKBYTES )
253 const size_t left = inlen__ - id__ * BLAKE2S_BLOCKBYTES;
254 const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES;
255 blake2s_update( S[id__], in__, len );
258 blake2s_final( S[id__], hash[id__], BLAKE2S_OUTBYTES );
261 if( blake2sp_init_root( FS, ( uint8_t ) outlen, ( uint8_t ) keylen ) < 0 )
266 for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
267 blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES );
269 return blake2s_final( FS, out, outlen );