Test: test framework and test suites

 -- Test framework
 -- Test secure service
 -- TFM Core secure/non-secure test suites
 -- SST secure/non-secure test suites

Change-Id: I5868d9a65a740b984748d975a3a5bd486cbfafc4
Signed-off-by: Abhishek Pandit <abhishek.pandit@arm.com>
Co-Authored-By: Mate Toth-pal <mate.toth-pal@arm.com>
Co-Authored-By: Antonio de Angelis <antonio.deangelis@arm.com>
Co-Authored-By: Miklos Balint <miklos.balint@arm.com>
Co-Authored-By: Jamie Fox <jamie.fox@arm.com>
Co-Authored-By: Ashutosh Singh <ashutosh.singh@arm.com>
diff --git a/test/framework/helpers.c b/test/framework/helpers.c
new file mode 100755
index 0000000..f6d5df7
--- /dev/null
+++ b/test/framework/helpers.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "helpers.h"
+
+#include <stdio.h>
+
+const char *sst_err_to_str(enum tfm_sst_err_t err)
+{
+    switch (err) {
+    case TFM_SST_ERR_SUCCESS:
+        return "TFM_SST_ERR_SUCCESS";
+    case TFM_SST_ERR_ASSET_NOT_PREPARED:
+        return "TFM_SST_ERR_ASSET_NOT_PREPARED";
+    case TFM_SST_ERR_ASSET_NOT_FOUND:
+        return "TFM_SST_ERR_ASSET_NOT_FOUND";
+    case TFM_SST_ERR_PARAM_ERROR:
+        return "TFM_SST_ERR_PARAM_ERROR";
+    case TFM_SST_ERR_INVALID_HANDLE:
+        return "TFM_SST_ERR_INVALID_HANDLE";
+    case TFM_SST_ERR_STORAGE_SYSTEM_FULL:
+        return "TFM_SST_ERR_STORAGE_SYSTEM_FULL";
+    case TFM_SST_ERR_SYSTEM_ERROR:
+        return "TFM_SST_ERR_SYSTEM_ERROR";
+    case TFM_SST_ERR_FORCE_INT_SIZE:
+        return "TFM_SST_ERR_FORCE_INT_SIZE";
+    /* default:  The default is not defined intentionally to force the
+     *           compiler to check that all the enumeration values are
+     *           covered in the switch.
+     */
+    }
+}
+
+const char *asset_perms_to_str(uint8_t permissions)
+{
+    switch (permissions) {
+    case 0:
+        return "No permissions";
+    case 1:
+        return "SECURE_ASSET_REFERENCE";
+    case 2:
+        return "SECURE_ASSET_WRITE";
+    case 3:
+        return "SECURE_ASSET_REFERENCE | SECURE_ASSET_WRITE";
+    case 4:
+        return "SECURE_ASSET_READ";
+    case 5:
+        return "SECURE_ASSET_REFERENCE | SECURE_ASSET_READ";
+    case 6:
+        return "SECURE_ASSET_WRITE | SECURE_ASSET_READ";
+    case 7:
+        return "SECURE_ASSET_REFERENCE | SECURE_ASSET_WRITE | "
+               "SECURE_ASSET_READ";
+    default:
+        return "Unknown permissions";
+    }
+}
+
+void printf_set_color(enum serial_color_t color_id)
+{
+    printf("\33[3%dm", color_id);
+}
diff --git a/test/framework/helpers.h b/test/framework/helpers.h
new file mode 100755
index 0000000..517c4b0
--- /dev/null
+++ b/test/framework/helpers.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __HELPERS_H__
+#define __HELPERS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include "tfm_sst_defs.h"
+#include "secure_fw/services/secure_storage/sst_asset_management.h"
+#include "test_framework.h"
+
+enum serial_color_t {
+    BLACK = 0,
+    RED = 1,
+    GREEN = 2,
+    YELLOW = 3,
+    BLUE = 4,
+    MAGENDA = 5,
+    CYAN = 6,
+    WHITE = 7,
+};
+
+/**
+ * \brief Translates tfm_sst_err_t into a string.
+ *
+ * \param[in] err  tfm_sst_err_t error value.
+ *
+ * \return tfm_sst_err_t as string.
+ */
+const char *sst_err_to_str(enum tfm_sst_err_t err);
+
+/**
+ * \brief Translates asset permissions into a string.
+ *
+ * \param[in] permissions  Asset permissions value.
+ *
+ * \return asset permissions as string.
+ */
+const char *asset_perms_to_str(uint8_t permissions);
+
+/**
+ * \brief Sets the the text color in the serial port.
+ *
+ * \param[in] color_id  Serial foreground color.
+ *
+ * \return 0 if the message is send successfully, 1 otherwise.
+ */
+void printf_set_color(enum serial_color_t color_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HELPERS_H__ */
diff --git a/test/framework/integ_test.h b/test/framework/integ_test.h
new file mode 100644
index 0000000..d00fa39
--- /dev/null
+++ b/test/framework/integ_test.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __INTEG_TEST_H__
+#define __INTEG_TEST_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Executes integration tests.
+ */
+void start_integ_test(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INTEG_TEST_H__ */
diff --git a/test/framework/integ_test_helper.c b/test/framework/integ_test_helper.c
new file mode 100644
index 0000000..264b197
--- /dev/null
+++ b/test/framework/integ_test_helper.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdio.h>
+
+#include "test_framework.h"
+#include "integ_test_helper.h"
+
+void integ_test(const char *suite_type,
+                struct test_suite_t test_suites[],
+                uint32_t test_suite_cnt)
+{
+    uint32_t i;
+
+    printf_set_color(YELLOW);
+    printf("\r\n#### Execute test suites for the %s area ####\r\n", suite_type);
+
+    /* Executes test suites */
+    for (i = 0; i < test_suite_cnt; i++) {
+        if (run_testsuite(&test_suites[i]) != TEST_SUITE_ERR_NO_ERROR) {
+            /* End function execution */
+            return;
+        }
+    }
+
+    /* Prints test suites summary */
+    printf_set_color(YELLOW);
+    printf("\r\n*** %s test suites summary ***\r\n", suite_type);
+    for (i = 0; i < test_suite_cnt; i++) {
+        printf_set_color(WHITE);
+        printf("Test suite '%s' has ", test_suites[i].name);
+        if (test_suites[i].val == TEST_PASSED) {
+            printf_set_color(GREEN);
+            printf(" PASSED");
+        } else {
+            printf_set_color(RED);
+            printf(" FAILED");
+        }
+        printf("\r\n");
+    }
+
+    printf_set_color(YELLOW);
+    printf("\r\n*** End of %s test suites ***\r\n", suite_type);
+}
diff --git a/test/framework/integ_test_helper.h b/test/framework/integ_test_helper.h
new file mode 100644
index 0000000..cfe7ace
--- /dev/null
+++ b/test/framework/integ_test_helper.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __INTEG_TEST_HELPER_H__
+#define __INTEG_TEST_HELPER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "test_framework.h"
+
+/**
+ * \brief Executes integration test suites provided in the parameters.
+ *
+ * \param[in] suite_type      A string containing the type of the suite
+ *                            (used for printing).
+ * \param[in] test_suites     The suites to be executed.
+ * \param[in] test_suite_cnt  The number of test suites to be executed.
+ */
+void integ_test(const char *suite_type,
+                struct test_suite_t test_suites[],
+                uint32_t test_suite_cnt);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INTEG_TEST_HELPER_H__ */
diff --git a/test/framework/non_secure_suites.c b/test/framework/non_secure_suites.c
new file mode 100644
index 0000000..b14c685
--- /dev/null
+++ b/test/framework/non_secure_suites.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "integ_test.h"
+#include "integ_test_helper.h"
+#include "test_framework.h"
+
+/* Service specific includes */
+#include "test/suites/sst/non_secure/sst_ns_tests.h"
+#include "test/suites/invert/non_secure/invert_ns_tests.h"
+#include "test/suites/core/non_secure/core_ns_tests.h"
+
+static struct test_suite_t test_suites[] = {
+#ifdef SERVICES_TEST_NS
+    /* Non-secure SST test cases */
+    {&register_testsuite_ns_sst_interface, 0, 0, 0},
+
+#ifdef CORE_TEST_SERVICES
+    /* Non-secure invert test cases */
+    /* Note: since this is sample code, only run if test services are enabled */
+    {&register_testsuite_ns_invert_interface, 0, 0, 0},
+#endif
+#endif
+
+#ifdef CORE_TEST_POSITIVE
+    /* Non-secure core test cases */
+    {&register_testsuite_ns_core_positive, 0, 0, 0},
+#endif
+
+#ifdef CORE_TEST_INTERACTIVE
+    /* Non-secure interactive test cases */
+    {&register_testsuite_ns_core_interactive, 0, 0, 0},
+#endif
+};
+
+void start_integ_test(void)
+{
+    integ_test("Non-secure", test_suites,
+               sizeof(test_suites)/sizeof(test_suites[0]));
+}
diff --git a/test/framework/secure_suites.c b/test/framework/secure_suites.c
new file mode 100644
index 0000000..1b5360c
--- /dev/null
+++ b/test/framework/secure_suites.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "integ_test.h"
+#include "integ_test_helper.h"
+#include "test_framework.h"
+
+/* Service specific includes */
+#include "test/suites/sst/secure/sst_tests.h"
+#include "test/suites/invert/secure/invert_s_tests.h"
+#include "secure_fw/services/secure_storage/sst_core_interface.h"
+
+static struct test_suite_t test_suites[] = {
+#ifdef SERVICES_TEST_S
+    /* Secure SST test cases */
+    {&register_testsuite_s_sst_sec_interface, 0, 0, 0},
+    {&register_testsuite_s_sst_reliability, 0, 0, 0},
+
+    /* FIXME: this test suite needs to be refactored to accomodate it to
+     *        use only secure application ID.
+     *
+     * {&register_testsuite_s_sst_interface, 0, 0, 0},
+     */
+
+#ifdef CORE_TEST_SERVICES
+    /* Secure invert test cases */
+    /* Note: since this is sample code, only run if test services are enabled */
+    {&register_testsuite_s_invert_interface, 0, 0, 0},
+#endif
+#endif /* SERVICES_TEST_S */
+};
+
+static void setup_integ_test(void)
+{
+    /* Left empty intentionally, currently implemented
+     * test suites require no setup
+     */
+}
+
+static void tear_down_integ_test(void)
+{
+    /* Leave the SST area clean after execute the tests */
+    sst_object_wipe_all();
+    sst_object_prepare();
+}
+
+void start_integ_test(void)
+{
+    setup_integ_test();
+    integ_test("Secure",
+               test_suites,
+               sizeof(test_suites)/sizeof(test_suites[0]));
+    tear_down_integ_test();
+}
diff --git a/test/framework/test_framework.c b/test/framework/test_framework.c
new file mode 100644
index 0000000..fcb7451
--- /dev/null
+++ b/test/framework/test_framework.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "test_framework.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "helpers.h"
+
+static void test_failed(const struct test_result_t *ret)
+{
+    printf_set_color(RED);
+    if (ret->info_msg != 0) {
+        printf("  %s", ret->info_msg);
+        if (ret->filename != 0) {
+            printf(" (Failed at %s:%d)\r\n", ret->filename, ret->line);
+        }
+    } else {
+        if (ret->filename != 0) {
+            printf("  Failed at %s:%d\r\n", ret->filename, ret->line);
+        }
+    }
+
+    printf("  TEST FAILED!");
+    printf("\r\n");
+}
+
+static void print_error(const char *err_msg)
+{
+    printf_set_color(RED);
+    printf("Error ( %s )\r\n", err_msg);
+}
+
+const char *test_err_to_str(enum test_suite_err_t err)
+{
+    switch (err) {
+    case TEST_SUITE_ERR_NO_ERROR:
+        return "TEST_SUITE_ERR_NO_ERROR";
+    case TEST_SUITE_ERR_INVALID_DATA:
+        return "TEST_SUITE_ERR_INVALID_DATA";
+    case TEST_SUITE_ERR_INVALID_TEST_DATA:
+        return "TEST_SUITE_ERR_INVALID_TEST_DATA";
+    case TEST_SUITE_ERR_TEST_FAILED:
+        return "TEST_SUITE_ERR_TEST_FAILED";
+    /* default:  The default is not defined intentionally to force the
+     *           compiler to check that all the enumeration values are
+     *           covered in the switch.
+     */
+    }
+}
+
+enum test_suite_err_t set_testsuite(const char *name,
+                                    struct test_t *test_list, uint32_t size,
+                                    struct test_suite_t *p_ts)
+{
+    if (p_ts == 0) {
+        print_error("TEST_SUITE_ERR_INVALID_DATA!");
+        return TEST_SUITE_ERR_INVALID_DATA;
+    }
+
+    p_ts->name = name;
+    p_ts->test_list = test_list;
+    p_ts->list_size = size;
+
+    return TEST_SUITE_ERR_NO_ERROR;
+}
+
+void set_test_failed(const char *info_msg, const char *filename, uint32_t line,
+                     struct test_result_t *ret)
+{
+    if (ret == 0) {
+        print_error("TEST_SUITE_ERR_INVALID_TEST_DATA!");
+        return;
+    }
+
+    ret->val = TEST_FAILED;
+    ret->info_msg = info_msg;
+    ret->filename = filename;
+    ret->line = line;
+}
+
+enum test_suite_err_t run_testsuite(struct test_suite_t *test_suite)
+{
+    uint32_t failed_tests = 0;
+    uint32_t i;
+    struct test_t *p_test;
+
+    if (test_suite == 0 || test_suite->freg == 0) {
+        print_error("TEST_SUITE_ERR_INVALID_DATA!");
+        return TEST_SUITE_ERR_INVALID_DATA;
+    }
+
+    /* Sets test suite parameters */
+    test_suite->freg(test_suite);
+    if (test_suite->name == 0 || test_suite->list_size == 0) {
+        print_error("TEST_SUITE_ERR_INVALID_DATA!");
+        return TEST_SUITE_ERR_INVALID_DATA;
+    }
+
+    printf_set_color(YELLOW);
+    printf("Running Test Suite %s...\r\n", test_suite->name);
+
+    /* Sets pointer to the first test */
+    p_test = test_suite->test_list;
+
+    for (i = 0; i < test_suite->list_size; i++) {
+
+        if (p_test->test == 0 || p_test->name == 0) {
+            print_error("TEST_SUITE_ERR_INVALID_TEST_DATA!");
+            return TEST_SUITE_ERR_INVALID_TEST_DATA;
+        }
+
+        printf_set_color(WHITE);
+        printf("> Executing '%s' \r\n  Description: '%s'\r\n",
+               p_test->name, p_test->desc);
+
+        /* Sets the default value before the test */
+        p_test->ret.val = TEST_PASSED;
+
+        /* Executes the test */
+        p_test->test(&p_test->ret);
+        if (p_test->ret.val == TEST_FAILED) {
+            test_failed(&p_test->ret);
+            failed_tests++;
+        } else {
+            printf_set_color(GREEN);
+            printf("  TEST PASSED!\r\n");
+        }
+
+        /* Sets pointer to the next test */
+        p_test++;
+    }
+
+
+    if (failed_tests == 0) {
+        printf_set_color(GREEN);
+        printf("TESTSUITE PASSED!\r\n");
+        test_suite->val = TEST_PASSED;
+    } else {
+        printf_set_color(RED);
+        printf("TESTSUITE FAILED!\r\n");
+        printf_set_color(YELLOW);
+        printf("Number of failed tests: %d of %d\r\n",
+               failed_tests, test_suite->list_size);
+        test_suite->val = TEST_FAILED;
+    }
+
+    return TEST_SUITE_ERR_NO_ERROR;
+}
diff --git a/test/framework/test_framework.h b/test/framework/test_framework.h
new file mode 100644
index 0000000..acd0315
--- /dev/null
+++ b/test/framework/test_framework.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TEST_FRAMEWORK_H__
+#define __TEST_FRAMEWORK_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#include "helpers.h"
+
+enum test_status_t {
+    TEST_PASSED = 0,  /*!< Test has passed */
+    TEST_FAILED = 1,  /*!< Test has failed */
+};
+
+struct test_result_t {
+    enum test_status_t val;  /*!< Test result \ref test_status_t */
+    const char *info_msg;    /*!< Information message to show in case of
+                              *   failure
+                              */
+    const char *filename;    /*!< Filename where the failure has occured */
+    uint32_t    line;        /*!< Line where the failure has occured */
+};
+
+/**
+ * \brief Runs the test.
+ *
+ * \param[out] ret  Test result value
+ */
+typedef void TEST_FUN(struct test_result_t *ret);
+
+struct test_t {
+    TEST_FUN * const test;         /*!< Test function to call */
+    const char *name;              /*!< Test name */
+    const char *desc;              /*!< Test description */
+    struct test_result_t ret;      /*!< Test result */
+};
+
+struct test_suite_t;
+
+/**
+ * \brief Registers test in the testsuite structure and sets the name.
+ *
+ * \param[in] p_test_suite  Pointer to the p_test_suite_location.
+ */
+typedef void TESTSUITE_REG(struct test_suite_t *p_test_suite);
+
+struct test_suite_t {
+    TESTSUITE_REG * const freg;     /*!< Function to set all follow fields
+                                     *   of the current test suite
+                                     */
+    struct test_t *test_list;      /*!< List of tests */
+    uint32_t list_size;            /*!< List size */
+    const char *name;              /*!< Test suite name */
+    enum test_status_t val;        /*!< Test suite result \ref test_result_t */
+};
+
+enum test_suite_err_t {
+    TEST_SUITE_ERR_NO_ERROR = 0,           /*!< No error */
+    TEST_SUITE_ERR_INVALID_DATA = 1,       /*!< Invalid test suite if any of the
+                                            *   pointers is NULL
+                                            */
+    TEST_SUITE_ERR_INVALID_TEST_DATA = 2,  /*!< Invalid test if any of the
+                                            *  pointers is NULL
+                                            */
+    TEST_SUITE_ERR_TEST_FAILED  = 3,       /*!< Last executed test has failed */
+};
+
+/**
+ * \brief Translates the test suite error into a string.
+ *
+ * \param[in] err  Error value \ref test_suite_err_t
+ *
+ * \returns error as string.
+ */
+const char *test_err_to_str(enum test_suite_err_t err);
+
+/**
+ * \brief Sets test suite parameters in the \ref structure.
+ *
+ * \param[in] name       Test suite name
+ * \param[in] test_list  Pointer to the test list
+ * \param[in] size       Test list size
+ * \param[in/out] p_ts   Pointer to test suite object to fill in the
+ *                       parameters
+ *
+ * \returns Returns error code as specified in \ref test_suite_err_t
+ */
+enum test_suite_err_t set_testsuite(const char *name,
+                                    struct test_t *test_list, uint32_t size,
+                                    struct test_suite_t *p_ts);
+
+/**
+ * \brief Runs the given test suite.
+ *
+ * \param[in/out] test_suite  Test suite to run the list of tests and
+ *                            store test results.
+ *
+ * \returns Returns error code as specified in \ref test_suite_err_t
+ */
+enum test_suite_err_t run_testsuite(struct test_suite_t *test_suite);
+
+/**
+ * \brief Prints all test in the the given test suite.
+ *
+ * \param[in] ts  Test suite to print the list of tests
+ */
+void show_tests(const struct test_suite_t *ts);
+
+/**
+ * \brief Sets test failure state and information in the \ref sst_test_result_t
+ *        structure.
+ *
+ * \param[in]  info_msg  Information message to show
+ * \param[in]  filename  Filename where the error has ocurred
+ * \param[in]  line      Line in the file where the error has ocurred
+ * \param[out] ret       Pointer to \ref sst_test_result_t structure to
+ *                       set the values
+ *
+ * \note: If info_msg is "" or , info message is not shown. If filename is "",
+ *        filename and line are not shown.
+ */
+void set_test_failed(const char *info_msg, const char *filename, uint32_t line,
+                     struct test_result_t *ret);
+
+#define TEST_FAIL(info_msg)  set_test_failed(info_msg, __FILE__, __LINE__, ret)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TEST_FRAMEWORK_H__ */
diff --git a/test/suites/core/non_secure/core_ns_interactive_testsuite.c b/test/suites/core/non_secure/core_ns_interactive_testsuite.c
new file mode 100644
index 0000000..85603a2
--- /dev/null
+++ b/test/suites/core/non_secure/core_ns_interactive_testsuite.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "core_ns_tests.h"
+#include "tfm_api.h"
+#include "app/tfm_integ_test.h"
+#include "test/suites/core/non_secure/core_test_api.h"
+#include "test/test_services/tfm_core_test/core_test_defs.h"
+
+#include <stdio.h>
+#include <string.h>
+
+/* Define test suite for core interactive tests */
+/* List of tests */
+static void tfm_core_test_2001(struct test_result_t *ret);
+
+static struct test_t core_tests[] = {
+    {&tfm_core_test_2001, "TFM_CORE_TEST_2001",
+     "Interactive tests", {0} },
+};
+
+void register_testsuite_ns_core_interactive(struct test_suite_t *p_test_suite)
+{
+    uint32_t list_size;
+
+    list_size = (sizeof(core_tests) / sizeof(core_tests[0]));
+
+    set_testsuite("Core non-secure interactive tests (TFM_CORE_TEST_2XXX)",
+                  core_tests, list_size, p_test_suite);
+}
+
+/**
+ * \brief Tests core function with interactive test cases
+ */
+static void tfm_core_test_2001(struct test_result_t *ret)
+{
+    execute_ns_interactive_tests();
+
+    ret->val = TEST_PASSED;
+}
diff --git a/test/suites/core/non_secure/core_ns_positive_testsuite.c b/test/suites/core/non_secure/core_ns_positive_testsuite.c
new file mode 100644
index 0000000..828791a
--- /dev/null
+++ b/test/suites/core/non_secure/core_ns_positive_testsuite.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "core_ns_tests.h"
+#include "tfm_api.h"
+#include "test/test_services/tfm_core_test/tfm_ss_core_test_veneers.h"
+#include "test/test_services/tfm_core_test_2/tfm_ss_core_test_2_veneers.h"
+#include "test/suites/core/non_secure/core_test_api.h"
+#include "test/test_services/tfm_core_test/core_test_defs.h"
+
+#include <stdio.h>
+#include <string.h>
+
+/* Define test suite for core tests */
+/* List of tests */
+
+#define TOSTRING(x) #x
+#define CORE_TEST_DESCRIPTION(number, fn, description) \
+    {fn, "TFM_CORE_TEST_"TOSTRING(number),\
+     description, {0} }
+
+static void tfm_core_test_ns_thread(struct test_result_t *ret);
+static void tfm_core_test_ns_svc(struct test_result_t *ret);
+static void tfm_core_test_check_init(struct test_result_t *ret);
+static void tfm_core_test_recursion(struct test_result_t *ret);
+static void tfm_core_test_permissions(struct test_result_t *ret);
+static void tfm_core_test_mpu_access(struct test_result_t *ret);
+static void tfm_core_test_buffer_check(struct test_result_t *ret);
+static void tfm_core_test_ss_to_ss(struct test_result_t *ret);
+static void tfm_core_test_share_change(struct test_result_t *ret);
+static void tfm_core_test_ss_to_ss_buffer(struct test_result_t *ret);
+static void tfm_core_test_two_sfn_one_svc(struct test_result_t *ret);
+static void tfm_core_test_peripheral_access(struct test_result_t *ret);
+
+static struct test_t core_tests[] = {
+CORE_TEST_DESCRIPTION(CORE_TEST_ID_NS_THREAD, tfm_core_test_ns_thread,
+    "Test service request from NS thread mode"),
+CORE_TEST_DESCRIPTION(CORE_TEST_ID_NS_SVC, tfm_core_test_ns_svc,
+    "Test service request from NS SVC"),
+CORE_TEST_DESCRIPTION(CORE_TEST_ID_CHECK_INIT, tfm_core_test_check_init,
+    "Test the success of service init"),
+CORE_TEST_DESCRIPTION(CORE_TEST_ID_RECURSION, tfm_core_test_recursion,
+    "Test direct recursion of secure services"),
+CORE_TEST_DESCRIPTION(CORE_TEST_ID_MEMORY_PERMISSIONS,
+    tfm_core_test_permissions,
+    "Test secure service memory access permissions"),
+CORE_TEST_DESCRIPTION(CORE_TEST_ID_MPU_ACCESS, tfm_core_test_mpu_access,
+    "Test secure service MPU accesses"),
+CORE_TEST_DESCRIPTION(CORE_TEST_ID_BUFFER_CHECK, tfm_core_test_buffer_check,
+    "Test secure service buffer accesses"),
+CORE_TEST_DESCRIPTION(CORE_TEST_ID_SS_TO_SS, tfm_core_test_ss_to_ss,
+    "Test secure service to service call"),
+CORE_TEST_DESCRIPTION(CORE_TEST_ID_SHARE_REDIRECTION,
+    tfm_core_test_share_change,
+    "Test secure service share change request"),
+CORE_TEST_DESCRIPTION(CORE_TEST_ID_SS_TO_SS_BUFFER,
+    tfm_core_test_ss_to_ss_buffer,
+    "Test secure service to service call with buffer handling"),
+CORE_TEST_DESCRIPTION(CORE_TEST_ID_TWO_SFN_ONE_SVC,
+    tfm_core_test_two_sfn_one_svc,
+    "Test multiple service calls from single SVC"),
+CORE_TEST_DESCRIPTION(CORE_TEST_ID_PERIPHERAL_ACCESS,
+    tfm_core_test_peripheral_access,
+    "Test service peripheral access"),
+};
+
+void register_testsuite_ns_core_positive(struct test_suite_t *p_test_suite)
+{
+    uint32_t list_size;
+
+    list_size = (sizeof(core_tests) / sizeof(core_tests[0]));
+
+    set_testsuite("Core non-secure positive tests (TFM_CORE_TEST_1XXX)",
+                  core_tests, list_size, p_test_suite);
+}
+
+/* Args that may or may not be used for service calls */
+int32_t args[] = {0};
+
+static void tfm_core_test_ns_thread(struct test_result_t *ret)
+{
+    int32_t err = tfm_core_test_sfn(CORE_TEST_ID_NS_THREAD, 0, 0, 0);
+
+    if (err == TFM_SUCCESS) {
+        TEST_FAIL("TFM Core allowed service to run.");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+static void tfm_core_test_ns_svc(struct test_result_t *ret)
+{
+    args[0] = CORE_TEST_ID_NS_SVC;
+
+    int32_t err = tfm_core_test_svc(tfm_core_test_sfn, args);
+
+    if (err != TFM_SUCCESS) {
+        TEST_FAIL("Service failed to run.");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+static void tfm_core_test_peripheral_access(struct test_result_t *ret)
+{
+    args[0] = CORE_TEST_ID_PERIPHERAL_ACCESS;
+
+    int32_t err = tfm_core_test_svc(tfm_core_test_sfn, args);
+
+    if ((err != TFM_SUCCESS) && (err < TFM_SERVICE_SPECIFIC_ERROR_MIN)) {
+        TEST_FAIL("TFM Core returned error.");
+        return;
+    }
+
+    switch (err) {
+    case CORE_TEST_ERRNO_SUCCESS:
+        ret->val = TEST_PASSED;
+        return;
+    case CORE_TEST_ERRNO_PERIPHERAL_ACCESS_FAILED:
+        TEST_FAIL("Service peripheral access failed.");
+        return;
+    default:
+        TEST_FAIL("Unexpected return value received.");
+        return;
+    }
+}
+
+/*
+ * \brief Tests whether the initialisation of the service was successful.
+ *
+ */
+static void tfm_core_test_check_init(struct test_result_t *ret)
+{
+    int32_t err;
+
+    err = tfm_core_test_svc(tfm_core_test_sfn_init_success, args);
+
+    if ((err != TFM_SUCCESS) && (err < TFM_SERVICE_SPECIFIC_ERROR_MIN)) {
+        TEST_FAIL("TFM Core returned error.");
+        return;
+    }
+
+    if (err != CORE_TEST_ERRNO_SUCCESS) {
+        TEST_FAIL("Failed to initialise test service.");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Tests what happens when a service calls itself directly
+ *
+ * \return Returns \ref CORE_TEST_ERRNO_SUCCESS
+ */
+static void tfm_core_test_recursion(struct test_result_t *ret)
+{
+    int32_t err;
+
+    /* Initialize depth argument to 0 */
+    args[0] = 0;
+    err = tfm_core_test_svc(tfm_core_test_sfn_direct_recursion, args);
+
+    if (err != TFM_SUCCESS && err < 256) {
+        TEST_FAIL("TFM Core returned error.");
+        return;
+    }
+
+    switch (err) {
+    case CORE_TEST_ERRNO_SUCCESS:
+        ret->val = TEST_PASSED;
+        return;
+    case CORE_TEST_ERRNO_SERVICE_RECURSION_NOT_REJECTED:
+        TEST_FAIL("TF-M Core failed to reject recursive service call.");
+        return;
+    default:
+        TEST_FAIL("Unexpected return value received.");
+        return;
+    }
+}
+
+static char *error_to_string(const char *desc, int32_t err)
+{
+    static char info[80];
+
+    sprintf(info, "%s. Error code: %d, extra data: %d",
+        desc,
+        CORE_TEST_ERROR_GET_CODE(err),
+        CORE_TEST_ERROR_GET_EXTRA(err));
+    return info;
+}
+
+static void tfm_core_test_mpu_access(struct test_result_t *ret)
+{
+    int32_t err;
+
+    int32_t args[] = {
+        CORE_TEST_ID_MPU_ACCESS,
+        (int32_t)args,
+        /* Make sure the pointer in code segment is word-aligned */
+        (int32_t)tfm_core_test_mpu_access & (~(0x3)),
+        (int32_t)args};
+
+    err = tfm_core_test_svc(tfm_core_test_sfn, args);
+
+    if (err != TFM_SUCCESS && err < TFM_SERVICE_SPECIFIC_ERROR_MIN) {
+        TEST_FAIL("TFM Core returned error.");
+        return;
+    }
+
+    if (err != CORE_TEST_ERRNO_SUCCESS) {
+        char *info = error_to_string(
+            "Service memory accesses configured incorrectly.", err);
+        TEST_FAIL(info);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+static void tfm_core_test_permissions(struct test_result_t *ret)
+{
+    int32_t err;
+
+    int32_t args[] = {
+        CORE_TEST_ID_MEMORY_PERMISSIONS,
+        (int32_t)args,
+        /* Make sure the pointer in code segment is word-aligned */
+        (int32_t)tfm_core_test_mpu_access & (~(0x3)),
+        (int32_t)args};
+
+    err = tfm_core_test_svc(tfm_core_test_sfn, args);
+
+    if (err != TFM_SUCCESS && err < TFM_SERVICE_SPECIFIC_ERROR_MIN) {
+        TEST_FAIL("TFM Core returned error.");
+        return;
+    }
+
+    if (err != CORE_TEST_ERRNO_SUCCESS) {
+        char *info = error_to_string(
+            "Service memory accesses configured incorrectly.", err);
+        TEST_FAIL(info);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+static void tfm_core_test_buffer_check(struct test_result_t *ret)
+{
+    int32_t res, i;
+
+    uint32_t inbuf[] = {1, 2, 3, 4, 0xAAAFFF, 0xFFFFFFFF};
+    uint32_t outbuf[16] = {0};
+    int32_t result;
+    int32_t args[] = {(int32_t)&result, (int32_t)inbuf,
+                  (int32_t)outbuf, (int32_t)sizeof(inbuf) >> 2};
+
+    res = tfm_core_test_svc(tfm_core_test_2_sfn_invert, args);
+    if ((res != TFM_SUCCESS) && (res < TFM_SERVICE_SPECIFIC_ERROR_MIN)) {
+        TEST_FAIL("Call to secure service should be successful.");
+        return;
+    }
+    if ((result == 0) && (res == TFM_SUCCESS)) {
+        for (i = 0; i < sizeof(inbuf) >> 2; i++) {
+            if (outbuf[i] != ~inbuf[i]) {
+                TEST_FAIL("Secure function failed to modify buffer.");
+                return;
+            }
+        }
+        for (; i < sizeof(outbuf) >> 2; i++) {
+            if (outbuf[i] != 0) {
+                TEST_FAIL("Secure function buffer access overflow.");
+                return;
+            }
+        }
+    } else {
+        TEST_FAIL("Secure service returned error.");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+static void tfm_core_test_ss_to_ss(struct test_result_t *ret)
+{
+    int32_t err;
+
+    args[0] = CORE_TEST_ID_SS_TO_SS;
+    err = tfm_core_test_svc(tfm_core_test_sfn, args);
+
+    if (err != TFM_SUCCESS && err < TFM_SERVICE_SPECIFIC_ERROR_MIN) {
+        TEST_FAIL("Call to secure service should be successful.");
+        return;
+    }
+
+    if (err != CORE_TEST_ERRNO_SUCCESS) {
+        TEST_FAIL("The internal service call failed.");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+static void tfm_core_test_share_change(struct test_result_t *ret)
+{
+    int32_t err;
+
+    args[0] = CORE_TEST_ID_SHARE_REDIRECTION;
+    err = tfm_core_test_svc(tfm_core_test_sfn, args);
+
+    if ((err != TFM_SUCCESS) && (err < TFM_SERVICE_SPECIFIC_ERROR_MIN)) {
+        TEST_FAIL("TFM Core returned error.");
+        return;
+    }
+
+    if (err != CORE_TEST_ERRNO_SUCCESS) {
+        TEST_FAIL("Failed to redirect share region in service.");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+static void tfm_core_test_ss_to_ss_buffer(struct test_result_t *ret)
+{
+    int32_t res, i;
+
+    uint32_t inbuf[] = {1, 2, 3, 4, 0xAAAFFF, 0xFFFFFFFF};
+    uint32_t outbuf[16] = {0};
+    int32_t args[] = {CORE_TEST_ID_SS_TO_SS_BUFFER, (int32_t)inbuf,
+                  (int32_t)outbuf, (int32_t)sizeof(inbuf) >> 2};
+
+    res = tfm_core_test_svc(tfm_core_test_sfn, args);
+    if ((res != TFM_SUCCESS) && (res < TFM_SERVICE_SPECIFIC_ERROR_MIN)) {
+        TEST_FAIL("Call to secure service should be successful.");
+        return;
+    }
+    switch (res) {
+    case TFM_SUCCESS:
+        for (i = 0; i < sizeof(inbuf) >> 2; i++) {
+            if (outbuf[i] != ~inbuf[i]) {
+                TEST_FAIL("Secure function failed to modify buffer.");
+                return;
+            }
+        }
+        for (; i < sizeof(outbuf) >> 2; i++) {
+            if (outbuf[i] != 0) {
+                TEST_FAIL("Secure function buffer access overflow.");
+                return;
+            }
+        }
+        ret->val = TEST_PASSED;
+        return;
+    case CORE_TEST_ERRNO_INVALID_BUFFER:
+        TEST_FAIL("NS buffer rejected by TF-M core.");
+        return;
+    case CORE_TEST_ERRNO_SLAVE_SERVICE_CALL_FAILURE:
+        TEST_FAIL("Slave service call failed.");
+        return;
+    case CORE_TEST_ERRNO_SLAVE_SERVICE_BUFFER_FAILURE:
+        TEST_FAIL("Slave secure function failed to modify buffer.");
+        return;
+    default:
+        TEST_FAIL("Secure service returned error.");
+        return;
+    }
+}
+
+static void tfm_core_test_two_sfn_one_svc(struct test_result_t *ret)
+{
+    int32_t err;
+
+    args[0] = CORE_TEST_ID_TWO_SFN_ONE_SVC;
+    err = tfm_core_test_multiple_calls_svc(tfm_core_test_sfn, args);
+
+    if ((err != TFM_SUCCESS) && (err < TFM_SERVICE_SPECIFIC_ERROR_MIN)) {
+        TEST_FAIL("TFM Core returned error.");
+        return;
+    }
+
+    switch (err) {
+    case TFM_SUCCESS:
+        ret->val = TEST_PASSED;
+        return;
+    case CORE_TEST_ERRNO_FIRST_CALL_FAILED:
+        TEST_FAIL("First call failed.");
+        return;
+    case CORE_TEST_ERRNO_SECOND_CALL_FAILED:
+        TEST_FAIL("Second call failed.");
+        return;
+    default:
+        TEST_FAIL("Secure service returned unknown error.");
+        return;
+    }
+}
diff --git a/test/suites/core/non_secure/core_ns_tests.h b/test/suites/core/non_secure/core_ns_tests.h
new file mode 100644
index 0000000..52d10b5
--- /dev/null
+++ b/test/suites/core/non_secure/core_ns_tests.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __CORE_NS_TESTS_H__
+#define __CORE_NS_TESTS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "test/framework/test_framework.h"
+
+/**
+ * \brief Register testsuite for the core positive tests.
+ *
+ * \param[in] p_test_suite  The test suite to be executed.
+ */
+void register_testsuite_ns_core_positive(struct test_suite_t *p_test_suite);
+
+/**
+ * \brief Register testsuite for the core interactive tests.
+ *
+ * \param[in] p_test_suite  The test suite to be executed.
+ */
+void register_testsuite_ns_core_interactive(struct test_suite_t *p_test_suite);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_NS_TESTS_H__ */
diff --git a/test/suites/core/non_secure/core_test_api.c b/test/suites/core/non_secure/core_test_api.c
new file mode 100644
index 0000000..828bdbc
--- /dev/null
+++ b/test/suites/core/non_secure/core_test_api.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "app/tfm_integ_test.h"
+
+#include "core_test_api.h"
+#include "tfm_ns_svc.h"
+
+__attribute__ ((naked)) int32_t tfm_core_test_svc(void *fn_ptr, int32_t args[])
+{
+    SVC(SVC_TFM_CORE_TEST);
+    __ASM("BX LR");
+}
+
+__attribute__ ((naked)) int32_t tfm_core_test_multiple_calls_svc(void *fn_ptr,
+                                                                 int32_t args[])
+{
+    SVC(SVC_TFM_CORE_TEST_MULTIPLE_CALLS);
+    __ASM("BX LR");
+}
diff --git a/test/suites/core/non_secure/core_test_api.h b/test/suites/core/non_secure/core_test_api.h
new file mode 100644
index 0000000..32f2746
--- /dev/null
+++ b/test/suites/core/non_secure/core_test_api.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __CORE_TEST_API_H__
+#define __CORE_TEST_API_H__
+
+#include <stdio.h>
+#include <cmsis_compiler.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Does an SVC for calling the secure function provided in \ref fn_ptr
+ *
+ * \param[in] fn_ptr  Secure function to be called.
+ * \param[in] args    Arguments for fn_ptr.
+ *
+ * \return Returns value depending on fn_ptr.
+ */
+int32_t tfm_core_test_svc(void *fn_ptr, int32_t args[]);
+
+/**
+ * \brief Tests secure function \ref fn_ptr called two times sequentially.
+ *
+ * \param[in] fn_ptr  Secure function to be called.
+ * \param[in] args    Arguments for fn_ptr.
+ *
+ * \return Returns \ref CORE_TEST_ERRNO_SUCCESS or error if one of the calls
+ *         failed
+ */
+int32_t tfm_core_test_multiple_calls_svc(void *fn_ptr, int32_t args[]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_TEST_API_H__ */
diff --git a/test/suites/core/non_secure/svc_core_test_ns.c b/test/suites/core/non_secure/svc_core_test_ns.c
new file mode 100644
index 0000000..9ad17ba
--- /dev/null
+++ b/test/suites/core/non_secure/svc_core_test_ns.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "test/test_services/tfm_core_test/core_test_defs.h"
+
+int32_t svc_tfm_core_test(int32_t (*fn_ptr)(int32_t, int32_t, int32_t, int32_t),
+                          int32_t args[])
+{
+    return fn_ptr(args[0], args[1], args[2], args[3]);
+}
+
+int32_t svc_tfm_core_test_multiple_calls(
+            int32_t (*fn_ptr)(int32_t, int32_t, int32_t, int32_t),
+            int32_t args[])
+{
+    int32_t res = fn_ptr(args[0], args[1], args[2], args[3]);
+
+    if (res != CORE_TEST_ERRNO_SUCCESS) {
+        return CORE_TEST_ERRNO_FIRST_CALL_FAILED;
+    }
+    res = fn_ptr(args[0], args[1], args[2], args[3]);
+    if (res != CORE_TEST_ERRNO_SUCCESS) {
+        return CORE_TEST_ERRNO_SECOND_CALL_FAILED;
+    }
+    return CORE_TEST_ERRNO_SUCCESS;
+}
diff --git a/test/suites/core/non_secure/svc_core_test_ns.h b/test/suites/core/non_secure/svc_core_test_ns.h
new file mode 100644
index 0000000..55b87c7
--- /dev/null
+++ b/test/suites/core/non_secure/svc_core_test_ns.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __SVC_CORE_TEST_NS_H__
+#define __SVC_CORE_TEST_NS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The following functions are SVC handlers for calling tests services. */
+/* Note: only the symbols are needed, not exact prototype. For documentation
+ * on the parameters and return value of these functions see
+ * \ref core_test_api.h
+ */
+
+/**
+ * \brief SVC handler for calling a secure function.
+ */
+int32_t svc_tfm_core_test(void);
+
+/**
+ * \brief SVC handler for calling a secure function multiple times.
+ */
+int32_t svc_tfm_core_test_multiple_calls(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SVC_CORE_TEST_NS_H__ */
diff --git a/test/suites/invert/non_secure/invert_ns_interface_testsuite.c b/test/suites/invert/non_secure/invert_ns_interface_testsuite.c
new file mode 100644
index 0000000..4b9128b
--- /dev/null
+++ b/test/suites/invert/non_secure/invert_ns_interface_testsuite.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "invert_ns_tests.h"
+#include "tfm_api.h"
+#include "test/test_services/tfm_core_test_2/tfm_ss_core_test_2_veneers.h"
+#include "test/suites/core/non_secure/core_test_api.h"
+
+#include <stdio.h>
+#include <string.h>
+
+/* Define test suite for asset manager tests */
+/* List of tests */
+static void tfm_invert_test_1001(struct test_result_t *ret);
+static void tfm_invert_test_1002(struct test_result_t *ret);
+
+static struct test_t invert_veeners_tests[] = {
+    {&tfm_invert_test_1001, "TFM_INVERT_TEST_1001",
+     "Invert with valid buffer", {0} },
+    {&tfm_invert_test_1002, "TFM_INVERT_TEST_1002",
+     "Invert with invalid buffer", {0} },
+};
+
+void register_testsuite_ns_invert_interface(struct test_suite_t *p_test_suite)
+{
+    uint32_t list_size;
+
+    list_size = (sizeof(invert_veeners_tests) /
+                 sizeof(invert_veeners_tests[0]));
+
+    set_testsuite("Invert non-secure interface tests (TFM_INVERT_TEST_1XXX)",
+                  invert_veeners_tests, list_size, p_test_suite);
+}
+
+/**
+ * \brief Tests invert function with valid length
+ */
+static void tfm_invert_test_1001(struct test_result_t *ret)
+{
+    int32_t err;
+    int32_t res;
+    int32_t len;
+    int32_t i;
+
+    uint32_t in_ptr[] = {0xBADC0FFEU, 0xDEADBEEFU};
+    uint32_t out_ptr[sizeof(in_ptr) / sizeof(in_ptr[0])];
+
+    memset(out_ptr, 0, sizeof(out_ptr));
+
+    len = sizeof(in_ptr)/sizeof(in_ptr[0]);
+
+    int32_t args[] = {(int32_t)&res, (int32_t)in_ptr,
+                      (int32_t)out_ptr, (int32_t)len};
+
+    err = tfm_core_test_svc(tfm_core_test_2_sfn_invert, args);
+
+    if (err != TFM_SUCCESS) {
+        TEST_FAIL("Call to secure service should be successful");
+        return;
+    }
+
+    if (res != 0) {
+        TEST_FAIL("Invert should succeed on small buffer");
+        return;
+    }
+
+    for (i = 0; i < len; ++i) {
+        if (~in_ptr[i] != out_ptr[i]) {
+            TEST_FAIL("Output should be the inverted version of input");
+            return;
+        }
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Tests invert function with invalid length
+ */
+static void tfm_invert_test_1002(struct test_result_t *ret)
+{
+    int32_t err;
+    int32_t res;
+    uint32_t *in_ptr = (uint32_t *)0xFFFFFFFFU;
+    uint32_t *out_ptr = in_ptr;
+
+    int32_t len = 1024;
+
+    int32_t args[] = {(int32_t)&res, (int32_t)in_ptr,
+                                     (int32_t)out_ptr, (int32_t)len};
+
+    err = tfm_core_test_svc(tfm_core_test_2_sfn_invert, args);
+
+    if (err == TFM_SUCCESS) {
+        TEST_FAIL("Call to secure service should not be successful");
+        return;
+    }
+
+    if (res != -1) {
+        TEST_FAIL("Invert should fail with large buffer. Unexpected result");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
diff --git a/test/suites/invert/non_secure/invert_ns_tests.h b/test/suites/invert/non_secure/invert_ns_tests.h
new file mode 100644
index 0000000..45ead7a
--- /dev/null
+++ b/test/suites/invert/non_secure/invert_ns_tests.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __INVERT_NS_TESTS_H__
+#define __INVERT_NS_TESTS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "test/framework/test_framework.h"
+
+/**
+ * \brief Register testsuite for the invert test service.
+ *
+ * \param[in] p_test_suite The test suite to be executed.
+ */
+void register_testsuite_ns_invert_interface(struct test_suite_t *p_test_suite);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INVERT_NS_TESTS_H__ */
diff --git a/test/suites/invert/secure/invert_s_interface_testsuite.c b/test/suites/invert/secure/invert_s_interface_testsuite.c
new file mode 100644
index 0000000..6d074d5
--- /dev/null
+++ b/test/suites/invert/secure/invert_s_interface_testsuite.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "invert_s_tests.h"
+#include "tfm_api.h"
+#include "test/test_services/tfm_core_test_2/tfm_ss_core_test_2_veneers.h"
+#include <stdio.h>
+#include <string.h>
+
+/* Define test suite for asset manager tests */
+/* List of tests */
+static void tfm_invert_test_1001(struct test_result_t *ret);
+static void tfm_invert_test_1002(struct test_result_t *ret);
+
+static struct test_t invert_veeners_tests[] = {
+    {&tfm_invert_test_1001, "TFM_INVERT_TEST_1001",
+     "Invert with valid buffer", {0} },
+    {&tfm_invert_test_1002, "TFM_INVERT_TEST_1002",
+     "Invert with invalid buffer", {0} },
+};
+
+void register_testsuite_s_invert_interface(struct test_suite_t *p_test_suite)
+{
+    uint32_t list_size;
+
+    list_size = (sizeof(invert_veeners_tests) /
+                 sizeof(invert_veeners_tests[0]));
+
+    set_testsuite("Invert secure interface tests (TFM_INVERT_TEST_1XXX)",
+                  invert_veeners_tests, list_size, p_test_suite);
+}
+
+/**
+ * \brief Tests invert function with valid length
+ */
+static void tfm_invert_test_1001(struct test_result_t *ret)
+{
+    int32_t res;
+    int32_t len;
+    int32_t i;
+    uint32_t in_ptr[] = {0xBADC0FFEU, 0xDEADBEEFU};
+    uint32_t out_ptr[sizeof(in_ptr) / sizeof(in_ptr[0])];
+
+    memset(out_ptr, 0, sizeof(out_ptr));
+
+    len = sizeof(in_ptr)/sizeof(in_ptr[0]);
+
+    tfm_core_test_2_sfn_invert(&res, in_ptr, out_ptr, len);
+
+    if (res != 0) {
+        TEST_FAIL("Invert should succeed on small buffer");
+        return;
+    }
+
+    for (i = 0; i < len; ++i) {
+        if (~in_ptr[i] != out_ptr[i]) {
+            TEST_FAIL("Output should be the inverted version of input");
+            return;
+        }
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Tests invert function with invalid length
+ */
+static void tfm_invert_test_1002(struct test_result_t *ret)
+{
+    int32_t res;
+    uint32_t *in_ptr = (uint32_t *)0xFFFFFFFFU;
+    uint32_t *out_ptr = in_ptr;
+
+    int32_t len = 1024;
+
+    tfm_core_test_2_sfn_invert(&res, in_ptr, out_ptr, len);
+
+    if (res != -1) {
+        TEST_FAIL("Invert should fail with large buffer");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
diff --git a/test/suites/invert/secure/invert_s_tests.h b/test/suites/invert/secure/invert_s_tests.h
new file mode 100644
index 0000000..e69e99d
--- /dev/null
+++ b/test/suites/invert/secure/invert_s_tests.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __INVERT_S_TESTS_H__
+#define __INVERT_S_TESTS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "test/framework/test_framework.h"
+
+/**
+ * \brief Register testsuite for the invert test service.
+ *
+ * \param[in] p_test_suite The test suite to be executed.
+ */
+void register_testsuite_s_invert_interface(struct test_suite_t *p_test_suite);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INVERT_S_TESTS_H__ */
diff --git a/test/suites/sst/non_secure/os_wrapper.h b/test/suites/sst/non_secure/os_wrapper.h
new file mode 100644
index 0000000..9a9cded
--- /dev/null
+++ b/test/suites/sst/non_secure/os_wrapper.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __OS_WRAPPER_H__
+#define __OS_WRAPPER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#define OS_WRAPPER_ERROR  0xFFFFFFFF
+
+/* prototype for the thread entry function */
+typedef void (*os_wrapper_thread_func) (void *argument);
+
+/**
+ * \brief Creates a new semaphore
+ *
+ * \param[in] max_count       Highest count of the semaphore
+ * \param[in] initial_count   Starting count of the semaphore
+ * \param[in] name            Name of the semaphore
+ *
+ * \return Returns ID of the semaphore created, or OS_WRAPPER_ERROR in case of
+ *         error
+ */
+uint32_t os_wrapper_semaphore_create(uint32_t max_count, uint32_t initial_count,
+                                     const char *name);
+
+/**
+ * \brief Acquires the semaphore
+ *
+ * \param[in] semaphore_id Semaphore ID
+ * \param[in] timeout      Timeout value
+ *
+ * \return 0 in case of successful acquision, or OS_WRAPPER_ERROR in case of
+ *         error
+ */
+uint32_t os_wrapper_semaphore_acquire(uint32_t semaphore_id, uint32_t timeout);
+
+/**
+ * \brief Releases the semaphore
+ *
+ * \param[in] semaphore_id Semaphore ID
+ *
+ * \return 0 in case of successful release, or OS_WRAPPER_ERROR in case of error
+ */
+uint32_t os_wrapper_semaphore_release(uint32_t semaphore_id);
+
+/**
+ * \brief Deletes the semaphore
+ *
+ * \param[in] semaphore_id Semaphore ID
+ *
+ * \return 0 in case of successful release, or OS_WRAPPER_ERROR in case of error
+ */
+uint32_t os_wrapper_semaphore_delete(uint32_t sema);
+
+/**
+ * \brief Creates a new thread
+ *
+ * \param[in] name        Name of the thread
+ * \param[in] stack_size  Size of stack to be allocated for this thread
+ * \param[in] func        Pointer to the function invoked by thread
+ * \param[in] priority    Initial thread priority
+ *
+ * \return Returns thread ID, or OS_WRAPPER_ERROR in case of error
+ */
+uint32_t os_wrapper_new_thread(const char *name, uint32_t stack_size,
+                               os_wrapper_thread_func func, uint32_t priority);
+/**
+ * \brief Gets current thread ID
+ *
+ * \return Returns thread ID, or OS_WRAPPER_ERROR in case of error
+ */
+uint32_t os_wrapper_get_thread_id(void);
+
+/**
+ * \brief Gets thread priority
+ *
+ * \param[in] id  Thread ID
+ *
+ * \return Returns thread priority value, or OS_WRAPPER_ERROR in case of error
+ */
+uint32_t os_wrapper_get_thread_priority(uint32_t id);
+
+/**
+ * \brief Deletes thread
+ *
+ * \param[in] id  Thread ID
+ *
+ * \return 0 in case of successful delete or OS_WRAPPER_ERROR in case of error.
+ */
+uint32_t os_wrapper_delete_thread(uint32_t id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __OS_WRAPPER_H__ */
diff --git a/test/suites/sst/non_secure/sst_ns_interface_testsuite.c b/test/suites/sst/non_secure/sst_ns_interface_testsuite.c
new file mode 100644
index 0000000..335b968
--- /dev/null
+++ b/test/suites/sst/non_secure/sst_ns_interface_testsuite.c
@@ -0,0 +1,1859 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "sst_ns_tests.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "cmsis.h"
+#include "cmsis_os2.h"
+#include "os_wrapper.h"
+
+#include "test/framework/helpers.h"
+#include "secure_fw/services/secure_storage/assets/sst_asset_defs.h"
+#include "tfm_sst_api.h"
+
+/* Test suite defines */
+#define INVALID_ASSET_ID           0xFFFF
+#define READ_BUF_SIZE                12UL
+#define WRITE_BUF_SIZE                5UL
+
+/* Memory bounds to check */
+#define ROM_ADDR_LOCATION        0x00000000
+#define DEV_ADDR_LOCATION        0x40000000
+#define SECURE_ADDR_LOCATION     0x30000000
+#define NON_EXIST_ADDR_LOCATION  0xFFFFFFFF
+
+/* Test data sized to fill the SHA224 asset */
+#define READ_DATA_SHA224    "XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+#define WRITE_DATA_SHA224_1 "TEST_DATA_ONE_TWO_THREE_FOUR"
+#define WRITE_DATA_SHA224_2 "(ABCDEFGHIJKLMNOPQRSTUVWXYZ)"
+#define BUF_SIZE_SHA224     (SST_ASSET_MAX_SIZE_SHA224_HASH + 1)
+
+/* test tasks's stack size */
+#define SST_TEST_TASK_STACK_SIZE 2048
+static uint32_t tfm_sst_test_sema;
+static struct test_result_t transient_result;
+
+/* shared asset handles for multithreaded tests */
+static uint32_t tfm_sst_test_1004_handle;
+static uint32_t tfm_sst_test_1006_handle;
+static uint32_t tfm_sst_test_1008_handle;
+static uint32_t tfm_sst_test_1017_asset1_handle;
+static uint32_t tfm_sst_test_1017_asset2_handle;
+/* Define test suite for asset manager tests */
+/* List of tests */
+static void tfm_sst_test_1001(struct test_result_t *ret);
+static void tfm_sst_test_1002(struct test_result_t *ret);
+static void tfm_sst_test_1003(struct test_result_t *ret);
+static void tfm_sst_test_1004(struct test_result_t *ret);
+static void tfm_sst_test_1005(struct test_result_t *ret);
+static void tfm_sst_test_1006(struct test_result_t *ret);
+static void tfm_sst_test_1007(struct test_result_t *ret);
+static void tfm_sst_test_1008(struct test_result_t *ret);
+static void tfm_sst_test_1009(struct test_result_t *ret);
+static void tfm_sst_test_1010(struct test_result_t *ret);
+static void tfm_sst_test_1011(struct test_result_t *ret);
+static void tfm_sst_test_1012(struct test_result_t *ret);
+static void tfm_sst_test_1013(struct test_result_t *ret);
+static void tfm_sst_test_1014(struct test_result_t *ret);
+static void tfm_sst_test_1015(struct test_result_t *ret);
+static void tfm_sst_test_1016(struct test_result_t *ret);
+static void tfm_sst_test_1017(struct test_result_t *ret);
+static void tfm_sst_test_1018(struct test_result_t *ret);
+
+static struct test_t asset_veeners_tests[] = {
+    {&tfm_sst_test_1001, "TFM_SST_TEST_1001",
+     "Create interface from allowed appid", {0} },
+    {&tfm_sst_test_1002, "TFM_SST_TEST_1002",
+     "Create interface from non allowed appid", {0} },
+    {&tfm_sst_test_1003, "TFM_SST_TEST_1003",
+     "Get handle interface", {0} },
+    {&tfm_sst_test_1004, "TFM_SST_TEST_1004",
+     "Get attributes interface",  {0} },
+    {&tfm_sst_test_1005, "TFM_SST_TEST_1005",
+     "Get attributes interface from non authorized task",  {0} },
+    {&tfm_sst_test_1006, "TFM_SST_TEST_1006",
+     "Write interface", {0} },
+    {&tfm_sst_test_1007, "TFM_SST_TEST_1007",
+     "Write interface from non authorized task", {0} },
+    {&tfm_sst_test_1008, "TFM_SST_TEST_1008",
+     "Read interface", {0} },
+    {&tfm_sst_test_1009, "TFM_SST_TEST_1009",
+     "Read interface from non authorized task", {0} },
+    {&tfm_sst_test_1010, "TFM_SST_TEST_1010",
+     "Read interface test cleanup", {0} },
+    {&tfm_sst_test_1011, "TFM_SST_TEST_1011",
+     "Delete interface", {0} },
+    {&tfm_sst_test_1012, "TFM_SST_TEST_1012",
+     "Delete interface multiple from multiple contexts", {0} },
+    {&tfm_sst_test_1013, "TFM_SST_TEST_1013",
+     "Write and partial reads", {0} },
+    {&tfm_sst_test_1014, "TFM_SST_TEST_1014",
+     "Write more data than asset max size", {0} },
+    {&tfm_sst_test_1015, "TFM_SST_TEST_1015",
+     "Appending data to an asset", {0} },
+    {&tfm_sst_test_1016, "TFM_SST_TEST_1016",
+     "Appending data to an asset until eof", {0} },
+    {&tfm_sst_test_1017, "TFM_SST_TEST_1017",
+     "Write data to two assets alternately", {0} },
+    {&tfm_sst_test_1018, "TFM_SST_TEST_1018",
+     "Write and read data from illegal locations", {0} },
+};
+
+void register_testsuite_ns_sst_interface(struct test_suite_t *p_test_suite)
+{
+    uint32_t list_size;
+
+    list_size = (sizeof(asset_veeners_tests) / sizeof(asset_veeners_tests[0]));
+
+    set_testsuite("SST non-secure interface tests (TFM_SST_TEST_1XXX)",
+                  asset_veeners_tests, list_size, p_test_suite);
+}
+
+/**
+ * \note List of relations between thread name, app ID and permissions
+ *
+ * Asset permissions: SST_ASSET_ID_X509_CERT_LARGE
+ *
+ *   THREAD NAME | APP_ID       | Permissions
+ *   ------------|--------------------------------------
+ *     Thread_A  | SST_APP_ID_0 | REFERENCE
+ *     Thread_B  | SST_APP_ID_1 | REFERENCE, READ
+ *     Thread_C  | SST_APP_ID_2 | REFERENCE, READ, WRITE
+ *
+ * Asset permissions: SST_ASSET_ID_SHA224_HASH
+ *
+ *   THREAD NAME | APP_ID       | Permissions
+ *   ------------|--------------------------------------
+ *     Thread_A  | SST_APP_ID_0 | NONE
+ *     Thread_B  | SST_APP_ID_1 | REFERENCE, READ, WRITE
+ *     Thread_C  | SST_APP_ID_2 | NONE
+ *
+ * Asset permissions: SST_ASSET_ID_SHA384_HASH
+ *
+ *   THREAD NAME | APP_ID       | Permissions
+ *   ------------|--------------------------------
+ *     Thread_A  | SST_APP_ID_0 | NONE
+ *     Thread_B  | SST_APP_ID_1 | NONE
+ *     Thread_C  | SST_APP_ID_2 | REFERENCE, WRITE
+ */
+
+/**
+ * \brief Executes given test from specified thread context
+ */
+
+static void tfm_sst_run_test(const char *name, struct test_result_t *ret,
+                             os_wrapper_thread_func func)
+{
+    uint32_t err;
+    uint32_t current_thread_id;
+    uint32_t current_thread_priority;
+    uint32_t thread;
+
+    tfm_sst_test_sema = os_wrapper_semaphore_create(1, 0, "sst_tests_mutex");
+    if (tfm_sst_test_sema == OS_WRAPPER_ERROR) {
+        TEST_FAIL("semaphore creation has failed\n");
+        return;
+    }
+
+    current_thread_id = os_wrapper_get_thread_id();
+    if (current_thread_id == OS_WRAPPER_ERROR) {
+        os_wrapper_semaphore_delete(tfm_sst_test_sema);
+        TEST_FAIL("get current thread ID has failed");
+        return;
+    }
+
+    current_thread_priority = os_wrapper_get_thread_priority(current_thread_id);
+    if (current_thread_priority == OS_WRAPPER_ERROR) {
+        os_wrapper_semaphore_delete(tfm_sst_test_sema);
+        TEST_FAIL("get current thread priority has failed");
+        return;
+    }
+
+    /* increase the priority of the new thread */
+    current_thread_priority += 1;
+
+    thread = os_wrapper_new_thread(name, SST_TEST_TASK_STACK_SIZE,
+                                   func, current_thread_priority);
+    if (thread == OS_WRAPPER_ERROR) {
+        os_wrapper_semaphore_delete(tfm_sst_test_sema);
+        TEST_FAIL("thread creation has failed");
+        return;
+    }
+
+    /* wait for the test to finish and release the semaphore */
+    err = os_wrapper_semaphore_acquire(tfm_sst_test_sema, 0xFFFFFFFF);
+    if (err == OS_WRAPPER_ERROR) {
+        os_wrapper_semaphore_delete(tfm_sst_test_sema);
+        TEST_FAIL("semaphore wait has failed");
+        return;
+    }
+
+    err = os_wrapper_delete_thread(thread);
+    if (err == OS_WRAPPER_ERROR) {
+        os_wrapper_semaphore_delete(tfm_sst_test_sema);
+        TEST_FAIL("delete thread has failed");
+        return;
+    }
+
+    /* populate the results */
+    memcpy(ret, &transient_result, sizeof(struct test_result_t));
+    os_wrapper_semaphore_delete(tfm_sst_test_sema);
+}
+
+/**
+ * \brief Tests create function against:
+ * - Valid application ID and asset ID
+ * - Invalid asset ID
+ * - Invalid application ID
+ */
+static void tfm_sst_test_1001_task(void *arg)
+{
+    const uint16_t asset_uuid = SST_ASSET_ID_X509_CERT_LARGE;
+    enum tfm_sst_err_t err;
+    uint32_t hdl;
+    struct test_result_t *ret = &transient_result;
+
+    /* Checks write permissions in create function */
+    err = tfm_sst_create(asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for Thread_C");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    err = tfm_sst_get_handle(asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls create with invalid asset ID */
+    err = tfm_sst_create(INVALID_ASSET_ID);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Create should fail for invalid ASSET ID");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls delete asset to clean up SST area for next test */
+    err = tfm_sst_delete(hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("The delete action should work correctly");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+static void tfm_sst_test_1002_task(void *arg)
+{
+    struct test_result_t *ret = &transient_result;
+    enum tfm_sst_err_t err;
+    const uint16_t asset_uuid = SST_ASSET_ID_X509_CERT_LARGE;
+    /* Calls create with invalid application ID */
+    ret->val = TEST_PASSED;
+    err = tfm_sst_create(asset_uuid);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Create should fail for thread without write permissions");
+    }
+
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+/**
+ * \brief Tests get handle function against:
+ * - Valid asset ID and not created asset
+ * - Valid asset ID and created asset
+ * - Invalid asset ID
+ */
+static void tfm_sst_test_1003_task(void *arg)
+{
+    const uint16_t asset_uuid = SST_ASSET_ID_X509_CERT_LARGE;
+    struct test_result_t *ret = &transient_result;
+    enum tfm_sst_err_t err;
+    uint32_t hdl;
+
+    /* Calls get handle before create the asset */
+    err = tfm_sst_get_handle(asset_uuid, &hdl);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should fail as the asset is not created");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_create(asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for Thread_C");
+        /* wait for the test to finish and release the semaphore */
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls get handle with a valid asset ID and the asset created */
+    err = tfm_sst_get_handle(asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        /* wait for the test to finish and release the semaphore */
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls get handle with invalid asset ID */
+    err = tfm_sst_get_handle(INVALID_ASSET_ID, &hdl);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should fail as asset hanlde is invalid");
+        /* wait for the test to finish and release the semaphore */
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls get handle with invalid handle pointer */
+    err = tfm_sst_get_handle(asset_uuid, NULL);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should fail as handle pointer is invalid");
+        /* wait for the test to finish and release the semaphore */
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls delete asset to clean up SST area for next test */
+    err = tfm_sst_delete(hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("The delete action should work correctly");
+        /* wait for the test to finish and release the semaphore */
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+    /* wait for the test to finish and release the semaphore */
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+/**
+ * \brief Tests get attributes function against:
+ * - Valid application ID, asset handle and attributes struct pointer
+ * - Invalid application ID
+ * - Invalid asset handle
+ * - Invalid attributes struct pointer
+ */
+static void tfm_sst_test_1004_task(void *arg)
+{
+    const uint16_t asset_uuid = SST_ASSET_ID_X509_CERT_LARGE;
+    struct test_result_t *ret = &transient_result;
+    struct tfm_sst_attribs_t asset_attrs;
+    enum tfm_sst_err_t err;
+    uint32_t hdl;
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_create(asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for Thread_C");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Gets asset's handle */
+    err = tfm_sst_get_handle(asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+    tfm_sst_test_1004_handle = hdl;
+
+    /* Calls get_attributes with valid application ID, asset handle and
+     * attributes struct pointer
+     */
+    err = tfm_sst_get_attributes(hdl, &asset_attrs);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Thread_C should read the attributes of this asset");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Checks attributes */
+    if (asset_attrs.size_current != 0) {
+        TEST_FAIL("Asset current size should be 0 as it is only created");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    if (asset_attrs.size_max != SST_ASSET_MAX_SIZE_X509_CERT_LARGE) {
+        TEST_FAIL("Max size of the asset is incorrect");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls get_attributes with invalid asset handle */
+    err = tfm_sst_get_attributes(0, &asset_attrs);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get attributes function should fail for an invalid "
+                  "asset handle");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls get_attributes with invalid struct attributes pointer */
+    err = tfm_sst_get_attributes(hdl, NULL);
+    if (err != TFM_SST_ERR_PARAM_ERROR) {
+        TEST_FAIL("Get attributes function should fail for an invalid "
+                  "struct attributes pointer");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls delete asset to clean up SST area for next test */
+    err = tfm_sst_delete(hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("The delete action should work correctly");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+static void tfm_sst_test_1005_task(void *arg)
+{
+    struct test_result_t *ret = &transient_result;
+    struct tfm_sst_attribs_t asset_attrs;
+    enum tfm_sst_err_t err;
+
+    ret->val = TEST_PASSED;
+    /* Calls get_attributes with invalid application ID */
+    err = tfm_sst_get_attributes(tfm_sst_test_1004_handle, &asset_attrs);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get attributes function should fail for an invalid "
+                  "application ID");
+    }
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+/**
+ * \brief Tests write function against:
+ * - Valid application ID, asset handle and data pointer
+ * - Invalid application ID
+ * - Invalid asset handle
+ * - NULL pointer as write buffer
+ * - Offet + write data size larger than max asset size
+ */
+/* handle to be shared between tasks for testing write api
+ * from non authorised task with valid handle
+ */
+static void tfm_sst_test_1006_task(void *arg)
+{
+    const uint16_t asset_uuid = SST_ASSET_ID_X509_CERT_LARGE;
+    struct test_result_t *ret = &transient_result;
+    struct tfm_sst_attribs_t asset_attrs;
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint32_t hdl;
+    uint8_t wrt_data[WRITE_BUF_SIZE] = "DATA";
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_create(asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for Thread_C");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Gets asset's handle */
+    err = tfm_sst_get_handle(asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* for the next test */
+    tfm_sst_test_1006_handle = hdl;
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = 0;
+
+    /* Write data in the asset */
+    err = tfm_sst_write(hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write should works correctly");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls get_attributes with valid application ID, asset handle and
+     * attributes struct pointer
+     */
+    err = tfm_sst_get_attributes(hdl, &asset_attrs);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Thread_C should read the attributes of this asset");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Checks attributes */
+    if (asset_attrs.size_current != WRITE_BUF_SIZE) {
+        TEST_FAIL("Asset current size should be size of the write data");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls write function with invalid asset handle */
+    err = tfm_sst_write(0, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Invalid asset handle should not write in the asset");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls write function with invalid asset handle */
+    err = tfm_sst_write(hdl, NULL);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("NULL data pointer should make the write fail");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = 1;
+    io_data.offset = SST_ASSET_MAX_SIZE_X509_CERT_LARGE;
+
+    /* Calls write function with offset + write data size larger than
+     * max asset size
+     */
+    err = tfm_sst_write(hdl, &io_data);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Offset + write data size larger than max asset size "
+                  "should make the write fail");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls delete asset to clean up SST area for next test */
+    err = tfm_sst_delete(hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("The delete action should work correctly");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+static void tfm_sst_test_1007_task(void *arg)
+{
+    struct test_result_t *ret = &transient_result;
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+
+    ret->val = TEST_PASSED;
+    /* Calls write function with invalid application ID */
+    err = tfm_sst_write(tfm_sst_test_1006_handle, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Thread_A should not write in the asset as it doesn't have"
+                  " write permissions");
+    }
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+/**
+ * \brief Tests read function against:
+ * - Valid application ID, asset handle and data pointer
+ * - Invalid application ID
+ * - Invalid asset handle
+ * - NULL pointer as write buffer
+ * - Offet + read data size larger than current asset size
+ */
+static void tfm_sst_test_1008_task(void *arg)
+{
+    const uint16_t asset_uuid = SST_ASSET_ID_X509_CERT_LARGE;
+    struct test_result_t *ret = &transient_result;
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    struct tfm_sst_attribs_t asset_attrs;
+    uint32_t hdl;
+    uint8_t wrt_data[WRITE_BUF_SIZE] = "DATA";
+    uint8_t read_data[READ_BUF_SIZE] = "XXXXXXXXXXX";
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_create(asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for Thread_C");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Gets asset's handle */
+    err = tfm_sst_get_handle(asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+    /* for next test */
+    tfm_sst_test_1008_handle = hdl;
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = 0;
+
+    /* Write data in the asset */
+    err = tfm_sst_write(hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write should work correctly");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure for read*/
+    io_data.data = read_data+3;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = 0;
+
+    /* Read data from the asset */
+    err = tfm_sst_read(hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Read should works correctly");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    if (memcmp(read_data, "XXX", 3) != 0) {
+        TEST_FAIL("Read buffer contains illegal pre-data");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    if (memcmp((read_data+3), wrt_data, WRITE_BUF_SIZE) != 0) {
+        TEST_FAIL("Read buffer has read incorrect data");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    if (memcmp((read_data+8), "XXX", 3) != 0) {
+        TEST_FAIL("Read buffer contains illegal post-data");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls read with invalid asset handle */
+    err = tfm_sst_read(0, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Read should fail when read is called with an invalid "
+                  "asset handle");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls read with invalid asset handle */
+    err = tfm_sst_read(hdl, NULL);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Read should fail when read is called with an invalid "
+                  "data pointer");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Gets current asset attributes */
+    err = tfm_sst_get_attributes(hdl, &asset_attrs);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Thread_C should read the attributes of this asset");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Checks attributes */
+    if (asset_attrs.size_current == 0) {
+        TEST_FAIL("Asset current size should be bigger than 0");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = read_data;
+    io_data.size = 1;
+    io_data.offset = asset_attrs.size_current;
+
+    /* Calls write function with offset + read data size larger than current
+     * asset size
+     */
+    err = tfm_sst_read(hdl, &io_data);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Offset + read data size larger than current asset size");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+static void tfm_sst_test_1009_task(void *arg)
+{
+    struct test_result_t *ret = &transient_result;
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint8_t read_data[READ_BUF_SIZE] = "XXXXXXXXXXX";
+
+    /* Sets data structure */
+    io_data.data = read_data;
+    io_data.size = 1;
+    io_data.offset = 0;
+
+    ret->val = TEST_PASSED;
+    /* Calls read with invalid application ID */
+    err = tfm_sst_read(tfm_sst_test_1008_handle, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Read should fail when read is called from thread without "
+                  "read permissions");
+    }
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+static void tfm_sst_test_1010_task(void *arg)
+{
+    struct test_result_t *ret = &transient_result;
+    enum tfm_sst_err_t err;
+
+    ret->val = TEST_PASSED;
+    /* Calls delete asset to clean up SST area for next test */
+    err = tfm_sst_delete(tfm_sst_test_1008_handle);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("The delete action should work correctly");
+    }
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+/**
+ * \brief Tests delete function against:
+ * - Valid application ID and asset handle
+ * - Invalid application ID
+ * - Invalid asset handle
+ * - Remove first asset in the data block and check if
+ *   next asset's data is compacted correctly.
+ */
+static void tfm_sst_test_1011_task(void *arg)
+{
+    const uint16_t asset_uuid_1 = SST_ASSET_ID_SHA224_HASH;
+    enum tfm_sst_err_t err;
+    uint32_t hdl_1;
+
+    struct test_result_t *ret = &transient_result;
+
+    ret->val = TEST_PASSED;
+    /* Creates assset 1 to get a valid handle */
+    err = tfm_sst_create(asset_uuid_1);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for Thread_B");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Gets asset 1 handle */
+    err = tfm_sst_get_handle(asset_uuid_1, &hdl_1);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls delete asset */
+    err = tfm_sst_delete(hdl_1);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("The delete action should not fail as thread has"
+                  " write permissions");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls delete with a deleted asset handle */
+    err = tfm_sst_delete(hdl_1);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("The delete action should fail as handle is not valid");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls delete asset with invalid asset handle */
+    err = tfm_sst_delete(0);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("The delete action should fail handle is not valid");
+    }
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+/**
+ * \brief Test data block compact feature.
+ *        Create asset 2 to locate it at the beginning of the block. Then,
+ *        create asset 1 to be located after asset 2. Write data on asset
+ *        1 and remove asset 2. If delete works correctly, when the code
+ *        reads back the asset 1 data, the data must be correct.
+ */
+static void tfm_sst_test_1012_part1_task(void *arg)
+{
+    const uint16_t asset_uuid_2 = SST_ASSET_ID_SHA384_HASH;
+    enum tfm_sst_err_t err;
+    uint32_t hdl_2;
+    struct test_result_t *ret = &transient_result;
+
+    ret->val = TEST_PASSED;
+
+    /* Create asset 2 first to locate it at the beginning of the data block */
+    err = tfm_sst_create(asset_uuid_2);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for Thread_C");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Gets asset 2 handle */
+    err = tfm_sst_get_handle(asset_uuid_2, &hdl_2);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+    }
+
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+static void tfm_sst_test_1012_part2_task(void *arg)
+{
+    const uint16_t asset_uuid_1 = SST_ASSET_ID_SHA224_HASH;
+    struct tfm_sst_buf_t io_data;
+    enum tfm_sst_err_t err;
+    uint32_t hdl_1;
+    uint8_t wrt_data[BUF_SIZE_SHA224] = WRITE_DATA_SHA224_1;
+    struct test_result_t *ret = &transient_result;
+
+    ret->val = TEST_PASSED;
+
+    /* Creates asset 1 handle */
+    err = tfm_sst_create(asset_uuid_1);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for Thread_B");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Gets asset 1 handle */
+    err = tfm_sst_get_handle(asset_uuid_1, &hdl_1);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = SST_ASSET_MAX_SIZE_SHA224_HASH;
+    io_data.offset = 0;
+
+    /* Calls write function  */
+    err = tfm_sst_write(hdl_1, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write should not fail for Thread_B");
+    }
+
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+static void tfm_sst_test_1012_part3_task(void *arg)
+{
+    const uint16_t asset_uuid_2 = SST_ASSET_ID_SHA384_HASH;
+    enum tfm_sst_err_t err;
+    uint32_t hdl_2;
+    struct test_result_t *ret = &transient_result;
+
+    ret->val = TEST_PASSED;
+
+    err = tfm_sst_get_handle(asset_uuid_2, &hdl_2);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls delete asset */
+    err = tfm_sst_delete(hdl_2);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("The delete action should work correctly");
+    }
+
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+static void tfm_sst_test_1012_part4_task(void *arg)
+{
+    const uint16_t asset_uuid_1 = SST_ASSET_ID_SHA224_HASH;
+    enum tfm_sst_err_t err;
+    uint32_t hdl_1;
+    struct tfm_sst_buf_t io_data;
+    uint8_t read_data[BUF_SIZE_SHA224] = READ_DATA_SHA224;
+    uint8_t wrt_data[BUF_SIZE_SHA224] = WRITE_DATA_SHA224_1;
+    struct test_result_t *ret = &transient_result;
+
+    ret->val = TEST_PASSED;
+    err = tfm_sst_get_handle(asset_uuid_1, &hdl_1);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = read_data;
+    io_data.size = SST_ASSET_MAX_SIZE_SHA224_HASH;
+    io_data.offset = 0;
+
+    err = tfm_sst_read(hdl_1, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Read should not fail for Thread_B");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    if (memcmp(read_data, wrt_data, BUF_SIZE_SHA224) != 0) {
+        TEST_FAIL("Read buffer has incorrect data");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls delete asset */
+    err = tfm_sst_delete(hdl_1);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("The delete action should work correctly");
+    }
+
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+/**
+ * \brief Tests write and partial reads.
+ */
+static void tfm_sst_test_1013_task(void *arg)
+{
+    const uint16_t asset_uuid = SST_ASSET_ID_X509_CERT_LARGE;
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint32_t hdl;
+    struct test_result_t *ret = &transient_result;
+    uint32_t i;
+    uint8_t read_data[READ_BUF_SIZE] = "XXXXXXXXXXX";
+    uint8_t wrt_data[WRITE_BUF_SIZE] = "DATA";
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_create(asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for Thread_C");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Gets asset's handle */
+    err = tfm_sst_get_handle(asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = 0;
+
+    /* Write data in the asset */
+    err = tfm_sst_write(hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write should works correctly");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure for read*/
+    io_data.data = (read_data + 3);
+    io_data.size = 1;
+    io_data.offset = 0;
+
+    for (i = 0; i < WRITE_BUF_SIZE; i++) {
+        /* Read data from the asset */
+        err = tfm_sst_read(hdl, &io_data);
+        if (err != TFM_SST_ERR_SUCCESS) {
+            TEST_FAIL("Read should works correctly");
+            os_wrapper_semaphore_release(tfm_sst_test_sema);
+            return;
+        }
+
+        /* Increases data pointer and offset */
+        io_data.data++;
+        io_data.offset++;
+    }
+
+    if (memcmp(read_data, "XXX", 3) != 0) {
+        TEST_FAIL("Read buffer contains illegal pre-data");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    if (memcmp((read_data + 3), wrt_data, WRITE_BUF_SIZE) != 0) {
+        TEST_FAIL("Read buffer has read incorrect data");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    if (memcmp((read_data + 8), "XXX", 3) != 0) {
+        TEST_FAIL("Read buffer contains illegal post-data");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls delete asset */
+    err = tfm_sst_delete(hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("The delete action should work correctly");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+/**
+ * \brief Tests write function against a write call where data size is
+ *        bigger than the maximum assert size.
+ */
+static void tfm_sst_test_1014_task(void *arg)
+{
+    const uint16_t asset_uuid = SST_ASSET_ID_SHA224_HASH;
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint32_t hdl;
+    struct test_result_t *ret = &transient_result;
+    uint8_t wrt_data[BUF_SIZE_SHA224] = {0};
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_create(asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for Thread_B");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Gets asset's handle */
+    err = tfm_sst_get_handle(asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = SST_ASSET_MAX_SIZE_SHA224_HASH + 1;
+    io_data.offset = 0;
+
+    /* Write data in the asset */
+    err = tfm_sst_write(hdl, &io_data);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Should have failed asset write of too large");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls delete asset */
+    err = tfm_sst_delete(hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("The delete action should work correctly");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+/**
+ * \brief Tests write function against multiple writes.
+ */
+static void tfm_sst_test_1015_task(void *arg)
+{
+    const uint16_t asset_uuid = SST_ASSET_ID_SHA224_HASH;
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint32_t hdl;
+    uint8_t read_data[READ_BUF_SIZE]  = "XXXXXXXXXXX";
+    uint8_t wrt_data[WRITE_BUF_SIZE+1]  = "Hello";
+    uint8_t wrt_data2[WRITE_BUF_SIZE+1] = "World";
+    struct test_result_t *ret = &transient_result;
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_create(asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for Thread_B");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Gets asset's handle */
+    err = tfm_sst_get_handle(asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = 0;
+
+    /* Write data in the asset */
+    err = tfm_sst_write(hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data 1 failed");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data2;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = WRITE_BUF_SIZE;
+
+    /* Write data 2 in the asset */
+    err = tfm_sst_write(hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data 2 failed");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = read_data;
+    io_data.size = WRITE_BUF_SIZE * 2;
+    io_data.offset = 0;
+
+    /* Read back the data */
+    err = tfm_sst_read(hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Incorrect number of bytes read back");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    if (memcmp(read_data, "HelloWorldX", READ_BUF_SIZE) != 0) {
+        TEST_FAIL("Read buffer has read incorrect data");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls delete asset */
+    err = tfm_sst_delete(hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("The delete action should work correctly");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+/**
+ * \brief Tests write function against multiple writes until the end of asset.
+ */
+static void tfm_sst_test_1016_task(void *arg)
+{
+    const uint16_t asset_uuid = SST_ASSET_ID_SHA224_HASH;
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint32_t hdl;
+    uint8_t read_data[BUF_SIZE_SHA224] = READ_DATA_SHA224;
+    uint8_t wrt_data[BUF_SIZE_SHA224] = WRITE_DATA_SHA224_1;
+    uint8_t wrt_data2[BUF_SIZE_SHA224] = WRITE_DATA_SHA224_2;
+    struct test_result_t *ret = &transient_result;
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_create(asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for Thread_B");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Gets asset's handle */
+    err = tfm_sst_get_handle(asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = 0;
+
+    /* Write data in the asset */
+    err = tfm_sst_write(hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data 1 failed");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data2;
+    io_data.size = (SST_ASSET_MAX_SIZE_SHA224_HASH - WRITE_BUF_SIZE) + 1;
+    io_data.offset = WRITE_BUF_SIZE;
+
+    /* Write data in the asset */
+    err = tfm_sst_write(hdl, &io_data);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data 2 should have failed as this write tries to "
+                  "write more bytes that the max size");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data + WRITE_BUF_SIZE;
+    io_data.size = SST_ASSET_MAX_SIZE_SHA224_HASH - WRITE_BUF_SIZE;
+    io_data.offset = WRITE_BUF_SIZE;
+
+    /* Write data in the asset */
+    err = tfm_sst_write(hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data 3 failed");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = read_data;
+    io_data.size = SST_ASSET_MAX_SIZE_SHA224_HASH;
+    io_data.offset = 0;
+
+    /* Read back the data */
+    err = tfm_sst_read(hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Incorrect number of bytes read back");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    if (memcmp(read_data, wrt_data, BUF_SIZE_SHA224) != 0) {
+        TEST_FAIL("Read buffer has read incorrect data");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls delete asset */
+    err = tfm_sst_delete(hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("The delete action should work correctly");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+/**
+ * \brief Tests write and read to/from 2 assets.
+ */
+static void tfm_sst_test_1017_part1_task(void *arg)
+{
+    const uint16_t asset_uuid_1 = SST_ASSET_ID_X509_CERT_LARGE;
+    enum tfm_sst_err_t err;
+    uint32_t hdl_1;
+
+    struct test_result_t *ret = &transient_result;
+
+    /* Creates asset 1 to get a valid handle */
+    err = tfm_sst_create(asset_uuid_1);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for Thread_C");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Gets asset's handle 1 */
+    err = tfm_sst_get_handle(asset_uuid_1, &hdl_1);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    tfm_sst_test_1017_asset1_handle = hdl_1;
+    ret->val = TEST_PASSED;
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+static void tfm_sst_test_1017_part2_task(void *arg)
+{
+    const uint16_t asset_uuid_2 = SST_ASSET_ID_SHA224_HASH;
+    enum tfm_sst_err_t err;
+    uint32_t hdl_2;
+    struct test_result_t *ret = &transient_result;
+
+    /* Creates asset 2 to get a valid handle */
+    err = tfm_sst_create(asset_uuid_2);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for Thread_B");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Gets asset's handle 2*/
+    err = tfm_sst_get_handle(asset_uuid_2, &hdl_2);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    tfm_sst_test_1017_asset2_handle = hdl_2;
+
+    ret->val = TEST_PASSED;
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+static void tfm_sst_test_1017_part3_task(void *arg)
+{
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint8_t wrt_data[WRITE_BUF_SIZE+1]  = "Hello";
+    struct test_result_t *ret = &transient_result;
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = 0;
+
+    /* Write data in asset 1 */
+    err = tfm_sst_write(tfm_sst_test_1017_asset1_handle, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data should work for Thread_C");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+static void tfm_sst_test_1017_part4_task(void *arg)
+{
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint8_t wrt_data2[3] = "Hi";
+    struct test_result_t *ret = &transient_result;
+
+    /* Write data 2 in asset 2 */
+    /* Sets data structure */
+    io_data.data = wrt_data2;
+    io_data.size = 2;
+    io_data.offset = 0;
+
+    err = tfm_sst_write(tfm_sst_test_1017_asset2_handle, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data should work for Thread_B");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+static void tfm_sst_test_1017_part5_task(void *arg)
+{
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint8_t wrt_data3[WRITE_BUF_SIZE+1] = "World";
+    struct test_result_t *ret = &transient_result;
+
+    /* Sets data structure */
+    io_data.data = wrt_data3;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = WRITE_BUF_SIZE;
+
+    /* Write data 3 in asset 1 */
+    err = tfm_sst_write(tfm_sst_test_1017_asset1_handle, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data should work for Thread_C");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+    ret->val = TEST_PASSED;
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+static void tfm_sst_test_1017_part6_task(void *arg)
+{
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint8_t wrt_data4[WRITE_BUF_SIZE+1] = "12345";
+    struct test_result_t *ret = &transient_result;
+
+    /* Sets data structure */
+    io_data.data = wrt_data4;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = 2;
+
+    /* Write data 4 in asset 2 */
+    err = tfm_sst_write(tfm_sst_test_1017_asset2_handle, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data should work for Thread_B");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+static void tfm_sst_test_1017_part7_task(void *arg)
+{
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint8_t read_data[READ_BUF_SIZE]  = "XXXXXXXXXXX";
+    struct test_result_t *ret = &transient_result;
+
+    /* Sets data structure */
+    io_data.data = read_data;
+    /* size of wrt_data + wrt_data3 */
+    io_data.size = WRITE_BUF_SIZE + WRITE_BUF_SIZE;
+    io_data.offset = 0;
+
+    /* Read back the asset 1 */
+    err = tfm_sst_read(tfm_sst_test_1017_asset1_handle, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Read should not fail for Thread_C");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    if (memcmp(read_data, "HelloWorldX", READ_BUF_SIZE) != 0) {
+        TEST_FAIL("Read buffer has incorrect data");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+static void tfm_sst_test_1017_part8_task(void *arg)
+{
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint8_t read_data[READ_BUF_SIZE]  = "XXXXXXXXXXX";
+    struct test_result_t *ret = &transient_result;
+
+    /* Sets data structure */
+    io_data.data = read_data;
+    io_data.size = 2 + WRITE_BUF_SIZE; /* size of wrt_data2 + wrt_data4 */
+    io_data.offset = 0;
+
+    /* Read back the asset 1 */
+    err = tfm_sst_read(tfm_sst_test_1017_asset2_handle, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Incorrect number of bytes read back");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    if (memcmp(read_data, "Hi12345XXXX", READ_BUF_SIZE) != 0) {
+        TEST_FAIL("Read buffer has incorrect data");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls delete asset */
+    err = tfm_sst_delete(tfm_sst_test_1017_asset2_handle);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("The delete action should work correctly");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+static void tfm_sst_test_1017_part9_task(void *arg)
+{
+    enum tfm_sst_err_t err;
+    struct test_result_t *ret = &transient_result;
+
+    /* Calls delete asset 1 */
+    err = tfm_sst_delete(tfm_sst_test_1017_asset1_handle);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("The delete action should work correctly");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+/**
+ * \brief Tests write and read to/from the follow illegal locations:
+ * - ROM memory
+ * - Device memory
+ * - Secure memory
+ * - Non existing memory location
+ */
+static void tfm_sst_test_1018_task(void *arg)
+{
+    const uint16_t asset_uuid = SST_ASSET_ID_SHA224_HASH;
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+
+    uint32_t hdl;
+    struct test_result_t *ret = &transient_result;
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_create(asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for Thread_B");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Gets asset's handle */
+    err = tfm_sst_get_handle(asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /*** Check functions against ROM address location ***/
+
+    /* Gets asset's handle with a ROM address location to store asset's
+     * handle
+     */
+    err = tfm_sst_get_handle(asset_uuid, (uint32_t *)ROM_ADDR_LOCATION);
+    if (err != TFM_SST_ERR_PARAM_ERROR) {
+        TEST_FAIL("Get handle should fail for an illegal location");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = (uint8_t *)ROM_ADDR_LOCATION;
+    io_data.size = 1;
+    io_data.offset = 0;
+
+    /* Calls write with a ROM address location */
+    err = tfm_sst_write(hdl, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Write should fail for an illegal location");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls read with a ROM address location */
+    err = tfm_sst_read(hdl, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Read should fail for an illegal location");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /*** Check functions against devices address location ***/
+
+    /* Gets asset's handle with a devices address location to store asset's
+     * handle
+     */
+    err = tfm_sst_get_handle(asset_uuid, (uint32_t *)DEV_ADDR_LOCATION);
+    if (err != TFM_SST_ERR_PARAM_ERROR) {
+        TEST_FAIL("Get handle should fail for an illegal location");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = (uint8_t *)DEV_ADDR_LOCATION;
+
+    /* Calls write with a device address location */
+    err = tfm_sst_write(hdl, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Write should fail for an illegal location");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls read with a device address location */
+    err = tfm_sst_read(hdl, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Read should fail for an illegal location");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /*** Check functions against secure address location ***/
+
+    /* Gets asset's handle with a secure address location to store asset's
+     * handle
+     */
+    err = tfm_sst_get_handle(asset_uuid,
+                             (uint32_t *)SECURE_ADDR_LOCATION);
+    if (err != TFM_SST_ERR_PARAM_ERROR) {
+        TEST_FAIL("Get handle should fail for an illegal location");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = (uint8_t *)SECURE_ADDR_LOCATION;
+
+    /* Calls write with a secure address location */
+    err = tfm_sst_write(hdl, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Write should fail for an illegal location");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls read with a secure address location */
+    err = tfm_sst_read(hdl, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Read should fail for an illegal location");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /*** Check functions against non existing address location ***/
+
+    /* Gets asset's handle with a non existing address location to store asset's
+     * handle
+     */
+    err = tfm_sst_get_handle(asset_uuid,
+                             (uint32_t *)NON_EXIST_ADDR_LOCATION);
+    if (err != TFM_SST_ERR_PARAM_ERROR) {
+        TEST_FAIL("Get handle should fail for an illegal location");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = (uint8_t *)NON_EXIST_ADDR_LOCATION;
+
+    /* Calls write with a non-existing address location */
+    err = tfm_sst_write(hdl, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Write should fail for an illegal location");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    /* Calls read with a non-existing address location */
+    err = tfm_sst_read(hdl, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Read should fail for an illegal location");
+        os_wrapper_semaphore_release(tfm_sst_test_sema);
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+    os_wrapper_semaphore_release(tfm_sst_test_sema);
+}
+
+static void tfm_sst_test_1001(struct test_result_t *ret)
+{
+    tfm_sst_run_test("Thread_C", ret,
+                     tfm_sst_test_1001_task);
+}
+
+static void tfm_sst_test_1002(struct test_result_t *ret)
+{
+    tfm_sst_run_test("Thread_A", ret,
+                     tfm_sst_test_1002_task);
+}
+
+static void tfm_sst_test_1003(struct test_result_t *ret)
+{
+    tfm_sst_run_test("Thread_C", ret,
+                     tfm_sst_test_1003_task);
+}
+
+static void tfm_sst_test_1004(struct test_result_t *ret)
+{
+    tfm_sst_run_test("Thread_C", ret,
+                     tfm_sst_test_1004_task);
+}
+
+static void tfm_sst_test_1005(struct test_result_t *ret)
+{
+    tfm_sst_run_test("Thread_INVALID", ret,
+                     tfm_sst_test_1005_task);
+}
+
+static void tfm_sst_test_1006(struct test_result_t *ret)
+{
+    tfm_sst_run_test("Thread_C", ret,
+                     tfm_sst_test_1006_task);
+}
+
+static void tfm_sst_test_1007(struct test_result_t *ret)
+{
+    tfm_sst_run_test("Thread_A", ret,
+                     tfm_sst_test_1007_task);
+}
+
+static void tfm_sst_test_1008(struct test_result_t *ret)
+{
+    tfm_sst_run_test("Thread_C", ret,
+                     tfm_sst_test_1008_task);
+}
+
+static void tfm_sst_test_1009(struct test_result_t *ret)
+{
+    tfm_sst_run_test("Thread_A", ret,
+                     tfm_sst_test_1009_task);
+}
+
+static void tfm_sst_test_1010(struct test_result_t *ret)
+{
+    tfm_sst_run_test("Thread_C", ret,
+                     tfm_sst_test_1010_task);
+}
+
+static void tfm_sst_test_1011(struct test_result_t *ret)
+{
+    tfm_sst_run_test("Thread_B", ret,
+                     tfm_sst_test_1011_task);
+}
+
+static void tfm_sst_test_1012(struct test_result_t *ret)
+{
+    tfm_sst_run_test("Thread_C", ret,
+                     tfm_sst_test_1012_part1_task);
+    if (ret->val != TEST_PASSED) {
+        return;
+    }
+    tfm_sst_run_test("Thread_B", ret,
+                     tfm_sst_test_1012_part2_task);
+    if (ret->val != TEST_PASSED) {
+        return;
+    }
+    tfm_sst_run_test("Thread_C", ret,
+                     tfm_sst_test_1012_part3_task);
+    if (ret->val != TEST_PASSED) {
+        return;
+    }
+    tfm_sst_run_test("Thread_B", ret,
+                     tfm_sst_test_1012_part4_task);
+}
+
+static void tfm_sst_test_1013(struct test_result_t *ret)
+{
+    tfm_sst_run_test("Thread_C", ret,
+                     tfm_sst_test_1013_task);
+}
+
+static void tfm_sst_test_1014(struct test_result_t *ret)
+{
+    tfm_sst_run_test("Thread_B", ret,
+                     tfm_sst_test_1014_task);
+}
+
+static void tfm_sst_test_1015(struct test_result_t *ret)
+{
+    tfm_sst_run_test("Thread_B", ret,
+                     tfm_sst_test_1015_task);
+}
+
+static void tfm_sst_test_1016(struct test_result_t *ret)
+{
+    tfm_sst_run_test("Thread_B", ret,
+                     tfm_sst_test_1016_task);
+}
+
+static void tfm_sst_test_1017(struct test_result_t *ret)
+{
+    tfm_sst_run_test("Thread_C", ret,
+                     tfm_sst_test_1017_part1_task);
+    if (ret->val != TEST_PASSED) {
+        return;
+    }
+
+    tfm_sst_run_test("Thread_B", ret,
+                     tfm_sst_test_1017_part2_task);
+    if (ret->val != TEST_PASSED) {
+        return;
+    }
+
+    tfm_sst_run_test("Thread_C", ret,
+                     tfm_sst_test_1017_part3_task);
+    if (ret->val != TEST_PASSED) {
+        return;
+    }
+
+    tfm_sst_run_test("Thread_B", ret,
+                     tfm_sst_test_1017_part4_task);
+    if (ret->val != TEST_PASSED) {
+        return;
+    }
+
+    tfm_sst_run_test("Thread_C", ret,
+                     tfm_sst_test_1017_part5_task);
+    if (ret->val != TEST_PASSED) {
+        return;
+    }
+
+    tfm_sst_run_test("Thread_B", ret,
+                     tfm_sst_test_1017_part6_task);
+    if (ret->val != TEST_PASSED) {
+        return;
+    }
+
+    tfm_sst_run_test("Thread_C", ret,
+                     tfm_sst_test_1017_part7_task);
+    if (ret->val != TEST_PASSED) {
+        return;
+    }
+
+    tfm_sst_run_test("Thread_B", ret,
+                     tfm_sst_test_1017_part8_task);
+    if (ret->val != TEST_PASSED) {
+        return;
+    }
+
+    tfm_sst_run_test("Thread_C", ret,
+                     tfm_sst_test_1017_part9_task);
+    if (ret->val != TEST_PASSED) {
+        return;
+    }
+
+}
+
+static void tfm_sst_test_1018(struct test_result_t *ret)
+{
+    tfm_sst_run_test("Thread_B", ret,
+                     tfm_sst_test_1018_task);
+}
diff --git a/test/suites/sst/non_secure/sst_ns_tests.h b/test/suites/sst/non_secure/sst_ns_tests.h
new file mode 100644
index 0000000..df99a71
--- /dev/null
+++ b/test/suites/sst/non_secure/sst_ns_tests.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __SST_NS_TESTS_H__
+#define __SST_NS_TESTS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "test/framework/test_framework.h"
+
+/**
+ * \brief Register testsuite for the SST tests.
+ *
+ * \param[in] p_test_suite  The test suite to be executed.
+ */
+void register_testsuite_ns_sst_interface(struct test_suite_t *p_test_suite);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SST_NS_TESTS_H__ */
diff --git a/test/suites/sst/secure/s_test_helpers.c b/test/suites/sst/secure/s_test_helpers.c
new file mode 100755
index 0000000..e001885
--- /dev/null
+++ b/test/suites/sst/secure/s_test_helpers.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "s_test_helpers.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "test/framework/test_framework.h"
+#include "secure_fw/services/secure_storage/sst_core_interface.h"
+
+uint32_t prepare_test_ctx(struct test_result_t *ret)
+{
+    /* Wipes secure storage area */
+    sst_object_wipe_all();
+
+    /* Prepares secure storage area before write */
+    if (sst_object_prepare() != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Wiped system should be preparable");
+        return 1;
+    }
+
+    return 0;
+}
diff --git a/test/suites/sst/secure/s_test_helpers.h b/test/suites/sst/secure/s_test_helpers.h
new file mode 100755
index 0000000..4ae531b
--- /dev/null
+++ b/test/suites/sst/secure/s_test_helpers.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __S_TEST_HELPERS_H__
+#define __S_TEST_HELPERS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "test/framework/test_framework.h"
+
+/**
+ * \brief Prepares secure storage area for the new tests. It executes wipes and
+ *        prepare.
+ *
+ * \param[out] ret  Pointer to the test result structure.
+ *
+ * \return 0 if the context is correcly prepared. Otherwise 1.
+ */
+uint32_t prepare_test_ctx(struct test_result_t *ret);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __S_TEST_HELPERS_H__ */
diff --git a/test/suites/sst/secure/sst_policy_testsuite.c b/test/suites/sst/secure/sst_policy_testsuite.c
new file mode 100644
index 0000000..8611d0a
--- /dev/null
+++ b/test/suites/sst/secure/sst_policy_testsuite.c
@@ -0,0 +1,676 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "sst_tests.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "test/framework/helpers.h"
+#include "secure_fw/services/secure_storage/assets/sst_asset_defs.h"
+#include "tfm_sst_defs.h"
+#include "secure_fw/services/secure_storage/sst_core_interface.h"
+#include "tfm_sst_veneers.h"
+#include "s_test_helpers.h"
+
+/* Test suite defines */
+#define INVALID_ASSET_ID           0
+#define READ_BUF_SIZE             12UL
+#define WRITE_BUF_SIZE             5UL
+
+/*
+ * Summary of tests covered by the test suite:
+ * - read/write to an asset with READ/WRITE permission
+ * - read/write to an asset when the application doesn't have any
+ *   permission (NONE)
+ * - read/write to an asset when the application has REFERENCE permission
+ * - write to an asset when the application has REFERENCE/READ permission
+ * - read to an asset when the application has REFERENCE/WRITE permission
+ * - read attributes to an asset when the application has REFERENCE permission
+ */
+/* Define test suite for secure side veneer i/f tests */
+/* List of tests */
+static void tfm_sst_test_4001(struct test_result_t *ret);
+static void tfm_sst_test_4002(struct test_result_t *ret);
+static void tfm_sst_test_4003(struct test_result_t *ret);
+
+static struct test_t interface_tests[] = {
+    {&tfm_sst_test_4001, "TFM_SST_TEST_4001",
+     "Check policy against large asset 1", {0} },
+    {&tfm_sst_test_4002, "TFM_SST_TEST_4002",
+     "Check policy against small asset 1", {0} },
+    {&tfm_sst_test_4003, "TFM_SST_TEST_4003",
+     "Check policy against small asset 2", {0} },
+};
+
+void register_testsuite_s_sst_interface(struct test_suite_t *p_test_suite)
+{
+    uint32_t list_size = (sizeof(interface_tests) / sizeof(interface_tests[0]));
+
+    set_testsuite("SST policy tests (TFM_SST_TEST_4XXX)",
+                  interface_tests, list_size, p_test_suite);
+}
+
+/**
+ * \brief Tests policy against SST_ASSET_ID_X509_CERT_LARGE with the following
+ *        permissions
+ *        APP_ID       | Permissions
+ *        -------------------------------------
+ *        S_APP_ID | REFERENCE
+ *        S_APP_ID | REFERENCE, READ
+ *        S_APP_ID | REFERENCE, READ, WRITE
+ */
+static void tfm_sst_test_4001(struct test_result_t *ret)
+{
+    uint32_t hdl;
+    uint32_t app_id;
+    const uint16_t asset_uuid = SST_ASSET_ID_X509_CERT_LARGE;
+    struct tfm_sst_attribs_t asset_attrs = {0};
+    struct tfm_sst_buf_t data;
+    enum tfm_sst_err_t err;
+    uint8_t wrt_data[WRITE_BUF_SIZE] = "DATA";
+    uint8_t read_data[READ_BUF_SIZE] = "XXXXXXXXXXX";
+
+    /* Prepares test context */
+    if (prepare_test_ctx(ret) != 0) {
+        return;
+    }
+
+    /* Sets application ID S_APP_ID and check its permissions
+     * (REFERENCE, READ, WRITE)
+     */
+    app_id = S_APP_ID;
+
+    /* Checks write permissions in create function */
+    err = tfm_sst_veneer_create(app_id, asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should not fail");
+        return;
+    }
+
+    /* Sets data structure */
+    data.data = wrt_data;
+    data.size = WRITE_BUF_SIZE;
+    data.offset = 0;
+
+    /* Checks write permissions in the write function */
+    err = tfm_sst_veneer_write(app_id, hdl, &data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Sets data structure */
+    data.data = read_data;
+    data.size = WRITE_BUF_SIZE;
+    data.offset = 0;
+
+    /* Checks write permissions in the read function */
+    err = tfm_sst_veneer_read(app_id, hdl, &data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Read should not fail for application S_APP_ID");
+        return;
+    }
+
+    if (memcmp(read_data, "DATA", WRITE_BUF_SIZE) != 0) {
+        TEST_FAIL("Read buffer contains incorrect data");
+        return;
+    }
+
+    /* Gets asset's attributes. It should succeed as the app ID has REFERENCE
+     * permissions.
+     */
+    err = tfm_sst_veneer_get_attributes(app_id, hdl, &asset_attrs);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Application S_APP_ID should read the attributes of this "
+                  "file");
+        return;
+    }
+
+    /* Checks attributes */
+    if (asset_attrs.size_current != WRITE_BUF_SIZE) {
+        TEST_FAIL("Asset current size should be write buffer size");
+        return;
+    }
+
+    if (asset_attrs.size_max != SST_ASSET_MAX_SIZE_X509_CERT_LARGE) {
+        TEST_FAIL("Max size of the asset is incorrect");
+        return;
+    }
+
+    /* Sets application ID S_APP_ID and check its permissions (REFERENCE) */
+    app_id = S_APP_ID;
+
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should not fail");
+        return;
+    }
+
+    /* Sets data structure */
+    data.data = wrt_data;
+    data.size = WRITE_BUF_SIZE;
+    data.offset = 0;
+
+    /* Checks write permissions in the write function */
+    err = tfm_sst_veneer_write(app_id, hdl, &data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Application S_APP_ID is not allowed to write into this "
+                  "file");
+        return;
+    }
+
+    /* Sets data structure */
+    data.data = read_data;
+    data.size = WRITE_BUF_SIZE;
+    data.offset = 0;
+
+    /* Checks write permissions in the read function */
+    err = tfm_sst_veneer_read(app_id, hdl, &data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Application S_APP_ID is not allowed to read this file");
+        return;
+    }
+
+    /* Resets asset attributes structure values*/
+    asset_attrs.size_current = 0;
+    asset_attrs.size_max = 0;
+
+    /* Gets asset's attributes. It should succeed as the app ID has REFERENCE
+     * permissions.
+     */
+    err = tfm_sst_veneer_get_attributes(app_id, hdl, &asset_attrs);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Application S_APP_ID should read the attributes of this "
+                  "file");
+        return;
+    }
+
+    /* Checks attributes */
+    if (asset_attrs.size_current != WRITE_BUF_SIZE) {
+        TEST_FAIL("Asset current size should be write buffer size");
+        return;
+    }
+
+    if (asset_attrs.size_max != SST_ASSET_MAX_SIZE_X509_CERT_LARGE) {
+        TEST_FAIL("Max size of the asset is incorrect");
+        return;
+    }
+
+    /* Sets application ID S_APP_ID and check its permissions
+     * (REFERENCE, READ)
+     */
+    app_id = S_APP_ID;
+
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should not fail");
+        return;
+    }
+
+    /* Sets data structure */
+    data.data = wrt_data;
+    data.size = WRITE_BUF_SIZE;
+    data.offset = 0;
+
+    /* Checks write permissions in the write function */
+    err = tfm_sst_veneer_write(app_id, hdl, &data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Application S_APP_ID is not allowed to write into this "
+                  "file");
+        return;
+    }
+
+    /* Sets data structure */
+    data.data = read_data;
+    data.size = WRITE_BUF_SIZE;
+    data.offset = 0;
+
+    /* Resets read data contain */
+    memset(read_data, 'X', READ_BUF_SIZE);
+
+    /* Checks write permissions in the write function */
+    err = tfm_sst_veneer_read(app_id, hdl, &data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Application S_APP_ID is allowed to read this file");
+        return;
+    }
+
+    if (memcmp(read_data, "DATA", WRITE_BUF_SIZE) != 0) {
+        TEST_FAIL("Read buffer contains incorrect data");
+        return;
+    }
+
+    /* Resets asset attributes structure values*/
+    asset_attrs.size_current = 0;
+    asset_attrs.size_max = 0;
+
+    /* Gets asset's attributes. It should succeed as the app ID has REFERENCE
+     * permissions.
+     */
+    err = tfm_sst_veneer_get_attributes(app_id, hdl, &asset_attrs);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Application S_APP_ID should read the attributes of this "
+                  "file");
+        return;
+    }
+
+    /* Checks attributes */
+    if (asset_attrs.size_current != WRITE_BUF_SIZE) {
+        TEST_FAIL("Asset current size should be write buffer size");
+        return;
+    }
+
+    if (asset_attrs.size_max != SST_ASSET_MAX_SIZE_X509_CERT_LARGE) {
+        TEST_FAIL("Max size of the asset is incorrect");
+        return;
+    }
+
+    /* Sets application ID S_APP_ID and check its permissions to delete */
+    app_id = S_APP_ID;
+
+    /* Checks write permissions in delete function*/
+    err = tfm_sst_veneer_delete(app_id, hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Delete should not fail for application S_APP_ID");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Tests policy against SST_ASSET_ID_SHA224_HASH with the following
+ *        permissions
+ *        APP_ID       | Permissions
+ *        -------------------------------------
+ *        S_APP_ID | NONE
+ *        S_APP_ID | REFERENCE, READ, WRITE
+ *        S_APP_ID | NONE
+ */
+static void tfm_sst_test_4002(struct test_result_t *ret)
+{
+    uint32_t hdl;
+    uint32_t tmp_hdl = 0;
+    uint32_t app_id;
+    const uint16_t asset_uuid = SST_ASSET_ID_SHA224_HASH;
+    struct tfm_sst_attribs_t asset_attrs = {0};
+    struct tfm_sst_buf_t data;
+    enum tfm_sst_err_t err;
+    uint8_t wrt_data[WRITE_BUF_SIZE] = "DATA";
+    uint8_t read_data[READ_BUF_SIZE] = "XXXXXXXXXXX";
+
+    /* Prepares test context */
+    if (prepare_test_ctx(ret) != 0) {
+        return;
+    }
+
+    /* Sets application ID S_APP_ID and check its permissions
+     * (REFERENCE, READ, WRITE)
+     */
+    app_id = S_APP_ID;
+
+    /* Checks write permissions in create function*/
+    err = tfm_sst_veneer_create(app_id, asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should not fail");
+        return;
+    }
+
+    /* Sets data structure */
+    data.data = wrt_data;
+    data.size = WRITE_BUF_SIZE;
+    data.offset = 0;
+
+    /* Checks write permissions in the write function */
+    err = tfm_sst_veneer_write(app_id, hdl, &data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Sets data structure */
+    data.data = read_data;
+    data.size = WRITE_BUF_SIZE;
+    data.offset = 0;
+
+    /* Checks write permissions in the read function */
+    err = tfm_sst_veneer_read(app_id, hdl, &data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Read should not fail for application S_APP_ID");
+        return;
+    }
+
+    if (memcmp(read_data, "DATA", WRITE_BUF_SIZE) != 0) {
+        TEST_FAIL("Read buffer contains incorrect data");
+        return;
+    }
+
+    /* Gets asset's attributes. It should succeed as the app ID has REFERENCE
+     * permissions.
+     */
+    err = tfm_sst_veneer_get_attributes(app_id, hdl, &asset_attrs);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Application S_APP_ID should read the attributes of this "
+                  "file");
+        return;
+    }
+
+    /* Checks attributes */
+    if (asset_attrs.size_current != WRITE_BUF_SIZE) {
+        TEST_FAIL("Asset current size should be write buffer size");
+        return;
+    }
+
+    if (asset_attrs.size_max != SST_ASSET_MAX_SIZE_SHA224_HASH) {
+        TEST_FAIL("Max size of the asset is incorrect");
+        return;
+    }
+
+    /* Sets application ID S_APP_ID and check its permissions (NONE) */
+    app_id = S_APP_ID;
+
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &tmp_hdl);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Get handle should fail");
+        return;
+    }
+
+    /* Sets data structure */
+    data.data = wrt_data;
+    data.size = WRITE_BUF_SIZE;
+    data.offset = 0;
+
+    /* Checks write permissions in the write function */
+    err = tfm_sst_veneer_write(app_id, hdl, &data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Application S_APP_ID is not allowed to write into this "
+                  "file");
+        return;
+    }
+
+    /* Sets data structure */
+    data.data = read_data;
+    data.size = WRITE_BUF_SIZE;
+    data.offset = 0;
+
+    /* Checks write permissions in the read function */
+    err = tfm_sst_veneer_read(app_id, hdl, &data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Application S_APP_ID is not allowed to read this file");
+        return;
+    }
+
+    /* Gets asset's attributes. It should fail as the app ID doesn't have
+     * REFERENCE permissions.
+     */
+    err = tfm_sst_veneer_get_attributes(app_id, hdl, &asset_attrs);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Application S_APP_ID should not be able to read the "
+                  "attributes of this file as it doesn't have permissions");
+        return;
+    }
+
+    /* Sets application ID S_APP_ID and check its permissions (NONE) */
+    app_id = S_APP_ID;
+
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &tmp_hdl);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Get handle should fail");
+        return;
+    }
+
+    /* Sets data structure */
+    data.data = wrt_data;
+    data.size = WRITE_BUF_SIZE;
+    data.offset = 0;
+
+    /* Checks write permissions in the write function */
+    err = tfm_sst_veneer_write(app_id, hdl, &data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Application S_APP_ID is not allowed to write into this "
+                  "file");
+        return;
+    }
+
+    /* Sets data structure */
+    data.data = read_data;
+    data.size = WRITE_BUF_SIZE;
+    data.offset = 0;
+
+    /* Checks write permissions in the read function */
+    err = tfm_sst_veneer_read(app_id, hdl, &data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Application S_APP_ID is not allowed to read this file");
+        return;
+    }
+
+    /* Gets asset's attributes. It should fail as the app ID doesn't have
+     * REFERENCE permissions.
+     */
+    err = tfm_sst_veneer_get_attributes(app_id, hdl, &asset_attrs);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Application S_APP_ID should not be able to read the "
+                  "attributes of this file as it doesn't have permissions");
+        return;
+    }
+
+    /* Sets application ID S_APP_ID and check its permissions to delete */
+    app_id = S_APP_ID;
+
+    /* Checks write permissions in delete function*/
+    err = tfm_sst_veneer_delete(app_id, hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Delete should not fail for application S_APP_ID");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Tests policy against SST_ASSET_ID_SHA384_HASH with the following
+ *        permissions
+ *        APP_ID       | Permissions
+ *        -------------------------------
+ *        S_APP_ID | NONE
+ *        S_APP_ID | NONE
+ *        S_APP_ID | REFERENCE, WRITE
+ */
+static void tfm_sst_test_4003(struct test_result_t *ret)
+{
+
+    uint32_t app_id;
+    const uint16_t asset_uuid = SST_ASSET_ID_SHA384_HASH;
+    struct tfm_sst_attribs_t asset_attrs = {0};
+    struct tfm_sst_buf_t data;
+    enum tfm_sst_err_t err;
+    uint32_t hdl;
+    uint32_t tmp_hdl;
+    uint8_t wrt_data[WRITE_BUF_SIZE] = "DATA";
+    uint8_t read_data[READ_BUF_SIZE] = "XXXXXXXXXXX";
+
+    /* Prepares test context */
+    if (prepare_test_ctx(ret) != 0) {
+        return;
+    }
+
+    /* Sets application ID S_APP_ID and check its permissions
+     * (REFERENCE, WRITE)
+     */
+    app_id = S_APP_ID;
+
+    /* Checks write permissions in create function*/
+    err = tfm_sst_veneer_create(app_id, asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should not fail");
+        return;
+    }
+
+    /* Sets data structure */
+    data.data = wrt_data;
+    data.size = WRITE_BUF_SIZE;
+    data.offset = 0;
+
+    /* Checks write permissions in the write function */
+    err = tfm_sst_veneer_write(app_id, hdl, &data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Sets data structure */
+    data.data = read_data;
+    data.size = WRITE_BUF_SIZE;
+    data.offset = 0;
+
+    /* Checks write permissions in the read function */
+    err = tfm_sst_veneer_read(app_id, hdl, &data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Application S_APP_ID doesn't have read permissions");
+        return;
+    }
+
+    /* Gets asset's attributes. It should succeed as the app ID has REFERENCE
+     * permissions.
+     */
+    err = tfm_sst_veneer_get_attributes(app_id, hdl, &asset_attrs);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Application S_APP_ID should read the attributes of this "
+                  "file");
+        return;
+    }
+
+    /* Checks attributes */
+    if (asset_attrs.size_current != WRITE_BUF_SIZE) {
+        TEST_FAIL("Asset current size should be write buffer size");
+        return;
+    }
+
+    if (asset_attrs.size_max != SST_ASSET_MAX_SIZE_SHA384_HASH) {
+        TEST_FAIL("Max size of the asset is incorrect");
+        return;
+    }
+
+    /* Sets application ID S_APP_ID and check its permissions (NONE) */
+    app_id = S_APP_ID;
+
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &tmp_hdl);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Get handle should fail");
+        return;
+    }
+
+    /* Sets data structure */
+    data.data = wrt_data;
+    data.size = WRITE_BUF_SIZE;
+    data.offset = 0;
+
+    /* Checks write permissions in the write function */
+    err = tfm_sst_veneer_write(app_id, hdl, &data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Application S_APP_ID is not allowed to write into this "
+                  "file");
+        return;
+    }
+
+    /* Sets data structure */
+    data.data = read_data;
+    data.size = WRITE_BUF_SIZE;
+    data.offset = 0;
+
+    /* Checks write permissions in the read function */
+    err = tfm_sst_veneer_read(app_id, hdl, &data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Application S_APP_ID is not allowed to read this file");
+        return;
+    }
+
+    /* Gets asset's attributes. It should fail as the app ID doesn't have
+     * REFERENCE permissions.
+     */
+    err = tfm_sst_veneer_get_attributes(app_id, hdl, &asset_attrs);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Application S_APP_ID should not be able to read the "
+                  "attributes of this file as it doesn't have permissions");
+        return;
+    }
+
+    /* Sets application ID S_APP_ID and check its permissions (NONE) */
+    app_id = S_APP_ID;
+
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &tmp_hdl);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Get handle should fail");
+        return;
+    }
+
+    /* Sets data structure */
+    data.data = wrt_data;
+    data.size = WRITE_BUF_SIZE;
+    data.offset = 0;
+
+    /* Checks write permissions in the write function */
+    err = tfm_sst_veneer_write(app_id, hdl, &data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Application S_APP_ID is not allowed to write into this "
+                  "file");
+        return;
+    }
+
+    /* Sets data structure */
+    data.data = read_data;
+    data.size = WRITE_BUF_SIZE;
+    data.offset = 0;
+
+    /* Checks write permissions in the read function */
+    err = tfm_sst_veneer_read(app_id, hdl, &data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Application S_APP_ID is not allowed to read this file");
+        return;
+    }
+
+    /* Gets asset's attributes. It should fail as the app ID doesn't have
+     * REFERENCE permissions.
+     */
+    err = tfm_sst_veneer_get_attributes(app_id, hdl, &asset_attrs);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Application S_APP_ID should not be able to read the "
+                  "attributes of this file as it doesn't have permissions");
+        return;
+    }
+
+    /* Sets application ID S_APP_ID and check its permissions to delete */
+    app_id = S_APP_ID;
+
+    /* Checks write permissions in delete function*/
+    err = tfm_sst_veneer_delete(app_id, hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Delete should not fail for application S_APP_ID");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
diff --git a/test/suites/sst/secure/sst_reliability_testsuite.c b/test/suites/sst/secure/sst_reliability_testsuite.c
new file mode 100644
index 0000000..e17c349
--- /dev/null
+++ b/test/suites/sst/secure/sst_reliability_testsuite.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "sst_tests.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "test/framework/helpers.h"
+#include "tfm_sst_defs.h"
+#include "secure_fw/services/secure_storage/assets/sst_asset_defs.h"
+#include "tfm_sst_veneers.h"
+#include "s_test_helpers.h"
+
+/* Test suite defines */
+#define LOOP_ITERATION   15UL
+#define READ_BUF_SIZE    11UL
+#define WRITE_BUF_SIZE    5UL
+
+/* Define test suite for SST reliability tests */
+/* List of tests */
+static void tfm_sst_test_3001(struct test_result_t *ret);
+static void tfm_sst_test_3002(struct test_result_t *ret);
+
+static struct test_t reliability_tests[] = {
+    {&tfm_sst_test_3001, "TFM_SST_TEST_3001",
+     "repetitive writes in an asset", {0} },
+    {&tfm_sst_test_3002, "TFM_SST_TEST_3002",
+     "repetitive create, write, read and delete", {0} },
+};
+
+void register_testsuite_s_sst_reliability(struct test_suite_t *p_test_suite)
+{
+    uint32_t list_size = (sizeof(reliability_tests) /
+                          sizeof(reliability_tests[0]));
+
+    set_testsuite("SST reliability tests (TFM_SST_TEST_3XXX)",
+                  reliability_tests, list_size, p_test_suite);
+}
+
+/**
+ * \brief Tests repetitive writes in an asset with the follow permissions:
+ *        APP_ID       | Permissions
+ *        -------------------------------------
+ *        S_APP_ID | REFERENCE, READ, WRITE
+ */
+static void tfm_sst_test_3001(struct test_result_t *ret)
+{
+    uint32_t hdl;
+    uint32_t app_id = S_APP_ID;
+    uint32_t asset_offset = 0;
+    const uint16_t asset_uuid = SST_ASSET_ID_X509_CERT_LARGE;
+    struct tfm_sst_buf_t data;
+    enum tfm_sst_err_t err;
+    uint32_t itr;
+    uint8_t wrt_data[WRITE_BUF_SIZE] = "GOOD";
+    uint8_t read_data[READ_BUF_SIZE] = "XXXXXXXXXX";
+
+    /* Prepares test context */
+    if (prepare_test_ctx(ret) != 0) {
+        return;
+    }
+
+    /* Checks write permissions in create function */
+    err = tfm_sst_veneer_create(app_id, asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should not fail");
+        return;
+    }
+
+    /* Sets write and read sizes */
+    data.size = WRITE_BUF_SIZE-1;
+
+    for (itr = 0; itr < LOOP_ITERATION; itr++) {
+        do {
+            /* Sets data structure */
+            data.data = wrt_data;
+            data.offset = asset_offset;
+
+            /* Checks write permissions in the write function */
+            err = tfm_sst_veneer_write(app_id, hdl, &data);
+            if (err != TFM_SST_ERR_SUCCESS) {
+                TEST_FAIL("Write should not fail for application S_APP_ID");
+                return;
+            }
+
+            /* Updates data structure to point to the read buffer */
+            data.data = &read_data[3];
+
+            /* Checks write permissions in the read function */
+            err = tfm_sst_veneer_read(app_id, hdl, &data);
+            if (err != TFM_SST_ERR_SUCCESS) {
+                TEST_FAIL("Application S_APP_ID must get file handle");
+                return;
+            }
+
+            /* Checks read data buffer content */
+            if (memcmp(read_data, "XXXGOODXXX", READ_BUF_SIZE) != 0) {
+                TEST_FAIL("Read buffer contains incorrect data");
+                return;
+            }
+
+            /* Reset read buffer data */
+            memset(data.data, 'X', data.size);
+
+            /* Moves asset offsets to next position */
+            asset_offset += data.size;
+
+        } while (asset_offset < SST_ASSET_MAX_SIZE_X509_CERT_LARGE);
+
+        /* Resets asset_offset */
+        asset_offset = 0;
+    }
+
+    /* Checks write permissions in delete function */
+    err = tfm_sst_veneer_delete(app_id, hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Delete should not fail for application S_APP_ID");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Tests repetitive creates, reads, writes and deletes, with the follow
+ *        permissions:
+ *        APP_ID       | Permissions
+ *        -------------------------------------
+ *        S_APP_ID | REFERENCE, READ, WRITE
+ */
+static void tfm_sst_test_3002(struct test_result_t *ret)
+{
+    uint32_t hdl;
+    uint32_t app_id = S_APP_ID;
+    uint32_t asset_offset = 0;
+    const uint16_t asset_uuid = SST_ASSET_ID_X509_CERT_LARGE;
+    struct tfm_sst_buf_t data;
+    enum tfm_sst_err_t err;
+    uint32_t itr;
+    uint8_t wrt_data[WRITE_BUF_SIZE] = "GOOD";
+    uint8_t read_data[READ_BUF_SIZE] = "XXXXXXXXXX";
+
+    /* Prepares test context */
+    if (prepare_test_ctx(ret) != 0) {
+        return;
+    }
+
+    /* Sets write and read sizes */
+    data.size = WRITE_BUF_SIZE-1;
+
+    for (itr = 0; itr < LOOP_ITERATION; itr++) {
+        /* Checks write permissions in create function */
+        err = tfm_sst_veneer_create(app_id, asset_uuid);
+        if (err != TFM_SST_ERR_SUCCESS) {
+            TEST_FAIL("Create should not fail for application S_APP_ID");
+            return;
+        }
+
+        err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &hdl);
+        if (err != TFM_SST_ERR_SUCCESS) {
+            TEST_FAIL("Get handle should not fail");
+            return;
+        }
+
+        do {
+            /* Sets data structure */
+            data.data = wrt_data;
+            data.offset = asset_offset;
+
+            /* Checks write permissions in the write function */
+            err = tfm_sst_veneer_write(app_id, hdl, &data);
+            if (err != TFM_SST_ERR_SUCCESS) {
+                TEST_FAIL("Write should not fail for application S_APP_ID");
+                return;
+            }
+
+            /* Updates data structure to point to the read buffer */
+            data.data = &read_data[3];
+
+            /* Checks write permissions in the read function */
+            err = tfm_sst_veneer_read(app_id, hdl, &data);
+            if (err != TFM_SST_ERR_SUCCESS) {
+                TEST_FAIL("Application S_APP_ID must get file handle");
+                return;
+            }
+
+            /* Checks read data buffer content */
+            if (memcmp(read_data, "XXXGOODXXX", READ_BUF_SIZE) != 0) {
+                read_data[READ_BUF_SIZE-1] = 0;
+                TEST_FAIL("Read buffer contains incorrect data");
+                return;
+            }
+
+            /* Reset read buffer data */
+            memset(data.data, 'X', data.size);
+
+            /* Moves asset offsets to next position */
+            asset_offset += data.size;
+
+        } while (asset_offset < SST_ASSET_MAX_SIZE_X509_CERT_LARGE);
+
+        /* Checks write permissions in delete function */
+        err = tfm_sst_veneer_delete(app_id, hdl);
+        if (err != TFM_SST_ERR_SUCCESS) {
+            TEST_FAIL("Delete should not fail for application S_APP_ID");
+            return;
+        }
+
+        /* Resets asset_offset */
+        asset_offset = 0;
+    }
+
+    ret->val = TEST_PASSED;
+}
diff --git a/test/suites/sst/secure/sst_sec_interface_testsuite.c b/test/suites/sst/secure/sst_sec_interface_testsuite.c
new file mode 100644
index 0000000..837f39d
--- /dev/null
+++ b/test/suites/sst/secure/sst_sec_interface_testsuite.c
@@ -0,0 +1,1311 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "sst_tests.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "test/framework/helpers.h"
+#include "secure_fw/services/secure_storage/assets/sst_asset_defs.h"
+#include "secure_fw/services/secure_storage/sst_core_interface.h"
+#include "tfm_sst_veneers.h"
+#include "s_test_helpers.h"
+
+/* Test suite defines */
+#define INVALID_APP_ID         0xFFFFFFFF
+#define INVALID_ASSET_ID           0xFFFF
+#define READ_BUF_SIZE                12UL
+#define WRITE_BUF_SIZE                5UL
+
+/* Memory bounds to check */
+#define ROM_ADDR_LOCATION        0x10000000
+#define DEV_ADDR_LOCATION        0x20000000
+#define NON_EXIST_ADDR_LOCATION  0xFFFFFFFF
+
+/* Test data sized to fill the SHA224 asset */
+#define READ_DATA_SHA224    "XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+#define WRITE_DATA_SHA224_1 "TEST_DATA_ONE_TWO_THREE_FOUR"
+#define WRITE_DATA_SHA224_2 "(ABCDEFGHIJKLMNOPQRSTUVWXYZ)"
+#define BUF_SIZE_SHA224     (SST_ASSET_MAX_SIZE_SHA224_HASH + 1)
+
+/* Define test suite for asset manager tests */
+/* List of tests */
+static void tfm_sst_test_2001(struct test_result_t *ret);
+static void tfm_sst_test_2002(struct test_result_t *ret);
+static void tfm_sst_test_2003(struct test_result_t *ret);
+static void tfm_sst_test_2004(struct test_result_t *ret);
+static void tfm_sst_test_2005(struct test_result_t *ret);
+static void tfm_sst_test_2006(struct test_result_t *ret);
+static void tfm_sst_test_2007(struct test_result_t *ret);
+static void tfm_sst_test_2008(struct test_result_t *ret);
+static void tfm_sst_test_2009(struct test_result_t *ret);
+static void tfm_sst_test_2010(struct test_result_t *ret);
+static void tfm_sst_test_2011(struct test_result_t *ret);
+static void tfm_sst_test_2012(struct test_result_t *ret);
+static void tfm_sst_test_2013(struct test_result_t *ret);
+
+static struct test_t write_tests[] = {
+    {&tfm_sst_test_2001, "TFM_SST_TEST_2001",
+     "Create interface", {0} },
+    {&tfm_sst_test_2002, "TFM_SST_TEST_2002",
+     "Get handle interface", {0} },
+    {&tfm_sst_test_2003, "TFM_SST_TEST_2003",
+     "Get attributes interface", {0} },
+    {&tfm_sst_test_2004, "TFM_SST_TEST_2004",
+     "Write interface", {0} },
+    {&tfm_sst_test_2005, "TFM_SST_TEST_2005",
+     "Read interface", {0} },
+    {&tfm_sst_test_2006, "TFM_SST_TEST_2006",
+     "Delete interface", {0} },
+    {&tfm_sst_test_2007, "TFM_SST_TEST_2007",
+     "Write and partial reads", {0} },
+    {&tfm_sst_test_2008, "TFM_SST_TEST_2008",
+     "Write partial data in an asset and reload secure storage area", {0} },
+    {&tfm_sst_test_2009, "TFM_SST_TEST_2009",
+     "Write more data than asset max size", {0} },
+    {&tfm_sst_test_2010, "TFM_SST_TEST_2010",
+     "Appending data to an asset", {0} },
+    {&tfm_sst_test_2011, "TFM_SST_TEST_2011",
+     "Appending data to an asset until eof", {0} },
+    {&tfm_sst_test_2012, "TFM_SST_TEST_2012",
+     "Write data to two assets alternately", {0} },
+    {&tfm_sst_test_2013, "TFM_SST_TEST_2013",
+     "Write and read data from illegal locations", {0} },
+};
+
+void register_testsuite_s_sst_sec_interface(struct test_suite_t *p_test_suite)
+{
+    uint32_t list_size = (sizeof(write_tests) / sizeof(write_tests[0]));
+
+    set_testsuite("SST secure interface tests (TFM_SST_TEST_2XXX)",
+                  write_tests, list_size, p_test_suite);
+}
+
+/**
+ * \brief Tests create function against:
+ * - Valid application ID and asset ID
+ * - Invalid asset ID
+ * - Invalid application ID
+ */
+static void tfm_sst_test_2001(struct test_result_t *ret)
+{
+    const uint32_t app_id = S_APP_ID;
+    const uint16_t asset_uuid = SST_ASSET_ID_X509_CERT_LARGE;
+    enum tfm_sst_err_t err;
+
+    /* Prepares test context */
+    if (prepare_test_ctx(ret) != 0) {
+        return;
+    }
+
+    /* Checks write permissions in create function */
+    err = tfm_sst_veneer_create(app_id, asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Calls create with invalid asset ID */
+    err = tfm_sst_veneer_create(app_id, INVALID_ASSET_ID);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Create should fail for invalid ASSET ID");
+        return;
+    }
+
+    /* Calls create with invalid application ID */
+    err = tfm_sst_veneer_create(INVALID_APP_ID, asset_uuid);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Create should fail for invalid application ID");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Tests get handle function against:
+ * - Valid asset ID and not created file
+ * - Valid asset ID and created file
+ * - Invalid asset ID
+ */
+static void tfm_sst_test_2002(struct test_result_t *ret)
+{
+    const uint32_t app_id = S_APP_ID;
+    const uint16_t asset_uuid = SST_ASSET_ID_X509_CERT_LARGE;
+    enum tfm_sst_err_t err;
+    uint32_t hdl;
+
+    /* Prepares test context */
+    if (prepare_test_ctx(ret) != 0) {
+        return;
+    }
+
+    /* Calls get handle before create the asset */
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &hdl);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should fail as the file is not created");
+        return;
+    }
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_veneer_create(app_id, asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Resets handle before read the new one */
+    hdl = 0;
+
+    /* Gets asset's handle */
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        return;
+    }
+
+    /* Calls get handle with invalid app ID */
+    err = tfm_sst_veneer_get_handle(INVALID_APP_ID, asset_uuid, &hdl);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should fail as application ID is invalid");
+        return;
+    }
+
+    /* Calls get handle with invalid asset ID */
+    err = tfm_sst_veneer_get_handle(app_id, INVALID_ASSET_ID, &hdl);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should fail as asset hanlder is invalid");
+        return;
+    }
+
+    /* Calls get handle with invalid handle pointer */
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, NULL);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should fail as asset hanlder pointer is invalid");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Tests get attributes function against:
+ * - Valid application ID, asset handle and attributes struct pointer
+ * - Invalid application ID
+ * - Invalid asset handle
+ * - Invalid attributes struct pointer
+ */
+static void tfm_sst_test_2003(struct test_result_t *ret)
+{
+    const uint32_t app_id = S_APP_ID;
+    const uint16_t asset_uuid = SST_ASSET_ID_X509_CERT_LARGE;
+    struct tfm_sst_attribs_t asset_attrs;
+    enum tfm_sst_err_t err;
+    uint32_t hdl;
+
+    /* Prepares test context */
+    if (prepare_test_ctx(ret) != 0) {
+        return;
+    }
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_veneer_create(app_id, asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Gets asset's handle */
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        return;
+    }
+
+    /* Calls get_attributes with valid application ID, asset handle and
+     * attributes struct pointer
+     */
+    err = tfm_sst_veneer_get_attributes(app_id, hdl, &asset_attrs);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Application S_APP_ID should be able to read the "
+                  "attributes of this file");
+        return;
+    }
+
+    /* Checks attributes */
+    if (asset_attrs.size_current != 0) {
+        TEST_FAIL("Asset current size should be 0 as it is only created");
+        return;
+    }
+
+    if (asset_attrs.size_max != SST_ASSET_MAX_SIZE_X509_CERT_LARGE) {
+        TEST_FAIL("Max size of the asset is incorrect");
+        return;
+    }
+
+    /* Calls get_attributes with invalid application ID */
+    err = tfm_sst_veneer_get_attributes(INVALID_APP_ID, hdl, &asset_attrs);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get attributes function should fail for an invalid "
+                  "application ID");
+        return;
+    }
+
+    /* Calls get_attributes with invalid asset handle */
+    err = tfm_sst_veneer_get_attributes(app_id, 0, &asset_attrs);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get attributes function should fail for an invalid "
+                  "asset handle");
+        return;
+    }
+
+    /* Calls get_attributes with invalid struct attributes pointer */
+    err = tfm_sst_veneer_get_attributes(app_id, hdl, NULL);
+    if (err != TFM_SST_ERR_PARAM_ERROR) {
+        TEST_FAIL("Get attributes function should fail for an invalid "
+                  "struct attributes pointer");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Tests write function against:
+ * - Valid application ID, asset handle and data pointer
+ * - Invalid application ID
+ * - Invalid asset handle
+ * - NULL pointer as write buffer
+ * - Offset + write data size larger than max asset size
+ */
+static void tfm_sst_test_2004(struct test_result_t *ret)
+{
+    const uint32_t app_id = S_APP_ID;
+    const uint16_t asset_uuid = SST_ASSET_ID_X509_CERT_LARGE;
+    struct tfm_sst_attribs_t asset_attrs;
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint32_t hdl;
+    uint8_t wrt_data[WRITE_BUF_SIZE] = "DATA";
+
+    /* Prepares test context */
+    if (prepare_test_ctx(ret) != 0) {
+        return;
+    }
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_veneer_create(app_id, asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Gets asset's handle */
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = 0;
+
+    /* Write data in the asset */
+    err = tfm_sst_veneer_write(app_id, hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write should works correctly");
+        return;
+    }
+
+    /* Calls get_attributes with valid application ID, asset handle and
+     * attributes struct pointer
+     */
+    err = tfm_sst_veneer_get_attributes(app_id, hdl, &asset_attrs);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Application S_APP_ID should be able to read the "
+                  "attributes of this file");
+        return;
+    }
+
+    /* Checks attributes */
+    if (asset_attrs.size_current != WRITE_BUF_SIZE) {
+        TEST_FAIL("Asset current size should be size of the write data");
+        return;
+    }
+
+    /* Calls write function with invalid application ID */
+    err = tfm_sst_veneer_write(INVALID_APP_ID, hdl, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Invalid application ID should not write in the file");
+        return;
+    }
+
+    /* Calls write function with invalid asset handle */
+    err = tfm_sst_veneer_write(app_id, 0, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Invalid asset handle should not write in the file");
+        return;
+    }
+
+    /* Calls write function with invalid asset handle */
+    err = tfm_sst_veneer_write(app_id, hdl, NULL);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("NULL data pointer should make the write fail");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = 1;
+    io_data.offset = SST_ASSET_MAX_SIZE_X509_CERT_LARGE;
+
+    /* Calls write function with offset + write data size larger than
+     * max asset size
+     */
+    err = tfm_sst_veneer_write(app_id, hdl, &io_data);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Offset + write data size larger than max asset size "
+                  "should make the write fail");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Tests read function against:
+ * - Valid application ID, asset handle and data pointer
+ * - Invalid application ID
+ * - Invalid asset handle
+ * - NULL pointer as write buffer
+ * - Offset + read data size larger than current asset size
+ */
+static void tfm_sst_test_2005(struct test_result_t *ret)
+{
+    const uint32_t app_id = S_APP_ID;
+    const uint16_t asset_uuid = SST_ASSET_ID_X509_CERT_LARGE;
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    struct tfm_sst_attribs_t asset_attrs;
+    uint32_t hdl;
+    uint8_t wrt_data[WRITE_BUF_SIZE] = "DATA";
+    uint8_t read_data[READ_BUF_SIZE] = "XXXXXXXXXXX";
+
+    /* Prepares test context */
+    if (prepare_test_ctx(ret) != 0) {
+        return;
+    }
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_veneer_create(app_id, asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Gets asset's handle */
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = 0;
+
+    /* Write data in the asset */
+    err = tfm_sst_veneer_write(app_id, hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write should works correctly");
+        return;
+    }
+
+    /* Sets data structure for read*/
+    io_data.data = read_data+3;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = 0;
+
+    /* Read data from the asset */
+    err = tfm_sst_veneer_read(app_id, hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Read should works correctly");
+        return;
+    }
+
+    if (memcmp(read_data, "XXX", 3) != 0) {
+        TEST_FAIL("Read buffer contains illegal pre-data");
+        return;
+    }
+
+    if (memcmp((read_data+3), wrt_data, WRITE_BUF_SIZE) != 0) {
+        TEST_FAIL("Read buffer has read incorrect data");
+        return;
+    }
+
+    if (memcmp((read_data+8), "XXX", 3) != 0) {
+        TEST_FAIL("Read buffer contains illegal post-data");
+        return;
+    }
+
+    /* Calls read with invalid application ID */
+    err = tfm_sst_veneer_read(INVALID_APP_ID, hdl, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Read should fail when read is called with an invalid "
+                  "application ID");
+        return;
+    }
+
+    /* Calls read with invalid asset handle */
+    err = tfm_sst_veneer_read(app_id, 0, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Read should fail when read is called with an invalid "
+                  "asset handle");
+        return;
+    }
+
+    /* Calls read with invalid asset handle */
+    err = tfm_sst_veneer_read(app_id, hdl, NULL);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Read should fail when read is called with an invalid "
+                  "data pointer");
+        return;
+    }
+
+    /* Gets current asset attributes */
+    err = tfm_sst_veneer_get_attributes(app_id, hdl, &asset_attrs);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Application S_APP_ID should be able to read the "
+                  "attributes of this file");
+        return;
+    }
+
+    /* Checks attributes */
+    if (asset_attrs.size_current == 0) {
+        TEST_FAIL("Asset current size should be bigger than 0");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = read_data;
+    io_data.size = 1;
+    io_data.offset = asset_attrs.size_current;
+
+    /* Calls write function with offset + read data size larger than current
+     * asset size
+     */
+    err = tfm_sst_veneer_read(app_id, hdl, &io_data);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Offset + read data size larger than current asset size");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Tests delete function against:
+ * - Valid application ID and asset handle
+ * - Invalid application ID
+ * - Invalid asset handle
+ * - Remove first asset in the data block and check if
+ *   next asset's data is compacted correctly.
+ */
+static void tfm_sst_test_2006(struct test_result_t *ret)
+{
+    const uint32_t app_id_1 = S_APP_ID;
+    const uint32_t app_id_2 = S_APP_ID;
+    const uint16_t asset_uuid_1 = SST_ASSET_ID_SHA224_HASH;
+    const uint16_t asset_uuid_2 = SST_ASSET_ID_SHA384_HASH;
+    struct tfm_sst_buf_t io_data;
+    enum tfm_sst_err_t err;
+    uint32_t hdl_1;
+    uint32_t hdl_2;
+    uint8_t read_data[BUF_SIZE_SHA224] = READ_DATA_SHA224;
+    uint8_t wrt_data[BUF_SIZE_SHA224] = WRITE_DATA_SHA224_1;
+
+    /* Prepares test context */
+    if (prepare_test_ctx(ret) != 0) {
+        return;
+    }
+
+    /* Creates assset to get a valid handle */
+    err = tfm_sst_veneer_create(app_id_1, asset_uuid_1);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Gets asset's handle */
+    err = tfm_sst_veneer_get_handle(app_id_1, asset_uuid_1, &hdl_1);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        return;
+    }
+
+    /* Calls delete asset with invalid application ID */
+    err = tfm_sst_veneer_delete(INVALID_APP_ID, hdl_1);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("The delete action should fail if an invalid application "
+                  "ID is provided");
+        return;
+    }
+
+    /* Calls delete asset */
+    err = tfm_sst_veneer_delete(app_id_1, hdl_1);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("The delete action should work correctly");
+        return;
+    }
+
+    /* Calls delete with a deleted asset handle */
+    err = tfm_sst_veneer_delete(app_id_1, hdl_1);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("The delete action should fail as handle is not valid");
+        return;
+    }
+
+    /* Calls delete asset with invalid asset handle */
+    err = tfm_sst_veneer_delete(app_id_1, 0);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("The delete action should fail if an invalid asset handle "
+                  "is provided");
+        return;
+    }
+
+    /***** Test data block compact feature *****/
+    /* Create asset 2 to locate it at the beginning of the block. Then,
+     * create asset 1 to be located after asset 2. Write data on asset
+     * 1 and remove asset 2. If delete works correctly, when the code
+     * reads back the asset 1 data, the data must be correct.
+     */
+
+    /* Creates assset 2 first to locate it at the beginning of the
+     * data block
+     */
+    err = tfm_sst_veneer_create(app_id_2, asset_uuid_2);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Gets asset 2 handle */
+    err = tfm_sst_veneer_get_handle(app_id_2, asset_uuid_2, &hdl_2);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        return;
+    }
+
+    /* Creates asset 1 to locate it after the asset 2 in the data block */
+    err = tfm_sst_veneer_create(app_id_1, asset_uuid_1);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Gets asset 1 handle */
+    err = tfm_sst_veneer_get_handle(app_id_1, asset_uuid_1, &hdl_1);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = SST_ASSET_MAX_SIZE_SHA224_HASH;
+    io_data.offset = 0;
+
+    /* Write data in asset 1 */
+    err = tfm_sst_veneer_write(app_id_1, hdl_1, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data should work for application S_APP_ID");
+        return;
+    }
+
+    /* Deletes asset 2. It means that after the delete call, asset 1 should be
+     * at the beginning of the block.
+     */
+    err = tfm_sst_veneer_delete(app_id_2, hdl_2);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("The delete action should work correctly");
+        return;
+    }
+
+    /* If compact works as expected, the code should be able to read back
+     * correctly the data from asset 1
+     */
+
+    /* Sets data structure */
+    io_data.data = read_data;
+    io_data.size = SST_ASSET_MAX_SIZE_SHA224_HASH;
+    io_data.offset = 0;
+
+    /* Read back the asset 1 */
+    err = tfm_sst_veneer_read(app_id_1, hdl_1, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Incorrect number of bytes read back");
+        return;
+    }
+
+    if (memcmp(read_data, wrt_data, BUF_SIZE_SHA224) != 0) {
+        TEST_FAIL("Read buffer has incorrect data");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Tests write and partial reads.
+ */
+static void tfm_sst_test_2007(struct test_result_t *ret)
+{
+    const uint32_t app_id = S_APP_ID;
+    const uint16_t asset_uuid = SST_ASSET_ID_X509_CERT_LARGE;
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint32_t hdl;
+    uint32_t i;
+    uint8_t read_data[READ_BUF_SIZE] = "XXXXXXXXXXX";
+    uint8_t wrt_data[WRITE_BUF_SIZE] = "DATA";
+
+    /* Prepares test context */
+    if (prepare_test_ctx(ret) != 0) {
+        return;
+    }
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_veneer_create(app_id, asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Gets asset's handle */
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = 0;
+
+    /* Write data in the asset */
+    err = tfm_sst_veneer_write(app_id, hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write should works correctly");
+        return;
+    }
+
+    /* Sets data structure for read*/
+    io_data.data = (read_data + 3);
+    io_data.size = 1;
+    io_data.offset = 0;
+
+    for (i = 0; i < WRITE_BUF_SIZE; i++) {
+        /* Read data from the asset */
+        err = tfm_sst_veneer_read(app_id, hdl, &io_data);
+        if (err != TFM_SST_ERR_SUCCESS) {
+            TEST_FAIL("Read should works correctly");
+            return;
+        }
+
+        /* Increases data pointer and offset */
+        io_data.data++;
+        io_data.offset++;
+    }
+
+    if (memcmp(read_data, "XXX", 3) != 0) {
+        TEST_FAIL("Read buffer contains illegal pre-data");
+        return;
+    }
+
+    if (memcmp((read_data + 3), wrt_data, WRITE_BUF_SIZE) != 0) {
+        TEST_FAIL("Read buffer has read incorrect data");
+        return;
+    }
+
+    if (memcmp((read_data + 8), "XXX", 3) != 0) {
+        TEST_FAIL("Read buffer contains illegal post-data");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Tests correct behaviour when data is written in the secure storage
+ *        area and the secure_fs_perpare is called after it.
+ *        The expected behaviour is to read back the data wrote
+ *        before the seconds perpare call.
+ */
+static void tfm_sst_test_2008(struct test_result_t *ret)
+{
+    const uint32_t app_id = S_APP_ID;
+    const uint16_t asset_uuid = SST_ASSET_ID_X509_CERT_LARGE;
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint32_t hdl;
+    uint8_t read_data[READ_BUF_SIZE] = "XXXXXXXXXXX";
+    uint8_t wrt_data[WRITE_BUF_SIZE] = "DATA";
+
+    /* Prepares test context */
+    if (prepare_test_ctx(ret) != 0) {
+        return;
+    }
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_veneer_create(app_id, asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Gets asset's handle */
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = 0;
+
+    /* Write data in the asset */
+    err = tfm_sst_veneer_write(app_id, hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write should works correctly");
+        return;
+    }
+
+    /* Calls prepare again to simulate reinitialization */
+    err = sst_object_prepare();
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Saved system should have been preparable");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = (read_data + 3);
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = 0;
+
+    /* Read back the data after the prepare */
+    err = tfm_sst_veneer_read(app_id, hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Incorrect number of bytes read back");
+        return;
+    }
+
+    if (memcmp(read_data, "XXX", 3) != 0) {
+        TEST_FAIL("Read buffer contains illegal pre-data");
+        return;
+    }
+
+    if (memcmp((read_data + 3), wrt_data, WRITE_BUF_SIZE) != 0) {
+        TEST_FAIL("Read buffer has read incorrect data");
+        return;
+    }
+
+    if (memcmp((read_data + 8), "XXX", 3) != 0) {
+        TEST_FAIL("Read buffer contains illegal post-data");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Tests write function against a write call where data size is
+ *        bigger than the maximum assert size.
+ */
+static void tfm_sst_test_2009(struct test_result_t *ret)
+{
+    const uint32_t app_id = S_APP_ID;
+    const uint16_t asset_uuid = SST_ASSET_ID_SHA224_HASH;
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint32_t hdl;
+    uint8_t wrt_data[BUF_SIZE_SHA224] = {0};
+
+    /* Prepares test context */
+    if (prepare_test_ctx(ret) != 0) {
+        return;
+    }
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_veneer_create(app_id, asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Gets asset's handle */
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = SST_ASSET_MAX_SIZE_SHA224_HASH + 1;
+    io_data.offset = 0;
+
+    /* Write data in the asset when data size is bigger than asset size */
+    err = tfm_sst_veneer_write(app_id, hdl, &io_data);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Should have failed asset write of too large");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Tests write function against multiple writes.
+ */
+static void tfm_sst_test_2010(struct test_result_t *ret)
+{
+    const uint32_t app_id = S_APP_ID;
+    const uint16_t asset_uuid = SST_ASSET_ID_SHA224_HASH;
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint32_t hdl;
+    uint8_t read_data[READ_BUF_SIZE]  = "XXXXXXXXXXX";
+    uint8_t wrt_data[WRITE_BUF_SIZE+1]  = "Hello";
+    uint8_t wrt_data2[WRITE_BUF_SIZE+1] = "World";
+
+    /* Prepares test context */
+    if (prepare_test_ctx(ret) != 0) {
+        return;
+    }
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_veneer_create(app_id, asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Gets asset's handle */
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = 0;
+
+    /* Write data in the asset */
+    err = tfm_sst_veneer_write(app_id, hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data 1 failed");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data2;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = WRITE_BUF_SIZE;
+
+    /* Write data 2 in the asset */
+    err = tfm_sst_veneer_write(app_id, hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data 2 failed");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = read_data;
+    io_data.size = WRITE_BUF_SIZE * 2;
+    io_data.offset = 0;
+
+    /* Read back the data */
+    err = tfm_sst_veneer_read(app_id, hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Incorrect number of bytes read back");
+        return;
+    }
+
+    /* The X is used to check that the number of bytes read was exactly the
+     * number requested
+     */
+    if (memcmp(read_data, "HelloWorldX", READ_BUF_SIZE) != 0) {
+        TEST_FAIL("Read buffer has read incorrect data");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Tests write function against multiple writes until the end of asset.
+ */
+static void tfm_sst_test_2011(struct test_result_t *ret)
+{
+    const uint32_t app_id = S_APP_ID;
+    const uint16_t asset_uuid = SST_ASSET_ID_SHA224_HASH;
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint32_t hdl;
+    uint8_t read_data[BUF_SIZE_SHA224] = READ_DATA_SHA224;
+    uint8_t wrt_data[BUF_SIZE_SHA224] = WRITE_DATA_SHA224_1;
+    uint8_t wrt_data2[BUF_SIZE_SHA224] = WRITE_DATA_SHA224_2;
+
+    /* Prepares test context */
+    if (prepare_test_ctx(ret) != 0) {
+        return;
+    }
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_veneer_create(app_id, asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Gets asset's handle */
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = 0;
+
+    /* Write data in the asset */
+    err = tfm_sst_veneer_write(app_id, hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data 1 failed");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data2;
+    io_data.size = (SST_ASSET_MAX_SIZE_SHA224_HASH - WRITE_BUF_SIZE) + 1;
+    io_data.offset = WRITE_BUF_SIZE;
+
+    /* Write data in the asset */
+    err = tfm_sst_veneer_write(app_id, hdl, &io_data);
+    if (err == TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data 2 should have failed as this write tries to "
+                  "write more bytes that the max size");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data + WRITE_BUF_SIZE;
+    io_data.size = SST_ASSET_MAX_SIZE_SHA224_HASH - WRITE_BUF_SIZE;
+    io_data.offset = WRITE_BUF_SIZE;
+
+    /* Write data in the asset */
+    err = tfm_sst_veneer_write(app_id, hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data 3 failed");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = read_data;
+    io_data.size = SST_ASSET_MAX_SIZE_SHA224_HASH;
+    io_data.offset = 0;
+
+    /* Read back the data */
+    err = tfm_sst_veneer_read(app_id, hdl, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Incorrect number of bytes read back");
+        return;
+    }
+
+    if (memcmp(read_data, wrt_data, BUF_SIZE_SHA224) != 0) {
+        TEST_FAIL("Read buffer has incorrect data");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+/**
+ * \brief Tests write and read to/from 2 assets.
+ */
+static void tfm_sst_test_2012(struct test_result_t *ret)
+{
+
+    const uint32_t app_id_1 = S_APP_ID;
+    const uint32_t app_id_2 = S_APP_ID;
+    const uint16_t asset_uuid_1 = SST_ASSET_ID_X509_CERT_LARGE;
+    const uint16_t asset_uuid_2 = SST_ASSET_ID_SHA224_HASH;
+    enum tfm_sst_err_t err;
+    uint32_t hdl_1;
+    uint32_t hdl_2;
+    struct tfm_sst_buf_t io_data;
+    uint8_t read_data[READ_BUF_SIZE] = "XXXXXXXXXXX";
+    uint8_t wrt_data[WRITE_BUF_SIZE+1] = "Hello";
+    uint8_t wrt_data2[3] = "Hi";
+    uint8_t wrt_data3[WRITE_BUF_SIZE+1] = "World";
+    uint8_t wrt_data4[WRITE_BUF_SIZE+1] = "12345";
+
+    /* Prepares test context */
+    if (prepare_test_ctx(ret) != 0) {
+        return;
+    }
+
+    /* Creates asset 1 to get a valid handle */
+    err = tfm_sst_veneer_create(app_id_1, asset_uuid_1);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Gets asset's handle 1 */
+    err = tfm_sst_veneer_get_handle(app_id_1, asset_uuid_1, &hdl_1);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        return;
+    }
+
+    /* Creates asset 2 to get a valid handle */
+    err = tfm_sst_veneer_create(app_id_2, asset_uuid_2);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Gets asset's handle 2 */
+    err = tfm_sst_veneer_get_handle(app_id_2, asset_uuid_2, &hdl_2);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = 0;
+
+    /* Write data in asset 1 */
+    err = tfm_sst_veneer_write(app_id_1, hdl_1, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data should work for application S_APP_ID");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data2;
+    io_data.size = 2;
+    io_data.offset = 0;
+
+    /* Write data 2 in asset 2 */
+    err = tfm_sst_veneer_write(app_id_2, hdl_2, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data should work for application S_APP_ID");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data3;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = WRITE_BUF_SIZE;
+
+    /* Write data 3 in asset 1 */
+    err = tfm_sst_veneer_write(app_id_1, hdl_1, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data should work for application S_APP_ID");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = wrt_data4;
+    io_data.size = WRITE_BUF_SIZE;
+    io_data.offset = 2;
+
+    /* Write data 4 in asset 2 */
+    err = tfm_sst_veneer_write(app_id_2, hdl_2, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Write data should work for application S_APP_ID");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = read_data;
+    io_data.size = WRITE_BUF_SIZE * 2; /* size of wrt_data + wrt_data3 */
+    io_data.offset = 0;
+
+    /* Read back the asset 1 */
+    err = tfm_sst_veneer_read(app_id_1, hdl_1, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Incorrect number of bytes read back");
+        return;
+    }
+
+    if (memcmp(read_data, "HelloWorldX", READ_BUF_SIZE) != 0) {
+        TEST_FAIL("Read buffer has incorrect data");
+        return;
+    }
+
+    /* Resets read buffer content to a known data */
+    memset(read_data, 'X', READ_BUF_SIZE - 1);
+
+    /* Sets data structure */
+    io_data.data = read_data;
+    io_data.size = 2 + WRITE_BUF_SIZE; /* size of wrt_data2 + wrt_data4 */
+    io_data.offset = 0;
+
+    /* Read back the asset 2 */
+    err = tfm_sst_veneer_read(app_id_2, hdl_2, &io_data);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Incorrect number of bytes read back");
+        return;
+    }
+
+    if (memcmp(read_data, "Hi12345XXXX", READ_BUF_SIZE) != 0) {
+        TEST_FAIL("Read buffer has incorrect data");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Tests write and read to/from the follow illegal locations:
+ * - ROM memory
+ * - Device memory
+ * - Non existing memory location
+ */
+static void tfm_sst_test_2013(struct test_result_t *ret)
+{
+    uint32_t app_id = S_APP_ID;
+    const uint16_t asset_uuid = SST_ASSET_ID_SHA224_HASH;
+    enum tfm_sst_err_t err;
+    struct tfm_sst_buf_t io_data;
+    uint32_t hdl;
+
+    /* Prepares test context */
+    if (prepare_test_ctx(ret) != 0) {
+        return;
+    }
+
+    /* Creates asset to get a valid handle */
+    err = tfm_sst_veneer_create(app_id, asset_uuid);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Create should not fail for application S_APP_ID");
+        return;
+    }
+
+    /* Gets asset's handle */
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid, &hdl);
+    if (err != TFM_SST_ERR_SUCCESS) {
+        TEST_FAIL("Get handle should return a valid asset handle");
+        return;
+    }
+
+    /*** Check functions against ROM address location ***/
+
+    /* Gets asset's handle with a ROM address location to store asset's
+     * handle
+     */
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid,
+                                    (uint32_t *)ROM_ADDR_LOCATION);
+    if (err != TFM_SST_ERR_PARAM_ERROR) {
+        TEST_FAIL("Get handle should fail for an illegal location");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = (uint8_t *)ROM_ADDR_LOCATION;
+    io_data.size = 1;
+    io_data.offset = 0;
+
+    /* Calls write with a ROM address location */
+    err = tfm_sst_veneer_write(app_id, hdl, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Write should fail for an illegal location");
+        return;
+    }
+
+    /* Calls read with a ROM address location */
+    err = tfm_sst_veneer_read(app_id, hdl, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Read should fail for an illegal location");
+        return;
+    }
+
+    /*** Check functions against devices address location ***/
+
+    /* Gets asset's handle with a devices address location to store asset's
+     * handle
+     */
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid,
+                                    (uint32_t *)DEV_ADDR_LOCATION);
+    if (err != TFM_SST_ERR_PARAM_ERROR) {
+        TEST_FAIL("Get handle should fail for an illegal location");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = (uint8_t *)DEV_ADDR_LOCATION;
+
+    /* Calls write with a device address location */
+    err = tfm_sst_veneer_write(app_id, hdl, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Write should fail for an illegal location");
+        return;
+    }
+
+    /* Calls read with a device address location */
+    err = tfm_sst_veneer_read(app_id, hdl, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Read should fail for an illegal location");
+        return;
+    }
+
+    /*** Check functions against non existing address location ***/
+
+    /* Gets asset's handle with a non existing address location to store asset's
+     * handle
+     */
+    err = tfm_sst_veneer_get_handle(app_id, asset_uuid,
+                                    (uint32_t *)NON_EXIST_ADDR_LOCATION);
+    if (err != TFM_SST_ERR_PARAM_ERROR) {
+        TEST_FAIL("Get handle should fail for an illegal location");
+        return;
+    }
+
+    /* Sets data structure */
+    io_data.data = (uint8_t *)NON_EXIST_ADDR_LOCATION;
+
+    /* Calls write with a non-existing address location */
+    err = tfm_sst_veneer_write(app_id, hdl, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Write should fail for an illegal location");
+        return;
+    }
+
+    /* Calls read with a non-existing address location */
+    err = tfm_sst_veneer_read(app_id, hdl, &io_data);
+    if (err != TFM_SST_ERR_ASSET_NOT_FOUND) {
+        TEST_FAIL("Read should fail for an illegal location");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
diff --git a/test/suites/sst/secure/sst_tests.h b/test/suites/sst/secure/sst_tests.h
new file mode 100644
index 0000000..de0003f
--- /dev/null
+++ b/test/suites/sst/secure/sst_tests.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __SST_TESTS_H__
+#define __SST_TESTS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "test/framework/test_framework.h"
+
+/**
+ * \brief Register testsuite for the sst policy tests.
+ *
+ * \param[in] p_test_suite  The test suite to be executed.
+ */
+void register_testsuite_s_sst_interface(struct test_suite_t *p_test_suite);
+
+/**
+ * \brief Register testsuite for the sst interface tests.
+ *
+ * \param[in] p_test_suite  The test suite to be executed.
+ */
+void register_testsuite_s_sst_sec_interface(struct test_suite_t *p_test_suite);
+
+/**
+ * \brief Register testsuite for the sst reliability tests.
+ *
+ * \param[in] p_test_suite  The test suite to be executed.
+ */
+void register_testsuite_s_sst_reliability(struct test_suite_t *p_test_suite);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SST_TESTS_H__ */
diff --git a/test/test_services/tfm_core_test/core_test_defs.h b/test/test_services/tfm_core_test/core_test_defs.h
new file mode 100644
index 0000000..871926b
--- /dev/null
+++ b/test/test_services/tfm_core_test/core_test_defs.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __CORE_TEST_DEFS_H__
+#define __CORE_TEST_DEFS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <inttypes.h>
+#include <limits.h>
+#include "tfm_api.h"
+
+/* These definitions are used in symbols, only digits are permitted */
+#define CORE_TEST_ID_NS_THREAD          1001
+#define CORE_TEST_ID_NS_SVC             1002
+#define CORE_TEST_ID_CHECK_INIT         1003
+#define CORE_TEST_ID_RECURSION          1004
+#define CORE_TEST_ID_MEMORY_PERMISSIONS 1005
+#define CORE_TEST_ID_MPU_ACCESS         1006
+#define CORE_TEST_ID_BUFFER_CHECK       1007
+#define CORE_TEST_ID_SS_TO_SS           1008
+#define CORE_TEST_ID_SHARE_REDIRECTION  1009
+#define CORE_TEST_ID_SS_TO_SS_BUFFER    1010
+#define CORE_TEST_ID_TWO_SFN_ONE_SVC    1011
+#define CORE_TEST_ID_PERIPHERAL_ACCESS  1012
+#define CORE_TEST_ID_BLOCK              2001
+
+/* Use lower 16 bits in return value for error code, upper 16 for line number
+ * in test service
+ */
+#define CORE_TEST_RETURN_ERROR(x) return (((__LINE__) << 16) | x)
+#define CORE_TEST_ERROR_GET_EXTRA(x) (x >> 16)
+#define CORE_TEST_ERROR_GET_CODE(x) (x & 0xFFFF)
+
+enum core_test_errno_t {
+    CORE_TEST_ERRNO_SUCCESS = 0,
+    CORE_TEST_ERRNO_SERVICE_NOT_INITED = TFM_SERVICE_SPECIFIC_ERROR_MIN,
+    CORE_TEST_ERRNO_UNEXPECTED_CORE_BEHAVIOUR,
+    CORE_TEST_ERRNO_SERVICE_RECURSION_NOT_REJECTED,
+    CORE_TEST_ERRNO_INVALID_BUFFER,
+    CORE_TEST_ERRNO_SLAVE_SERVICE_CALL_FAILURE,
+    CORE_TEST_ERRNO_SLAVE_SERVICE_BUFFER_FAILURE,
+    CORE_TEST_ERRNO_FIRST_CALL_FAILED,
+    CORE_TEST_ERRNO_SECOND_CALL_FAILED,
+    CORE_TEST_ERRNO_PERIPHERAL_ACCESS_FAILED,
+    CORE_TEST_ERRNO_TEST_FAULT,
+    CORE_TEST_ERRNO_INVALID_TEST_ID,
+    /* Following entry is only to ensure the error code of int size */
+    CORE_TEST_ERRNO_FORCE_INT_SIZE = INT_MAX
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_TEST_DEFS_H__ */
diff --git a/test/test_services/tfm_core_test/tfm_ss_core_test.c b/test/test_services/tfm_core_test/tfm_ss_core_test.c
new file mode 100644
index 0000000..fcbffb7
--- /dev/null
+++ b/test/test_services/tfm_core_test/tfm_ss_core_test.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stddef.h>
+#include "tfm_ss_core_test.h"
+#include "tfm_api.h"
+#include "core_test_defs.h"
+#include "tfm_ss_core_test_veneers.h"
+#include "test/test_services/tfm_core_test_2/tfm_ss_core_test_2_veneers.h"
+#include "secure_fw/core/secure_utilities.h"
+#include "tfm_secure_api.h"
+
+#include "smm_mps2.h"
+
+static int32_t service_init_done;
+
+int32_t core_test_init(void)
+{
+    service_init_done = 1;
+    return TFM_SUCCESS;
+}
+
+
+int32_t spm_core_test_sfn_init_success(void)
+{
+    if (service_init_done) {
+        return CORE_TEST_ERRNO_SUCCESS;
+    } else {
+        return CORE_TEST_ERRNO_SERVICE_NOT_INITED;
+    }
+}
+
+int32_t spm_core_test_sfn_direct_recursion(int32_t depth)
+{
+    if (depth != 0) {
+        /* Protect against scenario where TF-M core fails to block recursion */
+        return CORE_TEST_ERRNO_SERVICE_RECURSION_NOT_REJECTED;
+    }
+    /* Call to the same service again, should be rejected */
+    int32_t ret = tfm_core_test_sfn_direct_recursion(++depth);
+
+    if (ret == TFM_SUCCESS) {
+        /* This is an unexpected return value */
+        return CORE_TEST_ERRNO_UNEXPECTED_CORE_BEHAVIOUR;
+    } else if (ret == CORE_TEST_ERRNO_SERVICE_RECURSION_NOT_REJECTED) {
+        /* This means that service was started in recursion */
+        return CORE_TEST_ERRNO_SERVICE_RECURSION_NOT_REJECTED;
+    } else {
+        return CORE_TEST_ERRNO_SUCCESS;
+    }
+}
+
+
+/* Service RW data array for testing memory accesses */
+static int32_t mem[4] = {1, 2, 3, 4};
+
+#define MPS2_USERLED_MASK   (0x3)
+
+int32_t test_mpu_access(
+    uint32_t *data_r_ptr, uint32_t *code_ptr, uint32_t *data_w_ptr)
+{
+    /* If these accesses fail, TFM Core kicks in, there's no returning to sfn */
+    /* Code execution, stack access is implicitly tested */
+    /* Read RW data */
+    int32_t len = sizeof(uint32_t);
+    int32_t tmp = mem[0];
+
+    tmp++;
+    /* Write to RW data region */
+    mem[0] = mem[1];
+    mem[1] = tmp;
+    mem[2] = len;
+    mem[3] = ~len;
+
+    /* Read from NS data region */
+    if (tfm_core_memory_permission_check(data_r_ptr, len, TFM_MEMORY_ACCESS_RO)
+        != TFM_SUCCESS) {
+        CORE_TEST_RETURN_ERROR(CORE_TEST_ERRNO_INVALID_BUFFER);
+    }
+    mem[0] = *data_r_ptr;
+
+    /* Write to NS data region */
+    if (tfm_core_memory_permission_check(data_w_ptr, len, TFM_MEMORY_ACCESS_RW)
+        != TFM_SUCCESS) {
+        CORE_TEST_RETURN_ERROR(CORE_TEST_ERRNO_INVALID_BUFFER);
+    }
+    data_w_ptr[0] = mem[0];
+    data_w_ptr[1] = len;
+
+    /* Read from NS code region */
+    if (tfm_core_memory_permission_check(code_ptr, len, TFM_MEMORY_ACCESS_RO)
+        != TFM_SUCCESS) {
+        CORE_TEST_RETURN_ERROR(CORE_TEST_ERRNO_INVALID_BUFFER);
+    }
+    data_w_ptr[2] = *code_ptr;
+
+    return TFM_SUCCESS;
+}
+
+int32_t test_memory_permissions(
+    uint32_t *data_r_ptr, uint32_t *code_ptr, uint32_t *data_w_ptr)
+{
+    int32_t len = sizeof(uint32_t);
+    /* Read from NS data region */
+    if (tfm_core_memory_permission_check(data_r_ptr, len, TFM_MEMORY_ACCESS_RO)
+        != TFM_SUCCESS) {
+        CORE_TEST_RETURN_ERROR(CORE_TEST_ERRNO_UNEXPECTED_CORE_BEHAVIOUR);
+    }
+
+    /* Write to NS data region */
+    if (tfm_core_memory_permission_check(data_w_ptr, len, TFM_MEMORY_ACCESS_RW)
+        != TFM_SUCCESS) {
+        CORE_TEST_RETURN_ERROR(CORE_TEST_ERRNO_UNEXPECTED_CORE_BEHAVIOUR);
+    }
+
+    /* Read from NS code region */
+    if (tfm_core_memory_permission_check(code_ptr, len, TFM_MEMORY_ACCESS_RO)
+        != TFM_SUCCESS) {
+        CORE_TEST_RETURN_ERROR(CORE_TEST_ERRNO_UNEXPECTED_CORE_BEHAVIOUR);
+    }
+
+    /* Write to NS code region - should be rejected */
+    if (tfm_core_memory_permission_check(code_ptr, len, TFM_MEMORY_ACCESS_RW)
+        == TFM_SUCCESS) {
+        CORE_TEST_RETURN_ERROR(CORE_TEST_ERRNO_UNEXPECTED_CORE_BEHAVIOUR);
+    }
+
+    /* NS peripheral region - should be rejected */
+    if (tfm_core_memory_permission_check(
+        (uint32_t *)0x40000000, len, TFM_MEMORY_ACCESS_RO) == TFM_SUCCESS) {
+        CORE_TEST_RETURN_ERROR(CORE_TEST_ERRNO_UNEXPECTED_CORE_BEHAVIOUR);
+    }
+
+    /* S peripheral region - should be rejected */
+    if (tfm_core_memory_permission_check(
+        (uint32_t *)0x50000000, len, TFM_MEMORY_ACCESS_RO) == TFM_SUCCESS) {
+        CORE_TEST_RETURN_ERROR(CORE_TEST_ERRNO_UNEXPECTED_CORE_BEHAVIOUR);
+    }
+
+    return TFM_SUCCESS;
+}
+
+int32_t test_share_redirection(void)
+{
+    uint32_t tmp;
+
+    if (tfm_core_set_buffer_area(TFM_BUFFER_SHARE_SCRATCH) != TFM_SUCCESS) {
+        return CORE_TEST_ERRNO_UNEXPECTED_CORE_BEHAVIOUR;
+    }
+    /* Read from scratch */
+    tmp = tfm_scratch_area[0];
+    /* Write to scratch */
+    tfm_scratch_area[1] = tmp;
+
+    return TFM_SUCCESS;
+}
+
+int32_t test_peripheral_access(void)
+{
+    struct arm_mps2_fpgaio_t *fpgaio = SEC_MPS2_FPGAIO;
+    /* Check read access */
+    uint32_t leds = fpgaio->LED;
+    /* Write access */
+    fpgaio->LED = ~leds;
+    /* Check result of write access, only compare 2 valid bits */
+    uint32_t invleds = fpgaio->LED;
+
+    if ((invleds & MPS2_USERLED_MASK) != (~leds & MPS2_USERLED_MASK)) {
+        /* Code failed to invert value in peripheral reg */
+        return CORE_TEST_ERRNO_PERIPHERAL_ACCESS_FAILED;
+    }
+
+    return TFM_SUCCESS;
+}
+
+#define SS_BUFFER_LEN 16
+
+int32_t test_ss_to_ss_buffer(uint32_t *in_ptr, uint32_t *out_ptr, int32_t len)
+{
+    int32_t i;
+    /* Service internal buffer */
+    uint32_t ss_buffer[SS_BUFFER_LEN];
+    /* Slave service has to use scratch area */
+    uint32_t *slave_buffer = (uint32_t *)tfm_scratch_area;
+    /* Store result at end of scratch area to test entire range for RW access */
+    int32_t *result_ptr = (int32_t *)&tfm_scratch_area[tfm_scratch_area_size-4];
+
+    if (len > SS_BUFFER_LEN) {
+        return CORE_TEST_ERRNO_TEST_FAULT;
+    }
+
+    /* Check requires byte-based size */
+    if ((tfm_core_memory_permission_check(in_ptr, len << 2,
+        TFM_MEMORY_ACCESS_RW) != TFM_SUCCESS) ||
+        (tfm_core_memory_permission_check(out_ptr, len << 2,
+        TFM_MEMORY_ACCESS_RW) != TFM_SUCCESS)) {
+        return CORE_TEST_ERRNO_INVALID_BUFFER;
+    }
+
+    for (i = 0; i < len; i++) {
+        ss_buffer[i] = in_ptr[i];
+    }
+
+    if (tfm_core_set_buffer_area(TFM_BUFFER_SHARE_SCRATCH) != TFM_SUCCESS) {
+        return CORE_TEST_ERRNO_UNEXPECTED_CORE_BEHAVIOUR;
+    }
+
+    for (i = 0; i < len; i++) {
+        slave_buffer[i] = ss_buffer[i];
+    }
+
+    /* Call internal service with buffer handling */
+    int32_t res = tfm_core_test_2_sfn_invert(result_ptr, slave_buffer,
+                                         slave_buffer, len);
+
+    if (res != TFM_SUCCESS) {
+        return CORE_TEST_ERRNO_SLAVE_SERVICE_CALL_FAILURE;
+    }
+
+    for (i = 0; i < len; i++) {
+        if (slave_buffer[i] != ~ss_buffer[i]) {
+            return CORE_TEST_ERRNO_SLAVE_SERVICE_BUFFER_FAILURE;
+        }
+        ss_buffer[i] = slave_buffer[i];
+    }
+
+    if (tfm_core_set_buffer_area(TFM_BUFFER_SHARE_DEFAULT) != TFM_SUCCESS) {
+        return CORE_TEST_ERRNO_UNEXPECTED_CORE_BEHAVIOUR;
+    }
+
+    for (i = 0; i < len; i++) {
+        out_ptr[i] = ss_buffer[i];
+    }
+
+    return TFM_SUCCESS;
+}
+
+
+static int32_t test_ss_to_ss(void)
+{
+    /* Call to a different service, should be sucessful */
+    int32_t ret = tfm_core_test_2_veneer_slave_service();
+
+    if (ret == TFM_SUCCESS) {
+        return CORE_TEST_ERRNO_SUCCESS;
+    } else {
+        return CORE_TEST_ERRNO_SLAVE_SERVICE_CALL_FAILURE;
+    }
+}
+
+#ifdef CORE_TEST_INTERACTIVE
+#define MPS2_USERPB0_BASE   (0x50302008)
+#define MPS2_USERPB0_MASK   (0x1)
+
+static void wait_button_event(void)
+{
+    volatile uint32_t *p_btn = (volatile uint32_t *) MPS2_USERPB0_BASE;
+    *p_btn = *p_btn;
+
+    /* Wait until user button 0 is pressed */
+    while (!(*p_btn & MPS2_USERPB0_MASK)) {
+      ;
+    }
+
+    /*
+     * The follow wait is required to skip multiple continues in one go due to
+     * the fast execution of the code and time used by the user to
+     * release button.
+     */
+
+    /* Wait until user button 0 is released */
+    while ((*p_btn & MPS2_USERPB0_MASK)) {
+      ;
+    }
+}
+
+int32_t test_wait_button(void)
+{
+    LOG_MSG("Inside the service, press button to continue...");
+    wait_button_event();
+    LOG_MSG("Leaving the service");
+}
+#endif
+
+static int32_t test_block(int32_t arg1, int32_t arg2, int32_t arg3)
+{
+#ifdef CORE_TEST_INTERACTIVE
+    /* Only block if interactive test is turned on */
+    LOG_MSG("Inside the service, press button to continue...");
+    wait_button_event();
+    LOG_MSG("Leaving the service");
+    return TFM_SUCCESS;
+#else
+    /* This test should not be run if interactive tests are disabled */
+    return CORE_TEST_ERRNO_TEST_FAULT;
+#endif /* CORE_TEST_INTERACTIVE */
+}
+
+int32_t spm_core_test_sfn(int32_t tc, int32_t arg1, int32_t arg2, int32_t arg3)
+{
+    switch (tc) {
+    case CORE_TEST_ID_MPU_ACCESS:
+        return test_mpu_access(
+            (uint32_t *)arg1, (uint32_t *)arg2, (uint32_t *)arg3);
+    case CORE_TEST_ID_MEMORY_PERMISSIONS:
+        return test_memory_permissions(
+            (uint32_t *)arg1, (uint32_t *)arg2, (uint32_t *)arg3);
+    case CORE_TEST_ID_SHARE_REDIRECTION:
+        return test_share_redirection();
+    case CORE_TEST_ID_SS_TO_SS:
+        return test_ss_to_ss();
+    case CORE_TEST_ID_SS_TO_SS_BUFFER:
+        return test_ss_to_ss_buffer((uint32_t *)arg1, (uint32_t *)arg2, arg3);
+    case CORE_TEST_ID_PERIPHERAL_ACCESS:
+        return test_peripheral_access();
+    case CORE_TEST_ID_BLOCK:
+        return test_block(arg1, arg2, arg3);
+    case CORE_TEST_ID_NS_THREAD:
+    case CORE_TEST_ID_NS_SVC:
+    case CORE_TEST_ID_TWO_SFN_ONE_SVC:
+        /* dummy service call is enough */
+        return CORE_TEST_ERRNO_SUCCESS;
+    default:
+        return CORE_TEST_ERRNO_INVALID_TEST_ID;
+    }
+}
diff --git a/test/test_services/tfm_core_test/tfm_ss_core_test.h b/test/test_services/tfm_core_test/tfm_ss_core_test.h
new file mode 100644
index 0000000..44d0a5b
--- /dev/null
+++ b/test/test_services/tfm_core_test/tfm_ss_core_test.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_SS_CORE_TEST_H__
+#define __TFM_SS_CORE_TEST_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <inttypes.h>
+#include <limits.h>
+
+/**
+ * \brief Tests whether the initialisation of the service was successful.
+ *
+ * \return Returns \ref CORE_TEST_ERRNO_SUCCESS on success, and
+ *                 \ref CORE_TEST_ERRNO_SERVICE_NOT_INITED on failure.
+ */
+int32_t spm_core_test_sfn_init_success(void);
+
+/**
+ * \brief Tests what happens when a service calls itself directly.
+ *
+ * \param[in] depth  The current depth of the call (0 when first called).
+ *
+ * \return Returns \ref CORE_TEST_ERRNO_SUCCESS.
+ */
+int32_t spm_core_test_sfn_direct_recursion(int32_t depth);
+
+/**
+ * \brief Entry point for multiple test cases to be executed on the secure side.
+ *
+ * \param[in] a  The id of the testcase.
+ * \param[in] b  First parameter for testcase.
+ * \param[in] c  Second parameter for testcase.
+ * \param[in] d  Third parameter for testcase.
+ *
+ * \return Can return various error codes.
+ */
+int32_t spm_core_test_sfn(int32_t tc, int32_t arg1, int32_t arg2, int32_t arg3);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_SS_CORE_TEST_H__ */
diff --git a/test/test_services/tfm_core_test/tfm_ss_core_test_veneers.c b/test/test_services/tfm_core_test/tfm_ss_core_test_veneers.c
new file mode 100644
index 0000000..0568411
--- /dev/null
+++ b/test/test_services/tfm_core_test/tfm_ss_core_test_veneers.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "tfm_ss_core_test_veneers.h"
+#include "tfm_secure_api.h"
+#include "tfm_ss_core_test.h"
+#include "secure_fw/spm/spm_api.h"
+
+int32_t tfm_core_test_sfn_init_success(void)
+{
+    TFM_CORE_SERVICE_REQUEST(TFM_SEC_FUNC_CORE_TEST_ID,
+                             spm_core_test_sfn_init_success,
+                             0, 0, 0, 0);
+}
+
+int32_t tfm_core_test_sfn_direct_recursion(int32_t depth)
+{
+    TFM_CORE_SERVICE_REQUEST(TFM_SEC_FUNC_CORE_TEST_ID,
+                             spm_core_test_sfn_direct_recursion,
+                             depth, 0, 0, 0);
+}
+
+int32_t tfm_core_test_sfn(int32_t a, int32_t b, int32_t c, int32_t d)
+{
+    TFM_CORE_SERVICE_REQUEST(TFM_SEC_FUNC_CORE_TEST_ID, spm_core_test_sfn,
+                             a, b, c, d);
+}
diff --git a/test/test_services/tfm_core_test/tfm_ss_core_test_veneers.h b/test/test_services/tfm_core_test/tfm_ss_core_test_veneers.h
new file mode 100644
index 0000000..a7d1089
--- /dev/null
+++ b/test/test_services/tfm_core_test/tfm_ss_core_test_veneers.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_SS_CORE_TEST_VENEERS_H__
+#define __TFM_SS_CORE_TEST_VENEERS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <cmsis_compiler.h>
+
+/**
+ * \brief Tests whether the initialisation of the service was successful.
+ *
+ * \return Returns \ref CORE_TEST_ERRNO_SUCCESS on success, and
+ *                 \ref CORE_TEST_ERRNO_SERVICE_NOT_INITED on failure.
+ */
+int32_t tfm_core_test_sfn_init_success(void)
+__attribute__((cmse_nonsecure_entry, noinline, section("SFN")));
+
+/**
+ * \brief Tests what happens when a service calls itself directly.
+ *
+ * \param[in] depth  The current depth of the call (0 when first called).
+ *
+ * \return Returns \ref CORE_TEST_ERRNO_SUCCESS on succes, error othervise.
+ */
+int32_t tfm_core_test_sfn_direct_recursion(int32_t depth)
+__attribute__((cmse_nonsecure_entry, noinline, section("SFN")));
+
+/**
+ * \brief Entry point for multiple test cases to be executed on the secure side.
+ *
+ * \param[in] a  The id of the testcase.
+ * \param[in] b  First parameter for testcase.
+ * \param[in] c  Second parameter for testcase.
+ * \param[in] d  Third parameter for testcase.
+ *
+ * \return Can return various error codes.
+ */
+int32_t tfm_core_test_sfn(int32_t a, int32_t b, int32_t c, int32_t d)
+__attribute__((cmse_nonsecure_entry, noinline, section("SFN")));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_SS_CORE_TEST_VENEERS_H__ */
diff --git a/test/test_services/tfm_core_test_2/tfm_ss_core_test_2.c b/test/test_services/tfm_core_test_2/tfm_ss_core_test_2.c
new file mode 100644
index 0000000..08f1389
--- /dev/null
+++ b/test/test_services/tfm_core_test_2/tfm_ss_core_test_2.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stddef.h>
+#include "tfm_ss_core_test_2.h"
+#include "tfm_api.h"
+#include "tfm_secure_api.h"
+#include "test/test_services/tfm_core_test/core_test_defs.h"
+
+int32_t core_test_2_init(void)
+{
+    return TFM_ERROR_GENERIC;
+}
+
+int32_t spm_core_test_2_slave_service(void)
+{
+    return TFM_SUCCESS;
+}
+
+/* Invert function */
+#define SFN_INVERT_MAX_LEN 128
+
+int32_t spm_core_test_2_sfn_invert(int32_t *res_ptr, uint32_t *in_ptr,
+                                   uint32_t *out_ptr, int32_t len)
+{
+    int32_t i;
+    static uint32_t invert_buffer[SFN_INVERT_MAX_LEN];
+
+    if (tfm_core_memory_permission_check(res_ptr, sizeof(int32_t),
+        TFM_MEMORY_ACCESS_RW) != TFM_SUCCESS) {
+        return TFM_SERVICE_BUSY;
+    }
+
+    *res_ptr = -1;
+
+    if (len > SFN_INVERT_MAX_LEN) {
+        return TFM_SERVICE_BUSY;
+    }
+
+    /* Check requires byte-based size */
+    if ((tfm_core_memory_permission_check(in_ptr, len << 2,
+        TFM_MEMORY_ACCESS_RW) != TFM_SUCCESS) ||
+        (tfm_core_memory_permission_check(out_ptr, len << 2,
+        TFM_MEMORY_ACCESS_RW) != TFM_SUCCESS)) {
+        return TFM_SERVICE_BUSY;
+    }
+
+    for (i = 0; i < len; i++) {
+        invert_buffer[i] = in_ptr[i];
+    }
+    for (i = 0; i < len; i++) {
+        invert_buffer[i] = ~invert_buffer[i];
+    }
+    for (i = 0; i < len; i++) {
+        out_ptr[i] = invert_buffer[i];
+    }
+
+    *res_ptr = 0;
+    return TFM_SUCCESS;
+}
diff --git a/test/test_services/tfm_core_test_2/tfm_ss_core_test_2.h b/test/test_services/tfm_core_test_2/tfm_ss_core_test_2.h
new file mode 100644
index 0000000..46b3573
--- /dev/null
+++ b/test/test_services/tfm_core_test_2/tfm_ss_core_test_2.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_SS_CORE_TEST_2_H__
+#define __TFM_SS_CORE_TEST_2_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <inttypes.h>
+#include <limits.h>
+
+/**
+ * \brief A minimal test service to be called from another service.
+ *
+ * \return Returns \ref TFM_SUCCESS.
+ */
+int32_t spm_core_test_2_slave_service(void);
+
+
+/**
+ * \brief Bitwise inverts the buffer received as input.
+ *
+ * \param[out] res_ptr  Result, 0 on success, -1 othervise.
+ * \param[in] in_ptr    Buffer containing data to be inverted.
+ * \param[out] out_ptr  Buffer to store the inverted data.
+ * \param[in] len       Number of bytes to be inverted.
+ *
+ * \return Returns \ref TFM_SUCCESS on success, TFM_SERVICE_BUSY otherwise.
+ */
+int32_t spm_core_test_2_sfn_invert(
+        int32_t *res_ptr, uint32_t *in_ptr, uint32_t *out_ptr, int32_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_SS_CORE_TEST_2_H__ */
diff --git a/test/test_services/tfm_core_test_2/tfm_ss_core_test_2_veneers.c b/test/test_services/tfm_core_test_2/tfm_ss_core_test_2_veneers.c
new file mode 100644
index 0000000..ca8d437
--- /dev/null
+++ b/test/test_services/tfm_core_test_2/tfm_ss_core_test_2_veneers.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "tfm_ss_core_test_2_veneers.h"
+#include "tfm_secure_api.h"
+#include "tfm_ss_core_test_2.h"
+#include "secure_fw/spm/spm_api.h"
+
+/* Add functions to the service*/
+int32_t tfm_core_test_2_veneer_slave_service(void)
+{
+   TFM_CORE_SERVICE_REQUEST(TFM_SEC_FUNC_CORE_TEST_2_ID,
+                            spm_core_test_2_slave_service,
+                            0, 0, 0, 0);
+}
+
+int32_t tfm_core_test_2_sfn_invert(int32_t *res_ptr, uint32_t *in_ptr,
+                                   uint32_t *out_ptr, int32_t len)
+{
+    TFM_CORE_SERVICE_REQUEST(TFM_SEC_FUNC_CORE_TEST_2_ID,
+                             spm_core_test_2_sfn_invert,
+                             res_ptr, in_ptr, out_ptr, len);
+}
diff --git a/test/test_services/tfm_core_test_2/tfm_ss_core_test_2_veneers.h b/test/test_services/tfm_core_test_2/tfm_ss_core_test_2_veneers.h
new file mode 100644
index 0000000..50d8ad6
--- /dev/null
+++ b/test/test_services/tfm_core_test_2/tfm_ss_core_test_2_veneers.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_SS_CORE_TEST_2_VENEERS_H__
+#define __TFM_SS_CORE_TEST_2_VENEERS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <cmsis_compiler.h>
+
+/**
+ * \brief A minimal test service to be called from another service.
+ *
+ * \return Returns \ref TFM_SUCCESS.
+ */
+int32_t tfm_core_test_2_veneer_slave_service(void)
+__attribute__((cmse_nonsecure_entry, noinline, section("SFN")));
+
+/**
+ * \brief Bitwise inverts the buffer received as input.
+ *
+ * \param[out] res_ptr  Result, 0 on success, -1 othervise.
+ * \param[in] in_ptr    Buffer containing data to be inverted.
+ * \param[out] out_ptr  Buffer to store the inverted data.
+ * \param[in] len       Number of bytes to be inverted.
+ *
+ * \return Returns \ref TFM_SUCCESS on success, TFM_SERVICE_BUSY otherwise.
+ */
+__attribute__((cmse_nonsecure_entry, noinline, section("SFN")))
+int32_t tfm_core_test_2_sfn_invert(
+        int32_t *res_ptr, uint32_t *in_ptr, uint32_t *out_ptr, int32_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_SS_CORE_TEST_2_VENEERS_H__ */