]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/rt2860/common/crypt_md5.c
7c9ecfa8e5a2d04020b2bb71711f27122c350dff
[net-next-2.6.git] / drivers / staging / rt2860 / common / crypt_md5.c
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) + (UINT32)(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) + (UINT32)(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) + (UINT32)(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) + (UINT32)(ac); \
58     (a)  = ROTL32((a),(s));                     \
59     (a) += (b);                                 \
60 }
61 static const UINT32 MD5_DefaultHashValue[4] = {
62     0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL
63 };
64 #endif /* MD5_SUPPORT */
65
66
67 #ifdef MD5_SUPPORT
68 /*
69 ========================================================================
70 Routine Description:
71     Initial Md5_CTX_STRUC
72
73 Arguments:
74     pMD5_CTX        Pointer to Md5_CTX_STRUC
75
76 Return Value:
77     None
78
79 Note:
80     None
81 ========================================================================
82 */
83 VOID MD5_Init (
84     IN  MD5_CTX_STRUC *pMD5_CTX)
85 {
86     NdisMoveMemory(pMD5_CTX->HashValue, MD5_DefaultHashValue,
87         sizeof(MD5_DefaultHashValue));
88     NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE);
89     pMD5_CTX->BlockLen   = 0;
90     pMD5_CTX->MessageLen = 0;
91 } /* End of MD5_Init */
92
93
94 /*
95 ========================================================================
96 Routine Description:
97     MD5 computation for one block (512 bits)
98
99 Arguments:
100     pMD5_CTX        Pointer to Md5_CTX_STRUC
101
102 Return Value:
103     None
104
105 Note:
106     T[i] := floor(abs(sin(i + 1)) * (2 pow 32)), i is number of round
107 ========================================================================
108 */
109 VOID MD5_Hash (
110     IN  MD5_CTX_STRUC *pMD5_CTX)
111 {
112     UINT32 X_i;
113     UINT32 X[16];
114     UINT32 a,b,c,d;
115
116     /* Prepare the message schedule, {X_i} */
117     NdisMoveMemory(X, pMD5_CTX->Block, MD5_BLOCK_SIZE);
118     for (X_i = 0; X_i < 16; X_i++)
119         X[X_i] = cpu2le32(X[X_i]); /* Endian Swap */
120         /* End of for */
121
122     /* MD5 hash computation */
123     /* Initialize the working variables */
124     a = pMD5_CTX->HashValue[0];
125     b = pMD5_CTX->HashValue[1];
126     c = pMD5_CTX->HashValue[2];
127     d = pMD5_CTX->HashValue[3];
128
129     /*
130      *  Round 1
131      *  Let [abcd k s i] denote the operation
132      *  a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s)
133      */
134     ROUND1(a, b, c, d, X[ 0],  7, 0xd76aa478); /* 1 */
135     ROUND1(d, a, b, c, X[ 1], 12, 0xe8c7b756); /* 2 */
136     ROUND1(c, d, a, b, X[ 2], 17, 0x242070db); /* 3 */
137     ROUND1(b, c, d, a, X[ 3], 22, 0xc1bdceee); /* 4 */
138     ROUND1(a, b, c, d, X[ 4],  7, 0xf57c0faf); /* 5 */
139     ROUND1(d, a, b, c, X[ 5], 12, 0x4787c62a); /* 6 */
140     ROUND1(c, d, a, b, X[ 6], 17, 0xa8304613); /* 7 */
141     ROUND1(b, c, d, a, X[ 7], 22, 0xfd469501); /* 8 */
142     ROUND1(a, b, c, d, X[ 8],  7, 0x698098d8); /* 9 */
143     ROUND1(d, a, b, c, X[ 9], 12, 0x8b44f7af); /* 10 */
144     ROUND1(c, d, a, b, X[10], 17, 0xffff5bb1); /* 11 */
145     ROUND1(b, c, d, a, X[11], 22, 0x895cd7be); /* 12 */
146     ROUND1(a, b, c, d, X[12],  7, 0x6b901122); /* 13 */
147     ROUND1(d, a, b, c, X[13], 12, 0xfd987193); /* 14 */
148     ROUND1(c, d, a, b, X[14], 17, 0xa679438e); /* 15 */
149     ROUND1(b, c, d, a, X[15], 22, 0x49b40821); /* 16 */
150
151     /*
152      *  Round 2
153      *  Let [abcd k s i] denote the operation
154      *  a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s)
155      */
156     ROUND2(a, b, c, d, X[ 1],  5, 0xf61e2562); /* 17 */
157     ROUND2(d, a, b, c, X[ 6],  9, 0xc040b340); /* 18 */
158     ROUND2(c, d, a, b, X[11], 14, 0x265e5a51); /* 19 */
159     ROUND2(b, c, d, a, X[ 0], 20, 0xe9b6c7aa); /* 20 */
160     ROUND2(a, b, c, d, X[ 5],  5, 0xd62f105d); /* 21 */
161     ROUND2(d, a, b, c, X[10],  9,  0x2441453); /* 22 */
162     ROUND2(c, d, a, b, X[15], 14, 0xd8a1e681); /* 23 */
163     ROUND2(b, c, d, a, X[ 4], 20, 0xe7d3fbc8); /* 24 */
164     ROUND2(a, b, c, d, X[ 9],  5, 0x21e1cde6); /* 25 */
165     ROUND2(d, a, b, c, X[14],  9, 0xc33707d6); /* 26 */
166     ROUND2(c, d, a, b, X[ 3], 14, 0xf4d50d87); /* 27 */
167     ROUND2(b, c, d, a, X[ 8], 20, 0x455a14ed); /* 28 */
168     ROUND2(a, b, c, d, X[13],  5, 0xa9e3e905); /* 29 */
169     ROUND2(d, a, b, c, X[ 2],  9, 0xfcefa3f8); /* 30 */
170     ROUND2(c, d, a, b, X[ 7], 14, 0x676f02d9); /* 31 */
171     ROUND2(b, c, d, a, X[12], 20, 0x8d2a4c8a); /* 32 */
172
173     /*
174      *  Round 3
175      *  Let [abcd k s t] denote the operation
176      *  a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s)
177      */
178     ROUND3(a, b, c, d, X[ 5],  4, 0xfffa3942); /* 33 */
179     ROUND3(d, a, b, c, X[ 8], 11, 0x8771f681); /* 34 */
180     ROUND3(c, d, a, b, X[11], 16, 0x6d9d6122); /* 35 */
181     ROUND3(b, c, d, a, X[14], 23, 0xfde5380c); /* 36 */
182     ROUND3(a, b, c, d, X[ 1],  4, 0xa4beea44); /* 37 */
183     ROUND3(d, a, b, c, X[ 4], 11, 0x4bdecfa9); /* 38 */
184     ROUND3(c, d, a, b, X[ 7], 16, 0xf6bb4b60); /* 39 */
185     ROUND3(b, c, d, a, X[10], 23, 0xbebfbc70); /* 40 */
186     ROUND3(a, b, c, d, X[13],  4, 0x289b7ec6); /* 41 */
187     ROUND3(d, a, b, c, X[ 0], 11, 0xeaa127fa); /* 42 */
188     ROUND3(c, d, a, b, X[ 3], 16, 0xd4ef3085); /* 43 */
189     ROUND3(b, c, d, a, X[ 6], 23,  0x4881d05); /* 44 */
190     ROUND3(a, b, c, d, X[ 9],  4, 0xd9d4d039); /* 45 */
191     ROUND3(d, a, b, c, X[12], 11, 0xe6db99e5); /* 46 */
192     ROUND3(c, d, a, b, X[15], 16, 0x1fa27cf8); /* 47 */
193     ROUND3(b, c, d, a, X[ 2], 23, 0xc4ac5665); /* 48 */
194
195     /*
196      *  Round 4
197      *  Let [abcd k s t] denote the operation
198      *  a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s)
199      */
200     ROUND4(a, b, c, d, X[ 0],  6, 0xf4292244); /* 49 */
201     ROUND4(d, a, b, c, X[ 7], 10, 0x432aff97); /* 50 */
202     ROUND4(c, d, a, b, X[14], 15, 0xab9423a7); /* 51 */
203     ROUND4(b, c, d, a, X[ 5], 21, 0xfc93a039); /* 52 */
204     ROUND4(a, b, c, d, X[12],  6, 0x655b59c3); /* 53 */
205     ROUND4(d, a, b, c, X[ 3], 10, 0x8f0ccc92); /* 54 */
206     ROUND4(c, d, a, b, X[10], 15, 0xffeff47d); /* 55 */
207     ROUND4(b, c, d, a, X[ 1], 21, 0x85845dd1); /* 56 */
208     ROUND4(a, b, c, d, X[ 8],  6, 0x6fa87e4f); /* 57 */
209     ROUND4(d, a, b, c, X[15], 10, 0xfe2ce6e0); /* 58 */
210     ROUND4(c, d, a, b, X[ 6], 15, 0xa3014314); /* 59 */
211     ROUND4(b, c, d, a, X[13], 21, 0x4e0811a1); /* 60 */
212     ROUND4(a, b, c, d, X[ 4],  6, 0xf7537e82); /* 61 */
213     ROUND4(d, a, b, c, X[11], 10, 0xbd3af235); /* 62 */
214     ROUND4(c, d, a, b, X[ 2], 15, 0x2ad7d2bb); /* 63 */
215     ROUND4(b, c, d, a, X[ 9], 21, 0xeb86d391); /* 64 */
216
217     /* Compute the i^th intermediate hash value H^(i) */
218     pMD5_CTX->HashValue[0] += a;
219     pMD5_CTX->HashValue[1] += b;
220     pMD5_CTX->HashValue[2] += c;
221     pMD5_CTX->HashValue[3] += d;
222
223     NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE);
224     pMD5_CTX->BlockLen = 0;
225 } /* End of MD5_Hash */
226
227
228 /*
229 ========================================================================
230 Routine Description:
231     The message is appended to block. If block size > 64 bytes, the MD5_Hash
232 will be called.
233
234 Arguments:
235     pMD5_CTX        Pointer to MD5_CTX_STRUC
236     message         Message context
237     messageLen      The length of message in bytes
238
239 Return Value:
240     None
241
242 Note:
243     None
244 ========================================================================
245 */
246 VOID MD5_Append (
247     IN  MD5_CTX_STRUC *pMD5_CTX,
248     IN  const UINT8 Message[],
249     IN  UINT MessageLen)
250 {
251     UINT appendLen = 0;
252     UINT diffLen = 0;
253
254     while (appendLen != MessageLen) {
255         diffLen = MessageLen - appendLen;
256         if ((pMD5_CTX->BlockLen + diffLen) < MD5_BLOCK_SIZE) {
257             NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen,
258                 Message + appendLen, diffLen);
259             pMD5_CTX->BlockLen += diffLen;
260             appendLen += diffLen;
261         }
262         else
263         {
264             NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen,
265                 Message + appendLen, MD5_BLOCK_SIZE - pMD5_CTX->BlockLen);
266             appendLen += (MD5_BLOCK_SIZE - pMD5_CTX->BlockLen);
267             pMD5_CTX->BlockLen = MD5_BLOCK_SIZE;
268             MD5_Hash(pMD5_CTX);
269         } /* End of if */
270     } /* End of while */
271     pMD5_CTX->MessageLen += MessageLen;
272 } /* End of MD5_Append */
273
274
275 /*
276 ========================================================================
277 Routine Description:
278     1. Append bit 1 to end of the message
279     2. Append the length of message in rightmost 64 bits
280     3. Transform the Hash Value to digest message
281
282 Arguments:
283     pMD5_CTX        Pointer to MD5_CTX_STRUC
284
285 Return Value:
286     digestMessage   Digest message
287
288 Note:
289     None
290 ========================================================================
291 */
292 VOID MD5_End (
293     IN  MD5_CTX_STRUC *pMD5_CTX,
294     OUT UINT8 DigestMessage[])
295 {
296     UINT index;
297     UINT64 message_length_bits;
298
299     /* append 1 bits to end of the message */
300     NdisFillMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen, 1, 0x80);
301
302     /* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */
303     if (pMD5_CTX->BlockLen > 55)
304         MD5_Hash(pMD5_CTX);
305         /* End of if */
306
307     /* Append the length of message in rightmost 64 bits */
308     message_length_bits = pMD5_CTX->MessageLen*8;
309     message_length_bits = cpu2le64(message_length_bits);
310     NdisMoveMemory(&pMD5_CTX->Block[56], &message_length_bits, 8);
311     MD5_Hash(pMD5_CTX);
312
313     /* Return message digest, transform the UINT32 hash value to bytes */
314     for (index = 0; index < 4;index++)
315         pMD5_CTX->HashValue[index] = cpu2le32(pMD5_CTX->HashValue[index]);
316         /* End of for */
317     NdisMoveMemory(DigestMessage, pMD5_CTX->HashValue, MD5_DIGEST_SIZE);
318 } /* End of MD5_End */
319
320
321 /*
322 ========================================================================
323 Routine Description:
324     MD5 algorithm
325
326 Arguments:
327     message         Message context
328     messageLen      The length of message in bytes
329
330 Return Value:
331     digestMessage   Digest message
332
333 Note:
334     None
335 ========================================================================
336 */
337 VOID RT_MD5 (
338     IN  const UINT8 Message[],
339     IN  UINT MessageLen,
340     OUT UINT8 DigestMessage[])
341 {
342     MD5_CTX_STRUC md5_ctx;
343
344     NdisZeroMemory(&md5_ctx, sizeof(MD5_CTX_STRUC));
345     MD5_Init(&md5_ctx);
346     MD5_Append(&md5_ctx, Message, MessageLen);
347     MD5_End(&md5_ctx, DigestMessage);
348 } /* End of RT_MD5 */
349
350 #endif /* MD5_SUPPORT */
351
352 /* End of crypt_md5.c */