From patchwork Wed Oct 26 10:43:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 618805 Delivered-To: patch@linaro.org Received: by 2002:a17:522:c983:b0:460:3032:e3c4 with SMTP id kr3csp310018pvb; Wed, 26 Oct 2022 03:44:07 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6xteTV8wNmeWrRXoo4iHgev0uW5Lj+6yzeG34Oo+cbWCHvCCj+1H7QWODa52/GnJIU95gJ X-Received: by 2002:a17:906:6a27:b0:7a6:c537:ba4 with SMTP id qw39-20020a1709066a2700b007a6c5370ba4mr14363330ejc.517.1666781047268; Wed, 26 Oct 2022 03:44:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666781047; cv=none; d=google.com; s=arc-20160816; b=clVMiuj3BKe/qQXnFSsCixjldRISgzc5pbA8FbPAZXwp5pLMAuXmpzUNHgx7CHE8t0 A3FYrnKRTeWRQgQWI1ZKcQlAi6bV+h7Pwg7nAYImjjjyprWl1lTls4KGCiHfFO8c0vRa tZzrLAK9aJ3niW3yZK6aJh+GBhxGib1fS1Iar7J/S07EG5kb/ncYvgLqLvLfXTN0hNPP 8BIaJlCSzxhwYvO6bsjRReXVpY3oUr06sgY7w/nleuqg+tS0wQEE02X8Qbvy7ivydTHm /O/0JnrW8LTsIptF95mvHzmbAlrR4jqqmDqeNsz5dI0zvKDeUHYFkytz/SjLfBOiwgdg x1iw== 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=6qKj9U3A8zisDcgjU1MuKS2Dq7bFUzlPVQACg19XtiA=; b=Z0osJ5P7lshEiQfC/ZpeCmy1UrsW6Byi7Lzip9sH4ZARhOwXgIanoe63M2Zjb/BFhW a3ijwUU2suQO6v/Sal4iVk8GRLL3KqDyrby4/BTPu+cQl1rZ1O3GBSSzB2ChgTZHXW8j ETMhgi2QkPJYxI0n2Fkeo0fORi9Fm7ECscep1eeHPvU3GtZoKxi0/9q21vBdSyBhtgds k5aNvMGTe6LG76zH38NDPGkljdcVaDFfOZr7OJzpSmGk59qIaL1S2NTapRoREzkL4JNC FZg0dUUHVAG4hLHXmf3xroNEf1DjUy7EOwHFFiijYljOOkRhzI5p3qiJGZS0+EPExF9l d7ug== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=rbbI2bId; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 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. [85.214.62.61]) by mx.google.com with ESMTPS id x2-20020a05640226c200b0045cda8e8383si6107187edd.542.2022.10.26.03.44.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Oct 2022 03:44:07 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) client-ip=85.214.62.61; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=rbbI2bId; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 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 067D78502D; Wed, 26 Oct 2022 12:44:06 +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="rbbI2bId"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 2801985038; Wed, 26 Oct 2022 12:43:35 +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-x434.google.com (mail-pf1-x434.google.com [IPv6:2607:f8b0:4864:20::434]) (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 D38E684F9E for ; Wed, 26 Oct 2022 12:43:24 +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-x434.google.com with SMTP id w189so13412379pfw.4 for ; Wed, 26 Oct 2022 03:43:24 -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=6qKj9U3A8zisDcgjU1MuKS2Dq7bFUzlPVQACg19XtiA=; b=rbbI2bIdMfsm+RLAwENyuU7fZgHHOXF2eZGIq0aluWmwvv2bOA56JnGT3CAciQ4/Mv /pqSg2NDntI5jzqXl0xzOa8Q2fPJ7fAQhdpJKZmlxmY2A3N7gj8MDqqwWroiqFBGA2Iu 1X4SrNuyXNsERTSsNDl8fMg25YUsI5FQHKW2D4OMODoNasf5jXwwI3XLwKzzj1Q5v+mn pz4qBtm4q5QC0r1KuG5rr4tdiruu4BaliXyHBI4IrFXivricFJLE1Bu+l/YYU+SEywXh EDiybymD3ATVfrQ7t5hT6WNngvA9fKr+N8jz5iBiiVdKSHVe8f/nZMjOjCp0ty5VfGbw cqTQ== 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=6qKj9U3A8zisDcgjU1MuKS2Dq7bFUzlPVQACg19XtiA=; b=xSsvLzQHmDoWyxT0NGQsGYazDtrFr2lyrJED00gA7UoTCE9MNEQmm6ydsDIzN1aD+3 DvCcCkICZXRBVdDmlvmvICIUg1mxGAvHt9JINFuZkGP+1Q7AQH7n5i2WZTfSNsEubKES 9CMDZZUKKZSreJlfL+1eFxQo2bK6xLYFZxno521BpQHUECZG4NXDh0NA/yNLfna6TA/v MbuMUuzoStrQI60VJWkUZ6KpheQEKeUldaltQJJlypaZSWFvVwNf8YsA5skO2sWcyTni tpBLT1NIStKemAv5BoCZs2Z4DS0w4QFxwhAt6nA2QG4/xUTQ7S/O+O3VwPHvlruZm22i nGfw== X-Gm-Message-State: ACrzQf07GEqq//eH/eSqyiLxtOuHl6netG3FZGXJV7JJTgQfwqjV6Jvx 1bnbDGrkEremgqExGxMCQ8mt0TX0gkTePg== X-Received: by 2002:a63:5a46:0:b0:434:e36b:438f with SMTP id k6-20020a635a46000000b00434e36b438fmr36832281pgm.351.1666781002580; Wed, 26 Oct 2022 03:43:22 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id b3-20020a1709027e0300b00186881e1feasm2637078plm.112.2022.10.26.03.43.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Oct 2022 03:43:22 -0700 (PDT) From: Masahisa Kojima To: u-boot@lists.denx.de Cc: Heinrich Schuchardt , Ilias Apalodimas , Simon Glass , Takahiro Akashi , Etienne Carriere , Masahisa Kojima Subject: [PATCH v6 5/5] eficonfig: add "Show/Delete Signature Database" menu entry Date: Wed, 26 Oct 2022 19:43:45 +0900 Message-Id: <20221026104345.28714-6-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20221026104345.28714-1-masahisa.kojima@linaro.org> References: <20221026104345.28714-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 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 #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; + } + } +} + /** * 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}, };