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