Attest: Add initial attestation prototype

Details:
 - implement initial version of API
 - implement veneer function and SVC handler
 - implement wrapper functions around veneers on S and NS side
 - create manifest files and generate new partition defines
 - add attestation service to build system
 - update linker scripts for ARMCLANG and GNUARM

Change-Id: I987509c6cad08fcd082667bca7dbc9a328ea03de
Signed-off-by: Tamas Ban <tamas.ban@arm.com>
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index ca71227..798b24d 100755
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -47,6 +47,7 @@
 	"${INTERFACE_DIR}/src/tfm_audit_api.c"
 	"${INTERFACE_DIR}/src/tfm_crypto_api.c"
 	"${INTERFACE_DIR}/src/tfm_platform_api.c"
+	"${INTERFACE_DIR}/src/tfm_initial_attestation_api.c"
 	"${INTERFACE_DIR}/src/tfm_ns_lock_rtx.c"
 	)
 
diff --git a/interface/include/tfm_initial_attestation_veneers.h b/interface/include/tfm_initial_attestation_veneers.h
new file mode 100644
index 0000000..502ab3e
--- /dev/null
+++ b/interface/include/tfm_initial_attestation_veneers.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_INITIAL_ATTESTATION_VENEERS_H__
+#define __TFM_INITIAL_ATTESTATION_VENEERS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "psa_client.h"
+
+/**
+ * \brief Get initial attestation token
+ *
+ * \param[in]     in_vec     Pointer to in_vec array, which contains input data
+ *                           to attestation service
+ * \param[in]     num_invec  Number of elements in in_vec array
+ * \param[in/out] out_vec    Pointer out_vec array, which contains output data
+ *                           to attestation service
+ * \param[in]     num_outvec Number of elements in out_vec array
+ *
+ * \return Returns error code as specified in \ref psa_attest_err_t
+ */
+enum psa_attest_err_t
+tfm_attest_veneer_get_token(const psa_invec  *in_vec,  uint32_t num_invec,
+                                  psa_outvec *out_vec, uint32_t num_outvec);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_INITIAL_ATTESTATION_VENEERS_H__ */
diff --git a/interface/src/tfm_initial_attestation_api.c b/interface/src/tfm_initial_attestation_api.c
new file mode 100644
index 0000000..b935f34
--- /dev/null
+++ b/interface/src/tfm_initial_attestation_api.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "psa_initial_attestation_api.h"
+#include "tfm_initial_attestation_veneers.h"
+#include "tfm_ns_lock.h"
+#include "psa_client.h"
+
+enum psa_attest_err_t
+psa_initial_attest_get_token(const uint8_t *challenge_obj,
+                             uint32_t       challenge_size,
+                             uint8_t       *token,
+                             uint32_t      *token_size)
+{
+    psa_invec  in_vec[1];
+    psa_outvec out_vec[1];
+
+    in_vec[0].base = challenge_obj;
+    in_vec[0].len  = challenge_size;
+
+    out_vec[0].base = token;
+    out_vec[0].len  = *token_size;
+
+    return tfm_ns_lock_dispatch((veneer_fn)tfm_attest_veneer_get_token,
+                                (uint32_t)in_vec,  1,
+                                (uint32_t)out_vec, 1);
+}
diff --git a/platform/ext/target/mps2/an519/armclang/mps2_an519_s.sct b/platform/ext/target/mps2/an519/armclang/mps2_an519_s.sct
index 3820076..840724a 100644
--- a/platform/ext/target/mps2/an519/armclang/mps2_an519_s.sct
+++ b/platform/ext/target/mps2/an519/armclang/mps2_an519_s.sct
@@ -87,6 +87,11 @@
         *(TFM_SP_PLATFORM_ATTR_FN)
     }
 
+    TFM_SP_INITIAL_ATTESTATION +0 ALIGN 32 {
+        *tfm_attest* (+RO)
+        *(TFM_SP_INITIAL_ATTESTATION_ATTR_FN)
+    }
+
 #ifdef TFM_PARTITION_TEST_CORE
     TFM_SP_CORE_TEST +0 ALIGN 32 {
         *tfm_ss_core_test.* (+RO)
@@ -177,6 +182,13 @@
     TFM_SP_PLATFORM_STACK +0 ALIGN 128 EMPTY 0x0400 {
     }
 
+    TFM_SP_INITIAL_ATTESTATION_DATA +0 ALIGN 32 {
+        *tfm_attest* (+RW +ZI)
+    }
+
+    TFM_SP_INITIAL_ATTESTATION_STACK +0 ALIGN 128 EMPTY 0x400 {
+    }
+
 #ifdef TFM_PARTITION_TEST_CORE
     TFM_SP_CORE_TEST_DATA +0 ALIGN 32 {
         tfm_ss_core_test.o (+RW +ZI)
diff --git a/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld b/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld
index 8eb0502..5598438 100644
--- a/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld
+++ b/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld
@@ -103,6 +103,9 @@
         LONG (LOADADDR(.TFM_SP_PLATFORM_DATA))
         LONG (ADDR(.TFM_SP_PLATFORM_DATA))
         LONG (SIZEOF(.TFM_SP_PLATFORM_DATA))
+        LONG (LOADADDR(.TFM_SP_INITIAL_ATTESTATION_DATA))
+        LONG (ADDR(.TFM_SP_INITIAL_ATTESTATION_DATA))
+        LONG (SIZEOF(.TFM_SP_INITIAL_ATTESTATION_DATA))
 #ifdef TFM_PARTITION_TEST_CORE
         LONG (LOADADDR(.TFM_SP_CORE_TEST_DATA))
         LONG (ADDR(.TFM_SP_CORE_TEST_DATA))
@@ -149,6 +152,10 @@
         LONG (SIZEOF(.TFM_SP_PLATFORM_BSS))
         LONG (ADDR(.TFM_SP_PLATFORM_STACK))
         LONG (SIZEOF(.TFM_SP_PLATFORM_STACK))
+        LONG (ADDR(.TFM_SP_INITIAL_ATTESTATION_BSS))
+        LONG (SIZEOF(.TFM_SP_INITIAL_ATTESTATION_BSS))
+        LONG (ADDR(.TFM_SP_INITIAL_ATTESTATION_STACK))
+        LONG (SIZEOF(.TFM_SP_INITIAL_ATTESTATION_STACK))
 #ifdef TFM_PARTITION_TEST_CORE
         LONG (ADDR(.TFM_SP_CORE_TEST_BSS))
         LONG (SIZEOF(.TFM_SP_CORE_TEST_BSS))
@@ -250,6 +257,18 @@
     Image$$TFM_SP_PLATFORM$$Base = ADDR(.TFM_SP_PLATFORM);
     Image$$TFM_SP_PLATFORM$$Limit = ADDR(.TFM_SP_PLATFORM) + SIZEOF(.TFM_SP_PLATFORM);
 
+    .TFM_SP_INITIAL_ATTESTATION : ALIGN(32)
+    {
+        *tfm_attest*:*(.text*)
+        *tfm_attest*:*(.rodata*)
+        *(TFM_SP_INITIAL_ATTESTATION_ATTR_FN)
+        . = ALIGN(32);
+    } > FLASH
+    Image$$TFM_SP_INITIAL_ATTESTATION$$RO$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION);
+    Image$$TFM_SP_INITIAL_ATTESTATION$$RO$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION);
+    Image$$TFM_SP_INITIAL_ATTESTATION$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION);
+    Image$$TFM_SP_INITIAL_ATTESTATION$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION);
+
 #ifdef TFM_PARTITION_TEST_CORE
     .TFM_SP_CORE_TEST : ALIGN(32)
     {
@@ -543,6 +562,30 @@
     Image$$TFM_SP_PLATFORM_STACK$$ZI$$Base = ADDR(.TFM_SP_PLATFORM_STACK);
     Image$$TFM_SP_PLATFORM_STACK$$ZI$$Limit = ADDR(.TFM_SP_PLATFORM_STACK) + SIZEOF(.TFM_SP_PLATFORM_STACK);
 
+    .TFM_SP_INITIAL_ATTESTATION_DATA : ALIGN(32)
+    {
+        *tfm_attest*:*(.data*)
+        . = ALIGN(32);
+    } > RAM AT> FLASH
+    Image$$TFM_SP_INITIAL_ATTESTATION_DATA$$RW$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION_DATA);
+    Image$$TFM_SP_INITIAL_ATTESTATION_DATA$$RW$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION_DATA) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION_DATA);
+
+    .TFM_SP_INITIAL_ATTESTATION_BSS : ALIGN(32)
+    {
+        *tfm_attest*:*(.bss*)
+        *tfm_attest*:*(COMMON)
+        . = ALIGN(32);
+    } > RAM AT> FLASH
+    Image$$TFM_SP_INITIAL_ATTESTATION_DATA$$ZI$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION_BSS);
+    Image$$TFM_SP_INITIAL_ATTESTATION_DATA$$ZI$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION_BSS) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION_BSS);
+
+    .TFM_SP_INITIAL_ATTESTATION_STACK : ALIGN(128)
+    {
+        . += 0x0400;
+    } > RAM AT> FLASH
+    Image$$TFM_SP_INITIAL_ATTESTATION_STACK$$ZI$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION_STACK);
+    Image$$TFM_SP_INITIAL_ATTESTATION_STACK$$ZI$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION_STACK) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION_STACK);
+
 #ifdef TFM_PARTITION_TEST_CORE
     .TFM_SP_CORE_TEST_DATA : ALIGN(32)
     {
diff --git a/platform/ext/target/mps2/an521/armclang/mps2_an521_s.sct b/platform/ext/target/mps2/an521/armclang/mps2_an521_s.sct
index 3820076..7c2401c 100644
--- a/platform/ext/target/mps2/an521/armclang/mps2_an521_s.sct
+++ b/platform/ext/target/mps2/an521/armclang/mps2_an521_s.sct
@@ -87,6 +87,11 @@
         *(TFM_SP_PLATFORM_ATTR_FN)
     }
 
