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

Signed-off-by: Masahisa Kojima <masahisa.koj...@linaro.org>
---
 cmd/eficonfig_sbkey.c | 283 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 283 insertions(+)

diff --git a/cmd/eficonfig_sbkey.c b/cmd/eficonfig_sbkey.c
index a5c0dbe9b3..02ab8f8218 100644
--- a/cmd/eficonfig_sbkey.c
+++ b/cmd/eficonfig_sbkey.c
@@ -17,6 +17,64 @@
 #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,
+       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}, 
*/
+};
+
+static void eficonfig_console_wait_enter(void)
+{
+       int esc = 0;
+       enum bootmenu_key key = KEY_NONE;
+
+       while (1) {
+               bootmenu_loop(NULL, &key, &esc);
+
+               switch (key) {
+               case KEY_SELECT:
+                       return;
+               default:
+                       break;
+               }
+       }
+
+       /* never happens */
+       debug("eficonfig: this should not happen");
+       return;
+}
+
 static bool is_secureboot_enabled(void)
 {
        efi_status_t ret;
@@ -113,13 +171,238 @@ out:
        return ret;
 }
 
+static void display_sigdata_info(struct eficonfig_sig_data *sg)
+{
+       u32 i;
+
+       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;
+                       }
+               }
+       }
+}
+
+static void display_sigdata_header(struct eficonfig_sig_data *sg, char *str)
+{
+       puts(ANSI_CURSOR_HIDE);
+       puts(ANSI_CLEAR_CONSOLE);
+       printf(ANSI_CURSOR_POSITION, 1, 1);
+
+       *sg->selected = sg;
+       printf("\n  *** U-Boot Signature Database (%s %ls) ***\n\n"
+              "    Owner GUID:\n"
+              "      %pUL\n",
+              str, sg->varname, sg->esd->signature_owner.b);
+}
+
+static efi_status_t eficonfig_process_sigdata_show(void *data)
+{
+       struct eficonfig_sig_data *sg = data;
+
+       display_sigdata_header(sg, "Show");
+       display_sigdata_info(sg);
+
+       printf("\n\n  Press ENTER to continue");
+       eficonfig_console_wait_enter();
+
+       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,
+                                             struct eficonfig_sig_data 
**selected,
+                                             struct list_head *siglist_list,
+                                             u32 *count)
+{
+       u32 num = 0;
+       efi_uintn_t size;
+       struct list_head *pos, *n;
+       struct efi_signature_list *esl;
+       struct efi_signature_data *esd;
+       struct eficonfig_item *menu_item, *iter;
+       struct eficonfig_sig_data *sg;
+
+       INIT_LIST_HEAD(siglist_list);
+       esl = db;
+       size = db_size;
+
+       /*
+        * parse the signature database and save the pointers to
+        * efi_signature_list and efi_signature_data.
+        * We expect the signature list is saved in correct format.
+        */
+       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) {
+                       sg = calloc(1, sizeof(struct eficonfig_sig_data));
+                       if (!sg)
+                               return EFI_OUT_OF_RESOURCES;
+
+                       sg->esl = esl;
+                       sg->esd = esd;
+                       list_add_tail(&sg->list, siglist_list);
+                       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);
+       }
+
+       menu_item = calloc(num + 1, sizeof(struct eficonfig_item));
+       if (!menu_item)
+               return EFI_OUT_OF_RESOURCES;
+
+       iter = menu_item;
+       list_for_each_safe(pos, n, siglist_list) {
+               char buf[40] = {0};
+               char *title;
+
+               sg = list_entry(pos, struct eficonfig_sig_data, list);
+
+               snprintf(buf, sizeof(buf), "%pUL", &sg->esd->signature_owner);
+               title = calloc(1, (strlen(buf) + 1));
+               if (!title)
+                       return EFI_OUT_OF_RESOURCES;
+
+               strlcpy(title, buf, strlen(buf) + 1);
+               iter->title = title;
+               sg->selected = selected;
+               sg->varname = varname;
+               iter->func = func;
+               iter->data = sg;
+               iter++;
+       }
+
+       /* add "Quit" entry */
+       iter->title = "Quit";
+       iter->func = eficonfig_process_quit;
+       iter->data = NULL;
+       num += 1;
+
+       *count = num;
+       *output = menu_item;
+
+       return EFI_SUCCESS;
+}
+
+static efi_status_t process_show_signature_db(void *varname)
+{
+       u32 i, count = 0;
+       efi_status_t ret;
+       struct eficonfig_item *menu_item = NULL, *iter;
+       void *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.");
+               return EFI_NOT_FOUND;
+       }
+
+       ret = prepare_signature_db_list(&menu_item, varname, db, db_size,
+                                       eficonfig_process_sigdata_show, 
&selected,
+                                       &siglist_list, &count);
+       if (ret != EFI_SUCCESS)
+               goto out;
+
+       ret = eficonfig_process_common(menu_item, count, "  ** Show Signature 
Database **");
+
+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);
+
+       return ret;
+}
+
+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)
+                       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},
        {"Quit", eficonfig_process_quit},
 };
 
 static struct eficonfig_item key_config_menu_items[] = {
        {"Enroll New Key", eficonfig_process_enroll_key},
+       {"Show Signature Database", eficonfig_process_show_signature_db},
        {"Quit", eficonfig_process_quit},
 };
 
-- 
2.17.1

Reply via email to