1000 lines
26 KiB
C
1000 lines
26 KiB
C
/*++
|
||
|
||
Copyright (c) 1996 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
efs.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the code that implements the EFS
|
||
file system filter driver.
|
||
|
||
Author:
|
||
|
||
Robert Gu (robertg) 29-Oct-1996
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
#include "efs.h"
|
||
#include "efsrtl.h"
|
||
|
||
|
||
#define BUFFER_SIZE 1024
|
||
#define BUFFER_REG_VAL L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\NTFS\\EFS\\Parameters"
|
||
#define MAX_ALLOC_BUFFER L"MaximumBlob"
|
||
#define EFS_KERNEL_CACHE_PERIOD L"EFSKCACHEPERIOD"
|
||
|
||
//
|
||
// Global storage for this file system filter driver.
|
||
//
|
||
EFS_DATA EfsData;
|
||
WORK_QUEUE_ITEM EfsShutdownCleanupWorkItem;
|
||
|
||
//
|
||
// $EFS stream name
|
||
//
|
||
WCHAR AttrName[5] = L"$EFS";
|
||
|
||
#if DBG
|
||
|
||
ULONG EFSDebug = 0;
|
||
|
||
#endif
|
||
|
||
ENCRYPTION_CALL_BACK EFSCallBackTable = {
|
||
ENCRYPTION_CURRENT_INTERFACE_VERSION,
|
||
ENCRYPTION_ALL_STREAMS,
|
||
EfsOpenFile,
|
||
NULL,
|
||
EFSFilePostCreate,
|
||
EfsFileControl,
|
||
EfsFileControl,
|
||
EFSFsControl,
|
||
EfsRead,
|
||
EfsWrite,
|
||
EfsFreeContext
|
||
};
|
||
|
||
VOID
|
||
EfspShutdownCleanup(
|
||
IN PVOID Parameter
|
||
);
|
||
|
||
//
|
||
// Assign text sections for each routine.
|
||
//
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGE, EfspShutdownCleanup)
|
||
#pragma alloc_text(PAGE, EfsInitialization)
|
||
#pragma alloc_text(PAGE, EfsGetSessionKey)
|
||
#pragma alloc_text(PAGE, GetKeyBlobLength)
|
||
#pragma alloc_text(PAGE, GetKeyBlobBuffer)
|
||
#pragma alloc_text(PAGE, SetKeyTable)
|
||
#pragma alloc_text(PAGE, EfsInitFips)
|
||
#endif
|
||
|
||
|
||
VOID
|
||
EfspShutdownCleanup(
|
||
IN PVOID Parameter
|
||
)
|
||
{
|
||
PEPROCESS LsaProcess;
|
||
|
||
PAGED_CODE();
|
||
|
||
UNREFERENCED_PARAMETER(Parameter);
|
||
|
||
if (EfsData.LsaProcess) {
|
||
LsaProcess = EfsData.LsaProcess;
|
||
EfsData.LsaProcess = NULL;
|
||
ObDereferenceObject(LsaProcess);
|
||
}
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
EfsInitialization(
|
||
void
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the initialization routine for the general purpose file system
|
||
filter driver. This routine creates the device object that represents this
|
||
driver in the system and registers it for watching all file systems that
|
||
register or unregister themselves as active file systems.
|
||
|
||
Arguments:
|
||
|
||
DriverObject - Pointer to driver object created by the system.
|
||
|
||
Return Value:
|
||
|
||
The function value is the final status from the initialization operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
UNICODE_STRING nameString;
|
||
PDEVICE_EXTENSION deviceExtension;
|
||
PFILE_OBJECT fileObject;
|
||
NTSTATUS status;
|
||
HANDLE threadHdl;
|
||
ULONG i;
|
||
OBJECT_ATTRIBUTES objAttr;
|
||
UNICODE_STRING efsInitEventName;
|
||
UNICODE_STRING efsBufValue;
|
||
ULONG resultLength;
|
||
PKEY_VALUE_PARTIAL_INFORMATION pPartialValue = NULL;
|
||
HANDLE efsKey;
|
||
EFS_INIT_DATAEXG InitDataFromSrv;
|
||
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// Mark our global data record
|
||
//
|
||
|
||
EfsData.AllocMaxBuffer = FALSE;
|
||
EfsData.FipsFileObject = NULL;
|
||
EfsData.FipsFunctionTable.Fips3Des = NULL;
|
||
EfsData.FipsFunctionTable.Fips3Des3Key = NULL;
|
||
EfsData.EfsDriverCacheLength = DefaultTimeExpirePeriod;
|
||
|
||
RtlInitUnicodeString( &efsBufValue, BUFFER_REG_VAL );
|
||
|
||
InitializeObjectAttributes(
|
||
&objAttr,
|
||
&efsBufValue,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
status = ZwOpenKey(
|
||
&efsKey,
|
||
KEY_READ,
|
||
&objAttr);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
pPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePool(NonPagedPool, BUFFER_SIZE);
|
||
if (pPartialValue) {
|
||
RtlInitUnicodeString(&efsBufValue, MAX_ALLOC_BUFFER);
|
||
|
||
status = ZwQueryValueKey(
|
||
efsKey,
|
||
&efsBufValue,
|
||
KeyValuePartialInformation,
|
||
(PVOID)pPartialValue,
|
||
BUFFER_SIZE,
|
||
&resultLength
|
||
);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
ASSERT(pPartialValue->Type == REG_DWORD);
|
||
if (*((PLONG)&(pPartialValue->Data))){
|
||
EfsData.AllocMaxBuffer = TRUE;
|
||
}
|
||
}
|
||
|
||
RtlInitUnicodeString(&efsBufValue, EFS_KERNEL_CACHE_PERIOD);
|
||
|
||
status = ZwQueryValueKey(
|
||
efsKey,
|
||
&efsBufValue,
|
||
KeyValuePartialInformation,
|
||
(PVOID)pPartialValue,
|
||
BUFFER_SIZE,
|
||
&resultLength
|
||
);
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
ASSERT(pPartialValue->Type == REG_DWORD);
|
||
if (((*((DWORD *)&(pPartialValue->Data))) >= MINCACHEPERIOD) &&
|
||
((*((DWORD *)&(pPartialValue->Data))) <= MAXCACHEPERIOD)){
|
||
EfsData.EfsDriverCacheLength = *((DWORD *)&(pPartialValue->Data));
|
||
EfsData.EfsDriverCacheLength *= 10000000;
|
||
}
|
||
}
|
||
ExFreePool(pPartialValue);
|
||
}
|
||
ZwClose(efsKey);
|
||
}
|
||
|
||
EfsData.NodeTypeCode = EFS_NTC_DATA_HEADER;
|
||
EfsData.NodeByteSize = sizeof( EFS_DATA );
|
||
EfsData.EfsInitialized = FALSE;
|
||
EfsData.InitEventHandle = NULL;
|
||
EfsData.LsaProcess = NULL;
|
||
|
||
//
|
||
// Initialize global data structures.
|
||
//
|
||
|
||
ExInitializeWorkItem( &EfsShutdownCleanupWorkItem,
|
||
&EfspShutdownCleanup,
|
||
NULL );
|
||
status = PoQueueShutdownWorkItem( &EfsShutdownCleanupWorkItem );
|
||
if (!NT_SUCCESS(status)) {
|
||
return status;
|
||
}
|
||
|
||
InitializeListHead( &(EfsData.EfsOpenCacheList) );
|
||
InitializeListHead( &(EfsData.EfsKeyLookAsideList) );
|
||
ExInitializeFastMutex( &(EfsData.EfsKeyBlobMemSrcMutex) );
|
||
ExInitializeFastMutex( &(EfsData.EfsOpenCacheMutex) );
|
||
|
||
//
|
||
// Initialize the event lookaside list
|
||
//
|
||
|
||
ExInitializeNPagedLookasideList(&(EfsData.EfsEventPool),
|
||
NULL,
|
||
NULL,
|
||
0,
|
||
sizeof(KEVENT),
|
||
'levE',
|
||
EFS_EVENTDEPTH
|
||
);
|
||
|
||
//
|
||
// Try to allocate at least one event in the list. This one will be used for
|
||
// sure later.
|
||
//
|
||
|
||
{
|
||
PVOID pTryEvent;
|
||
|
||
pTryEvent = ExAllocateFromNPagedLookasideList(&(EfsData.EfsEventPool));
|
||
if ( NULL == pTryEvent ){
|
||
//
|
||
// Free previously allocated memory
|
||
//
|
||
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsEventPool));
|
||
return STATUS_NO_MEMORY;
|
||
}
|
||
ExFreeToNPagedLookasideList(&(EfsData.EfsEventPool), pTryEvent);
|
||
}
|
||
|
||
//
|
||
// Initialize the context lookaside list
|
||
//
|
||
|
||
ExInitializeNPagedLookasideList(&(EfsData.EfsContextPool),
|
||
NULL,
|
||
NULL,
|
||
0,
|
||
sizeof(EFS_CONTEXT),
|
||
'nocE',
|
||
EFS_CONTEXTDEPTH
|
||
);
|
||
|
||
//
|
||
// Initialize the cache lookaside list
|
||
//
|
||
|
||
ExInitializePagedLookasideList(&(EfsData.EfsOpenCachePool),
|
||
NULL,
|
||
NULL,
|
||
0,
|
||
sizeof(OPEN_CACHE),
|
||
'hcoE',
|
||
EFS_CACHEDEPTH
|
||
);
|
||
|
||
ExInitializePagedLookasideList(&(EfsData.EfsMemSourceItem),
|
||
NULL,
|
||
NULL,
|
||
0,
|
||
sizeof(KEY_BLOB_RAMPOOL),
|
||
'msfE',
|
||
EFS_ALGDEPTH
|
||
);
|
||
|
||
ExInitializeNPagedLookasideList(&(EfsData.EfsLookAside),
|
||
NULL,
|
||
NULL,
|
||
0,
|
||
sizeof(NPAGED_LOOKASIDE_LIST),
|
||
'msfE',
|
||
EFS_ALGDEPTH
|
||
);
|
||
|
||
status = NtOfsRegisterCallBacks( Encryption, &EFSCallBackTable );
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
//
|
||
// Register callback failed
|
||
//
|
||
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsEventPool));
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsContextPool));
|
||
ExDeletePagedLookasideList(&(EfsData.EfsOpenCachePool));
|
||
ExDeletePagedLookasideList(&(EfsData.EfsMemSourceItem));
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsLookAside));
|
||
return status;
|
||
}
|
||
|
||
RtlInitUnicodeString(&(EfsData.EfsName), &AttrName[0]);
|
||
|
||
//
|
||
// Create an event
|
||
//
|
||
|
||
RtlInitUnicodeString( &efsInitEventName, L"\\EFSInitEvent" );
|
||
|
||
InitializeObjectAttributes(
|
||
&objAttr,
|
||
&efsInitEventName,
|
||
0,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
//
|
||
// Try to create an event. If the event was not created, the EFS
|
||
// server is not loaded yet. We will create a thread waiting for
|
||
// EFS server to be loaded. If the event was already created, we
|
||
// will just go ahead and get the session key from the EFS server.
|
||
//
|
||
|
||
status = ZwCreateEvent(
|
||
&(EfsData.InitEventHandle),
|
||
EVENT_MODIFY_STATE,
|
||
&objAttr,
|
||
NotificationEvent,
|
||
FALSE
|
||
);
|
||
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
if ( STATUS_OBJECT_NAME_COLLISION == status ){
|
||
|
||
//
|
||
// EFS server has been loaded. This is the normal case.
|
||
// Call server to get the session key.
|
||
//
|
||
|
||
status = GenerateSessionKey(
|
||
&InitDataFromSrv
|
||
);
|
||
|
||
|
||
if (NT_SUCCESS( status )) {
|
||
|
||
//
|
||
// Set session key
|
||
//
|
||
|
||
RtlCopyMemory( &(EfsData.SessionKey[0]), InitDataFromSrv.Key, DES_KEYSIZE );
|
||
deskey( (DESTable*)&(EfsData.SessionDesTable[0]),
|
||
&(EfsData.SessionKey[0]));
|
||
|
||
status = PsLookupProcessByProcessId(
|
||
InitDataFromSrv.LsaProcessID,
|
||
&(EfsData.LsaProcess)
|
||
);
|
||
|
||
if (NT_SUCCESS( status )) {
|
||
EfsData.EfsInitialized = TRUE;
|
||
if ( PsGetCurrentProcess() != EfsData.LsaProcess ){
|
||
|
||
KAPC_STATE ApcState;
|
||
|
||
KeStackAttachProcess (
|
||
EfsData.LsaProcess,
|
||
&ApcState
|
||
);
|
||
InitSecurityInterface();
|
||
KeUnstackDetachProcess(&ApcState);
|
||
} else {
|
||
InitSecurityInterface();
|
||
}
|
||
EfsInitFips();
|
||
} else {
|
||
#if DBG
|
||
|
||
if ( (EFSTRACEALL | EFSTRACELIGHT) & EFSDebug ){
|
||
|
||
DbgPrint("PsLookupProcessByProcessId failed, status = %x\n",status);
|
||
|
||
}
|
||
|
||
#endif
|
||
//
|
||
// Failed to get the process pointer
|
||
//
|
||
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsEventPool));
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsContextPool));
|
||
ExDeletePagedLookasideList(&(EfsData.EfsOpenCachePool));
|
||
ExDeletePagedLookasideList(&(EfsData.EfsMemSourceItem));
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsLookAside));
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
#if DBG
|
||
|
||
if ( (EFSTRACEALL | EFSTRACELIGHT) & EFSDebug ){
|
||
|
||
DbgPrint("GenerateSessionKey failed, status = %x\n",status);
|
||
|
||
}
|
||
|
||
#endif
|
||
//
|
||
// Failed to get the session key
|
||
//
|
||
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsEventPool));
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsContextPool));
|
||
ExDeletePagedLookasideList(&(EfsData.EfsOpenCachePool));
|
||
ExDeletePagedLookasideList(&(EfsData.EfsMemSourceItem));
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsLookAside));
|
||
|
||
}
|
||
|
||
|
||
} else {
|
||
|
||
//
|
||
// Unexpected error occured. EFS cannot be loaded
|
||
//
|
||
|
||
#if DBG
|
||
|
||
if ( (EFSTRACEALL | EFSTRACELIGHT ) & EFSDebug ){
|
||
DbgPrint("EFSFILTER: Efs init event creation failed.%x\n", status);
|
||
}
|
||
|
||
#endif
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsEventPool));
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsContextPool));
|
||
ExDeletePagedLookasideList(&(EfsData.EfsOpenCachePool));
|
||
ExDeletePagedLookasideList(&(EfsData.EfsMemSourceItem));
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsLookAside));
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// The server is not ready yet.
|
||
// Create a thread and wait for the server in that thread
|
||
//
|
||
|
||
status = PsCreateSystemThread(
|
||
&threadHdl,
|
||
GENERIC_ALL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
EfsGetSessionKey,
|
||
NULL
|
||
);
|
||
|
||
if ( NT_SUCCESS( status ) ){
|
||
|
||
ZwClose( threadHdl );
|
||
|
||
} else {
|
||
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsEventPool));
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsContextPool));
|
||
ExDeletePagedLookasideList(&(EfsData.EfsOpenCachePool));
|
||
ExDeletePagedLookasideList(&(EfsData.EfsMemSourceItem));
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsLookAside));
|
||
|
||
}
|
||
}
|
||
|
||
return status;
|
||
}
|
||
|
||
VOID
|
||
EfsUninitialization(
|
||
VOID
|
||
)
|
||
{
|
||
PLIST_ENTRY pLink;
|
||
PKEY_BLOB_RAMPOOL pTmpItem;
|
||
PNPAGED_LOOKASIDE_LIST MemSrcList;
|
||
|
||
while (!IsListEmpty (&EfsData.EfsKeyLookAsideList)) {
|
||
pLink = RemoveHeadList (&EfsData.EfsKeyLookAsideList);
|
||
pTmpItem = CONTAINING_RECORD(pLink, KEY_BLOB_RAMPOOL, MemSourceChain);
|
||
MemSrcList = pTmpItem->MemSourceList;
|
||
|
||
ExDeleteNPagedLookasideList(MemSrcList);
|
||
ExFreeToNPagedLookasideList(&(EfsData.EfsLookAside), MemSrcList );
|
||
ExFreeToPagedLookasideList(&(EfsData.EfsMemSourceItem), pTmpItem );
|
||
}
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsEventPool));
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsContextPool));
|
||
ExDeletePagedLookasideList(&(EfsData.EfsOpenCachePool));
|
||
ExDeletePagedLookasideList(&(EfsData.EfsMemSourceItem));
|
||
ExDeleteNPagedLookasideList(&(EfsData.EfsLookAside));
|
||
if (EfsData.FipsFileObject) {
|
||
ObDereferenceObject(EfsData.FipsFileObject);
|
||
EfsData.FipsFileObject = NULL;
|
||
}
|
||
}
|
||
|
||
VOID
|
||
EfsGetSessionKey(
|
||
IN PVOID StartContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is invoked in DriverEntry. It runs in a seperate thread.
|
||
|
||
The purpose of this routine is to wait for the EFS server. And Get the session key.
|
||
|
||
Arguments:
|
||
|
||
StartContext - Start context of the thread.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
SECURITY_DESCRIPTOR efsInitEventSecurityDescriptor;
|
||
NTSTATUS status;
|
||
EFS_INIT_DATAEXG InitDataFromSrv;
|
||
|
||
#if DBG
|
||
|
||
if ( EFSTRACEALL & EFSDebug ){
|
||
DbgPrint( "EFSFILTER: Thread started. %x\n", EfsData.NodeTypeCode );
|
||
}
|
||
|
||
#endif
|
||
|
||
#if 0
|
||
//
|
||
// Prepare to create an event for synchronizing with the Efs.
|
||
// First, build the Security Descriptor for the Init Event Object
|
||
//
|
||
|
||
status = RtlCreateSecurityDescriptor(
|
||
&efsInitEventSecurityDescriptor,
|
||
SECURITY_DESCRIPTOR_REVISION
|
||
);
|
||
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
#if DBG
|
||
DbgPrint(("EFSFILTER: Creating Efs Init Event Desc failed 0x%lx\n",
|
||
status));
|
||
#endif
|
||
|
||
return ;
|
||
}
|
||
|
||
//
|
||
// Allocate a temporary buffer from the paged pool. It is a fatal
|
||
// system error if the allocation fails since security cannot be
|
||
// enabled.
|
||
//
|
||
|
||
aclSize = sizeof(ACL) +
|
||
sizeof(ACCESS_ALLOWED_ACE) +
|
||
RtlLengthSid(SeLocalSystemSid);
|
||
|
||
efsInitEventSecurityDescriptor.Dacl =
|
||
ExAllocatePoolWithTag(PagedPool, aclSize, 'cAeS');
|
||
|
||
if (efsInitEventSecurityDescriptor.Dacl == NULL) {
|
||
|
||
#if DBG
|
||
DbgPrint(("EFSFILTER: Insufficient resources to initialize\n"));
|
||
#endif
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Now create the Discretionary ACL within the Security Descriptor
|
||
//
|
||
|
||
status = RtlCreateAcl(
|
||
efsInitEventSecurityDescriptor.Dacl,
|
||
aclSize,
|
||
ACL_REVISION2
|
||
);
|
||
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
#if DBG
|
||
DbgPrint(("EFSFILTER: Creating Efs Init Event Dacl failed 0x%lx\n",
|
||
status));
|
||
#endif
|
||
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Now add an ACE giving GENERIC_ALL access to the User ID
|
||
//
|
||
|
||
status = RtlAddAccessAllowedAce(
|
||
efsInitEventSecurityDescriptor.Dacl,
|
||
ACL_REVISION2,
|
||
GENERIC_ALL,
|
||
SeLocalSystemSid
|
||
);
|
||
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
#if DBG
|
||
DbgPrint(("EFSFILTER: Adding Efs Init Event ACE failed 0x%lx\n",
|
||
status));
|
||
#endif
|
||
|
||
return;
|
||
}
|
||
|
||
#endif // #if 0
|
||
|
||
|
||
status = ZwWaitForSingleObject (
|
||
EfsData.InitEventHandle,
|
||
FALSE,
|
||
(PLARGE_INTEGER)NULL
|
||
);
|
||
|
||
ZwClose( EfsData.InitEventHandle );
|
||
|
||
//
|
||
// Call server to get the session key
|
||
//
|
||
|
||
|
||
status = GenerateSessionKey(
|
||
&InitDataFromSrv
|
||
);
|
||
|
||
|
||
if (!NT_SUCCESS( status )) {
|
||
|
||
#if DBG
|
||
|
||
if ( (EFSTRACEALL | EFSTRACELIGHT) & EFSDebug ){
|
||
|
||
DbgPrint("GenerateSessionKey failed, status = %x\n",status);
|
||
|
||
}
|
||
|
||
#endif
|
||
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Set session key
|
||
//
|
||
|
||
RtlCopyMemory( &(EfsData.SessionKey[0]), InitDataFromSrv.Key, DES_KEYSIZE );
|
||
deskey( (DESTable*)&(EfsData.SessionDesTable[0]),
|
||
&(EfsData.SessionKey[0]));
|
||
|
||
status = PsLookupProcessByProcessId(
|
||
InitDataFromSrv.LsaProcessID,
|
||
&(EfsData.LsaProcess)
|
||
);
|
||
|
||
if (NT_SUCCESS( status )) {
|
||
|
||
EfsData.EfsInitialized = TRUE;
|
||
if ( PsGetCurrentProcess() != EfsData.LsaProcess ){
|
||
KAPC_STATE ApcState;
|
||
|
||
//KeAttachProcess(EfsData.LsaProcess);
|
||
KeStackAttachProcess (
|
||
EfsData.LsaProcess,
|
||
&ApcState
|
||
);
|
||
InitSecurityInterface();
|
||
//KeDetachProcess();
|
||
KeUnstackDetachProcess(&ApcState);
|
||
} else {
|
||
InitSecurityInterface();
|
||
}
|
||
|
||
EfsInitFips();
|
||
|
||
} else {
|
||
|
||
#if DBG
|
||
|
||
if ( (EFSTRACEALL | EFSTRACELIGHT) & EFSDebug ){
|
||
|
||
DbgPrint("PsLookupProcessByProcessId failed, status = %x\n",status);
|
||
|
||
}
|
||
|
||
#endif
|
||
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
ULONG GetKeyBlobLength(
|
||
ULONG AlgID
|
||
)
|
||
{
|
||
if (EfsData.AllocMaxBuffer) {
|
||
return AES_KEY_BLOB_LENGTH_256;
|
||
}
|
||
switch (AlgID){
|
||
case CALG_DESX:
|
||
return DESX_KEY_BLOB_LENGTH;
|
||
case CALG_3DES:
|
||
return DES3_KEY_BLOB_LENGTH;
|
||
case CALG_AES_256:
|
||
return AES_KEY_BLOB_LENGTH_256;
|
||
case CALG_DES:
|
||
default:
|
||
return DES_KEY_BLOB_LENGTH;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
PKEY_BLOB
|
||
GetKeyBlobBuffer(
|
||
ULONG AlgID
|
||
)
|
||
{
|
||
|
||
PNPAGED_LOOKASIDE_LIST MemSrcList = NULL;
|
||
PKEY_BLOB_RAMPOOL KeyBlobPoolListItem = NULL;
|
||
PKEY_BLOB_RAMPOOL pTmpItem = NULL;
|
||
ULONG KeyBlobLength;
|
||
PLIST_ENTRY pLink = NULL;
|
||
PKEY_BLOB NewKeyBlob;
|
||
|
||
KeyBlobLength = GetKeyBlobLength(AlgID);
|
||
|
||
if (!KeyBlobLength){
|
||
ASSERT(KeyBlobLength);
|
||
return NULL;
|
||
}
|
||
|
||
ExAcquireFastMutex( &(EfsData.EfsKeyBlobMemSrcMutex));
|
||
for (pLink = EfsData.EfsKeyLookAsideList.Flink; pLink != &(EfsData.EfsKeyLookAsideList); pLink = pLink->Flink) {
|
||
pTmpItem = CONTAINING_RECORD(pLink, KEY_BLOB_RAMPOOL, MemSourceChain);
|
||
if (pTmpItem->AlgorithmID == AlgID) {
|
||
|
||
//
|
||
// The lookaside list already exists
|
||
//
|
||
|
||
MemSrcList = pTmpItem->MemSourceList;
|
||
break;
|
||
}
|
||
}
|
||
ExReleaseFastMutex( &(EfsData.EfsKeyBlobMemSrcMutex) );
|
||
|
||
if ( MemSrcList == NULL ) {
|
||
|
||
//
|
||
// No lookaside for this type of key. Go and create one item.
|
||
//
|
||
|
||
MemSrcList = (PNPAGED_LOOKASIDE_LIST)ExAllocateFromNPagedLookasideList(&(EfsData.EfsLookAside));
|
||
KeyBlobPoolListItem = (PKEY_BLOB_RAMPOOL) ExAllocateFromPagedLookasideList(&(EfsData.EfsMemSourceItem));
|
||
if ( (NULL == MemSrcList) || (NULL == KeyBlobPoolListItem) ){
|
||
if (MemSrcList) {
|
||
ExFreeToNPagedLookasideList(&(EfsData.EfsLookAside), MemSrcList );
|
||
}
|
||
if (KeyBlobPoolListItem){
|
||
ExFreeToPagedLookasideList(&(EfsData.EfsMemSourceItem), KeyBlobPoolListItem );
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
RtlZeroMemory( KeyBlobPoolListItem, sizeof( KEY_BLOB_RAMPOOL ) );
|
||
KeyBlobPoolListItem->MemSourceList = MemSrcList;
|
||
KeyBlobPoolListItem->AlgorithmID = AlgID;
|
||
|
||
ExInitializeNPagedLookasideList(
|
||
MemSrcList,
|
||
NULL,
|
||
NULL,
|
||
0,
|
||
KeyBlobLength,
|
||
'msfE',
|
||
EFS_KEYDEPTH
|
||
);
|
||
|
||
ExAcquireFastMutex( &(EfsData.EfsKeyBlobMemSrcMutex));
|
||
InsertHeadList( &(EfsData.EfsKeyLookAsideList), &(KeyBlobPoolListItem->MemSourceChain));
|
||
ExReleaseFastMutex( &(EfsData.EfsKeyBlobMemSrcMutex) );
|
||
}
|
||
|
||
//
|
||
// Allocate the Key Blob
|
||
//
|
||
|
||
NewKeyBlob = (PKEY_BLOB)ExAllocateFromNPagedLookasideList(MemSrcList);
|
||
|
||
if (NewKeyBlob){
|
||
NewKeyBlob->AlgorithmID = AlgID;
|
||
NewKeyBlob->KeyLength = KeyBlobLength;
|
||
NewKeyBlob->MemSource = MemSrcList;
|
||
}
|
||
return NewKeyBlob;
|
||
|
||
}
|
||
|
||
BOOLEAN
|
||
SetKeyTable(
|
||
PKEY_BLOB KeyBlob,
|
||
PEFS_KEY EfsKey
|
||
)
|
||
{
|
||
|
||
char DesXTmpKey[DESX_KEYSIZE];
|
||
|
||
switch ( EfsKey->Algorithm ){
|
||
case CALG_3DES:
|
||
if (EfsData.AllocMaxBuffer) {
|
||
RtlZeroMemory( &(KeyBlob->Key[0]) + DES3_TABLESIZE, KeyBlob->KeyLength - DES3_KEY_BLOB_LENGTH);
|
||
}
|
||
if (EfsData.FipsFunctionTable.Fips3Des3Key) {
|
||
EfsData.FipsFunctionTable.Fips3Des3Key(
|
||
(DES3TABLE*) &(KeyBlob->Key[0]),
|
||
((char *)EfsKey) + sizeof ( EFS_KEY )
|
||
);
|
||
} else {
|
||
return FALSE;
|
||
}
|
||
//tripledes3key(
|
||
// (DES3TABLE*) &(KeyBlob->Key[0]),
|
||
// ((char *)EfsKey) + sizeof ( EFS_KEY )
|
||
// );
|
||
break;
|
||
case CALG_DESX:
|
||
//
|
||
// Flush the non used area.
|
||
//
|
||
|
||
if (EfsData.AllocMaxBuffer) {
|
||
RtlZeroMemory( &(KeyBlob->Key[0]) + DESX_TABLESIZE, KeyBlob->KeyLength - DESX_KEY_BLOB_LENGTH);
|
||
}
|
||
desexpand128to192(
|
||
((char *)EfsKey) + sizeof ( EFS_KEY ),
|
||
DesXTmpKey
|
||
);
|
||
|
||
desxkey(
|
||
(DESXTable*) &(KeyBlob->Key[0]),
|
||
DesXTmpKey
|
||
);
|
||
break;
|
||
|
||
case CALG_AES_256:
|
||
aeskey(
|
||
(AESTable*) &(KeyBlob->Key[0]),
|
||
((char *)EfsKey) + sizeof ( EFS_KEY ),
|
||
AES_ROUNDS_256
|
||
);
|
||
break;
|
||
|
||
case CALG_DES:
|
||
default:
|
||
if (EfsData.AllocMaxBuffer) {
|
||
RtlZeroMemory( &(KeyBlob->Key[0]) + DES_TABLESIZE, KeyBlob->KeyLength - DES_KEY_BLOB_LENGTH);
|
||
}
|
||
deskey(
|
||
(DESTable*) &(KeyBlob->Key[0]),
|
||
((char *)EfsKey) + sizeof ( EFS_KEY )
|
||
);
|
||
break;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
EfsInitFips(VOID)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Initialize the FIPS library table.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
TRUE/FALSE.
|
||
|
||
--*/
|
||
{
|
||
UNICODE_STRING deviceName;
|
||
NTSTATUS status;
|
||
PDEVICE_OBJECT pDeviceObject;
|
||
// PFILE_OBJECT pFileObject = NULL;
|
||
PIRP pIrp;
|
||
IO_STATUS_BLOCK IoStatusBlock;
|
||
|
||
PAGED_CODE();
|
||
|
||
RtlInitUnicodeString(&deviceName, FIPS_DEVICE_NAME);
|
||
|
||
//
|
||
// Get the file and device objects for FIPS.
|
||
//
|
||
|
||
status = IoGetDeviceObjectPointer( &deviceName,
|
||
FILE_ALL_ACCESS,
|
||
&EfsData.FipsFileObject,
|
||
&pDeviceObject);
|
||
|
||
if (status != STATUS_SUCCESS) {
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Build the request to send to FIPS to get library table.
|
||
//
|
||
pIrp = IoBuildDeviceIoControlRequest( IOCTL_FIPS_GET_FUNCTION_TABLE,
|
||
pDeviceObject,
|
||
NULL,
|
||
0,
|
||
&EfsData.FipsFunctionTable,
|
||
sizeof(FIPS_FUNCTION_TABLE),
|
||
FALSE,
|
||
NULL,
|
||
&IoStatusBlock
|
||
);
|
||
|
||
if (pIrp == NULL) {
|
||
#if DBG
|
||
DbgPrint("EfsInitFips: IoBuildDeviceIoControlRequest IOCTL_FIPS_GET_FUNCTION_TABLE failed.\n");
|
||
#endif
|
||
ObDereferenceObject(EfsData.FipsFileObject);
|
||
EfsData.FipsFileObject = NULL;
|
||
return FALSE;
|
||
}
|
||
|
||
status = IoCallDriver(pDeviceObject, pIrp);
|
||
|
||
if (status != STATUS_SUCCESS) {
|
||
ObDereferenceObject(EfsData.FipsFileObject);
|
||
EfsData.FipsFileObject = NULL;
|
||
#if DBG
|
||
DbgPrint("EfsInitFips: IoCallDriver failed, status = %x\n",status);
|
||
#endif
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|