Add many new plugins to support for the Host Security ID

The HSI specification is currently incomplete and in active development.

Sample output for my Lenovo P50 Laptop:

    Host Security ID: HSI:2+UA!

    HSI-1
    ✔  UEFI dbx: OK
    ✔  TPM: v2.0
    ✔  SPI: Write disabled
    ✔  SPI: Lock enabled
    ✔  SPI: SMM required
    ✔  UEFI Secure Boot: Enabled

    HSI-2
    ✔  TPM Reconstruction: Matched PCR0 reading

    HSI-3
    ✘  Linux Kernel S3 Sleep: Deep sleep available

    HSI-4
    ✘  Intel CET: Unavailable

    Runtime Suffix -U
    ✔  Firmware Updates: Newest release is 8 months old

    Runtime Suffix -A
    ✔  Firmware Attestation: OK

    Runtime Suffix -!
    ✔  fwupd plugins: OK
    ✔  Linux Kernel: OK
    ✔  Linux Kernel: Locked down
    ✘  Linux Swap: Not encrypted
This commit is contained in:
Richard Hughes 2020-05-01 15:51:44 +01:00
parent f58ac7316c
commit c1eda7d516
40 changed files with 1279 additions and 62 deletions

View File

@ -329,6 +329,8 @@ mkdir -p --mode=0700 $RPM_BUILD_ROOT%{_localstatedir}/lib/fwupd/gnupg
/usr/lib/udev/rules.d/*.rules
/usr/lib/systemd/system-shutdown/fwupd.shutdown
%dir %{_libdir}/fwupd-plugins-3
%{_libdir}/fwupd-plugins-3/libfu_plugin_acpi_dmar.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_acpi_facp.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_altos.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_amt.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_ata.so
@ -352,7 +354,11 @@ mkdir -p --mode=0700 $RPM_BUILD_ROOT%{_localstatedir}/lib/fwupd/gnupg
%endif
%{_libdir}/fwupd-plugins-3/libfu_plugin_fresco_pd.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_jabra.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_linux_lockdown.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_linux_sleep.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_linux_spi_lpc.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_linux_swap.so
%{_libdir}/fwupd-plugins-3/libfu_plugin_linux_tainted.so
%if 0%{?have_modem_manager}
%{_libdir}/fwupd-plugins-3/libfu_plugin_modem_manager.so
%endif

View File

@ -0,0 +1,8 @@
DMA Protection
==============
Introduction
------------
This plugin checks if DMA remapping for Thunderbolt devices is available. The
result will be stored in an security attribute for HSI.

View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include <string.h>
#include "fu-common.h"
#include "fu-acpi-dmar.h"
struct _FuAcpiDmar {
GObject parent_instance;
gboolean opt_in;
};
G_DEFINE_TYPE (FuAcpiDmar, fu_acpi_dmar, G_TYPE_OBJECT)
#define DMAR_DMA_CTRL_PLATFORM_OPT_IN_FLAG 2
FuAcpiDmar *
fu_acpi_dmar_new (GBytes *blob, GError **error)
{
FuAcpiDmar *self = g_object_new (FU_TYPE_ACPI_DMAR, NULL);
gchar creator_id[5] = { '\0' };
gchar oem_table_id[9] = { '\0' };
gchar signature[5] = { '\0' };
gsize bufsz = 0;
guint8 flags = 0;
const guint8 *buf = g_bytes_get_data (blob, &bufsz);
/* parse table */
if (!fu_memcpy_safe ((guint8 *) signature, sizeof(signature), 0x0, /* dst */
buf, bufsz, 0x00, /* src */
sizeof(signature) - 1, error))
return FALSE;
if (strcmp (signature, "DMAR") != 0) {
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
"Not a DMAR table, got %s",
signature);
return FALSE;
}
if (!fu_memcpy_safe ((guint8 *) oem_table_id, sizeof(oem_table_id), 0x0,/* dst */
buf, bufsz, 0x10, /* src */
sizeof(oem_table_id) - 1, error))
return FALSE;
g_debug ("OemTableId: %s", oem_table_id);
if (!fu_memcpy_safe ((guint8 *) creator_id, sizeof(creator_id), 0x0, /* dst */
buf, bufsz, 0x1c, /* src */
sizeof(creator_id) - 1, error))
return FALSE;
g_debug ("CreatorId: %s", creator_id);
if (!fu_memcpy_safe (&flags, sizeof(flags), 0x0, /* dst */
buf, bufsz, 0x25, /* src */
sizeof(flags), error))
return FALSE;
g_debug ("Flags: 0x%02x", flags);
self->opt_in = (flags & DMAR_DMA_CTRL_PLATFORM_OPT_IN_FLAG) > 0;
return self;
}
gboolean
fu_acpi_dmar_get_opt_in (FuAcpiDmar *self)
{
g_return_val_if_fail (FU_IS_ACPI_DMAR (self), FALSE);
return self->opt_in;
}
static void
fu_acpi_dmar_class_init (FuAcpiDmarClass *klass)
{
}
static void
fu_acpi_dmar_init (FuAcpiDmar *self)
{
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
#include <gio/gio.h>
#define FU_TYPE_ACPI_DMAR (fu_acpi_dmar_get_type ())
G_DECLARE_FINAL_TYPE (FuAcpiDmar, fu_acpi_dmar, FU, ACPI_DMAR, GObject)
FuAcpiDmar *fu_acpi_dmar_new (GBytes *blob,
GError **error);
gboolean fu_acpi_dmar_get_opt_in (FuAcpiDmar *self);

View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include "fu-plugin-vfuncs.h"
#include "fu-hash.h"
#include "fu-acpi-dmar.h"
void
fu_plugin_init (FuPlugin *plugin)
{
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
}
void
fu_plugin_add_security_attrs (FuPlugin *plugin, FuSecurityAttrs *attrs)
{
g_autofree gchar *fn = NULL;
g_autofree gchar *path = NULL;
g_autoptr(FuAcpiDmar) dmar = NULL;
g_autoptr(FwupdSecurityAttr) attr = NULL;
g_autoptr(GBytes) blob = NULL;
g_autoptr(GError) error_local = NULL;
/* only Intel */
if (!fu_common_is_cpu_intel ())
return;
/* create attr */
attr = fwupd_security_attr_new ("org.uefi.ACPI.Dmar");
fwupd_security_attr_set_level (attr, FWUPD_SECURITY_ATTR_LEVEL_THEORETICAL);
fwupd_security_attr_set_name (attr, "Pre-boot kernel DMA protection");
fu_security_attrs_append (attrs, attr);
/* load DMAR table */
path = fu_common_get_path (FU_PATH_KIND_ACPI_TABLES);
fn = g_build_filename (path, "DMAR", NULL);
blob = fu_common_get_contents_bytes (fn, &error_local);
if (blob == NULL) {
g_warning ("failed to load %s: %s", fn, error_local->message);
fwupd_security_attr_set_result (attr, "Could not load DMAR");
return;
}
dmar = fu_acpi_dmar_new (blob, &error_local);
if (dmar == NULL) {
g_warning ("failed to parse %s: %s", fn, error_local->message);
fwupd_security_attr_set_result (attr, "Could not parse DMAR");
return;
}
if (!fu_acpi_dmar_get_opt_in (dmar)) {
fwupd_security_attr_set_result (attr, "Unavailable");
return;
}
/* success */
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS);
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include <fwupd.h>
#include "fu-common.h"
#include "fu-acpi-dmar.h"
static void
fu_acpi_dmar_opt_in_func (void)
{
g_autoptr(FuAcpiDmar) dmar = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GBytes) blob = NULL;
g_autofree gchar *fn = NULL;
fn = g_build_filename (TESTDATADIR, "DMAR", NULL);
blob = fu_common_get_contents_bytes (fn, &error);
g_assert_no_error (error);
g_assert_nonnull (blob);
dmar = fu_acpi_dmar_new (blob, &error);
g_assert_no_error (error);
g_assert_nonnull (dmar);
g_assert_true (fu_acpi_dmar_get_opt_in (dmar));
}
static void
fu_acpi_dmar_opt_out_func (void)
{
g_autoptr(FuAcpiDmar) dmar = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GBytes) blob = NULL;
g_autofree gchar *fn = NULL;
fn = g_build_filename (TESTDATADIR, "DMAR-OPTOUT", NULL);
blob = fu_common_get_contents_bytes (fn, &error);
g_assert_no_error (error);
g_assert_nonnull (blob);
dmar = fu_acpi_dmar_new (blob, &error);
g_assert_no_error (error);
g_assert_nonnull (dmar);
g_assert_false (fu_acpi_dmar_get_opt_in (dmar));
}
int
main (int argc, char **argv)
{
g_test_init (&argc, &argv, NULL);
/* only critical and error are fatal */
g_log_set_fatal_mask (NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL);
g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
/* tests go here */
g_test_add_func ("/acpi-dmar/opt-in", fu_acpi_dmar_opt_in_func);
g_test_add_func ("/acpi-dmar/opt-out", fu_acpi_dmar_opt_out_func);
return g_test_run ();
}

