Crypto: Implement PSA key policy APIs

Extends the Crypto service key module to add support for
the PSA Crypto key policy and lifetime APIs. Adds new test
cases for the key policy interface and modifies existing
tests to use key policies.

Change-Id: Ic820fcc395d591dbb5f8fe09446049ff460dfe02
Signed-off-by: Jamie Fox <jamie.fox@arm.com>
diff --git a/interface/include/tfm_crypto_veneers.h b/interface/include/tfm_crypto_veneers.h
index 83ab510..9e95475 100644
--- a/interface/include/tfm_crypto_veneers.h
+++ b/interface/include/tfm_crypto_veneers.h
@@ -68,6 +68,106 @@
                                                    uint8_t *data,
                                                    size_t data_size,
                                                    size_t *data_length);
+
+/**
+ * \brief Initialise the key policy to a default that forbids any use of the
+ *        key (veneer function)
+ *
+ * \param[out] policy  Key policy to initialise
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_veneer_key_policy_init(
+                                                      psa_key_policy_t *policy);
+
+/**
+ * \brief Set the permitted usage and algorithm for the provided key policy
+ *        (veneer function)
+ *
+ * \param[out] policy  Key policy to modify
+ * \param[in]  usage   Permitted usage
+ * \param[in]  alg     Permitted algorithm
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_veneer_key_policy_set_usage(
+                                                       psa_key_policy_t *policy,
+                                                       psa_key_usage_t usage,
+                                                       psa_algorithm_t alg);
+
+/**
+ * \brief Get the permitted usage for the provided key policy (veneer function)
+ *
+ * \param[in]  policy  Key policy
+ * \param[out] usage   Permitted usage for this key policy
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_veneer_key_policy_get_usage(
+                                                 const psa_key_policy_t *policy,
+                                                 psa_key_usage_t *usage);
+
+/**
+ * \brief Get the permitted algorithm for the provided key policy
+ *        (veneer function)
+ *
+ * \param[in]  policy  Key policy
+ * \param[out] alg     Permitted algorithm for this key policy
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_veneer_key_policy_get_algorithm(
+                                                 const psa_key_policy_t *policy,
+                                                 psa_algorithm_t *alg);
+
+/**
+ * \brief Set the key policy for the provided key slot (veneer function)
+ *
+ * \param[in] key     Key slot
+ * \param[in] policy  Key policy
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_veneer_set_key_policy(
+                                                psa_key_slot_t key,
+                                                const psa_key_policy_t *policy);
+
+/**
+ * \brief Get the key policy for the provided key slot (veneer function)
+ *
+ * \param[in]  key     Key slot
+ * \param[out] policy  Key policy
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_veneer_get_key_policy(
+                                                      psa_key_slot_t key,
+                                                      psa_key_policy_t *policy);
+
+/**
+ * \brief Set the lifetime for the provided key slot (veneer function)
+ *
+ * \param[in] key       Key slot
+ * \param[in] lifetime  Lifetime value
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_veneer_set_key_lifetime(
+                                                   psa_key_slot_t key,
+                                                   psa_key_lifetime_t lifetime);
+
+/**
+ * \brief Get the lifetime for the provided key slot (veneer function)
+ *
+ * \param[in]  key       Key slot
+ * \param[out] lifetime  Lifetime value
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_veneer_get_key_lifetime(
+                                                  psa_key_slot_t key,
+                                                  psa_key_lifetime_t *lifetime);
+
 /**
  * \brief Set the initialisation vector on the provided cipher operation (veneer
  *        function)
diff --git a/interface/src/tfm_crypto_api.c b/interface/src/tfm_crypto_api.c
index 8069934..9d28d5b 100644
--- a/interface/src/tfm_crypto_api.c
+++ b/interface/src/tfm_crypto_api.c
@@ -87,6 +87,125 @@
     return PSA_ERROR_NOT_SUPPORTED;
 }
 
+void psa_key_policy_init(psa_key_policy_t *policy)
+{
+    /* PSA API returns void so just ignore error value returned */
+    (void)tfm_ns_lock_dispatch((veneer_fn)tfm_crypto_veneer_key_policy_init,
+                               (uint32_t)policy,
+                               0,
+                               0,
+                               0);
+}
+
+void psa_key_policy_set_usage(psa_key_policy_t *policy,
+                              psa_key_usage_t usage,
+                              psa_algorithm_t alg)
+{
+    /* PSA API returns void so just ignore error value returned */
+    (void)tfm_ns_lock_dispatch(
+                              (veneer_fn)tfm_crypto_veneer_key_policy_set_usage,
+                              (uint32_t)policy,
+                              (uint32_t)usage,
+                              (uint32_t)alg,
+                              0);
+}
+
+psa_key_usage_t psa_key_policy_get_usage(const psa_key_policy_t *policy)
+{
+    psa_key_usage_t usage;
+
+    /* Initialise to a sensible default to avoid returning an uninitialised
+     * value in case the secure function fails.
+     */
+    usage = 0;
+
+    /* The PSA API does not return an error, so ignore any error from TF-M */
+    (void)tfm_ns_lock_dispatch(
+                              (veneer_fn)tfm_crypto_veneer_key_policy_get_usage,
+                              (uint32_t)policy,
+                              (uint32_t)&usage,
+                              0,
+                              0);
+
+    return usage;
+}
+
+psa_algorithm_t psa_key_policy_get_algorithm(const psa_key_policy_t *policy)
+{
+    psa_algorithm_t alg;
+
+    /* Initialise to a sensible default to avoid returning an uninitialised
+     * value in case the secure function fails.
+     */
+    alg = 0;
+
+    /* The PSA API does not return an error, so ignore any error from TF-M */
+    (void)tfm_ns_lock_dispatch(
+                          (veneer_fn)tfm_crypto_veneer_key_policy_get_algorithm,
+                          (uint32_t)policy,
+                          (uint32_t)&alg,
+                          0,
+                          0);
+
+    return alg;
+}
+
+psa_status_t psa_set_key_policy(psa_key_slot_t key,
+                                const psa_key_policy_t *policy)
+{
+    enum tfm_crypto_err_t err;
+
+    err = tfm_ns_lock_dispatch((veneer_fn)tfm_crypto_veneer_set_key_policy,
+                               (uint32_t)key,
+                               (uint32_t)policy,
+                               0,
+                               0);
+
+    return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+psa_status_t psa_get_key_policy(psa_key_slot_t key,
+                                psa_key_policy_t *policy)
+{
+    enum tfm_crypto_err_t err;
+
+    err = tfm_ns_lock_dispatch((veneer_fn)tfm_crypto_veneer_get_key_policy,
+                               (uint32_t)key,
+                               (uint32_t)policy,
+                               0,
+                               0);
+
+    return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+psa_status_t psa_set_key_lifetime(psa_key_slot_t key,
+                                  psa_key_lifetime_t lifetime)
+{
+    enum tfm_crypto_err_t err;
+
+    err = tfm_ns_lock_dispatch((veneer_fn)tfm_crypto_veneer_set_key_lifetime,
+                               (uint32_t)key,
+                               (uint32_t)lifetime,
+                               0,
+                               0);
+
+    return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
+psa_status_t psa_get_key_lifetime(psa_key_slot_t key,
+                                  psa_key_lifetime_t *lifetime)
+{
+    enum tfm_crypto_err_t err;
+
+    err = tfm_ns_lock_dispatch((veneer_fn)tfm_crypto_veneer_get_key_lifetime,
+                               (uint32_t)key,
+                               (uint32_t)lifetime,
+                               0,
+                               0);
+
+    return TFM_CRYPTO_ERR_TO_PSA_STATUS(err);
+}
+
 psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation,
                                const unsigned char *iv,
                                size_t iv_length)
diff --git a/secure_fw/ns_callable/tfm_crypto_veneers.c b/secure_fw/ns_callable/tfm_crypto_veneers.c
index a3ecc8d..314603a 100644
--- a/secure_fw/ns_callable/tfm_crypto_veneers.c
+++ b/secure_fw/ns_callable/tfm_crypto_veneers.c
@@ -52,6 +52,76 @@
                          key, data, data_size, data_length);
 }
 
