1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
24 * *
25 *************************************************************************/
26
27 #include "../crypt_md5.h"
28
29 #ifdef MD5_SUPPORT
30 /*
31 * F, G, H and I are basic MD5 functions.
32 */
33 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
34 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
35 #define H(x, y, z) ((x) ^ (y) ^ (z))
36 #define I(x, y, z) ((y) ^ ((x) | (~z)))
37
38 #define ROTL(x,n,w) ((x << n) | (x >> (w - n)))
39 #define ROTL32(x,n) ROTL(x,n,32) /* 32 bits word */
40
41 #define ROUND1(a, b, c, d, x, s, ac) { \
42 (a) += F((b),(c),(d)) + (x) + (u32)(ac); \
43 (a) = ROTL32((a),(s)); \
44 (a) += (b); \
45 }
46 #define ROUND2(a, b, c, d, x, s, ac) { \
47 (a) += G((b),(c),(d)) + (x) + (u32)(ac); \
48 (a) = ROTL32((a),(s)); \
49 (a) += (b); \
50 }
51 #define ROUND3(a, b, c, d, x, s, ac) { \
52 (a) += H((b),(c),(d)) + (x) + (u32)(ac); \
53 (a) = ROTL32((a),(s)); \
54 (a) += (b); \
55 }
56 #define ROUND4(a, b, c, d, x, s, ac) { \
57 (a) += I((b),(c),(d)) + (x) + (u32)(ac); \
58 (a) = ROTL32((a),(s)); \
59 (a) += (b); \
60 }
61 static const u32 MD5_DefaultHashValue[4] = {
62 0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL
63 };
64 #endif /* MD5_SUPPORT */
65
66 #ifdef MD5_SUPPORT
67 /*
68 ========================================================================
69 Routine Description:
70 Initial Md5_CTX_STRUC
71
72 Arguments:
73 pMD5_CTX Pointer to Md5_CTX_STRUC
74
75 Return Value:
76 None
77
78 Note:
79 None
80 ========================================================================
81 */
MD5_Init(struct rt_md5_ctx_struc * pMD5_CTX)82 void MD5_Init(struct rt_md5_ctx_struc *pMD5_CTX)
83 {
84 NdisMoveMemory(pMD5_CTX->HashValue, MD5_DefaultHashValue,
85 sizeof(MD5_DefaultHashValue));
86 NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE);
87 pMD5_CTX->BlockLen = 0;
88 pMD5_CTX->MessageLen = 0;
89 } /* End of MD5_Init */
90
91 /*
92 ========================================================================
93 Routine Description:
94 MD5 computation for one block (512 bits)
95
96 Arguments:
97 pMD5_CTX Pointer to Md5_CTX_STRUC
98
99 Return Value:
100 None
101
102 Note:
103 T[i] := floor(abs(sin(i + 1)) * (2 pow 32)), i is number of round
104 ========================================================================
105 */
MD5_Hash(struct rt_md5_ctx_struc * pMD5_CTX)106 void MD5_Hash(struct rt_md5_ctx_struc *pMD5_CTX)
107 {
108 u32 X_i;
109 u32 X[16];
110 u32 a, b, c, d;
111
112 /* Prepare the message schedule, {X_i} */
113 NdisMoveMemory(X, pMD5_CTX->Block, MD5_BLOCK_SIZE);
114 for (X_i = 0; X_i < 16; X_i++)
115 X[X_i] = cpu2le32(X[X_i]); /* Endian Swap */
116 /* End of for */
117
118 /* MD5 hash computation */
119 /* Initialize the working variables */
120 a = pMD5_CTX->HashValue[0];
121 b = pMD5_CTX->HashValue[1];
122 c = pMD5_CTX->HashValue[2];
123 d = pMD5_CTX->HashValue[3];
124
125 /*
126 * Round 1
127 * Let [abcd k s i] denote the operation
128 * a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s)
129 */
130 ROUND1(a, b, c, d, X[0], 7, 0xd76aa478); /* 1 */
131 ROUND1(d, a, b, c, X[1], 12, 0xe8c7b756); /* 2 */
132 ROUND1(c, d, a, b, X[2], 17, 0x242070db); /* 3 */
133 ROUND1(b, c, d, a, X[3], 22, 0xc1bdceee); /* 4 */
134 ROUND1(a, b, c, d, X[4], 7, 0xf57c0faf); /* 5 */
135 ROUND1(d, a, b, c, X[5], 12, 0x4787c62a); /* 6 */
136 ROUND1(c, d, a, b, X[6], 17, 0xa8304613); /* 7 */
137 ROUND1(b, c, d, a, X[7], 22, 0xfd469501); /* 8 */
138 ROUND1(a, b, c, d, X[8], 7, 0x698098d8); /* 9 */
139 ROUND1(d, a, b, c, X[9], 12, 0x8b44f7af); /* 10 */
140 ROUND1(c, d, a, b, X[10], 17, 0xffff5bb1); /* 11 */
141 ROUND1(b, c, d, a, X[11], 22, 0x895cd7be); /* 12 */
142 ROUND1(a, b, c, d, X[12], 7, 0x6b901122); /* 13 */
143 ROUND1(d, a, b, c, X[13], 12, 0xfd987193); /* 14 */
144 ROUND1(c, d, a, b, X[14], 17, 0xa679438e); /* 15 */
145 ROUND1(b, c, d, a, X[15], 22, 0x49b40821); /* 16 */
146
147 /*
148 * Round 2
149 * Let [abcd k s i] denote the operation
150 * a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s)
151 */
152 ROUND2(a, b, c, d, X[1], 5, 0xf61e2562); /* 17 */
153 ROUND2(d, a, b, c, X[6], 9, 0xc040b340); /* 18 */
154 ROUND2(c, d, a, b, X[11], 14, 0x265e5a51); /* 19 */
155 ROUND2(b, c, d, a, X[0], 20, 0xe9b6c7aa); /* 20 */
156 ROUND2(a, b, c, d, X[5], 5, 0xd62f105d); /* 21 */
157 ROUND2(d, a, b, c, X[10], 9, 0x2441453); /* 22 */
158 ROUND2(c, d, a, b, X[15], 14, 0xd8a1e681); /* 23 */
159 ROUND2(b, c, d, a, X[4], 20, 0xe7d3fbc8); /* 24 */
160 ROUND2(a, b, c, d, X[9], 5, 0x21e1cde6); /* 25 */
161 ROUND2(d, a, b, c, X[14], 9, 0xc33707d6); /* 26 */
162 ROUND2(c, d, a, b, X[3], 14, 0xf4d50d87); /* 27 */
163 ROUND2(b, c, d, a, X[8], 20, 0x455a14ed); /* 28 */
164 ROUND2(a, b, c, d, X[13], 5, 0xa9e3e905); /* 29 */
165 ROUND2(d, a, b, c, X[2], 9, 0xfcefa3f8); /* 30 */
166 ROUND2(c, d, a, b, X[7], 14, 0x676f02d9); /* 31 */
167 ROUND2(b, c, d, a, X[12], 20, 0x8d2a4c8a); /* 32 */
168
169 /*
170 * Round 3
171 * Let [abcd k s t] denote the operation
172 * a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s)
173 */
174 ROUND3(a, b, c, d, X[5], 4, 0xfffa3942); /* 33 */
175 ROUND3(d, a, b, c, X[8], 11, 0x8771f681); /* 34 */
176 ROUND3(c, d, a, b, X[11], 16, 0x6d9d6122); /* 35 */
177 ROUND3(b, c, d, a, X[14], 23, 0xfde5380c); /* 36 */
178 ROUND3(a, b, c, d, X[1], 4, 0xa4beea44); /* 37 */
179 ROUND3(d, a, b, c, X[4], 11, 0x4bdecfa9); /* 38 */
180 ROUND3(c, d, a, b, X[7], 16, 0xf6bb4b60); /* 39 */
181 ROUND3(b, c, d, a, X[10], 23, 0xbebfbc70); /* 40 */
182 ROUND3(a, b, c, d, X[13], 4, 0x289b7ec6); /* 41 */
183 ROUND3(d, a, b, c, X[0], 11, 0xeaa127fa); /* 42 */
184 ROUND3(c, d, a, b, X[3], 16, 0xd4ef3085); /* 43 */
185 ROUND3(b, c, d, a, X[6], 23, 0x4881d05); /* 44 */
186 ROUND3(a, b, c, d, X[9], 4, 0xd9d4d039); /* 45 */
187 ROUND3(d, a, b, c, X[12], 11, 0xe6db99e5); /* 46 */
188 ROUND3(c, d, a, b, X[15], 16, 0x1fa27cf8); /* 47 */
189 ROUND3(b, c, d, a, X[2], 23, 0xc4ac5665); /* 48 */
190
191 /*
192 * Round 4
193 * Let [abcd k s t] denote the operation
194 * a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s)
195 */
196 ROUND4(a, b, c, d, X[0], 6, 0xf4292244); /* 49 */
197 ROUND4(d, a, b, c, X[7], 10, 0x432aff97); /* 50 */
198 ROUND4(c, d, a, b, X[14], 15, 0xab9423a7); /* 51 */
199 ROUND4(b, c, d, a, X[5], 21, 0xfc93a039); /* 52 */
200 ROUND4(a, b, c, d, X[12], 6, 0x655b59c3); /* 53 */
201 ROUND4(d, a, b, c, X[3], 10, 0x8f0ccc92); /* 54 */
202 ROUND4(c, d, a, b, X[10], 15, 0xffeff47d); /* 55 */
203 ROUND4(b, c, d, a, X[1], 21, 0x85845dd1); /* 56 */
204 ROUND4(a, b, c, d, X[8], 6, 0x6fa87e4f); /* 57 */
205 ROUND4(d, a, b, c, X[15], 10, 0xfe2ce6e0); /* 58 */
206 ROUND4(c, d, a, b, X[6], 15, 0xa3014314); /* 59 */
207 ROUND4(b, c, d, a, X[13], 21, 0x4e0811a1); /* 60 */
208 ROUND4(a, b, c, d, X[4], 6, 0xf7537e82); /* 61 */
209 ROUND4(d, a, b, c, X[11], 10, 0xbd3af235); /* 62 */
210 ROUND4(c, d, a, b, X[2], 15, 0x2ad7d2bb); /* 63 */
211 ROUND4(b, c, d, a, X[9], 21, 0xeb86d391); /* 64 */
212
213 /* Compute the i^th intermediate hash value H^(i) */
214 pMD5_CTX->HashValue[0] += a;
215 pMD5_CTX->HashValue[1] += b;
216 pMD5_CTX->HashValue[2] += c;
217 pMD5_CTX->HashValue[3] += d;
218
219 NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE);
220 pMD5_CTX->BlockLen = 0;
221 } /* End of MD5_Hash */
222
223 /*
224 ========================================================================
225 Routine Description:
226 The message is appended to block. If block size > 64 bytes, the MD5_Hash
227 will be called.
228
229 Arguments:
230 pMD5_CTX Pointer to struct rt_md5_ctx_struc
231 message Message context
232 messageLen The length of message in bytes
233
234 Return Value:
235 None
236
237 Note:
238 None
239 ========================================================================
240 */
MD5_Append(struct rt_md5_ctx_struc * pMD5_CTX,IN const u8 Message[],u32 MessageLen)241 void MD5_Append(struct rt_md5_ctx_struc *pMD5_CTX,
242 IN const u8 Message[], u32 MessageLen)
243 {
244 u32 appendLen = 0;
245 u32 diffLen = 0;
246
247 while (appendLen != MessageLen) {
248 diffLen = MessageLen - appendLen;
249 if ((pMD5_CTX->BlockLen + diffLen) < MD5_BLOCK_SIZE) {
250 NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen,
251 Message + appendLen, diffLen);
252 pMD5_CTX->BlockLen += diffLen;
253 appendLen += diffLen;
254 } else {
255 NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen,
256 Message + appendLen,
257 MD5_BLOCK_SIZE - pMD5_CTX->BlockLen);
258 appendLen += (MD5_BLOCK_SIZE - pMD5_CTX->BlockLen);
259 pMD5_CTX->BlockLen = MD5_BLOCK_SIZE;
260 MD5_Hash(pMD5_CTX);
261 } /* End of if */
262 } /* End of while */
263 pMD5_CTX->MessageLen += MessageLen;
264 } /* End of MD5_Append */
265
266 /*
267 ========================================================================
268 Routine Description:
269 1. Append bit 1 to end of the message
270 2. Append the length of message in rightmost 64 bits
271 3. Transform the Hash Value to digest message
272
273 Arguments:
274 pMD5_CTX Pointer to struct rt_md5_ctx_struc
275
276 Return Value:
277 digestMessage Digest message
278
279 Note:
280 None
281 ========================================================================
282 */
MD5_End(struct rt_md5_ctx_struc * pMD5_CTX,u8 DigestMessage[])283 void MD5_End(struct rt_md5_ctx_struc *pMD5_CTX, u8 DigestMessage[])
284 {
285 u32 index;
286 u64 message_length_bits;
287
288 /* append 1 bits to end of the message */
289 NdisFillMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen, 1, 0x80);
290
291 /* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */
292 if (pMD5_CTX->BlockLen > 55)
293 MD5_Hash(pMD5_CTX);
294 /* End of if */
295
296 /* Append the length of message in rightmost 64 bits */
297 message_length_bits = pMD5_CTX->MessageLen * 8;
298 message_length_bits = cpu2le64(message_length_bits);
299 NdisMoveMemory(&pMD5_CTX->Block[56], &message_length_bits, 8);
300 MD5_Hash(pMD5_CTX);
301
302 /* Return message digest, transform the u32 hash value to bytes */
303 for (index = 0; index < 4; index++)
304 pMD5_CTX->HashValue[index] =
305 cpu2le32(pMD5_CTX->HashValue[index]);
306 /* End of for */
307 NdisMoveMemory(DigestMessage, pMD5_CTX->HashValue, MD5_DIGEST_SIZE);
308 } /* End of MD5_End */
309
310 /*
311 ========================================================================
312 Routine Description:
313 MD5 algorithm
314
315 Arguments:
316 message Message context
317 messageLen The length of message in bytes
318
319 Return Value:
320 digestMessage Digest message
321
322 Note:
323 None
324 ========================================================================
325 */
RT_MD5(IN const u8 Message[],u32 MessageLen,u8 DigestMessage[])326 void RT_MD5(IN const u8 Message[],
327 u32 MessageLen, u8 DigestMessage[])
328 {
329 struct rt_md5_ctx_struc md5_ctx;
330
331 NdisZeroMemory(&md5_ctx, sizeof(struct rt_md5_ctx_struc));
332 MD5_Init(&md5_ctx);
333 MD5_Append(&md5_ctx, Message, MessageLen);
334 MD5_End(&md5_ctx, DigestMessage);
335 } /* End of RT_MD5 */
336
337 #endif /* MD5_SUPPORT */
338
339 /* End of crypt_md5.c */
340