Add components for attestation service

In preparation for implementing the attestation service provider,
building block components have been add.  This includes the
service access protocol definition, an external cbor library,
generic claim model and a concrete claim source for extracting
claims from a TCG event log.

This commit contains derived work, the following files are copied
from other projects:

components/service/attestation/claims/sources/event_log/tcg.h
   Origin:
        https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
        include/drivers/measured_boot/tcg.h
        #a5394205e94b70faf7ddd34841528ec631711d1a

components/service/attestation/include/psa/initial_attestation.h
   Origin:
        https://git.trustedfirmware.org/TF-M/trusted-firmware-m.git
        interface/include/psa/initial_attestation.h
        #9280ae9d898bffbb889e4796e51aab35a392ef82

Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: I5ed3e4ef7111a19b29643538ef3c47b3b6e1dd5c
diff --git a/components/common/endian/component.cmake b/components/common/endian/component.cmake
new file mode 100644
index 0000000..92d7138
--- /dev/null
+++ b/components/common/endian/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}/le.c"
+	)
diff --git a/components/common/endian/le.c b/components/common/endian/le.c
new file mode 100644
index 0000000..88196f6
--- /dev/null
+++ b/components/common/endian/le.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "le.h"
+
+uint8_t  load_u8_le(const void *base, size_t offset)
+{
+    const uint8_t *v = (const uint8_t*)base + offset;
+    uint8_t r = v[0];
+
+    return r;
+}
+
+uint16_t load_u16_le(const void *base, size_t offset)
+{
+    const uint8_t *v = (const uint8_t*)base + offset;
+    uint16_t r = 0;
+    r |= (uint16_t)v[0];
+    r |= (uint16_t)v[1] << 8;
+
+    return r;
+}
+
+uint32_t load_u32_le(const void *base, size_t offset)
+{
+    const uint8_t *v = (const uint8_t*)base + offset;
+    uint32_t r = 0;
+    r |= (uint32_t)v[0];
+    r |= (uint32_t)v[1] << 8;
+    r |= (uint32_t)v[2] << 16;
+    r |= (uint32_t)v[3] << 24;
+
+    return r;
+}
+
+uint64_t load_u64_le(const void *base, size_t offset)
+{
+    const uint8_t *v = (const uint8_t*)base + offset;
+    uint64_t r = 0;
+    r |= (uint64_t)v[0];
+    r |= (uint64_t)v[1] << 8;
+    r |= (uint64_t)v[2] << 16;
+    r |= (uint64_t)v[3] << 24;
+    r |= (uint64_t)v[4] << 32;
+    r |= (uint64_t)v[5] << 40;
+    r |= (uint64_t)v[6] << 48;
+    r |= (uint64_t)v[7] << 56;
+
+    return r;
+}
+
+void store_u8_le(void *base, size_t offset, uint8_t val)
+{
+    uint8_t *v = (uint8_t*)base + offset;
+    v[0] = val;
+}
+
+void store_u16_le(void *base, size_t offset, uint16_t val)
+{
+    uint8_t *v = (uint8_t*)base + offset;
+
+    v[0] = (uint8_t)(val & 0xff);
+    v[1] = (uint8_t)((val >> 8) & 0xff);
+}
+
+void store_u32_le(void *base, size_t offset, uint32_t val)
+{
+    uint8_t *v = (uint8_t*)base + offset;
+
+    v[0] = (uint8_t)(val & 0xff);
+    v[1] = (uint8_t)((val >> 8) & 0xff);
+    v[2] = (uint8_t)((val >> 16) & 0xff);
+    v[3] = (uint8_t)((val >> 24) & 0xff);
+}
+
+void store_u64_le(void *base, size_t offset, uint64_t val)
+{
+    uint8_t *v = (uint8_t*)base + offset;
+
+    v[0] = (uint8_t)(val & 0xff);
+    v[1] = (uint8_t)((val >> 8) & 0xff);
+    v[2] = (uint8_t)((val >> 16) & 0xff);
+    v[3] = (uint8_t)((val >> 24) & 0xff);
+    v[4] = (uint8_t)((val >> 32) & 0xff);
+    v[5] = (uint8_t)((val >> 40) & 0xff);
+    v[6] = (uint8_t)((val >> 48) & 0xff);
+    v[7] = (uint8_t)((val >> 56) & 0xff);
+}
diff --git a/components/common/endian/le.h b/components/common/endian/le.h
new file mode 100644
index 0000000..c6172e1
--- /dev/null
+++ b/components/common/endian/le.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ENDIAN_LE_H
+#define ENDIAN_LE_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Functions for loading and storing integer values as unaligned
+ * values in Little Endian byte order.  The address to load or
+ * store the value is specified by a base address and an offset
+ * to facilitate unaligned structure access.
+ */
+uint8_t  load_u8_le(const void *base, size_t offset);
+uint16_t load_u16_le(const void *base, size_t offset);
+uint32_t load_u32_le(const void *base, size_t offset);
+uint64_t load_u64_le(const void *base, size_t offset);
+
+void store_u8_le(void *base, size_t offset, uint8_t val);
+void store_u16_le(void *base, size_t offset, uint16_t val);
+void store_u32_le(void *base, size_t offset, uint32_t val);
+void store_u64_le(void *base, size_t offset, uint64_t val);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ENDIAN_LE_H */
diff --git a/components/common/endian/test/component.cmake b/components/common/endian/test/component.cmake
new file mode 100644
index 0000000..c909666
--- /dev/null
+++ b/components/common/endian/test/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}/endian_test.cpp"
+	)
diff --git a/components/common/endian/test/endian_test.cpp b/components/common/endian/test/endian_test.cpp
new file mode 100644
index 0000000..dabf276
--- /dev/null
+++ b/components/common/endian/test/endian_test.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <cstring>
+#include <common/endian/le.h>
+#include <CppUTest/TestHarness.h>
+
+TEST_GROUP(EndianTests)
+{
+
+};
+
+TEST(EndianTests, le8)
+{
+    const uint8_t test_vector[] = {0x00, 0x01, 0x02, 0x03, 0x04};
+    uint8_t store_result[sizeof(test_vector)];
+
+    memcpy(store_result, test_vector, sizeof(test_vector));
+
+    UNSIGNED_LONGS_EQUAL(0x03, load_u8_le(test_vector, 3));
+
+    store_u8_le(store_result, 2, 0x02);
+    MEMCMP_EQUAL(test_vector, store_result, sizeof(test_vector));
+}
+
+TEST(EndianTests, le16)
+{
+    const uint8_t test_vector[] = {0x00, 0x01, 0x02, 0x03, 0x04};
+    uint8_t store_result[sizeof(test_vector)];
+
+    memcpy(store_result, test_vector, sizeof(test_vector));
+
+    UNSIGNED_LONGS_EQUAL(0x0201, load_u16_le(test_vector, 1));
+
+    store_u16_le(store_result, 1, 0x0201);
+    MEMCMP_EQUAL(test_vector, store_result, sizeof(test_vector));
+}
+
+TEST(EndianTests, le32)
+{
+    const uint8_t test_vector[] = {0x00, 0x01, 0x02, 0x03, 0x04};
+    uint8_t store_result[sizeof(test_vector)];
+
+    memcpy(store_result, test_vector, sizeof(test_vector));
+
+    UNSIGNED_LONGS_EQUAL(0x04030201, load_u32_le(test_vector, 1));
+
+    store_u32_le(store_result, 1, 0x04030201);
+    MEMCMP_EQUAL(test_vector, store_result, sizeof(test_vector));
+}
+
+TEST(EndianTests, le64)
+{
+    const uint8_t test_vector[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
+    uint8_t store_result[sizeof(test_vector)];
+
+    memcpy(store_result, test_vector, sizeof(test_vector));
+
+    UNSIGNED_LONGS_EQUAL(0x0807060504030201, load_u64_le(test_vector, 1));
+
+    store_u64_le(store_result, 1, 0x0807060504030201);
+    MEMCMP_EQUAL(test_vector, store_result, sizeof(test_vector));
+}
diff --git a/components/service/attestation/claims/claim.h b/components/service/attestation/claims/claim.h
new file mode 100644
index 0000000..d36825d
--- /dev/null
+++ b/components/service/attestation/claims/claim.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CLAIM_H
+#define CLAIM_H
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct claim;
+
+/**
+ * An iterator for accessing claims within a collection.  A concrete
+ * claim_iterator provides functions that understand a specific
+ * representation of measurements or observations.
+ */
+struct claim_iterator
+{
+    /**
+     * Initialise the iterator to the first claim
+     * in a collection.
+     */
+    void (*first)(struct claim_iterator *iter);
+
+    /**
+     * Advance the iterator to the next claim
+     * in a collection.  Returns true if successful.
+     */
+    bool (*next)(struct claim_iterator *iter);
+
+    /**
+     * Check if iterator has reached the end of
+     * the collection.
+     */
+    bool (*is_done)(struct claim_iterator *iter);
+
+    /**
+     * Access the claim at the current iterator position.
+     * Returns true if there is a valid claim, else false.
+     */
+    bool (*current)(struct claim_iterator *iter, struct claim *claim);
+
+    /* Abstract handle marking the beginning of a collection */
+    const void *begin_pos;
+
+    /* Abstract handle marking the end of a collection */
+    const void *end_pos;
+
+    /* Abstract handle marking the current iterator position */
+    const void *cur_pos;
+};
+
+/**
+ * Claim variants for different types of claim.
+ */
+
+/* A variant for integer value claims */
+struct integer_claim_variant
+{
+    int32_t value;
+};
+
+/* A variant for zero terminated text string claims */
+struct text_string_claim_variant
+{
+    const char *string;
+};
+
+/* A variant for byte array claims */
+struct byte_string_claim_variant
+{
+    size_t len;
+    const uint8_t *bytes;
+};
+
+/* A variant for measurement claims that carry a digest that
+ * refects the security state of the mesaured component.
+ */
+struct measurement_claim_variant
+{
+    struct byte_string_claim_variant id;
+    struct byte_string_claim_variant digest;
+};
+
+/* A variant that is a container for 0..* claim objects */
+struct claim_collection_variant
+{
+    void (*create_iterator)(const struct claim_collection_variant *variant,
+                            struct claim_iterator *iter);
+
+    const void *begin_pos;
+    const void *end_pos;
+};
+
+/**
+ * \brief Initializes an iterator to access a concrete claim collection
+ *
+ * \param[in] variant    The claim variant to access
+ * \param[out] iter      The iterator to initialize
+ */
+static inline void claim_collection_variant_create_iterator(
+                        const struct claim_collection_variant *variant,
+                        struct claim_iterator *iter)
+{
+    variant->create_iterator(variant, iter);
+}
+
+/**
+ * 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 variant identifier.  Identifies the concrete claim variant.
+ */
+enum claim_variant_id
+{
+    CLAIM_VARIANT_ID_UNSUPPORTED,
+    CLAIM_VARIANT_ID_INTEGER,
+    CLAIM_VARIANT_ID_TEXT_STRING,
+    CLAIM_VARIANT_ID_BYTE_STRING,
+    CLAIM_VARIANT_ID_MEASUREMENT,
+    CLAIM_VARIANT_ID_COLLECTION
+};
+
+/**
+ * The common claim structure, holds a particular variant, identified
+ * by the variant_id.  A claim may be an arbitrarily deep tree or just
+ * a single node.
+ */
+struct claim
+{
+    enum claim_subject_id subject_id;
+    enum claim_variant_id variant_id;
+
+    /* Pointer to the raw record.  Allows a client with
+     * knowledge of the record format to access additional
+     * information.  NULL if not available.
+     */
+    const uint8_t *raw_data;
+
+    union claim_variant
+    {
+        struct integer_claim_variant integer;
+        struct text_string_claim_variant text_string;
+        struct byte_string_claim_variant byte_string;
+        struct measurement_claim_variant measurement;
+        struct claim_collection_variant collection;
+
+    } variant;
+};
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* CLAIM_H */
diff --git a/components/service/attestation/claims/claim_source.h b/components/service/attestation/claims/claim_source.h
new file mode 100644
index 0000000..5c28c47
--- /dev/null
+++ b/components/service/attestation/claims/claim_source.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CLAIM_SOURCE_H
+#define CLAIM_SOURCE_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct claim;
+
+/**
+ * An abstract interface for getting a claim from some source.  The source
+ * may return any type of claim variant so it could be a single claim or a
+ * collection.
+ */
+struct claim_source
+{
+    bool (*get_claim)(void *context, struct claim *claim);
+    void *context;
+
+    /* Generic claim source properties to be added */
+};
+
+/**
+ * \brief Get a claim from the claim source
+ *
+ * \param[in] cs         The claim source
+ * \param[out] claim     The returned claim
+ *
+ * \return Returns true if a claim is returned.
+ */
+static inline bool claim_source_get_claim(struct claim_source *cs, struct claim *claim)
+{
+    return cs->get_claim(cs->context, claim);
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* CLAIM_SOURCE_H */
diff --git a/components/service/attestation/claims/sources/event_log/component.cmake b/components/service/attestation/claims/sources/event_log/component.cmake
new file mode 100644
index 0000000..1ee3f9c
--- /dev/null
+++ b/components/service/attestation/claims/sources/event_log/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}/event_log_claim_source.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
new file mode 100644
index 0000000..7abd02c
--- /dev/null
+++ b/components/service/attestation/claims/sources/event_log/event_log_claim_source.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stddef.h>
+#include <string.h>
+#include <common/endian/le.h>
+#include "event_log_claim_source.h"
+#include "tcg.h"
+
+static bool event_log_claim_source_get_claim(void *context, struct claim *claim);
+static void create_event_log_iterator(const struct claim_collection_variant *variant,
+                                struct claim_iterator *iter);
+
+static void event_log_iterator_first(struct claim_iterator *iter);
+static bool event_log_iterator_next(struct claim_iterator *iter);
+static bool event_log_iterator_is_done(struct claim_iterator *iter);
+static bool event_log_iterator_current(struct claim_iterator *iter, struct claim *claim);
+
+static size_t tcg_event2_digest_size(uint16_t algorithm_id);
+static size_t tcg_event2_header_size(const void *header, const void *limit);
+static size_t tcg_event1_record_size(const void *header, const void *limit);
+static void tcg_event2_extract_digest(const void *header,
+                                    struct measurement_claim_variant *measurement);
+static void tcg_event2_extract_measurement_id(const void *event_data,
+                                    struct measurement_claim_variant *measurement,
+                                    const void *limit);
+
+
+
+struct claim_source *event_log_claim_source_init(struct event_log_claim_source *instance,
+                                const uint8_t *event_log, size_t event_log_len)
+{
+    instance->base.get_claim = event_log_claim_source_get_claim;
+    instance->base.context = instance;
+
+    instance->event_log = event_log;
+    instance->event_log_len = event_log_len;
+
+    return &instance->base;
+}
+
+static bool event_log_claim_source_get_claim(void *context, struct claim *claim)
+{
+    bool is_available = false;
+    struct event_log_claim_source *instance = (struct event_log_claim_source*)context;
+
+    /* The claim returned from a event_log_claim_source is always a claim collection,
+     * realized by the associated event log.  The event log may contain 0..*
+     * claims.
+     */
+    if (instance->event_log && instance->event_log_len) {
+
+        claim->subject_id = CLAIM_SUBJECT_ID_NONE;
+        claim->variant_id = CLAIM_VARIANT_ID_COLLECTION;
+        claim->raw_data = instance->event_log;
+
+        claim->variant.collection.create_iterator = create_event_log_iterator;
+        claim->variant.collection.begin_pos = instance->event_log;
+        claim->variant.collection.end_pos = &instance->event_log[instance->event_log_len];
+
+        is_available = true;
+    }
+
+    return is_available;
+}
+
+static void create_event_log_iterator(const struct claim_collection_variant *variant,
+                                struct claim_iterator *iter)
+{
+    /* Assign concrete methods */
+    iter->first = event_log_iterator_first;
+    iter->next = event_log_iterator_next;
+    iter->is_done = event_log_iterator_is_done;
+    iter->current = event_log_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 event_log_iterator_first(struct claim_iterator *iter)
+{
+    iter->cur_pos = iter->begin_pos;
+}
+
+static bool event_log_iterator_next(struct claim_iterator *iter)
+{
+    const void *header = iter->cur_pos;
+    size_t record_len;
+
+    if (header == iter->begin_pos) {
+        /* The first record must in TSG EVENT-1 format */
+        record_len = tcg_event1_record_size(header, iter->end_pos);
+        if (!record_len) return false;      /* Problem in record */
+    }
+    else {
+        /* All subsequent records are assumed to be in variable
+         * length TCG_PCR_EVENT2 format.
+         */
+        record_len = tcg_event2_header_size(header, iter->end_pos);
+        if (!record_len) return false;      /* Problem in header */
+
+        /* Add the variable length space used for event data */
+        const void *event_data = ((const uint8_t*)iter->cur_pos + record_len);
+        record_len += sizeof(event2_data_t);
+        record_len += load_u32_le(event_data, offsetof(event2_data_t, event_size));
+    }
+
+    /* Advance iterator to start of next record */
+    iter->cur_pos = (const uint8_t*)iter->cur_pos + record_len;
+
+    return !event_log_iterator_is_done(iter);
+}
+
+static bool event_log_iterator_is_done(struct claim_iterator *iter)
+{
+    return (iter->cur_pos >= iter->end_pos) || (iter->cur_pos < iter->begin_pos);
+}
+
+static bool event_log_iterator_current(struct claim_iterator *iter, struct claim *claim)
+{
+    bool success = false;
+
+    if (!event_log_iterator_is_done(iter)) {
+
+        uint32_t event_type = EV_NO_ACTION;
+        const void *event_data = NULL;
+        const void *header = iter->cur_pos;
+        claim->raw_data = (const uint8_t*)header;
+
+        if (header != iter->begin_pos) {
+            /* Initial TSG EVENT-1 record is not supported */
+            size_t header_len = tcg_event2_header_size(header, iter->end_pos);
+            if (!header_len) return false;      /* Problem in header */
+
+            event_type = load_u32_le(header, offsetof(event2_header_t, event_type));
+            event_data = (const uint8_t*)header + header_len;
+        }
+
+        switch (event_type)
+        {
+            case EV_POST_CODE:
+                /* A measurement claim */
+                claim->subject_id = CLAIM_SUBJECT_ID_SW_COMPONENT;
+                claim->variant_id = CLAIM_VARIANT_ID_MEASUREMENT;
+                tcg_event2_extract_digest(header, &claim->variant.measurement);
+                tcg_event2_extract_measurement_id(event_data, &claim->variant.measurement,
+                                        iter->end_pos);
+                break;
+
+            default:
+                /* Unsupported event type */
+                claim->subject_id = CLAIM_SUBJECT_ID_NONE;
+                claim->variant_id = CLAIM_VARIANT_ID_UNSUPPORTED;
+                break;
+        }
+
+        success = true;
+    }
+
+    return success;
+}
+
+static size_t tcg_event2_digest_size(uint16_t algorithm_id)
+{
+    size_t size = 0;
+
+    switch (algorithm_id)
+    {
+        case TPM_ALG_SHA256:
+            size = SHA256_DIGEST_SIZE;
+            break;
+        case TPM_ALG_SHA384:
+            size = SHA384_DIGEST_SIZE;
+            break;
+        case TPM_ALG_SHA512:
+            size = SHA512_DIGEST_SIZE;
+            break;
+        default:
+            break;
+    }
+
+    return size;
+}
+
+static size_t tcg_event2_header_size(const void *header, const void *limit)
+{
+    /* Return the length of the variable length header.  Returns zero if there's
+     * a problem.
+     */
+    size_t header_len = 0;
+
+    /* Ensure that the header is within the limit of the event log */
+    if (((const uint8_t*)limit - sizeof(event2_header_t)) >= (const uint8_t*)header) {
+
+        uint32_t digest_count = load_u32_le(header, offsetof(event2_header_t, digests.count));
+        header_len = sizeof(event2_header_t);
+
+        /* Add the variable length space used for digests */
+        for (unsigned int i = 0; i < digest_count; ++i) {
+
+            uint16_t algorithm_id =
+                load_u16_le(header, offsetof(event2_header_t, digests.digests[i].algorithm_id));
+            size_t digest_size =
+                tcg_event2_digest_size(algorithm_id);
+
+            if (digest_size) header_len += sizeof(tpmt_ha) + digest_size;
+        }
+    }
+
+    return header_len;
+}
+
+static void tcg_event2_extract_digest(const void *header,
+                                    struct measurement_claim_variant *measurement)
+{
+    uint32_t digest_count = load_u32_le(header, offsetof(event2_header_t, digests.count));
+
+    measurement->digest.len = 0;
+    measurement->digest.bytes = NULL;
+
+    if (digest_count > 0) {
+
+        uint16_t algorithm_id =
+            load_u16_le(header, offsetof(event2_header_t, digests.digests[0].algorithm_id));
+        size_t digest_size =
+            tcg_event2_digest_size(algorithm_id);
+
+        if (digest_size) {
+
+            measurement->digest.len =
+                digest_size;
+            measurement->digest.bytes =
+                (const uint8_t*)header + offsetof(event2_header_t, digests.digests[0].digest);
+        }
+    }
+}
+
+static size_t tcg_event1_record_size(const void *header, const void *limit)
+{
+    size_t record_len = load_u32_le(header, offsetof(tcg_pcr_event_t, event_size));
+    record_len += sizeof(tcg_pcr_event_t);
+    return record_len;
+}
+
+static void tcg_event2_extract_measurement_id(const void *event_data,
+                                    struct measurement_claim_variant *measurement,
+                                    const void *limit)
+{
+    measurement->id.len = 0;
+    measurement->id.bytes = NULL;
+
+    if (((const uint8_t*)limit - sizeof(event2_data_t)) >= (const uint8_t*)event_data) {
+
+        size_t id_size =  load_u32_le(event_data, offsetof(event2_data_t, event_size));
+
+        if (id_size) {
+
+            measurement->id.len = id_size;
+            measurement->id.bytes = (const uint8_t*)event_data + offsetof(event2_data_t, event);
+        }
+    }
+}
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
new file mode 100644
index 0000000..e3b428c
--- /dev/null
+++ b/components/service/attestation/claims/sources/event_log/event_log_claim_source.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef EVENT_LOG_CLAIM_SOURCE_H
+#define EVENT_LOG_CLAIM_SOURCE_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include <service/attestation/claims/claim.h>
+#include <service/attestation/claims/claim_source.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A claim source for accessing a TCG event log, stored as
+ * a contiguous array of bytes.
+ */
+struct event_log_claim_source
+{
+    struct claim_source base;
+
+    const uint8_t *event_log;
+    size_t event_log_len;
+};
+
+/**
+ * \brief Initializes a event_log_claim_source.
+ *
+ * \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
+ *
+ * \return The initialize base claim_source structure
+ */
+struct claim_source *event_log_claim_source_init(struct event_log_claim_source *instance,
+                                const uint8_t *event_log, size_t event_log_len);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* EVENT_LOG_CLAIM_SOURCE_H */
diff --git a/components/service/attestation/claims/sources/event_log/tcg.h b/components/service/attestation/claims/sources/event_log/tcg.h
new file mode 100644
index 0000000..c1ff44c
--- /dev/null
+++ b/components/service/attestation/claims/sources/event_log/tcg.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2020-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TCG_H
+#define TCG_H
+
+#include <stdint.h>
+
+#define TCG_ID_EVENT_SIGNATURE_03	"Spec ID Event03"
+#define TCG_STARTUP_LOCALITY_SIGNATURE	"StartupLocality"
+
+#define TCG_SPEC_VERSION_MAJOR_TPM2   2
+#define TCG_SPEC_VERSION_MINOR_TPM2   0
+#define TCG_SPEC_ERRATA_TPM2          2
+
+/*
+ * Event types
+ * Ref. Table 9 Events
+ * TCG PC Client Platform Firmware Profile Specification.
+ */
+#define EV_PREBOOT_CERT						0x00000000
+#define EV_POST_CODE						0x00000001
+#define	EV_UNUSED							0x00000002
+#define EV_NO_ACTION						0x00000003
+#define EV_SEPARATOR						0x00000004
+#define EV_ACTION							0x00000005
+#define	EV_EVENT_TAG						0x00000006
+#define EV_S_CRTM_CONTENTS					0x00000007
+#define EV_S_CRTM_VERSION					0x00000008
+#define EV_CPU_MICROCODE					0x00000009
+#define EV_PLATFORM_CONFIG_FLAGS			0x0000000A
+#define EV_TABLE_OF_DEVICES					0x0000000B
+#define EV_COMPACT_HASH						0x0000000C
+#define	EV_IPL								0x0000000D
+#define	EV_IPL_PARTITION_DATA				0x0000000E
+#define EV_NONHOST_CODE						0x0000000F
+#define EV_NONHOST_CONFIG					0x00000010
+#define EV_NONHOST_INFO						0x00000011
+#define EV_OMIT_BOOT_DEVICE_EVENTS			0x00000012
+#define	EV_EFI_EVENT_BASE					0x80000000
+#define	EV_EFI_VARIABLE_DRIVER_CONFIG		0x80000001
+#define EV_EFI_VARIABLE_BOOT				0x80000002
+#define	EV_EFI_BOOT_SERVICES_APPLICATION	0x80000003
+#define	EV_EFI_BOOT_SERVICES_DRIVER			0x80000004
+#define	EV_EFI_RUNTIME_SERVICES_DRIVER		0x80000005
+#define	EV_EFI_GPT_EVENT					0x80000006
+#define	EV_EFI_ACTION						0x80000007
+#define	EV_EFI_PLATFORM_FIRMWARE_BLOB		0x80000008
+#define	EV_EFI_HANDOFF_TABLES				0x80000009
+#define	EV_EFI_HCRTM_EVENT					0x80000010
+#define	EV_EFI_VARIABLE_AUTHORITY			0x800000E0
+
+/*
+ * TPM_ALG_ID constants.
+ * Ref. Table 9 - Definition of (UINT16) TPM_ALG_ID Constants
+ * Trusted Platform Module Library. Part 2: Structures
+ */
+#define TPM_ALG_SHA256		0x000B
+#define TPM_ALG_SHA384		0x000C
+#define TPM_ALG_SHA512		0x000D
+
+/* TCG Platform Type */
+#define PLATFORM_CLASS_CLIENT   0
+#define PLATFORM_CLASS_SERVER   1
+
+/* SHA digest sizes in bytes */
+#define SHA1_DIGEST_SIZE	20
+#define SHA256_DIGEST_SIZE	32
+#define SHA384_DIGEST_SIZE	48
+#define SHA512_DIGEST_SIZE	64
+
+enum {
+	/*
+	 * SRTM, BIOS, Host Platform Extensions, Embedded
+	 * Option ROMs and PI Drivers
+	 */
+	PCR_0 = 0,
+	/* Host Platform Configuration */
+	PCR_1,
+	/* UEFI driver and application Code */
+	PCR_2,
+	/* UEFI driver and application Configuration and Data */
+	PCR_3,
+	/* UEFI Boot Manager Code (usually the MBR) and Boot Attempts */
+	PCR_4,
+	/*
+	 * Boot Manager Code Configuration and Data (for use
+	 * by the Boot Manager Code) and GPT/Partition Table
+	 */
+	PCR_5,
+	/* Host Platform Manufacturer Specific */
+	PCR_6,
+	/* Secure Boot Policy */
+	PCR_7,
+	/* 8-15: Defined for use by the Static OS */
+	PCR_8,
+	/* Debug */
+	PCR_16 = 16
+};
+
+#pragma pack(push, 1)
+
+/*
+ * PCR Event Header
+ * TCG EFI Protocol Specification
+ * 5.3 Event Log Header
+ */
+typedef struct {
+	/* PCRIndex:
+	 * The PCR Index to which this event is extended
+	 */
+	uint32_t	pcr_index;
+
+	/* EventType:
+	 * SHALL be an EV_NO_ACTION event
+	 */
+	uint32_t	event_type;
+
+	/* SHALL be 20 Bytes of 0x00 */
+	uint8_t		digest[SHA1_DIGEST_SIZE];
+
+	/* The size of the event */
+	uint32_t	event_size;
+
+	/* SHALL be a TCG_EfiSpecIdEvent */
+	uint8_t		event[];	/* [event_data_size] */
+} tcg_pcr_event_t;
+
+/*
+ * Log Header Entry Data
+ * Ref. Table 14 TCG_EfiSpecIdEventAlgorithmSize
+ * TCG PC Client Platform Firmware Profile 9.4.5.1
+ */
+typedef struct {
+	/* Algorithm ID (hashAlg) of the Hash used by BIOS */
+	uint16_t	algorithm_id;
+
+	/* The size of the digest produced by the implemented Hash algorithm */
+	uint16_t	digest_size;
+} id_event_algorithm_size_t;
+
+/*
+ * TCG_EfiSpecIdEvent structure
+ * Ref. Table 15 TCG_EfiSpecIdEvent
+ * TCG PC Client Platform Firmware Profile 9.4.5.1
+ */
+typedef struct {
+	/*
+	 * The NUL-terminated ASCII string "Spec ID Event03".
+	 * SHALL be set to {0x53, 0x70, 0x65, 0x63, 0x20, 0x49, 0x44,
+	 * 0x20, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x33, 0x00}.
+	 */
+	uint8_t		signature[16];
+
+	/*
+	 * The value for the Platform Class.
+	 * The enumeration is defined in the TCG ACPI Specification Client
+	 * Common Header.
+	 */
+	uint32_t	platform_class;
+
+	/*
+	 * The PC Client Platform Profile Specification minor version number
+	 * this BIOS supports.
+	 * Any BIOS supporting this version (2.0) MUST set this value to 0x00.
+	 */
+	uint8_t		spec_version_minor;
+
+	/*
+	 * The PC Client Platform Profile Specification major version number
+	 * this BIOS supports.
+	 * Any BIOS supporting this version (2.0) MUST set this value to 0x02.
+	 */
+	uint8_t		spec_version_major;
+
+	/*
+	 * The PC Client Platform Profile Specification errata version number
+	 * this BIOS supports.
+	 * Any BIOS supporting this version (2.0) MUST set this value to 0x02.
+	 */
+	uint8_t		spec_errata;
+
+	/*
+	 * Specifies the size of the UINTN fields used in various data
+	 * structures used in this specification.
+	 * 0x01 indicates UINT32 and 0x02 indicates UINT64.
+	 */
+	uint8_t		uintn_size;
+
+	/*
+	 * The number of Hash algorithms in the digestSizes field.
+	 * This field MUST be set to a value of 0x01 or greater.
+	 */
+	uint32_t	number_of_algorithms;
+
+	/*
+	 * Each TCG_EfiSpecIdEventAlgorithmSize SHALL contain an algorithmId
+	 * and digestSize for each hash algorithm used in the TCG_PCR_EVENT2
+	 * structure, the first of which is a Hash algorithmID and the second
+	 * is the size of the respective digest.
+	 */
+	id_event_algorithm_size_t    digest_size[]; /* number_of_algorithms */
+} id_event_struct_header_t;
+
+typedef struct {
+	/*
+	 * Size in bytes of the VendorInfo field.
+	 * Maximum value MUST be FFh bytes.
+	 */
+	uint8_t		vendor_info_size;
+
+	/*
+	 * Provided for use by Platform Firmware implementer. The value might
+	 * be used, for example, to provide more detailed information about the
+	 * specific BIOS such as BIOS revision numbers, etc. The values within
+	 * this field are not standardized and are implementer-specific.
+	 * Platform-specific or -unique information MUST NOT be provided in
+	 * this field.
+	 *
+	 */
+	uint8_t		vendor_info[];	/* [vendorInfoSize] */
+} id_event_struct_data_t;
+
+typedef struct {
+	id_event_struct_header_t	struct_header;
+	id_event_struct_data_t		struct_data;
+} id_event_struct_t;
+
+typedef struct {
+	tcg_pcr_event_t			header;
+	id_event_struct_header_t	struct_header;
+} id_event_headers_t;
+
+/* TPMT_HA Structure */
+typedef struct {
+	/* Selector of the hash contained in the digest that implies
+	 * the size of the digest
+	 */
+	uint16_t	algorithm_id;	/* AlgorithmId */
+
+	/* Digest, depends on AlgorithmId */
+	uint8_t		digest[];	/* Digest[] */
+} tpmt_ha;
+
+/*
+ * TPML_DIGEST_VALUES Structure
+ */
+typedef struct {
+	/* The number of digests in the list */
+	uint32_t	count;			/* Count */
+
+	/* The list of tagged digests, as sent to the TPM as part of a
+	 * TPM2_PCR_Extend or as received from a TPM2_PCR_Event command
+	 */
+	tpmt_ha		digests[];		/* Digests[Count] */
+} tpml_digest_values;
+
+/*
+ * TCG_PCR_EVENT2 header
+ */
+typedef struct {
+	 /* The PCR Index to which this event was extended */
+	uint32_t		pcr_index;	/* PCRIndex */
+
+	/* Type of event */
+	uint32_t		event_type;	/* EventType */
+
+	/* Digests:
+	 * A counted list of tagged digests, which contain the digest of
+	 * the event data (or external data) for all active PCR banks
+	 */
+	tpml_digest_values	digests;	/* Digests */
+} event2_header_t;
+
+typedef struct event2_data {
+	/* The size of the event data */
+	uint32_t		event_size;	/* EventSize */
+
+	/* The data of the event */
+	uint8_t			event[];	/* Event[EventSize] */
+} event2_data_t;
+
+/*
+ * Startup Locality Event
+ * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3
+ */
+typedef struct {
+	/*
+	 * The NUL-terminated ASCII string "StartupLocality" SHALL be
+	 * set to {0x53 0x74 0x61 0x72 0x74 0x75 0x70 0x4C 0x6F 0x63
+	 * 0x61 0x6C 0x69 0x74 0x79 0x00}
+	 */
+	uint8_t		signature[16];
+
+	/* The Locality Indicator which sent the TPM2_Startup command */
+	uint8_t		startup_locality;
+} startup_locality_event_t;
+
+#pragma pack(pop)
+
+#endif /* TCG_H */
diff --git a/components/service/attestation/claims/sources/event_log/test/component.cmake b/components/service/attestation/claims/sources/event_log/test/component.cmake
new file mode 100644
index 0000000..0220f56
--- /dev/null
+++ b/components/service/attestation/claims/sources/event_log/test/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}/tcg_event_log_test.cpp"
+	)
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
new file mode 100644
index 0000000..b6733c7
--- /dev/null
+++ b/components/service/attestation/claims/sources/event_log/test/tcg_event_log_test.cpp
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+#include <service/attestation/claims/sources/event_log/event_log_claim_source.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)
+{
+
+
+};
+
+TEST(TcgEventLogTests, interateBootMeasurements)
+{
+    struct event_log_claim_source event_log_claim_source;
+    struct claim_source *claim_source;
+
+    claim_source = event_log_claim_source_init(&event_log_claim_source,
+                                    tfa_measured_boot, sizeof(tfa_measured_boot));
+
+    CHECK_FALSE(claim_source == NULL);
+
+    struct claim boot_measurements;
+
+    CHECK_TRUE(claim_source_get_claim(claim_source, &boot_measurements));
+
+    UNSIGNED_LONGS_EQUAL(CLAIM_VARIANT_ID_COLLECTION, boot_measurements.variant_id);
+    UNSIGNED_LONGS_EQUAL(CLAIM_SUBJECT_ID_NONE, boot_measurements.subject_id);
+
+    /* Iterate over all claims in the collection */
+    unsigned int claim_count = 0;
+    unsigned int measurement_count = 0;
+    struct claim_iterator iter;
+
+    claim_collection_variant_create_iterator(&boot_measurements.variant.collection, &iter);
+
+    while (!iter.is_done(&iter)) {
+
+        struct claim sw_component_claim;
+
+        ++claim_count;
+        iter.current(&iter, &sw_component_claim);
+
+        if (sw_component_claim.variant_id == CLAIM_VARIANT_ID_MEASUREMENT) {
+
+            /* Check extracted values are as expected */
+            MEMCMP_EQUAL(expected_boot_measurement[measurement_count].id,
+                    sw_component_claim.variant.measurement.id.bytes,
+                    sw_component_claim.variant.measurement.id.len);
+            MEMCMP_EQUAL(expected_boot_measurement[measurement_count].digest,
+                    sw_component_claim.variant.measurement.digest.bytes,
+                    sw_component_claim.variant.measurement.digest.len);
+
+            ++measurement_count;
+        }
+
+        iter.next(&iter);
+    }
+
+    UNSIGNED_LONGS_EQUAL(10, claim_count);
+    UNSIGNED_LONGS_EQUAL(8, measurement_count);
+}
diff --git a/components/service/attestation/include/psa/initial_attestation.h b/components/service/attestation/include/psa/initial_attestation.h
new file mode 100644
index 0000000..bc630ee
--- /dev/null
+++ b/components/service/attestation/include/psa/initial_attestation.h
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/***************************************************************************/
+/*                             DRAFT UNDER REVIEW                          */
+/*   These APIs are still evolving and are meant as a prototype for review.*/
+/*   The APIs will change depending on feedback and will be firmed up      */
+/*   to a stable set of APIs once all the feedback has been considered.    */
+/***************************************************************************/
+
+#ifndef __PSA_INITIAL_ATTESTATION_H__
+#define __PSA_INITIAL_ATTESTATION_H__
+
+#include <limits.h>
+#include <stdint.h>
+#include <stddef.h>
+#include "psa/crypto.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief PSA INITIAL ATTESTATION API version
+ *
+ * Initial attestation API version is: 1.0.0
+ */
+#define PSA_INITIAL_ATTEST_API_VERSION_MAJOR (1)
+#define PSA_INITIAL_ATTEST_API_VERSION_MINOR (0)
+
+/**
+ * The allowed size of input challenge in bytes: 32, 48, 64
+ * Challenge can be a nonce from server
+ * or the hash of some combined data : nonce + attested data by caller.
+ */
+#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32  (32u)
+#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48  (48u)
+#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64  (64u)
+
+/**
+ * The maximum size of an attestation token that can be generated by the
+ * attestation service. Used to configure buffers for services that verify the
+ * produced tokens.
+ */
+#define PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE (0x400)
+
+/**
+ * The list of fixed claims in the initial attestation token is still evolving,
+ * you can expect slight changes in the future.
+ *
+ * The initial attestation token is planned to be aligned with future version of
+ * Entity Attestation Token format:
+ * https://tools.ietf.org/html/draft-mandyam-eat-01
+ *
+ * Current list of claims:
+ *  - Challenge:   Input object from caller. Can be a single nonce from server
+ *                 or hash of nonce and attested data. It is intended to provide
+ *                 freshness to reports and the caller has responsibility to
+ *                 arrange this. Allowed length: 32, 48, 64 bytes. The claim is
+ *                 modeled to be eventually represented by the EAT standard
+ *                 claim nonce. Until such a time as that standard exists,
+ *                 the claim will be represented by a custom claim. Value
+ *                 is encoded as byte string.
+ *
+ *  - Instance ID: It represents the unique identifier of the instance. In the
+ *                 PSA definition it is a hash of the public attestation key
+ *                 of the instance. The claim is modeled to be eventually
+ *                 represented by the EAT standard claim UEID of type GUID.
+ *                 Until such a time as that standard exists, the claim will be
+ *                 represented by a custom claim  Value is encoded as byte
+ *                 string.
+ *
+ *  - Verification service indicator: Optional, recommended claim. It is used by
+ *                 a Relying Party to locate a validation service for the token.
+ *                 The value is a text string that can be used to locate the
+ *                 service or a URL specifying the address of the service. The
+ *                 claim is modeled to be eventually represented by the EAT
+ *                 standard claim origination. Until such a time as that
+ *                 standard exists, the claim will be represented by a custom
+ *                 claim. Value is encoded as text string.
+ *
+ *  - Profile definition: Optional, recommended claim. It contains the name of
+ *                 a document that describes the 'profile' of the token, being
+ *                 a full description of the claims, their usage, verification
+ *                 and token signing. The document name may include versioning.
+ *                 Custom claim with a value encoded as text string.
+ *
+ *  - Implementation ID: It represents the original implementation signer of the
+ *                 attestation key and identifies the contract between the
+ *                 report and verification. A verification service will use this
+ *                 claim to locate the details of the verification process.
+ *                 Custom claim with a value encoded as byte string.
+ *
+ *  - Security lifecycle: It represents the current lifecycle state of the
+ *                 instance. Custom claim with a value encoded as integer that
+ *                 is divided to convey a major state and a minor state. The
+ *                 PSA state and implementation state are encoded as follows:
+ *                   - version[15:8] - PSA lifecycle state - major
+ *                   - version[7:0]  - IMPLEMENTATION DEFINED state - minor
+ *                 Possible PSA lifecycle states:
+ *                  - Unknown (0x1000u),
+ *                  - PSA_RoT_Provisioning (0x2000u),
+ *                  - Secured (0x3000u),
+ *                  - Non_PSA_RoT_Debug(0x4000u),
+ *                  - Recoverable_PSA_RoT_Debug (0x5000u),
+ *                  - Decommissioned (0x6000u)
+ *
+ *  - Client ID:   The partition ID of that secure partition or non-secure
+ *                 thread who called the initial attestation API. Custom claim
+ *                 with a value encoded as a *signed* integer. Negative number
+ *                 represents non-secure caller, positive numbers represents
+ *                 secure callers, zero is invalid.
+ *
+ *  - HW version:  Optional claim. Globally unique number in EAN-13 format
+ *                 identifying the GDSII that went to fabrication, HW and ROM.
+ *                 It can be used to reference the security level of the PSA-ROT
+ *                 via a certification website. Custom claim with a value is
+ *                 encoded as text string.
+
+ *  - Boot seed:   It represents a random value created at system boot time that
+ *                 will allow differentiation of reports from different system
+ *                 sessions. The size is 32 bytes. Custom claim with a value is
+ *                 encoded as byte string.
+ *
+ *  - Software components: Recommended claim. It represents the software state
+ *                 of the system. The value of the claim is an array of CBOR map
+ *                 entries, with one entry per software component within the
+ *                 device. Each map contains multiple claims that describe
+ *                 evidence about the details of the software component.
+ *
+ *     - Measurement type: Optional claim. It represents the role of the
+ *                    software component. Value is encoded as short(!) text
+ *                    string.
+ *
+ *     - Measurement value: It represents a hash of the invariant software
+ *                    component in memory at start-up time. The value must be a
+ *                    cryptographic hash of 256 bits or stronger.Value is
+ *                    encoded as byte string.
+ *
+ *     - Version:     Optional claim. It represents the issued software version.
+ *                    Value is encoded as text string.
+ *
+ *     - Signer ID:   It represents the hash of a signing authority public key.
+ *                    Value is encoded as byte string.
+ *
+ *     - Measurement description: Optional claim. It represents the way in which
+ *                    the measurement value of the software component is
+ *                    computed. Value is encoded as text string containing an
+ *                    abbreviated description (name) of the measurement method.
+ *
+ *  - No software measurements: In the event that the implementation does not
+ *                 contain any software measurements then the software
+ *                 components claim above can be omitted but instead
+ *                 it is mandatory to include this claim to indicate this is a
+ *                 deliberate state. Custom claim a value is encoded as unsigned
+ *                 integer set to 1.
+ */
+
+/**
+ * \brief Get initial attestation token
+ *
+ * \param[in]     auth_challenge  Pointer to buffer where challenge input is
+ *                                stored. Nonce and / or hash of attested data.
+ *                                Must be always
+ *                                \ref PSA_INITIAL_ATTEST_TOKEN_SIZE bytes
+ *                                long.
+ * \param[in]     challenge_size  Size of challenge object in bytes.
+ * \param[out]    token_buf       Pointer to the buffer where attestation token
+ *                                will be stored.
+ * \param[in]     token_buf_size  Size of allocated buffer for token, in bytes.
+ * \param[out]    token_size      Size of the token that has been returned, in
+ *                                bytes.
+ *
+ * \return Returns error code as specified in \ref psa_status_t
+ */
+psa_status_t
+psa_initial_attest_get_token(const uint8_t *auth_challenge,
+                             size_t         challenge_size,
+                             uint8_t       *token_buf,
+                             size_t         token_buf_size,
+                             size_t        *token_size);
+
+/**
+ * \brief Get the exact size of initial attestation token in bytes.
+ *
+ * It just returns with the size of the IAT token. It can be used if the caller
+ * dynamically allocates memory for the token buffer.
+ *
+ * \param[in]   challenge_size  Size of challenge object in bytes. This must be
+ *                              a supported challenge size (as above).
+ * \param[out]  token_size      Size of the token in bytes, which is created by
+ *                              initial attestation service.
+ *
+ * \return Returns error code as specified in \ref psa_status_t
+ */
+psa_status_t
+psa_initial_attest_get_token_size(size_t  challenge_size,
+                                  size_t *token_size);
+
+/**
+ * \brief Get the initial attestation public key.
+ *
+ * \param[out]  public_key        Pointer to the buffer where the public key
+ *                                will be stored.
+ * \param[in]   key_buf_size      Size of allocated buffer for key, in bytes.
+ * \param[out]  public_key_len    Size of public key in bytes.
+ * \param[out]  public_key_curve  Type of the elliptic curve which the key
+ *                                belongs to.
+ *
+ * \note Currently only the ECDSA P-256 over SHA-256 algorithm is supported.
+ *
+ * \return Returns error code as specified in \ref psa_status_t
+ */
+psa_status_t
+tfm_initial_attest_get_public_key(uint8_t          *public_key,
+                                  size_t            public_key_buf_size,
+                                  size_t           *public_key_len,
+                                  psa_ecc_family_t *elliptic_curve_type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PSA_INITIAL_ATTESTATION_H__ */