Test: Add Crypto test for key access control

Adds a test for access control for keys in the Crypto service based on
partition ID. Uses the Secure Client 2 test partition to attempt to
destroy a key belonging to another partition.

Change-Id: I2f3dfd2dfca0a9f7e9391836b190862b1df5dc18
Signed-off-by: Jamie Fox <jamie.fox@arm.com>
diff --git a/secure_fw/spm/tfm_spm_db.inc b/secure_fw/spm/tfm_spm_db.inc
index 2fbdd90..ce05fd6 100644
--- a/secure_fw/spm/tfm_spm_db.inc
+++ b/secure_fw/spm/tfm_spm_db.inc
@@ -591,6 +591,7 @@
 static int32_t dependencies_TFM_SP_SECURE_CLIENT_2[] =
 {
     TFM_ITS_GET_SID,
+    TFM_CRYPTO_SID,
 };
 #endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
 
@@ -843,7 +844,7 @@
                               ,
         .partition_priority   = TFM_PRIORITY(NORMAL),
         .partition_init       = tfm_secure_client_2_init,
-        .dependencies_num     = 1,
+        .dependencies_num     = 2,
         .p_dependencies       = dependencies_TFM_SP_SECURE_CLIENT_2,
     },
 #endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
diff --git a/test/suites/crypto/secure/crypto_sec_interface_testsuite.c b/test/suites/crypto/secure/crypto_sec_interface_testsuite.c
index e8dc27e..f9762ec 100644
--- a/test/suites/crypto/secure/crypto_sec_interface_testsuite.c
+++ b/test/suites/crypto/secure/crypto_sec_interface_testsuite.c
@@ -1,11 +1,12 @@
 /*
- * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
  */
 
 #include "test/framework/test_framework_helpers.h"
+#include "test/test_services/tfm_secure_client_2/tfm_secure_client_2_api.h"
 #include "tfm_api.h"
 #include "../crypto_tests_common.h"
 
@@ -31,6 +32,7 @@
 static void tfm_crypto_test_5031(struct test_result_t *ret);
 static void tfm_crypto_test_5032(struct test_result_t *ret);
 static void tfm_crypto_test_5033(struct test_result_t *ret);
+static void tfm_crypto_test_5034(struct test_result_t *ret);
 
 static struct test_t crypto_tests[] = {
     {&tfm_crypto_test_5001, "TFM_CRYPTO_TEST_5001",
@@ -75,6 +77,8 @@
      "Secure key policy interface", {0} },
     {&tfm_crypto_test_5033, "TFM_CRYPTO_TEST_5033",
      "Secure key policy check permissions", {0} },
+    {&tfm_crypto_test_5034, "TFM_CRYPTO_TEST_5034",
+     "Key access control", {0} },
 };
 
 void register_testsuite_s_crypto_interface(struct test_suite_t *p_test_suite)
@@ -200,3 +204,45 @@
 {
     psa_policy_invalid_policy_usage_test(ret);
 }
+
+/**
+ * \brief Tests key access control based on partition ID
+ *
+ * \param[out] ret  Test result
+ */
+static void tfm_crypto_test_5034(struct test_result_t *ret)
+{
+    psa_status_t status;
+    psa_key_handle_t key_handle;
+    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+
+    /* Allocate a transient key */
+    status = psa_allocate_key(&key_handle);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to allocate key");
+        return;
+    }
+
+    /* Setup the key policy */
+    psa_key_policy_set_usage(&policy, PSA_KEY_USAGE_EXPORT, PSA_ALG_CTR);
+    status = psa_set_key_policy(key_handle, &policy);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to set key policy");
+        return;
+    }
+
+    /* Attempt to destroy the key handle from the Secure Client 2 partition */
+    status = tfm_secure_client_2_call_test(
+                                      TFM_SECURE_CLIENT_2_ID_CRYPTO_ACCESS_CTRL,
+                                      &key_handle, sizeof(key_handle));
+    if (status != PSA_ERROR_NOT_PERMITTED) {
+        TEST_FAIL("Should not be able to destroy key from another partition");
+        return;
+    }
+
+    /* Destroy the key */
+    status = psa_destroy_key(key_handle);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Error destroying a key");
+    }
+}
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 463eb9b..153caac 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -7,6 +7,7 @@
 
 #include "tfm_secure_client_2_api.h"
 #include "psa/internal_trusted_storage.h"
