AVB相关image(vbmeta.img/system.img)的生成

AVB相关image(vbmeta.img/system.img)的生成

vbmeta.img/vbmeta_system.img(chain partition)的生成

调用build-vbmetaimage-target生成vbmeta.img

3762 $(INSTALLED_VBMETAIMAGE_TARGET): \
3763         $(AVBTOOL) \
3764         $(INSTALLED_BOOTIMAGE_TARGET) \
3765         $(INSTALLED_VENDOR_BOOTIMAGE_TARGET) \
3766         $(INSTALLED_SYSTEMIMAGE_TARGET) \
3767         $(INSTALLED_VENDORIMAGE_TARGET) \
3768         $(INSTALLED_PRODUCTIMAGE_TARGET) \
3769         $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \
3770         $(INSTALLED_ODMIMAGE_TARGET) \
3771         $(INSTALLED_DTBOIMAGE_TARGET) \
3772         $(INSTALLED_CUSTOMIMAGES_TARGET) \
3773         $(INSTALLED_RECOVERYIMAGE_TARGET) \
3774         $(INSTALLED_VBMETA_SYSTEMIMAGE_TARGET) \
3775         $(INSTALLED_VBMETA_VENDORIMAGE_TARGET) \
3776         $(BOARD_AVB_VBMETA_SYSTEM_KEY_PATH) \
3777         $(BOARD_AVB_VBMETA_VENDOR_KEY_PATH) \
3778         $(BOARD_AVB_KEY_PATH)
3779     $(build-vbmetaimage-target)

 

3745 define build-vbmetaimage-target
3746   $(call pretty,"Target vbmeta image: $(INSTALLED_VBMETAIMAGE_TARGET)")
3747   $(hide) mkdir -p $(AVB_CHAIN_KEY_DIR)
3748   $(call extract-avb-chain-public-keys, $(AVB_CHAIN_KEY_DIR))
3749   $(hide) $(AVBTOOL) make_vbmeta_image \
3750     $(INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS) \
3751     $(PRIVATE_AVB_VBMETA_SIGNING_ARGS) \
3752     $(BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS) \
3753     --output $@
3754   $(hide) rm -rf $(AVB_CHAIN_KEY_DIR)
3755 endef

 

3666 # $(1): the directory to extract public keys to
3667 define extract-avb-chain-public-keys
3668   $(if $(BOARD_AVB_BOOT_KEY_PATH),\
3669     $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_BOOT_KEY_PATH) \
3670       --output $(1)/boot.avbpubkey)
3671   $(if $(BOARD_AVB_VENDOR_BOOT_KEY_PATH),\
3672     $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VENDOR_BOOT_KEY_PATH) \
3673       --output $(1)/vendor_boot.avbpubkey)
3674   $(if $(BOARD_AVB_SYSTEM_KEY_PATH),\
3675     $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_SYSTEM_KEY_PATH) \
3676       --output $(1)/system.avbpubkey)
3677   $(if $(BOARD_AVB_VENDOR_KEY_PATH),\
3678     $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VENDOR_KEY_PATH) \
3679       --output $(1)/vendor.avbpubkey)
3680   $(if $(BOARD_AVB_PRODUCT_KEY_PATH),\
3681     $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_PRODUCT_KEY_PATH) \
3682       --output $(1)/product.avbpubkey)
3683   $(if $(BOARD_AVB_SYSTEM_EXT_KEY_PATH),\
3684     $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_SYSTEM_EXT_KEY_PATH) \
3685       --output $(1)/system_ext.avbpubkey)
3686   $(if $(BOARD_AVB_ODM_KEY_PATH),\
3687     $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_ODM_KEY_PATH) \
3688       --output $(1)/odm.avbpubkey)
3689   $(if $(BOARD_AVB_DTBO_KEY_PATH),\
3690     $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_DTBO_KEY_PATH) \
3691       --output $(1)/dtbo.avbpubkey)
3692   $(if $(BOARD_AVB_RECOVERY_KEY_PATH),\
3693     $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_RECOVERY_KEY_PATH) \
3694       --output $(1)/recovery.avbpubkey)
3695   $(if $(BOARD_AVB_VBMETA_SYSTEM_KEY_PATH),\
3696     $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VBMETA_SYSTEM_KEY_PATH) \
3697         --output $(1)/vbmeta_system.avbpubkey)
3698   $(if $(BOARD_AVB_VBMETA_VENDOR_KEY_PATH),\
3699     $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VBMETA_VENDOR_KEY_PATH) \
3700         --output $(1)/vbmeta_vendor.avbpubkey)
3701   $(if $(BOARD_CUSTOMIMAGES_PARTITION_LIST),\
3702     $(hide) $(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
3703         $(AVBTOOL) extract_public_key --key $(BOARD_AVB_$(call to-upper,$(partition))_KEY_PATH) \
3704             --output $(1)/$(partition).avbpubkey;))
3705 endef

