Android Verified Boot 相关工具

一、libavb库

1.1 目录结构

libavb库用于在设备端执行所有验证,在代码中的路径是external/avb。其目录结构如下:

(1)libavb:image验证的实现。具有高度可移植性。此代码会兼容C99的C编译器。其中avb_rsa.c/avb_rsa.h和avb_sha.c/avb_sha.h用于内部实现,不应在外部被使用。avb_sysdeps.h用于定义由平台提供的系统依赖项。如果平台提供了标准的C runtime,则可以使用avb_sysdeps_posix.c。

(2)libavb_atx:用于验证public key metadata的Android Things扩展。

(3)libavb_user:用于Android用户空间的AvbOps实现。在boot_control.avb和avbctl中被使用。

(4)libavb_ab:用于bootloader和适用于A/B系统的AVB实现(已于2018年6月1日弃用,必须定义AVB_AB_I_UNDERSTAND_LIBAVB_AB_IS_DEPRECATED才能使用它)。

(5)boot_control:使用libavb_ab 堆栈与bootloader一起使用的Android boot_control HAL的实现(已于2018年6月1日弃用)。

(6)contrib:包含其他项目中与AVB互操作性所需的patch。

(7)Android.bp:用于编译设备静态库libavb,单元测试的host库和单元测试的编译说明。

(8)avbtool:用于处理与verified boot相关的image。

(9)test:abvtool,libavb,libavb_ab和libavb_atx的单元测试代码。

(10)tool/ avbctl:可用于在Android runtime控制AVB的工具的源代码。

(11)example/ UEFI:使用libavb和libavb_ab的基于UEFI的bootloader的源代码。

(12)example/things:包含适用于Android Things的slot验证的源代码。

(13)README.md:说明文档。

(14)docs:包含文档文件。

1.2 版本号

avbtool有三个字段的版本号:主版本.次版本.子版本。如1.4.3中”1”代表主版本号,”4”代表次版本号,”3”代表子版本号。仅当兼容性有问题时,major version才会被改变,如结构字段已被删除或更改的情况出现。minor version只有在引入了新功能的情况下才会被更改,如已添加新算法或描述符。修正错误或进行其他不影响兼容性的更改时,sub version会增加。

在avb_vbmeta_image.h中定义AvbVBMetaImageHeader结构会带有libavb的主要版本号和次要版本号,用于验证相关结构。它存储在required_libavb_version_major和required_libavb_version_minor字段中。此外,此结构还包含一个文本字段,其中包含用于创建该结构的avbtool版本,例如”avbtool 1.4.3”或”avbtool 1.4.3 some_board Git-4589fbec”。如下图所示:

1
2
3
required_libavb_version_major = 1
required_libavb_version_minor = 0
avbtool_release_string = "avbtool 1.4.3"

二、avbtool脚本

2.1 编译image

(1)boot.img

1
2
3
4
5
6
out/host/linux-x86/bin/avbtool add_hash_footer \
--image out/target/product/mh4/boot.img \
--partition_size 0x04000000 \
--partition_name boot \
--algorithm SHA256_RSA4096 \
--key external/avb/test/data/testkey_rsa4096.pem

(2)dtbo.img

1
2
3
4
5
6
out/host/linux-x86/bin/avbtool add_hash_footer \
--image out/target/product/mh4/dtbo.img \
--partition_size 0x0800000 \
--partition_name dtbo \
--algorithm SHA256_RSA4096 \
--key external/avb/test/data/testkey_rsa4096.pem

(3)system.img

1
2
3
4
5
6
out/host/linux-x86/bin/avbtool add_hashtree_footer \
--partition_size 2797600768\
--partition_name system \
--image out/target/product/mh4/system.img \
--algorithm SHA256_RSA4096 \
--key external/avb/test/data/testkey_rsa4096.pem

(4)vendor.img

1
2
3
4
5
6
out/host/linux-x86/bin/avbtool add_hashtree_footer
--partition_size 654311424\
--partition_name vendor \
--image out/target/product/mh4/vendor.img \
--algorithm SHA256_RSA4096 \
--key external/avb/test/data/testkey_rsa4096.pem

(5)product.img

1
2
3
4
5
6
out/host/linux-x86/bin/avbtool add_hashtree_footer
--partition_size 1442840576\
--partition_name product\
--image out/target/product/mh4/product.img \
--algorithm SHA256_RSA4096 \
--key external/avb/test/data/testkey_rsa4096.pem

(6)vbmeta.img

