AVB相关的一些bug fix

vendor分区未加入avb校验中:

之前负责AVB的同事离职后,接手这个模块。走读代码时,发现vendor分区没有配置avb校验。

可能是之前整体调整fstab时,把这个配置给漏掉了。

拿手机试了下,确实如此:

# cat /sys/block/dm-*/dm/name
system_a
system_ext_a
product_a
vendor_a
system-verity
system_ext-verity
product-verity
userdata

修改点:

-vendor                                                   /vendor               ext4    ro,barrier=1,discard                                wait,slotselect,logical,first_stage_mount
+vendor                                                   /vendor               ext4    ro,barrier=1,discard                                wait,slotselect,avb,logical,first_stage_mount

修改之后:

# cat /sys/block/dm-*/dm/name
system_a
system_ext_a
product_a
vendor_a
system-verity
system_ext-verity
product-verity
vendor-verity
userdata

CTSKeystoreTestcases测试fail:

 

 从log看:

28104 10-31 09:58:06.506 3406 3423 I TestRunner: started: testEcAttestation_DeviceLocked(android.keystore.cts.KeyAttestationTest)
28604 10-31 09:58:07.482 3406 3423 E TestRunner: failed: testEcAttestation_DeviceLocked(android.keystore.cts.KeyAttestationTest)
28605 10-31 09:58:07.482 3406 3423 E TestRunner: ----- begin exception -----
28607 10-31 09:58:07.484 3406 3423 E TestRunner: junit.framework.AssertionFailedError: expected:<0> but was:<1> //这里不符合预期
28608 10-31 09:58:07.484 3406 3423 E TestRunner: at junit.framework.Assert.fail(Assert.java:50)
28609 10-31 09:58:07.484 3406 3423 E TestRunner: at junit.framework.Assert.failNotEquals(Assert.java:287)
28610 10-31 09:58:07.484 3406 3423 E TestRunner: at junit.framework.Assert.assertEquals(Assert.java:67)
28611 10-31 09:58:07.484 3406 3423 E TestRunner: at junit.framework.Assert.assertEquals(Assert.java:199)
28612 10-31 09:58:07.484 3406 3423 E TestRunner: at junit.framework.Assert.assertEquals(Assert.java:205)
28613 10-31 09:58:07.484 3406 3423 E TestRunner: at android.keystore.cts.KeyAttestationTest.checkRootOfTrust(KeyAttestationTest.java:1142)
28614 10-31 09:58:07.484 3406 3423 E TestRunner: at android.keystore.cts.KeyAttestationTest.checkDeviceLocked(KeyAttestationTest.java:1121)
28615 10-31 09:58:07.484 3406 3423 E TestRunner: at android.keystore.cts.KeyAttestationTest.testEcAttestation_DeviceLocked(KeyAttestationTest.java:301)

对应CTS测试代码:

private void checkRootOfTrust(Attestation attestation, boolean requireLocked) {
    RootOfTrust rootOfTrust = attestation.getTeeEnforced().getRootOfTrust();
    assertNotNull(rootOfTrust);
    assertNotNull(rootOfTrust.getVerifiedBootKey());
    assertTrue("Verified boot key is only " + rootOfTrust.getVerifiedBootKey().length +
               " bytes long", rootOfTrust.getVerifiedBootKey().length >= 32);
    if (requireLocked) {
        assertTrue(rootOfTrust.isDeviceLocked());
        checkEntropy(rootOfTrust.getVerifiedBootKey());
        assertEquals(KM_VERIFIED_BOOT_VERIFIED, rootOfTrust.getVerifiedBootState());//这里检查失败
    }
}

结合log中cmdline的输出:

00037 01-14 01:48:31.489 0 0 I : Kernel command line: security=selinux …… androidboot.verifiedbootstate=yellow ……

初步怀疑是AVB校验这边校验出异常了。

 

 

追查下来,发现是前面有笔提交,给IsUserKey赋值为true了。修改后复测pass。

查看系统属性,也对上啦:

 $ getprop |grep bootstate
[ro.boot.verifiedbootstate]: [green]