View File

@ -0,0 +1,51 @@
cargs = ['-DG_LOG_DOMAIN="FuPluginAcpiDmar"']
shared_module('fu_plugin_acpi_dmar',
fu_hash,
sources : [
'fu-plugin-acpi-dmar.c',
'fu-acpi-dmar.c',
],
include_directories : [
root_incdir,
fwupd_incdir,
fwupdplugin_incdir,
],
install : true,
install_dir: plugin_dir,
link_with : [
fwupd,
fwupdplugin,
],
c_args : cargs,
dependencies : [
plugin_deps,
],
)
if get_option('tests')
testdatadir = join_paths(meson.current_source_dir(), 'tests')
cargs += '-DTESTDATADIR="' + testdatadir + '"'
e = executable(
'acpi-dmar-self-test',
fu_hash,
sources : [
'fu-self-test.c',
'fu-acpi-dmar.c',
],
include_directories : [
root_incdir,
fwupd_incdir,
fwupdplugin_incdir,
],
dependencies : [
plugin_deps,
],
link_with : [
fwupd,
fwupdplugin,
],
c_args : cargs,
)
test('acpi-dmar-self-test', e)
endif

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,8 @@
ACPI FACP
=========
Introduction
------------
This plugin checks if S2I sleep is available. The result will be stored in an
security attribute for HSI.

View File