+    TFM_SP_INITIAL_ATTESTATION +0 ALIGN 32 {
+        *tfm_attest* (+RO)
+        *(TFM_SP_INITIAL_ATTESTATION_PLATFORM_ATTR_FN)
+    }
+
 #ifdef TFM_PARTITION_TEST_CORE
     TFM_SP_CORE_TEST +0 ALIGN 32 {
         *tfm_ss_core_test.* (+RO)
@@ -177,6 +182,13 @@
     TFM_SP_PLATFORM_STACK +0 ALIGN 128 EMPTY 0x0400 {
     }
 
+    TFM_SP_INITIAL_ATTESTATION_DATA +0 ALIGN 32 {
+        *tfm_attest* (+RW +ZI)
+    }
+
+    TFM_SP_INITIAL_ATTESTATION_STACK +0 ALIGN 128 EMPTY 0x400 {
+    }
+
 #ifdef TFM_PARTITION_TEST_CORE
     TFM_SP_CORE_TEST_DATA +0 ALIGN 32 {
         tfm_ss_core_test.o (+RW +ZI)
diff --git a/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld b/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld
index 880dace..b8b9c12 100644
--- a/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld
+++ b/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld
@@ -103,6 +103,9 @@
         LONG (LOADADDR(.TFM_SP_PLATFORM_DATA))
         LONG (ADDR(.TFM_SP_PLATFORM_DATA))
         LONG (SIZEOF(.TFM_SP_PLATFORM_DATA))
+        LONG (LOADADDR(.TFM_SP_INITIAL_ATTESTATION_DATA))
+        LONG (ADDR(.TFM_SP_INITIAL_ATTESTATION_DATA))
+        LONG (SIZEOF(.TFM_SP_INITIAL_ATTESTATION_DATA))
 #ifdef TFM_PARTITION_TEST_CORE
         LONG (LOADADDR(.TFM_SP_CORE_TEST_DATA))
         LONG (ADDR(.TFM_SP_CORE_TEST_DATA))
@@ -149,6 +152,10 @@
         LONG (SIZEOF(.TFM_SP_PLATFORM_BSS))
         LONG (ADDR(.TFM_SP_PLATFORM_STACK))
         LONG (SIZEOF(.TFM_SP_PLATFORM_STACK))
+        LONG (ADDR(.TFM_SP_INITIAL_ATTESTATION_BSS))
+        LONG (SIZEOF(.TFM_SP_INITIAL_ATTESTATION_BSS))
+        LONG (ADDR(.TFM_SP_INITIAL_ATTESTATION_STACK))
+        LONG (SIZEOF(.TFM_SP_INITIAL_ATTESTATION_STACK))
 #ifdef TFM_PARTITION_TEST_CORE
         LONG (ADDR(.TFM_SP_CORE_TEST_BSS))
         LONG (SIZEOF(.TFM_SP_CORE_TEST_BSS))
@@ -250,6 +257,18 @@
     Image$$TFM_SP_PLATFORM$$Base = ADDR(.TFM_SP_PLATFORM);
     Image$$TFM_SP_PLATFORM$$Limit = ADDR(.TFM_SP_PLATFORM) + SIZEOF(.TFM_SP_PLATFORM);
 
+    .TFM_SP_INITIAL_ATTESTATION : ALIGN(32)
+    {
+        *tfm_attest*:*(.text*)
+        *tfm_attest*:*(.rodata*)
+        *(TFM_SP_INITIAL_ATTESTATION_ATTR_FN)
+        . = ALIGN(32);
+    } > FLASH
+    Image$$TFM_SP_INITIAL_ATTESTATION$$RO$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION);
+    Image$$TFM_SP_INITIAL_ATTESTATION$$RO$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION);
+    Image$$TFM_SP_INITIAL_ATTESTATION$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION);
+    Image$$TFM_SP_INITIAL_ATTESTATION$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION);
+
 #ifdef TFM_PARTITION_TEST_CORE
     .TFM_SP_CORE_TEST : ALIGN(32)
     {
@@ -543,6 +562,30 @@
     Image$$TFM_SP_PLATFORM_STACK$$ZI$$Base = ADDR(.TFM_SP_PLATFORM_STACK);
     Image$$TFM_SP_PLATFORM_STACK$$ZI$$Limit = ADDR(.TFM_SP_PLATFORM_STACK) + SIZEOF(.TFM_SP_PLATFORM_STACK);
 
+    .TFM_SP_INITIAL_ATTESTATION_DATA : ALIGN(32)
+    {
+        *tfm_attest*:*(.data*)
+        . = ALIGN(32);
+    } > RAM AT> FLASH
+    Image$$TFM_SP_INITIAL_ATTESTATION_DATA$$RW$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION_DATA);
+    Image$$TFM_SP_INITIAL_ATTESTATION_DATA$$RW$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION_DATA) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION_DATA);
+
+    .TFM_SP_INITIAL_ATTESTATION_BSS : ALIGN(32)
+    {
+        *tfm_attest*:*(.bss*)
+        *tfm_attest*:*(COMMON)
+        . = ALIGN(32);
+    } > RAM AT> FLASH
+    Image$$TFM_SP_INITIAL_ATTESTATION_DATA$$ZI$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION_BSS);
+    Image$$TFM_SP_INITIAL_ATTESTATION_DATA$$ZI$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION_BSS) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION_BSS);
+
+    .TFM_SP_INITIAL_ATTESTATION_STACK : ALIGN(128)
+    {
+        . += 0x0400;
+    } > RAM AT> FLASH
+    Image$$TFM_SP_INITIAL_ATTESTATION_STACK$$ZI$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION_STACK);
+    Image$$TFM_SP_INITIAL_ATTESTATION_STACK$$ZI$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION_STACK) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION_STACK);
+
 #ifdef TFM_PARTITION_TEST_CORE
     .TFM_SP_CORE_TEST_DATA : ALIGN(32)
     {
diff --git a/platform/ext/target/musca_a/Device/Source/armclang/musca_s.sct b/platform/ext/target/musca_a/Device/Source/armclang/musca_s.sct
index 694b050..28de2ac 100755
--- a/platform/ext/target/musca_a/Device/Source/armclang/musca_s.sct
+++ b/platform/ext/target/musca_a/Device/Source/armclang/musca_s.sct
@@ -87,6 +87,11 @@
         *(TFM_SP_PLATFORM_ATTR_FN)
     }
 
