Test: Add a negative test case for isolation level 3

To verify if the boundary is set up correctly inside SPE, create a test
case to access memory in another ARoT partition. This is a negative test
and it causes hang, the switch is default as OFF.

Change-Id: Ie1d17c18d78ff24133ff3e5dede37db1c37b23e6
Signed-off-by: Shawn Shan <Shawn.Shan@arm.com>
diff --git a/test/suites/ipc/non_secure/ipc_ns_interface_testsuite.c b/test/suites/ipc/non_secure/ipc_ns_interface_testsuite.c
index d051b78..1cde2eb 100644
--- a/test/suites/ipc/non_secure/ipc_ns_interface_testsuite.c
+++ b/test/suites/ipc/non_secure/ipc_ns_interface_testsuite.c
@@ -35,6 +35,10 @@
 
 static void tfm_ipc_test_1010(struct test_result_t *ret);
 
+#ifdef TFM_IPC_ISOLATION_3_RETRIEVE_APP_MEM
+static void tfm_ipc_test_1011(struct test_result_t *ret);
+#endif
+
 static struct test_t ipc_veneers_tests[] = {
     {&tfm_ipc_test_1001, "TFM_IPC_TEST_1001",
      "Get PSA framework version", {TEST_PASSED}},
@@ -62,6 +66,10 @@
 #endif
     {&tfm_ipc_test_1010, "TFM_IPC_TEST_1010",
      "Test psa_call with the status of PSA_ERROR_PROGRAMMER_ERROR", {TEST_PASSED}},
+#ifdef TFM_IPC_ISOLATION_3_RETRIEVE_APP_MEM
+    {&tfm_ipc_test_1011, "TFM_IPC_TEST_1011",
+     "Call APP RoT access APP RoT memory test service", {TEST_PASSED}},
+#endif
 };
 
 void register_testsuite_ns_ipc_interface(struct test_suite_t *p_test_suite)
@@ -360,3 +368,32 @@
 
     psa_close(handle);
 }
+
+#ifdef TFM_IPC_ISOLATION_3_RETRIEVE_APP_MEM
+/**
+ * \brief Call IPC_CLIENT_TEST_RETRIEVE_APP_MEM_SID RoT Service
+ *  to run the IPC PSA access APP mem test.
+ */
+static void tfm_ipc_test_1011(struct test_result_t *ret)
+{
+    psa_handle_t handle;
+    int test_result;
+    struct psa_outvec outvecs[1] = {{&test_result, sizeof(test_result)}};
+
+    handle = psa_connect(IPC_CLIENT_TEST_RETRIEVE_APP_MEM_SID,
+                         IPC_CLIENT_TEST_RETRIEVE_APP_MEM_VERSION);
+    if (handle > 0) {
+        TEST_LOG("Connect success!\r\n");
+    } else {
+        TEST_LOG("The RoT Service has refused the connection!\r\n");
+        ret->val = TEST_FAILED;
+        return;
+    }
+
+    psa_call(handle, PSA_IPC_CALL, NULL, 0, outvecs, 1);
+
+    /* The system should panic in psa_call. If runs here, the test fails. */
+    ret->val = TEST_FAILED;
+    psa_close(handle);
+}
+#endif
diff --git a/test/test_services/CMakeLists.inc b/test/test_services/CMakeLists.inc
index afece9f..46cbb1b 100644
--- a/test/test_services/CMakeLists.inc
+++ b/test/test_services/CMakeLists.inc
@@ -83,6 +83,7 @@
 embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE)
 embedded_include_directories(PATH ${TFM_ROOT_DIR}/platform/include ABSOLUTE)
 embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/include ABSOLUTE)
+embedded_include_directories(PATH ${CORE_TEST_DIR}/tfm_secure_client_2 ABSOLUTE)
 
 set(BUILD_CMSIS_CORE Off)
 set(BUILD_RETARGET Off)
diff --git a/test/test_services/tfm_ipc_client/psa_manifest/tfm_ipc_client_test.h b/test/test_services/tfm_ipc_client/psa_manifest/tfm_ipc_client_test.h
index da942bb..118f747 100644
--- a/test/test_services/tfm_ipc_client/psa_manifest/tfm_ipc_client_test.h
+++ b/test/test_services/tfm_ipc_client/psa_manifest/tfm_ipc_client_test.h
@@ -19,6 +19,7 @@
 #define IPC_CLIENT_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SIGNAL     (1U << (2 + 4))
 #define IPC_CLIENT_TEST_APP_ACCESS_PSA_MEM_SIGNAL               (1U << (3 + 4))
 #define IPC_CLIENT_TEST_MEM_CHECK_SIGNAL                        (1U << (4 + 4))
