GNU libmicrohttpd 1.0.2
Loading...
Searching...
No Matches
md5.c
Go to the documentation of this file.
1/*
2 This file is part of GNU libmicrohttpd
3 Copyright (C) 2022-2023 Evgeny Grin (Karlson2k)
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
26#include "md5.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
40void
41MHD_MD5_init (struct Md5Ctx *ctx)
42{
43 /* Initial hash values, see RFC 1321, Clause 3.3 (step 3). */
44 /* Note: values specified in RFC by bytes and should be loaded in
45 little-endian mode, therefore hash values here are initialised with
46 original bytes used in little-endian order. */
47 ctx->H[0] = UINT32_C (0x67452301);
48 ctx->H[1] = UINT32_C (0xefcdab89);
49 ctx->H[2] = UINT32_C (0x98badcfe);
50 ctx->H[3] = UINT32_C (0x10325476);
51
52 /* Initialise the number of bytes. */
53 ctx->count = 0;
54}
55
56
58
65static void
67 const void *M)
68{
69 /* Working variables,
70 See RFC 1321, Clause 3.4 (step 4). */
71 uint32_t A = H[0];
72 uint32_t B = H[1];
73 uint32_t C = H[2];
74 uint32_t D = H[3];
75
76 /* The data buffer. See RFC 1321, Clause 3.4 (step 4). */
77 uint32_t X[16];
78
79#ifndef _MHD_GET_32BIT_LE_UNALIGNED
80 if (0 != (((uintptr_t) M) % _MHD_UINT32_ALIGN))
81 { /* The input data is unaligned. */
82 /* Copy the unaligned input data to the aligned buffer. */
83 memcpy (X, M, sizeof(X));
84 /* The X[] buffer itself will be used as the source of the data,
85 * but the data will be reloaded in correct bytes order on
86 * the next steps. */
87 M = (const void *) X;
88 }
89#endif /* _MHD_GET_32BIT_LE_UNALIGNED */
90
91 /* Four auxiliary functions, see RFC 1321, Clause 3.4 (step 4). */
92 /* Some optimisations used. */
93/* #define F_FUNC(x,y,z) (((x)&(y)) | ((~(x))&(z))) */ /* Original version */
94#define F_FUNC(x,y,z) ((((y) ^ (z)) & (x)) ^ (z))
95/* #define G_FUNC_1(x,y,z) (((x)&(z)) | ((y)&(~(z)))) */ /* Original version */
96/* #define G_FUNC_2(x,y,z) UINT32_C(0) */ /* Original version */
97#ifndef MHD_FAVOR_SMALL_CODE
98# define G_FUNC_1(x,y,z) ((~(z)) & (y))
99# define G_FUNC_2(x,y,z) ((z) & (x))
100#else /* MHD_FAVOR_SMALL_CODE */
101# define G_FUNC_1(x,y,z) ((((x) ^ (y)) & (z)) ^ (y))
102# define G_FUNC_2(x,y,z) UINT32_C(0)
103#endif /* MHD_FAVOR_SMALL_CODE */
104#define H_FUNC(x,y,z) ((x) ^ (y) ^ (z)) /* Original version */
105/* #define I_FUNC(x,y,z) ((y) ^ ((x) | (~(z)))) */ /* Original version */
106#define I_FUNC(x,y,z) (((~(z)) | (x)) ^ (y))
107
108 /* One step of round 1 of MD5 computation, see RFC 1321, Clause 3.4 (step 4).
109 The original function was modified to use X[k] and T[i] as
110 direct inputs. */
111#define MD5STEP_R1(va,vb,vc,vd,vX,vs,vT) do { \
112 (va) += (vX) + (vT); \
113 (va) += F_FUNC((vb),(vc),(vd)); \
114 (va) = _MHD_ROTL32((va),(vs)) + (vb); } while (0)
115
116 /* Get value of X(k) from input data buffer.
117 See RFC 1321 Clause 3.4 (step 4). */
118#define GET_X_FROM_DATA(buf,t) \
119 _MHD_GET_32BIT_LE (((const uint32_t*) (buf)) + (t))
120
121 /* One step of round 2 of MD5 computation, see RFC 1321, Clause 3.4 (step 4).
122 The original function was modified to use X[k] and T[i] as
123 direct inputs. */
124#define MD5STEP_R2(va,vb,vc,vd,vX,vs,vT) do { \
125 (va) += (vX) + (vT); \
126 (va) += G_FUNC_1((vb),(vc),(vd)); \
127 (va) += G_FUNC_2((vb),(vc),(vd)); \
128 (va) = _MHD_ROTL32((va),(vs)) + (vb); } while (0)
129
130 /* One step of round 3 of MD5 computation, see RFC 1321, Clause 3.4 (step 4).
131 The original function was modified to use X[k] and T[i] as
132 direct inputs. */
133#define MD5STEP_R3(va,vb,vc,vd,vX,vs,vT) do { \
134 (va) += (vX) + (vT); \
135 (va) += H_FUNC((vb),(vc),(vd)); \
136 (va) = _MHD_ROTL32((va),(vs)) + (vb); } while (0)
137
138 /* One step of round 4 of MD5 computation, see RFC 1321, Clause 3.4 (step 4).
139 The original function was modified to use X[k] and T[i] as
140 direct inputs. */
141#define MD5STEP_R4(va,vb,vc,vd,vX,vs,vT) do { \
142 (va) += (vX) + (vT); \
143 (va) += I_FUNC((vb),(vc),(vd)); \
144 (va) = _MHD_ROTL32((va),(vs)) + (vb); } while (0)
145
146#if ! defined(MHD_FAVOR_SMALL_CODE)
147
148 /* Round 1. */
149
150#if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
151 if ((const void *) X == M)
152 {
153 /* The input data is already in the data buffer X[] in correct bytes
154 order. */
155 MD5STEP_R1 (A, B, C, D, X[0], 7, UINT32_C (0xd76aa478));
156 MD5STEP_R1 (D, A, B, C, X[1], 12, UINT32_C (0xe8c7b756));
157 MD5STEP_R1 (C, D, A, B, X[2], 17, UINT32_C (0x242070db));
158 MD5STEP_R1 (B, C, D, A, X[3], 22, UINT32_C (0xc1bdceee));
159
160 MD5STEP_R1 (A, B, C, D, X[4], 7, UINT32_C (0xf57c0faf));
161 MD5STEP_R1 (D, A, B, C, X[5], 12, UINT32_C (0x4787c62a));
162 MD5STEP_R1 (C, D, A, B, X[6], 17, UINT32_C (0xa8304613));
163 MD5STEP_R1 (B, C, D, A, X[7], 22, UINT32_C (0xfd469501));
164
165 MD5STEP_R1 (A, B, C, D, X[8], 7, UINT32_C (0x698098d8));
166 MD5STEP_R1 (D, A, B, C, X[9], 12, UINT32_C (0x8b44f7af));
167 MD5STEP_R1 (C, D, A, B, X[10], 17, UINT32_C (0xffff5bb1));
168 MD5STEP_R1 (B, C, D, A, X[11], 22, UINT32_C (0x895cd7be));
169
170 MD5STEP_R1 (A, B, C, D, X[12], 7, UINT32_C (0x6b901122));
171 MD5STEP_R1 (D, A, B, C, X[13], 12, UINT32_C (0xfd987193));
172 MD5STEP_R1 (C, D, A, B, X[14], 17, UINT32_C (0xa679438e));
173 MD5STEP_R1 (B, C, D, A, X[15], 22, UINT32_C (0x49b40821));
174 }
175 else /* Combined with the next 'if' */
176#endif /* _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN */
177 if (1)
178 {
179 /* The input data is loaded in correct (little-endian) format before
180 calculations on each step. */
181 MD5STEP_R1 (A, B, C, D, X[0] = GET_X_FROM_DATA (M, 0), 7, \
182 UINT32_C (0xd76aa478));
183 MD5STEP_R1 (D, A, B, C, X[1] = GET_X_FROM_DATA (M, 1), 12, \
184 UINT32_C (0xe8c7b756));
185 MD5STEP_R1 (C, D, A, B, X[2] = GET_X_FROM_DATA (M, 2), 17, \
186 UINT32_C (0x242070db));
187 MD5STEP_R1 (B, C, D, A, X[3] = GET_X_FROM_DATA (M, 3), 22, \
188 UINT32_C (0xc1bdceee));
189
190 MD5STEP_R1 (A, B, C, D, X[4] = GET_X_FROM_DATA (M, 4), 7, \
191 UINT32_C (0xf57c0faf));
192 MD5STEP_R1 (D, A, B, C, X[5] = GET_X_FROM_DATA (M, 5), 12, \
193 UINT32_C (0x4787c62a));
194 MD5STEP_R1 (C, D, A, B, X[6] = GET_X_FROM_DATA (M, 6), 17, \
195 UINT32_C (0xa8304613));
196 MD5STEP_R1 (B, C, D, A, X[7] = GET_X_FROM_DATA (M, 7), 22, \
197 UINT32_C (0xfd469501));
198
199 MD5STEP_R1 (A, B, C, D, X[8] = GET_X_FROM_DATA (M, 8), 7, \
200 UINT32_C (0x698098d8));
201 MD5STEP_R1 (D, A, B, C, X[9] = GET_X_FROM_DATA (M, 9), 12, \
202 UINT32_C (0x8b44f7af));
203 MD5STEP_R1 (C, D, A, B, X[10] = GET_X_FROM_DATA (M, 10), 17, \
204 UINT32_C (0xffff5bb1));
205 MD5STEP_R1 (B, C, D, A, X[11] = GET_X_FROM_DATA (M, 11), 22, \
206 UINT32_C (0x895cd7be));
207
208 MD5STEP_R1 (A, B, C, D, X[12] = GET_X_FROM_DATA (M, 12), 7, \
209 UINT32_C (0x6b901122));
210 MD5STEP_R1 (D, A, B, C, X[13] = GET_X_FROM_DATA (M, 13), 12, \
211 UINT32_C (0xfd987193));
212 MD5STEP_R1 (C, D, A, B, X[14] = GET_X_FROM_DATA (M, 14), 17, \
213 UINT32_C (0xa679438e));
214 MD5STEP_R1 (B, C, D, A, X[15] = GET_X_FROM_DATA (M, 15), 22, \
215 UINT32_C (0x49b40821));
216 }
217
218 /* Round 2. */
219
220 MD5STEP_R2 (A, B, C, D, X[1], 5, UINT32_C (0xf61e2562));
221 MD5STEP_R2 (D, A, B, C, X[6], 9, UINT32_C (0xc040b340));
222 MD5STEP_R2 (C, D, A, B, X[11], 14, UINT32_C (0x265e5a51));
223 MD5STEP_R2 (B, C, D, A, X[0], 20, UINT32_C (0xe9b6c7aa));
224
225 MD5STEP_R2 (A, B, C, D, X[5], 5, UINT32_C (0xd62f105d));
226 MD5STEP_R2 (D, A, B, C, X[10], 9, UINT32_C (0x02441453));
227 MD5STEP_R2 (C, D, A, B, X[15], 14, UINT32_C (0xd8a1e681));
228 MD5STEP_R2 (B, C, D, A, X[4], 20, UINT32_C (0xe7d3fbc8));
229
230 MD5STEP_R2 (A, B, C, D, X[9], 5, UINT32_C (0x21e1cde6));
231 MD5STEP_R2 (D, A, B, C, X[14], 9, UINT32_C (0xc33707d6));
232 MD5STEP_R2 (C, D, A, B, X[3], 14, UINT32_C (0xf4d50d87));
233 MD5STEP_R2 (B, C, D, A, X[8], 20, UINT32_C (0x455a14ed));
234
235 MD5STEP_R2 (A, B, C, D, X[13], 5, UINT32_C (0xa9e3e905));
236 MD5STEP_R2 (D, A, B, C, X[2], 9, UINT32_C (0xfcefa3f8));
237 MD5STEP_R2 (C, D, A, B, X[7], 14, UINT32_C (0x676f02d9));
238 MD5STEP_R2 (B, C, D, A, X[12], 20, UINT32_C (0x8d2a4c8a));
239
240 /* Round 3. */
241
242 MD5STEP_R3 (A, B, C, D, X[5], 4, UINT32_C (0xfffa3942));
243 MD5STEP_R3 (D, A, B, C, X[8], 11, UINT32_C (0x8771f681));
244 MD5STEP_R3 (C, D, A, B, X[11], 16, UINT32_C (0x6d9d6122));
245 MD5STEP_R3 (B, C, D, A, X[14], 23, UINT32_C (0xfde5380c));
246
247 MD5STEP_R3 (A, B, C, D, X[1], 4, UINT32_C (0xa4beea44));
248 MD5STEP_R3 (D, A, B, C, X[4], 11, UINT32_C (0x4bdecfa9));
249 MD5STEP_R3 (C, D, A, B, X[7], 16, UINT32_C (0xf6bb4b60));
250 MD5STEP_R3 (B, C, D, A, X[10], 23, UINT32_C (0xbebfbc70));
251
252 MD5STEP_R3 (A, B, C, D, X[13], 4, UINT32_C (0x289b7ec6));
253 MD5STEP_R3 (D, A, B, C, X[0], 11, UINT32_C (0xeaa127fa));
254 MD5STEP_R3 (C, D, A, B, X[3], 16, UINT32_C (0xd4ef3085));
255 MD5STEP_R3 (B, C, D, A, X[6], 23, UINT32_C (0x04881d05));
256
257 MD5STEP_R3 (A, B, C, D, X[9], 4, UINT32_C (0xd9d4d039));
258 MD5STEP_R3 (D, A, B, C, X[12], 11, UINT32_C (0xe6db99e5));
259 MD5STEP_R3 (C, D, A, B, X[15], 16, UINT32_C (0x1fa27cf8));
260 MD5STEP_R3 (B, C, D, A, X[2], 23, UINT32_C (0xc4ac5665));
261
262 /* Round 4. */
263
264 MD5STEP_R4 (A, B, C, D, X[0], 6, UINT32_C (0xf4292244));
265 MD5STEP_R4 (D, A, B, C, X[7], 10, UINT32_C (0x432aff97));
266 MD5STEP_R4 (C, D, A, B, X[14], 15, UINT32_C (0xab9423a7));
267 MD5STEP_R4 (B, C, D, A, X[5], 21, UINT32_C (0xfc93a039));
268
269 MD5STEP_R4 (A, B, C, D, X[12], 6, UINT32_C (0x655b59c3));
270 MD5STEP_R4 (D, A, B, C, X[3], 10, UINT32_C (0x8f0ccc92));
271 MD5STEP_R4 (C, D, A, B, X[10], 15, UINT32_C (0xffeff47d));
272 MD5STEP_R4 (B, C, D, A, X[1], 21, UINT32_C (0x85845dd1));
273
274 MD5STEP_R4 (A, B, C, D, X[8], 6, UINT32_C (0x6fa87e4f));
275 MD5STEP_R4 (D, A, B, C, X[15], 10, UINT32_C (0xfe2ce6e0));
276 MD5STEP_R4 (C, D, A, B, X[6], 15, UINT32_C (0xa3014314));
277 MD5STEP_R4 (B, C, D, A, X[13], 21, UINT32_C (0x4e0811a1));
278
279 MD5STEP_R4 (A, B, C, D, X[4], 6, UINT32_C (0xf7537e82));
280 MD5STEP_R4 (D, A, B, C, X[11], 10, UINT32_C (0xbd3af235));
281 MD5STEP_R4 (C, D, A, B, X[2], 15, UINT32_C (0x2ad7d2bb));
282 MD5STEP_R4 (B, C, D, A, X[9], 21, UINT32_C (0xeb86d391));
283#else /* MHD_FAVOR_SMALL_CODE */
284 if (1)
285 {
286 static const uint32_t T[64] =
287 { UINT32_C (0xd76aa478), UINT32_C (0xe8c7b756), UINT32_C (0x242070db),
288 UINT32_C (0xc1bdceee), UINT32_C (0xf57c0faf), UINT32_C (0x4787c62a),
289 UINT32_C (0xa8304613), UINT32_C (0xfd469501), UINT32_C (0x698098d8),
290 UINT32_C (0x8b44f7af), UINT32_C (0xffff5bb1), UINT32_C (0x895cd7be),
291 UINT32_C (0x6b901122), UINT32_C (0xfd987193), UINT32_C (0xa679438e),
292 UINT32_C (0x49b40821), UINT32_C (0xf61e2562), UINT32_C (0xc040b340),
293 UINT32_C (0x265e5a51), UINT32_C (0xe9b6c7aa), UINT32_C (0xd62f105d),
294 UINT32_C (0x02441453), UINT32_C (0xd8a1e681), UINT32_C (0xe7d3fbc8),
295 UINT32_C (0x21e1cde6), UINT32_C (0xc33707d6), UINT32_C (0xf4d50d87),
296 UINT32_C (0x455a14ed), UINT32_C (0xa9e3e905), UINT32_C (0xfcefa3f8),
297 UINT32_C (0x676f02d9), UINT32_C (0x8d2a4c8a), UINT32_C (0xfffa3942),
298 UINT32_C (0x8771f681), UINT32_C (0x6d9d6122), UINT32_C (0xfde5380c),
299 UINT32_C (0xa4beea44), UINT32_C (0x4bdecfa9), UINT32_C (0xf6bb4b60),
300 UINT32_C (0xbebfbc70), UINT32_C (0x289b7ec6), UINT32_C (0xeaa127fa),
301 UINT32_C (0xd4ef3085), UINT32_C (0x04881d05), UINT32_C (0xd9d4d039),
302 UINT32_C (0xe6db99e5), UINT32_C (0x1fa27cf8), UINT32_C (0xc4ac5665),
303 UINT32_C (0xf4292244), UINT32_C (0x432aff97), UINT32_C (0xab9423a7),
304 UINT32_C (0xfc93a039), UINT32_C (0x655b59c3), UINT32_C (0x8f0ccc92),
305 UINT32_C (0xffeff47d), UINT32_C (0x85845dd1), UINT32_C (0x6fa87e4f),
306 UINT32_C (0xfe2ce6e0), UINT32_C (0xa3014314), UINT32_C (0x4e0811a1),
307 UINT32_C (0xf7537e82), UINT32_C (0xbd3af235), UINT32_C (0x2ad7d2bb),
308 UINT32_C (0xeb86d391) };
309 unsigned int i;
311 /* Round 1. */
312
313 i = 0;
314 do
315 {
316 /* The input data is loaded in correct (little-endian) format before
317 calculations on each step. */
318 MD5STEP_R1 (A, B, C, D, X[i] = GET_X_FROM_DATA (M, i), 7, T[i]);
319 ++i;
320 MD5STEP_R1 (D, A, B, C, X[i] = GET_X_FROM_DATA (M, i), 12, T[i]);
321 ++i;
322 MD5STEP_R1 (C, D, A, B, X[i] = GET_X_FROM_DATA (M, i), 17, T[i]);
323 ++i;
324 MD5STEP_R1 (B, C, D, A, X[i] = GET_X_FROM_DATA (M, i), 22, T[i]);
325 ++i;
326 } while (i < 16);
327
328 /* Round 2. */
329
330 do
331 {
332 const unsigned int idx_add = i;
333 MD5STEP_R2 (A, B, C, D, X[(1U + idx_add) & 15U], 5, T[i]);
334 ++i;
335 MD5STEP_R2 (D, A, B, C, X[(6U + idx_add) & 15U], 9, T[i]);
336 ++i;
337 MD5STEP_R2 (C, D, A, B, X[(11U + idx_add) & 15U], 14, T[i]);
338 ++i;
339 MD5STEP_R2 (B, C, D, A, X[(0U + idx_add) & 15U], 20, T[i]);
340 ++i;
341 } while (i < 32);
342
343 /* Round 3. */
344
345 do
346 {
347 const unsigned int idx_add = i;
348 MD5STEP_R3 (A, B, C, D, X[(5U + 64U - idx_add) & 15U], 4, T[i]);
349 ++i;
350 MD5STEP_R3 (D, A, B, C, X[(8U + 64U - idx_add) & 15U], 11, T[i]);
351 ++i;
352 MD5STEP_R3 (C, D, A, B, X[(11U + 64U - idx_add) & 15U], 16, T[i]);
353 ++i;
354 MD5STEP_R3 (B, C, D, A, X[(14U + 64U - idx_add) & 15U], 23, T[i]);
355 ++i;
356 } while (i < 48);
357
358 /* Round 4. */
359
360 do
361 {
362 const unsigned int idx_add = i;
363 MD5STEP_R4 (A, B, C, D, X[(0U + 64U - idx_add) & 15U], 6, T[i]);
364 ++i;
365 MD5STEP_R4 (D, A, B, C, X[(7U + 64U - idx_add) & 15U], 10, T[i]);
366 ++i;
367 MD5STEP_R4 (C, D, A, B, X[(14U + 64U - idx_add) & 15U], 15, T[i]);
368 ++i;
369 MD5STEP_R4 (B, C, D, A, X[(5U + 64U - idx_add) & 15U], 21, T[i]);
370 ++i;
371 } while (i < 64);
372 }
373#endif /* MHD_FAVOR_SMALL_CODE */
374
375 /* Finally increment and store working variables.
376 See RFC 1321, end of Clause 3.4 (step 4). */
377
378 H[0] += A;
379 H[1] += B;
380 H[2] += C;
381 H[3] += D;
382}
383
384
392void
394 const uint8_t *data,
395 size_t length)
396{
397 unsigned int bytes_have;
399 mhd_assert ((data != NULL) || (length == 0));
400
401#ifndef MHD_FAVOR_SMALL_CODE
402 if (0 == length)
403 return; /* Shortcut, do nothing */
404#endif /* MHD_FAVOR_SMALL_CODE */
405
406 /* Note: (count & (MD5_BLOCK_SIZE-1))
407 equals (count % MD5_BLOCK_SIZE) for this block size. */
408 bytes_have = (unsigned int) (ctx->count & (MD5_BLOCK_SIZE - 1));
409 ctx->count += length;
410
411 if (0 != bytes_have)
412 {
413 unsigned int bytes_left = MD5_BLOCK_SIZE - bytes_have;
414 if (length >= bytes_left)
415 { /* Combine new data with data in the buffer and
416 process the full block. */
417 memcpy (((uint8_t *) ctx->buffer) + bytes_have,
418 data,
419 bytes_left);
420 data += bytes_left;
421 length -= bytes_left;
422 md5_transform (ctx->H, ctx->buffer);
423 bytes_have = 0;
424 }
425 }
426
427 while (MD5_BLOCK_SIZE <= length)
428 { /* Process any full blocks of new data directly,
429 without copying to the buffer. */
430 md5_transform (ctx->H, data);
432 length -= MD5_BLOCK_SIZE;
433 }
434
435 if (0 != length)
436 { /* Copy incomplete block of new data (if any)
437 to the buffer. */
438 memcpy (((uint8_t *) ctx->buffer) + bytes_have, data, length);
439 }
440}
441
442
447#define MD5_SIZE_OF_LEN_ADD_BITS 64
448
452#define MD5_SIZE_OF_LEN_ADD (MD5_SIZE_OF_LEN_ADD_BITS / 8)
453
460void
462 uint8_t digest[MD5_DIGEST_SIZE])
463{
464 uint64_t num_bits;
465 unsigned int bytes_have;
467 /* Memorise the number of processed bits.
468 The padding and other data added here during the postprocessing must
469 not change the amount of hashed data. */
470 num_bits = ctx->count << 3;
471
472 /* Note: (count & (MD5_BLOCK_SIZE-1))
473 equals (count % MD5_BLOCK_SIZE) for this block size. */
474 bytes_have = (unsigned int) (ctx->count & (MD5_BLOCK_SIZE - 1));
475
476 /* Input data must be padded with a single bit "1", then with zeros and
477 the finally the length of data in bits must be added as the final bytes
478 of the last block.
479 See RFC 1321, Clauses 3.1 and 3.2 (steps 1 and 2). */
480 /* Data is always processed in form of bytes (not by individual bits),
481 therefore position of the first padding bit in byte is always
482 predefined (0x80). */
483 /* Buffer always have space for one byte at least (as full buffers are
484 processed immediately). */
485 ((uint8_t *) ctx->buffer)[bytes_have++] = 0x80;
486
487 if (MD5_BLOCK_SIZE - bytes_have < MD5_SIZE_OF_LEN_ADD)
488 { /* No space in the current block to put the total length of message.
489 Pad the current block with zeros and process it. */
490 if (bytes_have < MD5_BLOCK_SIZE)
491 memset (((uint8_t *) ctx->buffer) + bytes_have, 0,
492 MD5_BLOCK_SIZE - bytes_have);
493 /* Process the full block. */
494 md5_transform (ctx->H, ctx->buffer);
495 /* Start the new block. */
496 bytes_have = 0;
497 }
498
499 /* Pad the rest of the buffer with zeros. */
500 memset (((uint8_t *) ctx->buffer) + bytes_have, 0,
501 MD5_BLOCK_SIZE - MD5_SIZE_OF_LEN_ADD - bytes_have);
502 /* Put the number of bits in processed data as little-endian value.
503 See RFC 1321, clauses 2 and 3.2 (step 2). */
505 num_bits);
506 /* Process the full final block. */
507 md5_transform (ctx->H, ctx->buffer);
508
509 /* Put in LE mode the hash as the final digest.
510 See RFC 1321, clauses 2 and 3.5 (step 5). */
511#ifndef _MHD_PUT_32BIT_LE_UNALIGNED
512 if (1
513#ifndef MHD_FAVOR_SMALL_CODE
514 && (0 != ((uintptr_t) digest) % _MHD_UINT32_ALIGN)
515#endif /* MHD_FAVOR_SMALL_CODE */
516 )
517 {
518 /* If storing of the final result requires aligned address and
519 the destination address is not aligned or compact code is used,
520 store the final digest in aligned temporary buffer first, then
521 copy it to the destination. */
522 uint32_t alig_dgst[MD5_DIGEST_SIZE_WORDS];
523 _MHD_PUT_32BIT_LE (alig_dgst + 0, ctx->H[0]);
524 _MHD_PUT_32BIT_LE (alig_dgst + 1, ctx->H[1]);
525 _MHD_PUT_32BIT_LE (alig_dgst + 2, ctx->H[2]);
526 _MHD_PUT_32BIT_LE (alig_dgst + 3, ctx->H[3]);
527 /* Copy result to the unaligned destination address. */
528 memcpy (digest, alig_dgst, MD5_DIGEST_SIZE);
529 }
530#ifndef MHD_FAVOR_SMALL_CODE
531 else /* Combined with the next 'if' */
532#endif /* MHD_FAVOR_SMALL_CODE */
533#endif /* ! _MHD_PUT_32BIT_LE_UNALIGNED */
534#if ! defined(MHD_FAVOR_SMALL_CODE) || defined(_MHD_PUT_32BIT_LE_UNALIGNED)
535 if (1)
536 {
537 /* Use cast to (void*) here to mute compiler alignment warnings.
538 * Compilers are not smart enough to see that alignment has been checked. */
539 _MHD_PUT_32BIT_LE ((void *) (digest + 0 * MD5_BYTES_IN_WORD), ctx->H[0]);
540 _MHD_PUT_32BIT_LE ((void *) (digest + 1 * MD5_BYTES_IN_WORD), ctx->H[1]);
541 _MHD_PUT_32BIT_LE ((void *) (digest + 2 * MD5_BYTES_IN_WORD), ctx->H[2]);
542 _MHD_PUT_32BIT_LE ((void *) (digest + 3 * MD5_BYTES_IN_WORD), ctx->H[3]);
543 }
544#endif /* ! MHD_FAVOR_SMALL_CODE || _MHD_PUT_32BIT_LE_UNALIGNED */
545
546 /* Erase potentially sensitive data. */
547 memset (ctx, 0, sizeof(struct Md5Ctx));
548}
549
550
#define MD5STEP_R3(va, vb, vc, vd, vX, vs, vT)
void MHD_MD5_finish(struct Md5Ctx *ctx, uint8_t digest[MD5_DIGEST_SIZE])
Definition md5.c:461
#define GET_X_FROM_DATA(buf, t)
static MHD_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE_ void md5_transform(uint32_t H[MD5_HASH_SIZE_WORDS], const void *M)
Definition md5.c:66
#define MD5STEP_R2(va, vb, vc, vd, vX, vs, vT)
void MHD_MD5_update(struct Md5Ctx *ctx, const uint8_t *data, size_t length)
Definition md5.c:393
#define MD5_SIZE_OF_LEN_ADD
Definition md5.c:452
#define MD5STEP_R4(va, vb, vc, vd, vX, vs, vT)
void MHD_MD5_init(struct Md5Ctx *ctx)
Definition md5.c:41
#define MD5STEP_R1(va, vb, vc, vd, vX, vs, vT)
Calculation of MD5 digest.
#define MD5_DIGEST_SIZE_WORDS
Definition md5.h:55
#define MD5_BLOCK_SIZE
Definition md5.h:76
#define MD5_BLOCK_SIZE_WORDS
Definition md5.h:81
#define MD5_HASH_SIZE_WORDS
Definition md5.h:49
#define MD5_DIGEST_SIZE
Definition md5.h:61
#define MD5_BYTES_IN_WORD
Definition md5.h:43
#define _MHD_UINT32_ALIGN
Definition mhd_align.h:85
macros for mhd_assert()
#define mhd_assert(ignore)
Definition mhd_assert.h:45
macros for bits manipulations
_MHD_static_inline void _MHD_PUT_64BIT_LE_SAFE(void *dst, uint64_t value)
#define _MHD_PUT_32BIT_LE(addr, value32)
#define NULL
#define MHD_DATA_TRUNCATION_RUNTIME_CHECK_DISABLE_
#define MHD_DATA_TRUNCATION_RUNTIME_CHECK_RESTORE_
void * data
Definition md5.h:88
uint64_t count
Definition md5.h:91
uint32_t buffer[MD5_BLOCK_SIZE_WORDS]
Definition md5.h:90
uint32_t H[MD5_HASH_SIZE_WORDS]
Definition md5.h:89