[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.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [libmicrohttpd] branch master updated: Fixed unaligned data processing in SHA-256 and MD5,
gnunet <=