blob: cb51b666ca607a3419326936291df3e0f141e233 [file] [log] [blame]
Sherry Zhang07b42412021-01-07 14:19:41 +08001/*
David Vincze8c95d2a2022-01-19 10:11:58 +01002 * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
Sherry Zhang07b42412021-01-07 14:19:41 +08003 *
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"
David Vincze8c95d2a2022-01-19 10:11:58 +010013#include "mcuboot_config/mcuboot_config.h"
14
15#if defined(CONFIG_TFM_BOOT_STORE_MEASUREMENTS) && !defined(MCUBOOT_MEASURED_BOOT)
16#include <stdio.h>
17#include "boot_hal.h"
18#include "boot_measurement.h"
19#include "bootutil_priv.h"
20#include "psa/crypto.h"
21
22#define MCUBOOT_HASH_ALG PSA_ALG_SHA_256
23#define MCUBOOT_HASH_SIZE (32)
24
25#ifdef MCUBOOT_HW_KEY
26#include "bootutil/crypto/sha256.h"
27#define SIG_BUF_SIZE (MCUBOOT_SIGN_RSA_LEN / 8)
28#endif
29#endif /* CONFIG_TFM_BOOT_STORE_MEASUREMENTS && !MCUBOOT_MEASURED_BOOT */
Sherry Zhang07b42412021-01-07 14:19:41 +080030
31/* Firmware Update specific macros */
32#define TLV_MAJOR_FWU 0x2
33#define MODULE_MASK 0x3F /* 6 bit */
34#define CLAIM_MASK 0x3F /* 6 bit */
35
36#define SET_FWU_MINOR(sw_module, claim) \
37 ((uint16_t)((sw_module & MODULE_MASK) << 6) | \
38 (uint16_t)(claim & CLAIM_MASK))
39
David Vincze8c95d2a2022-01-19 10:11:58 +010040#ifdef TFM_PARTITION_FIRMWARE_UPDATE
41extern int boot_add_data_to_shared_area(uint8_t major_type,
42 uint16_t minor_type,
43 size_t size,
44 const uint8_t *data);
45#endif /* TFM_PARTITION_FIRMWARE_UPDATE */
46
47
48#if defined(CONFIG_TFM_BOOT_STORE_MEASUREMENTS) && !defined(MCUBOOT_MEASURED_BOOT)
49/**
50 * Collect boot measurement and available associated metadata from the
51 * TLV area of an image.
52 *
53 * @param[in] hdr Pointer to the image header stored in RAM.
54 * @param[in] fap Pointer to the flash area where image is stored.
55 * @param[out] metadata Pointer to measurement metadata structure.
56 * @param[out] measurement_buf Buffer to store the boot measurement.
57 * @param[in] measurement_buf_size As an input value it indicates the size
58 * of the measurement buffer in bytes.
59 *
60 * @return 0 on success; nonzero on failure.
61 *
62 */
63static int collect_image_measurement_and_metadata(
64 const struct image_header *hdr,
65 const struct flash_area *fap,
66 struct boot_measurement_metadata *metadata,
67 uint8_t *measurement_buf,
68 size_t measurement_buf_size)
69{
70 struct image_tlv_iter it;
71 uint32_t off;
72 uint16_t len;
73 uint16_t type;
74#ifdef MCUBOOT_HW_KEY
75 /* Few extra bytes for encoding and for public exponent. */
76 uint8_t key_buf[SIG_BUF_SIZE + 24];
77 bootutil_sha256_context sha256_ctx;
78#endif
79 int rc;
80
81 /* Copy the software version information from the image header. */
82 rc = snprintf(metadata->sw_version, sizeof(metadata->sw_version),
83 "%u.%u.%u+%u",
84 hdr->ih_ver.iv_major,
85 hdr->ih_ver.iv_minor,
86 hdr->ih_ver.iv_revision,
87 hdr->ih_ver.iv_build_num);
88 if ((rc < 0) || (rc >= sizeof(metadata->sw_version))) {
89 return -1;
90 }
91
92 /* Traverse through all of the TLVs for the required items. */
93 rc = bootutil_tlv_iter_begin(&it, hdr, fap, IMAGE_TLV_ANY, false);
94 if (rc) {
95 return rc;
96 }
97
98 while (true) {
99 rc = bootutil_tlv_iter_next(&it, &off, &len, &type);
100 if (rc < 0) {
101 return -1;
102 } else if (rc > 0) {
103 break;
104 }
105
106 if (type == IMAGE_TLV_SHA256) {
107 /* Retrieve the image hash (measurement value) from the TLV area. */
108 if (len > measurement_buf_size) {
109 return -1;
110 }
111 rc = LOAD_IMAGE_DATA(hdr, fap, off, measurement_buf, len);
112 if (rc) {
113 return -1;
114 }
115#ifdef MCUBOOT_HW_KEY
116 } else if (type == IMAGE_TLV_PUBKEY) {
117 /* Retrieve the signer ID (hash of PUBKEY) from the TLV area. */
118 if (len > sizeof(key_buf)) {
119 /* Something is wrong with the public key, proceed without
120 * the signer ID.
121 */
122 continue;
123 }
124 rc = LOAD_IMAGE_DATA(hdr, fap, off, key_buf, len);
125 if (rc) {
126 /* Proceed without this piece of data. */
127 continue;
128 }
129
130 /* Calculate the hash of the public key (signer ID). */
131 bootutil_sha256_init(&sha256_ctx);
132 bootutil_sha256_update(&sha256_ctx, key_buf, len);
133 bootutil_sha256_finish(&sha256_ctx, metadata->signer_id);
134#else
135 } else if (type == IMAGE_TLV_KEYHASH) {
136 /* Retrieve the signer ID (hash of PUBKEY) from the TLV area. */
137 if (len != MCUBOOT_HASH_SIZE) {
138 /* Something is wrong with the key hash, proceed without
139 * the signer ID.
140 */
141 continue;
142 }
143 rc = LOAD_IMAGE_DATA(hdr, fap, off,
144 metadata->signer_id, MCUBOOT_HASH_SIZE);
145 if (rc) {
146 /* Proceed without this piece of data. */
147 continue;
148 }
149#endif /* MCUBOOT_HW_KEY */
150 metadata->signer_id_size = MCUBOOT_HASH_SIZE;
151 }
152 }
153
154 return 0;
155}
156#endif /* CONFIG_TFM_BOOT_STORE_MEASUREMENTS && !MCUBOOT_MEASURED_BOOT */
Sherry Zhang07b42412021-01-07 14:19:41 +0800157
158/**
159 * Add application specific data to the shared memory area between the
160 * bootloader and runtime SW.
161 *
162 * @param[in] hdr Pointer to the image header stored in RAM.
163 * @param[in] fap Pointer to the flash area where image is stored.
164 *
165 * @return 0 on success; nonzero on failure.
166 */
167int boot_save_shared_data(const struct image_header *hdr,
168 const struct flash_area *fap)
169{
Sherry Zhang07b42412021-01-07 14:19:41 +0800170 const struct flash_area *temp_fap;
171 uint8_t mcuboot_image_id = 0;
172 uint8_t i;
David Vincze8c95d2a2022-01-19 10:11:58 +0100173 int32_t rc;
174#ifdef TFM_PARTITION_FIRMWARE_UPDATE
Jamie Foxc48bb6c2022-12-01 15:51:43 +0000175 struct image_version image_ver;
David Vincze8c95d2a2022-01-19 10:11:58 +0100176 uint16_t fwu_minor;
177#endif
178#if defined(CONFIG_TFM_BOOT_STORE_MEASUREMENTS) && !defined(MCUBOOT_MEASURED_BOOT)
179 enum boot_measurement_slot_t slot_id;
180 uint8_t image_hash[MCUBOOT_HASH_SIZE];
181 struct boot_measurement_metadata metadata = {
182 .measurement_type = MCUBOOT_HASH_ALG,
183 .sw_type = "",
184 .sw_version = "",
185 .signer_id = { 0 },
186 .signer_id_size = 0,
187 };
188#endif /* CONFIG_TFM_BOOT_STORE_MEASUREMENTS && !MCUBOOT_MEASURED_BOOT */
Sherry Zhang07b42412021-01-07 14:19:41 +0800189
190 if (hdr == NULL || fap == NULL) {
191 return -1;
192 }
193
David Vincze8c95d2a2022-01-19 10:11:58 +0100194 /* Look for the given flash area to determine the image ID. */
Sherry Zhang07b42412021-01-07 14:19:41 +0800195 for (i = 0; i < MCUBOOT_IMAGE_NUMBER; i++) {
Jamie Fox7980b232022-08-15 16:56:33 +0100196 if (flash_area_open(FLASH_AREA_IMAGE_PRIMARY(i), &temp_fap) == 0 &&
197 fap == temp_fap) {
Sherry Zhang07b42412021-01-07 14:19:41 +0800198 mcuboot_image_id = i;
199 break;
200 }
Jamie Fox7980b232022-08-15 16:56:33 +0100201#if defined(MCUBOOT_DIRECT_XIP) || defined(MCUBOOT_RAM_LOAD)
202 else if (flash_area_open(FLASH_AREA_IMAGE_SECONDARY(i), &temp_fap) == 0 &&
203 fap == temp_fap) {
204 mcuboot_image_id = i;
205 break;
206 }
207#endif
Sherry Zhang07b42412021-01-07 14:19:41 +0800208 }
209
210 if (i == MCUBOOT_IMAGE_NUMBER) {
211 return -1;
212 }
213
Jamie Foxc48bb6c2022-12-01 15:51:43 +0000214#ifdef TFM_PARTITION_FIRMWARE_UPDATE
Sherry Zhang07b42412021-01-07 14:19:41 +0800215 image_ver = hdr->ih_ver;
216
Sherry Zhang07b42412021-01-07 14:19:41 +0800217 /* Currently hardcode it to 0 which indicates the full image. */
218 fwu_minor = SET_FWU_MINOR(mcuboot_image_id, SW_VERSION);
David Vincze8c95d2a2022-01-19 10:11:58 +0100219 rc = boot_add_data_to_shared_area(TLV_MAJOR_FWU,
220 fwu_minor,
221 sizeof(image_ver),
222 (const uint8_t *)&image_ver);
223 if (rc) {
224 return rc;
225 }
226#endif /* TFM_PARTITION_FIRMWARE_UPDATE */
227
228#if defined(CONFIG_TFM_BOOT_STORE_MEASUREMENTS) && !defined(MCUBOOT_MEASURED_BOOT)
229 /* Determine the index of the measurement slot. */
230 slot_id = BOOT_MEASUREMENT_SLOT_RT_0 + mcuboot_image_id;
231
232 switch (slot_id) {
233 case BOOT_MEASUREMENT_SLOT_RT_0:
Antonio de Angelise07a8ba2022-10-19 16:04:17 +0100234 if (sizeof(metadata.sw_type) < sizeof("RT_0")) {
235 return 1;
236 }
237 memcpy(metadata.sw_type, "RT_0", sizeof("RT_0"));
David Vincze8c95d2a2022-01-19 10:11:58 +0100238 break;
239 case BOOT_MEASUREMENT_SLOT_RT_1:
Antonio de Angelise07a8ba2022-10-19 16:04:17 +0100240 if (sizeof(metadata.sw_type) < sizeof("RT_1")) {
241 return 1;
242 }
243 memcpy(metadata.sw_type, "RT_1", sizeof("RT_1"));
David Vincze8c95d2a2022-01-19 10:11:58 +0100244 break;
245 case BOOT_MEASUREMENT_SLOT_RT_2:
Antonio de Angelise07a8ba2022-10-19 16:04:17 +0100246 if (sizeof(metadata.sw_type) < sizeof("RT_2")) {
247 return 1;
248 }
249 memcpy(metadata.sw_type, "RT_2", sizeof("RT_2"));
David Vincze8c95d2a2022-01-19 10:11:58 +0100250 break;
251 default:
252 /* Proceed without this piece of data. */
253 break;
254 }
255
256 rc = collect_image_measurement_and_metadata(hdr, fap,
257 &metadata,
258 image_hash,
259 sizeof(image_hash));
260 if (rc) {
261 return rc;
262 }
263
264 /* Save the boot measurement(s) about the runtime image(s).
265 * If there are multiple images, the measurement slot will be extended
266 * with the subsequent measurements.
267 */
268 rc = boot_store_measurement((uint8_t)slot_id, image_hash,
269 sizeof(image_hash), &metadata, false);
270 if (rc) {
271 return rc;
272 }
273#endif /* CONFIG_TFM_BOOT_STORE_MEASUREMENTS && !MCUBOOT_MEASURED_BOOT */
274
275 return 0;
Sherry Zhang07b42412021-01-07 14:19:41 +0800276}