1
2
3
4
5
6
7
8
9
10
out/host/linux-x86/bin/avbtool make_vbmeta_image
--include_descriptors_from_image out/target/product/mh4/boot.img \
--include_descriptors_from_image out/target/product/mh4/system.img \
--include_descriptors_from_image out/target/product/mh4/vendor.img \
--include_descriptors_from_image out/target/product/mh4/product.img \
--include_descriptors_from_image out/target/product/mh4/dtbo.img \
--setup_as_rootfs_from_kernel out/target/product/tf10/obj/PACKAGING/systemimage_intermediates/system.img \
--algorithm SHA256_RSA4096 \
--key external/avb/test/data/testkey_rsa4096.pem \
--output out/target/product/m4/vbmeta.img

2.2 获取image信息

(1)boot.img

执行指令:avbtool info_image –image boot.img > boot.img.info,然后用文本编辑器打开boot.img.info文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Footer version:           1.0
Image size: 67108864 bytes
Original image size: 22110208 bytes
VBMeta offset: 22110208
VBMeta size: 512 bytes
--
Minimum libavb version: 1.0
Header Block: 256 bytes
Authentication Block: 0 bytes
Auxiliary Block: 256 bytes
Algorithm: NONE
Rollback Index: 0
Flags: 0
Release String: 'avbtool 1.1.0'
Descriptors:
Hash descriptor:
Image Size: 22110208 bytes
Hash Algorithm: sha256
Partition Name: boot
Salt: 7b4dfcca246616c387ebf9c1f27607b714e1884fdbbf3d8f635401f18ce90072
Digest: 3a076b7ec8052cc6d4b8e75a41e0bcca542f3ab52ff23ea718693ddcebc18a5a
Flags: 0

(2)dtbo.img

执行指令:avbtool info_image –image dtbo.img > dtbo.img.info,然后用文本编辑器打开dtbo.img.info文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Footer version:           1.0
Image size: 8388608 bytes
Original image size: 884876 bytes
VBMeta offset: 888832
VBMeta size: 512 bytes
--
Minimum libavb version: 1.0
Header Block: 256 bytes
Authentication Block: 0 bytes
Auxiliary Block: 256 bytes
Algorithm: NONE
Rollback Index: 0
Flags: 0
Release String: 'avbtool 1.1.0'
Descriptors:
Hash descriptor:
Image Size: 884876 bytes
Hash Algorithm: sha256
Partition Name: dtbo
Salt: edd273c37eff93d2fae049a507c54ff291878a7351aaa4d4faa9347c22b300bc
Digest: 393d3a964874db65e566798dc5b369d66beec4391e7192912b9cbcdfbfd2423e
Flags: 0

(3)system.img

执行指令:avbtool info_image –image system.img > system.img.info,然后用文本编辑器打开system.img.info文件:

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
26
27
28
29
30
31
32
33
34
35
36
Footer version:           1.0
Image size: 4831838208 bytes
Original image size: 4755517440 bytes
VBMeta offset: 4830863360
VBMeta size: 1856 bytes
--
Minimum libavb version: 1.0 (Sparse)
Header Block: 256 bytes
Authentication Block: 320 bytes
Auxiliary Block: 1280 bytes
Algorithm: SHA256_RSA2048
Rollback Index: 0
Flags: 0
Release String: 'avbtool 1.1.0'
Descriptors:
Hashtree descriptor:
Version of dm-verity: 1
Image Size: 4755517440 bytes
Tree Offset: 4755517440
Tree Size: 37449728 bytes
Data Block Size: 4096 bytes
Hash Block Size: 4096 bytes
FEC num roots: 2
FEC offset: 4792967168
FEC size: 37896192 bytes
Hash Algorithm: sha1
Partition Name: system
Salt: 2af56bd6a339d14619816f1a432ac20a269d4d37
Root Digest: a550134cdb421e710581705f835102e936a9c6a4
Flags: 0
Kernel Cmdline descriptor:
Flags: 1
Kernel Cmdline: 'dm="1 vroot none ro 1,0 9288120 verity 1 PARTUUID=$(ANDROID_SYSTEM_PARTUUID) PARTUUID=$(ANDROID_SYSTEM_PARTUUID) 4096 4096 1161015 1161015 sha1 a550134cdb421e710581705f835102e936a9c6a4 2af56bd6a339d14619816f1a432ac20a269d4d37 10 $(ANDROID_VERITY_MODE) ignore_zero_blocks use_fec_from_device PARTUUID=$(ANDROID_SYSTEM_PARTUUID) fec_roots 2 fec_blocks 1170158 fec_start 1170158" root=/dev/dm-0'
Kernel Cmdline descriptor:
Flags: 2
Kernel Cmdline: 'root=PARTUUID=$(ANDROID_SYSTEM_PARTUUID)'

(4)vendor.img

