Android dm-verity 实现原理深入研究

思维导图:

dm-verifydm-verity

说明:源码基于 SC20 平台 Android5.1
Android dm-verify overview

目录

android dm-verify overview.. 1

一、原理… 1

与Verified Boot关系… 1

dm-verity. 1

作用分区… 2

二、模块结构… 2

1.签名… 2

生成OEM自己的密钥对… 4

验签… 5
用户空间,android 部分… 5

内核空间… 5

三、如何启用… 5

四、测试… 6

测试样例1. 无法 remount, 无法 push 文件… 6

测试样例2. 6

五、存在风险… 6

物理块出现坏块… 6

六、其他… 6

七、参考文档… 6

一、原理

Verified Boot关系

Verified Boot 是 Android 4.4 开始引入的一个新特性,配合可选的 dm-verify 功能,可以检测系统是否被篡改,以此保存系统的完整性。

dm-verity

dm-verity 基于kernel 的 Device mapper 框架,Device mapper 是Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机制下,用户可以很方便的根据自己的需要制定实现存储资源的管理策略。关于 Device mapper,可以参考此文献

https://www.ibm.com/developerworks/cn/linux/l-devmapper/

dm-verity 用一个 hash 树来描述整个 system 镜像。这种机制允许 system 分区在读写的时候进行校验,而不是一次性将整个 system 镜像进行校验。当校验 hash 值不一致的时候,返回 IO 错误

框架示意图:

dm-verity-hash-treedm-verity-hash-tree

 作用分区

system

vendor

OEM

其他只读分区

二、模块结构

 1.签名

如何生成用于dm-verity 校验的镜像,可以参考一下主流程:

主流程,Android 官方文档如下:

– Generate an ext4 system image.

– Generate a hash tree for that image.

– Build a dm-verity table for that hash tree.

– Sign that dm-verity table to produce a table signature.

– Bundle the table signature and dm-verity table into verity metadata.

– Concatenate the system image, the verity metadata, and the hash tree.

  • 生成 ext4 格式的 system 镜像
  • 生成 system 镜像的 hash 树
  • 根据 hash 树生成 dm-verity table
  • 对 dm-verity 进行签名,得到签名文件
  • 将签名、dm-verity table 打包到 metadata 镜像
  • 将 verity metadata,hash 树 添加到 system 镜像末尾
  • 生成 ext4 格式的 system 镜像
    build/tools/releasetools/build_image.py  BuildImage 函数 中

通过 prop_dict 属性,判断是否启用 verity 功能,启用的话,调整 system 分区大小,以便后面添加相关文件到 system.img 末尾,然后 RunCommand(build_command) 生成初始的 system.img。

prop_dict 文件路径:

out/target/product/msm8909/obj/PACKAGING/systemimage_intermediates/system_image_info.txt

prop_dict 文件内容:

fs_type=ext4

system_size=1288491008

userdata_size=4831838208

cache_fs_type=ext4

cache_size=268435456

extfs_sparse_flag=-s

selinux_fc=out/target/product/msm8909/root/file_contexts

verity=true

verity_key=build/target/product/security/verity

verity_signer_cmd=out/host/linux-x86/bin/verity_signer

system_verity_block_device=/dev/block/bootdevice/by-name/system

skip_fsck=true

  • 生成 system 镜像的 hash 

BuildVerityTree 函数生成 hash tree (verity_image)

步骤3,4,5BuildVerityMetadata中实现,BuildVerityMetadata 调用build_verity_metadata.py 来实现

BuildVerityMetadata 生成 metadata (metadata_image),

跳转到 system/extras/verity/build_verity_metadata.py

  • 根据 hash 树生成 dm-verity table

build_verity_table 生成 dm-table

dm-table 其实就是一个字符串

  •  dm-verity 进行签名,得到签名文件

sign_verity_table 将 dm-table 签名

signer_key = build/target/product/security/verity.pk8

  • 将签名、dm-verity table 打包到 metadata 镜像

build_metadata_block 将 dm-table 和 签名信息打包,写入 datameta.img

  •  verity metadatahash  添加到 system 镜像末尾

build/tools/releasetools/build_image.py  BuildVerifiedImage 生成最终的可以用于 dm-verity 校验的镜像

Append2Simg 添加 verity_image 和 datameta.img 到 system.img 末尾

其他

FIXED_SALT 可以修改为自己的 salt

如何生成自己的oem key

dm-verity 相关的密钥

build/target/product/security/ build/target/product/verity.mk verity.pk8 – 私钥,用于签名 boot.img 和 system.img

verity.x509.pem – 包含公钥的证书

