Commit db543e50 authored by Hugo L'Hostis's avatar Hugo L'Hostis Committed by Fabio Utzig
Browse files

boot : Adding encrypted ram-load support



This patch adds the possibility to boot using ram-load with an
encrypted image. This is enabled when both the flags MCUBOOT_RAM_LOAD
and MCUBOOT_ENC_IMAGES are defined.

Signed-off-by: default avatarFabio Utzig <utzig@apache.org>
Signed-off-by: default avatarHugo L'Hostis <hugo.lhostis@arm.com>
Signed-off-by: default avatarSalome Thirot <salome.thirot@arm.com>
Change-Id: I7756c2c634d90a2e726117d6cfc5650653cf1b51
parent 8fcdfc5c
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -143,9 +143,9 @@ _Static_assert(BOOT_IMAGE_NUMBER > 0, "Invalid value for BOOT_IMAGE_NUMBER");
#else
#define ARE_SLOTS_EQUIVALENT()    1

#ifdef MCUBOOT_ENC_IMAGES
#error "Image encryption (MCUBOOT_ENC_IMAGES) is not supported when MCUBOOT_DIRECT_XIP or MCUBOOT_RAM_LOAD mode is selected."
#endif
#if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_ENC_IMAGES)
#error "Image encryption (MCUBOOT_ENC_IMAGES) is not supported when MCUBOOT_DIRECT_XIP is selected."
#endif /* MCUBOOT_DIRECT_XIP && MCUBOOT_ENC_IMAGES */
#endif /* MCUBOOT_DIRECT_XIP || MCUBOOT_RAM_LOAD */

#define BOOT_MAX_IMG_SECTORS       MCUBOOT_MAX_IMG_SECTORS
+116 −2
Original line number Diff line number Diff line
@@ -499,7 +499,9 @@ boot_image_check(struct boot_loader_state *state, struct image_header *hdr,

    image_index = BOOT_CURR_IMG(state);

#ifdef MCUBOOT_ENC_IMAGES
/* In the case of ram loading the image has already been decrypted as it is
 * decrypted when copied in ram */
#if defined(MCUBOOT_ENC_IMAGES) && !defined(MCUBOOT_RAM_LOAD)
    if (MUST_DECRYPT(fap, image_index, hdr)) {
        rc = boot_enc_load(BOOT_CURR_ENC(state), image_index, hdr, fap, bs);
        if (rc < 0) {
@@ -2415,6 +2417,110 @@ boot_verify_ram_load_address(struct boot_loader_state *state,
    return 0;
}

#ifdef MCUBOOT_ENC_IMAGES

/**
 * Copies and decrypts an image from a slot in the flash to an SRAM address.
 *
 * @param  state    Boot loader status information.
 * @param  slot     The flash slot of the image to be copied to SRAM.
 * @param  hdr      The image header.
 * @param  src_sz   Size of the image.
 * @param  img_dst  Pointer to the address at which the image needs to be
 *                  copied to SRAM.
 *
 * @return          0 on success; nonzero on failure.
 */
static int
boot_decrypt_and_copy_image_to_sram(struct boot_loader_state *state,
                                    uint32_t slot, struct image_header *hdr,
                                    uint32_t src_sz, uint32_t img_dst)
{
    /* The flow for the decryption and copy of the image is as follows :
     * 1. The whole image is copied to the RAM (header + payload + TLV).
     * 2. The encryption key is loaded from the TLV in flash.
     * 3. The image is then decrypted chunk by chunk in RAM (1 chunk
     * is 1024 bytes). Only the payload section is decrypted.
     * 4. The image is authenticated in RAM.
     */
    const struct flash_area *fap_src = NULL;
    struct boot_status bs;
    uint32_t blk_off;
    uint32_t tlv_off;
    uint32_t blk_sz;
    uint32_t bytes_copied = hdr->ih_hdr_size;
    uint32_t chunk_sz;
    uint32_t max_sz = 1024;
    uint16_t idx;
    uint8_t image_index;
    uint8_t * cur_dst;
    int area_id;
    int rc;
    uint8_t * ram_dst = (void *)(IMAGE_RAM_BASE + img_dst);

    image_index = BOOT_CURR_IMG(state);
    area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
    rc = flash_area_open(area_id, &fap_src);
    if (rc != 0){
        return BOOT_EFLASH;
    }

    tlv_off = BOOT_TLV_OFF(hdr);

    /* Copying the whole image in RAM */
    rc = flash_area_read(fap_src, 0, ram_dst, src_sz);
    if (rc != 0) {
        goto done;
    }

    rc = boot_enc_load(BOOT_CURR_ENC(state), image_index, hdr, fap_src, &bs);
    if (rc < 0) {
        goto done;
    }

    /* if rc > 0 then the key has already been loaded */
    if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), slot, &bs)) {
        goto done;
    }

    /* Starting at the end of the header as the header section is not encrypted */
    while (bytes_copied < tlv_off) { /* TLV section copied previously */
        if (src_sz - bytes_copied > max_sz) {
            chunk_sz = max_sz;
        } else {
            chunk_sz = src_sz - bytes_copied;
        }

        cur_dst = ram_dst + bytes_copied;
        blk_sz = chunk_sz;
        idx = 0;
        if (bytes_copied + chunk_sz > tlv_off) {
            /* Going over TLV section
             * Part of the chunk is encrypted payload */
            blk_off = ((bytes_copied) - hdr->ih_hdr_size) & 0xf;
            blk_sz = tlv_off - (bytes_copied);
            boot_encrypt(BOOT_CURR_ENC(state), image_index, fap_src,
                (bytes_copied + idx) - hdr->ih_hdr_size, blk_sz,
                blk_off, cur_dst);
        } else {
            /* Image encrypted payload section */
            blk_off = ((bytes_copied) - hdr->ih_hdr_size) & 0xf;
            boot_encrypt(BOOT_CURR_ENC(state), image_index, fap_src,
                    (bytes_copied + idx) - hdr->ih_hdr_size, blk_sz,
                    blk_off, cur_dst);
        }

        bytes_copied += chunk_sz;
    }
    rc = 0;

done:
    flash_area_close(fap_src);

    return rc;
}

