非交互式全盘加密系统设计与实现*
2020-03-26杨景贺
黄 沾,杨景贺
(中国电子科技网络信息安全有限公司,四川 成都 610041)
0 引 言
随着计算机和网络的飞速发展,海量的数据存储在各种设备中。其中,块设备是最主要的存储设备,携带着大量涉密文档。倘若系统存在漏洞被未授权使用或者块设备被盗、丢失,都会引起政府、企业或个人的重大经济和精神损失。如何有效地保护涉密文档的安全性,尤其在计算机丢失或失窃后,防止机密信息非法泄露,对目前普遍存在的存储安全提出了新的挑战。在通用消费者领域,Android智能手机操作系统在其3.0版本中提供了存储加密功能[1],而微软的Windows也推出了BitLocker功能[2],可以对整个磁盘进行加密。但式,这些解决方案需要大量的用户响应(如输入密码),无疑不适应于工业环境中运行的设备,因为这些设备要求7×24 h运行,无人工干预。因此,本文设计并实现了一个适用于工业环境的非交互式全盘加密系统,下面将从设计目标、方案和实现3个方面分别进行描述。
1 全盘加密系统设计目标
本系统的设计目标是一个尽量利用现有硬件设施,在不增加硬件成本的基础上,使用软件方来提高设备存储私密性,同时对现有应用做到无缝衔接。
(1)兼容性:设计方案必须保持对现有设备的兼容性,如ARM平台、X86平台和龙芯平台等。
(2)密钥随机:每台设备的密钥都可以随机设置,避免一台主机被破解后所有主机都告破,形成事实上的“后门”。
(3)硬件绑定:每个存储的访问都与该存储所在设备绑定,将存储通过物理方法取出直接访问,或者放置到其他任何设备无法直接访问存储。
(4)易用性:方案应尽量减少对现有应用的干扰,即现有应用可以不做任何更改。
(5)非交互式:由于设备运行要求7×24 h无人值守运行,必须要求系统必须是非交互式的,与现有的加密系统有根本区别。
2 全盘加密系统设计方案
2.1 概述
将系统分为MBR镜像、Bootloader(这里为GRUB2)、内核与文件系统和其他分区等,位置如图1所示。
图1 存储分区
MBR镜像位于是磁盘第一个扇区(512 Bytes),包含了分区表与GRUB2的stage1加载代码。GRUB2镜像位于MBR与实际分区间的空隙,由于设备本身没有加解密设施,所以GRUB2这里未被加密。而内核与文件系统及后面的分区都已被加密处理(图1中阴影部分)。GRUB2会在启动过程中自动获取密钥并将内核与文件系统解密,然后再启动解密后的内核。
基于设计目标,需要将密钥存放于设备的硬件中,以达到与设备绑定的目的,同时存储的信息必须保留。同时,为了安全性,密钥至少需要保留16 Bytes以上,以防止暴力破解。基于以上考虑,选择网卡ROM存放密钥。
2.2 系统初始化及加密
在设备未加密前,需要进行系统初始化工作。在进入系统后:
(1)随机生成密钥并将密钥写入网卡ROM中;
(2)调用cryptsetup工具,将未加密分区转换为加密分区。
2.3 GRUB2解密
在GRUB2中,需要应对分区加密与未加密两种情况。最重要的是获取密钥并解密,因为网卡一般采用PCI接口与设备相连,而GRUB2提供了完善的PCI访问接口,可以较容易地进行PCI设备寄存器访问。
2.4 文件系统解密
在设备运行过渡到内核并切换到文件系统后,为了让其他应用程序能访问存储分区,需要再次将存储解密。这里比较简单,获取ROM以及解密都有现成的工具可用。
3 全盘加密系统的实现
为了实现上述系统,需要整合多个现有技术。下面从关键技术及其用法出发,阐述功能实现的方法。
3.1 关键技术
3.1.1 GRUB2
GRUB2(GRand Unified Bootloader 2) 是 原GRUB的升级版本,支持多个体系平台和多种部署方式,同时内置了对多个加密方法的支持,包括LUKS、geli等。此外,GRUB2支持密码锁定等常见安全措施。
3.1.2 LUKS
LUKS(Linux Unified Key Setup)是 Linux硬盘加密标准,通过提供标准的磁盘格式,不仅可以促进发行版之间的兼容性,还可以提供对多个用户密码的安全管理。
对于本方案而言,使用LUKS有以下几点考虑:
(1)实现相对容易,在GRUB2中已有基本的LUKS模块,实现了基本的LUKS加密分区读取,后续只要获取密钥传递给LUKS模块即可。
(2)支持多个密码:LUKS支持增加和删除用户密码,后续在系统更新时可随时更换密码,提高了安全性。
(3)LUKS作为广泛应用的加密标准,安全性得到了良好验证,同时其对应的工具cryptsetup功能强大、稳定可靠。
3.2 密钥的存放与获取
密钥的存放与获取是本方案的关键,这里以网卡ROM作为密钥存放点为例。实际使用中还可以将ROM中的信息做多重变换,如使用pbkdf2算法增加破解难度。
密钥的设置是在文件系统启动后进行,而密钥的读取同时存在于GRUB2与文件系统启动后。
所以,设置一个可执行文件diskkey作为文件系统启动后密钥的写入与读取,而在GRUB2流程中将作为补丁打入GRUB2的LUKS模块,替换原有的提示用户输入密码部分。
3.2.1 diskkey实现
diskkey实现密钥的读取与写入,实现必须保密,防止对外泄露。diskkey的实现与设备高度关联,而且应该不定时变换。
示例:
ethtool -e eth0 raw on offset 0 length 32
ethtool读取网卡ROM信息中前32位信息作为密钥输出。
3.2.2 GRUB2实现
以Intel网卡芯片82540为例,其开发手册记录了如何使用EEPROM Read register(EERD)寄存器来访问网卡ROM。
示例:
regs是寄存器基地址,根据手册EERD位于0x14h,即第5个双字的位置。regs[0x5]=eerd将想要访问的ROM地址赋予EERD寄存器,后续检测EERD的DONE bit是否置位,置位表示网卡已经将ROM内容写入EERD寄存器。需要注意,该函数每次能够读取两字节(一个字)长度的ROM,需要按照密钥存储约定多次调用。而regs变量的获得,可以通过调用grub2 pci接口相关API获取。
3.3 GRUB2启动流程
设备启动后会加载GRUB2,而GRUB2必须判断存储是否已经加密。如果未加密,则走初始化流程;如果已经加密,则必须调用解密命令,再加载解密后的内核与文件系统。
一个GRUB2配置文件示例:
GRUB2一开始加载biosdisk和part_msdos两个模块,以便后续访问设备上的存储及其分区,然后加载LUKS模块。LUKS模块已经经过修改,不会再提示用户输入密码,能自动加载磁盘密码。
if linux (hd0,msdos1)/vmlinuz这行尝试直接加载分区上的内核,如果成功,说明磁盘还没有加密,继续加载initramfs,然后启动。如果加载失败,系统尝试使用cryptomount解密分区。解密后的分区用crypto0表示,如果linux指令依然无法访问内核,则表示解密过程失败,设备可能存在异常情况,系统进行关机处理。
3.4 文件系统启动流程
系统启动后,需要将原加密分区进行解密,这样对其他应用不会造成干扰。解密过程主要使用cryptsetup工具[3],示例如下(DEVICE变量为LUKS所在分区设备名):
cryptsetup isLuks判断分区是否经过LUKS加密。diskkey读取加密密钥,cryptsetup luksOpen完成解密过程,最后调用mount挂载加密分区,后续使用与普通分区相同。
3.5 系统防护
系统启动后,必须确保系统访问是授权情况。如果解密方式公开,意味着加密失效。所以,在现有Linux安全防护措施基础上,对整个启动流程进行了全方面的系统安全加固。
3.5.1 锁定GRUB2
GRUB2是系统启动的第一步,可以任意指定内核、文件系统、内核参数等。所以,为了系统的安全启动,必须锁定GRUB2。GRUB2提供了锁定其运行配置文件的方法,使GRUB2只能按照指定的流程运行,包括固定的内核、内核参数等。
示例:
set superusers="root"设置超级用户为root,后面password_pbkdf2设置root密码(即XXXX部分),root密码调用grub-mkpasswd-pbkdf2命令生成。menuentry表示后面的启动命令无需认证即可执行。
最后达到的效果是menuentry中的启动流程可以无干扰执行,而要修改启动项如修改内核参数,需要输入root用户密码进行认证。
3.5.2 禁用init与rdinit内核参数
由于GRUB2是未加密的,虽然在上一步已做锁定GRUB2,但是仍然要堤防GRUB2配置文件被修改。必须假定GRUB2传给内核的参数已经被修改,而内核默认提供了init(rdinit)内核参数来自定义内核启动的init进程执行文件路径。通过修改init参数,如直接修改为/bin/sh,可以直接绕过登录认证访问文件系统,就直接暴露了diskkey的实现,导致加密系统告破。由于使用initramfs启动,对应的是rdinit参数,只需要禁用rdinit参数即可。解决办法比较简单,将内核中rdinit参数处理函数注释掉即可,对应的代码位于init/main.c中,不做赘述。
3.5.3 系统固件加密
系统揭秘方法也在系统的升级固件中可以获取,所以系统固件必须加密。由于各个系统实现不同,这部分不做展开。
4 结 语
本文提出的非交互式全盘加密系统解决了在现有硬件设备存储安全的问题,同时系统还有很多需要改进的地方,包括对现有安全硬件技术的支持(如UEFI Secure Boot、TPM)等,将是下一步的研究内容。