@ -0,0 +1,54 @@
/*
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include <string.h>
#include "fu-common.h"
#include "fu-acpi-facp.h"
struct _FuAcpiFacp {
GObject parent_instance;
gboolean get_s2i;
};
G_DEFINE_TYPE (FuAcpiFacp, fu_acpi_facp, G_TYPE_OBJECT)
#define LOW_POWER_S0_IDLE_CAPABLE (1 << 21)
FuAcpiFacp *
fu_acpi_facp_new (GBytes *blob, GError **error)
{
FuAcpiFacp *self = g_object_new (FU_TYPE_ACPI_FACP, NULL);
gsize bufsz = 0;
guint32 flags = 0;
const guint8 *buf = g_bytes_get_data (blob, &bufsz);
/* parse table */
if (!fu_common_read_uint32_safe (buf, bufsz, 0x70, &flags, G_LITTLE_ENDIAN, error))
return FALSE;
g_debug ("Flags: 0x%04x", flags);
self->get_s2i = (flags & LOW_POWER_S0_IDLE_CAPABLE) > 0;
return self;
}
gboolean
fu_acpi_facp_get_s2i (FuAcpiFacp *self)
{
g_return_val_if_fail (FU_IS_ACPI_FACP (self), FALSE);
return self->get_s2i;
}
static void
fu_acpi_facp_class_init (FuAcpiFacpClass *klass)
{
}
static void
fu_acpi_facp_init (FuAcpiFacp *self)
{
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
#include <gio/gio.h>
#define FU_TYPE_ACPI_FACP (fu_acpi_facp_get_type ())
G_DECLARE_FINAL_TYPE (FuAcpiFacp, fu_acpi_facp, FU, ACPI_FACP, GObject)
FuAcpiFacp *fu_acpi_facp_new (GBytes *blob,
GError **error);
gboolean fu_acpi_facp_get_s2i (FuAcpiFacp *self);

View File

@ -0,0 +1,57 @@
/*
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include "fu-plugin-vfuncs.h"
#include "fu-hash.h"
#include "fu-acpi-facp.h"
void
fu_plugin_init (FuPlugin *plugin)
{
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
}
void
fu_plugin_add_security_attrs (FuPlugin *plugin, FuSecurityAttrs *attrs)
{
g_autofree gchar *fn = NULL;
g_autofree gchar *path = NULL;
g_autoptr(FuAcpiFacp) facp = NULL;
g_autoptr(FwupdSecurityAttr) attr = NULL;
g_autoptr(GBytes) blob = NULL;
g_autoptr(GError) error_local = NULL;
/* create attr */
attr = fwupd_security_attr_new ("org.uefi.ACPI.Facp");
fwupd_security_attr_set_level (attr, FWUPD_SECURITY_ATTR_LEVEL_THEORETICAL);
fwupd_security_attr_set_name (attr, "Suspend2Idle");
fu_security_attrs_append (attrs, attr);
/* load FACP table */
path = fu_common_get_path (FU_PATH_KIND_ACPI_TABLES);
fn = g_build_filename (path, "FACP", NULL);
blob = fu_common_get_contents_bytes (fn, &error_local);
if (blob == NULL) {
g_warning ("failed to load %s: %s", fn, error_local->message);
fwupd_security_attr_set_result (attr, "Could not load FACP");
return;
}
facp = fu_acpi_facp_new (blob, &error_local);
if (facp == NULL) {
g_warning ("failed to parse %s: %s", fn, error_local->message);
fwupd_security_attr_set_result (attr, "Could not parse FACP");
return;
}
if (!fu_acpi_facp_get_s2i (facp)) {
fwupd_security_attr_set_result (attr, "Default set as suspend-to-ram (S3)");
return;
}
/* success */
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS);
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include <fwupd.h>
#include "fu-common.h"
#include "fu-acpi-facp.h"
static void
fu_acpi_facp_s2i_disabled_func (void)
{
g_autofree gchar *fn = NULL;
g_autoptr(FuAcpiFacp) facp = NULL;
g_autoptr(GBytes) blob = NULL;
g_autoptr(GError) error = NULL;
fn = g_build_filename (TESTDATADIR, "FACP", NULL);
blob = fu_common_get_contents_bytes (fn, &error);
g_assert_no_error (error);
g_assert_nonnull (blob);
facp = fu_acpi_facp_new (blob, &error);
g_assert_no_error (error);
g_assert_nonnull (facp);
g_assert_false (fu_acpi_facp_get_s2i (facp));
}
static void
fu_acpi_facp_s2i_enabled_func (void)
{
g_autofree gchar *fn = NULL;
g_autoptr(FuAcpiFacp) facp = NULL;
g_autoptr(GBytes) blob = NULL;
g_autoptr(GError) error = NULL;
fn = g_build_filename (TESTDATADIR, "FACP-S2I", NULL);
blob = fu_common_get_contents_bytes (fn, &error);
g_assert_no_error (error);
g_assert_nonnull (blob);
facp = fu_acpi_facp_new (blob, &error);
g_assert_no_error (error);
g_assert_nonnull (facp);
g_assert_true (fu_acpi_facp_get_s2i (facp));
}
int
main (int argc, char **argv)
{
g_test_init (&argc, &argv, NULL);
/* only critical and error are fatal */
g_log_set_fatal_mask (NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL);
g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
/* tests go here */
g_test_add_func ("/acpi-facp/s2i{disabled}", fu_acpi_facp_s2i_disabled_func);
g_test_add_func ("/acpi-facp/s2i{enabled}", fu_acpi_facp_s2i_enabled_func);
return g_test_run ();
}

View File

@ -0,0 +1,51 @@
cargs = ['-DG_LOG_DOMAIN="FuPluginAcpiFacp"']
shared_module('fu_plugin_acpi_facp',
fu_hash,
sources : [
'fu-plugin-acpi-facp.c',
'fu-acpi-facp.c',
],
include_directories : [
root_incdir,
fwupd_incdir,
fwupdplugin_incdir,
],
install : true,
install_dir: plugin_dir,
link_with : [
fwupd,
fwupdplugin,
],
c_args : cargs,
dependencies : [
plugin_deps,
],
)
if get_option('tests')
testdatadir = join_paths(meson.current_source_dir(), 'tests')
cargs += '-DTESTDATADIR="' + testdatadir + '"'
e = executable(
'acpi-facp-self-test',
fu_hash,
sources : [
'fu-self-test.c',
'fu-acpi-facp.c',
],
include_directories : [
root_incdir,
fwupd_incdir,
fwupdplugin_incdir,
],
dependencies : [
plugin_deps,
],
link_with : [
fwupd,
fwupdplugin,
],
c_args : cargs,
)
test('acpi-facp-self-test', e)
endif

Binary file not shown.

Binary file not shown.

View File

@ -10,23 +10,29 @@
#include "fu-hash.h"
#include "fu-cpu-device.h"
struct FuPluginData {
gboolean has_cet;
};
void
fu_plugin_init (FuPlugin *plugin)
{
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_plugin_alloc_data (plugin, sizeof (FuPluginData));
}
gboolean
fu_plugin_coldplug (FuPlugin *plugin, GError **error)
{
FuPluginData *data = fu_plugin_get_data (plugin);
gsize length;
g_autofree gchar *data = NULL;
g_autofree gchar *buf = NULL;
g_auto(GStrv) lines = NULL;
if (!g_file_get_contents ("/proc/cpuinfo", &data, &length, error))
if (!g_file_get_contents ("/proc/cpuinfo", &buf, &length, error))
return FALSE;
lines = g_strsplit (data, "\n\n", 0);
lines = g_strsplit (buf, "\n\n", 0);
for (guint i = 0; lines[i] != NULL; i++) {
g_autoptr(FuCpuDevice) dev = NULL;
if (strlen (lines[i]) == 0)
@ -34,8 +40,36 @@ fu_plugin_coldplug (FuPlugin *plugin, GError **error)
dev = fu_cpu_device_new (lines[i]);
if (!fu_device_setup (FU_DEVICE (dev), error))
return FALSE;
if (fu_cpu_device_has_shstk (dev) &&
fu_cpu_device_has_ibt (dev))
data->has_cet = TRUE;
fu_plugin_device_add (plugin, FU_DEVICE (dev));
}
return TRUE;
}
void
fu_plugin_add_security_attrs (FuPlugin *plugin, FuSecurityAttrs *attrs)
{
FuPluginData *data = fu_plugin_get_data (plugin);
g_autoptr(FwupdSecurityAttr) attr = NULL;
/* only Intel */
if (!fu_common_is_cpu_intel ())
return;
/* create attr */
attr = fwupd_security_attr_new ("com.intel.CET");
fwupd_security_attr_set_level (attr, FWUPD_SECURITY_ATTR_LEVEL_SYSTEM_PROTECTION);
fwupd_security_attr_set_name (attr, "Intel CET");
fu_security_attrs_append (attrs, attr);
/* check for CET */
if (!data->has_cet) {
fwupd_security_attr_set_result (attr, "Unavailable");
return;
}
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS);
fwupd_security_attr_set_result (attr, "SHSTK+IBT");
}

