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