On Sun, Jul 10, 2022 at 12:10:13PM +0200, Heinrich Schuchardt wrote:
> On 6/19/22 07:20, Masahisa Kojima wrote:
> > This commit add the menu-driven interface to delete the
> > signature database entry.
> > 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,
> 
> Why don't you mention 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.
> 
> Updating PK with an empty value must be possible if if the new value is
> signed with the old PK.
> 
> > 
> > Signed-off-by: Masahisa Kojima <masahisa.koj...@linaro.org>
> > ---
> >   cmd/eficonfig_sbkey.c | 218 +++++++++++++++++++++++++++++++++++++++++-
> >   1 file changed, 217 insertions(+), 1 deletion(-)
> > 
> > diff --git a/cmd/eficonfig_sbkey.c b/cmd/eficonfig_sbkey.c
> > index 02ab8f8218..142bb4cef5 100644
> > --- a/cmd/eficonfig_sbkey.c
> > +++ b/cmd/eficonfig_sbkey.c
> > @@ -54,6 +54,29 @@ static const struct eficonfig_sigtype_to_str 
> > sigtype_to_str[] = {
> >   /*        {EFI_CERT_SHA512_GUID,          "SHA512",               
> > SIG_TYPE_HASH}, */
> >   };
> > 
> 
> Please, add documentation to all functions.
> 
> > +static int eficonfig_console_yes_no(void)
> > +{
> > +   int esc = 0;
> > +   enum bootmenu_key key = KEY_NONE;
> > +
> > +   while (1) {
> > +           bootmenu_loop(NULL, &key, &esc);
> > +
> > +           switch (key) {
> > +           case KEY_SELECT:
> > +                   return 1;
> > +           case KEY_QUIT:
> > +                   return 0;
> > +           default:
> > +                   break;
> > +           }
> > +   }
> > +
> > +   /* never happens */
> > +   debug("eficonfig: this should not happen");
> > +   return 0;
> 
> If this code is unreachable, remove it.
> 
> > +}
> > +
> >   static void eficonfig_console_wait_enter(void)
> >   {
> >     int esc = 0;
> > @@ -72,7 +95,19 @@ static void eficonfig_console_wait_enter(void)
> > 
> >     /* never happens */
> >     debug("eficonfig: this should not happen");
> > -   return;
> 
> Please remove unreachable code.
> 
> > +}
> > +
> > +static bool is_setupmode(void)
> > +{
> > +   efi_status_t ret;
> > +   u8 setup_mode;
> > +   efi_uintn_t size;
> > +
> > +   size = sizeof(setup_mode);
> > +   ret = efi_get_variable_int(u"SetupMode", &efi_global_variable_guid,
> > +                              NULL, &size, &setup_mode, NULL);
> > +
> > +   return setup_mode == 1;
> >   }
> > 
> >   static bool is_secureboot_enabled(void)
> > @@ -254,6 +289,103 @@ static efi_status_t 
> > eficonfig_process_sigdata_show(void *data)
> >     return EFI_SUCCESS;
> >   }
> > 
> > +static efi_status_t eficonfig_process_sigdata_delete(void *data)
> > +{
> > +   int yes_no;
> > +   struct eficonfig_sig_data *sg = data;
> > +
> > +   display_sigdata_header(sg, "Delete");
> > +   display_sigdata_info(sg);
> > +
> > +   printf("\n\n  Press ENTER to delete, ESC/CTRL+C to quit");
> > +   yes_no = eficonfig_console_yes_no();
> > +   if (!yes_no)
> > +           return EFI_NOT_READY;
> > +
> > +   return EFI_SUCCESS;
> > +}
> > +
> > +static void delete_selected_signature_data(void *db, efi_uintn_t *db_size,
> > +                                      struct eficonfig_sig_data *target,
> > +                                      struct list_head *siglist_list)
> > +{
> > +   u8 *dest, *start;
> > +   struct list_head *pos, *n;
> > +   u32 remain;
> > +   u32 size = *db_size;
> > +   u8 *end = (u8 *)db + size;
> > +   struct eficonfig_sig_data *sg;
> > +
> > +   list_for_each_safe(pos, n, siglist_list) {
> > +           sg = list_entry(pos, struct eficonfig_sig_data, list);
> > +           if (sg->esl == target->esl && sg->esd == target->esd) {
> > +                   remain = sg->esl->signature_list_size -
> > +                            (sizeof(struct efi_signature_list) -
> > +                            sg->esl->signature_header_size) -
> > +                            sg->esl->signature_size;
> > +                   if (remain > 0) {
> > +                           /* only delete the single signature data */
> > +                           sg->esl->signature_list_size -= 
> > sg->esl->signature_size;
> > +                           size -= sg->esl->signature_size;
> > +                           dest = (u8 *)sg->esd;
> > +                           start = (u8 *)sg->esd + sg->esl->signature_size;
> > +                   } else {
> > +                           /* delete entire signature list */
> > +                           dest = (u8 *)sg->esl;
> > +                           start = (u8 *)sg->esl + 
> > sg->esl->signature_list_size;
> > +                           size -= sg->esl->signature_list_size;
> > +                   }
> > +                   memmove(dest, start, (end - start));
> > +           }
> > +   }
> > +
> > +   *db_size = size;
> > +}
> > +
> > +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 = 0x0200;
> > +   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;
> > +}
> > +
> >   static efi_status_t prepare_signature_db_list(struct eficonfig_item 
> > **output, void *varname,
> >                                           void *db, efi_uintn_t db_size,
> >                                           eficonfig_entry_func func,
> > @@ -378,6 +510,68 @@ out:
> >     return ret;
> >   }
> > 
> > +static efi_status_t process_delete_key(void *varname)
> > +{
> > +   u32 attr, i, count = 0;
> > +   efi_status_t ret;
> > +   struct eficonfig_item *menu_item = NULL, *iter;
> > +   void *db = NULL, *new_db = NULL;
> > +   efi_uintn_t db_size;
> > +   struct list_head siglist_list;
> > +   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.");
> 
> Please, use the terms of the UEFI specification.
> %s/signature database/signature store/

Signature database is also a common term throughout the specification.
See "section 32.4.1 Signature Database", for example.

-Takahiro Akashi


> > +           return EFI_NOT_FOUND;
> > +   }
> > +
> > +   ret = prepare_signature_db_list(&menu_item, varname, db, db_size,
> > +                                   eficonfig_process_sigdata_delete, 
> > &selected,
> > +                                   &siglist_list, &count);
> > +   if (ret != EFI_SUCCESS)
> > +           goto out;
> > +
> > +   ret = eficonfig_process_common(menu_item, count, " ** Delete Key **");
> > +
> > +   if (ret == EFI_SUCCESS) {
> > +           delete_selected_signature_data(db, &db_size, selected, 
> > &siglist_list);
> > +
> > +           ret = create_time_based_payload(db, &new_db, &db_size);
> > +           if (ret != EFI_SUCCESS)
> > +                   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! Fail to delete signature 
> > database");
> 
> %s/Fail/Failed/
> 
> Please, use the terms of the UEFI specification.
> %s/signature database/signature store/
> 
> > +                   goto out;
> > +           }
> > +   }
> > +
> > +out:
> > +   if (menu_item) {
> > +           iter = menu_item;
> > +           for (i = 0; i < count - 1; iter++, i++) {
> > +                   free(iter->title);
> > +                   free(iter->data);
> > +           }
> > +   }
> > +
> > +   free(menu_item);
> > +   free(db);
> > +   free(new_db);
> > +
> > +   /* to stay the parent menu */
> > +   ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
> > +
> > +   return ret;
> > +}
> > +
> >   static efi_status_t eficonfig_process_show_signature_db(void *data)
> >   {
> >     efi_status_t ret;
> > @@ -394,6 +588,27 @@ static efi_status_t 
> > eficonfig_process_show_signature_db(void *data)
> >     return ret;
> >   }
> > 
> > +static efi_status_t eficonfig_process_delete_key(void *data)
> > +{
> > +   efi_status_t ret;
> > +
> > +   if (!is_setupmode()) {
> > +           eficonfig_print_msg("Not in the SetupMode, can not delete.");
> 
> Both in Setup Mode and in Audit Mode you should be able to edit keys.
> 
> > +           return EFI_SUCCESS;
> > +   }
> > +
> > +   while (1) {
> > +           ret = process_delete_key(data);
> > +           if (ret != EFI_SUCCESS)
> > +                   break;
> > +   }
> > +
> > +   /* to stay the parent menu */
> > +   ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
> > +
> > +   return ret;
> > +}
> > +
> >   static struct eficonfig_item key_config_pk_menu_items[] = {
> >     {"Enroll New Key", eficonfig_process_enroll_key},
> >     {"Show Signature Database", eficonfig_process_show_signature_db},
> 
> %s/Signature Database/signature store/
> 
> > @@ -403,6 +618,7 @@ static struct eficonfig_item key_config_pk_menu_items[] 
> > = {
> >   static struct eficonfig_item key_config_menu_items[] = {
> >     {"Enroll New Key", eficonfig_process_enroll_key},
> >     {"Show Signature Database", eficonfig_process_show_signature_db},
> 
> %s/Signature Database/signature store/
> 
> Best regards
> 
> Heinrich
> 
> > +   {"Delete Key", eficonfig_process_delete_key},
> >     {"Quit", eficonfig_process_quit},
> >   };
> > 
> 

Reply via email to