All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 0/5] eficonfig: add UEFI Secure Boot key maintenance interface
@ 2022-10-26 10:43 Masahisa Kojima
  2022-10-26 10:43 ` [PATCH v6 1/5] eficonfig: refactor eficonfig_select_file_handler() Masahisa Kojima
                   ` (4 more replies)
  0 siblings, 5 replies; 17+ messages in thread
From: Masahisa Kojima @ 2022-10-26 10:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Simon Glass,
	Takahiro Akashi, Etienne Carriere, Masahisa Kojima

This series adds the UEFI Secure Boot key maintenance interface
to the eficonfig command.
User can enroll and delete the PK, KEK, db and dbx.

Source code can be cloned with:
$ git clone https://git.linaro.org/people/masahisa.kojima/u-boot.git -b kojima/eficonfig_sbkey_v6

Masahisa Kojima (5):
  eficonfig: refactor eficonfig_select_file_handler()
  eficonfig: expose append entry function
  eficonfig: refactor change boot order implementation
  eficonfig: add UEFI Secure Boot Key enrollment interface
  eficonfig: add "Show/Delete Signature Database" menu entry

 cmd/Makefile                                  |   5 +
 cmd/eficonfig.c                               | 177 +++--
 cmd/eficonfig_sbkey.c                         | 727 ++++++++++++++++++
 include/efi_config.h                          |  10 +
 .../py/tests/test_eficonfig/test_eficonfig.py |   1 +
 5 files changed, 835 insertions(+), 85 deletions(-)
 create mode 100644 cmd/eficonfig_sbkey.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v6 1/5] eficonfig: refactor eficonfig_select_file_handler()
  2022-10-26 10:43 [PATCH v6 0/5] eficonfig: add UEFI Secure Boot key maintenance interface Masahisa Kojima
@ 2022-10-26 10:43 ` Masahisa Kojima
  2022-11-04 15:12   ` Ilias Apalodimas
  2022-10-26 10:43 ` [PATCH v6 2/5] eficonfig: expose append entry function Masahisa Kojima
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 17+ messages in thread
From: Masahisa Kojima @ 2022-10-26 10:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Simon Glass,
	Takahiro Akashi, Etienne Carriere, Masahisa Kojima

eficonfig_select_file_handler() is commonly used to select the
file. eficonfig_display_select_file_option() intends to add the
additional menu mainly to clear the selected file information.
eficonfig_display_select_file_option() is not necessary for the
file selection process, so it should be outside of
eficonfig_select_file_handler().

Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
---
No change since v2

newly created in v2

 cmd/eficonfig.c                                | 13 +++++--------
 test/py/tests/test_eficonfig/test_eficonfig.py |  1 +
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
index 2595dd9563..f6a99bd01a 100644
--- a/cmd/eficonfig.c
+++ b/cmd/eficonfig.c
@@ -968,7 +968,7 @@ efi_status_t eficonfig_process_clear_file_selection(void *data)
 }
 
 static struct eficonfig_item select_file_menu_items[] = {
-	{"Select File", eficonfig_process_select_file},
+	{"Select File", eficonfig_select_file_handler},
 	{"Clear", eficonfig_process_clear_file_selection},
 	{"Quit", eficonfig_process_quit},
 };
@@ -980,12 +980,13 @@ static struct eficonfig_item select_file_menu_items[] = {
  * @file_info:	pointer to the file information structure
  * Return:	status code
  */
-efi_status_t eficonfig_display_select_file_option(struct eficonfig_select_file_info *file_info)
+efi_status_t eficonfig_display_select_file_option(void *data)
 {
 	efi_status_t ret;
 	struct efimenu *efi_menu;
 
-	select_file_menu_items[1].data = file_info;
+	select_file_menu_items[0].data = data;
+	select_file_menu_items[1].data = data;
 	efi_menu = eficonfig_create_fixed_menu(select_file_menu_items,
 					       ARRAY_SIZE(select_file_menu_items));
 	if (!efi_menu)
@@ -1016,10 +1017,6 @@ efi_status_t eficonfig_select_file_handler(void *data)
 	struct eficonfig_select_file_info *tmp = NULL;
 	struct eficonfig_select_file_info *file_info = data;
 
-	ret = eficonfig_display_select_file_option(file_info);
-	if (ret != EFI_SUCCESS)
-		return ret;
-
 	tmp = calloc(1, sizeof(struct eficonfig_select_file_info));
 	if (!tmp)
 		return EFI_OUT_OF_RESOURCES;
@@ -1284,7 +1281,7 @@ static efi_status_t prepare_file_selection_entry(struct efimenu *efi_menu, char
 	utf8_utf16_strcpy(&p, devname);
 	u16_strlcat(file_name, file_info->current_path, len);
 	ret = create_boot_option_entry(efi_menu, title, file_name,
-				       eficonfig_select_file_handler, file_info);
+				       eficonfig_display_select_file_option, file_info);
 out:
 	free(devname);
 	free(file_name);
diff --git a/test/py/tests/test_eficonfig/test_eficonfig.py b/test/py/tests/test_eficonfig/test_eficonfig.py
index 99606d9c4b..102bfd7541 100644
--- a/test/py/tests/test_eficonfig/test_eficonfig.py
+++ b/test/py/tests/test_eficonfig/test_eficonfig.py
@@ -349,6 +349,7 @@ def test_efi_eficonfig(u_boot_console, efi_eficonfig_data):
         press_up_down_enter_and_wait(0, 1, True, 'Quit')
         press_up_down_enter_and_wait(0, 0, True, 'No block device found!')
         press_escape_key(False)
+        press_escape_key(False)
         check_current_is_maintenance_menu()
         # Return to U-Boot console
         press_escape_key(True)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v6 2/5] eficonfig: expose append entry function
  2022-10-26 10:43 [PATCH v6 0/5] eficonfig: add UEFI Secure Boot key maintenance interface Masahisa Kojima
  2022-10-26 10:43 ` [PATCH v6 1/5] eficonfig: refactor eficonfig_select_file_handler() Masahisa Kojima
@ 2022-10-26 10:43 ` Masahisa Kojima
  2022-11-04 15:16   ` Ilias Apalodimas
  2022-10-26 10:43 ` [PATCH v6 3/5] eficonfig: refactor change boot order implementation Masahisa Kojima
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 17+ messages in thread
From: Masahisa Kojima @ 2022-10-26 10:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Simon Glass,
	Takahiro Akashi, Etienne Carriere, Masahisa Kojima

This commit exposes the eficonfig menu entry append function.

Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
---
No change since v2

newly created in v2

 cmd/eficonfig.c      | 32 +++++++++++++++++---------------
 include/efi_config.h |  5 +++++
 2 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
index f6a99bd01a..0cb0770ac3 100644
--- a/cmd/eficonfig.c
+++ b/cmd/eficonfig.c
@@ -263,7 +263,7 @@ efi_status_t eficonfig_process_quit(void *data)
 }
 
 /**
- * append_entry() - append menu item
+ * eficonfig_append_menu_entry() - append menu item
  *
  * @efi_menu:	pointer to the efimenu structure
  * @title:	pointer to the entry title
@@ -271,8 +271,9 @@ efi_status_t eficonfig_process_quit(void *data)
  * @data:	pointer to the data to be passed to each entry callback
  * Return:	status code
  */
-static efi_status_t append_entry(struct efimenu *efi_menu,
-				 char *title, eficonfig_entry_func func, void *data)
+efi_status_t eficonfig_append_menu_entry(struct efimenu *efi_menu,
+					 char *title, eficonfig_entry_func func,
+					 void *data)
 {
 	struct eficonfig_entry *entry;
 
@@ -295,12 +296,12 @@ static efi_status_t append_entry(struct efimenu *efi_menu,
 }
 
 /**
- * append_quit_entry() - append quit entry
+ * eficonfig_append_quit_entry() - append quit entry
  *
  * @efi_menu:	pointer to the efimenu structure
  * Return:	status code
  */
-static efi_status_t append_quit_entry(struct efimenu *efi_menu)
+efi_status_t eficonfig_append_quit_entry(struct efimenu *efi_menu)
 {
 	char *title;
 	efi_status_t ret;
@@ -309,7 +310,7 @@ static efi_status_t append_quit_entry(struct efimenu *efi_menu)
 	if (!title)
 		return EFI_OUT_OF_RESOURCES;
 
-	ret = append_entry(efi_menu, title, eficonfig_process_quit, NULL);
+	ret = eficonfig_append_menu_entry(efi_menu, title, eficonfig_process_quit, NULL);
 	if (ret != EFI_SUCCESS)
 		free(title);
 
@@ -341,7 +342,7 @@ void *eficonfig_create_fixed_menu(const struct eficonfig_item *items, int count)
 		if (!title)
 			goto out;
 
-		ret = append_entry(efi_menu, title, iter->func, iter->data);
+		ret = eficonfig_append_menu_entry(efi_menu, title, iter->func, iter->data);
 		if (ret != EFI_SUCCESS) {
 			free(title);
 			goto out;
@@ -634,14 +635,15 @@ static efi_status_t eficonfig_select_volume(struct eficonfig_select_file_info *f
 		info->v = v;
 		info->dp = device_path;
 		info->file_info = file_info;
-		ret = append_entry(efi_menu, devname, eficonfig_volume_selected, info);
+		ret = eficonfig_append_menu_entry(efi_menu, devname, eficonfig_volume_selected,
+						  info);
 		if (ret != EFI_SUCCESS) {
 			free(info);
 			goto out;
 		}
 	}
 
-	ret = append_quit_entry(efi_menu);
+	ret = eficonfig_append_quit_entry(efi_menu);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
@@ -745,8 +747,8 @@ eficonfig_create_file_entry(struct efimenu *efi_menu, u32 count,
 	      (int (*)(const void *, const void *))sort_file);
 
 	for (i = 0; i < entry_num; i++) {
-		ret = append_entry(efi_menu, tmp_infos[i]->file_name,
-				   eficonfig_file_selected, tmp_infos[i]);
+		ret = eficonfig_append_menu_entry(efi_menu, tmp_infos[i]->file_name,
+						  eficonfig_file_selected, tmp_infos[i]);
 		if (ret != EFI_SUCCESS)
 			goto out;
 	}
@@ -815,7 +817,7 @@ static efi_status_t eficonfig_select_file(struct eficonfig_select_file_info *fil
 		if (ret != EFI_SUCCESS)
 			goto err;
 
-		ret = append_quit_entry(efi_menu);
+		ret = eficonfig_append_quit_entry(efi_menu);
 		if (ret != EFI_SUCCESS)
 			goto err;
 
@@ -1218,7 +1220,7 @@ static efi_status_t create_boot_option_entry(struct efimenu *efi_menu, char *tit
 		utf16_utf8_strcpy(&p, val);
 	}
 
-	return append_entry(efi_menu, buf, func, data);
+	return eficonfig_append_menu_entry(efi_menu, buf, func, data);
 }
 
 /**
@@ -1677,7 +1679,7 @@ static efi_status_t eficonfig_add_boot_selection_entry(struct efimenu *efi_menu,
 	utf16_utf8_strcpy(&p, lo.label);
 	info->boot_index = boot_index;
 	info->selected = selected;
-	ret = append_entry(efi_menu, buf, eficonfig_process_boot_selected, info);
+	ret = eficonfig_append_menu_entry(efi_menu, buf, eficonfig_process_boot_selected, info);
 	if (ret != EFI_SUCCESS) {
 		free(load_option);
 		free(info);
@@ -1736,7 +1738,7 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected)
 			break;
 	}
 
-	ret = append_quit_entry(efi_menu);
+	ret = eficonfig_append_quit_entry(efi_menu);
 	if (ret != EFI_SUCCESS)
 		goto out;
 
diff --git a/include/efi_config.h b/include/efi_config.h
index 098cac2115..86bc801211 100644
--- a/include/efi_config.h
+++ b/include/efi_config.h
@@ -95,4 +95,9 @@ efi_status_t eficonfig_get_unused_bootoption(u16 *buf,
 efi_status_t eficonfig_append_bootorder(u16 index);
 efi_status_t eficonfig_generate_media_device_boot_option(void);
 
+efi_status_t eficonfig_append_menu_entry(struct efimenu *efi_menu,
+					 char *title, eficonfig_entry_func func,
+					 void *data);
+efi_status_t eficonfig_append_quit_entry(struct efimenu *efi_menu);
+
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v6 3/5] eficonfig: refactor change boot order implementation
  2022-10-26 10:43 [PATCH v6 0/5] eficonfig: add UEFI Secure Boot key maintenance interface Masahisa Kojima
  2022-10-26 10:43 ` [PATCH v6 1/5] eficonfig: refactor eficonfig_select_file_handler() Masahisa Kojima
  2022-10-26 10:43 ` [PATCH v6 2/5] eficonfig: expose append entry function Masahisa Kojima
@ 2022-10-26 10:43 ` Masahisa Kojima
  2022-11-04 22:08   ` Ilias Apalodimas
  2022-10-26 10:43 ` [PATCH v6 4/5] eficonfig: add UEFI Secure Boot Key enrollment interface Masahisa Kojima
  2022-10-26 10:43 ` [PATCH v6 5/5] eficonfig: add "Show/Delete Signature Database" menu entry Masahisa Kojima
  4 siblings, 1 reply; 17+ messages in thread
From: Masahisa Kojima @ 2022-10-26 10:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Simon Glass,
	Takahiro Akashi, Etienne Carriere, Masahisa Kojima

This commit refactors change boot order implementation
to use 'eficonfig_entry' structure.

Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
---
No update since v5

Changes in v5:
- remove direct access mode

newly created in v4

 cmd/eficonfig.c | 129 +++++++++++++++++++++++++-----------------------
 1 file changed, 67 insertions(+), 62 deletions(-)

diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
index 0cb0770ac3..c765b795d0 100644
--- a/cmd/eficonfig.c
+++ b/cmd/eficonfig.c
@@ -93,20 +93,14 @@ struct eficonfig_boot_selection_data {
 };
 
 /**
- * struct eficonfig_boot_order - structure to be used to update BootOrder variable
+ * struct eficonfig_boot_order_data - structure to be used to update BootOrder variable
  *
- * @num:		index in the menu entry
- * @description:	pointer to the description string
  * @boot_index:		boot option index
  * @active:		flag to include the boot option into BootOrder variable
- * @list:		list structure
  */
-struct eficonfig_boot_order {
-	u32 num;
-	u16 *description;
+struct eficonfig_boot_order_data {
 	u32 boot_index;
 	bool active;
-	struct list_head list;
 };
 
 /**
@@ -1814,7 +1808,7 @@ static void eficonfig_display_change_boot_order(struct efimenu *efi_menu)
 {
 	bool reverse;
 	struct list_head *pos, *n;
-	struct eficonfig_boot_order *entry;
+	struct eficonfig_entry *entry;
 
 	printf(ANSI_CLEAR_CONSOLE ANSI_CURSOR_POSITION
 	       "\n  ** Change Boot Order **\n"
@@ -1830,7 +1824,7 @@ static void eficonfig_display_change_boot_order(struct efimenu *efi_menu)
 
 	/* draw boot option list */
 	list_for_each_safe(pos, n, &efi_menu->list) {
-		entry = list_entry(pos, struct eficonfig_boot_order, list);
+		entry = list_entry(pos, struct eficonfig_entry, list);
 		reverse = (entry->num == efi_menu->active);
 
 		printf(ANSI_CURSOR_POSITION, entry->num + 4, 7);
@@ -1839,13 +1833,13 @@ static void eficonfig_display_change_boot_order(struct efimenu *efi_menu)
 			puts(ANSI_COLOR_REVERSE);
 
 		if (entry->num < efi_menu->count - 2) {
-			if (entry->active)
+			if (((struct eficonfig_boot_order_data *)entry->data)->active)
 				printf("[*]  ");
 			else
 				printf("[ ]  ");
 		}
 
-		printf("%ls", entry->description);
+		printf("%s", entry->title);
 
 		if (reverse)
 			puts(ANSI_COLOR_RESET);
@@ -1862,9 +1856,8 @@ static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu)
 {
 	int esc = 0;
 	struct list_head *pos, *n;
-	struct eficonfig_boot_order *tmp;
 	enum bootmenu_key key = KEY_NONE;
-	struct eficonfig_boot_order *entry;
+	struct eficonfig_entry *entry, *tmp;
 
 	while (1) {
 		bootmenu_loop(NULL, &key, &esc);
@@ -1873,11 +1866,11 @@ static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu)
 		case KEY_PLUS:
 			if (efi_menu->active > 0) {
 				list_for_each_safe(pos, n, &efi_menu->list) {
-					entry = list_entry(pos, struct eficonfig_boot_order, list);
+					entry = list_entry(pos, struct eficonfig_entry, list);
 					if (entry->num == efi_menu->active)
 						break;
 				}
-				tmp = list_entry(pos->prev, struct eficonfig_boot_order, list);
+				tmp = list_entry(pos->prev, struct eficonfig_entry, list);
 				entry->num--;
 				tmp->num++;
 				list_del(&tmp->list);
@@ -1891,11 +1884,11 @@ static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu)
 		case KEY_MINUS:
 			if (efi_menu->active < efi_menu->count - 3) {
 				list_for_each_safe(pos, n, &efi_menu->list) {
-					entry = list_entry(pos, struct eficonfig_boot_order, list);
+					entry = list_entry(pos, struct eficonfig_entry, list);
 					if (entry->num == efi_menu->active)
 						break;
 				}
-				tmp = list_entry(pos->next, struct eficonfig_boot_order, list);
+				tmp = list_entry(pos->next, struct eficonfig_entry, list);
 				entry->num++;
 				tmp->num--;
 				list_del(&entry->list);
@@ -1921,9 +1914,11 @@ static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu)
 		case KEY_SPACE:
 			if (efi_menu->active < efi_menu->count - 2) {
 				list_for_each_safe(pos, n, &efi_menu->list) {
-					entry = list_entry(pos, struct eficonfig_boot_order, list);
+					entry = list_entry(pos, struct eficonfig_entry, list);
 					if (entry->num == efi_menu->active) {
-						entry->active = entry->active ? false : true;
+						struct eficonfig_boot_order_data *data = entry->data;
+
+						data->active = data->active ? false : true;
 						return EFI_NOT_READY;
 					}
 				}
@@ -1949,12 +1944,13 @@ static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu)
 static efi_status_t eficonfig_add_change_boot_order_entry(struct efimenu *efi_menu,
 							  u32 boot_index, bool active)
 {
+	char *title, *p;
 	efi_status_t ret;
 	efi_uintn_t size;
 	void *load_option;
 	struct efi_load_option lo;
 	u16 varname[] = u"Boot####";
-	struct eficonfig_boot_order *entry;
+	struct eficonfig_boot_order_data *data;
 
 	efi_create_indexed_name(varname, sizeof(varname), "Boot", boot_index);
 	load_option = efi_get_var(varname, &efi_global_variable_guid, &size);
@@ -1962,31 +1958,38 @@ static efi_status_t eficonfig_add_change_boot_order_entry(struct efimenu *efi_me
 		return EFI_SUCCESS;
 
 	ret = efi_deserialize_load_option(&lo, load_option, &size);
-	if (ret != EFI_SUCCESS) {
-		free(load_option);
-		return ret;
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	data = calloc(1, sizeof(struct eficonfig_boot_order_data));
+	if (!data) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out;
 	}
 
-	entry = calloc(1, sizeof(struct eficonfig_boot_order));
-	if (!entry) {
-		free(load_option);
-		return EFI_OUT_OF_RESOURCES;
+	title = calloc(1, utf16_utf8_strlen(lo.label) + 1);
+	if (!title) {
+		free(data);
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out;
 	}
+	p = title;
+	utf16_utf8_strcpy(&p, lo.label);
 
-	entry->description = u16_strdup(lo.label);
-	if (!entry->description) {
-		free(load_option);
-		free(entry);
-		return EFI_OUT_OF_RESOURCES;
+	data->boot_index = boot_index;
+	data->active = active;
+
+	ret = eficonfig_append_menu_entry(efi_menu, title, NULL, data);
+	if (ret != EFI_SUCCESS) {
+		free(data);
+		free(title);
+		goto out;
 	}
-	entry->num = efi_menu->count++;
-	entry->boot_index = boot_index;
-	entry->active = active;
-	list_add_tail(&entry->list, &efi_menu->list);
 
+out:
 	free(load_option);
 
-	return EFI_SUCCESS;
+	return ret;
 }
 
 /**
@@ -2001,8 +2004,8 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi
 							     u16 *bootorder, efi_uintn_t num)
 {
 	u32 i;
+	char *title;
 	efi_status_t ret;
-	struct eficonfig_boot_order *entry;
 
 	/* list the load option in the order of BootOrder variable */
 	for (i = 0; i < num; i++) {
@@ -2029,27 +2032,25 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi
 	}
 
 	/* add "Save" and "Quit" entries */
-	entry = calloc(1, sizeof(struct eficonfig_boot_order));
-	if (!entry)
+	title = strdup("Save");
+	if (!title) {
+		ret = EFI_OUT_OF_RESOURCES;
 		goto out;
+	}
 
-	entry->num = efi_menu->count++;
-	entry->description = u16_strdup(u"Save");
-	list_add_tail(&entry->list, &efi_menu->list);
-
-	entry = calloc(1, sizeof(struct eficonfig_boot_order));
-	if (!entry)
+	ret = eficonfig_append_menu_entry(efi_menu, title, NULL, NULL);
+	if (ret != EFI_SUCCESS)
 		goto out;
 
-	entry->num = efi_menu->count++;
-	entry->description = u16_strdup(u"Quit");
-	list_add_tail(&entry->list, &efi_menu->list);
+	ret = eficonfig_append_quit_entry(efi_menu);
+	if (ret != EFI_SUCCESS)
+		goto out;
 
 	efi_menu->active = 0;
 
 	return EFI_SUCCESS;
 out:
-	return EFI_OUT_OF_RESOURCES;
+	return ret;
 }
 
 /**
@@ -2065,7 +2066,7 @@ static efi_status_t eficonfig_process_change_boot_order(void *data)
 	efi_status_t ret;
 	efi_uintn_t num, size;
 	struct list_head *pos, *n;
-	struct eficonfig_boot_order *entry;
+	struct eficonfig_entry *entry;
 	struct efimenu *efi_menu;
 
 	efi_menu = calloc(1, sizeof(struct efimenu));
@@ -2096,9 +2097,16 @@ static efi_status_t eficonfig_process_change_boot_order(void *data)
 			/* create new BootOrder  */
 			count = 0;
 			list_for_each_safe(pos, n, &efi_menu->list) {
-				entry = list_entry(pos, struct eficonfig_boot_order, list);
-				if (entry->active)
-					new_bootorder[count++] = entry->boot_index;
+				struct eficonfig_boot_order_data *data;
+
+				entry = list_entry(pos, struct eficonfig_entry, list);
+				/* exit the loop when iteration reaches "Save" */
+				if (!strncmp(entry->title, "Save", strlen("Save")))
+					break;
+
+				data = entry->data;
+				if (data->active)
+					new_bootorder[count++] = data->boot_index;
 			}
 
 			size = count * sizeof(u16);
@@ -2117,15 +2125,12 @@ static efi_status_t eficonfig_process_change_boot_order(void *data)
 		}
 	}
 out:
+	free(bootorder);
 	list_for_each_safe(pos, n, &efi_menu->list) {
-		entry = list_entry(pos, struct eficonfig_boot_order, list);
-		list_del(&entry->list);
-		free(entry->description);
-		free(entry);
+		entry = list_entry(pos, struct eficonfig_entry, list);
+		free(entry->data);
 	}
-
-	free(bootorder);
-	free(efi_menu);
+	eficonfig_destroy(efi_menu);
 
 	/* to stay the parent menu */
 	ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v6 4/5] eficonfig: add UEFI Secure Boot Key enrollment interface
  2022-10-26 10:43 [PATCH v6 0/5] eficonfig: add UEFI Secure Boot key maintenance interface Masahisa Kojima
                   ` (2 preceding siblings ...)
  2022-10-26 10:43 ` [PATCH v6 3/5] eficonfig: refactor change boot order implementation Masahisa Kojima
@ 2022-10-26 10:43 ` Masahisa Kojima
  2022-11-04 21:46   ` Ilias Apalodimas
  2022-10-26 10:43 ` [PATCH v6 5/5] eficonfig: add "Show/Delete Signature Database" menu entry Masahisa Kojima
  4 siblings, 1 reply; 17+ messages in thread
