/src/mhd2/src/mhd2/md5_int.c
Line | Count | Source |
1 | | /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ |
2 | | /* |
3 | | This file is part of GNU libmicrohttpd. |
4 | | Copyright (C) 2022-2024 Evgeny Grin (Karlson2k) |
5 | | |
6 | | GNU libmicrohttpd is free software; you can redistribute it and/or |
7 | | modify it under the terms of the GNU Lesser General Public |
8 | | License as published by the Free Software Foundation; either |
9 | | version 2.1 of the License, or (at your option) any later version. |
10 | | |
11 | | GNU libmicrohttpd is distributed in the hope that it will be useful, |
12 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | | Lesser General Public License for more details. |
15 | | |
16 | | Alternatively, you can redistribute GNU libmicrohttpd and/or |
17 | | modify it under the terms of the GNU General Public License as |
18 | | published by the Free Software Foundation; either version 2 of |
19 | | the License, or (at your option) any later version, together |
20 | | with the eCos exception, as follows: |
21 | | |
22 | | As a special exception, if other files instantiate templates or |
23 | | use macros or inline functions from this file, or you compile this |
24 | | file and link it with other works to produce a work based on this |
25 | | file, this file does not by itself cause the resulting work to be |
26 | | covered by the GNU General Public License. However the source code |
27 | | for this file must still be made available in accordance with |
28 | | section (3) of the GNU General Public License v2. |
29 | | |
30 | | This exception does not invalidate any other reasons why a work |
31 | | based on this file might be covered by the GNU General Public |
32 | | License. |
33 | | |
34 | | You should have received copies of the GNU Lesser General Public |
35 | | License and the GNU General Public License along with this library; |
36 | | if not, see <https://www.gnu.org/licenses/>. |
37 | | */ |
38 | | |
39 | | /** |
40 | | * @file src/mhd2/md5_int.c |
41 | | * @brief Calculation of MD5 digest as defined in RFC 1321 |
42 | | * @author Karlson2k (Evgeny Grin) |
43 | | */ |
44 | | |
45 | | #include "mhd_sys_options.h" |
46 | | |
47 | | #include "sys_bool_type.h" |
48 | | |
49 | | #include <string.h> |
50 | | #include "mhd_bithelpers.h" |
51 | | #include "mhd_assert.h" |
52 | | |
53 | | #include "md5_int.h" |
54 | | |
55 | | MHD_INTERNAL void MHD_FN_PAR_NONNULL_ALL_ |
56 | | mhd_MD5_init (struct mhd_Md5CtxInt *ctx) |
57 | 0 | { |
58 | | /* Initial hash values, see RFC 1321, Clause 3.3 (step 3). */ |
59 | | /* Note: values specified in RFC by bytes and should be loaded in |
60 | | little-endian mode, therefore hash values here are initialised with |
61 | | original bytes used in little-endian order. */ |
62 | 0 | ctx->H[0] = UINT32_C (0x67452301); |
63 | 0 | ctx->H[1] = UINT32_C (0xefcdab89); |
64 | 0 | ctx->H[2] = UINT32_C (0x98badcfe); |
65 | 0 | ctx->H[3] = UINT32_C (0x10325476); |
66 | | |
67 | | /* Initialise the number of bytes. */ |
68 | 0 | ctx->count = 0; |
69 | 0 | } |
70 | | |
71 | | |
72 | | mhd_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE |
73 | | |
74 | | /** |
75 | | * Base of MD5 transformation. |
76 | | * Gets full 64 bytes block of data and updates hash values; |
77 | | * @param H hash values |
78 | | * @param M the data buffer with #mhd_MD5_BLOCK_SIZE bytes block |
79 | | */ |
80 | | static MHD_FN_PAR_NONNULL_ALL_ void |
81 | | md5_transform (uint32_t H[mhd_MD5_HASH_SIZE_WORDS], |
82 | | const void *restrict M) |
83 | 0 | { |
84 | | /* Working variables, |
85 | | See RFC 1321, Clause 3.4 (step 4). */ |
86 | 0 | uint32_t A = H[0]; |
87 | 0 | uint32_t B = H[1]; |
88 | 0 | uint32_t C = H[2]; |
89 | 0 | uint32_t D = H[3]; |
90 | | |
91 | | /* The data buffer. See RFC 1321, Clause 3.4 (step 4). */ |
92 | 0 | uint32_t X[16]; |
93 | |
|
94 | 0 | #ifndef mhd_GET_32BIT_LE_UNALIGNED |
95 | 0 | if (0 != (((uintptr_t) M) % mhd_UINT32_ALIGN)) |
96 | 0 | { /* The input data is unaligned. */ |
97 | | /* Copy the unaligned input data to the aligned buffer. */ |
98 | 0 | memcpy (X, M, sizeof(X)); |
99 | | /* The X[] buffer itself will be used as the source of the data, |
100 | | * but the data will be reloaded in correct bytes order on |
101 | | * the next steps. */ |
102 | 0 | M = (const void *) X; |
103 | 0 | } |
104 | 0 | #endif /* mhd_GET_32BIT_LE_UNALIGNED */ |
105 | | |
106 | | /* Four auxiliary functions, see RFC 1321, Clause 3.4 (step 4). */ |
107 | | /* Some optimisations used. */ |
108 | | /* #define F_FUNC(x,y,z) (((x)&(y)) | ((~(x))&(z))) */ /* Original version */ |
109 | 0 | #define F_FUNC(x,y,z) ((((y) ^ (z)) & (x)) ^ (z)) |
110 | | /* #define G_FUNC_1(x,y,z) (((x)&(z)) | ((y)&(~(z)))) */ /* Original version */ |
111 | | /* #define G_FUNC_2(x,y,z) UINT32_C(0) */ /* Original version */ |
112 | 0 | #ifndef MHD_FAVOR_SMALL_CODE |
113 | 0 | # define G_FUNC_1(x,y,z) ((~(z)) & (y)) |
114 | 0 | # define G_FUNC_2(x,y,z) ((z) & (x)) |
115 | | #else /* MHD_FAVOR_SMALL_CODE */ |
116 | | # define G_FUNC_1(x,y,z) ((((x) ^ (y)) & (z)) ^ (y)) |
117 | | # define G_FUNC_2(x,y,z) UINT32_C (0) |
118 | | #endif /* MHD_FAVOR_SMALL_CODE */ |
119 | 0 | #define H_FUNC(x,y,z) ((x) ^ (y) ^ (z)) /* Original version */ |
120 | | /* #define I_FUNC(x,y,z) ((y) ^ ((x) | (~(z)))) */ /* Original version */ |
121 | 0 | #define I_FUNC(x,y,z) (((~(z)) | (x)) ^ (y)) |
122 | | |
123 | | /* One step of round 1 of MD5 computation, see RFC 1321, Clause 3.4 (step 4). |
124 | | The original function was modified to use X[k] and T[i] as |
125 | | direct inputs. */ |
126 | 0 | #define MD5STEP_R1(va,vb,vc,vd,vX,vs,vT) do { \ |
127 | 0 | (va) += (vX) + (vT); \ |
128 | 0 | (va) += F_FUNC ((vb),(vc),(vd)); \ |
129 | 0 | (va) = mhd_ROTL32 ((va),(vs)) + (vb); } while (0) |
130 | | |
131 | | /* Get value of X(k) from input data buffer. |
132 | | See RFC 1321 Clause 3.4 (step 4). */ |
133 | 0 | #define GET_X_FROM_DATA(buf,t) \ |
134 | 0 | mhd_GET_32BIT_LE (((const uint32_t*) (buf)) + (t)) |
135 | | |
136 | | /* One step of round 2 of MD5 computation, see RFC 1321, Clause 3.4 (step 4). |
137 | | The original function was modified to use X[k] and T[i] as |
138 | | direct inputs. */ |
139 | 0 | #define MD5STEP_R2(va,vb,vc,vd,vX,vs,vT) do { \ |
140 | 0 | (va) += (vX) + (vT); \ |
141 | 0 | (va) += G_FUNC_1 ((vb),(vc),(vd)); \ |
142 | 0 | (va) += G_FUNC_2 ((vb),(vc),(vd)); \ |
143 | 0 | (va) = mhd_ROTL32 ((va),(vs)) + (vb); } while (0) |
144 | | |
145 | | /* One step of round 3 of MD5 computation, see RFC 1321, Clause 3.4 (step 4). |
146 | | The original function was modified to use X[k] and T[i] as |
147 | | direct inputs. */ |
148 | 0 | #define MD5STEP_R3(va,vb,vc,vd,vX,vs,vT) do { \ |
149 | 0 | (va) += (vX) + (vT); \ |
150 | 0 | (va) += H_FUNC ((vb),(vc),(vd)); \ |
151 | 0 | (va) = mhd_ROTL32 ((va),(vs)) + (vb); } while (0) |
152 | | |
153 | | /* One step of round 4 of MD5 computation, see RFC 1321, Clause 3.4 (step 4). |
154 | | The original function was modified to use X[k] and T[i] as |
155 | | direct inputs. */ |
156 | 0 | #define MD5STEP_R4(va,vb,vc,vd,vX,vs,vT) do { \ |
157 | 0 | (va) += (vX) + (vT); \ |
158 | 0 | (va) += I_FUNC ((vb),(vc),(vd)); \ |
159 | 0 | (va) = mhd_ROTL32 ((va),(vs)) + (vb); } while (0) |
160 | |
|
161 | 0 | #if ! defined(MHD_FAVOR_SMALL_CODE) |
162 | | |
163 | | /* Round 1. */ |
164 | |
|
165 | 0 | #if mhd_BYTE_ORDER == mhd_LITTLE_ENDIAN |
166 | 0 | if ((const void *) X == M) |
167 | 0 | { |
168 | | /* The input data is already in the data buffer X[] in correct bytes |
169 | | order. */ |
170 | 0 | MD5STEP_R1 (A, B, C, D, X[0], 7, UINT32_C (0xd76aa478)); |
171 | 0 | MD5STEP_R1 (D, A, B, C, X[1], 12, UINT32_C (0xe8c7b756)); |
172 | 0 | MD5STEP_R1 (C, D, A, B, X[2], 17, UINT32_C (0x242070db)); |
173 | 0 | MD5STEP_R1 (B, C, D, A, X[3], 22, UINT32_C (0xc1bdceee)); |
174 | |
|
175 | 0 | MD5STEP_R1 (A, B, C, D, X[4], 7, UINT32_C (0xf57c0faf)); |
176 | 0 | MD5STEP_R1 (D, A, B, C, X[5], 12, UINT32_C (0x4787c62a)); |
177 | 0 | MD5STEP_R1 (C, D, A, B, X[6], 17, UINT32_C (0xa8304613)); |
178 | 0 | MD5STEP_R1 (B, C, D, A, X[7], 22, UINT32_C (0xfd469501)); |
179 | |
|
180 | 0 | MD5STEP_R1 (A, B, C, D, X[8], 7, UINT32_C (0x698098d8)); |
181 | 0 | MD5STEP_R1 (D, A, B, C, X[9], 12, UINT32_C (0x8b44f7af)); |
182 | 0 | MD5STEP_R1 (C, D, A, B, X[10], 17, UINT32_C (0xffff5bb1)); |
183 | 0 | MD5STEP_R1 (B, C, D, A, X[11], 22, UINT32_C (0x895cd7be)); |
184 | |
|
185 | 0 | MD5STEP_R1 (A, B, C, D, X[12], 7, UINT32_C (0x6b901122)); |
186 | 0 | MD5STEP_R1 (D, A, B, C, X[13], 12, UINT32_C (0xfd987193)); |
187 | 0 | MD5STEP_R1 (C, D, A, B, X[14], 17, UINT32_C (0xa679438e)); |
188 | 0 | MD5STEP_R1 (B, C, D, A, X[15], 22, UINT32_C (0x49b40821)); |
189 | 0 | } |
190 | 0 | else /* Combined with the next 'if' */ |
191 | 0 | #endif /* mhd_BYTE_ORDER == mhd_LITTLE_ENDIAN */ |
192 | 0 | if (1) |
193 | 0 | { |
194 | | /* The input data is loaded in correct (little-endian) format before |
195 | | calculations on each step. */ |
196 | 0 | MD5STEP_R1 (A, B, C, D, X[0] = GET_X_FROM_DATA (M, 0), 7, \ |
197 | 0 | UINT32_C (0xd76aa478)); |
198 | 0 | MD5STEP_R1 (D, A, B, C, X[1] = GET_X_FROM_DATA (M, 1), 12, \ |
199 | 0 | UINT32_C (0xe8c7b756)); |
200 | 0 | MD5STEP_R1 (C, D, A, B, X[2] = GET_X_FROM_DATA (M, 2), 17, \ |
201 | 0 | UINT32_C (0x242070db)); |
202 | 0 | MD5STEP_R1 (B, C, D, A, X[3] = GET_X_FROM_DATA (M, 3), 22, \ |
203 | 0 | UINT32_C (0xc1bdceee)); |
204 | |
|
205 | 0 | MD5STEP_R1 (A, B, C, D, X[4] = GET_X_FROM_DATA (M, 4), 7, \ |
206 | 0 | UINT32_C (0xf57c0faf)); |
207 | 0 | MD5STEP_R1 (D, A, B, C, X[5] = GET_X_FROM_DATA (M, 5), 12, \ |
208 | 0 | UINT32_C (0x4787c62a)); |
209 | 0 | MD5STEP_R1 (C, D, A, B, X[6] = GET_X_FROM_DATA (M, 6), 17, \ |
210 | 0 | UINT32_C (0xa8304613)); |
211 | 0 | MD5STEP_R1 (B, C, D, A, X[7] = GET_X_FROM_DATA (M, 7), 22, \ |
212 | 0 | UINT32_C (0xfd469501)); |
213 | |
|
214 | 0 | MD5STEP_R1 (A, B, C, D, X[8] = GET_X_FROM_DATA (M, 8), 7, \ |
215 | 0 | UINT32_C (0x698098d8)); |
216 | 0 | MD5STEP_R1 (D, A, B, C, X[9] = GET_X_FROM_DATA (M, 9), 12, \ |
217 | 0 | UINT32_C (0x8b44f7af)); |
218 | 0 | MD5STEP_R1 (C, D, A, B, X[10] = GET_X_FROM_DATA (M, 10), 17, \ |
219 | 0 | UINT32_C (0xffff5bb1)); |
220 | 0 | MD5STEP_R1 (B, C, D, A, X[11] = GET_X_FROM_DATA (M, 11), 22, \ |
221 | 0 | UINT32_C (0x895cd7be)); |
222 | |
|
223 | 0 | MD5STEP_R1 (A, B, C, D, X[12] = GET_X_FROM_DATA (M, 12), 7, \ |
224 | 0 | UINT32_C (0x6b901122)); |
225 | 0 | MD5STEP_R1 (D, A, B, C, X[13] = GET_X_FROM_DATA (M, 13), 12, \ |
226 | 0 | UINT32_C (0xfd987193)); |
227 | 0 | MD5STEP_R1 (C, D, A, B, X[14] = GET_X_FROM_DATA (M, 14), 17, \ |
228 | 0 | UINT32_C (0xa679438e)); |
229 | 0 | MD5STEP_R1 (B, C, D, A, X[15] = GET_X_FROM_DATA (M, 15), 22, \ |
230 | 0 | UINT32_C (0x49b40821)); |
231 | 0 | } |
232 | | |
233 | | /* Round 2. */ |
234 | |
|
235 | 0 | MD5STEP_R2 (A, B, C, D, X[1], 5, UINT32_C (0xf61e2562)); |
236 | 0 | MD5STEP_R2 (D, A, B, C, X[6], 9, UINT32_C (0xc040b340)); |
237 | 0 | MD5STEP_R2 (C, D, A, B, X[11], 14, UINT32_C (0x265e5a51)); |
238 | 0 | MD5STEP_R2 (B, C, D, A, X[0], 20, UINT32_C (0xe9b6c7aa)); |
239 | |
|
240 | 0 | MD5STEP_R2 (A, B, C, D, X[5], 5, UINT32_C (0xd62f105d)); |
241 | 0 | MD5STEP_R2 (D, A, B, C, X[10], 9, UINT32_C (0x02441453)); |
242 | 0 | MD5STEP_R2 (C, D, A, B, X[15], 14, UINT32_C (0xd8a1e681)); |
243 | 0 | MD5STEP_R2 (B, C, D, A, X[4], 20, UINT32_C (0xe7d3fbc8)); |
244 | |
|
245 | 0 | MD5STEP_R2 (A, B, C, D, X[9], 5, UINT32_C (0x21e1cde6)); |
246 | 0 | MD5STEP_R2 (D, A, B, C, X[14], 9, UINT32_C (0xc33707d6)); |
247 | 0 | MD5STEP_R2 (C, D, A, B, X[3], 14, UINT32_C (0xf4d50d87)); |
248 | 0 | MD5STEP_R2 (B, C, D, A, X[8], 20, UINT32_C (0x455a14ed)); |
249 | |
|
250 | 0 | MD5STEP_R2 (A, B, C, D, X[13], 5, UINT32_C (0xa9e3e905)); |
251 | 0 | MD5STEP_R2 (D, A, B, C, X[2], 9, UINT32_C (0xfcefa3f8)); |
252 | 0 | MD5STEP_R2 (C, D, A, B, X[7], 14, UINT32_C (0x676f02d9)); |
253 | 0 | MD5STEP_R2 (B, C, D, A, X[12], 20, UINT32_C (0x8d2a4c8a)); |
254 | | |
255 | | /* Round 3. */ |
256 | |
|
257 | 0 | MD5STEP_R3 (A, B, C, D, X[5], 4, UINT32_C (0xfffa3942)); |
258 | 0 | MD5STEP_R3 (D, A, B, C, X[8], 11, UINT32_C (0x8771f681)); |
259 | 0 | MD5STEP_R3 (C, D, A, B, X[11], 16, UINT32_C (0x6d9d6122)); |
260 | 0 | MD5STEP_R3 (B, C, D, A, X[14], 23, UINT32_C (0xfde5380c)); |
261 | |
|
262 | 0 | MD5STEP_R3 (A, B, C, D, X[1], 4, UINT32_C (0xa4beea44)); |
263 | 0 | MD5STEP_R3 (D, A, B, C, X[4], 11, UINT32_C (0x4bdecfa9)); |
264 | 0 | MD5STEP_R3 (C, D, A, B, X[7], 16, UINT32_C (0xf6bb4b60)); |
265 | 0 | MD5STEP_R3 (B, C, D, A, X[10], 23, UINT32_C (0xbebfbc70)); |
266 | |
|
267 | 0 | MD5STEP_R3 (A, B, C, D, X[13], 4, UINT32_C (0x289b7ec6)); |
268 | 0 | MD5STEP_R3 (D, A, B, C, X[0], 11, UINT32_C (0xeaa127fa)); |
269 | 0 | MD5STEP_R3 (C, D, A, B, X[3], 16, UINT32_C (0xd4ef3085)); |
270 | 0 | MD5STEP_R3 (B, C, D, A, X[6], 23, UINT32_C (0x04881d05)); |
271 | |
|
272 | 0 | MD5STEP_R3 (A, B, C, D, X[9], 4, UINT32_C (0xd9d4d039)); |
273 | 0 | MD5STEP_R3 (D, A, B, C, X[12], 11, UINT32_C (0xe6db99e5)); |
274 | 0 | MD5STEP_R3 (C, D, A, B, X[15], 16, UINT32_C (0x1fa27cf8)); |
275 | 0 | MD5STEP_R3 (B, C, D, A, X[2], 23, UINT32_C (0xc4ac5665)); |
276 | | |
277 | | /* Round 4. */ |
278 | |
|
279 | 0 | MD5STEP_R4 (A, B, C, D, X[0], 6, UINT32_C (0xf4292244)); |
280 | 0 | MD5STEP_R4 (D, A, B, C, X[7], 10, UINT32_C (0x432aff97)); |
281 | 0 | MD5STEP_R4 (C, D, A, B, X[14], 15, UINT32_C (0xab9423a7)); |
282 | 0 | MD5STEP_R4 (B, C, D, A, X[5], 21, UINT32_C (0xfc93a039)); |
283 | |
|
284 | 0 | MD5STEP_R4 (A, B, C, D, X[12], 6, UINT32_C (0x655b59c3)); |
285 | 0 | MD5STEP_R4 (D, A, B, C, X[3], 10, UINT32_C (0x8f0ccc92)); |
286 | 0 | MD5STEP_R4 (C, D, A, B, X[10], 15, UINT32_C (0xffeff47d)); |
287 | 0 | MD5STEP_R4 (B, C, D, A, X[1], 21, UINT32_C (0x85845dd1)); |
288 | |
|
289 | 0 | MD5STEP_R4 (A, B, C, D, X[8], 6, UINT32_C (0x6fa87e4f)); |
290 | 0 | MD5STEP_R4 (D, A, B, C, X[15], 10, UINT32_C (0xfe2ce6e0)); |
291 | 0 | MD5STEP_R4 (C, D, A, B, X[6], 15, UINT32_C (0xa3014314)); |
292 | 0 | MD5STEP_R4 (B, C, D, A, X[13], 21, UINT32_C (0x4e0811a1)); |
293 | |
|
294 | 0 | MD5STEP_R4 (A, B, C, D, X[4], 6, UINT32_C (0xf7537e82)); |
295 | 0 | MD5STEP_R4 (D, A, B, C, X[11], 10, UINT32_C (0xbd3af235)); |
296 | 0 | MD5STEP_R4 (C, D, A, B, X[2], 15, UINT32_C (0x2ad7d2bb)); |
297 | 0 | MD5STEP_R4 (B, C, D, A, X[9], 21, UINT32_C (0xeb86d391)); |
298 | | #else /* MHD_FAVOR_SMALL_CODE */ |
299 | | if (1) |
300 | | { |
301 | | static const uint32_t T[64] = |
302 | | { UINT32_C (0xd76aa478), UINT32_C (0xe8c7b756), UINT32_C (0x242070db), |
303 | | UINT32_C (0xc1bdceee), UINT32_C (0xf57c0faf), UINT32_C (0x4787c62a), |
304 | | UINT32_C (0xa8304613), UINT32_C (0xfd469501), UINT32_C (0x698098d8), |
305 | | UINT32_C (0x8b44f7af), UINT32_C (0xffff5bb1), UINT32_C (0x895cd7be), |
306 | | UINT32_C (0x6b901122), UINT32_C (0xfd987193), UINT32_C (0xa679438e), |
307 | | UINT32_C (0x49b40821), UINT32_C (0xf61e2562), UINT32_C (0xc040b340), |
308 | | UINT32_C (0x265e5a51), UINT32_C (0xe9b6c7aa), UINT32_C (0xd62f105d), |
309 | | UINT32_C (0x02441453), UINT32_C (0xd8a1e681), UINT32_C (0xe7d3fbc8), |
310 | | UINT32_C (0x21e1cde6), UINT32_C (0xc33707d6), UINT32_C (0xf4d50d87), |
311 | | UINT32_C (0x455a14ed), UINT32_C (0xa9e3e905), UINT32_C (0xfcefa3f8), |
312 | | UINT32_C (0x676f02d9), UINT32_C (0x8d2a4c8a), UINT32_C (0xfffa3942), |
313 | | UINT32_C (0x8771f681), UINT32_C (0x6d9d6122), UINT32_C (0xfde5380c), |
314 | | UINT32_C (0xa4beea44), UINT32_C (0x4bdecfa9), UINT32_C (0xf6bb4b60), |
315 | | UINT32_C (0xbebfbc70), UINT32_C (0x289b7ec6), UINT32_C (0xeaa127fa), |
316 | | UINT32_C (0xd4ef3085), UINT32_C (0x04881d05), UINT32_C (0xd9d4d039), |
317 | | UINT32_C (0xe6db99e5), UINT32_C (0x1fa27cf8), UINT32_C (0xc4ac5665), |
318 | | UINT32_C (0xf4292244), UINT32_C (0x432aff97), UINT32_C (0xab9423a7), |
319 | | UINT32_C (0xfc93a039), UINT32_C (0x655b59c3), UINT32_C (0x8f0ccc92), |
320 | | UINT32_C (0xffeff47d), UINT32_C (0x85845dd1), UINT32_C (0x6fa87e4f), |
321 | | UINT32_C (0xfe2ce6e0), UINT32_C (0xa3014314), UINT32_C (0x4e0811a1), |
322 | | UINT32_C (0xf7537e82), UINT32_C (0xbd3af235), UINT32_C (0x2ad7d2bb), |
323 | | UINT32_C (0xeb86d391) }; |
324 | | unsigned int i; /**< Zero-based index */ |
325 | | |
326 | | /* Round 1. */ |
327 | | |
328 | | i = 0; |
329 | | do |
330 | | { |
331 | | /* The input data is loaded in correct (little-endian) format before |
332 | | calculations on each step. */ |
333 | | MD5STEP_R1 (A, B, C, D, X[i] = GET_X_FROM_DATA (M, i), 7, T[i]); |
334 | | ++i; |
335 | | MD5STEP_R1 (D, A, B, C, X[i] = GET_X_FROM_DATA (M, i), 12, T[i]); |
336 | | ++i; |
337 | | MD5STEP_R1 (C, D, A, B, X[i] = GET_X_FROM_DATA (M, i), 17, T[i]); |
338 | | ++i; |
339 | | MD5STEP_R1 (B, C, D, A, X[i] = GET_X_FROM_DATA (M, i), 22, T[i]); |
340 | | ++i; |
341 | | } while (i < 16); |
342 | | |
343 | | /* Round 2. */ |
344 | | |
345 | | do |
346 | | { |
347 | | const unsigned int idx_add = i; |
348 | | MD5STEP_R2 (A, B, C, D, X[(1U + idx_add) & 15U], 5, T[i]); |
349 | | ++i; |
350 | | MD5STEP_R2 (D, A, B, C, X[(6U + idx_add) & 15U], 9, T[i]); |
351 | | ++i; |
352 | | MD5STEP_R2 (C, D, A, B, X[(11U + idx_add) & 15U], 14, T[i]); |
353 | | ++i; |
354 | | MD5STEP_R2 (B, C, D, A, X[(0U + idx_add) & 15U], 20, T[i]); |
355 | | ++i; |
356 | | } while (i < 32); |
357 | | |
358 | | /* Round 3. */ |
359 | | |
360 | | do |
361 | | { |
362 | | const unsigned int idx_add = i; |
363 | | MD5STEP_R3 (A, B, C, D, X[(5U + 64U - idx_add) & 15U], 4, T[i]); |
364 | | ++i; |
365 | | MD5STEP_R3 (D, A, B, C, X[(8U + 64U - idx_add) & 15U], 11, T[i]); |
366 | | ++i; |
367 | | MD5STEP_R3 (C, D, A, B, X[(11U + 64U - idx_add) & 15U], 16, T[i]); |
368 | | ++i; |
369 | | MD5STEP_R3 (B, C, D, A, X[(14U + 64U - idx_add) & 15U], 23, T[i]); |
370 | | ++i; |
371 | | } while (i < 48); |
372 | | |
373 | | /* Round 4. */ |
374 | | |
375 | | do |
376 | | { |
377 | | const unsigned int idx_add = i; |
378 | | MD5STEP_R4 (A, B, C, D, X[(0U + 64U - idx_add) & 15U], 6, T[i]); |
379 | | ++i; |
380 | | MD5STEP_R4 (D, A, B, C, X[(7U + 64U - idx_add) & 15U], 10, T[i]); |
381 | | ++i; |
382 | | MD5STEP_R4 (C, D, A, B, X[(14U + 64U - idx_add) & 15U], 15, T[i]); |
383 | | ++i; |
384 | | MD5STEP_R4 (B, C, D, A, X[(5U + 64U - idx_add) & 15U], 21, T[i]); |
385 | | ++i; |
386 | | } while (i < 64); |
387 | | } |
388 | | #endif /* MHD_FAVOR_SMALL_CODE */ |
389 | | |
390 | | /* Finally increment and store working variables. |
391 | | See RFC 1321, end of Clause 3.4 (step 4). */ |
392 | |
|
393 | 0 | H[0] += A; |
394 | 0 | H[1] += B; |
395 | 0 | H[2] += C; |
396 | 0 | H[3] += D; |
397 | 0 | } |
398 | | |
399 | | |
400 | | MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ |
401 | | MHD_FN_PAR_IN_SIZE_ (3, 2) void |
402 | | mhd_MD5_update (struct mhd_Md5CtxInt *restrict ctx, |
403 | | size_t size, |
404 | | const uint8_t *restrict data) |
405 | 0 | { |
406 | 0 | unsigned int bytes_have; /**< Number of bytes in the context buffer */ |
407 | |
|
408 | 0 | mhd_assert (0 != size); |
409 | | |
410 | | /* Note: (count & (mhd_MD5_BLOCK_SIZE-1)) |
411 | | equals (count % mhd_MD5_BLOCK_SIZE) for this block size. */ |
412 | 0 | bytes_have = (unsigned int) (ctx->count & (mhd_MD5_BLOCK_SIZE - 1)); |
413 | 0 | ctx->count += size; |
414 | |
|
415 | 0 | if (0 != bytes_have) |
416 | 0 | { |
417 | 0 | unsigned int bytes_left = mhd_MD5_BLOCK_SIZE - bytes_have; |
418 | 0 | if (size >= bytes_left) |
419 | 0 | { /* Combine new data with data in the buffer and |
420 | | process the full block. */ |
421 | 0 | memcpy (((uint8_t *) ctx->buffer) + bytes_have, |
422 | 0 | data, |
423 | 0 | bytes_left); |
424 | 0 | data += bytes_left; |
425 | 0 | size -= bytes_left; |
426 | 0 | md5_transform (ctx->H, ctx->buffer); |
427 | 0 | bytes_have = 0; |
428 | 0 | } |
429 | 0 | } |
430 | |
|
431 | 0 | while (mhd_MD5_BLOCK_SIZE <= size) |
432 | 0 | { /* Process any full blocks of new data directly, |
433 | | without copying to the buffer. */ |
434 | 0 | md5_transform (ctx->H, data); |
435 | 0 | data += mhd_MD5_BLOCK_SIZE; |
436 | 0 | size -= mhd_MD5_BLOCK_SIZE; |
437 | 0 | } |
438 | |
|
439 | 0 | if (0 != size) |
440 | 0 | { /* Copy incomplete block of new data (if any) |
441 | | to the buffer. */ |
442 | 0 | memcpy (((uint8_t *) ctx->buffer) + bytes_have, data, size); |
443 | 0 | } |
444 | 0 | } |
445 | | |
446 | | |
447 | | /** |
448 | | * Size of "length" insertion in bits. |
449 | | * See RFC 1321, end of Clause 3.2 (step 2). |
450 | | */ |
451 | 0 | #define MD5_SIZE_OF_LEN_ADD_BITS 64 |
452 | | |
453 | | /** |
454 | | * Size of "length" insertion in bytes. |
455 | | */ |
456 | 0 | #define MD5_SIZE_OF_LEN_ADD (MD5_SIZE_OF_LEN_ADD_BITS / 8) |
457 | | |
458 | | MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ |
459 | | MHD_FN_PAR_OUT_ (2) void |
460 | | mhd_MD5_finish (struct mhd_Md5CtxInt *restrict ctx, |
461 | | uint8_t digest[mhd_MD5_DIGEST_SIZE]) |
462 | 0 | { |
463 | 0 | uint64_t num_bits; /**< Number of processed bits */ |
464 | 0 | unsigned int bytes_have; /**< Number of bytes in the context buffer */ |
465 | | |
466 | | /* Memorise the number of processed bits. |
467 | | The padding and other data added here during the postprocessing must |
468 | | not change the amount of hashed data. */ |
469 | 0 | num_bits = ctx->count << 3; |
470 | | |
471 | | /* Note: (count & (mhd_MD5_BLOCK_SIZE-1)) |
472 | | equals (count % mhd_MD5_BLOCK_SIZE) for this block size. */ |
473 | 0 | bytes_have = (unsigned int) (ctx->count & (mhd_MD5_BLOCK_SIZE - 1)); |
474 | | |
475 | | /* Input data must be padded with a single bit "1", then with zeros and |
476 | | the finally the length of data in bits must be added as the final bytes |
477 | | of the last block. |
478 | | See RFC 1321, Clauses 3.1 and 3.2 (steps 1 and 2). */ |
479 | | /* Data is always processed in form of bytes (not by individual bits), |
480 | | therefore position of the first padding bit in byte is always |
481 | | predefined (0x80). */ |
482 | | /* Buffer always have space for one byte at least (as full buffers are |
483 | | processed immediately). */ |
484 | 0 | ((uint8_t *) ctx->buffer)[bytes_have++] = 0x80; |
485 | |
|
486 | 0 | if (mhd_MD5_BLOCK_SIZE - bytes_have < MD5_SIZE_OF_LEN_ADD) |
487 | 0 | { /* No space in the current block to put the total length of message. |
488 | | Pad the current block with zeros and process it. */ |
489 | 0 | if (bytes_have < mhd_MD5_BLOCK_SIZE) |
490 | 0 | memset (((uint8_t *) ctx->buffer) + bytes_have, 0, |
491 | 0 | mhd_MD5_BLOCK_SIZE - bytes_have); |
492 | | /* Process the full block. */ |
493 | 0 | md5_transform (ctx->H, ctx->buffer); |
494 | | /* Start the new block. */ |
495 | 0 | bytes_have = 0; |
496 | 0 | } |
497 | | |
498 | | /* Pad the rest of the buffer with zeros. */ |
499 | 0 | memset (((uint8_t *) ctx->buffer) + bytes_have, 0, |
500 | 0 | mhd_MD5_BLOCK_SIZE - MD5_SIZE_OF_LEN_ADD - bytes_have); |
501 | | /* Put the number of bits in processed data as little-endian value. |
502 | | See RFC 1321, clauses 2 and 3.2 (step 2). */ |
503 | 0 | mhd_PUT_64BIT_LE_UNALIGN (ctx->buffer + mhd_MD5_BLOCK_SIZE_WORDS - 2, |
504 | 0 | num_bits); |
505 | | /* Process the full final block. */ |
506 | 0 | md5_transform (ctx->H, ctx->buffer); |
507 | | |
508 | | /* Put in LE mode the hash as the final digest. |
509 | | See RFC 1321, clauses 2 and 3.5 (step 5). */ |
510 | 0 | if (1) |
511 | 0 | { |
512 | 0 | bool use_tmp_buf_to_align_result; |
513 | |
|
514 | | #if defined(mhd_PUT_32BIT_LE_UNALIGNED) |
515 | | use_tmp_buf_to_align_result = false; |
516 | | #elif defined (MHD_FAVOR_SMALL_CODE) |
517 | | use_tmp_buf_to_align_result = true; /* smaller code: eliminated branch below */ |
518 | | #else |
519 | 0 | use_tmp_buf_to_align_result = |
520 | 0 | (0 != ((uintptr_t) digest) % mhd_UINT32_ALIGN); |
521 | 0 | #endif |
522 | 0 | if (use_tmp_buf_to_align_result) |
523 | 0 | { |
524 | | /* If storing of the final result requires aligned address and |
525 | | the destination address is not aligned or compact code is used, |
526 | | store the final digest in aligned temporary buffer first, then |
527 | | copy it to the destination. */ |
528 | 0 | uint32_t alig_dgst[mhd_MD5_DIGEST_SIZE_WORDS]; |
529 | 0 | mhd_PUT_32BIT_LE (alig_dgst + 0, ctx->H[0]); |
530 | 0 | mhd_PUT_32BIT_LE (alig_dgst + 1, ctx->H[1]); |
531 | 0 | mhd_PUT_32BIT_LE (alig_dgst + 2, ctx->H[2]); |
532 | 0 | mhd_PUT_32BIT_LE (alig_dgst + 3, ctx->H[3]); |
533 | | /* Copy result to the unaligned destination address. */ |
534 | 0 | memcpy (digest, alig_dgst, mhd_MD5_DIGEST_SIZE); |
535 | 0 | } |
536 | 0 | else |
537 | 0 | { |
538 | | /* Use cast to (void*) here to mute compiler alignment warnings. |
539 | | * Compilers are not smart enough to see that alignment has been checked. */ |
540 | 0 | mhd_PUT_32BIT_LE ((void *) (digest + 0 * mhd_MD5_BYTES_IN_WORD), \ |
541 | 0 | ctx->H[0]); |
542 | 0 | mhd_PUT_32BIT_LE ((void *) (digest + 1 * mhd_MD5_BYTES_IN_WORD), \ |
543 | 0 | ctx->H[1]); |
544 | 0 | mhd_PUT_32BIT_LE ((void *) (digest + 2 * mhd_MD5_BYTES_IN_WORD), \ |
545 | 0 | ctx->H[2]); |
546 | 0 | mhd_PUT_32BIT_LE ((void *) (digest + 3 * mhd_MD5_BYTES_IN_WORD), \ |
547 | 0 | ctx->H[3]); |
548 | 0 | } |
549 | 0 | } |
550 | | |
551 | | /* Erase potentially sensitive data. */ |
552 | 0 | memset (ctx, 0, sizeof(struct mhd_Md5CtxInt)); |
553 | 0 | } |
554 | | |
555 | | |
556 | | mhd_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE |