Add attestation report creation

Adds components to create a cbor encoded attestion report using
claims gathered from registered claim sources.  Tests added
that check the decoded cbor is as expected.

Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: I8faddd6c5bea120745f85d70846725c5c51665b6
diff --git a/components/service/attestation/claims/claim.h b/components/service/attestation/claims/claim.h
index d36825d..1808f45 100644
--- a/components/service/attestation/claims/claim.h
+++ b/components/service/attestation/claims/claim.h
@@ -114,13 +114,47 @@
 }
 
 /**
+ * Claim category.  Values may be combined in a bitmap
+ * to allow a set of categries to be expressed.
+ */
+enum claim_category
+{
+    CLAIM_CATEGORY_NONE = 0,
+
+    /**
+     * A catagory of claim about the device instance.
+     */
+    CLAIM_CATEGORY_DEVICE = (1U << 0),
+
+    /**
+     * A catagory of claim based on a measurement during boot.
+     */
+    CLAIM_CATEGORY_BOOT_MEASUREMENT = (1U << 1),
+
+    /**
+     * A catagory of claim about an associated verifcation service.
+     */
+    CLAIM_CATEGORY_VERIFICATION_SERVICE = (1U << 2)
+};
+
+/**
  * Claim subject identifier.  Used for identifying what the claim relates
  * to.
  */
 enum claim_subject_id
 {
     CLAIM_SUBJECT_ID_NONE = 0,
-    CLAIM_SUBJECT_ID_SW_COMPONENT,
+    CLAIM_SUBJECT_ID_AUTH_CHALLENGE,
+    CLAIM_SUBJECT_ID_INSTANCE_ID,
+    CLAIM_SUBJECT_ID_VERIFICATION_SERVICE_INDICATOR,
+    CLAIM_SUBJECT_ID_PROFILE_DEFINITION,
+    CLAIM_SUBJECT_ID_IMPLEMENTATION_ID,
+    CLAIM_SUBJECT_ID_CLIENT_ID,
+    CLAIM_SUBJECT_ID_LIFECYCLE_STATE,
+    CLAIM_SUBJECT_ID_HW_VERSION,
+    CLAIM_SUBJECT_ID_BOOT_SEED,
+    CLAIM_SUBJECT_ID_NO_SW_MEASUREMENTS,
+    CLAIM_SUBJECT_ID_SW_COMPONENT
 };
 
 /**
@@ -143,6 +177,7 @@
  */
 struct claim
 {
+    enum claim_category category;
     enum claim_subject_id subject_id;
     enum claim_variant_id variant_id;
 
diff --git a/components/service/attestation/claims/claim_source.h b/components/service/attestation/claims/claim_source.h
index 5c28c47..381f263 100644
--- a/components/service/attestation/claims/claim_source.h
+++ b/components/service/attestation/claims/claim_source.h
@@ -7,6 +7,7 @@
 #ifndef CLAIM_SOURCE_H
 #define CLAIM_SOURCE_H
 
+#include <stdint.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -24,7 +25,12 @@
     bool (*get_claim)(void *context, struct claim *claim);
     void *context;
 
-    /* Generic claim source properties to be added */
+    /**
+     * A bitmap of claim categories that this claim_source provides claims for.
+     * Claim categories are enumerated by enum claim_category.
+     */
+    uint32_t category_map;
+
 };
 
 /**
diff --git a/components/service/attestation/claims/claim_vector.c b/components/service/attestation/claims/claim_vector.c
new file mode 100644
index 0000000..afa68b0
--- /dev/null
+++ b/components/service/attestation/claims/claim_vector.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+#include "claim_vector.h"
+
+void claim_vector_init(struct claim_vector *v, size_t limit)
+{
+    v->claims = malloc(sizeof(struct claim) * limit);
+    v->limit = (v->claims) ? limit : 0;
+    v->size = 0;
+}
+
+void claim_vector_deinit(struct claim_vector *v)
+{
+    free(v->claims);
+    v->claims = NULL;
+    v->limit = 0;
+    v->size = 0;
+}
+
+void claim_vector_push_back(struct claim_vector *v, const struct claim *claim)
+{
+    if (v->size < v->limit) {
+
+        v->claims[v->size] = *claim;
+        ++v->size;
+    }
+}
+
+size_t claim_vector_size(const struct claim_vector *v)
+{
+    return v->size;
+}
+
+const struct claim *claim_vector_get_claim(const struct claim_vector *v, size_t index)
+{
+    const struct claim *claim = NULL;
+    if (index < v->size) claim = &v->claims[index];
+    return claim;
+}
diff --git a/components/service/attestation/claims/claim_vector.h b/components/service/attestation/claims/claim_vector.h
new file mode 100644
index 0000000..227ab98
--- /dev/null
+++ b/components/service/attestation/claims/claim_vector.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CLAIM_VECTOR_H
+#define CLAIM_VECTOR_H
+
+#include <stddef.h>
+#include "claim.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A claim_vector is a general purpose variable length array
+ * of claims.  The maximum number of claims is specified
+ * when the claim_vector is initialized.  Deinit must be
+ * called after use to free any allocated space.
+ */
+struct claim_vector
+{
+    size_t limit;
+    size_t size;
+    struct claim *claims;
+};
+
+/**
+ * \brief Initializes a claim_vector.
+ *
+ *  Space is allocated for the specified limit but the vector is
+ *  initially empty.
+ *
+ * \param[in] v         This claim_vector
+ * \param[in] limit     The maximum number of claims that can be held
+ */
+void claim_vector_init(struct claim_vector *v, size_t limit);
+
+/**
+ * \brief De-initializes a claim_vector.
+ *
+ *  Frees any space allocated.  Must be called when the claim_vector
+ *  is finished with.
+ *
+ * \param[in] v         This claim_vector
+ */
+void claim_vector_deinit(struct claim_vector *v);
+
+/**
+ * \brief Add a claim to the back of the vector
+ *
+ * \param[in] v         This claim_vector
+ * \param[in] claim     Claim to add to the vector
+ */
+void claim_vector_push_back(struct claim_vector *v, const struct claim *claim);
+
+/**
+ * \brief Returns the number of claims held
+ *
+ * \param[in] v         This claim_vector
+ *
+ * \return Count of claims held
+ */
+size_t claim_vector_size(const struct claim_vector *v);
+
+/**
+ * \brief Returns a pointer to the claim at the specified index
+ *
+ * \param[in] v         This claim_vector
+ * \param[in] index     Index into vector
+ *
+ * \return Pointer to claim or NULL
+ */
+const struct claim *claim_vector_get_claim(const struct claim_vector *v, size_t index);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* CLAIM_VECTOR_H */
diff --git a/components/service/attestation/claims/claims_register.c b/components/service/attestation/claims/claims_register.c
new file mode 100644
index 0000000..76c09c8
--- /dev/null
+++ b/components/service/attestation/claims/claims_register.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+#include "claims_register.h"
+
+/* Maximum registered claim_sources for a deployment */
+#define CLAIMS_REGISTER_MAX_CLAIM_SOURCES           (20)
+
+/**
+ * The singleton claims_register instance.
+ */
+static struct claims_register
+{
+    size_t num_sources;
+    struct claim_source *sources[CLAIMS_REGISTER_MAX_CLAIM_SOURCES];
+
+} instance;
+
+static void query_collection_by_category(struct claim *collection,
+                    enum claim_category category, struct claim_vector *result);
+
+
+
+void claims_register_init(void)
+{
+    instance.num_sources = 0;
+    memset(instance.sources, 0, sizeof(instance.sources));
+}
+
+void claims_register_deinit(void)
+{
+    instance.num_sources = 0;
+}
+
+void claims_register_add_claim_source(uint32_t category_map,
+                                struct claim_source *source)
+{
+    if (instance.num_sources < CLAIMS_REGISTER_MAX_CLAIM_SOURCES) {
+
+        source->category_map = category_map;
+
+        instance.sources[instance.num_sources] = source;
+        ++instance.num_sources;
+    }
+}
+
+void claims_register_query_by_category(enum claim_category category,
+                            struct claim_vector *result)
+{
+    /* Iterate over all claim_sources and gather qualifying claims.
+     * A claim_source may source different categories of claim.  e.g.
+     * an event log is a flexible logging mechanism that can hold
+     * arbitrary claims.
+     */
+    for (size_t i = 0; i < instance.num_sources; ++i) {
+
+        struct claim_source *source = instance.sources[i];
+
+        if (source->category_map & category) {
+
+            struct claim claim;
+
+            if (claim_source_get_claim(source, &claim)) {
+
+                if (claim.variant_id == CLAIM_VARIANT_ID_COLLECTION) {
+
+                    query_collection_by_category(&claim, category, result);
+                }
+                else if (claim.category == category) {
+
+                    claim_vector_push_back(result, &claim);
+                }
+            }
+        }
+    }
+}
+
+static void query_collection_by_category(struct claim *collection,
+                    enum claim_category category, struct claim_vector *result)
+{
+    struct claim_iterator iter;
+
+    claim_collection_variant_create_iterator(&collection->variant.collection, &iter);
+
+    while (!iter.is_done(&iter)) {
+
+        struct claim claim;
+
+        iter.current(&iter, &claim);
+
+        if (claim.category == category) {
+
+            claim_vector_push_back(result, &claim);
+        }
+
+        iter.next(&iter);
+    }
+}
diff --git a/components/service/attestation/claims/claims_register.h b/components/service/attestation/claims/claims_register.h
new file mode 100644
index 0000000..9953633
--- /dev/null
+++ b/components/service/attestation/claims/claims_register.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CLAIMS_REGISTER_H
+#define CLAIMS_REGISTER_H
+
+#include <stdint.h>
+#include "claim_vector.h"
+#include "claim_source.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The claims_register is a singleton that provides a query
+ * method for obtaining claims about a device.  The claims_register
+ * decouples a report generator from the details of where claims
+ * come from.  A deployment specific set of claim_source objects
+ * are registered with the claims_register to actually gather claims.
+ */
+
+/**
+ * \brief Initialize the singleton claims_register
+ *
+ */
+void claims_register_init(void);
+
+/**
+ * \brief De-initializes the claims_register.
+ *
+ */
+void claims_register_deinit(void);
+
+/**
+ * \brief Add a claim_source
+ *
+ * Because of diversity in where information about the security state of
+ * a device comes from, a set of deployment specific claim_sources are
+ * registered during service provider initialization.  The bitmap
+ * of claim categories that can be sourced.
+ *
+ * \param[in] category_map  The set of claim categries
+ * \param[in] source        A concrete claim_source
+ */
+void claims_register_add_claim_source(uint32_t category_map,
+                                struct claim_source *source);
+
+/**
+ * \brief Query for claims of a specific category
+ *
+ * Used by a report generator to obtain claims that correspond to
+ * a particular category.
+ *
+  * \param[in] category  Claim category
+ * \param[out] result   Qualifying claims are added the result claim_vector
+ */
+void claims_register_query_by_category(enum claim_category category,
+                                struct claim_vector *result);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* CLAIMS_REGISTER_H */
diff --git a/components/service/attestation/claims/component.cmake b/components/service/attestation/claims/component.cmake
new file mode 100644
index 0000000..f367e89
--- /dev/null
+++ b/components/service/attestation/claims/component.cmake
@@ -0,0 +1,14 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+	message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+	"${CMAKE_CURRENT_LIST_DIR}/claim_vector.c"
+	"${CMAKE_CURRENT_LIST_DIR}/claims_register.c"
+	)
diff --git a/components/service/attestation/claims/sources/event_log/event_log_claim_source.c b/components/service/attestation/claims/sources/event_log/event_log_claim_source.c
index 7abd02c..82603e4 100644
--- a/components/service/attestation/claims/sources/event_log/event_log_claim_source.c
+++ b/components/service/attestation/claims/sources/event_log/event_log_claim_source.c
@@ -145,6 +145,7 @@
         {
             case EV_POST_CODE:
                 /* A measurement claim */
+                claim->category = CLAIM_CATEGORY_BOOT_MEASUREMENT;
                 claim->subject_id = CLAIM_SUBJECT_ID_SW_COMPONENT;
                 claim->variant_id = CLAIM_VARIANT_ID_MEASUREMENT;
                 tcg_event2_extract_digest(header, &claim->variant.measurement);
@@ -154,6 +155,7 @@
 
             default:
                 /* Unsupported event type */
+                claim->category = CLAIM_CATEGORY_NONE;
                 claim->subject_id = CLAIM_SUBJECT_ID_NONE;
                 claim->variant_id = CLAIM_VARIANT_ID_UNSUPPORTED;
                 break;
diff --git a/components/service/attestation/claims/sources/event_log/event_log_claim_source.h b/components/service/attestation/claims/sources/event_log/event_log_claim_source.h
index e3b428c..8e85166 100644
--- a/components/service/attestation/claims/sources/event_log/event_log_claim_source.h
+++ b/components/service/attestation/claims/sources/event_log/event_log_claim_source.h
@@ -33,7 +33,7 @@
  *
  * \param[in] instance      The event_log_claim_source instance to initialze
  * \param[in] event_log     Pointer to the event log.
- * \param[in] event_log_len Byte length of the event logf
+ * \param[in] event_log_len Byte length of the event log
  *
  * \return The initialize base claim_source structure
  */
diff --git a/components/service/attestation/claims/sources/event_log/mock/component.cmake b/components/service/attestation/claims/sources/event_log/mock/component.cmake
new file mode 100644
index 0000000..1b92516
--- /dev/null
+++ b/components/service/attestation/claims/sources/event_log/mock/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+	message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+	"${CMAKE_CURRENT_LIST_DIR}/mock_event_log.c"
+	)
diff --git a/components/service/attestation/claims/sources/event_log/mock/mock_event_log.c b/components/service/attestation/claims/sources/event_log/mock/mock_event_log.c
new file mode 100644
index 0000000..3bd9e75
--- /dev/null
+++ b/components/service/attestation/claims/sources/event_log/mock/mock_event_log.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+#include "mock_event_log.h"
+
+/* Event log data captured from TF-A measured boot */
+static const uint8_t mock_event_log[] = {MOCK_EVENT_LOG_DATA};
+
+/* Expected boot measurements for the mock event log*/
+static const struct mock_event_log_measurement expected_boot_measurement[] =
+{
+    {.id = "BL_2",
+     .digest = {0xa8,0x4f,0xb4,0x7b,0x54,0xd9,0x4b,0xab,0x49,0x73,0x63,0xf7,0x9b,0xfc,0x66,0xcb,
+                0x85,0x12,0xab,0x18,0x6f,0x24,0x74,0x01,0x5d,0xcf,0x33,0xf3,0x80,0x9e,0x9b,0x20}},
+    {.id = "BL_31",
+     .digest = {0x2f,0xd3,0x43,0x6c,0x6f,0xef,0x9b,0x11,0xc2,0x16,0xdd,0x1f,0x8b,0xdf,0x9b,0xa5,
+                0x24,0x14,0xa5,0xc1,0x97,0x0c,0x3a,0x6c,0x78,0xbf,0xef,0x64,0x0f,0xc1,0x23,0xe1}},
+    {.id = "HW_CONFIG",
+     .digest = {0xf3,0xde,0x4e,0x17,0xa1,0xa5,0xa7,0xfe,0xd9,0xd9,0xf4,0x16,0x3c,0x49,0x36,0x7e,
+                0xae,0xf7,0x2f,0x2a,0xa8,0x87,0xe6,0xb6,0x22,0x89,0xcd,0x27,0xdc,0x1c,0x80,0x25}},
+    {.id = "SOC_FW_CONFIG",
+     .digest = {0x4e,0xe4,0x8e,0x5a,0xe6,0x50,0xed,0xe0,0xb5,0xa3,0x54,0x8a,0x1f,0xd6,0x0e,0x8a,
+                0xea,0x0e,0x71,0x75,0x0e,0xa4,0x3f,0x82,0x76,0xce,0xaf,0xcd,0x7c,0xb0,0x91,0xe0}},
+    {.id = "BL_32",
+     .digest = {0x62,0x22,0x4f,0x0f,0xb0,0x5d,0xb4,0x77,0x1b,0x3f,0xa5,0x2e,0xab,0x76,0x1e,0x61,
+                0x17,0xb8,0xc6,0x6e,0xac,0x8c,0xc8,0x4d,0x2e,0xb0,0x7d,0x70,0x08,0x60,0x4b,0x41}},
+    {.id = "BL32_EXTRA1_IMAGE",
+     .digest = {0x39,0xd2,0xb8,0x5d,0x93,0x5d,0xf6,0xd8,0xf8,0xed,0x0c,0x1a,0x3a,0xe3,0xc8,0x90,
+                0x72,0x19,0xf4,0x88,0x5c,0x79,0x15,0x05,0x7b,0xf0,0x76,0xdb,0xc1,0x4c,0x5d,0x77}},
+    {.id = "BL_33",
+     .digest = {0xb5,0xd6,0x08,0x61,0xdd,0xfa,0x6d,0xda,0xa3,0xf7,0xa5,0xde,0xd6,0x8f,0x6f,0x39,
+                0x25,0xb1,0x57,0xfa,0x3e,0xdb,0x46,0x42,0x58,0x24,0x8e,0x81,0x1c,0x45,0x5d,0x38}},
+    {.id = "NT_FW_CONFIG",
+     .digest = {0x25,0x10,0x60,0x5d,0xd4,0xbc,0x9d,0x82,0x7a,0x16,0x9f,0x8a,0xcc,0x47,0x95,0xa6,
+                0xfd,0xca,0xa0,0xc1,0x2b,0xc9,0x99,0x8f,0x51,0x20,0xff,0xc6,0xed,0x74,0x68,0x5a}}
+};
+
+const uint8_t *mock_event_log_start(void)
+{
+    return mock_event_log;
+}
+
+size_t mock_event_log_size(void)
+{
+    return sizeof(mock_event_log);
+}
+
+const struct mock_event_log_measurement *mock_event_Log_measurement(size_t i)
+{
+    const struct mock_event_log_measurement *measurement = NULL;
+
+    if (i < mock_event_Log_measurement_count()) {
+
+        measurement = &expected_boot_measurement[i];
+    }
+
+    return measurement;
+}
+
+size_t mock_event_Log_measurement_count(void)
+{
+    return sizeof(expected_boot_measurement)/sizeof(struct mock_event_log_measurement);
+}
diff --git a/components/service/attestation/claims/sources/event_log/mock/mock_event_log.h b/components/service/attestation/claims/sources/event_log/mock/mock_event_log.h
new file mode 100644
index 0000000..9370933
--- /dev/null
+++ b/components/service/attestation/claims/sources/event_log/mock/mock_event_log.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef MOCK_EVENT_LOG_H
+#define MOCK_EVENT_LOG_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***********************************************************************************
+    An event log captured from the TF-A measured boot
+
+    The event log dump that corresponds to the data looks like this:
+
+    NOTICE:  TCG_EfiSpecIDEvent:
+    NOTICE:    PCRIndex           : 0
+    NOTICE:    EventType          : 3
+    NOTICE:    Digest             : 00
+    NOTICE:                       : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+    NOTICE:                       : 00 00 00
+    NOTICE:    EventSize          : 33
+    NOTICE:    Signature          : Spec ID Event03
+    NOTICE:    PlatformClass      : 0
+    NOTICE:    SpecVersion        : 2.0.2
+    NOTICE:    UintnSize          : 1
+    NOTICE:    NumberOfAlgorithms : 1
+    NOTICE:    DigestSizes        :
+    NOTICE:      #0 AlgorithmId   : SHA256
+    NOTICE:         DigestSize    : 32
+    NOTICE:    VendorInfoSize     : 0
+    NOTICE:  PCR_Event2:
+    NOTICE:    PCRIndex           : 0
+    NOTICE:    EventType          : 3
+    NOTICE:    Digests Count      : 1
+    NOTICE:      #0 AlgorithmId   : SHA256
+    NOTICE:         Digest        : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+    NOTICE:                       : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+    NOTICE:    EventSize          : 17
+    NOTICE:    Signature          : StartupLocality
+    NOTICE:    StartupLocality    : 0
+    NOTICE:  PCR_Event2:
+    NOTICE:    PCRIndex           : 0
+    NOTICE:    EventType          : 1
+    NOTICE:    Digests Count      : 1
+    NOTICE:      #0 AlgorithmId   : SHA256
+    NOTICE:         Digest        : a8 4f b4 7b 54 d9 4b ab 49 73 63 f7 9b fc 66 cb
+    NOTICE:                       : 85 12 ab 18 6f 24 74 01 5d cf 33 f3 80 9e 9b 20
+    NOTICE:    EventSize          : 5
+    NOTICE:    Event              : BL_2
+    NOTICE:  PCR_Event2:
+    NOTICE:    PCRIndex           : 0
+    NOTICE:    EventType          : 1
+    NOTICE:    Digests Count      : 1
+    NOTICE:      #0 AlgorithmId   : SHA256
+    NOTICE:         Digest        : 2f d3 43 6c 6f ef 9b 11 c2 16 dd 1f 8b df 9b a5
+    NOTICE:                       : 24 14 a5 c1 97 0c 3a 6c 78 bf ef 64 0f c1 23 e1
+    NOTICE:    EventSize          : 6
+    NOTICE:    Event              : BL_31
+    NOTICE:  PCR_Event2:
+    NOTICE:    PCRIndex           : 0
+    NOTICE:    EventType          : 1
+    NOTICE:    Digests Count      : 1
+    NOTICE:      #0 AlgorithmId   : SHA256
+    NOTICE:         Digest        : f3 de 4e 17 a1 a5 a7 fe d9 d9 f4 16 3c 49 36 7e
+    NOTICE:                       : ae f7 2f 2a a8 87 e6 b6 22 89 cd 27 dc 1c 80 25
+    NOTICE:    EventSize          : 10
+    NOTICE:    Event              : HW_CONFIG
+    NOTICE:  PCR_Event2:
+    NOTICE:    PCRIndex           : 0
+    NOTICE:    EventType          : 1
+    NOTICE:    Digests Count      : 1
+    NOTICE:      #0 AlgorithmId   : SHA256
+    NOTICE:         Digest        : 4e e4 8e 5a e6 50 ed e0 b5 a3 54 8a 1f d6 0e 8a
+    NOTICE:                       : ea 0e 71 75 0e a4 3f 82 76 ce af cd 7c b0 91 e0
+    NOTICE:    EventSize          : 14
+    NOTICE:    Event              : SOC_FW_CONFIG
+    NOTICE:  PCR_Event2:
+    NOTICE:    PCRIndex           : 0
+    NOTICE:    EventType          : 1
+    NOTICE:    Digests Count      : 1
+    NOTICE:      #0 AlgorithmId   : SHA256
+    NOTICE:         Digest        : 62 22 4f 0f b0 5d b4 77 1b 3f a5 2e ab 76 1e 61
+    NOTICE:                       : 17 b8 c6 6e ac 8c c8 4d 2e b0 7d 70 08 60 4b 41
+    NOTICE:    EventSize          : 6
+    NOTICE:    Event              : BL_32
+    NOTICE:  PCR_Event2:
+    NOTICE:    PCRIndex           : 0
+    NOTICE:    EventType          : 1
+    NOTICE:    Digests Count      : 1
+    NOTICE:      #0 AlgorithmId   : SHA256
+    NOTICE:         Digest        : 39 d2 b8 5d 93 5d f6 d8 f8 ed 0c 1a 3a e3 c8 90
+    NOTICE:                       : 72 19 f4 88 5c 79 15 05 7b f0 76 db c1 4c 5d 77
+    NOTICE:    EventSize          : 18
+    NOTICE:    Event              : BL32_EXTRA1_IMAGE
+    NOTICE:  PCR_Event2:
+    NOTICE:    PCRIndex           : 0
+    NOTICE:    EventType          : 1
+    NOTICE:    Digests Count      : 1
+    NOTICE:      #0 AlgorithmId   : SHA256
+    NOTICE:         Digest        : b5 d6 08 61 dd fa 6d da a3 f7 a5 de d6 8f 6f 39
+    NOTICE:                       : 25 b1 57 fa 3e db 46 42 58 24 8e 81 1c 45 5d 38
+    NOTICE:    EventSize          : 6
+    NOTICE:    Event              : BL_33
+    NOTICE:  PCR_Event2:
+    NOTICE:    PCRIndex           : 0
+    NOTICE:    EventType          : 1
+    NOTICE:    Digests Count      : 1
+    NOTICE:      #0 AlgorithmId   : SHA256
+    NOTICE:         Digest        : 25 10 60 5d d4 bc 9d 82 7a 16 9f 8a cc 47 95 a6
+    NOTICE:                       : fd ca a0 c1 2b c9 99 8f 51 20 ff c6 ed 74 68 5a
+    NOTICE:    EventSize          : 13
+    NOTICE:    Event              : NT_FW_CONFIG
+
+ ************************************************************************************/
+#define MOCK_EVENT_LOG_DATA \
+    0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,    \
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,    \
+    0x53,0x70,0x65,0x63,0x20,0x49,0x44,0x20,0x45,0x76,0x65,0x6e,0x74,0x30,0x33,0x00,    \
+    0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x01,0x01,0x00,0x00,0x00,0x0b,0x00,0x20,0x00,    \
+    0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x00,    \
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,    \
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,    \
+    0x00,0x00,0x00,0x53,0x74,0x61,0x72,0x74,0x75,0x70,0x4c,0x6f,0x63,0x61,0x6c,0x69,    \
+    0x74,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,    \
+    0x0b,0x00,0xa8,0x4f,0xb4,0x7b,0x54,0xd9,0x4b,0xab,0x49,0x73,0x63,0xf7,0x9b,0xfc,    \
+    0x66,0xcb,0x85,0x12,0xab,0x18,0x6f,0x24,0x74,0x01,0x5d,0xcf,0x33,0xf3,0x80,0x9e,    \
+    0x9b,0x20,0x05,0x00,0x00,0x00,0x42,0x4c,0x5f,0x32,0x00,0x00,0x00,0x00,0x00,0x01,    \
+    0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x2f,0xd3,0x43,0x6c,0x6f,0xef,0x9b,    \
+    0x11,0xc2,0x16,0xdd,0x1f,0x8b,0xdf,0x9b,0xa5,0x24,0x14,0xa5,0xc1,0x97,0x0c,0x3a,    \
+    0x6c,0x78,0xbf,0xef,0x64,0x0f,0xc1,0x23,0xe1,0x06,0x00,0x00,0x00,0x42,0x4c,0x5f,    \
+    0x33,0x31,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0b,    \
+    0x00,0xf3,0xde,0x4e,0x17,0xa1,0xa5,0xa7,0xfe,0xd9,0xd9,0xf4,0x16,0x3c,0x49,0x36,    \
+    0x7e,0xae,0xf7,0x2f,0x2a,0xa8,0x87,0xe6,0xb6,0x22,0x89,0xcd,0x27,0xdc,0x1c,0x80,    \
+    0x25,0x0a,0x00,0x00,0x00,0x48,0x57,0x5f,0x43,0x4f,0x4e,0x46,0x49,0x47,0x00,0x00,    \
+    0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x4e,0xe4,0x8e,    \
+    0x5a,0xe6,0x50,0xed,0xe0,0xb5,0xa3,0x54,0x8a,0x1f,0xd6,0x0e,0x8a,0xea,0x0e,0x71,    \
+    0x75,0x0e,0xa4,0x3f,0x82,0x76,0xce,0xaf,0xcd,0x7c,0xb0,0x91,0xe0,0x0e,0x00,0x00,    \
+    0x00,0x53,0x4f,0x43,0x5f,0x46,0x57,0x5f,0x43,0x4f,0x4e,0x46,0x49,0x47,0x00,0x00,    \
+    0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x62,0x22,0x4f,    \
+    0x0f,0xb0,0x5d,0xb4,0x77,0x1b,0x3f,0xa5,0x2e,0xab,0x76,0x1e,0x61,0x17,0xb8,0xc6,    \
+    0x6e,0xac,0x8c,0xc8,0x4d,0x2e,0xb0,0x7d,0x70,0x08,0x60,0x4b,0x41,0x06,0x00,0x00,    \
+    0x00,0x42,0x4c,0x5f,0x33,0x32,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,    \
+    0x00,0x00,0x00,0x0b,0x00,0x39,0xd2,0xb8,0x5d,0x93,0x5d,0xf6,0xd8,0xf8,0xed,0x0c,    \
+    0x1a,0x3a,0xe3,0xc8,0x90,0x72,0x19,0xf4,0x88,0x5c,0x79,0x15,0x05,0x7b,0xf0,0x76,    \
+    0xdb,0xc1,0x4c,0x5d,0x77,0x12,0x00,0x00,0x00,0x42,0x4c,0x33,0x32,0x5f,0x45,0x58,    \
+    0x54,0x52,0x41,0x31,0x5f,0x49,0x4d,0x41,0x47,0x45,0x00,0x00,0x00,0x00,0x00,0x01,    \
+    0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0xb5,0xd6,0x08,0x61,0xdd,0xfa,0x6d,    \
+    0xda,0xa3,0xf7,0xa5,0xde,0xd6,0x8f,0x6f,0x39,0x25,0xb1,0x57,0xfa,0x3e,0xdb,0x46,    \
+    0x42,0x58,0x24,0x8e,0x81,0x1c,0x45,0x5d,0x38,0x06,0x00,0x00,0x00,0x42,0x4c,0x5f,    \
+    0x33,0x33,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0b,    \
+    0x00,0x25,0x10,0x60,0x5d,0xd4,0xbc,0x9d,0x82,0x7a,0x16,0x9f,0x8a,0xcc,0x47,0x95,    \
+    0xa6,0xfd,0xca,0xa0,0xc1,0x2b,0xc9,0x99,0x8f,0x51,0x20,0xff,0xc6,0xed,0x74,0x68,    \
+    0x5a,0x0d,0x00,0x00,0x00,0x4e,0x54,0x5f,0x46,0x57,0x5f,0x43,0x4f,0x4e,0x46,0x49,    \
+    0x47,0x00
+
+/* Provides the expected values for a measurement */
+struct mock_event_log_measurement
+{
+    const char *id;
+    uint8_t digest[32];
+};
+
+/**
+ * Returns the start address of the mock event log data
+ */
+const uint8_t *mock_event_log_start(void);
+
+/**
+ * Returns the length mock event log data
+ */
+size_t mock_event_log_size(void);
+
+/**
+ * Returns the expected measurement at the specified index.
+ */
+const struct mock_event_log_measurement *mock_event_Log_measurement(size_t i);
+
+/**
+ * Returns the expected number of measurements.
+ */
+size_t mock_event_Log_measurement_count(void);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* MOCK_EVENT_LOG_H */
diff --git a/components/service/attestation/claims/sources/event_log/test/tcg_event_log_test.cpp b/components/service/attestation/claims/sources/event_log/test/tcg_event_log_test.cpp
index b6733c7..c4865fc 100644
--- a/components/service/attestation/claims/sources/event_log/test/tcg_event_log_test.cpp
+++ b/components/service/attestation/claims/sources/event_log/test/tcg_event_log_test.cpp
@@ -6,191 +6,9 @@
 
 #include <stdint.h>
 #include <service/attestation/claims/sources/event_log/event_log_claim_source.h>
+#include <service/attestation/claims/sources/event_log/mock/mock_event_log.h>
 #include <CppUTest/TestHarness.h>
 
-/***********************************************************************************
-    An event log captured from the TF-A measured boot
-
-    The event log dump that corresponds to the data looks like this:
-
-    NOTICE:  TCG_EfiSpecIDEvent:
-    NOTICE:    PCRIndex           : 0
-    NOTICE:    EventType          : 3
-    NOTICE:    Digest             : 00
-    NOTICE:                       : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-    NOTICE:                       : 00 00 00
-    NOTICE:    EventSize          : 33
-    NOTICE:    Signature          : Spec ID Event03
-    NOTICE:    PlatformClass      : 0
-    NOTICE:    SpecVersion        : 2.0.2
-    NOTICE:    UintnSize          : 1
-    NOTICE:    NumberOfAlgorithms : 1
-    NOTICE:    DigestSizes        :
-    NOTICE:      #0 AlgorithmId   : SHA256
-    NOTICE:         DigestSize    : 32
-    NOTICE:    VendorInfoSize     : 0
-    NOTICE:  PCR_Event2:
-    NOTICE:    PCRIndex           : 0
-    NOTICE:    EventType          : 3
-    NOTICE:    Digests Count      : 1
-    NOTICE:      #0 AlgorithmId   : SHA256
-    NOTICE:         Digest        : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-    NOTICE:                       : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-    NOTICE:    EventSize          : 17
-    NOTICE:    Signature          : StartupLocality
-    NOTICE:    StartupLocality    : 0
-    NOTICE:  PCR_Event2:
-    NOTICE:    PCRIndex           : 0
-    NOTICE:    EventType          : 1
-    NOTICE:    Digests Count      : 1
-    NOTICE:      #0 AlgorithmId   : SHA256
-    NOTICE:         Digest        : a8 4f b4 7b 54 d9 4b ab 49 73 63 f7 9b fc 66 cb
-    NOTICE:                       : 85 12 ab 18 6f 24 74 01 5d cf 33 f3 80 9e 9b 20
-    NOTICE:    EventSize          : 5
-    NOTICE:    Event              : BL_2
-    NOTICE:  PCR_Event2:
-    NOTICE:    PCRIndex           : 0
-    NOTICE:    EventType          : 1
-    NOTICE:    Digests Count      : 1
-    NOTICE:      #0 AlgorithmId   : SHA256
-    NOTICE:         Digest        : 2f d3 43 6c 6f ef 9b 11 c2 16 dd 1f 8b df 9b a5
-    NOTICE:                       : 24 14 a5 c1 97 0c 3a 6c 78 bf ef 64 0f c1 23 e1
-    NOTICE:    EventSize          : 6
-    NOTICE:    Event              : BL_31
-    NOTICE:  PCR_Event2:
-    NOTICE:    PCRIndex           : 0
-    NOTICE:    EventType          : 1
-    NOTICE:    Digests Count      : 1
-    NOTICE:      #0 AlgorithmId   : SHA256
-    NOTICE:         Digest        : f3 de 4e 17 a1 a5 a7 fe d9 d9 f4 16 3c 49 36 7e
-    NOTICE:                       : ae f7 2f 2a a8 87 e6 b6 22 89 cd 27 dc 1c 80 25
-    NOTICE:    EventSize          : 10
-    NOTICE:    Event              : HW_CONFIG
-    NOTICE:  PCR_Event2:
-    NOTICE:    PCRIndex           : 0
-    NOTICE:    EventType          : 1
-    NOTICE:    Digests Count      : 1
-    NOTICE:      #0 AlgorithmId   : SHA256
-    NOTICE:         Digest        : 4e e4 8e 5a e6 50 ed e0 b5 a3 54 8a 1f d6 0e 8a
-    NOTICE:                       : ea 0e 71 75 0e a4 3f 82 76 ce af cd 7c b0 91 e0
-    NOTICE:    EventSize          : 14
-    NOTICE:    Event              : SOC_FW_CONFIG
-    NOTICE:  PCR_Event2:
-    NOTICE:    PCRIndex           : 0
-    NOTICE:    EventType          : 1
-    NOTICE:    Digests Count      : 1
-    NOTICE:      #0 AlgorithmId   : SHA256
-    NOTICE:         Digest        : 62 22 4f 0f b0 5d b4 77 1b 3f a5 2e ab 76 1e 61
-    NOTICE:                       : 17 b8 c6 6e ac 8c c8 4d 2e b0 7d 70 08 60 4b 41
-    NOTICE:    EventSize          : 6
-    NOTICE:    Event              : BL_32
-    NOTICE:  PCR_Event2:
-    NOTICE:    PCRIndex           : 0
-    NOTICE:    EventType          : 1
-    NOTICE:    Digests Count      : 1
-    NOTICE:      #0 AlgorithmId   : SHA256
-    NOTICE:         Digest        : 39 d2 b8 5d 93 5d f6 d8 f8 ed 0c 1a 3a e3 c8 90
-    NOTICE:                       : 72 19 f4 88 5c 79 15 05 7b f0 76 db c1 4c 5d 77
-    NOTICE:    EventSize          : 18
-    NOTICE:    Event              : BL32_EXTRA1_IMAGE
-    NOTICE:  PCR_Event2:
-    NOTICE:    PCRIndex           : 0
-    NOTICE:    EventType          : 1
-    NOTICE:    Digests Count      : 1
-    NOTICE:      #0 AlgorithmId   : SHA256
-    NOTICE:         Digest        : b5 d6 08 61 dd fa 6d da a3 f7 a5 de d6 8f 6f 39
-    NOTICE:                       : 25 b1 57 fa 3e db 46 42 58 24 8e 81 1c 45 5d 38
-    NOTICE:    EventSize          : 6
-    NOTICE:    Event              : BL_33
-    NOTICE:  PCR_Event2:
-    NOTICE:    PCRIndex           : 0
-    NOTICE:    EventType          : 1
-    NOTICE:    Digests Count      : 1
-    NOTICE:      #0 AlgorithmId   : SHA256
-    NOTICE:         Digest        : 25 10 60 5d d4 bc 9d 82 7a 16 9f 8a cc 47 95 a6
-    NOTICE:                       : fd ca a0 c1 2b c9 99 8f 51 20 ff c6 ed 74 68 5a
-    NOTICE:    EventSize          : 13
-    NOTICE:    Event              : NT_FW_CONFIG
-
- ************************************************************************************/
-static const uint8_t tfa_measured_boot[] =
-{
-    0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,
-    0x53,0x70,0x65,0x63,0x20,0x49,0x44,0x20,0x45,0x76,0x65,0x6e,0x74,0x30,0x33,0x00,
-    0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x01,0x01,0x00,0x00,0x00,0x0b,0x00,0x20,0x00,
-    0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x00,
-    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,
-    0x00,0x00,0x00,0x53,0x74,0x61,0x72,0x74,0x75,0x70,0x4c,0x6f,0x63,0x61,0x6c,0x69,
-    0x74,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
-    0x0b,0x00,0xa8,0x4f,0xb4,0x7b,0x54,0xd9,0x4b,0xab,0x49,0x73,0x63,0xf7,0x9b,0xfc,
-    0x66,0xcb,0x85,0x12,0xab,0x18,0x6f,0x24,0x74,0x01,0x5d,0xcf,0x33,0xf3,0x80,0x9e,
-    0x9b,0x20,0x05,0x00,0x00,0x00,0x42,0x4c,0x5f,0x32,0x00,0x00,0x00,0x00,0x00,0x01,
-    0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x2f,0xd3,0x43,0x6c,0x6f,0xef,0x9b,
-    0x11,0xc2,0x16,0xdd,0x1f,0x8b,0xdf,0x9b,0xa5,0x24,0x14,0xa5,0xc1,0x97,0x0c,0x3a,
-    0x6c,0x78,0xbf,0xef,0x64,0x0f,0xc1,0x23,0xe1,0x06,0x00,0x00,0x00,0x42,0x4c,0x5f,
-    0x33,0x31,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0b,
-    0x00,0xf3,0xde,0x4e,0x17,0xa1,0xa5,0xa7,0xfe,0xd9,0xd9,0xf4,0x16,0x3c,0x49,0x36,
-    0x7e,0xae,0xf7,0x2f,0x2a,0xa8,0x87,0xe6,0xb6,0x22,0x89,0xcd,0x27,0xdc,0x1c,0x80,
-    0x25,0x0a,0x00,0x00,0x00,0x48,0x57,0x5f,0x43,0x4f,0x4e,0x46,0x49,0x47,0x00,0x00,
-    0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x4e,0xe4,0x8e,
-    0x5a,0xe6,0x50,0xed,0xe0,0xb5,0xa3,0x54,0x8a,0x1f,0xd6,0x0e,0x8a,0xea,0x0e,0x71,
-    0x75,0x0e,0xa4,0x3f,0x82,0x76,0xce,0xaf,0xcd,0x7c,0xb0,0x91,0xe0,0x0e,0x00,0x00,
-    0x00,0x53,0x4f,0x43,0x5f,0x46,0x57,0x5f,0x43,0x4f,0x4e,0x46,0x49,0x47,0x00,0x00,
-    0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0x62,0x22,0x4f,
-    0x0f,0xb0,0x5d,0xb4,0x77,0x1b,0x3f,0xa5,0x2e,0xab,0x76,0x1e,0x61,0x17,0xb8,0xc6,
-    0x6e,0xac,0x8c,0xc8,0x4d,0x2e,0xb0,0x7d,0x70,0x08,0x60,0x4b,0x41,0x06,0x00,0x00,
-    0x00,0x42,0x4c,0x5f,0x33,0x32,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,
-    0x00,0x00,0x00,0x0b,0x00,0x39,0xd2,0xb8,0x5d,0x93,0x5d,0xf6,0xd8,0xf8,0xed,0x0c,
-    0x1a,0x3a,0xe3,0xc8,0x90,0x72,0x19,0xf4,0x88,0x5c,0x79,0x15,0x05,0x7b,0xf0,0x76,
-    0xdb,0xc1,0x4c,0x5d,0x77,0x12,0x00,0x00,0x00,0x42,0x4c,0x33,0x32,0x5f,0x45,0x58,
-    0x54,0x52,0x41,0x31,0x5f,0x49,0x4d,0x41,0x47,0x45,0x00,0x00,0x00,0x00,0x00,0x01,
-    0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0b,0x00,0xb5,0xd6,0x08,0x61,0xdd,0xfa,0x6d,
-    0xda,0xa3,0xf7,0xa5,0xde,0xd6,0x8f,0x6f,0x39,0x25,0xb1,0x57,0xfa,0x3e,0xdb,0x46,
-    0x42,0x58,0x24,0x8e,0x81,0x1c,0x45,0x5d,0x38,0x06,0x00,0x00,0x00,0x42,0x4c,0x5f,
-    0x33,0x33,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0b,
-    0x00,0x25,0x10,0x60,0x5d,0xd4,0xbc,0x9d,0x82,0x7a,0x16,0x9f,0x8a,0xcc,0x47,0x95,
-    0xa6,0xfd,0xca,0xa0,0xc1,0x2b,0xc9,0x99,0x8f,0x51,0x20,0xff,0xc6,0xed,0x74,0x68,
-    0x5a,0x0d,0x00,0x00,0x00,0x4e,0x54,0x5f,0x46,0x57,0x5f,0x43,0x4f,0x4e,0x46,0x49,
-    0x47,0x00
-};
-
-/* Expected boot measurements */
-static const struct
-{
-    const char *id;
-    uint8_t digest[32];
-}
-expected_boot_measurement[] =
-{
-    {.id = "BL_2",
-     .digest = {0xa8,0x4f,0xb4,0x7b,0x54,0xd9,0x4b,0xab,0x49,0x73,0x63,0xf7,0x9b,0xfc,0x66,0xcb,
-                0x85,0x12,0xab,0x18,0x6f,0x24,0x74,0x01,0x5d,0xcf,0x33,0xf3,0x80,0x9e,0x9b,0x20}},
-    {.id = "BL_31",
-     .digest = {0x2f,0xd3,0x43,0x6c,0x6f,0xef,0x9b,0x11,0xc2,0x16,0xdd,0x1f,0x8b,0xdf,0x9b,0xa5,
-                0x24,0x14,0xa5,0xc1,0x97,0x0c,0x3a,0x6c,0x78,0xbf,0xef,0x64,0x0f,0xc1,0x23,0xe1}},
-    {.id = "HW_CONFIG",
-     .digest = {0xf3,0xde,0x4e,0x17,0xa1,0xa5,0xa7,0xfe,0xd9,0xd9,0xf4,0x16,0x3c,0x49,0x36,0x7e,
-                0xae,0xf7,0x2f,0x2a,0xa8,0x87,0xe6,0xb6,0x22,0x89,0xcd,0x27,0xdc,0x1c,0x80,0x25}},
-    {.id = "SOC_FW_CONFIG",
-     .digest = {0x4e,0xe4,0x8e,0x5a,0xe6,0x50,0xed,0xe0,0xb5,0xa3,0x54,0x8a,0x1f,0xd6,0x0e,0x8a,
-                0xea,0x0e,0x71,0x75,0x0e,0xa4,0x3f,0x82,0x76,0xce,0xaf,0xcd,0x7c,0xb0,0x91,0xe0}},
-    {.id = "BL_32",
-     .digest = {0x62,0x22,0x4f,0x0f,0xb0,0x5d,0xb4,0x77,0x1b,0x3f,0xa5,0x2e,0xab,0x76,0x1e,0x61,
-                0x17,0xb8,0xc6,0x6e,0xac,0x8c,0xc8,0x4d,0x2e,0xb0,0x7d,0x70,0x08,0x60,0x4b,0x41}},
-    {.id = "BL32_EXTRA1_IMAGE",
-     .digest = {0x39,0xd2,0xb8,0x5d,0x93,0x5d,0xf6,0xd8,0xf8,0xed,0x0c,0x1a,0x3a,0xe3,0xc8,0x90,
-                0x72,0x19,0xf4,0x88,0x5c,0x79,0x15,0x05,0x7b,0xf0,0x76,0xdb,0xc1,0x4c,0x5d,0x77}},
-    {.id = "BL_33",
-     .digest = {0xb5,0xd6,0x08,0x61,0xdd,0xfa,0x6d,0xda,0xa3,0xf7,0xa5,0xde,0xd6,0x8f,0x6f,0x39,
-                0x25,0xb1,0x57,0xfa,0x3e,0xdb,0x46,0x42,0x58,0x24,0x8e,0x81,0x1c,0x45,0x5d,0x38}},
-    {.id = "NT_FW_CONFIG",
-     .digest = {0x25,0x10,0x60,0x5d,0xd4,0xbc,0x9d,0x82,0x7a,0x16,0x9f,0x8a,0xcc,0x47,0x95,0xa6,
-                0xfd,0xca,0xa0,0xc1,0x2b,0xc9,0x99,0x8f,0x51,0x20,0xff,0xc6,0xed,0x74,0x68,0x5a}}
-};
-
-
 TEST_GROUP(TcgEventLogTests)
 {
 
@@ -203,7 +21,7 @@
     struct claim_source *claim_source;
 
     claim_source = event_log_claim_source_init(&event_log_claim_source,
-                                    tfa_measured_boot, sizeof(tfa_measured_boot));
+                                    mock_event_log_start(), mock_event_log_size());
 
     CHECK_FALSE(claim_source == NULL);
 
