[U-Boot,v3] spl: implement CRC check on U-Boot uImage

Message ID 20190210203437.20644-1-simon.k.r.goldschmidt@gmail.com
State Accepted
Commit dae5c2dcdc2bc826a4ee0a58b08fd004b6259373
Delegated to: Tom Rini
Headers show
Series
  • [U-Boot,v3] spl: implement CRC check on U-Boot uImage
Related show

Commit Message

Simon Goldschmidt Feb. 10, 2019, 8:34 p.m.
SPL currently does not check uImage CRCs when loading U-Boot.

This patch adds checking the uImage CRC when SPL loads U-Boot. It does
this by reusing the existing config option SPL_CRC32_SUPPORT to allow
leaving out the CRC check on boards where the additional code size or
boot time is a problem (adding the CRC check currently adds ~1.4 kByte
to flash).

The SPL_CRC32_SUPPORT config option now gets enabled by default if SPL
support for legacy images is enabled to check the CRC on all boards
that don't actively take countermeasures.

Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- collected tags
- don't make new Kconfig option SPL_LEGACY_IMAGE_CRC_CHECK default 'y'
  to prevent breaking SPL size checks (requested for sunxi)
- make Kconfig help more explicit
- fix compiling TPL (don't use CONFIG_IS_ENABLED)

Changes in v2:
- added Kconfig option SPL_LEGACY_IMAGE_CRC_CHECK to enable/disable
  checking CRC on legacy images

 common/spl/Kconfig | 22 ++++++++++++++++------
 common/spl/spl.c   | 30 +++++++++++++++++++++++++++++-
 include/spl.h      |  5 +++++
 3 files changed, 50 insertions(+), 7 deletions(-)

Comments

Tom Rini Feb. 20, 2019, 1:57 a.m. | #1
On Sun, Feb 10, 2019 at 09:34:37PM +0100, Simon Goldschmidt wrote:

> SPL currently does not check uImage CRCs when loading U-Boot.
> 
> This patch adds checking the uImage CRC when SPL loads U-Boot. It does
> this by reusing the existing config option SPL_CRC32_SUPPORT to allow
> leaving out the CRC check on boards where the additional code size or
> boot time is a problem (adding the CRC check currently adds ~1.4 kByte
> to flash).
> 
> The SPL_CRC32_SUPPORT config option now gets enabled by default if SPL
> support for legacy images is enabled to check the CRC on all boards
> that don't actively take countermeasures.
> 
> Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
> Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot/master, thanks!

Patch

diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 59028529c9..8a642b2ac3 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -100,6 +100,16 @@  config SPL_LEGACY_IMAGE_SUPPORT
 	  is y. If this is not set, SPL will move on to other available
 	  boot media to find a suitable image.
 
+config SPL_LEGACY_IMAGE_CRC_CHECK
+	bool "Check CRC of Legacy images"
+	depends on SPL_LEGACY_IMAGE_SUPPORT
+	select SPL_CRC32_SUPPORT
+	help
+	  Enable this to check the CRC of Legacy images. While this increases
+	  reliability, it affects both code size and boot duration.
+	  If disabled, Legacy images are booted if the image magic and size
+	  are correct, without further integrity checks.
+
 config SPL_SYS_MALLOC_SIMPLE
 	bool
 	prompt "Only use malloc_simple functions in the SPL"
@@ -236,13 +246,13 @@  config SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_TYPE
 
 config SPL_CRC32_SUPPORT
 	bool "Support CRC32"
-	depends on SPL_FIT
+	default y if SPL_LEGACY_IMAGE_SUPPORT
 	help
-	  Enable this to support CRC32 in FIT images within SPL. This is a
-	  32-bit checksum value that can be used to verify images. This is
-	  the least secure type of checksum, suitable for detected
-	  accidental image corruption. For secure applications you should
-	  consider SHA1 or SHA256.
+	  Enable this to support CRC32 in uImages or FIT images within SPL.
+	  This is a 32-bit checksum value that can be used to verify images.
+	  For FIT images, this is the least secure type of checksum, suitable
+	  for detected accidental image corruption. For secure applications you
+	  should consider SHA1 or SHA256.
 
 config SPL_MD5_SUPPORT
 	bool "Support MD5"
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 35120b6efd..2e2af1b28e 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -239,6 +239,14 @@  int spl_parse_image_header(struct spl_image_info *spl_image,
 #ifdef CONFIG_SPL_LEGACY_IMAGE_SUPPORT
 		u32 header_size = sizeof(struct image_header);
 
+#ifdef CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK
+		/* check uImage header CRC */
+		if (!image_check_hcrc(header)) {
+			puts("SPL: Image header CRC check failed!\n");
+			return -EINVAL;
+		}
+#endif
+
 		if (spl_image->flags & SPL_COPY_PAYLOAD_ONLY) {
 			/*
 			 * On some system (e.g. powerpc), the load-address and
@@ -256,6 +264,13 @@  int spl_parse_image_header(struct spl_image_info *spl_image,
 			spl_image->size = image_get_data_size(header) +
 				header_size;
 		}
+#ifdef CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK
+		/* store uImage data length and CRC to check later */
+		spl_image->dcrc_data = image_get_load(header);
+		spl_image->dcrc_length = image_get_data_size(header);
+		spl_image->dcrc = image_get_dcrc(header);
+#endif
+
 		spl_image->os = image_get_os(header);
 		spl_image->name = image_get_name(header);
 		debug(SPL_TPL_PROMPT
@@ -495,12 +510,25 @@  static struct spl_image_loader *spl_ll_find_loader(uint boot_device)
 static int spl_load_image(struct spl_image_info *spl_image,
 			  struct spl_image_loader *loader)
 {
+	int ret;
 	struct spl_boot_device bootdev;
 
 	bootdev.boot_device = loader->boot_device;
 	bootdev.boot_device_name = NULL;
 
-	return loader->load_image(spl_image, &bootdev);
+	ret = loader->load_image(spl_image, &bootdev);
+#ifdef CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK
+	if (!ret && spl_image->dcrc_length) {
+		/* check data crc */
+		ulong dcrc = crc32_wd(0, (unsigned char *)spl_image->dcrc_data,
+				      spl_image->dcrc_length, CHUNKSZ_CRC32);
+		if (dcrc != spl_image->dcrc) {
+			puts("SPL: Image data CRC check failed!\n");
+			ret = -EINVAL;
+		}
+	}
+#endif
+	return ret;
 }
 
 /**
diff --git a/include/spl.h b/include/spl.h
index c82f2fd033..f09909e189 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -74,6 +74,11 @@  struct spl_image_info {
 	u32 size;
 	u32 flags;
 	void *arg;
+#ifdef CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK
+	ulong dcrc_data;
+	ulong dcrc_length;
+	ulong dcrc;
+#endif
 };
 
 /*