Boot: Save SW component's boot satus info
Bootloader must provide certain attributes of the
authenticated SW components to the runtime SW.
These informations are included to the initial
attestation token.
Change-Id: I35f9cd4321e1f8ca776303bcb1e32d11cb5dabe6
Signed-off-by: Tamas Ban <tamas.ban@arm.com>
diff --git a/bl2/ext/mcuboot/bootutil/src/loader.c b/bl2/ext/mcuboot/bootutil/src/loader.c
index f038785..52602b8 100644
--- a/bl2/ext/mcuboot/bootutil/src/loader.c
+++ b/bl2/ext/mcuboot/bootutil/src/loader.c
@@ -251,12 +251,12 @@
* Validate image hash/signature in a slot.
*/
static int
-boot_image_check(struct image_header *hdr, const struct flash_area *fap, uint8_t *out_hash)
+boot_image_check(struct image_header *hdr, const struct flash_area *fap)
{
static uint8_t tmpbuf[BOOT_TMPBUF_SZ];
if (bootutil_img_validate(hdr, fap, tmpbuf, BOOT_TMPBUF_SZ,
- NULL, 0, out_hash)) {
+ NULL, 0, NULL)) {
return BOOT_EBADIMAGE;
}
return 0;
@@ -267,7 +267,6 @@
{
const struct flash_area *fap;
struct image_header *hdr;
- uint8_t hash[32];
int rc;
hdr = boot_img_hdr(&boot_data, slot);
@@ -282,7 +281,7 @@
}
if ((hdr->ih_magic != IMAGE_MAGIC ||
- boot_image_check(hdr, fap, hash) != 0)) {
+ boot_image_check(hdr, fap) != 0)) {
if (slot != 0) {
rc = flash_area_erase(fap, 0, fap->fa_size);
if(rc != 0) {
@@ -296,13 +295,6 @@
BOOT_LOG_ERR("Authentication failed! Image in slot %d is not valid.",
slot);
return -1;
- } else {
- if (0 != boot_add_data_to_shared_area(TLV_MAJOR_IAS,
- TLV_MINOR_IAS_S_NS_MEASURE_VALUE,
- sizeof(hash),
- hash)) {
- BOOT_LOG_ERR("Failed to add data to shared area");
- }
}
flash_area_close(fap);
@@ -1375,6 +1367,14 @@
rsp->br_image_off = boot_img_slot_off(&boot_data, 0);
rsp->br_hdr = boot_img_hdr(&boot_data, slot);
+ /* Save boot status to shared memory area */
+ rc = boot_save_boot_status(SW_S_NS,
+ rsp->br_hdr,
+ BOOT_IMG_AREA(&boot_data, slot));
+ if (rc) {
+ BOOT_LOG_ERR("Failed to add data to shared area");
+ }
+
out:
flash_area_close(BOOT_SCRATCH_AREA(&boot_data));
for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
@@ -1691,6 +1691,14 @@
rc = BOOT_EBADIMAGE;
}
+ /* Save boot status to shared memory area */
+ rc = boot_save_boot_status(SW_S_NS,
+ rsp->br_hdr,
+ BOOT_IMG_AREA(&boot_data, slot));
+ if (rc) {
+ BOOT_LOG_ERR("Failed to add data to shared area");
+ }
+
out:
for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
flash_area_close(BOOT_IMG_AREA(&boot_data, BOOT_NUM_SLOTS - 1 - slot));
diff --git a/bl2/include/boot_record.h b/bl2/include/boot_record.h
index f7a6308..217a206 100644
--- a/bl2/include/boot_record.h
+++ b/bl2/include/boot_record.h
@@ -11,6 +11,8 @@
#include <stdint.h>
#include <stddef.h>
#include <limits.h>
+#include "../ext/mcuboot/bootutil/include/bootutil/image.h"
+#include "../ext/mcuboot/include/flash_map/flash_map.h"
#ifdef __cplusplus
extern "C" {
@@ -31,6 +33,16 @@
};
/*!
+ * \enum boot_status_err_t
+ *
+ * \brief Return values for saving boot status information to shared memory are
+ */
+enum boot_status_err_t {
+ BOOT_STATUS_OK,
+ BOOT_STATUS_ERROR,
+};
+
+/*!
* \brief Add a data item to the shared data area between bootloader and
* runtime SW
*
@@ -47,6 +59,21 @@
size_t size,
const uint8_t *data);
+/*!
+ * \brief Add an image's all boot status information to the shared data area
+ * between bootloader and runtime SW
+ *
+ * \param[in] sw_module Identifier of the SW component
+ * \param[in] hdr Pointer to the image header stored in RAM
+ * \param[in] fap Pointer to the flash area where image is stored
+ *
+ * \return Returns error code as specified in \ref boot_status_err_t
+ */
+enum boot_status_err_t
+boot_save_boot_status(uint8_t sw_module,
+ const struct image_header *hdr,
+ const struct flash_area *fap);
+
#ifdef __cplusplus
}
#endif
diff --git a/bl2/src/boot_record.c b/bl2/src/boot_record.c
index b12b9e9..e24d2c4 100644
--- a/bl2/src/boot_record.c
+++ b/bl2/src/boot_record.c
@@ -8,8 +8,11 @@
#include "boot_record.h"
#include "tfm_boot_status.h"
#include "target.h"
+#include "../ext/mcuboot/bootutil/include/bootutil/image.h"
+#include "../ext/mcuboot/include/flash_map/flash_map.h"
#include <stdint.h>
#include <string.h>
+#include <stdio.h>
/*!
* \var shared_memory_init_done
@@ -33,6 +36,217 @@
*/
#define SHARED_MEMORY_INITIALZED (1u)
+/*!
+ * \brief Add the measurement data of SW component to the shared memory area
+ *
+ * Measurements data are:
+ * - measurement value: Hash of the image, read out from the image's manifest
+ * section.
+ * - measurement type: Short test description: SHA256, etc.
+ * - signer ID: Hash of the image public key, read out from the
+ * image's manifest section.
+ *
+ * \param[in] sw_module Identifier of the SW component
+ * \param[in] hdr Pointer to the image header stored in RAM
+ * \param[in] fap Pointer to the flash area where image is stored
+ *
+ * \return Returns error code as specified in \ref boot_status_err_t
+ */
+static enum boot_status_err_t
+boot_save_sw_measurements(uint8_t sw_module,
+ const struct image_header *hdr,
+ const struct flash_area *fap)
+{
+ struct image_tlv_info tlv_header;
+ struct image_tlv tlv_entry;
+ uintptr_t tlv_end, offset;
+ uint8_t buf[32];
+ int32_t res;
+ uint16_t ias_minor;
+ enum shared_memory_err_t res2;
+ char measure_type[] = "SHA256";
+
+ /* Manifest data is concatenated to the end of the image. It is encoded in
+ * TLV format.
+ */
+ offset = hdr->ih_img_size + hdr->ih_hdr_size;
+
+ res = flash_area_read(fap, offset, &tlv_header, sizeof(tlv_header));
+ if (res) {
+ return BOOT_STATUS_ERROR;
+ }
+ if (tlv_header.it_magic != IMAGE_TLV_INFO_MAGIC) {
+ return BOOT_STATUS_ERROR;
+ }
+ tlv_end = offset + tlv_header.it_tlv_tot;
+ offset += sizeof(tlv_header);
+
+ /* Iterates over the manifest data and copy the relevant attributes to the
+ * shared data area:
+ * - image hash: SW component measurement value
+ * - public key hash: Signer ID
+ */
+ for (; offset < tlv_end; offset += sizeof(tlv_entry) + tlv_entry.it_len) {
+ res = flash_area_read(fap, offset, &tlv_entry, sizeof(tlv_entry));
+ if (res) {
+ return BOOT_STATUS_ERROR;
+ }
+
+ if (tlv_entry.it_type == IMAGE_TLV_SHA256) {
+ /* Get the image's hash value from the manifest section */
+ res = flash_area_read(fap, offset + sizeof(tlv_entry),
+ buf, tlv_entry.it_len);
+ if (res) {
+ return BOOT_STATUS_ERROR;
+ }
+
+ /* Add the image's hash value to the shared data area */
+ ias_minor = SET_IAS_MINOR(sw_module, SW_MEASURE_VALUE);
+ res2 = boot_add_data_to_shared_area(TLV_MAJOR_IAS,
+ ias_minor,
+ tlv_entry.it_len,
+ buf);
+ if (res2) {
+ return BOOT_STATUS_ERROR;
+ }
+
+ /* Add the measurement type to the shared data area */
+ ias_minor = SET_IAS_MINOR(sw_module, SW_MEASURE_TYPE);
+ res2 = boot_add_data_to_shared_area(TLV_MAJOR_IAS,
+ ias_minor,
+ sizeof(measure_type) - 1,
+ (const uint8_t *)measure_type);
+ if (res2) {
+ return BOOT_STATUS_ERROR;
+ }
+
+#ifdef MCUBOOT_SIGN_RSA
+ } else if (tlv_entry.it_type == IMAGE_TLV_KEYHASH) {
+ /* Get the hash of the public key from the manifest section */
+ res = flash_area_read(fap, offset + sizeof(tlv_entry),
+ buf, tlv_entry.it_len);
+ if (res) {
+ return BOOT_STATUS_ERROR;
+ }
+
+ /* Add the hash of the public key to the shared data area */
+ ias_minor = SET_IAS_MINOR(sw_module, SW_SIGNER_ID);
+ res2 = boot_add_data_to_shared_area(TLV_MAJOR_IAS,
+ ias_minor,
+ tlv_entry.it_len,
+ buf);
+ if (res2) {
+ return BOOT_STATUS_ERROR;
+ }
+#endif
+ }
+ }
+
+ return BOOT_STATUS_OK;
+}
+
+/*!
+ * \brief Add the security epoch counter of SW component to the shared
+ * memory area
+ *
+ * \param[in] sw_module Identifier of the SW component
+ *
+ * \return Returns error code as specified in \ref boot_status_err_t
+ */
+static enum boot_status_err_t
+boot_save_sw_epoch(uint8_t sw_module)
+{
+ /*FixMe: Epoch does not exist in the current MCUBoot image manifest. Use a
+ * hard coded value for now.
+ */
+ uint32_t epoch = 0;
+ uint16_t ias_minor;
+ enum shared_memory_err_t res;
+
+ /* Add the security epoch counter of the SW components to the shared data */
+ ias_minor = SET_IAS_MINOR(sw_module, SW_EPOCH);
+ res = boot_add_data_to_shared_area(TLV_MAJOR_IAS,
+ ias_minor,
+ sizeof(epoch),
+ (const uint8_t *)&epoch);
+ if (res) {
+ return BOOT_STATUS_ERROR;
+ }
+
+ return BOOT_STATUS_OK;
+}
+
+/*!
+ * \brief Add a type identifier(short test name) of SW component to the shared
+ * memory area
+ *
+ * \param[in] sw_module Identifier of the SW component
+ *
+ * \return Returns error code as specified in \ref boot_status_err_t
+ */
+static enum boot_status_err_t
+boot_save_sw_type(uint8_t sw_module)
+{
+ /*FixMe: Use a hard coded value for now. Later on when multiple image will
+ * be handled by MCUBoot then this must be revisited.
+ */
+ uint16_t ias_minor;
+ enum shared_memory_err_t res;
+ char sw_type[] = "NSPE_SPE";
+
+ /* Add the type identifier of the SW component to the shared data area */
+ ias_minor = SET_IAS_MINOR(sw_module, SW_TYPE);
+ res = boot_add_data_to_shared_area(TLV_MAJOR_IAS,
+ ias_minor,
+ sizeof(sw_type) - 1,
+ (const uint8_t *)sw_type);
+ if (res) {
+ return BOOT_STATUS_ERROR;
+ }
+
+ return BOOT_STATUS_OK;
+}
+
+/*!
+ * \brief Add the version of SW component to the shared memory area
+ *
+ * \param[in] sw_module Identifier of the SW component
+ * \param[in] hdr Pointer to the image header stored in RAM
+ *
+ * \return Returns error code as specified in \ref boot_status_err_t
+ */
+static enum boot_status_err_t
+boot_save_sw_version(uint8_t sw_module,
+ const struct image_header *hdr)
+{
+ int32_t cnt;
+ enum shared_memory_err_t res;
+ char sw_version[14]; /* 8bit.8bit.16bit: 3 + 1 + 3 + 1 + 5 + 1 */
+ uint16_t ias_minor;
+
+ /* FixMe: snprintf can be replaced with a custom implementation */
+ cnt = snprintf(sw_version, sizeof(sw_version), "%u.%u.%u",
+ hdr->ih_ver.iv_major,
+ hdr->ih_ver.iv_minor,
+ hdr->ih_ver.iv_revision);
+ if (cnt < 0 || cnt >= sizeof(sw_version)) {
+ return BOOT_STATUS_ERROR;
+ }
+
+ /* Add the version of the SW component to the shared data area */
+ ias_minor = SET_IAS_MINOR(sw_module, SW_VERSION);
+ res = boot_add_data_to_shared_area(TLV_MAJOR_IAS,
+ ias_minor,
+ cnt,
+ (const uint8_t *)sw_version);
+ if (res) {
+ return BOOT_STATUS_ERROR;
+ }
+
+ return BOOT_STATUS_OK;
+}
+
+/* See in boot_record.h */
enum shared_memory_err_t
boot_add_data_to_shared_area(uint8_t major_type,
uint16_t minor_type,
@@ -65,7 +279,7 @@
/* Iterates over the TLV section looks for the same entry if found then
* returns with error: SHARED_MEMORY_OVERWRITE
*/
- for(; offset < tlv_end; offset += tlv_entry.tlv_len) {
+ for (; offset < tlv_end; offset += tlv_entry.tlv_len) {
tlv_entry = *((struct shared_data_tlv_entry *)offset);
if (GET_MAJOR(tlv_entry.tlv_type) == major_type &&
GET_MINOR(tlv_entry.tlv_type) == minor_type) {
@@ -93,3 +307,34 @@
return SHARED_MEMORY_OK;
}
+
+/* See in boot_record.h */
+enum boot_status_err_t
+boot_save_boot_status(uint8_t sw_module,
+ const struct image_header *hdr,
+ const struct flash_area *fap)
+{
+ enum boot_status_err_t res;
+
+ res = boot_save_sw_type(sw_module);
+ if (res) {
+ return res;
+ }
+
+ res = boot_save_sw_version(sw_module, hdr);
+ if (res) {
+ return res;
+ }
+
+ res = boot_save_sw_epoch(sw_module);
+ if (res) {
+ return res;
+ }
+
+ res = boot_save_sw_measurements(sw_module, hdr, fap);
+ if (res) {
+ return res;
+ }
+
+ return BOOT_STATUS_OK;
+}