android dm-verity 功能【转】
转自:https://blog.csdn.net/ee230/article/details/73348344
Android dm-verity 实现原理深入研究
思维导图:
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 错误
框架示意图:
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,5在BuildVerityMetadata中实现,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 metadata,hash 树 添加到 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自己的密钥对
- HSM(Hardware Security Module)
- 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
- 使用下面的命令来生成 verity key 的工具 generate_verity_key: source build/envsetup.sh choosecombo make generate_verity_key (mmm system/extras/verity/)
- 将 *.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
- 拷贝并重命名
- 拷贝pk8,mykey.x509.pem,verity_key.pub 至 build/target/product/security/ 目录,将其重命名: verity.pk8, verity.x509.pem,verity_key ,并替换默认的开发 key。
- 生成 keystore
- 执行下面的两个命令,生成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
- 通过下面的脚本将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
- 验签
用户空间,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 是否正确即可。
三、如何启用
- kernel 配置文件使能 CONFIG_DM_VERITY
kernel/arch/arm/configs/msm8909-1gb_defconfig
- Android 相关 mk 文件配置
device/qcom/msm8909/msm8909.mk PRODUCT_SUPPORTS_VERITY := true PRODUCT_SYSTEM_VERITY_PARTITION := /dev/block/bootdevice/by-name/system
- 更新 fstab,system 分区添加 verify 标志
/dev/block/bootdevice/by-name/system /system ext4 ro,barrier=1 wait,verify
- 编译 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
五、存在风险
物理块出现坏块
- 开机检验出错,无法开机
- 开机检验没问题,读取文件出错,返回 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/
android dm-verity 功能【转】的更多相关文章
- Android Studio调试功能使用总结【转】
Android Studio调试功能使用总结[转] 这段时间一直在使用Intellij IDEA, 今天把调试区工具的使用方法记录于此. 先编译好要调试的程序. 1.设置断点 选定要设置断点的代码 ...
- Android 实现闹钟功能
原文地址:Android 实现闹钟功能作者:Android_Learners 一.手机闹钟主要用到了AlarmManager类,AlarmManager类提供了访问系统定时服务的途径,开发人员可以 ...
- Android Studio调试功能使用总结---转
Android Studio调试功能使用总结[转] 这段时间一直在使用Intellij IDEA, 今天把调试区工具的使用方法记录于此. 先编译好要调试的程序. 1.设置断点 选定要设置断点的代码 ...
- 集成Android免费语音合成功能(在线、离线、离在线融合)
集成Android免费语音合成功能(在线.离线.离在线融合),有这一篇文章就够了(离线)集成Android免费语音合成功能(在线.离线.离在线融合),有这一篇文章就够了(离在线融合) 转眼间,大半年没 ...
- Android中选项卡功能的实现
Android中选项卡功能的实现 Android中使用TabHost和TabWidget来实现选项卡功能.TabHost必须是布局的根节点,它包含两个子节点: TabWidget,显示选项卡: Fra ...
- Android社会化分享功能的实现步骤
众所周知,互联网是一个资源共享的地方,在网络上,我们可以分享我们所有认为好的资源.而随着互联网信息爆发式的增长,我们习惯了一键分享功能,比如:微博分享.微信分享.QQ空间分享.人人网分享等等.由此可见 ...
- Android微信分享功能实例+demo
Android微信分享功能实例 1 微信开放平台注册 2 获得appId,添加到程序中,并运行程序 3 使用应用签名apk生成签名,添加到微信开放平台应用签名,完成注册 4 测试分享功能. 有问题请留 ...
- (转载) Android 带清除功能的输入框控件ClearEditText,仿IOS的输入框
Android 带清除功能的输入框控件ClearEditText,仿IOS的输入框 标签: Android清除功能EditText仿IOS的输入框 2013-09-04 17:33 70865人阅读 ...
- Android 调用摄像头功能【拍照与视频】
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/ma_hoking/article/details/28292973 应用场景: 在Android开发 ...
- Android开启OTG功能/USB Host API功能
Android USB 模式简介 设备模式 当计算机或其他USB主机需要连接安卓设备时,此时安卓设备是作为"USB设备"角色的,在计算机上显示为 USB 外设.现在的安卓设备已经被 ...
随机推荐
- 信用评分卡 (part 1 of 7)
python信用评分卡(附代码,博主录制) https://study.163.com/course/introduction.htm?courseId=1005214003&utm_camp ...
- 使用二进制安装包的方式单机部署MySQL8.0.13
使用二进制安装包的方式单机部署MySQL8.0.13 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 关于MySQL的介绍我这里就不多做赘述了,如何下载MySQL详情请参考:MySQ ...
- ES DSL 基础查询语法学习笔记
1.查询数量 1 2 3 4 5 6 7 curl -XGET 'http://192.168.6.97:9200/_count?pretty' -d ' { "query" ...
- mysql引擎,完整的见表语句,数据库模式, 常用数据类型,约束条件
引擎 show engines : 查看引擎 innodb(默认引擎):支持事务,行级锁,外键 myisam:查询效率由于innodb,不需要支持事务,行级锁,外键,可以选用myisam来优化数据库 ...
- Spring boot中使用Mongodb
安装 使用Idea新建Spring boot工程时需要选择Mongodb 或者在工程中加入依赖 Maven: <dependency> <groupId>org.springf ...
- 混合app开发--js和webview之间的交互总结
使用场景:原生APP内嵌套H5页面,app使用的是webview框架进行嵌套 这样就存在两种情况 1.原生app调用H5的方法 2.H5调用app的方法 分别讲解下,其实app与H5之间的交互式非常简 ...
- 【转载】C++ getline函数用法
https://www.cnblogs.com/xiaofeiIDO/p/8574042.html 摘要: 通过getline()函数一个小小的实例,那么把getline()函数作为while的判断语 ...
- MySQL数据库基本命令-1
第一章:数据库概述1.数据(data) 数据库(DB) 数据库管理系统(DBMS) 数据库系统(DBS)2.数据库管理系统提供的功能: (1)数据定义语言:DDL (2)数据操作语言:DML 基本的数 ...
- GCC编译器原理(一)------交叉编译器制作和GCC组件及命令
1.1 交叉编译器制作 默认安装的 GCC 编译系统所产生的代码适用于本机,即运行 GCC 的机器,但也可将 GCC 安装成能够生成其他的机器代码.安装一些必须的模块,就可产生多种目标机器代码,而且可 ...
- [译]Use Dependency Injection In WebForms Application
怎么在已用的WebForm应用中使用DI 假设有一个电影网站,有个页面会列出最近热门的电影.这个项目中使用了仓储模式来获取数据. public partial class Default : Syst ...