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 blake2s_constant {
31 BLAKE2S_BLOCKBYTES = 64,
32 BLAKE2S_OUTBYTES = 32,
33 BLAKE2S_KEYBYTES = 32,
34 BLAKE2S_SALTBYTES = 8,
35 BLAKE2S_PERSONALBYTES = 8,
36 BLAKE2S_PARAM_SIZE = 32
55 struct blake2s_param {
56 unsigned char digest_length;
57 unsigned char key_length;
63 unsigned char node_depth;
64 unsigned char inner_length;
65 unsigned char salt[BLAKE2S_SALTBYTES];
66 unsigned char personal[BLAKE2S_PERSONALBYTES];
70 const struct ltc_hash_descriptor blake2s_128_desc =
76 { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 4 },
85 const struct ltc_hash_descriptor blake2s_160_desc =
91 { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 5 },
100 const struct ltc_hash_descriptor blake2s_224_desc =
106 { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 7 },
115 const struct ltc_hash_descriptor blake2s_256_desc =
121 { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 8 },
130 static const ulong32 blake2s_IV[8] = {
131 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
132 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
135 static const unsigned char blake2s_sigma[10][16] = {
136 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
137 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
138 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
139 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
140 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
141 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
142 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
143 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
144 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
145 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
148 static void blake2s_set_lastnode(hash_state *md) { md->blake2s.f[1] = 0xffffffffUL; }
150 /* Some helper functions, not necessarily useful */
151 static int blake2s_is_lastblock(const hash_state *md) { return md->blake2s.f[0] != 0; }
153 static void blake2s_set_lastblock(hash_state *md)
155 if (md->blake2s.last_node)
156 blake2s_set_lastnode(md);
158 md->blake2s.f[0] = 0xffffffffUL;
161 static void blake2s_increment_counter(hash_state *md, const ulong32 inc)
163 md->blake2s.t[0] += inc;
164 if (md->blake2s.t[0] < inc) md->blake2s.t[1]++;
167 static int blake2s_init0(hash_state *md)
170 XMEMSET(&md->blake2s, 0, sizeof(struct blake2s_state));
172 for (i = 0; i < 8; ++i)
173 md->blake2s.h[i] = blake2s_IV[i];
178 /* init2 xors IV with input parameter block */
179 static int blake2s_init_param(hash_state *md, const unsigned char *P)
185 /* IV XOR ParamBlock */
186 for (i = 0; i < 8; ++i) {
188 LOAD32L(tmp, P + i * 4);
189 md->blake2s.h[i] ^= tmp;
192 md->blake2s.outlen = P[O_DIGEST_LENGTH];
196 int blake2s_init(hash_state *md, unsigned long outlen, const unsigned char *key, unsigned long keylen)
198 unsigned char P[BLAKE2S_PARAM_SIZE];
201 LTC_ARGCHK(md != NULL);
203 if ((!outlen) || (outlen > BLAKE2S_OUTBYTES))
204 return CRYPT_INVALID_ARG;
206 if ((key && !keylen) || (keylen && !key) || (keylen > BLAKE2S_KEYBYTES))
207 return CRYPT_INVALID_ARG;
209 XMEMSET(P, 0, sizeof(P));
211 P[O_DIGEST_LENGTH] = (unsigned char)outlen;
212 P[O_KEY_LENGTH] = (unsigned char)keylen;
216 err = blake2s_init_param(md, P);
217 if (err != CRYPT_OK) return err;
220 unsigned char block[BLAKE2S_BLOCKBYTES];
222 XMEMSET(block, 0, BLAKE2S_BLOCKBYTES);
223 XMEMCPY(block, key, keylen);
224 blake2s_process(md, block, BLAKE2S_BLOCKBYTES);
226 #ifdef LTC_CLEAN_STACK
227 zeromem(block, sizeof(block));
233 int blake2s_128_init(hash_state *md) { return blake2s_init(md, 16, NULL, 0); }
235 int blake2s_160_init(hash_state *md) { return blake2s_init(md, 20, NULL, 0); }
237 int blake2s_224_init(hash_state *md) { return blake2s_init(md, 28, NULL, 0); }
239 int blake2s_256_init(hash_state *md) { return blake2s_init(md, 32, NULL, 0); }
241 #define G(r, i, a, b, c, d) \
243 a = a + b + m[blake2s_sigma[r][2 * i + 0]]; \
244 d = ROR(d ^ a, 16); \
246 b = ROR(b ^ c, 12); \
247 a = a + b + m[blake2s_sigma[r][2 * i + 1]]; \
254 G(r, 0, v[0], v[4], v[8], v[12]); \
255 G(r, 1, v[1], v[5], v[9], v[13]); \
256 G(r, 2, v[2], v[6], v[10], v[14]); \
257 G(r, 3, v[3], v[7], v[11], v[15]); \
258 G(r, 4, v[0], v[5], v[10], v[15]); \
259 G(r, 5, v[1], v[6], v[11], v[12]); \
260 G(r, 6, v[2], v[7], v[8], v[13]); \
261 G(r, 7, v[3], v[4], v[9], v[14]); \
264 #ifdef LTC_CLEAN_STACK
265 static int _blake2s_compress(hash_state *md, const unsigned char *buf)
267 static int blake2s_compress(hash_state *md, const unsigned char *buf)
274 for (i = 0; i < 16; ++i) {
275 LOAD32L(m[i], buf + i * sizeof(m[i]));
278 for (i = 0; i < 8; ++i)
279 v[i] = md->blake2s.h[i];
281 v[8] = blake2s_IV[0];
282 v[9] = blake2s_IV[1];
283 v[10] = blake2s_IV[2];
284 v[11] = blake2s_IV[3];
285 v[12] = md->blake2s.t[0] ^ blake2s_IV[4];
286 v[13] = md->blake2s.t[1] ^ blake2s_IV[5];
287 v[14] = md->blake2s.f[0] ^ blake2s_IV[6];
288 v[15] = md->blake2s.f[1] ^ blake2s_IV[7];
301 for (i = 0; i < 8; ++i)
302 md->blake2s.h[i] = md->blake2s.h[i] ^ v[i] ^ v[i + 8];
309 #ifdef LTC_CLEAN_STACK
310 static int blake2s_compress(hash_state *md, const unsigned char *buf)
313 err = _blake2s_compress(md, buf);
314 burn_stack(sizeof(ulong32) * (32) + sizeof(unsigned long));
319 int blake2s_process(hash_state *md, const unsigned char *in, unsigned long inlen)
321 LTC_ARGCHK(md != NULL);
322 LTC_ARGCHK(in != NULL);
324 if (md->blake2s.curlen > sizeof(md->blake2s.buf)) {
325 return CRYPT_INVALID_ARG;
329 unsigned long left = md->blake2s.curlen;
330 unsigned long fill = BLAKE2S_BLOCKBYTES - left;
332 md->blake2s.curlen = 0;
333 XMEMCPY(md->blake2s.buf + (left % sizeof(md->blake2s.buf)), in, fill); /* Fill buffer */
334 blake2s_increment_counter(md, BLAKE2S_BLOCKBYTES);
335 blake2s_compress(md, md->blake2s.buf); /* Compress */
338 while (inlen > BLAKE2S_BLOCKBYTES) {
339 blake2s_increment_counter(md, BLAKE2S_BLOCKBYTES);
340 blake2s_compress(md, in);
341 in += BLAKE2S_BLOCKBYTES;
342 inlen -= BLAKE2S_BLOCKBYTES;
345 XMEMCPY(md->blake2s.buf + md->blake2s.curlen, in, inlen);
346 md->blake2s.curlen += inlen;
351 int blake2s_done(hash_state *md, unsigned char *out)
353 unsigned char buffer[BLAKE2S_OUTBYTES] = { 0 };
356 LTC_ARGCHK(md != NULL);
357 LTC_ARGCHK(out != NULL);
359 /* if(md->blake2s.outlen != outlen) return CRYPT_INVALID_ARG; */
361 if (blake2s_is_lastblock(md))
364 blake2s_increment_counter(md, md->blake2s.curlen);
365 blake2s_set_lastblock(md);
366 XMEMSET(md->blake2s.buf + md->blake2s.curlen, 0, BLAKE2S_BLOCKBYTES - md->blake2s.curlen); /* Padding */
367 blake2s_compress(md, md->blake2s.buf);
369 for (i = 0; i < 8; ++i) /* Output full hash to temp buffer */
370 STORE32L(md->blake2s.h[i], buffer + i * 4);
372 XMEMCPY(out, buffer, md->blake2s.outlen);
373 zeromem(md, sizeof(hash_state));
374 #ifdef LTC_CLEAN_STACK
375 zeromem(buffer, sizeof(buffer));
382 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
384 int blake2s_256_test(void)
389 static const struct {
391 unsigned char hash[32];
394 { 0x69, 0x21, 0x7a, 0x30, 0x79, 0x90, 0x80, 0x94,
395 0xe1, 0x11, 0x21, 0xd0, 0x42, 0x35, 0x4a, 0x7c,
396 0x1f, 0x55, 0xb6, 0x48, 0x2c, 0xa1, 0xa5, 0x1e,
397 0x1b, 0x25, 0x0d, 0xfd, 0x1e, 0xd0, 0xee, 0xf9 } },
399 { 0x50, 0x8c, 0x5e, 0x8c, 0x32, 0x7c, 0x14, 0xe2,
400 0xe1, 0xa7, 0x2b, 0xa3, 0x4e, 0xeb, 0x45, 0x2f,
401 0x37, 0x45, 0x8b, 0x20, 0x9e, 0xd6, 0x3a, 0x29,
402 0x4d, 0x99, 0x9b, 0x4c, 0x86, 0x67, 0x59, 0x82 } },
403 { "12345678901234567890123456789012345678901234567890"
404 "12345678901234567890123456789012345678901234567890"
405 "12345678901234567890123456789012345678901234567890"
406 "12345678901234567890123456789012345678901234567890"
407 "12345678901234567890123456789012345678901234567890"
408 "12345678901234567890123456789012345678901234567890",
409 { 0xa3, 0x78, 0x8b, 0x5b, 0x59, 0xee, 0xe4, 0x41,
410 0x95, 0x23, 0x58, 0x00, 0xa4, 0xf9, 0xfa, 0x41,
411 0x86, 0x0c, 0x7b, 0x1c, 0x35, 0xa2, 0x42, 0x70,
412 0x50, 0x80, 0x79, 0x56, 0xe3, 0xbe, 0x31, 0x74 } },
418 unsigned char tmp[32];
421 for (i = 0; tests[i].msg != NULL; i++) {
422 blake2s_256_init(&md);
423 blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
424 blake2s_done(&md, tmp);
425 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_256", i)) {
426 return CRYPT_FAIL_TESTVECTOR;
436 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
438 int blake2s_224_test(void)
443 static const struct {
445 unsigned char hash[28];
448 { 0x1f, 0xa1, 0x29, 0x1e, 0x65, 0x24, 0x8b, 0x37,
449 0xb3, 0x43, 0x34, 0x75, 0xb2, 0xa0, 0xdd, 0x63,
450 0xd5, 0x4a, 0x11, 0xec, 0xc4, 0xe3, 0xe0, 0x34,
451 0xe7, 0xbc, 0x1e, 0xf4 } },
453 { 0x0b, 0x03, 0x3f, 0xc2, 0x26, 0xdf, 0x7a, 0xbd,
454 0xe2, 0x9f, 0x67, 0xa0, 0x5d, 0x3d, 0xc6, 0x2c,
455 0xf2, 0x71, 0xef, 0x3d, 0xfe, 0xa4, 0xd3, 0x87,
456 0x40, 0x7f, 0xbd, 0x55 } },
462 unsigned char tmp[28];
465 for (i = 0; tests[i].msg != NULL; i++) {
466 blake2s_224_init(&md);
467 blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
468 blake2s_done(&md, tmp);
469 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_224", i)) {
470 return CRYPT_FAIL_TESTVECTOR;
480 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
482 int blake2s_160_test(void)
487 static const struct {
489 unsigned char hash[20];
492 { 0x35, 0x4c, 0x9c, 0x33, 0xf7, 0x35, 0x96, 0x24,
493 0x18, 0xbd, 0xac, 0xb9, 0x47, 0x98, 0x73, 0x42,
494 0x9c, 0x34, 0x91, 0x6f} },
496 { 0x5a, 0xe3, 0xb9, 0x9b, 0xe2, 0x9b, 0x01, 0x83,
497 0x4c, 0x3b, 0x50, 0x85, 0x21, 0xed, 0xe6, 0x04,
498 0x38, 0xf8, 0xde, 0x17 } },
504 unsigned char tmp[20];
507 for (i = 0; tests[i].msg != NULL; i++) {
508 blake2s_160_init(&md);
509 blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
510 blake2s_done(&md, tmp);
511 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_160", i)) {
512 return CRYPT_FAIL_TESTVECTOR;
522 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
524 int blake2s_128_test(void)
529 static const struct {
531 unsigned char hash[16];
534 { 0x64, 0x55, 0x0d, 0x6f, 0xfe, 0x2c, 0x0a, 0x01,
535 0xa1, 0x4a, 0xba, 0x1e, 0xad, 0xe0, 0x20, 0x0c } },
537 { 0xaa, 0x49, 0x38, 0x11, 0x9b, 0x1d, 0xc7, 0xb8,
538 0x7c, 0xba, 0xd0, 0xff, 0xd2, 0x00, 0xd0, 0xae } },
544 unsigned char tmp[16];
547 for (i = 0; tests[i].msg != NULL; i++) {
548 blake2s_128_init(&md);
549 blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
550 blake2s_done(&md, tmp);
551 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_128", i)) {
552 return CRYPT_FAIL_TESTVECTOR;
561 /* ref: $Format:%D$ */
562 /* git commit: $Format:%H$ */
563 /* commit time: $Format:%ai$ */