gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [libmicrohttpd] branch master updated (c7d3fb71 -> 8d1a7ede


From: gnunet
Subject: [GNUnet-SVN] [libmicrohttpd] branch master updated (c7d3fb71 -> 8d1a7ede)
Date: Fri, 19 Apr 2019 08:50:15 +0200

This is an automated email from the git hooks/post-receive script.

karlson2k pushed a change to branch master
in repository libmicrohttpd.

    from c7d3fb71 Tests: added test_sha256 for SHA-256 testing
     new 2f1e0dcc .gitlab-ci.yml: added warnings flags, disabled parallel tests
     new 8d1a7ede SHA256: reimplemented from scratch, some ideas are borrowed 
from LGPLv2.1-licensed Libgcrypt

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .gitlab-ci.yml          |   7 +-
 src/microhttpd/sha256.c | 696 ++++++++++++++++++++++--------------------------
 src/microhttpd/sha256.h |  99 +++----
 3 files changed, 379 insertions(+), 423 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 131afe61..9343368a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -27,7 +27,7 @@ variables:
   MINGW_BUILD: buildenv-debian-mingw
   GET_SOURCES_ATTEMPTS: "3"
   CONFIGURE_BASE_FLAGS: --enable-asserts --cache-file cache/config.cache
-  CFLAGS_DEFAULT: -O0 -g -ggdb3
+  CFLAGS_DEFAULT: -O0 -g -ggdb3 -Wall -Wextra
 
 # In this build we combine
 #  * gcc
@@ -39,7 +39,7 @@ gcc/Stretch:
     - ./bootstrap
     - ./configure $CONFIGURE_BASE_FLAGS
     - make -j$(nproc)
-    - make -j$(nproc) check
+    - make check
     - make -j$(nproc) distcheck
   tags:
     - shared
@@ -65,6 +65,7 @@ Sanitizers/Stretch:
     - export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-3.8/bin/llvm-symbolizer
     - ./configure $CONFIGURE_BASE_FLAGS --disable-doc
     - make -j$(nproc) check
+    - make check
     - make -j$(nproc) distcheck
   tags:
     - shared
@@ -83,7 +84,7 @@ Scan-Build/Debian:
     - ./bootstrap
     - scan-build ./configure $CONFIGURE_BASE_FLAGS
     - scan-build -v -enable-checker security,nullability --status-bugs -o 
scan-build make -j$(nproc)
-    - scan-build -v -enable-checker security,nullability --status-bugs -o 
scan-build make -j$(nproc) check
+    - scan-build -v -enable-checker security,nullability --status-bugs -o 
scan-build make check
   tags:
     - shared
   except:
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]