GNU libmicrohttpd  0.9.75
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 */
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
#define NULL
Definition: reason_phrase.c:30
#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()
Definition: md5.h:32
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