以下文章来源于汽车信息安全 ,作者theoneandone
上一篇《谈谈QNX安全之软件编译安全》,我们谈到了软件编译时QNX的一些安全选项,那么软件刷进ECU后,如何保证刷写的软件没有被篡改呢?今天笔者就给大家简单介绍一下QNX的软件防篡改策略,主要包括Secure Boot、QTD、Power-Safe文件系统。
1. Secure Boot
安全启动想必大家肯定很熟悉,它是通过对启动过程的每个阶段进行加密验证,确保运行系统完整性的一种安全机制。如图1所示,QNX的安全启动可以保证由BootRom、PBL/SBL、IPL和IFS,最后到可选的文件系统的完整性。在启动过程中,每一个后续的固件和软件都是由其前身进行加密验证的。
QNX可以支持两套安全启动方案,如图1右侧所示:
方案1:将MRK(Master Root Key)作为信任根,其公钥存储在OTP或EEPROM中,由OTP或EEPROM保证MRK不可篡改,由MRK的私钥完成对CVK(Code Verification Key)公钥的签名,由CVK的私钥完成Bootloader等后续代码的签名。启动时,BootRom使用MRK的公钥验证CVK公钥,验证成功后,由CVK公钥验证下面代码的签名。这样做可以将代码签名密钥CVK和信任根MRK解绑。由于CVK由MRK保证其真实性,CVK的公钥不需要存储在有任何保护的存储器中。这在不安全的制造环境中非常有用,因为即使CVK被泄露,我们也可以将其进行替换,而MRK则由芯片厂家保管。
方案2:不使用MRK,将CVK作为信任根,其公钥存储在OTP或EEPROM中。有时候为了节省存储空间,也可以存储CVK的公钥哈希。由于没有MRK,BootRom直接使用CVK完成代码的验签。此时代码签名密钥和信任根都跟CVK关联,一旦CVK的私钥被泄露,基本无解,优点在于ECU的设备制造商可完全掌握代码签名。
2. QTD
Secure Boot中最后一项是可选的完整性保护的文件系统,QTD便是其中一种。QTD(QNX Trusted Disk),是QNX针对数据存储的安全机制,通过结合哈希树和PKI密钥签名,为二进制数据、关键系统配置等提供完整性和真实性保护。它基于 Merkle 树,如图2所示,在构建 QTD 映像时,元数据哈希树是从源文件系统映像的块一层一层构建的,直至RootHash。
与AVB中的DM-Verity类似,如图3所示。RootHash会进行签名保护,并纳入到安全启动链中。只要保证哈希树的RootHash未被篡改,便可以保证整个哈希树的完整性。这样可以带来一个好处,在安全启动的时候不用验证整个文件系统,只需要验证哈希树即可。当需要实际访问具体的某个存储块时,再通过对比哈希树中对应的哈希值即可发现存储块是否被更改。QTD的驱动程序位于原始块设备和受支持的上层文件系统层之间(例如,fs-qnx6.so 支持的power-safe文件系统)。在读取访问时,使用哈希树Metadata来验证数据的完整性。如果验证失败,则会返回错误。使用QTD肯定会有一定的性能开销,好在QTD可以通过预先缓存内部哈希计算来减少实际访问时哈希运算的数量。
需要注意的是,不同QNX版本支持的摘要算法和签名算法不同,当前QNX710支持的密码学算法如表1所示。
QTD 使用由QNX加密库qcrypto提供的加密算法,详细可参考 “QNX Cryptography Library”。当前支持 ECC 和 RSA 签名,其中私钥必须是 PKCS#8 格式,公钥必须是 X.509 格式,所有密钥都必须使用 PEM 编码。对于 RSA,最多支持 16 KiB (kibibits) 的密钥长度。
QTD的挂载由fs-qtd.so提供支持,devb-*驱动程序会在挂载QTD设备时加载它。以下命令构建 QTD 映像。-P 选项精确指定 2 MB 的镜像:
mkqfs qtd -s -vv -B 4096_-H sha256 -S ecdsa-sha256 -K _ec_test_private_key.pem_ -P 2097152 -o_qtd.img qnx6.img
以下命令通过全盘验证挂载 QTD 镜像:
mount -t qtd -o key=/proc/boot/ec_test_public_key.pem,stats,verbose,verify /dev/hd1 /dev/qtd-1
3. Power-Safe文件系统
Power-Safe文件系统是一个可靠的磁盘文件系统,可以承受电源故障而不丢失或损坏数据。它支持file-based加密,密钥类型如表2所示,可以对 Power-Safe 文件系统的全部或部分进行加密,以保护其内容。其中文件和文件夹被聚合到加密域中。每个域都有一个唯一的加密密钥,称之为域密钥,用于加密唯一的文件密钥。访问文件需要一些外部参与者使用主密钥解锁域密钥,向文件系统驱动程序提供域密钥,允许它解密文件密钥并授予对加密文件内容的访问权限。
具体使用的加密算法如表3所示。
Power-Safe文件系统中一个域可以包含任意数量的文件或目录,但一个文件或目录最多只能属于一个域。如果给一个目录指定了一个域,那么随后在该目录中创建的所有文件都会被加密并继承该域,但已经在其中的任何文件或目录不会加密。允许你创建多个加密域,你可以根据需要锁定或解锁这些域。在操作过程中,分配给一个域的文件被加密,只有当相关的域被解锁时,文件的内容才能被使用。当一个域被解锁时,该域下的所有文件和目录--无论它们在卷中的位置如何--也被解锁,因此可以被访问(根据基本文件权限)。当一个域被锁定时,对属于该域的文件内容的任何访问都被拒绝。锁定和解锁操作适用于整个域,而不是特定的文件或目录。
那么如何生成一个Power-Safe文件系统呢?以下命令生成一个小于 2MB 的 Power-Safe 文件系统镜像 (QNX):
mkxfs -t qnx6fsimg qnx6.build qnx6.img
可以使用以下命令挂载 Power-Safe 文件系统镜像:
mount -t qnx6 /dev/qtd-1 /fs
需要注意的是Power-Safe 文件系统可能包含在 QTD 分区中,因此有时候需要先挂载 QTD 分区。
小结
安全启动和QTD可以保证从BootRom到文件系统时软件的完整性,基于Power-Safe的文件加密可以保证存储在该文件系统中文件的机密性。这些都是QNX提供的安全特性,实际应用中可以基于芯片的安全能力,结合QNX的安全属性,搭建更加完善的防御体系。
作者:theoneandone
文章来源:汽车信息安全
推荐阅读
更多汽车电子干货请关注汽车电子与软件专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。