From patchwork Sun Nov 20 00:21:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 627132 Delivered-To: patch@linaro.org Received: by 2002:a17:522:c983:b0:460:3032:e3c4 with SMTP id kr3csp965095pvb; Sat, 19 Nov 2022 16:23:19 -0800 (PST) X-Google-Smtp-Source: AA0mqf4985R93ihMEYeVCuMJP47MINqzca2BmNh2Dt5hVebyuyeiLmNuxhGBckT7yTkOg8cIuNpR X-Received: by 2002:ab0:2855:0:b0:411:9a0:602e with SMTP id c21-20020ab02855000000b0041109a0602emr6963886uaq.35.1668903799816; Sat, 19 Nov 2022 16:23:19 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668903799; cv=none; d=google.com; s=arc-20160816; b=Z2hVD9tLiFw8GUIymIGIxa+w2n+jO+zaZrKh6mFIfXxDRN6oVC0q8MAMd/7oN+TIEJ mM9PckTK+n0oNSxkHgk2MoHqWnDSdkQtWZHNSyDcvp6jZ0XJPtqLvBsNww2IR+7BItjO bL6AxK9yOS2OHDRHKKTb8TmZUJI54pSzabAQ69lP5jbPV+t5r007xeHcY+xSj5PB+nBT gYdrwRfw7OPT8T/l7wgYEvgDfO4HiGWboJ6UGAWR0JOaQN0yJGIFjsvMgWTyP6kPCdRu VCPmzui1QRc4fvhJ/Ce36tAs9fDpFKSBvGpS0du5kLEqmrcLbet8311Lr07afgKBbEEn BYww== 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=ZoTzl+0LdLuWobiSCtSPo8FOeQVxpTG8qquic22ND54=; b=ICbmaixnlKEx/qPtbA9L5v8iO/ySUmCT2pV4poGNNsRpNancZr1nBbJLpbT0Hl0n9T Ll3/LE+Y38+VUp6lJY771It04VUvC/nO09uzfgV47bUxomFqQf4pu+BFRhzkIuysWlbi 0lRdNg7k7eOjKBSgrkSBggX05VcOKVmCWYUs1U2EaaXBTZsOtL6gRHysdS44uq7W65g5 IUwLdVKlOiVGOQoVZWkKomQWi+FoRsxmzLHmsFbBuGxmYcZ1XJunSO+zjZAyBpTAhz66 jmCvb2N6Jiuwapx+m6YSiDitdibULWe2RG39HVkwUdugIZ6yEY75DM6URfJHfvvdF0XH Q9LQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=wO7m8l6d; 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 p24-20020ab02a58000000b00418b7661e2dsi1214990uar.152.2022.11.19.16.23.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 19 Nov 2022 16:23:19 -0800 (PST) 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=wO7m8l6d; 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 39CBD8514A; Sun, 20 Nov 2022 01:22:31 +0100 (CET) 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="wO7m8l6d"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 3838D80F1E; Sun, 20 Nov 2022 01:22:16 +0100 (CET) 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-x42d.google.com (mail-pf1-x42d.google.com [IPv6:2607:f8b0:4864:20::42d]) (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 87DCF830E2 for ; Sun, 20 Nov 2022 01:22:10 +0100 (CET) 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-x42d.google.com with SMTP id c203so8231101pfc.11 for ; Sat, 19 Nov 2022 16:22:10 -0800 (PST) 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=ZoTzl+0LdLuWobiSCtSPo8FOeQVxpTG8qquic22ND54=; b=wO7m8l6dz8dNLp98A1jMm4WCPh5x4XiEnpa3g8ue9UEO4vSO0NbBZwzHlwDxyJaNQY 8YtLDx+Nv555bueUlXTni7wF78U3oFZvdpaeArtmHzbDAtfv/EUOTUNAeEMr2HpGhVWx bi6S3An9N+4atQGg3wEU7u5btqqFDZzI6SlXAjmrjWR/lLbsLuuE4bQANOK6wrTOJhJG LS9pBBB/JOqAqvDNxyQjwq+Ye2cp4moett4uPPo7WxVzvmtJMz51aF0OBUhyXRRx3aGd S0J1VGiMPPYkWS/xSEZnYuTHNaKwydbIbeYzb93acriRcQmrelQZZ+n4w0qdh9qEjhCe 7wrQ== 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=ZoTzl+0LdLuWobiSCtSPo8FOeQVxpTG8qquic22ND54=; b=2Rb/qWIlCPPwlWiJa+51ESLK7DaltHhlLlZRero2nCaVoOpYzSVqOI5gRjf7rr/EO6 p1s/zCVWy90k9d7DF2VPMZPCeWRT9hF+RlI0074WTBPOg7oQkupTcBnkvmHhEZ/zSniT VBCWTkxb1plbDkhwc5GN2+HkZFVyT62tGWhx0965Ce26csI2g8xiTC+/b8cdhxKTmUOG XksuXiCWNtHP7pA/JqPdtapIowM/lOzpLF/ZKzjc15h8j0wwJ2g9Jyfw6VLxRjThb5Gl D58048ryBIai7qyWfT+OkLJP6BoLAFaeSxfknne+FHpCMqurKaciyhbSsM0MiGNAVeHl ML/A== X-Gm-Message-State: ANoB5pnmpg1/+2u5jO8i/f697/tY+5gIDw71bmZPnIfbgZ904WMLnKGQ YpMzx7T6NjxQiUyHYyLCsMmunDu7bbIGew== X-Received: by 2002:aa7:942f:0:b0:56b:a149:1d89 with SMTP id y15-20020aa7942f000000b0056ba1491d89mr13981243pfo.83.1668903728381; Sat, 19 Nov 2022 16:22:08 -0800 (PST) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id d12-20020a170902654c00b00168dadc7354sm1859431pln.78.2022.11.19.16.22.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 19 Nov 2022 16:22:07 -0800 (PST) From: Masahisa Kojima To: u-boot@lists.denx.de Cc: Heinrich Schuchardt , Ilias Apalodimas , Simon Glass , Takahiro Akashi , Etienne Carriere , Masahisa Kojima , Roger Knecht , Ovidiu Panait , Ashok Reddy Soma Subject: [PATCH v10 6/7] eficonfig: add UEFI Secure Boot Key enrollment interface Date: Sun, 20 Nov 2022 09:21:18 +0900 Message-Id: <20221120002119.23683-7-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20221120002119.23683-1-masahisa.kojima@linaro.org> References: <20221120002119.23683-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 UEFI Secure Boot Key enrollment interface. User can enroll PK, KEK, db and dbx by selecting file. Only the signed EFI Signature List(s) with an authenticated header, typically '.auth' file, is accepted. To clear the PK, KEK, db and dbx, user needs to enroll the null key signed by PK or KEK. Signed-off-by: Masahisa Kojima Reviewed-by: Ilias Apalodimas --- Changes in v10: - use protocol interface - use efi_file_from_path() - use malloc instead of calloc Changes in v9: - move file size check, set ret = EFI_INVALID_PARAMETER Changes in v8: - fix missing efi_file_close_int() call Changes in v7: - only accept .auth file. - remove creating time based authenticated variable - update commit message - use efi_file_size() Changes in v6: - use efi_secure_boot_enabled() - replace with WIN_CERT_REVISION_2_0 from pe.h - call efi_build_signature_store() to check the valid EFI Signature List - update comment Changes in v4: - add CONFIG_EFI_MM_COMM_TEE dependency - fix error handling Changes in v3: - fix error handling Changes in v2: - allow to enroll .esl file - fix typos - add function comments cmd/Makefile | 5 + cmd/eficonfig.c | 3 + cmd/eficonfig_sbkey.c | 263 ++++++++++++++++++++++++++++++++++++++++++ include/efi_config.h | 4 + 4 files changed, 275 insertions(+) create mode 100644 cmd/eficonfig_sbkey.c diff --git a/cmd/Makefile b/cmd/Makefile index 2444d116c0..0b6a96c1d9 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -66,6 +66,11 @@ obj-$(CONFIG_CMD_EEPROM) += eeprom.o obj-$(CONFIG_EFI) += efi.o obj-$(CONFIG_CMD_EFIDEBUG) += efidebug.o obj-$(CONFIG_CMD_EFICONFIG) += eficonfig.o +ifdef CONFIG_CMD_EFICONFIG +ifdef CONFIG_EFI_MM_COMM_TEE +obj-$(CONFIG_EFI_SECURE_BOOT) += eficonfig_sbkey.o +endif +endif obj-$(CONFIG_CMD_ELF) += elf.o obj-$(CONFIG_CMD_EROFS) += erofs.o obj-$(CONFIG_HUSH_PARSER) += exit.o diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c index 6779b1792e..44eb82c3c1 100644 --- a/cmd/eficonfig.c +++ b/cmd/eficonfig.c @@ -2438,6 +2438,9 @@ static const struct eficonfig_item maintenance_menu_items[] = { {"Edit Boot Option", eficonfig_process_edit_boot_option}, {"Change Boot Order", eficonfig_process_change_boot_order}, {"Delete Boot Option", eficonfig_process_delete_boot_option}, +#if (CONFIG_IS_ENABLED(EFI_SECURE_BOOT) && CONFIG_IS_ENABLED(EFI_MM_COMM_TEE)) + {"Secure Boot Configuration", eficonfig_process_secure_boot_config}, +#endif {"Quit", eficonfig_process_quit}, }; diff --git a/cmd/eficonfig_sbkey.c b/cmd/eficonfig_sbkey.c new file mode 100644 index 0000000000..5130848dd9 --- /dev/null +++ b/cmd/eficonfig_sbkey.c @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Menu-driven UEFI Secure Boot Key Maintenance + * + * Copyright (c) 2022 Masahisa Kojima, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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}, */ +}; + +/** + * file_have_auth_header() - check file has EFI_VARIABLE_AUTHENTICATION_2 header + * @buf: pointer to file + * @size: file size + * Return: true if file has auth header, false otherwise + */ +static bool file_have_auth_header(void *buf, efi_uintn_t size) +{ + struct efi_variable_authentication_2 *auth = buf; + + if (auth->auth_info.hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) + return false; + + if (guidcmp(&auth->auth_info.cert_type, &efi_guid_cert_type_pkcs7)) + return false; + + return true; +} + +/** + * eficonfig_process_enroll_key() - enroll key into signature database + * + * @data: pointer to the data for each entry + * Return: status code + */ +static efi_status_t eficonfig_process_enroll_key(void *data) +{ + u32 attr; + char *buf = NULL; + efi_uintn_t size; + efi_status_t ret; + struct efi_file_handle *f = NULL; + struct efi_device_path *full_dp = NULL; + struct eficonfig_select_file_info file_info; + + file_info.current_path = calloc(1, EFICONFIG_FILE_PATH_BUF_SIZE); + if (!file_info.current_path) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + + ret = eficonfig_process_select_file(&file_info); + if (ret != EFI_SUCCESS) + goto out; + + full_dp = eficonfig_create_device_path(file_info.dp_volume, file_info.current_path); + if (!full_dp) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + f = efi_file_from_path(full_dp); + if (!f) { + ret = EFI_NOT_FOUND; + goto out; + } + + size = 0; + ret = EFI_CALL(f->getinfo(f, &efi_file_info_guid, &size, NULL)); + if (ret != EFI_BUFFER_TOO_SMALL) + goto out; + + buf = malloc(size); + if (!buf) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + ret = EFI_CALL(f->getinfo(f, &efi_file_info_guid, &size, buf)); + if (ret != EFI_SUCCESS) + goto out; + + size = ((struct efi_file_info *)buf)->file_size; + free(buf); + + if (!size) { + eficonfig_print_msg("ERROR! File is empty."); + ret = EFI_INVALID_PARAMETER; + goto out; + } + + buf = malloc(size); + if (!buf) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + + ret = EFI_CALL(f->read(f, &size, buf)); + if (ret != EFI_SUCCESS) { + eficonfig_print_msg("ERROR! Failed to read file."); + goto out; + } + if (!file_have_auth_header(buf, size)) { + eficonfig_print_msg("ERROR! Invalid file format. Only .auth variables is allowed."); + ret = EFI_INVALID_PARAMETER; + goto out; + } + + attr = EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS | + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; + + /* PK can enroll only one certificate */ + if (u16_strcmp(data, u"PK")) { + efi_uintn_t db_size = 0; + + /* check the variable exists. If exists, add APPEND_WRITE attribute */ + ret = efi_get_variable_int(data, efi_auth_var_get_guid(data), NULL, + &db_size, NULL, NULL); + if (ret == EFI_BUFFER_TOO_SMALL) + attr |= EFI_VARIABLE_APPEND_WRITE; + } + + ret = efi_set_variable_int((u16 *)data, efi_auth_var_get_guid((u16 *)data), + attr, size, buf, false); + if (ret != EFI_SUCCESS) + eficonfig_print_msg("ERROR! Failed to update signature database"); + +out: + free(file_info.current_path); + free(buf); + efi_free_pool(full_dp); + if (f) + EFI_CALL(f->close(f)); + + /* 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}, + {"Quit", eficonfig_process_quit}, +}; + +/** + * 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_set_secure_boot_key(void *data) +{ + u32 i; + efi_status_t ret; + char header_str[32]; + struct efimenu *efi_menu; + + for (i = 0; i < ARRAY_SIZE(key_config_menu_items); i++) + key_config_menu_items[i].data = data; + + snprintf(header_str, sizeof(header_str), " ** Configure %ls **", (u16 *)data); + + while (1) { + efi_menu = eficonfig_create_fixed_menu(key_config_menu_items, + ARRAY_SIZE(key_config_menu_items)); + + ret = eficonfig_process_common(efi_menu, header_str); + eficonfig_destroy(efi_menu); + + if (ret == EFI_ABORTED) + break; + } + + /* return to the parent menu */ + ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret; + + return ret; +} + +static const struct eficonfig_item secure_boot_menu_items[] = { + {"PK", eficonfig_process_set_secure_boot_key, u"PK"}, + {"KEK", eficonfig_process_set_secure_boot_key, u"KEK"}, + {"db", eficonfig_process_set_secure_boot_key, u"db"}, + {"dbx", eficonfig_process_set_secure_boot_key, u"dbx"}, + {"Quit", eficonfig_process_quit}, +}; + +/** + * eficonfig_process_secure_boot_config() - display the key list menu + * + * @data: pointer to the data for each entry + * Return: status code + */ +efi_status_t eficonfig_process_secure_boot_config(void *data) +{ + efi_status_t ret; + struct efimenu *efi_menu; + + while (1) { + char header_str[64]; + + snprintf(header_str, sizeof(header_str), + " ** UEFI Secure Boot Key Configuration (SecureBoot : %s) **", + (efi_secure_boot_enabled() ? "ON" : "OFF")); + + efi_menu = eficonfig_create_fixed_menu(secure_boot_menu_items, + ARRAY_SIZE(secure_boot_menu_items)); + if (!efi_menu) { + ret = EFI_OUT_OF_RESOURCES; + break; + } + + ret = eficonfig_process_common(efi_menu, header_str); + eficonfig_destroy(efi_menu); + + if (ret == EFI_ABORTED) + break; + } + + /* return to the parent menu */ + ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret; + + return ret; +} diff --git a/include/efi_config.h b/include/efi_config.h index 934de41e85..fd69926343 100644 --- a/include/efi_config.h +++ b/include/efi_config.h @@ -101,5 +101,9 @@ efi_status_t eficonfig_append_menu_entry(struct efimenu *efi_menu, efi_status_t eficonfig_append_quit_entry(struct efimenu *efi_menu); struct efi_device_path *eficonfig_create_device_path(struct efi_device_path *dp_volume, u16 *current_path); +void *eficonfig_create_fixed_menu(const struct eficonfig_item *items, int count); +#ifdef CONFIG_EFI_SECURE_BOOT +efi_status_t eficonfig_process_secure_boot_config(void *data); +#endif #endif