Encryption filter driver - design choices

Hello everyone. I’m trying to develop a filter device for disk encryption but after several days I’m still unclear about how I should design it. I’m considering some possibilities :

    • An upper device filter driver (attached above partmgr). I tried this possibility out but got several problems.
      * I succesfully installed (inf file) my filter driver as an upper class filter driver (based on diskperf WDK sample) but did not really understand how to install for a particular device.
      * I intercept Write IRPs (512 byte data blocs) by looking at the MdlAddress field in the irp stack location. Could I encrypt the whole 512 bytes at this level and would I recieve all writes (not fast i/o) directed at the target partition through this method?
      * In the case of a class filter, I tried to distinguish me drives by invoking IoGetDeviceProperty on concerned PDO device with Hardware ID. Is this a good way?
    • I also thought about creating an “Encryption” class file system filter driver.
      * Would this filter (installed with inf file) be inserted BELOW the filesystem (and above volume)? and would I be able to encrypt the whole data including file informations (name …)?
      * I did not manage to install such a driver too, the documentation I found about the addreg part for this type of filter was not very explicit… Maybe someone could sugest me where I could find some commented INF models for this purpose.

And finally, Is one of these choices more suitable for on the fly encryption of a drive (say C:)?

Many thanks for your answer,
best regards,
Jerome.

Comments inline:

xxxxx@live.fr” wrote in message
news:xxxxx@ntdev:

> Hello everyone. I’m trying to develop a filter device for disk encryption but after several days I’m still unclear about how I should design it. I’m considering some possibilities :
>
> 1) - An upper device filter driver (attached above partmgr). I tried this possibility out but got several problems.
> * I succesfully installed (inf file) my filter driver as an upper class filter driver (based on diskperf WDK sample) but did not really understand how to install for a particular device.
> * I intercept Write IRPs (512 byte data blocs) by looking at the MdlAddress field in the irp stack location. Could I encrypt the whole 512 bytes at this level and would I recieve all writes (not fast i/o) directed at the target partition through this method?

Yes you can encrypt all the data at this level but it may be more than
512 bytes, also you want to be careful on the blocks reserved for the
system that are not part of the file system data. Of course you need to
realize you have no clue who is reading and writing at this level so if
you are trying to deal with a per user control forget it.

> * In the case of a class filter, I tried to distinguish me drives by invoking IoGetDeviceProperty on concerned PDO device with Hardware ID. Is this a good way?

This normally works well if you are trying to distinguish certain types
of drives.
>
>
> 2) - I also thought about creating an “Encryption” class file system filter driver.
> * Would this filter (installed with inf file) be inserted BELOW the filesystem (and above volume)? and would I be able to encrypt the whole data including file informations (name …)?

No file system filters reside above the file system. Yes you can see
all writes but encryption is tricky, go to the NTFSD list and look at
the archives.

> * I did not manage to install such a driver too, the documentation I found about the addreg part for this type of filter was not very explicit… Maybe someone could sugest me where I could find some commented INF models for this purpose.

You should be able to take any of the INF files for a file system filter
and easily change it to your filter.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

Which path you take depends on what you end goals are.
Disk encryption vs. file encryption have quite different goals, and frankly, I am of the opinion that they have no touching goals.
If you need to encrypt file names, you have no choice - you need disk encryption.
Your upper device filter approach should suffice for you, but I would suggest looking at TrueCrypt code at least for learning purposes (note the strict licensing - it is not suitable if you want to make a commercial product, but it’s well written code if you want
to learn from it).
The answer to your 1) questions is:

  • Just don’t attach to the device you don’t want to attach to, if you are an upper class filter
  • Yes
  • Probably, yes, I am not sure how you tell which devices you need to filter. InstanceID will probably be the most appropriate.
    For 2) questions - it doesn’t attach below the FS, but above it.

Dejan.

xxxxx@live.fr wrote:

Hello everyone. I’m trying to develop a filter device for disk encryption but after several days I’m still unclear about how I should design it. I’m considering some possibilities :

    • An upper device filter driver (attached above partmgr). I tried this possibility out but got several problems.
      * I succesfully installed (inf file) my filter driver as an upper class filter driver (based on diskperf WDK sample) but did not really understand how to install for a particular device.
      * I intercept Write IRPs (512 byte data blocs) by looking at the MdlAddress field in the irp stack location. Could I encrypt the whole 512 bytes at this level and would I recieve all writes (not fast i/o) directed at the target partition through this method?
      * In the case of a class filter, I tried to distinguish me drives by invoking IoGetDeviceProperty on concerned PDO device with Hardware ID. Is this a good way?
    • I also thought about creating an “Encryption” class file system filter driver.
      * Would this filter (installed with inf file) be inserted BELOW the filesystem (and above volume)? and would I be able to encrypt the whole data including file informations (name …)?
      * I did not manage to install such a driver too, the documentation I found about the addreg part for this type of filter was not very explicit… Maybe someone could sugest me where I could find some commented INF models for this purpose.

And finally, Is one of these choices more suitable for on the fly encryption of a drive (say C:)?

Many thanks for your answer,
best regards,
Jerome.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other 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


Kind regards, Dejan (MSN support: xxxxx@alfasp.com)
http://www.alfasp.com
File system audit, security and encryption kits.

Many thanks for replies.

“also you want to be careful on the blocks reserved for the
system that are not part of the file system data.”
–> How to distinguish them? Would it be enough to ensure IRP is comming from usermode to encrypt it?

