gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [libmicrohttpd] branch master updated: import sha256 from G


From: gnunet
Subject: [GNUnet-SVN] [libmicrohttpd] branch master updated: import sha256 from GNU Nettle
Date: Tue, 20 Nov 2018 20:05:34 +0100

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

grothoff pushed a commit to branch master
in repository libmicrohttpd.

The following commit(s) were added to refs/heads/master by this push:
     new 8466a08d import sha256 from GNU Nettle
8466a08d is described below

commit 8466a08d3588608f018722d6a176ced2e0c2a539
Author: Christian Grothoff <address@hidden>
AuthorDate: Tue Nov 20 20:05:30 2018 +0100

    import sha256 from GNU Nettle
---
 src/microhttpd/sha256.c | 401 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/microhttpd/sha256.h |  74 +++++++++
 2 files changed, 475 insertions(+)

diff --git a/src/microhttpd/sha256.c b/src/microhttpd/sha256.c
new file mode 100644
index 00000000..12675a73
--- /dev/null
+++ b/src/microhttpd/sha256.c
@@ -0,0 +1,401 @@
+/* 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/.
+*/
+
+/* Modelled after the sha1.c code by Peter Gutmann. */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#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 */
+
+void
+sha256_init(struct sha256_ctx *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, 
+  };
+
+  memcpy(ctx->state, H0, sizeof(H0));
+
+  /* Initialize bit count */
+  ctx->count = 0;
+  
+  /* Initialize buffer */
+  ctx->index = 0;
+}
+
+
+/* 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)
+
+
+void
+sha256_update(struct sha256_ctx *ctx,
+             size_t length, const uint8_t *data)
+{
+  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;
+  
+  words = length / 4;
+  leftover = length % 4;
+
+  for (i = 0; i < words; i++, dst += 4)
+    WRITE_UINT32(dst, src[i]);
+
+  if (leftover)
+    {
+      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;
+       }
+    }
+}
+
+
+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);
+
+  /* There are 512 = 2^9 bits in one block */  
+  bit_count = (ctx->count << 9) | (ctx->index << 3);
+
+  /* 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);
+}
+
+void
+sha256_digest(struct sha256_ctx *ctx,
+             size_t length,
+             uint8_t *digest)
+{
+  sha256_write_digest(ctx, length, digest);
+  sha256_init(ctx);
+}
diff --git a/src/microhttpd/sha256.h b/src/microhttpd/sha256.h
new file mode 100644
index 00000000..6d36ebef
--- /dev/null
+++ b/src/microhttpd/sha256.h
@@ -0,0 +1,74 @@
+/* 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.
+
+   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/.
+*/
+ 
+#ifndef NETTLE_SHA2_H_INCLUDED
+#define NETTLE_SHA2_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SHA256_DIGEST_SIZE 32
+#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 */
+};
+
+void
+sha256_init(struct sha256_ctx *ctx);
+
+void
+sha256_update(struct sha256_ctx *ctx,
+             size_t length,
+             const uint8_t *data);
+
+void
+sha256_digest(struct sha256_ctx *ctx,
+             size_t length,
+             uint8_t *digest);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NETTLE_SHA2_H_INCLUDED */

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

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