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