From patchwork Tue Oct 4 14:35:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 612275 Delivered-To: patch@linaro.org Received: by 2002:a17:522:c983:b0:460:3032:e3c4 with SMTP id kr3csp216991pvb; Tue, 4 Oct 2022 07:36:03 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5KXChjRuYQxkjev+jmG4CmwyTum4TbigU3Q6oV2Gy+wr0ABFzfjX7UjU7fBxmLJZzZsBCo X-Received: by 2002:a05:6402:5210:b0:451:d4ff:ab02 with SMTP id s16-20020a056402521000b00451d4ffab02mr23790664edd.345.1664894162999; Tue, 04 Oct 2022 07:36:02 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1664894162; cv=none; d=google.com; s=arc-20160816; b=oWXJKIgqHQeYKvh2Bs0S9nHgV5aQWgTG6Aq26oQYb4EL82FNfV+xPU8vXqwWJZfbIy augWL40TwyRRVHlM9+ihPFgmosNVZDd2ADvfQy9O3eAFXULJX+v9dr1r/54YMRmJprWX 7DQnKji0oqb0msWhTjGOs8XWYwl0uvpVzIa2V4umG7OPpR+5z82SwS9Lq/BqASzzPZ3L 6lMr0o2wuNJVF54FGLT535HObhVhe2lKJlrxg4EVKIF2H+K5mJp17cM3tiHijQSdNgt+ uMK3UOLX99/JkVrEsiji1xra4WPxLaH2pueiYC9CBZ+NTPlhA9KKilDK8cWjqLVEkix4 agMA== 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=IZbKgCUm5Ybo1JK23Eo943kpOO3b6d/7Qg0GCz9FmjM=; b=a84TFs6xw6x1hFyx77W7v7uEBG51GZ8RtLf+qVWJdnx9A8LPVK0lNr8TNLXFjlhSIy lghWwYGj9UKNxP6ZHmSUQ8Kl7yBppkP08oQSuqixME3nrV6+9xUWB1JJX/+78lIb0J/Z H3TBox3a8dHKO571KRCXIGVbJImL4iUFan1IRm94ntWlt/bK49QTLpc09zD0e4vSZG7O NhN1tHA5QzWtaFjm3FdAiZJdvLj5zByMhYBrpDLEo+k55sxMU0d40Uh5f4C7aPnJCMwV F4WOUXlFaN3ove+SPiJl38rbB7LrrHjZRfk3eSrYVGpi1edMg6SV/B2wpThf5BYrgZ3T ONcA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=vg3TKKGu; 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 jg4-20020a170907970400b0078303058cd2si10413762ejc.23.2022.10.04.07.36.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 04 Oct 2022 07:36:02 -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=vg3TKKGu; 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 5709284DEA; Tue, 4 Oct 2022 16:35:49 +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="vg3TKKGu"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id E1BCE84E0A; Tue, 4 Oct 2022 16:35:44 +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-pf1-x429.google.com (mail-pf1-x429.google.com [IPv6:2607:f8b0:4864:20::429]) (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 8DA1784E08 for ; Tue, 4 Oct 2022 16:35:38 +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-pf1-x429.google.com with SMTP id 83so6309055pfw.10 for ; Tue, 04 Oct 2022 07:35:38 -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; bh=IZbKgCUm5Ybo1JK23Eo943kpOO3b6d/7Qg0GCz9FmjM=; b=vg3TKKGuoYwb8ICqwq3gB0Idmz0vJMVfLewHsB4SNoM8tMw6yWNigqsjD1Jh9qywKi 1S93AsenSAE5Si15/b8OQKtbVNE4QKLBTD6BgyM0Wyvbh9UfGuMpvmmu9EbXa38iWbeQ V6MqWrEybbKIAHwNW2aglZJlFvJ6nqFtIuHMi1drjhszwt5jOi2DazIj5fC8Rn+Ny9Uw BxPgMMaX3mAtsrDbG24t2cKr5Aqcoh4fI9IzPB0hLFqoqH1IVXrl3JAmCxo5Gp4CW6/v Xzzbrt8TcwmtNFpXBbYmHZk3pYeqgtZ5L/sXF9IoyPbZtKQYb0jNEQT9aFg+t9hw7e7G k7SA== 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; bh=IZbKgCUm5Ybo1JK23Eo943kpOO3b6d/7Qg0GCz9FmjM=; b=w72AmwL9t/3FEjutEd09t2h711WSKt2Lw33gAHFCjBi43KKBwrviiym8x7D1lZWWVu Ct7kQOnhWYy3JtlCWCMvAIR+U1EWUhnDDmQDv78afzUERK3Ejh9TSXH3XsOW7SG0Aj34 EDNua9MTXvhjZu1KMChRsrleFZD4P71k5I3EjoJmMzm3OULngJGcazBgFA2xsmZHYN0i MpZwXXNtE3I8q8lLljDsABGwnhg7W9eNNXyS7242gfjQOG65h0hJq5J8dHk/JOx7azjO P9hxiNdM9dLhckxeScZLPsyO6hIzBXXycJjg+4iON8dc0MNnoFyWNyCcheu0mJFe77bU kzag== X-Gm-Message-State: ACrzQf0xZDcpyiXDGuwOwDif2uluAwo5nOsQ7+u0c1ziiBdYalp+UCaS 7pRgZJYhEqyz7/56LW9XA2K5JxYr28TTVA== X-Received: by 2002:a05:6a00:24d4:b0:544:abd7:c944 with SMTP id d20-20020a056a0024d400b00544abd7c944mr28555210pfv.44.1664894136387; Tue, 04 Oct 2022 07:35:36 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id u6-20020a170902e80600b001783a917b9asm9044119plg.127.2022.10.04.07.35.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 04 Oct 2022 07:35:35 -0700 (PDT) From: Masahisa Kojima To: u-boot@lists.denx.de Cc: Heinrich Schuchardt , Ilias Apalodimas , Takahiro Akashi , Masahisa Kojima Subject: [PATCH v2 4/6] eficonfig: add "Show/Delete Signature Database" menu entry Date: Tue, 4 Oct 2022 23:35:40 +0900 Message-Id: <20221004143543.30000-5-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20221004143543.30000-1-masahisa.kojima@linaro.org> References: <20221004143543.30000-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 --- 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 e7f0545446..21f52d8578 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 * @@ -262,8 +296,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}, };