1 /*
2  * SPDX-License-Identifier: Apache-2.0
3  *
4  * Copyright (c) 2016-2020 Linaro LTD
5  * Copyright (c) 2016-2019 JUUL Labs
6  * Copyright (c) 2019-2023 Arm Limited
7  * Copyright (c) 2024 Nordic Semiconductor ASA
8  *
9  * Original license:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one
12  * or more contributor license agreements.  See the NOTICE file
13  * distributed with this work for additional information
14  * regarding copyright ownership.  The ASF licenses this file
15  * to you under the Apache License, Version 2.0 (the
16  * "License"); you may not use this file except in compliance
17  * with the License.  You may obtain a copy of the License at
18  *
19  *  http://www.apache.org/licenses/LICENSE-2.0
20  *
21  * Unless required by applicable law or agreed to in writing,
22  * software distributed under the License is distributed on an
23  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
24  * KIND, either express or implied.  See the License for the
25  * specific language governing permissions and limitations
26  * under the License.
27  */
28 
29 /**
30  * This file provides an interface to the boot loader.  Functions defined in
31  * this file should only be called while the boot loader is running.
32  */
33 
34 #include <stddef.h>
35 #include <stdbool.h>
36 #include <inttypes.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include "bootutil/bootutil.h"
40 #include "bootutil/bootutil_public.h"
41 #include "bootutil/image.h"
42 #include "bootutil_priv.h"
43 #include "swap_priv.h"
44 #include "bootutil/bootutil_log.h"
45 #include "bootutil/security_cnt.h"
46 #include "bootutil/boot_record.h"
47 #include "bootutil/fault_injection_hardening.h"
48 #include "bootutil/ramload.h"
49 #include "bootutil/boot_hooks.h"
50 #include "bootutil/mcuboot_status.h"
51 
52 #ifdef MCUBOOT_ENC_IMAGES
53 #include "bootutil/enc_key.h"
54 #endif
55 
56 #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
57 #include <os/os_malloc.h>
58 #endif
59 
60 #include "mcuboot_config/mcuboot_config.h"
61 
62 BOOT_LOG_MODULE_DECLARE(mcuboot);
63 
64 static struct boot_loader_state boot_data;
65 
66 #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING)
67 static struct image_max_size image_max_sizes[BOOT_IMAGE_NUMBER] = {0};
68 #endif
69 
70 #if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \
71 defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO)
72 #if !defined(__BOOTSIM__)
73 /* Used for holding static buffers in multiple functions to work around issues
74  * in older versions of gcc (e.g. 4.8.4)
75  */
76 struct sector_buffer_t {
77     boot_sector_t primary[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS];
78     boot_sector_t secondary[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS];
79 #if MCUBOOT_SWAP_USING_SCRATCH
80     boot_sector_t scratch[BOOT_MAX_IMG_SECTORS];
81 #endif
82 };
83 
84 static struct sector_buffer_t sector_buffers;
85 #endif
86 #endif
87 
88 #if (BOOT_IMAGE_NUMBER > 1)
89 #define IMAGES_ITER(x) for ((x) = 0; (x) < BOOT_IMAGE_NUMBER; ++(x))
90 #else
91 #define IMAGES_ITER(x)
92 #endif
93 
94 /*
95  * This macro allows some control on the allocation of local variables.
96  * When running natively on a target, we don't want to allocated huge
97  * variables on the stack, so make them global instead. For the simulator
98  * we want to run as many threads as there are tests, and it's safer
99  * to just make those variables stack allocated.
100  */
101 #if !defined(__BOOTSIM__)
102 #define TARGET_STATIC static
103 #else
104 #define TARGET_STATIC
105 #endif
106 
107 #if BOOT_MAX_ALIGN > 1024
108 #define BUF_SZ BOOT_MAX_ALIGN
109 #else
110 #define BUF_SZ 1024
111 #endif
112 
113 #define NO_ACTIVE_SLOT UINT32_MAX
114 
115 static int
boot_read_image_headers(struct boot_loader_state * state,bool require_all,struct boot_status * bs)116 boot_read_image_headers(struct boot_loader_state *state, bool require_all,
117         struct boot_status *bs)
118 {
119     int rc;
120     int i;
121 
122     for (i = 0; i < BOOT_NUM_SLOTS; i++) {
123         rc = BOOT_HOOK_CALL(boot_read_image_header_hook, BOOT_HOOK_REGULAR,
124                             BOOT_CURR_IMG(state), i, boot_img_hdr(state, i));
125         if (rc == BOOT_HOOK_REGULAR)
126         {
127             rc = boot_read_image_header(state, i, boot_img_hdr(state, i), bs);
128         }
129         if (rc != 0) {
130             /* If `require_all` is set, fail on any single fail, otherwise
131              * if at least the first slot's header was read successfully,
132              * then the boot loader can attempt a boot.
133              *
134              * Failure to read any headers is a fatal error.
135              */
136             if (i > 0 && !require_all) {
137                 return 0;
138             } else {
139                 return rc;
140             }
141         }
142     }
143 
144     return 0;
145 }
146 
147 /**
148  * Saves boot status and shared data for current image.
149  *
150  * @param  state        Boot loader status information.
151  * @param  active_slot  Index of the slot will be loaded for current image.
152  *
153  * @return              0 on success; nonzero on failure.
154  */
155 static int
boot_add_shared_data(struct boot_loader_state * state,uint8_t active_slot)156 boot_add_shared_data(struct boot_loader_state *state,
157                      uint8_t active_slot)
158 {
159 #if defined(MCUBOOT_MEASURED_BOOT) || defined(MCUBOOT_DATA_SHARING)
160     int rc;
161 
162 #ifdef MCUBOOT_MEASURED_BOOT
163     rc = boot_save_boot_status(BOOT_CURR_IMG(state),
164                                 boot_img_hdr(state, active_slot),
165                                 BOOT_IMG_AREA(state, active_slot));
166     if (rc != 0) {
167         BOOT_LOG_ERR("Failed to add image data to shared area");
168         return rc;
169     }
170 #endif /* MCUBOOT_MEASURED_BOOT */
171 
172 #ifdef MCUBOOT_DATA_SHARING
173     rc = boot_save_shared_data(boot_img_hdr(state, active_slot),
174                                 BOOT_IMG_AREA(state, active_slot),
175                                 active_slot, image_max_sizes);
176     if (rc != 0) {
177         BOOT_LOG_ERR("Failed to add data to shared memory area.");
178         return rc;
179     }
180 #endif /* MCUBOOT_DATA_SHARING */
181 
182     return 0;
183 
184 #else /* MCUBOOT_MEASURED_BOOT || MCUBOOT_DATA_SHARING */
185     (void) (state);
186     (void) (active_slot);
187 
188     return 0;
189 #endif
190 }
191 
192 /**
193  * Fills rsp to indicate how booting should occur.
194  *
195  * @param  state        Boot loader status information.
196  * @param  rsp          boot_rsp struct to fill.
197  */
198 static void
fill_rsp(struct boot_loader_state * state,struct boot_rsp * rsp)199 fill_rsp(struct boot_loader_state *state, struct boot_rsp *rsp)
200 {
201     uint32_t active_slot;
202 
203 #if (BOOT_IMAGE_NUMBER > 1)
204     /* Always boot from the first enabled image. */
205     BOOT_CURR_IMG(state) = 0;
206     IMAGES_ITER(BOOT_CURR_IMG(state)) {
207         if (!state->img_mask[BOOT_CURR_IMG(state)]) {
208             break;
209         }
210     }
211     /* At least one image must be active, otherwise skip the execution */
212     if (BOOT_CURR_IMG(state) >= BOOT_IMAGE_NUMBER) {
213         return;
214     }
215 #endif
216 
217 #if defined(MCUBOOT_DIRECT_XIP) || defined(MCUBOOT_RAM_LOAD)
218     active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
219 #else
220     active_slot = BOOT_PRIMARY_SLOT;
221 #endif
222 
223     rsp->br_flash_dev_id = flash_area_get_device_id(BOOT_IMG_AREA(state, active_slot));
224     rsp->br_image_off = boot_img_slot_off(state, active_slot);
225     rsp->br_hdr = boot_img_hdr(state, active_slot);
226 }
227 
228 /**
229  * Closes all flash areas.
230  *
231  * @param  state    Boot loader status information.
232  */
233 static void
close_all_flash_areas(struct boot_loader_state * state)234 close_all_flash_areas(struct boot_loader_state *state)
235 {
236     uint32_t slot;
237 
238     IMAGES_ITER(BOOT_CURR_IMG(state)) {
239 #if BOOT_IMAGE_NUMBER > 1
240         if (state->img_mask[BOOT_CURR_IMG(state)]) {
241             continue;
242         }
243 #endif
244 #if MCUBOOT_SWAP_USING_SCRATCH
245         flash_area_close(BOOT_SCRATCH_AREA(state));
246 #endif
247         for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
248             flash_area_close(BOOT_IMG_AREA(state, BOOT_NUM_SLOTS - 1 - slot));
249         }
250     }
251 }
252 
253 #if (BOOT_IMAGE_NUMBER > 1) || \
254     defined(MCUBOOT_DIRECT_XIP) || \
255     defined(MCUBOOT_RAM_LOAD) || \
256     defined(MCUBOOT_DOWNGRADE_PREVENTION)
257 /**
258  * Compare image version numbers
259  *
260  * By default, the comparison does not take build number into account.
261  * Enable MCUBOOT_VERSION_CMP_USE_BUILD_NUMBER to take the build number into account.
262  *
263  * @param ver1           Pointer to the first image version to compare.
264  * @param ver2           Pointer to the second image version to compare.
265  *
266  * @retval -1           If ver1 is less than ver2.
267  * @retval 0            If the image version numbers are equal.
268  * @retval 1            If ver1 is greater than ver2.
269  */
270 static int
boot_version_cmp(const struct image_version * ver1,const struct image_version * ver2)271 boot_version_cmp(const struct image_version *ver1,
272                  const struct image_version *ver2)
273 {
274     if (ver1->iv_major > ver2->iv_major) {
275         return 1;
276     }
277     if (ver1->iv_major < ver2->iv_major) {
278         return -1;
279     }
280     /* The major version numbers are equal, continue comparison. */
281     if (ver1->iv_minor > ver2->iv_minor) {
282         return 1;
283     }
284     if (ver1->iv_minor < ver2->iv_minor) {
285         return -1;
286     }
287     /* The minor version numbers are equal, continue comparison. */
288     if (ver1->iv_revision > ver2->iv_revision) {
289         return 1;
290     }
291     if (ver1->iv_revision < ver2->iv_revision) {
292         return -1;
293     }
294 
295 #if defined(MCUBOOT_VERSION_CMP_USE_BUILD_NUMBER)
296     /* The revisions are equal, continue comparison. */
297     if (ver1->iv_build_num > ver2->iv_build_num) {
298         return 1;
299     }
300     if (ver1->iv_build_num < ver2->iv_build_num) {
301         return -1;
302     }
303 #endif
304 
305     return 0;
306 }
307 #endif
308 
309 #if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \
310 defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO)
311 static int
boot_initialize_area(struct boot_loader_state * state,int flash_area)312 boot_initialize_area(struct boot_loader_state *state, int flash_area)
313 {
314     uint32_t num_sectors = BOOT_MAX_IMG_SECTORS;
315     boot_sector_t *out_sectors;
316     uint32_t *out_num_sectors;
317     int rc;
318 
319     num_sectors = BOOT_MAX_IMG_SECTORS;
320 
321     if (flash_area == FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state))) {
322         out_sectors = BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors;
323         out_num_sectors = &BOOT_IMG(state, BOOT_PRIMARY_SLOT).num_sectors;
324     } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) {
325         out_sectors = BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors;
326         out_num_sectors = &BOOT_IMG(state, BOOT_SECONDARY_SLOT).num_sectors;
327 #if MCUBOOT_SWAP_USING_SCRATCH
328     } else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) {
329         out_sectors = state->scratch.sectors;
330         out_num_sectors = &state->scratch.num_sectors;
331 #endif
332     } else {
333         return BOOT_EFLASH;
334     }
335 
336 #ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
337     rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors);
338 #else
339     _Static_assert(sizeof(int) <= sizeof(uint32_t), "Fix needed");
340     rc = flash_area_to_sectors(flash_area, (int *)&num_sectors, out_sectors);
341 #endif /* defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */
342     if (rc != 0) {
343         return rc;
344     }
345     *out_num_sectors = num_sectors;
346     return 0;
347 }
348 #endif
349 
350 #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO)
351 static int
boot_read_sectors_recovery(struct boot_loader_state * state)352 boot_read_sectors_recovery(struct boot_loader_state *state)
353 {
354     uint8_t image_index;
355     int rc;
356 
357     image_index = BOOT_CURR_IMG(state);
358 
359     rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index));
360     if (rc != 0) {
361         return BOOT_EFLASH;
362     }
363 
364     rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SECONDARY(image_index));
365     if (rc != 0) {
366         /* We need to differentiate from the primary image issue */
367         return BOOT_EFLASH_SEC;
368     }
369 
370     return 0;
371 }
372 #endif
373 
374 
375 #if (BOOT_IMAGE_NUMBER > 1)
376 
377 static int
378 boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot);
379 
380 /**
381  * Check the image dependency whether it is satisfied and modify
382  * the swap type if necessary.
383  *
384  * @param dep               Image dependency which has to be verified.
385  *
386  * @return                  0 on success; nonzero on failure.
387  */
388 static int
boot_verify_slot_dependency(struct boot_loader_state * state,struct image_dependency * dep)389 boot_verify_slot_dependency(struct boot_loader_state *state,
390                             struct image_dependency *dep)
391 {
392     struct image_version *dep_version;
393     size_t dep_slot;
394     int rc;
395 
396     /* Determine the source of the image which is the subject of
397      * the dependency and get it's version. */
398 #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
399     uint8_t swap_type = state->swap_type[dep->image_id];
400     dep_slot = BOOT_IS_UPGRADE(swap_type) ? BOOT_SECONDARY_SLOT
401                                           : BOOT_PRIMARY_SLOT;
402 #else
403     dep_slot = state->slot_usage[dep->image_id].active_slot;
404 #endif
405 
406     dep_version = &state->imgs[dep->image_id][dep_slot].hdr.ih_ver;
407 
408     rc = boot_version_cmp(dep_version, &dep->image_min_version);
409 #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
410     if (rc < 0) {
411         /* Dependency not satisfied.
412          * Modify the swap type to decrease the version number of the image
413          * (which will be located in the primary slot after the boot process),
414          * consequently the number of unsatisfied dependencies will be
415          * decreased or remain the same.
416          */
417         switch (BOOT_SWAP_TYPE(state)) {
418         case BOOT_SWAP_TYPE_TEST:
419         case BOOT_SWAP_TYPE_PERM:
420             BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
421             break;
422         case BOOT_SWAP_TYPE_NONE:
423             BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_REVERT;
424             break;
425         default:
426             break;
427         }
428     } else {
429         /* Dependency satisfied. */
430         rc = 0;
431     }
432 #else
433   if (rc >= 0) {
434         /* Dependency satisfied. */
435         rc = 0;
436     }
437 #endif
438 
439     return rc;
440 }
441 
442 #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
443 /**
444  * Iterate over all the images and verify whether the image dependencies in the
445  * TLV area are all satisfied and update the related swap type if necessary.
446  */
447 static int
boot_verify_dependencies(struct boot_loader_state * state)448 boot_verify_dependencies(struct boot_loader_state *state)
449 {
450     int rc = -1;
451     uint8_t slot;
452 
453     BOOT_CURR_IMG(state) = 0;
454     while (BOOT_CURR_IMG(state) < BOOT_IMAGE_NUMBER) {
455         if (state->img_mask[BOOT_CURR_IMG(state)]) {
456             BOOT_CURR_IMG(state)++;
457             continue;
458         }
459         if (BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_NONE &&
460             BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_FAIL) {
461             slot = BOOT_SECONDARY_SLOT;
462         } else {
463             slot = BOOT_PRIMARY_SLOT;
464         }
465 
466         rc = boot_verify_slot_dependencies(state, slot);
467         if (rc == 0) {
468             /* All dependencies've been satisfied, continue with next image. */
469             BOOT_CURR_IMG(state)++;
470         } else {
471             /* Cannot upgrade due to non-met dependencies, so disable all
472              * image upgrades.
473              */
474             for (int idx = 0; idx < BOOT_IMAGE_NUMBER; idx++) {
475                 BOOT_CURR_IMG(state) = idx;
476                 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
477             }
478             break;
479         }
480     }
481     return rc;
482 }
483 #else
484 
485 #if defined MCUBOOT_RAM_LOAD
486 static inline int
487 boot_remove_image_from_sram(struct boot_loader_state *state);
488 #endif
489 
490 /**
491  * Checks the dependency of all the active slots. If an image found with
492  * invalid or not satisfied dependencies the image is removed from SRAM (in
493  * case of MCUBOOT_RAM_LOAD strategy) and its slot is set to unavailable.
494  *
495  * @param  state        Boot loader status information.
496  *
497  * @return              0 if dependencies are met; nonzero otherwise.
498  */
499 static int
boot_verify_dependencies(struct boot_loader_state * state)500 boot_verify_dependencies(struct boot_loader_state *state)
501 {
502     int rc = -1;
503     uint32_t active_slot;
504 
505     IMAGES_ITER(BOOT_CURR_IMG(state)) {
506         if (state->img_mask[BOOT_CURR_IMG(state)]) {
507             continue;
508         }
509         active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
510         rc = boot_verify_slot_dependencies(state, active_slot);
511         if (rc != 0) {
512             /* Dependencies not met or invalid dependencies. */
513 
514 #ifdef MCUBOOT_RAM_LOAD
515             boot_remove_image_from_sram(state);
516 #endif /* MCUBOOT_RAM_LOAD */
517 
518             state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
519             state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
520 
521             return rc;
522         }
523     }
524 
525     return rc;
526 }
527 #endif
528 
529 /**
530  * Read all dependency TLVs of an image from the flash and verify
531  * one after another to see if they are all satisfied.
532  *
533  * @param slot              Image slot number.
534  *
535  * @return                  0 on success; nonzero on failure.
536  */
537 static int
boot_verify_slot_dependencies(struct boot_loader_state * state,uint32_t slot)538 boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot)
539 {
540     const struct flash_area *fap;
541     struct image_tlv_iter it;
542     struct image_dependency dep;
543     uint32_t off;
544     uint16_t len;
545     int area_id;
546     int rc;
547 
548     area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
549     rc = flash_area_open(area_id, &fap);
550     if (rc != 0) {
551         rc = BOOT_EFLASH;
552         goto done;
553     }
554 
555     rc = bootutil_tlv_iter_begin(&it, boot_img_hdr(state, slot), fap,
556             IMAGE_TLV_DEPENDENCY, true);
557     if (rc != 0) {
558         goto done;
559     }
560 
561     while (true) {
562         rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
563         if (rc < 0) {
564             return -1;
565         } else if (rc > 0) {
566             rc = 0;
567             break;
568         }
569 
570         if (len != sizeof(dep)) {
571             rc = BOOT_EBADIMAGE;
572             goto done;
573         }
574 
575         rc = LOAD_IMAGE_DATA(boot_img_hdr(state, slot),
576                              fap, off, &dep, len);
577         if (rc != 0) {
578             rc = BOOT_EFLASH;
579             goto done;
580         }
581 
582         if (dep.image_id >= BOOT_IMAGE_NUMBER) {
583             rc = BOOT_EBADARGS;
584             goto done;
585         }
586 
587         /* Verify dependency and modify the swap type if not satisfied. */
588         rc = boot_verify_slot_dependency(state, &dep);
589         if (rc != 0) {
590             /* Dependency not satisfied */
591             goto done;
592         }
593     }
594 
595 done:
596     flash_area_close(fap);
597     return rc;
598 }
599 
600 #endif /* (BOOT_IMAGE_NUMBER > 1) */
601 
602 #if !defined(MCUBOOT_DIRECT_XIP)
603 /*
604  * Compute the total size of the given image.  Includes the size of
605  * the TLVs.
606  */
607 #if !defined(MCUBOOT_OVERWRITE_ONLY) ||  defined(MCUBOOT_OVERWRITE_ONLY_FAST)
608 static int
boot_read_image_size(struct boot_loader_state * state,int slot,uint32_t * size)609 boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size)
610 {
611     const struct flash_area *fap;
612     struct image_tlv_info info;
613     uint32_t off;
614     uint32_t protect_tlv_size;
615     int area_id;
616     int rc;
617 
618 #if (BOOT_IMAGE_NUMBER == 1)
619     (void)state;
620 #endif
621 
622     area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
623     rc = flash_area_open(area_id, &fap);
624     if (rc != 0) {
625         rc = BOOT_EFLASH;
626         goto done;
627     }
628 
629     off = BOOT_TLV_OFF(boot_img_hdr(state, slot));
630 
631     if (flash_area_read(fap, off, &info, sizeof(info))) {
632         rc = BOOT_EFLASH;
633         goto done;
634     }
635 
636     protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size;
637     if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) {
638         if (protect_tlv_size != info.it_tlv_tot) {
639             rc = BOOT_EBADIMAGE;
640             goto done;
641         }
642 
643         if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) {
644             rc = BOOT_EFLASH;
645             goto done;
646         }
647     } else if (protect_tlv_size != 0) {
648         rc = BOOT_EBADIMAGE;
649         goto done;
650     }
651 
652     if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
653         rc = BOOT_EBADIMAGE;
654         goto done;
655     }
656 
657     *size = off + protect_tlv_size + info.it_tlv_tot;
658     rc = 0;
659 
660 done:
661     flash_area_close(fap);
662     return rc;
663 }
664 #endif /* !MCUBOOT_OVERWRITE_ONLY */
665 
666 #if !defined(MCUBOOT_RAM_LOAD)
667 static uint32_t
boot_write_sz(struct boot_loader_state * state)668 boot_write_sz(struct boot_loader_state *state)
669 {
670     uint32_t elem_sz;
671 #if MCUBOOT_SWAP_USING_SCRATCH
672     uint32_t align;
673 #endif
674 
675     /* Figure out what size to write update status update as.  The size depends
676      * on what the minimum write size is for scratch area, active image slot.
677      * We need to use the bigger of those 2 values.
678      */
679     elem_sz = flash_area_align(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT));
680 #if MCUBOOT_SWAP_USING_SCRATCH
681     align = flash_area_align(BOOT_SCRATCH_AREA(state));
682     if (align > elem_sz) {
683         elem_sz = align;
684     }
685 #endif
686 
687     return elem_sz;
688 }
689 
690 /**
691  * Determines the sector layout of both image slots and the scratch area.
692  * This information is necessary for calculating the number of bytes to erase
693  * and copy during an image swap.  The information collected during this
694  * function is used to populate the state.
695  */
696 static int
boot_read_sectors(struct boot_loader_state * state)697 boot_read_sectors(struct boot_loader_state *state)
698 {
699     uint8_t image_index;
700     int rc;
701 
702     image_index = BOOT_CURR_IMG(state);
703 
704     rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index));
705     if (rc != 0) {
706         return BOOT_EFLASH;
707     }
708 
709     rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SECONDARY(image_index));
710     if (rc != 0) {
711         /* We need to differentiate from the primary image issue */
712         return BOOT_EFLASH_SEC;
713     }
714 
715 #if MCUBOOT_SWAP_USING_SCRATCH
716     rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SCRATCH);
717     if (rc != 0) {
718         return BOOT_EFLASH;
719     }
720 #endif
721 
722     BOOT_WRITE_SZ(state) = boot_write_sz(state);
723 
724     return 0;
725 }
726 
727 void
boot_status_reset(struct boot_status * bs)728 boot_status_reset(struct boot_status *bs)
729 {
730 #ifdef MCUBOOT_ENC_IMAGES
731     memset(&bs->enckey, 0xff, BOOT_NUM_SLOTS * BOOT_ENC_KEY_ALIGN_SIZE);
732 #if MCUBOOT_SWAP_SAVE_ENCTLV
733     memset(&bs->enctlv, 0xff, BOOT_NUM_SLOTS * BOOT_ENC_TLV_ALIGN_SIZE);
734 #endif
735 #endif /* MCUBOOT_ENC_IMAGES */
736 
737     bs->use_scratch = 0;
738     bs->swap_size = 0;
739     bs->source = 0;
740 
741     bs->op = BOOT_STATUS_OP_MOVE;
742     bs->idx = BOOT_STATUS_IDX_0;
743     bs->state = BOOT_STATUS_STATE_0;
744     bs->swap_type = BOOT_SWAP_TYPE_NONE;
745 }
746 
747 bool
boot_status_is_reset(const struct boot_status * bs)748 boot_status_is_reset(const struct boot_status *bs)
749 {
750     return (bs->op == BOOT_STATUS_OP_MOVE &&
751             bs->idx == BOOT_STATUS_IDX_0 &&
752             bs->state == BOOT_STATUS_STATE_0);
753 }
754 
755 /**
756  * Writes the supplied boot status to the flash file system.  The boot status
757  * contains the current state of an in-progress image copy operation.
758  *
759  * @param bs                    The boot status to write.
760  *
761  * @return                      0 on success; nonzero on failure.
762  */
763 int
boot_write_status(const struct boot_loader_state * state,struct boot_status * bs)764 boot_write_status(const struct boot_loader_state *state, struct boot_status *bs)
765 {
766     const struct flash_area *fap;
767     uint32_t off;
768     int area_id;
769     int rc = 0;
770     uint8_t buf[BOOT_MAX_ALIGN];
771     uint32_t align;
772     uint8_t erased_val;
773 
774     /* NOTE: The first sector copied (that is the last sector on slot) contains
775      *       the trailer. Since in the last step the primary slot is erased, the
776      *       first two status writes go to the scratch which will be copied to
777      *       the primary slot!
778      */
779 
780 #if MCUBOOT_SWAP_USING_SCRATCH
781     if (bs->use_scratch) {
782         /* Write to scratch. */
783         area_id = FLASH_AREA_IMAGE_SCRATCH;
784     } else {
785 #endif
786         /* Write to the primary slot. */
787         area_id = FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state));
788 #if MCUBOOT_SWAP_USING_SCRATCH
789     }
790 #endif
791 
792     rc = flash_area_open(area_id, &fap);
793     if (rc != 0) {
794         return BOOT_EFLASH;
795     }
796 
797     off = boot_status_off(fap) +
798           boot_status_internal_off(bs, BOOT_WRITE_SZ(state));
799     align = flash_area_align(fap);
800     erased_val = flash_area_erased_val(fap);
801     memset(buf, erased_val, BOOT_MAX_ALIGN);
802     buf[0] = bs->state;
803 
804     BOOT_LOG_DBG("writing swap status; fa_id=%d off=0x%lx (0x%lx)",
805                  flash_area_get_id(fap), (unsigned long)off,
806                  (unsigned long)flash_area_get_off(fap) + off);
807 
808     rc = flash_area_write(fap, off, buf, align);
809     if (rc != 0) {
810         rc = BOOT_EFLASH;
811     }
812 
813     flash_area_close(fap);
814 
815     return rc;
816 }
817 #endif /* !MCUBOOT_RAM_LOAD */
818 #endif /* !MCUBOOT_DIRECT_XIP */
819 
820 /*
821  * Validate image hash/signature and optionally the security counter in a slot.
822  */
823 static fih_ret
boot_image_check(struct boot_loader_state * state,struct image_header * hdr,const struct flash_area * fap,struct boot_status * bs)824 boot_image_check(struct boot_loader_state *state, struct image_header *hdr,
825                  const struct flash_area *fap, struct boot_status *bs)
826 {
827     TARGET_STATIC uint8_t tmpbuf[BOOT_TMPBUF_SZ];
828     int rc;
829     FIH_DECLARE(fih_rc, FIH_FAILURE);
830 
831 #if (BOOT_IMAGE_NUMBER == 1)
832     (void)state;
833 #endif
834 
835     (void)bs;
836     (void)rc;
837 
838 /* In the case of ram loading the image has already been decrypted as it is
839  * decrypted when copied in ram */
840 #if defined(MCUBOOT_ENC_IMAGES) && !defined(MCUBOOT_RAM_LOAD)
841     if (MUST_DECRYPT(fap, BOOT_CURR_IMG(state), hdr)) {
842         rc = boot_enc_load(BOOT_CURR_ENC(state), 1, hdr, fap, bs);
843         if (rc < 0) {
844             FIH_RET(fih_rc);
845         }
846         if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), 1, bs)) {
847             FIH_RET(fih_rc);
848         }
849     }
850 #endif
851 
852     FIH_CALL(bootutil_img_validate, fih_rc, BOOT_CURR_ENC(state),
853              BOOT_CURR_IMG(state), hdr, fap, tmpbuf, BOOT_TMPBUF_SZ,
854              NULL, 0, NULL);
855 
856     FIH_RET(fih_rc);
857 }
858 
859 #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
860 static fih_ret
split_image_check(struct image_header * app_hdr,const struct flash_area * app_fap,struct image_header * loader_hdr,const struct flash_area * loader_fap)861 split_image_check(struct image_header *app_hdr,
862                   const struct flash_area *app_fap,
863                   struct image_header *loader_hdr,
864                   const struct flash_area *loader_fap)
865 {
866     static void *tmpbuf;
867     uint8_t loader_hash[32];
868     FIH_DECLARE(fih_rc, FIH_FAILURE);
869 
870     if (!tmpbuf) {
871         tmpbuf = malloc(BOOT_TMPBUF_SZ);
872         if (!tmpbuf) {
873             goto out;
874         }
875     }
876 
877     FIH_CALL(bootutil_img_validate, fih_rc, NULL, 0, loader_hdr, loader_fap,
878              tmpbuf, BOOT_TMPBUF_SZ, NULL, 0, loader_hash);
879     if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
880         FIH_RET(fih_rc);
881     }
882 
883     FIH_CALL(bootutil_img_validate, fih_rc, NULL, 0, app_hdr, app_fap,
884              tmpbuf, BOOT_TMPBUF_SZ, loader_hash, 32, NULL);
885 
886 out:
887     FIH_RET(fih_rc);
888 }
889 #endif /* !MCUBOOT_DIRECT_XIP && !MCUBOOT_RAM_LOAD */
890 
891 /*
892  * Check that this is a valid header.  Valid means that the magic is
893  * correct, and that the sizes/offsets are "sane".  Sane means that
894  * there is no overflow on the arithmetic, and that the result fits
895  * within the flash area we are in. Also check the flags in the image
896  * and class the image as invalid if flags for encryption/compression
897  * are present but these features are not enabled.
898  */
899 static bool
boot_is_header_valid(const struct image_header * hdr,const struct flash_area * fap,struct boot_loader_state * state)900 boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fap,
901                      struct boot_loader_state *state)
902 {
903     uint32_t size;
904 
905     (void)state;
906 
907     if (hdr->ih_magic != IMAGE_MAGIC) {
908         return false;
909     }
910 
911     if (!boot_u32_safe_add(&size, hdr->ih_img_size, hdr->ih_hdr_size)) {
912         return false;
913     }
914 
915 #ifdef MCUBOOT_DECOMPRESS_IMAGES
916     if (!MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), hdr)) {
917 #else
918     if (1) {
919 #endif
920         if (!boot_u32_safe_add(&size, size, hdr->ih_protect_tlv_size)) {
921             return false;
922         }
923     }
924 
925     if (size >= flash_area_get_size(fap)) {
926         return false;
927     }
928 
929 #if !defined(MCUBOOT_ENC_IMAGES)
930     if (IS_ENCRYPTED(hdr)) {
931         return false;
932     }
933 #else
934     if ((hdr->ih_flags & IMAGE_F_ENCRYPTED_AES128) &&
935         (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES256))
936     {
937         return false;
938     }
939 #endif
940 
941 #if !defined(MCUBOOT_DECOMPRESS_IMAGES)
942     if (IS_COMPRESSED(hdr)) {
943         return false;
944     }
945 #else
946     if ((hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1) &&
947         (hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2))
948     {
949         return false;
950     }
951 #endif
952 
953     return true;
954 }
955 
956 /*
957  * Check that a memory area consists of a given value.
958  */
959 static inline bool
960 boot_data_is_set_to(uint8_t val, void *data, size_t len)
961 {
962     uint8_t i;
963     uint8_t *p = (uint8_t *)data;
964     for (i = 0; i < len; i++) {
965         if (val != p[i]) {
966             return false;
967         }
968     }
969     return true;
970 }
971 
972 static int
973 boot_check_header_erased(struct boot_loader_state *state, int slot)
974 {
975     const struct flash_area *fap;
976     struct image_header *hdr;
977     uint8_t erased_val;
978     int area_id;
979     int rc;
980 
981     area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
982     rc = flash_area_open(area_id, &fap);
983     if (rc != 0) {
984         return -1;
985     }
986 
987     erased_val = flash_area_erased_val(fap);
988     flash_area_close(fap);
989 
990     hdr = boot_img_hdr(state, slot);
991     if (!boot_data_is_set_to(erased_val, &hdr->ih_magic, sizeof(hdr->ih_magic))) {
992         return -1;
993     }
994 
995     return 0;
996 }
997 
998 #if defined(MCUBOOT_DIRECT_XIP)
999 /**
1000  * Check if image in slot has been set with specific ROM address to run from
1001  * and whether the slot starts at that address.
1002  *
1003  * @returns 0 if IMAGE_F_ROM_FIXED flag is not set;
1004  *          0 if IMAGE_F_ROM_FIXED flag is set and ROM address specified in
1005  *            header matches the slot address;
1006  *          1 if IMF_F_ROM_FIXED flag is set but ROM address specified in header
1007  *          does not match the slot address.
1008  */
1009 static bool
1010 boot_rom_address_check(struct boot_loader_state *state)
1011 {
1012     uint32_t active_slot;
1013     const struct image_header *hdr;
1014     uint32_t f_off;
1015 
1016     active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
1017     hdr = boot_img_hdr(state, active_slot);
1018     f_off = boot_img_slot_off(state, active_slot);
1019 
1020     if (hdr->ih_flags & IMAGE_F_ROM_FIXED && hdr->ih_load_addr != f_off) {
1021         BOOT_LOG_WRN("Image in %s slot at 0x%x has been built for offset 0x%x"\
1022                      ", skipping",
1023                      active_slot == 0 ? "primary" : "secondary", f_off,
1024                      hdr->ih_load_addr);
1025 
1026         /* If there is address mismatch, the image is not bootable from this
1027          * slot.
1028          */
1029         return 1;
1030     }
1031     return 0;
1032 }
1033 #endif
1034 
1035 /*
1036  * Check that there is a valid image in a slot
1037  *
1038  * @returns
1039  *         FIH_SUCCESS                      if image was successfully validated
1040  *         FIH_NO_BOOTABLE_IMAGE            if no bootloable image was found
1041  *         FIH_FAILURE                      on any errors
1042  */
1043 static fih_ret
1044 boot_validate_slot(struct boot_loader_state *state, int slot,
1045                    struct boot_status *bs)
1046 {
1047     const struct flash_area *fap;
1048     struct image_header *hdr;
1049     int area_id;
1050     FIH_DECLARE(fih_rc, FIH_FAILURE);
1051     int rc;
1052 
1053     area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
1054     rc = flash_area_open(area_id, &fap);
1055     if (rc != 0) {
1056         FIH_RET(fih_rc);
1057     }
1058 
1059     hdr = boot_img_hdr(state, slot);
1060     if (boot_check_header_erased(state, slot) == 0 ||
1061         (hdr->ih_flags & IMAGE_F_NON_BOOTABLE)) {
1062 
1063 #if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE)
1064         /*
1065          * This fixes an issue where an image might be erased, but a trailer
1066          * be left behind. It can happen if the image is in the secondary slot
1067          * and did not pass validation, in which case the whole slot is erased.
1068          * If during the erase operation, a reset occurs, parts of the slot
1069          * might have been erased while some did not. The concerning part is
1070          * the trailer because it might disable a new image from being loaded
1071          * through mcumgr; so we just get rid of the trailer here, if the header
1072          * is erased.
1073          */
1074         if (slot != BOOT_PRIMARY_SLOT) {
1075             swap_erase_trailer_sectors(state, fap);
1076         }
1077 #endif
1078 
1079         /* No bootable image in slot; continue booting from the primary slot. */
1080         fih_rc = FIH_NO_BOOTABLE_IMAGE;
1081         goto out;
1082     }
1083 
1084 #if defined(MCUBOOT_OVERWRITE_ONLY) && defined(MCUBOOT_DOWNGRADE_PREVENTION)
1085     if (slot != BOOT_PRIMARY_SLOT) {
1086         /* Check if version of secondary slot is sufficient */
1087         rc = boot_version_cmp(
1088                 &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver,
1089                 &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver);
1090         if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) {
1091             BOOT_LOG_ERR("insufficient version in secondary slot");
1092             flash_area_erase(fap, 0, flash_area_get_size(fap));
1093             /* Image in the secondary slot does not satisfy version requirement.
1094              * Erase the image and continue booting from the primary slot.
1095              */
1096             fih_rc = FIH_NO_BOOTABLE_IMAGE;
1097             goto out;
1098         }
1099     }
1100 #endif
1101     if (!boot_is_header_valid(hdr, fap, state)) {
1102         fih_rc = FIH_FAILURE;
1103     } else {
1104         BOOT_HOOK_CALL_FIH(boot_image_check_hook, FIH_BOOT_HOOK_REGULAR,
1105                            fih_rc, BOOT_CURR_IMG(state), slot);
1106         if (FIH_EQ(fih_rc, FIH_BOOT_HOOK_REGULAR)) {
1107             FIH_CALL(boot_image_check, fih_rc, state, hdr, fap, bs);
1108         }
1109     }
1110     if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
1111         if ((slot != BOOT_PRIMARY_SLOT) || ARE_SLOTS_EQUIVALENT()) {
1112             flash_area_erase(fap, 0, flash_area_get_size(fap));
1113             /* Image is invalid, erase it to prevent further unnecessary
1114              * attempts to validate and boot it.
1115              */
1116         }
1117 #if !defined(__BOOTSIM__)
1118         BOOT_LOG_ERR("Image in the %s slot is not valid!",
1119                      (slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary");
1120 #endif
1121         fih_rc = FIH_NO_BOOTABLE_IMAGE;
1122         goto out;
1123     }
1124 
1125 #if MCUBOOT_IMAGE_NUMBER > 1 && !defined(MCUBOOT_ENC_IMAGES) && defined(MCUBOOT_VERIFY_IMG_ADDRESS)
1126     /* Verify that the image in the secondary slot has a reset address
1127      * located in the primary slot. This is done to avoid users incorrectly
1128      * overwriting an application written to the incorrect slot.
1129      * This feature is only supported by ARM platforms.
1130      */
1131     if (area_id == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) {
1132         const struct flash_area *pri_fa = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT);
1133         struct image_header *secondary_hdr = boot_img_hdr(state, slot);
1134         uint32_t reset_value = 0;
1135         uint32_t reset_addr = secondary_hdr->ih_hdr_size + sizeof(reset_value);
1136 
1137         rc = flash_area_read(fap, reset_addr, &reset_value, sizeof(reset_value));
1138         if (rc != 0) {
1139             fih_rc = FIH_NO_BOOTABLE_IMAGE;
1140             goto out;
1141         }
1142 
1143         if (reset_value < pri_fa->fa_off || reset_value> (pri_fa->fa_off + pri_fa->fa_size)) {
1144             BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot");
1145             BOOT_LOG_ERR("Erasing image from secondary slot");
1146 
1147             /* The vector table in the image located in the secondary
1148              * slot does not target the primary slot. This might
1149              * indicate that the image was loaded to the wrong slot.
1150              *
1151              * Erase the image and continue booting from the primary slot.
1152              */
1153             flash_area_erase(fap, 0, fap->fa_size);
1154             fih_rc = FIH_NO_BOOTABLE_IMAGE;
1155             goto out;
1156         }
1157     }
1158 #endif
1159 
1160 out:
1161     flash_area_close(fap);
1162 
1163     FIH_RET(fih_rc);
1164 }
1165 
1166 #ifdef MCUBOOT_HW_ROLLBACK_PROT
1167 /**
1168  * Updates the stored security counter value with the image's security counter
1169  * value which resides in the given slot, only if it's greater than the stored
1170  * value.
1171  *
1172  * @param image_index   Index of the image to determine which security
1173  *                      counter to update.
1174  * @param slot          Slot number of the image.
1175  * @param hdr           Pointer to the image header structure of the image
1176  *                      that is currently stored in the given slot.
1177  *
1178  * @return              0 on success; nonzero on failure.
1179  */
1180 static int
1181 boot_update_security_counter(uint8_t image_index, int slot,
1182                              struct image_header *hdr)
1183 {
1184     const struct flash_area *fap = NULL;
1185     uint32_t img_security_cnt;
1186     int rc;
1187 
1188     rc = flash_area_open(flash_area_id_from_multi_image_slot(image_index, slot),
1189                          &fap);
1190     if (rc != 0) {
1191         rc = BOOT_EFLASH;
1192         goto done;
1193     }
1194 
1195     rc = bootutil_get_img_security_cnt(hdr, fap, &img_security_cnt);
1196     if (rc != 0) {
1197         goto done;
1198     }
1199 
1200     rc = boot_nv_security_counter_update(image_index, img_security_cnt);
1201     if (rc != 0) {
1202         goto done;
1203     }
1204 
1205 done:
1206     flash_area_close(fap);
1207     return rc;
1208 }
1209 #endif /* MCUBOOT_HW_ROLLBACK_PROT */
1210 
1211 #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
1212 /**
1213  * Determines which swap operation to perform, if any.  If it is determined
1214  * that a swap operation is required, the image in the secondary slot is checked
1215  * for validity.  If the image in the secondary slot is invalid, it is erased,
1216  * and a swap type of "none" is indicated.
1217  *
1218  * @return                      The type of swap to perform (BOOT_SWAP_TYPE...)
1219  */
1220 static int
1221 boot_validated_swap_type(struct boot_loader_state *state,
1222                          struct boot_status *bs)
1223 {
1224     int swap_type;
1225     FIH_DECLARE(fih_rc, FIH_FAILURE);
1226 
1227     swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state));
1228     if (BOOT_IS_UPGRADE(swap_type)) {
1229         /* Boot loader wants to switch to the secondary slot.
1230          * Ensure image is valid.
1231          */
1232         FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_SECONDARY_SLOT, bs);
1233         if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
1234             if (FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) {
1235                 swap_type = BOOT_SWAP_TYPE_NONE;
1236             } else {
1237                 swap_type = BOOT_SWAP_TYPE_FAIL;
1238             }
1239         }
1240     }
1241 
1242     return swap_type;
1243 }
1244 #endif
1245 
1246 /**
1247  * Erases a region of flash.
1248  *
1249  * @param flash_area           The flash_area containing the region to erase.
1250  * @param off                   The offset within the flash area to start the
1251  *                                  erase.
1252  * @param sz                    The number of bytes to erase.
1253  *
1254  * @return                      0 on success; nonzero on failure.
1255  */
1256 int
1257 boot_erase_region(const struct flash_area *fap, uint32_t off, uint32_t sz)
1258 {
1259     return flash_area_erase(fap, off, sz);
1260 }
1261 
1262 #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
1263 
1264 #if defined(MCUBOOT_ENC_IMAGES) || defined(MCUBOOT_SWAP_SAVE_ENCTLV)
1265 /* Replacement for memset(p, 0, sizeof(*p) that does not get
1266  * optimized out.
1267  */
1268 static void like_mbedtls_zeroize(void *p, size_t n)
1269 {
1270     volatile unsigned char *v = (unsigned char *)p;
1271 
1272     for (size_t i = 0; i < n; i++) {
1273         v[i] = 0;
1274     }
1275 }
1276 #endif
1277 
1278 /**
1279  * Copies the contents of one flash region to another.  You must erase the
1280  * destination region prior to calling this function.
1281  *
1282  * @param flash_area_id_src     The ID of the source flash area.
1283  * @param flash_area_id_dst     The ID of the destination flash area.
1284  * @param off_src               The offset within the source flash area to
1285  *                                  copy from.
1286  * @param off_dst               The offset within the destination flash area to
1287  *                                  copy to.
1288  * @param sz                    The number of bytes to copy.
1289  *
1290  * @return                      0 on success; nonzero on failure.
1291  */
1292 int
1293 boot_copy_region(struct boot_loader_state *state,
1294                  const struct flash_area *fap_src,
1295                  const struct flash_area *fap_dst,
1296                  uint32_t off_src, uint32_t off_dst, uint32_t sz)
1297 {
1298     uint32_t bytes_copied;
1299     int chunk_sz;
1300     int rc;
1301 #ifdef MCUBOOT_ENC_IMAGES
1302     uint32_t off = off_dst;
1303     uint32_t tlv_off;
1304     size_t blk_off;
1305     struct image_header *hdr;
1306     uint16_t idx;
1307     uint32_t blk_sz;
1308     uint8_t image_index = BOOT_CURR_IMG(state);
1309     bool encrypted_src;
1310     bool encrypted_dst;
1311     /* Assuming the secondary slot is source; note that 0 here not only
1312      * means that primary slot is source, but also that there will be
1313      * encryption happening, if it is 1 then there is decryption from
1314      * secondary slot.
1315      */
1316     int source_slot = 1;
1317     /* In case of encryption enabled, we may have to do more work than
1318      * just copy bytes */
1319     bool only_copy = false;
1320 #else
1321     (void)state;
1322 #endif
1323 
1324     TARGET_STATIC uint8_t buf[BUF_SZ] __attribute__((aligned(4)));
1325 
1326 #ifdef MCUBOOT_ENC_IMAGES
1327     encrypted_src = (flash_area_get_id(fap_src) != FLASH_AREA_IMAGE_PRIMARY(image_index));
1328     encrypted_dst = (flash_area_get_id(fap_dst) != FLASH_AREA_IMAGE_PRIMARY(image_index));
1329 
1330     if (encrypted_src != encrypted_dst) {
1331         if (encrypted_dst) {
1332             /* Need encryption, metadata from the primary slot */
1333             hdr = boot_img_hdr(state, BOOT_PRIMARY_SLOT);
1334             source_slot = 0;
1335         } else {
1336             /* Need decryption, metadata from the secondary slot */
1337             hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
1338             source_slot = 1;
1339         }
1340     } else {
1341         /* In case when source and targe is the same area, this means that we
1342          * only have to copy bytes, no encryption or decryption.
1343          */
1344         only_copy = true;
1345     }
1346 #endif
1347 
1348     bytes_copied = 0;
1349     while (bytes_copied < sz) {
1350         if (sz - bytes_copied > sizeof buf) {
1351             chunk_sz = sizeof buf;
1352         } else {
1353             chunk_sz = sz - bytes_copied;
1354         }
1355 
1356         rc = flash_area_read(fap_src, off_src + bytes_copied, buf, chunk_sz);
1357         if (rc != 0) {
1358             return BOOT_EFLASH;
1359         }
1360 
1361 #ifdef MCUBOOT_ENC_IMAGES
1362         /* If only copy, then does not matter if header indicates need for
1363          * encryptio/decryptio, we just copy data. */
1364         if (!only_copy && IS_ENCRYPTED(hdr)) {
1365             uint32_t abs_off = off + bytes_copied;
1366             if (abs_off < hdr->ih_hdr_size) {
1367                 /* do not decrypt header */
1368                 if (abs_off + chunk_sz > hdr->ih_hdr_size) {
1369                     /* The lower part of the chunk contains header data */
1370                     blk_off = 0;
1371                     blk_sz = chunk_sz - (hdr->ih_hdr_size - abs_off);
1372                     idx = hdr->ih_hdr_size  - abs_off;
1373                 } else {
1374                     /* The chunk contains exclusively header data */
1375                     blk_sz = 0; /* nothing to decrypt */
1376                 }
1377             } else {
1378                 idx = 0;
1379                 blk_sz = chunk_sz;
1380                 blk_off = (abs_off - hdr->ih_hdr_size) & 0xf;
1381             }
1382 
1383             if (blk_sz > 0)
1384             {
1385                 tlv_off = BOOT_TLV_OFF(hdr);
1386                 if (abs_off + chunk_sz > tlv_off) {
1387                     /* do not decrypt TLVs */
1388                     if (abs_off >= tlv_off) {
1389                         blk_sz = 0;
1390                     } else {
1391                         blk_sz = tlv_off - abs_off;
1392                     }
1393                 }
1394                 if (source_slot == 0) {
1395                     boot_enc_encrypt(BOOT_CURR_ENC(state), source_slot,
1396                             (abs_off + idx) - hdr->ih_hdr_size, blk_sz,
1397                             blk_off, &buf[idx]);
1398                 } else {
1399                     boot_enc_decrypt(BOOT_CURR_ENC(state), source_slot,
1400                             (abs_off + idx) - hdr->ih_hdr_size, blk_sz,
1401                             blk_off, &buf[idx]);
1402                 }
1403             }
1404         }
1405 #endif
1406 
1407         rc = flash_area_write(fap_dst, off_dst + bytes_copied, buf, chunk_sz);
1408         if (rc != 0) {
1409             return BOOT_EFLASH;
1410         }
1411 
1412         bytes_copied += chunk_sz;
1413 
1414         MCUBOOT_WATCHDOG_FEED();
1415     }
1416 
1417     return 0;
1418 }
1419 
1420 /**
1421  * Overwrite primary slot with the image contained in the secondary slot.
1422  * If a prior copy operation was interrupted by a system reset, this function
1423  * redos the copy.
1424  *
1425  * @param bs                    The current boot status.  This function reads
1426  *                                  this struct to determine if it is resuming
1427  *                                  an interrupted swap operation.  This
1428  *                                  function writes the updated status to this
1429  *                                  function on return.
1430  *
1431  * @return                      0 on success; nonzero on failure.
1432  */
1433 #if defined(MCUBOOT_OVERWRITE_ONLY) || defined(MCUBOOT_BOOTSTRAP)
1434 static int
1435 boot_copy_image(struct boot_loader_state *state, struct boot_status *bs)
1436 {
1437     size_t sect_count;
1438     size_t sect;
1439     int rc;
1440     size_t size;
1441     size_t this_size;
1442     size_t last_sector;
1443     const struct flash_area *fap_primary_slot;
1444     const struct flash_area *fap_secondary_slot;
1445     uint8_t image_index;
1446 
1447 #if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
1448     uint32_t sector;
1449     uint32_t trailer_sz;
1450     uint32_t off;
1451     uint32_t sz;
1452 #endif
1453 
1454     (void)bs;
1455 
1456 #if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
1457     uint32_t src_size = 0;
1458     rc = boot_read_image_size(state, BOOT_SECONDARY_SLOT, &src_size);
1459     assert(rc == 0);
1460 #endif
1461 
1462     image_index = BOOT_CURR_IMG(state);
1463 
1464     BOOT_LOG_INF("Image %d upgrade secondary slot -> primary slot", image_index);
1465     BOOT_LOG_INF("Erasing the primary slot");
1466 
1467     rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index),
1468             &fap_primary_slot);
1469     assert (rc == 0);
1470 
1471     rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index),
1472             &fap_secondary_slot);
1473     assert (rc == 0);
1474 
1475     sect_count = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT);
1476     for (sect = 0, size = 0; sect < sect_count; sect++) {
1477         this_size = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, sect);
1478         rc = boot_erase_region(fap_primary_slot, size, this_size);
1479         assert(rc == 0);
1480 
1481 #if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
1482         if ((size + this_size) >= src_size) {
1483             size += src_size - size;
1484             size += BOOT_WRITE_SZ(state) - (size % BOOT_WRITE_SZ(state));
1485             break;
1486         }
1487 #endif
1488 
1489         size += this_size;
1490     }
1491 
1492 #if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
1493     trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state));
1494     sector = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) - 1;
1495     sz = 0;
1496     do {
1497         sz += boot_img_sector_size(state, BOOT_PRIMARY_SLOT, sector);
1498         off = boot_img_sector_off(state, BOOT_PRIMARY_SLOT, sector);
1499         sector--;
1500     } while (sz < trailer_sz);
1501 
1502     rc = boot_erase_region(fap_primary_slot, off, sz);
1503     assert(rc == 0);
1504 #endif
1505 
1506 #ifdef MCUBOOT_ENC_IMAGES
1507     if (IS_ENCRYPTED(boot_img_hdr(state, BOOT_SECONDARY_SLOT))) {
1508         rc = boot_enc_load(BOOT_CURR_ENC(state), BOOT_SECONDARY_SLOT,
1509                 boot_img_hdr(state, BOOT_SECONDARY_SLOT),
1510                 fap_secondary_slot, bs);
1511 
1512         if (rc < 0) {
1513             return BOOT_EBADIMAGE;
1514         }
1515         if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), 1, bs)) {
1516             return BOOT_EBADIMAGE;
1517         }
1518     }
1519 #endif
1520 
1521     BOOT_LOG_INF("Image %d copying the secondary slot to the primary slot: 0x%zx bytes",
1522                  image_index, size);
1523     rc = boot_copy_region(state, fap_secondary_slot, fap_primary_slot, 0, 0, size);
1524     if (rc != 0) {
1525         return rc;
1526     }
1527 
1528 #if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
1529     rc = boot_write_magic(fap_primary_slot);
1530     if (rc != 0) {
1531         return rc;
1532     }
1533 #endif
1534 
1535     rc = BOOT_HOOK_CALL(boot_copy_region_post_hook, 0, BOOT_CURR_IMG(state),
1536                         BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT), size);
1537     if (rc != 0) {
1538         return rc;
1539     }
1540 
1541 #ifdef MCUBOOT_HW_ROLLBACK_PROT
1542     /* Update the stored security counter with the new image's security counter
1543      * value. Both slots hold the new image at this point, but the secondary
1544      * slot's image header must be passed since the image headers in the
1545      * boot_data structure have not been updated yet.
1546      */
1547     rc = boot_update_security_counter(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT,
1548                                 boot_img_hdr(state, BOOT_SECONDARY_SLOT));
1549     if (rc != 0) {
1550         BOOT_LOG_ERR("Security counter update failed after image upgrade.");
1551         return rc;
1552     }
1553 #endif /* MCUBOOT_HW_ROLLBACK_PROT */
1554 
1555 #ifndef MCUBOOT_OVERWRITE_ONLY_KEEP_BACKUP
1556     /*
1557      * Erases header and trailer. The trailer is erased because when a new
1558      * image is written without a trailer as is the case when using newt, the
1559      * trailer that was left might trigger a new upgrade.
1560      */
1561     BOOT_LOG_DBG("erasing secondary header");
1562     rc = boot_erase_region(fap_secondary_slot,
1563                            boot_img_sector_off(state, BOOT_SECONDARY_SLOT, 0),
1564                            boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0));
1565     assert(rc == 0);
1566 #endif
1567 
1568     last_sector = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) - 1;
1569     BOOT_LOG_DBG("erasing secondary trailer");
1570     rc = boot_erase_region(fap_secondary_slot,
1571                            boot_img_sector_off(state, BOOT_SECONDARY_SLOT,
1572                                last_sector),
1573                            boot_img_sector_size(state, BOOT_SECONDARY_SLOT,
1574                                last_sector));
1575     assert(rc == 0);
1576 
1577     flash_area_close(fap_primary_slot);
1578     flash_area_close(fap_secondary_slot);
1579 
1580     /* TODO: Perhaps verify the primary slot's signature again? */
1581 
1582     return 0;
1583 }
1584 #endif
1585 
1586 #if !defined(MCUBOOT_OVERWRITE_ONLY)
1587 /**
1588  * Swaps the two images in flash.  If a prior copy operation was interrupted
1589  * by a system reset, this function completes that operation.
1590  *
1591  * @param bs                    The current boot status.  This function reads
1592  *                                  this struct to determine if it is resuming
1593  *                                  an interrupted swap operation.  This
1594  *                                  function writes the updated status to this
1595  *                                  function on return.
1596  *
1597  * @return                      0 on success; nonzero on failure.
1598  */
1599 static int
1600 boot_swap_image(struct boot_loader_state *state, struct boot_status *bs)
1601 {
1602     struct image_header *hdr;
1603     const struct flash_area *fap;
1604 #ifdef MCUBOOT_ENC_IMAGES
1605     uint8_t slot;
1606     uint8_t i;
1607 #endif
1608     uint32_t size;
1609     uint32_t copy_size;
1610     uint8_t image_index;
1611     int rc;
1612 
1613     /* FIXME: just do this if asked by user? */
1614 
1615     size = copy_size = 0;
1616     image_index = BOOT_CURR_IMG(state);
1617 
1618     if (boot_status_is_reset(bs)) {
1619         /*
1620          * No swap ever happened, so need to find the largest image which
1621          * will be used to determine the amount of sectors to swap.
1622          */
1623         hdr = boot_img_hdr(state, BOOT_PRIMARY_SLOT);
1624         if (hdr->ih_magic == IMAGE_MAGIC) {
1625             rc = boot_read_image_size(state, BOOT_PRIMARY_SLOT, &copy_size);
1626             assert(rc == 0);
1627         }
1628 
1629 #ifdef MCUBOOT_ENC_IMAGES
1630         if (IS_ENCRYPTED(hdr)) {
1631             fap = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT);
1632             rc = boot_enc_load(BOOT_CURR_ENC(state), 0, hdr, fap, bs);
1633             assert(rc >= 0);
1634 
1635             if (rc == 0) {
1636                 rc = boot_enc_set_key(BOOT_CURR_ENC(state), 0, bs);
1637                 assert(rc == 0);
1638             } else {
1639                 rc = 0;
1640             }
1641         } else {
1642             memset(bs->enckey[0], 0xff, BOOT_ENC_KEY_ALIGN_SIZE);
1643         }
1644 #endif
1645 
1646         hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
1647         if (hdr->ih_magic == IMAGE_MAGIC) {
1648             rc = boot_read_image_size(state, BOOT_SECONDARY_SLOT, &size);
1649             assert(rc == 0);
1650         }
1651 
1652 #ifdef MCUBOOT_ENC_IMAGES
1653         hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
1654         if (IS_ENCRYPTED(hdr)) {
1655             fap = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT);
1656             rc = boot_enc_load(BOOT_CURR_ENC(state), 1, hdr, fap, bs);
1657             assert(rc >= 0);
1658 
1659             if (rc == 0) {
1660                 rc = boot_enc_set_key(BOOT_CURR_ENC(state), 1, bs);
1661                 assert(rc == 0);
1662             } else {
1663                 rc = 0;
1664             }
1665         } else {
1666             memset(bs->enckey[1], 0xff, BOOT_ENC_KEY_ALIGN_SIZE);
1667         }
1668 #endif
1669 
1670         if (size > copy_size) {
1671             copy_size = size;
1672         }
1673 
1674         bs->swap_size = copy_size;
1675     } else {
1676         /*
1677          * If a swap was under way, the swap_size should already be present
1678          * in the trailer...
1679          */
1680 
1681         rc = boot_find_status(image_index, &fap);
1682         assert(fap != NULL);
1683         rc = boot_read_swap_size(fap, &bs->swap_size);
1684         assert(rc == 0);
1685 
1686         copy_size = bs->swap_size;
1687 
1688 #ifdef MCUBOOT_ENC_IMAGES
1689         for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
1690             rc = boot_read_enc_key(fap, slot, bs);
1691             assert(rc == 0);
1692 
1693             for (i = 0; i < BOOT_ENC_KEY_SIZE; i++) {
1694                 if (bs->enckey[slot][i] != 0xff) {
1695                     break;
1696                 }
1697             }
1698 
1699             boot_enc_init(BOOT_CURR_ENC(state), slot);
1700 
1701             if (i != BOOT_ENC_KEY_SIZE) {
1702                 boot_enc_set_key(BOOT_CURR_ENC(state), slot, bs);
1703             }
1704         }
1705 #endif
1706         flash_area_close(fap);
1707     }
1708 
1709     swap_run(state, bs, copy_size);
1710 
1711 #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
1712     extern int boot_status_fails;
1713     if (boot_status_fails > 0) {
1714         BOOT_LOG_WRN("%d status write fails performing the swap",
1715                      boot_status_fails);
1716     }
1717 #endif
1718     rc = BOOT_HOOK_CALL(boot_copy_region_post_hook, 0, BOOT_CURR_IMG(state),
1719                         BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT), size);
1720 
1721     return 0;
1722 }
1723 #endif
1724 
1725 
1726 /**
1727  * Performs a clean (not aborted) image update.
1728  *
1729  * @param bs                    The current boot status.
1730  *
1731  * @return                      0 on success; nonzero on failure.
1732  */
1733 static int
1734 boot_perform_update(struct boot_loader_state *state, struct boot_status *bs)
1735 {
1736     int rc;
1737 #ifndef MCUBOOT_OVERWRITE_ONLY
1738     uint8_t swap_type;
1739 #endif
1740 
1741     /* At this point there are no aborted swaps. */
1742 #if defined(MCUBOOT_OVERWRITE_ONLY)
1743     rc = boot_copy_image(state, bs);
1744 #elif defined(MCUBOOT_BOOTSTRAP)
1745     /* Check if the image update was triggered by a bad image in the
1746      * primary slot (the validity of the image in the secondary slot had
1747      * already been checked).
1748      */
1749     FIH_DECLARE(fih_rc, FIH_FAILURE);
1750     rc = boot_check_header_erased(state, BOOT_PRIMARY_SLOT);
1751     FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, bs);
1752     if (rc == 0 || FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
1753         rc = boot_copy_image(state, bs);
1754     } else {
1755         rc = boot_swap_image(state, bs);
1756     }
1757 #else
1758         rc = boot_swap_image(state, bs);
1759 #endif
1760     assert(rc == 0);
1761 
1762 #ifndef MCUBOOT_OVERWRITE_ONLY
1763     /* The following state needs image_ok be explicitly set after the
1764      * swap was finished to avoid a new revert.
1765      */
1766     swap_type = BOOT_SWAP_TYPE(state);
1767     if (swap_type == BOOT_SWAP_TYPE_REVERT ||
1768             swap_type == BOOT_SWAP_TYPE_PERM) {
1769         rc = swap_set_image_ok(BOOT_CURR_IMG(state));
1770         if (rc != 0) {
1771             BOOT_SWAP_TYPE(state) = swap_type = BOOT_SWAP_TYPE_PANIC;
1772         }
1773     }
1774 
1775 #ifdef MCUBOOT_HW_ROLLBACK_PROT
1776     if (swap_type == BOOT_SWAP_TYPE_PERM) {
1777         /* Update the stored security counter with the new image's security
1778          * counter value. The primary slot holds the new image at this point,
1779          * but the secondary slot's image header must be passed since image
1780          * headers in the boot_data structure have not been updated yet.
1781          *
1782          * In case of a permanent image swap mcuboot will never attempt to
1783          * revert the images on the next reboot. Therefore, the security
1784          * counter must be increased right after the image upgrade.
1785          */
1786         rc = boot_update_security_counter(
1787                                     BOOT_CURR_IMG(state),
1788                                     BOOT_PRIMARY_SLOT,
1789                                     boot_img_hdr(state, BOOT_SECONDARY_SLOT));
1790         if (rc != 0) {
1791             BOOT_LOG_ERR("Security counter update failed after "
1792                          "image upgrade.");
1793             BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
1794         }
1795     }
1796 #endif /* MCUBOOT_HW_ROLLBACK_PROT */
1797 
1798     if (BOOT_IS_UPGRADE(swap_type)) {
1799         rc = swap_set_copy_done(BOOT_CURR_IMG(state));
1800         if (rc != 0) {
1801             BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
1802         }
1803     }
1804 #endif /* !MCUBOOT_OVERWRITE_ONLY */
1805 
1806     return rc;
1807 }
1808 
1809 /**
1810  * Completes a previously aborted image swap.
1811  *
1812  * @param bs                    The current boot status.
1813  *
1814  * @return                      0 on success; nonzero on failure.
1815  */
1816 #if !defined(MCUBOOT_OVERWRITE_ONLY)
1817 static int
1818 boot_complete_partial_swap(struct boot_loader_state *state,
1819         struct boot_status *bs)
1820 {
1821     int rc;
1822 
1823     /* Determine the type of swap operation being resumed from the
1824      * `swap-type` trailer field.
1825      */
1826     rc = boot_swap_image(state, bs);
1827     assert(rc == 0);
1828 
1829     BOOT_SWAP_TYPE(state) = bs->swap_type;
1830 
1831     /* The following states need image_ok be explicitly set after the
1832      * swap was finished to avoid a new revert.
1833      */
1834     if (bs->swap_type == BOOT_SWAP_TYPE_REVERT ||
1835         bs->swap_type == BOOT_SWAP_TYPE_PERM) {
1836         rc = swap_set_image_ok(BOOT_CURR_IMG(state));
1837         if (rc != 0) {
1838             BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
1839         }
1840     }
1841 
1842     if (BOOT_IS_UPGRADE(bs->swap_type)) {
1843         rc = swap_set_copy_done(BOOT_CURR_IMG(state));
1844         if (rc != 0) {
1845             BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
1846         }
1847     }
1848 
1849     if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_PANIC) {
1850         BOOT_LOG_ERR("panic!");
1851         assert(0);
1852 
1853         /* Loop forever... */
1854         while (1) {}
1855     }
1856 
1857     return rc;
1858 }
1859 #endif /* !MCUBOOT_OVERWRITE_ONLY */
1860 
1861 #if (BOOT_IMAGE_NUMBER > 1)
1862 /**
1863  * Review the validity of previously determined swap types of other images.
1864  *
1865  * @param aborted_swap          The current image upgrade is a
1866  *                              partial/aborted swap.
1867  */
1868 static void
1869 boot_review_image_swap_types(struct boot_loader_state *state,
1870                              bool aborted_swap)
1871 {
1872     /* In that case if we rebooted in the middle of an image upgrade process, we
1873      * must review the validity of swap types, that were previously determined
1874      * for other images. The image_ok flag had not been set before the reboot
1875      * for any of the updated images (only the copy_done flag) and thus falsely
1876      * the REVERT swap type has been determined for the previous images that had
1877      * been updated before the reboot.
1878      *
1879      * There are two separate scenarios that we have to deal with:
1880      *
1881      * 1. The reboot has happened during swapping an image:
1882      *      The current image upgrade has been determined as a
1883      *      partial/aborted swap.
1884      * 2. The reboot has happened between two separate image upgrades:
1885      *      In this scenario we must check the swap type of the current image.
1886      *      In those cases if it is NONE or REVERT we cannot certainly determine
1887      *      the fact of a reboot. In a consistent state images must move in the
1888      *      same direction or stay in place, e.g. in practice REVERT and TEST
1889      *      swap types cannot be present at the same time. If the swap type of
1890      *      the current image is either TEST, PERM or FAIL we must review the
1891      *      already determined swap types of other images and set each false
1892      *      REVERT swap types to NONE (these images had been successfully
1893      *      updated before the system rebooted between two separate image
1894      *      upgrades).
1895      */
1896 
1897     if (BOOT_CURR_IMG(state) == 0) {
1898         /* Nothing to do */
1899         return;
1900     }
1901 
1902     if (!aborted_swap) {
1903         if ((BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) ||
1904             (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_REVERT)) {
1905             /* Nothing to do */
1906             return;
1907         }
1908     }
1909 
1910     for (uint8_t i = 0; i < BOOT_CURR_IMG(state); i++) {
1911         if (state->swap_type[i] == BOOT_SWAP_TYPE_REVERT) {
1912             state->swap_type[i] = BOOT_SWAP_TYPE_NONE;
1913         }
1914     }
1915 }
1916 #endif
1917 
1918 /**
1919  * Prepare image to be updated if required.
1920  *
1921  * Prepare image to be updated if required with completing an image swap
1922  * operation if one was aborted and/or determining the type of the
1923  * swap operation. In case of any error set the swap type to NONE.
1924  *
1925  * @param state                 TODO
1926  * @param bs                    Pointer where the read and possibly updated
1927  *                              boot status can be written to.
1928  */
1929 static void
1930 boot_prepare_image_for_update(struct boot_loader_state *state,
1931                               struct boot_status *bs)
1932 {
1933     int rc;
1934     FIH_DECLARE(fih_rc, FIH_FAILURE);
1935 
1936 #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING)
1937     int max_size;
1938 #endif
1939 
1940     /* Determine the sector layout of the image slots and scratch area. */
1941     rc = boot_read_sectors(state);
1942     if (rc != 0) {
1943         BOOT_LOG_WRN("Failed reading sectors; BOOT_MAX_IMG_SECTORS=%d"
1944                      " - too small?", BOOT_MAX_IMG_SECTORS);
1945         /* Unable to determine sector layout, continue with next image
1946          * if there is one.
1947          */
1948         BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
1949         if (rc == BOOT_EFLASH)
1950         {
1951             /* Only return on error from the primary image flash */
1952             return;
1953         }
1954     }
1955 
1956     /* Attempt to read an image header from each slot. */
1957     rc = boot_read_image_headers(state, false, NULL);
1958     if (rc != 0) {
1959         /* Continue with next image if there is one. */
1960         BOOT_LOG_WRN("Failed reading image headers; Image=%u",
1961                 BOOT_CURR_IMG(state));
1962         BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
1963         return;
1964     }
1965 
1966 #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING)
1967     /* Fetch information on maximum sizes for later usage, if needed */
1968     max_size = app_max_size(state);
1969 
1970     if (max_size > 0) {
1971         image_max_sizes[BOOT_CURR_IMG(state)].calculated = true;
1972         image_max_sizes[BOOT_CURR_IMG(state)].max_size = max_size;
1973     }
1974 #endif
1975 
1976     /* If the current image's slots aren't compatible, no swap is possible.
1977      * Just boot into primary slot.
1978      */
1979     if (boot_slots_compatible(state)) {
1980         boot_status_reset(bs);
1981 
1982 #ifndef MCUBOOT_OVERWRITE_ONLY
1983         rc = swap_read_status(state, bs);
1984         if (rc != 0) {
1985             BOOT_LOG_WRN("Failed reading boot status; Image=%u",
1986                     BOOT_CURR_IMG(state));
1987             /* Continue with next image if there is one. */
1988             BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
1989             return;
1990         }
1991 #endif
1992 
1993 #if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE)
1994         /*
1995          * Must re-read image headers because the boot status might
1996          * have been updated in the previous function call.
1997          */
1998         rc = boot_read_image_headers(state, !boot_status_is_reset(bs), bs);
1999 #ifdef MCUBOOT_BOOTSTRAP
2000         /* When bootstrapping it's OK to not have image magic in the primary slot */
2001         if (rc != 0 && (BOOT_CURR_IMG(state) != BOOT_PRIMARY_SLOT ||
2002                 boot_check_header_erased(state, BOOT_PRIMARY_SLOT) != 0)) {
2003 #else
2004         if (rc != 0) {
2005 #endif
2006 
2007             /* Continue with next image if there is one. */
2008             BOOT_LOG_WRN("Failed reading image headers; Image=%u",
2009                     BOOT_CURR_IMG(state));
2010             BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
2011             return;
2012         }
2013 #endif
2014 
2015         /* Determine if we rebooted in the middle of an image swap
2016          * operation. If a partial swap was detected, complete it.
2017          */
2018         if (!boot_status_is_reset(bs)) {
2019 
2020 #if (BOOT_IMAGE_NUMBER > 1)
2021             boot_review_image_swap_types(state, true);
2022 #endif
2023 
2024 #ifdef MCUBOOT_OVERWRITE_ONLY
2025             /* Should never arrive here, overwrite-only mode has
2026              * no swap state.
2027              */
2028             assert(0);
2029 #else
2030             /* Determine the type of swap operation being resumed from the
2031              * `swap-type` trailer field.
2032              */
2033             rc = boot_complete_partial_swap(state, bs);
2034             assert(rc == 0);
2035 #endif
2036             /* Attempt to read an image header from each slot. Ensure that
2037              * image headers in slots are aligned with headers in boot_data.
2038              */
2039             rc = boot_read_image_headers(state, false, bs);
2040             assert(rc == 0);
2041 
2042             /* Swap has finished set to NONE */
2043             BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
2044         } else {
2045             /* There was no partial swap, determine swap type. */
2046             if (bs->swap_type == BOOT_SWAP_TYPE_NONE) {
2047                 BOOT_SWAP_TYPE(state) = boot_validated_swap_type(state, bs);
2048             } else {
2049                 FIH_CALL(boot_validate_slot, fih_rc,
2050                          state, BOOT_SECONDARY_SLOT, bs);
2051                 if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
2052                     BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_FAIL;
2053                 } else {
2054                     BOOT_SWAP_TYPE(state) = bs->swap_type;
2055                 }
2056             }
2057 
2058 #if (BOOT_IMAGE_NUMBER > 1)
2059             boot_review_image_swap_types(state, false);
2060 #endif
2061 
2062 #ifdef MCUBOOT_BOOTSTRAP
2063             if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) {
2064                 /* Header checks are done first because they are
2065                  * inexpensive. Since overwrite-only copies starting from
2066                  * offset 0, if interrupted, it might leave a valid header
2067                  * magic, so also run validation on the primary slot to be
2068                  * sure it's not OK.
2069                  */
2070                 rc = boot_check_header_erased(state, BOOT_PRIMARY_SLOT);
2071                 FIH_CALL(boot_validate_slot, fih_rc,
2072                          state, BOOT_PRIMARY_SLOT, bs);
2073 
2074                 if (rc == 0 || FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
2075 
2076                     rc = (boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_magic == IMAGE_MAGIC) ? 1: 0;
2077                     FIH_CALL(boot_validate_slot, fih_rc,
2078                              state, BOOT_SECONDARY_SLOT, bs);
2079 
2080                     if (rc == 1 && FIH_EQ(fih_rc, FIH_SUCCESS)) {
2081                         /* Set swap type to REVERT to overwrite the primary
2082                          * slot with the image contained in secondary slot
2083                          * and to trigger the explicit setting of the
2084                          * image_ok flag.
2085                          */
2086                         BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_REVERT;
2087                     }
2088                 }
2089             }
2090 #endif
2091         }
2092     } else {
2093         /* In that case if slots are not compatible. */
2094         BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
2095     }
2096 }
2097 
2098 /**
2099  * Updates the security counter for the current image.
2100  *
2101  * @param  state        Boot loader status information.
2102  *
2103  * @return              0 on success; nonzero on failure.
2104  */
2105 static int
2106 boot_update_hw_rollback_protection(struct boot_loader_state *state)
2107 {
2108 #ifdef MCUBOOT_HW_ROLLBACK_PROT
2109     int rc;
2110 
2111     /* Update the stored security counter with the active image's security
2112     * counter value. It will only be updated if the new security counter is
2113     * greater than the stored value.
2114     *
2115     * In case of a successful image swapping when the swap type is TEST the
2116     * security counter can be increased only after a reset, when the swap
2117     * type is NONE and the image has marked itself "OK" (the image_ok flag
2118     * has been set). This way a "revert" can be performed when it's
2119     * necessary.
2120     */
2121     if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) {
2122         rc = boot_update_security_counter(
2123                                 BOOT_CURR_IMG(state),
2124                                 BOOT_PRIMARY_SLOT,
2125                                 boot_img_hdr(state, BOOT_PRIMARY_SLOT));
2126         if (rc != 0) {
2127             BOOT_LOG_ERR("Security counter update failed after image "
2128                             "validation.");
2129             return rc;
2130         }
2131     }
2132 
2133     return 0;
2134 
2135 #else /* MCUBOOT_HW_ROLLBACK_PROT */
2136     (void) (state);
2137 
2138     return 0;
2139 #endif
2140 }
2141 
2142 /**
2143  * Checks test swap downgrade prevention conditions.
2144  *
2145  * Function called only for swap upgrades test run.  It may prevent
2146  * swap if slot 1 image has <= version number or < security counter
2147  *
2148  * @param  state        Boot loader status information.
2149  *
2150  * @return              0 - image can be swapped, -1 downgrade prevention
2151  */
2152 static int
2153 check_downgrade_prevention(struct boot_loader_state *state)
2154 {
2155 #if defined(MCUBOOT_DOWNGRADE_PREVENTION) && \
2156     (defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_SCRATCH))
2157     uint32_t security_counter[2];
2158     int rc;
2159 
2160     if (MCUBOOT_DOWNGRADE_PREVENTION_SECURITY_COUNTER) {
2161         /* If there was security no counter in slot 0, allow swap */
2162         rc = bootutil_get_img_security_cnt(&(BOOT_IMG(state, 0).hdr),
2163                                            BOOT_IMG(state, 0).area,
2164                                            &security_counter[0]);
2165         if (rc != 0) {
2166             return 0;
2167         }
2168         /* If there is no security counter in slot 1, or it's lower than
2169          * that of slot 0, prevent downgrade */
2170         rc = bootutil_get_img_security_cnt(&(BOOT_IMG(state, 1).hdr),
2171                                            BOOT_IMG(state, 1).area,
2172                                            &security_counter[1]);
2173         if (rc != 0 || security_counter[0] > security_counter[1]) {
2174             rc = -1;
2175         }
2176     }
2177     else {
2178         rc = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver,
2179                               &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver);
2180     }
2181     if (rc < 0) {
2182         /* Image in slot 0 prevents downgrade, delete image in slot 1 */
2183         BOOT_LOG_INF("Image %d in slot 1 erased due to downgrade prevention", BOOT_CURR_IMG(state));
2184         flash_area_erase(BOOT_IMG(state, 1).area, 0,
2185                          flash_area_get_size(BOOT_IMG(state, 1).area));
2186     } else {
2187         rc = 0;
2188     }
2189     return rc;
2190 #else
2191     (void)state;
2192     return 0;
2193 #endif
2194 }
2195 
2196 fih_ret
2197 context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
2198 {
2199     size_t slot;
2200     struct boot_status bs;
2201     int rc = -1;
2202     FIH_DECLARE(fih_rc, FIH_FAILURE);
2203     int fa_id;
2204     int image_index;
2205     bool has_upgrade;
2206     volatile int fih_cnt;
2207 
2208 #if defined(__BOOTSIM__)
2209     /* The array of slot sectors are defined here (as opposed to file scope) so
2210      * that they don't get allocated for non-boot-loader apps.  This is
2211      * necessary because the gcc option "-fdata-sections" doesn't seem to have
2212      * any effect in older gcc versions (e.g., 4.8.4).
2213      */
2214     TARGET_STATIC boot_sector_t primary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS];
2215     TARGET_STATIC boot_sector_t secondary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS];
2216 #if MCUBOOT_SWAP_USING_SCRATCH
2217     TARGET_STATIC boot_sector_t scratch_sectors[BOOT_MAX_IMG_SECTORS];
2218 #endif
2219 #endif
2220 
2221     has_upgrade = false;
2222 
2223 #if (BOOT_IMAGE_NUMBER == 1)
2224     (void)has_upgrade;
2225 #endif
2226 
2227     /* Iterate over all the images. By the end of the loop the swap type has
2228      * to be determined for each image and all aborted swaps have to be
2229      * completed.
2230      */
2231     IMAGES_ITER(BOOT_CURR_IMG(state)) {
2232 #if BOOT_IMAGE_NUMBER > 1
2233         if (state->img_mask[BOOT_CURR_IMG(state)]) {
2234             continue;
2235         }
2236 #endif
2237 #if defined(MCUBOOT_ENC_IMAGES) && (BOOT_IMAGE_NUMBER > 1)
2238         /* The keys used for encryption may no longer be valid (could belong to
2239          * another images). Therefore, mark them as invalid to force their reload
2240          * by boot_enc_load().
2241          */
2242         boot_enc_zeroize(BOOT_CURR_ENC(state));
2243 #endif
2244 
2245         image_index = BOOT_CURR_IMG(state);
2246 
2247 #if !defined(__BOOTSIM__)
2248         BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors =
2249             sector_buffers.primary[image_index];
2250         BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors =
2251             sector_buffers.secondary[image_index];
2252 #if MCUBOOT_SWAP_USING_SCRATCH
2253         state->scratch.sectors = sector_buffers.scratch;
2254 #endif
2255 #else
2256         BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors =
2257             primary_slot_sectors[image_index];
2258         BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors =
2259             secondary_slot_sectors[image_index];
2260 #if MCUBOOT_SWAP_USING_SCRATCH
2261         state->scratch.sectors = scratch_sectors;
2262 #endif
2263 #endif
2264 
2265         /* Open primary and secondary image areas for the duration
2266          * of this call.
2267          */
2268         for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
2269             fa_id = flash_area_id_from_multi_image_slot(image_index, slot);
2270             rc = flash_area_open(fa_id, &BOOT_IMG_AREA(state, slot));
2271             assert(rc == 0);
2272 
2273             if (rc != 0) {
2274                 BOOT_LOG_ERR("Failed to open flash area ID %d (image %d slot %d): %d, "
2275                              "cannot continue", fa_id, image_index, (int8_t)slot, rc);
2276                 FIH_PANIC;
2277             }
2278         }
2279 #if MCUBOOT_SWAP_USING_SCRATCH
2280         rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH,
2281                              &BOOT_SCRATCH_AREA(state));
2282         assert(rc == 0);
2283 
2284         if (rc != 0) {
2285             BOOT_LOG_ERR("Failed to open scratch flash area: %d, cannot continue", rc);
2286             FIH_PANIC;
2287         }
2288 #endif
2289 
2290         /* Determine swap type and complete swap if it has been aborted. */
2291         boot_prepare_image_for_update(state, &bs);
2292 
2293         if (BOOT_IS_UPGRADE(BOOT_SWAP_TYPE(state))) {
2294             has_upgrade = true;
2295         }
2296     }
2297 
2298 #if (BOOT_IMAGE_NUMBER > 1)
2299     if (has_upgrade) {
2300         /* Iterate over all the images and verify whether the image dependencies
2301          * are all satisfied and update swap type if necessary.
2302          */
2303         rc = boot_verify_dependencies(state);
2304         if (rc != 0) {
2305             /*
2306              * It was impossible to upgrade because the expected dependency version
2307              * was not available. Here we already changed the swap_type so that
2308              * instead of asserting the bootloader, we continue and no upgrade is
2309              * performed.
2310              */
2311             rc = 0;
2312         }
2313     }
2314 #endif
2315 
2316     /* Trigger status change callback with upgrading status */
2317     mcuboot_status_change(MCUBOOT_STATUS_UPGRADING);
2318 
2319     /* Iterate over all the images. At this point there are no aborted swaps
2320      * and the swap types are determined for each image. By the end of the loop
2321      * all required update operations will have been finished.
2322      */
2323     IMAGES_ITER(BOOT_CURR_IMG(state)) {
2324 #if (BOOT_IMAGE_NUMBER > 1)
2325         if (state->img_mask[BOOT_CURR_IMG(state)]) {
2326             continue;
2327         }
2328 
2329 #ifdef MCUBOOT_ENC_IMAGES
2330         /* The keys used for encryption may no longer be valid (could belong to
2331          * another images). Therefore, mark them as invalid to force their reload
2332          * by boot_enc_load().
2333          */
2334         boot_enc_zeroize(BOOT_CURR_ENC(state));
2335 #endif /* MCUBOOT_ENC_IMAGES */
2336 
2337         /* Indicate that swap is not aborted */
2338         boot_status_reset(&bs);
2339 #endif /* (BOOT_IMAGE_NUMBER > 1) */
2340 
2341         /* Set the previously determined swap type */
2342         bs.swap_type = BOOT_SWAP_TYPE(state);
2343 
2344         switch (BOOT_SWAP_TYPE(state)) {
2345         case BOOT_SWAP_TYPE_NONE:
2346             break;
2347 
2348         case BOOT_SWAP_TYPE_TEST:
2349             /* fallthrough */
2350         case BOOT_SWAP_TYPE_PERM:
2351             if (check_downgrade_prevention(state) != 0) {
2352                 /* Downgrade prevented */
2353                 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
2354                 break;
2355             }
2356             /* fallthrough */
2357         case BOOT_SWAP_TYPE_REVERT:
2358             rc = BOOT_HOOK_CALL(boot_perform_update_hook, BOOT_HOOK_REGULAR,
2359                                 BOOT_CURR_IMG(state), &(BOOT_IMG(state, 1).hdr),
2360                                 BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT));
2361             if (rc == BOOT_HOOK_REGULAR)
2362             {
2363                 rc = boot_perform_update(state, &bs);
2364             }
2365             assert(rc == 0);
2366             break;
2367 
2368         case BOOT_SWAP_TYPE_FAIL:
2369             /* The image in secondary slot was invalid and is now erased. Ensure
2370              * we don't try to boot into it again on the next reboot. Do this by
2371              * pretending we just reverted back to primary slot.
2372              */
2373 #ifndef MCUBOOT_OVERWRITE_ONLY
2374             /* image_ok needs to be explicitly set to avoid a new revert. */
2375             rc = swap_set_image_ok(BOOT_CURR_IMG(state));
2376             if (rc != 0) {
2377                 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
2378             }
2379 #endif /* !MCUBOOT_OVERWRITE_ONLY */
2380             break;
2381 
2382         default:
2383             BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
2384         }
2385 
2386         if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_PANIC) {
2387             BOOT_LOG_ERR("panic!");
2388             assert(0);
2389 
2390             /* Loop forever... */
2391             FIH_PANIC;
2392         }
2393     }
2394 
2395     /* Iterate over all the images. At this point all required update operations
2396      * have finished. By the end of the loop each image in the primary slot will
2397      * have been re-validated.
2398      */
2399     FIH_SET(fih_cnt, 0);
2400     IMAGES_ITER(BOOT_CURR_IMG(state)) {
2401 #if BOOT_IMAGE_NUMBER > 1
2402         /* Hardenned to prevent from skipping check of a given image,
2403          * tmp_img_mask is declared volatile
2404          */
2405         volatile bool tmp_img_mask;
2406         FIH_SET(tmp_img_mask, state->img_mask[BOOT_CURR_IMG(state)]);
2407         if (FIH_EQ(tmp_img_mask, true)) {
2408             ++fih_cnt;
2409             continue;
2410         }
2411 #endif
2412         if (BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_NONE) {
2413             /* Attempt to read an image header from each slot. Ensure that image
2414              * headers in slots are aligned with headers in boot_data.
2415 	     * Note: Quite complicated internal logic of boot_read_image_headers
2416 	     * uses boot state, the last parm, to figure out in which slot which
2417 	     * header is located; when boot state is not provided, then it
2418 	     * is assumed that headers are at proper slots (we are not in
2419 	     * the middle of moving images, etc).
2420              */
2421             rc = boot_read_image_headers(state, false, NULL);
2422             if (rc != 0) {
2423                 FIH_SET(fih_rc, FIH_FAILURE);
2424                 goto out;
2425             }
2426             /* Since headers were reloaded, it can be assumed we just performed
2427              * a swap or overwrite. Now the header info that should be used to
2428              * provide the data for the bootstrap, which previously was at
2429              * secondary slot, was updated to primary slot.
2430              */
2431         }
2432 
2433 #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
2434         FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, NULL);
2435         /* Check for all possible values is redundant in normal operation it
2436          * is meant to prevent FI attack.
2437          */
2438         if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS) ||
2439             FIH_EQ(fih_rc, FIH_FAILURE) ||
2440             FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) {
2441             FIH_SET(fih_rc, FIH_FAILURE);
2442             goto out;
2443         }
2444 #else
2445         /* Even if we're not re-validating the primary slot, we could be booting
2446          * onto an empty flash chip. At least do a basic sanity check that
2447          * the magic number on the image is OK.
2448          */
2449         if (BOOT_IMG(state, BOOT_PRIMARY_SLOT).hdr.ih_magic != IMAGE_MAGIC) {
2450             BOOT_LOG_ERR("bad image magic 0x%lx; Image=%u", (unsigned long)
2451                          BOOT_IMG(state, BOOT_PRIMARY_SLOT).hdr.ih_magic,
2452                          BOOT_CURR_IMG(state));
2453             rc = BOOT_EBADIMAGE;
2454             FIH_SET(fih_rc, FIH_FAILURE);
2455             goto out;
2456         }
2457 #endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */
2458 
2459         rc = boot_update_hw_rollback_protection(state);
2460         if (rc != 0) {
2461             FIH_SET(fih_rc, FIH_FAILURE);
2462             goto out;
2463         }
2464 
2465         rc = boot_add_shared_data(state, BOOT_PRIMARY_SLOT);
2466         if (rc != 0) {
2467             FIH_SET(fih_rc, FIH_FAILURE);
2468             goto out;
2469         }
2470         ++fih_cnt;
2471     }
2472     /*
2473      * fih_cnt should be equal to BOOT_IMAGE_NUMBER now.
2474      * If this is not the case, at least one iteration of the loop
2475      * has been skipped.
2476      */
2477     if(FIH_NOT_EQ(fih_cnt, BOOT_IMAGE_NUMBER)) {
2478         FIH_PANIC;
2479     }
2480 
2481     fill_rsp(state, rsp);
2482 
2483     fih_rc = FIH_SUCCESS;
2484 out:
2485     /*
2486      * Since the boot_status struct stores plaintext encryption keys, reset
2487      * them here to avoid the possibility of jumping into an image that could
2488      * easily recover them.
2489      */
2490 #if defined(MCUBOOT_ENC_IMAGES) || defined(MCUBOOT_SWAP_SAVE_ENCTLV)
2491     like_mbedtls_zeroize(&bs, sizeof(bs));
2492 #else
2493     memset(&bs, 0, sizeof(struct boot_status));
2494 #endif
2495 
2496     close_all_flash_areas(state);
2497     FIH_RET(fih_rc);
2498 }
2499 
2500 fih_ret
2501 split_go(int loader_slot, int split_slot, void **entry)
2502 {
2503     boot_sector_t *sectors;
2504     uintptr_t entry_val;
2505     int loader_flash_id;
2506     int split_flash_id;
2507     int rc;
2508     FIH_DECLARE(fih_rc, FIH_FAILURE);
2509 
2510     sectors = malloc(BOOT_MAX_IMG_SECTORS * 2 * sizeof *sectors);
2511     if (sectors == NULL) {
2512         FIH_RET(FIH_FAILURE);
2513     }
2514     BOOT_IMG(&boot_data, loader_slot).sectors = sectors + 0;
2515     BOOT_IMG(&boot_data, split_slot).sectors = sectors + BOOT_MAX_IMG_SECTORS;
2516 
2517     loader_flash_id = flash_area_id_from_image_slot(loader_slot);
2518     rc = flash_area_open(loader_flash_id,
2519                          &BOOT_IMG_AREA(&boot_data, loader_slot));
2520     assert(rc == 0);
2521     split_flash_id = flash_area_id_from_image_slot(split_slot);
2522     rc = flash_area_open(split_flash_id,
2523                          &BOOT_IMG_AREA(&boot_data, split_slot));
2524     assert(rc == 0);
2525 
2526     /* Determine the sector layout of the image slots and scratch area. */
2527     rc = boot_read_sectors(&boot_data);
2528     if (rc != 0) {
2529         rc = SPLIT_GO_ERR;
2530         goto done;
2531     }
2532 
2533     rc = boot_read_image_headers(&boot_data, true, NULL);
2534     if (rc != 0) {
2535         goto done;
2536     }
2537 
2538     /* Don't check the bootable image flag because we could really call a
2539      * bootable or non-bootable image.  Just validate that the image check
2540      * passes which is distinct from the normal check.
2541      */
2542     FIH_CALL(split_image_check, fih_rc,
2543              boot_img_hdr(&boot_data, split_slot),
2544              BOOT_IMG_AREA(&boot_data, split_slot),
2545              boot_img_hdr(&boot_data, loader_slot),
2546              BOOT_IMG_AREA(&boot_data, loader_slot));
2547     if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
2548         goto done;
2549     }
2550 
2551     entry_val = boot_img_slot_off(&boot_data, split_slot) +
2552                 boot_img_hdr(&boot_data, split_slot)->ih_hdr_size;
2553     *entry = (void *) entry_val;
2554     rc = SPLIT_GO_OK;
2555 
2556 done:
2557     flash_area_close(BOOT_IMG_AREA(&boot_data, split_slot));
2558     flash_area_close(BOOT_IMG_AREA(&boot_data, loader_slot));
2559     free(sectors);
2560 
2561     if (rc) {
2562         FIH_SET(fih_rc, FIH_FAILURE);
2563     }
2564 
2565     FIH_RET(fih_rc);
2566 }
2567 
2568 #else /* MCUBOOT_DIRECT_XIP || MCUBOOT_RAM_LOAD */
2569 
2570 /**
2571  * Opens all flash areas and checks which contain an image with a valid header.
2572  *
2573  * @param  state        Boot loader status information.
2574  *
2575  * @return              0 on success; nonzero on failure.
2576  */
2577 static int
2578 boot_get_slot_usage(struct boot_loader_state *state)
2579 {
2580     uint32_t slot;
2581     int fa_id;
2582     int rc;
2583     struct image_header *hdr = NULL;
2584 
2585     IMAGES_ITER(BOOT_CURR_IMG(state)) {
2586 #if BOOT_IMAGE_NUMBER > 1
2587         if (state->img_mask[BOOT_CURR_IMG(state)]) {
2588             continue;
2589         }
2590 #endif
2591         /* Open all the slots */
2592         for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
2593             fa_id = flash_area_id_from_multi_image_slot(
2594                                                 BOOT_CURR_IMG(state), slot);
2595             rc = flash_area_open(fa_id, &BOOT_IMG_AREA(state, slot));
2596             assert(rc == 0);
2597         }
2598 
2599         /* Attempt to read an image header from each slot. */
2600         rc = boot_read_image_headers(state, false, NULL);
2601         if (rc != 0) {
2602             BOOT_LOG_WRN("Failed reading image headers.");
2603             return rc;
2604         }
2605 
2606         /* Check headers in all slots */
2607         for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
2608             hdr = boot_img_hdr(state, slot);
2609 
2610             if (boot_is_header_valid(hdr, BOOT_IMG_AREA(state, slot), state)) {
2611                 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = true;
2612                 BOOT_LOG_IMAGE_INFO(slot, hdr);
2613             } else {
2614                 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = false;
2615                 BOOT_LOG_INF("Image %d %s slot: Image not found",
2616                              BOOT_CURR_IMG(state),
2617                              (slot == BOOT_PRIMARY_SLOT)
2618                              ? "Primary" : "Secondary");
2619             }
2620         }
2621 
2622         state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
2623     }
2624 
2625     return 0;
2626 }
2627 
2628 /**
2629  * Finds the slot containing the image with the highest version number for the
2630  * current image.
2631  *
2632  * @param  state        Boot loader status information.
2633  *
2634  * @return              NO_ACTIVE_SLOT if no available slot found, number of
2635  *                      the found slot otherwise.
2636  */
2637 static uint32_t
2638 find_slot_with_highest_version(struct boot_loader_state *state)
2639 {
2640     uint32_t slot;
2641     uint32_t candidate_slot = NO_ACTIVE_SLOT;
2642     int rc;
2643 
2644     for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
2645         if (state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot]) {
2646             if (candidate_slot == NO_ACTIVE_SLOT) {
2647                 candidate_slot = slot;
2648             } else {
2649                 rc = boot_version_cmp(
2650                             &boot_img_hdr(state, slot)->ih_ver,
2651                             &boot_img_hdr(state, candidate_slot)->ih_ver);
2652                 if (rc == 1) {
2653                     /* The version of the image being examined is greater than
2654                      * the version of the current candidate.
2655                      */
2656                     candidate_slot = slot;
2657                 }
2658             }
2659         }
2660     }
2661 
2662     return candidate_slot;
2663 }
2664 
2665 #ifdef MCUBOOT_HAVE_LOGGING
2666 /**
2667  * Prints the state of the loaded images.
2668  *
2669  * @param  state        Boot loader status information.
2670  */
2671 static void
2672 print_loaded_images(struct boot_loader_state *state)
2673 {
2674     uint32_t active_slot;
2675 
2676     (void)state;
2677 
2678     IMAGES_ITER(BOOT_CURR_IMG(state)) {
2679 #if BOOT_IMAGE_NUMBER > 1
2680         if (state->img_mask[BOOT_CURR_IMG(state)]) {
2681             continue;
2682         }
2683 #endif
2684         active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
2685 
2686         BOOT_LOG_INF("Image %d loaded from the %s slot",
2687                      BOOT_CURR_IMG(state),
2688                      (active_slot == BOOT_PRIMARY_SLOT) ?
2689                      "primary" : "secondary");
2690     }
2691 }
2692 #endif
2693 
2694 #if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT)
2695 /**
2696  * Checks whether the active slot of the current image was previously selected
2697  * to run. Erases the image if it was selected but its execution failed,
2698  * otherwise marks it as selected if it has not been before.
2699  *
2700  * @param  state        Boot loader status information.
2701  *
2702  * @return              0 on success; nonzero on failure.
2703  */
2704 static int
2705 boot_select_or_erase(struct boot_loader_state *state)
2706 {
2707     const struct flash_area *fap;
2708     int fa_id;
2709     int rc;
2710     uint32_t active_slot;
2711     struct boot_swap_state* active_swap_state;
2712 
2713     active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
2714 
2715     fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), active_slot);
2716     rc = flash_area_open(fa_id, &fap);
2717     assert(rc == 0);
2718 
2719     active_swap_state = &(state->slot_usage[BOOT_CURR_IMG(state)].swap_state);
2720 
2721     memset(active_swap_state, 0, sizeof(struct boot_swap_state));
2722     rc = boot_read_swap_state(fap, active_swap_state);
2723     assert(rc == 0);
2724 
2725     if (active_swap_state->magic != BOOT_MAGIC_GOOD ||
2726         (active_swap_state->copy_done == BOOT_FLAG_SET &&
2727          active_swap_state->image_ok  != BOOT_FLAG_SET)) {
2728         /*
2729          * A reboot happened without the image being confirmed at
2730          * runtime or its trailer is corrupted/invalid. Erase the image
2731          * to prevent it from being selected again on the next reboot.
2732          */
2733         BOOT_LOG_DBG("Erasing faulty image in the %s slot.",
2734                      (active_slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary");
2735         rc = flash_area_erase(fap, 0, flash_area_get_size(fap));
2736         assert(rc == 0);
2737 
2738         flash_area_close(fap);
2739         rc = -1;
2740     } else {
2741         if (active_swap_state->copy_done != BOOT_FLAG_SET) {
2742             if (active_swap_state->copy_done == BOOT_FLAG_BAD) {
2743                 BOOT_LOG_DBG("The copy_done flag had an unexpected value. Its "
2744                              "value was neither 'set' nor 'unset', but 'bad'.");
2745             }
2746             /*
2747              * Set the copy_done flag, indicating that the image has been
2748              * selected to boot. It can be set in advance, before even
2749              * validating the image, because in case the validation fails, the
2750              * entire image slot will be erased (including the trailer).
2751              */
2752             rc = boot_write_copy_done(fap);
2753             if (rc != 0) {
2754                 BOOT_LOG_WRN("Failed to set copy_done flag of the image in "
2755                              "the %s slot.", (active_slot == BOOT_PRIMARY_SLOT) ?
2756                              "primary" : "secondary");
2757                 rc = 0;
2758             }
2759         }
2760         flash_area_close(fap);
2761     }
2762 
2763     return rc;
2764 }
2765 #endif /* MCUBOOT_DIRECT_XIP && MCUBOOT_DIRECT_XIP_REVERT */
2766 
2767 #ifdef MCUBOOT_RAM_LOAD
2768 
2769 #ifndef MULTIPLE_EXECUTABLE_RAM_REGIONS
2770 #if !defined(IMAGE_EXECUTABLE_RAM_START) || !defined(IMAGE_EXECUTABLE_RAM_SIZE)
2771 #error "Platform MUST define executable RAM bounds in case of RAM_LOAD"
2772 #endif
2773 #endif
2774 
2775 /**
2776  * Verifies that the active slot of the current image can be loaded within the
2777  * predefined bounds that are allowed to be used by executable images.
2778  *
2779  * @param  state        Boot loader status information.
2780  *
2781  * @return              0 on success; nonzero on failure.
2782  */
2783 static int
2784 boot_verify_ram_load_address(struct boot_loader_state *state)
2785 {
2786     uint32_t img_dst;
2787     uint32_t img_sz;
2788     uint32_t img_end_addr;
2789     uint32_t exec_ram_start;
2790     uint32_t exec_ram_size;
2791 
2792     (void)state;
2793 
2794 #ifdef MULTIPLE_EXECUTABLE_RAM_REGIONS
2795     int      rc;
2796 
2797     rc = boot_get_image_exec_ram_info(BOOT_CURR_IMG(state), &exec_ram_start,
2798                                       &exec_ram_size);
2799     if (rc != 0) {
2800         return BOOT_EBADSTATUS;
2801     }
2802 #else
2803     exec_ram_start = IMAGE_EXECUTABLE_RAM_START;
2804     exec_ram_size = IMAGE_EXECUTABLE_RAM_SIZE;
2805 #endif
2806 
2807     img_dst = state->slot_usage[BOOT_CURR_IMG(state)].img_dst;
2808     img_sz = state->slot_usage[BOOT_CURR_IMG(state)].img_sz;
2809 
2810     if (img_dst < exec_ram_start) {
2811         return BOOT_EBADIMAGE;
2812     }
2813 
2814     if (!boot_u32_safe_add(&img_end_addr, img_dst, img_sz)) {
2815         return BOOT_EBADIMAGE;
2816     }
2817 
2818     if (img_end_addr > (exec_ram_start + exec_ram_size)) {
2819         return BOOT_EBADIMAGE;
2820     }
2821 
2822     return 0;
2823 }
2824 
2825 #ifdef MCUBOOT_ENC_IMAGES
2826 
2827 /**
2828  * Copies and decrypts an image from a slot in the flash to an SRAM address.
2829  *
2830  * @param  state    Boot loader status information.
2831  * @param  slot     The flash slot of the image to be copied to SRAM.
2832  * @param  hdr      The image header.
2833  * @param  src_sz   Size of the image.
2834  * @param  img_dst  Pointer to the address at which the image needs to be
2835  *                  copied to SRAM.
2836  *
2837  * @return          0 on success; nonzero on failure.
2838  */
2839 static int
2840 boot_decrypt_and_copy_image_to_sram(struct boot_loader_state *state,
2841                                     uint32_t slot, struct image_header *hdr,
2842                                     uint32_t src_sz, uint32_t img_dst)
2843 {
2844     /* The flow for the decryption and copy of the image is as follows :
2845      * 1. The whole image is copied to the RAM (header + payload + TLV).
2846      * 2. The encryption key is loaded from the TLV in flash.
2847      * 3. The image is then decrypted chunk by chunk in RAM (1 chunk
2848      * is 1024 bytes). Only the payload section is decrypted.
2849      * 4. The image is authenticated in RAM.
2850      */
2851     const struct flash_area *fap_src = NULL;
2852     struct boot_status bs;
2853     uint32_t blk_off;
2854     uint32_t tlv_off;
2855     uint32_t blk_sz;
2856     uint32_t bytes_copied = hdr->ih_hdr_size;
2857     uint32_t chunk_sz;
2858     uint32_t max_sz = 1024;
2859     uint16_t idx;
2860     uint8_t * cur_dst;
2861     int area_id;
2862     int rc;
2863     uint8_t * ram_dst = (void *)(IMAGE_RAM_BASE + img_dst);
2864 
2865     area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
2866     rc = flash_area_open(area_id, &fap_src);
2867     if (rc != 0){
2868         return BOOT_EFLASH;
2869     }
2870 
2871     tlv_off = BOOT_TLV_OFF(hdr);
2872 
2873     /* Copying the whole image in RAM */
2874     rc = flash_area_read(fap_src, 0, ram_dst, src_sz);
2875     if (rc != 0) {
2876         goto done;
2877     }
2878 
2879     rc = boot_enc_load(BOOT_CURR_ENC(state), slot, hdr, fap_src, &bs);
2880     if (rc < 0) {
2881         goto done;
2882     }
2883 
2884     /* if rc > 0 then the key has already been loaded */
2885     if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), slot, &bs)) {
2886         goto done;
2887     }
2888 
2889     /* Starting at the end of the header as the header section is not encrypted */
2890     while (bytes_copied < tlv_off) { /* TLV section copied previously */
2891         if (src_sz - bytes_copied > max_sz) {
2892             chunk_sz = max_sz;
2893         } else {
2894             chunk_sz = src_sz - bytes_copied;
2895         }
2896 
2897         cur_dst = ram_dst + bytes_copied;
2898         blk_sz = chunk_sz;
2899         idx = 0;
2900         blk_off = ((bytes_copied) - hdr->ih_hdr_size) & 0xf;
2901         if (bytes_copied + chunk_sz > tlv_off) {
2902             /* Going over TLV section
2903              * Part of the chunk is encrypted payload */
2904             blk_sz = tlv_off - (bytes_copied);
2905         }
2906         boot_enc_decrypt(BOOT_CURR_ENC(state), slot,
2907                 (bytes_copied + idx) - hdr->ih_hdr_size, blk_sz,
2908                 blk_off, cur_dst);
2909         bytes_copied += chunk_sz;
2910     }
2911     rc = 0;
2912 
2913 done:
2914     flash_area_close(fap_src);
2915 
2916     return rc;
2917 }
2918 
2919 #endif /* MCUBOOT_ENC_IMAGES */
2920 /**
2921  * Copies a slot of the current image into SRAM.
2922  *
2923  * @param  state    Boot loader status information.
2924  * @param  slot     The flash slot of the image to be copied to SRAM.
2925  * @param  img_dst  The address at which the image needs to be copied to
2926  *                  SRAM.
2927  * @param  img_sz   The size of the image that needs to be copied to SRAM.
2928  *
2929  * @return          0 on success; nonzero on failure.
2930  */
2931 static int
2932 boot_copy_image_to_sram(struct boot_loader_state *state, int slot,
2933                         uint32_t img_dst, uint32_t img_sz)
2934 {
2935     int rc;
2936     const struct flash_area *fap_src = NULL;
2937     int area_id;
2938 
2939 #if (BOOT_IMAGE_NUMBER == 1)
2940     (void)state;
2941 #endif
2942 
2943     area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
2944 
2945     rc = flash_area_open(area_id, &fap_src);
2946     if (rc != 0) {
2947         return BOOT_EFLASH;
2948     }
2949 
2950     /* Direct copy from flash to its new location in SRAM. */
2951     rc = flash_area_read(fap_src, 0, (void *)(IMAGE_RAM_BASE + img_dst), img_sz);
2952     if (rc != 0) {
2953         BOOT_LOG_INF("Error whilst copying image %d from Flash to SRAM: %d",
2954                      BOOT_CURR_IMG(state), rc);
2955     }
2956 
2957     flash_area_close(fap_src);
2958 
2959     return rc;
2960 }
2961 
2962 #if (BOOT_IMAGE_NUMBER > 1)
2963 /**
2964  * Checks if two memory regions (A and B) are overlap or not.
2965  *
2966  * @param  start_a  Start of the A region.
2967  * @param  end_a    End of the A region.
2968  * @param  start_b  Start of the B region.
2969  * @param  end_b    End of the B region.
2970  *
2971  * @return          true if there is overlap; false otherwise.
2972  */
2973 static bool
2974 do_regions_overlap(uint32_t start_a, uint32_t end_a,
2975                    uint32_t start_b, uint32_t end_b)
2976 {
2977     if (start_b > end_a) {
2978         return false;
2979     } else if (start_b >= start_a) {
2980         return true;
2981     } else if (end_b > start_a) {
2982         return true;
2983     }
2984 
2985     return false;
2986 }
2987 
2988 /**
2989  * Checks if the image we want to load to memory overlap with an already
2990  * ramloaded image.
2991  *
2992  * @param  state    Boot loader status information.
2993  *
2994  * @return                    0 if there is no overlap; nonzero otherwise.
2995  */
2996 static int
2997 boot_check_ram_load_overlapping(struct boot_loader_state *state)
2998 {
2999     uint32_t i;
3000 
3001     uint32_t start_a;
3002     uint32_t end_a;
3003     uint32_t start_b;
3004     uint32_t end_b;
3005     uint32_t image_id_to_check = BOOT_CURR_IMG(state);
3006 
3007     start_a = state->slot_usage[image_id_to_check].img_dst;
3008     /* Safe to add here, values are already verified in
3009      * boot_verify_ram_load_address() */
3010     end_a = start_a + state->slot_usage[image_id_to_check].img_sz;
3011 
3012     for (i = 0; i < BOOT_IMAGE_NUMBER; i++) {
3013         if (state->slot_usage[i].active_slot == NO_ACTIVE_SLOT
3014             || i == image_id_to_check) {
3015             continue;
3016         }
3017 
3018         start_b = state->slot_usage[i].img_dst;
3019         /* Safe to add here, values are already verified in
3020          * boot_verify_ram_load_address() */
3021         end_b = start_b + state->slot_usage[i].img_sz;
3022 
3023         if (do_regions_overlap(start_a, end_a, start_b, end_b)) {
3024             return -1;
3025         }
3026     }
3027 
3028     return 0;
3029 }
3030 #endif
3031 
3032 /**
3033  * Loads the active slot of the current image into SRAM. The load address and
3034  * image size is extracted from the image header.
3035  *
3036  * @param  state        Boot loader status information.
3037  *
3038  * @return              0 on success; nonzero on failure.
3039  */
3040 static int
3041 boot_load_image_to_sram(struct boot_loader_state *state)
3042 {
3043     uint32_t active_slot;
3044     struct image_header *hdr = NULL;
3045     uint32_t img_dst;
3046     uint32_t img_sz;
3047     int rc;
3048 
3049     active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
3050     hdr = boot_img_hdr(state, active_slot);
3051 
3052     if (hdr->ih_flags & IMAGE_F_RAM_LOAD) {
3053 
3054         img_dst = hdr->ih_load_addr;
3055 
3056         rc = boot_read_image_size(state, active_slot, &img_sz);
3057         if (rc != 0) {
3058             return rc;
3059         }
3060 
3061         state->slot_usage[BOOT_CURR_IMG(state)].img_dst = img_dst;
3062         state->slot_usage[BOOT_CURR_IMG(state)].img_sz = img_sz;
3063 
3064         rc = boot_verify_ram_load_address(state);
3065         if (rc != 0) {
3066             BOOT_LOG_INF("Image %d RAM load address 0x%x is invalid.", BOOT_CURR_IMG(state), img_dst);
3067             return rc;
3068         }
3069 
3070 #if (BOOT_IMAGE_NUMBER > 1)
3071         rc = boot_check_ram_load_overlapping(state);
3072         if (rc != 0) {
3073             BOOT_LOG_INF("Image %d RAM loading to address 0x%x would overlap with\
3074                          another image.", BOOT_CURR_IMG(state), img_dst);
3075             return rc;
3076         }
3077 #endif
3078 #ifdef MCUBOOT_ENC_IMAGES
3079         /* decrypt image if encrypted and copy it to RAM */
3080         if (IS_ENCRYPTED(hdr)) {
3081             rc = boot_decrypt_and_copy_image_to_sram(state, active_slot, hdr, img_sz, img_dst);
3082         } else {
3083             rc = boot_copy_image_to_sram(state, active_slot, img_dst, img_sz);
3084         }
3085 #else
3086         /* Copy image to the load address from where it currently resides in
3087          * flash.
3088          */
3089         rc = boot_copy_image_to_sram(state, active_slot, img_dst, img_sz);
3090 #endif
3091         if (rc != 0) {
3092             BOOT_LOG_INF("Image %d RAM loading to 0x%x is failed.", BOOT_CURR_IMG(state), img_dst);
3093         } else {
3094             BOOT_LOG_INF("Image %d RAM loading to 0x%x is succeeded.", BOOT_CURR_IMG(state), img_dst);
3095         }
3096     } else {
3097         /* Only images that support IMAGE_F_RAM_LOAD are allowed if
3098          * MCUBOOT_RAM_LOAD is set.
3099          */
3100         rc = BOOT_EBADIMAGE;
3101     }
3102 
3103     if (rc != 0) {
3104         state->slot_usage[BOOT_CURR_IMG(state)].img_dst = 0;
3105         state->slot_usage[BOOT_CURR_IMG(state)].img_sz = 0;
3106     }
3107 
3108     return rc;
3109 }
3110 
3111 /**
3112  * Removes an image from SRAM, by overwriting it with zeros.
3113  *
3114  * @param  state        Boot loader status information.
3115  *
3116  * @return              0 on success; nonzero on failure.
3117  */
3118 static inline int
3119 boot_remove_image_from_sram(struct boot_loader_state *state)
3120 {
3121     (void)state;
3122 
3123     BOOT_LOG_INF("Removing image %d from SRAM at address 0x%x",
3124                  BOOT_CURR_IMG(state),
3125                  state->slot_usage[BOOT_CURR_IMG(state)].img_dst);
3126 
3127     memset((void*)(IMAGE_RAM_BASE + state->slot_usage[BOOT_CURR_IMG(state)].img_dst),
3128            0, state->slot_usage[BOOT_CURR_IMG(state)].img_sz);
3129 
3130     state->slot_usage[BOOT_CURR_IMG(state)].img_dst = 0;
3131     state->slot_usage[BOOT_CURR_IMG(state)].img_sz = 0;
3132 
3133     return 0;
3134 }
3135 
3136 /**
3137  * Removes an image from flash by erasing the corresponding flash area
3138  *
3139  * @param  state    Boot loader status information.
3140  * @param  slot     The flash slot of the image to be erased.
3141  *
3142  * @return          0 on success; nonzero on failure.
3143  */
3144 static inline int
3145 boot_remove_image_from_flash(struct boot_loader_state *state, uint32_t slot)
3146 {
3147     int area_id;
3148     int rc;
3149     const struct flash_area *fap;
3150 
3151     (void)state;
3152 
3153     BOOT_LOG_INF("Removing image %d slot %d from flash", BOOT_CURR_IMG(state),
3154                                                          slot);
3155     area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
3156     rc = flash_area_open(area_id, &fap);
3157     if (rc == 0) {
3158         flash_area_erase(fap, 0, flash_area_get_size(fap));
3159         flash_area_close(fap);
3160     }
3161 
3162     return rc;
3163 }
3164 #endif /* MCUBOOT_RAM_LOAD */
3165 
3166 
3167 /**
3168  * Tries to load a slot for all the images with validation.
3169  *
3170  * @param  state        Boot loader status information.
3171  *
3172  * @return              0 on success; nonzero on failure.
3173  */
3174 fih_ret
3175 boot_load_and_validate_images(struct boot_loader_state *state)
3176 {
3177     uint32_t active_slot;
3178     int rc;
3179     fih_ret fih_rc;
3180 
3181     /* Go over all the images and try to load one */
3182     IMAGES_ITER(BOOT_CURR_IMG(state)) {
3183         /* All slots tried until a valid image found. Breaking from this loop
3184          * means that a valid image found or already loaded. If no slot is
3185          * found the function returns with error code. */
3186         while (true) {
3187             /* Go over all the slots and try to load one */
3188             active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
3189             if (active_slot != NO_ACTIVE_SLOT){
3190                 /* A slot is already active, go to next image. */
3191                 break;
3192             }
3193 
3194             active_slot = find_slot_with_highest_version(state);
3195             if (active_slot == NO_ACTIVE_SLOT) {
3196                 BOOT_LOG_INF("No slot to load for image %d",
3197                              BOOT_CURR_IMG(state));
3198                 FIH_RET(FIH_FAILURE);
3199             }
3200 
3201             /* Save the number of the active slot. */
3202             state->slot_usage[BOOT_CURR_IMG(state)].active_slot = active_slot;
3203 
3204 #if BOOT_IMAGE_NUMBER > 1
3205         if (state->img_mask[BOOT_CURR_IMG(state)]) {
3206             continue;
3207         }
3208 #endif
3209 
3210 #ifdef MCUBOOT_DIRECT_XIP
3211             rc = boot_rom_address_check(state);
3212             if (rc != 0) {
3213                 /* The image is placed in an unsuitable slot. */
3214                 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
3215                 state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
3216                 continue;
3217             }
3218 
3219 #ifdef MCUBOOT_DIRECT_XIP_REVERT
3220             rc = boot_select_or_erase(state);
3221             if (rc != 0) {
3222                 /* The selected image slot has been erased. */
3223                 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
3224                 state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
3225                 continue;
3226             }
3227 #endif /* MCUBOOT_DIRECT_XIP_REVERT */
3228 #endif /* MCUBOOT_DIRECT_XIP */
3229 
3230 #ifdef MCUBOOT_RAM_LOAD
3231             /* Image is first loaded to RAM and authenticated there in order to
3232              * prevent TOCTOU attack during image copy. This could be applied
3233              * when loading images from external (untrusted) flash to internal
3234              * (trusted) RAM and image is authenticated before copying.
3235              */
3236             rc = boot_load_image_to_sram(state);
3237             if (rc != 0 ) {
3238                 /* Image cannot be ramloaded. */
3239                 boot_remove_image_from_flash(state, active_slot);
3240                 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
3241                 state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
3242                 continue;
3243             }
3244 #endif /* MCUBOOT_RAM_LOAD */
3245 
3246             FIH_CALL(boot_validate_slot, fih_rc, state, active_slot, NULL);
3247             if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
3248                 /* Image is invalid. */
3249 #ifdef MCUBOOT_RAM_LOAD
3250                 boot_remove_image_from_sram(state);
3251 #endif /* MCUBOOT_RAM_LOAD */
3252                 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
3253                 state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
3254                 continue;
3255             }
3256 
3257             /* Valid image loaded from a slot, go to next image. */
3258             break;
3259         }
3260     }
3261 
3262     FIH_RET(FIH_SUCCESS);
3263 }
3264 
3265 /**
3266  * Updates the security counter for the current image.
3267  *
3268  * @param  state        Boot loader status information.
3269  *
3270  * @return              0 on success; nonzero on failure.
3271  */
3272 static int
3273 boot_update_hw_rollback_protection(struct boot_loader_state *state)
3274 {
3275 #ifdef MCUBOOT_HW_ROLLBACK_PROT
3276     int rc;
3277 
3278     /* Update the stored security counter with the newer (active) image's
3279      * security counter value.
3280      */
3281 #if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT)
3282     /* When the 'revert' mechanism is enabled in direct-xip mode, the
3283      * security counter can be increased only after reboot, if the image
3284      * has been confirmed at runtime (the image_ok flag has been set).
3285      * This way a 'revert' can be performed when it's necessary.
3286      */
3287     if (state->slot_usage[BOOT_CURR_IMG(state)].swap_state.image_ok == BOOT_FLAG_SET) {
3288 #endif
3289         rc = boot_update_security_counter(BOOT_CURR_IMG(state),
3290                                           state->slot_usage[BOOT_CURR_IMG(state)].active_slot,
3291                                           boot_img_hdr(state, state->slot_usage[BOOT_CURR_IMG(state)].active_slot));
3292         if (rc != 0) {
3293             BOOT_LOG_ERR("Security counter update failed after image %d validation.", BOOT_CURR_IMG(state));
3294             return rc;
3295         }
3296 #if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT)
3297     }
3298 #endif
3299 
3300     return 0;
3301 
3302 #else /* MCUBOOT_HW_ROLLBACK_PROT */
3303     (void) (state);
3304     return 0;
3305 #endif
3306 }
3307 
3308 fih_ret
3309 context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
3310 {
3311     int rc;
3312     FIH_DECLARE(fih_rc, FIH_FAILURE);
3313 
3314     rc = boot_get_slot_usage(state);
3315     if (rc != 0) {
3316         goto out;
3317     }
3318 
3319 #if (BOOT_IMAGE_NUMBER > 1)
3320     while (true) {
3321 #endif
3322         FIH_CALL(boot_load_and_validate_images, fih_rc, state);
3323         if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
3324             FIH_SET(fih_rc, FIH_FAILURE);
3325             goto out;
3326         }
3327 
3328 #if (BOOT_IMAGE_NUMBER > 1)
3329         rc = boot_verify_dependencies(state);
3330         if (rc != 0) {
3331             /* Dependency check failed for an image, it has been removed from
3332              * SRAM in case of MCUBOOT_RAM_LOAD strategy, and set to
3333              * unavailable. Try to load an image from another slot.
3334              */
3335             continue;
3336         }
3337         /* Dependency check was successful. */
3338         break;
3339     }
3340 #endif
3341 
3342     IMAGES_ITER(BOOT_CURR_IMG(state)) {
3343 #if BOOT_IMAGE_NUMBER > 1
3344         if (state->img_mask[BOOT_CURR_IMG(state)]) {
3345             continue;
3346         }
3347 #endif
3348         rc = boot_update_hw_rollback_protection(state);
3349         if (rc != 0) {
3350             FIH_SET(fih_rc, FIH_FAILURE);
3351             goto out;
3352         }
3353 
3354         rc = boot_add_shared_data(state, (uint8_t)state->slot_usage[BOOT_CURR_IMG(state)].active_slot);
3355         if (rc != 0) {
3356             FIH_SET(fih_rc, FIH_FAILURE);
3357             goto out;
3358         }
3359     }
3360 
3361     /* All image loaded successfully. */
3362 #ifdef MCUBOOT_HAVE_LOGGING
3363     print_loaded_images(state);
3364 #endif
3365 
3366     fill_rsp(state, rsp);
3367 
3368 out:
3369     close_all_flash_areas(state);
3370 
3371     if (rc != 0) {
3372         FIH_SET(fih_rc, FIH_FAILURE);
3373     }
3374 
3375     FIH_RET(fih_rc);
3376 }
3377 #endif /* MCUBOOT_DIRECT_XIP || MCUBOOT_RAM_LOAD */
3378 
3379 /**
3380  * Prepares the booting process. This function moves images around in flash as
3381  * appropriate, and tells you what address to boot from.
3382  *
3383  * @param rsp                   On success, indicates how booting should occur.
3384  *
3385  * @return                      FIH_SUCCESS on success; nonzero on failure.
3386  */
3387 fih_ret
3388 boot_go(struct boot_rsp *rsp)
3389 {
3390     FIH_DECLARE(fih_rc, FIH_FAILURE);
3391 
3392     boot_state_clear(NULL);
3393 
3394     FIH_CALL(context_boot_go, fih_rc, &boot_data, rsp);
3395     FIH_RET(fih_rc);
3396 }
3397 
3398 /**
3399  * Prepares the booting process, considering only a single image. This function
3400  * moves images around in flash as appropriate, and tells you what address to
3401  * boot from.
3402  *
3403  * @param rsp                   On success, indicates how booting should occur.
3404  *
3405  * @param image_id              The image ID to prepare the boot process for.
3406  *
3407  * @return                      FIH_SUCCESS on success; nonzero on failure.
3408  */
3409 fih_ret
3410 boot_go_for_image_id(struct boot_rsp *rsp, uint32_t image_id)
3411 {
3412     FIH_DECLARE(fih_rc, FIH_FAILURE);
3413 
3414     if (image_id >= BOOT_IMAGE_NUMBER) {
3415         FIH_RET(FIH_FAILURE);
3416     }
3417 
3418 #if BOOT_IMAGE_NUMBER > 1
3419     memset(&boot_data.img_mask, 1, BOOT_IMAGE_NUMBER);
3420     boot_data.img_mask[image_id] = 0;
3421 #endif
3422 
3423     FIH_CALL(context_boot_go, fih_rc, &boot_data, rsp);
3424     FIH_RET(fih_rc);
3425 }
3426 
3427 /**
3428  * Clears the boot state, so that previous operations have no effect on new
3429  * ones.
3430  *
3431  * @param state                 The state that should be cleared. If the value
3432  *                              is NULL, the default bootloader state will be
3433  *                              cleared.
3434  */
3435 void boot_state_clear(struct boot_loader_state *state)
3436 {
3437     if (state != NULL) {
3438         memset(state, 0, sizeof(struct boot_loader_state));
3439     } else {
3440         memset(&boot_data, 0, sizeof(struct boot_loader_state));
3441     }
3442 }
3443 
3444 #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO)
3445 /**
3446  * Reads image data to find out the maximum application sizes. Only needs to
3447  * be called in serial recovery mode, as the state information is unpopulated
3448  * at that time
3449  */
3450 static void boot_fetch_slot_state_sizes(void)
3451 {
3452     size_t slot;
3453     int rc = -1;
3454     int fa_id;
3455     int image_index;
3456 
3457     IMAGES_ITER(BOOT_CURR_IMG(&boot_data)) {
3458         int max_size = 0;
3459 
3460         image_index = BOOT_CURR_IMG(&boot_data);
3461 
3462         BOOT_IMG(&boot_data, BOOT_PRIMARY_SLOT).sectors =
3463             sector_buffers.primary[image_index];
3464         BOOT_IMG(&boot_data, BOOT_SECONDARY_SLOT).sectors =
3465             sector_buffers.secondary[image_index];
3466 #if MCUBOOT_SWAP_USING_SCRATCH
3467         boot_data.scratch.sectors = sector_buffers.scratch;
3468 #endif
3469 
3470         /* Open primary and secondary image areas for the duration
3471          * of this call.
3472          */
3473         for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
3474             fa_id = flash_area_id_from_multi_image_slot(image_index, slot);
3475             rc = flash_area_open(fa_id, &BOOT_IMG_AREA(&boot_data, slot));
3476             assert(rc == 0);
3477 
3478             if (rc != 0) {
3479                 goto finish;
3480             }
3481         }
3482 
3483 #if MCUBOOT_SWAP_USING_SCRATCH
3484         rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH,
3485                              &BOOT_SCRATCH_AREA(&boot_data));
3486         assert(rc == 0);
3487 
3488         if (rc != 0) {
3489             goto finish;
3490         }
3491 #endif
3492 
3493         /* Determine the sector layout of the image slots and scratch area. */
3494         rc = boot_read_sectors_recovery(&boot_data);
3495 
3496         if (rc == 0) {
3497             max_size = app_max_size(&boot_data);
3498 
3499             if (max_size > 0) {
3500                 image_max_sizes[image_index].calculated = true;
3501                 image_max_sizes[image_index].max_size = max_size;
3502             }
3503         }
3504     }
3505 
3506 finish:
3507     close_all_flash_areas(&boot_data);
3508     memset(&boot_data, 0x00, sizeof(boot_data));
3509 }
3510 #endif
3511 
3512 #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING)
3513 /**
3514  * Fetches the maximum allowed size of the image
3515  */
3516 const struct image_max_size *boot_get_max_app_size(void)
3517 {
3518 #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO)
3519     uint8_t i = 0;
3520 
3521     while (i < BOOT_IMAGE_NUMBER) {
3522         if (image_max_sizes[i].calculated == true) {
3523             break;
3524         }
3525 
3526         ++i;
3527     }
3528 
3529     if (i == BOOT_IMAGE_NUMBER) {
3530         /* Information not available, need to fetch it */
3531         boot_fetch_slot_state_sizes();
3532     }
3533 #endif
3534 
3535     return image_max_sizes;
3536 }
3537 #endif
3538