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