Rev 47 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
47 | dimkam | 1 | /** |
2 | * support MD5 for PPPoE CHAP mode |
||
3 | * |
||
4 | * taken from RFC-1321/Appendix A.3 |
||
5 | * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm |
||
6 | */ |
||
7 | |||
8 | /* |
||
9 | ******************************************************************************** |
||
10 | File Include Section |
||
11 | ******************************************************************************** |
||
12 | */ |
||
13 | |||
14 | #include <string.h> |
||
15 | #include "md5.h" |
||
16 | |||
17 | // Constants for Transform routine. |
||
18 | #define S11 7 |
||
19 | #define S12 12 |
||
20 | #define S13 17 |
||
21 | #define S14 22 |
||
22 | #define S21 5 |
||
23 | #define S22 9 |
||
24 | #define S23 14 |
||
25 | #define S24 20 |
||
26 | #define S31 4 |
||
27 | #define S32 11 |
||
28 | #define S33 16 |
||
29 | #define S34 23 |
||
30 | #define S41 6 |
||
31 | #define S42 10 |
||
32 | #define S43 15 |
||
33 | #define S44 21 |
||
34 | |||
35 | void md5_transform (uint32[4], uint8 [64]); |
||
36 | void md5_encode (uint8 *, uint32 *, uint32); |
||
37 | void md5_decode (uint32 *, uint8 *, uint32); |
||
38 | |||
39 | uint8 padding[64] = { |
||
40 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||
41 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||
42 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||
43 | 0, 0 |
||
44 | }; |
||
45 | |||
46 | // F, G, H and I are basic md5 functions. |
||
47 | #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) |
||
48 | #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) |
||
49 | #define H(x, y, z) ((x) ^ (y) ^ (z)) |
||
50 | #define I(x, y, z) ((y) ^ ((x) | (~z))) |
||
51 | |||
52 | // ROTATE_LEFT rotates x left n bits. |
||
53 | #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) |
||
54 | |||
55 | |||
56 | uint32 FF(uint32 a, uint32 b, uint32 c, uint32 d, uint32 x, uint32 s, uint32 ac) |
||
57 | { |
||
58 | a += F (b, c, d) + x + (uint32)(ac); |
||
59 | a = ROTATE_LEFT (a, s); |
||
60 | a += b; |
||
61 | return a; |
||
62 | } |
||
63 | uint32 GG(uint32 a, uint32 b, uint32 c, uint32 d, uint32 x, uint32 s, uint32 ac) |
||
64 | { |
||
65 | a += G (b, c, d) + x + (uint32)(ac); |
||
66 | a = ROTATE_LEFT (a, s); |
||
67 | a += b; |
||
68 | return a; |
||
69 | } |
||
70 | |||
71 | uint32 HH(uint32 a, uint32 b, uint32 c, uint32 d, uint32 x, uint32 s, uint32 ac) |
||
72 | { |
||
73 | a += H (b, c, d) + x + (uint32)(ac); |
||
74 | a = ROTATE_LEFT (a, s); |
||
75 | a += b; |
||
76 | return a; |
||
77 | } |
||
78 | |||
79 | uint32 II(uint32 a, uint32 b, uint32 c, uint32 d, uint32 x, uint32 s, uint32 ac) |
||
80 | { |
||
81 | a += I (b, c, d) + x + (uint32)(ac); |
||
82 | a = ROTATE_LEFT (a, s); |
||
83 | a += b; |
||
84 | return a; |
||
85 | } |
||
86 | |||
87 | // md5 initialization. Begins an md5 operation, writing a new context. |
||
88 | void md5_init(md5_ctx *context) |
||
89 | { |
||
90 | context->count[0] = context->count[1] = 0; |
||
91 | |||
92 | // Load magic initialization constants. |
||
93 | context->state[0] = 0x67452301; |
||
94 | context->state[1] = 0xefcdab89; |
||
95 | context->state[2] = 0x98badcfe; |
||
96 | context->state[3] = 0x10325476; |
||
97 | } |
||
98 | |||
99 | // md5 block update operation. Continues an md5 message-digest operation, |
||
100 | // processing another message block, and updating the context. |
||
101 | void md5_update(md5_ctx * context, uint8 *input, uint32 inputLen) |
||
102 | { |
||
103 | uint32 i, index, partLen; |
||
104 | |||
105 | // Compute number of bytes mod 64 |
||
106 | index = (uint32)((context->count[0] >> 3) & 0x3F); |
||
107 | |||
108 | // Update number of bits |
||
109 | if ((context->count[0] += ((uint32)inputLen << 3)) < ((uint32)inputLen << 3)) |
||
110 | context->count[1]++; |
||
111 | context->count[1] += ((uint32)inputLen >> 29); |
||
112 | |||
113 | partLen = 64 - index; |
||
114 | |||
115 | // md5_Transform as many times as possible. |
||
116 | if (inputLen >= partLen) |
||
117 | { |
||
118 | memcpy(&context->buffer[index], input, partLen); |
||
119 | md5_transform(context->state, context->buffer); |
||
120 | |||
121 | for (i = partLen; i + 63 < inputLen; i += 64) |
||
122 | md5_transform(context->state, &input[i]); |
||
123 | index = 0; |
||
124 | } |
||
125 | else |
||
126 | i = 0; |
||
127 | |||
128 | // Buffer remaining input |
||
129 | memcpy(&context->buffer[index], &input[i], inputLen - i); |
||
130 | } |
||
131 | |||
132 | // md5 finalization. Ends an md5 message-digest operation, writing the |
||
133 | // message digest and zeroizing the context. |
||
134 | void md5_final(uint8 digest[16], md5_ctx *context) |
||
135 | { |
||
136 | uint8 bits[8]; |
||
137 | uint32 index, padLen; |
||
138 | |||
139 | // Save number of bits |
||
140 | md5_encode(bits, context->count, 8); |
||
141 | |||
142 | // Pad out to 56 mod 64. |
||
143 | index = (uint32)((context->count[0] >> 3) & 0x3f); |
||
144 | padLen = (index < 56) ? (56 - index) : (120 - index); |
||
145 | md5_update(context, padding, padLen); |
||
146 | |||
147 | // Append length (before padding) |
||
148 | md5_update(context, bits, 8); |
||
149 | // Store state in digest |
||
150 | md5_encode(digest, context->state, 16); |
||
151 | |||
152 | // Zeroize sensitive information. |
||
153 | memset((void*)context,0,sizeof(*context)); |
||
154 | } |
||
155 | |||
156 | // md5 basic transformation. Transforms state based on block. |
||
157 | void md5_transform(uint32 state[4], uint8 block[64]) |
||
158 | { |
||
159 | uint32 a = state[0]; |
||
160 | uint32 b = state[1]; |
||
161 | uint32 c = state[2]; |
||
162 | uint32 d = state[3]; |
||
163 | uint32 x[16]; |
||
164 | |||
165 | md5_decode(x, block, 64); |
||
166 | |||
167 | // Round 1 |
||
168 | a = FF(a, b, c, d, x[0], S11, 0xd76aa478); // 1 |
||
169 | d = FF(d, a, b, c, x[1], S12, 0xe8c7b756); // 2 |
||
170 | c = FF(c, d, a, b, x[2], S13, 0x242070db); // 3 |
||
171 | b = FF(b, c, d, a, x[3], S14, 0xc1bdceee); // 4 |
||
172 | a = FF(a, b, c, d, x[4], S11, 0xf57c0faf); // 5 |
||
173 | d = FF(d, a, b, c, x[5], S12, 0x4787c62a); // 6 |
||
174 | c = FF(c, d, a, b, x[6], S13, 0xa8304613); // 7 |
||
175 | b = FF(b, c, d, a, x[7], S14, 0xfd469501); // 8 |
||
176 | a = FF(a, b, c, d, x[8], S11, 0x698098d8); // 9 |
||
177 | d = FF(d, a, b, c, x[9], S12, 0x8b44f7af); // 10 |
||
178 | c = FF(c, d, a, b, x[10], S13, 0xffff5bb1); // 11 |
||
179 | b = FF(b, c, d, a, x[11], S14, 0x895cd7be); // 12 |
||
180 | a = FF(a, b, c, d, x[12], S11, 0x6b901122); // 13 |
||
181 | d = FF(d, a, b, c, x[13], S12, 0xfd987193); // 14 |
||
182 | c = FF(c, d, a, b, x[14], S13, 0xa679438e); // 15 |
||
183 | b = FF(b, c, d, a, x[15], S14, 0x49b40821); // 16 |
||
184 | |||
185 | // Round 2 |
||
186 | a = GG(a, b, c, d, x[1], S21, 0xf61e2562); // 17 |
||
187 | d = GG(d, a, b, c, x[6], S22, 0xc040b340); // 18 |
||
188 | c = GG(c, d, a, b, x[11], S23, 0x265e5a51); // 19 |
||
189 | b = GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); // 20 |
||
190 | a = GG(a, b, c, d, x[5], S21, 0xd62f105d); // 21 |
||
191 | d = GG(d, a, b, c, x[10], S22, 0x2441453); // 22 |
||
192 | c = GG(c, d, a, b, x[15], S23, 0xd8a1e681); // 23 |
||
193 | b = GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); // 24 |
||
194 | a = GG(a, b, c, d, x[9], S21, 0x21e1cde6); // 25 |
||
195 | d = GG(d, a, b, c, x[14], S22, 0xc33707d6); // 26 |
||
196 | c = GG(c, d, a, b, x[3], S23, 0xf4d50d87); // 27 |
||
197 | b = GG(b, c, d, a, x[8], S24, 0x455a14ed); // 28 |
||
198 | a = GG(a, b, c, d, x[13], S21, 0xa9e3e905); // 29 |
||
199 | d = GG(d, a, b, c, x[2], S22, 0xfcefa3f8); // 30 |
||
200 | c = GG(c, d, a, b, x[7], S23, 0x676f02d9); // 31 |
||
201 | b = GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); // 32 |
||
202 | |||
203 | // Round 3 |
||
204 | a = HH(a, b, c, d, x[5], S31, 0xfffa3942); // 33 |
||
205 | d = HH(d, a, b, c, x[8], S32, 0x8771f681); // 34 |
||
206 | c = HH(c, d, a, b, x[11], S33, 0x6d9d6122); // 35 |
||
207 | b = HH(b, c, d, a, x[14], S34, 0xfde5380c); // 36 |
||
208 | a = HH(a, b, c, d, x[1], S31, 0xa4beea44); // 37 |
||
209 | d = HH(d, a, b, c, x[4], S32, 0x4bdecfa9); // 38 |
||
210 | c = HH(c, d, a, b, x[7], S33, 0xf6bb4b60); // 39 |
||
211 | b = HH(b, c, d, a, x[10], S34, 0xbebfbc70); // 40 |
||
212 | a = HH(a, b, c, d, x[13], S31, 0x289b7ec6); // 41 |
||
213 | d = HH(d, a, b, c, x[0], S32, 0xeaa127fa); // 42 |
||
214 | c = HH(c, d, a, b, x[3], S33, 0xd4ef3085); // 43 |
||
215 | b = HH(b, c, d, a, x[6], S34, 0x4881d05); // 44 |
||
216 | a = HH(a, b, c, d, x[9], S31, 0xd9d4d039); // 45 |
||
217 | d = HH(d, a, b, c, x[12], S32, 0xe6db99e5); // 46 |
||
218 | c = HH(c, d, a, b, x[15], S33, 0x1fa27cf8); // 47 |
||
219 | b = HH(b, c, d, a, x[2], S34, 0xc4ac5665); // 48 |
||
220 | |||
221 | // Round 4 |
||
222 | a = II(a, b, c, d, x[0], S41, 0xf4292244); // 49 |
||
223 | d = II(d, a, b, c, x[7], S42, 0x432aff97); // 50 |
||
224 | c = II(c, d, a, b, x[14], S43, 0xab9423a7); // 51 |
||
225 | b = II(b, c, d, a, x[5], S44, 0xfc93a039); // 52 |
||
226 | a = II(a, b, c, d, x[12], S41, 0x655b59c3); // 53 |
||
227 | d = II(d, a, b, c, x[3], S42, 0x8f0ccc92); // 54 |
||
228 | c = II(c, d, a, b, x[10], S43, 0xffeff47d); // 55 |
||
229 | b = II(b, c, d, a, x[1], S44, 0x85845dd1); // 56 |
||
230 | a = II(a, b, c, d, x[8], S41, 0x6fa87e4f); // 57 |
||
231 | d = II(d, a, b, c, x[15], S42, 0xfe2ce6e0); // 58 |
||
232 | c = II(c, d, a, b, x[6], S43, 0xa3014314); // 59 |
||
233 | b = II(b, c, d, a, x[13], S44, 0x4e0811a1); // 60 |
||
234 | a = II(a, b, c, d, x[4], S41, 0xf7537e82); // 61 |
||
235 | d = II(d, a, b, c, x[11], S42, 0xbd3af235); // 62 |
||
236 | c = II(c, d, a, b, x[2], S43, 0x2ad7d2bb); // 63 |
||
237 | b = II(b, c, d, a, x[9], S44, 0xeb86d391); // 64 |
||
238 | |||
239 | state[0] += a; |
||
240 | state[1] += b; |
||
241 | state[2] += c; |
||
242 | state[3] += d; |
||
243 | |||
244 | // Zeroize sensitive information. |
||
245 | memset(&x,0,sizeof(x)); |
||
246 | } |
||
247 | |||
248 | // Encodes input (uint32) into output (uint8). Assumes len is a |
||
249 | // multiple of 4. |
||
250 | void md5_encode(uint8 *output, uint32 *input, uint32 len) |
||
251 | { |
||
252 | uint32 i, j; |
||
253 | |||
254 | for (i = 0, j = 0; j < len; i++, j += 4) |
||
255 | { |
||
256 | output[j] = (uint8)(input[i] & 0xff); |
||
257 | output[j + 1] = (uint8)((input[i] >> 8) & 0xff); |
||
258 | output[j + 2] = (uint8)((input[i] >> 16) & 0xff); |
||
259 | output[j + 3] = (uint8)((input[i] >> 24) & 0xff); |
||
260 | } |
||
261 | } |
||
262 | |||
263 | // Decodes input (uint8) into output (uint32). Assumes len is a |
||
264 | // multiple of 4. |
||
265 | void md5_decode(uint32 *output, uint8 *input, uint32 len) |
||
266 | { |
||
267 | uint32 i, j; |
||
268 | for (i = 0, j = 0; j < len; i++, j += 4) |
||
269 | output[i] = ((uint32) input[j]) | (((uint32) input[j + 1]) << 8) | |
||
270 | (((uint32)input[j + 2]) << 16) | (((uint32)input[j + 3]) << 24); |
||
271 | } |
||
272 |