diff options
author | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2021-05-18 22:17:29 +0300 |
---|---|---|
committer | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2021-05-18 22:17:29 +0300 |
commit | f959b8435217a903d0b5ddaa2deaa23af54812ab (patch) | |
tree | 27cea2f945fde723aabd0e1a6e6c6a79e4e75fd6 | |
parent | 7b3e010b6159017b65a1621478fc7b22e34df119 (diff) | |
download | libmicrohttpd-f959b8435217a903d0b5ddaa2deaa23af54812ab.tar.gz libmicrohttpd-f959b8435217a903d0b5ddaa2deaa23af54812ab.zip |
Fixed unaligned data processing in SHA-256 and MD5
-rw-r--r-- | src/microhttpd/md5.c | 79 | ||||
-rw-r--r-- | src/microhttpd/mhd_bithelpers.h | 32 | ||||
-rw-r--r-- | src/microhttpd/sha1.c | 2 | ||||
-rw-r--r-- | src/microhttpd/sha1.h | 2 | ||||
-rw-r--r-- | src/microhttpd/sha256.c | 68 | ||||
-rw-r--r-- | 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 @@ | |||
26 | #include "mhd_bithelpers.h" | 26 | #include "mhd_bithelpers.h" |
27 | #include "mhd_assert.h" | 27 | #include "mhd_assert.h" |
28 | 28 | ||
29 | /** | ||
30 | * Number of bytes in single MD5 word | ||
31 | * used to process data | ||
32 | */ | ||
33 | #define MD5_BYTES_IN_WORD (32 / 8) | ||
34 | |||
29 | 35 | ||
30 | /** | 36 | /** |
31 | * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious | 37 | * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious |
@@ -87,26 +93,37 @@ MHD_MD5Final (void *ctx_, | |||
87 | 93 | ||
88 | /* Put number of bits */ | 94 | /* Put number of bits */ |
89 | count_bits = ctx->count << 3; | 95 | count_bits = ctx->count << 3; |
90 | _MHD_PUT_64BIT_LE (ctx->buffer + 56, count_bits); | 96 | _MHD_PUT_64BIT_LE_SAFE (ctx->buffer + 56, count_bits); |
91 | MD5Transform (ctx->state, ctx->buffer); | 97 | MD5Transform (ctx->state, ctx->buffer); |
92 | 98 | ||
93 | /* Put digest in LE mode */ | 99 | /* Put digest in LE mode */ |
94 | _MHD_PUT_32BIT_LE (digest, ctx->state[0]); | 100 | #ifndef _MHD_PUT_32BIT_LE_UNALIGNED |
95 | _MHD_PUT_32BIT_LE (digest + 4, ctx->state[1]); | 101 | if (0 != ((uintptr_t) digest) % _MHD_UINT32_ALIGN) |
96 | _MHD_PUT_32BIT_LE (digest + 8, ctx->state[2]); | 102 | { |
97 | _MHD_PUT_32BIT_LE (digest + 12, ctx->state[3]); | 103 | uint32_t alig_dgst[MD5_DIGEST_SIZE / MD5_BYTES_IN_WORD]; |
104 | _MHD_PUT_32BIT_LE (alig_dgst + 0, ctx->state[0]); | ||
105 | _MHD_PUT_32BIT_LE (alig_dgst + 1, ctx->state[1]); | ||
106 | _MHD_PUT_32BIT_LE (alig_dgst + 2, ctx->state[2]); | ||
107 | _MHD_PUT_32BIT_LE (alig_dgst + 3, ctx->state[3]); | ||
108 | /* Copy result to unaligned destination address */ | ||
109 | memcpy (digest, alig_dgst, MD5_DIGEST_SIZE); | ||
110 | } | ||
111 | else | ||
112 | #else /* _MHD_PUT_32BIT_LE_UNALIGNED */ | ||
113 | if (1) | ||
114 | #endif /* _MHD_PUT_32BIT_LE_UNALIGNED */ | ||
115 | { | ||
116 | _MHD_PUT_32BIT_LE (digest, ctx->state[0]); | ||
117 | _MHD_PUT_32BIT_LE (digest + 4, ctx->state[1]); | ||
118 | _MHD_PUT_32BIT_LE (digest + 8, ctx->state[2]); | ||
119 | _MHD_PUT_32BIT_LE (digest + 12, ctx->state[3]); | ||
120 | } | ||
98 | 121 | ||
99 | /* Erase buffer */ | 122 | /* Erase buffer */ |
100 | memset (ctx, 0, sizeof(*ctx)); | 123 | memset (ctx, 0, sizeof(*ctx)); |
101 | } | 124 | } |
102 | 125 | ||
103 | 126 | ||
104 | /** | ||
105 | * Number of bytes in single SHA-256 word | ||
106 | * used to process data | ||
107 | */ | ||
108 | #define MD5_BYTES_IN_WORD (32 / 8) | ||
109 | |||
110 | /* The four core functions - F1 is optimized somewhat */ | 127 | /* The four core functions - F1 is optimized somewhat */ |
111 | 128 | ||
112 | /* #define F1(x, y, z) (x & y | ~x & z) */ | 129 | /* #define F1(x, y, z) (x & y | ~x & z) */ |
@@ -129,18 +146,40 @@ MD5Transform (uint32_t state[4], | |||
129 | const uint8_t block[MD5_BLOCK_SIZE]) | 146 | const uint8_t block[MD5_BLOCK_SIZE]) |
130 | { | 147 | { |
131 | uint32_t a, b, c, d; | 148 | uint32_t a, b, c, d; |
149 | uint32_t data_buf[MD5_BLOCK_SIZE / MD5_BYTES_IN_WORD]; | ||
150 | const uint32_t *in; | ||
132 | 151 | ||
133 | #if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN | 152 | #if (_MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN) || \ |
134 | const uint32_t *in = (const uint32_t *) block; | 153 | ! defined (_MHD_GET_32BIT_LE_UNALIGNED) |
135 | #else | 154 | if (0 != (((uintptr_t) block) % _MHD_UINT32_ALIGN)) |
136 | uint32_t in[MD5_BLOCK_SIZE / MD5_BYTES_IN_WORD]; | ||
137 | int i; | ||
138 | |||
139 | for (i = 0; i < MD5_BLOCK_SIZE / MD5_BYTES_IN_WORD; i++) | ||
140 | { | 155 | { |
141 | in[i] = _MHD_GET_32BIT_LE (block + i * MD5_BYTES_IN_WORD); | 156 | /* Copy data to the aligned buffer */ |
157 | memcpy (data_buf, block, MD5_BLOCK_SIZE); | ||
158 | in = data_buf; | ||
142 | } | 159 | } |
143 | #endif | 160 | else |
161 | in = (const uint32_t *) block; | ||
162 | #endif /* _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN) || \ | ||
163 | ! _MHD_GET_32BIT_LE_UNALIGNED */ | ||
164 | #if _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN | ||
165 | data_buf[0] = _MHD_GET_32BIT_LE (in + 0); | ||
166 | data_buf[1] = _MHD_GET_32BIT_LE (in + 1); | ||
167 | data_buf[2] = _MHD_GET_32BIT_LE (in + 2); | ||
168 | data_buf[3] = _MHD_GET_32BIT_LE (in + 3); | ||
169 | data_buf[4] = _MHD_GET_32BIT_LE (in + 4); | ||
170 | data_buf[5] = _MHD_GET_32BIT_LE (in + 5); | ||
171 | data_buf[6] = _MHD_GET_32BIT_LE (in + 6); | ||
172 | data_buf[7] = _MHD_GET_32BIT_LE (in + 7); | ||
173 | data_buf[8] = _MHD_GET_32BIT_LE (in + 8); | ||
174 | data_buf[9] = _MHD_GET_32BIT_LE (in + 9); | ||
175 | data_buf[10] = _MHD_GET_32BIT_LE (in + 10); | ||
176 | data_buf[11] = _MHD_GET_32BIT_LE (in + 11); | ||
177 | data_buf[12] = _MHD_GET_32BIT_LE (in + 12); | ||
178 | data_buf[13] = _MHD_GET_32BIT_LE (in + 13); | ||
179 | data_buf[14] = _MHD_GET_32BIT_LE (in + 14); | ||
180 | data_buf[15] = _MHD_GET_32BIT_LE (in + 15); | ||
181 | in = data_buf; | ||
182 | #endif /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */ | ||
144 | 183 | ||
145 | a = state[0]; | 184 | a = state[0]; |
146 | b = state[1]; | 185 | 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 @@ | |||
99 | * put native-endian 64-bit value64 to addr | 99 | * put native-endian 64-bit value64 to addr |
100 | * in little-endian mode. | 100 | * in little-endian mode. |
101 | */ | 101 | */ |
102 | /* Slow version that works with unaligned addr and with any bytes order */ | ||
103 | #define _MHD_PUT_64BIT_LE_SLOW(addr, value64) do { \ | ||
104 | ((uint8_t*) (addr))[0] = (uint8_t) ((uint64_t) (value64)); \ | ||
105 | ((uint8_t*) (addr))[1] = (uint8_t) (((uint64_t) (value64)) >> 8); \ | ||
106 | ((uint8_t*) (addr))[2] = (uint8_t) (((uint64_t) (value64)) >> 16); \ | ||
107 | ((uint8_t*) (addr))[3] = (uint8_t) (((uint64_t) (value64)) >> 24); \ | ||
108 | ((uint8_t*) (addr))[4] = (uint8_t) (((uint64_t) (value64)) >> 32); \ | ||
109 | ((uint8_t*) (addr))[5] = (uint8_t) (((uint64_t) (value64)) >> 40); \ | ||
110 | ((uint8_t*) (addr))[6] = (uint8_t) (((uint64_t) (value64)) >> 48); \ | ||
111 | ((uint8_t*) (addr))[7] = (uint8_t) (((uint64_t) (value64)) >> 56); \ | ||
112 | } while (0) | ||
102 | #if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN | 113 | #if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN |
103 | #define _MHD_PUT_64BIT_LE(addr, value64) \ | 114 | #define _MHD_PUT_64BIT_LE(addr, value64) \ |
104 | ((*(uint64_t*) (addr)) = (uint64_t) (value64)) | 115 | ((*(uint64_t*) (addr)) = (uint64_t) (value64)) |
@@ -117,8 +128,23 @@ | |||
117 | ((uint8_t*) (addr))[6] = (uint8_t) (((uint64_t) (value64)) >> 48); \ | 128 | ((uint8_t*) (addr))[6] = (uint8_t) (((uint64_t) (value64)) >> 48); \ |
118 | ((uint8_t*) (addr))[7] = (uint8_t) (((uint64_t) (value64)) >> 56); \ | 129 | ((uint8_t*) (addr))[7] = (uint8_t) (((uint64_t) (value64)) >> 56); \ |
119 | } while (0) | 130 | } while (0) |
131 | /* Indicate that _MHD_PUT_64BIT_LE does not need aligned pointer */ | ||
132 | #define _MHD_PUT_64BIT_LE_UNALIGNED 1 | ||
120 | #endif /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */ | 133 | #endif /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */ |
121 | 134 | ||
135 | /* Put result safely to unaligned address */ | ||
136 | _MHD_static_inline void | ||
137 | _MHD_PUT_64BIT_LE_SAFE (void *dst, uint64_t value) | ||
138 | { | ||
139 | #ifndef _MHD_PUT_64BIT_LE_UNALIGNED | ||
140 | if (0 != ((uintptr_t) dst) % (_MHD_UINT64_ALIGN)) | ||
141 | _MHD_PUT_64BIT_LE_SLOW (dst, value); | ||
142 | else | ||
143 | #endif /* ! _MHD_PUT_64BIT_BE_UNALIGNED */ | ||
144 | _MHD_PUT_64BIT_LE (dst, value); | ||
145 | } | ||
146 | |||
147 | |||
122 | /* _MHD_PUT_32BIT_LE (addr, value32) | 148 | /* _MHD_PUT_32BIT_LE (addr, value32) |
123 | * put native-endian 32-bit value32 to addr | 149 | * put native-endian 32-bit value32 to addr |
124 | * in little-endian mode. | 150 | * in little-endian mode. |
@@ -137,6 +163,8 @@ | |||
137 | ((uint8_t*) (addr))[2] = (uint8_t) (((uint32_t) (value32)) >> 16); \ | 163 | ((uint8_t*) (addr))[2] = (uint8_t) (((uint32_t) (value32)) >> 16); \ |
138 | ((uint8_t*) (addr))[3] = (uint8_t) (((uint32_t) (value32)) >> 24); \ | 164 | ((uint8_t*) (addr))[3] = (uint8_t) (((uint32_t) (value32)) >> 24); \ |
139 | } while (0) | 165 | } while (0) |
166 | /* Indicate that _MHD_PUT_32BIT_LE does not need aligned pointer */ | ||
167 | #define _MHD_PUT_32BIT_LE_UNALIGNED 1 | ||
140 | #endif /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */ | 168 | #endif /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */ |
141 | 169 | ||
142 | /* _MHD_GET_32BIT_LE (addr) | 170 | /* _MHD_GET_32BIT_LE (addr) |
@@ -156,6 +184,8 @@ | |||
156 | | (((uint32_t) (((const uint8_t*) addr)[1])) << 8) \ | 184 | | (((uint32_t) (((const uint8_t*) addr)[1])) << 8) \ |
157 | | (((uint32_t) (((const uint8_t*) addr)[2])) << 16) \ | 185 | | (((uint32_t) (((const uint8_t*) addr)[2])) << 16) \ |
158 | | (((uint32_t) (((const uint8_t*) addr)[3])) << 24) ) | 186 | | (((uint32_t) (((const uint8_t*) addr)[3])) << 24) ) |
187 | /* Indicate that _MHD_GET_32BIT_LE does not need aligned pointer */ | ||
188 | #define _MHD_GET_32BIT_LE_UNALIGNED 1 | ||
159 | #endif /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */ | 189 | #endif /* _MHD_BYTE_ORDER != _MHD_BIG_ENDIAN */ |
160 | 190 | ||
161 | 191 | ||
@@ -195,7 +225,7 @@ _MHD_PUT_64BIT_BE_SAFE (void *dst, uint64_t value) | |||
195 | if (0 != ((uintptr_t) dst) % (_MHD_UINT64_ALIGN)) | 225 | if (0 != ((uintptr_t) dst) % (_MHD_UINT64_ALIGN)) |
196 | _MHD_PUT_64BIT_BE_SLOW (dst, value); | 226 | _MHD_PUT_64BIT_BE_SLOW (dst, value); |
197 | else | 227 | else |
198 | #endif /* _MHD_BYTE_ORDER_IS_BIG_OR_LITTLE_ENDIAN */ | 228 | #endif /* ! _MHD_PUT_64BIT_BE_UNALIGNED */ |
199 | _MHD_PUT_64BIT_BE (dst, value); | 229 | _MHD_PUT_64BIT_BE (dst, value); |
200 | } | 230 | } |
201 | 231 | ||
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], | |||
109 | _MHD_GET_32BIT_BE (((const uint8_t*) (buf)) + (t) * SHA1_BYTES_IN_WORD) | 109 | _MHD_GET_32BIT_BE (((const uint8_t*) (buf)) + (t) * SHA1_BYTES_IN_WORD) |
110 | 110 | ||
111 | #ifndef _MHD_GET_32BIT_BE_UNALIGNED | 111 | #ifndef _MHD_GET_32BIT_BE_UNALIGNED |
112 | if (0 != ((size_t) data % _MHD_UINT32_ALIGN)) | 112 | if (0 != (((uintptr_t) data) % _MHD_UINT32_ALIGN)) |
113 | { | 113 | { |
114 | /* Copy the unaligned input data to the aligned buffer */ | 114 | /* Copy the unaligned input data to the aligned buffer */ |
115 | memcpy (W, data, SHA1_BLOCK_SIZE); | 115 | 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 @@ | |||
36 | #define _SHA1_DIGEST_LENGTH 5 | 36 | #define _SHA1_DIGEST_LENGTH 5 |
37 | 37 | ||
38 | /** | 38 | /** |
39 | * Number of bytes in single SHA-1 word | 39 | * Number of bits in single SHA-1 word |
40 | */ | 40 | */ |
41 | #define SHA1_WORD_SIZE_BITS 32 | 41 | #define SHA1_WORD_SIZE_BITS 32 |
42 | 42 | ||
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 | |||
@@ -60,12 +60,6 @@ MHD_SHA256_init (void *ctx_) | |||
60 | 60 | ||
61 | 61 | ||
62 | /** | 62 | /** |
63 | * Number of bytes in single SHA-256 word | ||
64 | * used to process data | ||
65 | */ | ||
66 | #define SHA256_BYTES_IN_WORD 4 | ||
67 | |||
68 | /** | ||
69 | * Base of SHA-256 transformation. | 63 | * Base of SHA-256 transformation. |
70 | * Gets full 64 bytes block of data and updates hash values; | 64 | * Gets full 64 bytes block of data and updates hash values; |
71 | * @param H hash values | 65 | * @param H hash values |
@@ -126,6 +120,18 @@ sha256_transform (uint32_t H[_SHA256_DIGEST_LENGTH], | |||
126 | (vD) += ((vH) += SIG1 ((vE)) + Ch ((vE),(vF),(vG)) + (kt) + (wt)); \ | 120 | (vD) += ((vH) += SIG1 ((vE)) + Ch ((vE),(vF),(vG)) + (kt) + (wt)); \ |
127 | (vH) += SIG0 ((vA)) + Maj ((vA),(vB),(vC)); } while (0) | 121 | (vH) += SIG0 ((vA)) + Maj ((vA),(vB),(vC)); } while (0) |
128 | 122 | ||
123 | #ifndef _MHD_GET_32BIT_BE_UNALIGNED | ||
124 | if (0 != (((uintptr_t) data) % _MHD_UINT32_ALIGN)) | ||
125 | { | ||
126 | /* Copy the unaligned input data to the aligned buffer */ | ||
127 | memcpy (W, data, SHA256_BLOCK_SIZE); | ||
128 | /* The W[] buffer itself will be used as the source of the data, | ||
129 | * but data will be reloaded in correct bytes order during | ||
130 | * the next steps */ | ||
131 | data = (uint8_t*) W; | ||
132 | } | ||
133 | #endif /* _MHD_GET_32BIT_BE_UNALIGNED */ | ||
134 | |||
129 | /* Get value of W(t) from input data buffer, | 135 | /* Get value of W(t) from input data buffer, |
130 | See FIPS PUB 180-4 paragraph 6.2. | 136 | See FIPS PUB 180-4 paragraph 6.2. |
131 | Input data must be read in big-endian bytes order, | 137 | Input data must be read in big-endian bytes order, |
@@ -267,7 +273,7 @@ MHD_SHA256_update (void *ctx_, | |||
267 | return; /* Do nothing */ | 273 | return; /* Do nothing */ |
268 | 274 | ||
269 | /* Note: (count & (SHA256_BLOCK_SIZE-1)) | 275 | /* Note: (count & (SHA256_BLOCK_SIZE-1)) |
270 | equal (count % SHA256_BLOCK_SIZE) for this block size. */ | 276 | equals (count % SHA256_BLOCK_SIZE) for this block size. */ |
271 | bytes_have = (unsigned) (ctx->count & (SHA256_BLOCK_SIZE - 1)); | 277 | bytes_have = (unsigned) (ctx->count & (SHA256_BLOCK_SIZE - 1)); |
272 | ctx->count += length; | 278 | ctx->count += length; |
273 | 279 | ||
@@ -275,7 +281,7 @@ MHD_SHA256_update (void *ctx_, | |||
275 | { | 281 | { |
276 | unsigned bytes_left = SHA256_BLOCK_SIZE - bytes_have; | 282 | unsigned bytes_left = SHA256_BLOCK_SIZE - bytes_have; |
277 | if (length >= bytes_left) | 283 | if (length >= bytes_left) |
278 | { /* Combine new data with data in buffer and | 284 | { /* Combine new data with data in the buffer and |
279 | process full block. */ | 285 | process full block. */ |
280 | memcpy (ctx->buffer + bytes_have, | 286 | memcpy (ctx->buffer + bytes_have, |
281 | data, | 287 | data, |
@@ -289,7 +295,7 @@ MHD_SHA256_update (void *ctx_, | |||
289 | 295 | ||
290 | while (SHA256_BLOCK_SIZE <= length) | 296 | while (SHA256_BLOCK_SIZE <= length) |
291 | { /* Process any full blocks of new data directly, | 297 | { /* Process any full blocks of new data directly, |
292 | without copying to buffer. */ | 298 | without copying to the buffer. */ |
293 | sha256_transform (ctx->H, data); | 299 | sha256_transform (ctx->H, data); |
294 | data += SHA256_BLOCK_SIZE; | 300 | data += SHA256_BLOCK_SIZE; |
295 | length -= SHA256_BLOCK_SIZE; | 301 | length -= SHA256_BLOCK_SIZE; |
@@ -297,7 +303,7 @@ MHD_SHA256_update (void *ctx_, | |||
297 | 303 | ||
298 | if (0 != length) | 304 | if (0 != length) |
299 | { /* Copy incomplete block of new data (if any) | 305 | { /* Copy incomplete block of new data (if any) |
300 | to buffer. */ | 306 | to the buffer. */ |
301 | memcpy (ctx->buffer + bytes_have, data, length); | 307 | memcpy (ctx->buffer + bytes_have, data, length); |
302 | } | 308 | } |
303 | } | 309 | } |
@@ -351,20 +357,42 @@ MHD_SHA256_finish (void *ctx_, | |||
351 | memset (ctx->buffer + bytes_have, 0, | 357 | memset (ctx->buffer + bytes_have, 0, |
352 | SHA256_BLOCK_SIZE - SHA256_SIZE_OF_LEN_ADD - bytes_have); | 358 | SHA256_BLOCK_SIZE - SHA256_SIZE_OF_LEN_ADD - bytes_have); |
353 | /* Put number of bits in processed message as big-endian value. */ | 359 | /* Put number of bits in processed message as big-endian value. */ |
354 | _MHD_PUT_64BIT_BE (ctx->buffer + SHA256_BLOCK_SIZE - SHA256_SIZE_OF_LEN_ADD, | 360 | _MHD_PUT_64BIT_BE_SAFE (ctx->buffer + SHA256_BLOCK_SIZE |
355 | num_bits); | 361 | - SHA256_SIZE_OF_LEN_ADD, |
362 | num_bits); | ||
356 | /* Process full final block. */ | 363 | /* Process full final block. */ |
357 | sha256_transform (ctx->H, ctx->buffer); | 364 | sha256_transform (ctx->H, ctx->buffer); |
358 | 365 | ||
359 | /* Put final hash/digest in BE mode */ | 366 | /* Put final hash/digest in BE mode */ |
360 | _MHD_PUT_32BIT_BE (digest + 0 * SHA256_BYTES_IN_WORD, ctx->H[0]); | 367 | #ifndef _MHD_PUT_32BIT_BE_UNALIGNED |
361 | _MHD_PUT_32BIT_BE (digest + 1 * SHA256_BYTES_IN_WORD, ctx->H[1]); | 368 | if (0 != ((uintptr_t) digest) % _MHD_UINT32_ALIGN) |
362 | _MHD_PUT_32BIT_BE (digest + 2 * SHA256_BYTES_IN_WORD, ctx->H[2]); | 369 | { |
363 | _MHD_PUT_32BIT_BE (digest + 3 * SHA256_BYTES_IN_WORD, ctx->H[3]); | 370 | uint32_t alig_dgst[_SHA256_DIGEST_LENGTH]; |
364 | _MHD_PUT_32BIT_BE (digest + 4 * SHA256_BYTES_IN_WORD, ctx->H[4]); | 371 | _MHD_PUT_32BIT_BE (alig_dgst + 0, ctx->H[0]); |
365 | _MHD_PUT_32BIT_BE (digest + 5 * SHA256_BYTES_IN_WORD, ctx->H[5]); | 372 | _MHD_PUT_32BIT_BE (alig_dgst + 1, ctx->H[1]); |
366 | _MHD_PUT_32BIT_BE (digest + 6 * SHA256_BYTES_IN_WORD, ctx->H[6]); | 373 | _MHD_PUT_32BIT_BE (alig_dgst + 2, ctx->H[2]); |
367 | _MHD_PUT_32BIT_BE (digest + 7 * SHA256_BYTES_IN_WORD, ctx->H[7]); | 374 | _MHD_PUT_32BIT_BE (alig_dgst + 3, ctx->H[3]); |
375 | _MHD_PUT_32BIT_BE (alig_dgst + 4, ctx->H[4]); | ||
376 | _MHD_PUT_32BIT_BE (alig_dgst + 5, ctx->H[5]); | ||
377 | _MHD_PUT_32BIT_BE (alig_dgst + 6, ctx->H[6]); | ||
378 | _MHD_PUT_32BIT_BE (alig_dgst + 7, ctx->H[7]); | ||
379 | /* Copy result to unaligned destination address */ | ||
380 | memcpy (digest, alig_dgst, SHA256_DIGEST_SIZE); | ||
381 | } | ||
382 | else | ||
383 | #else /* _MHD_PUT_32BIT_BE_UNALIGNED */ | ||
384 | if (1) | ||
385 | #endif /* _MHD_PUT_32BIT_BE_UNALIGNED */ | ||
386 | { | ||
387 | _MHD_PUT_32BIT_BE (digest + 0 * SHA256_BYTES_IN_WORD, ctx->H[0]); | ||
388 | _MHD_PUT_32BIT_BE (digest + 1 * SHA256_BYTES_IN_WORD, ctx->H[1]); | ||
389 | _MHD_PUT_32BIT_BE (digest + 2 * SHA256_BYTES_IN_WORD, ctx->H[2]); | ||
390 | _MHD_PUT_32BIT_BE (digest + 3 * SHA256_BYTES_IN_WORD, ctx->H[3]); | ||
391 | _MHD_PUT_32BIT_BE (digest + 4 * SHA256_BYTES_IN_WORD, ctx->H[4]); | ||
392 | _MHD_PUT_32BIT_BE (digest + 5 * SHA256_BYTES_IN_WORD, ctx->H[5]); | ||
393 | _MHD_PUT_32BIT_BE (digest + 6 * SHA256_BYTES_IN_WORD, ctx->H[6]); | ||
394 | _MHD_PUT_32BIT_BE (digest + 7 * SHA256_BYTES_IN_WORD, ctx->H[7]); | ||
395 | } | ||
368 | 396 | ||
369 | /* Erase potentially sensitive data. */ | 397 | /* Erase potentially sensitive data. */ |
370 | memset (ctx, 0, sizeof(struct sha256_ctx)); | 398 | 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 @@ | |||
30 | #include <stdint.h> | 30 | #include <stdint.h> |
31 | #include <stddef.h> | 31 | #include <stddef.h> |
32 | 32 | ||
33 | |||
33 | /** | 34 | /** |
34 | * Digest is kept internally as 8 32-bit words. | 35 | * Digest is kept internally as 8 32-bit words. |
35 | */ | 36 | */ |
36 | #define _SHA256_DIGEST_LENGTH 8 | 37 | #define _SHA256_DIGEST_LENGTH 8 |
37 | 38 | ||
38 | /** | 39 | /** |
40 | * Number of bits in single SHA-256 word | ||
41 | */ | ||
42 | #define SHA256_WORD_SIZE_BITS 32 | ||
43 | |||
44 | /** | ||
45 | * Number of bytes in single SHA-256 word | ||
46 | * used to process data | ||
47 | */ | ||
48 | #define SHA256_BYTES_IN_WORD (SHA256_WORD_SIZE_BITS / 8) | ||
49 | |||
50 | /** | ||
39 | * Size of SHA-256 digest in bytes | 51 | * Size of SHA-256 digest in bytes |
40 | */ | 52 | */ |
41 | #define SHA256_DIGEST_SIZE (_SHA256_DIGEST_LENGTH * 4) | 53 | #define SHA256_DIGEST_SIZE (_SHA256_DIGEST_LENGTH * SHA256_BYTES_IN_WORD) |
42 | 54 | ||
43 | /** | 55 | /** |
44 | * Size of SHA-256 digest string in chars | 56 | * Size of SHA-256 digest string in chars including termination NUL |
45 | */ | 57 | */ |
46 | #define SHA256_DIGEST_STRING_SIZE ((SHA256_DIGEST_SIZE) * 2 + 1) | 58 | #define SHA256_DIGEST_STRING_SIZE ((SHA256_DIGEST_SIZE) * 2 + 1) |
47 | 59 | ||
48 | /** | 60 | /** |
61 | * Size of single processing block in bits | ||
62 | */ | ||
63 | #define SHA256_BLOCK_SIZE_BITS 512 | ||
64 | |||
65 | /** | ||
49 | * Size of single processing block in bytes | 66 | * Size of single processing block in bytes |
50 | */ | 67 | */ |
51 | #define SHA256_BLOCK_SIZE 64 | 68 | #define SHA256_BLOCK_SIZE (SHA256_BLOCK_SIZE_BITS / 8) |
52 | 69 | ||
53 | 70 | ||
54 | struct sha256_ctx | 71 | struct sha256_ctx |