]>
Commit | Line | Data |
---|---|---|
50f955b1 TP |
1 | /** |
2 | * BLAKE2 reference source code package - reference C implementations | |
3 | * | |
4 | * Written in 2012 by Samuel Neves <[email protected]> | |
5 | * | |
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. | |
9 | * | |
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/>. | |
12 | */ | |
13 | ||
14 | #include <stdint.h> | |
15 | #include <string.h> | |
16 | #include <stdio.h> | |
17 | ||
18 | #include "sha3/sph_types.h" | |
9f3083cd | 19 | #include "crypto/blake2s.h" |
50f955b1 TP |
20 | |
21 | static const uint32_t blake2s_IV[8] = | |
22 | { | |
23 | 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, | |
24 | 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL | |
25 | }; | |
26 | ||
27 | static const uint8_t blake2s_sigma[10][16] = | |
28 | { | |
29 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , | |
30 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , | |
31 | { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , | |
32 | { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , | |
33 | { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , | |
34 | { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , | |
35 | { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , | |
36 | { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , | |
37 | { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , | |
38 | { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , | |
39 | }; | |
40 | ||
41 | static inline int blake2s_set_lastnode( blake2s_state *S ) | |
42 | { | |
43 | S->f[1] = ~0U; | |
44 | return 0; | |
45 | } | |
46 | ||
47 | static inline int blake2s_clear_lastnode( blake2s_state *S ) | |
48 | { | |
49 | S->f[1] = 0U; | |
50 | return 0; | |
51 | } | |
52 | ||
53 | /* Some helper functions, not necessarily useful */ | |
54 | static inline int blake2s_set_lastblock( blake2s_state *S ) | |
55 | { | |
56 | if( S->last_node ) blake2s_set_lastnode( S ); | |
57 | ||
58 | S->f[0] = ~0U; | |
59 | return 0; | |
60 | } | |
61 | ||
62 | static inline int blake2s_clear_lastblock( blake2s_state *S ) | |
63 | { | |
64 | if( S->last_node ) blake2s_clear_lastnode( S ); | |
65 | ||
66 | S->f[0] = 0U; | |
67 | return 0; | |
68 | } | |
69 | ||
70 | static inline int blake2s_increment_counter( blake2s_state *S, const uint32_t inc ) | |
71 | { | |
72 | S->t[0] += inc; | |
73 | S->t[1] += ( S->t[0] < inc ); | |
74 | return 0; | |
75 | } | |
76 | ||
77 | // Parameter-related functions | |
78 | static inline int blake2s_param_set_digest_length( blake2s_param *P, const uint8_t digest_length ) | |
79 | { | |
80 | P->digest_length = digest_length; | |
81 | return 0; | |
82 | } | |
83 | ||
84 | static inline int blake2s_param_set_fanout( blake2s_param *P, const uint8_t fanout ) | |
85 | { | |
86 | P->fanout = fanout; | |
87 | return 0; | |
88 | } | |
89 | ||
90 | static inline int blake2s_param_set_max_depth( blake2s_param *P, const uint8_t depth ) | |
91 | { | |
92 | P->depth = depth; | |
93 | return 0; | |
94 | } | |
95 | ||
96 | static inline int blake2s_param_set_leaf_length( blake2s_param *P, const uint32_t leaf_length ) | |
97 | { | |
98 | store32( &P->leaf_length, leaf_length ); | |
99 | return 0; | |
100 | } | |
101 | ||
102 | static inline int blake2s_param_set_node_offset( blake2s_param *P, const uint64_t node_offset ) | |
103 | { | |
104 | store48( P->node_offset, node_offset ); | |
105 | return 0; | |
106 | } | |
107 | ||
108 | static inline int blake2s_param_set_node_depth( blake2s_param *P, const uint8_t node_depth ) | |
109 | { | |
110 | P->node_depth = node_depth; | |
111 | return 0; | |
112 | } | |
113 | ||
114 | static inline int blake2s_param_set_inner_length( blake2s_param *P, const uint8_t inner_length ) | |
115 | { | |
116 | P->inner_length = inner_length; | |
117 | return 0; | |
118 | } | |
119 | ||
120 | static inline int blake2s_param_set_salt( blake2s_param *P, const uint8_t salt[BLAKE2S_SALTBYTES] ) | |
121 | { | |
122 | memcpy( P->salt, salt, BLAKE2S_SALTBYTES ); | |
123 | return 0; | |
124 | } | |
125 | ||
126 | static inline int blake2s_param_set_personal( blake2s_param *P, const uint8_t personal[BLAKE2S_PERSONALBYTES] ) | |
127 | { | |
128 | memcpy( P->personal, personal, BLAKE2S_PERSONALBYTES ); | |
129 | return 0; | |
130 | } | |
131 | ||
132 | static inline int blake2s_init0( blake2s_state *S ) | |
133 | { | |
134 | memset( S, 0, sizeof( blake2s_state ) ); | |
135 | ||
136 | for( int i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i]; | |
137 | ||
138 | return 0; | |
139 | } | |
140 | ||
141 | /* init2 xors IV with input parameter block */ | |
142 | int blake2s_init_param( blake2s_state *S, const blake2s_param *P ) | |
143 | { | |
144 | blake2s_init0( S ); | |
145 | uint32_t *p = ( uint32_t * )( P ); | |
146 | ||
147 | /* IV XOR ParamBlock */ | |
148 | for( size_t i = 0; i < 8; ++i ) | |
149 | S->h[i] ^= load32( &p[i] ); | |
150 | ||
151 | return 0; | |
152 | } | |
153 | ||
154 | ||
155 | // Sequential blake2s initialization | |
156 | int blake2s_init( blake2s_state *S, const uint8_t outlen ) | |
157 | { | |
158 | blake2s_param P[1]; | |
159 | ||
160 | /* Move interval verification here? */ | |
161 | if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; | |
162 | ||
163 | P->digest_length = outlen; | |
164 | P->key_length = 0; | |
165 | P->fanout = 1; | |
166 | P->depth = 1; | |
167 | store32( &P->leaf_length, 0 ); | |
168 | store48( &P->node_offset, 0 ); | |
169 | P->node_depth = 0; | |
170 | P->inner_length = 0; | |
171 | // memset(P->reserved, 0, sizeof(P->reserved) ); | |
172 | memset( P->salt, 0, sizeof( P->salt ) ); | |
173 | memset( P->personal, 0, sizeof( P->personal ) ); | |
174 | return blake2s_init_param( S, P ); | |
175 | } | |
176 | ||
177 | int blake2s_init_key( blake2s_state *S, const uint8_t outlen, const void *key, const uint8_t keylen ) | |
178 | { | |
179 | blake2s_param P[1]; | |
180 | ||
181 | if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; | |
182 | ||
183 | if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1; | |
184 | ||
185 | P->digest_length = outlen; | |
186 | P->key_length = keylen; | |
187 | P->fanout = 1; | |
188 | P->depth = 1; | |
189 | store32( &P->leaf_length, 0 ); | |
190 | store48( &P->node_offset, 0 ); | |
191 | P->node_depth = 0; | |
192 | P->inner_length = 0; | |
193 | // memset(P->reserved, 0, sizeof(P->reserved) ); | |
194 | memset( P->salt, 0, sizeof( P->salt ) ); | |
195 | memset( P->personal, 0, sizeof( P->personal ) ); | |
196 | ||
197 | if( blake2s_init_param( S, P ) < 0 ) return -1; | |
198 | ||
199 | { | |
200 | uint8_t block[BLAKE2S_BLOCKBYTES]; | |
201 | memset( block, 0, BLAKE2S_BLOCKBYTES ); | |
202 | memcpy( block, key, keylen ); | |
203 | blake2s_update( S, block, BLAKE2S_BLOCKBYTES ); | |
204 | secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */ | |
205 | } | |
206 | return 0; | |
207 | } | |
208 | ||
209 | int blake2s_compress( blake2s_state *S, const uint8_t block[BLAKE2S_BLOCKBYTES] ) | |
210 | { | |
211 | uint32_t m[16]; | |
212 | uint32_t v[16]; | |
213 | ||
214 | for( size_t i = 0; i < 16; ++i ) | |
215 | m[i] = load32( block + i * sizeof( m[i] ) ); | |
216 | ||
217 | for( size_t i = 0; i < 8; ++i ) | |
218 | v[i] = S->h[i]; | |
219 | ||
220 | v[ 8] = blake2s_IV[0]; | |
221 | v[ 9] = blake2s_IV[1]; | |
222 | v[10] = blake2s_IV[2]; | |
223 | v[11] = blake2s_IV[3]; | |
224 | v[12] = S->t[0] ^ blake2s_IV[4]; | |
225 | v[13] = S->t[1] ^ blake2s_IV[5]; | |
226 | v[14] = S->f[0] ^ blake2s_IV[6]; | |
227 | v[15] = S->f[1] ^ blake2s_IV[7]; | |
228 | #define G(r,i,a,b,c,d) \ | |
229 | do { \ | |
230 | a = a + b + m[blake2s_sigma[r][2*i+0]]; \ | |
231 | d = SPH_ROTR32(d ^ a, 16); \ | |
232 | c = c + d; \ | |
233 | b = SPH_ROTR32(b ^ c, 12); \ | |
234 | a = a + b + m[blake2s_sigma[r][2*i+1]]; \ | |
235 | d = SPH_ROTR32(d ^ a, 8); \ | |
236 | c = c + d; \ | |
237 | b = SPH_ROTR32(b ^ c, 7); \ | |
238 | } while(0) | |
239 | #define ROUND(r) \ | |
240 | do { \ | |
241 | G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ | |
242 | G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ | |
243 | G(r,2,v[ 2],v[ 6],v[10],v[14]); \ | |
244 | G(r,3,v[ 3],v[ 7],v[11],v[15]); \ | |
245 | G(r,4,v[ 0],v[ 5],v[10],v[15]); \ | |
246 | G(r,5,v[ 1],v[ 6],v[11],v[12]); \ | |
247 | G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ | |
248 | G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ | |
249 | } while(0) | |
250 | ROUND( 0 ); | |
251 | ROUND( 1 ); | |
252 | ROUND( 2 ); | |
253 | ROUND( 3 ); | |
254 | ROUND( 4 ); | |
255 | ROUND( 5 ); | |
256 | ROUND( 6 ); | |
257 | ROUND( 7 ); | |
258 | ROUND( 8 ); | |
259 | ROUND( 9 ); | |
260 | ||
261 | for( size_t i = 0; i < 8; ++i ) | |
262 | S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; | |
263 | ||
264 | #undef G | |
265 | #undef ROUND | |
266 | return 0; | |
267 | } | |
268 | ||
269 | ||
270 | int blake2s_update( blake2s_state *S, const uint8_t *in, uint64_t inlen ) | |
271 | { | |
272 | while( inlen > 0 ) | |
273 | { | |
274 | size_t left = S->buflen; | |
275 | size_t fill = 2 * BLAKE2S_BLOCKBYTES - left; | |
276 | ||
277 | if( inlen > fill ) | |
278 | { | |
279 | memcpy( S->buf + left, in, fill ); // Fill buffer | |
280 | S->buflen += fill; | |
281 | blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); | |
282 | blake2s_compress( S, S->buf ); // Compress | |
283 | memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); // Shift buffer left | |
284 | S->buflen -= BLAKE2S_BLOCKBYTES; | |
285 | in += fill; | |
286 | inlen -= fill; | |
287 | } | |
288 | else // inlen <= fill | |
289 | { | |
588f5d90 TP |
290 | memcpy(S->buf + left, in, (size_t) inlen); |
291 | S->buflen += (size_t) inlen; // Be lazy, do not compress | |
50f955b1 TP |
292 | in += inlen; |
293 | inlen -= inlen; | |
294 | } | |
295 | } | |
296 | ||
297 | return 0; | |
298 | } | |
299 | ||
300 | int blake2s_final( blake2s_state *S, uint8_t *out, uint8_t outlen ) | |
301 | { | |
302 | uint8_t buffer[BLAKE2S_OUTBYTES]; | |
303 | ||
304 | if( S->buflen > BLAKE2S_BLOCKBYTES ) | |
305 | { | |
306 | blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); | |
307 | blake2s_compress( S, S->buf ); | |
308 | S->buflen -= BLAKE2S_BLOCKBYTES; | |
309 | memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, S->buflen ); | |
310 | } | |
311 | ||
312 | blake2s_increment_counter( S, ( uint32_t )S->buflen ); | |
313 | blake2s_set_lastblock( S ); | |
314 | memset( S->buf + S->buflen, 0, 2 * BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */ | |
315 | blake2s_compress( S, S->buf ); | |
316 | ||
317 | for( int i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ | |
318 | store32( buffer + sizeof( S->h[i] ) * i, S->h[i] ); | |
319 | ||
320 | memcpy( out, buffer, outlen ); | |
321 | return 0; | |
322 | } | |
323 | ||
324 | int blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ) | |
325 | { | |
7411020c | 326 | blake2s_state S; |
50f955b1 TP |
327 | |
328 | /* Verify parameters */ | |
329 | if ( NULL == in ) return -1; | |
330 | ||
331 | if ( NULL == out ) return -1; | |
332 | ||
333 | if ( NULL == key ) keylen = 0; /* Fail here instead if keylen != 0 and key == NULL? */ | |
334 | ||
335 | if( keylen > 0 ) | |
336 | { | |
7411020c | 337 | if( blake2s_init_key( &S, outlen, key, keylen ) < 0 ) return -1; |
50f955b1 TP |
338 | } |
339 | else | |
340 | { | |
7411020c | 341 | if( blake2s_init( &S, outlen ) < 0 ) return -1; |
50f955b1 TP |
342 | } |
343 | ||
7411020c | 344 | blake2s_update( &S, ( uint8_t * )in, inlen ); |
345 | blake2s_final( &S, out, outlen ); | |
50f955b1 TP |
346 | return 0; |
347 | } | |
348 | ||
349 | #if defined(BLAKE2S_SELFTEST) | |
350 | #include <string.h> | |
351 | #include "blake2-kat.h" /* test data not included */ | |
352 | int main( int argc, char **argv ) | |
353 | { | |
354 | uint8_t key[BLAKE2S_KEYBYTES]; | |
355 | uint8_t buf[KAT_LENGTH]; | |
356 | ||
357 | for( size_t i = 0; i < BLAKE2S_KEYBYTES; ++i ) | |
358 | key[i] = ( uint8_t )i; | |
359 | ||
360 | for( size_t i = 0; i < KAT_LENGTH; ++i ) | |
361 | buf[i] = ( uint8_t )i; | |
362 | ||
363 | for( size_t i = 0; i < KAT_LENGTH; ++i ) | |
364 | { | |
365 | uint8_t hash[BLAKE2S_OUTBYTES]; | |
366 | blake2s( hash, buf, key, BLAKE2S_OUTBYTES, i, BLAKE2S_KEYBYTES ); | |
367 | ||
368 | if( 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) ) | |
369 | { | |
370 | puts( "error" ); | |
371 | return -1; | |
372 | } | |
373 | } | |
374 | ||
375 | puts( "ok" ); | |
376 | return 0; | |
377 | } | |
378 | #endif |