Core: Add dependency support

According to PSA FF, if access between a client Secure Partition and an
RoT Service is not specified in the manifest, then the client is not
allowed to connect to the RoT Service.

Change-Id: Iae45242a143981658e3fd73576b5a8f7f054a7bd
Signed-off-by: Edison Ai <edison.ai@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 40ba17e..f6d2f71 100644
--- a/secure_fw/core/ipc/tfm_psa_client_call.c
+++ b/secure_fw/core/ipc/tfm_psa_client_call.c
@@ -36,11 +36,11 @@
     }
 
     /*
-     * It should return PSA_VERSION_NONE if the caller is not authorized
-     * to access the RoT Service.
+     * It is a fatal error if the caller is not authorized to access the RoT
+     * Service.
      */
-    if (ns_caller && !service->service_db->non_secure_client) {
-        return PSA_VERSION_NONE;
+    if (tfm_spm_check_authorization(sid, service, ns_caller) != IPC_SUCCESS) {
+        tfm_panic();
     }
 
     return service->service_db->version;
@@ -67,6 +67,14 @@
     }
 
     /*
+     * It is a fatal error if the caller is not authorized to access the RoT
+     * Service.
+     */
+    if (tfm_spm_check_authorization(sid, service, ns_caller) != IPC_SUCCESS) {
+        tfm_panic();
+    }
+
+    /*
      * Create connection handle here since it is possible to return the error
      * code to client when creation fails.
      */
@@ -76,14 +84,6 @@
     }
 
     /*
-     * It is a fatal error if the caller is not authorized to access the RoT
-     * Service.
-     */
-    if (ns_caller && !service->service_db->non_secure_client) {
-        tfm_panic();
-    }
-
-    /*
      * It is a fatal error if the version of the RoT Service requested is not
      * supported on the platform.
      */
diff --git a/secure_fw/services/initial_attestation/tfm_initial_attestation.yaml b/secure_fw/services/initial_attestation/tfm_initial_attestation.yaml
index 2e790aa..015e75f 100644
--- a/secure_fw/services/initial_attestation/tfm_initial_attestation.yaml
+++ b/secure_fw/services/initial_attestation/tfm_initial_attestation.yaml
@@ -66,5 +66,8 @@
       "version": 1,
       "version_policy": "STRICT"
     }
+  ],
+  "dependencies": [
+    "TFM_CRYPTO"
   ]
 }
diff --git a/secure_fw/services/secure_storage/tfm_secure_storage.yaml b/secure_fw/services/secure_storage/tfm_secure_storage.yaml
index 74e46fa..e7c8a42 100644
--- a/secure_fw/services/secure_storage/tfm_secure_storage.yaml
+++ b/secure_fw/services/secure_storage/tfm_secure_storage.yaml
@@ -86,6 +86,9 @@
     "version_policy": "STRICT"
    }
   ],
