• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/staging/rt2860/common/
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}
61static const u32 MD5_DefaultHashValue[4] = {
62	0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL
63};
64#endif /* MD5_SUPPORT */
65
66#ifdef MD5_SUPPORT
67/*
68========================================================================
69Routine Description:
70    Initial Md5_CTX_STRUC
71
72Arguments:
73    pMD5_CTX        Pointer to Md5_CTX_STRUC
74
75Return Value:
76    None
77
78Note:
79    None
80========================================================================
81*/
82void 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========================================================================
93Routine Description:
94    MD5 computation for one block (512 bits)
95
96Arguments:
97    pMD5_CTX        Pointer to Md5_CTX_STRUC
98
99Return Value:
100    None
101
102Note:
103    T[i] := floor(abs(sin(i + 1)) * (2 pow 32)), i is number of round
104========================================================================
105*/
106void 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========================================================================
225Routine Description:
226    The message is appended to block. If block size > 64 bytes, the MD5_Hash
227will be called.
228
229Arguments:
230    pMD5_CTX        Pointer to struct rt_md5_ctx_struc
231    message         Message context
232    messageLen      The length of message in bytes
233
234Return Value:
235    None
236
237Note:
238    None
239========================================================================
240*/
241void 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========================================================================
268Routine 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
273Arguments:
274    pMD5_CTX        Pointer to struct rt_md5_ctx_struc
275
276Return Value:
277    digestMessage   Digest message
278
279Note:
280    None
281========================================================================
282*/
283void 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========================================================================
312Routine Description:
313    MD5 algorithm
314
315Arguments:
316    message         Message context
317    messageLen      The length of message in bytes
318
319Return Value:
320    digestMessage   Digest message
321
322Note:
323    None
324========================================================================
325*/
326void 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