diff --git a/plugins/uefi-dbx/fu-dbxtool.c b/plugins/uefi-dbx/fu-dbxtool.c index a18665a7f..2a9601e79 100644 --- a/plugins/uefi-dbx/fu-dbxtool.c +++ b/plugins/uefi-dbx/fu-dbxtool.c @@ -221,6 +221,18 @@ main (int argc, char *argv[]) return EXIT_FAILURE; } + /* validate this is safe to apply */ + if (!force) { + /* TRANSLATORS: ESP refers to the EFI System Partition */ + g_print ("%s\n", _("Validating ESP contents…")); + if (!fu_uefi_dbx_signature_list_validate (dbx_update, &error)) { + /* TRANSLATORS: something with a blocked hash exists + * in the users ESP -- which would be bad! */ + g_printerr ("%s: %s\n", _("Failed to validate ESP contents"), error->message); + return EXIT_FAILURE; + } + } + /* TRANSLATORS: actually sending the update to the hardware */ g_print ("%s\n", _("Applying update…")); if (!fu_efivar_set_data (FU_EFIVAR_GUID_SECURITY_DATABASE, diff --git a/plugins/uefi-dbx/fu-efi-image.c b/plugins/uefi-dbx/fu-efi-image.c new file mode 100644 index 000000000..31229316b --- /dev/null +++ b/plugins/uefi-dbx/fu-efi-image.c @@ -0,0 +1,332 @@ +/* + * Copyright (C) 2020 Richard Hughes + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#include "config.h" + +#include "fu-common.h" +#include "fu-efi-image.h" + +struct _FuEfiImage { + GObject parent_instance; + gchar *checksum; +}; + +typedef struct { + gsize offset; + gsize size; + gchar *name; +} FuEfiImageRegion; + +typedef struct __attribute__((packed)) { + guint32 addr; + guint32 size; +} FuEfiImageDataDirEntry; + +G_DEFINE_TYPE (FuEfiImage, fu_efi_image, G_TYPE_OBJECT) + +#define _DOS_OFFSET_SIGNATURE 0x00 +#define _DOS_OFFSET_TO_PE_HEADER 0x3c + +#define _PEI_OFFSET_SIGNATURE 0x00 +#define _PEI_OFFSET_MACHINE 0x04 +#define _PEI_OFFSET_NUMBER_OF_SECTIONS 0x06 +#define _PEI_OFFSET_OPTIONAL_HEADER_SIZE 0x14 +#define _PEI_HEADER_SIZE 0x18 + +#define _PE_OFFSET_SIZE_OF_HEADERS 0x54 +#define _PE_OFFSET_CHECKSUM 0x58 +#define _PE_OFFSET_DEBUG_TABLE_OFFSET 0x98 + +#define _PEP_OFFSET_SIZE_OF_HEADERS 0x54 +#define _PEP_OFFSET_CHECKSUM 0x58 +#define _PEP_OFFSET_DEBUG_TABLE_OFFSET 0xa8 + +#define _SECTION_HEADER_OFFSET_NAME 0x0 +#define _SECTION_HEADER_OFFSET_SIZE 0x10 +#define _SECTION_HEADER_OFFSET_PTR 0x14 +#define _SECTION_HEADER_SIZE 0x28 + +#define IMAGE_FILE_MACHINE_AMD64 0x8664 +#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_THUMB 0x01c2 +#define IMAGE_FILE_MACHINE_AARCH64 0xaa64 + +static gint +fu_efi_image_region_sort_cb (gconstpointer a, gconstpointer b) +{ + const FuEfiImageRegion *r1 = *((const FuEfiImageRegion **) a); + const FuEfiImageRegion *r2 = *((const FuEfiImageRegion **) b); + if (r1->offset < r2->offset) + return -1; + if (r1->offset > r2->offset) + return 1; + return 0; +} + +static FuEfiImageRegion * +fu_efi_image_add_region (GPtrArray *checksum_regions, + const gchar *name, + gsize offset_start, + gsize offset_end) +{ + FuEfiImageRegion *r = g_new0 (FuEfiImageRegion, 1); + r->name = g_strdup (name); + r->offset = offset_start; + r->size = offset_end - offset_start; + g_ptr_array_add (checksum_regions, r); + return r; +} + +static void +fu_efi_image_region_free (FuEfiImageRegion *r) +{ + g_free (r->name); + g_free (r); +} + +FuEfiImage * +fu_efi_image_new (GBytes *data, GError **error) +{ + FuEfiImageRegion *r; + const guint8 *buf; + gsize bufsz; + gsize image_bytes = 0; + gsize checksum_offset; + gsize data_dir_debug_offset; + gsize offset_tmp; + guint16 dos_sig = 0; + guint16 machine = 0; + guint16 opthdrsz; + guint16 sections; + guint32 baseaddr = 0; + guint32 cert_table_size; + guint32 header_size; + guint32 nt_sig = 0; + g_autoptr(FuEfiImage) self = g_object_new (FU_TYPE_EFI_IMAGE, NULL); + g_autoptr(GChecksum) checksum = g_checksum_new (G_CHECKSUM_SHA256); + g_autoptr(GPtrArray) checksum_regions = NULL; + + /* verify this is a DOS file */ + buf = g_bytes_get_data (data, &bufsz); + if (!fu_common_read_uint16_safe (buf, bufsz, + _DOS_OFFSET_SIGNATURE, + &dos_sig, G_LITTLE_ENDIAN, error)) + return NULL; + if (dos_sig != 0x5a4d) { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + "Invalid DOS header magic %04x", dos_sig); + return NULL; + } + + /* verify the PE signature */ + if (!fu_common_read_uint32_safe (buf, bufsz, + _DOS_OFFSET_TO_PE_HEADER, + &baseaddr, G_LITTLE_ENDIAN, error)) + return NULL; + if (!fu_common_read_uint32_safe (buf, bufsz, + baseaddr + _PEI_OFFSET_SIGNATURE, + &nt_sig, G_LITTLE_ENDIAN, error)) + return NULL; + if (nt_sig != 0x4550) { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + "Invalid PE header signature %08x", nt_sig); + return NULL; + } + + /* which machine type are we reading */ + if (!fu_common_read_uint16_safe (buf, bufsz, + baseaddr + _PEI_OFFSET_MACHINE, + &machine, G_LITTLE_ENDIAN, error)) + return NULL; + if (machine == IMAGE_FILE_MACHINE_AMD64 || + machine == IMAGE_FILE_MACHINE_AARCH64) { + + /* a.out header directly follows PE header */ + if (!fu_common_read_uint16_safe (buf, bufsz, + baseaddr + _PEI_HEADER_SIZE, + &machine, G_LITTLE_ENDIAN, error)) + return NULL; + if (machine != 0x020b) { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + "Invalid a.out machine type %04x", machine); + return NULL; + } + if (!fu_common_read_uint32_safe (buf, bufsz, + baseaddr + _PEP_OFFSET_SIZE_OF_HEADERS, + &header_size, G_LITTLE_ENDIAN, error)) + return NULL; + + checksum_offset = baseaddr + _PEP_OFFSET_CHECKSUM; + + /* now, this is odd. sbsigntools seems to think that we're + * skipping the CertificateTable -- but we actually seems to be + * ignoring Debug instead */ + data_dir_debug_offset = baseaddr + _PEP_OFFSET_DEBUG_TABLE_OFFSET; + + } else if (machine == IMAGE_FILE_MACHINE_I386 || + machine == IMAGE_FILE_MACHINE_THUMB) { + + /* a.out header directly follows PE header */ + if (!fu_common_read_uint16_safe (buf, bufsz, + baseaddr + _PEI_HEADER_SIZE, + &machine, G_LITTLE_ENDIAN, error)) + return NULL; + if (machine != 0x010b) { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + "Invalid a.out machine type %04x", machine); + return NULL; + } + if (!fu_common_read_uint32_safe (buf, bufsz, + baseaddr + _PE_OFFSET_SIZE_OF_HEADERS, + &header_size, G_LITTLE_ENDIAN, error)) + return NULL; + + checksum_offset = baseaddr + _PE_OFFSET_CHECKSUM; + data_dir_debug_offset = baseaddr + _PE_OFFSET_DEBUG_TABLE_OFFSET; + + } else { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + "Invalid PE header machine %04x", machine); + return NULL; + } + + /* get sections */ + if (!fu_common_read_uint32_safe (buf, bufsz, + data_dir_debug_offset + sizeof(guint32), + &cert_table_size, G_LITTLE_ENDIAN, error)) + return NULL; + if (!fu_common_read_uint16_safe (buf, bufsz, + baseaddr + _PEI_OFFSET_NUMBER_OF_SECTIONS, + §ions, G_LITTLE_ENDIAN, error)) + return NULL; + g_debug ("number_of_sections: %u", sections); + + /* get header size */ + if (!fu_common_read_uint16_safe (buf, bufsz, + baseaddr + _PEI_OFFSET_OPTIONAL_HEADER_SIZE, + &opthdrsz, G_LITTLE_ENDIAN, error)) + return NULL; + g_debug ("optional_header_size: 0x%x", opthdrsz); + + /* first region: beginning to checksum_offset field */ + checksum_regions = g_ptr_array_new_with_free_func ((GDestroyNotify) fu_efi_image_region_free); + r = fu_efi_image_add_region (checksum_regions, "begin->cksum", 0x0, checksum_offset); + image_bytes += r->size + sizeof(guint32); + + /* second region: end of checksum_offset to certificate table entry */ + r = fu_efi_image_add_region (checksum_regions, "cksum->datadir[DEBUG]", + checksum_offset + sizeof(guint32), + data_dir_debug_offset); + image_bytes += r->size + sizeof(FuEfiImageDataDirEntry); + + /* third region: end of checksum_offset to end of headers */ + r = fu_efi_image_add_region (checksum_regions, "datadir[DEBUG]->headers", + data_dir_debug_offset + sizeof(FuEfiImageDataDirEntry), + header_size); + image_bytes += r->size; + + /* add COFF sections */ + offset_tmp = baseaddr + _PEI_HEADER_SIZE + opthdrsz; + for (guint i = 0; i < sections; i++) { + guint32 file_offset = 0; + guint32 file_size = 0; + gchar name[9] = { '\0' }; + + if (!fu_common_read_uint32_safe (buf, bufsz, + offset_tmp + _SECTION_HEADER_OFFSET_PTR, + &file_offset, G_LITTLE_ENDIAN, error)) + return NULL; + if (!fu_common_read_uint32_safe (buf, bufsz, + offset_tmp + _SECTION_HEADER_OFFSET_SIZE, + &file_size, G_LITTLE_ENDIAN, error)) + return NULL; + if (file_size == 0) + continue; + if (!fu_memcpy_safe ((guint8 *) name, sizeof(name), 0x0, /* dst */ + buf, bufsz, + offset_tmp + _SECTION_HEADER_OFFSET_NAME, /* src */ + sizeof(name) - 1, error)) + return NULL; + r = fu_efi_image_add_region (checksum_regions, name, file_offset, file_offset + file_size); + image_bytes += r->size; + + if (file_offset + r->size > bufsz) { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_DATA, + "file-aligned section %s extends beyond end of file", + r->name); + return NULL; + } + offset_tmp += _SECTION_HEADER_SIZE; + } + + /* make sure in order */ + g_ptr_array_sort (checksum_regions, fu_efi_image_region_sort_cb); + + /* for the data at the end of the image */ + if (image_bytes + cert_table_size < bufsz) { + fu_efi_image_add_region (checksum_regions, "endjunk", + image_bytes, bufsz - cert_table_size); + } else if (image_bytes + cert_table_size > bufsz) { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_DATA, + "checksum_offset areas outside image size"); + return NULL; + } + + /* calculate the checksum we would find in the dbx */ + for (guint i = 0; i < checksum_regions->len; i++) { + r = g_ptr_array_index (checksum_regions, i); + g_debug ("region %s: 0x%04x -> 0x%04x [0x%04x]", + r->name, + (guint) r->offset, + (guint) (r->offset + r->size - 1), + (guint) r->size); + g_checksum_update (checksum, + (const guchar *) buf + r->offset, + (gssize) r->size); + } + self->checksum = g_strdup (g_checksum_get_string (checksum)); + return g_steal_pointer (&self); +} + +const gchar * +fu_efi_image_get_checksum (FuEfiImage *self) +{ + return self->checksum; +} + +static void +fu_efi_image_finalize (GObject *obj) +{ + FuEfiImage *self = FU_EFI_IMAGE (obj); + g_free (self->checksum); + G_OBJECT_CLASS (fu_efi_image_parent_class)->finalize (obj); +} + +static void +fu_efi_image_class_init (FuEfiImageClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->finalize = fu_efi_image_finalize; +} + +static void +fu_efi_image_init (FuEfiImage *self) +{ +} diff --git a/plugins/uefi-dbx/fu-efi-image.h b/plugins/uefi-dbx/fu-efi-image.h new file mode 100644 index 000000000..64aebad42 --- /dev/null +++ b/plugins/uefi-dbx/fu-efi-image.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2020 Richard Hughes + * + * SPDX-License-Identifier: LGPL-2.1+ + */ + +#pragma once + +#include + +#define FU_TYPE_EFI_IMAGE (fu_efi_image_get_type ()) +G_DECLARE_FINAL_TYPE (FuEfiImage, fu_efi_image, FU, EFI_IMAGE, GObject) + +FuEfiImage *fu_efi_image_new (GBytes *data, + GError **error); +const gchar *fu_efi_image_get_checksum (FuEfiImage *self); diff --git a/plugins/uefi-dbx/fu-efi-signature-common.c b/plugins/uefi-dbx/fu-efi-signature-common.c index 00d43fe7f..825ac3266 100644 --- a/plugins/uefi-dbx/fu-efi-signature-common.c +++ b/plugins/uefi-dbx/fu-efi-signature-common.c @@ -9,7 +9,7 @@ #include "fu-efi-signature-common.h" #include "fu-efi-signature-list.h" -static gboolean +gboolean fu_efi_signature_list_array_has_checksum (GPtrArray *siglists, const gchar *checksum) { for (guint i = 0; i < siglists->len; i++) { diff --git a/plugins/uefi-dbx/fu-efi-signature-common.h b/plugins/uefi-dbx/fu-efi-signature-common.h index 48a89c64b..fe9511d1d 100644 --- a/plugins/uefi-dbx/fu-efi-signature-common.h +++ b/plugins/uefi-dbx/fu-efi-signature-common.h @@ -11,3 +11,5 @@ gboolean fu_efi_signature_list_array_inclusive (GPtrArray *outer, GPtrArray *inner); guint fu_efi_signature_list_array_version (GPtrArray *siglists); +gboolean fu_efi_signature_list_array_has_checksum (GPtrArray *siglists, + const gchar *checksum); diff --git a/plugins/uefi-dbx/fu-self-test.c b/plugins/uefi-dbx/fu-self-test.c index de8657b55..fb310e30f 100644 --- a/plugins/uefi-dbx/fu-self-test.c +++ b/plugins/uefi-dbx/fu-self-test.c @@ -8,9 +8,41 @@ #include +#include "fu-common.h" #include "fu-uefi-dbx-common.h" +#include "fu-efi-image.h" #include "fu-efi-signature-parser.h" +static gchar * +fu_test_get_filename (const gchar *filename) +{ + g_autofree gchar *path = NULL; + path = g_build_filename (TESTDATADIR, filename, NULL); + return fu_common_realpath (path, NULL); +} + +static void +fu_efi_image_func (void) +{ + const gchar *csum = NULL; + g_autofree gchar *fn = NULL; + g_autoptr(FuEfiImage) img = NULL; + g_autoptr(GBytes) bytes = NULL; + g_autoptr(GError) error = NULL; + + fn = fu_test_get_filename ("fwupdx64.efi"); + g_assert_nonnull (fn); + bytes = fu_common_get_contents_bytes (fn, &error); + g_assert_no_error (error); + g_assert_nonnull (bytes); + + img = fu_efi_image_new (bytes, &error); + g_assert_no_error (error); + g_assert_nonnull (img); + csum = fu_efi_image_get_checksum (img); + g_assert_cmpstr (csum, ==, "e99707d4378140c01eb3f867240d5cc9e237b126d3db0c3b4bbcd3da1720ddff"); +} + static void fu_efi_signature_list_parse_func (void) { @@ -55,6 +87,7 @@ main (int argc, char **argv) g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); /* tests go here */ + g_test_add_func ("/uefi-dbx/image", fu_efi_image_func); g_test_add_func ("/uefi-dbx/file-parse", fu_efi_signature_list_parse_func); return g_test_run (); } diff --git a/plugins/uefi-dbx/fu-uefi-dbx-common.c b/plugins/uefi-dbx/fu-uefi-dbx-common.c index 2971e81a6..bdcd0a44a 100644 --- a/plugins/uefi-dbx/fu-uefi-dbx-common.c +++ b/plugins/uefi-dbx/fu-uefi-dbx-common.c @@ -7,6 +7,10 @@ #include "config.h" #include "fu-common.h" +#include "fu-efi-image.h" +#include "fu-efi-signature-common.h" +#include "fu-volume.h" + #include "fu-uefi-dbx-common.h" gchar * @@ -26,3 +30,85 @@ fu_uefi_dbx_get_dbxupdate (GError **error) return NULL; return g_strdup (g_ptr_array_index (files, 0)); } + +gchar * +fu_uefi_dbx_get_authenticode_hash (const gchar *fn, GError **error) +{ + g_autoptr(FuEfiImage) img = NULL; + g_autoptr(GBytes) bytes = NULL; + g_autoptr(GMappedFile) mmap = NULL; + + g_debug ("getting Authenticode hash of %s", fn); + mmap = g_mapped_file_new (fn, FALSE, error); + if (mmap == NULL) + return NULL; + bytes = g_mapped_file_get_bytes (mmap); + + img = fu_efi_image_new (bytes, error); + if (img == NULL) + return NULL; + g_debug ("SHA256 was %s", fu_efi_image_get_checksum (img)); + return g_strdup (fu_efi_image_get_checksum (img)); +} + +static gboolean +fu_uefi_dbx_signature_list_validate_volume (GPtrArray *siglists, FuVolume *esp, GError **error) +{ + g_autofree gchar *esp_path = NULL; + g_autoptr(GPtrArray) files = NULL; + + /* get list of files contained in the ESP */ + esp_path = fu_volume_get_mount_point (esp); + if (esp_path == NULL) + return TRUE; + files = fu_common_get_files_recursive (esp_path, error); + if (files == NULL) + return FALSE; + + /* verify each file does not exist in the ESP */ + for (guint i = 0; i < files->len; i++) { + const gchar *fn = g_ptr_array_index (files, i); + g_autofree gchar *checksum = NULL; + g_autoptr(GError) error_local = NULL; + + /* get checksum of file */ + checksum = fu_uefi_dbx_get_authenticode_hash (fn, &error_local); + if (checksum == NULL) { + g_debug ("failed to get checksum for %s: %s", fn, error_local->message); + continue; + } + + /* Authenticode signature is present in dbx! */ + g_debug ("fn=%s, checksum=%s", fn, checksum); + if (fu_efi_signature_list_array_has_checksum (siglists, checksum)) { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_DATA, + "%s Authenticode checksum [%s] is present in dbx", + fn, checksum); + return FALSE; + } + } + + /* success */ + return TRUE; +} + +gboolean +fu_uefi_dbx_signature_list_validate (GPtrArray *siglists, GError **error) +{ + g_autoptr(GPtrArray) volumes = NULL; + volumes = fu_common_get_volumes_by_kind (FU_VOLUME_KIND_ESP, error); + if (volumes == NULL) + return FALSE; + for (guint i = 0; i < volumes->len; i++) { + FuVolume *esp = g_ptr_array_index (volumes, i); + g_autoptr(FuDeviceLocker) locker = NULL; + locker = fu_volume_locker (esp, error); + if (locker == NULL) + return FALSE; + if (!fu_uefi_dbx_signature_list_validate_volume (siglists, esp, error)) + return FALSE; + } + return TRUE; +} diff --git a/plugins/uefi-dbx/fu-uefi-dbx-common.h b/plugins/uefi-dbx/fu-uefi-dbx-common.h index fd4243217..de33f8805 100644 --- a/plugins/uefi-dbx/fu-uefi-dbx-common.h +++ b/plugins/uefi-dbx/fu-uefi-dbx-common.h @@ -8,4 +8,8 @@ #include -gchar *fu_uefi_dbx_get_dbxupdate (GError **error); +gchar *fu_uefi_dbx_get_dbxupdate (GError **error); +gchar *fu_uefi_dbx_get_authenticode_hash (const gchar *fn, + GError **error); +gboolean fu_uefi_dbx_signature_list_validate (GPtrArray *siglists, + GError **error); diff --git a/plugins/uefi-dbx/fu-uefi-dbx-device.c b/plugins/uefi-dbx/fu-uefi-dbx-device.c index 92e4c6d42..3236a1be2 100644 --- a/plugins/uefi-dbx/fu-uefi-dbx-device.c +++ b/plugins/uefi-dbx/fu-uefi-dbx-device.c @@ -10,6 +10,7 @@ #include "fu-efi-signature-common.h" #include "fu-efi-signature-parser.h" +#include "fu-uefi-dbx-common.h" #include "fu-uefi-dbx-device.h" struct _FuUefiDbxDevice { @@ -75,6 +76,40 @@ fu_uefi_dbx_device_set_version_number (FuDevice *device, GError **error) return TRUE; } +static FuFirmware * +fu_uefi_dbx_prepare_firmware (FuDevice *device, + GBytes *fw, + FwupdInstallFlags flags, + GError **error) +{ + const guint8 *buf; + gsize bufsz = 0; + g_autoptr(GPtrArray) siglists = NULL; + + /* parse dbx */ + fu_device_set_status (device, FWUPD_STATUS_DECOMPRESSING); + buf = g_bytes_get_data (fw, &bufsz); + siglists = fu_efi_signature_parser_new (buf, bufsz, + FU_EFI_SIGNATURE_PARSER_FLAGS_IGNORE_HEADER, + error); + if (siglists == NULL) + return NULL; + + /* validate this is safe to apply */ + if ((flags & FWUPD_INSTALL_FLAG_FORCE) == 0) { + fu_device_set_status (device, FWUPD_STATUS_DEVICE_VERIFY); + if (!fu_uefi_dbx_signature_list_validate (siglists, error)) { + g_prefix_error (error, + "Blocked executable in the ESP, " + "ensure grub and shim are up to date: "); + return NULL; + } + } + + /* default blob */ + return fu_firmware_new_from_bytes (fw); +} + static gboolean fu_uefi_dbx_device_probe (FuDevice *device, GError **error) { @@ -137,6 +172,7 @@ fu_uefi_dbx_device_class_init (FuUefiDbxDeviceClass *klass) FuDeviceClass *klass_device = FU_DEVICE_CLASS (klass); klass_device->probe = fu_uefi_dbx_device_probe; klass_device->write_firmware = fu_uefi_dbx_device_write_firmware; + klass_device->prepare_firmware = fu_uefi_dbx_prepare_firmware; } FuUefiDbxDevice * diff --git a/plugins/uefi-dbx/meson.build b/plugins/uefi-dbx/meson.build index a257c6bdd..6961dfab2 100644 --- a/plugins/uefi-dbx/meson.build +++ b/plugins/uefi-dbx/meson.build @@ -6,6 +6,7 @@ shared_module('fu_plugin_uefi_dbx', 'fu-plugin-uefi-dbx.c', 'fu-uefi-dbx-common.c', 'fu-uefi-dbx-device.c', + 'fu-efi-image.c', 'fu-efi-signature.c', 'fu-efi-signature-common.c', 'fu-efi-signature-list.c', @@ -29,12 +30,15 @@ shared_module('fu_plugin_uefi_dbx', ) if get_option('tests') + testdatadir = join_paths(meson.current_source_dir(), 'tests') + cargs += '-DTESTDATADIR="' + testdatadir + '"' e = executable( 'uefi-dbx-self-test', fu_hash, sources : [ 'fu-self-test.c', 'fu-uefi-dbx-common.c', + 'fu-efi-image.c', 'fu-efi-signature.c', 'fu-efi-signature-common.c', 'fu-efi-signature-list.c', @@ -52,6 +56,7 @@ if get_option('tests') fwupd, fwupdplugin, ], + c_args : cargs, ) test('uefi-dbx-self-test', e) endif @@ -60,10 +65,12 @@ uefi_dbx_fuzzer = executable( 'uefi-dbx-fuzzer', sources : [ 'fu-fuzzer.c', + 'fu-efi-image.c', 'fu-efi-signature.c', 'fu-efi-signature-common.c', 'fu-efi-signature-list.c', 'fu-efi-signature-parser.c', + 'fu-uefi-dbx-common.c', ], include_directories : [ root_incdir, @@ -84,6 +91,7 @@ dbxtool = executable( sources : [ 'fu-dbxtool.c', 'fu-uefi-dbx-common.c', + 'fu-efi-image.c', 'fu-efi-signature.c', 'fu-efi-signature-common.c', 'fu-efi-signature-list.c', diff --git a/plugins/uefi-dbx/tests/fwupdx64.efi b/plugins/uefi-dbx/tests/fwupdx64.efi new file mode 100755 index 000000000..8d38a5e8e Binary files /dev/null and b/plugins/uefi-dbx/tests/fwupdx64.efi differ