Files
Linux_Drivers/osdrv/extdrv/wireless/mediatek/mt7603/common/crypt_md5.c
forum_service 213c880673 add driver of tp、wiegand-gpio and wireless
Change-Id: Ie3c11d9d85cf1a05042f5690ac711856fe8b1ad7
2023-12-22 09:56:05 +08:00

1123 lines
32 KiB
C

/****************************************************************************
* Ralink Tech Inc.
* Taiwan, R.O.C.
*
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************/
#ifndef CRYPT_GPL_ALGORITHM
/****************************************************************************
Module Name:
MD5
Abstract:
RFC1321: The MD5 Message-Digest Algorithm
Revision History:
Who When What
-------- ---------- ------------------------------------------
Eddy 2008/11/24 Create md5
***************************************************************************/
#endif /* CRYPT_GPL_ALGORITHM */
#ifdef CRYPT_TESTPLAN
#include "crypt_testplan.h"
#else
#include "rt_config.h"
#endif /* CRYPT_TESTPLAN */
#ifdef CRYPT_GPL_ALGORITHM
/**
* md5_mac:
* @key: pointer to the key used for MAC generation
* @key_len: length of the key in bytes
* @data: pointer to the data area for which the MAC is generated
* @data_len: length of the data in bytes
* @mac: pointer to the buffer holding space for the MAC; the buffer should
* have space for 128-bit (16 bytes) MD5 hash value
*
* md5_mac() determines the message authentication code by using secure hash
* MD5(key | data | key).
*/
void md5_mac(UINT8 *key, size_t key_len, UINT8 *data, size_t data_len, UINT8 *mac)
{
MD5_CTX context;
MD5Init(&context);
MD5Update(&context, key, key_len);
MD5Update(&context, data, data_len);
MD5Update(&context, key, key_len);
MD5Final(mac, &context);
}
/**
* hmac_md5:
* @key: pointer to the key used for MAC generation
* @key_len: length of the key in bytes
* @data: pointer to the data area for which the MAC is generated
* @data_len: length of the data in bytes
* @mac: pointer to the buffer holding space for the MAC; the buffer should
* have space for 128-bit (16 bytes) MD5 hash value
*
* hmac_md5() determines the message authentication code using HMAC-MD5.
* This implementation is based on the sample code presented in RFC 2104.
*/
void hmac_md5(UINT8 *key, size_t key_len, UINT8 *data, size_t data_len, UINT8 *mac)
{
/* MD5_CTX context;*/
MD5_CTX *pcontext = NULL;
UINT8 k_ipad[65]; /* inner padding - key XORd with ipad */
UINT8 k_opad[65]; /* outer padding - key XORd with opad */
UINT8 tk[16];
int i;
/* allocate memory */
os_alloc_mem(NULL, (UCHAR **)&pcontext, sizeof(MD5_CTX));
if (pcontext == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
return;
}
/*assert(key != NULL && data != NULL && mac != NULL);*/
/* if key is longer than 64 bytes reset it to key = MD5(key) */
if (key_len > 64) {
MD5Init(pcontext);
MD5Update(pcontext, key, key_len);
MD5Final(tk, pcontext);
/*key=(PUCHAR)ttcontext.buf;*/
key = tk;
key_len = 16;
}
/* the HMAC_MD5 transform looks like:
*
* MD5(K XOR opad, MD5(K XOR ipad, text))
*
* where K is an n byte key
* ipad is the byte 0x36 repeated 64 times
* opad is the byte 0x5c repeated 64 times
* and text is the data being protected */
/* start out by storing key in pads */
NdisZeroMemory(k_ipad, sizeof(k_ipad));
NdisZeroMemory(k_opad, sizeof(k_opad));
/*assert(key_len < sizeof(k_ipad));*/
NdisMoveMemory(k_ipad, key, key_len);
NdisMoveMemory(k_opad, key, key_len);
/* XOR key with ipad and opad values */
for (i = 0; i < 64; i++) {
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/* perform inner MD5 */
MD5Init(pcontext); /* init context for 1st pass */
MD5Update(pcontext, k_ipad, 64); /* start with inner pad */
MD5Update(pcontext, data, data_len); /* then text of datagram */
MD5Final(mac, pcontext); /* finish up 1st pass */
/* perform outer MD5 */
MD5Init(pcontext); /* init context for 2nd pass */
MD5Update(pcontext, k_opad, 64); /* start with outer pad */
MD5Update(pcontext, mac, 16); /* then results of 1st hash */
MD5Final(mac, pcontext); /* finish up 2nd pass */
if (pcontext != NULL)
os_free_mem(NULL, pcontext);
}
#ifndef RT_BIG_ENDIAN
#define byteReverse(buf, len) /* Nothing */
#else
void byteReverse(unsigned char *buf, unsigned longs);
void byteReverse(unsigned char *buf, unsigned longs)
{
do {
*(ULONG *)buf = SWAP32(*(ULONG *)buf);
buf += 4;
} while (--longs);
}
#endif
/* ========================== MD5 implementation =========================== */
/* four base functions for MD5 */
#define MD5_F1(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define MD5_F2(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define MD5_F3(x, y, z) ((x) ^ (y) ^ (z))
#define MD5_F4(x, y, z) ((y) ^ ((x) | (~z)))
#define CYCLIC_LEFT_SHIFT(w, s) (((w) << (s)) | ((w) >> (32-(s))))
#define MD5Step(f, w, x, y, z, data, t, s) \
( w += f(x, y, z) + data + t, w = (CYCLIC_LEFT_SHIFT(w, s)) & 0xffffffff, w += x )
/*
* Function Description:
* Initiate MD5 Context satisfied in RFC 1321
*
* Arguments:
* pCtx Pointer to MD5 context
*
* Return Value:
* None
*/
VOID MD5Init(MD5_CTX *pCtx)
{
pCtx->Buf[0]=0x67452301;
pCtx->Buf[1]=0xefcdab89;
pCtx->Buf[2]=0x98badcfe;
pCtx->Buf[3]=0x10325476;
pCtx->LenInBitCount[0]=0;
pCtx->LenInBitCount[1]=0;
}
/*
* Function Description:
* Update MD5 Context, allow of an arrary of octets as the next portion
* of the message
*
* Arguments:
* pCtx Pointer to MD5 context
* pData Pointer to input data
* LenInBytes The length of input data (unit: byte)
*
* Return Value:
* None
*
* Note:
* Called after MD5Init or MD5Update(itself)
*/
VOID MD5Update(MD5_CTX *pCtx, UCHAR *pData, ULONG LenInBytes)
{
ULONG TfTimes;
ULONG temp;
unsigned int i;
temp = pCtx->LenInBitCount[0];
pCtx->LenInBitCount[0] = (ULONG) (pCtx->LenInBitCount[0] + (LenInBytes << 3));
if (pCtx->LenInBitCount[0] < temp)
pCtx->LenInBitCount[1]++; /*carry in*/
pCtx->LenInBitCount[1] += LenInBytes >> 29;
/* mod 64 bytes*/
temp = (temp >> 3) & 0x3f;
/* process lacks of 64-byte data */
if (temp)
{
UCHAR *pAds = (UCHAR *) pCtx->Input + temp;
if ((temp+LenInBytes) < 64)
{
NdisMoveMemory(pAds, (UCHAR *)pData, LenInBytes);
return;
}
NdisMoveMemory(pAds, (UCHAR *)pData, 64-temp);
byteReverse(pCtx->Input, 16);
MD5Transform(pCtx->Buf, (ULONG *)pCtx->Input);
pData += 64-temp;
LenInBytes -= 64-temp;
} /* end of if (temp)*/
TfTimes = (LenInBytes >> 6);
for (i=TfTimes; i>0; i--)
{
NdisMoveMemory(pCtx->Input, (UCHAR *)pData, 64);
byteReverse(pCtx->Input, 16);
MD5Transform(pCtx->Buf, (ULONG *)pCtx->Input);
pData += 64;
LenInBytes -= 64;
} /* end of for*/
/* buffering lacks of 64-byte data*/
if(LenInBytes)
NdisMoveMemory(pCtx->Input, (UCHAR *)pData, LenInBytes);
}
/*
* Function Description:
* Append padding bits and length of original message in the tail
* The message digest has to be completed in the end
*
* Arguments:
* Digest Output of Digest-Message for MD5
* pCtx Pointer to MD5 context
*
* Return Value:
* None
*
* Note:
* Called after MD5Update
*/
VOID MD5Final(UCHAR Digest[16], MD5_CTX *pCtx)
{
UCHAR Remainder;
UCHAR PadLenInBytes;
UCHAR *pAppend=0;
unsigned int i;
Remainder = (UCHAR)((pCtx->LenInBitCount[0] >> 3) & 0x3f);
PadLenInBytes = (Remainder < 56) ? (56-Remainder) : (120-Remainder);
pAppend = (UCHAR *)pCtx->Input + Remainder;
/* padding bits without crossing block(64-byte based) boundary*/
if (Remainder < 56)
{
*pAppend = 0x80;
PadLenInBytes --;
NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, PadLenInBytes);
/* add data-length field, from low to high*/
for (i=0; i<4; i++)
{
pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[0] >> (i << 3)) & 0xff);
pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[1] >> (i << 3)) & 0xff);
}
byteReverse(pCtx->Input, 16);
MD5Transform(pCtx->Buf, (ULONG *)pCtx->Input);
} /* end of if*/
/* padding bits with crossing block(64-byte based) boundary*/
else
{
/* the first block ===*/
*pAppend = 0x80;
PadLenInBytes --;
NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, (64-Remainder-1));
PadLenInBytes -= (64 - Remainder - 1);
byteReverse(pCtx->Input, 16);
MD5Transform(pCtx->Buf, (ULONG *)pCtx->Input);
/* the second block ===*/
NdisZeroMemory((UCHAR *)pCtx->Input, PadLenInBytes);
/* add data-length field*/
for (i=0; i<4; i++)
{
pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[0] >> (i << 3)) & 0xff);
pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[1] >> (i << 3)) & 0xff);
}
byteReverse(pCtx->Input, 16);
MD5Transform(pCtx->Buf, (ULONG *)pCtx->Input);
} /* end of else*/
NdisMoveMemory((UCHAR *)Digest, (ULONG *)pCtx->Buf, 16); /* output*/
byteReverse((UCHAR *)Digest, 4);
NdisZeroMemory(pCtx, sizeof(pCtx)); /* memory free */
}
/*
* Function Description:
* The central algorithm of MD5, consists of four rounds and sixteen
* steps per round
*
* Arguments:
* Buf Buffers of four states (output: 16 bytes)
* Mes Input data (input: 64 bytes)
*
* Return Value:
* None
*
* Note:
* Called by MD5Update or MD5Final
*/
VOID MD5Transform(ULONG Buf[4], ULONG Mes[16])
{
ULONG Reg[4], Temp;
unsigned int i;
static UCHAR LShiftVal[16] =
{
7, 12, 17, 22,
5, 9 , 14, 20,
4, 11, 16, 23,
6, 10, 15, 21,
};
/* [equal to 4294967296*abs(sin(index))]*/
static ULONG MD5Table[64] =
{
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
};
for (i=0; i<4; i++)
Reg[i]=Buf[i];
/* 64 steps in MD5 algorithm*/
for (i=0; i<16; i++)
{
MD5Step(MD5_F1, Reg[0], Reg[1], Reg[2], Reg[3], Mes[i],
MD5Table[i], LShiftVal[i & 0x3]);
/* one-word right shift*/
Temp = Reg[3];
Reg[3] = Reg[2];
Reg[2] = Reg[1];
Reg[1] = Reg[0];
Reg[0] = Temp;
}
for (i=16; i<32; i++)
{
MD5Step(MD5_F2, Reg[0], Reg[1], Reg[2], Reg[3], Mes[(5*(i & 0xf)+1) & 0xf],
MD5Table[i], LShiftVal[(0x1 << 2)+(i & 0x3)]);
/* one-word right shift*/
Temp = Reg[3];
Reg[3] = Reg[2];
Reg[2] = Reg[1];
Reg[1] = Reg[0];
Reg[0] = Temp;
}
for (i=32; i<48; i++)
{
MD5Step(MD5_F3, Reg[0], Reg[1], Reg[2], Reg[3], Mes[(3*(i & 0xf)+5) & 0xf],
MD5Table[i], LShiftVal[(0x1 << 3)+(i & 0x3)]);
/* one-word right shift*/
Temp = Reg[3];
Reg[3] = Reg[2];
Reg[2] = Reg[1];
Reg[1] = Reg[0];
Reg[0] = Temp;
}
for (i=48; i<64; i++)
{
MD5Step(MD5_F4, Reg[0], Reg[1], Reg[2], Reg[3], Mes[(7*(i & 0xf)) & 0xf],
MD5Table[i], LShiftVal[(0x3 << 2)+(i & 0x3)]);
/* one-word right shift*/
Temp = Reg[3];
Reg[3] = Reg[2];
Reg[2] = Reg[1];
Reg[1] = Reg[0];
Reg[0] = Temp;
}
/* (temporary)output*/
for (i=0; i<4; i++)
Buf[i] += Reg[i];
}
/* ========================= SHA-1 implementation ========================== */
/* four base functions for SHA-1*/
#define SHA1_F1(b, c, d) (((b) & (c)) | ((~b) & (d)))
#define SHA1_F2(b, c, d) ((b) ^ (c) ^ (d))
#define SHA1_F3(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
#define SHA1Step(f, a, b, c, d, e, w, k) \
( e += ( f(b, c, d) + w + k + CYCLIC_LEFT_SHIFT(a, 5)) & 0xffffffff, \
b = CYCLIC_LEFT_SHIFT(b, 30) )
/*Initiate SHA-1 Context satisfied in RFC 3174 */
VOID SHAInit(SHA_CTX *pCtx)
{
pCtx->Buf[0]=0x67452301;
pCtx->Buf[1]=0xefcdab89;
pCtx->Buf[2]=0x98badcfe;
pCtx->Buf[3]=0x10325476;
pCtx->Buf[4]=0xc3d2e1f0;
pCtx->LenInBitCount[0]=0;
pCtx->LenInBitCount[1]=0;
}
/*
* Function Description:
* Update SHA-1 Context, allow of an arrary of octets as the next
* portion of the message
*
* Arguments:
* pCtx Pointer to SHA-1 context
* pData Pointer to input data
* LenInBytes The length of input data (unit: byte)
*
* Return Value:
* error indicate more than pow(2,64) bits of data
*
* Note:
* Called after SHAInit or SHAUpdate(itself)
*/
UCHAR SHAUpdate(SHA_CTX *pCtx, UCHAR *pData, ULONG LenInBytes)
{
ULONG TfTimes;
ULONG temp1,temp2;
unsigned int i;
UCHAR err=1;
temp1 = pCtx->LenInBitCount[0];
temp2 = pCtx->LenInBitCount[1];
pCtx->LenInBitCount[0] = (ULONG) (pCtx->LenInBitCount[0] + (LenInBytes << 3));
if (pCtx->LenInBitCount[0] < temp1)
pCtx->LenInBitCount[1]++; /*carry in*/
pCtx->LenInBitCount[1] = (ULONG) (pCtx->LenInBitCount[1] +(LenInBytes >> 29));
if (pCtx->LenInBitCount[1] < temp2)
return (err); /*check total length of original data*/
/* mod 64 bytes*/
temp1 = (temp1 >> 3) & 0x3f;
/* process lacks of 64-byte data */
if (temp1)
{
UCHAR *pAds = (UCHAR *) pCtx->Input + temp1;
if ((temp1+LenInBytes) < 64)
{
NdisMoveMemory(pAds, (UCHAR *)pData, LenInBytes);
return (0);
}
NdisMoveMemory(pAds, (UCHAR *)pData, 64-temp1);
byteReverse((UCHAR *)pCtx->Input, 16);
NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16);
SHATransform(pCtx->Buf, (ULONG *)pCtx->Input);
pData += 64-temp1;
LenInBytes -= 64-temp1;
} /* end of if (temp1)*/
TfTimes = (LenInBytes >> 6);
for (i=TfTimes; i>0; i--)
{
NdisMoveMemory(pCtx->Input, (UCHAR *)pData, 64);
byteReverse((UCHAR *)pCtx->Input, 16);
NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16);
SHATransform(pCtx->Buf, (ULONG *)pCtx->Input);
pData += 64;
LenInBytes -= 64;
} /* end of for*/
/* buffering lacks of 64-byte data*/
if(LenInBytes)
NdisMoveMemory(pCtx->Input, (UCHAR *)pData, LenInBytes);
return (0);
}
/* Append padding bits and length of original message in the tail */
/* The message digest has to be completed in the end */
VOID SHAFinal(SHA_CTX *pCtx, UCHAR Digest[20])
{
UCHAR Remainder;
UCHAR PadLenInBytes;
UCHAR *pAppend=0;
unsigned int i;
Remainder = (UCHAR)((pCtx->LenInBitCount[0] >> 3) & 0x3f);
pAppend = (UCHAR *)pCtx->Input + Remainder;
PadLenInBytes = (Remainder < 56) ? (56-Remainder) : (120-Remainder);
/* padding bits without crossing block(64-byte based) boundary*/
if (Remainder < 56)
{
*pAppend = 0x80;
PadLenInBytes --;
NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, PadLenInBytes);
/* add data-length field, from high to low*/
for (i=0; i<4; i++)
{
pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[1] >> ((3-i) << 3)) & 0xff);
pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[0] >> ((3-i) << 3)) & 0xff);
}
byteReverse((UCHAR *)pCtx->Input, 16);
NdisZeroMemory((UCHAR *)pCtx->Input + 64, 14);
SHATransform(pCtx->Buf, (ULONG *)pCtx->Input);
} /* end of if*/
/* padding bits with crossing block(64-byte based) boundary*/
else
{
/* the first block ===*/
*pAppend = 0x80;
PadLenInBytes --;
NdisZeroMemory((UCHAR *)pCtx->Input + Remainder+1, (64-Remainder-1));
PadLenInBytes -= (64 - Remainder - 1);
byteReverse((UCHAR *)pCtx->Input, 16);
NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16);
SHATransform(pCtx->Buf, (ULONG *)pCtx->Input);
/* the second block ===*/
NdisZeroMemory((UCHAR *)pCtx->Input, PadLenInBytes);
/* add data-length field*/
for (i=0; i<4; i++)
{
pCtx->Input[56+i] = (UCHAR)((pCtx->LenInBitCount[1] >> ((3-i) << 3)) & 0xff);
pCtx->Input[60+i] = (UCHAR)((pCtx->LenInBitCount[0] >> ((3-i) << 3)) & 0xff);
}
byteReverse((UCHAR *)pCtx->Input, 16);
NdisZeroMemory((UCHAR *)pCtx->Input + 64, 16);
SHATransform(pCtx->Buf, (ULONG *)pCtx->Input);
} /* end of else*/
/*Output, bytereverse*/
for (i=0; i<20; i++)
{
Digest [i] = (UCHAR)(pCtx->Buf[i>>2] >> 8*(3-(i & 0x3)));
}
NdisZeroMemory(pCtx, sizeof(pCtx)); /* memory free */
}
/* The central algorithm of SHA-1, consists of four rounds and */
/* twenty steps per round*/
VOID SHATransform(ULONG Buf[5], ULONG Mes[20])
{
ULONG Reg[5],Temp;
unsigned int i;
/* ULONG W[80]; */
ULONG *W = NULL;
static ULONG SHA1Table[4] = { 0x5a827999, 0x6ed9eba1,
0x8f1bbcdc, 0xca62c1d6 };
/* allocate memory */
os_alloc_mem(NULL, (UCHAR **)&W, sizeof(ULONG)*80);
if (W == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
return;
}
Reg[0]=Buf[0];
Reg[1]=Buf[1];
Reg[2]=Buf[2];
Reg[3]=Buf[3];
Reg[4]=Buf[4];
/*the first octet of a word is stored in the 0th element, bytereverse*/
for(i = 0; i < 16; i++)
{
W[i] = (Mes[i] >> 24) & 0xff;
W[i] |= (Mes[i] >> 8 ) & 0xff00;
W[i] |= (Mes[i] << 8 ) & 0xff0000;
W[i] |= (Mes[i] << 24) & 0xff000000;
}
for (i = 0; i < 64; i++)
W[16+i] = CYCLIC_LEFT_SHIFT(W[i] ^ W[2+i] ^ W[8+i] ^ W[13+i], 1);
/* 80 steps in SHA-1 algorithm*/
for (i=0; i<80; i++)
{
if (i<20)
SHA1Step(SHA1_F1, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4],
W[i], SHA1Table[0]);
else if (i>=20 && i<40)
SHA1Step(SHA1_F2, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4],
W[i], SHA1Table[1]);
else if (i>=40 && i<60)
SHA1Step(SHA1_F3, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4],
W[i], SHA1Table[2]);
else
SHA1Step(SHA1_F2, Reg[0], Reg[1], Reg[2], Reg[3], Reg[4],
W[i], SHA1Table[3]);
/* one-word right shift*/
Temp = Reg[4];
Reg[4] = Reg[3];
Reg[3] = Reg[2];
Reg[2] = Reg[1];
Reg[1] = Reg[0];
Reg[0] = Temp;
} /* end of for-loop*/
/* (temporary)output*/
for (i=0; i<5; i++)
Buf[i] += Reg[i];
if (W != NULL)
os_free_mem(NULL, W);
}
/*
========================================================================
Routine Description:
SHA1 function
Arguments:
Return Value:
Note:
========================================================================
*/
VOID HMAC_SHA1(
IN UCHAR *text,
IN UINT text_len,
IN UCHAR *key,
IN UINT key_len,
IN UCHAR *digest)
{
/* SHA_CTX context;*/
SHA_CTX *pcontext = NULL;
UCHAR k_ipad[65]; /* inner padding - key XORd with ipad */
UCHAR k_opad[65]; /* outer padding - key XORd with opad */
INT i;
/* allocate memory */
os_alloc_mem(NULL, (UCHAR **)&pcontext, sizeof(SHA_CTX));
if (pcontext == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
return;
}
/* if key is longer than 64 bytes reset it to key=SHA1(key) */
if (key_len > 64)
{
SHAInit(pcontext);
SHAUpdate(pcontext, key, key_len);
SHAFinal(pcontext, key);
key_len = 20;
}
NdisZeroMemory(k_ipad, sizeof(k_ipad));
NdisZeroMemory(k_opad, sizeof(k_opad));
NdisMoveMemory(k_ipad, key, key_len);
NdisMoveMemory(k_opad, key, key_len);
/* XOR key with ipad and opad values */
for (i = 0; i < 64; i++)
{
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/* perform inner SHA1 */
SHAInit(pcontext); /* init context for 1st pass */
SHAUpdate(pcontext, k_ipad, 64); /* start with inner pad */
SHAUpdate(pcontext, text, text_len); /* then text of datagram */
SHAFinal(pcontext, digest); /* finish up 1st pass */
/*perform outer SHA1 */
SHAInit(pcontext); /* init context for 2nd pass */
SHAUpdate(pcontext, k_opad, 64); /* start with outer pad */
SHAUpdate(pcontext, digest, 20); /* then results of 1st hash */
SHAFinal(pcontext, digest); /* finish up 2nd pass */
if (pcontext != NULL)
os_free_mem(NULL, pcontext);
}
#else /* CRYPT_GPL_ALGORITHM */
#ifdef MD5_SUPPORT
/*
* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
#define ROTL(x,n,w) ((x << n) | (x >> (w - n)))
#define ROTL32(x,n) ROTL(x,n,32) /* 32 bits word */
#define ROUND1(a, b, c, d, x, s, ac) { \
(a) += F((b),(c),(d)) + (x) + (UINT32)(ac); \
(a) = ROTL32((a),(s)); \
(a) += (b); \
}
#define ROUND2(a, b, c, d, x, s, ac) { \
(a) += G((b),(c),(d)) + (x) + (UINT32)(ac); \
(a) = ROTL32((a),(s)); \
(a) += (b); \
}
#define ROUND3(a, b, c, d, x, s, ac) { \
(a) += H((b),(c),(d)) + (x) + (UINT32)(ac); \
(a) = ROTL32((a),(s)); \
(a) += (b); \
}
#define ROUND4(a, b, c, d, x, s, ac) { \
(a) += I((b),(c),(d)) + (x) + (UINT32)(ac); \
(a) = ROTL32((a),(s)); \
(a) += (b); \
}
static const UINT32 MD5_DefaultHashValue[4] = {
0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL
};
#endif /* MD5_SUPPORT */
#ifdef MD5_SUPPORT
/*
========================================================================
Routine Description:
Initial Md5_CTX_STRUC
Arguments:
pMD5_CTX Pointer to Md5_CTX_STRUC
Return Value:
None
Note:
None
========================================================================
*/
VOID RT_MD5_Init (
IN MD5_CTX_STRUC *pMD5_CTX)
{
NdisMoveMemory(pMD5_CTX->HashValue, MD5_DefaultHashValue,
sizeof(MD5_DefaultHashValue));
NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE);
pMD5_CTX->BlockLen = 0;
pMD5_CTX->MessageLen = 0;
} /* End of RT_MD5_Init */
/*
========================================================================
Routine Description:
MD5 computation for one block (512 bits)
Arguments:
pMD5_CTX Pointer to Md5_CTX_STRUC
Return Value:
None
Note:
T[i] := floor(abs(sin(i + 1)) * (2 pow 32)), i is number of round
========================================================================
*/
VOID RT_MD5_Hash (
IN MD5_CTX_STRUC *pMD5_CTX)
{
UINT32 X_i;
UINT32 X[16];
UINT32 a,b,c,d;
/* Prepare the message schedule, {X_i} */
NdisMoveMemory(X, pMD5_CTX->Block, MD5_BLOCK_SIZE);
for (X_i = 0; X_i < 16; X_i++)
X[X_i] = cpu2le32(X[X_i]); /* Endian Swap */
/* End of for */
/* MD5 hash computation */
/* Initialize the working variables */
a = pMD5_CTX->HashValue[0];
b = pMD5_CTX->HashValue[1];
c = pMD5_CTX->HashValue[2];
d = pMD5_CTX->HashValue[3];
/*
* Round 1
* Let [abcd k s i] denote the operation
* a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s)
*/
ROUND1(a, b, c, d, X[ 0], 7, 0xd76aa478); /* 1 */
ROUND1(d, a, b, c, X[ 1], 12, 0xe8c7b756); /* 2 */
ROUND1(c, d, a, b, X[ 2], 17, 0x242070db); /* 3 */
ROUND1(b, c, d, a, X[ 3], 22, 0xc1bdceee); /* 4 */
ROUND1(a, b, c, d, X[ 4], 7, 0xf57c0faf); /* 5 */
ROUND1(d, a, b, c, X[ 5], 12, 0x4787c62a); /* 6 */
ROUND1(c, d, a, b, X[ 6], 17, 0xa8304613); /* 7 */
ROUND1(b, c, d, a, X[ 7], 22, 0xfd469501); /* 8 */
ROUND1(a, b, c, d, X[ 8], 7, 0x698098d8); /* 9 */
ROUND1(d, a, b, c, X[ 9], 12, 0x8b44f7af); /* 10 */
ROUND1(c, d, a, b, X[10], 17, 0xffff5bb1); /* 11 */
ROUND1(b, c, d, a, X[11], 22, 0x895cd7be); /* 12 */
ROUND1(a, b, c, d, X[12], 7, 0x6b901122); /* 13 */
ROUND1(d, a, b, c, X[13], 12, 0xfd987193); /* 14 */
ROUND1(c, d, a, b, X[14], 17, 0xa679438e); /* 15 */
ROUND1(b, c, d, a, X[15], 22, 0x49b40821); /* 16 */
/*
* Round 2
* Let [abcd k s i] denote the operation
* a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s)
*/
ROUND2(a, b, c, d, X[ 1], 5, 0xf61e2562); /* 17 */
ROUND2(d, a, b, c, X[ 6], 9, 0xc040b340); /* 18 */
ROUND2(c, d, a, b, X[11], 14, 0x265e5a51); /* 19 */
ROUND2(b, c, d, a, X[ 0], 20, 0xe9b6c7aa); /* 20 */
ROUND2(a, b, c, d, X[ 5], 5, 0xd62f105d); /* 21 */
ROUND2(d, a, b, c, X[10], 9, 0x2441453); /* 22 */
ROUND2(c, d, a, b, X[15], 14, 0xd8a1e681); /* 23 */
ROUND2(b, c, d, a, X[ 4], 20, 0xe7d3fbc8); /* 24 */
ROUND2(a, b, c, d, X[ 9], 5, 0x21e1cde6); /* 25 */
ROUND2(d, a, b, c, X[14], 9, 0xc33707d6); /* 26 */
ROUND2(c, d, a, b, X[ 3], 14, 0xf4d50d87); /* 27 */
ROUND2(b, c, d, a, X[ 8], 20, 0x455a14ed); /* 28 */
ROUND2(a, b, c, d, X[13], 5, 0xa9e3e905); /* 29 */
ROUND2(d, a, b, c, X[ 2], 9, 0xfcefa3f8); /* 30 */
ROUND2(c, d, a, b, X[ 7], 14, 0x676f02d9); /* 31 */
ROUND2(b, c, d, a, X[12], 20, 0x8d2a4c8a); /* 32 */
/*
* Round 3
* Let [abcd k s t] denote the operation
* a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s)
*/
ROUND3(a, b, c, d, X[ 5], 4, 0xfffa3942); /* 33 */
ROUND3(d, a, b, c, X[ 8], 11, 0x8771f681); /* 34 */
ROUND3(c, d, a, b, X[11], 16, 0x6d9d6122); /* 35 */
ROUND3(b, c, d, a, X[14], 23, 0xfde5380c); /* 36 */
ROUND3(a, b, c, d, X[ 1], 4, 0xa4beea44); /* 37 */
ROUND3(d, a, b, c, X[ 4], 11, 0x4bdecfa9); /* 38 */
ROUND3(c, d, a, b, X[ 7], 16, 0xf6bb4b60); /* 39 */
ROUND3(b, c, d, a, X[10], 23, 0xbebfbc70); /* 40 */
ROUND3(a, b, c, d, X[13], 4, 0x289b7ec6); /* 41 */
ROUND3(d, a, b, c, X[ 0], 11, 0xeaa127fa); /* 42 */
ROUND3(c, d, a, b, X[ 3], 16, 0xd4ef3085); /* 43 */
ROUND3(b, c, d, a, X[ 6], 23, 0x4881d05); /* 44 */
ROUND3(a, b, c, d, X[ 9], 4, 0xd9d4d039); /* 45 */
ROUND3(d, a, b, c, X[12], 11, 0xe6db99e5); /* 46 */
ROUND3(c, d, a, b, X[15], 16, 0x1fa27cf8); /* 47 */
ROUND3(b, c, d, a, X[ 2], 23, 0xc4ac5665); /* 48 */
/*
* Round 4
* Let [abcd k s t] denote the operation
* a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s)
*/
ROUND4(a, b, c, d, X[ 0], 6, 0xf4292244); /* 49 */
ROUND4(d, a, b, c, X[ 7], 10, 0x432aff97); /* 50 */
ROUND4(c, d, a, b, X[14], 15, 0xab9423a7); /* 51 */
ROUND4(b, c, d, a, X[ 5], 21, 0xfc93a039); /* 52 */
ROUND4(a, b, c, d, X[12], 6, 0x655b59c3); /* 53 */
ROUND4(d, a, b, c, X[ 3], 10, 0x8f0ccc92); /* 54 */
ROUND4(c, d, a, b, X[10], 15, 0xffeff47d); /* 55 */
ROUND4(b, c, d, a, X[ 1], 21, 0x85845dd1); /* 56 */
ROUND4(a, b, c, d, X[ 8], 6, 0x6fa87e4f); /* 57 */
ROUND4(d, a, b, c, X[15], 10, 0xfe2ce6e0); /* 58 */
ROUND4(c, d, a, b, X[ 6], 15, 0xa3014314); /* 59 */
ROUND4(b, c, d, a, X[13], 21, 0x4e0811a1); /* 60 */
ROUND4(a, b, c, d, X[ 4], 6, 0xf7537e82); /* 61 */
ROUND4(d, a, b, c, X[11], 10, 0xbd3af235); /* 62 */
ROUND4(c, d, a, b, X[ 2], 15, 0x2ad7d2bb); /* 63 */
ROUND4(b, c, d, a, X[ 9], 21, 0xeb86d391); /* 64 */
/* Compute the i^th intermediate hash value H^(i) */
pMD5_CTX->HashValue[0] += a;
pMD5_CTX->HashValue[1] += b;
pMD5_CTX->HashValue[2] += c;
pMD5_CTX->HashValue[3] += d;
NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE);
pMD5_CTX->BlockLen = 0;
} /* End of RT_MD5_Hash */
/*
========================================================================
Routine Description:
The message is appended to block. If block size > 64 bytes, the MD5_Hash
will be called.
Arguments:
pMD5_CTX Pointer to MD5_CTX_STRUC
message Message context
messageLen The length of message in bytes
Return Value:
None
Note:
None
========================================================================
*/
VOID RT_MD5_Append (
IN MD5_CTX_STRUC *pMD5_CTX,
IN const UINT8 Message[],
IN UINT MessageLen)
{
UINT appendLen = 0;
UINT diffLen = 0;
while (appendLen != MessageLen) {
diffLen = MessageLen - appendLen;
if ((pMD5_CTX->BlockLen + diffLen) < MD5_BLOCK_SIZE) {
NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen,
Message + appendLen, diffLen);
pMD5_CTX->BlockLen += diffLen;
appendLen += diffLen;
}
else
{
NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen,
Message + appendLen, MD5_BLOCK_SIZE - pMD5_CTX->BlockLen);
appendLen += (MD5_BLOCK_SIZE - pMD5_CTX->BlockLen);
pMD5_CTX->BlockLen = MD5_BLOCK_SIZE;
RT_MD5_Hash(pMD5_CTX);
} /* End of if */
} /* End of while */
pMD5_CTX->MessageLen += MessageLen;
} /* End of RT_MD5_Append */
/*
========================================================================
Routine Description:
1. Append bit 1 to end of the message
2. Append the length of message in rightmost 64 bits
3. Transform the Hash Value to digest message
Arguments:
pMD5_CTX Pointer to MD5_CTX_STRUC
Return Value:
digestMessage Digest message
Note:
None
========================================================================
*/
VOID RT_MD5_End (
IN MD5_CTX_STRUC *pMD5_CTX,
OUT UINT8 DigestMessage[])
{
UINT index;
UINT64 message_length_bits;
/* append 1 bits to end of the message */
NdisFillMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen, 1, 0x80);
/* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */
if (pMD5_CTX->BlockLen > 55)
RT_MD5_Hash(pMD5_CTX);
/* End of if */
/* Append the length of message in rightmost 64 bits */
message_length_bits = pMD5_CTX->MessageLen*8;
message_length_bits = cpu2le64(message_length_bits);
NdisMoveMemory(&pMD5_CTX->Block[56], &message_length_bits, 8);
RT_MD5_Hash(pMD5_CTX);
/* Return message digest, transform the UINT32 hash value to bytes */
for (index = 0; index < 4;index++)
pMD5_CTX->HashValue[index] = cpu2le32(pMD5_CTX->HashValue[index]);
/* End of for */
NdisMoveMemory(DigestMessage, pMD5_CTX->HashValue, MD5_DIGEST_SIZE);
} /* End of RT_MD5_End */
/*
========================================================================
Routine Description:
MD5 algorithm
Arguments:
message Message context
messageLen The length of message in bytes
Return Value:
digestMessage Digest message
Note:
None
========================================================================
*/
VOID RT_MD5 (
IN const UINT8 Message[],
IN UINT MessageLen,
OUT UINT8 DigestMessage[])
{
MD5_CTX_STRUC md5_ctx;
NdisZeroMemory(&md5_ctx, sizeof(MD5_CTX_STRUC));
RT_MD5_Init(&md5_ctx);
RT_MD5_Append(&md5_ctx, Message, MessageLen);
RT_MD5_End(&md5_ctx, DigestMessage);
} /* End of RT_MD5 */
#endif /* MD5_SUPPORT */
#endif /* CRYPT_GPL_ALGORITHM */
/* End of crypt_md5.c */