1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846
|
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Evgeny Grin (Karlson2k), <k2k@narod.ru>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if !defined(CURL_DISABLE_DIGEST_AUTH) && !defined(CURL_DISABLE_SHA512_256)
#include "curl_sha512_256.h"
#include "curlx/warnless.h"
/* The recommended order of the TLS backends:
* * OpenSSL
* * GnuTLS
* * wolfSSL
* * Schannel SSPI
* * Secure Transport (Darwin)
* * mbedTLS
* * BearSSL
* * Rustls
* Skip the backend if it does not support the required algorithm */
#if defined(USE_OPENSSL)
# include <openssl/opensslv.h>
# if (!defined(LIBRESSL_VERSION_NUMBER) && \
defined(OPENSSL_VERSION_NUMBER) && \
(OPENSSL_VERSION_NUMBER >= 0x10101000L)) || \
(defined(LIBRESSL_VERSION_NUMBER) && \
(LIBRESSL_VERSION_NUMBER >= 0x3080000fL))
# include <openssl/opensslconf.h>
# if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA512)
# include <openssl/evp.h>
# define USE_OPENSSL_SHA512_256 1
# define HAS_SHA512_256_IMPLEMENTATION 1
# ifdef __NetBSD__
/* Some NetBSD versions has a bug in SHA-512/256.
* See https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=58039
* The problematic versions:
* - NetBSD before 9.4
* - NetBSD 9 all development versions (9.99.x)
* - NetBSD 10 development versions (10.99.x) before 10.99.11
* The bug was fixed in NetBSD 9.4 release, NetBSD 10.0 release,
* NetBSD 10.99.11 development.
* It is safe to apply the workaround even if the bug is not present, as
* the workaround just reduces performance slightly. */
# include <sys/param.h>
# if __NetBSD_Version__ < 904000000 || \
(__NetBSD_Version__ >= 999000000 && \
__NetBSD_Version__ < 1000000000) || \
(__NetBSD_Version__ >= 1099000000 && \
__NetBSD_Version__ < 1099001100)
# define NEED_NETBSD_SHA512_256_WORKAROUND 1
# include <string.h>
# endif
# endif
# endif
# endif
#endif /* USE_OPENSSL */
#if !defined(HAS_SHA512_256_IMPLEMENTATION) && defined(USE_GNUTLS)
# include <nettle/sha.h>
# if defined(SHA512_256_DIGEST_SIZE)
# define USE_GNUTLS_SHA512_256 1
# endif
#endif /* ! HAS_SHA512_256_IMPLEMENTATION && USE_GNUTLS */
#if defined(USE_OPENSSL_SHA512_256)
/* OpenSSL does not provide macros for SHA-512/256 sizes */
/**
* Size of the SHA-512/256 single processing block in bytes.
*/
#define CURL_SHA512_256_BLOCK_SIZE 128
/**
* Size of the SHA-512/256 resulting digest in bytes.
* This is the final digest size, not intermediate hash.
*/
#define CURL_SHA512_256_DIGEST_SIZE CURL_SHA512_256_DIGEST_LENGTH
/**
* Context type used for SHA-512/256 calculations
*/
typedef EVP_MD_CTX *Curl_sha512_256_ctx;
/**
* Initialise structure for SHA-512/256 calculation.
*
* @param context the calculation context
* @return CURLE_OK if succeed,
* error code otherwise
*/
static CURLcode
Curl_sha512_256_init(void *context)
{
Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
*ctx = EVP_MD_CTX_create();
if(!*ctx)
return CURLE_OUT_OF_MEMORY;
if(EVP_DigestInit_ex(*ctx, EVP_sha512_256(), NULL)) {
/* Check whether the header and this file use the same numbers */
DEBUGASSERT(EVP_MD_CTX_size(*ctx) == CURL_SHA512_256_DIGEST_SIZE);
/* Check whether the block size is correct */
DEBUGASSERT(EVP_MD_CTX_block_size(*ctx) == CURL_SHA512_256_BLOCK_SIZE);
return CURLE_OK; /* Success */
}
/* Cleanup */
EVP_MD_CTX_destroy(*ctx);
return CURLE_FAILED_INIT;
}
/**
* Process portion of bytes.
*
* @param context the calculation context
* @param data bytes to add to hash
* @return CURLE_OK if succeed,
* error code otherwise
*/
static CURLcode
Curl_sha512_256_update(void *context,
const unsigned char *data,
size_t length)
{
Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
if(!EVP_DigestUpdate(*ctx, data, length))
return CURLE_SSL_CIPHER;
return CURLE_OK;
}
/**
* Finalise SHA-512/256 calculation, return digest.
*
* @param context the calculation context
* @param[out] digest set to the hash, must be #CURL_SHA512_256_DIGEST_SIZE
# bytes
* @return CURLE_OK if succeed,
* error code otherwise
*/
static CURLcode
Curl_sha512_256_finish(unsigned char *digest,
void *context)
{
CURLcode ret;
Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
#ifdef NEED_NETBSD_SHA512_256_WORKAROUND
/* Use a larger buffer to work around a bug in NetBSD:
https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=58039 */
unsigned char tmp_digest[CURL_SHA512_256_DIGEST_SIZE * 2];
ret = EVP_DigestFinal_ex(*ctx,
tmp_digest, NULL) ? CURLE_OK : CURLE_SSL_CIPHER;
if(ret == CURLE_OK)
memcpy(digest, tmp_digest, CURL_SHA512_256_DIGEST_SIZE);
explicit_memset(tmp_digest, 0, sizeof(tmp_digest));
#else /* ! NEED_NETBSD_SHA512_256_WORKAROUND */
ret = EVP_DigestFinal_ex(*ctx, digest, NULL) ? CURLE_OK : CURLE_SSL_CIPHER;
#endif /* ! NEED_NETBSD_SHA512_256_WORKAROUND */
EVP_MD_CTX_destroy(*ctx);
*ctx = NULL;
return ret;
}
#elif defined(USE_GNUTLS_SHA512_256)
#define CURL_SHA512_256_BLOCK_SIZE SHA512_256_BLOCK_SIZE
#define CURL_SHA512_256_DIGEST_SIZE SHA512_256_DIGEST_SIZE
/**
* Context type used for SHA-512/256 calculations
*/
typedef struct sha512_256_ctx Curl_sha512_256_ctx;
/**
* Initialise structure for SHA-512/256 calculation.
*
* @param context the calculation context
* @return always CURLE_OK
*/
static CURLcode
Curl_sha512_256_init(void *context)
{
Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
/* Check whether the header and this file use the same numbers */
DEBUGASSERT(CURL_SHA512_256_DIGEST_LENGTH == CURL_SHA512_256_DIGEST_SIZE);
sha512_256_init(ctx);
return CURLE_OK;
}
/**
* Process portion of bytes.
*
* @param context the calculation context
* @param data bytes to add to hash
* @param length number of bytes in @a data
* @return always CURLE_OK
*/
static CURLcode
Curl_sha512_256_update(void *context,
const unsigned char *data,
size_t length)
{
Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
DEBUGASSERT((data != NULL) || (length == 0));
sha512_256_update(ctx, length, (const uint8_t *)data);
return CURLE_OK;
}
/**
* Finalise SHA-512/256 calculation, return digest.
*
* @param context the calculation context
* @param[out] digest set to the hash, must be #CURL_SHA512_256_DIGEST_SIZE
# bytes
* @return always CURLE_OK
*/
static CURLcode
Curl_sha512_256_finish(unsigned char *digest,
void *context)
{
Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context;
sha512_256_digest(ctx,
(size_t)CURL_SHA512_256_DIGEST_SIZE, (uint8_t *)digest);
return CURLE_OK;
}
#else /* No system or TLS backend SHA-512/256 implementation available */
/* ** This implementation of SHA-512/256 hash calculation was originally ** *
* ** written by Evgeny Grin (Karlson2k) for GNU libmicrohttpd. ** *
* ** The author ported the code to libcurl. The ported code is provided ** *
* ** under curl license. ** *
* ** This is a minimal version with minimal optimizations. Performance ** *
* ** can be significantly improved. Big-endian store and load macros ** *
* ** are obvious targets for optimization. ** */
#ifdef __GNUC__
# if defined(__has_attribute) && defined(__STDC_VERSION__)
# if __has_attribute(always_inline) && __STDC_VERSION__ >= 199901
# define CURL_FORCEINLINE CURL_INLINE __attribute__((always_inline))
# endif
# endif
#endif
#if !defined(CURL_FORCEINLINE) && \
defined(_MSC_VER) && !defined(__GNUC__) && !defined(__clang__)
# define CURL_FORCEINLINE __forceinline
#endif
#if !defined(CURL_FORCEINLINE)
/* Assume that 'CURL_INLINE' keyword works or the
* macro was already defined correctly. */
# define CURL_FORCEINLINE CURL_INLINE
#endif
/* Bits manipulation macros and functions.
Can be moved to other headers to reuse. */
#define CURL_GET_64BIT_BE(ptr) \
( ((curl_uint64_t)(((const unsigned char*)(ptr))[0]) << 56) | \
((curl_uint64_t)(((const unsigned char*)(ptr))[1]) << 48) | \
((curl_uint64_t)(((const unsigned char*)(ptr))[2]) << 40) | \
((curl_uint64_t)(((const unsigned char*)(ptr))[3]) << 32) | \
((curl_uint64_t)(((const unsigned char*)(ptr))[4]) << 24) | \
((curl_uint64_t)(((const unsigned char*)(ptr))[5]) << 16) | \
((curl_uint64_t)(((const unsigned char*)(ptr))[6]) << 8) | \
(curl_uint64_t)(((const unsigned char*)(ptr))[7]) )
#define CURL_PUT_64BIT_BE(ptr,val) do { \
((unsigned char*)(ptr))[7]=(unsigned char)((curl_uint64_t)(val)); \
((unsigned char*)(ptr))[6]=(unsigned char)(((curl_uint64_t)(val)) >> 8); \
((unsigned char*)(ptr))[5]=(unsigned char)(((curl_uint64_t)(val)) >> 16); \
((unsigned char*)(ptr))[4]=(unsigned char)(((curl_uint64_t)(val)) >> 24); \
((unsigned char*)(ptr))[3]=(unsigned char)(((curl_uint64_t)(val)) >> 32); \
((unsigned char*)(ptr))[2]=(unsigned char)(((curl_uint64_t)(val)) >> 40); \
((unsigned char*)(ptr))[1]=(unsigned char)(((curl_uint64_t)(val)) >> 48); \
((unsigned char*)(ptr))[0]=(unsigned char)(((curl_uint64_t)(val)) >> 56); \
} while(0)
/* Defined as a function. The macro version may duplicate the binary code
* size as each argument is used twice, so if any calculation is used
* as an argument, the calculation could be done twice. */
static CURL_FORCEINLINE curl_uint64_t
Curl_rotr64(curl_uint64_t value, unsigned int bits)
{
bits %= 64;
if(0 == bits)
return value;
/* Defined in a form which modern compiler could optimize. */
return (value >> bits) | (value << (64 - bits));
}
/* SHA-512/256 specific data */
/**
* Number of bits in a single SHA-512/256 word.
*/
#define SHA512_256_WORD_SIZE_BITS 64
/**
* Number of bytes in a single SHA-512/256 word.
*/
#define SHA512_256_BYTES_IN_WORD (SHA512_256_WORD_SIZE_BITS / 8)
/**
* Hash is kept internally as 8 64-bit words.
* This is the intermediate hash size, used during computing the final digest.
*/
#define SHA512_256_HASH_SIZE_WORDS 8
/**
* Size of the SHA-512/256 resulting digest in words.
* This is the final digest size, not intermediate hash.
*/
#define SHA512_256_DIGEST_SIZE_WORDS (SHA512_256_HASH_SIZE_WORDS / 2)
/**
* Size of the SHA-512/256 resulting digest in bytes
* This is the final digest size, not intermediate hash.
*/
#define CURL_SHA512_256_DIGEST_SIZE \
(SHA512_256_DIGEST_SIZE_WORDS * SHA512_256_BYTES_IN_WORD)
/**
* Size of the SHA-512/256 single processing block in bits.
*/
#define SHA512_256_BLOCK_SIZE_BITS 1024
/**
* Size of the SHA-512/256 single processing block in bytes.
*/
#define CURL_SHA512_256_BLOCK_SIZE (SHA512_256_BLOCK_SIZE_BITS / 8)
/**
* Size of the SHA-512/256 single processing block in words.
*/
#define SHA512_256_BLOCK_SIZE_WORDS \
(SHA512_256_BLOCK_SIZE_BITS / SHA512_256_WORD_SIZE_BITS)
/**
* SHA-512/256 calculation context
*/
struct Curl_sha512_256ctx
{
/**
* Intermediate hash value. The variable is properly aligned. Smart
* compilers may automatically use fast load/store instruction for big
* endian data on little endian machine.
*/
curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS];
/**
* SHA-512/256 input data buffer. The buffer is properly aligned. Smart
* compilers may automatically use fast load/store instruction for big
* endian data on little endian machine.
*/
curl_uint64_t buffer[SHA512_256_BLOCK_SIZE_WORDS];
/**
* The number of bytes, lower part
*/
curl_uint64_t count;
/**
* The number of bits, high part. Unlike lower part, this counts the number
* of bits, not bytes.
*/
curl_uint64_t count_bits_hi;
};
/**
* Context type used for SHA-512/256 calculations
*/
typedef struct Curl_sha512_256ctx Curl_sha512_256_ctx;
/**
* Initialise structure for SHA-512/256 calculation.
*
* @param context the calculation context
* @return always CURLE_OK
*/
static CURLcode
Curl_sha512_256_init(void *context)
{
struct Curl_sha512_256ctx *const ctx = (struct Curl_sha512_256ctx *)context;
/* Check whether the header and this file use the same numbers */
DEBUGASSERT(CURL_SHA512_256_DIGEST_LENGTH == CURL_SHA512_256_DIGEST_SIZE);
DEBUGASSERT(sizeof(curl_uint64_t) == 8);
/* Initial hash values, see FIPS PUB 180-4 section 5.3.6.2 */
/* Values generated by "IV Generation Function" as described in
* section 5.3.6 */
ctx->H[0] = CURL_UINT64_C(0x22312194FC2BF72C);
ctx->H[1] = CURL_UINT64_C(0x9F555FA3C84C64C2);
ctx->H[2] = CURL_UINT64_C(0x2393B86B6F53B151);
ctx->H[3] = CURL_UINT64_C(0x963877195940EABD);
ctx->H[4] = CURL_UINT64_C(0x96283EE2A88EFFE3);
ctx->H[5] = CURL_UINT64_C(0xBE5E1E2553863992);
ctx->H[6] = CURL_UINT64_C(0x2B0199FC2C85B8AA);
ctx->H[7] = CURL_UINT64_C(0x0EB72DDC81C52CA2);
/* Initialise number of bytes and high part of number of bits. */
ctx->count = CURL_UINT64_C(0);
ctx->count_bits_hi = CURL_UINT64_C(0);
return CURLE_OK;
}
/**
* Base of the SHA-512/256 transformation.
* Gets a full 128 bytes block of data and updates hash values;
* @param H hash values
* @param data the data buffer with #CURL_SHA512_256_BLOCK_SIZE bytes block
*/
static void
Curl_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS],
const void *data)
{
/* Working variables,
see FIPS PUB 180-4 section 6.7, 6.4. */
curl_uint64_t a = H[0];
curl_uint64_t b = H[1];
curl_uint64_t c = H[2];
curl_uint64_t d = H[3];
curl_uint64_t e = H[4];
curl_uint64_t f = H[5];
curl_uint64_t g = H[6];
curl_uint64_t h = H[7];
/* Data buffer, used as a cyclic buffer.
See FIPS PUB 180-4 section 5.2.2, 6.7, 6.4. */
curl_uint64_t W[16];
/* 'Ch' and 'Maj' macro functions are defined with widely-used optimization.
See FIPS PUB 180-4 formulae 4.8, 4.9. */
#define Sha512_Ch(x,y,z) ( (z) ^ ((x) & ((y) ^ (z))) )
#define Sha512_Maj(x,y,z) ( ((x) & (y)) ^ ((z) & ((x) ^ (y))) )
/* Four 'Sigma' macro functions.
See FIPS PUB 180-4 formulae 4.10, 4.11, 4.12, 4.13. */
#define SIG0(x) \
( Curl_rotr64((x), 28) ^ Curl_rotr64((x), 34) ^ Curl_rotr64((x), 39) )
#define SIG1(x) \
( Curl_rotr64((x), 14) ^ Curl_rotr64((x), 18) ^ Curl_rotr64((x), 41) )
#define sig0(x) \
( Curl_rotr64((x), 1) ^ Curl_rotr64((x), 8) ^ ((x) >> 7) )
#define sig1(x) \
( Curl_rotr64((x), 19) ^ Curl_rotr64((x), 61) ^ ((x) >> 6) )
if(1) {
unsigned int t;
/* K constants array.
See FIPS PUB 180-4 section 4.2.3 for K values. */
static const curl_uint64_t K[80] = {
CURL_UINT64_C(0x428a2f98d728ae22), CURL_UINT64_C(0x7137449123ef65cd),
CURL_UINT64_C(0xb5c0fbcfec4d3b2f), CURL_UINT64_C(0xe9b5dba58189dbbc),
CURL_UINT64_C(0x3956c25bf348b538), CURL_UINT64_C(0x59f111f1b605d019),
CURL_UINT64_C(0x923f82a4af194f9b), CURL_UINT64_C(0xab1c5ed5da6d8118),
CURL_UINT64_C(0xd807aa98a3030242), CURL_UINT64_C(0x12835b0145706fbe),
CURL_UINT64_C(0x243185be4ee4b28c), CURL_UINT64_C(0x550c7dc3d5ffb4e2),
CURL_UINT64_C(0x72be5d74f27b896f), CURL_UINT64_C(0x80deb1fe3b1696b1),
CURL_UINT64_C(0x9bdc06a725c71235), CURL_UINT64_C(0xc19bf174cf692694),
CURL_UINT64_C(0xe49b69c19ef14ad2), CURL_UINT64_C(0xefbe4786384f25e3),
CURL_UINT64_C(0x0fc19dc68b8cd5b5), CURL_UINT64_C(0x240ca1cc77ac9c65),
CURL_UINT64_C(0x2de92c6f592b0275), CURL_UINT64_C(0x4a7484aa6ea6e483),
CURL_UINT64_C(0x5cb0a9dcbd41fbd4), CURL_UINT64_C(0x76f988da831153b5),
CURL_UINT64_C(0x983e5152ee66dfab), CURL_UINT64_C(0xa831c66d2db43210),
CURL_UINT64_C(0xb00327c898fb213f), CURL_UINT64_C(0xbf597fc7beef0ee4),
CURL_UINT64_C(0xc6e00bf33da88fc2), CURL_UINT64_C(0xd5a79147930aa725),
CURL_UINT64_C(0x06ca6351e003826f), CURL_UINT64_C(0x142929670a0e6e70),
CURL_UINT64_C(0x27b70a8546d22ffc), CURL_UINT64_C(0x2e1b21385c26c926),
CURL_UINT64_C(0x4d2c6dfc5ac42aed), CURL_UINT64_C(0x53380d139d95b3df),
CURL_UINT64_C(0x650a73548baf63de), CURL_UINT64_C(0x766a0abb3c77b2a8),
CURL_UINT64_C(0x81c2c92e47edaee6), CURL_UINT64_C(0x92722c851482353b),
CURL_UINT64_C(0xa2bfe8a14cf10364), CURL_UINT64_C(0xa81a664bbc423001),
CURL_UINT64_C(0xc24b8b70d0f89791), CURL_UINT64_C(0xc76c51a30654be30),
CURL_UINT64_C(0xd192e819d6ef5218), CURL_UINT64_C(0xd69906245565a910),
CURL_UINT64_C(0xf40e35855771202a), CURL_UINT64_C(0x106aa07032bbd1b8),
CURL_UINT64_C(0x19a4c116b8d2d0c8), CURL_UINT64_C(0x1e376c085141ab53),
CURL_UINT64_C(0x2748774cdf8eeb99), CURL_UINT64_C(0x34b0bcb5e19b48a8),
CURL_UINT64_C(0x391c0cb3c5c95a63), CURL_UINT64_C(0x4ed8aa4ae3418acb),
CURL_UINT64_C(0x5b9cca4f7763e373), CURL_UINT64_C(0x682e6ff3d6b2b8a3),
CURL_UINT64_C(0x748f82ee5defb2fc), CURL_UINT64_C(0x78a5636f43172f60),
CURL_UINT64_C(0x84c87814a1f0ab72), CURL_UINT64_C(0x8cc702081a6439ec),
CURL_UINT64_C(0x90befffa23631e28), CURL_UINT64_C(0xa4506cebde82bde9),
CURL_UINT64_C(0xbef9a3f7b2c67915), CURL_UINT64_C(0xc67178f2e372532b),
CURL_UINT64_C(0xca273eceea26619c), CURL_UINT64_C(0xd186b8c721c0c207),
CURL_UINT64_C(0xeada7dd6cde0eb1e), CURL_UINT64_C(0xf57d4f7fee6ed178),
CURL_UINT64_C(0x06f067aa72176fba), CURL_UINT64_C(0x0a637dc5a2c898a6),
CURL_UINT64_C(0x113f9804bef90dae), CURL_UINT64_C(0x1b710b35131c471b),
CURL_UINT64_C(0x28db77f523047d84), CURL_UINT64_C(0x32caab7b40c72493),
CURL_UINT64_C(0x3c9ebe0a15c9bebc), CURL_UINT64_C(0x431d67c49c100d4c),
CURL_UINT64_C(0x4cc5d4becb3e42b6), CURL_UINT64_C(0x597f299cfc657e2a),
CURL_UINT64_C(0x5fcb6fab3ad6faec), CURL_UINT64_C(0x6c44198c4a475817)
};
/* One step of SHA-512/256 computation,
see FIPS PUB 180-4 section 6.4.2 step 3.
* Note: this macro updates working variables in-place, without rotation.
* Note: the first (vH += SIG1(vE) + Ch(vE,vF,vG) + kt + wt) equals T1 in
FIPS PUB 180-4 section 6.4.2 step 3.
the second (vH += SIG0(vA) + Maj(vE,vF,vC) equals T1 + T2 in
FIPS PUB 180-4 section 6.4.2 step 3.
* Note: 'wt' must be used exactly one time in this macro as macro for
'wt' calculation may change other data as well every time when
used. */
#define SHA2STEP64(vA,vB,vC,vD,vE,vF,vG,vH,kt,wt) do { \
(vD) += ((vH) += SIG1((vE)) + Sha512_Ch((vE),(vF),(vG)) + (kt) + (wt)); \
(vH) += SIG0((vA)) + Sha512_Maj((vA),(vB),(vC)); } while (0)
/* One step of SHA-512/256 computation with working variables rotation,
see FIPS PUB 180-4 section 6.4.2 step 3. This macro version reassigns
all working variables on each step. */
#define SHA2STEP64RV(vA,vB,vC,vD,vE,vF,vG,vH,kt,wt) do { \
curl_uint64_t tmp_h_ = (vH); \
SHA2STEP64((vA),(vB),(vC),(vD),(vE),(vF),(vG),tmp_h_,(kt),(wt)); \
(vH) = (vG); \
(vG) = (vF); \
(vF) = (vE); \
(vE) = (vD); \
(vD) = (vC); \
(vC) = (vB); \
(vB) = (vA); \
(vA) = tmp_h_; } while(0)
/* Get value of W(t) from input data buffer for 0 <= t <= 15,
See FIPS PUB 180-4 section 6.2.
Input data must be read in big-endian bytes order,
see FIPS PUB 180-4 section 3.1.2. */
#define SHA512_GET_W_FROM_DATA(buf,t) \
CURL_GET_64BIT_BE( \
((const unsigned char*) (buf)) + (t) * SHA512_256_BYTES_IN_WORD)
/* During first 16 steps, before making any calculation on each step, the
W element is read from the input data buffer as a big-endian value and
stored in the array of W elements. */
for(t = 0; t < 16; ++t) {
SHA2STEP64RV(a, b, c, d, e, f, g, h, K[t], \
W[t] = SHA512_GET_W_FROM_DATA(data, t));
}
/* 'W' generation and assignment for 16 <= t <= 79.
See FIPS PUB 180-4 section 6.4.2.
As only the last 16 'W' are used in calculations, it is possible to
use 16 elements array of W as a cyclic buffer.
Note: ((t-16) & 15) have same value as (t & 15) */
#define Wgen(w,t) \
(curl_uint64_t)( (w)[(t - 16) & 15] + sig1((w)[((t) - 2) & 15]) \
+ (w)[((t) - 7) & 15] + sig0((w)[((t) - 15) & 15]) )
/* During the last 64 steps, before making any calculation on each step,
current W element is generated from other W elements of the cyclic
buffer and the generated value is stored back in the cyclic buffer. */
for(t = 16; t < 80; ++t) {
SHA2STEP64RV(a, b, c, d, e, f, g, h, K[t], \
W[t & 15] = Wgen(W, t));
}
}
/* Compute and store the intermediate hash.
See FIPS PUB 180-4 section 6.4.2 step 4. */
H[0] += a;
H[1] += b;
H[2] += c;
H[3] += d;
H[4] += e;
H[5] += f;
H[6] += g;
H[7] += h;
}
/**
* Process portion of bytes.
*
* @param context the calculation context
* @param data bytes to add to hash
* @param length number of bytes in @a data
* @return always CURLE_OK
*/
static CURLcode
Curl_sha512_256_update(void *context,
const unsigned char *data,
size_t length)
{
unsigned int bytes_have; /**< Number of bytes in the context buffer */
struct Curl_sha512_256ctx *const ctx = (struct Curl_sha512_256ctx *)context;
/* the void pointer here is required to mute Intel compiler warning */
void *const ctx_buf = ctx->buffer;
DEBUGASSERT((data != NULL) || (length == 0));
if(0 == length)
return CURLE_OK; /* Shortcut, do nothing */
/* Note: (count & (CURL_SHA512_256_BLOCK_SIZE-1))
equals (count % CURL_SHA512_256_BLOCK_SIZE) for this block size. */
bytes_have = (unsigned int) (ctx->count & (CURL_SHA512_256_BLOCK_SIZE - 1));
ctx->count += length;
if(length > ctx->count)
ctx->count_bits_hi += 1U << 3; /* Value wrap */
ctx->count_bits_hi += ctx->count >> 61;
ctx->count &= CURL_UINT64_C(0x1FFFFFFFFFFFFFFF);
if(0 != bytes_have) {
unsigned int bytes_left = CURL_SHA512_256_BLOCK_SIZE - bytes_have;
if(length >= bytes_left) {
/* Combine new data with data in the buffer and process the full
block. */
memcpy(((unsigned char *) ctx_buf) + bytes_have,
data,
bytes_left);
data += bytes_left;
length -= bytes_left;
Curl_sha512_256_transform(ctx->H, ctx->buffer);
bytes_have = 0;
}
}
while(CURL_SHA512_256_BLOCK_SIZE <= length) {
/* Process any full blocks of new data directly,
without copying to the buffer. */
Curl_sha512_256_transform(ctx->H, data);
data += CURL_SHA512_256_BLOCK_SIZE;
length -= CURL_SHA512_256_BLOCK_SIZE;
}
if(0 != length) {
/* Copy incomplete block of new data (if any)
to the buffer. */
memcpy(((unsigned char *) ctx_buf) + bytes_have, data, length);
}
return CURLE_OK;
}
/**
* Size of "length" insertion in bits.
* See FIPS PUB 180-4 section 5.1.2.
*/
#define SHA512_256_SIZE_OF_LEN_ADD_BITS 128
/**
* Size of "length" insertion in bytes.
*/
#define SHA512_256_SIZE_OF_LEN_ADD (SHA512_256_SIZE_OF_LEN_ADD_BITS / 8)
/**
* Finalise SHA-512/256 calculation, return digest.
*
* @param context the calculation context
* @param[out] digest set to the hash, must be #CURL_SHA512_256_DIGEST_SIZE
# bytes
* @return always CURLE_OK
*/
static CURLcode
Curl_sha512_256_finish(unsigned char *digest,
void *context)
{
struct Curl_sha512_256ctx *const ctx = (struct Curl_sha512_256ctx *)context;
curl_uint64_t num_bits; /**< Number of processed bits */
unsigned int bytes_have; /**< Number of bytes in the context buffer */
/* the void pointer here is required to mute Intel compiler warning */
void *const ctx_buf = ctx->buffer;
/* Memorise the number of processed bits.
The padding and other data added here during the postprocessing must
not change the amount of hashed data. */
num_bits = ctx->count << 3;
/* Note: (count & (CURL_SHA512_256_BLOCK_SIZE-1))
equals (count % CURL_SHA512_256_BLOCK_SIZE) for this block size. */
bytes_have = (unsigned int) (ctx->count & (CURL_SHA512_256_BLOCK_SIZE - 1));
/* Input data must be padded with a single bit "1", then with zeros and
the finally the length of data in bits must be added as the final bytes
of the last block.
See FIPS PUB 180-4 section 5.1.2. */
/* Data is always processed in form of bytes (not by individual bits),
therefore position of the first padding bit in byte is always
predefined (0x80). */
/* Buffer always have space at least for one byte (as full buffers are
processed when formed). */
((unsigned char *) ctx_buf)[bytes_have++] = 0x80U;
if(CURL_SHA512_256_BLOCK_SIZE - bytes_have < SHA512_256_SIZE_OF_LEN_ADD) {
/* No space in the current block to put the total length of message.
Pad the current block with zeros and process it. */
if(bytes_have < CURL_SHA512_256_BLOCK_SIZE)
memset(((unsigned char *) ctx_buf) + bytes_have, 0,
CURL_SHA512_256_BLOCK_SIZE - bytes_have);
/* Process the full block. */
Curl_sha512_256_transform(ctx->H, ctx->buffer);
/* Start the new block. */
bytes_have = 0;
}
/* Pad the rest of the buffer with zeros. */
memset(((unsigned char *) ctx_buf) + bytes_have, 0,
CURL_SHA512_256_BLOCK_SIZE - SHA512_256_SIZE_OF_LEN_ADD - bytes_have);
/* Put high part of number of bits in processed message and then lower
part of number of bits as big-endian values.
See FIPS PUB 180-4 section 5.1.2. */
/* Note: the target location is predefined and buffer is always aligned */
CURL_PUT_64BIT_BE(((unsigned char *) ctx_buf) \
+ CURL_SHA512_256_BLOCK_SIZE \
- SHA512_256_SIZE_OF_LEN_ADD, \
ctx->count_bits_hi);
CURL_PUT_64BIT_BE(((unsigned char *) ctx_buf) \
+ CURL_SHA512_256_BLOCK_SIZE \
- SHA512_256_SIZE_OF_LEN_ADD \
+ SHA512_256_BYTES_IN_WORD, \
num_bits);
/* Process the full final block. */
Curl_sha512_256_transform(ctx->H, ctx->buffer);
/* Put in BE mode the leftmost part of the hash as the final digest.
See FIPS PUB 180-4 section 6.7. */
CURL_PUT_64BIT_BE((digest + 0 * SHA512_256_BYTES_IN_WORD), ctx->H[0]);
CURL_PUT_64BIT_BE((digest + 1 * SHA512_256_BYTES_IN_WORD), ctx->H[1]);
CURL_PUT_64BIT_BE((digest + 2 * SHA512_256_BYTES_IN_WORD), ctx->H[2]);
CURL_PUT_64BIT_BE((digest + 3 * SHA512_256_BYTES_IN_WORD), ctx->H[3]);
/* Erase potentially sensitive data. */
memset(ctx, 0, sizeof(struct Curl_sha512_256ctx));
return CURLE_OK;
}
#endif /* Local SHA-512/256 code */
/**
* Compute SHA-512/256 hash for the given data in one function call
* @param[out] output the pointer to put the hash
* @param[in] input the pointer to the data to process
* @param input_size the size of the data pointed by @a input
* @return always #CURLE_OK
*/
CURLcode
Curl_sha512_256it(unsigned char *output, const unsigned char *input,
size_t input_size)
{
Curl_sha512_256_ctx ctx;
CURLcode res;
res = Curl_sha512_256_init(&ctx);
if(res != CURLE_OK)
return res;
res = Curl_sha512_256_update(&ctx, (const void *) input, input_size);
if(res != CURLE_OK) {
(void) Curl_sha512_256_finish(output, &ctx);
return res;
}
return Curl_sha512_256_finish(output, &ctx);
}
/* Wrapper function, takes 'unsigned int' as length type, returns void */
static void
Curl_sha512_256_update_i(void *context,
const unsigned char *data,
unsigned int length)
{
/* Hypothetically the function may fail, but assume it does not */
(void) Curl_sha512_256_update(context, data, length);
}
/* Wrapper function, returns void */
static void
Curl_sha512_256_finish_v(unsigned char *result,
void *context)
{
/* Hypothetically the function may fail, but assume it does not */
(void) Curl_sha512_256_finish(result, context);
}
/* Wrapper function, takes 'unsigned int' as length type, returns void */
const struct HMAC_params Curl_HMAC_SHA512_256[] = {
{
/* Initialize context procedure. */
Curl_sha512_256_init,
/* Update context with data. */
Curl_sha512_256_update_i,
/* Get final result procedure. */
Curl_sha512_256_finish_v,
/* Context structure size. */
sizeof(Curl_sha512_256_ctx),
/* Maximum key length (bytes). */
CURL_SHA512_256_BLOCK_SIZE,
/* Result length (bytes). */
CURL_SHA512_256_DIGEST_SIZE
}
};
#endif /* !CURL_DISABLE_DIGEST_AUTH && !CURL_DISABLE_SHA512_256 */
|