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

思维导图:

android dm-verity 功能_第1张图片dm-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 错误

框架示意图:

android dm-verity 功能_第2张图片dm-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/

转载:http://kevinems.com/software-development/600.html

更多相关文章

  1. Android SAX解析xml文件
  2. android studio无法在可视化页面预览布局文件
  3. 我的hosts文件
  4. Android学习笔记(九) Android文件读写操作
  5. android的各种*.img 文件
  6. Android Studio sdk tools文件夹下文件缺失问题以及解决方法
  7. Android中xml文件解析 SAX方式 与 PULL方式
  8. android studio so文件导入

随机推荐

  1. Android(安卓)Studio的基本控件 图片框与
  2. Android中自动朗读(TTS)的简单使用
  3. Android 插件化 动态升级
  4. Android(安卓)WebView的加载超时处理
  5. AndroidManifest.xml文件剖析
  6. android Aspectj实践问题
  7. android 一个很漂亮的控件ObservableScro
  8. Android性能调优总结
  9. 简析Android对Linux内核的改动
  10. Android开发秘籍学习笔记(八)