gnunet-svn
[Top][All Lists]
Advanced

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

[libmicrohttpd] branch master updated: Fixed unaligned data processing i


From: gnunet
Subject: [libmicrohttpd] branch master updated: Fixed unaligned data processing in SHA-256 and MD5
Date: Tue, 18 May 2021 21:20:06 +0200

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

karlson2k pushed a commit to branch master
in repository libmicrohttpd.

The following commit(s) were added to refs/heads/master by this push:
     new f959b843 Fixed unaligned data processing in SHA-256 and MD5
f959b843 is described below

commit f959b8435217a903d0b5ddaa2deaa23af54812ab
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Tue May 18 22:17:29 2021 +0300

    Fixed unaligned data processing in SHA-256 and MD5
---
 src/microhttpd/md5.c            | 79 ++++++++++++++++++++++++++++++-----------
 src/microhttpd/mhd_bithelpers.h | 32 ++++++++++++++++-
 src/microhttpd/sha1.c           |  2 +-
 src/microhttpd/sha1.h           |  2 +-
 src/microhttpd/sha256.c         | 68 ++++++++++++++++++++++++-----------
 src/microhttpd/sha256.h         | 23 ++++++++++--
 6 files changed, 160 insertions(+), 46 deletions(-)

diff --git a/src/microhttpd/md5.c b/src/microhttpd/md5.c
index 05a2c9e6..785873b5 100644
--- a/src/microhttpd/md5.c
+++ b/src/microhttpd/md5.c
@@ -26,6 +26,12 @@
 #include "mhd_bithelpers.h"
 #include "mhd_assert.h"
 
+/**
+ * Number of bytes in single MD5 word
+ * used to process data
+ */
+#define MD5_BYTES_IN_WORD (32 / 8)
+
 
 /**
  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
@@ -87,26 +93,37 @@ MHD_MD5Final (void *ctx_,
 
   /* Put number of bits */
   count_bits = ctx->count << 3;
-  _MHD_PUT_64BIT_LE (ctx->buffer + 56, count_bits);
+  _MHD_PUT_64BIT_LE_SAFE (ctx->buffer + 56, count_bits);
   MD5Transform (ctx->state, ctx->buffer);
 
   /* Put digest in LE mode */
-  _MHD_PUT_32BIT_LE (digest, ctx->state[0]);
-  _MHD_PUT_32BIT_LE (digest + 4, ctx->state[1]);
-  _MHD_PUT_32BIT_LE (digest + 8, ctx->state[2]);
-  _MHD_PUT_32BIT_LE (digest + 12, ctx->state[3]);
+#ifndef _MHD_PUT_32BIT_LE_UNALIGNED
+  if (0 != ((uintptr_t) digest) % _MHD_UINT32_ALIGN)
+  {
+    uint32_t alig_dgst[MD5_DIGEST_SIZE / MD5_BYTES_IN_WORD];
+    _MHD_PUT_32BIT_LE (alig_dgst + 0, ctx->state[0]);
+    _MHD_PUT_32BIT_LE (alig_dgst + 1, ctx->state[1]);
+    _MHD_PUT_32BIT_LE (alig_dgst + 2, ctx->state[2]);
+    _MHD_PUT_32BIT_LE (alig_dgst + 3, ctx->state[3]);
+    /* Copy result to unaligned destination address */
+    memcpy (digest, alig_dgst, MD5_DIGEST_SIZE);
+  }
+  else
+#else  /* _MHD_PUT_32BIT_LE_UNALIGNED */
+  if (1)
+#endif /* _MHD_PUT_32BIT_LE_UNALIGNED */
+  {
+    _MHD_PUT_32BIT_LE (digest, ctx->state[0]);
+    _MHD_PUT_32BIT_LE (digest + 4, ctx->state[1]);
+    _MHD_PUT_32BIT_LE (digest + 8, ctx->state[2]);
+    _MHD_PUT_32BIT_LE (digest + 12, ctx->state[3]);
+  }
 
   /* Erase buffer */
   memset (ctx, 0, sizeof(*ctx));
 }
 
 
-/**
- * Number of bytes in single SHA-256 word
- * used to process data
- */
-#define MD5_BYTES_IN_WORD (32 / 8)
-
 /* The four core functions - F1 is optimized somewhat */
 
 /* #define F1(x, y, z) (x & y | ~x & z) */
