1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
6 * The library is free for all purposes without any express
11 BLAKE2 reference source code package - reference C implementations
13 Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
14 terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
15 your option. The terms of these licenses can be found at:
17 - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
18 - OpenSSL license : https://www.openssl.org/source/license.html
19 - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
21 More information about the BLAKE2 hash function can be found at
24 /* see also https://www.ietf.org/rfc/rfc7693.txt */
30 enum blake2b_constant {
31 BLAKE2B_BLOCKBYTES = 128,
32 BLAKE2B_OUTBYTES = 64,
33 BLAKE2B_KEYBYTES = 64,
34 BLAKE2B_SALTBYTES = 16,
35 BLAKE2B_PERSONALBYTES = 16,
36 BLAKE2B_PARAM_SIZE = 64
56 struct blake2b_param {
57 unsigned char digest_length;
58 unsigned char key_length;
64 unsigned char node_depth;
65 unsigned char inner_length;
66 unsigned char reserved[14];
67 unsigned char salt[BLAKE2B_SALTBYTES];
68 unsigned char personal[BLAKE2B_PERSONALBYTES];
72 const struct ltc_hash_descriptor blake2b_160_desc =
78 { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 5 },
87 const struct ltc_hash_descriptor blake2b_256_desc =
93 { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 8 },
102 const struct ltc_hash_descriptor blake2b_384_desc =
108 { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 12 },
117 const struct ltc_hash_descriptor blake2b_512_desc =
123 { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 16 },
132 static const ulong64 blake2b_IV[8] =
134 CONST64(0x6a09e667f3bcc908), CONST64(0xbb67ae8584caa73b),
135 CONST64(0x3c6ef372fe94f82b), CONST64(0xa54ff53a5f1d36f1),
136 CONST64(0x510e527fade682d1), CONST64(0x9b05688c2b3e6c1f),
137 CONST64(0x1f83d9abfb41bd6b), CONST64(0x5be0cd19137e2179)
140 static const unsigned char blake2b_sigma[12][16] =
142 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
143 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
144 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
145 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
146 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
147 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
148 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
149 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
150 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
151 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
152 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
153 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
156 static void blake2b_set_lastnode(hash_state *md) { md->blake2b.f[1] = CONST64(0xffffffffffffffff); }
158 /* Some helper functions, not necessarily useful */
159 static int blake2b_is_lastblock(const hash_state *md) { return md->blake2b.f[0] != 0; }
161 static void blake2b_set_lastblock(hash_state *md)
163 if (md->blake2b.last_node)
164 blake2b_set_lastnode(md);
166 md->blake2b.f[0] = CONST64(0xffffffffffffffff);
169 static void blake2b_increment_counter(hash_state *md, ulong64 inc)
171 md->blake2b.t[0] += inc;
172 if (md->blake2b.t[0] < inc) md->blake2b.t[1]++;
175 static void blake2b_init0(hash_state *md)
178 XMEMSET(&md->blake2b, 0, sizeof(md->blake2b));
180 for (i = 0; i < 8; ++i)
181 md->blake2b.h[i] = blake2b_IV[i];
184 /* init xors IV with input parameter block */
185 static int blake2b_init_param(hash_state *md, const unsigned char *P)
191 /* IV XOR ParamBlock */
192 for (i = 0; i < 8; ++i) {
194 LOAD64L(tmp, P + i * 8);
195 md->blake2b.h[i] ^= tmp;
198 md->blake2b.outlen = P[O_DIGEST_LENGTH];
202 int blake2b_init(hash_state *md, unsigned long outlen, const unsigned char *key, unsigned long keylen)
204 unsigned char P[BLAKE2B_PARAM_SIZE];
207 LTC_ARGCHK(md != NULL);
209 if ((!outlen) || (outlen > BLAKE2B_OUTBYTES))
210 return CRYPT_INVALID_ARG;
212 if ((key && !keylen) || (keylen && !key) || (keylen > BLAKE2B_KEYBYTES))
213 return CRYPT_INVALID_ARG;
215 XMEMSET(P, 0, sizeof(P));
217 P[O_DIGEST_LENGTH] = (unsigned char)outlen;
218 P[O_KEY_LENGTH] = (unsigned char)keylen;
222 err = blake2b_init_param(md, P);
223 if (err != CRYPT_OK) return err;
226 unsigned char block[BLAKE2B_BLOCKBYTES];
228 XMEMSET(block, 0, BLAKE2B_BLOCKBYTES);
229 XMEMCPY(block, key, keylen);
230 blake2b_process(md, block, BLAKE2B_BLOCKBYTES);
232 #ifdef LTC_CLEAN_STACK
233 zeromem(block, sizeof(block));
240 int blake2b_160_init(hash_state *md) { return blake2b_init(md, 20, NULL, 0); }
242 int blake2b_256_init(hash_state *md) { return blake2b_init(md, 32, NULL, 0); }
244 int blake2b_384_init(hash_state *md) { return blake2b_init(md, 48, NULL, 0); }
246 int blake2b_512_init(hash_state *md) { return blake2b_init(md, 64, NULL, 0); }
248 #define G(r, i, a, b, c, d) \
250 a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \
251 d = ROR64(d ^ a, 32); \
253 b = ROR64(b ^ c, 24); \
254 a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \
255 d = ROR64(d ^ a, 16); \
257 b = ROR64(b ^ c, 63); \
262 G(r, 0, v[0], v[4], v[8], v[12]); \
263 G(r, 1, v[1], v[5], v[9], v[13]); \
264 G(r, 2, v[2], v[6], v[10], v[14]); \
265 G(r, 3, v[3], v[7], v[11], v[15]); \
266 G(r, 4, v[0], v[5], v[10], v[15]); \
267 G(r, 5, v[1], v[6], v[11], v[12]); \
268 G(r, 6, v[2], v[7], v[8], v[13]); \
269 G(r, 7, v[3], v[4], v[9], v[14]); \
272 #ifdef LTC_CLEAN_STACK
273 static int _blake2b_compress(hash_state *md, const unsigned char *buf)
275 static int blake2b_compress(hash_state *md, const unsigned char *buf)
282 for (i = 0; i < 16; ++i) {
283 LOAD64L(m[i], buf + i * sizeof(m[i]));
286 for (i = 0; i < 8; ++i) {
287 v[i] = md->blake2b.h[i];
290 v[8] = blake2b_IV[0];
291 v[9] = blake2b_IV[1];
292 v[10] = blake2b_IV[2];
293 v[11] = blake2b_IV[3];
294 v[12] = blake2b_IV[4] ^ md->blake2b.t[0];
295 v[13] = blake2b_IV[5] ^ md->blake2b.t[1];
296 v[14] = blake2b_IV[6] ^ md->blake2b.f[0];
297 v[15] = blake2b_IV[7] ^ md->blake2b.f[1];
312 for (i = 0; i < 8; ++i) {
313 md->blake2b.h[i] = md->blake2b.h[i] ^ v[i] ^ v[i + 8];
321 #ifdef LTC_CLEAN_STACK
322 static int blake2b_compress(hash_state *md, const unsigned char *buf)
325 err = _blake2b_compress(md, buf);
326 burn_stack(sizeof(ulong64) * 32 + sizeof(unsigned long));
331 int blake2b_process(hash_state *md, const unsigned char *in, unsigned long inlen)
333 LTC_ARGCHK(md != NULL);
334 LTC_ARGCHK(in != NULL);
336 if (md->blake2b.curlen > sizeof(md->blake2b.buf)) {
337 return CRYPT_INVALID_ARG;
341 unsigned long left = md->blake2b.curlen;
342 unsigned long fill = BLAKE2B_BLOCKBYTES - left;
344 md->blake2b.curlen = 0;
345 XMEMCPY(md->blake2b.buf + (left % sizeof(md->blake2b.buf)), in, fill); /* Fill buffer */
346 blake2b_increment_counter(md, BLAKE2B_BLOCKBYTES);
347 blake2b_compress(md, md->blake2b.buf); /* Compress */
350 while (inlen > BLAKE2B_BLOCKBYTES) {
351 blake2b_increment_counter(md, BLAKE2B_BLOCKBYTES);
352 blake2b_compress(md, in);
353 in += BLAKE2B_BLOCKBYTES;
354 inlen -= BLAKE2B_BLOCKBYTES;
357 XMEMCPY(md->blake2b.buf + md->blake2b.curlen, in, inlen);
358 md->blake2b.curlen += inlen;
363 int blake2b_done(hash_state *md, unsigned char *out)
365 unsigned char buffer[BLAKE2B_OUTBYTES] = { 0 };
368 LTC_ARGCHK(md != NULL);
369 LTC_ARGCHK(out != NULL);
371 /* if(md->blakebs.outlen != outlen) return CRYPT_INVALID_ARG; */
373 if (blake2b_is_lastblock(md))
376 blake2b_increment_counter(md, md->blake2b.curlen);
377 blake2b_set_lastblock(md);
378 XMEMSET(md->blake2b.buf + md->blake2b.curlen, 0, BLAKE2B_BLOCKBYTES - md->blake2b.curlen); /* Padding */
379 blake2b_compress(md, md->blake2b.buf);
381 for (i = 0; i < 8; ++i) /* Output full hash to temp buffer */
382 STORE64L(md->blake2b.h[i], buffer + i * 8);
384 XMEMCPY(out, buffer, md->blake2b.outlen);
385 zeromem(md, sizeof(hash_state));
386 #ifdef LTC_CLEAN_STACK
387 zeromem(buffer, sizeof(buffer));
394 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
396 int blake2b_512_test(void)
401 static const struct {
403 unsigned char hash[64];
406 { 0x78, 0x6a, 0x02, 0xf7, 0x42, 0x01, 0x59, 0x03,
407 0xc6, 0xc6, 0xfd, 0x85, 0x25, 0x52, 0xd2, 0x72,
408 0x91, 0x2f, 0x47, 0x40, 0xe1, 0x58, 0x47, 0x61,
409 0x8a, 0x86, 0xe2, 0x17, 0xf7, 0x1f, 0x54, 0x19,
410 0xd2, 0x5e, 0x10, 0x31, 0xaf, 0xee, 0x58, 0x53,
411 0x13, 0x89, 0x64, 0x44, 0x93, 0x4e, 0xb0, 0x4b,
412 0x90, 0x3a, 0x68, 0x5b, 0x14, 0x48, 0xb7, 0x55,
413 0xd5, 0x6f, 0x70, 0x1a, 0xfe, 0x9b, 0xe2, 0xce } },
415 { 0xba, 0x80, 0xa5, 0x3f, 0x98, 0x1c, 0x4d, 0x0d,
416 0x6a, 0x27, 0x97, 0xb6, 0x9f, 0x12, 0xf6, 0xe9,
417 0x4c, 0x21, 0x2f, 0x14, 0x68, 0x5a, 0xc4, 0xb7,
418 0x4b, 0x12, 0xbb, 0x6f, 0xdb, 0xff, 0xa2, 0xd1,
419 0x7d, 0x87, 0xc5, 0x39, 0x2a, 0xab, 0x79, 0x2d,
420 0xc2, 0x52, 0xd5, 0xde, 0x45, 0x33, 0xcc, 0x95,
421 0x18, 0xd3, 0x8a, 0xa8, 0xdb, 0xf1, 0x92, 0x5a,
422 0xb9, 0x23, 0x86, 0xed, 0xd4, 0x00, 0x99, 0x23 } },
428 unsigned char tmp[64];
431 for (i = 0; tests[i].msg != NULL; i++) {
432 blake2b_512_init(&md);
433 blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
434 blake2b_done(&md, tmp);
435 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_512", i)) {
436 return CRYPT_FAIL_TESTVECTOR;
445 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
447 int blake2b_384_test(void)
452 static const struct {
454 unsigned char hash[48];
457 { 0xb3, 0x28, 0x11, 0x42, 0x33, 0x77, 0xf5, 0x2d,
458 0x78, 0x62, 0x28, 0x6e, 0xe1, 0xa7, 0x2e, 0xe5,
459 0x40, 0x52, 0x43, 0x80, 0xfd, 0xa1, 0x72, 0x4a,
460 0x6f, 0x25, 0xd7, 0x97, 0x8c, 0x6f, 0xd3, 0x24,
461 0x4a, 0x6c, 0xaf, 0x04, 0x98, 0x81, 0x26, 0x73,
462 0xc5, 0xe0, 0x5e, 0xf5, 0x83, 0x82, 0x51, 0x00 } },
464 { 0x6f, 0x56, 0xa8, 0x2c, 0x8e, 0x7e, 0xf5, 0x26,
465 0xdf, 0xe1, 0x82, 0xeb, 0x52, 0x12, 0xf7, 0xdb,
466 0x9d, 0xf1, 0x31, 0x7e, 0x57, 0x81, 0x5d, 0xbd,
467 0xa4, 0x60, 0x83, 0xfc, 0x30, 0xf5, 0x4e, 0xe6,
468 0xc6, 0x6b, 0xa8, 0x3b, 0xe6, 0x4b, 0x30, 0x2d,
469 0x7c, 0xba, 0x6c, 0xe1, 0x5b, 0xb5, 0x56, 0xf4 } },
475 unsigned char tmp[48];
478 for (i = 0; tests[i].msg != NULL; i++) {
479 blake2b_384_init(&md);
480 blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
481 blake2b_done(&md, tmp);
482 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_384", i)) {
483 return CRYPT_FAIL_TESTVECTOR;
492 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
494 int blake2b_256_test(void)
499 static const struct {
501 unsigned char hash[32];
504 { 0x0e, 0x57, 0x51, 0xc0, 0x26, 0xe5, 0x43, 0xb2,
505 0xe8, 0xab, 0x2e, 0xb0, 0x60, 0x99, 0xda, 0xa1,
506 0xd1, 0xe5, 0xdf, 0x47, 0x77, 0x8f, 0x77, 0x87,
507 0xfa, 0xab, 0x45, 0xcd, 0xf1, 0x2f, 0xe3, 0xa8 } },
509 { 0xbd, 0xdd, 0x81, 0x3c, 0x63, 0x42, 0x39, 0x72,
510 0x31, 0x71, 0xef, 0x3f, 0xee, 0x98, 0x57, 0x9b,
511 0x94, 0x96, 0x4e, 0x3b, 0xb1, 0xcb, 0x3e, 0x42,
512 0x72, 0x62, 0xc8, 0xc0, 0x68, 0xd5, 0x23, 0x19 } },
513 { "12345678901234567890123456789012345678901234567890"
514 "12345678901234567890123456789012345678901234567890"
515 "12345678901234567890123456789012345678901234567890"
516 "12345678901234567890123456789012345678901234567890"
517 "12345678901234567890123456789012345678901234567890"
518 "12345678901234567890123456789012345678901234567890",
519 { 0x0f, 0x6e, 0x01, 0x8d, 0x38, 0xd6, 0x3f, 0x08,
520 0x4d, 0x58, 0xe3, 0x0c, 0x90, 0xfb, 0xa2, 0x41,
521 0x5f, 0xca, 0x17, 0xfa, 0x66, 0x26, 0x49, 0xf3,
522 0x8a, 0x30, 0x41, 0x7c, 0x57, 0xcd, 0xa8, 0x14 } },
528 unsigned char tmp[32];
531 for (i = 0; tests[i].msg != NULL; i++) {
532 blake2b_256_init(&md);
533 blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
534 blake2b_done(&md, tmp);
535 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_256", i)) {
536 return CRYPT_FAIL_TESTVECTOR;
545 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
547 int blake2b_160_test(void)
552 static const struct {
554 unsigned char hash[20];
557 { 0x33, 0x45, 0x52, 0x4a, 0xbf, 0x6b, 0xbe, 0x18,
558 0x09, 0x44, 0x92, 0x24, 0xb5, 0x97, 0x2c, 0x41,
559 0x79, 0x0b, 0x6c, 0xf2 } },
561 { 0x38, 0x42, 0x64, 0xf6, 0x76, 0xf3, 0x95, 0x36,
562 0x84, 0x05, 0x23, 0xf2, 0x84, 0x92, 0x1c, 0xdc,
563 0x68, 0xb6, 0x84, 0x6b } },
569 unsigned char tmp[20];
572 for (i = 0; tests[i].msg != NULL; i++) {
573 blake2b_160_init(&md);
574 blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
575 blake2b_done(&md, tmp);
576 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_160", i)) {
577 return CRYPT_FAIL_TESTVECTOR;
586 /* ref: $Format:%D$ */
587 /* git commit: $Format:%H$ */
588 /* commit time: $Format:%ai$ */