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
42
void
43
MHD_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
56
static
void
57
MD5Transform
(
uint32_t
state
[4],
58
const
uint8_t
block
[
MD5_BLOCK_SIZE
]);
59
60
66
void
67
MHD_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
144
static
void
145
MD5Transform
(
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
268
void
269
MHD_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 */
MHD_HTTP_OK
#define MHD_HTTP_OK
Definition
microhttpd.h:356
mhd_assert
#define mhd_assert(CHK)
Definition
mhd_assert.h:39
NULL
#define NULL
Definition
reason_phrase.c:30
MD5STEP
#define MD5STEP(f, w, x, y, z, data, s)
Definition
md5.c:136
MHD_MD5Update
void MHD_MD5Update(void *ctx_, const uint8_t *input, size_t len)
Definition
md5.c:269
MHD_MD5Final
void MHD_MD5Final(void *ctx_, uint8_t digest[MD5_DIGEST_SIZE])
Definition
md5.c:67
F1
#define F1(x, y, z)
Definition
md5.c:130
F4
#define F4(x, y, z)
Definition
md5.c:133
MHD_MD5Init
void MHD_MD5Init(void *ctx_)
Definition
md5.c:43
F3
#define F3(x, y, z)
Definition
md5.c:132
MD5Transform
static void MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_SIZE])
Definition
md5.c:145
F2
#define F2(x, y, z)
Definition
md5.c:131
MD5_BYTES_IN_WORD
#define MD5_BYTES_IN_WORD
Definition
md5.c:33
md5.h
MD5_BLOCK_SIZE
#define MD5_BLOCK_SIZE
Definition
md5.h:27
MD5_DIGEST_SIZE
#define MD5_DIGEST_SIZE
Definition
md5.h:28
_MHD_UINT32_ALIGN
#define _MHD_UINT32_ALIGN
Definition
mhd_align.h:85
mhd_bithelpers.h
macros for bits manipulations
_MHD_GET_32BIT_LE
#define _MHD_GET_32BIT_LE(addr)
Definition
mhd_bithelpers.h:181
_MHD_PUT_64BIT_LE_SAFE
_MHD_static_inline void _MHD_PUT_64BIT_LE_SAFE(void *dst, uint64_t value)
Definition
mhd_bithelpers.h:136
_MHD_PUT_32BIT_LE
#define _MHD_PUT_32BIT_LE(addr, value32)
Definition
mhd_bithelpers.h:159
mhd_assert.h
macros for mhd_assert()
MD5Context
Definition
md5.h:32
MD5Context::state
uint32_t state[4]
Definition
md5.h:33
MD5Context::count
uint64_t count
Definition
md5.h:34
MD5Context::buffer
uint8_t buffer[MD5_BLOCK_SIZE]
Definition
md5.h:35
src
microhttpd
md5.c
Generated by
1.9.8