Is it Impossible that Using FileHeader Solution in on-the-fly encryption?

Hi, Everyone.
I am developing a legacy fsfilter driver for on-the-fly encryption, and I append a file header(4K) for every encrypted file.

In Read/Write dispatch, I only process non-cache and page i/o. For every request, I modify the irpSp->Parameters.Read/Write.ByteOffset(+4K), and send it to filesystem.
Read is ok, write non-cache i/o is also ok, but write page i/o has problem: recursive problem!!

For exmaple: a encrypted file, file header length is 0x1000, file data length is 0x400.
Now i do a non-cache write for this file. write offset is 0x600 and write length is 0x200.
In my filter i receive first non-cache write irp, offset is 0x600, i changed offset to 0x1600 and send to filesystem.
In filesystem, fsd will invoke CcZeroData for 0x1400-0x1600 and then i receive second page i/o which offset is 0x1400, this time I shouldn’t modify the offset, but i can’t recognize this situation in code context.

This is one situation, and I don’t known if there is more similar situation like this.
I read WRK and FastFat, but can’t find a way to determine when to modify the offset and when not to modify the offset in page write i/o.
Is there anyone who can give me a good suggestion?

You need to have the file sizes adjusted correctly before you receive
the paging write, as you hopefully have read in this forum paging writes
will not extend the file size. Therefore you need to adjust the file
size either during the cached IO request, writing out encrypted zeroes
or tracking this length internally, or during the set file info request.
In either case, by the time you receive the paging write the file size
will be correct and you will not hit the case you are seeing. These edge
cases are some of the biggest problems to get right when trying to
implement an encryption filter driver.

Pete

On 7/17/2014 11:07 PM, xxxxx@gmail.com wrote:

Hi, Everyone.
I am developing a legacy fsfilter driver for on-the-fly encryption, and I append a file header(4K) for every encrypted file.

In Read/Write dispatch, I only process non-cache and page i/o. For every request, I modify the irpSp->Parameters.Read/Write.ByteOffset(+4K), and send it to filesystem.
Read is ok, write non-cache i/o is also ok, but write page i/o has problem: recursive problem!!

For exmaple: a encrypted file, file header length is 0x1000, file data length is 0x400.
Now i do a non-cache write for this file. write offset is 0x600 and write length is 0x200.
In my filter i receive first non-cache write irp, offset is 0x600, i changed offset to 0x1600 and send to filesystem.
In filesystem, fsd will invoke CcZeroData for 0x1400-0x1600 and then i receive second page i/o which offset is 0x1400, this time I shouldn’t modify the offset, but i can’t recognize this situation in code context.

This is one situation, and I don’t known if there is more similar situation like this.
I read WRK and FastFat, but can’t find a way to determine when to modify the offset and when not to modify the offset in page write i/o.
Is there anyone who can give me a good suggestion?


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295

Thanks Peter.

I processed IRP_MJ_QUERY_INFORMATION for returning modified length,
but I didn’t change FSRTL_COMMON_FCB_HEADER.AllocationSize/FileSize/ValidDataLength.
For a encrypted file, these values are the encrypted file real size,
and so in CM, the file cache size is also the encrypted file real size.

File in Disk: XXXX(FileHeader,4K) DDDD(FileEncryptedData,4K)
File in Cache: DDDD(FilePlainData, 4K) ???(4K)

FCB_HEADER is used in NT and FSD, so i think i shouldn’t change AllocationSize/FileSize/ValidDataLength in FSRTL_COMMON_FCB_HEADER.
am I wrong?? In CM the file size should be modified size or real size?? i am a little confused.

You need to have the file sizes adjusted correctly…
Sorry, I not quite understand how to adjust the file size correct,
in my example, CcZeroData is invoked by FSD and i don’t have chance to adjust the file size.

Some of the cases which you need to handle are 1) During a cached write,
if the write is an extending write then you need to call into the file
system and either extend the file size via a setfileinfo() call or write
out encrypted zeroes to extend the file size. These IOs must be
non-cached writes so they don’t effect the cache. 2) During a
setfileinfo() call, you need to add your header size onto this. If this
new size extends the file size then you need to, again, extend the file
on disk. You can do this by writing out encrypted zeros or by simply
setting the size passed down to the extended size. Note that in either
case above, if you don’t write out encrypted zeros when extending the
file then you need to internally track what part of the file is actually
encrypted so if a read is processed for a non-encrypted region you do
not decrypt a zero filled buffer. 3) Non-cached, non-paging writes are
another area but since they can extend the file length they are handled
as a non-cached write request.

Finally, when a paging write is being processed, the file size in the
file system;i.e. on disk, must already be large enough to accommodate
the write adjusted for your header length. You will run into too many
problems if you attempt to extend the file at the time of the paging
write, such as an asynchronous request, etc.

Pete

On 7/18/2014 12:23 AM, xxxxx@gmail.com wrote:

Thanks Peter.

I processed IRP_MJ_QUERY_INFORMATION for returning modified length,
but I didn’t change FSRTL_COMMON_FCB_HEADER.AllocationSize/FileSize/ValidDataLength.
For a encrypted file, these values are the encrypted file real size,
and so in CM, the file cache size is also the encrypted file real size.

