1 /*
2  * Copyright (c) 2021-2024, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 #include <string.h>
8 #include "bootutil/boot_record.h"
9 #include "bootutil/boot_status.h"
10 #include "bootutil/image.h"
11 #include "flash_map/flash_map.h"
12 #include "sysflash/sysflash.h"
13 #include "mcuboot_config/mcuboot_config.h"
14 
15 #ifdef TFM_MEASURED_BOOT_API
16 #include "boot_hal.h"
17 #include "boot_measurement.h"
18 #include "bootutil/crypto/sha.h"
19 #include "bootutil_priv.h"
20 #include "psa/crypto.h"
21 
22 #if defined(MCUBOOT_SIGN_EC384)
23 #define MCUBOOT_HASH_ALG    PSA_ALG_SHA_384
24 #define MCUBOOT_HASH_SIZE   (48)
25 #else
26 #define MCUBOOT_HASH_ALG    PSA_ALG_SHA_256
27 #define MCUBOOT_HASH_SIZE   (32)
28 #endif /* MCUBOOT_SIGN_EC384 */
29 
30 #ifdef MCUBOOT_HW_KEY
31 #if defined(MCUBOOT_SIGN_RSA)
32 #define SIG_BUF_SIZE (MCUBOOT_SIGN_RSA_LEN / 8)
33 #define SIG_EXTRA_BYTES     (24) /* Few extra bytes for encoding and for public exponent. */
34 #elif defined(MCUBOOT_SIGN_EC256)
35 #define SIG_BUF_SIZE        (64) /* Curve byte (32) * 2 for EC-256 */
36 #define SIG_EXTRA_BYTES     (32)
37 #elif defined(MCUBOOT_SIGN_EC384)
38 #define SIG_BUF_SIZE        (96) /* Curve byte (48) * 2 for EC-384 */
39 #define SIG_EXTRA_BYTES     (48)
40 #endif /* MCUBOOT_SIGN_RSA */
41 #endif /* MCUBOOT_HW_KEY */
42 #endif /* TFM_MEASURED_BOOT_API */
43 
44 /* Firmware Update specific macros */
45 #define TLV_MAJOR_FWU   0x2
46 #define MODULE_MASK     0x3F           /* 6 bit */
47 #define CLAIM_MASK      0x3F           /* 6 bit */
48 
49 #define SET_FWU_MINOR(sw_module, claim)  \
50                      ((uint16_t)((sw_module & MODULE_MASK) << 6) | \
51                       (uint16_t)(claim & CLAIM_MASK))
52 
53 #ifdef TFM_PARTITION_FIRMWARE_UPDATE
54 extern int boot_add_data_to_shared_area(uint8_t        major_type,
55                                         uint16_t       minor_type,
56                                         size_t         size,
57                                         const uint8_t *data);
58 #endif /* TFM_PARTITION_FIRMWARE_UPDATE */
59 
60 
61 #ifdef TFM_MEASURED_BOOT_API
62 /**
63  * Collect boot measurement and available associated metadata from the
64  * TLV area of an image.
65  *
66  * @param[in]  hdr        Pointer to the image header stored in RAM.
67  * @param[in]  fap        Pointer to the flash area where image is stored.
68  * @param[out] metadata   Pointer to measurement metadata structure.
69  * @param[out] measurement_buf          Buffer to store the boot measurement.
70  * @param[in]  measurement_buf_size     As an input value it indicates the size
71  *                                      of the measurement buffer in bytes.
72  *
73  * @return                0 on success; nonzero on failure.
74  *
75  */
collect_image_measurement_and_metadata(const struct image_header * hdr,const struct flash_area * fap,struct boot_measurement_metadata * metadata,uint8_t * measurement_buf,size_t measurement_buf_size)76 static int collect_image_measurement_and_metadata(
77                                     const struct image_header *hdr,
78                                     const struct flash_area *fap,
79                                     struct boot_measurement_metadata *metadata,
80                                     uint8_t *measurement_buf,
81                                     size_t   measurement_buf_size)
82 {
83     struct image_tlv_iter it;
84     uint32_t off;
85     uint16_t len;
86     uint16_t type;
87 #ifdef MCUBOOT_HW_KEY
88     /* Few extra bytes for encoding and for public exponent. */
89     uint8_t key_buf[SIG_BUF_SIZE + SIG_EXTRA_BYTES];
90     bootutil_sha_context sha_ctx;
91 #endif
92     int rc;
93 
94     /* Copy the software version information from the image header. */
95     metadata->sw_version.major = hdr->ih_ver.iv_major;
96     metadata->sw_version.minor = hdr->ih_ver.iv_minor;
97     metadata->sw_version.revision = hdr->ih_ver.iv_revision;
98     metadata->sw_version.build_num = hdr->ih_ver.iv_build_num;
99 
100     /* Traverse through all of the TLVs for the required items. */
101     rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false);
102     if (rc) {
103         return rc;
104     }
105 
106     while (true) {
107         rc = bootutil_tlv_iter_next(&it, &off, &len, &type);
108         if (rc < 0) {
109             return -1;
110         } else if (rc > 0) {
111             break;
112         }
113 
114         if (type == EXPECTED_HASH_TLV) {
115             /* Retrieve the image hash (measurement value) from the TLV area. */
116             if (len > measurement_buf_size) {
117                 return -1;
118             }
119             rc = LOAD_IMAGE_DATA(hdr, fap, off, measurement_buf, len);
120             if (rc) {
121                 return -1;
122             }
123 #ifdef MCUBOOT_HW_KEY
124         } else if (type == IMAGE_TLV_PUBKEY) {
125             /* Retrieve the signer ID (hash of PUBKEY) from the TLV area. */
126             if (len > sizeof(key_buf)) {
127                 /* Something is wrong with the public key, proceed without
128                  * the signer ID.
129                  */
130                 continue;
131             }
132             rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len);
133             if (rc) {
134                 /* Proceed without this piece of data. */
135                 continue;
136             }
137 
138             /* Calculate the hash of the public key (signer ID). */
139             bootutil_sha_init(&sha_ctx);
140             bootutil_sha_update(&sha_ctx, key_buf, len);
141             bootutil_sha_finish(&sha_ctx, metadata->signer_id);
142 #else
143         } else if (type == IMAGE_TLV_KEYHASH) {
144             /* Retrieve the signer ID (hash of PUBKEY) from the TLV area. */
145             if (len != MCUBOOT_HASH_SIZE) {
146                 /* Something is wrong with the key hash, proceed without
147                  * the signer ID.
148                  */
149                 continue;
150             }
151             rc = LOAD_IMAGE_DATA(hdr, fap, off,
152                                  metadata->signer_id, MCUBOOT_HASH_SIZE);
153             if (rc) {
154                 /* Proceed without this piece of data. */
155                 continue;
156             }
157 #endif /* MCUBOOT_HW_KEY */
158             metadata->signer_id_size = MCUBOOT_HASH_SIZE;
159         }
160     }
161 
162     return 0;
163 }
164 #endif /* TFM_MEASURED_BOOT_API */
165 
166 /**
167  * Add application specific data to the shared memory area between the
168  * bootloader and runtime SW.
169  *
170  * @param[in]  hdr           Pointer to the image header stored in RAM.
171  * @param[in]  fap           Pointer to the flash area where image is stored.
172  * @param[in]  active_slot   Which slot is active (to boot).
173  * @param[in]  max_app_size  Maximum allowed size of application for update
174  *                           slot.
175  *
176  * @return                0 on success; nonzero on failure.
177  */
boot_save_shared_data(const struct image_header * hdr,const struct flash_area * fap,const uint8_t active_slot,const int max_app_size)178 int boot_save_shared_data(const struct image_header *hdr,
179                           const struct flash_area *fap,
180                           const uint8_t active_slot,
181                           const int max_app_size)
182 {
183     const struct flash_area *temp_fap;
184     uint8_t mcuboot_image_id = 0;
185     uint8_t i;
186     int32_t rc;
187 #ifdef TFM_PARTITION_FIRMWARE_UPDATE
188     struct image_version image_ver;
189     uint16_t fwu_minor;
190 #endif
191 #ifdef TFM_MEASURED_BOOT_API
192     enum boot_measurement_slot_t slot_id;
193     uint8_t image_hash[MCUBOOT_HASH_SIZE];
194     struct boot_measurement_metadata metadata = {
195         .measurement_type = MCUBOOT_HASH_ALG,
196         .signer_id = { 0 },
197         .signer_id_size = 0,
198         .sw_type = "",
199         .sw_version = { 0 },
200     };
201 #endif /* TFM_MEASURED_BOOT_API */
202 
203     (void)active_slot;
204     (void)max_app_size;
205 
206     if (hdr == NULL || fap == NULL) {
207         return -1;
208     }
209 
210     /* Look for the given flash area to determine the image ID. */
211     for (i = 0; i < MCUBOOT_IMAGE_NUMBER; i++) {
212         if (flash_area_open(FLASH_AREA_IMAGE_PRIMARY(i), &temp_fap) == 0 &&
213             fap == temp_fap) {
214             mcuboot_image_id = i;
215             break;
216         }
217 #if defined(MCUBOOT_DIRECT_XIP) || defined(MCUBOOT_RAM_LOAD)
218         else if (flash_area_open(FLASH_AREA_IMAGE_SECONDARY(i), &temp_fap) == 0 &&
219                  fap == temp_fap) {
220             mcuboot_image_id = i;
221             break;
222         }
223 #endif
224     }
225 
226     if (i == MCUBOOT_IMAGE_NUMBER) {
227         return -1;
228     }
229 
230 #ifdef TFM_PARTITION_FIRMWARE_UPDATE
231     image_ver = hdr->ih_ver;
232 
233     /* Currently hardcode it to 0 which indicates the full image. */
234     fwu_minor = SET_FWU_MINOR(mcuboot_image_id, SW_VERSION);
235     rc = boot_add_data_to_shared_area(TLV_MAJOR_FWU,
236                                       fwu_minor,
237                                       sizeof(image_ver),
238                                       (const uint8_t *)&image_ver);
239     if (rc) {
240         return rc;
241     }
242 #endif /* TFM_PARTITION_FIRMWARE_UPDATE */
243 
244 #ifdef TFM_MEASURED_BOOT_API
245     /* Determine the index of the measurement slot. */
246     slot_id = BOOT_MEASUREMENT_SLOT_RT_0 + mcuboot_image_id;
247 
248     switch (slot_id) {
249     case BOOT_MEASUREMENT_SLOT_RT_0:
250         if (sizeof(metadata.sw_type) < sizeof("RT_0")) {
251             return 1;
252         }
253         memcpy(metadata.sw_type, "RT_0", sizeof("RT_0"));
254         break;
255     case BOOT_MEASUREMENT_SLOT_RT_1:
256         if (sizeof(metadata.sw_type) < sizeof("RT_1")) {
257             return 1;
258         }
259         memcpy(metadata.sw_type, "RT_1", sizeof("RT_1"));
260         break;
261     case BOOT_MEASUREMENT_SLOT_RT_2:
262         if (sizeof(metadata.sw_type) < sizeof("RT_2")) {
263             return 1;
264         }
265         memcpy(metadata.sw_type, "RT_2", sizeof("RT_2"));
266         break;
267     default:
268         /* Proceed without this piece of data. */
269         break;
270     }
271 
272     rc = collect_image_measurement_and_metadata(hdr, fap,
273                                                 &metadata,
274                                                 image_hash,
275                                                 sizeof(image_hash));
276     if (rc) {
277         return rc;
278     }
279 
280     /* Save the boot measurement(s) about the runtime image(s).
281      * If there are multiple images, the measurement slot will be extended
282      * with the subsequent measurements.
283      */
284     rc = boot_store_measurement((uint8_t)slot_id, image_hash,
285                                 sizeof(image_hash), &metadata, false);
286     if (rc) {
287         return rc;
288     }
289 #endif /* TFM_MEASURED_BOOT_API */
290 
291     return 0;
292 }
293