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_sizes The maximum sizes of images that can be loaded.
174 *
175 * @return 0 on success; nonzero on failure.
176 */
boot_save_shared_data(const struct image_header * hdr,const struct flash_area * fap,const uint8_t active_slot,const struct image_max_size * max_app_sizes)177 int boot_save_shared_data(const struct image_header *hdr,
178 const struct flash_area *fap,
179 const uint8_t active_slot,
180 const struct image_max_size *max_app_sizes)
181 {
182 const struct flash_area *temp_fap;
183 uint8_t mcuboot_image_id = 0;
184 uint8_t i;
185 int32_t rc;
186 #ifdef TFM_PARTITION_FIRMWARE_UPDATE
187 struct image_version image_ver;
188 uint16_t fwu_minor;
189 #endif
190 #ifdef TFM_MEASURED_BOOT_API
191 enum boot_measurement_slot_t slot_id;
192 uint8_t image_hash[MCUBOOT_HASH_SIZE];
193 struct boot_measurement_metadata metadata = {
194 .measurement_type = MCUBOOT_HASH_ALG,
195 .signer_id = { 0 },
196 .signer_id_size = 0,
197 .sw_type = "",
198 .sw_version = { 0 },
199 };
200 #endif /* TFM_MEASURED_BOOT_API */
201
202 (void)active_slot;
203 (void)max_app_sizes;
204
205 if (hdr == NULL || fap == NULL) {
206 return -1;
207 }
208
209 /* Look for the given flash area to determine the image ID. */
210 for (i = 0; i < MCUBOOT_IMAGE_NUMBER; i++) {
211 if (flash_area_open(FLASH_AREA_IMAGE_PRIMARY(i), &temp_fap) == 0 &&
212 fap == temp_fap) {
213 mcuboot_image_id = i;
214 break;
215 }
216 #if defined(MCUBOOT_DIRECT_XIP) || defined(MCUBOOT_RAM_LOAD)
217 else if (flash_area_open(FLASH_AREA_IMAGE_SECONDARY(i), &temp_fap) == 0 &&
218 fap == temp_fap) {
219 mcuboot_image_id = i;
220 break;
221 }
222 #endif
223 }
224
225 if (i == MCUBOOT_IMAGE_NUMBER) {
226 return -1;
227 }
228
229 #ifdef TFM_PARTITION_FIRMWARE_UPDATE
230 image_ver = hdr->ih_ver;
231
232 /* Currently hardcode it to 0 which indicates the full image. */
233 fwu_minor = SET_FWU_MINOR(mcuboot_image_id, SW_VERSION);
234 rc = boot_add_data_to_shared_area(TLV_MAJOR_FWU,
235 fwu_minor,
236 sizeof(image_ver),
237 (const uint8_t *)&image_ver);
238 if (rc) {
239 return rc;
240 }
241 #endif /* TFM_PARTITION_FIRMWARE_UPDATE */
242
243 #ifdef TFM_MEASURED_BOOT_API
244 /* Determine the index of the measurement slot. */
245 slot_id = BOOT_MEASUREMENT_SLOT_RT_0 + mcuboot_image_id;
246
247 switch (slot_id) {
248 case BOOT_MEASUREMENT_SLOT_RT_0:
249 if (sizeof(metadata.sw_type) < sizeof("RT_0")) {
250 return 1;
251 }
252 memcpy(metadata.sw_type, "RT_0", sizeof("RT_0"));
253 break;
254 case BOOT_MEASUREMENT_SLOT_RT_1:
255 if (sizeof(metadata.sw_type) < sizeof("RT_1")) {
256 return 1;
257 }
258 memcpy(metadata.sw_type, "RT_1", sizeof("RT_1"));
259 break;
260 case BOOT_MEASUREMENT_SLOT_RT_2:
261 if (sizeof(metadata.sw_type) < sizeof("RT_2")) {
262 return 1;
263 }
264 memcpy(metadata.sw_type, "RT_2", sizeof("RT_2"));
265 break;
266 default:
267 /* Proceed without this piece of data. */
268 break;
269 }
270
271 rc = collect_image_measurement_and_metadata(hdr, fap,
272 &metadata,
273 image_hash,
274 sizeof(image_hash));
275 if (rc) {
276 return rc;
277 }
278
279 /* Save the boot measurement(s) about the runtime image(s).
280 * If there are multiple images, the measurement slot will be extended
281 * with the subsequent measurements.
282 */
283 rc = boot_store_measurement((uint8_t)slot_id, image_hash,
284 sizeof(image_hash), &metadata, false);
285 if (rc) {
286 return rc;
287 }
288 #endif /* TFM_MEASURED_BOOT_API */
289
290 return 0;
291 }
292