aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2022-09-13 18:51:19 +0300
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2022-09-25 18:39:41 +0300
commiteb26d6c9d3ec79ae27e15d7444c24cf571d25581 (patch)
tree8d3e240e10ac320746d1089745029053064e4f2c /src/microhttpd
parent85a90925974b0c69e0ef77b555bcc6a8f051dc65 (diff)
downloadlibmicrohttpd-eb26d6c9d3ec79ae27e15d7444c24cf571d25581.tar.gz
libmicrohttpd-eb26d6c9d3ec79ae27e15d7444c24cf571d25581.zip
sha256: implemented compact code version, similarly to SHA-512/256
Diffstat (limited to 'src/microhttpd')
-rw-r--r--src/microhttpd/sha256.c147
-rw-r--r--src/microhttpd/sha256.h6
2 files changed, 117 insertions, 36 deletions
diff --git a/src/microhttpd/sha256.c b/src/microhttpd/sha256.c
index 2203441e..b03e7555 100644
--- a/src/microhttpd/sha256.c
+++ b/src/microhttpd/sha256.c
@@ -65,7 +65,7 @@ MHD_SHA256_init (struct Sha256Ctx *ctx)
65 * @param data data, must be exactly 64 bytes long 65 * @param data data, must be exactly 64 bytes long
66 */ 66 */
67static void 67static void
68sha256_transform (uint32_t H[_SHA256_DIGEST_LENGTH], 68sha256_transform (uint32_t H[SHA256_DIGEST_SIZE_WORDS],
69 const void *data) 69 const void *data)
70{ 70{
71 /* Working variables, 71 /* Working variables,
@@ -83,6 +83,18 @@ sha256_transform (uint32_t H[_SHA256_DIGEST_LENGTH],
83 See FIPS PUB 180-4 paragraphs 5.2.1, 6.2. */ 83 See FIPS PUB 180-4 paragraphs 5.2.1, 6.2. */
84 uint32_t W[16]; 84 uint32_t W[16];
85 85
86#ifndef _MHD_GET_32BIT_BE_UNALIGNED
87 if (0 != (((uintptr_t) data) % _MHD_UINT32_ALIGN))
88 {
89 /* Copy the unaligned input data to the aligned buffer */
90 memcpy (W, data, SHA256_BLOCK_SIZE);
91 /* The W[] buffer itself will be used as the source of the data,
92 * but data will be reloaded in correct bytes order during
93 * the next steps */
94 data = (const void *) W;
95 }
96#endif /* _MHD_GET_32BIT_BE_UNALIGNED */
97
86 /* 'Ch' and 'Maj' macro functions are defined with 98 /* 'Ch' and 'Maj' macro functions are defined with
87 widely-used optimization. 99 widely-used optimization.
88 See FIPS PUB 180-4 formulae 4.2, 4.3. */ 100 See FIPS PUB 180-4 formulae 4.2, 4.3. */
@@ -103,14 +115,9 @@ sha256_transform (uint32_t H[_SHA256_DIGEST_LENGTH],
103#define sig1(x) (_MHD_ROTR32 ((x), 17) ^ _MHD_ROTR32 ((x),19) ^ \ 115#define sig1(x) (_MHD_ROTR32 ((x), 17) ^ _MHD_ROTR32 ((x),19) ^ \
104 ((x) >> 10) ) 116 ((x) >> 10) )
105 117
106 /* Single step of SHA-256 computation, 118 /* One step of SHA-256 computation,
107 see FIPS PUB 180-4 paragraph 6.2.2 step 3. 119 see FIPS PUB 180-4 paragraph 6.2.2 step 3.
108 * Note: instead of reassigning all working variables on each step, 120 * Note: this macro updates working variables in-place, without rotation.
109 variables are rotated for each step:
110 SHA2STEP32(a, b, c, d, e, f, g, h, K[0], data[0]);
111 SHA2STEP32(h, a, b, c, d, e, f, g, K[1], data[1]);
112 so current 'vD' will be used as 'vE' on next step,
113 current 'vH' will be used as 'vA' on next step.
114 * Note: first (vH += SIG1(vE) + Ch(vE,vF,vG) + kt + wt) equals T1 in FIPS PUB 180-4 paragraph 6.2.2 step 3. 121 * Note: first (vH += SIG1(vE) + Ch(vE,vF,vG) + kt + wt) equals T1 in FIPS PUB 180-4 paragraph 6.2.2 step 3.
115 second (vH += SIG0(vA) + Maj(vE,vF,vC) equals T1 + T2 in FIPS PUB 180-4 paragraph 6.2.2 step 3. 122 second (vH += SIG0(vA) + Maj(vE,vF,vC) equals T1 + T2 in FIPS PUB 180-4 paragraph 6.2.2 step 3.
116 * Note: 'wt' must be used exactly one time in this macro as it change other data as well 123 * Note: 'wt' must be used exactly one time in this macro as it change other data as well
@@ -119,18 +126,6 @@ sha256_transform (uint32_t H[_SHA256_DIGEST_LENGTH],
119 (vD) += ((vH) += SIG1 ((vE)) + Ch ((vE),(vF),(vG)) + (kt) + (wt)); \ 126 (vD) += ((vH) += SIG1 ((vE)) + Ch ((vE),(vF),(vG)) + (kt) + (wt)); \
120 (vH) += SIG0 ((vA)) + Maj ((vA),(vB),(vC)); } while (0) 127 (vH) += SIG0 ((vA)) + Maj ((vA),(vB),(vC)); } while (0)
121 128
122#ifndef _MHD_GET_32BIT_BE_UNALIGNED
123 if (0 != (((uintptr_t) data) % _MHD_UINT32_ALIGN))
124 {
125 /* Copy the unaligned input data to the aligned buffer */
126 memcpy (W, data, SHA256_BLOCK_SIZE);
127 /* The W[] buffer itself will be used as the source of the data,
128 * but data will be reloaded in correct bytes order during
129 * the next steps */
130 data = (const void *) W;
131 }
132#endif /* _MHD_GET_32BIT_BE_UNALIGNED */
133
134 /* Get value of W(t) from input data buffer, 129 /* Get value of W(t) from input data buffer,
135 See FIPS PUB 180-4 paragraph 6.2. 130 See FIPS PUB 180-4 paragraph 6.2.
136 Input data must be read in big-endian bytes order, 131 Input data must be read in big-endian bytes order,
@@ -141,11 +136,27 @@ sha256_transform (uint32_t H[_SHA256_DIGEST_LENGTH],
141 _MHD_GET_32BIT_BE ((const void*)(((const uint8_t*) (buf)) + \ 136 _MHD_GET_32BIT_BE ((const void*)(((const uint8_t*) (buf)) + \
142 (t) * SHA256_BYTES_IN_WORD)) 137 (t) * SHA256_BYTES_IN_WORD))
143 138
139 /* 'W' generation and assignment for 16 <= t <= 63.
140 See FIPS PUB 180-4 paragraph 6.2.2.
141 As only last 16 'W' are used in calculations, it is possible to
142 use 16 elements array of W as cyclic buffer.
143 * Note: ((t-16)&0xf) have same value as (t&0xf) */
144#define Wgen(w,t) ( (w)[(t - 16) & 0xf] + sig1 ((w)[((t) - 2) & 0xf]) \
145 + (w)[((t) - 7) & 0xf] + sig0 ((w)[((t) - 15) & 0xf]) )
146
147#ifndef MHD_FAVOR_SMALL_CODE
144 /* During first 16 steps, before making any calculations on each step, 148 /* During first 16 steps, before making any calculations on each step,
145 the W element is read from input data buffer as big-endian value and 149 the W element is read from input data buffer as big-endian value and
146 stored in array of W elements. */ 150 stored in array of W elements. */
147 /* Note: instead of using K constants as array, all K values are specified 151 /* Note: instead of using K constants as array, all K values are specified
148 individually for each step, see FIPS PUB 180-4 paragraph 4.2.2 for K values. */ 152 individually for each step, see FIPS PUB 180-4 paragraph 4.2.2 for
153 K values. */
154 /* Note: instead of reassigning all working variables on each step,
155 variables are rotated for each step:
156 SHA2STEP32(a, b, c, d, e, f, g, h, K[0], data[0]);
157 SHA2STEP32(h, a, b, c, d, e, f, g, K[1], data[1]);
158 so current 'vD' will be used as 'vE' on next step,
159 current 'vH' will be used as 'vA' on next step. */
149 SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0x428a2f98), W[0] = \ 160 SHA2STEP32 (a, b, c, d, e, f, g, h, UINT32_C (0x428a2f98), W[0] = \
150 GET_W_FROM_DATA (data, 0)); 161 GET_W_FROM_DATA (data, 0));
151 SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0x71374491), W[1] = \ 162 SHA2STEP32 (h, a, b, c, d, e, f, g, UINT32_C (0x71374491), W[1] = \
@@ -179,14 +190,6 @@ sha256_transform (uint32_t H[_SHA256_DIGEST_LENGTH],
179 SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0xc19bf174), W[15] = \ 190 SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0xc19bf174), W[15] = \
180 GET_W_FROM_DATA (data, 15)); 191 GET_W_FROM_DATA (data, 15));
181 192
182 /* 'W' generation and assignment for 16 <= t <= 63.
183 See FIPS PUB 180-4 paragraph 6.2.2.
184 As only last 16 'W' are used in calculations, it is possible to
185 use 16 elements array of W as cyclic buffer.
186 * Note: ((t-16)&0xf) have same value as (t&0xf) */
187#define Wgen(w,t) ( (w)[(t - 16) & 0xf] + sig1 ((w)[((t) - 2) & 0xf]) \
188 + (w)[((t) - 7) & 0xf] + sig0 ((w)[((t) - 15) & 0xf]) )
189
190 /* During last 48 steps, before making any calculations on each step, 193 /* During last 48 steps, before making any calculations on each step,
191 current W element is generated from other W elements of the cyclic buffer 194 current W element is generated from other W elements of the cyclic buffer
192 and the generated value is stored back in the cyclic buffer. */ 195 and the generated value is stored back in the cyclic buffer. */
@@ -288,6 +291,70 @@ sha256_transform (uint32_t H[_SHA256_DIGEST_LENGTH],
288 Wgen (W,62)); 291 Wgen (W,62));
289 SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0xc67178f2), W[63 & 0xf] = \ 292 SHA2STEP32 (b, c, d, e, f, g, h, a, UINT32_C (0xc67178f2), W[63 & 0xf] = \
290 Wgen (W,63)); 293 Wgen (W,63));
294#else /* ! MHD_FAVOR_SMALL_CODE */
295 if (1)
296 {
297 unsigned int t;
298 /* K constants array.
299 See FIPS PUB 180-4 paragraph 4.2.2 for K values. */
300 static const uint32_t K[80] =
301 { UINT32_C (0x428a2f98), UINT32_C (0x71374491), UINT32_C (0xb5c0fbcf),
302 UINT32_C (0xe9b5dba5), UINT32_C (0x3956c25b), UINT32_C (0x59f111f1),
303 UINT32_C (0x923f82a4), UINT32_C (0xab1c5ed5), UINT32_C (0xd807aa98),
304 UINT32_C (0x12835b01), UINT32_C (0x243185be), UINT32_C (0x550c7dc3),
305 UINT32_C (0x72be5d74), UINT32_C (0x80deb1fe), UINT32_C (0x9bdc06a7),
306 UINT32_C (0xc19bf174), UINT32_C (0xe49b69c1), UINT32_C (0xefbe4786),
307 UINT32_C (0x0fc19dc6), UINT32_C (0x240ca1cc), UINT32_C (0x2de92c6f),
308 UINT32_C (0x4a7484aa), UINT32_C (0x5cb0a9dc), UINT32_C (0x76f988da),
309 UINT32_C (0x983e5152), UINT32_C (0xa831c66d), UINT32_C (0xb00327c8),
310 UINT32_C (0xbf597fc7), UINT32_C (0xc6e00bf3), UINT32_C (0xd5a79147),
311 UINT32_C (0x06ca6351), UINT32_C (0x14292967), UINT32_C (0x27b70a85),
312 UINT32_C (0x2e1b2138), UINT32_C (0x4d2c6dfc), UINT32_C (0x53380d13),
313 UINT32_C (0x650a7354), UINT32_C (0x766a0abb), UINT32_C (0x81c2c92e),
314 UINT32_C (0x92722c85), UINT32_C (0xa2bfe8a1), UINT32_C (0xa81a664b),
315 UINT32_C (0xc24b8b70), UINT32_C (0xc76c51a3), UINT32_C (0xd192e819),
316 UINT32_C (0xd6990624), UINT32_C (0xf40e3585), UINT32_C (0x106aa070),
317 UINT32_C (0x19a4c116), UINT32_C (0x1e376c08), UINT32_C (0x2748774c),
318 UINT32_C (0x34b0bcb5), UINT32_C (0x391c0cb3), UINT32_C (0x4ed8aa4a),
319 UINT32_C (0x5b9cca4f), UINT32_C (0x682e6ff3), UINT32_C (0x748f82ee),
320 UINT32_C (0x78a5636f), UINT32_C (0x84c87814), UINT32_C (0x8cc70208),
321 UINT32_C (0x90befffa), UINT32_C (0xa4506ceb), UINT32_C (0xbef9a3f7),
322 UINT32_C (0xc67178f2) };
323 /* One step of SHA-256 computation with working variables rotation,
324 see FIPS PUB 180-4 paragraph 6.2.2 step 3.
325 * Note: this version of macro reassign all working variable on
326 each step. */
327#define SHA2STEP32RV(vA,vB,vC,vD,vE,vF,vG,vH,kt,wt) do { \
328 uint32_t tmp_h_ = (vH); \
329 SHA2STEP32((vA),(vB),(vC),(vD),(vE),(vF),(vG),tmp_h_,(kt),(wt)); \
330 (vH) = (vG); \
331 (vG) = (vF); \
332 (vF) = (vE); \
333 (vE) = (vD); \
334 (vD) = (vC); \
335 (vC) = (vB); \
336 (vB) = (vA); \
337 (vA) = tmp_h_; } while (0)
338
339 /* During first 16 steps, before making any calculations on each step,
340 the W element is read from input data buffer as big-endian value and
341 stored in array of W elements. */
342 for (t = 0; t < 16; ++t)
343 {
344 SHA2STEP32RV (a, b, c, d, e, f, g, h, K[t], \
345 W[t] = GET_W_FROM_DATA (data, t));
346 }
347
348 /* During last 48 steps, before making any calculations on each step,
349 current W element is generated from other W elements of the cyclic buffer
350 and the generated value is stored back in the cyclic buffer. */
351 for (t = 16; t < 64; ++t)
352 {
353 SHA2STEP32RV (a, b, c, d, e, f, g, h, K[t], W[t & 15] = Wgen (W,t));
354 }
355 }
356#endif /* ! MHD_FAVOR_SMALL_CODE */
357
291 358
292 /* Compute intermediate hash. 359 /* Compute intermediate hash.
293 See FIPS PUB 180-4 paragraph 6.2.2 step 4. */ 360 See FIPS PUB 180-4 paragraph 6.2.2 step 4. */
@@ -318,8 +385,10 @@ MHD_SHA256_update (struct Sha256Ctx *ctx,
318 385
319 mhd_assert ((data != NULL) || (length == 0)); 386 mhd_assert ((data != NULL) || (length == 0));
320 387
388#ifndef MHD_FAVOR_SMALL_CODE
321 if (0 == length) 389 if (0 == length)
322 return; /* Do nothing */ 390 return; /* Shortcut, do nothing */
391#endif /* MHD_FAVOR_SMALL_CODE */
323 392
324 /* Note: (count & (SHA256_BLOCK_SIZE-1)) 393 /* Note: (count & (SHA256_BLOCK_SIZE-1))
325 equals (count % SHA256_BLOCK_SIZE) for this block size. */ 394 equals (count % SHA256_BLOCK_SIZE) for this block size. */
@@ -416,9 +485,17 @@ MHD_SHA256_finish (struct Sha256Ctx *ctx,
416 485
417 /* Put final hash/digest in BE mode */ 486 /* Put final hash/digest in BE mode */
418#ifndef _MHD_PUT_32BIT_BE_UNALIGNED 487#ifndef _MHD_PUT_32BIT_BE_UNALIGNED
419 if (0 != ((uintptr_t) digest) % _MHD_UINT32_ALIGN) 488 if (1
489#ifndef MHD_FAVOR_SMALL_CODE
490 && (0 != ((uintptr_t) digest) % _MHD_UINT32_ALIGN)
491#endif /* MHD_FAVOR_SMALL_CODE */
492 )
420 { 493 {
421 uint32_t alig_dgst[_SHA256_DIGEST_LENGTH]; 494 /* If storing of the final result requires aligned address and
495 the destination address is not aligned or compact code is used,
496 store the final digest in aligned temporary buffer first, then
497 copy it to the destination. */
498 uint32_t alig_dgst[SHA256_DIGEST_SIZE_WORDS];
422 _MHD_PUT_32BIT_BE (alig_dgst + 0, ctx->H[0]); 499 _MHD_PUT_32BIT_BE (alig_dgst + 0, ctx->H[0]);
423 _MHD_PUT_32BIT_BE (alig_dgst + 1, ctx->H[1]); 500 _MHD_PUT_32BIT_BE (alig_dgst + 1, ctx->H[1]);
424 _MHD_PUT_32BIT_BE (alig_dgst + 2, ctx->H[2]); 501 _MHD_PUT_32BIT_BE (alig_dgst + 2, ctx->H[2]);
@@ -430,8 +507,11 @@ MHD_SHA256_finish (struct Sha256Ctx *ctx,
430 /* Copy result to unaligned destination address */ 507 /* Copy result to unaligned destination address */
431 memcpy (digest, alig_dgst, SHA256_DIGEST_SIZE); 508 memcpy (digest, alig_dgst, SHA256_DIGEST_SIZE);
432 } 509 }
433 else 510#ifndef MHD_FAVOR_SMALL_CODE
511 else /* Combined with the next 'if' */
512#endif /* MHD_FAVOR_SMALL_CODE */
434#endif /* ! _MHD_PUT_32BIT_BE_UNALIGNED */ 513#endif /* ! _MHD_PUT_32BIT_BE_UNALIGNED */
514#if ! defined(MHD_FAVOR_SMALL_CODE) || defined(_MHD_PUT_32BIT_BE_UNALIGNED)
435 if (1) 515 if (1)
436 { 516 {
437 /* Use cast to (void*) here to mute compiler alignment warnings. 517 /* Use cast to (void*) here to mute compiler alignment warnings.
@@ -445,6 +525,7 @@ MHD_SHA256_finish (struct Sha256Ctx *ctx,
445 _MHD_PUT_32BIT_BE ((void *) (digest + 6 * SHA256_BYTES_IN_WORD), ctx->H[6]); 525 _MHD_PUT_32BIT_BE ((void *) (digest + 6 * SHA256_BYTES_IN_WORD), ctx->H[6]);
446 _MHD_PUT_32BIT_BE ((void *) (digest + 7 * SHA256_BYTES_IN_WORD), ctx->H[7]); 526 _MHD_PUT_32BIT_BE ((void *) (digest + 7 * SHA256_BYTES_IN_WORD), ctx->H[7]);
447 } 527 }
528#endif /* ! MHD_FAVOR_SMALL_CODE || _MHD_PUT_32BIT_BE_UNALIGNED */
448 529
449 /* Erase potentially sensitive data. */ 530 /* Erase potentially sensitive data. */
450 memset (ctx, 0, sizeof(struct Sha256Ctx)); 531 memset (ctx, 0, sizeof(struct Sha256Ctx));
diff --git a/src/microhttpd/sha256.h b/src/microhttpd/sha256.h
index 192f906a..c3d32e9c 100644
--- a/src/microhttpd/sha256.h
+++ b/src/microhttpd/sha256.h
@@ -36,7 +36,7 @@
36/** 36/**
37 * Digest is kept internally as 8 32-bit words. 37 * Digest is kept internally as 8 32-bit words.
38 */ 38 */
39#define _SHA256_DIGEST_LENGTH 8 39#define SHA256_DIGEST_SIZE_WORDS 8
40 40
41/** 41/**
42 * Number of bits in single SHA-256 word 42 * Number of bits in single SHA-256 word
@@ -52,7 +52,7 @@
52/** 52/**
53 * Size of SHA-256 digest in bytes 53 * Size of SHA-256 digest in bytes
54 */ 54 */
55#define SHA256_DIGEST_SIZE (_SHA256_DIGEST_LENGTH * SHA256_BYTES_IN_WORD) 55#define SHA256_DIGEST_SIZE (SHA256_DIGEST_SIZE_WORDS * SHA256_BYTES_IN_WORD)
56 56
57/** 57/**
58 * Size of SHA-256 digest string in chars including termination NUL 58 * Size of SHA-256 digest string in chars including termination NUL
@@ -77,7 +77,7 @@
77 77
78struct Sha256Ctx 78struct Sha256Ctx
79{ 79{
80 uint32_t H[_SHA256_DIGEST_LENGTH]; /**< Intermediate hash value / digest at end of calculation */ 80 uint32_t H[SHA256_DIGEST_SIZE_WORDS]; /**< Intermediate hash value / digest at end of calculation */
81 uint32_t buffer[SHA256_BLOCK_SIZE_WORDS]; /**< SHA256 input data buffer */ 81 uint32_t buffer[SHA256_BLOCK_SIZE_WORDS]; /**< SHA256 input data buffer */
82 uint64_t count; /**< number of bytes, mod 2^64 */ 82 uint64_t count; /**< number of bytes, mod 2^64 */
83}; 83};