From patchwork Fri Oct 14 06:56:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 615064 Delivered-To: patch@linaro.org Received: by 2002:a17:522:c983:b0:460:3032:e3c4 with SMTP id kr3csp113101pvb; Thu, 13 Oct 2022 23:58:25 -0700 (PDT) X-Google-Smtp-Source: AMsMyM7iCAiKfSFQStcYjSWDTht9A4OIqzFQluCG7fy6RgsUOMPGxYA/2BuClPgbJnWKZrjVXEC9 X-Received: by 2002:a17:907:6088:b0:78d:8e24:40d0 with SMTP id ht8-20020a170907608800b0078d8e2440d0mr2532498ejc.590.1665730705644; Thu, 13 Oct 2022 23:58:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665730705; cv=none; d=google.com; s=arc-20160816; b=xfktOtS8nt0NSgLrl56/LFtU0Ez3OjV7rdavz4gSUwkG5bap9+PVj/7FpyzhFfv8ik KbqGKLO2dWadku0Lt/+r9Qttm/MtiXxjb9f9jsDMQF523W/guDrf86lFPL7MMQGSv1n4 hVT0M2YIFM6o4gcNBiNjYVLY7IXIszCaIdxfJe6FWle7e9Fr84hlasaJhEV0kDVHB9Z+ bEuGKsGtsoQKHboX7lE+NxMz5h8Rq80LutVMaNzP7OSk4deBxf5bFZjB7/q7AGsg2amc Mm1VFhHRzdXDMzA9UMCStRUvl1kX6kLR1GHwUPWnunkrVANvHxcVnaAqoxAsQ3UsMp2X cyyw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=s/PcSYSQQ9UTesLdc2CqwfUMSiEKqt/VoedMPQCkZfw=; b=m+WDtPovZ9BFr/e18MbmEEh+EuhyQavFAks8u18n032EIH85p9BJOVTFA6hh1nirD7 2RD8eRZR4O7LiR2nROr5ql9ipIlKwAgyc+Rb9mtQ5//xskOuJlmOqLpKmnIrYSvJpXmP p1YppzClUBB5oZjST3IaGzjSNZ4Bjx728sdLmoQHff8qeJeQpxRmpDg1A/yE/cuqYSsB eFL7JUDCIP4F6LfJ6RMg2T3GTSIcaV+a2ObpmJCZW+a5oLCGEQYnwBXgW8dGAV949o4e gkZq3G4LMU31Q0xCvfh6vYpjH/ap2qeHSRLmo1DDtQIPP6aV4d3z2vogawsIdE5Yn2b5 /0lQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=h8A9Dny2; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id d38-20020a056402402600b0045cd5902d51si1680062eda.507.2022.10.13.23.58.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Oct 2022 23:58:25 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=h8A9Dny2; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 7921A84F37; Fri, 14 Oct 2022 08:57:57 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="h8A9Dny2"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id CB27384EAE; Fri, 14 Oct 2022 08:57:47 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pg1-x531.google.com (mail-pg1-x531.google.com [IPv6:2607:f8b0:4864:20::531]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id EDFF284F26 for ; Fri, 14 Oct 2022 08:57:39 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=masahisa.kojima@linaro.org Received: by mail-pg1-x531.google.com with SMTP id 128so3576814pga.1 for ; Thu, 13 Oct 2022 23:57:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=references:in-reply-to:message-id:date:subject:cc:to:from:from:to :cc:subject:date:message-id:reply-to; bh=s/PcSYSQQ9UTesLdc2CqwfUMSiEKqt/VoedMPQCkZfw=; b=h8A9Dny2e2KVV9J/g5xbDVDNj2r9SkiAIvSBVLgf3/opQp13smCKaGRYuUHO4vwHYc aZtcQaCBiHw/EjNHxYhgB6pAZ5idZvuZf9OGc0alYvP5SEj0clHJfbwH0gJkxh+f3oIH +csBXkEMLQgn6D8XW3bq8yb1b2FOk7bzIpqX08c0wXEVKAEeSGKnCLP59KiThbouTD16 Fssrq+5kGh5WwNpJEHGG7owvqIZ83bjGMzuDu5j4uOaMZ9akX8nQ/1jPyTK5llheqYZR abVuAx4dqw4xKFaPAZLBmsPqkFOgu5eCs3c1kPviLWXllBcZTQxcgyc0OYTKdYnrJ79w RF6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=references:in-reply-to:message-id:date:subject:cc:to:from :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=s/PcSYSQQ9UTesLdc2CqwfUMSiEKqt/VoedMPQCkZfw=; b=qjtfT4muahHbhH6LwviIXzkfDGgqs5EMpHYZscBbKX7Zoj5P6W1ttaFpiRLGt1PHZN QObW+S28RD3v10CsT4J+LPyB7sYmXaeoGE/PYTtDCe/wNeK73KqhfRg9cQUDbRDDpMYP 1E7NyZFfAKvJWBt8q1K6NNJp6qiUwcy0D3FeufYVcZCRbqnlK2OE4v9h5udgA9b4QwWZ 5JRVuQFFMT6cB3y1tXH9tfFs8niN9djFcf7ndHcP6ZJzybGXQD1NixaZSkBHojdYFVwL c7a4Bk67JuBI6wFfNS7zGf4u4adFcG5XP1Co4hr+WCaNjpu++mzbm2YQDCDGlc6WVLji v52g== X-Gm-Message-State: ACrzQf2zMY57tAUGkbx1rhr4GiXqOi5fJ0cC1udXy4aO8d6ZJAtn4xNu 340seILLu07C0AWbbgAtjvUfaQxqWe+76A== X-Received: by 2002:a05:6a00:1a92:b0:565:d5c0:f627 with SMTP id e18-20020a056a001a9200b00565d5c0f627mr3849737pfv.10.1665730657574; Thu, 13 Oct 2022 23:57:37 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id d67-20020a621d46000000b00550724f8ea0sm850581pfd.128.2022.10.13.23.57.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 13 Oct 2022 23:57:37 -0700 (PDT) From: Masahisa Kojima To: u-boot@lists.denx.de Cc: Heinrich Schuchardt , Ilias Apalodimas , Takahiro Akashi , Masahisa Kojima Subject: [PATCH v3 4/6] eficonfig: add "Show/Delete Signature Database" menu entry Date: Fri, 14 Oct 2022 15:56:58 +0900 Message-Id: <20221014065705.5249-5-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20221014065705.5249-1-masahisa.kojima@linaro.org> References: <20221014065705.5249-1-masahisa.kojima@linaro.org> X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.6 at phobos.denx.de X-Virus-Status: Clean 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 --- No change since v2 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 cc27f78e66..e8ba15726d 100644 --- a/cmd/eficonfig_sbkey.c +++ b/cmd/eficonfig_sbkey.c @@ -17,6 +17,14 @@ #include #include +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; + } + } +} + /** * is_secureboot_enabled() - check UEFI Secure Boot is enabled * @@ -270,8 +304,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_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_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; + } + + /* to stay 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}, };