Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

239 lines
7.3 KiB

#include "stdafx.h"
#include "auth.h"
#include "md5.h"
const CHAR g_cszADVAPI32DllName[] = "ADVAPI32.DLL";
const CHAR g_cszCryptAcquireContextA[] = "CryptAcquireContextA";
const CHAR g_cszCryptCreateHash[] = "CryptCreateHash";
const CHAR g_cszCryptHashData[] = "CryptHashData";
const CHAR g_cszCryptGetHashParam[] = "CryptGetHashParam";
const CHAR g_cszCryptDestroyHash[] = "CryptDestroyHash";
const CHAR g_cszCryptReleaseContext[] = "CryptReleaseContext";
const CHAR g_rgchHexNumMap[] =
{
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
const int MD5_HASH_LEN = 16;
void
hmac_md5(
unsigned char* text, /* pointer to data stream */
int text_len, /* length of data stream */
unsigned char* key, /* pointer to authentication key */
int key_len, /* length of authentication key */
BYTE digest[16]) /* caller digest to be filled in */
{
MD5_CTX context;
memset(&context, 0, sizeof(context));
unsigned char k_ipad[65]; /* inner padding -
* key XORd with ipad
*/
unsigned char k_opad[65]; /* outer padding -
* key XORd with opad
*/
int i;
/* if key is longer than 64 bytes reset it to key=MD5(key) */
if (key_len > 64) {
MD5_CTX tctx;
memset(&tctx, 0, sizeof(tctx));
MD5Init(&tctx);
MD5Update(&tctx, key, key_len);
MD5Final(&tctx);
key = tctx.digest;
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 */
ZeroMemory( k_ipad, sizeof k_ipad);
ZeroMemory( k_opad, sizeof k_opad);
CopyMemory( k_ipad, key, key_len);
CopyMemory( 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(&context); /* init context for 1st
* pass */
MD5Update(&context, k_ipad, 64); /* start with inner pad */
MD5Update(&context, text, text_len); /* then text of datagram */
MD5Final(&context); /* finish up 1st pass */
CopyMemory(digest, context.digest, 16);
/*
* perform outer MD5
*/
MD5Init(&context); /* init context for 2nd
* pass */
MD5Update(&context, k_opad, 64); /* start with outer pad */
MD5Update(&context, digest, 16); /* then results of 1st
* hash */
MD5Final(&context); /* finish up 2nd pass */
CopyMemory(digest, context.digest, 16);
}
//------------------------------------------------------------------------------------
//
// Initialize the static class members.
//
//------------------------------------------------------------------------------------
CAuthentication* CAuthentication::m_spAuthentication = NULL;
PSTR CAuthentication::GetHMACMD5Result(PSTR pszChallengeInfo, PSTR pszPassword)
{
MD5_CTX MD5Buffer;
memset(&MD5Buffer, 0, sizeof(MD5Buffer));
MD5Init(&MD5Buffer);
MD5Update(&MD5Buffer, (const unsigned char*)pszPassword, lstrlenA(pszPassword));
MD5Final(&MD5Buffer);
BYTE pbHash[16];
PBYTE pbHexHash = NULL; // The MD5 result in hex string format
pbHexHash = new BYTE[MD5DIGESTLEN * 2 + 1];
if (pbHexHash)
{
hmac_md5((unsigned char *) pszChallengeInfo, lstrlenA(pszChallengeInfo), MD5Buffer.digest, sizeof(MD5Buffer.digest), pbHash);
PBYTE pCurrent = pbHexHash;
// Convert the hash data to hex string.
for (int i = 0; i < MD5DIGESTLEN; i++)
{
*pCurrent++ = g_rgchHexNumMap[pbHash[i]/16];
*pCurrent++ = g_rgchHexNumMap[pbHash[i]%16];
}
*pCurrent = '\0';
}
return (PSTR) pbHexHash;
}
//------------------------------------------------------------------------------------
//
// Method: CAuthentication::GetMD5Key()
//
// Synopsis: Construct the MD5 hash key based on the ChallengeInfo and password.
//
// Append the password to the ChallengeInfo.
//
//------------------------------------------------------------------------------------
PSTR
CAuthentication::GetMD5Key(PSTR pszChallengeInfo, PSTR pszPassword)
{
int cbChallengeInfo = lstrlenA(pszChallengeInfo);
int cbPassword = lstrlenA(pszPassword);
PBYTE pbData = new BYTE[cbChallengeInfo + cbPassword + 1];
if (!pbData)
{
//WARNING_OUT(("CAuthentication::GetMD5Key> Out of memory"));
return NULL;
}
PBYTE pCurrent = pbData;
::CopyMemory(pCurrent, pszChallengeInfo, cbChallengeInfo);
pCurrent += cbChallengeInfo;
::CopyMemory(pCurrent, pszPassword, cbPassword);
pCurrent += cbPassword;
*pCurrent = '\0';
return (PSTR)pbData;
}
//------------------------------------------------------------------------------------
//
// Method: CAuthentication::GetMD5Result()
//
// Synposis: Compute the MD5 hash result based on the clear text.
//
//------------------------------------------------------------------------------------
PSTR
CAuthentication::GetMD5Result(PCSTR pszClearText)
{
PBYTE pbHexHash = NULL;
if (pszClearText)
{
MD5_CTX MD5Buffer;
MD5Init(&MD5Buffer);
MD5Update(&MD5Buffer, (const unsigned char*)pszClearText, lstrlenA(pszClearText));
MD5Final(&MD5Buffer);
PBYTE pbHash = MD5Buffer.digest;
pbHexHash = new BYTE[MD5DIGESTLEN * 2 + 1];
if (pbHexHash)
{
PBYTE pCurrent = pbHexHash;
// Convert the hash data to hex string.
for (int i = 0; i < MD5DIGESTLEN; i++)
{
*pCurrent++ = g_rgchHexNumMap[pbHash[i]/16];
*pCurrent++ = g_rgchHexNumMap[pbHash[i]%16];
}
*pCurrent = '\0';
}
else
{
//WARNING_OUT(("CAuthentication::GetMD5Result> Out of memory"));
}
}
return (PSTR)pbHexHash;
}
//------------------------------------------------------------------------------------
//
// Method: CAuthentication::GetMD5Result()
//
// Synopsis: Compute the MD5 hash result based on the ChallengeInfo and password.
//
//------------------------------------------------------------------------------------
PSTR
CAuthentication::GetMD5Result(PSTR pszChallengeInfo, PSTR pszPassword)
{
PSTR pbHexHash = NULL; // The MD5 result in hex string format
PSTR pMD5Key = GetMD5Key(pszChallengeInfo, pszPassword);
pbHexHash = GetMD5Result(pMD5Key);
delete pMD5Key;
return pbHexHash;
}