diff options
author | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2022-09-13 18:51:19 +0300 |
---|---|---|
committer | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2022-09-25 18:39:41 +0300 |
commit | eb26d6c9d3ec79ae27e15d7444c24cf571d25581 (patch) | |
tree | 8d3e240e10ac320746d1089745029053064e4f2c | |
parent | 85a90925974b0c69e0ef77b555bcc6a8f051dc65 (diff) | |
download | libmicrohttpd-eb26d6c9d3ec79ae27e15d7444c24cf571d25581.tar.gz libmicrohttpd-eb26d6c9d3ec79ae27e15d7444c24cf571d25581.zip |
sha256: implemented compact code version, similarly to SHA-512/256
-rw-r--r-- | src/microhttpd/sha256.c | 147 | ||||
-rw-r--r-- | src/microhttpd/sha256.h | 6 |
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 | */ |
67 | static void | 67 | static void |
68 | sha256_transform (uint32_t H[_SHA256_DIGEST_LENGTH], | 68 | sha256_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 | ||
78 | struct Sha256Ctx | 78 | struct 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 | }; |