From: Takashi Iwai <tiwai@suse.de>
To: Matthew Garrett <mjg59@srcf.ucam.org>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>, joeyli <jlee@suse.com>,
Jiri Kosina <jkosina@suse.cz>,
David Howells <dhowells@redhat.com>,
Rusty Russell <rusty@rustcorp.com.au>,
linux-kernel@vger.kernel.org,
linux-security-module@vger.kernel.org, linux-efi@vger.kernel.org
Subject: [PATCH RFC 3/4] firmware: Add a signature check
Date: Mon, 05 Nov 2012 18:20:29 +0100 [thread overview]
Message-ID: <s5hd2zs9db6.wl%tiwai@suse.de> (raw)
In-Reply-To: <s5hhap49den.wl%tiwai@suse.de>
Add a feature to check the firmware signature, specified via Kconfig
CONFIG_FIRMWARE_SIG. The signature check is performed only for the
direct fw loading without udev. Also no check for built-in firmware
blobs is implemented yet.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
drivers/base/Kconfig | 6 +++++
drivers/base/firmware_class.c | 56 +++++++++++++++++++++++++++++++++++---
include/linux/firmware.h | 7 +++++
kernel/module_signing.c | 63 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 128 insertions(+), 4 deletions(-)
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index b34b5cd..3696fd7 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -145,6 +145,12 @@ config EXTRA_FIRMWARE_DIR
this option you can point it elsewhere, such as /lib/firmware/ or
some other directory containing the firmware files.
+config FIRMWARE_SIG
+ bool "Firmware signature verification"
+ depends on FW_LOADER && MODULE_SIG
+ help
+ Enable firmware signature check.
+
config DEBUG_DRIVER
bool "Driver Core verbose debug messages"
depends on DEBUG_KERNEL
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 8945f4e..575bc4c 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -36,6 +36,11 @@ MODULE_AUTHOR("Manuel Estrada Sainz");
MODULE_DESCRIPTION("Multi purpose firmware loading support");
MODULE_LICENSE("GPL");
+#ifdef CONFIG_FIRMWARE_SIG
+static bool sig_enforce;
+module_param(sig_enforce, bool, 0644);
+#endif
+
/* Builtin firmware support */
#ifdef CONFIG_FW_LOADER
@@ -287,7 +292,7 @@ static noinline long fw_file_size(struct file *file)
return st.size;
}
-static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
+static bool fw_read_file_contents(struct file *file, void **bufp, size_t *sizep)
{
long size;
char *buf;
@@ -302,11 +307,39 @@ static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf
vfree(buf);
return false;
}
- fw_buf->data = buf;
- fw_buf->size = size;
+ *bufp = buf;
+ *sizep = size;
return true;
}
+#ifdef CONFIG_FIRMWARE_SIG
+static bool verify_signature(struct firmware_buf *buf, const char *path)
+{
+ const unsigned long markerlen = sizeof(FIRMWARE_SIG_STRING) - 1;
+ struct file *file;
+ void *sig_data;
+ size_t sig_size;
+ bool success;
+
+ file = filp_open(path, O_RDONLY, 0);
+ if (IS_ERR(file))
+ return false;
+
+ success = fw_read_file_contents(file, &sig_data, &sig_size);
+ fput(file);
+ if (success) {
+ if (sig_size > markerlen &&
+ !memcmp(sig_data, FIRMWARE_SIG_STRING, markerlen))
+ success = !fw_verify_sig(buf->data, buf->size,
+ sig_data + markerlen,
+ sig_size - markerlen);
+ pr_debug("verified signature %s: %d\n", path, success);
+ vfree(sig_data);
+ }
+ return success;
+}
+#endif /* CONFIG_FIRMWARE_SIG */
+
static bool fw_get_filesystem_firmware(struct firmware_buf *buf)
{
int i;
@@ -320,8 +353,23 @@ static bool fw_get_filesystem_firmware(struct firmware_buf *buf)
file = filp_open(path, O_RDONLY, 0);
if (IS_ERR(file))
continue;
- success = fw_read_file_contents(file, buf);
+ success = fw_read_file_contents(file, &buf->data, &buf->size);
fput(file);
+#ifdef CONFIG_FIRMWARE_SIG
+ if (success) {
+ snprintf(path, PATH_MAX, "%s/%s.sig", fw_path[i],
+ buf->fw_id);
+ if (!verify_signature(buf, path)) {
+ pr_err("Invalid signature file %s\n", path);
+ if (sig_enforce) {
+ vfree(buf->data);
+ buf->data = NULL;
+ buf->size = 0;
+ success = false;
+ }
+ }
+ }
+#endif /* CONFIG_FIRMWARE_SIG */
if (success)
break;
}
diff --git a/include/linux/firmware.h b/include/linux/firmware.h
index e4279fe..2e9e457 100644
--- a/include/linux/firmware.h
+++ b/include/linux/firmware.h
@@ -79,4 +79,11 @@ static inline int uncache_firmware(const char *name)
}
#endif
+#ifdef CONFIG_FIRMWARE_SIG
+#define FIRMWARE_SIG_STRING "~Linux firmware signature~\n"
+/* defined in kernel/module_signing.c */
+int fw_verify_sig(const void *fw_data, size_t fw_size,
+ const void *sig_data, size_t sig_size);
+#endif
+
#endif
diff --git a/kernel/module_signing.c b/kernel/module_signing.c
index ea1b1df..7994452 100644
--- a/kernel/module_signing.c
+++ b/kernel/module_signing.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/err.h>
+#include <linux/export.h>
#include <crypto/public_key.h>
#include <crypto/hash.h>
#include <keys/asymmetric-type.h>
@@ -247,3 +248,65 @@ error_put_key:
pr_devel("<==%s() = %d\n", __func__, ret);
return ret;
}
+
+#ifdef CONFIG_FIRMWARE_SIG
+/*
+ * Verify the firmware signature, similar like module signature check
+ * but it's stored in a separate file
+ */
+int fw_verify_sig(const void *fw_data, size_t fw_size,
+ const void *sig_data, size_t sig_size)
+{
+ struct public_key_signature *pks;
+ struct module_signature ms;
+ struct key *key;
+ size_t sig_len;
+ int ret;
+
+ if (sig_size <= sizeof(ms))
+ return -EBADMSG;
+
+ memcpy(&ms, sig_data, sizeof(ms));
+ sig_data += sizeof(ms);
+ sig_size -= sizeof(ms);
+
+ sig_len = be32_to_cpu(ms.sig_len);
+ if (sig_size < sig_len + (size_t)ms.signer_len + ms.key_id_len)
+ return -EBADMSG;
+
+ /* For the moment, only support RSA and X.509 identifiers */
+ if (ms.algo != PKEY_ALGO_RSA ||
+ ms.id_type != PKEY_ID_X509)
+ return -ENOPKG;
+
+ if (ms.hash >= PKEY_HASH__LAST ||
+ !pkey_hash_algo[ms.hash])
+ return -ENOPKG;
+
+ key = request_asymmetric_key(sig_data, ms.signer_len,
+ sig_data + ms.signer_len, ms.key_id_len);
+ if (IS_ERR(key))
+ return PTR_ERR(key);
+
+ pks = mod_make_digest(ms.hash, fw_data, fw_size);
+ if (IS_ERR(pks)) {
+ ret = PTR_ERR(pks);
+ goto error_put_key;
+ }
+
+ sig_data += ms.signer_len + ms.key_id_len;
+ ret = mod_extract_mpi_array(pks, sig_data, sig_len);
+ if (ret < 0)
+ goto error_free_pks;
+
+ ret = verify_signature(key, pks);
+
+error_free_pks:
+ mpi_free(pks->rsa.s);
+ kfree(pks);
+error_put_key:
+ key_put(key);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(fw_verify_sig);
+#endif /* CONFIG_FIRMWARE_SIG */
--
1.8.0
next prev parent reply other threads:[~2012-11-05 17:20 UTC|newest]
Thread overview: 224+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-09-20 14:40 [RFC] Second attempt at kernel secure boot support Matthew Garrett
2012-09-20 14:40 ` [PATCH V2 01/10] Secure boot: Add new capability Matthew Garrett
2012-09-28 3:10 ` Serge Hallyn
2012-10-20 0:15 ` joeyli
2012-10-20 9:02 ` Matt Fleming
2012-09-20 14:40 ` [PATCH V2 02/10] PCI: Lock down BAR access in secure boot environments Matthew Garrett
2012-09-20 14:40 ` [PATCH V2 03/10] x86: Lock down IO port " Matthew Garrett
2012-09-20 14:40 ` [PATCH V2 04/10] ACPI: Limit access to custom_method Matthew Garrett
2012-09-20 14:41 ` [PATCH V2 05/10] asus-wmi: Restrict debugfs interface Matthew Garrett
2012-09-20 14:41 ` [PATCH V2 06/10] Restrict /dev/mem and /dev/kmem in secure boot setups Matthew Garrett
2012-09-20 14:41 ` [PATCH V2 07/10] Secure boot: Add a dummy kernel parameter that will switch on Secure Boot mode Matthew Garrett
2012-09-20 16:32 ` Greg KH
2012-09-20 17:40 ` Josh Boyer
2012-09-25 13:08 ` [PATCH V3 " Josh Boyer
2012-10-29 9:00 ` joeyli
2012-10-30 17:48 ` Josh Boyer
2012-10-30 19:27 ` joeyli
2012-09-21 8:20 ` [PATCH V2 " joeyli
2012-09-28 3:20 ` Serge Hallyn
2012-09-20 14:41 ` [PATCH V2 08/10] efi: Enable secure boot lockdown automatically when enabled in firmware Matthew Garrett
2012-09-28 3:21 ` Serge Hallyn
2012-10-22 13:22 ` Matt Fleming
2012-09-20 14:41 ` [PATCH V2 09/10] acpi: Ignore acpi_rsdp kernel parameter in a secure boot environment Matthew Garrett
2012-09-20 14:41 ` [PATCH V2 10/10] SELinux: define mapping for new Secure Boot capability Matthew Garrett
2012-09-21 22:55 ` [RFC] Second attempt at kernel secure boot support Eric W. Biederman
2012-09-22 15:21 ` Matthew Garrett
2012-10-29 7:49 ` Jiri Kosina
2012-10-29 17:41 ` Matthew Garrett
2012-10-31 14:50 ` Jiri Kosina
2012-10-31 14:54 ` Josh Boyer
2012-10-31 14:59 ` Shea Levy
2012-10-31 15:55 ` Alan Cox
2012-10-31 15:55 ` Jiri Kosina
2012-10-31 17:03 ` Alan Cox
2012-10-31 17:01 ` Shea Levy
2012-10-31 17:17 ` Alan Cox
2012-10-31 17:10 ` Matthew Garrett
2012-10-31 17:21 ` Alan Cox
2012-10-31 17:17 ` Matthew Garrett
2012-10-31 17:39 ` Alan Cox
2012-10-31 17:37 ` Matthew Garrett
2012-10-31 17:49 ` Alan Cox
2012-10-31 17:45 ` Matthew Garrett
2012-10-31 20:14 ` Oliver Neukum
2012-10-31 21:58 ` Chris Friesen
2012-10-31 22:00 ` Jiri Kosina
2012-10-31 22:19 ` Oliver Neukum
2012-11-01 9:08 ` James Bottomley
2012-11-01 9:20 ` Jiri Kosina
2012-11-01 9:38 ` James Bottomley
2012-11-01 9:45 ` Jiri Kosina
2012-11-01 9:59 ` James Bottomley
2012-11-01 10:06 ` Jiri Kosina
2012-11-01 14:29 ` Eric Paris
2012-11-01 14:42 ` James Bottomley
2012-11-01 14:49 ` Matthew Garrett
2012-11-01 15:06 ` James Bottomley
2012-11-01 15:17 ` Eric Paris
2012-11-01 16:26 ` Matthew Garrett
2012-11-01 15:06 ` Alan Cox
2012-11-01 16:29 ` Matthew Garrett
2012-11-01 16:40 ` Alan Cox
2012-11-01 14:59 ` Eric Paris
2012-11-01 15:11 ` Alan Cox
2012-11-01 15:18 ` James Bottomley
2012-11-01 17:50 ` Eric Paris
2012-11-01 21:03 ` James Bottomley
2012-11-01 21:06 ` Matthew Garrett
2012-11-01 21:14 ` James Bottomley
2012-11-01 21:18 ` Matthew Garrett
2012-11-01 21:35 ` Alan Cox
2012-11-01 21:31 ` Alan Cox
2012-11-01 21:28 ` Matthew Garrett
2012-11-01 21:37 ` Alan Cox
2012-11-01 21:34 ` Matthew Garrett
2012-11-01 21:58 ` Alan Cox
2012-11-01 21:57 ` Matthew Garrett
2012-11-02 8:49 ` Eric W. Biederman
2012-11-02 14:00 ` Matthew Garrett
2012-11-02 22:03 ` Eric W. Biederman
2012-11-02 22:19 ` Chris Friesen
2012-11-02 23:46 ` Alan Cox
2012-11-03 0:23 ` Matthew Garrett
2012-11-03 0:55 ` Alan Cox
2012-11-03 0:20 ` Matthew Garrett
2012-11-03 0:47 ` Eric W. Biederman
2012-11-03 1:03 ` Alan Cox
2012-11-03 1:43 ` Matthew Garrett
2012-11-03 16:31 ` Alan Cox
2012-11-03 16:37 ` Matthew Garrett
2012-11-03 16:37 ` Eric Paris
2012-11-03 16:42 ` Matthew Garrett
2012-11-02 17:19 ` Vivek Goyal
2012-11-01 14:46 ` Alan Cox
2012-11-01 15:04 ` Eric Paris
2012-11-01 20:27 ` Pavel Machek
2012-11-01 21:02 ` Chris Friesen
2012-11-02 15:48 ` Vivek Goyal
2012-11-02 16:54 ` Chris Friesen
2012-11-02 17:03 ` Vivek Goyal
2012-11-03 23:09 ` Jiri Kosina
2012-11-05 6:38 ` Eric W. Biederman
2012-11-05 14:40 ` Jiri Kosina
2012-11-05 15:31 ` Jiri Kosina
2012-11-05 15:37 ` Chris Friesen
2012-11-05 18:22 ` Vivek Goyal
2012-11-02 16:33 ` Pavel Machek
2012-11-02 16:52 ` James Bottomley
2012-11-02 16:54 ` Matthew Garrett
2012-11-02 17:48 ` James Bottomley
2012-11-02 17:54 ` Matthew Garrett
2012-11-02 17:57 ` James Bottomley
2012-11-02 18:04 ` Matthew Garrett
2012-11-02 19:18 ` Eric Paris
2012-11-02 23:38 ` James Bottomley
2012-11-03 0:22 ` Matthew Garrett
2012-11-03 12:03 ` James Bottomley
2012-11-03 13:46 ` Matthew Garrett
2012-11-03 22:56 ` James Bottomley
2012-11-04 4:28 ` Matthew Garrett
2012-11-04 9:14 ` James Bottomley
2012-11-04 13:52 ` Matthew Garrett
2012-11-05 6:14 ` Eric W. Biederman
2012-11-05 7:12 ` H. Peter Anvin
2012-11-05 7:24 ` Eric W. Biederman
2012-11-05 7:40 ` H. Peter Anvin
2012-11-05 8:50 ` Eric W. Biederman
2012-11-05 8:53 ` H. Peter Anvin
2012-11-05 12:38 ` Matthew Garrett
2012-11-05 13:44 ` Alan Cox
2012-11-05 13:46 ` Matthew Garrett
2012-11-05 19:16 ` Eric W. Biederman
2012-11-05 20:25 ` Matthew Garrett
2012-11-06 2:46 ` Eric W. Biederman
2012-11-06 3:12 ` Matthew Garrett
2012-11-06 3:36 ` Eric W. Biederman
2012-11-06 3:53 ` Matthew Garrett
2012-11-06 5:19 ` Eric W. Biederman
2012-11-06 5:34 ` Matthew Garrett
2012-11-06 7:56 ` Florian Weimer
2012-11-06 15:14 ` Chris Friesen
2012-11-06 15:19 ` Jiri Kosina
2012-11-06 21:51 ` Florian Weimer
2012-11-06 21:55 ` Matthew Garrett
2012-11-06 22:06 ` Florian Weimer
2012-11-06 22:31 ` Matthew Garrett
2012-11-06 22:49 ` Alan Cox
2012-11-06 22:47 ` Matthew Garrett
[not found] ` <CAMFK0gt7oAr4ArD8FmD8QE+i4g4rSTmQjbbLcjs02xwQeXGx-A@mail.gmail.com>
2012-11-07 14:55 ` Matthew Garrett
2012-11-08 10:18 ` James Courtier-Dutton
[not found] ` <CAAMvbhFF=kb8TJ4oE+40Zrx7HD1OkD0NOYj7QEZegZKGtqDm_A@mail.gmail.com>
2012-11-08 11:19 ` Alan Cox
2012-11-06 9:12 ` Alan Cox
2012-11-06 13:17 ` Matthew Garrett
2012-11-06 8:13 ` Valdis.Kletnieks
2012-11-05 8:20 ` James Bottomley
2012-11-05 12:36 ` Matthew Garrett
2012-11-04 11:53 ` Pavel Machek
2012-11-05 21:25 ` Florian Weimer
2012-11-02 14:55 ` Vivek Goyal
2012-11-01 10:12 ` Oliver Neukum
2012-10-31 17:21 ` Jiri Kosina
2012-10-31 15:56 ` Matthew Garrett
2012-10-31 17:08 ` Alan Cox
2012-10-31 17:08 ` Shea Levy
2012-10-31 16:04 ` Jiri Kosina
2012-10-31 16:10 ` Josh Boyer
2012-10-31 15:02 ` Matthew Garrett
2012-10-31 15:05 ` Shea Levy
2012-10-31 15:09 ` Matthew Garrett
2012-11-02 15:30 ` Vivek Goyal
2012-11-02 15:42 ` Matthew Garrett
2012-11-02 15:52 ` Vivek Goyal
2012-11-02 16:22 ` Jiri Kosina
2012-11-02 18:30 ` Vivek Goyal
2012-11-02 16:35 ` Shuah Khan
2012-11-06 12:51 ` Jiri Kosina
2012-11-06 13:16 ` Matthew Garrett
2012-10-31 17:28 ` Takashi Iwai
2012-10-31 17:37 ` Matthew Garrett
2012-10-31 17:44 ` Alan Cox
2012-10-31 17:44 ` Matthew Garrett
2012-10-31 18:53 ` Takashi Iwai
2012-11-01 4:21 ` joeyli
2012-11-01 13:18 ` Alan Cox
2012-11-05 17:13 ` Takashi Iwai
2012-11-05 17:18 ` [PATCH RFC 0/4] Add firmware signature file check Takashi Iwai
2012-11-05 17:19 ` [PATCH RFC 1/4] scripts/sign-file: Allow specifying hash algorithm via -a option Takashi Iwai
2012-11-05 17:19 ` [PATCH RFC 2/4] scripts/sign-file: Support firmware signing Takashi Iwai
2012-11-05 17:20 ` Takashi Iwai [this message]
2012-11-06 6:03 ` [PATCH RFC 3/4] firmware: Add a signature check Mimi Zohar
2012-11-05 17:20 ` [PATCH RFC 4/4] firmware: Install signature files automatically Takashi Iwai
2012-11-05 18:12 ` [PATCH RFC 0/4] Add firmware signature file check Takashi Iwai
2012-11-05 20:43 ` Josh Boyer
2012-11-06 6:46 ` Takashi Iwai
2012-11-06 9:20 ` Alan Cox
2012-11-06 10:05 ` Takashi Iwai
2012-11-06 2:30 ` Ming Lei
2012-11-06 5:46 ` lee joey
2012-11-06 7:03 ` Takashi Iwai
2012-11-06 7:16 ` Ming Lei
2012-11-06 7:32 ` Takashi Iwai
2012-11-06 8:04 ` Ming Lei
2012-11-06 8:18 ` Takashi Iwai
2012-11-06 10:04 ` Ming Lei
2012-11-06 10:17 ` Takashi Iwai
2012-11-06 10:40 ` Ming Lei
2012-11-06 10:53 ` Takashi Iwai
2012-11-06 11:03 ` Ming Lei
2012-11-06 11:15 ` Alan Cox
[not found] ` <CAGB3EUTrSMDhja9Gu3h7nuZX+H2_owp8MnUNwbZuCW=_GuawqQ@mail.gmail.com>
2012-11-06 7:06 ` Takashi Iwai
2012-11-06 7:30 ` Ming Lei
2012-11-08 17:35 ` [PATCH RFC v2 " Takashi Iwai
2012-11-08 17:35 ` [PATCH RFC v2 1/4] firmware: Add the firmware signing support to scripts/sign-file Takashi Iwai
2012-11-23 6:51 ` joeyli
2012-11-08 17:35 ` [PATCH RFC v2 2/4] firmware: Add -a option " Takashi Iwai
2012-11-23 6:51 ` joeyli
2012-11-08 17:35 ` [PATCH RFC v2 3/4] firmware: Add support for signature checks Takashi Iwai
2012-11-23 6:56 ` joeyli
2012-11-23 7:34 ` Takashi Iwai
2012-11-08 17:35 ` [PATCH RFC v2 4/4] firmware: Install firmware signature files automatically Takashi Iwai
2012-11-23 6:52 ` joeyli
2012-11-06 0:01 ` [PATCH RFC 0/4] Add firmware signature file check David Howells
2012-11-06 7:01 ` Takashi Iwai
2012-11-06 0:05 ` David Howells
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=s5hd2zs9db6.wl%tiwai@suse.de \
--to=tiwai@suse.de \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=dhowells@redhat.com \
--cc=jkosina@suse.cz \
--cc=jlee@suse.com \
--cc=linux-efi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=mjg59@srcf.ucam.org \
--cc=rusty@rustcorp.com.au \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®