Volume filter driver for encryption/decryption

Hi,

As the title suggests, I’m writing a filter driver whose job is to be encrypt a volume entirely.

For this, I’ve written a kmdf-based volume filter driver that tracks all the READs, WRITEs and IOCLTs happening on the volume at the moment. I need to fit encryption/decryption part into this and for that need to understand what parts of a volume should be excluded from this process and be treated as clear text all the time?

I’ve read a related thread about this here https://community.osr.com/discussion/64507/problems-with-a-disk-encryption-filter-driver, and that sector 0 (boot sector) should be excluded but I guess it does not really apply in my case since I’m not really filtering a disk here.

I’m testing this with a vhd at the moment. So when I try to create a simple volume and format it with NTFS, I get below output. From the output I can see that reads are coming through long before first write on the volume is even issued. This suggests that one can not blindly just start doing encryption/decryption immediately after attaching to the volume stack.

Here’s the output from sample run (output has been truncated but removed stuff doesn’t contain write request):

KmdfHelloWorld: IOCTL Code → 5046280; OutputBufferLength → 0x102; InputBufferLength → 0x0
KmdfHelloWorld: IOCTL Code → 5046272; OutputBufferLength → 0x82; InputBufferLength → 0x0
KmdfHelloWorld: IOCTL Code → 5046296; OutputBufferLength → 0x10; InputBufferLength → 0x0
KmdfHelloWorld: IOCTL Code → 5636152; OutputBufferLength → 0x8; InputBufferLength → 0x0
KmdfHelloWorld: IOCTL Code → 2953616; OutputBufferLength → 0x14; InputBufferLength → 0x8
KmdfHelloWorld: IOCTL Code → 5046284; OutputBufferLength → 0x20; InputBufferLength → 0x0
KmdfHelloWorld: IOCTL Code → 5636168; OutputBufferLength → 0x1; InputBufferLength → 0x0
KmdfHelloWorld: IOCTL Code → 5636096; OutputBufferLength → 0x20; InputBufferLength → 0x0
KmdfHelloWorld: IOCTL Code → 458824; OutputBufferLength → 0x90; InputBufferLength → 0x0
KmdfHelloWorld: IOCTL Code → 458832; OutputBufferLength → 0x1000; InputBufferLength → 0x0
KmdfHelloWorld: IOCTL Code → 5095440; OutputBufferLength → 0x0; InputBufferLength → 0x62
KmdfHelloWorld: IOCTL Code → 5046288; OutputBufferLength → 0x0; InputBufferLength → 0x62
KmdfHelloWorld: IOCTL Code → 5095440; OutputBufferLength → 0x0; InputBufferLength → 0x1e
KmdfHelloWorld: IOCTL Code → 5046288; OutputBufferLength → 0x0; InputBufferLength → 0x1e
KmdfHelloWorld: IOCTL Code → 5685256; OutputBufferLength → 0x0; InputBufferLength → 0x0
KmdfHelloWorld: IOCTL Code → 5046280; OutputBufferLength → 0x102; InputBufferLength → 0x0
KmdfHelloWorld: IOCTL Code → 5046280; OutputBufferLength → 0x102; InputBufferLength → 0x0
KmdfHelloWorld: IOCTL Code → 5685348; OutputBufferLength → 0x0; InputBufferLength → 0x0
KmdfHelloWorld: IOCTL Code → 2953612; OutputBufferLength → 0x48; InputBufferLength → 0x4
KmdfHelloWorld: IOCTL Code → 458752; OutputBufferLength → 0x18; InputBufferLength → 0x0
KmdfHelloWorld: IO → READ; DeviceOffset → 32768; Length → 2048;
KmdfHelloWorld: IO → POST READ; Buffer → 0xFFFFAC819AA4F000; Length → 0x800; Status → 0x0; Information → 2048


KmdfHelloWorld: IOCTL Code → 2952212; OutputBufferLength → 0x8; InputBufferLength → 0x0
KmdfHelloWorld: IOCTL Code → 2953344; OutputBufferLength → 0xc; InputBufferLength → 0x0
KmdfHelloWorld: IO → READ; DeviceOffset → 0; Length → 4096;
KmdfHelloWorld: IO → POST READ; Buffer → 0xFFFFAC819AA50000; Length → 0x1000; Status → 0x0; Information → 4096


