]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/rt2860/common/crypt_md5.c
b3701f2bcc12f72316be5763b33b1920c02d5b28
[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 #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 */
82 VOID MD5_Init(IN 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 */
106 VOID MD5_Hash(IN MD5_CTX_STRUC * pMD5_CTX)
107 {
108         UINT32 X_i;
109         UINT32 X[16];
110         UINT32 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 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 */
241 VOID MD5_Append(IN MD5_CTX_STRUC * pMD5_CTX,
242                 IN const UINT8 Message[], IN UINT MessageLen)
243 {
244         UINT appendLen = 0;
245         UINT 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 MD5_CTX_STRUC
275
276 Return Value:
277     digestMessage   Digest message
278
279 Note:
280     None
281 ========================================================================
282 */
283 VOID MD5_End(IN MD5_CTX_STRUC * pMD5_CTX, OUT UINT8 DigestMessage[])
284 {
285         UINT index;
286         UINT64 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 UINT32 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 */
326 VOID RT_MD5(IN const UINT8 Message[],
327             IN UINT MessageLen, OUT UINT8 DigestMessage[])
328 {
329         MD5_CTX_STRUC md5_ctx;
330
331         NdisZeroMemory(&md5_ctx, sizeof(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 */