* In the case of a class filter, I tried to distinguish me drives by
invoking IoGetDeviceProperty on concerned PDO device with Hardware ID. Is this a
good way?

This normally works well if you are trying to distinguish certain types
of drives.

–> To distinguish different partitions I thought using the volume serial number. How can I retrieve this number (in kernel mode)?
The “DevicePropertyHardwareID” registry type for IoGetDeviceProperty does not seem to be this volume serial.

EDIT : I think I’ll proceed this way to distinguish my drives :

–>CreateFile(TEXT"\\.\D:", …) to open a handle on the seeked volume.
–>IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS to retrieve disk number

–>ObOpenObjectByPointer(PDO,…) and same as before and then compare informations…

I will try this out tomorrow.

Now, where could I find information on what the captured IRP_WRITE buffer contains (512 bytes or more)? to for example dump it’s content? (printing it just as it gives me always the same short string)

Many thanks.

How do you mean what it contains? The buffer will contain data that is supposed to be written to disk in binary format. You can’t exactly get useful print out of it.
The IRP will contain the offset at which the data should be written. You cannot presume anything from this offset though, apart from offset 0 surely containing system data (though some file systems
might not even work that way)

Now, where could I find information on what the captured IRP_WRITE buffer contains (512 bytes or more)? to for example dump it’s content? (printing it just as it gives me always the same short string)


Kind regards, Dejan (MSN support: xxxxx@alfasp.com)
http://www.alfasp.com
File system audit, security and encryption kits.

Hello, thank you for answering. Today I tried out checking Device parameters like device number in the AddDevice() function but I kept getting an IRQL_NOT_LESS_OR_EQUAL blue screen.
From what I need I know I have to be carefull with IRQL_LEVEL but I based my code on the DDK diskperf sample and don’t really understand where the problem comes from / how to fix it…

In AddDevice I call this function : GetDeviceNumber(IN PDEVICE_OBJECT) which does nothing more than printing the PDO’s device number.

NTSTATUS
GetDeviceNumber(IN PDEVICE_OBJECT PhysicalDeviceObject)
{
IO_STATUS_BLOCK ioStatus;
KEVENT event;
PIRP irp;
STORAGE_DEVICE_NUMBER number;
NTSTATUS status = STATUS_SUCCESS;

PAGED_CODE();

KeInitializeEvent(&event, NotificationEvent, FALSE);

//
// Request for the device number
//
irp = IoBuildDeviceIoControlRequest(
IOCTL_STORAGE_GET_DEVICE_NUMBER,
PhysicalDeviceObject,
NULL,
0,
&number,
sizeof(STORAGE_DEVICE_NUMBER),
FALSE,
&event,
&ioStatus);
if (!irp) {
DbgPrint(“IoBUildDeviceIoControlRequest : Failed to build IRP…\n”);
return STATUS_INSUFFICIENT_RESOURCES;
}

status = IoCallDriver(PhysicalDeviceObject, irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatus.Status;
}

if (NT_SUCCESS(status)) {

//
// Create device name for each partition
//

DbgPrint(“\Device\Harddisk%d\Partition%d\n”, number.DeviceNumber, number.PartitionNumber);

}
else {

DbgPrint(“AddDevice : Getting device and partition numbers for PDO failed…\n”);
}

return status;
}

Is there some problem calling this function in AddDevice? I read something about setting up a workjob to ensure work is done at PASSIVE_LEVEL, but I don’t see how it would help me here…

Many thanks for help!

What is the output of !analyze -v?

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@live.fr
Sent: Monday, May 23, 2011 12:11 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Encryption filter driver - design choices

Hello, thank you for answering. Today I tried out checking Device parameters like device number in the AddDevice() function but I kept getting an IRQL_NOT_LESS_OR_EQUAL blue screen.
From what I need I know I have to be carefull with IRQL_LEVEL but I based my code on the DDK diskperf sample and don’t really understand where the problem comes from / how to fix it…

In AddDevice I call this function : GetDeviceNumber(IN PDEVICE_OBJECT) which does nothing more than printing the PDO’s device number.

NTSTATUS
GetDeviceNumber(IN PDEVICE_OBJECT PhysicalDeviceObject) {
IO_STATUS_BLOCK ioStatus;
KEVENT event;
PIRP irp;
STORAGE_DEVICE_NUMBER number;
NTSTATUS status = STATUS_SUCCESS;

PAGED_CODE();

KeInitializeEvent(&event, NotificationEvent, FALSE);

//
// Request for the device number
//
irp = IoBuildDeviceIoControlRequest(
IOCTL_STORAGE_GET_DEVICE_NUMBER,
PhysicalDeviceObject,
NULL,
0,
&number,
sizeof(STORAGE_DEVICE_NUMBER),
FALSE,
&event,
&ioStatus);
if (!irp) {
DbgPrint(“IoBUildDeviceIoControlRequest : Failed to build IRP…\n”);
return STATUS_INSUFFICIENT_RESOURCES;
}

status = IoCallDriver(PhysicalDeviceObject, irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatus.Status;
}

if (NT_SUCCESS(status)) {

//
// Create device name for each partition
//

DbgPrint(“\Device\Harddisk%d\Partition%d\n”, number.DeviceNumber, number.PartitionNumber);

}
else {

DbgPrint(“AddDevice : Getting device and partition numbers for PDO failed…\n”);
}

return status;
}

Is there some problem calling this function in AddDevice? I read something about setting up a workjob to ensure work is done at PASSIVE_LEVEL, but I don’t see how it would help me here…

Many thanks for help!


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other 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