#endif /* MCUBOOT_ENC_IMAGES */
/**
 * Copies a slot of the current image into SRAM.
 *
@@ -2575,11 +2681,19 @@ boot_load_image_to_sram(struct boot_loader_state *state,
            return rc;
        }
#endif

#ifdef MCUBOOT_ENC_IMAGES
        /* decrypt image if encrypted and copy it to RAM */
        if (IS_ENCRYPTED(hdr)) {
            rc = boot_decrypt_and_copy_image_to_sram(state, active_slot, hdr, img_sz, img_dst);
        } else {
            rc = boot_copy_image_to_sram(state, active_slot, img_dst, img_sz);
        }
#else
        /* Copy image to the load address from where it currently resides in
         * flash.
         */
        rc = boot_copy_image_to_sram(state, active_slot, img_dst, img_sz);
#endif
        if (rc != 0) {
            BOOT_LOG_INF("RAM loading to 0x%x is failed.", img_dst);
        } else {
+7 −3
Original line number Diff line number Diff line
@@ -287,7 +287,11 @@ script must also be used when signing the images. This option set the `RAM_LOAD`
flag in the image header which indicates that the image should be loaded to the
RAM and also set the load address in the image header.

The ram-load mode currently does not support the image encryption feature.
When the encryption option is enabled (`MCUBOOT_ENC_IMAGES`) along with ram-load
the image is checked for encryption. If the image is not encrypted, RAM loading
happens as described above. If the image is encrypted, it is copied in RAM at
the provided address and then decrypted. Finally, the decrypted image is
authenticated in RAM and executed.

## [Boot Swap Types](#boot-swap-types)

@@ -1020,8 +1024,8 @@ producing signed images, see: [signed_images](signed_images.md).
If you want to enable and use encrypted images, see:
[encrypted_images](encrypted_images.md).

Note: Image encryption is not supported when the direct-xip or the ram-load
upgrade strategy is selected.
Note: Image encryption is not supported when the direct-xip upgrade strategy
is selected.

### [Using Hardware Keys for Verification](#hw-key-support)