+  "dependencies": [
+    "TFM_CRYPTO"
+  ],
   "linker_pattern": {
     "library_list": [
       "*tfm_storage*"
diff --git a/secure_fw/spm/spm_api.h b/secure_fw/spm/spm_api.h
index 35be8c2..9d748bc 100644
--- a/secure_fw/spm/spm_api.h
+++ b/secure_fw/spm/spm_api.h
@@ -628,6 +628,21 @@
                                      uint32_t version);
 
 /**
+ * \brief                   Check the client access authorization
+ *
+ * \param[in] sid           Target RoT Service identity
+ * \param[in] service       Target service context pointer, which can be get
+ *                          by partition management functions
+ * \param[in] ns_caller     Whether from NS caller
+ *
+ * \retval IPC_SUCCESS      Success
+ * \retval IPC_ERROR_GENERIC Authorization check failed
+ */
+int32_t tfm_spm_check_authorization(uint32_t sid,
+                                    struct tfm_spm_service_t *service,
+                                    int32_t ns_caller);
+
+/**
  * \brief                      Check the memory reference is valid.
  *
  * \param[in] buffer           Pointer of memory reference
diff --git a/secure_fw/spm/spm_api_ipc.c b/secure_fw/spm/spm_api_ipc.c
index 4933e97..6eed0c0 100644
--- a/secure_fw/spm/spm_api_ipc.c
+++ b/secure_fw/spm/spm_api_ipc.c
@@ -262,6 +262,38 @@
     return IPC_SUCCESS;
 }
 
+int32_t tfm_spm_check_authorization(uint32_t sid,
+                                    struct tfm_spm_service_t *service,
+                                    int32_t ns_caller)
+{
+    struct spm_partition_desc_t *partition = NULL;
+    int32_t i;
+
+    TFM_ASSERT(service);
+
+    if (ns_caller) {
+        if (!service->service_db->non_secure_client) {
+            return IPC_ERROR_GENERIC;
+        }
+    } else {
+        partition = tfm_spm_get_running_partition();
+        if (!partition) {
+            tfm_panic();
+        }
+
+        for (i = 0; i < partition->static_data->dependencies_num; i++) {
+            if (partition->static_data->p_dependencies[i] == sid) {
+                break;
+            }
+        }
+
+        if (i == partition->static_data->dependencies_num) {
+            return IPC_ERROR_GENERIC;
+        }
+    }
+    return IPC_SUCCESS;
+}
+
 /* Message functions */
 struct tfm_msg_body_t *tfm_spm_get_msg_from_handle(psa_handle_t msg_handle)
 {
diff --git a/secure_fw/spm/spm_db.h b/secure_fw/spm/spm_db.h
index c5869fc..593a180 100644
--- a/secure_fw/spm/spm_db.h
+++ b/secure_fw/spm/spm_db.h
@@ -41,6 +41,8 @@
     uint32_t partition_flags;
     uint32_t partition_priority;
     sp_entry_point partition_init;
+    uint32_t dependencies_num;
+    int32_t *p_dependencies;
 };
 
 /**
diff --git a/secure_fw/spm/tfm_spm_db.inc b/secure_fw/spm/tfm_spm_db.inc
index a854967..28f0e1a 100644
--- a/secure_fw/spm/tfm_spm_db.inc
+++ b/secure_fw/spm/tfm_spm_db.inc
@@ -11,6 +11,7 @@
 #define __TFM_SPM_DB_INC__
 
 #include "spm_api.h"
+#include "psa_manifest/sid.h"
 
 /**************************************************************************/
 /** IRQ count per partition */
@@ -448,6 +449,65 @@
 #endif /* !defined(TFM_PSA_API) */
 
 /**************************************************************************/
+/** Dependencies array for Secure Partition */
+/**************************************************************************/
+static int32_t dependencies_TFM_SP_STORAGE[] =
+{
+    TFM_CRYPTO_SID,
+};
+
+static int32_t dependencies_TFM_SP_INITIAL_ATTESTATION[] =
+{
+    TFM_CRYPTO_SID,
+};
+
+#ifdef TFM_PARTITION_TEST_CORE
+static int32_t dependencies_TFM_SP_CORE_TEST[] =
+{
+    SPM_CORE_TEST_2_INVERT_SID,
+    SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_SID,
+    SPM_CORE_TEST_2_SLAVE_SERVICE_SID,
+};
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+static int32_t dependencies_TFM_SP_SECURE_TEST_PARTITION[] =
+{
+    TFM_CRYPTO_SID,
+    TFM_SST_SET_SID,
+    TFM_SST_GET_SID,
+    TFM_SST_GET_INFO_SID,
+    TFM_SST_REMOVE_SID,
+    TFM_SST_GET_SUPPORT_SID,
+    TFM_ITS_SET_SID,
+    TFM_ITS_GET_SID,
+    TFM_ITS_GET_INFO_SID,
+    TFM_ITS_REMOVE_SID,
+    TFM_ATTEST_GET_TOKEN_SID,
+    TFM_ATTEST_GET_TOKEN_SIZE_SID,
+    TFM_ATTEST_GET_PUBLIC_KEY_SID,
+    TFM_SST_TEST_PREPARE_SID,
+};
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+static int32_t dependencies_TFM_SP_IPC_CLIENT_TEST[] =
+{
+    IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SID,
+    IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_SID,
+    IPC_SERVICE_TEST_BASIC_SID,
+    IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_SID,
+};
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_PARTITION_TEST_SST
+static int32_t dependencies_TFM_SP_SST_TEST[] =
+{
+    TFM_CRYPTO_SID,
+};
+#endif /* TFM_PARTITION_TEST_SST */
+
+/**************************************************************************/
 /** The static data of the partition list */
 /**************************************************************************/
 const struct spm_partition_static_data_t static_data_list[] =
@@ -487,6 +547,8 @@
                               ,
         .partition_priority   = TFM_PRIORITY(NORMAL),
         .partition_init       = tfm_sst_req_mngr_init,
+        .dependencies_num     = 1,
+        .p_dependencies       = dependencies_TFM_SP_STORAGE,
     },
 
     {
@@ -499,6 +561,8 @@
                               ,
         .partition_priority   = TFM_PRIORITY(NORMAL),
         .partition_init       = tfm_its_req_mngr_init,
+        .dependencies_num     = 0,
+        .p_dependencies       = NULL,
     },
 
 #ifdef TFM_PARTITION_AUDIT_LOG
