The OP-TEE AVB TA stores the device lock state (TA_AVB_CMD_READ/WRITE_LOCK_STATE) but U-Boot only ever read it, so a device backed by the TA could never leave the unlocked (orange) state from the bootloader. Add avb lock and avb unlock, which set the state through a new avb_write_lock_state() helper. As documented by the TA, changing the state resets all rollback indexes.
Signed-off-by: Igor Opaniuk <[email protected]> --- cmd/avb.c | 40 ++++++++++++++++++++++++++++++++++++++++ common/avb_verify.c | 23 +++++++++++++++++++++++ include/avb_verify.h | 3 +++ 3 files changed, 66 insertions(+) diff --git a/cmd/avb.c b/cmd/avb.c index 6f8df7ecb6d..5e45975d349 100644 --- a/cmd/avb.c +++ b/cmd/avb.c @@ -522,6 +522,41 @@ int do_avb_write_pvalue_hex(struct cmd_tbl *cmdtp, int flag, int argc, return CMD_RET_FAILURE; } +#ifdef CONFIG_OPTEE_TA_AVB +static int avb_set_lock(bool locked) +{ + int ret; + + if (!avb_ops) { + printf("AVB is not initialized, please run 'avb init <id>'\n"); + return CMD_RET_FAILURE; + } + + ret = avb_write_lock_state(avb_ops, locked); + if (ret != AVB_IO_RESULT_OK) { + printf("Failed to %s the device, err = %d\n", + locked ? "lock" : "unlock", ret); + return CMD_RET_FAILURE; + } + + printf("Device %s, rollback indexes reset\n", + locked ? "locked" : "unlocked"); + + return CMD_RET_SUCCESS; +} + +int do_avb_lock(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + return avb_set_lock(true); +} + +int do_avb_unlock(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + return avb_set_lock(false); +} +#endif + static struct cmd_tbl cmd_avb[] = { U_BOOT_CMD_MKENT(init, 2, 0, do_avb_init, "", ""), U_BOOT_CMD_MKENT(read_rb, 2, 0, do_avb_read_rb, "", ""), @@ -537,6 +572,8 @@ static struct cmd_tbl cmd_avb[] = { U_BOOT_CMD_MKENT(write_pvalue, 3, 0, do_avb_write_pvalue, "", ""), U_BOOT_CMD_MKENT(read_pvalue_hex, 3, 0, do_avb_read_pvalue_hex, "", ""), U_BOOT_CMD_MKENT(write_pvalue_hex, 3, 0, do_avb_write_pvalue_hex, "", ""), + U_BOOT_CMD_MKENT(lock, 1, 0, do_avb_lock, "", ""), + U_BOOT_CMD_MKENT(unlock, 1, 0, do_avb_unlock, "", ""), #endif }; @@ -579,6 +616,9 @@ U_BOOT_CMD( " and print it as hex\n" "avb write_pvalue_hex <name> <hex> - write the bytes given as a hex\n" " string to persistent value <name>\n" + "avb lock - lock the device (verification errors stop the boot);\n" + " resets all rollback indexes\n" + "avb unlock - unlock the device; resets all rollback indexes\n" #endif "avb verify [slot_suffix] - run verification process using hash data\n" " from vbmeta structure\n" diff --git a/common/avb_verify.c b/common/avb_verify.c index 09f1534c3cc..9231366d5fa 100644 --- a/common/avb_verify.c +++ b/common/avb_verify.c @@ -1056,6 +1056,29 @@ free_name: } #endif +#ifdef CONFIG_OPTEE_TA_AVB +/** + * avb_write_lock_state() - sets the device lock state in the AVB TA + * + * @ops: contains AvbOps handlers + * @locked: true to lock the device, false to unlock it + * + * Changing the lock state resets all rollback indexes in the TA. + * + * Return: AVB_IO_RESULT_OK or an AvbIOResult error + */ +AvbIOResult avb_write_lock_state(AvbOps *ops, bool locked) +{ + struct tee_param param = { + .attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT, + .u.value.a = locked, + }; + + return invoke_func(ops->user_data, TA_AVB_CMD_WRITE_LOCK_STATE, 1, + ¶m); +} +#endif + /** * ============================================================================ * AVB root key digest providers (selected via CONFIG_AVB_ROOT_KEY_*) diff --git a/include/avb_verify.h b/include/avb_verify.h index 66655aab871..d2136b2ce02 100644 --- a/include/avb_verify.h +++ b/include/avb_verify.h @@ -45,6 +45,9 @@ enum mmc_io_type { }; AvbOps *avb_ops_alloc(int boot_device); +#ifdef CONFIG_OPTEE_TA_AVB +AvbIOResult avb_write_lock_state(AvbOps *ops, bool locked); +#endif void avb_ops_free(AvbOps *ops); /** -- 2.53.0
