Android Verified Boot 使能方式

一、使能Verified Boot 1.0

1.1 QCT平台使能配置

(1)在kernel/msm-4.4/arch/arm64/configs/$project_defconfig中打开dm-verity功能:

1
2
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y

(2)在device/qcom/common/base.mk中启用system/vendor签名:

1
2
3
4
5
6
7
ifneq ($(BOARD_AVB_ENABLE), true)
PRODUCT_SYSTEM_VERITY_PARTITION=/dev/block/bootdevice/by-name/system
ifeq ($(ENABLE_VENDOR_IMAGE), true)
PRODUCT_VENDOR_VERITY_PARTITION=/dev/block/bootdevice/by-name/vendor
endif
$(call inherit-product, build/target/product/verity.mk)
endif

(3)在device/$manufacturer/$project/$project.mk中启用PRODUCT_SUPPORTS_VERITY:

1
2
3
ifneq ($(BOARD_AVB_ENABLE), true)
PRODUCT_SUPPORTS_VERITY := true
endif

(4)在device/$manufacturer/$project/fstab.qti中为system/vendor添加verify flag:

1
2
/dev/block/bootdevice/by-name/system  /   ext4   ro,barrier=1,discard   wait,verify
/dev/block/bootdevice/by-name/vendor /vendor ext4 ro,barrier=1,discard wait,verify

(5)在kernel/msm-4.4/arch/arm64/boot/dts/qcom/$platform.dtsi中为system/vendor添加verify flag:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
firmware: firmware {
android {
compatible = "android,firmware";
fstab {
compatible = "android,fstab";
vendor {
compatible = "android,vendor";
dev = "/dev/block/platform/soc/7824900.sdhci/by-name/vendor";
type = "ext4";
mnt_flags = "ro,barrier=1,discard";
fsmgr_flags = "wait,verify";
status = "ok";
};
system {
compatible = "android,system";
dev = "/dev/block/platform/soc/7824900.sdhci/by-name/system";
type = "ext4";
mnt_flags = "ro,barrier=1,discard";
fsmgr_flags = "wait,verify";
status = "ok";
};
};
};
};

1.2 MTK平台使能配置

(1)在kernel-4.4/arch/arm64/configs/${project}_defconfig中打开dm-verity功能:

1
2
3
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
# CONFIG_MTK_DM_VERITY_OFF is not set

(2)在device/mediatek/common/device.mk中启用system/vendor签名:

1
2
PRODUCT_SYSTEM_VERITY_PARTITION := /dev/block/platform/bootdevice/by-name/system
PRODUCT_VENDOR_VERITY_PARTITION := /dev/block/platform/bootdevice/by-name/vendor

(3)在device/$manufacturer/$project/ProjectConfig.mk中关闭MTK_DM_VERITY_OFF宏:

1
MTK_DM_VERITY_OFF=no

