GNU libmicrohttpd 0.9.77
Loading...
Searching...
No Matches
md5.c
Go to the documentation of this file.
1/*
2 * This code implements the MD5 message-digest algorithm.
3 * The algorithm is due to Ron Rivest. This code was
4 * written by Colin Plumb in 1993, no copyright is claimed.
5 * This code is in the public domain; do with it what you wish.
6 *
7 * Equivalent code is available from RSA Data Security, Inc.
8 * This code has been tested against that, and is equivalent,
9 * except that you don't need to include two pages of legalese
10 * with every copy.
11 *
12 * To compute the message digest of a chunk of bytes, declare an
13 * MD5Context structure, pass it to MHD_MD5Init, call MHD_MD5Update as
14 * needed on buffers full of bytes, and then call MHD_MD5Final, which
15 * will fill a supplied 16-byte array with the digest.
16 */
17
18/* Based on OpenBSD modifications.
19 * Optimized by Karlson2k (Evgeny Grin). */
20
21#include "md5.h"
22#include <string.h>
23#ifdef HAVE_MEMORY_H
24#include <memory.h>
25#endif /* HAVE_MEMORY_H */
26#include "mhd_bithelpers.h"
27#include "mhd_assert.h"
28
33#define MD5_BYTES_IN_WORD (32 / 8)
34
35
42void
43MHD_MD5Init (void *ctx_)
44{
45 struct MD5Context *ctx = ctx_;
46
47 mhd_assert (ctx != NULL);
48 ctx->count = 0;
49 ctx->state[0] = UINT32_C (0x67452301);
50 ctx->state[1] = UINT32_C (0xefcdab89);
51 ctx->state[2] = UINT32_C (0x98badcfe);
52 ctx->state[3] = UINT32_C (0x10325476);
53}
54
55
56static void
57MD5Transform (uint32_t state[4],
58 const uint8_t block[MD5_BLOCK_SIZE]);
59
60
66void
67MHD_MD5Final (void *ctx_,
68 uint8_t digest[MD5_DIGEST_SIZE])
69{
70 struct MD5Context *ctx = ctx_;
71 uint64_t count_bits;
72 size_t have_bytes;
73
74 mhd_assert (ctx != NULL);
75 mhd_assert (digest != NULL);
76
77 /* Convert count to 8 bytes in little endian order. */
78 have_bytes = (ctx->count) & (MD5_BLOCK_SIZE - 1);
79
80 /* Pad data */
81 /* Buffer always have space for one byte or more. */
82 ctx->buffer[have_bytes++] = 0x80; /* First padding byte is 0x80 */
83
84 if (MD5_BLOCK_SIZE - have_bytes < 8)
85 { /* Not enough space to put number of bits */
86 while (have_bytes < MD5_BLOCK_SIZE)
87 ctx->buffer[have_bytes++] = 0;
88 MD5Transform (ctx->state, ctx->buffer);
89 have_bytes = 0; /* Additional block */
90 }
91 /* Pad out to 56 */
92 memset (ctx->buffer + have_bytes, 0, MD5_BLOCK_SIZE - have_bytes - 8);
93
94 /* Put number of bits */
95 count_bits = ctx->count << 3;
96 _MHD_PUT_64BIT_LE_SAFE (ctx->buffer + 56, count_bits);
97 MD5Transform (ctx->state, ctx->buffer);
98
99 /* Put digest in LE mode */
100#ifndef _MHD_PUT_32BIT_LE_UNALIGNED
101 if (0 != ((uintptr_t) digest) % _MHD_UINT32_ALIGN)
102 {
103 uint32_t alig_dgst[MD5_DIGEST_SIZE / MD5_BYTES_IN_WORD];
104 _MHD_PUT_32BIT_LE (alig_dgst + 0, ctx->state[0]);
105 _MHD_PUT_32BIT_LE (alig_dgst + 1, ctx->state[1]);
106 _MHD_PUT_32BIT_LE (alig_dgst + 2, ctx->state[2]);
107 _MHD_PUT_32BIT_LE (alig_dgst + 3, ctx->state[3]);
108 /* Copy result to unaligned destination address */
109 memcpy (digest, alig_dgst, MD5_DIGEST_SIZE);
110 }
111 else
112#else /* _MHD_PUT_32BIT_LE_UNALIGNED */
113 if (1)
114#endif /* _MHD_PUT_32BIT_LE_UNALIGNED */
115 {
116 _MHD_PUT_32BIT_LE (digest, ctx->state[0]);
117 _MHD_PUT_32BIT_LE (digest + 4, ctx->state[1]);
118 _MHD_PUT_32BIT_LE (digest + 8, ctx->state[2]);
119 _MHD_PUT_32BIT_LE (digest + 12, ctx->state[3]);
120 }
121
122 /* Erase buffer */
123 memset (ctx, 0, sizeof(*ctx));
124}
125
126
127/* The four core functions - F1 is optimized somewhat */
128
129/* #define F1(x, y, z) (x & y | ~x & z) */
130#define F1(x, y, z) (z ^ (x & (y ^ z)))
131#define F2(x, y, z) F1 (z, x, y)
132#define F3(x, y, z) (x ^ y ^ z)
133#define F4(x, y, z) (y ^ (x | ~z))
134
135/* This is the central step in the MD5 algorithm. */
136#define MD5STEP(f, w, x, y, z, data, s) \
137 (w += f (x, y, z) + data, w = _MHD_ROTL32(w, s), w += x)
138
144static void
145MD5Transform (uint32_t state[4],
146 const uint8_t block[MD5_BLOCK_SIZE])
147{
148 uint32_t a, b, c, d;
149 uint32_t data_buf[MD5_BLOCK_SIZE / MD5_BYTES_IN_WORD];
150 const uint32_t *in;
151
152#if (_MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN) || \
153 ! defined(_MHD_GET_32BIT_LE_UNALIGNED)
154 if (0 != (((uintptr_t) block) % _MHD_UINT32_ALIGN))
155 {
156 /* Copy data to the aligned buffer */
157 memcpy (data_buf, block, MD5_BLOCK_SIZE);
158 in = data_buf;
159 }
160 else
161 in = (const uint32_t *) block;
162#endif /* _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN) || \
163 ! _MHD_GET_32BIT_LE_UNALIGNED */
164#if _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN
165 data_buf[0] = _MHD_GET_32BIT_LE (in + 0);
166 data_buf[1] = _MHD_GET_32BIT_LE (in + 1);
167 data_buf[2] = _MHD_GET_32BIT_LE (in + 2);
168 data_buf[3] = _MHD_GET_32BIT_LE (in + 3);
169 data_buf[4] = _MHD_GET_32BIT_LE (in + 4);
170 data_buf[5] = _MHD_GET_32BIT_LE (in + 5);
171 data_buf[6] = _MHD_GET_32BIT_LE (in + 6);
172 data_buf[7] = _MHD_GET_32BIT_LE (in + 7);
173 data_buf[8] = _MHD_GET_32BIT_LE (in + 8);
174 data_buf[9] = _MHD_GET_32BIT_LE (in + 9);
175 data_buf[10] = _MHD_GET_32BIT_LE (in + 10);
176 data_buf[11] = _MHD_GET_32BIT_LE (in + 11);
177 data_buf[12] = _MHD_GET_32BIT_LE (in + 12);
178 data_buf[13] = _MHD_GET_32BIT_LE (in + 13);
179 data_buf[14] = _MHD_GET_32BIT_LE (in + 14);
180 data_buf[15] = _MHD_GET_32BIT_LE (in + 15);
181 in = data_buf;
182#endif /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
183
184 a = state[0];
185 b = state[1];
186 c = state[2];
187 d = state[3];
188
189 MD5STEP (F1, a, b, c, d, in[0] + UINT32_C (0xd76aa478), 7);
190 MD5STEP (F1, d, a, b, c, in[1] + UINT32_C (0xe8c7b756), 12);
191 MD5STEP (F1, c, d, a, b, in[2] + UINT32_C (0x242070db), 17);
192 MD5STEP (F1, b, c, d, a, in[3] + UINT32_C (0xc1bdceee), 22);
193 MD5STEP (F1, a, b, c, d, in[4] + UINT32_C (0xf57c0faf), 7);
194 MD5STEP (F1, d, a, b, c, in[5] + UINT32_C (0x4787c62a), 12);
195 MD5STEP (F1, c, d, a, b, in[6] + UINT32_C (0xa8304613), 17);
196 MD5STEP (F1, b, c, d, a, in[7] + UINT32_C (0xfd469501), 22);
197 MD5STEP (F1, a, b, c, d, in[8] + UINT32_C (0x698098d8), 7);
198 MD5STEP (F1, d, a, b, c, in[9] + UINT32_C (0x8b44f7af), 12);
199 MD5STEP (F1, c, d, a, b, in[10] + UINT32_C (0xffff5bb1), 17);
200 MD5STEP (F1, b, c, d, a, in[11] + UINT32_C (0x895cd7be), 22);
201 MD5STEP (F1, a, b, c, d, in[12] + UINT32_C (0x6b901122), 7);
202 MD5STEP (F1, d, a, b, c, in[13] + UINT32_C (0xfd987193), 12);
203 MD5STEP (F1, c, d, a, b, in[14] + UINT32_C (0xa679438e), 17);
204 MD5STEP (F1, b, c, d, a, in[15] + UINT32_C (0x49b40821), 22);
205
206 MD5STEP (F2, a, b, c, d, in[1] + UINT32_C (0xf61e2562), 5);
207 MD5STEP (F2, d, a, b, c, in[6] + UINT32_C (0xc040b340), 9);
208 MD5STEP (F2, c, d, a, b, in[11] + UINT32_C (0x265e5a51), 14);
209 MD5STEP (F2, b, c, d, a, in[0] + UINT32_C (0xe9b6c7aa), 20);
210 MD5STEP (F2, a, b, c, d, in[5] + UINT32_C (0xd62f105d), 5);
211 MD5STEP (F2, d, a, b, c, in[10] + UINT32_C (0x02441453), 9);
212 MD5STEP (F2, c, d, a, b, in[15] + UINT32_C (0xd8a1e681), 14);
213 MD5STEP (F2, b, c, d, a, in[4] + UINT32_C (0xe7d3fbc8), 20);
214 MD5STEP (F2, a, b, c, d, in[9] + UINT32_C (0x21e1cde6), 5);
215 MD5STEP (F2, d, a, b, c, in[14] + UINT32_C (0xc33707d6), 9);
216 MD5STEP (F2, c, d, a, b, in[3] + UINT32_C (0xf4d50d87), 14);
217 MD5STEP (F2, b, c, d, a, in[8] + UINT32_C (0x455a14ed), 20);
218 MD5STEP (F2, a, b, c, d, in[13] + UINT32_C (0xa9e3e905), 5);
219 MD5STEP (F2, d, a, b, c, in[2] + UINT32_C (0xfcefa3f8), 9);
220 MD5STEP (F2, c, d, a, b, in[7] + UINT32_C (0x676f02d9), 14);
221 MD5STEP (F2, b, c, d, a, in[12] + UINT32_C (0x8d2a4c8a), 20);
222
223 MD5STEP (F3, a, b, c, d, in[5] + UINT32_C (0xfffa3942), 4);
224 MD5STEP (F3, d, a, b, c, in[8] + UINT32_C (0x8771f681), 11);
225 MD5STEP (F3, c, d, a, b, in[11] + UINT32_C (0x6d9d6122), 16);
226 MD5STEP (F3, b, c, d, a, in[14] + UINT32_C (0xfde5380c), 23);
227 MD5STEP (F3, a, b, c, d, in[1] + UINT32_C (0xa4beea44), 4);
228 MD5STEP (F3, d, a, b, c, in[4] + UINT32_C (0x4bdecfa9), 11);
229 MD5STEP (F3, c, d, a, b, in[7] + UINT32_C (0xf6bb4b60), 16);
230 MD5STEP (F3, b, c, d, a, in[10] + UINT32_C (0xbebfbc70), 23);
231 MD5STEP (F3, a, b, c, d, in[13] + UINT32_C (0x289b7ec6), 4);
232 MD5STEP (F3, d, a, b, c, in[0] + UINT32_C (0xeaa127fa), 11);
233 MD5STEP (F3, c, d, a, b, in[3] + UINT32_C (0xd4ef3085), 16);
234 MD5STEP (F3, b, c, d, a, in[6] + UINT32_C (0x04881d05), 23);
235 MD5STEP (F3, a, b, c, d, in[9] + UINT32_C (0xd9d4d039), 4);
236 MD5STEP (F3, d, a, b, c, in[12] + UINT32_C (0xe6db99e5), 11);
237 MD5STEP (F3, c, d, a, b, in[15] + UINT32_C (0x1fa27cf8), 16);
238 MD5STEP (F3, b, c, d, a, in[2] + UINT32_C (0xc4ac5665), 23);
239
240 MD5STEP (F4, a, b, c, d, in[0] + UINT32_C (0xf4292244), 6);
241 MD5STEP (F4, d, a, b, c, in[7] + UINT32_C (0x432aff97), 10);
242 MD5STEP (F4, c, d, a, b, in[14] + UINT32_C (0xab9423a7), 15);
243 MD5STEP (F4, b, c, d, a, in[5] + UINT32_C (0xfc93a039), 21);
244 MD5STEP (F4, a, b, c, d, in[12] + UINT32_C (0x655b59c3), 6);
245 MD5STEP (F4, d, a, b, c, in[3] + UINT32_C (0x8f0ccc92), 10);
246 MD5STEP (F4, c, d, a, b, in[10] + UINT32_C (0xffeff47d), 15);
247 MD5STEP (F4, b, c, d, a, in[1] + UINT32_C (0x85845dd1), 21);
248 MD5STEP (F4, a, b, c, d, in[8] + UINT32_C (0x6fa87e4f), 6);
249 MD5STEP (F4, d, a, b, c, in[15] + UINT32_C (0xfe2ce6e0), 10);
250 MD5STEP (F4, c, d, a, b, in[6] + UINT32_C (0xa3014314), 15);
251 MD5STEP (F4, b, c, d, a, in[13] + UINT32_C (0x4e0811a1), 21);
252 MD5STEP (F4, a, b, c, d, in[4] + UINT32_C (0xf7537e82), 6);
253 MD5STEP (F4, d, a, b, c, in[11] + UINT32_C (0xbd3af235), 10);
254 MD5STEP (F4, c, d, a, b, in[2] + UINT32_C (0x2ad7d2bb), 15);
255 MD5STEP (F4, b, c, d, a, in[9] + UINT32_C (0xeb86d391), 21);
256
257 state[0] += a;
258 state[1] += b;
259 state[2] += c;
260 state[3] += d;
261}
262
263
268void
269MHD_MD5Update (void *ctx_,
270 const uint8_t *input,
271 size_t len)
272{
273 struct MD5Context *ctx = ctx_;
274 size_t have, need;
275
276 mhd_assert (ctx != NULL);
277 mhd_assert ((ctx != NULL) || (len == 0));
278
279 /* Check how many bytes we already have and how many more we need. */
280 have = (size_t) ((ctx->count) & (MD5_BLOCK_SIZE - 1));
281 need = MD5_BLOCK_SIZE - have;
282
283 /* Update bytecount */
284 ctx->count += (uint64_t) len;
285
286 if (len >= need)
287 {
288 if (have != 0)
289 {
290 memcpy (ctx->buffer + have,
291 input,
292 need);
293 MD5Transform (ctx->state, ctx->buffer);
294 input += need;
295 len -= need;
296 have = 0;
297 }
298
299 /* Process data in MD5_BLOCK_SIZE-byte chunks. */
300 while (len >= MD5_BLOCK_SIZE)
301 {
302 MD5Transform (ctx->state,
303 (const unsigned char *) input);
304 input += MD5_BLOCK_SIZE;
305 len -= MD5_BLOCK_SIZE;
306 }
307 }
308
309 /* Handle any remaining bytes of data. */
310 if (0 != len)
311 memcpy (ctx->buffer + have,
312 input,
313 len);
314}
315
316
317/* end of md5.c */
#define mhd_assert(CHK)
Definition mhd_assert.h:39
#define NULL
#define MD5STEP(f, w, x, y, z, data, s)
Definition md5.c:136
void MHD_MD5Update(void *ctx_, const uint8_t *input, size_t len)
Definition md5.c:269
void MHD_MD5Final(void *ctx_, uint8_t digest[MD5_DIGEST_SIZE])
Definition md5.c:67
#define F1(x, y, z)
Definition md5.c:130
#define F4(x, y, z)
Definition md5.c:133
void MHD_MD5Init(void *ctx_)
Definition md5.c:43
#define F3(x, y, z)
Definition md5.c:132
static void MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_SIZE])
Definition md5.c:145
#define F2(x, y, z)
Definition md5.c:131
#define MD5_BYTES_IN_WORD
Definition md5.c:33
#define MD5_BLOCK_SIZE
Definition md5.h:27
#define MD5_DIGEST_SIZE
Definition md5.h:28
#define _MHD_UINT32_ALIGN
Definition mhd_align.h:85
macros for bits manipulations
#define _MHD_GET_32BIT_LE(addr)
_MHD_static_inline void _MHD_PUT_64BIT_LE_SAFE(void *dst, uint64_t value)
#define _MHD_PUT_32BIT_LE(addr, value32)
macros for mhd_assert()
uint32_t state[4]
Definition md5.h:33
uint64_t count
Definition md5.h:34
uint8_t buffer[MD5_BLOCK_SIZE]
Definition md5.h:35