gnunet-svn
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]