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