From patchwork Thu Oct 20 11:21:24 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 78480 Delivered-To: patch@linaro.org Received: by 10.140.97.247 with SMTP id m110csp726094qge; Thu, 20 Oct 2016 04:23:22 -0700 (PDT) X-Received: by 10.99.62.205 with SMTP id l196mr196924pga.161.1476962601884; Thu, 20 Oct 2016 04:23:21 -0700 (PDT) Return-Path: Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id i10si44623098pfk.178.2016.10.20.04.23.21 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 20 Oct 2016 04:23:21 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 2001:1868:205::9 as permitted sender) client-ip=2001:1868:205::9; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 2001:1868:205::9 as permitted sender) smtp.mailfrom=linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bxBQQ-0006iy-8X; Thu, 20 Oct 2016 11:22:18 +0000 Received: from mail-qk0-x22e.google.com ([2607:f8b0:400d:c09::22e]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bxBQA-0006eu-2L for linux-arm-kernel@lists.infradead.org; Thu, 20 Oct 2016 11:22:02 +0000 Received: by mail-qk0-x22e.google.com with SMTP id o68so87634478qkf.3 for ; Thu, 20 Oct 2016 04:21:41 -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=F4/J0ZAC4sFVKqauDyL2hBNcQd9zBBf8+R2bH5f/zQg=; b=glRD6cAc0KPVOaBlF5kf6jC2QIAZjrL2wLfd4uMko2ZdhPiVSeoGhoV3aE9zaQlPwj dCApFK7xeJfExBx6XQdnFXJx3VpSkGkINh7VS8ZaP2RYo7cx+1lZictT95EFN8upqfzt 2AgFhG0IKmDdz1OuT8SFe4CuHzk7QFwbUsN84= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=F4/J0ZAC4sFVKqauDyL2hBNcQd9zBBf8+R2bH5f/zQg=; b=RyuzsIEBxPrI77+BHw7BxDB8BQhPF6xYwn8mNAmFPp9KQRusaWmfPEZmEzMc0oSr6u jSio0iy1GgaPY1Ra6CIJZY3zerAawnEUQIcddIKNHV/jJ4Hvxozra8lUFVyUEWr3o47x frEtlRzS8NwV7KUc8vl9PA0njtZdbz5dPDGr+bfg3oMbNSjpRYtLeIav6JzMyTz2NYVD 4txizacSj+u6iy4MaSYi+Ezl16vrKS3RmvRztm8Ki052VyQs+1R7oV99L0Qux3bUmqkp zZhxeLuASxcyy35FXINqYIzr0ScbVOXauXTZ0DjNhISrIpo8wQqQN+hbMfhfM5NocW97 Rxqg== X-Gm-Message-State: AA6/9Rns8rP223jlAghJChYLkMxo/DAs8MaSEu3PAayZjynjOHr2Z+CTt0otRoyNgNtizGru X-Received: by 10.194.104.98 with SMTP id gd2mr97327wjb.216.1476962500594; Thu, 20 Oct 2016 04:21:40 -0700 (PDT) Received: from localhost.localdomain ([196.66.89.52]) by smtp.gmail.com with ESMTPSA id e2sm77893018wjw.14.2016.10.20.04.21.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 20 Oct 2016 04:21:40 -0700 (PDT) From: Ard Biesheuvel To: linux-arm-kernel@lists.infradead.org, linux-efi@vger.kernel.org, mark.rutland@arm.com, matt@codeblueprint.co.uk, keescook@chromium.org Subject: [PATCH v2 1/3] efi: add support for seeding the RNG from a UEFI config table Date: Thu, 20 Oct 2016 12:21:24 +0100 Message-Id: <1476962486-18368-2-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1476962486-18368-1-git-send-email-ard.biesheuvel@linaro.org> References: <1476962486-18368-1-git-send-email-ard.biesheuvel@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20161020_042202_210187_BCB85FDE X-CRM114-Status: GOOD ( 19.11 ) X-Spam-Score: -2.7 (--) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-2.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [2607:f8b0:400d:c09:0:0:0:22e listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: tytso@mit.edu, Ard Biesheuvel MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org Specify a Linux specific UEFI configuration table that carries some random bits, and use the contents during early boot to seed the kernel's random number generator. This allows much strong random numbers to be generated early on. The entropy is fed to the kernel using add_device_randomness(), which is documented as being appropriate for being called very early. Since UEFI configuration tables may also be consumed by kexec'd kernels, register a reboot notifier that updates the seed in the table. Note that the config table could be generated by the EFI stub or by any other UEFI driver or application (e.g., GRUB), but the random seed table GUID and the associated functionality should be considered an internal kernel interface (unless it is promoted to ABI later on) Signed-off-by: Ard Biesheuvel --- drivers/firmware/efi/efi.c | 67 ++++++++++++++++++++ include/linux/efi.h | 8 +++ 2 files changed, 75 insertions(+) -- 2.7.4 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 1ac199cd75e7..47937ffd9f2f 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -48,6 +50,7 @@ struct efi __read_mostly efi = { .esrt = EFI_INVALID_TABLE_ADDR, .properties_table = EFI_INVALID_TABLE_ADDR, .mem_attr_table = EFI_INVALID_TABLE_ADDR, + .rng_seed = EFI_INVALID_TABLE_ADDR, }; EXPORT_SYMBOL(efi); @@ -438,6 +441,7 @@ static __initdata efi_config_table_type_t common_tables[] = { {EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt}, {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table}, {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table}, + {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed}, {NULL_GUID, NULL, NULL}, }; @@ -499,6 +503,29 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz, pr_cont("\n"); set_bit(EFI_CONFIG_TABLES, &efi.flags); + if (efi.rng_seed != EFI_INVALID_TABLE_ADDR) { + struct linux_efi_random_seed *seed; + u32 size = 0; + + seed = early_memremap(efi.rng_seed, sizeof(*seed)); + if (seed != NULL) { + size = seed->size; + early_memunmap(seed, sizeof(*seed)); + } else { + pr_err("Could not map UEFI random seed!\n"); + } + if (size > 0) { + seed = early_memremap(efi.rng_seed, + sizeof(*seed) + size); + if (seed != NULL) { + add_device_randomness(seed->bits, seed->size); + early_memunmap(seed, sizeof(*seed) + size); + } else { + pr_err("Could not map UEFI random seed!\n"); + } + } + } + /* Parse the EFI Properties table if it exists */ if (efi.properties_table != EFI_INVALID_TABLE_ADDR) { efi_properties_table_t *tbl; @@ -822,3 +849,43 @@ int efi_status_to_err(efi_status_t status) return err; } + +#ifdef CONFIG_KEXEC +static int update_efi_random_seed(struct notifier_block *nb, + unsigned long code, void *unused) +{ + struct linux_efi_random_seed *seed; + u32 size = 0; + + seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB); + if (seed != NULL) { + size = seed->size; + memunmap(seed); + } else { + pr_err("Could not map UEFI random seed!\n"); + } + if (size > 0) { + seed = memremap(efi.rng_seed, sizeof(*seed) + size, + MEMREMAP_WB); + if (seed != NULL) { + get_random_bytes(seed->bits, seed->size); + memunmap(seed); + } else { + pr_err("Could not map UEFI random seed!\n"); + } + } + return NOTIFY_DONE; +} + +static struct notifier_block efi_random_seed_nb = { + .notifier_call = update_efi_random_seed, +}; + +static int register_update_efi_random_seed(void) +{ + if (efi.rng_seed == EFI_INVALID_TABLE_ADDR) + return 0; + return register_reboot_notifier(&efi_random_seed_nb); +} +late_initcall(register_update_efi_random_seed); +#endif diff --git a/include/linux/efi.h b/include/linux/efi.h index 2d089487d2da..85e28b138cdd 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -599,6 +599,7 @@ void efi_native_runtime_setup(void); */ #define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95) #define LINUX_EFI_LOADER_ENTRY_GUID EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f) +#define LINUX_EFI_RANDOM_SEED_TABLE_GUID EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2, 0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b) typedef struct { efi_guid_t guid; @@ -872,6 +873,7 @@ extern struct efi { unsigned long esrt; /* ESRT table */ unsigned long properties_table; /* properties table */ unsigned long mem_attr_table; /* memory attributes table */ + unsigned long rng_seed; /* UEFI firmware random seed */ efi_get_time_t *get_time; efi_set_time_t *set_time; efi_get_wakeup_time_t *get_wakeup_time; @@ -1493,4 +1495,10 @@ efi_status_t efi_exit_boot_services(efi_system_table_t *sys_table, struct efi_boot_memmap *map, void *priv, efi_exit_boot_map_processing priv_func); + +struct linux_efi_random_seed { + u32 size; + u8 bits[]; +}; + #endif /* _LINUX_EFI_H */