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_BLAKE2B 30 31 enum blake2b_constant { 32 BLAKE2B_BLOCKBYTES = 128, 33 BLAKE2B_OUTBYTES = 64, 34 BLAKE2B_KEYBYTES = 64, 35 BLAKE2B_SALTBYTES = 16, 36 BLAKE2B_PERSONALBYTES = 16, 37 BLAKE2B_PARAM_SIZE = 64 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 = 16, 50 O_INNER_LENGTH = 17, 51 O_RESERVED = 18, 52 O_SALT = 32, 53 O_PERSONAL = 48 54 }; 55 56 /* 57 struct blake2b_param { 58 unsigned char digest_length; 59 unsigned char key_length; 60 unsigned char fanout; 61 unsigned char depth; 62 ulong32 leaf_length; 63 ulong32 node_offset; 64 ulong32 xof_length; 65 unsigned char node_depth; 66 unsigned char inner_length; 67 unsigned char reserved[14]; 68 unsigned char salt[BLAKE2B_SALTBYTES]; 69 unsigned char personal[BLAKE2B_PERSONALBYTES]; 70 }; 71 */ 72 73 const struct ltc_hash_descriptor blake2b_160_desc = 74 { 75 "blake2b-160", 76 25, 77 20, 78 128, 79 { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 5 }, 80 11, 81 &blake2b_160_init, 82 &blake2b_process, 83 &blake2b_done, 84 &blake2b_160_test, 85 NULL 86 }; 87 88 const struct ltc_hash_descriptor blake2b_256_desc = 89 { 90 "blake2b-256", 91 26, 92 32, 93 128, 94 { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 8 }, 95 11, 96 &blake2b_256_init, 97 &blake2b_process, 98 &blake2b_done, 99 &blake2b_256_test, 100 NULL 101 }; 102 103 const struct ltc_hash_descriptor blake2b_384_desc = 104 { 105 "blake2b-384", 106 27, 107 48, 108 128, 109 { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 12 }, 110 11, 111 &blake2b_384_init, 112 &blake2b_process, 113 &blake2b_done, 114 &blake2b_384_test, 115 NULL 116 }; 117 118 const struct ltc_hash_descriptor blake2b_512_desc = 119 { 120 "blake2b-512", 121 28, 122 64, 123 128, 124 { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 16 }, 125 11, 126 &blake2b_512_init, 127 &blake2b_process, 128 &blake2b_done, 129 &blake2b_512_test, 130 NULL 131 }; 132 133 static const ulong64 blake2b_IV[8] = 134 { 135 CONST64(0x6a09e667f3bcc908), CONST64(0xbb67ae8584caa73b), 136 CONST64(0x3c6ef372fe94f82b), CONST64(0xa54ff53a5f1d36f1), 137 CONST64(0x510e527fade682d1), CONST64(0x9b05688c2b3e6c1f), 138 CONST64(0x1f83d9abfb41bd6b), CONST64(0x5be0cd19137e2179) 139 }; 140 141 static const unsigned char blake2b_sigma[12][16] = 142 { 143 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 144 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , 145 { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , 146 { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , 147 { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , 148 { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , 149 { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , 150 { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , 151 { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , 152 { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , 153 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 154 { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } 155 }; 156 157 static void blake2b_set_lastnode(hash_state *md) { md->blake2b.f[1] = CONST64(0xffffffffffffffff); } 158 159 /* Some helper functions, not necessarily useful */ 160 static int blake2b_is_lastblock(const hash_state *md) { return md->blake2b.f[0] != 0; } 161 162 static void blake2b_set_lastblock(hash_state *md) 163 { 164 if (md->blake2b.last_node) { 165 blake2b_set_lastnode(md); 166 } 167 md->blake2b.f[0] = CONST64(0xffffffffffffffff); 168 } 169 170 static void blake2b_increment_counter(hash_state *md, ulong64 inc) 171 { 172 md->blake2b.t[0] += inc; 173 if (md->blake2b.t[0] < inc) md->blake2b.t[1]++; 174 } 175 176 static void blake2b_init0(hash_state *md) 177 { 178 unsigned long i; 179 XMEMSET(&md->blake2b, 0, sizeof(md->blake2b)); 180 181 for (i = 0; i < 8; ++i) { 182 md->blake2b.h[i] = blake2b_IV[i]; 183 } 184 } 185 186 /* init xors IV with input parameter block */ 187 static int blake2b_init_param(hash_state *md, const unsigned char *P) 188 { 189 unsigned long i; 190 191 blake2b_init0(md); 192 193 /* IV XOR ParamBlock */ 194 for (i = 0; i < 8; ++i) { 195 ulong64 tmp; 196 LOAD64L(tmp, P + i * 8); 197 md->blake2b.h[i] ^= tmp; 198 } 199 200 md->blake2b.outlen = P[O_DIGEST_LENGTH]; 201 return CRYPT_OK; 202 } 203 204 /** 205 Initialize the hash/MAC state 206 207 Use this function to init for arbitrary sizes. 208 209 Give a key and keylen to init for MAC mode. 210 211 @param md The hash state you wish to initialize 212 @param outlen The desired output-length 213 @param key The key of the MAC 214 @param keylen The length of the key 215 @return CRYPT_OK if successful 216 */ 217 int blake2b_init(hash_state *md, unsigned long outlen, const unsigned char *key, unsigned long keylen) 218 { 219 unsigned char P[BLAKE2B_PARAM_SIZE]; 220 int err; 221 222 LTC_ARGCHK(md != NULL); 223 224 if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) { 225 return CRYPT_INVALID_ARG; 226 } 227 if ((key && !keylen) || (keylen && !key) || (keylen > BLAKE2B_KEYBYTES)) { 228 return CRYPT_INVALID_ARG; 229 } 230 231 XMEMSET(P, 0, sizeof(P)); 232 233 P[O_DIGEST_LENGTH] = (unsigned char)outlen; 234 P[O_KEY_LENGTH] = (unsigned char)keylen; 235 P[O_FANOUT] = 1; 236 P[O_DEPTH] = 1; 237 238 err = blake2b_init_param(md, P); 239 if (err != CRYPT_OK) return err; 240 241 if (key) { 242 unsigned char block[BLAKE2B_BLOCKBYTES]; 243 244 XMEMSET(block, 0, BLAKE2B_BLOCKBYTES); 245 XMEMCPY(block, key, keylen); 246 blake2b_process(md, block, BLAKE2B_BLOCKBYTES); 247 248 #ifdef LTC_CLEAN_STACK 249 zeromem(block, sizeof(block)); 250 #endif 251 } 252 253 return CRYPT_OK; 254 } 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 blake2b_160_init(hash_state *md) { return blake2b_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 blake2b_256_init(hash_state *md) { return blake2b_init(md, 32, 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 blake2b_384_init(hash_state *md) { return blake2b_init(md, 48, NULL, 0); } 276 277 /** 278 Initialize the hash state 279 @param md The hash state you wish to initialize 280 @return CRYPT_OK if successful 281 */ 282 int blake2b_512_init(hash_state *md) { return blake2b_init(md, 64, NULL, 0); } 283 284 #define G(r, i, a, b, c, d) \ 285 do { \ 286 a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \ 287 d = ROR64(d ^ a, 32); \ 288 c = c + d; \ 289 b = ROR64(b ^ c, 24); \ 290 a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \ 291 d = ROR64(d ^ a, 16); \ 292 c = c + d; \ 293 b = ROR64(b ^ c, 63); \ 294 } while (0) 295 296 #define ROUND(r) \ 297 do { \ 298 G(r, 0, v[0], v[4], v[8], v[12]); \ 299 G(r, 1, v[1], v[5], v[9], v[13]); \ 300 G(r, 2, v[2], v[6], v[10], v[14]); \ 301 G(r, 3, v[3], v[7], v[11], v[15]); \ 302 G(r, 4, v[0], v[5], v[10], v[15]); \ 303 G(r, 5, v[1], v[6], v[11], v[12]); \ 304 G(r, 6, v[2], v[7], v[8], v[13]); \ 305 G(r, 7, v[3], v[4], v[9], v[14]); \ 306 } while (0) 307 308 #ifdef LTC_CLEAN_STACK 309 static int _blake2b_compress(hash_state *md, const unsigned char *buf) 310 #else 311 static int blake2b_compress(hash_state *md, const unsigned char *buf) 312 #endif 313 { 314 ulong64 m[16]; 315 ulong64 v[16]; 316 unsigned long i; 317 318 for (i = 0; i < 16; ++i) { 319 LOAD64L(m[i], buf + i * sizeof(m[i])); 320 } 321 322 for (i = 0; i < 8; ++i) { 323 v[i] = md->blake2b.h[i]; 324 } 325 326 v[8] = blake2b_IV[0]; 327 v[9] = blake2b_IV[1]; 328 v[10] = blake2b_IV[2]; 329 v[11] = blake2b_IV[3]; 330 v[12] = blake2b_IV[4] ^ md->blake2b.t[0]; 331 v[13] = blake2b_IV[5] ^ md->blake2b.t[1]; 332 v[14] = blake2b_IV[6] ^ md->blake2b.f[0]; 333 v[15] = blake2b_IV[7] ^ md->blake2b.f[1]; 334 335 ROUND(0); 336 ROUND(1); 337 ROUND(2); 338 ROUND(3); 339 ROUND(4); 340 ROUND(5); 341 ROUND(6); 342 ROUND(7); 343 ROUND(8); 344 ROUND(9); 345 ROUND(10); 346 ROUND(11); 347 348 for (i = 0; i < 8; ++i) { 349 md->blake2b.h[i] = md->blake2b.h[i] ^ v[i] ^ v[i + 8]; 350 } 351 return CRYPT_OK; 352 } 353 354 #undef G 355 #undef ROUND 356 357 #ifdef LTC_CLEAN_STACK 358 static int blake2b_compress(hash_state *md, const unsigned char *buf) 359 { 360 int err; 361 err = _blake2b_compress(md, buf); 362 burn_stack(sizeof(ulong64) * 32 + sizeof(unsigned long)); 363 return err; 364 } 365 #endif 366 367 /** 368 Process a block of memory through the hash 369 @param md The hash state 370 @param in The data to hash 371 @param inlen The length of the data (octets) 372 @return CRYPT_OK if successful 373 */ 374 int blake2b_process(hash_state *md, const unsigned char *in, unsigned long inlen) 375 { 376 LTC_ARGCHK(md != NULL); 377 LTC_ARGCHK(in != NULL); 378 379 if (md->blake2b.curlen > sizeof(md->blake2b.buf)) { 380 return CRYPT_INVALID_ARG; 381 } 382 383 if (inlen > 0) { 384 unsigned long left = md->blake2b.curlen; 385 unsigned long fill = BLAKE2B_BLOCKBYTES - left; 386 if (inlen > fill) { 387 md->blake2b.curlen = 0; 388 XMEMCPY(md->blake2b.buf + (left % sizeof(md->blake2b.buf)), in, fill); /* Fill buffer */ 389 blake2b_increment_counter(md, BLAKE2B_BLOCKBYTES); 390 blake2b_compress(md, md->blake2b.buf); /* Compress */ 391 in += fill; 392 inlen -= fill; 393 while (inlen > BLAKE2B_BLOCKBYTES) { 394 blake2b_increment_counter(md, BLAKE2B_BLOCKBYTES); 395 blake2b_compress(md, in); 396 in += BLAKE2B_BLOCKBYTES; 397 inlen -= BLAKE2B_BLOCKBYTES; 398 } 399 } 400 XMEMCPY(md->blake2b.buf + md->blake2b.curlen, in, inlen); 401 md->blake2b.curlen += inlen; 402 } 403 return CRYPT_OK; 404 } 405 406 /** 407 Terminate the hash to get the digest 408 @param md The hash state 409 @param out [out] The destination of the hash (size depending on the length used on init) 410 @return CRYPT_OK if successful 411 */ 412 int blake2b_done(hash_state *md, unsigned char *out) 413 { 414 unsigned char buffer[BLAKE2B_OUTBYTES] = { 0 }; 415 unsigned long i; 416 417 LTC_ARGCHK(md != NULL); 418 LTC_ARGCHK(out != NULL); 419 420 /* if(md->blakebs.outlen != outlen) return CRYPT_INVALID_ARG; */ 421 422 if (blake2b_is_lastblock(md)) { 423 return CRYPT_ERROR; 424 } 425 426 blake2b_increment_counter(md, md->blake2b.curlen); 427 blake2b_set_lastblock(md); 428 XMEMSET(md->blake2b.buf + md->blake2b.curlen, 0, BLAKE2B_BLOCKBYTES - md->blake2b.curlen); /* Padding */ 429 blake2b_compress(md, md->blake2b.buf); 430 431 for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */ 432 STORE64L(md->blake2b.h[i], buffer + i * 8); 433 } 434 435 XMEMCPY(out, buffer, md->blake2b.outlen); 436 zeromem(md, sizeof(hash_state)); 437 #ifdef LTC_CLEAN_STACK 438 zeromem(buffer, sizeof(buffer)); 439 #endif 440 return CRYPT_OK; 441 } 442 443 /** 444 Self-test the hash 445 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled 446 */ 447 int blake2b_512_test(void) 448 { 449 #ifndef LTC_TEST 450 return CRYPT_NOP; 451 #else 452 static const struct { 453 const char *msg; 454 unsigned char hash[64]; 455 } tests[] = { 456 { "", 457 { 0x78, 0x6a, 0x02, 0xf7, 0x42, 0x01, 0x59, 0x03, 458 0xc6, 0xc6, 0xfd, 0x85, 0x25, 0x52, 0xd2, 0x72, 459 0x91, 0x2f, 0x47, 0x40, 0xe1, 0x58, 0x47, 0x61, 460 0x8a, 0x86, 0xe2, 0x17, 0xf7, 0x1f, 0x54, 0x19, 461 0xd2, 0x5e, 0x10, 0x31, 0xaf, 0xee, 0x58, 0x53, 462 0x13, 0x89, 0x64, 0x44, 0x93, 0x4e, 0xb0, 0x4b, 463 0x90, 0x3a, 0x68, 0x5b, 0x14, 0x48, 0xb7, 0x55, 464 0xd5, 0x6f, 0x70, 0x1a, 0xfe, 0x9b, 0xe2, 0xce } }, 465 { "abc", 466 { 0xba, 0x80, 0xa5, 0x3f, 0x98, 0x1c, 0x4d, 0x0d, 467 0x6a, 0x27, 0x97, 0xb6, 0x9f, 0x12, 0xf6, 0xe9, 468 0x4c, 0x21, 0x2f, 0x14, 0x68, 0x5a, 0xc4, 0xb7, 469 0x4b, 0x12, 0xbb, 0x6f, 0xdb, 0xff, 0xa2, 0xd1, 470 0x7d, 0x87, 0xc5, 0x39, 0x2a, 0xab, 0x79, 0x2d, 471 0xc2, 0x52, 0xd5, 0xde, 0x45, 0x33, 0xcc, 0x95, 472 0x18, 0xd3, 0x8a, 0xa8, 0xdb, 0xf1, 0x92, 0x5a, 473 0xb9, 0x23, 0x86, 0xed, 0xd4, 0x00, 0x99, 0x23 } }, 474 475 { NULL, { 0 } } 476 }; 477 478 int i; 479 unsigned char tmp[64]; 480 hash_state md; 481 482 for (i = 0; tests[i].msg != NULL; i++) { 483 blake2b_512_init(&md); 484 blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg)); 485 blake2b_done(&md, tmp); 486 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_512", i)) { 487 return CRYPT_FAIL_TESTVECTOR; 488 } 489 } 490 return CRYPT_OK; 491 #endif 492 } 493 494 /** 495 Self-test the hash 496 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled 497 */ 498 int blake2b_384_test(void) 499 { 500 #ifndef LTC_TEST 501 return CRYPT_NOP; 502 #else 503 static const struct { 504 const char *msg; 505 unsigned char hash[48]; 506 } tests[] = { 507 { "", 508 { 0xb3, 0x28, 0x11, 0x42, 0x33, 0x77, 0xf5, 0x2d, 509 0x78, 0x62, 0x28, 0x6e, 0xe1, 0xa7, 0x2e, 0xe5, 510 0x40, 0x52, 0x43, 0x80, 0xfd, 0xa1, 0x72, 0x4a, 511 0x6f, 0x25, 0xd7, 0x97, 0x8c, 0x6f, 0xd3, 0x24, 512 0x4a, 0x6c, 0xaf, 0x04, 0x98, 0x81, 0x26, 0x73, 513 0xc5, 0xe0, 0x5e, 0xf5, 0x83, 0x82, 0x51, 0x00 } }, 514 { "abc", 515 { 0x6f, 0x56, 0xa8, 0x2c, 0x8e, 0x7e, 0xf5, 0x26, 516 0xdf, 0xe1, 0x82, 0xeb, 0x52, 0x12, 0xf7, 0xdb, 517 0x9d, 0xf1, 0x31, 0x7e, 0x57, 0x81, 0x5d, 0xbd, 518 0xa4, 0x60, 0x83, 0xfc, 0x30, 0xf5, 0x4e, 0xe6, 519 0xc6, 0x6b, 0xa8, 0x3b, 0xe6, 0x4b, 0x30, 0x2d, 520 0x7c, 0xba, 0x6c, 0xe1, 0x5b, 0xb5, 0x56, 0xf4 } }, 521 522 { NULL, { 0 } } 523 }; 524 525 int i; 526 unsigned char tmp[48]; 527 hash_state md; 528 529 for (i = 0; tests[i].msg != NULL; i++) { 530 blake2b_384_init(&md); 531 blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg)); 532 blake2b_done(&md, tmp); 533 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_384", i)) { 534 return CRYPT_FAIL_TESTVECTOR; 535 } 536 } 537 return CRYPT_OK; 538 #endif 539 } 540 541 /** 542 Self-test the hash 543 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled 544 */ 545 int blake2b_256_test(void) 546 { 547 #ifndef LTC_TEST 548 return CRYPT_NOP; 549 #else 550 static const struct { 551 const char *msg; 552 unsigned char hash[32]; 553 } tests[] = { 554 { "", 555 { 0x0e, 0x57, 0x51, 0xc0, 0x26, 0xe5, 0x43, 0xb2, 556 0xe8, 0xab, 0x2e, 0xb0, 0x60, 0x99, 0xda, 0xa1, 557 0xd1, 0xe5, 0xdf, 0x47, 0x77, 0x8f, 0x77, 0x87, 558 0xfa, 0xab, 0x45, 0xcd, 0xf1, 0x2f, 0xe3, 0xa8 } }, 559 { "abc", 560 { 0xbd, 0xdd, 0x81, 0x3c, 0x63, 0x42, 0x39, 0x72, 561 0x31, 0x71, 0xef, 0x3f, 0xee, 0x98, 0x57, 0x9b, 562 0x94, 0x96, 0x4e, 0x3b, 0xb1, 0xcb, 0x3e, 0x42, 563 0x72, 0x62, 0xc8, 0xc0, 0x68, 0xd5, 0x23, 0x19 } }, 564 { "12345678901234567890123456789012345678901234567890" 565 "12345678901234567890123456789012345678901234567890" 566 "12345678901234567890123456789012345678901234567890" 567 "12345678901234567890123456789012345678901234567890" 568 "12345678901234567890123456789012345678901234567890" 569 "12345678901234567890123456789012345678901234567890", 570 { 0x0f, 0x6e, 0x01, 0x8d, 0x38, 0xd6, 0x3f, 0x08, 571 0x4d, 0x58, 0xe3, 0x0c, 0x90, 0xfb, 0xa2, 0x41, 572 0x5f, 0xca, 0x17, 0xfa, 0x66, 0x26, 0x49, 0xf3, 573 0x8a, 0x30, 0x41, 0x7c, 0x57, 0xcd, 0xa8, 0x14 } }, 574 575 { NULL, { 0 } } 576 }; 577 578 int i; 579 unsigned char tmp[32]; 580 hash_state md; 581 582 for (i = 0; tests[i].msg != NULL; i++) { 583 blake2b_256_init(&md); 584 blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg)); 585 blake2b_done(&md, tmp); 586 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_256", i)) { 587 return CRYPT_FAIL_TESTVECTOR; 588 } 589 } 590 return CRYPT_OK; 591 #endif 592 } 593 594 /** 595 Self-test the hash 596 @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled 597 */ 598 int blake2b_160_test(void) 599 { 600 #ifndef LTC_TEST 601 return CRYPT_NOP; 602 #else 603 static const struct { 604 const char *msg; 605 unsigned char hash[20]; 606 } tests[] = { 607 { "", 608 { 0x33, 0x45, 0x52, 0x4a, 0xbf, 0x6b, 0xbe, 0x18, 609 0x09, 0x44, 0x92, 0x24, 0xb5, 0x97, 0x2c, 0x41, 610 0x79, 0x0b, 0x6c, 0xf2 } }, 611 { "abc", 612 { 0x38, 0x42, 0x64, 0xf6, 0x76, 0xf3, 0x95, 0x36, 613 0x84, 0x05, 0x23, 0xf2, 0x84, 0x92, 0x1c, 0xdc, 614 0x68, 0xb6, 0x84, 0x6b } }, 615 616 { NULL, { 0 } } 617 }; 618 619 int i; 620 unsigned char tmp[20]; 621 hash_state md; 622 623 for (i = 0; tests[i].msg != NULL; i++) { 624 blake2b_160_init(&md); 625 blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg)); 626 blake2b_done(&md, tmp); 627 if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_160", i)) { 628 return CRYPT_FAIL_TESTVECTOR; 629 } 630 } 631 return CRYPT_OK; 632 #endif 633 } 634 635 #endif 636 637 /* ref: $Format:%D$ */ 638 /* git commit: $Format:%H$ */ 639 /* commit time: $Format:%ai$ */ 640