+#include "psa/crypto.h"
 
 #ifdef TFM_PSA_API
 #include "psa/service.h"
@@ -15,7 +16,40 @@
 #include "psa/client.h"
 #endif
 
+#ifdef ENABLE_CRYPTO_SERVICE_TESTS
+/**
+ * \brief Tests calling psa_destroy_key() with the supplied key handle.
+ *
+ * \param[in] arg      Pointer to key handle
+ * \param[in] arg_len  Length of arg in bytes
+ *
+ * \return Returns test result as specified in \ref psa_status_t
+ */
+static psa_status_t secure_client_2_test_crypto_access_ctrl(const void *arg,
+                                                            size_t arg_len)
+{
+    psa_key_handle_t key_handle;
+
+    if (arg_len != sizeof(key_handle)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    key_handle = *((psa_key_handle_t *)arg);
+
+    /* Attempt to destroy the key handle */
+    return psa_destroy_key(key_handle);
+}
+#endif /* ENABLE_CRYPTO_SERVICE_TESTS */
+
 #ifdef ENABLE_INTERNAL_TRUSTED_STORAGE_SERVICE_TESTS
+/**
+ * \brief Tests calling psa_its_get() with the supplied uid.
+ *
+ * \param[in] arg      Pointer to uid
+ * \param[in] arg_len  Length of arg in bytes
+ *
+ * \return Returns test result as specified in \ref psa_status_t
+ */
 static psa_status_t secure_client_2_test_its_access_ctrl(const void *arg,
                                                          size_t arg_len)
 {
@@ -32,8 +66,18 @@
     /* Attempt to get one byte from the UID and return the resulting status */
     return psa_its_get(uid, 0, sizeof(data), data, &p_data_length);
 }
-#endif
+#endif /* ENABLE_INTERNAL_TRUSTED_STORAGE_SERVICE_TESTS */
 
+/**
+ * \brief Calls the test function with the supplied ID and returns the result
+ *        from the test function.
+ *
+ * \param[in] id       The ID of the test function
+ * \param[in] arg      Pointer to argument to pass to test function
+ * \param[in] arg_len  Length of argument in bytes
+ *
+ * \return Returns test result as specified in \ref psa_status_t
+ */
 static psa_status_t secure_client_2_dispatch(int32_t id, const void *arg,
                                              size_t arg_len)
 {
@@ -42,6 +86,10 @@
     case TFM_SECURE_CLIENT_2_ID_ITS_ACCESS_CTRL:
         return secure_client_2_test_its_access_ctrl(arg, arg_len);
 #endif
+#ifdef ENABLE_CRYPTO_SERVICE_TESTS
+    case TFM_SECURE_CLIENT_2_ID_CRYPTO_ACCESS_CTRL:
+        return secure_client_2_test_crypto_access_ctrl(arg, arg_len);
+#endif
     default:
         return PSA_ERROR_PROGRAMMER_ERROR;
     }
diff --git a/test/test_services/tfm_secure_client_2/tfm_secure_client_2.yaml b/test/test_services/tfm_secure_client_2/tfm_secure_client_2.yaml
index c750c45..0ae20c8 100644
--- a/test/test_services/tfm_secure_client_2/tfm_secure_client_2.yaml
+++ b/test/test_services/tfm_secure_client_2/tfm_secure_client_2.yaml
@@ -31,7 +31,8 @@
     }
   ],
   "dependencies": [
-    "TFM_ITS_GET"
+    "TFM_ITS_GET",
+    "TFM_CRYPTO"
   ],
   "linker_pattern": {
     "object_list": [
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 4387710..a6018c5 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -17,7 +17,8 @@
 extern "C" {
 #endif
 
-#define TFM_SECURE_CLIENT_2_ID_ITS_ACCESS_CTRL 1001
+#define TFM_SECURE_CLIENT_2_ID_ITS_ACCESS_CTRL    1001
+#define TFM_SECURE_CLIENT_2_ID_CRYPTO_ACCESS_CTRL 2001
 
 /**
  * \brief Calls the test function with the supplied ID within the execution