调用build-chained-vbmeta-image生成vbmeta_system.img

3725 ifdef BUILDING_SYSTEM_IMAGE
3726 ifdef BOARD_AVB_VBMETA_SYSTEM
3727 INSTALLED_VBMETA_SYSTEMIMAGE_TARGET := $(PRODUCT_OUT)/vbmeta_system.img
3728 $(INSTALLED_VBMETA_SYSTEMIMAGE_TARGET): \
3729         $(AVBTOOL) \
3730         $(call images-for-partitions,$(BOARD_AVB_VBMETA_SYSTEM)) \
3731         $(BOARD_AVB_VBMETA_SYSTEM_KEY_PATH)
3732     $(call build-chained-vbmeta-image,vbmeta_system)
3733 endif
3734 endif # BUILDING_SYSTEM_IMAGE

 

在enable了AVB的情况下system.img生成flow(system.img里将包含AVB hashtree)

(调用BuildImage之前的flow是怎样的参考blog:android related image generation - aspirs - 博客园 (cnblogs.com)

build/make/tools/releasetools/build_image.py

def BuildImage(in_dir, prop_dict, out_file, target_out=None):
410   verity_image_builder = verity_utils.CreateVerityImageBuilder(prop_dict)
412   if (prop_dict.get("use_dynamic_partition_size") == "true" and
413       "partition_size" not in prop_dict):
414     # If partition_size is not defined, use output of `du' + reserved_size.
415     size = GetDiskUsage(in_dir)
419     reserved_size = int(prop_dict.get("partition_reserved_size", BYTES_IN_MB * 16))
423     size += reserved_size
434       BuildImageMkfs(in_dir, prop_dict, out_file, target_out, fs_config)
498   if verity_image_builder:
499     verity_image_builder.Build(out_file)

调用BuildImage来生成system.img,主要有4点:

1.调用CreateVerityImageBuilder生成verity_image_builder

2.对于system.img,因为在Android 10上开始使用super partition,所以use_dynamic_partition_size是true,同时在system_image_info.txt里没有指定system partition size,所以上述条件是成立的。如果system_image_info.txt里没有指定partition size,那生成的system.img(ext4)文件系统多大怎么设定的,这个是根据in_dir( $PRODUCT_OUT/system)目录的size加上system_image_info.txt里的system_reserved_size(在ImagePropFromGlobalDict被转成partition_reserved_size)来确定的

3.调用BuildImageMkfs生成指定文件系统格式(ext4)的system.img

4.调用verity_image_builder.Build(out_file) 构建system.img的hashtree、vbmeta、avb footer并依次将它们append到system.img

CreateVerityImageBuilder生成verity_image_builder

system_image_info.txt里没有指定verity和verity_block_device property,所以不是verified boot 1.0,而是verified boot 2.0

system_image_info.txt里指定了avb_hashtree_enable等于true,没有指定avb_hash_enable

143 def CreateVerityImageBuilder(prop_dict):
159   # Verified Boot 1.0
160   verity_supported = prop_dict.get("verity") == "true"
161   is_verity_partition = "verity_block_device" in prop_dict
162   if verity_supported and is_verity_partition:

176   # Verified Boot 2.0
177   if (prop_dict.get("avb_hash_enable") == "true" or
178       prop_dict.get("avb_hashtree_enable") == "true"):
195     # Image uses hashtree footer.
196     return VerifiedBootVersion2VerityImageBuilder(
197         prop_dict["partition_name"],
198         partition_size,
199         VerifiedBootVersion2VerityImageBuilder.AVB_HASHTREE_FOOTER,
200         prop_dict["avb_avbtool"],
201         key_path,
202         algorithm,
203         prop_dict.get("avb_salt"),
204         prop_dict["avb_add_hashtree_footer_args"])

verity_image_builder.Build(out_file) 构建system.img的hashtree、vbmeta、avb footer并依次将它们append到system.img

/build/make/tools/releasetools/verity_utils.py

调用avbtool add_hashtree_footer

这里self.partition_name为"system",self.partition_size前面也设置过了,self.key_path、self.algorithm均为空(system_image_info.txt里没有指定)

483   def Build(self, out_file):
484     """Adds dm-verity hashtree and AVB metadata to an image.
485 
486     Args:
487       out_file: Path to image to modify.
488     """
489     add_footer = ("add_hash_footer" if self.footer_type == self.AVB_HASH_FOOTER
490                   else "add_hashtree_footer")
491     cmd = [self.avbtool, add_footer,
492            "--partition_size", str(self.partition_size),
493            "--partition_name", self.partition_name,
494            "--image", out_file]
495     if self.key_path and self.algorithm:
496       cmd.extend(["--key", self.key_path, "--algorithm", self.algorithm])
497     if self.salt:
498       cmd.extend(["--salt", self.salt])
499     cmd.extend(shlex.split(self.signing_args))
500 
501     proc = common.Run(cmd)

上面avbtool add_hashtree_footer会调用到如下方法:

def add_hashtree_footer(self, args): member in AvbTool

这个方法会调用到:

def add_hashtree_footer(self, image_filename, partition_size, partition_name, member in Avb

external/avb/avbtool.py

3352   def add_hashtree_footer(self, image_filename, partition_size, partition_name,
3353                           generate_fec, fec_num_roots, hash_algorithm,
3354                           block_size, salt, chain_partitions, algorithm_name,
3355                           key_path,
3356                           public_key_metadata_path, rollback_index, flags,
3357                           props, props_from_file, kernel_cmdlines,
3358                           setup_rootfs_from_kernel,
3359                           setup_as_rootfs_from_kernel,
3360                           include_descriptors_from_image,
3361                           calc_max_image_size, signing_helper,
3362                           signing_helper_with_files,
3363                           release_string, append_to_release_string,
3364                           output_vbmeta_image, do_not_append_vbmeta_image,
3365                           print_required_libavb_version,
3366                           use_persistent_root_digest, do_not_use_ab,
3367                           no_hashtree):

add_hashtree_footer方法做了如下事情:

1.根据image size以及block size计算hash_level_offsets、tree_size,前者表示hash tree是有几层(level),tree size是hash tree的size(各层hash值block的size之和)

2.对image data以block size为单位计算hash值,并将hash值保存到hash tree中,即先以block size为单位计算image data的hash值,这些hash值构成hash tree的最低一层(第0层),之后根据这一层的hash值数据进行第1层hash值的计算,类似这样一层一层计算,直到某一层的hash值所占用的空间等于(有padding,会对齐到block size,所以只会是等于)block size时hash tree构建完成,此时对这等于block size的hash数据进行hash值计算,计算出的结果做为root digest返回,同时也会返回这里构建的hash tree

3.将2中计算出来的hash tree append到image

4.创建hashtree descriptor,然后设置它,如下,ht_desc.root_digest即是2中计算出来的root digest。之后将根据此hashtree descriptor创建vbmeta_blob,之后将创建的vbmeta_blob append到image

3532       ht_desc = AvbHashtreeDescriptor()
3533       ht_desc.dm_verity_version = 1
3534       ht_desc.image_size = image.image_size
3535       ht_desc.tree_offset = tree_offset
3536       ht_desc.tree_size = tree_size
3537       ht_desc.data_block_size = block_size
3538       ht_desc.hash_block_size = block_size
3539       ht_desc.hash_algorithm = hash_algorithm
3540       ht_desc.partition_name = partition_name
3541       ht_desc.salt = salt
3544       if not use_persistent_root_digest:
3545         ht_desc.root_digest = root_digest

 

3577       vbmeta_blob = self._generate_vbmeta_blob(
3578           algorithm_name, key_path, public_key_metadata_path, [ht_desc],
3579           chain_partitions, rollback_index, flags, props, props_from_file,
3580           kernel_cmdlines, setup_rootfs_from_kernel, ht_desc_to_setup,
3581           include_descriptors_from_image, signing_helper,
3582           signing_helper_with_files, release_string,
3583           append_to_release_string, required_libavb_version_minor)

5.创建avbfooter,并设置它的vbmeta_offset以及vbmeta_size(即是上面vbmeta_blob的size)成员,然后将avb footer写到image的最后一个block,注意avb footer位于这个block的最后,这个block前面没有占用的部分将用0填充:

3598         if partition_size > 0:
3599           image.append_dont_care(partition_size - image.image_size -
3600                                  1*image.block_size) #填充最后没有使用的空间(除了最后一个block,将最后一个block留出来给avb footer)
3601 
3602         # Generate the Footer that tells where the VBMeta footer
3603         # is. Also put enough padding in the front of the footer since
3604         # we'll write out an entire block.
3605         footer = AvbFooter()
3606         footer.original_image_size = original_image_size
3607         footer.vbmeta_offset = vbmeta_offset
3608         footer.vbmeta_size = len(vbmeta_blob)
3609         footer_blob = footer.encode()
3610         footer_blob_with_padding = ('\0'*(image.block_size - AvbFooter.SIZE) +
3611                                     footer_blob)
3612         image.append_raw(footer_blob_with_padding)

注:

上面2中对一个block(4K)计算hash值,如果是采用的hash256算法,则计算出来的hash值有256bit,即32 byte,假设system.img size是1G,则hash tree layer0数据size为2048 block(4K)( (30 - 12) + 5 - 12 = 11),同样的方法后面计算layer 0、1等的hash值,最上面的layer只有一个block,最后这个hash tree一共有3个layer(layer0/1/2),这部分可以参考如下blog:

dm-verity原理剖析_内核工匠的博客-CSDN博客

 

posted @ 2022-05-16 00:06  aspirs  阅读(2182)  评论(0编辑  收藏  举报