@@ -230,11 +48,16 @@
 
         if (sw_component_claim.variant_id == CLAIM_VARIANT_ID_MEASUREMENT) {
 
+            CHECK_TRUE(measurement_count < mock_event_Log_measurement_count());
+
+            const struct mock_event_log_measurement *expected =
+                    mock_event_Log_measurement(measurement_count);
+
             /* Check extracted values are as expected */
-            MEMCMP_EQUAL(expected_boot_measurement[measurement_count].id,
+            MEMCMP_EQUAL(expected->id,
                     sw_component_claim.variant.measurement.id.bytes,
                     sw_component_claim.variant.measurement.id.len);
-            MEMCMP_EQUAL(expected_boot_measurement[measurement_count].digest,
+            MEMCMP_EQUAL(expected->digest,
                     sw_component_claim.variant.measurement.digest.bytes,
                     sw_component_claim.variant.measurement.digest.len);
 
diff --git a/components/service/attestation/claims/sources/preloaded/component.cmake b/components/service/attestation/claims/sources/preloaded/component.cmake
new file mode 100644
index 0000000..5a289f2
--- /dev/null
+++ b/components/service/attestation/claims/sources/preloaded/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+	message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+	"${CMAKE_CURRENT_LIST_DIR}/preloaded_claim_source.c"
+	)
diff --git a/components/service/attestation/claims/sources/preloaded/preloaded_claim_source.c b/components/service/attestation/claims/sources/preloaded/preloaded_claim_source.c
new file mode 100644
index 0000000..dd612d6
--- /dev/null
+++ b/components/service/attestation/claims/sources/preloaded/preloaded_claim_source.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "preloaded_claim_source.h"
+
+static bool preloaded_claim_source_get_claim(void *context, struct claim *claim);
+static void create_preloaded_iterator(const struct claim_collection_variant *variant,
+                                struct claim_iterator *iter);
+
+static void preloaded_iterator_first(struct claim_iterator *iter);
+static bool preloaded_iterator_next(struct claim_iterator *iter);
+static bool preloaded_iterator_is_done(struct claim_iterator *iter);
+static bool preloaded_iterator_current(struct claim_iterator *iter, struct claim *claim);
+
+
+struct claim_source *preloaded_claim_source_init(struct preloaded_claim_source *instance,
+                                const struct claim_vector *claims)
+{
+    instance->base.get_claim = preloaded_claim_source_get_claim;
+    instance->base.context = instance;
+
+    instance->preloaded_claims = claims;
+
+    return &instance->base;
+}
+
+static bool preloaded_claim_source_get_claim(void *context, struct claim *claim)
+{
+    bool is_available = false;
+    struct preloaded_claim_source *instance = (struct preloaded_claim_source*)context;
+
+    /* The claim returned from a preloaded_claim_source is always a claim collection,
+     * containing 0..* preloaded claims.
+     */
+    if (instance->preloaded_claims) {
+
+        claim->subject_id = CLAIM_SUBJECT_ID_NONE;
+        claim->variant_id = CLAIM_VARIANT_ID_COLLECTION;
+        claim->raw_data = NULL;
+
+        claim->variant.collection.create_iterator = create_preloaded_iterator;
+        claim->variant.collection.begin_pos = &instance->preloaded_claims->claims[0];
+        claim->variant.collection.end_pos = &instance->preloaded_claims->claims[instance->preloaded_claims->size];
+
+        is_available = true;
+    }
+
+    return is_available;
+}
+
+static void create_preloaded_iterator(const struct claim_collection_variant *variant,
+                                struct claim_iterator *iter)
+{
+    /* Assign concrete methods */
+    iter->first = preloaded_iterator_first;
+    iter->next = preloaded_iterator_next;
+    iter->is_done = preloaded_iterator_is_done;
+    iter->current = preloaded_iterator_current;
+
+    /* Initialize to start of collection */
+    iter->begin_pos = variant->begin_pos;
+    iter->end_pos = variant->end_pos;
+    iter->cur_pos = variant->begin_pos;
+}
+
+static void preloaded_iterator_first(struct claim_iterator *iter)
+{
+    iter->cur_pos = iter->begin_pos;
+}
+
+static bool preloaded_iterator_next(struct claim_iterator *iter)
+{
+    const uint8_t *pos = (const uint8_t*)iter->cur_pos;
+    pos += sizeof(struct claim);
+    iter->cur_pos = pos;
+
+    return !preloaded_iterator_is_done(iter);
+}
+
+static bool preloaded_iterator_is_done(struct claim_iterator *iter)
+{
+    return (iter->cur_pos >= iter->end_pos) || (iter->cur_pos < iter->begin_pos);
+}
+
+static bool preloaded_iterator_current(struct claim_iterator *iter, struct claim *claim)
+{
+    bool success = false;
+
+    if (!preloaded_iterator_is_done(iter)) {
+
+        const struct claim *current_claim = (const struct claim*)iter->current;
+        *claim = *current_claim;
+        success = true;
+    }
+
+    return success;
+}
diff --git a/components/service/attestation/claims/sources/preloaded/preloaded_claim_source.h b/components/service/attestation/claims/sources/preloaded/preloaded_claim_source.h
new file mode 100644
index 0000000..83a2182
--- /dev/null
+++ b/components/service/attestation/claims/sources/preloaded/preloaded_claim_source.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PRELOADED_CLAIM_SOURCE_H
+#define PRELOADED_CLAIM_SOURCE_H
+
+#include <service/attestation/claims/claim.h>
+#include <service/attestation/claims/claim_source.h>
+#include <service/attestation/claims/claim_vector.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A claim source that sources claims that have been preloaded
+ * into a claim_vector.
+ */
+struct preloaded_claim_source
+{
+    struct claim_source base;
+
+    const struct claim_vector *preloaded_claims;
+};
+
+/**
+ * \brief Initializes a preloaded_claim_source.
+ *
+ * \param[in] instance      The preloaded_claim_source instance to initialze
+ * \param[in] claims        claim_vector containing preloaded claims.
+ *
+ * \return The initialize base claim_source structure
+ */
+struct claim_source *preloaded_claim_source_init(struct preloaded_claim_source *instance,
+                                const struct claim_vector *claims);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* PRELOADED_CLAIM_SOURCE_H */
diff --git a/components/service/attestation/reporter/attestation_report.h b/components/service/attestation/reporter/attestation_report.h
new file mode 100644
index 0000000..aa70b59
--- /dev/null
+++ b/components/service/attestation/reporter/attestation_report.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ATTESTATION_REPORT_H
+#define ATTESTATION_REPORT_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Creates an attestation report
+ *
+ *  Using the view of the security state of the device provided by
+ *  the claims_register, a signed attestation report is created.  On
+ *  success, a buffer is allocated for the serialized report.  The buffer
+ *  must be freed by calling attestation_reporter_destroy().
+ *
+ * \param[in] client_id             The requesting client id
+ * \param[in] auth_challenge_data   The auth challenge from the requester
+ * \param[in] auth_challenge_len    The auth challenge from the requester
+ * \param[out] report               The created report
+ * \param[out] report_len           The length of the report
+ *
+ * \return Operation status
+ */
+int attestation_report_create(int32_t client_id,
+        const uint8_t *auth_challenge_data, size_t auth_challenge_len,
+        const uint8_t **report, size_t *report_len);
+
+/**
+ * \brief Destroys an attestation report
+ *
+ *  Frees any resource associated with a created report
+ *
+ * \param[in] report               The created report
+ */
+void attestation_report_destroy(const uint8_t *report);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ATTESTATION_REPORT_H */
diff --git a/components/service/attestation/reporter/psa/attestation_report.c b/components/service/attestation/reporter/psa/attestation_report.c
new file mode 100644
index 0000000..87454a6
--- /dev/null
+++ b/components/service/attestation/reporter/psa/attestation_report.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * An attestation reporter that creates PSA compliant attestation
+ * reports.  The report content is specified by theh PSA Attestation
+ * specification.  Reports are serialized usingg CBOR and signed using
+ * COSE.
+ */
+
+#include <stdlib.h>
+#include <psa/error.h>
+#include <service/attestation/reporter/attestation_report.h>
+#include <service/attestation/claims/claims_register.h>
+#include "report_serializer.h"
+
+/* Local defines */
+#define MAX_DEVICE_CLAIMS       (50)
+#define MAX_SW_CLAIMS           (50)
+
+static void add_auth_challenge_claim(struct claim_vector *v, const uint8_t *data, size_t len);
+static void add_client_id_claim(struct claim_vector *v, int32_t client_id);
+static void add_no_sw_claim(struct claim_vector *v);
+
+
+int attestation_report_create(int32_t client_id,
+    const uint8_t *auth_challenge_data, size_t auth_challenge_len,
+    const uint8_t **report, size_t *report_len)
+{
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    struct claim_vector device_claims;
+    struct claim_vector sw_claims;
+
+    *report = NULL;
+    *report_len = 0;
+
+    claim_vector_init(&device_claims, MAX_DEVICE_CLAIMS);
+    claim_vector_init(&sw_claims, MAX_SW_CLAIMS);
+
+    /* Add claims related to the requester */
+    add_auth_challenge_claim(&device_claims, auth_challenge_data, auth_challenge_len);
+    add_client_id_claim(&device_claims, client_id);
+
+    /* Collate all other claims to include in the report */
+    claims_register_query_by_category(CLAIM_CATEGORY_DEVICE, &device_claims);
+    claims_register_query_by_category(CLAIM_CATEGORY_VERIFICATION_SERVICE, &device_claims);
+    claims_register_query_by_category(CLAIM_CATEGORY_BOOT_MEASUREMENT, &sw_claims);
+
+    /* And if there aren't any sw claims, indicate in report */
+    if (!sw_claims.size) add_no_sw_claim(&device_claims);
+
+    /* Serialize the collated claims to create the final report */
+    status = serialize_report(&device_claims, &sw_claims, report, report_len);
+
+    claim_vector_deinit(&device_claims);
+    claim_vector_deinit(&sw_claims);
+
+    return status;
+}
+
+void attestation_report_destroy(const uint8_t *report)
+{
+    free((void*)report);
+}
+
+static void add_auth_challenge_claim(struct claim_vector *v, const uint8_t *data, size_t len)
+{
+    struct claim claim;
+
+    claim.subject_id = CLAIM_SUBJECT_ID_AUTH_CHALLENGE;
+    claim.variant_id = CLAIM_VARIANT_ID_BYTE_STRING;
+    claim.raw_data = NULL;
+
+    claim.variant.byte_string.bytes = data;
+    claim.variant.byte_string.len = len;
+
+    claim_vector_push_back(v, &claim);
+}
+
+static void add_client_id_claim(struct claim_vector *v, int32_t client_id)
+{
+    struct claim claim;
+
+    claim.subject_id = CLAIM_SUBJECT_ID_CLIENT_ID;
+    claim.variant_id = CLAIM_VARIANT_ID_INTEGER;
+    claim.raw_data = NULL;
+
+    claim.variant.integer.value = client_id;
+
+    claim_vector_push_back(v, &claim);
+}
+
+static void add_no_sw_claim(struct claim_vector *v)
+{
+    struct claim claim;
+
+    claim.subject_id = CLAIM_SUBJECT_ID_NO_SW_MEASUREMENTS;
+    claim.variant_id = CLAIM_VARIANT_ID_INTEGER;
+    claim.raw_data = NULL;
+
+    claim.variant.integer.value = 1;
+
+    claim_vector_push_back(v, &claim);
+}
diff --git a/components/service/attestation/reporter/psa/component.cmake b/components/service/attestation/reporter/psa/component.cmake
new file mode 100644
index 0000000..26be202
--- /dev/null
+++ b/components/service/attestation/reporter/psa/component.cmake
@@ -0,0 +1,14 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+	message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+	"${CMAKE_CURRENT_LIST_DIR}/attestation_report.c"
+	"${CMAKE_CURRENT_LIST_DIR}/report_serializer.c"
+	)
diff --git a/components/service/attestation/reporter/psa/report_serializer.c b/components/service/attestation/reporter/psa/report_serializer.c
new file mode 100644
index 0000000..d66060e
--- /dev/null
+++ b/components/service/attestation/reporter/psa/report_serializer.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <qcbor/qcbor_encode.h>
+#include <psa/error.h>
+#include <protocols/service/attestation/packed-c/eat.h>
+#include <service/attestation/claims/claim.h>
+#include "report_serializer.h"
+
+static bool alloc_encode_buffer(const struct claim_vector *device_claims,
+    const struct claim_vector *sw_claims, UsefulBuf *encode_buffer);
+
+static void encode_claim(QCBOREncodeContext *encode_ctx, const struct claim *claim);
+static int eat_label(enum claim_subject_id subject_id);
+static int qcbor_to_psa_status(QCBORError qcbor_err);
+
+int serialize_report(const struct claim_vector *device_claims,
+    const struct claim_vector *sw_claims,
+    const uint8_t **report, size_t *report_len)
+{
+    UsefulBuf encode_buffer;
+
+    if (!alloc_encode_buffer(device_claims, sw_claims, &encode_buffer))
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+
+    QCBOREncodeContext encode_ctx;
+    QCBOREncode_Init(&encode_ctx, encode_buffer);
+    QCBOREncode_OpenMap(&encode_ctx);
+
+    /* Encode all device claims */
+    for (size_t i = 0; i < device_claims->size; ++i) {
+
+        encode_claim(&encode_ctx, &device_claims->claims[i]);
+    }
+
+    /* Add child array of sw claims if there are any */
+    if (sw_claims->size) {
+
+        QCBOREncode_OpenArrayInMapN(&encode_ctx, EAT_ARM_PSA_CLAIM_ID_SW_COMPONENTS);
+
+        for (size_t i = 0; i < sw_claims->size; ++i) {
+
+            encode_claim(&encode_ctx, &sw_claims->claims[i]);
+        }
+
+        QCBOREncode_CloseArray(&encode_ctx);
+    }
+
+    QCBOREncode_CloseMap(&encode_ctx);
+
+    /* Finalize the encoding to create the CBOR serialized report */
+    UsefulBufC encoded_cbor;
+    QCBORError qcbor_error;
+    qcbor_error = QCBOREncode_Finish(&encode_ctx, &encoded_cbor);
+
+    if (qcbor_error == QCBOR_SUCCESS) {
+
+        *report = encoded_cbor.ptr;
+        *report_len = encoded_cbor.len;
+    }
+    else {
+
+        free(encode_buffer.ptr);
+        *report = NULL;
+        *report_len = 0;
+    }
+
+    return qcbor_to_psa_status(qcbor_error);
+}
+
+static bool alloc_encode_buffer(const struct claim_vector *device_claims,
+    const struct claim_vector *sw_claims, UsefulBuf *encode_buffer)
+{
+    // todo estimate required space
+
+    encode_buffer->len = 4096;
+    encode_buffer->ptr = malloc(encode_buffer->len);
+
+    return encode_buffer->ptr;
+}
+
+static void encode_claim(QCBOREncodeContext *encode_ctx, const struct claim *claim)
+{
+    int label = eat_label(claim->subject_id);
+
+    switch (claim->variant_id)
+    {
+        case CLAIM_VARIANT_ID_INTEGER:
+        {
+            QCBOREncode_AddInt64ToMapN(encode_ctx, label, claim->variant.integer.value);
+            break;
+        }
+        case CLAIM_VARIANT_ID_TEXT_STRING:
+        {
+            QCBOREncode_AddSZStringToMapN(encode_ctx, label, claim->variant.text_string.string);
+            break;
+        }
+        case CLAIM_VARIANT_ID_BYTE_STRING:
+        {
+            UsefulBufC byte_string;
+            byte_string.ptr = claim->variant.byte_string.bytes;
+            byte_string.len = claim->variant.byte_string.len;
+            QCBOREncode_AddBytesToMapN(encode_ctx, label, byte_string);
+            break;
+        }
+        case CLAIM_VARIANT_ID_MEASUREMENT:
+        {
+            UsefulBufC byte_string;
+            QCBOREncode_OpenMap(encode_ctx);
+            byte_string.ptr = claim->variant.measurement.id.bytes;
+            byte_string.len = claim->variant.measurement.id.len;
+            QCBOREncode_AddBytesToMapN(encode_ctx,
+                EAT_SW_COMPONENT_CLAIM_ID_MEASUREMENT_TYPE, byte_string);
+            byte_string.ptr = claim->variant.measurement.digest.bytes;
+            byte_string.len = claim->variant.measurement.digest.len;
+            QCBOREncode_AddBytesToMapN(encode_ctx,
+                EAT_SW_COMPONENT_CLAIM_ID_MEASUREMENT_VALUE, byte_string);
+            QCBOREncode_CloseMap(encode_ctx);
+            break;
+        }
+        default:
+            break;
+    }
+}
+
+static int eat_label(enum claim_subject_id subject_id)
+{
+    int label = 0;
+
+    switch (subject_id)
+    {
+        case CLAIM_SUBJECT_ID_AUTH_CHALLENGE:
+            label = EAT_ARM_PSA_CLAIM_ID_CHALLENGE;
+            break;
+        case CLAIM_SUBJECT_ID_INSTANCE_ID:
+            label = EAT_ARM_PSA_CLAIM_ID_INSTANCE_ID;
+            break;
+        case CLAIM_SUBJECT_ID_VERIFICATION_SERVICE_INDICATOR:
+            label = EAT_ARM_PSA_CLAIM_ID_VERIFIER;
+            break;
+        case CLAIM_SUBJECT_ID_PROFILE_DEFINITION:
+            label = EAT_ARM_PSA_CLAIM_ID_PROFILE_DEFINITION;
+            break;
+        case CLAIM_SUBJECT_ID_IMPLEMENTATION_ID:
+            label = EAT_ARM_PSA_CLAIM_ID_IMPLEMENTATION_ID;
+            break;
+        case CLAIM_SUBJECT_ID_CLIENT_ID:
+            label = EAT_ARM_PSA_CLAIM_ID_CLIENT_ID;
+            break;
+        case CLAIM_SUBJECT_ID_LIFECYCLE_STATE:
+            label = EAT_ARM_PSA_CLAIM_ID_SECURITY_LIFECYCLE;
+            break;
+        case CLAIM_SUBJECT_ID_HW_VERSION:
+            label = EAT_ARM_PSA_CLAIM_ID_HW_VERSION;
+            break;
+        case CLAIM_SUBJECT_ID_BOOT_SEED:
+            label = EAT_ARM_PSA_CLAIM_ID_BOOT_SEED;
+            break;
+        case CLAIM_SUBJECT_ID_NO_SW_MEASUREMENTS:
+            label = EAT_ARM_PSA_CLAIM_ID_NO_SW_COMPONENTS;
+            break;
+        case CLAIM_SUBJECT_ID_SW_COMPONENT:
+            label = EAT_ARM_PSA_CLAIM_ID_SW_COMPONENTS;
+            break;
+        default:
+            break;
+    }
+
+    return label;
+}
+
+static int qcbor_to_psa_status(QCBORError qcbor_err)
+{
+    if (qcbor_err == QCBOR_SUCCESS)                 return PSA_SUCCESS;
+    if (qcbor_err == QCBOR_ERR_BUFFER_TOO_SMALL)    return PSA_ERROR_BUFFER_TOO_SMALL;
+
+    return PSA_ERROR_PROGRAMMER_ERROR;
+}
diff --git a/components/service/attestation/reporter/psa/report_serializer.h b/components/service/attestation/reporter/psa/report_serializer.h
new file mode 100644
index 0000000..5da5a66
--- /dev/null
+++ b/components/service/attestation/reporter/psa/report_serializer.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PSA_REPORT_SERIALIZER_H
+#define PSA_REPORT_SERIALIZER_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <service/attestation/claims/claim_vector.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Serialize the collated set of claims
+ *
+ *  Serializes the claims into a CBOR document using PSA defined
+ *  EAT custom claims to identify claim objects.
+ *
+ * \param[in] device_claims         Collated device claims
+ * \param[in] sw_claims             Collated software claims
+ * \param[out] report               The serialized report
+ * \param[out] report_len           The length of the report
+ *
+ * \return Operation status
+ */
+int serialize_report(const struct claim_vector *device_claims,
+    const struct claim_vector *sw_claims,
+    const uint8_t **report, size_t *report_len);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* PSA_REPORT_SERIALIZER_H */
diff --git a/components/service/attestation/test/component/attestation_reporter_tests.cpp b/components/service/attestation/test/component/attestation_reporter_tests.cpp
new file mode 100644
index 0000000..71fc10d
--- /dev/null
+++ b/components/service/attestation/test/component/attestation_reporter_tests.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <psa/error.h>
+#include <qcbor/qcbor_spiffy_decode.h>
+#include <service/attestation/claims/claims_register.h>
+#include <service/attestation/claims/sources/event_log/event_log_claim_source.h>
+#include <service/attestation/claims/sources/event_log/mock/mock_event_log.h>
+#include <service/attestation/claims/sources/preloaded/preloaded_claim_source.h>
+#include <service/attestation/reporter/attestation_report.h>
+#include <protocols/service/attestation/packed-c/eat.h>
+#include <CppUTest/TestHarness.h>
+#include "report_dump.h"
+
+#include <stdio.h>
+
+TEST_GROUP(AttestationReporterTests)
+{
+    void setup()
+    {
+        struct claim_source *claim_source;
+
+        report = NULL;
+        report_len;
+
+        /* The set of registered claim_sources determines the content
+         * of a generated attestation source.  The set and type of
+         * claim_sources registered will be deployment specific.
+         */
+        claims_register_init();
+
+        /* Boot measurement source */
+        claim_source = event_log_claim_source_init(&event_log_claim_source,
+            mock_event_log_start(), mock_event_log_size());
+        claims_register_add_claim_source(CLAIM_CATEGORY_BOOT_MEASUREMENT, claim_source);
+    }
+
+    void teardown()
+    {
+        attestation_report_destroy(report);
+        claims_register_deinit();
+    }
+
+    struct event_log_claim_source event_log_claim_source;
+    const uint8_t *report;
+    size_t report_len;
+};
+
+TEST(AttestationReporterTests, createReport)
+{
+    int status;
+
+    /* Client inputs */
+    int32_t client_id = 0x552791aa;
+    const uint8_t auth_challenge[] = {
+         1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,
+        17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32
+    };
+
+    /* Create a report */
+    status = attestation_report_create(client_id,
+        auth_challenge, sizeof(auth_challenge),
+        &report, &report_len);
+
+    /* Expect the operation to succeed and a non-zero length
+     * report created.
+     */
+    UNSIGNED_LONGS_EQUAL(PSA_SUCCESS, status);
+    CHECK_TRUE(report);
+    CHECK_TRUE(report_len);
+
+    /* Check the report contents */
+    QCBORDecodeContext decode_ctx;
+    UsefulBufC report_buf;
+
+    report_buf.ptr = report;
+    report_buf.len = report_len;
+
+    QCBORDecode_Init(&decode_ctx, report_buf, QCBOR_DECODE_MODE_NORMAL);
+    QCBORDecode_EnterMap(&decode_ctx, NULL);
+
+    /* Check client id */
+    int64_t decoded_client_id = 0;
+    QCBORDecode_GetInt64InMapN(&decode_ctx,
+        EAT_ARM_PSA_CLAIM_ID_CLIENT_ID, &decoded_client_id);
+
+    UNSIGNED_LONGS_EQUAL(QCBOR_SUCCESS, QCBORDecode_GetError(&decode_ctx));
+    UNSIGNED_LONGS_EQUAL(client_id, decoded_client_id);
+
+    /* Check the auth challenge */
+    UsefulBufC auth_challenge_buf;
+    auth_challenge_buf.ptr = NULL;
+    auth_challenge_buf.len = 0;
+    QCBORDecode_GetByteStringInMapN(&decode_ctx,
+        EAT_ARM_PSA_CLAIM_ID_CHALLENGE, &auth_challenge_buf);
+
+    UNSIGNED_LONGS_EQUAL(QCBOR_SUCCESS, QCBORDecode_GetError(&decode_ctx));
+    CHECK_TRUE(auth_challenge_buf.ptr);
+    UNSIGNED_LONGS_EQUAL(sizeof(auth_challenge), auth_challenge_buf.len);
+    MEMCMP_EQUAL(auth_challenge, auth_challenge_buf.ptr, sizeof(auth_challenge));
+
+    /* Shouldn't expect to see the 'NO_SW_COMPONENTS' claim */
+    int64_t no_sw = 0;
+    QCBORDecode_GetInt64InMapN(&decode_ctx, EAT_ARM_PSA_CLAIM_ID_NO_SW_COMPONENTS, &no_sw);
+    UNSIGNED_LONGS_EQUAL(QCBOR_ERR_LABEL_NOT_FOUND, QCBORDecode_GetAndResetError(&decode_ctx));
+    CHECK_FALSE(no_sw);
+
+    /* Check the sw components */
+    QCBORDecode_EnterArrayFromMapN(&decode_ctx, EAT_ARM_PSA_CLAIM_ID_SW_COMPONENTS);
+    UNSIGNED_LONGS_EQUAL(QCBOR_SUCCESS, QCBORDecode_GetError(&decode_ctx));
+
+    /* Iterate over all array members */
+    size_t sw_component_count = 0;
+    while (true) {
+
+        QCBORDecode_EnterMap(&decode_ctx, NULL);
+
+        if (QCBORDecode_GetAndResetError(&decode_ctx) == QCBOR_SUCCESS) {
+
+            CHECK_TRUE(sw_component_count < mock_event_Log_measurement_count());
+
+            UsefulBufC property;
+            const struct mock_event_log_measurement *measurement =
+                mock_event_Log_measurement(sw_component_count);
+
+            /* Check measurement id */
+            QCBORDecode_GetByteStringInMapN(&decode_ctx,
+                    EAT_SW_COMPONENT_CLAIM_ID_MEASUREMENT_TYPE, &property);
+            UNSIGNED_LONGS_EQUAL(QCBOR_SUCCESS, QCBORDecode_GetError(&decode_ctx));
+            CHECK_TRUE(property.ptr);
+            CHECK_TRUE(property.len);
+            MEMCMP_EQUAL(measurement->id, property.ptr, property.len);
+
+            /* Check measurement digest */
+            QCBORDecode_GetByteStringInMapN(&decode_ctx,
+                    EAT_SW_COMPONENT_CLAIM_ID_MEASUREMENT_VALUE, &property);
+            UNSIGNED_LONGS_EQUAL(QCBOR_SUCCESS, QCBORDecode_GetError(&decode_ctx));
+            CHECK_TRUE(property.ptr);
+            CHECK_TRUE(property.len);
+            MEMCMP_EQUAL(measurement->digest, property.ptr, property.len);
+
+            QCBORDecode_ExitMap(&decode_ctx);
+
+            ++sw_component_count;
+        }
+        else {
+            /* No more sw components */
+            break;
+        }
+    }
+
+    QCBORDecode_ExitArray(&decode_ctx);
+    UNSIGNED_LONGS_EQUAL(QCBOR_SUCCESS, QCBORDecode_GetError(&decode_ctx));
+
+    QCBORError qcbor_error;
+    QCBORDecode_ExitMap(&decode_ctx);
+    qcbor_error = QCBORDecode_Finish(&decode_ctx);
+    UNSIGNED_LONGS_EQUAL(QCBOR_SUCCESS, qcbor_error);
+}
diff --git a/components/service/attestation/test/component/component.cmake b/components/service/attestation/test/component/component.cmake
new file mode 100644
index 0000000..9db9a97
--- /dev/null
+++ b/components/service/attestation/test/component/component.cmake
@@ -0,0 +1,14 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+	message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+	"${CMAKE_CURRENT_LIST_DIR}/attestation_reporter_tests.cpp"
+	"${CMAKE_CURRENT_LIST_DIR}/report_dump.cpp"
+	)
diff --git a/components/service/attestation/test/component/report_dump.cpp b/components/service/attestation/test/component/report_dump.cpp
new file mode 100644
index 0000000..65f4a85
--- /dev/null
+++ b/components/service/attestation/test/component/report_dump.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdio.h>
+#include "report_dump.h"
+
+void report_dump(const uint8_t *report, size_t len)
+{
+    size_t bytes_in_row = 0;
+    size_t byte_count = 0;
+
+    printf("\n*******report dump start (len: %ld)*******\n", len);
+
+    while (byte_count < len) {
+
+        printf("%02x", report[byte_count]);
+
+        ++byte_count;
+        ++bytes_in_row;
+
+        if (bytes_in_row < 16) {
+
+            printf(" ");
+        }
+        else {
+
+            bytes_in_row = 0;
+            printf("\n");
+        }
+    }
+
+    if (bytes_in_row) printf("\n");
+
+    printf("*******report dump end *******\n");
+}
diff --git a/components/service/attestation/test/component/report_dump.h b/components/service/attestation/test/component/report_dump.h
new file mode 100644
index 0000000..81becc5
--- /dev/null
+++ b/components/service/attestation/test/component/report_dump.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef REPORT_DUMP_H
+#define REPORT_DUMP_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Dump a serialized report as an array of hex bytes.  Bytes are
+ * output to stdout. This is useful for viewing the report contents
+ * using an external CBOR decoder.
+ */
+void report_dump(const uint8_t *report, size_t len);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* REPORT_DUMP_H */
diff --git a/deployments/component-test/component-test.cmake b/deployments/component-test/component-test.cmake
index 30ab199..e731538 100644
--- a/deployments/component-test/component-test.cmake
+++ b/deployments/component-test/component-test.cmake
@@ -41,8 +41,13 @@
 		"components/service/locator/standalone/services/internal-trusted-storage"
 		"components/service/locator/standalone/services/protected-storage"
 		"components/service/locator/standalone/services/test-runner"
