宅科技 - 科技,宅出新生活

搜索
热搜: 活动 交友 discuz
如果你还没有论坛的账号,赶快注册吧!
立即注册

合作站点账号登陆

快捷导航
查看: 1652|回复: 0

[移动安全] system分区签名校验方法

[复制链接] [提交至百度]

93

主题

96

帖子

2135

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2135
发表于 2018-8-28 14:16:11 | 显示全部楼层 |阅读模式
扫码领红包
签名过程
整个system签名过程如下图所示:
  • 哈希树的生成
Dm-verity 使用加密散列树提供块设备的透明完整性检查,每个块以 4k 的大小来划分,都有一个 SHA256 的值。树中的每个节点是加密 hash,其中叶节点包含物理数据块的 hash,并且中间节点包含其子节点的 hash。因为根节点中的哈希是基于所有其他节点的值,所以只有根哈希需要被信任才能验证树的其余部分。对任何一个节点块的改动都破坏整个加密 hash。整个哈希树的结构如下图所示:
  • dm-verity table的生成
根据上面生成的哈希树,调用build_verity_metadata.py脚本生成dm-verity table。实际上dm-verity table就是描述之前生成的hash tree的一段字符串,该table中的内容是需要传递给dm-verity使用的。这个dm-verity table的组成格式需要参考内核dm-verity的文档:Documentation/device-mapper/verity.txt
Construction Parameters =======================     <version> <dev> <hash_dev>     <data_block_size> <hash_block_size>     <num_data_blocks> <hash_start_block>     <algorithm> <digest> <salt>     [<#opt_params> <opt_params>
可以看到其中包含了hash tree的根节点,总共多少个block,每个block的大小,加盐值,算法名称等等关键数据。这个table最终是需要校验通过后传递给内核中的dm-verity驱动的。
  • RSA数字签名的生成
对dm-verity table进行签名生成数字签名,和dm-verity table一起放在system分区的后面。
  • 打包生成verity-metadata
把上面生成的dm-verity table和数字签名一起打包生成verity-metadata.img
  • system.img的组成
和上图中描述的一致,包含了system data/verity-metadata.img/verity.img,分别对应的打包数据内容是system data/dm-verity table+signature/hash tree。
校验过程
init代码中是会调用libfs_mgr库中的函数来挂载分区,所以分区校验的关键过程实现是在fs_mgr中。fs_mgr会读取该boot.img中的公钥key,高通平台的verity_key存放在ramdisk的根目录下。init中是通过do_mount/do_mount_all来实现分区挂载,对应到init.rc中的命令就是mount/mount_all。所以init.rc中需要定义mount或者mount_all来挂载对应的分区。mount_all是会查找fstab文件中的定义来挂载分区的。被验证的目标分区,有着一个包含了dm-verity table和它自身签名的元数据块,被附加到镜像的最后,通过在 fstab 文件中对挂载设备添加 verify 标签,在挂载时,当fs_mgr检测到该标签,则会使用 verity_key 公钥加载校验该分区最后附加的元数据。如果签名验证通过,则会把解析出的 dm-verity table 传递给内核,内核中的dm-verity驱动根据table包含的信息来创建虚拟的 dm-verity 块设备,然后将该虚拟块设备安装在 fstab 中指定的安装点上。因此,所有读自底层物理设备的数据都会用预先生成的hash tree散列树进行验证。对设备任何修改或添加文件,包括重新挂载为读写权限都会引起 I/O 错误。
示例如下:
fstab:/dev/block/bootdevice/by-name/system       /system     ext4     ro,barrier=1     wait, verify使用fstab来挂载
可执行文件:
init/fs_mgr
代码:
system/core/initsystem/core/fs_mgrAndroid O + avb 2.0 + A/B system
使能了A/B system之后,android O把rootfs和system data集成到一起放到system分区了(也就是说system.img会被挂载到/根目录上,其中包含了system),boot分区只存放kernel,所以校验方法如下图所示,首先bootloader需要用公钥校验vbmeta的签名,以及boot签名和system签名,签名验证通过之后才允许下一步booting,校验签名完成之后,会启动kernel,并把system分区中的rootfs相关的dm-verity数据通过cmdline的形式传递给kernel,kernel启动会挂载rootfs(注意rootfs中包含了system,两者为同一个分区),所以可以认为system的挂载是在kernel中完成的,并且使用dm-verity模式进行的挂载。
为什么要让bootloader去检验签名system分区签名并且kernel去挂载呢?我一直有这个疑问,按照以往的项目,都是fs_mgr和init中的mount来做签名校验和挂载system分区的,原因是rootfs被放置在system分区,而fs_mgr和init都都在rootfs中,如果kernel不去挂载system分区到rootfs上,我们根本是无法执行其中的init和fs_mgr程序去校验签名。
注意:1.上表中的keystore就是vbmeta分区2.bootloader使用的是uefi3.A/Bsystem使能后,system.img会被挂载到/根目录上,这就意味着fs_mgr/init也存在与system.img中,因而不能被用来system自己了。4.system分区是被bootloader使用公钥校验,并由kernel中的dm-verity挂载的,所需要的信息通过cmdline传递。Android O + avb 2.0 + Non-A/B system
未使能A/Bsystem特性的android o,ramdisk是和kernel一起编译进boot分区的,因此我们依然采用传统的方式来校验分区,首先是bootloader校验boot分区中的签名,然后启动kernel,kernel挂载ramdisk,fs_mgr和init都在ramdisk中,所以可以由init/fs_mgr来进行后续分区的挂载。
由于Android O的特性,很多ko驱动模块被单独编译出来并放置于system分区中,所以我们需要在init的stage one第一阶段就把system分区挂载上,并insmode其中的模块,如果不如此,后续的启动流程可能会失败,因为很多关键的驱动ko都没有加载。init会在init_first_stage的第一阶段就调用fs_mgr中的相关函数把system分区校验并挂载起来,并且insmod其中的一些ko驱动。而其他分区依然在fstab中配置并在以后进行挂载,当然如果使用了AVB 2.0,那么需要调用libavb中的一些函数来实现校验的过程。




上一篇:教你如何生成用于 Verifiedboot 的 system.img
下一篇:魅蓝NOTE6 超级简单 快速获取ROOT的方法
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

微信公众号
微信扫码关注,
回复“领取金币”
每周抽取5位
会员奖励500金币

手机版|小黑屋|网站地图|宅科技 ( 粤ICP备15107403号

GMT+8, 2019-11-15 13:44 , Processed in 0.708635 second(s), 26 queries .

Copyright © 2016 宅科技 | 智能终端极客社区

Powered by Discuz! X3.4 Licensed

快速回复 返回顶部 返回列表