Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

433 lines
9.0 KiB

/*++
Copyright (c) 1994-1998 Microsoft Corporation
Module Name:
encrypt.c
Abstract:
Contains functions that encrypt and decrypt data sent accross client and
server.
Author:
Madan Appiah (madana) 24-Jan-1998
Environment:
User Mode - Win32
Revision History:
--*/
#include <seccom.h>
VOID
GenerateMACSignature(
LPBYTE pbData,
DWORD dwDataLen,
LPBYTE pbMACSaltKey,
DWORD dwMACSaltKey,
LPBYTE pbSignature,
BOOL fIncludeEncryptionCount,
DWORD dwEncryptionCount
)
/*++
Routine Description:
This function generates a message authentication signature.
Arguments:
pbData - pointer to a data buffer.
dwDataLen - length of the above data.
pbMACSaltKey - pointer to a MAC salt key.
pbSignature - pointer a signature buffer.
fIncludeEncryptionCount - TRUE to salt in the encryption count
dwEncryptionCount - total encryption count
Return Value:
None.
--*/
{
A_SHA_CTX SHAHash;
MD5_CTX MD5Hash;
BYTE abSHADigest[A_SHA_DIGEST_LEN];
//
// make a SHA(MACSalt + g_abPad1 + Length + Content) hash.
//
A_SHAInit(&SHAHash);
A_SHAUpdate(&SHAHash, pbMACSaltKey, dwMACSaltKey);
A_SHAUpdate(&SHAHash, (unsigned char *)g_abPad1, 40);
A_SHAUpdate(&SHAHash, (LPBYTE)&dwDataLen, sizeof(DWORD));
A_SHAUpdate(&SHAHash, pbData, dwDataLen);
if (fIncludeEncryptionCount) {
A_SHAUpdate(&SHAHash, (LPBYTE)&dwEncryptionCount, sizeof(DWORD));
}
A_SHAFinal(&SHAHash, abSHADigest);
//
// make a MD5(MACSalt + g_abPad2 + SHAHash) hash.
//
MD5Init(&MD5Hash);
MD5Update(&MD5Hash, pbMACSaltKey, dwMACSaltKey);
MD5Update(&MD5Hash, g_abPad2, 48);
MD5Update(&MD5Hash, abSHADigest, A_SHA_DIGEST_LEN);
MD5Final(&MD5Hash);
ASSERT( DATA_SIGNATURE_SIZE <= MD5DIGESTLEN );
memcpy(pbSignature, MD5Hash.digest, DATA_SIGNATURE_SIZE);
return;
}
BOOL
EncryptData(
DWORD dwEncryptionLevel,
LPBYTE pSessionKey,
struct RC4_KEYSTRUCT FAR *prc4EncryptKey,
DWORD dwKeyLength,
LPBYTE pbData,
DWORD dwDataLen,
LPBYTE pbMACSaltKey,
LPBYTE pbSignature,
BOOL fSecureChecksum,
DWORD dwEncryptionCount
)
/*++
Routine Description:
Encrypt the given data buffer in place.
Arguments:
dwEncryptionLevel - encryption level, used to select the encryption
algorithm.
pSessionKey - pointer to the session key.
prc4EncryptKey - pointer to a RC4 key.
dwKeyLength - length of the session key.
pbData - pointer to the data buffer being encrypted, encrypted data is
returned in the same buffer.
dwDataLen - length of the data buffer.
pbMACSaltKey - pointer to a message authentication key buffer.
pbSignature - pointer to a signature buffer where the data signature is
returned.
fSecureChecksum - TRUE if the checksum is to be salted with the encryption
count
dwDecryptionCount - running counter of all encryptions
Return Value:
TRUE - if successfully encrypted the data.
FALSE - otherwise.
--*/
{
//
// generate the MAC signature first.
//
GenerateMACSignature (
pbData,
dwDataLen,
pbMACSaltKey,
dwKeyLength,
pbSignature,
fSecureChecksum,
dwEncryptionCount
);
//
// encrypt data.
//
//
// use microsoft version of rc4 algorithm (super fast!) for level 1 and
// level 2 encryption, for level 3 use RSA rc4 algorithm.
//
if( dwEncryptionLevel <= 2 ) {
msrc4(prc4EncryptKey, (UINT)dwDataLen, pbData );
}
else {
rc4(prc4EncryptKey, (UINT)dwDataLen, pbData );
}
return( TRUE );
}
BOOL
DecryptData(
DWORD dwEncryptionLevel,
LPBYTE pSessionKey,
struct RC4_KEYSTRUCT FAR *prc4DecryptKey,
DWORD dwKeyLength,
LPBYTE pbData,
DWORD dwDataLen,
LPBYTE pbMACSaltKey,
LPBYTE pbSignature,
BOOL fSecureChecksum,
DWORD dwDecryptionCount
)
/*++
Routine Description:
Decrypt the given data buffer in place.
Arguments:
dwEncryptionLevel - encryption level, used to select the encryption
algorithm.
pSessionKey - pointer to the session key.
prc4DecryptKey - pointer to a RC4 key.
dwKeyLength - length of the session key.
pbData - pointer to the data buffer being decrypted, decrypted data is
returned in the same buffer.
dwDataLen - length of the data buffer.
pbMACSaltKey - pointer to a message authentication key buffer.
pbSignature - pointer to a signature buffer where the data signature is
returned.
fSecureChecksum - TRUE if the checksum is to be salted with the encryption
count
dwDecryptionCount - running counter of all encryptions
Return Value:
TRUE - if successfully encrypted the data.
FALSE - otherwise.
--*/
{
BYTE abSignature[DATA_SIGNATURE_SIZE];
//
// decrypt data.
//
//
// use microsoft version of rc4 algorithm (super fast!) for level 1 and
// level 2 encryption, for level 3 use RSA rc4 algorithm.
//
if( dwEncryptionLevel <= 2 ) {
msrc4(prc4DecryptKey, (UINT)dwDataLen, pbData );
}
else {
rc4(prc4DecryptKey, (UINT)dwDataLen, pbData );
}
GenerateMACSignature (
pbData,
dwDataLen,
pbMACSaltKey,
dwKeyLength,
(LPBYTE)abSignature,
fSecureChecksum,
dwDecryptionCount
);
//
// check to see the sigature match.
//
if( memcmp(
(LPBYTE)abSignature,
pbSignature,
sizeof(abSignature) ) ) {
return( FALSE );
}
return( TRUE );
}
#ifdef USE_MSRC4
VOID
msrc4_key(
struct RC4_KEYSTRUCT FAR *pKS,
DWORD dwLen,
LPBYTE pbKey
)
/*++
Routine Description:
Generate the key control structure. Key can be any size.
Assumes pKS is locked against simultaneous use.
Arguments:
pKS - pointer to a KEYSTRUCT structure that will be initialized.
dwLen - Size of the key, in bytes.
pbKey - Pointer to the key.
Return Value:
NONE.
--*/
{
#define SWAP(_x_, _y_) { BYTE _t_; _t_ = (_x_); (_x_) = (_y_); (_y_) = _t_; }
BYTE index1;
BYTE index2;
UINT counter;
BYTE bLen;
ASSERT( dwLen < 256 );
bLen = ( dwLen >= 256 ) ? 255 : (BYTE)dwLen;
for (counter = 0; counter < 256; counter++) {
pKS->S[counter] = (BYTE) counter;
}
pKS->i = 0;
pKS->j = 0;
index1 = 0;
index2 = 0;
for (counter = 0; counter < 256; counter++) {
index2 = (pbKey[index1] + pKS->S[counter] + index2);
SWAP(pKS->S[counter], pKS->S[index2]);
index1 = (index1 + 1) % bLen;
}
}
VOID
msrc4(
struct RC4_KEYSTRUCT FAR *pKS,
DWORD dwLen,
LPBYTE pbuf
)
/*++
Routine Description:
Performs the actual encryption or decryption.
Assumes pKS is locked against simultaneous use.
Arguments:
pKS - Pointer to the KEYSTRUCT created using msrc4_key().
dwLen - Size of buffer, in bytes.
pbuf - Buffer to be encrypted.
Return Value:
NONE.
--*/
{
BYTE FAR *const s = pKS->S;
BYTE a, b;
while(dwLen--) {
a = s[++(pKS->i)];
pKS->j += a;
b = s[pKS->j];
s[pKS->j] = a;
a += b;
s[pKS->i] = b;
*pbuf++ ^= s[a];
}
}
#endif // USE_MSRC4
/****************************************************************************/
/* PortableEncode and PortableEncode50 are functions used to */
/* encrypt/decrypt data on different machines. */
/****************************************************************************/
#define PE_RANDOM_CONSTANT "d72775a4-c832-11d1-9685-00c04fb15601"
void PortableEncode(LPBYTE pbData, DWORD dwDataLen)
{
A_SHA_CTX SHAHash;
BYTE abSHADigest[A_SHA_DIGEST_LEN];
struct RC4_KEYSTRUCT rc4Key;
A_SHAInit(&SHAHash);
A_SHAUpdate(&SHAHash, (LPBYTE)PE_RANDOM_CONSTANT,
sizeof(PE_RANDOM_CONSTANT));
A_SHAFinal(&SHAHash, abSHADigest);
msrc4_key(&rc4Key, MAX_SESSION_KEY_SIZE, abSHADigest);
msrc4(&rc4Key, (UINT)dwDataLen, pbData);
}
void PortableEncode50(LPBYTE pbData,
DWORD dwDataLen,
LPBYTE pbSalt,
DWORD dwSaltLength)
{
A_SHA_CTX SHAHash;
BYTE abSHADigest[A_SHA_DIGEST_LEN];
DWORD dw;
struct RC4_KEYSTRUCT rc4Key;
A_SHAInit(&SHAHash);
A_SHAUpdate(&SHAHash, (LPBYTE)PE_RANDOM_CONSTANT,
sizeof(PE_RANDOM_CONSTANT));
A_SHAFinal(&SHAHash, abSHADigest);
for (dw = 0; dw < 256; dw++) {
A_SHAInit(&SHAHash);
A_SHAUpdate(&SHAHash, pbSalt, dwSaltLength);
A_SHAUpdate(&SHAHash, abSHADigest, A_SHA_DIGEST_LEN);
A_SHAFinal(&SHAHash, abSHADigest);
}
msrc4_key(&rc4Key, MAX_SESSION_KEY_SIZE, abSHADigest);
msrc4(&rc4Key, (UINT)dwDataLen, pbData);
}
#undef PE_RANDOM_CONSTANT