diff --git a/.github/workflows/zephyr_build.yaml b/.github/workflows/zephyr_build.yaml index 9b40abcdb..d353e06e2 100644 --- a/.github/workflows/zephyr_build.yaml +++ b/.github/workflows/zephyr_build.yaml @@ -40,12 +40,12 @@ jobs: runs-on: ubuntu-latest # Docker image from the zephyr upstream. Includes SDK and other required tools container: - image: zephyrprojectrtos/ci:v0.27.4 + image: zephyrprojectrtos/ci:v0.27.6 options: '--entrypoint /bin/bash' volumes: - /home/runners/zephyrproject:/github/cache/zephyrproject env: - ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.17.0 + ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.17.1-rc2 steps: - name: Set versions when workflow_dispatch diff --git a/README.md b/README.md index 081d88467..52a40da54 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ [travis]: https://travis-ci.org/mcu-tools/mcuboot [license]: https://github.com/mcu-tools/mcuboot/blob/main/LICENSE -This is MCUboot version 2.2.0-rc2 +This is MCUboot version 2.2.0 MCUboot is a secure bootloader for 32-bits microcontrollers. It defines a common infrastructure for the bootloader and the system flash layout on diff --git a/boot/boot_serial/include/boot_serial/boot_serial_encryption.h b/boot/boot_serial/include/boot_serial/boot_serial_encryption.h index 890f0cb18..6b42a3bdc 100644 --- a/boot/boot_serial/include/boot_serial/boot_serial_encryption.h +++ b/boot/boot_serial/include/boot_serial/boot_serial_encryption.h @@ -11,6 +11,7 @@ /** * Validate hash of a primary boot image doing on the fly decryption as well * + * @param[in] state bootloader state * @param[in] fa_p flash area pointer * @param[in] hdr boot image header pointer * @param[in] buf buffer which is used for validating data @@ -20,12 +21,10 @@ * @return FIH_SUCCESS on success, error code otherwise */ fih_ret -boot_image_validate_encrypted(const struct flash_area *fa_p, +boot_image_validate_encrypted(struct boot_loader_state *state, + const struct flash_area *fa_p, struct image_header *hdr, uint8_t *buf, uint16_t buf_size -#ifdef MCUBOOT_SWAP_USING_OFFSET - , uint32_t start_off -#endif ); /** diff --git a/boot/boot_serial/src/boot_serial.c b/boot/boot_serial/src/boot_serial.c index fd1871b5e..e1ec8d21c 100644 --- a/boot/boot_serial/src/boot_serial.c +++ b/boot/boot_serial/src/boot_serial.c @@ -288,10 +288,10 @@ bs_list_img_ver(char *dst, int maxlen, struct image_version *ver) * List images. */ static void -bs_list(char *buf, int len) +bs_list(struct boot_loader_state *state, char *buf, int len) { struct image_header hdr; - uint32_t slot, area_id; + uint32_t slot; const struct flash_area *fap; uint8_t image_index; #ifdef MCUBOOT_SERIAL_IMG_GRP_HASH @@ -301,11 +301,13 @@ bs_list(char *buf, int len) zcbor_map_start_encode(cbor_state, 1); zcbor_tstr_put_lit_cast(cbor_state, "images"); zcbor_list_start_encode(cbor_state, 5); - image_index = 0; - IMAGES_ITER(image_index) { + + IMAGES_ITER(BOOT_CURR_IMG(state)) { #if defined(MCUBOOT_SERIAL_IMG_GRP_IMAGE_STATE) || defined(MCUBOOT_SWAP_USING_OFFSET) - int swap_status = boot_swap_type_multi(image_index); + int swap_status = boot_swap_type_multi(BOOT_CURR_IMG(state)); #endif + image_index = BOOT_CURR_IMG(state); + (void) image_index; /* Might be unused depending on the configuration */ for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { FIH_DECLARE(fih_rc, FIH_FAILURE); @@ -323,25 +325,15 @@ bs_list(char *buf, int len) uint32_t start_off = 0; #endif - area_id = flash_area_id_from_multi_image_slot(image_index, slot); - if (flash_area_open(area_id, &fap)) { + fap = BOOT_IMG_AREA(state, slot); + if (fap == NULL) { continue; } #ifdef MCUBOOT_SWAP_USING_OFFSET if (slot == BOOT_SECONDARY_SLOT && swap_status != BOOT_SWAP_TYPE_REVERT) { - uint32_t num_sectors = SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN; - struct flash_sector sector_data; - - rc = flash_area_sectors(fap, &num_sectors, §or_data); - - if ((rc != 0 && rc != -ENOMEM) || - num_sectors != SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN) { - flash_area_close(fap); - continue; - } - - start_off = sector_data.fs_size; + start_off = boot_img_sector_size(state, slot, 0); + state->secondary_offset[image_index] = start_off; } #endif @@ -366,13 +358,8 @@ bs_list(char *buf, int len) #if defined(MCUBOOT_ENC_IMAGES) #if !defined(MCUBOOT_SINGLE_APPLICATION_SLOT) if (IS_ENCRYPTED(&hdr) && MUST_DECRYPT(fap, image_index, &hdr)) { -#ifdef MCUBOOT_SWAP_USING_OFFSET - FIH_CALL(boot_image_validate_encrypted, fih_rc, fap, - &hdr, tmpbuf, sizeof(tmpbuf), start_off); -#else - FIH_CALL(boot_image_validate_encrypted, fih_rc, fap, + FIH_CALL(boot_image_validate_encrypted, fih_rc, state, fap, &hdr, tmpbuf, sizeof(tmpbuf)); -#endif } else { #endif if (IS_ENCRYPTED(&hdr)) { @@ -384,14 +371,8 @@ bs_list(char *buf, int len) hdr.ih_flags &= ~ENCRYPTIONFLAGS; } #endif - -#ifdef MCUBOOT_SWAP_USING_OFFSET - FIH_CALL(bootutil_img_validate, fih_rc, NULL, &hdr, - fap, tmpbuf, sizeof(tmpbuf), NULL, 0, NULL, start_off); -#else - FIH_CALL(bootutil_img_validate, fih_rc, NULL, &hdr, + FIH_CALL(bootutil_img_validate, fih_rc, state, &hdr, fap, tmpbuf, sizeof(tmpbuf), NULL, 0, NULL); -#endif #if defined(MCUBOOT_ENC_IMAGES) && !defined(MCUBOOT_SINGLE_APPLICATION_SLOT) } #endif @@ -399,7 +380,6 @@ bs_list(char *buf, int len) } if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { - flash_area_close(fap); continue; } @@ -412,7 +392,6 @@ bs_list(char *buf, int len) #endif #endif - flash_area_close(fap); zcbor_map_start_encode(cbor_state, 20); #if (BOOT_IMAGE_NUMBER > 1) @@ -501,7 +480,7 @@ bs_list(char *buf, int len) * Set image state. */ static void -bs_set(char *buf, int len) +bs_set(struct boot_loader_state *state, char *buf, int len) { /* * Expected data format. @@ -550,45 +529,36 @@ bs_set(char *buf, int len) } if (img_hash.len != 0) { - IMAGES_ITER(image_index) { + IMAGES_ITER(BOOT_CURR_IMG(state)) { #ifdef MCUBOOT_SWAP_USING_OFFSET - int swap_status = boot_swap_type_multi(image_index); + int swap_status = boot_swap_type_multi(BOOT_CURR_IMG(state)); #endif + image_index = BOOT_CURR_IMG(state); + (void) image_index; /* Might be unused depending on the configuration */ for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { struct image_header hdr; - uint32_t area_id; const struct flash_area *fap; uint8_t tmpbuf[64]; #ifdef MCUBOOT_SWAP_USING_OFFSET - uint32_t num_sectors = SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN; - struct flash_sector sector_data; uint32_t start_off = 0; #endif - area_id = flash_area_id_from_multi_image_slot(image_index, slot); - if (flash_area_open(area_id, &fap)) { - BOOT_LOG_ERR("Failed to open flash area ID %d", area_id); + fap = BOOT_IMG_AREA(state, slot); + if (fap == NULL) { continue; } #ifdef MCUBOOT_SWAP_USING_OFFSET if (slot == BOOT_SECONDARY_SLOT && swap_status != BOOT_SWAP_TYPE_REVERT) { - rc = flash_area_sectors(fap, &num_sectors, §or_data); - - if ((rc != 0 && rc != -ENOMEM) || - num_sectors != SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN) { - flash_area_close(fap); - continue; - } - - start_off = sector_data.fs_size; + start_off = boot_img_sector_size(state, slot, 0); + state->secondary_offset[image_index] = start_off; } #endif rc = BOOT_HOOK_CALL(boot_read_image_header_hook, - BOOT_HOOK_REGULAR, image_index, 1, &hdr); + BOOT_HOOK_REGULAR, image_index, slot, &hdr); if (rc == BOOT_HOOK_REGULAR) { #ifdef MCUBOOT_SWAP_USING_OFFSET @@ -604,27 +574,17 @@ bs_set(char *buf, int len) BOOT_HOOK_CALL_FIH(boot_image_check_hook, FIH_BOOT_HOOK_REGULAR, - fih_rc, image_index, 1); + fih_rc, image_index, slot); if (FIH_EQ(fih_rc, FIH_BOOT_HOOK_REGULAR)) { #ifdef MCUBOOT_ENC_IMAGES if (IS_ENCRYPTED(&hdr)) { -#ifdef MCUBOOT_SWAP_USING_OFFSET - FIH_CALL(boot_image_validate_encrypted, fih_rc, fap, - &hdr, tmpbuf, sizeof(tmpbuf), start_off); -#else - FIH_CALL(boot_image_validate_encrypted, fih_rc, fap, + FIH_CALL(boot_image_validate_encrypted, fih_rc, state, fap, &hdr, tmpbuf, sizeof(tmpbuf)); -#endif } else { #endif -#ifdef MCUBOOT_SWAP_USING_OFFSET - FIH_CALL(bootutil_img_validate, fih_rc, NULL, &hdr, - fap, tmpbuf, sizeof(tmpbuf), NULL, 0, NULL, start_off); -#else - FIH_CALL(bootutil_img_validate, fih_rc, NULL, &hdr, + FIH_CALL(bootutil_img_validate, fih_rc, state, &hdr, fap, tmpbuf, sizeof(tmpbuf), NULL, 0, NULL); -#endif #ifdef MCUBOOT_ENC_IMAGES } #endif @@ -643,8 +603,6 @@ bs_set(char *buf, int len) rc = boot_serial_get_hash(&hdr, fap, hash); #endif #endif - flash_area_close(fap); - if (rc == 0 && memcmp(hash, img_hash.value, sizeof(hash)) == 0) { /* Hash matches, set this slot for test or confirmation */ found = true; @@ -668,7 +626,7 @@ bs_set(char *buf, int len) out: if (rc == 0) { /* Success - return updated list of images */ - bs_list(buf, len); + bs_list(state, buf, len); } else { /* Error code, only return the error */ zcbor_map_start_encode(cbor_state, 10); @@ -697,16 +655,52 @@ bs_rc_rsp(int rc_code) static void bs_list_set(uint8_t op, char *buf, int len) { + int rc; + struct boot_loader_state *state; + bool area_opened = false; + + state = boot_get_loader_state(); + boot_state_clear(state); + + rc = boot_open_all_flash_areas(state); + if (rc != 0) { + BOOT_LOG_ERR("Failed to open flash areas: %d", rc); + rc = MGMT_ERR_EUNKNOWN; + goto out; + } + + area_opened = true; + +#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) + IMAGES_ITER(BOOT_CURR_IMG(state)) { + rc = boot_read_sectors(state, NULL); + if (rc != 0) { + BOOT_LOG_ERR("Failed to read sectors: %d", rc); + rc = MGMT_ERR_EUNKNOWN; + goto out; + } + } +#endif + if (op == NMGR_OP_READ) { - bs_list(buf, len); + bs_list(state, buf, len); } else { #ifdef MCUBOOT_SERIAL_IMG_GRP_IMAGE_STATE - bs_set(buf, len); + bs_set(state, buf, len); #else - bs_rc_rsp(MGMT_ERR_ENOTSUP); + rc = MGMT_ERR_ENOTSUP; #endif } +out: + if (area_opened) { + boot_close_all_flash_areas(state); + } + + if (rc != 0) { + bs_rc_rsp(rc); + } + reset_cbor_state(); } @@ -734,104 +728,109 @@ bs_slot_info(uint8_t op, char *buf, int len) IMAGES_ITER(image_index) { for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { if (slot == 0) { - ok = zcbor_map_start_encode(cbor_state, CBOR_ENTRIES_SLOT_INFO_IMAGE_MAP) && - zcbor_tstr_put_lit(cbor_state, "image") && - zcbor_uint32_put(cbor_state, (uint32_t)image_index) && - zcbor_tstr_put_lit(cbor_state, "slots") && - zcbor_list_start_encode(cbor_state, BOOT_NUM_SLOTS); + ok = zcbor_map_start_encode(cbor_state, CBOR_ENTRIES_SLOT_INFO_IMAGE_MAP) && + zcbor_tstr_put_lit(cbor_state, "image") && + zcbor_uint32_put(cbor_state, (uint32_t)image_index) && + zcbor_tstr_put_lit(cbor_state, "slots") && + zcbor_list_start_encode(cbor_state, BOOT_NUM_SLOTS); - if (!ok) { - goto finish; - } + if (!ok) { + goto finish; } + } - ok = zcbor_map_start_encode(cbor_state, CBOR_ENTRIES_SLOT_INFO_SLOTS_MAP) && - zcbor_tstr_put_lit(cbor_state, "slot") && - zcbor_uint32_put(cbor_state, slot); + ok = zcbor_map_start_encode(cbor_state, CBOR_ENTRIES_SLOT_INFO_SLOTS_MAP) && + zcbor_tstr_put_lit(cbor_state, "slot") && + zcbor_uint32_put(cbor_state, slot); - if (!ok) { - goto finish; - } + if (!ok) { + goto finish; + } - area_id = flash_area_id_from_multi_image_slot(image_index, slot); - rc = flash_area_open(area_id, &fap); + area_id = flash_area_id_from_multi_image_slot(image_index, slot); + rc = flash_area_open(area_id, &fap); + + if (rc) { + ok = zcbor_tstr_put_lit(cbor_state, "rc") && + zcbor_int32_put(cbor_state, rc) && + zcbor_map_end_encode(cbor_state, CBOR_ENTRIES_SLOT_INFO_SLOTS_MAP); - if (rc) { - ok = zcbor_tstr_put_lit(cbor_state, "rc") && - zcbor_int32_put(cbor_state, rc); + if (ok && slot == (BOOT_NUM_SLOTS - 1)) { + ok = zcbor_list_end_encode(cbor_state, BOOT_NUM_SLOTS) && + zcbor_map_end_encode(cbor_state, CBOR_ENTRIES_SLOT_INFO_IMAGE_MAP); + } + } else { + if (sizeof(fap->fa_size) == sizeof(uint64_t)) { + ok = zcbor_tstr_put_lit(cbor_state, "size") && + zcbor_uint64_put(cbor_state, fap->fa_size); } else { - if (sizeof(fap->fa_size) == sizeof(uint64_t)) { - ok = zcbor_tstr_put_lit(cbor_state, "size") && - zcbor_uint64_put(cbor_state, fap->fa_size); - } else { - ok = zcbor_tstr_put_lit(cbor_state, "size") && - zcbor_uint32_put(cbor_state, fap->fa_size); - } + ok = zcbor_tstr_put_lit(cbor_state, "size") && + zcbor_uint32_put(cbor_state, fap->fa_size); + } - if (!ok) { - flash_area_close(fap); - goto finish; - } + if (!ok) { + flash_area_close(fap); + goto finish; + } - /* - * Check if we support uploading to this slot and if so, return the - * image ID - */ + /* + * Check if we support uploading to this slot and if so, return the + * image ID + */ #if defined(MCUBOOT_SINGLE_APPLICATION_SLOT) - ok = zcbor_tstr_put_lit(cbor_state, "upload_image_id") && - zcbor_uint32_put(cbor_state, (image_index + 1)); + ok = zcbor_tstr_put_lit(cbor_state, "upload_image_id") && + zcbor_uint32_put(cbor_state, (image_index + 1)); #elif defined(MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD) - ok = zcbor_tstr_put_lit(cbor_state, "upload_image_id") && - zcbor_uint32_put(cbor_state, (image_index * 2 + slot + 1)); + ok = zcbor_tstr_put_lit(cbor_state, "upload_image_id") && + zcbor_uint32_put(cbor_state, (image_index * 2 + slot + 1)); #else - if (slot == 1) { - ok = zcbor_tstr_put_lit(cbor_state, "upload_image_id") && - zcbor_uint32_put(cbor_state, (image_index * 2 + 1)); - } + if (slot == 1) { + ok = zcbor_tstr_put_lit(cbor_state, "upload_image_id") && + zcbor_uint32_put(cbor_state, (image_index * 2 + 1)); + } #endif - flash_area_close(fap); + flash_area_close(fap); - if (!ok) { + if (!ok) { + goto finish; + } + + ok = zcbor_map_end_encode(cbor_state, CBOR_ENTRIES_SLOT_INFO_SLOTS_MAP); + + if (!ok) { goto finish; - } + } - ok = zcbor_map_end_encode(cbor_state, CBOR_ENTRIES_SLOT_INFO_SLOTS_MAP); + if (slot == (BOOT_NUM_SLOTS - 1)) { + ok = zcbor_list_end_encode(cbor_state, BOOT_NUM_SLOTS); if (!ok) { - goto finish; + goto finish; } - if (slot == (BOOT_NUM_SLOTS - 1)) { - ok = zcbor_list_end_encode(cbor_state, BOOT_NUM_SLOTS); + if (image_max_sizes[image_index].calculated == true) { + ok = zcbor_tstr_put_lit(cbor_state, "max_image_size") && + zcbor_uint32_put(cbor_state, + image_max_sizes[image_index].max_size); if (!ok) { goto finish; } - - if (image_max_sizes[image_index].calculated == true) { - ok = zcbor_tstr_put_lit(cbor_state, "max_image_size") && - zcbor_uint32_put(cbor_state, - image_max_sizes[image_index].max_size); - - if (!ok) { - goto finish; - } - } - - ok = zcbor_map_end_encode(cbor_state, CBOR_ENTRIES_SLOT_INFO_IMAGE_MAP); - } - } - if (!ok) { - goto finish; + ok = zcbor_map_end_encode(cbor_state, CBOR_ENTRIES_SLOT_INFO_IMAGE_MAP); } } + + if (!ok) { + goto finish; + } } + } - ok = zcbor_list_end_encode(cbor_state, MCUBOOT_IMAGE_NUMBER) && - zcbor_map_end_encode(cbor_state, 1); + ok = zcbor_list_end_encode(cbor_state, MCUBOOT_IMAGE_NUMBER) && + zcbor_map_end_encode(cbor_state, 1); finish: if (!ok) { @@ -990,7 +989,7 @@ bs_upload(char *buf, int len) */ const size_t area_size = flash_area_get_size(fap); -#ifdef MCUBOOT_SWAP_USING_OFFSET +#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD) uint32_t num_sectors = SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN; struct flash_sector sector_data; #endif @@ -1037,8 +1036,7 @@ bs_upload(char *buf, int len) img_size = img_size_tmp; -#ifdef MCUBOOT_SWAP_USING_OFFSET -#ifdef MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD +#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD) if (img_num > 0 && (img_num % BOOT_NUM_SLOTS) == BOOT_DIRECT_UPLOAD_SECONDARY_SLOT_ID_REMAINDER) { rc = flash_area_sectors(fap, &num_sectors, §or_data); @@ -1053,17 +1051,6 @@ bs_upload(char *buf, int len) } else { start_off = 0; } -#else - rc = flash_area_sectors(fap, &num_sectors, §or_data); - - if ((rc != 0 && rc != -ENOMEM) || - num_sectors != SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN) { - rc = MGMT_ERR_ENOENT; - goto out; - } - - start_off = sector_data.fs_size; -#endif #endif } else if (img_chunk_off != curr_off) { /* If received chunk offset does not match expected one jump, pretend diff --git a/boot/boot_serial/src/boot_serial_encryption.c b/boot/boot_serial/src/boot_serial_encryption.c index 60ad587cb..4bbe74dc3 100644 --- a/boot/boot_serial/src/boot_serial_encryption.c +++ b/boot/boot_serial/src/boot_serial_encryption.c @@ -19,29 +19,19 @@ BOOT_LOG_MODULE_DECLARE(serial_encryption); fih_ret -boot_image_validate_encrypted(const struct flash_area *fa_p, +boot_image_validate_encrypted(struct boot_loader_state *state, + const struct flash_area *fa_p, struct image_header *hdr, uint8_t *buf, - uint16_t buf_size -#ifdef MCUBOOT_SWAP_USING_OFFSET - , uint32_t start_off -#endif - ) + uint16_t buf_size) { 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; int rc; - memset(&boot_data, 0, sizeof(struct boot_loader_state)); - if(IS_ENCRYPTED(hdr)) { -#ifdef MCUBOOT_SWAP_USING_OFFSET - rc = boot_enc_load(state, 1, hdr, fa_p, bs, start_off); -#else + if (MUST_DECRYPT(fa_p, BOOT_CURR_IMG(state), hdr)) { rc = boot_enc_load(state, 1, hdr, fa_p, bs); -#endif if (rc < 0) { FIH_RET(fih_rc); } @@ -51,13 +41,10 @@ boot_image_validate_encrypted(const struct flash_area *fa_p, } } -#ifdef MCUBOOT_SWAP_USING_OFFSET - FIH_CALL(bootutil_img_validate, fih_rc, state, - hdr, fa_p, buf, buf_size, NULL, 0, NULL, start_off); -#else FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fa_p, buf, buf_size, NULL, 0, NULL); -#endif + + boot_enc_zeroize(BOOT_CURR_ENC(state)); FIH_RET(fih_rc); } @@ -241,18 +228,14 @@ decrypt_image_inplace(const struct flash_area *fa_p, #if 0 //Skip this step?, the image will just not boot if it's not decrypted properly static uint8_t tmpbuf[BOOT_TMPBUF_SZ]; /* First check if the encrypted image is a good image before decrypting */ - FIH_CALL(boot_image_validate_encrypted,fih_rc,fa_p,&_hdr,tmpbuf,BOOT_TMPBUF_SZ); + FIH_CALL(boot_image_validate_encrypted, fih_rc, state, fa_p, &_hdr, tmpbuf, BOOT_TMPBUF_SZ); 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 */ -#ifdef MCUBOOT_SWAP_USING_OFFSET - rc = boot_enc_load(state, 0, hdr, fa_p, bs, 0); -#else rc = boot_enc_load(state, 0, hdr, fa_p, bs); -#endif if (rc < 0) { FIH_RET(fih_rc); } diff --git a/boot/bootutil/include/bootutil/boot_hooks.h b/boot/bootutil/include/bootutil/boot_hooks.h index ef7a89b28..f5b10e8c7 100644 --- a/boot/bootutil/include/bootutil/boot_hooks.h +++ b/boot/bootutil/include/bootutil/boot_hooks.h @@ -82,6 +82,18 @@ #endif /* MCUBOOT_BOOT_GO_HOOKS */ +#ifdef MCUBOOT_FIND_NEXT_SLOT_HOOKS + +#define BOOT_HOOK_FIND_SLOT_CALL(f, ret_default, ...) \ + DO_HOOK_CALL(f, ret_default, __VA_ARGS__) + +#else + +#define BOOT_HOOK_FIND_SLOT_CALL(f, ret_default, ...) \ + HOOK_CALL_NOP(f, ret_default, __VA_ARGS__) + +#endif /* MCUBOOT_FIND_NEXT_SLOT_HOOKS */ + #ifdef MCUBOOT_FLASH_AREA_HOOKS #define BOOT_HOOK_FLASH_AREA_CALL(f, ret_default, ...) \ @@ -260,4 +272,16 @@ int flash_area_get_device_id_hook(const struct flash_area *fa, #define BOOT_RESET_REQUEST_HOOK_CHECK_FAILED 3 #define BOOT_RESET_REQUEST_HOOK_INTERNAL_ERROR 4 +/** + * Finds the preferred slot containing the image. + * + * @param[in] state Boot loader status information. + * @param[in] image Image, for which the slot should be found. + * @param[out] active_slot Number of the preferred slot. + * + * @return 0 if a slot was requested; + * BOOT_HOOK_REGULAR follow the normal execution path. + */ +int boot_find_next_slot_hook(struct boot_loader_state *state, uint8_t image, uint32_t *active_slot); + #endif /*H_BOOTUTIL_HOOKS*/ diff --git a/boot/bootutil/include/bootutil/boot_status.h b/boot/bootutil/include/bootutil/boot_status.h index 91f266bc7..4198559e1 100644 --- a/boot/bootutil/include/bootutil/boot_status.h +++ b/boot/bootutil/include/bootutil/boot_status.h @@ -119,6 +119,11 @@ extern "C" { #define BLINFO_MAX_APPLICATION_SIZE_IMAGE_2 0x07 #define BLINFO_MAX_APPLICATION_SIZE_IMAGE_3 0x08 #define BLINFO_MAX_APPLICATION_SIZE_IMAGE_4 0x09 +#define BLINFO_SECURITY_COUNTER_IMAGE_0 0x10 +#define BLINFO_SECURITY_COUNTER_IMAGE_1 0x11 +#define BLINFO_SECURITY_COUNTER_IMAGE_2 0x12 +#define BLINFO_SECURITY_COUNTER_IMAGE_3 0x13 +#define BLINFO_SECURITY_COUNTER_IMAGE_4 0x14 enum mcuboot_mode { MCUBOOT_MODE_SINGLE_SLOT, diff --git a/boot/bootutil/include/bootutil/bootutil.h b/boot/bootutil/include/bootutil/bootutil.h index babb62fdc..a666b2a31 100644 --- a/boot/bootutil/include/bootutil/bootutil.h +++ b/boot/bootutil/include/bootutil/bootutil.h @@ -89,7 +89,9 @@ fih_ret boot_go_for_image_id(struct boot_rsp *rsp, uint32_t image_id); void boot_state_clear(struct boot_loader_state *state); fih_ret context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp); struct boot_loader_state *boot_get_loader_state(void); +struct image_max_size *boot_get_image_max_sizes(void); const struct image_max_size *boot_get_max_app_size(void); +void boot_fetch_slot_state_sizes(void); uint32_t boot_get_state_secondary_offset(struct boot_loader_state *state, const struct flash_area *fap); diff --git a/boot/bootutil/include/bootutil/crypto/ecdh_p256.h b/boot/bootutil/include/bootutil/crypto/ecdh_p256.h index 962535cbc..e3ac9be6a 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdh_p256.h +++ b/boot/bootutil/include/bootutil/crypto/ecdh_p256.h @@ -35,6 +35,7 @@ extern "C" { #if defined(MCUBOOT_USE_TINYCRYPT) typedef uintptr_t bootutil_ecdh_p256_context; +typedef bootutil_ecdh_p256_context bootutil_key_exchange_ctx; static inline void bootutil_ecdh_p256_init(bootutil_ecdh_p256_context *ctx) { (void)ctx; @@ -80,6 +81,7 @@ typedef struct bootutil_ecdh_p256_context { mbedtls_mpi z; mbedtls_mpi d; } bootutil_ecdh_p256_context; +typedef bootutil_ecdh_p256_context bootutil_key_exchange_ctx; static inline void bootutil_ecdh_p256_init(bootutil_ecdh_p256_context *ctx) { diff --git a/boot/bootutil/include/bootutil/crypto/ecdh_x25519.h b/boot/bootutil/include/bootutil/crypto/ecdh_x25519.h index 1d11b6473..e868e5817 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdh_x25519.h +++ b/boot/bootutil/include/bootutil/crypto/ecdh_x25519.h @@ -26,6 +26,7 @@ extern int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32], const uint8_t peer_public_value[32]); typedef uintptr_t bootutil_ecdh_x25519_context; +typedef bootutil_ecdh_x25519_context bootutil_key_exchange_ctx; static inline void bootutil_ecdh_x25519_init(bootutil_ecdh_x25519_context *ctx) { (void)ctx; diff --git a/boot/bootutil/include/bootutil/crypto/ecdsa.h b/boot/bootutil/include/bootutil/crypto/ecdsa.h index 0e9205c29..7fc5474e2 100644 --- a/boot/bootutil/include/bootutil/crypto/ecdsa.h +++ b/boot/bootutil/include/bootutil/crypto/ecdsa.h @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: Apache-2.0 * - * Copyright (c) 2023-2024 Arm Limited + * Copyright (c) 2023-2025 Arm Limited */ /* @@ -69,7 +69,9 @@ #include "mbedtls/oid.h" #include "mbedtls/asn1.h" #include "bootutil/sign_key.h" -#include "common.h" +#if !defined(MCUBOOT_USE_PSA_CRYPTO) +#include "bootutil/crypto/common.h" +#endif #if defined(MCUBOOT_USE_NRF_EXTERNAL_CRYPTO) #include diff --git a/boot/bootutil/include/bootutil/crypto/rsa.h b/boot/bootutil/include/bootutil/crypto/rsa.h index 87ab1de56..dfc888b99 100644 --- a/boot/bootutil/include/bootutil/crypto/rsa.h +++ b/boot/bootutil/include/bootutil/crypto/rsa.h @@ -68,6 +68,7 @@ extern "C" { typedef struct { psa_key_id_t key_id; } bootutil_rsa_context; +typedef bootutil_rsa_context bootutil_key_exchange_ctx; static inline void bootutil_rsa_init(bootutil_rsa_context *ctx) { @@ -176,6 +177,7 @@ static inline int bootutil_rsassa_pss_verify(const bootutil_rsa_context *ctx, #elif defined(MCUBOOT_USE_MBED_TLS) typedef mbedtls_rsa_context bootutil_rsa_context; +typedef bootutil_rsa_context bootutil_key_exchange_ctx; static inline void bootutil_rsa_init(bootutil_rsa_context *ctx) { diff --git a/boot/bootutil/include/bootutil/enc_key.h b/boot/bootutil/include/bootutil/enc_key.h index 85cb7e1b9..89411bf17 100644 --- a/boot/bootutil/include/bootutil/enc_key.h +++ b/boot/bootutil/include/bootutil/enc_key.h @@ -67,11 +67,7 @@ int boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot, const struct boot_status *bs); int boot_enc_load(struct boot_loader_state *state, int slot, const struct image_header *hdr, const struct flash_area *fap, - struct boot_status *bs -#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) - , uint32_t start_off -#endif - ); + struct boot_status *bs); bool boot_enc_valid(struct enc_key_data *enc_state, int slot); void boot_enc_encrypt(struct enc_key_data *enc_state, int slot, uint32_t off, uint32_t sz, uint32_t blk_off, uint8_t *buf); diff --git a/boot/bootutil/include/bootutil/fault_injection_hardening.h b/boot/bootutil/include/bootutil/fault_injection_hardening.h index fdf01b539..497b437ea 100644 --- a/boot/bootutil/include/bootutil/fault_injection_hardening.h +++ b/boot/bootutil/include/bootutil/fault_injection_hardening.h @@ -137,7 +137,7 @@ extern fih_ret FIH_BOOT_HOOK_REGULAR; /* Global failure handler - more resistant to unlooping. noinline and used are * used to prevent optimization */ -__attribute__((noinline)) __attribute__((used)) +__attribute__((noinline)) __attribute__((used)) __attribute__((noreturn)) void fih_panic_loop(void); #define FIH_PANIC fih_panic_loop() #else diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 52fa6d1bb..2bd20061d 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -216,9 +216,6 @@ fih_ret bootutil_img_validate(struct boot_loader_state *state, const struct flash_area *fap, uint8_t *tmp_buf, uint32_t tmp_buf_sz, uint8_t *seed, int seed_len, uint8_t *out_hash -#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) - , uint32_t start_off -#endif ); struct image_tlv_iter { diff --git a/boot/bootutil/src/boot_record.c b/boot/bootutil/src/boot_record.c index 3ab704ef2..84dac8f92 100644 --- a/boot/bootutil/src/boot_record.c +++ b/boot/bootutil/src/boot_record.c @@ -24,6 +24,9 @@ #include "mcuboot_config/mcuboot_config.h" #include "bootutil/crypto/sha.h" +#ifdef MCUBOOT_HW_ROLLBACK_PROT +#include "bootutil/security_cnt.h" +#endif #if defined(MCUBOOT_MEASURED_BOOT) || defined(MCUBOOT_DATA_SHARING) #include "bootutil/boot_record.h" @@ -242,6 +245,10 @@ int boot_save_shared_data(const struct image_header *hdr, const struct flash_are int rc; #if !defined(MCUBOOT_SINGLE_APPLICATION_SLOT) uint8_t image = 0; +#ifdef MCUBOOT_HW_ROLLBACK_PROT + uint32_t security_cnt; + FIH_DECLARE(fih_rc, FIH_FAILURE); +#endif #endif #if defined(MCUBOOT_SINGLE_APPLICATION_SLOT) @@ -346,14 +353,37 @@ int boot_save_shared_data(const struct image_header *hdr, const struct flash_are } #endif +#if !defined(MCUBOOT_SINGLE_APPLICATION_SLOT) && defined(MCUBOOT_HW_ROLLBACK_PROT) + image = 0; + while (image < BOOT_IMAGE_NUMBER && !rc) { + FIH_CALL(boot_nv_security_counter_get, fih_rc, image, &security_cnt); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + /* Some platforms support only a single security counter. */ + continue; + } + + rc = boot_add_data_to_shared_area(TLV_MAJOR_BLINFO, + BLINFO_SECURITY_COUNTER_IMAGE_0 + image, + sizeof(security_cnt), + (void *)&security_cnt); + if (!rc) { + break; + } + ++image; + } +#endif /* !defined(MCUBOOT_SINGLE_APPLICATION_SLOT) && defined(MCUBOOT_HW_ROLLBACK_PROT) */ + #if !defined(MCUBOOT_SINGLE_APPLICATION_SLOT) + image = 0; while (image < BOOT_IMAGE_NUMBER && !rc) { if (max_app_sizes[image].calculated == true) { rc = boot_add_data_to_shared_area(TLV_MAJOR_BLINFO, (BLINFO_MAX_APPLICATION_SIZE + image), sizeof(max_app_sizes[image].max_size), (void *)&max_app_sizes[image].max_size); - + if (!rc) { + break; + } } ++image; diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c index 96be26692..5dd9a8cfd 100644 --- a/boot/bootutil/src/bootutil_misc.c +++ b/boot/bootutil/src/bootutil_misc.c @@ -47,6 +47,10 @@ #include "swap_priv.h" #endif +#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_SWAP_USING_SCRATCH) +#include "swap_priv.h" +#endif + #if defined(MCUBOOT_DECOMPRESS_IMAGES) #include #include @@ -57,6 +61,14 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); /* Currently only used by imgmgr */ int boot_current_slot; +#if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \ +defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) +/* Used for holding static buffers in multiple functions to work around issues + * in older versions of gcc (e.g. 4.8.4) + */ +static struct boot_sector_buffer sector_buffers; +#endif + /** * @brief Determine if the data at two memory addresses is equal * @@ -108,12 +120,6 @@ fih_ret boot_fih_memequal(const void *s1, const void *s2, size_t n) static inline uint32_t boot_trailer_info_sz(void) { -#if defined(MCUBOOT_SINGLE_APPLICATION_SLOT) || \ - defined(MCUBOOT_FIRMWARE_LOADER) || \ - defined(MCUBOOT_SINGLE_APPLICATION_SLOT_RAM_LOAD) - /* Single image MCUboot modes do not have a trailer */ - return 0; -#else return ( #ifdef MCUBOOT_ENC_IMAGES /* encryption keys */ @@ -127,7 +133,6 @@ boot_trailer_info_sz(void) BOOT_MAX_ALIGN * 4 + BOOT_MAGIC_ALIGN_SIZE ); -#endif } /* @@ -675,3 +680,206 @@ boot_erase_region(const struct flash_area *fa, uint32_t off, uint32_t size, bool end: return rc; } + +#if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \ +defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) +int +boot_initialize_area(struct boot_loader_state *state, int flash_area) +{ + uint32_t num_sectors = BOOT_MAX_IMG_SECTORS; + boot_sector_t *out_sectors; + uint32_t *out_num_sectors; + int rc; + + num_sectors = BOOT_MAX_IMG_SECTORS; + + if (flash_area == FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state))) { + out_sectors = BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors; + out_num_sectors = &BOOT_IMG(state, BOOT_PRIMARY_SLOT).num_sectors; +#if BOOT_NUM_SLOTS > 1 + } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) { + out_sectors = BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors; + out_num_sectors = &BOOT_IMG(state, BOOT_SECONDARY_SLOT).num_sectors; +#if MCUBOOT_SWAP_USING_SCRATCH + } else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) { + out_sectors = state->scratch.sectors; + out_num_sectors = &state->scratch.num_sectors; +#endif +#endif + } else { + return BOOT_EFLASH; + } + +#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS + rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors); +#else + _Static_assert(sizeof(int) <= sizeof(uint32_t), "Fix needed"); + rc = flash_area_to_sectors(flash_area, (int *)&num_sectors, out_sectors); +#endif /* defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */ + if (rc != 0) { + return rc; + } + *out_num_sectors = num_sectors; + return 0; +} + +static uint32_t +boot_write_sz(struct boot_loader_state *state) +{ + uint32_t elem_sz; +#if MCUBOOT_SWAP_USING_SCRATCH + uint32_t align; +#endif + + /* Figure out what size to write update status update as. The size depends + * on what the minimum write size is for scratch area, active image slot. + * We need to use the bigger of those 2 values. + */ + elem_sz = flash_area_align(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); +#if MCUBOOT_SWAP_USING_SCRATCH + align = flash_area_align(BOOT_SCRATCH_AREA(state)); + if (align > elem_sz) { + elem_sz = align; + } +#endif + + return elem_sz; +} + +int +boot_read_sectors(struct boot_loader_state *state, struct boot_sector_buffer *sectors) +{ + uint8_t image_index; + int rc; + + if (sectors == NULL) { + sectors = §or_buffers; + } + + image_index = BOOT_CURR_IMG(state); + + BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors = + sectors->primary[image_index]; +#if BOOT_NUM_SLOTS > 1 + BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors = + sectors->secondary[image_index]; +#if MCUBOOT_SWAP_USING_SCRATCH + state->scratch.sectors = sectors->scratch; +#endif +#endif + + rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index)); + if (rc != 0) { + return BOOT_EFLASH; + } + +#if BOOT_NUM_SLOTS > 1 + rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SECONDARY(image_index)); + if (rc != 0) { + /* We need to differentiate from the primary image issue */ + return BOOT_EFLASH_SEC; + } + +#if MCUBOOT_SWAP_USING_SCRATCH + rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SCRATCH); + if (rc != 0) { + return BOOT_EFLASH; + } +#endif +#endif + + BOOT_WRITE_SZ(state) = boot_write_sz(state); + + return 0; +} +#endif + +#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) +static int +boot_read_sectors_recovery(struct boot_loader_state *state) +{ + uint8_t image_index; + int rc; + + image_index = BOOT_CURR_IMG(state); + + rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index)); + if (rc != 0) { + return BOOT_EFLASH; + } + + rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SECONDARY(image_index)); + if (rc != 0) { + /* We need to differentiate from the primary image issue */ + return BOOT_EFLASH_SEC; + } + + return 0; +} + +/** + * Reads image data to find out the maximum application sizes. Only needs to + * be called in serial recovery mode, as the state information is unpopulated + * at that time + */ +void boot_fetch_slot_state_sizes(void) +{ + int rc = -1; + int image_index; + + rc = boot_open_all_flash_areas(boot_get_loader_state()); + if (rc != 0) { + BOOT_LOG_DBG("boot_fetch_slot_state_sizes: error %d while opening flash areas", rc); + goto finish; + } + + IMAGES_ITER(BOOT_CURR_IMG(boot_get_loader_state())) { + int max_size = 0; + + image_index = BOOT_CURR_IMG(boot_get_loader_state()); + + BOOT_IMG(boot_get_loader_state(), BOOT_PRIMARY_SLOT).sectors = + sector_buffers.primary[image_index]; +#if BOOT_NUM_SLOTS > 1 + BOOT_IMG(boot_get_loader_state(), BOOT_SECONDARY_SLOT).sectors = + sector_buffers.secondary[image_index]; +#if MCUBOOT_SWAP_USING_SCRATCH + boot_get_loader_state()->scratch.sectors = sector_buffers.scratch; +#endif +#endif + + /* Determine the sector layout of the image slots and scratch area. */ + rc = boot_read_sectors_recovery(boot_get_loader_state()); + + if (rc == 0) { + max_size = app_max_size(boot_get_loader_state()); + + if (max_size > 0) { + boot_get_image_max_sizes()[image_index].calculated = true; + boot_get_image_max_sizes()[image_index].max_size = max_size; + } + } + } + +finish: + boot_close_all_flash_areas(boot_get_loader_state()); + memset(boot_get_loader_state(), 0, sizeof(struct boot_loader_state)); +} +#endif + +/** + * Clears the boot state, so that previous operations have no effect on new + * ones. + * + * @param state The state that should be cleared. If the value + * is NULL, the default bootloader state will be + * cleared. + */ +void boot_state_clear(struct boot_loader_state *state) +{ + if (state != NULL) { + memset(state, 0, sizeof(struct boot_loader_state)); + } else { + memset(boot_get_loader_state(), 0, sizeof(struct boot_loader_state)); + } +} diff --git a/boot/bootutil/src/bootutil_priv.h b/boot/bootutil/src/bootutil_priv.h index 5d5a58a04..c0a285bbe 100644 --- a/boot/bootutil/src/bootutil_priv.h +++ b/boot/bootutil/src/bootutil_priv.h @@ -54,7 +54,11 @@ struct flash_area; #define NO_ACTIVE_SLOT UINT32_MAX /** Number of image slots in flash; currently limited to two. */ +#if defined(MCUBOOT_SINGLE_APPLICATION_SLOT) || defined(MCUBOOT_SINGLE_APPLICATION_SLOT_RAM_LOAD) +#define BOOT_NUM_SLOTS 1 +#else #define BOOT_NUM_SLOTS 2 +#endif #if (defined(MCUBOOT_OVERWRITE_ONLY) + \ defined(MCUBOOT_SWAP_USING_MOVE) + \ @@ -88,6 +92,12 @@ struct flash_area; #define BOOT_STATUS_OP_SWAP 2 #endif +#if (BOOT_IMAGE_NUMBER > 1) +#define IMAGES_ITER(x) for ((x) = 0; (x) < BOOT_IMAGE_NUMBER; ++(x)) +#else +#define IMAGES_ITER(x) +#endif + /* * Maintain state of copy progress. */ @@ -275,7 +285,8 @@ struct boot_loader_state { /* Image destination and size for the active slot */ uint32_t img_dst; uint32_t img_sz; -#elif defined(MCUBOOT_DIRECT_XIP_REVERT) +#endif +#if defined(MCUBOOT_DIRECT_XIP_REVERT) || defined(MCUBOOT_RAM_LOAD_REVERT) /* Swap status for the active slot */ struct boot_swap_state swap_state; #endif @@ -283,6 +294,14 @@ struct boot_loader_state { #endif /* MCUBOOT_DIRECT_XIP || MCUBOOT_RAM_LOAD */ }; +struct boot_sector_buffer { + boot_sector_t primary[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; + boot_sector_t secondary[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; +#if MCUBOOT_SWAP_USING_SCRATCH + boot_sector_t scratch[BOOT_MAX_IMG_SECTORS]; +#endif +}; + /* The function is intended for verification of image hash against * provided signature. */ @@ -383,6 +402,37 @@ uint32_t boot_scratch_trailer_sz(uint32_t min_write_sz); bool bootutil_buffer_is_erased(const struct flash_area *area, const void *buffer, size_t len); +/** + * Opens the flash areas of all images. + * + * @param state Bootloader state. + * + * @return 0 on success, another value otherwise. + */ +int boot_open_all_flash_areas(struct boot_loader_state *state); + +/** + * Closes the flash areas of all images. + * + * @param state Bootloader state. + */ +void boot_close_all_flash_areas(struct boot_loader_state *state); + +#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD) +/** + * Determines the sector layout of both image slots and the scratch area. + * + * This information is necessary for calculating the number of bytes to erase + * and copy during an image swap. The information collected during this + * function is used to populate the state. + * + * @param state Bootloader state. + * @param sectors Buffers where to store the sector layout. If NULL, the statically-allocated + * buffers in loader.c will be used. + */ +int boot_read_sectors(struct boot_loader_state *state, struct boot_sector_buffer *sectors); +#endif + /** * Safe (non-overflowing) uint32_t addition. Returns true, and stores * the result in *dest if it can be done without overflow. Otherwise, diff --git a/boot/bootutil/src/bootutil_public.c b/boot/bootutil/src/bootutil_public.c index 8860fca41..cb689be3b 100644 --- a/boot/bootutil/src/bootutil_public.c +++ b/boot/bootutil/src/bootutil_public.c @@ -578,10 +578,7 @@ boot_set_next(const struct flash_area *fa, bool active, bool confirm) if (active) { rc = BOOT_EBADVECT; } else { - /* The image slot is corrupt. There is no way to recover, so erase the - * slot to allow future upgrades. - */ - flash_area_erase(fa, 0, flash_area_get_size(fa)); + /* This image will not be boot next time anyway */ rc = BOOT_EBADIMAGE; } break; diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c index cf6f380e2..0d01fa51d 100644 --- a/boot/bootutil/src/encrypted.c +++ b/boot/bootutil/src/encrypted.c @@ -239,15 +239,15 @@ parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key) * @param okm_len On input the requested length; on output the generated length */ static int -hkdf(uint8_t *ikm, uint16_t ikm_len, uint8_t *info, uint16_t info_len, - uint8_t *okm, uint16_t *okm_len) +hkdf(const uint8_t *ikm, size_t ikm_len, const uint8_t *info, size_t info_len, + uint8_t *okm, size_t *okm_len) { bootutil_hmac_sha256_context hmac; uint8_t salt[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE]; uint8_t prk[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE]; uint8_t T[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE]; - uint16_t off; - uint16_t len; + size_t off; + size_t len; uint8_t counter; bool first; int rc; @@ -380,35 +380,26 @@ static int fake_rng(void *p_rng, unsigned char *output, size_t len) int boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) { -#if defined(MCUBOOT_ENCRYPT_RSA) - bootutil_rsa_context rsa; - uint8_t *cp; - uint8_t *cpend; - size_t olen; -#endif - - BOOT_LOG_DBG("boot_decrypt_key"); -#if defined(MCUBOOT_ENCRYPT_EC256) - bootutil_ecdh_p256_context ecdh_p256; -#endif -#if defined(MCUBOOT_ENCRYPT_X25519) - bootutil_ecdh_x25519_context ecdh_x25519; -#endif #if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) bootutil_hmac_sha256_context hmac; bootutil_aes_ctr_context aes_ctr; uint8_t tag[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE]; uint8_t shared[EC_SHARED_LEN]; uint8_t derived_key[BOOT_ENC_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE]; - uint8_t *cp; - uint8_t *cpend; uint8_t private_key[EC_PRIVK_LEN]; uint8_t counter[BOOT_ENC_BLOCK_SIZE]; - uint16_t len; +#endif +#if !defined(MCUBOOT_ENCRYPT_KW) + bootutil_key_exchange_ctx pk_ctx; + uint8_t *cp; + uint8_t *cpend; + size_t len; #endif struct bootutil_key *bootutil_enc_key = NULL; int rc = -1; + BOOT_LOG_DBG("boot_decrypt_key"); + rc = boot_enc_retrieve_private_key(&bootutil_enc_key); if (rc) { return rc; @@ -418,21 +409,23 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) return rc; } -#if defined(MCUBOOT_ENCRYPT_RSA) - - bootutil_rsa_init(&rsa); +#if !defined(MCUBOOT_ENCRYPT_KW) cp = (uint8_t *)bootutil_enc_key->key; cpend = cp + *bootutil_enc_key->len; +#endif + +#if defined(MCUBOOT_ENCRYPT_RSA) + bootutil_rsa_init(&pk_ctx); /* The enckey is encrypted through RSA so for decryption we need the private key */ - rc = bootutil_rsa_parse_private_key(&rsa, &cp, cpend); + rc = bootutil_rsa_parse_private_key(&pk_ctx, &cp, cpend); if (rc) { - bootutil_rsa_drop(&rsa); + bootutil_rsa_drop(&pk_ctx); return rc; } - rc = bootutil_rsa_oaep_decrypt(&rsa, &olen, buf, enckey, BOOT_ENC_KEY_SIZE); - bootutil_rsa_drop(&rsa); + rc = bootutil_rsa_oaep_decrypt(&pk_ctx, &len, buf, enckey, BOOT_ENC_KEY_SIZE); + bootutil_rsa_drop(&pk_ctx); if (rc) { return rc; } @@ -447,10 +440,6 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) #endif /* defined(MCUBOOT_ENCRYPT_KW) */ #if defined(MCUBOOT_ENCRYPT_EC256) - - cp = (uint8_t *)bootutil_enc_key->key; - cpend = cp + *bootutil_enc_key->len; - /* * Load the stored EC256 decryption private key */ @@ -463,10 +452,10 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) /* * First "element" in the TLV is the curve point (public key) */ - bootutil_ecdh_p256_init(&ecdh_p256); + bootutil_ecdh_p256_init(&pk_ctx); - rc = bootutil_ecdh_p256_shared_secret(&ecdh_p256, &buf[EC_PUBK_INDEX], private_key, shared); - bootutil_ecdh_p256_drop(&ecdh_p256); + rc = bootutil_ecdh_p256_shared_secret(&pk_ctx, &buf[EC_PUBK_INDEX], private_key, shared); + bootutil_ecdh_p256_drop(&pk_ctx); if (rc != 0) { return -1; } @@ -474,10 +463,6 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) #endif /* defined(MCUBOOT_ENCRYPT_EC256) */ #if defined(MCUBOOT_ENCRYPT_X25519) - - cp = (uint8_t *)bootutil_enc_key->key; - cpend = cp + *bootutil_enc_key->len; - /* * Load the stored X25519 decryption private key */ @@ -491,10 +476,10 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) * First "element" in the TLV is the curve point (public key) */ - bootutil_ecdh_x25519_init(&ecdh_x25519); + bootutil_ecdh_x25519_init(&pk_ctx); - rc = bootutil_ecdh_x25519_shared_secret(&ecdh_x25519, &buf[EC_PUBK_INDEX], private_key, shared); - bootutil_ecdh_x25519_drop(&ecdh_x25519); + rc = bootutil_ecdh_x25519_shared_secret(&pk_ctx, &buf[EC_PUBK_INDEX], private_key, shared); + bootutil_ecdh_x25519_drop(&pk_ctx); if (!rc) { return -1; } @@ -537,18 +522,15 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) /* Assumes the tag buffer is at least sizeof(hmac_tag_size(state)) bytes */ rc = bootutil_hmac_sha256_finish(&hmac, tag, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE); + (void)bootutil_hmac_sha256_drop(&hmac); if (rc != 0) { - (void)bootutil_hmac_sha256_drop(&hmac); return -1; } if (bootutil_constant_time_compare(tag, &buf[EC_TAG_INDEX], EC_TAG_LEN) != 0) { - (void)bootutil_hmac_sha256_drop(&hmac); return -1; } - bootutil_hmac_sha256_drop(&hmac); - /* * Finally decrypt the received ciphered key */ @@ -588,11 +570,7 @@ boot_decrypt_key(const uint8_t *buf, uint8_t *enckey) int boot_enc_load(struct boot_loader_state *state, int slot, const struct image_header *hdr, const struct flash_area *fap, - struct boot_status *bs -#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) - , uint32_t start_off -#endif - ) + struct boot_status *bs) { struct enc_key_data *enc_state = BOOT_CURR_ENC(state); uint32_t off; @@ -617,11 +595,7 @@ boot_enc_load(struct boot_loader_state *state, int slot, boot_enc_init(enc_state, slot); #if defined(MCUBOOT_SWAP_USING_OFFSET) -#if defined(MCUBOOT_SERIAL_RECOVERY) - it.start_off = boot_get_state_secondary_offset(state, fap) + start_off; -#else it.start_off = boot_get_state_secondary_offset(state, fap); -#endif #endif rc = bootutil_tlv_iter_begin(&it, hdr, fap, BOOT_ENC_TLV, false); diff --git a/boot/bootutil/src/fault_injection_hardening.c b/boot/bootutil/src/fault_injection_hardening.c index 11436cfa7..fbe75e87e 100644 --- a/boot/bootutil/src/fault_injection_hardening.c +++ b/boot/bootutil/src/fault_injection_hardening.c @@ -63,6 +63,7 @@ void fih_cfi_decrement(void) */ __attribute__((used)) __attribute__((noinline)) +__attribute__((noreturn)) void fih_panic_loop(void) { __asm volatile ("b fih_panic_loop"); @@ -74,5 +75,10 @@ void fih_panic_loop(void) __asm volatile ("b fih_panic_loop"); __asm volatile ("b fih_panic_loop"); __asm volatile ("b fih_panic_loop"); + + /* An infinite loop to suppress compiler warnings + * about the return of a noreturn function + */ + while (1) {} } #endif /* FIH_ENABLE_GLOBAL_FAIL */ diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 522e5da2d..1076a1888 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -59,10 +59,6 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); #if defined(MCUBOOT_SIGN_EC256) #include "mbedtls/ecdsa.h" #endif -#if defined(MCUBOOT_ENC_IMAGES) || defined(MCUBOOT_SIGN_RSA) || \ - defined(MCUBOOT_SIGN_EC256) -#include "mbedtls/asn1.h" -#endif #include "bootutil_priv.h" @@ -77,9 +73,6 @@ bootutil_img_hash(struct boot_loader_state *state, struct image_header *hdr, const struct flash_area *fap, uint8_t *tmp_buf, uint32_t tmp_buf_sz, uint8_t *hash_result, uint8_t *seed, int seed_len -#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) - , uint32_t start_offset -#endif ) { bootutil_sha_context sha_ctx; @@ -142,11 +135,7 @@ bootutil_img_hash(struct boot_loader_state *state, /* For swap using offset mode, the image starts in the second sector of the upgrade slot, so * apply the offset when this is needed */ -#if defined(MCUBOOT_SERIAL_RECOVERY) - sector_off = boot_get_state_secondary_offset(state, fap) + start_offset; -#else sector_off = boot_get_state_secondary_offset(state, fap); -#endif #endif bootutil_sha_init(&sha_ctx); @@ -292,6 +281,8 @@ bootutil_img_hash(struct boot_loader_state *state, # define KEY_BUF_SIZE (SIG_BUF_SIZE + 24) #endif /* !MCUBOOT_HW_KEY */ +#if !defined(MCUBOOT_BYPASS_KEY_MATCH) +/* Find functions are only needed when key is checked first */ #if !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) #if !defined(MCUBOOT_HW_KEY) static int @@ -345,8 +336,8 @@ bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len) } /* Adding hardening to avoid this potential attack: - * - Image is signed with an arbitrary key and the corresponding public - * key is added as a TLV field. + * - Image is signed with an arbitrary key and the corresponding public + * key is added as a TLV field. * - During public key validation (comparing against key-hash read from * HW) a fault is injected to accept the public key as valid one. */ @@ -363,6 +354,18 @@ bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len) #endif /* !MCUBOOT_BUILTIN_KEY */ #endif /* !defined(CONFIG_BOOT_SIGNATURE_USING_KMU) */ #endif /* EXPECTED_SIG_TLV */ +#else /* !MCUBOOT_BYPASS_KEY_MATCH */ +static inline int +bootutil_find_key(uint8_t image_index, uint8_t *key, uint16_t key_len) +{ + (void)image_index; + (void)key; + (void)key_len; + + /* There is only one key, so it always matches */ + return 0; +} +#endif /* !MCUBOOT_BYPASS_KEY_MATCH */ /** * Reads the value of an image's security counter. @@ -509,9 +512,6 @@ bootutil_img_validate(struct boot_loader_state *state, struct image_header *hdr, const struct flash_area *fap, uint8_t *tmp_buf, uint32_t tmp_buf_sz, uint8_t *seed, int seed_len, uint8_t *out_hash -#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) - , uint32_t start_offset -#endif ) { #if (defined(EXPECTED_KEY_TLV) && defined(MCUBOOT_HW_KEY)) || defined(MCUBOOT_HW_ROLLBACK_PROT) || defined(MCUBOOT_DECOMPRESS_IMAGES) \ @@ -623,12 +623,7 @@ bootutil_img_validate(struct boot_loader_state *state, #endif #if defined(EXPECTED_HASH_TLV) && !defined(MCUBOOT_SIGN_PURE) -#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) - rc = bootutil_img_hash(state, hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len, - start_offset); -#else rc = bootutil_img_hash(state, hdr, fap, tmp_buf, tmp_buf_sz, hash, seed, seed_len); -#endif if (rc) { goto out; } @@ -648,11 +643,7 @@ bootutil_img_validate(struct boot_loader_state *state, #endif #if defined(MCUBOOT_SWAP_USING_OFFSET) -#if defined(MCUBOOT_SERIAL_RECOVERY) - it.start_off = boot_get_state_secondary_offset(state, fap) + start_offset; -#else it.start_off = boot_get_state_secondary_offset(state, fap); -#endif #endif rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false); @@ -835,6 +826,8 @@ bootutil_img_validate(struct boot_loader_state *state, fih_rc = fih_ret_encode_zero_equality(img_security_cnt < (uint32_t)fih_int_decode(security_cnt)); if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + BOOT_LOG_ERR("Image security counter value %u lower than monotonic value %u", + img_security_cnt, (uint32_t)fih_int_decode(security_cnt)); FIH_SET(fih_rc, FIH_FAILURE); goto out; } diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index 23a65d1ec..0f2fff28c 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -109,7 +109,6 @@ struct sector_buffer_t { #endif }; -static struct sector_buffer_t sector_buffers; #endif #endif @@ -162,6 +161,14 @@ struct boot_loader_state *boot_get_loader_state(void) return &boot_data; } +#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) +struct image_max_size *boot_get_image_max_sizes(void) +{ + return image_max_sizes; +} +#endif + + static int boot_read_image_headers(struct boot_loader_state *state, bool require_all, struct boot_status *bs) @@ -284,31 +291,6 @@ fill_rsp(struct boot_loader_state *state, struct boot_rsp *rsp) rsp->br_hdr = boot_img_hdr(state, active_slot); } -/** - * Closes all flash areas. - * - * @param state Boot loader status information. - */ -static void -close_all_flash_areas(struct boot_loader_state *state) -{ - uint32_t slot; - - IMAGES_ITER(BOOT_CURR_IMG(state)) { -#if BOOT_IMAGE_NUMBER > 1 - if (state->img_mask[BOOT_CURR_IMG(state)]) { - continue; - } -#endif -#if MCUBOOT_SWAP_USING_SCRATCH - flash_area_close(BOOT_SCRATCH_AREA(state)); -#endif - for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { - flash_area_close(BOOT_IMG_AREA(state, BOOT_NUM_SLOTS - 1 - slot)); - } - } -} - #if (BOOT_IMAGE_NUMBER > 1) || \ defined(MCUBOOT_DIRECT_XIP) || \ defined(MCUBOOT_RAM_LOAD) || \ @@ -378,72 +360,6 @@ boot_version_cmp(const struct image_version *ver1, } #endif -#if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \ -defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) -static int -boot_initialize_area(struct boot_loader_state *state, int flash_area) -{ - uint32_t num_sectors = BOOT_MAX_IMG_SECTORS; - boot_sector_t *out_sectors; - uint32_t *out_num_sectors; - int rc; - - num_sectors = BOOT_MAX_IMG_SECTORS; - - if (flash_area == FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state))) { - out_sectors = BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors; - out_num_sectors = &BOOT_IMG(state, BOOT_PRIMARY_SLOT).num_sectors; - } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) { - out_sectors = BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors; - out_num_sectors = &BOOT_IMG(state, BOOT_SECONDARY_SLOT).num_sectors; -#if MCUBOOT_SWAP_USING_SCRATCH - } else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) { - out_sectors = state->scratch.sectors; - out_num_sectors = &state->scratch.num_sectors; -#endif - } else { - return BOOT_EFLASH; - } - -#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS - rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors); -#else - _Static_assert(sizeof(int) <= sizeof(uint32_t), "Fix needed"); - rc = flash_area_to_sectors(flash_area, (int *)&num_sectors, out_sectors); -#endif /* defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */ - if (rc != 0) { - return rc; - } - *out_num_sectors = num_sectors; - return 0; -} -#endif - -#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) -static int -boot_read_sectors_recovery(struct boot_loader_state *state) -{ - uint8_t image_index; - int rc; - - image_index = BOOT_CURR_IMG(state); - - rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index)); - if (rc != 0) { - return BOOT_EFLASH; - } - - rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SECONDARY(image_index)); - if (rc != 0) { - /* We need to differentiate from the primary image issue */ - return BOOT_EFLASH_SEC; - } - - return 0; -} -#endif - - #if (BOOT_IMAGE_NUMBER > 1) static int @@ -725,66 +641,6 @@ boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot) #if !defined(MCUBOOT_DIRECT_XIP) #if !defined(MCUBOOT_RAM_LOAD) -static uint32_t -boot_write_sz(struct boot_loader_state *state) -{ - uint32_t elem_sz; -#if MCUBOOT_SWAP_USING_SCRATCH - uint32_t align; -#endif - - /* Figure out what size to write update status update as. The size depends - * on what the minimum write size is for scratch area, active image slot. - * We need to use the bigger of those 2 values. - */ - elem_sz = flash_area_align(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); -#if MCUBOOT_SWAP_USING_SCRATCH - align = flash_area_align(BOOT_SCRATCH_AREA(state)); - if (align > elem_sz) { - elem_sz = align; - } -#endif - - return elem_sz; -} - -/** - * Determines the sector layout of both image slots and the scratch area. - * This information is necessary for calculating the number of bytes to erase - * and copy during an image swap. The information collected during this - * function is used to populate the state. - */ -static int -boot_read_sectors(struct boot_loader_state *state) -{ - uint8_t image_index; - int rc; - - image_index = BOOT_CURR_IMG(state); - - rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index)); - if (rc != 0) { - return BOOT_EFLASH; - } - - rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SECONDARY(image_index)); - if (rc != 0) { - /* We need to differentiate from the primary image issue */ - return BOOT_EFLASH_SEC; - } - -#if MCUBOOT_SWAP_USING_SCRATCH - rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SCRATCH); - if (rc != 0) { - return BOOT_EFLASH; - } -#endif - - BOOT_WRITE_SZ(state) = boot_write_sz(state); - - return 0; -} - void boot_status_reset(struct boot_status *bs) { @@ -902,11 +758,7 @@ boot_image_check(struct boot_loader_state *state, struct image_header *hdr, */ #if defined(MCUBOOT_ENC_IMAGES) && !defined(MCUBOOT_RAM_LOAD) if (MUST_DECRYPT(fap, BOOT_CURR_IMG(state), hdr)) { -#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) - rc = boot_enc_load(state, 1, hdr, fap, bs, 0); -#else rc = boot_enc_load(state, 1, hdr, fap, bs); -#endif if (rc < 0) { FIH_RET(fih_rc); } @@ -973,24 +825,15 @@ split_image_check(struct image_header *app_hdr, } } -#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) - FIH_CALL(bootutil_img_validate, fih_rc, NULL, loader_hdr, loader_fap, - tmpbuf, BOOT_TMPBUF_SZ, NULL, 0, loader_hash, 0); -#else FIH_CALL(bootutil_img_validate, fih_rc, NULL, loader_hdr, loader_fap, tmpbuf, BOOT_TMPBUF_SZ, NULL, 0, loader_hash); -#endif + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { FIH_RET(fih_rc); } -#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) - FIH_CALL(bootutil_img_validate, fih_rc, NULL, app_hdr, app_fap, - tmpbuf, BOOT_TMPBUF_SZ, loader_hash, 32, NULL, 0); -#else FIH_CALL(bootutil_img_validate, fih_rc, NULL, app_hdr, app_fap, tmpbuf, BOOT_TMPBUF_SZ, loader_hash, 32, NULL); -#endif out: FIH_RET(fih_rc); @@ -2045,7 +1888,7 @@ boot_copy_region(struct boot_loader_state *state, if (abs_off >= tlv_off) { blk_sz = 0; } else { - blk_sz = tlv_off - abs_off; + blk_sz = tlv_off - abs_off - idx; } } if (source_slot == 0) { @@ -2160,15 +2003,9 @@ boot_copy_image(struct boot_loader_state *state, struct boot_status *bs) #ifdef MCUBOOT_ENC_IMAGES if (IS_ENCRYPTED(boot_img_hdr(state, BOOT_SECONDARY_SLOT))) { -#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) - rc = boot_enc_load(state, BOOT_SECONDARY_SLOT, - boot_img_hdr(state, BOOT_SECONDARY_SLOT), - fap_secondary_slot, bs, 0); -#else rc = boot_enc_load(state, BOOT_SECONDARY_SLOT, boot_img_hdr(state, BOOT_SECONDARY_SLOT), fap_secondary_slot, bs); -#endif if (rc < 0) { return BOOT_EBADIMAGE; @@ -2291,11 +2128,7 @@ boot_swap_image(struct boot_loader_state *state, struct boot_status *bs) #ifdef MCUBOOT_ENC_IMAGES if (IS_ENCRYPTED(hdr)) { fap = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT); -#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) - rc = boot_enc_load(state, 0, hdr, fap, bs, 0); -#else rc = boot_enc_load(state, 0, hdr, fap, bs); -#endif assert(rc >= 0); if (rc == 0) { @@ -2319,11 +2152,7 @@ boot_swap_image(struct boot_loader_state *state, struct boot_status *bs) hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT); if (IS_ENCRYPTED(hdr)) { fap = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT); -#if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY) - rc = boot_enc_load(state, 1, hdr, fap, bs, 0); -#else rc = boot_enc_load(state, 1, hdr, fap, bs); -#endif assert(rc >= 0); if (rc == 0) { @@ -2618,22 +2447,6 @@ boot_prepare_image_for_update(struct boot_loader_state *state, int max_size; #endif - /* Determine the sector layout of the image slots and scratch area. */ - rc = boot_read_sectors(state); - if (rc != 0) { - BOOT_LOG_WRN("Failed reading sectors; BOOT_MAX_IMG_SECTORS=%d" - " - too small?", BOOT_MAX_IMG_SECTORS); - /* Unable to determine sector layout, continue with next image - * if there is one. - */ - BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; - if (rc == BOOT_EFLASH) - { - /* Only return on error from the primary image flash */ - return; - } - } - /* Attempt to read an image header from each slot. */ rc = boot_read_image_headers(state, false, NULL); if (rc != 0) { @@ -2911,28 +2724,18 @@ check_downgrade_prevention(struct boot_loader_state *state) fih_ret context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) { - size_t slot; struct boot_status bs; + struct boot_sector_buffer *sectors = NULL; int rc = -1; FIH_DECLARE(fih_rc, FIH_FAILURE); - int fa_id; - int image_index; bool has_upgrade; volatile int fih_cnt; BOOT_LOG_DBG("context_boot_go"); #if defined(__BOOTSIM__) - /* The array of slot sectors are defined here (as opposed to file scope) so - * that they don't get allocated for non-boot-loader apps. This is - * necessary because the gcc option "-fdata-sections" doesn't seem to have - * any effect in older gcc versions (e.g., 4.8.4). - */ - TARGET_STATIC boot_sector_t primary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; - TARGET_STATIC boot_sector_t secondary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS]; -#if MCUBOOT_SWAP_USING_SCRATCH - TARGET_STATIC boot_sector_t scratch_sectors[BOOT_MAX_IMG_SECTORS]; -#endif + struct boot_sector_buffer sector_buf; + sectors = §or_buf; #endif has_upgrade = false; @@ -2941,6 +2744,15 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) (void)has_upgrade; #endif + /* Open primary and secondary image areas for the duration + * of this call. + */ + rc = boot_open_all_flash_areas(state); + if (rc != 0) { + BOOT_LOG_ERR("Failed to open flash areas, cannot continue"); + FIH_PANIC; + } + /* Iterate over all the images. By the end of the loop the swap type has * to be determined for each image and all aborted swaps have to be * completed. @@ -2958,54 +2770,22 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) */ boot_enc_zeroize(BOOT_CURR_ENC(state)); #endif - - image_index = BOOT_CURR_IMG(state); - -#if !defined(__BOOTSIM__) - BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors = - sector_buffers.primary[image_index]; - BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors = - sector_buffers.secondary[image_index]; -#if MCUBOOT_SWAP_USING_SCRATCH - state->scratch.sectors = sector_buffers.scratch; -#endif -#else - BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors = - primary_slot_sectors[image_index]; - BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors = - secondary_slot_sectors[image_index]; -#if MCUBOOT_SWAP_USING_SCRATCH - state->scratch.sectors = scratch_sectors; -#endif -#endif - - /* Open primary and secondary image areas for the duration - * of this call. - */ - for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { - fa_id = flash_area_id_from_multi_image_slot(image_index, slot); - rc = flash_area_open(fa_id, &BOOT_IMG_AREA(state, slot)); - assert(rc == 0); - - if (rc != 0) { - BOOT_LOG_ERR("Failed to open flash area ID %d (image %d slot %d): %d, " - "cannot continue", fa_id, image_index, (int8_t)slot, rc); - FIH_PANIC; - } - } -#if MCUBOOT_SWAP_USING_SCRATCH - rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, - &BOOT_SCRATCH_AREA(state)); - assert(rc == 0); - + /* Determine the sector layout of the image slots and scratch area. */ + rc = boot_read_sectors(state, sectors); if (rc != 0) { - BOOT_LOG_ERR("Failed to open scratch flash area: %d, cannot continue", rc); - FIH_PANIC; + BOOT_LOG_WRN("Failed reading sectors; BOOT_MAX_IMG_SECTORS=%d" + " - too small?", BOOT_MAX_IMG_SECTORS); + BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE; } -#endif - /* Determine swap type and complete swap if it has been aborted. */ - boot_prepare_image_for_update(state, &bs); + /* Unless there was an error when determining the sector layout of the primary slot, + * determine swap type and complete swap if it has been aborted. + * + * Note boot_read_sectors returns BOOT_EFLASH_SEC for errors regarding the secondary slot. + */ + if (rc != BOOT_EFLASH) { + boot_prepare_image_for_update(state, &bs); + } if (BOOT_IS_UPGRADE(BOOT_SWAP_TYPE(state))) { has_upgrade = true; @@ -3246,26 +3026,24 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) memset(&bs, 0, sizeof(struct boot_status)); #endif - close_all_flash_areas(state); + boot_close_all_flash_areas(state); FIH_RET(fih_rc); } fih_ret split_go(int loader_slot, int split_slot, void **entry) { - boot_sector_t *sectors; + struct boot_sector_buffer *sectors; uintptr_t entry_val; int loader_flash_id; int split_flash_id; int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - sectors = malloc(BOOT_MAX_IMG_SECTORS * 2 * sizeof *sectors); + sectors = malloc(sizeof(struct boot_sector_buffer)); if (sectors == NULL) { FIH_RET(FIH_FAILURE); } - BOOT_IMG(&boot_data, loader_slot).sectors = sectors + 0; - BOOT_IMG(&boot_data, split_slot).sectors = sectors + BOOT_MAX_IMG_SECTORS; loader_flash_id = flash_area_id_from_image_slot(loader_slot); rc = flash_area_open(loader_flash_id, @@ -3277,7 +3055,7 @@ split_go(int loader_slot, int split_slot, void **entry) assert(rc == 0); /* Determine the sector layout of the image slots and scratch area. */ - rc = boot_read_sectors(&boot_data); + rc = boot_read_sectors(&boot_data, sectors); if (rc != 0) { rc = SPLIT_GO_ERR; goto done; @@ -3331,7 +3109,6 @@ static int boot_get_slot_usage(struct boot_loader_state *state) { uint32_t slot; - int fa_id; int rc; struct image_header *hdr = NULL; @@ -3341,14 +3118,6 @@ boot_get_slot_usage(struct boot_loader_state *state) continue; } #endif - /* Open all the slots */ - for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { - fa_id = flash_area_id_from_multi_image_slot( - BOOT_CURR_IMG(state), slot); - rc = flash_area_open(fa_id, &BOOT_IMG_AREA(state, slot)); - assert(rc == 0); - } - /* Attempt to read an image header from each slot. */ rc = boot_read_image_headers(state, false, NULL); if (rc != 0) { @@ -3444,7 +3213,8 @@ print_loaded_images(struct boot_loader_state *state) } #endif -#if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT) +#if (defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT)) || \ + (defined(MCUBOOT_RAM_LOAD) && defined(MCUBOOT_RAM_LOAD_REVERT)) /** * Checks whether the active slot of the current image was previously selected * to run. Erases the image if it was selected but its execution failed, @@ -3605,7 +3375,12 @@ boot_load_and_validate_images(struct boot_loader_state *state) break; } - active_slot = find_slot_with_highest_version(state); + rc = BOOT_HOOK_FIND_SLOT_CALL(boot_find_next_slot_hook, BOOT_HOOK_REGULAR, + state, BOOT_CURR_IMG(state), &active_slot); + if (rc == BOOT_HOOK_REGULAR) { + active_slot = find_slot_with_highest_version(state); + } + if (active_slot == NO_ACTIVE_SLOT) { BOOT_LOG_INF("No slot to load for image %d", BOOT_CURR_IMG(state)); @@ -3652,7 +3427,12 @@ boot_load_and_validate_images(struct boot_loader_state *state) break; } - active_slot = find_slot_with_highest_version(state); + rc = BOOT_HOOK_FIND_SLOT_CALL(boot_find_next_slot_hook, BOOT_HOOK_REGULAR, + state, BOOT_CURR_IMG(state), &active_slot); + if (rc == BOOT_HOOK_REGULAR) { + active_slot = find_slot_with_highest_version(state); + } + if (active_slot == NO_ACTIVE_SLOT) { BOOT_LOG_INF("No slot to load for image %d", BOOT_CURR_IMG(state)); @@ -3676,8 +3456,9 @@ boot_load_and_validate_images(struct boot_loader_state *state) state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; continue; } +#endif /* MCUBOOT_DIRECT_XIP */ -#ifdef MCUBOOT_DIRECT_XIP_REVERT +#if defined(MCUBOOT_DIRECT_XIP_REVERT) || defined(MCUBOOT_RAM_LOAD_REVERT) rc = boot_select_or_erase(state); if (rc != 0) { /* The selected image slot has been erased. */ @@ -3685,8 +3466,7 @@ boot_load_and_validate_images(struct boot_loader_state *state) state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT; continue; } -#endif /* MCUBOOT_DIRECT_XIP_REVERT */ -#endif /* MCUBOOT_DIRECT_XIP */ +#endif /* MCUBOOT_DIRECT_XIP_REVERT || MCUBOOT_RAM_LOAD_REVERT */ #ifdef MCUBOOT_RAM_LOAD /* Image is first loaded to RAM and authenticated there in order to @@ -3773,18 +3553,23 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) int rc; FIH_DECLARE(fih_rc, FIH_FAILURE); - rc = boot_get_slot_usage(state); + rc = boot_open_all_flash_areas(state); if (rc != 0) { goto out; } + rc = boot_get_slot_usage(state); + if (rc != 0) { + goto close; + } + #if (BOOT_IMAGE_NUMBER > 1) while (true) { #endif FIH_CALL(boot_load_and_validate_images, fih_rc, state); if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { FIH_SET(fih_rc, FIH_FAILURE); - goto out; + goto close; } #if (BOOT_IMAGE_NUMBER > 1) @@ -3810,13 +3595,13 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) rc = boot_update_hw_rollback_protection(state); if (rc != 0) { FIH_SET(fih_rc, FIH_FAILURE); - goto out; + goto close; } rc = boot_add_shared_data(state, (uint8_t)state->slot_usage[BOOT_CURR_IMG(state)].active_slot); if (rc != 0) { FIH_SET(fih_rc, FIH_FAILURE); - goto out; + goto close; } } @@ -3827,9 +3612,10 @@ context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp) fill_rsp(state, rsp); -out: - close_all_flash_areas(state); +close: + boot_close_all_flash_areas(state); +out: if (rc != 0) { FIH_SET(fih_rc, FIH_FAILURE); } @@ -3886,92 +3672,77 @@ boot_go_for_image_id(struct boot_rsp *rsp, uint32_t image_id) FIH_RET(fih_rc); } -/** - * Clears the boot state, so that previous operations have no effect on new - * ones. - * - * @param state The state that should be cleared. If the value - * is NULL, the default bootloader state will be - * cleared. - */ -void boot_state_clear(struct boot_loader_state *state) -{ - if (state != NULL) { - memset(state, 0, sizeof(struct boot_loader_state)); - } else { - memset(&boot_data, 0, sizeof(struct boot_loader_state)); - } -} - -#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) -/** - * Reads image data to find out the maximum application sizes. Only needs to - * be called in serial recovery mode, as the state information is unpopulated - * at that time - */ -static void boot_fetch_slot_state_sizes(void) +int +boot_open_all_flash_areas(struct boot_loader_state *state) { size_t slot; - int rc = -1; + int rc = 0; int fa_id; int image_index; - IMAGES_ITER(BOOT_CURR_IMG(&boot_data)) { - int max_size = 0; - - image_index = BOOT_CURR_IMG(&boot_data); - - BOOT_IMG(&boot_data, BOOT_PRIMARY_SLOT).sectors = - sector_buffers.primary[image_index]; - BOOT_IMG(&boot_data, BOOT_SECONDARY_SLOT).sectors = - sector_buffers.secondary[image_index]; -#if MCUBOOT_SWAP_USING_SCRATCH - boot_data.scratch.sectors = sector_buffers.scratch; + IMAGES_ITER(BOOT_CURR_IMG(state)) { +#if BOOT_IMAGE_NUMBER > 1 + if (state->img_mask[BOOT_CURR_IMG(state)]) { + continue; + } #endif + image_index = BOOT_CURR_IMG(state); - /* Open primary and secondary image areas for the duration - * of this call. - */ for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { fa_id = flash_area_id_from_multi_image_slot(image_index, slot); - rc = flash_area_open(fa_id, &BOOT_IMG_AREA(&boot_data, slot)); + rc = flash_area_open(fa_id, &BOOT_IMG_AREA(state, slot)); assert(rc == 0); if (rc != 0) { - BOOT_LOG_DBG("boot_fetch_slot_state_sizes: error %d for %d", - rc, fa_id); - goto finish; + BOOT_LOG_ERR("Failed to open flash area ID %d (image %d slot %zu): %d", + fa_id, image_index, slot, rc); + goto out; } } + } #if MCUBOOT_SWAP_USING_SCRATCH - rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, - &BOOT_SCRATCH_AREA(&boot_data)); - assert(rc == 0); + rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &BOOT_SCRATCH_AREA(state)); + assert(rc == 0); - if (rc != 0) { - goto finish; - } + if (rc != 0) { + BOOT_LOG_ERR("Failed to open scratch flash area: %d", rc); + goto out; + } #endif - /* Determine the sector layout of the image slots and scratch area. */ - rc = boot_read_sectors_recovery(&boot_data); +out: + if (rc != 0) { + boot_close_all_flash_areas(state); + } - if (rc == 0) { - max_size = app_max_size(&boot_data); + return rc; +} + +void +boot_close_all_flash_areas(struct boot_loader_state *state) +{ + uint32_t slot; + +#if MCUBOOT_SWAP_USING_SCRATCH + if (BOOT_SCRATCH_AREA(state) != NULL) { + flash_area_close(BOOT_SCRATCH_AREA(state)); + } +#endif - if (max_size > 0) { - image_max_sizes[image_index].calculated = true; - image_max_sizes[image_index].max_size = max_size; + IMAGES_ITER(BOOT_CURR_IMG(state)) { +#if BOOT_IMAGE_NUMBER > 1 + if (state->img_mask[BOOT_CURR_IMG(state)]) { + continue; + } +#endif + for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) { + if (BOOT_IMG_AREA(state, BOOT_NUM_SLOTS - 1 - slot) != NULL) { + flash_area_close(BOOT_IMG_AREA(state, BOOT_NUM_SLOTS - 1 - slot)); } } } - -finish: - close_all_flash_areas(&boot_data); - memset(&boot_data, 0x00, sizeof(boot_data)); } -#endif #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING) /** diff --git a/boot/espressif/include/crypto_config/mbedtls_custom_config.h b/boot/espressif/include/crypto_config/mbedtls_custom_config.h index ed3c0efc2..0db9a0fdf 100644 --- a/boot/espressif/include/crypto_config/mbedtls_custom_config.h +++ b/boot/espressif/include/crypto_config/mbedtls_custom_config.h @@ -133,7 +133,7 @@ * * Comment if your system does not support time functions */ -#define MBEDTLS_HAVE_TIME +// #define MBEDTLS_HAVE_TIME /** * \def MBEDTLS_HAVE_TIME_DATE @@ -154,7 +154,7 @@ * mbedtls_platform_gmtime_r() at compile-time by using the macro * MBEDTLS_PLATFORM_GMTIME_R_ALT. */ -#define MBEDTLS_HAVE_TIME_DATE +// #define MBEDTLS_HAVE_TIME_DATE /** * \def MBEDTLS_PLATFORM_MEMORY diff --git a/boot/espressif/include/crypto_config/rsa.cmake b/boot/espressif/include/crypto_config/rsa.cmake index ee146cd72..54f1bd1d3 100644 --- a/boot/espressif/include/crypto_config/rsa.cmake +++ b/boot/espressif/include/crypto_config/rsa.cmake @@ -14,6 +14,8 @@ if (DEFINED CONFIG_ESP_USE_MBEDTLS) ${MBEDTLS_DIR}/library/sha256.c ${MBEDTLS_DIR}/library/rsa.c ${MBEDTLS_DIR}/library/bignum.c + ${MBEDTLS_DIR}/library/bignum_core.c + ${MBEDTLS_DIR}/library/constant_time.c ${MBEDTLS_DIR}/library/asn1parse.c ${MBEDTLS_DIR}/library/md.c ${MBEDTLS_DIR}/library/memory_buffer_alloc.c diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index abb0f9a2d..694426598 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -85,19 +85,13 @@ if(DEFINED CONFIG_ENABLE_MGMT_PERUSER) SECTIONS include/boot_serial/boot_serial.ld ) - if(DEFINED CONFIG_BOOT_MGMT_CUSTOM_STORAGE_ERASE OR DEFINED CONFIG_BOOT_MGMT_CUSTOM_IMG_LIST) + if(DEFINED CONFIG_BOOT_MGMT_CUSTOM_STORAGE_ERASE) zephyr_library_sources( boot_serial_extension_zephyr_basic.c ) endif() endif() -if(NOT DEFINED CONFIG_FLASH_PAGE_LAYOUT) - zephyr_library_sources( - flash_map_legacy.c - ) -endif() - if(DEFINED CONFIG_BOOT_SHARE_BACKEND_RETENTION) zephyr_library_sources( shared_data.c @@ -482,9 +476,17 @@ if(CONFIG_BOOT_ENCRYPTION_KEY_FILE AND NOT CONFIG_BOOT_ENCRYPTION_KEY_FILE STREQ endif() if(CONFIG_MCUBOOT_CLEANUP_ARM_CORE) -zephyr_library_sources( - ${BOOT_DIR}/zephyr/arm_cleanup.c -) + # ARM Cortex-M + zephyr_library_sources_ifdef( + CONFIG_CPU_CORTEX_M + ${BOOT_DIR}/zephyr/cleanup/arm_cortex_m.c + ) + + # ARM Cortex-R + zephyr_library_sources_ifdef( + CONFIG_ARMV7_R + ${BOOT_DIR}/zephyr/cleanup/arm_cortex_r.c + ) endif() if(CONFIG_MCUBOOT_BOOT_BANNER) @@ -579,6 +581,10 @@ if((CONFIG_BOOT_SWAP_USING_SCRATCH OR CONFIG_BOOT_SWAP_USING_MOVE OR CONFIG_BOOT zephyr_library_sources(flash_check.c) endif() +if(CONFIG_BOOT_RAM_LOAD) + zephyr_library_sources(ram_load.c) +endif() + if(SYSBUILD) if(CONFIG_SINGLE_APPLICATION_SLOT OR CONFIG_BOOT_FIRMWARE_LOADER OR CONFIG_BOOT_SWAP_USING_SCRATCH OR CONFIG_BOOT_SWAP_USING_MOVE OR CONFIG_BOOT_SWAP_USING_OFFSET OR CONFIG_BOOT_UPGRADE_ONLY OR CONFIG_BOOT_DIRECT_XIP OR CONFIG_BOOT_RAM_LOAD) # TODO: RAM LOAD support diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index cdb4d29cc..b8eb99790 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -384,6 +384,19 @@ endif endchoice +config BOOT_BYPASS_KEY_MATCH + bool "Do not match TLV key hash against built in key" + depends on !BOOT_SIGNATURE_TYPE_NONE + depends on !BOOT_HW_KEY + help + MCUboot reads, from TLV, hash of a key that should be used to verify + a signature and uses it to find a builtin key. + This action is pointless when there is single key compiled in, + as the signature verification process will just fail if that is not + the right key. + Enabling this option turns off key matching, slightly reducing + MCUboot code and boot time. + config BOOT_SIGNATURE_USING_KMU bool "Use KMU stored keys for signature verification" depends on NRF_SECURITY @@ -452,7 +465,7 @@ endif config MCUBOOT_CLEANUP_ARM_CORE bool "Perform core cleanup before chain-load the application" - depends on CPU_CORTEX_M + depends on CPU_CORTEX_M || ARMV7_R default y help This option instructs MCUboot to perform a clean-up of a set of @@ -524,6 +537,7 @@ config BOOT_VALIDATE_SLOT0_ONCE config BOOT_PREFER_SWAP_OFFSET bool "Prefer the newer swap offset algorithm" + default y if !$(dt_nodelabel_enabled,scratch_partition) && !SOC_FAMILY_STM32 help If y, the BOOT_IMAGE_UPGRADE_MODE will default to using "offset" instead of "scratch". This is a separate bool config option, because Kconfig doesn't allow defaults to be @@ -531,7 +545,7 @@ config BOOT_PREFER_SWAP_OFFSET config BOOT_PREFER_SWAP_MOVE bool "Prefer the newer swap move algorithm" - default y if SOC_FAMILY_NORDIC_NRF + depends on !BOOT_PREFER_SWAP_OFFSET default y if !$(dt_nodelabel_enabled,scratch_partition) help If y, the BOOT_IMAGE_UPGRADE_MODE will default to using @@ -627,6 +641,17 @@ config BOOT_DIRECT_XIP_REVERT attempt to boot the previous image. The images can also be made permanent (marked as confirmed in advance) just like in swap mode. +config BOOT_RAM_LOAD_REVERT + bool "Enable the revert mechanism in ram-load mode" + depends on BOOT_RAM_LOAD + help + If y, enables the revert mechanism in ram-load similar to the one in + swap mode. It requires the trailer magic to be added to the signed image. + When a reboot happens without the image being confirmed at runtime, the + bootloader considers the image faulty and erases it. After this it will + attempt to boot the previous image. The images can also be made permanent + (marked as confirmed in advance) just like in swap mode. + config BOOT_BOOTSTRAP bool "Bootstrap erased the primary slot from the secondary slot" help @@ -670,6 +695,14 @@ config BOOT_IMAGE_EXECUTABLE_RAM_SIZE default $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_SRAM),0) endif +config MULTIPLE_EXECUTABLE_RAM_REGIONS + bool "Platform RAM is split over multiple areas" + depends on BOOT_RAM_LOAD + help + To be selected if MCUBoot should be aware of several executable RAM areas. + When selected, boot_get_image_exec_ram_info() should be updated to provide + the information about the areas. + config FLASH_RUNTIME_SOURCES bool "Images are read from flash partitions defined at runtime" depends on SINGLE_APPLICATION_SLOT @@ -724,6 +757,22 @@ config BOOT_ENCRYPT_X25519 help Hidden option selecting x25519 encryption. +if BOOT_ENCRYPT_IMAGE + +choice BOOT_ENCRYPT_ALG + prompt "Algorithm used for image encryption" + default BOOT_ENCRYPT_ALG_AES_128 + +config BOOT_ENCRYPT_ALG_AES_128 + bool "Use AES-128 for image encryption" + +config BOOT_ENCRYPT_ALG_AES_256 + bool "Use AES-256 for image encryption" + +endchoice # BOOT_ENCRYPT_ALG + +endif # BOOT_ENCRYPT_IMAGE + if BOOT_ENCRYPT_X25519 && BOOT_USE_PSA_CRYPTO choice BOOT_HMAC_SHA @@ -1130,6 +1179,13 @@ config MCUBOOT_ACTION_HOOKS 'mcuboot_status_type_t' is listed in boot/bootutil/include/bootutil/mcuboot_status.h +config FIND_NEXT_SLOT_HOOKS + bool "Enable hooks for finding the next active slot" + help + Allow to provide procedures for override or extend the search policy + for the best slot to boot in the Direct XIP mode. + By default a slot with the highest version is selected. + config BOOT_DISABLE_CACHES bool "Disable I/D caches before chain-loading application" depends on CPU_HAS_ICACHE || CPU_HAS_DCACHE diff --git a/boot/zephyr/boards/ctcc_nrf52840.conf b/boot/zephyr/boards/ctcc_nrf52840.conf index ec8ea7f9f..5cbe290f6 100644 --- a/boot/zephyr/boards/ctcc_nrf52840.conf +++ b/boot/zephyr/boards/ctcc_nrf52840.conf @@ -18,3 +18,6 @@ CONFIG_MULTITHREADING=y # USB CONFIG_USB_DEVICE_STACK=y CONFIG_USB_DEVICE_REMOTE_WAKEUP=n + +# Partitions set up for swap using move +CONFIG_BOOT_PREFER_SWAP_MOVE=y diff --git a/boot/zephyr/boards/decawave_dwm3001cdk.conf b/boot/zephyr/boards/decawave_dwm3001cdk.conf new file mode 100644 index 000000000..13013eaeb --- /dev/null +++ b/boot/zephyr/boards/decawave_dwm3001cdk.conf @@ -0,0 +1,2 @@ +# Partitions set up for swap using move +CONFIG_BOOT_PREFER_SWAP_MOVE=y diff --git a/boot/zephyr/boards/frdm_mcxn947_mcxn947_cpu0.conf b/boot/zephyr/boards/frdm_mcxn947_mcxn947_cpu0.conf deleted file mode 100644 index 801162f1a..000000000 --- a/boot/zephyr/boards/frdm_mcxn947_mcxn947_cpu0.conf +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright 2024 NXP -# SPDX-License-Identifier: Apache-2.0 - -#MCXN94x does not support the MCUBoot swap mode. -CONFIG_BOOT_UPGRADE_ONLY=y diff --git a/boot/zephyr/boards/frdm_mcxn947_mcxn947_cpu0_qspi.conf b/boot/zephyr/boards/frdm_mcxn947_mcxn947_cpu0_qspi.conf deleted file mode 100644 index 1df4d9cb1..000000000 --- a/boot/zephyr/boards/frdm_mcxn947_mcxn947_cpu0_qspi.conf +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright 2023 NXP -# SPDX-License-Identifier: Apache-2.0 - -CONFIG_BOOT_UPGRADE_ONLY=y diff --git a/boot/zephyr/boards/frdm_mcxn947_mcxn947_cpu0_qspi.overlay b/boot/zephyr/boards/frdm_mcxn947_mcxn947_cpu0_qspi.overlay deleted file mode 100644 index 4fd133b81..000000000 --- a/boot/zephyr/boards/frdm_mcxn947_mcxn947_cpu0_qspi.overlay +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright 2023 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/ { - chosen { - zephyr,flash = &flash; - zephyr,code-partition = &boot_partition; - }; -}; - diff --git a/boot/zephyr/boards/it8xxx2_evb.conf b/boot/zephyr/boards/it8xxx2_evb.conf new file mode 100644 index 000000000..13013eaeb --- /dev/null +++ b/boot/zephyr/boards/it8xxx2_evb.conf @@ -0,0 +1,2 @@ +# Partitions set up for swap using move +CONFIG_BOOT_PREFER_SWAP_MOVE=y diff --git a/boot/zephyr/boards/mcx_n9xx_evk_mcxn947_cpu0.conf b/boot/zephyr/boards/mcx_n9xx_evk_mcxn947_cpu0.conf deleted file mode 100644 index ef44ad314..000000000 --- a/boot/zephyr/boards/mcx_n9xx_evk_mcxn947_cpu0.conf +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright 2025 NXP -# SPDX-License-Identifier: Apache-2.0 - -#MCXN94x does not support the MCUBoot swap mode. -CONFIG_BOOT_UPGRADE_ONLY=y diff --git a/boot/zephyr/boards/mcx_n9xx_evk_mcxn947_cpu0_qspi.conf b/boot/zephyr/boards/mcx_n9xx_evk_mcxn947_cpu0_qspi.conf deleted file mode 100644 index 638b3f72e..000000000 --- a/boot/zephyr/boards/mcx_n9xx_evk_mcxn947_cpu0_qspi.conf +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright 2025 NXP -# SPDX-License-Identifier: Apache-2.0 - -CONFIG_BOOT_UPGRADE_ONLY=y diff --git a/boot/zephyr/boards/mcx_n9xx_evk_mcxn947_cpu0_qspi.overlay b/boot/zephyr/boards/mcx_n9xx_evk_mcxn947_cpu0_qspi.overlay deleted file mode 100644 index bcc8bd98a..000000000 --- a/boot/zephyr/boards/mcx_n9xx_evk_mcxn947_cpu0_qspi.overlay +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2025 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/ { - chosen { - zephyr,flash = &flash; - zephyr,code-partition = &boot_partition; - }; -}; diff --git a/boot/zephyr/boards/micromod_nrf52840..conf b/boot/zephyr/boards/micromod_nrf52840..conf new file mode 100644 index 000000000..13013eaeb --- /dev/null +++ b/boot/zephyr/boards/micromod_nrf52840..conf @@ -0,0 +1,2 @@ +# Partitions set up for swap using move +CONFIG_BOOT_PREFER_SWAP_MOVE=y diff --git a/boot/zephyr/boards/mimxrt1050_evk_mimxrt1052_hyperflash_ram_load.overlay b/boot/zephyr/boards/mimxrt1050_evk_mimxrt1052_hyperflash_ram_load.overlay new file mode 100644 index 000000000..23a0298f3 --- /dev/null +++ b/boot/zephyr/boards/mimxrt1050_evk_mimxrt1052_hyperflash_ram_load.overlay @@ -0,0 +1,31 @@ +/ { + sram@80007F00 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x80007F00 0x100>; + zephyr,memory-region = "RetainedMem"; + status = "okay"; + + retainedmem { + compatible = "zephyr,retained-ram"; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + + boot_info0: boot_info@0 { + compatible = "zephyr,retention"; + status = "okay"; + reg = <0x0 0x100>; + }; + }; + }; + + chosen { + zephyr,bootloader-info = &boot_info0; + zephyr,code-partition = &boot_partition; + }; +}; + +/* Reduce size of slot 0 to match slot 1 */ +&slot0_partition { + reg = <0x40000 0x300000>; +}; diff --git a/boot/zephyr/boards/myra_sip_baseboard.conf b/boot/zephyr/boards/myra_sip_baseboard.conf new file mode 100644 index 000000000..13013eaeb --- /dev/null +++ b/boot/zephyr/boards/myra_sip_baseboard.conf @@ -0,0 +1,2 @@ +# Partitions set up for swap using move +CONFIG_BOOT_PREFER_SWAP_MOVE=y diff --git a/boot/zephyr/boards/nrf52840_big.overlay b/boot/zephyr/boards/nrf52840_big.overlay index 8ad19fca2..ed96bafd7 100644 --- a/boot/zephyr/boards/nrf52840_big.overlay +++ b/boot/zephyr/boards/nrf52840_big.overlay @@ -10,22 +10,24 @@ &flash0 { partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x000000000 0x00010000>; - }; - slot0_partition: partition@10000 { - label = "image-0"; - reg = <0x000010000 0x000074000>; - }; - slot1_partition: partition@75000 { - label = "image-1"; - reg = <0x00084000 0x000074000>; - }; + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x000000000 0x00010000>; + }; + + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x000010000 0x000074000>; + }; + + slot1_partition: partition@75000 { + label = "image-1"; + reg = <0x00084000 0x000074000>; + }; }; }; diff --git a/boot/zephyr/boards/nrf52840_single_slot.overlay b/boot/zephyr/boards/nrf52840_single_slot.overlay index 8e7cc333c..c65808af0 100644 --- a/boot/zephyr/boards/nrf52840_single_slot.overlay +++ b/boot/zephyr/boards/nrf52840_single_slot.overlay @@ -18,6 +18,7 @@ label = "mcuboot"; reg = <0x000000000 0x00010000>; }; + slot0_partition: partition@10000 { label = "image-0"; reg = <0x000010000 0x0000E8000>; diff --git a/boot/zephyr/boards/nrf52840dk_nrf52840_ram_load.overlay b/boot/zephyr/boards/nrf52840dk_nrf52840_ram_load.overlay new file mode 100644 index 000000000..e9ad880e5 --- /dev/null +++ b/boot/zephyr/boards/nrf52840dk_nrf52840_ram_load.overlay @@ -0,0 +1,31 @@ +&gpregret1 { + /delete-node/ boot_mode@0; +}; + +/ { + sram@2003FC00 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x2003FC00 DT_SIZE_K(1)>; + zephyr,memory-region = "RetainedMem"; + status = "okay"; + + retainedmem { + compatible = "zephyr,retained-ram"; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + + boot_info0: boot_info@0 { + compatible = "zephyr,retention"; + status = "okay"; + reg = <0x0 0x100>; + }; + }; + }; + + chosen { + /delete-property/ zephyr,boot-mode; + zephyr,bootloader-info = &boot_info0; + zephyr,code-partition = &boot_partition; + }; +}; diff --git a/boot/zephyr/boards/nrf52840dk_qspi_nor_secondary.overlay b/boot/zephyr/boards/nrf52840dk_qspi_nor_secondary.overlay index 948a530ad..bfebf81ef 100644 --- a/boot/zephyr/boards/nrf52840dk_qspi_nor_secondary.overlay +++ b/boot/zephyr/boards/nrf52840dk_qspi_nor_secondary.overlay @@ -14,6 +14,7 @@ label = "mcuboot"; reg = <0x000000000 0x00010000>; }; + slot0_partition: partition@10000 { label = "image-0"; reg = <0x000010000 0x0000e8000>; diff --git a/boot/zephyr/boards/nrf52840dk_ram.overlay b/boot/zephyr/boards/nrf52840dk_ram.overlay index d489e97e7..f854ab859 100644 --- a/boot/zephyr/boards/nrf52840dk_ram.overlay +++ b/boot/zephyr/boards/nrf52840dk_ram.overlay @@ -14,6 +14,7 @@ label = "mcuboot"; reg = <0x000000000 0x00010000>; }; + slot0_partition: partition@10000 { label = "image-0"; reg = <0x000010000 0x00000A000>; diff --git a/boot/zephyr/boards/nrf52840dk_ram_multi.overlay b/boot/zephyr/boards/nrf52840dk_ram_multi.overlay index aeb0b05b4..4f4685158 100644 --- a/boot/zephyr/boards/nrf52840dk_ram_multi.overlay +++ b/boot/zephyr/boards/nrf52840dk_ram_multi.overlay @@ -14,14 +14,17 @@ label = "mcuboot"; reg = <0x000000000 0x00010000>; }; + slot0_partition: partition@10000 { label = "image-0"; reg = <0x000010000 0x00000A000>; }; + slot1_partition: partition@1A000 { label = "image-1"; reg = <0x00001A000 0x00000A000>; }; + slot3_partition: partition@24000 { label = "image-3"; reg = <0x000024000 0x00000A000>; diff --git a/boot/zephyr/boards/nrf52840dongle_nrf52840_bare.conf b/boot/zephyr/boards/nrf52840dongle_nrf52840_bare.conf new file mode 100644 index 000000000..d219f351d --- /dev/null +++ b/boot/zephyr/boards/nrf52840dongle_nrf52840_bare.conf @@ -0,0 +1,26 @@ +# The UART is used for Serial Recovery, so logging requires +# an RTT console, which is not available out of the box on this board. +# Disable logging. +CONFIG_LOG=n + +# Serial +CONFIG_CONSOLE=n +CONFIG_SERIAL=y +CONFIG_UART_NRFX=n +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_UART_LINE_CTRL=y + +# MCUBoot serial +CONFIG_GPIO=y +CONFIG_MCUBOOT_SERIAL=y +CONFIG_BOOT_SERIAL_CDC_ACM=y + +# Required by USB +CONFIG_MULTITHREADING=y + +# USB +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_REMOTE_WAKEUP=n +CONFIG_USB_DEVICE_PRODUCT="MCUBOOT" + +CONFIG_NORDIC_QSPI_NOR=n diff --git a/boot/zephyr/boards/nrf52_minimal_footprint.conf b/boot/zephyr/boards/nrf52_minimal_footprint.conf index a290312be..73fa4f66f 100644 --- a/boot/zephyr/boards/nrf52_minimal_footprint.conf +++ b/boot/zephyr/boards/nrf52_minimal_footprint.conf @@ -16,10 +16,6 @@ CONFIG_BOOT_SIGNATURE_KEY_FILE="root-ec-p256.pem" # by reliability reason. CONFIG_BOOT_UPGRADE_ONLY=y -# CONFIG_BOARD_ENABLE_DCDC is not set -CONFIG_SOC_SERIES_NRF52X=y -CONFIG_SOC_NRF52832_QFAA=y -CONFIG_ARM=y CONFIG_ARM_MPU=n CONFIG_MAIN_STACK_SIZE=10240 CONFIG_THREAD_STACK_INFO=n @@ -27,9 +23,11 @@ CONFIG_THREAD_STACK_INFO=n CONFIG_FLASH=y CONFIG_CONSOLE=n +CONFIG_UART_CONSOLE=n CONFIG_DEBUG=n CONFIG_EARLY_CONSOLE=n CONFIG_PRINTK=n +CONFIG_LOG=n CONFIG_SYS_CLOCK_EXISTS=n @@ -37,7 +35,6 @@ CONFIG_SYS_CLOCK_EXISTS=n CONFIG_I2C=n CONFIG_WATCHDOG=n CONFIG_GPIO=n -CONFIG_PINMUX=n CONFIG_SPI=n CONFIG_SERIAL=n @@ -49,13 +46,11 @@ CONFIG_DYNAMIC_INTERRUPTS=n CONFIG_IRQ_OFFLOAD=n # Memory protection -CONFIG_MEMORY_PROTECTION=n CONFIG_THREAD_CUSTOM_DATA=n CONFIG_FPU=n # Boot CONFIG_BOOT_BANNER=n -CONFIG_BOOT_DELAY=0 # Console CONFIG_STDOUT_CONSOLE=n diff --git a/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf b/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp.conf similarity index 70% rename from boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf rename to boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp.conf index 31666d9fe..cddf7b646 100644 --- a/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf +++ b/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -10,3 +10,7 @@ CONFIG_SPI_NOR=n CONFIG_FPROTECT=n CONFIG_BOOT_WATCHDOG_FEED=n + +# Power domains forced on by default on boot, no need +# to manage them in bootloader. +CONFIG_POWER_DOMAIN=n diff --git a/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 000000000..d564ed924 --- /dev/null +++ b/boot/zephyr/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&gdpwr { + status = "disabled"; +}; + +&gdpwr_fast_active_0 { + status = "disabled"; +}; + +&gdpwr_fast_active_1 { + status = "disabled"; +}; + +&gdpwr_fast_main { + status = "disabled"; +}; + +&gdpwr_slow_active { + status = "disabled"; +}; + +&gdpwr_slow_main { + status = "disabled"; +}; + +&gpio_pad_group0 { + status = "disabled"; +}; + +&gpio_pad_group1 { + status = "disabled"; +}; + +&gpio_pad_group2 { + status = "disabled"; +}; + +&gpio_pad_group6 { + status = "disabled"; +}; + +&gpio_pad_group7 { + status = "disabled"; +}; + +&gpio_pad_group9 { + status = "disabled"; +}; diff --git a/boot/zephyr/boards/nucleo_h7s3l8.conf b/boot/zephyr/boards/nucleo_h7s3l8.conf new file mode 100644 index 000000000..93013ed9a --- /dev/null +++ b/boot/zephyr/boards/nucleo_h7s3l8.conf @@ -0,0 +1,4 @@ +CONFIG_BOOT_DIRECT_XIP=y +CONFIG_STM32_MEMMAP=y +CONFIG_BOOT_MAX_IMG_SECTORS_AUTO=n +CONFIG_BOOT_MAX_IMG_SECTORS=4096 diff --git a/boot/zephyr/boards/numaker_pfm_m467.conf b/boot/zephyr/boards/numaker_pfm_m467.conf new file mode 100644 index 000000000..13013eaeb --- /dev/null +++ b/boot/zephyr/boards/numaker_pfm_m467.conf @@ -0,0 +1,2 @@ +# Partitions set up for swap using move +CONFIG_BOOT_PREFER_SWAP_MOVE=y diff --git a/boot/zephyr/boards/stm32h573i_dk.conf b/boot/zephyr/boards/stm32h573i_dk.conf new file mode 100644 index 000000000..93013ed9a --- /dev/null +++ b/boot/zephyr/boards/stm32h573i_dk.conf @@ -0,0 +1,4 @@ +CONFIG_BOOT_DIRECT_XIP=y +CONFIG_STM32_MEMMAP=y +CONFIG_BOOT_MAX_IMG_SECTORS_AUTO=n +CONFIG_BOOT_MAX_IMG_SECTORS=4096 diff --git a/boot/zephyr/boards/stm32h7s78_dk.conf b/boot/zephyr/boards/stm32h7s78_dk.conf new file mode 100644 index 000000000..93013ed9a --- /dev/null +++ b/boot/zephyr/boards/stm32h7s78_dk.conf @@ -0,0 +1,4 @@ +CONFIG_BOOT_DIRECT_XIP=y +CONFIG_STM32_MEMMAP=y +CONFIG_BOOT_MAX_IMG_SECTORS_AUTO=n +CONFIG_BOOT_MAX_IMG_SECTORS=4096 diff --git a/boot/zephyr/boards/stm32n6570_dk_stm32n657xx_fsbl.conf b/boot/zephyr/boards/stm32n6570_dk_stm32n657xx_fsbl.conf new file mode 100644 index 000000000..706afac74 --- /dev/null +++ b/boot/zephyr/boards/stm32n6570_dk_stm32n657xx_fsbl.conf @@ -0,0 +1,5 @@ +CONFIG_STM32_MEMMAP=y +CONFIG_BOOT_MAX_IMG_SECTORS_AUTO=n +CONFIG_BOOT_MAX_IMG_SECTORS=4096 + +CONFIG_MULTIPLE_EXECUTABLE_RAM_REGIONS=y diff --git a/boot/zephyr/arm_cleanup.c b/boot/zephyr/cleanup/arm_cortex_m.c similarity index 91% rename from boot/zephyr/arm_cleanup.c rename to boot/zephyr/cleanup/arm_cortex_m.c index 3b6c71ace..9b3f37c16 100644 --- a/boot/zephyr/arm_cleanup.c +++ b/boot/zephyr/cleanup/arm_cortex_m.c @@ -7,11 +7,13 @@ #include #include -#if CONFIG_CPU_HAS_NXP_MPU +#if CONFIG_CPU_HAS_NXP_SYSMPU #include #endif -void cleanup_arm_nvic(void) { + +void cleanup_arm_interrupts(void) +{ /* Allow any pending interrupts to be recognized */ __ISB(); __disable_irq(); @@ -38,7 +40,7 @@ __weak void z_arm_clear_arm_mpu_config(void) ARM_MPU_ClrRegion(i); } } -#elif CONFIG_CPU_HAS_NXP_MPU +#elif CONFIG_CPU_HAS_NXP_SYSMPU __weak void z_arm_clear_arm_mpu_config(void) { int i; diff --git a/boot/zephyr/cleanup/arm_cortex_r.c b/boot/zephyr/cleanup/arm_cortex_r.c new file mode 100644 index 000000000..4611cd109 --- /dev/null +++ b/boot/zephyr/cleanup/arm_cortex_r.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * Copyright (c) 2025 Siemens Mobility GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#ifdef CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER +extern void z_soc_irq_eoi(unsigned int irq); +#else +#include +#endif + +#define READ_COPROCESSOR_REGISTER(out, coproc, opc1, crn, crm, opc2) \ + __asm__ volatile("mrc " #coproc ", " #opc1 ", %0, " #crn ", " #crm ", " #opc2 "\n" : "=r" (out) ::); + +#define WRITE_COPROCESSOR_REGISTER(in, coproc, opc1, crn, crm, opc2) \ + __asm__ volatile("mcr " #coproc ", " #opc1 ", %0, " #crn ", " #crm ", " #opc2 "\n" :: "r" (in) :) + +void cleanup_arm_interrupts(void) +{ + /* Allow any pending interrupts to be recognized */ + __ISB(); + __disable_irq(); + + for (unsigned int i = 0; i < CONFIG_NUM_IRQS; ++i) { + irq_disable(i); + } + + for (unsigned int i = 0; i < CONFIG_NUM_IRQS; ++i) { +#ifdef CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER + z_soc_irq_eoi(i); +#else + arm_gic_eoi(i); +#endif /* CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ + } +} + +#if CONFIG_CPU_HAS_ARM_MPU +__weak void z_arm_clear_arm_mpu_config(void) +{ + uint8_t i; + uint8_t num_regions; + uint32_t mpu_type_register; + + /* Disable MPU */ + uint32_t val; + READ_COPROCESSOR_REGISTER(val, p15, 0, c1, c0, 0); + val &= ~BIT(0); + __DSB(); + + WRITE_COPROCESSOR_REGISTER(val, p15, 0, c1, c0, 0); + __ISB(); + + /* The number of MPU regions is stored in bits 15:8 of the MPU type register */ + READ_COPROCESSOR_REGISTER(mpu_type_register, p15, 0, c0, c0, 4); + num_regions = (uint8_t) ((mpu_type_register >> 8) & BIT_MASK(8)); + + for (i = 0; i < num_regions; ++i) { + /* Select region in the MPU and clear the region size field */ + WRITE_COPROCESSOR_REGISTER(i, p15, 0, c6, c2, 0); + WRITE_COPROCESSOR_REGISTER(0, p15, 0, c6, c1, 2); + } +} +#endif diff --git a/boot/zephyr/flash_map_extended.c b/boot/zephyr/flash_map_extended.c index 3b95b1fd7..c5afb632b 100644 --- a/boot/zephyr/flash_map_extended.c +++ b/boot/zephyr/flash_map_extended.c @@ -20,7 +20,26 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); -#if (!defined(CONFIG_XTENSA) && DT_HAS_CHOSEN(zephyr_flash_controller)) +#if defined(CONFIG_STM32_MEMMAP) +/* MEMORY MAPPED for XiP on external NOR flash takes the sspi-nor or ospi-nor or qspi-nor device */ +#define FLASH_DEVICE_ID SPI_FLASH_0_ID +#if DT_NODE_HAS_STATUS(DT_INST(0, st_stm32_xspi_nor), okay) +#define DT_DRV_COMPAT st_stm32_xspi_nor +#define FLASH_DEVICE_NODE DT_INST(0, st_stm32_xspi_nor) +#define FLASH_DEVICE_BASE DT_REG_ADDR_BY_IDX(DT_INST_PARENT(0), 1) +#elif DT_NODE_HAS_STATUS(DT_INST(0, st_stm32_ospi_nor), okay) +#define DT_DRV_COMPAT st_stm32_ospi_nor +#define FLASH_DEVICE_NODE DT_INST(0, st_stm32_ospi_nor) +#define FLASH_DEVICE_BASE DT_REG_ADDR_BY_IDX(DT_INST_PARENT(0), 1) +#elif DT_NODE_HAS_STATUS(DT_INST(0, st_stm32_qspi_nor), okay) +#define DT_DRV_COMPAT st_stm32_qspi_nor +#define FLASH_DEVICE_NODE DT_INST(0, st_stm32_qspi_nor) +#define FLASH_DEVICE_BASE DT_REG_ADDR_BY_IDX(DT_INST_PARENT(0), 1) +#else +#error "FLASH_DEVICE_NODE could not be determined" +#endif + +#elif (!defined(CONFIG_XTENSA) && DT_HAS_CHOSEN(zephyr_flash_controller)) #define FLASH_DEVICE_ID SOC_FLASH_0_ID #define FLASH_DEVICE_BASE CONFIG_FLASH_BASE_ADDRESS #define FLASH_DEVICE_NODE DT_CHOSEN(zephyr_flash_controller) diff --git a/boot/zephyr/flash_map_legacy.c b/boot/zephyr/flash_map_legacy.c deleted file mode 100644 index 6a8e7ae3d..000000000 --- a/boot/zephyr/flash_map_legacy.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * @file - * @brief Legacy flash fallbacks - * - * This file contains hacks for flash drivers without page layout - * support. They're hacks because they guess a page layout that may be - * incorrect, but is likely to "work". Needless to say, such guesswork - * is undesirable in trusted bootloader code. - * - * The behavior is: - * - * - If FLASH_AREA_IMAGE_SECTOR_SIZE is defined (this was used by - * older Zephyr ports), the image sectors have uniform sector sizes. - * We also assume that's the size of the scratch sectors. - * - * - Otherwise, we assume that the size of the entire scratch area is - * a least common multiple of all sector sizes, and use that as - * FLASH_AREA_IMAGE_SECTOR_SIZE. - */ - -#include "bootutil/bootutil_log.h" - -#include -#include -#include - -#warning "The flash driver lacks page layout support; falling back on hacks." - -#if !defined(FLASH_AREA_IMAGE_SECTOR_SIZE) -#define FLASH_AREA_IMAGE_SECTOR_SIZE FLASH_AREA_IMAGE_SCRATCH_SIZE -#endif - -BOOT_LOG_MODULE_DECLARE(mcuboot); - -/* - * Lookup the sector map for a given flash area. This should fill in - * `ret` with all of the sectors in the area. `*cnt` will be set to - * the storage at `ret` and should be set to the final number of - * sectors in this area. - */ -int flash_area_get_sectors(int idx, uint32_t *cnt, struct flash_sector *ret) -{ - const struct flash_area *fa; - uint32_t max_cnt = *cnt; - uint32_t rem_len; - int rc = -1; - - if (flash_area_open(idx, &fa)) { - goto out; - } - - BOOT_LOG_DBG("area %d: offset=0x%x, length=0x%x", idx, fa->fa_off, - fa->fa_size); - - if (*cnt < 1) { - goto fa_close_out; - } - - rem_len = fa->fa_size; - *cnt = 0; - while (rem_len > 0 && *cnt < max_cnt) { - if (rem_len < FLASH_AREA_IMAGE_SECTOR_SIZE) { - BOOT_LOG_ERR("area %d size 0x%x not divisible by sector size 0x%x", - idx, fa->fa_size, FLASH_AREA_IMAGE_SECTOR_SIZE); - goto fa_close_out; - } - - ret[*cnt].fs_off = FLASH_AREA_IMAGE_SECTOR_SIZE * (*cnt); - ret[*cnt].fs_size = FLASH_AREA_IMAGE_SECTOR_SIZE; - *cnt = *cnt + 1; - rem_len -= FLASH_AREA_IMAGE_SECTOR_SIZE; - } - - if (*cnt >= max_cnt) { - BOOT_LOG_ERR("flash area %d sector count overflow", idx); - goto fa_close_out; - } - - rc = 0; - -fa_close_out: - flash_area_close(fa); -out: - return rc; -} diff --git a/boot/zephyr/hooks_sample.c b/boot/zephyr/hooks_sample.c index a5a729314..fc7bd2fa4 100644 --- a/boot/zephyr/hooks_sample.c +++ b/boot/zephyr/hooks_sample.c @@ -93,3 +93,8 @@ int boot_img_install_stat_hook(int image_index, int slot, int *img_install_stat) { return BOOT_HOOK_REGULAR; } + +int boot_find_next_slot_hook(struct boot_loader_state *state, uint8_t image, uint32_t *active_slot) +{ + return BOOT_HOOK_REGULAR; +} diff --git a/boot/zephyr/include/arm_cleanup.h b/boot/zephyr/include/arm_cleanup.h index 565477c09..8df50420b 100644 --- a/boot/zephyr/include/arm_cleanup.h +++ b/boot/zephyr/include/arm_cleanup.h @@ -11,9 +11,9 @@ /** * Cleanup interrupt priority and interupt enable registers. */ -void cleanup_arm_nvic(void); +void cleanup_arm_interrupts(void); -#if defined(CONFIG_CPU_HAS_ARM_MPU) || defined(CONFIG_CPU_HAS_NXP_MPU) +#if defined(CONFIG_CPU_HAS_ARM_MPU) || defined(CONFIG_CPU_HAS_NXP_SYSMPU) /** * Cleanup all ARM MPU region configuration */ diff --git a/boot/zephyr/include/mcuboot_config/mcuboot_config.h b/boot/zephyr/include/mcuboot_config/mcuboot_config.h index 8ba030738..2db83b0b0 100644 --- a/boot/zephyr/include/mcuboot_config/mcuboot_config.h +++ b/boot/zephyr/include/mcuboot_config/mcuboot_config.h @@ -106,6 +106,10 @@ #define MCUBOOT_DIRECT_XIP_REVERT #endif +#ifdef CONFIG_BOOT_RAM_LOAD_REVERT +#define MCUBOOT_RAM_LOAD_REVERT +#endif + #ifdef CONFIG_BOOT_RAM_LOAD #define MCUBOOT_RAM_LOAD 1 #define IMAGE_EXECUTABLE_RAM_START CONFIG_BOOT_IMAGE_EXECUTABLE_RAM_START @@ -144,6 +148,10 @@ #define IMAGE_EXECUTABLE_RAM_SIZE CONFIG_BOOT_IMAGE_EXECUTABLE_RAM_SIZE #endif +#ifdef CONFIG_MULTIPLE_EXECUTABLE_RAM_REGIONS +#define MULTIPLE_EXECUTABLE_RAM_REGIONS +#endif + #ifdef CONFIG_LOG #define MCUBOOT_HAVE_LOGGING 1 #endif @@ -163,6 +171,14 @@ #define MCUBOOT_ENCRYPT_X25519 #endif +#ifdef CONFIG_BOOT_ENCRYPT_ALG_AES_128 +#define MCUBOOT_AES_128 +#endif + +#ifdef CONFIG_BOOT_ENCRYPT_ALG_AES_256 +#define MCUBOOT_AES_256 +#endif + /* Support for HMAC/HKDF using SHA512; this is used in key exchange where * HKDF is used for key expansion and HMAC is used for key verification. */ @@ -170,6 +186,15 @@ #define MCUBOOT_HMAC_SHA512 #endif +/* Turn off check of public key hash against compiled in key + * before attempting signature verification. When there is only + * one key, matching is pointless, the signature may just be + * verified with the only key that there is. + */ +#ifdef CONFIG_BOOT_BYPASS_KEY_MATCH +#define MCUBOOT_BYPASS_KEY_MATCH +#endif + #ifdef CONFIG_BOOT_DECOMPRESSION #define MCUBOOT_DECOMPRESS_IMAGES #endif @@ -251,10 +276,6 @@ #define MCUBOOT_PERUSER_MGMT_GROUP_ENABLED 0 #endif -#ifdef CONFIG_BOOT_MGMT_CUSTOM_IMG_LIST -#define MCUBOOT_MGMT_CUSTOM_IMG_LIST -#endif - #ifdef CONFIG_BOOT_MGMT_ECHO #define MCUBOOT_BOOT_MGMT_ECHO #endif @@ -271,6 +292,10 @@ #define MCUBOOT_FLASH_AREA_HOOKS #endif +#ifdef CONFIG_FIND_NEXT_SLOT_HOOKS +#define MCUBOOT_FIND_NEXT_SLOT_HOOKS +#endif + #ifdef CONFIG_MCUBOOT_VERIFY_IMG_ADDRESS #define MCUBOOT_VERIFY_IMG_ADDRESS #endif diff --git a/boot/zephyr/io.c b/boot/zephyr/io.c index f2342c1ad..3cdbf4dfa 100644 --- a/boot/zephyr/io.c +++ b/boot/zephyr/io.c @@ -67,9 +67,6 @@ */ #if DT_NODE_EXISTS(DT_ALIAS(mcuboot_led0)) #define LED0_NODE DT_ALIAS(mcuboot_led0) -#elif DT_NODE_EXISTS(DT_ALIAS(bootloader_led0)) -#warning "bootloader-led0 alias is deprecated; use mcuboot-led0 instead" -#define LED0_NODE DT_ALIAS(bootloader_led0) #endif #if DT_NODE_HAS_STATUS(LED0_NODE, okay) && DT_NODE_HAS_PROP(LED0_NODE, gpios) diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index c51616dda..4cb7421c1 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -3,6 +3,7 @@ * Copyright (c) 2020 Arm Limited * Copyright (c) 2021-2023 Nordic Semiconductor ASA * Copyright (c) 2025 Aerlync Labs Inc. + * Copyright (c) 2025 Siemens Mobility GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +33,7 @@ #include #endif -#if defined(CONFIG_ARM) +#if defined(CONFIG_CPU_CORTEX_M) #include #endif @@ -135,8 +136,8 @@ K_SEM_DEFINE(boot_log_sem, 1, 1); /* synchronous log mode doesn't need to be initalized by the application */ #define ZEPHYR_BOOT_LOG_START() do { } while (false) #define ZEPHYR_BOOT_LOG_STOP() do { } while (false) -#endif /* defined(CONFIG_LOG) && !defined(ZEPHYR_LOG_MODE_IMMEDIATE) && \ - * !defined(ZEPHYR_LOG_MODE_MINIMAL) +#endif /* defined(CONFIG_LOG) && !defined(CONFIG_LOG_MODE_IMMEDIATE) && \ + * !defined(CONFIG_LOG_MODE_MINIMAL) */ #if USE_PARTITION_MANAGER && CONFIG_FPROTECT @@ -159,8 +160,19 @@ extern void *_vector_table_pointer; #endif struct arm_vector_table { +#ifdef CONFIG_CPU_CORTEX_M uint32_t msp; uint32_t reset; +#else + uint32_t reset; + uint32_t undef_instruction; + uint32_t svc; + uint32_t abort_prefetch; + uint32_t abort_data; + uint32_t reserved; + uint32_t irq; + uint32_t fiq; +#endif }; static void do_boot(struct boot_rsp *rsp) @@ -228,7 +240,7 @@ static void do_boot(struct boot_rsp *rsp) nrf_cleanup_ns_ram(); #endif #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE - cleanup_arm_nvic(); /* cleanup NVIC registers */ + cleanup_arm_interrupts(); /* Disable and acknowledge all interrupts */ #if defined(CONFIG_BOOT_DISABLE_CACHES) /* Flush and disable instruction/data caches before chain-loading the application */ @@ -238,7 +250,7 @@ static void do_boot(struct boot_rsp *rsp) sys_cache_data_disable(); #endif -#if CONFIG_CPU_HAS_ARM_MPU || CONFIG_CPU_HAS_NXP_MPU +#if CONFIG_CPU_HAS_ARM_MPU || CONFIG_CPU_HAS_NXP_SYSMPU z_arm_clear_arm_mpu_config(); #endif @@ -271,10 +283,31 @@ static void do_boot(struct boot_rsp *rsp) #endif #endif /* CONFIG_BOOT_INTR_VEC_RELOC */ +#ifdef CONFIG_CPU_CORTEX_M __set_MSP(vt->msp); +#endif + #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE +#ifdef CONFIG_CPU_CORTEX_M __set_CONTROL(0x00); /* application will configures core on its own */ __ISB(); +#else + /* Set mode to supervisor and A, I and F bit as described in the + * Cortex R5 TRM */ + __asm__ volatile( + " mrs r0, CPSR\n" + /* change mode bits to supervisor */ + " bic r0, #0x1f\n" + " orr r0, #0x13\n" + /* set the A, I and F bit */ + " mov r1, #0b111\n" + " lsl r1, #0x6\n" + " orr r0, r1\n" + + " msr CPSR, r0\n" + ::: "r0", "r1"); +#endif /* CONFIG_CPU_CORTEX_M */ + #endif #if CONFIG_MCUBOOT_CLEANUP_RAM __asm__ volatile ( @@ -305,7 +338,18 @@ static void do_boot(struct boot_rsp *rsp) : "r0", "r1", "r2", "r3", "memory" ); #else + +#ifdef CONFIG_CPU_CORTEX_M ((void (*)(void))vt->reset)(); +#else + /* Some ARM CPUs like the Cortex-R5 can run in thumb mode but reset into ARM + * mode (depending on a CPU signal configurations). To do the switch into ARM + * mode, if needed, an explicit branch with exchange instruction set + * instruction is needed + */ + __asm__("bx %0\n" : : "r" (&vt->reset)); +#endif + #endif } @@ -369,6 +413,37 @@ static void do_boot(struct boot_rsp *rsp) #endif /* CONFIG_SOC_FAMILY_ESPRESSIF_ESP32 */ } +#elif defined(CONFIG_ARC) + +/* + * ARC vector table has a pointer to the reset function as the first entry + * in the vector table. Assume the vector table is at the start of the image, + * and jump to reset + */ +static void do_boot(struct boot_rsp *rsp) +{ + struct arc_vector_table { + void (*reset)(void); /* Reset vector */ + } *vt; + +#if defined(MCUBOOT_RAM_LOAD) + vt = (struct arc_vector_table *)(rsp->br_hdr->ih_load_addr + rsp->br_hdr->ih_hdr_size); +#else + uintptr_t flash_base; + int rc; + + rc = flash_device_base(rsp->br_flash_dev_id, &flash_base); + assert(rc == 0); + + vt = (struct arc_vector_table *)(flash_base + rsp->br_image_off + + rsp->br_hdr->ih_hdr_size); +#endif + + /* Lock interrupts and dive into the entry point */ + irq_lock(); + vt->reset(); +} + #else /* Default: Assume entry point is at the very beginning of the image. Simply * lock interrupts and jump there. This is the right thing to do for X86 and @@ -397,8 +472,8 @@ static void do_boot(struct boot_rsp *rsp) } #endif -#if defined(CONFIG_LOG) && !defined(ZEPHYR_LOG_MODE_IMMEDIATE) && \ - !defined(CONFIG_LOG_PROCESS_THREAD) && !defined(ZEPHYR_LOG_MODE_MINIMAL) +#if defined(CONFIG_LOG) && !defined(CONFIG_LOG_MODE_IMMEDIATE) && \ + !defined(CONFIG_LOG_PROCESS_THREAD) && !defined(CONFIG_LOG_MODE_MINIMAL) /* The log internal thread for log processing can't transfer log well as has too * low priority. * Dedicated thread for log processing below uses highest application @@ -416,12 +491,7 @@ void boot_log_thread_func(void *dummy1, void *dummy2, void *dummy3) log_init(); while (1) { -#if defined(CONFIG_LOG1) || defined(CONFIG_LOG2) - /* support Zephyr legacy logging implementation before commit c5f2cde */ - if (log_process(false) == false) { -#else if (log_process() == false) { -#endif if (boot_log_stop) { break; } @@ -455,8 +525,8 @@ void zephyr_boot_log_stop(void) */ (void)k_sem_take(&boot_log_sem, K_FOREVER); } -#endif /* defined(CONFIG_LOG) && !defined(ZEPHYR_LOG_MODE_IMMEDIATE) && \ - * !defined(CONFIG_LOG_PROCESS_THREAD) && !defined(ZEPHYR_LOG_MODE_MINIMAL) +#endif /* defined(CONFIG_LOG) && !defined(CONFIG_LOG_MODE_IMMEDIATE) && \ + * !defined(CONFIG_LOG_PROCESS_THREAD) && !defined(CONFIG_LOG_MODE_MINIMAL) */ #if defined(CONFIG_BOOT_SERIAL_ENTRANCE_GPIO) || defined(CONFIG_BOOT_SERIAL_PIN_RESET) \ diff --git a/boot/zephyr/prj.conf b/boot/zephyr/prj.conf index 87829ba63..9de28b890 100644 --- a/boot/zephyr/prj.conf +++ b/boot/zephyr/prj.conf @@ -11,12 +11,6 @@ CONFIG_BOOT_BOOTSTRAP=n ### mbedTLS has its own heap # CONFIG_HEAP_MEM_POOL_SIZE is not set -### We never want Zephyr's copy of tinycrypt. If tinycrypt is needed, -### MCUboot has its own copy in tree. -# CONFIG_TINYCRYPT is not set -# CONFIG_TINYCRYPT_ECC_DSA is not set -# CONFIG_TINYCRYPT_SHA256 is not set - CONFIG_FLASH=y ### Various Zephyr boards enable features that we don't want. @@ -25,7 +19,7 @@ CONFIG_FLASH=y # CONFIG_I2C is not set CONFIG_LOG=y -CONFIG_LOG_MODE_MINIMAL=y # former CONFIG_MODE_MINIMAL +CONFIG_LOG_MODE_MINIMAL=y ### Ensure Zephyr logging changes don't use more resources CONFIG_LOG_DEFAULT_LEVEL=0 ### Use info log level by default diff --git a/boot/zephyr/ram_load.c b/boot/zephyr/ram_load.c new file mode 100644 index 000000000..92d521d80 --- /dev/null +++ b/boot/zephyr/ram_load.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 STMicroelectonics + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../bootutil/include/bootutil/bootutil.h" +#include "../bootutil/include/bootutil/ramload.h" + +#include + +#ifdef MULTIPLE_EXECUTABLE_RAM_REGIONS +int boot_get_image_exec_ram_info(uint32_t image_id, + uint32_t *exec_ram_start, + uint32_t *exec_ram_size) +{ + +#ifdef CONFIG_SOC_SERIES_STM32N6X + *exec_ram_start = DT_PROP_BY_IDX(DT_NODELABEL(axisram1), reg, 0); + *exec_ram_size = DT_PROP_BY_IDX(DT_NODELABEL(axisram1), reg, 1); +#endif + + return 0; +} +#endif /* MULTIPLE_EXECUTABLE_RAM_REGIONS */ diff --git a/boot/zephyr/sample.yaml b/boot/zephyr/sample.yaml index bf5bc93ea..f66f2e693 100644 --- a/boot/zephyr/sample.yaml +++ b/boot/zephyr/sample.yaml @@ -49,19 +49,20 @@ tests: tags: bootloader_mcuboot sample.bootloader.mcuboot.usb_cdc_acm_recovery: tags: bootloader_mcuboot - platform_allow: nrf52840dongle/nrf52840 + platform_allow: nrf52840dongle/nrf52840 extra_args: - EXTRA_CONF_FILE=./usb_cdc_acm_recovery.conf - DTC_OVERLAY_FILE="./usb_cdc_acm.overlay;app.overlay" - integration_platforms: - - nrf52840dongle/nrf52840 + extra_configs: + - CONFIG_DEPRECATION_TEST=y sample.bootloader.mcuboot.usb_cdc_acm_recovery_log: - extra_args: EXTRA_CONF_FILE=./usb_cdc_acm_log_recovery.conf - DTC_OVERLAY_FILE="./boards/nrf52840_big.overlay;app.overlay" - platform_allow: nrf52840dk/nrf52840 - integration_platforms: - - nrf52840dk/nrf52840 tags: bootloader_mcuboot + platform_allow: nrf52840dk/nrf52840 + extra_args: + - EXTRA_CONF_FILE=./usb_cdc_acm_log_recovery.conf + - DTC_OVERLAY_FILE="./boards/nrf52840_big.overlay;app.overlay" + extra_configs: + - CONFIG_DEPRECATION_TEST=y sample.bootloader.mcuboot.single_slot: extra_args: EXTRA_CONF_FILE=./single_slot.conf DTC_OVERLAY_FILE="./boards/nrf52840_single_slot.overlay;app.overlay" diff --git a/boot/zephyr/single_loader.c b/boot/zephyr/single_loader.c index 31c4a8bf7..69e2daa81 100644 --- a/boot/zephyr/single_loader.c +++ b/boot/zephyr/single_loader.c @@ -18,16 +18,24 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); -/* Variables passed outside of unit via poiters. */ -static const struct flash_area *_fa_p; +/* Variables passed outside of unit via pointers. */ static struct image_header _hdr = { 0 }; -static struct boot_loader_state boot_data; +static struct boot_loader_state state; struct boot_loader_state *boot_get_loader_state(void) { - return &boot_data; + return &state; } +#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) +static struct image_max_size image_max_sizes[BOOT_IMAGE_NUMBER] = {0}; + +struct image_max_size *boot_get_image_max_sizes(void) +{ + return image_max_sizes; +} +#endif + #if defined(MCUBOOT_VALIDATE_PRIMARY_SLOT) || defined(MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE) /** * Validate hash of a primary boot image. @@ -103,6 +111,69 @@ boot_image_validate_once(const struct flash_area *fa_p, } #endif +int +boot_open_all_flash_areas(struct boot_loader_state *state) +{ + int rc; + + rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(0), &BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); + assert(rc == 0); + + return rc; +} + +void +boot_close_all_flash_areas(struct boot_loader_state *state) +{ + flash_area_close(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)); +} + +#if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) +static int app_max_sectors(struct boot_loader_state *state) +{ + uint32_t sz = 0; + uint32_t sector_sz; + uint32_t trailer_sz; + uint32_t trailer_sectors = 0; + + sector_sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); + trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state)); + + while (1) { + sz += sector_sz; + ++trailer_sectors; + + if (sz >= trailer_sz) { + break; + } + } + + return boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) - trailer_sectors; +} + +int app_max_size(struct boot_loader_state *state) +{ + uint32_t sector_sz; + + sector_sz = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, 0); + + return app_max_sectors(state) * sector_sz; +} + +/** + * Fetches the maximum allowed size of the image + */ +const struct image_max_size *boot_get_max_app_size(void) +{ + if (image_max_sizes[0].calculated == false) { + /* Information not available, need to fetch it */ + boot_fetch_slot_state_sizes(); + } + + return image_max_sizes; +} +#endif + /** * Gather information on image and prepare for booting. * @@ -118,16 +189,13 @@ boot_go(struct boot_rsp *rsp) BOOT_LOG_DBG("boot_go: Single loader"); - rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(0), &_fa_p); - assert(rc == 0); + rc = boot_open_all_flash_areas(&state); - rc = boot_image_load_header(_fa_p, &_hdr); + rc = boot_image_load_header(BOOT_IMG_AREA(&state, BOOT_PRIMARY_SLOT), &_hdr); if (rc != 0) goto out; #ifdef MCUBOOT_RAM_LOAD - static struct boot_loader_state state; - BOOT_IMG_AREA(&state, 0) = _fa_p; state.imgs[0][0].hdr = _hdr; rc = boot_load_image_to_sram(&state); @@ -136,7 +204,7 @@ boot_go(struct boot_rsp *rsp) #endif #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT - FIH_CALL(boot_image_validate, fih_rc, _fa_p, &_hdr); + FIH_CALL(boot_image_validate, fih_rc, BOOT_IMG_AREA(&state, BOOT_PRIMARY_SLOT), &_hdr); if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { #ifdef MCUBOOT_RAM_LOAD boot_remove_image_from_sram(&state); @@ -144,7 +212,7 @@ boot_go(struct boot_rsp *rsp) goto out; } #elif defined(MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE) - FIH_CALL(boot_image_validate_once, fih_rc, _fa_p, &_hdr); + FIH_CALL(boot_image_validate_once, fih_rc, BOOT_IMG_AREA(&state, BOOT_PRIMARY_SLOT), &_hdr); if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { #ifdef MCUBOOT_RAM_LOAD boot_remove_image_from_sram(&state); @@ -156,7 +224,7 @@ boot_go(struct boot_rsp *rsp) #endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */ #ifdef MCUBOOT_MEASURED_BOOT - rc = boot_save_boot_status(0, &_hdr, _fa_p); + rc = boot_save_boot_status(0, &_hdr, BOOT_IMG_AREA(&state, BOOT_PRIMARY_SLOT)); if (rc != 0) { BOOT_LOG_ERR("Failed to add image data to shared area"); return rc; @@ -164,19 +232,19 @@ boot_go(struct boot_rsp *rsp) #endif /* MCUBOOT_MEASURED_BOOT */ #ifdef MCUBOOT_DATA_SHARING - rc = boot_save_shared_data(&_hdr, _fa_p, 0, NULL); + rc = boot_save_shared_data(&_hdr, BOOT_IMG_AREA(&state, BOOT_PRIMARY_SLOT), 0, NULL); if (rc != 0) { BOOT_LOG_ERR("Failed to add data to shared memory area."); return rc; } #endif /* MCUBOOT_DATA_SHARING */ - rsp->br_flash_dev_id = flash_area_get_device_id(_fa_p); - rsp->br_image_off = flash_area_get_off(_fa_p); + rsp->br_flash_dev_id = flash_area_get_device_id(BOOT_IMG_AREA(&state, BOOT_PRIMARY_SLOT)); + rsp->br_image_off = flash_area_get_off(BOOT_IMG_AREA(&state, BOOT_PRIMARY_SLOT)); rsp->br_hdr = &_hdr; out: - flash_area_close(_fa_p); + boot_close_all_flash_areas(&state); FIH_RET(fih_rc); } diff --git a/ci/fih-tests_run.sh b/ci/fih-tests_run.sh index 66357d5ca..4697c8851 100755 --- a/ci/fih-tests_run.sh +++ b/ci/fih-tests_run.sh @@ -18,16 +18,18 @@ set -e source $(dirname "$0")/fih-tests_version.sh -pushd .. &&\ - git clone https://git.trustedfirmware.org/TF-M/trusted-firmware-m.git &&\ - pushd trusted-firmware-m &&\ - git checkout eb8ff0db7d657b77abcd0262d5bf7f38eb1e1cdc &&\ - source lib/ext/tf-m-tests/version.txt &&\ - popd &&\ - git clone https://git.trustedfirmware.org/TF-M/tf-m-tests.git &&\ - pushd tf-m-tests &&\ - git checkout $version &&\ - popd +# Note that we are pulling from a github mirror of these repos, not direct upstream. If the sha +# checked out below changes, the mirrors might need to be updated. +pushd .. +git clone https://github.com/mcu-tools/trusted-firmware-m +pushd trusted-firmware-m +git checkout eb8ff0db7d657b77abcd0262d5bf7f38eb1e1cdc +source lib/ext/tf-m-tests/version.txt +popd +git clone https://github.com/mcu-tools/tf-m-tests.git +pushd tf-m-tests +git checkout $version +popd if [[ $GITHUB_ACTIONS == true ]]; then if [[ -z $FIH_ENV ]]; then diff --git a/docs/SECURITY.md b/docs/SECURITY.md index f995385c3..6627c1417 100644 --- a/docs/SECURITY.md +++ b/docs/SECURITY.md @@ -1,56 +1,31 @@ # Project security policy -The MCUboot team takes security, vulnerabilities, and weaknesses -seriously. +The MCUboot project uses the [TrustedFirmware.org security +policy](https://www.trustedfirmware.org/.well-known/security.txt). -## Reporting security issues +## Reporting security vulnerabilities -The preferred way to report security issues with MCUboot is via the "Report a -security vulnerability" button on the main [security -page](https://github.com/mcu-tools/mcuboot/security). +The preferred way to report a security vulnerability with MCUboot is via the +"Report a vulnerability" button on the main [security page +](https://github.com/mcu-tools/mcuboot/security). -You can also directly contact the following maintainers of the project: - -- David Brown: davidb@davidb.org or david.brown@linaro.org -- Fabio Utzig: utzig@apache.org - -If you wish to send an encrypted email, you may use these PGP keys: - -``` - pub rsa4096 2011-10-14 [SC] - DAFD760825AE2636AEA9CB19E6BA9F5C5E54DF82 - uid [ultimate] David Brown - uid [ultimate] David Brown - sub rsa4096 2011-10-14 [E] -``` - -and - -``` - pub rsa4096 2017-07-28 [SC] - 126087C7E725625BC7E89CC7537097EDFD4A7339 - uid [ unknown] Fabio Utzig - uid [ unknown] Fabio Utzig - sub rsa4096 2017-07-28 [E] -``` - -Please include the word "SECURITY" as well as "MCUboot" in the subject +You can also email the MCUboot security team at +mcuboot-security@lists.trustedfirmware.org as per the TrustedFirmware.org +policy. Please include the word "SECURITY" as well as "MCUboot" in the subject of any message. -We will make our best effort to respond in a timely manner. Most -vulnerabilities found within published code will undergo an embargo of -90 days to allow time fixes to be developed and deployed. - -## Vulnerability advisories +## Disclosure -Vulnerability reports and published fixes will be reported as follows: +Any confirmed security vulnerability will be disclosed to Trusted Stakeholders +as per the TrustedFirmware.org policy. -- Issues will be entered into MCUboot's [security advisory - system](https://github.com/mcu-tools/mcuboot/security/advisories) on GitHub, with - the interested parties (including the reporter) added as viewers. +A draft advisory and vulnerability fix will be created in MCUboot's [security +advisory system](https://github.com/mcu-tools/mcuboot/security/advisories) on +GitHub, with any interested Trusted Stakeholders and the reporter added as +viewers. -- The release notes will contain a reference to any allocated CVE(s). +On the public disclosure date, the security advisory page will be made public, +and the public CVE database will be updated with all relevant information. -- When the embargo is lifted, the security advisory page will be made - public, and the public CVE database will be updated with all - relevant information. +The release notes of the next MCUboot release will refer to any allocated +CVE(s). diff --git a/docs/design.md b/docs/design.md index c080b2b82..e4da1bfa8 100755 --- a/docs/design.md +++ b/docs/design.md @@ -345,7 +345,7 @@ image. After a successful validation of the selected image the bootloader chain-loads it. An additional "revert" mechanism is also supported. For more information, please -read the [corresponding section](#direct-xip-revert). +read the [corresponding section](#direct-xip-ram-load-revert). Handling the primary and secondary slots as equals has its drawbacks. Since the images are not moved between the slots, the on-the-fly image encryption/decryption can't be supported (it only applies to storing the image @@ -400,6 +400,11 @@ 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. +Similar to direct-xip, ram-load mode also supports a "revert" mechanism. +This mechanism works in the same manner as the direct-xip revert mechanism does, +so please see the [corresponding section](#direct-xip-ram-load-revert) for +more details. + ## [Boot swap types](#boot-swap-types) When the device first boots under normal circumstances, there is an up-to-date @@ -455,19 +460,22 @@ The "swap type" is a high-level representation of the outcome of the boot. Subsequent sections describe how MCUboot determines the swap type from the bit-level contents of flash. -### [Revert mechanism in direct-xip mode](#direct-xip-revert) - -The direct-xip mode also supports a "revert" mechanism which is the equivalent -of the swap mode's "revert" swap. When the direct-xip mode is selected it can be -enabled with the MCUBOOT_DIRECT_XIP_REVERT config option and an image trailer -must also be added to the signed images (the "--pad" option of the `imgtool` -script must be used). For more information on this please read the -[Image Trailer](#image-trailer) section and the [imgtool](imgtool.md) -documentation. Making the images permanent (marking them as confirmed in -advance) is also supported just like in swap mode. The individual steps of the -direct-xip mode's "revert" mechanism are the following: - -1. Select the slot which holds the newest potential image. +### [Revert mechanism in direct-xip and ram-load mode](#direct-xip-ram-load-revert) + +The direct-xip and ram-load modes also support a "revert" mechanism which is the +equivalent of the swap mode's "revert" swap. When the direct-xip mode is +selected it can be enabled with the `MCUBOOT_DIRECT_XIP_REVERT` config option. +In ram-load mode, the feature is enabled with `MCUBOOT_RAM_LOAD_REVERT` config +option. Note that an image trailer must also be added to the signed images (the +"--pad" option of the `imgtool` script must be used). Otherwise, MCUboot will +not recognize the image as valid and will attempt to revert it. For more +information on this please read the [Image Trailer](#image-trailer) section and +the [imgtool](imgtool.md) documentation. Making the images permanent (marking +them as confirmed in advance) is also supported just like in swap mode. The +individual steps of this "revert" mechanism are the following: + +1. Select the slot which holds the newest potential image, based on the + version number 2. Was the image previously selected to run (during a previous boot)? + Yes: Did the image mark itself "OK" (was the self-test successful)? + Yes. diff --git a/docs/index.md b/docs/index.md index a4744f393..4b36dc389 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,7 +1,7 @@ # MCUboot MCUboot is a secure bootloader for 32-bits microcontrollers. This document is -for release v2.2.0-rc2. +for release v2.2.0. Please see [Contributing](contributing.md) on how you can contribute to MCUboot. diff --git a/docs/readme-zephyr.md b/docs/readme-zephyr.md index 1d6daaef6..6b12b5b06 100644 --- a/docs/readme-zephyr.md +++ b/docs/readme-zephyr.md @@ -249,7 +249,6 @@ The mapping of image number to partition is as follows: Use the ``CONFIG_ENABLE_MGMT_PERUSER=y`` Kconfig option to enable the following additional commands: * Storage erase - This command allows erasing the storage partition (enable with ``CONFIG_BOOT_MGMT_CUSTOM_STORAGE_ERASE=y``). -* Custom image list - This command allows fetching version and installation status (custom properties) for all images (enable with ``CONFIG_BOOT_MGMT_CUSTOM_IMG_LIST=y``). ### More configuration diff --git a/docs/release-notes.d/add-cortex-r-support-00-basic.md b/docs/release-notes.d/add-cortex-r-support-00-basic.md new file mode 100644 index 000000000..a7005af5c --- /dev/null +++ b/docs/release-notes.d/add-cortex-r-support-00-basic.md @@ -0,0 +1 @@ +- Added support for booting Cortex-R5 images diff --git a/docs/release-notes.d/add-cortex-r-support-01-cleanup-core.md b/docs/release-notes.d/add-cortex-r-support-01-cleanup-core.md new file mode 100644 index 000000000..27b5039d0 --- /dev/null +++ b/docs/release-notes.d/add-cortex-r-support-01-cleanup-core.md @@ -0,0 +1 @@ +- Add support for cleaning up the Cortex-R core before final jumping diff --git a/docs/release-notes.d/align-security-policy.md b/docs/release-notes.d/align-security-policy.md new file mode 100644 index 000000000..46c0dac7f --- /dev/null +++ b/docs/release-notes.d/align-security-policy.md @@ -0,0 +1,2 @@ +- Aligned the project security policy with the [TrustedFirmware.org security +policy](https://www.trustedfirmware.org/.well-known/security.txt). diff --git a/docs/release-notes.d/click.md b/docs/release-notes.d/click.md new file mode 100644 index 000000000..820e94afa --- /dev/null +++ b/docs/release-notes.d/click.md @@ -0,0 +1 @@ + - Fixed imgtool dependency on click package version. diff --git a/docs/release-notes.d/enable-ram-load-revert.md b/docs/release-notes.d/enable-ram-load-revert.md new file mode 100644 index 000000000..117dd66c2 --- /dev/null +++ b/docs/release-notes.d/enable-ram-load-revert.md @@ -0,0 +1,2 @@ +- Enabled support for ram-load revert mode, which functions using the same + logic as direct-xip revert mode but loads the executable image to ram. diff --git a/docs/release-notes.d/fix-boot-scramble-region.md b/docs/release-notes.d/fix-boot-scramble-region.md new file mode 100644 index 000000000..55042de87 --- /dev/null +++ b/docs/release-notes.d/fix-boot-scramble-region.md @@ -0,0 +1,3 @@ + - Fixed issue in boot_scramble_regions, where incorrect boundary + check would cause function to attempt to write pass a designated + flash area. diff --git a/docs/release-notes.d/imgtool-compression-header-fix.md b/docs/release-notes.d/imgtool-compression-header-fix.md new file mode 100644 index 000000000..e9a7bda6b --- /dev/null +++ b/docs/release-notes.d/imgtool-compression-header-fix.md @@ -0,0 +1,2 @@ + - Fixed issue with imgtool when trying to compress images with + no header padding requested. diff --git a/docs/release-notes.d/picolibc.md b/docs/release-notes.d/picolibc.md new file mode 100644 index 000000000..5a54a7a8b --- /dev/null +++ b/docs/release-notes.d/picolibc.md @@ -0,0 +1 @@ + - Switched to picolibc as the default C library in Zephyr. diff --git a/docs/release-notes.d/single-slot-fixes.md b/docs/release-notes.d/single-slot-fixes.md new file mode 100644 index 000000000..92666b813 --- /dev/null +++ b/docs/release-notes.d/single-slot-fixes.md @@ -0,0 +1,5 @@ + - Fixed wrong define specifying 2 slots in single loader mode + instead of just 1 + - Fixed wrong slot ID in hook calls from serial recovery. + - Fixed issues with serial recovery not building/not + working/faulting. diff --git a/docs/release-notes.d/trailer-fixes.md b/docs/release-notes.d/trailer-fixes.md new file mode 100644 index 000000000..6c708e0f7 --- /dev/null +++ b/docs/release-notes.d/trailer-fixes.md @@ -0,0 +1,6 @@ + - Fixed issue with platforms that have + MCUBOOT_SUPPORT_DEV_WITHOUT_ERASE set that did not scramble + (delete) data sections from the trailer that should have been + deleted. + - Fixed issue with boot_scramble_region escaping flash area due + to error in the range check. diff --git a/docs/release-notes.d/zephyr-pinreset-trigger.md b/docs/release-notes.d/zephyr-pinreset-trigger.md new file mode 100644 index 000000000..af93f8b80 --- /dev/null +++ b/docs/release-notes.d/zephyr-pinreset-trigger.md @@ -0,0 +1,2 @@ +- Fixed issue with checking pin reset not checking for single + flag in Zephyr. diff --git a/docs/release-notes.md b/docs/release-notes.md index f63e80b2b..368ecd5fb 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -89,6 +89,8 @@ - Fixed issue with trailer and swap status sizes wrongly being included in single slot/firmware loaded modes which wrongly reduced the maximum allowable firmware sizes. +- Fixes for Zephyr 4.1 and MPU/SYSMPU renaming +- Fix support for MCX-N9XX with Zephyr. ## Version 2.1.0 diff --git a/ext/mbedtls b/ext/mbedtls index 8df2f8e7b..2ca6c285a 160000 --- a/ext/mbedtls +++ b/ext/mbedtls @@ -1 +1 @@ -Subproject commit 8df2f8e7b9c7bb9390ac74bb7bace27edca81a2b +Subproject commit 2ca6c285a0dd3f33982dd57299012dacab1ff206 diff --git a/repository.yml b/repository.yml index 61fd17bf8..587835320 100644 --- a/repository.yml +++ b/repository.yml @@ -41,7 +41,7 @@ repo.versions: "2.2.0": "v2.2.0" "0-dev": "0.0.0" # main - "0-latest": "2.1.0" # latest stable release + "0-latest": "2.2.0" # latest stable release "1-latest": "1.11.0" "2-latest": "2.2.0" diff --git a/scripts/imgtool/__init__.py b/scripts/imgtool/__init__.py index 24aec1bb3..83c1a2bbb 100644 --- a/scripts/imgtool/__init__.py +++ b/scripts/imgtool/__init__.py @@ -14,4 +14,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -imgtool_version = "2.2.0rc2" +imgtool_version = "2.2.0" diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py old mode 100644 new mode 100755 index b24e5de8d..7f485bcc8 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -185,6 +185,7 @@ def tlv_sha_to_sha(tlv): keys.ECDSA384P1 : ['384'], keys.ECDSA384P1Public : ['384'], keys.ECDSA256P1 : ['256'], + keys.ECDSA256P1Public : ['256'], keys.RSA : ['256'], keys.RSAPublic : ['256'], # This two are set to 256 for compatibility, the right would be 512 @@ -443,14 +444,23 @@ def ecies_hkdf(self, enckey, plainkey, hmac_sha_alg): else: newpk = X25519PrivateKey.generate() shared = newpk.exchange(enckey._get_public()) + + # Detect AES key length from plainkey size + key_len = len(plainkey) # 16 for AES-128, 32 for AES-256 + + # Generate derived key with appropriate length (key_len + 32 bytes for HMAC) derived_key = HKDF( - algorithm=hmac_sha_alg, length=16 + hmac_sha_alg.digest_size, salt=None, + algorithm=hmac_sha_alg, length=key_len + hmac_sha_alg.digest_size, salt=None, info=b'MCUBoot_ECIES_v1', backend=default_backend()).derive(shared) - encryptor = Cipher(algorithms.AES(derived_key[:16]), + + # Use appropriate key length for AES encryption + encryptor = Cipher(algorithms.AES(derived_key[:key_len]), modes.CTR(bytes([0] * 16)), backend=default_backend()).encryptor() cipherkey = encryptor.update(plainkey) + encryptor.finalize() - mac = hmac.HMAC(derived_key[16:], hmac_sha_alg, + + # Use remaining bytes for HMAC (after the AES key) + mac = hmac.HMAC(derived_key[key_len:], hmac_sha_alg, backend=default_backend()) mac.update(cipherkey) ciphermac = mac.finalize() diff --git a/scripts/tests/test_commands.py b/scripts/tests/test_commands.py index 458e4e2c9..c0c605213 100644 --- a/scripts/tests/test_commands.py +++ b/scripts/tests/test_commands.py @@ -12,11 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. +from importlib import metadata + import pytest from click.testing import CliRunner from imgtool.main import imgtool from imgtool import imgtool_version +from packaging.version import Version # all available imgtool commands COMMANDS = [ @@ -53,7 +56,10 @@ def test_help(): # by default help should be also produced result_empty = runner.invoke(imgtool) - assert result_empty.exit_code == 0 + + # return value without arguments differs based on click version + expected_exit_code = 2 if Version(metadata.version("click")) >= Version("8.2.0") else 0 + assert result_empty.exit_code == expected_exit_code assert result_empty.output == result_short.output diff --git a/sim/mcuboot-sys/build.rs b/sim/mcuboot-sys/build.rs index e74a086d0..12726f928 100644 --- a/sim/mcuboot-sys/build.rs +++ b/sim/mcuboot-sys/build.rs @@ -109,6 +109,7 @@ fn main() { conf.file("../../ext/mbedtls/library/chachapoly.c"); conf.file("../../ext/mbedtls/library/cipher.c"); conf.file("../../ext/mbedtls/library/cipher_wrap.c"); + conf.file("../../ext/mbedtls/library/constant_time.c"); conf.file("../../ext/mbedtls/library/ctr_drbg.c"); conf.file("../../ext/mbedtls/library/des.c"); conf.file("../../ext/mbedtls/library/ecdsa.c"); @@ -131,7 +132,6 @@ fn main() { conf.file("../../ext/mbedtls/library/psa_crypto.c"); conf.file("../../ext/mbedtls/library/psa_crypto_cipher.c"); conf.file("../../ext/mbedtls/library/psa_crypto_client.c"); - conf.file("../../ext/mbedtls/library/psa_crypto_driver_wrappers.c"); conf.file("../../ext/mbedtls/library/psa_crypto_ecp.c"); conf.file("../../ext/mbedtls/library/psa_crypto_hash.c"); conf.file("../../ext/mbedtls/library/psa_crypto_mac.c"); @@ -139,6 +139,7 @@ fn main() { conf.file("../../ext/mbedtls/library/psa_crypto_slot_management.c"); conf.file("../../ext/mbedtls/library/psa_crypto_storage.c"); conf.file("../../ext/mbedtls/library/psa_its_file.c"); + conf.file("../../ext/mbedtls/library/psa_util.c"); conf.file("../../ext/mbedtls/library/ripemd160.c"); conf.file("../../ext/mbedtls/library/rsa_alt_helpers.c"); conf.file("../../ext/mbedtls/library/sha1.c"); @@ -170,6 +171,9 @@ fn main() { conf.file("../../ext/mbedtls/library/rsa.c"); conf.file("../../ext/mbedtls/library/bignum.c"); + conf.file("../../ext/mbedtls/library/bignum_core.c"); + conf.file("../../ext/mbedtls/library/constant_time.c"); + conf.file("../../ext/mbedtls/library/nist_kw.c"); conf.file("../../ext/mbedtls/library/platform.c"); conf.file("../../ext/mbedtls/library/platform_util.c"); conf.file("../../ext/mbedtls/library/asn1parse.c"); @@ -203,6 +207,9 @@ fn main() { conf.file("../../ext/mbedtls/library/asn1parse.c"); conf.file("../../ext/mbedtls/library/bignum.c"); + conf.file("../../ext/mbedtls/library/bignum_core.c"); + conf.file("../../ext/mbedtls/library/constant_time.c"); + conf.file("../../ext/mbedtls/library/nist_kw.c"); conf.file("../../ext/mbedtls/library/ecdsa.c"); conf.file("../../ext/mbedtls/library/ecp.c"); conf.file("../../ext/mbedtls/library/ecp_curves.c"); @@ -222,6 +229,9 @@ fn main() { conf.file("csupport/keys.c"); conf.file("../../ext/mbedtls/library/asn1parse.c"); conf.file("../../ext/mbedtls/library/bignum.c"); + conf.file("../../ext/mbedtls/library/bignum_core.c"); + conf.file("../../ext/mbedtls/library/constant_time.c"); + conf.file("../../ext/mbedtls/library/nist_kw.c"); conf.file("../../ext/mbedtls/library/ecp.c"); conf.file("../../ext/mbedtls/library/ecp_curves.c"); conf.file("../../ext/mbedtls/library/platform.c"); @@ -285,6 +295,9 @@ fn main() { conf.file("../../ext/mbedtls/library/md.c"); conf.file("../../ext/mbedtls/library/aes.c"); conf.file("../../ext/mbedtls/library/bignum.c"); + conf.file("../../ext/mbedtls/library/bignum_core.c"); + conf.file("../../ext/mbedtls/library/constant_time.c"); + conf.file("../../ext/mbedtls/library/nist_kw.c"); conf.file("../../ext/mbedtls/library/asn1parse.c"); } @@ -308,6 +321,7 @@ fn main() { conf.conf.include("../../ext/mbedtls/library"); conf.file("../../ext/mbedtls/library/platform_util.c"); conf.file("../../ext/mbedtls/library/nist_kw.c"); + conf.file("../../ext/mbedtls/library/constant_time.c"); conf.file("../../ext/mbedtls/library/cipher.c"); conf.file("../../ext/mbedtls/library/cipher_wrap.c"); conf.file("../../ext/mbedtls/library/aes.c"); @@ -372,6 +386,9 @@ fn main() { conf.file("../../ext/mbedtls/library/sha256.c"); conf.file("../../ext/mbedtls/library/asn1parse.c"); conf.file("../../ext/mbedtls/library/bignum.c"); + conf.file("../../ext/mbedtls/library/bignum_core.c"); + conf.file("../../ext/mbedtls/library/constant_time.c"); + conf.file("../../ext/mbedtls/library/nist_kw.c"); conf.file("../../ext/mbedtls/library/ecdh.c"); conf.file("../../ext/mbedtls/library/md.c"); conf.file("../../ext/mbedtls/library/aes.c"); diff --git a/sim/mcuboot-sys/csupport/config-ec-psa.h b/sim/mcuboot-sys/csupport/config-ec-psa.h index 5dbb4956e..309739838 100644 --- a/sim/mcuboot-sys/csupport/config-ec-psa.h +++ b/sim/mcuboot-sys/csupport/config-ec-psa.h @@ -22,6 +22,7 @@ #define MBEDTLS_BIGNUM_C #define MBEDTLS_MD_C #define MBEDTLS_OID_C +#define MBEDTLS_CIPHER_C #if defined(MCUBOOT_SIGN_EC384) #define MBEDTLS_SHA384_C #define MBEDTLS_SHA512_C diff --git a/sim/mcuboot-sys/csupport/config-rsa-kw.h b/sim/mcuboot-sys/csupport/config-rsa-kw.h index e06debf47..43f47b4c4 100644 --- a/sim/mcuboot-sys/csupport/config-rsa-kw.h +++ b/sim/mcuboot-sys/csupport/config-rsa-kw.h @@ -63,6 +63,7 @@ /* mbed TLS modules */ #define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C #define MBEDTLS_BIGNUM_C #define MBEDTLS_MD_C #define MBEDTLS_OID_C @@ -72,10 +73,6 @@ #define MBEDTLS_CIPHER_C #define MBEDTLS_NIST_KW_C -/* Save RAM by adjusting to our exact needs */ -#define MBEDTLS_ECP_MAX_BITS 2048 -#define MBEDTLS_MPI_MAX_SIZE 256 - #define MBEDTLS_SSL_MAX_CONTENT_LEN 1024 /* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */ diff --git a/sim/mcuboot-sys/csupport/run.c b/sim/mcuboot-sys/csupport/run.c index 24e50adc1..2bf09e65a 100644 --- a/sim/mcuboot-sys/csupport/run.c +++ b/sim/mcuboot-sys/csupport/run.c @@ -289,6 +289,63 @@ int invoke_boot_go(struct sim_context *ctx, struct area_desc *adesc, } } +int invoke_boot_load_image_from_flash_to_sram(struct sim_context *ctx, struct area_desc *adesc) +{ +#ifdef MCUBOOT_RAM_LOAD + int res; + struct boot_loader_state *state; + const struct flash_area *fa_p; + struct image_header hdr; + +#if defined(MCUBOOT_SIGN_RSA) || \ + (defined(MCUBOOT_SIGN_EC256) && defined(MCUBOOT_USE_MBED_TLS)) ||\ + (defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS)) ||\ + (defined(MCUBOOT_ENCRYPT_X25519) && defined(MCUBOOT_USE_MBED_TLS)) + mbedtls_platform_set_calloc_free(calloc, free); +#endif + + state = malloc(sizeof(struct boot_loader_state)); + + sim_set_flash_areas(adesc); + sim_set_context(ctx); + boot_state_clear(state); + + res = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(0), &fa_p); + if (res != 0) { + printf("Failed to open primary image area: %d\n", res); + sim_reset_flash_areas(); + sim_reset_context(); + free(state); + return res; + } + + res = boot_image_load_header(fa_p, &hdr); + if (res != 0) { + printf("Failed to load image header: %d\n", res); + flash_area_close(fa_p); + sim_reset_flash_areas(); + sim_reset_context(); + free(state); + return res; + } + + res = boot_load_image_from_flash_to_sram(state, &hdr, fa_p); + if (res != 0) { + printf("Failed to load image from flash to SRAM: %d\n", res); + } + + flash_area_close(fa_p); + sim_reset_flash_areas(); + sim_reset_context(); + free(state); + return res; +#else + (void)ctx; + (void)adesc; + return 0; +#endif /* MCUBOOT_RAM_LOAD */ +} + void *os_malloc(size_t size) { // printf("os_malloc 0x%x bytes\n", size); diff --git a/sim/mcuboot-sys/src/c.rs b/sim/mcuboot-sys/src/c.rs index 2643866ae..015d91c04 100644 --- a/sim/mcuboot-sys/src/c.rs +++ b/sim/mcuboot-sys/src/c.rs @@ -115,6 +115,28 @@ pub fn boot_go(multiflash: &mut SimMultiFlash, areadesc: &AreaDesc, } } +pub fn boot_load_image_from_flash_to_sram(multiflash: &mut SimMultiFlash, areadesc: &AreaDesc) -> bool { + init_crypto(); + + for (&dev_id, flash) in multiflash.iter_mut() { + api::set_flash(dev_id, flash); + } + let mut sim_ctx = api::CSimContext { + flash_counter: 0, + c_catch_asserts: 0, + .. Default::default() + }; + let result: i32 = unsafe { + let adesc = areadesc.get_c(); + raw::invoke_boot_load_image_from_flash_to_sram(&mut sim_ctx as *mut _, + adesc.borrow() as *const _) as i32 + }; + for &dev_id in multiflash.keys() { + api::clear_flash(dev_id); + } + result == 0 +} + pub fn boot_trailer_sz(align: u32) -> u32 { unsafe { raw::boot_trailer_sz(align) } } @@ -181,6 +203,9 @@ mod raw { pub fn invoke_boot_go(sim_ctx: *mut CSimContext, areadesc: *const CAreaDesc, rsp: *mut BootRsp, image_index: libc::c_int) -> libc::c_int; + pub fn invoke_boot_load_image_from_flash_to_sram(sim_ctx: *mut CSimContext, + areadesc: *const CAreaDesc) -> libc::c_int; + pub fn boot_trailer_sz(min_write_sz: u32) -> u32; pub fn boot_status_sz(min_write_sz: u32) -> u32; diff --git a/sim/src/image.rs b/sim/src/image.rs index 14e59d622..9703714b3 100644 --- a/sim/src/image.rs +++ b/sim/src/image.rs @@ -1413,6 +1413,40 @@ impl Images { false } + pub fn run_ram_load_from_flash(&self) -> bool { + if !Caps::RamLoad.present() { + return false; + } + + // Clone the flash so we can tell if unchanged. + let mut flash = self.flash.clone(); + + // Create RAM config. + let ram = RamBlock::new(self.ram.total - RAM_LOAD_ADDR, RAM_LOAD_ADDR); + + // Run boot_load_image_from_flash_to_sram directly + let result = ram.invoke(|| c::boot_load_image_from_flash_to_sram(&mut flash, &self.areadesc)); + + if !result { + error!("RAM load from flash failed!"); + return true; + } + + // Compare loaded image with the first image in the flash. + let image = &self.images[0].primaries; + let ram_image = ram.borrow(); + let src_sz = image.plain.len(); + let src_image = &image.plain[0..src_sz]; + let ram_image = &ram_image[0..src_sz]; + + if ram_image != src_image { + error!("Image not loaded correctly"); + return true; + } + + false + } + /// Adds a new flash area that fails statistically fn mark_bad_status_with_rate(&self, flash: &mut SimMultiFlash, slot: usize, rate: f32) { diff --git a/sim/tests/core.rs b/sim/tests/core.rs index 0e7687ad7..69745ab26 100644 --- a/sim/tests/core.rs +++ b/sim/tests/core.rs @@ -68,6 +68,7 @@ sim_test!(downgrade_prevention, make_image(&REV_DEPS, true), run_nodowngrade()); sim_test!(direct_xip_first, make_no_upgrade_image(&NO_DEPS, ImageManipulation::None), run_direct_xip()); sim_test!(ram_load_first, make_no_upgrade_image(&NO_DEPS, ImageManipulation::None), run_ram_load()); sim_test!(ram_load_split, make_no_upgrade_image(&NO_DEPS, ImageManipulation::None), run_split_ram_load()); +sim_test!(ram_load_from_flash, make_no_upgrade_image(&NO_DEPS, ImageManipulation::None), run_ram_load_from_flash()); sim_test!(hw_prot_failed_security_cnt_check, make_image_with_security_counter(Some(0)), run_hw_rollback_prot()); sim_test!(hw_prot_missing_security_cnt, make_image_with_security_counter(None), run_hw_rollback_prot()); sim_test!(ram_load_out_of_bounds, make_no_upgrade_image(&NO_DEPS, ImageManipulation::WrongOffset), run_ram_load_boot_with_result(false)); diff --git a/zephyr/module.yml b/zephyr/module.yml index b73ae2a0d..65af58bb5 100644 --- a/zephyr/module.yml +++ b/zephyr/module.yml @@ -8,3 +8,5 @@ package-managers: pip: requirement-files: - zephyr/requirements.txt +samples: + - boot/zephyr diff --git a/zephyr/requirements.txt b/zephyr/requirements.txt index 0eaed4d84..822a1665d 100644 --- a/zephyr/requirements.txt +++ b/zephyr/requirements.txt @@ -1,2 +1,2 @@ cbor>=1.0.0 -imgtool>=2.1.0 +imgtool>=2.2.0