Line data Source code
1 : /* md5.c
2 : ** MD5 hash function implemention, adapted for local use
3 : **
4 : ** This code is in the Public Domain
5 : */
6 :
7 : /*
8 : * This code implements the MD5 message-digest algorithm.
9 : * The algorithm is due to Ron Rivest. This code was
10 : * written by Colin Plumb in 1993, no copyright is claimed.
11 : * This code is in the public domain; do with it what you wish.
12 : *
13 : * Equivalent code is available from RSA Data Security, Inc.
14 : * This code has been tested against that, and is equivalent,
15 : * except that you don't need to include two pages of legalese
16 : * with every copy.
17 : *
18 : * To compute the message digest of a chunk of bytes, declare an
19 : * MD5Context structure, pass it to MD5Init, call MD5Update as
20 : * needed on buffers full of bytes, and then call MD5Final, which
21 : * will fill a supplied 16-byte array with the digest.
22 : */
23 :
24 : /** @file
25 : * MD5 hash.
26 : */
27 :
28 : #include <string.h> /* memcpy(), memset() */
29 : #include "md5.h"
30 :
31 : /* little-endian word access macros */
32 : #define GET_32BIT_LSB_FIRST(cp) \
33 : (((uint32_t)(unsigned char)(cp)[0]) | \
34 : ((uint32_t)(unsigned char)(cp)[1] << 8) | \
35 : ((uint32_t)(unsigned char)(cp)[2] << 16) | \
36 : ((uint32_t)(unsigned char)(cp)[3] << 24))
37 :
38 : #define PUT_32BIT_LSB_FIRST(cp, value) \
39 : do { \
40 : (cp)[0] = (value)&0xFF; \
41 : (cp)[1] = ((value) >> 8) & 0xFF; \
42 : (cp)[2] = ((value) >> 16) & 0xFF; \
43 : (cp)[3] = ((value) >> 24) & 0xFF; \
44 : } while (0)
45 :
46 : static void MD5Transform(uint32_t buf[4], const unsigned char inext[64]);
47 :
48 : /*
49 : * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
50 : * initialization constants.
51 : */
52 0 : void MD5Init(struct MD5Context *ctx)
53 : {
54 0 : ctx->buf[0] = 0x67452301;
55 0 : ctx->buf[1] = 0xefcdab89;
56 0 : ctx->buf[2] = 0x98badcfe;
57 0 : ctx->buf[3] = 0x10325476;
58 :
59 0 : ctx->bits[0] = 0;
60 0 : ctx->bits[1] = 0;
61 :
62 0 : memset(ctx->in, 0, 64);
63 0 : }
64 :
65 : /*
66 : * Update context to reflect the concatenation of another buffer full
67 : * of bytes.
68 : */
69 0 : void MD5Update(struct MD5Context *ctx, unsigned char const *buf, uint32_t len)
70 : {
71 0 : uint32_t t;
72 :
73 : /* Update bitcount */
74 :
75 0 : t = ctx->bits[0];
76 0 : if ((ctx->bits[0] = (t + ((uint32_t)len << 3)) & 0xffffffff) < t)
77 0 : ctx->bits[1]++; /* Carry from low to high */
78 0 : ctx->bits[1] += len >> 29;
79 :
80 0 : t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
81 :
82 : /* Handle any leading odd-sized chunks */
83 :
84 0 : if (t) {
85 0 : unsigned char *p = ctx->in + t;
86 :
87 0 : t = 64 - t;
88 0 : if (len < t) {
89 0 : memcpy(p, buf, len);
90 0 : return;
91 : }
92 0 : memcpy(p, buf, t);
93 0 : MD5Transform(ctx->buf, ctx->in);
94 0 : buf += t;
95 0 : len -= t;
96 : }
97 : /* Process data in 64-byte chunks */
98 :
99 0 : while (len >= 64) {
100 0 : memcpy(ctx->in, buf, 64);
101 0 : MD5Transform(ctx->buf, ctx->in);
102 0 : buf += 64;
103 0 : len -= 64;
104 : }
105 :
106 : /* Handle any remaining bytes of data. */
107 :
108 0 : memcpy(ctx->in, buf, len);
109 : }
110 :
111 : /*
112 : * Final wrapup - pad to 64-byte boundary with the bit pattern
113 : * 1 0* (64-bit count of bits processed, MSB-first)
114 : */
115 0 : void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
116 : {
117 0 : unsigned count;
118 0 : unsigned char *p;
119 :
120 : /* Compute number of bytes mod 64 */
121 0 : count = (ctx->bits[0] >> 3) & 0x3F;
122 :
123 : /* Set the first char of padding to 0x80. This is safe since there is
124 : always at least one byte free */
125 0 : p = ctx->in + count;
126 0 : *p++ = 0x80;
127 :
128 : /* Bytes of padding needed to make 64 bytes */
129 0 : count = 64 - 1 - count;
130 :
131 : /* Pad out to 56 mod 64 */
132 0 : if (count < 8) {
133 : /* Two lots of padding: Pad the first block to 64 bytes */
134 0 : memset(p, 0, count);
135 0 : MD5Transform(ctx->buf, ctx->in);
136 :
137 : /* Now fill the next block with 56 bytes */
138 0 : memset(ctx->in, 0, 56);
139 : } else {
140 : /* Pad block to 56 bytes */
141 0 : memset(p, 0, count - 8);
142 : }
143 :
144 : /* Append length in bits and transform */
145 0 : PUT_32BIT_LSB_FIRST(ctx->in + 56, ctx->bits[0]);
146 0 : PUT_32BIT_LSB_FIRST(ctx->in + 60, ctx->bits[1]);
147 :
148 0 : MD5Transform(ctx->buf, ctx->in);
149 0 : PUT_32BIT_LSB_FIRST(digest, ctx->buf[0]);
150 0 : PUT_32BIT_LSB_FIRST(digest + 4, ctx->buf[1]);
151 0 : PUT_32BIT_LSB_FIRST(digest + 8, ctx->buf[2]);
152 0 : PUT_32BIT_LSB_FIRST(digest + 12, ctx->buf[3]);
153 0 : memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
154 0 : }
155 :
156 : /* The four core functions - F1 is optimized somewhat */
157 :
158 : /* #define F1(x, y, z) (x & y | ~x & z) */
159 : #define F1(x, y, z) (z ^ (x & (y ^ z)))
160 : #define F2(x, y, z) F1(z, x, y)
161 : #define F3(x, y, z) (x ^ y ^ z)
162 : #define F4(x, y, z) (y ^ (x | ~z))
163 :
164 : /* This is the central step in the MD5 algorithm. */
165 : /* debugging version: */
166 : /*
167 : #define MD5STEP(f, w, x, y, z, data, s) \
168 : printf("MD5STEP: w: %x x: %x y: %x z: %x data: %x s: %x\n", \
169 : w, x, y, z, data, s); \
170 : printf("f(x,y,z) = %x\n", f(x,y,z)+data); \
171 : ( w += f(x, y, z) + data, printf(" - w: %x ", w), \
172 : w = w<<s | w>>(32-s), printf(" - w: %x\n", w), w += x )
173 : */
174 : #define MD5STEP(f, w, x, y, z, data, s) \
175 : (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
176 :
177 : /*
178 : * The core of the MD5 algorithm, this alters an existing MD5 hash to
179 : * reflect the addition of 16 longwords of new data. MD5Update blocks
180 : * the data and converts bytes into longwords for this routine.
181 : */
182 0 : static void MD5Transform(uint32_t buf[4], const unsigned char inext[64])
183 : {
184 0 : register uint32_t a, b, c, d, i;
185 0 : uint32_t in[16];
186 :
187 0 : for (i = 0; i < 16; i++)
188 0 : in[i] = GET_32BIT_LSB_FIRST(inext + 4 * i);
189 :
190 0 : a = buf[0];
191 0 : b = buf[1];
192 0 : c = buf[2];
193 0 : d = buf[3];
194 :
195 0 : MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
196 :
197 0 : MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
198 0 : MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
199 0 : MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
200 0 : MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
201 0 : MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
202 0 : MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
203 0 : MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
204 0 : MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
205 0 : MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
206 0 : MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
207 0 : MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
208 0 : MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
209 0 : MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
210 0 : MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
211 0 : MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
212 :
213 0 : MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
214 0 : MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
215 0 : MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
216 0 : MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
217 0 : MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
218 0 : MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
219 0 : MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
220 0 : MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
221 0 : MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
222 0 : MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
223 0 : MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
224 0 : MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
225 0 : MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
226 0 : MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
227 0 : MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
228 0 : MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
229 :
230 0 : MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
231 0 : MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
232 0 : MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
233 0 : MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
234 0 : MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
235 0 : MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
236 0 : MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
237 0 : MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
238 0 : MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
239 0 : MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
240 0 : MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
241 0 : MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
242 0 : MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
243 0 : MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
244 0 : MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
245 0 : MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
246 :
247 0 : MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
248 0 : MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
249 0 : MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
250 0 : MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
251 0 : MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
252 0 : MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
253 0 : MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
254 0 : MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
255 0 : MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
256 0 : MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
257 0 : MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
258 0 : MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
259 0 : MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
260 0 : MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
261 0 : MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
262 0 : MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
263 :
264 0 : buf[0] += a;
265 0 : buf[1] += b;
266 0 : buf[2] += c;
267 0 : buf[3] += d;
268 0 : }
|