From patchwork Fri Jun 2 13:52:04 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 101257 Delivered-To: patch@linaro.org Received: by 10.182.202.35 with SMTP id kf3csp205129obc; Fri, 2 Jun 2017 06:55:40 -0700 (PDT) X-Received: by 10.84.212.137 with SMTP id e9mr28713pli.115.1496411740722; Fri, 02 Jun 2017 06:55:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1496411740; cv=none; d=google.com; s=arc-20160816; b=V3/gb0kKGVUw5vdKLmz0uoc2/H9U5Pc1S0onpf2ttCFOBm401E2F9wkGVvcdfiXKU+ N4p5rWUj5ORVGajwU5jnwznDlQSn0G/a1XxXFMDWr41AnxNBJYkFXEVpR3fHL4d2cTyC jK26CSeZAfiXY518j2XnNbzHZ5ErHaC5P1U39RO3PrtQhW6WIJrzONcScqOXr7XVHXS0 heEuJn/Ni2Yn3/SsyupPI77GkMNICmkSPHfeWYyvEULqsS9Uo61OTzBHV1MWkl4vlOax qZQoM4y7BFQnLAqORjRlVRq6KQGCG0kFsHADG00gd4NsRZ2crBbRO0NdNrgvgAQnMejV nK5Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=KMnQHuzOKmABhFS0kuifn2e3S7n9oJDZAGkdnt9K8Jg=; b=NKits77lLAalglpRzlNVqtg/P6HHNsZ0JcUTdOTh4Wlo/MXIWaGuF+OBnGtdTviVys sXwWea+KSuEcwefTRjsyE+b6eVKzjh2regDgxxJIKI/zA23j6w9XrGClhuwlYuuWGbqN vfrCS1+7Iuz7flBX0a2pWDTBoni5ZZcFNl8TmpOrxI4q5zmpR3wPQrQcM374K5UO5YHF xeEqoneJ2uP1v8SnDJfnaHdIMlRAoIOhJYHsaNsVvUoepD5c6Eiimi8XDWPlyPgbgbIG PggbEAtpWzcjvOY49/Dc43eAfDe/lLbZRcZym14BB/ftJeHHzIKcbhkSJwyJpQprLS/v EjKA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l17si3183385pgj.43.2017.06.02.06.55.40; Fri, 02 Jun 2017 06:55:40 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751586AbdFBNzK (ORCPT + 25 others); Fri, 2 Jun 2017 09:55:10 -0400 Received: from mail-wm0-f47.google.com ([74.125.82.47]:36699 "EHLO mail-wm0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751561AbdFBNzG (ORCPT ); Fri, 2 Jun 2017 09:55:06 -0400 Received: by mail-wm0-f47.google.com with SMTP id 7so26356964wmo.1 for ; Fri, 02 Jun 2017 06:55:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=KMnQHuzOKmABhFS0kuifn2e3S7n9oJDZAGkdnt9K8Jg=; b=L2czGv1zSrx7kS5p8SNaeYkedm0NEurnay5cve+lc3viRd8dnzf9RPUea9swyLUYbf gSZC1pXqvf/vI2vuoIJxiIEZPOPfM4YLsi9IElIUupaGqxvdPfgPqANL2itq5RTvqe8f WaC9DByF0oe8G+MsVl9OYOfAknKqMR+FQ0OKY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=KMnQHuzOKmABhFS0kuifn2e3S7n9oJDZAGkdnt9K8Jg=; b=XL/pDsaTAeVQ87DTOIPO4SHwG+PJbd2PbjJ/PIGDEN4Bt0eDfhpY6WOLxY25VGorop 7mkE03AWXRczqfSp/v73uR2cFPFlPncFy7t3x5ABw5uHA4QJ9yk4Wd/J1SY0ygDMg+pL DLlCzxhbrp11YdyVm6yeUkXEp6atYgH5aAPLwcHwm5Ao+khk42j7IvWhM2trHrR2BWvW sSr/YZLEcWv6hq67ZoWxZEPIVoNxdePci18BSkJRio8I278eQJVDB3Ns/uyxHwOiKkEm ukGlZihF+759rGbhSqsMgy0ffJfLRjaUH4yV/QmxLepOSS0qXREuOkjLIliQe/7v0ED5 hDPg== X-Gm-Message-State: AODbwcCl2u5Pcgtx0eELmlWtlmg87um1dp3a0bHncWw/uiVnhy3vuV46 h05LbdymAX226VzI X-Received: by 10.80.143.227 with SMTP id y90mr6281492edy.131.1496411705151; Fri, 02 Jun 2017 06:55:05 -0700 (PDT) Received: from localhost.localdomain ([105.151.155.95]) by smtp.gmail.com with ESMTPSA id g48sm9756076edc.8.2017.06.02.06.55.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 02 Jun 2017 06:55:04 -0700 (PDT) From: Ard Biesheuvel To: linux-efi@vger.kernel.org, Ingo Molnar , Thomas Gleixner , "H . Peter Anvin" Cc: Jan Kiszka , Ard Biesheuvel , linux-kernel@vger.kernel.org, Matt Fleming Subject: [PATCH 10/13] efi/capsule: Add support for Quark security header Date: Fri, 2 Jun 2017 13:52:04 +0000 Message-Id: <20170602135207.21708-11-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170602135207.21708-1-ard.biesheuvel@linaro.org> References: <20170602135207.21708-1-ard.biesheuvel@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Jan Kiszka The firmware for Quark X102x prepends a security header to the capsule which is needed to support the mandatory secure boot on this processor. The header can be detected by checking for the "_CSH" signature and - to avoid any GUID conflict - validating its size field to contain the expected value. Then we need to look for the EFI header right after the security header and pass the real header to __efi_capsule_setup_info. To be minimal invasive and maximal safe, the quirk version of efi_capsule_identify_image is only effective on Quark processors. Signed-off-by: Jan Kiszka Cc: Matt Fleming Tested-by: "Bryan O'Donoghue" Reviewed-by: Andy Shevchenko Signed-off-by: Ard Biesheuvel --- arch/x86/platform/efi/quirks.c | 137 +++++++++++++++++++++++++++++++++++++++++ drivers/firmware/efi/Kconfig | 9 +++ 2 files changed, 146 insertions(+) -- 2.9.3 diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c index 26615991d69c..93867ee08eac 100644 --- a/arch/x86/platform/efi/quirks.c +++ b/arch/x86/platform/efi/quirks.c @@ -15,12 +15,66 @@ #include #include #include +#include #define EFI_MIN_RESERVE 5120 #define EFI_DUMMY_GUID \ EFI_GUID(0x4424ac57, 0xbe4b, 0x47dd, 0x9e, 0x97, 0xed, 0x50, 0xf0, 0x9f, 0x92, 0xa9) +#define QUARK_CSH_SIGNATURE 0x5f435348 /* _CSH */ +#define QUARK_SECURITY_HEADER_SIZE 0x400 + +/* + * Header prepended to the standard EFI capsule on Quark systems the are based + * on Intel firmware BSP. + * @csh_signature: Unique identifier to sanity check signed module + * presence ("_CSH"). + * @version: Current version of CSH used. Should be one for Quark A0. + * @modulesize: Size of the entire module including the module header + * and payload. + * @security_version_number_index: Index of SVN to use for validation of signed + * module. + * @security_version_number: Used to prevent against roll back of modules. + * @rsvd_module_id: Currently unused for Clanton (Quark). + * @rsvd_module_vendor: Vendor Identifier. For Intel products value is + * 0x00008086. + * @rsvd_date: BCD representation of build date as yyyymmdd, where + * yyyy=4 digit year, mm=1-12, dd=1-31. + * @headersize: Total length of the header including including any + * padding optionally added by the signing tool. + * @hash_algo: What Hash is used in the module signing. + * @cryp_algo: What Crypto is used in the module signing. + * @keysize: Total length of the key data including including any + * padding optionally added by the signing tool. + * @signaturesize: Total length of the signature including including any + * padding optionally added by the signing tool. + * @rsvd_next_header: 32-bit pointer to the next Secure Boot Module in the + * chain, if there is a next header. + * @rsvd: Reserved, padding structure to required size. + * + * See also QuartSecurityHeader_t in + * Quark_EDKII_v1.2.1.1/QuarkPlatformPkg/Include/QuarkBootRom.h + * from https://downloadcenter.intel.com/download/23197/Intel-Quark-SoC-X1000-Board-Support-Package-BSP + */ +struct quark_security_header { + u32 csh_signature; + u32 version; + u32 modulesize; + u32 security_version_number_index; + u32 security_version_number; + u32 rsvd_module_id; + u32 rsvd_module_vendor; + u32 rsvd_date; + u32 headersize; + u32 hash_algo; + u32 cryp_algo; + u32 keysize; + u32 signaturesize; + u32 rsvd_next_header; + u32 rsvd[2]; +}; + static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 }; static bool efi_no_storage_paranoia; @@ -501,3 +555,86 @@ bool efi_poweroff_required(void) { return acpi_gbl_reduced_hardware || acpi_no_s5; } + +#ifdef CONFIG_EFI_CAPSULE_QUIRK_QUARK_CSH + +static int qrk_capsule_setup_info(struct capsule_info *cap_info, void **pkbuff, + size_t hdr_bytes) +{ + struct quark_security_header *csh = *pkbuff; + + /* Only process data block that is larger than the security header */ + if (hdr_bytes < sizeof(struct quark_security_header)) + return 0; + + if (csh->csh_signature != QUARK_CSH_SIGNATURE || + csh->headersize != QUARK_SECURITY_HEADER_SIZE) + return 1; + + /* Only process data block if EFI header is included */ + if (hdr_bytes < QUARK_SECURITY_HEADER_SIZE + + sizeof(efi_capsule_header_t)) + return 0; + + pr_debug("Quark security header detected\n"); + + if (csh->rsvd_next_header != 0) { + pr_err("multiple Quark security headers not supported\n"); + return -EINVAL; + } + + *pkbuff += csh->headersize; + cap_info->total_size = csh->headersize; + + /* + * Update the first page pointer to skip over the CSH header. + */ + cap_info->pages[0] += csh->headersize; + + return 1; +} + +#define ICPU(family, model, quirk_handler) \ + { X86_VENDOR_INTEL, family, model, X86_FEATURE_ANY, \ + (unsigned long)&quirk_handler } + +static const struct x86_cpu_id efi_capsule_quirk_ids[] = { + ICPU(5, 9, qrk_capsule_setup_info), /* Intel Quark X1000 */ + { } +}; + +int efi_capsule_setup_info(struct capsule_info *cap_info, void *kbuff, + size_t hdr_bytes) +{ + int (*quirk_handler)(struct capsule_info *, void **, size_t); + const struct x86_cpu_id *id; + int ret; + + if (hdr_bytes < sizeof(efi_capsule_header_t)) + return 0; + + cap_info->total_size = 0; + + id = x86_match_cpu(efi_capsule_quirk_ids); + if (id) { + /* + * The quirk handler is supposed to return + * - a value > 0 if the setup should continue, after advancing + * kbuff as needed + * - 0 if not enough hdr_bytes are available yet + * - a negative error code otherwise + */ + quirk_handler = (typeof(quirk_handler))id->driver_data; + ret = quirk_handler(cap_info, &kbuff, hdr_bytes); + if (ret <= 0) + return ret; + } + + memcpy(&cap_info->header, kbuff, sizeof(cap_info->header)); + + cap_info->total_size += cap_info->header.imagesize; + + return __efi_capsule_setup_info(cap_info); +} + +#endif diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index 2e78b0b96d74..394db40ed374 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig @@ -112,6 +112,15 @@ config EFI_CAPSULE_LOADER Most users should say N. +config EFI_CAPSULE_QUIRK_QUARK_CSH + boolean "Add support for Quark capsules with non-standard headers" + depends on X86 && !64BIT + select EFI_CAPSULE_LOADER + default y + help + Add support for processing Quark X1000 EFI capsules, whose header + layout deviates from the layout mandated by the UEFI specification. + config EFI_TEST tristate "EFI Runtime Service Tests Support" depends on EFI