|
|
//+-----------------------------------------------------------------------
//
// File: RC4CWRAP.C
//
// Contents: CryptoSystem wrapper functions for RC4
//
//
// History: 25 Feb 92 RichardW Created
//
//------------------------------------------------------------------------
#ifndef KERNEL_MODE
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#else
#include <ntifs.h>
#endif
#include <string.h>
#include <malloc.h>
#include <kerbcon.h>
#include <security.h>
#include <cryptdll.h>
#include <rc4.h>
#include <md4.h>
#include <md5.h>
//#define DONT_SUPPORT_OLD_ETYPES 1
typedef struct RC4_KEYSTRUCT RC4KEY;
#define RC4_LEGAL_KEYSIZE 8
#define RC4_CONFOUNDER_LEN 8
typedef struct _RC4_MDx_HEADER { UCHAR Confounder[RC4_CONFOUNDER_LEN]; UCHAR Checksum[MD4_LEN]; } RC4_MDx_HEADER, *PRC4_MDx_HEADER;
typedef struct _RC4_STATE_BUFFER { PCHECKSUM_FUNCTION ChecksumFunction; PCHECKSUM_BUFFER ChecksumBuffer; RC4KEY Key; } RC4_STATE_BUFFER, *PRC4_STATE_BUFFER;
typedef struct _RC4_HMAC_STATE_BUFFER { UCHAR Key[MD5_LEN]; BOOLEAN IncludeHmac; } RC4_HMAC_STATE_BUFFER, *PRC4_HMAC_STATE_BUFFER;
NTSTATUS NTAPI rc4Md4Initialize(PUCHAR, ULONG, ULONG, PCRYPT_STATE_BUFFER *); NTSTATUS NTAPI rc4LmInitialize(PUCHAR, ULONG, ULONG, PCRYPT_STATE_BUFFER *); #ifndef DONT_SUPPORT_OLD_ETYPES
NTSTATUS NTAPI rc4Plain2Initialize(PUCHAR, ULONG, ULONG, PCRYPT_STATE_BUFFER *); NTSTATUS NTAPI rc4LmHashPassword(PSECURITY_STRING, PUCHAR); #endif
NTSTATUS NTAPI rc4Encrypt(PCRYPT_STATE_BUFFER, PUCHAR, ULONG, PUCHAR, PULONG); NTSTATUS NTAPI rc4Decrypt(PCRYPT_STATE_BUFFER, PUCHAR, ULONG, PUCHAR, PULONG); NTSTATUS NTAPI rc4Finish(PCRYPT_STATE_BUFFER *); NTSTATUS NTAPI rc4Md4HashPassword(PSECURITY_STRING, PUCHAR); NTSTATUS NTAPI rc4Md4RandomKey(PUCHAR, ULONG, PUCHAR); NTSTATUS NTAPI rc4Control(ULONG, PCRYPT_STATE_BUFFER, PUCHAR, ULONG);
NTSTATUS NTAPI rc4PlainInitializeOld(PUCHAR, ULONG, ULONG, PCRYPT_STATE_BUFFER *); NTSTATUS NTAPI rc4PlainExpInitializeOld(PUCHAR, ULONG, ULONG, PCRYPT_STATE_BUFFER *); NTSTATUS NTAPI rc4HmacInitializeOld(PUCHAR, ULONG, ULONG, PCRYPT_STATE_BUFFER *); NTSTATUS NTAPI rc4HmacExpInitializeOld(PUCHAR, ULONG, ULONG, PCRYPT_STATE_BUFFER *); NTSTATUS NTAPI rc4HmacEncryptOld(PCRYPT_STATE_BUFFER, PUCHAR, ULONG, PUCHAR, PULONG); NTSTATUS NTAPI rc4HmacDecryptOld(PCRYPT_STATE_BUFFER, PUCHAR, ULONG, PUCHAR, PULONG); NTSTATUS NTAPI rc4HmacFinishOld(PCRYPT_STATE_BUFFER *); NTSTATUS NTAPI rc4HmacControlOld(ULONG, PCRYPT_STATE_BUFFER, PUCHAR, ULONG); NTSTATUS NTAPI rc4HmacRandomKeyOld(PUCHAR, ULONG, PUCHAR);
#ifdef KERNEL_MODE
#pragma alloc_text( PAGEMSG, rc4Md4Initialize )
#pragma alloc_text( PAGEMSG, rc4LmInitialize )
#pragma alloc_text( PAGEMSG, rc4Encrypt )
#pragma alloc_text( PAGEMSG, rc4Decrypt )
#pragma alloc_text( PAGEMSG, rc4Finish )
#pragma alloc_text( PAGEMSG, rc4Md4HashPassword )
#pragma alloc_text( PAGEMSG, rc4Md4RandomKey )
#pragma alloc_text( PAGEMSG, rc4Control )
#pragma alloc_text( PAGEMSG, rc4PlainInitializeOld )
#pragma alloc_text( PAGEMSG, rc4PlainExpInitializeOld )
#pragma alloc_text( PAGEMSG, rc4HmacInitializeOld )
#pragma alloc_text( PAGEMSG, rc4HmacExpInitializeOld )
#pragma alloc_text( PAGEMSG, rc4HmacDecryptOld )
#pragma alloc_text( PAGEMSG, rc4HmacEncryptOld )
#pragma alloc_text( PAGEMSG, rc4HmacFinishOld )
#pragma alloc_text( PAGEMSG, rc4HmacControlOld )
#pragma alloc_text( PAGEMSG, rc4HmacRandomKeyOld )
#endif
CRYPTO_SYSTEM csRC4_MD4 = { KERB_ETYPE_RC4_MD4, // Etype
1, // Blocksize (stream)
0, // no exportable version
MD4_LEN, // Key size, in bytes
sizeof(RC4_MDx_HEADER), // header size
KERB_CHECKSUM_MD4, // Preferred Checksum
CSYSTEM_INTEGRITY_PROTECTED, // attributes
L"RSADSI RC4-MD4", // Text name
rc4Md4Initialize, rc4Encrypt, rc4Decrypt, rc4Finish, rc4Md4HashPassword, rc4Md4RandomKey, rc4Control };
#ifndef DONT_SUPPORT_OLD_ETYPES
CRYPTO_SYSTEM csRC4_LM = { KERB_ETYPE_RC4_LM, // Etype
1, // Blocksize (stream)
0, // no exportable version
MD4_LEN, // State buffer size
sizeof(RC4_MDx_HEADER), // header size
KERB_CHECKSUM_LM, // Preferred Checksum
CSYSTEM_INTEGRITY_PROTECTED, // attributes
L"RSADSI RC4-LM", // Text name
rc4LmInitialize, rc4Encrypt, rc4Decrypt, rc4Finish, rc4LmHashPassword, rc4Md4RandomKey, rc4Control };
CRYPTO_SYSTEM csRC4_PLAIN2 = { KERB_ETYPE_RC4_PLAIN2, // Etype
1, // Blocksize (stream)
0, // no exportable version
MD4_LEN, // Key size, in bytes
0, // header size
KERB_CHECKSUM_MD4, // Preferred Checksum
0, // no attributes
L"RSADSI RC4-PLAIN", // Text name
rc4Plain2Initialize, rc4Encrypt, rc4Decrypt, rc4Finish, rc4Md4HashPassword, rc4Md4RandomKey, rc4Control }; #endif
CRYPTO_SYSTEM csRC4_HMAC_OLD = { KERB_ETYPE_RC4_HMAC_OLD, // Etype
1, // Blocksize (stream)
KERB_ETYPE_RC4_HMAC_OLD_EXP,// Exportable version
MD4_LEN, // Key size, in bytes
sizeof(RC4_MDx_HEADER), // header size
KERB_CHECKSUM_MD4, // Preferred Checksum
CSYSTEM_INTEGRITY_PROTECTED, // attributes
L"RSADSI RC4-HMAC", // Text name
rc4HmacInitializeOld, rc4HmacEncryptOld, rc4HmacDecryptOld, rc4HmacFinishOld, rc4Md4HashPassword, rc4HmacRandomKeyOld, rc4HmacControlOld };
CRYPTO_SYSTEM csRC4_HMAC_OLD_EXP = { KERB_ETYPE_RC4_HMAC_OLD_EXP, // Etype
1, // Blocksize (stream)
KERB_ETYPE_RC4_HMAC_OLD_EXP, // Exportable version
MD4_LEN, // Key size, in bytes
sizeof(RC4_MDx_HEADER), // header size
KERB_CHECKSUM_MD4, // Preferred Checksum
CSYSTEM_INTEGRITY_PROTECTED | CSYSTEM_EXPORT_STRENGTH, // attributes
L"RSADSI RC4-HMAC", // Text name
rc4HmacInitializeOld, rc4HmacEncryptOld, rc4HmacDecryptOld, rc4HmacFinishOld, rc4Md4HashPassword, rc4HmacRandomKeyOld, rc4HmacControlOld };
CRYPTO_SYSTEM csRC4_PLAIN_OLD = { KERB_ETYPE_RC4_PLAIN_OLD, // Etype
1, // Blocksize (stream)
KERB_ETYPE_RC4_PLAIN_OLD_EXP, // exportable version
MD4_LEN, // Key size, in bytes
0, // header size
KERB_CHECKSUM_MD4, // Preferred Checksum
0, // no attributes
L"RSADSI RC4", // Text name
rc4PlainInitializeOld, rc4HmacEncryptOld, rc4HmacDecryptOld, rc4HmacFinishOld, rc4Md4HashPassword, rc4HmacRandomKeyOld, rc4HmacControlOld };
CRYPTO_SYSTEM csRC4_PLAIN_OLD_EXP = { KERB_ETYPE_RC4_PLAIN_OLD_EXP, // Etype
1, // Blocksize (stream)
KERB_ETYPE_RC4_PLAIN_OLD_EXP, // exportable version
MD4_LEN, // Key size, in bytes
0, // header size
KERB_CHECKSUM_MD4, // Preferred Checksum
CSYSTEM_EXPORT_STRENGTH, // no attributes
L"RSADSI RC4-EXP", // Text name
rc4PlainExpInitializeOld, rc4HmacEncryptOld, rc4HmacDecryptOld, rc4HmacFinishOld, rc4Md4HashPassword, rc4HmacRandomKeyOld, rc4HmacControlOld };
NTSTATUS NTAPI rc4Initialize( PUCHAR pbKey, ULONG KeySize, ULONG MessageType, ULONG ChecksumFunction, PCRYPT_STATE_BUFFER * psbBuffer) { NTSTATUS Status; PRC4_STATE_BUFFER pRC4Key; PCHECKSUM_FUNCTION Checksum = NULL;
//
// Get the appropriate checksum here.
//
if (ChecksumFunction != 0) { Status = CDLocateCheckSum( ChecksumFunction, &Checksum ); if (!NT_SUCCESS(Status)) { return(Status); }
} //
// if the key is too short, fail here.
//
if (KeySize < RC4_LEGAL_KEYSIZE) { return(SEC_E_ETYPE_NOT_SUPP); }
#ifdef KERNEL_MODE
pRC4Key = ExAllocatePool(NonPagedPool, sizeof(RC4_STATE_BUFFER)); #else
pRC4Key = LocalAlloc(0, sizeof(RC4_STATE_BUFFER)); #endif
if (pRC4Key == NULL) { return(STATUS_INSUFFICIENT_RESOURCES); }
rc4_key(&pRC4Key->Key, RC4_LEGAL_KEYSIZE, pbKey);
//
// Initialize the checksum function, if we have one.
//
pRC4Key->ChecksumFunction = Checksum;
if (Checksum != NULL) {
Status = Checksum->Initialize( 0, &pRC4Key->ChecksumBuffer ); if (!NT_SUCCESS(Status)) { #ifdef KERNEL_MODE
ExFreePool(pRC4Key); #else
LocalFree(pRC4Key); #endif
return(Status); } }
*psbBuffer = (PCRYPT_STATE_BUFFER) pRC4Key; return(STATUS_SUCCESS); }
NTSTATUS NTAPI rc4Md4Initialize( IN PUCHAR pbKey, IN ULONG KeySize, IN ULONG MessageType, OUT PCRYPT_STATE_BUFFER * psbBuffer ) { return(rc4Initialize( pbKey, KeySize, MessageType, KERB_CHECKSUM_MD4, psbBuffer )); }
NTSTATUS NTAPI rc4LmInitialize( IN PUCHAR pbKey, IN ULONG KeySize, IN ULONG MessageType, OUT PCRYPT_STATE_BUFFER * psbBuffer ) { return(rc4Initialize( pbKey, KeySize, MessageType, KERB_CHECKSUM_LM, psbBuffer )); }
#ifndef DONT_SUPPORT_OLD_ETYPES
NTSTATUS NTAPI rc4Plain2Initialize( IN PUCHAR pbKey, IN ULONG KeySize, IN ULONG MessageType, OUT PCRYPT_STATE_BUFFER * psbBuffer ) { return(rc4Initialize( pbKey, KeySize, MessageType, 0, // no checksum
psbBuffer )); }
#endif
NTSTATUS NTAPI rc4Encrypt( IN PCRYPT_STATE_BUFFER psbBuffer, IN PUCHAR pbInput, IN ULONG cbInput, OUT PUCHAR pbOutput, OUT PULONG cbOutput ) { PRC4_STATE_BUFFER StateBuffer = (PRC4_STATE_BUFFER) psbBuffer; PRC4_MDx_HEADER CryptHeader = (PRC4_MDx_HEADER) pbOutput; ULONG Offset = 0;
if (StateBuffer->ChecksumFunction != NULL) { Offset = sizeof(RC4_MDx_HEADER); } RtlMoveMemory( pbOutput + Offset, pbInput, cbInput ); *cbOutput = cbInput + Offset;
RtlZeroMemory( CryptHeader, Offset );
rc4(&StateBuffer->Key, *cbOutput, pbOutput);
return( STATUS_SUCCESS ); }
NTSTATUS NTAPI rc4Decrypt( PCRYPT_STATE_BUFFER psbBuffer, PUCHAR pbInput, ULONG cbInput, PUCHAR pbOutput, PULONG cbOutput) { PRC4_STATE_BUFFER StateBuffer = (PRC4_STATE_BUFFER) psbBuffer; RC4_MDx_HEADER TempHeader; ULONG Offset = 0;
if (*cbOutput < cbInput) { *cbOutput = cbInput; return(STATUS_BUFFER_TOO_SMALL); } RtlCopyMemory( pbOutput, pbInput, cbInput );
rc4(&StateBuffer->Key, cbInput, pbOutput);
if (StateBuffer->ChecksumFunction != NULL) { Offset = sizeof(RC4_MDx_HEADER); }
RtlZeroMemory( &TempHeader, Offset );
if (RtlEqualMemory( &TempHeader, pbOutput, Offset ) != TRUE) { return(STATUS_UNSUCCESSFUL); }
*cbOutput = cbInput - Offset;
RtlMoveMemory( pbOutput, pbOutput + Offset, *cbOutput );
return( STATUS_SUCCESS ); }
NTSTATUS NTAPI rc4Finish( PCRYPT_STATE_BUFFER * psbBuffer) { PRC4_STATE_BUFFER StateBuffer = (PRC4_STATE_BUFFER) *psbBuffer;
if (StateBuffer->ChecksumFunction != NULL) { StateBuffer->ChecksumFunction->Finish(&StateBuffer->ChecksumBuffer); } #ifdef KERNEL_MODE
ExFreePool(*psbBuffer); #else
LocalFree(*psbBuffer); #endif
*psbBuffer = NULL; return(STATUS_SUCCESS); }
NTSTATUS NTAPI rc4HashPassword( IN PSECURITY_STRING Password, IN ULONG Checksum, OUT PUCHAR Key ) { PCHECKSUM_FUNCTION SumFunction; PCHECKSUM_BUFFER Buffer; NTSTATUS Status;
Status = CDLocateCheckSum(Checksum, &SumFunction); if (!NT_SUCCESS(Status)) { return(SEC_E_CHECKSUM_NOT_SUPP); }
Status = SumFunction->Initialize(0, &Buffer); if (!NT_SUCCESS(Status)) { return(Status); }
(void) SumFunction->Sum(Buffer, Password->Length, (PUCHAR) Password->Buffer); (void) SumFunction->Finalize(Buffer, Key); (void) SumFunction->Finish(&Buffer); return(STATUS_SUCCESS); }
NTSTATUS NTAPI rc4Md4HashPassword( PSECURITY_STRING pbPassword, PUCHAR pbKey) { return(rc4HashPassword( pbPassword, KERB_CHECKSUM_MD4, pbKey)); }
NTSTATUS NTAPI rc4LmHashPassword( PSECURITY_STRING pbPassword, PUCHAR pbKey) { return(rc4HashPassword( pbPassword, KERB_CHECKSUM_LM, pbKey)); }
NTSTATUS NTAPI rc4RandomKey( IN ULONG KeyLength, OUT PUCHAR pbKey ) {
CDGenerateRandomBits(pbKey,KeyLength);
return(STATUS_SUCCESS); }
NTSTATUS NTAPI rc4Md4RandomKey( IN OPTIONAL PUCHAR Seed, IN ULONG SeedLength, OUT PUCHAR pbKey ) { memset( pbKey, 0xab, MD4_LEN ); return(rc4RandomKey(5,pbKey)); }
NTSTATUS NTAPI rc4Control( IN ULONG Function, IN PCRYPT_STATE_BUFFER StateBuffer, IN PUCHAR InputBuffer, IN ULONG InputBufferSize ) { UCHAR TempBuffer[128];
PRC4_STATE_BUFFER Rc4StateBuffer = (PRC4_STATE_BUFFER) StateBuffer;
if (Function != CRYPT_CONTROL_SET_INIT_VECT) { return(STATUS_INVALID_PARAMETER); } if (InputBufferSize > sizeof(TempBuffer)) { return(STATUS_INVALID_PARAMETER); }
//
// We set the IV by encrypting the supplied buffer and leaving the
// keystate changed.
//
memcpy( TempBuffer, InputBuffer, InputBufferSize ); rc4(&Rc4StateBuffer->Key, InputBufferSize, TempBuffer );
return(STATUS_SUCCESS); }
//////////////////////////////////////////////////////////////////////////
//
// RC4 HMAC crypt type
//
//////////////////////////////////////////////////////////////////////////
BOOLEAN md5Hmac( IN PUCHAR pbKeyMaterial, IN ULONG cbKeyMaterial, IN PUCHAR pbData, IN ULONG cbData, IN PUCHAR pbData2, IN ULONG cbData2, OUT PUCHAR HmacData ) { BOOLEAN fRet = FALSE; #define HMAC_K_PADSIZE 64
UCHAR Kipad[HMAC_K_PADSIZE]; UCHAR Kopad[HMAC_K_PADSIZE]; UCHAR HMACTmp[HMAC_K_PADSIZE+MD5_LEN]; ULONG dwBlock; MD5_CTX Md5Hash;
// truncate
if (cbKeyMaterial > HMAC_K_PADSIZE) cbKeyMaterial = HMAC_K_PADSIZE;
RtlZeroMemory(Kipad, HMAC_K_PADSIZE); RtlCopyMemory(Kipad, pbKeyMaterial, cbKeyMaterial);
RtlZeroMemory(Kopad, HMAC_K_PADSIZE); RtlCopyMemory(Kopad, pbKeyMaterial, cbKeyMaterial);
//
// Kipad, Kopad are padded sMacKey. Now XOR across...
//
for(dwBlock=0; dwBlock<HMAC_K_PADSIZE/sizeof(ULONG); dwBlock++) { ((ULONG*)Kipad)[dwBlock] ^= 0x36363636; ((ULONG*)Kopad)[dwBlock] ^= 0x5C5C5C5C; }
//
// prepend Kipad to data, Hash to get H1
//
MD5Init(&Md5Hash); MD5Update(&Md5Hash, Kipad, HMAC_K_PADSIZE); if (cbData != 0) { MD5Update(&Md5Hash, pbData, cbData); } if (cbData2 != 0) { MD5Update(&Md5Hash, pbData2, cbData2); }
// Finish off the hash
MD5Final(&Md5Hash);
// prepend Kopad to H1, hash to get HMAC
RtlCopyMemory(HMACTmp, Kopad, HMAC_K_PADSIZE); RtlCopyMemory(HMACTmp+HMAC_K_PADSIZE, Md5Hash.digest, MD5_LEN);
// final hash: output value into passed-in buffer
MD5Init(&Md5Hash); MD5Update(&Md5Hash,HMACTmp, sizeof(HMACTmp)); MD5Final(&Md5Hash); RtlCopyMemory( HmacData, Md5Hash.digest, MD5_LEN );
return TRUE; }
NTSTATUS NTAPI rc4HmacBaseInitializeOld( IN PUCHAR pbKey, IN ULONG KeySize, IN ULONG MessageType, IN BOOLEAN IncludeHmac, IN BOOLEAN Exportable, OUT PCRYPT_STATE_BUFFER * psbBuffer ) { PRC4_HMAC_STATE_BUFFER StateBuffer = NULL; LPSTR Direction = NULL; ULONG DirectionSize = 0; LPSTR Usage = NULL; ULONG UsageSize = 0; ULONG LocalKeySize = 0;
//
// Compute the HMAC pad
//
#ifdef KERNEL_MODE
StateBuffer = ExAllocatePool(NonPagedPool, sizeof(RC4_HMAC_STATE_BUFFER)); #else
StateBuffer = LocalAlloc(0, sizeof(RC4_HMAC_STATE_BUFFER)); #endif
if (StateBuffer == NULL) { return(STATUS_INSUFFICIENT_RESOURCES); }
//
// If the key is not exportable, shrink it first
//
if (!Exportable) { md5Hmac( pbKey, KeySize, (PUCHAR) &MessageType, sizeof(ULONG), NULL, 0, StateBuffer->Key ); LocalKeySize = MD5_LEN; } else { md5Hmac( pbKey, KeySize, "fortybits", sizeof("fortybits"), (PUCHAR) &MessageType, sizeof(ULONG), StateBuffer->Key ); LocalKeySize = 5; // 40 bits
}
//
// Pad exportable keys with 0xababab
//
memset( StateBuffer->Key+LocalKeySize, 0xab, MD5_LEN-LocalKeySize );
StateBuffer->IncludeHmac = IncludeHmac; *psbBuffer = StateBuffer; return(STATUS_SUCCESS); }
NTSTATUS NTAPI rc4HmacInitializeOld( IN PUCHAR pbKey, IN ULONG KeySize, IN ULONG MessageType, OUT PCRYPT_STATE_BUFFER * psbBuffer ) { return(rc4HmacBaseInitializeOld( pbKey, KeySize, MessageType, TRUE, // include hmac
FALSE, // not exportable
psbBuffer )); }
NTSTATUS NTAPI rc4PlainInitializeOld( IN PUCHAR pbKey, IN ULONG KeySize, IN ULONG MessageType, OUT PCRYPT_STATE_BUFFER * psbBuffer ) { return(rc4HmacBaseInitializeOld( pbKey, KeySize, MessageType, FALSE, // no hmac
FALSE, // not exportable
psbBuffer )); }
NTSTATUS NTAPI rc4PlainExpInitializeOld( IN PUCHAR pbKey, IN ULONG KeySize, IN ULONG MessageType, OUT PCRYPT_STATE_BUFFER * psbBuffer ) { return(rc4HmacBaseInitializeOld( pbKey, KeySize, // only use 40 bites
MessageType, FALSE, // no hmac
TRUE, // exportable
psbBuffer )); }
NTSTATUS NTAPI rc4HmacControlOld( IN ULONG Function, IN PCRYPT_STATE_BUFFER StateBuffer, IN PUCHAR InputBuffer, IN ULONG InputBufferSize ) {
PRC4_HMAC_STATE_BUFFER HmacStateBuffer = (PRC4_HMAC_STATE_BUFFER) StateBuffer;
if (Function == CRYPT_CONTROL_SET_INIT_VECT) { md5Hmac( HmacStateBuffer->Key, MD5_LEN, InputBuffer, InputBufferSize, NULL, 0, HmacStateBuffer->Key ); } else { return(STATUS_INVALID_PARAMETER); }
return(STATUS_SUCCESS); }
NTSTATUS NTAPI rc4HmacEncryptOld( IN PCRYPT_STATE_BUFFER psbBuffer, IN PUCHAR pbInput, IN ULONG cbInput, OUT PUCHAR pbOutput, OUT PULONG cbOutput ) { PRC4_HMAC_STATE_BUFFER StateBuffer = (PRC4_HMAC_STATE_BUFFER) psbBuffer; PRC4_MDx_HEADER CryptHeader = (PRC4_MDx_HEADER) pbOutput; ULONG Offset = 0; RC4KEY Rc4Key;
if (StateBuffer->IncludeHmac) { Offset = sizeof(RC4_MDx_HEADER); } else { Offset = 0; } RtlMoveMemory( pbOutput + Offset, pbInput, cbInput ); *cbOutput = cbInput + Offset;
//
// Create the header - the confounder & checksum
//
if (Offset != 0) { RtlZeroMemory( CryptHeader->Checksum, MD4_LEN );
CDGenerateRandomBits( CryptHeader->Confounder, RC4_CONFOUNDER_LEN );
md5Hmac( StateBuffer->Key, MD5_LEN, pbOutput, *cbOutput, NULL, 0, CryptHeader->Checksum ); }
rc4_key( &Rc4Key, MD5_LEN, StateBuffer->Key );
rc4(&Rc4Key, *cbOutput, pbOutput);
return(STATUS_SUCCESS); }
NTSTATUS NTAPI rc4HmacDecryptOld( PCRYPT_STATE_BUFFER psbBuffer, PUCHAR pbInput, ULONG cbInput, PUCHAR pbOutput, PULONG cbOutput) { PRC4_HMAC_STATE_BUFFER StateBuffer = (PRC4_HMAC_STATE_BUFFER) psbBuffer; RC4_MDx_HEADER TempHeader; UCHAR TempChecksum[MD5_LEN]; ULONG Offset = sizeof(RC4_MDx_HEADER); RC4KEY Rc4Key;
if (!StateBuffer->IncludeHmac) { Offset = 0; }
if (cbInput < Offset) { return(STATUS_INVALID_PARAMETER); }
rc4_key( &Rc4Key, MD5_LEN, StateBuffer->Key );
//
// Copy the input to the output before decrypting
//
RtlCopyMemory( &TempHeader, pbInput, Offset );
*cbOutput = cbInput - Offset; RtlMoveMemory( pbOutput, pbInput + Offset, *cbOutput );
//
// Now decrypt the two buffers
//
if (Offset != 0) { rc4( &Rc4Key, Offset, (PUCHAR) &TempHeader ); }
rc4( &Rc4Key, *cbOutput, pbOutput );
//
// Now verify the checksum. First copy it out of the way, zero the
// header
//
if (Offset != 0) {
RtlCopyMemory( TempChecksum, TempHeader.Checksum, MD5_LEN );
RtlZeroMemory( TempHeader.Checksum, MD5_LEN );
md5Hmac( StateBuffer->Key, MD5_LEN, (PUCHAR) &TempHeader, Offset, pbOutput, *cbOutput, TempHeader.Checksum );
if (RtlEqualMemory( TempHeader.Checksum, TempChecksum, MD5_LEN ) != TRUE) { return(STATUS_UNSUCCESSFUL); } }
return(STATUS_SUCCESS); }
NTSTATUS NTAPI rc4HmacFinishOld( PCRYPT_STATE_BUFFER * psbBuffer) { #ifdef KERNEL_MODE
ExFreePool(*psbBuffer); #else
LocalFree(*psbBuffer); #endif
*psbBuffer = NULL; return(STATUS_SUCCESS); }
NTSTATUS NTAPI rc4HmacRandomKeyOld( IN OPTIONAL PUCHAR Seed, IN ULONG SeedLength, OUT PUCHAR pbKey ) { return(rc4RandomKey(MD5_LEN,pbKey)); }
|