Android Verified Boot 使能方式

一、使能Verified Boot 1.0

1.1 使能配置

(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 生成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.3 验证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
#qualcomm
adb pull vendor/etc/fstab.qcom .

二、使能AVB 2.0

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

2.1 使能配置

(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 分区签名文件存储位置

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.3 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.4 自定义密钥方式

默认情况下,算法”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>