+    TFM_SP_INITIAL_ATTESTATION +0 ALIGN 32 {
+        *tfm_attest* (+RO)
+        *(TFM_SP_INITIAL_ATTESTATION_ATTR_FN)
+    }
+
 #ifdef TFM_PARTITION_TEST_CORE
     TFM_SP_CORE_TEST +0 ALIGN 32 {
         *tfm_ss_core_test.* (+RO)
@@ -177,6 +182,13 @@
     TFM_SP_PLATFORM_STACK +0 ALIGN 128 EMPTY 0x0400 {
     }
 
+    TFM_SP_INITIAL_ATTESTATION_DATA +0 ALIGN 32 {
+        *tfm_attest* (+RW +ZI)
+    }
+
+    TFM_SP_INITIAL_ATTESTATION_STACK +0 ALIGN 128 EMPTY 0x400 {
+    }
+
 #ifdef TFM_PARTITION_TEST_CORE
     TFM_SP_CORE_TEST_DATA +0 ALIGN 32 {
         tfm_ss_core_test.o (+RW +ZI)
diff --git a/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld b/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld
index 8eb0502..5598438 100644
--- a/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld
+++ b/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld
@@ -103,6 +103,9 @@
         LONG (LOADADDR(.TFM_SP_PLATFORM_DATA))
         LONG (ADDR(.TFM_SP_PLATFORM_DATA))
         LONG (SIZEOF(.TFM_SP_PLATFORM_DATA))
+        LONG (LOADADDR(.TFM_SP_INITIAL_ATTESTATION_DATA))
+        LONG (ADDR(.TFM_SP_INITIAL_ATTESTATION_DATA))
+        LONG (SIZEOF(.TFM_SP_INITIAL_ATTESTATION_DATA))
 #ifdef TFM_PARTITION_TEST_CORE
         LONG (LOADADDR(.TFM_SP_CORE_TEST_DATA))
         LONG (ADDR(.TFM_SP_CORE_TEST_DATA))
@@ -149,6 +152,10 @@
         LONG (SIZEOF(.TFM_SP_PLATFORM_BSS))
         LONG (ADDR(.TFM_SP_PLATFORM_STACK))
         LONG (SIZEOF(.TFM_SP_PLATFORM_STACK))
+        LONG (ADDR(.TFM_SP_INITIAL_ATTESTATION_BSS))
+        LONG (SIZEOF(.TFM_SP_INITIAL_ATTESTATION_BSS))
+        LONG (ADDR(.TFM_SP_INITIAL_ATTESTATION_STACK))
+        LONG (SIZEOF(.TFM_SP_INITIAL_ATTESTATION_STACK))
 #ifdef TFM_PARTITION_TEST_CORE
         LONG (ADDR(.TFM_SP_CORE_TEST_BSS))
         LONG (SIZEOF(.TFM_SP_CORE_TEST_BSS))
@@ -250,6 +257,18 @@
     Image$$TFM_SP_PLATFORM$$Base = ADDR(.TFM_SP_PLATFORM);
     Image$$TFM_SP_PLATFORM$$Limit = ADDR(.TFM_SP_PLATFORM) + SIZEOF(.TFM_SP_PLATFORM);
 
+    .TFM_SP_INITIAL_ATTESTATION : ALIGN(32)
+    {
+        *tfm_attest*:*(.text*)
+        *tfm_attest*:*(.rodata*)
+        *(TFM_SP_INITIAL_ATTESTATION_ATTR_FN)
+        . = ALIGN(32);
+    } > FLASH
+    Image$$TFM_SP_INITIAL_ATTESTATION$$RO$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION);
+    Image$$TFM_SP_INITIAL_ATTESTATION$$RO$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION);
+    Image$$TFM_SP_INITIAL_ATTESTATION$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION);
+    Image$$TFM_SP_INITIAL_ATTESTATION$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION);
+
 #ifdef TFM_PARTITION_TEST_CORE
     .TFM_SP_CORE_TEST : ALIGN(32)
     {
@@ -543,6 +562,30 @@
     Image$$TFM_SP_PLATFORM_STACK$$ZI$$Base = ADDR(.TFM_SP_PLATFORM_STACK);
     Image$$TFM_SP_PLATFORM_STACK$$ZI$$Limit = ADDR(.TFM_SP_PLATFORM_STACK) + SIZEOF(.TFM_SP_PLATFORM_STACK);
 
+    .TFM_SP_INITIAL_ATTESTATION_DATA : ALIGN(32)
+    {
+        *tfm_attest*:*(.data*)
+        . = ALIGN(32);
+    } > RAM AT> FLASH
+    Image$$TFM_SP_INITIAL_ATTESTATION_DATA$$RW$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION_DATA);
+    Image$$TFM_SP_INITIAL_ATTESTATION_DATA$$RW$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION_DATA) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION_DATA);
+
+    .TFM_SP_INITIAL_ATTESTATION_BSS : ALIGN(32)
+    {
+        *tfm_attest*:*(.bss*)
+        *tfm_attest*:*(COMMON)
+        . = ALIGN(32);
+    } > RAM AT> FLASH
+    Image$$TFM_SP_INITIAL_ATTESTATION_DATA$$ZI$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION_BSS);
+    Image$$TFM_SP_INITIAL_ATTESTATION_DATA$$ZI$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION_BSS) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION_BSS);
+
+    .TFM_SP_INITIAL_ATTESTATION_STACK : ALIGN(128)
+    {
+        . += 0x0400;
+    } > RAM AT> FLASH
+    Image$$TFM_SP_INITIAL_ATTESTATION_STACK$$ZI$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION_STACK);
+    Image$$TFM_SP_INITIAL_ATTESTATION_STACK$$ZI$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION_STACK) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION_STACK);
+
 #ifdef TFM_PARTITION_TEST_CORE
     .TFM_SP_CORE_TEST_DATA : ALIGN(32)
     {
diff --git a/platform/ext/target/musca_b1/Device/Source/armclang/musca_s.sct b/platform/ext/target/musca_b1/Device/Source/armclang/musca_s.sct
index 966a796..dd946fa 100644
--- a/platform/ext/target/musca_b1/Device/Source/armclang/musca_s.sct
+++ b/platform/ext/target/musca_b1/Device/Source/armclang/musca_s.sct
@@ -87,6 +87,11 @@
         *(TFM_SP_PLATFORM_ATTR_FN)
     }
 
