[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] [libmicrohttpd] 02/02: SHA256: reimplemented from scratch,
From: |
gnunet |
Subject: |
[GNUnet-SVN] [libmicrohttpd] 02/02: SHA256: reimplemented from scratch, some ideas are borrowed from LGPLv2.1-licensed Libgcrypt |
Date: |
Fri, 19 Apr 2019 08:50:17 +0200 |
This is an automated email from the git hooks/post-receive script.
karlson2k pushed a commit to branch master
in repository libmicrohttpd.
commit 8d1a7ede98a1bb22132c34e115e58fcb49e0e610
Author: Evgeny Grin (Karlson2k) <address@hidden>
AuthorDate: Fri Apr 19 09:49:51 2019 +0300
SHA256: reimplemented from scratch,
some ideas are borrowed from LGPLv2.1-licensed Libgcrypt
---
src/microhttpd/sha256.c | 696 ++++++++++++++++++++++--------------------------
src/microhttpd/sha256.h | 99 +++----
2 files changed, 375 insertions(+), 420 deletions(-)
diff --git a/src/microhttpd/sha256.c b/src/microhttpd/sha256.c
index 977296f9..2c3c057d 100644
--- a/src/microhttpd/sha256.c
+++ b/src/microhttpd/sha256.c
@@ -1,407 +1,353 @@
-/* sha256.c
-
- The sha256 hash function.
- See http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
-
- Copyright (C) 2001 Niels Möller
- Copyright (C) 2018 Christian Grothoff (extraction of minimal subset
- from GNU Nettle to work with GNU libmicrohttpd)
-
- This file is part of GNU Nettle.
-
- GNU Nettle is free software: you can redistribute it and/or
- modify it under the terms of either:
-
- * the GNU Lesser General Public License as published by the Free
- Software Foundation; either version 3 of the License, or (at your
- option) any later version.
-
- or
-
- * the GNU General Public License as published by the Free
- Software Foundation; either version 2 of the License, or (at your
- option) any later version.
-
- or both in parallel, as here.
-
- GNU Nettle is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received copies of the GNU General Public License and
- the GNU Lesser General Public License along with this program. If
- not, see http://www.gnu.org/licenses/.
+/*
+ This file is part of libmicrohttpd
+ Copyright (C) 2019 Karlson2k (Evgeny Grin)
+ Some ideas are based on Libgcrypt implementation.
+ Copyright (C) 2003, 2006, 2008, 2009 Free Software Foundation, Inc.
+
+ libmicrohttpd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library.
+ If not, see <http://www.gnu.org/licenses/>.
*/
-/* Modelled after the sha1.c code by Peter Gutmann. */
+/**
+ * @file microhttpd/sha256.c
+ * @brief Calculation of SHA-256 digest as defined in FIPS PUB 180-4 (2015)
+ * @author Karlson2k (Evgeny Grin)
+ */
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
+/* Some tricks are based on Libgcrypt implementation. */
#include "sha256.h"
-
-/* Generated by the shadata program. */
-static const uint32_t
-K[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,
-};
-
-
-/* A block, treated as a sequence of 32-bit words. */
-#define SHA256_DATA_LENGTH 16
-
-/* The SHA256 functions. The Choice function is the same as the SHA1
- function f1, and the majority function is the same as the SHA1 f3
- function. They can be optimized to save one boolean operation each
- - thanks to Rich Schroeppel, address@hidden for discovering
- this */
-
-/* #define Choice(x,y,z) ( ( (x) & (y) ) | ( ~(x) & (z) ) ) */
-#define Choice(x,y,z) ( (z) ^ ( (x) & ( (y) ^ (z) ) ) )
-/* #define Majority(x,y,z) ( ((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)) ) */
-#define Majority(x,y,z) ( ((x) & (y)) ^ ((z) & ((x) ^ (y))) )
-
-#define S0(x) (ROTL32(30,(x)) ^ ROTL32(19,(x)) ^ ROTL32(10,(x)))
-#define S1(x) (ROTL32(26,(x)) ^ ROTL32(21,(x)) ^ ROTL32(7,(x)))
-
-#define s0(x) (ROTL32(25,(x)) ^ ROTL32(14,(x)) ^ ((x) >> 3))
-#define s1(x) (ROTL32(15,(x)) ^ ROTL32(13,(x)) ^ ((x) >> 10))
-
-/* The initial expanding function. The hash function is defined over an
- 64-word expanded input array W, where the first 16 are copies of the input
- data, and the remaining 64 are defined by
-
- W[ t ] = s1(W[t-2]) + W[t-7] + s0(W[i-15]) + W[i-16]
-
- This implementation generates these values on the fly in a circular
- buffer - thanks to Colin Plumb, address@hidden for this
- optimization.
-*/
-
-#define EXPAND(W,i) \
-( W[(i) & 15 ] += (s1(W[((i)-2) & 15]) + W[((i)-7) & 15] + s0(W[((i)-15) &
15])) )
-
-/* The prototype SHA sub-round. The fundamental sub-round is:
-
- T1 = h + S1(e) + Choice(e,f,g) + K[t] + W[t]
- T2 = S0(a) + Majority(a,b,c)
- a' = T1+T2
- b' = a
- c' = b
- d' = c
- e' = d + T1
- f' = e
- g' = f
- h' = g
-
- but this is implemented by unrolling the loop 8 times and renaming
- the variables
- ( h, a, b, c, d, e, f, g ) = ( a, b, c, d, e, f, g, h ) each
- iteration. */
-
-/* It's crucial that DATA is only used once, as that argument will
- * have side effects. */
-#define ROUND(a,b,c,d,e,f,g,h,k,data) do { \
- h += S1(e) + Choice(e,f,g) + k + data; \
- d += h; \
- h += S0(a) + Majority(a,b,c); \
- } while (0)
-
-
-/* Reads a 32-bit integer, in network, big-endian, byte order */
-#define READ_UINT32(p) \
-( (((uint32_t) (p)[0]) << 24) \
- | (((uint32_t) (p)[1]) << 16) \
- | (((uint32_t) (p)[2]) << 8) \
- | ((uint32_t) (p)[3]))
-
-#define WRITE_UINT32(p, i) \
-do { \
- (p)[0] = ((i) >> 24) & 0xff; \
- (p)[1] = ((i) >> 16) & 0xff; \
- (p)[2] = ((i) >> 8) & 0xff; \
- (p)[3] = (i) & 0xff; \
-} while(0)
-
-#define WRITE_UINT64(p, i) \
-do { \
- (p)[0] = ((i) >> 56) & 0xff; \
- (p)[1] = ((i) >> 48) & 0xff; \
- (p)[2] = ((i) >> 40) & 0xff; \
- (p)[3] = ((i) >> 32) & 0xff; \
- (p)[4] = ((i) >> 24) & 0xff; \
- (p)[5] = ((i) >> 16) & 0xff; \
- (p)[6] = ((i) >> 8) & 0xff; \
- (p)[7] = (i) & 0xff; \
-} while(0)
-
-/* The masking of the right shift is needed to allow n == 0 (using
- just 32 - n and 64 - n results in undefined behaviour). Most uses
- of these macros use a constant and non-zero rotation count. */
-#define ROTL32(n,x) (((x)<<(n)) | ((x)>>((-(n)&31))))
-
-static void
-_nettle_sha256_compress(uint32_t *state, const uint8_t *input, const uint32_t
*k)
-{
- uint32_t data[SHA256_DATA_LENGTH];
- uint32_t A, B, C, D, E, F, G, H; /* Local vars */
- unsigned i;
- uint32_t *d;
-
- for (i = 0; i < SHA256_DATA_LENGTH; i++, input+= 4)
- {
- data[i] = READ_UINT32(input);
- }
-
- /* Set up first buffer and local data buffer */
- A = state[0];
- B = state[1];
- C = state[2];
- D = state[3];
- E = state[4];
- F = state[5];
- G = state[6];
- H = state[7];
-
- /* Heavy mangling */
- /* First 16 subrounds that act on the original data */
-
- for (i = 0, d = data; i<16; i+=8, k += 8, d+= 8)
- {
- ROUND(A, B, C, D, E, F, G, H, k[0], d[0]);
- ROUND(H, A, B, C, D, E, F, G, k[1], d[1]);
- ROUND(G, H, A, B, C, D, E, F, k[2], d[2]);
- ROUND(F, G, H, A, B, C, D, E, k[3], d[3]);
- ROUND(E, F, G, H, A, B, C, D, k[4], d[4]);
- ROUND(D, E, F, G, H, A, B, C, k[5], d[5]);
- ROUND(C, D, E, F, G, H, A, B, k[6], d[6]);
- ROUND(B, C, D, E, F, G, H, A, k[7], d[7]);
- }
-
- for (; i<64; i += 16, k+= 16)
- {
- ROUND(A, B, C, D, E, F, G, H, k[ 0], EXPAND(data, 0));
- ROUND(H, A, B, C, D, E, F, G, k[ 1], EXPAND(data, 1));
- ROUND(G, H, A, B, C, D, E, F, k[ 2], EXPAND(data, 2));
- ROUND(F, G, H, A, B, C, D, E, k[ 3], EXPAND(data, 3));
- ROUND(E, F, G, H, A, B, C, D, k[ 4], EXPAND(data, 4));
- ROUND(D, E, F, G, H, A, B, C, k[ 5], EXPAND(data, 5));
- ROUND(C, D, E, F, G, H, A, B, k[ 6], EXPAND(data, 6));
- ROUND(B, C, D, E, F, G, H, A, k[ 7], EXPAND(data, 7));
- ROUND(A, B, C, D, E, F, G, H, k[ 8], EXPAND(data, 8));
- ROUND(H, A, B, C, D, E, F, G, k[ 9], EXPAND(data, 9));
- ROUND(G, H, A, B, C, D, E, F, k[10], EXPAND(data, 10));
- ROUND(F, G, H, A, B, C, D, E, k[11], EXPAND(data, 11));
- ROUND(E, F, G, H, A, B, C, D, k[12], EXPAND(data, 12));
- ROUND(D, E, F, G, H, A, B, C, k[13], EXPAND(data, 13));
- ROUND(C, D, E, F, G, H, A, B, k[14], EXPAND(data, 14));
- ROUND(B, C, D, E, F, G, H, A, k[15], EXPAND(data, 15));
- }
-
- /* Update state */
- state[0] += A;
- state[1] += B;
- state[2] += C;
- state[3] += D;
- state[4] += E;
- state[5] += F;
- state[6] += G;
- state[7] += H;
-}
-
-
-#define COMPRESS(ctx, data) (_nettle_sha256_compress((ctx)->state, (data), K))
-
-/* Initialize the SHA values */
-
+#include <string.h>
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif /* HAVE_MEMORY_H */
+#include "mhd_bithelpers.h"
+#include "mhd_assert.h"
+
+/**
+ * Initialise structure for SHA256 calculation.
+ *
+ * @param ctx_ must be a `struct sha256_ctx *`
+ */
void
sha256_init (void *ctx_)
{
- /* Initial values, also generated by the shadata program. */
- static const uint32_t H0[_SHA256_DIGEST_LENGTH] =
- {
- 0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL,
- 0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL,
- };
- struct sha256_ctx *ctx = ctx_;
-
- memcpy(ctx->state, H0, sizeof(H0));
-
- /* Initialize bit count */
+ struct sha256_ctx *const ctx = ctx_;
+ /* Initial hash values, see FIPS PUB 180-4 paragraph 5.3.3 */
+ /* First thirty-two bits of the fractional parts of the square
+ * roots of the first eight prime numbers: 2, 3, 5, 7, 11, 13,
+ * 17, 19." */
+ ctx->H[0] = 0x6a09e667UL;
+ ctx->H[1] = 0xbb67ae85UL;
+ ctx->H[2] = 0x3c6ef372UL;
+ ctx->H[3] = 0xa54ff53aUL;
+ ctx->H[4] = 0x510e527fUL;
+ ctx->H[5] = 0x9b05688cUL;
+ ctx->H[6] = 0x1f83d9abUL;
+ ctx->H[7] = 0x5be0cd19UL;
+
+ /* Initialise number of bytes. */
ctx->count = 0;
-
- /* Initialize buffer */
- ctx->index = 0;
}
+/**
+ * Number of bytes in single SHA-256 word
+ * used to process data
+ */
+#define SHA256_BYTES_IN_WORD 4
+
+/**
+ * Length of data block in words
+ */
+#define SHA256_BLOCK_LENGTH (SHA256_BLOCK_SIZE / SHA256_BYTES_IN_WORD)
+
+/**
+ * Base of SHA-256 transformation.
+ * Gets full 64 bytes block of data and updates hash values;
+ * @param H hash values
+ * @param data data, must be exactly 64 bytes long
+ */
+static void
+sha256_transform (uint32_t H[_SHA256_DIGEST_LENGTH],
+ const uint8_t data[SHA256_BLOCK_SIZE])
+{
+ /* Working variables,
+ see FIPS PUB 180-4 paragraph 6.2. */
+ uint32_t a = H[0];
+ uint32_t b = H[1];
+ uint32_t c = H[2];
+ uint32_t d = H[3];
+ uint32_t e = H[4];
+ uint32_t f = H[5];
+ uint32_t g = H[6];
+ uint32_t h = H[7];
+
+ /* Data buffer, used as cyclic buffer.
+ See FIPS PUB 180-4 paragraphs 5.2.1, 6.2. */
+ uint32_t W[16];
+
+ /* 'Ch' and 'Maj' macro functions are defined with
+ widely-used optimization.
+ See FIPS PUB 180-4 formulae 4.2, 4.3. */
+#define Ch(x,y,z) ( (z) ^ ((x) & ((y) ^ (z))) )
+#define Maj(x,y,z) ( ((x) & (y)) ^ ((z) & ((x) ^ (y))) )
+ /* Unoptimized (original) versions: */
+/* #define Ch(x,y,z) ( ( (x) & (y) ) | ( ~(x) & (z) ) ) */
+/* #define Maj(x,y,z) ( ((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)) ) */
+
+ /* Four 'Sigma' macro functions.
+ See FIPS PUB 180-4 formulae 4.4, 4.5, 4.6, 4.7. */
+#define SIG0(x) ( _MHD_ROTR32((x),2) ^ _MHD_ROTR32((x),13) ^
_MHD_ROTR32((x),22) )
+#define SIG1(x) ( _MHD_ROTR32((x),6) ^ _MHD_ROTR32((x),11) ^
_MHD_ROTR32((x),25) )
+#define sig0(x) ( _MHD_ROTR32((x),7) ^ _MHD_ROTR32((x),18) ^ ((x) >> 3) )
+#define sig1(x) ( _MHD_ROTR32((x),17) ^ _MHD_ROTR32((x),19) ^ ((x) >> 10) )
+
+ /* Single step of SHA-256 computation,
+ see FIPS PUB 180-4 paragraph 6.2.2 step 3.
+ * Note: instead of reassigning all working variables on each step,
+ variables are rotated for each step:
+ SHA2STEP32(a, b, c, d, e, f, g, h, K[0], data[0]);
+ SHA2STEP32(h, a, b, c, d, e, f, g, K[1], data[1]);
+ so current 'vD' will be used as 'vE' on next step,
+ current 'vH' will be used as 'vA' on next step.
+ * Note: first (vH += SIG1(vE) + Ch(vE,vF,vG) + kt + wt) equals T1 in FIPS
PUB 180-4 paragraph 6.2.2 step 3.
+ second (vH += SIG0(vA) + Maj(vE,vF,vC) equals T1 + T2 in FIPS PUB
180-4 paragraph 6.2.2 step 3.
+ * Note: 'wt' must be used exactly one time in this macro as it change other
data as well
+ every time when used. */
+#define SHA2STEP32(vA,vB,vC,vD,vE,vF,vG,vH,kt,wt) do { \
+ (vD) += ((vH) += SIG1((vE)) + Ch((vE),(vF),(vG)) + (kt) + (wt)); \
+ (vH) += SIG0((vA)) + Maj((vA),(vB),(vC)); } while (0)
+
+ /* Get value of W(t) from input data buffer,
+ See FIPS PUB 180-4 paragraph 6.2.
+ Input data must be read in big-endian bytes order,
+ see FIPS PUB 180-4 paragraph 3.1.2. */
+#define GET_W_FROM_DATA(buf,t) \
+ _MHD_GET_32BIT_BE(((uint8_t*)(buf)) + (t) * SHA256_BYTES_IN_WORD)
+
+ /* During first 16 steps, before making any calculations on each step,
+ the W element is read from input data buffer as big-endian value and
+ stored in array of W elements. */
+ /* Note: instead of using K constants as array, all K values are specified
+ individually for each step, see FIPS PUB 180-4 paragraph 4.2.2 for K
values. */
+ SHA2STEP32(a, b, c, d, e, f, g, h, 0x428a2f98UL, W[0] =
GET_W_FROM_DATA(data,0));
+ SHA2STEP32(h, a, b, c, d, e, f, g, 0x71374491UL, W[1] =
GET_W_FROM_DATA(data,1));
+ SHA2STEP32(g, h, a, b, c, d, e, f, 0xb5c0fbcfUL, W[2] =
GET_W_FROM_DATA(data,2));
+ SHA2STEP32(f, g, h, a, b, c, d, e, 0xe9b5dba5UL, W[3] =
GET_W_FROM_DATA(data,3));
+ SHA2STEP32(e, f, g, h, a, b, c, d, 0x3956c25bUL, W[4] =
GET_W_FROM_DATA(data,4));
+ SHA2STEP32(d, e, f, g, h, a, b, c, 0x59f111f1UL, W[5] =
GET_W_FROM_DATA(data,5));
+ SHA2STEP32(c, d, e, f, g, h, a, b, 0x923f82a4UL, W[6] =
GET_W_FROM_DATA(data,6));
+ SHA2STEP32(b, c, d, e, f, g, h, a, 0xab1c5ed5UL, W[7] =
GET_W_FROM_DATA(data,7));
+ SHA2STEP32(a, b, c, d, e, f, g, h, 0xd807aa98UL, W[8] =
GET_W_FROM_DATA(data,8));
+ SHA2STEP32(h, a, b, c, d, e, f, g, 0x12835b01UL, W[9] =
GET_W_FROM_DATA(data,9));
+ SHA2STEP32(g, h, a, b, c, d, e, f, 0x243185beUL, W[10] =
GET_W_FROM_DATA(data,10));
+ SHA2STEP32(f, g, h, a, b, c, d, e, 0x550c7dc3UL, W[11] =
GET_W_FROM_DATA(data,11));
+ SHA2STEP32(e, f, g, h, a, b, c, d, 0x72be5d74UL, W[12] =
GET_W_FROM_DATA(data,12));
+ SHA2STEP32(d, e, f, g, h, a, b, c, 0x80deb1feUL, W[13] =
GET_W_FROM_DATA(data,13));
+ SHA2STEP32(c, d, e, f, g, h, a, b, 0x9bdc06a7UL, W[14] =
GET_W_FROM_DATA(data,14));
+ SHA2STEP32(b, c, d, e, f, g, h, a, 0xc19bf174UL, W[15] =
GET_W_FROM_DATA(data,15));
+
+ /* 'W' generation and assignment for 16 <= t <= 63.
+ See FIPS PUB 180-4 paragraph 6.2.2.
+ As only last 16 'W' are used in calculations, it is possible to
+ use 16 elements array of W as cyclic buffer.
+ * Note: ((t-16)&0xf) have same value as (t&0xf) */
+#define Wgen(w,t) ( (w)[(t-16)&0xf] + sig1((w)[((t)-2)&0xf]) + \
+ (w)[((t)-7)&0xf] + sig0((w)[((t)-15)&0xf]) )
+
+ /* During last 48 steps, before making any calculations on each step,
+ W element is generated from W elements of cyclic buffer and generated
value
+ stored back in cyclic buffer. */
+ /* Note: instead of using K constants as array, all K values are specified
+ individually for each step, see FIPS PUB 180-4 paragraph 4.2.2 for K
values. */
+ SHA2STEP32(a, b, c, d, e, f, g, h, 0xe49b69c1UL, W[16&0xf] = Wgen(W,16));
+ SHA2STEP32(h, a, b, c, d, e, f, g, 0xefbe4786UL, W[17&0xf] = Wgen(W,17));
+ SHA2STEP32(g, h, a, b, c, d, e, f, 0x0fc19dc6UL, W[18&0xf] = Wgen(W,18));
+ SHA2STEP32(f, g, h, a, b, c, d, e, 0x240ca1ccUL, W[19&0xf] = Wgen(W,19));
+ SHA2STEP32(e, f, g, h, a, b, c, d, 0x2de92c6fUL, W[20&0xf] = Wgen(W,20));
+ SHA2STEP32(d, e, f, g, h, a, b, c, 0x4a7484aaUL, W[21&0xf] = Wgen(W,21));
+ SHA2STEP32(c, d, e, f, g, h, a, b, 0x5cb0a9dcUL, W[22&0xf] = Wgen(W,22));
+ SHA2STEP32(b, c, d, e, f, g, h, a, 0x76f988daUL, W[23&0xf] = Wgen(W,23));
+ SHA2STEP32(a, b, c, d, e, f, g, h, 0x983e5152UL, W[24&0xf] = Wgen(W,24));
+ SHA2STEP32(h, a, b, c, d, e, f, g, 0xa831c66dUL, W[25&0xf] = Wgen(W,25));
+ SHA2STEP32(g, h, a, b, c, d, e, f, 0xb00327c8UL, W[26&0xf] = Wgen(W,26));
+ SHA2STEP32(f, g, h, a, b, c, d, e, 0xbf597fc7UL, W[27&0xf] = Wgen(W,27));
+ SHA2STEP32(e, f, g, h, a, b, c, d, 0xc6e00bf3UL, W[28&0xf] = Wgen(W,28));
+ SHA2STEP32(d, e, f, g, h, a, b, c, 0xd5a79147UL, W[29&0xf] = Wgen(W,29));
+ SHA2STEP32(c, d, e, f, g, h, a, b, 0x06ca6351UL, W[30&0xf] = Wgen(W,30));
+ SHA2STEP32(b, c, d, e, f, g, h, a, 0x14292967UL, W[31&0xf] = Wgen(W,31));
+ SHA2STEP32(a, b, c, d, e, f, g, h, 0x27b70a85UL, W[32&0xf] = Wgen(W,32));
+ SHA2STEP32(h, a, b, c, d, e, f, g, 0x2e1b2138UL, W[33&0xf] = Wgen(W,33));
+ SHA2STEP32(g, h, a, b, c, d, e, f, 0x4d2c6dfcUL, W[34&0xf] = Wgen(W,34));
+ SHA2STEP32(f, g, h, a, b, c, d, e, 0x53380d13UL, W[35&0xf] = Wgen(W,35));
+ SHA2STEP32(e, f, g, h, a, b, c, d, 0x650a7354UL, W[36&0xf] = Wgen(W,36));
+ SHA2STEP32(d, e, f, g, h, a, b, c, 0x766a0abbUL, W[37&0xf] = Wgen(W,37));
+ SHA2STEP32(c, d, e, f, g, h, a, b, 0x81c2c92eUL, W[38&0xf] = Wgen(W,38));
+ SHA2STEP32(b, c, d, e, f, g, h, a, 0x92722c85UL, W[39&0xf] = Wgen(W,39));
+ SHA2STEP32(a, b, c, d, e, f, g, h, 0xa2bfe8a1UL, W[40&0xf] = Wgen(W,40));
+ SHA2STEP32(h, a, b, c, d, e, f, g, 0xa81a664bUL, W[41&0xf] = Wgen(W,41));
+ SHA2STEP32(g, h, a, b, c, d, e, f, 0xc24b8b70UL, W[42&0xf] = Wgen(W,42));
+ SHA2STEP32(f, g, h, a, b, c, d, e, 0xc76c51a3UL, W[43&0xf] = Wgen(W,43));
+ SHA2STEP32(e, f, g, h, a, b, c, d, 0xd192e819UL, W[44&0xf] = Wgen(W,44));
+ SHA2STEP32(d, e, f, g, h, a, b, c, 0xd6990624UL, W[45&0xf] = Wgen(W,45));
+ SHA2STEP32(c, d, e, f, g, h, a, b, 0xf40e3585UL, W[46&0xf] = Wgen(W,46));
+ SHA2STEP32(b, c, d, e, f, g, h, a, 0x106aa070UL, W[47&0xf] = Wgen(W,47));
+ SHA2STEP32(a, b, c, d, e, f, g, h, 0x19a4c116UL, W[48&0xf] = Wgen(W,48));
+ SHA2STEP32(h, a, b, c, d, e, f, g, 0x1e376c08UL, W[49&0xf] = Wgen(W,49));
+ SHA2STEP32(g, h, a, b, c, d, e, f, 0x2748774cUL, W[50&0xf] = Wgen(W,50));
+ SHA2STEP32(f, g, h, a, b, c, d, e, 0x34b0bcb5UL, W[51&0xf] = Wgen(W,51));
+ SHA2STEP32(e, f, g, h, a, b, c, d, 0x391c0cb3UL, W[52&0xf] = Wgen(W,52));
+ SHA2STEP32(d, e, f, g, h, a, b, c, 0x4ed8aa4aUL, W[53&0xf] = Wgen(W,53));
+ SHA2STEP32(c, d, e, f, g, h, a, b, 0x5b9cca4fUL, W[54&0xf] = Wgen(W,54));
+ SHA2STEP32(b, c, d, e, f, g, h, a, 0x682e6ff3UL, W[55&0xf] = Wgen(W,55));
+ SHA2STEP32(a, b, c, d, e, f, g, h, 0x748f82eeUL, W[56&0xf] = Wgen(W,56));
+ SHA2STEP32(h, a, b, c, d, e, f, g, 0x78a5636fUL, W[57&0xf] = Wgen(W,57));
+ SHA2STEP32(g, h, a, b, c, d, e, f, 0x84c87814UL, W[58&0xf] = Wgen(W,58));
+ SHA2STEP32(f, g, h, a, b, c, d, e, 0x8cc70208UL, W[59&0xf] = Wgen(W,59));
+ SHA2STEP32(e, f, g, h, a, b, c, d, 0x90befffaUL, W[60&0xf] = Wgen(W,60));
+ SHA2STEP32(d, e, f, g, h, a, b, c, 0xa4506cebUL, W[61&0xf] = Wgen(W,61));
+ SHA2STEP32(c, d, e, f, g, h, a, b, 0xbef9a3f7UL, W[62&0xf] = Wgen(W,62));
+ SHA2STEP32(b, c, d, e, f, g, h, a, 0xc67178f2UL, W[63&0xf] = Wgen(W,63));
+
+ /* Compute intermediate hash.
+ See FIPS PUB 180-4 paragraph 4.2.2 step 4. */
+ H[0] += a;
+ H[1] += b;
+ H[2] += c;
+ H[3] += d;
+ H[4] += e;
+ H[5] += f;
+ H[6] += g;
+ H[7] += h;
+}
-/* Takes the compression function f as argument. NOTE: also clobbers
- length and data. */
-#define MD_UPDATE(ctx, length, data, f, incr) \
- do { \
- if ((ctx)->index) \
- {
\
- /* Try to fill partial block */ \
- unsigned __md_left = sizeof((ctx)->block) - (ctx)->index; \
- if ((length) < __md_left) \
- { \
- memcpy((ctx)->block + (ctx)->index, (data), (length)); \
- (ctx)->index += (length); \
- goto __md_done; /* Finished */ \
- } \
- else \
- { \
- memcpy((ctx)->block + (ctx)->index, (data), __md_left); \
- \
- f((ctx), (ctx)->block); \
- (incr); \
- \
- (data) += __md_left; \
- (length) -= __md_left; \
- } \
- }
\
- while ((length) >= sizeof((ctx)->block)) \
- {
\
- f((ctx), (data)); \
- (incr); \
- \
- (data) += sizeof((ctx)->block); \
- (length) -= sizeof((ctx)->block); \
- }
\
- memcpy ((ctx)->block, (data), (length)); \
- (ctx)->index = (length); \
- __md_done: \
- ; \
- } while (0)
-
-/* Pads the block to a block boundary with the bit pattern 1 0*,
- leaving size octets for the length field at the end. If needed,
- compresses the block and starts a new one. */
-#define MD_PAD(ctx, size, f) \
- do { \
- unsigned __md_i; \
- __md_i = (ctx)->index; \
- \
- /* Set the first char of padding to 0x80. This is safe since there \
- is always at least one byte free */ \
- \
- assert(__md_i < sizeof((ctx)->block)); \
- (ctx)->block[__md_i++] = 0x80; \
- \
- if (__md_i > (sizeof((ctx)->block) - (size))) \
- { /* No room for length in this block. Process it and \
- pad with another one */ \
- memset((ctx)->block + __md_i, 0, sizeof((ctx)->block) - __md_i); \
- \
- f((ctx), (ctx)->block); \
- __md_i = 0; \
- }
\
- memset((ctx)->block + __md_i, 0, \
- sizeof((ctx)->block) - (size) - __md_i); \
- \
- } while (0)
-
-
+/**
+ * Process portion of bytes.
+ *
+ * @param ctx_ must be a `struct sha256_ctx *`
+ * @param data bytes to add to hash
+ * @param length number of bytes in @a data
+ */
void
sha256_update (void *ctx_,
const uint8_t *data,
size_t length)
{
- struct sha256_ctx *ctx = ctx_;
- MD_UPDATE (ctx, length, data, COMPRESS, ctx->count++);
-}
-
-
-
-void
-_nettle_write_be32(size_t length, uint8_t *dst,
- const uint32_t *src)
-{
- size_t i;
- size_t words;
- unsigned leftover;
+ struct sha256_ctx *const ctx = ctx_;
+ unsigned bytes_have; /**< Number of bytes in buffer */
- words = length / 4;
- leftover = length % 4;
+ mhd_assert((data != NULL) || (length == 0));
- for (i = 0; i < words; i++, dst += 4)
- WRITE_UINT32(dst, src[i]);
+ /* Note: (count & (SHA256_BLOCK_SIZE-1))
+ equal (count % SHA256_BLOCK_SIZE) for this block size. */
+ bytes_have = (unsigned)(ctx->count & (SHA256_BLOCK_SIZE-1));
+ ctx->count += length;
- if (leftover)
+ if (bytes_have)
{
- uint32_t word;
- unsigned j = leftover;
-
- word = src[i];
-
- switch (leftover)
- {
- default:
- abort();
- case 3:
- dst[--j] = (word >> 8) & 0xff;
- /* Fall through */
- case 2:
- dst[--j] = (word >> 16) & 0xff;
- /* Fall through */
- case 1:
- dst[--j] = (word >> 24) & 0xff;
- }
+ unsigned bytes_left = SHA256_BLOCK_SIZE - bytes_have;
+ if (length >= bytes_left)
+ { /* Combine new data with data in buffer and
+ process full block. */
+ memcpy (ctx->buffer + bytes_have,
+ data,
+ bytes_left);
+ data += bytes_left;
+ length -= bytes_left;
+ sha256_transform (ctx->H, ctx->buffer);
+ bytes_have = 0;
+ }
}
-}
-
-static void
-sha256_write_digest (struct sha256_ctx *ctx,
- size_t length,
- uint8_t *digest)
-{
- uint64_t bit_count;
-
- assert(length <= SHA256_DIGEST_SIZE);
-
- MD_PAD(ctx, 8, COMPRESS);
+ while (length >= SHA256_BLOCK_SIZE)
+ { /* Process any full blocks of new data directly,
+ without copying to buffer. */
+ sha256_transform (ctx->H, data);
+ data += SHA256_BLOCK_SIZE;
+ length -= SHA256_BLOCK_SIZE;
+ }
- /* There are 512 = 2^9 bits in one block */
- bit_count = (ctx->count << 9) | (ctx->index << 3);
+ if (length != 0)
+ { /* Copy incomplete block of new data (if any)
+ to buffer. */
+ memcpy (ctx->buffer + bytes_have, data, length);
+ }
+}
- /* This is slightly inefficient, as the numbers are converted to
- big-endian format, and will be converted back by the compression
- function. It's probably not worth the effort to fix this. */
- WRITE_UINT64(ctx->block + (SHA256_BLOCK_SIZE - 8), bit_count);
- COMPRESS(ctx, ctx->block);
- _nettle_write_be32(length, digest, ctx->state);
-}
+/**
+ * Size of "length" padding addition in bytes.
+ * See FIPS PUB 180-4 paragraph 5.1.1.
+ */
+#define SHA256_SIZE_OF_LEN_ADD (64 / 8)
+/**
+ * Finalise SHA256 calculation, return digest.
+ *
+ * @param ctx_ must be a `struct sha256_ctx *`
+ * @param digest[out] set to the hash, must be #SHA256_DIGEST_SIZE bytes
+ */
void
-sha256_digest (void *ctx_,
- uint8_t *digest)
+sha256_finish (void *ctx_,
+ uint8_t digest[SHA256_DIGEST_SIZE])
{
- struct sha256_ctx *ctx = ctx_;
+ struct sha256_ctx *const ctx = ctx_;
+ uint64_t num_bits; /**< Number of processed bits */
+ unsigned bytes_have; /**< Number of bytes in buffer */
+
+ num_bits = ctx->count << 3;
+ /* Note: (count & (SHA256_BLOCK_SIZE-1))
+ equal (count % SHA256_BLOCK_SIZE) for this block size. */
+ bytes_have = (unsigned)(ctx->count & (SHA256_BLOCK_SIZE-1));
+
+ /* Input data must be padded with bit "1" and with length of data in bits.
+ See FIPS PUB 180-4 paragraph 5.1.1. */
+ /* Data is always processed in form of bytes (not by individual bits),
+ therefore position of first padding bit in byte is always predefined
(0x80). */
+ /* Buffer always have space at least for one byte (as full buffers are
+ processed immediately). */
+ ctx->buffer[bytes_have++] = 0x80;
+
+ if (SHA256_BLOCK_SIZE - bytes_have < SHA256_SIZE_OF_LEN_ADD)
+ { /* No space in current block to put total length of message.
+ Pad current block with zeros and process it. */
+ while (bytes_have < SHA256_BLOCK_SIZE) ctx->buffer[bytes_have++] = 0;
+ /* Process full block. */
+ sha256_transform (ctx->H, ctx->buffer);
+ /* Start new block. */
+ bytes_have = 0;
+ }
- sha256_write_digest (ctx,
- SHA256_DIGEST_SIZE,
- digest);
- sha256_init (ctx);
+ /* Pad the rest of the buffer with zeros. */
+ memset(ctx->buffer + bytes_have, 0,
+ SHA256_BLOCK_SIZE - SHA256_SIZE_OF_LEN_ADD - bytes_have);
+ /* Put number of bits in processed message as big-endian value. */
+ _MHD_PUT_64BIT_BE(ctx->buffer + SHA256_BLOCK_SIZE - SHA256_SIZE_OF_LEN_ADD,
num_bits);
+ /* Process full final block. */
+ sha256_transform (ctx->H, ctx->buffer);
+
+ /* Put final hash/digest in BE mode */
+ _MHD_PUT_32BIT_BE(digest + 0 * SHA256_BYTES_IN_WORD, ctx->H[0]);
+ _MHD_PUT_32BIT_BE(digest + 1 * SHA256_BYTES_IN_WORD, ctx->H[1]);
+ _MHD_PUT_32BIT_BE(digest + 2 * SHA256_BYTES_IN_WORD, ctx->H[2]);
+ _MHD_PUT_32BIT_BE(digest + 3 * SHA256_BYTES_IN_WORD, ctx->H[3]);
+ _MHD_PUT_32BIT_BE(digest + 4 * SHA256_BYTES_IN_WORD, ctx->H[4]);
+ _MHD_PUT_32BIT_BE(digest + 5 * SHA256_BYTES_IN_WORD, ctx->H[5]);
+ _MHD_PUT_32BIT_BE(digest + 6 * SHA256_BYTES_IN_WORD, ctx->H[6]);
+ _MHD_PUT_32BIT_BE(digest + 7 * SHA256_BYTES_IN_WORD, ctx->H[7]);
+
+ /* Erase potentially sensitive data. */
+ memset(ctx, 0, sizeof(struct sha256_ctx));
}
diff --git a/src/microhttpd/sha256.h b/src/microhttpd/sha256.h
index 5eee4a41..77064c7c 100644
--- a/src/microhttpd/sha256.h
+++ b/src/microhttpd/sha256.h
@@ -1,58 +1,64 @@
-/* sha256.h
-
- The sha256 hash function.
-
- Copyright (C) 2001, 2012 Niels Möller
- Copyright (C) 2018 Christian Grothoff (extraction of minimal subset
- from GNU Nettle to work with GNU libmicrohttpd)
-
- This file is part of GNU Nettle.
-
- GNU Nettle is free software: you can redistribute it and/or
- modify it under the terms of either:
-
- * the GNU Lesser General Public License as published by the Free
- Software Foundation; either version 3 of the License, or (at your
- option) any later version.
+/*
+ This file is part of libmicrohttpd
+ Copyright (C) 2019 Karlson2k (Evgeny Grin)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library.
+ If not, see <http://www.gnu.org/licenses/>.
+*/
- or
+/**
+ * @file microhttpd/sha256.h
+ * @brief Calculation of SHA-256 digest
+ * @author Karlson2k (Evgeny Grin)
+ */
- * the GNU General Public License as published by the Free
- Software Foundation; either version 2 of the License, or (at your
- option) any later version.
+#ifndef MHD_SHA256_H
+#define MHD_SHA256_H 1
- or both in parallel, as here.
+#include "mhd_options.h"
+#include <stdint.h>
- GNU Nettle is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+/**
+ * Digest is kept internally as 8 32-bit words.
+ */
+#define _SHA256_DIGEST_LENGTH 8
- You should have received copies of the GNU General Public License and
- the GNU Lesser General Public License along with this program. If
- not, see http://www.gnu.org/licenses/.
-*/
+/**
+ * Size of SHA-256 digest in bytes
+ */
+#define SHA256_DIGEST_SIZE (_SHA256_DIGEST_LENGTH * 4)
-#ifndef NETTLE_SHA2_H_INCLUDED
-#define NETTLE_SHA2_H_INCLUDED
+/**
+ * Size of SHA-256 digest string in chars
+ */
+#define SHA256_DIGEST_STRING_SIZE ((SHA256_DIGEST_SIZE) * 2 + 1)
-#define SHA256_DIGEST_SIZE 32
+/**
+ * Size of single processing block in bytes
+ */
#define SHA256_BLOCK_SIZE 64
-/* Digest is kept internally as 8 32-bit words. */
-#define _SHA256_DIGEST_LENGTH 8
struct sha256_ctx
{
- uint32_t state[_SHA256_DIGEST_LENGTH]; /* State variables */
- uint64_t count; /* 64-bit block count */
- uint8_t block[SHA256_BLOCK_SIZE]; /* SHA256 data buffer */
- unsigned int index; /* index into buffer */
+ uint32_t H[_SHA256_DIGEST_LENGTH]; /**< Intermediate hash value / digest
at end of calculation */
+ uint64_t count; /**< number of bytes, mod 2^64 */
+ uint8_t buffer[SHA256_BLOCK_SIZE]; /**< SHA256 input data buffer */
};
-
/**
- * Start SHA256 calculation.
+ * Initialise structure for SHA256 calculation.
*
* @param ctx_ must be a `struct sha256_ctx *`
*/
@@ -61,25 +67,28 @@ sha256_init (void *ctx_);
/**
- * Update hash calculation.
+ * Process portion of bytes.
*
* @param ctx_ must be a `struct sha256_ctx *`
- * @param length number of bytes in @a data
* @param data bytes to add to hash
+ * @param length number of bytes in @a data
*/
void
sha256_update (void *ctx_,
const uint8_t *data,
size_t length);
+
/**
- * Complete SHA256 calculation.
+ * Finalise SHA256 calculation, return digest.
*
* @param ctx_ must be a `struct sha256_ctx *`
* @param digest[out] set to the hash, must be #SHA256_DIGEST_SIZE bytes
*/
void
-sha256_digest (void *ctx_,
+sha256_finish (void *ctx_,
uint8_t digest[SHA256_DIGEST_SIZE]);
-#endif /* NETTLE_SHA2_H_INCLUDED */
+#define sha256_digest sha256_finish
+
+#endif /* MHD_SHA256_H */
--
To stop receiving notification emails like this one, please contact
address@hidden