执行指令:avbtool info_image –image vendor.img > vendor.img.info,然后用文本编辑器打开vendor.img.info文件:

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
26
27
28
29
30
Footer version:           1.0
Image size: 1073741824 bytes
Original image size: 1056714752 bytes
VBMeta offset: 1073463296
VBMeta size: 512 bytes
--
Minimum libavb version: 1.0 (Sparse)
Header Block: 256 bytes
Authentication Block: 0 bytes
Auxiliary Block: 256 bytes
Algorithm: NONE
Rollback Index: 0
Flags: 0
Release String: 'avbtool 1.1.0'
Descriptors:
Hashtree descriptor:
Version of dm-verity: 1
Image Size: 1056714752 bytes
Tree Offset: 1056714752
Tree Size: 8327168 bytes
Data Block Size: 4096 bytes
Hash Block Size: 4096 bytes
FEC num roots: 2
FEC offset: 1065041920
FEC size: 8421376 bytes
Hash Algorithm: sha1
Partition Name: vendor
Salt: a7b29e339d9583845e4da7be047052a6b748ac8a
Root Digest: a6e12dfad11420ecd46892410bc3d85a84f46fcf
Flags: 0

(5)product.img

执行指令:avbtool info_image –image product.img > product.img.info,然后用文本编辑器打开product.img.info文件:

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
26
27
28
29
30
Footer version:           1.0
Image size: 1610612736 bytes
Original image size: 1585115136 bytes
VBMeta offset: 1610235904
VBMeta size: 512 bytes
--
Minimum libavb version: 1.0 (Sparse)
Header Block: 256 bytes
Authentication Block: 0 bytes
Auxiliary Block: 256 bytes
Algorithm: NONE
Rollback Index: 0
Flags: 0
Release String: 'avbtool 1.1.0'
Descriptors:
Hashtree descriptor:
Version of dm-verity: 1
Image Size: 1585115136 bytes
Tree Offset: 1585115136
Tree Size: 12488704 bytes
Data Block Size: 4096 bytes
Hash Block Size: 4096 bytes
FEC num roots: 2
FEC offset: 1597603840
FEC size: 12632064 bytes
Hash Algorithm: sha1
Partition Name: product
Salt: 1e59ddfb5e23b479aa9cb8bb00345ba8b426fb9c
Root Digest: 1a621c82d44e2ebf4d1cc50d009bc17ae96b1279
Flags: 0

(6)vbmeta.img

执行指令:avbtool info_image –image vbmeta.img > vbmeta.img.info,然后用文本编辑器打开vbmeta.img.info文件:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
Minimum libavb version:   1.0
Header Block: 256 bytes
Authentication Block: 576 bytes
Auxiliary Block: 2560 bytes
Algorithm: SHA256_RSA4096
Rollback Index: 0
Flags: 0
Release String: 'avbtool 1.1.0'
Descriptors:
Chain Partition descriptor:
Partition Name: system
Rollback Index Location: 2
Public key (sha1): cdbb77177f731920bbe0a0f94f84d9038ae0617d
Hash descriptor:
Image Size: 22110208 bytes
Hash Algorithm: sha256
Partition Name: boot
Salt: 7b4dfcca246616c387ebf9c1f27607b714e1884fdbbf3d8f635401f18ce90072
Digest: 3a076b7ec8052cc6d4b8e75a41e0bcca542f3ab52ff23ea718693ddcebc18a5a
Flags: 0
Hashtree descriptor:
Version of dm-verity: 1
Image Size: 1056714752 bytes
Tree Offset: 1056714752
Tree Size: 8327168 bytes
Data Block Size: 4096 bytes
Hash Block Size: 4096 bytes
FEC num roots: 2
FEC offset: 1065041920
FEC size: 8421376 bytes
Hash Algorithm: sha1
Partition Name: vendor
Salt: a7b29e339d9583845e4da7be047052a6b748ac8a
Root Digest: a6e12dfad11420ecd46892410bc3d85a84f46fcf
Flags: 0
Hashtree descriptor:
Version of dm-verity: 1
Image Size: 1585115136 bytes
Tree Offset: 1585115136
Tree Size: 12488704 bytes
Data Block Size: 4096 bytes
Hash Block Size: 4096 bytes
FEC num roots: 2
FEC offset: 1597603840
FEC size: 12632064 bytes
Hash Algorithm: sha1
Partition Name: product
Salt: 1e59ddfb5e23b479aa9cb8bb00345ba8b426fb9c
Root Digest: 1a621c82d44e2ebf4d1cc50d009bc17ae96b1279
Flags: 0
Hash descriptor:
Image Size: 884876 bytes
Hash Algorithm: sha256
Partition Name: dtbo
Salt: edd273c37eff93d2fae049a507c54ff291878a7351aaa4d4faa9347c22b300bc
Digest: 393d3a964874db65e566798dc5b369d66beec4391e7192912b9cbcdfbfd2423e
Flags: 0