+    TFM_SP_INITIAL_ATTESTATION +0 ALIGN 32 {
+        *tfm_attest* (+RO)
+        *(TFM_SP_INITIAL_ATTESTATION_ATTR_FN)
+    }
+
 #ifdef TFM_PARTITION_TEST_CORE
     TFM_SP_CORE_TEST +0 ALIGN 32 {
         *tfm_ss_core_test.* (+RO)
@@ -177,6 +182,13 @@
     TFM_SP_PLATFORM_STACK +0 ALIGN 128 EMPTY 0x0400 {
     }
 
+    TFM_SP_INITIAL_ATTESTATION_DATA +0 ALIGN 32 {
+        *tfm_attest* (+RW +ZI)
+    }
+
+    TFM_SP_INITIAL_ATTESTATION_STACK +0 ALIGN 128 EMPTY 0x400 {
+    }
+
 #ifdef TFM_PARTITION_TEST_CORE
     TFM_SP_CORE_TEST_DATA +0 ALIGN 32 {
         tfm_ss_core_test.o (+RW +ZI)
diff --git a/platform/ext/target/musca_b1/Device/Source/gcc/musca_s.ld b/platform/ext/target/musca_b1/Device/Source/gcc/musca_s.ld
index bf5796c..4911be0 100644
--- a/platform/ext/target/musca_b1/Device/Source/gcc/musca_s.ld
+++ b/platform/ext/target/musca_b1/Device/Source/gcc/musca_s.ld
@@ -103,6 +103,9 @@
         LONG (LOADADDR(.TFM_SP_PLATFORM_DATA))
         LONG (ADDR(.TFM_SP_PLATFORM_DATA))
         LONG (SIZEOF(.TFM_SP_PLATFORM_DATA))
+        LONG (LOADADDR(.TFM_SP_INITIAL_ATTESTATION_DATA))
+        LONG (ADDR(.TFM_SP_INITIAL_ATTESTATION_DATA))
+        LONG (SIZEOF(.TFM_SP_INITIAL_ATTESTATION_DATA))
 #ifdef TFM_PARTITION_TEST_CORE
         LONG (LOADADDR(.TFM_SP_CORE_TEST_DATA))
         LONG (ADDR(.TFM_SP_CORE_TEST_DATA))
@@ -149,6 +152,10 @@
         LONG (SIZEOF(.TFM_SP_PLATFORM_BSS))
         LONG (ADDR(.TFM_SP_PLATFORM_STACK))
         LONG (SIZEOF(.TFM_SP_PLATFORM_STACK))
+        LONG (ADDR(.TFM_SP_INITIAL_ATTESTATION_BSS))
+        LONG (SIZEOF(.TFM_SP_INITIAL_ATTESTATION_BSS))
+        LONG (ADDR(.TFM_SP_INITIAL_ATTESTATION_STACK))
+        LONG (SIZEOF(.TFM_SP_INITIAL_ATTESTATION_STACK))
 #ifdef TFM_PARTITION_TEST_CORE
         LONG (ADDR(.TFM_SP_CORE_TEST_BSS))
         LONG (SIZEOF(.TFM_SP_CORE_TEST_BSS))
@@ -250,6 +257,18 @@
     Image$$TFM_SP_PLATFORM$$Base = ADDR(.TFM_SP_PLATFORM);
     Image$$TFM_SP_PLATFORM$$Limit = ADDR(.TFM_SP_PLATFORM) + SIZEOF(.TFM_SP_PLATFORM);
 
+    .TFM_SP_INITIAL_ATTESTATION : ALIGN(32)
+    {
+        *tfm_attest*:*(.text*)
+        *tfm_attest*:*(.rodata*)
+        *(TFM_SP_INITIAL_ATTESTATION_ATTR_FN)
+        . = ALIGN(32);
+    } > FLASH
+    Image$$TFM_SP_INITIAL_ATTESTATION$$RO$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION);
+    Image$$TFM_SP_INITIAL_ATTESTATION$$RO$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION);
+    Image$$TFM_SP_INITIAL_ATTESTATION$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION);
+    Image$$TFM_SP_INITIAL_ATTESTATION$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION);
+
 #ifdef TFM_PARTITION_TEST_CORE
     .TFM_SP_CORE_TEST : ALIGN(32)
     {
@@ -543,6 +562,30 @@
     Image$$TFM_SP_PLATFORM_STACK$$ZI$$Base = ADDR(.TFM_SP_PLATFORM_STACK);
     Image$$TFM_SP_PLATFORM_STACK$$ZI$$Limit = ADDR(.TFM_SP_PLATFORM_STACK) + SIZEOF(.TFM_SP_PLATFORM_STACK);
 
+    .TFM_SP_INITIAL_ATTESTATION_DATA : ALIGN(32)
+    {
+        *tfm_attest*:*(.data*)
+        . = ALIGN(32);
+    } > RAM AT> FLASH
+    Image$$TFM_SP_INITIAL_ATTESTATION_DATA$$RW$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION_DATA);
+    Image$$TFM_SP_INITIAL_ATTESTATION_DATA$$RW$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION_DATA) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION_DATA);
+
+    .TFM_SP_INITIAL_ATTESTATION_BSS : ALIGN(32)
+    {
+        *tfm_attest*:*(.bss*)
+        *tfm_attest*:*(COMMON)
+        . = ALIGN(32);
+    } > RAM AT> FLASH
+    Image$$TFM_SP_INITIAL_ATTESTATION_DATA$$ZI$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION_BSS);
+    Image$$TFM_SP_INITIAL_ATTESTATION_DATA$$ZI$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION_BSS) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION_BSS);
+
+    .TFM_SP_INITIAL_ATTESTATION_STACK : ALIGN(128)
+    {
+        . += 0x0400;
+    } > RAM AT> FLASH
+    Image$$TFM_SP_INITIAL_ATTESTATION_STACK$$ZI$$Base = ADDR(.TFM_SP_INITIAL_ATTESTATION_STACK);
+    Image$$TFM_SP_INITIAL_ATTESTATION_STACK$$ZI$$Limit = ADDR(.TFM_SP_INITIAL_ATTESTATION_STACK) + SIZEOF(.TFM_SP_INITIAL_ATTESTATION_STACK);
+
 #ifdef TFM_PARTITION_TEST_CORE
     .TFM_SP_CORE_TEST_DATA : ALIGN(32)
     {
diff --git a/secure_fw/CMakeLists.txt b/secure_fw/CMakeLists.txt
index 9008f07..7bd047e 100644
--- a/secure_fw/CMakeLists.txt
+++ b/secure_fw/CMakeLists.txt
@@ -136,6 +136,7 @@
 	add_dependencies(${EXE_NAME} tfm_audit)
 	add_dependencies(${EXE_NAME} tfm_platform)
 	add_dependencies(${EXE_NAME} tfm_secure_tests)
+	add_dependencies(${EXE_NAME} tfm_attest)
 
 	#Set macro definitions for the project.
 	embedded_set_target_compile_defines(TARGET ${PROJECT_OBJ_LIB} LANGUAGE C DEFINES __thumb2__ __ARM_FEATURE_CMSE=3 TFM_LVL=${TFM_LVL} DAUTH_CHIP_DEFAULT APPEND)
@@ -144,14 +145,14 @@
 		#The test service veneers may not be referenced in the secure binary so the
 		#veneer objects are explicitly loaded from the secure tests library.
 		if(${COMPILER} STREQUAL "ARMCLANG")
-			target_link_libraries(${EXE_NAME} tfm_crypto tfm_storage tfm_audit tfm_platform $<TARGET_LINKER_FILE:tfm_secure_tests>\(*veneers.o\) tfm_secure_tests)
+			target_link_libraries(${EXE_NAME} tfm_crypto tfm_storage tfm_audit tfm_platform tfm_attest $<TARGET_LINKER_FILE:tfm_secure_tests>\(*veneers.o\) tfm_secure_tests)
 		elseif(${COMPILER} STREQUAL "GNUARM")
-			target_link_libraries(${EXE_NAME} tfm_secure_tests tfm_crypto tfm_storage tfm_audit tfm_platform)
+			target_link_libraries(${EXE_NAME} tfm_secure_tests tfm_crypto tfm_storage tfm_audit tfm_platform tfm_attest)
 		else()
 			message(FATAL_ERROR "unknown compiler" )
 		endif()
 	else()
-		target_link_libraries(${EXE_NAME} tfm_crypto tfm_storage tfm_audit tfm_platform)
+		target_link_libraries(${EXE_NAME} tfm_crypto tfm_storage tfm_audit tfm_platform tfm_attest)
 	endif()
 
 
@@ -261,6 +262,9 @@
 #Add the platform service library target
 add_subdirectory(${SECURE_FW_DIR}/services/platform)
 
+#Add the initial attestation service library target
+add_subdirectory(${SECURE_FW_DIR}/services/initial_attestation)
+
 if (LINK_TO_BOTH_MEMORY_REGION)
 	#Link to primary memory region
 	set_up_secure_fw_build(S_TARGET      ${PROJECT_NAME}
diff --git a/secure_fw/ns_callable/CMakeLists.inc b/secure_fw/ns_callable/CMakeLists.inc
index afba7d5..8b883db 100644
--- a/secure_fw/ns_callable/CMakeLists.inc
+++ b/secure_fw/ns_callable/CMakeLists.inc
@@ -26,7 +26,8 @@
 set (SS_NS_CALLABLE_C_SRC "${CMAKE_CURRENT_LIST_DIR}/tfm_sst_veneers.c"
                           "${CMAKE_CURRENT_LIST_DIR}/tfm_audit_veneers.c"
                           "${CMAKE_CURRENT_LIST_DIR}/tfm_crypto_veneers.c"
-                          "${CMAKE_CURRENT_LIST_DIR}/tfm_platform_veneers.c")
+                          "${CMAKE_CURRENT_LIST_DIR}/tfm_platform_veneers.c"
+                          "${CMAKE_CURRENT_LIST_DIR}/tfm_initial_attestation_veneers.c")
 
 #Append all our source files to global lists.
 list(APPEND ALL_SRC_C ${SS_NS_CALLABLE_C_SRC})
diff --git a/secure_fw/ns_callable/tfm_initial_attestation_veneers.c b/secure_fw/ns_callable/tfm_initial_attestation_veneers.c
new file mode 100644
index 0000000..df154d4
--- /dev/null
+++ b/secure_fw/ns_callable/tfm_initial_attestation_veneers.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "tfm_initial_attestation_veneers.h"
+#include "secure_fw/services/initial_attestation/attestation.h"
+#include "tfm_secure_api.h"
+#include "tfm_api.h"
+#include "spm_partition_defs.h"
+#include "psa_client.h"
+
+__tfm_secure_gateway_attributes__
+enum psa_attest_err_t
+tfm_attest_veneer_get_token(const psa_invec  *in_vec,  uint32_t num_invec,
+                                  psa_outvec *out_vec, uint32_t num_outvec)
+{
+    TFM_CORE_SFN_REQUEST(TFM_SP_INITIAL_ATTESTATION_ID,
+                         initial_attest_get_token,
+                         in_vec,  num_invec,
+                         out_vec, num_outvec);
+}
diff --git a/secure_fw/services/initial_attestation/CMakeLists.inc b/secure_fw/services/initial_attestation/CMakeLists.inc
new file mode 100644
index 0000000..7bc1f2a
--- /dev/null
+++ b/secure_fw/services/initial_attestation/CMakeLists.inc
@@ -0,0 +1,69 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+#Definitions to compile the "initial_attestation" module.
+#This file assumes it will be included from a project specific cmakefile, and
+#will not create a library or executable.
+#Inputs:
+#	MBEDTLS_INSTALL_DIR - directory where mbedtls headers and libraries can be found.
+#	TFM_ROOT_DIR        - root directory of the TF-M repository.
+#Outputs:
+#	Will modify include directories to make the source compile.
+#	ALL_SRC_C: C source files to be compiled will be added to this list. This shall be added to your add_executable or add_library command.
+#	ALL_SRC_CXX: C++ source files to be compiled will be added to this list. This shall be added to your add_executable or add_library command.
+#	ALL_SRC_ASM: assembly source files to be compiled will be added to this list. This shall be added to your add_executable or add_library command.
+#	Include directories will be modified by using the include_directories() commands as needed.
+
+#Get the current directory where this file is located.
+set(INITIAL_ATTESTATION_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+#Check input variables
+if (NOT DEFINED ENABLE_INITIAL_ATTESTATION)
+	message(FATAL_ERROR "Incomplete build configuration: ENABLE_INITIAL_ATTESTATION is undefined. ")
+endif()
+
+if (ENABLE_INITIAL_ATTESTATION)
+	if (NOT DEFINED TFM_ROOT_DIR)
+		message(FATAL_ERROR "Please set TFM_ROOT_DIR before including this file.")
+	endif()
+
+	#Append all our source files to global lists.
+	list(APPEND ALL_SRC_C
+		"${INITIAL_ATTESTATION_DIR}/tfm_attestation_secure_api.c"
+		"${INITIAL_ATTESTATION_DIR}/attestation_core.c"
+		)
+
+	#Setting include directories
+	embedded_include_directories(PATH ${TFM_ROOT_DIR} ABSOLUTE)
+	embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE)
+	embedded_include_directories(PATH ${TFM_ROOT_DIR}/platform/ext/common ABSOLUTE)
+
+	set(BUILD_CMSIS_CORE Off)
+	set(BUILD_RETARGET Off)
+	set(BUILD_NATIVE_DRIVERS Off)
+	set(BUILD_STARTUP Off)
+	set(BUILD_TARGET_CFG Off)
+	set(BUILD_TARGET_HARDWARE_KEYS Off)
+	set(BUILD_TARGET_NV_COUNTERS Off)
+	set(BUILD_CMSIS_DRIVERS Off)
+	set(BUILD_TIME Off)
+	set(BUILD_UART_STDOUT Off)
+	set(BUILD_FLASH Off)
+	set(BUILD_BOOT_SEED On)
+	set(BUILD_DEVICE_ID On)
+	if(NOT DEFINED PLATFORM_CMAKE_FILE)
+		message (FATAL_ERROR "Platform specific CMake is not defined. Please set PLATFORM_CMAKE_FILE.")
+	elseif(NOT EXISTS ${PLATFORM_CMAKE_FILE})
+		message (FATAL_ERROR "Platform specific CMake \"${PLATFORM_CMAKE_FILE}\" file does not exist. Please fix value of PLATFORM_CMAKE_FILE.")
+	else()
+		include(${PLATFORM_CMAKE_FILE})
+	endif()
+
+else()
+	message(FATAL_ERROR "Build system currently doesn't support selectively disabling of a service.")
+endif()
+
diff --git a/secure_fw/services/initial_attestation/CMakeLists.txt b/secure_fw/services/initial_attestation/CMakeLists.txt
new file mode 100644
index 0000000..1a1ea5f
--- /dev/null
+++ b/secure_fw/services/initial_attestation/CMakeLists.txt
@@ -0,0 +1,41 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+cmake_minimum_required(VERSION 3.7)
+
+#Tell cmake where our modules can be found
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/../../../cmake)
+
+#Include common stuff to control cmake.
+include("Common/BuildSys")
+
+#Start an embedded project.
+embedded_project_start(CONFIG "${CMAKE_CURRENT_LIST_DIR}/../../../ConfigDefault.cmake")
+project(tfm_attest LANGUAGES ASM C)
+embedded_project_fixup()
+
+###Some project global settings
+set (INITIAL_ATTESTATION_DIR "${CMAKE_CURRENT_LIST_DIR}")
+get_filename_component(TFM_ROOT_DIR "${INITIAL_ATTESTATION_DIR}/../../.." ABSOLUTE)
+
+###Get the definition of what files we need to build
+set (ENABLE_INITIAL_ATTESTATION ON)
+include(CMakeLists.inc)
+
+if (NOT DEFINED TFM_LVL)
+	message(FATAL_ERROR "Incomplete build configuration: TFM_LVL is undefined.")
+endif()
+
+#Specify what we build (for the initial attestation service, build as a static library)
+add_library(tfm_attest STATIC ${ALL_SRC_ASM} ${ALL_SRC_C})
+embedded_set_target_compile_defines(TARGET tfm_attest LANGUAGE C DEFINES __ARM_FEATURE_CMSE=3 __thumb2__ TFM_LVL=${TFM_LVL})
+
+#Set common compiler and linker flags
+config_setting_shared_compiler_flags(tfm_attest)
+config_setting_shared_linker_flags(tfm_attest)
+
+embedded_project_end(tfm_attest)
diff --git a/secure_fw/services/initial_attestation/attestation.h b/secure_fw/services/initial_attestation/attestation.h
new file mode 100644
index 0000000..2072cb4
--- /dev/null
+++ b/secure_fw/services/initial_attestation/attestation.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __ATTESTATION_H__
+#define __ATTESTATION_H__
+
+#include "psa_initial_attestation_api.h"
+#include "psa_client.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Extension of shared data TLVs defined in bl2/include/tfm_boot_status.h */
+#define TLV_MINOR_IAS_BOOT_SEED       0x0f
+#define TLV_MINOR_IAS_DEVICE_ID       0x10
+#define TLV_MINOR_IAS_CHALLENGE       0x11
+#define TLV_MINOR_IAS_CALLER_ID       0x12
+
+/*!
+ * \brief Initialise the initial attestation service during the TF-M boot up
+ *        process.
+ *
+ * \return Returns PSA_ATTEST_ERR_SUCCESS if init has been completed,
+ *         otherwise error as specified in \ref psa_attest_err_t
+ */
+enum psa_attest_err_t attest_init(void);
+
+/*!
+ * \brief Get initial attestation token
+ *
+ * \param[in]     in_vec     Pointer to in_vec array, which contains input data
+ *                           to attestation service
+ * \param[in]     num_invec  Number of elements in in_vec array
+ * \param[in/out] out_vec    Pointer out_vec array, which contains output data
+ *                           to attestation service
+ * \param[in]     num_outvec Number of elements in out_vec array
+ *
+ * \return Returns error code as specified in \ref psa_attest_err_t
+ */
+enum psa_attest_err_t
+initial_attest_get_token(const psa_invec  *in_vec,  uint32_t num_invec,
+                               psa_outvec *out_vec, uint32_t num_outvec);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ATTESTATION_H__ */
diff --git a/secure_fw/services/initial_attestation/attestation_core.c b/secure_fw/services/initial_attestation/attestation_core.c
new file mode 100644
index 0000000..c16d4a3
--- /dev/null
+++ b/secure_fw/services/initial_attestation/attestation_core.c
@@ -0,0 +1,460 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <stddef.h>
+#include "psa_initial_attestation_api.h"
+#include "attestation.h"
+#include "secure_utilities.h"
+#include "tfm_api.h"
+#include "tfm_secure_api.h"
+#include "psa_client.h"
+#include "bl2/include/tfm_boot_status.h"
+#include "platform/include/tfm_plat_device_id.h"
+#include "platform/include/tfm_plat_boot_seed.h"
+
+#define MAX_BOOT_STATUS 512
+
+/*!
+ * \var boot_status
+ *
+ * \brief Array variable to store the boot status in service's memory.
+ *
+ * \details Boot status comes from the secure bootloader and primarily stored
+ *          on a memory area which is shared between bootloader and SPM.
+ *          SPM provides the \ref tfm_core_get_boot_data() API to retrieve
+ *          the service related data from shared area.
+ */
+
+/* FixMe: Enforcement of 4 byte alignment can be removed as soon as memory type
+ *        is configured in the MPU to be normal, instead of device, which
+ *        prohibits unaligned access.
+ */
+__attribute__ ((aligned(4)))
+static uint8_t boot_status[MAX_BOOT_STATUS];
+
+enum psa_attest_err_t attest_init(void)
+{
+    enum tfm_status_e res;
+
+    res = tfm_core_get_boot_data(TLV_MAJOR_IAS, boot_status, MAX_BOOT_STATUS);
+    if (res != TFM_SUCCESS) {
+        return PSA_ATTEST_ERR_INIT_FAILED;
+    }
+
+    return PSA_ATTEST_ERR_SUCCESS;
+}
+
+/*!
+ * \brief Static function to look up a specific entry in the shared data
+ *        section.
+ *
+ * \param[in]  minor_type The identifier of the shared data entry
+ * \param[out] tlv_len    Length of the shared data entry
+ * \param[out] tlv_ptr    Pointer to the shared data entry
+ *
+ * \return Returns 0 on success. Otherwise, 1.
+ */
+static uint32_t attest_get_tlv(uint8_t    minor_type,
+                               uint16_t  *tlv_len,
+                               uint8_t  **tlv_ptr)
+{
+    struct shared_data_tlv_header *tlv_header;
+    struct shared_data_tlv_entry  *tlv_entry;
+    uintptr_t tlv_end;
+    uintptr_t tlv_curr;
+
+    tlv_header = (struct shared_data_tlv_header *)boot_status;
+    if (tlv_header->tlv_magic != SHARED_DATA_TLV_INFO_MAGIC) {
+        return 1;
+    }
+
+    /* Get the boundaries of TLV section */
+    tlv_end  = (uintptr_t)boot_status + tlv_header->tlv_tot_len;
+    tlv_curr = (uintptr_t)boot_status + SHARED_DATA_HEADER_SIZE;
+
+    /* Iterates over the TLV section and copy TLVs with requested minor
+     * type to the provided buffer.
+     */
+    for(; tlv_curr < tlv_end; tlv_curr += tlv_entry->tlv_len) {
+        tlv_entry = (struct shared_data_tlv_entry *)tlv_curr;
+        if (tlv_entry->tlv_minor_type == minor_type) {
+            *tlv_ptr = (uint8_t *)tlv_entry;
+            *tlv_len = tlv_entry ->tlv_len;
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+/*!
+ * \brief Static function to copy a TLV entry from shared data section to the
+ *        attestation token.
+ *
+ * \param[in]  tlv_len        The length of TLV entry in bytes
+ * \param[in]  tlv_ptr        Pointer from where to copy the TLV entry
+ * \param[in]  token_buf_size Size of token buffer in bytes
+ * \param[out] token_buf      Pointer to buffer which stores the token
+ *
+ * \return Returns 0 on success. Otherwise, 1.
+ */
+static uint32_t attest_copy_tlv(uint16_t       tlv_len,
+                                const uint8_t *tlv_ptr,
+                                uint32_t       token_buf_size,
+                                uint8_t       *token_buf)
+{
+    struct shared_data_tlv_header *tlv_header;
+    uint8_t *next_tlv = token_buf;
+
+    tlv_header = (struct shared_data_tlv_header *)token_buf;
+    if (tlv_header->tlv_magic != SHARED_DATA_TLV_INFO_MAGIC) {
+        return 1;
+    }
+
+    if (tlv_header->tlv_tot_len + tlv_len > token_buf_size) {
+        return 1;
+    }
+
+    next_tlv += tlv_header->tlv_tot_len;
+    tlv_header->tlv_tot_len += tlv_len;
+    tfm_memcpy(next_tlv, tlv_ptr, tlv_len);
+
+    return 0;
+}
+
+/*!
+ * \brief Static function to add a TLV entry to the attestation token.
+ *
+ * \param[in]  minor_type     The identifier of the TLV entry
+ * \param[in]  size           Size of the TLV entry in bytes
+ * \param[in]  data           Pointer to the buffer which stores the TLV entry
+ * \param[in]  token_buf_size Size of token buffer in bytes
+ * \param[out] token_buf      Pointer to buffer which stores the token
+ *
+ * \return Returns 0 on success. Otherwise, 1.
+ */
+static uint32_t attest_add_tlv(uint8_t        minor_type,
+                               uint32_t       size,
+                               const uint8_t *data,
+                               uint32_t       token_buf_size,
+                               uint8_t       *token_buf)
+{
+    struct shared_data_tlv_header *tlv_header;
+    struct shared_data_tlv_entry  *tlv_entry;
+    uint8_t *next_tlv = token_buf;
+
+    tlv_header = (struct shared_data_tlv_header *)token_buf;
+    if (tlv_header->tlv_magic != SHARED_DATA_TLV_INFO_MAGIC) {
+        return 1;
+    }
+
+    if (tlv_header->tlv_tot_len + SHARED_DATA_ENTRY_SIZE(size) >
+        token_buf_size) {
+        return 1;
+    }
+
+    next_tlv += tlv_header->tlv_tot_len;
+    tlv_header->tlv_tot_len += SHARED_DATA_ENTRY_SIZE(size);
+
+    tlv_entry = (struct shared_data_tlv_entry *)next_tlv;
+    tlv_entry->tlv_major_type = TLV_MAJOR_IAS;
+    tlv_entry->tlv_minor_type = minor_type;
+    tlv_entry->tlv_len = SHARED_DATA_ENTRY_SIZE(size);
+
+    next_tlv += SHARED_DATA_ENTRY_HEADER_SIZE;
+    tfm_memcpy(next_tlv, data, size);
+
+    return 0;
+}
+
+/*!
+ * \brief Static function to initalise the token buffer. Add TLV data header to
+ *        it.
+ *
+ * \param[in]  token_buf_size Size of token buffer in bytes
+ * \param[out] token_buf      Pointer to buffer which stores the token
+ *
+ * \return Returns error code as specified in \ref psa_attest_err_t
+ */
+static enum psa_attest_err_t
+attest_init_token(uint32_t token_buf_size, uint8_t *token_buf)
+{
+    struct shared_data_tlv_header *tlv_header;
+
+    if (SHARED_DATA_HEADER_SIZE > token_buf_size) {
+        return PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW;
+    }
+
+    tlv_header = (struct shared_data_tlv_header *)token_buf;
+    tlv_header->tlv_magic = SHARED_DATA_TLV_INFO_MAGIC;
+    tlv_header->tlv_tot_len = SHARED_DATA_HEADER_SIZE;
+
+    return PSA_ATTEST_ERR_SUCCESS;
+}
+
+/*!
+ * \brief Static function to add boot status claim to attestation token.
+ *
+ * \param[in]  token_buf_size Size of token buffer in bytes
+ * \param[out] token_buf      Pointer to buffer which stores the token
+ *
+ * \return Returns error code as specified in \ref psa_attest_err_t
+ */
+static enum psa_attest_err_t
+attest_add_s_ns_sha256_claim(uint32_t token_buf_size, uint8_t *token_buf)
+{
+    uint16_t tlv_len;
+    uint8_t *tlv_ptr;
+    uint32_t res;
+
+    res = attest_get_tlv(TLV_MINOR_IAS_S_NS_SHA256, &tlv_len, &tlv_ptr);
+    if (res != 0) {
+        return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE;
+    }
+
+    res = attest_copy_tlv(tlv_len, tlv_ptr, token_buf_size, token_buf);
+    if (res != 0) {
+        return PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW;
+    }
+
+    return PSA_ATTEST_ERR_SUCCESS;
+}
+
+/*!
+ * \brief Static function to add boot seed claim to attestation token.
+ *
+ * \param[in]  token_buf_size Size of token buffer in bytes
+ * \param[out] token_buf      Pointer to buffer which stores the token
+ *
+ * \return Returns error code as specified in \ref psa_attest_err_t
+ */
+static enum psa_attest_err_t
+attest_add_boot_seed_claim(uint32_t token_buf_size, uint8_t *token_buf)
+{
+    /* FixMe: Enforcement of 4 byte alignment can be removed as soon as memory
+     *        type is configured in the MPU to be normal, instead of device,
+     *        which prohibits unaligned access.
+     */
+    __attribute__ ((aligned(4)))
+    uint8_t boot_seed[BOOT_SEED_SIZE];
+    uint32_t res;
+
+    res = tfm_plat_get_boot_seed(sizeof(boot_seed), boot_seed);
+    if (res != 0) {
+        return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE;
+    }
+
+    res = attest_add_tlv(TLV_MINOR_IAS_BOOT_SEED,
+                         BOOT_SEED_SIZE,
+                         boot_seed,
+                         token_buf_size,
+                         token_buf);
+    if (res != 0) {
+        return PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW;
+    }
+
+    return PSA_ATTEST_ERR_SUCCESS;
+}
+
+/*!
+ * \brief Static function to add device id claim to attestation token.
+ *
+ * \param[in]  token_buf_size Size of token buffer in bytes
+ * \param[out] token_buf      Pointer to buffer which stores the token
+ *
+ * \return Returns error code as specified in \ref psa_attest_err_t
+ */
+static enum psa_attest_err_t
+attest_add_device_id_claim(uint32_t token_buf_size, uint8_t *token_buf)
+{
+    /* FixMe: Enforcement of 4 byte alignment can be removed as soon as memory
+     *        type is configured in the MPU to be normal, instead of device,
+     *        which prohibits unaligned access.
+     */
+    __attribute__ ((aligned(4)))
+    uint8_t device_id[DEVICE_ID_MAX_SIZE];
+    uint32_t res;
+    int32_t size;
+
+    size = tfm_plat_get_device_id(sizeof(device_id), device_id);
+    if (size < 0) {
+        return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE;
+    }
+
+    res = attest_add_tlv(TLV_MINOR_IAS_DEVICE_ID,
+                         size,
+                         device_id,
+                         token_buf_size,
+                         token_buf);
+    if (res != 0) {
+        return PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW;
+    }
+
+    return PSA_ATTEST_ERR_SUCCESS;
+}
+
+/*!
+ * \brief Static function to add caller id claim to attestation token.
+ *
+ * \param[in]  token_buf_size Size of token buffer in bytes
+ * \param[out] token_buf      Pointer to buffer which stores the token
+ *
+ * \return Returns error code as specified in \ref psa_attest_err_t
+ */
+static enum psa_attest_err_t
+attest_add_caller_id_claim(uint32_t token_buf_size, uint8_t *token_buf)
+{
+    uint32_t res;
+    int32_t  caller_id;
+
+    res = tfm_core_get_caller_client_id(&caller_id);
+    if (res != 0) {
+        return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE;
+    }
+
+    res = attest_add_tlv(TLV_MINOR_IAS_CALLER_ID,
+                         sizeof(int32_t),
+                         (uint8_t *)&caller_id,
+                         token_buf_size,
+                         token_buf);
+    if (res != 0) {
+        return PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW;
+    }
+
+    return PSA_ATTEST_ERR_SUCCESS;
+}
+
+/*!
+ * \brief Static function to add challenge claim to attestation token.
+ *
+ * \param[in]  challenge_buf_size Size of challenge object in bytes
+ * \param[in]  challenge_buf      Pointer to buffer which stores the challenge
+ *                                object
+ * \param[in]  token_buf_size     Size of token buffer in bytes
+ * \param[out] token_buf          Pointer to buffer which stores the token
+ *
+ * \return Returns error code as specified in \ref psa_attest_err_t
+ */
+static enum psa_attest_err_t
+attest_add_challenge_claim(uint32_t       challenge_buf_size,
+                           const uint8_t *challenge_buf,
+                           uint32_t       token_buf_size,
+                           uint8_t       *token_buf)
+{
+    uint32_t res;
+
+    res = attest_add_tlv(TLV_MINOR_IAS_CHALLENGE,
+                         challenge_buf_size,
+                         challenge_buf,
+                         token_buf_size,
+                         token_buf);
+    if (res != 0) {
+        return PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW;
+    }
+
+    return PSA_ATTEST_ERR_SUCCESS;
+}
+
+/*!
+ * \brief Static function to retrieve the constructed attestation token's size.
+ *
+ * \param[in] token_buf Pointer to buffer which stores the token
+ *
+ * \return Returns the size of token in bytes
+ */
+static uint32_t attest_get_token_size(const uint8_t *token_buf)
+{
+    struct shared_data_tlv_header *tlv_header;
+
+    tlv_header = (struct shared_data_tlv_header *)token_buf;
+
+    return tlv_header->tlv_tot_len;
+}
+
+/* Initial implementation of attestation service:
+ *  - data is TLV encoded
+ *  - token is not signed yet
+ *  - only fixed set of claims are supported
+ *  - external claims are not handled, expect challenge object
+ */
+enum psa_attest_err_t
+initial_attest_get_token(const psa_invec  *in_vec,  uint32_t num_invec,
+                               psa_outvec *out_vec, uint32_t num_outvec)
+{
+    enum tfm_status_e tfm_err;
+    enum psa_attest_err_t attest_err = PSA_ATTEST_ERR_SUCCESS;
+
+    const uint8_t *challenge_buf = (uint8_t *)in_vec[0].base;
+    size_t   challenge_buf_size  = in_vec[0].len;
+    uint8_t *token_buf           = (uint8_t *)out_vec[0].base;
+    size_t  *token_buf_size      = &(out_vec[0].len);
+
+    if (challenge_buf_size > PSA_INITIAL_ATTEST_MAX_CHALLENGE_SIZE) {
+        return PSA_ATTEST_ERR_INVALID_INPUT;
+    }
+
+    if (challenge_buf_size > 0) {
+        tfm_err = tfm_core_memory_permission_check((void *)challenge_buf,
+                                                   challenge_buf_size,
+                                                   TFM_MEMORY_ACCESS_RO);
+        if (tfm_err != TFM_SUCCESS) {
+            attest_err =  PSA_ATTEST_ERR_INVALID_INPUT;
+            goto error;
+        }
+    }
+
+    tfm_err = tfm_core_memory_permission_check(token_buf,
+                                               *token_buf_size,
+                                               TFM_MEMORY_ACCESS_RW);
+    if (tfm_err != TFM_SUCCESS) {
+        attest_err =  PSA_ATTEST_ERR_INVALID_INPUT;
+        goto error;
+    }
+
+    attest_err = attest_init_token(*token_buf_size, token_buf);
+    if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
+        goto error;
+    }
+
+    attest_err = attest_add_s_ns_sha256_claim(*token_buf_size, token_buf);
+    if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
+        goto error;
+    }
+
+    attest_err = attest_add_boot_seed_claim(*token_buf_size, token_buf);
+    if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
+        goto error;
+    }
+
+    attest_err = attest_add_device_id_claim(*token_buf_size, token_buf);
+    if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
+        goto error;
+    }
+
+    if (challenge_buf_size > 0) {
+        attest_err = attest_add_challenge_claim(challenge_buf_size,
+                                                challenge_buf,
+                                                *token_buf_size,
+                                                token_buf);
+        if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
+            goto error;
+        }
+    }
+
+    attest_err = attest_add_caller_id_claim(*token_buf_size, token_buf);
+    if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
+        goto error;
+    }
+     /* FixMe: Token should be signed with attestation key */
+
+    *token_buf_size = attest_get_token_size(token_buf);
+
+error:
+    return attest_err;
+}
diff --git a/secure_fw/services/initial_attestation/manifest.yaml b/secure_fw/services/initial_attestation/manifest.yaml
new file mode 100644
index 0000000..319987b
--- /dev/null
+++ b/secure_fw/services/initial_attestation/manifest.yaml
@@ -0,0 +1,37 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+{
+  "name": "INITIAL_ATTESTATION",
+  "type": "TRUSTED",
+  "tfm_partition_name": "TFM_SP_INITIAL_ATTESTATION",
+  "tfm_trusted": true,
+  "priority": "NORMAL",
+  "id": "0x00000103",
+  "entry_point": "main",
+  "stack_size": "0x0400",
+  "heap_size": "0x0400",
+  "tfm_init_symbol": "attest_init",
+  "secure_functions": [
+    {
+      "sfid": "TFM_ATTEST_GET_TOKEN_SFID",
+      "signal": "TFM_ATTEST_GET_TOKEN",
+      "tfm_symbol": "attest_get_token",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "strict"
+    }
+  ],
+  "source_files": [
+    "attestation_core.c"
+  ],
+  "tfm_linker_pattern": [
+    "library_list": [
+      "*tfm_attest*"
+    ]
+  ]
+}
diff --git a/secure_fw/services/initial_attestation/tfm_attestation_secure_api.c b/secure_fw/services/initial_attestation/tfm_attestation_secure_api.c
new file mode 100644
index 0000000..0943de0
--- /dev/null
+++ b/secure_fw/services/initial_attestation/tfm_attestation_secure_api.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "psa_initial_attestation_api.h"
+#include "tfm_initial_attestation_veneers.h"
+#include "secure_utilities.h"
+#include "psa_client.h"
+#include "tfm_secure_api.h"
+#include <string.h>
+
+/* FIXME: If iovec will be supported by SPM then remove the usage of
+ * scratch area.
+ */
+extern uint8_t *tfm_scratch_area;
+
+__attribute__((section("SFN")))
+enum psa_attest_err_t
+psa_initial_attest_get_token(const uint8_t *challenge_obj,
+                             uint32_t       challenge_size,
+                             uint8_t       *token,
+                             uint32_t      *token_size)
+{
+    enum psa_attest_err_t err;
+    psa_invec *in_vec;
+    psa_outvec *out_vec;
+    uint8_t *challenge_buff;
+    uint8_t *token_buff;
+
+    if (tfm_core_set_buffer_area(TFM_BUFFER_SHARE_SCRATCH) != TFM_SUCCESS) {
+        return PSA_ATTEST_ERR_GENERAL;
+    }
+
+    /*
+     * Scratch area layout
+     * -------------------------------------------------------
+     * |in_vec[0] | out_vec[0] | challenge_buff | token_buff |
+     * -------------------------------------------------------
+     */
+
+    in_vec  = (psa_invec  *)(tfm_scratch_area);
+    out_vec = (psa_outvec *)(in_vec + 1);
+
+    challenge_buff = (uint8_t *)(out_vec + 1);
+    token_buff     = (uint8_t *)(challenge_buff + challenge_size);
+
+    /* Copy challenge object to scratch area */
+    tfm_memcpy(challenge_buff, challenge_obj, challenge_size);
+
+
+    in_vec[0].base = challenge_buff;
+    in_vec[0].len  = challenge_size;
+
+    out_vec[0].base = token_buff;
+    out_vec[0].len  = *token_size;
+
+    err = tfm_attest_veneer_get_token(in_vec, 1, out_vec, 1);
+    if (err != PSA_ATTEST_ERR_SUCCESS) {
+        return err;
+    }
+
+    /* Copy output token to local buffer */
+    tfm_memcpy(token, out_vec[0].base, out_vec[0].len);
+    *token_size = out_vec[0].len;
+
+    return err;
+}
diff --git a/secure_fw/services/tfm_partition_defs.inc b/secure_fw/services/tfm_partition_defs.inc
index 1ef4cf0..a84c54b 100644
--- a/secure_fw/services/tfm_partition_defs.inc
+++ b/secure_fw/services/tfm_partition_defs.inc
@@ -18,22 +18,24 @@
 
 #define TFM_SP_PLATFORM_ID (TFM_SP_BASE + 3)
 
