Commit 48c6e7dc authored by Jithu Joseph's avatar Jithu Joseph Committed by Borislav Petkov
Browse files

platform/x86/intel/ifs: Add metadata validation



The data portion of a IFS test image file contains a metadata region
containing possibly multiple metadata structures in addition to test
data and hashes.

    IFS Metadata layout
   +----------------------+  0
   |META_TYPE_IFS (=1)    |
   +----------------------+
   |meta_size             |
   +----------------------+
   |test type             |
   +----------------------+
   |fusa info             |
   +----------------------+
   |total images          |
   +----------------------+
   |current image#        |
   +----------------------+
   |total chunks          |
   +----------------------+
   |starting chunk        |
   +----------------------+
   |size per chunk        |
   +----------------------+
   |chunks per stride     |
   +----------------------+
   |Reserved[54]          |
   +----------------------+ 256
   |                      |
   |  Test Data/Chunks    |
   |                      |
   +----------------------+  meta_size
   |   META_TYPE_END (=0) |
   +----------------------+  meta_size + 4
   |   size of end (=8)   |
   +----------------------+  meta_size + 8

Introduce the layout of this meta_data structure and validate
the sanity of certain fields of the new image before loading.

Tweak references to IFS test image chunks to reflect the updated
layout of the test image.

  [ bp: Massage commit message. ]

Signed-off-by: default avatarJithu Joseph <jithu.joseph@intel.com>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Reviewed-by: default avatarTony Luck <tony.luck@intel.com>
Reviewed-by: default avatarSohil Mehta <sohil.mehta@intel.com>
Reviewed-by: default avatarHans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20221117230408.30331-1-jithu.joseph@intel.com
parent aa63e0fd
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -197,6 +197,7 @@ union ifs_status {
 * @valid_chunks: number of chunks which could be validated.
 * @status: it holds simple status pass/fail/untested
 * @scan_details: opaque scan status code from h/w
 * @cur_batch: number indicating the currently loaded test file
 */
struct ifs_data {
	int	integrity_cap_bit;
@@ -207,6 +208,7 @@ struct ifs_data {
	int	valid_chunks;
	int	status;
	u64	scan_details;
	u32	cur_batch;
};

struct ifs_work {
+57 −1
Original line number Diff line number Diff line
@@ -7,7 +7,25 @@

#include "ifs.h"

#define IFS_CHUNK_ALIGNMENT	256
union meta_data {
	struct {
		u32 meta_type;		// metadata type
		u32 meta_size;		// size of this entire struct including hdrs.
		u32 test_type;		// IFS test type
		u32 fusa_info;		// Fusa info
		u32 total_images;	// Total number of images
		u32 current_image;	// Current Image #
		u32 total_chunks;	// Total number of chunks in this image
		u32 starting_chunk;	// Starting chunk number in this image
		u32 size_per_chunk;	// size of each chunk
		u32 chunks_per_stride;	// number of chunks in a stride
	};
	u8 padding[IFS_CHUNK_ALIGNMENT];
};

#define IFS_HEADER_SIZE	(sizeof(struct microcode_header_intel))
#define META_TYPE_IFS	1
static  struct microcode_header_intel *ifs_header_ptr;	/* pointer to the ifs image header */
static u64 ifs_hash_ptr;			/* Address of ifs metadata (hash) */
static u64 ifs_test_image_ptr;			/* 256B aligned address of test pattern */
@@ -128,6 +146,41 @@ static void copy_hashes_authenticate_chunks(struct work_struct *work)
	complete(&ifs_done);
}

static int validate_ifs_metadata(struct device *dev)
{
	struct ifs_data *ifsd = ifs_get_data(dev);
	union meta_data *ifs_meta;
	char test_file[64];
	int ret = -EINVAL;

	snprintf(test_file, sizeof(test_file), "%02x-%02x-%02x-%02x.scan",
		 boot_cpu_data.x86, boot_cpu_data.x86_model,
		 boot_cpu_data.x86_stepping, ifsd->cur_batch);

	ifs_meta = (union meta_data *)find_meta_data(ifs_header_ptr, META_TYPE_IFS);
	if (!ifs_meta) {
		dev_err(dev, "IFS Metadata missing in file %s\n", test_file);
		return ret;
	}

	ifs_test_image_ptr = (u64)ifs_meta + sizeof(union meta_data);

	/* Scan chunk start must be 256 byte aligned */
	if (!IS_ALIGNED(ifs_test_image_ptr, IFS_CHUNK_ALIGNMENT)) {
		dev_err(dev, "Scan pattern is not aligned on %d bytes aligned in %s\n",
			IFS_CHUNK_ALIGNMENT, test_file);
		return ret;
	}

	if (ifs_meta->current_image != ifsd->cur_batch) {
		dev_warn(dev, "Mismatch between filename %s and batch metadata 0x%02x\n",
			 test_file, ifs_meta->current_image);
		return ret;
	}

	return 0;
}

/*
 * IFS requires scan chunks authenticated per each socket in the platform.
 * Once the test chunk is authenticated, it is automatically copied to secured memory
@@ -139,8 +192,11 @@ static int scan_chunks_sanity_check(struct device *dev)
	struct ifs_work local_work;
	int curr_pkg, cpu, ret;


	memset(ifsd->pkg_auth, 0, (topology_max_packages() * sizeof(bool)));
	ret = validate_ifs_metadata(dev);
	if (ret)
		return ret;

	ifsd->loading_error = false;
	ifsd->loaded_version = ifs_header_ptr->rev;