KmdfHelloWorld: IOCTL Code → 2954240; OutputBufferLength → 0x400; InputBufferLength → 0xc
KmdfHelloWorld: IOCTL Code → 2953616; OutputBufferLength → 0x14; InputBufferLength → 0x8
KmdfHelloWorld: IO → READ; DeviceOffset → 0; Length → 512;
KmdfHelloWorld: IO → POST READ; Buffer → 0xFFFFCF86AFC619A0; Length → 0x200; Status → 0x0; Information → 512


KmdfHelloWorld: IOCTL Code → 475228; OutputBufferLength → 0x8; InputBufferLength → 0x0
KmdfHelloWorld: IOCTL Code → 458752; OutputBufferLength → 0x18; InputBufferLength → 0x0
KmdfHelloWorld: IO → READ; DeviceOffset → 0; Length → 512;
KmdfHelloWorld: IO → POST READ; Buffer → 0xFFFFAC819AA5B000; Length → 0x200; Status → 0x0; Information → 512
KmdfHelloWorld: IOCTL Code → 475228; OutputBufferLength → 0x8; InputBufferLength → 0x0
KmdfHelloWorld: IOCTL Code → 458752; OutputBufferLength → 0x18; InputBufferLength → 0x0
KmdfHelloWorld: IO → READ; DeviceOffset → 0; Length → 512;
KmdfHelloWorld: IO → POST READ; Buffer → 0xFFFFAC819AA5C000; Length → 0x200; Status → 0x0; Information → 512
KmdfHelloWorld: IOCTL Code → 475228; OutputBufferLength → 0x8; InputBufferLength → 0x0
KmdfHelloWorld: IOCTL Code → 458752; OutputBufferLength → 0x18; InputBufferLength → 0x0
KmdfHelloWorld: IO → READ; DeviceOffset → 0; Length → 512;
KmdfHelloWorld: IO → POST READ; Buffer → 0xFFFFAC819AA5D000; Length → 0x200; Status → 0x0; Information → 512

Also, I found that there’s scarcity of information when it comes to writing volume filter drivers (on the contrary to say fs minifilters etc).
So if you happen to have links, documentation that talk about care to be taken while writing such filter drivers and share those that will be great.

Thanks

As the title suggests, I’m writing a filter driver whose job is to be encrypt a volume entirely.

Because that’s never been done before?

Hi Tim, Thanks for getting back. I was under the impression that solutions like TrueCrypt do that (I admit I haven’t gone over the codebase and verified that). If that’s the case, do you reckon writing disk filter driver to encrypt/decrypt entire disk would be better ? Thanks

That was my snarky point. There are many, many solutions today that provide full-disk encryption, including some built-in to the hardware,and at least one built-in to Windows. What can you possibly provide that isn’t already available? Why go to the trouble?

Got you. Out of curiosity though, I thought the only advantage would have been being able to pick n choose volumes as you attach to volumes and encrypt those instead of encrypting the whole disk. But I guess that can still be done at a disk level, by taking a peek into partition table, reading offsets at which particular volumes resides etc ? Also, any recommendations which samples I should look at that will help me get started with disk encryption. Thanks

The advantage of doing this versus the various commercial and open source alternatives is the betterment of your knowledge. Many times I have ‘re invented the wheel’ for the purpose of educating myself. That is not a null objective, but from a commercial point of view it is not a good one

We are looking at the possibility of having an in-house solution that will encrypt our vhds. There is no use-case where we would attach to actual disks in the system (say boot device etc.) and start encrypting those - that’s not the requirement. At the moment, I’m just looking to build a lightweight POC kind of driver that will attach to vhds, access data buffers during IOs, encrypt/decrypt those using a very simple technique (may be XOR) and then take it from there.

I’ve come across couple of issues in my disk filter for which I’ll be starting a new thread but any pointers related to handling encryption/decryption at disk level, samples etc. would be great.