+#define IPC_CLIENT_TEST_RETRIEVE_APP_MEM_SIGNAL                 (1U << (5 + 4))
 
 #ifdef __cplusplus
 }
diff --git a/test/test_services/tfm_ipc_client/tfm_ipc_client_test.c b/test/test_services/tfm_ipc_client/tfm_ipc_client_test.c
index 2528e16..60105e6 100644
--- a/test/test_services/tfm_ipc_client/tfm_ipc_client_test.c
+++ b/test/test_services/tfm_ipc_client/tfm_ipc_client_test.c
@@ -5,13 +5,14 @@
  *
  */
 
-#include <stdio.h>
 #include <assert.h>
+#include <stdio.h>
 #include "psa/client.h"
 #include "psa/service.h"
-#include "psa_manifest/tfm_ipc_client_test.h"
-#include "utilities.h"
 #include "psa_manifest/sid.h"
+#include "psa_manifest/tfm_ipc_client_test.h"
+#include "tfm_secure_client_2_api.h"
+#include "utilities.h"
 
 /* Define the return status */
 #define IPC_SP_TEST_SUCCESS     (1)
@@ -134,7 +135,7 @@
     status = psa_call(handle, PSA_IPC_CALL, NULL, 0, outvecs, 1);
     if (status >= 0) {
         /*
-         * outvecs should contain the pointer pointed to ipc service parition
+         * outvecs should contain the pointer pointed to ipc service partition
          * memory. Read the pointed memory should cause panic.
          */
         uint8_t *psa_data_p = outvec_data[0];
@@ -168,7 +169,7 @@
     status = psa_call(handle, PSA_IPC_CALL, NULL, 0, outvecs, 1);
     if (status >= 0) {
         /*
-         * outvecs should contain the pointer pointed to ipc service parition
+         * outvecs should contain the pointer pointed to ipc service partition
          * memory. In psa_call, it checks whether the target partition has the
          * access right to the invecs indicated memory. If no, the system will
          * panic.
@@ -187,6 +188,40 @@
 }
 #endif
 
+#ifdef TFM_IPC_ISOLATION_3_RETRIEVE_APP_MEM
+static int ipc_client_retrieve_app_mem_test(void)
+{
+    psa_handle_t handle;
+    psa_status_t status;
+    uint8_t *outvec_data[1] = {0};
+    struct psa_outvec outvecs[1] = {{outvec_data, sizeof(outvec_data[0])}};
+
+    handle = psa_connect(TFM_SECURE_CLIENT_2_SID,
+                         TFM_SECURE_CLIENT_2_VERSION);
+
+    if (handle <= 0) {
+        return IPC_SP_TEST_FAILED;
+    }
+
+    status = psa_call(handle, TFM_SECURE_CLIENT_2_ID_RETRIEVE_APP_MEM, NULL, 0,
+                      outvecs, 1);
+    if (status >= 0) {
+        /*
+         * outvecs should contain the pointer pointed to app service partition
+         * memory. Read the pointed memory should cause panic.
+         */
+        uint8_t *psa_data_p = outvec_data[0];
+        if (psa_data_p) {
+            (*psa_data_p)++;
+        }
+    }
+
+    /* The system should panic before here. */
+    psa_close(handle);
+    return IPC_SP_TEST_FAILED;
+}
+#endif
+
 static void ipc_client_handle_ser_req(psa_msg_t msg, uint32_t signals,
                                       int (*fn)(void))
 {
@@ -255,6 +290,12 @@
             ipc_client_handle_ser_req(msg, IPC_CLIENT_TEST_MEM_CHECK_SIGNAL,
                                       &ipc_client_mem_check_test);
 #endif
+#ifdef TFM_IPC_ISOLATION_3_RETRIEVE_APP_MEM
+        } else if (signals & IPC_CLIENT_TEST_RETRIEVE_APP_MEM_SIGNAL) {
+            ipc_client_handle_ser_req(msg,
+            IPC_CLIENT_TEST_RETRIEVE_APP_MEM_SIGNAL,
+            &ipc_client_retrieve_app_mem_test);
+#endif
         } else {
             /* Should not go here. */
             tfm_abort();
diff --git a/test/test_services/tfm_ipc_client/tfm_ipc_client_test.yaml b/test/test_services/tfm_ipc_client/tfm_ipc_client_test.yaml
index e66139e..68d05f7 100644
--- a/test/test_services/tfm_ipc_client/tfm_ipc_client_test.yaml
+++ b/test/test_services/tfm_ipc_client/tfm_ipc_client_test.yaml
@@ -49,12 +49,20 @@
       "non_secure_clients": true,
       "version": 1,
       "version_policy": "STRICT"
+    },
+    {
+      "name": "IPC_CLIENT_TEST_RETRIEVE_APP_MEM",
+      "sid": "0x0000F065",
+      "non_secure_clients": true,
+      "version": 1,
+      "version_policy": "STRICT"
     }
   ],
   "dependencies": [
     "IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM",
     "IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM",
     "IPC_SERVICE_TEST_BASIC",
-    "IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM"
+    "IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM",
+    "TFM_SECURE_CLIENT_2"
   ]
 }
