summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJi Luo <ji.luo@nxp.com>2022-05-24 17:02:56 +0800
committerJi Luo <ji.luo@nxp.com>2022-05-25 12:00:49 +0800
commit587c0e19a32ac49e681c8e05926e10cb9a9a43a7 (patch)
tree867a0313c67fa75d491b019e3ab63dd4f52fa0f6
parent6c10cfe481c32cec642a2e09a8cece25982915aa (diff)
MA-20303-1 Support rollback index check for single bootloader
Add support to check the rollback index of next stage images (ATF, TEE, u-boot proper) in SPL to harden the security. And because there is no backup bootloader image to fall back to so the board would hang in SPL if rollback index is rejected. Change-Id: I4c7d1f084dd5b3d37899a9e4c4755c03145542c7 Signed-off-by: Ji Luo <ji.luo@nxp.com>
-rw-r--r--arch/arm/mach-imx/parse-container.c3
-rw-r--r--arch/arm/mach-imx/spl.c7
-rw-r--r--common/spl/spl_fit.c4
-rw-r--r--common/spl/spl_mmc.c4
-rw-r--r--disk/part_efi.c14
-rw-r--r--include/part.h4
-rw-r--r--include/spl.h2
-rw-r--r--lib/avb/fsl/fsl_avbkey.c12
-rw-r--r--lib/avb/fsl/fsl_avbkey.h2
-rwxr-xr-xlib/avb/fsl/fsl_bootctrl.c219
10 files changed, 167 insertions, 104 deletions
diff --git a/arch/arm/mach-imx/parse-container.c b/arch/arm/mach-imx/parse-container.c
index 503d2cf796..334fe3b12e 100644
--- a/arch/arm/mach-imx/parse-container.c
+++ b/arch/arm/mach-imx/parse-container.c
@@ -139,8 +139,7 @@ static int read_auth_container(struct spl_image_info *spl_image,
}
}
-#if defined(CONFIG_SPL_BUILD) && \
- defined(CONFIG_DUAL_BOOTLOADER) && defined(CONFIG_IMX_TRUSTY_OS)
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_IMX_TRUSTY_OS)
/* Everything checks out, get the sw_version now. */
spl_image->rbindex = (uint64_t)container->sw_version;
#endif
diff --git a/arch/arm/mach-imx/spl.c b/arch/arm/mach-imx/spl.c
index 2995ba4281..ea709d15a5 100644
--- a/arch/arm/mach-imx/spl.c
+++ b/arch/arm/mach-imx/spl.c
@@ -458,10 +458,15 @@ void board_spl_fit_post_load(const void *fit, struct spl_image_info *spl_image)
}
#ifdef CONFIG_IMX_TRUSTY_OS
+int check_rollback_index(struct spl_image_info *spl_image, struct mmc *mmc);
int check_rpmb_blob(struct mmc *mmc);
-int mmc_image_load_late(struct mmc *mmc)
+int mmc_image_load_late(struct spl_image_info *spl_image, struct mmc *mmc)
{
+ /* Check the rollback index of next stage image */
+ if (check_rollback_index(spl_image, mmc) < 0)
+ return -1;
+
/* Check the rpmb key blob for trusty enabled platfrom. */
return check_rpmb_blob(mmc);
}
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index b40d604c05..9d5a6dccec 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -67,7 +67,7 @@ static int find_node_from_desc(const void *fit, int node, const char *str)
return -ENOENT;
}
-#ifdef CONFIG_DUAL_BOOTLOADER
+#ifdef CONFIG_IMX_TRUSTY_OS
extern int spl_fit_get_rbindex(const void *fit);
#endif
@@ -741,7 +741,7 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
if (ret < 0)
return ret;
-#if defined(CONFIG_DUAL_BOOTLOADER) && defined(CONFIG_IMX_TRUSTY_OS)
+#ifdef CONFIG_IMX_TRUSTY_OS
int rbindex;
rbindex = spl_fit_get_rbindex(ctx.fit);
if (rbindex < 0) {
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index 591c238a63..cbbd166eb3 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -82,7 +82,7 @@ int mmc_load_image_raw_sector_dual_uboot(struct spl_image_info *spl_image,
struct mmc *mmc);
#endif
-int __weak mmc_image_load_late(struct mmc *mmc)
+int __weak mmc_image_load_late(struct spl_image_info *spl_image, struct mmc *mmc)
{
return 0;
}
@@ -140,7 +140,7 @@ end:
return -1;
}
- ret = mmc_image_load_late(mmc);
+ ret = mmc_image_load_late(spl_image, mmc);
return ret;
}
diff --git a/disk/part_efi.c b/disk/part_efi.c
index e810d9e938..e1d9dced03 100644
--- a/disk/part_efi.c
+++ b/disk/part_efi.c
@@ -272,7 +272,7 @@ void part_print_efi(struct blk_desc *dev_desc)
printf("\tguid:\t%pUl\n", uuid);
}
-#if !defined(CONFIG_DUAL_BOOTLOADER) || !defined(CONFIG_SPL_BUILD)
+#if !(defined(CONFIG_DUAL_BOOTLOADER) || defined(CONFIG_IMX_TRUSTY_OS)) || !defined(CONFIG_SPL_BUILD)
/* Remember to free pte */
free(gpt_pte);
#endif
@@ -299,7 +299,7 @@ int part_get_info_efi(struct blk_desc *dev_desc, int part,
!is_pte_valid(&gpt_pte[part - 1])) {
debug("%s: *** ERROR: Invalid partition number %d ***\n",
__func__, part);
-#if !defined(CONFIG_DUAL_BOOTLOADER) || !defined(CONFIG_SPL_BUILD)
+#if !(defined(CONFIG_DUAL_BOOTLOADER) || defined(CONFIG_IMX_TRUSTY_OS)) || !defined(CONFIG_SPL_BUILD)
free(gpt_pte);
#endif
return -1;
@@ -328,7 +328,7 @@ int part_get_info_efi(struct blk_desc *dev_desc, int part,
debug("%s: start 0x" LBAF ", size 0x" LBAF ", name %s\n", __func__,
info->start, info->size, info->name);
-#if !defined(CONFIG_DUAL_BOOTLOADER) || !defined(CONFIG_SPL_BUILD)
+#if !(defined(CONFIG_DUAL_BOOTLOADER) || defined(CONFIG_IMX_TRUSTY_OS)) || !defined(CONFIG_SPL_BUILD)
/* Heap memory is very limited in SPL, if the dual bootloader is
* enabled, just load pte to dram instead of oc-ram. In such case,
* this part of memory shouldn't be freed. But in common routine,
@@ -339,7 +339,7 @@ int part_get_info_efi(struct blk_desc *dev_desc, int part,
return 0;
}
-#if defined(CONFIG_DUAL_BOOTLOADER) && defined(CONFIG_SPL_BUILD)
+#if (defined(CONFIG_DUAL_BOOTLOADER) || defined(CONFIG_IMX_TRUSTY_OS)) && defined(CONFIG_SPL_BUILD)
int part_get_info_efi_by_name(struct blk_desc *dev_desc, const char *name,
struct disk_partition *info)
{
@@ -393,7 +393,7 @@ int part_get_info_efi_by_name(struct blk_desc *dev_desc, const char *name,
return -1;
}
-#endif /* CONFIG_DUAL_BOOTLOADER && CONFIG_SPL_BUILD */
+#endif /* (CONFIG_DUAL_BOOTLOADER || CONFIG_IMX_TRUSTY_OS) && CONFIG_SPL_BUILD */
static int part_test_efi(struct blk_desc *dev_desc)
{
@@ -1196,7 +1196,7 @@ static gpt_entry *alloc_read_gpt_entries(struct blk_desc *dev_desc,
* don't forget to free the memory after use.
*/
if (count != 0) {
-#if defined(CONFIG_DUAL_BOOTLOADER) && defined(CONFIG_SPL_BUILD)
+#if (defined(CONFIG_DUAL_BOOTLOADER) || defined(CONFIG_IMX_TRUSTY_OS)) && defined(CONFIG_SPL_BUILD)
pte = (gpt_entry *)CONFIG_SYS_SPL_PTE_RAM_BASE;
#else
pte = memalign(ARCH_DMA_MINALIGN,
@@ -1215,7 +1215,7 @@ static gpt_entry *alloc_read_gpt_entries(struct blk_desc *dev_desc,
blk_cnt = BLOCK_CNT(count, dev_desc);
if (blk_dread(dev_desc, blk, (lbaint_t)blk_cnt, pte) != blk_cnt) {
printf("*** ERROR: Can't read GPT Entries ***\n");
-#if !defined(CONFIG_DUAL_BOOTLOADER) || !defined(CONFIG_SPL_BUILD)
+#if !(defined(CONFIG_DUAL_BOOTLOADER) || defined(CONFIG_IMX_TRUSTY_OS)) || !defined(CONFIG_SPL_BUILD)
free(pte);
#endif
return NULL;
diff --git a/include/part.h b/include/part.h
index 8594251166..1db0db4d9c 100644
--- a/include/part.h
+++ b/include/part.h
@@ -297,7 +297,7 @@ part_get_info_by_dev_and_name_or_num(const char *dev_iface,
# define part_print_ptr(x) NULL
# if defined(CONFIG_SPL_FS_EXT4) || defined(CONFIG_SPL_FS_FAT) || \
defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION) || \
- defined(CONFIG_DUAL_BOOTLOADER)
+ defined(CONFIG_DUAL_BOOTLOADER) || defined(CONFIG_IMX_TRUSTY_OS)
# define part_get_info_ptr(x) x
# else
# define part_get_info_ptr(x) NULL
@@ -479,7 +479,7 @@ int gpt_verify_partitions(struct blk_desc *dev_desc,
*/
int get_disk_guid(struct blk_desc *dev_desc, char *guid);
-#if defined(CONFIG_DUAL_BOOTLOADER) && defined(CONFIG_SPL_BUILD)
+#if (defined(CONFIG_DUAL_BOOTLOADER) || defined(CONFIG_IMX_TRUSTY_OS)) && defined(CONFIG_SPL_BUILD)
int part_get_info_efi_by_name(struct blk_desc *dev_desc, const char *name,
struct disk_partition *info);
#endif
diff --git a/include/spl.h b/include/spl.h
index d44903fc0c..951616b895 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -229,7 +229,7 @@ struct spl_image_info {
ulong dcrc_length;
ulong dcrc;
#endif
-#ifdef CONFIG_DUAL_BOOTLOADER
+#ifdef CONFIG_IMX_TRUSTY_OS
uint64_t rbindex;
#endif
};
diff --git a/lib/avb/fsl/fsl_avbkey.c b/lib/avb/fsl/fsl_avbkey.c
index d01b1931cb..096492dbe6 100644
--- a/lib/avb/fsl/fsl_avbkey.c
+++ b/lib/avb/fsl/fsl_avbkey.c
@@ -483,7 +483,7 @@ fail:
}
int rpmb_init(void) {
-#if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_DUAL_BOOTLOADER)
+#if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_IMX_TRUSTY_OS)
int i;
#endif
kblb_hdr_t hdr;
@@ -502,7 +502,7 @@ int rpmb_init(void) {
* RPMB which is different from the rollback index for vbmeta and
* ATX key versions.
*/
-#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_DUAL_BOOTLOADER)
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_IMX_TRUSTY_OS)
if (rpmb_read(mmc_dev, (uint8_t *)&hdr, sizeof(hdr),
BOOTLOADER_RBIDX_OFFSET) != 0) {
#else
@@ -516,7 +516,7 @@ int rpmb_init(void) {
else
printf("initialize rollback index...\n");
/* init rollback index */
-#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_DUAL_BOOTLOADER)
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_IMX_TRUSTY_OS)
offset = BOOTLOADER_RBIDX_START;
rbidx_len = BOOTLOADER_RBIDX_LEN;
rbidx = malloc(rbidx_len);
@@ -536,7 +536,7 @@ int rpmb_init(void) {
}
if (rbidx != NULL)
free(rbidx);
-#else /* CONFIG_SPL_BUILD && CONFIG_DUAL_BOOTLOADER */
+#else /* CONFIG_SPL_BUILD && CONFIG_IMX_TRUSTY_OS */
offset = AVB_RBIDX_START;
rbidx_len = AVB_RBIDX_LEN;
rbidx = malloc(rbidx_len);
@@ -582,11 +582,11 @@ int rpmb_init(void) {
if (rbidx != NULL)
free(rbidx);
#endif
-#endif /* CONFIG_SPL_BUILD && CONFIG_DUAL_BOOTLOADER */
+#endif /* CONFIG_SPL_BUILD && CONFIG_IMX_TRUSTY_OS */
/* init hdr */
memcpy(hdr.magic, AVB_KBLB_MAGIC, AVB_KBLB_MAGIC_LEN);
-#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_DUAL_BOOTLOADER)
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_IMX_TRUSTY_OS)
if (rpmb_write(mmc_dev, (uint8_t *)&hdr, sizeof(hdr),
BOOTLOADER_RBIDX_OFFSET) != 0) {
#else
diff --git a/lib/avb/fsl/fsl_avbkey.h b/lib/avb/fsl/fsl_avbkey.h
index a4343e06d3..2d6adf02be 100644
--- a/lib/avb/fsl/fsl_avbkey.h
+++ b/lib/avb/fsl/fsl_avbkey.h
@@ -66,7 +66,7 @@ struct kblb_hdr {
/* Rollback index for bootloader is managed by SPL and
* will be stored in RPMB.
*/
-#if defined(CONFIG_DUAL_BOOTLOADER) && defined(CONFIG_SPL_BUILD)
+#if defined(CONFIG_IMX_TRUSTY_OS) && defined(CONFIG_SPL_BUILD)
kblb_tag_t bootloader_rbk_tags;
#endif
/* public key keyblb tag */
diff --git a/lib/avb/fsl/fsl_bootctrl.c b/lib/avb/fsl/fsl_bootctrl.c
index 36db39eea9..797503a857 100755
--- a/lib/avb/fsl/fsl_bootctrl.c
+++ b/lib/avb/fsl/fsl_bootctrl.c
@@ -455,55 +455,11 @@ out:
return ret;
}
-
-/* Below are the A/B AVB flow in spl and uboot proper. */
-#if defined(CONFIG_DUAL_BOOTLOADER) && defined(CONFIG_SPL_BUILD)
-
-#define PARTITION_NAME_LEN 13
-#define PARTITION_BOOTLOADER "bootloader"
-
-extern int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value);
-
-/* Pre-declaration of h_spl_load_read(), see detail implementation in
- * common/spl/spl_mmc.c.
- */
-ulong h_spl_load_read(struct spl_load_info *load, ulong sector,
- ulong count, void *buf);
-
-/* Writes A/B metadata to disk only if it has changed.
- */
-int fsl_save_metadata_if_changed_dual_uboot(struct blk_desc *dev_desc,
- struct bootloader_control* ab_data,
- struct bootloader_control* ab_data_orig) {
- struct bootloader_control serialized;
- size_t num_bytes;
- struct disk_partition info;
-
- /* Save metadata if changed. */
- if (memcmp(ab_data, ab_data_orig, sizeof(struct bootloader_control)) != 0) {
- /* Get misc partition info */
- if (part_get_info_efi_by_name(dev_desc, FASTBOOT_PARTITION_MISC, &info) == -1) {
- printf("Can't get partition info of partition: misc\n");
- return -1;
- }
-
- /* Writing A/B metadata to disk. */
- fsl_avb_ab_data_update_crc_and_byteswap(ab_data, &serialized);
- if (write_to_partition_in_bytes(dev_desc, &info,
- FSL_AB_METADATA_MISC_PARTITION_OFFSET,
- sizeof(struct bootloader_control),
- (void *)&serialized, &num_bytes) ||
- (num_bytes != sizeof(struct bootloader_control))) {
- printf("Error--write metadata fail!\n");
- return -1;
- }
- }
- return 0;
-}
-
+#ifdef CONFIG_SPL_BUILD
/* Load metadate from misc partition.
*/
-int fsl_load_metadata_dual_uboot(struct blk_desc *dev_desc,
+#if defined(CONFIG_IMX_TRUSTY_OS) || defined(CONFIG_DUAL_BOOTLOADER)
+int spl_fsl_load_metadata(struct blk_desc *dev_desc,
struct bootloader_control* ab_data,
struct bootloader_control* ab_data_orig) {
struct disk_partition info;
@@ -549,8 +505,9 @@ int fsl_load_metadata_dual_uboot(struct blk_desc *dev_desc,
}
}
}
+#endif /* CONFIG_IMX_TRUSTY_OS || CONFIG_DUAL_BOOTLOADER */
-#if !defined(CONFIG_XEN) && defined(CONFIG_IMX_TRUSTY_OS)
+#ifdef CONFIG_IMX_TRUSTY_OS
static int spl_verify_rbidx(struct mmc *mmc, struct slot_metadata *slot,
struct spl_image_info *spl_image)
{
@@ -610,7 +567,139 @@ static int spl_verify_rbidx(struct mmc *mmc, struct slot_metadata *slot,
}
}
-#endif /* !CONFIG_XEN && CONFIG_IMX_TRUSTY_OS */
+/*
+ * spl_fit_get_rbindex(): Get rollback index of the bootloader.
+ * @fit: Pointer to the FDT blob.
+ *
+ * Return: the rollback index value of bootloader or a negative
+ * error number.
+ */
+int spl_fit_get_rbindex(const void *fit)
+{
+ const char *str;
+ uint64_t index;
+ int conf_node;
+ int len;
+
+ conf_node = fit_find_config_node(fit);
+ if (conf_node < 0) {
+ return conf_node;
+ }
+
+ str = fdt_getprop(fit, conf_node, "rbindex", &len);
+ if (!str) {
+ debug("cannot find property 'rbindex'\n");
+ return -EINVAL;
+ }
+
+ index = simple_strtoul(str, NULL, 10);
+
+ return index;
+}
+
+int check_rollback_index(struct spl_image_info *spl_image, struct mmc *mmc)
+{
+ struct disk_partition info;
+ struct blk_desc *desc;
+ struct bootloader_control ab_data, ab_data_orig;
+ size_t target_slot;
+ int ret = -1;
+ unsigned char original_part;
+
+ /* Only checks rollback index when rpmb key is set */
+ if (!rpmbkey_is_set()) {
+ printf("RPMB key is not set.\n");
+ return 0;
+ }
+
+ /* Check if gpt is valid */
+ desc = mmc_get_blk_desc(mmc);
+ if (desc) {
+ /* switch to user partition of eMMC */
+ original_part = desc->hwpart;
+ if (desc->hwpart != 0) {
+ if (mmc_switch_part(mmc, 0) != 0)
+ return -1;
+ desc->hwpart = 0;
+ }
+
+ if (part_get_info(desc, 1, &info)) {
+ printf("GPT is invalid, please flash correct GPT!\n");
+ ret = -1;
+ goto fail;
+ }
+ } else {
+ printf("Get block desc fail!\n");
+ return -1;
+ }
+
+ /* Load AB metadata from misc partition */
+ if (spl_fsl_load_metadata(desc, &ab_data, &ab_data_orig)) {
+ ret = -1;
+ goto fail;
+ }
+ target_slot = (ab_data.slot_info[1].priority > ab_data.slot_info[0].priority) ? 1 : 0;
+
+ ret = spl_verify_rbidx(mmc, &ab_data.slot_info[target_slot], spl_image);
+
+fail:
+ /* Return to original partition */
+ if (desc->hwpart != original_part) {
+ if (mmc_switch_part(mmc, original_part) != 0)
+ ret = -1;
+ else
+ desc->hwpart = original_part;
+ }
+
+ return ret;
+}
+#endif /* CONFIG_IMX_TRUSTY_OS */
+#endif /* CONFIG_SPL_BUILD */
+
+/* Below are the A/B AVB flow in spl and uboot proper. */
+#if defined(CONFIG_DUAL_BOOTLOADER) && defined(CONFIG_SPL_BUILD)
+
+#define PARTITION_NAME_LEN 13
+#define PARTITION_BOOTLOADER "bootloader"
+
+extern int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value);
+
+/* Pre-declaration of h_spl_load_read(), see detail implementation in
+ * common/spl/spl_mmc.c.
+ */
+ulong h_spl_load_read(struct spl_load_info *load, ulong sector,
+ ulong count, void *buf);
+
+/* Writes A/B metadata to disk only if it has changed.
+ */
+int fsl_save_metadata_if_changed_dual_uboot(struct blk_desc *dev_desc,
+ struct bootloader_control* ab_data,
+ struct bootloader_control* ab_data_orig) {
+ struct bootloader_control serialized;
+ size_t num_bytes;
+ struct disk_partition info;
+
+ /* Save metadata if changed. */
+ if (memcmp(ab_data, ab_data_orig, sizeof(struct bootloader_control)) != 0) {
+ /* Get misc partition info */
+ if (part_get_info_efi_by_name(dev_desc, FASTBOOT_PARTITION_MISC, &info) == -1) {
+ printf("Can't get partition info of partition: misc\n");
+ return -1;
+ }
+
+ /* Writing A/B metadata to disk. */
+ fsl_avb_ab_data_update_crc_and_byteswap(ab_data, &serialized);
+ if (write_to_partition_in_bytes(dev_desc, &info,
+ FSL_AB_METADATA_MISC_PARTITION_OFFSET,
+ sizeof(struct bootloader_control),
+ (void *)&serialized, &num_bytes) ||
+ (num_bytes != sizeof(struct bootloader_control))) {
+ printf("Error--write metadata fail!\n");
+ return -1;
+ }
+ }
+ return 0;
+}
int mmc_load_image_raw_sector_dual_uboot(struct spl_image_info *spl_image,
struct mmc *mmc)
@@ -652,7 +741,7 @@ int mmc_load_image_raw_sector_dual_uboot(struct spl_image_info *spl_image,
#endif
/* Load AB metadata from misc partition */
- if (fsl_load_metadata_dual_uboot(dev_desc, &ab_data,
+ if (spl_fsl_load_metadata(dev_desc, &ab_data,
&ab_data_orig)) {
return -1;
}
@@ -825,36 +914,6 @@ end:
return 0;
}
-/*
- * spl_fit_get_rbindex(): Get rollback index of the bootloader.
- * @fit: Pointer to the FDT blob.
- *
- * Return: the rollback index value of bootloader or a negative
- * error number.
- */
-int spl_fit_get_rbindex(const void *fit)
-{
- const char *str;
- uint64_t index;
- int conf_node;
- int len;
-
- conf_node = fit_find_config_node(fit);
- if (conf_node < 0) {
- return conf_node;
- }
-
- str = fdt_getprop(fit, conf_node, "rbindex", &len);
- if (!str) {
- debug("cannot find property 'rbindex'\n");
- return -EINVAL;
- }
-
- index = simple_strtoul(str, NULL, 10);
-
- return index;
-}
-
/* For normal build */
#elif !defined(CONFIG_SPL_BUILD)