1*7b5038d7SDag-Erling Smørgrav /* 2*7b5038d7SDag-Erling Smørgrav * FILE: sha2.c 3*7b5038d7SDag-Erling Smørgrav * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ 4*7b5038d7SDag-Erling Smørgrav * 5*7b5038d7SDag-Erling Smørgrav * Copyright (c) 2000-2001, Aaron D. Gifford 6*7b5038d7SDag-Erling Smørgrav * All rights reserved. 7*7b5038d7SDag-Erling Smørgrav * 8*7b5038d7SDag-Erling Smørgrav * Modified by Jelte Jansen to fit in ldns, and not clash with any 9*7b5038d7SDag-Erling Smørgrav * system-defined SHA code. 10*7b5038d7SDag-Erling Smørgrav * Changes: 11*7b5038d7SDag-Erling Smørgrav * - Renamed (external) functions and constants to fit ldns style 12*7b5038d7SDag-Erling Smørgrav * - Removed _End and _Data functions 13*7b5038d7SDag-Erling Smørgrav * - Added ldns_shaX(data, len, digest) convenience functions 14*7b5038d7SDag-Erling Smørgrav * - Removed prototypes of _Transform functions and made those static 15*7b5038d7SDag-Erling Smørgrav * 16*7b5038d7SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 17*7b5038d7SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 18*7b5038d7SDag-Erling Smørgrav * are met: 19*7b5038d7SDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 20*7b5038d7SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer. 21*7b5038d7SDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 22*7b5038d7SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 23*7b5038d7SDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 24*7b5038d7SDag-Erling Smørgrav * 3. Neither the name of the copyright holder nor the names of contributors 25*7b5038d7SDag-Erling Smørgrav * may be used to endorse or promote products derived from this software 26*7b5038d7SDag-Erling Smørgrav * without specific prior written permission. 27*7b5038d7SDag-Erling Smørgrav * 28*7b5038d7SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND 29*7b5038d7SDag-Erling Smørgrav * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30*7b5038d7SDag-Erling Smørgrav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31*7b5038d7SDag-Erling Smørgrav * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE 32*7b5038d7SDag-Erling Smørgrav * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33*7b5038d7SDag-Erling Smørgrav * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34*7b5038d7SDag-Erling Smørgrav * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35*7b5038d7SDag-Erling Smørgrav * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36*7b5038d7SDag-Erling Smørgrav * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37*7b5038d7SDag-Erling Smørgrav * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38*7b5038d7SDag-Erling Smørgrav * SUCH DAMAGE. 39*7b5038d7SDag-Erling Smørgrav * 40*7b5038d7SDag-Erling Smørgrav * $Id: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $ 41*7b5038d7SDag-Erling Smørgrav */ 42*7b5038d7SDag-Erling Smørgrav 43*7b5038d7SDag-Erling Smørgrav #include <ldns/config.h> 44*7b5038d7SDag-Erling Smørgrav #include <string.h> /* memcpy()/memset() or bcopy()/bzero() */ 45*7b5038d7SDag-Erling Smørgrav #include <assert.h> /* assert() */ 46*7b5038d7SDag-Erling Smørgrav #include <ldns/sha2.h> 47*7b5038d7SDag-Erling Smørgrav 48*7b5038d7SDag-Erling Smørgrav /* 49*7b5038d7SDag-Erling Smørgrav * ASSERT NOTE: 50*7b5038d7SDag-Erling Smørgrav * Some sanity checking code is included using assert(). On my FreeBSD 51*7b5038d7SDag-Erling Smørgrav * system, this additional code can be removed by compiling with NDEBUG 52*7b5038d7SDag-Erling Smørgrav * defined. Check your own systems manpage on assert() to see how to 53*7b5038d7SDag-Erling Smørgrav * compile WITHOUT the sanity checking code on your system. 54*7b5038d7SDag-Erling Smørgrav * 55*7b5038d7SDag-Erling Smørgrav * UNROLLED TRANSFORM LOOP NOTE: 56*7b5038d7SDag-Erling Smørgrav * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform 57*7b5038d7SDag-Erling Smørgrav * loop version for the hash transform rounds (defined using macros 58*7b5038d7SDag-Erling Smørgrav * later in this file). Either define on the command line, for example: 59*7b5038d7SDag-Erling Smørgrav * 60*7b5038d7SDag-Erling Smørgrav * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c 61*7b5038d7SDag-Erling Smørgrav * 62*7b5038d7SDag-Erling Smørgrav * or define below: 63*7b5038d7SDag-Erling Smørgrav * 64*7b5038d7SDag-Erling Smørgrav * #define SHA2_UNROLL_TRANSFORM 65*7b5038d7SDag-Erling Smørgrav * 66*7b5038d7SDag-Erling Smørgrav */ 67*7b5038d7SDag-Erling Smørgrav 68*7b5038d7SDag-Erling Smørgrav 69*7b5038d7SDag-Erling Smørgrav /*** SHA-256/384/512 Machine Architecture Definitions *****************/ 70*7b5038d7SDag-Erling Smørgrav /* 71*7b5038d7SDag-Erling Smørgrav * BYTE_ORDER NOTE: 72*7b5038d7SDag-Erling Smørgrav * 73*7b5038d7SDag-Erling Smørgrav * Please make sure that your system defines BYTE_ORDER. If your 74*7b5038d7SDag-Erling Smørgrav * architecture is little-endian, make sure it also defines 75*7b5038d7SDag-Erling Smørgrav * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are 76*7b5038d7SDag-Erling Smørgrav * equivilent. 77*7b5038d7SDag-Erling Smørgrav * 78*7b5038d7SDag-Erling Smørgrav * If your system does not define the above, then you can do so by 79*7b5038d7SDag-Erling Smørgrav * hand like this: 80*7b5038d7SDag-Erling Smørgrav * 81*7b5038d7SDag-Erling Smørgrav * #define LITTLE_ENDIAN 1234 82*7b5038d7SDag-Erling Smørgrav * #define BIG_ENDIAN 4321 83*7b5038d7SDag-Erling Smørgrav * 84*7b5038d7SDag-Erling Smørgrav * And for little-endian machines, add: 85*7b5038d7SDag-Erling Smørgrav * 86*7b5038d7SDag-Erling Smørgrav * #define BYTE_ORDER LITTLE_ENDIAN 87*7b5038d7SDag-Erling Smørgrav * 88*7b5038d7SDag-Erling Smørgrav * Or for big-endian machines: 89*7b5038d7SDag-Erling Smørgrav * 90*7b5038d7SDag-Erling Smørgrav * #define BYTE_ORDER BIG_ENDIAN 91*7b5038d7SDag-Erling Smørgrav * 92*7b5038d7SDag-Erling Smørgrav * The FreeBSD machine this was written on defines BYTE_ORDER 93*7b5038d7SDag-Erling Smørgrav * appropriately by including <sys/types.h> (which in turn includes 94*7b5038d7SDag-Erling Smørgrav * <machine/endian.h> where the appropriate definitions are actually 95*7b5038d7SDag-Erling Smørgrav * made). 96*7b5038d7SDag-Erling Smørgrav */ 97*7b5038d7SDag-Erling Smørgrav #if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) 98*7b5038d7SDag-Erling Smørgrav #error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN 99*7b5038d7SDag-Erling Smørgrav #endif 100*7b5038d7SDag-Erling Smørgrav 101*7b5038d7SDag-Erling Smørgrav typedef uint8_t sha2_byte; /* Exactly 1 byte */ 102*7b5038d7SDag-Erling Smørgrav typedef uint32_t sha2_word32; /* Exactly 4 bytes */ 103*7b5038d7SDag-Erling Smørgrav #ifdef S_SPLINT_S 104*7b5038d7SDag-Erling Smørgrav typedef unsigned long long sha2_word64; /* lint 8 bytes */ 105*7b5038d7SDag-Erling Smørgrav #else 106*7b5038d7SDag-Erling Smørgrav typedef uint64_t sha2_word64; /* Exactly 8 bytes */ 107*7b5038d7SDag-Erling Smørgrav #endif 108*7b5038d7SDag-Erling Smørgrav 109*7b5038d7SDag-Erling Smørgrav /*** SHA-256/384/512 Various Length Definitions ***********************/ 110*7b5038d7SDag-Erling Smørgrav /* NOTE: Most of these are in sha2.h */ 111*7b5038d7SDag-Erling Smørgrav #define ldns_sha256_SHORT_BLOCK_LENGTH (LDNS_SHA256_BLOCK_LENGTH - 8) 112*7b5038d7SDag-Erling Smørgrav #define ldns_sha384_SHORT_BLOCK_LENGTH (LDNS_SHA384_BLOCK_LENGTH - 16) 113*7b5038d7SDag-Erling Smørgrav #define ldns_sha512_SHORT_BLOCK_LENGTH (LDNS_SHA512_BLOCK_LENGTH - 16) 114*7b5038d7SDag-Erling Smørgrav 115*7b5038d7SDag-Erling Smørgrav 116*7b5038d7SDag-Erling Smørgrav /*** ENDIAN REVERSAL MACROS *******************************************/ 117*7b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 118*7b5038d7SDag-Erling Smørgrav #define REVERSE32(w,x) { \ 119*7b5038d7SDag-Erling Smørgrav sha2_word32 tmp = (w); \ 120*7b5038d7SDag-Erling Smørgrav tmp = (tmp >> 16) | (tmp << 16); \ 121*7b5038d7SDag-Erling Smørgrav (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ 122*7b5038d7SDag-Erling Smørgrav } 123*7b5038d7SDag-Erling Smørgrav #ifndef S_SPLINT_S 124*7b5038d7SDag-Erling Smørgrav #define REVERSE64(w,x) { \ 125*7b5038d7SDag-Erling Smørgrav sha2_word64 tmp = (w); \ 126*7b5038d7SDag-Erling Smørgrav tmp = (tmp >> 32) | (tmp << 32); \ 127*7b5038d7SDag-Erling Smørgrav tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \ 128*7b5038d7SDag-Erling Smørgrav ((tmp & 0x00ff00ff00ff00ffULL) << 8); \ 129*7b5038d7SDag-Erling Smørgrav (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \ 130*7b5038d7SDag-Erling Smørgrav ((tmp & 0x0000ffff0000ffffULL) << 16); \ 131*7b5038d7SDag-Erling Smørgrav } 132*7b5038d7SDag-Erling Smørgrav #else /* splint */ 133*7b5038d7SDag-Erling Smørgrav #define REVERSE64(w,x) /* splint */ 134*7b5038d7SDag-Erling Smørgrav #endif /* splint */ 135*7b5038d7SDag-Erling Smørgrav #endif /* BYTE_ORDER == LITTLE_ENDIAN */ 136*7b5038d7SDag-Erling Smørgrav 137*7b5038d7SDag-Erling Smørgrav /* 138*7b5038d7SDag-Erling Smørgrav * Macro for incrementally adding the unsigned 64-bit integer n to the 139*7b5038d7SDag-Erling Smørgrav * unsigned 128-bit integer (represented using a two-element array of 140*7b5038d7SDag-Erling Smørgrav * 64-bit words): 141*7b5038d7SDag-Erling Smørgrav */ 142*7b5038d7SDag-Erling Smørgrav #define ADDINC128(w,n) { \ 143*7b5038d7SDag-Erling Smørgrav (w)[0] += (sha2_word64)(n); \ 144*7b5038d7SDag-Erling Smørgrav if ((w)[0] < (n)) { \ 145*7b5038d7SDag-Erling Smørgrav (w)[1]++; \ 146*7b5038d7SDag-Erling Smørgrav } \ 147*7b5038d7SDag-Erling Smørgrav } 148*7b5038d7SDag-Erling Smørgrav #ifdef S_SPLINT_S 149*7b5038d7SDag-Erling Smørgrav #undef ADDINC128 150*7b5038d7SDag-Erling Smørgrav #define ADDINC128(w,n) /* splint */ 151*7b5038d7SDag-Erling Smørgrav #endif 152*7b5038d7SDag-Erling Smørgrav 153*7b5038d7SDag-Erling Smørgrav /* 154*7b5038d7SDag-Erling Smørgrav * Macros for copying blocks of memory and for zeroing out ranges 155*7b5038d7SDag-Erling Smørgrav * of memory. Using these macros makes it easy to switch from 156*7b5038d7SDag-Erling Smørgrav * using memset()/memcpy() and using bzero()/bcopy(). 157*7b5038d7SDag-Erling Smørgrav * 158*7b5038d7SDag-Erling Smørgrav * Please define either SHA2_USE_MEMSET_MEMCPY or define 159*7b5038d7SDag-Erling Smørgrav * SHA2_USE_BZERO_BCOPY depending on which function set you 160*7b5038d7SDag-Erling Smørgrav * choose to use: 161*7b5038d7SDag-Erling Smørgrav */ 162*7b5038d7SDag-Erling Smørgrav #if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY) 163*7b5038d7SDag-Erling Smørgrav /* Default to memset()/memcpy() if no option is specified */ 164*7b5038d7SDag-Erling Smørgrav #define SHA2_USE_MEMSET_MEMCPY 1 165*7b5038d7SDag-Erling Smørgrav #endif 166*7b5038d7SDag-Erling Smørgrav #if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY) 167*7b5038d7SDag-Erling Smørgrav /* Abort with an error if BOTH options are defined */ 168*7b5038d7SDag-Erling Smørgrav #error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both! 169*7b5038d7SDag-Erling Smørgrav #endif 170*7b5038d7SDag-Erling Smørgrav 171*7b5038d7SDag-Erling Smørgrav #ifdef SHA2_USE_MEMSET_MEMCPY 172*7b5038d7SDag-Erling Smørgrav #define MEMSET_BZERO(p,l) memset((p), 0, (l)) 173*7b5038d7SDag-Erling Smørgrav #define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l)) 174*7b5038d7SDag-Erling Smørgrav #endif 175*7b5038d7SDag-Erling Smørgrav #ifdef SHA2_USE_BZERO_BCOPY 176*7b5038d7SDag-Erling Smørgrav #define MEMSET_BZERO(p,l) bzero((p), (l)) 177*7b5038d7SDag-Erling Smørgrav #define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l)) 178*7b5038d7SDag-Erling Smørgrav #endif 179*7b5038d7SDag-Erling Smørgrav 180*7b5038d7SDag-Erling Smørgrav 181*7b5038d7SDag-Erling Smørgrav /*** THE SIX LOGICAL FUNCTIONS ****************************************/ 182*7b5038d7SDag-Erling Smørgrav /* 183*7b5038d7SDag-Erling Smørgrav * Bit shifting and rotation (used by the six SHA-XYZ logical functions: 184*7b5038d7SDag-Erling Smørgrav * 185*7b5038d7SDag-Erling Smørgrav * NOTE: The naming of R and S appears backwards here (R is a SHIFT and 186*7b5038d7SDag-Erling Smørgrav * S is a ROTATION) because the SHA-256/384/512 description document 187*7b5038d7SDag-Erling Smørgrav * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this 188*7b5038d7SDag-Erling Smørgrav * same "backwards" definition. 189*7b5038d7SDag-Erling Smørgrav */ 190*7b5038d7SDag-Erling Smørgrav /* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ 191*7b5038d7SDag-Erling Smørgrav #define R(b,x) ((x) >> (b)) 192*7b5038d7SDag-Erling Smørgrav /* 32-bit Rotate-right (used in SHA-256): */ 193*7b5038d7SDag-Erling Smørgrav #define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) 194*7b5038d7SDag-Erling Smørgrav /* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ 195*7b5038d7SDag-Erling Smørgrav #define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) 196*7b5038d7SDag-Erling Smørgrav 197*7b5038d7SDag-Erling Smørgrav /* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ 198*7b5038d7SDag-Erling Smørgrav #define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) 199*7b5038d7SDag-Erling Smørgrav #define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) 200*7b5038d7SDag-Erling Smørgrav 201*7b5038d7SDag-Erling Smørgrav /* Four of six logical functions used in SHA-256: */ 202*7b5038d7SDag-Erling Smørgrav #define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) 203*7b5038d7SDag-Erling Smørgrav #define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) 204*7b5038d7SDag-Erling Smørgrav #define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) 205*7b5038d7SDag-Erling Smørgrav #define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) 206*7b5038d7SDag-Erling Smørgrav 207*7b5038d7SDag-Erling Smørgrav /* Four of six logical functions used in SHA-384 and SHA-512: */ 208*7b5038d7SDag-Erling Smørgrav #define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) 209*7b5038d7SDag-Erling Smørgrav #define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) 210*7b5038d7SDag-Erling Smørgrav #define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) 211*7b5038d7SDag-Erling Smørgrav #define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) 212*7b5038d7SDag-Erling Smørgrav 213*7b5038d7SDag-Erling Smørgrav /*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ 214*7b5038d7SDag-Erling Smørgrav /* Hash constant words K for SHA-256: */ 215*7b5038d7SDag-Erling Smørgrav static const sha2_word32 K256[64] = { 216*7b5038d7SDag-Erling Smørgrav 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 217*7b5038d7SDag-Erling Smørgrav 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 218*7b5038d7SDag-Erling Smørgrav 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, 219*7b5038d7SDag-Erling Smørgrav 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, 220*7b5038d7SDag-Erling Smørgrav 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 221*7b5038d7SDag-Erling Smørgrav 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 222*7b5038d7SDag-Erling Smørgrav 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 223*7b5038d7SDag-Erling Smørgrav 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, 224*7b5038d7SDag-Erling Smørgrav 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, 225*7b5038d7SDag-Erling Smørgrav 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 226*7b5038d7SDag-Erling Smørgrav 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 227*7b5038d7SDag-Erling Smørgrav 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 228*7b5038d7SDag-Erling Smørgrav 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 229*7b5038d7SDag-Erling Smørgrav 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, 230*7b5038d7SDag-Erling Smørgrav 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 231*7b5038d7SDag-Erling Smørgrav 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL 232*7b5038d7SDag-Erling Smørgrav }; 233*7b5038d7SDag-Erling Smørgrav 234*7b5038d7SDag-Erling Smørgrav /* initial hash value H for SHA-256: */ 235*7b5038d7SDag-Erling Smørgrav static const sha2_word32 ldns_sha256_initial_hash_value[8] = { 236*7b5038d7SDag-Erling Smørgrav 0x6a09e667UL, 237*7b5038d7SDag-Erling Smørgrav 0xbb67ae85UL, 238*7b5038d7SDag-Erling Smørgrav 0x3c6ef372UL, 239*7b5038d7SDag-Erling Smørgrav 0xa54ff53aUL, 240*7b5038d7SDag-Erling Smørgrav 0x510e527fUL, 241*7b5038d7SDag-Erling Smørgrav 0x9b05688cUL, 242*7b5038d7SDag-Erling Smørgrav 0x1f83d9abUL, 243*7b5038d7SDag-Erling Smørgrav 0x5be0cd19UL 244*7b5038d7SDag-Erling Smørgrav }; 245*7b5038d7SDag-Erling Smørgrav 246*7b5038d7SDag-Erling Smørgrav /* Hash constant words K for SHA-384 and SHA-512: */ 247*7b5038d7SDag-Erling Smørgrav static const sha2_word64 K512[80] = { 248*7b5038d7SDag-Erling Smørgrav 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 249*7b5038d7SDag-Erling Smørgrav 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 250*7b5038d7SDag-Erling Smørgrav 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 251*7b5038d7SDag-Erling Smørgrav 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 252*7b5038d7SDag-Erling Smørgrav 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 253*7b5038d7SDag-Erling Smørgrav 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 254*7b5038d7SDag-Erling Smørgrav 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 255*7b5038d7SDag-Erling Smørgrav 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, 256*7b5038d7SDag-Erling Smørgrav 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 257*7b5038d7SDag-Erling Smørgrav 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 258*7b5038d7SDag-Erling Smørgrav 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 259*7b5038d7SDag-Erling Smørgrav 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, 260*7b5038d7SDag-Erling Smørgrav 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 261*7b5038d7SDag-Erling Smørgrav 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, 262*7b5038d7SDag-Erling Smørgrav 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 263*7b5038d7SDag-Erling Smørgrav 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 264*7b5038d7SDag-Erling Smørgrav 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 265*7b5038d7SDag-Erling Smørgrav 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, 266*7b5038d7SDag-Erling Smørgrav 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 267*7b5038d7SDag-Erling Smørgrav 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, 268*7b5038d7SDag-Erling Smørgrav 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 269*7b5038d7SDag-Erling Smørgrav 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 270*7b5038d7SDag-Erling Smørgrav 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 271*7b5038d7SDag-Erling Smørgrav 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, 272*7b5038d7SDag-Erling Smørgrav 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 273*7b5038d7SDag-Erling Smørgrav 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, 274*7b5038d7SDag-Erling Smørgrav 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 275*7b5038d7SDag-Erling Smørgrav 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 276*7b5038d7SDag-Erling Smørgrav 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 277*7b5038d7SDag-Erling Smørgrav 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, 278*7b5038d7SDag-Erling Smørgrav 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 279*7b5038d7SDag-Erling Smørgrav 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, 280*7b5038d7SDag-Erling Smørgrav 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 281*7b5038d7SDag-Erling Smørgrav 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 282*7b5038d7SDag-Erling Smørgrav 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 283*7b5038d7SDag-Erling Smørgrav 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, 284*7b5038d7SDag-Erling Smørgrav 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 285*7b5038d7SDag-Erling Smørgrav 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, 286*7b5038d7SDag-Erling Smørgrav 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 287*7b5038d7SDag-Erling Smørgrav 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL 288*7b5038d7SDag-Erling Smørgrav }; 289*7b5038d7SDag-Erling Smørgrav 290*7b5038d7SDag-Erling Smørgrav /* initial hash value H for SHA-384 */ 291*7b5038d7SDag-Erling Smørgrav static const sha2_word64 sha384_initial_hash_value[8] = { 292*7b5038d7SDag-Erling Smørgrav 0xcbbb9d5dc1059ed8ULL, 293*7b5038d7SDag-Erling Smørgrav 0x629a292a367cd507ULL, 294*7b5038d7SDag-Erling Smørgrav 0x9159015a3070dd17ULL, 295*7b5038d7SDag-Erling Smørgrav 0x152fecd8f70e5939ULL, 296*7b5038d7SDag-Erling Smørgrav 0x67332667ffc00b31ULL, 297*7b5038d7SDag-Erling Smørgrav 0x8eb44a8768581511ULL, 298*7b5038d7SDag-Erling Smørgrav 0xdb0c2e0d64f98fa7ULL, 299*7b5038d7SDag-Erling Smørgrav 0x47b5481dbefa4fa4ULL 300*7b5038d7SDag-Erling Smørgrav }; 301*7b5038d7SDag-Erling Smørgrav 302*7b5038d7SDag-Erling Smørgrav /* initial hash value H for SHA-512 */ 303*7b5038d7SDag-Erling Smørgrav static const sha2_word64 sha512_initial_hash_value[8] = { 304*7b5038d7SDag-Erling Smørgrav 0x6a09e667f3bcc908ULL, 305*7b5038d7SDag-Erling Smørgrav 0xbb67ae8584caa73bULL, 306*7b5038d7SDag-Erling Smørgrav 0x3c6ef372fe94f82bULL, 307*7b5038d7SDag-Erling Smørgrav 0xa54ff53a5f1d36f1ULL, 308*7b5038d7SDag-Erling Smørgrav 0x510e527fade682d1ULL, 309*7b5038d7SDag-Erling Smørgrav 0x9b05688c2b3e6c1fULL, 310*7b5038d7SDag-Erling Smørgrav 0x1f83d9abfb41bd6bULL, 311*7b5038d7SDag-Erling Smørgrav 0x5be0cd19137e2179ULL 312*7b5038d7SDag-Erling Smørgrav }; 313*7b5038d7SDag-Erling Smørgrav 314*7b5038d7SDag-Erling Smørgrav /*** SHA-256: *********************************************************/ 315*7b5038d7SDag-Erling Smørgrav void ldns_sha256_init(ldns_sha256_CTX* context) { 316*7b5038d7SDag-Erling Smørgrav if (context == (ldns_sha256_CTX*)0) { 317*7b5038d7SDag-Erling Smørgrav return; 318*7b5038d7SDag-Erling Smørgrav } 319*7b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(context->state, ldns_sha256_initial_hash_value, LDNS_SHA256_DIGEST_LENGTH); 320*7b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context->buffer, LDNS_SHA256_BLOCK_LENGTH); 321*7b5038d7SDag-Erling Smørgrav context->bitcount = 0; 322*7b5038d7SDag-Erling Smørgrav } 323*7b5038d7SDag-Erling Smørgrav 324*7b5038d7SDag-Erling Smørgrav #ifdef SHA2_UNROLL_TRANSFORM 325*7b5038d7SDag-Erling Smørgrav 326*7b5038d7SDag-Erling Smørgrav /* Unrolled SHA-256 round macros: */ 327*7b5038d7SDag-Erling Smørgrav 328*7b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 329*7b5038d7SDag-Erling Smørgrav 330*7b5038d7SDag-Erling Smørgrav #define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ 331*7b5038d7SDag-Erling Smørgrav REVERSE32(*data++, W256[j]); \ 332*7b5038d7SDag-Erling Smørgrav T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ 333*7b5038d7SDag-Erling Smørgrav K256[j] + W256[j]; \ 334*7b5038d7SDag-Erling Smørgrav (d) += T1; \ 335*7b5038d7SDag-Erling Smørgrav (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ 336*7b5038d7SDag-Erling Smørgrav j++ 337*7b5038d7SDag-Erling Smørgrav 338*7b5038d7SDag-Erling Smørgrav 339*7b5038d7SDag-Erling Smørgrav #else /* BYTE_ORDER == LITTLE_ENDIAN */ 340*7b5038d7SDag-Erling Smørgrav 341*7b5038d7SDag-Erling Smørgrav #define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ 342*7b5038d7SDag-Erling Smørgrav T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ 343*7b5038d7SDag-Erling Smørgrav K256[j] + (W256[j] = *data++); \ 344*7b5038d7SDag-Erling Smørgrav (d) += T1; \ 345*7b5038d7SDag-Erling Smørgrav (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ 346*7b5038d7SDag-Erling Smørgrav j++ 347*7b5038d7SDag-Erling Smørgrav 348*7b5038d7SDag-Erling Smørgrav #endif /* BYTE_ORDER == LITTLE_ENDIAN */ 349*7b5038d7SDag-Erling Smørgrav 350*7b5038d7SDag-Erling Smørgrav #define ROUND256(a,b,c,d,e,f,g,h) \ 351*7b5038d7SDag-Erling Smørgrav s0 = W256[(j+1)&0x0f]; \ 352*7b5038d7SDag-Erling Smørgrav s0 = sigma0_256(s0); \ 353*7b5038d7SDag-Erling Smørgrav s1 = W256[(j+14)&0x0f]; \ 354*7b5038d7SDag-Erling Smørgrav s1 = sigma1_256(s1); \ 355*7b5038d7SDag-Erling Smørgrav T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \ 356*7b5038d7SDag-Erling Smørgrav (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ 357*7b5038d7SDag-Erling Smørgrav (d) += T1; \ 358*7b5038d7SDag-Erling Smørgrav (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ 359*7b5038d7SDag-Erling Smørgrav j++ 360*7b5038d7SDag-Erling Smørgrav 361*7b5038d7SDag-Erling Smørgrav static void ldns_sha256_Transform(ldns_sha256_CTX* context, 362*7b5038d7SDag-Erling Smørgrav const sha2_word32* data) { 363*7b5038d7SDag-Erling Smørgrav sha2_word32 a, b, c, d, e, f, g, h, s0, s1; 364*7b5038d7SDag-Erling Smørgrav sha2_word32 T1, *W256; 365*7b5038d7SDag-Erling Smørgrav int j; 366*7b5038d7SDag-Erling Smørgrav 367*7b5038d7SDag-Erling Smørgrav W256 = (sha2_word32*)context->buffer; 368*7b5038d7SDag-Erling Smørgrav 369*7b5038d7SDag-Erling Smørgrav /* initialize registers with the prev. intermediate value */ 370*7b5038d7SDag-Erling Smørgrav a = context->state[0]; 371*7b5038d7SDag-Erling Smørgrav b = context->state[1]; 372*7b5038d7SDag-Erling Smørgrav c = context->state[2]; 373*7b5038d7SDag-Erling Smørgrav d = context->state[3]; 374*7b5038d7SDag-Erling Smørgrav e = context->state[4]; 375*7b5038d7SDag-Erling Smørgrav f = context->state[5]; 376*7b5038d7SDag-Erling Smørgrav g = context->state[6]; 377*7b5038d7SDag-Erling Smørgrav h = context->state[7]; 378*7b5038d7SDag-Erling Smørgrav 379*7b5038d7SDag-Erling Smørgrav j = 0; 380*7b5038d7SDag-Erling Smørgrav do { 381*7b5038d7SDag-Erling Smørgrav /* Rounds 0 to 15 (unrolled): */ 382*7b5038d7SDag-Erling Smørgrav ROUND256_0_TO_15(a,b,c,d,e,f,g,h); 383*7b5038d7SDag-Erling Smørgrav ROUND256_0_TO_15(h,a,b,c,d,e,f,g); 384*7b5038d7SDag-Erling Smørgrav ROUND256_0_TO_15(g,h,a,b,c,d,e,f); 385*7b5038d7SDag-Erling Smørgrav ROUND256_0_TO_15(f,g,h,a,b,c,d,e); 386*7b5038d7SDag-Erling Smørgrav ROUND256_0_TO_15(e,f,g,h,a,b,c,d); 387*7b5038d7SDag-Erling Smørgrav ROUND256_0_TO_15(d,e,f,g,h,a,b,c); 388*7b5038d7SDag-Erling Smørgrav ROUND256_0_TO_15(c,d,e,f,g,h,a,b); 389*7b5038d7SDag-Erling Smørgrav ROUND256_0_TO_15(b,c,d,e,f,g,h,a); 390*7b5038d7SDag-Erling Smørgrav } while (j < 16); 391*7b5038d7SDag-Erling Smørgrav 392*7b5038d7SDag-Erling Smørgrav /* Now for the remaining rounds to 64: */ 393*7b5038d7SDag-Erling Smørgrav do { 394*7b5038d7SDag-Erling Smørgrav ROUND256(a,b,c,d,e,f,g,h); 395*7b5038d7SDag-Erling Smørgrav ROUND256(h,a,b,c,d,e,f,g); 396*7b5038d7SDag-Erling Smørgrav ROUND256(g,h,a,b,c,d,e,f); 397*7b5038d7SDag-Erling Smørgrav ROUND256(f,g,h,a,b,c,d,e); 398*7b5038d7SDag-Erling Smørgrav ROUND256(e,f,g,h,a,b,c,d); 399*7b5038d7SDag-Erling Smørgrav ROUND256(d,e,f,g,h,a,b,c); 400*7b5038d7SDag-Erling Smørgrav ROUND256(c,d,e,f,g,h,a,b); 401*7b5038d7SDag-Erling Smørgrav ROUND256(b,c,d,e,f,g,h,a); 402*7b5038d7SDag-Erling Smørgrav } while (j < 64); 403*7b5038d7SDag-Erling Smørgrav 404*7b5038d7SDag-Erling Smørgrav /* Compute the current intermediate hash value */ 405*7b5038d7SDag-Erling Smørgrav context->state[0] += a; 406*7b5038d7SDag-Erling Smørgrav context->state[1] += b; 407*7b5038d7SDag-Erling Smørgrav context->state[2] += c; 408*7b5038d7SDag-Erling Smørgrav context->state[3] += d; 409*7b5038d7SDag-Erling Smørgrav context->state[4] += e; 410*7b5038d7SDag-Erling Smørgrav context->state[5] += f; 411*7b5038d7SDag-Erling Smørgrav context->state[6] += g; 412*7b5038d7SDag-Erling Smørgrav context->state[7] += h; 413*7b5038d7SDag-Erling Smørgrav 414*7b5038d7SDag-Erling Smørgrav /* Clean up */ 415*7b5038d7SDag-Erling Smørgrav a = b = c = d = e = f = g = h = T1 = 0; 416*7b5038d7SDag-Erling Smørgrav } 417*7b5038d7SDag-Erling Smørgrav 418*7b5038d7SDag-Erling Smørgrav #else /* SHA2_UNROLL_TRANSFORM */ 419*7b5038d7SDag-Erling Smørgrav 420*7b5038d7SDag-Erling Smørgrav static void ldns_sha256_Transform(ldns_sha256_CTX* context, 421*7b5038d7SDag-Erling Smørgrav const sha2_word32* data) { 422*7b5038d7SDag-Erling Smørgrav sha2_word32 a, b, c, d, e, f, g, h, s0, s1; 423*7b5038d7SDag-Erling Smørgrav sha2_word32 T1, T2, *W256; 424*7b5038d7SDag-Erling Smørgrav int j; 425*7b5038d7SDag-Erling Smørgrav 426*7b5038d7SDag-Erling Smørgrav W256 = (sha2_word32*)context->buffer; 427*7b5038d7SDag-Erling Smørgrav 428*7b5038d7SDag-Erling Smørgrav /* initialize registers with the prev. intermediate value */ 429*7b5038d7SDag-Erling Smørgrav a = context->state[0]; 430*7b5038d7SDag-Erling Smørgrav b = context->state[1]; 431*7b5038d7SDag-Erling Smørgrav c = context->state[2]; 432*7b5038d7SDag-Erling Smørgrav d = context->state[3]; 433*7b5038d7SDag-Erling Smørgrav e = context->state[4]; 434*7b5038d7SDag-Erling Smørgrav f = context->state[5]; 435*7b5038d7SDag-Erling Smørgrav g = context->state[6]; 436*7b5038d7SDag-Erling Smørgrav h = context->state[7]; 437*7b5038d7SDag-Erling Smørgrav 438*7b5038d7SDag-Erling Smørgrav j = 0; 439*7b5038d7SDag-Erling Smørgrav do { 440*7b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 441*7b5038d7SDag-Erling Smørgrav /* Copy data while converting to host byte order */ 442*7b5038d7SDag-Erling Smørgrav REVERSE32(*data++,W256[j]); 443*7b5038d7SDag-Erling Smørgrav /* Apply the SHA-256 compression function to update a..h */ 444*7b5038d7SDag-Erling Smørgrav T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; 445*7b5038d7SDag-Erling Smørgrav #else /* BYTE_ORDER == LITTLE_ENDIAN */ 446*7b5038d7SDag-Erling Smørgrav /* Apply the SHA-256 compression function to update a..h with copy */ 447*7b5038d7SDag-Erling Smørgrav T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++); 448*7b5038d7SDag-Erling Smørgrav #endif /* BYTE_ORDER == LITTLE_ENDIAN */ 449*7b5038d7SDag-Erling Smørgrav T2 = Sigma0_256(a) + Maj(a, b, c); 450*7b5038d7SDag-Erling Smørgrav h = g; 451*7b5038d7SDag-Erling Smørgrav g = f; 452*7b5038d7SDag-Erling Smørgrav f = e; 453*7b5038d7SDag-Erling Smørgrav e = d + T1; 454*7b5038d7SDag-Erling Smørgrav d = c; 455*7b5038d7SDag-Erling Smørgrav c = b; 456*7b5038d7SDag-Erling Smørgrav b = a; 457*7b5038d7SDag-Erling Smørgrav a = T1 + T2; 458*7b5038d7SDag-Erling Smørgrav 459*7b5038d7SDag-Erling Smørgrav j++; 460*7b5038d7SDag-Erling Smørgrav } while (j < 16); 461*7b5038d7SDag-Erling Smørgrav 462*7b5038d7SDag-Erling Smørgrav do { 463*7b5038d7SDag-Erling Smørgrav /* Part of the message block expansion: */ 464*7b5038d7SDag-Erling Smørgrav s0 = W256[(j+1)&0x0f]; 465*7b5038d7SDag-Erling Smørgrav s0 = sigma0_256(s0); 466*7b5038d7SDag-Erling Smørgrav s1 = W256[(j+14)&0x0f]; 467*7b5038d7SDag-Erling Smørgrav s1 = sigma1_256(s1); 468*7b5038d7SDag-Erling Smørgrav 469*7b5038d7SDag-Erling Smørgrav /* Apply the SHA-256 compression function to update a..h */ 470*7b5038d7SDag-Erling Smørgrav T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + 471*7b5038d7SDag-Erling Smørgrav (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); 472*7b5038d7SDag-Erling Smørgrav T2 = Sigma0_256(a) + Maj(a, b, c); 473*7b5038d7SDag-Erling Smørgrav h = g; 474*7b5038d7SDag-Erling Smørgrav g = f; 475*7b5038d7SDag-Erling Smørgrav f = e; 476*7b5038d7SDag-Erling Smørgrav e = d + T1; 477*7b5038d7SDag-Erling Smørgrav d = c; 478*7b5038d7SDag-Erling Smørgrav c = b; 479*7b5038d7SDag-Erling Smørgrav b = a; 480*7b5038d7SDag-Erling Smørgrav a = T1 + T2; 481*7b5038d7SDag-Erling Smørgrav 482*7b5038d7SDag-Erling Smørgrav j++; 483*7b5038d7SDag-Erling Smørgrav } while (j < 64); 484*7b5038d7SDag-Erling Smørgrav 485*7b5038d7SDag-Erling Smørgrav /* Compute the current intermediate hash value */ 486*7b5038d7SDag-Erling Smørgrav context->state[0] += a; 487*7b5038d7SDag-Erling Smørgrav context->state[1] += b; 488*7b5038d7SDag-Erling Smørgrav context->state[2] += c; 489*7b5038d7SDag-Erling Smørgrav context->state[3] += d; 490*7b5038d7SDag-Erling Smørgrav context->state[4] += e; 491*7b5038d7SDag-Erling Smørgrav context->state[5] += f; 492*7b5038d7SDag-Erling Smørgrav context->state[6] += g; 493*7b5038d7SDag-Erling Smørgrav context->state[7] += h; 494*7b5038d7SDag-Erling Smørgrav 495*7b5038d7SDag-Erling Smørgrav /* Clean up */ 496*7b5038d7SDag-Erling Smørgrav a = b = c = d = e = f = g = h = T1 = T2 = 0; 497*7b5038d7SDag-Erling Smørgrav } 498*7b5038d7SDag-Erling Smørgrav 499*7b5038d7SDag-Erling Smørgrav #endif /* SHA2_UNROLL_TRANSFORM */ 500*7b5038d7SDag-Erling Smørgrav 501*7b5038d7SDag-Erling Smørgrav void ldns_sha256_update(ldns_sha256_CTX* context, const sha2_byte *data, size_t len) { 502*7b5038d7SDag-Erling Smørgrav size_t freespace, usedspace; 503*7b5038d7SDag-Erling Smørgrav 504*7b5038d7SDag-Erling Smørgrav if (len == 0) { 505*7b5038d7SDag-Erling Smørgrav /* Calling with no data is valid - we do nothing */ 506*7b5038d7SDag-Erling Smørgrav return; 507*7b5038d7SDag-Erling Smørgrav } 508*7b5038d7SDag-Erling Smørgrav 509*7b5038d7SDag-Erling Smørgrav /* Sanity check: */ 510*7b5038d7SDag-Erling Smørgrav assert(context != (ldns_sha256_CTX*)0 && data != (sha2_byte*)0); 511*7b5038d7SDag-Erling Smørgrav 512*7b5038d7SDag-Erling Smørgrav usedspace = (context->bitcount >> 3) % LDNS_SHA256_BLOCK_LENGTH; 513*7b5038d7SDag-Erling Smørgrav if (usedspace > 0) { 514*7b5038d7SDag-Erling Smørgrav /* Calculate how much free space is available in the buffer */ 515*7b5038d7SDag-Erling Smørgrav freespace = LDNS_SHA256_BLOCK_LENGTH - usedspace; 516*7b5038d7SDag-Erling Smørgrav 517*7b5038d7SDag-Erling Smørgrav if (len >= freespace) { 518*7b5038d7SDag-Erling Smørgrav /* Fill the buffer completely and process it */ 519*7b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); 520*7b5038d7SDag-Erling Smørgrav context->bitcount += freespace << 3; 521*7b5038d7SDag-Erling Smørgrav len -= freespace; 522*7b5038d7SDag-Erling Smørgrav data += freespace; 523*7b5038d7SDag-Erling Smørgrav ldns_sha256_Transform(context, (sha2_word32*)context->buffer); 524*7b5038d7SDag-Erling Smørgrav } else { 525*7b5038d7SDag-Erling Smørgrav /* The buffer is not yet full */ 526*7b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(&context->buffer[usedspace], data, len); 527*7b5038d7SDag-Erling Smørgrav context->bitcount += len << 3; 528*7b5038d7SDag-Erling Smørgrav /* Clean up: */ 529*7b5038d7SDag-Erling Smørgrav usedspace = freespace = 0; 530*7b5038d7SDag-Erling Smørgrav return; 531*7b5038d7SDag-Erling Smørgrav } 532*7b5038d7SDag-Erling Smørgrav } 533*7b5038d7SDag-Erling Smørgrav while (len >= LDNS_SHA256_BLOCK_LENGTH) { 534*7b5038d7SDag-Erling Smørgrav /* Process as many complete blocks as we can */ 535*7b5038d7SDag-Erling Smørgrav ldns_sha256_Transform(context, (sha2_word32*)data); 536*7b5038d7SDag-Erling Smørgrav context->bitcount += LDNS_SHA256_BLOCK_LENGTH << 3; 537*7b5038d7SDag-Erling Smørgrav len -= LDNS_SHA256_BLOCK_LENGTH; 538*7b5038d7SDag-Erling Smørgrav data += LDNS_SHA256_BLOCK_LENGTH; 539*7b5038d7SDag-Erling Smørgrav } 540*7b5038d7SDag-Erling Smørgrav if (len > 0) { 541*7b5038d7SDag-Erling Smørgrav /* There's left-overs, so save 'em */ 542*7b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(context->buffer, data, len); 543*7b5038d7SDag-Erling Smørgrav context->bitcount += len << 3; 544*7b5038d7SDag-Erling Smørgrav } 545*7b5038d7SDag-Erling Smørgrav /* Clean up: */ 546*7b5038d7SDag-Erling Smørgrav usedspace = freespace = 0; 547*7b5038d7SDag-Erling Smørgrav } 548*7b5038d7SDag-Erling Smørgrav 549*7b5038d7SDag-Erling Smørgrav void ldns_sha256_final(sha2_byte digest[], ldns_sha256_CTX* context) { 550*7b5038d7SDag-Erling Smørgrav sha2_word32 *d = (sha2_word32*)digest; 551*7b5038d7SDag-Erling Smørgrav size_t usedspace; 552*7b5038d7SDag-Erling Smørgrav 553*7b5038d7SDag-Erling Smørgrav /* Sanity check: */ 554*7b5038d7SDag-Erling Smørgrav assert(context != (ldns_sha256_CTX*)0); 555*7b5038d7SDag-Erling Smørgrav 556*7b5038d7SDag-Erling Smørgrav /* If no digest buffer is passed, we don't bother doing this: */ 557*7b5038d7SDag-Erling Smørgrav if (digest != (sha2_byte*)0) { 558*7b5038d7SDag-Erling Smørgrav usedspace = (context->bitcount >> 3) % LDNS_SHA256_BLOCK_LENGTH; 559*7b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 560*7b5038d7SDag-Erling Smørgrav /* Convert FROM host byte order */ 561*7b5038d7SDag-Erling Smørgrav REVERSE64(context->bitcount,context->bitcount); 562*7b5038d7SDag-Erling Smørgrav #endif 563*7b5038d7SDag-Erling Smørgrav if (usedspace > 0) { 564*7b5038d7SDag-Erling Smørgrav /* Begin padding with a 1 bit: */ 565*7b5038d7SDag-Erling Smørgrav context->buffer[usedspace++] = 0x80; 566*7b5038d7SDag-Erling Smørgrav 567*7b5038d7SDag-Erling Smørgrav if (usedspace <= ldns_sha256_SHORT_BLOCK_LENGTH) { 568*7b5038d7SDag-Erling Smørgrav /* Set-up for the last transform: */ 569*7b5038d7SDag-Erling Smørgrav MEMSET_BZERO(&context->buffer[usedspace], ldns_sha256_SHORT_BLOCK_LENGTH - usedspace); 570*7b5038d7SDag-Erling Smørgrav } else { 571*7b5038d7SDag-Erling Smørgrav if (usedspace < LDNS_SHA256_BLOCK_LENGTH) { 572*7b5038d7SDag-Erling Smørgrav MEMSET_BZERO(&context->buffer[usedspace], LDNS_SHA256_BLOCK_LENGTH - usedspace); 573*7b5038d7SDag-Erling Smørgrav } 574*7b5038d7SDag-Erling Smørgrav /* Do second-to-last transform: */ 575*7b5038d7SDag-Erling Smørgrav ldns_sha256_Transform(context, (sha2_word32*)context->buffer); 576*7b5038d7SDag-Erling Smørgrav 577*7b5038d7SDag-Erling Smørgrav /* And set-up for the last transform: */ 578*7b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context->buffer, ldns_sha256_SHORT_BLOCK_LENGTH); 579*7b5038d7SDag-Erling Smørgrav } 580*7b5038d7SDag-Erling Smørgrav } else { 581*7b5038d7SDag-Erling Smørgrav /* Set-up for the last transform: */ 582*7b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context->buffer, ldns_sha256_SHORT_BLOCK_LENGTH); 583*7b5038d7SDag-Erling Smørgrav 584*7b5038d7SDag-Erling Smørgrav /* Begin padding with a 1 bit: */ 585*7b5038d7SDag-Erling Smørgrav *context->buffer = 0x80; 586*7b5038d7SDag-Erling Smørgrav } 587*7b5038d7SDag-Erling Smørgrav /* Set the bit count: */ 588*7b5038d7SDag-Erling Smørgrav *(sha2_word64*)&context->buffer[ldns_sha256_SHORT_BLOCK_LENGTH] = context->bitcount; 589*7b5038d7SDag-Erling Smørgrav 590*7b5038d7SDag-Erling Smørgrav /* final transform: */ 591*7b5038d7SDag-Erling Smørgrav ldns_sha256_Transform(context, (sha2_word32*)context->buffer); 592*7b5038d7SDag-Erling Smørgrav 593*7b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 594*7b5038d7SDag-Erling Smørgrav { 595*7b5038d7SDag-Erling Smørgrav /* Convert TO host byte order */ 596*7b5038d7SDag-Erling Smørgrav int j; 597*7b5038d7SDag-Erling Smørgrav for (j = 0; j < 8; j++) { 598*7b5038d7SDag-Erling Smørgrav REVERSE32(context->state[j],context->state[j]); 599*7b5038d7SDag-Erling Smørgrav *d++ = context->state[j]; 600*7b5038d7SDag-Erling Smørgrav } 601*7b5038d7SDag-Erling Smørgrav } 602*7b5038d7SDag-Erling Smørgrav #else 603*7b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(d, context->state, LDNS_SHA256_DIGEST_LENGTH); 604*7b5038d7SDag-Erling Smørgrav #endif 605*7b5038d7SDag-Erling Smørgrav } 606*7b5038d7SDag-Erling Smørgrav 607*7b5038d7SDag-Erling Smørgrav /* Clean up state data: */ 608*7b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context, sizeof(ldns_sha256_CTX)); 609*7b5038d7SDag-Erling Smørgrav usedspace = 0; 610*7b5038d7SDag-Erling Smørgrav } 611*7b5038d7SDag-Erling Smørgrav 612*7b5038d7SDag-Erling Smørgrav unsigned char * 613*7b5038d7SDag-Erling Smørgrav ldns_sha256(unsigned char *data, unsigned int data_len, unsigned char *digest) 614*7b5038d7SDag-Erling Smørgrav { 615*7b5038d7SDag-Erling Smørgrav ldns_sha256_CTX ctx; 616*7b5038d7SDag-Erling Smørgrav ldns_sha256_init(&ctx); 617*7b5038d7SDag-Erling Smørgrav ldns_sha256_update(&ctx, data, data_len); 618*7b5038d7SDag-Erling Smørgrav ldns_sha256_final(digest, &ctx); 619*7b5038d7SDag-Erling Smørgrav return digest; 620*7b5038d7SDag-Erling Smørgrav } 621*7b5038d7SDag-Erling Smørgrav 622*7b5038d7SDag-Erling Smørgrav /*** SHA-512: *********************************************************/ 623*7b5038d7SDag-Erling Smørgrav void ldns_sha512_init(ldns_sha512_CTX* context) { 624*7b5038d7SDag-Erling Smørgrav if (context == (ldns_sha512_CTX*)0) { 625*7b5038d7SDag-Erling Smørgrav return; 626*7b5038d7SDag-Erling Smørgrav } 627*7b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(context->state, sha512_initial_hash_value, LDNS_SHA512_DIGEST_LENGTH); 628*7b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context->buffer, LDNS_SHA512_BLOCK_LENGTH); 629*7b5038d7SDag-Erling Smørgrav context->bitcount[0] = context->bitcount[1] = 0; 630*7b5038d7SDag-Erling Smørgrav } 631*7b5038d7SDag-Erling Smørgrav 632*7b5038d7SDag-Erling Smørgrav #ifdef SHA2_UNROLL_TRANSFORM 633*7b5038d7SDag-Erling Smørgrav 634*7b5038d7SDag-Erling Smørgrav /* Unrolled SHA-512 round macros: */ 635*7b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 636*7b5038d7SDag-Erling Smørgrav 637*7b5038d7SDag-Erling Smørgrav #define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ 638*7b5038d7SDag-Erling Smørgrav REVERSE64(*data++, W512[j]); \ 639*7b5038d7SDag-Erling Smørgrav T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ 640*7b5038d7SDag-Erling Smørgrav K512[j] + W512[j]; \ 641*7b5038d7SDag-Erling Smørgrav (d) += T1, \ 642*7b5038d7SDag-Erling Smørgrav (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \ 643*7b5038d7SDag-Erling Smørgrav j++ 644*7b5038d7SDag-Erling Smørgrav 645*7b5038d7SDag-Erling Smørgrav 646*7b5038d7SDag-Erling Smørgrav #else /* BYTE_ORDER == LITTLE_ENDIAN */ 647*7b5038d7SDag-Erling Smørgrav 648*7b5038d7SDag-Erling Smørgrav #define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ 649*7b5038d7SDag-Erling Smørgrav T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ 650*7b5038d7SDag-Erling Smørgrav K512[j] + (W512[j] = *data++); \ 651*7b5038d7SDag-Erling Smørgrav (d) += T1; \ 652*7b5038d7SDag-Erling Smørgrav (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ 653*7b5038d7SDag-Erling Smørgrav j++ 654*7b5038d7SDag-Erling Smørgrav 655*7b5038d7SDag-Erling Smørgrav #endif /* BYTE_ORDER == LITTLE_ENDIAN */ 656*7b5038d7SDag-Erling Smørgrav 657*7b5038d7SDag-Erling Smørgrav #define ROUND512(a,b,c,d,e,f,g,h) \ 658*7b5038d7SDag-Erling Smørgrav s0 = W512[(j+1)&0x0f]; \ 659*7b5038d7SDag-Erling Smørgrav s0 = sigma0_512(s0); \ 660*7b5038d7SDag-Erling Smørgrav s1 = W512[(j+14)&0x0f]; \ 661*7b5038d7SDag-Erling Smørgrav s1 = sigma1_512(s1); \ 662*7b5038d7SDag-Erling Smørgrav T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \ 663*7b5038d7SDag-Erling Smørgrav (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ 664*7b5038d7SDag-Erling Smørgrav (d) += T1; \ 665*7b5038d7SDag-Erling Smørgrav (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ 666*7b5038d7SDag-Erling Smørgrav j++ 667*7b5038d7SDag-Erling Smørgrav 668*7b5038d7SDag-Erling Smørgrav static void ldns_sha512_Transform(ldns_sha512_CTX* context, 669*7b5038d7SDag-Erling Smørgrav const sha2_word64* data) { 670*7b5038d7SDag-Erling Smørgrav sha2_word64 a, b, c, d, e, f, g, h, s0, s1; 671*7b5038d7SDag-Erling Smørgrav sha2_word64 T1, *W512 = (sha2_word64*)context->buffer; 672*7b5038d7SDag-Erling Smørgrav int j; 673*7b5038d7SDag-Erling Smørgrav 674*7b5038d7SDag-Erling Smørgrav /* initialize registers with the prev. intermediate value */ 675*7b5038d7SDag-Erling Smørgrav a = context->state[0]; 676*7b5038d7SDag-Erling Smørgrav b = context->state[1]; 677*7b5038d7SDag-Erling Smørgrav c = context->state[2]; 678*7b5038d7SDag-Erling Smørgrav d = context->state[3]; 679*7b5038d7SDag-Erling Smørgrav e = context->state[4]; 680*7b5038d7SDag-Erling Smørgrav f = context->state[5]; 681*7b5038d7SDag-Erling Smørgrav g = context->state[6]; 682*7b5038d7SDag-Erling Smørgrav h = context->state[7]; 683*7b5038d7SDag-Erling Smørgrav 684*7b5038d7SDag-Erling Smørgrav j = 0; 685*7b5038d7SDag-Erling Smørgrav do { 686*7b5038d7SDag-Erling Smørgrav ROUND512_0_TO_15(a,b,c,d,e,f,g,h); 687*7b5038d7SDag-Erling Smørgrav ROUND512_0_TO_15(h,a,b,c,d,e,f,g); 688*7b5038d7SDag-Erling Smørgrav ROUND512_0_TO_15(g,h,a,b,c,d,e,f); 689*7b5038d7SDag-Erling Smørgrav ROUND512_0_TO_15(f,g,h,a,b,c,d,e); 690*7b5038d7SDag-Erling Smørgrav ROUND512_0_TO_15(e,f,g,h,a,b,c,d); 691*7b5038d7SDag-Erling Smørgrav ROUND512_0_TO_15(d,e,f,g,h,a,b,c); 692*7b5038d7SDag-Erling Smørgrav ROUND512_0_TO_15(c,d,e,f,g,h,a,b); 693*7b5038d7SDag-Erling Smørgrav ROUND512_0_TO_15(b,c,d,e,f,g,h,a); 694*7b5038d7SDag-Erling Smørgrav } while (j < 16); 695*7b5038d7SDag-Erling Smørgrav 696*7b5038d7SDag-Erling Smørgrav /* Now for the remaining rounds up to 79: */ 697*7b5038d7SDag-Erling Smørgrav do { 698*7b5038d7SDag-Erling Smørgrav ROUND512(a,b,c,d,e,f,g,h); 699*7b5038d7SDag-Erling Smørgrav ROUND512(h,a,b,c,d,e,f,g); 700*7b5038d7SDag-Erling Smørgrav ROUND512(g,h,a,b,c,d,e,f); 701*7b5038d7SDag-Erling Smørgrav ROUND512(f,g,h,a,b,c,d,e); 702*7b5038d7SDag-Erling Smørgrav ROUND512(e,f,g,h,a,b,c,d); 703*7b5038d7SDag-Erling Smørgrav ROUND512(d,e,f,g,h,a,b,c); 704*7b5038d7SDag-Erling Smørgrav ROUND512(c,d,e,f,g,h,a,b); 705*7b5038d7SDag-Erling Smørgrav ROUND512(b,c,d,e,f,g,h,a); 706*7b5038d7SDag-Erling Smørgrav } while (j < 80); 707*7b5038d7SDag-Erling Smørgrav 708*7b5038d7SDag-Erling Smørgrav /* Compute the current intermediate hash value */ 709*7b5038d7SDag-Erling Smørgrav context->state[0] += a; 710*7b5038d7SDag-Erling Smørgrav context->state[1] += b; 711*7b5038d7SDag-Erling Smørgrav context->state[2] += c; 712*7b5038d7SDag-Erling Smørgrav context->state[3] += d; 713*7b5038d7SDag-Erling Smørgrav context->state[4] += e; 714*7b5038d7SDag-Erling Smørgrav context->state[5] += f; 715*7b5038d7SDag-Erling Smørgrav context->state[6] += g; 716*7b5038d7SDag-Erling Smørgrav context->state[7] += h; 717*7b5038d7SDag-Erling Smørgrav 718*7b5038d7SDag-Erling Smørgrav /* Clean up */ 719*7b5038d7SDag-Erling Smørgrav a = b = c = d = e = f = g = h = T1 = 0; 720*7b5038d7SDag-Erling Smørgrav } 721*7b5038d7SDag-Erling Smørgrav 722*7b5038d7SDag-Erling Smørgrav #else /* SHA2_UNROLL_TRANSFORM */ 723*7b5038d7SDag-Erling Smørgrav 724*7b5038d7SDag-Erling Smørgrav static void ldns_sha512_Transform(ldns_sha512_CTX* context, 725*7b5038d7SDag-Erling Smørgrav const sha2_word64* data) { 726*7b5038d7SDag-Erling Smørgrav sha2_word64 a, b, c, d, e, f, g, h, s0, s1; 727*7b5038d7SDag-Erling Smørgrav sha2_word64 T1, T2, *W512 = (sha2_word64*)context->buffer; 728*7b5038d7SDag-Erling Smørgrav int j; 729*7b5038d7SDag-Erling Smørgrav 730*7b5038d7SDag-Erling Smørgrav /* initialize registers with the prev. intermediate value */ 731*7b5038d7SDag-Erling Smørgrav a = context->state[0]; 732*7b5038d7SDag-Erling Smørgrav b = context->state[1]; 733*7b5038d7SDag-Erling Smørgrav c = context->state[2]; 734*7b5038d7SDag-Erling Smørgrav d = context->state[3]; 735*7b5038d7SDag-Erling Smørgrav e = context->state[4]; 736*7b5038d7SDag-Erling Smørgrav f = context->state[5]; 737*7b5038d7SDag-Erling Smørgrav g = context->state[6]; 738*7b5038d7SDag-Erling Smørgrav h = context->state[7]; 739*7b5038d7SDag-Erling Smørgrav 740*7b5038d7SDag-Erling Smørgrav j = 0; 741*7b5038d7SDag-Erling Smørgrav do { 742*7b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 743*7b5038d7SDag-Erling Smørgrav /* Convert TO host byte order */ 744*7b5038d7SDag-Erling Smørgrav REVERSE64(*data++, W512[j]); 745*7b5038d7SDag-Erling Smørgrav /* Apply the SHA-512 compression function to update a..h */ 746*7b5038d7SDag-Erling Smørgrav T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; 747*7b5038d7SDag-Erling Smørgrav #else /* BYTE_ORDER == LITTLE_ENDIAN */ 748*7b5038d7SDag-Erling Smørgrav /* Apply the SHA-512 compression function to update a..h with copy */ 749*7b5038d7SDag-Erling Smørgrav T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++); 750*7b5038d7SDag-Erling Smørgrav #endif /* BYTE_ORDER == LITTLE_ENDIAN */ 751*7b5038d7SDag-Erling Smørgrav T2 = Sigma0_512(a) + Maj(a, b, c); 752*7b5038d7SDag-Erling Smørgrav h = g; 753*7b5038d7SDag-Erling Smørgrav g = f; 754*7b5038d7SDag-Erling Smørgrav f = e; 755*7b5038d7SDag-Erling Smørgrav e = d + T1; 756*7b5038d7SDag-Erling Smørgrav d = c; 757*7b5038d7SDag-Erling Smørgrav c = b; 758*7b5038d7SDag-Erling Smørgrav b = a; 759*7b5038d7SDag-Erling Smørgrav a = T1 + T2; 760*7b5038d7SDag-Erling Smørgrav 761*7b5038d7SDag-Erling Smørgrav j++; 762*7b5038d7SDag-Erling Smørgrav } while (j < 16); 763*7b5038d7SDag-Erling Smørgrav 764*7b5038d7SDag-Erling Smørgrav do { 765*7b5038d7SDag-Erling Smørgrav /* Part of the message block expansion: */ 766*7b5038d7SDag-Erling Smørgrav s0 = W512[(j+1)&0x0f]; 767*7b5038d7SDag-Erling Smørgrav s0 = sigma0_512(s0); 768*7b5038d7SDag-Erling Smørgrav s1 = W512[(j+14)&0x0f]; 769*7b5038d7SDag-Erling Smørgrav s1 = sigma1_512(s1); 770*7b5038d7SDag-Erling Smørgrav 771*7b5038d7SDag-Erling Smørgrav /* Apply the SHA-512 compression function to update a..h */ 772*7b5038d7SDag-Erling Smørgrav T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + 773*7b5038d7SDag-Erling Smørgrav (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); 774*7b5038d7SDag-Erling Smørgrav T2 = Sigma0_512(a) + Maj(a, b, c); 775*7b5038d7SDag-Erling Smørgrav h = g; 776*7b5038d7SDag-Erling Smørgrav g = f; 777*7b5038d7SDag-Erling Smørgrav f = e; 778*7b5038d7SDag-Erling Smørgrav e = d + T1; 779*7b5038d7SDag-Erling Smørgrav d = c; 780*7b5038d7SDag-Erling Smørgrav c = b; 781*7b5038d7SDag-Erling Smørgrav b = a; 782*7b5038d7SDag-Erling Smørgrav a = T1 + T2; 783*7b5038d7SDag-Erling Smørgrav 784*7b5038d7SDag-Erling Smørgrav j++; 785*7b5038d7SDag-Erling Smørgrav } while (j < 80); 786*7b5038d7SDag-Erling Smørgrav 787*7b5038d7SDag-Erling Smørgrav /* Compute the current intermediate hash value */ 788*7b5038d7SDag-Erling Smørgrav context->state[0] += a; 789*7b5038d7SDag-Erling Smørgrav context->state[1] += b; 790*7b5038d7SDag-Erling Smørgrav context->state[2] += c; 791*7b5038d7SDag-Erling Smørgrav context->state[3] += d; 792*7b5038d7SDag-Erling Smørgrav context->state[4] += e; 793*7b5038d7SDag-Erling Smørgrav context->state[5] += f; 794*7b5038d7SDag-Erling Smørgrav context->state[6] += g; 795*7b5038d7SDag-Erling Smørgrav context->state[7] += h; 796*7b5038d7SDag-Erling Smørgrav 797*7b5038d7SDag-Erling Smørgrav /* Clean up */ 798*7b5038d7SDag-Erling Smørgrav a = b = c = d = e = f = g = h = T1 = T2 = 0; 799*7b5038d7SDag-Erling Smørgrav } 800*7b5038d7SDag-Erling Smørgrav 801*7b5038d7SDag-Erling Smørgrav #endif /* SHA2_UNROLL_TRANSFORM */ 802*7b5038d7SDag-Erling Smørgrav 803*7b5038d7SDag-Erling Smørgrav void ldns_sha512_update(ldns_sha512_CTX* context, const sha2_byte *data, size_t len) { 804*7b5038d7SDag-Erling Smørgrav size_t freespace, usedspace; 805*7b5038d7SDag-Erling Smørgrav 806*7b5038d7SDag-Erling Smørgrav if (len == 0) { 807*7b5038d7SDag-Erling Smørgrav /* Calling with no data is valid - we do nothing */ 808*7b5038d7SDag-Erling Smørgrav return; 809*7b5038d7SDag-Erling Smørgrav } 810*7b5038d7SDag-Erling Smørgrav 811*7b5038d7SDag-Erling Smørgrav /* Sanity check: */ 812*7b5038d7SDag-Erling Smørgrav assert(context != (ldns_sha512_CTX*)0 && data != (sha2_byte*)0); 813*7b5038d7SDag-Erling Smørgrav 814*7b5038d7SDag-Erling Smørgrav usedspace = (context->bitcount[0] >> 3) % LDNS_SHA512_BLOCK_LENGTH; 815*7b5038d7SDag-Erling Smørgrav if (usedspace > 0) { 816*7b5038d7SDag-Erling Smørgrav /* Calculate how much free space is available in the buffer */ 817*7b5038d7SDag-Erling Smørgrav freespace = LDNS_SHA512_BLOCK_LENGTH - usedspace; 818*7b5038d7SDag-Erling Smørgrav 819*7b5038d7SDag-Erling Smørgrav if (len >= freespace) { 820*7b5038d7SDag-Erling Smørgrav /* Fill the buffer completely and process it */ 821*7b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); 822*7b5038d7SDag-Erling Smørgrav ADDINC128(context->bitcount, freespace << 3); 823*7b5038d7SDag-Erling Smørgrav len -= freespace; 824*7b5038d7SDag-Erling Smørgrav data += freespace; 825*7b5038d7SDag-Erling Smørgrav ldns_sha512_Transform(context, (sha2_word64*)context->buffer); 826*7b5038d7SDag-Erling Smørgrav } else { 827*7b5038d7SDag-Erling Smørgrav /* The buffer is not yet full */ 828*7b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(&context->buffer[usedspace], data, len); 829*7b5038d7SDag-Erling Smørgrav ADDINC128(context->bitcount, len << 3); 830*7b5038d7SDag-Erling Smørgrav /* Clean up: */ 831*7b5038d7SDag-Erling Smørgrav usedspace = freespace = 0; 832*7b5038d7SDag-Erling Smørgrav return; 833*7b5038d7SDag-Erling Smørgrav } 834*7b5038d7SDag-Erling Smørgrav } 835*7b5038d7SDag-Erling Smørgrav while (len >= LDNS_SHA512_BLOCK_LENGTH) { 836*7b5038d7SDag-Erling Smørgrav /* Process as many complete blocks as we can */ 837*7b5038d7SDag-Erling Smørgrav ldns_sha512_Transform(context, (sha2_word64*)data); 838*7b5038d7SDag-Erling Smørgrav ADDINC128(context->bitcount, LDNS_SHA512_BLOCK_LENGTH << 3); 839*7b5038d7SDag-Erling Smørgrav len -= LDNS_SHA512_BLOCK_LENGTH; 840*7b5038d7SDag-Erling Smørgrav data += LDNS_SHA512_BLOCK_LENGTH; 841*7b5038d7SDag-Erling Smørgrav } 842*7b5038d7SDag-Erling Smørgrav if (len > 0) { 843*7b5038d7SDag-Erling Smørgrav /* There's left-overs, so save 'em */ 844*7b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(context->buffer, data, len); 845*7b5038d7SDag-Erling Smørgrav ADDINC128(context->bitcount, len << 3); 846*7b5038d7SDag-Erling Smørgrav } 847*7b5038d7SDag-Erling Smørgrav /* Clean up: */ 848*7b5038d7SDag-Erling Smørgrav usedspace = freespace = 0; 849*7b5038d7SDag-Erling Smørgrav } 850*7b5038d7SDag-Erling Smørgrav 851*7b5038d7SDag-Erling Smørgrav static void ldns_sha512_Last(ldns_sha512_CTX* context) { 852*7b5038d7SDag-Erling Smørgrav size_t usedspace; 853*7b5038d7SDag-Erling Smørgrav 854*7b5038d7SDag-Erling Smørgrav usedspace = (context->bitcount[0] >> 3) % LDNS_SHA512_BLOCK_LENGTH; 855*7b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 856*7b5038d7SDag-Erling Smørgrav /* Convert FROM host byte order */ 857*7b5038d7SDag-Erling Smørgrav REVERSE64(context->bitcount[0],context->bitcount[0]); 858*7b5038d7SDag-Erling Smørgrav REVERSE64(context->bitcount[1],context->bitcount[1]); 859*7b5038d7SDag-Erling Smørgrav #endif 860*7b5038d7SDag-Erling Smørgrav if (usedspace > 0) { 861*7b5038d7SDag-Erling Smørgrav /* Begin padding with a 1 bit: */ 862*7b5038d7SDag-Erling Smørgrav context->buffer[usedspace++] = 0x80; 863*7b5038d7SDag-Erling Smørgrav 864*7b5038d7SDag-Erling Smørgrav if (usedspace <= ldns_sha512_SHORT_BLOCK_LENGTH) { 865*7b5038d7SDag-Erling Smørgrav /* Set-up for the last transform: */ 866*7b5038d7SDag-Erling Smørgrav MEMSET_BZERO(&context->buffer[usedspace], ldns_sha512_SHORT_BLOCK_LENGTH - usedspace); 867*7b5038d7SDag-Erling Smørgrav } else { 868*7b5038d7SDag-Erling Smørgrav if (usedspace < LDNS_SHA512_BLOCK_LENGTH) { 869*7b5038d7SDag-Erling Smørgrav MEMSET_BZERO(&context->buffer[usedspace], LDNS_SHA512_BLOCK_LENGTH - usedspace); 870*7b5038d7SDag-Erling Smørgrav } 871*7b5038d7SDag-Erling Smørgrav /* Do second-to-last transform: */ 872*7b5038d7SDag-Erling Smørgrav ldns_sha512_Transform(context, (sha2_word64*)context->buffer); 873*7b5038d7SDag-Erling Smørgrav 874*7b5038d7SDag-Erling Smørgrav /* And set-up for the last transform: */ 875*7b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context->buffer, LDNS_SHA512_BLOCK_LENGTH - 2); 876*7b5038d7SDag-Erling Smørgrav } 877*7b5038d7SDag-Erling Smørgrav } else { 878*7b5038d7SDag-Erling Smørgrav /* Prepare for final transform: */ 879*7b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context->buffer, ldns_sha512_SHORT_BLOCK_LENGTH); 880*7b5038d7SDag-Erling Smørgrav 881*7b5038d7SDag-Erling Smørgrav /* Begin padding with a 1 bit: */ 882*7b5038d7SDag-Erling Smørgrav *context->buffer = 0x80; 883*7b5038d7SDag-Erling Smørgrav } 884*7b5038d7SDag-Erling Smørgrav /* Store the length of input data (in bits): */ 885*7b5038d7SDag-Erling Smørgrav *(sha2_word64*)&context->buffer[ldns_sha512_SHORT_BLOCK_LENGTH] = context->bitcount[1]; 886*7b5038d7SDag-Erling Smørgrav *(sha2_word64*)&context->buffer[ldns_sha512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0]; 887*7b5038d7SDag-Erling Smørgrav 888*7b5038d7SDag-Erling Smørgrav /* final transform: */ 889*7b5038d7SDag-Erling Smørgrav ldns_sha512_Transform(context, (sha2_word64*)context->buffer); 890*7b5038d7SDag-Erling Smørgrav } 891*7b5038d7SDag-Erling Smørgrav 892*7b5038d7SDag-Erling Smørgrav void ldns_sha512_final(sha2_byte digest[], ldns_sha512_CTX* context) { 893*7b5038d7SDag-Erling Smørgrav sha2_word64 *d = (sha2_word64*)digest; 894*7b5038d7SDag-Erling Smørgrav 895*7b5038d7SDag-Erling Smørgrav /* Sanity check: */ 896*7b5038d7SDag-Erling Smørgrav assert(context != (ldns_sha512_CTX*)0); 897*7b5038d7SDag-Erling Smørgrav 898*7b5038d7SDag-Erling Smørgrav /* If no digest buffer is passed, we don't bother doing this: */ 899*7b5038d7SDag-Erling Smørgrav if (digest != (sha2_byte*)0) { 900*7b5038d7SDag-Erling Smørgrav ldns_sha512_Last(context); 901*7b5038d7SDag-Erling Smørgrav 902*7b5038d7SDag-Erling Smørgrav /* Save the hash data for output: */ 903*7b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 904*7b5038d7SDag-Erling Smørgrav { 905*7b5038d7SDag-Erling Smørgrav /* Convert TO host byte order */ 906*7b5038d7SDag-Erling Smørgrav int j; 907*7b5038d7SDag-Erling Smørgrav for (j = 0; j < 8; j++) { 908*7b5038d7SDag-Erling Smørgrav REVERSE64(context->state[j],context->state[j]); 909*7b5038d7SDag-Erling Smørgrav *d++ = context->state[j]; 910*7b5038d7SDag-Erling Smørgrav } 911*7b5038d7SDag-Erling Smørgrav } 912*7b5038d7SDag-Erling Smørgrav #else 913*7b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(d, context->state, LDNS_SHA512_DIGEST_LENGTH); 914*7b5038d7SDag-Erling Smørgrav #endif 915*7b5038d7SDag-Erling Smørgrav } 916*7b5038d7SDag-Erling Smørgrav 917*7b5038d7SDag-Erling Smørgrav /* Zero out state data */ 918*7b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context, sizeof(ldns_sha512_CTX)); 919*7b5038d7SDag-Erling Smørgrav } 920*7b5038d7SDag-Erling Smørgrav 921*7b5038d7SDag-Erling Smørgrav unsigned char * 922*7b5038d7SDag-Erling Smørgrav ldns_sha512(unsigned char *data, unsigned int data_len, unsigned char *digest) 923*7b5038d7SDag-Erling Smørgrav { 924*7b5038d7SDag-Erling Smørgrav ldns_sha512_CTX ctx; 925*7b5038d7SDag-Erling Smørgrav ldns_sha512_init(&ctx); 926*7b5038d7SDag-Erling Smørgrav ldns_sha512_update(&ctx, data, data_len); 927*7b5038d7SDag-Erling Smørgrav ldns_sha512_final(digest, &ctx); 928*7b5038d7SDag-Erling Smørgrav return digest; 929*7b5038d7SDag-Erling Smørgrav } 930*7b5038d7SDag-Erling Smørgrav 931*7b5038d7SDag-Erling Smørgrav /*** SHA-384: *********************************************************/ 932*7b5038d7SDag-Erling Smørgrav void ldns_sha384_init(ldns_sha384_CTX* context) { 933*7b5038d7SDag-Erling Smørgrav if (context == (ldns_sha384_CTX*)0) { 934*7b5038d7SDag-Erling Smørgrav return; 935*7b5038d7SDag-Erling Smørgrav } 936*7b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(context->state, sha384_initial_hash_value, LDNS_SHA512_DIGEST_LENGTH); 937*7b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context->buffer, LDNS_SHA384_BLOCK_LENGTH); 938*7b5038d7SDag-Erling Smørgrav context->bitcount[0] = context->bitcount[1] = 0; 939*7b5038d7SDag-Erling Smørgrav } 940*7b5038d7SDag-Erling Smørgrav 941*7b5038d7SDag-Erling Smørgrav void ldns_sha384_update(ldns_sha384_CTX* context, const sha2_byte* data, size_t len) { 942*7b5038d7SDag-Erling Smørgrav ldns_sha512_update((ldns_sha512_CTX*)context, data, len); 943*7b5038d7SDag-Erling Smørgrav } 944*7b5038d7SDag-Erling Smørgrav 945*7b5038d7SDag-Erling Smørgrav void ldns_sha384_final(sha2_byte digest[], ldns_sha384_CTX* context) { 946*7b5038d7SDag-Erling Smørgrav sha2_word64 *d = (sha2_word64*)digest; 947*7b5038d7SDag-Erling Smørgrav 948*7b5038d7SDag-Erling Smørgrav /* Sanity check: */ 949*7b5038d7SDag-Erling Smørgrav assert(context != (ldns_sha384_CTX*)0); 950*7b5038d7SDag-Erling Smørgrav 951*7b5038d7SDag-Erling Smørgrav /* If no digest buffer is passed, we don't bother doing this: */ 952*7b5038d7SDag-Erling Smørgrav if (digest != (sha2_byte*)0) { 953*7b5038d7SDag-Erling Smørgrav ldns_sha512_Last((ldns_sha512_CTX*)context); 954*7b5038d7SDag-Erling Smørgrav 955*7b5038d7SDag-Erling Smørgrav /* Save the hash data for output: */ 956*7b5038d7SDag-Erling Smørgrav #if BYTE_ORDER == LITTLE_ENDIAN 957*7b5038d7SDag-Erling Smørgrav { 958*7b5038d7SDag-Erling Smørgrav /* Convert TO host byte order */ 959*7b5038d7SDag-Erling Smørgrav int j; 960*7b5038d7SDag-Erling Smørgrav for (j = 0; j < 6; j++) { 961*7b5038d7SDag-Erling Smørgrav REVERSE64(context->state[j],context->state[j]); 962*7b5038d7SDag-Erling Smørgrav *d++ = context->state[j]; 963*7b5038d7SDag-Erling Smørgrav } 964*7b5038d7SDag-Erling Smørgrav } 965*7b5038d7SDag-Erling Smørgrav #else 966*7b5038d7SDag-Erling Smørgrav MEMCPY_BCOPY(d, context->state, LDNS_SHA384_DIGEST_LENGTH); 967*7b5038d7SDag-Erling Smørgrav #endif 968*7b5038d7SDag-Erling Smørgrav } 969*7b5038d7SDag-Erling Smørgrav 970*7b5038d7SDag-Erling Smørgrav /* Zero out state data */ 971*7b5038d7SDag-Erling Smørgrav MEMSET_BZERO(context, sizeof(ldns_sha384_CTX)); 972*7b5038d7SDag-Erling Smørgrav } 973*7b5038d7SDag-Erling Smørgrav 974*7b5038d7SDag-Erling Smørgrav unsigned char * 975*7b5038d7SDag-Erling Smørgrav ldns_sha384(unsigned char *data, unsigned int data_len, unsigned char *digest) 976*7b5038d7SDag-Erling Smørgrav { 977*7b5038d7SDag-Erling Smørgrav ldns_sha384_CTX ctx; 978*7b5038d7SDag-Erling Smørgrav ldns_sha384_init(&ctx); 979*7b5038d7SDag-Erling Smørgrav ldns_sha384_update(&ctx, data, data_len); 980*7b5038d7SDag-Erling Smørgrav ldns_sha384_final(digest, &ctx); 981*7b5038d7SDag-Erling Smørgrav return digest; 982*7b5038d7SDag-Erling Smørgrav } 983