1 /*
2  * Copyright (c) 2018-2023 Arm Limited
3  * Copyright (c) 2020 Linaro Limited
4  * Copyright (c) 2023, Nordic Semiconductor ASA
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <stddef.h>
20 #include <stdint.h>
21 #include <limits.h>
22 #include <stdbool.h>
23 #include <string.h>
24 
25 #include "mcuboot_config/mcuboot_config.h"
26 #include "bootutil/crypto/sha.h"
27 
28 #if defined(MCUBOOT_MEASURED_BOOT) || defined(MCUBOOT_DATA_SHARING)
29 #include "bootutil/boot_record.h"
30 #include "bootutil/boot_status.h"
31 #include "bootutil_priv.h"
32 #include "bootutil/image.h"
33 #include "flash_map_backend/flash_map_backend.h"
34 
35 #if !defined(MCUBOOT_CUSTOM_DATA_SHARING_FUNCTION)
36 /**
37  * @var shared_memory_init_done
38  *
39  * @brief Indicates whether shared memory area was already initialized.
40  *
41  */
42 static bool shared_memory_init_done;
43 
44 /* See in boot_record.h */
45 int
boot_add_data_to_shared_area(uint8_t major_type,uint16_t minor_type,size_t size,const uint8_t * data)46 boot_add_data_to_shared_area(uint8_t        major_type,
47                              uint16_t       minor_type,
48                              size_t         size,
49                              const uint8_t *data)
50 {
51     struct shared_data_tlv_entry tlv_entry = {0};
52     struct shared_boot_data *boot_data;
53     uint16_t boot_data_size;
54     uintptr_t tlv_end, offset;
55 
56     if (data == NULL) {
57         return SHARED_MEMORY_GEN_ERROR;
58     }
59 
60     boot_data = (struct shared_boot_data *)MCUBOOT_SHARED_DATA_BASE;
61 
62     /* Check whether first time to call this function. If does then initialise
63      * shared data area.
64      */
65     if (!shared_memory_init_done) {
66         memset((void *)MCUBOOT_SHARED_DATA_BASE, 0, MCUBOOT_SHARED_DATA_SIZE);
67         boot_data->header.tlv_magic   = SHARED_DATA_TLV_INFO_MAGIC;
68         boot_data->header.tlv_tot_len = SHARED_DATA_HEADER_SIZE;
69         shared_memory_init_done = true;
70     }
71 
72     /* Check whether TLV entry is already added.
73      * Get the boundaries of TLV section
74      */
75     tlv_end = MCUBOOT_SHARED_DATA_BASE + boot_data->header.tlv_tot_len;
76     offset  = MCUBOOT_SHARED_DATA_BASE + SHARED_DATA_HEADER_SIZE;
77 
78     /* Iterates over the TLV section looks for the same entry if found then
79      * returns with error: SHARED_MEMORY_OVERWRITE
80      */
81     while (offset < tlv_end) {
82         /* Create local copy to avoid unaligned access */
83         memcpy(&tlv_entry, (const void *)offset, SHARED_DATA_ENTRY_HEADER_SIZE);
84         if (GET_MAJOR(tlv_entry.tlv_type) == major_type &&
85             GET_MINOR(tlv_entry.tlv_type) == minor_type) {
86             return SHARED_MEMORY_OVERWRITE;
87         }
88 
89         offset += SHARED_DATA_ENTRY_SIZE(tlv_entry.tlv_len);
90     }
91 
92     /* Add TLV entry */
93     tlv_entry.tlv_type = SET_TLV_TYPE(major_type, minor_type);
94     tlv_entry.tlv_len  = size;
95 
96     if (!boot_u16_safe_add(&boot_data_size, boot_data->header.tlv_tot_len,
97                            SHARED_DATA_ENTRY_SIZE(size))) {
98         return SHARED_MEMORY_GEN_ERROR;
99     }
100 
101     /* Verify overflow of shared area */
102     if (boot_data_size > MCUBOOT_SHARED_DATA_SIZE) {
103         return SHARED_MEMORY_OVERFLOW;
104     }
105 
106     offset = tlv_end;
107     memcpy((void *)offset, &tlv_entry, SHARED_DATA_ENTRY_HEADER_SIZE);
108 
109     offset += SHARED_DATA_ENTRY_HEADER_SIZE;
110     memcpy((void *)offset, data, size);
111 
112     boot_data->header.tlv_tot_len += SHARED_DATA_ENTRY_SIZE(size);
113 
114     return SHARED_MEMORY_OK;
115 }
116 #endif /* MCUBOOT_MEASURED_BOOT OR MCUBOOT_DATA_SHARING */
117 #endif /* !MCUBOOT_CUSTOM_DATA_SHARING_FUNCTION */
118 
119 #ifdef MCUBOOT_MEASURED_BOOT
120 /* See in boot_record.h */
121 int
boot_save_boot_status(uint8_t sw_module,const struct image_header * hdr,const struct flash_area * fap)122 boot_save_boot_status(uint8_t sw_module,
123                       const struct image_header *hdr,
124                       const struct flash_area *fap)
125 {
126 
127     struct image_tlv_iter it;
128     uint32_t offset;
129     uint16_t len;
130     uint16_t type;
131     uint16_t ias_minor;
132     size_t record_len = 0;
133     uint8_t image_hash[IMAGE_HASH_SIZE];
134     uint8_t buf[MAX_BOOT_RECORD_SZ];
135     bool boot_record_found = false;
136     bool hash_found = false;
137     int rc;
138 
139     /* Manifest data is concatenated to the end of the image.
140      * It is encoded in TLV format.
141      */
142 
143     rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false);
144     if (rc) {
145         return -1;
146     }
147 
148     /* Traverse through the TLV area to find the boot record
149      * and image hash TLVs.
150      */
151     while (true) {
152         rc = bootutil_tlv_iter_next(&it, &offset, &len, &type);
153         if (rc < 0) {
154             return -1;
155         } else if (rc > 0) {
156             break;
157         }
158 
159         if (type == IMAGE_TLV_BOOT_RECORD) {
160             if (len > sizeof(buf)) {
161                 return -1;
162             }
163             rc = flash_area_read(fap, offset, buf, len);
164             if (rc) {
165                 return -1;
166             }
167 
168             record_len = len;
169             boot_record_found = true;
170 
171         } else if (type == EXPECTED_HASH_TLV) {
172             /* Get the image's hash value from the manifest section. */
173             if (len > sizeof(image_hash)) {
174                 return -1;
175             }
176             rc = flash_area_read(fap, offset, image_hash, len);
177             if (rc) {
178                 return -1;
179             }
180 
181             hash_found = true;
182 
183             /* The boot record TLV is part of the protected TLV area which is
184              * located before the other parts of the TLV area (including the
185              * image hash) so at this point it is okay to break the loop
186              * as the boot record TLV should have already been found.
187              */
188             break;
189         }
190     }
191 
192     if (!boot_record_found || !hash_found) {
193         return -1;
194     }
195 
196     /* Ensure that we have enough in the record for the hash.  This
197      * prevents an underflow in the calculation below.
198      */
199     if (record_len < sizeof(image_hash)) {
200 	return -1;
201     }
202 
203     /* Update the measurement value (hash of the image) data item in the
204      * boot record. It is always the last item in the structure to make
205      * it easy to calculate its position.
206      * The image hash is computed over the image header, the image itself and
207      * the protected TLV area (which should already include the image hash as
208      * part of the boot record TLV). For this reason this field has been
209      * filled with zeros during the image signing process.
210      */
211     offset = record_len - sizeof(image_hash);
212     /* The size of 'buf' has already been checked when
213      * the BOOT_RECORD TLV was read, it won't overflow.
214      */
215     memcpy(buf + offset, image_hash, sizeof(image_hash));
216 
217     /* Add the CBOR encoded boot record to the shared data area. */
218     ias_minor = SET_IAS_MINOR(sw_module, SW_BOOT_RECORD);
219     rc = boot_add_data_to_shared_area(TLV_MAJOR_IAS,
220                                       ias_minor,
221                                       record_len,
222                                       buf);
223     if (rc != SHARED_MEMORY_OK) {
224         return rc;
225     }
226 
227     return 0;
228 }
229 #endif /* MCUBOOT_MEASURED_BOOT */
230 
231 #ifdef MCUBOOT_DATA_SHARING_BOOTINFO
boot_save_shared_data(const struct image_header * hdr,const struct flash_area * fap,const uint8_t slot,const int max_app_size)232 int boot_save_shared_data(const struct image_header *hdr, const struct flash_area *fap,
233                           const uint8_t slot, const int max_app_size)
234 {
235     int rc;
236 
237 #if defined(MCUBOOT_SINGLE_APPLICATION_SLOT)
238     uint8_t mode = MCUBOOT_MODE_SINGLE_SLOT;
239 #elif defined(MCUBOOT_SWAP_USING_SCRATCH)
240     uint8_t mode = MCUBOOT_MODE_SWAP_USING_SCRATCH;
241 #elif defined(MCUBOOT_OVERWRITE_ONLY)
242     uint8_t mode = MCUBOOT_MODE_UPGRADE_ONLY;
243 #elif defined(MCUBOOT_SWAP_USING_MOVE)
244     uint8_t mode = MCUBOOT_MODE_SWAP_USING_MOVE;
245 #elif defined(MCUBOOT_DIRECT_XIP)
246 #if defined(MCUBOOT_DIRECT_XIP_REVERT)
247     uint8_t mode = MCUBOOT_MODE_DIRECT_XIP_WITH_REVERT;
248 #else
249     uint8_t mode = MCUBOOT_MODE_DIRECT_XIP;
250 #endif
251 #elif defined(MCUBOOT_RAM_LOAD)
252     uint8_t mode = MCUBOOT_MODE_RAM_LOAD;
253 #elif defined(MCUBOOT_FIRMWARE_LOADER)
254     uint8_t mode = MCUBOOT_MODE_FIRMWARE_LOADER;
255 #else
256 #error "Unknown mcuboot operating mode"
257 #endif
258 
259 #if defined(MCUBOOT_SIGN_RSA)
260     uint8_t signature_type = MCUBOOT_SIGNATURE_TYPE_RSA;
261 #elif defined(MCUBOOT_SIGN_EC256)
262     uint8_t signature_type = MCUBOOT_SIGNATURE_TYPE_ECDSA_P256;
263 #elif defined(MCUBOOT_SIGN_ED25519)
264     uint8_t signature_type = MCUBOOT_SIGNATURE_TYPE_ED25519;
265 #else
266     uint8_t signature_type = MCUBOOT_SIGNATURE_TYPE_NONE;
267 #endif
268 
269 #if defined(MCUBOOT_SERIAL_RECOVERY)
270     uint8_t recovery = MCUBOOT_RECOVERY_MODE_SERIAL_RECOVERY;
271 #elif defined(MCUBOOT_USB_DFU)
272     uint8_t recovery = MCUBOOT_RECOVERY_MODE_DFU;
273 #else
274     uint8_t recovery = MCUBOOT_RECOVERY_MODE_NONE;
275 #endif
276 
277 #if defined(MCUBOOT_VERSION_AVAILABLE)
278     struct image_version mcuboot_version = {
279         .iv_major = MCUBOOT_VERSION_MAJOR,
280         .iv_minor = MCUBOOT_VERSION_MINOR,
281 
282 #if defined(MCUBOOT_VERSION_PATCHLEVEL)
283         .iv_revision = MCUBOOT_VERSION_PATCHLEVEL,
284 #else
285         .iv_revision = 0,
286 #endif
287 
288 #if defined(MCUBOOT_VERSION_TWEAK)
289         .iv_build_num = MCUBOOT_VERSION_TWEAK,
290 #else
291         .iv_build_num = 0,
292 #endif
293     };
294 #endif
295 
296     /* Write out all fields */
297     rc = boot_add_data_to_shared_area(TLV_MAJOR_BLINFO, BLINFO_MODE,
298                                       sizeof(mode), &mode);
299 
300     if (!rc) {
301         rc = boot_add_data_to_shared_area(TLV_MAJOR_BLINFO,
302                                           BLINFO_SIGNATURE_TYPE,
303                                           sizeof(signature_type),
304                                           &signature_type);
305     }
306 
307     if (!rc) {
308         rc = boot_add_data_to_shared_area(TLV_MAJOR_BLINFO,
309                                           BLINFO_RECOVERY,
310                                           sizeof(recovery), &recovery);
311     }
312 
313     if (!rc) {
314         rc = boot_add_data_to_shared_area(TLV_MAJOR_BLINFO,
315                                           BLINFO_RUNNING_SLOT,
316                                           sizeof(slot), (void *)&slot);
317     }
318 
319 #if defined(MCUBOOT_VERSION_AVAILABLE)
320     if (!rc) {
321         rc = boot_add_data_to_shared_area(TLV_MAJOR_BLINFO,
322                                           BLINFO_BOOTLOADER_VERSION,
323                                           sizeof(mcuboot_version),
324                                           (void *)&mcuboot_version);
325     }
326 #endif
327 
328     if (!rc) {
329         rc = boot_add_data_to_shared_area(TLV_MAJOR_BLINFO,
330                                           BLINFO_MAX_APPLICATION_SIZE,
331                                           sizeof(max_app_size),
332                                           (void *)&max_app_size);
333     }
334 
335     return rc;
336 }
337 #endif /* MCUBOOT_DATA_SHARING_BOOTINFO */
338