View File

@ -0,0 +1,8 @@
Linux Kernel Lockdown
=====================
Introduction
------------
This plugin checks if the currently running kernel is locked down. The result
will be stored in an security attribute for HSI.

View File

@ -0,0 +1,94 @@
/*
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include "fu-plugin-vfuncs.h"
#include "fu-hash.h"
struct FuPluginData {
GFile *file;
GFileMonitor *monitor;
};
void
fu_plugin_init (FuPlugin *plugin)
{
fu_plugin_alloc_data (plugin, sizeof (FuPluginData));
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
}
void
fu_plugin_destroy (FuPlugin *plugin)
{
FuPluginData *data = fu_plugin_get_data (plugin);
if (data->file != NULL)
g_object_unref (data->file);
if (data->monitor != NULL)
g_object_unref (data->monitor);
}
static void
fu_plugin_linux_lockdown_changed_cb (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
gpointer user_data)
{
FuPlugin *plugin = FU_PLUGIN (user_data);
fu_plugin_security_changed (plugin);
}
gboolean
fu_plugin_startup (FuPlugin *plugin, GError **error)
{
FuPluginData *data = fu_plugin_get_data (plugin);
g_autofree gchar *path = NULL;
g_autofree gchar *fn = NULL;
path = fu_common_get_path (FU_PATH_KIND_SYSFSDIR_SECURITY);
fn = g_build_filename (path, "lockdown", NULL);
data->file = g_file_new_for_path (fn);
data->monitor = g_file_monitor (data->file, G_FILE_MONITOR_NONE, NULL, error);
if (data->monitor == NULL)
return FALSE;
g_signal_connect (data->monitor, "changed",
G_CALLBACK (fu_plugin_linux_lockdown_changed_cb), plugin);
return TRUE;
}
void
fu_plugin_add_security_attrs (FuPlugin *plugin, FuSecurityAttrs *attrs)
{
FuPluginData *data = fu_plugin_get_data (plugin);
gsize bufsz = 0;
g_autofree gchar *buf = NULL;
g_autoptr(FwupdSecurityAttr) attr = NULL;
g_autoptr(GError) error_local = NULL;
/* create attr */
attr = fwupd_security_attr_new ("org.kernel.CheckLockdown");
fwupd_security_attr_set_name (attr, "Linux Kernel");
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_RUNTIME_ISSUE);
fu_security_attrs_append (attrs, attr);
/* load file */
if (!g_file_load_contents (data->file, NULL, &buf, &bufsz, NULL, &error_local)) {
g_autofree gchar *fn = g_file_get_path (data->file);
g_warning ("could not open %s: %s", fn, error_local->message);
fwupd_security_attr_set_result (attr, "Could not open file");
return;
}
if (g_strstr_len (buf, bufsz, "[integrity]") == NULL &&
g_strstr_len (buf, bufsz, "[confidentiality]") == NULL) {
fwupd_security_attr_set_result (attr, "Not locked down");
return;
}
/* success */
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS);
fwupd_security_attr_set_result (attr, "Locked down");
}

View File

@ -0,0 +1,23 @@
cargs = ['-DG_LOG_DOMAIN="FuPluginLinuxLockdown"']
shared_module('fu_plugin_linux_lockdown',
fu_hash,
sources : [
'fu-plugin-linux-lockdown.c',
],
include_directories : [
root_incdir,
fwupd_incdir,
fwupdplugin_incdir,
],
install : true,
install_dir: plugin_dir,
link_with : [
fwupd,
fwupdplugin,
],
c_args : cargs,
dependencies : [
plugin_deps,
],
)

View File

@ -0,0 +1,8 @@
Linux Kernel Sleep
==================
Introduction
------------
This plugin checks if s3 sleep is available. The result will be stored in an
security attribute for HSI.

View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include "fu-plugin-vfuncs.h"
#include "fu-hash.h"
void
fu_plugin_init (FuPlugin *plugin)
{
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
}
void
fu_plugin_add_security_attrs (FuPlugin *plugin, FuSecurityAttrs *attrs)
{
gsize bufsz = 0;
g_autofree gchar *buf = NULL;
g_autoptr(FwupdSecurityAttr) attr = NULL;
g_autoptr(GError) error_local = NULL;
g_autoptr(GFile) file = g_file_new_for_path ("/sys/power/mem_sleep");
/* create attr */
attr = fwupd_security_attr_new ("org.kernel.CheckS3Sleep");
fwupd_security_attr_set_level (attr, FWUPD_SECURITY_ATTR_LEVEL_THEORETICAL);
fwupd_security_attr_set_name (attr, "Linux Kernel S3 Sleep");
fu_security_attrs_append (attrs, attr);
/* load file */
if (!g_file_load_contents (file, NULL, &buf, &bufsz, NULL, &error_local)) {
g_autofree gchar *fn = g_file_get_path (file);
g_warning ("could not open %s: %s", fn, error_local->message);
fwupd_security_attr_set_result (attr, "Deep sleep status unavailable");
return;
}
if (g_strstr_len (buf, bufsz, "[deep]") != NULL) {
fwupd_security_attr_set_result (attr, "System configured to suspend-to-ram (S3)");
return;
}
/* success */
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS);
}

View File

@ -0,0 +1,23 @@
cargs = ['-DG_LOG_DOMAIN="FuPluginLinuxSleep"']
shared_module('fu_plugin_linux_sleep',
fu_hash,
sources : [
'fu-plugin-linux-sleep.c',
],
include_directories : [
root_incdir,
fwupd_incdir,
fwupdplugin_incdir,
],
install : true,
install_dir: plugin_dir,
link_with : [
fwupd,
fwupdplugin,
],
c_args : cargs,
dependencies : [
plugin_deps,
],
)

View File

@ -0,0 +1,8 @@
Linux SPI LPC
=============
Introduction
------------
This plugin checks if the system SPI chip is locked. The result will be stored
in an security attribute for HSI.

View File