File in Disk: XXXX(FileHeader,4K) DDDD(FileEncryptedData,4K)
File in Cache: DDDD(FilePlainData, 4K) ???(4K)

FCB_HEADER is used in NT and FSD, so i think i shouldn’t change AllocationSize/FileSize/ValidDataLength in FSRTL_COMMON_FCB_HEADER.
am I wrong?? In CM the file size should be modified size or real size?? i am a little confused.

> You need to have the file sizes adjusted correctly…
Sorry, I not quite understand how to adjust the file size correct,
in my example, CcZeroData is invoked by FSD and i don’t have chance to adjust the file size.


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295

Thanks Peter for your suggestion.

Forget the plaintext zeroes. Encrypt them. I can think of lots of ways
of leaking information by extending an encrypted file if I know it uses
plaintext zeroes at the end. (In 2002 I was working in the area of TCB
devices, with a guy who has a PhD in cryptology algorithms. He would
regale us with tales of ways to leak information–it was part of our
“training”).
joe

joe

Some of the cases which you need to handle are 1) During a cached write,
if the write is an extending write then you need to call into the file
system and either extend the file size via a setfileinfo() call or write
out encrypted zeroes to extend the file size. These IOs must be
non-cached writes so they don’t effect the cache. 2) During a
setfileinfo() call, you need to add your header size onto this. If this
new size extends the file size then you need to, again, extend the file
on disk. You can do this by writing out encrypted zeros or by simply
setting the size passed down to the extended size. Note that in either
case above, if you don’t write out encrypted zeros when extending the
file then you need to internally track what part of the file is actually
encrypted so if a read is processed for a non-encrypted region you do
not decrypt a zero filled buffer. 3) Non-cached, non-paging writes are
another area but since they can extend the file length they are handled
as a non-cached write request.

Finally, when a paging write is being processed, the file size in the
file system;i.e. on disk, must already be large enough to accommodate
the write adjusted for your header length. You will run into too many
problems if you attempt to extend the file at the time of the paging
write, such as an asynchronous request, etc.

Pete

On 7/18/2014 12:23 AM, xxxxx@gmail.com wrote:
> Thanks Peter.
>
> I processed IRP_MJ_QUERY_INFORMATION for returning modified length,
> but I didn’t change
> FSRTL_COMMON_FCB_HEADER.AllocationSize/FileSize/ValidDataLength.
> For a encrypted file, these values are the encrypted file real size,
> and so in CM, the file cache size is also the encrypted file real size.
>
> File in Disk: XXXX(FileHeader,4K) DDDD(FileEncryptedData,4K)
> File in Cache: DDDD(FilePlainData, 4K) ???(4K)
>
> FCB_HEADER is used in NT and FSD, so i think i shouldn’t change
> AllocationSize/FileSize/ValidDataLength in FSRTL_COMMON_FCB_HEADER.
> am I wrong?? In CM the file size should be modified size or real size??
> i am a little confused.
>
>> You need to have the file sizes adjusted correctly…
> Sorry, I not quite understand how to adjust the file size correct,
> in my example, CcZeroData is invoked by FSD and i don’t have chance to
> adjust the file size.
>
>
> —
> NTFSD is sponsored by OSR
>
> OSR is hiring!! Info at http://www.osr.com/careers
>
> For our schedule of debugging and file system seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer

Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Peter, you write:

During a cached write,
if the write is an extending write then you need to call into the file
system and […] write out encrypted zeroes to extend the file size.
These IOs must be non-cached writes so they don’t effect the cache.

I think a minifilter sees most writes twice:
First, a cached write (to the cache).
Second, an uncached write (to the disk).

So I think that all cached writes should all be ignored as we’re only interested in encrypting what goes to disk.

You say to write out encrypted zeros to Disk during a Cached write that extends the file.
Is it not the case then that there will be more encryption during the uncached write to disk that follows.
i.e. you end up having to do the encryption computation twice?

My thinking above is probably wrong. Indeed, I’m having problems with file-extension operations in my encrypting minifilter! Please can you point out my error?

All the best,

David

What do you do about the network, where the file’s caching state is unknown to you?

Actually, this is the tip of the iceberg. You ALSO need to worry about what to do with sparse files (and compressed files are a bit problematic).

Bottom line: if data is being written to disk (including a zero filling EOF move) you need to ensure that data gets encrypted, otherwise you will either be exposing data content or you won’t decrypt properly. This includes data that is written outside your scope (e.g., by the FSD below you).

Tony
OSR

Tony, I understand that I’ve a fair way to go on this journey. You are correct that my filter does not presently handle sparse and compressed files. I appreciate your insight into the complexity of this problem.

Peter, I followed your sage advice:

During a cached write,
if the write is an extending write then you need to call into the file
system and […] write out encrypted zeroes to extend the file size.
These IOs must be non-cached writes so they don’t effect the cache.
and I’m pleased to say that file extension and truncation is now works except for one awkward platform specific case which I’ll write up in a new thread.

All the best,

David

> You ALSO need to worry about what to do with sparse files (and compressed files are a bit problematic).

Hi, Tony. can you give me a more detail information about this.

Rod’s description was sufficient. Bottom line, if you don’t believe us, by all means feel free to prove us wrong!

Tony
OSR