+__tfm_secure_gateway_attributes__
+enum tfm_crypto_err_t tfm_crypto_veneer_key_policy_init(
+                                                       psa_key_policy_t *policy)
+{
+    TFM_CORE_SFN_REQUEST(TFM_SP_CRYPTO_ID, tfm_crypto_key_policy_init,
+                         policy, 0, 0, 0);
+}
+
+__tfm_secure_gateway_attributes__
+enum tfm_crypto_err_t tfm_crypto_veneer_key_policy_set_usage(
+                                                       psa_key_policy_t *policy,
+                                                       psa_key_usage_t usage,
+                                                       psa_algorithm_t alg)
+{
+    TFM_CORE_SFN_REQUEST(TFM_SP_CRYPTO_ID, tfm_crypto_key_policy_set_usage,
+                         policy, usage, alg, 0);
+}
+
+__tfm_secure_gateway_attributes__
+enum tfm_crypto_err_t tfm_crypto_veneer_key_policy_get_usage(
+                                                 const psa_key_policy_t *policy,
+                                                 psa_key_usage_t *usage)
+{
+    TFM_CORE_SFN_REQUEST(TFM_SP_CRYPTO_ID, tfm_crypto_key_policy_get_usage,
+                         policy, usage, 0, 0);
+}
+
+__tfm_secure_gateway_attributes__
+enum tfm_crypto_err_t tfm_crypto_veneer_key_policy_get_algorithm(
+                                                 const psa_key_policy_t *policy,
+                                                 psa_algorithm_t *alg)
+{
+    TFM_CORE_SFN_REQUEST(TFM_SP_CRYPTO_ID, tfm_crypto_key_policy_get_algorithm,
+                         policy, alg, 0, 0);
+}
+
+__tfm_secure_gateway_attributes__
+enum tfm_crypto_err_t tfm_crypto_veneer_set_key_policy(
+                                                 psa_key_slot_t key,
+                                                 const psa_key_policy_t *policy)
+{
+    TFM_CORE_SFN_REQUEST(TFM_SP_CRYPTO_ID, tfm_crypto_set_key_policy,
+                         key, policy, 0, 0);
+}
+
+__tfm_secure_gateway_attributes__
+enum tfm_crypto_err_t tfm_crypto_veneer_get_key_policy(psa_key_slot_t key,
+                                                       psa_key_policy_t *policy)
+{
+    TFM_CORE_SFN_REQUEST(TFM_SP_CRYPTO_ID, tfm_crypto_get_key_policy,
+                         key, policy, 0, 0);
+}
+
+__tfm_secure_gateway_attributes__
+enum tfm_crypto_err_t tfm_crypto_veneer_set_key_lifetime(
+                                                    psa_key_slot_t key,
+                                                    psa_key_lifetime_t lifetime)
+{
+    TFM_CORE_SFN_REQUEST(TFM_SP_CRYPTO_ID, tfm_crypto_set_key_lifetime,
+                         key, lifetime, 0, 0);
+}
+
+__tfm_secure_gateway_attributes__
+enum tfm_crypto_err_t tfm_crypto_veneer_get_key_lifetime(
+                                                   psa_key_slot_t key,
+                                                   psa_key_lifetime_t *lifetime)
+{
+    TFM_CORE_SFN_REQUEST(TFM_SP_CRYPTO_ID, tfm_crypto_get_key_lifetime,
+                         key, lifetime, 0, 0);
+}
 
 __tfm_secure_gateway_attributes__
 enum tfm_crypto_err_t tfm_crypto_veneer_cipher_set_iv(
diff --git a/secure_fw/services/crypto/crypto_aead.c b/secure_fw/services/crypto/crypto_aead.c
index a0e2a5c..ec8b3a1 100644
--- a/secure_fw/services/crypto/crypto_aead.c
+++ b/secure_fw/services/crypto/crypto_aead.c
@@ -102,10 +102,12 @@
     }
 
     /* Access the crypto service key module to retrieve key data */
