test(fvp): Test trusted key certificate corruption

This also includes a test framework for use with corrupting the
root of trust private key certificate in the boot FIP, found
using its UUID.

Signed-off-by: Jimmy Brisson <jimmy.brisson@arm.com>
Change-Id: I988c517637edcf6fdcaf271628eb650781c276f8
diff --git a/include/common/firmware_image_package.h b/include/common/firmware_image_package.h
index aba5b57..2a144ba 100644
--- a/include/common/firmware_image_package.h
+++ b/include/common/firmware_image_package.h
@@ -22,6 +22,8 @@
 	{{0x4f, 0x51, 0x1d, 0x11}, {0x2b, 0xe5}, {0x4e, 0x49}, 0xb4, 0xc5, {0x83, 0xc2, 0xf7, 0x15, 0x84, 0x0a} }
 #define UUID_FIRMWARE_UPDATE_FWU_CERT \
 	{{0x71, 0x40, 0x8a, 0xb2}, {0x18, 0xd6}, {0x87, 0x4c}, 0x8b, 0x2e, {0xc6, 0xdc, 0xcd, 0x50, 0xf0, 0x96} }
+#define UUID_TRUSTED_KEY_CERT \
+	{{0x82,  0x7e, 0xe8, 0x90}, {0xf8, 0x60}, {0xe4, 0x11}, 0xa1, 0xb4, {0x77, 0x7a, 0x21, 0xb4, 0xf9, 0x4c} }
 
 typedef struct fip_toc_header {
 	uint32_t	name;
diff --git a/include/lib/tftf_lib.h b/include/lib/tftf_lib.h
index 8eff7fc..36e2e0f 100644
--- a/include/lib/tftf_lib.h
+++ b/include/lib/tftf_lib.h
@@ -38,6 +38,23 @@
 #define TEST_RESULT_IS_VALID(result) \
 	((result >= TEST_RESULT_MIN) && (result < TEST_RESULT_MAX))
 
+#define TEST_ASSERT(must_be_true) \
+	do { \
+		if (!(must_be_true)) { \
+			tftf_testcase_printf("Failed at %s:%d\n", __FILE__, __LINE__); \
+			return TEST_RESULT_FAIL;\
+		} \
+	} while (0)
+
+#define TEST_ASSERT_SKIP(must_be_true) \
+	do { \
+		if (!(must_be_true)) { \
+			tftf_testcase_printf("Failed at %s:%d\n", __FILE__, __LINE__); \
+			return TEST_RESULT_SKIPPED;\
+		} \
+	} while (0)
+
+
 /*
  * PSCI Function Wrappers
  *
diff --git a/plat/arm/fvp/include/platform_def.h b/plat/arm/fvp/include/platform_def.h
index b8871c4..e6ae4d7 100644
--- a/plat/arm/fvp/include/platform_def.h
+++ b/plat/arm/fvp/include/platform_def.h
@@ -89,6 +89,12 @@
 #define SECURE_MEMORY_ACCESS_ADDR		U(0xFD000000)
 
 /*******************************************************************************
+ * Base address and size for the FIP.
+ ******************************************************************************/
+#define PLAT_ARM_FIP_BASE		(FLASH_BASE)
+#define PLAT_ARM_FIP_SIZE		(0x100000)
+
+/*******************************************************************************
  * Base address and size for the FIP that contains FWU images.
  ******************************************************************************/
 #define PLAT_ARM_FWU_FIP_BASE		(FLASH_BASE + 0x400000)
diff --git a/tftf/tests/tbb-tests/tbb_test_infra.c b/tftf/tests/tbb-tests/tbb_test_infra.c
new file mode 100644
index 0000000..dc8ae38
--- /dev/null
+++ b/tftf/tests/tbb-tests/tbb_test_infra.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "tbb_test_infra.h"
+
+#include <fwu_nvm.h>
+#include <io_storage.h>
+#include <platform.h>
+#include <status.h>
+#include <test_helpers.h>
+#include <tftf_lib.h>
+
+test_result_t test_corrupt_boot_fip(unsigned int offset)
+{
+	unsigned int flag = 0xDEADBEEF;
+	size_t written = 0;
+	uintptr_t dev_handle;
+	int result;
+
+	if (tftf_is_rebooted()) {
+		/* FIP successfully repaired */
+		return TEST_RESULT_SUCCESS;
+	}
+
+	/* Corrupt the FIP at the provided offset */
+	plat_get_nvm_handle(&dev_handle);
+	result = io_seek(dev_handle, IO_SEEK_SET, offset);
+	TEST_ASSERT(result == IO_SUCCESS);
+	result = io_write(dev_handle, (uintptr_t) &flag, sizeof(flag), &written);
+	TEST_ASSERT(result == IO_SUCCESS);
+	TEST_ASSERT(written == sizeof(flag));
+
+	/*
+	 * Now reboot the system.
+	 * On the next boot, EL3 firmware should notice and repair the corruption
+	 * before re-entering TFTF
+	 */
+
+	tftf_notify_reboot();
+	psci_system_reset();
+	return TEST_RESULT_FAIL;
+}
diff --git a/tftf/tests/tbb-tests/tbb_test_infra.h b/tftf/tests/tbb-tests/tbb_test_infra.h
new file mode 100644
index 0000000..e6bf0e5
--- /dev/null
+++ b/tftf/tests/tbb-tests/tbb_test_infra.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TBB_TEST_INFRA_H_INCLUDED
+#define TBB_TEST_INFRA_H_INCLUDED
+
+#include <tftf_lib.h>
+
+test_result_t test_corrupt_boot_fip(unsigned int offset);
+
+#endif /* TBB_TEST_INFRA_H_INCLUDED */
+
diff --git a/tftf/tests/tbb-tests/test_tbb_corrupt_fip.c b/tftf/tests/tbb-tests/test_tbb_corrupt_fip.c
new file mode 100644
index 0000000..135efee
--- /dev/null
+++ b/tftf/tests/tbb-tests/test_tbb_corrupt_fip.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <uuid.h>
+
+#include "tbb_test_infra.h"
+
+#include <firmware_image_package.h>
+#include <platform.h>
+#include <tftf_lib.h>
+#include <uuid_utils.h>
+
+/*
+ * Return the offset relative to the base of the FIP of
+ * the image described by the uuid. 0 is returned on failure.
+ * The first image will not have an offset of 0, as the header
+ * exists at offset 0.
+ */
+static unsigned int
+find_offset_in_fip(const uuid_t *uuid)
+{
+	fip_toc_entry_t *current_file =
+		(fip_toc_entry_t *) (PLAT_ARM_FIP_BASE + sizeof(fip_toc_header_t));
+
+	while (!is_uuid_null(&(current_file->uuid))) {
+		if (uuid_equal(&(current_file->uuid), uuid)) {
+			return current_file->offset_address;
+		}
+		current_file += 1;
+	};
+	return 0;
+}
+
+test_result_t test_tbb_tkey_cert_header(void)
+{
+	static const uuid_t tkey_cert_uuid = UUID_TRUSTED_KEY_CERT;
+	unsigned int image_offset = find_offset_in_fip(&tkey_cert_uuid);
+
+	TEST_ASSERT_SKIP(image_offset != 0);
+	return test_corrupt_boot_fip(image_offset);
+}
+
diff --git a/tftf/tests/tests-corrupt-fip.mk b/tftf/tests/tests-corrupt-fip.mk
new file mode 100644
index 0000000..22fa686
--- /dev/null
+++ b/tftf/tests/tests-corrupt-fip.mk
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2023, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+TESTS_SOURCES	+=	$(addprefix tftf/tests/tbb-tests/,	\
+	test_tbb_corrupt_fip.c						\
+	tbb_test_infra.c						\
+)
+
+TESTS_SOURCES	+=	plat/common/fwu_nvm_accessors.c \
+	plat/arm/common/arm_fwu_io_storage.c \
+	drivers/io/io_fip.c \
+	drivers/io/io_memmap.c
diff --git a/tftf/tests/tests-corrupt-fip.xml b/tftf/tests/tests-corrupt-fip.xml
new file mode 100644
index 0000000..6bfa4a4
--- /dev/null
+++ b/tftf/tests/tests-corrupt-fip.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright (c) 2023, Arm Limited. All rights reserved.
+
+  SPDX-License-Identifier: BSD-3-Clause
+-->
+
+<testsuites>
+
+  <testsuite name="tbb corrupt trusted key header" description="The FIP is corrupted before update">
+     <testcase name="tbb bad tkey cert header" function="test_tbb_tkey_cert_header" />
+  </testsuite>
+
+</testsuites>