@@ -129,18 +146,40 @@ MD5Transform (uint32_t state[4],
               const uint8_t block[MD5_BLOCK_SIZE])
 {
   uint32_t a, b, c, d;
+  uint32_t data_buf[MD5_BLOCK_SIZE / MD5_BYTES_IN_WORD];
+  const uint32_t *in;
 
-#if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
-  const uint32_t *in = (const uint32_t *) block;
-#else
-  uint32_t in[MD5_BLOCK_SIZE / MD5_BYTES_IN_WORD];
-  int i;
-
-  for (i = 0; i < MD5_BLOCK_SIZE / MD5_BYTES_IN_WORD; i++)
+#if (_MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN) || \
+  ! defined (_MHD_GET_32BIT_LE_UNALIGNED)
+  if (0 != (((uintptr_t) block) % _MHD_UINT32_ALIGN))
   {
-    in[i] = _MHD_GET_32BIT_LE (block + i * MD5_BYTES_IN_WORD);
+    /* Copy data to the aligned buffer */
+    memcpy (data_buf, block, MD5_BLOCK_SIZE);
+    in = data_buf;
   }
-#endif
+  else
+    in = (const uint32_t *) block;
+#endif /* _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN) || \
+          ! _MHD_GET_32BIT_LE_UNALIGNED */
+#if _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN
+  data_buf[0] = _MHD_GET_32BIT_LE (in + 0);
+  data_buf[1] = _MHD_GET_32BIT_LE (in + 1);
+  data_buf[2] = _MHD_GET_32BIT_LE (in + 2);
+  data_buf[3] = _MHD_GET_32BIT_LE (in + 3);
+  data_buf[4] = _MHD_GET_32BIT_LE (in + 4);
+  data_buf[5] = _MHD_GET_32BIT_LE (in + 5);
+  data_buf[6] = _MHD_GET_32BIT_LE (in + 6);
+  data_buf[7] = _MHD_GET_32BIT_LE (in + 7);
+  data_buf[8] = _MHD_GET_32BIT_LE (in + 8);
+  data_buf[9] = _MHD_GET_32BIT_LE (in + 9);
+  data_buf[10] = _MHD_GET_32BIT_LE (in + 10);
+  data_buf[11] = _MHD_GET_32BIT_LE (in + 11);
+  data_buf[12] = _MHD_GET_32BIT_LE (in + 12);
+  data_buf[13] = _MHD_GET_32BIT_LE (in + 13);
+  data_buf[14] = _MHD_GET_32BIT_LE (in + 14);
+  data_buf[15] = _MHD_GET_32BIT_LE (in + 15);
+  in = data_buf;
+#endif /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
 
   a = state[0];
   b = state[1];
diff --git a/src/microhttpd/mhd_bithelpers.h b/src/microhttpd/mhd_bithelpers.h
index 12e1a569..9bd2df79 100644
--- a/src/microhttpd/mhd_bithelpers.h
+++ b/src/microhttpd/mhd_bithelpers.h
@@ -99,6 +99,17 @@
  * put native-endian 64-bit value64 to addr
  * in little-endian mode.
  */
+/* Slow version that works with unaligned addr and with any bytes order */
+#define _MHD_PUT_64BIT_LE_SLOW(addr, value64) do {                       \
+    ((uint8_t*) (addr))[0] = (uint8_t) ((uint64_t) (value64));           \
+    ((uint8_t*) (addr))[1] = (uint8_t) (((uint64_t) (value64)) >> 8);    \
+    ((uint8_t*) (addr))[2] = (uint8_t) (((uint64_t) (value64)) >> 16);   \
+    ((uint8_t*) (addr))[3] = (uint8_t) (((uint64_t) (value64)) >> 24);   \
+    ((uint8_t*) (addr))[4] = (uint8_t) (((uint64_t) (value64)) >> 32);   \
+    ((uint8_t*) (addr))[5] = (uint8_t) (((uint64_t) (value64)) >> 40);   \
+    ((uint8_t*) (addr))[6] = (uint8_t) (((uint64_t) (value64)) >> 48);   \
+    ((uint8_t*) (addr))[7] = (uint8_t) (((uint64_t) (value64)) >> 56);   \
+} while (0)
 #if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
 #define _MHD_PUT_64BIT_LE(addr, value64)             \
   ((*(uint64_t*) (addr)) = (uint64_t) (value64))
@@ -117,8 +128,23 @@
     ((uint8_t*) (addr))[6] = (uint8_t) (((uint64_t) (value64)) >> 48);   \
     ((uint8_t*) (addr))[7] = (uint8_t) (((uint64_t) (value64)) >> 56);   \
 } while (0)
+/* Indicate that _MHD_PUT_64BIT_LE does not need aligned pointer */
+#define _MHD_PUT_64BIT_LE_UNALIGNED 1
 #endif /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
 
