diff --git a/docs/hsi.xml b/docs/hsi.xml index cb80654ca7b..6450c061d55 100644 --- a/docs/hsi.xml +++ b/docs/hsi.xml @@ -710,10 +710,10 @@ - DRAM total memory encryption (TME) + DRAM memory encryption - Total memory encryption technology is used by the firmware on supported - SOCs to encrypt all data on external memory buses. + TME (Intel) or TSME (AMD) is used by the firmware on supported SOCs to + encrypt all data on external memory buses. It mitigates against an attacker being able to capture memory data while the system is running or to capture memory by removing a DRAM chip. @@ -732,7 +732,12 @@ Intel TME Press Release - 0 + + + + WikiChip SME Overview + + diff --git a/libfwupdplugin/README.md b/libfwupdplugin/README.md new file mode 100644 index 00000000000..c1bbc1345f1 --- /dev/null +++ b/libfwupdplugin/README.md @@ -0,0 +1,4 @@ +Planned API/ABI changes for next release +======================================== + + * Remove fu_common_is_cpu_intel() diff --git a/libfwupdplugin/fu-common.c b/libfwupdplugin/fu-common.c index 1755552b2ff..d4dd4aef52c 100644 --- a/libfwupdplugin/fu-common.c +++ b/libfwupdplugin/fu-common.c @@ -2236,26 +2236,49 @@ fu_common_cpuid (guint32 leaf, * Uses CPUID to discover the CPU vendor and check if it is Intel. * * Return value: %TRUE if the vendor was Intel. + * Deprecated: 1.5.5: Use fu_common_get_cpu_vendor() instead. * * Since: 1.5.0 **/ gboolean fu_common_is_cpu_intel (void) { + return fu_common_get_cpu_vendor () == FU_CPU_VENDOR_INTEL; +} + +/** + * fu_common_get_cpu_vendor: + * + * Uses CPUID to discover the CPU vendor. + * + * Return value: a #FuCpuVendor, e.g. %FU_CPU_VENDOR_AMD if the vendor was AMD. + * + * Since: 1.5.5 + **/ +FuCpuVendor +fu_common_get_cpu_vendor (void) +{ +#ifdef HAVE_CPUID_H guint ebx = 0; guint ecx = 0; guint edx = 0; - if (!fu_common_cpuid (0x0, NULL, &ebx, &ecx, &edx, NULL)) - return FALSE; -#ifdef HAVE_CPUID_H - if (ebx == signature_INTEL_ebx && - edx == signature_INTEL_edx && - ecx == signature_INTEL_ecx) { - return TRUE; + if (fu_common_cpuid (0x0, NULL, &ebx, &ecx, &edx, NULL)) { + if (ebx == signature_INTEL_ebx && + edx == signature_INTEL_edx && + ecx == signature_INTEL_ecx) { + return FU_CPU_VENDOR_INTEL; + } + if (ebx == signature_AMD_ebx && + edx == signature_AMD_edx && + ecx == signature_AMD_ecx) { + return FU_CPU_VENDOR_AMD; + } } #endif - return FALSE; + + /* failed */ + return FU_CPU_VENDOR_UNKNOWN; } /** diff --git a/libfwupdplugin/fu-common.h b/libfwupdplugin/fu-common.h index 0b3d71ef621..b266500be6a 100644 --- a/libfwupdplugin/fu-common.h +++ b/libfwupdplugin/fu-common.h @@ -84,6 +84,22 @@ typedef enum { FU_PATH_KIND_LAST } FuPathKind; +/** + * FuCpuVendor: + * @FU_CPU_VENDOR_UNKNOWN: Unknown + * @FU_CPU_VENDOR_INTEL: Intel + * @FU_CPU_VENDOR_AMD: AMD + * + * The CPU vendor. + **/ +typedef enum { + FU_CPU_VENDOR_UNKNOWN, + FU_CPU_VENDOR_INTEL, + FU_CPU_VENDOR_AMD, + /*< private >*/ + FU_CPU_VENDOR_LAST +} FuCpuVendor; + typedef void (*FuOutputHandler) (const gchar *line, gpointer user_data); @@ -260,7 +276,9 @@ gboolean fu_common_cpuid (guint32 leaf, guint32 *edx, GError **error) G_GNUC_WARN_UNUSED_RESULT; -gboolean fu_common_is_cpu_intel (void); +gboolean fu_common_is_cpu_intel (void) +G_DEPRECATED_FOR(fu_common_get_cpu_vendor); +FuCpuVendor fu_common_get_cpu_vendor (void); gboolean fu_common_is_live_media (void); GPtrArray *fu_common_get_volumes_by_kind (const gchar *kind, GError **error) diff --git a/libfwupdplugin/fwupdplugin.map b/libfwupdplugin/fwupdplugin.map index 2a6a13aac05..bd35f03f96b 100644 --- a/libfwupdplugin/fwupdplugin.map +++ b/libfwupdplugin/fwupdplugin.map @@ -702,6 +702,7 @@ LIBFWUPDPLUGIN_1.5.4 { LIBFWUPDPLUGIN_1.5.5 { global: + fu_common_get_cpu_vendor; fu_common_strsafe; fu_device_add_internal_flag; fu_device_has_internal_flag; diff --git a/plugins/acpi-dmar/fu-plugin-acpi-dmar.c b/plugins/acpi-dmar/fu-plugin-acpi-dmar.c index 0826a0c6ec1..f344cfb8aae 100644 --- a/plugins/acpi-dmar/fu-plugin-acpi-dmar.c +++ b/plugins/acpi-dmar/fu-plugin-acpi-dmar.c @@ -27,7 +27,7 @@ fu_plugin_add_security_attrs (FuPlugin *plugin, FuSecurityAttrs *attrs) g_autoptr(GError) error_local = NULL; /* only Intel */ - if (!fu_common_is_cpu_intel ()) + if (fu_common_get_cpu_vendor () != FU_CPU_VENDOR_INTEL) return; /* create attr */ diff --git a/plugins/cpu/fu-plugin-cpu.c b/plugins/cpu/fu-plugin-cpu.c index 7d8422090d0..326cd933fd9 100644 --- a/plugins/cpu/fu-plugin-cpu.c +++ b/plugins/cpu/fu-plugin-cpu.c @@ -158,7 +158,7 @@ void fu_plugin_add_security_attrs (FuPlugin *plugin, FuSecurityAttrs *attrs) { /* only Intel */ - if (!fu_common_is_cpu_intel ()) + if (fu_common_get_cpu_vendor () != FU_CPU_VENDOR_INTEL) return; fu_plugin_add_security_attrs_intel_cet_enabled (plugin, attrs); diff --git a/plugins/msr/fu-plugin-msr.c b/plugins/msr/fu-plugin-msr.c index cf529321a9f..03898643559 100644 --- a/plugins/msr/fu-plugin-msr.c +++ b/plugins/msr/fu-plugin-msr.c @@ -21,13 +21,25 @@ typedef union { } __attribute__((packed)) fields; } FuMsrIa32Debug; +typedef union { + guint32 data; + struct { + guint32 unknown0 : 23; /* 0 -> 22 inc */ + guint32 sev_is_enabled : 1; + guint32 unknown1 : 8; + } __attribute__((packed)) fields; +} FuMsrK8Syscfg; + struct FuPluginData { gboolean ia32_debug_supported; FuMsrIa32Debug ia32_debug; + gboolean k8_syscfg_supported; + FuMsrK8Syscfg k8_syscfg; }; #define PCI_MSR_IA32_DEBUG_INTERFACE 0xc80 #define PCI_MSR_IA32_BIOS_SIGN_ID 0x8b +#define PCI_MSR_K8_SYSCFG 0xC0010010 void fu_plugin_init (FuPlugin *plugin) @@ -41,12 +53,23 @@ gboolean fu_plugin_startup (FuPlugin *plugin, GError **error) { FuPluginData *priv = fu_plugin_get_data (plugin); + guint eax = 0; guint ecx = 0; /* sdbg is supported: https://en.wikipedia.org/wiki/CPUID */ - if (!fu_common_cpuid (0x01, NULL, NULL, &ecx, NULL, error)) - return FALSE; - priv->ia32_debug_supported = ((ecx >> 11) & 0x1) > 0; + if (fu_common_get_cpu_vendor () == FU_CPU_VENDOR_INTEL) { + if (!fu_common_cpuid (0x01, NULL, NULL, &ecx, NULL, error)) + return FALSE; + priv->ia32_debug_supported = ((ecx >> 11) & 0x1) > 0; + } + + /* indicates support for SEV */ + if (fu_common_get_cpu_vendor () == FU_CPU_VENDOR_AMD) { + if (!fu_common_cpuid (0x8000001f, &eax, NULL, NULL, NULL, error)) + return FALSE; + priv->k8_syscfg_supported = ((eax >> 0) & 0x1) > 0; + } + return TRUE; } @@ -91,6 +114,21 @@ fu_plugin_udev_device_added (FuPlugin *plugin, FuUdevDevice *device, GError **er priv->ia32_debug.fields.debug_occurred); } + /* grab MSR */ + if (priv->k8_syscfg_supported) { + if (!fu_udev_device_pread_full (device, PCI_MSR_K8_SYSCFG, + buf, sizeof(buf), error)) { + g_prefix_error (error, "could not read MSR_K8_SYSCFG: "); + return FALSE; + } + if (!fu_common_read_uint32_safe (buf, sizeof(buf), 0x0, + &priv->k8_syscfg.data, G_LITTLE_ENDIAN, + error)) + return FALSE; + g_debug ("MSR_K8_SYSCFG: sev_is_enabled=%i", + priv->k8_syscfg.fields.sev_is_enabled); + } + /* get microcode version */ if (device_cpu != NULL) { guint32 ver_raw; @@ -134,7 +172,7 @@ fu_plugin_add_security_attr_dci_enabled (FuPlugin *plugin, FuSecurityAttrs *attr g_autoptr(FwupdSecurityAttr) attr = NULL; /* this MSR is only valid for a subset of Intel CPUs */ - if (!fu_common_is_cpu_intel ()) + if (fu_common_get_cpu_vendor () != FU_CPU_VENDOR_INTEL) return; if (!priv->ia32_debug_supported) return; @@ -163,7 +201,7 @@ fu_plugin_add_security_attr_dci_locked (FuPlugin *plugin, FuSecurityAttrs *attrs g_autoptr(FwupdSecurityAttr) attr = NULL; /* this MSR is only valid for a subset of Intel CPUs */ - if (!fu_common_is_cpu_intel ()) + if (fu_common_get_cpu_vendor () != FU_CPU_VENDOR_INTEL) return; if (!priv->ia32_debug_supported) return; @@ -185,9 +223,41 @@ fu_plugin_add_security_attr_dci_locked (FuPlugin *plugin, FuSecurityAttrs *attrs fwupd_security_attr_set_result (attr, FWUPD_SECURITY_ATTR_RESULT_LOCKED); } +static void +fu_plugin_add_security_attr_amd_tsme_enabled (FuPlugin *plugin, FuSecurityAttrs *attrs) +{ + FuPluginData *priv = fu_plugin_get_data (plugin); + g_autoptr(FwupdSecurityAttr) attr = NULL; + + /* this MSR is only valid for a subset of AMD CPUs */ + if (fu_common_get_cpu_vendor () != FU_CPU_VENDOR_AMD) + return; + + /* create attr */ + 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); + fu_security_attrs_append (attrs, attr); + + /* check fields */ + if (!priv->k8_syscfg_supported) { + fwupd_security_attr_set_result (attr, FWUPD_SECURITY_ATTR_RESULT_NOT_SUPPORTED); + return; + } + if (!priv->k8_syscfg.fields.sev_is_enabled) { + fwupd_security_attr_set_result (attr, FWUPD_SECURITY_ATTR_RESULT_NOT_ENABLED); + return; + } + + /* success */ + fwupd_security_attr_add_flag (attr, FWUPD_SECURITY_ATTR_FLAG_SUCCESS); + fwupd_security_attr_set_result (attr, FWUPD_SECURITY_ATTR_RESULT_ENABLED); +} + void fu_plugin_add_security_attrs (FuPlugin *plugin, FuSecurityAttrs *attrs) { fu_plugin_add_security_attr_dci_enabled (plugin, attrs); fu_plugin_add_security_attr_dci_locked (plugin, attrs); + fu_plugin_add_security_attr_amd_tsme_enabled (plugin, attrs); } diff --git a/plugins/pci-bcr/fu-plugin-pci-bcr.c b/plugins/pci-bcr/fu-plugin-pci-bcr.c index e4402d78a0a..857d1ac2a5c 100644 --- a/plugins/pci-bcr/fu-plugin-pci-bcr.c +++ b/plugins/pci-bcr/fu-plugin-pci-bcr.c @@ -167,7 +167,7 @@ void fu_plugin_add_security_attrs (FuPlugin *plugin, FuSecurityAttrs *attrs) { /* only Intel */ - if (!fu_common_is_cpu_intel ()) + if (fu_common_get_cpu_vendor () != FU_CPU_VENDOR_INTEL) return; /* add attrs */ diff --git a/plugins/pci-mei/fu-plugin-pci-mei.c b/plugins/pci-mei/fu-plugin-pci-mei.c index 6e5517d02b7..b7a668e5610 100644 --- a/plugins/pci-mei/fu-plugin-pci-mei.c +++ b/plugins/pci-mei/fu-plugin-pci-mei.c @@ -467,7 +467,7 @@ fu_plugin_add_security_attrs (FuPlugin *plugin, FuSecurityAttrs *attrs) FuPluginData *priv = fu_plugin_get_data (plugin); /* only Intel */ - if (!fu_common_is_cpu_intel ()) + if (fu_common_get_cpu_vendor () != FU_CPU_VENDOR_INTEL) return; if (!priv->has_device) return;