verity_key – 公钥,dm verity 中用于验签 system 分区

   生成OEM自己的密钥对

  1. HSM(Hardware Security Module)
  1. OpenSSL tool
  • 生成新得密钥对 >openssl version OpenSSL 1.0.2d 9 Jul 2015 >development/tools/make_key mykey ‘/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com’
  • 为DM-Verity 功能生成 verity key
    1. 使用下面的命令来生成 verity key 的工具 generate_verity_key: source build/envsetup.sh choosecombo make generate_verity_key (mmm system/extras/verity/)
    2. 将 *.x509.pem 转换成 verity key generate_verity_key 的代码位于:system/extra/verity/generate_verity_key.c generate_verity_key 的用法:generate_verity_key | -convert 实例: out/host/linux-x86/bin/generate_verity_key -convert mykey.x509.pem verity_key
  • 拷贝并重命名
    1. 拷贝pk8,mykey.x509.pem,verity_key.pub 至 build/target/product/security/ 目录,将其重命名: verity.pk8, verity.x509.pem,verity_key ,并替换默认的开发 key。
  • 生成 keystore
    1. 执行下面的两个命令,生成img openssl rsa -in mykey.pk8 -inform DER -pubout -outform DER -out mypub.der java -Xmx512M -jar out/host/linux-x86/framework/KeystoreSigner.jar mykey.pk8 mykey.x509.pem keystore.img mypub.der
    2. 通过下面的脚本将img生成oem_keystore.h文件,shell 输入: function generate_oem_keystore_h() { echo \#ifndef __OEM_KEYSTORE_H echo \#define __OEM_KEYSTORE_H xxd -i $1 | sed -e ‘s/unsigned char .* = {/const unsigned char OEM_KEYSTORE[] = {/g’ -e ‘s/unsigned int .* =.*;//g’ echo \#endif }
  • generate_oem_keystore_h keystore.img > oem_keystore.h
  • 将该h文件拷贝到:bootable/bootloader/lk/platform/msm_shared/include
  1. 验签

用户空间,android 部分

相关文件:

system/core/fs_mgr/fs_mgr_verity.c

用户空间对 dm-verity 进行初始化,验签 hash_table 的签名,传入 hash_table 等参数

内核空间

相关文件:

KERNEL_SRC/driver/md/dm-verity.c 相关代码

内核空间根据用户空间传入的参数,进行初始化

当有 IO 操作时,对相应 data block 进行验签。

data block 读取时,不仅当前 data block 需要 hash 校验,上一层的 hash block 也需要进行校验,直到root hash。

每一个 data block 如果已经验签过,再次读取时就不用进行层层的校验,只校验当前 data block 的 hash 是否正确即可。

三、如何启用

  1. kernel 配置文件使能 CONFIG_DM_VERITY

kernel/arch/arm/configs/msm8909-1gb_defconfig

  1. Android 相关 mk 文件配置

device/qcom/msm8909/msm8909.mk PRODUCT_SUPPORTS_VERITY := true PRODUCT_SYSTEM_VERITY_PARTITION := /dev/block/bootdevice/by-name/system

  1. 更新 fstab,system 分区添加 verify 标志

/dev/block/bootdevice/by-name/system /system ext4 ro,barrier=1 wait,verify

  1. 编译 userdebug 或者 user 版本 boot.img 以及 system.img,烧录

四、测试

测试样例1. 无法 remount, 无法 push 文件

Mount | grep system /dev/block/dm-0 /system ext4 ro, seclable, relatime, data=ordered 0 0

adb pull /fstab.qcom c:\temp\fstab, 检查 verify 标志: /dev/block/bootdevice/by-name/system /system ext4 ro,barrier=1 wait, verify

adb remount Use “adb disable-verity” to disable verity. If you do not, remount may succeed, however, you will still not be able to write to these volumes. remount of system failed: Read-only file system remount failed

 测试样例2.

(1).先烧录启用 verity 功能的 boot.img 和 system.img

(2). 然后烧录未启用 verity 功能的 boot.img,重启后 push 一个 apk 到 /system/app/ 目录

(3). 重新烧录启用了 verity 功能的 boot.img,重启后,机器无法开机,kernel log 可以看到 data block xxx is corrupted

五、存在风险

 物理块出现坏块

  1. 开机检验出错,无法开机
  2. 开机检验没问题,读取文件出错,返回 Error IO

六、其他

软件集成和 OTA 升级,必须使用 block 方式生成 OTA 升级包,需要注意适配。

 七、参考文档

Verified Boot

https://source.android.com/security/verifiedboot/index.html

Verifying Boot

https://source.android.com/security/verifiedboot/verified-boot.html

Implementing dm-verity

https://source.android.com/security/verifiedboot/dm-verity.html

Dmverity

https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity

dm-table format

https://Git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/device-mapper/verity.txt

Device mapper

https://www.ibm.com/developerworks/cn/linux/l-devmapper/

### 回答1: Linux dm-verity是一个Linux内核模块,用于对块设备进行数据完整性校验。它通过使用哈希函数和预先计算的哈希树来实现校验,可以防止恶意修改或篡改块设备中的数据。 dm-verity的源代码位于Linux内核的"drivers/md/dm-verity.c"文件中。该文件包含了实现dm-verity功能所需的所有函数和数据结构。 dm-verity的主要流程如下: 1. 初始化:在加载模块时,dm-verity会注册自己为块设备处理器,并初始化一些数据结构和参数。 2. 设置参数:当用户通过命令行或者sysfs文件系统设置dm-verity参数时,dm-verity会解析这些参数并存储到对应的数据结构中。 3. 启动校验:当用户通过命令行或者sysfs文件系统启动dm-verity时,dm-verity会从块设备中读取哈希树,并使用哈希函数进行校验。 4. 处理请求:当用户对块设备发出读写请求时,dm-verity会拦截这些请求并进行数据校验。如果数据完整,则将请求转发到原始的块设备中;如果数据不完整,则返回错误 ### 回答2: Linux dm-verity是一种用于数据完整性校验的Linux内核模块。它通过计算数据块的校验值,确保数据在存储或传输过程中没有被篡改。下面对dm-verity的源码进行解析。 dm-verity的源码位于Linux内核的源码树中的drivers/md/dm-verity目录下。主要的源码文件包括verity_target.c、verity_blk.c和verity_metadata.c。 verity_target.c文件实现了dm-verity的核心逻辑。它定义了用于创建和管理verity设备的API接口函数。在这个文件中,dm-verity模块会将读取和写入请求传递给真实的存储设备,并使用verity_blk.c中的函数来计算和验证数据的校验值。它还负责处理校验失败的情况,例如将读取请求重定向到镜像设备。 verity_blk.c文件实现了校验块设备的功能。它使用了基本块设备的API函数,例如bio和request_queue,来处理请求。在这个文件中,校验模块会计算每个数据块的哈希值,将其与元数据中的预期值进行比较,并确定数据的完整性。这个过程是通过使用散列函数和加密算法来计算和比较校验值的。 verity_metadata.c文件定义了元数据的结构和操作函数。元数据是用于存储每个数据块的哈希值和其他校验相关信息的地方。它使用了dm自带的二叉树数据结构来组织数据块。 除了这些源码文件,dm-verity还涉及到一些其他的文件,如kconfig和Makefile等。这些文件用于配置和编译dm-verity模块,并将其与Linux内核进行集成。 总结起来,Linux dm-verity源码的解析涉及到多个文件,用于实现数据完整性校验的各个方面,包括读写请求的管理、校验值的计算和验证、元数据的存储等。通过分析这些源码文件,我们可以更深入地了解dm-verity模块的工作原理和实现细节。 ### 回答3: DM-Verity 是一种用于保护 Linux 文件系统完整性的技术。它基于数据验证和完整性保护,可防止篡改和数据损坏。DM-Verity的源代码解析可以帮助我们了解其工作原理和实现细节。 DM-Verity 的源代码主要分为两个部分:内核模块和用户空间工具。 内核模块部分是通过 Linux 内核的 Device Mapper(DM)框架实现的。它包含了核心的验证逻辑,在存储设备的块层进行数据验证。DM-Verity使用 Merkle 树的数据结构来计算和验证每个块的哈希值,这些哈希值存储在一个元数据区域中。当读取文件时,DM-Verity会对读取的数据块进行哈希计算,并与元数据中的哈希进行比对,以验证数据的完整性。如果哈希不匹配,则说明数据已被篡改。 用户空间工具部分提供了一套命令行工具来配置和管理 DM-Verity。主要的工具有 veritysetup 和 fsverityctl。veritysetup用于创建和配置DM-Verity设备,包括进行根文件系统的完整性保护。fsverityctl用于管理和查询已配置的 DM-Verity 设备,提供了一些实用的操作,比如启用和禁用 DM-Verity,查询校验结果等。 通过分析 DM-Verity 的源代码,我们可以了解到其实现的核心原理和具体实现细节。例如,可以了解到 DM-Verity 是如何在内核中通过设备映射层实现数据验证和完整性保护的。此外,还可以学习到DM-Verity如何使用 Merkle 树来计算和验证数据块的哈希值,以及如何通过元数据区域存储和管理这些哈希值。对于学习和理解 Linux 文件系统的完整性保护机制以及数据安全性的提升,DM-Verity的源代码解析是非常有价值的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值