+		"components/service/attestation/claims"
+		"components/service/attestation/claims/sources/preloaded"
 		"components/service/attestation/claims/sources/event_log"
+		"components/service/attestation/claims/sources/event_log/mock"
 		"components/service/attestation/claims/sources/event_log/test"
+		"components/service/attestation/reporter/psa"
+		"components/service/attestation/test/component"
 		"components/service/crypto/client/cpp"
 		"components/service/crypto/client/cpp/protobuf"
 		"components/service/crypto/client/cpp/packed-c"
diff --git a/protocols/service/attestation/packed-c/eat.h b/protocols/service/attestation/packed-c/eat.h
index a5ed312..980190d 100644
--- a/protocols/service/attestation/packed-c/eat.h
+++ b/protocols/service/attestation/packed-c/eat.h
@@ -30,8 +30,8 @@
 #define EAT_ARM_PSA_CLAIM_ID_SW_COMPONENTS          (EAT_ARM_PSA_CLAIM_ID_BASE - 6)
 #define EAT_ARM_PSA_CLAIM_ID_NO_SW_COMPONENTS       (EAT_ARM_PSA_CLAIM_ID_BASE - 7)
 #define EAT_ARM_PSA_CLAIM_ID_CHALLENGE              (EAT_ARM_PSA_CLAIM_ID_BASE - 8)
-#define EAT_ARM_PSA_CLAIM_ID_UEID                   (EAT_ARM_PSA_CLAIM_ID_BASE - 9)
-#define EAT_ARM_PSA_CLAIM_ID_ORIGINATION            (EAT_ARM_PSA_CLAIM_ID_BASE - 10)
+#define EAT_ARM_PSA_CLAIM_ID_INSTANCE_ID            (EAT_ARM_PSA_CLAIM_ID_BASE - 9)
+#define EAT_ARM_PSA_CLAIM_ID_VERIFIER               (EAT_ARM_PSA_CLAIM_ID_BASE - 10)
 
 /**
  * SW component EAT claim IDs