@ -0,0 +1,139 @@
/*
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include "fu-plugin-vfuncs.h"
#include "fu-hash.h"
#define FU_PLUGIN_LINUX_SPI_LPC_SYSFS_DIR "/sys/kernel/security/spi"
void
fu_plugin_init (FuPlugin *plugin)
{
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
}
static void
fu_plugin_add_security_attr_bioswe (FuPlugin *plugin, FuSecurityAttrs *attrs)
{
gsize bufsz = 0;
g_autofree gchar *buf = NULL;
g_autofree gchar *fn = NULL;
g_autoptr(FwupdSecurityAttr) attr = NULL;
g_autoptr(GError) error_local = NULL;
/* create attr */
attr = fwupd_security_attr_new ("org.kernel.BIOSWE");
fwupd_security_attr_set_level (attr, FWUPD_SECURITY_ATTR_LEVEL_CRITICAL);
fwupd_security_attr_set_name (attr, "SPI");
fu_security_attrs_append (attrs, attr);
/* load file */
fn = g_build_filename (FU_PLUGIN_LINUX_SPI_LPC_SYSFS_DIR, "bioswe", NULL);
if (!g_file_get_contents (fn, &buf, &bufsz, &error_local)) {
g_warning ("could not open %s: %s", fn, error_local->message);
fwupd_security_attr_set_result (attr, "Could not open file");
return;
}
if (g_strcmp0 (buf, "0\n") != 0) {
fwupd_security_attr_set_result (attr, "Write enabled");
return;
}
/* success */
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS);
fwupd_security_attr_set_result (attr, "Write disabled");
}
static void
fu_plugin_add_security_attr_ble (FuPlugin *plugin, FuSecurityAttrs *attrs)
{
gsize bufsz = 0;
g_autofree gchar *buf = NULL;
g_autofree gchar *fn = NULL;
g_autoptr(FwupdSecurityAttr) attr = NULL;
g_autoptr(GError) error_local = NULL;
/* create attr */
attr = fwupd_security_attr_new ("org.kernel.BLE");
fwupd_security_attr_set_level (attr, FWUPD_SECURITY_ATTR_LEVEL_CRITICAL);
fwupd_security_attr_set_name (attr, "SPI");
fu_security_attrs_append (attrs, attr);
/* load file */
fn = g_build_filename (FU_PLUGIN_LINUX_SPI_LPC_SYSFS_DIR, "ble", NULL);
if (!g_file_get_contents (fn, &buf, &bufsz, &error_local)) {
g_warning ("could not open %s: %s", fn, error_local->message);
fwupd_security_attr_set_result (attr, "Could not open file");
return;
}
if (g_strcmp0 (buf, "1\n") != 0) {
fwupd_security_attr_set_result (attr, "Lock disabled");
return;
}
/* success */
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS);
fwupd_security_attr_set_result (attr, "Lock enabled");
}
static void
fu_plugin_add_security_attr_smm_bwp (FuPlugin *plugin, FuSecurityAttrs *attrs)
{
gsize bufsz = 0;
g_autofree gchar *buf = NULL;
g_autofree gchar *fn = NULL;
g_autoptr(FwupdSecurityAttr) attr = NULL;
g_autoptr(GError) error_local = NULL;
/* create attr */
attr = fwupd_security_attr_new ("org.kernel.SMM_BWP");
fwupd_security_attr_set_level (attr, FWUPD_SECURITY_ATTR_LEVEL_CRITICAL);
fwupd_security_attr_set_name (attr, "BIOS region of SPI");
fu_security_attrs_append (attrs, attr);
/* load file */
fn = g_build_filename (FU_PLUGIN_LINUX_SPI_LPC_SYSFS_DIR, "smm_bwp", NULL);
if (!g_file_get_contents (fn, &buf, &bufsz, &error_local)) {
g_warning ("could not open %s: %s", fn, error_local->message);
fwupd_security_attr_set_result (attr, "Could not open file");
return;
}
if (g_strcmp0 (buf, "1\n") != 0) {
fwupd_security_attr_set_result (attr, "Writable by OS");
return;
}
/* success */
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS);
fwupd_security_attr_set_result (attr, "Writable only through BIOS");
}
void
fu_plugin_add_security_attrs (FuPlugin *plugin, FuSecurityAttrs *attrs)
{
/* only Intel */
if (!fu_common_is_cpu_intel ())
return;
/* maybe the kernel module does not exist */
if (!g_file_test (FU_PLUGIN_LINUX_SPI_LPC_SYSFS_DIR, G_FILE_TEST_IS_DIR)) {
g_autoptr(FwupdSecurityAttr) attr = NULL;
attr = fwupd_security_attr_new ("org.kernel.BIOSWE");
fwupd_security_attr_set_level (attr, FWUPD_SECURITY_ATTR_LEVEL_CRITICAL);
fwupd_security_attr_set_name (attr, "SPI");
fwupd_security_attr_set_result (attr, "Kernel support not present");
fu_security_attrs_append (attrs, attr);
return;
}
/* look for the three files in sysfs */
fu_plugin_add_security_attr_bioswe (plugin, attrs);
fu_plugin_add_security_attr_ble (plugin, attrs);
fu_plugin_add_security_attr_smm_bwp (plugin, attrs);
}

View File

@ -0,0 +1,23 @@
cargs = ['-DG_LOG_DOMAIN="FuPluginLinuxSpiLpc"']
shared_module('fu_plugin_linux_spi_lpc',
fu_hash,
sources : [
'fu-plugin-linux-spi-lpc.c',
],
include_directories : [
root_incdir,
fwupd_incdir,
fwupdplugin_incdir,
],
install : true,
install_dir: plugin_dir,
link_with : [
fwupd,
fwupdplugin,
],
c_args : cargs,
dependencies : [
plugin_deps,
],
)

View File

@ -5,4 +5,4 @@ Introduction
------------
This plugin checks if the currently available swap partitions and files are
all encrypted.
all encrypted. The result will be stored in an security attribute for HSI.

View File

