diff --git a/reactos/dll/win32/advapi32/CMakeLists.txt b/reactos/dll/win32/advapi32/CMakeLists.txt index 20cbef3e218..45f3fea67e8 100644 --- a/reactos/dll/win32/advapi32/CMakeLists.txt +++ b/reactos/dll/win32/advapi32/CMakeLists.txt @@ -8,6 +8,7 @@ add_definitions(-D_WIN32_WINNT=0x600) include_directories( ${REACTOS_SOURCE_DIR}/include/reactos/idl + ${REACTOS_SOURCE_DIR}/include/reactos/drivers/ksecdd ${REACTOS_SOURCE_DIR}/lib/cryptlib ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/reactos/dll/win32/advapi32/misc/dllmain.c b/reactos/dll/win32/advapi32/misc/dllmain.c index d7e766a4105..7959cc2dd7c 100644 --- a/reactos/dll/win32/advapi32/misc/dllmain.c +++ b/reactos/dll/win32/advapi32/misc/dllmain.c @@ -14,6 +14,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(advapi); extern BOOL RegInitialize(VOID); extern BOOL RegCleanup(VOID); extern VOID UnloadNtMarta(VOID); +extern VOID CloseKsecDdHandle(VOID); BOOL WINAPI @@ -33,6 +34,7 @@ DllMain( CloseLogonLsaHandle(); RegCleanup(); UnloadNtMarta(); + CloseKsecDdHandle(); break; } diff --git a/reactos/dll/win32/advapi32/misc/sysfunc.c b/reactos/dll/win32/advapi32/misc/sysfunc.c index 12713ddc945..45033f095b1 100644 --- a/reactos/dll/win32/advapi32/misc/sysfunc.c +++ b/reactos/dll/win32/advapi32/misc/sysfunc.c @@ -12,10 +12,16 @@ */ #include +#include #include #include #include +/* FIXME: this should be in some shared header */ +#define RTL_ENCRYPT_OPTION_SAME_PROCESS 0 +#define RTL_ENCRYPT_OPTION_CROSS_PROCESS 1 +#define RTL_ENCRYPT_OPTION_SAME_LOGON 2 + static const unsigned char CRYPT_LMhash_Magic[8] = { 'K', 'G', 'S', '!', '@', '#', '$', '%' }; @@ -615,6 +621,93 @@ SystemFunction036(PVOID pbBuffer, ULONG dwLen) return TRUE; } +HANDLE KsecDeviceHandle; + +static +NTSTATUS +KsecOpenDevice() +{ + UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\KsecDD"); + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + HANDLE DeviceHandle; + NTSTATUS Status; + + InitializeObjectAttributes(&ObjectAttributes, + &DeviceName, + 0x18, + NULL, + NULL); + Status = NtOpenFile(&DeviceHandle, + 0x100001, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_SYNCHRONOUS_IO_NONALERT); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + if (InterlockedCompareExchangePointer(&KsecDeviceHandle, DeviceHandle, NULL) != NULL) + { + NtClose(DeviceHandle); + } + + return STATUS_SUCCESS; +} + +VOID +CloseKsecDdHandle(VOID) +{ + /* Check if we already opened a handle to ksecdd */ + if (KsecDeviceHandle != NULL) + { + /* Close it */ + CloseHandle(KsecDeviceHandle); + KsecDeviceHandle = NULL; + } +} + +static +NTSTATUS +KsecDeviceIoControl( + ULONG IoControlCode, + PVOID InputBuffer, + SIZE_T InputBufferLength, + PVOID OutputBuffer, + SIZE_T OutputBufferLength) +{ + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS Status; + + /* Check if we already have a handle */ + if (KsecDeviceHandle == NULL) + { + /* Try to open the device */ + Status = KsecOpenDevice(); + if (!NT_SUCCESS(Status)) + { + //ERR("Failed to open handle to KsecDd driver!\n"); + return Status; + } + } + + /* Call the driver */ + Status = NtDeviceIoControlFile(KsecDeviceHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + IoControlCode, + InputBuffer, + InputBufferLength, + OutputBuffer, + OutputBufferLength); + + return Status; +} + /* These functions have nearly identical prototypes to CryptProtectMemory and CryptUnprotectMemory, in crypt32.dll. @@ -642,10 +735,36 @@ SystemFunction036(PVOID pbBuffer, ULONG dwLen) * If flags are specified when encrypting, the same flag value must be given * when decrypting the memory. */ -NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags) +NTSTATUS +WINAPI +SystemFunction040( + _Inout_ PVOID Memory, + _In_ ULONG MemoryLength, + _In_ ULONG OptionFlags) { + ULONG IoControlCode; + //FIXME("(%p, %x, %x): stub [RtlEncryptMemory]\n", memory, length, flags); return STATUS_SUCCESS; + + if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_PROCESS) + { + IoControlCode = IOCTL_KSEC_ENCRYPT_SAME_PROCESS; + } + else if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS) + { + IoControlCode = IOCTL_KSEC_ENCRYPT_CROSS_PROCESS; + } + else if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_LOGON) + { + IoControlCode = IOCTL_KSEC_ENCRYPT_SAME_LOGON; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + return KsecDeviceIoControl(IoControlCode, Memory, MemoryLength, Memory, MemoryLength); } /****************************************************************************** @@ -670,10 +789,36 @@ NTSTATUS WINAPI SystemFunction040(PVOID memory, ULONG length, ULONG flags) * If flags are specified when encrypting, the same flag value must be given * when decrypting the memory. */ -NTSTATUS WINAPI SystemFunction041(PVOID memory, ULONG length, ULONG flags) +NTSTATUS +WINAPI +SystemFunction041( + _Inout_ PVOID Memory, + _In_ ULONG MemoryLength, + _In_ ULONG OptionFlags) { + ULONG IoControlCode; + //FIXME("(%p, %x, %x): stub [RtlDecryptMemory]\n", memory, length, flags); return STATUS_SUCCESS; + + if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_PROCESS) + { + IoControlCode = IOCTL_KSEC_DECRYPT_SAME_PROCESS; + } + else if (OptionFlags == RTL_ENCRYPT_OPTION_CROSS_PROCESS) + { + IoControlCode = IOCTL_KSEC_DECRYPT_CROSS_PROCESS; + } + else if (OptionFlags == RTL_ENCRYPT_OPTION_SAME_LOGON) + { + IoControlCode = IOCTL_KSEC_DECRYPT_SAME_LOGON; + } + else + { + return STATUS_INVALID_PARAMETER; + } + + return KsecDeviceIoControl(IoControlCode, Memory, MemoryLength, Memory, MemoryLength); } /* EOF */ diff --git a/reactos/drivers/crypto/ksecdd/CMakeLists.txt b/reactos/drivers/crypto/ksecdd/CMakeLists.txt index 790ca1cf705..389f6a3db42 100644 --- a/reactos/drivers/crypto/ksecdd/CMakeLists.txt +++ b/reactos/drivers/crypto/ksecdd/CMakeLists.txt @@ -8,6 +8,7 @@ include_directories( list(APPEND SOURCE ksecdd.c dispatch.c + crypt.c random.c stubs.c ksecdd.rc diff --git a/reactos/drivers/crypto/ksecdd/crypt.c b/reactos/drivers/crypto/ksecdd/crypt.c new file mode 100644 index 00000000000..6e4eda3661f --- /dev/null +++ b/reactos/drivers/crypto/ksecdd/crypt.c @@ -0,0 +1,31 @@ +/* + * 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" + +NTSTATUS +NTAPI +KsecEncryptMemory ( + _Inout_ PVOID Buffer, + _In_ ULONG Length, + _In_ ULONG OptionFlags) +{ + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +KsecDecryptMemory ( + _Inout_ PVOID Buffer, + _In_ ULONG Length, + _In_ ULONG OptionFlags) +{ + return STATUS_SUCCESS; +} diff --git a/reactos/drivers/crypto/ksecdd/dispatch.c b/reactos/drivers/crypto/ksecdd/dispatch.c index 9209bc2ed46..6b6e07449c7 100644 --- a/reactos/drivers/crypto/ksecdd/dispatch.c +++ b/reactos/drivers/crypto/ksecdd/dispatch.c @@ -33,7 +33,7 @@ KsecQueryFileInformation( } /* Validate buffer size */ - if (*BufferLength >= sizeof(FILE_STANDARD_INFORMATION)) + if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION)) { *BufferLength = sizeof(FILE_STANDARD_INFORMATION); return STATUS_INFO_LENGTH_MISMATCH; @@ -92,7 +92,28 @@ KsecDeviceControl( { NTSTATUS Status; - Status = STATUS_SUCCESS; + if ((IoControlCode == IOCTL_KSEC_RANDOM_FILL_BUFFER) || + (IoControlCode == IOCTL_KSEC_ENCRYPT_SAME_PROCESS) || + (IoControlCode == IOCTL_KSEC_DECRYPT_SAME_PROCESS) || + (IoControlCode == IOCTL_KSEC_ENCRYPT_CROSS_PROCESS) || + (IoControlCode == IOCTL_KSEC_DECRYPT_CROSS_PROCESS) || + (IoControlCode == IOCTL_KSEC_ENCRYPT_SAME_LOGON) || + (IoControlCode == IOCTL_KSEC_DECRYPT_SAME_LOGON)) + { + /* Make sure we have a valid output buffer */ + if ((Buffer == NULL) || (OutputLength == NULL)) + { + return STATUS_INVALID_PARAMETER; + } + + /* Check if the input is smaller than the output */ + if (InputLength < *OutputLength) + { + /* We might have uninitialized memory, zero it out */ + RtlSecureZeroMemory((PUCHAR)Buffer + InputLength, + *OutputLength - InputLength); + } + } /* Check ioctl code */ switch (IoControlCode) @@ -107,6 +128,48 @@ KsecDeviceControl( Status = KsecGenRandom(Buffer, *OutputLength); break; + case IOCTL_KSEC_ENCRYPT_SAME_PROCESS: + + Status = KsecEncryptMemory(Buffer, + *OutputLength, + RTL_ENCRYPT_OPTION_SAME_PROCESS); + break; + + case IOCTL_KSEC_DECRYPT_SAME_PROCESS: + + Status = KsecDecryptMemory(Buffer, + *OutputLength, + RTL_ENCRYPT_OPTION_SAME_PROCESS); + break; + + case IOCTL_KSEC_ENCRYPT_CROSS_PROCESS: + + Status = KsecEncryptMemory(Buffer, + *OutputLength, + RTL_ENCRYPT_OPTION_CROSS_PROCESS); + break; + + case IOCTL_KSEC_DECRYPT_CROSS_PROCESS: + + Status = KsecDecryptMemory(Buffer, + *OutputLength, + RTL_ENCRYPT_OPTION_CROSS_PROCESS); + break; + + case IOCTL_KSEC_ENCRYPT_SAME_LOGON: + + Status = KsecEncryptMemory(Buffer, + *OutputLength, + RTL_ENCRYPT_OPTION_SAME_LOGON); + break; + + case IOCTL_KSEC_DECRYPT_SAME_LOGON: + + Status = KsecDecryptMemory(Buffer, + *OutputLength, + RTL_ENCRYPT_OPTION_SAME_LOGON); + break; + default: DPRINT1("Unhandled control code 0x%lx\n", IoControlCode); __debugbreak(); @@ -188,11 +251,31 @@ KsecDdDispatch( case IRP_MJ_DEVICE_CONTROL: /* Extract the parameters */ - Buffer = Irp->AssociatedIrp.SystemBuffer; InputLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength; OutputLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength; IoControlCode = IoStackLocation->Parameters.DeviceIoControl.IoControlCode; + /* Check for METHOD_OUT_DIRECT method */ + if ((METHOD_FROM_CTL_CODE(IoControlCode) == METHOD_OUT_DIRECT) && + (OutputLength != 0)) + { + /* Use the provided MDL */ + OutputLength = Irp->MdlAddress->ByteCount; + Buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, + NormalPagePriority); + if (Buffer == NULL) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + Information = 0; + break; + } + } + else + { + /* Otherwise this is METHOD_BUFFERED, use the SystemBuffer */ + Buffer = Irp->AssociatedIrp.SystemBuffer; + } + /* Call the internal function */ Status = KsecDeviceControl(IoControlCode, Buffer, @@ -205,6 +288,7 @@ KsecDdDispatch( DPRINT1("Unhandled major function %lu!\n", IoStackLocation->MajorFunction); ASSERT(FALSE); + return STATUS_INVALID_DEVICE_REQUEST; } /* Return the information */ diff --git a/reactos/drivers/crypto/ksecdd/ksecdd.h b/reactos/drivers/crypto/ksecdd/ksecdd.h index addcd153456..f15e8cc8d84 100644 --- a/reactos/drivers/crypto/ksecdd/ksecdd.h +++ b/reactos/drivers/crypto/ksecdd/ksecdd.h @@ -9,6 +9,26 @@ #define _NO_KSECDD_IMPORT_ #include #include +#include +#include +#include +#include + +#define STATUS_KSEC_INTERNAL_ERROR ((NTSTATUS)0x80090304) + +/* FIXME: this should be in some shared header */ +#define RTL_ENCRYPT_OPTION_SAME_PROCESS 0 +#define RTL_ENCRYPT_OPTION_CROSS_PROCESS 1 +#define RTL_ENCRYPT_OPTION_SAME_LOGON 2 + +typedef struct _KSEC_CONNECTION_INFO +{ + ULONG Unknown0; + NTSTATUS Status; + ULONG_PTR Information; + CHAR ConnectionString[128]; + ULONG Flags; +} KSEC_CONNECTION_INFO; #if defined(_M_IX86) || defined(_M_AMD64) typedef struct _KSEC_MACHINE_SPECIFIC_COUNTERS @@ -41,6 +61,9 @@ typedef struct _KSEC_ENTROPY_DATA SYSTEM_PROCESS_INFORMATION SystemProcessInformation; } KSEC_ENTROPY_DATA, *PKSEC_ENTROPY_DATA; +extern PEPROCESS KsecLsaProcess;; +extern HANDLE KsecLsaProcessHandle; + NTSTATUS NTAPI KsecDdDispatch( @@ -54,3 +77,37 @@ KsecGenRandom( PVOID Buffer, SIZE_T Length); +NTSTATUS +NTAPI +KsecEncryptMemory ( + _Inout_ PVOID Buffer, + _In_ ULONG Length, + _In_ ULONG OptionFlags); + +NTSTATUS +NTAPI +KsecDecryptMemory ( + _Inout_ PVOID Buffer, + _In_ ULONG Length, + _In_ ULONG OptionFlags); + +NTSTATUS +NTAPI +KsecInitLsaMemory(VOID); + +/// +PVOID +NTAPI +PsGetProcessSecurityPort( + PEPROCESS Process); + +NTSTATUS +NTAPI +PsSetProcessSecurityPort( + PEPROCESS Process, + PVOID SecurityPort); + +HANDLE +NTAPI +PsGetCurrentThreadProcessId(VOID); + diff --git a/reactos/include/reactos/drivers/ksecdd/ksecioctl.h b/reactos/include/reactos/drivers/ksecdd/ksecioctl.h index 004db5a7cd0..957e7a0d758 100644 --- a/reactos/include/reactos/drivers/ksecdd/ksecioctl.h +++ b/reactos/include/reactos/drivers/ksecdd/ksecioctl.h @@ -15,11 +15,11 @@ CTL_CODE(FILE_DEVICE_KSEC, 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS) // 3: 0x39000E - called from SystemFunction040 aka RtlEncryptMemory with OptionFlags == 0 -#define IOCTL_KSEC_ENCRYPT_PROCESS \ +#define IOCTL_KSEC_ENCRYPT_SAME_PROCESS \ CTL_CODE(FILE_DEVICE_KSEC, 0x03, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) // 4: 0x390012 - called from SystemFunction041 aka RtlDecryptMemory with OptionFlags == 0 -#define IOCTL_KSEC_DECRYPT_PROCESS \ +#define IOCTL_KSEC_DECRYPT_SAME_PROCESS \ CTL_CODE(FILE_DEVICE_KSEC, 0x04, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) // 5: 0x390016 - called from SystemFunction040 aka RtlEncryptMemory with OptionFlags == 1