The different Android versions have their own partition layout, so the AVB verification process should be dynamic.
In the new verification process, we need to use the header version fetched from boot partition, so we need to check the boot partition firstly to avoid the downgrade attacking. If we didn't check boot firstly, just use it, the attacker can bypass the AVB verification by flashing a boot image with header version 3 or earlier. Signed-off-by: Valentin Liu <[email protected]> --- boot/bootmeth_android.c | 43 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/boot/bootmeth_android.c b/boot/bootmeth_android.c index 904640d360b..55cd99f3043 100644 --- a/boot/bootmeth_android.c +++ b/boot/bootmeth_android.c @@ -479,11 +479,12 @@ static int avb_append_commandline(struct bootflow *bflow, char *cmdline) return 0; } -static int run_avb_verification(struct bootflow *bflow) +static int run_avb_verification(struct bootflow *bflow, const bool boot_only) { struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); struct android_priv *priv = bflow->bootmeth_priv; - const char * const requested_partitions[] = {"boot", "vendor_boot", NULL}; + const char *requested_partitions[4]; + int requested_partitions_num = 0; struct AvbOps *avb_ops; AvbSlotVerifyResult result; AvbSlotVerifyData *out_data = NULL; @@ -493,6 +494,28 @@ static int run_avb_verification(struct bootflow *bflow) bool unlocked = false; int ret; + /* + * Always verify boot first. + * + * When boot_only is true, only verify the boot partition. + * Otherwise, select additional partitions according to the + * Android boot image header version. + */ + requested_partitions[requested_partitions_num++] = "boot"; + + if (!boot_only) { + if (priv->header_version >= 3) + requested_partitions[requested_partitions_num++] = + "vendor_boot"; + + if (priv->header_version >= 4 && + priv->init_boot_img_size > 0) + requested_partitions[requested_partitions_num++] = + "init_boot"; + } + + requested_partitions[requested_partitions_num] = NULL; + avb_ops = avb_ops_alloc(desc->devnum); if (!avb_ops) return log_msg_ret("avb ops", -ENOMEM); @@ -562,9 +585,10 @@ static int run_avb_verification(struct bootflow *bflow) return ret; } #else -static int run_avb_verification(struct bootflow *bflow) +static int run_avb_verification(struct bootflow *bflow, const bool boot_only) { int ret; + (void)boot_only; /* When AVB is unsupported, pass ORANGE state */ ret = bootflow_cmdline_set_arg(bflow, @@ -617,9 +641,13 @@ static int boot_android_normal(struct bootflow *bflow) ulong iloadaddr = env_get_hex("init_boot_comp_addr_r", 0); ulong vloadaddr = env_get_hex("vendor_boot_comp_addr_r", 0); - ret = run_avb_verification(bflow); + /* + * Checking the boot partition firstly because the standard AVB + * verification is rely on the header version from boot partition. + */ + ret = run_avb_verification(bflow, true); if (ret < 0) - return log_msg_ret("avb", ret); + return log_msg_ret("avb boot", ret); /* Read slot once more to decrement counter from BCB */ ret = android_read_slot_from_bcb(bflow, true); @@ -631,6 +659,11 @@ static int boot_android_normal(struct bootflow *bflow) if (ret < 0) return log_msg_ret("read boot", ret); + /* Standard AVB verification */ + ret = run_avb_verification(bflow, false); + if (ret < 0) + return log_msg_ret("avb", ret); + if (priv->header_version >= 4 && priv->init_boot_img_size > 0) { ret = read_slotted_partition(desc, "init_boot", priv->slot, priv->init_boot_img_size, -- 2.53.0
