Test: Add test suite for Attestation Service

Initial test cases for Attestation Service prototype added.

Change-Id: I7e60a90d85a1f9299214d6ce1cf94af05b1236c8
Signed-off-by: Tamas Ban <tamas.ban@arm.com>
diff --git a/test/CMakeLists.inc b/test/CMakeLists.inc
index 97f3566..6c22af7 100644
--- a/test/CMakeLists.inc
+++ b/test/CMakeLists.inc
@@ -32,4 +32,5 @@
 include(${CMAKE_CURRENT_LIST_DIR}/suites/sst/CMakeLists.inc)
 include(${CMAKE_CURRENT_LIST_DIR}/suites/audit/CMakeLists.inc)
 include(${CMAKE_CURRENT_LIST_DIR}/suites/crypto/CMakeLists.inc)
+include(${CMAKE_CURRENT_LIST_DIR}/suites/attestation/CMakeLists.inc)
 include(${CMAKE_CURRENT_LIST_DIR}/test_services/CMakeLists.inc)
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index f3491ae..7198c64 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -50,6 +50,7 @@
 set(ENABLE_AUDIT_LOGGING_SERVICE_TESTS TRUE)
 set(ENABLE_CRYPTO_SERVICE_TESTS TRUE)
 set(ENABLE_INVERT_SERVICE_TESTS TRUE)
+set(ENABLE_ATTESTATION_SERVICE_TESTS TRUE)
 include(${CMAKE_CURRENT_LIST_DIR}/CMakeLists.inc)
 
 #Build the secure library
diff --git a/test/framework/non_secure_suites.c b/test/framework/non_secure_suites.c
index 7ba01f5..496dc4f 100644
--- a/test/framework/non_secure_suites.c
+++ b/test/framework/non_secure_suites.c
@@ -13,6 +13,7 @@
 #include "test/suites/sst/non_secure/sst_ns_tests.h"
 #include "test/suites/audit/non_secure/audit_ns_tests.h"
 #include "test/suites/crypto/non_secure/crypto_ns_tests.h"
+#include "test/suites/attestation/non_secure/attestation_ns_tests.h"
 #include "test/suites/invert/non_secure/invert_ns_tests.h"
 #include "test/suites/core/non_secure/core_ns_tests.h"
 
@@ -20,6 +21,8 @@
 #if TFM_LVL == 3
 #ifdef SERVICES_TEST_NS
     /* List test cases which compliant with level 3 isolation */
+    /* Non-secure initial attestation service test cases */
+    {&register_testsuite_ns_attestation_interface, 0, 0, 0},
 
 #ifdef TFM_PARTITION_TEST_CORE
     /* Non-secure invert test cases */
@@ -51,6 +54,9 @@
     /* Non-secure Crypto test cases */
     {&register_testsuite_ns_crypto_interface, 0, 0, 0},
 
+    /* Non-secure initial attestation service test cases */
+    {&register_testsuite_ns_attestation_interface, 0, 0, 0},
+
 #ifdef TFM_PARTITION_TEST_CORE
     /* Non-secure invert test cases */
     /* Note: since this is sample code, only run if test services are enabled */
diff --git a/test/framework/secure_suites.c b/test/framework/secure_suites.c
index cb92f79..1dde38d 100644
--- a/test/framework/secure_suites.c
+++ b/test/framework/secure_suites.c
@@ -12,6 +12,7 @@
 /* Service specific includes */
 #include "test/suites/sst/secure/sst_tests.h"
 #include "test/suites/audit/secure/audit_s_tests.h"
+#include "test/suites/attestation/secure/attestation_s_tests.h"
 #include "test/suites/invert/secure/invert_s_tests.h"
 #include "test/suites/crypto/secure/crypto_s_tests.h"
 
@@ -21,6 +22,8 @@
 #if TFM_LVL == 3
 #ifdef SERVICES_TEST_S
     /* List test cases which compliant with level 3 isolation */
+    /* Secure initial attestation service test cases */
+    {&register_testsuite_s_attestation_interface, 0, 0, 0},
 #endif /* SERVICES_TEST_S */
 
 #else /* TFM_LVL == 3 */
@@ -41,6 +44,9 @@
     /* Crypto test cases */
     {&register_testsuite_s_crypto_interface, 0, 0, 0},
 
