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