From: Masahisa Kojima @ 2022-10-26 10:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Simon Glass,
	Takahiro Akashi, Etienne Carriere, Masahisa Kojima, Roger Knecht,
	Chris Morgan, Stefan Roese, Ovidiu Panait, Ashok Reddy Soma

This commit adds the menu-driven UEFI Secure Boot Key
enrollment interface. User can enroll the PK, KEK, db
and dbx by selecting EFI Signature Lists file.
After the PK is enrolled, UEFI Secure Boot is enabled and
EFI Signature Lists file must be signed by KEK or PK.

Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
---
Changes in v6:
- use efi_secure_boot_enabled()
- replace with WIN_CERT_REVISION_2_0 from pe.h
- call efi_build_signature_store() to check the valid EFI Signature List
- update comment

Changes in v4:
- add CONFIG_EFI_MM_COMM_TEE dependency
- fix error handling

Changes in v3:
- fix error handling

Changes in v2:
- allow to enroll .esl file
- fix typos
- add function comments

 cmd/Makefile          |   5 +
 cmd/eficonfig.c       |   3 +
 cmd/eficonfig_sbkey.c | 333 ++++++++++++++++++++++++++++++++++++++++++
 include/efi_config.h  |   5 +
 4 files changed, 346 insertions(+)
 create mode 100644 cmd/eficonfig_sbkey.c

diff --git a/cmd/Makefile b/cmd/Makefile
index c95e09d058..e43ef22e98 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -66,6 +66,11 @@ obj-$(CONFIG_CMD_EEPROM) += eeprom.o
 obj-$(CONFIG_EFI) += efi.o
 obj-$(CONFIG_CMD_EFIDEBUG) += efidebug.o
 obj-$(CONFIG_CMD_EFICONFIG) += eficonfig.o
+ifdef CONFIG_CMD_EFICONFIG
+ifdef CONFIG_EFI_MM_COMM_TEE
+obj-$(CONFIG_EFI_SECURE_BOOT) += eficonfig_sbkey.o
+endif
+endif
 obj-$(CONFIG_CMD_ELF) += elf.o
 obj-$(CONFIG_CMD_EROFS) += erofs.o
 obj-$(CONFIG_HUSH_PARSER) += exit.o
diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
index c765b795d0..0b643a046c 100644
--- a/cmd/eficonfig.c
+++ b/cmd/eficonfig.c
@@ -2447,6 +2447,9 @@ static const struct eficonfig_item maintenance_menu_items[] = {
 	{"Edit Boot Option", eficonfig_process_edit_boot_option},
 	{"Change Boot Order", eficonfig_process_change_boot_order},
 	{"Delete Boot Option", eficonfig_process_delete_boot_option},
+#if (CONFIG_IS_ENABLED(EFI_SECURE_BOOT) && CONFIG_IS_ENABLED(EFI_MM_COMM_TEE))
+	{"Secure Boot Configuration", eficonfig_process_secure_boot_config},
+#endif
 	{"Quit", eficonfig_process_quit},
 };
 
diff --git a/cmd/eficonfig_sbkey.c b/cmd/eficonfig_sbkey.c
new file mode 100644
index 0000000000..e4a3573f1b
--- /dev/null
+++ b/cmd/eficonfig_sbkey.c
@@ -0,0 +1,333 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  Menu-driven UEFI Secure Boot Key Maintenance
+ *
+ *  Copyright (c) 2022 Masahisa Kojima, Linaro Limited
+ */
+
+#include <ansi.h>
+#include <common.h>
+#include <charset.h>
+#include <hexdump.h>
+#include <log.h>
+#include <malloc.h>
+#include <menu.h>
+#include <efi_loader.h>
+#include <efi_config.h>
+#include <efi_variable.h>
+#include <crypto/pkcs7_parser.h>
+
+enum efi_sbkey_signature_type {
+	SIG_TYPE_X509 = 0,
+	SIG_TYPE_HASH,
+	SIG_TYPE_CRL,
+	SIG_TYPE_RSA2048,
+};
+
+struct eficonfig_sigtype_to_str {
+	efi_guid_t sig_type;
+	char *str;
+	enum efi_sbkey_signature_type type;
+};
+
+static const struct eficonfig_sigtype_to_str sigtype_to_str[] = {
+	{EFI_CERT_X509_GUID,		"X509",			SIG_TYPE_X509},
+	{EFI_CERT_SHA256_GUID,		"SHA256",		SIG_TYPE_HASH},
+	{EFI_CERT_X509_SHA256_GUID,	"X509_SHA256 CRL",	SIG_TYPE_CRL},
+	{EFI_CERT_X509_SHA384_GUID,	"X509_SHA384 CRL",	SIG_TYPE_CRL},
+	{EFI_CERT_X509_SHA512_GUID,	"X509_SHA512 CRL",	SIG_TYPE_CRL},
+	/* U-Boot does not support the following signature types */
+/*	{EFI_CERT_RSA2048_GUID,		"RSA2048",		SIG_TYPE_RSA2048}, */
+/*	{EFI_CERT_RSA2048_SHA256_GUID,	"RSA2048_SHA256",	SIG_TYPE_RSA2048}, */
+/*	{EFI_CERT_SHA1_GUID,		"SHA1",			SIG_TYPE_HASH}, */
+/*	{EFI_CERT_RSA2048_SHA_GUID,	"RSA2048_SHA",		SIG_TYPE_RSA2048 }, */
+/*	{EFI_CERT_SHA224_GUID,		"SHA224",		SIG_TYPE_HASH}, */
+/*	{EFI_CERT_SHA384_GUID,		"SHA384",		SIG_TYPE_HASH}, */
+/*	{EFI_CERT_SHA512_GUID,		"SHA512",		SIG_TYPE_HASH}, */
+};
+
+/**
+ * create_time_based_payload() - create payload for time based authenticate variable
+ *
+ * @db:		pointer to the original signature database
+ * @new_db:	pointer to the authenticated variable payload
+ * @size:	pointer to payload size
+ * Return:	status code
+ */
+static efi_status_t create_time_based_payload(void *db, void **new_db, efi_uintn_t *size)
+{
+	efi_status_t ret;
+	struct efi_time time;
+	efi_uintn_t total_size;
+	struct efi_variable_authentication_2 *auth;
+
+	*new_db = NULL;
+
+	/*
+	 * SetVariable() call with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
+	 * attribute requires EFI_VARIABLE_AUTHENTICATED_2 descriptor, prepare it
+	 * without certificate data in it.
+	 */
+	total_size = sizeof(struct efi_variable_authentication_2) + *size;
+
+	auth = calloc(1, total_size);
+	if (!auth)
+		return EFI_OUT_OF_RESOURCES;
+
+	ret = EFI_CALL((*efi_runtime_services.get_time)(&time, NULL));
+	if (ret != EFI_SUCCESS) {
+		free(auth);
+		return EFI_OUT_OF_RESOURCES;
+	}
+	time.pad1 = 0;
+	time.nanosecond = 0;
+	time.timezone = 0;
+	time.daylight = 0;
+	time.pad2 = 0;
+	memcpy(&auth->time_stamp, &time, sizeof(time));
+	auth->auth_info.hdr.dwLength = sizeof(struct win_certificate_uefi_guid);
+	auth->auth_info.hdr.wRevision = WIN_CERT_REVISION_2_0;
+	auth->auth_info.hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
+	guidcpy(&auth->auth_info.cert_type, &efi_guid_cert_type_pkcs7);
+	if (db)
+		memcpy((u8 *)auth + sizeof(struct efi_variable_authentication_2), db, *size);
+
+	*new_db = auth;
+	*size = total_size;
+
+	return EFI_SUCCESS;
+}
+
+/**
+ * file_have_auth_header() - check file has EFI_VARIABLE_AUTHENTICATION_2 header
+ * @buf:	pointer to file
+ * @size:	file size
+ * Return:	true if file has auth header, false otherwise
+ */
+static bool file_have_auth_header(void *buf, efi_uintn_t size)
+{
+	struct efi_variable_authentication_2 *auth = buf;
+
+	if (auth->auth_info.hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID)
+		return false;
+
+	if (guidcmp(&auth->auth_info.cert_type, &efi_guid_cert_type_pkcs7))
+		return false;
+
+	return true;
+}
+
+/**
+ * eficonfig_process_enroll_key() - enroll key into signature database
+ *
+ * @data:	pointer to the data for each entry
+ * Return:	status code
+ */
+static efi_status_t eficonfig_process_enroll_key(void *data)
+{
+	u32 attr;
+	char *buf = NULL;
+	efi_uintn_t size;
+	efi_status_t ret;
+	void *new_db = NULL;
+	struct efi_file_handle *f;
+	struct efi_file_handle *root;
+	struct eficonfig_select_file_info file_info;
+
+	file_info.current_path = calloc(1, EFICONFIG_FILE_PATH_BUF_SIZE);
+	if (!file_info.current_path) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+
+	ret = eficonfig_select_file_handler(&file_info);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	ret = efi_open_volume_int(file_info.current_volume, &root);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	ret = efi_file_open_int(root, &f, file_info.current_path, EFI_FILE_MODE_READ, 0);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	size = 0;
+	ret = EFI_CALL(f->getinfo(f, &efi_file_info_guid, &size, NULL));
+	if (ret != EFI_BUFFER_TOO_SMALL)
+		goto out;
+
+	buf = calloc(1, size);
+	if (!buf) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+	ret = EFI_CALL(f->getinfo(f, &efi_file_info_guid, &size, buf));
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	size = ((struct efi_file_info *)buf)->file_size;
+	free(buf);
+
+	buf = calloc(1, size);
+	if (!buf) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+
+	ret = efi_file_read_int(f, &size, buf);
+	if (ret != EFI_SUCCESS) {
+		eficonfig_print_msg("ERROR! Failed to read file.");
+		goto out;
+	}
+	if (size == 0) {
+		eficonfig_print_msg("ERROR! File is empty.");
+		goto out;
+	}
+
+	if (!file_have_auth_header(buf, size)) {
+		struct efi_signature_store *sigstore;
+		char *tmp_buf;
+
+		/* Check if the file is valid EFI Signature List(s) */
+		tmp_buf = calloc(1, size);
+		if (!tmp_buf) {
+			ret = EFI_OUT_OF_RESOURCES;
+			goto out;
+		}
+		memcpy(tmp_buf, buf, size);
+		/* tmp_buf is freed in efi_build_signature_store() */
+		sigstore = efi_build_signature_store(tmp_buf, size);
+		if (!sigstore) {
+			eficonfig_print_msg("ERROR! Invalid file format.");
+			ret = EFI_INVALID_PARAMETER;
+			goto out;
+		}
+		efi_sigstore_free(sigstore);
+
+		ret = create_time_based_payload(buf, &new_db, &size);
+		if (ret != EFI_SUCCESS) {
+			eficonfig_print_msg("ERROR! Failed to create payload with timestamp.");
+			goto out;
+		}
+
+		free(buf);
+		buf = new_db;
+	}
+
+	attr = EFI_VARIABLE_NON_VOLATILE |
+	       EFI_VARIABLE_BOOTSERVICE_ACCESS |
+	       EFI_VARIABLE_RUNTIME_ACCESS |
+	       EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+
+	/* PK can enroll only one certificate */
+	if (u16_strcmp(data, u"PK")) {
+		efi_uintn_t db_size = 0;
+
+		/* check the variable exists. If exists, add APPEND_WRITE attribute */
+		ret = efi_get_variable_int(data, efi_auth_var_get_guid(data), NULL,
+					   &db_size, NULL,  NULL);
+		if (ret == EFI_BUFFER_TOO_SMALL)
+			attr |= EFI_VARIABLE_APPEND_WRITE;
+	}
+
+	ret = efi_set_variable_int((u16 *)data, efi_auth_var_get_guid((u16 *)data),
+				   attr, size, buf, false);
+	if (ret != EFI_SUCCESS)
+		eficonfig_print_msg("ERROR! Failed to update signature database");
+
+out:
+	free(file_info.current_path);
+	free(buf);
+
+	/* return to the parent menu */
+	ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
+
+	return ret;
+}
+
+static struct eficonfig_item key_config_menu_items[] = {
+	{"Enroll New Key", eficonfig_process_enroll_key},
+	{"Quit", eficonfig_process_quit},
+};
+
+/**
+ * eficonfig_process_set_secure_boot_key() - display the key configuration menu
+ *
+ * @data:	pointer to the data for each entry
+ * Return:	status code
+ */
+static efi_status_t eficonfig_process_set_secure_boot_key(void *data)
+{
+	u32 i;
+	efi_status_t ret;
+	char header_str[32];
+	struct efimenu *efi_menu;
+
+	for (i = 0; i < ARRAY_SIZE(key_config_menu_items); i++)
+		key_config_menu_items[i].data = data;
+
+	snprintf(header_str, sizeof(header_str), "  ** Configure %ls **", (u16 *)data);
+
+	while (1) {
+		efi_menu = eficonfig_create_fixed_menu(key_config_menu_items,
+						       ARRAY_SIZE(key_config_menu_items));
+
+		ret = eficonfig_process_common(efi_menu, header_str);
+		eficonfig_destroy(efi_menu);
+
+		if (ret == EFI_ABORTED)
+			break;
+	}
+
+	/* return to the parent menu */
+	ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
+
+	return ret;
+}
+
+static const struct eficonfig_item secure_boot_menu_items[] = {
+	{"PK", eficonfig_process_set_secure_boot_key, u"PK"},
+	{"KEK", eficonfig_process_set_secure_boot_key, u"KEK"},
+	{"db", eficonfig_process_set_secure_boot_key, u"db"},
+	{"dbx", eficonfig_process_set_secure_boot_key, u"dbx"},
+	{"Quit", eficonfig_process_quit},
+};
+
+/**
+ * eficonfig_process_secure_boot_config() - display the key list menu
+ *
+ * @data:	pointer to the data for each entry
+ * Return:	status code
+ */
+efi_status_t eficonfig_process_secure_boot_config(void *data)
+{
+	efi_status_t ret;
+	struct efimenu *efi_menu;
+
+	while (1) {
+		char header_str[64];
+
+		snprintf(header_str, sizeof(header_str),
+			 "  ** UEFI Secure Boot Key Configuration (SecureBoot : %s) **",
+			 (efi_secure_boot_enabled() ? "ON" : "OFF"));
+
+		efi_menu = eficonfig_create_fixed_menu(secure_boot_menu_items,
+						       ARRAY_SIZE(secure_boot_menu_items));
+		if (!efi_menu) {
+			ret = EFI_OUT_OF_RESOURCES;
+			break;
+		}
+
+		ret = eficonfig_process_common(efi_menu, header_str);
+		eficonfig_destroy(efi_menu);
+
+		if (ret == EFI_ABORTED)
+			break;
+	}
+
+	/* return to the parent menu */
+	ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
+
+	return ret;
+}
diff --git a/include/efi_config.h b/include/efi_config.h
index 86bc801211..6db8e123f0 100644
--- a/include/efi_config.h
+++ b/include/efi_config.h
@@ -99,5 +99,10 @@ efi_status_t eficonfig_append_menu_entry(struct efimenu *efi_menu,
 					 char *title, eficonfig_entry_func func,
 					 void *data);
 efi_status_t eficonfig_append_quit_entry(struct efimenu *efi_menu);
