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