+#define TFM_SP_INITIAL_ATTESTATION_ID (TFM_SP_BASE + 4)
+
 #ifdef TFM_PARTITION_TEST_CORE
-#define TFM_SP_CORE_TEST_ID (TFM_SP_BASE + 4)
+#define TFM_SP_CORE_TEST_ID (TFM_SP_BASE + 5)
 #endif /* TFM_PARTITION_TEST_CORE */
 
 #ifdef TFM_PARTITION_TEST_CORE
-#define TFM_SP_CORE_TEST_2_ID (TFM_SP_BASE + 5)
+#define TFM_SP_CORE_TEST_2_ID (TFM_SP_BASE + 6)
 #endif /* TFM_PARTITION_TEST_CORE */
 
 #ifdef TFM_PARTITION_TEST_SST
-#define TFM_SP_SST_TEST_PARTITION_ID (TFM_SP_BASE + 6)
+#define TFM_SP_SST_TEST_PARTITION_ID (TFM_SP_BASE + 7)
 #endif /* TFM_PARTITION_TEST_SST */
 
 #ifdef TFM_PARTITION_TEST_SECURE_SERVICES
-#define TFM_SP_SECURE_TEST_PARTITION_ID (TFM_SP_BASE + 7)
+#define TFM_SP_SECURE_TEST_PARTITION_ID (TFM_SP_BASE + 8)
 #endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
 