+void *eficonfig_create_fixed_menu(const struct eficonfig_item *items, int count);
+
+#ifdef CONFIG_EFI_SECURE_BOOT
+efi_status_t eficonfig_process_secure_boot_config(void *data);
+#endif
 
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH v6 5/5] eficonfig: add "Show/Delete Signature Database" menu entry
  2022-10-26 10:43 [PATCH v6 0/5] eficonfig: add UEFI Secure Boot key maintenance interface Masahisa Kojima
                   ` (3 preceding siblings ...)
  2022-10-26 10:43 ` [PATCH v6 4/5] eficonfig: add UEFI Secure Boot Key enrollment interface Masahisa Kojima
@ 2022-10-26 10:43 ` Masahisa Kojima
  4 siblings, 0 replies; 17+ messages in thread
From: Masahisa Kojima @ 2022-10-26 10:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Simon Glass,
	Takahiro Akashi, Etienne Carriere, Masahisa Kojima

This commit adds the menu-driven interface to show and delete the
signature database.

EFI Signature Lists can contain the multiple signature
entries, this menu can delete the indivisual entry.

If the PK is enrolled and UEFI Secure Boot is in User Mode or
Deployed Mode,  user can not delete the existing signature lists
since the signature lists must be signed by KEK or PK but signing
information is not stored in the signature database.

To delete PK, user needs to enroll the new key with an empty
value and this new key must be signed with the old PK.

Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
---
Changes in v6:
- update comment

Changes in v2:
- integrate show and delete signature database menu
- add confirmation message before delete
- add function comment

 cmd/eficonfig_sbkey.c | 394 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 394 insertions(+)

diff --git a/cmd/eficonfig_sbkey.c b/cmd/eficonfig_sbkey.c
index e4a3573f1b..e14d5ac7f2 100644
--- a/cmd/eficonfig_sbkey.c
+++ b/cmd/eficonfig_sbkey.c
@@ -17,6 +17,14 @@
 #include <efi_variable.h>
 #include <crypto/pkcs7_parser.h>
 
+struct eficonfig_sig_data {
+	struct efi_signature_list *esl;
+	struct efi_signature_data *esd;
+	struct list_head list;
+	struct eficonfig_sig_data **selected;
+	u16 *varname;
+};
+
 enum efi_sbkey_signature_type {
 	SIG_TYPE_X509 = 0,
 	SIG_TYPE_HASH,
@@ -46,6 +54,32 @@ static const struct eficonfig_sigtype_to_str sigtype_to_str[] = {
 /*	{EFI_CERT_SHA512_GUID,		"SHA512",		SIG_TYPE_HASH}, */
 };
 
+/**
+ * eficonfig_console_wait_enter() - wait ENTER key press
+ *
+ * Return:	1 if ENTER key is pressed, 0 if user selects to quit
+ */
+static int eficonfig_console_wait_enter(void)
+{
+	int esc = 0;
+	enum bootmenu_key key = KEY_NONE;
+
+	puts(ANSI_CURSOR_HIDE);
+
+	while (1) {
+		bootmenu_loop(NULL, &key, &esc);
+
+		switch (key) {
+		case KEY_SELECT:
+			return 1;
+		case KEY_QUIT:
+			return 0;
+		default:
+			break;
+		}
+	}
+}
+
 /**
  * create_time_based_payload() - create payload for time based authenticate variable
  *
@@ -246,8 +280,368 @@ out:
 	return ret;
 }
 
+/**
+ * delete_selected_signature_data() - delete the signature data from signature list
+ *
+ * @db:		pointer to the signature database
+ * @db_size:	pointer to the signature database size
+ * @target:	pointer to the signature data to be deleted
+ * Return:	status code
+ */
+static void delete_selected_signature_data(void *db, efi_uintn_t *db_size,
+					   struct eficonfig_sig_data *target)
+{
+	u32 remain;
+	u8 *dest, *start, *end;
+	efi_uintn_t total_size, esd_size, size;
+	struct efi_signature_list *esl;
+	struct efi_signature_data *esd;
+
+	esl = db;
+	total_size = *db_size;
+	size = *db_size;
+	end = (u8 *)db + *db_size;
+	while (total_size > 0) {
+		esd = (struct efi_signature_data *)((u8 *)esl +
+		      sizeof(struct efi_signature_list) + esl->signature_header_size);
+		esd_size = esl->signature_list_size - sizeof(struct efi_signature_list) -
+			   esl->signature_header_size;
+		for (; esd_size > 0; esd_size -= esl->signature_size) {
+			if (esl == target->esl && esd == target->esd) {
+				remain = esl->signature_list_size -
+					 (sizeof(struct efi_signature_list) -
+					 esl->signature_header_size) -
+					 esl->signature_size;
+				if (remain > 0) {
+					/* only delete the single signature data */
+					esl->signature_list_size -= esl->signature_size;
+					size -= esl->signature_size;
+					dest = (u8 *)esd;
+					start = (u8 *)esd + esl->signature_size;
+				} else {
+					/* delete entire signature list */
+					dest = (u8 *)esl;
+					start = (u8 *)esl + esl->signature_list_size;
+					size -= esl->signature_list_size;
+				}
+				memmove(dest, start, (end - start));
+				goto out;
+			}
+			esd = (struct efi_signature_data *)((u8 *)esd + esl->signature_size);
+		}
+		total_size -= esl->signature_list_size;
+		esl = (struct efi_signature_list *)((u8 *)esl + esl->signature_list_size);
+	}
+out:
+	*db_size = size;
+}
+
+/**
+ * display_sigdata_info() - display signature data information
+ *
+ * @sg:		pointer to the internal signature data structure
+ * Return:	status code
+ */
+static void display_sigdata_info(struct eficonfig_sig_data *sg)
+{
+	u32 i;
+
+	puts(ANSI_CURSOR_HIDE);
+	puts(ANSI_CLEAR_CONSOLE);
+	printf(ANSI_CURSOR_POSITION, 1, 1);
+
+	*sg->selected = sg;
+	printf("\n  ** Show/Delete Signature Database (%ls) **\n\n"
+	       "    Owner GUID:\n"
+	       "      %pUL\n",
+	       sg->varname, sg->esd->signature_owner.b);
+
+	for (i = 0; i < ARRAY_SIZE(sigtype_to_str); i++) {
+		if (!guidcmp(&sg->esl->signature_type, &sigtype_to_str[i].sig_type)) {
+			printf("    Signature Type:\n"
+			       "      %s\n", sigtype_to_str[i].str);
+
+			switch (sigtype_to_str[i].type) {
+			case SIG_TYPE_X509:
+			{
+				struct x509_certificate *cert_tmp;
+
+				cert_tmp = x509_cert_parse(sg->esd->signature_data,
+							   sg->esl->signature_size);
+				printf("    Subject:\n"
+				       "      %s\n"
+				       "    Issuer:\n"
+				       "      %s\n",
+				       cert_tmp->subject, cert_tmp->issuer);
+				break;
+			}
+			case SIG_TYPE_CRL:
+			{
+				u32 hash_size = sg->esl->signature_size - sizeof(efi_guid_t) -
+						sizeof(struct efi_time);
+				struct efi_time *time =
+					(struct efi_time *)((u8 *)sg->esd->signature_data +
+					hash_size);
+
+				printf("    ToBeSignedHash:\n");
+				print_hex_dump("      ", DUMP_PREFIX_NONE, 16, 1,
+					       sg->esd->signature_data, hash_size, false);
+				printf("    TimeOfRevocation:\n"
+				       "      %d-%d-%d %02d:%02d:%02d\n",
+				       time->year, time->month, time->day,
+				       time->hour, time->minute, time->second);
+				break;
+			}
+			case SIG_TYPE_HASH:
+			{
+				u32 hash_size = sg->esl->signature_size - sizeof(efi_guid_t);
+
+				printf("    Hash:\n");
+				print_hex_dump("      ", DUMP_PREFIX_NONE, 16, 1,
+					       sg->esd->signature_data, hash_size, false);
+				break;
+			}
+			default:
+				eficonfig_print_msg("ERROR! Unsupported format.");
+				break;
+			}
+		}
+	}
+}
+
+/**
+ * eficonfig_process_sigdata_delete() - delete signature data
+ *
+ * @data:	pointer to the data for each entry
+ * Return:	status code
+ */
+static efi_status_t eficonfig_process_sigdata_delete(void *data)
+{
+	int delete;
+	efi_status_t ret;
+	efi_uintn_t size;
+	u8 setup_mode = 0;
+	u8 audit_mode = 0;
+
+	struct eficonfig_sig_data *sg = data;
+
+	display_sigdata_info(sg);
+
+	if (!u16_strcmp(sg->varname, u"PK")) {
+		while (tstc())
+			getchar();
+
+		printf("\n\n  Can not delete PK, Press any key to continue");
+		getchar();
+		return EFI_NOT_READY;
+	}
+
+	printf("\n\n  Press ENTER to delete, ESC/CTRL+C to quit");
+	delete = eficonfig_console_wait_enter();
+	if (!delete)
+		return EFI_NOT_READY;
+
+	size = sizeof(setup_mode);
+	ret = efi_get_variable_int(u"SetupMode", &efi_global_variable_guid,
+				   NULL, &size, &setup_mode, NULL);
+	size = sizeof(audit_mode);
+	ret = efi_get_variable_int(u"AuditMode", &efi_global_variable_guid,
+				   NULL, &size, &audit_mode, NULL);
+
+	if (!setup_mode && !audit_mode) {
+		eficonfig_print_msg("Not in the SetupMode or AuditMode, can not delete.");
+		return EFI_NOT_READY;
+	}
+
+	return EFI_SUCCESS;
+}
+
+/**
+ * prepare_signature_db_list() - create the signature data menu entry
+ *
+ * @efimenu:	pointer to the efimenu structure
+ * @varname:	pointer to the variable name
+ * @db:		pointer to the variable raw data
+ * @db_size:	variable data size
+ * @func:	callback of each entry
+ * @selected:	pointer to selected signature data
+ * Return:	status code
+ */
+static efi_status_t prepare_signature_db_list(struct efimenu *efi_menu, void *varname,
+					      void *db, efi_uintn_t db_size,
+					      eficonfig_entry_func func,
+					      struct eficonfig_sig_data **selected)
+{
+	u32 num = 0;
+	efi_uintn_t size;
+	struct eficonfig_sig_data *sg;
+	struct efi_signature_list *esl;
+	struct efi_signature_data *esd;
+	efi_status_t ret = EFI_SUCCESS;
+
+	INIT_LIST_HEAD(&efi_menu->list);
+
+	esl = db;
+	size = db_size;
+	while (size > 0) {
+		u32 remain;
+
+		esd = (struct efi_signature_data *)((u8 *)esl +
+						    (sizeof(struct efi_signature_list) +
+						    esl->signature_header_size));
+		remain = esl->signature_list_size - sizeof(struct efi_signature_list) -
+			 esl->signature_header_size;
+		for (; remain > 0; remain -= esl->signature_size) {
+			char buf[40];
+			char *title;
+
+			if (num >= EFICONFIG_ENTRY_NUM_MAX - 1) {
+				ret = EFI_OUT_OF_RESOURCES;
+				goto out;
+			}
+
+			sg = calloc(1, sizeof(struct eficonfig_sig_data));
+			if (!sg) {
+				ret = EFI_OUT_OF_RESOURCES;
+				goto err;
+			}
+
+			snprintf(buf, sizeof(buf), "%pUL", &esd->signature_owner);
+			title = calloc(1, (strlen(buf) + 1));
+			if (!title) {
+				free(sg);
+				ret = EFI_OUT_OF_RESOURCES;
+				goto err;
+			}
+			strlcpy(title, buf, strlen(buf) + 1);
+
+			sg->esl = esl;
+			sg->esd = esd;
+			sg->selected = selected;
+			sg->varname = varname;
+			ret = eficonfig_append_menu_entry(efi_menu, title, func, sg);
+			if (ret != EFI_SUCCESS) {
+				free(sg);
+				free(title);
+				goto err;
+			}
+			esd = (struct efi_signature_data *)((u8 *)esd + esl->signature_size);
+			num++;
+		}
+
+		size -= esl->signature_list_size;
+		esl = (struct efi_signature_list *)((u8 *)esl + esl->signature_list_size);
+	}
+out:
+	ret = eficonfig_append_quit_entry(efi_menu);
+err:
+	return ret;
+}
+
+/**
+ * process_show_signature_db() - display the signature data list
+ *
+ * @data:	pointer to the data for each entry
+ * Return:	status code
+ */
+static efi_status_t process_show_signature_db(void *varname)
+{
+	char buf[50];
+	efi_status_t ret;
+	efi_uintn_t db_size;
+	void *db, *new_db = NULL;
+	struct efimenu *efi_menu;
+	struct list_head *pos, *n;
+	struct eficonfig_entry *entry;
+	struct eficonfig_sig_data *selected;
+
+	db = efi_get_var(varname, efi_auth_var_get_guid(varname), &db_size);
+	if (!db) {
+		eficonfig_print_msg("There is no entry in the signature database.");
+		return EFI_NOT_FOUND;
+	}
+
+	efi_menu = calloc(1, sizeof(struct efimenu));
+	if (!efi_menu) {
+		free(db);
+		return EFI_OUT_OF_RESOURCES;
+	}
+
+	ret = prepare_signature_db_list(efi_menu, varname, db, db_size,
+					eficonfig_process_sigdata_delete, &selected);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	snprintf(buf, sizeof(buf), "  ** Show/Delete Signature Database (%ls) **",
+		 (u16 *)varname);
+	ret = eficonfig_process_common(efi_menu, buf);
+	if (ret == EFI_SUCCESS) {
+		u32 attr;
+		int delete;
+
+		printf(ANSI_CURSOR_HIDE
+		       "\n\n   Are you sure you want to delete this item?\n\n"
+		       "  Press ENTER to delete, ESC/CTRL+C to quit");
+		delete = eficonfig_console_wait_enter();
+		if (!delete)
+			goto out;
+
+		delete_selected_signature_data(db, &db_size, selected);
+
+		ret = create_time_based_payload(db, &new_db, &db_size);
+		if (ret != EFI_SUCCESS) {
+			eficonfig_print_msg("ERROR! Failed to create payload with timestamp.");
+			goto out;
+		}
+
+		attr = EFI_VARIABLE_NON_VOLATILE |
+		       EFI_VARIABLE_BOOTSERVICE_ACCESS |
+		       EFI_VARIABLE_RUNTIME_ACCESS |
+		       EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+		ret = efi_set_variable_int((u16 *)varname, efi_auth_var_get_guid((u16 *)varname),
+					   attr, db_size, new_db, false);
+		if (ret != EFI_SUCCESS) {
+			eficonfig_print_msg("ERROR! Failed to delete signature database");
+			goto out;
+		}
+	}
+out:
+	list_for_each_safe(pos, n, &efi_menu->list) {
+		entry = list_entry(pos, struct eficonfig_entry, list);
+		free(entry->data);
+	}
+	eficonfig_destroy(efi_menu);
+	free(new_db);
+	free(db);
+
+	return ret;
+}
+
+/**
+ * eficonfig_process_show_signature_db() - display the key configuration menu
+ *
+ * @data:	pointer to the data for each entry
+ * Return:	status code
+ */
+static efi_status_t eficonfig_process_show_signature_db(void *data)
+{
+	efi_status_t ret;
+
+	while (1) {
+		ret = process_show_signature_db(data);
+		if (ret != EFI_SUCCESS && ret != EFI_NOT_READY)
+			break;
+	}
+
+	/* return to the parent menu */
+	ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
+
+	return ret;
+}
+
 static struct eficonfig_item key_config_menu_items[] = {
 	{"Enroll New Key", eficonfig_process_enroll_key},
+	{"Show/Delete Signature Database", eficonfig_process_show_signature_db},
 	{"Quit", eficonfig_process_quit},
 };
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH v6 1/5] eficonfig: refactor eficonfig_select_file_handler()
  2022-10-26 10:43 ` [PATCH v6 1/5] eficonfig: refactor eficonfig_select_file_handler() Masahisa Kojima