@ -11,6 +11,7 @@
#include "fu-linux-swap.h"
struct FuPluginData {
GFile *file;
GFileMonitor *monitor;
};
@ -25,6 +26,8 @@ void
fu_plugin_destroy (FuPlugin *plugin)
{
FuPluginData *data = fu_plugin_get_data (plugin);
if (data->file != NULL)
g_object_unref (data->file);
if (data->monitor != NULL)
g_object_unref (data->monitor);
}
@ -36,41 +39,72 @@ fu_plugin_linux_swap_changed_cb (GFileMonitor *monitor,
GFileMonitorEvent event_type,
gpointer user_data)
{
g_debug ("swap changed");
FuPlugin *plugin = FU_PLUGIN (user_data);
fu_plugin_security_changed (plugin);
}
gboolean
fu_plugin_startup (FuPlugin *plugin, GError **error)
{
FuPluginData *data = fu_plugin_get_data (plugin);
gsize bufsz = 0;
g_autofree gchar *buf = NULL;
g_autofree gchar *fn = NULL;
g_autofree gchar *procfs = NULL;
g_autoptr(FuLinuxSwap) swap = NULL;
g_autoptr(GFile) file = NULL;
procfs = fu_common_get_path (FU_PATH_KIND_PROCFS);
fn = g_build_filename (procfs, "swaps", NULL);
file = g_file_new_for_path (fn);
data->monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, error);
data->file = g_file_new_for_path (fn);
data->monitor = g_file_monitor (data->file, G_FILE_MONITOR_NONE, NULL, error);
if (data->monitor == NULL)
return FALSE;
g_signal_connect (data->monitor, "changed",
G_CALLBACK (fu_plugin_linux_swap_changed_cb), plugin);
/* load list of linux_swaps */
if (!g_file_get_contents (fn, &buf, &bufsz, error)) {
g_prefix_error (error, "could not open %s: ", fn);
return FALSE;
}
swap = fu_linux_swap_new (buf, bufsz, error);
if (swap == NULL) {
g_prefix_error (error, "could not parse %s: ", fn);
return FALSE;
}
g_debug ("swap %s and %s",
fu_linux_swap_get_enabled (swap) ? "enabled" : "disabled",
fu_linux_swap_get_encrypted (swap) ? "encrypted" : "unencrypted");
return TRUE;
}
void
fu_plugin_add_security_attrs (FuPlugin *plugin, FuSecurityAttrs *attrs)
{
FuPluginData *data = fu_plugin_get_data (plugin);
gsize bufsz = 0;
g_autofree gchar *buf = NULL;
g_autoptr(FuLinuxSwap) swap = NULL;
g_autoptr(FwupdSecurityAttr) attr = NULL;
g_autoptr(GError) error_local = NULL;
/* create attr */
attr = fwupd_security_attr_new ("org.kernel.Swap");
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_RUNTIME_ISSUE);
fwupd_security_attr_set_name (attr, "Linux Swap");
fu_security_attrs_append (attrs, attr);
/* load list of swaps */
if (!g_file_load_contents (data->file, NULL, &buf, &bufsz, NULL, &error_local)) {
g_autofree gchar *fn = g_file_get_path (data->file);
g_warning ("could not open %s: %s", fn, error_local->message);
fwupd_security_attr_set_result (attr, "Could not open file");
return;
}
swap = fu_linux_swap_new (buf, bufsz, &error_local);
if (swap == NULL) {
g_autofree gchar *fn = g_file_get_path (data->file);
g_warning ("could not parse %s: %s", fn, error_local->message);
fwupd_security_attr_set_result (attr, "Could not parse file");
return;
}
/* none configured */
if (!fu_linux_swap_get_enabled (swap)) {
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS);
return;
}
/* add security attribute */
if (!fu_linux_swap_get_encrypted (swap)) {
fwupd_security_attr_set_result (attr, "Not encrypted");
return;
}
/* success */
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS);
fwupd_security_attr_set_result (attr, "Encrypted");
}

View File

@ -0,0 +1,8 @@
Linux Kernel Tainted
====================
Introduction
------------
This plugin checks if the currently running kernel is tainted. The result will
be stored in an security attribute for HSI.

View File

@ -0,0 +1,92 @@
/*
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include "fu-plugin-vfuncs.h"
#include "fu-hash.h"
struct FuPluginData {
GFile *file;
GFileMonitor *monitor;
};
void
fu_plugin_init (FuPlugin *plugin)
{
fu_plugin_alloc_data (plugin, sizeof (FuPluginData));
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
}
void
fu_plugin_destroy (FuPlugin *plugin)
{
FuPluginData *data = fu_plugin_get_data (plugin);
if (data->file != NULL)
g_object_unref (data->file);
if (data->monitor != NULL)
g_object_unref (data->monitor);
}
static void
fu_plugin_linux_tainted_changed_cb (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
gpointer user_data)
{
FuPlugin *plugin = FU_PLUGIN (user_data);
fu_plugin_security_changed (plugin);
}
gboolean
fu_plugin_startup (FuPlugin *plugin, GError **error)
{
FuPluginData *data = fu_plugin_get_data (plugin);
g_autofree gchar *fn = NULL;
g_autofree gchar *procfs = NULL;
procfs = fu_common_get_path (FU_PATH_KIND_PROCFS);
fn = g_build_filename (procfs, "sys", "kernel", "tainted", NULL);
data->file = g_file_new_for_path (fn);
data->monitor = g_file_monitor (data->file, G_FILE_MONITOR_NONE, NULL, error);
if (data->monitor == NULL)
return FALSE;
g_signal_connect (data->monitor, "changed",
G_CALLBACK (fu_plugin_linux_tainted_changed_cb), plugin);
return TRUE;
}
void
fu_plugin_add_security_attrs (FuPlugin *plugin, FuSecurityAttrs *attrs)
{
FuPluginData *data = fu_plugin_get_data (plugin);
gsize bufsz = 0;
g_autofree gchar *buf = NULL;
g_autoptr(FwupdSecurityAttr) attr = NULL;
g_autoptr(GError) error_local = NULL;
/* create attr */
attr = fwupd_security_attr_new ("org.kernel.CheckTainted");
fwupd_security_attr_set_name (attr, "Linux Kernel");
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_RUNTIME_ISSUE);
fu_security_attrs_append (attrs, attr);
/* load file */
if (!g_file_load_contents (data->file, NULL, &buf, &bufsz, NULL, &error_local)) {
g_autofree gchar *fn = g_file_get_path (data->file);
g_warning ("could not open %s: %s", fn, error_local->message);
fwupd_security_attr_set_result (attr, "Could not open file");
return;
}
if (g_strcmp0 (buf, "0\n") != 0) {
fwupd_security_attr_set_result (attr, "Tainted");
return;
}
/* success */
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS);
}

View File

@ -0,0 +1,23 @@
cargs = ['-DG_LOG_DOMAIN="FuPluginLinuxTainted"']
shared_module('fu_plugin_linux_tainted',
fu_hash,
sources : [
'fu-plugin-linux-tainted.c',
],
include_directories : [
root_incdir,
fwupd_incdir,
fwupdplugin_incdir,
],
install : true,
install_dir: plugin_dir,
link_with : [
fwupd,
fwupdplugin,
],
c_args : cargs,
dependencies : [
plugin_deps,
],
)

View File

@ -1,3 +1,5 @@
subdir('acpi-dmar')
subdir('acpi-facp')
subdir('ccgx')
subdir('cpu')
subdir('dfu')
@ -7,7 +9,11 @@ subdir('ep963x')
subdir('fastboot')
subdir('fresco-pd')
subdir('jabra')
subdir('linux-lockdown')
subdir('linux-sleep')
subdir('linux-spi-lpc')
subdir('linux-swap')
subdir('linux-tainted')
subdir('steelseries')
subdir('dell-dock')
subdir('nitrokey')