-    err = tfm_crypto_export_key(key,
-                                &key_data[0],
-                                TFM_CRYPTO_MAX_KEY_LENGTH,
-                                (size_t *)&key_size);
+    err = tfm_crypto_get_key(key,
+                             PSA_KEY_USAGE_ENCRYPT,
+                             alg,
+                             key_data,
+                             TFM_CRYPTO_MAX_KEY_LENGTH,
+                             (size_t *)&key_size);
     if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
         return err;
     }
@@ -208,10 +210,12 @@
     }
 
     /* Access the crypto service key module to retrieve key data */
-    err = tfm_crypto_export_key(key,
-                                &key_data[0],
-                                TFM_CRYPTO_MAX_KEY_LENGTH,
-                                (size_t *)&key_size);
+    err = tfm_crypto_get_key(key,
+                             PSA_KEY_USAGE_DECRYPT,
+                             alg,
+                             key_data,
+                             TFM_CRYPTO_MAX_KEY_LENGTH,
+                             (size_t *)&key_size);
     if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
         return err;
     }
diff --git a/secure_fw/services/crypto/crypto_cipher.c b/secure_fw/services/crypto/crypto_cipher.c
index ca78e8a..84b5b78 100644
--- a/secure_fw/services/crypto/crypto_cipher.c
+++ b/secure_fw/services/crypto/crypto_cipher.c
@@ -31,6 +31,7 @@
     enum tfm_crypto_err_t err;
     struct tfm_cipher_operation_s *ctx = NULL;
     struct cipher_engine_info engine_info;
+    psa_key_usage_t usage;
 
     /* Validate pointers */
     err = tfm_crypto_memory_check(operation,
@@ -91,11 +92,17 @@
         return PSA_STATUS_TO_TFM_CRYPTO_ERR(status);
     }
 
+    /* Set the key usage based on the cipher mode */
+    usage = (c_mode == ENGINE_CIPHER_MODE_DECRYPT) ? PSA_KEY_USAGE_DECRYPT
+                                                   : PSA_KEY_USAGE_ENCRYPT;
+
     /* Access the crypto service key module to retrieve key data */
-    err = tfm_crypto_export_key(key,
-                                &key_data[0],
-                                TFM_CRYPTO_MAX_KEY_LENGTH,
-                                &key_size);
+    err = tfm_crypto_get_key(key,
+                             usage,
+                             alg,
+                             key_data,
+                             TFM_CRYPTO_MAX_KEY_LENGTH,
+                             &key_size);
     if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
         /* Release the operation context */
         tfm_crypto_operation_release(&(operation->handle));
diff --git a/secure_fw/services/crypto/crypto_key.c b/secure_fw/services/crypto/crypto_key.c
index d6b99c7..90638f2 100644
--- a/secure_fw/services/crypto/crypto_key.c
+++ b/secure_fw/services/crypto/crypto_key.c
@@ -5,12 +5,12 @@
  *
  */
 
-#include <limits.h>
+#include <stddef.h>
 
-#include "tfm_crypto_defs.h"
+#include "tfm_crypto_api.h"
+#include "crypto_utils.h"
 #include "psa_crypto.h"
-
-#include "tfm_crypto_struct.h"
+#include "tfm_crypto_defs.h"
 #include "secure_fw/core/secure_utilities.h"
 
 /**
@@ -22,6 +22,8 @@
 struct tfm_crypto_key_storage_s {
     uint8_t in_use;                 /*!< Indicates if the key store is in use */
     psa_key_type_t type;            /*!< Type of the key stored */
+    psa_key_policy_t policy;        /*!< Policy of the key stored */
+    psa_key_lifetime_t lifetime;    /*!< Lifetime of the key stored */
     size_t data_length;             /*!< Length of the key stored */
     uint8_t data[TFM_CRYPTO_MAX_KEY_LENGTH]; /*!< Buffer containining the key */
 };
@@ -41,13 +43,60 @@
     return TFM_CRYPTO_ERR_PSA_SUCCESS;
 }
 
+enum tfm_crypto_err_t tfm_crypto_get_key(psa_key_slot_t key,
+                                         psa_key_usage_t usage,
+                                         psa_algorithm_t alg,
+                                         uint8_t *data,
+                                         size_t data_size,
+                                         size_t *data_length)
+{
+    size_t i;
+
+    if (key >= TFM_CRYPTO_KEY_STORAGE_NUM) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (key_storage[key].in_use == TFM_CRYPTO_NOT_IN_USE) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_EMPTY_SLOT;
+    }
+
+    /* Check that usage is permitted for this key */
+    if ((usage & key_storage[key].policy.usage) != usage) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_NOT_PERMITTED;
+    }
+
+    /* Check that alg is compatible with this key */
+    if (alg != 0 && alg != key_storage[key].policy.alg) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_NOT_PERMITTED;
+    }
+
+    if (key_storage[key].data_length > data_size) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+    for (i = 0; i < key_storage[key].data_length; i++) {
+        data[i] = key_storage[key].data[i];
+    }
+
+    *data_length = key_storage[key].data_length;
+
+    return TFM_CRYPTO_ERR_PSA_SUCCESS;
+}
+
 enum tfm_crypto_err_t tfm_crypto_import_key(psa_key_slot_t key,
                                             psa_key_type_t type,
                                             const uint8_t *data,
                                             size_t data_length)
 {
+    enum tfm_crypto_err_t err;
     size_t i;
 
+    err = tfm_crypto_memory_check((uint8_t *)data, data_length,
+                                  TFM_MEMORY_ACCESS_RO);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
     if (key >= TFM_CRYPTO_KEY_STORAGE_NUM) {
         return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
     }
@@ -69,7 +118,6 @@
 
     key_storage[key].data_length = data_length;
 
-
     return TFM_CRYPTO_ERR_PSA_SUCCESS;
 }
 