@ 2022-11-04 15:12   ` Ilias Apalodimas
  2022-11-07  2:31     ` Masahisa Kojima
  0 siblings, 1 reply; 17+ messages in thread
From: Ilias Apalodimas @ 2022-11-04 15:12 UTC (permalink / raw)
  To: Masahisa Kojima
  Cc: u-boot, Heinrich Schuchardt, Simon Glass, Takahiro Akashi,
	Etienne Carriere

Hi Kojima-san

I think there's some information missing from the commit message. 

On Wed, Oct 26, 2022 at 07:43:41PM +0900, Masahisa Kojima wrote:
> eficonfig_select_file_handler() is commonly used to select the
> file.
> eficonfig_display_select_file_option() intends to add the
> additional menu mainly to clear the selected file information.
'eficonfig_display_select_file_option() adds an additional menu to clear
the selected file' sounds better?

> eficonfig_display_select_file_option() is not necessary for the
> file selection process, so it should be outside of
> eficonfig_select_file_handler().

In a followup patch I think we should rename eficonfig_select_file().  It's
a bit confusing to have both eficonfig_select_file_handler() and
eficonfig_select_file() and iirc the latter creates the menu for the file
selection. 

> 
> Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> ---
> No change since v2
> 
> newly created in v2
> 
>  cmd/eficonfig.c                                | 13 +++++--------
>  test/py/tests/test_eficonfig/test_eficonfig.py |  1 +
>  2 files changed, 6 insertions(+), 8 deletions(-)
> 
> diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
> index 2595dd9563..f6a99bd01a 100644
> --- a/cmd/eficonfig.c
> +++ b/cmd/eficonfig.c
> @@ -968,7 +968,7 @@ efi_status_t eficonfig_process_clear_file_selection(void *data)
>  }
>  
>  static struct eficonfig_item select_file_menu_items[] = {
> -	{"Select File", eficonfig_process_select_file},

eficonfig_process_select_file() is not used anywhere anymore now.  We need
to get rid of the function declaration

> +	{"Select File", eficonfig_select_file_handler},

This is a different change right? It effectively allows you to choose
between files. 
Can we explain this change as well on the commit message?

>  	{"Clear", eficonfig_process_clear_file_selection},
>  	{"Quit", eficonfig_process_quit},
>  };
> @@ -980,12 +980,13 @@ static struct eficonfig_item select_file_menu_items[] = {
>   * @file_info:	pointer to the file information structure
>   * Return:	status code
>   */
> -efi_status_t eficonfig_display_select_file_option(struct eficonfig_select_file_info *file_info)
> +efi_status_t eficonfig_display_select_file_option(void *data)
>  {
>  	efi_status_t ret;
>  	struct efimenu *efi_menu;
>  
> -	select_file_menu_items[1].data = file_info;
> +	select_file_menu_items[0].data = data;
> +	select_file_menu_items[1].data = data;
>  	efi_menu = eficonfig_create_fixed_menu(select_file_menu_items,
>  					       ARRAY_SIZE(select_file_menu_items));
>  	if (!efi_menu)
> @@ -1016,10 +1017,6 @@ efi_status_t eficonfig_select_file_handler(void *data)
>  	struct eficonfig_select_file_info *tmp = NULL;
>  	struct eficonfig_select_file_info *file_info = data;
>  
> -	ret = eficonfig_display_select_file_option(file_info);
> -	if (ret != EFI_SUCCESS)
> -		return ret;
> -
>  	tmp = calloc(1, sizeof(struct eficonfig_select_file_info));
>  	if (!tmp)
>  		return EFI_OUT_OF_RESOURCES;
> @@ -1284,7 +1281,7 @@ static efi_status_t prepare_file_selection_entry(struct efimenu *efi_menu, char
>  	utf8_utf16_strcpy(&p, devname);
>  	u16_strlcat(file_name, file_info->current_path, len);
>  	ret = create_boot_option_entry(efi_menu, title, file_name,
> -				       eficonfig_select_file_handler, file_info);
> +				       eficonfig_display_select_file_option, file_info);
>  out:
>  	free(devname);
>  	free(file_name);
> diff --git a/test/py/tests/test_eficonfig/test_eficonfig.py b/test/py/tests/test_eficonfig/test_eficonfig.py
> index 99606d9c4b..102bfd7541 100644
> --- a/test/py/tests/test_eficonfig/test_eficonfig.py
> +++ b/test/py/tests/test_eficonfig/test_eficonfig.py
> @@ -349,6 +349,7 @@ def test_efi_eficonfig(u_boot_console, efi_eficonfig_data):
>          press_up_down_enter_and_wait(0, 1, True, 'Quit')
>          press_up_down_enter_and_wait(0, 0, True, 'No block device found!')
>          press_escape_key(False)
> +        press_escape_key(False)
>          check_current_is_maintenance_menu()
>          # Return to U-Boot console
>          press_escape_key(True)
> -- 
> 2.17.1
> 

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v6 2/5] eficonfig: expose append entry function
  2022-10-26 10:43 ` [PATCH v6 2/5] eficonfig: expose append entry function Masahisa Kojima
@ 2022-11-04 15:16   ` Ilias Apalodimas
  2022-11-07  2:32     ` Masahisa Kojima
  0 siblings, 1 reply; 17+ messages in thread
From: Ilias Apalodimas @ 2022-11-04 15:16 UTC (permalink / raw)
  To: Masahisa Kojima
  Cc: u-boot, Heinrich Schuchardt, Simon Glass, Takahiro Akashi,
	Etienne Carriere

Hi Kojima-san

On Wed, Oct 26, 2022 at 07:43:42PM +0900, Masahisa Kojima wrote:
> This commit exposes the eficonfig menu entry append function.

Can we update the description to something we could look up in the future?
e.g
'Following commits are adding support for variable management via the
eficonfig menu.  Those functions needs to use append_entry and
append_quit_entry, so move them out of their static declarations'

> 
> Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> ---
> No change since v2
> 
> newly created in v2
> 
>  cmd/eficonfig.c      | 32 +++++++++++++++++---------------
>  include/efi_config.h |  5 +++++
>  2 files changed, 22 insertions(+), 15 deletions(-)
> 
> diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
> index f6a99bd01a..0cb0770ac3 100644
> --- a/cmd/eficonfig.c
> +++ b/cmd/eficonfig.c
> @@ -263,7 +263,7 @@ efi_status_t eficonfig_process_quit(void *data)
>  }
>  
>  /**
> - * append_entry() - append menu item
> + * eficonfig_append_menu_entry() - append menu item
>   *
>   * @efi_menu:	pointer to the efimenu structure
>   * @title:	pointer to the entry title
> @@ -271,8 +271,9 @@ efi_status_t eficonfig_process_quit(void *data)
>   * @data:	pointer to the data to be passed to each entry callback
>   * Return:	status code
>   */
> -static efi_status_t append_entry(struct efimenu *efi_menu,
> -				 char *title, eficonfig_entry_func func, void *data)
> +efi_status_t eficonfig_append_menu_entry(struct efimenu *efi_menu,
> +					 char *title, eficonfig_entry_func func,
> +					 void *data)
>  {
>  	struct eficonfig_entry *entry;
>  
> @@ -295,12 +296,12 @@ static efi_status_t append_entry(struct efimenu *efi_menu,
>  }
>  
>  /**
> - * append_quit_entry() - append quit entry
> + * eficonfig_append_quit_entry() - append quit entry
>   *
>   * @efi_menu:	pointer to the efimenu structure
>   * Return:	status code
>   */
> -static efi_status_t append_quit_entry(struct efimenu *efi_menu)
> +efi_status_t eficonfig_append_quit_entry(struct efimenu *efi_menu)
>  {
>  	char *title;
>  	efi_status_t ret;
> @@ -309,7 +310,7 @@ static efi_status_t append_quit_entry(struct efimenu *efi_menu)
>  	if (!title)
>  		return EFI_OUT_OF_RESOURCES;
>  
> -	ret = append_entry(efi_menu, title, eficonfig_process_quit, NULL);
> +	ret = eficonfig_append_menu_entry(efi_menu, title, eficonfig_process_quit, NULL);
>  	if (ret != EFI_SUCCESS)
>  		free(title);
>  
> @@ -341,7 +342,7 @@ void *eficonfig_create_fixed_menu(const struct eficonfig_item *items, int count)
>  		if (!title)
>  			goto out;
>  
> -		ret = append_entry(efi_menu, title, iter->func, iter->data);
> +		ret = eficonfig_append_menu_entry(efi_menu, title, iter->func, iter->data);
>  		if (ret != EFI_SUCCESS) {
>  			free(title);
>  			goto out;
> @@ -634,14 +635,15 @@ static efi_status_t eficonfig_select_volume(struct eficonfig_select_file_info *f
>  		info->v = v;
>  		info->dp = device_path;
>  		info->file_info = file_info;
> -		ret = append_entry(efi_menu, devname, eficonfig_volume_selected, info);
> +		ret = eficonfig_append_menu_entry(efi_menu, devname, eficonfig_volume_selected,
> +						  info);
>  		if (ret != EFI_SUCCESS) {
>  			free(info);
>  			goto out;
>  		}
>  	}
>  
> -	ret = append_quit_entry(efi_menu);
> +	ret = eficonfig_append_quit_entry(efi_menu);
>  	if (ret != EFI_SUCCESS)
>  		goto out;
>  
> @@ -745,8 +747,8 @@ eficonfig_create_file_entry(struct efimenu *efi_menu, u32 count,
>  	      (int (*)(const void *, const void *))sort_file);
>  
>  	for (i = 0; i < entry_num; i++) {
> -		ret = append_entry(efi_menu, tmp_infos[i]->file_name,
> -				   eficonfig_file_selected, tmp_infos[i]);
> +		ret = eficonfig_append_menu_entry(efi_menu, tmp_infos[i]->file_name,
> +						  eficonfig_file_selected, tmp_infos[i]);
>  		if (ret != EFI_SUCCESS)
>  			goto out;
>  	}
> @@ -815,7 +817,7 @@ static efi_status_t eficonfig_select_file(struct eficonfig_select_file_info *fil
>  		if (ret != EFI_SUCCESS)
>  			goto err;
>  
> -		ret = append_quit_entry(efi_menu);
> +		ret = eficonfig_append_quit_entry(efi_menu);
>  		if (ret != EFI_SUCCESS)
>  			goto err;
>  
> @@ -1218,7 +1220,7 @@ static efi_status_t create_boot_option_entry(struct efimenu *efi_menu, char *tit
>  		utf16_utf8_strcpy(&p, val);
>  	}
>  
> -	return append_entry(efi_menu, buf, func, data);
> +	return eficonfig_append_menu_entry(efi_menu, buf, func, data);
>  }
>  
>  /**
> @@ -1677,7 +1679,7 @@ static efi_status_t eficonfig_add_boot_selection_entry(struct efimenu *efi_menu,
>  	utf16_utf8_strcpy(&p, lo.label);
>  	info->boot_index = boot_index;
>  	info->selected = selected;
> -	ret = append_entry(efi_menu, buf, eficonfig_process_boot_selected, info);
> +	ret = eficonfig_append_menu_entry(efi_menu, buf, eficonfig_process_boot_selected, info);
>  	if (ret != EFI_SUCCESS) {
>  		free(load_option);
>  		free(info);
> @@ -1736,7 +1738,7 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected)
>  			break;
>  	}
>  
> -	ret = append_quit_entry(efi_menu);
> +	ret = eficonfig_append_quit_entry(efi_menu);
>  	if (ret != EFI_SUCCESS)
>  		goto out;
>  
> diff --git a/include/efi_config.h b/include/efi_config.h
> index 098cac2115..86bc801211 100644
> --- a/include/efi_config.h
> +++ b/include/efi_config.h
> @@ -95,4 +95,9 @@ efi_status_t eficonfig_get_unused_bootoption(u16 *buf,
>  efi_status_t eficonfig_append_bootorder(u16 index);
>  efi_status_t eficonfig_generate_media_device_boot_option(void);
>  
> +efi_status_t eficonfig_append_menu_entry(struct efimenu *efi_menu,
> +					 char *title, eficonfig_entry_func func,
> +					 void *data);
> +efi_status_t eficonfig_append_quit_entry(struct efimenu *efi_menu);
> +
>  #endif
> -- 
> 2.17.1
> 

Other than that
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v6 4/5] eficonfig: add UEFI Secure Boot Key enrollment interface
  2022-10-26 10:43 ` [PATCH v6 4/5] eficonfig: add UEFI Secure Boot Key enrollment interface Masahisa Kojima
@ 2022-11-04 21:46   ` Ilias Apalodimas
  2022-11-07  3:12     ` Masahisa Kojima
  0 siblings, 1 reply; 17+ messages in thread
From: Ilias Apalodimas @ 2022-11-04 21:46 UTC (permalink / raw)
  To: Masahisa Kojima
  Cc: u-boot, Heinrich Schuchardt, Simon Glass, Takahiro Akashi,
	Etienne Carriere, Roger Knecht, Chris Morgan, Stefan Roese,
	Ovidiu Panait, Ashok Reddy Soma

Hi Kojima-san

On Wed, Oct 26, 2022 at 07:43:44PM +0900, Masahisa Kojima wrote:
> This commit adds the menu-driven UEFI Secure Boot Key
> enrollment interface. User can enroll the PK, KEK, db
> and dbx by selecting EFI Signature Lists file.
> After the PK is enrolled, UEFI Secure Boot is enabled and
> EFI Signature Lists file must be signed by KEK or PK.
> 
> Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> ---
> Changes in v6:
> - use efi_secure_boot_enabled()
> - replace with WIN_CERT_REVISION_2_0 from pe.h
> - call efi_build_signature_store() to check the valid EFI Signature List
> - update comment
> 
> Changes in v4:
> - add CONFIG_EFI_MM_COMM_TEE dependency
> - fix error handling
> 
> Changes in v3:
> - fix error handling
> 
> Changes in v2:
> - allow to enroll .esl file
> - fix typos
> - add function comments
> 
>  cmd/Makefile          |   5 +
>  cmd/eficonfig.c       |   3 +
>  cmd/eficonfig_sbkey.c | 333 ++++++++++++++++++++++++++++++++++++++++++
>  include/efi_config.h  |   5 +
>  4 files changed, 346 insertions(+)
>  create mode 100644 cmd/eficonfig_sbkey.c
> 
> diff --git a/cmd/Makefile b/cmd/Makefile
> index c95e09d058..e43ef22e98 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -66,6 +66,11 @@ obj-$(CONFIG_CMD_EEPROM) += eeprom.o
>  obj-$(CONFIG_EFI) += efi.o
>  obj-$(CONFIG_CMD_EFIDEBUG) += efidebug.o
>  obj-$(CONFIG_CMD_EFICONFIG) += eficonfig.o
> +ifdef CONFIG_CMD_EFICONFIG
> +ifdef CONFIG_EFI_MM_COMM_TEE
> +obj-$(CONFIG_EFI_SECURE_BOOT) += eficonfig_sbkey.o
> +endif
> +endif
>  obj-$(CONFIG_CMD_ELF) += elf.o
>  obj-$(CONFIG_CMD_EROFS) += erofs.o
>  obj-$(CONFIG_HUSH_PARSER) += exit.o
> diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
> index c765b795d0..0b643a046c 100644
> --- a/cmd/eficonfig.c
> +++ b/cmd/eficonfig.c
> @@ -2447,6 +2447,9 @@ static const struct eficonfig_item maintenance_menu_items[] = {
>  	{"Edit Boot Option", eficonfig_process_edit_boot_option},
>  	{"Change Boot Order", eficonfig_process_change_boot_order},
>  	{"Delete Boot Option", eficonfig_process_delete_boot_option},
> +#if (CONFIG_IS_ENABLED(EFI_SECURE_BOOT) && CONFIG_IS_ENABLED(EFI_MM_COMM_TEE))
> +	{"Secure Boot Configuration", eficonfig_process_secure_boot_config},
> +#endif
>  	{"Quit", eficonfig_process_quit},
>  };
>  
> diff --git a/cmd/eficonfig_sbkey.c b/cmd/eficonfig_sbkey.c
> new file mode 100644
> index 0000000000..e4a3573f1b
> --- /dev/null
> +++ b/cmd/eficonfig_sbkey.c
> @@ -0,0 +1,333 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + *  Menu-driven UEFI Secure Boot Key Maintenance
> + *
> + *  Copyright (c) 2022 Masahisa Kojima, Linaro Limited
> + */
> +
> +#include <ansi.h>
> +#include <common.h>
> +#include <charset.h>
> +#include <hexdump.h>
> +#include <log.h>
> +#include <malloc.h>
> +#include <menu.h>
> +#include <efi_loader.h>
> +#include <efi_config.h>
> +#include <efi_variable.h>
> +#include <crypto/pkcs7_parser.h>
> +
> +enum efi_sbkey_signature_type {
> +	SIG_TYPE_X509 = 0,
> +	SIG_TYPE_HASH,
> +	SIG_TYPE_CRL,
> +	SIG_TYPE_RSA2048,
> +};
> +
> +struct eficonfig_sigtype_to_str {
> +	efi_guid_t sig_type;
> +	char *str;
> +	enum efi_sbkey_signature_type type;
> +};
> +
> +static const struct eficonfig_sigtype_to_str sigtype_to_str[] = {
> +	{EFI_CERT_X509_GUID,		"X509",			SIG_TYPE_X509},
> +	{EFI_CERT_SHA256_GUID,		"SHA256",		SIG_TYPE_HASH},
> +	{EFI_CERT_X509_SHA256_GUID,	"X509_SHA256 CRL",	SIG_TYPE_CRL},
> +	{EFI_CERT_X509_SHA384_GUID,	"X509_SHA384 CRL",	SIG_TYPE_CRL},
> +	{EFI_CERT_X509_SHA512_GUID,	"X509_SHA512 CRL",	SIG_TYPE_CRL},
> +	/* U-Boot does not support the following signature types */
> +/*	{EFI_CERT_RSA2048_GUID,		"RSA2048",		SIG_TYPE_RSA2048}, */
> +/*	{EFI_CERT_RSA2048_SHA256_GUID,	"RSA2048_SHA256",	SIG_TYPE_RSA2048}, */
> +/*	{EFI_CERT_SHA1_GUID,		"SHA1",			SIG_TYPE_HASH}, */
> +/*	{EFI_CERT_RSA2048_SHA_GUID,	"RSA2048_SHA",		SIG_TYPE_RSA2048 }, */
> +/*	{EFI_CERT_SHA224_GUID,		"SHA224",		SIG_TYPE_HASH}, */
> +/*	{EFI_CERT_SHA384_GUID,		"SHA384",		SIG_TYPE_HASH}, */
> +/*	{EFI_CERT_SHA512_GUID,		"SHA512",		SIG_TYPE_HASH}, */
> +};
> +
> +/**
> + * create_time_based_payload() - create payload for time based authenticate variable
> + *
> + * @db:		pointer to the original signature database
> + * @new_db:	pointer to the authenticated variable payload
> + * @size:	pointer to payload size
> + * Return:	status code
> + */
> +static efi_status_t create_time_based_payload(void *db, void **new_db, efi_uintn_t *size)
> +{
> +	efi_status_t ret;
> +	struct efi_time time;
> +	efi_uintn_t total_size;
> +	struct efi_variable_authentication_2 *auth;
> +
> +	*new_db = NULL;
> +
> +	/*
> +	 * SetVariable() call with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
> +	 * attribute requires EFI_VARIABLE_AUTHENTICATED_2 descriptor, prepare it
> +	 * without certificate data in it.
> +	 */
> +	total_size = sizeof(struct efi_variable_authentication_2) + *size;
> +
> +	auth = calloc(1, total_size);
> +	if (!auth)
> +		return EFI_OUT_OF_RESOURCES;
> +
> +	ret = EFI_CALL((*efi_runtime_services.get_time)(&time, NULL));
> +	if (ret != EFI_SUCCESS) {
> +		free(auth);
> +		return EFI_OUT_OF_RESOURCES;
> +	}
> +	time.pad1 = 0;
> +	time.nanosecond = 0;
> +	time.timezone = 0;
> +	time.daylight = 0;
> +	time.pad2 = 0;

Can't we do struct efi_time time = {0}?
Unless you explicitly need daylight to be set to zero

> +	memcpy(&auth->time_stamp, &time, sizeof(time));
> +	auth->auth_info.hdr.dwLength = sizeof(struct win_certificate_uefi_guid);
> +	auth->auth_info.hdr.wRevision = WIN_CERT_REVISION_2_0;
> +	auth->auth_info.hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
> +	guidcpy(&auth->auth_info.cert_type, &efi_guid_cert_type_pkcs7);
> +	if (db)
> +		memcpy((u8 *)auth + sizeof(struct efi_variable_authentication_2), db, *size);
> +
> +	*new_db = auth;
> +	*size = total_size;
> +
> +	return EFI_SUCCESS;
> +}
> +
> +/**
> + * file_have_auth_header() - check file has EFI_VARIABLE_AUTHENTICATION_2 header
> + * @buf:	pointer to file
> + * @size:	file size
> + * Return:	true if file has auth header, false otherwise
> + */
> +static bool file_have_auth_header(void *buf, efi_uintn_t size)
> +{
> +	struct efi_variable_authentication_2 *auth = buf;
> +
> +	if (auth->auth_info.hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID)
> +		return false;
> +
> +	if (guidcmp(&auth->auth_info.cert_type, &efi_guid_cert_type_pkcs7))
> +		return false;
> +
> +	return true;
> +}
> +
> +/**
> + * eficonfig_process_enroll_key() - enroll key into signature database
> + *
> + * @data:	pointer to the data for each entry
> + * Return:	status code
> + */
> +static efi_status_t eficonfig_process_enroll_key(void *data)
> +{
> +	u32 attr;
> +	char *buf = NULL;
> +	efi_uintn_t size;
> +	efi_status_t ret;
> +	void *new_db = NULL;
> +	struct efi_file_handle *f;
> +	struct efi_file_handle *root;
> +	struct eficonfig_select_file_info file_info;
> +
> +	file_info.current_path = calloc(1, EFICONFIG_FILE_PATH_BUF_SIZE);
> +	if (!file_info.current_path) {
> +		ret = EFI_OUT_OF_RESOURCES;
> +		goto out;
> +	}
> +
> +	ret = eficonfig_select_file_handler(&file_info);
> +	if (ret != EFI_SUCCESS)
> +		goto out;
> +
> +	ret = efi_open_volume_int(file_info.current_volume, &root);
> +	if (ret != EFI_SUCCESS)
> +		goto out;
> +
> +	ret = efi_file_open_int(root, &f, file_info.current_path, EFI_FILE_MODE_READ, 0);
> +	if (ret != EFI_SUCCESS)
> +		goto out;
> +
> +	size = 0;
> +	ret = EFI_CALL(f->getinfo(f, &efi_file_info_guid, &size, NULL));
> +	if (ret != EFI_BUFFER_TOO_SMALL)
> +		goto out;
> +
> +	buf = calloc(1, size);
> +	if (!buf) {
> +		ret = EFI_OUT_OF_RESOURCES;
> +		goto out;
> +	}
> +	ret = EFI_CALL(f->getinfo(f, &efi_file_info_guid, &size, buf));
> +	if (ret != EFI_SUCCESS)
> +		goto out;
> +
> +	size = ((struct efi_file_info *)buf)->file_size;
> +	free(buf);

You can replace most of this code with efi_file_size()

> +
> +	buf = calloc(1, size);
> +	if (!buf) {
> +		ret = EFI_OUT_OF_RESOURCES;
> +		goto out;
> +	}
> +
> +	ret = efi_file_read_int(f, &size, buf);
> +	if (ret != EFI_SUCCESS) {
> +		eficonfig_print_msg("ERROR! Failed to read file.");
> +		goto out;
> +	}
> +	if (size == 0) {
> +		eficonfig_print_msg("ERROR! File is empty.");
> +		goto out;
> +	}
> +
> +	if (!file_have_auth_header(buf, size)) {

Can you explain why we need this?  I would expect the user to prepare an
.esl file with ./tools/efivar.py 

> +		struct efi_signature_store *sigstore;
> +		char *tmp_buf;
> +
> +		/* Check if the file is valid EFI Signature List(s) */
> +		tmp_buf = calloc(1, size);
> +		if (!tmp_buf) {
> +			ret = EFI_OUT_OF_RESOURCES;
> +			goto out;
> +		}
> +		memcpy(tmp_buf, buf, size);
> +		/* tmp_buf is freed in efi_build_signature_store() */
> +		sigstore = efi_build_signature_store(tmp_buf, size);
> +		if (!sigstore) {
> +			eficonfig_print_msg("ERROR! Invalid file format.");
> +			ret = EFI_INVALID_PARAMETER;
> +			goto out;
> +		}
> +		efi_sigstore_free(sigstore);
> +
> +		ret = create_time_based_payload(buf, &new_db, &size);
> +		if (ret != EFI_SUCCESS) {
> +			eficonfig_print_msg("ERROR! Failed to create payload with timestamp.");
> +			goto out;
> +		}
> +
> +		free(buf);
> +		buf = new_db;
> +	}
> +
> +	attr = EFI_VARIABLE_NON_VOLATILE |
> +	       EFI_VARIABLE_BOOTSERVICE_ACCESS |
> +	       EFI_VARIABLE_RUNTIME_ACCESS |
> +	       EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
> +
[...]

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v6 3/5] eficonfig: refactor change boot order implementation
  2022-10-26 10:43 ` [PATCH v6 3/5] eficonfig: refactor change boot order implementation Masahisa Kojima
@ 2022-11-04 22:08   ` Ilias Apalodimas
  2022-11-07  3:18     ` Masahisa Kojima
  0 siblings, 1 reply; 17+ messages in thread
From: Ilias Apalodimas @ 2022-11-04 22:08 UTC (permalink / raw)
  To: Masahisa Kojima
  Cc: u-boot, Heinrich Schuchardt, Simon Glass, Takahiro Akashi,
	Etienne Carriere

Hi Kojima-san

On Wed, Oct 26, 2022 at 07:43:43PM +0900, Masahisa Kojima wrote:
> This commit refactors change boot order implementation
> to use 'eficonfig_entry' structure.

Please add an explanation on why we are doing this, instead of what the
patch is doing. I am assuming it cleans up some code and allows us to reuse 
eficonfig_entry since ->data is now pointing to an
eficonfig_boot_order_data struct?

> 
> Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> ---
> No update since v5
> 
> Changes in v5:
> - remove direct access mode
> 
> newly created in v4
> 
>  cmd/eficonfig.c | 129 +++++++++++++++++++++++++-----------------------
>  1 file changed, 67 insertions(+), 62 deletions(-)
> 
>  				list_del(&tmp->list);

[...]

> @@ -1891,11 +1884,11 @@ static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu)
>  		case KEY_MINUS:
>  			if (efi_menu->active < efi_menu->count - 3) {
>  				list_for_each_safe(pos, n, &efi_menu->list) {
> -					entry = list_entry(pos, struct eficonfig_boot_order, list);
> +					entry = list_entry(pos, struct eficonfig_entry, list);
>  					if (entry->num == efi_menu->active)
>  						break;
>  				}
> -				tmp = list_entry(pos->next, struct eficonfig_boot_order, list);
> +				tmp = list_entry(pos->next, struct eficonfig_entry, list);
>  				entry->num++;
>  				tmp->num--;
>  				list_del(&entry->list);
> @@ -1921,9 +1914,11 @@ static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu)
>  		case KEY_SPACE:
>  			if (efi_menu->active < efi_menu->count - 2) {
>  				list_for_each_safe(pos, n, &efi_menu->list) {
> -					entry = list_entry(pos, struct eficonfig_boot_order, list);
> +					entry = list_entry(pos, struct eficonfig_entry, list);
>  					if (entry->num == efi_menu->active) {
> -						entry->active = entry->active ? false : true;
> +						struct eficonfig_boot_order_data *data = entry->data;
> +
> +						data->active = data->active ? false : true;
 
data->active = !!data->active seems a bit better here imho

>  						return EFI_NOT_READY;
>  					}
>  				}
> @@ -1949,12 +1944,13 @@ static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu)
>  static efi_status_t eficonfig_add_change_boot_order_entry(struct efimenu *efi_menu,
>  							  u32 boot_index, bool active)
>  {
> +	char *title, *p;
>  	efi_status_t ret;
>  	efi_uintn_t size;
>  	void *load_option;
>  	struct efi_load_option lo;
>  	u16 varname[] = u"Boot####";
> -	struct eficonfig_boot_order *entry;
> +	struct eficonfig_boot_order_data *data;
>  
>  	efi_create_indexed_name(varname, sizeof(varname), "Boot", boot_index);
>  	load_option = efi_get_var(varname, &efi_global_variable_guid, &size);
> @@ -1962,31 +1958,38 @@ static efi_status_t eficonfig_add_change_boot_order_entry(struct efimenu *efi_me
>  		return EFI_SUCCESS;
>  
>  	ret = efi_deserialize_load_option(&lo, load_option, &size);
> -	if (ret != EFI_SUCCESS) {
> -		free(load_option);
> -		return ret;
> +	if (ret != EFI_SUCCESS)
> +		goto out;
> +
> +	data = calloc(1, sizeof(struct eficonfig_boot_order_data));

sizeof(*data)

> +	if (!data) {
> +		ret = EFI_OUT_OF_RESOURCES;
> +		goto out;
>  	}
>  
> -	entry = calloc(1, sizeof(struct eficonfig_boot_order));

sizeof(*entry)

> -	if (!entry) {
> -		free(load_option);
> -		return EFI_OUT_OF_RESOURCES;
> +	title = calloc(1, utf16_utf8_strlen(lo.label) + 1);
> +	if (!title) {
> +		free(data);
> +		ret = EFI_OUT_OF_RESOURCES;
> +		goto out;
>  	}
> +	p = title;
> +	utf16_utf8_strcpy(&p, lo.label);
>  
> -	entry->description = u16_strdup(lo.label);
> -	if (!entry->description) {
> -		free(load_option);
> -		free(entry);
> -		return EFI_OUT_OF_RESOURCES;
> +	data->boot_index = boot_index;
> +	data->active = active;
> +
> +	ret = eficonfig_append_menu_entry(efi_menu, title, NULL, data);
> +	if (ret != EFI_SUCCESS) {
> +		free(data);
> +		free(title);

Thanks
/Ilias

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v6 1/5] eficonfig: refactor eficonfig_select_file_handler()
  2022-11-04 15:12   ` Ilias Apalodimas
@ 2022-11-07  2:31     ` Masahisa Kojima
  0 siblings, 0 replies; 17+ messages in thread
From: Masahisa Kojima @ 2022-11-07  2:31 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, Heinrich Schuchardt, Simon Glass, Takahiro Akashi,
	Etienne Carriere

"Hi Ilias,

On Sat, 5 Nov 2022 at 00:12, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Kojima-san
>
> I think there's some information missing from the commit message.
>
> On Wed, Oct 26, 2022 at 07:43:41PM +0900, Masahisa Kojima wrote:
> > eficonfig_select_file_handler() is commonly used to select the
> > file.
> > eficonfig_display_select_file_option() intends to add the
> > additional menu mainly to clear the selected file information.
> 'eficonfig_display_select_file_option() adds an additional menu to clear
> the selected file' sounds better?

OK, I will update the commit message.

>
> > eficonfig_display_select_file_option() is not necessary for the
> > file selection process, so it should be outside of
> > eficonfig_select_file_handler().
>
> In a followup patch I think we should rename eficonfig_select_file().  It's
> a bit confusing to have both eficonfig_select_file_handler() and
> eficonfig_select_file() and iirc the latter creates the menu for the file
> selection.

Yes, I agree.
I will rename the functions as follows.
 eficonfig_select_file_handler -> eficonfig_process_select_file()
 eficonfig_select_file -> eficonfig_show_file_selection()

>
> >
> > Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> > ---
> > No change since v2
> >
> > newly created in v2
> >
> >  cmd/eficonfig.c                                | 13 +++++--------
> >  test/py/tests/test_eficonfig/test_eficonfig.py |  1 +
> >  2 files changed, 6 insertions(+), 8 deletions(-)
> >
> > diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
> > index 2595dd9563..f6a99bd01a 100644
> > --- a/cmd/eficonfig.c
> > +++ b/cmd/eficonfig.c
> > @@ -968,7 +968,7 @@ efi_status_t eficonfig_process_clear_file_selection(void *data)
> >  }
> >
> >  static struct eficonfig_item select_file_menu_items[] = {
> > -     {"Select File", eficonfig_process_select_file},
>
> eficonfig_process_select_file() is not used anywhere anymore now.  We need
> to get rid of the function declaration

Yes, I will remove it. Note that this function name
"eficonfig_process_select_file"
will be used for renaming "eficonfig_select_file_handler" in the followup patch.

>
> > +     {"Select File", eficonfig_select_file_handler},
>
> This is a different change right? It effectively allows you to choose
> between files.
> Can we explain this change as well on the commit message?

Yes, I will update the commit message.

Thank you for your feedback.

Regards,
Masahisa Kojima

>
> >       {"Clear", eficonfig_process_clear_file_selection},
> >       {"Quit", eficonfig_process_quit},
> >  };
> > @@ -980,12 +980,13 @@ static struct eficonfig_item select_file_menu_items[] = {
> >   * @file_info:       pointer to the file information structure
> >   * Return:   status code
> >   */
> > -efi_status_t eficonfig_display_select_file_option(struct eficonfig_select_file_info *file_info)
> > +efi_status_t eficonfig_display_select_file_option(void *data)
> >  {
> >       efi_status_t ret;
> >       struct efimenu *efi_menu;
> >
> > -     select_file_menu_items[1].data = file_info;
> > +     select_file_menu_items[0].data = data;
> > +     select_file_menu_items[1].data = data;
> >       efi_menu = eficonfig_create_fixed_menu(select_file_menu_items,
> >                                              ARRAY_SIZE(select_file_menu_items));
> >       if (!efi_menu)
> > @@ -1016,10 +1017,6 @@ efi_status_t eficonfig_select_file_handler(void *data)
> >       struct eficonfig_select_file_info *tmp = NULL;
> >       struct eficonfig_select_file_info *file_info = data;
> >
> > -     ret = eficonfig_display_select_file_option(file_info);
> > -     if (ret != EFI_SUCCESS)
> > -             return ret;
> > -
> >       tmp = calloc(1, sizeof(struct eficonfig_select_file_info));
> >       if (!tmp)
> >               return EFI_OUT_OF_RESOURCES;
> > @@ -1284,7 +1281,7 @@ static efi_status_t prepare_file_selection_entry(struct efimenu *efi_menu, char
> >       utf8_utf16_strcpy(&p, devname);
> >       u16_strlcat(file_name, file_info->current_path, len);
> >       ret = create_boot_option_entry(efi_menu, title, file_name,
> > -                                    eficonfig_select_file_handler, file_info);
> > +                                    eficonfig_display_select_file_option, file_info);
> >  out:
> >       free(devname);
> >       free(file_name);
> > diff --git a/test/py/tests/test_eficonfig/test_eficonfig.py b/test/py/tests/test_eficonfig/test_eficonfig.py
> > index 99606d9c4b..102bfd7541 100644
> > --- a/test/py/tests/test_eficonfig/test_eficonfig.py
> > +++ b/test/py/tests/test_eficonfig/test_eficonfig.py
> > @@ -349,6 +349,7 @@ def test_efi_eficonfig(u_boot_console, efi_eficonfig_data):
> >          press_up_down_enter_and_wait(0, 1, True, 'Quit')
> >          press_up_down_enter_and_wait(0, 0, True, 'No block device found!')
> >          press_escape_key(False)
> > +        press_escape_key(False)
> >          check_current_is_maintenance_menu()
> >          # Return to U-Boot console
> >          press_escape_key(True)
> > --
> > 2.17.1
> >
>
> Thanks
> /Ilias

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v6 2/5] eficonfig: expose append entry function
  2022-11-04 15:16   ` Ilias Apalodimas
@ 2022-11-07  2:32     ` Masahisa Kojima
  0 siblings, 0 replies; 17+ messages in thread
From: Masahisa Kojima @ 2022-11-07  2:32 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, Heinrich Schuchardt, Simon Glass, Takahiro Akashi,
	Etienne Carriere

On Sat, 5 Nov 2022 at 00:16, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Kojima-san
>
> On Wed, Oct 26, 2022 at 07:43:42PM +0900, Masahisa Kojima wrote:
> > This commit exposes the eficonfig menu entry append function.
>
> Can we update the description to something we could look up in the future?
> e.g
> 'Following commits are adding support for variable management via the
> eficonfig menu.  Those functions needs to use append_entry and
> append_quit_entry, so move them out of their static declarations'
>
> >
> > Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> > ---
> > No change since v2
> >
> > newly created in v2
> >
> >  cmd/eficonfig.c      | 32 +++++++++++++++++---------------
> >  include/efi_config.h |  5 +++++
> >  2 files changed, 22 insertions(+), 15 deletions(-)
> >
> > diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
> > index f6a99bd01a..0cb0770ac3 100644
> > --- a/cmd/eficonfig.c
> > +++ b/cmd/eficonfig.c
> > @@ -263,7 +263,7 @@ efi_status_t eficonfig_process_quit(void *data)
> >  }
> >
> >  /**
> > - * append_entry() - append menu item
> > + * eficonfig_append_menu_entry() - append menu item
> >   *
> >   * @efi_menu:        pointer to the efimenu structure
> >   * @title:   pointer to the entry title
> > @@ -271,8 +271,9 @@ efi_status_t eficonfig_process_quit(void *data)
> >   * @data:    pointer to the data to be passed to each entry callback
> >   * Return:   status code
> >   */
> > -static efi_status_t append_entry(struct efimenu *efi_menu,
> > -                              char *title, eficonfig_entry_func func, void *data)
> > +efi_status_t eficonfig_append_menu_entry(struct efimenu *efi_menu,
> > +                                      char *title, eficonfig_entry_func func,
> > +                                      void *data)
> >  {
> >       struct eficonfig_entry *entry;
> >
> > @@ -295,12 +296,12 @@ static efi_status_t append_entry(struct efimenu *efi_menu,
> >  }
> >
> >  /**
> > - * append_quit_entry() - append quit entry
> > + * eficonfig_append_quit_entry() - append quit entry
> >   *
> >   * @efi_menu:        pointer to the efimenu structure
> >   * Return:   status code
> >   */
> > -static efi_status_t append_quit_entry(struct efimenu *efi_menu)
> > +efi_status_t eficonfig_append_quit_entry(struct efimenu *efi_menu)
> >  {
> >       char *title;
> >       efi_status_t ret;
> > @@ -309,7 +310,7 @@ static efi_status_t append_quit_entry(struct efimenu *efi_menu)
> >       if (!title)
> >               return EFI_OUT_OF_RESOURCES;
> >
> > -     ret = append_entry(efi_menu, title, eficonfig_process_quit, NULL);
> > +     ret = eficonfig_append_menu_entry(efi_menu, title, eficonfig_process_quit, NULL);
> >       if (ret != EFI_SUCCESS)
> >               free(title);
> >
> > @@ -341,7 +342,7 @@ void *eficonfig_create_fixed_menu(const struct eficonfig_item *items, int count)
> >               if (!title)
> >                       goto out;
> >
> > -             ret = append_entry(efi_menu, title, iter->func, iter->data);
> > +             ret = eficonfig_append_menu_entry(efi_menu, title, iter->func, iter->data);
> >               if (ret != EFI_SUCCESS) {
> >                       free(title);
> >                       goto out;
> > @@ -634,14 +635,15 @@ static efi_status_t eficonfig_select_volume(struct eficonfig_select_file_info *f
> >               info->v = v;
> >               info->dp = device_path;
> >               info->file_info = file_info;
> > -             ret = append_entry(efi_menu, devname, eficonfig_volume_selected, info);
> > +             ret = eficonfig_append_menu_entry(efi_menu, devname, eficonfig_volume_selected,
> > +                                               info);
> >               if (ret != EFI_SUCCESS) {
> >                       free(info);
> >                       goto out;
> >               }
> >       }
> >
> > -     ret = append_quit_entry(efi_menu);
> > +     ret = eficonfig_append_quit_entry(efi_menu);
> >       if (ret != EFI_SUCCESS)
> >               goto out;
> >
> > @@ -745,8 +747,8 @@ eficonfig_create_file_entry(struct efimenu *efi_menu, u32 count,
> >             (int (*)(const void *, const void *))sort_file);
> >
> >       for (i = 0; i < entry_num; i++) {
> > -             ret = append_entry(efi_menu, tmp_infos[i]->file_name,
> > -                                eficonfig_file_selected, tmp_infos[i]);
> > +             ret = eficonfig_append_menu_entry(efi_menu, tmp_infos[i]->file_name,
> > +                                               eficonfig_file_selected, tmp_infos[i]);
> >               if (ret != EFI_SUCCESS)
> >                       goto out;
> >       }
> > @@ -815,7 +817,7 @@ static efi_status_t eficonfig_select_file(struct eficonfig_select_file_info *fil
> >               if (ret != EFI_SUCCESS)
> >                       goto err;
> >
> > -             ret = append_quit_entry(efi_menu);
> > +             ret = eficonfig_append_quit_entry(efi_menu);
> >               if (ret != EFI_SUCCESS)
> >                       goto err;
> >
> > @@ -1218,7 +1220,7 @@ static efi_status_t create_boot_option_entry(struct efimenu *efi_menu, char *tit
> >               utf16_utf8_strcpy(&p, val);
> >       }
> >
> > -     return append_entry(efi_menu, buf, func, data);
> > +     return eficonfig_append_menu_entry(efi_menu, buf, func, data);
> >  }
> >
> >  /**
> > @@ -1677,7 +1679,7 @@ static efi_status_t eficonfig_add_boot_selection_entry(struct efimenu *efi_menu,
> >       utf16_utf8_strcpy(&p, lo.label);
> >       info->boot_index = boot_index;
> >       info->selected = selected;
> > -     ret = append_entry(efi_menu, buf, eficonfig_process_boot_selected, info);
> > +     ret = eficonfig_append_menu_entry(efi_menu, buf, eficonfig_process_boot_selected, info);
> >       if (ret != EFI_SUCCESS) {
> >               free(load_option);
> >               free(info);
> > @@ -1736,7 +1738,7 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected)
> >                       break;
> >       }
> >
> > -     ret = append_quit_entry(efi_menu);
> > +     ret = eficonfig_append_quit_entry(efi_menu);
> >       if (ret != EFI_SUCCESS)
> >               goto out;
> >
> > diff --git a/include/efi_config.h b/include/efi_config.h
> > index 098cac2115..86bc801211 100644
> > --- a/include/efi_config.h
> > +++ b/include/efi_config.h
> > @@ -95,4 +95,9 @@ efi_status_t eficonfig_get_unused_bootoption(u16 *buf,
> >  efi_status_t eficonfig_append_bootorder(u16 index);
> >  efi_status_t eficonfig_generate_media_device_boot_option(void);
> >
> > +efi_status_t eficonfig_append_menu_entry(struct efimenu *efi_menu,
> > +                                      char *title, eficonfig_entry_func func,
> > +                                      void *data);
> > +efi_status_t eficonfig_append_quit_entry(struct efimenu *efi_menu);
> > +
> >  #endif
> > --
> > 2.17.1
> >
>
> Other than that
> Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>

OK, I will update the commit message.

Thanks,
Masahisa Kojima

>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v6 4/5] eficonfig: add UEFI Secure Boot Key enrollment interface
  2022-11-04 21:46   ` Ilias Apalodimas
@ 2022-11-07  3:12     ` Masahisa Kojima
  2022-11-07 13:27       ` Ilias Apalodimas
  0 siblings, 1 reply; 17+ messages in thread
From: Masahisa Kojima @ 2022-11-07  3:12 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, Heinrich Schuchardt, Simon Glass, Takahiro Akashi,
	Etienne Carriere, Roger Knecht, Chris Morgan, Stefan Roese,
	Ovidiu Panait, Ashok Reddy Soma

Hi Ilias,

On Sat, 5 Nov 2022 at 06:46, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Kojima-san
>
> On Wed, Oct 26, 2022 at 07:43:44PM +0900, Masahisa Kojima wrote:
> > This commit adds the menu-driven UEFI Secure Boot Key
> > enrollment interface. User can enroll the PK, KEK, db
> > and dbx by selecting EFI Signature Lists file.
> > After the PK is enrolled, UEFI Secure Boot is enabled and
> > EFI Signature Lists file must be signed by KEK or PK.
> >
> > Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> > ---
> > Changes in v6:
> > - use efi_secure_boot_enabled()
> > - replace with WIN_CERT_REVISION_2_0 from pe.h
> > - call efi_build_signature_store() to check the valid EFI Signature List
> > - update comment
> >
> > Changes in v4:
> > - add CONFIG_EFI_MM_COMM_TEE dependency
> > - fix error handling
> >
> > Changes in v3:
> > - fix error handling
> >
> > Changes in v2:
> > - allow to enroll .esl file
> > - fix typos
> > - add function comments
> >
> >  cmd/Makefile          |   5 +
> >  cmd/eficonfig.c       |   3 +
> >  cmd/eficonfig_sbkey.c | 333 ++++++++++++++++++++++++++++++++++++++++++
> >  include/efi_config.h  |   5 +
> >  4 files changed, 346 insertions(+)
> >  create mode 100644 cmd/eficonfig_sbkey.c
> >
> > diff --git a/cmd/Makefile b/cmd/Makefile
> > index c95e09d058..e43ef22e98 100644
> > --- a/cmd/Makefile
> > +++ b/cmd/Makefile
> > @@ -66,6 +66,11 @@ obj-$(CONFIG_CMD_EEPROM) += eeprom.o
> >  obj-$(CONFIG_EFI) += efi.o
> >  obj-$(CONFIG_CMD_EFIDEBUG) += efidebug.o
> >  obj-$(CONFIG_CMD_EFICONFIG) += eficonfig.o
> > +ifdef CONFIG_CMD_EFICONFIG
> > +ifdef CONFIG_EFI_MM_COMM_TEE
> > +obj-$(CONFIG_EFI_SECURE_BOOT) += eficonfig_sbkey.o
> > +endif
> > +endif
> >  obj-$(CONFIG_CMD_ELF) += elf.o
> >  obj-$(CONFIG_CMD_EROFS) += erofs.o
> >  obj-$(CONFIG_HUSH_PARSER) += exit.o
> > diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
> > index c765b795d0..0b643a046c 100644
> > --- a/cmd/eficonfig.c
> > +++ b/cmd/eficonfig.c
> > @@ -2447,6 +2447,9 @@ static const struct eficonfig_item maintenance_menu_items[] = {
> >       {"Edit Boot Option", eficonfig_process_edit_boot_option},
> >       {"Change Boot Order", eficonfig_process_change_boot_order},
> >       {"Delete Boot Option", eficonfig_process_delete_boot_option},
> > +#if (CONFIG_IS_ENABLED(EFI_SECURE_BOOT) && CONFIG_IS_ENABLED(EFI_MM_COMM_TEE))
> > +     {"Secure Boot Configuration", eficonfig_process_secure_boot_config},
> > +#endif
> >       {"Quit", eficonfig_process_quit},
> >  };
> >
> > diff --git a/cmd/eficonfig_sbkey.c b/cmd/eficonfig_sbkey.c
> > new file mode 100644
> > index 0000000000..e4a3573f1b
> > --- /dev/null
> > +++ b/cmd/eficonfig_sbkey.c
> > @@ -0,0 +1,333 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + *  Menu-driven UEFI Secure Boot Key Maintenance
> > + *
> > + *  Copyright (c) 2022 Masahisa Kojima, Linaro Limited
> > + */
> > +
> > +#include <ansi.h>
> > +#include <common.h>
> > +#include <charset.h>
> > +#include <hexdump.h>
> > +#include <log.h>
> > +#include <malloc.h>
> > +#include <menu.h>
> > +#include <efi_loader.h>
> > +#include <efi_config.h>
> > +#include <efi_variable.h>
> > +#include <crypto/pkcs7_parser.h>
> > +
> > +enum efi_sbkey_signature_type {
> > +     SIG_TYPE_X509 = 0,
> > +     SIG_TYPE_HASH,
> > +     SIG_TYPE_CRL,
> > +     SIG_TYPE_RSA2048,
> > +};
> > +
> > +struct eficonfig_sigtype_to_str {
> > +     efi_guid_t sig_type;
> > +     char *str;
> > +     enum efi_sbkey_signature_type type;
> > +};
> > +
> > +static const struct eficonfig_sigtype_to_str sigtype_to_str[] = {
> > +     {EFI_CERT_X509_GUID,            "X509",                 SIG_TYPE_X509},
> > +     {EFI_CERT_SHA256_GUID,          "SHA256",               SIG_TYPE_HASH},
> > +     {EFI_CERT_X509_SHA256_GUID,     "X509_SHA256 CRL",      SIG_TYPE_CRL},
> > +     {EFI_CERT_X509_SHA384_GUID,     "X509_SHA384 CRL",      SIG_TYPE_CRL},
> > +     {EFI_CERT_X509_SHA512_GUID,     "X509_SHA512 CRL",      SIG_TYPE_CRL},
> > +     /* U-Boot does not support the following signature types */
> > +/*   {EFI_CERT_RSA2048_GUID,         "RSA2048",              SIG_TYPE_RSA2048}, */
> > +/*   {EFI_CERT_RSA2048_SHA256_GUID,  "RSA2048_SHA256",       SIG_TYPE_RSA2048}, */
> > +/*   {EFI_CERT_SHA1_GUID,            "SHA1",                 SIG_TYPE_HASH}, */
> > +/*   {EFI_CERT_RSA2048_SHA_GUID,     "RSA2048_SHA",          SIG_TYPE_RSA2048 }, */
> > +/*   {EFI_CERT_SHA224_GUID,          "SHA224",               SIG_TYPE_HASH}, */
> > +/*   {EFI_CERT_SHA384_GUID,          "SHA384",               SIG_TYPE_HASH}, */
> > +/*   {EFI_CERT_SHA512_GUID,          "SHA512",               SIG_TYPE_HASH}, */
> > +};
> > +
> > +/**
> > + * create_time_based_payload() - create payload for time based authenticate variable
> > + *
> > + * @db:              pointer to the original signature database
> > + * @new_db:  pointer to the authenticated variable payload
> > + * @size:    pointer to payload size
> > + * Return:   status code
> > + */
> > +static efi_status_t create_time_based_payload(void *db, void **new_db, efi_uintn_t *size)
> > +{
> > +     efi_status_t ret;
> > +     struct efi_time time;
> > +     efi_uintn_t total_size;
> > +     struct efi_variable_authentication_2 *auth;
> > +
> > +     *new_db = NULL;
> > +
> > +     /*
> > +      * SetVariable() call with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
> > +      * attribute requires EFI_VARIABLE_AUTHENTICATED_2 descriptor, prepare it
> > +      * without certificate data in it.
> > +      */
> > +     total_size = sizeof(struct efi_variable_authentication_2) + *size;
> > +
> > +     auth = calloc(1, total_size);
> > +     if (!auth)
> > +             return EFI_OUT_OF_RESOURCES;
> > +
> > +     ret = EFI_CALL((*efi_runtime_services.get_time)(&time, NULL));
> > +     if (ret != EFI_SUCCESS) {
> > +             free(auth);
> > +             return EFI_OUT_OF_RESOURCES;
> > +     }
> > +     time.pad1 = 0;
> > +     time.nanosecond = 0;
> > +     time.timezone = 0;
> > +     time.daylight = 0;
> > +     time.pad2 = 0;
>
> Can't we do struct efi_time time = {0}?
> Unless you explicitly need daylight to be set to zero

efi_get_time_boottime() calls "memset(time, 0, sizeof(*time));",
So no need to do struct efi_time time = {0}.
efi_get_time_boottime() may update timezone and daylight, so
we explicitly need timezone and daylight to be set to zero.

>
> > +     memcpy(&auth->time_stamp, &time, sizeof(time));
> > +     auth->auth_info.hdr.dwLength = sizeof(struct win_certificate_uefi_guid);
> > +     auth->auth_info.hdr.wRevision = WIN_CERT_REVISION_2_0;
> > +     auth->auth_info.hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
> > +     guidcpy(&auth->auth_info.cert_type, &efi_guid_cert_type_pkcs7);
> > +     if (db)
> > +             memcpy((u8 *)auth + sizeof(struct efi_variable_authentication_2), db, *size);
> > +
> > +     *new_db = auth;
> > +     *size = total_size;
> > +
> > +     return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > + * file_have_auth_header() - check file has EFI_VARIABLE_AUTHENTICATION_2 header
> > + * @buf:     pointer to file
> > + * @size:    file size
> > + * Return:   true if file has auth header, false otherwise
> > + */
> > +static bool file_have_auth_header(void *buf, efi_uintn_t size)
> > +{
> > +     struct efi_variable_authentication_2 *auth = buf;
> > +
> > +     if (auth->auth_info.hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID)
> > +             return false;
> > +
> > +     if (guidcmp(&auth->auth_info.cert_type, &efi_guid_cert_type_pkcs7))
> > +             return false;
> > +
> > +     return true;
> > +}
> > +
> > +/**
> > + * eficonfig_process_enroll_key() - enroll key into signature database
> > + *
> > + * @data:    pointer to the data for each entry
> > + * Return:   status code
> > + */
> > +static efi_status_t eficonfig_process_enroll_key(void *data)
> > +{
> > +     u32 attr;
> > +     char *buf = NULL;
> > +     efi_uintn_t size;
> > +     efi_status_t ret;
> > +     void *new_db = NULL;
> > +     struct efi_file_handle *f;
> > +     struct efi_file_handle *root;
> > +     struct eficonfig_select_file_info file_info;
> > +
> > +     file_info.current_path = calloc(1, EFICONFIG_FILE_PATH_BUF_SIZE);
> > +     if (!file_info.current_path) {
> > +             ret = EFI_OUT_OF_RESOURCES;
> > +             goto out;
> > +     }
> > +
> > +     ret = eficonfig_select_file_handler(&file_info);
> > +     if (ret != EFI_SUCCESS)
> > +             goto out;
> > +
> > +     ret = efi_open_volume_int(file_info.current_volume, &root);
> > +     if (ret != EFI_SUCCESS)
> > +             goto out;
> > +
> > +     ret = efi_file_open_int(root, &f, file_info.current_path, EFI_FILE_MODE_READ, 0);
> > +     if (ret != EFI_SUCCESS)
> > +             goto out;
> > +
> > +     size = 0;
> > +     ret = EFI_CALL(f->getinfo(f, &efi_file_info_guid, &size, NULL));
> > +     if (ret != EFI_BUFFER_TOO_SMALL)
> > +             goto out;
> > +
> > +     buf = calloc(1, size);
> > +     if (!buf) {
> > +             ret = EFI_OUT_OF_RESOURCES;
> > +             goto out;
> > +     }
> > +     ret = EFI_CALL(f->getinfo(f, &efi_file_info_guid, &size, buf));
> > +     if (ret != EFI_SUCCESS)
> > +             goto out;
> > +
> > +     size = ((struct efi_file_info *)buf)->file_size;
> > +     free(buf);
>
> You can replace most of this code with efi_file_size()

Thanks. I will use it.

>
> > +
> > +     buf = calloc(1, size);
> > +     if (!buf) {
> > +             ret = EFI_OUT_OF_RESOURCES;
> > +             goto out;
> > +     }
> > +
> > +     ret = efi_file_read_int(f, &size, buf);
> > +     if (ret != EFI_SUCCESS) {
> > +             eficonfig_print_msg("ERROR! Failed to read file.");
> > +             goto out;
> > +     }
> > +     if (size == 0) {
> > +             eficonfig_print_msg("ERROR! File is empty.");
> > +             goto out;
> > +     }
> > +
> > +     if (!file_have_auth_header(buf, size)) {
>
> Can you explain why we need this?  I would expect the user to prepare an
> .esl file with ./tools/efivar.py

This is for the case that the user selects the .auth file
signed by 'sign-efi-sig-list' tool.

Thanks,
Masahisa Kojima

>
> > +             struct efi_signature_store *sigstore;
> > +             char *tmp_buf;
> > +
> > +             /* Check if the file is valid EFI Signature List(s) */
> > +             tmp_buf = calloc(1, size);
> > +             if (!tmp_buf) {
> > +                     ret = EFI_OUT_OF_RESOURCES;
> > +                     goto out;
> > +             }
> > +             memcpy(tmp_buf, buf, size);
> > +             /* tmp_buf is freed in efi_build_signature_store() */
> > +             sigstore = efi_build_signature_store(tmp_buf, size);
> > +             if (!sigstore) {
> > +                     eficonfig_print_msg("ERROR! Invalid file format.");
> > +                     ret = EFI_INVALID_PARAMETER;
> > +                     goto out;
> > +             }
> > +             efi_sigstore_free(sigstore);
> > +
> > +             ret = create_time_based_payload(buf, &new_db, &size);
> > +             if (ret != EFI_SUCCESS) {
> > +                     eficonfig_print_msg("ERROR! Failed to create payload with timestamp.");
> > +                     goto out;
> > +             }
> > +
> > +             free(buf);
> > +             buf = new_db;
> > +     }
> > +
> > +     attr = EFI_VARIABLE_NON_VOLATILE |
> > +            EFI_VARIABLE_BOOTSERVICE_ACCESS |
> > +            EFI_VARIABLE_RUNTIME_ACCESS |
> > +            EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
> > +
> [...]
>
> Thanks
> /Ilias

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v6 3/5] eficonfig: refactor change boot order implementation
  2022-11-04 22:08   ` Ilias Apalodimas
@ 2022-11-07  3:18     ` Masahisa Kojima
  0 siblings, 0 replies; 17+ messages in thread
From: Masahisa Kojima @ 2022-11-07  3:18 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, Heinrich Schuchardt, Simon Glass, Takahiro Akashi,
	Etienne Carriere

Hi Ilias,

On Sat, 5 Nov 2022 at 07:08, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Kojima-san
>
> On Wed, Oct 26, 2022 at 07:43:43PM +0900, Masahisa Kojima wrote:
> > This commit refactors change boot order implementation
> > to use 'eficonfig_entry' structure.
>
> Please add an explanation on why we are doing this, instead of what the
> patch is doing. I am assuming it cleans up some code and allows us to reuse
> eficonfig_entry since ->data is now pointing to an
> eficonfig_boot_order_data struct?

Yes, I will update the commit message.

>
> >
> > Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> > ---
> > No update since v5
> >
> > Changes in v5:
> > - remove direct access mode
> >
> > newly created in v4
> >
> >  cmd/eficonfig.c | 129 +++++++++++++++++++++++++-----------------------
> >  1 file changed, 67 insertions(+), 62 deletions(-)
> >
> >                               list_del(&tmp->list);
>
> [...]
>
> > @@ -1891,11 +1884,11 @@ static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu)
> >               case KEY_MINUS:
> >                       if (efi_menu->active < efi_menu->count - 3) {
> >                               list_for_each_safe(pos, n, &efi_menu->list) {
> > -                                     entry = list_entry(pos, struct eficonfig_boot_order, list);
> > +                                     entry = list_entry(pos, struct eficonfig_entry, list);
> >                                       if (entry->num == efi_menu->active)
> >                                               break;
> >                               }
> > -                             tmp = list_entry(pos->next, struct eficonfig_boot_order, list);
> > +                             tmp = list_entry(pos->next, struct eficonfig_entry, list);
> >                               entry->num++;
> >                               tmp->num--;
> >                               list_del(&entry->list);
> > @@ -1921,9 +1914,11 @@ static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu)
> >               case KEY_SPACE:
> >                       if (efi_menu->active < efi_menu->count - 2) {
> >                               list_for_each_safe(pos, n, &efi_menu->list) {
> > -                                     entry = list_entry(pos, struct eficonfig_boot_order, list);
> > +                                     entry = list_entry(pos, struct eficonfig_entry, list);
> >                                       if (entry->num == efi_menu->active) {
> > -                                             entry->active = entry->active ? false : true;
> > +                                             struct eficonfig_boot_order_data *data = entry->data;
> > +
> > +                                             data->active = data->active ? false : true;
>
> data->active = !!data->active seems a bit better here imho

Yes, I will replace with "data->active = !data->active;" here.

>
> >                                               return EFI_NOT_READY;
> >                                       }
> >                               }
> > @@ -1949,12 +1944,13 @@ static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu)
> >  static efi_status_t eficonfig_add_change_boot_order_entry(struct efimenu *efi_menu,
> >                                                         u32 boot_index, bool active)
> >  {
> > +     char *title, *p;
> >       efi_status_t ret;
> >       efi_uintn_t size;
> >       void *load_option;
> >       struct efi_load_option lo;
> >       u16 varname[] = u"Boot####";
> > -     struct eficonfig_boot_order *entry;
> > +     struct eficonfig_boot_order_data *data;
> >
> >       efi_create_indexed_name(varname, sizeof(varname), "Boot", boot_index);
> >       load_option = efi_get_var(varname, &efi_global_variable_guid, &size);
> > @@ -1962,31 +1958,38 @@ static efi_status_t eficonfig_add_change_boot_order_entry(struct efimenu *efi_me
> >               return EFI_SUCCESS;
> >
> >       ret = efi_deserialize_load_option(&lo, load_option, &size);
> > -     if (ret != EFI_SUCCESS) {
> > -             free(load_option);
> > -             return ret;
> > +     if (ret != EFI_SUCCESS)
> > +             goto out;
> > +
> > +     data = calloc(1, sizeof(struct eficonfig_boot_order_data));
>
> sizeof(*data)

OK.

>
> > +     if (!data) {
> > +             ret = EFI_OUT_OF_RESOURCES;
> > +             goto out;
> >       }
> >
> > -     entry = calloc(1, sizeof(struct eficonfig_boot_order));
>
> sizeof(*entry)

OK.

Thanks,
Masahisa Kojima

>
> > -     if (!entry) {
> > -             free(load_option);
> > -             return EFI_OUT_OF_RESOURCES;
> > +     title = calloc(1, utf16_utf8_strlen(lo.label) + 1);
> > +     if (!title) {
> > +             free(data);
> > +             ret = EFI_OUT_OF_RESOURCES;
> > +             goto out;
> >       }
> > +     p = title;
> > +     utf16_utf8_strcpy(&p, lo.label);
> >
> > -     entry->description = u16_strdup(lo.label);
> > -     if (!entry->description) {
> > -             free(load_option);
> > -             free(entry);
> > -             return EFI_OUT_OF_RESOURCES;
> > +     data->boot_index = boot_index;
> > +     data->active = active;
> > +
> > +     ret = eficonfig_append_menu_entry(efi_menu, title, NULL, data);
> > +     if (ret != EFI_SUCCESS) {
> > +             free(data);
> > +             free(title);
>
> Thanks
> /Ilias

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v6 4/5] eficonfig: add UEFI Secure Boot Key enrollment interface
  2022-11-07  3:12     ` Masahisa Kojima
@ 2022-11-07 13:27       ` Ilias Apalodimas
  2022-11-07 13:37         ` Ilias Apalodimas
  0 siblings, 1 reply; 17+ messages in thread
From: Ilias Apalodimas @ 2022-11-07 13:27 UTC (permalink / raw)
  To: Masahisa Kojima
  Cc: u-boot, Heinrich Schuchardt, Simon Glass, Takahiro Akashi,
	Etienne Carriere, Roger Knecht, Chris Morgan, Stefan Roese,
	Ovidiu Panait, Ashok Reddy Soma

Hi Kojima-san

[...]

> > > +     }
> > > +
> > > +     if (!file_have_auth_header(buf, size)) {
> >
> > Can you explain why we need this?  I would expect the user to prepare an
> > .esl file with ./tools/efivar.py
> 
> This is for the case that the user selects the .auth file
> signed by 'sign-efi-sig-list' tool.

Right that's what I imagined.  So we are trying to make sure the '-t'
option from sign-efi-sig-list is the user didn't since it's now mandatory
on the spec, right?

I get what you are trying to do here.  You basically want to make sure the
user will be allowed to enroll the keys in random order. IOW if the user
first enrolls a PK, the KEK, DB and DBX must be authenticated variables.
But if he started by enrolling DB(x) he can use with the .esl file
right ?(at least until PK is registered)

I don't think this is a bad idea, but I'd prefer being more pedantic here. 
I think we are better off *always* expecting .auth files and leave the decision
of accepting a timestamped authenticated variable or not to the core UEFI
subsystem, instead of shoehorning a timestamp.

Heirich, thoughts?

Thanks
/Ilias
> 
> Thanks,
> Masahisa Kojima
> 
> >
> > > +             struct efi_signature_store *sigstore;
> > > +             char *tmp_buf;
> > > +
> > > +             /* Check if the file is valid EFI Signature List(s) */
> > > +             tmp_buf = calloc(1, size);
> > > +             if (!tmp_buf) {
> > > +                     ret = EFI_OUT_OF_RESOURCES;
> > > +                     goto out;
> > > +             }
> > > +             memcpy(tmp_buf, buf, size);
> > > +             /* tmp_buf is freed in efi_build_signature_store() */
> > > +             sigstore = efi_build_signature_store(tmp_buf, size);
> > > +             if (!sigstore) {
> > > +                     eficonfig_print_msg("ERROR! Invalid file format.");
> > > +                     ret = EFI_INVALID_PARAMETER;
> > > +                     goto out;
> > > +             }
> > > +             efi_sigstore_free(sigstore);
> > > +
> > > +             ret = create_time_based_payload(buf, &new_db, &size);
> > > +             if (ret != EFI_SUCCESS) {
> > > +                     eficonfig_print_msg("ERROR! Failed to create payload with timestamp.");
> > > +                     goto out;
> > > +             }
> > > +
> > > +             free(buf);
> > > +             buf = new_db;
> > > +     }
> > > +
> > > +     attr = EFI_VARIABLE_NON_VOLATILE |
> > > +            EFI_VARIABLE_BOOTSERVICE_ACCESS |
> > > +            EFI_VARIABLE_RUNTIME_ACCESS |
> > > +            EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
> > > +
> > [...]
> >
> > Thanks
> > /Ilias

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH v6 4/5] eficonfig: add UEFI Secure Boot Key enrollment interface
  2022-11-07 13:27       ` Ilias Apalodimas
@ 2022-11-07 13:37         ` Ilias Apalodimas
  0 siblings, 0 replies; 17+ messages in thread
From: Ilias Apalodimas @ 2022-11-07 13:37 UTC (permalink / raw)
  To: Masahisa Kojima
  Cc: u-boot, Heinrich Schuchardt, Simon Glass, Takahiro Akashi,
	Etienne Carriere, Roger Knecht, Chris Morgan, Stefan Roese,
	Ovidiu Panait, Ashok Reddy Soma

Replying to myself here for a clarification on sign-efi-sig-list

On Mon, 7 Nov 2022 at 15:27, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Kojima-san
>
> [...]
>
> > > > +     }
> > > > +
> > > > +     if (!file_have_auth_header(buf, size)) {
> > >
> > > Can you explain why we need this?  I would expect the user to prepare an
> > > .esl file with ./tools/efivar.py
> >
> > This is for the case that the user selects the .auth file
> > signed by 'sign-efi-sig-list' tool.
>
> Right that's what I imagined.  So we are trying to make sure the '-t'
> option from sign-efi-sig-list is the user didn't since it's now mandatory
> on the spec, right?

I remembered sign-efi-sig-list wrong, if -t is not specified the
system time is added

Cheers
/Ilias

>
> I get what you are trying to do here.  You basically want to make sure the
> user will be allowed to enroll the keys in random order. IOW if the user
> first enrolls a PK, the KEK, DB and DBX must be authenticated variables.
> But if he started by enrolling DB(x) he can use with the .esl file
> right ?(at least until PK is registered)
>
> I don't think this is a bad idea, but I'd prefer being more pedantic here.
> I think we are better off *always* expecting .auth files and leave the decision
> of accepting a timestamped authenticated variable or not to the core UEFI
> subsystem, instead of shoehorning a timestamp.
>
> Heirich, thoughts?
>
> Thanks
> /Ilias
> >
> > Thanks,
> > Masahisa Kojima
> >
> > >
> > > > +             struct efi_signature_store *sigstore;
> > > > +             char *tmp_buf;
> > > > +
> > > > +             /* Check if the file is valid EFI Signature List(s) */
> > > > +             tmp_buf = calloc(1, size);
> > > > +             if (!tmp_buf) {
> > > > +                     ret = EFI_OUT_OF_RESOURCES;
> > > > +                     goto out;
> > > > +             }
> > > > +             memcpy(tmp_buf, buf, size);
> > > > +             /* tmp_buf is freed in efi_build_signature_store() */
> > > > +             sigstore = efi_build_signature_store(tmp_buf, size);
> > > > +             if (!sigstore) {
> > > > +                     eficonfig_print_msg("ERROR! Invalid file format.");
> > > > +                     ret = EFI_INVALID_PARAMETER;
> > > > +                     goto out;
> > > > +             }
> > > > +             efi_sigstore_free(sigstore);
> > > > +
> > > > +             ret = create_time_based_payload(buf, &new_db, &size);
> > > > +             if (ret != EFI_SUCCESS) {
> > > > +                     eficonfig_print_msg("ERROR! Failed to create payload with timestamp.");
> > > > +                     goto out;
> > > > +             }
> > > > +
> > > > +             free(buf);
> > > > +             buf = new_db;
> > > > +     }
> > > > +
> > > > +     attr = EFI_VARIABLE_NON_VOLATILE |
> > > > +            EFI_VARIABLE_BOOTSERVICE_ACCESS |
> > > > +            EFI_VARIABLE_RUNTIME_ACCESS |
> > > > +            EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
> > > > +
> > > [...]
> > >
> > > Thanks
> > > /Ilias

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH v6 4/5] eficonfig: add UEFI Secure Boot Key enrollment interface
  2022-11-09  3:28 [PATCH v6 0/5] eficonfig: add UEFI Secure Boot key maintenance interface Masahisa Kojima
@ 2022-11-09  3:29 ` Masahisa Kojima
  0 siblings, 0 replies; 17+ messages in thread
From: Masahisa Kojima @ 2022-11-09  3:29 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Simon Glass,
	Takahiro Akashi, Etienne Carriere, Masahisa Kojima, Roger Knecht,
	Ashok Reddy Soma, Ovidiu Panait

This commit adds the menu-driven UEFI Secure Boot Key
enrollment interface. User can enroll the PK, KEK, db
and dbx by selecting EFI Signature Lists file.
After the PK is enrolled, UEFI Secure Boot is enabled and
EFI Signature Lists file must be signed by KEK or PK.

Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
---
Changes in v6:
- use efi_secure_boot_enabled()
- replace with WIN_CERT_REVISION_2_0 from pe.h
- call efi_build_signature_store() to check the valid EFI Signature List
- update comment

Changes in v4:
- add CONFIG_EFI_MM_COMM_TEE dependency
- fix error handling

Changes in v3:
- fix error handling

Changes in v2:
- allow to enroll .esl file
- fix typos
- add function comments

 cmd/Makefile          |   5 +
 cmd/eficonfig.c       |   3 +
 cmd/eficonfig_sbkey.c | 333 ++++++++++++++++++++++++++++++++++++++++++
 include/efi_config.h  |   5 +
 4 files changed, 346 insertions(+)
 create mode 100644 cmd/eficonfig_sbkey.c

diff --git a/cmd/Makefile b/cmd/Makefile
index c95e09d058..e43ef22e98 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -66,6 +66,11 @@ obj-$(CONFIG_CMD_EEPROM) += eeprom.o
 obj-$(CONFIG_EFI) += efi.o
 obj-$(CONFIG_CMD_EFIDEBUG) += efidebug.o
 obj-$(CONFIG_CMD_EFICONFIG) += eficonfig.o
+ifdef CONFIG_CMD_EFICONFIG
+ifdef CONFIG_EFI_MM_COMM_TEE
+obj-$(CONFIG_EFI_SECURE_BOOT) += eficonfig_sbkey.o
+endif
+endif
 obj-$(CONFIG_CMD_ELF) += elf.o
 obj-$(CONFIG_CMD_EROFS) += erofs.o
 obj-$(CONFIG_HUSH_PARSER) += exit.o
diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
index c765b795d0..0b643a046c 100644
--- a/cmd/eficonfig.c
+++ b/cmd/eficonfig.c
@@ -2447,6 +2447,9 @@ static const struct eficonfig_item maintenance_menu_items[] = {
 	{"Edit Boot Option", eficonfig_process_edit_boot_option},
 	{"Change Boot Order", eficonfig_process_change_boot_order},
 	{"Delete Boot Option", eficonfig_process_delete_boot_option},
+#if (CONFIG_IS_ENABLED(EFI_SECURE_BOOT) && CONFIG_IS_ENABLED(EFI_MM_COMM_TEE))
+	{"Secure Boot Configuration", eficonfig_process_secure_boot_config},
+#endif
 	{"Quit", eficonfig_process_quit},
 };
 
diff --git a/cmd/eficonfig_sbkey.c b/cmd/eficonfig_sbkey.c
new file mode 100644
index 0000000000..e4a3573f1b
--- /dev/null
+++ b/cmd/eficonfig_sbkey.c
@@ -0,0 +1,333 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  Menu-driven UEFI Secure Boot Key Maintenance
+ *
+ *  Copyright (c) 2022 Masahisa Kojima, Linaro Limited
+ */
+
+#include <ansi.h>
+#include <common.h>
+#include <charset.h>
+#include <hexdump.h>
+#include <log.h>
+#include <malloc.h>
+#include <menu.h>
+#include <efi_loader.h>
+#include <efi_config.h>
+#include <efi_variable.h>
+#include <crypto/pkcs7_parser.h>
+
+enum efi_sbkey_signature_type {
+	SIG_TYPE_X509 = 0,
+	SIG_TYPE_HASH,
+	SIG_TYPE_CRL,
+	SIG_TYPE_RSA2048,
+};
+
+struct eficonfig_sigtype_to_str {
+	efi_guid_t sig_type;
+	char *str;
+	enum efi_sbkey_signature_type type;
+};
+
+static const struct eficonfig_sigtype_to_str sigtype_to_str[] = {
+	{EFI_CERT_X509_GUID,		"X509",			SIG_TYPE_X509},
+	{EFI_CERT_SHA256_GUID,		"SHA256",		SIG_TYPE_HASH},
+	{EFI_CERT_X509_SHA256_GUID,	"X509_SHA256 CRL",	SIG_TYPE_CRL},
+	{EFI_CERT_X509_SHA384_GUID,	"X509_SHA384 CRL",	SIG_TYPE_CRL},
+	{EFI_CERT_X509_SHA512_GUID,	"X509_SHA512 CRL",	SIG_TYPE_CRL},
+	/* U-Boot does not support the following signature types */
+/*	{EFI_CERT_RSA2048_GUID,		"RSA2048",		SIG_TYPE_RSA2048}, */
+/*	{EFI_CERT_RSA2048_SHA256_GUID,	"RSA2048_SHA256",	SIG_TYPE_RSA2048}, */
+/*	{EFI_CERT_SHA1_GUID,		"SHA1",			SIG_TYPE_HASH}, */
+/*	{EFI_CERT_RSA2048_SHA_GUID,	"RSA2048_SHA",		SIG_TYPE_RSA2048 }, */
+/*	{EFI_CERT_SHA224_GUID,		"SHA224",		SIG_TYPE_HASH}, */
+/*	{EFI_CERT_SHA384_GUID,		"SHA384",		SIG_TYPE_HASH}, */
+/*	{EFI_CERT_SHA512_GUID,		"SHA512",		SIG_TYPE_HASH}, */
+};
+
+/**
+ * create_time_based_payload() - create payload for time based authenticate variable
+ *
+ * @db:		pointer to the original signature database
+ * @new_db:	pointer to the authenticated variable payload
+ * @size:	pointer to payload size
+ * Return:	status code
+ */
+static efi_status_t create_time_based_payload(void *db, void **new_db, efi_uintn_t *size)
+{
+	efi_status_t ret;
+	struct efi_time time;
+	efi_uintn_t total_size;
+	struct efi_variable_authentication_2 *auth;
+
+	*new_db = NULL;
+
+	/*
+	 * SetVariable() call with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
+	 * attribute requires EFI_VARIABLE_AUTHENTICATED_2 descriptor, prepare it
+	 * without certificate data in it.
+	 */
+	total_size = sizeof(struct efi_variable_authentication_2) + *size;
+
+	auth = calloc(1, total_size);
+	if (!auth)
+		return EFI_OUT_OF_RESOURCES;
+
+	ret = EFI_CALL((*efi_runtime_services.get_time)(&time, NULL));
+	if (ret != EFI_SUCCESS) {
+		free(auth);
+		return EFI_OUT_OF_RESOURCES;
+	}
+	time.pad1 = 0;
+	time.nanosecond = 0;
+	time.timezone = 0;
+	time.daylight = 0;
+	time.pad2 = 0;
+	memcpy(&auth->time_stamp, &time, sizeof(time));
+	auth->auth_info.hdr.dwLength = sizeof(struct win_certificate_uefi_guid);
+	auth->auth_info.hdr.wRevision = WIN_CERT_REVISION_2_0;
+	auth->auth_info.hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
+	guidcpy(&auth->auth_info.cert_type, &efi_guid_cert_type_pkcs7);
+	if (db)
+		memcpy((u8 *)auth + sizeof(struct efi_variable_authentication_2), db, *size);
+
+	*new_db = auth;
+	*size = total_size;
+
+	return EFI_SUCCESS;
+}
+
+/**
+ * file_have_auth_header() - check file has EFI_VARIABLE_AUTHENTICATION_2 header
+ * @buf:	pointer to file
+ * @size:	file size
+ * Return:	true if file has auth header, false otherwise
+ */
+static bool file_have_auth_header(void *buf, efi_uintn_t size)
+{
+	struct efi_variable_authentication_2 *auth = buf;
+
+	if (auth->auth_info.hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID)
+		return false;
+
+	if (guidcmp(&auth->auth_info.cert_type, &efi_guid_cert_type_pkcs7))
+		return false;
+
+	return true;
+}
+
+/**
+ * eficonfig_process_enroll_key() - enroll key into signature database
+ *
+ * @data:	pointer to the data for each entry
+ * Return:	status code
+ */
+static efi_status_t eficonfig_process_enroll_key(void *data)
+{
+	u32 attr;
+	char *buf = NULL;
+	efi_uintn_t size;
+	efi_status_t ret;
+	void *new_db = NULL;
+	struct efi_file_handle *f;
+	struct efi_file_handle *root;
+	struct eficonfig_select_file_info file_info;
+
+	file_info.current_path = calloc(1, EFICONFIG_FILE_PATH_BUF_SIZE);
+	if (!file_info.current_path) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+
+	ret = eficonfig_select_file_handler(&file_info);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	ret = efi_open_volume_int(file_info.current_volume, &root);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	ret = efi_file_open_int(root, &f, file_info.current_path, EFI_FILE_MODE_READ, 0);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	size = 0;
+	ret = EFI_CALL(f->getinfo(f, &efi_file_info_guid, &size, NULL));
+	if (ret != EFI_BUFFER_TOO_SMALL)
+		goto out;
+
+	buf = calloc(1, size);
+	if (!buf) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+	ret = EFI_CALL(f->getinfo(f, &efi_file_info_guid, &size, buf));
+	if (ret != EFI_SUCCESS)
+		goto out;
+
+	size = ((struct efi_file_info *)buf)->file_size;
+	free(buf);
+
+	buf = calloc(1, size);
+	if (!buf) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+
+	ret = efi_file_read_int(f, &size, buf);
+	if (ret != EFI_SUCCESS) {
+		eficonfig_print_msg("ERROR! Failed to read file.");
+		goto out;
+	}
+	if (size == 0) {
+		eficonfig_print_msg("ERROR! File is empty.");
+		goto out;
+	}
+
+	if (!file_have_auth_header(buf, size)) {
+		struct efi_signature_store *sigstore;
+		char *tmp_buf;
+
+		/* Check if the file is valid EFI Signature List(s) */
+		tmp_buf = calloc(1, size);
+		if (!tmp_buf) {
+			ret = EFI_OUT_OF_RESOURCES;
+			goto out;
+		}
+		memcpy(tmp_buf, buf, size);
+		/* tmp_buf is freed in efi_build_signature_store() */
+		sigstore = efi_build_signature_store(tmp_buf, size);
+		if (!sigstore) {
+			eficonfig_print_msg("ERROR! Invalid file format.");
+			ret = EFI_INVALID_PARAMETER;
+			goto out;
+		}
+		efi_sigstore_free(sigstore);
+
+		ret = create_time_based_payload(buf, &new_db, &size);
+		if (ret != EFI_SUCCESS) {
+			eficonfig_print_msg("ERROR! Failed to create payload with timestamp.");
+			goto out;
+		}
+
+		free(buf);
+		buf = new_db;
+	}
+
+	attr = EFI_VARIABLE_NON_VOLATILE |
+	       EFI_VARIABLE_BOOTSERVICE_ACCESS |
+	       EFI_VARIABLE_RUNTIME_ACCESS |
+	       EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+
+	/* PK can enroll only one certificate */
+	if (u16_strcmp(data, u"PK")) {
+		efi_uintn_t db_size = 0;
+
+		/* check the variable exists. If exists, add APPEND_WRITE attribute */
+		ret = efi_get_variable_int(data, efi_auth_var_get_guid(data), NULL,
+					   &db_size, NULL,  NULL);
+		if (ret == EFI_BUFFER_TOO_SMALL)
+			attr |= EFI_VARIABLE_APPEND_WRITE;
+	}
+
+	ret = efi_set_variable_int((u16 *)data, efi_auth_var_get_guid((u16 *)data),
+				   attr, size, buf, false);
+	if (ret != EFI_SUCCESS)
+		eficonfig_print_msg("ERROR! Failed to update signature database");
+
+out:
+	free(file_info.current_path);
+	free(buf);
+
+	/* return to the parent menu */
+	ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
+
+	return ret;
+}
+
+static struct eficonfig_item key_config_menu_items[] = {
+	{"Enroll New Key", eficonfig_process_enroll_key},
+	{"Quit", eficonfig_process_quit},
+};
+
+/**
+ * eficonfig_process_set_secure_boot_key() - display the key configuration menu
+ *
+ * @data:	pointer to the data for each entry
+ * Return:	status code
+ */
+static efi_status_t eficonfig_process_set_secure_boot_key(void *data)
+{
+	u32 i;
+	efi_status_t ret;
+	char header_str[32];
+	struct efimenu *efi_menu;
+
+	for (i = 0; i < ARRAY_SIZE(key_config_menu_items); i++)
+		key_config_menu_items[i].data = data;
+
+	snprintf(header_str, sizeof(header_str), "  ** Configure %ls **", (u16 *)data);
+
+	while (1) {
+		efi_menu = eficonfig_create_fixed_menu(key_config_menu_items,
+						       ARRAY_SIZE(key_config_menu_items));
+
+		ret = eficonfig_process_common(efi_menu, header_str);
+		eficonfig_destroy(efi_menu);
+
+		if (ret == EFI_ABORTED)
+			break;
+	}
+
+	/* return to the parent menu */
+	ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
+
+	return ret;
+}
+
+static const struct eficonfig_item secure_boot_menu_items[] = {
+	{"PK", eficonfig_process_set_secure_boot_key, u"PK"},
+	{"KEK", eficonfig_process_set_secure_boot_key, u"KEK"},
+	{"db", eficonfig_process_set_secure_boot_key, u"db"},
+	{"dbx", eficonfig_process_set_secure_boot_key, u"dbx"},
+	{"Quit", eficonfig_process_quit},
+};
+
+/**
+ * eficonfig_process_secure_boot_config() - display the key list menu
+ *
+ * @data:	pointer to the data for each entry
+ * Return:	status code
+ */
+efi_status_t eficonfig_process_secure_boot_config(void *data)
+{
+	efi_status_t ret;
+	struct efimenu *efi_menu;
+
+	while (1) {
+		char header_str[64];
+
+		snprintf(header_str, sizeof(header_str),
+			 "  ** UEFI Secure Boot Key Configuration (SecureBoot : %s) **",
+			 (efi_secure_boot_enabled() ? "ON" : "OFF"));
+
+		efi_menu = eficonfig_create_fixed_menu(secure_boot_menu_items,
+						       ARRAY_SIZE(secure_boot_menu_items));
+		if (!efi_menu) {
+			ret = EFI_OUT_OF_RESOURCES;
+			break;
+		}
+
+		ret = eficonfig_process_common(efi_menu, header_str);
+		eficonfig_destroy(efi_menu);
+
+		if (ret == EFI_ABORTED)
+			break;
+	}
+
+	/* return to the parent menu */
+	ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
+
+	return ret;
+}
diff --git a/include/efi_config.h b/include/efi_config.h
index 86bc801211..6db8e123f0 100644
--- a/include/efi_config.h
+++ b/include/efi_config.h
@@ -99,5 +99,10 @@ efi_status_t eficonfig_append_menu_entry(struct efimenu *efi_menu,
 					 char *title, eficonfig_entry_func func,
 					 void *data);
 efi_status_t eficonfig_append_quit_entry(struct efimenu *efi_menu);
+void *eficonfig_create_fixed_menu(const struct eficonfig_item *items, int count);
+
+#ifdef CONFIG_EFI_SECURE_BOOT
+efi_status_t eficonfig_process_secure_boot_config(void *data);
+#endif
 
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2022-11-09  3:28 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-26 10:43 [PATCH v6 0/5] eficonfig: add UEFI Secure Boot key maintenance interface Masahisa Kojima
2022-10-26 10:43 ` [PATCH v6 1/5] eficonfig: refactor eficonfig_select_file_handler() Masahisa Kojima
2022-11-04 15:12   ` Ilias Apalodimas
2022-11-07  2:31     ` Masahisa Kojima
2022-10-26 10:43 ` [PATCH v6 2/5] eficonfig: expose append entry function Masahisa Kojima
2022-11-04 15:16   ` Ilias Apalodimas
2022-11-07  2:32     ` Masahisa Kojima
2022-10-26 10:43 ` [PATCH v6 3/5] eficonfig: refactor change boot order implementation Masahisa Kojima
2022-11-04 22:08   ` Ilias Apalodimas
2022-11-07  3:18     ` Masahisa Kojima
2022-10-26 10:43 ` [PATCH v6 4/5] eficonfig: add UEFI Secure Boot Key enrollment interface Masahisa Kojima
2022-11-04 21:46   ` Ilias Apalodimas
2022-11-07  3:12     ` Masahisa Kojima
2022-11-07 13:27       ` Ilias Apalodimas
2022-11-07 13:37         ` Ilias Apalodimas
2022-10-26 10:43 ` [PATCH v6 5/5] eficonfig: add "Show/Delete Signature Database" menu entry Masahisa Kojima
2022-11-09  3:28 [PATCH v6 0/5] eficonfig: add UEFI Secure Boot key maintenance interface Masahisa Kojima
2022-11-09  3:29 ` [PATCH v6 4/5] eficonfig: add UEFI Secure Boot Key enrollment interface Masahisa Kojima

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.