-#define TFM_MAX_USER_PARTITIONS (8)
+#define TFM_MAX_USER_PARTITIONS (9)
 
 #endif /* __TFM_PARTITION_DEFS_INC__ */
diff --git a/secure_fw/services/tfm_partition_list.inc b/secure_fw/services/tfm_partition_list.inc
index 8be6ef9..57dd18f 100644
--- a/secure_fw/services/tfm_partition_list.inc
+++ b/secure_fw/services/tfm_partition_list.inc
@@ -29,6 +29,10 @@
 PARTITION_DECLARE(TFM_SP_PLATFORM, SPM_PART_FLAG_SECURE | SPM_PART_FLAG_TRUSTED);
 PARTITION_ADD_INIT_FUNC(TFM_SP_PLATFORM, platform_sp_init);
 
+/******** TFM_SP_INITIAL_ATTESTATION ********/
+PARTITION_DECLARE(TFM_SP_INITIAL_ATTESTATION, SPM_PART_FLAG_SECURE | SPM_PART_FLAG_TRUSTED);
+PARTITION_ADD_INIT_FUNC(TFM_SP_INITIAL_ATTESTATION, attest_init);
+
 #ifdef TFM_PARTITION_TEST_CORE
 /******** TFM_SP_CORE_TEST ********/
 PARTITION_DECLARE(TFM_SP_CORE_TEST, SPM_PART_FLAG_SECURE);