@@ -99,6 +147,19 @@
                                                      psa_key_type_t *type,
                                                      size_t *bits)
 {
+    enum tfm_crypto_err_t err;
+
+    err = tfm_crypto_memory_check(type, sizeof(psa_key_type_t),
+                                  TFM_MEMORY_ACCESS_RW);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    err = tfm_crypto_memory_check(bits, sizeof(size_t), TFM_MEMORY_ACCESS_RW);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
     if (key >= TFM_CRYPTO_KEY_STORAGE_NUM) {
         return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
     }
@@ -119,27 +180,21 @@
                                             size_t data_size,
                                             size_t *data_length)
 {
-    size_t i;
+    enum tfm_crypto_err_t err;
 
-    if (key >= TFM_CRYPTO_KEY_STORAGE_NUM) {
+    err = tfm_crypto_memory_check(data, data_size, TFM_MEMORY_ACCESS_RW);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
         return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
     }
 
-    if (key_storage[key].in_use == TFM_CRYPTO_NOT_IN_USE) {
-        return TFM_CRYPTO_ERR_PSA_ERROR_EMPTY_SLOT;
+    err = tfm_crypto_memory_check(data_length, sizeof(size_t),
+                                  TFM_MEMORY_ACCESS_RW);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
     }
 
-    if (key_storage[key].data_length > data_size) {
-        return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
-    }
-
-    for (i=0; i<key_storage[key].data_length; i++) {
-        data[i] = key_storage[key].data[i];
-    }
-
-    *data_length = key_storage[key].data_length;
-
-    return TFM_CRYPTO_ERR_PSA_SUCCESS;
+    return tfm_crypto_get_key(key, PSA_KEY_USAGE_EXPORT, 0, data, data_size,
+                              data_length);
 }
 
 enum tfm_crypto_err_t tfm_crypto_export_public_key(psa_key_slot_t key,
@@ -150,4 +205,198 @@
     /* FIXME: This API is not supported yet */
     return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
 }
+
+enum tfm_crypto_err_t tfm_crypto_key_policy_init(psa_key_policy_t *policy)
+{
+    enum tfm_crypto_err_t err;
+
+    err = tfm_crypto_memory_check(policy, sizeof(psa_key_policy_t),
+                                  TFM_MEMORY_ACCESS_RW);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    policy->usage = 0;
+    policy->alg = 0;
+
+    return TFM_CRYPTO_ERR_PSA_SUCCESS;
+}
+
+enum tfm_crypto_err_t tfm_crypto_key_policy_set_usage(psa_key_policy_t *policy,
+                                                      psa_key_usage_t usage,
+                                                      psa_algorithm_t alg)
+{
+    enum tfm_crypto_err_t err;
+
+    err = tfm_crypto_memory_check(policy, sizeof(psa_key_policy_t),
+                                  TFM_MEMORY_ACCESS_RW);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    policy->usage = usage;
+    policy->alg = alg;
+
+    return TFM_CRYPTO_ERR_PSA_SUCCESS;
+}
+
+enum tfm_crypto_err_t tfm_crypto_key_policy_get_usage(
+                                                 const psa_key_policy_t *policy,
+                                                 psa_key_usage_t *usage)
+{
+    enum tfm_crypto_err_t err;
+
+    err = tfm_crypto_memory_check((psa_key_policy_t *)policy,
+                                  sizeof(psa_key_policy_t),
+                                  TFM_MEMORY_ACCESS_RO);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    err = tfm_crypto_memory_check((psa_key_policy_t *)usage,
+                                  sizeof(psa_key_usage_t),
+                                  TFM_MEMORY_ACCESS_RW);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    *usage = policy->usage;
+
+    return TFM_CRYPTO_ERR_PSA_SUCCESS;
+}
+
+enum tfm_crypto_err_t tfm_crypto_key_policy_get_algorithm(
+                                                 const psa_key_policy_t *policy,
+                                                 psa_algorithm_t *alg)
+{
+    enum tfm_crypto_err_t err;
+
+    err = tfm_crypto_memory_check((psa_key_policy_t *)policy,
+                                  sizeof(psa_key_policy_t),
+                                  TFM_MEMORY_ACCESS_RO);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    err = tfm_crypto_memory_check((psa_key_policy_t *)alg,
+                                  sizeof(psa_algorithm_t),
+                                  TFM_MEMORY_ACCESS_RW);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    *alg = policy->alg;
+
+    return TFM_CRYPTO_ERR_PSA_SUCCESS;
+}
+
+enum tfm_crypto_err_t tfm_crypto_set_key_policy(psa_key_slot_t key,
+                                                const psa_key_policy_t *policy)
+{
+    enum tfm_crypto_err_t err;
+
+    err = tfm_crypto_memory_check((psa_key_policy_t *)policy,
+                                  sizeof(psa_key_policy_t),
+                                  TFM_MEMORY_ACCESS_RO);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (key >= TFM_CRYPTO_KEY_STORAGE_NUM) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Check that the policy is valid */
+    if (policy->usage & ~(PSA_KEY_USAGE_EXPORT
+                          | PSA_KEY_USAGE_ENCRYPT
+                          | PSA_KEY_USAGE_DECRYPT
+                          | PSA_KEY_USAGE_SIGN
+                          | PSA_KEY_USAGE_VERIFY
+                          | PSA_KEY_USAGE_DERIVE)) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Changing the policy of an occupied slot is not permitted as
+     * this is a requirement of the PSA Crypto API
+     */
+    if (key_storage[key].in_use != TFM_CRYPTO_NOT_IN_USE) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_OCCUPIED_SLOT;
+    }
+
+    key_storage[key].policy = *policy;
+
+    return TFM_CRYPTO_ERR_PSA_SUCCESS;
+}
+
+enum tfm_crypto_err_t tfm_crypto_get_key_policy(psa_key_slot_t key,
+                                                psa_key_policy_t *policy)
+{
+    enum tfm_crypto_err_t err;
+
+    err = tfm_crypto_memory_check(policy, sizeof(psa_key_policy_t),
+                                  TFM_MEMORY_ACCESS_RW);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (key >= TFM_CRYPTO_KEY_STORAGE_NUM) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    *policy = key_storage[key].policy;
+
+    return TFM_CRYPTO_ERR_PSA_SUCCESS;
+}
+
+enum tfm_crypto_err_t tfm_crypto_set_key_lifetime(psa_key_slot_t key,
+                                                  psa_key_lifetime_t lifetime)
+{
+    if (key >= TFM_CRYPTO_KEY_STORAGE_NUM) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Check that the lifetime is valid */
+    if (lifetime != PSA_KEY_LIFETIME_VOLATILE
+        && lifetime != PSA_KEY_LIFETIME_PERSISTENT
+        && lifetime != PSA_KEY_LIFETIME_WRITE_ONCE) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* TF-M Crypto service does not support changing the lifetime of an occupied
+     * slot.
+     */
+    if (key_storage[key].in_use != TFM_CRYPTO_NOT_IN_USE) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_OCCUPIED_SLOT;
+    }
+
+    /* Only volatile keys are currently supported */
+    if (lifetime != PSA_KEY_LIFETIME_VOLATILE) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    key_storage[key].lifetime = lifetime;
+
+    return TFM_CRYPTO_ERR_PSA_SUCCESS;
+}
+
+enum tfm_crypto_err_t tfm_crypto_get_key_lifetime(psa_key_slot_t key,
+                                                  psa_key_lifetime_t *lifetime)
+{
+    enum tfm_crypto_err_t err;
+
+    err = tfm_crypto_memory_check(lifetime, sizeof(psa_key_lifetime_t),
+                                  TFM_MEMORY_ACCESS_RW);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (key >= TFM_CRYPTO_KEY_STORAGE_NUM) {
+        return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    *lifetime = key_storage[key].lifetime;
+
+    return TFM_CRYPTO_ERR_PSA_SUCCESS;
+}
+
 /*!@}*/
diff --git a/secure_fw/services/crypto/crypto_mac.c b/secure_fw/services/crypto/crypto_mac.c
index a068830..25a98da 100644
--- a/secure_fw/services/crypto/crypto_mac.c
+++ b/secure_fw/services/crypto/crypto_mac.c
@@ -60,6 +60,7 @@
     uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
     uint8_t *opad = ctx->ctx.hmac.opad;
     size_t i;
+    psa_key_usage_t usage;
 
     /* Check provided key */
     err = tfm_crypto_get_key_information(key, &key_type, &key_size);
@@ -71,11 +72,22 @@
         return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
     }
 
