验证启动(Verified Boot)是Android一个重要的安全功能,主要是为了访问启动镜像被篡改,提高系统的抗攻击能力,简单描述做法就是在启动过程中增加一条校验链,即 ROM code 校验 BootLoader,确保 BootLoader 的合法性和完整性,BootLoader 则需要校验 boot image,确保 Kernel 启动所需 image 的合法性和完整性,而 Kernel 则负责校验 System 分区和 vendor 分区。
由于 ROM code 和 BootLoader 通常都是由设备厂商 OEM 提供,而各家实际做法和研发能力不尽相同,为了让设备厂商更方便的引入 Verified boot 功能,Google 在 Android O上推出了一个统一的验证启动框架 Android verified boot 2.0,好处是既保证了基于该框架开发的verified boot 功能能够满足 CDD 要求,也保留了各家 OEM 定制启动校验流程的弹性。
由于 ROM code 校验 BootLoader 的功能通常与 IC的设计相关,所以 AVB 2.0 关注的重点在 BootLoader 之后的校验流程。BootLoader 之后系统启动所涉及的关键镜像通常包括 boot.img,system.img,Android O 的 treble Project 还引入了 dtbo 和 vendor.img。这些 image 挨个校验可以说费时费力,而 AVB 2.0 的做法事实上十分简单,引入一个新的分区:vbmeta.img(verified boot metadata),然后把所有需要校验的内容在编译时就计算好打包到这个分区,那么启动过程中 BootLoader 只需要校验 vbmeta.img,就能确认 vbmeta 内的数据是否可信。再用 vbmeta 中的数据去比对 bootimg,dtbo,system,img,vendor.img 即可。至于 OEM 是还需要放什么其他东西到 vbmeta 中,则可以由 OEM 自由定制,可以说保留了很好的客制化空间。
除了最基本的验证启动之外,AVB 2.0 还提供防止回滚的功能和对AB分区备份的支持,AVB 2.0 的详细文档可以参考:Android Verified Boot 2.0
无论是验证启动还是防止回滚,vbmeta 都是很重要的数据结构,下面对最简单的 vbmeta struct 做一个分析说明。
下面是 vbmeta struct 的结构图示:
vbmetaStruct.png
以上 vbmeta 所包含的数据可以分成两个大的Block:紫色色块部分为 Authentication data block 和 其他为 Auxiliary data block。当 BOARD_AVB_ALGORITHM 定义为 SHA256_RSA2048 时,默认编译出的 vbmeta.img 通常为 4KB。vbmeta.img 组成如下:
------------------------------------------------------------------------------
| Header | Authentication Data | Auxiliary Data |
------------------------------------------------------------------------------
其中 Header 的固定长度为 0x100 个字节,Authentication data 和 Auxiliary data 的长度存储在 Header 中。
下面分别对这三个部分进行分析、
Header 解析
Header 的数据结构为:typedef struct AvbVBMetaImageHeader
用 UE 打开 vbmeta.img,前 0x100 个字节信息如下:
根据 struct AvbVBMetaImageHeader,上图中的 Header 信息解析如下:
字节 | AvbVBMetaImageHeader 成员变量 | 说明 |
---|---|---|
0x0 - 0x3 | magic[AVB_MAGIC_LEN] |
magic字符串,固定为 AVB0 |
0x4 - 0x7 | required_libavb_version_major |
libavb 大版本号 0x1 |
0x8 - 0xb | required_libavb_version_minor |
libavb 小版本号 0x0 |
0xc - 0x13 | authentication_data_block_size |
如果选用 SHA256_RSA2048算法,则 authentication data size 固定为 0x140 |
0x14 - 0x1B | auxiliary_data_block_size |
根据 make_vbmeta_image 不同参数,长度不同,上图为 0x4C0 |
0x1C - 0x1F | algorithm_type |
由AvbAlgorithmType 定义, 0x1 表示AVB_ALGORITHM_TYPE_SHA256_RSA2048
|
0x20 - 0x27 | hash_offset |
hash data 在 authentication data 中的位置,通常为 0x0,hash data的具体说明会在 Authentication data 的解析中加以说明 |
0x28 - 0x2F | hash_size |
hash data 的大小,使用SHA256算法时 Hash data 固定为 0x20 个字节,即 256 bits |
0x30 - 0x37 | signature_offset |
signature data 在 authentication data 中的位置,signature data紧跟在 Hash data 后面,所以 offset 在 hash 算法为 SHA256时,固定为 0x20 |
0x38 - 0x3F | signature_size |
signature data 的大小,在签名算法使用 RSA2048 时,固定为 0x100个字节,即 2048 bits |
0x40 - 0x47 | public_key_offset |
签名算法对应的公钥存储在 Auxiliary data block 中的位置,上图为 0x298 |
0x48 - 0x4F | public_key_size |
签名算法对应的公钥长度,使用RSA2048 作为签名算法时,该长度固定为 0x208, public key 部分会在 Auxiliary data block 的解析中加以说明 |
0x50 - 0x57 | public_key_metadata_offset |
public key metadata 在 auxiliary data block 中的存储位置 |
0x58 - 0x5F | public_key_metadata_size |
public key metadata 的大小,为 0x0 表示没有 public key metadata 数据 |
0x60 - 0x67 | descriptors_offset |
descriptor 在 Auxiliary data block 中的位置,默认固定为 0x0,descriptor 的具体含义会在 Auxiliary data block 的解析中加以说明 |
0x68 - 0x6F | descriptors_size |
descriptor 的长度,取决于 make_vbmeta_image 时的参数 ---include_descriptor_from_image |
0x70 - 0x77 | rollback_index |
供rollback protection 功能使用,由 make_vbmeta_image 时的参数 ---rollback_index 指定,上图中为 0x0,即未对回滚保护做支持 |
0x78 - 0x7F | reserved0[4] |
16字节对齐使用,固定为四个 0x0 |
0x80 - 0xAF | release_string[AVB_RELEASE_STRING_SIZE] |
avbtool 的 release 信息,48个字节,一般为 avbtool 1.0.0 xxxxx |
0xB0 - 0xFF | reserved[80] |
padding数据,保证 Header长度为 x100,内容必须全部填 0x0 |
Authentication data block 解析
Authentication data block 用于校验 vbmeta.img 的合法性和完整性,包含两部分内容:Hash data 和 signature data。
通过分析avbtool 的 Python 脚本,即可了解 hash data 和 signature data 的生成过程。
Hash data 的生成
hash data 是对 vbmeta 的 header 和 auxiliary data block 的 hash 计算,所以是先生成了 auxiliary data block,然后生成的 authentication data block,使用的算法由 header 中的 algorithm_type 指定,本文使用 SHA256,计算出的 hash data 长度为 0x20。截取 avbtool 的脚本代码如下:
# Calculate the hash. ha = hashlib.new(alg.hash_name) ha.update(header_data_blob) ha.update(aux_data_blob) binary_hash.extend(ha.digest())
signature data 的生成
signature data 是对 上文计算出的 hash data 做 padding 之后的签名,使用的算法同样由 header 中的 algorithm_type 指定,本文使用 RSA2048,计算出的 signature data 长度为 0x100。截取 avbtool 的脚本代码如下:
# Calculate the signature. padding_and_hash = str(bytearray(alg.padding)) + binary_hash binary_signature.extend(raw_sign(signing_helper, signing_helper_with_files, algorithm_name, alg.signature_num_bytes, key_path, padding_and_hash))
有一个需要注意的地方是,hash data 和 signature data 的总长加在一起为0x120,但header 中的 authentication data block size 却为 0x140,这是因为 image 对齐需要,0x120 不能被 64 整除,所以用 0x0 填充到长度为 0x140。
Auxiliary data block 解析
Auxiliary data block 的内容则十分丰富,总得来说分为两个大类:AvbDescriptor 和 RSA public key。
AvbDescriptor 的生成
根据 avbtool make_vbmeta_image 命令支持的参数,OEM 可以自由的定制一些需要打包到 vbmeta.img 的数据,这样一段一段的二进制数据都按照AvbDescriptor 的数据结构打包进 auxiliary data block。AvbDescriptor 按照不同的 tag 分为以下几种:
typedef enum {
AVB_DESCRIPTOR_TAG_PROPERTY,
AVB_DESCRIPTOR_TAG_HASHTREE,
AVB_DESCRIPTOR_TAG_HASH,
AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,
AVB_DESCRIPTOR_TAG_CHAIN_PARTITION,
} AvbDescriptorTag;
最常用的参数 ---include_descriptor_from_image
可以将 boot.img,dtbo,recovery.img,system.img,vendor.img 的 descriptor 打包到 Auxiliary data block 中。这些 descriptors 在 BootLoader 确认 vbmeta.img 的合法性和完整性后,可以直接被用来校验 boot.img,dtbo,recovery.img,system.img,vendor.img。
RSA public key的生成
除了这些 descriptor 之外,auxiliary data block 中还有一个重要的信息,就是 RSA public key。这个 public key 将被用来校验 authentication data block 中的 signature data。
在 avbtool make_vbmeta_image 时,必须用--key
参数来指定生成 signature data 的 RSA private key,AOSP external/avb/test/data 目录下有各种供测试使用 RSA private key,格式为 PEM。avbtool 会根据 RSA private key 提取 public key 并加上 RSA key 的 header 打包进 auxiliary data block。
可以通过avbtool extract_public_key --key [priv_key_path] --output [outpubk_path]
来查看生成的 public key 信息。
其中 RSA key header 格式如下:
typedef struct AvbRSAPublicKeyHeader {
uint32_t key_num_bits;
uint32_t n0inv;
} AVB_ATTR_PACKED AvbRSAPublicKeyHeader;
前文中所描述 header 中的 public key size 为 0x208,即 0x8 个字节的 AvbRSAPublicKeyHeader 长度,加上 0x200个字节即 2048位 的 public key 长度。
以上就是 vbmeta 除 padding 填充 0x0 之外,主要的数据信息。
网友评论