2
*************************************************************************
4
* 5F., No.36, Taiyuan St., Jhubei City,
8
* (c) Copyright 2002-2007, Ralink Technology, Inc.
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. *
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. *
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. *
25
*************************************************************************/
27
#include "../crypt_md5.h"
31
* F, G, H and I are basic MD5 functions.
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)))
38
#define ROTL(x,n,w) ((x << n) | (x >> (w - n)))
39
#define ROTL32(x,n) ROTL(x,n,32) /* 32 bits word */
41
#define ROUND1(a, b, c, d, x, s, ac) { \
42
(a) += F((b),(c),(d)) + (x) + (u32)(ac); \
43
(a) = ROTL32((a),(s)); \
46
#define ROUND2(a, b, c, d, x, s, ac) { \
47
(a) += G((b),(c),(d)) + (x) + (u32)(ac); \
48
(a) = ROTL32((a),(s)); \
51
#define ROUND3(a, b, c, d, x, s, ac) { \
52
(a) += H((b),(c),(d)) + (x) + (u32)(ac); \
53
(a) = ROTL32((a),(s)); \
56
#define ROUND4(a, b, c, d, x, s, ac) { \
57
(a) += I((b),(c),(d)) + (x) + (u32)(ac); \
58
(a) = ROTL32((a),(s)); \
61
static const u32 MD5_DefaultHashValue[4] = {
62
0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL
64
#endif /* MD5_SUPPORT */
68
========================================================================
73
pMD5_CTX Pointer to Md5_CTX_STRUC
80
========================================================================
82
void MD5_Init(struct rt_md5_ctx_struc *pMD5_CTX)
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 */
92
========================================================================
94
MD5 computation for one block (512 bits)
97
pMD5_CTX Pointer to Md5_CTX_STRUC
103
T[i] := floor(abs(sin(i + 1)) * (2 pow 32)), i is number of round
104
========================================================================
106
void MD5_Hash(struct rt_md5_ctx_struc *pMD5_CTX)
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 */
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];
127
* Let [abcd k s i] denote the operation
128
* a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s)
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 */
149
* Let [abcd k s i] denote the operation
150
* a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s)
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 */
171
* Let [abcd k s t] denote the operation
172
* a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s)
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 */
193
* Let [abcd k s t] denote the operation
194
* a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s)
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 */
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;
219
NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE);
220
pMD5_CTX->BlockLen = 0;
221
} /* End of MD5_Hash */
224
========================================================================
226
The message is appended to block. If block size > 64 bytes, the MD5_Hash
230
pMD5_CTX Pointer to struct rt_md5_ctx_struc
231
message Message context
232
messageLen The length of message in bytes
239
========================================================================
241
void MD5_Append(struct rt_md5_ctx_struc *pMD5_CTX,
242
IN const u8 Message[], u32 MessageLen)
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;
255
NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen,
257
MD5_BLOCK_SIZE - pMD5_CTX->BlockLen);
258
appendLen += (MD5_BLOCK_SIZE - pMD5_CTX->BlockLen);
259
pMD5_CTX->BlockLen = MD5_BLOCK_SIZE;
263
pMD5_CTX->MessageLen += MessageLen;
264
} /* End of MD5_Append */
267
========================================================================
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
274
pMD5_CTX Pointer to struct rt_md5_ctx_struc
277
digestMessage Digest message
281
========================================================================
283
void MD5_End(struct rt_md5_ctx_struc *pMD5_CTX, u8 DigestMessage[])
286
u64 message_length_bits;
288
/* append 1 bits to end of the message */
289
NdisFillMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen, 1, 0x80);
291
/* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */
292
if (pMD5_CTX->BlockLen > 55)
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);
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]);
307
NdisMoveMemory(DigestMessage, pMD5_CTX->HashValue, MD5_DIGEST_SIZE);
308
} /* End of MD5_End */
311
========================================================================
316
message Message context
317
messageLen The length of message in bytes
320
digestMessage Digest message
324
========================================================================
326
void RT_MD5(IN const u8 Message[],
327
u32 MessageLen, u8 DigestMessage[])
329
struct rt_md5_ctx_struc md5_ctx;
331
NdisZeroMemory(&md5_ctx, sizeof(struct rt_md5_ctx_struc));
333
MD5_Append(&md5_ctx, Message, MessageLen);
334
MD5_End(&md5_ctx, DigestMessage);
335
} /* End of RT_MD5 */
337
#endif /* MD5_SUPPORT */
339
/* End of crypt_md5.c */