+    /* Set the key usage based on whether this is a sign or verify operation */
+    if ((ctx->key_usage_sign == 1) && (ctx->key_usage_verify == 0)) {
+        usage = PSA_KEY_USAGE_SIGN;
+    } else if ((ctx->key_usage_sign == 0) && (ctx->key_usage_verify == 1)) {
+        usage = PSA_KEY_USAGE_VERIFY;
+    } else {
+        return TFM_CRYPTO_ERR_PSA_ERROR_BAD_STATE;
+    }
+
     /* Get the key data to start the HMAC */
-    err = tfm_crypto_export_key(key,
-                                &key_data[0],
-                                TFM_CRYPTO_MAX_KEY_LENGTH,
-                                &key_size);
+    err = tfm_crypto_get_key(key,
+                             usage,
+                             alg,
+                             key_data,
+                             TFM_CRYPTO_MAX_KEY_LENGTH,
+                             &key_size);
     if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
         return err;
     }
diff --git a/secure_fw/services/crypto/manifest.yaml b/secure_fw/services/crypto/manifest.yaml
index dae7a12..e1030a3 100644
--- a/secure_fw/services/crypto/manifest.yaml
+++ b/secure_fw/services/crypto/manifest.yaml
@@ -50,6 +50,70 @@
       "minor_policy": "strict"
     },
     {
+      "sfid": "TFM_CRYPTO_KEY_POLICY_INIT_SFID",
+      "signal": "TFM_CRYPTO_KEY_POLICY_INIT",
+      "tfm_symbol": "tfm_crypto_key_policy_init",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "strict"
+    },
+    {
+      "sfid": "TFM_CRYPTO_KEY_POLICY_SET_USAGE_SFID",
+      "signal": "TFM_CRYPTO_KEY_POLICY_SET_USAGE",
+      "tfm_symbol": "tfm_crypto_key_policy_set_usage",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "strict"
+    },
+    {
+      "sfid": "TFM_CRYPTO_KEY_POLICY_GET_USAGE_SFID",
+      "signal": "TFM_CRYPTO_KEY_POLICY_GET_USAGE",
+      "tfm_symbol": "tfm_crypto_key_policy_get_usage",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "strict"
+    },
+    {
+      "sfid": "TFM_CRYPTO_KEY_POLICY_GET_ALGORITHM_SFID",
+      "signal": "TFM_CRYPTO_KEY_POLICY_GET_ALGORITHM",
+      "tfm_symbol": "tfm_crypto_key_policy_get_algorithm",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "strict"
+    },
+    {
+      "sfid": "TFM_CRYPTO_SET_KEY_POLICY_SFID",
+      "signal": "TFM_CRYPTO_SET_KEY_POLICY",
+      "tfm_symbol": "tfm_crypto_set_key_policy",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "strict"
+    },
+    {
+      "sfid": "TFM_CRYPTO_GET_KEY_POLICY_SFID",
+      "signal": "TFM_CRYPTO_GET_KEY_POLICY",
+      "tfm_symbol": "tfm_crypto_get_key_policy",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "strict"
+    },
+    {
+      "sfid": "TFM_CRYPTO_GET_KEY_LIFETIME_SFID",
+      "signal": "TFM_CRYPTO_GET_KEY_LIFETIME",
+      "tfm_symbol": "tfm_crypto_get_key_lifetime",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "strict"
+    },
+    {
+      "sfid": "TFM_CRYPTO_SET_KEY_LIFETIME_SFID",
+      "signal": "TFM_CRYPTO_SET_KEY_LIFETIME",
+      "tfm_symbol": "tfm_crypto_set_key_lifetime",
+      "non_secure_clients": true,
+      "minor_version": 1,
+      "minor_policy": "strict"
+    },
+    {
       "sfid": "TFM_CRYPTO_CIPHER_SET_IV_SFID",
       "signal": "TFM_CRYPTO_CIPHER_SET_IV",
       "tfm_symbol": "tfm_crypto_cipher_set_iv",
diff --git a/secure_fw/services/crypto/tfm_crypto_api.h b/secure_fw/services/crypto/tfm_crypto_api.h
index af8f7fb..8f51b66 100644
--- a/secure_fw/services/crypto/tfm_crypto_api.h
+++ b/secure_fw/services/crypto/tfm_crypto_api.h
@@ -27,7 +27,6 @@
     TFM_CRYPTO_CIPHER_OPERATION = 1,
     TFM_CRYPTO_MAC_OPERATION = 2,
     TFM_CRYPTO_HASH_OPERATION = 3,
-    TFM_CRYPTO_KEY_POLICY = 4,
 
     /* Used to force the enum size */
     TFM_CRYPTO_OPERATION_TYPE_MAX = INT_MAX
@@ -89,6 +88,26 @@
                                         uint32_t handle,
                                         void **oper);
 /**
+ * \brief Retrieve a key from the provided key slot according to the key
+ *        policy and algorithm provided. This function is expected to be
+ *        called intra-service
+ *
+ * \param[in]  key         Key slot
+ * \param[in]  usage       Usage policy to be used on the retrieved key
+ * \param[in]  alg         Algorithm to be used for the retrieved key
+ * \param[out] data        Buffer to hold the exported key
+ * \param[in]  data_size   Length of the buffer pointed to by data
+ * \param[out] data_length Length of the exported key
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_get_key(psa_key_slot_t key,
+                                         psa_key_usage_t usage,
+                                         psa_algorithm_t alg,
+                                         uint8_t *data,
+                                         size_t data_size,
+                                         size_t *data_length);
+/**
  * \brief Import the key data in the provided key slot
  *
  * \param[in] key         Key slot
@@ -137,6 +156,98 @@
                                             uint8_t *data,
                                             size_t data_size,
                                             size_t *data_length);
+
+/**
+ * \brief Initialise the key policy to a default that forbids any use of the
+ *        key
+ *
+ * \param[out] policy  Key policy to initialise
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_key_policy_init(psa_key_policy_t *policy);
+
+/**
+ * \brief Set the permitted usage and algorithm for the provided key policy
+ *
+ * \param[out] policy  Key policy to modify
+ * \param[in]  usage   Permitted usage
+ * \param[in]  alg     Permitted algorithm
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_key_policy_set_usage(psa_key_policy_t *policy,
+                                                      psa_key_usage_t usage,
+                                                      psa_algorithm_t alg);
+
+/**
+ * \brief Get the permitted usage for the provided key policy
+ *
+ * \param[in]  policy  Key policy
+ * \param[out] usage   Permitted usage for this key policy
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_key_policy_get_usage(
+                                                 const psa_key_policy_t *policy,
+                                                 psa_key_usage_t *usage);
+
+/**
+ * \brief Get the permitted algorithm for the provided key policy
+ *
+ * \param[in]  policy  Key policy
+ * \param[out] alg     Permitted algorithm for this key policy
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_key_policy_get_algorithm(
+                                                 const psa_key_policy_t *policy,
+                                                 psa_algorithm_t *alg);
+
+/**
+ * \brief Set the key policy for the provided key slot
+ *
+ * \param[in] key     Key slot
+ * \param[in] policy  Key policy
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_set_key_policy(psa_key_slot_t key,
+                                                const psa_key_policy_t *policy);
+
+/**
+ * \brief Get the key policy for the provided key slot
+ *
+ * \param[in]  key     Key slot
+ * \param[out] policy  Key policy
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_get_key_policy(psa_key_slot_t key,
+                                                psa_key_policy_t *policy);
+
+/**
+ * \brief Set the lifetime for the provided key slot
+ *
+ * \param[in] key       Key slot
+ * \param[in] lifetime  Lifetime value
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_set_key_lifetime(psa_key_slot_t key,
+                                                  psa_key_lifetime_t lifetime);
+
+/**
+ * \brief Get the lifetime for the provided key slot
+ *
+ * \param[in]  key       Key slot
+ * \param[out] lifetime  Lifetime value
+ *
+ * \return Return values as described in \ref tfm_crypto_err_t
+ */
+enum tfm_crypto_err_t tfm_crypto_get_key_lifetime(psa_key_slot_t key,
+                                                  psa_key_lifetime_t *lifetime);
+
 /**
  * \brief Export the public key contained in the provided key slot
  *        for an asymmetric key pair
diff --git a/secure_fw/services/tfm_sfid_list.inc b/secure_fw/services/tfm_sfid_list.inc
index f9d0708..4e56af4 100644
--- a/secure_fw/services/tfm_sfid_list.inc
+++ b/secure_fw/services/tfm_sfid_list.inc
@@ -31,6 +31,14 @@
     {tfm_crypto_destroy_key, TFM_CRYPTO_DESTROY_KEY_SFID},
     {tfm_crypto_get_key_information, TFM_CRYPTO_GET_KEY_INFORMATION_SFID},
     {tfm_crypto_export_key, TFM_CRYPTO_EXPORT_KEY_SFID},
+    {tfm_crypto_key_policy_init, TFM_CRYPTO_KEY_POLICY_INIT_SFID},
+    {tfm_crypto_key_policy_set_usage, TFM_CRYPTO_KEY_POLICY_SET_USAGE_SFID},
+    {tfm_crypto_key_policy_get_usage, TFM_CRYPTO_KEY_POLICY_GET_USAGE_SFID},
+    {tfm_crypto_key_policy_get_algorithm, TFM_CRYPTO_KEY_POLICY_GET_ALGORITHM_SFID},
+    {tfm_crypto_set_key_policy, TFM_CRYPTO_SET_KEY_POLICY_SFID},
+    {tfm_crypto_get_key_policy, TFM_CRYPTO_GET_KEY_POLICY_SFID},
+    {tfm_crypto_get_key_lifetime, TFM_CRYPTO_GET_KEY_LIFETIME_SFID},
+    {tfm_crypto_set_key_lifetime, TFM_CRYPTO_SET_KEY_LIFETIME_SFID},
     {tfm_crypto_cipher_set_iv, TFM_CRYPTO_CIPHER_SET_IV_SFID},
     {tfm_crypto_cipher_encrypt_setup, TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SFID},
     {tfm_crypto_cipher_decrypt_setup, TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SFID},
diff --git a/test/suites/crypto/non_secure/crypto_ns_interface_testsuite.c b/test/suites/crypto/non_secure/crypto_ns_interface_testsuite.c
index ea9316b..12c7d57 100644
--- a/test/suites/crypto/non_secure/crypto_ns_interface_testsuite.c
+++ b/test/suites/crypto/non_secure/crypto_ns_interface_testsuite.c
@@ -44,7 +44,8 @@
 static void tfm_crypto_test_6022(struct test_result_t *ret);
 static void tfm_crypto_test_6028(struct test_result_t *ret);
 static void tfm_crypto_test_6029(struct test_result_t *ret);
-
+static void tfm_crypto_test_6030(struct test_result_t *ret);
+static void tfm_crypto_test_6031(struct test_result_t *ret);
 
 static struct test_t crypto_veneers_tests[] = {
     {&tfm_crypto_test_6001, "TFM_CRYPTO_TEST_6001",
@@ -95,6 +96,10 @@
      "Non Secure AEAD (AES-128-CCM) interface", {0} },
     {&tfm_crypto_test_6029, "TFM_CRYPTO_TEST_6029",
      "Non Secure AEAD (AES-128-GCM) interface", {0} },
+    {&tfm_crypto_test_6030, "TFM_CRYPTO_TEST_6030",
+     "Non Secure key policy interface", {0} },
+    {&tfm_crypto_test_6031, "TFM_CRYPTO_TEST_6031",
+     "Non Secure key policy check permissions", {0} },
 };
 
 void register_testsuite_ns_crypto_interface(struct test_suite_t *p_test_suite)
@@ -125,6 +130,16 @@
     size_t bits = 0;
     uint8_t exported_data[sizeof(data)] = {0};
     size_t exported_data_size = 0;
+    psa_key_policy_t policy;
+
+    /* Setup the key policy */
+    psa_key_policy_init(&policy);
+    psa_key_policy_set_usage(&policy, PSA_KEY_USAGE_EXPORT, 0);
+    status = psa_set_key_policy(slot, &policy);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to set key policy");
+        return;
+    }
 
     status = psa_import_key(slot, PSA_KEY_TYPE_AES, data, sizeof(data));
     if (status != PSA_SUCCESS) {
@@ -219,6 +234,17 @@
     size_t output_length = 0, total_output_length = 0;
     uint8_t encrypted_data[ENC_DEC_BUFFER_SIZE] = {0};
     uint32_t comp_result;
+    psa_key_policy_t policy;
+    psa_key_usage_t usage = (PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
+
+    /* Setup the key policy */
+    psa_key_policy_init(&policy);
+    psa_key_policy_set_usage(&policy, usage, alg);
+    status = psa_set_key_policy(slot, &policy);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to set key policy");
+        return;
+    }
 
     ret->val = TEST_PASSED;
 
@@ -411,6 +437,17 @@
     psa_cipher_operation_t handle;
     const psa_key_slot_t slot = 0;
     uint8_t data[TFM_CRYPTO_MAX_KEY_LENGTH];
+    psa_key_policy_t policy;
+    psa_key_usage_t usage = (PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
+
+    /* Setup the key policy */
+    psa_key_policy_init(&policy);
+    psa_key_policy_set_usage(&policy, usage, alg);
+    status = psa_set_key_policy(slot, &policy);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to set key policy");
+        return;
+    }
 
     /* Fill the key data */
     memset(data, 'A', key_size);
@@ -662,6 +699,17 @@
     size_t bit_size_test_key = 0;
     psa_status_t status;
     psa_mac_operation_t handle;
+    psa_key_policy_t policy;
+    psa_key_usage_t usage = PSA_KEY_USAGE_VERIFY;
+
+    /* Setup the key policy */
+    psa_key_policy_init(&policy);
+    psa_key_policy_set_usage(&policy, usage, alg);
+    status = psa_set_key_policy(slot, &policy);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to set key policy");
+        return;
+    }
 
     ret->val = TEST_PASSED;
 
