blob: 263088d23404d95b600b8e5a7cada4ef6c4edd3e [file] [log] [blame]
Tamas Bana9de4a62018-09-18 08:09:45 +01001/*
Tamas Ban5b647472019-01-05 08:59:30 +00002 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
Tamas Bana9de4a62018-09-18 08:09:45 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include "boot_record.h"
9#include "tfm_boot_status.h"
10#include "target.h"
Tamas Ban0e8ab302019-01-17 11:45:31 +000011#include "../ext/mcuboot/bootutil/include/bootutil/image.h"
12#include "../ext/mcuboot/include/flash_map/flash_map.h"
Tamas Bana9de4a62018-09-18 08:09:45 +010013#include <stdint.h>
14#include <string.h>
Tamas Ban0e8ab302019-01-17 11:45:31 +000015#include <stdio.h>
Tamas Bana9de4a62018-09-18 08:09:45 +010016
17/*!
18 * \var shared_memory_init_done
19 *
20 * \brief Indicates whether shared memory area was already initialized.
21 *
22 */
23static uint32_t shared_memory_init_done;
24
25/*!
26 * \def SHARED_MEMORY_UNINITIALZED
27 *
28 * \brief Indicates that shared memory is uninitialized.
29 */
30#define SHARED_MEMORY_UNINITIALZED (0u)
31
32/*!
33 * \def SHARED_MEMORY_INITIALZED
34 *
35 * \brief Indicates that shared memory was already initialized.
36 */
37#define SHARED_MEMORY_INITIALZED (1u)
38
Tamas Ban0e8ab302019-01-17 11:45:31 +000039/*!
40 * \brief Add the measurement data of SW component to the shared memory area
41 *
42 * Measurements data are:
43 * - measurement value: Hash of the image, read out from the image's manifest
44 * section.
45 * - measurement type: Short test description: SHA256, etc.
46 * - signer ID: Hash of the image public key, read out from the
47 * image's manifest section.
48 *
49 * \param[in] sw_module Identifier of the SW component
50 * \param[in] hdr Pointer to the image header stored in RAM
51 * \param[in] fap Pointer to the flash area where image is stored
52 *
53 * \return Returns error code as specified in \ref boot_status_err_t
54 */
55static enum boot_status_err_t
56boot_save_sw_measurements(uint8_t sw_module,
57 const struct image_header *hdr,
58 const struct flash_area *fap)
59{
60 struct image_tlv_info tlv_header;
61 struct image_tlv tlv_entry;
62 uintptr_t tlv_end, offset;
63 uint8_t buf[32];
64 int32_t res;
65 uint16_t ias_minor;
66 enum shared_memory_err_t res2;
67 char measure_type[] = "SHA256";
68
69 /* Manifest data is concatenated to the end of the image. It is encoded in
70 * TLV format.
71 */
72 offset = hdr->ih_img_size + hdr->ih_hdr_size;
73
74 res = flash_area_read(fap, offset, &tlv_header, sizeof(tlv_header));
75 if (res) {
76 return BOOT_STATUS_ERROR;
77 }
78 if (tlv_header.it_magic != IMAGE_TLV_INFO_MAGIC) {
79 return BOOT_STATUS_ERROR;
80 }
81 tlv_end = offset + tlv_header.it_tlv_tot;
82 offset += sizeof(tlv_header);
83
84 /* Iterates over the manifest data and copy the relevant attributes to the
85 * shared data area:
86 * - image hash: SW component measurement value
87 * - public key hash: Signer ID
88 */
89 for (; offset < tlv_end; offset += sizeof(tlv_entry) + tlv_entry.it_len) {
90 res = flash_area_read(fap, offset, &tlv_entry, sizeof(tlv_entry));
91 if (res) {
92 return BOOT_STATUS_ERROR;
93 }
94
95 if (tlv_entry.it_type == IMAGE_TLV_SHA256) {
96 /* Get the image's hash value from the manifest section */
97 res = flash_area_read(fap, offset + sizeof(tlv_entry),
98 buf, tlv_entry.it_len);
99 if (res) {
100 return BOOT_STATUS_ERROR;
101 }
102
103 /* Add the image's hash value to the shared data area */
104 ias_minor = SET_IAS_MINOR(sw_module, SW_MEASURE_VALUE);
105 res2 = boot_add_data_to_shared_area(TLV_MAJOR_IAS,
106 ias_minor,
107 tlv_entry.it_len,
108 buf);
109 if (res2) {
110 return BOOT_STATUS_ERROR;
111 }
112
113 /* Add the measurement type to the shared data area */
114 ias_minor = SET_IAS_MINOR(sw_module, SW_MEASURE_TYPE);
115 res2 = boot_add_data_to_shared_area(TLV_MAJOR_IAS,
116 ias_minor,
117 sizeof(measure_type) - 1,
118 (const uint8_t *)measure_type);
119 if (res2) {
120 return BOOT_STATUS_ERROR;
121 }
122
123#ifdef MCUBOOT_SIGN_RSA
124 } else if (tlv_entry.it_type == IMAGE_TLV_KEYHASH) {
125 /* Get the hash of the public key from the manifest section */
126 res = flash_area_read(fap, offset + sizeof(tlv_entry),
127 buf, tlv_entry.it_len);
128 if (res) {
129 return BOOT_STATUS_ERROR;
130 }
131
132 /* Add the hash of the public key to the shared data area */
133 ias_minor = SET_IAS_MINOR(sw_module, SW_SIGNER_ID);
134 res2 = boot_add_data_to_shared_area(TLV_MAJOR_IAS,
135 ias_minor,
136 tlv_entry.it_len,
137 buf);
138 if (res2) {
139 return BOOT_STATUS_ERROR;
140 }
141#endif
142 }
143 }
144
145 return BOOT_STATUS_OK;
146}
147
148/*!
149 * \brief Add the security epoch counter of SW component to the shared
150 * memory area
151 *
152 * \param[in] sw_module Identifier of the SW component
153 *
154 * \return Returns error code as specified in \ref boot_status_err_t
155 */
156static enum boot_status_err_t
157boot_save_sw_epoch(uint8_t sw_module)
158{
159 /*FixMe: Epoch does not exist in the current MCUBoot image manifest. Use a
160 * hard coded value for now.
161 */
162 uint32_t epoch = 0;
163 uint16_t ias_minor;
164 enum shared_memory_err_t res;
165
166 /* Add the security epoch counter of the SW components to the shared data */
167 ias_minor = SET_IAS_MINOR(sw_module, SW_EPOCH);
168 res = boot_add_data_to_shared_area(TLV_MAJOR_IAS,
169 ias_minor,
170 sizeof(epoch),
171 (const uint8_t *)&epoch);
172 if (res) {
173 return BOOT_STATUS_ERROR;
174 }
175
176 return BOOT_STATUS_OK;
177}
178
179/*!
180 * \brief Add a type identifier(short test name) of SW component to the shared
181 * memory area
182 *
183 * \param[in] sw_module Identifier of the SW component
184 *
185 * \return Returns error code as specified in \ref boot_status_err_t
186 */
187static enum boot_status_err_t
188boot_save_sw_type(uint8_t sw_module)
189{
190 /*FixMe: Use a hard coded value for now. Later on when multiple image will
191 * be handled by MCUBoot then this must be revisited.
192 */
193 uint16_t ias_minor;
194 enum shared_memory_err_t res;
195 char sw_type[] = "NSPE_SPE";
196
197 /* Add the type identifier of the SW component to the shared data area */
198 ias_minor = SET_IAS_MINOR(sw_module, SW_TYPE);
199 res = boot_add_data_to_shared_area(TLV_MAJOR_IAS,
200 ias_minor,
201 sizeof(sw_type) - 1,
202 (const uint8_t *)sw_type);
203 if (res) {
204 return BOOT_STATUS_ERROR;
205 }
206
207 return BOOT_STATUS_OK;
208}
209
210/*!
211 * \brief Add the version of SW component to the shared memory area
212 *
213 * \param[in] sw_module Identifier of the SW component
214 * \param[in] hdr Pointer to the image header stored in RAM
215 *
216 * \return Returns error code as specified in \ref boot_status_err_t
217 */
218static enum boot_status_err_t
219boot_save_sw_version(uint8_t sw_module,
220 const struct image_header *hdr)
221{
222 int32_t cnt;
223 enum shared_memory_err_t res;
224 char sw_version[14]; /* 8bit.8bit.16bit: 3 + 1 + 3 + 1 + 5 + 1 */
225 uint16_t ias_minor;
226
227 /* FixMe: snprintf can be replaced with a custom implementation */
228 cnt = snprintf(sw_version, sizeof(sw_version), "%u.%u.%u",
229 hdr->ih_ver.iv_major,
230 hdr->ih_ver.iv_minor,
231 hdr->ih_ver.iv_revision);
232 if (cnt < 0 || cnt >= sizeof(sw_version)) {
233 return BOOT_STATUS_ERROR;
234 }
235
236 /* Add the version of the SW component to the shared data area */
237 ias_minor = SET_IAS_MINOR(sw_module, SW_VERSION);
238 res = boot_add_data_to_shared_area(TLV_MAJOR_IAS,
239 ias_minor,
240 cnt,
241 (const uint8_t *)sw_version);
242 if (res) {
243 return BOOT_STATUS_ERROR;
244 }
245
246 return BOOT_STATUS_OK;
247}
248
249/* See in boot_record.h */
Tamas Bana9de4a62018-09-18 08:09:45 +0100250enum shared_memory_err_t
251boot_add_data_to_shared_area(uint8_t major_type,
Tamas Ban5b647472019-01-05 08:59:30 +0000252 uint16_t minor_type,
Tamas Bana9de4a62018-09-18 08:09:45 +0100253 size_t size,
254 const uint8_t *data)
255{
256 struct shared_data_tlv_entry tlv_entry = {0};
Tamas Bana24ce042019-02-20 11:50:22 +0000257 struct tfm_boot_data *boot_data;
Tamas Bana9de4a62018-09-18 08:09:45 +0100258 uint8_t *next_tlv;
259 uintptr_t tlv_end, offset;
260
Tamas Bana24ce042019-02-20 11:50:22 +0000261 boot_data = (struct tfm_boot_data *)BOOT_TFM_SHARED_DATA_BASE;
Tamas Bana9de4a62018-09-18 08:09:45 +0100262
263 /* Check whether first time to call this function. If does then initialise
264 * shared data area.
265 */
266 if (shared_memory_init_done == SHARED_MEMORY_UNINITIALZED) {
267 memset((void *)BOOT_TFM_SHARED_DATA_BASE, 0, BOOT_TFM_SHARED_DATA_SIZE);
Tamas Bana24ce042019-02-20 11:50:22 +0000268 boot_data->header.tlv_magic = SHARED_DATA_TLV_INFO_MAGIC;
269 boot_data->header.tlv_tot_len = SHARED_DATA_HEADER_SIZE;
Tamas Bana9de4a62018-09-18 08:09:45 +0100270 shared_memory_init_done = SHARED_MEMORY_INITIALZED;
271 }
272
273 /* Check whether TLV entry is already added.
274 * Get the boundaries of TLV section
275 */
Tamas Bana24ce042019-02-20 11:50:22 +0000276 tlv_end = BOOT_TFM_SHARED_DATA_BASE + boot_data->header.tlv_tot_len;
Tamas Bana9de4a62018-09-18 08:09:45 +0100277 offset = BOOT_TFM_SHARED_DATA_BASE + SHARED_DATA_HEADER_SIZE;
278
279 /* Iterates over the TLV section looks for the same entry if found then
280 * returns with error: SHARED_MEMORY_OVERWRITE
281 */
Tamas Ban0e8ab302019-01-17 11:45:31 +0000282 for (; offset < tlv_end; offset += tlv_entry.tlv_len) {
Tamas Banc43181d2019-02-18 14:21:35 +0000283 /* Create local copy to avoid unaligned access */
284 memcpy(&tlv_entry, (const void *)offset, SHARED_DATA_ENTRY_HEADER_SIZE);
Tamas Ban5b647472019-01-05 08:59:30 +0000285 if (GET_MAJOR(tlv_entry.tlv_type) == major_type &&
286 GET_MINOR(tlv_entry.tlv_type) == minor_type) {
Tamas Bana9de4a62018-09-18 08:09:45 +0100287 return SHARED_MEMORY_OVERWRITE;
288 }
289 }
290
291 /* Add TLV entry */
Tamas Ban5b647472019-01-05 08:59:30 +0000292 tlv_entry.tlv_type = SET_TLV_TYPE(major_type, minor_type);
293 tlv_entry.tlv_len = SHARED_DATA_ENTRY_SIZE(size);
Tamas Bana9de4a62018-09-18 08:09:45 +0100294
295 /* Verify overflow of shared area */
Tamas Bana24ce042019-02-20 11:50:22 +0000296 if ((boot_data->header.tlv_tot_len + tlv_entry.tlv_len) >
Tamas Bana9de4a62018-09-18 08:09:45 +0100297 BOOT_TFM_SHARED_DATA_SIZE){
298 return SHARED_MEMORY_OVERFLOW;
299 }
300
Tamas Bana24ce042019-02-20 11:50:22 +0000301 next_tlv = (uint8_t *)boot_data + boot_data->header.tlv_tot_len;
Tamas Bana9de4a62018-09-18 08:09:45 +0100302 memcpy(next_tlv, &tlv_entry, SHARED_DATA_ENTRY_HEADER_SIZE);
303
304 next_tlv += SHARED_DATA_ENTRY_HEADER_SIZE;
305 memcpy(next_tlv, data, size);
306
Tamas Bana24ce042019-02-20 11:50:22 +0000307 boot_data->header.tlv_tot_len += tlv_entry.tlv_len;
Tamas Bana9de4a62018-09-18 08:09:45 +0100308
309 return SHARED_MEMORY_OK;
310}
Tamas Ban0e8ab302019-01-17 11:45:31 +0000311
312/* See in boot_record.h */
313enum boot_status_err_t
314boot_save_boot_status(uint8_t sw_module,
315 const struct image_header *hdr,
316 const struct flash_area *fap)
317{
318 enum boot_status_err_t res;
319
320 res = boot_save_sw_type(sw_module);
321 if (res) {
322 return res;
323 }
324
325 res = boot_save_sw_version(sw_module, hdr);
326 if (res) {
327 return res;
328 }
329
330 res = boot_save_sw_epoch(sw_module);
331 if (res) {
332 return res;
333 }
334
335 res = boot_save_sw_measurements(sw_module, hdr, fap);
336 if (res) {
337 return res;
338 }
339
340 return BOOT_STATUS_OK;
341}