blake2s-ref.c - pee - Pee a password manager;Pee - because you have to... | |
git clone git://vernunftzentrum.de/pee.git | |
Log | |
Files | |
Refs | |
LICENSE | |
--- | |
blake2s-ref.c (10089B) | |
--- | |
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 co… | |
7 and related and neighboring rights to this software to the public dom… | |
8 worldwide. This software is distributed without any warranty. | |
9 | |
10 You should have received a copy of the CC0 Public Domain Dedication a… | |
11 this software. If not, see <http://creativecommons.org/publicdomain/z… | |
12 */ | |
13 | |
14 #include <stdint.h> | |
15 #include <string.h> | |
16 #include <stdio.h> | |
17 | |
18 #include "blake2.h" | |
19 #include "blake2-impl.h" | |
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] = -1; | |
44 return 0; | |
45 } | |
46 | |
47 static inline int blake2s_clear_lastnode( blake2s_state *S ) | |
48 { | |
49 S->f[1] = 0; | |
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] = -1; | |
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] = 0; | |
67 return 0; | |
68 } | |
69 | |
70 static inline int blake2s_increment_counter( blake2s_state *S, const uin… | |
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, con… | |
79 { | |
80 P->digest_length = digest_length; | |
81 return 0; | |
82 } | |
83 | |
84 static inline int blake2s_param_set_fanout( blake2s_param *P, const uint… | |
85 { | |
86 P->fanout = fanout; | |
87 return 0; | |
88 } | |
89 | |
90 static inline int blake2s_param_set_max_depth( blake2s_param *P, const u… | |
91 { | |
92 P->depth = depth; | |
93 return 0; | |
94 } | |
95 | |
96 static inline int blake2s_param_set_leaf_length( blake2s_param *P, const… | |
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… | |
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 … | |
109 { | |
110 P->node_depth = node_depth; | |
111 return 0; | |
112 } | |
113 | |
114 static inline int blake2s_param_set_inner_length( blake2s_param *P, cons… | |
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_… | |
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 ui… | |
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 const uint32_t *p = ( const 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… | |
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 fro… | |
205 } | |
206 return 0; | |
207 } | |
208 | |
209 static int blake2s_compress( blake2s_state *S, const uint8_t block[BLAKE… | |
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 = rotr32(d ^ a, 16); \ | |
232 c = c + d; \ | |
233 b = rotr32(b ^ c, 12); \ | |
234 a = a + b + m[blake2s_sigma[r][2*i+1]]; \ | |
235 d = rotr32(d ^ a, 8); \ | |
236 c = c + d; \ | |
237 b = 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 );… | |
284 S->buflen -= BLAKE2S_BLOCKBYTES; | |
285 in += fill; | |
286 inlen -= fill; | |
287 } | |
288 else // inlen <= fill | |
289 { | |
290 memcpy( S->buf + left, in, inlen ); | |
291 S->buflen += inlen; // Be lazy, do not compress | |
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] = {0}; | |
303 | |
304 if( outlen > BLAKE2S_OUTBYTES ) | |
305 return -1; | |
306 | |
307 if( S->buflen > BLAKE2S_BLOCKBYTES ) | |
308 { | |
309 blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); | |
310 blake2s_compress( S, S->buf ); | |
311 S->buflen -= BLAKE2S_BLOCKBYTES; | |
312 memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, S->buflen ); | |
313 } | |
314 | |
315 blake2s_increment_counter( S, ( uint32_t )S->buflen ); | |
316 blake2s_set_lastblock( S ); | |
317 memset( S->buf + S->buflen, 0, 2 * BLAKE2S_BLOCKBYTES - S->buflen ); /… | |
318 blake2s_compress( S, S->buf ); | |
319 | |
320 for( int i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ | |
321 store32( buffer + sizeof( S->h[i] ) * i, S->h[i] ); | |
322 | |
323 memcpy( out, buffer, outlen ); | |
324 return 0; | |
325 } | |
326 | |
327 int blake2s( uint8_t *out, const void *in, const void *key, const uint8_… | |
328 { | |
329 blake2s_state S[1]; | |
330 | |
331 /* Verify parameters */ | |
332 if ( NULL == in && inlen > 0 ) return -1; | |
333 | |
334 if ( NULL == out ) return -1; | |
335 | |
336 if ( NULL == key && keylen > 0) return -1; | |
337 | |
338 if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1; | |
339 | |
340 if( keylen > BLAKE2S_KEYBYTES ) return -1; | |
341 | |
342 if( keylen > 0 ) | |
343 { | |
344 if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1; | |
345 } | |
346 else | |
347 { | |
348 if( blake2s_init( S, outlen ) < 0 ) return -1; | |
349 } | |
350 | |
351 blake2s_update( S, ( const uint8_t * )in, inlen ); | |
352 blake2s_final( S, out, outlen ); | |
353 return 0; | |
354 } | |
355 | |
356 #if defined(SUPERCOP) | |
357 int crypto_hash( unsigned char *out, unsigned char *in, unsigned long lo… | |
358 { | |
359 return blake2s( out, in, NULL, BLAKE2S_OUTBYTES, inlen, 0 ); | |
360 } | |
361 #endif | |
362 | |
363 #if defined(BLAKE2S_SELFTEST) | |
364 #include <string.h> | |
365 #include "blake2-kat.h" | |
366 int main( int argc, char **argv ) | |
367 { | |
368 uint8_t key[BLAKE2S_KEYBYTES]; | |
369 uint8_t buf[KAT_LENGTH]; | |
370 | |
371 for( size_t i = 0; i < BLAKE2S_KEYBYTES; ++i ) | |
372 key[i] = ( uint8_t )i; | |
373 | |
374 for( size_t i = 0; i < KAT_LENGTH; ++i ) | |
375 buf[i] = ( uint8_t )i; | |
376 | |
377 for( size_t i = 0; i < KAT_LENGTH; ++i ) | |
378 { | |
379 uint8_t hash[BLAKE2S_OUTBYTES]; | |
380 blake2s( hash, buf, key, BLAKE2S_OUTBYTES, i, BLAKE2S_KEYBYTES ); | |
381 | |
382 if( 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) ) | |
383 { | |
384 puts( "error" ); | |
385 return -1; | |
386 } | |
387 } | |
388 | |
389 puts( "ok" ); | |
390 return 0; | |
391 } | |
392 #endif | |
393 | |
394 |