(4)在kernel-4.9/arch/arm64/boot/dts/mtxxxx.dts或kernel-4.9/arch/arm/boot/dts/mtxxxx.dts中在fsmgr_flag中添加verify。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
firmware {
android {
compatible="android,firmware";
fstab {
compatible="android,fstab";
#ifndef CONFIG_MTK_AB_OTA_UPDATER
system {
compatible="android,system";
dev="/dev/block/platform/mtk-msdc.0/1123000.msdc0/by-name/system"
type="ext4"
mnt_flags="ro"
fsmgr_flags="wait,verify"
};
#endif
#ifndef CONFIG_MTK_LATE_MOUNT
vendor {
compatible="android,vendor"
dev="/dev/block/platform/mtk-msdc.0/1123000.msdc0/by-name/vendor"
type="ext4"
mnt_flags="ro";
#ifndef CONFIG_MTK_AB_OTA_UPDATER
fsmgr_flags="wait,verify";
#else
#ifndef CONFIG_MTK_DM_VERITY_OFF
fsmgr_flags="wait,slotselect,verify"

(5)在vendor/mediatek/proprietary/bootable/bootloader/lk/project/$project.mk中关闭MTK_DM_VERITY_OFF宏:

1
MTK_DM_VERITY_OFF=no

1.3 生成verity key的方式

(1)生成RSA密钥对

1
openssl genrsa -out prvk.pem 2048

(2)生成verity.pk8

1
openssl pkcs8 -topk8 -inform PEM -outform DER -in prvk.pem -out verity.pk8 -nocrypt

(3)生成verity.x509.pem和verity.x509

1
2
openssl req -new -x509 -key prvk.pem -out verity.x509.pem -ha256
openssl x509 -n verity.x509.pem -outform der -out verity.x509

(4)执行下面命令可以在out/host/linux-x86/bin目录生成generate_verity_key工具。

1
2
3
make generate_verity_key

mmm system/extras/verity

(5)通过generate_verity_key工具将verity.x509.pem转换为verity_key。

1
2
./out/host/linux-x86/bin/generate_verity_key -convert verity.x509.pem verity_key
mv verity_key.pub verity_key

(6)将key拷贝到指定目录。

1
2
3
4
cp verity.pk8/verity.x509.pem/verity_key to build/target/product/security/
cp verity.x509.pem to build/target/product/security/
cp verity_key to build/target/product/security/
cp verity.x509.pem to kernel-4.4/certs/verity.x509.pem

1.4 验证DM-VERITY功能方式

(1)执行下面指令挂载分区后,若system分区中包含dm-x字样即表明dm-verity功能已启用

1
2
3
4
$adb shell mount | grep system
/dev/block/dm-0 /system ext4 ro, seclable, relatime, data=ordered 0 0
$adb shell mount -o rw,remount /system
Buffer I/O error on device dm-0, logical block 0 Lost page write due to I/O error on dm-0

(2)从vendor/etc中导入fstab文件,检查是否包含verify flag。

1
2
3
4
#mediatek
adb pull vendor/etc/fstab.mtxxxx .
#qualcomm
adb pull vendor/etc/fstab.qcom .

二、使能AVB 2.0

注:如果平台使用的kernel版本大于等于4.9,并且是Android P版本,AVB2.0是必须要开启的。

2.1 QCT平台使能配置

(1)在device/$manufacturer/$project/$project.mk中打开BOARD_AVB_ENABLE宏,并做如下配置:

1
2
3
4
5
BOARD_AVB_ENABLE := true
BOARD_AVB_SYSTEM_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
BOARD_AVB_SYSTEM_ALGORITHM := SHA256_RSA2048
BOARD_AVB_SYSTEM_ROLLBACK_INDEX := 0
BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 2

(2)还可以根据需要添加以下配置:

配置 选项
BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS –set_hashtree_disabled_flag
BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS –hash_algorithm –salt
BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS –hash_algorithm –salt –block_size –do_not_generate_fec
BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS –hash_algorithm –salt –block_size –do_not_generate_fec
BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS –hash_algorithm –salt

2.2 MTK平台使能配置

(1)在device/mediatek/common/device.mk中打开AVB宏,配置 key:

1
2
3
BOARD_AVB_ENABLE := true
BOARD_AVB_ALGORITHM := SHA256_RSA2048
BOARD_AVB_KEY_PATH := device/mediatek/common/oem_prvk.pem

(2)在vendor/mediatek/proprietary/bootable/bootloader/lk/target/$project/inc/avbkey.h中配置oem_prvk.pem对应的public key(用于校验vbmeta中的public key合法性) 。

(3)在vendor/mediate/proprietary/bootable/bootloader/lk/platform/$platform/rules.mk打开AVB20宏:

1
MTK_AVB20_SUPPORT=yes

(4)在kernel-4.9/arch/arm64/configs/$porject_defconfig打开AVB宏:

1
CONFIG_MTK_AVB20_SUPPORT=y

(5)如有需要可在device/mediatek/common/device.mk中为recovery/system添加chain partition配置,否则默认为hash partition:

1
2
3
4
5
6
7
8
9
10
11
12
#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
# 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

注:MTK默认会调用自己的脚本将dtbo改为mtk签名方式,即不受AVB 2.0保护。但是如果编译OTA包,又会改用AVB签名方式。

2.3 分区签名文件存储位置

partition meta verifier verify key enable dm-verity mount partition
vbmeta bootloader oem_pubk N/A fs_mgr
boot bootloader boot_pubk N/A fs_mgr
dtbo bootloader dtbo_pubk N/A fs_mgr
system bootloader system_pubk kernel kernel
vendor bootloader and fs_mgr vendor_pubk fs_mgr fs_mgr

2.4 command line中vbmeta信息

1
2
3
4
5
6
7
androidboot.vbmeta.device=PARTUUID=9c1520f3-c2c5-4b89-8284-fe4c61208a9e
androidboot.vbmeta.avb_version=1.0
androidboot.vbmeta.device_state=locked
androidboot.vbmeta.hash_alg=sha256
androidboot.vbmeta.size=1792
androidboot.vbmeta.digest=20cddc43f2e23ba5b55f5e4179a1bc1a8dc07be48d83f0bc94587c42c1b140e
androidboot.vbmeta.invalidate_on_error=yes

2.5 自定义密钥方式

默认情况下,算法”SHA256_RSA4096”与”external / avb / test / data”目录中的测试密钥一起使用。可以使用BOARD_AVB_ALGORITHMBOARD_AVB_KEY_PATH变量来覆盖它以使用例如4096位RSA密钥和SHA-512:

1
2
BOARD_AVB_ALGORITHM:= SHA512_RSA4096
BOARD_AVB_KEY_PATH:= device/qcom/common/rsa_key_4096.pem

该密钥的公共部分必须可用于设备的bootloader,以验证image。使用avbtool extract_public_key以预期格式提取密钥avbpubkey。

(1)生成oem.key

1
openssl genrsa -out oem.key -f4 4096

(2)用oem.key替换external/avb/test/data/testkey_rsa4096.pem

(3)在bootable/bootloader/edk2/QcomModulePkg/Include/Library/DeviceInfo.h中保存该key。

1
2
3
4
5
typedef struct device_info {
<snip>
UINT32 user_public_key_length;
CHAR8 user_public_key[MAX_USER_KEY_SIZE]; <snip>
}DeviceInfo;

(4)在bootable/bootloader/edk2/QcomModulePkg/Library/avb/OEMPublicKey.h或
bootable/bootloader/lk/platform/msm_shared/avb/OEMPublicKey.h中保存key

1
2
3
4
5
/**
* Internal builds use TestKeyRSA4096Public
* OEM should replace this Array with public key used to sign boot.img * avbtool extract_public_key --key KEY --output OUTPUT
*/
static const char OEMPublicKey[] = {
1
2
3
openssl pkcs8 -inform DER -nocrypt -in <PRODUCT_VERITY_SIGNING_KEY> -out <RSA_PUBLIC_KEY_PEM>
openssl rsa –in <RSA_PUBLIC_KEY_PEM> -pubout –outform DER –out <RSA_PUBLIC_KEY_DER>
keystore_signer <PRODUCT_VERITY_SIGNING_KEY> <verity.x509.pem> <KEYSTORE_IMG> <RSA_PUBLIC_KEY_DER>