From cfbeb4b0b91bc9f807f6cefcc5bb0a52f2ba3e64 Mon Sep 17 00:00:00 2001 From: Igor Opaniuk Date: Tue, 13 Feb 2024 08:36:38 +0100 Subject: [PATCH 1/8] MAINTAINERS: add custodian tree info for AVB/AB Add information about a custodian tree [1] for AVB/AB, which is maintained by Mattijs Korpershoek. [1] https://source.denx.de/u-boot/custodians/u-boot-dfu Signed-off-by: Igor Opaniuk Reviewed-by: Mattijs Korpershoek Reviewed-by: Marek Vasut Link: https://lore.kernel.org/r/20240213073638.1125429-1-igor.opaniuk@foundries.io Signed-off-by: Mattijs Korpershoek --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 46ba17647f3..32f3ee30710 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -62,6 +62,7 @@ M: Igor Opaniuk M: Mattijs Korpershoek R: Sam Protsenko S: Maintained +T: git https://source.denx.de/u-boot/custodians/u-boot-dfu.git F: boot/android_ab.c F: cmd/ab_select.c F: doc/android/ab.rst @@ -72,6 +73,7 @@ ANDROID AVB M: Igor Opaniuk M: Mattijs Korpershoek S: Maintained +T: git https://source.denx.de/u-boot/custodians/u-boot-dfu.git F: cmd/avb.c F: common/avb_verify.c F: doc/android/avb2.rst From c2f72d00ab88402038d3c9625124575715acdf4f Mon Sep 17 00:00:00 2001 From: Igor Opaniuk Date: Fri, 9 Feb 2024 20:20:39 +0100 Subject: [PATCH 2/8] common: avb_verify: don't call mmc_switch_part for SD mmc_switch_part() is used for switching between hw partitions on eMMC (boot0, boot1, user, rpmb). There is no need to do that for SD card. This fixes the avb command usage on SD cards. Reviewed-by: Mattijs Korpershoek Signed-off-by: Igor Opaniuk Reviewed-by: Dragan Simic Link: https://lore.kernel.org/r/20240209192045.3961832-2-igor.opaniuk@foundries.io Signed-off-by: Mattijs Korpershoek --- common/avb_verify.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/common/avb_verify.c b/common/avb_verify.c index 48ba8db51e5..59f2c25e0de 100644 --- a/common/avb_verify.c +++ b/common/avb_verify.c @@ -358,9 +358,11 @@ static struct mmc_part *get_partition(AvbOps *ops, const char *partition) goto err; } - ret = mmc_switch_part(part->mmc, part_num); - if (ret) - goto err; + if (IS_MMC(part->mmc)) { + ret = mmc_switch_part(part->mmc, part_num); + if (ret) + goto err; + } mmc_blk = mmc_get_blk_desc(part->mmc); if (!mmc_blk) { From a14aa59e7e696f9b90d3fe0de55ce50cf0e21dd5 Mon Sep 17 00:00:00 2001 From: Igor Opaniuk Date: Fri, 9 Feb 2024 20:20:40 +0100 Subject: [PATCH 3/8] avb: move SPDX license identifiers to the first line Move SPDX license identifiers to the first line, so it conforms to license placement rule [1]: Placement: The SPDX license identifier in kernel files shall be added at the first possible line in a file which can contain a comment. For the majority of files this is the first line, except for scripts which require the '#!PATH_TO_INTERPRETER' in the first line. For those scripts the SPDX identifier goes into the second line. [1] https://www.kernel.org/doc/Documentation/process/license-rules.rst Reviewed-by: Mattijs Korpershoek Signed-off-by: Igor Opaniuk Link: https://lore.kernel.org/r/20240209192045.3961832-3-igor.opaniuk@foundries.io Signed-off-by: Mattijs Korpershoek --- cmd/avb.c | 4 +--- common/avb_verify.c | 3 +-- include/avb_verify.h | 4 +--- test/py/tests/test_android/test_avb.py | 3 +-- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/cmd/avb.c b/cmd/avb.c index 783f51b8169..ce8b63873f2 100644 --- a/cmd/avb.c +++ b/cmd/avb.c @@ -1,8 +1,6 @@ - +// SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2018, Linaro Limited - * - * SPDX-License-Identifier: GPL-2.0+ */ #include diff --git a/common/avb_verify.c b/common/avb_verify.c index 59f2c25e0de..938a5383b5d 100644 --- a/common/avb_verify.c +++ b/common/avb_verify.c @@ -1,7 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2018, Linaro Limited - * - * SPDX-License-Identifier: GPL-2.0+ */ #include diff --git a/include/avb_verify.h b/include/avb_verify.h index 1e787ba6668..2fb850044d9 100644 --- a/include/avb_verify.h +++ b/include/avb_verify.h @@ -1,8 +1,6 @@ - +/* SPDX-License-Identifier: GPL-2.0+ */ /* * (C) Copyright 2018, Linaro Limited - * - * SPDX-License-Identifier: GPL-2.0+ */ #ifndef _AVB_VERIFY_H diff --git a/test/py/tests/test_android/test_avb.py b/test/py/tests/test_android/test_avb.py index 238b48c90fa..865efbca4de 100644 --- a/test/py/tests/test_android/test_avb.py +++ b/test/py/tests/test_android/test_avb.py @@ -1,6 +1,5 @@ -# Copyright (c) 2018, Linaro Limited -# # SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2018, Linaro Limited # # Android Verified Boot 2.0 Test From 0508a7c6678685d46ba7f50ad0a70a1a38245945 Mon Sep 17 00:00:00 2001 From: Igor Opaniuk Date: Fri, 9 Feb 2024 20:20:41 +0100 Subject: [PATCH 4/8] common: avb_verify: rework error/debug prints Make error prints more verbose with additional context. Also s/print/debug/g for prints, which might be relevant only for debugging purposes. Reviewed-by: Mattijs Korpershoek Signed-off-by: Igor Opaniuk Link: https://lore.kernel.org/r/20240209192045.3961832-4-igor.opaniuk@foundries.io Signed-off-by: Mattijs Korpershoek --- common/avb_verify.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/common/avb_verify.c b/common/avb_verify.c index 938a5383b5d..ed58239cf8a 100644 --- a/common/avb_verify.c +++ b/common/avb_verify.c @@ -279,9 +279,9 @@ static unsigned long mmc_read_and_flush(struct mmc_part *part, * Reading fails on unaligned buffers, so we have to * use aligned temporary buffer and then copy to destination */ - if (unaligned) { - printf("Handling unaligned read buffer..\n"); + debug("%s: handling unaligned read buffer, addr = 0x%p\n", + __func__, buffer); tmp_buf = get_sector_buf(); buf_size = get_sector_buf_size(); if (sectors > buf_size / part->info.blksz) @@ -320,7 +320,8 @@ static unsigned long mmc_write(struct mmc_part *part, lbaint_t start, if (unaligned) { tmp_buf = get_sector_buf(); buf_size = get_sector_buf_size(); - printf("Handling unaligned wrire buffer..\n"); + debug("%s: handling unaligned read buffer, addr = 0x%p\n", + __func__, buffer); if (sectors > buf_size / part->info.blksz) sectors = buf_size / part->info.blksz; @@ -348,30 +349,35 @@ static struct mmc_part *get_partition(AvbOps *ops, const char *partition) dev_num = get_boot_device(ops); part->mmc = find_mmc_device(dev_num); if (!part->mmc) { - printf("No MMC device at slot %x\n", dev_num); + printf("%s: no MMC device at slot %x\n", __func__, dev_num); goto err; } - if (mmc_init(part->mmc)) { - printf("MMC initialization failed\n"); + ret = mmc_init(part->mmc); + if (ret) { + printf("%s: MMC initialization failed, err = %d\n", + __func__, ret); goto err; } if (IS_MMC(part->mmc)) { ret = mmc_switch_part(part->mmc, part_num); - if (ret) + if (ret) { + printf("%s: MMC part switch failed, err = %d\n", + __func__, ret); goto err; + } } mmc_blk = mmc_get_blk_desc(part->mmc); if (!mmc_blk) { - printf("Error - failed to obtain block descriptor\n"); + printf("%s: failed to obtain block descriptor\n", __func__); goto err; } ret = part_get_info_by_name(mmc_blk, partition, &part->info); if (ret < 0) { - printf("Can't find partition '%s'\n", partition); + printf("%s: can't find partition '%s'\n", __func__, partition); goto err; } @@ -684,7 +690,7 @@ static AvbIOResult read_rollback_index(AvbOps *ops, { #ifndef CONFIG_OPTEE_TA_AVB /* For now we always return 0 as the stored rollback index. */ - printf("%s not supported yet\n", __func__); + debug("%s: rollback protection is not implemented\n", __func__); if (out_rollback_index) *out_rollback_index = 0; @@ -730,7 +736,7 @@ static AvbIOResult write_rollback_index(AvbOps *ops, { #ifndef CONFIG_OPTEE_TA_AVB /* For now this is a no-op. */ - printf("%s not supported yet\n", __func__); + debug("%s: rollback protection is not implemented\n", __func__); return AVB_IO_RESULT_OK; #else @@ -766,8 +772,7 @@ static AvbIOResult read_is_device_unlocked(AvbOps *ops, bool *out_is_unlocked) { #ifndef CONFIG_OPTEE_TA_AVB /* For now we always return that the device is unlocked. */ - - printf("%s not supported yet\n", __func__); + debug("%s: device locking is not implemented\n", __func__); *out_is_unlocked = true; From 0ef0825a8cbbaf7d96a949840a5b4febf60fcebd Mon Sep 17 00:00:00 2001 From: Igor Opaniuk Date: Fri, 9 Feb 2024 20:20:42 +0100 Subject: [PATCH 5/8] cmd: avb: rework prints Simplify and add more context for prints where it's needed. Signed-off-by: Igor Opaniuk Reviewed-by: Mattijs Korpershoek Link: https://lore.kernel.org/r/20240209192045.3961832-5-igor.opaniuk@foundries.io Signed-off-by: Mattijs Korpershoek --- cmd/avb.c | 123 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 48 deletions(-) diff --git a/cmd/avb.c b/cmd/avb.c index ce8b63873f2..62a3ee18e7f 100644 --- a/cmd/avb.c +++ b/cmd/avb.c @@ -11,6 +11,7 @@ #include #define AVB_BOOTARGS "avb_bootargs" + static struct AvbOps *avb_ops; int do_avb_init(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) @@ -28,8 +29,10 @@ int do_avb_init(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) avb_ops = avb_ops_alloc(mmc_dev); if (avb_ops) return CMD_RET_SUCCESS; + else + printf("Can't allocate AvbOps"); - printf("Failed to initialize avb2\n"); + printf("Failed to initialize AVB\n"); return CMD_RET_FAILURE; } @@ -41,10 +44,11 @@ int do_avb_read_part(struct cmd_tbl *cmdtp, int flag, int argc, s64 offset; size_t bytes, bytes_read = 0; void *buffer; + int ret; if (!avb_ops) { - printf("AVB 2.0 is not initialized, please run 'avb init'\n"); - return CMD_RET_USAGE; + printf("AVB is not initialized, please run 'avb init '\n"); + return CMD_RET_FAILURE; } if (argc != 5) @@ -55,14 +59,15 @@ int do_avb_read_part(struct cmd_tbl *cmdtp, int flag, int argc, bytes = hextoul(argv[3], NULL); buffer = (void *)hextoul(argv[4], NULL); - if (avb_ops->read_from_partition(avb_ops, part, offset, bytes, - buffer, &bytes_read) == - AVB_IO_RESULT_OK) { + ret = avb_ops->read_from_partition(avb_ops, part, offset, + bytes, buffer, &bytes_read); + if (ret == AVB_IO_RESULT_OK) { printf("Read %zu bytes\n", bytes_read); return CMD_RET_SUCCESS; } - printf("Failed to read from partition\n"); + printf("Failed to read from partition '%s', err = %d\n", + part, ret); return CMD_RET_FAILURE; } @@ -74,10 +79,11 @@ int do_avb_read_part_hex(struct cmd_tbl *cmdtp, int flag, int argc, s64 offset; size_t bytes, bytes_read = 0; char *buffer; + int ret; if (!avb_ops) { - printf("AVB 2.0 is not initialized, please run 'avb init'\n"); - return CMD_RET_USAGE; + printf("AVB is not initialized, please run 'avb init '\n"); + return CMD_RET_FAILURE; } if (argc != 4) @@ -94,8 +100,9 @@ int do_avb_read_part_hex(struct cmd_tbl *cmdtp, int flag, int argc, } memset(buffer, 0, bytes); - if (avb_ops->read_from_partition(avb_ops, part, offset, bytes, buffer, - &bytes_read) == AVB_IO_RESULT_OK) { + ret = avb_ops->read_from_partition(avb_ops, part, offset, + bytes, buffer, &bytes_read); + if (ret == AVB_IO_RESULT_OK) { printf("Requested %zu, read %zu bytes\n", bytes, bytes_read); printf("Data: "); for (int i = 0; i < bytes_read; i++) @@ -107,7 +114,8 @@ int do_avb_read_part_hex(struct cmd_tbl *cmdtp, int flag, int argc, return CMD_RET_SUCCESS; } - printf("Failed to read from partition\n"); + printf("Failed to read from partition '%s', err = %d\n", + part, ret); free(buffer); return CMD_RET_FAILURE; @@ -120,9 +128,10 @@ int do_avb_write_part(struct cmd_tbl *cmdtp, int flag, int argc, s64 offset; size_t bytes; void *buffer; + int ret; if (!avb_ops) { - printf("AVB 2.0 is not initialized, run 'avb init' first\n"); + printf("AVB is not initialized, please run 'avb init '\n"); return CMD_RET_FAILURE; } @@ -134,13 +143,15 @@ int do_avb_write_part(struct cmd_tbl *cmdtp, int flag, int argc, bytes = hextoul(argv[3], NULL); buffer = (void *)hextoul(argv[4], NULL); - if (avb_ops->write_to_partition(avb_ops, part, offset, bytes, buffer) == - AVB_IO_RESULT_OK) { + ret = avb_ops->write_to_partition(avb_ops, part, offset, + bytes, buffer); + if (ret == AVB_IO_RESULT_OK) { printf("Wrote %zu bytes\n", bytes); return CMD_RET_SUCCESS; } - printf("Failed to write in partition\n"); + printf("Failed to write in partition '%s', err = %d\n", + part, ret); return CMD_RET_FAILURE; } @@ -150,9 +161,10 @@ int do_avb_read_rb(struct cmd_tbl *cmdtp, int flag, int argc, { size_t index; u64 rb_idx; + int ret; if (!avb_ops) { - printf("AVB 2.0 is not initialized, run 'avb init' first\n"); + printf("AVB is not initialized, please run 'avb init '\n"); return CMD_RET_FAILURE; } @@ -161,13 +173,14 @@ int do_avb_read_rb(struct cmd_tbl *cmdtp, int flag, int argc, index = (size_t)hextoul(argv[1], NULL); - if (avb_ops->read_rollback_index(avb_ops, index, &rb_idx) == - AVB_IO_RESULT_OK) { + ret = avb_ops->read_rollback_index(avb_ops, index, &rb_idx); + if (ret == AVB_IO_RESULT_OK) { printf("Rollback index: %llx\n", rb_idx); return CMD_RET_SUCCESS; } - printf("Failed to read rollback index\n"); + printf("Failed to read rollback index id = %zu, err = %d\n", + index, ret); return CMD_RET_FAILURE; } @@ -177,9 +190,10 @@ int do_avb_write_rb(struct cmd_tbl *cmdtp, int flag, int argc, { size_t index; u64 rb_idx; + int ret; if (!avb_ops) { - printf("AVB 2.0 is not initialized, run 'avb init' first\n"); + printf("AVB is not initialized, please run 'avb init '\n"); return CMD_RET_FAILURE; } @@ -189,11 +203,12 @@ int do_avb_write_rb(struct cmd_tbl *cmdtp, int flag, int argc, index = (size_t)hextoul(argv[1], NULL); rb_idx = hextoul(argv[2], NULL); - if (avb_ops->write_rollback_index(avb_ops, index, rb_idx) == - AVB_IO_RESULT_OK) + ret = avb_ops->write_rollback_index(avb_ops, index, rb_idx); + if (ret == AVB_IO_RESULT_OK) return CMD_RET_SUCCESS; - printf("Failed to write rollback index\n"); + printf("Failed to write rollback index id = %zu, err = %d\n", + index, ret); return CMD_RET_FAILURE; } @@ -203,9 +218,10 @@ int do_avb_get_uuid(struct cmd_tbl *cmdtp, int flag, { const char *part; char buffer[UUID_STR_LEN + 1]; + int ret; if (!avb_ops) { - printf("AVB 2.0 is not initialized, run 'avb init' first\n"); + printf("AVB is not initialized, please run 'avb init '\n"); return CMD_RET_FAILURE; } @@ -214,14 +230,16 @@ int do_avb_get_uuid(struct cmd_tbl *cmdtp, int flag, part = argv[1]; - if (avb_ops->get_unique_guid_for_partition(avb_ops, part, buffer, - UUID_STR_LEN + 1) == - AVB_IO_RESULT_OK) { + ret = avb_ops->get_unique_guid_for_partition(avb_ops, part, + buffer, + UUID_STR_LEN + 1); + if (ret == AVB_IO_RESULT_OK) { printf("'%s' UUID: %s\n", part, buffer); return CMD_RET_SUCCESS; } - printf("Failed to read UUID\n"); + printf("Failed to read partition '%s' UUID, err = %d\n", + part, ret); return CMD_RET_FAILURE; } @@ -235,12 +253,13 @@ int do_avb_verify_part(struct cmd_tbl *cmdtp, int flag, char *cmdline; char *extra_args; char *slot_suffix = ""; + int ret; bool unlocked = false; int res = CMD_RET_FAILURE; if (!avb_ops) { - printf("AVB 2.0 is not initialized, run 'avb init' first\n"); + printf("AVB is not initialized, please run 'avb init '\n"); return CMD_RET_FAILURE; } @@ -253,9 +272,10 @@ int do_avb_verify_part(struct cmd_tbl *cmdtp, int flag, printf("## Android Verified Boot 2.0 version %s\n", avb_version_string()); - if (avb_ops->read_is_device_unlocked(avb_ops, &unlocked) != - AVB_IO_RESULT_OK) { - printf("Can't determine device lock state.\n"); + ret = avb_ops->read_is_device_unlocked(avb_ops, &unlocked); + if (ret != AVB_IO_RESULT_OK) { + printf("Can't determine device lock state, err = %d\n", + ret); return CMD_RET_FAILURE; } @@ -302,10 +322,10 @@ int do_avb_verify_part(struct cmd_tbl *cmdtp, int flag, printf("Corrupted dm-verity metadata detected\n"); break; case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION: - printf("Unsupported version avbtool was used\n"); + printf("Unsupported version of avbtool was used\n"); break; case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX: - printf("Checking rollback index failed\n"); + printf("Rollback index check failed\n"); break; case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED: printf("Public key was rejected\n"); @@ -324,9 +344,10 @@ int do_avb_is_unlocked(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { bool unlock; + int ret; if (!avb_ops) { - printf("AVB not initialized, run 'avb init' first\n"); + printf("AVB is not initialized, please run 'avb init '\n"); return CMD_RET_FAILURE; } @@ -335,13 +356,14 @@ int do_avb_is_unlocked(struct cmd_tbl *cmdtp, int flag, return CMD_RET_USAGE; } - if (avb_ops->read_is_device_unlocked(avb_ops, &unlock) == - AVB_IO_RESULT_OK) { + ret = avb_ops->read_is_device_unlocked(avb_ops, &unlock); + if (ret == AVB_IO_RESULT_OK) { printf("Unlocked = %d\n", unlock); return CMD_RET_SUCCESS; } - printf("Can't determine device lock state.\n"); + printf("Can't determine device lock state, err = %d\n", + ret); return CMD_RET_FAILURE; } @@ -354,9 +376,10 @@ int do_avb_read_pvalue(struct cmd_tbl *cmdtp, int flag, int argc, size_t bytes_read; void *buffer; char *endp; + int ret; if (!avb_ops) { - printf("AVB 2.0 is not initialized, run 'avb init' first\n"); + printf("AVB is not initialized, please run 'avb init '\n"); return CMD_RET_FAILURE; } @@ -372,15 +395,16 @@ int do_avb_read_pvalue(struct cmd_tbl *cmdtp, int flag, int argc, if (!buffer) return CMD_RET_FAILURE; - if (avb_ops->read_persistent_value(avb_ops, name, bytes, buffer, - &bytes_read) == AVB_IO_RESULT_OK) { + ret = avb_ops->read_persistent_value(avb_ops, name, bytes, + buffer, &bytes_read); + if (ret == AVB_IO_RESULT_OK) { printf("Read %zu bytes, value = %s\n", bytes_read, (char *)buffer); free(buffer); return CMD_RET_SUCCESS; } - printf("Failed to read persistent value\n"); + printf("Failed to read persistent value, err = %d\n", ret); free(buffer); @@ -392,9 +416,10 @@ int do_avb_write_pvalue(struct cmd_tbl *cmdtp, int flag, int argc, { const char *name; const char *value; + int ret; if (!avb_ops) { - printf("AVB 2.0 is not initialized, run 'avb init' first\n"); + printf("AVB is not initialized, please run 'avb init '\n"); return CMD_RET_FAILURE; } @@ -404,14 +429,16 @@ int do_avb_write_pvalue(struct cmd_tbl *cmdtp, int flag, int argc, name = argv[1]; value = argv[2]; - if (avb_ops->write_persistent_value(avb_ops, name, strlen(value) + 1, - (const uint8_t *)value) == - AVB_IO_RESULT_OK) { + ret = avb_ops->write_persistent_value(avb_ops, name, + strlen(value) + 1, + (const uint8_t *)value); + if (ret == AVB_IO_RESULT_OK) { printf("Wrote %zu bytes\n", strlen(value) + 1); return CMD_RET_SUCCESS; } - printf("Failed to write persistent value\n"); + printf("Failed to write persistent value `%s` = `%s`, err = %d\n", + name, value, ret); return CMD_RET_FAILURE; } From fc7ef0f9e780ed45305002609cf920647787bc79 Mon Sep 17 00:00:00 2001 From: Igor Opaniuk Date: Fri, 9 Feb 2024 20:20:43 +0100 Subject: [PATCH 6/8] common: avb_verify: add str_avb_io_error/str_avb_slot_error Introduce str_avb_io_error() and str_avb_slot_error() functions, that provide a pointer to AVB runtime error message. Reviewed-by: Mattijs Korpershoek Signed-off-by: Igor Opaniuk Link: https://lore.kernel.org/r/20240209192045.3961832-6-igor.opaniuk@foundries.io Signed-off-by: Mattijs Korpershoek --- common/avb_verify.c | 49 ++++++++++++++++++++++++++++++++++++++++++++ include/avb_verify.h | 3 ++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/common/avb_verify.c b/common/avb_verify.c index ed58239cf8a..cff9117d92f 100644 --- a/common/avb_verify.c +++ b/common/avb_verify.c @@ -119,6 +119,55 @@ static const unsigned char avb_root_pub[1032] = { 0xd8, 0x7e, }; +const char *str_avb_io_error(AvbIOResult res) +{ + switch (res) { + case AVB_IO_RESULT_OK: + return "Requested operation was successful"; + case AVB_IO_RESULT_ERROR_IO: + return "Underlying hardware encountered an I/O error"; + case AVB_IO_RESULT_ERROR_OOM: + return "Unable to allocate memory"; + case AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION: + return "Requested partition does not exist"; + case AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION: + return "Bytes requested is outside the range of partition"; + case AVB_IO_RESULT_ERROR_NO_SUCH_VALUE: + return "Named persistent value does not exist"; + case AVB_IO_RESULT_ERROR_INVALID_VALUE_SIZE: + return "Named persistent value size is not supported"; + case AVB_IO_RESULT_ERROR_INSUFFICIENT_SPACE: + return "Buffer is too small for the requested operation"; + default: + return "Unknown AVB error"; + } +} + +const char *str_avb_slot_error(AvbSlotVerifyResult res) +{ + switch (res) { + case AVB_SLOT_VERIFY_RESULT_OK: + return "Verification passed successfully"; + case AVB_SLOT_VERIFY_RESULT_ERROR_OOM: + return "Allocation of memory failed"; + case AVB_SLOT_VERIFY_RESULT_ERROR_IO: + return "I/O error occurred while trying to load data"; + case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION: + return "Digest didn't match or signature checks failed"; + case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX: + return "Rollback index is less than its stored value"; + case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED: + return "Public keys are not accepted"; + case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA: + return "Metadata is invalid or inconsistent"; + case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION: + return "Metadata requires a newer version of libavb"; + case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_ARGUMENT: + return "Invalid arguments are used"; + default: + return "Unknown AVB slot verification error"; + } +} /** * ============================================================================ * Boot states support (GREEN, YELLOW, ORANGE, RED) and dm_verity diff --git a/include/avb_verify.h b/include/avb_verify.h index 2fb850044d9..5d998b5a302 100644 --- a/include/avb_verify.h +++ b/include/avb_verify.h @@ -52,7 +52,8 @@ char *avb_set_enforce_verity(const char *cmdline); char *avb_set_ignore_corruption(const char *cmdline); char *append_cmd_line(char *cmdline_orig, char *cmdline_new); - +const char *str_avb_io_error(AvbIOResult res); +const char *str_avb_slot_error(AvbSlotVerifyResult res); /** * ============================================================================ * I/O helper inline functions From df3cfceeb12b389e87cd33aec860bc0dcbbb8330 Mon Sep 17 00:00:00 2001 From: Igor Opaniuk Date: Fri, 9 Feb 2024 20:20:44 +0100 Subject: [PATCH 7/8] cmd: avb: rework do_avb_verify_part Use existing str_avb_slot_error() function for obtaining verification fail reason details. Take into account device lock state for setting correct androidboot.verifiedbootstate kernel cmdline parameter. Reviewed-by: Mattijs Korpershoek Signed-off-by: Igor Opaniuk Link: https://lore.kernel.org/r/20240209192045.3961832-7-igor.opaniuk@foundries.io Signed-off-by: Mattijs Korpershoek --- cmd/avb.c | 50 +++++++++++++++++--------------------------------- 1 file changed, 17 insertions(+), 33 deletions(-) diff --git a/cmd/avb.c b/cmd/avb.c index 62a3ee18e7f..8fbd48ee5a2 100644 --- a/cmd/avb.c +++ b/cmd/avb.c @@ -250,6 +250,7 @@ int do_avb_verify_part(struct cmd_tbl *cmdtp, int flag, const char * const requested_partitions[] = {"boot", NULL}; AvbSlotVerifyResult slot_result; AvbSlotVerifyData *out_data; + enum avb_boot_state boot_state; char *cmdline; char *extra_args; char *slot_suffix = ""; @@ -287,18 +288,23 @@ int do_avb_verify_part(struct cmd_tbl *cmdtp, int flag, AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, &out_data); - switch (slot_result) { - case AVB_SLOT_VERIFY_RESULT_OK: - /* Until we don't have support of changing unlock states, we - * assume that we are by default in locked state. - * So in this case we can boot only when verification is - * successful; we also supply in cmdline GREEN boot state - */ + /* + * LOCKED devices with custom root of trust setup is not supported (YELLOW) + */ + if (slot_result == AVB_SLOT_VERIFY_RESULT_OK) { printf("Verification passed successfully\n"); - /* export additional bootargs to AVB_BOOTARGS env var */ + /* + * ORANGE state indicates that device may be freely modified. + * Device integrity is left to the user to verify out-of-band. + */ + if (unlocked) + boot_state = AVB_ORANGE; + else + boot_state = AVB_GREEN; - extra_args = avb_set_state(avb_ops, AVB_GREEN); + /* export boot state to AVB_BOOTARGS env var */ + extra_args = avb_set_state(avb_ops, boot_state); if (extra_args) cmdline = append_cmd_line(out_data->cmdline, extra_args); @@ -308,30 +314,8 @@ int do_avb_verify_part(struct cmd_tbl *cmdtp, int flag, env_set(AVB_BOOTARGS, cmdline); res = CMD_RET_SUCCESS; - break; - case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION: - printf("Verification failed\n"); - break; - case AVB_SLOT_VERIFY_RESULT_ERROR_IO: - printf("I/O error occurred during verification\n"); - break; - case AVB_SLOT_VERIFY_RESULT_ERROR_OOM: - printf("OOM error occurred during verification\n"); - break; - case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA: - printf("Corrupted dm-verity metadata detected\n"); - break; - case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION: - printf("Unsupported version of avbtool was used\n"); - break; - case AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX: - printf("Rollback index check failed\n"); - break; - case AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED: - printf("Public key was rejected\n"); - break; - default: - printf("Unknown error occurred\n"); + } else { + printf("Verification failed, reason: %s\n", str_avb_slot_error(slot_result)); } if (out_data) From e2f6270f2da844d598555702d3af4f2e3fae3f9f Mon Sep 17 00:00:00 2001 From: Igor Opaniuk Date: Fri, 9 Feb 2024 20:20:45 +0100 Subject: [PATCH 8/8] doc: android: avb: sync usage details Sync usage info with the one cmd/avb.c. Signed-off-by: Igor Opaniuk Reviewed-by: Mattijs Korpershoek Link: https://lore.kernel.org/r/20240209192045.3961832-8-igor.opaniuk@foundries.io Signed-off-by: Mattijs Korpershoek --- doc/android/avb2.rst | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/doc/android/avb2.rst b/doc/android/avb2.rst index a072119574f..4aca7a5c660 100644 --- a/doc/android/avb2.rst +++ b/doc/android/avb2.rst @@ -38,16 +38,22 @@ AVB 2.0 U-Boot shell commands Provides CLI interface to invoke AVB 2.0 verification + misc. commands for different testing purposes:: - avb init - initialize avb 2.0 for - avb verify - run verification process using hash data from vbmeta structure + avb init - initialize avb 2 for avb read_rb - read rollback index at location avb write_rb - write rollback index to avb is_unlocked - returns unlock status of the device - avb get_uuid - read and print uuid of partition + avb get_uuid - read and print uuid of partition avb read_part - read bytes from - partition to buffer + partition to buffer + avb read_part_hex - read bytes from + partition and print to stdout avb write_part - write bytes to - by using data from + by using data from + avb read_pvalue - read a persistent value + avb write_pvalue - write a persistent value + avb verify [slot_suffix] - run verification process using hash data + from vbmeta structure + [slot_suffix] - _a, _b, etc (if vbmeta partition is slotted) Partitions tampering (example) ------------------------------