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_DATA_SHARING_BOOTINFO)
36 static bool saved_bootinfo = false;
37 #endif
38
39 #if !defined(MCUBOOT_CUSTOM_DATA_SHARING_FUNCTION)
40 /**
41 * @var shared_memory_init_done
42 *
43 * @brief Indicates whether shared memory area was already initialized.
44 *
45 */
46 static bool shared_memory_init_done;
47
48 /* See in boot_record.h */
49 int
boot_add_data_to_shared_area(uint8_t major_type,uint16_t minor_type,size_t size,const uint8_t * data)50 boot_add_data_to_shared_area(uint8_t major_type,
51 uint16_t minor_type,
52 size_t size,
53 const uint8_t *data)
54 {
55 struct shared_data_tlv_entry tlv_entry = {0};
56 struct shared_boot_data *boot_data;
57 uint16_t boot_data_size;
58 uintptr_t tlv_end, offset;
59
60 if (data == NULL) {
61 return SHARED_MEMORY_GEN_ERROR;
62 }
63
64 boot_data = (struct shared_boot_data *)MCUBOOT_SHARED_DATA_BASE;
65
66 /* Check whether first time to call this function. If does then initialise
67 * shared data area.
68 */
69 if (!shared_memory_init_done) {
70 memset((void *)MCUBOOT_SHARED_DATA_BASE, 0, MCUBOOT_SHARED_DATA_SIZE);
71 boot_data->header.tlv_magic = SHARED_DATA_TLV_INFO_MAGIC;
72 boot_data->header.tlv_tot_len = SHARED_DATA_HEADER_SIZE;
73 shared_memory_init_done = true;
74 }
75
76 /* Check whether TLV entry is already added.
77 * Get the boundaries of TLV section
78 */
79 tlv_end = MCUBOOT_SHARED_DATA_BASE + boot_data->header.tlv_tot_len;
80 offset = MCUBOOT_SHARED_DATA_BASE + SHARED_DATA_HEADER_SIZE;
81
82 /* Iterates over the TLV section looks for the same entry if found then
83 * returns with error: SHARED_MEMORY_OVERWRITE
84 */
85 while (offset < tlv_end) {
86 /* Create local copy to avoid unaligned access */
87 memcpy(&tlv_entry, (const void *)offset, SHARED_DATA_ENTRY_HEADER_SIZE);
88 if (GET_MAJOR(tlv_entry.tlv_type) == major_type &&
89 GET_MINOR(tlv_entry.tlv_type) == minor_type) {
90 return SHARED_MEMORY_OVERWRITE;
91 }
92
93 offset += SHARED_DATA_ENTRY_SIZE(tlv_entry.tlv_len);
94 }
95
96 /* Add TLV entry */
97 tlv_entry.tlv_type = SET_TLV_TYPE(major_type, minor_type);
98 tlv_entry.tlv_len = size;
99
100 if (!boot_u16_safe_add(&boot_data_size, boot_data->header.tlv_tot_len,
101 SHARED_DATA_ENTRY_SIZE(size))) {
102 return SHARED_MEMORY_GEN_ERROR;
103 }
104
105 /* Verify overflow of shared area */
106 if (boot_data_size > MCUBOOT_SHARED_DATA_SIZE) {
107 return SHARED_MEMORY_OVERFLOW;
108 }
109
110 offset = tlv_end;
111 memcpy((void *)offset, &tlv_entry, SHARED_DATA_ENTRY_HEADER_SIZE);
112
113 offset += SHARED_DATA_ENTRY_HEADER_SIZE;
114 memcpy((void *)offset, data, size);
115
116 boot_data->header.tlv_tot_len += SHARED_DATA_ENTRY_SIZE(size);
117
118 return SHARED_MEMORY_OK;
119 }
120 #endif /* MCUBOOT_MEASURED_BOOT OR MCUBOOT_DATA_SHARING */
121 #endif /* !MCUBOOT_CUSTOM_DATA_SHARING_FUNCTION */
122
123 #ifdef MCUBOOT_MEASURED_BOOT
124 /* See in boot_record.h */
125 int
boot_save_boot_status(uint8_t sw_module,const struct image_header * hdr,const struct flash_area * fap)126 boot_save_boot_status(uint8_t sw_module,
127 const struct image_header *hdr,
128 const struct flash_area *fap)
129 {
130
131 struct image_tlv_iter it;
132 uint32_t offset;
133 uint16_t len;
134 uint16_t type;
135 uint16_t ias_minor;
136 size_t record_len = 0;
137 uint8_t image_hash[IMAGE_HASH_SIZE];
138 uint8_t buf[MAX_BOOT_RECORD_SZ];
139 bool boot_record_found = false;
140 bool hash_found = false;
141 int rc;
142
143 /* Manifest data is concatenated to the end of the image.
144 * It is encoded in TLV format.
145 */
146 #if defined(MCUBOOT_SWAP_USING_OFFSET)
147 it.start_off = 0;
148 #endif
149
150 rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false);
151 if (rc) {
152 return -1;
153 }
154
155 /* Traverse through the TLV area to find the boot record
156 * and image hash TLVs.
157 */
158 while (true) {
159 rc = bootutil_tlv_iter_next(&it, &offset, &len, &type);
160 if (rc < 0) {
161 return -1;
162 } else if (rc > 0) {
163 break;
164 }
165
166 if (type == IMAGE_TLV_BOOT_RECORD) {
167 if (len > sizeof(buf)) {
168 return -1;
169 }
170 rc = flash_area_read(fap, offset, buf, len);
171 if (rc) {
172 return -1;
173 }
174
175 record_len = len;
176 boot_record_found = true;
177
178 } else if (type == EXPECTED_HASH_TLV) {
179 /* Get the image's hash value from the manifest section. */
180 if (len > sizeof(image_hash)) {
181 return -1;
182 }
183 rc = flash_area_read(fap, offset, image_hash, len);
184 if (rc) {
185 return -1;
186 }
187
188 hash_found = true;
189
190 /* The boot record TLV is part of the protected TLV area which is
191 * located before the other parts of the TLV area (including the
192 * image hash) so at this point it is okay to break the loop
193 * as the boot record TLV should have already been found.
194 */
195 break;
196 }
197 }
198
199 if (!boot_record_found || !hash_found) {
200 return -1;
201 }
202
203 /* Ensure that we have enough in the record for the hash. This
204 * prevents an underflow in the calculation below.
205 */
206 if (record_len < sizeof(image_hash)) {
207 return -1;
208 }
209
210 /* Update the measurement value (hash of the image) data item in the
211 * boot record. It is always the last item in the structure to make
212 * it easy to calculate its position.
213 * The image hash is computed over the image header, the image itself and
214 * the protected TLV area (which should already include the image hash as
215 * part of the boot record TLV). For this reason this field has been
216 * filled with zeros during the image signing process.
217 */
218 offset = record_len - sizeof(image_hash);
219 /* The size of 'buf' has already been checked when
220 * the BOOT_RECORD TLV was read, it won't overflow.
221 */
222 memcpy(buf + offset, image_hash, sizeof(image_hash));
223
224 /* Add the CBOR encoded boot record to the shared data area. */
225 ias_minor = SET_IAS_MINOR(sw_module, SW_BOOT_RECORD);
226 rc = boot_add_data_to_shared_area(TLV_MAJOR_IAS,
227 ias_minor,
228 record_len,
229 buf);
230 if (rc != SHARED_MEMORY_OK) {
231 return rc;
232 }
233
234 return 0;
235 }
236 #endif /* MCUBOOT_MEASURED_BOOT */
237
238 #ifdef MCUBOOT_DATA_SHARING_BOOTINFO
boot_save_shared_data(const struct image_header * hdr,const struct flash_area * fap,const uint8_t slot,const struct image_max_size * max_app_sizes)239 int boot_save_shared_data(const struct image_header *hdr, const struct flash_area *fap,
240 const uint8_t slot, const struct image_max_size *max_app_sizes)
241 {
242 int rc;
243 #if !defined(MCUBOOT_SINGLE_APPLICATION_SLOT)
244 uint8_t image = 0;
245 #endif
246
247 #if defined(MCUBOOT_SINGLE_APPLICATION_SLOT)
248 uint8_t mode = MCUBOOT_MODE_SINGLE_SLOT;
249 #elif defined(MCUBOOT_SWAP_USING_SCRATCH)
250 uint8_t mode = MCUBOOT_MODE_SWAP_USING_SCRATCH;
251 #elif defined(MCUBOOT_OVERWRITE_ONLY)
252 uint8_t mode = MCUBOOT_MODE_UPGRADE_ONLY;
253 #elif defined(MCUBOOT_SWAP_USING_MOVE)
254 uint8_t mode = MCUBOOT_MODE_SWAP_USING_MOVE;
255 #elif defined(MCUBOOT_SWAP_USING_OFFSET)
256 uint8_t mode = MCUBOOT_MODE_SWAP_USING_OFFSET;
257 #elif defined(MCUBOOT_DIRECT_XIP)
258 #if defined(MCUBOOT_DIRECT_XIP_REVERT)
259 uint8_t mode = MCUBOOT_MODE_DIRECT_XIP_WITH_REVERT;
260 #else
261 uint8_t mode = MCUBOOT_MODE_DIRECT_XIP;
262 #endif
263 #elif defined(MCUBOOT_RAM_LOAD)
264 uint8_t mode = MCUBOOT_MODE_RAM_LOAD;
265 #elif defined(MCUBOOT_FIRMWARE_LOADER)
266 uint8_t mode = MCUBOOT_MODE_FIRMWARE_LOADER;
267 #elif defined(MCUBOOT_SINGLE_APPLICATION_SLOT_RAM_LOAD)
268 uint8_t mode = MCUBOOT_MODE_SINGLE_SLOT_RAM_LOAD;
269 #else
270 #error "Unknown mcuboot operating mode"
271 #endif
272
273 #if defined(MCUBOOT_SIGN_RSA)
274 uint8_t signature_type = MCUBOOT_SIGNATURE_TYPE_RSA;
275 #elif defined(MCUBOOT_SIGN_EC256)
276 uint8_t signature_type = MCUBOOT_SIGNATURE_TYPE_ECDSA_P256;
277 #elif defined(MCUBOOT_SIGN_ED25519)
278 uint8_t signature_type = MCUBOOT_SIGNATURE_TYPE_ED25519;
279 #else
280 uint8_t signature_type = MCUBOOT_SIGNATURE_TYPE_NONE;
281 #endif
282
283 #if defined(MCUBOOT_SERIAL_RECOVERY)
284 uint8_t recovery = MCUBOOT_RECOVERY_MODE_SERIAL_RECOVERY;
285 #elif defined(MCUBOOT_USB_DFU)
286 uint8_t recovery = MCUBOOT_RECOVERY_MODE_DFU;
287 #else
288 uint8_t recovery = MCUBOOT_RECOVERY_MODE_NONE;
289 #endif
290
291 #if defined(MCUBOOT_VERSION_AVAILABLE)
292 struct image_version mcuboot_version = {
293 .iv_major = MCUBOOT_VERSION_MAJOR,
294 .iv_minor = MCUBOOT_VERSION_MINOR,
295
296 #if defined(MCUBOOT_VERSION_PATCHLEVEL)
297 .iv_revision = MCUBOOT_VERSION_PATCHLEVEL,
298 #else
299 .iv_revision = 0,
300 #endif
301
302 #if defined(MCUBOOT_VERSION_TWEAK)
303 .iv_build_num = MCUBOOT_VERSION_TWEAK,
304 #else
305 .iv_build_num = 0,
306 #endif
307 };
308 #endif
309
310 if (saved_bootinfo) {
311 /* Boot info has already been saved, nothing to do */
312 return 0;
313 }
314
315 /* Write out all fields */
316 rc = boot_add_data_to_shared_area(TLV_MAJOR_BLINFO, BLINFO_MODE,
317 sizeof(mode), &mode);
318
319 if (!rc) {
320 rc = boot_add_data_to_shared_area(TLV_MAJOR_BLINFO,
321 BLINFO_SIGNATURE_TYPE,
322 sizeof(signature_type),
323 &signature_type);
324 }
325
326 if (!rc) {
327 rc = boot_add_data_to_shared_area(TLV_MAJOR_BLINFO,
328 BLINFO_RECOVERY,
329 sizeof(recovery), &recovery);
330 }
331
332 #if !defined(MCUBOOT_SINGLE_APPLICATION_SLOT)
333 if (!rc) {
334 rc = boot_add_data_to_shared_area(TLV_MAJOR_BLINFO,
335 BLINFO_RUNNING_SLOT,
336 sizeof(slot), (void *)&slot);
337 }
338 #endif
339
340 #if defined(MCUBOOT_VERSION_AVAILABLE)
341 if (!rc) {
342 rc = boot_add_data_to_shared_area(TLV_MAJOR_BLINFO,
343 BLINFO_BOOTLOADER_VERSION,
344 sizeof(mcuboot_version),
345 (void *)&mcuboot_version);
346 }
347 #endif
348
349 #if !defined(MCUBOOT_SINGLE_APPLICATION_SLOT)
350 while (image < BOOT_IMAGE_NUMBER && !rc) {
351 if (max_app_sizes[image].calculated == true) {
352 rc = boot_add_data_to_shared_area(TLV_MAJOR_BLINFO,
353 (BLINFO_MAX_APPLICATION_SIZE + image),
354 sizeof(max_app_sizes[image].max_size),
355 (void *)&max_app_sizes[image].max_size);
356
357 }
358
359 ++image;
360 }
361 #endif
362
363 if (!rc) {
364 saved_bootinfo = true;
365 }
366
367 return rc;
368 }
369 #endif /* MCUBOOT_DATA_SHARING_BOOTINFO */
370