Root/
Source at commit 1322 created 12 years 8 months ago. By meklort, Add doxygen to utils folder | |
---|---|
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 MD5Init, call MD5Update as␊ |
14 | * needed on buffers full of bytes, and then call MD5Final, which␊ |
15 | * will fill a supplied 16-byte array with the digest.␊ |
16 | *␊ |
17 | * Changed so as no longer to depend on Colin Plumb's `usual.h' header␊ |
18 | * definitions; now uses stuff from dpkg's config.h.␊ |
19 | * - Ian Jackson <ian@chiark.greenend.org.uk>.␊ |
20 | * Still in the public domain.␊ |
21 | */␊ |
22 | ␊ |
23 | #include <string.h>␉␉/* for memcpy() */␊ |
24 | #include <sys/types.h>␉␉/* for stupid systems */␊ |
25 | ␊ |
26 | #include "md5.h"␊ |
27 | ␊ |
28 | void␊ |
29 | MD5Transform(UWORD32 buf[4], UWORD32 const in[16]);␊ |
30 | ␊ |
31 | int g_bigEndian = 0;␊ |
32 | int g_endianessDetected = 0;␊ |
33 | ␊ |
34 | static void ␊ |
35 | detectEndianess()␊ |
36 | {␊ |
37 | int nl = 0x12345678;␊ |
38 | short ns = 0x1234;␊ |
39 | ␊ |
40 | unsigned char *p = (unsigned char *)(&nl); ␊ |
41 | unsigned char *sp = (unsigned char *)(&ns);␊ |
42 | ␊ |
43 | if (g_endianessDetected) return;␊ |
44 | if ( p[0] == 0x12 && p[1] == 0x34 && p[2] == 0x56 && p[3] == 0x78 )␊ |
45 | {␊ |
46 | g_bigEndian = 1;␊ |
47 | }␊ |
48 | else if ( p[0] == 0x78 && p[1] == 0x56 && p[2] == 0x34 && p[3] == 0x12 )␊ |
49 | {␊ |
50 | g_bigEndian = 0;␊ |
51 | }␊ |
52 | else␊ |
53 | {␊ |
54 | g_bigEndian = *sp != 0x12;␊ |
55 | }␊ |
56 | ␊ |
57 | g_endianessDetected=1;␊ |
58 | }␊ |
59 | ␊ |
60 | static void␊ |
61 | byteSwap(UWORD32 *buf, unsigned words)␊ |
62 | {␊ |
63 | md5byte *p;␊ |
64 | ␊ |
65 | if (!g_bigEndian) return;␊ |
66 | ␊ |
67 | ␉p = (md5byte *)buf;␊ |
68 | ␊ |
69 | ␉do {␊ |
70 | ␉␉*buf++ = (UWORD32)((unsigned)p[3] << 8 | p[2]) << 16 |␊ |
71 | ␉␉␉((unsigned)p[1] << 8 | p[0]);␊ |
72 | ␉␉p += 4;␊ |
73 | ␉} while (--words);␊ |
74 | }␊ |
75 | ␊ |
76 | /*␊ |
77 | * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious␊ |
78 | * initialization constants.␊ |
79 | */␊ |
80 | void␊ |
81 | MD5Init(struct MD5Context *ctx)␊ |
82 | {␊ |
83 | detectEndianess();␊ |
84 | ␊ |
85 | ␉ctx->buf[0] = 0x67452301;␊ |
86 | ␉ctx->buf[1] = 0xefcdab89;␊ |
87 | ␉ctx->buf[2] = 0x98badcfe;␊ |
88 | ␉ctx->buf[3] = 0x10325476;␊ |
89 | ␊ |
90 | ␉ctx->bytes[0] = 0;␊ |
91 | ␉ctx->bytes[1] = 0;␊ |
92 | }␊ |
93 | ␊ |
94 | /*␊ |
95 | * Update context to reflect the concatenation of another buffer full␊ |
96 | * of bytes.␊ |
97 | */␊ |
98 | void␊ |
99 | MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len)␊ |
100 | {␊ |
101 | ␉UWORD32 t;␊ |
102 | ␊ |
103 | ␉/* Update byte count */␊ |
104 | ␊ |
105 | ␉t = ctx->bytes[0];␊ |
106 | ␉if ((ctx->bytes[0] = t + len) < t)␊ |
107 | ␉␉ctx->bytes[1]++;␉/* Carry from low to high */␊ |
108 | ␊ |
109 | ␉t = 64 - (t & 0x3f);␉/* Space available in ctx->in (at least 1) */␊ |
110 | ␉if (t > len) {␊ |
111 | ␉␉memcpy((md5byte *)ctx->in + 64 - t, buf, len);␊ |
112 | ␉␉return;␊ |
113 | ␉}␊ |
114 | ␉/* First chunk is an odd size */␊ |
115 | ␉memcpy((md5byte *)ctx->in + 64 - t, buf, t);␊ |
116 | ␉byteSwap(ctx->in, 16);␊ |
117 | ␉MD5Transform(ctx->buf, ctx->in);␊ |
118 | ␉buf += t;␊ |
119 | ␉len -= t;␊ |
120 | ␊ |
121 | ␉/* Process data in 64-byte chunks */␊ |
122 | ␉while (len >= 64) {␊ |
123 | ␉␉memcpy(ctx->in, buf, 64);␊ |
124 | ␉␉byteSwap(ctx->in, 16);␊ |
125 | ␉␉MD5Transform(ctx->buf, ctx->in);␊ |
126 | ␉␉buf += 64;␊ |
127 | ␉␉len -= 64;␊ |
128 | ␉}␊ |
129 | ␊ |
130 | ␉/* Handle any remaining bytes of data. */␊ |
131 | ␉memcpy(ctx->in, buf, len);␊ |
132 | }␊ |
133 | ␊ |
134 | /*␊ |
135 | * Final wrapup - pad to 64-byte boundary with the bit pattern ␊ |
136 | * 1 0* (64-bit count of bits processed, MSB-first)␊ |
137 | */␊ |
138 | void␊ |
139 | MD5Final(md5byte digest[16], struct MD5Context *ctx)␊ |
140 | {␊ |
141 | ␉int count = ctx->bytes[0] & 0x3f;␉/* Number of bytes in ctx->in */␊ |
142 | ␉md5byte *p = (md5byte *)ctx->in + count;␊ |
143 | ␊ |
144 | ␉/* Set the first char of padding to 0x80. There is always room. */␊ |
145 | ␉*p++ = 0x80;␊ |
146 | ␊ |
147 | ␉/* Bytes of padding needed to make 56 bytes (-8..55) */␊ |
148 | ␉count = 56 - 1 - count;␊ |
149 | ␊ |
150 | ␉if (count < 0) {␉/* Padding forces an extra block */␊ |
151 | ␉␉memset(p, 0, count + 8);␊ |
152 | ␉␉byteSwap(ctx->in, 16);␊ |
153 | ␉␉MD5Transform(ctx->buf, ctx->in);␊ |
154 | ␉␉p = (md5byte *)ctx->in;␊ |
155 | ␉␉count = 56;␊ |
156 | ␉}␊ |
157 | ␉memset(p, 0, count);␊ |
158 | ␉byteSwap(ctx->in, 14);␊ |
159 | ␊ |
160 | ␉/* Append length in bits and transform */␊ |
161 | ␉ctx->in[14] = ctx->bytes[0] << 3;␊ |
162 | ␉ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;␊ |
163 | ␉MD5Transform(ctx->buf, ctx->in);␊ |
164 | ␊ |
165 | ␉byteSwap(ctx->buf, 4);␊ |
166 | ␉memcpy(digest, ctx->buf, 16);␊ |
167 | ␉memset(ctx, 0, sizeof(ctx));␉/* In case it's sensitive */␊ |
168 | }␊ |
169 | ␊ |
170 | #ifndef ASM_MD5␊ |
171 | ␊ |
172 | /* The four core functions - F1 is optimized somewhat */␊ |
173 | ␊ |
174 | /* #define F1(x, y, z) (x & y | ~x & z) */␊ |
175 | #define F1(x, y, z) (z ^ (x & (y ^ z)))␊ |
176 | #define F2(x, y, z) F1(z, x, y)␊ |
177 | #define F3(x, y, z) (x ^ y ^ z)␊ |
178 | #define F4(x, y, z) (y ^ (x | ~z))␊ |
179 | ␊ |
180 | /* This is the central step in the MD5 algorithm. */␊ |
181 | #define MD5STEP(f,w,x,y,z,in,s) \␊ |
182 | ␉ (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)␊ |
183 | ␊ |
184 | /*␊ |
185 | * The core of the MD5 algorithm, this alters an existing MD5 hash to␊ |
186 | * reflect the addition of 16 longwords of new data. MD5Update blocks␊ |
187 | * the data and converts bytes into longwords for this routine.␊ |
188 | */␊ |
189 | void␊ |
190 | MD5Transform(UWORD32 buf[4], UWORD32 const in[16])␊ |
191 | {␊ |
192 | ␉register UWORD32 a, b, c, d;␊ |
193 | ␊ |
194 | ␉a = buf[0];␊ |
195 | ␉b = buf[1];␊ |
196 | ␉c = buf[2];␊ |
197 | ␉d = buf[3];␊ |
198 | ␊ |
199 | ␉MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);␊ |
200 | ␉MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);␊ |
201 | ␉MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);␊ |
202 | ␉MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);␊ |
203 | ␉MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);␊ |
204 | ␉MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);␊ |
205 | ␉MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);␊ |
206 | ␉MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);␊ |
207 | ␉MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);␊ |
208 | ␉MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);␊ |
209 | ␉MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);␊ |
210 | ␉MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);␊ |
211 | ␉MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);␊ |
212 | ␉MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);␊ |
213 | ␉MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);␊ |
214 | ␉MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);␊ |
215 | ␊ |
216 | ␉MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);␊ |
217 | ␉MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);␊ |
218 | ␉MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);␊ |
219 | ␉MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);␊ |
220 | ␉MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);␊ |
221 | ␉MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);␊ |
222 | ␉MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);␊ |
223 | ␉MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);␊ |
224 | ␉MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);␊ |
225 | ␉MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);␊ |
226 | ␉MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);␊ |
227 | ␉MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);␊ |
228 | ␉MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);␊ |
229 | ␉MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);␊ |
230 | ␉MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);␊ |
231 | ␉MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);␊ |
232 | ␊ |
233 | ␉MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);␊ |
234 | ␉MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);␊ |
235 | ␉MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);␊ |
236 | ␉MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);␊ |
237 | ␉MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);␊ |
238 | ␉MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);␊ |
239 | ␉MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);␊ |
240 | ␉MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);␊ |
241 | ␉MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);␊ |
242 | ␉MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);␊ |
243 | ␉MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);␊ |
244 | ␉MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);␊ |
245 | ␉MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);␊ |
246 | ␉MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);␊ |
247 | ␉MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);␊ |
248 | ␉MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);␊ |
249 | ␊ |
250 | ␉MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);␊ |
251 | ␉MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);␊ |
252 | ␉MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);␊ |
253 | ␉MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);␊ |
254 | ␉MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);␊ |
255 | ␉MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);␊ |
256 | ␉MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);␊ |
257 | ␉MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);␊ |
258 | ␉MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);␊ |
259 | ␉MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);␊ |
260 | ␉MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);␊ |
261 | ␉MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);␊ |
262 | ␉MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);␊ |
263 | ␉MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);␊ |
264 | ␉MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);␊ |
265 | ␉MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);␊ |
266 | ␊ |
267 | ␉buf[0] += a;␊ |
268 | ␉buf[1] += b;␊ |
269 | ␉buf[2] += c;␊ |
270 | ␉buf[3] += d;␊ |
271 | }␊ |
272 | ␊ |
273 | #endif␊ |
274 | ␊ |
275 | void MD5Buffer (const unsigned char *buf,unsigned int len,unsigned char sig[16])␊ |
276 | {␊ |
277 | struct MD5Context md5;␊ |
278 | MD5Init(&md5);␊ |
279 | MD5Update(&md5,buf,len);␊ |
280 | MD5Final(sig,&md5);␊ |
281 | }␊ |
282 | ␊ |
283 | #define HEX_STRING "0123456789abcdef" /* to convert to hex */␊ |
284 | ␊ |
285 | void MD5SigToString(unsigned char signature[16],char *str,int len)␊ |
286 | {␊ |
287 | unsigned char *sig_p;␊ |
288 | char *str_p, *max_p;␊ |
289 | unsigned int high, low;␊ |
290 | ␊ |
291 | str_p = str;␊ |
292 | max_p = str + len;␊ |
293 | ␊ |
294 | for (sig_p = (unsigned char *)signature;␊ |
295 | sig_p < (unsigned char *)signature + 16;␊ |
296 | sig_p++)␊ |
297 | {␊ |
298 | high = *sig_p / 16;␊ |
299 | low = *sig_p % 16;␊ |
300 | /* account for 2 chars */␊ |
301 | if (str_p + 1 >= max_p) {␊ |
302 | break;␊ |
303 | }␊ |
304 | *str_p++ = HEX_STRING[high];␊ |
305 | *str_p++ = HEX_STRING[low];␊ |
306 | }␊ |
307 | /* account for 2 chars */␊ |
308 | if (str_p < max_p) {␊ |
309 | *str_p++ = '\0';␊ |
310 | }␊ |
311 | }␊ |
312 | ␊ |
313 | ␊ |
314 |