@@ -794,6 +842,17 @@
     psa_key_type_t type = PSA_KEY_TYPE_NONE;
     size_t bits = 0;
     uint32_t comp_result;
+    psa_key_policy_t policy;
+    psa_key_usage_t usage = (PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
+
+    /* Setup the key policy */
+    psa_key_policy_init(&policy);
+    psa_key_policy_set_usage(&policy, usage, alg);
+    status = psa_set_key_policy(slot, &policy);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to set key policy");
+        return;
+    }
 
     ret->val = TEST_PASSED;
 
@@ -899,3 +958,169 @@
 {
     psa_aead_test(PSA_KEY_TYPE_AES, PSA_ALG_GCM, ret);
 }
+
+static void tfm_crypto_test_6030(struct test_result_t *ret)
+{
+    psa_status_t status;
+    psa_algorithm_t alg = PSA_ALG_CBC_BASE;
+    psa_algorithm_t alg_out;
+    psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_VOLATILE;
+    psa_key_lifetime_t lifetime_out;
+    psa_key_policy_t policy;
+    psa_key_policy_t policy_out;
+    psa_key_slot_t slot = 0;
+    psa_key_usage_t usage = PSA_KEY_USAGE_EXPORT;
+    psa_key_usage_t usage_out;
+
+    /* Initialise the key policy */
+    psa_key_policy_init(&policy);
+
+    /* Verify that initialised policy forbids all usage */
+    usage_out = psa_key_policy_get_usage(&policy);
+    if (usage_out != 0) {
+        TEST_FAIL("Unexpected usage value");
+        return;
+    }
+
+    alg_out = psa_key_policy_get_algorithm(&policy);
+    if (alg_out != 0) {
+        TEST_FAIL("Unexpected algorithm value");
+        return;
+    }
+
+    /* Set the key policy values */
+    psa_key_policy_set_usage(&policy, usage, alg);
+
+    /* Check that the key policy has the correct usage */
+    usage_out = psa_key_policy_get_usage(&policy);
+    if (usage_out != usage) {
+        TEST_FAIL("Unexpected usage value");
+        return;
+    }
+
+    /* Check that the key policy has the correct algorithm */
+    alg_out = psa_key_policy_get_algorithm(&policy);
+    if (alg_out != alg) {
+        TEST_FAIL("Unexpected algorithm value");
+        return;
+    }
+
+    /* Set the key policy for the key slot */
+    status = psa_set_key_policy(slot, &policy);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to set key policy");
+        return;
+    }
+
+    /* Check the key slot has the correct key policy */
+    status = psa_get_key_policy(slot, &policy_out);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to get key policy");
+        return;
+    }
+
+    usage_out = psa_key_policy_get_usage(&policy_out);
+    if (usage_out != usage) {
+        TEST_FAIL("Unexpected usage value");
+        return;
+    }
+
+    alg_out = psa_key_policy_get_algorithm(&policy_out);
+    if (alg_out != alg) {
+        TEST_FAIL("Unexpected algorithm value");
+        return;
+    }
+
+    /* Set the key lifetime for the key slot */
+    status = psa_set_key_lifetime(slot, lifetime);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to set key lifetime");
+        return;
+    }
+
+    /* Check the key slot has the correct key lifetime */
+    status = psa_get_key_lifetime(slot, &lifetime_out);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to get key lifetime");
+        return;
+    }
+
+    if (lifetime_out != lifetime) {
+        TEST_FAIL("Unexpected key lifetime value");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+static void tfm_crypto_test_6031(struct test_result_t *ret)
+{
+    psa_status_t status;
+    psa_algorithm_t alg = PSA_ALG_CBC_BASE;
+    psa_cipher_operation_t handle;
+    psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_VOLATILE;
+    psa_key_policy_t policy;
+    psa_key_slot_t slot = 0;
+    psa_key_usage_t usage = (PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
+    size_t data_len;
+    const uint8_t data[] = "THIS IS MY KEY1";
+    uint8_t data_out[sizeof(data)];
+
+    ret->val = TEST_PASSED;
+
+    /* Setup the key policy */
+    psa_key_policy_init(&policy);
+    psa_key_policy_set_usage(&policy, usage, alg);
+    status = psa_set_key_policy(slot, &policy);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to set key policy");
+        return;
+    }
+
+    /* Set the key lifetime for the key slot */
+    status = psa_set_key_lifetime(slot, lifetime);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to set key lifetime");
+        return;
+    }
+
+    /* Import a key to the slot for which policy has been set */
+    status = psa_import_key(slot, PSA_KEY_TYPE_AES, data, sizeof(data));
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to import a key");
+        return;
+    }
+
+    /* Setup a cipher permitted by the key policy */
+    status = psa_cipher_encrypt_setup(&handle, slot, alg);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to setup cipher operation");
+        goto destroy_key;
+    }
+
+    status = psa_cipher_abort(&handle);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to abort cipher operation");
+        goto destroy_key;
+    }
+
+    /* Attempt to setup a cipher with an alg not permitted by the policy */
+    status = psa_cipher_encrypt_setup(&handle, slot, PSA_ALG_CFB_BASE);
+    if (status != PSA_ERROR_NOT_PERMITTED) {
+        TEST_FAIL("Was able to setup cipher operation with wrong alg");
+        goto destroy_key;
+    }
+
+    /* Attempt to export the key, which is forbidden by the key policy */
+    status = psa_export_key(slot, data_out, sizeof(data_out), &data_len);
+    if (status != PSA_ERROR_NOT_PERMITTED) {
+        TEST_FAIL("Should not be able to export key without correct usage");
+        goto destroy_key;
+    }
+
+destroy_key:
+    status = psa_destroy_key(slot);
+    if (status != PSA_SUCCESS) {
+        TEST_FAIL("Failed to destroy key");
+    }
+}
diff --git a/test/suites/crypto/secure/crypto_sec_interface_testsuite.c b/test/suites/crypto/secure/crypto_sec_interface_testsuite.c
index c39d205..a0d28ed 100644
--- a/test/suites/crypto/secure/crypto_sec_interface_testsuite.c
+++ b/test/suites/crypto/secure/crypto_sec_interface_testsuite.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -40,11 +40,21 @@
     enum tfm_crypto_err_t err;
     uint32_t i = 0;
     const psa_key_slot_t slot = 0;
-    const uint8_t data[] = "THIS IS MY KEY1";
+    uint8_t data[] = "THIS IS MY KEY1";
     psa_key_type_t type = PSA_KEY_TYPE_NONE;
     size_t bits = 0;
     uint8_t exported_data[sizeof(data)] = {0};
     size_t exported_data_size = 0;
+    psa_key_policy_t policy;
+
+    /* Setup the key policy */
+    tfm_crypto_veneer_key_policy_init(&policy);
+    tfm_crypto_veneer_key_policy_set_usage(&policy, PSA_KEY_USAGE_EXPORT, 0);
+    err = tfm_crypto_veneer_set_key_policy(slot, &policy);
+    if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
+        TEST_FAIL("Failed to set key policy");
+        return;
+    }
 
     err = tfm_crypto_veneer_import_key(slot,
                                        PSA_KEY_TYPE_AES,