View File

@ -131,16 +131,23 @@ fu_plugin_add_security_attrs (FuPlugin *plugin, FuSecurityAttrs *attrs)
FuPluginData *data = fu_plugin_get_data (plugin);
g_autoptr(FwupdSecurityAttr) attr = NULL;
/* create attr */
attr = fwupd_security_attr_new ("org.trustedcomputinggroup.TpmEventLog");
fwupd_security_attr_set_level (attr, FWUPD_SECURITY_ATTR_LEVEL_IMPORTANT);
fwupd_security_attr_set_name (attr, "TPM Reconstruction");
fu_security_attrs_append (attrs, attr);
/* check reconstructed to PCR0 */
if (!fu_plugin_get_enabled (plugin)) {
fwupd_security_attr_set_result (attr, "No binary bios measurements available");
} else if (data->reconstructed) {
fwupd_security_attr_set_result (attr, "Matched PCR0 reading");
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS);
} else {
fwupd_security_attr_set_result (attr, "Did not match PCR0 reading");
return;
}
fu_security_attrs_append (attrs, attr);
if (!data->reconstructed) {
fwupd_security_attr_set_result (attr, "Did not match PCR0 reading");
return;
}
/* success */
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS);
fwupd_security_attr_set_result (attr, "Matched PCR0 reading");
}

View File

@ -11,10 +11,52 @@
#include "fu-tpm-device.h"
struct FuPluginData {
gboolean has_tpm;
gboolean has_tpm_v20;
};
void
fu_plugin_init (FuPlugin *plugin)
{
fu_plugin_alloc_data (plugin, sizeof (FuPluginData));
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
fu_plugin_add_udev_subsystem (plugin, "tpm");
fu_plugin_set_device_gtype (plugin, FU_TYPE_TPM_DEVICE);
}
void
fu_plugin_device_added (FuPlugin *plugin, FuDevice *dev)
{
FuPluginData *data = fu_plugin_get_data (plugin);
data->has_tpm = TRUE;
if (g_strcmp0 (fu_tpm_device_get_family (FU_TPM_DEVICE (dev)), "2.0") == 0)
data->has_tpm_v20 = TRUE;
}
void
fu_plugin_add_security_attrs (FuPlugin *plugin, FuSecurityAttrs *attrs)
{
FuPluginData *data = fu_plugin_get_data (plugin);
g_autoptr(FwupdSecurityAttr) attr = NULL;
/* create attr */
attr = fwupd_security_attr_new ("org.trustedcomputinggroup.Tpm");
fwupd_security_attr_set_level (attr, FWUPD_SECURITY_ATTR_LEVEL_CRITICAL);
fwupd_security_attr_set_name (attr, "TPM");
fu_security_attrs_append (attrs, attr);
/* check exists, and in v2.0 mode */
if (!data->has_tpm) {
fwupd_security_attr_set_result (attr, "Not found");
return;
}
if (!data->has_tpm_v20) {
fwupd_security_attr_set_result (attr, "Not in v2.0 mode");
return;
}
/* success */
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS);
fwupd_security_attr_set_result (attr, "v2.0");
}

View File

