Allow adding GUIDs to each HSI security attr

This indicates the GUID in some way contributed to the result decided.

It also allows us to match the submitted HSI results back to a firmware
stream on the LVFS, which allows us to allow vendors to see a subset of
results for uploaded devices.
This commit is contained in:
Richard Hughes 2021-09-03 14:16:21 +01:00
parent 841adff03d
commit f56878ff88
11 changed files with 195 additions and 9 deletions

View File

@ -25,6 +25,7 @@ fwupd_security_attr_finalize(GObject *object);
typedef struct {
gchar *appstream_id;
GPtrArray *obsoletes;
GPtrArray *guids;
GHashTable *metadata; /* (nullable) */
gchar *name;
gchar *plugin;
@ -196,6 +197,91 @@ fwupd_security_attr_has_obsolete(FwupdSecurityAttr *self, const gchar *appstream
return FALSE;
}
/**
* fwupd_security_attr_get_guids:
* @self: a #FwupdSecurityAttr
*
* Gets the list of attribute GUIDs. The GUID values will not modify the calculated HSI value.
*
* Returns: (element-type utf8) (transfer none): the GUIDs, which may be empty
*
* Since: 1.7.0
**/
GPtrArray *
fwupd_security_attr_get_guids(FwupdSecurityAttr *self)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
g_return_val_if_fail(FWUPD_IS_SECURITY_ATTR(self), NULL);
return priv->guids;
}
/**
* fwupd_security_attr_add_guid:
* @self: a #FwupdSecurityAttr
* @guid: the GUID
*
* Adds a device GUID to the attribute. This indicates the GUID in some way contributed to the
* result decided.
*
* Since: 1.7.0
**/
void
fwupd_security_attr_add_guid(FwupdSecurityAttr *self, const gchar *guid)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
g_return_if_fail(FWUPD_IS_SECURITY_ATTR(self));
g_return_if_fail(fwupd_guid_is_valid(guid));
if (fwupd_security_attr_has_guid(self, guid))
return;
g_ptr_array_add(priv->guids, g_strdup(guid));
}
/**
* fwupd_security_attr_add_guids:
* @self: a #FwupdSecurityAttr
* @guids: (element-type utf8): the GUIDs
*
* Adds device GUIDs to the attribute. This indicates the GUIDs in some way contributed to the
* result decided.
*
* Since: 1.7.0
**/
void
fwupd_security_attr_add_guids(FwupdSecurityAttr *self, GPtrArray *guids)
{
g_return_if_fail(FWUPD_IS_SECURITY_ATTR(self));
g_return_if_fail(guids != NULL);
for (guint i = 0; i < guids->len; i++) {
const gchar *guid = g_ptr_array_index(guids, i);
fwupd_security_attr_add_guid(self, guid);
}
}
/**
* fwupd_security_attr_has_guid:
* @self: a #FwupdSecurityAttr
* @guid: the attribute guid
*
* Finds out if a specific GUID was added to the attribute.
*
* Returns: %TRUE if the self matches
*
* Since: 1.7.0
**/
gboolean
fwupd_security_attr_has_guid(FwupdSecurityAttr *self, const gchar *guid)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
g_return_val_if_fail(FWUPD_IS_SECURITY_ATTR(self), FALSE);
g_return_val_if_fail(guid != NULL, FALSE);
for (guint i = 0; i < priv->guids->len; i++) {
const gchar *guid_tmp = g_ptr_array_index(priv->guids, i);
if (g_strcmp0(guid_tmp, guid) == 0)
return TRUE;
}
return FALSE;
}
/**
* fwupd_security_attr_get_appstream_id:
* @self: a #FwupdSecurityAttr
@ -553,6 +639,15 @@ fwupd_security_attr_to_variant(FwupdSecurityAttr *self)
FWUPD_RESULT_KEY_CATEGORIES,
g_variant_new_strv(strv, -1));
}
if (priv->guids->len > 0) {
g_autofree const gchar **strv = g_new0(const gchar *, priv->guids->len + 1);
for (guint i = 0; i < priv->guids->len; i++)
strv[i] = (const gchar *)g_ptr_array_index(priv->guids, i);
g_variant_builder_add(&builder,
"{sv}",
FWUPD_RESULT_KEY_GUID,
g_variant_new_strv(strv, -1));
}
if (priv->flags != 0) {
g_variant_builder_add(&builder,
"{sv}",
@ -657,6 +752,12 @@ fwupd_security_attr_from_key_value(FwupdSecurityAttr *self, const gchar *key, GV
fwupd_security_attr_set_result(self, g_variant_get_uint32(value));
return;
}
if (g_strcmp0(key, FWUPD_RESULT_KEY_GUID) == 0) {
g_autofree const gchar **strv = g_variant_get_strv(value, NULL);
for (guint i = 0; strv[i] != NULL; i++)
fwupd_security_attr_add_guid(self, strv[i]);
return;
}
if (g_strcmp0(key, FWUPD_RESULT_KEY_METADATA) == 0) {
if (priv->metadata != NULL)
g_hash_table_unref(priv->metadata);
@ -745,6 +846,15 @@ fwupd_security_attr_to_json(FwupdSecurityAttr *self, JsonBuilder *builder)
}
json_builder_end_array(builder);
}
if (priv->guids->len > 0) {
json_builder_set_member_name(builder, FWUPD_RESULT_KEY_GUID);
json_builder_begin_array(builder);
for (guint i = 0; i < priv->guids->len; i++) {
const gchar *guid = g_ptr_array_index(priv->guids, i);
json_builder_add_string_value(builder, guid);
}
json_builder_end_array(builder);
}
if (priv->metadata != NULL) {
g_autoptr(GList) keys = g_hash_table_get_keys(priv->metadata);
for (GList *l = keys; l != NULL; l = l->next) {
@ -788,6 +898,10 @@ fwupd_security_attr_to_string(FwupdSecurityAttr *self)
const gchar *appstream_id = g_ptr_array_index(priv->obsoletes, i);
fwupd_pad_kv_str(str, "Obsolete", appstream_id);
}
for (guint i = 0; i < priv->guids->len; i++) {
const gchar *guid = g_ptr_array_index(priv->guids, i);
fwupd_pad_kv_str(str, FWUPD_RESULT_KEY_GUID, guid);
}
if (priv->metadata != NULL) {
g_autoptr(GList) keys = g_hash_table_get_keys(priv->metadata);
for (GList *l = keys; l != NULL; l = l->next) {
@ -812,6 +926,7 @@ fwupd_security_attr_init(FwupdSecurityAttr *self)
{
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
priv->obsoletes = g_ptr_array_new_with_free_func(g_free);
priv->guids = g_ptr_array_new_with_free_func(g_free);
}
static void
@ -827,6 +942,7 @@ fwupd_security_attr_finalize(GObject *object)
g_free(priv->plugin);
g_free(priv->url);
g_ptr_array_unref(priv->obsoletes);
g_ptr_array_unref(priv->guids);
G_OBJECT_CLASS(fwupd_security_attr_parent_class)->finalize(object);
}

View File

@ -148,6 +148,14 @@ void
fwupd_security_attr_add_obsolete(FwupdSecurityAttr *self, const gchar *appstream_id);
gboolean
fwupd_security_attr_has_obsolete(FwupdSecurityAttr *self, const gchar *appstream_id);
GPtrArray *
fwupd_security_attr_get_guids(FwupdSecurityAttr *self);
void
fwupd_security_attr_add_guid(FwupdSecurityAttr *self, const gchar *guid);
void
fwupd_security_attr_add_guids(FwupdSecurityAttr *self, GPtrArray *guids);
gboolean
fwupd_security_attr_has_guid(FwupdSecurityAttr *self, const gchar *guid);
const gchar *
fwupd_security_attr_get_metadata(FwupdSecurityAttr *self, const gchar *key);
void

View File

@ -700,3 +700,12 @@ LIBFWUPD_1.6.2 {
fwupd_request_to_variant;
local: *;
} LIBFWUPD_1.6.1;
LIBFWUPD_1.7.0 {
global:
fwupd_security_attr_add_guid;
fwupd_security_attr_add_guids;
fwupd_security_attr_get_guids;
fwupd_security_attr_has_guid;
local: *;
} LIBFWUPD_1.6.2;

View File

@ -303,6 +303,7 @@ fu_cpu_device_add_security_attrs_intel_cet_enabled(FuCpuDevice *self, FuSecurity
attr = fwupd_security_attr_new(FWUPD_SECURITY_ATTR_ID_INTEL_CET_ENABLED);
fwupd_security_attr_set_plugin(attr, fu_device_get_plugin(FU_DEVICE(self)));
fwupd_security_attr_set_level(attr, FWUPD_SECURITY_ATTR_LEVEL_THEORETICAL);
fwupd_security_attr_add_guids(attr, fu_device_get_guids(FU_DEVICE(self)));
fu_security_attrs_append(attrs, attr);
/* check for CET */
@ -334,6 +335,7 @@ fu_cpu_device_add_security_attrs_intel_cet_active(FuCpuDevice *self, FuSecurityA
attr = fwupd_security_attr_new(FWUPD_SECURITY_ATTR_ID_INTEL_CET_ACTIVE);
fwupd_security_attr_set_plugin(attr, fu_device_get_plugin(FU_DEVICE(self)));
fwupd_security_attr_set_level(attr, FWUPD_SECURITY_ATTR_LEVEL_THEORETICAL);
fwupd_security_attr_add_guids(attr, fu_device_get_guids(FU_DEVICE(self)));
fwupd_security_attr_add_flag(attr, FWUPD_SECURITY_ATTR_FLAG_RUNTIME_ISSUE);
fu_security_attrs_append(attrs, attr);
@ -362,6 +364,7 @@ fu_cpu_device_add_security_attrs_intel_tme(FuCpuDevice *self, FuSecurityAttrs *a
attr = fwupd_security_attr_new(FWUPD_SECURITY_ATTR_ID_ENCRYPTED_RAM);
fwupd_security_attr_set_plugin(attr, fu_device_get_plugin(FU_DEVICE(self)));
fwupd_security_attr_set_level(attr, FWUPD_SECURITY_ATTR_LEVEL_SYSTEM_PROTECTION);
fwupd_security_attr_add_guids(attr, fu_device_get_guids(FU_DEVICE(self)));
fu_security_attrs_append(attrs, attr);
/* check for TME */
@ -384,6 +387,7 @@ fu_cpu_device_add_security_attrs_intel_smap(FuCpuDevice *self, FuSecurityAttrs *
attr = fwupd_security_attr_new(FWUPD_SECURITY_ATTR_ID_INTEL_SMAP);
fwupd_security_attr_set_plugin(attr, fu_device_get_plugin(FU_DEVICE(self)));
fwupd_security_attr_set_level(attr, FWUPD_SECURITY_ATTR_LEVEL_SYSTEM_PROTECTION);
fwupd_security_attr_add_guids(attr, fu_device_get_guids(FU_DEVICE(self)));
fu_security_attrs_append(attrs, attr);
/* check for SMEP and SMAP */

View File

@ -214,6 +214,7 @@ fu_intel_spi_device_add_security_attrs(FuDevice *device, FuSecurityAttrs *attrs)
attr = fwupd_security_attr_new(FWUPD_SECURITY_ATTR_ID_SPI_DESCRIPTOR);
fwupd_security_attr_set_plugin(attr, fu_device_get_plugin(FU_DEVICE(self)));
fwupd_security_attr_set_level(attr, FWUPD_SECURITY_ATTR_LEVEL_CRITICAL);
fwupd_security_attr_add_guids(attr, fu_device_get_guids(device));
fu_security_attrs_append(attrs, attr);
/* check for read access from other regions */

View File

@ -187,6 +187,7 @@ static void
fu_plugin_add_security_attr_dci_enabled(FuPlugin *plugin, FuSecurityAttrs *attrs)
{
FuPluginData *priv = fu_plugin_get_data(plugin);
FuDevice *device = fu_plugin_cache_lookup(plugin, "cpu");
g_autoptr(FwupdSecurityAttr) attr = NULL;
/* this MSR is only valid for a subset of Intel CPUs */
@ -199,6 +200,8 @@ fu_plugin_add_security_attr_dci_enabled(FuPlugin *plugin, FuSecurityAttrs *attrs
attr = fwupd_security_attr_new(FWUPD_SECURITY_ATTR_ID_INTEL_DCI_ENABLED);
fwupd_security_attr_set_plugin(attr, fu_plugin_get_name(plugin));
fwupd_security_attr_set_level(attr, FWUPD_SECURITY_ATTR_LEVEL_CRITICAL);
if (device != NULL)
fwupd_security_attr_add_guids(attr, fu_device_get_guids(device));
fu_security_attrs_append(attrs, attr);
/* check fields */
@ -216,6 +219,7 @@ static void
fu_plugin_add_security_attr_dci_locked(FuPlugin *plugin, FuSecurityAttrs *attrs)
{
FuPluginData *priv = fu_plugin_get_data(plugin);
FuDevice *device = fu_plugin_cache_lookup(plugin, "cpu");
g_autoptr(FwupdSecurityAttr) attr = NULL;
/* this MSR is only valid for a subset of Intel CPUs */
@ -228,6 +232,8 @@ fu_plugin_add_security_attr_dci_locked(FuPlugin *plugin, FuSecurityAttrs *attrs)
attr = fwupd_security_attr_new(FWUPD_SECURITY_ATTR_ID_INTEL_DCI_LOCKED);
fwupd_security_attr_set_plugin(attr, fu_plugin_get_name(plugin));
fwupd_security_attr_set_level(attr, FWUPD_SECURITY_ATTR_LEVEL_IMPORTANT);
if (device != NULL)
fwupd_security_attr_add_guids(attr, fu_device_get_guids(device));
fu_security_attrs_append(attrs, attr);
/* check fields */
@ -245,6 +251,7 @@ static void
fu_plugin_add_security_attr_amd_tsme_enabled(FuPlugin *plugin, FuSecurityAttrs *attrs)
{
FuPluginData *priv = fu_plugin_get_data(plugin);
FuDevice *device = fu_plugin_cache_lookup(plugin, "cpu");
g_autoptr(FwupdSecurityAttr) attr = NULL;
/* this MSR is only valid for a subset of AMD CPUs */
@ -255,6 +262,8 @@ fu_plugin_add_security_attr_amd_tsme_enabled(FuPlugin *plugin, FuSecurityAttrs *
attr = fwupd_security_attr_new(FWUPD_SECURITY_ATTR_ID_ENCRYPTED_RAM);
fwupd_security_attr_set_plugin(attr, fu_plugin_get_name(plugin));
fwupd_security_attr_set_level(attr, FWUPD_SECURITY_ATTR_LEVEL_SYSTEM_PROTECTION);
if (device != NULL)
fwupd_security_attr_add_guids(attr, fu_device_get_guids(device));
fu_security_attrs_append(attrs, attr);
/* check fields */

View File

@ -69,12 +69,15 @@ static void
fu_plugin_add_security_attr_bioswe(FuPlugin *plugin, FuSecurityAttrs *attrs)
{
FuPluginData *priv = fu_plugin_get_data(plugin);
FuDevice *msf_device = fu_plugin_cache_lookup(plugin, "main-system-firmware");
g_autoptr(FwupdSecurityAttr) attr = NULL;
/* create attr */
attr = fwupd_security_attr_new(FWUPD_SECURITY_ATTR_ID_SPI_BIOSWE);
fwupd_security_attr_set_plugin(attr, fu_plugin_get_name(plugin));
fwupd_security_attr_set_level(attr, FWUPD_SECURITY_ATTR_LEVEL_CRITICAL);
if (msf_device != NULL)
fwupd_security_attr_add_guids(attr, fu_device_get_guids(msf_device));
fu_security_attrs_append(attrs, attr);
/* no device */
@ -98,6 +101,7 @@ static void
fu_plugin_add_security_attr_ble(FuPlugin *plugin, FuSecurityAttrs *attrs)
{
FuPluginData *priv = fu_plugin_get_data(plugin);
FuDevice *msf_device = fu_plugin_cache_lookup(plugin, "main-system-firmware");
g_autoptr(FwupdSecurityAttr) attr = NULL;
/* no device */
@ -108,6 +112,8 @@ fu_plugin_add_security_attr_ble(FuPlugin *plugin, FuSecurityAttrs *attrs)
attr = fwupd_security_attr_new(FWUPD_SECURITY_ATTR_ID_SPI_BLE);
fwupd_security_attr_set_plugin(attr, fu_plugin_get_name(plugin));
fwupd_security_attr_set_level(attr, FWUPD_SECURITY_ATTR_LEVEL_CRITICAL);
if (msf_device != NULL)
fwupd_security_attr_add_guids(attr, fu_device_get_guids(msf_device));
fu_security_attrs_append(attrs, attr);
/* load file */
@ -125,6 +131,7 @@ static void
fu_plugin_add_security_attr_smm_bwp(FuPlugin *plugin, FuSecurityAttrs *attrs)
{
FuPluginData *priv = fu_plugin_get_data(plugin);
FuDevice *msf_device = fu_plugin_cache_lookup(plugin, "main-system-firmware");
g_autoptr(FwupdSecurityAttr) attr = NULL;
/* no device */
@ -135,6 +142,8 @@ fu_plugin_add_security_attr_smm_bwp(FuPlugin *plugin, FuSecurityAttrs *attrs)
attr = fwupd_security_attr_new(FWUPD_SECURITY_ATTR_ID_SPI_SMM_BWP);
fwupd_security_attr_set_plugin(attr, fu_plugin_get_name(plugin));
fwupd_security_attr_set_level(attr, FWUPD_SECURITY_ATTR_LEVEL_CRITICAL);
if (msf_device != NULL)
fwupd_security_attr_add_guids(attr, fu_device_get_guids(msf_device));
fu_security_attrs_append(attrs, attr);
/* load file */

View File

@ -11,7 +11,7 @@
#include "fu-mei-common.h"
struct FuPluginData {
gboolean has_device;
FuDevice *pci_device;
FuMeiHfsts1 hfsts1;
FuMeiHfsts2 hfsts2;
FuMeiHfsts3 hfsts3;
@ -56,6 +56,14 @@ fu_plugin_init(FuPlugin *plugin)
fu_plugin_add_udev_subsystem(plugin, "pci");
}
void
fu_plugin_destroy(FuPlugin *plugin)
{
FuPluginData *data = fu_plugin_get_data(plugin);
if (data->pci_device != NULL)
g_object_unref(data->pci_device);
}
static FuMeiFamily
fu_mei_detect_family(FuPlugin *plugin)
{
@ -218,7 +226,7 @@ fu_plugin_backend_device_added(FuPlugin *plugin, FuDevice *device, GError **erro
return FALSE;
}
priv->hfsts6.data = fu_common_read_uint32(buf, G_LITTLE_ENDIAN);
priv->has_device = TRUE;
g_set_object(&priv->pci_device, device);
/* dump to console */
if (g_getenv("FWUPD_PCI_MEI_VERBOSE") != NULL) {
@ -503,7 +511,7 @@ fu_plugin_add_security_attrs(FuPlugin *plugin, FuSecurityAttrs *attrs)
/* only Intel */
if (fu_common_get_cpu_vendor() != FU_CPU_VENDOR_INTEL)
return;
if (!priv->has_device)
if (priv->pci_device == NULL)
return;
fu_plugin_add_security_attrs_manufacturing_mode(plugin, attrs);

View File

@ -12,7 +12,7 @@
struct FuPluginData {
GPtrArray *pcr0s;
gboolean has_tpm_device;
FuDevice *tpm_device;
gboolean has_uefi_device;
gboolean reconstructed;
};
@ -32,6 +32,8 @@ fu_plugin_destroy(FuPlugin *plugin)
FuPluginData *data = fu_plugin_get_data(plugin);
if (data->pcr0s != NULL)
g_ptr_array_unref(data->pcr0s);
if (data->tpm_device != NULL)
g_object_unref(data->tpm_device);
}
gboolean
@ -93,7 +95,7 @@ static void
fu_plugin_device_registered_tpm(FuPlugin *plugin, FuDevice *device)
{
FuPluginData *data = fu_plugin_get_data(plugin);
data->has_tpm_device = TRUE;
g_set_object(&data->tpm_device, device);
}
static void
@ -150,13 +152,14 @@ fu_plugin_add_security_attrs(FuPlugin *plugin, FuSecurityAttrs *attrs)
g_autoptr(FwupdSecurityAttr) attr = NULL;
/* no TPM device */
if (!data->has_tpm_device)
if (data->tpm_device == NULL)
return;
/* create attr */
attr = fwupd_security_attr_new(FWUPD_SECURITY_ATTR_ID_TPM_RECONSTRUCTION_PCR0);
fwupd_security_attr_set_plugin(attr, fu_plugin_get_name(plugin));
fwupd_security_attr_set_level(attr, FWUPD_SECURITY_ATTR_LEVEL_IMPORTANT);
fwupd_security_attr_add_guids(attr, fu_device_get_guids(data->tpm_device));
fu_security_attrs_append(attrs, attr);
/* check reconstructed to PCR0 */

View File

@ -11,7 +11,7 @@
#include "fu-tpm-device.h"
struct FuPluginData {
gboolean has_tpm;
FuDevice *tpm_device;
gboolean has_tpm_v20;
};
@ -24,13 +24,21 @@ fu_plugin_init(FuPlugin *plugin)
fu_plugin_add_device_gtype(plugin, FU_TYPE_TPM_DEVICE);
}
void
fu_plugin_destroy(FuPlugin *plugin)
{
FuPluginData *data = fu_plugin_get_data(plugin);
if (data->tpm_device != NULL)
g_object_unref(data->tpm_device);
}
void
fu_plugin_device_added(FuPlugin *plugin, FuDevice *dev)
{
FuPluginData *data = fu_plugin_get_data(plugin);
const gchar *family = fu_tpm_device_get_family(FU_TPM_DEVICE(dev));
data->has_tpm = TRUE;
g_set_object(&data->tpm_device, dev);
if (g_strcmp0(family, "2.0") == 0)
data->has_tpm_v20 = TRUE;
fu_plugin_add_report_metadata(plugin, "TpmFamily", family);
@ -49,7 +57,7 @@ fu_plugin_add_security_attrs(FuPlugin *plugin, FuSecurityAttrs *attrs)
fu_security_attrs_append(attrs, attr);
/* check exists, and in v2.0 mode */
if (!data->has_tpm) {
if (data->tpm_device == NULL) {
fwupd_security_attr_set_result(attr, FWUPD_SECURITY_ATTR_RESULT_NOT_FOUND);
return;
}
@ -59,6 +67,7 @@ fu_plugin_add_security_attrs(FuPlugin *plugin, FuSecurityAttrs *attrs)
}
/* success */
fwupd_security_attr_add_guids(attr, fu_device_get_guids(data->tpm_device));
fwupd_security_attr_add_flag(attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS);
fwupd_security_attr_set_result(attr, FWUPD_SECURITY_ATTR_RESULT_FOUND);
}

View File

@ -158,16 +158,26 @@ fu_plugin_init(FuPlugin *plugin)
fu_plugin_set_build_hash(plugin, FU_BUILD_HASH);
}
void
fu_plugin_device_registered(FuPlugin *plugin, FuDevice *device)
{
if (fu_device_has_instance_id(device, "main-system-firmware"))
fu_plugin_cache_add(plugin, "main-system-firmware", device);
}
void
fu_plugin_add_security_attrs(FuPlugin *plugin, FuSecurityAttrs *attrs)
{
FuPluginData *priv = fu_plugin_get_data(plugin);
FuDevice *msf_device = fu_plugin_cache_lookup(plugin, "main-system-firmware");
g_autoptr(FwupdSecurityAttr) attr = NULL;
/* create attr */
attr = fwupd_security_attr_new(FWUPD_SECURITY_ATTR_ID_UEFI_PK);
fwupd_security_attr_set_level(attr, FWUPD_SECURITY_ATTR_LEVEL_CRITICAL);
fwupd_security_attr_set_plugin(attr, fu_plugin_get_name(plugin));
if (msf_device != NULL)
fwupd_security_attr_add_guids(attr, fu_device_get_guids(msf_device));
fu_security_attrs_append(attrs, attr);
/* test key is not secure */