+/* Put result safely to unaligned address */
+_MHD_static_inline void
+_MHD_PUT_64BIT_LE_SAFE (void *dst, uint64_t value)
+{
+#ifndef _MHD_PUT_64BIT_LE_UNALIGNED
+  if (0 != ((uintptr_t) dst) % (_MHD_UINT64_ALIGN))
+    _MHD_PUT_64BIT_LE_SLOW (dst, value);
+  else
+#endif /* ! _MHD_PUT_64BIT_BE_UNALIGNED */
+  _MHD_PUT_64BIT_LE (dst, value);
+}
+
+
 /* _MHD_PUT_32BIT_LE (addr, value32)
  * put native-endian 32-bit value32 to addr
  * in little-endian mode.
@@ -137,6 +163,8 @@
     ((uint8_t*) (addr))[2] = (uint8_t) (((uint32_t) (value32)) >> 16);   \
     ((uint8_t*) (addr))[3] = (uint8_t) (((uint32_t) (value32)) >> 24);   \
 } while (0)
+/* Indicate that _MHD_PUT_32BIT_LE does not need aligned pointer */
+#define _MHD_PUT_32BIT_LE_UNALIGNED 1
 #endif /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
 
 /* _MHD_GET_32BIT_LE (addr)
@@ -156,6 +184,8 @@
     | (((uint32_t) (((const uint8_t*) addr)[1])) << 8)    \
     | (((uint32_t) (((const uint8_t*) addr)[2])) << 16)   \
     | (((uint32_t) (((const uint8_t*) addr)[3])) << 24) )
+/* Indicate that _MHD_GET_32BIT_LE does not need aligned pointer */
+#define _MHD_GET_32BIT_LE_UNALIGNED 1
 #endif /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */
 
 
@@ -195,7 +225,7 @@ _MHD_PUT_64BIT_BE_SAFE (void *dst, uint64_t value)
   if (0 != ((uintptr_t) dst) % (_MHD_UINT64_ALIGN))
     _MHD_PUT_64BIT_BE_SLOW (dst, value);
   else
-#endif /* _MHD_BYTE_ORDER_IS_BIG_OR_LITTLE_ENDIAN */
+#endif /* ! _MHD_PUT_64BIT_BE_UNALIGNED */
   _MHD_PUT_64BIT_BE (dst, value);
 }
 
diff --git a/src/microhttpd/sha1.c b/src/microhttpd/sha1.c
index 2ed84208..5d4a5b93 100644
--- a/src/microhttpd/sha1.c
+++ b/src/microhttpd/sha1.c
@@ -109,7 +109,7 @@ sha1_transform (uint32_t H[_SHA1_DIGEST_LENGTH],
   _MHD_GET_32BIT_BE (((const uint8_t*) (buf)) + (t) * SHA1_BYTES_IN_WORD)
 
 #ifndef _MHD_GET_32BIT_BE_UNALIGNED
-  if (0 != ((size_t) data % _MHD_UINT32_ALIGN))
+  if (0 != (((uintptr_t) data) % _MHD_UINT32_ALIGN))
   {
     /* Copy the unaligned input data to the aligned buffer */
     memcpy (W, data, SHA1_BLOCK_SIZE);
diff --git a/src/microhttpd/sha1.h b/src/microhttpd/sha1.h
index 59f00217..3464f268 100644
--- a/src/microhttpd/sha1.h
+++ b/src/microhttpd/sha1.h
@@ -36,7 +36,7 @@
 #define _SHA1_DIGEST_LENGTH 5
 
 /**
- * Number of bytes in single SHA-1 word
+ * Number of bits in single SHA-1 word
  */
 #define SHA1_WORD_SIZE_BITS 32
 
diff --git a/src/microhttpd/sha256.c b/src/microhttpd/sha256.c
index 80c41eb5..df6a1aa3 100644
--- a/src/microhttpd/sha256.c
+++ b/src/microhttpd/sha256.c
@@ -59,12 +59,6 @@ MHD_SHA256_init (void *ctx_)
 }
 
 
-/**
- * Number of bytes in single SHA-256 word
- * used to process data
- */
-#define SHA256_BYTES_IN_WORD 4
-
 /**
  * Base of SHA-256 transformation.
  * Gets full 64 bytes block of data and updates hash values;
@@ -126,6 +120,18 @@ sha256_transform (uint32_t H[_SHA256_DIGEST_LENGTH],
     (vD) += ((vH) += SIG1 ((vE)) + Ch ((vE),(vF),(vG)) + (kt) + (wt));  \
     (vH) += SIG0 ((vA)) + Maj ((vA),(vB),(vC)); } while (0)
 
+#ifndef _MHD_GET_32BIT_BE_UNALIGNED
+  if (0 != (((uintptr_t) data) % _MHD_UINT32_ALIGN))
+  {
+    /* Copy the unaligned input data to the aligned buffer */
+    memcpy (W, data, SHA256_BLOCK_SIZE);
+    /* The W[] buffer itself will be used as the source of the data,
+     * but data will be reloaded in correct bytes order during
+     * the next steps */
+    data = (uint8_t*) W;
+  }
+#endif /* _MHD_GET_32BIT_BE_UNALIGNED */
+
   /* 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,
@@ -267,7 +273,7 @@ MHD_SHA256_update (void *ctx_,
     return; /* Do nothing */
 
   /* Note: (count & (SHA256_BLOCK_SIZE-1))
-           equal (count % SHA256_BLOCK_SIZE) for this block size. */
+           equals (count % SHA256_BLOCK_SIZE) for this block size. */
   bytes_have = (unsigned) (ctx->count & (SHA256_BLOCK_SIZE - 1));
   ctx->count += length;
 
