From e753821ea0d4dc0cd57b72fa1d4cba56545b7d3a Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 6 Nov 2017 11:06:37 +0100 Subject: [PATCH] fel: Check the U-Boot's CRC instead of its size The current code checks that the transferred size is matching the size reported in the image header. Unfortunately, the transferred image might be padded, which doesn't change anything at the functional level, but will make that check trigger since the actual image will be smaller than the transferred data. Change that logic to first check that the transferred size isn't less that the header image size, which will still be an error, and then check for the CRC of the image itself. This will prove to be an more robust integrity check than what we have right now anyway. The CRC used in the image header is the CRC32 algorithm, that is implemented in the zlib, which is installed on most devices on the planet, so we can just use that implementation instead of rolling our own. Tested-by: Frank Kunz Signed-off-by: Maxime Ripard --- Makefile | 8 +++++++- fel.c | 24 ++++++++++-------------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 4e95726..b9de5d9 100644 --- a/Makefile +++ b/Makefile @@ -118,6 +118,11 @@ sunxi-fexc: fexc.h script.h script.c \ LIBUSB = libusb-1.0 LIBUSB_CFLAGS ?= `pkg-config --cflags $(LIBUSB)` LIBUSB_LIBS ?= `pkg-config --libs $(LIBUSB)` + +ZLIB = zlib +ZLIB_CFLAGS ?= `pkg-config --cflags $(ZLIB)` +ZLIB_LIBS ?= `pkg-config --libs $(ZLIB)` + ifeq ($(OS),Windows_NT) # Windows lacks mman.h / mmap() DEFAULT_CFLAGS += -DNO_MMAP @@ -132,7 +137,8 @@ SOC_INFO := soc_info.c soc_info.h FEL_LIB := fel_lib.c fel_lib.h sunxi-fel: fel.c thunks/fel-to-spl-thunk.h $(PROGRESS) $(SOC_INFO) $(FEL_LIB) - $(CC) $(HOST_CFLAGS) $(LIBUSB_CFLAGS) $(LDFLAGS) -o $@ $(filter %.c,$^) $(LIBS) $(LIBUSB_LIBS) + $(CC) $(HOST_CFLAGS) $(LIBUSB_CFLAGS) $(ZLIB_CFLAGS) $(LDFLAGS) -o $@ \ + $(filter %.c,$^) $(LIBS) $(LIBUSB_LIBS) $(ZLIB_LIBS) sunxi-nand-part: nand-part-main.c nand-part.c nand-part-a10.h nand-part-a20.h $(CC) $(HOST_CFLAGS) -c -o nand-part-main.o nand-part-main.c diff --git a/fel.c b/fel.c index 20ed3a3..0fdefad 100644 --- a/fel.c +++ b/fel.c @@ -27,6 +27,7 @@ #include #include #include +#include #include static bool verbose = false; /* If set, makes the 'fel' tool more talkative */ @@ -785,21 +786,16 @@ void aw_fel_write_uboot_image(feldev_handle *dev, uint8_t *buf, size_t len) uint32_t data_size = be32toh(hdr.ih_size); /* Image Data Size */ uint32_t load_addr = be32toh(hdr.ih_load); /* Data Load Address */ - if (data_size != len - HEADER_SIZE) - pr_fatal("U-Boot image data size mismatch: " - "expected %zu, got %u\n", len - HEADER_SIZE, data_size); + if (data_size > len - HEADER_SIZE) + pr_fatal("U-Boot image data trucated: " + "expected %zu bytes, got %u\n", + len - HEADER_SIZE, data_size); - /* TODO: Verify image data integrity using the checksum field ih_dcrc, - * available from be32toh(buf32[6]) - * - * However, this requires CRC routines that mimic their U-Boot - * counterparts, namely image_check_dcrc() in ${U-BOOT}/common/image.c - * and crc_wd() in ${U-BOOT}/lib/crc32.c - * - * It should be investigated if existing CRC routines in sunxi-tools - * could be factored out and reused for this purpose - e.g. calc_crc32() - * from nand-part-main.c - */ + uint32_t dcrc = be32toh(hdr.ih_dcrc); + uint32_t computed_dcrc = crc32(0, buf + HEADER_SIZE, data_size); + if (dcrc != computed_dcrc) + pr_fatal("U-Boot data CRC mismatch: expected %x, got %x\n", + dcrc, computed_dcrc); /* If we get here, we're "good to go" (i.e. actually write the data) */ pr_info("Writing image \"%.*s\", %u bytes @ 0x%08X.\n",