diff --git a/secure_fw/services/tfm_sfid_list.inc b/secure_fw/services/tfm_sfid_list.inc
index f2656df..e224dce 100644
--- a/secure_fw/services/tfm_sfid_list.inc
+++ b/secure_fw/services/tfm_sfid_list.inc
@@ -49,6 +49,9 @@
     /******** TFM_SP_PLATFORM ********/
     {platform_sp_system_reset, TFM_SP_PLATFORM_SYSTEM_RESET_SFID},
 
+    /******** TFM_SP_INITIAL_ATTESTATION ********/
+    {attest_get_token, TFM_ATTEST_GET_TOKEN_SFID},
+
 #ifdef TFM_PARTITION_TEST_CORE
     /******** TFM_SP_CORE_TEST ********/
     {spm_core_test_sfn, TFM_CORE_TEST_SFN_SFID},
diff --git a/tools/tfm_manifest_list.yaml b/tools/tfm_manifest_list.yaml
index 4363fc3..c06a13e 100644
--- a/tools/tfm_manifest_list.yaml
+++ b/tools/tfm_manifest_list.yaml
@@ -36,14 +36,22 @@
       "version_minor": 1

     },

     {

-      "name": "TFM Platform Service",
-      "short_name": "TFM_SP_Platform",
-      "manifest": "secure_fw/services/platform/manifest.yaml",
-      "tfm_extensions": true,
-      "version_major": 0,
-      "version_minor": 1
-    },
-    {
+      "name": "TFM Platform Service",

+      "short_name": "TFM_SP_Platform",

+      "manifest": "secure_fw/services/platform/manifest.yaml",

+      "tfm_extensions": true,

+      "version_major": 0,

+      "version_minor": 1

+    },

+    {

+      "name": "TFM Initial Attestation Service",

+      "short_name": "TFM_Init_Attest",

+      "manifest": "secure_fw/services/initial_attestation/manifest.yaml",

+      "tfm_extensions": true,

+      "version_major": 0,

+      "version_minor": 1

+    },

+    {

       "name": "TFM Core Test Service",

       "short_name": "TFM_Core_Test",

       "manifest": "test/test_services/tfm_core_test/manifest.yaml",