+    /* Secure initial attestation service test cases */
+    {&register_testsuite_s_attestation_interface, 0, 0, 0},
+
 #ifdef TFM_PARTITION_TEST_CORE
     /* Secure invert test cases */
     /* Note: since this is sample code, only run if test services are enabled */
diff --git a/test/framework/test_framework.c b/test/framework/test_framework.c
index e991dd4..862c43f 100644
--- a/test/framework/test_framework.c
+++ b/test/framework/test_framework.c
@@ -26,8 +26,7 @@
         }
     }
 
-    printf("  TEST FAILED!");
-    printf("\r\n");
+    printf("  TEST FAILED!\r\n");
 }
 
 static void print_error(const char *err_msg)
diff --git a/test/suites/attestation/CMakeLists.inc b/test/suites/attestation/CMakeLists.inc
new file mode 100644
index 0000000..c503554
--- /dev/null
+++ b/test/suites/attestation/CMakeLists.inc
@@ -0,0 +1,36 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+#Definitions to compile the "secure attestation test" module.
+#This file assumes it will be included from a project specific cmakefile, and
+#will not create a library or executable.
+#Inputs:
+#	TFM_ROOT_DIR - root directory of the TF-M repo.
+#
+#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(ATTESTATION_TEST_DIR ${CMAKE_CURRENT_LIST_DIR})
+if(NOT DEFINED TFM_ROOT_DIR)
+	message(FATAL_ERROR "Please set TFM_ROOT_DIR before including this file.")
+endif()
+
+if (NOT DEFINED ENABLE_ATTESTATION_SERVICE_TESTS)
+	message(FATAL_ERROR "Incomplete build configuration: ENABLE_ATTESTATION_SERVICE_TESTS is undefined. ")
+elseif(ENABLE_ATTESTATION_SERVICE_TESTS)
+	list(APPEND ALL_SRC_C_S  "${ATTESTATION_TEST_DIR}/secure/attestation_s_interface_testsuite.c")
+	list(APPEND ALL_SRC_C_NS "${ATTESTATION_TEST_DIR}/non_secure/attestation_ns_interface_testsuite.c")
+
+	#Setting include directories
+	embedded_include_directories(PATH ${TFM_ROOT_DIR} ABSOLUTE)
+	embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE)
+endif()
diff --git a/test/suites/attestation/attestation_tests_common.h b/test/suites/attestation/attestation_tests_common.h
new file mode 100644
index 0000000..d9f03ff
--- /dev/null
+++ b/test/suites/attestation/attestation_tests_common.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __ATTESTATION_TESTS_COMMON_H__
+#define __ATTESTATION_TESTS_COMMON_H__
+
+#include "psa_initial_attestation_api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * \def TEST_TOKEN_SIZE
+ *
+ * \brief Size of token buffer in bytes.
+ */
+#define TEST_TOKEN_SIZE PSA_INITIAL_ATTEST_TOKEN_SIZE
+
+/*!
+ * \def TOO_SMALL_TOKEN_BUFFER
+ *
+ * \brief Smaller buffer size which is not big enough to store the created token
+ *        by attestation service.
+ */
+#define TOO_SMALL_TOKEN_BUFFER (16u)
+
+/*!
+ * \def TEST_CHALLENGE_OBJ_SIZE
+ *
+ * \brief Size of challenge object in bytes used for test.
+ */
+#define TEST_CHALLENGE_OBJ_SIZE (16u)
+
+/*!
+ * \def TOO_BIG_CHALLENGE_OBJECT
+ *
+ * \brief Size of challenge object that is bigger than it is allowed.
+ */
+#define TOO_BIG_CHALLENGE_OBJECT (PSA_INITIAL_ATTEST_MAX_CHALLENGE_SIZE + 1)
+
+/*!
+ * \def CHALLENGE_FOR_TEST
+ *
+ * \brief Fix value used as challenge object, because currently random number
+ *        generation is not supported on secure side.
+ */
+#define CHALLENGE_FOR_TEST    0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, \
+                              0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ATTESTATION_TESTS_COMMON_H__ */
diff --git a/test/suites/attestation/non_secure/attestation_ns_interface_testsuite.c b/test/suites/attestation/non_secure/attestation_ns_interface_testsuite.c
new file mode 100644
index 0000000..70f9a56
--- /dev/null
+++ b/test/suites/attestation/non_secure/attestation_ns_interface_testsuite.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "attestation_ns_tests.h"
+#include "psa_initial_attestation_api.h"
+#include "secure_fw/services/initial_attestation/attestation.h"
+#include "../attestation_tests_common.h"
+#include "bl2/include/tfm_boot_status.h"
+#include "secure_utilities.h"
+#include "platform/include/tfm_plat_device_id.h"
+#include "platform/include/tfm_plat_boot_seed.h"
+#include "tfm_api.h"
+#include <string.h>
+#include <stdlib.h>
+
+static uint8_t token_buffer[TEST_TOKEN_SIZE];
+static uint8_t challenge_buffer[TEST_CHALLENGE_OBJ_SIZE];
+
+/* Define test suite for attestation service tests */
+/* List of tests */
+static void tfm_attest_test_1001(struct test_result_t *ret);
+static void tfm_attest_test_1002(struct test_result_t *ret);
+
+static struct test_t attestation_interface_tests[] = {
+    {&tfm_attest_test_1001, "TFM_ATTEST_TEST_1001",
+     "Get attestation token and check claims", {0} },
+    {&tfm_attest_test_1002, "TFM_ATTEST_TEST_1002",
+     "Negative test cases for initial attestation service", {0} },
+};
+
+/*!
+ * \brief Static function to iterates over the TLV fields in the attestation
+ *        token and look for the location of the specified TLV type.
+ *
+ * \param[in]  minor_type The identifier of the TLV data entry
+ * \param[in]  token_buf  Pointer to the buffer which stores the token
+ * \param[out] tlv_ptr    Pointer to the TLV data entry
+ *
+ * \return Returns 0 on success. Otherwise, 1.
+ */
+static uint32_t attest_get_tlv_data(uint8_t   minor_type,
+                                    uint8_t  *token_buf,
+                                    uint8_t **tlv_data_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 *)token_buf;
+    if (tlv_header->tlv_magic != SHARED_DATA_TLV_INFO_MAGIC) {
+        return 1u;
+    }
+
+    /* Get the boundaries of TLV section */
+    tlv_end  = (uintptr_t)token_buf + tlv_header->tlv_tot_len;
+    tlv_curr = (uintptr_t)token_buf + 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_data_ptr = (uint8_t *)tlv_entry +
+                            SHARED_DATA_ENTRY_HEADER_SIZE;
+            return 0;
+        }
+    }
+
+    return 1u;
+}
+
+/*!
+ * \brief Static function to generate a random byte stream. It is used as a
+ *        challenge object to test attestation service.
+ *
+ * \param[in]  bytes The size of the random bytes to generate
+ * \param[out] buf   Pointer to the buffer to store random bytes
+ *
+ */
+static void generate_challenge(uint32_t bytes, uint8_t *buf)
+{
+    uint32_t random_value;
+    uint8_t  *p_buf = buf;
+
+    while (bytes) {
+        /* FixMe: use a valid source to generate random values */
+        random_value = rand();
+
+        if (bytes >= sizeof(random_value)) {
+            tfm_memcpy(p_buf, &random_value, sizeof(random_value));
+            bytes -= sizeof(random_value);
+            p_buf += sizeof(random_value);
+        } else {
+            tfm_memcpy(p_buf, &random_value, bytes);
+            bytes = 0;
+        }
+    }
+}
+
+void
+register_testsuite_ns_attestation_interface(struct test_suite_t *p_test_suite)
+{
+    uint32_t list_size;
+
+    list_size = (sizeof(attestation_interface_tests) /
+                 sizeof(attestation_interface_tests[0]));
+
+    set_testsuite("Initial Attestation Service secure interface tests"
+                  "(TFM_ATTEST_TEST_1XXX)",
+                  attestation_interface_tests, list_size, p_test_suite);
+}
+
+/*!
+ * \brief Positive tests for initial attestation service
+ *
+ *      - Calling Initial Attestation service to get token
+ *      - Check the existence of the fixed set of claims:
+ *          - Boot status
+ *          - Boot seed
+ *          - Device ID
+ *          - Challenge object
+ *          - Caller ID
+ *      - Comparing value of claims:
+ *          - Boot seed: Compare boot seed from subsequent calls
+ *          - Device ID: Currently compare with fix value
+ *          - Challenge: Compare with input object
+ *          - Caller ID: Check whether is it in non-secure range
+ */
+static void tfm_attest_test_1001(struct test_result_t *ret)
+{
+    enum psa_attest_err_t err;
+    uint32_t token_size = TEST_TOKEN_SIZE;
+    uint8_t boot_seed_buffer[BOOT_SEED_SIZE];
+    uint8_t device_id_buffer[DEVICE_ID_MAX_SIZE];
+    uint8_t *tlv_data_ptr;
+    int32_t device_id_size;
+    int32_t caller_id;
+    uint32_t res;
+
+    generate_challenge(TEST_CHALLENGE_OBJ_SIZE, challenge_buffer);
+
+    /* Get attestation token */
+    err = psa_initial_attest_get_token(challenge_buffer,
+                                       TEST_CHALLENGE_OBJ_SIZE,
+                                       token_buffer,
+                                       &token_size);
+    if (err != PSA_ATTEST_ERR_SUCCESS) {
+        TEST_FAIL("Get token failed");
+        return;
+    }
+
+    /* Check IMAGE HASH
+     * The image hash cannot be retrieved from image manifest if code runs in
+     * NS context, because the image header resides in S memory area.
+     */
+    res = attest_get_tlv_data(TLV_MINOR_IAS_S_NS_SHA256, token_buffer,
+                              &tlv_data_ptr);
+    if (res != 0) {
+        TEST_FAIL("Missing claim: TLV_MINOR_IAS_S_NS_SHA256");
+        return;
+    }
+
+
+    /* Check DEVICE_ID */
+    res = attest_get_tlv_data(TLV_MINOR_IAS_DEVICE_ID, token_buffer,
+                              &tlv_data_ptr);
+    if (res != 0) {
+        TEST_FAIL("Missing claim: TLV_MINOR_IAS_DEVICE_ID");
+        return;
+    }
+
+    /* Get device ID directly */
+    device_id_size = tfm_plat_get_device_id(sizeof(device_id_buffer),
+                                            device_id_buffer);
+    if (device_id_size < 0) {
+        TEST_FAIL("Device ID unavailable");
+        return;
+    }
+
+    /* Compare the value from token and from direct call */
+    if (tfm_memcmp(tlv_data_ptr, device_id_buffer, device_id_size) != 0) {
+        TEST_FAIL("Faulty claim: TLV_MINOR_IAS_DEVICE_ID");
+        return;
+    }
+
+    /* Check CHALLENGE */
+    res = attest_get_tlv_data(TLV_MINOR_IAS_CHALLENGE, token_buffer,
+                              &tlv_data_ptr);
+    if (res != 0) {
+        TEST_FAIL("Missing claim: TLV_MINOR_IAS_CHALLENGE");
+        return;
+    }
+    if (tfm_memcmp(tlv_data_ptr, challenge_buffer,
+                   TEST_CHALLENGE_OBJ_SIZE) != 0) {
+        TEST_FAIL("Faulty claim: TLV_MINOR_IAS_CHALLENGE");
+        return;
+    }
+
+    /* Check CALLER ID */
+    res = attest_get_tlv_data(TLV_MINOR_IAS_CALLER_ID, token_buffer,
+                              &tlv_data_ptr);
+    if (res != 0) {
+        TEST_FAIL("Missing claim: TLV_MINOR_IAS_CALLER_ID");
+        return;
+    }
+
+    caller_id = *((int32_t *)tlv_data_ptr);
+    if (!TFM_CLIENT_ID_IS_NS(caller_id)) {
+        TEST_FAIL("Faulty claim: TLV_MINOR_IAS_CALLER_ID");
+        return;
+    }
+
+    /* Check BOOT_SEED */
+    res = attest_get_tlv_data(TLV_MINOR_IAS_BOOT_SEED, token_buffer,
+                              &tlv_data_ptr);
+    if (res != 0) {
+        TEST_FAIL("Missing claim: TLV_MINOR_IAS_BOOT_SEED");
+        return;
+    }
+
+    /* Store received boot seed. */
+    tfm_memcpy(boot_seed_buffer, tlv_data_ptr, BOOT_SEED_SIZE);
+
+    /* Call attest API again and compare the value of boot seed on subsequent
+     * calls. They must be equal within the same boot cycle.
+     */
+    err = psa_initial_attest_get_token(challenge_buffer,
+                                       TEST_CHALLENGE_OBJ_SIZE,
+                                       token_buffer,
+                                       &token_size);
+    if (err != PSA_ATTEST_ERR_SUCCESS) {
+        TEST_FAIL("Get token failed");
+        return;
+    }
+
+    /* Get boot seed again */
+    res = attest_get_tlv_data(TLV_MINOR_IAS_BOOT_SEED, token_buffer,
+                              &tlv_data_ptr);
+    if (res != 0) {
+        TEST_FAIL("Missing claim: TLV_MINOR_IAS_BOOT_SEED");
+        return;
+    }
+
+    /*Compare the values of boot seed on subsequent calls */
+    if (tfm_memcmp(tlv_data_ptr, boot_seed_buffer, BOOT_SEED_SIZE) != 0) {
+        TEST_FAIL("Faulty claim: TLV_MINOR_IAS_BOOT_SEED");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/*!
+ * \brief Negative tests for initial attestation service
+ *
+ *    - Calling initial attestation service with bigger challenge object than
+ *      allowed.
+ *    - Calling initial attesttion service with smaller buffer size than the
+ *      expected size of the token.
+ */
+static void tfm_attest_test_1002(struct test_result_t *ret)
+{
+    enum psa_attest_err_t err;
+    uint32_t token_size = TEST_TOKEN_SIZE;
+
+    /* Call with with bigger challenge object than allowed */
+    err = psa_initial_attest_get_token(challenge_buffer,
+                                       TOO_BIG_CHALLENGE_OBJECT,
+                                       token_buffer,
+                                       &token_size);
+
+    if (err != PSA_ATTEST_ERR_INVALID_INPUT) {
+        TEST_FAIL("Attestation should fail with too big challenge object");
+        return;
+    }
+
+    /* Call with smaller buffer size than size of test token */
+    token_size = TOO_SMALL_TOKEN_BUFFER;
+    err = psa_initial_attest_get_token(challenge_buffer,
+                                       TEST_CHALLENGE_OBJ_SIZE,
+                                       token_buffer,
+                                       &token_size);
+
+    if (err == PSA_ATTEST_ERR_SUCCESS) {
+        TEST_FAIL("Attestation should fail with too small token buffer");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
diff --git a/test/suites/attestation/non_secure/attestation_ns_tests.h b/test/suites/attestation/non_secure/attestation_ns_tests.h
new file mode 100644
index 0000000..c2d5a3e
--- /dev/null
+++ b/test/suites/attestation/non_secure/attestation_ns_tests.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __ATTESTATION_NS_TESTS_H__
+#define __ATTESTATION_NS_TESTS_H__
+
+#include "test/framework/test_framework.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Register testsuite for the initial attestation service.
+ *
+ * \param[in] p_test_suite The test suite to be executed.
+ */
+void
+register_testsuite_ns_attestation_interface(struct test_suite_t *p_test_suite);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ATTESTATION_NS_TESTS_H__ */
diff --git a/test/suites/attestation/secure/attestation_s_interface_testsuite.c b/test/suites/attestation/secure/attestation_s_interface_testsuite.c
new file mode 100644
index 0000000..0f15157
--- /dev/null
+++ b/test/suites/attestation/secure/attestation_s_interface_testsuite.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "attestation_s_tests.h"
+#include "psa_initial_attestation_api.h"
+#include "secure_fw/services/initial_attestation/attestation.h"
+#include "../attestation_tests_common.h"
+#include "bl2/include/tfm_boot_status.h"
+#include "bl2/ext/mcuboot/bootutil/include/bootutil/image.h"
+#include "secure_utilities.h"
+#include "platform/include/tfm_plat_device_id.h"
+#include "platform/include/tfm_plat_boot_seed.h"
+#include "flash_layout.h"
+#include "spm_partition_defs.h"
+#include <string.h>
+#include <stdlib.h>
+
+static uint8_t token_buffer[TEST_TOKEN_SIZE];
+static const uint8_t challenge_buffer[TEST_CHALLENGE_OBJ_SIZE] =
+                                     {CHALLENGE_FOR_TEST};
+
+/* Define test suite for attestation service tests */
+/* List of tests */
+static void tfm_attest_test_1001(struct test_result_t *ret);
+static void tfm_attest_test_1002(struct test_result_t *ret);
+
+static struct test_t attestation_interface_tests[] = {
+    {&tfm_attest_test_1001, "TFM_ATTEST_TEST_1001",
+     "Get attestation token and check claims", {0} },
+    {&tfm_attest_test_1002, "TFM_ATTEST_TEST_1002",
+     "Negative test cases for initial attestation service", {0} },
+};
+
+/*!
+ * \brief Static function to iterates over the TLV fields in the attestation
+ *        token and look for the location of the specified TLV type.
+ *
+ * \param[in]  minor_type The identifier of the TLV data entry
+ * \param[in]  token_buf  Pointer to the buffer which stores the token
+ * \param[out] tlv_ptr    Pointer to the TLV data entry
+ *
+ * \return Returns 0 on success. Otherwise, 1.
+ */
+static uint32_t attest_get_tlv_data(uint8_t   minor_type,
+                                    uint8_t  *token_buf,
+                                    uint8_t **tlv_data_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 *)token_buf;
+    if (tlv_header->tlv_magic != SHARED_DATA_TLV_INFO_MAGIC) {
+        return 1u;
+    }
+
+    /* Get the boundaries of TLV section */
+    tlv_end  = (uintptr_t)token_buf + tlv_header->tlv_tot_len;
+    tlv_curr = (uintptr_t)token_buf + 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_data_ptr = (uint8_t *)tlv_entry +
+                            SHARED_DATA_ENTRY_HEADER_SIZE;
+            return 0;
+        }
+    }
+
+    return 1u;
+}
+
+/*!
+ * \brief Get image hash from the image manifest.
+ *
+ * This function iterates over the image manifest section to look for
+ * the image's hash value. This manifest section is also TLV encoded.
+ * This function can be called if TFM_LVL == 1, to avoid MemMange fault, which
+ * is triggered by enabled MPU at level 3 isolation.
+ *
+ * Note 1: The access of manifest section must be done with NS alias to avoid
+ *         MPC fault, because manifest section is configured to be NS memory.
+ *
+ * Note 2: This function assumes that active image resides in slot 0 or in RAM
+ *         pointing by LOAD_ADDRESS macro. But these assumptions might not be
+ *         valid if MCUBOOT_NO_SWAP mode is used.
+ *
+ * \param[out] Pointer to the location of image hash value in the image
+ *             manifest section.
+ *
+ * \return Returns 0 on success. Otherwise, 1.
+ */
+#if TFM_LVL == 1
+/* FixMe: This offset should be calculated per device */
+#define USUAL_S_NS_ALIAS_OFFSET 0x10000000u
+static uint32_t attest_get_s_ns_sha256(uint8_t **hash)
+{
+    struct image_header *image_header;
+    struct image_tlv_info *tlv_info;
+    struct image_tlv *tlv_entry;
+    uint32_t image_header_address;
+    uint8_t *off;
+    uint8_t *end;
+
+#ifdef LOAD_ADDRESS
+    image_header_address = LOAD_ADDRESS;
+#else
+    image_header_address = (FLASH_BASE_ADDRESS + FLASH_AREA_IMAGE_0_OFFSET);
+#endif
+    image_header = (struct image_header *)image_header_address;
+    /* Calculates NS memory alias of manifest section */
+    tlv_info     = (struct image_tlv_info *)(image_header_address +
+                                             image_header->ih_hdr_size +
+                                             image_header->ih_img_size -
+                                             USUAL_S_NS_ALIAS_OFFSET);
+
+    end = (uint8_t *)tlv_info + tlv_info->it_tlv_tot;
+    off = (uint8_t *)tlv_info + sizeof(struct image_tlv_info);
+
+    for (; off < end; off += sizeof(struct image_tlv) + tlv_entry->it_len) {
+        tlv_entry = (struct image_tlv *)(off);
+        if (tlv_entry->it_type == IMAGE_TLV_SHA256) {
+                *hash = (uint8_t *)tlv_entry + sizeof(struct image_tlv);
+                return 0;
+        }
+    }
+
+    return 1u;
+}
+#endif /* TFM_LVL == 1 */
+
+void
+register_testsuite_s_attestation_interface(struct test_suite_t *p_test_suite)
+{
+    uint32_t list_size;
+
+    list_size = (sizeof(attestation_interface_tests) /
+                 sizeof(attestation_interface_tests[0]));
+
+    set_testsuite("Initial Attestation Service secure interface tests"
+                  "(TFM_ATTEST_TEST_1XXX)",
+                  attestation_interface_tests, list_size, p_test_suite);
+}
+
+/*!
+ * \brief Positive tests for initial attestation service
+ *
+ *      - Calling Initial Attestation service to get token
+ *      - Check the existence of the fixed set of claims:
+ *          - Boot status
+ *          - Boot seed
+ *          - Device ID
+ *          - Challenge object
+ *          - Caller ID
+ *      - Comparing value of claims:
+ *          - Boot status: Get boot status from token and from image manifest
+ *                         and compare them
+ *          - Boot seed: Compare boot seed from subsequent calls
+ *          - Device ID: Currently compare with fix value
+ *          - Challenge: Compare with input object
+ *          - Caller ID: Check whether is it in non-secure range
+ */
+static void tfm_attest_test_1001(struct test_result_t *ret)
+{
+    enum psa_attest_err_t err;
+    uint32_t token_size = TEST_TOKEN_SIZE;
+    uint8_t boot_seed_buffer[BOOT_SEED_SIZE];
+    uint8_t device_id_buffer[DEVICE_ID_MAX_SIZE];
+    uint8_t *tlv_data_ptr;
+    int32_t device_id_size;
+    int32_t caller_id;
+    uint32_t res;
+
+    /* Get attestation token
+     * FixMe: Hard coded challenge is used, because currently there is no
+     *        support for random source(RNG, rand(), etc.) on secure side.
+     */
+    err = psa_initial_attest_get_token(challenge_buffer,
+                                       TEST_CHALLENGE_OBJ_SIZE,
+                                       token_buffer,
+                                       &token_size);
+    if (err != PSA_ATTEST_ERR_SUCCESS) {
+        TEST_FAIL("Get token failed");
+        return;
+    }
+
+    /* Check IMAGE HASH */
+    res = attest_get_tlv_data(TLV_MINOR_IAS_S_NS_SHA256, token_buffer,
+                              &tlv_data_ptr);
+    if (res != 0) {
+        TEST_FAIL("Missing claim: TLV_MINOR_IAS_S_NS_SHA256");
+        return;
+    }
+    /* Extract image hash from manifest data and compare with claim.
+     * This can be done only from secure side if S_MPU is not enabled.
+     */
+#if TFM_LVL == 1
+    uint8_t *hash_from_image;
+    res = attest_get_s_ns_sha256(&hash_from_image);
+    if (res == 0) {
+        if (tfm_memcmp(tlv_data_ptr, hash_from_image, 32) != 0) {
+            TEST_FAIL("Faulty claim: TLV_MINOR_IAS_S_NS_SHA256");
+            return;
+        }
+    }
+#endif /* TFM_LVL == 1 */
+
+    /* Check DEVICE_ID */
+    res = attest_get_tlv_data(TLV_MINOR_IAS_DEVICE_ID, token_buffer,
+                              &tlv_data_ptr);
+    if (res != 0) {
+        TEST_FAIL("Missing claim: TLV_MINOR_IAS_DEVICE_ID");
+        return;
+    }
+
+    /* Get device ID directly */
+    device_id_size = tfm_plat_get_device_id(sizeof(device_id_buffer),
+                                            device_id_buffer);
+    if (device_id_size < 0) {
+        TEST_FAIL("Device ID unavailable");
+        return;
+    }
+
+    /* Compare the value from token and from direct call */
+    if (tfm_memcmp(tlv_data_ptr, device_id_buffer, device_id_size) != 0) {
+        TEST_FAIL("Faulty claim: TLV_MINOR_IAS_DEVICE_ID");
+        return;
+    }
+
+    /* Check CHALLENGE */
+    res = attest_get_tlv_data(TLV_MINOR_IAS_CHALLENGE, token_buffer,
+                              &tlv_data_ptr);
+    if (res != 0) {
+        TEST_FAIL("Missing claim: TLV_MINOR_IAS_CHALLENGE");
+        return;
+    }
+    if (tfm_memcmp(tlv_data_ptr, challenge_buffer,
+                   TEST_CHALLENGE_OBJ_SIZE) != 0) {
+        TEST_FAIL("Faulty claim: TLV_MINOR_IAS_CHALLENGE");
+        return;
+    }
+
+    /* Check CALLER ID */
+    res = attest_get_tlv_data(TLV_MINOR_IAS_CALLER_ID, token_buffer,
+                              &tlv_data_ptr);
+    if (res != 0) {
+        TEST_FAIL("Missing claim: TLV_MINOR_IAS_CALLER_ID");
+        return;
+    }
+
+    caller_id = *((int32_t *)tlv_data_ptr);
+    if (caller_id < TFM_SP_BASE) {
+        TEST_FAIL("Faulty claim: TLV_MINOR_IAS_CALLER_ID");
+        return;
+    }
+
+    /* Check BOOT_SEED */
+    res = attest_get_tlv_data(TLV_MINOR_IAS_BOOT_SEED, token_buffer,
+                              &tlv_data_ptr);
+    if (res != 0) {
+        TEST_FAIL("Missing claim: TLV_MINOR_IAS_BOOT_SEED");
+        return;
+    }
+
+    /* Store received boot seed. */
+    tfm_memcpy(boot_seed_buffer, tlv_data_ptr, BOOT_SEED_SIZE);
+
+    /* Call attest API again and compare the value of boot seed on subsequent
+     * calls. They must be equal within the same boot cycle.
+     */
+    err = psa_initial_attest_get_token(challenge_buffer,
+                                       TEST_CHALLENGE_OBJ_SIZE,
+                                       token_buffer,
+                                       &token_size);
+    if (err != PSA_ATTEST_ERR_SUCCESS) {
+        TEST_FAIL("Get token failed");
+        return;
+    }
+
+    /* Get boot seed again */
+    res = attest_get_tlv_data(TLV_MINOR_IAS_BOOT_SEED, token_buffer,
+                              &tlv_data_ptr);
+    if (res != 0) {
+        TEST_FAIL("Missing claim: TLV_MINOR_IAS_BOOT_SEED");
+        return;
+    }
+
+    /*Compare the values of boot seed on subsequent calls */
+    if (tfm_memcmp(tlv_data_ptr, boot_seed_buffer, BOOT_SEED_SIZE) != 0) {
+        TEST_FAIL("Faulty claim: TLV_MINOR_IAS_BOOT_SEED");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/*!
+ * \brief Negative tests for initial attestation service
+ *
+ *    - Calling initial attestation service with smaller buffer size than the
+ *      expected size of the token.
+ */
+static void tfm_attest_test_1002(struct test_result_t *ret)
+{
+    enum psa_attest_err_t err;
+    uint32_t token_size = TEST_TOKEN_SIZE;
+
+    /* Call with smaller buffer size than size of test token */
+    token_size = TOO_SMALL_TOKEN_BUFFER;
+    err = psa_initial_attest_get_token(challenge_buffer,
+                                       TEST_CHALLENGE_OBJ_SIZE,
+                                       token_buffer,
+                                       &token_size);
+
+    if (err != PSA_ATTEST_ERR_TOKEN_BUFFER_OVERFLOW) {
+        TEST_FAIL("Attestation should fail with small buffer");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
diff --git a/test/suites/attestation/secure/attestation_s_tests.h b/test/suites/attestation/secure/attestation_s_tests.h
new file mode 100644
index 0000000..f240c94
--- /dev/null
+++ b/test/suites/attestation/secure/attestation_s_tests.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __ATTESTATION_S_TESTS_H__
+#define __ATTESTATION_S_TESTS_H__
+
+#include "test/framework/test_framework.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Register testsuite for the initial attestation service.
+ *
+ * \param[in] p_test_suite The test suite to be executed.
+ */
+void
+register_testsuite_s_attestation_interface(struct test_suite_t *p_test_suite);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ATTESTATION_S_TESTS_H__ */
diff --git a/test/test_services/CMakeLists.inc b/test/test_services/CMakeLists.inc
index 7f25834..42c309c 100644
--- a/test/test_services/CMakeLists.inc
+++ b/test/test_services/CMakeLists.inc
@@ -77,7 +77,7 @@
 set(BUILD_UART_STDOUT Off)
 set(BUILD_FLASH Off)
 set(BUILD_BOOT_SEED Off)
-set(BUILD_DEVICE_ID Off)
+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})
diff --git a/test/test_services/tfm_secure_client_service/manifest.yaml b/test/test_services/tfm_secure_client_service/manifest.yaml
index 7833eba..9ab5b62 100644
--- a/test/test_services/tfm_secure_client_service/manifest.yaml
+++ b/test/test_services/tfm_secure_client_service/manifest.yaml
@@ -47,6 +47,7 @@
       "*arm_uart_drv.*",   # MPS2-AN521, MPS2-AN519
       "*uart_pl011_drv.*", # Musca-A1, Musca-B1
       "*secure_suites.*",
+      "*attestation_s_interface_testsuite.*"
     ]
   }
 }