@@ -275,7 +281,7 @@ MHD_SHA256_update (void *ctx_,
   {
     unsigned bytes_left = SHA256_BLOCK_SIZE - bytes_have;
     if (length >= bytes_left)
-    {     /* Combine new data with data in buffer and
+    {     /* Combine new data with data in the buffer and
              process full block. */
       memcpy (ctx->buffer + bytes_have,
               data,
@@ -289,7 +295,7 @@ MHD_SHA256_update (void *ctx_,
 
   while (SHA256_BLOCK_SIZE <= length)
   {   /* Process any full blocks of new data directly,
-         without copying to buffer. */
+         without copying to the buffer. */
     sha256_transform (ctx->H, data);
     data += SHA256_BLOCK_SIZE;
     length -= SHA256_BLOCK_SIZE;
@@ -297,7 +303,7 @@ MHD_SHA256_update (void *ctx_,
 
   if (0 != length)
   {   /* Copy incomplete block of new data (if any)
-         to buffer. */
+         to the buffer. */
     memcpy (ctx->buffer + bytes_have, data, length);
   }
 }
@@ -351,20 +357,42 @@ MHD_SHA256_finish (void *ctx_,
   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);
+  _MHD_PUT_64BIT_BE_SAFE (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]);
+#ifndef _MHD_PUT_32BIT_BE_UNALIGNED
+  if (0 != ((uintptr_t) digest) % _MHD_UINT32_ALIGN)
+  {
+    uint32_t alig_dgst[_SHA256_DIGEST_LENGTH];
+    _MHD_PUT_32BIT_BE (alig_dgst + 0, ctx->H[0]);
+    _MHD_PUT_32BIT_BE (alig_dgst + 1, ctx->H[1]);
+    _MHD_PUT_32BIT_BE (alig_dgst + 2, ctx->H[2]);
+    _MHD_PUT_32BIT_BE (alig_dgst + 3, ctx->H[3]);
+    _MHD_PUT_32BIT_BE (alig_dgst + 4, ctx->H[4]);
+    _MHD_PUT_32BIT_BE (alig_dgst + 5, ctx->H[5]);
+    _MHD_PUT_32BIT_BE (alig_dgst + 6, ctx->H[6]);
+    _MHD_PUT_32BIT_BE (alig_dgst + 7, ctx->H[7]);
+    /* Copy result to unaligned destination address */
+    memcpy (digest, alig_dgst, SHA256_DIGEST_SIZE);
+  }
+  else
+#else  /* _MHD_PUT_32BIT_BE_UNALIGNED */
+  if (1)
+#endif /* _MHD_PUT_32BIT_BE_UNALIGNED */
+  {
+    _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 88a558fc..3b866af2 100644
--- a/src/microhttpd/sha256.h
+++ b/src/microhttpd/sha256.h
@@ -30,25 +30,42 @@
 #include <stdint.h>
 #include <stddef.h>
 
+
 /**
  *  Digest is kept internally as 8 32-bit words.
  */
 #define _SHA256_DIGEST_LENGTH 8
 
+/**
+ * Number of bits in single SHA-256 word
+ */
+#define SHA256_WORD_SIZE_BITS 32
+
+/**
+ * Number of bytes in single SHA-256 word
+ * used to process data
+ */
+#define SHA256_BYTES_IN_WORD (SHA256_WORD_SIZE_BITS / 8)
+
 /**
  * Size of SHA-256 digest in bytes
  */
-#define SHA256_DIGEST_SIZE (_SHA256_DIGEST_LENGTH * 4)
+#define SHA256_DIGEST_SIZE (_SHA256_DIGEST_LENGTH * SHA256_BYTES_IN_WORD)
 
 /**
- * Size of SHA-256 digest string in chars
+ * Size of SHA-256 digest string in chars including termination NUL
  */
 #define SHA256_DIGEST_STRING_SIZE ((SHA256_DIGEST_SIZE) * 2 + 1)
 
+/**
+ * Size of single processing block in bits
+ */
+#define SHA256_BLOCK_SIZE_BITS 512
+
 /**
  * Size of single processing block in bytes
  */
-#define SHA256_BLOCK_SIZE 64
+#define SHA256_BLOCK_SIZE (SHA256_BLOCK_SIZE_BITS / 8)
 
 
 struct sha256_ctx

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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