diff --git a/test/test_services/tfm_secure_client_2/tfm_secure_client_2.c b/test/test_services/tfm_secure_client_2/tfm_secure_client_2.c
index 153caac..442aca0 100644
--- a/test/test_services/tfm_secure_client_2/tfm_secure_client_2.c
+++ b/test/test_services/tfm_secure_client_2/tfm_secure_client_2.c
@@ -16,6 +16,12 @@
 #include "psa/client.h"
 #endif
 
+#ifdef TFM_IPC_ISOLATION_3_RETRIEVE_APP_MEM
+/* Define the global variable for the TFM_SECURE_CLIENT_2_SID service. */
+uint8_t secure_client_2_data;
+uint8_t *secure_client_2_data_p = &secure_client_2_data;
+#endif
+
 #ifdef ENABLE_CRYPTO_SERVICE_TESTS
 /**
  * \brief Tests calling psa_destroy_key() with the supplied key handle.
@@ -68,6 +74,26 @@
 }
 #endif /* ENABLE_INTERNAL_TRUSTED_STORAGE_SERVICE_TESTS */
 
+#ifdef TFM_IPC_ISOLATION_3_RETRIEVE_APP_MEM
+/**
+ * \brief Tests calling psa_write() to write a pointer to outvec.
+ *
+ * \param[in] msg    Pointer to the message of the test function
+ */
+static void secure_client_2_test_retrieve_app_mem(psa_msg_t *msg)
+{
+        if (msg->out_size[0] != 0) {
+            /*
+             * Write a pointer to outvec. The pointer points to uint8_t
+             * memory in ipc servive partition.
+             */
+            psa_write(msg->handle, 0, &secure_client_2_data_p,
+                      sizeof(secure_client_2_data_p));
+        }
+        psa_reply(msg->handle, PSA_SUCCESS);
+}
+#endif /* TFM_IPC_ISOLATION_3_RETRIEVE_APP_MEM */
+
 /**
  * \brief Calls the test function with the supplied ID and returns the result
  *        from the test function.
@@ -114,6 +140,11 @@
         case PSA_IPC_DISCONNECT:
             psa_reply(msg.handle, PSA_SUCCESS);
             break;
+#ifdef TFM_IPC_ISOLATION_3_RETRIEVE_APP_MEM
+        case TFM_SECURE_CLIENT_2_ID_RETRIEVE_APP_MEM:
+            secure_client_2_test_retrieve_app_mem(&msg);
+            break;
+#endif
         default:
             len = psa_read(msg.handle, 0, arg, SECURE_CLIENT_2_MAX_ARG_LEN);
             psa_reply(msg.handle, secure_client_2_dispatch(msg.type, arg, len));
diff --git a/test/test_services/tfm_secure_client_2/tfm_secure_client_2_api.h b/test/test_services/tfm_secure_client_2/tfm_secure_client_2_api.h
index a6018c5..2d2fd5b 100644
--- a/test/test_services/tfm_secure_client_2/tfm_secure_client_2_api.h
+++ b/test/test_services/tfm_secure_client_2/tfm_secure_client_2_api.h
@@ -19,6 +19,7 @@
 
 #define TFM_SECURE_CLIENT_2_ID_ITS_ACCESS_CTRL    1001
 #define TFM_SECURE_CLIENT_2_ID_CRYPTO_ACCESS_CTRL 2001
+#define TFM_SECURE_CLIENT_2_ID_RETRIEVE_APP_MEM   3001
 
 /**
  * \brief Calls the test function with the supplied ID within the execution