problem with cache in a swapbuffer example(2)

Hi,
I previously received help on the same topic form my FS encryption project.

I had to bypass decryption on cached IO in order to prevent multiple decryption on a single file there.
In the current working state, I check on preRead/PostRead callbacks and bypass the operation for non-cached IO. this way the filter only operates on the first read and the decrypted data is stored in FS cache and remains there until the cache is considered valid.

Now I want to reverse the logic to prevent plain data access after filter is unloaded or some specific conditions occur.
I thought if I reverse the bypass condition in preRead/PostRead callbacks, then I will have encrypted data in FS cache and my filter will decrypt it upon any non-cached read. This way my filter can control file access.

I did as I mentioned but the resulting filter is not decrypting the file correctly.

Do you think my approach was not feasible or I made a mistake in implementing it?

I’m a little confused. You are asking whether you can protect access to
data when your filter is unloaded?

Prevent your filter from being unloaded, if it is unloaded there is
little you can do for someone accessing the underlying data.

Pete


Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com http:</http:>
866.263.9295

------ Original Message ------
From: xxxxx@yahoo.com
To: “Windows File Systems Devs Interest List”
Sent: 6/8/2016 6:53:20 AM
Subject: [ntfsd] problem with cache in a swapbuffer example(2)

>Hi,
>I previously received help on the same topic form my FS encryption
>project.
>
>I had to bypass decryption on cached IO in order to prevent multiple
>decryption on a single file there.
>In the current working state, I check on preRead/PostRead callbacks and
>bypass the operation for non-cached IO. this way the filter only
>operates on the first read and the decrypted data is stored in FS cache
>and remains there until the cache is considered valid.
>
>Now I want to reverse the logic to prevent plain data access after
>filter is unloaded or some specific conditions occur.
>I thought if I reverse the bypass condition in preRead/PostRead
>callbacks, then I will have encrypted data in FS cache and my filter
>will decrypt it upon any non-cached read. This way my filter can
>control file access.
>
>I did as I mentioned but the resulting filter is not decrypting the
>file correctly.
>
>Do you think my approach was not feasible or I made a mistake in
>implementing it?
>
>—
>NTFSD is sponsored by OSR
>
>
>MONTHLY seminars on crash dump analysis, WDF, Windows internals and
>software drivers!
>Details at http:
>
>To unsubscribe, visit the List Server section of OSR Online at
>http:</http:></http:>

sorry for my bad english.
As I said my project, in its current state, stores data encrypted on the disk and decrypts data when reading from the disk(into FS cache). so I always have encrypted data on the disk and plain(decrypted) data on FS cache. The project operates fine in this state but this way when the filter is unloaded/forced to stop and has no control over read/write operations and access to plain data is gained and plain data will be written back to FS when flushing the cache.
I used this code in preRead and preWrite callbacks to bypass the cached IOs to plain cache and encrypt/decrypt only when a non-cached IO is in progress.

if (!FlagOn(IRP_NOCACHE, iopb->IrpFlags))
return FLT_PREOP_SUCCESS_NO_CALLBACK;
else
// encrypt/decrypt the read/write buffer.

Now, I think a better approach will be having the same encrypted data in FS cache and decrypting upon cached IO requests.
So I taught just reversing the condition should work. I removed the ‘!’ but it is not working.
As the new code dictates any non-cached IO will be passed down the filter stack with no change and the buffer of any cached read/write request will be processed. the logic seams perfect to me. but I don’t get what could have caused the problem.

Peter, Is there any flawless way to protect a filter from unloading? It should protect the filter from unloading at all conditions unless it won’t suit my need.

There might be something else you are missing.
Anyway plain and simple you should not detach from a volume when you are using this kind of encryption filter. As well as pointing your driver unload routine to NULL, which will make your driver unloadable.

But I am afraid you might be missing something else, but I am not sure how much you have tested this out. I am guessing you use some kind of block cipher encryption algorithm. Is it kernel CNG with a symmetric key ? I am just guessing here, but most likely something like this.

During the Read operations happening at the end of the file, depending on how the file was opened ( for synchronous I/O or not ) you might not get the complete data you expect.

Imagine this scenario:
you open a file for read/write and you write in it 1 sector size of data + 1 byte, let’s imagine the sector size is 0x200, you write from notepad/filetest let’s say 0x201 worth of data.
You close the file and eventually the data is being written to disk you will see either 1 write with a length of 0x400 or 2 writes each 0x200 in length.
The second one will contain 1 byte of your info and the rest are zeros. You encrypt all this sector including the zeros.

No when you read let’s say 0x400, this is where the tricky part comes in. If you have a async read, in pre-read you will have a readlength of 0x400 but in post read you will hava Data IoStatus.Information = 0x201 and your swapped buffer will contain you encrypted information all 0x201 bytes of it but the rest will be zero-ed out, even though upon write you encrypted all the zeros as well.
Since you use block cipher encryption, you then have a pbem since you cannot decrypt 1 byte, you need the whole last block, but you have “1 encrypted byte” and the rest zeros.
This does not happen all the time though, for a non-cached synch reads, the Information member of the IoStatus is still 0x201( in this case ) which is expected, but the data in the read buffer contains also what is there beyond the end of file or in the last sector of the file, or in your case
the encrypted zeros that you wrote down, and more precisely the last block of encrypted data is now available.
I am not sure why the FS does this in some cases and not in other, and I guess for non-cached I/O it is desirable to get fetched/transferred the entire last sector upon a read but it is not the case all the time, it being zeroed for async I/O at least from my tests.
I would be curious how other experienced people here deal with this because I am sure I am not the first one to notice it.
Maybe this is also why you sometimes don’t see the proper data ?

Regards,
Gabriel
Windows Kernel Driver Consulting
www.kasardia.com

Just a quick addition:
Above, I am talking about NTFS.

The only solution that worked for me was to encrypt the remaining (not aligned) data with padding and write padded data. It introduced a lot of new problems eg. keeping the real file size in metadata and as result modify the response of all file size requests.

Regards,
Adam
Windows Driver Developer
www.fractaldrivers.com

OK, keeping track of the real file size etc is the way to go, but the idea
is that you do not really need to use padding on the remaining data.
All the noncached writes, will always be “padded” to the sector size. The
data is there on disk, the data you need.
It’s just how do you get it on reads. Some reads transfer data in your
buffer beyond the EOF some just zero out your buffer beyond the EOF offset
in the buffer.
Try it yourself with FileTest / NTFS and just open a test file with 0 as
CreateOptions and read until EOF and see the nonCached reads in your filter
and then open it with NO_INTERMEDIATE_BUFF | SYNC and do the same. You will
see this time your
read’s last read buffer will contain the data beyond EOF, or what you wrote
on the encrypt.
If that would be the case all the time, the issue you had to deal with,
filesizes, etc… would be gone, since you could just decrypt properly, now
data would never be unaligned/unpadded etc…

Gabriel.
www.kasardia.com

On Sat, Jun 11, 2016 at 5:51 PM, wrote:

> The only solution that worked for me was to encrypt the remaining (not
> aligned) data with padding and write padded data. It introduced a lot of
> new problems eg. keeping the real file size in metadata and as result
> modify the response of all file size requests.
>
> Regards,
> Adam
> Windows Driver Developer
> www.fractaldrivers.com
>
> —
> NTFSD is sponsored by OSR
>
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> software drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at <
> http://www.osronline.com/page.cfm?name=ListServer&gt;
>


Bercea. G.</http:>