mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-10-30 23:15:32 +01:00 
			
		
		
		
	Replace SHA256 implementation with one from LibreSSL
They have cleaner code than OpenSSL :) from here: https://github.com/libressl/openbsd/tree/master/src/lib/libcrypto and https://github.com/libressl/portable
This commit is contained in:
		| @@ -1,399 +1,580 @@ | ||||
| /* crypto/sha/sha256.c */ | ||||
| /* libcrypto/sha/sha256.c */ | ||||
| /* ==================================================================== | ||||
|  * Copyright (c) 2004 The OpenSSL Project.  All rights reserved | ||||
|  * according to the OpenSSL license [found in ../../LICENSE]. | ||||
|  * Copyright (c) 1998-2011 The OpenSSL Project.  All rights reserved. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions | ||||
|  * are met: | ||||
|  * | ||||
|  * 1. Redistributions of source code must retain the above copyright | ||||
|  *    notice, this list of conditions and the following disclaimer. | ||||
|  * | ||||
|  * 2. Redistributions in binary form must reproduce the above copyright | ||||
|  *    notice, this list of conditions and the following disclaimer in | ||||
|  *    the documentation and/or other materials provided with the | ||||
|  *    distribution. | ||||
|  * | ||||
|  * 3. All advertising materials mentioning features or use of this | ||||
|  *    software must display the following acknowledgment: | ||||
|  *    "This product includes software developed by the OpenSSL Project | ||||
|  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" | ||||
|  * | ||||
|  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | ||||
|  *    endorse or promote products derived from this software without | ||||
|  *    prior written permission. For written permission, please contact | ||||
|  *    openssl-core@openssl.org. | ||||
|  * | ||||
|  * 5. Products derived from this software may not be called "OpenSSL" | ||||
|  *    nor may "OpenSSL" appear in their names without prior written | ||||
|  *    permission of the OpenSSL Project. | ||||
|  * | ||||
|  * 6. Redistributions of any form whatsoever must retain the following | ||||
|  *    acknowledgment: | ||||
|  *    "This product includes software developed by the OpenSSL Project | ||||
|  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | ||||
|  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||||
|  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR | ||||
|  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
|  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||||
|  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||
|  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | ||||
|  * OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  * ==================================================================== | ||||
|  * | ||||
|  * This product includes cryptographic software written by Eric Young | ||||
|  * (eay@cryptsoft.com).  This product includes software written by Tim | ||||
|  * Hudson (tjh@cryptsoft.com). | ||||
|  */ | ||||
| # include <stdlib.h> | ||||
| # include <string.h> | ||||
|  | ||||
| # include <util/sha2.h> | ||||
| #include <stdint.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #  define OPENSSL_VERSION_TEXT    "OpenSSL 1.0.2a 19 Mar 2015" | ||||
| # define OPENSSL_VERSION_PTEXT   " part of " OPENSSL_VERSION_TEXT | ||||
| #include "util/sha256.h" | ||||
|  | ||||
| const char SHA256_version[] = "SHA-256" OPENSSL_VERSION_PTEXT; | ||||
| #if defined(_MSC_VER) && !defined(__clang__) && !defined(__attribute__) | ||||
| #define __attribute__(a) | ||||
| #endif | ||||
|  | ||||
| /* mem_clr.c */ | ||||
| unsigned static char cleanse_ctr = 0; | ||||
| static void OPENSSL_cleanse(void *ptr, size_t len) | ||||
| { | ||||
|     unsigned char *p = (unsigned char *)ptr; | ||||
|     size_t loop = len, ctr = cleanse_ctr; | ||||
|     while (loop--) { | ||||
|         *(p++) = (unsigned char)ctr; | ||||
|         ctr += (17 + ((size_t)p & 0xF)); | ||||
|     } | ||||
|     p = (unsigned char *)memchr(ptr, (unsigned char)ctr, len); | ||||
|     if (p) | ||||
|         ctr += (63 + (size_t)p); | ||||
|     cleanse_ctr = (unsigned char)ctr; | ||||
| } | ||||
| /* pull HAVE_ENDIAN_H from Minetest */ | ||||
| #include "config.h" | ||||
| #if !HAVE_ENDIAN_H | ||||
| #undef HAVE_ENDIAN_H | ||||
| #endif | ||||
|  | ||||
| fips_md_init_ctx(SHA224, SHA256) | ||||
| { | ||||
|     memset(c, 0, sizeof(*c)); | ||||
|     c->h[0] = 0xc1059ed8UL; | ||||
|     c->h[1] = 0x367cd507UL; | ||||
|     c->h[2] = 0x3070dd17UL; | ||||
|     c->h[3] = 0xf70e5939UL; | ||||
|     c->h[4] = 0xffc00b31UL; | ||||
|     c->h[5] = 0x68581511UL; | ||||
|     c->h[6] = 0x64f98fa7UL; | ||||
|     c->h[7] = 0xbefa4fa4UL; | ||||
|     c->md_len = SHA224_DIGEST_LENGTH; | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
| fips_md_init(SHA256) | ||||
| { | ||||
|     memset(c, 0, sizeof(*c)); | ||||
|     c->h[0] = 0x6a09e667UL; | ||||
|     c->h[1] = 0xbb67ae85UL; | ||||
|     c->h[2] = 0x3c6ef372UL; | ||||
|     c->h[3] = 0xa54ff53aUL; | ||||
|     c->h[4] = 0x510e527fUL; | ||||
|     c->h[5] = 0x9b05688cUL; | ||||
|     c->h[6] = 0x1f83d9abUL; | ||||
|     c->h[7] = 0x5be0cd19UL; | ||||
|     c->md_len = SHA256_DIGEST_LENGTH; | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
| unsigned char *SHA224(const unsigned char *d, size_t n, unsigned char *md) | ||||
| { | ||||
|     SHA256_CTX c; | ||||
|     static unsigned char m[SHA224_DIGEST_LENGTH]; | ||||
|  | ||||
|     if (md == NULL) | ||||
|         md = m; | ||||
|     SHA224_Init(&c); | ||||
|     SHA256_Update(&c, d, n); | ||||
|     SHA256_Final(md, &c); | ||||
|     OPENSSL_cleanse(&c, sizeof(c)); | ||||
|     return (md); | ||||
| } | ||||
|  | ||||
| unsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md) | ||||
| { | ||||
|     SHA256_CTX c; | ||||
|     static unsigned char m[SHA256_DIGEST_LENGTH]; | ||||
|  | ||||
|     if (md == NULL) | ||||
|         md = m; | ||||
|     SHA256_Init(&c); | ||||
|     SHA256_Update(&c, d, n); | ||||
|     SHA256_Final(md, &c); | ||||
|     OPENSSL_cleanse(&c, sizeof(c)); | ||||
|     return (md); | ||||
| } | ||||
|  | ||||
| int SHA224_Update(SHA256_CTX *c, const void *data, size_t len) | ||||
| { | ||||
|     return SHA256_Update(c, data, len); | ||||
| } | ||||
|  | ||||
| int SHA224_Final(unsigned char *md, SHA256_CTX *c) | ||||
| { | ||||
|     return SHA256_Final(md, c); | ||||
| } | ||||
|  | ||||
| # define DATA_ORDER_IS_BIG_ENDIAN | ||||
|  | ||||
| # define HASH_LONG               SHA_LONG | ||||
| # define HASH_CTX                SHA256_CTX | ||||
| # define HASH_CBLOCK             SHA_CBLOCK | ||||
| /** endian.h **/ | ||||
| /* | ||||
|  * Note that FIPS180-2 discusses "Truncation of the Hash Function Output." | ||||
|  * default: case below covers for it. It's not clear however if it's | ||||
|  * permitted to truncate to amount of bytes not divisible by 4. I bet not, | ||||
|  * but if it is, then default: case shall be extended. For reference. | ||||
|  * Idea behind separate cases for pre-defined lenghts is to let the | ||||
|  * compiler decide if it's appropriate to unroll small loops. | ||||
|  * Public domain | ||||
|  * endian.h compatibility shim | ||||
|  */ | ||||
| # define HASH_MAKE_STRING(c,s)   do {    \ | ||||
|         unsigned long ll;               \ | ||||
|         unsigned int  nn;               \ | ||||
|         switch ((c)->md_len)            \ | ||||
|         {   case SHA224_DIGEST_LENGTH:  \ | ||||
|                 for (nn=0;nn<SHA224_DIGEST_LENGTH/4;nn++)       \ | ||||
|                 {   ll=(c)->h[nn]; (void)HOST_l2c(ll,(s));   }  \ | ||||
|                 break;                  \ | ||||
|             case SHA256_DIGEST_LENGTH:  \ | ||||
|                 for (nn=0;nn<SHA256_DIGEST_LENGTH/4;nn++)       \ | ||||
|                 {   ll=(c)->h[nn]; (void)HOST_l2c(ll,(s));   }  \ | ||||
|                 break;                  \ | ||||
|             default:                    \ | ||||
|                 if ((c)->md_len > SHA256_DIGEST_LENGTH) \ | ||||
|                     return 0;                           \ | ||||
|                 for (nn=0;nn<(c)->md_len/4;nn++)                \ | ||||
|                 {   ll=(c)->h[nn]; (void)HOST_l2c(ll,(s));   }  \ | ||||
|                 break;                  \ | ||||
|         }                               \ | ||||
|         } while (0) | ||||
|  | ||||
| # define HASH_UPDATE             SHA256_Update | ||||
| # define HASH_TRANSFORM          SHA256_Transform | ||||
| # define HASH_FINAL              SHA256_Final | ||||
| # define HASH_BLOCK_DATA_ORDER   sha256_block_data_order | ||||
| # ifndef SHA256_ASM | ||||
| static | ||||
| # endif | ||||
| void sha256_block_data_order(SHA256_CTX *ctx, const void *in, size_t num); | ||||
| #if defined(_WIN32) | ||||
|  | ||||
| # include "md32_common.h" | ||||
| #define LITTLE_ENDIAN 1234 | ||||
| #define BIG_ENDIAN 4321 | ||||
| #define PDP_ENDIAN 3412 | ||||
|  | ||||
| /* | ||||
|  * Use GCC and Visual Studio compiler defines to determine endian. | ||||
|  */ | ||||
| #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | ||||
| #define BYTE_ORDER LITTLE_ENDIAN | ||||
| #else | ||||
| #define BYTE_ORDER BIG_ENDIAN | ||||
| #endif | ||||
|  | ||||
| #elif defined(HAVE_ENDIAN_H) | ||||
| #include <endian.h> | ||||
|  | ||||
| #elif defined(__MACH__) && defined(__APPLE__) | ||||
| #include <machine/endian.h> | ||||
|  | ||||
| #elif defined(__sun) || defined(_AIX) || defined(__hpux) | ||||
| #include <arpa/nameser_compat.h> | ||||
| #include <sys/types.h> | ||||
|  | ||||
| #elif defined(__sgi) | ||||
| #include <standards.h> | ||||
| #include <sys/endian.h> | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #ifndef __STRICT_ALIGNMENT | ||||
| #define __STRICT_ALIGNMENT | ||||
| #if defined(__i386) || defined(__i386__) || defined(__x86_64) ||               \ | ||||
|     defined(__x86_64__) || defined(__s390__) || defined(__s390x__) ||          \ | ||||
|     defined(__aarch64__) ||                                                    \ | ||||
|     ((defined(__arm__) || defined(__arm)) && __ARM_ARCH >= 6) | ||||
| #undef __STRICT_ALIGNMENT | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #if defined(__APPLE__) && !defined(HAVE_ENDIAN_H) | ||||
| #include <libkern/OSByteOrder.h> | ||||
| #define be16toh(x) OSSwapBigToHostInt16((x)) | ||||
| #define htobe16(x) OSSwapHostToBigInt16((x)) | ||||
| #define le32toh(x) OSSwapLittleToHostInt32((x)) | ||||
| #define be32toh(x) OSSwapBigToHostInt32((x)) | ||||
| #define htole32(x) OSSwapHostToLittleInt32(x) | ||||
| #define htobe32(x) OSSwapHostToBigInt32(x) | ||||
| #endif /* __APPLE__ && !HAVE_ENDIAN_H */ | ||||
|  | ||||
| #if defined(_WIN32) && !defined(HAVE_ENDIAN_H) | ||||
| #include <winsock2.h> | ||||
|  | ||||
| #define be16toh(x) ntohs((x)) | ||||
| #define htobe16(x) htons((x)) | ||||
| #define le32toh(x) (x) | ||||
| #define be32toh(x) ntohl((x)) | ||||
| #define htole32(x) (x) | ||||
| #define htobe32(x) ntohl((x)) | ||||
| #endif /* _WIN32 && !HAVE_ENDIAN_H */ | ||||
|  | ||||
| #ifdef __linux__ | ||||
| #if !defined(betoh16) | ||||
| #define betoh16(x) be16toh(x) | ||||
| #endif | ||||
| #if !defined(betoh32) | ||||
| #define betoh32(x) be32toh(x) | ||||
| #endif | ||||
| #endif /* __linux__ */ | ||||
|  | ||||
| #if defined(__FreeBSD__) | ||||
| #if !defined(HAVE_ENDIAN_H) | ||||
| #include <sys/endian.h> | ||||
| #endif | ||||
| #if !defined(betoh16) | ||||
| #define betoh16(x) be16toh(x) | ||||
| #endif | ||||
| #if !defined(betoh32) | ||||
| #define betoh32(x) be32toh(x) | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #if defined(__NetBSD__) | ||||
| #if !defined(betoh16) | ||||
| #define betoh16(x) be16toh(x) | ||||
| #endif | ||||
| #if !defined(betoh32) | ||||
| #define betoh32(x) be32toh(x) | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #if defined(__sun) | ||||
| #include <sys/byteorder.h> | ||||
| #define be16toh(x) BE_16(x) | ||||
| #define htobe16(x) BE_16(x) | ||||
| #define le32toh(x) LE_32(x) | ||||
| #define be32toh(x) BE_32(x) | ||||
| #define htole32(x) LE_32(x) | ||||
| #define htobe32(x) BE_32(x) | ||||
| #endif | ||||
| /** **/ | ||||
|  | ||||
| /** libcrypto/crypto_internal.h **/ | ||||
| #define CTASSERT(x) \ | ||||
|     extern char _ctassert[(x) ? 1 : -1] __attribute__((__unused__)) | ||||
|  | ||||
| static inline uint32_t | ||||
| crypto_load_be32toh(const uint8_t *src) | ||||
| { | ||||
| 	uint32_t v; | ||||
|  | ||||
| 	memcpy(&v, src, sizeof(v)); | ||||
|  | ||||
| 	return be32toh(v); | ||||
| } | ||||
|  | ||||
| static inline void | ||||
| crypto_store_htobe32(uint8_t *dst, uint32_t v) | ||||
| { | ||||
| 	v = htobe32(v); | ||||
| 	memcpy(dst, &v, sizeof(v)); | ||||
| } | ||||
|  | ||||
| static inline uint32_t | ||||
| crypto_ror_u32(uint32_t v, size_t shift) | ||||
| { | ||||
| 	return (v << (32 - shift)) | (v >> shift); | ||||
| } | ||||
| /** **/ | ||||
|  | ||||
| /** libcrypto/hidden/crypto_namespace.h **/ | ||||
| # define LCRYPTO_UNUSED(x) | ||||
| # define LCRYPTO_USED(x) | ||||
| # define LCRYPTO_ALIAS1(pre,x) | ||||
| # define LCRYPTO_ALIAS(x) | ||||
| /** **/ | ||||
|  | ||||
| /* Ensure that SHA_LONG and uint32_t are equivalent. */ | ||||
| CTASSERT(sizeof(SHA_LONG) == sizeof(uint32_t)); | ||||
|  | ||||
| static void sha256_block_data_order(SHA256_CTX *ctx, const void *_in, size_t num); | ||||
|  | ||||
| # ifndef SHA256_ASM | ||||
| static const SHA_LONG K256[64] = { | ||||
|     0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, | ||||
|     0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, | ||||
|     0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, | ||||
|     0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, | ||||
|     0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, | ||||
|     0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, | ||||
|     0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, | ||||
|     0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, | ||||
|     0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, | ||||
|     0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, | ||||
|     0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, | ||||
|     0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, | ||||
|     0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, | ||||
|     0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, | ||||
|     0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, | ||||
|     0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL | ||||
| 	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, | ||||
| 	0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, | ||||
| 	0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, | ||||
| 	0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, | ||||
| 	0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, | ||||
| 	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, | ||||
| 	0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, | ||||
| 	0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, | ||||
| 	0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, | ||||
| 	0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, | ||||
| 	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, | ||||
| 	0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, | ||||
| 	0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, | ||||
| 	0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, | ||||
| 	0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, | ||||
| 	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL, | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * FIPS specification refers to right rotations, while our ROTATE macro | ||||
|  * is left one. This is why you might notice that rotation coefficients | ||||
|  * differ from those observed in FIPS document by 32-N... | ||||
|  */ | ||||
| #  define Sigma0(x)       (ROTATE((x),30) ^ ROTATE((x),19) ^ ROTATE((x),10)) | ||||
| #  define Sigma1(x)       (ROTATE((x),26) ^ ROTATE((x),21) ^ ROTATE((x),7)) | ||||
| #  define sigma0(x)       (ROTATE((x),25) ^ ROTATE((x),14) ^ ((x)>>3)) | ||||
| #  define sigma1(x)       (ROTATE((x),15) ^ ROTATE((x),13) ^ ((x)>>10)) | ||||
|  | ||||
| #  define Ch(x,y,z)       (((x) & (y)) ^ ((~(x)) & (z))) | ||||
| #  define Maj(x,y,z)      (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) | ||||
|  | ||||
| #  ifdef OPENSSL_SMALL_FOOTPRINT | ||||
|  | ||||
| static void sha256_block_data_order(SHA256_CTX *ctx, const void *in, | ||||
|                                     size_t num) | ||||
| static inline SHA_LONG | ||||
| Sigma0(SHA_LONG x) | ||||
| { | ||||
|     unsigned MD32_REG_T a, b, c, d, e, f, g, h, s0, s1, T1, T2; | ||||
|     SHA_LONG X[16], l; | ||||
|     int i; | ||||
|     const unsigned char *data = in; | ||||
|  | ||||
|     while (num--) { | ||||
|  | ||||
|         a = ctx->h[0]; | ||||
|         b = ctx->h[1]; | ||||
|         c = ctx->h[2]; | ||||
|         d = ctx->h[3]; | ||||
|         e = ctx->h[4]; | ||||
|         f = ctx->h[5]; | ||||
|         g = ctx->h[6]; | ||||
|         h = ctx->h[7]; | ||||
|  | ||||
|         for (i = 0; i < 16; i++) { | ||||
|             HOST_c2l(data, l); | ||||
|             T1 = X[i] = l; | ||||
|             T1 += h + Sigma1(e) + Ch(e, f, g) + K256[i]; | ||||
|             T2 = Sigma0(a) + Maj(a, b, c); | ||||
|             h = g; | ||||
|             g = f; | ||||
|             f = e; | ||||
|             e = d + T1; | ||||
|             d = c; | ||||
|             c = b; | ||||
|             b = a; | ||||
|             a = T1 + T2; | ||||
|         } | ||||
|  | ||||
|         for (; i < 64; i++) { | ||||
|             s0 = X[(i + 1) & 0x0f]; | ||||
|             s0 = sigma0(s0); | ||||
|             s1 = X[(i + 14) & 0x0f]; | ||||
|             s1 = sigma1(s1); | ||||
|  | ||||
|             T1 = X[i & 0xf] += s0 + s1 + X[(i + 9) & 0xf]; | ||||
|             T1 += h + Sigma1(e) + Ch(e, f, g) + K256[i]; | ||||
|             T2 = Sigma0(a) + Maj(a, b, c); | ||||
|             h = g; | ||||
|             g = f; | ||||
|             f = e; | ||||
|             e = d + T1; | ||||
|             d = c; | ||||
|             c = b; | ||||
|             b = a; | ||||
|             a = T1 + T2; | ||||
|         } | ||||
|  | ||||
|         ctx->h[0] += a; | ||||
|         ctx->h[1] += b; | ||||
|         ctx->h[2] += c; | ||||
|         ctx->h[3] += d; | ||||
|         ctx->h[4] += e; | ||||
|         ctx->h[5] += f; | ||||
|         ctx->h[6] += g; | ||||
|         ctx->h[7] += h; | ||||
|  | ||||
|     } | ||||
| 	return crypto_ror_u32(x, 2) ^ crypto_ror_u32(x, 13) ^ | ||||
| 	    crypto_ror_u32(x, 22); | ||||
| } | ||||
|  | ||||
| #  else | ||||
|  | ||||
| #   define ROUND_00_15(i,a,b,c,d,e,f,g,h)          do {    \ | ||||
|         T1 += h + Sigma1(e) + Ch(e,f,g) + K256[i];      \ | ||||
|         h = Sigma0(a) + Maj(a,b,c);                     \ | ||||
|         d += T1;        h += T1;                } while (0) | ||||
|  | ||||
| #   define ROUND_16_63(i,a,b,c,d,e,f,g,h,X)        do {    \ | ||||
|         s0 = X[(i+1)&0x0f];     s0 = sigma0(s0);        \ | ||||
|         s1 = X[(i+14)&0x0f];    s1 = sigma1(s1);        \ | ||||
|         T1 = X[(i)&0x0f] += s0 + s1 + X[(i+9)&0x0f];    \ | ||||
|         ROUND_00_15(i,a,b,c,d,e,f,g,h);         } while (0) | ||||
|  | ||||
| static void sha256_block_data_order(SHA256_CTX *ctx, const void *in, | ||||
|                                     size_t num) | ||||
| static inline SHA_LONG | ||||
| Sigma1(SHA_LONG x) | ||||
| { | ||||
|     unsigned MD32_REG_T a, b, c, d, e, f, g, h, s0, s1, T1; | ||||
|     SHA_LONG X[16]; | ||||
|     int i; | ||||
|     const unsigned char *data = (const unsigned char *)in; | ||||
|     const union { | ||||
|         long one; | ||||
|         char little; | ||||
|     } is_endian = { | ||||
|         1 | ||||
|     }; | ||||
|  | ||||
|     while (num--) { | ||||
|  | ||||
|         a = ctx->h[0]; | ||||
|         b = ctx->h[1]; | ||||
|         c = ctx->h[2]; | ||||
|         d = ctx->h[3]; | ||||
|         e = ctx->h[4]; | ||||
|         f = ctx->h[5]; | ||||
|         g = ctx->h[6]; | ||||
|         h = ctx->h[7]; | ||||
|  | ||||
|         if (!is_endian.little && sizeof(SHA_LONG) == 4 | ||||
|             && ((size_t)in % 4) == 0) { | ||||
|             const SHA_LONG *W = (const SHA_LONG *)data; | ||||
|  | ||||
|             T1 = X[0] = W[0]; | ||||
|             ROUND_00_15(0, a, b, c, d, e, f, g, h); | ||||
|             T1 = X[1] = W[1]; | ||||
|             ROUND_00_15(1, h, a, b, c, d, e, f, g); | ||||
|             T1 = X[2] = W[2]; | ||||
|             ROUND_00_15(2, g, h, a, b, c, d, e, f); | ||||
|             T1 = X[3] = W[3]; | ||||
|             ROUND_00_15(3, f, g, h, a, b, c, d, e); | ||||
|             T1 = X[4] = W[4]; | ||||
|             ROUND_00_15(4, e, f, g, h, a, b, c, d); | ||||
|             T1 = X[5] = W[5]; | ||||
|             ROUND_00_15(5, d, e, f, g, h, a, b, c); | ||||
|             T1 = X[6] = W[6]; | ||||
|             ROUND_00_15(6, c, d, e, f, g, h, a, b); | ||||
|             T1 = X[7] = W[7]; | ||||
|             ROUND_00_15(7, b, c, d, e, f, g, h, a); | ||||
|             T1 = X[8] = W[8]; | ||||
|             ROUND_00_15(8, a, b, c, d, e, f, g, h); | ||||
|             T1 = X[9] = W[9]; | ||||
|             ROUND_00_15(9, h, a, b, c, d, e, f, g); | ||||
|             T1 = X[10] = W[10]; | ||||
|             ROUND_00_15(10, g, h, a, b, c, d, e, f); | ||||
|             T1 = X[11] = W[11]; | ||||
|             ROUND_00_15(11, f, g, h, a, b, c, d, e); | ||||
|             T1 = X[12] = W[12]; | ||||
|             ROUND_00_15(12, e, f, g, h, a, b, c, d); | ||||
|             T1 = X[13] = W[13]; | ||||
|             ROUND_00_15(13, d, e, f, g, h, a, b, c); | ||||
|             T1 = X[14] = W[14]; | ||||
|             ROUND_00_15(14, c, d, e, f, g, h, a, b); | ||||
|             T1 = X[15] = W[15]; | ||||
|             ROUND_00_15(15, b, c, d, e, f, g, h, a); | ||||
|  | ||||
|             data += SHA256_CBLOCK; | ||||
|         } else { | ||||
|             SHA_LONG l; | ||||
|  | ||||
|             HOST_c2l(data, l); | ||||
|             T1 = X[0] = l; | ||||
|             ROUND_00_15(0, a, b, c, d, e, f, g, h); | ||||
|             HOST_c2l(data, l); | ||||
|             T1 = X[1] = l; | ||||
|             ROUND_00_15(1, h, a, b, c, d, e, f, g); | ||||
|             HOST_c2l(data, l); | ||||
|             T1 = X[2] = l; | ||||
|             ROUND_00_15(2, g, h, a, b, c, d, e, f); | ||||
|             HOST_c2l(data, l); | ||||
|             T1 = X[3] = l; | ||||
|             ROUND_00_15(3, f, g, h, a, b, c, d, e); | ||||
|             HOST_c2l(data, l); | ||||
|             T1 = X[4] = l; | ||||
|             ROUND_00_15(4, e, f, g, h, a, b, c, d); | ||||
|             HOST_c2l(data, l); | ||||
|             T1 = X[5] = l; | ||||
|             ROUND_00_15(5, d, e, f, g, h, a, b, c); | ||||
|             HOST_c2l(data, l); | ||||
|             T1 = X[6] = l; | ||||
|             ROUND_00_15(6, c, d, e, f, g, h, a, b); | ||||
|             HOST_c2l(data, l); | ||||
|             T1 = X[7] = l; | ||||
|             ROUND_00_15(7, b, c, d, e, f, g, h, a); | ||||
|             HOST_c2l(data, l); | ||||
|             T1 = X[8] = l; | ||||
|             ROUND_00_15(8, a, b, c, d, e, f, g, h); | ||||
|             HOST_c2l(data, l); | ||||
|             T1 = X[9] = l; | ||||
|             ROUND_00_15(9, h, a, b, c, d, e, f, g); | ||||
|             HOST_c2l(data, l); | ||||
|             T1 = X[10] = l; | ||||
|             ROUND_00_15(10, g, h, a, b, c, d, e, f); | ||||
|             HOST_c2l(data, l); | ||||
|             T1 = X[11] = l; | ||||
|             ROUND_00_15(11, f, g, h, a, b, c, d, e); | ||||
|             HOST_c2l(data, l); | ||||
|             T1 = X[12] = l; | ||||
|             ROUND_00_15(12, e, f, g, h, a, b, c, d); | ||||
|             HOST_c2l(data, l); | ||||
|             T1 = X[13] = l; | ||||
|             ROUND_00_15(13, d, e, f, g, h, a, b, c); | ||||
|             HOST_c2l(data, l); | ||||
|             T1 = X[14] = l; | ||||
|             ROUND_00_15(14, c, d, e, f, g, h, a, b); | ||||
|             HOST_c2l(data, l); | ||||
|             T1 = X[15] = l; | ||||
|             ROUND_00_15(15, b, c, d, e, f, g, h, a); | ||||
|         } | ||||
|  | ||||
|         for (i = 16; i < 64; i += 8) { | ||||
|             ROUND_16_63(i + 0, a, b, c, d, e, f, g, h, X); | ||||
|             ROUND_16_63(i + 1, h, a, b, c, d, e, f, g, X); | ||||
|             ROUND_16_63(i + 2, g, h, a, b, c, d, e, f, X); | ||||
|             ROUND_16_63(i + 3, f, g, h, a, b, c, d, e, X); | ||||
|             ROUND_16_63(i + 4, e, f, g, h, a, b, c, d, X); | ||||
|             ROUND_16_63(i + 5, d, e, f, g, h, a, b, c, X); | ||||
|             ROUND_16_63(i + 6, c, d, e, f, g, h, a, b, X); | ||||
|             ROUND_16_63(i + 7, b, c, d, e, f, g, h, a, X); | ||||
|         } | ||||
|  | ||||
|         ctx->h[0] += a; | ||||
|         ctx->h[1] += b; | ||||
|         ctx->h[2] += c; | ||||
|         ctx->h[3] += d; | ||||
|         ctx->h[4] += e; | ||||
|         ctx->h[5] += f; | ||||
|         ctx->h[6] += g; | ||||
|         ctx->h[7] += h; | ||||
|  | ||||
|     } | ||||
| 	return crypto_ror_u32(x, 6) ^ crypto_ror_u32(x, 11) ^ | ||||
| 	    crypto_ror_u32(x, 25); | ||||
| } | ||||
|  | ||||
| #  endif | ||||
| # endif                         /* SHA256_ASM */ | ||||
| static inline SHA_LONG | ||||
| sigma0(SHA_LONG x) | ||||
| { | ||||
| 	return crypto_ror_u32(x, 7) ^ crypto_ror_u32(x, 18) ^ (x >> 3); | ||||
| } | ||||
|  | ||||
| static inline SHA_LONG | ||||
| sigma1(SHA_LONG x) | ||||
| { | ||||
| 	return crypto_ror_u32(x, 17) ^ crypto_ror_u32(x, 19) ^ (x >> 10); | ||||
| } | ||||
|  | ||||
| static inline SHA_LONG | ||||
| Ch(SHA_LONG x, SHA_LONG y, SHA_LONG z) | ||||
| { | ||||
| 	return (x & y) ^ (~x & z); | ||||
| } | ||||
|  | ||||
| static inline SHA_LONG | ||||
| Maj(SHA_LONG x, SHA_LONG y, SHA_LONG z) | ||||
| { | ||||
| 	return (x & y) ^ (x & z) ^ (y & z); | ||||
| } | ||||
|  | ||||
| static inline void | ||||
| sha256_msg_schedule_update(SHA_LONG *W0, SHA_LONG W1, | ||||
|     SHA_LONG W9, SHA_LONG W14) | ||||
| { | ||||
| 	*W0 = sigma1(W14) + W9 + sigma0(W1) + *W0; | ||||
| } | ||||
|  | ||||
| static inline void | ||||
| sha256_round(SHA_LONG *a, SHA_LONG *b, SHA_LONG *c, SHA_LONG *d, | ||||
|     SHA_LONG *e, SHA_LONG *f, SHA_LONG *g, SHA_LONG *h, | ||||
|     SHA_LONG Kt, SHA_LONG Wt) | ||||
| { | ||||
| 	SHA_LONG T1, T2; | ||||
|  | ||||
| 	T1 = *h + Sigma1(*e) + Ch(*e, *f, *g) + Kt + Wt; | ||||
| 	T2 = Sigma0(*a) + Maj(*a, *b, *c); | ||||
|  | ||||
| 	*h = *g; | ||||
| 	*g = *f; | ||||
| 	*f = *e; | ||||
| 	*e = *d + T1; | ||||
| 	*d = *c; | ||||
| 	*c = *b; | ||||
| 	*b = *a; | ||||
| 	*a = T1 + T2; | ||||
| } | ||||
|  | ||||
| static void | ||||
| sha256_block_data_order(SHA256_CTX *ctx, const void *_in, size_t num) | ||||
| { | ||||
| 	const uint8_t *in = _in; | ||||
| 	const SHA_LONG *in32; | ||||
| 	SHA_LONG a, b, c, d, e, f, g, h; | ||||
| 	SHA_LONG X[16]; | ||||
| 	int i; | ||||
|  | ||||
| 	while (num--) { | ||||
| 		a = ctx->h[0]; | ||||
| 		b = ctx->h[1]; | ||||
| 		c = ctx->h[2]; | ||||
| 		d = ctx->h[3]; | ||||
| 		e = ctx->h[4]; | ||||
| 		f = ctx->h[5]; | ||||
| 		g = ctx->h[6]; | ||||
| 		h = ctx->h[7]; | ||||
|  | ||||
| 		if ((size_t)in % 4 == 0) { | ||||
| 			/* Input is 32 bit aligned. */ | ||||
| 			in32 = (const SHA_LONG *)in; | ||||
| 			X[0] = be32toh(in32[0]); | ||||
| 			X[1] = be32toh(in32[1]); | ||||
| 			X[2] = be32toh(in32[2]); | ||||
| 			X[3] = be32toh(in32[3]); | ||||
| 			X[4] = be32toh(in32[4]); | ||||
| 			X[5] = be32toh(in32[5]); | ||||
| 			X[6] = be32toh(in32[6]); | ||||
| 			X[7] = be32toh(in32[7]); | ||||
| 			X[8] = be32toh(in32[8]); | ||||
| 			X[9] = be32toh(in32[9]); | ||||
| 			X[10] = be32toh(in32[10]); | ||||
| 			X[11] = be32toh(in32[11]); | ||||
| 			X[12] = be32toh(in32[12]); | ||||
| 			X[13] = be32toh(in32[13]); | ||||
| 			X[14] = be32toh(in32[14]); | ||||
| 			X[15] = be32toh(in32[15]); | ||||
| 		} else { | ||||
| 			/* Input is not 32 bit aligned. */ | ||||
| 			X[0] = crypto_load_be32toh(&in[0 * 4]); | ||||
| 			X[1] = crypto_load_be32toh(&in[1 * 4]); | ||||
| 			X[2] = crypto_load_be32toh(&in[2 * 4]); | ||||
| 			X[3] = crypto_load_be32toh(&in[3 * 4]); | ||||
| 			X[4] = crypto_load_be32toh(&in[4 * 4]); | ||||
| 			X[5] = crypto_load_be32toh(&in[5 * 4]); | ||||
| 			X[6] = crypto_load_be32toh(&in[6 * 4]); | ||||
| 			X[7] = crypto_load_be32toh(&in[7 * 4]); | ||||
| 			X[8] = crypto_load_be32toh(&in[8 * 4]); | ||||
| 			X[9] = crypto_load_be32toh(&in[9 * 4]); | ||||
| 			X[10] = crypto_load_be32toh(&in[10 * 4]); | ||||
| 			X[11] = crypto_load_be32toh(&in[11 * 4]); | ||||
| 			X[12] = crypto_load_be32toh(&in[12 * 4]); | ||||
| 			X[13] = crypto_load_be32toh(&in[13 * 4]); | ||||
| 			X[14] = crypto_load_be32toh(&in[14 * 4]); | ||||
| 			X[15] = crypto_load_be32toh(&in[15 * 4]); | ||||
| 		} | ||||
| 		in += SHA256_CBLOCK; | ||||
|  | ||||
| 		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[0], X[0]); | ||||
| 		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[1], X[1]); | ||||
| 		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[2], X[2]); | ||||
| 		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[3], X[3]); | ||||
| 		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[4], X[4]); | ||||
| 		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[5], X[5]); | ||||
| 		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[6], X[6]); | ||||
| 		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[7], X[7]); | ||||
| 		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[8], X[8]); | ||||
| 		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[9], X[9]); | ||||
| 		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[10], X[10]); | ||||
| 		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[11], X[11]); | ||||
| 		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[12], X[12]); | ||||
| 		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[13], X[13]); | ||||
| 		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[14], X[14]); | ||||
| 		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[15], X[15]); | ||||
|  | ||||
| 		for (i = 16; i < 64; i += 16) { | ||||
| 			sha256_msg_schedule_update(&X[0], X[1], X[9], X[14]); | ||||
| 			sha256_msg_schedule_update(&X[1], X[2], X[10], X[15]); | ||||
| 			sha256_msg_schedule_update(&X[2], X[3], X[11], X[0]); | ||||
| 			sha256_msg_schedule_update(&X[3], X[4], X[12], X[1]); | ||||
| 			sha256_msg_schedule_update(&X[4], X[5], X[13], X[2]); | ||||
| 			sha256_msg_schedule_update(&X[5], X[6], X[14], X[3]); | ||||
| 			sha256_msg_schedule_update(&X[6], X[7], X[15], X[4]); | ||||
| 			sha256_msg_schedule_update(&X[7], X[8], X[0], X[5]); | ||||
| 			sha256_msg_schedule_update(&X[8], X[9], X[1], X[6]); | ||||
| 			sha256_msg_schedule_update(&X[9], X[10], X[2], X[7]); | ||||
| 			sha256_msg_schedule_update(&X[10], X[11], X[3], X[8]); | ||||
| 			sha256_msg_schedule_update(&X[11], X[12], X[4], X[9]); | ||||
| 			sha256_msg_schedule_update(&X[12], X[13], X[5], X[10]); | ||||
| 			sha256_msg_schedule_update(&X[13], X[14], X[6], X[11]); | ||||
| 			sha256_msg_schedule_update(&X[14], X[15], X[7], X[12]); | ||||
| 			sha256_msg_schedule_update(&X[15], X[0], X[8], X[13]); | ||||
|  | ||||
| 			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 0], X[0]); | ||||
| 			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 1], X[1]); | ||||
| 			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 2], X[2]); | ||||
| 			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 3], X[3]); | ||||
| 			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 4], X[4]); | ||||
| 			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 5], X[5]); | ||||
| 			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 6], X[6]); | ||||
| 			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 7], X[7]); | ||||
| 			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 8], X[8]); | ||||
| 			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 9], X[9]); | ||||
| 			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 10], X[10]); | ||||
| 			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 11], X[11]); | ||||
| 			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 12], X[12]); | ||||
| 			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 13], X[13]); | ||||
| 			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 14], X[14]); | ||||
| 			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 15], X[15]); | ||||
| 		} | ||||
|  | ||||
| 		ctx->h[0] += a; | ||||
| 		ctx->h[1] += b; | ||||
| 		ctx->h[2] += c; | ||||
| 		ctx->h[3] += d; | ||||
| 		ctx->h[4] += e; | ||||
| 		ctx->h[5] += f; | ||||
| 		ctx->h[6] += g; | ||||
| 		ctx->h[7] += h; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int | ||||
| SHA256_Init(SHA256_CTX *c) | ||||
| { | ||||
| 	memset(c, 0, sizeof(*c)); | ||||
|  | ||||
| 	c->h[0] = 0x6a09e667UL; | ||||
| 	c->h[1] = 0xbb67ae85UL; | ||||
| 	c->h[2] = 0x3c6ef372UL; | ||||
| 	c->h[3] = 0xa54ff53aUL; | ||||
| 	c->h[4] = 0x510e527fUL; | ||||
| 	c->h[5] = 0x9b05688cUL; | ||||
| 	c->h[6] = 0x1f83d9abUL; | ||||
| 	c->h[7] = 0x5be0cd19UL; | ||||
|  | ||||
| 	c->md_len = SHA256_DIGEST_LENGTH; | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
| LCRYPTO_ALIAS(SHA256_Init); | ||||
|  | ||||
| int | ||||
| SHA256_Update(SHA256_CTX *c, const void *data_, size_t len) | ||||
| { | ||||
| 	const unsigned char *data = data_; | ||||
| 	unsigned char *p; | ||||
| 	SHA_LONG l; | ||||
| 	size_t n; | ||||
|  | ||||
| 	if (len == 0) | ||||
| 		return 1; | ||||
|  | ||||
| 	l = (c->Nl + (((SHA_LONG)len) << 3)) & 0xffffffffUL; | ||||
| 	/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to | ||||
| 	 * Wei Dai <weidai@eskimo.com> for pointing it out. */ | ||||
| 	if (l < c->Nl) /* overflow */ | ||||
| 		c->Nh++; | ||||
| 	c->Nh += (SHA_LONG)(len >> 29);	/* might cause compiler warning on 16-bit */ | ||||
| 	c->Nl = l; | ||||
|  | ||||
| 	n = c->num; | ||||
| 	if (n != 0) { | ||||
| 		p = (unsigned char *)c->data; | ||||
|  | ||||
| 		if (len >= SHA_CBLOCK || len + n >= SHA_CBLOCK) { | ||||
| 			memcpy(p + n, data, SHA_CBLOCK - n); | ||||
| 			sha256_block_data_order(c, p, 1); | ||||
| 			n = SHA_CBLOCK - n; | ||||
| 			data += n; | ||||
| 			len -= n; | ||||
| 			c->num = 0; | ||||
| 			memset(p, 0, SHA_CBLOCK);	/* keep it zeroed */ | ||||
| 		} else { | ||||
| 			memcpy(p + n, data, len); | ||||
| 			c->num += (unsigned int)len; | ||||
| 			return 1; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	n = len/SHA_CBLOCK; | ||||
| 	if (n > 0) { | ||||
| 		sha256_block_data_order(c, data, n); | ||||
| 		n *= SHA_CBLOCK; | ||||
| 		data += n; | ||||
| 		len -= n; | ||||
| 	} | ||||
|  | ||||
| 	if (len != 0) { | ||||
| 		p = (unsigned char *)c->data; | ||||
| 		c->num = (unsigned int)len; | ||||
| 		memcpy(p, data, len); | ||||
| 	} | ||||
| 	return 1; | ||||
| } | ||||
| LCRYPTO_ALIAS(SHA256_Update); | ||||
|  | ||||
| void | ||||
| SHA256_Transform(SHA256_CTX *c, const unsigned char *data) | ||||
| { | ||||
| 	sha256_block_data_order(c, data, 1); | ||||
| } | ||||
| LCRYPTO_ALIAS(SHA256_Transform); | ||||
|  | ||||
| int | ||||
| SHA256_Final(unsigned char *md, SHA256_CTX *c) | ||||
| { | ||||
| 	unsigned char *p = (unsigned char *)c->data; | ||||
| 	size_t n = c->num; | ||||
| 	unsigned int nn; | ||||
|  | ||||
| 	p[n] = 0x80; /* there is always room for one */ | ||||
| 	n++; | ||||
|  | ||||
| 	if (n > (SHA_CBLOCK - 8)) { | ||||
| 		memset(p + n, 0, SHA_CBLOCK - n); | ||||
| 		n = 0; | ||||
| 		sha256_block_data_order(c, p, 1); | ||||
| 	} | ||||
|  | ||||
| 	memset(p + n, 0, SHA_CBLOCK - 8 - n); | ||||
| 	c->data[SHA_LBLOCK - 2] = htobe32(c->Nh); | ||||
| 	c->data[SHA_LBLOCK - 1] = htobe32(c->Nl); | ||||
|  | ||||
| 	sha256_block_data_order(c, p, 1); | ||||
| 	c->num = 0; | ||||
| 	memset(p, 0, SHA_CBLOCK); | ||||
|  | ||||
| 	/* | ||||
| 	 * Note that FIPS180-2 discusses "Truncation of the Hash Function Output." | ||||
| 	 * default: case below covers for it. It's not clear however if it's | ||||
| 	 * permitted to truncate to amount of bytes not divisible by 4. I bet not, | ||||
| 	 * but if it is, then default: case shall be extended. For reference. | ||||
| 	 * Idea behind separate cases for pre-defined lengths is to let the | ||||
| 	 * compiler decide if it's appropriate to unroll small loops. | ||||
| 	 */ | ||||
| 	switch (c->md_len) { | ||||
| 	case SHA256_DIGEST_LENGTH: | ||||
| 		for (nn = 0; nn < SHA256_DIGEST_LENGTH / 4; nn++) { | ||||
| 			crypto_store_htobe32(md, c->h[nn]); | ||||
| 			md += 4; | ||||
| 		} | ||||
| 		break; | ||||
|  | ||||
| 	default: | ||||
| 		if (c->md_len > SHA256_DIGEST_LENGTH) | ||||
| 			return 0; | ||||
| 		for (nn = 0; nn < c->md_len / 4; nn++) { | ||||
| 			crypto_store_htobe32(md, c->h[nn]); | ||||
| 			md += 4; | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	return 1; | ||||
| } | ||||
| LCRYPTO_ALIAS(SHA256_Final); | ||||
|  | ||||
| unsigned char * | ||||
| SHA256(const unsigned char *d, size_t n, unsigned char *md) | ||||
| { | ||||
| 	SHA256_CTX c; | ||||
| 	static unsigned char m[SHA256_DIGEST_LENGTH]; | ||||
|  | ||||
| 	if (md == NULL) | ||||
| 		md = m; | ||||
|  | ||||
| 	SHA256_Init(&c); | ||||
| 	SHA256_Update(&c, d, n); | ||||
| 	SHA256_Final(md, &c); | ||||
|  | ||||
| 	memset(&c, 0, sizeof(c)); | ||||
|  | ||||
| 	return (md); | ||||
| } | ||||
| LCRYPTO_ALIAS(SHA256); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user