@@ -512,6 +576,8 @@
                               ,
         .partition_priority   = TFM_PRIORITY(NORMAL),
         .partition_init       = audit_core_init,
+        .dependencies_num     = 0,
+        .p_dependencies       = NULL,
     },
 #endif /* TFM_PARTITION_AUDIT_LOG */
 
@@ -525,6 +591,8 @@
                               ,
         .partition_priority   = TFM_PRIORITY(NORMAL),
         .partition_init       = tfm_crypto_init,
+        .dependencies_num     = 0,
+        .p_dependencies       = NULL,
     },
 
 #ifdef TFM_PARTITION_PLATFORM
@@ -538,6 +606,8 @@
                               ,
         .partition_priority   = TFM_PRIORITY(NORMAL),
         .partition_init       = platform_sp_init,
+        .dependencies_num     = 0,
+        .p_dependencies       = NULL,
     },
 #endif /* TFM_PARTITION_PLATFORM */
 
@@ -551,6 +621,8 @@
                               ,
         .partition_priority   = TFM_PRIORITY(NORMAL),
         .partition_init       = attest_partition_init,
+        .dependencies_num     = 1,
+        .p_dependencies       = dependencies_TFM_SP_INITIAL_ATTESTATION,
     },
 
 #ifdef TFM_PARTITION_TEST_CORE
@@ -564,6 +636,8 @@
                               ,
         .partition_priority   = TFM_PRIORITY(NORMAL),
         .partition_init       = core_test_init,
+        .dependencies_num     = 3,
+        .p_dependencies       = dependencies_TFM_SP_CORE_TEST,
     },
 #endif /* TFM_PARTITION_TEST_CORE */
 
@@ -578,6 +652,8 @@
                               ,
         .partition_priority   = TFM_PRIORITY(NORMAL),
         .partition_init       = core_test_2_init,
+        .dependencies_num     = 0,
+        .p_dependencies       = NULL,
     },
 #endif /* TFM_PARTITION_TEST_CORE */
 
@@ -592,6 +668,8 @@
                               ,
         .partition_priority   = TFM_PRIORITY(NORMAL),
         .partition_init       = tfm_secure_client_service_init,
+        .dependencies_num     = 14,
+        .p_dependencies       = dependencies_TFM_SP_SECURE_TEST_PARTITION,
     },
 #endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
 
@@ -606,6 +684,8 @@
                               ,
         .partition_priority   = TFM_PRIORITY(HIGH),
         .partition_init       = ipc_service_test_main,
+        .dependencies_num     = 0,
+        .p_dependencies       = NULL,
     },
 #endif /* TFM_PARTITION_TEST_CORE_IPC */
 
@@ -620,6 +700,8 @@
                               ,
         .partition_priority   = TFM_PRIORITY(NORMAL),
         .partition_init       = ipc_client_test_main,
+        .dependencies_num     = 4,
+        .p_dependencies       = dependencies_TFM_SP_IPC_CLIENT_TEST,
     },
 #endif /* TFM_PARTITION_TEST_CORE_IPC */
 
@@ -634,6 +716,8 @@
                               ,
         .partition_priority   = TFM_PRIORITY(NORMAL),
         .partition_init       = tfm_irq_test_1_init,
+        .dependencies_num     = 0,
+        .p_dependencies       = NULL,
     },
 #endif /* TFM_ENABLE_IRQ_TEST */
 
@@ -648,6 +732,8 @@
                               ,
         .partition_priority   = TFM_PRIORITY(NORMAL),
         .partition_init       = tfm_sst_test_init,
+        .dependencies_num     = 1,
+        .p_dependencies       = dependencies_TFM_SP_SST_TEST,
     },
 #endif /* TFM_PARTITION_TEST_SST */
 
diff --git a/secure_fw/spm/tfm_spm_db.inc.template b/secure_fw/spm/tfm_spm_db.inc.template
index 5e12dd0..5e84b5d 100644
--- a/secure_fw/spm/tfm_spm_db.inc.template
+++ b/secure_fw/spm/tfm_spm_db.inc.template
@@ -11,6 +11,7 @@
 #define __TFM_SPM_DB_INC__
 
 #include "spm_api.h"
+#include "psa_manifest/sid.h"
 
 /**************************************************************************/
 /** IRQ count per partition */
