Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360/* * PROJECT: ReactOS Drivers * COPYRIGHT: See COPYING in the top level directory * PURPOSE: Kernel Security Support Provider Interface Driver * * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org) */
/* INCLUDES *******************************************************************/
#include "ksecdd.h"
MD5_CTX KsecLoadTimeStartMd5s[2];DES3_KEY KsecGlobalDes3Key;AES_KEY KsecGlobalAesKey;
typedef struct _KSEC_PROCESS_DATA{ PEPROCESS Process; HANDLE ProcessId; LONGLONG CreateTime; ULONG_PTR DirectoryTableBase;} KSEC_PROCESS_DATA, *PKSEC_PROCESS_DATA;
typedef struct _KSEC_LOGON_DATA{ LUID LogonId;} KSEC_LOGON_DATA, *PKSEC_LOGON_DATA;
#if 0void PrintKeyData(PUCHAR KeyData){ ULONG i; for (i = 0; i < 32; i++) { DbgPrint("%02X", KeyData[i]); } DbgPrint("\n");}#endif
VOIDNTAPIKsecInitializeEncryptionSupport ( VOID){ KSEC_ENTROPY_DATA EntropyData; MD5_CTX Md5Context; UCHAR KeyDataBuffer[32];
KsecGatherEntropyData(&EntropyData); MD5Init(&Md5Context); MD5Update(&Md5Context, (PVOID)&EntropyData, sizeof(EntropyData)); KsecLoadTimeStartMd5s[0] = Md5Context; MD5Final(&Md5Context); RtlCopyMemory(KeyDataBuffer, &Md5Context.digest, 16);
KsecGatherEntropyData(&EntropyData); Md5Context = KsecLoadTimeStartMd5s[0]; MD5Update(&Md5Context, (PVOID)&EntropyData, sizeof(EntropyData)); KsecLoadTimeStartMd5s[1] = Md5Context; MD5Final(&Md5Context); RtlCopyMemory(&KeyDataBuffer[16], &Md5Context.digest, 16);
/* Create the global keys */ aes_setup(KeyDataBuffer, 32, 0, &KsecGlobalAesKey); des3_setup(KeyDataBuffer, 24, 0, &KsecGlobalDes3Key);
/* Erase the temp data */ RtlSecureZeroMemory(KeyDataBuffer, sizeof(KeyDataBuffer)); RtlSecureZeroMemory(&Md5Context, sizeof(Md5Context));}
staticVOIDKsecGetKeyData ( _Out_ UCHAR KeyData[32], _In_ ULONG OptionFlags){ MD5_CTX Md5Contexts[2]; KSEC_PROCESS_DATA ProcessData; KSEC_LOGON_DATA LogonData; PEPROCESS CurrentProcess; PACCESS_TOKEN Token;
/* We need to generate the key, start with our load MD5s */ Md5Contexts[0] = KsecLoadTimeStartMd5s[0]; Md5Contexts[1] = KsecLoadTimeStartMd5s[1];
/* Get the current process */ CurrentProcess = PsGetCurrentProcess();
if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_PROCESS) { /* Hash some process specific data to generate the key */ RtlZeroMemory(&ProcessData, sizeof(ProcessData)); ProcessData.Process = CurrentProcess; ProcessData.ProcessId = CurrentProcess->UniqueProcessId; ProcessData.CreateTime = PsGetProcessCreateTimeQuadPart(CurrentProcess); ProcessData.DirectoryTableBase = CurrentProcess->Pcb.DirectoryTableBase[0]; MD5Update(&Md5Contexts[0], (PVOID)&ProcessData, sizeof(ProcessData)); MD5Update(&Md5Contexts[1], (PVOID)&ProcessData, sizeof(ProcessData)); } else if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_LOGON) { /* Hash the logon id to generate the key */ RtlZeroMemory(&LogonData, sizeof(LogonData)); Token = PsReferencePrimaryToken(CurrentProcess); SeQueryAuthenticationIdToken(Token, &LogonData.LogonId); PsDereferencePrimaryToken(Token); MD5Update(&Md5Contexts[0], (PVOID)&LogonData, sizeof(LogonData)); MD5Update(&Md5Contexts[1], (PVOID)&LogonData, sizeof(LogonData)); } else if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS) { /* Use the original MD5s to generate the global key */ NOTHING; } else { /* Must not pass anything else */ ASSERT(FALSE); }
/* Finalize the MD5s */ MD5Final(&Md5Contexts[0]); MD5Final(&Md5Contexts[1]);
/* Copy the md5 data */ RtlCopyMemory(KeyData, &Md5Contexts[0].digest, 16); RtlCopyMemory((PUCHAR)KeyData + 16, &Md5Contexts[1].digest, 16);
/* Erase the temp data */ RtlSecureZeroMemory(&Md5Contexts, sizeof(Md5Contexts));}
staticVOIDKsecGetDes3Key ( _Out_ PDES3_KEY Des3Key, _In_ ULONG OptionFlags){ UCHAR KeyDataBuffer[32];
/* Check if the caller allows cross process encryption */ if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS) { /* Return our global cached DES3 key */ *Des3Key = KsecGlobalDes3Key; } else { /* Setup the key */ KsecGetKeyData(KeyDataBuffer, OptionFlags); des3_setup(KeyDataBuffer, 24, 0, Des3Key);
/* Erase the temp data */ RtlSecureZeroMemory(KeyDataBuffer, sizeof(KeyDataBuffer)); }}
staticVOIDKsecGetAesKey ( _Out_ PAES_KEY AesKey, _In_ ULONG OptionFlags){ UCHAR KeyDataBuffer[32];
/* Check if the caller allows cross process encryption */ if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS) { /* Return our global cached AES key */ *AesKey = KsecGlobalAesKey; } else { /* Setup the key */ KsecGetKeyData(KeyDataBuffer, OptionFlags); aes_setup(KeyDataBuffer, 32, 0, AesKey);
/* Erase the temp data */ RtlSecureZeroMemory(KeyDataBuffer, sizeof(KeyDataBuffer)); }}
staticVOIDKsecEncryptMemoryDes3 ( _Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags){ UCHAR EncryptedBlockData[8]; DES3_KEY Des3Key;
/* Get they triple DES key */ KsecGetDes3Key(&Des3Key, OptionFlags);
/* Do the triple DES encryption */ while (Length >= sizeof(EncryptedBlockData)) { des3_ecb_encrypt(Buffer, EncryptedBlockData, &Des3Key); RtlCopyMemory(Buffer, EncryptedBlockData, sizeof(EncryptedBlockData)); Buffer = (PUCHAR)Buffer + sizeof(EncryptedBlockData); Length -= sizeof(EncryptedBlockData); }
/* Erase the key data */ RtlSecureZeroMemory(&Des3Key, sizeof(Des3Key));}
staticVOIDKsecDecryptMemoryDes3 ( _Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags){ UCHAR BlockData[8]; DES3_KEY Des3Key;
/* Get they triple DES key */ KsecGetDes3Key(&Des3Key, OptionFlags);
/* Do the triple DES decryption */ while (Length >= sizeof(BlockData)) { des3_ecb_decrypt(Buffer, BlockData, &Des3Key); RtlCopyMemory(Buffer, BlockData, sizeof(BlockData)); Buffer = (PUCHAR)Buffer + sizeof(BlockData); Length -= sizeof(BlockData); }
/* Erase the key data */ RtlSecureZeroMemory(&Des3Key, sizeof(Des3Key));}
staticVOIDKsecEncryptMemoryAes ( _Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags){ UCHAR EncryptedBlockData[16]; AES_KEY AesKey;
/* Get they AES key */ KsecGetAesKey(&AesKey, OptionFlags);
/* Do the AES encryption */ while (Length >= sizeof(EncryptedBlockData)) { aes_ecb_encrypt(Buffer, EncryptedBlockData, &AesKey); RtlCopyMemory(Buffer, EncryptedBlockData, sizeof(EncryptedBlockData)); Buffer = (PUCHAR)Buffer + sizeof(EncryptedBlockData); Length -= sizeof(EncryptedBlockData); }
/* Erase the key data */ RtlSecureZeroMemory(&AesKey, sizeof(AesKey));}
staticVOIDKsecDecryptMemoryAes ( _Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags){ UCHAR BlockData[16]; AES_KEY AesKey;
/* Get they AES key */ KsecGetAesKey(&AesKey, OptionFlags);
/* Do the AES decryption */ while (Length >= sizeof(BlockData)) { aes_ecb_decrypt(Buffer, BlockData, &AesKey); RtlCopyMemory(Buffer, BlockData, sizeof(BlockData)); Buffer = (PUCHAR)Buffer + sizeof(BlockData); Length -= sizeof(BlockData); }
/* Erase the key data */ RtlSecureZeroMemory(&AesKey, sizeof(AesKey));}
NTSTATUSNTAPIKsecEncryptMemory ( _Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags){ /* Validate parameter */ if (OptionFlags > RTL_ENCRYPT_OPTION_SAME_LOGON) { return STATUS_INVALID_PARAMETER; }
/* Check if the length is not 16 bytes aligned */ if (Length & 15) { /* Is it at least 8 bytes aligned? */ if (Length & 7) { /* No, we can't deal with it! */ return STATUS_INVALID_PARAMETER; }
/* Use triple DES encryption */ KsecEncryptMemoryDes3(Buffer, Length, OptionFlags); } else { /* Use AES encryption */ KsecEncryptMemoryAes(Buffer, Length, OptionFlags); }
return STATUS_SUCCESS;}
NTSTATUSNTAPIKsecDecryptMemory ( _Inout_ PVOID Buffer, _In_ ULONG Length, _In_ ULONG OptionFlags){ /* Validate parameter */ if (OptionFlags > RTL_ENCRYPT_OPTION_SAME_LOGON) { return STATUS_INVALID_PARAMETER; }
/* Check if the length is not 16 bytes aligned */ if (Length & 15) { /* Is it at least 8 bytes aligned? */ if (Length & 7) { /* No, we can't deal with it! */ return STATUS_INVALID_PARAMETER; }
/* Use triple DES encryption */ KsecDecryptMemoryDes3(Buffer, Length, OptionFlags); } else { /* Use AES encryption */ KsecDecryptMemoryAes(Buffer, Length, OptionFlags); }
return STATUS_SUCCESS;}