Core: Add connect handle check

Check from the two aspects:
- Check the validation of the connection handle by checking if it is
  allocated from conn_handle_pool.
- Check the ownership of the connection handle by checking if the
  client_id stored in handle is the same as the current caller.

Change-Id: I4a6031f34d022760800acf1c3a41c4f7dc7747cc
Signed-off-by: Summer Qin <summer.qin@arm.com>
diff --git a/secure_fw/core/ipc/tfm_psa_client_call.c b/secure_fw/core/ipc/tfm_psa_client_call.c
index 668a262..40ba17e 100644
--- a/secure_fw/core/ipc/tfm_psa_client_call.c
+++ b/secure_fw/core/ipc/tfm_psa_client_call.c
@@ -15,6 +15,7 @@
 #include "tfm_psa_client_call.h"
 #include "tfm_utils.h"
 #include "tfm_wait.h"
+#include "tfm_nspm.h"
 
 uint32_t tfm_psa_framework_version(void)
 {
@@ -51,6 +52,7 @@
     struct tfm_spm_service_t *service;
     struct tfm_msg_body_t *msg;
     psa_handle_t connect_handle;
+    int32_t client_id;
 
     /* It is a fatal error if the RoT Service does not exist on the platform */
     service = tfm_spm_get_service_by_sid(sid);
@@ -58,11 +60,17 @@
         tfm_panic();
     }
 
+    if (ns_caller) {
+        client_id = tfm_nspm_get_current_client_id();
+    } else {
+        client_id = tfm_spm_partition_get_running_partition_id();
+    }
+
     /*
      * Create connection handle here since it is possible to return the error
      * code to client when creation fails.
      */
-    connect_handle = tfm_spm_create_conn_handle(service);
+    connect_handle = tfm_spm_create_conn_handle(service, client_id);
     if (connect_handle == PSA_NULL_HANDLE) {
         return PSA_ERROR_CONNECTION_BUSY;
     }
@@ -91,7 +99,7 @@
 
     /* No input or output needed for connect message */
     tfm_spm_fill_msg(msg, service, connect_handle, PSA_IPC_CONNECT,
-                     ns_caller, NULL, 0, NULL, 0, NULL);
+                     client_id, NULL, 0, NULL, 0, NULL);
 
     /*
      * Send message and wake up the SP who is waiting on message queue,
@@ -112,6 +120,7 @@
     struct tfm_spm_service_t *service;
     struct tfm_msg_body_t *msg;
     int i;
+    int32_t client_id;
 
     /* It is a fatal error if in_len + out_len > PSA_MAX_IOVEC. */
     if ((in_num > PSA_MAX_IOVEC) ||
@@ -120,7 +129,16 @@
         tfm_panic();
     }
 
+    if (ns_caller) {
+        client_id = tfm_nspm_get_current_client_id();
+    } else {
+        client_id = tfm_spm_partition_get_running_partition_id();
+    }
+
     /* It is a fatal error if an invalid handle was passed. */
+    if (tfm_spm_validate_conn_handle(handle, client_id) != IPC_SUCCESS) {
+        tfm_panic();
+    }
     service = tfm_spm_get_service_by_handle(handle);
     if (!service) {
         /* FixMe: Need to implement one mechanism to resolve this failure. */
@@ -184,7 +202,7 @@
         tfm_panic();
     }
 
