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/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;
+}