@@ -126,6 +127,26 @@
 #endif /* !defined(TFM_PSA_API) */
 
 /**************************************************************************/
+/** Dependencies array for Secure Partition */
+/**************************************************************************/
+{% for manifest in manifests %}
+    {% if manifest.manifest.dependencies %}
+        {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+        {% endif %}
+static int32_t dependencies_{{manifest.manifest.name}}[] =
+{
+        {% for dependence in manifest.manifest.dependencies %}
+    {{dependence}}_SID,
+        {% endfor %}
+};
+        {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+        {% endif %}
+
+    {% endif %}
+{% endfor %}
+/**************************************************************************/
 /** The static data of the partition list */
 /**************************************************************************/
 const struct spm_partition_static_data_t static_data_list[] =
@@ -183,6 +204,12 @@
                               ,
         .partition_priority   = TFM_PRIORITY({{manifest.manifest.priority}}),
         .partition_init       = {{manifest.manifest.entry_point}},
+        .dependencies_num     = {{manifest.manifest.dependencies | length()}},
+    {% if manifest.manifest.dependencies %}
+        .p_dependencies       = dependencies_{{manifest.manifest.name}},
+    {% else %}
+        .p_dependencies       = NULL,
+    {% endif %}
     {{'},'}}
     {% if manifest.attr.conditional %}
 #endif /* {{manifest.attr.conditional}} */
diff --git a/test/test_services/tfm_core_test/tfm_test_core.yaml b/test/test_services/tfm_core_test/tfm_test_core.yaml
index b198a63..d6ccdcf 100644
--- a/test/test_services/tfm_core_test/tfm_test_core.yaml
+++ b/test/test_services/tfm_core_test/tfm_test_core.yaml
@@ -132,5 +132,10 @@
       "version": 1,
       "version_policy": "STRICT"
     }
+  ],
+  "dependencies": [
+    "SPM_CORE_TEST_2_INVERT",
+    "SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE",
+    "SPM_CORE_TEST_2_SLAVE_SERVICE"
   ]
 }
diff --git a/test/test_services/tfm_ipc_client/tfm_ipc_client_partition.yaml b/test/test_services/tfm_ipc_client/tfm_ipc_client_partition.yaml
index 9160721..d5de667 100644
--- a/test/test_services/tfm_ipc_client/tfm_ipc_client_partition.yaml
+++ b/test/test_services/tfm_ipc_client/tfm_ipc_client_partition.yaml
@@ -52,6 +52,12 @@
       "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"
+  ],
   "linker_pattern": {
     "object_list": [
       "*ipc_client_test.*"
diff --git a/test/test_services/tfm_secure_client_service/tfm_test_client_service.yaml b/test/test_services/tfm_secure_client_service/tfm_test_client_service.yaml
index 80159bd..fe13566 100644
--- a/test/test_services/tfm_secure_client_service/tfm_test_client_service.yaml
+++ b/test/test_services/tfm_secure_client_service/tfm_test_client_service.yaml
@@ -37,6 +37,22 @@
       "version_policy": "STRICT"
     }
   ],
+  "dependencies": [
+    "TFM_CRYPTO",
+    "TFM_SST_SET",
+    "TFM_SST_GET",
+    "TFM_SST_GET_INFO",
+    "TFM_SST_REMOVE",
+    "TFM_SST_GET_SUPPORT",
+    "TFM_ITS_SET",
+    "TFM_ITS_GET",
+    "TFM_ITS_GET_INFO",
+    "TFM_ITS_REMOVE",
+    "TFM_ATTEST_GET_TOKEN",
+    "TFM_ATTEST_GET_TOKEN_SIZE",
+    "TFM_ATTEST_GET_PUBLIC_KEY",
+    "TFM_SST_TEST_PREPARE"
+  ],
 # Currently there is no platform dependent section of the manifest file,
 # therefore all platform dependent files must be listed here which can be used
 # on any supported platform.
diff --git a/test/test_services/tfm_sst_test_service/tfm_sst_test_service.yaml b/test/test_services/tfm_sst_test_service/tfm_sst_test_service.yaml
index b69d0c6..de3a67c 100644
--- a/test/test_services/tfm_sst_test_service/tfm_sst_test_service.yaml
+++ b/test/test_services/tfm_sst_test_service/tfm_sst_test_service.yaml
@@ -31,6 +31,9 @@
       "version_policy": "STRICT"
     }
   ],
+  "dependencies": [
+    "TFM_CRYPTO",
+  ],
   "linker_pattern": {
     "object_list": [
       "*tfm_sst_test_service.*",