diff options
Diffstat (limited to 'src/microhttpd/sha512_256.c')
-rw-r--r-- | src/microhttpd/sha512_256.c | 591 |
1 files changed, 591 insertions, 0 deletions
diff --git a/src/microhttpd/sha512_256.c b/src/microhttpd/sha512_256.c new file mode 100644 index 00000000..54389c6b --- /dev/null +++ b/src/microhttpd/sha512_256.c | |||
@@ -0,0 +1,591 @@ | |||
1 | /* | ||
2 | This file is part of GNU libmicrohttpd | ||
3 | Copyright (C) 2022 Karlson2k (Evgeny Grin) | ||
4 | |||
5 | GNU libmicrohttpd is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2.1 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public | ||
16 | License along with this library. | ||
17 | If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file microhttpd/sha512_256.c | ||
22 | * @brief Calculation of SHA-512/256 digest as defined in FIPS PUB 180-4 (2015) | ||
23 | * @author Karlson2k (Evgeny Grin) | ||
24 | */ | ||
25 | |||
26 | #include "sha512_256.h" | ||
27 | |||
28 | #include <string.h> | ||
29 | #ifdef HAVE_MEMORY_H | ||
30 | #include <memory.h> | ||
31 | #endif /* HAVE_MEMORY_H */ | ||
32 | #include "mhd_bithelpers.h" | ||
33 | #include "mhd_assert.h" | ||
34 | |||
35 | /** | ||
36 | * Initialise structure for SHA-512/256 calculation. | ||
37 | * | ||
38 | * @param ctx the calculation context | ||
39 | */ | ||
40 | void | ||
41 | MHD_SHA512_256_init (struct Sha512_256Ctx *ctx) | ||
42 | { | ||
43 | /* Initial hash values, see FIPS PUB 180-4 clause 5.3.6.2 */ | ||
44 | /* Values generated by "IV Generation Function" as described in | ||
45 | * clause 5.3.6 */ | ||
46 | ctx->H[0] = UINT64_C (0x22312194FC2BF72C); | ||
47 | ctx->H[1] = UINT64_C (0x9F555FA3C84C64C2); | ||
48 | ctx->H[2] = UINT64_C (0x2393B86B6F53B151); | ||
49 | ctx->H[3] = UINT64_C (0x963877195940EABD); | ||
50 | ctx->H[4] = UINT64_C (0x96283EE2A88EFFE3); | ||
51 | ctx->H[5] = UINT64_C (0xBE5E1E2553863992); | ||
52 | ctx->H[6] = UINT64_C (0x2B0199FC2C85B8AA); | ||
53 | ctx->H[7] = UINT64_C (0x0EB72DDC81C52CA2); | ||
54 | |||
55 | /* Initialise number of bytes and high part of number of bits. */ | ||
56 | ctx->count = 0; | ||
57 | ctx->count_bits_hi = 0; | ||
58 | } | ||
59 | |||
60 | |||
61 | /** | ||
62 | * Base of SHA-512/256 transformation. | ||
63 | * Gets full 64 bytes block of data and updates hash values; | ||
64 | * @param H hash values | ||
65 | * @param data the data buffer with SHA512_256_BLOCK_SIZE bytes block | ||
66 | */ | ||
67 | static void | ||
68 | sha512_256_transform (uint64_t H[SHA512_256_HASH_SIZE_WORDS], | ||
69 | const void *data) | ||
70 | { | ||
71 | /* Working variables, | ||
72 | see FIPS PUB 180-4 clause 6.7, 6.4. */ | ||
73 | uint64_t a = H[0]; | ||
74 | uint64_t b = H[1]; | ||
75 | uint64_t c = H[2]; | ||
76 | uint64_t d = H[3]; | ||
77 | uint64_t e = H[4]; | ||
78 | uint64_t f = H[5]; | ||
79 | uint64_t g = H[6]; | ||
80 | uint64_t h = H[7]; | ||
81 | |||
82 | /* Data buffer, used as a cyclic buffer. | ||
83 | See FIPS PUB 180-4 clause 5.2.2, 6.7, 6.4. */ | ||
84 | uint64_t W[16]; | ||
85 | |||
86 | #ifndef _MHD_GET_64BIT_BE_ALLOW_UNALIGNED | ||
87 | if (0 != (((uintptr_t) data) % _MHD_UINT64_ALIGN)) | ||
88 | { /* The input data is unaligned */ | ||
89 | /* Copy the unaligned input data to the aligned buffer */ | ||
90 | memcpy (W, data, sizeof(W)); | ||
91 | /* The W[] buffer itself will be used as the source of the data, | ||
92 | * but the data will be reloaded in correct bytes order on | ||
93 | * the next steps */ | ||
94 | data = (uint8_t *) W; | ||
95 | } | ||
96 | #endif /* _MHD_GET_64BIT_BE_ALLOW_UNALIGNED */ | ||
97 | |||
98 | /* 'Ch' and 'Maj' macro functions are defined with | ||
99 | widely-used optimisation. | ||
100 | See FIPS PUB 180-4 formulae 4.8, 4.9. */ | ||
101 | #define Ch(x,y,z) ( (z) ^ ((x) & ((y) ^ (z))) ) | ||
102 | #define Maj(x,y,z) ( ((x) & (y)) ^ ((z) & ((x) ^ (y))) ) | ||
103 | /* Unoptimized (original) versions: */ | ||
104 | /* #define Ch(x,y,z) ( ( (x) & (y) ) ^ ( ~(x) & (z) ) ) */ | ||
105 | /* #define Maj(x,y,z) ( ((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)) ) */ | ||
106 | |||
107 | /* Four 'Sigma' macro functions. | ||
108 | See FIPS PUB 180-4 formulae 4.10, 4.11, 4.12, 4.13. */ | ||
109 | #define SIG0(x) \ | ||
110 | ( _MHD_ROTR64 ((x), 28) ^ _MHD_ROTR64 ((x), 34) ^ _MHD_ROTR64 ((x), 39) ) | ||
111 | #define SIG1(x) \ | ||
112 | ( _MHD_ROTR64 ((x), 14) ^ _MHD_ROTR64 ((x), 18) ^ _MHD_ROTR64 ((x), 41) ) | ||
113 | #define sig0(x) \ | ||
114 | ( _MHD_ROTR64 ((x), 1) ^ _MHD_ROTR64 ((x), 8) ^ ((x) >> 7) ) | ||
115 | #define sig1(x) \ | ||
116 | ( _MHD_ROTR64 ((x), 19) ^ _MHD_ROTR64 ((x), 61) ^ ((x) >> 6) ) | ||
117 | |||
118 | /* One step of SHA-512/256 computation, | ||
119 | see FIPS PUB 180-4 clause 6.4.2 step 3. | ||
120 | * Note: this macro updates working variables in-place, without rotation. | ||
121 | * Note: instead of reassigning all working variables on each step, | ||
122 | variables are rotated for each step: | ||
123 | SHA2STEP64(a, b, c, d, e, f, g, h, K[0], data[0]); | ||
124 | SHA2STEP64(h, a, b, c, d, e, f, g, K[1], data[1]); | ||
125 | so current 'vD' will be used as 'vE' on next step, | ||
126 | current 'vH' will be used as 'vA' on next step. | ||
127 | * Note: the first (vH += SIG1(vE) + Ch(vE,vF,vG) + kt + wt) equals T1 in | ||
128 | FIPS PUB 180-4 clause 6.4.2 step 3. | ||
129 | the second (vH += SIG0(vA) + Maj(vE,vF,vC) equals T1 + T2 in | ||
130 | FIPS PUB 180-4 clause 6.4.2 step 3. | ||
131 | * Note: 'wt' must be used exactly one time in this macro as it change other | ||
132 | data as well every time when used. */ | ||
133 | #define SHA2STEP64(vA,vB,vC,vD,vE,vF,vG,vH,kt,wt) do { \ | ||
134 | (vD) += ((vH) += SIG1 ((vE)) + Ch ((vE),(vF),(vG)) + (kt) + (wt)); \ | ||
135 | (vH) += SIG0 ((vA)) + Maj ((vA),(vB),(vC)); } while (0) | ||
136 | |||
137 | /* Get value of W(t) from input data buffer for 0 <= t <= 15, | ||
138 | See FIPS PUB 180-4 clause 6.2. | ||
139 | Input data must be read in big-endian bytes order, | ||
140 | see FIPS PUB 180-4 clause 3.1.2. */ | ||
141 | #define GET_W_FROM_DATA(buf,t) \ | ||
142 | _MHD_GET_64BIT_BE (((const uint64_t*) (buf)) + (t)) | ||
143 | |||
144 | /* 'W' generation and assignment for 16 <= t <= 79. | ||
145 | See FIPS PUB 180-4 clause 6.4.2. | ||
146 | As only last 16 'W' are used in calculations, it is possible to | ||
147 | use 16 elements array of W as a cyclic buffer. | ||
148 | * Note: ((t-16) & 15) have same value as (t & 15) */ | ||
149 | #define Wgen(w,t) ( (w)[(t - 16) & 15] + sig1 ((w)[((t) - 2) & 15]) \ | ||
150 | + (w)[((t) - 7) & 15] + sig0 ((w)[((t) - 15) & 15]) ) | ||
151 | |||
152 | #ifndef MHD_FAVOR_SMALL_CODE | ||
153 | /* During first 16 steps, before making any calculations on each step, | ||
154 | the W element is read from the input data buffer as big-endian value and | ||
155 | stored in the array of W elements. */ | ||
156 | /* Note: instead of using K constants as array, all K values are specified | ||
157 | individually for each step, see FIPS PUB 180-4 clause 4.2.3 for | ||
158 | K values. */ | ||
159 | /* Note: instead of reassigning all working variables on each step, | ||
160 | variables are rotated for each step: | ||
161 | SHA2STEP64(a, b, c, d, e, f, g, h, K[0], data[0]); | ||
162 | SHA2STEP64(h, a, b, c, d, e, f, g, K[1], data[1]); | ||
163 | so current 'vD' will be used as 'vE' on next step, | ||
164 | current 'vH' will be used as 'vA' on next step. */ | ||
165 | SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x428a2f98d728ae22), \ | ||
166 | W[0] = GET_W_FROM_DATA (data, 0)); | ||
167 | SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x7137449123ef65cd), \ | ||
168 | W[1] = GET_W_FROM_DATA (data, 1)); | ||
169 | SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0xb5c0fbcfec4d3b2f), \ | ||
170 | W[2] = GET_W_FROM_DATA (data, 2)); | ||
171 | SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0xe9b5dba58189dbbc), \ | ||
172 | W[3] = GET_W_FROM_DATA (data, 3)); | ||
173 | SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x3956c25bf348b538), \ | ||
174 | W[4] = GET_W_FROM_DATA (data, 4)); | ||
175 | SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x59f111f1b605d019), \ | ||
176 | W[5] = GET_W_FROM_DATA (data, 5)); | ||
177 | SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x923f82a4af194f9b), \ | ||
178 | W[6] = GET_W_FROM_DATA (data, 6)); | ||
179 | SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0xab1c5ed5da6d8118), \ | ||
180 | W[7] = GET_W_FROM_DATA (data, 7)); | ||
181 | SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0xd807aa98a3030242), \ | ||
182 | W[8] = GET_W_FROM_DATA (data, 8)); | ||
183 | SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x12835b0145706fbe), \ | ||
184 | W[9] = GET_W_FROM_DATA (data, 9)); | ||
185 | SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x243185be4ee4b28c), \ | ||
186 | W[10] = GET_W_FROM_DATA (data, 10)); | ||
187 | SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x550c7dc3d5ffb4e2), \ | ||
188 | W[11] = GET_W_FROM_DATA (data, 11)); | ||
189 | SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x72be5d74f27b896f), \ | ||
190 | W[12] = GET_W_FROM_DATA (data, 12)); | ||
191 | SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x80deb1fe3b1696b1), \ | ||
192 | W[13] = GET_W_FROM_DATA (data, 13)); | ||
193 | SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x9bdc06a725c71235), \ | ||
194 | W[14] = GET_W_FROM_DATA (data, 14)); | ||
195 | SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0xc19bf174cf692694), \ | ||
196 | W[15] = GET_W_FROM_DATA (data, 15)); | ||
197 | |||
198 | /* During last 64 steps, before making any calculations on each step, | ||
199 | current W element is generated from other W elements of the cyclic buffer | ||
200 | and the generated value is stored back in the cyclic buffer. */ | ||
201 | /* Note: instead of using K constants as array, all K values are specified | ||
202 | individually for each step, see FIPS PUB 180-4 clause 4.2.3 for | ||
203 | K values. */ | ||
204 | SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0xe49b69c19ef14ad2), \ | ||
205 | W[16 & 15] = Wgen (W,16)); | ||
206 | SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0xefbe4786384f25e3), \ | ||
207 | W[17 & 15] = Wgen (W,17)); | ||
208 | SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x0fc19dc68b8cd5b5), \ | ||
209 | W[18 & 15] = Wgen (W,18)); | ||
210 | SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x240ca1cc77ac9c65), \ | ||
211 | W[19 & 15] = Wgen (W,19)); | ||
212 | SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x2de92c6f592b0275), \ | ||
213 | W[20 & 15] = Wgen (W,20)); | ||
214 | SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x4a7484aa6ea6e483), \ | ||
215 | W[21 & 15] = Wgen (W,21)); | ||
216 | SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x5cb0a9dcbd41fbd4), \ | ||
217 | W[22 & 15] = Wgen (W,22)); | ||
218 | SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x76f988da831153b5), \ | ||
219 | W[23 & 15] = Wgen (W,23)); | ||
220 | SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x983e5152ee66dfab), \ | ||
221 | W[24 & 15] = Wgen (W,24)); | ||
222 | SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0xa831c66d2db43210), \ | ||
223 | W[25 & 15] = Wgen (W,25)); | ||
224 | SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0xb00327c898fb213f), \ | ||
225 | W[26 & 15] = Wgen (W,26)); | ||
226 | SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0xbf597fc7beef0ee4), \ | ||
227 | W[27 & 15] = Wgen (W,27)); | ||
228 | SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0xc6e00bf33da88fc2), \ | ||
229 | W[28 & 15] = Wgen (W,28)); | ||
230 | SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0xd5a79147930aa725), \ | ||
231 | W[29 & 15] = Wgen (W,29)); | ||
232 | SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x06ca6351e003826f), \ | ||
233 | W[30 & 15] = Wgen (W,30)); | ||
234 | SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x142929670a0e6e70), \ | ||
235 | W[31 & 15] = Wgen (W,31)); | ||
236 | SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x27b70a8546d22ffc), \ | ||
237 | W[32 & 15] = Wgen (W,32)); | ||
238 | SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x2e1b21385c26c926), \ | ||
239 | W[33 & 15] = Wgen (W,33)); | ||
240 | SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x4d2c6dfc5ac42aed), \ | ||
241 | W[34 & 15] = Wgen (W,34)); | ||
242 | SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x53380d139d95b3df), \ | ||
243 | W[35 & 15] = Wgen (W,35)); | ||
244 | SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x650a73548baf63de), \ | ||
245 | W[36 & 15] = Wgen (W,36)); | ||
246 | SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x766a0abb3c77b2a8), \ | ||
247 | W[37 & 15] = Wgen (W,37)); | ||
248 | SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x81c2c92e47edaee6), \ | ||
249 | W[38 & 15] = Wgen (W,38)); | ||
250 | SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x92722c851482353b), \ | ||
251 | W[39 & 15] = Wgen (W,39)); | ||
252 | SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0xa2bfe8a14cf10364), \ | ||
253 | W[40 & 15] = Wgen (W,40)); | ||
254 | SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0xa81a664bbc423001), \ | ||
255 | W[41 & 15] = Wgen (W,41)); | ||
256 | SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0xc24b8b70d0f89791), \ | ||
257 | W[42 & 15] = Wgen (W,42)); | ||
258 | SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0xc76c51a30654be30), \ | ||
259 | W[43 & 15] = Wgen (W,43)); | ||
260 | SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0xd192e819d6ef5218), \ | ||
261 | W[44 & 15] = Wgen (W,44)); | ||
262 | SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0xd69906245565a910), \ | ||
263 | W[45 & 15] = Wgen (W,45)); | ||
264 | SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0xf40e35855771202a), \ | ||
265 | W[46 & 15] = Wgen (W,46)); | ||
266 | SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x106aa07032bbd1b8), \ | ||
267 | W[47 & 15] = Wgen (W,47)); | ||
268 | SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x19a4c116b8d2d0c8), \ | ||
269 | W[48 & 15] = Wgen (W,48)); | ||
270 | SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x1e376c085141ab53), \ | ||
271 | W[49 & 15] = Wgen (W,49)); | ||
272 | SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x2748774cdf8eeb99), \ | ||
273 | W[50 & 15] = Wgen (W,50)); | ||
274 | SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x34b0bcb5e19b48a8), \ | ||
275 | W[51 & 15] = Wgen (W,51)); | ||
276 | SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x391c0cb3c5c95a63), \ | ||
277 | W[52 & 15] = Wgen (W,52)); | ||
278 | SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x4ed8aa4ae3418acb), \ | ||
279 | W[53 & 15] = Wgen (W,53)); | ||
280 | SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x5b9cca4f7763e373), \ | ||
281 | W[54 & 15] = Wgen (W,54)); | ||
282 | SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x682e6ff3d6b2b8a3), \ | ||
283 | W[55 & 15] = Wgen (W,55)); | ||
284 | SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x748f82ee5defb2fc), \ | ||
285 | W[56 & 15] = Wgen (W,56)); | ||
286 | SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x78a5636f43172f60), \ | ||
287 | W[57 & 15] = Wgen (W,57)); | ||
288 | SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x84c87814a1f0ab72), \ | ||
289 | W[58 & 15] = Wgen (W,58)); | ||
290 | SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x8cc702081a6439ec), \ | ||
291 | W[59 & 15] = Wgen (W,59)); | ||
292 | SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x90befffa23631e28), \ | ||
293 | W[60 & 15] = Wgen (W,60)); | ||
294 | SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0xa4506cebde82bde9), \ | ||
295 | W[61 & 15] = Wgen (W,61)); | ||
296 | SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0xbef9a3f7b2c67915), \ | ||
297 | W[62 & 15] = Wgen (W,62)); | ||
298 | SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0xc67178f2e372532b), \ | ||
299 | W[63 & 15] = Wgen (W,63)); | ||
300 | SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0xca273eceea26619c), \ | ||
301 | W[64 & 15] = Wgen (W,64)); | ||
302 | SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0xd186b8c721c0c207), \ | ||
303 | W[65 & 15] = Wgen (W,65)); | ||
304 | SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0xeada7dd6cde0eb1e), \ | ||
305 | W[66 & 15] = Wgen (W,66)); | ||
306 | SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0xf57d4f7fee6ed178), \ | ||
307 | W[67 & 15] = Wgen (W,67)); | ||
308 | SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x06f067aa72176fba), \ | ||
309 | W[68 & 15] = Wgen (W,68)); | ||
310 | SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x0a637dc5a2c898a6), \ | ||
311 | W[69 & 15] = Wgen (W,69)); | ||
312 | SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x113f9804bef90dae), \ | ||
313 | W[70 & 15] = Wgen (W,70)); | ||
314 | SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x1b710b35131c471b), \ | ||
315 | W[71 & 15] = Wgen (W,71)); | ||
316 | SHA2STEP64 (a, b, c, d, e, f, g, h, UINT64_C (0x28db77f523047d84), \ | ||
317 | W[72 & 15] = Wgen (W,72)); | ||
318 | SHA2STEP64 (h, a, b, c, d, e, f, g, UINT64_C (0x32caab7b40c72493), \ | ||
319 | W[73 & 15] = Wgen (W,73)); | ||
320 | SHA2STEP64 (g, h, a, b, c, d, e, f, UINT64_C (0x3c9ebe0a15c9bebc), \ | ||
321 | W[74 & 15] = Wgen (W,74)); | ||
322 | SHA2STEP64 (f, g, h, a, b, c, d, e, UINT64_C (0x431d67c49c100d4c), \ | ||
323 | W[75 & 15] = Wgen (W,75)); | ||
324 | SHA2STEP64 (e, f, g, h, a, b, c, d, UINT64_C (0x4cc5d4becb3e42b6), \ | ||
325 | W[76 & 15] = Wgen (W,76)); | ||
326 | SHA2STEP64 (d, e, f, g, h, a, b, c, UINT64_C (0x597f299cfc657e2a), \ | ||
327 | W[77 & 15] = Wgen (W,77)); | ||
328 | SHA2STEP64 (c, d, e, f, g, h, a, b, UINT64_C (0x5fcb6fab3ad6faec), \ | ||
329 | W[78 & 15] = Wgen (W,78)); | ||
330 | SHA2STEP64 (b, c, d, e, f, g, h, a, UINT64_C (0x6c44198c4a475817), \ | ||
331 | W[79 & 15] = Wgen (W,79)); | ||
332 | #else /* MHD_FAVOR_SMALL_CODE */ | ||
333 | if (1) | ||
334 | { | ||
335 | unsigned int t; | ||
336 | /* K constants array. | ||
337 | See FIPS PUB 180-4 clause 4.2.3 for K values. */ | ||
338 | static const uint64_t K[80] = | ||
339 | { UINT64_C (0x428a2f98d728ae22), UINT64_C (0x7137449123ef65cd), | ||
340 | UINT64_C (0xb5c0fbcfec4d3b2f), UINT64_C (0xe9b5dba58189dbbc), | ||
341 | UINT64_C (0x3956c25bf348b538), UINT64_C (0x59f111f1b605d019), | ||
342 | UINT64_C (0x923f82a4af194f9b), UINT64_C (0xab1c5ed5da6d8118), | ||
343 | UINT64_C (0xd807aa98a3030242), UINT64_C (0x12835b0145706fbe), | ||
344 | UINT64_C (0x243185be4ee4b28c), UINT64_C (0x550c7dc3d5ffb4e2), | ||
345 | UINT64_C (0x72be5d74f27b896f), UINT64_C (0x80deb1fe3b1696b1), | ||
346 | UINT64_C (0x9bdc06a725c71235), UINT64_C (0xc19bf174cf692694), | ||
347 | UINT64_C (0xe49b69c19ef14ad2), UINT64_C (0xefbe4786384f25e3), | ||
348 | UINT64_C (0x0fc19dc68b8cd5b5), UINT64_C (0x240ca1cc77ac9c65), | ||
349 | UINT64_C (0x2de92c6f592b0275), UINT64_C (0x4a7484aa6ea6e483), | ||
350 | UINT64_C (0x5cb0a9dcbd41fbd4), UINT64_C (0x76f988da831153b5), | ||
351 | UINT64_C (0x983e5152ee66dfab), UINT64_C (0xa831c66d2db43210), | ||
352 | UINT64_C (0xb00327c898fb213f), UINT64_C (0xbf597fc7beef0ee4), | ||
353 | UINT64_C (0xc6e00bf33da88fc2), UINT64_C (0xd5a79147930aa725), | ||
354 | UINT64_C (0x06ca6351e003826f), UINT64_C (0x142929670a0e6e70), | ||
355 | UINT64_C (0x27b70a8546d22ffc), UINT64_C (0x2e1b21385c26c926), | ||
356 | UINT64_C (0x4d2c6dfc5ac42aed), UINT64_C (0x53380d139d95b3df), | ||
357 | UINT64_C (0x650a73548baf63de), UINT64_C (0x766a0abb3c77b2a8), | ||
358 | UINT64_C (0x81c2c92e47edaee6), UINT64_C (0x92722c851482353b), | ||
359 | UINT64_C (0xa2bfe8a14cf10364), UINT64_C (0xa81a664bbc423001), | ||
360 | UINT64_C (0xc24b8b70d0f89791), UINT64_C (0xc76c51a30654be30), | ||
361 | UINT64_C (0xd192e819d6ef5218), UINT64_C (0xd69906245565a910), | ||
362 | UINT64_C (0xf40e35855771202a), UINT64_C (0x106aa07032bbd1b8), | ||
363 | UINT64_C (0x19a4c116b8d2d0c8), UINT64_C (0x1e376c085141ab53), | ||
364 | UINT64_C (0x2748774cdf8eeb99), UINT64_C (0x34b0bcb5e19b48a8), | ||
365 | UINT64_C (0x391c0cb3c5c95a63), UINT64_C (0x4ed8aa4ae3418acb), | ||
366 | UINT64_C (0x5b9cca4f7763e373), UINT64_C (0x682e6ff3d6b2b8a3), | ||
367 | UINT64_C (0x748f82ee5defb2fc), UINT64_C (0x78a5636f43172f60), | ||
368 | UINT64_C (0x84c87814a1f0ab72), UINT64_C (0x8cc702081a6439ec), | ||
369 | UINT64_C (0x90befffa23631e28), UINT64_C (0xa4506cebde82bde9), | ||
370 | UINT64_C (0xbef9a3f7b2c67915), UINT64_C (0xc67178f2e372532b), | ||
371 | UINT64_C (0xca273eceea26619c), UINT64_C (0xd186b8c721c0c207), | ||
372 | UINT64_C (0xeada7dd6cde0eb1e), UINT64_C (0xf57d4f7fee6ed178), | ||
373 | UINT64_C (0x06f067aa72176fba), UINT64_C (0x0a637dc5a2c898a6), | ||
374 | UINT64_C (0x113f9804bef90dae), UINT64_C (0x1b710b35131c471b), | ||
375 | UINT64_C (0x28db77f523047d84), UINT64_C (0x32caab7b40c72493), | ||
376 | UINT64_C (0x3c9ebe0a15c9bebc), UINT64_C (0x431d67c49c100d4c), | ||
377 | UINT64_C (0x4cc5d4becb3e42b6), UINT64_C (0x597f299cfc657e2a), | ||
378 | UINT64_C (0x5fcb6fab3ad6faec), UINT64_C (0x6c44198c4a475817)}; | ||
379 | |||
380 | /* One step of SHA-512/256 computation with working variables rotation, | ||
381 | see FIPS PUB 180-4 clause 6.4.2 step 3. | ||
382 | * Note: this version of macro reassign all working variable on | ||
383 | each step. */ | ||
384 | #define SHA2STEP64RV(vA,vB,vC,vD,vE,vF,vG,vH,kt,wt) do { \ | ||
385 | uint64_t tmp_h_ = (vH); \ | ||
386 | SHA2STEP64((vA),(vB),(vC),(vD),(vE),(vF),(vG),tmp_h_,(kt),(wt)); \ | ||
387 | (vH) = (vG); \ | ||
388 | (vG) = (vF); \ | ||
389 | (vF) = (vE); \ | ||
390 | (vE) = (vD); \ | ||
391 | (vD) = (vC); \ | ||
392 | (vC) = (vB); \ | ||
393 | (vB) = (vA); \ | ||
394 | (vA) = tmp_h_; } while (0) | ||
395 | |||
396 | /* During first 16 steps, before making any calculations on each step, | ||
397 | the W element is read from the input data buffer as big-endian value and | ||
398 | stored in the array of W elements. */ | ||
399 | for (t = 0; t < 16; ++t) | ||
400 | { | ||
401 | SHA2STEP64RV (a, b, c, d, e, f, g, h, K[t], \ | ||
402 | W[t] = GET_W_FROM_DATA (data, t)); | ||
403 | } | ||
404 | /* During last 64 steps, before making any calculations on each step, | ||
405 | current W element is generated from other W elements of the cyclic buffer | ||
406 | and the generated value is stored back in the cyclic buffer. */ | ||
407 | for (t = 16; t < 80; ++t) | ||
408 | { | ||
409 | SHA2STEP64RV (a, b, c, d, e, f, g, h, K[t], \ | ||
410 | W[t & 15] = Wgen (W,t)); | ||
411 | } | ||
412 | } | ||
413 | #endif /* MHD_FAVOR_SMALL_CODE */ | ||
414 | |||
415 | /* Compute and store the intermediate hash. | ||
416 | See FIPS PUB 180-4 clause 6.4.2 step 4. */ | ||
417 | H[0] += a; | ||
418 | H[1] += b; | ||
419 | H[2] += c; | ||
420 | H[3] += d; | ||
421 | H[4] += e; | ||
422 | H[5] += f; | ||
423 | H[6] += g; | ||
424 | H[7] += h; | ||
425 | } | ||
426 | |||
427 | |||
428 | /** | ||
429 | * Process portion of bytes. | ||
430 | * | ||
431 | * @param ctx the calculation context | ||
432 | * @param data bytes to add to hash | ||
433 | * @param length number of bytes in @a data | ||
434 | */ | ||
435 | void | ||
436 | MHD_SHA512_256_update (struct Sha512_256Ctx *ctx, | ||
437 | const uint8_t *data, | ||
438 | size_t length) | ||
439 | { | ||
440 | unsigned int bytes_have; /**< Number of bytes in the context buffer */ | ||
441 | uint64_t count_hi; /**< The high part to be moved to another variable */ | ||
442 | |||
443 | mhd_assert ((data != NULL) || (length == 0)); | ||
444 | |||
445 | if (0 == length) | ||
446 | return; /* Do nothing */ | ||
447 | |||
448 | /* Note: (count & (SHA512_256_BLOCK_SIZE-1)) | ||
449 | equals (count % SHA512_256_BLOCK_SIZE) for this block size. */ | ||
450 | bytes_have = (unsigned int) (ctx->count & (SHA512_256_BLOCK_SIZE - 1)); | ||
451 | ctx->count += length; | ||
452 | count_hi = ctx->count >> 61; | ||
453 | if (0 != count_hi) | ||
454 | { | ||
455 | ctx->count_bits_hi += count_hi; | ||
456 | ctx->count &= UINT64_C (0x1FFFFFFFFFFFFFFF); | ||
457 | } | ||
458 | |||
459 | if (0 != bytes_have) | ||
460 | { | ||
461 | unsigned int bytes_left = SHA512_256_BLOCK_SIZE - bytes_have; | ||
462 | if (length >= bytes_left) | ||
463 | { /* Combine new data with data in the buffer and | ||
464 | process the full block. */ | ||
465 | memcpy (((uint8_t *) ctx->buffer) + bytes_have, | ||
466 | data, | ||
467 | bytes_left); | ||
468 | data += bytes_left; | ||
469 | length -= bytes_left; | ||
470 | sha512_256_transform (ctx->H, ctx->buffer); | ||
471 | bytes_have = 0; | ||
472 | } | ||
473 | } | ||
474 | |||
475 | while (SHA512_256_BLOCK_SIZE <= length) | ||
476 | { /* Process any full blocks of new data directly, | ||
477 | without copying to the buffer. */ | ||
478 | sha512_256_transform (ctx->H, data); | ||
479 | data += SHA512_256_BLOCK_SIZE; | ||
480 | length -= SHA512_256_BLOCK_SIZE; | ||
481 | } | ||
482 | |||
483 | if (0 != length) | ||
484 | { /* Copy incomplete block of new data (if any) | ||
485 | to the buffer. */ | ||
486 | memcpy (((uint8_t *) ctx->buffer) + bytes_have, data, length); | ||
487 | } | ||
488 | } | ||
489 | |||
490 | |||
491 | /** | ||
492 | * Size of "length" insertion in bits. | ||
493 | * See FIPS PUB 180-4 clause 5.1.2. | ||
494 | */ | ||
495 | #define SHA512_256_SIZE_OF_LEN_ADD_BITS 128 | ||
496 | |||
497 | /** | ||
498 | * Size of "length" insertion in bytes. | ||
499 | */ | ||
500 | #define SHA512_256_SIZE_OF_LEN_ADD (SHA512_256_SIZE_OF_LEN_ADD_BITS / 8) | ||
501 | |||
502 | /** | ||
503 | * Finalise SHA-512/256 calculation, return digest. | ||
504 | * | ||
505 | * @param ctx the calculation context | ||
506 | * @param[out] digest set to the hash, must be #SHA512_256_DIGEST_SIZE bytes | ||
507 | */ | ||
508 | void | ||
509 | MHD_SHA512_256_finish (struct Sha512_256Ctx *ctx, | ||
510 | uint8_t digest[SHA512_256_DIGEST_SIZE]) | ||
511 | { | ||
512 | uint64_t num_bits; /**< Number of processed bits */ | ||
513 | unsigned int bytes_have; /**< Number of bytes in the context buffer */ | ||
514 | |||
515 | /* Memorise the number of processed bits. | ||
516 | The padding and other data added here during the postprocessing must | ||
517 | not change the amount of hashed data. */ | ||
518 | num_bits = ctx->count << 3; | ||
519 | |||
520 | /* Note: (count & (SHA512_256_BLOCK_SIZE-1)) | ||
521 | equals (count % SHA512_256_BLOCK_SIZE) for this block size. */ | ||
522 | bytes_have = (unsigned int) (ctx->count & (SHA512_256_BLOCK_SIZE - 1)); | ||
523 | |||
524 | /* Input data must be padded with bit "1" and then the length of data in bits | ||
525 | must be added as the final bytes of the last block. | ||
526 | See FIPS PUB 180-4 clause 5.1.2. */ | ||
527 | /* Data is always processed in form of bytes (not by individual bits), | ||
528 | therefore position of the first padding bit in byte is always | ||
529 | predefined (0x80). */ | ||
530 | /* Buffer always have space for one byte at least (as full buffers are | ||
531 | processed immediately). */ | ||
532 | ((uint8_t *) ctx->buffer)[bytes_have++] = 0x80; | ||
533 | |||
534 | if (SHA512_256_BLOCK_SIZE - bytes_have < SHA512_256_SIZE_OF_LEN_ADD) | ||
535 | { /* No space in the current block to put the total length of message. | ||
536 | Pad the current block with zeros and process it. */ | ||
537 | if (bytes_have < SHA512_256_BLOCK_SIZE) | ||
538 | memset (((uint8_t *) ctx->buffer) + bytes_have, 0, | ||
539 | SHA512_256_BLOCK_SIZE - bytes_have); | ||
540 | /* Process the full block. */ | ||
541 | sha512_256_transform (ctx->H, ctx->buffer); | ||
542 | /* Start the new block. */ | ||
543 | bytes_have = 0; | ||
544 | } | ||
545 | |||
546 | /* Pad the rest of the buffer with zeros. */ | ||
547 | memset (((uint8_t *) ctx->buffer) + bytes_have, 0, | ||
548 | SHA512_256_BLOCK_SIZE - SHA512_256_SIZE_OF_LEN_ADD - bytes_have); | ||
549 | /* Put high part of number of bits in processed message and then lower | ||
550 | part of number of bits as big-endian values. | ||
551 | See FIPS PUB 180-4 clause 5.1.2. */ | ||
552 | /* Note: the target location is predefined and buffer is always aligned */ | ||
553 | _MHD_PUT_64BIT_BE (ctx->buffer + SHA512_256_BLOCK_SIZE_WORDS - 2, | ||
554 | ctx->count_bits_hi); | ||
555 | _MHD_PUT_64BIT_BE (ctx->buffer + SHA512_256_BLOCK_SIZE_WORDS - 1, | ||
556 | num_bits); | ||
557 | /* Process the full final block. */ | ||
558 | sha512_256_transform (ctx->H, ctx->buffer); | ||
559 | |||
560 | /* Put in BE mode the leftmost part of the hash as the final digest. | ||
561 | See FIPS PUB 180-4 clause 6.7. */ | ||
562 | #ifndef _MHD_PUT_64BIT_BE_UNALIGNED | ||
563 | if (0 != ((uintptr_t) digest) % _MHD_UINT64_ALIGN) | ||
564 | { /* The destination is unaligned */ | ||
565 | uint64_t alig_dgst[SHA512_256_DIGEST_SIZE_WORDS]; | ||
566 | _MHD_PUT_64BIT_BE (alig_dgst + 0, ctx->H[0]); | ||
567 | _MHD_PUT_64BIT_BE (alig_dgst + 1, ctx->H[1]); | ||
568 | _MHD_PUT_64BIT_BE (alig_dgst + 2, ctx->H[2]); | ||
569 | _MHD_PUT_64BIT_BE (alig_dgst + 3, ctx->H[3]); | ||
570 | /* Copy result to the unaligned destination address */ | ||
571 | memcpy (digest, alig_dgst, SHA512_256_DIGEST_SIZE); | ||
572 | } | ||
573 | else /* Combined with the next 'if' */ | ||
574 | #endif /* ! _MHD_PUT_64BIT_BE_UNALIGNED */ | ||
575 | if (1) | ||
576 | { | ||
577 | /* Use cast to (void*) here to mute compiler alignment warnings. | ||
578 | * Compilers are not smart enough to see that alignment has been checked. */ | ||
579 | _MHD_PUT_64BIT_BE ((void *) (digest + 0 * SHA512_256_BYTES_IN_WORD), \ | ||
580 | ctx->H[0]); | ||
581 | _MHD_PUT_64BIT_BE ((void *) (digest + 1 * SHA512_256_BYTES_IN_WORD), \ | ||
582 | ctx->H[1]); | ||
583 | _MHD_PUT_64BIT_BE ((void *) (digest + 2 * SHA512_256_BYTES_IN_WORD), \ | ||
584 | ctx->H[2]); | ||
585 | _MHD_PUT_64BIT_BE ((void *) (digest + 3 * SHA512_256_BYTES_IN_WORD), \ | ||
586 | ctx->H[3]); | ||
587 | } | ||
588 | |||
589 | /* Erase potentially sensitive data. */ | ||
590 | memset (ctx, 0, sizeof(struct Sha512_256Ctx)); | ||
591 | } | ||