Re: data not decrypted correctly in Read completion routine of filter driver

For LOCAL access (i.e. access to a local disk), it is sufficient to do
encryption/decryption for non cached access only.
For NETWORK, you have to handle ALL I/O - and make it non cached. Network file
access does not require sector size aligned offset and lengths, so it is
sufficient to say Irp->Flags |= IRP_NOCACHE.
You need not handle fast I/O for local (you can ignore it, and let it though),
but must handle it for network access - or fail it which will result in read/write
IRPs to be generated.

zhangbo wrote:

Thx for your kind reply.

sorry I didn’t consider the cached I/O, non-cached I/O and paging I/O in
the previous source code. I have re-read the OSR FAQ. My main goal is to
do encryption/decryption when *.DWG files are read_from/written_to local
disk or network shares.

Now my questions are:

  1. Shall I only deal with non-cached I/O AND paging I/O?
  2. Shall I also do encryption/decryption in FastIO?

The function IsProcessNameMatched() is to match AutoCAD process
name(acad.exe). It should be removed according to your comments.

> There are some details that are not clear in your description:
> - Do you preform encryption/decryption only for NonCached read/write? If you
> perform encryption for both Cached and NonCached IO you may end up
> encrypting/decripting some data twice. You will have also encrypted data in
> cache, so applications that use memory mapped file will see encrypted data.
> You do not filter FastIO that will return data excatly as it is in cache.
> Generally it is good idea to always have plian data in cache and encrypted
> data on disk.
> - What does IsProcessNameMatched() do? PagingIO may come in the context of
> system process, not in the context of application. If you don’t want some
> applications to access data it is better to deny access during create
> instead of failing to perfrom encryption/decryption.
>
> Alexei.
>
> “zhangbo” wrote in message news:xxxxx@ntfsd…
> > >
> > > Hi,
> > >
> > > I have written a testing-purpose filter driver based on FileMon. It
> > > decrypts/encrypts *.DWG files only when AutoCAD(acad.exe) accesses them.
> > > It doesn’t change file size.
> > >
> > > I track the DWG files using FileObj->FsContext. After IRP_MJ_CREATE
> > > succeeds, add it to tracking structure, while after IRP_MJ_CLOSE, decrease
> > > the reference count. Decrypt the data in-place after IRP_MJ_READ and
> > > encrypt the data using my own IRP before IRP_MJ_WRITE is passed down to
> > > lower driver.
> > >
> > > But AutoCAD still says “Corrupt file” when it tries to open an DWG
> > > file(This file is already encrypted with a little tool before my driver
> > > starts).
> > >
> > > Did I miss sth.? I post the source. Hope gurus can help me out. Thx!
> > >
> > > //------------------------------------------------------------------------
> > > //procedure for IRP_MJ_READ
> > > NTSTATUS CheckReadIRP(PDEVICE_OBJECT HookDevice, IN PIRP Irp)
> > > {
> > > PMDL ReadBufferMdl;
> > >
> > > currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
> > > nextIrpStack = IoGetNextIrpStackLocation(Irp);
> > >
> > > fileObject = currentIrpStack->FileObject;
> > >
> > > hookExt = HookDevice->DeviceExtension;
> > >
> > > if (! fileObject)
> > > {
> > > goto PassThrough;
> > > }
> > >
> > > if(!(hookExt->Hooked) || !ProcessNameOffset)
> > > {
> > > goto PassThrough;
> > > }
> > >
> > > if (! IsProcessNameMatched())
> > > {
> > > goto PassThrough;
> > > }
> > >
> > >
> > > //Check the tracking structure
> > > if (! IsFileObjInTrackList(fileObject) || ! FilterOn)
> > > {
> > > goto PassThrough;
> > > }
> > >
> > > ReadBufferMdl = NULL;
> > > if (((hookExt->FileSystem->Flags & DO_BUFFERED_IO) == 0)
> > > && ((hookExt->FileSystem->Flags & DO_DIRECT_IO) == 0))
> > > {
> > > if (Irp->MdlAddress)
> > > {
> > > ReadBufferMdl = Irp->MdlAddress;
> > > }
> > > else if (Irp->UserBuffer)
> > > {
> > > ReadBufferMdl = IoAllocateMdl(Irp->UserBuffer,
> > > currentIrpStack->Parameters.Read.Length,
> > > FALSE, FALSE, NULL);
> > > if (ReadBufferMdl)
> > > {
> > > __try
> > > {
> > > MmProbeAndLockPages(ReadBufferMdl, KernelMode, IoModifyAccess);
> > > }
> > >__except(EXCEPTION_EXECUTE_HANDLER)
> > > {
> > > IoFreeMdl(ReadBufferMdl);
> > > ReadBufferMdl = NULL;
> > > }
> > > }
> > > }
> > > }
> > >
> > > *nextIrpStack = *currentIrpStack;
> > > IoSetCompletionRoutine( Irp, SpecialReadCompletionRoutine,
> > > (PVOID)ReadBufferMdl, TRUE, TRUE, TRUE );
> > > return IoCallDriver( hookExt->FileSystem, Irp );
> > >
> > > PassThrough:
> > >
> > > *nextIrpStack = *currentIrpStack;
> > > IoSetCompletionRoutine( Irp, FilemonHookDone, NULL, TRUE, TRUE, TRUE
> > > );
> > > return IoCallDriver( hookExt->FileSystem, Irp );
> > >
> > > }
> > > //-----------------------------------------------------------------------
> > > //completion procedure for IRP_MJ_READ
> > >
> > > NTSTATUS SpecialReadCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN
> > > PIRP Irp,
> > > IN PVOID Context )
> > > {
> > > PFILE_OBJECT fileObject;
> > > PIO_STACK_LOCATION currentIrpStack;
> > > PHOOK_EXTENSION hookExt;
> > > char *Data;
> > > DWORD Len;
> > > PMDL ReadBufferMdl;
> > >
> > > if(Irp->PendingReturned)
> > > {
> > > IoMarkIrpPending(Irp);
> > > }
> > >
> > > if (! NT_SUCCESS(Irp->IoStatus.Status))
> > > {
> > > return Irp->IoStatus.Status;
> > > }
> > >
> > > Len = Irp->IoStatus.Information;
> > > if (Len == 0)
> > > {
> > > return Irp->IoStatus.Status;
> > > }
> > >
> > > currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
> > >
> > > fileObject = currentIrpStack->FileObject;
> > >
> > > hookExt = DeviceObject->DeviceExtension;
> > >
> > > if ((hookExt->FileSystem->Flags & DO_BUFFERED_IO) &&
> > > (Irp->AssociatedIrp.SystemBuffer))
> > > {
> > > Data = Irp->AssociatedIrp.SystemBuffer;
> > > GuardDecrypt(currentIrpStack->Parameters.Read.ByteOffset, Data, Len);
> > > }
> > > else if ((hookExt->FileSystem->Flags & DO_DIRECT_IO) &&
> > > (Irp->MdlAddress))
> > > {
> > > Data = MmGetSystemAddressForMdl(Irp->MdlAddress);
> > > if (Data)
> > > {
> > > //Data += MmGetMdlByteOffset(Irp->MdlAddress);
> > > GuardDecrypt(currentIrpStack->Parameters.Read.ByteOffset, Data, Len);
> > > }
> > > }
> > > else if (((hookExt->FileSystem->Flags & DO_BUFFERED_IO) == 0)
> > > && ((hookExt->FileSystem->Flags & DO_DIRECT_IO) == 0)
> > > //&& (Irp->UserBuffer)
> > > )
> > > {
> > > ReadBufferMdl = (PMDL)Context;
> > > if (ReadBufferMdl)
> > > {
> > > Data = MmGetSystemAddressForMdl(ReadBufferMdl);
> > > if (Data)
> > > {
> > > //Data += MmGetMdlByteOffset(ReadBufferMdl);
> > > GuardDecrypt(currentIrpStack->Parameters.Read.ByteOffset, Data, Len);
> > > }
> > >
> > > if (Irp->MdlAddress == NULL)
> > > {
> > > MmUnlockPages(ReadBufferMdl);
> > > IoFreeMdl(ReadBufferMdl);
> > > }
> > > }
> > > }
> > >
> > > return Irp->IoStatus.Status;
> > > }
> > >
> > >
>
> —
> You are currently subscribed to ntfsd as: xxxxx@alfasp.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com


Kind regards, Dejan M. MVP for DDK
http://www.alfasp.com E-mail: xxxxx@alfasp.com
Alfa Transparent File Encryptor - Transparent file encryption services.
Alfa File Protector - File protection and hiding library for Win32 developers.
Alfa File Monitor - File monitoring library for Win32 developers.