17b5038d7SDag-Erling Smørgrav /* 27b5038d7SDag-Erling Smørgrav * FILE: sha2.c 37b5038d7SDag-Erling Smørgrav * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ 47b5038d7SDag-Erling Smørgrav * 57b5038d7SDag-Erling Smørgrav * Copyright (c) 2000-2001, Aaron D. Gifford 67b5038d7SDag-Erling Smørgrav * All rights reserved. 77b5038d7SDag-Erling Smørgrav * 87b5038d7SDag-Erling Smørgrav * Modified by Jelte Jansen to fit in ldns, and not clash with any 97b5038d7SDag-Erling Smørgrav * system-defined SHA code. 107b5038d7SDag-Erling Smørgrav * Changes: 117b5038d7SDag-Erling Smørgrav * - Renamed (external) functions and constants to fit ldns style 127b5038d7SDag-Erling Smørgrav * - Removed _End and _Data functions 137b5038d7SDag-Erling Smørgrav * - Added ldns_shaX(data, len, digest) convenience functions 147b5038d7SDag-Erling Smørgrav * - Removed prototypes of _Transform functions and made those static 157b5038d7SDag-Erling Smørgrav * 167b5038d7SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 177b5038d7SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 187b5038d7SDag-Erling Smørgrav * are met: 197b5038d7SDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 207b5038d7SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer. 217b5038d7SDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 227b5038d7SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 237b5038d7SDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 247b5038d7SDag-Erling Smørgrav * 3. Neither the name of the copyright holder nor the names of contributors 257b5038d7SDag-Erling Smørgrav * may be used to endorse or promote products derived from this software 267b5038d7SDag-Erling Smørgrav * without specific prior written permission. 277b5038d7SDag-Erling Smørgrav * 287b5038d7SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND 297b5038d7SDag-Erling Smørgrav * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 307b5038d7SDag-Erling Smørgrav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 317b5038d7SDag-Erling Smørgrav * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE 327b5038d7SDag-Erling Smørgrav * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 337b5038d7SDag-Erling Smørgrav * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 347b5038d7SDag-Erling Smørgrav * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 357b5038d7SDag-Erling Smørgrav * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 367b5038d7SDag-Erling Smørgrav * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 377b5038d7SDag-Erling Smørgrav * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 387b5038d7SDag-Erling Smørgrav * SUCH DAMAGE. 397b5038d7SDag-Erling Smørgrav * 407b5038d7SDag-Erling Smørgrav * $Id: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $ 417b5038d7SDag-Erling Smørgrav */ 427b5038d7SDag-Erling Smørgrav 437b5038d7SDag-Erling Smørgrav #include <ldns/config.h> 447b5038d7SDag-Erling Smørgrav #include <string.h> /* memcpy()/memset() or bcopy()/bzero() */ 457b5038d7SDag-Erling Smørgrav #include <assert.h> /* assert() */ 467b5038d7SDag-Erling Smørgrav #include <ldns/sha2.h> 477b5038d7SDag-Erling Smørgrav 487b5038d7SDag-Erling Smørgrav /* 497b5038d7SDag-Erling Smørgrav * ASSERT NOTE: 507b5038d7SDag-Erling Smørgrav * Some sanity checking code is included using assert(). On my FreeBSD 517b5038d7SDag-Erling Smørgrav * system, this additional code can be removed by compiling with NDEBUG 527b5038d7SDag-Erling Smørgrav * defined. Check your own systems manpage on assert() to see how to 537b5038d7SDag-Erling Smørgrav * compile WITHOUT the sanity checking code on your system. 547b5038d7SDag-Erling Smørgrav * 557b5038d7SDag-Erling Smørgrav * UNROLLED TRANSFORM LOOP NOTE: 567b5038d7SDag-Erling Smørgrav * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform 577b5038d7SDag-Erling Smørgrav * loop version for the hash transform rounds (defined using macros 587b5038d7SDag-Erling Smørgrav * later in this file). Either define on the command line, for example: 597b5038d7SDag-Erling Smørgrav * 607b5038d7SDag-Erling Smørgrav * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c 617b5038d7SDag-Erling Smørgrav * 627b5038d7SDag-Erling Smørgrav * or define below: 637b5038d7SDag-Erling Smørgrav * 647b5038d7SDag-Erling Smørgrav * #define SHA2_UNROLL_TRANSFORM 657b5038d7SDag-Erling Smørgrav * 667b5038d7SDag-Erling Smørgrav */ 677b5038d7SDag-Erling Smørgrav 687b5038d7SDag-Erling Smørgrav 697b5038d7SDag-Erling Smørgrav /*** SHA-256/384/512 Machine Architecture Definitions *****************/ 707b5038d7SDag-Erling Smørgrav /* 717b5038d7SDag-Erling Smørgrav * BYTE_ORDER NOTE: 727b5038d7SDag-Erling Smørgrav * 737b5038d7SDag-Erling Smørgrav * Please make sure that your system defines BYTE_ORDER. If your 747b5038d7SDag-Erling Smørgrav * architecture is little-endian, make sure it also defines 757b5038d7SDag-Erling Smørgrav * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are 767b5038d7SDag-Erling Smørgrav * equivilent. 777b5038d7SDag-Erling Smørgrav * 787b5038d7SDag-Erling Smørgrav * If your system does not define the above, then you can do so by 797b5038d7SDag-Erling Smørgrav * hand like this: 807b5038d7SDag-Erling Smørgrav * 817b5038d7SDag-Erling Smørgrav * #define LITTLE_ENDIAN 1234 827b5038d7SDag-Erling Smørgrav * #define BIG_ENDIAN 4321 837b5038d7SDag-Erling Smørgrav * 847b5038d7SDag-Erling Smørgrav * And for little-endian machines, add: 857b5038d7SDag-Erling Smørgrav * 867b5038d7SDag-Erling Smørgrav * #define BYTE_ORDER LITTLE_ENDIAN 877b5038d7SDag-Erling Smørgrav * 887b5038d7SDag-Erling Smørgrav * Or for big-endian machines: 897b5038d7SDag-Erling Smørgrav * 907b5038d7SDag-Erling Smørgrav * #define BYTE_ORDER BIG_ENDIAN 917b5038d7SDag-Erling Smørgrav * 927b5038d7SDag-Erling Smørgrav * The FreeBSD machine this was written on defines BYTE_ORDER 937b5038d7SDag-Erling Smørgrav * appropriately by including <sys/types.h> (which in turn includes 947b5038d7SDag-Erling Smørgrav * <machine/endian.h> where the appropriate definitions are actually 957b5038d7SDag-Erling Smørgrav * made). 967b5038d7SDag-Erling Smørgrav */ 977b5038d7SDag-Erling Smørgrav #if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) 987b5038d7SDag-Erling Smørgrav #error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN 997b5038d7SDag-Erling Smørgrav #endif 1007b5038d7SDag-Erling Smørgrav 1017b5038d7SDag-Erling Smørgrav typedef uint8_t sha2_byte; /* Exactly 1 byte */ 1027b5038d7SDag-Erling Smørgrav typedef uint32_t sha2_word32; /* Exactly 4 bytes */ 1037b5038d7SDag-Erling Smørgrav #ifdef S_SPLINT_S 1047b5038d7SDag-Erling Smørgrav typedef unsigned long long sha2_word64; /* lint 8 bytes */ 1057b5038d7SDag-Erling Smørgrav #else 1067b5038d7SDag-Erling Smørgrav typedef uint64_t sha2_word64; /* Exactly 8 bytes */ 1077b5038d7SDag-Erling Smørgrav #endif 1087b5038d7SDag-Erling Smørgrav 1097b5038d7SDag-Erling Smørgrav /*** SHA-256/384/512 Various Length Definitions ***********************/ 1107b5038d7SDag-Erling Smørgrav /* NOTE: Most of these are in sha2.h */ 1117b5038d7SDag-Erling Smørgrav #define ldns_sha256_SHORT_BLOCK_LENGTH (LDNS_SHA256_BLOCK_LENGTH - 8) 1127b5038d7SDag-Erling Smørgrav #define ldns_sha384_SHORT_BLOCK_LENGTH (LDNS_SHA384_BLOCK_LENGTH - 16) 1137b5038d7SDag-Erling Smørgrav #define ldns_sha512_SHORT_BLOCK_LENGTH (LDNS_SHA512_BLOCK_LENGTH - 16) 1147b5038d7SDag-Erling Smørgrav 1157b5038d7SDag-Erling Smørgrav 1167b5038d7SDag-Erling Smørgrav /*** ENDIAN REVERSAL MACROS *******************************************/ 1177b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 1187b5038d7SDag-Erling Smørgrav #define REVERSE32(w,x) { \ 1197b5038d7SDag-Erling Smørgrav sha2_word32 tmp = (w); \ 1207b5038d7SDag-Erling Smørgrav tmp = (tmp >> 16) | (tmp << 16); \ 1217b5038d7SDag-Erling Smørgrav (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ 1227b5038d7SDag-Erling Smørgrav } 1237b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S 1247b5038d7SDag-Erling Smørgrav #define REVERSE64(w,x) { \ 1257b5038d7SDag-Erling Smørgrav sha2_word64 tmp = (w); \ 1267b5038d7SDag-Erling Smørgrav tmp = (tmp >> 32) | (tmp << 32); \ 1277b5038d7SDag-Erling Smørgrav tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \ 1287b5038d7SDag-Erling Smørgrav ((tmp & 0x00ff00ff00ff00ffULL) << 8); \ 1297b5038d7SDag-Erling Smørgrav (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \ 1307b5038d7SDag-Erling Smørgrav ((tmp & 0x0000ffff0000ffffULL) << 16); \ 1317b5038d7SDag-Erling Smørgrav } 1327b5038d7SDag-Erling Smørgrav #else /* splint */ 1337b5038d7SDag-Erling Smørgrav #define REVERSE64(w,x) /* splint */ 1347b5038d7SDag-Erling Smørgrav #endif /* splint */ 1357b5038d7SDag-Erling Smørgrav #endif /* BYTE_ORDER == LITTLE_ENDIAN */ 1367b5038d7SDag-Erling Smørgrav 1377b5038d7SDag-Erling Smørgrav /* 1387b5038d7SDag-Erling Smørgrav * Macro for incrementally adding the unsigned 64-bit integer n to the 1397b5038d7SDag-Erling Smørgrav * unsigned 128-bit integer (represented using a two-element array of 1407b5038d7SDag-Erling Smørgrav * 64-bit words): 1417b5038d7SDag-Erling Smørgrav */ 1427b5038d7SDag-Erling Smørgrav #define ADDINC128(w,n) { \ 1437b5038d7SDag-Erling Smørgrav (w)[0] += (sha2_word64)(n); \ 1447b5038d7SDag-Erling Smørgrav if ((w)[0] < (n)) { \ 1457b5038d7SDag-Erling Smørgrav (w)[1]++; \ 1467b5038d7SDag-Erling Smørgrav } \ 1477b5038d7SDag-Erling Smørgrav } 1487b5038d7SDag-Erling Smørgrav #ifdef S_SPLINT_S 1497b5038d7SDag-Erling Smørgrav #undef ADDINC128 1507b5038d7SDag-Erling Smørgrav #define ADDINC128(w,n) /* splint */ 1517b5038d7SDag-Erling Smørgrav #endif 1527b5038d7SDag-Erling Smørgrav 1537b5038d7SDag-Erling Smørgrav /* 1547b5038d7SDag-Erling Smørgrav * Macros for copying blocks of memory and for zeroing out ranges 1557b5038d7SDag-Erling Smørgrav * of memory. Using these macros makes it easy to switch from 1567b5038d7SDag-Erling Smørgrav * using memset()/memcpy() and using bzero()/bcopy(). 1577b5038d7SDag-Erling Smørgrav * 1587b5038d7SDag-Erling Smørgrav * Please define either SHA2_USE_MEMSET_MEMCPY or define 1597b5038d7SDag-Erling Smørgrav * SHA2_USE_BZERO_BCOPY depending on which function set you 1607b5038d7SDag-Erling Smørgrav * choose to use: 1617b5038d7SDag-Erling Smørgrav */ 1627b5038d7SDag-Erling Smørgrav #if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY) 1637b5038d7SDag-Erling Smørgrav /* Default to memset()/memcpy() if no option is specified */ 1647b5038d7SDag-Erling Smørgrav #define SHA2_USE_MEMSET_MEMCPY 1 1657b5038d7SDag-Erling Smørgrav #endif 1667b5038d7SDag-Erling Smørgrav #if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY) 1677b5038d7SDag-Erling Smørgrav /* Abort with an error if BOTH options are defined */ 1687b5038d7SDag-Erling Smørgrav #error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both! 1697b5038d7SDag-Erling Smørgrav #endif 1707b5038d7SDag-Erling Smørgrav 1717b5038d7SDag-Erling Smørgrav #ifdef SHA2_USE_MEMSET_MEMCPY 1727b5038d7SDag-Erling Smørgrav #define MEMSET_BZERO(p,l) memset((p), 0, (l)) 1737b5038d7SDag-Erling Smørgrav #define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l)) 1747b5038d7SDag-Erling Smørgrav #endif 1757b5038d7SDag-Erling Smørgrav #ifdef SHA2_USE_BZERO_BCOPY 1767b5038d7SDag-Erling Smørgrav #define MEMSET_BZERO(p,l) bzero((p), (l)) 1777b5038d7SDag-Erling Smørgrav #define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l)) 1787b5038d7SDag-Erling Smørgrav #endif 1797b5038d7SDag-Erling Smørgrav 1807b5038d7SDag-Erling Smørgrav 1817b5038d7SDag-Erling Smørgrav /*** THE SIX LOGICAL FUNCTIONS ****************************************/ 1827b5038d7SDag-Erling Smørgrav /* 1837b5038d7SDag-Erling Smørgrav * Bit shifting and rotation (used by the six SHA-XYZ logical functions: 1847b5038d7SDag-Erling Smørgrav * 1857b5038d7SDag-Erling Smørgrav * NOTE: The naming of R and S appears backwards here (R is a SHIFT and 1867b5038d7SDag-Erling Smørgrav * S is a ROTATION) because the SHA-256/384/512 description document 1877b5038d7SDag-Erling Smørgrav * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this 1887b5038d7SDag-Erling Smørgrav * same "backwards" definition. 1897b5038d7SDag-Erling Smørgrav */ 1907b5038d7SDag-Erling Smørgrav /* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ 1917b5038d7SDag-Erling Smørgrav #define R(b,x) ((x) >> (b)) 1927b5038d7SDag-Erling Smørgrav /* 32-bit Rotate-right (used in SHA-256): */ 1937b5038d7SDag-Erling Smørgrav #define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) 1947b5038d7SDag-Erling Smørgrav /* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ 1957b5038d7SDag-Erling Smørgrav #define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) 1967b5038d7SDag-Erling Smørgrav 1977b5038d7SDag-Erling Smørgrav /* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ 1987b5038d7SDag-Erling Smørgrav #define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) 1997b5038d7SDag-Erling Smørgrav #define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) 2007b5038d7SDag-Erling Smørgrav 2017b5038d7SDag-Erling Smørgrav /* Four of six logical functions used in SHA-256: */ 2027b5038d7SDag-Erling Smørgrav #define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) 2037b5038d7SDag-Erling Smørgrav #define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) 2047b5038d7SDag-Erling Smørgrav #define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) 2057b5038d7SDag-Erling Smørgrav #define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) 2067b5038d7SDag-Erling Smørgrav 2077b5038d7SDag-Erling Smørgrav /* Four of six logical functions used in SHA-384 and SHA-512: */ 2087b5038d7SDag-Erling Smørgrav #define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) 2097b5038d7SDag-Erling Smørgrav #define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) 2107b5038d7SDag-Erling Smørgrav #define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) 2117b5038d7SDag-Erling Smørgrav #define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) 2127b5038d7SDag-Erling Smørgrav 2137b5038d7SDag-Erling Smørgrav /*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ 2147b5038d7SDag-Erling Smørgrav /* Hash constant words K for SHA-256: */ 2157b5038d7SDag-Erling Smørgrav static const sha2_word32 K256[64] = { 2167b5038d7SDag-Erling Smørgrav 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 2177b5038d7SDag-Erling Smørgrav 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 2187b5038d7SDag-Erling Smørgrav 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, 2197b5038d7SDag-Erling Smørgrav 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, 2207b5038d7SDag-Erling Smørgrav 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 2217b5038d7SDag-Erling Smørgrav 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 2227b5038d7SDag-Erling Smørgrav 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 2237b5038d7SDag-Erling Smørgrav 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, 2247b5038d7SDag-Erling Smørgrav 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, 2257b5038d7SDag-Erling Smørgrav 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 2267b5038d7SDag-Erling Smørgrav 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 2277b5038d7SDag-Erling Smørgrav 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 2287b5038d7SDag-Erling Smørgrav 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 2297b5038d7SDag-Erling Smørgrav 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, 2307b5038d7SDag-Erling Smørgrav 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 2317b5038d7SDag-Erling Smørgrav 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL 2327b5038d7SDag-Erling Smørgrav }; 2337b5038d7SDag-Erling Smørgrav 2347b5038d7SDag-Erling Smørgrav /* initial hash value H for SHA-256: */ 2357b5038d7SDag-Erling Smørgrav static const sha2_word32 ldns_sha256_initial_hash_value[8] = { 2367b5038d7SDag-Erling Smørgrav 0x6a09e667UL, 2377b5038d7SDag-Erling Smørgrav 0xbb67ae85UL, 2387b5038d7SDag-Erling Smørgrav 0x3c6ef372UL, 2397b5038d7SDag-Erling Smørgrav 0xa54ff53aUL, 2407b5038d7SDag-Erling Smørgrav 0x510e527fUL, 2417b5038d7SDag-Erling Smørgrav 0x9b05688cUL, 2427b5038d7SDag-Erling Smørgrav 0x1f83d9abUL, 2437b5038d7SDag-Erling Smørgrav 0x5be0cd19UL 2447b5038d7SDag-Erling Smørgrav }; 2457b5038d7SDag-Erling Smørgrav 2467b5038d7SDag-Erling Smørgrav /* Hash constant words K for SHA-384 and SHA-512: */ 2477b5038d7SDag-Erling Smørgrav static const sha2_word64 K512[80] = { 2487b5038d7SDag-Erling Smørgrav 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 2497b5038d7SDag-Erling Smørgrav 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 2507b5038d7SDag-Erling Smørgrav 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 2517b5038d7SDag-Erling Smørgrav 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 2527b5038d7SDag-Erling Smørgrav 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 2537b5038d7SDag-Erling Smørgrav 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 2547b5038d7SDag-Erling Smørgrav 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 2557b5038d7SDag-Erling Smørgrav 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, 2567b5038d7SDag-Erling Smørgrav 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 2577b5038d7SDag-Erling Smørgrav 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 2587b5038d7SDag-Erling Smørgrav 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 2597b5038d7SDag-Erling Smørgrav 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 2607b5038d7SDag-Erling Smørgrav 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 2617b5038d7SDag-Erling Smørgrav 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, 2627b5038d7SDag-Erling Smørgrav 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 2637b5038d7SDag-Erling Smørgrav 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 2647b5038d7SDag-Erling Smørgrav 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 2657b5038d7SDag-Erling Smørgrav 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, 2667b5038d7SDag-Erling Smørgrav 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 2677b5038d7SDag-Erling Smørgrav 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, 2687b5038d7SDag-Erling Smørgrav 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 2697b5038d7SDag-Erling Smørgrav 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 2707b5038d7SDag-Erling Smørgrav 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 2717b5038d7SDag-Erling Smørgrav 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 2727b5038d7SDag-Erling Smørgrav 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 2737b5038d7SDag-Erling Smørgrav 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, 2747b5038d7SDag-Erling Smørgrav 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 2757b5038d7SDag-Erling Smørgrav 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 2767b5038d7SDag-Erling Smørgrav 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 2777b5038d7SDag-Erling Smørgrav 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, 2787b5038d7SDag-Erling Smørgrav 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 2797b5038d7SDag-Erling Smørgrav 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, 2807b5038d7SDag-Erling Smørgrav 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 2817b5038d7SDag-Erling Smørgrav 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 2827b5038d7SDag-Erling Smørgrav 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 2837b5038d7SDag-Erling Smørgrav 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 2847b5038d7SDag-Erling Smørgrav 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 2857b5038d7SDag-Erling Smørgrav 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, 2867b5038d7SDag-Erling Smørgrav 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 2877b5038d7SDag-Erling Smørgrav 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL 2887b5038d7SDag-Erling Smørgrav }; 2897b5038d7SDag-Erling Smørgrav 2907b5038d7SDag-Erling Smørgrav /* initial hash value H for SHA-384 */ 2917b5038d7SDag-Erling Smørgrav static const sha2_word64 sha384_initial_hash_value[8] = { 2927b5038d7SDag-Erling Smørgrav 0xcbbb9d5dc1059ed8ULL, 2937b5038d7SDag-Erling Smørgrav 0x629a292a367cd507ULL, 2947b5038d7SDag-Erling Smørgrav 0x9159015a3070dd17ULL, 2957b5038d7SDag-Erling Smørgrav 0x152fecd8f70e5939ULL, 2967b5038d7SDag-Erling Smørgrav 0x67332667ffc00b31ULL, 2977b5038d7SDag-Erling Smørgrav 0x8eb44a8768581511ULL, 2987b5038d7SDag-Erling Smørgrav 0xdb0c2e0d64f98fa7ULL, 2997b5038d7SDag-Erling Smørgrav 0x47b5481dbefa4fa4ULL 3007b5038d7SDag-Erling Smørgrav }; 3017b5038d7SDag-Erling Smørgrav 3027b5038d7SDag-Erling Smørgrav /* initial hash value H for SHA-512 */ 3037b5038d7SDag-Erling Smørgrav static const sha2_word64 sha512_initial_hash_value[8] = { 3047b5038d7SDag-Erling Smørgrav 0x6a09e667f3bcc908ULL, 3057b5038d7SDag-Erling Smørgrav 0xbb67ae8584caa73bULL, 3067b5038d7SDag-Erling Smørgrav 0x3c6ef372fe94f82bULL, 3077b5038d7SDag-Erling Smørgrav 0xa54ff53a5f1d36f1ULL, 3087b5038d7SDag-Erling Smørgrav 0x510e527fade682d1ULL, 3097b5038d7SDag-Erling Smørgrav 0x9b05688c2b3e6c1fULL, 3107b5038d7SDag-Erling Smørgrav 0x1f83d9abfb41bd6bULL, 3117b5038d7SDag-Erling Smørgrav 0x5be0cd19137e2179ULL 3127b5038d7SDag-Erling Smørgrav }; 3137b5038d7SDag-Erling Smørgrav 3147b5038d7SDag-Erling Smørgrav /*** SHA-256: *********************************************************/ 3157b5038d7SDag-Erling Smørgrav void ldns_sha256_init(ldns_sha256_CTX* context) { 3167b5038d7SDag-Erling Smørgrav if (context == (ldns_sha256_CTX*)0) { 3177b5038d7SDag-Erling Smørgrav return; 3187b5038d7SDag-Erling Smørgrav } 3197b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(context->state, ldns_sha256_initial_hash_value, LDNS_SHA256_DIGEST_LENGTH); 3207b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context->buffer, LDNS_SHA256_BLOCK_LENGTH); 3217b5038d7SDag-Erling Smørgrav context->bitcount = 0; 3227b5038d7SDag-Erling Smørgrav } 3237b5038d7SDag-Erling Smørgrav 3247b5038d7SDag-Erling Smørgrav #ifdef SHA2_UNROLL_TRANSFORM 3257b5038d7SDag-Erling Smørgrav 3267b5038d7SDag-Erling Smørgrav /* Unrolled SHA-256 round macros: */ 3277b5038d7SDag-Erling Smørgrav 3287b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 3297b5038d7SDag-Erling Smørgrav 3307b5038d7SDag-Erling Smørgrav #define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ 3317b5038d7SDag-Erling Smørgrav REVERSE32(*data++, W256[j]); \ 3327b5038d7SDag-Erling Smørgrav T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ 3337b5038d7SDag-Erling Smørgrav K256[j] + W256[j]; \ 3347b5038d7SDag-Erling Smørgrav (d) += T1; \ 3357b5038d7SDag-Erling Smørgrav (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ 3367b5038d7SDag-Erling Smørgrav j++ 3377b5038d7SDag-Erling Smørgrav 3387b5038d7SDag-Erling Smørgrav 3397b5038d7SDag-Erling Smørgrav #else /* BYTE_ORDER == LITTLE_ENDIAN */ 3407b5038d7SDag-Erling Smørgrav 3417b5038d7SDag-Erling Smørgrav #define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ 3427b5038d7SDag-Erling Smørgrav T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ 3437b5038d7SDag-Erling Smørgrav K256[j] + (W256[j] = *data++); \ 3447b5038d7SDag-Erling Smørgrav (d) += T1; \ 3457b5038d7SDag-Erling Smørgrav (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ 3467b5038d7SDag-Erling Smørgrav j++ 3477b5038d7SDag-Erling Smørgrav 3487b5038d7SDag-Erling Smørgrav #endif /* BYTE_ORDER == LITTLE_ENDIAN */ 3497b5038d7SDag-Erling Smørgrav 3507b5038d7SDag-Erling Smørgrav #define ROUND256(a,b,c,d,e,f,g,h) \ 3517b5038d7SDag-Erling Smørgrav s0 = W256[(j+1)&0x0f]; \ 3527b5038d7SDag-Erling Smørgrav s0 = sigma0_256(s0); \ 3537b5038d7SDag-Erling Smørgrav s1 = W256[(j+14)&0x0f]; \ 3547b5038d7SDag-Erling Smørgrav s1 = sigma1_256(s1); \ 3557b5038d7SDag-Erling Smørgrav T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \ 3567b5038d7SDag-Erling Smørgrav (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ 3577b5038d7SDag-Erling Smørgrav (d) += T1; \ 3587b5038d7SDag-Erling Smørgrav (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ 3597b5038d7SDag-Erling Smørgrav j++ 3607b5038d7SDag-Erling Smørgrav 3617b5038d7SDag-Erling Smørgrav static void ldns_sha256_Transform(ldns_sha256_CTX* context, 3627b5038d7SDag-Erling Smørgrav const sha2_word32* data) { 3637b5038d7SDag-Erling Smørgrav sha2_word32 a, b, c, d, e, f, g, h, s0, s1; 3647b5038d7SDag-Erling Smørgrav sha2_word32 T1, *W256; 3657b5038d7SDag-Erling Smørgrav int j; 3667b5038d7SDag-Erling Smørgrav 3677b5038d7SDag-Erling Smørgrav W256 = (sha2_word32*)context->buffer; 3687b5038d7SDag-Erling Smørgrav 3697b5038d7SDag-Erling Smørgrav /* initialize registers with the prev. intermediate value */ 3707b5038d7SDag-Erling Smørgrav a = context->state[0]; 3717b5038d7SDag-Erling Smørgrav b = context->state[1]; 3727b5038d7SDag-Erling Smørgrav c = context->state[2]; 3737b5038d7SDag-Erling Smørgrav d = context->state[3]; 3747b5038d7SDag-Erling Smørgrav e = context->state[4]; 3757b5038d7SDag-Erling Smørgrav f = context->state[5]; 3767b5038d7SDag-Erling Smørgrav g = context->state[6]; 3777b5038d7SDag-Erling Smørgrav h = context->state[7]; 3787b5038d7SDag-Erling Smørgrav 3797b5038d7SDag-Erling Smørgrav j = 0; 3807b5038d7SDag-Erling Smørgrav do { 3817b5038d7SDag-Erling Smørgrav /* Rounds 0 to 15 (unrolled): */ 3827b5038d7SDag-Erling Smørgrav ROUND256_0_TO_15(a,b,c,d,e,f,g,h); 3837b5038d7SDag-Erling Smørgrav ROUND256_0_TO_15(h,a,b,c,d,e,f,g); 3847b5038d7SDag-Erling Smørgrav ROUND256_0_TO_15(g,h,a,b,c,d,e,f); 3857b5038d7SDag-Erling Smørgrav ROUND256_0_TO_15(f,g,h,a,b,c,d,e); 3867b5038d7SDag-Erling Smørgrav ROUND256_0_TO_15(e,f,g,h,a,b,c,d); 3877b5038d7SDag-Erling Smørgrav ROUND256_0_TO_15(d,e,f,g,h,a,b,c); 3887b5038d7SDag-Erling Smørgrav ROUND256_0_TO_15(c,d,e,f,g,h,a,b); 3897b5038d7SDag-Erling Smørgrav ROUND256_0_TO_15(b,c,d,e,f,g,h,a); 3907b5038d7SDag-Erling Smørgrav } while (j < 16); 3917b5038d7SDag-Erling Smørgrav 3927b5038d7SDag-Erling Smørgrav /* Now for the remaining rounds to 64: */ 3937b5038d7SDag-Erling Smørgrav do { 3947b5038d7SDag-Erling Smørgrav ROUND256(a,b,c,d,e,f,g,h); 3957b5038d7SDag-Erling Smørgrav ROUND256(h,a,b,c,d,e,f,g); 3967b5038d7SDag-Erling Smørgrav ROUND256(g,h,a,b,c,d,e,f); 3977b5038d7SDag-Erling Smørgrav ROUND256(f,g,h,a,b,c,d,e); 3987b5038d7SDag-Erling Smørgrav ROUND256(e,f,g,h,a,b,c,d); 3997b5038d7SDag-Erling Smørgrav ROUND256(d,e,f,g,h,a,b,c); 4007b5038d7SDag-Erling Smørgrav ROUND256(c,d,e,f,g,h,a,b); 4017b5038d7SDag-Erling Smørgrav ROUND256(b,c,d,e,f,g,h,a); 4027b5038d7SDag-Erling Smørgrav } while (j < 64); 4037b5038d7SDag-Erling Smørgrav 4047b5038d7SDag-Erling Smørgrav /* Compute the current intermediate hash value */ 4057b5038d7SDag-Erling Smørgrav context->state[0] += a; 4067b5038d7SDag-Erling Smørgrav context->state[1] += b; 4077b5038d7SDag-Erling Smørgrav context->state[2] += c; 4087b5038d7SDag-Erling Smørgrav context->state[3] += d; 4097b5038d7SDag-Erling Smørgrav context->state[4] += e; 4107b5038d7SDag-Erling Smørgrav context->state[5] += f; 4117b5038d7SDag-Erling Smørgrav context->state[6] += g; 4127b5038d7SDag-Erling Smørgrav context->state[7] += h; 4137b5038d7SDag-Erling Smørgrav 4147b5038d7SDag-Erling Smørgrav /* Clean up */ 4157b5038d7SDag-Erling Smørgrav a = b = c = d = e = f = g = h = T1 = 0; 4167b5038d7SDag-Erling Smørgrav } 4177b5038d7SDag-Erling Smørgrav 4187b5038d7SDag-Erling Smørgrav #else /* SHA2_UNROLL_TRANSFORM */ 4197b5038d7SDag-Erling Smørgrav 4207b5038d7SDag-Erling Smørgrav static void ldns_sha256_Transform(ldns_sha256_CTX* context, 4217b5038d7SDag-Erling Smørgrav const sha2_word32* data) { 4227b5038d7SDag-Erling Smørgrav sha2_word32 a, b, c, d, e, f, g, h, s0, s1; 4237b5038d7SDag-Erling Smørgrav sha2_word32 T1, T2, *W256; 4247b5038d7SDag-Erling Smørgrav int j; 4257b5038d7SDag-Erling Smørgrav 4267b5038d7SDag-Erling Smørgrav W256 = (sha2_word32*)context->buffer; 4277b5038d7SDag-Erling Smørgrav 4287b5038d7SDag-Erling Smørgrav /* initialize registers with the prev. intermediate value */ 4297b5038d7SDag-Erling Smørgrav a = context->state[0]; 4307b5038d7SDag-Erling Smørgrav b = context->state[1]; 4317b5038d7SDag-Erling Smørgrav c = context->state[2]; 4327b5038d7SDag-Erling Smørgrav d = context->state[3]; 4337b5038d7SDag-Erling Smørgrav e = context->state[4]; 4347b5038d7SDag-Erling Smørgrav f = context->state[5]; 4357b5038d7SDag-Erling Smørgrav g = context->state[6]; 4367b5038d7SDag-Erling Smørgrav h = context->state[7]; 4377b5038d7SDag-Erling Smørgrav 4387b5038d7SDag-Erling Smørgrav j = 0; 4397b5038d7SDag-Erling Smørgrav do { 4407b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 4417b5038d7SDag-Erling Smørgrav /* Copy data while converting to host byte order */ 4427b5038d7SDag-Erling Smørgrav REVERSE32(*data++,W256[j]); 4437b5038d7SDag-Erling Smørgrav /* Apply the SHA-256 compression function to update a..h */ 4447b5038d7SDag-Erling Smørgrav T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; 4457b5038d7SDag-Erling Smørgrav #else /* BYTE_ORDER == LITTLE_ENDIAN */ 4467b5038d7SDag-Erling Smørgrav /* Apply the SHA-256 compression function to update a..h with copy */ 4477b5038d7SDag-Erling Smørgrav T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++); 4487b5038d7SDag-Erling Smørgrav #endif /* BYTE_ORDER == LITTLE_ENDIAN */ 4497b5038d7SDag-Erling Smørgrav T2 = Sigma0_256(a) + Maj(a, b, c); 4507b5038d7SDag-Erling Smørgrav h = g; 4517b5038d7SDag-Erling Smørgrav g = f; 4527b5038d7SDag-Erling Smørgrav f = e; 4537b5038d7SDag-Erling Smørgrav e = d + T1; 4547b5038d7SDag-Erling Smørgrav d = c; 4557b5038d7SDag-Erling Smørgrav c = b; 4567b5038d7SDag-Erling Smørgrav b = a; 4577b5038d7SDag-Erling Smørgrav a = T1 + T2; 4587b5038d7SDag-Erling Smørgrav 4597b5038d7SDag-Erling Smørgrav j++; 4607b5038d7SDag-Erling Smørgrav } while (j < 16); 4617b5038d7SDag-Erling Smørgrav 4627b5038d7SDag-Erling Smørgrav do { 4637b5038d7SDag-Erling Smørgrav /* Part of the message block expansion: */ 4647b5038d7SDag-Erling Smørgrav s0 = W256[(j+1)&0x0f]; 4657b5038d7SDag-Erling Smørgrav s0 = sigma0_256(s0); 4667b5038d7SDag-Erling Smørgrav s1 = W256[(j+14)&0x0f]; 4677b5038d7SDag-Erling Smørgrav s1 = sigma1_256(s1); 4687b5038d7SDag-Erling Smørgrav 4697b5038d7SDag-Erling Smørgrav /* Apply the SHA-256 compression function to update a..h */ 4707b5038d7SDag-Erling Smørgrav T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + 4717b5038d7SDag-Erling Smørgrav (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); 4727b5038d7SDag-Erling Smørgrav T2 = Sigma0_256(a) + Maj(a, b, c); 4737b5038d7SDag-Erling Smørgrav h = g; 4747b5038d7SDag-Erling Smørgrav g = f; 4757b5038d7SDag-Erling Smørgrav f = e; 4767b5038d7SDag-Erling Smørgrav e = d + T1; 4777b5038d7SDag-Erling Smørgrav d = c; 4787b5038d7SDag-Erling Smørgrav c = b; 4797b5038d7SDag-Erling Smørgrav b = a; 4807b5038d7SDag-Erling Smørgrav a = T1 + T2; 4817b5038d7SDag-Erling Smørgrav 4827b5038d7SDag-Erling Smørgrav j++; 4837b5038d7SDag-Erling Smørgrav } while (j < 64); 4847b5038d7SDag-Erling Smørgrav 4857b5038d7SDag-Erling Smørgrav /* Compute the current intermediate hash value */ 4867b5038d7SDag-Erling Smørgrav context->state[0] += a; 4877b5038d7SDag-Erling Smørgrav context->state[1] += b; 4887b5038d7SDag-Erling Smørgrav context->state[2] += c; 4897b5038d7SDag-Erling Smørgrav context->state[3] += d; 4907b5038d7SDag-Erling Smørgrav context->state[4] += e; 4917b5038d7SDag-Erling Smørgrav context->state[5] += f; 4927b5038d7SDag-Erling Smørgrav context->state[6] += g; 4937b5038d7SDag-Erling Smørgrav context->state[7] += h; 4947b5038d7SDag-Erling Smørgrav 4957b5038d7SDag-Erling Smørgrav /* Clean up */ 4967b5038d7SDag-Erling Smørgrav a = b = c = d = e = f = g = h = T1 = T2 = 0; 4977b5038d7SDag-Erling Smørgrav } 4987b5038d7SDag-Erling Smørgrav 4997b5038d7SDag-Erling Smørgrav #endif /* SHA2_UNROLL_TRANSFORM */ 5007b5038d7SDag-Erling Smørgrav 5017b5038d7SDag-Erling Smørgrav void ldns_sha256_update(ldns_sha256_CTX* context, const sha2_byte *data, size_t len) { 5027b5038d7SDag-Erling Smørgrav size_t freespace, usedspace; 5037b5038d7SDag-Erling Smørgrav 5047b5038d7SDag-Erling Smørgrav if (len == 0) { 5057b5038d7SDag-Erling Smørgrav /* Calling with no data is valid - we do nothing */ 5067b5038d7SDag-Erling Smørgrav return; 5077b5038d7SDag-Erling Smørgrav } 5087b5038d7SDag-Erling Smørgrav 5097b5038d7SDag-Erling Smørgrav /* Sanity check: */ 5107b5038d7SDag-Erling Smørgrav assert(context != (ldns_sha256_CTX*)0 && data != (sha2_byte*)0); 5117b5038d7SDag-Erling Smørgrav 5127b5038d7SDag-Erling Smørgrav usedspace = (context->bitcount >> 3) % LDNS_SHA256_BLOCK_LENGTH; 5137b5038d7SDag-Erling Smørgrav if (usedspace > 0) { 5147b5038d7SDag-Erling Smørgrav /* Calculate how much free space is available in the buffer */ 5157b5038d7SDag-Erling Smørgrav freespace = LDNS_SHA256_BLOCK_LENGTH - usedspace; 5167b5038d7SDag-Erling Smørgrav 5177b5038d7SDag-Erling Smørgrav if (len >= freespace) { 5187b5038d7SDag-Erling Smørgrav /* Fill the buffer completely and process it */ 5197b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); 5207b5038d7SDag-Erling Smørgrav context->bitcount += freespace << 3; 5217b5038d7SDag-Erling Smørgrav len -= freespace; 5227b5038d7SDag-Erling Smørgrav data += freespace; 5237b5038d7SDag-Erling Smørgrav ldns_sha256_Transform(context, (sha2_word32*)context->buffer); 5247b5038d7SDag-Erling Smørgrav } else { 5257b5038d7SDag-Erling Smørgrav /* The buffer is not yet full */ 5267b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(&context->buffer[usedspace], data, len); 5277b5038d7SDag-Erling Smørgrav context->bitcount += len << 3; 5287b5038d7SDag-Erling Smørgrav /* Clean up: */ 5297b5038d7SDag-Erling Smørgrav usedspace = freespace = 0; 5307b5038d7SDag-Erling Smørgrav return; 5317b5038d7SDag-Erling Smørgrav } 5327b5038d7SDag-Erling Smørgrav } 5337b5038d7SDag-Erling Smørgrav while (len >= LDNS_SHA256_BLOCK_LENGTH) { 5347b5038d7SDag-Erling Smørgrav /* Process as many complete blocks as we can */ 5357b5038d7SDag-Erling Smørgrav ldns_sha256_Transform(context, (sha2_word32*)data); 5367b5038d7SDag-Erling Smørgrav context->bitcount += LDNS_SHA256_BLOCK_LENGTH << 3; 5377b5038d7SDag-Erling Smørgrav len -= LDNS_SHA256_BLOCK_LENGTH; 5387b5038d7SDag-Erling Smørgrav data += LDNS_SHA256_BLOCK_LENGTH; 5397b5038d7SDag-Erling Smørgrav } 5407b5038d7SDag-Erling Smørgrav if (len > 0) { 5417b5038d7SDag-Erling Smørgrav /* There's left-overs, so save 'em */ 5427b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(context->buffer, data, len); 5437b5038d7SDag-Erling Smørgrav context->bitcount += len << 3; 5447b5038d7SDag-Erling Smørgrav } 5457b5038d7SDag-Erling Smørgrav /* Clean up: */ 5467b5038d7SDag-Erling Smørgrav usedspace = freespace = 0; 5477b5038d7SDag-Erling Smørgrav } 5487b5038d7SDag-Erling Smørgrav 549*17d15b25SDag-Erling Smørgrav typedef union _ldns_sha2_buffer_union { 550*17d15b25SDag-Erling Smørgrav uint8_t* theChars; 551*17d15b25SDag-Erling Smørgrav uint64_t* theLongs; 552*17d15b25SDag-Erling Smørgrav } ldns_sha2_buffer_union; 553*17d15b25SDag-Erling Smørgrav 5547b5038d7SDag-Erling Smørgrav void ldns_sha256_final(sha2_byte digest[], ldns_sha256_CTX* context) { 5557b5038d7SDag-Erling Smørgrav sha2_word32 *d = (sha2_word32*)digest; 5567b5038d7SDag-Erling Smørgrav size_t usedspace; 557*17d15b25SDag-Erling Smørgrav ldns_sha2_buffer_union cast_var; 5587b5038d7SDag-Erling Smørgrav 5597b5038d7SDag-Erling Smørgrav /* Sanity check: */ 5607b5038d7SDag-Erling Smørgrav assert(context != (ldns_sha256_CTX*)0); 5617b5038d7SDag-Erling Smørgrav 5627b5038d7SDag-Erling Smørgrav /* If no digest buffer is passed, we don't bother doing this: */ 5637b5038d7SDag-Erling Smørgrav if (digest != (sha2_byte*)0) { 5647b5038d7SDag-Erling Smørgrav usedspace = (context->bitcount >> 3) % LDNS_SHA256_BLOCK_LENGTH; 5657b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 5667b5038d7SDag-Erling Smørgrav /* Convert FROM host byte order */ 5677b5038d7SDag-Erling Smørgrav REVERSE64(context->bitcount,context->bitcount); 5687b5038d7SDag-Erling Smørgrav #endif 5697b5038d7SDag-Erling Smørgrav if (usedspace > 0) { 5707b5038d7SDag-Erling Smørgrav /* Begin padding with a 1 bit: */ 5717b5038d7SDag-Erling Smørgrav context->buffer[usedspace++] = 0x80; 5727b5038d7SDag-Erling Smørgrav 5737b5038d7SDag-Erling Smørgrav if (usedspace <= ldns_sha256_SHORT_BLOCK_LENGTH) { 5747b5038d7SDag-Erling Smørgrav /* Set-up for the last transform: */ 5757b5038d7SDag-Erling Smørgrav MEMSET_BZERO(&context->buffer[usedspace], ldns_sha256_SHORT_BLOCK_LENGTH - usedspace); 5767b5038d7SDag-Erling Smørgrav } else { 5777b5038d7SDag-Erling Smørgrav if (usedspace < LDNS_SHA256_BLOCK_LENGTH) { 5787b5038d7SDag-Erling Smørgrav MEMSET_BZERO(&context->buffer[usedspace], LDNS_SHA256_BLOCK_LENGTH - usedspace); 5797b5038d7SDag-Erling Smørgrav } 5807b5038d7SDag-Erling Smørgrav /* Do second-to-last transform: */ 5817b5038d7SDag-Erling Smørgrav ldns_sha256_Transform(context, (sha2_word32*)context->buffer); 5827b5038d7SDag-Erling Smørgrav 5837b5038d7SDag-Erling Smørgrav /* And set-up for the last transform: */ 5847b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context->buffer, ldns_sha256_SHORT_BLOCK_LENGTH); 5857b5038d7SDag-Erling Smørgrav } 5867b5038d7SDag-Erling Smørgrav } else { 5877b5038d7SDag-Erling Smørgrav /* Set-up for the last transform: */ 5887b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context->buffer, ldns_sha256_SHORT_BLOCK_LENGTH); 5897b5038d7SDag-Erling Smørgrav 5907b5038d7SDag-Erling Smørgrav /* Begin padding with a 1 bit: */ 5917b5038d7SDag-Erling Smørgrav *context->buffer = 0x80; 5927b5038d7SDag-Erling Smørgrav } 5937b5038d7SDag-Erling Smørgrav /* Set the bit count: */ 594*17d15b25SDag-Erling Smørgrav cast_var.theChars = context->buffer; 595*17d15b25SDag-Erling Smørgrav cast_var.theLongs[ldns_sha256_SHORT_BLOCK_LENGTH / 8] = context->bitcount; 5967b5038d7SDag-Erling Smørgrav 5977b5038d7SDag-Erling Smørgrav /* final transform: */ 5987b5038d7SDag-Erling Smørgrav ldns_sha256_Transform(context, (sha2_word32*)context->buffer); 5997b5038d7SDag-Erling Smørgrav 6007b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 6017b5038d7SDag-Erling Smørgrav { 6027b5038d7SDag-Erling Smørgrav /* Convert TO host byte order */ 6037b5038d7SDag-Erling Smørgrav int j; 6047b5038d7SDag-Erling Smørgrav for (j = 0; j < 8; j++) { 6057b5038d7SDag-Erling Smørgrav REVERSE32(context->state[j],context->state[j]); 6067b5038d7SDag-Erling Smørgrav *d++ = context->state[j]; 6077b5038d7SDag-Erling Smørgrav } 6087b5038d7SDag-Erling Smørgrav } 6097b5038d7SDag-Erling Smørgrav #else 6107b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(d, context->state, LDNS_SHA256_DIGEST_LENGTH); 6117b5038d7SDag-Erling Smørgrav #endif 6127b5038d7SDag-Erling Smørgrav } 6137b5038d7SDag-Erling Smørgrav 6147b5038d7SDag-Erling Smørgrav /* Clean up state data: */ 6157b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context, sizeof(ldns_sha256_CTX)); 6167b5038d7SDag-Erling Smørgrav usedspace = 0; 6177b5038d7SDag-Erling Smørgrav } 6187b5038d7SDag-Erling Smørgrav 6197b5038d7SDag-Erling Smørgrav unsigned char * 6207b5038d7SDag-Erling Smørgrav ldns_sha256(unsigned char *data, unsigned int data_len, unsigned char *digest) 6217b5038d7SDag-Erling Smørgrav { 6227b5038d7SDag-Erling Smørgrav ldns_sha256_CTX ctx; 6237b5038d7SDag-Erling Smørgrav ldns_sha256_init(&ctx); 6247b5038d7SDag-Erling Smørgrav ldns_sha256_update(&ctx, data, data_len); 6257b5038d7SDag-Erling Smørgrav ldns_sha256_final(digest, &ctx); 6267b5038d7SDag-Erling Smørgrav return digest; 6277b5038d7SDag-Erling Smørgrav } 6287b5038d7SDag-Erling Smørgrav 6297b5038d7SDag-Erling Smørgrav /*** SHA-512: *********************************************************/ 6307b5038d7SDag-Erling Smørgrav void ldns_sha512_init(ldns_sha512_CTX* context) { 6317b5038d7SDag-Erling Smørgrav if (context == (ldns_sha512_CTX*)0) { 6327b5038d7SDag-Erling Smørgrav return; 6337b5038d7SDag-Erling Smørgrav } 6347b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(context->state, sha512_initial_hash_value, LDNS_SHA512_DIGEST_LENGTH); 6357b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context->buffer, LDNS_SHA512_BLOCK_LENGTH); 6367b5038d7SDag-Erling Smørgrav context->bitcount[0] = context->bitcount[1] = 0; 6377b5038d7SDag-Erling Smørgrav } 6387b5038d7SDag-Erling Smørgrav 6397b5038d7SDag-Erling Smørgrav #ifdef SHA2_UNROLL_TRANSFORM 6407b5038d7SDag-Erling Smørgrav 6417b5038d7SDag-Erling Smørgrav /* Unrolled SHA-512 round macros: */ 6427b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 6437b5038d7SDag-Erling Smørgrav 6447b5038d7SDag-Erling Smørgrav #define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ 6457b5038d7SDag-Erling Smørgrav REVERSE64(*data++, W512[j]); \ 6467b5038d7SDag-Erling Smørgrav T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ 6477b5038d7SDag-Erling Smørgrav K512[j] + W512[j]; \ 6487b5038d7SDag-Erling Smørgrav (d) += T1, \ 6497b5038d7SDag-Erling Smørgrav (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \ 6507b5038d7SDag-Erling Smørgrav j++ 6517b5038d7SDag-Erling Smørgrav 6527b5038d7SDag-Erling Smørgrav 6537b5038d7SDag-Erling Smørgrav #else /* BYTE_ORDER == LITTLE_ENDIAN */ 6547b5038d7SDag-Erling Smørgrav 6557b5038d7SDag-Erling Smørgrav #define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ 6567b5038d7SDag-Erling Smørgrav T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ 6577b5038d7SDag-Erling Smørgrav K512[j] + (W512[j] = *data++); \ 6587b5038d7SDag-Erling Smørgrav (d) += T1; \ 6597b5038d7SDag-Erling Smørgrav (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ 6607b5038d7SDag-Erling Smørgrav j++ 6617b5038d7SDag-Erling Smørgrav 6627b5038d7SDag-Erling Smørgrav #endif /* BYTE_ORDER == LITTLE_ENDIAN */ 6637b5038d7SDag-Erling Smørgrav 6647b5038d7SDag-Erling Smørgrav #define ROUND512(a,b,c,d,e,f,g,h) \ 6657b5038d7SDag-Erling Smørgrav s0 = W512[(j+1)&0x0f]; \ 6667b5038d7SDag-Erling Smørgrav s0 = sigma0_512(s0); \ 6677b5038d7SDag-Erling Smørgrav s1 = W512[(j+14)&0x0f]; \ 6687b5038d7SDag-Erling Smørgrav s1 = sigma1_512(s1); \ 6697b5038d7SDag-Erling Smørgrav T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \ 6707b5038d7SDag-Erling Smørgrav (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ 6717b5038d7SDag-Erling Smørgrav (d) += T1; \ 6727b5038d7SDag-Erling Smørgrav (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ 6737b5038d7SDag-Erling Smørgrav j++ 6747b5038d7SDag-Erling Smørgrav 6757b5038d7SDag-Erling Smørgrav static void ldns_sha512_Transform(ldns_sha512_CTX* context, 6767b5038d7SDag-Erling Smørgrav const sha2_word64* data) { 6777b5038d7SDag-Erling Smørgrav sha2_word64 a, b, c, d, e, f, g, h, s0, s1; 6787b5038d7SDag-Erling Smørgrav sha2_word64 T1, *W512 = (sha2_word64*)context->buffer; 6797b5038d7SDag-Erling Smørgrav int j; 6807b5038d7SDag-Erling Smørgrav 6817b5038d7SDag-Erling Smørgrav /* initialize registers with the prev. intermediate value */ 6827b5038d7SDag-Erling Smørgrav a = context->state[0]; 6837b5038d7SDag-Erling Smørgrav b = context->state[1]; 6847b5038d7SDag-Erling Smørgrav c = context->state[2]; 6857b5038d7SDag-Erling Smørgrav d = context->state[3]; 6867b5038d7SDag-Erling Smørgrav e = context->state[4]; 6877b5038d7SDag-Erling Smørgrav f = context->state[5]; 6887b5038d7SDag-Erling Smørgrav g = context->state[6]; 6897b5038d7SDag-Erling Smørgrav h = context->state[7]; 6907b5038d7SDag-Erling Smørgrav 6917b5038d7SDag-Erling Smørgrav j = 0; 6927b5038d7SDag-Erling Smørgrav do { 6937b5038d7SDag-Erling Smørgrav ROUND512_0_TO_15(a,b,c,d,e,f,g,h); 6947b5038d7SDag-Erling Smørgrav ROUND512_0_TO_15(h,a,b,c,d,e,f,g); 6957b5038d7SDag-Erling Smørgrav ROUND512_0_TO_15(g,h,a,b,c,d,e,f); 6967b5038d7SDag-Erling Smørgrav ROUND512_0_TO_15(f,g,h,a,b,c,d,e); 6977b5038d7SDag-Erling Smørgrav ROUND512_0_TO_15(e,f,g,h,a,b,c,d); 6987b5038d7SDag-Erling Smørgrav ROUND512_0_TO_15(d,e,f,g,h,a,b,c); 6997b5038d7SDag-Erling Smørgrav ROUND512_0_TO_15(c,d,e,f,g,h,a,b); 7007b5038d7SDag-Erling Smørgrav ROUND512_0_TO_15(b,c,d,e,f,g,h,a); 7017b5038d7SDag-Erling Smørgrav } while (j < 16); 7027b5038d7SDag-Erling Smørgrav 7037b5038d7SDag-Erling Smørgrav /* Now for the remaining rounds up to 79: */ 7047b5038d7SDag-Erling Smørgrav do { 7057b5038d7SDag-Erling Smørgrav ROUND512(a,b,c,d,e,f,g,h); 7067b5038d7SDag-Erling Smørgrav ROUND512(h,a,b,c,d,e,f,g); 7077b5038d7SDag-Erling Smørgrav ROUND512(g,h,a,b,c,d,e,f); 7087b5038d7SDag-Erling Smørgrav ROUND512(f,g,h,a,b,c,d,e); 7097b5038d7SDag-Erling Smørgrav ROUND512(e,f,g,h,a,b,c,d); 7107b5038d7SDag-Erling Smørgrav ROUND512(d,e,f,g,h,a,b,c); 7117b5038d7SDag-Erling Smørgrav ROUND512(c,d,e,f,g,h,a,b); 7127b5038d7SDag-Erling Smørgrav ROUND512(b,c,d,e,f,g,h,a); 7137b5038d7SDag-Erling Smørgrav } while (j < 80); 7147b5038d7SDag-Erling Smørgrav 7157b5038d7SDag-Erling Smørgrav /* Compute the current intermediate hash value */ 7167b5038d7SDag-Erling Smørgrav context->state[0] += a; 7177b5038d7SDag-Erling Smørgrav context->state[1] += b; 7187b5038d7SDag-Erling Smørgrav context->state[2] += c; 7197b5038d7SDag-Erling Smørgrav context->state[3] += d; 7207b5038d7SDag-Erling Smørgrav context->state[4] += e; 7217b5038d7SDag-Erling Smørgrav context->state[5] += f; 7227b5038d7SDag-Erling Smørgrav context->state[6] += g; 7237b5038d7SDag-Erling Smørgrav context->state[7] += h; 7247b5038d7SDag-Erling Smørgrav 7257b5038d7SDag-Erling Smørgrav /* Clean up */ 7267b5038d7SDag-Erling Smørgrav a = b = c = d = e = f = g = h = T1 = 0; 7277b5038d7SDag-Erling Smørgrav } 7287b5038d7SDag-Erling Smørgrav 7297b5038d7SDag-Erling Smørgrav #else /* SHA2_UNROLL_TRANSFORM */ 7307b5038d7SDag-Erling Smørgrav 7317b5038d7SDag-Erling Smørgrav static void ldns_sha512_Transform(ldns_sha512_CTX* context, 7327b5038d7SDag-Erling Smørgrav const sha2_word64* data) { 7337b5038d7SDag-Erling Smørgrav sha2_word64 a, b, c, d, e, f, g, h, s0, s1; 7347b5038d7SDag-Erling Smørgrav sha2_word64 T1, T2, *W512 = (sha2_word64*)context->buffer; 7357b5038d7SDag-Erling Smørgrav int j; 7367b5038d7SDag-Erling Smørgrav 7377b5038d7SDag-Erling Smørgrav /* initialize registers with the prev. intermediate value */ 7387b5038d7SDag-Erling Smørgrav a = context->state[0]; 7397b5038d7SDag-Erling Smørgrav b = context->state[1]; 7407b5038d7SDag-Erling Smørgrav c = context->state[2]; 7417b5038d7SDag-Erling Smørgrav d = context->state[3]; 7427b5038d7SDag-Erling Smørgrav e = context->state[4]; 7437b5038d7SDag-Erling Smørgrav f = context->state[5]; 7447b5038d7SDag-Erling Smørgrav g = context->state[6]; 7457b5038d7SDag-Erling Smørgrav h = context->state[7]; 7467b5038d7SDag-Erling Smørgrav 7477b5038d7SDag-Erling Smørgrav j = 0; 7487b5038d7SDag-Erling Smørgrav do { 7497b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 7507b5038d7SDag-Erling Smørgrav /* Convert TO host byte order */ 7517b5038d7SDag-Erling Smørgrav REVERSE64(*data++, W512[j]); 7527b5038d7SDag-Erling Smørgrav /* Apply the SHA-512 compression function to update a..h */ 7537b5038d7SDag-Erling Smørgrav T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; 7547b5038d7SDag-Erling Smørgrav #else /* BYTE_ORDER == LITTLE_ENDIAN */ 7557b5038d7SDag-Erling Smørgrav /* Apply the SHA-512 compression function to update a..h with copy */ 7567b5038d7SDag-Erling Smørgrav T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++); 7577b5038d7SDag-Erling Smørgrav #endif /* BYTE_ORDER == LITTLE_ENDIAN */ 7587b5038d7SDag-Erling Smørgrav T2 = Sigma0_512(a) + Maj(a, b, c); 7597b5038d7SDag-Erling Smørgrav h = g; 7607b5038d7SDag-Erling Smørgrav g = f; 7617b5038d7SDag-Erling Smørgrav f = e; 7627b5038d7SDag-Erling Smørgrav e = d + T1; 7637b5038d7SDag-Erling Smørgrav d = c; 7647b5038d7SDag-Erling Smørgrav c = b; 7657b5038d7SDag-Erling Smørgrav b = a; 7667b5038d7SDag-Erling Smørgrav a = T1 + T2; 7677b5038d7SDag-Erling Smørgrav 7687b5038d7SDag-Erling Smørgrav j++; 7697b5038d7SDag-Erling Smørgrav } while (j < 16); 7707b5038d7SDag-Erling Smørgrav 7717b5038d7SDag-Erling Smørgrav do { 7727b5038d7SDag-Erling Smørgrav /* Part of the message block expansion: */ 7737b5038d7SDag-Erling Smørgrav s0 = W512[(j+1)&0x0f]; 7747b5038d7SDag-Erling Smørgrav s0 = sigma0_512(s0); 7757b5038d7SDag-Erling Smørgrav s1 = W512[(j+14)&0x0f]; 7767b5038d7SDag-Erling Smørgrav s1 = sigma1_512(s1); 7777b5038d7SDag-Erling Smørgrav 7787b5038d7SDag-Erling Smørgrav /* Apply the SHA-512 compression function to update a..h */ 7797b5038d7SDag-Erling Smørgrav T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + 7807b5038d7SDag-Erling Smørgrav (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); 7817b5038d7SDag-Erling Smørgrav T2 = Sigma0_512(a) + Maj(a, b, c); 7827b5038d7SDag-Erling Smørgrav h = g; 7837b5038d7SDag-Erling Smørgrav g = f; 7847b5038d7SDag-Erling Smørgrav f = e; 7857b5038d7SDag-Erling Smørgrav e = d + T1; 7867b5038d7SDag-Erling Smørgrav d = c; 7877b5038d7SDag-Erling Smørgrav c = b; 7887b5038d7SDag-Erling Smørgrav b = a; 7897b5038d7SDag-Erling Smørgrav a = T1 + T2; 7907b5038d7SDag-Erling Smørgrav 7917b5038d7SDag-Erling Smørgrav j++; 7927b5038d7SDag-Erling Smørgrav } while (j < 80); 7937b5038d7SDag-Erling Smørgrav 7947b5038d7SDag-Erling Smørgrav /* Compute the current intermediate hash value */ 7957b5038d7SDag-Erling Smørgrav context->state[0] += a; 7967b5038d7SDag-Erling Smørgrav context->state[1] += b; 7977b5038d7SDag-Erling Smørgrav context->state[2] += c; 7987b5038d7SDag-Erling Smørgrav context->state[3] += d; 7997b5038d7SDag-Erling Smørgrav context->state[4] += e; 8007b5038d7SDag-Erling Smørgrav context->state[5] += f; 8017b5038d7SDag-Erling Smørgrav context->state[6] += g; 8027b5038d7SDag-Erling Smørgrav context->state[7] += h; 8037b5038d7SDag-Erling Smørgrav 8047b5038d7SDag-Erling Smørgrav /* Clean up */ 8057b5038d7SDag-Erling Smørgrav a = b = c = d = e = f = g = h = T1 = T2 = 0; 8067b5038d7SDag-Erling Smørgrav } 8077b5038d7SDag-Erling Smørgrav 8087b5038d7SDag-Erling Smørgrav #endif /* SHA2_UNROLL_TRANSFORM */ 8097b5038d7SDag-Erling Smørgrav 8107b5038d7SDag-Erling Smørgrav void ldns_sha512_update(ldns_sha512_CTX* context, const sha2_byte *data, size_t len) { 8117b5038d7SDag-Erling Smørgrav size_t freespace, usedspace; 8127b5038d7SDag-Erling Smørgrav 8137b5038d7SDag-Erling Smørgrav if (len == 0) { 8147b5038d7SDag-Erling Smørgrav /* Calling with no data is valid - we do nothing */ 8157b5038d7SDag-Erling Smørgrav return; 8167b5038d7SDag-Erling Smørgrav } 8177b5038d7SDag-Erling Smørgrav 8187b5038d7SDag-Erling Smørgrav /* Sanity check: */ 8197b5038d7SDag-Erling Smørgrav assert(context != (ldns_sha512_CTX*)0 && data != (sha2_byte*)0); 8207b5038d7SDag-Erling Smørgrav 8217b5038d7SDag-Erling Smørgrav usedspace = (context->bitcount[0] >> 3) % LDNS_SHA512_BLOCK_LENGTH; 8227b5038d7SDag-Erling Smørgrav if (usedspace > 0) { 8237b5038d7SDag-Erling Smørgrav /* Calculate how much free space is available in the buffer */ 8247b5038d7SDag-Erling Smørgrav freespace = LDNS_SHA512_BLOCK_LENGTH - usedspace; 8257b5038d7SDag-Erling Smørgrav 8267b5038d7SDag-Erling Smørgrav if (len >= freespace) { 8277b5038d7SDag-Erling Smørgrav /* Fill the buffer completely and process it */ 8287b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); 8297b5038d7SDag-Erling Smørgrav ADDINC128(context->bitcount, freespace << 3); 8307b5038d7SDag-Erling Smørgrav len -= freespace; 8317b5038d7SDag-Erling Smørgrav data += freespace; 8327b5038d7SDag-Erling Smørgrav ldns_sha512_Transform(context, (sha2_word64*)context->buffer); 8337b5038d7SDag-Erling Smørgrav } else { 8347b5038d7SDag-Erling Smørgrav /* The buffer is not yet full */ 8357b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(&context->buffer[usedspace], data, len); 8367b5038d7SDag-Erling Smørgrav ADDINC128(context->bitcount, len << 3); 8377b5038d7SDag-Erling Smørgrav /* Clean up: */ 8387b5038d7SDag-Erling Smørgrav usedspace = freespace = 0; 8397b5038d7SDag-Erling Smørgrav return; 8407b5038d7SDag-Erling Smørgrav } 8417b5038d7SDag-Erling Smørgrav } 8427b5038d7SDag-Erling Smørgrav while (len >= LDNS_SHA512_BLOCK_LENGTH) { 8437b5038d7SDag-Erling Smørgrav /* Process as many complete blocks as we can */ 8447b5038d7SDag-Erling Smørgrav ldns_sha512_Transform(context, (sha2_word64*)data); 8457b5038d7SDag-Erling Smørgrav ADDINC128(context->bitcount, LDNS_SHA512_BLOCK_LENGTH << 3); 8467b5038d7SDag-Erling Smørgrav len -= LDNS_SHA512_BLOCK_LENGTH; 8477b5038d7SDag-Erling Smørgrav data += LDNS_SHA512_BLOCK_LENGTH; 8487b5038d7SDag-Erling Smørgrav } 8497b5038d7SDag-Erling Smørgrav if (len > 0) { 8507b5038d7SDag-Erling Smørgrav /* There's left-overs, so save 'em */ 8517b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(context->buffer, data, len); 8527b5038d7SDag-Erling Smørgrav ADDINC128(context->bitcount, len << 3); 8537b5038d7SDag-Erling Smørgrav } 8547b5038d7SDag-Erling Smørgrav /* Clean up: */ 8557b5038d7SDag-Erling Smørgrav usedspace = freespace = 0; 8567b5038d7SDag-Erling Smørgrav } 8577b5038d7SDag-Erling Smørgrav 8587b5038d7SDag-Erling Smørgrav static void ldns_sha512_Last(ldns_sha512_CTX* context) { 8597b5038d7SDag-Erling Smørgrav size_t usedspace; 860*17d15b25SDag-Erling Smørgrav ldns_sha2_buffer_union cast_var; 8617b5038d7SDag-Erling Smørgrav 8627b5038d7SDag-Erling Smørgrav usedspace = (context->bitcount[0] >> 3) % LDNS_SHA512_BLOCK_LENGTH; 8637b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 8647b5038d7SDag-Erling Smørgrav /* Convert FROM host byte order */ 8657b5038d7SDag-Erling Smørgrav REVERSE64(context->bitcount[0],context->bitcount[0]); 8667b5038d7SDag-Erling Smørgrav REVERSE64(context->bitcount[1],context->bitcount[1]); 8677b5038d7SDag-Erling Smørgrav #endif 8687b5038d7SDag-Erling Smørgrav if (usedspace > 0) { 8697b5038d7SDag-Erling Smørgrav /* Begin padding with a 1 bit: */ 8707b5038d7SDag-Erling Smørgrav context->buffer[usedspace++] = 0x80; 8717b5038d7SDag-Erling Smørgrav 8727b5038d7SDag-Erling Smørgrav if (usedspace <= ldns_sha512_SHORT_BLOCK_LENGTH) { 8737b5038d7SDag-Erling Smørgrav /* Set-up for the last transform: */ 8747b5038d7SDag-Erling Smørgrav MEMSET_BZERO(&context->buffer[usedspace], ldns_sha512_SHORT_BLOCK_LENGTH - usedspace); 8757b5038d7SDag-Erling Smørgrav } else { 8767b5038d7SDag-Erling Smørgrav if (usedspace < LDNS_SHA512_BLOCK_LENGTH) { 8777b5038d7SDag-Erling Smørgrav MEMSET_BZERO(&context->buffer[usedspace], LDNS_SHA512_BLOCK_LENGTH - usedspace); 8787b5038d7SDag-Erling Smørgrav } 8797b5038d7SDag-Erling Smørgrav /* Do second-to-last transform: */ 8807b5038d7SDag-Erling Smørgrav ldns_sha512_Transform(context, (sha2_word64*)context->buffer); 8817b5038d7SDag-Erling Smørgrav 8827b5038d7SDag-Erling Smørgrav /* And set-up for the last transform: */ 8837b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context->buffer, LDNS_SHA512_BLOCK_LENGTH - 2); 8847b5038d7SDag-Erling Smørgrav } 8857b5038d7SDag-Erling Smørgrav } else { 8867b5038d7SDag-Erling Smørgrav /* Prepare for final transform: */ 8877b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context->buffer, ldns_sha512_SHORT_BLOCK_LENGTH); 8887b5038d7SDag-Erling Smørgrav 8897b5038d7SDag-Erling Smørgrav /* Begin padding with a 1 bit: */ 8907b5038d7SDag-Erling Smørgrav *context->buffer = 0x80; 8917b5038d7SDag-Erling Smørgrav } 8927b5038d7SDag-Erling Smørgrav /* Store the length of input data (in bits): */ 893*17d15b25SDag-Erling Smørgrav cast_var.theChars = context->buffer; 894*17d15b25SDag-Erling Smørgrav cast_var.theLongs[ldns_sha512_SHORT_BLOCK_LENGTH / 8] = context->bitcount[1]; 895*17d15b25SDag-Erling Smørgrav cast_var.theLongs[ldns_sha512_SHORT_BLOCK_LENGTH / 8 + 1] = context->bitcount[0]; 8967b5038d7SDag-Erling Smørgrav 8977b5038d7SDag-Erling Smørgrav /* final transform: */ 8987b5038d7SDag-Erling Smørgrav ldns_sha512_Transform(context, (sha2_word64*)context->buffer); 8997b5038d7SDag-Erling Smørgrav } 9007b5038d7SDag-Erling Smørgrav 9017b5038d7SDag-Erling Smørgrav void ldns_sha512_final(sha2_byte digest[], ldns_sha512_CTX* context) { 9027b5038d7SDag-Erling Smørgrav sha2_word64 *d = (sha2_word64*)digest; 9037b5038d7SDag-Erling Smørgrav 9047b5038d7SDag-Erling Smørgrav /* Sanity check: */ 9057b5038d7SDag-Erling Smørgrav assert(context != (ldns_sha512_CTX*)0); 9067b5038d7SDag-Erling Smørgrav 9077b5038d7SDag-Erling Smørgrav /* If no digest buffer is passed, we don't bother doing this: */ 9087b5038d7SDag-Erling Smørgrav if (digest != (sha2_byte*)0) { 9097b5038d7SDag-Erling Smørgrav ldns_sha512_Last(context); 9107b5038d7SDag-Erling Smørgrav 9117b5038d7SDag-Erling Smørgrav /* Save the hash data for output: */ 9127b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 9137b5038d7SDag-Erling Smørgrav { 9147b5038d7SDag-Erling Smørgrav /* Convert TO host byte order */ 9157b5038d7SDag-Erling Smørgrav int j; 9167b5038d7SDag-Erling Smørgrav for (j = 0; j < 8; j++) { 9177b5038d7SDag-Erling Smørgrav REVERSE64(context->state[j],context->state[j]); 9187b5038d7SDag-Erling Smørgrav *d++ = context->state[j]; 9197b5038d7SDag-Erling Smørgrav } 9207b5038d7SDag-Erling Smørgrav } 9217b5038d7SDag-Erling Smørgrav #else 9227b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(d, context->state, LDNS_SHA512_DIGEST_LENGTH); 9237b5038d7SDag-Erling Smørgrav #endif 9247b5038d7SDag-Erling Smørgrav } 9257b5038d7SDag-Erling Smørgrav 9267b5038d7SDag-Erling Smørgrav /* Zero out state data */ 9277b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context, sizeof(ldns_sha512_CTX)); 9287b5038d7SDag-Erling Smørgrav } 9297b5038d7SDag-Erling Smørgrav 9307b5038d7SDag-Erling Smørgrav unsigned char * 9317b5038d7SDag-Erling Smørgrav ldns_sha512(unsigned char *data, unsigned int data_len, unsigned char *digest) 9327b5038d7SDag-Erling Smørgrav { 9337b5038d7SDag-Erling Smørgrav ldns_sha512_CTX ctx; 9347b5038d7SDag-Erling Smørgrav ldns_sha512_init(&ctx); 9357b5038d7SDag-Erling Smørgrav ldns_sha512_update(&ctx, data, data_len); 9367b5038d7SDag-Erling Smørgrav ldns_sha512_final(digest, &ctx); 9377b5038d7SDag-Erling Smørgrav return digest; 9387b5038d7SDag-Erling Smørgrav } 9397b5038d7SDag-Erling Smørgrav 9407b5038d7SDag-Erling Smørgrav /*** SHA-384: *********************************************************/ 9417b5038d7SDag-Erling Smørgrav void ldns_sha384_init(ldns_sha384_CTX* context) { 9427b5038d7SDag-Erling Smørgrav if (context == (ldns_sha384_CTX*)0) { 9437b5038d7SDag-Erling Smørgrav return; 9447b5038d7SDag-Erling Smørgrav } 9457b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(context->state, sha384_initial_hash_value, LDNS_SHA512_DIGEST_LENGTH); 9467b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context->buffer, LDNS_SHA384_BLOCK_LENGTH); 9477b5038d7SDag-Erling Smørgrav context->bitcount[0] = context->bitcount[1] = 0; 9487b5038d7SDag-Erling Smørgrav } 9497b5038d7SDag-Erling Smørgrav 9507b5038d7SDag-Erling Smørgrav void ldns_sha384_update(ldns_sha384_CTX* context, const sha2_byte* data, size_t len) { 9517b5038d7SDag-Erling Smørgrav ldns_sha512_update((ldns_sha512_CTX*)context, data, len); 9527b5038d7SDag-Erling Smørgrav } 9537b5038d7SDag-Erling Smørgrav 9547b5038d7SDag-Erling Smørgrav void ldns_sha384_final(sha2_byte digest[], ldns_sha384_CTX* context) { 9557b5038d7SDag-Erling Smørgrav sha2_word64 *d = (sha2_word64*)digest; 9567b5038d7SDag-Erling Smørgrav 9577b5038d7SDag-Erling Smørgrav /* Sanity check: */ 9587b5038d7SDag-Erling Smørgrav assert(context != (ldns_sha384_CTX*)0); 9597b5038d7SDag-Erling Smørgrav 9607b5038d7SDag-Erling Smørgrav /* If no digest buffer is passed, we don't bother doing this: */ 9617b5038d7SDag-Erling Smørgrav if (digest != (sha2_byte*)0) { 9627b5038d7SDag-Erling Smørgrav ldns_sha512_Last((ldns_sha512_CTX*)context); 9637b5038d7SDag-Erling Smørgrav 9647b5038d7SDag-Erling Smørgrav /* Save the hash data for output: */ 9657b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 9667b5038d7SDag-Erling Smørgrav { 9677b5038d7SDag-Erling Smørgrav /* Convert TO host byte order */ 9687b5038d7SDag-Erling Smørgrav int j; 9697b5038d7SDag-Erling Smørgrav for (j = 0; j < 6; j++) { 9707b5038d7SDag-Erling Smørgrav REVERSE64(context->state[j],context->state[j]); 9717b5038d7SDag-Erling Smørgrav *d++ = context->state[j]; 9727b5038d7SDag-Erling Smørgrav } 9737b5038d7SDag-Erling Smørgrav } 9747b5038d7SDag-Erling Smørgrav #else 9757b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(d, context->state, LDNS_SHA384_DIGEST_LENGTH); 9767b5038d7SDag-Erling Smørgrav #endif 9777b5038d7SDag-Erling Smørgrav } 9787b5038d7SDag-Erling Smørgrav 9797b5038d7SDag-Erling Smørgrav /* Zero out state data */ 9807b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context, sizeof(ldns_sha384_CTX)); 9817b5038d7SDag-Erling Smørgrav } 9827b5038d7SDag-Erling Smørgrav 9837b5038d7SDag-Erling Smørgrav unsigned char * 9847b5038d7SDag-Erling Smørgrav ldns_sha384(unsigned char *data, unsigned int data_len, unsigned char *digest) 9857b5038d7SDag-Erling Smørgrav { 9867b5038d7SDag-Erling Smørgrav ldns_sha384_CTX ctx; 9877b5038d7SDag-Erling Smørgrav ldns_sha384_init(&ctx); 9887b5038d7SDag-Erling Smørgrav ldns_sha384_update(&ctx, data, data_len); 9897b5038d7SDag-Erling Smørgrav ldns_sha384_final(digest, &ctx); 9907b5038d7SDag-Erling Smørgrav return digest; 9917b5038d7SDag-Erling Smørgrav } 992