GSI版本启动失败:

异常日志:

30275 [ 10.307797] device-mapper: verity-fec: 253:0: FEC 0: failed to correct: -74
30276 [ 10.323250] device-mapper: verity: 253:0: data block 0 is corrupted
30304 [ 10.899018] reboot: Restarting system with command 'dm-verity device corrupted'

查看253:0是哪个分区: 

# dmctl list devices
Available Device Mapper Devices:
system_ext_a : 253:1
userdata : 253:8
system_a : 253:0
vendor-verity : 253:7
vendor_a : 253:3
system_ext-verity : 253:5
product-verity : 253:6
system-verity : 253:4
product_a : 253:2

最终追查下来,是使用的fastboot版本太低导致的问题。工作中真的是什么奇奇怪怪的问题都能碰到啊。 

hash partition优化提升开机时间

修改原理如下:

首先,这处改动发生在函数load_and_verify_hash_partition中。

其中io_ret = ops->get_size_of_partition(ops, part_name, &image_size);是从partition中读到整个分区的长度。

我们注释掉了这条语句,转而通过image_size = hash_desc.image_size;来确定将要读取的数据大小。

这个是因为,对于hash partition(如boot,dtbo和vendor_boot),其image的大体框架如下:

 

 

以dtbo.img为例,该image的真实数据是dtbo + padding + vbmeta + padding + footer。

其中需要校验的仅仅是第一部分的真实dtbo数据,这块数据的长度在vbmeta.img的hash descriptor中保留了。

而这块数据在整个dtbo.img中占比较小,如果在读分区时只读这一部分,那么读取时间会得以较大改善。

如下,

original image size of dtbo = 0x11cf9b,从footer中读出的。

vbmeta的offset为0x11d000,也是footer中读出。

我们来看看0x11d000的数据,这里是vbmeta数据的位置,前面0x11cf9b所占整个dtbo.img的比例为 0x11cf9b ÷ 0x18000000 = 0.046

以本地的一份dtbo.img来看:

这个是编译过程中的打印,如下:

09157 add_hash_footer partition =  dtbo
09158 add_hash_footer image_size =  1193543

这个是dtbo.img的footer中original_image_size,为0x123647 = 1193543,和打印值能对上。

上面的打印值是加在add_hash_footer中生成hash descriptor的地方,如下:

3286       h_desc = AvbHashDescriptor()
3287       h_desc.image_size = image.image_size
3288       h_desc.hash_algorithm = hash_algorithm
3289       h_desc.partition_name = partition_name
3290       print('add_hash_footer partition = ', partition_name)
3291       print('add_hash_footer image_size = ', image.image_size)
3292       h_desc.salt = salt
3293       h_desc.flags = 0
3294       if do_not_use_ab:
3295         h_desc.flags |= 1  # AVB_HASH_DESCRIPTOR_FLAGS_DO_NOT_USE_AB
3296       if not use_persistent_digest:
3297         h_desc.digest = digest

从这里可以看到,hash descriptor中的hash值,其实算的是original dtbo image数据,而非整个分区长度。

uboot中在load_and_verify_hash_partition时,计算hash也是只算了这一部分,所以locked状态下,没有必要读取整个分区长度数据(耗时,无意义):

    if (Avb_StrnCmp((CONST CHAR8 *)hash_desc.hash_algorithm, "sha256",
                    avb_strlen("sha256")) == 0)
    {
        avb_debugv(part_name, "[avb]: do sha256 hash operation start.\n", NULL);
        avb_sha256_init(&sha256_ctx);
        avb_sha256_update(&sha256_ctx, desc_salt, hash_desc.salt_len);
        avb_sha256_update(&sha256_ctx, image_buf, hash_desc.image_size);
        digest = avb_sha256_final(&sha256_ctx);
        digest_len = AVB_SHA256_DIGEST_SIZE;
        avb_debugv(part_name, "[avb]: do sha256 hash operation done.\n", NULL);
    }

 

posted @ 2023-04-03 09:31  xiululu  阅读(442)  评论(3编辑  收藏  举报