搜索
热搜: 活动 交友 discuz
查看: 1865|回复: 0

[知识科普] system分区签名校验方法

[复制链接]

43

主题

44

帖子

1160

积分

超级版主

Rank: 8Rank: 8

积分
1160
发表于 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 =======================                             [ 可以看到其中包含了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中的一些函数来实现校验的过程。

来源:{http://bbs.zecoki.com/forum-70-1.html}
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




上一篇:修改2K屏幕降为1080P的方法
下一篇:Android 8.0学习---模块化内核
回复

使用道具 举报

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

本版积分规则

抖音账号
关注抖音
加入粉丝群,抽取论坛金币


Archiver|手机版|小黑屋|IT趣-GEEK社区

GMT+8, 2024-5-3 02:33 , Processed in 0.136724 second(s), 23 queries .

Powered by Discuz! X3.4. 技术支持 by 巅峰设计

© 2001-2013 Comsenz Inc.

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