linux/drivers/staging/rt2860/common/crypt_md5.c
<<
>>
Prefs
   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