Android安全启动学习(五):Android Verified Boot 2.0

简介: Android安全启动学习(五):Android Verified Boot 2.0

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的过程

这部分的理解还是存在局部的细节问题,等待继续思考学习


目录
相关文章
|
1月前
|
XML 缓存 Android开发
Android开发,使用kotlin学习多媒体功能(详细)
Android开发,使用kotlin学习多媒体功能(详细)
90 0
|
3月前
|
安全 Linux Android开发
Android 安全功能
Android 安全功能
37 0
|
3月前
|
存储 安全 Linux
Android安全启动学习(四):device-mapper-verity (dm-verity)和哈希树
Android安全启动学习(四):device-mapper-verity (dm-verity)和哈希树
116 0
|
3月前
|
存储 算法 安全
AVB数据解析:Android verified boot 2.0 vbmeta 数据结构解析
AVB数据解析:Android verified boot 2.0 vbmeta 数据结构解析
115 0
|
3月前
|
存储 算法 Android开发
AVB校验微观版本:android avb(Android Verified Boot)验证
AVB校验微观版本:android avb(Android Verified Boot)验证
209 0
|
3月前
|
开发框架 物联网 数据库
89个android学习样例源码
89个android学习样例源码
75 0
|
3月前
|
Java Android开发 C++
2023安卓逆向 -- JNI学习(从开发到反编译)
2023安卓逆向 -- JNI学习(从开发到反编译)
19 0
|
3月前
|
Android开发
Android源码学习(五):AVB2.0-libavb库介绍2
Android源码学习(五):AVB2.0-libavb库介绍2
101 0
|
17天前
|
Java Android开发
Android 开发获取通知栏权限时会出现两个应用图标
Android 开发获取通知栏权限时会出现两个应用图标
12 0