1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3
4 /*
5 BLAKE2 reference source code package - reference C implementations
6
7 Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
8 terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
9 your option. The terms of these licenses can be found at:
10
11 - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
12 - OpenSSL license : https://www.openssl.org/source/license.html
13 - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
14
15 More information about the BLAKE2 hash function can be found at
16 https://blake2.net.
17 */
18 /* see also https://www.ietf.org/rfc/rfc7693.txt */
19
20 #include "tomcrypt_private.h"
21
22 #ifdef LTC_BLAKE2S
23
24 enum blake2s_constant {
25 BLAKE2S_BLOCKBYTES = 64,
26 BLAKE2S_OUTBYTES = 32,
27 BLAKE2S_KEYBYTES = 32,
28 BLAKE2S_SALTBYTES = 8,
29 BLAKE2S_PERSONALBYTES = 8,
30 BLAKE2S_PARAM_SIZE = 32
31 };
32
33 /* param offsets */
34 enum {
35 O_DIGEST_LENGTH = 0,
36 O_KEY_LENGTH = 1,
37 O_FANOUT = 2,
38 O_DEPTH = 3,
39 O_LEAF_LENGTH = 4,
40 O_NODE_OFFSET = 8,
41 O_XOF_LENGTH = 12,
42 O_NODE_DEPTH = 14,
43 O_INNER_LENGTH = 15,
44 O_SALT = 16,
45 O_PERSONAL = 24
46 };
47
48 /*
49 struct blake2s_param {
50 unsigned char digest_length;
51 unsigned char key_length;
52 unsigned char fanout;
53 unsigned char depth;
54 ulong32 leaf_length;
55 ulong32 node_offset;
56 ushort16 xof_length;
57 unsigned char node_depth;
58 unsigned char inner_length;
59 unsigned char salt[BLAKE2S_SALTBYTES];
60 unsigned char personal[BLAKE2S_PERSONALBYTES];
61 };
62 */
63
64 const struct ltc_hash_descriptor blake2s_128_desc =
65 {
66 "blake2s-128",
67 21,
68 16,
69 64,
70 { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 4 },
71 11,
72 &blake2s_128_init,
73 &blake2s_process,
74 &blake2s_done,
75 &blake2s_128_test,
76 NULL
77 };
78
79 const struct ltc_hash_descriptor blake2s_160_desc =
80 {
81 "blake2s-160",
82 22,
83 20,
84 64,
85 { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 5 },
86 11,
87 &blake2s_160_init,
88 &blake2s_process,
89 &blake2s_done,
90 &blake2s_160_test,
91 NULL
92 };
93
94 const struct ltc_hash_descriptor blake2s_224_desc =
95 {
96 "blake2s-224",
97 23,
98 28,
99 64,
100 { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 7 },
101 11,
102 &blake2s_224_init,
103 &blake2s_process,
104 &blake2s_done,
105 &blake2s_224_test,
106 NULL
107 };
108
109 const struct ltc_hash_descriptor blake2s_256_desc =
110 {
111 "blake2s-256",
112 24,
113 32,
114 64,
115 { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 8 },
116 11,
117 &blake2s_256_init,
118 &blake2s_process,
119 &blake2s_done,
120 &blake2s_256_test,
121 NULL
122 };
123
124 static const ulong32 blake2s_IV[8] = {
125 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
126 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
127 };
128
129 static const unsigned char blake2s_sigma[10][16] = {
130 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
131 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
132 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
133 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
134 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
135 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
136 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
137 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
138 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
139 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
140 };
141
s_blake2s_set_lastnode(hash_state * md)142 static void s_blake2s_set_lastnode(hash_state *md) { md->blake2s.f[1] = 0xffffffffUL; }
143
144 /* Some helper functions, not necessarily useful */
s_blake2s_is_lastblock(const hash_state * md)145 static int s_blake2s_is_lastblock(const hash_state *md) { return md->blake2s.f[0] != 0; }
146
s_blake2s_set_lastblock(hash_state * md)147 static void s_blake2s_set_lastblock(hash_state *md)
148 {
149 if (md->blake2s.last_node) {
150 s_blake2s_set_lastnode(md);
151 }
152 md->blake2s.f[0] = 0xffffffffUL;
153 }
154
s_blake2s_increment_counter(hash_state * md,const ulong32 inc)155 static void s_blake2s_increment_counter(hash_state *md, const ulong32 inc)
156 {
157 md->blake2s.t[0] += inc;
158 if (md->blake2s.t[0] < inc) md->blake2s.t[1]++;
159 }
160
s_blake2s_init0(hash_state * md)161 static int s_blake2s_init0(hash_state *md)
162 {
163 int i;
164 XMEMSET(&md->blake2s, 0, sizeof(struct blake2s_state));
165
166 for (i = 0; i < 8; ++i) {
167 md->blake2s.h[i] = blake2s_IV[i];
168 }
169
170 return CRYPT_OK;
171 }
172
173 /* init2 xors IV with input parameter block */
s_blake2s_init_param(hash_state * md,const unsigned char * P)174 static int s_blake2s_init_param(hash_state *md, const unsigned char *P)
175 {
176 unsigned long i;
177
178 s_blake2s_init0(md);
179
180 /* IV XOR ParamBlock */
181 for (i = 0; i < 8; ++i) {
182 ulong32 tmp;
183 LOAD32L(tmp, P + i * 4);
184 md->blake2s.h[i] ^= tmp;
185 }
186
187 md->blake2s.outlen = P[O_DIGEST_LENGTH];
188 return CRYPT_OK;
189 }
190
191 /**
192 Initialize the hash/MAC state
193
194 Use this function to init for arbitrary sizes.
195
196 Give a key and keylen to init for MAC mode.
197
198 @param md The hash state you wish to initialize
199 @param outlen The desired output-length
200 @param key The key of the MAC
201 @param keylen The length of the key
202 @return CRYPT_OK if successful
203 */
blake2s_init(hash_state * md,unsigned long outlen,const unsigned char * key,unsigned long keylen)204 int blake2s_init(hash_state *md, unsigned long outlen, const unsigned char *key, unsigned long keylen)
205 {
206 unsigned char P[BLAKE2S_PARAM_SIZE];
207 int err;
208
209 LTC_ARGCHK(md != NULL);
210
211 if ((!outlen) || (outlen > BLAKE2S_OUTBYTES)) {
212 return CRYPT_INVALID_ARG;
213 }
214 if ((key && !keylen) || (keylen && !key) || (keylen > BLAKE2S_KEYBYTES)) {
215 return CRYPT_INVALID_ARG;
216 }
217
218 XMEMSET(P, 0, sizeof(P));
219
220 P[O_DIGEST_LENGTH] = (unsigned char)outlen;
221 P[O_KEY_LENGTH] = (unsigned char)keylen;
222 P[O_FANOUT] = 1;
223 P[O_DEPTH] = 1;
224
225 err = s_blake2s_init_param(md, P);
226 if (err != CRYPT_OK) return err;
227
228 if (key) {
229 unsigned char block[BLAKE2S_BLOCKBYTES];
230
231 XMEMSET(block, 0, BLAKE2S_BLOCKBYTES);
232 XMEMCPY(block, key, keylen);
233 blake2s_process(md, block, BLAKE2S_BLOCKBYTES);
234
235 #ifdef LTC_CLEAN_STACK
236 zeromem(block, sizeof(block));
237 #endif
238 }
239 return CRYPT_OK;
240 }
241
242 /**
243 Initialize the hash state
244 @param md The hash state you wish to initialize
245 @return CRYPT_OK if successful
246 */
blake2s_128_init(hash_state * md)247 int blake2s_128_init(hash_state *md) { return blake2s_init(md, 16, NULL, 0); }
248
249 /**
250 Initialize the hash state
251 @param md The hash state you wish to initialize
252 @return CRYPT_OK if successful
253 */
blake2s_160_init(hash_state * md)254 int blake2s_160_init(hash_state *md) { return blake2s_init(md, 20, NULL, 0); }
255
256 /**
257 Initialize the hash state
258 @param md The hash state you wish to initialize
259 @return CRYPT_OK if successful
260 */
blake2s_224_init(hash_state * md)261 int blake2s_224_init(hash_state *md) { return blake2s_init(md, 28, NULL, 0); }
262
263 /**
264 Initialize the hash state
265 @param md The hash state you wish to initialize
266 @return CRYPT_OK if successful
267 */
blake2s_256_init(hash_state * md)268 int blake2s_256_init(hash_state *md) { return blake2s_init(md, 32, NULL, 0); }
269
270 #define G(r, i, a, b, c, d) \
271 do { \
272 a = a + b + m[blake2s_sigma[r][2 * i + 0]]; \
273 d = ROR(d ^ a, 16); \
274 c = c + d; \
275 b = ROR(b ^ c, 12); \
276 a = a + b + m[blake2s_sigma[r][2 * i + 1]]; \
277 d = ROR(d ^ a, 8); \
278 c = c + d; \
279 b = ROR(b ^ c, 7); \
280 } while (0)
281 #define ROUND(r) \
282 do { \
283 G(r, 0, v[0], v[4], v[8], v[12]); \
284 G(r, 1, v[1], v[5], v[9], v[13]); \
285 G(r, 2, v[2], v[6], v[10], v[14]); \
286 G(r, 3, v[3], v[7], v[11], v[15]); \
287 G(r, 4, v[0], v[5], v[10], v[15]); \
288 G(r, 5, v[1], v[6], v[11], v[12]); \
289 G(r, 6, v[2], v[7], v[8], v[13]); \
290 G(r, 7, v[3], v[4], v[9], v[14]); \
291 } while (0)
292
293 #ifdef LTC_CLEAN_STACK
ss_blake2s_compress(hash_state * md,const unsigned char * buf)294 static int ss_blake2s_compress(hash_state *md, const unsigned char *buf)
295 #else
296 static int s_blake2s_compress(hash_state *md, const unsigned char *buf)
297 #endif
298 {
299 unsigned long i;
300 ulong32 m[16];
301 ulong32 v[16];
302
303 for (i = 0; i < 16; ++i) {
304 LOAD32L(m[i], buf + i * sizeof(m[i]));
305 }
306
307 for (i = 0; i < 8; ++i) {
308 v[i] = md->blake2s.h[i];
309 }
310
311 v[8] = blake2s_IV[0];
312 v[9] = blake2s_IV[1];
313 v[10] = blake2s_IV[2];
314 v[11] = blake2s_IV[3];
315 v[12] = md->blake2s.t[0] ^ blake2s_IV[4];
316 v[13] = md->blake2s.t[1] ^ blake2s_IV[5];
317 v[14] = md->blake2s.f[0] ^ blake2s_IV[6];
318 v[15] = md->blake2s.f[1] ^ blake2s_IV[7];
319
320 ROUND(0);
321 ROUND(1);
322 ROUND(2);
323 ROUND(3);
324 ROUND(4);
325 ROUND(5);
326 ROUND(6);
327 ROUND(7);
328 ROUND(8);
329 ROUND(9);
330
331 for (i = 0; i < 8; ++i) {
332 md->blake2s.h[i] = md->blake2s.h[i] ^ v[i] ^ v[i + 8];
333 }
334 return CRYPT_OK;
335 }
336 #undef G
337 #undef ROUND
338
339 #ifdef LTC_CLEAN_STACK
s_blake2s_compress(hash_state * md,const unsigned char * buf)340 static int s_blake2s_compress(hash_state *md, const unsigned char *buf)
341 {
342 int err;
343 err = ss_blake2s_compress(md, buf);
344 burn_stack(sizeof(ulong32) * (32) + sizeof(unsigned long));
345 return err;
346 }
347 #endif
348
349 /**
350 Process a block of memory through the hash
351 @param md The hash state
352 @param in The data to hash
353 @param inlen The length of the data (octets)
354 @return CRYPT_OK if successful
355 */
blake2s_process(hash_state * md,const unsigned char * in,unsigned long inlen)356 int blake2s_process(hash_state *md, const unsigned char *in, unsigned long inlen)
357 {
358 LTC_ARGCHK(md != NULL);
359 LTC_ARGCHK(in != NULL);
360
361 if (md->blake2s.curlen > sizeof(md->blake2s.buf)) {
362 return CRYPT_INVALID_ARG;
363 }
364
365 if (inlen > 0) {
366 unsigned long left = md->blake2s.curlen;
367 unsigned long fill = BLAKE2S_BLOCKBYTES - left;
368 if (inlen > fill) {
369 md->blake2s.curlen = 0;
370 XMEMCPY(md->blake2s.buf + (left % sizeof(md->blake2s.buf)), in, fill); /* Fill buffer */
371 s_blake2s_increment_counter(md, BLAKE2S_BLOCKBYTES);
372 s_blake2s_compress(md, md->blake2s.buf); /* Compress */
373 in += fill;
374 inlen -= fill;
375 while (inlen > BLAKE2S_BLOCKBYTES) {
376 s_blake2s_increment_counter(md, BLAKE2S_BLOCKBYTES);
377 s_blake2s_compress(md, in);
378 in += BLAKE2S_BLOCKBYTES;
379 inlen -= BLAKE2S_BLOCKBYTES;
380 }
381 }
382 XMEMCPY(md->blake2s.buf + md->blake2s.curlen, in, inlen);
383 md->blake2s.curlen += inlen;
384 }
385 return CRYPT_OK;
386 }
387
388 /**
389 Terminate the hash to get the digest
390 @param md The hash state
391 @param out [out] The destination of the hash (size depending on the length used on init)
392 @return CRYPT_OK if successful
393 */
blake2s_done(hash_state * md,unsigned char * out)394 int blake2s_done(hash_state *md, unsigned char *out)
395 {
396 unsigned char buffer[BLAKE2S_OUTBYTES] = { 0 };
397 unsigned long i;
398
399 LTC_ARGCHK(md != NULL);
400 LTC_ARGCHK(out != NULL);
401
402 /* if(md->blake2s.outlen != outlen) return CRYPT_INVALID_ARG; */
403
404 if (s_blake2s_is_lastblock(md)) {
405 return CRYPT_ERROR;
406 }
407 s_blake2s_increment_counter(md, md->blake2s.curlen);
408 s_blake2s_set_lastblock(md);
409 XMEMSET(md->blake2s.buf + md->blake2s.curlen, 0, BLAKE2S_BLOCKBYTES - md->blake2s.curlen); /* Padding */
410 s_blake2s_compress(md, md->blake2s.buf);
411
412 for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */
413 STORE32L(md->blake2s.h[i], buffer + i * 4);
414 }
415
416 XMEMCPY(out, buffer, md->blake2s.outlen);
417 zeromem(md, sizeof(hash_state));
418 #ifdef LTC_CLEAN_STACK
419 zeromem(buffer, sizeof(buffer));
420 #endif
421 return CRYPT_OK;
422 }
423
424 /**
425 Self-test the hash
426 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
427 */
blake2s_256_test(void)428 int blake2s_256_test(void)
429 {
430 #ifndef LTC_TEST
431 return CRYPT_NOP;
432 #else
433 static const struct {
434 const char *msg;
435 unsigned char hash[32];
436 } tests[] = {
437 { "",
438 { 0x69, 0x21, 0x7a, 0x30, 0x79, 0x90, 0x80, 0x94,
439 0xe1, 0x11, 0x21, 0xd0, 0x42, 0x35, 0x4a, 0x7c,
440 0x1f, 0x55, 0xb6, 0x48, 0x2c, 0xa1, 0xa5, 0x1e,
441 0x1b, 0x25, 0x0d, 0xfd, 0x1e, 0xd0, 0xee, 0xf9 } },
442 { "abc",
443 { 0x50, 0x8c, 0x5e, 0x8c, 0x32, 0x7c, 0x14, 0xe2,
444 0xe1, 0xa7, 0x2b, 0xa3, 0x4e, 0xeb, 0x45, 0x2f,
445 0x37, 0x45, 0x8b, 0x20, 0x9e, 0xd6, 0x3a, 0x29,
446 0x4d, 0x99, 0x9b, 0x4c, 0x86, 0x67, 0x59, 0x82 } },
447 { "12345678901234567890123456789012345678901234567890"
448 "12345678901234567890123456789012345678901234567890"
449 "12345678901234567890123456789012345678901234567890"
450 "12345678901234567890123456789012345678901234567890"
451 "12345678901234567890123456789012345678901234567890"
452 "12345678901234567890123456789012345678901234567890",
453 { 0xa3, 0x78, 0x8b, 0x5b, 0x59, 0xee, 0xe4, 0x41,
454 0x95, 0x23, 0x58, 0x00, 0xa4, 0xf9, 0xfa, 0x41,
455 0x86, 0x0c, 0x7b, 0x1c, 0x35, 0xa2, 0x42, 0x70,
456 0x50, 0x80, 0x79, 0x56, 0xe3, 0xbe, 0x31, 0x74 } },
457
458 { NULL, { 0 } }
459 };
460
461 int i;
462 unsigned char tmp[32];
463 hash_state md;
464
465 for (i = 0; tests[i].msg != NULL; i++) {
466 blake2s_256_init(&md);
467 blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
468 blake2s_done(&md, tmp);
469 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_256", i)) {
470 return CRYPT_FAIL_TESTVECTOR;
471 }
472
473 }
474 return CRYPT_OK;
475 #endif
476 }
477
478 /**
479 Self-test the hash
480 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
481 */
blake2s_224_test(void)482 int blake2s_224_test(void)
483 {
484 #ifndef LTC_TEST
485 return CRYPT_NOP;
486 #else
487 static const struct {
488 const char *msg;
489 unsigned char hash[28];
490 } tests[] = {
491 { "",
492 { 0x1f, 0xa1, 0x29, 0x1e, 0x65, 0x24, 0x8b, 0x37,
493 0xb3, 0x43, 0x34, 0x75, 0xb2, 0xa0, 0xdd, 0x63,
494 0xd5, 0x4a, 0x11, 0xec, 0xc4, 0xe3, 0xe0, 0x34,
495 0xe7, 0xbc, 0x1e, 0xf4 } },
496 { "abc",
497 { 0x0b, 0x03, 0x3f, 0xc2, 0x26, 0xdf, 0x7a, 0xbd,
498 0xe2, 0x9f, 0x67, 0xa0, 0x5d, 0x3d, 0xc6, 0x2c,
499 0xf2, 0x71, 0xef, 0x3d, 0xfe, 0xa4, 0xd3, 0x87,
500 0x40, 0x7f, 0xbd, 0x55 } },
501
502 { NULL, { 0 } }
503 };
504
505 int i;
506 unsigned char tmp[28];
507 hash_state md;
508
509 for (i = 0; tests[i].msg != NULL; i++) {
510 blake2s_224_init(&md);
511 blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
512 blake2s_done(&md, tmp);
513 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_224", i)) {
514 return CRYPT_FAIL_TESTVECTOR;
515 }
516
517 }
518 return CRYPT_OK;
519 #endif
520 }
521
522 /**
523 Self-test the hash
524 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
525 */
blake2s_160_test(void)526 int blake2s_160_test(void)
527 {
528 #ifndef LTC_TEST
529 return CRYPT_NOP;
530 #else
531 static const struct {
532 const char *msg;
533 unsigned char hash[20];
534 } tests[] = {
535 { "",
536 { 0x35, 0x4c, 0x9c, 0x33, 0xf7, 0x35, 0x96, 0x24,
537 0x18, 0xbd, 0xac, 0xb9, 0x47, 0x98, 0x73, 0x42,
538 0x9c, 0x34, 0x91, 0x6f} },
539 { "abc",
540 { 0x5a, 0xe3, 0xb9, 0x9b, 0xe2, 0x9b, 0x01, 0x83,
541 0x4c, 0x3b, 0x50, 0x85, 0x21, 0xed, 0xe6, 0x04,
542 0x38, 0xf8, 0xde, 0x17 } },
543
544 { NULL, { 0 } }
545 };
546
547 int i;
548 unsigned char tmp[20];
549 hash_state md;
550
551 for (i = 0; tests[i].msg != NULL; i++) {
552 blake2s_160_init(&md);
553 blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
554 blake2s_done(&md, tmp);
555 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_160", i)) {
556 return CRYPT_FAIL_TESTVECTOR;
557 }
558
559 }
560 return CRYPT_OK;
561 #endif
562 }
563
564 /**
565 Self-test the hash
566 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
567 */
blake2s_128_test(void)568 int blake2s_128_test(void)
569 {
570 #ifndef LTC_TEST
571 return CRYPT_NOP;
572 #else
573 static const struct {
574 const char *msg;
575 unsigned char hash[16];
576 } tests[] = {
577 { "",
578 { 0x64, 0x55, 0x0d, 0x6f, 0xfe, 0x2c, 0x0a, 0x01,
579 0xa1, 0x4a, 0xba, 0x1e, 0xad, 0xe0, 0x20, 0x0c } },
580 { "abc",
581 { 0xaa, 0x49, 0x38, 0x11, 0x9b, 0x1d, 0xc7, 0xb8,
582 0x7c, 0xba, 0xd0, 0xff, 0xd2, 0x00, 0xd0, 0xae } },
583
584 { NULL, { 0 } }
585 };
586
587 int i;
588 unsigned char tmp[16];
589 hash_state md;
590
591 for (i = 0; tests[i].msg != NULL; i++) {
592 blake2s_128_init(&md);
593 blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
594 blake2s_done(&md, tmp);
595 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_128", i)) {
596 return CRYPT_FAIL_TESTVECTOR;
597 }
598 }
599 return CRYPT_OK;
600 #endif
601 }
602
603 #endif
604