1、AVB概要
AVB2.0被用于启动引导,此用法添加一个“vbmeta.img”镜像。
public key被编译到bootloader中用于校验vbmeta数据,vbmeta.img包含应由此public key验证的签名。
vbmeta.img包含用于验证的public key,但只有bootloader验证过vbmeta.img才会可信,就好比认证一样,包含可信public key和签名。
因此,我们在AVB中有两个重要key,一个验证vbmeta.img的OEM key,一个验证其他分区(boot/system/vendor)的verity key。当然可以使用OEM key作为verity key。
我们知道OEM key用于在bootloader阶段验证vbmeta.img。这还不够,我们必须验证其他分区,vbmeta.img包含的public key用于此目的。就像avb1.0中verity key一样,此public key用于验证system、vendor分区和boot分区。
这里有些不同之处,avb1.0使用OEM key验证boot分区,使用verity key验证system/vendor分区,但avb2.0使用OEM key验证vbmeta.img,并使用其中包含的public key验证其他分区(system/vendor/boot等)。
2、AVB流程图
非A/B系统
AVB1.0
A/B系统
AVB1.0
boot.img=kernel + ramdisk + signature,使用OEM key验证boot.img的signature合法性。
AVB2.0
正如我们上面所说,avb2.0使用OEM key来验证vbmeta.img,并使用其中所包含的public key验证其他分区。
启动时bootloader将验证两个分区,一个是使用OEM key验证vbmeta.img,一个是使用vbmeta.img所包含的public key验证boot分区,而system/vendor分区由init/fs_mgr来验证(使用vbmeta.img所包含的public key)。(注意从1.0到2.0的顺序变化)
3、VBMeta结构
AVB2.0增加了一个vbmeta分区,对应的vbmeta.img由make_vbmeta_image工具编译生成的,其主要包含如下三大部分:
vbmeta image header(256 Bytes)
authentication data
hash
signature
auxiliary data
public key
public key metadata
descriptors
hash descriptors
hashtree descriptors
chain partition descriptors
vbmeta分区保存了受保护分区的所有信息,每个被avb2.0保护的分区后面都有一个vbmeta结构。vbmeta结构中包含多个描述符(和其他元数据),并且所有这些数据都被加密签名。受保护的分区可以配置为hash分区或者chain(链式)分区:
-
hash分区:hash校验,用hash描述符中hash(保存在vbmeta分区的vbmeta结构里)验证目标分区(看目标生成的保存我这里的一样不)
-
chain分区:key校验,用chain分区描述符中的public key(保存在vbmeta分区的vbmeta结构里)验证目标分区vbmeta结构的完整性(vbmeta被private key签名)
chain分区:key校验
AVB中使用的中心数据结构是VBMeta结构,此数据结构包含多个描述符(和其他元数据),并且所有这些数据都被加密签名。描述符用于image哈希、image哈希表元数据和所谓的链式分区。
key0来自bootloader的oem_pubk。
其中主vbmeta分区在哈希描述符中保存boot分区的哈希,对于system和vendor分区,哈希表在文件系统之后,主vbmeta分区在哈希表描述符中保存哈希表的root hash、salt和offset。(这里想起前面的哈希树没–roothash)
因为vbmeta分区中的vbmeta结构是以密码方式签名的,所以bootloader可以检测签名,并验证它是有key0的所有者(例如,通过嵌入key0的公共部分)创建的,从而信任于boot、system和vendor。
链式分区描述符用于委托权限——它包含委托权限的分区名称以及该特定分区上的签名所信任的public key。
hash分区:hash校验
在这个设置中,xyz分区有一个完整性检查的哈希表,在哈希表后面是一个vbmeta结构,它包含带有哈希表元数据(root has、salt和offset等),这个结构用key1签名的。最后,在此分区的末尾是一个页脚,它具有vbmeta结构的offset。
此设置允许bootloader使用链分区描述符来查找分区末尾的页脚(使用链分区描述符中的名称),有助于帮助找到xyz分区的vbmeta结构并验证是否由key1签名的(保存在链式分区描述符中的key1 public key)。至关重要的是,因为有一个带offset的页脚,所以可以更新zyz分区,而不需要vbmeta分区进行任何更改。
白话一刻:这里的就是在vbmeta结构中,针对不同的镜像有不同的校验方式。
4、vbmeta.img中vbmeta结构
- chain分区描述符
- 保存了用于验证目标分区vbmeta结构的public key
- 如果目标分区vbmeta结构验证失败,将无法启动
- hash表描述符
- 目标分区vbmeta结构没有被使用,忽略
- hash描述符
- 除非它在“requested_partitions”中,被输入到avb2.0的入口函数:avb_slot_verify(),否则忽略目标分支vbmeta结构
vbmeta与boot/recovery/system/vendor绑定
-
配置为hash分区:必须与主vbmeta一起更新
-
配置为chain分区:假如目标分区vbmeta结构发生异常,就算此分区在当前启动模式不被使用,设备也将无法启动。
比如,假如recovery分区配置为chain分区,一旦recovery发生异常,normal boot也将无法启动
一旦recovery分区配置为hash分区,不能通过OTA改为chain分区配置
5、打开使用AVB功能
使能AVB2.0功能
android的kernel版本大于4.9,avb2.0是必须打开的。
lk:vendor/mediatek/proprietary/bootable/bootloader/lk/project/<project.mk>
MTK_AVB20_SUPPORT = yes
kernel:_debug_defconfig & _defconfig
1
CONFIG_MTK_AVB20_SUPPORT = y
配置avb分区
kernel-4.9\arch\arm64\boot\dts\mediatek\xxxx.dts
配置vbmeta.img的公钥与私钥
vbmeta.img被oem_prvk.pem进行私钥签名,在启动阶段lk使用avbkey.h中的公钥对vbmeta.img进行验证,所以avbkey.h配置的公钥与oem_prvk.pem的私钥必须是一对,且此key与secure boot校验其他分区的key不是同一个,配置文件也不是同一个,但是可以配置成同一组key。
配置受保护分区
默认不配置情况下,受保护分区采用hash分区方式,如需配置成chain分区方式,采用如下方式:
#settings for main vbmeta
BOARD_AVB_ALGORITHM := SHA256_RSA2048
BOARD_AVB_KEY_PATH := device/mediatek/common/oem_prvk.pem
ifeq ($(strip $(MAIN_VBMETA_IN_BOOT)),no)
#settings for recovery, which is configured as chain partition
BOARD_AVB_RECOVERY_KEY_PATH := device/mediatek/common/recovery_prvk.pem
BOARD_AVB_RECOVERY_ALGORITHM := SHA256_RSA2048
BOARD_AVB_RECOVERY_ROLLBACK_INDEX := 0
# Always assign "1" to BOARD_AVB_RECOVERY_ROLLBACK_INDEX_LOCATION
# if MTK_OTP_FRAMEWORK_V2 is turned on in LK. In other words,
# rollback_index_location "1" can only be assigned to
# recovery partition.
BOARD_AVB_RECOVERY_ROLLBACK_INDEX_LOCATION := 1
endif
#settings for system, which is configured as chain partition
BOARD_AVB_SYSTEM_KEY_PATH := device/mediatek/common/system_prvk.pem
BOARD_AVB_SYSTEM_ALGORITHM := SHA256_RSA2048
BOARD_AVB_SYSTEM_ROLLBACK_INDEX := 0
BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 2
- 配置了system分区为chain分区方式
- 算法为SHA256_RSA2048
- private key为device/mediatek/common/system_prvk.pem
- 当MAIN_VBMETA_IN_BOOT宏为no时,配置recovery分区为chain分区方式
6、小结
在vbmeta 中包含了 数个descriptor ,每个descriptor 描述关于镜像文件的信息。例如 boot 镜像的hash值,dtbo 镜像的hash值。system和vendor分区比较大,因此在这里存放了这两个分区的Hashtree的数据。在vbmeta的镜像文件中除了存放vbmeta struct,还有AVB 私钥(key0)对vbmeta image的签名数据,以及AVB 公钥的数据。
AVB key 是一对非对称密钥。私钥用来签名,公钥用来验证。如关系如图所示:
其中key在源代码中存放的位置如下:
私钥
${MY_ANDROID}/device/fsl/common/security/xxxx_private.pem
公钥
${MY_ANDROID}/device/fsl/common/security/xxxx_public.bin.
为了更直观地了解vbmeta struct deneirong,我们可以根据Android 提供的工具,分析下vbmeta文件镜像的内容。命令下下:
Vbmeta image can be parsed using avbtool in Android.
$ cd ${MY_ANDROID}/out/target/product/xxxx
$ ../../../../external/avb/avbtool info_image --image vbmeta.img > vbmeta.img.info
$ cat vbmeta.img.info
还得为 dm-verity 表签名,为 dm-verity 表签名以生成表签名。在验证分区时,会首先验证表签名。该验证是对照位于启动映像上某个固定位置的密钥来完成的。密钥通常包含在制造商的构建系统中,以便自动添加到设备上的固定位置。
DM-verity 的私钥在source code的地址:
${MY_ANDROID}/build/target/product/security/verity_private_dev_key.
公钥所在地址:
${MY_ANDROID}/build/target/product/security/verity_key.
对dm-verity table 签名之后,公钥放在boot镜像文件所在的分区中。
签名得对vbmeta签名,还得对dm-verity 表签名。为啥还得对表签名?这涉及到对于dm-verity table的理解。和hashtree 相对应的dm-verity table。
前面说过每个block都在hash-tree中记录了对应的hash值,这样就能防止别人篡改block的内容了,但是如果黑客把block改了之后,重新计算hash把hash-tree中对应的hash值也改了呢,这样就能神不知鬼不觉了,所以必须要有一种机制防止hash-tree被篡改,hash-tree是这样一种结构,所有的block对应的hash值放在最底层,也就是第0层,Android中采用的方法是算root-hash的签名,verity-table中保存了root-hash,对verity-table进行签名。
verity-table的校验是在用户空间(/system/core/fs_mgr/ )中完成的,校验合法之后会将verity-table传给kernel使用。
最后整个安全启动过程:
1.在刚启动的时候芯片rom对bootloader,或者如果使能了TEE OS,还包括对TEE 镜像的验证。
2.bootloader 对boot.img(kernel) 进行验证.
3.kernel启动完成后,对/system /vendor分区进行验证
第二步和第三步就是AVB的过程
这部分的理解还是存在局部的细节问题,等待继续思考学习
参考资料:文章来源:https://www.toymoban.com/news/detail-422142.html
https://ressrc.com/2018/10/07/android-p
https://android.googlesource.com/platform/external/avb/+/master/README.md#The-VBMeta-struct
https://blog.csdn.net/StevenYang2008/article/details/106747458/文章来源地址https://www.toymoban.com/news/detail-422142.html
到了这里,关于Android安全启动学习(五):Android Verified Boot 2.0的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!