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,
+                          &param);
+}
+#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

Reply via email to