-    tfm_spm_fill_msg(msg, service, handle, type, ns_caller, invecs,
+    tfm_spm_fill_msg(msg, service, handle, type, client_id, invecs,
                      in_num, outvecs, out_num, outptr);
 
     /*
@@ -202,16 +220,26 @@
 {
     struct tfm_spm_service_t *service;
     struct tfm_msg_body_t *msg;
+    int32_t client_id;
 
     /* It will have no effect if called with the NULL handle */
     if (handle == PSA_NULL_HANDLE) {
         return;
     }
 
+    if (ns_caller) {
+        client_id = tfm_nspm_get_current_client_id();
+    } else {
+        client_id = tfm_spm_partition_get_running_partition_id();
+    }
+
     /*
      * It is a fatal error if an invalid handle was provided that is not the
      * null handle.
      */
+    if (tfm_spm_validate_conn_handle(handle, client_id) != IPC_SUCCESS) {
+        tfm_panic();
+    }
     service = tfm_spm_get_service_by_handle(handle);
     if (!service) {
         /* FixMe: Need to implement one mechanism to resolve this failure. */
@@ -231,7 +259,7 @@
     }
 
     /* No input or output needed for close message */
-    tfm_spm_fill_msg(msg, service, handle, PSA_IPC_DISCONNECT, ns_caller,
+    tfm_spm_fill_msg(msg, service, handle, PSA_IPC_DISCONNECT, client_id,
                      NULL, 0, NULL, 0, NULL);
 
     /*
diff --git a/secure_fw/spm/spm_api.h b/secure_fw/spm/spm_api.h
index 9929b3c..35be8c2 100644
--- a/secure_fw/spm/spm_api.h
+++ b/secure_fw/spm/spm_api.h
@@ -123,6 +123,12 @@
                                          * TFM_HANDLE_STATUS_ACTIVE and
                                          * TFM_HANDLE_STATUS_IDLE
                                          */
+    int32_t client_id;                  /*
+                                         * Partition ID of the sender of the
+                                         * message:
+                                         *  - secure partition id;
+                                         *  - non secure client endpoint id.
+                                         */
     struct tfm_msg_body_t internal_msg; /* Internal message for message queue */
     struct tfm_spm_service_t *service;  /* RoT service pointer               */
     struct tfm_list_node_t list;        /* list node                         */
@@ -412,11 +418,25 @@
  * \brief                   Create connection handle for client connect
  *
  * \param[in] service       Target service context pointer
+ * \param[in] client_id     Partition ID of the sender of the message
  *
  * \retval PSA_NULL_HANDLE  Create failed \ref PSA_NULL_HANDLE
  * \retval >0               Service handle created, \ref psa_handle_t
  */
-psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service);
+psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service,
+                                        int32_t client_id);
+
+/**
+ * \brief                   Validate connection handle for client connect
+ *
+ * \param[in] conn_handle   Handle to be validated
+ * \param[in] client_id     Partition ID of the sender of the message
+ *
+ * \retval IPC_SUCCESS        Success
+ * \retval IPC_ERROR_GENERIC  Invalid handle
+ */
+int32_t tfm_spm_validate_conn_handle(psa_handle_t conn_handle,
+                                     int32_t client_id);
 
 /**
  * \brief                   Free connection handle which not used anymore.
@@ -560,7 +580,7 @@
  * \prarm[in] handle        Connect handle return by psa_connect().
  * \param[in] type          Message type, PSA_IPC_CONNECT, PSA_IPC_CALL or
  *                          PSA_IPC_DISCONNECT
- * \param[in] ns_caller     Whether from NS caller
+ * \param[in] client_id     Partition ID of the sender of the message
  * \param[in] invec         Array of input \ref psa_invec structures
  * \param[in] in_len        Number of input \ref psa_invec structures
  * \param[in] outvec        Array of output \ref psa_outvec structures
@@ -570,7 +590,7 @@
 void tfm_spm_fill_msg(struct tfm_msg_body_t *msg,
                       struct tfm_spm_service_t *service,
                       psa_handle_t handle,
-                      int32_t type, int32_t ns_caller,
+                      int32_t type, int32_t client_id,
                       psa_invec *invec, size_t in_len,
                       psa_outvec *outvec, size_t out_len,
                       psa_outvec *caller_outvec);
diff --git a/secure_fw/spm/spm_api_ipc.c b/secure_fw/spm/spm_api_ipc.c
index 58a0fd3..4933e97 100644
--- a/secure_fw/spm/spm_api_ipc.c
+++ b/secure_fw/spm/spm_api_ipc.c
@@ -50,7 +50,8 @@
 /********************** SPM functions for handler mode ***********************/
 
 /* Service handle management functions */
-psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service)
+psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service,
+                                        int32_t client_id)
 {
     struct tfm_conn_handle_t *p_handle;
 
@@ -64,6 +65,7 @@
 
     p_handle->service = service;
     p_handle->status = TFM_HANDLE_STATUS_IDLE;
+    p_handle->client_id = client_id;
 
     /* Add handle node to list for next psa functions */
     tfm_list_add_tail(&service->handle_list, &p_handle->list);
@@ -71,6 +73,23 @@
     return (psa_handle_t)p_handle;
 }
 
+int32_t tfm_spm_validate_conn_handle(psa_handle_t conn_handle,
+                                     int32_t client_id)
+{
+    /* Check the handle address is validated */
+    if (is_valid_chunk_data_in_pool(conn_handle_pool,
+                                    (uint8_t *)conn_handle) != true) {
+        return IPC_ERROR_GENERIC;
+    }
+
+    /* Check the handle caller is correct */
+    if (((struct tfm_conn_handle_t *)conn_handle)->client_id != client_id) {
+        return IPC_ERROR_GENERIC;
+    }
+
+    return IPC_SUCCESS;
+}
+
 static struct tfm_conn_handle_t *
     tfm_spm_find_conn_handle_node(struct tfm_spm_service_t *service,
                                   psa_handle_t conn_handle)
@@ -304,7 +323,7 @@
 void tfm_spm_fill_msg(struct tfm_msg_body_t *msg,
                       struct tfm_spm_service_t *service,
                       psa_handle_t handle,
-                      int32_t type, int32_t ns_caller,
+                      int32_t type, int32_t client_id,
                       psa_invec *invec, size_t in_len,
                       psa_outvec *outvec, size_t out_len,
                       psa_outvec *caller_outvec)
@@ -327,12 +346,7 @@
     msg->service = service;
     msg->handle = handle;
     msg->caller_outvec = caller_outvec;
-    /* Get current partition id */
-    if (ns_caller) {
-        msg->msg.client_id = tfm_nspm_get_current_client_id();
-    } else {
-        msg->msg.client_id = tfm_spm_partition_get_running_partition_id();
-    }
+    msg->msg.client_id = client_id;
 
     /* Copy contents */
     msg->msg.type = type;