@ -12,6 +12,7 @@
struct _FuTpmDevice {
FuUdevDevice parent_instance;
gchar *family;
};
G_DEFINE_TYPE (FuTpmDevice, fu_tpm_device, FU_TYPE_UDEV_DEVICE)
@ -22,6 +23,12 @@ static void Esys_Finalize_autoptr_cleanup (ESYS_CONTEXT *esys_context)
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ESYS_CONTEXT, Esys_Finalize_autoptr_cleanup)
const gchar *
fu_tpm_device_get_family (FuTpmDevice *self)
{
return self->family;
}
static gboolean
fu_tpm_device_probe (FuUdevDevice *device, GError **error)
{
@ -134,6 +141,7 @@ fu_tpm_device_convert_manufacturer (const gchar *manufacturer)
static gboolean
fu_tpm_device_setup (FuDevice *device, GError **error)
{
FuTpmDevice *self = FU_TPM_DEVICE (device);
FwupdVersionFormat verfmt;
TSS2_RC rc;
const gchar *tmp;
@ -141,7 +149,6 @@ fu_tpm_device_setup (FuDevice *device, GError **error)
guint32 version1 = 0;
guint32 version2 = 0;
guint64 version_raw;
g_autofree gchar *family = NULL;
g_autofree gchar *id1 = NULL;
g_autofree gchar *id2 = NULL;
g_autofree gchar *id3 = NULL;
@ -171,8 +178,8 @@ fu_tpm_device_setup (FuDevice *device, GError **error)
}
/* lookup guaranteed details from TPM */
family = fu_tpm_device_get_string (ctx, TPM2_PT_FAMILY_INDICATOR, error);
if (family == NULL) {
self->family = fu_tpm_device_get_string (ctx, TPM2_PT_FAMILY_INDICATOR, error);
if (self->family == NULL) {
g_prefix_error (error, "failed to read TPM family");
return FALSE;
}
@ -202,9 +209,9 @@ fu_tpm_device_setup (FuDevice *device, GError **error)
fu_device_add_instance_id (device, id1);
id2 = g_strdup_printf ("TPM\\VEN_%s&MOD_%s", manufacturer, model);
fu_device_add_instance_id (device, id2);
id3 = g_strdup_printf ("TPM\\VEN_%s&DEV_%04X&VER_%s", manufacturer, tpm_type, family);
id3 = g_strdup_printf ("TPM\\VEN_%s&DEV_%04X&VER_%s", manufacturer, tpm_type, self->family);
fu_device_add_instance_id (device, id3);
id4 = g_strdup_printf ("TPM\\VEN_%s&MOD_%s&VER_%s", manufacturer, model, family);
id4 = g_strdup_printf ("TPM\\VEN_%s&MOD_%s&VER_%s", manufacturer, model, self->family);
fu_device_add_instance_id (device, id4);
/* enforce vendors can only ship updates for their own hardware */
@ -245,6 +252,8 @@ fu_tpm_device_init (FuTpmDevice *self)
static void
fu_tpm_device_finalize (GObject *object)
{
FuTpmDevice *self = FU_TPM_DEVICE (object);
g_free (self->family);
G_OBJECT_CLASS (fu_tpm_device_parent_class)->finalize (object);
}

View File

@ -10,3 +10,5 @@
#define FU_TYPE_TPM_DEVICE (fu_tpm_device_get_type ())
G_DECLARE_FINAL_TYPE (FuTpmDevice, fu_tpm_device, FU, TPM_DEVICE, FuUdevDevice)
const gchar *fu_tpm_device_get_family (FuTpmDevice *self);

View File

@ -5,4 +5,4 @@ Introduction
------------
This plugin checks if the UEFI dbx contains all the most recent blacklisted
checksums.
checksums. The result will be stored in an security attribute for HSI.

View File

@ -32,6 +32,17 @@ fu_plugin_destroy (FuPlugin *plugin)
gboolean
fu_plugin_startup (FuPlugin *plugin, GError **error)
{
FuPluginData *data = fu_plugin_get_data (plugin);
data->fn = fu_uefi_dbx_get_dbxupdate (error);
if (data->fn == NULL)
return FALSE;
g_debug ("using %s", data->fn);
return TRUE;
}
void
fu_plugin_add_security_attrs (FuPlugin *plugin, FuSecurityAttrs *attrs)
{
FuPluginData *data = fu_plugin_get_data (plugin);
GPtrArray *checksums;
@ -41,46 +52,55 @@ fu_plugin_startup (FuPlugin *plugin, GError **error)
g_autofree guint8 *buf_update = NULL;
g_autoptr(FuUefiDbxFile) dbx_system = NULL;
g_autoptr(FuUefiDbxFile) dbx_update = NULL;
g_autoptr(FwupdSecurityAttr) attr = NULL;
g_autoptr(GError) error_local = NULL;
/* get binary blob */
data->fn = fu_uefi_dbx_get_dbxupdate (error);
if (data->fn == NULL) {
/* create attr */
attr = fwupd_security_attr_new ("org.uefi.SecureBoot.dbx");
fwupd_security_attr_set_level (attr, FWUPD_SECURITY_ATTR_LEVEL_CRITICAL);
fwupd_security_attr_set_name (attr, "UEFI dbx");
fu_security_attrs_append (attrs, attr);
/* no binary blob */
if (!fu_plugin_get_enabled (plugin)) {
g_autofree gchar *dbxdir = NULL;
g_autofree gchar *result = NULL;
dbxdir = fu_common_get_path (FU_PATH_KIND_EFIDBXDIR);
g_set_error (error,
FWUPD_ERROR,
FWUPD_ERROR_NOT_SUPPORTED,
"file can be downloaded from %s and decompressed into %s: ",
FU_UEFI_DBX_DATA_URL, dbxdir);
return FALSE;
result = g_strdup_printf ("DBX can be downloaded from %s and decompressed into %s: ",
FU_UEFI_DBX_DATA_URL, dbxdir);
fwupd_security_attr_set_result (attr, result);
return;
}
/* get update dbx */
if (!g_file_get_contents (data->fn, (gchar **) &buf_update, &bufsz, error)) {
g_prefix_error (error, "failed to load %s: ", data->fn);
return FALSE;
if (!g_file_get_contents (data->fn, (gchar **) &buf_update, &bufsz, &error_local)) {
g_warning ("failed to load %s: %s", data->fn, error_local->message);
fwupd_security_attr_set_result (attr, "Failed to load update DBX");
return;
}
dbx_update = fu_uefi_dbx_file_new (buf_update, bufsz,
FU_UEFI_DBX_FILE_PARSE_FLAGS_IGNORE_HEADER,
error);
&error_local);
if (dbx_update == NULL) {
g_prefix_error (error, "could not parse %s: ", data->fn);
return FALSE;
g_warning ("failed to parse %s: %s", data->fn, error_local->message);
fwupd_security_attr_set_result (attr, "Failed to parse update DBX");
return;
}
/* get system dbx */
if (!fu_efivar_get_data ("d719b2cb-3d3a-4596-a3bc-dad00e67656f", "dbx",
&buf_system, &bufsz, NULL, error)) {
g_prefix_error (error, "failed to get dbx: ");
return FALSE;
&buf_system, &bufsz, NULL, &error_local)) {
g_warning ("failed to load EFI dbx: %s", error_local->message);
fwupd_security_attr_set_result (attr, "Failed to load EFI DBX");
return;
}
dbx_system = fu_uefi_dbx_file_new (buf_system, bufsz,
FU_UEFI_DBX_FILE_PARSE_FLAGS_NONE,
error);
&error_local);
if (dbx_system == NULL) {
g_prefix_error (error, "could not parse variable: ");
return FALSE;
g_warning ("failed to parse EFI dbx: %s", error_local->message);
fwupd_security_attr_set_result (attr, "Failed to parse EFI DBX");
return;
}
/* look for each checksum in the update in the system version */
@ -88,11 +108,18 @@ fu_plugin_startup (FuPlugin *plugin, GError **error)
for (guint i = 0; i < checksums->len; i++) {
const gchar *checksum = g_ptr_array_index (checksums, i);
if (!fu_uefi_dbx_file_has_checksum (dbx_system, checksum)) {
g_debug ("%s missing from the system dbx", checksum);
g_debug ("%s missing from the system DBX", checksum);
missing_cnt += 1;
}
}
if (missing_cnt > 0)
g_warning ("%u hashes missing", missing_cnt);
return TRUE;
/* add security attribute */
if (missing_cnt > 0) {
g_autofree gchar *summary = g_strdup_printf ("%u hashes missing", missing_cnt);
fwupd_security_attr_set_result (attr, summary);
return;
}
/* success */
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS);
}

View File

@ -91,6 +91,28 @@ fu_plugin_get_results (FuPlugin *plugin, FuDevice *device, GError **error)
return TRUE;
}
void
fu_plugin_add_security_attrs (FuPlugin *plugin, FuSecurityAttrs *attrs)
{
g_autoptr(FwupdSecurityAttr) attr = NULL;
/* create attr */
attr = fwupd_security_attr_new ("com.uefi.SecureBoot");
fwupd_security_attr_set_level (attr, FWUPD_SECURITY_ATTR_LEVEL_CRITICAL);
fwupd_security_attr_set_name (attr, "UEFI Secure Boot");
fu_security_attrs_append (attrs, attr);
/* SB disabled */
if (!fu_efivar_secure_boot_enabled ()) {
fwupd_security_attr_set_result (attr, "Disabled");
return;
}
/* success */
fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS);
fwupd_security_attr_set_result (attr, "Enabled");
}
static GBytes *
fu_plugin_uefi_get_splash_data (guint width, guint height, GError **error)
{