2.3 其它功能

(1)使用resize_image命令更改带有完整页脚的映像的大小:

1
2
3
$ avbtool resize_image          \
--image IMAGE \
--partition_size SIZE

(2)可以删除映像上的完整性页脚。哈希树可以选择保留在适当的位置:

1
$ avbtool erase_footer --image IMAGE [--keep_hashtree]

(3)可以使用命令将映像中的哈希树和FEC数据清零:

1
$ avbtool zero_hashtree --image IMAGE

(4)可使用–calc_max_image_size选项计算适合给定大小分区的映像的最大大小:

1
2
3
4
5
6
$ avbtool add_hash_footer --partition_size $((10*1024*1024))  \
--calc_max_image_size
10416128
$ avbtool add_hashtree_footer --partition_size $((10*1024*1024)) \
--calc_max_image_size
10330112

(5)可使用–print_required_libavb_version选项获取放入vbmeta结构中的所需libavb版本:

1
2
3
4
5
6
$ avbtool make_vbmeta_image \
--algorithm SHA256_RSA2048 --key external/avb/test/data/testkey_rsa4096.pem \
--include_descriptors_from_image out/target/product/mh4/boot.img \
--include_descriptors_from_image out/target/product/mh4/system.img \
--print_required_libavb_version
1.0

(6)–no_hashtree可以与avbtool add_hashtree_footer命令一起使用。如果给出了–no_hashtree,则省略哈希树blob,仅将其描述符添加到vbmeta结构中。描述符表示哈希树的大小为0,这表明应用程序需要重新计算哈希树。

(7)append_vbmeta_image命令可用于将整个vbmeta blob附加到另一个映像的末尾。这在不使用任何vbmeta分区的情况下非常有用,例如:

1
2
3
4
5
6
$ cp boot.img boot-with-vbmeta-appended.img
$ avbtool append_vbmeta_image \
--image boot-with-vbmeta-appended.img \
--partition_size SIZE_OF_BOOT_PARTITION \
--vbmeta_image vbmeta.img
$ fastboot flash boot boot-with-vbmeta-appended.img

(8)verify_image命令可用于同时验证多个映像文件的内容。在映像上调用时,将执行以下检查:

如果映像具有VBMeta结构,则根据嵌入式public key检查签名。如果映像看起来不像vbmeta.img,那么将查找页脚并使用它。如果传递了–key选项,则应使用.pem文件,并检查所述VBMeta结构中的嵌入式public key是否与给定密钥匹配。采用下列方式检查VBMeta结构中的所有描述符:

a.对于散列描述符,将加载与分区名称相对应的映像文件,并对照描述符中的摘要检查其摘要。

b. 对于哈希树描述符,将加载与分区名称相对应的映像文件,并计算哈希树,并将其根摘要与描述符中的摘要进行比较。

c. 对于链接的分区描述符,将其内容与需要通过–expected_chain_partition选项传递的内容进行比较。该选项的格式类似于–chain_partition选项的格式。如果链分区描述符没有–expected_chain_partition描述符,则检查失败。

下面是一个示例,其中boot.img和system.img的摘要存储在vbmeta.img中,该摘要已用my_key.pem签名。它还检查分区foobar的链分区是否使用回滚索引8,以及AVB格式的公钥是否与文件foobar_vendor_key.avbpubkey的公钥匹配:

1
2
3
4
5
6
$ avbtool verify_image \
--image out/target/product/mh4/vbmeta.img \
--key external/avb/test/data/testkey_rsa4096.pem \
--expect_chained_partition system:2:system.avbpubkey
Verifying image ../1607/vbmeta.img using key at test/data/testkey_rsa4096.pem
system: Successfully verified sha1 hashtree of out/target/product/mh4/system.img for image of 4831838208 bytes

(9)compute_vbmeta_digest命令可用于同时计算多个映像文件的vbmeta摘要。结果将以十六进制字符串的形式打印在STDOUT或提供的路径上(使用–output选项):

1
2
3
4
$ avbtool calculate_vbmeta_digest \
--hash_algorithm sha256 \
--image /path/to/vbmeta.img
a20fdd01a6638c55065fe08497186acde350d6797d59a55d70ffbcf41e95c2f5

calculate_vbmeta_digest命令将加载vbmeta.img文件。如果此映像具有一个或多个链分区描述符,则使用与verify_image命令相同的逻辑来加载这些文件的文件(例如,假定与给定映像具有相同的目录和文件扩展名)。加载完所有vbmeta结构后,将计算摘要(使用–hash_algorithm选项提供的哈希算法)并打印出来。