aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/sha512_256.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/sha512_256.c')
-rw-r--r--src/microhttpd/sha512_256.c591
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 */
40void
41MHD_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 */
67static void
68sha512_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 */
435void
436MHD_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 */
508void
509MHD_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}