1 /*
2  * SPDX-License-Identifier: Apache-2.0
3  *
4  * Copyright (c) 2017-2019 Linaro LTD
5  * Copyright (c) 2016-2019 JUUL Labs
6  * Copyright (c) 2019-2020 Arm Limited
7  *
8  * Original license:
9  *
10  * Licensed to the Apache Software Foundation (ASF) under one
11  * or more contributor license agreements.  See the NOTICE file
12  * distributed with this work for additional information
13  * regarding copyright ownership.  The ASF licenses this file
14  * to you under the Apache License, Version 2.0 (the
15  * "License"); you may not use this file except in compliance
16  * with the License.  You may obtain a copy of the License at
17  *
18  *  http://www.apache.org/licenses/LICENSE-2.0
19  *
20  * Unless required by applicable law or agreed to in writing,
21  * software distributed under the License is distributed on an
22  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
23  * KIND, either express or implied.  See the License for the
24  * specific language governing permissions and limitations
25  * under the License.
26  */
27 
28 #include <string.h>
29 #include <inttypes.h>
30 #include <stddef.h>
31 
32 #include "sysflash/sysflash.h"
33 #include "flash_map_backend/flash_map_backend.h"
34 
35 #include "bootutil/image.h"
36 #include "bootutil/bootutil.h"
37 #include "bootutil_priv.h"
38 #include "bootutil_misc.h"
39 #include "bootutil/bootutil_log.h"
40 #include "bootutil/fault_injection_hardening.h"
41 #ifdef MCUBOOT_ENC_IMAGES
42 #include "bootutil/enc_key.h"
43 #endif
44 
45 BOOT_LOG_MODULE_DECLARE(mcuboot);
46 
47 /* Currently only used by imgmgr */
48 int boot_current_slot;
49 
50 /**
51  * @brief Determine if the data at two memory addresses is equal
52  *
53  * @param s1    The first  memory region to compare.
54  * @param s2    The second memory region to compare.
55  * @param n     The amount of bytes to compare.
56  *
57  * @note        This function does not comply with the specification of memcmp,
58  *              so should not be considered a drop-in replacement. It has no
59  *              constant time execution. The point is to make sure that all the
60  *              bytes are compared and detect if loop was abused and some cycles
61  *              was skipped due to fault injection.
62  *
63  * @return      FIH_SUCCESS if memory regions are equal, otherwise FIH_FAILURE
64  */
65 #ifdef MCUBOOT_FIH_PROFILE_OFF
66 inline
boot_fih_memequal(const void * s1,const void * s2,size_t n)67 fih_ret boot_fih_memequal(const void *s1, const void *s2, size_t n)
68 {
69     return memcmp(s1, s2, n);
70 }
71 #else
boot_fih_memequal(const void * s1,const void * s2,size_t n)72 fih_ret boot_fih_memequal(const void *s1, const void *s2, size_t n)
73 {
74     size_t i;
75     uint8_t *s1_p = (uint8_t*) s1;
76     uint8_t *s2_p = (uint8_t*) s2;
77     FIH_DECLARE(ret, FIH_FAILURE);
78 
79     for (i = 0; i < n; i++) {
80         if (s1_p[i] != s2_p[i]) {
81             goto out;
82         }
83     }
84     if (i == n) {
85         ret = FIH_SUCCESS;
86     }
87 
88 out:
89     FIH_RET(ret);
90 }
91 #endif
92 
93 /*
94  * Amount of space used to save information required when doing a swap,
95  * or while a swap is under progress, but not the status of sector swap
96  * progress itself.
97  */
98 static inline uint32_t
boot_trailer_info_sz(void)99 boot_trailer_info_sz(void)
100 {
101     return (
102 #ifdef MCUBOOT_ENC_IMAGES
103            /* encryption keys */
104 #  if MCUBOOT_SWAP_SAVE_ENCTLV
105            BOOT_ENC_TLV_ALIGN_SIZE * 2            +
106 #  else
107            BOOT_ENC_KEY_ALIGN_SIZE * 2            +
108 #  endif
109 #endif
110            /* swap_type + copy_done + image_ok + swap_size */
111            BOOT_MAX_ALIGN * 4                     +
112            BOOT_MAGIC_ALIGN_SIZE
113            );
114 }
115 
116 /*
117  * Amount of space used to maintain progress information for a single swap
118  * operation.
119  */
120 static inline uint32_t
boot_status_entry_sz(uint32_t min_write_sz)121 boot_status_entry_sz(uint32_t min_write_sz)
122 {
123     return BOOT_STATUS_STATE_COUNT * min_write_sz;
124 }
125 
126 uint32_t
boot_status_sz(uint32_t min_write_sz)127 boot_status_sz(uint32_t min_write_sz)
128 {
129     return BOOT_STATUS_MAX_ENTRIES * boot_status_entry_sz(min_write_sz);
130 }
131 
132 uint32_t
boot_trailer_sz(uint32_t min_write_sz)133 boot_trailer_sz(uint32_t min_write_sz)
134 {
135     return boot_status_sz(min_write_sz) + boot_trailer_info_sz();
136 }
137 
138 #if MCUBOOT_SWAP_USING_SCRATCH
139 /*
140  * Similar to `boot_trailer_sz` but this function returns the space used to
141  * store status in the scratch partition. The scratch partition only stores
142  * status during the swap of the last sector from primary/secondary (which
143  * is the first swap operation) and thus only requires space for one swap.
144  */
145 static uint32_t
boot_scratch_trailer_sz(uint32_t min_write_sz)146 boot_scratch_trailer_sz(uint32_t min_write_sz)
147 {
148     return boot_status_entry_sz(min_write_sz) + boot_trailer_info_sz();
149 }
150 #endif
151 
152 int
boot_status_entries(int image_index,const struct flash_area * fap)153 boot_status_entries(int image_index, const struct flash_area *fap)
154 {
155 #if MCUBOOT_SWAP_USING_SCRATCH
156     if (flash_area_get_id(fap) == FLASH_AREA_IMAGE_SCRATCH) {
157         return BOOT_STATUS_STATE_COUNT;
158     } else
159 #endif
160     if (flash_area_get_id(fap) == FLASH_AREA_IMAGE_PRIMARY(image_index) ||
161         flash_area_get_id(fap) == FLASH_AREA_IMAGE_SECONDARY(image_index)) {
162         return BOOT_STATUS_STATE_COUNT * BOOT_STATUS_MAX_ENTRIES;
163     }
164     return -1;
165 }
166 
167 uint32_t
boot_status_off(const struct flash_area * fap)168 boot_status_off(const struct flash_area *fap)
169 {
170     uint32_t off_from_end;
171     uint32_t elem_sz;
172 
173     elem_sz = flash_area_align(fap);
174 
175 #if MCUBOOT_SWAP_USING_SCRATCH
176     if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
177         off_from_end = boot_scratch_trailer_sz(elem_sz);
178     } else {
179 #endif
180         off_from_end = boot_trailer_sz(elem_sz);
181 #if MCUBOOT_SWAP_USING_SCRATCH
182     }
183 #endif
184 
185     assert(off_from_end <= flash_area_get_size(fap));
186     return flash_area_get_size(fap) - off_from_end;
187 }
188 
189 #ifdef MCUBOOT_ENC_IMAGES
190 static inline uint32_t
boot_enc_key_off(const struct flash_area * fap,uint8_t slot)191 boot_enc_key_off(const struct flash_area *fap, uint8_t slot)
192 {
193 #if MCUBOOT_SWAP_SAVE_ENCTLV
194     return boot_swap_size_off(fap) - ((slot + 1) * BOOT_ENC_TLV_ALIGN_SIZE);
195 #else
196     return boot_swap_size_off(fap) - ((slot + 1) * BOOT_ENC_KEY_ALIGN_SIZE);
197 #endif
198 }
199 #endif
200 
201 /**
202  * This functions tries to locate the status area after an aborted swap,
203  * by looking for the magic in the possible locations.
204  *
205  * If the magic is successfully found, a flash_area * is returned and it
206  * is the responsibility of the called to close it.
207  *
208  * @returns 0 on success, -1 on errors
209  */
210 int
boot_find_status(int image_index,const struct flash_area ** fap)211 boot_find_status(int image_index, const struct flash_area **fap)
212 {
213     uint8_t areas[] = {
214 #if MCUBOOT_SWAP_USING_SCRATCH
215         FLASH_AREA_IMAGE_SCRATCH,
216 #endif
217         FLASH_AREA_IMAGE_PRIMARY(image_index),
218     };
219     unsigned int i;
220 
221     /*
222      * In the middle a swap, tries to locate the area that is currently
223      * storing a valid magic, first on the primary slot, then on scratch.
224      * Both "slots" can end up being temporary storage for a swap and it
225      * is assumed that if magic is valid then other metadata is too,
226      * because magic is always written in the last step.
227      */
228 
229     for (i = 0; i < sizeof(areas) / sizeof(areas[0]); i++) {
230         uint8_t magic[BOOT_MAGIC_SZ];
231 
232         if (flash_area_open(areas[i], fap)) {
233             break;
234         }
235 
236         if (flash_area_read(*fap, boot_magic_off(*fap), magic, BOOT_MAGIC_SZ)) {
237             flash_area_close(*fap);
238             break;
239         }
240 
241         if (BOOT_MAGIC_GOOD == boot_magic_decode(magic)) {
242             return 0;
243         }
244 
245         flash_area_close(*fap);
246     }
247 
248     /* If we got here, no magic was found */
249     fap = NULL;
250     return -1;
251 }
252 
253 int
boot_read_swap_size(const struct flash_area * fap,uint32_t * swap_size)254 boot_read_swap_size(const struct flash_area *fap, uint32_t *swap_size)
255 {
256     uint32_t off;
257     int rc;
258 
259     off = boot_swap_size_off(fap);
260     rc = flash_area_read(fap, off, swap_size, sizeof *swap_size);
261 
262     return rc;
263 }
264 
265 #ifdef MCUBOOT_ENC_IMAGES
266 int
boot_read_enc_key(const struct flash_area * fap,uint8_t slot,struct boot_status * bs)267 boot_read_enc_key(const struct flash_area *fap, uint8_t slot, struct boot_status *bs)
268 {
269     uint32_t off;
270 #if MCUBOOT_SWAP_SAVE_ENCTLV
271     int i;
272 #endif
273     int rc;
274 
275     off = boot_enc_key_off(fap, slot);
276 #if MCUBOOT_SWAP_SAVE_ENCTLV
277     rc = flash_area_read(fap, off, bs->enctlv[slot], BOOT_ENC_TLV_ALIGN_SIZE);
278     if (rc == 0) {
279         for (i = 0; i < BOOT_ENC_TLV_ALIGN_SIZE; i++) {
280             if (bs->enctlv[slot][i] != 0xff) {
281                 break;
282             }
283         }
284         /* Only try to decrypt non-erased TLV metadata */
285         if (i != BOOT_ENC_TLV_ALIGN_SIZE) {
286             rc = boot_enc_decrypt(bs->enctlv[slot], bs->enckey[slot]);
287         }
288     }
289 #else
290     rc = flash_area_read(fap, off, bs->enckey[slot], BOOT_ENC_KEY_ALIGN_SIZE);
291 #endif
292 
293     return rc;
294 }
295 #endif
296 
297 int
boot_write_swap_size(const struct flash_area * fap,uint32_t swap_size)298 boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size)
299 {
300     uint32_t off;
301 
302     off = boot_swap_size_off(fap);
303     BOOT_LOG_DBG("writing swap_size; fa_id=%d off=0x%lx (0x%lx)",
304                  flash_area_get_id(fap), (unsigned long)off,
305                  (unsigned long)flash_area_get_off(fap) + off);
306     return boot_write_trailer(fap, off, (const uint8_t *) &swap_size, 4);
307 }
308 
309 #ifdef MCUBOOT_ENC_IMAGES
310 int
boot_write_enc_key(const struct flash_area * fap,uint8_t slot,const struct boot_status * bs)311 boot_write_enc_key(const struct flash_area *fap, uint8_t slot,
312         const struct boot_status *bs)
313 {
314     uint32_t off;
315     int rc;
316 
317     off = boot_enc_key_off(fap, slot);
318     BOOT_LOG_DBG("writing enc_key; fa_id=%d off=0x%lx (0x%lx)",
319                  flash_area_get_id(fap), (unsigned long)off,
320                  (unsigned long)flash_area_get_off(fap) + off);
321 #if MCUBOOT_SWAP_SAVE_ENCTLV
322     rc = flash_area_write(fap, off, bs->enctlv[slot], BOOT_ENC_TLV_ALIGN_SIZE);
323 #else
324     rc = flash_area_write(fap, off, bs->enckey[slot], BOOT_ENC_KEY_ALIGN_SIZE);
325 #endif
326     if (rc != 0) {
327         return BOOT_EFLASH;
328     }
329 
330     return 0;
331 }
332 #endif
333 
bootutil_max_image_size(const struct flash_area * fap)334 uint32_t bootutil_max_image_size(const struct flash_area *fap)
335 {
336 #if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SINGLE_APPLICATION_SLOT) || \
337     defined(MCUBOOT_FIRMWARE_LOADER)
338     return boot_status_off(fap);
339 #elif defined(MCUBOOT_SWAP_USING_MOVE)
340     struct flash_sector sector;
341     /* get the last sector offset */
342     int rc = flash_area_get_sector(fap, boot_status_off(fap), &sector);
343     if (rc) {
344         BOOT_LOG_ERR("Unable to determine flash sector of the image trailer");
345         return 0; /* Returning of zero here should cause any check which uses
346                    * this value to fail.
347                    */
348     }
349     return flash_sector_get_off(&sector);
350 #elif defined(MCUBOOT_OVERWRITE_ONLY)
351     return boot_swap_info_off(fap);
352 #elif defined(MCUBOOT_DIRECT_XIP)
353     return boot_swap_info_off(fap);
354 #elif defined(MCUBOOT_RAM_LOAD)
355     return boot_swap_info_off(fap);
356 #endif
357 }
358