boot: boot_serial: Fix issue with encrypted second slot images
Fixes issues whereby encrypted images were not properly listed due
to not treating them as encrypted, also removes a piece of wrong
hack code that would never run as the primary slot cannot be
encrypted.
Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
diff --git a/boot/zephyr/single_loader.c b/boot/zephyr/single_loader.c
index 86d5052..5d1e76f 100644
--- a/boot/zephyr/single_loader.c
+++ b/boot/zephyr/single_loader.c
@@ -9,6 +9,7 @@
#include "bootutil/image.h"
#include "bootutil_priv.h"
#include "bootutil/bootutil_log.h"
+#include "bootutil/bootutil_public.h"
#include "bootutil/fault_injection_hardening.h"
#include "mcuboot_config/mcuboot_config.h"
@@ -57,7 +58,6 @@
}
#endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT || MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE*/
-
inline static fih_ret
boot_image_validate_once(const struct flash_area *fa_p,
struct image_header *hdr)
@@ -90,349 +90,6 @@
}
/**
- * Attempts to load image header from flash; verifies flash header fields.
- *
- * @param[in] fa_p flash area pointer
- * @param[out] hdr buffer for image header
- *
- * @return 0 on success, error code otherwise
- */
-static int
-boot_image_load_header(const struct flash_area *fa_p,
- struct image_header *hdr)
-{
- uint32_t size;
- int rc = flash_area_read(fa_p, 0, hdr, sizeof *hdr);
-
- if (rc != 0) {
- rc = BOOT_EFLASH;
- BOOT_LOG_ERR("Failed reading image header");
- return BOOT_EFLASH;
- }
-
- if (hdr->ih_magic != IMAGE_MAGIC) {
- BOOT_LOG_ERR("Bad image magic 0x%lx", (unsigned long)hdr->ih_magic);
-
- return BOOT_EBADIMAGE;
- }
-
- if (hdr->ih_flags & IMAGE_F_NON_BOOTABLE) {
- BOOT_LOG_ERR("Image not bootable");
-
- return BOOT_EBADIMAGE;
- }
-
- if (!boot_u32_safe_add(&size, hdr->ih_img_size, hdr->ih_hdr_size) ||
- size >= flash_area_get_size(fa_p)) {
- return BOOT_EBADIMAGE;
- }
-
- return 0;
-}
-
-#ifdef MCUBOOT_ENC_IMAGES
-
-/**
- * Validate hash of a primary boot image doing on the fly decryption as well
- *
- * @param[in] fa_p flash area pointer
- * @param[in] hdr boot image header pointer
- *
- * @return FIH_SUCCESS on success, error code otherwise
- */
-inline static fih_ret
-boot_image_validate_encrypted(const struct flash_area *fa_p,
- struct image_header *hdr)
-{
- static uint8_t tmpbuf[BOOT_TMPBUF_SZ];
- FIH_DECLARE(fih_rc, FIH_FAILURE);
-
- struct boot_loader_state boot_data;
- struct boot_loader_state *state = &boot_data;
- struct boot_status _bs;
- struct boot_status *bs = &_bs;
- uint8_t image_index;
- int rc;
-
- memset(&boot_data, 0, sizeof(struct boot_loader_state));
- image_index = BOOT_CURR_IMG(state);
- if (MUST_DECRYPT(fa_p, image_index, hdr)) {
- rc = boot_enc_load(BOOT_CURR_ENC(state), image_index, hdr, fa_p, bs);
- if (rc < 0) {
- FIH_RET(fih_rc);
- }
- if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), 0, bs)) {
- FIH_RET(fih_rc);
- }
- }
- FIH_CALL(bootutil_img_validate, fih_rc, BOOT_CURR_ENC(state), image_index,
- hdr, fa_p, tmpbuf, BOOT_TMPBUF_SZ, NULL, 0, NULL);
-
- FIH_RET(fih_rc);
-}
-
-/*
- * Compute the total size of the given image. Includes the size of
- * the TLVs.
- */
-static int
-read_image_size(const struct flash_area *fa_p,
- struct image_header *hdr,
- uint32_t *size)
-{
- struct image_tlv_info info;
- uint32_t off;
- uint32_t protect_tlv_size;
- int rc;
-
- off = BOOT_TLV_OFF(hdr);
-
- if (flash_area_read(fa_p, off, &info, sizeof(info))) {
- rc = BOOT_EFLASH;
- goto done;
- }
-
- protect_tlv_size = hdr->ih_protect_tlv_size;
- if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) {
- if (protect_tlv_size != info.it_tlv_tot) {
- rc = BOOT_EBADIMAGE;
- goto done;
- }
-
- if (flash_area_read(fa_p, off + info.it_tlv_tot, &info, sizeof(info))) {
- rc = BOOT_EFLASH;
- goto done;
- }
- } else if (protect_tlv_size != 0) {
- rc = BOOT_EBADIMAGE;
- goto done;
- }
-
- if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
- rc = BOOT_EBADIMAGE;
- goto done;
- }
-
- *size = off + protect_tlv_size + info.it_tlv_tot;
- rc = 0;
-
-done:
- return rc;
-}
-
-
-/* Get the SOC's flash erase block size from the DTS, fallback to 1024. */
-#define SOC_FLASH_ERASE_BLK_SZ \
- DT_PROP_OR(DT_CHOSEN(zephyr_flash), erase_block_size,1024)
-
-/**
- * reads, decrypts in RAM & write back the decrypted image in the same region
- * This function is NOT power failsafe since the image is decrypted in the RAM
- * buffer.
- *
- * @param flash_area The ID of the source flash area.
- * @param off_src The offset within the flash area to
- * copy from.
- * @param sz The number of bytes to copy. should match erase sector
- *
- * @return 0 on success; nonzero on failure.
- */
-int
-decrypt_region_inplace(struct boot_loader_state *state,
- const struct flash_area *fap,
- struct image_header *hdr,
- uint32_t off, uint32_t sz)
-{
- uint32_t bytes_copied;
- int chunk_sz;
- int rc;
- uint32_t tlv_off;
- size_t blk_off;
- uint16_t idx;
- uint32_t blk_sz;
- uint8_t image_index;
-
- static uint8_t buf[SOC_FLASH_ERASE_BLK_SZ] __attribute__((aligned));
- assert(sz <= sizeof buf);
-
- bytes_copied = 0;
- while (bytes_copied < sz) {
- if (sz - bytes_copied > sizeof buf) {
- chunk_sz = sizeof buf;
- } else {
- chunk_sz = sz - bytes_copied;
- }
-
- rc = flash_area_read(fap, off + bytes_copied, buf, chunk_sz);
- if (rc != 0) {
- return BOOT_EFLASH;
- }
-
- image_index = BOOT_CURR_IMG(state);
- if (IS_ENCRYPTED(hdr)) {
- blk_sz = chunk_sz;
- idx = 0;
- if (off + bytes_copied < hdr->ih_hdr_size) {
- /* do not decrypt header */
- if (hdr->ih_hdr_size > (off + bytes_copied + chunk_sz)) {
- /* all bytes in header, skip decryption */
- blk_sz = 0;
- }
- else {
- blk_sz = off + bytes_copied + chunk_sz - hdr->ih_hdr_size;
- }
-
- blk_off = 0;
- idx = hdr->ih_hdr_size;
- } else {
- blk_off = ((off + bytes_copied) - hdr->ih_hdr_size) & 0xf;
- }
- tlv_off = BOOT_TLV_OFF(hdr);
- if (off + bytes_copied + chunk_sz > tlv_off) {
- /* do not decrypt TLVs */
- if (off + bytes_copied >= tlv_off) {
- blk_sz = 0;
- } else {
- blk_sz = tlv_off - (off + bytes_copied);
- }
- }
- boot_encrypt(BOOT_CURR_ENC(state), image_index, fap,
- (off + bytes_copied + idx) - hdr->ih_hdr_size, blk_sz,
- blk_off, &buf[idx]);
- }
- rc = flash_area_erase(fap, off + bytes_copied, chunk_sz);
- if (rc != 0) {
- return BOOT_EFLASH;
- }
- rc = flash_area_write(fap, off + bytes_copied, buf, chunk_sz);
- if (rc != 0) {
- return BOOT_EFLASH;
- }
-
- bytes_copied += chunk_sz;
-
- MCUBOOT_WATCHDOG_FEED();
- }
-
- return 0;
-}
-
-/**
- * Check if a image was encrypted into the first slot, and decrypt it
- * in place. this operation is not power failsafe.
- *
- * The operation is done by checking the last flash sector, and using it as a
- * temporarely scratch partition. The
- *
- * @param[in] fa_p flash area pointer
- * @param[in] hdr boot image header pointer
- *
- * @return FIH_SUCCESS on success, error code otherwise
- */
-inline static fih_ret
-decrypt_image_inplace(const struct flash_area *fa_p,
- struct image_header *hdr)
-{
- FIH_DECLARE(fih_rc, FIH_FAILURE);
- int rc;
- struct boot_loader_state boot_data;
- struct boot_loader_state *state = &boot_data;
- struct boot_status _bs;
- struct boot_status *bs = &_bs;
- size_t size;
- size_t sect_size;
- size_t sect_count;
- size_t sect;
- uint8_t image_index;
- struct flash_sector sector;
-
- memset(&boot_data, 0, sizeof(struct boot_loader_state));
- memset(&_bs, 0, sizeof(struct boot_status));
-
- /* Get size from last sector to know page/sector erase size */
- rc = flash_area_get_sector(fa_p, boot_status_off(fa_p), §or);
-
-
- image_index = BOOT_CURR_IMG(state);
-
- if (MUST_DECRYPT(fa_p, image_index, hdr)) {
-#if 0 //Skip this step?, the image will just not boot if it's not decrypted properly
- /* First check if the encrypted image is a good image before decrypting */
- FIH_CALL(boot_image_validate_encrypted,fih_rc,_fa_p,&_hdr);
- if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
- FIH_RET(fih_rc);
- }
-#endif
- memset(&boot_data, 0, sizeof(struct boot_loader_state));
- /* Load the encryption keys into cache */
- rc = boot_enc_load(BOOT_CURR_ENC(state), image_index, hdr, fa_p, bs);
- if (rc < 0) {
- FIH_RET(fih_rc);
- }
- if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), 0, bs)) {
- FIH_RET(fih_rc);
- }
- }
- else
- {
- /* Expected encrypted image! */
- FIH_RET(fih_rc);
- }
-
- uint32_t src_size = 0;
- rc = read_image_size(fa_p,hdr, &src_size);
- if (rc != 0) {
- FIH_RET(fih_rc);
- }
-
- sect_size = sector.fs_size;
- sect_count = fa_p->fa_size / sect_size;
- for (sect = 0, size = 0; size < src_size && sect < sect_count; sect++) {
- rc = decrypt_region_inplace(state, fa_p,hdr, size, sect_size);
- if (rc != 0) {
- FIH_RET(fih_rc);
- }
- size += sect_size;
- }
-
- fih_rc = FIH_SUCCESS;
- FIH_RET(fih_rc);
-}
-
-int
-boot_handle_enc_fw()
-{
- int rc = -1;
- FIH_DECLARE(fih_rc, FIH_FAILURE);
-
- rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(0), &_fa_p);
- assert(rc == 0);
-
- rc = boot_image_load_header(_fa_p, &_hdr);
- if (rc != 0) {
- goto out;
- }
-
- if (IS_ENCRYPTED(&_hdr)) {
- //encrypted, we need to decrypt in place
- FIH_CALL(decrypt_image_inplace,fih_rc,_fa_p,&_hdr);
- if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
- rc = -1;
- goto out;
- }
- }
- else
- {
- rc = 0;
- }
-
-out:
- flash_area_close(_fa_p);
- return rc;
-}
-#endif
-
-/**
* Gather information on image and prepare for booting.
*
* @parami[out] rsp Parameters for booting image, on success