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